@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.
Files changed (142) hide show
  1. package/.flowconfig +2 -4
  2. package/CHANGELOG.json +31 -1
  3. package/CHANGELOG.md +24 -8
  4. package/Libraries/Alert/Alert.js +3 -0
  5. package/Libraries/Animated/AnimatedImplementation.js +7 -7
  6. package/Libraries/Animated/animations/Animation.js +10 -0
  7. package/Libraries/Animated/animations/TimingAnimation.js +1 -0
  8. package/Libraries/Animated/components/AnimatedScrollView.js +2 -2
  9. package/Libraries/Animated/createAnimatedComponent.js +1 -1
  10. package/Libraries/Animated/nodes/AnimatedValue.js +1 -0
  11. package/Libraries/Animated/useAnimatedProps.js +138 -6
  12. package/Libraries/BatchedBridge/NativeModules.js +2 -0
  13. package/Libraries/Blob/FileReader.js +1 -1
  14. package/Libraries/Blob/URL.js +2 -62
  15. package/Libraries/Blob/URLSearchParams.js +71 -0
  16. package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +1 -1
  17. package/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js +1 -1
  18. package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +3 -0
  19. package/Libraries/Components/ScrollView/ScrollView.js +5 -5
  20. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +3 -0
  21. package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +1 -1
  22. package/Libraries/Components/StatusBar/StatusBar.js +3 -1
  23. package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +3 -0
  24. package/Libraries/Components/TextInput/TextInput.d.ts +32 -2
  25. package/Libraries/Components/TextInput/TextInput.js +220 -80
  26. package/Libraries/Components/TextInput/TextInput.win32.js +220 -86
  27. package/Libraries/Components/View/ReactNativeStyleAttributes.js +22 -0
  28. package/Libraries/Components/View/ReactNativeViewAttributes.js +2 -0
  29. package/Libraries/Components/View/ReactNativeViewAttributes.win32.js +2 -0
  30. package/Libraries/Components/View/ViewAccessibility.d.ts +15 -0
  31. package/Libraries/Components/View/ViewNativeComponent.js +6 -0
  32. package/Libraries/Components/View/ViewPropTypes.js +14 -0
  33. package/Libraries/Components/View/ViewPropTypes.win32.js +14 -0
  34. package/Libraries/Core/ExceptionsManager.js +2 -0
  35. package/Libraries/Core/InitializeCore.js +1 -1
  36. package/Libraries/Core/ReactFiberErrorDialog.js +3 -0
  37. package/Libraries/Core/ReactNativeVersion.js +1 -1
  38. package/Libraries/Core/setUpErrorHandling.js +7 -1
  39. package/Libraries/Core/setUpReactRefresh.js +0 -4
  40. package/Libraries/Image/AssetSourceResolver.js +28 -1
  41. package/Libraries/Image/Image.android.js +9 -14
  42. package/Libraries/Image/Image.ios.js +11 -22
  43. package/Libraries/Image/Image.win32.js +10 -21
  44. package/Libraries/Image/ImageBackground.js +1 -8
  45. package/Libraries/Image/ImageUtils.js +9 -9
  46. package/Libraries/Image/ImageViewNativeComponent.js +4 -0
  47. package/Libraries/Inspector/NetworkOverlay.js +1 -1
  48. package/Libraries/Interaction/TaskQueue.js +1 -0
  49. package/Libraries/Lists/FlatList.js +1 -1
  50. package/Libraries/Lists/SectionList.js +2 -2
  51. package/Libraries/Lists/SectionListModern.js +1 -1
  52. package/Libraries/LogBox/Data/LogBoxData.js +31 -4
  53. package/Libraries/NativeComponent/BaseViewConfig.android.js +2 -0
  54. package/Libraries/NativeComponent/BaseViewConfig.ios.js +7 -0
  55. package/Libraries/NativeComponent/BaseViewConfig.win32.js +7 -0
  56. package/Libraries/NativeComponent/NativeComponentRegistry.js +9 -2
  57. package/Libraries/Network/XMLHttpRequest.js +4 -2
  58. package/Libraries/ReactNative/BridgelessUIManager.js +1 -0
  59. package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricHostComponent.js +1 -1
  60. package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricPublicInstance.js +5 -5
  61. package/Libraries/ReactNative/RendererImplementation.js +24 -2
  62. package/Libraries/ReactNative/getNativeComponentAttributes.js +8 -0
  63. package/Libraries/Renderer/shims/ReactNativeTypes.js +3 -1
  64. package/Libraries/StyleSheet/StyleSheet.js +1 -1
  65. package/Libraries/StyleSheet/StyleSheet.win32.js +1 -1
  66. package/Libraries/StyleSheet/StyleSheetTypes.d.ts +57 -19
  67. package/Libraries/StyleSheet/StyleSheetTypes.js +60 -23
  68. package/Libraries/StyleSheet/processBackgroundImage.js +286 -0
  69. package/Libraries/StyleSheet/processBoxShadow.js +211 -0
  70. package/Libraries/StyleSheet/processFilter.js +24 -14
  71. package/Libraries/Text/Text.js +395 -212
  72. package/Libraries/Text/Text.win32.js +443 -245
  73. package/Libraries/Text/TextNativeComponent.js +7 -0
  74. package/Libraries/Text/TextNativeComponent.win32.js +7 -0
  75. package/Libraries/TurboModule/TurboModuleRegistry.js +13 -50
  76. package/Libraries/Types/CodegenTypes.js +3 -1
  77. package/Libraries/Utilities/HMRClient.js +1 -0
  78. package/Libraries/Utilities/Platform.android.js +1 -1
  79. package/Libraries/Utilities/Platform.d.ts +1 -1
  80. package/Libraries/Utilities/Platform.flow.js +2 -2
  81. package/Libraries/Utilities/Platform.flow.win32.js +3 -3
  82. package/Libraries/Utilities/Platform.ios.js +1 -1
  83. package/Libraries/Utilities/Platform.win32.js +1 -1
  84. package/Libraries/Utilities/ReactNativeTestTools.js +1 -1
  85. package/Libraries/WebSocket/WebSocket.js +1 -1
  86. package/Libraries/vendor/emitter/EventEmitter.js +1 -0
  87. package/flow/jest.js +2 -2
  88. package/index.js +1 -0
  89. package/index.win32.js +1 -0
  90. package/jest/mockModal.js +1 -3
  91. package/jest/mockScrollView.js +1 -1
  92. package/jest/renderer.js +2 -2
  93. package/jest/setup.js +16 -9
  94. package/overrides.json +16 -16
  95. package/package.json +15 -15
  96. package/src/private/{core/components → components}/HScrollViewNativeComponents.js +8 -8
  97. package/src/private/{core/components → components}/VScrollViewNativeComponents.js +7 -7
  98. package/src/private/{core/components → components}/useSyncOnScroll.js +2 -2
  99. package/src/private/featureflags/ReactNativeFeatureFlags.js +143 -19
  100. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +25 -5
  101. package/src/private/hooks/DebouncedEffectImplementation.js +148 -0
  102. package/src/private/hooks/useDebouncedEffect.js +23 -0
  103. package/{Libraries/Core → src/private/renderer/errorhandling}/ErrorHandlers.js +14 -4
  104. package/src/private/setup/setUpDOM.js +28 -0
  105. package/src/private/setup/setUpIntersectionObserver.js +27 -0
  106. package/src/private/setup/setUpMutationObserver.js +26 -0
  107. package/src/private/setup/setUpPerformanceObserver.js +64 -0
  108. package/src/private/specs/modules/NativeDebuggerSessionObserver.js +23 -0
  109. package/src/private/specs/modules/NativeLinkingManager.js +1 -1
  110. package/src/private/specs/modules/NativePlatformConstantsAndroid.js +1 -1
  111. package/src/private/specs/modules/NativePlatformConstantsIOS.js +1 -1
  112. package/src/private/specs/modules/NativePlatformConstantsWin.js +8 -1
  113. package/src/private/webapis/dom/nodes/ReadOnlyNode.js +6 -4
  114. package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver}/IntersectionObserver.js +1 -1
  115. package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver}/IntersectionObserverEntry.js +3 -3
  116. package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver}/IntersectionObserverManager.js +5 -8
  117. package/src/private/{specs/modules → webapis/intersectionobserver/specs}/NativeIntersectionObserver.js +2 -2
  118. package/{Libraries/IntersectionObserver → src/private/webapis/intersectionobserver/specs}/__mocks__/NativeIntersectionObserver.js +4 -4
  119. package/{Libraries/MutationObserver → src/private/webapis/mutationobserver}/MutationObserver.js +1 -1
  120. package/{Libraries/MutationObserver → src/private/webapis/mutationobserver}/MutationObserverManager.js +5 -5
  121. package/{Libraries/MutationObserver → src/private/webapis/mutationobserver}/MutationRecord.js +4 -6
  122. package/src/private/{specs/modules → webapis/mutationobserver/specs}/NativeMutationObserver.js +2 -2
  123. package/{Libraries/MutationObserver → src/private/webapis/mutationobserver/specs}/__mocks__/NativeMutationObserver.js +5 -5
  124. package/src/private/webapis/performance/{EventCounts.js → EventTiming.js} +65 -3
  125. package/src/private/webapis/performance/LongTasks.js +39 -0
  126. package/src/private/webapis/performance/Performance.js +22 -9
  127. package/src/private/webapis/performance/PerformanceEntry.js +36 -18
  128. package/src/private/webapis/performance/PerformanceObserver.js +29 -43
  129. package/src/private/webapis/performance/RawPerformanceEntry.js +24 -1
  130. package/src/private/webapis/performance/UserTiming.js +17 -12
  131. package/src/private/webapis/performance/specs/NativePerformanceObserver.js +1 -1
  132. package/src-win/Libraries/Components/View/ViewAccessibility.d.ts +15 -0
  133. package/types/experimental.d.ts +20 -1
  134. package/Libraries/Core/setUpIntersectionObserver.js +0 -16
  135. package/Libraries/Core/setUpMutationObserver.js +0 -16
  136. package/Libraries/Core/setUpPerformanceObserver.js +0 -18
  137. package/Libraries/IntersectionObserver/NativeIntersectionObserver.js +0 -13
  138. package/Libraries/MutationObserver/NativeMutationObserver.js +0 -13
  139. package/Libraries/Text/TextOptimized.js +0 -538
  140. package/src/private/core/setUpDOM.js +0 -18
  141. package/src/private/webapis/performance/PerformanceEventTiming.js +0 -55
  142. /package/src/private/{core → styles}/composeStyles.js +0 -0
