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

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