Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/react-strict-dom/src/native/compat.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

import type { StrictProps } from '../types/StrictProps';
import type { StrictReactNativeMetaProps } from '../types/renderer.native';

import * as React from 'react';

Expand All @@ -31,7 +32,9 @@ import { createStrictDOMTextInputComponent as createStrictTextInput } from './mo
* aria-label="label"
* as="text"
* >
* {(nativeProps: React.PropsOf<Text>)) => (
* {(nativeProps: React.PropsOf<Text>, meta) => (
* // `meta.inheritedTextStyle` and `meta.resolveStyleValue` allow resolving
* // CSS inheritance and `var(...)` for non-RSD host components.
* <Text {...nativeProps} />
* )}
* </compat.native>
Expand All @@ -42,7 +45,7 @@ const defaultProps = {};
type StrictPropsOnlyCompat<T> = {
...StrictProps,
as?: 'div' | 'img' | 'input' | 'span' | 'textarea',
children: (nativeProps: T) => React.Node
children: (nativeProps: T, meta: StrictReactNativeMetaProps) => React.Node
};

const StrictText = createStrictText('span', defaultProps) as $FlowFixMe;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,29 @@
*/

import type { ReactNativeProps } from '../../types/renderer.native';
import type { StrictReactNativeMetaProps } from '../../types/renderer.native';
import type { StrictProps as StrictPropsOriginal } from '../../types/StrictProps';

import * as React from 'react';
import * as ReactNative from '../react-native';

import { ProvideCustomProperties } from './ContextCustomProperties';
import { ProvideDisplayInside, useDisplayInside } from './ContextDisplayInside';
import { ProvideInheritedStyles } from './ContextInheritedStyles';
import {
ProvideInheritedStyles,
useInheritedStyles
} from './ContextInheritedStyles';
import { flattenStyle } from './flattenStyle';
import { TextString } from './TextString';
import { errorMsg } from '../../shared/logUtils';
import { useNativeProps } from './useNativeProps';
import { useStrictDOMElement } from './useStrictDOMElement';

type StrictProps = Readonly<{
...StrictPropsOriginal,
children?: React.Node | ((ReactNativeProps) => React.Node)
children?:
| React.Node
| ((ReactNativeProps, StrictReactNativeMetaProps) => React.Node)
}>;

const AnimatedPressable = ReactNative.Animated.createAnimatedComponent(
Expand Down Expand Up @@ -54,15 +61,22 @@ export function createStrictDOMComponent<T, P extends StrictProps>(
* Resolve global HTML and style props
*/

const { customProperties, nativeProps, inheritableStyle } = useNativeProps(
defaultProps,
props,
{
provideInheritableStyle,
withInheritedStyle: false,
withTextStyle: false
}
);
const {
customProperties,
resolveStyleValue,
nativeProps,
inheritableStyle
} = useNativeProps(defaultProps, props, {
provideInheritableStyle,
withInheritedStyle: false,
withTextStyle: false
});

const ancestorInheritedStyle = useInheritedStyles();
const inheritedTextStyle = flattenStyle([
ancestorInheritedStyle,
inheritableStyle
]);

if (
nativeProps.onPress != null &&
Expand Down Expand Up @@ -193,7 +207,7 @@ export function createStrictDOMComponent<T, P extends StrictProps>(

let element: React.Node =
typeof props.children === 'function' ? (
props.children(nativeProps)
props.children(nativeProps, { inheritedTextStyle, resolveStyleValue })
) : (
// $FlowFixMe[incompatible-type]
<NativeComponent {...nativeProps} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import * as React from 'react';
import * as ReactNative from '../react-native';

import { useNativeProps } from './useNativeProps';
import { useInheritedStyles } from './ContextInheritedStyles';
import { flattenStyle } from './flattenStyle';
import { useStrictDOMElement } from './useStrictDOMElement';
import * as css from '../css';

Expand Down Expand Up @@ -52,11 +54,21 @@ export function createStrictDOMImageComponent<
]
};

const { nativeProps } = useNativeProps(defaultProps, props, {
provideInheritableStyle: false,
withInheritedStyle: false,
withTextStyle: false
});
const { resolveStyleValue, nativeProps, inheritableStyle } = useNativeProps(
defaultProps,
props,
{
provideInheritableStyle: false,
withInheritedStyle: false,
withTextStyle: false
}
);

const ancestorInheritedStyle = useInheritedStyles();
const inheritedTextStyle = flattenStyle([
ancestorInheritedStyle,
inheritableStyle
]);

// Tag-specific props

Expand Down Expand Up @@ -122,7 +134,7 @@ export function createStrictDOMImageComponent<

const element: React.Node =
typeof props.children === 'function' ? (
props.children(nativeProps)
props.children(nativeProps, { inheritedTextStyle, resolveStyleValue })
) : (
// strict-dom's wide ReactNativeProps spreads onto RN 0.83's exact
// ImageProps; harmless extras are ignored at runtime.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,27 @@
*/

import type { ReactNativeProps } from '../../types/renderer.native';
import type { StrictReactNativeMetaProps } from '../../types/renderer.native';
import type { StrictProps as StrictPropsOriginal } from '../../types/StrictProps';

import * as React from 'react';
import * as ReactNative from '../react-native';

import { ProvideCustomProperties } from './ContextCustomProperties';
import { ProvideInheritedStyles } from './ContextInheritedStyles';
import {
ProvideInheritedStyles,
useInheritedStyles
} from './ContextInheritedStyles';
import { flattenStyle } from './flattenStyle';
import { errorMsg } from '../../shared/logUtils';
import { useNativeProps } from './useNativeProps';
import { useStrictDOMElement } from './useStrictDOMElement';

type StrictProps = Readonly<{
...StrictPropsOriginal,
children?: React.Node | ((ReactNativeProps) => React.Node)
children?:
| React.Node
| ((ReactNativeProps, StrictReactNativeMetaProps) => React.Node)
}>;

function hasElementChildren(children: unknown): boolean {
Expand All @@ -44,19 +51,26 @@ export function createStrictDOMTextComponent<T, P extends StrictProps>(
* Resolve global HTML and style props
*/

const { customProperties, nativeProps, inheritableStyle } = useNativeProps(
defaultProps,
props,
{
provideInheritableStyle:
tagName !== 'br' ||
// $FlowFixMe[invalid-compare]
tagName !== 'option' ||
hasElementChildren(props.children),
withInheritedStyle: true,
withTextStyle: true
}
);
const {
customProperties,
resolveStyleValue,
nativeProps,
inheritableStyle
} = useNativeProps(defaultProps, props, {
provideInheritableStyle:
tagName !== 'br' ||
// $FlowFixMe[invalid-compare]
tagName !== 'option' ||
hasElementChildren(props.children),
withInheritedStyle: true,
withTextStyle: true
});

const ancestorInheritedStyle = useInheritedStyles();
const inheritedTextStyle = flattenStyle([
ancestorInheritedStyle,
inheritableStyle
]);

// Tag-specific props

Expand Down Expand Up @@ -128,7 +142,7 @@ export function createStrictDOMTextComponent<T, P extends StrictProps>(

let element: React.Node =
typeof props.children === 'function' ? (
props.children(nativeProps)
props.children(nativeProps, { inheritedTextStyle, resolveStyleValue })
) : (
// $FlowFixMe[incompatible-type]
<NativeComponent {...nativeProps} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import * as ReactNative from '../react-native';

import { errorMsg } from '../../shared/logUtils';
import { mergeRefs } from '../../shared/mergeRefs';
import { useInheritedStyles } from './ContextInheritedStyles';
import { flattenStyle } from './flattenStyle';
import { useNativeProps } from './useNativeProps';
import { useStrictDOMElement } from './useStrictDOMElement';

Expand Down Expand Up @@ -76,11 +78,21 @@ export function createStrictDOMTextInputComponent<
* Resolve global HTML and style props
*/

const { nativeProps } = useNativeProps(defaultProps, props, {
provideInheritableStyle: false,
withInheritedStyle: false,
withTextStyle: true
});
const { resolveStyleValue, nativeProps, inheritableStyle } = useNativeProps(
defaultProps,
props,
{
provideInheritableStyle: false,
withInheritedStyle: false,
withTextStyle: true
}
);

const ancestorInheritedStyle = useInheritedStyles();
const inheritedTextStyle = flattenStyle([
ancestorInheritedStyle,
inheritableStyle
]);

// Tag-specific props

Expand Down Expand Up @@ -246,7 +258,7 @@ export function createStrictDOMTextInputComponent<

const element =
typeof props.children === 'function' ? (
props.children(nativeProps)
props.children(nativeProps, { inheritedTextStyle, resolveStyleValue })
) : (
// strict-dom's wide ReactNativeProps spreads onto RN 0.83's exact
// TextInputProps; harmless extras are ignored at runtime.
Expand Down
32 changes: 30 additions & 2 deletions packages/react-strict-dom/src/native/modules/useNativeProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,32 @@
*/

import type { CustomProperties } from '../../types/styles';
import type { ReactNativeProps } from '../../types/renderer.native';
import type {
ReactNativeProps,
StrictReactNativeMetaProps
} from '../../types/renderer.native';
import type { StrictProps as StrictPropsOriginal } from '../../types/StrictProps';
import type { Style } from '../../types/styles';

import * as ReactNative from '../react-native';
import { CSSUnparsedValue } from '../css/typed-om/CSSUnparsedValue';
import {
resolveVariableReferences,
stringContainsVariables
} from '../css/customProperties';
import { errorMsg, warnMsg } from '../../shared/logUtils';
import { extractStyleThemes } from './extractStyleThemes';
import { isPropAllowed } from '../../shared/isPropAllowed';
import { useCustomProperties } from './ContextCustomProperties';
import { useStyleProps } from './useStyleProps';

export type ResolveStyleValue = (value: string) => string | number | null;

type StrictProps = Readonly<{
...StrictPropsOriginal,
children?: React.Node | ((ReactNativeProps) => React.Node)
children?:
| React.Node
| ((ReactNativeProps, StrictReactNativeMetaProps) => React.Node)
}>;

/**
Expand Down Expand Up @@ -83,6 +96,7 @@ type OptionsType = {|
|};
type ReturnType = {|
customProperties: ?CustomProperties,
resolveStyleValue: ResolveStyleValue,
nativeProps: ReactNativeProps,
inheritableStyle: ?Style
|};
Expand Down Expand Up @@ -158,6 +172,19 @@ export function useNativeProps(
extractStyleThemes(renderStyle);
const customProperties = useCustomProperties(customPropertiesFromThemes);

const colorScheme = ReactNative.useColorScheme();
const resolveStyleValue: ResolveStyleValue = (value) => {
if (typeof value !== 'string' || !stringContainsVariables(value)) {
return value;
}
return resolveVariableReferences(
'styleValue',
CSSUnparsedValue.parse('styleValue', value),
customProperties,
colorScheme === 'dark' ? 'dark' : 'light'
);
};

const { nativeProps, inheritableStyle } = useStyleProps(extractedStyle, {
customProperties,
provideInheritableStyle: options.provideInheritableStyle,
Expand Down Expand Up @@ -440,6 +467,7 @@ export function useNativeProps(
return {
customProperties:
customPropertiesFromThemes != null ? customProperties : null,
resolveStyleValue,
nativeProps,
inheritableStyle
};
Expand Down
7 changes: 7 additions & 0 deletions packages/react-strict-dom/src/types/renderer.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import type {
// $FlowFixMe[nonstrict-import]
ViewProps
} from 'react-native/Libraries/Components/View/ViewPropTypes';
import type { Style } from './styles';

type ReactNativeProps = {
accessible?: ViewProps['accessible'],
Expand Down Expand Up @@ -147,11 +148,17 @@ type ReactNativeStyleValue =

type ReactNativeStyle = { [string]: ?ReactNativeStyleValue };

type StrictReactNativeMetaProps = {
+inheritedTextStyle: Style,
+resolveStyleValue: (value: string) => string | number | null
};

export type {
CompositeAnimation,
ReactNativeProps,
ReactNativeStyle,
ReactNativeStyleValue,
ReactNativeTransform,
StrictReactNativeMetaProps,
SyntheticEvent
};
Loading
Loading