@@ -8,10 +8,12 @@
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
- import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
15
17
  import * as PressabilityDebug from '../Pressability/PressabilityDebug';
16
18
  import usePressability from '../Pressability/usePressability';
17
19
  import flattenStyle from '../StyleSheet/flattenStyle';
@@ -19,121 +21,402 @@ import processColor from '../StyleSheet/processColor';
19
21
  import Platform from '../Utilities/Platform';
20
22
  import TextAncestor from './TextAncestor';
21
23
  import {NativeText, NativeVirtualText} from './TextNativeComponent';
22
- import TextOptimized from './TextOptimized';
23
24
  import * as React from 'react';
24
25
  import {useContext, useMemo, useState} from 'react';
25
26
 
27
+ type TextForwardRef = React.ElementRef<
28
+ typeof NativeText | typeof NativeVirtualText,
29
+ >;
30
+
26
31
  /**
27
32
  * Text is the fundamental component for displaying text.
28
33
  *
29
34
  * @see https://reactnative.dev/docs/text
30
35
  */
31
- const TextLegacy: React.AbstractComponent<
32
- TextProps,
33
- React.ElementRef<typeof NativeText | typeof NativeVirtualText>,
34
- > = React.forwardRef((props: TextProps, forwardedRef) => {
35
- const {
36
- accessible,
37
- accessibilityControls, // Win32
38
- accessibilityDescribedBy, // Win32
39
- accessibilityDescription, // Win32
40
- accessibilityLabel,
41
- accessibilityLevel, // Win32
42
- accessibilityPositionInSet, // Win32
43
- accessibilitySetSize, // Win32
44
- accessibilityState,
45
- allowFontScaling,
46
- 'aria-busy': ariaBusy,
47
- 'aria-checked': ariaChecked,
48
- 'aria-controls': ariaControls, // Win32
49
- 'aria-describedby': ariaDescribedBy, // Win32
50
- 'aria-description': ariaDescription, // Win32
51
- 'aria-disabled': ariaDisabled,
52
- 'aria-expanded': ariaExpanded,
53
- 'aria-label': ariaLabel,
54
- 'aria-level': ariaLevel, // Win32
55
- 'aria-multiselectable': ariaMultiselectable, // Win32
56
- 'aria-posinset': ariaPosinset, // Win32
57
- 'aria-required': ariaRequired, // Win32
58
- 'aria-selected': ariaSelected,
59
- 'aria-setsize': ariaSetsize, // Win32
60
- ellipsizeMode,
61
- disabled,
62
- id,
63
- nativeID,
64
- numberOfLines,
65
- onLongPress,
66
- onPress,
67
- onPressIn,
68
- onPressOut,
69
- onResponderGrant,
70
- onResponderMove,
71
- onResponderRelease,
72
- onResponderTerminate,
73
- onResponderTerminationRequest,
74
- onStartShouldSetResponder,
75
- pressRetentionOffset,
76
- selectable,
77
- selectionColor,
78
- suppressHighlighting,
79
- style,
80
- ...restProps
81
- } = props;
82
-
83
- const [isHighlighted, setHighlighted] = useState(false);
84
-
85
- const _accessibilityLabel = ariaLabel ?? accessibilityLabel;
86
-
87
- let _accessibilityState: ?TextProps['accessibilityState'] =
88
- accessibilityState;
89
- if (
90
- ariaBusy != null ||
91
- ariaChecked != null ||
92
- ariaDisabled != null ||
93
- ariaExpanded != null ||
94
- ariaMultiselectable != null ||
95
- ariaRequired != null ||
96
- ariaSelected != null
97
- ) {
98
- if (_accessibilityState != null) {
99
- _accessibilityState = {
100
- busy: ariaBusy ?? _accessibilityState.busy,
101
- checked: ariaChecked ?? _accessibilityState.checked,
102
- disabled: ariaDisabled ?? _accessibilityState.disabled,
103
- expanded: ariaExpanded ?? _accessibilityState.expanded,
104
- multiselectable:
105
- ariaMultiselectable ?? accessibilityState?.multiselectable, // Win32
106
- required: ariaRequired ?? accessibilityState?.required, // Win32
107
- selected: ariaSelected ?? _accessibilityState.selected,
108
- };
109
- } else {
110
- _accessibilityState = {
111
- busy: ariaBusy,
112
- checked: ariaChecked,
113
- disabled: ariaDisabled,
114
- expanded: ariaExpanded,
115
- multiselectable: ariaMultiselectable, // Win32,
116
- required: ariaRequired, // Win32
117
- selected: ariaSelected,
118
- };
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
96
+
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
+ }
128
+
129
+ const _accessibilityStateDisabled = _accessibilityState?.disabled;
130
+ const _disabled = disabled ?? _accessibilityStateDisabled;
131
+
132
+ const isPressable =
133
+ (onPress != null ||
134
+ onLongPress != null ||
135
+ onStartShouldSetResponder != null) &&
136
+ _disabled !== true;
137
+
138
+ // TODO: Move this processing to the view configuration.
139
+ const _selectionColor =
140
+ selectionColor == null ? null : processColor(selectionColor);
141
+
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,
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
+ );
119
377
  }
120
- }
378
+ );
121
379
 
