@office-iss/react-native-win32 0.75.2 → 0.76.0-preview.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/.eslintrc.js +11 -0
  2. package/.flowconfig +5 -4
  3. package/CHANGELOG.json +191 -47
  4. package/CHANGELOG.md +63 -28
  5. package/Libraries/Alert/Alert.js +3 -0
  6. package/Libraries/Animated/AnimatedEvent.js +1 -1
  7. package/Libraries/Animated/AnimatedImplementation.js +7 -7
  8. package/Libraries/Animated/NativeAnimatedAllowlist.js +111 -0
  9. package/Libraries/Animated/animations/Animation.js +11 -1
  10. package/Libraries/Animated/animations/DecayAnimation.js +1 -1
  11. package/Libraries/Animated/animations/SpringAnimation.js +1 -1
  12. package/Libraries/Animated/animations/TimingAnimation.js +2 -1
  13. package/Libraries/Animated/components/AnimatedScrollView.js +3 -2
  14. package/Libraries/Animated/createAnimatedComponent.js +10 -9
  15. package/Libraries/Animated/nodes/AnimatedColor.js +1 -1
  16. package/Libraries/Animated/nodes/AnimatedInterpolation.js +3 -2
  17. package/Libraries/Animated/nodes/AnimatedNode.js +42 -33
  18. package/Libraries/Animated/nodes/AnimatedObject.js +56 -50
  19. package/Libraries/Animated/nodes/AnimatedProps.js +77 -40
  20. package/Libraries/Animated/nodes/AnimatedStyle.js +103 -59
  21. package/Libraries/Animated/nodes/AnimatedTracking.js +1 -1
  22. package/Libraries/Animated/nodes/AnimatedTransform.js +102 -67
  23. package/Libraries/Animated/nodes/AnimatedValue.js +2 -1
  24. package/Libraries/Animated/nodes/AnimatedWithChildren.js +21 -22
  25. package/Libraries/Animated/useAnimatedProps.js +142 -7
  26. package/Libraries/BatchedBridge/NativeModules.js +2 -0
  27. package/Libraries/Blob/FileReader.js +1 -1
  28. package/Libraries/Blob/URL.js +2 -62
  29. package/Libraries/Blob/URLSearchParams.js +71 -0
  30. package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +1 -1
  31. package/Libraries/Components/Keyboard/KeyboardAvoidingView.js +17 -0
  32. package/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js +1 -1
  33. package/Libraries/Components/ScrollView/ScrollView.js +131 -169
  34. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +3 -0
  35. package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +1 -1
  36. package/Libraries/Components/StatusBar/StatusBar.js +3 -1
  37. package/Libraries/Components/TextInput/RCTTextInputViewConfig.js +10 -0
  38. package/Libraries/Components/TextInput/TextInput.d.ts +32 -2
  39. package/Libraries/Components/TextInput/TextInput.js +230 -94
  40. package/Libraries/Components/TextInput/TextInput.win32.js +230 -100
  41. package/Libraries/Components/View/ReactNativeStyleAttributes.js +23 -1
  42. package/Libraries/Components/View/ReactNativeViewAttributes.js +2 -0
  43. package/Libraries/Components/View/ReactNativeViewAttributes.win32.js +2 -0
  44. package/Libraries/Components/View/ViewAccessibility.d.ts +15 -0
  45. package/Libraries/Components/View/ViewNativeComponent.js +0 -1
  46. package/Libraries/Components/View/ViewPropTypes.js +14 -0
  47. package/Libraries/Components/View/ViewPropTypes.win32.js +14 -0
  48. package/Libraries/Core/ExceptionsManager.js +2 -0
  49. package/Libraries/Core/InitializeCore.js +3 -1
  50. package/Libraries/Core/ReactFiberErrorDialog.js +3 -0
  51. package/Libraries/Core/ReactNativeVersion.js +4 -4
  52. package/Libraries/Core/ReactNativeVersionCheck.win32.js +1 -1
  53. package/Libraries/Core/setUpDeveloperTools.js +5 -1
  54. package/Libraries/Core/setUpErrorHandling.js +7 -1
  55. package/Libraries/Core/setUpGlobals.js +1 -0
  56. package/Libraries/Core/setUpReactRefresh.js +0 -4
  57. package/Libraries/Image/AssetSourceResolver.js +28 -1
  58. package/Libraries/Image/Image.android.js +9 -14
  59. package/Libraries/Image/Image.ios.js +11 -22
  60. package/Libraries/Image/Image.win32.js +11 -24
  61. package/Libraries/Image/ImageBackground.js +1 -8
  62. package/Libraries/Image/ImageUtils.js +9 -9
  63. package/Libraries/Image/ImageViewNativeComponent.js +1 -0
  64. package/Libraries/Inspector/Inspector.js +3 -2
  65. package/Libraries/Inspector/Inspector.win32.js +3 -2
  66. package/Libraries/Inspector/InspectorPanel.js +16 -10
  67. package/Libraries/Inspector/NetworkOverlay.js +1 -1
  68. package/Libraries/Interaction/TaskQueue.js +1 -0
  69. package/Libraries/Lists/FlatList.js +1 -1
  70. package/Libraries/Lists/SectionList.js +2 -2
  71. package/Libraries/Lists/SectionListModern.js +3 -3
  72. package/Libraries/LogBox/Data/LogBoxData.js +24 -3
  73. package/Libraries/LogBox/LogBoxNotificationContainer.js +3 -2
  74. package/Libraries/LogBox/UI/LogBoxInspectorHeader.js +9 -8
  75. package/Libraries/LogBox/UI/LogBoxInspectorHeader.win32.js +9 -29
  76. package/Libraries/Modal/Modal.js +0 -1
  77. package/Libraries/NativeComponent/BaseViewConfig.android.js +9 -1
  78. package/Libraries/NativeComponent/BaseViewConfig.ios.js +17 -1
  79. package/Libraries/NativeComponent/BaseViewConfig.win32.js +17 -1
  80. package/Libraries/NativeComponent/NativeComponentRegistry.js +22 -22
  81. package/Libraries/NativeComponent/StaticViewConfigValidator.js +0 -21
  82. package/Libraries/Network/XMLHttpRequest.js +4 -2
  83. package/Libraries/ReactNative/AppContainer-dev.js +1 -5
  84. package/Libraries/ReactNative/AppContainer-prod.js +1 -5
  85. package/Libraries/ReactNative/AppContainer.js +0 -1
  86. package/Libraries/ReactNative/AppRegistry.js +0 -6
  87. package/Libraries/ReactNative/BridgelessUIManager.js +1 -0
  88. package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricHostComponent.js +1 -1
  89. package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricPublicInstance.js +5 -5
  90. package/Libraries/ReactNative/RendererImplementation.js +26 -4
  91. package/Libraries/ReactNative/getNativeComponentAttributes.js +12 -0
  92. package/Libraries/ReactNative/renderApplication.js +0 -2
  93. package/Libraries/Renderer/shims/ReactNativeTypes.js +11 -4
  94. package/Libraries/StyleSheet/StyleSheet.js +1 -1
  95. package/Libraries/StyleSheet/StyleSheet.win32.js +1 -1
  96. package/Libraries/StyleSheet/StyleSheetTypes.d.ts +152 -2
  97. package/Libraries/StyleSheet/StyleSheetTypes.js +60 -5
  98. package/Libraries/StyleSheet/processBackgroundImage.js +384 -0
  99. package/Libraries/StyleSheet/processBoxShadow.js +209 -0
  100. package/Libraries/StyleSheet/processFilter.js +231 -42
  101. package/Libraries/Text/Text.js +394 -196
  102. package/Libraries/Text/Text.win32.js +442 -229
  103. package/Libraries/Text/TextNativeComponent.js +2 -1
  104. package/Libraries/Text/TextNativeComponent.win32.js +1 -1
  105. package/Libraries/TurboModule/TurboModuleRegistry.js +13 -50
  106. package/Libraries/Types/CodegenTypes.js +3 -1
  107. package/Libraries/Utilities/Appearance.js +108 -84
  108. package/Libraries/Utilities/DevLoadingView.js +2 -4
  109. package/Libraries/Utilities/HMRClient.js +8 -6
  110. package/Libraries/Utilities/ReactNativeTestTools.js +1 -1
  111. package/Libraries/Utilities/createPerformanceLogger.js +0 -9
  112. package/Libraries/Utilities/stringifyViewConfig.js +22 -0
  113. package/Libraries/Utilities/useColorScheme.js +3 -3
  114. package/Libraries/WebSocket/WebSocket.js +1 -1
  115. package/Libraries/promiseRejectionTrackingOptions.js +1 -1
  116. package/Libraries/vendor/emitter/EventEmitter.js +6 -5
  117. package/flow/jest.js +2 -2
  118. package/index.js +3 -1
  119. package/index.win32.js +3 -1
  120. package/jest/mockComponent.js +4 -1
  121. package/jest/mockModal.js +1 -3
  122. package/jest/mockScrollView.js +1 -1
  123. package/jest/renderer.js +2 -2
  124. package/jest/setup.js +16 -13
  125. package/jest.config.js +1 -2
  126. package/overrides.json +22 -22
  127. package/package.json +32 -30
  128. package/src/private/animated/NativeAnimatedHelper.js +438 -0
  129. package/src/private/animated/NativeAnimatedHelper.win32.js +440 -0
  130. package/src/private/animated/NativeAnimatedValidation.js +64 -0
  131. package/src/private/components/HScrollViewNativeComponents.js +56 -0
  132. package/src/private/components/SafeAreaView_INTERNAL_DO_NOT_USE.js +29 -0
  133. package/src/private/components/VScrollViewNativeComponents.js +48 -0
  134. package/src/private/components/useSyncOnScroll.js +48 -0
  135. package/src/private/featureflags/ReactNativeFeatureFlags.js +166 -16
  136. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +29 -5
  137. package/src/private/fusebox/FuseboxSessionObserver.js +42 -0
  138. package/{Libraries/Core → src/private/renderer/errorhandling}/ErrorHandlers.js +14 -4
  139. package/src/private/setup/setUpDOM.js +28 -0
  140. package/src/private/setup/setUpIntersectionObserver.js +27 -0
  141. package/src/private/setup/setUpMutationObserver.js +26 -0
  142. package/src/private/setup/setUpPerformanceObserver.js +64 -0
  143. package/src/private/specs/modules/NativeAppearance.js +3 -3
  144. package/src/private/specs/modules/NativeLinkingManager.js +1 -1
  145. package/src/private/specs/modules/NativePlatformConstantsWin.js +7 -0
  146. package/src/private/specs/modules/NativeSampleTurboModule.js +14 -1
  147. package/src/private/webapis/dom/nodes/ReadOnlyNode.js +6 -4
  148. package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver}/IntersectionObserver.js +5 -3
  149. package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver}/IntersectionObserverEntry.js +3 -3
  150. package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver}/IntersectionObserverManager.js +14 -17
  151. package/src/private/{specs/modules → webapis/intersectionobserver/specs}/NativeIntersectionObserver.js +2 -2
  152. package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver/specs}/__mocks__/NativeIntersectionObserver.js +4 -4
  153. package/{Libraries/MutationObserver → src/private/webapis/mutationobserver}/MutationObserver.js +5 -3
  154. package/{Libraries/MutationObserver → src/private/webapis/mutationobserver}/MutationObserverManager.js +24 -15
  155. package/{Libraries/MutationObserver → src/private/webapis/mutationobserver}/MutationRecord.js +4 -6
  156. package/src/private/{specs/modules → webapis/mutationobserver/specs}/NativeMutationObserver.js +2 -2
  157. package/{Libraries/MutationObserver → src/private/webapis/mutationobserver/specs}/__mocks__/NativeMutationObserver.js +5 -5
  158. package/src/private/webapis/performance/{EventCounts.js → EventTiming.js} +65 -3
  159. package/src/private/webapis/performance/LongTasks.js +39 -0
  160. package/src/private/webapis/performance/Performance.js +22 -9
  161. package/src/private/webapis/performance/PerformanceEntry.js +36 -18
  162. package/src/private/webapis/performance/PerformanceObserver.js +29 -43
  163. package/src/private/webapis/performance/RawPerformanceEntry.js +24 -1
  164. package/src/private/webapis/performance/UserTiming.js +17 -12
  165. package/src/private/webapis/performance/specs/NativePerformanceObserver.js +1 -1
  166. package/src-win/Libraries/Components/View/ViewAccessibility.d.ts +15 -0
  167. package/types/experimental.d.ts +12 -98
  168. package/Libraries/Animated/NativeAnimatedHelper.js +0 -615
  169. package/Libraries/Animated/NativeAnimatedHelper.win32.js +0 -617
  170. package/Libraries/Core/setUpIntersectionObserver.js +0 -16
  171. package/Libraries/Core/setUpMutationObserver.js +0 -16
  172. package/Libraries/Core/setUpPerformanceObserver.js +0 -18
  173. package/Libraries/IntersectionObserver/NativeIntersectionObserver.js +0 -13
  174. package/Libraries/MutationObserver/NativeMutationObserver.js +0 -13
  175. package/Libraries/Utilities/verifyComponentAttributeEquivalence.js +0 -135
  176. package/src/private/core/setUpDOM.js +0 -18
  177. package/src/private/webapis/performance/PerformanceEventTiming.js +0 -55
  178. /package/src/private/{core → styles}/composeStyles.js +0 -0
