@office-iss/react-native-win32 0.0.0-canary.256 → 0.0.0-canary.258
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.flowconfig +4 -2
- package/CHANGELOG.json +79 -1
- package/CHANGELOG.md +32 -8
- package/Libraries/Components/ScrollView/ScrollView.js +124 -165
- package/Libraries/Core/InitializeCore.js +2 -0
- package/Libraries/Core/ReactNativeVersion.js +3 -3
- package/Libraries/Core/ReactNativeVersionCheck.win32.js +1 -1
- package/Libraries/Core/setUpGlobals.js +1 -0
- package/Libraries/Core/setUpTimers.js +19 -0
- package/Libraries/LogBox/Data/LogBoxData.js +39 -4
- package/Libraries/LogBox/Data/LogBoxLog.js +5 -2
- package/Libraries/LogBox/Data/parseLogBoxLog.js +22 -1
- package/Libraries/LogBox/LogBox.js +29 -12
- package/Libraries/LogBox/LogBoxNotificationContainer.js +4 -0
- package/Libraries/LogBox/UI/LogBoxInspector.js +8 -70
- package/Libraries/LogBox/UI/LogBoxInspectorBody.js +87 -0
- package/Libraries/LogBox/UI/LogBoxInspectorFooter.js +6 -42
- package/Libraries/LogBox/UI/LogBoxInspectorFooterButton.js +58 -0
- package/Libraries/LogBox/UI/LogBoxInspectorHeader.js +25 -74
- package/Libraries/LogBox/UI/LogBoxInspectorHeader.win32.js +27 -80
- package/Libraries/LogBox/UI/LogBoxInspectorHeaderButton.js +76 -0
- package/Libraries/LogBox/UI/LogBoxNotification.js +13 -152
- package/Libraries/LogBox/UI/LogBoxNotificationCountBadge.js +63 -0
- package/Libraries/LogBox/UI/LogBoxNotificationDismissButton.js +67 -0
- package/Libraries/LogBox/UI/LogBoxNotificationMessage.js +57 -0
- package/Libraries/ReactNative/AppContainer-dev.js +1 -5
- package/Libraries/ReactNative/AppContainer-prod.js +1 -5
- package/Libraries/ReactNative/AppContainer.js +0 -1
- package/Libraries/ReactNative/AppRegistry.js +0 -6
- package/Libraries/ReactNative/renderApplication.js +0 -2
- package/Libraries/Renderer/implementations/ReactFabric-dev.js +15690 -26405
- package/Libraries/Renderer/implementations/ReactFabric-prod.js +2675 -1630
- package/Libraries/Renderer/implementations/ReactFabric-profiling.js +2945 -1682
- package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +16141 -27018
- package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +2723 -1666
- package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +2984 -1737
- package/Libraries/Share/Share.d.ts +16 -10
- package/Libraries/Share/Share.js +14 -15
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +19 -0
- package/Libraries/StyleSheet/StyleSheetTypes.js +19 -1
- package/Libraries/StyleSheet/processFilter.js +214 -39
- package/Libraries/Text/Text.js +42 -22
- package/Libraries/Text/Text.win32.js +42 -22
- package/Libraries/Text/TextNativeComponent.js +1 -1
- package/Libraries/Text/TextNativeComponent.win32.js +1 -1
- package/Libraries/Text/TextOptimized.js +538 -0
- package/Libraries/Utilities/ReactNativeTestTools.js +7 -24
- package/Libraries/__tests__/ButtonWin32-test.js +7 -6
- package/Libraries/promiseRejectionTrackingOptions.js +1 -0
- package/index.js +1 -0
- package/index.win32.js +1 -0
- package/jest/mockComponent.js +4 -1
- package/jest/renderer.js +25 -14
- package/jest/setup.js +5 -0
- package/overrides.json +6 -6
- package/package.json +26 -26
- package/src/private/core/components/HScrollViewNativeComponents.js +55 -0
- package/src/private/core/components/VScrollViewNativeComponents.js +47 -0
- package/src/private/core/components/useSyncOnScroll.js +48 -0
- package/src/private/featureflags/ReactNativeFeatureFlags.js +12 -1
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +2 -1
- package/src/private/specs/modules/NativeDevSettings.js +1 -0
- package/src/private/specs/modules/NativeSampleTurboModule.js +14 -1
- package/src/private/webapis/idlecallbacks/specs/NativeIdleCallbacks.js +34 -0
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import type {PressEvent} from '../Types/CoreEventTypes';
|
|
12
12
|
import type {TextProps} from './TextProps';
|
|
13
13
|
|
|
14
|
+
import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
|
|
14
15
|
import * as PressabilityDebug from '../Pressability/PressabilityDebug';
|
|
15
16
|
import usePressability from '../Pressability/usePressability';
|
|
16
17
|
import flattenStyle from '../StyleSheet/flattenStyle';
|
|
@@ -18,6 +19,7 @@ import processColor from '../StyleSheet/processColor';
|
|
|
18
19
|
import Platform from '../Utilities/Platform';
|
|
19
20
|
import TextAncestor from './TextAncestor';
|
|
20
21
|
import {NativeText, NativeVirtualText} from './TextNativeComponent';
|
|
22
|
+
import TextOptimized from './TextOptimized';
|
|
21
23
|
import * as React from 'react';
|
|
22
24
|
import {useContext, useMemo, useState} from 'react';
|
|
23
25
|
|
|
@@ -26,7 +28,7 @@ import {useContext, useMemo, useState} from 'react';
|
|
|
26
28
|
*
|
|
27
29
|
* @see https://reactnative.dev/docs/text
|
|
28
30
|
*/
|
|
29
|
-
const
|
|
31
|
+
const TextLegacy: React.AbstractComponent<
|
|
30
32
|
TextProps,
|
|
31
33
|
React.ElementRef<typeof NativeText | typeof NativeVirtualText>,
|
|
32
34
|
> = React.forwardRef((props: TextProps, forwardedRef) => {
|
|
@@ -56,8 +58,10 @@ const Text: React.AbstractComponent<
|
|
|
56
58
|
'aria-selected': ariaSelected,
|
|
57
59
|
'aria-setsize': ariaSetsize, // Win32
|
|
58
60
|
ellipsizeMode,
|
|
61
|
+
disabled,
|
|
59
62
|
id,
|
|
60
63
|
nativeID,
|
|
64
|
+
numberOfLines,
|
|
61
65
|
onLongPress,
|
|
62
66
|
onPress,
|
|
63
67
|
onPressIn,
|
|
@@ -69,7 +73,10 @@ const Text: React.AbstractComponent<
|
|
|
69
73
|
onResponderTerminationRequest,
|
|
70
74
|
onStartShouldSetResponder,
|
|
71
75
|
pressRetentionOffset,
|
|
76
|
+
selectable,
|
|
77
|
+
selectionColor,
|
|
72
78
|
suppressHighlighting,
|
|
79
|
+
style,
|
|
73
80
|
...restProps
|
|
74
81
|
} = props;
|
|
75
82
|
|
|
@@ -113,7 +120,7 @@ const Text: React.AbstractComponent<
|
|
|
113
120
|
}
|
|
114
121
|
|
|
115
122
|
const _accessibilityStateDisabled = _accessibilityState?.disabled;
|
|
116
|
-
const _disabled =
|
|
123
|
+
const _disabled = disabled ?? _accessibilityStateDisabled;
|
|
117
124
|
|
|
118
125
|
const isPressable =
|
|
119
126
|
(onPress != null ||
|
|
@@ -216,29 +223,28 @@ const Text: React.AbstractComponent<
|
|
|
216
223
|
);
|
|
217
224
|
|
|
218
225
|
// TODO: Move this processing to the view configuration.
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
? null
|
|
222
|
-
: processColor(restProps.selectionColor);
|
|
226
|
+
const _selectionColor =
|
|
227
|
+
selectionColor == null ? null : processColor(selectionColor);
|
|
223
228
|
|
|
224
|
-
let
|
|
229
|
+
let _style = style;
|
|
225
230
|
if (__DEV__) {
|
|
226
231
|
if (PressabilityDebug.isEnabled() && onPress != null) {
|
|
227
|
-
|
|
232
|
+
_style = [style, {color: 'magenta'}];
|
|
228
233
|
}
|
|
229
234
|
}
|
|
230
235
|
|
|
231
|
-
let
|
|
232
|
-
if (
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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;
|
|
237
244
|
}
|
|
238
245
|
|
|
239
|
-
let _selectable =
|
|
240
|
-
|
|
241
|
-
const processedStyle = flattenStyle(style);
|
|
246
|
+
let _selectable = selectable;
|
|
247
|
+
const processedStyle = flattenStyle(_style);
|
|
242
248
|
if (processedStyle != null) {
|
|
243
249
|
if (typeof processedStyle.fontWeight === 'number') {
|
|
244
250
|
// $FlowFixMe[cannot-write]
|
|
@@ -279,11 +285,12 @@ const Text: React.AbstractComponent<
|
|
|
279
285
|
isHighlighted={isHighlighted}
|
|
280
286
|
isPressable={isPressable}
|
|
281
287
|
nativeID={_nativeID}
|
|
282
|
-
numberOfLines={
|
|
288
|
+
numberOfLines={_numberOfLines}
|
|
283
289
|
ref={forwardedRef}
|
|
284
290
|
selectable={_selectable}
|
|
285
|
-
selectionColor={
|
|
291
|
+
selectionColor={_selectionColor}
|
|
286
292
|
style={processedStyle}
|
|
293
|
+
disabled={disabled}
|
|
287
294
|
/>
|
|
288
295
|
);
|
|
289
296
|
}
|
|
@@ -325,17 +332,17 @@ const Text: React.AbstractComponent<
|
|
|
325
332
|
ellipsizeMode={ellipsizeMode ?? 'tail'}
|
|
326
333
|
isHighlighted={isHighlighted}
|
|
327
334
|
nativeID={_nativeID}
|
|
328
|
-
numberOfLines={
|
|
335
|
+
numberOfLines={_numberOfLines}
|
|
329
336
|
ref={forwardedRef}
|
|
330
337
|
selectable={_selectable}
|
|
331
|
-
selectionColor={
|
|
338
|
+
selectionColor={_selectionColor}
|
|
332
339
|
style={processedStyle}
|
|
333
340
|
/>
|
|
334
341
|
</TextAncestor.Provider>
|
|
335
342
|
);
|
|
336
343
|
});
|
|
337
344
|
|
|
338
|
-
|
|
345
|
+
TextLegacy.displayName = 'TextLegacy';
|
|
339
346
|
|
|
340
347
|
/**
|
|
341
348
|
* Returns false until the first time `newValue` is true, after which this will
|
|
@@ -365,4 +372,17 @@ const verticalAlignToTextAlignVerticalMap = {
|
|
|
365
372
|
middle: 'center',
|
|
366
373
|
};
|
|
367
374
|
|
|
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
|
+
|
|
368
388
|
module.exports = Text;
|
|
@@ -17,7 +17,7 @@ import {createViewConfig} from '../NativeComponent/ViewConfig';
|
|
|
17
17
|
import UIManager from '../ReactNative/UIManager';
|
|
18
18
|
import createReactNativeComponentClass from '../Renderer/shims/createReactNativeComponentClass';
|
|
19
19
|
|
|
20
|
-
type NativeTextProps = $ReadOnly<{
|
|
20
|
+
export type NativeTextProps = $ReadOnly<{
|
|
21
21
|
...TextProps,
|
|
22
22
|
isHighlighted?: ?boolean,
|
|
23
23
|
selectionColor?: ?ProcessedColorValue,
|
|
@@ -17,7 +17,7 @@ import {createViewConfig} from '../NativeComponent/ViewConfig';
|
|
|
17
17
|
import UIManager from '../ReactNative/UIManager';
|
|
18
18
|
import createReactNativeComponentClass from '../Renderer/shims/createReactNativeComponentClass';
|
|
19
19
|
|
|
20
|
-
type NativeTextProps = $ReadOnly<{
|
|
20
|
+
export type NativeTextProps = $ReadOnly<{
|
|
21
21
|
...TextProps,
|
|
22
22
|
isHighlighted?: ?boolean,
|
|
23
23
|
selectionColor?: ?ProcessedColorValue,
|
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {PressEvent} from '../Types/CoreEventTypes';
|
|
12
|
+
import type {NativeTextProps} from './TextNativeComponent';
|
|
13
|
+
import type {PressRetentionOffset, TextProps} from './TextProps';
|
|
14
|
+
|
|
15
|
+
import * as PressabilityDebug from '../Pressability/PressabilityDebug';
|
|
16
|
+
import usePressability from '../Pressability/usePressability';
|
|
17
|
+
import flattenStyle from '../StyleSheet/flattenStyle';
|
|
18
|
+
import processColor from '../StyleSheet/processColor';
|
|
19
|
+
import Platform from '../Utilities/Platform';
|
|
20
|
+
import TextAncestor from './TextAncestor';
|
|
21
|
+
import {NativeText, NativeVirtualText} from './TextNativeComponent';
|
|
22
|
+
import * as React from 'react';
|
|
23
|
+
import {useContext, useMemo, useState} from 'react';
|
|
24
|
+
|
|
25
|
+
type TextForwardRef = React.ElementRef<
|
|
26
|
+
typeof NativeText | typeof NativeVirtualText,
|
|
27
|
+
>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Text is the fundamental component for displaying text.
|
|
31
|
+
*
|
|
32
|
+
* @see https://reactnative.dev/docs/text
|
|
33
|
+
*
|
|
34
|
+
* NOTE: This file is a short term fork of `Text` for the purpose of performance
|
|
35
|
+
* testing. Any changes to either this component or `Text` should be avoided
|
|
36
|
+
* while this file exists.
|
|
37
|
+
*
|
|
38
|
+
* Specific differences from `Text`:
|
|
39
|
+
* - Lazy init Pressability via a nested component
|
|
40
|
+
* - Skip children context wrapper when safe.
|
|
41
|
+
* - Move props destructuring to function param.
|
|
42
|
+
*/
|
|
43
|
+
const TextOptimized: React.AbstractComponent<TextProps, TextForwardRef> =
|
|
44
|
+
React.forwardRef(
|
|
45
|
+
(
|
|
46
|
+
{
|
|
47
|
+
accessible,
|
|
48
|
+
accessibilityLabel,
|
|
49
|
+
accessibilityState,
|
|
50
|
+
allowFontScaling,
|
|
51
|
+
'aria-busy': ariaBusy,
|
|
52
|
+
'aria-checked': ariaChecked,
|
|
53
|
+
'aria-disabled': ariaDisabled,
|
|
54
|
+
'aria-expanded': ariaExpanded,
|
|
55
|
+
'aria-label': ariaLabel,
|
|
56
|
+
'aria-selected': ariaSelected,
|
|
57
|
+
children,
|
|
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
|
+
}: TextProps,
|
|
80
|
+
forwardedRef,
|
|
81
|
+
) => {
|
|
82
|
+
const _accessibilityLabel = ariaLabel ?? accessibilityLabel;
|
|
83
|
+
|
|
84
|
+
let _accessibilityState: ?TextProps['accessibilityState'] =
|
|
85
|
+
accessibilityState;
|
|
86
|
+
if (
|
|
87
|
+
ariaBusy != null ||
|
|
88
|
+
ariaChecked != null ||
|
|
89
|
+
ariaDisabled != null ||
|
|
90
|
+
ariaExpanded != null ||
|
|
91
|
+
ariaSelected != null
|
|
92
|
+
) {
|
|
93
|
+
if (_accessibilityState != null) {
|
|
94
|
+
_accessibilityState = {
|
|
95
|
+
busy: ariaBusy ?? _accessibilityState.busy,
|
|
96
|
+
checked: ariaChecked ?? _accessibilityState.checked,
|
|
97
|
+
disabled: ariaDisabled ?? _accessibilityState.disabled,
|
|
98
|
+
expanded: ariaExpanded ?? _accessibilityState.expanded,
|
|
99
|
+
selected: ariaSelected ?? _accessibilityState.selected,
|
|
100
|
+
};
|
|
101
|
+
} else {
|
|
102
|
+
_accessibilityState = {
|
|
103
|
+
busy: ariaBusy,
|
|
104
|
+
checked: ariaChecked,
|
|
105
|
+
disabled: ariaDisabled,
|
|
106
|
+
expanded: ariaExpanded,
|
|
107
|
+
selected: ariaSelected,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const _accessibilityStateDisabled = _accessibilityState?.disabled;
|
|
113
|
+
const _disabled = disabled ?? _accessibilityStateDisabled;
|
|
114
|
+
|
|
115
|
+
const isPressable =
|
|
116
|
+
(onPress != null ||
|
|
117
|
+
onLongPress != null ||
|
|
118
|
+
onStartShouldSetResponder != null) &&
|
|
119
|
+
_disabled !== true;
|
|
120
|
+
|
|
121
|
+
// TODO: Move this processing to the view configuration.
|
|
122
|
+
const _selectionColor =
|
|
123
|
+
selectionColor == null ? null : processColor(selectionColor);
|
|
124
|
+
|
|
125
|
+
let _style = style;
|
|
126
|
+
if (__DEV__) {
|
|
127
|
+
if (PressabilityDebug.isEnabled() && onPress != null) {
|
|
128
|
+
_style = [style, {color: 'magenta'}];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
let _numberOfLines = numberOfLines;
|
|
133
|
+
if (_numberOfLines != null && !(_numberOfLines >= 0)) {
|
|
134
|
+
if (__DEV__) {
|
|
135
|
+
console.error(
|
|
136
|
+
`'numberOfLines' in <Text> must be a non-negative number, received: ${_numberOfLines}. The value will be set to 0.`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
_numberOfLines = 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
let _selectable = selectable;
|
|
143
|
+
|
|
144
|
+
const processedStyle = flattenStyle(_style);
|
|
145
|
+
if (processedStyle != null) {
|
|
146
|
+
if (typeof processedStyle.fontWeight === 'number') {
|
|
147
|
+
// $FlowFixMe[cannot-write]
|
|
148
|
+
processedStyle.fontWeight = processedStyle.fontWeight.toString();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (processedStyle.userSelect != null) {
|
|
152
|
+
_selectable = userSelectToSelectableMap[processedStyle.userSelect];
|
|
153
|
+
// $FlowFixMe[cannot-write]
|
|
154
|
+
delete processedStyle.userSelect;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (processedStyle.verticalAlign != null) {
|
|
158
|
+
// $FlowFixMe[cannot-write]
|
|
159
|
+
processedStyle.textAlignVertical =
|
|
160
|
+
verticalAlignToTextAlignVerticalMap[processedStyle.verticalAlign];
|
|
161
|
+
// $FlowFixMe[cannot-write]
|
|
162
|
+
delete processedStyle.verticalAlign;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const _nativeID = id ?? nativeID;
|
|
167
|
+
|
|
168
|
+
const hasTextAncestor = useContext(TextAncestor);
|
|
169
|
+
if (hasTextAncestor) {
|
|
170
|
+
if (isPressable) {
|
|
171
|
+
return (
|
|
172
|
+
<NativePressableVirtualText
|
|
173
|
+
ref={forwardedRef}
|
|
174
|
+
textProps={{
|
|
175
|
+
...restProps,
|
|
176
|
+
accessibilityLabel: _accessibilityLabel,
|
|
177
|
+
accessibilityState: _accessibilityState,
|
|
178
|
+
nativeID: _nativeID,
|
|
179
|
+
numberOfLines: _numberOfLines,
|
|
180
|
+
selectable: _selectable,
|
|
181
|
+
selectionColor: _selectionColor,
|
|
182
|
+
style: processedStyle,
|
|
183
|
+
disabled: disabled,
|
|
184
|
+
children,
|
|
185
|
+
}}
|
|
186
|
+
textPressabilityProps={{
|
|
187
|
+
onLongPress,
|
|
188
|
+
onPress,
|
|
189
|
+
onPressIn,
|
|
190
|
+
onPressOut,
|
|
191
|
+
onResponderGrant,
|
|
192
|
+
onResponderMove,
|
|
193
|
+
onResponderRelease,
|
|
194
|
+
onResponderTerminate,
|
|
195
|
+
onResponderTerminationRequest,
|
|
196
|
+
onStartShouldSetResponder,
|
|
197
|
+
pressRetentionOffset,
|
|
198
|
+
suppressHighlighting,
|
|
199
|
+
}}
|
|
200
|
+
/>
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return (
|
|
205
|
+
<NativeVirtualText
|
|
206
|
+
{...restProps}
|
|
207
|
+
accessibilityLabel={_accessibilityLabel}
|
|
208
|
+
accessibilityState={_accessibilityState}
|
|
209
|
+
isHighlighted={false}
|
|
210
|
+
isPressable={false}
|
|
211
|
+
nativeID={_nativeID}
|
|
212
|
+
numberOfLines={_numberOfLines}
|
|
213
|
+
ref={forwardedRef}
|
|
214
|
+
selectable={_selectable}
|
|
215
|
+
selectionColor={_selectionColor}
|
|
216
|
+
style={processedStyle}
|
|
217
|
+
disabled={disabled}>
|
|
218
|
+
{children}
|
|
219
|
+
</NativeVirtualText>
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// If the disabled prop and accessibilityState.disabled are out of sync but not both in
|
|
224
|
+
// falsy states we need to update the accessibilityState object to use the disabled prop.
|
|
225
|
+
if (
|
|
226
|
+
_disabled !== _accessibilityStateDisabled &&
|
|
227
|
+
((_disabled != null && _disabled !== false) ||
|
|
228
|
+
(_accessibilityStateDisabled != null &&
|
|
229
|
+
_accessibilityStateDisabled !== false))
|
|
230
|
+
) {
|
|
231
|
+
_accessibilityState = {..._accessibilityState, disabled: _disabled};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const _accessible = Platform.select({
|
|
235
|
+
ios: accessible !== false,
|
|
236
|
+
android:
|
|
237
|
+
accessible == null
|
|
238
|
+
? onPress != null || onLongPress != null
|
|
239
|
+
: accessible,
|
|
240
|
+
default: accessible,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
let nativeText = null;
|
|
244
|
+
if (isPressable) {
|
|
245
|
+
nativeText = (
|
|
246
|
+
<NativePressableText
|
|
247
|
+
ref={forwardedRef}
|
|
248
|
+
textProps={{
|
|
249
|
+
...restProps,
|
|
250
|
+
accessibilityLabel: _accessibilityLabel,
|
|
251
|
+
accessibilityState: _accessibilityState,
|
|
252
|
+
accessible: _accessible,
|
|
253
|
+
allowFontScaling: allowFontScaling !== false,
|
|
254
|
+
disabled: _disabled,
|
|
255
|
+
ellipsizeMode: ellipsizeMode ?? 'tail',
|
|
256
|
+
nativeID: _nativeID,
|
|
257
|
+
numberOfLines: _numberOfLines,
|
|
258
|
+
selectable: _selectable,
|
|
259
|
+
selectionColor: _selectionColor,
|
|
260
|
+
style: processedStyle,
|
|
261
|
+
children,
|
|
262
|
+
}}
|
|
263
|
+
textPressabilityProps={{
|
|
264
|
+
onLongPress,
|
|
265
|
+
onPress,
|
|
266
|
+
onPressIn,
|
|
267
|
+
onPressOut,
|
|
268
|
+
onResponderGrant,
|
|
269
|
+
onResponderMove,
|
|
270
|
+
onResponderRelease,
|
|
271
|
+
onResponderTerminate,
|
|
272
|
+
onResponderTerminationRequest,
|
|
273
|
+
onStartShouldSetResponder,
|
|
274
|
+
pressRetentionOffset,
|
|
275
|
+
suppressHighlighting,
|
|
276
|
+
}}
|
|
277
|
+
/>
|
|
278
|
+
);
|
|
279
|
+
} else {
|
|
280
|
+
nativeText = (
|
|
281
|
+
<NativeText
|
|
282
|
+
{...restProps}
|
|
283
|
+
accessibilityLabel={_accessibilityLabel}
|
|
284
|
+
accessibilityState={_accessibilityState}
|
|
285
|
+
accessible={_accessible}
|
|
286
|
+
allowFontScaling={allowFontScaling !== false}
|
|
287
|
+
disabled={_disabled}
|
|
288
|
+
ellipsizeMode={ellipsizeMode ?? 'tail'}
|
|
289
|
+
isHighlighted={false}
|
|
290
|
+
nativeID={_nativeID}
|
|
291
|
+
numberOfLines={_numberOfLines}
|
|
292
|
+
ref={forwardedRef}
|
|
293
|
+
selectable={_selectable}
|
|
294
|
+
selectionColor={_selectionColor}
|
|
295
|
+
style={processedStyle}>
|
|
296
|
+
{children}
|
|
297
|
+
</NativeText>
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (children == null) {
|
|
302
|
+
return nativeText;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// If the children do not contain a JSX element it would not be possible to have a
|
|
306
|
+
// nested `Text` component so we can skip adding the `TextAncestor` context wrapper
|
|
307
|
+
// which has a performance overhead. Since we do this for performance reasons we need
|
|
308
|
+
// to keep the check simple to avoid regressing overall perf. For this reason the
|
|
309
|
+
// `children.length` constant is set to `3`, this should be a reasonable tradeoff
|
|
310
|
+
// to capture the majority of `Text` uses but also not make this check too expensive.
|
|
311
|
+
if (Array.isArray(children) && children.length <= 3) {
|
|
312
|
+
let hasNonTextChild = false;
|
|
313
|
+
for (let child of children) {
|
|
314
|
+
if (child != null && typeof child === 'object') {
|
|
315
|
+
hasNonTextChild = true;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (!hasNonTextChild) {
|
|
320
|
+
return nativeText;
|
|
321
|
+
}
|
|
322
|
+
} else if (typeof children !== 'object') {
|
|
323
|
+
return nativeText;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return (
|
|
327
|
+
<TextAncestor.Provider value={true}>{nativeText}</TextAncestor.Provider>
|
|
328
|
+
);
|
|
329
|
+
},
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
TextOptimized.displayName = 'TextOptimized';
|
|
333
|
+
|
|
334
|
+
type TextPressabilityProps = $ReadOnly<{
|
|
335
|
+
onLongPress?: ?(event: PressEvent) => mixed,
|
|
336
|
+
onPress?: ?(event: PressEvent) => mixed,
|
|
337
|
+
onPressIn?: ?(event: PressEvent) => mixed,
|
|
338
|
+
onPressOut?: ?(event: PressEvent) => mixed,
|
|
339
|
+
onResponderGrant?: ?(event: PressEvent) => void,
|
|
340
|
+
onResponderMove?: ?(event: PressEvent) => void,
|
|
341
|
+
onResponderRelease?: ?(event: PressEvent) => void,
|
|
342
|
+
onResponderTerminate?: ?(event: PressEvent) => void,
|
|
343
|
+
onResponderTerminationRequest?: ?() => boolean,
|
|
344
|
+
onStartShouldSetResponder?: ?() => boolean,
|
|
345
|
+
pressRetentionOffset?: ?PressRetentionOffset,
|
|
346
|
+
suppressHighlighting?: ?boolean,
|
|
347
|
+
}>;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Hook that handles setting up Pressability of Text components.
|
|
351
|
+
*
|
|
352
|
+
* NOTE: This hook is relatively expensive so it should only be used absolutely necessary.
|
|
353
|
+
*/
|
|
354
|
+
function useTextPressability({
|
|
355
|
+
onLongPress,
|
|
356
|
+
onPress,
|
|
357
|
+
onPressIn,
|
|
358
|
+
onPressOut,
|
|
359
|
+
onResponderGrant,
|
|
360
|
+
onResponderMove,
|
|
361
|
+
onResponderRelease,
|
|
362
|
+
onResponderTerminate,
|
|
363
|
+
onResponderTerminationRequest,
|
|
364
|
+
onStartShouldSetResponder,
|
|
365
|
+
pressRetentionOffset,
|
|
366
|
+
suppressHighlighting,
|
|
367
|
+
}: TextPressabilityProps) {
|
|
368
|
+
const [isHighlighted, setHighlighted] = useState(false);
|
|
369
|
+
|
|
370
|
+
// Setup pressability config and wrap callbacks needs to track the highlight state.
|
|
371
|
+
const config = useMemo(() => {
|
|
372
|
+
let _onPressIn = onPressIn;
|
|
373
|
+
let _onPressOut = onPressOut;
|
|
374
|
+
|
|
375
|
+
// Updating isHighlighted causes unnecessary re-renders for platforms that don't use it
|
|
376
|
+
// in the best case, and cause issues with text selection in the worst case. Forcing
|
|
377
|
+
// the isHighlighted prop to false on all platforms except iOS.
|
|
378
|
+
if (Platform.OS === 'ios') {
|
|
379
|
+
_onPressIn = (event: PressEvent) => {
|
|
380
|
+
setHighlighted(suppressHighlighting == null || !suppressHighlighting);
|
|
381
|
+
onPressIn?.(event);
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
_onPressOut = (event: PressEvent) => {
|
|
385
|
+
setHighlighted(false);
|
|
386
|
+
onPressOut?.(event);
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return {
|
|
391
|
+
disabled: false,
|
|
392
|
+
pressRectOffset: pressRetentionOffset,
|
|
393
|
+
onLongPress,
|
|
394
|
+
onPress,
|
|
395
|
+
onPressIn: _onPressIn,
|
|
396
|
+
onPressOut: _onPressOut,
|
|
397
|
+
};
|
|
398
|
+
}, [
|
|
399
|
+
pressRetentionOffset,
|
|
400
|
+
onLongPress,
|
|
401
|
+
onPress,
|
|
402
|
+
onPressIn,
|
|
403
|
+
onPressOut,
|
|
404
|
+
suppressHighlighting,
|
|
405
|
+
]);
|
|
406
|
+
|
|
407
|
+
// Init the pressability class
|
|
408
|
+
const eventHandlers = usePressability(config);
|
|
409
|
+
|
|
410
|
+
// Create NativeText event handlers which proxy events to pressability
|
|
411
|
+
const eventHandlersForText = useMemo(
|
|
412
|
+
() =>
|
|
413
|
+
eventHandlers == null
|
|
414
|
+
? null
|
|
415
|
+
: {
|
|
416
|
+
onResponderGrant(event: PressEvent) {
|
|
417
|
+
eventHandlers.onResponderGrant(event);
|
|
418
|
+
if (onResponderGrant != null) {
|
|
419
|
+
onResponderGrant(event);
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
onResponderMove(event: PressEvent) {
|
|
423
|
+
eventHandlers.onResponderMove(event);
|
|
424
|
+
if (onResponderMove != null) {
|
|
425
|
+
onResponderMove(event);
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
onResponderRelease(event: PressEvent) {
|
|
429
|
+
eventHandlers.onResponderRelease(event);
|
|
430
|
+
if (onResponderRelease != null) {
|
|
431
|
+
onResponderRelease(event);
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
onResponderTerminate(event: PressEvent) {
|
|
435
|
+
eventHandlers.onResponderTerminate(event);
|
|
436
|
+
if (onResponderTerminate != null) {
|
|
437
|
+
onResponderTerminate(event);
|
|
438
|
+
}
|
|
439
|
+
},
|
|
440
|
+
onClick: eventHandlers.onClick,
|
|
441
|
+
onResponderTerminationRequest:
|
|
442
|
+
onResponderTerminationRequest != null
|
|
443
|
+
? onResponderTerminationRequest
|
|
444
|
+
: eventHandlers.onResponderTerminationRequest,
|
|
445
|
+
onStartShouldSetResponder:
|
|
446
|
+
onStartShouldSetResponder != null
|
|
447
|
+
? onStartShouldSetResponder
|
|
448
|
+
: eventHandlers.onStartShouldSetResponder,
|
|
449
|
+
},
|
|
450
|
+
[
|
|
451
|
+
eventHandlers,
|
|
452
|
+
onResponderGrant,
|
|
453
|
+
onResponderMove,
|
|
454
|
+
onResponderRelease,
|
|
455
|
+
onResponderTerminate,
|
|
456
|
+
onResponderTerminationRequest,
|
|
457
|
+
onStartShouldSetResponder,
|
|
458
|
+
],
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
// Return the highlight state and NativeText event handlers
|
|
462
|
+
return useMemo(
|
|
463
|
+
() => [isHighlighted, eventHandlersForText],
|
|
464
|
+
[isHighlighted, eventHandlersForText],
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
type NativePressableTextProps = $ReadOnly<{
|
|
469
|
+
textProps: NativeTextProps,
|
|
470
|
+
textPressabilityProps: TextPressabilityProps,
|
|
471
|
+
}>;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Wrap the NativeVirtualText component and initialize pressability.
|
|
475
|
+
*
|
|
476
|
+
* This logic is split out from the main Text component to enable the more
|
|
477
|
+
* expensive pressability logic to be only initialized when needed.
|
|
478
|
+
*/
|
|
479
|
+
const NativePressableVirtualText: React.AbstractComponent<
|
|
480
|
+
NativePressableTextProps,
|
|
481
|
+
TextForwardRef,
|
|
482
|
+
> = React.forwardRef(({textProps, textPressabilityProps}, forwardedRef) => {
|
|
483
|
+
const [isHighlighted, eventHandlersForText] = useTextPressability(
|
|
484
|
+
textPressabilityProps,
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
return (
|
|
488
|
+
<NativeVirtualText
|
|
489
|
+
{...textProps}
|
|
490
|
+
{...eventHandlersForText}
|
|
491
|
+
isHighlighted={isHighlighted}
|
|
492
|
+
isPressable={true}
|
|
493
|
+
ref={forwardedRef}
|
|
494
|
+
/>
|
|
495
|
+
);
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Wrap the NativeText component and initialize pressability.
|
|
500
|
+
*
|
|
501
|
+
* This logic is split out from the main Text component to enable the more
|
|
502
|
+
* expensive pressability logic to be only initialized when needed.
|
|
503
|
+
*/
|
|
504
|
+
const NativePressableText: React.AbstractComponent<
|
|
505
|
+
NativePressableTextProps,
|
|
506
|
+
TextForwardRef,
|
|
507
|
+
> = React.forwardRef(({textProps, textPressabilityProps}, forwardedRef) => {
|
|
508
|
+
const [isHighlighted, eventHandlersForText] = useTextPressability(
|
|
509
|
+
textPressabilityProps,
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
return (
|
|
513
|
+
<NativeText
|
|
514
|
+
{...textProps}
|
|
515
|
+
{...eventHandlersForText}
|
|
516
|
+
isHighlighted={isHighlighted}
|
|
517
|
+
isPressable={true}
|
|
518
|
+
ref={forwardedRef}
|
|
519
|
+
/>
|
|
520
|
+
);
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
const userSelectToSelectableMap = {
|
|
524
|
+
auto: true,
|
|
525
|
+
text: true,
|
|
526
|
+
none: false,
|
|
527
|
+
contain: true,
|
|
528
|
+
all: true,
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
const verticalAlignToTextAlignVerticalMap = {
|
|
532
|
+
auto: 'auto',
|
|
533
|
+
top: 'top',
|
|
534
|
+
bottom: 'bottom',
|
|
535
|
+
middle: 'center',
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
module.exports = TextOptimized;
|