@office-iss/react-native-win32 0.0.0-canary.257 → 0.0.0-canary.259

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 (73) hide show
  1. package/.flowconfig +3 -3
  2. package/CHANGELOG.json +55 -1
  3. package/CHANGELOG.md +28 -8
  4. package/Libraries/Alert/Alert.js +3 -0
  5. package/Libraries/Animated/nodes/AnimatedValue.js +1 -0
  6. package/Libraries/Animated/useAnimatedProps.js +68 -3
  7. package/Libraries/BatchedBridge/NativeModules.js +2 -0
  8. package/Libraries/Components/ScrollView/ScrollView.js +124 -165
  9. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +3 -0
  10. package/Libraries/Components/TextInput/TextInput.js +204 -73
  11. package/Libraries/Components/TextInput/TextInput.win32.js +204 -79
  12. package/Libraries/Components/View/ReactNativeStyleAttributes.js +11 -0
  13. package/Libraries/Core/ErrorHandlers.js +9 -0
  14. package/Libraries/Core/ExceptionsManager.js +2 -0
  15. package/Libraries/Core/InitializeCore.js +2 -0
  16. package/Libraries/Core/ReactFiberErrorDialog.js +3 -0
  17. package/Libraries/Core/ReactNativeVersion.js +3 -3
  18. package/Libraries/Core/ReactNativeVersionCheck.win32.js +1 -1
  19. package/Libraries/Core/setUpGlobals.js +1 -0
  20. package/Libraries/Core/setUpReactRefresh.js +0 -4
  21. package/Libraries/Image/ImageViewNativeComponent.js +1 -0
  22. package/Libraries/Interaction/TaskQueue.js +1 -0
  23. package/Libraries/Lists/SectionList.js +1 -1
  24. package/Libraries/LogBox/Data/LogBoxData.js +1 -0
  25. package/Libraries/LogBox/UI/LogBoxInspectorHeader.js +20 -8
  26. package/Libraries/LogBox/UI/LogBoxInspectorHeader.win32.js +20 -8
  27. package/Libraries/NativeComponent/BaseViewConfig.android.js +1 -0
  28. package/Libraries/NativeComponent/BaseViewConfig.ios.js +3 -0
  29. package/Libraries/NativeComponent/BaseViewConfig.win32.js +3 -0
  30. package/Libraries/NativeComponent/NativeComponentRegistry.js +9 -2
  31. package/Libraries/ReactNative/AppContainer-dev.js +1 -5
  32. package/Libraries/ReactNative/AppContainer-prod.js +1 -5
  33. package/Libraries/ReactNative/AppContainer.js +0 -1
  34. package/Libraries/ReactNative/AppRegistry.js +0 -6
  35. package/Libraries/ReactNative/BridgelessUIManager.js +1 -0
  36. package/Libraries/ReactNative/renderApplication.js +0 -2
  37. package/Libraries/Renderer/shims/ReactNativeTypes.js +3 -1
  38. package/Libraries/StyleSheet/StyleSheetTypes.d.ts +46 -0
  39. package/Libraries/StyleSheet/StyleSheetTypes.js +48 -5
  40. package/Libraries/StyleSheet/processBoxShadow.js +211 -0
  41. package/Libraries/StyleSheet/processFilter.js +226 -41
  42. package/Libraries/Text/Text.js +393 -196
  43. package/Libraries/Text/Text.win32.js +440 -228
  44. package/Libraries/TurboModule/TurboModuleRegistry.js +13 -50
  45. package/Libraries/Types/CodegenTypes.js +3 -1
  46. package/Libraries/Utilities/HMRClient.js +1 -0
  47. package/Libraries/Utilities/Platform.android.js +1 -1
  48. package/Libraries/Utilities/Platform.d.ts +1 -1
  49. package/Libraries/Utilities/Platform.flow.js +2 -2
  50. package/Libraries/Utilities/Platform.flow.win32.js +3 -3
  51. package/Libraries/Utilities/Platform.ios.js +1 -1
  52. package/Libraries/Utilities/Platform.win32.js +1 -1
  53. package/Libraries/vendor/emitter/EventEmitter.js +1 -0
  54. package/index.js +1 -0
  55. package/index.win32.js +1 -0
  56. package/jest/mockComponent.js +4 -1
  57. package/jest/setup.js +8 -1
  58. package/overrides.json +11 -11
  59. package/package.json +23 -23
  60. package/src/private/core/components/HScrollViewNativeComponents.js +55 -0
  61. package/src/private/core/components/VScrollViewNativeComponents.js +47 -0
  62. package/src/private/core/components/useSyncOnScroll.js +48 -0
  63. package/src/private/featureflags/ReactNativeFeatureFlags.js +70 -12
  64. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +12 -4
  65. package/src/private/specs/modules/NativeLinkingManager.js +1 -1
  66. package/src/private/specs/modules/NativePlatformConstantsAndroid.js +1 -1
  67. package/src/private/specs/modules/NativePlatformConstantsIOS.js +1 -1
  68. package/src/private/specs/modules/NativePlatformConstantsWin.js +8 -1
  69. package/src/private/specs/modules/NativeSampleTurboModule.js +14 -1
  70. package/src/private/webapis/performance/PerformanceEntry.js +1 -1
  71. package/src/private/webapis/performance/RawPerformanceEntry.js +5 -0
  72. package/types/experimental.d.ts +12 -1
  73. package/Libraries/Text/TextOptimized.js +0 -538
