mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
189
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aaff0d37e2 | ||
|
|
16a89816fc | ||
|
|
04858ecbab | ||
|
|
d8e00f0bb1 | ||
|
|
07f6f70aef | ||
|
|
ece8ca82cd | ||
|
|
08a59c59e0 | ||
|
|
fbd44ade3a | ||
|
|
4f94028ca6 | ||
|
|
0a567a63cd | ||
|
|
19ebd4c188 | ||
|
|
a2a72e239d | ||
|
|
fedceecc37 | ||
|
|
e3047db0dc | ||
|
|
1e212f91bc | ||
|
|
4f1f72ea34 | ||
|
|
fe1aacae6d | ||
|
|
a82b5acf3d | ||
|
|
8cc2874d3f | ||
|
|
d012b2c19b | ||
|
|
cfc6960bc4 | ||
|
|
ef742dbc68 | ||
|
|
11a1ad7a98 | ||
|
|
b01a5f91fe | ||
|
|
65ae3dafcd | ||
|
|
d3495fd162 | ||
|
|
252e1345bf | ||
|
|
dd1b795abe | ||
|
|
c125f306c2 | ||
|
|
03ab6a3098 | ||
|
|
46b562b9b3 | ||
|
|
c1bf39bfdf | ||
|
|
f238b74658 | ||
|
|
76e2ab4ac8 | ||
|
|
35dba09724 | ||
|
|
9e96acbd0f | ||
|
|
40b8f4ad22 | ||
|
|
3306691d64 | ||
|
|
f184b591cf | ||
|
|
62d8d30652 | ||
|
|
60967fdffb | ||
|
|
4b91b63094 | ||
|
|
7f7655d711 | ||
|
|
76e04fac82 | ||
|
|
18f4db44ef | ||
|
|
251eb3fd4c | ||
|
|
3782fe865d | ||
|
|
5742227dd8 | ||
|
|
90654e4ba2 | ||
|
|
60c01b4715 | ||
|
|
69e028da45 | ||
|
|
152cb538f6 | ||
|
|
2ec6e3d901 | ||
|
|
1a86ee17fb | ||
|
|
8888cf9a2d | ||
|
|
27c97ac942 | ||
|
|
e69f0726cd | ||
|
|
1ced97fbe6 | ||
|
|
ff7e24f19a | ||
|
|
d9ec57a3b9 | ||
|
|
33fed54a16 | ||
|
|
7b7b538d6b | ||
|
|
9612d2e225 | ||
|
|
ee8b66e278 | ||
|
|
f214a52a9a | ||
|
|
f338db9c17 | ||
|
|
fe4047fe3a | ||
|
|
9f479ff8d6 | ||
|
|
dda8ab69d4 | ||
|
|
f04d1f1ef7 | ||
|
|
54a1e41694 | ||
|
|
269cf58140 | ||
|
|
941853974b | ||
|
|
36c0826f56 | ||
|
|
7970f79078 | ||
|
|
37e863e866 | ||
|
|
5961edd825 | ||
|
|
71d6d86ed6 | ||
|
|
0a7e1342cd | ||
|
|
891656d055 | ||
|
|
abbef4a0b8 | ||
|
|
e888329e9a | ||
|
|
1f8374e1dd | ||
|
|
a10ee5808b | ||
|
|
ab2ce4f2d8 | ||
|
|
ee256d11ae | ||
|
|
1f53d51e64 | ||
|
|
4f71a9434d | ||
|
|
ed9969b3d0 | ||
|
|
04da4800da | ||
|
|
bc093b8fa9 | ||
|
|
fbbd20dd63 | ||
|
|
710e08cd54 | ||
|
|
cc442eb8c8 | ||
|
|
aaad7e083d | ||
|
|
999f437b02 | ||
|
|
ffb37373ba | ||
|
|
e297fe1582 | ||
|
|
386a930afb | ||
|
|
281f48daf4 | ||
|
|
a44098ea27 | ||
|
|
0f7bf66bba | ||
|
|
14a213229a | ||
|
|
4223285a23 | ||
|
|
55b87a5293 | ||
|
|
0cf2985d27 | ||
|
|
2f3b104224 | ||
|
|
6a3116a8a9 | ||
|
|
432ad09c41 | ||
|
|
b950fa2afb | ||
|
|
52df5dee91 | ||
|
|
50ea5b4380 | ||
|
|
184664d47b | ||
|
|
2b75479fa2 | ||
|
|
2a52ee8ddb | ||
|
|
1d945629bf | ||
|
|
7885508f9b | ||
|
|
5e331304cb | ||
|
|
f00b449498 | ||
|
|
94cbf206d6 | ||
|
|
6bfc1187a8 | ||
|
|
29704b1f02 | ||
|
|
ccc8ce0d01 | ||
|
|
1cc12ce7fd | ||
|
|
28986a7599 | ||
|
|
ce75271d47 | ||
|
|
99c60bfe0a | ||
|
|
a477ee6ced | ||
|
|
a17a7003b1 | ||
|
|
f70c01cc30 | ||
|
|
bc6b4f0525 | ||
|
|
73133a31d5 | ||
|
|
9258e90c92 | ||
|
|
f783d30beb | ||
|
|
2915902763 | ||
|
|
c31ff55b92 | ||
|
|
d405e306e3 | ||
|
|
ad88309843 | ||
|
|
fd29d68c16 | ||
|
|
5348f9ff1e | ||
|
|
e08e27a6fa | ||
|
|
ded4ae1f78 | ||
|
|
331fab0683 | ||
|
|
33aa7b9161 | ||
|
|
560ac23001 | ||
|
|
87cd1c0a0a | ||
|
|
3ea4f156c9 | ||
|
|
5e1768746a | ||
|
|
e259961e8b | ||
|
|
aeaae4294f | ||
|
|
74b6acb1f0 | ||
|
|
a91e598e6a | ||
|
|
10cabcc0a7 | ||
|
|
3bfbaa8455 | ||
|
|
742ffa39fb | ||
|
|
6b40f35032 | ||
|
|
4556bdf4fc | ||
|
|
98fdc965b9 | ||
|
|
e8cdb99baa | ||
|
|
a15fc102e6 | ||
|
|
6ddfa708b0 | ||
|
|
1456d06c86 | ||
|
|
7bfadb429c | ||
|
|
faaec467b9 | ||
|
|
64ce7695f5 | ||
|
|
3ae9328571 | ||
|
|
89401b78cd | ||
|
|
089fb10740 | ||
|
|
2528e48e93 | ||
|
|
cb24596c33 | ||
|
|
cfb6c968dd | ||
|
|
3c17e101ee | ||
|
|
8174d02811 | ||
|
|
7e2f17ffe2 | ||
|
|
e13ee7a3d0 | ||
|
|
9613d377de | ||
|
|
3a0a7b0701 | ||
|
|
c777ad0b84 | ||
|
|
3412215e3a | ||
|
|
19fd1536a4 | ||
|
|
f6b7bd93d8 | ||
|
|
2ade12d747 | ||
|
|
f53f6137e6 | ||
|
|
ffe928ce50 | ||
|
|
d20b9cfdf0 | ||
|
|
b6e1938959 | ||
|
|
ddafd94124 | ||
|
|
eecd07c58b | ||
|
|
0e42d33cbc |
+4
-1
@@ -47,7 +47,10 @@ packages/react-native/flow/
|
|||||||
|
|
||||||
[options]
|
[options]
|
||||||
enums=true
|
enums=true
|
||||||
|
experimental.pattern_matching=true
|
||||||
|
experimental.pattern_matching.includes=<PROJECT_ROOT>/packages/react-native/src/private/components/virtualview/
|
||||||
casting_syntax=both
|
casting_syntax=both
|
||||||
|
component_syntax=true
|
||||||
|
|
||||||
emoji=true
|
emoji=true
|
||||||
|
|
||||||
@@ -102,4 +105,4 @@ untyped-import
|
|||||||
untyped-type-import
|
untyped-type-import
|
||||||
|
|
||||||
[version]
|
[version]
|
||||||
^0.273.1
|
^0.274.0
|
||||||
|
|||||||
@@ -26,9 +26,6 @@ runs:
|
|||||||
- name: Lint code
|
- name: Lint code
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./.github/workflow-scripts/exec_swallow_error.sh yarn lint --format junit -o ./reports/junit/eslint/results.xml
|
run: ./.github/workflow-scripts/exec_swallow_error.sh yarn lint --format junit -o ./reports/junit/eslint/results.xml
|
||||||
- name: Lint java
|
|
||||||
shell: bash
|
|
||||||
run: ./.github/workflow-scripts/exec_swallow_error.sh yarn lint-java --check
|
|
||||||
- name: Lint file structure
|
- name: Lint file structure
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./.github/workflow-scripts/lint_files.sh
|
run: ./.github/workflow-scripts/lint_files.sh
|
||||||
|
|||||||
@@ -13,9 +13,6 @@ export GITHUB_REPO=-react-native
|
|||||||
|
|
||||||
echo flow
|
echo flow
|
||||||
npm run flow-check --silent --json
|
npm run flow-check --silent --json
|
||||||
|
|
||||||
echo google-java-format
|
|
||||||
node scripts/lint-java.js --diff
|
|
||||||
} | node private/react-native-bots/code-analysis-bot.js
|
} | node private/react-native-bots/code-analysis-bot.js
|
||||||
|
|
||||||
STATUS=$?
|
STATUS=$?
|
||||||
|
|||||||
@@ -140,27 +140,6 @@ jobs:
|
|||||||
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
|
hermes-version: ${{ needs.prepare_hermes_workspace.outputs.hermes-version }}
|
||||||
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
|
react-native-version: ${{ needs.prepare_hermes_workspace.outputs.react-native-version }}
|
||||||
|
|
||||||
build_android:
|
|
||||||
runs-on: 8-core-ubuntu
|
|
||||||
needs: [set_release_type]
|
|
||||||
container:
|
|
||||||
image: reactnativecommunity/react-native-android:latest
|
|
||||||
env:
|
|
||||||
TERM: "dumb"
|
|
||||||
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
|
|
||||||
ORG_GRADLE_PROJECT_SIGNING_PWD: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_PWD }}
|
|
||||||
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.ORG_GRADLE_PROJECT_SIGNING_KEY }}
|
|
||||||
ORG_GRADLE_PROJECT_SONATYPE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_USERNAME }}
|
|
||||||
ORG_GRADLE_PROJECT_SONATYPE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_PASSWORD }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Build Android
|
|
||||||
uses: ./.github/actions/build-android
|
|
||||||
with:
|
|
||||||
release-type: ${{ needs.set_release_type.outputs.RELEASE_TYPE }}
|
|
||||||
gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }}
|
|
||||||
|
|
||||||
build_npm_package:
|
build_npm_package:
|
||||||
runs-on: 8-core-ubuntu
|
runs-on: 8-core-ubuntu
|
||||||
needs:
|
needs:
|
||||||
@@ -170,7 +149,6 @@ jobs:
|
|||||||
build_hermes_macos,
|
build_hermes_macos,
|
||||||
build_hermesc_linux,
|
build_hermesc_linux,
|
||||||
build_hermesc_windows,
|
build_hermesc_windows,
|
||||||
build_android,
|
|
||||||
prebuild_apple_dependencies,
|
prebuild_apple_dependencies,
|
||||||
prebuild_react_native_core,
|
prebuild_react_native_core,
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
|
repo-token: ${{ secrets.REACT_NATIVE_BOT_GITHUB_TOKEN }}
|
||||||
days-before-stale: 180
|
days-before-stale: 180
|
||||||
stale-issue-message: 'This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
|
stale-issue-message: 'This issue is stale because it has been open for 180 days with no activity. It will be closed in 7 days unless you comment on it or remove the "Stale" label.'
|
||||||
stale-pr-message: 'This PR is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
|
stale-pr-message: 'This PR is stale because it has been open for 180 days with no activity. It will be closed in 7 days unless you comment on it or remove the "Stale" label.'
|
||||||
close-issue-message: 'This issue was closed because it has been stalled for 7 days with no activity.'
|
close-issue-message: 'This issue was closed because it has been stalled for 7 days with no activity.'
|
||||||
close-pr-message: 'This PR was closed because it has been stalled for 7 days with no activity.'
|
close-pr-message: 'This PR was closed because it has been stalled for 7 days with no activity.'
|
||||||
exempt-issue-labels: 'Help Wanted :octocat:, Good first issue, Never gets stale, Issue: Author Provided Repro'
|
exempt-issue-labels: 'Help Wanted :octocat:, Good first issue, Never gets stale, Issue: Author Provided Repro'
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ vendor/
|
|||||||
/packages/react-native/React/FBReactNativeSpec/
|
/packages/react-native/React/FBReactNativeSpec/
|
||||||
/packages/react-native-codegen/lib
|
/packages/react-native-codegen/lib
|
||||||
/packages/react-native-codegen/tmp/
|
/packages/react-native-codegen/tmp/
|
||||||
/packages/react-native/ReactCommon/react/renderer/components/rncore/
|
|
||||||
/packages/rn-tester/NativeModuleExample/ScreenshotManagerSpec*
|
/packages/rn-tester/NativeModuleExample/ScreenshotManagerSpec*
|
||||||
/**/RCTThirdPartyFabricComponentsProvider.*
|
/**/RCTThirdPartyFabricComponentsProvider.*
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+260
-5117
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -124,7 +124,7 @@ if (project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoole
|
|||||||
configurations.all {
|
configurations.all {
|
||||||
resolutionStrategy.dependencySubstitution {
|
resolutionStrategy.dependencySubstitution {
|
||||||
substitute(project(":packages:react-native:ReactAndroid:hermes-engine"))
|
substitute(project(":packages:react-native:ReactAndroid:hermes-engine"))
|
||||||
.using(module("com.facebook.react:hermes-android:0.0.0-+"))
|
.using(module("com.facebook.react:hermes-android:0.+"))
|
||||||
.because("Users opted to use hermes from nightly")
|
.because("Users opted to use hermes from nightly")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-8
@@ -17,7 +17,6 @@
|
|||||||
"format": "npm run prettier && npm run clang-format",
|
"format": "npm run prettier && npm run clang-format",
|
||||||
"featureflags": "yarn --cwd packages/react-native featureflags",
|
"featureflags": "yarn --cwd packages/react-native featureflags",
|
||||||
"lint-ci": "./.github/workflow-scripts/analyze_code.sh && yarn shellcheck",
|
"lint-ci": "./.github/workflow-scripts/analyze_code.sh && yarn shellcheck",
|
||||||
"lint-java": "node ./scripts/lint-java.js",
|
|
||||||
"lint-markdown": "markdownlint-cli2 2>&1",
|
"lint-markdown": "markdownlint-cli2 2>&1",
|
||||||
"lint": "eslint --max-warnings 0 .",
|
"lint": "eslint --max-warnings 0 .",
|
||||||
"prettier": "prettier --write \"./**/*.{js,md,yml,ts,tsx}\"",
|
"prettier": "prettier --write \"./**/*.{js,md,yml,ts,tsx}\"",
|
||||||
@@ -55,11 +54,11 @@
|
|||||||
"@react-native/metro-babel-transformer": "0.80.0-main",
|
"@react-native/metro-babel-transformer": "0.80.0-main",
|
||||||
"@react-native/metro-config": "0.80.0-main",
|
"@react-native/metro-config": "0.80.0-main",
|
||||||
"@tsconfig/node22": "22.0.2",
|
"@tsconfig/node22": "22.0.2",
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.1.0",
|
||||||
"@typescript-eslint/parser": "^7.1.1",
|
"@typescript-eslint/parser": "^7.1.1",
|
||||||
"ansi-styles": "^4.2.1",
|
"ansi-styles": "^4.2.1",
|
||||||
"babel-plugin-minify-dead-code-elimination": "^0.5.2",
|
"babel-plugin-minify-dead-code-elimination": "^0.5.2",
|
||||||
"babel-plugin-syntax-hermes-parser": "0.28.1",
|
"babel-plugin-syntax-hermes-parser": "0.29.0",
|
||||||
"babel-plugin-transform-define": "^2.1.4",
|
"babel-plugin-transform-define": "^2.1.4",
|
||||||
"babel-plugin-transform-flow-enums": "^0.0.2",
|
"babel-plugin-transform-flow-enums": "^0.0.2",
|
||||||
"clang-format": "^1.8.0",
|
"clang-format": "^1.8.0",
|
||||||
@@ -77,11 +76,11 @@
|
|||||||
"eslint-plugin-react-native": "^4.0.0",
|
"eslint-plugin-react-native": "^4.0.0",
|
||||||
"eslint-plugin-redundant-undefined": "^0.4.0",
|
"eslint-plugin-redundant-undefined": "^0.4.0",
|
||||||
"eslint-plugin-relay": "^1.8.3",
|
"eslint-plugin-relay": "^1.8.3",
|
||||||
"flow-api-translator": "0.28.1",
|
"flow-api-translator": "0.29.0",
|
||||||
"flow-bin": "^0.273.1",
|
"flow-bin": "^0.274.0",
|
||||||
"glob": "^7.1.1",
|
"glob": "^7.1.1",
|
||||||
"hermes-eslint": "0.28.1",
|
"hermes-eslint": "0.29.0",
|
||||||
"hermes-transform": "0.28.1",
|
"hermes-transform": "0.29.0",
|
||||||
"inquirer": "^7.1.0",
|
"inquirer": "^7.1.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-config": "^29.7.0",
|
"jest-config": "^29.7.0",
|
||||||
@@ -97,7 +96,7 @@
|
|||||||
"node-fetch": "^2.2.0",
|
"node-fetch": "^2.2.0",
|
||||||
"nullthrows": "^1.1.1",
|
"nullthrows": "^1.1.1",
|
||||||
"prettier": "2.8.8",
|
"prettier": "2.8.8",
|
||||||
"prettier-plugin-hermes-parser": "0.28.1",
|
"prettier-plugin-hermes-parser": "0.29.0",
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-test-renderer": "19.1.0",
|
"react-test-renderer": "19.1.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@generated SignedSource<<9ada78dff12dcfc7937c8934261f47f4>>
|
@generated SignedSource<<cf5be4596d1f07e220b710fc286d02fa>>
|
||||||
Git revision: 68cfd0ae84acb0ed8e47b421afd64ae3b0b5b727
|
Git revision: d95ac13bf0ab64a5e6c2eb18eb138587063b9c34
|
||||||
Built with --nohooks: false
|
Built with --nohooks: false
|
||||||
Is local checkout: false
|
Is local checkout: false
|
||||||
Remote URL: https://github.com/facebook/react-native-devtools-frontend
|
Remote URL: https://github.com/facebook/react-native-devtools-frontend
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -81,6 +81,7 @@ export default function createDevMiddleware({
|
|||||||
projectRoot,
|
projectRoot,
|
||||||
serverBaseUrl,
|
serverBaseUrl,
|
||||||
logger,
|
logger,
|
||||||
|
// $FlowFixMe[prop-missing]
|
||||||
unstable_browserLauncher = DefaultBrowserLauncher,
|
unstable_browserLauncher = DefaultBrowserLauncher,
|
||||||
unstable_eventReporter,
|
unstable_eventReporter,
|
||||||
unstable_experiments: experimentConfig = {},
|
unstable_experiments: experimentConfig = {},
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
"bugs": "https://github.com/facebook/react-native/issues",
|
"bugs": "https://github.com/facebook/react-native/issues",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-plugin-syntax-hermes-parser": "0.28.1",
|
"babel-plugin-syntax-hermes-parser": "0.29.0",
|
||||||
"hermes-eslint": "0.28.1"
|
"hermes-eslint": "0.29.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 22.14.0"
|
"node": ">= 22.14.0"
|
||||||
|
|||||||
@@ -32,8 +32,8 @@
|
|||||||
"source-map-support": "0.5.0"
|
"source-map-support": "0.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-plugin-syntax-hermes-parser": "0.28.1",
|
"babel-plugin-syntax-hermes-parser": "0.29.0",
|
||||||
"hermes-eslint": "0.28.1"
|
"hermes-eslint": "0.29.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 22.14.0"
|
"node": ">= 22.14.0"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.10.1"
|
agp = "8.11.0"
|
||||||
gson = "2.8.9"
|
gson = "2.8.9"
|
||||||
guava = "31.0.1-jre"
|
guava = "31.0.1-jre"
|
||||||
javapoet = "1.13.0"
|
javapoet = "1.13.0"
|
||||||
|
|||||||
+116
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.react.tasks.internal
|
||||||
|
|
||||||
|
import javax.inject.Inject
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
|
import org.gradle.api.file.CopySpec
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.file.DuplicatesStrategy
|
||||||
|
import org.gradle.api.file.FileSystemOperations
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task that takes care of extracting gflags from a source folder/zip and preparing it to be
|
||||||
|
* consumed by the NDK. This task will also take care of applying the mapping for gflags parameters.
|
||||||
|
*/
|
||||||
|
abstract class PrepareGflagsTask : DefaultTask() {
|
||||||
|
|
||||||
|
@get:InputFiles abstract val gflagsPath: ConfigurableFileCollection
|
||||||
|
@get:InputDirectory abstract val gflagsThirdPartyPath: DirectoryProperty
|
||||||
|
@get:Input abstract val gflagsVersion: Property<String>
|
||||||
|
|
||||||
|
@get:OutputDirectory abstract val outputDir: DirectoryProperty
|
||||||
|
|
||||||
|
@get:Inject abstract val fs: FileSystemOperations
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun taskAction() {
|
||||||
|
val commonCopyConfig: (action: CopySpec) -> Unit = { action ->
|
||||||
|
action.from(gflagsPath)
|
||||||
|
action.from(gflagsThirdPartyPath)
|
||||||
|
action.duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||||
|
action.includeEmptyDirs = false
|
||||||
|
action.into(outputDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.copy { action ->
|
||||||
|
commonCopyConfig(action)
|
||||||
|
action.include(
|
||||||
|
"gflags-${gflagsVersion.get()}/src/*.h",
|
||||||
|
"gflags-${gflagsVersion.get()}/src/*.cc",
|
||||||
|
"CMakeLists.txt")
|
||||||
|
action.filesMatching("*/src/*") { matchedFile ->
|
||||||
|
matchedFile.path = "gflags/${matchedFile.name}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.copy { action ->
|
||||||
|
commonCopyConfig(action)
|
||||||
|
action.include("gflags-${gflagsVersion.get()}/src/gflags_declare.h.in")
|
||||||
|
action.filesMatching("*/src/*") { matchedFile ->
|
||||||
|
matchedFile.filter { line ->
|
||||||
|
// Replace all placeholders with appropriate values
|
||||||
|
// see https://github.com/gflags/gflags/blob/v2.2.0/src/gflags_declare.h.in
|
||||||
|
line
|
||||||
|
.replace(Regex("@GFLAGS_NAMESPACE@"), "gflags")
|
||||||
|
.replace(
|
||||||
|
Regex(
|
||||||
|
"@(HAVE_STDINT_H|HAVE_SYS_TYPES_H|HAVE_INTTYPES_H|GFLAGS_INTTYPES_FORMAT_C99)@"),
|
||||||
|
"1")
|
||||||
|
.replace(Regex("@([A-Z0-9_]+)@"), "1")
|
||||||
|
}
|
||||||
|
matchedFile.path = "gflags/${matchedFile.name.removeSuffix(".in")}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.copy { action ->
|
||||||
|
commonCopyConfig(action)
|
||||||
|
action.include("gflags-${gflagsVersion.get()}/src/config.h.in")
|
||||||
|
action.filesMatching("*/src/*") { matchedFile ->
|
||||||
|
matchedFile.filter { line -> line.replace(Regex("^#cmakedefine"), "//cmakedefine") }
|
||||||
|
matchedFile.path = "gflags/${matchedFile.name.removeSuffix(".in")}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.copy { action ->
|
||||||
|
commonCopyConfig(action)
|
||||||
|
action.include("gflags-${gflagsVersion.get()}/src/gflags_ns.h.in")
|
||||||
|
action.filesMatching("*/src/*") { matchedFile ->
|
||||||
|
matchedFile.filter { line ->
|
||||||
|
line.replace(Regex("@ns@"), "google").replace(Regex("@NS@"), "google".uppercase())
|
||||||
|
}
|
||||||
|
matchedFile.path = "gflags/gflags_google.h"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.copy { action ->
|
||||||
|
commonCopyConfig(action)
|
||||||
|
action.include("gflags-${gflagsVersion.get()}/src/gflags.h.in")
|
||||||
|
action.filesMatching("*/src/*") { matchedFile ->
|
||||||
|
matchedFile.filter { line ->
|
||||||
|
line
|
||||||
|
.replace(Regex("@GFLAGS_ATTRIBUTE_UNUSED@"), "")
|
||||||
|
.replace(Regex("@INCLUDE_GFLAGS_NS_H@"), "#include \"gflags/gflags_google.h\"")
|
||||||
|
}
|
||||||
|
matchedFile.path = "gflags/${matchedFile.name.removeSuffix(".in")}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.copy { action ->
|
||||||
|
commonCopyConfig(action)
|
||||||
|
action.include("gflags-${gflagsVersion.get()}/src/gflags_completions.h.in")
|
||||||
|
action.filesMatching("*/src/*") { matchedFile ->
|
||||||
|
matchedFile.filter { line -> line.replace(Regex("@GFLAGS_NAMESPACE@"), "gflags") }
|
||||||
|
matchedFile.path = "gflags/${matchedFile.name.removeSuffix(".in")}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -126,6 +126,8 @@ internal object NdkConfiguratorUtils {
|
|||||||
): Pair<List<String>, List<String>> {
|
): Pair<List<String>, List<String>> {
|
||||||
val excludes = mutableListOf<String>()
|
val excludes = mutableListOf<String>()
|
||||||
val includes = mutableListOf<String>()
|
val includes = mutableListOf<String>()
|
||||||
|
|
||||||
|
// note: libjsctooling.so is kept here for backward compatibility.
|
||||||
when {
|
when {
|
||||||
hermesEnabled -> {
|
hermesEnabled -> {
|
||||||
excludes.add("**/libjsc.so")
|
excludes.add("**/libjsc.so")
|
||||||
|
|||||||
+209
@@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.react.tasks.internal
|
||||||
|
|
||||||
|
import com.facebook.react.tests.createProject
|
||||||
|
import com.facebook.react.tests.createTestTask
|
||||||
|
import java.io.*
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.rules.TemporaryFolder
|
||||||
|
|
||||||
|
class PrepareGflagsTaskTest {
|
||||||
|
|
||||||
|
@get:Rule val tempFolder = TemporaryFolder()
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException::class)
|
||||||
|
fun prepareGflagsTask_withMissingConfiguration_fails() {
|
||||||
|
val task = createTestTask<PrepareGflagsTask>()
|
||||||
|
|
||||||
|
task.taskAction()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun prepareGflagsTask_copiesCMakefile() {
|
||||||
|
val gflagspath = tempFolder.newFolder("gflagspath")
|
||||||
|
val output = tempFolder.newFolder("output")
|
||||||
|
val project = createProject()
|
||||||
|
val gflagsThirdPartyPath = File(project.projectDir, "src/main/jni/third-party/gflags/")
|
||||||
|
val task =
|
||||||
|
createTestTask<PrepareGflagsTask>(project = project) {
|
||||||
|
it.gflagsPath.setFrom(gflagspath)
|
||||||
|
it.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
|
||||||
|
it.gflagsVersion.set("1.0.0")
|
||||||
|
it.outputDir.set(output)
|
||||||
|
}
|
||||||
|
File(gflagsThirdPartyPath, "CMakeLists.txt").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
createNewFile()
|
||||||
|
}
|
||||||
|
task.taskAction()
|
||||||
|
|
||||||
|
assertThat(output.listFiles()!!.any { it.name == "CMakeLists.txt" }).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun prepareGflagsTask_copiesSourceCodeAndHeaders() {
|
||||||
|
val gflagspath = tempFolder.newFolder("gflagspath")
|
||||||
|
val gflagsThirdPartyPath = tempFolder.newFolder("gflagspath/jni")
|
||||||
|
val output = tempFolder.newFolder("output")
|
||||||
|
val task =
|
||||||
|
createTestTask<PrepareGflagsTask> {
|
||||||
|
it.gflagsPath.setFrom(gflagspath)
|
||||||
|
it.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
|
||||||
|
it.gflagsVersion.set("1.0.0")
|
||||||
|
it.outputDir.set(output)
|
||||||
|
}
|
||||||
|
File(gflagspath, "gflags-1.0.0/src/gflags.cc").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
createNewFile()
|
||||||
|
}
|
||||||
|
File(gflagspath, "gflags-1.0.0/src/util.h").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
createNewFile()
|
||||||
|
}
|
||||||
|
|
||||||
|
task.taskAction()
|
||||||
|
|
||||||
|
assertThat(File(output, "gflags/gflags.cc").exists()).isTrue()
|
||||||
|
assertThat(File(output, "gflags/util.h").exists()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun prepareGflagsTask_replacesTokenCorrectly() {
|
||||||
|
val gflagspath = tempFolder.newFolder("gflagspath")
|
||||||
|
val gflagsThirdPartyPath = tempFolder.newFolder("gflagspath/jni")
|
||||||
|
val output = tempFolder.newFolder("output")
|
||||||
|
val task =
|
||||||
|
createTestTask<PrepareGflagsTask> {
|
||||||
|
it.gflagsPath.setFrom(gflagspath)
|
||||||
|
it.gflagsThirdPartyPath.set(gflagsThirdPartyPath)
|
||||||
|
it.gflagsVersion.set("1.0.0")
|
||||||
|
it.outputDir.set(output)
|
||||||
|
}
|
||||||
|
File(gflagspath, "gflags-1.0.0/src/gflags_declare.h.in").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
writeText(
|
||||||
|
"""
|
||||||
|
#define GFLAGS_NAMESPACE @GFLAGS_NAMESPACE@
|
||||||
|
#include <string>
|
||||||
|
#if @HAVE_STDINT_H@
|
||||||
|
# include <stdint.h>
|
||||||
|
#elif @HAVE_SYS_TYPES_H@
|
||||||
|
# include <sys/types.h>
|
||||||
|
#elif @HAVE_INTTYPES_H@
|
||||||
|
# include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace GFLAGS_NAMESPACE {
|
||||||
|
|
||||||
|
#if @GFLAGS_INTTYPES_FORMAT_C99@ // C99
|
||||||
|
typedef int32_t int32;
|
||||||
|
typedef uint32_t uint32;
|
||||||
|
typedef int64_t int64;
|
||||||
|
typedef uint64_t uint64;
|
||||||
|
#elif @GFLAGS_INTTYPES_FORMAT_BSD@ // BSD
|
||||||
|
typedef int32_t int32;
|
||||||
|
typedef u_int32_t uint32;
|
||||||
|
typedef int64_t int64;
|
||||||
|
typedef u_int64_t uint64;
|
||||||
|
#elif @GFLAGS_INTTYPES_FORMAT_VC7@ // Windows
|
||||||
|
typedef __int32 int32;
|
||||||
|
typedef unsigned __int32 uint32;
|
||||||
|
typedef __int64 int64;
|
||||||
|
typedef unsigned __int64 uint64;
|
||||||
|
#else
|
||||||
|
# error Do not know how to define a 32-bit integer quantity on your system
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace GFLAGS_NAMESPACE
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
File(gflagspath, "gflags-1.0.0/src/config.h.in").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
createNewFile()
|
||||||
|
writeText("#cmakedefine")
|
||||||
|
}
|
||||||
|
File(gflagspath, "gflags-1.0.0/src/gflags_ns.h.in").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
createNewFile()
|
||||||
|
writeText("@ns@ @NS@")
|
||||||
|
}
|
||||||
|
File(gflagspath, "gflags-1.0.0/src/gflags.h.in").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
createNewFile()
|
||||||
|
writeText("@GFLAGS_ATTRIBUTE_UNUSED@\n@INCLUDE_GFLAGS_NS_H@")
|
||||||
|
}
|
||||||
|
File(gflagspath, "gflags-1.0.0/src/gflags_completions.h.in").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
createNewFile()
|
||||||
|
writeText("@GFLAGS_NAMESPACE@")
|
||||||
|
}
|
||||||
|
|
||||||
|
task.taskAction()
|
||||||
|
|
||||||
|
val declareFile = File(output, "gflags/gflags_declare.h")
|
||||||
|
assertThat(declareFile.exists()).isTrue()
|
||||||
|
assertEquals(
|
||||||
|
declareFile.readText(),
|
||||||
|
"""
|
||||||
|
#define GFLAGS_NAMESPACE gflags
|
||||||
|
#include <string>
|
||||||
|
#if 1
|
||||||
|
# include <stdint.h>
|
||||||
|
#elif 1
|
||||||
|
# include <sys/types.h>
|
||||||
|
#elif 1
|
||||||
|
# include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace GFLAGS_NAMESPACE {
|
||||||
|
|
||||||
|
#if 1 // C99
|
||||||
|
typedef int32_t int32;
|
||||||
|
typedef uint32_t uint32;
|
||||||
|
typedef int64_t int64;
|
||||||
|
typedef uint64_t uint64;
|
||||||
|
#elif 1 // BSD
|
||||||
|
typedef int32_t int32;
|
||||||
|
typedef u_int32_t uint32;
|
||||||
|
typedef int64_t int64;
|
||||||
|
typedef u_int64_t uint64;
|
||||||
|
#elif 1 // Windows
|
||||||
|
typedef __int32 int32;
|
||||||
|
typedef unsigned __int32 uint32;
|
||||||
|
typedef __int64 int64;
|
||||||
|
typedef unsigned __int64 uint64;
|
||||||
|
#else
|
||||||
|
# error Do not know how to define a 32-bit integer quantity on your system
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace GFLAGS_NAMESPACE
|
||||||
|
""")
|
||||||
|
|
||||||
|
val configFile = File(output, "gflags/config.h")
|
||||||
|
assertThat(configFile.exists()).isTrue()
|
||||||
|
assertEquals(configFile.readText(), "//cmakedefine")
|
||||||
|
|
||||||
|
val nsFile = File(output, "gflags/gflags_google.h")
|
||||||
|
assertThat(nsFile.exists()).isTrue()
|
||||||
|
assertEquals(nsFile.readText(), "google GOOGLE")
|
||||||
|
|
||||||
|
val gflagsFile = File(output, "gflags/gflags.h")
|
||||||
|
assertThat(gflagsFile.exists()).isTrue()
|
||||||
|
assertEquals(gflagsFile.readText(), "\n#include \"gflags/gflags_google.h\"")
|
||||||
|
|
||||||
|
val completionsFile = File(output, "gflags/gflags_completions.h")
|
||||||
|
assertThat(completionsFile.exists()).isTrue()
|
||||||
|
assertEquals(completionsFile.readText(), "gflags")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.1.0",
|
||||||
"react": "*",
|
"react": "*",
|
||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
"@babel/plugin-transform-unicode-regex": "^7.24.7",
|
"@babel/plugin-transform-unicode-regex": "^7.24.7",
|
||||||
"@babel/template": "^7.25.0",
|
"@babel/template": "^7.25.0",
|
||||||
"@react-native/babel-plugin-codegen": "0.80.0-main",
|
"@react-native/babel-plugin-codegen": "0.80.0-main",
|
||||||
"babel-plugin-syntax-hermes-parser": "0.28.1",
|
"babel-plugin-syntax-hermes-parser": "0.29.0",
|
||||||
"babel-plugin-transform-flow-enums": "^0.0.2",
|
"babel-plugin-transform-flow-enums": "^0.0.2",
|
||||||
"react-refresh": "^0.14.0"
|
"react-refresh": "^0.14.0"
|
||||||
},
|
},
|
||||||
|
|||||||
+2
-1
@@ -15,8 +15,9 @@ const lazyImports = require('./lazy-imports');
|
|||||||
|
|
||||||
const EXCLUDED_FIRST_PARTY_PATHS = [
|
const EXCLUDED_FIRST_PARTY_PATHS = [
|
||||||
/[/\\]node_modules[/\\]/,
|
/[/\\]node_modules[/\\]/,
|
||||||
/[/\\]packages[/\\]react-native(?:-fantom)?[/\\]/,
|
/[/\\]packages[/\\]react-native[/\\]/,
|
||||||
/[/\\]packages[/\\]virtualized-lists[/\\]/,
|
/[/\\]packages[/\\]virtualized-lists[/\\]/,
|
||||||
|
/[/\\]private[/\\]react-native-fantom[/\\]/,
|
||||||
];
|
];
|
||||||
|
|
||||||
function isTypeScriptSource(fileName) {
|
function isTypeScriptSource(fileName) {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
"@react-native/babel-preset": "0.80.0-main",
|
"@react-native/babel-preset": "0.80.0-main",
|
||||||
"hermes-parser": "0.28.1",
|
"hermes-parser": "0.29.0",
|
||||||
"nullthrows": "^1.1.1"
|
"nullthrows": "^1.1.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob": "^7.1.1",
|
"glob": "^7.1.1",
|
||||||
"hermes-parser": "0.28.1",
|
"hermes-parser": "0.29.0",
|
||||||
"invariant": "^2.2.4",
|
"invariant": "^2.2.4",
|
||||||
"nullthrows": "^1.1.1",
|
"nullthrows": "^1.1.1",
|
||||||
"yargs": "^17.6.2"
|
"yargs": "^17.6.2"
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
"@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
|
"@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
|
||||||
"@babel/plugin-transform-optional-chaining": "^7.24.8",
|
"@babel/plugin-transform-optional-chaining": "^7.24.8",
|
||||||
"@babel/preset-env": "^7.25.3",
|
"@babel/preset-env": "^7.25.3",
|
||||||
"hermes-estree": "0.28.1",
|
"hermes-estree": "0.29.0",
|
||||||
"micromatch": "^4.0.4",
|
"micromatch": "^4.0.4",
|
||||||
"prettier": "2.8.8",
|
"prettier": "2.8.8",
|
||||||
"rimraf": "^3.0.2"
|
"rimraf": "^3.0.2"
|
||||||
|
|||||||
@@ -73,9 +73,9 @@ const ALL_GENERATORS = {
|
|||||||
generateViewConfigJs: generateViewConfigJs.generate,
|
generateViewConfigJs: generateViewConfigJs.generate,
|
||||||
};
|
};
|
||||||
|
|
||||||
type FilesOutput = Map<string, string>;
|
export type FilesOutput = Map<string, string>;
|
||||||
|
|
||||||
type GenerateFunction = (
|
export type GenerateFunction = (
|
||||||
libraryName: string,
|
libraryName: string,
|
||||||
schema: SchemaType,
|
schema: SchemaType,
|
||||||
packageName?: string,
|
packageName?: string,
|
||||||
@@ -83,11 +83,11 @@ type GenerateFunction = (
|
|||||||
headerPrefix?: string,
|
headerPrefix?: string,
|
||||||
) => FilesOutput;
|
) => FilesOutput;
|
||||||
|
|
||||||
type LibraryGeneratorsFunctions = $ReadOnly<{
|
export type LibraryGeneratorsFunctions = $ReadOnly<{
|
||||||
[string]: Array<GenerateFunction>,
|
[string]: Array<GenerateFunction>,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
type LibraryOptions = $ReadOnly<{
|
export type LibraryOptions = $ReadOnly<{
|
||||||
libraryName: string,
|
libraryName: string,
|
||||||
schema: SchemaType,
|
schema: SchemaType,
|
||||||
outputDirectory: string,
|
outputDirectory: string,
|
||||||
@@ -97,13 +97,13 @@ type LibraryOptions = $ReadOnly<{
|
|||||||
libraryGenerators?: LibraryGeneratorsFunctions,
|
libraryGenerators?: LibraryGeneratorsFunctions,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
type SchemasOptions = $ReadOnly<{
|
export type SchemasOptions = $ReadOnly<{
|
||||||
schemas: {[string]: SchemaType},
|
schemas: {[string]: SchemaType},
|
||||||
outputDirectory: string,
|
outputDirectory: string,
|
||||||
supportedApplePlatforms?: {[string]: {[string]: boolean}},
|
supportedApplePlatforms?: {[string]: {[string]: boolean}},
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
type LibraryGenerators =
|
export type LibraryGenerators =
|
||||||
| 'componentsAndroid'
|
| 'componentsAndroid'
|
||||||
| 'componentsIOS'
|
| 'componentsIOS'
|
||||||
| 'descriptors'
|
| 'descriptors'
|
||||||
@@ -116,14 +116,14 @@ type LibraryGenerators =
|
|||||||
| 'modulesCxx'
|
| 'modulesCxx'
|
||||||
| 'modulesIOS';
|
| 'modulesIOS';
|
||||||
|
|
||||||
type SchemasGenerators = 'providerIOS';
|
export type SchemasGenerators = 'providerIOS';
|
||||||
|
|
||||||
type LibraryConfig = $ReadOnly<{
|
export type LibraryConfig = $ReadOnly<{
|
||||||
generators: Array<LibraryGenerators>,
|
generators: Array<LibraryGenerators>,
|
||||||
test?: boolean,
|
test?: boolean,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
type SchemasConfig = $ReadOnly<{
|
export type SchemasConfig = $ReadOnly<{
|
||||||
generators: Array<SchemasGenerators>,
|
generators: Array<SchemasGenerators>,
|
||||||
test?: boolean,
|
test?: boolean,
|
||||||
}>;
|
}>;
|
||||||
|
|||||||
+4
-1
@@ -18,7 +18,10 @@ const flowFixtures = require('../../flow/modules/__test_fixtures__/fixtures.js')
|
|||||||
const tsFixtures = require('../../typescript/modules/__test_fixtures__/fixtures.js');
|
const tsFixtures = require('../../typescript/modules/__test_fixtures__/fixtures.js');
|
||||||
const {compareSnaps, compareTsArraySnaps} = require('../compareSnaps.js');
|
const {compareSnaps, compareTsArraySnaps} = require('../compareSnaps.js');
|
||||||
|
|
||||||
const flowExtraCases = ['PROMISE_WITH_COMMONLY_USED_TYPES'];
|
const flowExtraCases = [
|
||||||
|
'NATIVE_MODULE_WITH_OPAQUE_TYPES',
|
||||||
|
'PROMISE_WITH_COMMONLY_USED_TYPES',
|
||||||
|
];
|
||||||
const tsExtraCases = [
|
const tsExtraCases = [
|
||||||
'NATIVE_MODULE_WITH_ARRAY2_WITH_ALIAS',
|
'NATIVE_MODULE_WITH_ARRAY2_WITH_ALIAS',
|
||||||
'NATIVE_MODULE_WITH_ARRAY2_WITH_UNION_AND_TOUPLE',
|
'NATIVE_MODULE_WITH_ARRAY2_WITH_UNION_AND_TOUPLE',
|
||||||
|
|||||||
+32
@@ -691,6 +691,37 @@ export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
|
|||||||
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const NATIVE_MODULE_WITH_OPAQUE_TYPES = `
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @flow strict-local
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import type {TurboModule} from '../RCTExport';
|
||||||
|
import * as TurboModuleRegistry from '../TurboModuleRegistry';
|
||||||
|
|
||||||
|
export opaque type Task = mixed;
|
||||||
|
export opaque type TimeoutID = number;
|
||||||
|
|
||||||
|
export interface Spec extends TurboModule {
|
||||||
|
+createTask: (callback: () => void) => Task;
|
||||||
|
+cancelTask: (task: Task) => void;
|
||||||
|
|
||||||
|
+setTimeout: (callback: () => void) => TimeoutID;
|
||||||
|
+clearTimeout: (timeoutID: TimeoutID) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TurboModuleRegistry.getEnforcing<Spec>('SampleTurboModule');
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
const ANDROID_ONLY_NATIVE_MODULE = `
|
const ANDROID_ONLY_NATIVE_MODULE = `
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
@@ -976,6 +1007,7 @@ module.exports = {
|
|||||||
NATIVE_MODULE_WITH_UNION,
|
NATIVE_MODULE_WITH_UNION,
|
||||||
NATIVE_MODULE_WITH_UNION_RETURN_TYPES,
|
NATIVE_MODULE_WITH_UNION_RETURN_TYPES,
|
||||||
NATIVE_MODULE_WITH_EVENT_EMITTERS,
|
NATIVE_MODULE_WITH_EVENT_EMITTERS,
|
||||||
|
NATIVE_MODULE_WITH_OPAQUE_TYPES,
|
||||||
EMPTY_NATIVE_MODULE,
|
EMPTY_NATIVE_MODULE,
|
||||||
ANDROID_ONLY_NATIVE_MODULE,
|
ANDROID_ONLY_NATIVE_MODULE,
|
||||||
IOS_ONLY_NATIVE_MODULE,
|
IOS_ONLY_NATIVE_MODULE,
|
||||||
|
|||||||
+102
@@ -2187,6 +2187,108 @@ exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_OBJECT_W
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_OPAQUE_TYPES 1`] = `
|
||||||
|
"{
|
||||||
|
'modules': {
|
||||||
|
'NativeSampleTurboModule': {
|
||||||
|
'type': 'NativeModule',
|
||||||
|
'aliasMap': {},
|
||||||
|
'enumMap': {},
|
||||||
|
'spec': {
|
||||||
|
'eventEmitters': [],
|
||||||
|
'methods': [
|
||||||
|
{
|
||||||
|
'name': 'createTask',
|
||||||
|
'optional': false,
|
||||||
|
'typeAnnotation': {
|
||||||
|
'type': 'FunctionTypeAnnotation',
|
||||||
|
'returnTypeAnnotation': {
|
||||||
|
'type': 'GenericObjectTypeAnnotation'
|
||||||
|
},
|
||||||
|
'params': [
|
||||||
|
{
|
||||||
|
'name': 'callback',
|
||||||
|
'optional': false,
|
||||||
|
'typeAnnotation': {
|
||||||
|
'type': 'FunctionTypeAnnotation',
|
||||||
|
'returnTypeAnnotation': {
|
||||||
|
'type': 'VoidTypeAnnotation'
|
||||||
|
},
|
||||||
|
'params': []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'cancelTask',
|
||||||
|
'optional': false,
|
||||||
|
'typeAnnotation': {
|
||||||
|
'type': 'FunctionTypeAnnotation',
|
||||||
|
'returnTypeAnnotation': {
|
||||||
|
'type': 'VoidTypeAnnotation'
|
||||||
|
},
|
||||||
|
'params': [
|
||||||
|
{
|
||||||
|
'name': 'task',
|
||||||
|
'optional': false,
|
||||||
|
'typeAnnotation': {
|
||||||
|
'type': 'GenericObjectTypeAnnotation'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'setTimeout',
|
||||||
|
'optional': false,
|
||||||
|
'typeAnnotation': {
|
||||||
|
'type': 'FunctionTypeAnnotation',
|
||||||
|
'returnTypeAnnotation': {
|
||||||
|
'type': 'NumberTypeAnnotation'
|
||||||
|
},
|
||||||
|
'params': [
|
||||||
|
{
|
||||||
|
'name': 'callback',
|
||||||
|
'optional': false,
|
||||||
|
'typeAnnotation': {
|
||||||
|
'type': 'FunctionTypeAnnotation',
|
||||||
|
'returnTypeAnnotation': {
|
||||||
|
'type': 'VoidTypeAnnotation'
|
||||||
|
},
|
||||||
|
'params': []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'clearTimeout',
|
||||||
|
'optional': false,
|
||||||
|
'typeAnnotation': {
|
||||||
|
'type': 'FunctionTypeAnnotation',
|
||||||
|
'returnTypeAnnotation': {
|
||||||
|
'type': 'VoidTypeAnnotation'
|
||||||
|
},
|
||||||
|
'params': [
|
||||||
|
{
|
||||||
|
'name': 'timeoutID',
|
||||||
|
'optional': false,
|
||||||
|
'typeAnnotation': {
|
||||||
|
'type': 'NumberTypeAnnotation'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'moduleName': 'SampleTurboModule'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PARTIALS 1`] = `
|
exports[`RN Codegen Flow Parser can generate fixture NATIVE_MODULE_WITH_PARTIALS 1`] = `
|
||||||
"{
|
"{
|
||||||
'modules': {
|
'modules': {
|
||||||
|
|||||||
@@ -296,6 +296,7 @@ class FlowParser implements Parser {
|
|||||||
if (
|
if (
|
||||||
node.declaration != null &&
|
node.declaration != null &&
|
||||||
(node.declaration.type === 'TypeAlias' ||
|
(node.declaration.type === 'TypeAlias' ||
|
||||||
|
node.declaration.type === 'OpaqueType' ||
|
||||||
node.declaration.type === 'InterfaceDeclaration')
|
node.declaration.type === 'InterfaceDeclaration')
|
||||||
) {
|
) {
|
||||||
types[node.declaration.id.name] = node.declaration;
|
types[node.declaration.id.name] = node.declaration;
|
||||||
@@ -309,6 +310,7 @@ class FlowParser implements Parser {
|
|||||||
types[node.declaration.id.name] = node.declaration;
|
types[node.declaration.id.name] = node.declaration;
|
||||||
} else if (
|
} else if (
|
||||||
node.type === 'TypeAlias' ||
|
node.type === 'TypeAlias' ||
|
||||||
|
node.type === 'OpaqueType' ||
|
||||||
node.type === 'InterfaceDeclaration' ||
|
node.type === 'InterfaceDeclaration' ||
|
||||||
node.type === 'EnumDeclaration'
|
node.type === 'EnumDeclaration'
|
||||||
) {
|
) {
|
||||||
@@ -543,6 +545,10 @@ class FlowParser implements Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nextNodeForTypeAlias(typeAnnotation: $FlowFixMe): $FlowFixMe {
|
nextNodeForTypeAlias(typeAnnotation: $FlowFixMe): $FlowFixMe {
|
||||||
|
if (typeAnnotation.type === 'OpaqueType') {
|
||||||
|
return typeAnnotation.impltype;
|
||||||
|
}
|
||||||
|
|
||||||
return typeAnnotation.right;
|
return typeAnnotation.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1233,7 +1233,8 @@ function handleGenericTypeAnnotation(
|
|||||||
let node;
|
let node;
|
||||||
|
|
||||||
switch (resolvedTypeAnnotation.type) {
|
switch (resolvedTypeAnnotation.type) {
|
||||||
case parser.typeAlias: {
|
case parser.typeAlias:
|
||||||
|
case 'OpaqueType': {
|
||||||
typeResolutionStatus = getTypeResolutionStatus(
|
typeResolutionStatus = getTypeResolutionStatus(
|
||||||
'alias',
|
'alias',
|
||||||
typeAnnotation,
|
typeAnnotation,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
"@react-native/codegen": "0.80.0-main"
|
"@react-native/codegen": "0.80.0-main"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.1.0",
|
||||||
"react": "*",
|
"react": "*",
|
||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#import <React/RCTUIManager.h>
|
#import <React/RCTUIManager.h>
|
||||||
#import <React/RCTViewManager.h>
|
#import <React/RCTViewManager.h>
|
||||||
|
|
||||||
|
#import <string>
|
||||||
|
|
||||||
static UIColor *UIColorFromHexString(const std::string hexString)
|
static UIColor *UIColorFromHexString(const std::string hexString)
|
||||||
{
|
{
|
||||||
unsigned rgbValue = 0;
|
unsigned rgbValue = 0;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ Pod::Spec.new do |s|
|
|||||||
s.author = "Meta Platforms, Inc. and its affiliates"
|
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "*.{m}"
|
s.source_files = podspec_sources("*.{m}", "")
|
||||||
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
||||||
s.header_dir = "RCTActionSheet"
|
s.header_dir = "RCTActionSheet"
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export type EventConfig<T> = {
|
|||||||
platformConfig?: PlatformConfig,
|
platformConfig?: PlatformConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function attachNativeEvent(
|
export function attachNativeEventImpl(
|
||||||
viewRef: any,
|
viewRef: any,
|
||||||
eventName: string,
|
eventName: string,
|
||||||
argMapping: $ReadOnlyArray<?Mapping>,
|
argMapping: $ReadOnlyArray<?Mapping>,
|
||||||
@@ -181,7 +181,7 @@ export class AnimatedEvent {
|
|||||||
'Only native driven events need to be attached.',
|
'Only native driven events need to be attached.',
|
||||||
);
|
);
|
||||||
|
|
||||||
this._attachedEvent = attachNativeEvent(
|
this._attachedEvent = attachNativeEventImpl(
|
||||||
viewRef,
|
viewRef,
|
||||||
eventName,
|
eventName,
|
||||||
this._argMapping,
|
this._argMapping,
|
||||||
|
|||||||
@@ -10,6 +10,10 @@
|
|||||||
|
|
||||||
import AnimatedImplementation from './AnimatedImplementation';
|
import AnimatedImplementation from './AnimatedImplementation';
|
||||||
|
|
||||||
|
export type {DecayAnimationConfig} from './animations/DecayAnimation';
|
||||||
|
export type {SpringAnimationConfig} from './animations/SpringAnimation';
|
||||||
|
export type {TimingAnimationConfig} from './animations/TimingAnimation';
|
||||||
|
|
||||||
export {default as FlatList} from './components/AnimatedFlatList';
|
export {default as FlatList} from './components/AnimatedFlatList';
|
||||||
export {default as Image} from './components/AnimatedImage';
|
export {default as Image} from './components/AnimatedImage';
|
||||||
export {default as ScrollView} from './components/AnimatedScrollView';
|
export {default as ScrollView} from './components/AnimatedScrollView';
|
||||||
@@ -33,6 +37,7 @@ export type {default as AnimatedNode} from './nodes/AnimatedNode';
|
|||||||
export type {default as AnimatedAddition} from './nodes/AnimatedAddition';
|
export type {default as AnimatedAddition} from './nodes/AnimatedAddition';
|
||||||
export type {default as AnimatedDiffClamp} from './nodes/AnimatedDiffClamp';
|
export type {default as AnimatedDiffClamp} from './nodes/AnimatedDiffClamp';
|
||||||
export type {default as AnimatedDivision} from './nodes/AnimatedDivision';
|
export type {default as AnimatedDivision} from './nodes/AnimatedDivision';
|
||||||
|
export type {InterpolationConfigType as InterpolationConfig} from './nodes/AnimatedInterpolation';
|
||||||
export type {default as AnimatedModulo} from './nodes/AnimatedModulo';
|
export type {default as AnimatedModulo} from './nodes/AnimatedModulo';
|
||||||
export type {default as AnimatedMultiplication} from './nodes/AnimatedMultiplication';
|
export type {default as AnimatedMultiplication} from './nodes/AnimatedMultiplication';
|
||||||
export type {default as AnimatedSubtraction} from './nodes/AnimatedSubtraction';
|
export type {default as AnimatedSubtraction} from './nodes/AnimatedSubtraction';
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import type {DecayAnimationConfig} from './animations/DecayAnimation';
|
|||||||
import type {SpringAnimationConfig} from './animations/SpringAnimation';
|
import type {SpringAnimationConfig} from './animations/SpringAnimation';
|
||||||
import type {TimingAnimationConfig} from './animations/TimingAnimation';
|
import type {TimingAnimationConfig} from './animations/TimingAnimation';
|
||||||
|
|
||||||
import {AnimatedEvent, attachNativeEvent} from './AnimatedEvent';
|
import {AnimatedEvent, attachNativeEventImpl} from './AnimatedEvent';
|
||||||
import DecayAnimation from './animations/DecayAnimation';
|
import DecayAnimation from './animations/DecayAnimation';
|
||||||
import SpringAnimation from './animations/SpringAnimation';
|
import SpringAnimation from './animations/SpringAnimation';
|
||||||
import TimingAnimation from './animations/TimingAnimation';
|
import TimingAnimation from './animations/TimingAnimation';
|
||||||
@@ -47,39 +47,39 @@ export type CompositeAnimation = {
|
|||||||
...
|
...
|
||||||
};
|
};
|
||||||
|
|
||||||
const add = function (
|
const addImpl = function (
|
||||||
a: AnimatedNode | number,
|
a: AnimatedNode | number,
|
||||||
b: AnimatedNode | number,
|
b: AnimatedNode | number,
|
||||||
): AnimatedAddition {
|
): AnimatedAddition {
|
||||||
return new AnimatedAddition(a, b);
|
return new AnimatedAddition(a, b);
|
||||||
};
|
};
|
||||||
|
|
||||||
const subtract = function (
|
const subtractImpl = function (
|
||||||
a: AnimatedNode | number,
|
a: AnimatedNode | number,
|
||||||
b: AnimatedNode | number,
|
b: AnimatedNode | number,
|
||||||
): AnimatedSubtraction {
|
): AnimatedSubtraction {
|
||||||
return new AnimatedSubtraction(a, b);
|
return new AnimatedSubtraction(a, b);
|
||||||
};
|
};
|
||||||
|
|
||||||
const divide = function (
|
const divideImpl = function (
|
||||||
a: AnimatedNode | number,
|
a: AnimatedNode | number,
|
||||||
b: AnimatedNode | number,
|
b: AnimatedNode | number,
|
||||||
): AnimatedDivision {
|
): AnimatedDivision {
|
||||||
return new AnimatedDivision(a, b);
|
return new AnimatedDivision(a, b);
|
||||||
};
|
};
|
||||||
|
|
||||||
const multiply = function (
|
const multiplyImpl = function (
|
||||||
a: AnimatedNode | number,
|
a: AnimatedNode | number,
|
||||||
b: AnimatedNode | number,
|
b: AnimatedNode | number,
|
||||||
): AnimatedMultiplication {
|
): AnimatedMultiplication {
|
||||||
return new AnimatedMultiplication(a, b);
|
return new AnimatedMultiplication(a, b);
|
||||||
};
|
};
|
||||||
|
|
||||||
const modulo = function (a: AnimatedNode, modulus: number): AnimatedModulo {
|
const moduloImpl = function (a: AnimatedNode, modulus: number): AnimatedModulo {
|
||||||
return new AnimatedModulo(a, modulus);
|
return new AnimatedModulo(a, modulus);
|
||||||
};
|
};
|
||||||
|
|
||||||
const diffClamp = function (
|
const diffClampImpl = function (
|
||||||
a: AnimatedNode,
|
a: AnimatedNode,
|
||||||
min: number,
|
min: number,
|
||||||
max: number,
|
max: number,
|
||||||
@@ -120,7 +120,7 @@ const maybeVectorAnim = function (
|
|||||||
const aY = anim((value: AnimatedValueXY).y, configY);
|
const aY = anim((value: AnimatedValueXY).y, configY);
|
||||||
// We use `stopTogether: false` here because otherwise tracking will break
|
// We use `stopTogether: false` here because otherwise tracking will break
|
||||||
// because the second animation will get stopped before it can update.
|
// because the second animation will get stopped before it can update.
|
||||||
return parallel([aX, aY], {stopTogether: false});
|
return parallelImpl([aX, aY], {stopTogether: false});
|
||||||
} else if (value instanceof AnimatedColor) {
|
} else if (value instanceof AnimatedColor) {
|
||||||
const configR = {...config};
|
const configR = {...config};
|
||||||
const configG = {...config};
|
const configG = {...config};
|
||||||
@@ -146,12 +146,12 @@ const maybeVectorAnim = function (
|
|||||||
const aA = anim((value: AnimatedColor).a, configA);
|
const aA = anim((value: AnimatedColor).a, configA);
|
||||||
// We use `stopTogether: false` here because otherwise tracking will break
|
// We use `stopTogether: false` here because otherwise tracking will break
|
||||||
// because the second animation will get stopped before it can update.
|
// because the second animation will get stopped before it can update.
|
||||||
return parallel([aR, aG, aB, aA], {stopTogether: false});
|
return parallelImpl([aR, aG, aB, aA], {stopTogether: false});
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const spring = function (
|
const springImpl = function (
|
||||||
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
||||||
config: SpringAnimationConfig,
|
config: SpringAnimationConfig,
|
||||||
): CompositeAnimation {
|
): CompositeAnimation {
|
||||||
@@ -179,7 +179,7 @@ const spring = function (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
maybeVectorAnim(value, config, spring) || {
|
maybeVectorAnim(value, config, springImpl) || {
|
||||||
start: function (callback?: ?EndCallback): void {
|
start: function (callback?: ?EndCallback): void {
|
||||||
start(value, config, callback);
|
start(value, config, callback);
|
||||||
},
|
},
|
||||||
@@ -204,7 +204,7 @@ const spring = function (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const timing = function (
|
const timingImpl = function (
|
||||||
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
||||||
config: TimingAnimationConfig,
|
config: TimingAnimationConfig,
|
||||||
): CompositeAnimation {
|
): CompositeAnimation {
|
||||||
@@ -233,7 +233,7 @@ const timing = function (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
maybeVectorAnim(value, config, timing) || {
|
maybeVectorAnim(value, config, timingImpl) || {
|
||||||
start: function (callback?: ?EndCallback, isLooping?: boolean): void {
|
start: function (callback?: ?EndCallback, isLooping?: boolean): void {
|
||||||
start(value, {...config, isLooping}, callback);
|
start(value, {...config, isLooping}, callback);
|
||||||
},
|
},
|
||||||
@@ -258,7 +258,7 @@ const timing = function (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const decay = function (
|
const decayImpl = function (
|
||||||
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
||||||
config: DecayAnimationConfig,
|
config: DecayAnimationConfig,
|
||||||
): CompositeAnimation {
|
): CompositeAnimation {
|
||||||
@@ -275,7 +275,7 @@ const decay = function (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
maybeVectorAnim(value, config, decay) || {
|
maybeVectorAnim(value, config, decayImpl) || {
|
||||||
start: function (callback?: ?EndCallback): void {
|
start: function (callback?: ?EndCallback): void {
|
||||||
start(value, config, callback);
|
start(value, config, callback);
|
||||||
},
|
},
|
||||||
@@ -300,7 +300,7 @@ const decay = function (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const sequence = function (
|
const sequenceImpl = function (
|
||||||
animations: Array<CompositeAnimation>,
|
animations: Array<CompositeAnimation>,
|
||||||
): CompositeAnimation {
|
): CompositeAnimation {
|
||||||
let current = 0;
|
let current = 0;
|
||||||
@@ -363,7 +363,7 @@ type ParallelConfig = {
|
|||||||
stopTogether?: boolean,
|
stopTogether?: boolean,
|
||||||
...
|
...
|
||||||
};
|
};
|
||||||
const parallel = function (
|
const parallelImpl = function (
|
||||||
animations: Array<CompositeAnimation>,
|
animations: Array<CompositeAnimation>,
|
||||||
config?: ?ParallelConfig,
|
config?: ?ParallelConfig,
|
||||||
): CompositeAnimation {
|
): CompositeAnimation {
|
||||||
@@ -431,9 +431,9 @@ const parallel = function (
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
const delay = function (time: number): CompositeAnimation {
|
const delayImpl = function (time: number): CompositeAnimation {
|
||||||
// Would be nice to make a specialized implementation
|
// Would be nice to make a specialized implementation
|
||||||
return timing(new AnimatedValue(0), {
|
return timingImpl(new AnimatedValue(0), {
|
||||||
toValue: 0,
|
toValue: 0,
|
||||||
delay: time,
|
delay: time,
|
||||||
duration: 0,
|
duration: 0,
|
||||||
@@ -441,13 +441,13 @@ const delay = function (time: number): CompositeAnimation {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const stagger = function (
|
const staggerImpl = function (
|
||||||
time: number,
|
time: number,
|
||||||
animations: Array<CompositeAnimation>,
|
animations: Array<CompositeAnimation>,
|
||||||
): CompositeAnimation {
|
): CompositeAnimation {
|
||||||
return parallel(
|
return parallelImpl(
|
||||||
animations.map((animation, i) => {
|
animations.map((animation, i) => {
|
||||||
return sequence([delay(time * i), animation]);
|
return sequenceImpl([delayImpl(time * i), animation]);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -458,7 +458,7 @@ type LoopAnimationConfig = {
|
|||||||
...
|
...
|
||||||
};
|
};
|
||||||
|
|
||||||
const loop = function (
|
const loopImpl = function (
|
||||||
animation: CompositeAnimation,
|
animation: CompositeAnimation,
|
||||||
// $FlowFixMe[prop-missing]
|
// $FlowFixMe[prop-missing]
|
||||||
{iterations = -1, resetBeforeIteration = true}: LoopAnimationConfig = {},
|
{iterations = -1, resetBeforeIteration = true}: LoopAnimationConfig = {},
|
||||||
@@ -514,7 +514,7 @@ const loop = function (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
function forkEvent(
|
function forkEventImpl(
|
||||||
event: ?AnimatedEvent | ?Function,
|
event: ?AnimatedEvent | ?Function,
|
||||||
listener: Function,
|
listener: Function,
|
||||||
): AnimatedEvent | Function {
|
): AnimatedEvent | Function {
|
||||||
@@ -531,7 +531,7 @@ function forkEvent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function unforkEvent(
|
function unforkEventImpl(
|
||||||
event: ?AnimatedEvent | ?Function,
|
event: ?AnimatedEvent | ?Function,
|
||||||
listener: Function,
|
listener: Function,
|
||||||
): void {
|
): void {
|
||||||
@@ -540,7 +540,7 @@ function unforkEvent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = function <T>(
|
const eventImpl = function <T>(
|
||||||
argMapping: $ReadOnlyArray<?Mapping>,
|
argMapping: $ReadOnlyArray<?Mapping>,
|
||||||
config: EventConfig<T>,
|
config: EventConfig<T>,
|
||||||
): any {
|
): any {
|
||||||
@@ -606,25 +606,25 @@ export default {
|
|||||||
* See https://reactnative.dev/docs/animated#node
|
* See https://reactnative.dev/docs/animated#node
|
||||||
*/
|
*/
|
||||||
Node: AnimatedNode,
|
Node: AnimatedNode,
|
||||||
decay,
|
decay: decayImpl,
|
||||||
timing,
|
timing: timingImpl,
|
||||||
spring,
|
spring: springImpl,
|
||||||
add,
|
add: addImpl,
|
||||||
subtract,
|
subtract: subtractImpl,
|
||||||
divide,
|
divide: divideImpl,
|
||||||
multiply,
|
multiply: multiplyImpl,
|
||||||
modulo,
|
modulo: moduloImpl,
|
||||||
diffClamp,
|
diffClamp: diffClampImpl,
|
||||||
delay,
|
delay: delayImpl,
|
||||||
sequence,
|
sequence: sequenceImpl,
|
||||||
parallel,
|
parallel: parallelImpl,
|
||||||
stagger,
|
stagger: staggerImpl,
|
||||||
loop,
|
loop: loopImpl,
|
||||||
event,
|
event: eventImpl,
|
||||||
createAnimatedComponent,
|
createAnimatedComponent,
|
||||||
attachNativeEvent,
|
attachNativeEvent: attachNativeEventImpl,
|
||||||
forkEvent,
|
forkEvent: forkEventImpl,
|
||||||
unforkEvent,
|
unforkEvent: unforkEventImpl,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose Event class, so it can be used as a type for type checkers.
|
* Expose Event class, so it can be used as a type for type checkers.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import type {DecayAnimationConfig} from './animations/DecayAnimation';
|
|||||||
import type {SpringAnimationConfig} from './animations/SpringAnimation';
|
import type {SpringAnimationConfig} from './animations/SpringAnimation';
|
||||||
import type {TimingAnimationConfig} from './animations/TimingAnimation';
|
import type {TimingAnimationConfig} from './animations/TimingAnimation';
|
||||||
|
|
||||||
import {AnimatedEvent, attachNativeEvent} from './AnimatedEvent';
|
import {AnimatedEvent, attachNativeEventImpl} from './AnimatedEvent';
|
||||||
import AnimatedImplementation from './AnimatedImplementation';
|
import AnimatedImplementation from './AnimatedImplementation';
|
||||||
import createAnimatedComponent from './createAnimatedComponent';
|
import createAnimatedComponent from './createAnimatedComponent';
|
||||||
import AnimatedColor from './nodes/AnimatedColor';
|
import AnimatedColor from './nodes/AnimatedColor';
|
||||||
@@ -188,7 +188,7 @@ export default {
|
|||||||
loop,
|
loop,
|
||||||
event: AnimatedImplementation.event,
|
event: AnimatedImplementation.event,
|
||||||
createAnimatedComponent,
|
createAnimatedComponent,
|
||||||
attachNativeEvent,
|
attachNativeEvent: attachNativeEventImpl,
|
||||||
forkEvent: AnimatedImplementation.forkEvent,
|
forkEvent: AnimatedImplementation.forkEvent,
|
||||||
unforkEvent: AnimatedImplementation.unforkEvent,
|
unforkEvent: AnimatedImplementation.unforkEvent,
|
||||||
Event: AnimatedEvent,
|
Event: AnimatedEvent,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* This source code is licensed under the MIT license found in the
|
* This source code is licensed under the MIT license found in the
|
||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*
|
*
|
||||||
|
* @fantom_flags cxxNativeAnimatedRemoveJsSync:*
|
||||||
* @flow strict-local
|
* @flow strict-local
|
||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
@@ -16,6 +17,8 @@ import ensureInstance from '../../../src/private/__tests__/utilities/ensureInsta
|
|||||||
import * as Fantom from '@react-native/fantom';
|
import * as Fantom from '@react-native/fantom';
|
||||||
import {createRef} from 'react';
|
import {createRef} from 'react';
|
||||||
import {Animated, View, useAnimatedValue} from 'react-native';
|
import {Animated, View, useAnimatedValue} from 'react-native';
|
||||||
|
import {allowStyleProp} from 'react-native/Libraries/Animated/NativeAnimatedAllowlist';
|
||||||
|
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
|
||||||
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
|
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
|
||||||
|
|
||||||
test('moving box by 100 points', () => {
|
test('moving box by 100 points', () => {
|
||||||
@@ -32,11 +35,9 @@ test('moving box by 100 points', () => {
|
|||||||
{
|
{
|
||||||
width: 100,
|
width: 100,
|
||||||
height: 100,
|
height: 100,
|
||||||
backgroundColor: 'red',
|
|
||||||
},
|
},
|
||||||
{transform: [{translateX}]},
|
{transform: [{translateX}]},
|
||||||
]}
|
]}
|
||||||
testID="box"
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -75,11 +76,15 @@ test('moving box by 100 points', () => {
|
|||||||
Fantom.unstable_produceFramesForDuration(500);
|
Fantom.unstable_produceFramesForDuration(500);
|
||||||
|
|
||||||
// Animation is completed now. C++ Animated will commit the final position to the shadow tree.
|
// Animation is completed now. C++ Animated will commit the final position to the shadow tree.
|
||||||
expect(viewElement.getBoundingClientRect().x).toBe(100);
|
if (ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()) {
|
||||||
|
expect(viewElement.getBoundingClientRect().x).toBe(100);
|
||||||
|
// TODO(T223344928): this shouldn't be neccessary
|
||||||
|
Fantom.runWorkLoop();
|
||||||
|
} else {
|
||||||
|
expect(viewElement.getBoundingClientRect().x).toBe(0);
|
||||||
|
Fantom.runWorkLoop(); // Animated still schedules a React state update for synchronisation to shadow tree
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: this shouldn't be needed but C++ Animated still schedules a React state update
|
|
||||||
// for synchronisation, even though it doesn't need to.
|
|
||||||
Fantom.runWorkLoop();
|
|
||||||
expect(viewElement.getBoundingClientRect().x).toBe(100);
|
expect(viewElement.getBoundingClientRect().x).toBe(100);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -143,6 +148,392 @@ test('animation driven by onScroll event', () => {
|
|||||||
|
|
||||||
expect(transform.translateY).toBeCloseTo(100, 0.001);
|
expect(transform.translateY).toBeCloseTo(100, 0.001);
|
||||||
|
|
||||||
// TODO(T226364699): this should `toBe(100)` but we are not syncing shadow tree yet.
|
expect(viewElement.getBoundingClientRect().y).toBe(100);
|
||||||
expect(viewElement.getBoundingClientRect().y).toBe(0);
|
});
|
||||||
|
|
||||||
|
test('animated opacity', () => {
|
||||||
|
let _opacity;
|
||||||
|
let _opacityAnimation;
|
||||||
|
const viewRef = createRef<HostInstance>();
|
||||||
|
|
||||||
|
function MyApp() {
|
||||||
|
const opacity = useAnimatedValue(1);
|
||||||
|
_opacity = opacity;
|
||||||
|
return (
|
||||||
|
<Animated.View
|
||||||
|
ref={viewRef}
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
opacity: opacity,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = Fantom.createRoot();
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
root.render(<MyApp />);
|
||||||
|
});
|
||||||
|
|
||||||
|
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
|
||||||
|
|
||||||
|
expect(viewElement.getBoundingClientRect().x).toBe(0);
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
_opacityAnimation = Animated.timing(_opacity, {
|
||||||
|
toValue: 0,
|
||||||
|
duration: 30,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
|
});
|
||||||
|
|
||||||
|
Fantom.unstable_produceFramesForDuration(30);
|
||||||
|
expect(Fantom.unstable_getDirectManipulationProps(viewElement).opacity).toBe(
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: this shouldn't be neccessary since animation should be stopped after duration
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
_opacityAnimation?.stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(root.getRenderedOutput({props: ['opacity']}).toJSX()).toEqual(
|
||||||
|
<rn-view opacity="0" />,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('moving box by 50 points with offset 10', () => {
|
||||||
|
let _translateX;
|
||||||
|
const viewRef = createRef<HostInstance>();
|
||||||
|
|
||||||
|
function MyApp() {
|
||||||
|
const translateX = useAnimatedValue(0);
|
||||||
|
_translateX = translateX;
|
||||||
|
return (
|
||||||
|
<Animated.View
|
||||||
|
ref={viewRef}
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
},
|
||||||
|
{transform: [{translateX}]},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = Fantom.createRoot();
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
root.render(<MyApp />);
|
||||||
|
});
|
||||||
|
|
||||||
|
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
|
||||||
|
|
||||||
|
expect(viewElement.getBoundingClientRect().x).toBe(0);
|
||||||
|
|
||||||
|
let finishValue = null;
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
Animated.timing(_translateX, {
|
||||||
|
toValue: 50,
|
||||||
|
duration: 1000, // 1 second
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start(result => {
|
||||||
|
finishValue = result;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
_translateX.setOffset(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
Fantom.unstable_produceFramesForDuration(500);
|
||||||
|
|
||||||
|
// shadow tree is not synchronised yet, position X is still 0.
|
||||||
|
expect(viewElement.getBoundingClientRect().x).toBe(0);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
// $FlowFixMe[incompatible-use]
|
||||||
|
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0]
|
||||||
|
.translateX,
|
||||||
|
).toBeCloseTo(35, 0.001);
|
||||||
|
|
||||||
|
Fantom.unstable_produceFramesForDuration(500);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
// $FlowFixMe[incompatible-use]
|
||||||
|
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0]
|
||||||
|
.translateX,
|
||||||
|
).toBeCloseTo(60, 0.001);
|
||||||
|
|
||||||
|
if (ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()) {
|
||||||
|
expect(root.getRenderedOutput({props: ['transform']}).toJSX()).toEqual(
|
||||||
|
<rn-view transform='[{"translateX": 60.000000}]' />,
|
||||||
|
);
|
||||||
|
// TODO(T223344928): this shouldn't be neccessary
|
||||||
|
Fantom.runWorkLoop();
|
||||||
|
} else {
|
||||||
|
expect(root.getRenderedOutput({props: ['transform']}).toJSX()).toEqual(
|
||||||
|
<rn-view transform="[]" />,
|
||||||
|
);
|
||||||
|
Fantom.runWorkLoop(); // Animated still schedules a React state update for synchronisation to shadow tree
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(root.getRenderedOutput({props: ['transform']}).toJSX()).toEqual(
|
||||||
|
<rn-view transform='[{"translateX": 60.000000}]' />, // // must include offset.
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(finishValue?.finished).toBe(true);
|
||||||
|
expect(finishValue?.value).toBe(50); // must not include offset.
|
||||||
|
expect(finishValue?.offset).toBe(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Value.flattenOffset', () => {
|
||||||
|
it('accumulates offset with onScroll value', () => {
|
||||||
|
const scrollViewRef = createRef<HostInstance>();
|
||||||
|
const viewRef = createRef<HostInstance>();
|
||||||
|
let _onScroll;
|
||||||
|
|
||||||
|
function PressableWithNativeDriver() {
|
||||||
|
_onScroll = useAnimatedValue(0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{flex: 1}}>
|
||||||
|
<Animated.View
|
||||||
|
ref={viewRef}
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
transform: [{translateY: _onScroll}],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Animated.ScrollView
|
||||||
|
ref={scrollViewRef}
|
||||||
|
onScroll={Animated.event(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
nativeEvent: {
|
||||||
|
contentOffset: {
|
||||||
|
y: _onScroll,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{useNativeDriver: true},
|
||||||
|
)}>
|
||||||
|
<View style={{height: 1000, width: 100}} />
|
||||||
|
</Animated.ScrollView>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = Fantom.createRoot();
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
root.render(<PressableWithNativeDriver />);
|
||||||
|
});
|
||||||
|
|
||||||
|
const fn = jest.fn();
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
_onScroll.addListener(fn);
|
||||||
|
});
|
||||||
|
|
||||||
|
const scrollViewelement = ensureInstance(
|
||||||
|
scrollViewRef.current,
|
||||||
|
ReactNativeElement,
|
||||||
|
);
|
||||||
|
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
|
||||||
|
|
||||||
|
Fantom.scrollTo(scrollViewelement, {
|
||||||
|
x: 0,
|
||||||
|
y: 10,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(fn).toBeCalledWith({value: 10});
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
_onScroll.setOffset(15);
|
||||||
|
_onScroll.flattenOffset();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(fn).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
_onScroll.setOffset(15);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(fn).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
let transform =
|
||||||
|
// $FlowFixMe[incompatible-use]
|
||||||
|
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0];
|
||||||
|
|
||||||
|
expect(transform.translateY).toBeCloseTo(40, 0.001);
|
||||||
|
|
||||||
|
// TODO(T223344928): this shouldn't be neccessary with cxxNativeAnimatedRemoveJsSync:true
|
||||||
|
Fantom.runWorkLoop();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Value.extractOffset', () => {
|
||||||
|
it('sets the offset value to the base value and resets the base value to zero', () => {
|
||||||
|
const scrollViewRef = createRef<HostInstance>();
|
||||||
|
const viewRef = createRef<HostInstance>();
|
||||||
|
let _onScroll;
|
||||||
|
|
||||||
|
function PressableWithNativeDriver() {
|
||||||
|
_onScroll = useAnimatedValue(0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{flex: 1}}>
|
||||||
|
<Animated.View
|
||||||
|
ref={viewRef}
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
transform: [{translateY: _onScroll}],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Animated.ScrollView
|
||||||
|
ref={scrollViewRef}
|
||||||
|
onScroll={Animated.event(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
nativeEvent: {
|
||||||
|
contentOffset: {
|
||||||
|
y: _onScroll,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{useNativeDriver: true},
|
||||||
|
)}>
|
||||||
|
<View style={{height: 1000, width: 100}} />
|
||||||
|
</Animated.ScrollView>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = Fantom.createRoot();
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
root.render(<PressableWithNativeDriver />);
|
||||||
|
});
|
||||||
|
|
||||||
|
const fn = jest.fn();
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
_onScroll.addListener(fn);
|
||||||
|
});
|
||||||
|
|
||||||
|
const scrollViewelement = ensureInstance(
|
||||||
|
scrollViewRef.current,
|
||||||
|
ReactNativeElement,
|
||||||
|
);
|
||||||
|
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
|
||||||
|
|
||||||
|
Fantom.scrollTo(scrollViewelement, {
|
||||||
|
x: 0,
|
||||||
|
y: 10,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(fn).toBeCalledWith({value: 10});
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
_onScroll.setOffset(15);
|
||||||
|
// Sets offset to be 15 + 10 = 25 (this is not observable from JS).
|
||||||
|
_onScroll.extractOffset();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(fn).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
let transform =
|
||||||
|
// $FlowFixMe[incompatible-use]
|
||||||
|
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0];
|
||||||
|
|
||||||
|
// Animated value is now 0 but offset is 25. The final value is 25.
|
||||||
|
expect(transform.translateY).toBeCloseTo(25, 0.001);
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
// Sets offset 35, overriding the previous `setOffset`.
|
||||||
|
// Due to `extractOffset`, base value was restarted to 0.
|
||||||
|
_onScroll.setOffset(35);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(fn).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
transform =
|
||||||
|
// $FlowFixMe[incompatible-use]
|
||||||
|
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0];
|
||||||
|
|
||||||
|
// `extractOffset` resets value back to 0.
|
||||||
|
// Previously we set offset to 35. The final value is 35.
|
||||||
|
expect(transform.translateY).toBeCloseTo(35, 0.001);
|
||||||
|
|
||||||
|
// TODO(T223344928): this shouldn't be neccessary with cxxNativeAnimatedRemoveJsSync:true
|
||||||
|
Fantom.runWorkLoop();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('animate layout props', () => {
|
||||||
|
const viewRef = createRef<HostInstance>();
|
||||||
|
allowStyleProp('height');
|
||||||
|
|
||||||
|
let _animatedHeight;
|
||||||
|
let _heightAnimation;
|
||||||
|
|
||||||
|
function MyApp() {
|
||||||
|
const animatedHeight = useAnimatedValue(0);
|
||||||
|
_animatedHeight = animatedHeight;
|
||||||
|
return (
|
||||||
|
<Animated.View
|
||||||
|
ref={viewRef}
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
height: animatedHeight,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = Fantom.createRoot();
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
root.render(<MyApp />);
|
||||||
|
});
|
||||||
|
|
||||||
|
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
_heightAnimation = Animated.timing(_animatedHeight, {
|
||||||
|
toValue: 100,
|
||||||
|
duration: 10,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
|
});
|
||||||
|
|
||||||
|
Fantom.unstable_produceFramesForDuration(10);
|
||||||
|
|
||||||
|
// TODO: this shouldn't be neccessary since animation should be stopped after duration
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
_heightAnimation?.stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
// $FlowFixMe[incompatible-use]
|
||||||
|
expect(Fantom.unstable_getDirectManipulationProps(viewElement).height).toBe(
|
||||||
|
100,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(Fantom.unstable_getFabricUpdateProps(viewElement).height).toBe(100);
|
||||||
|
|
||||||
|
expect(root.getRenderedOutput({props: ['height']}).toJSX()).toEqual(
|
||||||
|
<rn-view height="100.000000" />,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import type AnimatedNode from '../nodes/AnimatedNode';
|
|||||||
import type AnimatedValue from '../nodes/AnimatedValue';
|
import type AnimatedValue from '../nodes/AnimatedValue';
|
||||||
|
|
||||||
import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper';
|
import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper';
|
||||||
|
import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
|
||||||
import AnimatedProps from '../nodes/AnimatedProps';
|
import AnimatedProps from '../nodes/AnimatedProps';
|
||||||
|
|
||||||
export type EndResult = {
|
export type EndResult = {
|
||||||
@@ -149,8 +150,15 @@ export default class Animation {
|
|||||||
if (value != null) {
|
if (value != null) {
|
||||||
animatedValue.__onAnimatedValueUpdateReceived(value, offset);
|
animatedValue.__onAnimatedValueUpdateReceived(value, offset);
|
||||||
|
|
||||||
if (this.__isLooping === true) {
|
if (
|
||||||
return;
|
!(
|
||||||
|
ReactNativeFeatureFlags.cxxNativeAnimatedEnabled() &&
|
||||||
|
ReactNativeFeatureFlags.cxxNativeAnimatedRemoveJsSync()
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (this.__isLooping === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once the JS side node is synced with the updated values, trigger an
|
// Once the JS side node is synced with the updated values, trigger an
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ import type {
|
|||||||
} from '../createAnimatedComponent';
|
} from '../createAnimatedComponent';
|
||||||
|
|
||||||
import RefreshControl from '../../Components/RefreshControl/RefreshControl';
|
import RefreshControl from '../../Components/RefreshControl/RefreshControl';
|
||||||
import ScrollView from '../../Components/ScrollView/ScrollView';
|
import ScrollView, {
|
||||||
|
type ScrollViewProps,
|
||||||
|
} from '../../Components/ScrollView/ScrollView';
|
||||||
import flattenStyle from '../../StyleSheet/flattenStyle';
|
import flattenStyle from '../../StyleSheet/flattenStyle';
|
||||||
import splitLayoutProps from '../../StyleSheet/splitLayoutProps';
|
import splitLayoutProps from '../../StyleSheet/splitLayoutProps';
|
||||||
import StyleSheet from '../../StyleSheet/StyleSheet';
|
import StyleSheet from '../../StyleSheet/StyleSheet';
|
||||||
@@ -26,21 +28,20 @@ import useAnimatedProps from '../useAnimatedProps';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {cloneElement, useMemo} from 'react';
|
import {cloneElement, useMemo} from 'react';
|
||||||
|
|
||||||
type AnimatedScrollViewProps = React.ElementConfig<typeof ScrollView>;
|
|
||||||
type AnimatedScrollViewInstance = React.ElementRef<typeof ScrollView>;
|
type AnimatedScrollViewInstance = React.ElementRef<typeof ScrollView>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://github.com/facebook/react-native/commit/b8c8562
|
* @see https://github.com/facebook/react-native/commit/b8c8562
|
||||||
*/
|
*/
|
||||||
const AnimatedScrollView: AnimatedComponentType<
|
const AnimatedScrollView: AnimatedComponentType<
|
||||||
AnimatedScrollViewProps,
|
ScrollViewProps,
|
||||||
AnimatedScrollViewInstance,
|
AnimatedScrollViewInstance,
|
||||||
> = function AnimatedScrollViewWithOrWithoutInvertedRefreshControl({
|
> = function AnimatedScrollViewWithOrWithoutInvertedRefreshControl({
|
||||||
ref: forwardedRef,
|
ref: forwardedRef,
|
||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
ref?: React.RefSetter<AnimatedScrollViewInstance>,
|
ref?: React.RefSetter<AnimatedScrollViewInstance>,
|
||||||
...AnimatedProps<AnimatedScrollViewProps>,
|
...AnimatedProps<ScrollViewProps>,
|
||||||
}) {
|
}) {
|
||||||
// (Android only) When a ScrollView has a RefreshControl and
|
// (Android only) When a ScrollView has a RefreshControl and
|
||||||
// any `style` property set with an Animated.Value, the CSS
|
// any `style` property set with an Animated.Value, the CSS
|
||||||
@@ -111,7 +112,7 @@ const AnimatedScrollViewWithInvertedRefreshControl =
|
|||||||
|
|
||||||
// Handle animated props on `NativeDirectionalScrollView`.
|
// Handle animated props on `NativeDirectionalScrollView`.
|
||||||
const [scrollViewAnimatedProps, scrollViewRef] = useAnimatedProps<
|
const [scrollViewAnimatedProps, scrollViewRef] = useAnimatedProps<
|
||||||
AnimatedScrollViewProps,
|
ScrollViewProps,
|
||||||
AnimatedScrollViewInstance,
|
AnimatedScrollViewInstance,
|
||||||
>(intermediatePropsForScrollView);
|
>(intermediatePropsForScrollView);
|
||||||
const ref = useMergeRefs<AnimatedScrollViewInstance>(
|
const ref = useMergeRefs<AnimatedScrollViewInstance>(
|
||||||
|
|||||||
@@ -10,13 +10,10 @@
|
|||||||
|
|
||||||
import type {AnimatedComponentType} from '../createAnimatedComponent';
|
import type {AnimatedComponentType} from '../createAnimatedComponent';
|
||||||
|
|
||||||
import Text from '../../Text/Text';
|
import Text, {type TextProps} from '../../Text/Text';
|
||||||
import createAnimatedComponent from '../createAnimatedComponent';
|
import createAnimatedComponent from '../createAnimatedComponent';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
export default (createAnimatedComponent(
|
export default (createAnimatedComponent(
|
||||||
(Text: $FlowFixMe),
|
(Text: $FlowFixMe),
|
||||||
): AnimatedComponentType<
|
): AnimatedComponentType<TextProps, React.ElementRef<typeof Text>>);
|
||||||
React.ElementConfig<typeof Text>,
|
|
||||||
React.ElementRef<typeof Text>,
|
|
||||||
>);
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type {ViewProps} from '../../Components/View/ViewPropTypes';
|
||||||
import type {AnimatedComponentType} from '../createAnimatedComponent';
|
import type {AnimatedComponentType} from '../createAnimatedComponent';
|
||||||
|
|
||||||
import View from '../../Components/View/View';
|
import View from '../../Components/View/View';
|
||||||
@@ -15,6 +16,6 @@ import createAnimatedComponent from '../createAnimatedComponent';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
export default (createAnimatedComponent(View): AnimatedComponentType<
|
export default (createAnimatedComponent(View): AnimatedComponentType<
|
||||||
React.ElementConfig<typeof View>,
|
ViewProps,
|
||||||
React.ElementRef<typeof View>,
|
React.ElementRef<typeof View>,
|
||||||
>);
|
>);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import type AnimatedValue from './nodes/AnimatedValue';
|
|||||||
|
|
||||||
import createAnimatedPropsHook from '../../src/private/animated/createAnimatedPropsHook';
|
import createAnimatedPropsHook from '../../src/private/animated/createAnimatedPropsHook';
|
||||||
import composeStyles from '../../src/private/styles/composeStyles';
|
import composeStyles from '../../src/private/styles/composeStyles';
|
||||||
import View from '../Components/View/View';
|
import {type ViewProps} from '../Components/View/ViewPropTypes';
|
||||||
import useMergeRefs from '../Utilities/useMergeRefs';
|
import useMergeRefs from '../Utilities/useMergeRefs';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {useMemo} from 'react';
|
import {useMemo} from 'react';
|
||||||
@@ -60,9 +60,7 @@ type NonAnimatedProps =
|
|||||||
| 'disabled'
|
| 'disabled'
|
||||||
| 'accessibilityLabel';
|
| 'accessibilityLabel';
|
||||||
type PassThroughProps = $ReadOnly<{
|
type PassThroughProps = $ReadOnly<{
|
||||||
passthroughAnimatedPropExplicitValues?: React.ElementConfig<
|
passthroughAnimatedPropExplicitValues?: ViewProps | null,
|
||||||
typeof View,
|
|
||||||
> | null,
|
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export type AnimatedProps<Props: {...}> = {
|
export type AnimatedProps<Props: {...}> = {
|
||||||
|
|||||||
@@ -14,12 +14,8 @@
|
|||||||
#import <memory>
|
#import <memory>
|
||||||
|
|
||||||
#if USE_THIRD_PARTY_JSC != 1
|
#if USE_THIRD_PARTY_JSC != 1
|
||||||
#if __has_include(<jsireact/HermesExecutorFactory.h>)
|
|
||||||
#import <jsireact/HermesExecutorFactory.h>
|
|
||||||
#elif __has_include(<reacthermes/HermesExecutorFactory.h>)
|
|
||||||
#import <reacthermes/HermesExecutorFactory.h>
|
#import <reacthermes/HermesExecutorFactory.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#import <ReactCommon/RCTTurboModuleManager.h>
|
#import <ReactCommon/RCTTurboModuleManager.h>
|
||||||
#import <jsireact/JSIExecutor.h>
|
#import <jsireact/JSIExecutor.h>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ Pod::Spec.new do |s|
|
|||||||
s.author = "Meta Platforms, Inc. and its affiliates"
|
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "**/*.{c,h,m,mm,S,cpp}"
|
s.source_files = podspec_sources("**/*.{c,h,m,mm,S,cpp}", "**/*.h")
|
||||||
|
|
||||||
# This guard prevent to install the dependencies when we run `pod install` in the old architecture.
|
# This guard prevent to install the dependencies when we run `pod install` in the old architecture.
|
||||||
s.compiler_flags = other_cflags
|
s.compiler_flags = other_cflags
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Pod::Spec.new do |s|
|
|||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.compiler_flags = '-Wno-nullability-completeness'
|
s.compiler_flags = '-Wno-nullability-completeness'
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "*.{h,m,mm}"
|
s.source_files = podspec_sources("*.{h,m,mm}", "**/*.h")
|
||||||
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
||||||
s.header_dir = "RCTBlob"
|
s.header_dir = "RCTBlob"
|
||||||
s.pod_target_xcconfig = {
|
s.pod_target_xcconfig = {
|
||||||
|
|||||||
+7
-4
@@ -63,6 +63,7 @@ export type ButtonProps = $ReadOnly<{
|
|||||||
@platform tv
|
@platform tv
|
||||||
|
|
||||||
@default false
|
@default false
|
||||||
|
@deprecated Use `focusable` instead
|
||||||
*/
|
*/
|
||||||
hasTVPreferredFocus?: ?boolean,
|
hasTVPreferredFocus?: ?boolean,
|
||||||
|
|
||||||
@@ -280,10 +281,12 @@ export type ButtonProps = $ReadOnly<{
|
|||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const Touchable: typeof TouchableNativeFeedback | typeof TouchableOpacity =
|
const NativeTouchable:
|
||||||
|
| typeof TouchableNativeFeedback
|
||||||
|
| typeof TouchableOpacity =
|
||||||
Platform.OS === 'android' ? TouchableNativeFeedback : TouchableOpacity;
|
Platform.OS === 'android' ? TouchableNativeFeedback : TouchableOpacity;
|
||||||
|
|
||||||
type ButtonRef = React.ElementRef<typeof Touchable>;
|
type ButtonRef = React.ElementRef<typeof NativeTouchable>;
|
||||||
|
|
||||||
const Button: component(
|
const Button: component(
|
||||||
ref?: React.RefSetter<ButtonRef>,
|
ref?: React.RefSetter<ButtonRef>,
|
||||||
@@ -361,7 +364,7 @@ const Button: component(
|
|||||||
: importantForAccessibility;
|
: importantForAccessibility;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Touchable
|
<NativeTouchable
|
||||||
accessible={accessible}
|
accessible={accessible}
|
||||||
accessibilityActions={accessibilityActions}
|
accessibilityActions={accessibilityActions}
|
||||||
onAccessibilityAction={onAccessibilityAction}
|
onAccessibilityAction={onAccessibilityAction}
|
||||||
@@ -390,7 +393,7 @@ const Button: component(
|
|||||||
{formattedTitle}
|
{formattedTitle}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</Touchable>
|
</NativeTouchable>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
|
||||||
import type {
|
import type {
|
||||||
GestureResponderEvent,
|
GestureResponderEvent,
|
||||||
LayoutChangeEvent,
|
LayoutChangeEvent,
|
||||||
@@ -26,8 +27,6 @@ import useAndroidRippleForView, {
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {memo, useMemo, useRef, useState} from 'react';
|
import {memo, useMemo, useRef, useState} from 'react';
|
||||||
|
|
||||||
type ViewStyleProp = React.ElementConfig<typeof View>['style'];
|
|
||||||
|
|
||||||
export type {PressableAndroidRippleConfig};
|
export type {PressableAndroidRippleConfig};
|
||||||
|
|
||||||
export type PressableStateCallbackType = $ReadOnly<{
|
export type PressableStateCallbackType = $ReadOnly<{
|
||||||
|
|||||||
@@ -13,12 +13,21 @@ import {NativeMethods} from '../../../types/public/ReactNativeTypes';
|
|||||||
import {ViewProps} from '../View/ViewPropTypes';
|
import {ViewProps} from '../View/ViewPropTypes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Use `react-native-safe-area-context` instead. This component is deprecated and will be removed in a future release.
|
||||||
|
*
|
||||||
* Renders nested content and automatically applies paddings reflect the portion of the view
|
* Renders nested content and automatically applies paddings reflect the portion of the view
|
||||||
* that is not covered by navigation bars, tab bars, toolbars, and other ancestor views.
|
* that is not covered by navigation bars, tab bars, toolbars, and other ancestor views.
|
||||||
* Moreover, and most importantly, Safe Area's paddings reflect physical limitation of the screen,
|
* Moreover, and most importantly, Safe Area's paddings reflect physical limitation of the screen,
|
||||||
* such as rounded corners or camera notches (aka sensor housing area on iPhone X).
|
* such as rounded corners or camera notches (aka sensor housing area on iPhone X).
|
||||||
*/
|
*/
|
||||||
declare class SafeAreaViewComponent extends React.Component<ViewProps> {}
|
declare class SafeAreaViewComponent extends React.Component<ViewProps> {}
|
||||||
|
|
||||||
declare const SafeAreaViewBase: Constructor<NativeMethods> &
|
declare const SafeAreaViewBase: Constructor<NativeMethods> &
|
||||||
typeof SafeAreaViewComponent;
|
typeof SafeAreaViewComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Use `react-native-safe-area-context` instead. This component is deprecated and will be removed in a future release.
|
||||||
|
*/
|
||||||
export class SafeAreaView extends SafeAreaViewBase {}
|
export class SafeAreaView extends SafeAreaViewBase {}
|
||||||
|
|||||||
@@ -22,8 +22,9 @@ import * as React from 'react';
|
|||||||
* Moreover, and most importantly, Safe Area's paddings reflect physical
|
* Moreover, and most importantly, Safe Area's paddings reflect physical
|
||||||
* limitation of the screen, such as rounded corners or camera notches (aka
|
* limitation of the screen, such as rounded corners or camera notches (aka
|
||||||
* sensor housing area on iPhone X).
|
* sensor housing area on iPhone X).
|
||||||
|
* @deprecated Use `react-native-safe-area-context` instead. This component will be removed in a future release.
|
||||||
*/
|
*/
|
||||||
const exported: component(
|
const SafeAreaView: component(
|
||||||
ref?: React.RefSetter<React.ElementRef<typeof View>>,
|
ref?: React.RefSetter<React.ElementRef<typeof View>>,
|
||||||
...props: ViewProps
|
...props: ViewProps
|
||||||
) = Platform.select({
|
) = Platform.select({
|
||||||
@@ -31,4 +32,4 @@ const exported: component(
|
|||||||
default: View,
|
default: View,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default exported;
|
export default SafeAreaView;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
import type * as React from 'react';
|
import type * as React from 'react';
|
||||||
import {Constructor} from '../../../types/private/Utilities';
|
import {Constructor} from '../../../types/private/Utilities';
|
||||||
import {Insets} from '../../../types/public/Insets';
|
import {Insets} from '../../../types/public/Insets';
|
||||||
|
import {HostInstance} from '../../../types/public/ReactNativeTypes';
|
||||||
import {ColorValue, StyleProp} from '../../StyleSheet/StyleSheet';
|
import {ColorValue, StyleProp} from '../../StyleSheet/StyleSheet';
|
||||||
import {ViewStyle} from '../../StyleSheet/StyleSheetTypes';
|
import {ViewStyle} from '../../StyleSheet/StyleSheetTypes';
|
||||||
import {
|
import {
|
||||||
@@ -878,6 +879,12 @@ export class ScrollView extends ScrollViewBase {
|
|||||||
// Undocumented
|
// Undocumented
|
||||||
getInnerViewNode(): any;
|
getInnerViewNode(): any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reference to the underlying native scroll view, or null if the
|
||||||
|
* native instance is not mounted.
|
||||||
|
*/
|
||||||
|
getNativeScrollRef: () => HostInstance | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use scrollTo instead
|
* @deprecated Use scrollTo instead
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1480,6 +1480,7 @@ class ScrollView extends React.Component<ScrollViewProps, ScrollViewState> {
|
|||||||
// then the second tap goes to the actual interior view)
|
// then the second tap goes to the actual interior view)
|
||||||
const {keyboardShouldPersistTaps} = this.props;
|
const {keyboardShouldPersistTaps} = this.props;
|
||||||
const keyboardNeverPersistTaps =
|
const keyboardNeverPersistTaps =
|
||||||
|
// $FlowFixMe[sketchy-null-bool]
|
||||||
!keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never';
|
!keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never';
|
||||||
|
|
||||||
if (typeof e.target === 'number') {
|
if (typeof e.target === 'number') {
|
||||||
@@ -1562,6 +1563,7 @@ class ScrollView extends React.Component<ScrollViewProps, ScrollViewState> {
|
|||||||
|
|
||||||
const {keyboardShouldPersistTaps} = this.props;
|
const {keyboardShouldPersistTaps} = this.props;
|
||||||
const keyboardNeverPersistsTaps =
|
const keyboardNeverPersistsTaps =
|
||||||
|
// $FlowFixMe[sketchy-null-bool]
|
||||||
!keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never';
|
!keyboardShouldPersistTaps || keyboardShouldPersistTaps === 'never';
|
||||||
|
|
||||||
// Dismiss the keyboard now if we didn't become responder in capture phase
|
// Dismiss the keyboard now if we didn't become responder in capture phase
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ export interface StatusBarPropsAndroid {
|
|||||||
/**
|
/**
|
||||||
* The background color of the status bar.
|
* The background color of the status bar.
|
||||||
*
|
*
|
||||||
|
* Please note that this prop has no effect on Android 15+
|
||||||
|
*
|
||||||
* @platform android
|
* @platform android
|
||||||
*/
|
*/
|
||||||
backgroundColor?: ColorValue | undefined;
|
backgroundColor?: ColorValue | undefined;
|
||||||
@@ -44,6 +46,8 @@ export interface StatusBarPropsAndroid {
|
|||||||
* the app will draw under the status bar. This is useful when using a
|
* the app will draw under the status bar. This is useful when using a
|
||||||
* semi transparent status bar color.
|
* semi transparent status bar color.
|
||||||
*
|
*
|
||||||
|
* Please note that this prop has no effect on Android 15+
|
||||||
|
*
|
||||||
* @platform android
|
* @platform android
|
||||||
*/
|
*/
|
||||||
translucent?: boolean | undefined;
|
translucent?: boolean | undefined;
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ export type StatusBarAnimation = $Keys<{
|
|||||||
export type StatusBarPropsAndroid = $ReadOnly<{
|
export type StatusBarPropsAndroid = $ReadOnly<{
|
||||||
/**
|
/**
|
||||||
* The background color of the status bar.
|
* The background color of the status bar.
|
||||||
|
*
|
||||||
|
* Please note that this prop has no effect on Android 15+
|
||||||
|
*
|
||||||
* @platform android
|
* @platform android
|
||||||
*/
|
*/
|
||||||
backgroundColor?: ?ColorValue,
|
backgroundColor?: ?ColorValue,
|
||||||
@@ -66,6 +69,8 @@ export type StatusBarPropsAndroid = $ReadOnly<{
|
|||||||
* When translucent is set to true, the app will draw under the status bar.
|
* When translucent is set to true, the app will draw under the status bar.
|
||||||
* This is useful when using a semi transparent status bar color.
|
* This is useful when using a semi transparent status bar color.
|
||||||
*
|
*
|
||||||
|
* Please note that this prop has no effect on Android 15+
|
||||||
|
*
|
||||||
* @platform android
|
* @platform android
|
||||||
*/
|
*/
|
||||||
translucent?: ?boolean,
|
translucent?: ?boolean,
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ type AndroidProps = $ReadOnly<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
type IOSProps = $ReadOnly<{
|
type IOSProps = $ReadOnly<{
|
||||||
|
/**
|
||||||
|
* @deprecated Use `focusable` instead
|
||||||
|
*/
|
||||||
hasTVPreferredFocus?: ?boolean,
|
hasTVPreferredFocus?: ?boolean,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|||||||
+1
@@ -29,6 +29,7 @@ type TVProps = {
|
|||||||
* *(Apple TV only)* TV preferred focus (see documentation for the View component).
|
* *(Apple TV only)* TV preferred focus (see documentation for the View component).
|
||||||
*
|
*
|
||||||
* @platform ios
|
* @platform ios
|
||||||
|
* @deprecated Use `focusable` instead
|
||||||
*/
|
*/
|
||||||
hasTVPreferredFocus?: ?boolean,
|
hasTVPreferredFocus?: ?boolean,
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export interface TVProps {
|
|||||||
* *(Apple TV only)* TV preferred focus (see documentation for the View component).
|
* *(Apple TV only)* TV preferred focus (see documentation for the View component).
|
||||||
*
|
*
|
||||||
* @platform ios
|
* @platform ios
|
||||||
|
* @deprecated Use `focusable` instead
|
||||||
*/
|
*/
|
||||||
hasTVPreferredFocus?: boolean | undefined;
|
hasTVPreferredFocus?: boolean | undefined;
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export type TVProps = $ReadOnly<{
|
|||||||
* *(Apple TV only)* TV preferred focus (see documentation for the View component).
|
* *(Apple TV only)* TV preferred focus (see documentation for the View component).
|
||||||
*
|
*
|
||||||
* @platform ios
|
* @platform ios
|
||||||
|
* @deprecated Use `focusable` instead
|
||||||
*/
|
*/
|
||||||
hasTVPreferredFocus?: ?boolean,
|
hasTVPreferredFocus?: ?boolean,
|
||||||
|
|
||||||
|
|||||||
+12
-13
@@ -16,11 +16,6 @@ import ViewNativeComponent from './ViewNativeComponent';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {use} from 'react';
|
import {use} from 'react';
|
||||||
|
|
||||||
type PropsWithRef = $ReadOnly<{
|
|
||||||
ref?: React.RefSetter<React.ElementRef<typeof ViewNativeComponent>>,
|
|
||||||
...ViewProps,
|
|
||||||
}>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The most fundamental component for building a UI, View is a container that
|
* The most fundamental component for building a UI, View is a container that
|
||||||
* supports layout with flexbox, style, some touch handling, and accessibility
|
* supports layout with flexbox, style, some touch handling, and accessibility
|
||||||
@@ -28,7 +23,10 @@ type PropsWithRef = $ReadOnly<{
|
|||||||
*
|
*
|
||||||
* @see https://reactnative.dev/docs/view
|
* @see https://reactnative.dev/docs/view
|
||||||
*/
|
*/
|
||||||
function View(props: PropsWithRef): React.Node {
|
export default component View(
|
||||||
|
ref?: React.RefSetter<React.ElementRef<typeof ViewNativeComponent>>,
|
||||||
|
...props: ViewProps
|
||||||
|
) {
|
||||||
const hasTextAncestor = use(TextAncestor);
|
const hasTextAncestor = use(TextAncestor);
|
||||||
|
|
||||||
let actualView;
|
let actualView;
|
||||||
@@ -55,7 +53,7 @@ function View(props: PropsWithRef): React.Node {
|
|||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
// Since we destructured props, we can now treat it as mutable
|
// Since we destructured props, we can now treat it as mutable
|
||||||
const processedProps = otherProps as {...PropsWithRef};
|
const processedProps = otherProps as {...ViewProps};
|
||||||
|
|
||||||
const parsedAriaLabelledBy = ariaLabelledBy?.split(/\s*,\s*/g);
|
const parsedAriaLabelledBy = ariaLabelledBy?.split(/\s*,\s*/g);
|
||||||
if (parsedAriaLabelledBy !== undefined) {
|
if (parsedAriaLabelledBy !== undefined) {
|
||||||
@@ -118,7 +116,12 @@ function View(props: PropsWithRef): React.Node {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
actualView = <ViewNativeComponent {...processedProps} />;
|
actualView =
|
||||||
|
ref == null ? (
|
||||||
|
<ViewNativeComponent {...processedProps} />
|
||||||
|
) : (
|
||||||
|
<ViewNativeComponent {...processedProps} ref={ref} />
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
const {
|
const {
|
||||||
accessibilityElementsHidden,
|
accessibilityElementsHidden,
|
||||||
@@ -198,6 +201,7 @@ function View(props: PropsWithRef): React.Node {
|
|||||||
: importantForAccessibility
|
: importantForAccessibility
|
||||||
}
|
}
|
||||||
nativeID={id ?? nativeID}
|
nativeID={id ?? nativeID}
|
||||||
|
ref={ref}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -207,8 +211,3 @@ function View(props: PropsWithRef): React.Node {
|
|||||||
}
|
}
|
||||||
return actualView;
|
return actualView;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default View as component(
|
|
||||||
ref?: React.RefSetter<React.ElementRef<typeof ViewNativeComponent>>,
|
|
||||||
...props: ViewProps
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -374,13 +374,6 @@ export type AccessibilityProps = $ReadOnly<{
|
|||||||
*/
|
*/
|
||||||
'aria-label'?: ?Stringish,
|
'aria-label'?: ?Stringish,
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the order in which descendant elements receive accessibility focus.
|
|
||||||
* The elements in the array represent nativeID values for the respective
|
|
||||||
* descendant elements.
|
|
||||||
*/
|
|
||||||
experimental_accessibilityOrder?: ?Array<string>,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates to accessibility services to treat UI component like a specific role.
|
* Indicates to accessibility services to treat UI component like a specific role.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ import {
|
|||||||
import {Touchable} from '../Touchable/Touchable';
|
import {Touchable} from '../Touchable/Touchable';
|
||||||
import {AccessibilityProps} from './ViewAccessibility';
|
import {AccessibilityProps} from './ViewAccessibility';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated These properties are not implemented natively.
|
||||||
|
*/
|
||||||
export interface TVViewPropsIOS {
|
export interface TVViewPropsIOS {
|
||||||
/**
|
/**
|
||||||
* *(Apple TV only)* When set to true, this view will be focusable
|
* *(Apple TV only)* When set to true, this view will be focusable
|
||||||
@@ -34,6 +37,7 @@ export interface TVViewPropsIOS {
|
|||||||
* *(Apple TV only)* May be set to true to force the Apple TV focus engine to move focus to this view.
|
* *(Apple TV only)* May be set to true to force the Apple TV focus engine to move focus to this view.
|
||||||
*
|
*
|
||||||
* @platform ios
|
* @platform ios
|
||||||
|
* @deprecated Use `focusable` instead
|
||||||
*/
|
*/
|
||||||
hasTVPreferredFocus?: boolean | undefined;
|
hasTVPreferredFocus?: boolean | undefined;
|
||||||
|
|
||||||
|
|||||||
@@ -280,6 +280,7 @@ export type ViewPropsAndroid = $ReadOnly<{
|
|||||||
* Whether to force the Android TV focus engine to move focus to this view.
|
* Whether to force the Android TV focus engine to move focus to this view.
|
||||||
*
|
*
|
||||||
* @platform android
|
* @platform android
|
||||||
|
* @deprecated Use `focusable` instead
|
||||||
*/
|
*/
|
||||||
hasTVPreferredFocus?: ?boolean,
|
hasTVPreferredFocus?: ?boolean,
|
||||||
|
|
||||||
@@ -489,6 +490,13 @@ type ViewBaseProps = $ReadOnly<{
|
|||||||
* See https://reactnative.dev/docs/view#removeclippedsubviews
|
* See https://reactnative.dev/docs/view#removeclippedsubviews
|
||||||
*/
|
*/
|
||||||
removeClippedSubviews?: ?boolean,
|
removeClippedSubviews?: ?boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the order in which descendant elements receive accessibility focus.
|
||||||
|
* The elements in the array represent nativeID values for the respective
|
||||||
|
* descendant elements.
|
||||||
|
*/
|
||||||
|
experimental_accessibilityOrder?: ?Array<string>,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export type ViewProps = $ReadOnly<{
|
export type ViewProps = $ReadOnly<{
|
||||||
|
|||||||
@@ -169,6 +169,20 @@ describe('<View>', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('transform style', () => {
|
||||||
|
it('causes view to be unflattened', () => {
|
||||||
|
const root = Fantom.createRoot();
|
||||||
|
|
||||||
|
Fantom.runTask(() => {
|
||||||
|
root.render(<View style={{transform: [{translateX: 10}]}} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(root.getRenderedOutput({props: ['transform']}).toJSX()).toEqual(
|
||||||
|
<rn-view transform='[{"translateX": 10.000000}]' />,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('props', () => {
|
describe('props', () => {
|
||||||
describe('pointerEvents', () => {
|
describe('pointerEvents', () => {
|
||||||
it('auto does not propagate to the mounting layer, it is the default', () => {
|
it('auto does not propagate to the mounting layer, it is the default', () => {
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ describe('<Button>', () => {
|
|||||||
.toJSX(),
|
.toJSX(),
|
||||||
).toEqual(
|
).toEqual(
|
||||||
// Upper case on Android (also used by Fantom)
|
// Upper case on Android (also used by Fantom)
|
||||||
<rn-view backgroundColor="rgba(33, 150, 243, 255)">
|
<rn-view backgroundColor="rgba(33, 150, 243, 1)">
|
||||||
<rn-paragraph foregroundColor="rgba(255, 255, 255, 255)">
|
<rn-paragraph foregroundColor="rgba(255, 255, 255, 1)">
|
||||||
HELLO
|
HELLO
|
||||||
</rn-paragraph>
|
</rn-paragraph>
|
||||||
</rn-view>,
|
</rn-view>,
|
||||||
@@ -53,8 +53,8 @@ describe('<Button>', () => {
|
|||||||
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
|
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
|
||||||
.toJSX(),
|
.toJSX(),
|
||||||
).toEqual(
|
).toEqual(
|
||||||
<rn-view backgroundColor="rgba(0, 0, 255, 255)">
|
<rn-view backgroundColor="rgba(0, 0, 255, 1)">
|
||||||
<rn-paragraph foregroundColor="rgba(255, 255, 255, 255)">
|
<rn-paragraph foregroundColor="rgba(255, 255, 255, 1)">
|
||||||
HELLO
|
HELLO
|
||||||
</rn-paragraph>
|
</rn-paragraph>
|
||||||
</rn-view>,
|
</rn-view>,
|
||||||
@@ -99,8 +99,8 @@ describe('<Button>', () => {
|
|||||||
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
|
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
|
||||||
.toJSX(),
|
.toJSX(),
|
||||||
).toEqual(
|
).toEqual(
|
||||||
<rn-view backgroundColor="rgba(223, 223, 223, 255)">
|
<rn-view backgroundColor="rgba(223, 223, 223, 1)">
|
||||||
<rn-paragraph foregroundColor="rgba(161, 161, 161, 255)">
|
<rn-paragraph foregroundColor="rgba(161, 161, 161, 1)">
|
||||||
HELLO
|
HELLO
|
||||||
</rn-paragraph>
|
</rn-paragraph>
|
||||||
</rn-view>,
|
</rn-view>,
|
||||||
@@ -181,8 +181,8 @@ describe('<Button>', () => {
|
|||||||
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
|
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
|
||||||
.toJSX(),
|
.toJSX(),
|
||||||
).toEqual(
|
).toEqual(
|
||||||
<rn-view backgroundColor="rgba(33, 150, 243, 255)">
|
<rn-view backgroundColor="rgba(33, 150, 243, 1)">
|
||||||
<rn-paragraph foregroundColor="rgba(255, 255, 255, 255)">
|
<rn-paragraph foregroundColor="rgba(255, 255, 255, 1)">
|
||||||
HELLO
|
HELLO
|
||||||
</rn-paragraph>
|
</rn-paragraph>
|
||||||
</rn-view>,
|
</rn-view>,
|
||||||
@@ -223,8 +223,8 @@ describe('<Button>', () => {
|
|||||||
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
|
.getRenderedOutput({props: ['foregroundColor', 'backgroundColor']})
|
||||||
.toJSX(),
|
.toJSX(),
|
||||||
).toEqual(
|
).toEqual(
|
||||||
<rn-view backgroundColor="rgba(223, 223, 223, 255)">
|
<rn-view backgroundColor="rgba(223, 223, 223, 1)">
|
||||||
<rn-paragraph foregroundColor="rgba(161, 161, 161, 255)">
|
<rn-paragraph foregroundColor="rgba(161, 161, 161, 1)">
|
||||||
HELLO
|
HELLO
|
||||||
</rn-paragraph>
|
</rn-paragraph>
|
||||||
</rn-view>,
|
</rn-view>,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export type {EventSubscription, EmitterSubscription};
|
|||||||
export type NativeEventSubscription = EventSubscription;
|
export type NativeEventSubscription = EventSubscription;
|
||||||
|
|
||||||
// $FlowFixMe[unclear-type] unclear type of events
|
// $FlowFixMe[unclear-type] unclear type of events
|
||||||
type UnsafeObject = Object;
|
type UnsafeNativeEventObject = Object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `NativeEventEmitter` is intended for use by Native Modules to emit events to
|
* `NativeEventEmitter` is intended for use by Native Modules to emit events to
|
||||||
@@ -46,8 +46,8 @@ type UnsafeObject = Object;
|
|||||||
*/
|
*/
|
||||||
export default class NativeEventEmitter<
|
export default class NativeEventEmitter<
|
||||||
TEventToArgsMap: $ReadOnly<
|
TEventToArgsMap: $ReadOnly<
|
||||||
Record<string, $ReadOnlyArray<UnsafeObject>>,
|
Record<string, $ReadOnlyArray<UnsafeNativeEventObject>>,
|
||||||
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
|
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeNativeEventObject>>>,
|
||||||
> implements IEventEmitter<TEventToArgsMap>
|
> implements IEventEmitter<TEventToArgsMap>
|
||||||
{
|
{
|
||||||
_nativeModule: ?NativeModule;
|
_nativeModule: ?NativeModule;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Pod::Spec.new do |s|
|
|||||||
s.author = "Meta Platforms, Inc. and its affiliates"
|
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "**/*.{c,h,m,mm,cpp}"
|
s.source_files = podspec_sources("**/*.{c,h,m,mm,cpp}", "**/*.h")
|
||||||
s.header_dir = "FBLazyVector"
|
s.header_dir = "FBLazyVector"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,9 +8,10 @@
|
|||||||
#import <React/RCTImageLoaderLoggable.h>
|
#import <React/RCTImageLoaderLoggable.h>
|
||||||
#import <React/RCTImageLoaderProtocol.h>
|
#import <React/RCTImageLoaderProtocol.h>
|
||||||
#import <React/RCTImageURLLoader.h>
|
#import <React/RCTImageURLLoader.h>
|
||||||
|
|
||||||
// TODO (T61325135): Remove C++ checks
|
// TODO (T61325135): Remove C++ checks
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
#import <string>
|
||||||
|
|
||||||
namespace facebook::react {
|
namespace facebook::react {
|
||||||
|
|
||||||
struct ImageURLLoaderAttribution {
|
struct ImageURLLoaderAttribution {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#import <React/RCTImageUtils.h>
|
#import <React/RCTImageUtils.h>
|
||||||
|
|
||||||
#import <tgmath.h>
|
#import <cmath>
|
||||||
|
|
||||||
#import <ImageIO/ImageIO.h>
|
#import <ImageIO/ImageIO.h>
|
||||||
#import <MobileCoreServices/UTCoreTypes.h>
|
#import <MobileCoreServices/UTCoreTypes.h>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ Pod::Spec.new do |s|
|
|||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.compiler_flags = '-Wno-nullability-completeness'
|
s.compiler_flags = '-Wno-nullability-completeness'
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "*.{m,mm}"
|
s.source_files = podspec_sources("*.{m,mm}", "**/*.h")
|
||||||
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
||||||
s.header_dir = "RCTImage"
|
s.header_dir = "RCTImage"
|
||||||
s.pod_target_xcconfig = {
|
s.pod_target_xcconfig = {
|
||||||
|
|||||||
@@ -229,7 +229,8 @@ function _processUpdate() {
|
|||||||
*/
|
*/
|
||||||
const InteractionManager = (
|
const InteractionManager = (
|
||||||
ReactNativeFeatureFlags.disableInteractionManager()
|
ReactNativeFeatureFlags.disableInteractionManager()
|
||||||
? require('./InteractionManagerStub').default
|
? // $FlowFixMe[incompatible-variance]
|
||||||
|
require('./InteractionManagerStub').default
|
||||||
: InteractionManagerImpl
|
: InteractionManagerImpl
|
||||||
) as typeof InteractionManagerImpl;
|
) as typeof InteractionManagerImpl;
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ type OnAnimationDidFailCallback = () => void;
|
|||||||
let isLayoutAnimationEnabled: boolean =
|
let isLayoutAnimationEnabled: boolean =
|
||||||
ReactNativeFeatureFlags.isLayoutAnimationEnabled();
|
ReactNativeFeatureFlags.isLayoutAnimationEnabled();
|
||||||
|
|
||||||
function setEnabled(value: boolean) {
|
function setLayoutAnimationEnabled(value: boolean) {
|
||||||
isLayoutAnimationEnabled = isLayoutAnimationEnabled;
|
isLayoutAnimationEnabled = isLayoutAnimationEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ function configureNext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function create(
|
function createLayoutAnimation(
|
||||||
duration: number,
|
duration: number,
|
||||||
type?: LayoutAnimationType,
|
type?: LayoutAnimationType,
|
||||||
property?: LayoutAnimationProperty,
|
property?: LayoutAnimationProperty,
|
||||||
@@ -129,12 +129,16 @@ function create(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Presets = {
|
const Presets = {
|
||||||
easeInEaseOut: (create(
|
easeInEaseOut: (createLayoutAnimation(
|
||||||
300,
|
300,
|
||||||
'easeInEaseOut',
|
'easeInEaseOut',
|
||||||
'opacity',
|
'opacity',
|
||||||
): LayoutAnimationConfig),
|
): LayoutAnimationConfig),
|
||||||
linear: (create(500, 'linear', 'opacity'): LayoutAnimationConfig),
|
linear: (createLayoutAnimation(
|
||||||
|
500,
|
||||||
|
'linear',
|
||||||
|
'opacity',
|
||||||
|
): LayoutAnimationConfig),
|
||||||
spring: ({
|
spring: ({
|
||||||
duration: 700,
|
duration: 700,
|
||||||
create: {
|
create: {
|
||||||
@@ -180,7 +184,7 @@ const LayoutAnimation = {
|
|||||||
/**
|
/**
|
||||||
* Helper for creating a config for `configureNext`.
|
* Helper for creating a config for `configureNext`.
|
||||||
*/
|
*/
|
||||||
create,
|
create: createLayoutAnimation,
|
||||||
Types: Object.freeze({
|
Types: Object.freeze({
|
||||||
spring: 'spring',
|
spring: 'spring',
|
||||||
linear: 'linear',
|
linear: 'linear',
|
||||||
@@ -208,7 +212,7 @@ const LayoutAnimation = {
|
|||||||
spring: (configureNext.bind(null, Presets.spring): (
|
spring: (configureNext.bind(null, Presets.spring): (
|
||||||
onAnimationDidEnd?: OnAnimationDidEndCallback,
|
onAnimationDidEnd?: OnAnimationDidEndCallback,
|
||||||
) => void),
|
) => void),
|
||||||
setEnabled,
|
setEnabled: setLayoutAnimationEnabled,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LayoutAnimation;
|
export default LayoutAnimation;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Pod::Spec.new do |s|
|
|||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.compiler_flags = '-Wno-nullability-completeness'
|
s.compiler_flags = '-Wno-nullability-completeness'
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "*.{m,mm}"
|
s.source_files = podspec_sources("*.{m,mm}", "")
|
||||||
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
||||||
s.header_dir = "RCTLinking"
|
s.header_dir = "RCTLinking"
|
||||||
s.pod_target_xcconfig = {
|
s.pod_target_xcconfig = {
|
||||||
|
|||||||
+1
-2
@@ -15,6 +15,7 @@ import type {
|
|||||||
ListRenderItemInfo,
|
ListRenderItemInfo,
|
||||||
ViewabilityConfigCallbackPair,
|
ViewabilityConfigCallbackPair,
|
||||||
ViewToken,
|
ViewToken,
|
||||||
|
VirtualizedListProps,
|
||||||
} from '@react-native/virtualized-lists';
|
} from '@react-native/virtualized-lists';
|
||||||
|
|
||||||
import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
|
import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
|
||||||
@@ -181,8 +182,6 @@ type FlatListBaseProps<ItemT> = {
|
|||||||
...OptionalProps<ItemT>,
|
...OptionalProps<ItemT>,
|
||||||
};
|
};
|
||||||
|
|
||||||
type VirtualizedListProps = React.ElementConfig<typeof VirtualizedList>;
|
|
||||||
|
|
||||||
export type FlatListProps<ItemT> = {
|
export type FlatListProps<ItemT> = {
|
||||||
...Omit<
|
...Omit<
|
||||||
VirtualizedListProps,
|
VirtualizedListProps,
|
||||||
|
|||||||
+8
-2
@@ -35,9 +35,9 @@ export interface ModalBaseProps {
|
|||||||
*/
|
*/
|
||||||
visible?: boolean | undefined;
|
visible?: boolean | undefined;
|
||||||
/**
|
/**
|
||||||
* The `onRequestClose` callback is called when the user taps the hardware back button on Android or the menu button on Apple TV.
|
* The `onRequestClose` callback is called when the user taps the hardware back button on Android, dismisses the sheet using a gesture on iOS (when `allowSwipeDismissal` is set to true) or the menu button on Apple TV.
|
||||||
*
|
*
|
||||||
* This is required on Apple TV and Android.
|
* This is required on iOS and Android.
|
||||||
*/
|
*/
|
||||||
onRequestClose?: ((event: NativeSyntheticEvent<any>) => void) | undefined;
|
onRequestClose?: ((event: NativeSyntheticEvent<any>) => void) | undefined;
|
||||||
/**
|
/**
|
||||||
@@ -89,6 +89,12 @@ export interface ModalPropsIOS {
|
|||||||
onOrientationChange?:
|
onOrientationChange?:
|
||||||
| ((event: NativeSyntheticEvent<any>) => void)
|
| ((event: NativeSyntheticEvent<any>) => void)
|
||||||
| undefined;
|
| undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls whether the modal can be dismissed by swiping down on iOS.
|
||||||
|
* This requires you to implement the `onRequestClose` prop to handle the dismissal.
|
||||||
|
*/
|
||||||
|
allowSwipeDismissal?: boolean | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModalPropsAndroid {
|
export interface ModalPropsAndroid {
|
||||||
|
|||||||
+19
-2
@@ -86,9 +86,9 @@ export type ModalBaseProps = {
|
|||||||
*/
|
*/
|
||||||
visible?: ?boolean,
|
visible?: ?boolean,
|
||||||
/**
|
/**
|
||||||
* The `onRequestClose` callback is called when the user taps the hardware back button on Android or the menu button on Apple TV.
|
* The `onRequestClose` callback is called when the user taps the hardware back button on Android, dismisses the sheet using a gesture on iOS (when `allowSwipeDismissal` is set to true) or the menu button on Apple TV.
|
||||||
*
|
*
|
||||||
* This is required on Apple TV and Android.
|
* This is required on iOS and Android.
|
||||||
*/
|
*/
|
||||||
// onRequestClose?: (event: NativeSyntheticEvent<any>) => void;
|
// onRequestClose?: (event: NativeSyntheticEvent<any>) => void;
|
||||||
onRequestClose?: ?DirectEventHandler<null>,
|
onRequestClose?: ?DirectEventHandler<null>,
|
||||||
@@ -147,6 +147,12 @@ export type ModalPropsIOS = {
|
|||||||
// | ((event: NativeSyntheticEvent<any>) => void)
|
// | ((event: NativeSyntheticEvent<any>) => void)
|
||||||
// | undefined;
|
// | undefined;
|
||||||
onOrientationChange?: ?DirectEventHandler<OrientationChangeEvent>,
|
onOrientationChange?: ?DirectEventHandler<OrientationChangeEvent>,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls whether the modal can be dismissed by swiping down on iOS.
|
||||||
|
* This requires you to implement the `onRequestClose` prop to handle the dismissal.
|
||||||
|
*/
|
||||||
|
allowSwipeDismissal?: ?boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ModalPropsAndroid = {
|
export type ModalPropsAndroid = {
|
||||||
@@ -192,6 +198,16 @@ function confirmProps(props: ModalProps) {
|
|||||||
'Modal with translucent navigation bar and without translucent status bar is not supported.',
|
'Modal with translucent navigation bar and without translucent status bar is not supported.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
Platform.OS === 'ios' &&
|
||||||
|
props.allowSwipeDismissal === true &&
|
||||||
|
!props.onRequestClose
|
||||||
|
) {
|
||||||
|
console.warn(
|
||||||
|
'Modal requires the onRequestClose prop when used with `allowSwipeDismissal`. This is necessary to prevent state corruption.',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,6 +343,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|||||||
onStartShouldSetResponder={this._shouldSetResponder}
|
onStartShouldSetResponder={this._shouldSetResponder}
|
||||||
supportedOrientations={this.props.supportedOrientations}
|
supportedOrientations={this.props.supportedOrientations}
|
||||||
onOrientationChange={this.props.onOrientationChange}
|
onOrientationChange={this.props.onOrientationChange}
|
||||||
|
allowSwipeDismissal={this.props.allowSwipeDismissal}
|
||||||
testID={this.props.testID}>
|
testID={this.props.testID}>
|
||||||
<VirtualizedListContextResetter>
|
<VirtualizedListContextResetter>
|
||||||
<ScrollView.Context.Provider value={null}>
|
<ScrollView.Context.Provider value={null}>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Pod::Spec.new do |s|
|
|||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.compiler_flags = '-Wno-nullability-completeness'
|
s.compiler_flags = '-Wno-nullability-completeness'
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "**/*.{h,m,mm}"
|
s.source_files = podspec_sources("**/*.{h,m,mm}", "**/*.h")
|
||||||
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
||||||
s.header_dir = "RCTAnimation"
|
s.header_dir = "RCTAnimation"
|
||||||
s.pod_target_xcconfig = {
|
s.pod_target_xcconfig = {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Pod::Spec.new do |s|
|
|||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.compiler_flags = '-Wno-nullability-completeness'
|
s.compiler_flags = '-Wno-nullability-completeness'
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "*.{m,mm}"
|
s.source_files = podspec_sources("*.{m,mm}", "")
|
||||||
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
||||||
s.header_dir = "RCTNetwork"
|
s.header_dir = "RCTNetwork"
|
||||||
s.pod_target_xcconfig = {
|
s.pod_target_xcconfig = {
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ const PERMISSIONS = Object.freeze({
|
|||||||
*
|
*
|
||||||
* See https://reactnative.dev/docs/permissionsandroid
|
* See https://reactnative.dev/docs/permissionsandroid
|
||||||
*/
|
*/
|
||||||
class PermissionsAndroid {
|
class PermissionsAndroidImpl {
|
||||||
PERMISSIONS: PermissionsType = PERMISSIONS;
|
PERMISSIONS: PermissionsType = PERMISSIONS;
|
||||||
RESULTS: $ReadOnly<{
|
RESULTS: $ReadOnly<{
|
||||||
DENIED: 'denied',
|
DENIED: 'denied',
|
||||||
@@ -297,5 +297,6 @@ class PermissionsAndroid {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PermissionsAndroidInstance: PermissionsAndroid = new PermissionsAndroid();
|
const PermissionsAndroidInstance: PermissionsAndroidImpl =
|
||||||
|
new PermissionsAndroidImpl();
|
||||||
export default PermissionsAndroidInstance;
|
export default PermissionsAndroidInstance;
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import type {RootTag} from '../Types/RootTagTypes';
|
|||||||
import type {IPerformanceLogger} from '../Utilities/createPerformanceLogger';
|
import type {IPerformanceLogger} from '../Utilities/createPerformanceLogger';
|
||||||
import type {DisplayModeType} from './DisplayMode';
|
import type {DisplayModeType} from './DisplayMode';
|
||||||
|
|
||||||
type Task = (taskData: any) => Promise<void>;
|
type HeadlessTask = (taskData: any) => Promise<void>;
|
||||||
export type TaskProvider = () => Task;
|
export type TaskProvider = () => HeadlessTask;
|
||||||
|
|
||||||
export type ComponentProvider = () => React.ComponentType<any>;
|
export type ComponentProvider = () => React.ComponentType<any>;
|
||||||
export type ComponentProviderInstrumentationHook = (
|
export type ComponentProviderInstrumentationHook = (
|
||||||
|
|||||||
packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/ReactNativeAttributePayload.js
Vendored
+81
-62
@@ -8,7 +8,7 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {AttributeConfiguration} from '../../Renderer/shims/ReactNativeTypes';
|
import type {PartialAttributeConfiguration as AttributeConfiguration} from '../../Renderer/shims/ReactNativeTypes';
|
||||||
|
|
||||||
import flattenStyle from '../../StyleSheet/flattenStyle';
|
import flattenStyle from '../../StyleSheet/flattenStyle';
|
||||||
import deepDiffer from '../../Utilities/differ/deepDiffer';
|
import deepDiffer from '../../Utilities/differ/deepDiffer';
|
||||||
@@ -61,7 +61,7 @@ function restoreDeletedValuesInNestedArray(
|
|||||||
} else if (node && removedKeyCount > 0) {
|
} else if (node && removedKeyCount > 0) {
|
||||||
const obj = node;
|
const obj = node;
|
||||||
for (const propKey in removedKeys) {
|
for (const propKey in removedKeys) {
|
||||||
// $FlowFixMe[incompatible-use] found when upgrading Flow
|
// $FlowFixMe[incompatible-use] removedKeys is always non-null
|
||||||
if (!removedKeys[propKey]) {
|
if (!removedKeys[propKey]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -133,12 +133,12 @@ function diffNestedArrayProperty(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (; i < nextArray.length; i++) {
|
for (; i < nextArray.length; i++) {
|
||||||
// Add all remaining properties.
|
// Add all remaining properties
|
||||||
updatePayload = addNestedProperty(
|
const nextProp = nextArray[i];
|
||||||
updatePayload,
|
if (!nextProp) {
|
||||||
nextArray[i],
|
continue;
|
||||||
validAttributes,
|
}
|
||||||
);
|
updatePayload = addNestedProperty(updatePayload, nextProp, validAttributes);
|
||||||
}
|
}
|
||||||
return updatePayload;
|
return updatePayload;
|
||||||
}
|
}
|
||||||
@@ -183,9 +183,7 @@ function diffNestedProperty(
|
|||||||
if (Array.isArray(prevProp)) {
|
if (Array.isArray(prevProp)) {
|
||||||
return diffProperties(
|
return diffProperties(
|
||||||
updatePayload,
|
updatePayload,
|
||||||
// $FlowFixMe - We know that this is always an object when the input is.
|
|
||||||
flattenStyle(prevProp),
|
flattenStyle(prevProp),
|
||||||
// $FlowFixMe - We know that this isn't an array because of above flow.
|
|
||||||
nextProp,
|
nextProp,
|
||||||
validAttributes,
|
validAttributes,
|
||||||
);
|
);
|
||||||
@@ -194,43 +192,11 @@ function diffNestedProperty(
|
|||||||
return diffProperties(
|
return diffProperties(
|
||||||
updatePayload,
|
updatePayload,
|
||||||
prevProp,
|
prevProp,
|
||||||
// $FlowFixMe - We know that this is always an object when the input is.
|
|
||||||
flattenStyle(nextProp),
|
flattenStyle(nextProp),
|
||||||
validAttributes,
|
validAttributes,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* addNestedProperty takes a single set of props and valid attribute
|
|
||||||
* attribute configurations. It processes each prop and adds it to the
|
|
||||||
* updatePayload.
|
|
||||||
*/
|
|
||||||
function addNestedProperty(
|
|
||||||
updatePayload: null | Object,
|
|
||||||
nextProp: NestedNode,
|
|
||||||
validAttributes: AttributeConfiguration,
|
|
||||||
): $FlowFixMe {
|
|
||||||
if (!nextProp) {
|
|
||||||
return updatePayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(nextProp)) {
|
|
||||||
// Add each property of the leaf.
|
|
||||||
return addProperties(updatePayload, nextProp, validAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < nextProp.length; i++) {
|
|
||||||
// Add all the properties of the array.
|
|
||||||
updatePayload = addNestedProperty(
|
|
||||||
updatePayload,
|
|
||||||
nextProp[i],
|
|
||||||
validAttributes,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return updatePayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clearNestedProperty takes a single set of props and valid attributes. It
|
* clearNestedProperty takes a single set of props and valid attributes. It
|
||||||
* adds a null sentinel to the updatePayload, for each prop key.
|
* adds a null sentinel to the updatePayload, for each prop key.
|
||||||
@@ -285,14 +251,19 @@ function diffProperties(
|
|||||||
prevProp = prevProps[propKey];
|
prevProp = prevProps[propKey];
|
||||||
nextProp = nextProps[propKey];
|
nextProp = nextProps[propKey];
|
||||||
|
|
||||||
// functions are converted to booleans as markers that the associated
|
|
||||||
// events should be sent from native.
|
|
||||||
if (typeof nextProp === 'function') {
|
if (typeof nextProp === 'function') {
|
||||||
nextProp = (true: any);
|
const attributeConfigHasProcess =
|
||||||
// If nextProp is not a function, then don't bother changing prevProp
|
typeof attributeConfig === 'object' &&
|
||||||
// since nextProp will win and go into the updatePayload regardless.
|
typeof attributeConfig.process === 'function';
|
||||||
if (typeof prevProp === 'function') {
|
if (!attributeConfigHasProcess) {
|
||||||
prevProp = (true: any);
|
// functions are converted to booleans as markers that the associated
|
||||||
|
// events should be sent from native.
|
||||||
|
nextProp = (true: any);
|
||||||
|
// If nextProp is not a function, then don't bother changing prevProp
|
||||||
|
// since nextProp will win and go into the updatePayload regardless.
|
||||||
|
if (typeof prevProp === 'function') {
|
||||||
|
prevProp = (true: any);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,16 +413,69 @@ function diffProperties(
|
|||||||
return updatePayload;
|
return updatePayload;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function addNestedProperty(
|
||||||
* addProperties adds all the valid props to the payload after being processed.
|
payload: null | Object,
|
||||||
*/
|
|
||||||
function addProperties(
|
|
||||||
updatePayload: null | Object,
|
|
||||||
props: Object,
|
props: Object,
|
||||||
validAttributes: AttributeConfiguration,
|
validAttributes: AttributeConfiguration,
|
||||||
): null | Object {
|
): null | Object {
|
||||||
// TODO: Fast path
|
// Flatten nested style props.
|
||||||
return diffProperties(updatePayload, emptyObject, props, validAttributes);
|
if (Array.isArray(props)) {
|
||||||
|
for (let i = 0; i < props.length; i++) {
|
||||||
|
payload = addNestedProperty(payload, props[i], validAttributes);
|
||||||
|
}
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const propKey in props) {
|
||||||
|
const prop = props[propKey];
|
||||||
|
|
||||||
|
const attributeConfig = ((validAttributes[
|
||||||
|
propKey
|
||||||
|
]: any): AttributeConfiguration);
|
||||||
|
|
||||||
|
if (attributeConfig == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let newValue;
|
||||||
|
|
||||||
|
if (prop === undefined) {
|
||||||
|
// Discard the prop if it was previously defined.
|
||||||
|
if (payload && payload[propKey] !== undefined) {
|
||||||
|
newValue = null;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (typeof attributeConfig === 'object') {
|
||||||
|
if (typeof attributeConfig.process === 'function') {
|
||||||
|
// An atomic prop with custom processing.
|
||||||
|
newValue = attributeConfig.process(prop);
|
||||||
|
} else if (typeof attributeConfig.diff === 'function') {
|
||||||
|
// An atomic prop with custom diffing. We don't need to do diffing when adding props.
|
||||||
|
newValue = prop;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (typeof prop === 'function') {
|
||||||
|
// A function prop. It represents an event handler. Pass it to native as 'true'.
|
||||||
|
newValue = true;
|
||||||
|
} else {
|
||||||
|
// An atomic prop. Doesn't need to be flattened.
|
||||||
|
newValue = prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newValue !== undefined) {
|
||||||
|
if (!payload) {
|
||||||
|
payload = ({}: {[string]: $FlowFixMe});
|
||||||
|
}
|
||||||
|
payload[propKey] = newValue;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload = addNestedProperty(payload, prop, attributeConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -463,7 +487,6 @@ function clearProperties(
|
|||||||
prevProps: Object,
|
prevProps: Object,
|
||||||
validAttributes: AttributeConfiguration,
|
validAttributes: AttributeConfiguration,
|
||||||
): null | Object {
|
): null | Object {
|
||||||
// TODO: Fast path
|
|
||||||
return diffProperties(updatePayload, prevProps, emptyObject, validAttributes);
|
return diffProperties(updatePayload, prevProps, emptyObject, validAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,11 +494,7 @@ export function create(
|
|||||||
props: Object,
|
props: Object,
|
||||||
validAttributes: AttributeConfiguration,
|
validAttributes: AttributeConfiguration,
|
||||||
): null | Object {
|
): null | Object {
|
||||||
return addProperties(
|
return addNestedProperty(null, props, validAttributes);
|
||||||
null, // updatePayload
|
|
||||||
props,
|
|
||||||
validAttributes,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function diff(
|
export function diff(
|
||||||
|
|||||||
+495
@@ -0,0 +1,495 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import type {PartialAttributeConfiguration as AttributeConfiguration} from '../../../Renderer/shims/ReactNativeTypes';
|
||||||
|
|
||||||
|
const {create, diff} = require('../ReactNativeAttributePayload');
|
||||||
|
|
||||||
|
describe('ReactNativeAttributePayload.create', () => {
|
||||||
|
it('should work with simple example', () => {
|
||||||
|
expect(create({b: 2, c: 3}, {a: true, b: true})).toEqual({
|
||||||
|
b: 2,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with complex example', () => {
|
||||||
|
const validAttributes: AttributeConfiguration = {
|
||||||
|
style: {
|
||||||
|
position: true,
|
||||||
|
zIndex: true,
|
||||||
|
flexGrow: true,
|
||||||
|
flexShrink: true,
|
||||||
|
flexDirection: true,
|
||||||
|
overflow: true,
|
||||||
|
backgroundColor: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
create(
|
||||||
|
{
|
||||||
|
style: [
|
||||||
|
{
|
||||||
|
flexGrow: 1,
|
||||||
|
flexShrink: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
overflow: 'scroll',
|
||||||
|
},
|
||||||
|
[
|
||||||
|
{position: 'relative', zIndex: 2},
|
||||||
|
{flexGrow: 0},
|
||||||
|
{backgroundColor: 'red'},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
validAttributes,
|
||||||
|
),
|
||||||
|
).toEqual({
|
||||||
|
flexGrow: 0,
|
||||||
|
flexShrink: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
overflow: 'scroll',
|
||||||
|
position: 'relative',
|
||||||
|
zIndex: 2,
|
||||||
|
backgroundColor: 'red',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should nullify previously defined style prop that is subsequently set to null or undefined', () => {
|
||||||
|
expect(
|
||||||
|
create({style: [{a: 0}, {a: undefined}]}, {style: {a: true}}),
|
||||||
|
).toEqual({a: null});
|
||||||
|
expect(create({style: [{a: 0}, {a: null}]}, {style: {a: true}})).toEqual({
|
||||||
|
a: null,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore non-style fields that are set to undefined', () => {
|
||||||
|
expect(create({}, {a: true})).toEqual(null);
|
||||||
|
expect(create({a: undefined}, {a: true})).toEqual(null);
|
||||||
|
expect(create({a: undefined, b: undefined}, {a: true, b: true})).toEqual(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
create({a: undefined, b: undefined, c: 1}, {a: true, b: true}),
|
||||||
|
).toEqual(null);
|
||||||
|
expect(
|
||||||
|
create({a: undefined, b: undefined, c: 1}, {a: true, b: true, c: true}),
|
||||||
|
).toEqual({c: 1});
|
||||||
|
expect(
|
||||||
|
create({a: 1, b: undefined, c: 2}, {a: true, b: true, c: true}),
|
||||||
|
).toEqual({a: 1, c: 2});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore invalid fields', () => {
|
||||||
|
expect(create({b: 2}, {})).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not use the diff attribute', () => {
|
||||||
|
const diffA = jest.fn();
|
||||||
|
expect(create({a: [2]}, {a: {diff: diffA}})).toEqual({a: [2]});
|
||||||
|
expect(diffA).not.toBeCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use the process attribute', () => {
|
||||||
|
const processA = jest.fn(a => a + 1);
|
||||||
|
expect(create({a: 2}, {a: {process: processA}})).toEqual({a: 3});
|
||||||
|
expect(processA).toBeCalledWith(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use the process attribute for functions as well', () => {
|
||||||
|
const process = (x: Object) => x;
|
||||||
|
const nextFunction = () => {};
|
||||||
|
expect(create({a: nextFunction}, {a: {process}})).toEqual({
|
||||||
|
a: nextFunction,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with undefined styles', () => {
|
||||||
|
expect(create({style: undefined}, {style: {b: true}})).toEqual(null);
|
||||||
|
expect(create({style: {a: '#ffffff', b: 1}}, {style: {b: true}})).toEqual({
|
||||||
|
b: 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should flatten nested styles and predefined styles', () => {
|
||||||
|
const validStyleAttribute: AttributeConfiguration = {
|
||||||
|
style: {foo: true, bar: true},
|
||||||
|
};
|
||||||
|
expect(create({style: [{foo: 1}, {bar: 2}]}, validStyleAttribute)).toEqual({
|
||||||
|
foo: 1,
|
||||||
|
bar: 2,
|
||||||
|
});
|
||||||
|
expect(create({}, validStyleAttribute)).toEqual(null);
|
||||||
|
const barStyle = {
|
||||||
|
bar: 3,
|
||||||
|
};
|
||||||
|
expect(
|
||||||
|
create({style: [[{foo: 1}, {foo: 2}], barStyle]}, validStyleAttribute),
|
||||||
|
).toEqual({foo: 2, bar: 3});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not flatten nested props if attribute config is a primitive or only has diff/process', () => {
|
||||||
|
expect(create({a: {foo: 1, bar: 2}}, {a: true})).toEqual({
|
||||||
|
a: {foo: 1, bar: 2},
|
||||||
|
});
|
||||||
|
expect(create({a: [{foo: 1}, {bar: 2}]}, {a: true})).toEqual({
|
||||||
|
a: [{foo: 1}, {bar: 2}],
|
||||||
|
});
|
||||||
|
expect(create({a: {foo: 1, bar: 2}}, {a: {diff: a => a}})).toEqual({
|
||||||
|
a: {foo: 1, bar: 2},
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
create({a: [{foo: 1}, {bar: 2}]}, {a: {diff: a => a, process: a => a}}),
|
||||||
|
).toEqual({a: [{foo: 1}, {bar: 2}]});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles attributes defined multiple times', () => {
|
||||||
|
const validAttributes: AttributeConfiguration = {
|
||||||
|
foo: true,
|
||||||
|
style: {foo: true},
|
||||||
|
};
|
||||||
|
expect(create({foo: 4, style: {foo: 2}}, validAttributes)).toEqual({
|
||||||
|
foo: 2,
|
||||||
|
});
|
||||||
|
expect(create({style: {foo: 2}}, validAttributes)).toEqual({
|
||||||
|
foo: 2,
|
||||||
|
});
|
||||||
|
expect(create({style: {foo: 2}, foo: 4}, validAttributes)).toEqual({
|
||||||
|
foo: 4,
|
||||||
|
});
|
||||||
|
expect(create({foo: 4, style: {foo: null}}, validAttributes)).toEqual({
|
||||||
|
foo: null, // this should ideally be null.
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
create({foo: 4, style: [{foo: null}, {foo: 5}]}, validAttributes),
|
||||||
|
).toEqual({
|
||||||
|
foo: 5,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Function properties are just markers to native that events should be sent.
|
||||||
|
it('should convert functions to booleans', () => {
|
||||||
|
expect(
|
||||||
|
create(
|
||||||
|
{
|
||||||
|
a: function () {
|
||||||
|
return 9;
|
||||||
|
},
|
||||||
|
b: function () {
|
||||||
|
return 3;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{a: true, b: true},
|
||||||
|
),
|
||||||
|
).toEqual({a: true, b: true});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('ReactNativeAttributePayload.diff', () => {
|
||||||
|
it('should work with simple example', () => {
|
||||||
|
expect(diff({a: 1, c: 3}, {b: 2, c: 3}, {a: true, b: true})).toEqual({
|
||||||
|
a: null,
|
||||||
|
b: 2,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should skip fields that are equal', () => {
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{a: 1, b: 'two', c: true, d: false, e: undefined, f: 0},
|
||||||
|
{a: 1, b: 'two', c: true, d: false, e: undefined, f: 0},
|
||||||
|
{a: true, b: true, c: true, d: true, e: true, f: true},
|
||||||
|
),
|
||||||
|
).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove fields', () => {
|
||||||
|
expect(diff({a: 1}, {}, {a: true})).toEqual({a: null});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove fields that are set to undefined', () => {
|
||||||
|
expect(diff({a: 1}, {a: undefined}, {a: true})).toEqual({a: null});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should ignore invalid fields', () => {
|
||||||
|
expect(diff({a: 1}, {b: 2}, {})).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use the diff attribute', () => {
|
||||||
|
const diffA = jest.fn((a, b) => true);
|
||||||
|
const diffB = jest.fn((a, b) => false);
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{a: [1], b: [3]},
|
||||||
|
{a: [2], b: [4]},
|
||||||
|
{a: {diff: diffA}, b: {diff: diffB}},
|
||||||
|
),
|
||||||
|
).toEqual({a: [2]});
|
||||||
|
expect(diffA).toBeCalledWith([1], [2]);
|
||||||
|
expect(diffB).toBeCalledWith([3], [4]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not use the diff attribute on addition/removal', () => {
|
||||||
|
const diffA = jest.fn();
|
||||||
|
const diffB = jest.fn();
|
||||||
|
expect(
|
||||||
|
diff({a: [1]}, {b: [2]}, {a: {diff: diffA}, b: {diff: diffB}}),
|
||||||
|
).toEqual({a: null, b: [2]});
|
||||||
|
expect(diffA).not.toBeCalled();
|
||||||
|
expect(diffB).not.toBeCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do deep diffs of Objects by default', () => {
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{a: [1], b: {k: [3, 4]}, c: {k: [4, 4]}},
|
||||||
|
{a: [2], b: {k: [3, 4]}, c: {k: [4, 5]}},
|
||||||
|
{a: true, b: true, c: true},
|
||||||
|
),
|
||||||
|
).toEqual({a: [2], c: {k: [4, 5]}});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with undefined styles', () => {
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{style: {a: '#ffffff', b: 1}},
|
||||||
|
{style: undefined},
|
||||||
|
{style: {b: true}},
|
||||||
|
),
|
||||||
|
).toEqual({b: null});
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{style: undefined},
|
||||||
|
{style: {a: '#ffffff', b: 1}},
|
||||||
|
{style: {b: true}},
|
||||||
|
),
|
||||||
|
).toEqual({b: 1});
|
||||||
|
expect(
|
||||||
|
diff({style: undefined}, {style: undefined}, {style: {b: true}}),
|
||||||
|
).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with empty styles', () => {
|
||||||
|
const validAttributes: AttributeConfiguration = {a: true, b: true};
|
||||||
|
expect(diff({a: 1, c: 3}, {}, validAttributes)).toEqual({a: null});
|
||||||
|
expect(diff({}, {a: 1, c: 3}, validAttributes)).toEqual({a: 1});
|
||||||
|
expect(diff({}, {}, validAttributes)).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should flatten nested styles and predefined styles', () => {
|
||||||
|
const validStyleAttribute: AttributeConfiguration = {
|
||||||
|
style: {foo: true, bar: true},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
diff({}, {style: [{foo: 1}, {bar: 2}]}, validStyleAttribute),
|
||||||
|
).toEqual({foo: 1, bar: 2});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
diff({style: [{foo: 1}, {bar: 2}]}, {}, validStyleAttribute),
|
||||||
|
).toEqual({foo: null, bar: null});
|
||||||
|
|
||||||
|
const barStyle = {
|
||||||
|
bar: 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
diff({}, {style: [[{foo: 1}, {foo: 2}], barStyle]}, validStyleAttribute),
|
||||||
|
).toEqual({foo: 2, bar: 3});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reset a value to a previous if it is removed', () => {
|
||||||
|
const validStyleAttribute: AttributeConfiguration = {
|
||||||
|
style: {foo: true, bar: true},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{style: [{foo: 1}, {foo: 3}]},
|
||||||
|
{style: [{foo: 1}, {bar: 2}]},
|
||||||
|
validStyleAttribute,
|
||||||
|
),
|
||||||
|
).toEqual({foo: 1, bar: 2});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not clear removed props if they are still in another slot', () => {
|
||||||
|
const validStyleAttribute: AttributeConfiguration = {
|
||||||
|
style: {foo: true, bar: true},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{style: [{}, {foo: 3, bar: 2}]},
|
||||||
|
{style: [{foo: 3}, {bar: 2}]},
|
||||||
|
validStyleAttribute,
|
||||||
|
),
|
||||||
|
).toEqual({foo: 3}); // this should ideally be null. heuristic tradeoff.
|
||||||
|
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{style: [{}, {foo: 3, bar: 2}]},
|
||||||
|
{style: [{foo: 1, bar: 1}, {bar: 2}]},
|
||||||
|
validStyleAttribute,
|
||||||
|
),
|
||||||
|
).toEqual({bar: 2, foo: 1});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should clear a prop if a later style is explicit null/undefined', () => {
|
||||||
|
const validStyleAttribute: AttributeConfiguration = {
|
||||||
|
style: {foo: true, bar: true},
|
||||||
|
};
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{style: [{}, {foo: 3, bar: 2}]},
|
||||||
|
{style: [{foo: 1}, {bar: 2, foo: null}]},
|
||||||
|
validStyleAttribute,
|
||||||
|
),
|
||||||
|
).toEqual({foo: null});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{style: [{foo: 3}, {foo: null, bar: 2}]},
|
||||||
|
{style: [{foo: null}, {bar: 2}]},
|
||||||
|
validStyleAttribute,
|
||||||
|
),
|
||||||
|
).toEqual({foo: null});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{style: [{foo: 1}, {foo: null}]},
|
||||||
|
{style: [{foo: 2}, {foo: null}]},
|
||||||
|
validStyleAttribute,
|
||||||
|
),
|
||||||
|
).toEqual({foo: null}); // this should ideally be null. heuristic.
|
||||||
|
|
||||||
|
// Test the same case with object equality because an early bailout doesn't
|
||||||
|
// work in this case.
|
||||||
|
const fooObj = {foo: 3};
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{style: [{foo: 1}, fooObj]},
|
||||||
|
{style: [{foo: 2}, fooObj]},
|
||||||
|
validStyleAttribute,
|
||||||
|
),
|
||||||
|
).toEqual({foo: 3}); // this should ideally be null. heuristic.
|
||||||
|
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{style: [{foo: 1}, {foo: 3}]},
|
||||||
|
{style: [{foo: 2}, {foo: undefined}]},
|
||||||
|
validStyleAttribute,
|
||||||
|
),
|
||||||
|
).toEqual({foo: null}); // this should ideally be null. heuristic.
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles attributes defined multiple times', () => {
|
||||||
|
const validAttributes: AttributeConfiguration = {
|
||||||
|
foo: true,
|
||||||
|
style: {foo: true},
|
||||||
|
};
|
||||||
|
expect(diff({}, {foo: 4, style: {foo: 2}}, validAttributes)).toEqual({
|
||||||
|
foo: 2,
|
||||||
|
});
|
||||||
|
expect(diff({foo: 4}, {style: {foo: 2}}, validAttributes)).toEqual({
|
||||||
|
foo: 2,
|
||||||
|
});
|
||||||
|
expect(diff({style: {foo: 2}}, {foo: 4}, validAttributes)).toEqual({
|
||||||
|
foo: 4,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Function properties are just markers to native that events should be sent.
|
||||||
|
it('should convert functions to booleans', () => {
|
||||||
|
// Note that if the property changes from one function to another, we don't
|
||||||
|
// need to send an update.
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{
|
||||||
|
a: function () {
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
b: function () {
|
||||||
|
return 2;
|
||||||
|
},
|
||||||
|
c: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
b: function () {
|
||||||
|
return 9;
|
||||||
|
},
|
||||||
|
c: function () {
|
||||||
|
return 3;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{a: true, b: true, c: true},
|
||||||
|
),
|
||||||
|
).toEqual({a: null, c: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should skip changed functions', () => {
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{
|
||||||
|
a: function () {
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a: function () {
|
||||||
|
return 9;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{a: true},
|
||||||
|
),
|
||||||
|
).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should skip deeply-nested changed functions', () => {
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{
|
||||||
|
wrapper: {
|
||||||
|
a: function () {
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
wrapper: {
|
||||||
|
a: function () {
|
||||||
|
return 9;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{wrapper: true},
|
||||||
|
),
|
||||||
|
).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use the process function config when prop is a function', () => {
|
||||||
|
const process = jest.fn(a => a);
|
||||||
|
const nextFunction = function () {};
|
||||||
|
expect(
|
||||||
|
diff(
|
||||||
|
{
|
||||||
|
a: function () {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a: nextFunction,
|
||||||
|
},
|
||||||
|
{a: {process}},
|
||||||
|
),
|
||||||
|
).toEqual({a: nextFunction});
|
||||||
|
expect(process).toBeCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -25,6 +25,6 @@ Pod::Spec.new do |s|
|
|||||||
s.author = "Meta Platforms, Inc. and its affiliates"
|
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "**/*.{c,h,m,mm,cpp}"
|
s.source_files = podspec_sources("**/*.{c,h,m,mm,cpp}", "**/*.h")
|
||||||
s.header_dir = "RCTRequired"
|
s.header_dir = "RCTRequired"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Pod::Spec.new do |s|
|
|||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.compiler_flags = '-Wno-nullability-completeness'
|
s.compiler_flags = '-Wno-nullability-completeness'
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "*.{m,mm}"
|
s.source_files = podspec_sources("*.{m,mm}", "**/*.h")
|
||||||
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
||||||
s.header_dir = "RCTSettings"
|
s.header_dir = "RCTSettings"
|
||||||
s.pod_target_xcconfig = {
|
s.pod_target_xcconfig = {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ Pod::Spec.new do |s|
|
|||||||
s.author = "Meta Platforms, Inc. and its affiliates"
|
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "**/*.{h,m,mm}"
|
s.source_files = podspec_sources("**/*.{h,m,mm}", "**/*.h")
|
||||||
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
||||||
s.header_dir = "RCTText"
|
s.header_dir = "RCTText"
|
||||||
s.framework = ["MobileCoreServices"]
|
s.framework = ["MobileCoreServices"]
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Pod::Spec.new do |s|
|
|||||||
s.author = "Meta Platforms, Inc. and its affiliates"
|
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "**/*.{c,h,m,mm,cpp}"
|
s.source_files = podspec_sources("**/*.{c,h,m,mm,cpp}", "**/*.h")
|
||||||
s.header_dir = "RCTTypeSafety"
|
s.header_dir = "RCTTypeSafety"
|
||||||
s.pod_target_xcconfig = {
|
s.pod_target_xcconfig = {
|
||||||
"USE_HEADERMAP" => "YES",
|
"USE_HEADERMAP" => "YES",
|
||||||
|
|||||||
@@ -9,6 +9,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export * from '../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo';
|
export * from '../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo';
|
||||||
import NativeDeviceInfo from '../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo';
|
export {default} from '../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo';
|
||||||
|
|
||||||
export default NativeDeviceInfo;
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ type Options = $ReadOnly<{
|
|||||||
excludedPlatforms?: $ReadOnlyArray<'iOS' | 'android'>,
|
excludedPlatforms?: $ReadOnlyArray<'iOS' | 'android'>,
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export type NativeComponentType<T> = HostComponent<T>;
|
export type NativeComponentType<T: {...}> = HostComponent<T>;
|
||||||
|
|
||||||
// If this function runs then that means the view configs were not
|
// If this function runs then that means the view configs were not
|
||||||
// generated at build time using `GenerateViewConfigJs.js`. Thus
|
// generated at build time using `GenerateViewConfigJs.js`. Thus
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Pod::Spec.new do |s|
|
|||||||
s.platforms = min_supported_versions
|
s.platforms = min_supported_versions
|
||||||
s.compiler_flags = '-Wno-nullability-completeness'
|
s.compiler_flags = '-Wno-nullability-completeness'
|
||||||
s.source = source
|
s.source = source
|
||||||
s.source_files = "*.{m,mm}"
|
s.source_files = podspec_sources("*.{m,mm}", "**/*.h")
|
||||||
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
|
||||||
s.header_dir = "RCTVibration"
|
s.header_dir = "RCTVibration"
|
||||||
s.pod_target_xcconfig = {
|
s.pod_target_xcconfig = {
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ export type EventConfig<T> = {
|
|||||||
useNativeDriver: boolean,
|
useNativeDriver: boolean,
|
||||||
platformConfig?: PlatformConfig,
|
platformConfig?: PlatformConfig,
|
||||||
};
|
};
|
||||||
declare export function attachNativeEvent(
|
declare export function attachNativeEventImpl(
|
||||||
viewRef: any,
|
viewRef: any,
|
||||||
eventName: string,
|
eventName: string,
|
||||||
argMapping: $ReadOnlyArray<?Mapping>,
|
argMapping: $ReadOnlyArray<?Mapping>,
|
||||||
@@ -166,7 +166,10 @@ declare export default {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`public API should not change unintentionally Libraries/Animated/AnimatedExports.js.flow 1`] = `
|
exports[`public API should not change unintentionally Libraries/Animated/AnimatedExports.js.flow 1`] = `
|
||||||
"export { default as FlatList } from \\"./components/AnimatedFlatList\\";
|
"export type { DecayAnimationConfig } from \\"./animations/DecayAnimation\\";
|
||||||
|
export type { SpringAnimationConfig } from \\"./animations/SpringAnimation\\";
|
||||||
|
export type { TimingAnimationConfig } from \\"./animations/TimingAnimation\\";
|
||||||
|
export { default as FlatList } from \\"./components/AnimatedFlatList\\";
|
||||||
export { default as Image } from \\"./components/AnimatedImage\\";
|
export { default as Image } from \\"./components/AnimatedImage\\";
|
||||||
export { default as ScrollView } from \\"./components/AnimatedScrollView\\";
|
export { default as ScrollView } from \\"./components/AnimatedScrollView\\";
|
||||||
export { default as SectionList } from \\"./components/AnimatedSectionList\\";
|
export { default as SectionList } from \\"./components/AnimatedSectionList\\";
|
||||||
@@ -185,6 +188,7 @@ export type { default as AnimatedNode } from \\"./nodes/AnimatedNode\\";
|
|||||||
export type { default as AnimatedAddition } from \\"./nodes/AnimatedAddition\\";
|
export type { default as AnimatedAddition } from \\"./nodes/AnimatedAddition\\";
|
||||||
export type { default as AnimatedDiffClamp } from \\"./nodes/AnimatedDiffClamp\\";
|
export type { default as AnimatedDiffClamp } from \\"./nodes/AnimatedDiffClamp\\";
|
||||||
export type { default as AnimatedDivision } from \\"./nodes/AnimatedDivision\\";
|
export type { default as AnimatedDivision } from \\"./nodes/AnimatedDivision\\";
|
||||||
|
export type { InterpolationConfigType as InterpolationConfig } from \\"./nodes/AnimatedInterpolation\\";
|
||||||
export type { default as AnimatedModulo } from \\"./nodes/AnimatedModulo\\";
|
export type { default as AnimatedModulo } from \\"./nodes/AnimatedModulo\\";
|
||||||
export type { default as AnimatedMultiplication } from \\"./nodes/AnimatedMultiplication\\";
|
export type { default as AnimatedMultiplication } from \\"./nodes/AnimatedMultiplication\\";
|
||||||
export type { default as AnimatedSubtraction } from \\"./nodes/AnimatedSubtraction\\";
|
export type { default as AnimatedSubtraction } from \\"./nodes/AnimatedSubtraction\\";
|
||||||
@@ -222,53 +226,53 @@ exports[`public API should not change unintentionally Libraries/Animated/Animate
|
|||||||
reset: () => void,
|
reset: () => void,
|
||||||
...
|
...
|
||||||
};
|
};
|
||||||
declare const add: (
|
declare const addImpl: (
|
||||||
a: AnimatedNode | number,
|
a: AnimatedNode | number,
|
||||||
b: AnimatedNode | number
|
b: AnimatedNode | number
|
||||||
) => AnimatedAddition;
|
) => AnimatedAddition;
|
||||||
declare const subtract: (
|
declare const subtractImpl: (
|
||||||
a: AnimatedNode | number,
|
a: AnimatedNode | number,
|
||||||
b: AnimatedNode | number
|
b: AnimatedNode | number
|
||||||
) => AnimatedSubtraction;
|
) => AnimatedSubtraction;
|
||||||
declare const divide: (
|
declare const divideImpl: (
|
||||||
a: AnimatedNode | number,
|
a: AnimatedNode | number,
|
||||||
b: AnimatedNode | number
|
b: AnimatedNode | number
|
||||||
) => AnimatedDivision;
|
) => AnimatedDivision;
|
||||||
declare const multiply: (
|
declare const multiplyImpl: (
|
||||||
a: AnimatedNode | number,
|
a: AnimatedNode | number,
|
||||||
b: AnimatedNode | number
|
b: AnimatedNode | number
|
||||||
) => AnimatedMultiplication;
|
) => AnimatedMultiplication;
|
||||||
declare const modulo: (a: AnimatedNode, modulus: number) => AnimatedModulo;
|
declare const moduloImpl: (a: AnimatedNode, modulus: number) => AnimatedModulo;
|
||||||
declare const diffClamp: (
|
declare const diffClampImpl: (
|
||||||
a: AnimatedNode,
|
a: AnimatedNode,
|
||||||
min: number,
|
min: number,
|
||||||
max: number
|
max: number
|
||||||
) => AnimatedDiffClamp;
|
) => AnimatedDiffClamp;
|
||||||
declare const spring: (
|
declare const springImpl: (
|
||||||
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
||||||
config: SpringAnimationConfig
|
config: SpringAnimationConfig
|
||||||
) => CompositeAnimation;
|
) => CompositeAnimation;
|
||||||
declare const timing: (
|
declare const timingImpl: (
|
||||||
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
||||||
config: TimingAnimationConfig
|
config: TimingAnimationConfig
|
||||||
) => CompositeAnimation;
|
) => CompositeAnimation;
|
||||||
declare const decay: (
|
declare const decayImpl: (
|
||||||
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
value: AnimatedValue | AnimatedValueXY | AnimatedColor,
|
||||||
config: DecayAnimationConfig
|
config: DecayAnimationConfig
|
||||||
) => CompositeAnimation;
|
) => CompositeAnimation;
|
||||||
declare const sequence: (
|
declare const sequenceImpl: (
|
||||||
animations: Array<CompositeAnimation>
|
animations: Array<CompositeAnimation>
|
||||||
) => CompositeAnimation;
|
) => CompositeAnimation;
|
||||||
type ParallelConfig = {
|
type ParallelConfig = {
|
||||||
stopTogether?: boolean,
|
stopTogether?: boolean,
|
||||||
...
|
...
|
||||||
};
|
};
|
||||||
declare const parallel: (
|
declare const parallelImpl: (
|
||||||
animations: Array<CompositeAnimation>,
|
animations: Array<CompositeAnimation>,
|
||||||
config?: ?ParallelConfig
|
config?: ?ParallelConfig
|
||||||
) => CompositeAnimation;
|
) => CompositeAnimation;
|
||||||
declare const delay: (time: number) => CompositeAnimation;
|
declare const delayImpl: (time: number) => CompositeAnimation;
|
||||||
declare const stagger: (
|
declare const staggerImpl: (
|
||||||
time: number,
|
time: number,
|
||||||
animations: Array<CompositeAnimation>
|
animations: Array<CompositeAnimation>
|
||||||
) => CompositeAnimation;
|
) => CompositeAnimation;
|
||||||
@@ -277,19 +281,19 @@ type LoopAnimationConfig = {
|
|||||||
resetBeforeIteration?: boolean,
|
resetBeforeIteration?: boolean,
|
||||||
...
|
...
|
||||||
};
|
};
|
||||||
declare const loop: (
|
declare const loopImpl: (
|
||||||
animation: CompositeAnimation,
|
animation: CompositeAnimation,
|
||||||
$$PARAM_1$$?: LoopAnimationConfig
|
$$PARAM_1$$?: LoopAnimationConfig
|
||||||
) => CompositeAnimation;
|
) => CompositeAnimation;
|
||||||
declare function forkEvent(
|
declare function forkEventImpl(
|
||||||
event: ?AnimatedEvent | ?Function,
|
event: ?AnimatedEvent | ?Function,
|
||||||
listener: Function
|
listener: Function
|
||||||
): AnimatedEvent | Function;
|
): AnimatedEvent | Function;
|
||||||
declare function unforkEvent(
|
declare function unforkEventImpl(
|
||||||
event: ?AnimatedEvent | ?Function,
|
event: ?AnimatedEvent | ?Function,
|
||||||
listener: Function
|
listener: Function
|
||||||
): void;
|
): void;
|
||||||
declare const event: <T>(
|
declare const eventImpl: <T>(
|
||||||
argMapping: $ReadOnlyArray<?Mapping>,
|
argMapping: $ReadOnlyArray<?Mapping>,
|
||||||
config: EventConfig<T>
|
config: EventConfig<T>
|
||||||
) => any;
|
) => any;
|
||||||
@@ -309,25 +313,25 @@ declare export default {
|
|||||||
Color: typeof AnimatedColor,
|
Color: typeof AnimatedColor,
|
||||||
Interpolation: typeof AnimatedInterpolation,
|
Interpolation: typeof AnimatedInterpolation,
|
||||||
Node: typeof AnimatedNode,
|
Node: typeof AnimatedNode,
|
||||||
decay: typeof decay,
|
decay: typeof decayImpl,
|
||||||
timing: typeof timing,
|
timing: typeof timingImpl,
|
||||||
spring: typeof spring,
|
spring: typeof springImpl,
|
||||||
add: typeof add,
|
add: typeof addImpl,
|
||||||
subtract: typeof subtract,
|
subtract: typeof subtractImpl,
|
||||||
divide: typeof divide,
|
divide: typeof divideImpl,
|
||||||
multiply: typeof multiply,
|
multiply: typeof multiplyImpl,
|
||||||
modulo: typeof modulo,
|
modulo: typeof moduloImpl,
|
||||||
diffClamp: typeof diffClamp,
|
diffClamp: typeof diffClampImpl,
|
||||||
delay: typeof delay,
|
delay: typeof delayImpl,
|
||||||
sequence: typeof sequence,
|
sequence: typeof sequenceImpl,
|
||||||
parallel: typeof parallel,
|
parallel: typeof parallelImpl,
|
||||||
stagger: typeof stagger,
|
stagger: typeof staggerImpl,
|
||||||
loop: typeof loop,
|
loop: typeof loopImpl,
|
||||||
event: typeof event,
|
event: typeof eventImpl,
|
||||||
createAnimatedComponent: typeof createAnimatedComponent,
|
createAnimatedComponent: typeof createAnimatedComponent,
|
||||||
attachNativeEvent: typeof attachNativeEvent,
|
attachNativeEvent: typeof attachNativeEventImpl,
|
||||||
forkEvent: typeof forkEvent,
|
forkEvent: typeof forkEventImpl,
|
||||||
unforkEvent: typeof unforkEvent,
|
unforkEvent: typeof unforkEventImpl,
|
||||||
Event: typeof AnimatedEvent,
|
Event: typeof AnimatedEvent,
|
||||||
};
|
};
|
||||||
"
|
"
|
||||||
@@ -628,10 +632,9 @@ exports[`public API should not change unintentionally Libraries/Animated/compone
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedScrollView.js 1`] = `
|
exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedScrollView.js 1`] = `
|
||||||
"type AnimatedScrollViewProps = React.ElementConfig<typeof ScrollView>;
|
"type AnimatedScrollViewInstance = React.ElementRef<typeof ScrollView>;
|
||||||
type AnimatedScrollViewInstance = React.ElementRef<typeof ScrollView>;
|
|
||||||
declare const AnimatedScrollView: AnimatedComponentType<
|
declare const AnimatedScrollView: AnimatedComponentType<
|
||||||
AnimatedScrollViewProps,
|
ScrollViewProps,
|
||||||
AnimatedScrollViewInstance,
|
AnimatedScrollViewInstance,
|
||||||
>;
|
>;
|
||||||
declare export default typeof AnimatedScrollView;
|
declare export default typeof AnimatedScrollView;
|
||||||
@@ -648,7 +651,7 @@ exports[`public API should not change unintentionally Libraries/Animated/compone
|
|||||||
|
|
||||||
exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedText.js 1`] = `
|
exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedText.js 1`] = `
|
||||||
"declare export default AnimatedComponentType<
|
"declare export default AnimatedComponentType<
|
||||||
React.ElementConfig<typeof Text>,
|
TextProps,
|
||||||
React.ElementRef<typeof Text>,
|
React.ElementRef<typeof Text>,
|
||||||
>;
|
>;
|
||||||
"
|
"
|
||||||
@@ -656,7 +659,7 @@ exports[`public API should not change unintentionally Libraries/Animated/compone
|
|||||||
|
|
||||||
exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedView.js 1`] = `
|
exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedView.js 1`] = `
|
||||||
"declare export default AnimatedComponentType<
|
"declare export default AnimatedComponentType<
|
||||||
React.ElementConfig<typeof View>,
|
ViewProps,
|
||||||
React.ElementRef<typeof View>,
|
React.ElementRef<typeof View>,
|
||||||
>;
|
>;
|
||||||
"
|
"
|
||||||
@@ -695,9 +698,7 @@ type NonAnimatedProps =
|
|||||||
| \\"disabled\\"
|
| \\"disabled\\"
|
||||||
| \\"accessibilityLabel\\";
|
| \\"accessibilityLabel\\";
|
||||||
type PassThroughProps = $ReadOnly<{
|
type PassThroughProps = $ReadOnly<{
|
||||||
passthroughAnimatedPropExplicitValues?: React.ElementConfig<
|
passthroughAnimatedPropExplicitValues?: ViewProps | null,
|
||||||
typeof View,
|
|
||||||
> | null,
|
|
||||||
}>;
|
}>;
|
||||||
export type AnimatedProps<Props: { ... }> = {
|
export type AnimatedProps<Props: { ... }> = {
|
||||||
[K in keyof Props]: K extends NonAnimatedProps
|
[K in keyof Props]: K extends NonAnimatedProps
|
||||||
@@ -1538,10 +1539,10 @@ exports[`public API should not change unintentionally Libraries/Components/Butto
|
|||||||
accessibilityHint?: ?string,
|
accessibilityHint?: ?string,
|
||||||
accessibilityLanguage?: ?Stringish,
|
accessibilityLanguage?: ?Stringish,
|
||||||
}>;
|
}>;
|
||||||
declare const Touchable:
|
declare const NativeTouchable:
|
||||||
| typeof TouchableNativeFeedback
|
| typeof TouchableNativeFeedback
|
||||||
| typeof TouchableOpacity;
|
| typeof TouchableOpacity;
|
||||||
type ButtonRef = React.ElementRef<typeof Touchable>;
|
type ButtonRef = React.ElementRef<typeof NativeTouchable>;
|
||||||
declare const Button: component(
|
declare const Button: component(
|
||||||
ref?: React.RefSetter<ButtonRef>,
|
ref?: React.RefSetter<ButtonRef>,
|
||||||
...props: ButtonProps
|
...props: ButtonProps
|
||||||
@@ -1757,8 +1758,7 @@ declare export default typeof LayoutConformanceNativeComponent;
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`public API should not change unintentionally Libraries/Components/Pressable/Pressable.js 1`] = `
|
exports[`public API should not change unintentionally Libraries/Components/Pressable/Pressable.js 1`] = `
|
||||||
"type ViewStyleProp = React.ElementConfig<typeof View>[\\"style\\"];
|
"export type { PressableAndroidRippleConfig };
|
||||||
export type { PressableAndroidRippleConfig };
|
|
||||||
export type PressableStateCallbackType = $ReadOnly<{
|
export type PressableStateCallbackType = $ReadOnly<{
|
||||||
pressed: boolean,
|
pressed: boolean,
|
||||||
}>;
|
}>;
|
||||||
@@ -1932,11 +1932,11 @@ export { default } from \\"../../../src/private/specs_DEPRECATED/components/RCTS
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`public API should not change unintentionally Libraries/Components/SafeAreaView/SafeAreaView.js 1`] = `
|
exports[`public API should not change unintentionally Libraries/Components/SafeAreaView/SafeAreaView.js 1`] = `
|
||||||
"declare const exported: component(
|
"declare const SafeAreaView: component(
|
||||||
ref?: React.RefSetter<React.ElementRef<typeof View>>,
|
ref?: React.RefSetter<React.ElementRef<typeof View>>,
|
||||||
...props: ViewProps
|
...props: ViewProps
|
||||||
);
|
);
|
||||||
declare export default typeof exported;
|
declare export default typeof SafeAreaView;
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -3515,7 +3515,7 @@ declare export default typeof ReactNativeViewAttributes;
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`public API should not change unintentionally Libraries/Components/View/View.js 1`] = `
|
exports[`public API should not change unintentionally Libraries/Components/View/View.js 1`] = `
|
||||||
"declare export default component(
|
"declare export default component View(
|
||||||
ref?: React.RefSetter<React.ElementRef<typeof ViewNativeComponent>>,
|
ref?: React.RefSetter<React.ElementRef<typeof ViewNativeComponent>>,
|
||||||
...props: ViewProps
|
...props: ViewProps
|
||||||
);
|
);
|
||||||
@@ -3685,7 +3685,6 @@ export type AccessibilityProps = $ReadOnly<{
|
|||||||
accessibilityLabel?: ?Stringish,
|
accessibilityLabel?: ?Stringish,
|
||||||
accessibilityHint?: ?Stringish,
|
accessibilityHint?: ?Stringish,
|
||||||
\\"aria-label\\"?: ?Stringish,
|
\\"aria-label\\"?: ?Stringish,
|
||||||
experimental_accessibilityOrder?: ?Array<string>,
|
|
||||||
accessibilityRole?: ?AccessibilityRole,
|
accessibilityRole?: ?AccessibilityRole,
|
||||||
role?: ?Role,
|
role?: ?Role,
|
||||||
accessibilityState?: ?AccessibilityState,
|
accessibilityState?: ?AccessibilityState,
|
||||||
@@ -3833,6 +3832,7 @@ type ViewBaseProps = $ReadOnly<{
|
|||||||
hitSlop?: ?EdgeInsetsOrSizeProp,
|
hitSlop?: ?EdgeInsetsOrSizeProp,
|
||||||
pointerEvents?: ?(\\"auto\\" | \\"box-none\\" | \\"box-only\\" | \\"none\\"),
|
pointerEvents?: ?(\\"auto\\" | \\"box-none\\" | \\"box-only\\" | \\"none\\"),
|
||||||
removeClippedSubviews?: ?boolean,
|
removeClippedSubviews?: ?boolean,
|
||||||
|
experimental_accessibilityOrder?: ?Array<string>,
|
||||||
}>;
|
}>;
|
||||||
export type ViewProps = $ReadOnly<{
|
export type ViewProps = $ReadOnly<{
|
||||||
...DirectEventProps,
|
...DirectEventProps,
|
||||||
@@ -4179,11 +4179,11 @@ exports[`public API should not change unintentionally Libraries/EventEmitter/Nat
|
|||||||
type EmitterSubscription = EventSubscription;
|
type EmitterSubscription = EventSubscription;
|
||||||
export type { EventSubscription, EmitterSubscription };
|
export type { EventSubscription, EmitterSubscription };
|
||||||
export type NativeEventSubscription = EventSubscription;
|
export type NativeEventSubscription = EventSubscription;
|
||||||
type UnsafeObject = Object;
|
type UnsafeNativeEventObject = Object;
|
||||||
declare export default class NativeEventEmitter<
|
declare export default class NativeEventEmitter<
|
||||||
TEventToArgsMap: $ReadOnly<
|
TEventToArgsMap: $ReadOnly<
|
||||||
Record<string, $ReadOnlyArray<UnsafeObject>>,
|
Record<string, $ReadOnlyArray<UnsafeNativeEventObject>>,
|
||||||
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
|
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeNativeEventObject>>>,
|
||||||
> implements IEventEmitter<TEventToArgsMap>
|
> implements IEventEmitter<TEventToArgsMap>
|
||||||
{
|
{
|
||||||
constructor(nativeModule?: ?NativeModule): void;
|
constructor(nativeModule?: ?NativeModule): void;
|
||||||
@@ -4859,13 +4859,13 @@ export type LayoutAnimationProperties = $ReadOnly<{
|
|||||||
}>;
|
}>;
|
||||||
type OnAnimationDidEndCallback = () => void;
|
type OnAnimationDidEndCallback = () => void;
|
||||||
type OnAnimationDidFailCallback = () => void;
|
type OnAnimationDidFailCallback = () => void;
|
||||||
declare function setEnabled(value: boolean): void;
|
declare function setLayoutAnimationEnabled(value: boolean): void;
|
||||||
declare function configureNext(
|
declare function configureNext(
|
||||||
config: LayoutAnimationConfig,
|
config: LayoutAnimationConfig,
|
||||||
onAnimationDidEnd?: OnAnimationDidEndCallback,
|
onAnimationDidEnd?: OnAnimationDidEndCallback,
|
||||||
onAnimationDidFail?: OnAnimationDidFailCallback
|
onAnimationDidFail?: OnAnimationDidFailCallback
|
||||||
): void;
|
): void;
|
||||||
declare function create(
|
declare function createLayoutAnimation(
|
||||||
duration: number,
|
duration: number,
|
||||||
type?: LayoutAnimationType,
|
type?: LayoutAnimationType,
|
||||||
property?: LayoutAnimationProperty
|
property?: LayoutAnimationProperty
|
||||||
@@ -4877,7 +4877,7 @@ declare const Presets: {
|
|||||||
};
|
};
|
||||||
declare const LayoutAnimation: {
|
declare const LayoutAnimation: {
|
||||||
configureNext: typeof configureNext,
|
configureNext: typeof configureNext,
|
||||||
create: typeof create,
|
create: typeof createLayoutAnimation,
|
||||||
Types: LayoutAnimationTypes,
|
Types: LayoutAnimationTypes,
|
||||||
Properties: LayoutAnimationProperties,
|
Properties: LayoutAnimationProperties,
|
||||||
checkConfig(...args: Array<mixed>): void,
|
checkConfig(...args: Array<mixed>): void,
|
||||||
@@ -4885,7 +4885,7 @@ declare const LayoutAnimation: {
|
|||||||
easeInEaseOut: (onAnimationDidEnd?: OnAnimationDidEndCallback) => void,
|
easeInEaseOut: (onAnimationDidEnd?: OnAnimationDidEndCallback) => void,
|
||||||
linear: (onAnimationDidEnd?: OnAnimationDidEndCallback) => void,
|
linear: (onAnimationDidEnd?: OnAnimationDidEndCallback) => void,
|
||||||
spring: (onAnimationDidEnd?: OnAnimationDidEndCallback) => void,
|
spring: (onAnimationDidEnd?: OnAnimationDidEndCallback) => void,
|
||||||
setEnabled: typeof setEnabled,
|
setEnabled: typeof setLayoutAnimationEnabled,
|
||||||
};
|
};
|
||||||
declare export default typeof LayoutAnimation;
|
declare export default typeof LayoutAnimation;
|
||||||
"
|
"
|
||||||
@@ -4940,8 +4940,7 @@ declare export default typeof FillRateHelper;
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`public API should not change unintentionally Libraries/Lists/FlatList.js 1`] = `
|
exports[`public API should not change unintentionally Libraries/Lists/FlatList.js 1`] = `
|
||||||
"declare const VirtualizedList: typeof VirtualizedLists.VirtualizedList;
|
"type RequiredProps<ItemT> = {
|
||||||
type RequiredProps<ItemT> = {
|
|
||||||
data: ?$ReadOnly<$ArrayLike<ItemT>>,
|
data: ?$ReadOnly<$ArrayLike<ItemT>>,
|
||||||
};
|
};
|
||||||
type OptionalProps<ItemT> = {
|
type OptionalProps<ItemT> = {
|
||||||
@@ -4971,7 +4970,6 @@ type FlatListBaseProps<ItemT> = {
|
|||||||
...RequiredProps<ItemT>,
|
...RequiredProps<ItemT>,
|
||||||
...OptionalProps<ItemT>,
|
...OptionalProps<ItemT>,
|
||||||
};
|
};
|
||||||
type VirtualizedListProps = React.ElementConfig<typeof VirtualizedList>;
|
|
||||||
export type FlatListProps<ItemT> = {
|
export type FlatListProps<ItemT> = {
|
||||||
...Omit<
|
...Omit<
|
||||||
VirtualizedListProps,
|
VirtualizedListProps,
|
||||||
@@ -5689,6 +5687,7 @@ export type ModalPropsIOS = {
|
|||||||
>,
|
>,
|
||||||
onDismiss?: ?() => void,
|
onDismiss?: ?() => void,
|
||||||
onOrientationChange?: ?DirectEventHandler<OrientationChangeEvent>,
|
onOrientationChange?: ?DirectEventHandler<OrientationChangeEvent>,
|
||||||
|
allowSwipeDismissal?: ?boolean,
|
||||||
};
|
};
|
||||||
export type ModalPropsAndroid = {
|
export type ModalPropsAndroid = {
|
||||||
hardwareAccelerated?: ?boolean,
|
hardwareAccelerated?: ?boolean,
|
||||||
@@ -6146,7 +6145,7 @@ type PermissionsType = $ReadOnly<{
|
|||||||
}>;
|
}>;
|
||||||
export type PermissionStatus = \\"granted\\" | \\"denied\\" | \\"never_ask_again\\";
|
export type PermissionStatus = \\"granted\\" | \\"denied\\" | \\"never_ask_again\\";
|
||||||
export type Permission = $Values<PermissionsType>;
|
export type Permission = $Values<PermissionsType>;
|
||||||
declare class PermissionsAndroid {
|
declare class PermissionsAndroidImpl {
|
||||||
PERMISSIONS: PermissionsType;
|
PERMISSIONS: PermissionsType;
|
||||||
RESULTS: $ReadOnly<{
|
RESULTS: $ReadOnly<{
|
||||||
DENIED: \\"denied\\",
|
DENIED: \\"denied\\",
|
||||||
@@ -6167,7 +6166,7 @@ declare class PermissionsAndroid {
|
|||||||
permissions: Array<Permission>
|
permissions: Array<Permission>
|
||||||
): Promise<{ [permission: Permission]: PermissionStatus, ... }>;
|
): Promise<{ [permission: Permission]: PermissionStatus, ... }>;
|
||||||
}
|
}
|
||||||
declare const PermissionsAndroidInstance: PermissionsAndroid;
|
declare const PermissionsAndroidInstance: PermissionsAndroidImpl;
|
||||||
declare export default typeof PermissionsAndroidInstance;
|
declare export default typeof PermissionsAndroidInstance;
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
@@ -6433,8 +6432,8 @@ declare export default typeof AppContainer;
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`public API should not change unintentionally Libraries/ReactNative/AppRegistry.flow.js 1`] = `
|
exports[`public API should not change unintentionally Libraries/ReactNative/AppRegistry.flow.js 1`] = `
|
||||||
"type Task = (taskData: any) => Promise<void>;
|
"type HeadlessTask = (taskData: any) => Promise<void>;
|
||||||
export type TaskProvider = () => Task;
|
export type TaskProvider = () => HeadlessTask;
|
||||||
export type ComponentProvider = () => React.ComponentType<any>;
|
export type ComponentProvider = () => React.ComponentType<any>;
|
||||||
export type ComponentProviderInstrumentationHook = (
|
export type ComponentProviderInstrumentationHook = (
|
||||||
component_: ComponentProvider,
|
component_: ComponentProvider,
|
||||||
@@ -8364,7 +8363,7 @@ declare export default typeof NativeDevLoadingView;
|
|||||||
|
|
||||||
exports[`public API should not change unintentionally Libraries/Utilities/NativeDeviceInfo.js 1`] = `
|
exports[`public API should not change unintentionally Libraries/Utilities/NativeDeviceInfo.js 1`] = `
|
||||||
"export * from \\"../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo\\";
|
"export * from \\"../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo\\";
|
||||||
declare export default typeof NativeDeviceInfo;
|
export { default } from \\"../../src/private/specs_DEPRECATED/modules/NativeDeviceInfo\\";
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -8655,7 +8654,7 @@ exports[`public API should not change unintentionally Libraries/Utilities/codege
|
|||||||
paperComponentNameDeprecated?: string,
|
paperComponentNameDeprecated?: string,
|
||||||
excludedPlatforms?: $ReadOnlyArray<\\"iOS\\" | \\"android\\">,
|
excludedPlatforms?: $ReadOnlyArray<\\"iOS\\" | \\"android\\">,
|
||||||
}>;
|
}>;
|
||||||
export type NativeComponentType<T> = HostComponent<T>;
|
export type NativeComponentType<T: { ... }> = HostComponent<T>;
|
||||||
declare function codegenNativeComponent<Props: { ... }>(
|
declare function codegenNativeComponent<Props: { ... }>(
|
||||||
componentName: string,
|
componentName: string,
|
||||||
options?: Options
|
options?: Options
|
||||||
@@ -8960,12 +8959,12 @@ declare export default ErrorUtils;
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`public API should not change unintentionally Libraries/vendor/emitter/EventEmitter.js 1`] = `
|
exports[`public API should not change unintentionally Libraries/vendor/emitter/EventEmitter.js 1`] = `
|
||||||
"type UnsafeObject = Object;
|
"type UnsafeEventObject = Object;
|
||||||
export interface EventSubscription {
|
export interface EventSubscription {
|
||||||
remove(): void;
|
remove(): void;
|
||||||
}
|
}
|
||||||
export interface IEventEmitter<
|
export interface IEventEmitter<
|
||||||
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
|
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
|
||||||
> {
|
> {
|
||||||
addListener<TEvent: $Keys<TEventToArgsMap>>(
|
addListener<TEvent: $Keys<TEventToArgsMap>>(
|
||||||
eventType: TEvent,
|
eventType: TEvent,
|
||||||
@@ -8981,8 +8980,8 @@ export interface IEventEmitter<
|
|||||||
}
|
}
|
||||||
declare export default class EventEmitter<
|
declare export default class EventEmitter<
|
||||||
TEventToArgsMap: $ReadOnly<
|
TEventToArgsMap: $ReadOnly<
|
||||||
Record<string, $ReadOnlyArray<UnsafeObject>>,
|
Record<string, $ReadOnlyArray<UnsafeEventObject>>,
|
||||||
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
|
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
|
||||||
> implements IEventEmitter<TEventToArgsMap>
|
> implements IEventEmitter<TEventToArgsMap>
|
||||||
{
|
{
|
||||||
constructor(): void;
|
constructor(): void;
|
||||||
@@ -9062,6 +9061,8 @@ export type {
|
|||||||
export { default as RefreshControl } from \\"./Libraries/Components/RefreshControl/RefreshControl\\";
|
export { default as RefreshControl } from \\"./Libraries/Components/RefreshControl/RefreshControl\\";
|
||||||
export { default as SafeAreaView } from \\"./Libraries/Components/SafeAreaView/SafeAreaView\\";
|
export { default as SafeAreaView } from \\"./Libraries/Components/SafeAreaView/SafeAreaView\\";
|
||||||
export type {
|
export type {
|
||||||
|
ScrollViewImperativeMethods,
|
||||||
|
ScrollViewScrollToOptions,
|
||||||
ScrollResponderType,
|
ScrollResponderType,
|
||||||
ScrollViewProps,
|
ScrollViewProps,
|
||||||
ScrollViewPropsAndroid,
|
ScrollViewPropsAndroid,
|
||||||
@@ -9348,6 +9349,11 @@ export type {
|
|||||||
PublicRootInstance,
|
PublicRootInstance,
|
||||||
PublicTextInstance,
|
PublicTextInstance,
|
||||||
} from \\"./Libraries/ReactPrivate/ReactNativePrivateInterface\\";
|
} from \\"./Libraries/ReactPrivate/ReactNativePrivateInterface\\";
|
||||||
|
export {
|
||||||
|
default as unstable_VirtualView,
|
||||||
|
VirtualViewMode,
|
||||||
|
} from \\"./src/private/components/virtualview/VirtualView\\";
|
||||||
|
export type { ModeChangeEvent } from \\"./src/private/components/virtualview/VirtualView\\";
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import type {TransformVisitor} from 'hermes-transform';
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
visitors: stripPrivateProperties,
|
visitors: stripPrivateProperties,
|
||||||
} = require('../../../../scripts/build-types/transforms/stripPrivateProperties');
|
} = require('../../../../scripts/build-types/transforms/flow/stripPrivateProperties');
|
||||||
const translate = require('flow-api-translator');
|
const translate = require('flow-api-translator');
|
||||||
const {existsSync, promises: fs} = require('fs');
|
const {existsSync, promises: fs} = require('fs');
|
||||||
const glob = require('glob');
|
const glob = require('glob');
|
||||||
|
|||||||
@@ -9,14 +9,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// $FlowFixMe[unclear-type] unclear type of events
|
// $FlowFixMe[unclear-type] unclear type of events
|
||||||
type UnsafeObject = Object;
|
type UnsafeEventObject = Object;
|
||||||
|
|
||||||
export interface EventSubscription {
|
export interface EventSubscription {
|
||||||
remove(): void;
|
remove(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEventEmitter<
|
export interface IEventEmitter<
|
||||||
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
|
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
|
||||||
> {
|
> {
|
||||||
addListener<TEvent: $Keys<TEventToArgsMap>>(
|
addListener<TEvent: $Keys<TEventToArgsMap>>(
|
||||||
eventType: TEvent,
|
eventType: TEvent,
|
||||||
@@ -41,7 +41,7 @@ interface Registration<TArgs> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Registry<
|
type Registry<
|
||||||
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
|
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
|
||||||
> = {
|
> = {
|
||||||
[K in keyof TEventToArgsMap]: Set<Registration<TEventToArgsMap[K]>>,
|
[K in keyof TEventToArgsMap]: Set<Registration<TEventToArgsMap[K]>>,
|
||||||
};
|
};
|
||||||
@@ -68,8 +68,8 @@ type Registry<
|
|||||||
*/
|
*/
|
||||||
export default class EventEmitter<
|
export default class EventEmitter<
|
||||||
TEventToArgsMap: $ReadOnly<
|
TEventToArgsMap: $ReadOnly<
|
||||||
Record<string, $ReadOnlyArray<UnsafeObject>>,
|
Record<string, $ReadOnlyArray<UnsafeEventObject>>,
|
||||||
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
|
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
|
||||||
> implements IEventEmitter<TEventToArgsMap>
|
> implements IEventEmitter<TEventToArgsMap>
|
||||||
{
|
{
|
||||||
#registry: Registry<TEventToArgsMap>;
|
#registry: Registry<TEventToArgsMap>;
|
||||||
@@ -157,7 +157,7 @@ export default class EventEmitter<
|
|||||||
}
|
}
|
||||||
|
|
||||||
function allocate<
|
function allocate<
|
||||||
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeObject>>>,
|
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
|
||||||
TEvent: $Keys<TEventToArgsMap>,
|
TEvent: $Keys<TEventToArgsMap>,
|
||||||
TEventArgs: TEventToArgsMap[TEvent],
|
TEventArgs: TEventToArgsMap[TEvent],
|
||||||
>(
|
>(
|
||||||
|
|||||||
@@ -336,7 +336,10 @@ let reactRuntime = RNTarget(
|
|||||||
name: .reactRuntime,
|
name: .reactRuntime,
|
||||||
path: "ReactCommon/react/runtime",
|
path: "ReactCommon/react/runtime",
|
||||||
excludedPaths: ["tests", "iostests", "platform"],
|
excludedPaths: ["tests", "iostests", "platform"],
|
||||||
dependencies: [.reactNativeDependencies, .jsi, .reactJsiExecutor, .reactCxxReact, .reactJsErrorHandler, .reactPerformanceTimeline, .reactUtils, .reactFeatureFlags, .reactJsInspector, .reactJsiTooling, .reactHermes, .reactRuntimeScheduler, .hermesPrebuilt]
|
dependencies: [.reactNativeDependencies, .jsi, .reactJsiExecutor, .reactCxxReact, .reactJsErrorHandler, .reactPerformanceTimeline, .reactUtils, .reactFeatureFlags, .reactJsInspector, .reactJsiTooling, .reactHermes, .reactRuntimeScheduler, .hermesPrebuilt],
|
||||||
|
defines: [
|
||||||
|
CXXSetting.define("HERMES_ENABLE_DEBUGGER", to: "1", .when(configuration: BuildConfiguration.debug))
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
/// React-runtimeApple.podspec
|
/// React-runtimeApple.podspec
|
||||||
@@ -394,6 +397,7 @@ let reactFabric = RNTarget(
|
|||||||
"components/textinput",
|
"components/textinput",
|
||||||
"components/textinput/platform/ios/",
|
"components/textinput/platform/ios/",
|
||||||
"components/unimplementedview",
|
"components/unimplementedview",
|
||||||
|
"components/virtualview",
|
||||||
"components/root/tests",
|
"components/root/tests",
|
||||||
],
|
],
|
||||||
dependencies: [.reactNativeDependencies, .reactJsiExecutor, .rctTypesafety, .reactTurboModuleCore, .jsi, .logger, .reactDebug, .reactFeatureFlags, .reactUtils, .reactRuntimeScheduler, .reactCxxReact, .reactRendererDebug, .reactGraphics, .yoga],
|
dependencies: [.reactNativeDependencies, .reactJsiExecutor, .rctTypesafety, .reactTurboModuleCore, .jsi, .logger, .reactDebug, .reactFeatureFlags, .reactUtils, .reactRuntimeScheduler, .reactCxxReact, .reactRendererDebug, .reactGraphics, .yoga],
|
||||||
@@ -412,6 +416,8 @@ let reactFabricComponents = RNTarget(
|
|||||||
name: .reactFabricComponents,
|
name: .reactFabricComponents,
|
||||||
path: "ReactCommon/react/renderer",
|
path: "ReactCommon/react/renderer",
|
||||||
excludedPaths: [
|
excludedPaths: [
|
||||||
|
"components/modal/platform/android",
|
||||||
|
"components/modal/platform/cxx",
|
||||||
"components/view/platform/android",
|
"components/view/platform/android",
|
||||||
"components/view/platform/windows",
|
"components/view/platform/windows",
|
||||||
"components/view/platform/macos",
|
"components/view/platform/macos",
|
||||||
@@ -427,7 +433,7 @@ let reactFabricComponents = RNTarget(
|
|||||||
"conponents/rncore", // this was the old folder where RN Core Components were generated. If you ran codegen in the past, you might have some files in it that might make the build fail.
|
"conponents/rncore", // this was the old folder where RN Core Components were generated. If you ran codegen in the past, you might have some files in it that might make the build fail.
|
||||||
],
|
],
|
||||||
dependencies: [.reactNativeDependencies, .reactCore, .reactJsiExecutor, .reactTurboModuleCore, .jsi, .logger, .reactDebug, .reactFeatureFlags, .reactUtils, .reactRuntimeScheduler, .reactCxxReact, .yoga, .reactRendererDebug, .reactGraphics, .reactFabric, .reactTurboModuleBridging],
|
dependencies: [.reactNativeDependencies, .reactCore, .reactJsiExecutor, .reactTurboModuleCore, .jsi, .logger, .reactDebug, .reactFeatureFlags, .reactUtils, .reactRuntimeScheduler, .reactCxxReact, .yoga, .reactRendererDebug, .reactGraphics, .reactFabric, .reactTurboModuleBridging],
|
||||||
sources: ["components/inputaccessory", "components/modal", "components/safeareaview", "components/text", "components/text/platform/cxx", "components/textinput", "components/textinput/platform/ios/", "components/unimplementedview", "textlayoutmanager", "textlayoutmanager/platform/ios"]
|
sources: ["components/inputaccessory", "components/modal", "components/safeareaview", "components/text", "components/text/platform/cxx", "components/textinput", "components/textinput/platform/ios/", "components/unimplementedview", "components/virtualview", "textlayoutmanager", "textlayoutmanager/platform/ios"]
|
||||||
)
|
)
|
||||||
|
|
||||||
/// React-FabricImage.podspec
|
/// React-FabricImage.podspec
|
||||||
@@ -489,6 +495,14 @@ let reactRCTNetwork = RNTarget(
|
|||||||
dependencies: [.yoga, .jsi, .reactTurboModuleCore]
|
dependencies: [.yoga, .jsi, .reactTurboModuleCore]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/// React-RCTVibration.podspec
|
||||||
|
let reactRCTVibration = RNTarget(
|
||||||
|
name: .reactRCTVibration,
|
||||||
|
path: "Libraries/Vibration",
|
||||||
|
linkedFrameworks: ["AudioToolbox"],
|
||||||
|
dependencies: [.yoga, .jsi, .reactTurboModuleCore]
|
||||||
|
)
|
||||||
|
|
||||||
/// React-RCTAppDelegate.podspec
|
/// React-RCTAppDelegate.podspec
|
||||||
let reactAppDelegate = RNTarget(
|
let reactAppDelegate = RNTarget(
|
||||||
name: .reactAppDelegate,
|
name: .reactAppDelegate,
|
||||||
@@ -554,6 +568,7 @@ let targets = [
|
|||||||
reactRCTText,
|
reactRCTText,
|
||||||
reactRCTBlob,
|
reactRCTBlob,
|
||||||
reactRCTNetwork,
|
reactRCTNetwork,
|
||||||
|
reactRCTVibration,
|
||||||
reactRCTLinking,
|
reactRCTLinking,
|
||||||
reactCoreModules,
|
reactCoreModules,
|
||||||
reactTurboModuleBridging,
|
reactTurboModuleBridging,
|
||||||
@@ -725,6 +740,7 @@ extension String {
|
|||||||
static let reactRCTText = "React-RCTText"
|
static let reactRCTText = "React-RCTText"
|
||||||
static let reactRCTBlob = "React-RCTBlob"
|
static let reactRCTBlob = "React-RCTBlob"
|
||||||
static let reactRCTNetwork = "React-RCTNetwork"
|
static let reactRCTNetwork = "React-RCTNetwork"
|
||||||
|
static let reactRCTVibration = "React-RCTVibration"
|
||||||
static let reactRCTActionSheet = "React-RCTActionSheet" // Empty target
|
static let reactRCTActionSheet = "React-RCTActionSheet" // Empty target
|
||||||
static let reactRCTLinking = "React-RCTLinking"
|
static let reactRCTLinking = "React-RCTLinking"
|
||||||
static let reactCoreModules = "React-CoreModules"
|
static let reactCoreModules = "React-CoreModules"
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
require "json"
|
||||||
|
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
||||||
|
version = package['version']
|
||||||
|
|
||||||
|
source = ReactNativeCoreUtils.resolve_podspec_source()
|
||||||
|
Pod::Spec.new do |s|
|
||||||
|
s.name = "React-Core-prebuilt"
|
||||||
|
s.version = version
|
||||||
|
s.summary = "The core of React Native prebuilt frameworks."
|
||||||
|
s.homepage = "https://reactnative.dev/"
|
||||||
|
s.license = package["license"]
|
||||||
|
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||||
|
s.platforms = min_supported_versions
|
||||||
|
s.source = source
|
||||||
|
s.vendored_frameworks = "React.xcframework"
|
||||||
|
|
||||||
|
s.preserve_paths = '**/*.*'
|
||||||
|
s.header_mappings_dir = 'React.xcframework/Headers'
|
||||||
|
s.source_files = 'React.xcframework/Headers/**/*.{h,hpp}'
|
||||||
|
|
||||||
|
s.module_name = 'React'
|
||||||
|
s.module_map = 'React.xcframework/Modules/module.modulemap'
|
||||||
|
s.public_header_files = 'React.xcframework/Headers/**/*.h'
|
||||||
|
|
||||||
|
add_rn_third_party_dependencies(s)
|
||||||
|
|
||||||
|
# We need to make sure that the React.xcframework is copied correctly - in the downloaded tarball
|
||||||
|
# the root directory is the framework, but when using it we need to have it in a subdirectory
|
||||||
|
# called React.xcframework, so we need to move the contents of the tarball into that directory.
|
||||||
|
# This is done in the prepare_command.
|
||||||
|
# We need to make sure that the headers are copied to the right place - local tar.gz has a different structure
|
||||||
|
# than the one from the maven repo
|
||||||
|
s.prepare_command = <<~'CMD'
|
||||||
|
CURRENT_PATH=$(pwd)
|
||||||
|
XCFRAMEWORK_PATH="${CURRENT_PATH}/React.xcframework"
|
||||||
|
|
||||||
|
# Check if XCFRAMEWORK_PATH is empty
|
||||||
|
if [ -z "$XCFRAMEWORK_PATH" ]; then
|
||||||
|
echo "ERROR: XCFRAMEWORK_PATH is empty."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${XCFRAMEWORK_PATH}"
|
||||||
|
find "$CURRENT_PATH" -mindepth 1 -maxdepth 1 ! -name "$(basename "$XCFRAMEWORK_PATH")" -exec mv {} "$XCFRAMEWORK_PATH" \;
|
||||||
|
CMD
|
||||||
|
|
||||||
|
# If we are passing a local tarball, we don't want to switch between Debug and Release
|
||||||
|
if !ENV["RCT_TESTONLY_RNCORE_TARBALL_PATH"]
|
||||||
|
script_phase = {
|
||||||
|
:name => "[RNDeps] Replace React Native Core for the right configuration, if needed",
|
||||||
|
:execution_position => :before_compile,
|
||||||
|
:script => <<-EOS
|
||||||
|
. "$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh"
|
||||||
|
|
||||||
|
CONFIG="Release"
|
||||||
|
if echo $GCC_PREPROCESSOR_DEFINITIONS | grep -q "DEBUG=1"; then
|
||||||
|
CONFIG="Debug"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO(T228219721): Add this for React Native Core as well
|
||||||
|
##### "$NODE_BINARY" "$REACT_NATIVE_PATH/third-party-podspecs/replace_dependencies_version.js" -c "$CONFIG" -r "#{version}" -p "$PODS_ROOT"
|
||||||
|
EOS
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# :always_out_of_date is only available in CocoaPods 1.13.0 and later
|
||||||
|
if Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.13.0')
|
||||||
|
# always run the script without warning
|
||||||
|
script_phase[:always_out_of_date] = "1"
|
||||||
|
end
|
||||||
|
|
||||||
|
s.script_phase = script_phase
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -66,7 +66,7 @@ Pod::Spec.new do |s|
|
|||||||
s.default_subspec = "Default"
|
s.default_subspec = "Default"
|
||||||
|
|
||||||
s.subspec "Default" do |ss|
|
s.subspec "Default" do |ss|
|
||||||
ss.source_files = "React/**/*.{c,h,m,mm,S,cpp}"
|
ss.source_files = podspec_sources("React/**/*.{c,h,m,mm,S,cpp}", "React/**/*.h")
|
||||||
exclude_files = [
|
exclude_files = [
|
||||||
"React/CoreModules/**/*",
|
"React/CoreModules/**/*",
|
||||||
"React/DevSupport/**/*",
|
"React/DevSupport/**/*",
|
||||||
@@ -76,17 +76,24 @@ Pod::Spec.new do |s|
|
|||||||
"React/Inspector/**/*",
|
"React/Inspector/**/*",
|
||||||
"React/Runtime/**/*",
|
"React/Runtime/**/*",
|
||||||
]
|
]
|
||||||
|
|
||||||
# The default is use hermes, we don't have jsc installed
|
# The default is use hermes, we don't have jsc installed
|
||||||
exclude_files = exclude_files.append("React/CxxBridge/JSCExecutorFactory.{h,mm}")
|
exclude_files = exclude_files.append("React/CxxBridge/JSCExecutorFactory.{h,mm}")
|
||||||
|
|
||||||
ss.exclude_files = exclude_files
|
ss.exclude_files = exclude_files
|
||||||
ss.private_header_files = "React/Cxx*/*.h"
|
ss.private_header_files = "React/Cxx*/*.h"
|
||||||
|
|
||||||
|
# Include prebuilt if we're not building from source
|
||||||
|
if !ReactNativeCoreUtils.build_rncore_from_source()
|
||||||
|
ss.dependency "React-Core-prebuilt", version
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
s.subspec "DevSupport" do |ss|
|
s.subspec "DevSupport" do |ss|
|
||||||
ss.source_files = "React/DevSupport/*.{h,mm,m}",
|
ss.source_files = podspec_sources(["React/DevSupport/*.{h,mm,m}",
|
||||||
"React/Inspector/*.{h,mm,m}"
|
"React/Inspector/*.{h,mm,m}"],
|
||||||
|
["React/DevSupport/*.h",
|
||||||
|
"React/Inspector/*.h"])
|
||||||
|
|
||||||
ss.dependency "React-Core/Default", version
|
ss.dependency "React-Core/Default", version
|
||||||
ss.dependency "React-Core/RCTWebSocket", version
|
ss.dependency "React-Core/RCTWebSocket", version
|
||||||
@@ -94,7 +101,7 @@ Pod::Spec.new do |s|
|
|||||||
end
|
end
|
||||||
|
|
||||||
s.subspec "RCTWebSocket" do |ss|
|
s.subspec "RCTWebSocket" do |ss|
|
||||||
ss.source_files = "Libraries/WebSocket/*.{h,m}"
|
ss.source_files = podspec_sources("Libraries/WebSocket/*.{h,m}", "Libraries/WebSocket/*.h")
|
||||||
ss.dependency "React-Core/Default", version
|
ss.dependency "React-Core/Default", version
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <tgmath.h>
|
|
||||||
|
|
||||||
#import <CoreGraphics/CoreGraphics.h>
|
#import <CoreGraphics/CoreGraphics.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ Pod::Spec.new do |s|
|
|||||||
s.compiler_flags = '-Wno-nullability-completeness'
|
s.compiler_flags = '-Wno-nullability-completeness'
|
||||||
s.source = source
|
s.source = source
|
||||||
|
|
||||||
s.source_files = "**/*.{c,m,mm,cpp}"
|
s.source_files = podspec_sources("**/*.{c,m,mm,cpp}", "**/*.h")
|
||||||
|
|
||||||
s.ios.exclude_files = "PlatformStubs/**/*"
|
s.ios.exclude_files = "PlatformStubs/**/*"
|
||||||
exclude_files = ["RCTStatusBarManager.mm"]
|
exclude_files = ["RCTStatusBarManager.mm"]
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef RCT_FIT_RM_OLD_RUNTIME
|
|
||||||
|
|
||||||
#include <jsireact/JSIExecutor.h>
|
|
||||||
|
|
||||||
namespace facebook::react {
|
|
||||||
|
|
||||||
class JSCExecutorFactory : public JSExecutorFactory {
|
|
||||||
public:
|
|
||||||
explicit JSCExecutorFactory(JSIExecutor::RuntimeInstaller runtimeInstaller)
|
|
||||||
: runtimeInstaller_(std::move(runtimeInstaller)) {}
|
|
||||||
|
|
||||||
std::unique_ptr<JSExecutor> createJSExecutor(
|
|
||||||
std::shared_ptr<ExecutorDelegate> delegate,
|
|
||||||
std::shared_ptr<MessageQueueThread> jsQueue) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
JSIExecutor::RuntimeInstaller runtimeInstaller_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace facebook::react
|
|
||||||
|
|
||||||
#endif // RCT_FIT_RM_OLD_RUNTIME
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 "JSCExecutorFactory.h"
|
|
||||||
|
|
||||||
#ifndef RCT_FIT_RM_OLD_RUNTIME
|
|
||||||
|
|
||||||
#import <jsc/JSCRuntime.h>
|
|
||||||
|
|
||||||
#import <memory>
|
|
||||||
|
|
||||||
namespace facebook::react {
|
|
||||||
|
|
||||||
std::unique_ptr<JSExecutor> JSCExecutorFactory::createJSExecutor(
|
|
||||||
std::shared_ptr<ExecutorDelegate> delegate,
|
|
||||||
std::shared_ptr<MessageQueueThread> __unused jsQueue)
|
|
||||||
{
|
|
||||||
return std::make_unique<JSIExecutor>(
|
|
||||||
facebook::jsc::makeJSCRuntime(), delegate, JSIExecutor::defaultTimeoutInvoker, runtimeInstaller_);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace facebook::react
|
|
||||||
|
|
||||||
#endif // RCT_FIT_RM_OLD_RUNTIME
|
|
||||||
-2
@@ -22,8 +22,6 @@
|
|||||||
}
|
}
|
||||||
_touchHandler = [RCTSurfaceTouchHandler new];
|
_touchHandler = [RCTSurfaceTouchHandler new];
|
||||||
|
|
||||||
self.modalInPresentation = YES;
|
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
@@ -124,6 +124,7 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
|||||||
_viewController = [RCTFabricModalHostViewController new];
|
_viewController = [RCTFabricModalHostViewController new];
|
||||||
_viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
|
_viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
|
||||||
_viewController.delegate = self;
|
_viewController.delegate = self;
|
||||||
|
_viewController.modalInPresentation = YES;
|
||||||
}
|
}
|
||||||
return _viewController;
|
return _viewController;
|
||||||
}
|
}
|
||||||
@@ -239,6 +240,7 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
|||||||
|
|
||||||
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
|
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
|
||||||
{
|
{
|
||||||
|
const auto &oldViewProps = static_cast<const ModalHostViewProps &>(*_props);
|
||||||
const auto &newProps = static_cast<const ModalHostViewProps &>(*props);
|
const auto &newProps = static_cast<const ModalHostViewProps &>(*props);
|
||||||
|
|
||||||
#if !TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
@@ -251,6 +253,10 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
|||||||
|
|
||||||
self.viewController.modalPresentationStyle = presentationConfiguration(newProps);
|
self.viewController.modalPresentationStyle = presentationConfiguration(newProps);
|
||||||
|
|
||||||
|
if (oldViewProps.allowSwipeDismissal != newProps.allowSwipeDismissal) {
|
||||||
|
self.viewController.modalInPresentation = !newProps.allowSwipeDismissal;
|
||||||
|
}
|
||||||
|
|
||||||
_shouldPresent = newProps.visible;
|
_shouldPresent = newProps.visible;
|
||||||
[self ensurePresentedOnlyIfNeeded];
|
[self ensurePresentedOnlyIfNeeded];
|
||||||
|
|
||||||
@@ -283,6 +289,16 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
|
||||||
|
{
|
||||||
|
auto eventEmitter = [self modalEventEmitter];
|
||||||
|
const auto &props = static_cast<const ModalHostViewProps &>(*_props);
|
||||||
|
|
||||||
|
if (eventEmitter && props.allowSwipeDismissal) {
|
||||||
|
eventEmitter->onRequestClose({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user