mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
remove gating for optimized text (#45317)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45317 changelog: [internal] ship optimized version of Text componant. In local benchmarking this version shows 35% improvement over old Text component. Reviewed By: NickGerleman Differential Revision: D59460871 fbshipit-source-id: c3a41d3aac4cd40e054b669d56295bcb631d8310
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c9fbc05bbc
commit
9fbc904592
+387
-213
@@ -9,9 +9,9 @@
|
||||
*/
|
||||
|
||||
import type {PressEvent} from '../Types/CoreEventTypes';
|
||||
import type {TextProps} from './TextProps';
|
||||
import type {NativeTextProps} from './TextNativeComponent';
|
||||
import type {PressRetentionOffset, TextProps} from './TextProps';
|
||||
|
||||
import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags';
|
||||
import * as PressabilityDebug from '../Pressability/PressabilityDebug';
|
||||
import usePressability from '../Pressability/usePressability';
|
||||
import flattenStyle from '../StyleSheet/flattenStyle';
|
||||
@@ -19,100 +19,347 @@ import processColor from '../StyleSheet/processColor';
|
||||
import Platform from '../Utilities/Platform';
|
||||
import TextAncestor from './TextAncestor';
|
||||
import {NativeText, NativeVirtualText} from './TextNativeComponent';
|
||||
import TextOptimized from './TextOptimized';
|
||||
import * as React from 'react';
|
||||
import {useContext, useMemo, useState} from 'react';
|
||||
|
||||
type TextForwardRef = React.ElementRef<
|
||||
typeof NativeText | typeof NativeVirtualText,
|
||||
>;
|
||||
|
||||
/**
|
||||
* Text is the fundamental component for displaying text.
|
||||
*
|
||||
* @see https://reactnative.dev/docs/text
|
||||
*/
|
||||
const TextLegacy: React.AbstractComponent<
|
||||
TextProps,
|
||||
React.ElementRef<typeof NativeText | typeof NativeVirtualText>,
|
||||
> = React.forwardRef((props: TextProps, forwardedRef) => {
|
||||
const {
|
||||
accessible,
|
||||
accessibilityLabel,
|
||||
accessibilityState,
|
||||
allowFontScaling,
|
||||
'aria-busy': ariaBusy,
|
||||
'aria-checked': ariaChecked,
|
||||
'aria-disabled': ariaDisabled,
|
||||
'aria-expanded': ariaExpanded,
|
||||
'aria-label': ariaLabel,
|
||||
'aria-selected': ariaSelected,
|
||||
ellipsizeMode,
|
||||
disabled,
|
||||
id,
|
||||
nativeID,
|
||||
numberOfLines,
|
||||
onLongPress,
|
||||
onPress,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
onResponderGrant,
|
||||
onResponderMove,
|
||||
onResponderRelease,
|
||||
onResponderTerminate,
|
||||
onResponderTerminationRequest,
|
||||
onStartShouldSetResponder,
|
||||
pressRetentionOffset,
|
||||
selectable,
|
||||
selectionColor,
|
||||
suppressHighlighting,
|
||||
style,
|
||||
...restProps
|
||||
} = props;
|
||||
const Text: React.AbstractComponent<TextProps, TextForwardRef> =
|
||||
React.forwardRef(
|
||||
(
|
||||
{
|
||||
accessible,
|
||||
accessibilityLabel,
|
||||
accessibilityState,
|
||||
allowFontScaling,
|
||||
'aria-busy': ariaBusy,
|
||||
'aria-checked': ariaChecked,
|
||||
'aria-disabled': ariaDisabled,
|
||||
'aria-expanded': ariaExpanded,
|
||||
'aria-label': ariaLabel,
|
||||
'aria-selected': ariaSelected,
|
||||
children,
|
||||
ellipsizeMode,
|
||||
disabled,
|
||||
id,
|
||||
nativeID,
|
||||
numberOfLines,
|
||||
onLongPress,
|
||||
onPress,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
onResponderGrant,
|
||||
onResponderMove,
|
||||
onResponderRelease,
|
||||
onResponderTerminate,
|
||||
onResponderTerminationRequest,
|
||||
onStartShouldSetResponder,
|
||||
pressRetentionOffset,
|
||||
selectable,
|
||||
selectionColor,
|
||||
suppressHighlighting,
|
||||
style,
|
||||
...restProps
|
||||
}: TextProps,
|
||||
forwardedRef,
|
||||
) => {
|
||||
const _accessibilityLabel = ariaLabel ?? accessibilityLabel;
|
||||
|
||||
let _accessibilityState: ?TextProps['accessibilityState'] =
|
||||
accessibilityState;
|
||||
if (
|
||||
ariaBusy != null ||
|
||||
ariaChecked != null ||
|
||||
ariaDisabled != null ||
|
||||
ariaExpanded != null ||
|
||||
ariaSelected != null
|
||||
) {
|
||||
if (_accessibilityState != null) {
|
||||
_accessibilityState = {
|
||||
busy: ariaBusy ?? _accessibilityState.busy,
|
||||
checked: ariaChecked ?? _accessibilityState.checked,
|
||||
disabled: ariaDisabled ?? _accessibilityState.disabled,
|
||||
expanded: ariaExpanded ?? _accessibilityState.expanded,
|
||||
selected: ariaSelected ?? _accessibilityState.selected,
|
||||
};
|
||||
} else {
|
||||
_accessibilityState = {
|
||||
busy: ariaBusy,
|
||||
checked: ariaChecked,
|
||||
disabled: ariaDisabled,
|
||||
expanded: ariaExpanded,
|
||||
selected: ariaSelected,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const _accessibilityStateDisabled = _accessibilityState?.disabled;
|
||||
const _disabled = disabled ?? _accessibilityStateDisabled;
|
||||
|
||||
const isPressable =
|
||||
(onPress != null ||
|
||||
onLongPress != null ||
|
||||
onStartShouldSetResponder != null) &&
|
||||
_disabled !== true;
|
||||
|
||||
// TODO: Move this processing to the view configuration.
|
||||
const _selectionColor =
|
||||
selectionColor == null ? null : processColor(selectionColor);
|
||||
|
||||
let _style = style;
|
||||
if (__DEV__) {
|
||||
if (PressabilityDebug.isEnabled() && onPress != null) {
|
||||
_style = [style, {color: 'magenta'}];
|
||||
}
|
||||
}
|
||||
|
||||
let _numberOfLines = numberOfLines;
|
||||
if (_numberOfLines != null && !(_numberOfLines >= 0)) {
|
||||
if (__DEV__) {
|
||||
console.error(
|
||||
`'numberOfLines' in <Text> must be a non-negative number, received: ${_numberOfLines}. The value will be set to 0.`,
|
||||
);
|
||||
}
|
||||
_numberOfLines = 0;
|
||||
}
|
||||
|
||||
let _selectable = selectable;
|
||||
|
||||
const processedStyle = flattenStyle(_style);
|
||||
if (processedStyle != null) {
|
||||
if (typeof processedStyle.fontWeight === 'number') {
|
||||
// $FlowFixMe[cannot-write]
|
||||
processedStyle.fontWeight = processedStyle.fontWeight.toString();
|
||||
}
|
||||
|
||||
if (processedStyle.userSelect != null) {
|
||||
_selectable = userSelectToSelectableMap[processedStyle.userSelect];
|
||||
// $FlowFixMe[cannot-write]
|
||||
delete processedStyle.userSelect;
|
||||
}
|
||||
|
||||
if (processedStyle.verticalAlign != null) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
processedStyle.textAlignVertical =
|
||||
verticalAlignToTextAlignVerticalMap[processedStyle.verticalAlign];
|
||||
// $FlowFixMe[cannot-write]
|
||||
delete processedStyle.verticalAlign;
|
||||
}
|
||||
}
|
||||
|
||||
const _nativeID = id ?? nativeID;
|
||||
|
||||
const hasTextAncestor = useContext(TextAncestor);
|
||||
if (hasTextAncestor) {
|
||||
if (isPressable) {
|
||||
return (
|
||||
<NativePressableVirtualText
|
||||
ref={forwardedRef}
|
||||
textProps={{
|
||||
...restProps,
|
||||
accessibilityLabel: _accessibilityLabel,
|
||||
accessibilityState: _accessibilityState,
|
||||
nativeID: _nativeID,
|
||||
numberOfLines: _numberOfLines,
|
||||
selectable: _selectable,
|
||||
selectionColor: _selectionColor,
|
||||
style: processedStyle,
|
||||
disabled: disabled,
|
||||
children,
|
||||
}}
|
||||
textPressabilityProps={{
|
||||
onLongPress,
|
||||
onPress,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
onResponderGrant,
|
||||
onResponderMove,
|
||||
onResponderRelease,
|
||||
onResponderTerminate,
|
||||
onResponderTerminationRequest,
|
||||
onStartShouldSetResponder,
|
||||
pressRetentionOffset,
|
||||
suppressHighlighting,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<NativeVirtualText
|
||||
{...restProps}
|
||||
accessibilityLabel={_accessibilityLabel}
|
||||
accessibilityState={_accessibilityState}
|
||||
isHighlighted={false}
|
||||
isPressable={false}
|
||||
nativeID={_nativeID}
|
||||
numberOfLines={_numberOfLines}
|
||||
ref={forwardedRef}
|
||||
selectable={_selectable}
|
||||
selectionColor={_selectionColor}
|
||||
style={processedStyle}
|
||||
disabled={disabled}>
|
||||
{children}
|
||||
</NativeVirtualText>
|
||||
);
|
||||
}
|
||||
|
||||
// If the disabled prop and accessibilityState.disabled are out of sync but not both in
|
||||
// falsy states we need to update the accessibilityState object to use the disabled prop.
|
||||
if (
|
||||
_disabled !== _accessibilityStateDisabled &&
|
||||
((_disabled != null && _disabled !== false) ||
|
||||
(_accessibilityStateDisabled != null &&
|
||||
_accessibilityStateDisabled !== false))
|
||||
) {
|
||||
_accessibilityState = {..._accessibilityState, disabled: _disabled};
|
||||
}
|
||||
|
||||
const _accessible = Platform.select({
|
||||
ios: accessible !== false,
|
||||
android:
|
||||
accessible == null
|
||||
? onPress != null || onLongPress != null
|
||||
: accessible,
|
||||
default: accessible,
|
||||
});
|
||||
|
||||
let nativeText = null;
|
||||
if (isPressable) {
|
||||
nativeText = (
|
||||
<NativePressableText
|
||||
ref={forwardedRef}
|
||||
textProps={{
|
||||
...restProps,
|
||||
accessibilityLabel: _accessibilityLabel,
|
||||
accessibilityState: _accessibilityState,
|
||||
accessible: _accessible,
|
||||
allowFontScaling: allowFontScaling !== false,
|
||||
disabled: _disabled,
|
||||
ellipsizeMode: ellipsizeMode ?? 'tail',
|
||||
nativeID: _nativeID,
|
||||
numberOfLines: _numberOfLines,
|
||||
selectable: _selectable,
|
||||
selectionColor: _selectionColor,
|
||||
style: processedStyle,
|
||||
children,
|
||||
}}
|
||||
textPressabilityProps={{
|
||||
onLongPress,
|
||||
onPress,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
onResponderGrant,
|
||||
onResponderMove,
|
||||
onResponderRelease,
|
||||
onResponderTerminate,
|
||||
onResponderTerminationRequest,
|
||||
onStartShouldSetResponder,
|
||||
pressRetentionOffset,
|
||||
suppressHighlighting,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
nativeText = (
|
||||
<NativeText
|
||||
{...restProps}
|
||||
accessibilityLabel={_accessibilityLabel}
|
||||
accessibilityState={_accessibilityState}
|
||||
accessible={_accessible}
|
||||
allowFontScaling={allowFontScaling !== false}
|
||||
disabled={_disabled}
|
||||
ellipsizeMode={ellipsizeMode ?? 'tail'}
|
||||
isHighlighted={false}
|
||||
nativeID={_nativeID}
|
||||
numberOfLines={_numberOfLines}
|
||||
ref={forwardedRef}
|
||||
selectable={_selectable}
|
||||
selectionColor={_selectionColor}
|
||||
style={processedStyle}>
|
||||
{children}
|
||||
</NativeText>
|
||||
);
|
||||
}
|
||||
|
||||
if (children == null) {
|
||||
return nativeText;
|
||||
}
|
||||
|
||||
// If the children do not contain a JSX element it would not be possible to have a
|
||||
// nested `Text` component so we can skip adding the `TextAncestor` context wrapper
|
||||
// which has a performance overhead. Since we do this for performance reasons we need
|
||||
// to keep the check simple to avoid regressing overall perf. For this reason the
|
||||
// `children.length` constant is set to `3`, this should be a reasonable tradeoff
|
||||
// to capture the majority of `Text` uses but also not make this check too expensive.
|
||||
if (Array.isArray(children) && children.length <= 3) {
|
||||
let hasNonTextChild = false;
|
||||
for (let child of children) {
|
||||
if (child != null && typeof child === 'object') {
|
||||
hasNonTextChild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasNonTextChild) {
|
||||
return nativeText;
|
||||
}
|
||||
} else if (typeof children !== 'object') {
|
||||
return nativeText;
|
||||
}
|
||||
|
||||
return (
|
||||
<TextAncestor.Provider value={true}>{nativeText}</TextAncestor.Provider>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Text.displayName = 'Text';
|
||||
|
||||
type TextPressabilityProps = $ReadOnly<{
|
||||
onLongPress?: ?(event: PressEvent) => mixed,
|
||||
onPress?: ?(event: PressEvent) => mixed,
|
||||
onPressIn?: ?(event: PressEvent) => mixed,
|
||||
onPressOut?: ?(event: PressEvent) => mixed,
|
||||
onResponderGrant?: ?(event: PressEvent) => void,
|
||||
onResponderMove?: ?(event: PressEvent) => void,
|
||||
onResponderRelease?: ?(event: PressEvent) => void,
|
||||
onResponderTerminate?: ?(event: PressEvent) => void,
|
||||
onResponderTerminationRequest?: ?() => boolean,
|
||||
onStartShouldSetResponder?: ?() => boolean,
|
||||
pressRetentionOffset?: ?PressRetentionOffset,
|
||||
suppressHighlighting?: ?boolean,
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Hook that handles setting up Pressability of Text components.
|
||||
*
|
||||
* NOTE: This hook is relatively expensive so it should only be used absolutely necessary.
|
||||
*/
|
||||
function useTextPressability({
|
||||
onLongPress,
|
||||
onPress,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
onResponderGrant,
|
||||
onResponderMove,
|
||||
onResponderRelease,
|
||||
onResponderTerminate,
|
||||
onResponderTerminationRequest,
|
||||
onStartShouldSetResponder,
|
||||
pressRetentionOffset,
|
||||
suppressHighlighting,
|
||||
}: TextPressabilityProps) {
|
||||
const [isHighlighted, setHighlighted] = useState(false);
|
||||
|
||||
const _accessibilityLabel = ariaLabel ?? accessibilityLabel;
|
||||
|
||||
let _accessibilityState: ?TextProps['accessibilityState'] =
|
||||
accessibilityState;
|
||||
if (
|
||||
ariaBusy != null ||
|
||||
ariaChecked != null ||
|
||||
ariaDisabled != null ||
|
||||
ariaExpanded != null ||
|
||||
ariaSelected != null
|
||||
) {
|
||||
if (_accessibilityState != null) {
|
||||
_accessibilityState = {
|
||||
busy: ariaBusy ?? _accessibilityState.busy,
|
||||
checked: ariaChecked ?? _accessibilityState.checked,
|
||||
disabled: ariaDisabled ?? _accessibilityState.disabled,
|
||||
expanded: ariaExpanded ?? _accessibilityState.expanded,
|
||||
selected: ariaSelected ?? _accessibilityState.selected,
|
||||
};
|
||||
} else {
|
||||
_accessibilityState = {
|
||||
busy: ariaBusy,
|
||||
checked: ariaChecked,
|
||||
disabled: ariaDisabled,
|
||||
expanded: ariaExpanded,
|
||||
selected: ariaSelected,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const _accessibilityStateDisabled = _accessibilityState?.disabled;
|
||||
const _disabled = disabled ?? _accessibilityStateDisabled;
|
||||
|
||||
const isPressable =
|
||||
(onPress != null ||
|
||||
onLongPress != null ||
|
||||
onStartShouldSetResponder != null) &&
|
||||
_disabled !== true;
|
||||
|
||||
const initialized = useLazyInitialization(isPressable);
|
||||
// Setup pressability config and wrap callbacks needs to track the highlight state.
|
||||
const config = useMemo(() => {
|
||||
if (!initialized) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let _onPressIn = onPressIn;
|
||||
let _onPressOut = onPressOut;
|
||||
|
||||
@@ -132,7 +379,7 @@ const TextLegacy: React.AbstractComponent<
|
||||
}
|
||||
|
||||
return {
|
||||
disabled: !isPressable,
|
||||
disabled: false,
|
||||
pressRectOffset: pressRetentionOffset,
|
||||
onLongPress,
|
||||
onPress,
|
||||
@@ -140,8 +387,6 @@ const TextLegacy: React.AbstractComponent<
|
||||
onPressOut: _onPressOut,
|
||||
};
|
||||
}, [
|
||||
initialized,
|
||||
isPressable,
|
||||
pressRetentionOffset,
|
||||
onLongPress,
|
||||
onPress,
|
||||
@@ -150,7 +395,10 @@ const TextLegacy: React.AbstractComponent<
|
||||
suppressHighlighting,
|
||||
]);
|
||||
|
||||
// Init the pressability class
|
||||
const eventHandlers = usePressability(config);
|
||||
|
||||
// Create NativeText event handlers which proxy events to pressability
|
||||
const eventHandlersForText = useMemo(
|
||||
() =>
|
||||
eventHandlers == null
|
||||
@@ -201,128 +449,67 @@ const TextLegacy: React.AbstractComponent<
|
||||
],
|
||||
);
|
||||
|
||||
// TODO: Move this processing to the view configuration.
|
||||
const _selectionColor =
|
||||
selectionColor == null ? null : processColor(selectionColor);
|
||||
// Return the highlight state and NativeText event handlers
|
||||
return useMemo(
|
||||
() => [isHighlighted, eventHandlersForText],
|
||||
[isHighlighted, eventHandlersForText],
|
||||
);
|
||||
}
|
||||
|
||||
let _style = style;
|
||||
if (__DEV__) {
|
||||
if (PressabilityDebug.isEnabled() && onPress != null) {
|
||||
_style = [style, {color: 'magenta'}];
|
||||
}
|
||||
}
|
||||
type NativePressableTextProps = $ReadOnly<{
|
||||
textProps: NativeTextProps,
|
||||
textPressabilityProps: TextPressabilityProps,
|
||||
}>;
|
||||
|
||||
let _numberOfLines = numberOfLines;
|
||||
if (_numberOfLines != null && !(_numberOfLines >= 0)) {
|
||||
if (__DEV__) {
|
||||
console.error(
|
||||
`'numberOfLines' in <Text> must be a non-negative number, received: ${_numberOfLines}. The value will be set to 0.`,
|
||||
);
|
||||
}
|
||||
_numberOfLines = 0;
|
||||
}
|
||||
|
||||
let _selectable = selectable;
|
||||
const processedStyle = flattenStyle(_style);
|
||||
if (processedStyle != null) {
|
||||
if (typeof processedStyle.fontWeight === 'number') {
|
||||
// $FlowFixMe[cannot-write]
|
||||
processedStyle.fontWeight = processedStyle.fontWeight.toString();
|
||||
}
|
||||
|
||||
if (processedStyle.userSelect != null) {
|
||||
_selectable = userSelectToSelectableMap[processedStyle.userSelect];
|
||||
// $FlowFixMe[cannot-write]
|
||||
delete processedStyle.userSelect;
|
||||
}
|
||||
|
||||
if (processedStyle.verticalAlign != null) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
processedStyle.textAlignVertical =
|
||||
verticalAlignToTextAlignVerticalMap[processedStyle.verticalAlign];
|
||||
// $FlowFixMe[cannot-write]
|
||||
delete processedStyle.verticalAlign;
|
||||
}
|
||||
}
|
||||
|
||||
const _nativeID = id ?? nativeID;
|
||||
|
||||
const hasTextAncestor = useContext(TextAncestor);
|
||||
if (hasTextAncestor) {
|
||||
return (
|
||||
<NativeVirtualText
|
||||
{...restProps}
|
||||
{...eventHandlersForText}
|
||||
accessibilityLabel={_accessibilityLabel}
|
||||
accessibilityState={_accessibilityState}
|
||||
isHighlighted={isHighlighted}
|
||||
isPressable={isPressable}
|
||||
nativeID={_nativeID}
|
||||
numberOfLines={_numberOfLines}
|
||||
ref={forwardedRef}
|
||||
selectable={_selectable}
|
||||
selectionColor={_selectionColor}
|
||||
style={processedStyle}
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// If the disabled prop and accessibilityState.disabled are out of sync but not both in
|
||||
// falsy states we need to update the accessibilityState object to use the disabled prop.
|
||||
if (
|
||||
_disabled !== _accessibilityStateDisabled &&
|
||||
((_disabled != null && _disabled !== false) ||
|
||||
(_accessibilityStateDisabled != null &&
|
||||
_accessibilityStateDisabled !== false))
|
||||
) {
|
||||
_accessibilityState = {..._accessibilityState, disabled: _disabled};
|
||||
}
|
||||
|
||||
const _accessible = Platform.select({
|
||||
ios: accessible !== false,
|
||||
android:
|
||||
accessible == null ? onPress != null || onLongPress != null : accessible,
|
||||
default: accessible,
|
||||
});
|
||||
/**
|
||||
* Wrap the NativeVirtualText component and initialize pressability.
|
||||
*
|
||||
* This logic is split out from the main Text component to enable the more
|
||||
* expensive pressability logic to be only initialized when needed.
|
||||
*/
|
||||
const NativePressableVirtualText: React.AbstractComponent<
|
||||
NativePressableTextProps,
|
||||
TextForwardRef,
|
||||
> = React.forwardRef(({textProps, textPressabilityProps}, forwardedRef) => {
|
||||
const [isHighlighted, eventHandlersForText] = useTextPressability(
|
||||
textPressabilityProps,
|
||||
);
|
||||
|
||||
return (
|
||||
<TextAncestor.Provider value={true}>
|
||||
<NativeText
|
||||
{...restProps}
|
||||
{...eventHandlersForText}
|
||||
accessibilityLabel={_accessibilityLabel}
|
||||
accessibilityState={_accessibilityState}
|
||||
accessible={_accessible}
|
||||
allowFontScaling={allowFontScaling !== false}
|
||||
disabled={_disabled}
|
||||
ellipsizeMode={ellipsizeMode ?? 'tail'}
|
||||
isHighlighted={isHighlighted}
|
||||
nativeID={_nativeID}
|
||||
numberOfLines={_numberOfLines}
|
||||
ref={forwardedRef}
|
||||
selectable={_selectable}
|
||||
selectionColor={_selectionColor}
|
||||
style={processedStyle}
|
||||
/>
|
||||
</TextAncestor.Provider>
|
||||
<NativeVirtualText
|
||||
{...textProps}
|
||||
{...eventHandlersForText}
|
||||
isHighlighted={isHighlighted}
|
||||
isPressable={true}
|
||||
ref={forwardedRef}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
TextLegacy.displayName = 'TextLegacy';
|
||||
|
||||
/**
|
||||
* Returns false until the first time `newValue` is true, after which this will
|
||||
* always return true. This is necessary to lazily initialize `Pressability` so
|
||||
* we do not eagerly create one for every pressable `Text` component.
|
||||
* Wrap the NativeText component and initialize pressability.
|
||||
*
|
||||
* This logic is split out from the main Text component to enable the more
|
||||
* expensive pressability logic to be only initialized when needed.
|
||||
*/
|
||||
function useLazyInitialization(newValue: boolean): boolean {
|
||||
const [oldValue, setValue] = useState(newValue);
|
||||
if (!oldValue && newValue) {
|
||||
setValue(newValue);
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
const NativePressableText: React.AbstractComponent<
|
||||
NativePressableTextProps,
|
||||
TextForwardRef,
|
||||
> = React.forwardRef(({textProps, textPressabilityProps}, forwardedRef) => {
|
||||
const [isHighlighted, eventHandlersForText] = useTextPressability(
|
||||
textPressabilityProps,
|
||||
);
|
||||
|
||||
return (
|
||||
<NativeText
|
||||
{...textProps}
|
||||
{...eventHandlersForText}
|
||||
isHighlighted={isHighlighted}
|
||||
isPressable={true}
|
||||
ref={forwardedRef}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const userSelectToSelectableMap = {
|
||||
auto: true,
|
||||
@@ -339,17 +526,4 @@ const verticalAlignToTextAlignVerticalMap = {
|
||||
middle: 'center',
|
||||
};
|
||||
|
||||
const Text: React.AbstractComponent<
|
||||
TextProps,
|
||||
React.ElementRef<typeof NativeText | typeof NativeVirtualText>,
|
||||
> = React.forwardRef((props: TextProps, forwardedRef) => {
|
||||
if (ReactNativeFeatureFlags.shouldUseOptimizedText()) {
|
||||
return <TextOptimized {...props} ref={forwardedRef} />;
|
||||
} else {
|
||||
return <TextLegacy {...props} ref={forwardedRef} />;
|
||||
}
|
||||
});
|
||||
|
||||
Text.displayName = 'Text';
|
||||
|
||||
module.exports = Text;
|
||||
|
||||
@@ -1,538 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
import type {PressEvent} from '../Types/CoreEventTypes';
|
||||
import type {NativeTextProps} from './TextNativeComponent';
|
||||
import type {PressRetentionOffset, TextProps} from './TextProps';
|
||||
|
||||
import * as PressabilityDebug from '../Pressability/PressabilityDebug';
|
||||
import usePressability from '../Pressability/usePressability';
|
||||
import flattenStyle from '../StyleSheet/flattenStyle';
|
||||
import processColor from '../StyleSheet/processColor';
|
||||
import Platform from '../Utilities/Platform';
|
||||
import TextAncestor from './TextAncestor';
|
||||
import {NativeText, NativeVirtualText} from './TextNativeComponent';
|
||||
import * as React from 'react';
|
||||
import {useContext, useMemo, useState} from 'react';
|
||||
|
||||
type TextForwardRef = React.ElementRef<
|
||||
typeof NativeText | typeof NativeVirtualText,
|
||||
>;
|
||||
|
||||
/**
|
||||
* Text is the fundamental component for displaying text.
|
||||
*
|
||||
* @see https://reactnative.dev/docs/text
|
||||
*
|
||||
* NOTE: This file is a short term fork of `Text` for the purpose of performance
|
||||
* testing. Any changes to either this component or `Text` should be avoided
|
||||
* while this file exists.
|
||||
*
|
||||
* Specific differences from `Text`:
|
||||
* - Lazy init Pressability via a nested component
|
||||
* - Skip children context wrapper when safe.
|
||||
* - Move props destructuring to function param.
|
||||
*/
|
||||
const TextOptimized: React.AbstractComponent<TextProps, TextForwardRef> =
|
||||
React.forwardRef(
|
||||
(
|
||||
{
|
||||
accessible,
|
||||
accessibilityLabel,
|
||||
accessibilityState,
|
||||
allowFontScaling,
|
||||
'aria-busy': ariaBusy,
|
||||
'aria-checked': ariaChecked,
|
||||
'aria-disabled': ariaDisabled,
|
||||
'aria-expanded': ariaExpanded,
|
||||
'aria-label': ariaLabel,
|
||||
'aria-selected': ariaSelected,
|
||||
children,
|
||||
ellipsizeMode,
|
||||
disabled,
|
||||
id,
|
||||
nativeID,
|
||||
numberOfLines,
|
||||
onLongPress,
|
||||
onPress,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
onResponderGrant,
|
||||
onResponderMove,
|
||||
onResponderRelease,
|
||||
onResponderTerminate,
|
||||
onResponderTerminationRequest,
|
||||
onStartShouldSetResponder,
|
||||
pressRetentionOffset,
|
||||
selectable,
|
||||
selectionColor,
|
||||
suppressHighlighting,
|
||||
style,
|
||||
...restProps
|
||||
}: TextProps,
|
||||
forwardedRef,
|
||||
) => {
|
||||
const _accessibilityLabel = ariaLabel ?? accessibilityLabel;
|
||||
|
||||
let _accessibilityState: ?TextProps['accessibilityState'] =
|
||||
accessibilityState;
|
||||
if (
|
||||
ariaBusy != null ||
|
||||
ariaChecked != null ||
|
||||
ariaDisabled != null ||
|
||||
ariaExpanded != null ||
|
||||
ariaSelected != null
|
||||
) {
|
||||
if (_accessibilityState != null) {
|
||||
_accessibilityState = {
|
||||
busy: ariaBusy ?? _accessibilityState.busy,
|
||||
checked: ariaChecked ?? _accessibilityState.checked,
|
||||
disabled: ariaDisabled ?? _accessibilityState.disabled,
|
||||
expanded: ariaExpanded ?? _accessibilityState.expanded,
|
||||
selected: ariaSelected ?? _accessibilityState.selected,
|
||||
};
|
||||
} else {
|
||||
_accessibilityState = {
|
||||
busy: ariaBusy,
|
||||
checked: ariaChecked,
|
||||
disabled: ariaDisabled,
|
||||
expanded: ariaExpanded,
|
||||
selected: ariaSelected,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const _accessibilityStateDisabled = _accessibilityState?.disabled;
|
||||
const _disabled = disabled ?? _accessibilityStateDisabled;
|
||||
|
||||
const isPressable =
|
||||
(onPress != null ||
|
||||
onLongPress != null ||
|
||||
onStartShouldSetResponder != null) &&
|
||||
_disabled !== true;
|
||||
|
||||
// TODO: Move this processing to the view configuration.
|
||||
const _selectionColor =
|
||||
selectionColor == null ? null : processColor(selectionColor);
|
||||
|
||||
let _style = style;
|
||||
if (__DEV__) {
|
||||
if (PressabilityDebug.isEnabled() && onPress != null) {
|
||||
_style = [style, {color: 'magenta'}];
|
||||
}
|
||||
}
|
||||
|
||||
let _numberOfLines = numberOfLines;
|
||||
if (_numberOfLines != null && !(_numberOfLines >= 0)) {
|
||||
if (__DEV__) {
|
||||
console.error(
|
||||
`'numberOfLines' in <Text> must be a non-negative number, received: ${_numberOfLines}. The value will be set to 0.`,
|
||||
);
|
||||
}
|
||||
_numberOfLines = 0;
|
||||
}
|
||||
|
||||
let _selectable = selectable;
|
||||
|
||||
const processedStyle = flattenStyle(_style);
|
||||
if (processedStyle != null) {
|
||||
if (typeof processedStyle.fontWeight === 'number') {
|
||||
// $FlowFixMe[cannot-write]
|
||||
processedStyle.fontWeight = processedStyle.fontWeight.toString();
|
||||
}
|
||||
|
||||
if (processedStyle.userSelect != null) {
|
||||
_selectable = userSelectToSelectableMap[processedStyle.userSelect];
|
||||
// $FlowFixMe[cannot-write]
|
||||
delete processedStyle.userSelect;
|
||||
}
|
||||
|
||||
if (processedStyle.verticalAlign != null) {
|
||||
// $FlowFixMe[cannot-write]
|
||||
processedStyle.textAlignVertical =
|
||||
verticalAlignToTextAlignVerticalMap[processedStyle.verticalAlign];
|
||||
// $FlowFixMe[cannot-write]
|
||||
delete processedStyle.verticalAlign;
|
||||
}
|
||||
}
|
||||
|
||||
const _nativeID = id ?? nativeID;
|
||||
|
||||
const hasTextAncestor = useContext(TextAncestor);
|
||||
if (hasTextAncestor) {
|
||||
if (isPressable) {
|
||||
return (
|
||||
<NativePressableVirtualText
|
||||
ref={forwardedRef}
|
||||
textProps={{
|
||||
...restProps,
|
||||
accessibilityLabel: _accessibilityLabel,
|
||||
accessibilityState: _accessibilityState,
|
||||
nativeID: _nativeID,
|
||||
numberOfLines: _numberOfLines,
|
||||
selectable: _selectable,
|
||||
selectionColor: _selectionColor,
|
||||
style: processedStyle,
|
||||
disabled: disabled,
|
||||
children,
|
||||
}}
|
||||
textPressabilityProps={{
|
||||
onLongPress,
|
||||
onPress,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
onResponderGrant,
|
||||
onResponderMove,
|
||||
onResponderRelease,
|
||||
onResponderTerminate,
|
||||
onResponderTerminationRequest,
|
||||
onStartShouldSetResponder,
|
||||
pressRetentionOffset,
|
||||
suppressHighlighting,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<NativeVirtualText
|
||||
{...restProps}
|
||||
accessibilityLabel={_accessibilityLabel}
|
||||
accessibilityState={_accessibilityState}
|
||||
isHighlighted={false}
|
||||
isPressable={false}
|
||||
nativeID={_nativeID}
|
||||
numberOfLines={_numberOfLines}
|
||||
ref={forwardedRef}
|
||||
selectable={_selectable}
|
||||
selectionColor={_selectionColor}
|
||||
style={processedStyle}
|
||||
disabled={disabled}>
|
||||
{children}
|
||||
</NativeVirtualText>
|
||||
);
|
||||
}
|
||||
|
||||
// If the disabled prop and accessibilityState.disabled are out of sync but not both in
|
||||
// falsy states we need to update the accessibilityState object to use the disabled prop.
|
||||
if (
|
||||
_disabled !== _accessibilityStateDisabled &&
|
||||
((_disabled != null && _disabled !== false) ||
|
||||
(_accessibilityStateDisabled != null &&
|
||||
_accessibilityStateDisabled !== false))
|
||||
) {
|
||||
_accessibilityState = {..._accessibilityState, disabled: _disabled};
|
||||
}
|
||||
|
||||
const _accessible = Platform.select({
|
||||
ios: accessible !== false,
|
||||
android:
|
||||
accessible == null
|
||||
? onPress != null || onLongPress != null
|
||||
: accessible,
|
||||
default: accessible,
|
||||
});
|
||||
|
||||
let nativeText = null;
|
||||
if (isPressable) {
|
||||
nativeText = (
|
||||
<NativePressableText
|
||||
ref={forwardedRef}
|
||||
textProps={{
|
||||
...restProps,
|
||||
accessibilityLabel: _accessibilityLabel,
|
||||
accessibilityState: _accessibilityState,
|
||||
accessible: _accessible,
|
||||
allowFontScaling: allowFontScaling !== false,
|
||||
disabled: _disabled,
|
||||
ellipsizeMode: ellipsizeMode ?? 'tail',
|
||||
nativeID: _nativeID,
|
||||
numberOfLines: _numberOfLines,
|
||||
selectable: _selectable,
|
||||
selectionColor: _selectionColor,
|
||||
style: processedStyle,
|
||||
children,
|
||||
}}
|
||||
textPressabilityProps={{
|
||||
onLongPress,
|
||||
onPress,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
onResponderGrant,
|
||||
onResponderMove,
|
||||
onResponderRelease,
|
||||
onResponderTerminate,
|
||||
onResponderTerminationRequest,
|
||||
onStartShouldSetResponder,
|
||||
pressRetentionOffset,
|
||||
suppressHighlighting,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
nativeText = (
|
||||
<NativeText
|
||||
{...restProps}
|
||||
accessibilityLabel={_accessibilityLabel}
|
||||
accessibilityState={_accessibilityState}
|
||||
accessible={_accessible}
|
||||
allowFontScaling={allowFontScaling !== false}
|
||||
disabled={_disabled}
|
||||
ellipsizeMode={ellipsizeMode ?? 'tail'}
|
||||
isHighlighted={false}
|
||||
nativeID={_nativeID}
|
||||
numberOfLines={_numberOfLines}
|
||||
ref={forwardedRef}
|
||||
selectable={_selectable}
|
||||
selectionColor={_selectionColor}
|
||||
style={processedStyle}>
|
||||
{children}
|
||||
</NativeText>
|
||||
);
|
||||
}
|
||||
|
||||
if (children == null) {
|
||||
return nativeText;
|
||||
}
|
||||
|
||||
// If the children do not contain a JSX element it would not be possible to have a
|
||||
// nested `Text` component so we can skip adding the `TextAncestor` context wrapper
|
||||
// which has a performance overhead. Since we do this for performance reasons we need
|
||||
// to keep the check simple to avoid regressing overall perf. For this reason the
|
||||
// `children.length` constant is set to `3`, this should be a reasonable tradeoff
|
||||
// to capture the majority of `Text` uses but also not make this check too expensive.
|
||||
if (Array.isArray(children) && children.length <= 3) {
|
||||
let hasNonTextChild = false;
|
||||
for (let child of children) {
|
||||
if (child != null && typeof child === 'object') {
|
||||
hasNonTextChild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasNonTextChild) {
|
||||
return nativeText;
|
||||
}
|
||||
} else if (typeof children !== 'object') {
|
||||
return nativeText;
|
||||
}
|
||||
|
||||
return (
|
||||
<TextAncestor.Provider value={true}>{nativeText}</TextAncestor.Provider>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
TextOptimized.displayName = 'TextOptimized';
|
||||
|
||||
type TextPressabilityProps = $ReadOnly<{
|
||||
onLongPress?: ?(event: PressEvent) => mixed,
|
||||
onPress?: ?(event: PressEvent) => mixed,
|
||||
onPressIn?: ?(event: PressEvent) => mixed,
|
||||
onPressOut?: ?(event: PressEvent) => mixed,
|
||||
onResponderGrant?: ?(event: PressEvent) => void,
|
||||
onResponderMove?: ?(event: PressEvent) => void,
|
||||
onResponderRelease?: ?(event: PressEvent) => void,
|
||||
onResponderTerminate?: ?(event: PressEvent) => void,
|
||||
onResponderTerminationRequest?: ?() => boolean,
|
||||
onStartShouldSetResponder?: ?() => boolean,
|
||||
pressRetentionOffset?: ?PressRetentionOffset,
|
||||
suppressHighlighting?: ?boolean,
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Hook that handles setting up Pressability of Text components.
|
||||
*
|
||||
* NOTE: This hook is relatively expensive so it should only be used absolutely necessary.
|
||||
*/
|
||||
function useTextPressability({
|
||||
onLongPress,
|
||||
onPress,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
onResponderGrant,
|
||||
onResponderMove,
|
||||
onResponderRelease,
|
||||
onResponderTerminate,
|
||||
onResponderTerminationRequest,
|
||||
onStartShouldSetResponder,
|
||||
pressRetentionOffset,
|
||||
suppressHighlighting,
|
||||
}: TextPressabilityProps) {
|
||||
const [isHighlighted, setHighlighted] = useState(false);
|
||||
|
||||
// Setup pressability config and wrap callbacks needs to track the highlight state.
|
||||
const config = useMemo(() => {
|
||||
let _onPressIn = onPressIn;
|
||||
let _onPressOut = onPressOut;
|
||||
|
||||
// Updating isHighlighted causes unnecessary re-renders for platforms that don't use it
|
||||
// in the best case, and cause issues with text selection in the worst case. Forcing
|
||||
// the isHighlighted prop to false on all platforms except iOS.
|
||||
if (Platform.OS === 'ios') {
|
||||
_onPressIn = (event: PressEvent) => {
|
||||
setHighlighted(suppressHighlighting == null || !suppressHighlighting);
|
||||
onPressIn?.(event);
|
||||
};
|
||||
|
||||
_onPressOut = (event: PressEvent) => {
|
||||
setHighlighted(false);
|
||||
onPressOut?.(event);
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
pressRectOffset: pressRetentionOffset,
|
||||
onLongPress,
|
||||
onPress,
|
||||
onPressIn: _onPressIn,
|
||||
onPressOut: _onPressOut,
|
||||
};
|
||||
}, [
|
||||
pressRetentionOffset,
|
||||
onLongPress,
|
||||
onPress,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
suppressHighlighting,
|
||||
]);
|
||||
|
||||
// Init the pressability class
|
||||
const eventHandlers = usePressability(config);
|
||||
|
||||
// Create NativeText event handlers which proxy events to pressability
|
||||
const eventHandlersForText = useMemo(
|
||||
() =>
|
||||
eventHandlers == null
|
||||
? null
|
||||
: {
|
||||
onResponderGrant(event: PressEvent) {
|
||||
eventHandlers.onResponderGrant(event);
|
||||
if (onResponderGrant != null) {
|
||||
onResponderGrant(event);
|
||||
}
|
||||
},
|
||||
onResponderMove(event: PressEvent) {
|
||||
eventHandlers.onResponderMove(event);
|
||||
if (onResponderMove != null) {
|
||||
onResponderMove(event);
|
||||
}
|
||||
},
|
||||
onResponderRelease(event: PressEvent) {
|
||||
eventHandlers.onResponderRelease(event);
|
||||
if (onResponderRelease != null) {
|
||||
onResponderRelease(event);
|
||||
}
|
||||
},
|
||||
onResponderTerminate(event: PressEvent) {
|
||||
eventHandlers.onResponderTerminate(event);
|
||||
if (onResponderTerminate != null) {
|
||||
onResponderTerminate(event);
|
||||
}
|
||||
},
|
||||
onClick: eventHandlers.onClick,
|
||||
onResponderTerminationRequest:
|
||||
onResponderTerminationRequest != null
|
||||
? onResponderTerminationRequest
|
||||
: eventHandlers.onResponderTerminationRequest,
|
||||
onStartShouldSetResponder:
|
||||
onStartShouldSetResponder != null
|
||||
? onStartShouldSetResponder
|
||||
: eventHandlers.onStartShouldSetResponder,
|
||||
},
|
||||
[
|
||||
eventHandlers,
|
||||
onResponderGrant,
|
||||
onResponderMove,
|
||||
onResponderRelease,
|
||||
onResponderTerminate,
|
||||
onResponderTerminationRequest,
|
||||
onStartShouldSetResponder,
|
||||
],
|
||||
);
|
||||
|
||||
// Return the highlight state and NativeText event handlers
|
||||
return useMemo(
|
||||
() => [isHighlighted, eventHandlersForText],
|
||||
[isHighlighted, eventHandlersForText],
|
||||
);
|
||||
}
|
||||
|
||||
type NativePressableTextProps = $ReadOnly<{
|
||||
textProps: NativeTextProps,
|
||||
textPressabilityProps: TextPressabilityProps,
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Wrap the NativeVirtualText component and initialize pressability.
|
||||
*
|
||||
* This logic is split out from the main Text component to enable the more
|
||||
* expensive pressability logic to be only initialized when needed.
|
||||
*/
|
||||
const NativePressableVirtualText: React.AbstractComponent<
|
||||
NativePressableTextProps,
|
||||
TextForwardRef,
|
||||
> = React.forwardRef(({textProps, textPressabilityProps}, forwardedRef) => {
|
||||
const [isHighlighted, eventHandlersForText] = useTextPressability(
|
||||
textPressabilityProps,
|
||||
);
|
||||
|
||||
return (
|
||||
<NativeVirtualText
|
||||
{...textProps}
|
||||
{...eventHandlersForText}
|
||||
isHighlighted={isHighlighted}
|
||||
isPressable={true}
|
||||
ref={forwardedRef}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Wrap the NativeText component and initialize pressability.
|
||||
*
|
||||
* This logic is split out from the main Text component to enable the more
|
||||
* expensive pressability logic to be only initialized when needed.
|
||||
*/
|
||||
const NativePressableText: React.AbstractComponent<
|
||||
NativePressableTextProps,
|
||||
TextForwardRef,
|
||||
> = React.forwardRef(({textProps, textPressabilityProps}, forwardedRef) => {
|
||||
const [isHighlighted, eventHandlersForText] = useTextPressability(
|
||||
textPressabilityProps,
|
||||
);
|
||||
|
||||
return (
|
||||
<NativeText
|
||||
{...textProps}
|
||||
{...eventHandlersForText}
|
||||
isHighlighted={isHighlighted}
|
||||
isPressable={true}
|
||||
ref={forwardedRef}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const userSelectToSelectableMap = {
|
||||
auto: true,
|
||||
text: true,
|
||||
none: false,
|
||||
contain: true,
|
||||
all: true,
|
||||
};
|
||||
|
||||
const verticalAlignToTextAlignVerticalMap = {
|
||||
auto: 'auto',
|
||||
top: 'top',
|
||||
bottom: 'bottom',
|
||||
middle: 'center',
|
||||
};
|
||||
|
||||
module.exports = TextOptimized;
|
||||
@@ -8083,10 +8083,10 @@ exports[`public API should not change unintentionally Libraries/StyleSheet/split
|
||||
`;
|
||||
|
||||
exports[`public API should not change unintentionally Libraries/Text/Text.js 1`] = `
|
||||
"declare const Text: React.AbstractComponent<
|
||||
TextProps,
|
||||
React.ElementRef<typeof NativeText | typeof NativeVirtualText>,
|
||||
"type TextForwardRef = React.ElementRef<
|
||||
typeof NativeText | typeof NativeVirtualText,
|
||||
>;
|
||||
declare const Text: React.AbstractComponent<TextProps, TextForwardRef>;
|
||||
declare module.exports: Text;
|
||||
"
|
||||
`;
|
||||
@@ -8110,15 +8110,6 @@ declare export const NativeVirtualText: HostComponent<NativeTextProps>;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`public API should not change unintentionally Libraries/Text/TextOptimized.js 1`] = `
|
||||
"type TextForwardRef = React.ElementRef<
|
||||
typeof NativeText | typeof NativeVirtualText,
|
||||
>;
|
||||
declare const TextOptimized: React.AbstractComponent<TextProps, TextForwardRef>;
|
||||
declare module.exports: TextOptimized;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`public API should not change unintentionally Libraries/Text/TextProps.js 1`] = `
|
||||
"export type PressRetentionOffset = $ReadOnly<{
|
||||
top: number,
|
||||
|
||||
@@ -197,10 +197,6 @@ const definitions: FeatureFlagDefinitions = {
|
||||
description:
|
||||
'Enables use of AnimatedObject for animating transform values.',
|
||||
},
|
||||
shouldUseOptimizedText: {
|
||||
defaultValue: false,
|
||||
description: 'Use optimized version of <Text /> component.',
|
||||
},
|
||||
shouldUseRemoveClippedSubviewsAsDefaultOnIOS: {
|
||||
defaultValue: false,
|
||||
description:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @generated SignedSource<<26d20b285e4ef25cd3cc991c9659f4f2>>
|
||||
* @generated SignedSource<<078eccf0c13142ed0cec1c59fc3d82bf>>
|
||||
* @flow strict-local
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,6 @@ export type ReactNativeFeatureFlagsJsOnly = {
|
||||
enableAccessToHostTreeInFabric: Getter<boolean>,
|
||||
isLayoutAnimationEnabled: Getter<boolean>,
|
||||
shouldUseAnimatedObjectForTransform: Getter<boolean>,
|
||||
shouldUseOptimizedText: Getter<boolean>,
|
||||
shouldUseRemoveClippedSubviewsAsDefaultOnIOS: Getter<boolean>,
|
||||
shouldUseSetNativePropsInFabric: Getter<boolean>,
|
||||
useRefsForTextInputState: Getter<boolean>,
|
||||
@@ -101,11 +100,6 @@ export const isLayoutAnimationEnabled: Getter<boolean> = createJavaScriptFlagGet
|
||||
*/
|
||||
export const shouldUseAnimatedObjectForTransform: Getter<boolean> = createJavaScriptFlagGetter('shouldUseAnimatedObjectForTransform', false);
|
||||
|
||||
/**
|
||||
* Use optimized version of <Text /> component.
|
||||
*/
|
||||
export const shouldUseOptimizedText: Getter<boolean> = createJavaScriptFlagGetter('shouldUseOptimizedText', false);
|
||||
|
||||
/**
|
||||
* removeClippedSubviews prop will be used as the default in FlatList on iOS to match Android
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user