From fd8ecb38f0e5a78e228bfab5ec72a85d17002dd1 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 2 Jul 2025 12:48:42 -0700 Subject: [PATCH] Consolidate all React Native API imports to internal module --- packages/react-strict-dom/src/native/html.js | 7 ++- .../native/modules/ContextInheritedStyles.js | 5 +- .../src/native/modules/TextString.js | 5 +- .../modules/createStrictDOMComponent.js | 38 +++++++------ .../modules/createStrictDOMImageComponent.js | 7 ++- .../modules/createStrictDOMTextComponent.js | 9 +-- .../createStrictDOMTextInputComponent.js | 16 +++--- .../src/native/modules/usePseudoStates.js | 12 ++-- .../src/native/modules/useStrictDOMElement.js | 5 +- .../src/native/modules/useStyleProps.js | 7 ++- .../src/native/modules/useStyleTransition.js | 56 +++++++++---------- .../src/native/modules/version.js | 4 +- .../{Text.js => LayoutConformance.js} | 2 +- .../src/native/react-native/TextInput.js | 10 ---- .../src/native/react-native/index.js | 13 ++++- 15 files changed, 102 insertions(+), 94 deletions(-) rename packages/react-strict-dom/src/native/react-native/{Text.js => LayoutConformance.js} (72%) delete mode 100644 packages/react-strict-dom/src/native/react-native/TextInput.js diff --git a/packages/react-strict-dom/src/native/html.js b/packages/react-strict-dom/src/native/html.js index 06f5a636..5030c2ad 100644 --- a/packages/react-strict-dom/src/native/html.js +++ b/packages/react-strict-dom/src/native/html.js @@ -28,7 +28,7 @@ import { createStrictDOMTextComponent as createStrictText } from './modules/crea // $FlowFixMe[nonstrict-import] import { createStrictDOMTextInputComponent as createStrictTextInput } from './modules/createStrictDOMTextInputComponent'; // $FlowFixMe[nonstrict-import] -import { Platform } from 'react-native'; +import * as ReactNative from './react-native'; import * as stylex from './stylex'; const styles = stylex.create({ @@ -45,7 +45,10 @@ const styles = stylex.create({ borderWidth: 1 }, code: { - fontFamily: Platform.select({ ios: 'Menlo', default: 'monospace' }) + fontFamily: ReactNative.Platform.select({ + ios: 'Menlo', + default: 'monospace' + }) }, heading: { fontSize: '1.5rem', diff --git a/packages/react-strict-dom/src/native/modules/ContextInheritedStyles.js b/packages/react-strict-dom/src/native/modules/ContextInheritedStyles.js index 70f7dde8..35482f58 100644 --- a/packages/react-strict-dom/src/native/modules/ContextInheritedStyles.js +++ b/packages/react-strict-dom/src/native/modules/ContextInheritedStyles.js @@ -10,7 +10,6 @@ import type { Style } from '../../types/styles'; import * as React from 'react'; -import { useMemo, useState } from 'react'; import { flattenStyle } from './flattenStyle'; import { shallowEqual } from './shallowEqual'; @@ -34,7 +33,7 @@ if (__DEV__) { export function ProvideInheritedStyles(props: ProviderProps): React.Node { const { children, value } = props; const inheritedStyles = useInheritedStyles(); - const flatStyle = useMemo(() => { + const flatStyle = React.useMemo(() => { if ( value == null || (typeof value === 'object' && Object.keys(value).length === 0) @@ -47,7 +46,7 @@ export function ProvideInheritedStyles(props: ProviderProps): React.Node { } }, [inheritedStyles, value]); - const [cachedFlatStyle, setCachedFlatStyle] = useState(flatStyle); + const [cachedFlatStyle, setCachedFlatStyle] = React.useState(flatStyle); if ( flatStyle !== cachedFlatStyle && diff --git a/packages/react-strict-dom/src/native/modules/TextString.js b/packages/react-strict-dom/src/native/modules/TextString.js index 7ab7c248..24cb1f5f 100644 --- a/packages/react-strict-dom/src/native/modules/TextString.js +++ b/packages/react-strict-dom/src/native/modules/TextString.js @@ -8,7 +8,8 @@ */ import * as React from 'react'; -import { Text } from 'react-native'; +import * as ReactNative from '../react-native'; + import { useCustomProperties } from './ContextCustomProperties'; import { useStyleProps } from './useStyleProps'; @@ -30,6 +31,6 @@ export function TextString(props: Props): React.Node { return ( // $FlowFixMe - + ); } diff --git a/packages/react-strict-dom/src/native/modules/createStrictDOMComponent.js b/packages/react-strict-dom/src/native/modules/createStrictDOMComponent.js index 7996499d..b73c48cb 100644 --- a/packages/react-strict-dom/src/native/modules/createStrictDOMComponent.js +++ b/packages/react-strict-dom/src/native/modules/createStrictDOMComponent.js @@ -11,9 +11,7 @@ import type { ReactNativeProps } from '../../types/renderer.native'; import type { StrictProps as StrictPropsOriginal } from '../../types/StrictProps'; import * as React from 'react'; -import { Animated, Pressable } from 'react-native'; -import { experimental_LayoutConformance as LayoutConformance } from 'react-native'; -import { ViewNativeComponent, TextAncestorContext } from '../react-native'; +import * as ReactNative from '../react-native'; import { ProvideCustomProperties } from './ContextCustomProperties'; import { ProvideDisplayInside, useDisplayInside } from './ContextDisplayInside'; @@ -29,10 +27,10 @@ type StrictProps = $ReadOnly<{ children?: React.Node | ((ReactNativeProps) => React.Node) }>; -const AnimatedPressable = Animated.createAnimatedComponent< - React.ElementConfig, - typeof Pressable ->(Pressable); +const AnimatedPressable = ReactNative.Animated.createAnimatedComponent< + React.ElementConfig, + typeof ReactNative.Pressable +>(ReactNative.Pressable); export function createStrictDOMComponent( tagName: string, @@ -41,9 +39,11 @@ export function createStrictDOMComponent( const component: React.AbstractComponent = React.forwardRef( function (props, forwardedRef) { let NativeComponent = - tagName === 'button' ? Pressable : ViewNativeComponent; + tagName === 'button' + ? ReactNative.Pressable + : ReactNative.ViewNativeComponent; const elementRef = useStrictDOMElement({ tagName }); - const hasTextAncestor = React.useContext(TextAncestorContext); + const hasTextAncestor = React.useContext(ReactNative.TextAncestorContext); /** * Resolve global HTML and style props @@ -59,9 +59,9 @@ export function createStrictDOMComponent( if ( nativeProps.onPress != null && - NativeComponent === ViewNativeComponent + NativeComponent === ReactNative.ViewNativeComponent ) { - NativeComponent = Pressable; + NativeComponent = ReactNative.Pressable; } // Tag-specific props @@ -78,7 +78,7 @@ export function createStrictDOMComponent( // Component-specific props - if (NativeComponent === Pressable) { + if (NativeComponent === ReactNative.Pressable) { if (props.disabled === true) { nativeProps.disabled = true; nativeProps.focusable = false; @@ -142,10 +142,10 @@ export function createStrictDOMComponent( // Use Animated components if necessary if (nativeProps.animated === true) { - if (NativeComponent === ViewNativeComponent) { - NativeComponent = Animated.View; + if (NativeComponent === ReactNative.ViewNativeComponent) { + NativeComponent = ReactNative.Animated.View; } - if (NativeComponent === Pressable) { + if (NativeComponent === ReactNative.Pressable) { NativeComponent = AnimatedPressable; } } @@ -164,7 +164,9 @@ export function createStrictDOMComponent( // Enable W3C layout support if (props['data-layoutconformance'] === 'strict') { - element = ; + element = ( + + ); } if ( @@ -200,9 +202,9 @@ export function createStrictDOMComponent( if (hasTextAncestor) { return ( - + {element} - + ); } diff --git a/packages/react-strict-dom/src/native/modules/createStrictDOMImageComponent.js b/packages/react-strict-dom/src/native/modules/createStrictDOMImageComponent.js index 9096df97..24313f67 100644 --- a/packages/react-strict-dom/src/native/modules/createStrictDOMImageComponent.js +++ b/packages/react-strict-dom/src/native/modules/createStrictDOMImageComponent.js @@ -10,7 +10,8 @@ import type { StrictReactDOMImageProps } from '../../types/StrictReactDOMImageProps'; import * as React from 'react'; -import { Animated, Image } from 'react-native'; +import * as ReactNative from '../react-native'; + import { mergeRefs } from '../../shared/mergeRefs'; import { useNativeProps } from './useNativeProps'; import { useStrictDOMElement } from './useStrictDOMElement'; @@ -22,7 +23,7 @@ export function createStrictDOMImageComponent( ): component(ref?: React.RefSetter, ...P) { const component: React.AbstractComponent = React.forwardRef( function (props, forwardedRef) { - let NativeComponent = Image; + let NativeComponent = ReactNative.Image; const elementRef = useStrictDOMElement({ tagName }); const { @@ -106,7 +107,7 @@ export function createStrictDOMImageComponent( // Use Animated components if necessary if (nativeProps.animated === true) { - NativeComponent = Animated.Image; + NativeComponent = ReactNative.Animated.Image; } const element: React.Node = diff --git a/packages/react-strict-dom/src/native/modules/createStrictDOMTextComponent.js b/packages/react-strict-dom/src/native/modules/createStrictDOMTextComponent.js index 8ed1268f..2f10ce48 100644 --- a/packages/react-strict-dom/src/native/modules/createStrictDOMTextComponent.js +++ b/packages/react-strict-dom/src/native/modules/createStrictDOMTextComponent.js @@ -11,7 +11,8 @@ import type { ReactNativeProps } from '../../types/renderer.native'; import type { StrictProps as StrictPropsOriginal } from '../../types/StrictProps'; import * as React from 'react'; -import { Animated, Platform, Text } from 'react-native'; +import * as ReactNative from '../react-native'; + import { ProvideCustomProperties } from './ContextCustomProperties'; import { ProvideInheritedStyles } from './ContextInheritedStyles'; import { errorMsg } from '../../shared/logUtils'; @@ -34,7 +35,7 @@ export function createStrictDOMTextComponent( ): component(ref?: React.RefSetter, ...P) { const component: React.AbstractComponent = React.forwardRef( function (props, forwardedRef) { - let NativeComponent = Text; + let NativeComponent = ReactNative.Text; const elementRef = useStrictDOMElement({ tagName }); const { href, label } = props; @@ -91,7 +92,7 @@ export function createStrictDOMTextComponent( // Workaround: Android doesn't support ellipsis truncation if Text is selectable // See #136 const disableUserSelect = - Platform.OS === 'android' && + ReactNative.Platform.OS === 'android' && nativeProps.numberOfLines != null && nativeProps.style.userSelect !== 'none'; @@ -102,7 +103,7 @@ export function createStrictDOMTextComponent( // Use Animated components if necessary if (nativeProps.animated === true) { - NativeComponent = Animated.Text; + NativeComponent = ReactNative.Animated.Text; } /** diff --git a/packages/react-strict-dom/src/native/modules/createStrictDOMTextInputComponent.js b/packages/react-strict-dom/src/native/modules/createStrictDOMTextInputComponent.js index c1308cf6..c1fbeafa 100644 --- a/packages/react-strict-dom/src/native/modules/createStrictDOMTextInputComponent.js +++ b/packages/react-strict-dom/src/native/modules/createStrictDOMTextInputComponent.js @@ -11,16 +11,17 @@ import type { StrictReactDOMInputProps } from '../../types/StrictReactDOMInputPr import type { StrictReactDOMTextAreaProps } from '../../types/StrictReactDOMTextAreaProps'; import * as React from 'react'; -import { Animated, TextInput } from 'react-native'; +import * as ReactNative from '../react-native'; + import { errorMsg } from '../../shared/logUtils'; import { mergeRefs } from '../../shared/mergeRefs'; import { useNativeProps } from './useNativeProps'; import { useStrictDOMElement } from './useStrictDOMElement'; -const AnimatedTextInput = Animated.createAnimatedComponent< - React.ElementConfig, - typeof TextInput ->(TextInput); +const AnimatedTextInput = ReactNative.Animated.createAnimatedComponent< + React.ElementConfig, + typeof ReactNative.TextInput +>(ReactNative.TextInput); export function createStrictDOMTextInputComponent< P: StrictReactDOMInputProps | StrictReactDOMTextAreaProps, @@ -31,8 +32,9 @@ export function createStrictDOMTextInputComponent< ): component(ref?: React.RefSetter, ...P) { const component: React.AbstractComponent = React.forwardRef( function (props, forwardedRef) { - let NativeComponent: typeof TextInput | typeof AnimatedTextInput = - TextInput; + let NativeComponent: + | typeof ReactNative.TextInput + | typeof AnimatedTextInput = ReactNative.TextInput; const elementRef = useStrictDOMElement({ tagName }); const { diff --git a/packages/react-strict-dom/src/native/modules/usePseudoStates.js b/packages/react-strict-dom/src/native/modules/usePseudoStates.js index 4a136486..eb478827 100644 --- a/packages/react-strict-dom/src/native/modules/usePseudoStates.js +++ b/packages/react-strict-dom/src/native/modules/usePseudoStates.js @@ -9,7 +9,7 @@ import type { Style } from '../../types/styles'; -import { useMemo, useState } from 'react'; +import * as React from 'react'; type InteractionHandlers = { onBlur?: () => void, @@ -31,10 +31,10 @@ type Interaction = { }; export function usePseudoStates(style: Style): Interaction { - const [focus, setFocus] = useState(false); - const [mouseHover, setMouseHover] = useState(false); - const [pointerHover, setPointerHover] = useState(false); - const [active, setActive] = useState(false); + const [focus, setFocus] = React.useState(false); + const [mouseHover, setMouseHover] = React.useState(false); + const [pointerHover, setPointerHover] = React.useState(false); + const [active, setActive] = React.useState(false); let isHoverStyledElement = false; let isFocusStyledElement = false; @@ -61,7 +61,7 @@ export function usePseudoStates(style: Style): Interaction { } } - const handlers = useMemo(() => { + const handlers = React.useMemo(() => { let value = null; if (isHoverStyledElement || isFocusStyledElement || isActiveStyledElement) { value = {} as InteractionHandlers; diff --git a/packages/react-strict-dom/src/native/modules/useStrictDOMElement.js b/packages/react-strict-dom/src/native/modules/useStrictDOMElement.js index 44ea3abd..663cf76d 100644 --- a/packages/react-strict-dom/src/native/modules/useStrictDOMElement.js +++ b/packages/react-strict-dom/src/native/modules/useStrictDOMElement.js @@ -9,7 +9,8 @@ import type { CallbackRef } from '../../types/react'; -import { useCallback } from 'react'; +import * as React from 'react'; + import { useElementCallback } from '../../shared/useElementCallback'; import { errorMsg } from '../../shared/logUtils'; @@ -33,7 +34,7 @@ type Options = { export function useStrictDOMElement({ tagName }: Options): CallbackRef { const elementCallback = useElementCallback( - useCallback( + React.useCallback( // $FlowFixMe[unclear-type] (node: any) => { Object.defineProperty(node, 'nodeName', { diff --git a/packages/react-strict-dom/src/native/modules/useStyleProps.js b/packages/react-strict-dom/src/native/modules/useStyleProps.js index 9caaced3..ed604680 100644 --- a/packages/react-strict-dom/src/native/modules/useStyleProps.js +++ b/packages/react-strict-dom/src/native/modules/useStyleProps.js @@ -14,7 +14,8 @@ import type { } from '../../types/renderer.native'; import * as stylex from '../stylex'; -import { useColorScheme, useWindowDimensions } from 'react-native'; +import * as ReactNative from '../react-native'; + import { flattenStyle } from './flattenStyle'; import { useInheritedStyles } from './ContextInheritedStyles'; import { usePseudoStates } from './usePseudoStates'; @@ -63,8 +64,8 @@ export function useStyleProps( writingDirection: dir } = options; - const { fontScale, height, width } = useWindowDimensions(); - const colorScheme = useColorScheme(); + const { fontScale, height, width } = ReactNative.useWindowDimensions(); + const colorScheme = ReactNative.useColorScheme(); // These values are already computed const { diff --git a/packages/react-strict-dom/src/native/modules/useStyleTransition.js b/packages/react-strict-dom/src/native/modules/useStyleTransition.js index 69178d17..e0b6e285 100644 --- a/packages/react-strict-dom/src/native/modules/useStyleTransition.js +++ b/packages/react-strict-dom/src/native/modules/useStyleTransition.js @@ -14,9 +14,10 @@ import type { ReactNativeTransform } from '../../types/renderer.native'; -import { useEffect, useLayoutEffect, useRef, useState } from 'react'; +import * as React from 'react'; +import * as ReactNative from '../react-native'; + import { errorMsg, warnMsg } from '../../shared/logUtils'; -import { Animated, Easing } from 'react-native'; type AnimatedStyle = { [string]: ?ReactNativeStyleValue | $ReadOnlyArray @@ -32,7 +33,7 @@ type TransitionMetadata = $ReadOnly<{ type AnimatedConfig = { start: () => void, dispose: () => void, - value: Animated.Value, + value: ReactNative.Animated.Value, referenceCount: number }; @@ -71,20 +72,20 @@ function canUseNativeDriver( function getEasingFunction(input: ?string) { if (input === 'ease') { - return Easing.ease; + return ReactNative.Easing.ease; } else if (input === 'ease-in') { - return Easing.in(Easing.ease); + return ReactNative.Easing.in(ReactNative.Easing.ease); } else if (input === 'ease-out') { - return Easing.out(Easing.ease); + return ReactNative.Easing.out(ReactNative.Easing.ease); } else if (input === 'ease-in-out') { - return Easing.inOut(Easing.ease); + return ReactNative.Easing.inOut(ReactNative.Easing.ease); } else if (input != null && input.includes('cubic-bezier')) { const chunk = input.split('cubic-bezier(')[1]; const str = chunk.split(')')[0]; const curve = str.split(',').map((point) => parseFloat(point.trim())); - return Easing.bezier(...curve); + return ReactNative.Easing.bezier(...curve); } - return Easing.linear; + return ReactNative.Easing.linear; } function getTransitionProperties(property: mixed): ?(string[]) { @@ -200,7 +201,7 @@ function transitionStyleHasChanged( } function getAnimation( - animatedValue: Animated.Value, + animatedValue: ReactNative.Animated.Value, duration: number, timingFunction: string | null, shouldUseNativeDriver: boolean @@ -215,7 +216,7 @@ function getAnimation( errorMsg( `spring() timing function of "${timingFunction}" is missing closing parenthesis.` ); - return Animated.timing(animatedValue, { + return ReactNative.Animated.timing(animatedValue, { duration, easing: getEasingFunction(null), toValue: 1, @@ -249,7 +250,7 @@ function getAnimation( initialVelocity = 0; } - return Animated.spring(animatedValue, { + return ReactNative.Animated.spring(animatedValue, { damping, mass, stiffness, @@ -259,7 +260,7 @@ function getAnimation( }); } - return Animated.timing(animatedValue, { + return ReactNative.Animated.timing(animatedValue, { duration, easing: getEasingFunction(timingFunction), toValue: 1, @@ -279,7 +280,7 @@ function getOrCreateAnimatedConfig(transitionMetadata: TransitionMetadata) { return animatedConfig; } - const animatedValue = new Animated.Value(0); + const animatedValue = new ReactNative.Animated.Value(0); let hasStarted = false; let animation; const newAnimatedConfig = { @@ -292,8 +293,8 @@ function getOrCreateAnimatedConfig(transitionMetadata: TransitionMetadata) { hasStarted = true; const { delay, duration, timingFunction, shouldUseNativeDriver } = transitionMetadata; - animation = Animated.sequence([ - Animated.delay(delay), + animation = ReactNative.Animated.sequence([ + ReactNative.Animated.delay(delay), getAnimation( animatedValue, duration, @@ -339,28 +340,25 @@ export function useStyleTransition(style: ReactNativeStyle): ReactNativeStyle { return output; }, {}); - const [currentStyle, setCurrentStyle] = useState( - style - ); - const [previousStyle, setPreviousStyle] = useState( - undefined - ); + const [currentStyle, setCurrentStyle] = + React.useState(style); + const [previousStyle, setPreviousStyle] = + React.useState(undefined); - const [animatedConfig, setAnimatedConfig] = useState( - undefined - ); + const [animatedConfig, setAnimatedConfig] = + React.useState(undefined); // This ref is utilized as a performance optimization so that the effect that contains the // animation trigger only is called when the animated value's identity changes. As far as the effect // is concerned it just needs the most up to date version of these transition properties; - const transitionMetadataRef = useRef({ + const transitionMetadataRef = React.useRef({ delay: transitionDelay, duration: transitionDuration, timingFunction: transitionTimingFunction, shouldUseNativeDriver: canUseNativeDriver(transitionStyle) }); // effect to sync the transition metadata - useEffect(() => { + React.useEffect(() => { transitionMetadataRef.current = { delay: transitionDelay, duration: transitionDuration, @@ -376,7 +374,7 @@ export function useStyleTransition(style: ReactNativeStyle): ReactNativeStyle { // effect to trigger a transition // REMEMBER: it is super important that this effect's dependency array **only** contains the animated config - useEffect(() => { + React.useEffect(() => { if (animatedConfig == null) { return; } @@ -392,7 +390,7 @@ export function useStyleTransition(style: ReactNativeStyle): ReactNativeStyle { currentStyle ); - useLayoutEffect(() => { + React.useLayoutEffect(() => { if (transitionStyleHasChangedResult) { setCurrentStyle(style); setPreviousStyle(currentStyle); diff --git a/packages/react-strict-dom/src/native/modules/version.js b/packages/react-strict-dom/src/native/modules/version.js index 515ee47e..97e7e523 100644 --- a/packages/react-strict-dom/src/native/modules/version.js +++ b/packages/react-strict-dom/src/native/modules/version.js @@ -8,9 +8,9 @@ */ // $FlowFixMe(nonstrict-import) -import { Platform } from 'react-native'; +import * as ReactNative from '../react-native'; -const reactNativeVersion = Platform.constants.reactNativeVersion; +const reactNativeVersion = ReactNative.Platform.constants.reactNativeVersion; const { major, minor, patch, prerelease } = reactNativeVersion; // Main branch OSS build, or internal build const isHead = major === 1000 && minor === 0 && patch === 0; diff --git a/packages/react-strict-dom/src/native/react-native/Text.js b/packages/react-strict-dom/src/native/react-native/LayoutConformance.js similarity index 72% rename from packages/react-strict-dom/src/native/react-native/Text.js rename to packages/react-strict-dom/src/native/react-native/LayoutConformance.js index b615279c..21bdcb58 100644 --- a/packages/react-strict-dom/src/native/react-native/Text.js +++ b/packages/react-strict-dom/src/native/react-native/LayoutConformance.js @@ -7,4 +7,4 @@ * @flow strict-local */ -export { Text } from 'react-native'; +export { experimental_LayoutConformance as LayoutConformance } from 'react-native'; diff --git a/packages/react-strict-dom/src/native/react-native/TextInput.js b/packages/react-strict-dom/src/native/react-native/TextInput.js deleted file mode 100644 index e8cecae6..00000000 --- a/packages/react-strict-dom/src/native/react-native/TextInput.js +++ /dev/null @@ -1,10 +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 - */ - -export { TextInput } from 'react-native'; diff --git a/packages/react-strict-dom/src/native/react-native/index.js b/packages/react-strict-dom/src/native/react-native/index.js index 425a5392..6c7da342 100644 --- a/packages/react-strict-dom/src/native/react-native/index.js +++ b/packages/react-strict-dom/src/native/react-native/index.js @@ -7,7 +7,16 @@ * @flow strict-local */ -export { Text } from './Text'; +export { + Animated, + Easing, + Image, + Platform, + Pressable, + Text, + TextInput +} from 'react-native'; +export { LayoutConformance } from './LayoutConformance'; export { TextAncestorContext } from './TextAncestorContext'; -export { TextInput } from './TextInput'; export { ViewNativeComponent } from './ViewNativeComponent'; +export { useColorScheme, useWindowDimensions } from 'react-native';