@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.
- package/.flowconfig +3 -3
- package/CHANGELOG.json +55 -1
- package/CHANGELOG.md +28 -8
- package/Libraries/Alert/Alert.js +3 -0
- package/Libraries/Animated/nodes/AnimatedValue.js +1 -0
- package/Libraries/Animated/useAnimatedProps.js +68 -3
- package/Libraries/BatchedBridge/NativeModules.js +2 -0
- package/Libraries/Components/ScrollView/ScrollView.js +124 -165
- package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +3 -0
- package/Libraries/Components/TextInput/TextInput.js +204 -73
- package/Libraries/Components/TextInput/TextInput.win32.js +204 -79
- package/Libraries/Components/View/ReactNativeStyleAttributes.js +11 -0
- package/Libraries/Core/ErrorHandlers.js +9 -0
- package/Libraries/Core/ExceptionsManager.js +2 -0
- package/Libraries/Core/InitializeCore.js +2 -0
- package/Libraries/Core/ReactFiberErrorDialog.js +3 -0
- package/Libraries/Core/ReactNativeVersion.js +3 -3
- package/Libraries/Core/ReactNativeVersionCheck.win32.js +1 -1
- package/Libraries/Core/setUpGlobals.js +1 -0
- package/Libraries/Core/setUpReactRefresh.js +0 -4
- package/Libraries/Image/ImageViewNativeComponent.js +1 -0
- package/Libraries/Interaction/TaskQueue.js +1 -0
- package/Libraries/Lists/SectionList.js +1 -1
- package/Libraries/LogBox/Data/LogBoxData.js +1 -0
- package/Libraries/LogBox/UI/LogBoxInspectorHeader.js +20 -8
- package/Libraries/LogBox/UI/LogBoxInspectorHeader.win32.js +20 -8
- package/Libraries/NativeComponent/BaseViewConfig.android.js +1 -0
- package/Libraries/NativeComponent/BaseViewConfig.ios.js +3 -0
- package/Libraries/NativeComponent/BaseViewConfig.win32.js +3 -0
- package/Libraries/NativeComponent/NativeComponentRegistry.js +9 -2
- package/Libraries/ReactNative/AppContainer-dev.js +1 -5
- package/Libraries/ReactNative/AppContainer-prod.js +1 -5
- package/Libraries/ReactNative/AppContainer.js +0 -1
- package/Libraries/ReactNative/AppRegistry.js +0 -6
- package/Libraries/ReactNative/BridgelessUIManager.js +1 -0
- package/Libraries/ReactNative/renderApplication.js +0 -2
- package/Libraries/Renderer/shims/ReactNativeTypes.js +3 -1
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +46 -0
- package/Libraries/StyleSheet/StyleSheetTypes.js +48 -5
- package/Libraries/StyleSheet/processBoxShadow.js +211 -0
- package/Libraries/StyleSheet/processFilter.js +226 -41
- package/Libraries/Text/Text.js +393 -196
- package/Libraries/Text/Text.win32.js +440 -228
- package/Libraries/TurboModule/TurboModuleRegistry.js +13 -50
- package/Libraries/Types/CodegenTypes.js +3 -1
- package/Libraries/Utilities/HMRClient.js +1 -0
- package/Libraries/Utilities/Platform.android.js +1 -1
- package/Libraries/Utilities/Platform.d.ts +1 -1
- package/Libraries/Utilities/Platform.flow.js +2 -2
- package/Libraries/Utilities/Platform.flow.win32.js +3 -3
- package/Libraries/Utilities/Platform.ios.js +1 -1
- package/Libraries/Utilities/Platform.win32.js +1 -1
- package/Libraries/vendor/emitter/EventEmitter.js +1 -0
- package/index.js +1 -0
- package/index.win32.js +1 -0
- package/jest/mockComponent.js +4 -1
- package/jest/setup.js +8 -1
- package/overrides.json +11 -11
- package/package.json +23 -23
- package/src/private/core/components/HScrollViewNativeComponents.js +55 -0
- package/src/private/core/components/VScrollViewNativeComponents.js +47 -0
- package/src/private/core/components/useSyncOnScroll.js +48 -0
- package/src/private/featureflags/ReactNativeFeatureFlags.js +70 -12
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +12 -4
- package/src/private/specs/modules/NativeLinkingManager.js +1 -1
- package/src/private/specs/modules/NativePlatformConstantsAndroid.js +1 -1
- package/src/private/specs/modules/NativePlatformConstantsIOS.js +1 -1
- package/src/private/specs/modules/NativePlatformConstantsWin.js +8 -1
- package/src/private/specs/modules/NativeSampleTurboModule.js +14 -1
- package/src/private/webapis/performance/PerformanceEntry.js +1 -1
- package/src/private/webapis/performance/RawPerformanceEntry.js +5 -0
- package/types/experimental.d.ts +12 -1
- 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
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
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
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
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
|
-
}, [
|
|
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
|
-
|
|
1405
|
-
|
|
1537
|
+
let style = flattenStyle<TextStyleProp>(props.style);
|
|
1406
1538
|
if (typeof style?.fontWeight === 'number') {
|
|
1407
|
-
// $FlowFixMe
|
|
1408
|
-
|
|
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
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
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
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
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
|
-
}, [
|
|
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
|
-
|
|
1518
|
-
|
|
1644
|
+
let style = flattenStyle<TextStyleProp>(props.style);
|
|
1519
1645
|
if (typeof style?.fontWeight === 'number') {
|
|
1520
|
-
// $FlowFixMe
|
|
1521
|
-
|
|
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
|
*/
|