react-native-boost 1.0.0 → 1.2.0
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/README.md +16 -4
- package/dist/plugin/esm/index.mjs +167 -92
- package/dist/plugin/esm/index.mjs.map +1 -1
- package/dist/plugin/index.d.ts +10 -0
- package/dist/plugin/index.js +167 -92
- package/dist/plugin/index.js.map +1 -1
- package/dist/runtime/esm/index.mjs +16 -4
- package/dist/runtime/esm/index.mjs.map +1 -1
- package/dist/runtime/esm/index.web.mjs +2 -1
- package/dist/runtime/esm/index.web.mjs.map +1 -1
- package/dist/runtime/index.d.ts +16 -3
- package/dist/runtime/index.js +15 -2
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/index.web.d.ts +2 -1
- package/dist/runtime/index.web.js +2 -0
- package/dist/runtime/index.web.js.map +1 -1
- package/package.json +6 -1
- package/src/plugin/index.ts +5 -1
- package/src/plugin/optimizers/text/index.ts +118 -50
- package/src/plugin/optimizers/view/index.ts +37 -41
- package/src/plugin/types/index.ts +18 -1
- package/src/plugin/utils/common/attributes.ts +71 -12
- package/src/plugin/utils/common/validation.ts +52 -32
- package/src/plugin/utils/logger.ts +16 -2
- package/src/runtime/index.ts +39 -5
- package/src/runtime/index.web.ts +5 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../src/runtime/utils/constants.ts","../../../src/runtime/components/native-text.tsx","../../../src/runtime/components/native-view.tsx","../../../src/runtime/index.ts"],"sourcesContent":["/**\n * Maps CSS-like `userSelect` values to React Native's `selectable` prop.\n */\nexport const userSelectToSelectableMap = {\n auto: true,\n text: true,\n none: false,\n contain: true,\n all: true,\n};\n\n/**\n * Maps CSS-like `verticalAlign` values to React Native's `textAlignVertical`.\n */\nexport const verticalAlignToTextAlignVerticalMap = {\n auto: 'auto',\n top: 'top',\n bottom: 'bottom',\n middle: 'center',\n};\n","/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n\nimport type { ComponentType } from 'react';\nimport type { TextProps } from 'react-native';\n\nconst reactNative = require('react-native');\nconst isWeb = reactNative.Platform.OS === 'web';\n\nlet nativeText = reactNative.unstable_NativeText;\n\nif (isWeb || nativeText == null) {\n // Fallback to regular Text component if unstable_NativeText is not available or we're on Web\n nativeText = reactNative.Text;\n}\n\n/**\n * Native Text component with graceful fallback.\n *\n * @remarks\n * Uses `unstable_NativeText` on supported native runtimes and falls back to `Text`\n * on web or when the unstable export is unavailable.\n */\nexport const NativeText: ComponentType<TextProps> = nativeText;\n","/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n\nimport type { ComponentType } from 'react';\nimport type { ViewProps } from 'react-native';\n\nconst reactNative = require('react-native');\nconst isWeb = reactNative.Platform.OS === 'web';\n\nlet nativeView = reactNative.unstable_NativeView;\n\nif (isWeb || nativeView == null) {\n // Fallback to regular View component if unstable_NativeView is not available or we're on Web\n nativeView = reactNative.View;\n}\n\n/**\n * Native View component with graceful fallback.\n *\n * @remarks\n * Uses `unstable_NativeView` on supported native runtimes and falls back to `View`\n * on web or when the unstable export is unavailable.\n */\nexport const NativeView: ComponentType<ViewProps> = nativeView;\n","import { TextProps, TextStyle, StyleSheet } from 'react-native';\nimport { GenericStyleProp } from './types';\nimport { userSelectToSelectableMap, verticalAlignToTextAlignVerticalMap } from './utils/constants';\n\nconst propsCache = new WeakMap();\n\n/**\n * Normalizes `Text` style values for `NativeText`.\n *\n * @param style - Style prop passed to a text-like component.\n * @returns Native-friendly text props. Returns an empty object when `style` is falsy or cannot be normalized.\n * @remarks\n * - Flattens style arrays via `StyleSheet.flatten`\n * - Converts numeric `fontWeight` values to string values\n * - Maps `userSelect` and `verticalAlign` to native-compatible props\n */\nexport function processTextStyle(style: GenericStyleProp<TextStyle>): Partial<TextProps> {\n if (!style) return {};\n\n // Cache the computed props\n let props = propsCache.get(style);\n if (props) return props;\n\n props = {};\n propsCache.set(style, props);\n\n style = StyleSheet.flatten(style) as TextStyle;\n\n if (!style) return {};\n\n if (typeof style?.fontWeight === 'number') {\n style.fontWeight = style.fontWeight.toString() as TextStyle['fontWeight'];\n }\n\n if (style?.userSelect != null) {\n props.selectable = userSelectToSelectableMap[style.userSelect];\n delete style.userSelect;\n }\n\n if (style?.verticalAlign != null) {\n style.textAlignVertical = verticalAlignToTextAlignVerticalMap[\n style.verticalAlign\n ] as TextStyle['textAlignVertical'];\n delete style.verticalAlign;\n }\n\n props.style = style;\n return props;\n}\n\n/**\n * Normalizes accessibility and ARIA props for runtime native components.\n *\n * @param props - Accessibility and ARIA props.\n * @returns Props with normalized accessibility fields.\n * @remarks\n * - Merges `aria-label` with `accessibilityLabel`\n * - Merges ARIA state fields into `accessibilityState`\n * - Defaults `accessible` to `true` when omitted\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function processAccessibilityProps(props: Record<string, any>): Record<string, any> {\n const {\n accessibilityLabel,\n ['aria-label']: ariaLabel,\n accessibilityState,\n ['aria-busy']: ariaBusy,\n ['aria-checked']: ariaChecked,\n ['aria-disabled']: ariaDisabled,\n ['aria-expanded']: ariaExpanded,\n ['aria-selected']: ariaSelected,\n accessible,\n ...restProperties\n } = props;\n\n // Merge label props: prefer the aria-label if defined.\n const normalizedLabel = ariaLabel ?? accessibilityLabel;\n\n // Merge the accessibilityState with any provided ARIA properties.\n let normalizedState = accessibilityState;\n if (ariaBusy != null || ariaChecked != null || ariaDisabled != null || ariaExpanded != null || ariaSelected != null) {\n normalizedState =\n normalizedState == null\n ? {\n busy: ariaBusy,\n checked: ariaChecked,\n disabled: ariaDisabled,\n expanded: ariaExpanded,\n selected: ariaSelected,\n }\n : {\n busy: ariaBusy ?? normalizedState.busy,\n checked: ariaChecked ?? normalizedState.checked,\n disabled: ariaDisabled ?? normalizedState.disabled,\n expanded: ariaExpanded ?? normalizedState.expanded,\n selected: ariaSelected ?? normalizedState.selected,\n };\n }\n\n // For the accessible prop, if not provided, default to `true`\n const normalizedAccessible = accessible == null ? true : accessible;\n\n return {\n ...restProperties,\n accessibilityLabel: normalizedLabel,\n accessibilityState: normalizedState,\n accessible: normalizedAccessible,\n };\n}\n\nexport * from './types';\nexport * from './utils/constants';\nexport * from './components/native-text';\nexport * from './components/native-view';\n"],"names":["reactNative","isWeb"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../src/runtime/utils/constants.ts","../../../src/runtime/components/native-text.tsx","../../../src/runtime/components/native-view.tsx","../../../src/runtime/index.ts"],"sourcesContent":["/**\n * Maps CSS-like `userSelect` values to React Native's `selectable` prop.\n */\nexport const userSelectToSelectableMap = {\n auto: true,\n text: true,\n none: false,\n contain: true,\n all: true,\n};\n\n/**\n * Maps CSS-like `verticalAlign` values to React Native's `textAlignVertical`.\n */\nexport const verticalAlignToTextAlignVerticalMap = {\n auto: 'auto',\n top: 'top',\n bottom: 'bottom',\n middle: 'center',\n};\n","/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n\nimport type { ComponentType } from 'react';\nimport type { TextProps } from 'react-native';\n\nconst reactNative = require('react-native');\nconst isWeb = reactNative.Platform.OS === 'web';\n\nlet nativeText = reactNative.unstable_NativeText;\n\nif (isWeb || nativeText == null) {\n // Fallback to regular Text component if unstable_NativeText is not available or we're on Web\n nativeText = reactNative.Text;\n}\n\n/**\n * Native Text component with graceful fallback.\n *\n * @remarks\n * Uses `unstable_NativeText` on supported native runtimes and falls back to `Text`\n * on web or when the unstable export is unavailable.\n */\nexport const NativeText: ComponentType<TextProps> = nativeText;\n","/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n\nimport type { ComponentType } from 'react';\nimport type { ViewProps } from 'react-native';\n\nconst reactNative = require('react-native');\nconst isWeb = reactNative.Platform.OS === 'web';\n\nlet nativeView = reactNative.unstable_NativeView;\n\nif (isWeb || nativeView == null) {\n // Fallback to regular View component if unstable_NativeView is not available or we're on Web\n nativeView = reactNative.View;\n}\n\n/**\n * Native View component with graceful fallback.\n *\n * @remarks\n * Uses `unstable_NativeView` on supported native runtimes and falls back to `View`\n * on web or when the unstable export is unavailable.\n */\nexport const NativeView: ComponentType<ViewProps> = nativeView;\n","import { TextProps, TextStyle, StyleSheet, Platform } from 'react-native';\nimport { GenericStyleProp } from './types';\nimport { userSelectToSelectableMap, verticalAlignToTextAlignVerticalMap } from './utils/constants';\n\nconst propsCache = new WeakMap();\n\n/**\n * Normalizes `Text` style values for `NativeText`.\n *\n * @param style - Style prop passed to a text-like component.\n * @returns Native-friendly text props. Returns an empty object when `style` is falsy or cannot be normalized.\n * @remarks\n * - Flattens style arrays via `StyleSheet.flatten`\n * - Converts numeric `fontWeight` values to string values\n * - Maps `userSelect` and `verticalAlign` to native-compatible props\n */\nexport function processTextStyle(style: GenericStyleProp<TextStyle>): Partial<TextProps> {\n if (!style) return {};\n\n // Cache the computed props\n let props = propsCache.get(style);\n if (props) return props;\n\n props = {};\n propsCache.set(style, props);\n\n style = StyleSheet.flatten(style) as TextStyle;\n\n if (!style) return {};\n\n if (typeof style?.fontWeight === 'number') {\n style.fontWeight = style.fontWeight.toString() as TextStyle['fontWeight'];\n }\n\n if (style?.userSelect != null) {\n props.selectable = userSelectToSelectableMap[style.userSelect];\n delete style.userSelect;\n }\n\n if (style?.verticalAlign != null) {\n style.textAlignVertical = verticalAlignToTextAlignVerticalMap[\n style.verticalAlign\n ] as TextStyle['textAlignVertical'];\n delete style.verticalAlign;\n }\n\n props.style = style;\n return props;\n}\n\n/**\n * The default value `Text` resolves for `accessible` when the prop is omitted: `true` on iOS (text is\n * an accessibility element unless opted out), `false` on Android, and `undefined` elsewhere.\n *\n * @remarks\n * Runtime fallback for the common optimized `<Text>` path (no accessibility props) when the target\n * platform is unknown at build time. When it is known (Metro reports it on the Babel caller), the\n * plugin inlines the literal instead and this is not emitted. Evaluated per render — like `Text`'s own\n * `Platform.select` — rather than hoisted to a constant, so it always reflects the current platform.\n */\nexport const getDefaultTextAccessible = (): boolean | undefined => Platform.select({ ios: true, android: false });\n\n/**\n * Normalizes accessibility and ARIA props for runtime native components, mirroring the reconciliation\n * `Text` performs before handing off to its native host.\n *\n * @param props - Accessibility and ARIA props.\n * @returns Props with normalized accessibility fields.\n * @remarks\n * - Merges `aria-label` with `accessibilityLabel`\n * - Merges ARIA state fields into `accessibilityState`\n * - Reconciles `disabled` with `accessibilityState.disabled` (the explicit `disabled` prop wins)\n * - Resolves the platform-specific `accessible` default (see {@link getDefaultTextAccessible})\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function processAccessibilityProps(props: Record<string, any>): Record<string, any> {\n const {\n accessibilityLabel,\n ['aria-label']: ariaLabel,\n accessibilityState,\n ['aria-busy']: ariaBusy,\n ['aria-checked']: ariaChecked,\n ['aria-disabled']: ariaDisabled,\n ['aria-expanded']: ariaExpanded,\n ['aria-selected']: ariaSelected,\n accessible,\n disabled,\n ...restProperties\n } = props;\n\n // Merge label props: prefer the aria-label if defined.\n const normalizedLabel = ariaLabel ?? accessibilityLabel;\n\n // Merge the accessibilityState with any provided ARIA properties.\n let normalizedState = accessibilityState;\n if (ariaBusy != null || ariaChecked != null || ariaDisabled != null || ariaExpanded != null || ariaSelected != null) {\n normalizedState =\n normalizedState == null\n ? {\n busy: ariaBusy,\n checked: ariaChecked,\n disabled: ariaDisabled,\n expanded: ariaExpanded,\n selected: ariaSelected,\n }\n : {\n busy: ariaBusy ?? normalizedState.busy,\n checked: ariaChecked ?? normalizedState.checked,\n disabled: ariaDisabled ?? normalizedState.disabled,\n expanded: ariaExpanded ?? normalizedState.expanded,\n selected: ariaSelected ?? normalizedState.selected,\n };\n }\n\n // Reconcile `disabled` with `accessibilityState.disabled`. When the two are out of sync (and not\n // both falsy) the explicit `disabled` prop wins and is mirrored back into the state object, so the\n // native host receives a consistent value on both fields.\n const stateDisabled = normalizedState?.disabled;\n const normalizedDisabled = disabled ?? stateDisabled;\n if (\n normalizedDisabled !== stateDisabled &&\n ((normalizedDisabled != null && normalizedDisabled !== false) || (stateDisabled != null && stateDisabled !== false))\n ) {\n normalizedState = { ...normalizedState, disabled: normalizedDisabled };\n }\n\n // Resolve `accessible` exactly as `Text` does: opt-out on iOS, off by default on Android. The\n // Android pressable case (`onPress`/`onLongPress`) never applies — press handlers bail out of\n // optimization — so an omitted prop falls back to the platform default.\n const normalizedAccessible = Platform.select({\n ios: accessible !== false,\n android: accessible ?? false,\n default: accessible,\n });\n\n return {\n ...restProperties,\n accessibilityLabel: normalizedLabel,\n accessibilityState: normalizedState,\n accessible: normalizedAccessible,\n disabled: normalizedDisabled,\n };\n}\n\nexport * from './types';\nexport * from './utils/constants';\nexport * from './components/native-text';\nexport * from './components/native-view';\n"],"names":["reactNative","isWeb"],"mappings":"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"}
|
|
@@ -13,11 +13,12 @@ const verticalAlignToTextAlignVerticalMap = {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
const processTextStyle = (style) => ({ style });
|
|
16
|
+
const getDefaultTextAccessible = () => void 0;
|
|
16
17
|
function processAccessibilityProps(props) {
|
|
17
18
|
return props;
|
|
18
19
|
}
|
|
19
20
|
const NativeText = require("react-native").Text;
|
|
20
21
|
const NativeView = require("react-native").View;
|
|
21
22
|
|
|
22
|
-
export { NativeText, NativeView, processAccessibilityProps, processTextStyle, userSelectToSelectableMap, verticalAlignToTextAlignVerticalMap };
|
|
23
|
+
export { NativeText, NativeView, getDefaultTextAccessible, processAccessibilityProps, processTextStyle, userSelectToSelectableMap, verticalAlignToTextAlignVerticalMap };
|
|
23
24
|
//# sourceMappingURL=index.web.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.web.mjs","sources":["../../../src/runtime/utils/constants.ts","../../../src/runtime/index.web.ts"],"sourcesContent":["/**\n * Maps CSS-like `userSelect` values to React Native's `selectable` prop.\n */\nexport const userSelectToSelectableMap = {\n auto: true,\n text: true,\n none: false,\n contain: true,\n all: true,\n};\n\n/**\n * Maps CSS-like `verticalAlign` values to React Native's `textAlignVertical`.\n */\nexport const verticalAlignToTextAlignVerticalMap = {\n auto: 'auto',\n top: 'top',\n bottom: 'bottom',\n middle: 'center',\n};\n","// This is a dummy file to ensure that nothing breaks when using the runtime in a web environment.\n\nimport { TextProps, TextStyle } from 'react-native';\nimport { GenericStyleProp } from './types';\n\nexport const processTextStyle = (style: GenericStyleProp<TextStyle>) => ({ style }) as Partial<TextProps>;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function processAccessibilityProps(props: Record<string, any>): Record<string, any> {\n return props;\n}\n\nexport * from './types';\nexport * from './utils/constants';\n\n// On Web, the native components are not available, so we use the standard components that'll be replaced by their DOM\n// equivalents by react-native-web.\n/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\nexport const NativeText = require('react-native').Text;\nexport const NativeView = require('react-native').View;\n/* eslint-enable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n"],"names":[],"mappings":"AAGO,MAAM,yBAAA,GAA4B;AAAA,EACvC,IAAA,EAAM,IAAA;AAAA,EACN,IAAA,EAAM,IAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,OAAA,EAAS,IAAA;AAAA,EACT,GAAA,EAAK;AACP;AAKO,MAAM,mCAAA,GAAsC;AAAA,EACjD,IAAA,EAAM,MAAA;AAAA,EACN,GAAA,EAAK,KAAA;AAAA,EACL,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ;AACV;;ACdO,MAAM,gBAAA,GAAmB,CAAC,KAAA,MAAwC,EAAE,KAAA,EAAM;
|
|
1
|
+
{"version":3,"file":"index.web.mjs","sources":["../../../src/runtime/utils/constants.ts","../../../src/runtime/index.web.ts"],"sourcesContent":["/**\n * Maps CSS-like `userSelect` values to React Native's `selectable` prop.\n */\nexport const userSelectToSelectableMap = {\n auto: true,\n text: true,\n none: false,\n contain: true,\n all: true,\n};\n\n/**\n * Maps CSS-like `verticalAlign` values to React Native's `textAlignVertical`.\n */\nexport const verticalAlignToTextAlignVerticalMap = {\n auto: 'auto',\n top: 'top',\n bottom: 'bottom',\n middle: 'center',\n};\n","// This is a dummy file to ensure that nothing breaks when using the runtime in a web environment.\n\nimport { TextProps, TextStyle } from 'react-native';\nimport { GenericStyleProp } from './types';\n\nexport const processTextStyle = (style: GenericStyleProp<TextStyle>) => ({ style }) as Partial<TextProps>;\n\n// On Web there is no platform-specific `accessible` default to apply; react-native-web's `Text`\n// derives accessibility from the rendered DOM. Returning `undefined` makes the injected\n// `accessible={getDefaultTextAccessible()}` a no-op.\nexport const getDefaultTextAccessible = (): boolean | undefined => undefined;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function processAccessibilityProps(props: Record<string, any>): Record<string, any> {\n return props;\n}\n\nexport * from './types';\nexport * from './utils/constants';\n\n// On Web, the native components are not available, so we use the standard components that'll be replaced by their DOM\n// equivalents by react-native-web.\n/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\nexport const NativeText = require('react-native').Text;\nexport const NativeView = require('react-native').View;\n/* eslint-enable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n"],"names":[],"mappings":"AAGO,MAAM,yBAAA,GAA4B;AAAA,EACvC,IAAA,EAAM,IAAA;AAAA,EACN,IAAA,EAAM,IAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,OAAA,EAAS,IAAA;AAAA,EACT,GAAA,EAAK;AACP;AAKO,MAAM,mCAAA,GAAsC;AAAA,EACjD,IAAA,EAAM,MAAA;AAAA,EACN,GAAA,EAAK,KAAA;AAAA,EACL,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ;AACV;;ACdO,MAAM,gBAAA,GAAmB,CAAC,KAAA,MAAwC,EAAE,KAAA,EAAM;AAK1E,MAAM,2BAA2B,MAA2B;AAG5D,SAAS,0BAA0B,KAAA,EAAiD;AACzF,EAAA,OAAO,KAAA;AACT;AAQO,MAAM,UAAA,GAAa,OAAA,CAAQ,cAAc,CAAA,CAAE;AAC3C,MAAM,UAAA,GAAa,OAAA,CAAQ,cAAc,CAAA,CAAE;;;;"}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -58,16 +58,29 @@ declare const NativeView: ComponentType<ViewProps>;
|
|
|
58
58
|
*/
|
|
59
59
|
declare function processTextStyle(style: GenericStyleProp<TextStyle>): Partial<TextProps>;
|
|
60
60
|
/**
|
|
61
|
-
*
|
|
61
|
+
* The default value `Text` resolves for `accessible` when the prop is omitted: `true` on iOS (text is
|
|
62
|
+
* an accessibility element unless opted out), `false` on Android, and `undefined` elsewhere.
|
|
63
|
+
*
|
|
64
|
+
* @remarks
|
|
65
|
+
* Runtime fallback for the common optimized `<Text>` path (no accessibility props) when the target
|
|
66
|
+
* platform is unknown at build time. When it is known (Metro reports it on the Babel caller), the
|
|
67
|
+
* plugin inlines the literal instead and this is not emitted. Evaluated per render — like `Text`'s own
|
|
68
|
+
* `Platform.select` — rather than hoisted to a constant, so it always reflects the current platform.
|
|
69
|
+
*/
|
|
70
|
+
declare const getDefaultTextAccessible: () => boolean | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Normalizes accessibility and ARIA props for runtime native components, mirroring the reconciliation
|
|
73
|
+
* `Text` performs before handing off to its native host.
|
|
62
74
|
*
|
|
63
75
|
* @param props - Accessibility and ARIA props.
|
|
64
76
|
* @returns Props with normalized accessibility fields.
|
|
65
77
|
* @remarks
|
|
66
78
|
* - Merges `aria-label` with `accessibilityLabel`
|
|
67
79
|
* - Merges ARIA state fields into `accessibilityState`
|
|
68
|
-
* -
|
|
80
|
+
* - Reconciles `disabled` with `accessibilityState.disabled` (the explicit `disabled` prop wins)
|
|
81
|
+
* - Resolves the platform-specific `accessible` default (see {@link getDefaultTextAccessible})
|
|
69
82
|
*/
|
|
70
83
|
declare function processAccessibilityProps(props: Record<string, any>): Record<string, any>;
|
|
71
84
|
|
|
72
|
-
export { NativeText, NativeView, processAccessibilityProps, processTextStyle, userSelectToSelectableMap, verticalAlignToTextAlignVerticalMap };
|
|
85
|
+
export { NativeText, NativeView, getDefaultTextAccessible, processAccessibilityProps, processTextStyle, userSelectToSelectableMap, verticalAlignToTextAlignVerticalMap };
|
|
73
86
|
export type { GenericStyleProp };
|
package/dist/runtime/index.js
CHANGED
|
@@ -55,6 +55,7 @@ function processTextStyle(style) {
|
|
|
55
55
|
props.style = style;
|
|
56
56
|
return props;
|
|
57
57
|
}
|
|
58
|
+
const getDefaultTextAccessible = () => reactNative$2.Platform.select({ ios: true, android: false });
|
|
58
59
|
function processAccessibilityProps(props) {
|
|
59
60
|
const {
|
|
60
61
|
accessibilityLabel,
|
|
@@ -66,6 +67,7 @@ function processAccessibilityProps(props) {
|
|
|
66
67
|
["aria-expanded"]: ariaExpanded,
|
|
67
68
|
["aria-selected"]: ariaSelected,
|
|
68
69
|
accessible,
|
|
70
|
+
disabled,
|
|
69
71
|
...restProperties
|
|
70
72
|
} = props;
|
|
71
73
|
const normalizedLabel = ariaLabel != null ? ariaLabel : accessibilityLabel;
|
|
@@ -85,17 +87,28 @@ function processAccessibilityProps(props) {
|
|
|
85
87
|
selected: ariaSelected != null ? ariaSelected : normalizedState.selected
|
|
86
88
|
};
|
|
87
89
|
}
|
|
88
|
-
const
|
|
90
|
+
const stateDisabled = normalizedState == null ? void 0 : normalizedState.disabled;
|
|
91
|
+
const normalizedDisabled = disabled != null ? disabled : stateDisabled;
|
|
92
|
+
if (normalizedDisabled !== stateDisabled && (normalizedDisabled != null && normalizedDisabled !== false || stateDisabled != null && stateDisabled !== false)) {
|
|
93
|
+
normalizedState = { ...normalizedState, disabled: normalizedDisabled };
|
|
94
|
+
}
|
|
95
|
+
const normalizedAccessible = reactNative$2.Platform.select({
|
|
96
|
+
ios: accessible !== false,
|
|
97
|
+
android: accessible != null ? accessible : false,
|
|
98
|
+
default: accessible
|
|
99
|
+
});
|
|
89
100
|
return {
|
|
90
101
|
...restProperties,
|
|
91
102
|
accessibilityLabel: normalizedLabel,
|
|
92
103
|
accessibilityState: normalizedState,
|
|
93
|
-
accessible: normalizedAccessible
|
|
104
|
+
accessible: normalizedAccessible,
|
|
105
|
+
disabled: normalizedDisabled
|
|
94
106
|
};
|
|
95
107
|
}
|
|
96
108
|
|
|
97
109
|
exports.NativeText = NativeText;
|
|
98
110
|
exports.NativeView = NativeView;
|
|
111
|
+
exports.getDefaultTextAccessible = getDefaultTextAccessible;
|
|
99
112
|
exports.processAccessibilityProps = processAccessibilityProps;
|
|
100
113
|
exports.processTextStyle = processTextStyle;
|
|
101
114
|
exports.userSelectToSelectableMap = userSelectToSelectableMap;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/runtime/utils/constants.ts","../../src/runtime/components/native-text.tsx","../../src/runtime/components/native-view.tsx","../../src/runtime/index.ts"],"sourcesContent":["/**\n * Maps CSS-like `userSelect` values to React Native's `selectable` prop.\n */\nexport const userSelectToSelectableMap = {\n auto: true,\n text: true,\n none: false,\n contain: true,\n all: true,\n};\n\n/**\n * Maps CSS-like `verticalAlign` values to React Native's `textAlignVertical`.\n */\nexport const verticalAlignToTextAlignVerticalMap = {\n auto: 'auto',\n top: 'top',\n bottom: 'bottom',\n middle: 'center',\n};\n","/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n\nimport type { ComponentType } from 'react';\nimport type { TextProps } from 'react-native';\n\nconst reactNative = require('react-native');\nconst isWeb = reactNative.Platform.OS === 'web';\n\nlet nativeText = reactNative.unstable_NativeText;\n\nif (isWeb || nativeText == null) {\n // Fallback to regular Text component if unstable_NativeText is not available or we're on Web\n nativeText = reactNative.Text;\n}\n\n/**\n * Native Text component with graceful fallback.\n *\n * @remarks\n * Uses `unstable_NativeText` on supported native runtimes and falls back to `Text`\n * on web or when the unstable export is unavailable.\n */\nexport const NativeText: ComponentType<TextProps> = nativeText;\n","/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n\nimport type { ComponentType } from 'react';\nimport type { ViewProps } from 'react-native';\n\nconst reactNative = require('react-native');\nconst isWeb = reactNative.Platform.OS === 'web';\n\nlet nativeView = reactNative.unstable_NativeView;\n\nif (isWeb || nativeView == null) {\n // Fallback to regular View component if unstable_NativeView is not available or we're on Web\n nativeView = reactNative.View;\n}\n\n/**\n * Native View component with graceful fallback.\n *\n * @remarks\n * Uses `unstable_NativeView` on supported native runtimes and falls back to `View`\n * on web or when the unstable export is unavailable.\n */\nexport const NativeView: ComponentType<ViewProps> = nativeView;\n","import { TextProps, TextStyle, StyleSheet } from 'react-native';\nimport { GenericStyleProp } from './types';\nimport { userSelectToSelectableMap, verticalAlignToTextAlignVerticalMap } from './utils/constants';\n\nconst propsCache = new WeakMap();\n\n/**\n * Normalizes `Text` style values for `NativeText`.\n *\n * @param style - Style prop passed to a text-like component.\n * @returns Native-friendly text props. Returns an empty object when `style` is falsy or cannot be normalized.\n * @remarks\n * - Flattens style arrays via `StyleSheet.flatten`\n * - Converts numeric `fontWeight` values to string values\n * - Maps `userSelect` and `verticalAlign` to native-compatible props\n */\nexport function processTextStyle(style: GenericStyleProp<TextStyle>): Partial<TextProps> {\n if (!style) return {};\n\n // Cache the computed props\n let props = propsCache.get(style);\n if (props) return props;\n\n props = {};\n propsCache.set(style, props);\n\n style = StyleSheet.flatten(style) as TextStyle;\n\n if (!style) return {};\n\n if (typeof style?.fontWeight === 'number') {\n style.fontWeight = style.fontWeight.toString() as TextStyle['fontWeight'];\n }\n\n if (style?.userSelect != null) {\n props.selectable = userSelectToSelectableMap[style.userSelect];\n delete style.userSelect;\n }\n\n if (style?.verticalAlign != null) {\n style.textAlignVertical = verticalAlignToTextAlignVerticalMap[\n style.verticalAlign\n ] as TextStyle['textAlignVertical'];\n delete style.verticalAlign;\n }\n\n props.style = style;\n return props;\n}\n\n/**\n * Normalizes accessibility and ARIA props for runtime native components.\n *\n * @param props - Accessibility and ARIA props.\n * @returns Props with normalized accessibility fields.\n * @remarks\n * - Merges `aria-label` with `accessibilityLabel`\n * - Merges ARIA state fields into `accessibilityState`\n * - Defaults `accessible` to `true` when omitted\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function processAccessibilityProps(props: Record<string, any>): Record<string, any> {\n const {\n accessibilityLabel,\n ['aria-label']: ariaLabel,\n accessibilityState,\n ['aria-busy']: ariaBusy,\n ['aria-checked']: ariaChecked,\n ['aria-disabled']: ariaDisabled,\n ['aria-expanded']: ariaExpanded,\n ['aria-selected']: ariaSelected,\n accessible,\n ...restProperties\n } = props;\n\n // Merge label props: prefer the aria-label if defined.\n const normalizedLabel = ariaLabel ?? accessibilityLabel;\n\n // Merge the accessibilityState with any provided ARIA properties.\n let normalizedState = accessibilityState;\n if (ariaBusy != null || ariaChecked != null || ariaDisabled != null || ariaExpanded != null || ariaSelected != null) {\n normalizedState =\n normalizedState == null\n ? {\n busy: ariaBusy,\n checked: ariaChecked,\n disabled: ariaDisabled,\n expanded: ariaExpanded,\n selected: ariaSelected,\n }\n : {\n busy: ariaBusy ?? normalizedState.busy,\n checked: ariaChecked ?? normalizedState.checked,\n disabled: ariaDisabled ?? normalizedState.disabled,\n expanded: ariaExpanded ?? normalizedState.expanded,\n selected: ariaSelected ?? normalizedState.selected,\n };\n }\n\n // For the accessible prop, if not provided, default to `true`\n const normalizedAccessible = accessible == null ? true : accessible;\n\n return {\n ...restProperties,\n accessibilityLabel: normalizedLabel,\n accessibilityState: normalizedState,\n accessible: normalizedAccessible,\n };\n}\n\nexport * from './types';\nexport * from './utils/constants';\nexport * from './components/native-text';\nexport * from './components/native-view';\n"],"names":["reactNative","isWeb","StyleSheet"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/runtime/utils/constants.ts","../../src/runtime/components/native-text.tsx","../../src/runtime/components/native-view.tsx","../../src/runtime/index.ts"],"sourcesContent":["/**\n * Maps CSS-like `userSelect` values to React Native's `selectable` prop.\n */\nexport const userSelectToSelectableMap = {\n auto: true,\n text: true,\n none: false,\n contain: true,\n all: true,\n};\n\n/**\n * Maps CSS-like `verticalAlign` values to React Native's `textAlignVertical`.\n */\nexport const verticalAlignToTextAlignVerticalMap = {\n auto: 'auto',\n top: 'top',\n bottom: 'bottom',\n middle: 'center',\n};\n","/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n\nimport type { ComponentType } from 'react';\nimport type { TextProps } from 'react-native';\n\nconst reactNative = require('react-native');\nconst isWeb = reactNative.Platform.OS === 'web';\n\nlet nativeText = reactNative.unstable_NativeText;\n\nif (isWeb || nativeText == null) {\n // Fallback to regular Text component if unstable_NativeText is not available or we're on Web\n nativeText = reactNative.Text;\n}\n\n/**\n * Native Text component with graceful fallback.\n *\n * @remarks\n * Uses `unstable_NativeText` on supported native runtimes and falls back to `Text`\n * on web or when the unstable export is unavailable.\n */\nexport const NativeText: ComponentType<TextProps> = nativeText;\n","/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n\nimport type { ComponentType } from 'react';\nimport type { ViewProps } from 'react-native';\n\nconst reactNative = require('react-native');\nconst isWeb = reactNative.Platform.OS === 'web';\n\nlet nativeView = reactNative.unstable_NativeView;\n\nif (isWeb || nativeView == null) {\n // Fallback to regular View component if unstable_NativeView is not available or we're on Web\n nativeView = reactNative.View;\n}\n\n/**\n * Native View component with graceful fallback.\n *\n * @remarks\n * Uses `unstable_NativeView` on supported native runtimes and falls back to `View`\n * on web or when the unstable export is unavailable.\n */\nexport const NativeView: ComponentType<ViewProps> = nativeView;\n","import { TextProps, TextStyle, StyleSheet, Platform } from 'react-native';\nimport { GenericStyleProp } from './types';\nimport { userSelectToSelectableMap, verticalAlignToTextAlignVerticalMap } from './utils/constants';\n\nconst propsCache = new WeakMap();\n\n/**\n * Normalizes `Text` style values for `NativeText`.\n *\n * @param style - Style prop passed to a text-like component.\n * @returns Native-friendly text props. Returns an empty object when `style` is falsy or cannot be normalized.\n * @remarks\n * - Flattens style arrays via `StyleSheet.flatten`\n * - Converts numeric `fontWeight` values to string values\n * - Maps `userSelect` and `verticalAlign` to native-compatible props\n */\nexport function processTextStyle(style: GenericStyleProp<TextStyle>): Partial<TextProps> {\n if (!style) return {};\n\n // Cache the computed props\n let props = propsCache.get(style);\n if (props) return props;\n\n props = {};\n propsCache.set(style, props);\n\n style = StyleSheet.flatten(style) as TextStyle;\n\n if (!style) return {};\n\n if (typeof style?.fontWeight === 'number') {\n style.fontWeight = style.fontWeight.toString() as TextStyle['fontWeight'];\n }\n\n if (style?.userSelect != null) {\n props.selectable = userSelectToSelectableMap[style.userSelect];\n delete style.userSelect;\n }\n\n if (style?.verticalAlign != null) {\n style.textAlignVertical = verticalAlignToTextAlignVerticalMap[\n style.verticalAlign\n ] as TextStyle['textAlignVertical'];\n delete style.verticalAlign;\n }\n\n props.style = style;\n return props;\n}\n\n/**\n * The default value `Text` resolves for `accessible` when the prop is omitted: `true` on iOS (text is\n * an accessibility element unless opted out), `false` on Android, and `undefined` elsewhere.\n *\n * @remarks\n * Runtime fallback for the common optimized `<Text>` path (no accessibility props) when the target\n * platform is unknown at build time. When it is known (Metro reports it on the Babel caller), the\n * plugin inlines the literal instead and this is not emitted. Evaluated per render — like `Text`'s own\n * `Platform.select` — rather than hoisted to a constant, so it always reflects the current platform.\n */\nexport const getDefaultTextAccessible = (): boolean | undefined => Platform.select({ ios: true, android: false });\n\n/**\n * Normalizes accessibility and ARIA props for runtime native components, mirroring the reconciliation\n * `Text` performs before handing off to its native host.\n *\n * @param props - Accessibility and ARIA props.\n * @returns Props with normalized accessibility fields.\n * @remarks\n * - Merges `aria-label` with `accessibilityLabel`\n * - Merges ARIA state fields into `accessibilityState`\n * - Reconciles `disabled` with `accessibilityState.disabled` (the explicit `disabled` prop wins)\n * - Resolves the platform-specific `accessible` default (see {@link getDefaultTextAccessible})\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function processAccessibilityProps(props: Record<string, any>): Record<string, any> {\n const {\n accessibilityLabel,\n ['aria-label']: ariaLabel,\n accessibilityState,\n ['aria-busy']: ariaBusy,\n ['aria-checked']: ariaChecked,\n ['aria-disabled']: ariaDisabled,\n ['aria-expanded']: ariaExpanded,\n ['aria-selected']: ariaSelected,\n accessible,\n disabled,\n ...restProperties\n } = props;\n\n // Merge label props: prefer the aria-label if defined.\n const normalizedLabel = ariaLabel ?? accessibilityLabel;\n\n // Merge the accessibilityState with any provided ARIA properties.\n let normalizedState = accessibilityState;\n if (ariaBusy != null || ariaChecked != null || ariaDisabled != null || ariaExpanded != null || ariaSelected != null) {\n normalizedState =\n normalizedState == null\n ? {\n busy: ariaBusy,\n checked: ariaChecked,\n disabled: ariaDisabled,\n expanded: ariaExpanded,\n selected: ariaSelected,\n }\n : {\n busy: ariaBusy ?? normalizedState.busy,\n checked: ariaChecked ?? normalizedState.checked,\n disabled: ariaDisabled ?? normalizedState.disabled,\n expanded: ariaExpanded ?? normalizedState.expanded,\n selected: ariaSelected ?? normalizedState.selected,\n };\n }\n\n // Reconcile `disabled` with `accessibilityState.disabled`. When the two are out of sync (and not\n // both falsy) the explicit `disabled` prop wins and is mirrored back into the state object, so the\n // native host receives a consistent value on both fields.\n const stateDisabled = normalizedState?.disabled;\n const normalizedDisabled = disabled ?? stateDisabled;\n if (\n normalizedDisabled !== stateDisabled &&\n ((normalizedDisabled != null && normalizedDisabled !== false) || (stateDisabled != null && stateDisabled !== false))\n ) {\n normalizedState = { ...normalizedState, disabled: normalizedDisabled };\n }\n\n // Resolve `accessible` exactly as `Text` does: opt-out on iOS, off by default on Android. The\n // Android pressable case (`onPress`/`onLongPress`) never applies — press handlers bail out of\n // optimization — so an omitted prop falls back to the platform default.\n const normalizedAccessible = Platform.select({\n ios: accessible !== false,\n android: accessible ?? false,\n default: accessible,\n });\n\n return {\n ...restProperties,\n accessibilityLabel: normalizedLabel,\n accessibilityState: normalizedState,\n accessible: normalizedAccessible,\n disabled: normalizedDisabled,\n };\n}\n\nexport * from './types';\nexport * from './utils/constants';\nexport * from './components/native-text';\nexport * from './components/native-view';\n"],"names":["reactNative","isWeb","StyleSheet","Platform"],"mappings":"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"}
|
|
@@ -28,10 +28,11 @@ declare const verticalAlignToTextAlignVerticalMap: {
|
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
declare const processTextStyle: (style: GenericStyleProp<TextStyle>) => Partial<TextProps>;
|
|
31
|
+
declare const getDefaultTextAccessible: () => boolean | undefined;
|
|
31
32
|
declare function processAccessibilityProps(props: Record<string, any>): Record<string, any>;
|
|
32
33
|
|
|
33
34
|
declare const NativeText: any;
|
|
34
35
|
declare const NativeView: any;
|
|
35
36
|
|
|
36
|
-
export { NativeText, NativeView, processAccessibilityProps, processTextStyle, userSelectToSelectableMap, verticalAlignToTextAlignVerticalMap };
|
|
37
|
+
export { NativeText, NativeView, getDefaultTextAccessible, processAccessibilityProps, processTextStyle, userSelectToSelectableMap, verticalAlignToTextAlignVerticalMap };
|
|
37
38
|
export type { GenericStyleProp };
|
|
@@ -15,6 +15,7 @@ const verticalAlignToTextAlignVerticalMap = {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const processTextStyle = (style) => ({ style });
|
|
18
|
+
const getDefaultTextAccessible = () => void 0;
|
|
18
19
|
function processAccessibilityProps(props) {
|
|
19
20
|
return props;
|
|
20
21
|
}
|
|
@@ -23,6 +24,7 @@ const NativeView = require("react-native").View;
|
|
|
23
24
|
|
|
24
25
|
exports.NativeText = NativeText;
|
|
25
26
|
exports.NativeView = NativeView;
|
|
27
|
+
exports.getDefaultTextAccessible = getDefaultTextAccessible;
|
|
26
28
|
exports.processAccessibilityProps = processAccessibilityProps;
|
|
27
29
|
exports.processTextStyle = processTextStyle;
|
|
28
30
|
exports.userSelectToSelectableMap = userSelectToSelectableMap;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.web.js","sources":["../../src/runtime/utils/constants.ts","../../src/runtime/index.web.ts"],"sourcesContent":["/**\n * Maps CSS-like `userSelect` values to React Native's `selectable` prop.\n */\nexport const userSelectToSelectableMap = {\n auto: true,\n text: true,\n none: false,\n contain: true,\n all: true,\n};\n\n/**\n * Maps CSS-like `verticalAlign` values to React Native's `textAlignVertical`.\n */\nexport const verticalAlignToTextAlignVerticalMap = {\n auto: 'auto',\n top: 'top',\n bottom: 'bottom',\n middle: 'center',\n};\n","// This is a dummy file to ensure that nothing breaks when using the runtime in a web environment.\n\nimport { TextProps, TextStyle } from 'react-native';\nimport { GenericStyleProp } from './types';\n\nexport const processTextStyle = (style: GenericStyleProp<TextStyle>) => ({ style }) as Partial<TextProps>;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function processAccessibilityProps(props: Record<string, any>): Record<string, any> {\n return props;\n}\n\nexport * from './types';\nexport * from './utils/constants';\n\n// On Web, the native components are not available, so we use the standard components that'll be replaced by their DOM\n// equivalents by react-native-web.\n/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\nexport const NativeText = require('react-native').Text;\nexport const NativeView = require('react-native').View;\n/* eslint-enable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n"],"names":[],"mappings":";;AAGO,MAAM,yBAAA,GAA4B;AAAA,EACvC,IAAA,EAAM,IAAA;AAAA,EACN,IAAA,EAAM,IAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,OAAA,EAAS,IAAA;AAAA,EACT,GAAA,EAAK;AACP;AAKO,MAAM,mCAAA,GAAsC;AAAA,EACjD,IAAA,EAAM,MAAA;AAAA,EACN,GAAA,EAAK,KAAA;AAAA,EACL,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ;AACV;;ACdO,MAAM,gBAAA,GAAmB,CAAC,KAAA,MAAwC,EAAE,KAAA,EAAM;
|
|
1
|
+
{"version":3,"file":"index.web.js","sources":["../../src/runtime/utils/constants.ts","../../src/runtime/index.web.ts"],"sourcesContent":["/**\n * Maps CSS-like `userSelect` values to React Native's `selectable` prop.\n */\nexport const userSelectToSelectableMap = {\n auto: true,\n text: true,\n none: false,\n contain: true,\n all: true,\n};\n\n/**\n * Maps CSS-like `verticalAlign` values to React Native's `textAlignVertical`.\n */\nexport const verticalAlignToTextAlignVerticalMap = {\n auto: 'auto',\n top: 'top',\n bottom: 'bottom',\n middle: 'center',\n};\n","// This is a dummy file to ensure that nothing breaks when using the runtime in a web environment.\n\nimport { TextProps, TextStyle } from 'react-native';\nimport { GenericStyleProp } from './types';\n\nexport const processTextStyle = (style: GenericStyleProp<TextStyle>) => ({ style }) as Partial<TextProps>;\n\n// On Web there is no platform-specific `accessible` default to apply; react-native-web's `Text`\n// derives accessibility from the rendered DOM. Returning `undefined` makes the injected\n// `accessible={getDefaultTextAccessible()}` a no-op.\nexport const getDefaultTextAccessible = (): boolean | undefined => undefined;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function processAccessibilityProps(props: Record<string, any>): Record<string, any> {\n return props;\n}\n\nexport * from './types';\nexport * from './utils/constants';\n\n// On Web, the native components are not available, so we use the standard components that'll be replaced by their DOM\n// equivalents by react-native-web.\n/* eslint-disable @typescript-eslint/no-require-imports,unicorn/prefer-module */\nexport const NativeText = require('react-native').Text;\nexport const NativeView = require('react-native').View;\n/* eslint-enable @typescript-eslint/no-require-imports,unicorn/prefer-module */\n"],"names":[],"mappings":";;AAGO,MAAM,yBAAA,GAA4B;AAAA,EACvC,IAAA,EAAM,IAAA;AAAA,EACN,IAAA,EAAM,IAAA;AAAA,EACN,IAAA,EAAM,KAAA;AAAA,EACN,OAAA,EAAS,IAAA;AAAA,EACT,GAAA,EAAK;AACP;AAKO,MAAM,mCAAA,GAAsC;AAAA,EACjD,IAAA,EAAM,MAAA;AAAA,EACN,GAAA,EAAK,KAAA;AAAA,EACL,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ;AACV;;ACdO,MAAM,gBAAA,GAAmB,CAAC,KAAA,MAAwC,EAAE,KAAA,EAAM;AAK1E,MAAM,2BAA2B,MAA2B;AAG5D,SAAS,0BAA0B,KAAA,EAAiD;AACzF,EAAA,OAAO,KAAA;AACT;AAQO,MAAM,UAAA,GAAa,OAAA,CAAQ,cAAc,CAAA,CAAE;AAC3C,MAAM,UAAA,GAAa,OAAA,CAAQ,cAAc,CAAA,CAAE;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-boost",
|
|
3
3
|
"description": "🚀 Boost your React Native app's performance with a single line of code",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/esm/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -88,7 +88,9 @@
|
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"@babel/plugin-syntax-jsx": "^7.25.0",
|
|
91
|
+
"@babel/preset-react": "^7.25.0",
|
|
91
92
|
"@babel/preset-typescript": "^7.25.0",
|
|
93
|
+
"@react-native/babel-preset": "0.83.2",
|
|
92
94
|
"@release-it/conventional-changelog": "^10.0.0",
|
|
93
95
|
"@rollup/plugin-alias": "^6.0.0",
|
|
94
96
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
@@ -99,6 +101,8 @@
|
|
|
99
101
|
"@types/node": "^24",
|
|
100
102
|
"babel-plugin-tester": "^12.0.0",
|
|
101
103
|
"esbuild-node-externals": "^1.18.0",
|
|
104
|
+
"react": "19.2.0",
|
|
105
|
+
"react-dom": "19.2.0",
|
|
102
106
|
"react-native": "0.83.2",
|
|
103
107
|
"release-it": "^19.2.4",
|
|
104
108
|
"rollup": "^4.34.8",
|
|
@@ -118,6 +122,7 @@
|
|
|
118
122
|
},
|
|
119
123
|
"npm": {
|
|
120
124
|
"publish": true,
|
|
125
|
+
"skipChecks": true,
|
|
121
126
|
"versionArgs": [
|
|
122
127
|
"--workspaces-update=false"
|
|
123
128
|
]
|
package/src/plugin/index.ts
CHANGED
|
@@ -15,6 +15,10 @@ type PluginState = {
|
|
|
15
15
|
export default declare((api) => {
|
|
16
16
|
api.assertVersion(7);
|
|
17
17
|
|
|
18
|
+
// Target platform, resolved at build time. Metro sets this on the Babel caller per platform bundle,
|
|
19
|
+
// letting optimizers inline platform-specific defaults instead of deferring them to the runtime.
|
|
20
|
+
const platform = api.caller((caller) => (caller as { platform?: string } | undefined)?.platform);
|
|
21
|
+
|
|
18
22
|
return {
|
|
19
23
|
name: 'react-native-boost',
|
|
20
24
|
visitor: {
|
|
@@ -24,7 +28,7 @@ export default declare((api) => {
|
|
|
24
28
|
const logger = getOrCreateLogger(pluginState, options);
|
|
25
29
|
|
|
26
30
|
if (isIgnoredFile(path, options.ignores ?? [])) return;
|
|
27
|
-
if (options.optimizations?.text !== false) textOptimizer(path, logger);
|
|
31
|
+
if (options.optimizations?.text !== false) textOptimizer(path, logger, options, platform);
|
|
28
32
|
if (options.optimizations?.view !== false) viewOptimizer(path, logger, options);
|
|
29
33
|
},
|
|
30
34
|
},
|
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
import { NodePath, types as t } from '@babel/core';
|
|
2
2
|
import { HubFile, Optimizer, PluginLogger } from '../../types';
|
|
3
3
|
import PluginError from '../../utils/plugin-error';
|
|
4
|
-
import { getFirstBailoutReason } from '../../utils/helpers';
|
|
4
|
+
import { BailoutCheck, getFirstBailoutReason } from '../../utils/helpers';
|
|
5
5
|
import {
|
|
6
6
|
addDefaultProperty,
|
|
7
7
|
addFileImportHint,
|
|
8
8
|
buildPropertiesFromAttributes,
|
|
9
9
|
hasAccessibilityProperty,
|
|
10
10
|
hasBlacklistedProperty,
|
|
11
|
+
isForcedLine,
|
|
11
12
|
isIgnoredLine,
|
|
12
13
|
isValidJSXComponent,
|
|
13
14
|
isReactNativeImport,
|
|
14
15
|
replaceWithNativeComponent,
|
|
15
|
-
|
|
16
|
+
isPrimitiveChild,
|
|
16
17
|
hasExpoRouterLinkParentWithAsChild,
|
|
18
|
+
extractStyleAttribute,
|
|
19
|
+
extractSelectableAndUpdateStyle,
|
|
20
|
+
ancestorBailoutChecks,
|
|
17
21
|
} from '../../utils/common';
|
|
18
|
-
import { RUNTIME_MODULE_NAME } from '../../utils/constants';
|
|
19
|
-
import { ACCESSIBILITY_PROPERTIES } from '../../utils/constants';
|
|
20
|
-
import { extractStyleAttribute, extractSelectableAndUpdateStyle } from '../../utils/common';
|
|
22
|
+
import { ACCESSIBILITY_PROPERTIES, RUNTIME_MODULE_NAME } from '../../utils/constants';
|
|
21
23
|
|
|
22
24
|
export const textBlacklistedProperties = new Set([
|
|
25
|
+
// The `Text` wrapper translates `aria-hidden` into `accessibilityElementsHidden` /
|
|
26
|
+
// `importantForAccessibility`, which `processAccessibilityProps` does not yet handle. Passing it
|
|
27
|
+
// through would drop it, so bail. TODO: handle this in the runtime helper instead.
|
|
28
|
+
'aria-hidden',
|
|
23
29
|
'id',
|
|
24
30
|
'nativeID',
|
|
25
31
|
'onLongPress',
|
|
@@ -37,21 +43,27 @@ export const textBlacklistedProperties = new Set([
|
|
|
37
43
|
'selectionColor', // TODO: we can use react-native's internal `processColor` to process this at runtime
|
|
38
44
|
]);
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Props handed off to `processAccessibilityProps` at runtime: the accessibility props plus `disabled`,
|
|
48
|
+
* which `Text` reconciles against `accessibilityState.disabled`. They are collected into a single
|
|
49
|
+
* helper call and stripped from the element so they are not also emitted verbatim.
|
|
50
|
+
*/
|
|
51
|
+
const NORMALIZED_PROPERTIES = new Set([...ACCESSIBILITY_PROPERTIES, 'disabled']);
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Type guard for a direct JSX attribute whose name is in {@link NORMALIZED_PROPERTIES}.
|
|
55
|
+
*/
|
|
56
|
+
const isNormalizedProperty = (attribute: t.JSXAttribute | t.JSXSpreadAttribute): attribute is t.JSXAttribute =>
|
|
57
|
+
t.isJSXAttribute(attribute) && t.isJSXIdentifier(attribute.name) && NORMALIZED_PROPERTIES.has(attribute.name.name);
|
|
58
|
+
|
|
59
|
+
export const textOptimizer: Optimizer = (path, logger, options, platform) => {
|
|
41
60
|
if (!isValidJSXComponent(path, 'Text')) return;
|
|
61
|
+
if (!isReactNativeImport(path, 'Text')) return;
|
|
42
62
|
|
|
43
|
-
// Verify that the Text only has string children
|
|
44
63
|
const parent = path.parent as t.JSXElement;
|
|
64
|
+
const forced = isForcedLine(path);
|
|
45
65
|
|
|
46
|
-
const
|
|
47
|
-
{
|
|
48
|
-
reason: 'line is marked with @boost-ignore',
|
|
49
|
-
shouldBail: () => isIgnoredLine(path),
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
reason: 'Text is not imported from react-native',
|
|
53
|
-
shouldBail: () => !isReactNativeImport(path, 'Text'),
|
|
54
|
-
},
|
|
66
|
+
const overridableChecks: BailoutCheck[] = [
|
|
55
67
|
{
|
|
56
68
|
reason: 'contains blacklisted props',
|
|
57
69
|
shouldBail: () => hasBlacklistedProperty(path, textBlacklistedProperties),
|
|
@@ -60,19 +72,34 @@ export const textOptimizer: Optimizer = (path, logger) => {
|
|
|
60
72
|
reason: 'is a direct child of expo-router Link with asChild',
|
|
61
73
|
shouldBail: () => hasExpoRouterLinkParentWithAsChild(path),
|
|
62
74
|
},
|
|
75
|
+
// The local children check runs before the ancestor checks because it is cheap and prunes the
|
|
76
|
+
// common nested-element `Text` before the unbounded ancestor walk those checks trigger.
|
|
63
77
|
{
|
|
64
|
-
reason: 'contains non-
|
|
78
|
+
reason: 'contains non-primitive children',
|
|
65
79
|
shouldBail: () => hasInvalidChildren(path, parent),
|
|
66
80
|
},
|
|
67
|
-
|
|
81
|
+
...ancestorBailoutChecks(path, options?.dangerouslyOptimizeTextWithUnknownAncestors === true),
|
|
82
|
+
];
|
|
68
83
|
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
reason:
|
|
74
|
-
}
|
|
75
|
-
|
|
84
|
+
if (forced) {
|
|
85
|
+
const overriddenReason = getFirstBailoutReason(overridableChecks);
|
|
86
|
+
|
|
87
|
+
if (overriddenReason) {
|
|
88
|
+
logger.forced({ component: 'Text', path, reason: overriddenReason });
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
const skipReason = getFirstBailoutReason([
|
|
92
|
+
{
|
|
93
|
+
reason: 'line is marked with @boost-ignore',
|
|
94
|
+
shouldBail: () => isIgnoredLine(path),
|
|
95
|
+
},
|
|
96
|
+
...overridableChecks,
|
|
97
|
+
]);
|
|
98
|
+
|
|
99
|
+
if (skipReason) {
|
|
100
|
+
logger.skipped({ component: 'Text', path, reason: skipReason });
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
76
103
|
}
|
|
77
104
|
|
|
78
105
|
const hub = path.hub as unknown;
|
|
@@ -91,7 +118,7 @@ export const textOptimizer: Optimizer = (path, logger) => {
|
|
|
91
118
|
fixNegativeNumberOfLines({ path, logger });
|
|
92
119
|
addDefaultProperty(path, 'allowFontScaling', t.booleanLiteral(true));
|
|
93
120
|
addDefaultProperty(path, 'ellipsizeMode', t.stringLiteral('tail'));
|
|
94
|
-
processProps(path, file);
|
|
121
|
+
processProps(path, file, platform);
|
|
95
122
|
|
|
96
123
|
// Replace the Text component with NativeText
|
|
97
124
|
replaceWithNativeComponent(path, parent, file, 'NativeText');
|
|
@@ -112,16 +139,16 @@ function hasInvalidChildren(path: NodePath<t.JSXOpeningElement>, parent: t.JSXEl
|
|
|
112
139
|
if (
|
|
113
140
|
t.isJSXIdentifier(attribute.name) &&
|
|
114
141
|
attribute.value &&
|
|
115
|
-
// For a "children" attribute, optimization is allowed only if it is a
|
|
142
|
+
// For a "children" attribute, optimization is allowed only if it is a provable primitive
|
|
116
143
|
attribute.name.name === 'children' &&
|
|
117
|
-
!
|
|
144
|
+
!isPrimitiveChild(path, attribute.value)
|
|
118
145
|
) {
|
|
119
146
|
return true;
|
|
120
147
|
}
|
|
121
148
|
}
|
|
122
149
|
|
|
123
|
-
// Return true if any child is not a
|
|
124
|
-
return !parent.children.every((child) =>
|
|
150
|
+
// Return true if any child is not a provably-primitive node
|
|
151
|
+
return !parent.children.every((child) => isPrimitiveChild(path, child));
|
|
125
152
|
}
|
|
126
153
|
|
|
127
154
|
/**
|
|
@@ -160,25 +187,31 @@ function fixNegativeNumberOfLines({ path, logger }: { path: NodePath<t.JSXOpenin
|
|
|
160
187
|
/**
|
|
161
188
|
* Processes style and accessibility attributes, replacing them with optimized versions.
|
|
162
189
|
*/
|
|
163
|
-
function processProps(path: NodePath<t.JSXOpeningElement>, file: HubFile) {
|
|
190
|
+
function processProps(path: NodePath<t.JSXOpeningElement>, file: HubFile, platform?: string) {
|
|
164
191
|
// Grab the up-to-date list of attributes
|
|
165
192
|
const currentAttributes = [...path.node.attributes];
|
|
166
193
|
|
|
167
194
|
const { styleExpr, styleAttribute } = extractStyleAttribute(currentAttributes);
|
|
168
|
-
|
|
195
|
+
|
|
196
|
+
// `Text` always resolves a platform-specific `accessible` default and reconciles `disabled` with
|
|
197
|
+
// `accessibilityState.disabled`. When any accessibility prop or `disabled` is present we hand the
|
|
198
|
+
// element off to `processAccessibilityProps` (which also performs the aria/label merges); otherwise
|
|
199
|
+
// only the `accessible` default is needed, so we inject it directly to keep the common path cheap.
|
|
200
|
+
const shouldNormalize =
|
|
201
|
+
hasAccessibilityProperty(path, currentAttributes) ||
|
|
202
|
+
currentAttributes.some(
|
|
203
|
+
(attribute) => t.isJSXAttribute(attribute) && t.isJSXIdentifier(attribute.name, { name: 'disabled' })
|
|
204
|
+
);
|
|
169
205
|
|
|
170
206
|
// ============================================
|
|
171
|
-
// 1. Prepare spread attributes (
|
|
207
|
+
// 1. Prepare spread attributes (a11y / style)
|
|
172
208
|
// ============================================
|
|
173
209
|
|
|
174
210
|
const spreadAttributes: t.JSXSpreadAttribute[] = [];
|
|
175
211
|
|
|
176
|
-
// --- Accessibility ---
|
|
177
|
-
if (
|
|
178
|
-
const
|
|
179
|
-
if (!t.isJSXAttribute(attribute)) return false;
|
|
180
|
-
return t.isJSXIdentifier(attribute.name) && ACCESSIBILITY_PROPERTIES.has(attribute.name.name as string);
|
|
181
|
-
});
|
|
212
|
+
// --- Accessibility & `disabled` ---
|
|
213
|
+
if (shouldNormalize) {
|
|
214
|
+
const normalizedAttributes = currentAttributes.filter((attribute) => isNormalizedProperty(attribute));
|
|
182
215
|
|
|
183
216
|
const normalizeIdentifier = addFileImportHint({
|
|
184
217
|
file,
|
|
@@ -188,7 +221,7 @@ function processProps(path: NodePath<t.JSXOpeningElement>, file: HubFile) {
|
|
|
188
221
|
moduleName: RUNTIME_MODULE_NAME,
|
|
189
222
|
});
|
|
190
223
|
|
|
191
|
-
const accessibilityObject = buildPropertiesFromAttributes(
|
|
224
|
+
const accessibilityObject = buildPropertiesFromAttributes(normalizedAttributes);
|
|
192
225
|
const accessibilityExpr = t.callExpression(t.identifier(normalizeIdentifier.name), [accessibilityObject]);
|
|
193
226
|
spreadAttributes.push(t.jsxSpreadAttribute(accessibilityExpr));
|
|
194
227
|
}
|
|
@@ -226,20 +259,55 @@ function processProps(path: NodePath<t.JSXOpeningElement>, file: HubFile) {
|
|
|
226
259
|
// Skip the style attribute (we have replaced it with a spread)
|
|
227
260
|
if (styleAttribute && attribute === styleAttribute) continue;
|
|
228
261
|
|
|
229
|
-
// Skip
|
|
230
|
-
if (
|
|
231
|
-
hasA11y &&
|
|
232
|
-
t.isJSXAttribute(attribute) &&
|
|
233
|
-
t.isJSXIdentifier(attribute.name) &&
|
|
234
|
-
ACCESSIBILITY_PROPERTIES.has(attribute.name.name as string)
|
|
235
|
-
) {
|
|
236
|
-
continue;
|
|
237
|
-
}
|
|
262
|
+
// Skip the props we routed through `processAccessibilityProps`
|
|
263
|
+
if (shouldNormalize && isNormalizedProperty(attribute)) continue;
|
|
238
264
|
|
|
239
265
|
remainingAttributes.push(attribute);
|
|
240
266
|
}
|
|
241
267
|
|
|
242
|
-
|
|
268
|
+
// ============================================
|
|
269
|
+
// 3. `accessible` default for the common path
|
|
270
|
+
// ============================================
|
|
271
|
+
// With no accessibility/`disabled` prop the helper is skipped, but `Text` still applies a
|
|
272
|
+
// platform-specific `accessible` default. We build it explicitly (rather than via `addDefaultProperty`,
|
|
273
|
+
// which gives up when it hits the unresolvable `{...processTextStyle(...)}` spread and would silently
|
|
274
|
+
// drop the default on styled text). The cheap path guarantees no `accessible` is already set — any
|
|
275
|
+
// such prop would have set `shouldNormalize`, and unresolvable spreads bail before this point — so
|
|
276
|
+
// appending it unconditionally is safe.
|
|
277
|
+
const accessibleAttribute = shouldNormalize ? undefined : buildAccessibleDefault(path, file, platform);
|
|
278
|
+
|
|
279
|
+
path.node.attributes = [...spreadAttributes, selectableAttribute, ...remainingAttributes, accessibleAttribute].filter(
|
|
243
280
|
(attribute): attribute is t.JSXAttribute | t.JSXSpreadAttribute => attribute !== undefined
|
|
244
281
|
);
|
|
245
282
|
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Builds the `accessible` default attribute `Text` applies when the prop is omitted: `true` on iOS,
|
|
286
|
+
* `false` on Android, omitted on web. Metro bundles per platform and reports the target on the Babel
|
|
287
|
+
* caller, so a known platform is inlined as a literal; an unknown platform (non-Metro bundlers,
|
|
288
|
+
* fixture tests) defers to the lightweight runtime resolver. Returns `undefined` when nothing should
|
|
289
|
+
* be emitted.
|
|
290
|
+
*/
|
|
291
|
+
function buildAccessibleDefault(
|
|
292
|
+
path: NodePath<t.JSXOpeningElement>,
|
|
293
|
+
file: HubFile,
|
|
294
|
+
platform?: string
|
|
295
|
+
): t.JSXAttribute | undefined {
|
|
296
|
+
if (platform === 'web') return undefined;
|
|
297
|
+
|
|
298
|
+
let value: t.Expression;
|
|
299
|
+
if (platform === 'ios' || platform === 'android') {
|
|
300
|
+
value = t.booleanLiteral(platform === 'ios');
|
|
301
|
+
} else {
|
|
302
|
+
const accessibleIdentifier = addFileImportHint({
|
|
303
|
+
file,
|
|
304
|
+
nameHint: 'getDefaultTextAccessible',
|
|
305
|
+
path,
|
|
306
|
+
importName: 'getDefaultTextAccessible',
|
|
307
|
+
moduleName: RUNTIME_MODULE_NAME,
|
|
308
|
+
});
|
|
309
|
+
value = t.callExpression(t.identifier(accessibleIdentifier.name), []);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return t.jsxAttribute(t.jsxIdentifier('accessible'), t.jsxExpressionContainer(value));
|
|
313
|
+
}
|