122
- const _accessibilityStateDisabled = _accessibilityState?.disabled;
123
- const _disabled = disabled ?? _accessibilityStateDisabled;
380
+ Text.displayName = 'Text';
124
381
 
125
- const isPressable =
126
- (onPress != null ||
127
- onLongPress != null ||
128
- onStartShouldSetResponder != null) &&
129
- _disabled !== true;
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
+ }>;
130
396
 
131
- const initialized = useLazyInitialization(isPressable);
132
- const config = useMemo(() => {
133
- if (!initialized) {
134
- return null;
135
- }
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);
136
417
 
418
+ // Setup pressability config and wrap callbacks needs to track the highlight state.
419
+ const config = useMemo(() => {
137
420
  let _onPressIn = onPressIn;
138
421
  let _onPressOut = onPressOut;
139
422
 
@@ -153,7 +436,7 @@ const TextLegacy: React.AbstractComponent<
153
436
  }
154
437
 
155
438
  return {
156
- disabled: !isPressable,
439
+ disabled: false,
157
440
  pressRectOffset: pressRetentionOffset,
158
441
  onLongPress,
159
442
  onPress,
@@ -161,8 +444,6 @@ const TextLegacy: React.AbstractComponent<
161
444
  onPressOut: _onPressOut,
162
445
  };
163
446
  }, [
164
- initialized,
165
- isPressable,
166
447
  pressRetentionOffset,
167
448
  onLongPress,
168
449
  onPress,
@@ -171,7 +452,10 @@ const TextLegacy: React.AbstractComponent<
171
452
  suppressHighlighting,
172
453
  ]);
