Compare commits

...
4 Commits
Author SHA1 Message Date
React Native Bot 3a625f72f0 Release 0.82.1
#publish-packages-to-npm&latest
2025-10-20 16:32:45 +00:00
Christian Falch 23182298b5 fixed cp command to work with gnu coreutils (#54063)
Summary:
When using gnu coreutils, installation of ReactNativeDependenices on iOS fails at compile time with errors like in the following issue (in the Expo repo):

https://github.com/expo/expo/issues/38992

This is caused by a missing `.` in the end of the path name that the built-in MacOS cp command handles well, but that will create an extra Headers folder when using cp from gnu coreutils.

This commit fixes this by adding the missing `.`

## Changelog:

[IOS] [FIXED] - Fixed issue when using gnu coreutils cp command when using precompiled binaries causing compilation error

Pull Request resolved: https://github.com/facebook/react-native/pull/54063

Test Plan:
- Verify that you're running gnu coreutils (`cp --version`)
- Create new expo app `npx create-expo-app`
- Build on iOS - should error without this fix, should work with the fix.

Reviewed By: christophpurrer

Differential Revision: D83964083

Pulled By: javache

fbshipit-source-id: 46dc074ca9b7fc97fa5a37ef48d68a895e3310ff
2025-10-20 15:07:16 +01:00
Pieter De Baets bdc2c198e0 Fix useNativeTransformHelper behaviour when frame size is 0 (#53978)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53978

Inconsistency between the previous and old version of `processTransform` - if frameSize is 0, the transform was being ignored, which is not correct when considering a fixed transform origin and a rotation animation for example. Instead, always apply the transform origin if it's set.

Changelog: [Android][Fixed] Fixed representation of transforms when view is originally zero-sized

Reviewed By: mdvacca

Differential Revision: D83469083

fbshipit-source-id: e9ae1500f64c700708edb00b2d5871e3f224fb07
2025-10-20 15:06:57 +01:00
React Native Bot b93e75dca7 [LOCAL] Bump Podfile.lock 2025-10-08 00:25:58 +00:00
39 changed files with 755 additions and 379 deletions
+2 -2
View File
@@ -58,8 +58,8 @@
"@jest/create-cache-key-function": "^29.7.0",
"@microsoft/api-extractor": "^7.52.2",
"@octokit/rest": "^22.0.0",
"@react-native/metro-babel-transformer": "0.82.0",
"@react-native/metro-config": "0.82.0",
"@react-native/metro-babel-transformer": "0.82.1",
"@react-native/metro-config": "0.82.1",
"@tsconfig/node22": "22.0.2",
"@types/react": "^19.1.0",
"@typescript-eslint/parser": "^8.36.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/assets-registry",
"version": "0.82.0",
"version": "0.82.1",
"description": "Asset support code for React Native.",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-plugin-codegen",
"version": "0.82.0",
"version": "0.82.1",
"description": "Babel plugin to generate native module and view manager code for React Native.",
"license": "MIT",
"repository": {
@@ -26,7 +26,7 @@
],
"dependencies": {
"@babel/traverse": "^7.25.3",
"@react-native/codegen": "0.82.0"
"@react-native/codegen": "0.82.1"
},
"devDependencies": {
"@babel/core": "^7.25.2"
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/community-cli-plugin",
"version": "0.82.0",
"version": "0.82.1",
"description": "Core CLI commands for React Native",
"keywords": [
"react-native",
@@ -22,7 +22,7 @@
"dist"
],
"dependencies": {
"@react-native/dev-middleware": "0.82.0",
"@react-native/dev-middleware": "0.82.1",
"debug": "^4.4.0",
"invariant": "^2.2.4",
"metro": "^0.83.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/core-cli-utils",
"version": "0.82.0",
"version": "0.82.1",
"description": "React Native CLI library for Frameworks to build on",
"license": "MIT",
"main": "./src/index.flow.js",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/debugger-frontend",
"version": "0.82.0",
"version": "0.82.1",
"description": "Debugger frontend for React Native based on Chrome DevTools",
"keywords": [
"react-native",
@@ -1,6 +1,6 @@
#!/usr/bin/env dotslash
// @generated SignedSource<<02ab38b39784853e42c1e8cab3894f5b>>
// @generated SignedSource<<ea146009f0eb66caf2e1e8c6ad9a664b>>
{
@@ -12,7 +12,7 @@
"digest": "4352f1c9848ca919101ec628bd08b87a72a828d1ab55fa43a02098329fa452fa",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0/React.Native.DevTools-linux-aarch64.tar.gz"
"url": "https://github.com/facebook/react-native/releases/download/v0.82.1/React.Native.DevTools-linux-aarch64.tar.gz"
},
{
"type": "http",
@@ -28,7 +28,7 @@
"digest": "11c7b07942928a6301b07fbf2bc77ce1229b2a52891f23541cdd9858b5250e64",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0/React.Native.DevTools-linux-x86_64.tar.gz"
"url": "https://github.com/facebook/react-native/releases/download/v0.82.1/React.Native.DevTools-linux-x86_64.tar.gz"
},
{
"type": "http",
@@ -44,7 +44,7 @@
"digest": "3cbe8b1b3d17e433347f1601435bb9a6cb758528a5c176a66fc52d9977223175",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0/React.Native.DevTools-macos-aarch64.tar.gz"
"url": "https://github.com/facebook/react-native/releases/download/v0.82.1/React.Native.DevTools-macos-aarch64.tar.gz"
},
{
"type": "http",
@@ -60,7 +60,7 @@
"digest": "6fb79bc2ba3008401b4c9c128248657b95b98581ccde60f8fadb622163779775",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0/React.Native.DevTools-macos-x86_64.tar.gz"
"url": "https://github.com/facebook/react-native/releases/download/v0.82.1/React.Native.DevTools-macos-x86_64.tar.gz"
},
{
"type": "http",
@@ -76,7 +76,7 @@
"digest": "579a5b0944c51c3b1b541ad5af66c1ffedf93cae2a891ecdf88cb7219fd9b096",
"providers": [
{
"url": "https://github.com/facebook/react-native/releases/download/v0.82.0/React.Native.DevTools-windows-x86_64.tar.gz"
"url": "https://github.com/facebook/react-native/releases/download/v0.82.1/React.Native.DevTools-windows-x86_64.tar.gz"
},
{
"type": "http",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/debugger-shell",
"version": "0.82.0",
"version": "0.82.1",
"description": "Experimental debugger shell for React Native for use with @react-native/debugger-frontend",
"keywords": [
"react-native",
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/dev-middleware",
"version": "0.82.0",
"version": "0.82.1",
"description": "Dev server middleware for React Native",
"keywords": [
"react-native",
@@ -23,8 +23,8 @@
],
"dependencies": {
"@isaacs/ttlcache": "^1.4.1",
"@react-native/debugger-frontend": "0.82.0",
"@react-native/debugger-shell": "0.82.0",
"@react-native/debugger-frontend": "0.82.1",
"@react-native/debugger-shell": "0.82.1",
"chrome-launcher": "^0.15.2",
"chromium-edge-launcher": "^0.2.0",
"connect": "^3.6.5",
@@ -39,7 +39,7 @@
"node": ">= 20.19.4"
},
"devDependencies": {
"@react-native/debugger-shell": "0.82.0",
"@react-native/debugger-shell": "0.82.1",
"selfsigned": "^2.4.1",
"undici": "^5.29.0",
"wait-for-expect": "^3.0.2"
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-config",
"version": "0.82.0",
"version": "0.82.1",
"description": "ESLint config for React Native",
"license": "MIT",
"repository": {
@@ -22,7 +22,7 @@
"dependencies": {
"@babel/core": "^7.25.2",
"@babel/eslint-parser": "^7.25.1",
"@react-native/eslint-plugin": "0.82.0",
"@react-native/eslint-plugin": "0.82.1",
"@typescript-eslint/eslint-plugin": "^8.36.0",
"@typescript-eslint/parser": "^8.36.0",
"eslint-config-prettier": "^8.5.0",
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin",
"version": "0.82.0",
"version": "0.82.1",
"description": "ESLint rules for @react-native/eslint-config",
"license": "MIT",
"repository": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/eslint-plugin-specs",
"version": "0.82.0",
"version": "0.82.1",
"description": "ESLint rules to validate NativeModule and Component Specs",
"license": "MIT",
"repository": {
@@ -26,7 +26,7 @@
"dependencies": {
"@babel/core": "^7.25.2",
"@babel/plugin-transform-flow-strip-types": "^7.25.2",
"@react-native/codegen": "0.82.0",
"@react-native/codegen": "0.82.1",
"make-dir": "^2.1.0",
"pirates": "^4.0.1",
"source-map-support": "0.5.0"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/gradle-plugin",
"version": "0.82.0",
"version": "0.82.1",
"description": "Gradle Plugin for React Native",
"license": "MIT",
"repository": {
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-config",
"version": "0.82.0",
"version": "0.82.1",
"description": "Metro configuration for React Native.",
"license": "MIT",
"repository": {
@@ -26,8 +26,8 @@
"dist"
],
"dependencies": {
"@react-native/js-polyfills": "0.82.0",
"@react-native/metro-babel-transformer": "0.82.0",
"@react-native/js-polyfills": "0.82.1",
"@react-native/metro-babel-transformer": "0.82.1",
"metro-config": "^0.83.1",
"metro-runtime": "^0.83.1"
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/new-app-screen",
"version": "0.82.0",
"version": "0.82.1",
"description": "NewAppScreen component for React Native",
"keywords": [
"react-native"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/normalize-colors",
"version": "0.82.0",
"version": "0.82.1",
"description": "Color normalization for React Native.",
"license": "MIT",
"repository": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/js-polyfills",
"version": "0.82.0",
"version": "0.82.1",
"description": "Polyfills for React Native.",
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/babel-preset",
"version": "0.82.0",
"version": "0.82.1",
"description": "Babel preset for React Native applications",
"repository": {
"type": "git",
@@ -66,7 +66,7 @@
"@babel/plugin-transform-typescript": "^7.25.2",
"@babel/plugin-transform-unicode-regex": "^7.24.7",
"@babel/template": "^7.25.0",
"@react-native/babel-plugin-codegen": "0.82.0",
"@react-native/babel-plugin-codegen": "0.82.1",
"babel-plugin-syntax-hermes-parser": "0.32.0",
"babel-plugin-transform-flow-enums": "^0.0.2",
"react-refresh": "^0.14.0"
@@ -1,6 +1,6 @@
{
"name": "@react-native/metro-babel-transformer",
"version": "0.82.0",
"version": "0.82.1",
"description": "Babel transformer for React Native applications.",
"repository": {
"type": "git",
@@ -27,7 +27,7 @@
],
"dependencies": {
"@babel/core": "^7.25.2",
"@react-native/babel-preset": "0.82.0",
"@react-native/babel-preset": "0.82.1",
"hermes-parser": "0.32.0",
"nullthrows": "^1.1.1"
},
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/codegen",
"version": "0.82.0",
"version": "0.82.1",
"description": "Code generation tools for React Native",
"license": "MIT",
"repository": {
@@ -1,6 +1,6 @@
{
"name": "@react-native/compatibility-check",
"version": "0.82.0",
"version": "0.82.1",
"description": "Check a React Native app's boundary between JS and Native for incompatibilities",
"license": "MIT",
"repository": {
@@ -29,7 +29,7 @@
"dist"
],
"dependencies": {
"@react-native/codegen": "0.82.0"
"@react-native/codegen": "0.82.1"
},
"devDependencies": {
"flow-remove-types": "^2.237.2",
@@ -1,6 +1,6 @@
{
"name": "@react-native/popup-menu-android",
"version": "0.82.0",
"version": "0.82.1",
"description": "PopupMenu for the Android platform",
"main": "index.js",
"files": [
@@ -21,7 +21,7 @@
},
"license": "MIT",
"devDependencies": {
"@react-native/codegen": "0.82.0"
"@react-native/codegen": "0.82.1"
},
"peerDependencies": {
"@types/react": "^19.1.0",
+1 -1
View File
@@ -28,7 +28,7 @@
export default class ReactNativeVersion {
static major: number = 0;
static minor: number = 82;
static patch: number = 0;
static patch: number = 1;
static prerelease: string | null = null;
static getVersionString(): string {
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
__rnVersion = @{
RCTVersionMajor: @(0),
RCTVersionMinor: @(82),
RCTVersionPatch: @(0),
RCTVersionPatch: @(1),
RCTVersionPrerelease: [NSNull null],
};
});
@@ -1,4 +1,4 @@
VERSION_NAME=0.82.0
VERSION_NAME=0.82.1
react.internal.publishingGroup=com.facebook.react
react.internal.hermesPublishingGroup=com.facebook.hermes
@@ -14,7 +14,7 @@ public object ReactNativeVersion {
public val VERSION: Map<String, Any?> = mapOf(
"major" to 0,
"minor" to 82,
"patch" to 0,
"patch" to 1,
"prerelease" to null
)
}
@@ -39,7 +39,9 @@ void processTransform(
}
auto result = BaseViewProps::resolveTransform(
Size(viewWidth, viewHeight), transform, transformOrigin);
Size{.width = viewWidth, .height = viewHeight},
transform,
transformOrigin);
// Convert from matrix of floats to double matrix
constexpr size_t MatrixSize = std::tuple_size_v<decltype(result.matrix)>;
@@ -14,14 +14,14 @@
#define REACT_NATIVE_VERSION_MAJOR 0
#define REACT_NATIVE_VERSION_MINOR 82
#define REACT_NATIVE_VERSION_PATCH 0
#define REACT_NATIVE_VERSION_PATCH 1
namespace facebook::react {
constexpr struct {
int32_t Major = 0;
int32_t Minor = 82;
int32_t Patch = 0;
int32_t Patch = 1;
std::string_view Prerelease = "";
} ReactNativeVersion;
@@ -558,9 +558,6 @@ Transform BaseViewProps::resolveTransform(
const Transform& transform,
const TransformOrigin& transformOrigin) {
auto transformMatrix = Transform{};
if (frameSize.width == 0 && frameSize.height == 0) {
return transformMatrix;
}
// transform is matrix
if (transform.operations.size() == 1 &&
@@ -0,0 +1,377 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <gtest/gtest.h>
#include <react/renderer/components/view/BaseViewProps.h>
namespace facebook::react {
namespace {
// For transforms involving rotations, use this helper to fix floating point
// accuracies
void expectTransformsEqual(const Transform& t1, const Transform& t2) {
for (int i = 0; i < 16; i++) {
EXPECT_NEAR(t1.matrix[i], t2.matrix[i], 0.0001);
}
}
} // namespace
class ResolveTransformTest : public ::testing::Test {
protected:
TransformOrigin createTransformOriginPoints(float x, float y, float z = 0) {
TransformOrigin origin;
origin.xy[0] = ValueUnit(x, UnitType::Point);
origin.xy[1] = ValueUnit(y, UnitType::Point);
origin.z = z;
return origin;
}
TransformOrigin createTransformOriginPercent(float x, float y, float z = 0) {
TransformOrigin origin;
origin.xy[0] = ValueUnit(x, UnitType::Percent);
origin.xy[1] = ValueUnit(y, UnitType::Percent);
origin.z = z;
return origin;
}
};
TEST_F(ResolveTransformTest, EmptyFrameNoTransformOrigin) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
TransformOrigin transformOrigin; // Default (not set)
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// With empty frame size and no transform origin, should just apply the
// transform directly
EXPECT_EQ(result.matrix, transform.matrix);
}
TEST_F(ResolveTransformTest, EmptyFrameTransformOriginPoints) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
TransformOrigin transformOrigin = createTransformOriginPoints(5, 8);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Should handle transform origin even with empty frame size
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
}
TEST_F(ResolveTransformTest, EmptyFrameTransformOriginPercent) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Transform origin does not affect translate transform
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
}
TEST_F(ResolveTransformTest, NonEmptyFrameNoTransformOrigin) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
TransformOrigin transformOrigin; // Default (not set)
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Transform origin does not affect translate transform
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
}
TEST_F(ResolveTransformTest, NonEmptyFrameTransformOriginPoints) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Scale(2.0, 1.5, 0.);
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
auto expected = Transform::Translate(25.0, 25.0, 0.0) * transform;
EXPECT_EQ(result.matrix, expected.matrix);
}
TEST_F(ResolveTransformTest, NonEmptyFrameTransformOriginPercent) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Scale(2.0, 1.5, 0.);
TransformOrigin transformOrigin =
createTransformOriginPercent(25, 75); // 25% width, 75% height
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Should resolve percentages: 25% of 100 = 25, 75% of 200 = 150
auto expected = Transform::Translate(25.0, -25.0, 0.0) * transform;
EXPECT_EQ(result.matrix, expected.matrix);
}
TEST_F(ResolveTransformTest, IdentityTransformWithOrigin) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Identity();
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Even with identity transform, transform origin should still apply
// translations but they should cancel out, resulting in identity
EXPECT_EQ(result.matrix, transform.matrix);
}
TEST_F(ResolveTransformTest, MultipleTransformOperations) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Identity();
transform = transform * Transform::Translate(10.0, 20.0, 0.0);
transform = transform * Transform::Scale(2.0, 1.5, 0.0);
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
EXPECT_EQ(result.matrix, transform.matrix);
}
TEST_F(ResolveTransformTest, VariousTransformOriginPositions) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Scale(2.0, 2.0, 0.);
// Test origin at top-left (0, 0)
TransformOrigin topLeft = createTransformOriginPoints(0, 0);
auto resultTopLeft =
BaseViewProps::resolveTransform(frameSize, transform, topLeft);
auto expected = Transform::Translate(50.0, 100.0, 0.0) * transform;
EXPECT_EQ(resultTopLeft.matrix, expected.matrix);
// Test origin at center (50%, 50%)
TransformOrigin center = createTransformOriginPercent(50, 50);
auto resultCenter =
BaseViewProps::resolveTransform(frameSize, transform, center);
EXPECT_EQ(resultCenter.matrix, transform.matrix);
// Test origin at bottom-right (100%, 100%)
TransformOrigin bottomRight = createTransformOriginPercent(100, 100);
auto resultBottomRight =
BaseViewProps::resolveTransform(frameSize, transform, bottomRight);
expected = Transform::Translate(-50.0, -100.0, 0.0) * transform;
EXPECT_EQ(resultBottomRight.matrix, expected.matrix);
}
// Test with z-component in transform origin
TEST_F(ResolveTransformTest, TransformOriginWithZComponent) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::Scale(1.5, 1.5, 0.);
TransformOrigin transformOrigin;
transformOrigin.xy[0] = ValueUnit(50, UnitType::Point);
transformOrigin.xy[1] = ValueUnit(100, UnitType::Point);
transformOrigin.z = 10.0f;
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
auto expected = Transform::Translate(0.0, 0.0, 10.0) * transform;
EXPECT_EQ(result.matrix, expected.matrix);
}
TEST_F(ResolveTransformTest, ArbitraryTransformMatrix) {
Size frameSize{.width = 100, .height = 200};
Transform transform;
transform.operations.push_back({
.type = TransformOperationType::Arbitrary,
.x = ValueUnit(0, UnitType::Point),
.y = ValueUnit(0, UnitType::Point),
.z = ValueUnit(0, UnitType::Point),
});
// Set custom matrix
transform.matrix = {{2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 10, 20, 0, 1}};
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
auto expected = Transform::Translate(25.0, 50.0, 0.0) * transform;
EXPECT_EQ(result.matrix, expected.matrix);
}
// Test rotation with empty frame size and no transform origin
TEST_F(ResolveTransformTest, RotationEmptyFrameNoTransformOrigin) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
TransformOrigin transformOrigin; // Default (not set)
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// With empty frame size and no transform origin, should just apply the
// rotation directly
expectTransformsEqual(result, transform);
}
// Test rotation with empty frame size and transform origin in points
TEST_F(ResolveTransformTest, RotationEmptyFrameTransformOriginPoints) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
TransformOrigin transformOrigin = createTransformOriginPoints(10, 20);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// With empty frame size, center is (0, 0), so origin offset is (10, 20)
auto expected = Transform::Translate(10.0, 20.0, 0.0) * transform *
Transform::Translate(-10.0, -20.0, 0.0);
expectTransformsEqual(result, expected);
}
// Test rotation with empty frame size and transform origin in percentages
TEST_F(ResolveTransformTest, RotationEmptyFrameTransformOriginPercent) {
Size frameSize{.width = 0, .height = 0};
Transform transform = Transform::RotateZ(M_PI / 6.0); // 30 degrees
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// With 0 frame size, percentages resolve to 0, so no origin offset
expectTransformsEqual(result, transform);
}
// Test rotation with non-empty frame size and no transform origin
TEST_F(ResolveTransformTest, RotationNonEmptyFrameNoTransformOrigin) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::RotateZ(M_PI / 3.0); // 60 degrees
TransformOrigin transformOrigin; // Default (not set)
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Without transform origin, rotation should happen around default center
expectTransformsEqual(result, transform);
}
// Test rotation with non-empty frame size and transform origin in points
TEST_F(ResolveTransformTest, RotationNonEmptyFrameTransformOriginPoints) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Center of 100x200 frame is (50, 100), origin at (25, 50) means offset of
// (-25, -50)
auto expected = Transform::Translate(-25.0, -50.0, 0.0) * transform *
Transform::Translate(25.0, 50.0, 0.0);
expectTransformsEqual(result, expected);
}
// Test rotation with non-empty frame size and transform origin in percentages
TEST_F(ResolveTransformTest, RotationNonEmptyFrameTransformOriginPercent) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::RotateZ(M_PI / 2.0); // 90 degrees
TransformOrigin transformOrigin =
createTransformOriginPercent(25, 75); // 25% width, 75% height
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Should resolve percentages: 25% of 100 = 25, 75% of 200 = 150
// Center is (50, 100), so origin offset is (25-50, 150-100) = (-25, 50)
auto expected = Transform::Translate(-25.0, 50.0, 0.0) * transform *
Transform::Translate(25.0, -50.0, 0.0);
expectTransformsEqual(result, expected);
}
// Test rotation with mixed transform origin units
TEST_F(ResolveTransformTest, RotationMixedTransformOriginUnits) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::RotateZ(M_PI); // 180 degrees
TransformOrigin transformOrigin;
transformOrigin.xy[0] = ValueUnit(30, UnitType::Point); // 30 points
transformOrigin.xy[1] = ValueUnit(25, UnitType::Percent); // 25% of 200 = 50
transformOrigin.z = 0;
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Center is (50, 100), origin is (30, 50), so offset is (-20, -50)
auto expected = Transform::Translate(-20.0, -50.0, 0.0) * transform *
Transform::Translate(20.0, 50.0, 0.0);
expectTransformsEqual(result, expected);
}
// Test multiple rotations (RotateX, RotateY, RotateZ)
TEST_F(ResolveTransformTest, MultipleRotationsWithTransformOrigin) {
Size frameSize{.width = 100, .height = 100};
Transform transform = Transform::Rotate(M_PI / 6.0, M_PI / 4.0, M_PI / 3.0);
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
expectTransformsEqual(result, transform);
}
// Test rotation with z-component in transform origin
TEST_F(ResolveTransformTest, RotationWithZTransformOrigin) {
Size frameSize{.width = 100, .height = 200};
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
TransformOrigin transformOrigin;
transformOrigin.xy[0] = ValueUnit(50, UnitType::Point);
transformOrigin.xy[1] = ValueUnit(100, UnitType::Point);
transformOrigin.z = 15.0f;
auto result =
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
// Center is (50, 100), origin is (50, 100, 15), so offset is (0, 0, 15)
auto expected = Transform::Translate(0.0, 0.0, 15.0) * transform *
Transform::Translate(0.0, 0.0, -15.0);
expectTransformsEqual(result, expected);
}
// Test rotation at different origin positions (corners vs center)
TEST_F(ResolveTransformTest, RotationDifferentOriginPositions) {
Size frameSize{.width = 100, .height = 100};
Transform transform = Transform::RotateZ(M_PI / 2.0); // 90 degrees
// Test rotation around top-left corner (0, 0)
TransformOrigin topLeft = createTransformOriginPoints(0, 0);
auto resultTopLeft =
BaseViewProps::resolveTransform(frameSize, transform, topLeft);
auto expectedTopLeft = Transform::Translate(-50.0, -50.0, 0.0) * transform *
Transform::Translate(50.0, 50.0, 0.0);
expectTransformsEqual(resultTopLeft, expectedTopLeft);
// Test rotation around center (50%, 50%)
TransformOrigin center = createTransformOriginPercent(50, 50);
auto resultCenter =
BaseViewProps::resolveTransform(frameSize, transform, center);
expectTransformsEqual(resultCenter, transform);
// Test rotation around bottom-right corner (100%, 100%)
TransformOrigin bottomRight = createTransformOriginPercent(100, 100);
auto resultBottomRight =
BaseViewProps::resolveTransform(frameSize, transform, bottomRight);
auto expectedBottomRight = Transform::Translate(50.0, 50.0, 0.0) * transform *
Transform::Translate(-50.0, -50.0, 0.0);
expectTransformsEqual(resultBottomRight, expectedBottomRight);
}
} // namespace facebook::react
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "react-native",
"version": "0.82.0",
"version": "0.82.1",
"description": "A framework for building native apps using React",
"license": "MIT",
"repository": {
@@ -162,13 +162,13 @@
},
"dependencies": {
"@jest/create-cache-key-function": "^29.7.0",
"@react-native/assets-registry": "0.82.0",
"@react-native/codegen": "0.82.0",
"@react-native/community-cli-plugin": "0.82.0",
"@react-native/gradle-plugin": "0.82.0",
"@react-native/js-polyfills": "0.82.0",
"@react-native/normalize-colors": "0.82.0",
"@react-native/virtualized-lists": "0.82.0",
"@react-native/assets-registry": "0.82.1",
"@react-native/codegen": "0.82.1",
"@react-native/community-cli-plugin": "0.82.1",
"@react-native/gradle-plugin": "0.82.1",
"@react-native/js-polyfills": "0.82.1",
"@react-native/normalize-colors": "0.82.1",
"@react-native/virtualized-lists": "0.82.1",
"abort-controller": "^3.0.0",
"anser": "^1.4.9",
"ansi-regex": "^5.0.0",
@@ -361,7 +361,7 @@ exports[`execute test-app "ReactAppDependencyProvider.podspec" should match snap
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
version = \\"0.82.0\\"
version = \\"0.82.1\\"
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
@@ -399,7 +399,7 @@ exports[`execute test-app "ReactCodegen.podspec" should match snapshot 1`] = `
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
version = \\"0.82.0\\"
version = \\"0.82.1\\"
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
@@ -840,7 +840,7 @@ exports[`execute test-app-legacy "ReactAppDependencyProvider.podspec" should mat
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
version = \\"0.82.0\\"
version = \\"0.82.1\\"
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
@@ -878,7 +878,7 @@ exports[`execute test-app-legacy "ReactCodegen.podspec" should match snapshot 1`
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
version = \\"0.82.0\\"
version = \\"0.82.1\\"
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
@@ -62,7 +62,7 @@ Pod::Spec.new do |spec|
exit 0
fi
cp -R "$HEADERS_PATH/" Headers
cp -R "$HEADERS_PATH/." Headers
mkdir -p framework/packages/react-native
cp -R "$XCFRAMEWORK_PATH/../." framework/packages/react-native/
find "$XCFRAMEWORK_PATH/.." -type f -exec rm {} +
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -26,8 +26,8 @@
"e2e-test-ios": "./scripts/maestro-test-ios.sh"
},
"dependencies": {
"@react-native/new-app-screen": "0.82.0",
"@react-native/popup-menu-android": "0.82.0",
"@react-native/new-app-screen": "0.82.1",
"@react-native/popup-menu-android": "0.82.1",
"flow-enums-runtime": "^0.0.6",
"invariant": "^2.2.4",
"nullthrows": "^1.1.1"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/typescript-config",
"version": "0.82.0",
"version": "0.82.1",
"description": "Default TypeScript configuration for React Native apps",
"license": "MIT",
"repository": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@react-native/virtualized-lists",
"version": "0.82.0",
"version": "0.82.1",
"description": "Virtualized lists for React Native.",
"license": "MIT",
"repository": {
+6 -6
View File
@@ -13,17 +13,17 @@
},
"dependencies": {
"react": "19.1.1",
"react-native": "0.82.0"
"react-native": "0.82.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"@babel/runtime": "^7.25.0",
"@react-native/babel-preset": "0.82.0",
"@react-native/core-cli-utils": "0.82.0",
"@react-native/eslint-config": "0.82.0",
"@react-native/metro-config": "0.82.0",
"@react-native/typescript-config": "0.82.0",
"@react-native/babel-preset": "0.82.1",
"@react-native/core-cli-utils": "0.82.1",
"@react-native/eslint-config": "0.82.1",
"@react-native/metro-config": "0.82.1",
"@react-native/typescript-config": "0.82.1",
"@types/jest": "^29.5.14",
"commander": "^12.0.0",
"eslint": "^8.19.0",
@@ -13,7 +13,7 @@
"prepare": "yarn run build"
},
"dependencies": {
"@react-native/codegen": "0.82.0"
"@react-native/codegen": "0.82.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",