@office-iss/react-native-win32 0.0.0-canary.258 → 0.0.0-canary.260
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 +2 -4
- package/CHANGELOG.json +31 -1
- package/CHANGELOG.md +24 -8
- package/Libraries/Alert/Alert.js +3 -0
- package/Libraries/Animated/AnimatedImplementation.js +7 -7
- package/Libraries/Animated/animations/Animation.js +10 -0
- package/Libraries/Animated/animations/TimingAnimation.js +1 -0
- package/Libraries/Animated/components/AnimatedScrollView.js +2 -2
- package/Libraries/Animated/createAnimatedComponent.js +1 -1
- package/Libraries/Animated/nodes/AnimatedValue.js +1 -0
- package/Libraries/Animated/useAnimatedProps.js +138 -6
- package/Libraries/BatchedBridge/NativeModules.js +2 -0
- package/Libraries/Blob/FileReader.js +1 -1
- package/Libraries/Blob/URL.js +2 -62
- package/Libraries/Blob/URLSearchParams.js +71 -0
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +1 -1
- package/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js +1 -1
- package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +3 -0
- package/Libraries/Components/ScrollView/ScrollView.js +5 -5
- package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +3 -0
- package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +1 -1
- package/Libraries/Components/StatusBar/StatusBar.js +3 -1
- package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +3 -0
- package/Libraries/Components/TextInput/TextInput.d.ts +32 -2
- package/Libraries/Components/TextInput/TextInput.js +220 -80
- package/Libraries/Components/TextInput/TextInput.win32.js +220 -86
- package/Libraries/Components/View/ReactNativeStyleAttributes.js +22 -0
- package/Libraries/Components/View/ReactNativeViewAttributes.js +2 -0
- package/Libraries/Components/View/ReactNativeViewAttributes.win32.js +2 -0
- package/Libraries/Components/View/ViewAccessibility.d.ts +15 -0
- package/Libraries/Components/View/ViewNativeComponent.js +6 -0
- package/Libraries/Components/View/ViewPropTypes.js +14 -0
- package/Libraries/Components/View/ViewPropTypes.win32.js +14 -0
- package/Libraries/Core/ExceptionsManager.js +2 -0
- package/Libraries/Core/InitializeCore.js +1 -1
- package/Libraries/Core/ReactFiberErrorDialog.js +3 -0
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/Core/setUpErrorHandling.js +7 -1
- package/Libraries/Core/setUpReactRefresh.js +0 -4
- package/Libraries/Image/AssetSourceResolver.js +28 -1
- package/Libraries/Image/Image.android.js +9 -14
- package/Libraries/Image/Image.ios.js +11 -22
- package/Libraries/Image/Image.win32.js +10 -21
- package/Libraries/Image/ImageBackground.js +1 -8
- package/Libraries/Image/ImageUtils.js +9 -9
- package/Libraries/Image/ImageViewNativeComponent.js +4 -0
- package/Libraries/Inspector/NetworkOverlay.js +1 -1
- package/Libraries/Interaction/TaskQueue.js +1 -0
- package/Libraries/Lists/FlatList.js +1 -1
- package/Libraries/Lists/SectionList.js +2 -2
- package/Libraries/Lists/SectionListModern.js +1 -1
- package/Libraries/LogBox/Data/LogBoxData.js +31 -4
- package/Libraries/NativeComponent/BaseViewConfig.android.js +2 -0
- package/Libraries/NativeComponent/BaseViewConfig.ios.js +7 -0
- package/Libraries/NativeComponent/BaseViewConfig.win32.js +7 -0
- package/Libraries/NativeComponent/NativeComponentRegistry.js +9 -2
- package/Libraries/Network/XMLHttpRequest.js +4 -2
- package/Libraries/ReactNative/BridgelessUIManager.js +1 -0
- package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricHostComponent.js +1 -1
- package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricPublicInstance.js +5 -5
- package/Libraries/ReactNative/RendererImplementation.js +24 -2
- package/Libraries/ReactNative/getNativeComponentAttributes.js +8 -0
- package/Libraries/Renderer/shims/ReactNativeTypes.js +3 -1
- package/Libraries/StyleSheet/StyleSheet.js +1 -1
- package/Libraries/StyleSheet/StyleSheet.win32.js +1 -1
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +57 -19
- package/Libraries/StyleSheet/StyleSheetTypes.js +60 -23
- package/Libraries/StyleSheet/processBackgroundImage.js +286 -0
- package/Libraries/StyleSheet/processBoxShadow.js +211 -0
- package/Libraries/StyleSheet/processFilter.js +24 -14
- package/Libraries/Text/Text.js +395 -212
- package/Libraries/Text/Text.win32.js +443 -245
- package/Libraries/Text/TextNativeComponent.js +7 -0
- package/Libraries/Text/TextNativeComponent.win32.js +7 -0
- 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/Utilities/ReactNativeTestTools.js +1 -1
- package/Libraries/WebSocket/WebSocket.js +1 -1
- package/Libraries/vendor/emitter/EventEmitter.js +1 -0
- package/flow/jest.js +2 -2
- package/index.js +1 -0
- package/index.win32.js +1 -0
- package/jest/mockModal.js +1 -3
- package/jest/mockScrollView.js +1 -1
- package/jest/renderer.js +2 -2
- package/jest/setup.js +16 -9
- package/overrides.json +16 -16
- package/package.json +15 -15
- package/src/private/{core/components → components}/HScrollViewNativeComponents.js +8 -8
- package/src/private/{core/components → components}/VScrollViewNativeComponents.js +7 -7
- package/src/private/{core/components → components}/useSyncOnScroll.js +2 -2
- package/src/private/featureflags/ReactNativeFeatureFlags.js +143 -19
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +25 -5
- package/src/private/hooks/DebouncedEffectImplementation.js +148 -0
- package/src/private/hooks/useDebouncedEffect.js +23 -0
- package/{Libraries/Core → src/private/renderer/errorhandling}/ErrorHandlers.js +14 -4
- package/src/private/setup/setUpDOM.js +28 -0
- package/src/private/setup/setUpIntersectionObserver.js +27 -0
- package/src/private/setup/setUpMutationObserver.js +26 -0
- package/src/private/setup/setUpPerformanceObserver.js +64 -0
- package/src/private/specs/modules/NativeDebuggerSessionObserver.js +23 -0
- 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/webapis/dom/nodes/ReadOnlyNode.js +6 -4
- package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver}/IntersectionObserver.js +1 -1
- package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver}/IntersectionObserverEntry.js +3 -3
- package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver}/IntersectionObserverManager.js +5 -8
- package/src/private/{specs/modules → webapis/intersectionobserver/specs}/NativeIntersectionObserver.js +2 -2
- package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver/specs}/__mocks__/NativeIntersectionObserver.js +4 -4
- package/{Libraries/MutationObserver → src/private/webapis/mutationobserver}/MutationObserver.js +1 -1
- package/{Libraries/MutationObserver → src/private/webapis/mutationobserver}/MutationObserverManager.js +5 -5
- package/{Libraries/MutationObserver → src/private/webapis/mutationobserver}/MutationRecord.js +4 -6
- package/src/private/{specs/modules → webapis/mutationobserver/specs}/NativeMutationObserver.js +2 -2
- package/{Libraries/MutationObserver → src/private/webapis/mutationobserver/specs}/__mocks__/NativeMutationObserver.js +5 -5
- package/src/private/webapis/performance/{EventCounts.js → EventTiming.js} +65 -3
- package/src/private/webapis/performance/LongTasks.js +39 -0
- package/src/private/webapis/performance/Performance.js +22 -9
- package/src/private/webapis/performance/PerformanceEntry.js +36 -18
- package/src/private/webapis/performance/PerformanceObserver.js +29 -43
- package/src/private/webapis/performance/RawPerformanceEntry.js +24 -1
- package/src/private/webapis/performance/UserTiming.js +17 -12
- package/src/private/webapis/performance/specs/NativePerformanceObserver.js +1 -1
- package/src-win/Libraries/Components/View/ViewAccessibility.d.ts +15 -0
- package/types/experimental.d.ts +20 -1
- package/Libraries/Core/setUpIntersectionObserver.js +0 -16
- package/Libraries/Core/setUpMutationObserver.js +0 -16
- package/Libraries/Core/setUpPerformanceObserver.js +0 -18
- package/Libraries/IntersectionObserver/NativeIntersectionObserver.js +0 -13
- package/Libraries/MutationObserver/NativeMutationObserver.js +0 -13
- package/Libraries/Text/TextOptimized.js +0 -538
- package/src/private/core/setUpDOM.js +0 -18
- package/src/private/webapis/performance/PerformanceEventTiming.js +0 -55
- /package/src/private/{core → styles}/composeStyles.js +0 -0
|
@@ -25,6 +25,9 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = {
|
|
|
25
25
|
disableIntervalMomentum: true,
|
|
26
26
|
maintainVisibleContentPosition: true,
|
|
27
27
|
endFillColor: {process: require('../../StyleSheet/processColor').default},
|
|
28
|
+
experimental_boxShadow: {
|
|
29
|
+
process: require('../../StyleSheet/processBoxShadow').default,
|
|
30
|
+
},
|
|
28
31
|
fadingEdgeLength: true,
|
|
29
32
|
nestedScrollEnabled: true,
|
|
30
33
|
overScrollMode: true,
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import type {
|
|
12
12
|
TScrollViewNativeComponentInstance,
|
|
13
13
|
TScrollViewNativeImperativeHandle,
|
|
14
|
-
} from '../../../src/private/
|
|
14
|
+
} from '../../../src/private/components/useSyncOnScroll';
|
|
15
15
|
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
|
|
16
16
|
import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType';
|
|
17
17
|
import type {PointProp} from '../../StyleSheet/PointPropType';
|
|
@@ -31,11 +31,11 @@ import type {Props as ScrollViewStickyHeaderProps} from './ScrollViewStickyHeade
|
|
|
31
31
|
import {
|
|
32
32
|
HScrollContentViewNativeComponent,
|
|
33
33
|
HScrollViewNativeComponent,
|
|
34
|
-
} from '../../../src/private/
|
|
34
|
+
} from '../../../src/private/components/HScrollViewNativeComponents';
|
|
35
35
|
import {
|
|
36
36
|
VScrollContentViewNativeComponent,
|
|
37
37
|
VScrollViewNativeComponent,
|
|
38
|
-
} from '../../../src/private/
|
|
38
|
+
} from '../../../src/private/components/VScrollViewNativeComponents';
|
|
39
39
|
import AnimatedImplementation from '../../Animated/AnimatedImplementation';
|
|
40
40
|
import FrameRateLogger from '../../Interaction/FrameRateLogger';
|
|
41
41
|
import {findNodeHandle} from '../../ReactNative/RendererProxy';
|
|
@@ -643,7 +643,7 @@ export type Props = $ReadOnly<{|
|
|
|
643
643
|
*/
|
|
644
644
|
/* $FlowFixMe[unclear-type] - how to handle generic type without existential
|
|
645
645
|
* operator? */
|
|
646
|
-
refreshControl?: ?
|
|
646
|
+
refreshControl?: ?ExactReactElement_DEPRECATED<any>,
|
|
647
647
|
children?: React.Node,
|
|
648
648
|
/**
|
|
649
649
|
* A ref to the inner View element of the ScrollView. This should be used
|
|
@@ -1648,7 +1648,7 @@ class ScrollView extends React.Component<Props, State> {
|
|
|
1648
1648
|
this.props.onTouchMove && this.props.onTouchMove(e);
|
|
1649
1649
|
};
|
|
1650
1650
|
|
|
1651
|
-
render(): React.Node
|
|
1651
|
+
render(): React.Node {
|
|
1652
1652
|
const horizontal = this.props.horizontal === true;
|
|
1653
1653
|
|
|
1654
1654
|
const NativeScrollView = horizontal
|
|
@@ -46,6 +46,9 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
|
|
|
46
46
|
},
|
|
47
47
|
decelerationRate: true,
|
|
48
48
|
enableSyncOnScroll: true, // Fabric only.
|
|
49
|
+
experimental_boxShadow: {
|
|
50
|
+
process: require('../../StyleSheet/processBoxShadow').default,
|
|
51
|
+
},
|
|
49
52
|
disableIntervalMomentum: true,
|
|
50
53
|
maintainVisibleContentPosition: true,
|
|
51
54
|
pagingEnabled: true,
|
|
@@ -19,7 +19,7 @@ import * as React from 'react';
|
|
|
19
19
|
import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
|
|
20
20
|
|
|
21
21
|
export type Props = $ReadOnly<{
|
|
22
|
-
children?:
|
|
22
|
+
children?: ExactReactElement_DEPRECATED<$FlowFixMe>,
|
|
23
23
|
nextHeaderLayoutY: ?number,
|
|
24
24
|
onLayout: (event: LayoutEvent) => void,
|
|
25
25
|
scrollAnimatedValue: Animated.Value,
|
|
@@ -272,8 +272,10 @@ class StatusBar extends React.Component<Props> {
|
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
/**
|
|
275
|
-
*
|
|
275
|
+
* DEPRECATED - The status bar network activity indicator is not supported in iOS 13 and later. This will be removed in a future release.
|
|
276
276
|
* @param visible Show the indicator.
|
|
277
|
+
*
|
|
278
|
+
* @deprecated
|
|
277
279
|
*/
|
|
278
280
|
static setNetworkActivityIndicatorVisible(visible: boolean) {
|
|
279
281
|
if (Platform.OS !== 'ios') {
|
|
@@ -739,6 +739,9 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = {
|
|
|
739
739
|
},
|
|
740
740
|
borderTopLeftRadius: true,
|
|
741
741
|
borderTopColor: {process: require('../../StyleSheet/processColor').default},
|
|
742
|
+
experimental_boxShadow: {
|
|
743
|
+
process: require('../../StyleSheet/processBoxShadow').default,
|
|
744
|
+
},
|
|
742
745
|
},
|
|
743
746
|
};
|
|
744
747
|
|
|
@@ -90,6 +90,8 @@ type DataDetectorTypes =
|
|
|
90
90
|
| 'none'
|
|
91
91
|
| 'all';
|
|
92
92
|
|
|
93
|
+
export type SubmitBehavior = 'submit' | 'blurAndSubmit' | 'newline';
|
|
94
|
+
|
|
93
95
|
/**
|
|
94
96
|
* DocumentSelectionState is responsible for maintaining selection information
|
|
95
97
|
* for a document.
|
|
@@ -649,11 +651,39 @@ export interface TextInputProps
|
|
|
649
651
|
autoFocus?: boolean | undefined;
|
|
650
652
|
|
|
651
653
|
/**
|
|
652
|
-
* If true
|
|
653
|
-
* The default value is true
|
|
654
|
+
* If `true`, the text field will blur when submitted.
|
|
655
|
+
* The default value is true for single-line fields and false for
|
|
656
|
+
* multiline fields. Note that for multiline fields, setting `blurOnSubmit`
|
|
657
|
+
* to `true` means that pressing return will blur the field and trigger the
|
|
658
|
+
* `onSubmitEditing` event instead of inserting a newline into the field.
|
|
659
|
+
*
|
|
660
|
+
* @deprecated
|
|
661
|
+
* Note that `submitBehavior` now takes the place of `blurOnSubmit` and will
|
|
662
|
+
* override any behavior defined by `blurOnSubmit`.
|
|
663
|
+
* @see submitBehavior
|
|
654
664
|
*/
|
|
655
665
|
blurOnSubmit?: boolean | undefined;
|
|
656
666
|
|
|
667
|
+
/**
|
|
668
|
+
* When the return key is pressed,
|
|
669
|
+
*
|
|
670
|
+
* For single line inputs:
|
|
671
|
+
*
|
|
672
|
+
* - `'newline`' defaults to `'blurAndSubmit'`
|
|
673
|
+
* - `undefined` defaults to `'blurAndSubmit'`
|
|
674
|
+
*
|
|
675
|
+
* For multiline inputs:
|
|
676
|
+
*
|
|
677
|
+
* - `'newline'` adds a newline
|
|
678
|
+
* - `undefined` defaults to `'newline'`
|
|
679
|
+
*
|
|
680
|
+
* For both single line and multiline inputs:
|
|
681
|
+
*
|
|
682
|
+
* - `'submit'` will only send a submit event and not blur the input
|
|
683
|
+
* - `'blurAndSubmit`' will both blur the input and send a submit event
|
|
684
|
+
*/
|
|
685
|
+
submitBehavior?: SubmitBehavior | undefined;
|
|
686
|
+
|
|
657
687
|
/**
|
|
658
688
|
* If true, caret is hidden. The default value is false.
|
|
659
689
|
*/
|
|
@@ -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
|
-
|
|
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
|
-
}
|
|
1150
|
-
|
|
1151
|
-
if (Object.keys(nativeUpdate).length === 0) {
|
|
1152
|
-
return;
|
|
1153
|
-
}
|
|
1289
|
+
const viewCommands =
|
|
1290
|
+
AndroidTextInputCommands ||
|
|
1291
|
+
(props.multiline === true
|
|
1292
|
+
? RCTMultilineTextInputNativeCommands
|
|
1293
|
+
: RCTSinglelineTextInputNativeCommands);
|
|
1154
1294
|
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
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
|
-
}, [
|
|
1324
|
+
}, []);
|
|
1191
1325
|
|
|
1192
1326
|
const setLocalRef = useCallback(
|
|
1193
1327
|
(instance: TextInputInstance | null) => {
|
|
@@ -1401,12 +1535,18 @@ function InternalTextInput(props: Props): React.Node {
|
|
|
1401
1535
|
};
|
|
1402
1536
|
}
|
|
1403
1537
|
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
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 (typeof flattenedStyle?.fontWeight === 'number') {
|
|
1542
|
+
_style = [
|
|
1543
|
+
_style,
|
|
1544
|
+
{
|
|
1545
|
+
fontWeight:
|
|
1546
|
+
// $FlowFixMe[incompatible-cast]
|
|
1547
|
+
(flattenedStyle.fontWeight.toString(): TextStyleInternal['fontWeight']),
|
|
1548
|
+
},
|
|
1549
|
+
];
|
|
1410
1550
|
}
|
|
1411
1551
|
|
|
1412
1552
|
if (Platform.OS === 'ios') {
|
|
@@ -1417,10 +1557,10 @@ function InternalTextInput(props: Props): React.Node {
|
|
|
1417
1557
|
|
|
1418
1558
|
const useMultilineDefaultStyle =
|
|
1419
1559
|
props.multiline === true &&
|
|
1420
|
-
(
|
|
1421
|
-
(
|
|
1422
|
-
|
|
1423
|
-
|
|
1560
|
+
(flattenedStyle == null ||
|
|
1561
|
+
(flattenedStyle.padding == null &&
|
|
1562
|
+
flattenedStyle.paddingVertical == null &&
|
|
1563
|
+
flattenedStyle.paddingTop == null));
|
|
1424
1564
|
|
|
1425
1565
|
textInput = (
|
|
1426
1566
|
<RCTTextInputView
|
|
@@ -1447,7 +1587,7 @@ function InternalTextInput(props: Props): React.Node {
|
|
|
1447
1587
|
selectionColor={selectionColor}
|
|
1448
1588
|
style={StyleSheet.compose(
|
|
1449
1589
|
useMultilineDefaultStyle ? styles.multilineDefault : null,
|
|
1450
|
-
|
|
1590
|
+
_style,
|
|
1451
1591
|
)}
|
|
1452
1592
|
text={text}
|
|
1453
1593
|
/>
|
|
@@ -1514,7 +1654,7 @@ function InternalTextInput(props: Props): React.Node {
|
|
|
1514
1654
|
onScroll={_onScroll}
|
|
1515
1655
|
onSelectionChange={_onSelectionChange}
|
|
1516
1656
|
placeholder={placeholder}
|
|
1517
|
-
style={
|
|
1657
|
+
style={_style}
|
|
1518
1658
|
text={text}
|
|
1519
1659
|
textBreakStrategy={props.textBreakStrategy}
|
|
1520
1660
|
/>
|