173
454
 
455
+ // Init the pressability class
174
456
  const eventHandlers = usePressability(config);
457
+
458
+ // Create NativeText event handlers which proxy events to pressability
175
459
  const eventHandlersForText = useMemo(
176
460
  () =>
177
461
  eventHandlers == null
@@ -222,140 +506,67 @@ const TextLegacy: React.AbstractComponent<
222
506
  ],
223
507
  );
224
508
 
225
- // TODO: Move this processing to the view configuration.
226
- const _selectionColor =
227
- selectionColor == null ? null : processColor(selectionColor);
228
-
229
- let _style = style;
230
- if (__DEV__) {
231
- if (PressabilityDebug.isEnabled() && onPress != null) {
232
- _style = [style, {color: 'magenta'}];
233
- }
234
- }
235
-
236
- let _numberOfLines = numberOfLines;
237
- if (_numberOfLines != null && !(_numberOfLines >= 0)) {
238
- if (__DEV__) {
239
- console.error(
240
- `'numberOfLines' in <Text> must be a non-negative number, received: ${_numberOfLines}. The value will be set to 0.`,
241
- );
242
- }
243
- _numberOfLines = 0;
244
- }
245
-
246
- let _selectable = selectable;
247
- const processedStyle = flattenStyle(_style);
248
- if (processedStyle != null) {
249
- if (typeof processedStyle.fontWeight === 'number') {
250
- // $FlowFixMe[cannot-write]
251
- processedStyle.fontWeight = processedStyle.fontWeight.toString();
252
- }
509
+ // Return the highlight state and NativeText event handlers
510
+ return useMemo(
511
+ () => [isHighlighted, eventHandlersForText],
512
+ [isHighlighted, eventHandlersForText],
513
+ );
514
+ }
253
515
 