@@ -17,6 +17,7 @@ import type {
17
17
  import type {ViewProps} from '../View/ViewPropTypes';
18
18
  import type {TextInputType} from './TextInput.flow';
19
19
 
20
+ import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
20
21
  import usePressability from '../../Pressability/usePressability';
21
22
  import flattenStyle from '../../StyleSheet/flattenStyle';
22
23
  import StyleSheet, {
@@ -957,8 +958,188 @@ export type Props = $ReadOnly<{|
957
958
  value?: ?Stringish,
958
959
  |}>;
959
960
 
961
+ type ViewCommands = $NonMaybeType<
962
+ | typeof AndroidTextInputCommands
963
+ | typeof RCTMultilineTextInputNativeCommands
964
+ | typeof RCTSinglelineTextInputNativeCommands,
965
+ >;
966
+
967
+ type LastNativeSelection = {|
968
+ selection: Selection,
969
+ mostRecentEventCount: number,
970
+ |};
971
+
960
972
  const emptyFunctionThatReturnsTrue = () => true;
961
973
 
974
+ /**
975
+ * This hook handles the synchronization between the state of the text input
976
+ * in native and in JavaScript. This is necessary due to the asynchronous nature
977
+ * of text input events.
978
+ */
979
+ function useTextInputStateSynchronization_STATE({
980
+ props,
981
+ mostRecentEventCount,
982
+ selection,
983
+ inputRef,
984
+ text,
985
+ viewCommands,
986
+ }: {
987
+ props: Props,
988
+ mostRecentEventCount: number,
989
+ selection: ?Selection,
990
+ inputRef: React.RefObject<null | React.ElementRef<HostComponent<mixed>>>,
991
+ text: string,
992
+ viewCommands: ViewCommands,
993
+ }): {
994
+ setLastNativeText: string => void,
995
+ setLastNativeSelection: LastNativeSelection => void,
996
+ } {
997
+ const [lastNativeText, setLastNativeText] = useState<?Stringish>(props.value);
998
+ const [lastNativeSelectionState, setLastNativeSelection] =
999
+ useState<LastNativeSelection>({
1000
+ selection: {start: -1, end: -1},
1001
+ mostRecentEventCount: mostRecentEventCount,
1002
+ });
1003
+
1004
+ const lastNativeSelection = lastNativeSelectionState.selection;
1005
+
1006
+ // This is necessary in case native updates the text and JS decides
1007
+ // that the update should be ignored and we should stick with the value
1008
+ // that we have in JS.
1009
+ useLayoutEffect(() => {
1010
+ const nativeUpdate: {text?: string, selection?: Selection} = {};
1011
+
1012
+ if (lastNativeText !== props.value && typeof props.value === 'string') {
1013
+ nativeUpdate.text = props.value;
1014
+ setLastNativeText(props.value);
1015
+ }
1016
+
1017
+ if (
1018
+ selection &&
1019
+ lastNativeSelection &&
1020
+ (lastNativeSelection.start !== selection.start ||
1021
+ lastNativeSelection.end !== selection.end)
1022
+ ) {
1023
+ nativeUpdate.selection = selection;
1024
+ setLastNativeSelection({selection, mostRecentEventCount});
1025
+ }
1026
+
1027
+ if (Object.keys(nativeUpdate).length === 0) {
1028
+ return;
1029
+ }
1030
+
1031
+ if (inputRef.current != null) {
1032
+ viewCommands.setTextAndSelection(
1033
+ inputRef.current,
1034
+ mostRecentEventCount,
1035
+ text,
1036
+ selection?.start ?? -1,
1037
+ selection?.end ?? -1,
1038
+ );
1039
+ }
1040
+ }, [
1041
+ mostRecentEventCount,
1042
+ inputRef,
1043
+ props.value,
1044
+ props.defaultValue,
1045
+ lastNativeText,
1046
+ selection,
1047
+ lastNativeSelection,
1048
+ text,
1049
+ viewCommands,
1050
+ ]);
1051
+
1052
+ return {setLastNativeText, setLastNativeSelection};
1053
+ }
1054
+
1055
+ /**
1056
+ * This hook handles the synchronization between the state of the text input
1057
+ * in native and in JavaScript. This is necessary due to the asynchronous nature
1058
+ * of text input events.
1059
+ */
1060
+ function useTextInputStateSynchronization_REFS({
1061
+ props,
1062
+ mostRecentEventCount,
1063
+ selection,
1064
+ inputRef,
1065
+ text,
1066
+ viewCommands,
1067
+ }: {
1068
+ props: Props,
1069
+ mostRecentEventCount: number,
1070
+ selection: ?Selection,
1071
+ inputRef: React.RefObject<null | React.ElementRef<HostComponent<mixed>>>,
1072
+ text: string,
1073
+ viewCommands: ViewCommands,
1074
+ }): {
1075
+ setLastNativeText: string => void,
1076
+ setLastNativeSelection: LastNativeSelection => void,
1077
+ } {
1078
+ const lastNativeTextRef = useRef<?Stringish>(props.value);
1079
+ const lastNativeSelectionRef = useRef<LastNativeSelection>({
1080
+ selection: {start: -1, end: -1},
1081
+ mostRecentEventCount: mostRecentEventCount,
1082
+ });
1083
+
1084
+ // This is necessary in case native updates the text and JS decides
1085
+ // that the update should be ignored and we should stick with the value
1086
+ // that we have in JS.
1087
+ useLayoutEffect(() => {
1088
+ const nativeUpdate: {text?: string, selection?: Selection} = {};
1089
+
1090
+ const lastNativeSelection = lastNativeSelectionRef.current.selection;
1091
+
1092
+ if (
1093
+ lastNativeTextRef.current !== props.value &&
1094
+ typeof props.value === 'string'
1095
+ ) {
1096
+ nativeUpdate.text = props.value;
1097
+ lastNativeTextRef.current = props.value;
1098
+ }
1099
+
1100
+ if (
1101
+ selection &&
1102
+ lastNativeSelection &&
1103
+ (lastNativeSelection.start !== selection.start ||
1104
+ lastNativeSelection.end !== selection.end)
1105
+ ) {
1106
+ nativeUpdate.selection = selection;
1107
+ lastNativeSelectionRef.current = {selection, mostRecentEventCount};
1108
+ }
1109
+
1110
+ if (Object.keys(nativeUpdate).length === 0) {
1111
+ return;
1112
+ }
1113
+
1114
+ if (inputRef.current != null) {
1115
+ viewCommands.setTextAndSelection(
1116
+ inputRef.current,
1117
+ mostRecentEventCount,
1118
+ text,
1119
+ selection?.start ?? -1,
1120
+ selection?.end ?? -1,
1121
+ );
1122
+ }
1123
+ }, [
1124
+ mostRecentEventCount,
1125
+ inputRef,
1126
+ props.value,
1127
+ props.defaultValue,
1128
+ selection,
1129
+ text,
1130
+ viewCommands,
1131
+ ]);
1132
+
1133
+ return {
1134
+ setLastNativeText: lastNativeText => {
1135
+ lastNativeTextRef.current = lastNativeText;
1136
+ },
1137
+ setLastNativeSelection: lastNativeSelection => {
1138
+ lastNativeSelectionRef.current = lastNativeSelection;
1139
+ },
1140
+ };
1141
+ }
1142
+
962
1143
  /**
963
1144
  * A foundational component for inputting text into the app via a
964
1145
  * keyboard. Props provide configurability for several features, such as
@@ -1089,7 +1270,6 @@ function InternalTextInput(props: Props): React.Node {
1089
1270
 
1090
1271
  const inputRef = useRef<null | React.ElementRef<HostComponent<mixed>>>(null);
1091
1272
 
1092
- // eslint-disable-next-line react-hooks/exhaustive-deps
1093
1273
  const selection: ?Selection =
1094
1274
  propsSelection == null
1095
1275
  ? null
@@ -1098,28 +1278,6 @@ function InternalTextInput(props: Props): React.Node {
1098
1278
  end: propsSelection.end ?? propsSelection.start,
1099
1279
  };
1100
1280
 
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
1281
  const text =
1124
1282
  typeof props.value === 'string'
1125
1283
  ? props.value
@@ -1127,51 +1285,26 @@ function InternalTextInput(props: Props): React.Node {
1127
1285
  ? props.defaultValue
1128
1286
  : '';
1129
1287
 
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} = {};
1135
-
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
- }
1288
+ const viewCommands =
1289
+ AndroidTextInputCommands ||
1290
+ (props.multiline === true
1291
+ ? RCTMultilineTextInputNativeCommands
1292
+ : RCTSinglelineTextInputNativeCommands);
1150
1293
 
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
- ]);
1294
+ const [mostRecentEventCount, setMostRecentEventCount] = useState<number>(0);
1295
+ const useTextInputStateSynchronization =
1296
+ ReactNativeFeatureFlags.useRefsForTextInputState()
1297
+ ? useTextInputStateSynchronization_REFS
1298
+ : useTextInputStateSynchronization_STATE;
1299
+ const {setLastNativeText, setLastNativeSelection} =
1300
+ useTextInputStateSynchronization({
1301
+ props,
1302
+ inputRef,
1303
+ mostRecentEventCount,
1304
+ selection,
1305
+ text,
1306
+ viewCommands,
1307
+ });
1175
1308
 
1176
1309
  useLayoutEffect(() => {
1177
1310
  const inputRefValue = inputRef.current;
@@ -1187,7 +1320,7 @@ function InternalTextInput(props: Props): React.Node {
1187
1320
  }
1188
1321
  };
1189
1322
  }
1190
- }, [inputRef]);
1323
+ }, []);
1191
1324
 
1192
1325
  const setLocalRef = useCallback(
1193
1326
  (instance: TextInputInstance | null) => {
@@ -1401,12 +1534,10 @@ function InternalTextInput(props: Props): React.Node {
1401
1534
  };
1402
1535
  }
1403
1536
 
1404
- const style = flattenStyle<TextStyleProp>(props.style);
1405
-
1537
+ let style = flattenStyle<TextStyleProp>(props.style);
1406
1538
  if (typeof style?.fontWeight === 'number') {
1407
- // $FlowFixMe[prop-missing]
1408
- // $FlowFixMe[cannot-write]
1409
- style.fontWeight = style?.fontWeight.toString();
1539
+ // $FlowFixMe
1540
+ style = [style, {fontWeight: style.fontWeight.toString()}];
1410
1541
  }
1411
1542
 
1412
1543
  if (Platform.OS === 'ios') {
@@ -17,6 +17,7 @@ import type {
17
17
  import type {ViewProps} from '../View/ViewPropTypes';
18
18
  import type {TextInputType} from './TextInput.flow';
19
19
 
20
+ import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
20
21
  import usePressability from '../../Pressability/usePressability';
21
22
  import flattenStyle from '../../StyleSheet/flattenStyle';
22
23
  import StyleSheet, {
@@ -1000,8 +1001,188 @@ export type Props = $ReadOnly<{|
1000
1001
  value?: ?Stringish,
1001
1002
  |}>;
1002
1003
 
1004
+ type ViewCommands = $NonMaybeType<
1005
+ | typeof AndroidTextInputCommands
1006
+ | typeof RCTMultilineTextInputNativeCommands
1007
+ | typeof RCTSinglelineTextInputNativeCommands,
1008
+ >;
1009
+
1010
+ type LastNativeSelection = {|
1011
+ selection: Selection,
1012
+ mostRecentEventCount: number,
1013
+ |};
1014
+
1003
1015
  const emptyFunctionThatReturnsTrue = () => true;
1004
1016
 
1017
+ /**
1018
+ * This hook handles the synchronization between the state of the text input
1019
+ * in native and in JavaScript. This is necessary due to the asynchronous nature
1020
+ * of text input events.
1021
+ */
1022
+ function useTextInputStateSynchronization_STATE({
1023
+ props,
1024
+ mostRecentEventCount,
1025
+ selection,
1026
+ inputRef,
1027
+ text,
1028
+ viewCommands,
1029
+ }: {
1030
+ props: Props,
1031
+ mostRecentEventCount: number,
1032
+ selection: ?Selection,
1033
+ inputRef: React.RefObject<null | React.ElementRef<HostComponent<mixed>>>,
1034
+ text: string,
1035
+ viewCommands: ViewCommands,
1036
+ }): {
1037
+ setLastNativeText: string => void,
1038
+ setLastNativeSelection: LastNativeSelection => void,
1039
+ } {
1040
+ const [lastNativeText, setLastNativeText] = useState<?Stringish>(props.value);
1041
+ const [lastNativeSelectionState, setLastNativeSelection] =
1042
+ useState<LastNativeSelection>({
1043
+ selection: {start: -1, end: -1},
1044
+ mostRecentEventCount: mostRecentEventCount,
1045
+ });
1046
+
1047
+ const lastNativeSelection = lastNativeSelectionState.selection;
1048
+
1049
+ // This is necessary in case native updates the text and JS decides
1050
+ // that the update should be ignored and we should stick with the value
1051
+ // that we have in JS.
1052
+ useLayoutEffect(() => {
1053
+ const nativeUpdate: {text?: string, selection?: Selection} = {};
1054
+
1055
+ if (lastNativeText !== props.value && typeof props.value === 'string') {
1056
+ nativeUpdate.text = props.value;
1057
+ setLastNativeText(props.value);
1058
+ }
1059
+
1060
+ if (
1061
+ selection &&
1062
+ lastNativeSelection &&
1063
+ (lastNativeSelection.start !== selection.start ||
1064
+ lastNativeSelection.end !== selection.end)
1065
+ ) {
1066
+ nativeUpdate.selection = selection;
1067
+ setLastNativeSelection({selection, mostRecentEventCount});
1068
+ }
1069
+
1070
+ if (Object.keys(nativeUpdate).length === 0) {
1071
+ return;
1072
+ }
1073
+
1074
+ if (inputRef.current != null) {
1075
+ viewCommands.setTextAndSelection(
1076
+ inputRef.current,
1077
+ mostRecentEventCount,
1078
+ text,
1079
+ selection?.start ?? -1,
1080
+ selection?.end ?? -1,
1081
+ );
1082
+ }
1083
+ }, [
1084
+ mostRecentEventCount,
1085
+ inputRef,
1086
+ props.value,
1087
+ props.defaultValue,
1088
+ lastNativeText,
1089
+ selection,
1090
+ lastNativeSelection,
1091
+ text,
1092
+ viewCommands,
1093
+ ]);
1094
+
1095
+ return {setLastNativeText, setLastNativeSelection};
1096
+ }
1097
+
1098
+ /**
1099
+ * This hook handles the synchronization between the state of the text input
1100
+ * in native and in JavaScript. This is necessary due to the asynchronous nature
1101
+ * of text input events.
1102
+ */
1103
+ function useTextInputStateSynchronization_REFS({
1104
+ props,
1105
+ mostRecentEventCount,
1106
+ selection,
1107
+ inputRef,
1108
+ text,
1109
+ viewCommands,
1110
+ }: {
1111
+ props: Props,
1112
+ mostRecentEventCount: number,
1113
+ selection: ?Selection,
1114
+ inputRef: React.RefObject<null | React.ElementRef<HostComponent<mixed>>>,
1115
+ text: string,
1116
+ viewCommands: ViewCommands,
1117
+ }): {
1118
+ setLastNativeText: string => void,
1119
+ setLastNativeSelection: LastNativeSelection => void,
1120
+ } {
1121
+ const lastNativeTextRef = useRef<?Stringish>(props.value);
1122
+ const lastNativeSelectionRef = useRef<LastNativeSelection>({
1123
+ selection: {start: -1, end: -1},
1124
+ mostRecentEventCount: mostRecentEventCount,
1125
+ });
1126
+
1127
+ // This is necessary in case native updates the text and JS decides
1128
+ // that the update should be ignored and we should stick with the value
1129
+ // that we have in JS.
1130
+ useLayoutEffect(() => {
1131
+ const nativeUpdate: {text?: string, selection?: Selection} = {};
1132
+
1133
+ const lastNativeSelection = lastNativeSelectionRef.current.selection;
1134
+
1135
+ if (
1136
+ lastNativeTextRef.current !== props.value &&
1137
+ typeof props.value === 'string'
1138
+ ) {
1139
+ nativeUpdate.text = props.value;
1140
+ lastNativeTextRef.current = props.value;
1141
+ }
1142
+
1143
+ if (
1144
+ selection &&
1145
+ lastNativeSelection &&
1146
+ (lastNativeSelection.start !== selection.start ||
1147
+ lastNativeSelection.end !== selection.end)
1148
+ ) {
1149
+ nativeUpdate.selection = selection;
1150
+ lastNativeSelectionRef.current = {selection, mostRecentEventCount};
1151
+ }
1152
+
1153
+ if (Object.keys(nativeUpdate).length === 0) {
1154
+ return;
1155
+ }
1156
+
1157
+ if (inputRef.current != null) {
1158
+ viewCommands.setTextAndSelection(
1159
+ inputRef.current,
1160
+ mostRecentEventCount,
1161
+ text,
1162
+ selection?.start ?? -1,
1163
+ selection?.end ?? -1,
1164
+ );
1165
+ }
1166
+ }, [
1167
+ mostRecentEventCount,
1168
+ inputRef,
1169
+ props.value,
1170
+ props.defaultValue,
1171
+ selection,
1172
+ text,
1173
+ viewCommands,
1174
+ ]);
1175
+
1176
+ return {
1177
+ setLastNativeText: lastNativeText => {
1178
+ lastNativeTextRef.current = lastNativeText;
1179
+ },
1180
+ setLastNativeSelection: lastNativeSelection => {
1181
+ lastNativeSelectionRef.current = lastNativeSelection;
1182
+ },
1183
+ };
1184
+ }
1185
+
1005
1186
  /**
1006
1187
  * A foundational component for inputting text into the app via a
1007
1188
  * keyboard. Props provide configurability for several features, such as
@@ -1134,7 +1315,6 @@ function InternalTextInput(props: Props): React.Node {
1134
1315
 
1135
1316
  const inputRef = useRef<null | React.ElementRef<HostComponent<mixed>>>(null);
1136
1317
 
1137
- // eslint-disable-next-line react-hooks/exhaustive-deps
1138
1318
  const selection: ?Selection =
1139
1319
  propsSelection == null
1140
1320
  ? null
@@ -1143,34 +1323,6 @@ function InternalTextInput(props: Props): React.Node {
1143
1323
  end: propsSelection.end ?? propsSelection.start,
1144
1324
  };
1145
1325
 
1146
- const [mostRecentEventCount, setMostRecentEventCount] = useState<number>(0);
1147
- const [lastNativeText, setLastNativeText] = useState<?Stringish>(props.value);
1148
- const [lastNativeSelectionState, setLastNativeSelection] = useState<{|
1149
- selection: Selection,
1150
- mostRecentEventCount: number,
1151
- |}>({
1152
- selection: {start: -1, end: -1},
1153
- mostRecentEventCount: mostRecentEventCount,
1154
- });
1155
-
1156
- const lastNativeSelection = lastNativeSelectionState.selection;
1157
-
1158
- let viewCommands;
1159
- if (AndroidTextInputCommands) {
1160
- viewCommands = AndroidTextInputCommands;
1161
- }
1162
- // [Windows
1163
- else if (WindowsTextInputCommands) {
1164
- viewCommands = WindowsTextInputCommands;
1165
- }
1166
- // Windows]
1167
- else {
1168
- viewCommands =
1169
- props.multiline === true
1170
- ? RCTMultilineTextInputNativeCommands
1171
- : RCTSinglelineTextInputNativeCommands;
1172
- }
1173
-
1174
1326
  const text =
1175
1327
  typeof props.value === 'string'
1176
1328
  ? props.value
@@ -1178,51 +1330,26 @@ function InternalTextInput(props: Props): React.Node {
1178
1330
  ? props.defaultValue
1179
1331
  : '';
1180
1332
 
1181
- // This is necessary in case native updates the text and JS decides
1182
- // that the update should be ignored and we should stick with the value
1183
- // that we have in JS.
1184
- useLayoutEffect(() => {
1185
- const nativeUpdate: {text?: string, selection?: Selection} = {};
1186
-
1187
- if (lastNativeText !== props.value && typeof props.value === 'string') {
1188
- nativeUpdate.text = props.value;
1189
- setLastNativeText(props.value);
1190
- }
1191
-
1192
- if (
1193
- selection &&
1194
- lastNativeSelection &&
1195
- (lastNativeSelection.start !== selection.start ||
1196
- lastNativeSelection.end !== selection.end)
1197
- ) {
1198
- nativeUpdate.selection = selection;
1199
- setLastNativeSelection({selection, mostRecentEventCount});
1200
- }
1333
+ const viewCommands =
1334
+ WindowsTextInputCommands || AndroidTextInputCommands || // [Windows]
1335
+ (props.multiline === true
1336
+ ? RCTMultilineTextInputNativeCommands
1337
+ : RCTSinglelineTextInputNativeCommands)
1201
1338
 
1202
- if (Object.keys(nativeUpdate).length === 0) {
1203
- return;
1204
- }
1205
-
1206
- if (inputRef.current != null) {
1207
- viewCommands.setTextAndSelection(
1208
- inputRef.current,
1209
- mostRecentEventCount,
1210
- text,
1211
- selection?.start ?? -1,
1212
- selection?.end ?? -1,
1213
- );
1214
- }
1215
- }, [
1216
- mostRecentEventCount,
1217
- inputRef,
1218
- props.value,
1219
- props.defaultValue,
1220
- lastNativeText,
1221
- selection,
1222
- lastNativeSelection,
1223
- text,
1224
- viewCommands,
1225
- ]);
1339
+ const [mostRecentEventCount, setMostRecentEventCount] = useState<number>(0);
1340
+ const useTextInputStateSynchronization =
1341
+ ReactNativeFeatureFlags.useRefsForTextInputState()
1342
+ ? useTextInputStateSynchronization_REFS
1343
+ : useTextInputStateSynchronization_STATE;
1344
+ const {setLastNativeText, setLastNativeSelection} =
1345
+ useTextInputStateSynchronization({
1346
+ props,
1347
+ inputRef,
1348
+ mostRecentEventCount,
1349
+ selection,
1350
+ text,
1351
+ viewCommands,
1352
+ });
1226
1353
 
1227
1354
  useLayoutEffect(() => {
1228
1355
  const inputRefValue = inputRef.current;
@@ -1238,7 +1365,7 @@ function InternalTextInput(props: Props): React.Node {
1238
1365
  }
1239
1366
  };
1240
1367
  }
1241
- }, [inputRef]);
1368
+ }, []);
1242
1369
 
1243
1370
  const setLocalRef = useCallback(
1244
1371
  (instance: TextInputInstance | null) => {
@@ -1514,12 +1641,10 @@ function InternalTextInput(props: Props): React.Node {
1514
1641
  };
1515
1642
  }
1516
1643
 
1517
- const style = flattenStyle<TextStyleProp>(props.style);
1518
-
1644
+ let style = flattenStyle<TextStyleProp>(props.style);
1519
1645
  if (typeof style?.fontWeight === 'number') {
1520
- // $FlowFixMe[prop-missing]
1521
- // $FlowFixMe[cannot-write]
1522
- style.fontWeight = style?.fontWeight.toString();
1646
+ // $FlowFixMe
1647
+ style = [style, {fontWeight: style.fontWeight.toString()}];
1523
1648
  }
1524
1649
 
1525
1650
  if (Platform.OS === 'ios') {
@@ -11,6 +11,7 @@
11
11
  import type {AnyAttributeType} from '../../Renderer/shims/ReactNativeTypes';
12
12
 
13
13
  import processAspectRatio from '../../StyleSheet/processAspectRatio';
14
+ import processBoxShadow from '../../StyleSheet/processBoxShadow';
14
15
  import processColor from '../../StyleSheet/processColor';
15
16
  import processFilter from '../../StyleSheet/processFilter';
16
17
  import processFontVariant from '../../StyleSheet/processFontVariant';
@@ -120,6 +121,16 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
120
121
  */
121
122
  experimental_filter: {process: processFilter},
122
123
 
124
+ /**
125
+ * MixBlendMode
126
+ */
127
+ experimental_mixBlendMode: true,
128
+
129
+ /*
130
+ * BoxShadow
131
+ */
132
+ experimental_boxShadow: {process: processBoxShadow},
133
+
123
134
  /**
124
135
  * View
125
136
  */