@@ -9,6 +9,7 @@
9
9
  */
10
10
 
11
11
  import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
12
+ import type {____TextStyle_Internal as TextStyleInternal} from '../../StyleSheet/StyleSheetTypes';
12
13
  import type {
13
14
  PressEvent,
14
15
  ScrollEvent,
@@ -17,6 +18,7 @@ import type {
17
18
  import type {ViewProps} from '../View/ViewPropTypes';
18
19
  import type {TextInputType} from './TextInput.flow';
19
20
 
21
+ import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
20
22
  import usePressability from '../../Pressability/usePressability';
21
23
  import flattenStyle from '../../StyleSheet/flattenStyle';
22
24
  import StyleSheet, {
@@ -957,8 +959,188 @@ export type Props = $ReadOnly<{|
957
959
  value?: ?Stringish,
958
960
  |}>;
959
961
 
962
+ type ViewCommands = $NonMaybeType<
963
+ | typeof AndroidTextInputCommands
964
+ | typeof RCTMultilineTextInputNativeCommands
965
+ | typeof RCTSinglelineTextInputNativeCommands,
966
+ >;
967
+
968
+ type LastNativeSelection = {|
969
+ selection: Selection,
970
+ mostRecentEventCount: number,
971
+ |};
972
+
960
973
  const emptyFunctionThatReturnsTrue = () => true;
961
974
 
975
+ /**
976
+ * This hook handles the synchronization between the state of the text input
977
+ * in native and in JavaScript. This is necessary due to the asynchronous nature
978
+ * of text input events.
979
+ */
980
+ function useTextInputStateSynchronization_STATE({
981
+ props,
982
+ mostRecentEventCount,
983
+ selection,
984
+ inputRef,
985
+ text,
986
+ viewCommands,
987
+ }: {
988
+ props: Props,
989
+ mostRecentEventCount: number,
990
+ selection: ?Selection,
991
+ inputRef: React.RefObject<null | React.ElementRef<HostComponent<mixed>>>,
992
+ text: string,
993
+ viewCommands: ViewCommands,
994
+ }): {
995
+ setLastNativeText: string => void,
996
+ setLastNativeSelection: LastNativeSelection => void,
997
+ } {
998
+ const [lastNativeText, setLastNativeText] = useState<?Stringish>(props.value);
999
+ const [lastNativeSelectionState, setLastNativeSelection] =
1000
+ useState<LastNativeSelection>({
1001
+ selection: {start: -1, end: -1},
1002
+ mostRecentEventCount: mostRecentEventCount,
1003
+ });
1004
+
1005
+ const lastNativeSelection = lastNativeSelectionState.selection;
1006
+
1007
+ // This is necessary in case native updates the text and JS decides
1008
+ // that the update should be ignored and we should stick with the value
1009
+ // that we have in JS.
1010
+ useLayoutEffect(() => {
1011
+ const nativeUpdate: {text?: string, selection?: Selection} = {};
1012
+
1013
+ if (lastNativeText !== props.value && typeof props.value === 'string') {
1014
+ nativeUpdate.text = props.value;
1015
+ setLastNativeText(props.value);
1016
+ }
1017
+
1018
+ if (
1019
+ selection &&
1020
+ lastNativeSelection &&
1021
+ (lastNativeSelection.start !== selection.start ||
1022
+ lastNativeSelection.end !== selection.end)
1023
+ ) {
1024
+ nativeUpdate.selection = selection;
1025
+ setLastNativeSelection({selection, mostRecentEventCount});
1026
+ }
1027
+
1028
+ if (Object.keys(nativeUpdate).length === 0) {
1029
+ return;
1030
+ }
1031
+
1032
+ if (inputRef.current != null) {
1033
+ viewCommands.setTextAndSelection(
1034
+ inputRef.current,
1035
+ mostRecentEventCount,
1036
+ text,
1037
+ selection?.start ?? -1,
1038
+ selection?.end ?? -1,
1039
+ );
1040
+ }
1041
+ }, [
1042
+ mostRecentEventCount,
1043
+ inputRef,
1044
+ props.value,
1045
+ props.defaultValue,
1046
+ lastNativeText,
1047
+ selection,
1048
+ lastNativeSelection,
1049
+ text,
1050
+ viewCommands,
1051
+ ]);
1052
+
1053
+ return {setLastNativeText, setLastNativeSelection};
1054
+ }
1055
+
1056
+ /**
1057
+ * This hook handles the synchronization between the state of the text input
1058
+ * in native and in JavaScript. This is necessary due to the asynchronous nature
1059
+ * of text input events.
1060
+ */
1061
+ function useTextInputStateSynchronization_REFS({
1062
+ props,
1063
+ mostRecentEventCount,
1064
+ selection,
1065
+ inputRef,
1066
+ text,
1067
+ viewCommands,
1068
+ }: {
1069
+ props: Props,
1070
+ mostRecentEventCount: number,
1071
+ selection: ?Selection,
1072
+ inputRef: React.RefObject<null | React.ElementRef<HostComponent<mixed>>>,
1073
+ text: string,
1074
+ viewCommands: ViewCommands,
1075
+ }): {
1076
+ setLastNativeText: string => void,
1077
+ setLastNativeSelection: LastNativeSelection => void,
1078
+ } {
1079
+ const lastNativeTextRef = useRef<?Stringish>(props.value);
1080
+ const lastNativeSelectionRef = useRef<LastNativeSelection>({
1081
+ selection: {start: -1, end: -1},
1082
+ mostRecentEventCount: mostRecentEventCount,
1083
+ });
1084
+
1085
+ // This is necessary in case native updates the text and JS decides
1086
+ // that the update should be ignored and we should stick with the value
1087
+ // that we have in JS.
1088
+ useLayoutEffect(() => {
1089
+ const nativeUpdate: {text?: string, selection?: Selection} = {};
1090
+
1091
+ const lastNativeSelection = lastNativeSelectionRef.current.selection;
1092
+
1093
+ if (
1094
+ lastNativeTextRef.current !== props.value &&
1095
+ typeof props.value === 'string'
1096
+ ) {
1097
+ nativeUpdate.text = props.value;
1098
+ lastNativeTextRef.current = props.value;
1099
+ }
1100
+
1101
+ if (
1102
+ selection &&
1103
+ lastNativeSelection &&
1104
+ (lastNativeSelection.start !== selection.start ||
1105
+ lastNativeSelection.end !== selection.end)
1106
+ ) {
1107
+ nativeUpdate.selection = selection;
1108
+ lastNativeSelectionRef.current = {selection, mostRecentEventCount};
1109
+ }
1110
+
1111
+ if (Object.keys(nativeUpdate).length === 0) {
1112
+ return;
1113
+ }
1114
+
1115
+ if (inputRef.current != null) {
1116
+ viewCommands.setTextAndSelection(
1117
+ inputRef.current,
1118
+ mostRecentEventCount,
1119
+ text,
1120
+ selection?.start ?? -1,
1121
+ selection?.end ?? -1,
1122
+ );
1123
+ }
1124
+ }, [
1125
+ mostRecentEventCount,
1126
+ inputRef,
1127
+ props.value,
1128
+ props.defaultValue,
1129
+ selection,
1130
+ text,
1131
+ viewCommands,
1132
+ ]);
1133
+
1134
+ return {
1135
+ setLastNativeText: lastNativeText => {
1136
+ lastNativeTextRef.current = lastNativeText;
1137
+ },
1138
+ setLastNativeSelection: lastNativeSelection => {
1139
+ lastNativeSelectionRef.current = lastNativeSelection;
1140
+ },
1141
+ };
1142
+ }
1143
+
962
1144
  /**
963
1145
  * A foundational component for inputting text into the app via a
964
1146
  * keyboard. Props provide configurability for several features, such as
@@ -1089,7 +1271,6 @@ function InternalTextInput(props: Props): React.Node {
1089
1271
 
1090
1272
  const inputRef = useRef<null | React.ElementRef<HostComponent<mixed>>>(null);
1091
1273
 
1092
- // eslint-disable-next-line react-hooks/exhaustive-deps
1093
1274
  const selection: ?Selection =
1094
1275
  propsSelection == null
1095
1276
  ? null
@@ -1098,28 +1279,6 @@ function InternalTextInput(props: Props): React.Node {
1098
1279
  end: propsSelection.end ?? propsSelection.start,
1099
1280
  };
1100
1281
 
1101
- const [mostRecentEventCount, setMostRecentEventCount] = useState<number>(0);
1102
- const [lastNativeText, setLastNativeText] = useState<?Stringish>(props.value);
1103
- const [lastNativeSelectionState, setLastNativeSelection] = useState<{|
1104
- selection: Selection,
1105
- mostRecentEventCount: number,
1106
- |}>({
1107
- selection: {start: -1, end: -1},
1108
- mostRecentEventCount: mostRecentEventCount,
1109
- });
1110
-
1111
- const lastNativeSelection = lastNativeSelectionState.selection;
1112
-
1113
- let viewCommands;
1114
- if (AndroidTextInputCommands) {
1115
- viewCommands = AndroidTextInputCommands;
1116
- } else {
1117
- viewCommands =
1118
- props.multiline === true
1119
- ? RCTMultilineTextInputNativeCommands
1120
- : RCTSinglelineTextInputNativeCommands;
1121
- }
1122
-
1123
1282
  const text =
1124
1283
  typeof props.value === 'string'
1125
1284
  ? props.value
@@ -1127,51 +1286,26 @@ function InternalTextInput(props: Props): React.Node {
1127
1286
  ? props.defaultValue
1128
1287
  : '';
1129
1288
 
1130
- // This is necessary in case native updates the text and JS decides
1131
- // that the update should be ignored and we should stick with the value
1132
- // that we have in JS.
1133
- useLayoutEffect(() => {
1134
- const nativeUpdate: {text?: string, selection?: Selection} = {};
1289
+ const viewCommands =
1290
+ AndroidTextInputCommands ||
1291
+ (props.multiline === true
1292
+ ? RCTMultilineTextInputNativeCommands
1293
+ : RCTSinglelineTextInputNativeCommands);
1135
1294
 
1136
- if (lastNativeText !== props.value && typeof props.value === 'string') {
1137
- nativeUpdate.text = props.value;
1138
- setLastNativeText(props.value);
1139
- }
1140
-
1141
- if (
1142
- selection &&
1143
- lastNativeSelection &&
1144
- (lastNativeSelection.start !== selection.start ||
1145
- lastNativeSelection.end !== selection.end)
1146
- ) {
1147
- nativeUpdate.selection = selection;
1148
- setLastNativeSelection({selection, mostRecentEventCount});
1149
- }
1150
-
1151
- if (Object.keys(nativeUpdate).length === 0) {
1152
- return;
1153
- }
1154
-
1155
- if (inputRef.current != null) {
1156
- viewCommands.setTextAndSelection(
1157
- inputRef.current,
1158
- mostRecentEventCount,
1159
- text,
1160
- selection?.start ?? -1,
1161
- selection?.end ?? -1,
1162
- );
1163
- }
1164
- }, [
1165
- mostRecentEventCount,
1166
- inputRef,
1167
- props.value,
1168
- props.defaultValue,
1169
- lastNativeText,
1170
- selection,
1171
- lastNativeSelection,
1172
- text,
1173
- viewCommands,
1174
- ]);
1295
+ const [mostRecentEventCount, setMostRecentEventCount] = useState<number>(0);
1296
+ const useTextInputStateSynchronization =
1297
+ ReactNativeFeatureFlags.useRefsForTextInputState()
1298
+ ? useTextInputStateSynchronization_REFS
1299
+ : useTextInputStateSynchronization_STATE;
1300
+ const {setLastNativeText, setLastNativeSelection} =
1301
+ useTextInputStateSynchronization({
1302
+ props,
1303
+ inputRef,
1304
+ mostRecentEventCount,
1305
+ selection,
1306
+ text,
1307
+ viewCommands,
1308
+ });
1175
1309
 
1176
1310
  useLayoutEffect(() => {
1177
1311
  const inputRefValue = inputRef.current;
@@ -1187,7 +1321,7 @@ function InternalTextInput(props: Props): React.Node {
1187
1321
  }
1188
1322
  };
1189
1323
  }
1190
- }, [inputRef]);
1324
+ }, []);
1191
1325
 
1192
1326
  const setLocalRef = useCallback(
1193
1327
  (instance: TextInputInstance | null) => {
@@ -1401,12 +1535,29 @@ function InternalTextInput(props: Props): React.Node {
1401
1535
  };
1402
1536
  }
1403
1537
 
1404
- const style = flattenStyle<TextStyleProp>(props.style);
1538
+ // Keep the original (potentially nested) style when possible, as React can diff these more efficiently
1539
+ let _style = props.style;
1540
+ const flattenedStyle = flattenStyle<TextStyleProp>(props.style);
1541
+ if (flattenedStyle != null) {
1542
+ let overrides: ?{...TextStyleInternal} = null;
1543
+ if (typeof flattenedStyle?.fontWeight === 'number') {
1544
+ overrides = overrides || ({}: {...TextStyleInternal});
1545
+ overrides.fontWeight =
1546
+ // $FlowFixMe[incompatible-cast]
1547
+ (flattenedStyle.fontWeight.toString(): TextStyleInternal['fontWeight']);
1548
+ }
1405
1549
 
1406
- if (typeof style?.fontWeight === 'number') {
1407
- // $FlowFixMe[prop-missing]
1408
- // $FlowFixMe[cannot-write]
1409
- style.fontWeight = style?.fontWeight.toString();
1550
+ if (flattenedStyle.verticalAlign != null) {
1551
+ overrides = overrides || ({}: {...TextStyleInternal});
1552
+ overrides.textAlignVertical =
1553
+ verticalAlignToTextAlignVerticalMap[flattenedStyle.verticalAlign];
1554
+ overrides.verticalAlign = undefined;
1555
+ }
1556
+
1557
+ if (overrides != null) {
1558
+ // $FlowFixMe[incompatible-type]
1559
+ _style = [_style, overrides];
1560
+ }
1410
1561
  }
1411
1562
 
1412
1563
  if (Platform.OS === 'ios') {
@@ -1417,10 +1568,10 @@ function InternalTextInput(props: Props): React.Node {
1417
1568
 
1418
1569
  const useMultilineDefaultStyle =
1419
1570
  props.multiline === true &&
1420
- (style == null ||
1421
- (style.padding == null &&
1422
- style.paddingVertical == null &&
1423
- style.paddingTop == null));
1571
+ (flattenedStyle == null ||
1572
+ (flattenedStyle.padding == null &&
1573
+ flattenedStyle.paddingVertical == null &&
1574
+ flattenedStyle.paddingTop == null));
1424
1575
 
1425
1576
  textInput = (
1426
1577
  <RCTTextInputView
@@ -1447,7 +1598,7 @@ function InternalTextInput(props: Props): React.Node {
1447
1598
  selectionColor={selectionColor}
1448
1599
  style={StyleSheet.compose(
1449
1600
  useMultilineDefaultStyle ? styles.multilineDefault : null,
1450
- style,
1601
+ _style,
1451
1602
  )}
1452
1603
  text={text}
1453
1604
  />
@@ -1514,7 +1665,7 @@ function InternalTextInput(props: Props): React.Node {
1514
1665
  onScroll={_onScroll}
1515
1666
  onSelectionChange={_onSelectionChange}
1516
1667
  placeholder={placeholder}
1517
- style={style}
1668
+ style={_style}
1518
1669
  text={text}
1519
1670
  textBreakStrategy={props.textBreakStrategy}
1520
1671
  />
@@ -1642,20 +1793,6 @@ const ExportedForwardRef: React.AbstractComponent<
1642
1793
  },
1643
1794
  forwardedRef: ReactRefSetter<TextInputInstance>,
1644
1795
  ) {
1645
- // $FlowFixMe[underconstrained-implicit-instantiation]
1646
- let style = flattenStyle(restProps.style);
1647
-
1648
- if (style?.verticalAlign != null) {
1649
- // $FlowFixMe[prop-missing]
1650
- // $FlowFixMe[cannot-write]
1651
- style.textAlignVertical =
1652
- // $FlowFixMe[invalid-computed-prop]
1653
- verticalAlignToTextAlignVerticalMap[style.verticalAlign];
1654
- // $FlowFixMe[prop-missing]
1655
- // $FlowFixMe[cannot-write]
1656
- delete style.verticalAlign;
1657
- }
1658
-
1659
1796
  return (
1660
1797
  <InternalTextInput
1661
1798
  allowFontScaling={allowFontScaling}
@@ -1692,7 +1829,6 @@ const ExportedForwardRef: React.AbstractComponent<
1692
1829
  }
1693
1830
  {...restProps}
1694
1831
  forwardedRef={forwardedRef}
1695
- style={style}
1696
1832
  />
1697
1833
  );
1698
1834
  });