254
- if (processedStyle.userSelect != null) {
255
- _selectable = userSelectToSelectableMap[processedStyle.userSelect];
256
- // $FlowFixMe[cannot-write]
257
- delete processedStyle.userSelect;
258
- }
516
+ type NativePressableTextProps = $ReadOnly<{
517
+ textProps: NativeTextProps,
518
+ textPressabilityProps: TextPressabilityProps,
519
+ }>;
259
520
 
260
- if (processedStyle.verticalAlign != null) {
261
- // $FlowFixMe[cannot-write]
262
- processedStyle.textAlignVertical =
263
- verticalAlignToTextAlignVerticalMap[processedStyle.verticalAlign];
264
- // $FlowFixMe[cannot-write]
265
- delete processedStyle.verticalAlign;
266
- }
267
- }
268
-
269
- const _nativeID = id ?? nativeID;
270
-
271
- const hasTextAncestor = useContext(TextAncestor);
272
- if (hasTextAncestor) {
273
- return (
274
- <NativeVirtualText
275
- {...restProps}
276
- {...eventHandlersForText}
277
- accessibilityLabel={_accessibilityLabel}
278
- accessibilityState={_accessibilityState}
279
- accessibilityControls={ariaControls ?? accessibilityControls} // Win32
280
- accessibilityDescribedBy={ariaDescribedBy ?? accessibilityDescribedBy} // Win32
281
- accessibilityDescription={ariaDescription ?? accessibilityDescription} // Win32
282
- accessibilityLevel={ariaLevel ?? accessibilityLevel} // Win32
283
- accessibilityPositionInSet={ariaPosinset ?? accessibilityPositionInSet} // Win32
284
- accessibilitySetSize={ariaSetsize ?? accessibilitySetSize} // Win32
285
- isHighlighted={isHighlighted}
286
- isPressable={isPressable}
287
- nativeID={_nativeID}
288
- numberOfLines={_numberOfLines}
289
- ref={forwardedRef}
290
- selectable={_selectable}
291
- selectionColor={_selectionColor}
292
- style={processedStyle}
293
- disabled={disabled}
294
- />
295
- );
296
- }
297
-
298
- // If the disabled prop and accessibilityState.disabled are out of sync but not both in
299
- // falsy states we need to update the accessibilityState object to use the disabled prop.
300
- if (
301
- _disabled !== _accessibilityStateDisabled &&
302
- ((_disabled != null && _disabled !== false) ||
303
- (_accessibilityStateDisabled != null &&
304
- _accessibilityStateDisabled !== false))
305
- ) {
306
- _accessibilityState = {..._accessibilityState, disabled: _disabled};
307
- }
308
-
309
- const _accessible = Platform.select({
310
- ios: accessible !== false,
311
- android:
312
- accessible == null ? onPress != null || onLongPress != null : accessible,
313
- default: accessible !== false,
314
- });
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
+ );
315
534
 
