@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
@@ -8,8 +8,11 @@
8
8
  * @format
9
9
  */
10
10
 
11
+ import type {TextStyleProp} from '../StyleSheet/StyleSheet';
12
+ import type {____TextStyle_Internal as TextStyleInternal} from '../StyleSheet/StyleSheetTypes';
11
13
  import type {PressEvent} from '../Types/CoreEventTypes';
12
- import type {TextProps} from './TextProps';
14
+ import type {NativeTextProps} from './TextNativeComponent';
15
+ import type {PressRetentionOffset, TextProps} from './TextProps';
13
16
 
14
17
  import * as PressabilityDebug from '../Pressability/PressabilityDebug';
15
18
  import usePressability from '../Pressability/usePressability';
@@ -21,117 +24,399 @@ import {NativeText, NativeVirtualText} from './TextNativeComponent';
21
24
  import * as React from 'react';
22
25
  import {useContext, useMemo, useState} from 'react';
23
26
 
27
+ type TextForwardRef = React.ElementRef<
28
+ typeof NativeText | typeof NativeVirtualText,
29
+ >;
30
+
24
31
  /**
25
32
  * Text is the fundamental component for displaying text.
26
33
  *
27
34
  * @see https://reactnative.dev/docs/text
28
35
  */
29
- const Text: React.AbstractComponent<
30
- TextProps,
31
- React.ElementRef<typeof NativeText | typeof NativeVirtualText>,
32
- > = React.forwardRef((props: TextProps, forwardedRef) => {
33
- const {
34
- accessible,
35
- accessibilityControls, // Win32
36
- accessibilityDescribedBy, // Win32
37
- accessibilityDescription, // Win32
38
- accessibilityLabel,
39
- accessibilityLevel, // Win32
40
- accessibilityPositionInSet, // Win32
41
- accessibilitySetSize, // Win32
42
- accessibilityState,
43
- allowFontScaling,
44
- 'aria-busy': ariaBusy,
45
- 'aria-checked': ariaChecked,
46
- 'aria-controls': ariaControls, // Win32
47
- 'aria-describedby': ariaDescribedBy, // Win32
48
- 'aria-description': ariaDescription, // Win32
49
- 'aria-disabled': ariaDisabled,
50
- 'aria-expanded': ariaExpanded,
51
- 'aria-label': ariaLabel,
52
- 'aria-level': ariaLevel, // Win32
53
- 'aria-multiselectable': ariaMultiselectable, // Win32
54
- 'aria-posinset': ariaPosinset, // Win32
55
- 'aria-required': ariaRequired, // Win32
56
- 'aria-selected': ariaSelected,
57
- 'aria-setsize': ariaSetsize, // Win32
58
- ellipsizeMode,
59
- disabled,
60
- id,
61
- nativeID,
62
- numberOfLines,
63
- onLongPress,
64
- onPress,
65
- onPressIn,
66
- onPressOut,
67
- onResponderGrant,
68
- onResponderMove,
69
- onResponderRelease,
70
- onResponderTerminate,
71
- onResponderTerminationRequest,
72
- onStartShouldSetResponder,
73
- pressRetentionOffset,
74
- selectable,
75
- selectionColor,
76
- suppressHighlighting,
77
- style,
78
- ...restProps
79
- } = props;
36
+ const Text: React.AbstractComponent<TextProps, TextForwardRef> =
37
+ React.forwardRef(
38
+ (
39
+ {
40
+ accessible,
41
+ accessibilityControls, // Win32
42
+ accessibilityDescribedBy, // Win32
43
+ accessibilityDescription, // Win32
44
+ accessibilityLabel,
45
+ accessibilityLevel, // Win32
46
+ accessibilityPositionInSet, // Win32
47
+ accessibilitySetSize, // Win32
48
+ accessibilityState,
49
+ allowFontScaling,
50
+ 'aria-busy': ariaBusy,
51
+ 'aria-checked': ariaChecked,
52
+ 'aria-controls': ariaControls, // Win32
53
+ 'aria-describedby': ariaDescribedBy, // Win32
54
+ 'aria-description': ariaDescription, // Win32
55
+ 'aria-disabled': ariaDisabled,
56
+ 'aria-expanded': ariaExpanded,
57
+ 'aria-label': ariaLabel,
58
+ 'aria-level': ariaLevel, // Win32
59
+ 'aria-multiselectable': ariaMultiselectable, // Win32
60
+ 'aria-posinset': ariaPosinset, // Win32
61
+ 'aria-required': ariaRequired, // Win32
62
+ 'aria-selected': ariaSelected,
63
+ 'aria-setsize': ariaSetsize, // Win32
64
+ children,
65
+ ellipsizeMode,
66
+ disabled,
67
+ id,
68
+ nativeID,
69
+ numberOfLines,
70
+ onLongPress,
71
+ onPress,
72
+ onPressIn,
73
+ onPressOut,
74
+ onResponderGrant,
75
+ onResponderMove,
76
+ onResponderRelease,
77
+ onResponderTerminate,
78
+ onResponderTerminationRequest,
79
+ onStartShouldSetResponder,
80
+ pressRetentionOffset,
81
+ selectable,
82
+ selectionColor,
83
+ suppressHighlighting,
84
+ style,
85
+ ...restProps
86
+ }: TextProps,
87
+ forwardedRef,
88
+ ) => {
89
+ const _accessibilityLabel = ariaLabel ?? accessibilityLabel;
90
+ const _accessibilityControls = ariaControls ?? accessibilityControls; // Win32
91
+ const _accessibilityDescribedBy = ariaDescribedBy ?? accessibilityDescribedBy; // Win32
92
+ const _accessibilityDescription = ariaDescription ?? accessibilityDescription; // Win32
93
+ const _accessibilityLevel = ariaLevel ?? accessibilityLevel; // Win32
94
+ const _accessibilityPositionInSet = ariaPosinset ?? accessibilityPositionInSet; // Win32
95
+ const _accessibilitySetSize = ariaSetsize ?? accessibilitySetSize; // Win32
80
96
 
81
- const [isHighlighted, setHighlighted] = useState(false);
97
+ let _accessibilityState: ?TextProps['accessibilityState'] =
98
+ accessibilityState;
99
+ if (
100
+ ariaBusy != null ||
101
+ ariaChecked != null ||
102
+ ariaDisabled != null ||
103
+ ariaExpanded != null ||
104
+ ariaSelected != null
105
+ ) {
106
+ if (_accessibilityState != null) {
107
+ _accessibilityState = {
108
+ busy: ariaBusy ?? _accessibilityState.busy,
109
+ checked: ariaChecked ?? _accessibilityState.checked,
110
+ disabled: ariaDisabled ?? _accessibilityState.disabled,
111
+ expanded: ariaExpanded ?? _accessibilityState.expanded,
112
+ multiselectable: ariaMultiselectable ?? accessibilityState?.multiselectable, // Win32
113
+ required: ariaRequired ?? accessibilityState?.required, // Win32
114
+ selected: ariaSelected ?? _accessibilityState.selected,
115
+ };
116
+ } else {
117
+ _accessibilityState = {
118
+ busy: ariaBusy,
119
+ checked: ariaChecked,
120
+ disabled: ariaDisabled,
121
+ expanded: ariaExpanded,
122
+ multiselectable: ariaMultiselectable, // Win32,
123
+ required: ariaRequired, // Win32
124
+ selected: ariaSelected,
125
+ };
126
+ }
127
+ }
82
128
 
83
- const _accessibilityLabel = ariaLabel ?? accessibilityLabel;
84
-
85
- let _accessibilityState: ?TextProps['accessibilityState'] =
86
- accessibilityState;
87
- if (
88
- ariaBusy != null ||
89
- ariaChecked != null ||
90
- ariaDisabled != null ||
91
- ariaExpanded != null ||
92
- ariaMultiselectable != null ||
93
- ariaRequired != null ||
94
- ariaSelected != null
95
- ) {
96
- if (_accessibilityState != null) {
97
- _accessibilityState = {
98
- busy: ariaBusy ?? _accessibilityState.busy,
99
- checked: ariaChecked ?? _accessibilityState.checked,
100
- disabled: ariaDisabled ?? _accessibilityState.disabled,
101
- expanded: ariaExpanded ?? _accessibilityState.expanded,
102
- multiselectable:
103
- ariaMultiselectable ?? accessibilityState?.multiselectable, // Win32
104
- required: ariaRequired ?? accessibilityState?.required, // Win32
105
- selected: ariaSelected ?? _accessibilityState.selected,
106
- };
107
- } else {
108
- _accessibilityState = {
109
- busy: ariaBusy,
110
- checked: ariaChecked,
111
- disabled: ariaDisabled,
112
- expanded: ariaExpanded,
113
- multiselectable: ariaMultiselectable, // Win32,
114
- required: ariaRequired, // Win32
115
- selected: ariaSelected,
116
- };
117
- }
118
- }
129
+ const _accessibilityStateDisabled = _accessibilityState?.disabled;
130
+ const _disabled = disabled ?? _accessibilityStateDisabled;
119
131
 
120
- const _accessibilityStateDisabled = _accessibilityState?.disabled;
121
- const _disabled = disabled ?? _accessibilityStateDisabled;
132
+ const isPressable =
133
+ (onPress != null ||
134
+ onLongPress != null ||
135
+ onStartShouldSetResponder != null) &&
136
+ _disabled !== true;
122
137
 
123
- const isPressable =
124
- (onPress != null ||
125
- onLongPress != null ||
126
- onStartShouldSetResponder != null) &&
127
- _disabled !== true;
138
+ // TODO: Move this processing to the view configuration.
139
+ const _selectionColor =
140
+ selectionColor == null ? null : processColor(selectionColor);
128
141
 
129
- const initialized = useLazyInitialization(isPressable);
130
- const config = useMemo(() => {
131
- if (!initialized) {
132
- return null;
142
+ let _style = style;
143
+ if (__DEV__) {
144
+ if (PressabilityDebug.isEnabled() && onPress != null) {
145
+ _style = [style, {color: 'magenta'}];
146
+ }
147
+ }
148
+
149
+ let _numberOfLines = numberOfLines;
150
+ if (_numberOfLines != null && !(_numberOfLines >= 0)) {
151
+ if (__DEV__) {
152
+ console.error(
153
+ `'numberOfLines' in <Text> must be a non-negative number, received: ${_numberOfLines}. The value will be set to 0.`,
154
+ );
155
+ }
156
+ _numberOfLines = 0;
157
+ }
158
+
159
+ let _selectable = selectable;
160
+
161
+ let processedStyle = flattenStyle<TextStyleProp>(_style);
162
+ if (processedStyle != null) {
163
+ let overrides: ?{...TextStyleInternal} = null;
164
+ if (typeof processedStyle.fontWeight === 'number') {
165
+ overrides = overrides || ({}: {...TextStyleInternal});
166
+ overrides.fontWeight =
167
+ // $FlowFixMe[incompatible-cast]
168
+ (processedStyle.fontWeight.toString(): TextStyleInternal['fontWeight']);
169
+ }
170
+
171
+ if (processedStyle.userSelect != null) {
172
+ _selectable = userSelectToSelectableMap[processedStyle.userSelect];
173
+ overrides = overrides || ({}: {...TextStyleInternal});
174
+ overrides.userSelect = undefined;
175
+ }
176
+
177
+ if (processedStyle.verticalAlign != null) {
178
+ overrides = overrides || ({}: {...TextStyleInternal});
179
+ overrides.textAlignVertical =
180
+ verticalAlignToTextAlignVerticalMap[processedStyle.verticalAlign];
181
+ overrides.verticalAlign = undefined;
182
+ }
183
+
184
+ if (overrides != null) {
185
+ // $FlowFixMe[incompatible-type]
186
+ _style = [_style, overrides];
187
+ }
188
+ }
189
+
190
+ const _nativeID = id ?? nativeID;
191
+
192
+ const hasTextAncestor = useContext(TextAncestor);
193
+ if (hasTextAncestor) {
194
+ if (isPressable) {
195
+ return (
196
+ <NativePressableVirtualText
197
+ ref={forwardedRef}
198
+ textProps={{
199
+ ...restProps,
200
+ accessibilityLabel: _accessibilityLabel,
201
+ accessibilityState: _accessibilityState,
202
+ accessibilityControls: _accessibilityControls, // Win32
203
+ accessibilityDescribedBy: _accessibilityDescribedBy, // Win32
204
+ accessibilityDescription: _accessibilityDescription, // Win32
205
+ accessibilityLevel: _accessibilityLevel, // Win32
206
+ accessibilityPositionInSet: _accessibilityPositionInSet, // Win32
207
+ accessibilitySetSize: _accessibilitySetSize, // Win32
208
+ nativeID: _nativeID,
209
+ numberOfLines: _numberOfLines,
210
+ selectable: _selectable,
211
+ selectionColor: _selectionColor,
212
+ style: _style,
213
+ disabled: disabled,
214
+ children,
215
+ }}
216
+ textPressabilityProps={{
217
+ onLongPress,
218
+ onPress,
219
+ onPressIn,
220
+ onPressOut,
221
+ onResponderGrant,
222
+ onResponderMove,
223
+ onResponderRelease,
224
+ onResponderTerminate,
225
+ onResponderTerminationRequest,
226
+ onStartShouldSetResponder,
227
+ pressRetentionOffset,
228
+ suppressHighlighting,
229
+ }}
230
+ />
231
+ );
232
+ }
233
+
234
+ return (
235
+ <NativeVirtualText
236
+ {...restProps}
237
+ accessibilityLabel={_accessibilityLabel}
238
+ accessibilityState={_accessibilityState}
239
+ accessibilityControls={_accessibilityControls} // Win32
240
+ accessibilityDescribedBy={_accessibilityDescribedBy} // Win32
241
+ accessibilityDescription={_accessibilityDescription} // Win32
242
+ accessibilityLevel={_accessibilityLevel} // Win32
243
+ accessibilityPositionInSet={_accessibilityPositionInSet} // Win32
244
+ accessibilitySetSize={_accessibilitySetSize} // Win32
245
+ isHighlighted={false}
246
+ isPressable={false}
247
+ nativeID={_nativeID}
248
+ numberOfLines={_numberOfLines}
249
+ ref={forwardedRef}
250
+ selectable={_selectable}
251
+ selectionColor={_selectionColor}
252
+ style={_style}
253
+ disabled={disabled}>
254
+ {children}
255
+ </NativeVirtualText>
256
+ );
257
+ }
258
+
259
+ // If the disabled prop and accessibilityState.disabled are out of sync but not both in
260
+ // falsy states we need to update the accessibilityState object to use the disabled prop.
261
+ if (
262
+ _disabled !== _accessibilityStateDisabled &&
263
+ ((_disabled != null && _disabled !== false) ||
264
+ (_accessibilityStateDisabled != null &&
265
+ _accessibilityStateDisabled !== false))
266
+ ) {
267
+ _accessibilityState = {..._accessibilityState, disabled: _disabled};
268
+ }
269
+
270
+ const _accessible = Platform.select({
271
+ ios: accessible !== false,
272
+ android:
273
+ accessible == null
274
+ ? onPress != null || onLongPress != null
275
+ : accessible,
276
+ default: accessible !== false, // Win32
277
+ });
278
+
279
+ let nativeText = null;
280
+ if (isPressable) {
281
+ nativeText = (
282
+ <NativePressableText
283
+ ref={forwardedRef}
284
+ textProps={{
285
+ ...restProps,
286
+ accessibilityLabel: _accessibilityLabel,
287
+ accessibilityState: _accessibilityState,
288
+ accessibilityControls: _accessibilityControls, // Win32
289
+ accessibilityDescribedBy: _accessibilityDescribedBy, // Win32
290
+ accessibilityDescription: _accessibilityDescription, // Win32
291
+ accessibilityLevel: _accessibilityLevel, // Win32
292
+ accessibilityPositionInSet: _accessibilityPositionInSet, // Win32
293
+ accessibilitySetSize: _accessibilitySetSize, // Win32
294
+ accessible: _accessible,
295
+ allowFontScaling: allowFontScaling !== false,
296
+ disabled: _disabled,
297
+ ellipsizeMode: ellipsizeMode ?? 'tail',
298
+ nativeID: _nativeID,
299
+ numberOfLines: _numberOfLines,
300
+ selectable: _selectable,
301
+ selectionColor: _selectionColor,
302
+ style: _style,
303
+ children,
304
+ }}
305
+ textPressabilityProps={{
306
+ onLongPress,
307
+ onPress,
308
+ onPressIn,
309
+ onPressOut,
310
+ onResponderGrant,
311
+ onResponderMove,
312
+ onResponderRelease,
313
+ onResponderTerminate,
314
+ onResponderTerminationRequest,
315
+ onStartShouldSetResponder,
316
+ pressRetentionOffset,
317
+ suppressHighlighting,
318
+ }}
319
+ />
320
+ );
321
+ } else {
322
+ nativeText = (
323
+ <NativeText
324
+ {...restProps}
325
+ accessibilityLabel={_accessibilityLabel}
326
+ accessibilityState={_accessibilityState}
327
+ accessibilityControls={_accessibilityControls} // Win32
328
+ accessibilityDescribedBy={_accessibilityDescribedBy} // Win32
329
+ accessibilityDescription={_accessibilityDescription} // Win32
330
+ accessibilityLevel={_accessibilityLevel} // Win32
331
+ accessibilityPositionInSet={_accessibilityPositionInSet} // Win32
332
+ accessibilitySetSize={_accessibilitySetSize} // Win32
333
+ accessible={_accessible}
334
+ allowFontScaling={allowFontScaling !== false}
335
+ disabled={_disabled}
336
+ ellipsizeMode={ellipsizeMode ?? 'tail'}
337
+ isHighlighted={false}
338
+ nativeID={_nativeID}
339
+ numberOfLines={_numberOfLines}
340
+ ref={forwardedRef}
341
+ selectable={_selectable}
342
+ selectionColor={_selectionColor}
343
+ style={_style}>
344
+ {children}
345
+ </NativeText>
346
+ );
347
+ }
348
+
349
+ if (children == null) {
350
+ return nativeText;
351
+ }
352
+
353
+ // If the children do not contain a JSX element it would not be possible to have a
354
+ // nested `Text` component so we can skip adding the `TextAncestor` context wrapper
355
+ // which has a performance overhead. Since we do this for performance reasons we need
356
+ // to keep the check simple to avoid regressing overall perf. For this reason the
357
+ // `children.length` constant is set to `3`, this should be a reasonable tradeoff
358
+ // to capture the majority of `Text` uses but also not make this check too expensive.
359
+ if (Array.isArray(children) && children.length <= 3) {
360
+ let hasNonTextChild = false;
361
+ for (let child of children) {
362
+ if (child != null && typeof child === 'object') {
363
+ hasNonTextChild = true;
364
+ break;
365
+ }
366
+ }
367
+ if (!hasNonTextChild) {
368
+ return nativeText;
369
+ }
370
+ } else if (typeof children !== 'object') {
371
+ return nativeText;
372
+ }
373
+
374
+ return (
375
+ <TextAncestor.Provider value={true}>{nativeText}</TextAncestor.Provider>
376
+ );
133
377
  }
378
+ );
379
+
380
+ Text.displayName = 'Text';
134
381
 
382
+ type TextPressabilityProps = $ReadOnly<{
383
+ onLongPress?: ?(event: PressEvent) => mixed,
384
+ onPress?: ?(event: PressEvent) => mixed,
385
+ onPressIn?: ?(event: PressEvent) => mixed,
386
+ onPressOut?: ?(event: PressEvent) => mixed,
387
+ onResponderGrant?: ?(event: PressEvent) => void,
388
+ onResponderMove?: ?(event: PressEvent) => void,
389
+ onResponderRelease?: ?(event: PressEvent) => void,
390
+ onResponderTerminate?: ?(event: PressEvent) => void,
391
+ onResponderTerminationRequest?: ?() => boolean,
392
+ onStartShouldSetResponder?: ?() => boolean,
393
+ pressRetentionOffset?: ?PressRetentionOffset,
394
+ suppressHighlighting?: ?boolean,
395
+ }>;
396
+
397
+ /**
398
+ * Hook that handles setting up Pressability of Text components.
399
+ *
400
+ * NOTE: This hook is relatively expensive so it should only be used absolutely necessary.
401
+ */
402
+ function useTextPressability({
403
+ onLongPress,
404
+ onPress,
405
+ onPressIn,
406
+ onPressOut,
407
+ onResponderGrant,
408
+ onResponderMove,
409
+ onResponderRelease,
410
+ onResponderTerminate,
411
+ onResponderTerminationRequest,
412
+ onStartShouldSetResponder,
413
+ pressRetentionOffset,
414
+ suppressHighlighting,
415
+ }: TextPressabilityProps) {
416
+ const [isHighlighted, setHighlighted] = useState(false);
417
+
418
+ // Setup pressability config and wrap callbacks needs to track the highlight state.
419
+ const config = useMemo(() => {
135
420
  let _onPressIn = onPressIn;
136
421
  let _onPressOut = onPressOut;
137
422
 
@@ -151,7 +436,7 @@ const Text: React.AbstractComponent<
151
436
  }
152
437
 
153
438
  return {
154
- disabled: !isPressable,
439
+ disabled: false,
155
440
  pressRectOffset: pressRetentionOffset,
156
441
  onLongPress,
157
442
  onPress,
@@ -159,8 +444,6 @@ const Text: React.AbstractComponent<
159
444
  onPressOut: _onPressOut,
160
445
  };
161
446
  }, [
162
- initialized,
163
- isPressable,
164
447
  pressRetentionOffset,
165
448
  onLongPress,
166
449
  onPress,
@@ -169,7 +452,10 @@ const Text: React.AbstractComponent<
169
452
  suppressHighlighting,
170
453
  ]);
171
454
 
455
+ // Init the pressability class
172
456
  const eventHandlers = usePressability(config);
457
+
458
+ // Create NativeText event handlers which proxy events to pressability
173
459
  const eventHandlersForText = useMemo(
174
460
  () =>
175
461
  eventHandlers == null
@@ -220,140 +506,67 @@ const Text: React.AbstractComponent<
220
506
  ],
221
507
  );
222
508
 
223
- // TODO: Move this processing to the view configuration.
224
- const _selectionColor =
225
- selectionColor == null ? null : processColor(selectionColor);
226
-
227
- let _style = style;
228
- if (__DEV__) {
229
- if (PressabilityDebug.isEnabled() && onPress != null) {
230
- _style = [style, {color: 'magenta'}];
231
- }
232
- }
509
+ // Return the highlight state and NativeText event handlers
510
+ return useMemo(
511
+ () => [isHighlighted, eventHandlersForText],
512
+ [isHighlighted, eventHandlersForText],
513
+ );
514
+ }
233
515
 
234
- let _numberOfLines = numberOfLines;
235
- if (_numberOfLines != null && !(_numberOfLines >= 0)) {
236
- if (__DEV__) {
237
- console.error(
238
- `'numberOfLines' in <Text> must be a non-negative number, received: ${_numberOfLines}. The value will be set to 0.`,
239
- );
240
- }
241
- _numberOfLines = 0;
242
- }
243
-
244
- let _selectable = selectable;
245
- const processedStyle = flattenStyle(_style);
246
- if (processedStyle != null) {
247
- if (typeof processedStyle.fontWeight === 'number') {
248
- // $FlowFixMe[cannot-write]
249
- processedStyle.fontWeight = processedStyle.fontWeight.toString();
250
- }
516
+ type NativePressableTextProps = $ReadOnly<{
517
+ textProps: NativeTextProps,
518
+ textPressabilityProps: TextPressabilityProps,
519
+ }>;
251
520
 
252
- if (processedStyle.userSelect != null) {
253
- _selectable = userSelectToSelectableMap[processedStyle.userSelect];
254
- // $FlowFixMe[cannot-write]
255
- delete processedStyle.userSelect;
256
- }
257
-
258
- if (processedStyle.verticalAlign != null) {
259
- // $FlowFixMe[cannot-write]
260
- processedStyle.textAlignVertical =
261
- verticalAlignToTextAlignVerticalMap[processedStyle.verticalAlign];
262
- // $FlowFixMe[cannot-write]
263
- delete processedStyle.verticalAlign;
264
- }
265
- }
266
-
267
- const _nativeID = id ?? nativeID;
268
-
269
- const hasTextAncestor = useContext(TextAncestor);
270
- if (hasTextAncestor) {
271
- return (
272
- <NativeVirtualText
273
- {...restProps}
274
- {...eventHandlersForText}
275
- accessibilityLabel={_accessibilityLabel}
276
- accessibilityState={_accessibilityState}
277
- accessibilityControls={ariaControls ?? accessibilityControls} // Win32
278
- accessibilityDescribedBy={ariaDescribedBy ?? accessibilityDescribedBy} // Win32
279
- accessibilityDescription={ariaDescription ?? accessibilityDescription} // Win32
280
- accessibilityLevel={ariaLevel ?? accessibilityLevel} // Win32
281
- accessibilityPositionInSet={ariaPosinset ?? accessibilityPositionInSet} // Win32
282
- accessibilitySetSize={ariaSetsize ?? accessibilitySetSize} // Win32
283
- isHighlighted={isHighlighted}
284
- isPressable={isPressable}
285
- nativeID={_nativeID}
286
- numberOfLines={_numberOfLines}
287
- ref={forwardedRef}
288
- selectable={_selectable}
289
- selectionColor={_selectionColor}
290
- style={processedStyle}
291
- disabled={disabled}
292
- />
293
- );
294
- }
295
-
296
- // If the disabled prop and accessibilityState.disabled are out of sync but not both in
297
- // falsy states we need to update the accessibilityState object to use the disabled prop.
298
- if (
299
- _disabled !== _accessibilityStateDisabled &&
300
- ((_disabled != null && _disabled !== false) ||
301
- (_accessibilityStateDisabled != null &&
302
- _accessibilityStateDisabled !== false))
303
- ) {
304
- _accessibilityState = {..._accessibilityState, disabled: _disabled};
305
- }
306
-
307
- const _accessible = Platform.select({
308
- ios: accessible !== false,
309
- android:
310
- accessible == null ? onPress != null || onLongPress != null : accessible,
311
- default: accessible !== false,
312
- });
521
+ /**
522
+ * Wrap the NativeVirtualText component and initialize pressability.
523
+ *
524
+ * This logic is split out from the main Text component to enable the more
525
+ * expensive pressability logic to be only initialized when needed.
526
+ */
527
+ const NativePressableVirtualText: React.AbstractComponent<
528
+ NativePressableTextProps,
529
+ TextForwardRef,
530
+ > = React.forwardRef(({textProps, textPressabilityProps}, forwardedRef) => {
531
+ const [isHighlighted, eventHandlersForText] = useTextPressability(
532
+ textPressabilityProps,
533
+ );
313
534
 
314
535
  return (
315
- <TextAncestor.Provider value={true}>
316
- <NativeText
317
- {...restProps}
318
- {...eventHandlersForText}
319
- accessibilityLabel={_accessibilityLabel}
320
- accessibilityState={_accessibilityState}
321
- accessible={_accessible}
322
- accessibilityControls={ariaControls ?? accessibilityControls} // Win32
323
- accessibilityDescribedBy={ariaDescribedBy ?? accessibilityDescribedBy} // Win32
324
- accessibilityDescription={ariaDescription ?? accessibilityDescription} // Win32
325
- accessibilityLevel={ariaLevel ?? accessibilityLevel} // Win32
326
- accessibilityPositionInSet={ariaPosinset ?? accessibilityPositionInSet} // Win32
327
- accessibilitySetSize={ariaSetsize ?? accessibilitySetSize} // Win32
328
- allowFontScaling={allowFontScaling !== false}
329
- disabled={_disabled}
330
- ellipsizeMode={ellipsizeMode ?? 'tail'}
331
- isHighlighted={isHighlighted}
332
- nativeID={_nativeID}
333
- numberOfLines={_numberOfLines}
334
- ref={forwardedRef}
335
- selectable={_selectable}
336
- selectionColor={_selectionColor}
337
- style={processedStyle}
338
- />
339
- </TextAncestor.Provider>
536
+ <NativeVirtualText
537
+ {...textProps}
538
+ {...eventHandlersForText}
539
+ isHighlighted={isHighlighted}
540
+ isPressable={true}
541
+ ref={forwardedRef}
542
+ />
340
543
  );
341
544
  });
342
545
 
343
- Text.displayName = 'Text';
344
-
345
546
  /**
346
- * Returns false until the first time `newValue` is true, after which this will
347
- * always return true. This is necessary to lazily initialize `Pressability` so
348
- * we do not eagerly create one for every pressable `Text` component.
547
+ * Wrap the NativeText component and initialize pressability.
548
+ *
549
+ * This logic is split out from the main Text component to enable the more
550
+ * expensive pressability logic to be only initialized when needed.
349
551
  */
350
- function useLazyInitialization(newValue: boolean): boolean {
351
- const [oldValue, setValue] = useState(newValue);
352
- if (!oldValue && newValue) {
353
- setValue(newValue);
354
- }
355
- return oldValue;
356
- }
552
+ const NativePressableText: React.AbstractComponent<
553
+ NativePressableTextProps,
554
+ TextForwardRef,
555
+ > = React.forwardRef(({textProps, textPressabilityProps}, forwardedRef) => {
556
+ const [isHighlighted, eventHandlersForText] = useTextPressability(
557
+ textPressabilityProps,
558
+ );
559
+
560
+ return (
561
+ <NativeText
562
+ {...textProps}
563
+ {...eventHandlersForText}
564
+ isHighlighted={isHighlighted}
565
+ isPressable={true}
566
+ ref={forwardedRef}
567
+ />
568
+ );
569
+ });
357
570
 
358
571
  const userSelectToSelectableMap = {
359
572
  auto: true,
@@ -370,4 +583,4 @@ const verticalAlignToTextAlignVerticalMap = {
370
583
  middle: 'center',
371
584
  };
372
585
 
373
- module.exports = Text;
586
+ module.exports = Text;