316
535
  return (
317
- <TextAncestor.Provider value={true}>
318
- <NativeText
319
- {...restProps}
320
- {...eventHandlersForText}
321
- accessibilityLabel={_accessibilityLabel}
322
- accessibilityState={_accessibilityState}
323
- accessible={_accessible}
324
- accessibilityControls={ariaControls ?? accessibilityControls} // Win32
325
- accessibilityDescribedBy={ariaDescribedBy ?? accessibilityDescribedBy} // Win32
326
- accessibilityDescription={ariaDescription ?? accessibilityDescription} // Win32
327
- accessibilityLevel={ariaLevel ?? accessibilityLevel} // Win32
328
- accessibilityPositionInSet={ariaPosinset ?? accessibilityPositionInSet} // Win32
329
- accessibilitySetSize={ariaSetsize ?? accessibilitySetSize} // Win32
330
- allowFontScaling={allowFontScaling !== false}
331
- disabled={_disabled}
332
- ellipsizeMode={ellipsizeMode ?? 'tail'}
333
- isHighlighted={isHighlighted}
334
- nativeID={_nativeID}
335
- numberOfLines={_numberOfLines}
336
- ref={forwardedRef}
337
- selectable={_selectable}
338
- selectionColor={_selectionColor}
339
- style={processedStyle}
340
- />
341
- </TextAncestor.Provider>
536
+ <NativeVirtualText
537
+ {...textProps}
538
+ {...eventHandlersForText}
539
+ isHighlighted={isHighlighted}
540
+ isPressable={true}
541
+ ref={forwardedRef}
542
+ />
342
543
  );
343
544
  });
344
545
 
345
- TextLegacy.displayName = 'TextLegacy';
346
-
347
546
  /**
348
- * Returns false until the first time `newValue` is true, after which this will
349
- * always return true. This is necessary to lazily initialize `Pressability` so
350
- * 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.
351
551
  */
352
- function useLazyInitialization(newValue: boolean): boolean {
353
- const [oldValue, setValue] = useState(newValue);
354
- if (!oldValue && newValue) {
355
- setValue(newValue);
356
- }
357
- return oldValue;
358
- }
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
+ });
359
570
 
360
571
  const userSelectToSelectableMap = {
361
572
  auto: true,
@@ -372,17 +583,4 @@ const verticalAlignToTextAlignVerticalMap = {
372
583
  middle: 'center',
373
584
  };
374
585
 
375
- const Text: React.AbstractComponent<
376
- TextProps,
377
- React.ElementRef<typeof NativeText | typeof NativeVirtualText>,
378
- > = React.forwardRef((props: TextProps, forwardedRef) => {
379
- if (ReactNativeFeatureFlags.shouldUseOptimizedText()) {
380
- return <TextOptimized {...props} ref={forwardedRef} />;
381
- } else {
382
- return <TextLegacy {...props} ref={forwardedRef} />;
383
- }
384
- });
385
-
386
- Text.displayName = 'Text';
387
-
388
586
  module.exports = Text;