rnwind 0.0.11 → 0.0.12

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.
Files changed (96) hide show
  1. package/lib/cjs/core/normalize-classname.cjs +3 -1
  2. package/lib/cjs/core/normalize-classname.cjs.map +1 -1
  3. package/lib/cjs/core/parser/border-dispatcher.cjs +20 -10
  4. package/lib/cjs/core/parser/border-dispatcher.cjs.map +1 -1
  5. package/lib/cjs/core/parser/color-properties-dispatcher.cjs +7 -5
  6. package/lib/cjs/core/parser/color-properties-dispatcher.cjs.map +1 -1
  7. package/lib/cjs/core/parser/color.cjs +194 -10
  8. package/lib/cjs/core/parser/color.cjs.map +1 -1
  9. package/lib/cjs/core/parser/color.d.ts +18 -3
  10. package/lib/cjs/core/parser/declaration.cjs +62 -4
  11. package/lib/cjs/core/parser/declaration.cjs.map +1 -1
  12. package/lib/cjs/core/parser/layout-dispatcher.cjs +32 -2
  13. package/lib/cjs/core/parser/layout-dispatcher.cjs.map +1 -1
  14. package/lib/cjs/core/parser/shorthand.cjs +10 -3
  15. package/lib/cjs/core/parser/shorthand.cjs.map +1 -1
  16. package/lib/cjs/core/parser/tokens.cjs +9 -0
  17. package/lib/cjs/core/parser/tokens.cjs.map +1 -1
  18. package/lib/cjs/core/parser/tw-parser.cjs +6 -0
  19. package/lib/cjs/core/parser/tw-parser.cjs.map +1 -1
  20. package/lib/cjs/core/parser/typography-dispatcher.cjs +15 -8
  21. package/lib/cjs/core/parser/typography-dispatcher.cjs.map +1 -1
  22. package/lib/cjs/core/style-builder/union-builder.cjs +81 -2
  23. package/lib/cjs/core/style-builder/union-builder.cjs.map +1 -1
  24. package/lib/cjs/core/style-builder/union-builder.d.ts +28 -0
  25. package/lib/cjs/metro/state.cjs +74 -13
  26. package/lib/cjs/metro/state.cjs.map +1 -1
  27. package/lib/cjs/metro/state.d.ts +18 -0
  28. package/lib/cjs/metro/transformer.cjs +10 -4
  29. package/lib/cjs/metro/transformer.cjs.map +1 -1
  30. package/lib/cjs/metro/with-config.cjs +57 -0
  31. package/lib/cjs/metro/with-config.cjs.map +1 -1
  32. package/lib/cjs/metro/with-config.d.ts +12 -0
  33. package/lib/cjs/metro/wrap-imports.cjs +36 -1
  34. package/lib/cjs/metro/wrap-imports.cjs.map +1 -1
  35. package/lib/cjs/runtime/hooks/use-scheme.cjs +14 -7
  36. package/lib/cjs/runtime/hooks/use-scheme.cjs.map +1 -1
  37. package/lib/cjs/runtime/resolve.cjs +6 -2
  38. package/lib/cjs/runtime/resolve.cjs.map +1 -1
  39. package/lib/cjs/runtime/resolve.d.ts +5 -1
  40. package/lib/esm/core/normalize-classname.mjs +3 -1
  41. package/lib/esm/core/normalize-classname.mjs.map +1 -1
  42. package/lib/esm/core/parser/border-dispatcher.mjs +21 -11
  43. package/lib/esm/core/parser/border-dispatcher.mjs.map +1 -1
  44. package/lib/esm/core/parser/color-properties-dispatcher.mjs +8 -6
  45. package/lib/esm/core/parser/color-properties-dispatcher.mjs.map +1 -1
  46. package/lib/esm/core/parser/color.d.ts +18 -3
  47. package/lib/esm/core/parser/color.mjs +195 -12
  48. package/lib/esm/core/parser/color.mjs.map +1 -1
  49. package/lib/esm/core/parser/declaration.mjs +63 -5
  50. package/lib/esm/core/parser/declaration.mjs.map +1 -1
  51. package/lib/esm/core/parser/layout-dispatcher.mjs +32 -2
  52. package/lib/esm/core/parser/layout-dispatcher.mjs.map +1 -1
  53. package/lib/esm/core/parser/shorthand.mjs +11 -4
  54. package/lib/esm/core/parser/shorthand.mjs.map +1 -1
  55. package/lib/esm/core/parser/tokens.mjs +10 -1
  56. package/lib/esm/core/parser/tokens.mjs.map +1 -1
  57. package/lib/esm/core/parser/tw-parser.mjs +6 -0
  58. package/lib/esm/core/parser/tw-parser.mjs.map +1 -1
  59. package/lib/esm/core/parser/typography-dispatcher.mjs +15 -8
  60. package/lib/esm/core/parser/typography-dispatcher.mjs.map +1 -1
  61. package/lib/esm/core/style-builder/union-builder.d.ts +28 -0
  62. package/lib/esm/core/style-builder/union-builder.mjs +82 -3
  63. package/lib/esm/core/style-builder/union-builder.mjs.map +1 -1
  64. package/lib/esm/metro/state.d.ts +18 -0
  65. package/lib/esm/metro/state.mjs +75 -14
  66. package/lib/esm/metro/state.mjs.map +1 -1
  67. package/lib/esm/metro/transformer.mjs +10 -4
  68. package/lib/esm/metro/transformer.mjs.map +1 -1
  69. package/lib/esm/metro/with-config.d.ts +12 -0
  70. package/lib/esm/metro/with-config.mjs +58 -2
  71. package/lib/esm/metro/with-config.mjs.map +1 -1
  72. package/lib/esm/metro/wrap-imports.mjs +36 -1
  73. package/lib/esm/metro/wrap-imports.mjs.map +1 -1
  74. package/lib/esm/runtime/hooks/use-scheme.mjs +14 -7
  75. package/lib/esm/runtime/hooks/use-scheme.mjs.map +1 -1
  76. package/lib/esm/runtime/resolve.d.ts +5 -1
  77. package/lib/esm/runtime/resolve.mjs +6 -2
  78. package/lib/esm/runtime/resolve.mjs.map +1 -1
  79. package/package.json +1 -1
  80. package/src/core/normalize-classname.ts +4 -1
  81. package/src/core/parser/border-dispatcher.ts +22 -11
  82. package/src/core/parser/color-properties-dispatcher.ts +7 -5
  83. package/src/core/parser/color.ts +182 -11
  84. package/src/core/parser/declaration.ts +61 -5
  85. package/src/core/parser/layout-dispatcher.ts +34 -2
  86. package/src/core/parser/shorthand.ts +9 -3
  87. package/src/core/parser/tokens.ts +10 -1
  88. package/src/core/parser/tw-parser.ts +5 -0
  89. package/src/core/parser/typography-dispatcher.ts +15 -6
  90. package/src/core/style-builder/union-builder.ts +83 -3
  91. package/src/metro/state.ts +117 -12
  92. package/src/metro/transformer.ts +9 -4
  93. package/src/metro/with-config.ts +59 -1
  94. package/src/metro/wrap-imports.ts +36 -1
  95. package/src/runtime/hooks/use-scheme.ts +13 -6
  96. package/src/runtime/resolve.ts +6 -2
@@ -1 +1 @@
1
- {"version":3,"file":"wrap-imports.mjs","sources":["../../../../src/metro/wrap-imports.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport type { File } from '@babel/types'\n\n/**\n * Build-time import rewrite. For every `import { View } from\n * 'react-native'` (and the other configured modules) it aliases the\n * original export and binds a `wrap()`-ed component in its place:\n *\n * ```\n * import { View, StyleSheet } from 'react-native'\n * ⇩\n * import { View as _rnw0, StyleSheet } from 'react-native'\n * import { wrap as _rnwWrap } from 'rnwind'\n * const View = _rnwWrap(_rnw0)\n * ```\n *\n * Now `<View className=\"…\">` resolves className → style at render via the\n * wrapper — no matter how className arrived (literal, `{...rest}` spread,\n * forwarded through custom layers). Non-component exports (`StyleSheet`)\n * are left untouched.\n */\n\n/** Local binding the injected `wrap` import is aliased to. */\nconst WRAP_LOCAL = '_rnwWrap'\n/** Local binding the injected `wrapNamespace` import is aliased to. */\nconst WRAP_NS_LOCAL = '_rnwWrapNs'\n/** Module the wrapper is imported from. */\nconst RUNTIME_MODULE = 'rnwind'\n\n/**\n * Wrap-modules whose DEFAULT export is a component NAMESPACE accessed via\n * member expressions (`Animated.View`), not a single component. Their\n * default import is bound through `wrapNamespace` (a Proxy that wraps each\n * accessed component member) instead of `wrap`. Every other default import\n * is treated as a plain component.\n */\nconst NAMESPACE_DEFAULT_MODULES: ReadonlySet<string> = new Set(['react-native-reanimated'])\n\n/**\n * react-native mixes styleable components with utilities (`StyleSheet`,\n * `Platform`, …). Only these named exports are wrapped; everything else\n * passes through. Other ecosystem modules export components only and use\n * the `'all'` policy instead.\n */\nconst REACT_NATIVE_COMPONENTS: ReadonlySet<string> = new Set([\n 'View',\n 'Text',\n 'TextInput',\n 'Pressable',\n 'ScrollView',\n 'Image',\n 'ImageBackground',\n 'FlatList',\n 'SectionList',\n 'VirtualizedList',\n 'KeyboardAvoidingView',\n 'SafeAreaView',\n 'Modal',\n 'Switch',\n 'RefreshControl',\n 'ActivityIndicator',\n 'TouchableOpacity',\n 'TouchableHighlight',\n 'TouchableWithoutFeedback',\n 'TouchableNativeFeedback',\n 'Button',\n 'StatusBar',\n])\n\n/**\n * Named exports that LOOK like components (PascalCase) under an `'all'`\n * policy but aren't — React contexts, gesture-handler enums/namespaces,\n * etc. Wrapping these would turn `Gesture.Pan()` / `State.ACTIVE` /\n * `<XContext.Provider>` into a `wrap()`-ed component and break them.\n * Names ending in `Context` are excluded separately.\n */\nconst NON_COMPONENT_EXPORTS: ReadonlySet<string> = new Set([\n 'Gesture',\n 'GestureObjects',\n 'State',\n 'Directions',\n 'Extrapolation',\n 'Extrapolate',\n 'Easing',\n 'ReduceMotion',\n 'KeyframeRegistry',\n])\n\n/** Per-module policy: an explicit allow-list, or `'all'` named exports. */\nexport type WrapPolicy = 'all' | ReadonlySet<string>\n\n/**\n * Default module → wrap policy. react-native is allow-listed (mixed\n * exports); the rest are component-only packages → `'all'`. Only modules\n * the project has installed are ever hit (you can't import from a missing\n * package), so listing optional peers is free.\n */\nexport const DEFAULT_WRAP_MODULES: ReadonlyMap<string, WrapPolicy> = new Map<string, WrapPolicy>([\n ['react-native', REACT_NATIVE_COMPONENTS],\n ['react-native-reanimated', 'all'],\n ['react-native-svg', 'all'],\n ['react-native-gesture-handler', 'all'],\n ['react-native-safe-area-context', 'all'],\n ['expo-linear-gradient', 'all'],\n ['expo-image', 'all'],\n ['expo-blur', 'all'],\n ['expo-symbols', 'all'],\n ['@shopify/flash-list', 'all'],\n ['@shopify/react-native-skia', 'all'],\n ['lottie-react-native', 'all'],\n])\n\n/**\n * Whether a named import from a wrap-module should be wrapped.\n *\n * Explicit allow-lists (react-native) match by exact name. The `'all'`\n * policy wraps only component-style names — PascalCase, not a React\n * context (`*Context`), and not a known non-component export. This is\n * what stops `useSafeAreaInsets` (a hook) from being wrapped into a\n * component and crashing when called.\n * @param policy The module's wrap policy.\n * @param importedName The exported name being imported.\n * @returns True when the name is a component to wrap.\n */\nfunction shouldWrap(policy: WrapPolicy, importedName: string): boolean {\n if (policy !== 'all') return policy.has(importedName)\n if (!/^[A-Z]/.test(importedName)) return false\n if (importedName.endsWith('Context')) return false\n return !NON_COMPONENT_EXPORTS.has(importedName)\n}\n\n/**\n * Merge user-supplied wrap modules onto the defaults — a bare module name\n * adopts the `'all'` policy.\n * @param extra User module specifiers (or undefined).\n * @returns Effective module → policy map.\n */\nexport function buildWrapModules(extra?: readonly string[]): ReadonlyMap<string, WrapPolicy> {\n if (!extra || extra.length === 0) return DEFAULT_WRAP_MODULES\n const merged = new Map<string, WrapPolicy>(DEFAULT_WRAP_MODULES)\n for (const moduleName of extra) if (!merged.has(moduleName)) merged.set(moduleName, 'all')\n return merged\n}\n\n/**\n * The `imported` name of an import specifier (`import { a as b }` → `'a'`).\n * @param specifier Named import specifier.\n * @returns The exported name.\n */\nfunction importedNameOf(specifier: t.ImportSpecifier): string {\n return t.isIdentifier(specifier.imported) ? specifier.imported.name : specifier.imported.value\n}\n\n/**\n * Build `const Local = <wrapper>(alias)` and rebind the specifier's local\n * to `alias` in place.\n * @param specifier The import specifier to rebind.\n * @param alias The `_rnwN` alias to bind the original import to.\n * @param wrapper The runtime helper local (`_rnwWrap` / `_rnwWrapNs`).\n * @returns The wrap declaration.\n */\nfunction makeWrapDecl(\n specifier: t.ImportSpecifier | t.ImportDefaultSpecifier | t.ImportNamespaceSpecifier,\n alias: string,\n wrapper: string,\n): t.VariableDeclaration {\n const { name: localName } = specifier.local\n specifier.local = t.identifier(alias)\n return t.variableDeclaration('const', [\n t.variableDeclarator(t.identifier(localName), t.callExpression(t.identifier(wrapper), [t.identifier(alias)])),\n ])\n}\n\n/**\n * Rewrite one import declaration's wrappable specifiers, aliasing each to\n * `_rnw<N>` in place:\n * - named (`{ View }`) → `const View = wrap(_rnwN)` (per policy),\n * - namespace (`* as Animated`) → `const Animated = wrapNamespace(_rnwN)`,\n * - default → `wrapNamespace` for {@link NAMESPACE_DEFAULT_MODULES}\n * (reanimated's `Animated`), else `wrap` (a plain default component).\n * @param node Import declaration to inspect.\n * @param policy The module's wrap policy.\n * @param counter Next alias index (caller-threaded for uniqueness).\n * @returns New wrap declarations, advanced counter, and whether any\n * binding used `wrapNamespace`.\n */\nfunction wrapSpecifiers(\n node: t.ImportDeclaration,\n policy: WrapPolicy,\n counter: number,\n): { decls: t.VariableDeclaration[]; counter: number; usesNamespace: boolean } {\n const decls: t.VariableDeclaration[] = []\n const moduleName = node.source.value\n let next = counter\n let usesNamespace = false\n for (const specifier of node.specifiers) {\n if (t.isImportSpecifier(specifier)) {\n if (!shouldWrap(policy, importedNameOf(specifier))) continue\n decls.push(makeWrapDecl(specifier, `_rnw${next}`, WRAP_LOCAL))\n next += 1\n continue\n }\n const isNamespace = t.isImportNamespaceSpecifier(specifier) || NAMESPACE_DEFAULT_MODULES.has(moduleName)\n const wrapper = isNamespace ? WRAP_NS_LOCAL : WRAP_LOCAL\n decls.push(makeWrapDecl(specifier, `_rnw${next}`, wrapper))\n next += 1\n if (isNamespace) usesNamespace = true\n }\n return { decls, counter: next, usesNamespace }\n}\n\n/**\n * Insert the `wrap` import at the top and the `const X = wrap(_rnwN)`\n * declarations AFTER every import. The consts reference the aliased\n * binding `_rnwN`, and in Metro's real transform (CommonJS interop + the\n * reanimated worklets plugin) a const placed above its source import\n * evaluates before the binding initialises → `ReferenceError: _rnw0\n * doesn't exist`. ESM-only hoisting would mask this; the bundle does not.\n * @param ast Parsed Babel file (mutated).\n * @param wrapDecls The wrap declarations to place.\n * @param usesNamespace Whether any binding used `wrapNamespace`.\n */\nfunction placeWrapDecls(ast: File, wrapDecls: readonly t.VariableDeclaration[], usesNamespace: boolean): void {\n const specifiers = [t.importSpecifier(t.identifier(WRAP_LOCAL), t.identifier('wrap'))]\n if (usesNamespace) specifiers.push(t.importSpecifier(t.identifier(WRAP_NS_LOCAL), t.identifier('wrapNamespace')))\n ast.program.body.unshift(t.importDeclaration(specifiers, t.stringLiteral(RUNTIME_MODULE)))\n let afterImports = 0\n for (let index = 0; index < ast.program.body.length; index += 1) {\n if (t.isImportDeclaration(ast.program.body[index])) afterImports = index + 1\n }\n ast.program.body.splice(afterImports, 0, ...wrapDecls)\n}\n\n/**\n * Rewrite component imports from the configured wrap-modules into\n * `wrap()`-ed bindings, in place. Injects the `wrap` import once when any\n * binding was rewritten.\n * @param ast Parsed Babel file (mutated).\n * @param modules Effective module → policy map.\n * @returns True when at least one import was wrapped.\n */\nexport function rewriteWrapImports(ast: File, modules: ReadonlyMap<string, WrapPolicy>): boolean {\n const wrapDecls: t.VariableDeclaration[] = []\n let counter = 0\n let usesNamespace = false\n\n for (const node of ast.program.body) {\n if (!t.isImportDeclaration(node)) continue\n const policy = modules.get(node.source.value)\n if (!policy) continue\n const { decls, counter: nextCounter, usesNamespace: ns } = wrapSpecifiers(node, policy, counter)\n counter = nextCounter\n usesNamespace = usesNamespace || ns\n wrapDecls.push(...decls)\n }\n\n if (wrapDecls.length === 0) return false\n placeWrapDecls(ast, wrapDecls, usesNamespace)\n return true\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wrap-imports.mjs","sources":["../../../../src/metro/wrap-imports.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport type { File } from '@babel/types'\n\n/**\n * Build-time import rewrite. For every `import { View } from\n * 'react-native'` (and the other configured modules) it aliases the\n * original export and binds a `wrap()`-ed component in its place:\n *\n * ```\n * import { View, StyleSheet } from 'react-native'\n * ⇩\n * import { View as _rnw0, StyleSheet } from 'react-native'\n * import { wrap as _rnwWrap } from 'rnwind'\n * const View = _rnwWrap(_rnw0)\n * ```\n *\n * Now `<View className=\"…\">` resolves className → style at render via the\n * wrapper — no matter how className arrived (literal, `{...rest}` spread,\n * forwarded through custom layers). Non-component exports (`StyleSheet`)\n * are left untouched.\n */\n\n/** Local binding the injected `wrap` import is aliased to. */\nconst WRAP_LOCAL = '_rnwWrap'\n/** Local binding the injected `wrapNamespace` import is aliased to. */\nconst WRAP_NS_LOCAL = '_rnwWrapNs'\n/** Module the wrapper is imported from. */\nconst RUNTIME_MODULE = 'rnwind'\n\n/**\n * Wrap-modules whose DEFAULT export is a component NAMESPACE accessed via\n * member expressions (`Animated.View`), not a single component. Their\n * default import is bound through `wrapNamespace` (a Proxy that wraps each\n * accessed component member) instead of `wrap`. Every other default import\n * is treated as a plain component.\n */\nconst NAMESPACE_DEFAULT_MODULES: ReadonlySet<string> = new Set(['react-native-reanimated'])\n\n/**\n * react-native mixes styleable components with utilities (`StyleSheet`,\n * `Platform`, …). Only these named exports are wrapped; everything else\n * passes through. Other ecosystem modules export components only and use\n * the `'all'` policy instead.\n */\nconst REACT_NATIVE_COMPONENTS: ReadonlySet<string> = new Set([\n 'View',\n 'Text',\n 'TextInput',\n 'Pressable',\n 'ScrollView',\n 'Image',\n 'ImageBackground',\n 'FlatList',\n 'SectionList',\n 'VirtualizedList',\n 'KeyboardAvoidingView',\n 'SafeAreaView',\n 'Modal',\n 'Switch',\n 'RefreshControl',\n 'ActivityIndicator',\n 'TouchableOpacity',\n 'TouchableHighlight',\n 'TouchableWithoutFeedback',\n 'TouchableNativeFeedback',\n 'Button',\n 'StatusBar',\n])\n\n/**\n * Named exports that LOOK like components (PascalCase) under an `'all'`\n * policy but aren't — React contexts, gesture-handler enums/namespaces,\n * etc. Wrapping these would turn `Gesture.Pan()` / `State.ACTIVE` /\n * `<XContext.Provider>` into a `wrap()`-ed component and break them.\n * Names ending in `Context` are excluded separately.\n */\nconst NON_COMPONENT_EXPORTS: ReadonlySet<string> = new Set([\n 'Gesture',\n 'GestureObjects',\n 'State',\n 'Directions',\n 'Extrapolation',\n 'Extrapolate',\n 'Easing',\n 'ReduceMotion',\n 'KeyframeRegistry',\n // gesture-handler enums (PascalCase, but value objects accessed as\n // `PointerType.TOUCH` / `MouseButton.LEFT`) — wrapping breaks the access.\n 'PointerType',\n 'MouseButton',\n 'HoverEffect',\n])\n\n/**\n * react-native-reanimated's NAMED exports are hooks, worklets, animation\n * builders (`FadeIn`, `ZoomIn`, `Keyframe`, `Layout`…), easing helpers and\n * enums (`SensorType`…) — NOT className-styleable components. Its only\n * styleable surface is the DEFAULT `Animated` namespace, wrapped separately\n * via {@link NAMESPACE_DEFAULT_MODULES}. Under the `'all'` policy the\n * PascalCase heuristic wrongly wrapped builders/enums into `wrap()`-ed\n * functions, so `FadeIn.duration()` / `new Keyframe()` / `SensorType.X` threw\n * \"is not a function\" / \"is not a constructor\" / read `undefined`. An empty\n * allow-list wraps none of them while leaving the default namespace intact.\n */\nconst REANIMATED_NAMED_COMPONENTS: ReadonlySet<string> = new Set()\n\n/** Per-module policy: an explicit allow-list, or `'all'` named exports. */\nexport type WrapPolicy = 'all' | ReadonlySet<string>\n\n/**\n * Default module → wrap policy. react-native is allow-listed (mixed\n * exports); the rest are component-only packages → `'all'`. Only modules\n * the project has installed are ever hit (you can't import from a missing\n * package), so listing optional peers is free.\n */\nexport const DEFAULT_WRAP_MODULES: ReadonlyMap<string, WrapPolicy> = new Map<string, WrapPolicy>([\n ['react-native', REACT_NATIVE_COMPONENTS],\n ['react-native-reanimated', REANIMATED_NAMED_COMPONENTS],\n ['react-native-svg', 'all'],\n ['react-native-gesture-handler', 'all'],\n ['react-native-safe-area-context', 'all'],\n ['expo-linear-gradient', 'all'],\n ['expo-image', 'all'],\n ['expo-blur', 'all'],\n ['expo-symbols', 'all'],\n ['@shopify/flash-list', 'all'],\n ['@shopify/react-native-skia', 'all'],\n ['lottie-react-native', 'all'],\n])\n\n/**\n * Whether a named import from a wrap-module should be wrapped.\n *\n * Explicit allow-lists (react-native) match by exact name. The `'all'`\n * policy wraps only component-style names — PascalCase, not a React\n * context (`*Context`), and not a known non-component export. This is\n * what stops `useSafeAreaInsets` (a hook) from being wrapped into a\n * component and crashing when called.\n * @param policy The module's wrap policy.\n * @param importedName The exported name being imported.\n * @returns True when the name is a component to wrap.\n */\nfunction shouldWrap(policy: WrapPolicy, importedName: string): boolean {\n if (policy !== 'all') return policy.has(importedName)\n if (!/^[A-Z]/.test(importedName)) return false\n if (importedName.endsWith('Context')) return false\n return !NON_COMPONENT_EXPORTS.has(importedName)\n}\n\n/**\n * Merge user-supplied wrap modules onto the defaults — a bare module name\n * adopts the `'all'` policy.\n * @param extra User module specifiers (or undefined).\n * @returns Effective module → policy map.\n */\nexport function buildWrapModules(extra?: readonly string[]): ReadonlyMap<string, WrapPolicy> {\n if (!extra || extra.length === 0) return DEFAULT_WRAP_MODULES\n const merged = new Map<string, WrapPolicy>(DEFAULT_WRAP_MODULES)\n for (const moduleName of extra) if (!merged.has(moduleName)) merged.set(moduleName, 'all')\n return merged\n}\n\n/**\n * The `imported` name of an import specifier (`import { a as b }` → `'a'`).\n * @param specifier Named import specifier.\n * @returns The exported name.\n */\nfunction importedNameOf(specifier: t.ImportSpecifier): string {\n return t.isIdentifier(specifier.imported) ? specifier.imported.name : specifier.imported.value\n}\n\n/**\n * Whether an import kind is type-only (`import type …` / `import { type … }`,\n * and the Flow `typeof` variants). Type-only bindings carry no runtime value —\n * preset-typescript strips them from the bundle — so wrapping one emits a\n * `const X = wrap(_rnwN)` referencing a binding that no longer exists at\n * runtime → Hermes \"Property '_rnwN' doesn't exist\". They must never be wrapped.\n * @param kind The `importKind` of a declaration or specifier.\n * @returns True when the import is type-only.\n */\nfunction isTypeOnly(kind: t.ImportDeclaration['importKind'] | t.ImportSpecifier['importKind']): boolean {\n return kind === 'type' || kind === 'typeof'\n}\n\n/**\n * Build `const Local = <wrapper>(alias)` and rebind the specifier's local\n * to `alias` in place.\n * @param specifier The import specifier to rebind.\n * @param alias The `_rnwN` alias to bind the original import to.\n * @param wrapper The runtime helper local (`_rnwWrap` / `_rnwWrapNs`).\n * @returns The wrap declaration.\n */\nfunction makeWrapDecl(\n specifier: t.ImportSpecifier | t.ImportDefaultSpecifier | t.ImportNamespaceSpecifier,\n alias: string,\n wrapper: string,\n): t.VariableDeclaration {\n const { name: localName } = specifier.local\n specifier.local = t.identifier(alias)\n return t.variableDeclaration('const', [\n t.variableDeclarator(t.identifier(localName), t.callExpression(t.identifier(wrapper), [t.identifier(alias)])),\n ])\n}\n\n/**\n * Rewrite one import declaration's wrappable specifiers, aliasing each to\n * `_rnw<N>` in place:\n * - named (`{ View }`) → `const View = wrap(_rnwN)` (per policy),\n * - namespace (`* as Animated`) → `const Animated = wrapNamespace(_rnwN)`,\n * - default → `wrapNamespace` for {@link NAMESPACE_DEFAULT_MODULES}\n * (reanimated's `Animated`), else `wrap` (a plain default component).\n * @param node Import declaration to inspect.\n * @param policy The module's wrap policy.\n * @param counter Next alias index (caller-threaded for uniqueness).\n * @returns New wrap declarations, advanced counter, and whether any\n * binding used `wrapNamespace`.\n */\nfunction wrapSpecifiers(\n node: t.ImportDeclaration,\n policy: WrapPolicy,\n counter: number,\n): { decls: t.VariableDeclaration[]; counter: number; usesNamespace: boolean } {\n const decls: t.VariableDeclaration[] = []\n const moduleName = node.source.value\n let next = counter\n let usesNamespace = false\n // `import type { … }` — whole declaration is type-only; nothing to wrap.\n if (isTypeOnly(node.importKind)) return { decls, counter: next, usesNamespace }\n for (const specifier of node.specifiers) {\n if (t.isImportSpecifier(specifier)) {\n // `import { type X }` — inline type-only specifier; skip it.\n if (isTypeOnly(specifier.importKind)) continue\n if (!shouldWrap(policy, importedNameOf(specifier))) continue\n decls.push(makeWrapDecl(specifier, `_rnw${next}`, WRAP_LOCAL))\n next += 1\n continue\n }\n const isNamespace = t.isImportNamespaceSpecifier(specifier) || NAMESPACE_DEFAULT_MODULES.has(moduleName)\n const wrapper = isNamespace ? WRAP_NS_LOCAL : WRAP_LOCAL\n decls.push(makeWrapDecl(specifier, `_rnw${next}`, wrapper))\n next += 1\n if (isNamespace) usesNamespace = true\n }\n return { decls, counter: next, usesNamespace }\n}\n\n/**\n * Insert the `wrap` import at the top and the `const X = wrap(_rnwN)`\n * declarations AFTER every import. The consts reference the aliased\n * binding `_rnwN`, and in Metro's real transform (CommonJS interop + the\n * reanimated worklets plugin) a const placed above its source import\n * evaluates before the binding initialises → `ReferenceError: _rnw0\n * doesn't exist`. ESM-only hoisting would mask this; the bundle does not.\n * @param ast Parsed Babel file (mutated).\n * @param wrapDecls The wrap declarations to place.\n * @param usesNamespace Whether any binding used `wrapNamespace`.\n */\nfunction placeWrapDecls(ast: File, wrapDecls: readonly t.VariableDeclaration[], usesNamespace: boolean): void {\n const specifiers = [t.importSpecifier(t.identifier(WRAP_LOCAL), t.identifier('wrap'))]\n if (usesNamespace) specifiers.push(t.importSpecifier(t.identifier(WRAP_NS_LOCAL), t.identifier('wrapNamespace')))\n ast.program.body.unshift(t.importDeclaration(specifiers, t.stringLiteral(RUNTIME_MODULE)))\n let afterImports = 0\n for (let index = 0; index < ast.program.body.length; index += 1) {\n if (t.isImportDeclaration(ast.program.body[index])) afterImports = index + 1\n }\n ast.program.body.splice(afterImports, 0, ...wrapDecls)\n}\n\n/**\n * Rewrite component imports from the configured wrap-modules into\n * `wrap()`-ed bindings, in place. Injects the `wrap` import once when any\n * binding was rewritten.\n * @param ast Parsed Babel file (mutated).\n * @param modules Effective module → policy map.\n * @returns True when at least one import was wrapped.\n */\nexport function rewriteWrapImports(ast: File, modules: ReadonlyMap<string, WrapPolicy>): boolean {\n const wrapDecls: t.VariableDeclaration[] = []\n let counter = 0\n let usesNamespace = false\n\n for (const node of ast.program.body) {\n if (!t.isImportDeclaration(node)) continue\n const policy = modules.get(node.source.value)\n if (!policy) continue\n const { decls, counter: nextCounter, usesNamespace: ns } = wrapSpecifiers(node, policy, counter)\n counter = nextCounter\n usesNamespace = usesNamespace || ns\n wrapDecls.push(...decls)\n }\n\n if (wrapDecls.length === 0) return false\n placeWrapDecls(ast, wrapDecls, usesNamespace)\n return true\n}\n"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { useMemo } from 'react';
1
2
  import { useRnwind } from '../components/rnwind-provider.mjs';
2
3
  import { getThemeTokens } from '../lookup-css.mjs';
3
4
 
@@ -21,14 +22,20 @@ function useTheme() {
21
22
  const { scheme, tables } = useRnwind();
22
23
  // The build registers token tables on the manifest so `useColor` works out
23
24
  // of the box; an explicit `tables` prop layers on top (the prop wins).
25
+ // `getThemeTokens()` REPLACES its map on registration, so its identity is
26
+ // stable between (HMR) registers — a sound memo dep. Memoizing keeps the
27
+ // merged table a STABLE reference across renders, so every `useColor` /
28
+ // `useToken` / `useSize` call avoids re-allocating 2–3 objects per render.
24
29
  const registered = getThemeTokens();
25
- const base = { ...registered[BASE_SCHEME], ...tables[BASE_SCHEME] };
26
- const schemeTable = { ...registered[scheme], ...tables[scheme] };
27
- // Base tokens apply everywhere (CSS `:root` cascade); the active scheme's
28
- // own entries override on overlap.
29
- if (Object.keys(schemeTable).length === 0)
30
- return base;
31
- return { ...base, ...schemeTable };
30
+ return useMemo(() => {
31
+ const base = { ...registered[BASE_SCHEME], ...tables[BASE_SCHEME] };
32
+ const schemeTable = { ...registered[scheme], ...tables[scheme] };
33
+ // Base tokens apply everywhere (CSS `:root` cascade); the active scheme's
34
+ // own entries override on overlap.
35
+ if (Object.keys(schemeTable).length === 0)
36
+ return base;
37
+ return { ...base, ...schemeTable };
38
+ }, [scheme, tables, registered]);
32
39
  }
33
40
  /**
34
41
  * Read a raw CSS custom property's value for the active scheme. Accepts
@@ -1 +1 @@
1
- {"version":3,"file":"use-scheme.mjs","sources":["../../../../../src/runtime/hooks/use-scheme.ts"],"sourcesContent":["import type { ThemeTable } from '../../core/types'\nimport { useRnwind } from '../components/rnwind-provider'\nimport { getThemeTokens } from '../lookup-css'\n\n/**\n * Synthetic scheme name applied when tokens aren't declared under any\n * `@variant` block — the \"no active variant\" fallback every theme table\n * inherits from.\n */\nconst BASE_SCHEME = 'base'\n\n/**\n * Access the resolved theme table for the active scheme.\n *\n * Tokens declared outside any `@variant` block live in the `base` table and\n * should apply everywhere — just like the CSS cascade treats `:root` as a\n * default for every ancestor-scoped override. We merge `base` under the\n * active scheme so a scheme that doesn't declare a token still sees the\n * base default, while the scheme's own entries win on overlap.\n * @returns Token table for the active scheme.\n */\nexport function useTheme(): ThemeTable {\n const { scheme, tables } = useRnwind()\n // The build registers token tables on the manifest so `useColor` works out\n // of the box; an explicit `tables` prop layers on top (the prop wins).\n const registered = getThemeTokens()\n const base = { ...registered[BASE_SCHEME], ...tables[BASE_SCHEME] }\n const schemeTable = { ...registered[scheme], ...tables[scheme] }\n // Base tokens apply everywhere (CSS `:root` cascade); the active scheme's\n // own entries override on overlap.\n if (Object.keys(schemeTable).length === 0) return base\n return { ...base, ...schemeTable }\n}\n\n/**\n * Read a raw CSS custom property's value for the active scheme. Accepts\n * either `--foo` or the bare `foo` form for convenience.\n * @param cssVariable CSS custom property name (with or without the leading `--`).\n * @returns The resolved value, or undefined when the token is missing.\n */\nexport function useToken(cssVariable: string): string | number | undefined {\n const table = useTheme()\n const name = cssVariable.startsWith('--') ? cssVariable : `--${cssVariable}`\n return table[name]\n}\n\n/**\n * Read a color token by shorthand name — `useColor('primary')` resolves\n * `--color-primary` for the active scheme. A fully-qualified name\n * (`--color-primary`) is accepted as-is, so the call doesn't silently miss by\n * double-prefixing into `--color---color-primary`.\n * @param name Token suffix after `--color-`, or the full `--color-*` name.\n * @returns Resolved color string, or undefined when the token is missing\n * or its value isn't a string.\n */\nexport function useColor(name: string): string | undefined {\n const value = useToken(name.startsWith('--') ? name : `--color-${name}`)\n return typeof value === 'string' ? value : undefined\n}\n\n/**\n * Read a spacing token by shorthand name — `useSize('4')` resolves\n * `--spacing-4` for the active scheme. A fully-qualified `--spacing-*` name is\n * accepted as-is (no double-prefix miss).\n * @param name Token suffix after `--spacing-`, or the full `--spacing-*` name.\n * @returns Resolved spacing value, or undefined when the token is missing.\n */\nexport function useSize(name: string): number | string | undefined {\n return useToken(name.startsWith('--') ? name : `--spacing-${name}`)\n}\n"],"names":[],"mappings":";;;AAIA;;;;AAIG;AACH,MAAM,WAAW,GAAG,MAAM;AAE1B;;;;;;;;;AASG;SACa,QAAQ,GAAA;IACtB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE;;;AAGtC,IAAA,MAAM,UAAU,GAAG,cAAc,EAAE;AACnC,IAAA,MAAM,IAAI,GAAG,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE;AACnE,IAAA,MAAM,WAAW,GAAG,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE;;;IAGhE,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,IAAI;AACtD,IAAA,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,WAAW,EAAE;AACpC;AAEA;;;;;AAKG;AACG,SAAU,QAAQ,CAAC,WAAmB,EAAA;AAC1C,IAAA,MAAM,KAAK,GAAG,QAAQ,EAAE;AACxB,IAAA,MAAM,IAAI,GAAG,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,WAAW,GAAG,CAAA,EAAA,EAAK,WAAW,EAAE;AAC5E,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC;AACpB;AAEA;;;;;;;;AAQG;AACG,SAAU,QAAQ,CAAC,IAAY,EAAA;IACnC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAA,QAAA,EAAW,IAAI,CAAA,CAAE,CAAC;AACxE,IAAA,OAAO,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,SAAS;AACtD;AAEA;;;;;;AAMG;AACG,SAAU,OAAO,CAAC,IAAY,EAAA;AAClC,IAAA,OAAO,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,aAAa,IAAI,CAAA,CAAE,CAAC;AACrE;;;;"}
1
+ {"version":3,"file":"use-scheme.mjs","sources":["../../../../../src/runtime/hooks/use-scheme.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport type { ThemeTable } from '../../core/types'\nimport { useRnwind } from '../components/rnwind-provider'\nimport { getThemeTokens } from '../lookup-css'\n\n/**\n * Synthetic scheme name applied when tokens aren't declared under any\n * `@variant` block — the \"no active variant\" fallback every theme table\n * inherits from.\n */\nconst BASE_SCHEME = 'base'\n\n/**\n * Access the resolved theme table for the active scheme.\n *\n * Tokens declared outside any `@variant` block live in the `base` table and\n * should apply everywhere — just like the CSS cascade treats `:root` as a\n * default for every ancestor-scoped override. We merge `base` under the\n * active scheme so a scheme that doesn't declare a token still sees the\n * base default, while the scheme's own entries win on overlap.\n * @returns Token table for the active scheme.\n */\nexport function useTheme(): ThemeTable {\n const { scheme, tables } = useRnwind()\n // The build registers token tables on the manifest so `useColor` works out\n // of the box; an explicit `tables` prop layers on top (the prop wins).\n // `getThemeTokens()` REPLACES its map on registration, so its identity is\n // stable between (HMR) registers — a sound memo dep. Memoizing keeps the\n // merged table a STABLE reference across renders, so every `useColor` /\n // `useToken` / `useSize` call avoids re-allocating 2–3 objects per render.\n const registered = getThemeTokens()\n return useMemo(() => {\n const base = { ...registered[BASE_SCHEME], ...tables[BASE_SCHEME] }\n const schemeTable = { ...registered[scheme], ...tables[scheme] }\n // Base tokens apply everywhere (CSS `:root` cascade); the active scheme's\n // own entries override on overlap.\n if (Object.keys(schemeTable).length === 0) return base\n return { ...base, ...schemeTable }\n }, [scheme, tables, registered])\n}\n\n/**\n * Read a raw CSS custom property's value for the active scheme. Accepts\n * either `--foo` or the bare `foo` form for convenience.\n * @param cssVariable CSS custom property name (with or without the leading `--`).\n * @returns The resolved value, or undefined when the token is missing.\n */\nexport function useToken(cssVariable: string): string | number | undefined {\n const table = useTheme()\n const name = cssVariable.startsWith('--') ? cssVariable : `--${cssVariable}`\n return table[name]\n}\n\n/**\n * Read a color token by shorthand name — `useColor('primary')` resolves\n * `--color-primary` for the active scheme. A fully-qualified name\n * (`--color-primary`) is accepted as-is, so the call doesn't silently miss by\n * double-prefixing into `--color---color-primary`.\n * @param name Token suffix after `--color-`, or the full `--color-*` name.\n * @returns Resolved color string, or undefined when the token is missing\n * or its value isn't a string.\n */\nexport function useColor(name: string): string | undefined {\n const value = useToken(name.startsWith('--') ? name : `--color-${name}`)\n return typeof value === 'string' ? value : undefined\n}\n\n/**\n * Read a spacing token by shorthand name — `useSize('4')` resolves\n * `--spacing-4` for the active scheme. A fully-qualified `--spacing-*` name is\n * accepted as-is (no double-prefix miss).\n * @param name Token suffix after `--spacing-`, or the full `--spacing-*` name.\n * @returns Resolved spacing value, or undefined when the token is missing.\n */\nexport function useSize(name: string): number | string | undefined {\n return useToken(name.startsWith('--') ? name : `--spacing-${name}`)\n}\n"],"names":[],"mappings":";;;;AAKA;;;;AAIG;AACH,MAAM,WAAW,GAAG,MAAM;AAE1B;;;;;;;;;AASG;SACa,QAAQ,GAAA;IACtB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE;;;;;;;AAOtC,IAAA,MAAM,UAAU,GAAG,cAAc,EAAE;IACnC,OAAO,OAAO,CAAC,MAAK;AAClB,QAAA,MAAM,IAAI,GAAG,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE;AACnE,QAAA,MAAM,WAAW,GAAG,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE;;;QAGhE,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,IAAI;AACtD,QAAA,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,WAAW,EAAE;IACpC,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;AAClC;AAEA;;;;;AAKG;AACG,SAAU,QAAQ,CAAC,WAAmB,EAAA;AAC1C,IAAA,MAAM,KAAK,GAAG,QAAQ,EAAE;AACxB,IAAA,MAAM,IAAI,GAAG,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,WAAW,GAAG,CAAA,EAAA,EAAK,WAAW,EAAE;AAC5E,IAAA,OAAO,KAAK,CAAC,IAAI,CAAC;AACpB;AAEA;;;;;;;;AAQG;AACG,SAAU,QAAQ,CAAC,IAAY,EAAA;IACnC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAA,QAAA,EAAW,IAAI,CAAA,CAAE,CAAC;AACxE,IAAA,OAAO,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,SAAS;AACtD;AAEA;;;;;;AAMG;AACG,SAAU,OAAO,CAAC,IAAY,EAAA;AAClC,IAAA,OAAO,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,aAAa,IAAI,CAAA,CAAE,CAAC;AACrE;;;;"}
@@ -29,7 +29,11 @@ export interface ResolvedCss {
29
29
  }
30
30
  /**
31
31
  * Register one scheme's pre-merged molecules (atom-merged literal
32
- * classNames). Merges onto any existing entries for the scheme.
32
+ * classNames). REPLACES the scheme's map each generated scheme file emits a
33
+ * single `registerMolecules(scheme, …)` carrying the complete molecule set
34
+ * (mirrors `registerAtoms`). Merging instead would leak molecules removed in a
35
+ * Fast Refresh edit, so a deleted/renamed className would keep resolving to its
36
+ * stale pre-edit style.
33
37
  * @param scheme Scheme name (or `'common'`).
34
38
  * @param entries Normalized className → merged style object.
35
39
  */
@@ -75,12 +75,16 @@ const DIRECTION_POINTS = {
75
75
  };
76
76
  /**
77
77
  * Register one scheme's pre-merged molecules (atom-merged literal
78
- * classNames). Merges onto any existing entries for the scheme.
78
+ * classNames). REPLACES the scheme's map each generated scheme file emits a
79
+ * single `registerMolecules(scheme, …)` carrying the complete molecule set
80
+ * (mirrors `registerAtoms`). Merging instead would leak molecules removed in a
81
+ * Fast Refresh edit, so a deleted/renamed className would keep resolving to its
82
+ * stale pre-edit style.
79
83
  * @param scheme Scheme name (or `'common'`).
80
84
  * @param entries Normalized className → merged style object.
81
85
  */
82
86
  function registerMolecules(scheme, entries) {
83
- molecules[scheme] = { ...molecules[scheme], ...entries };
87
+ molecules[scheme] = entries;
84
88
  registryVersion += 1;
85
89
  }
86
90
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.mjs","sources":["../../../../src/runtime/resolve.ts"],"sourcesContent":["import { breakpointTier, getStyleVersion, lookupCss, type InteractState } from './lookup-css'\nimport type { RnwindState } from './components/rnwind-provider'\nimport { normalizeClassName } from '../core/normalize-classname'\nimport type { GradientAtomInfo, GradientDirection } from '../core/parser/gradient'\nimport type { HapticRequest, HapticTrigger } from '../core/parser/haptics'\n\n/**\n * Rich className resolver — the runtime heart of the wrap / `useCss`.\n *\n * Resolution order, per className string:\n * 1. **Molecule** — a build-time PRE-MERGED single style object for the\n * whole literal className (per scheme). One map lookup returns it by\n * reference: no array, no merge, no per-atom loop. The common case.\n * 2. **Atom fallback** — for a className the scanner never saw (a\n * runtime-built string like `` `${className} px-2` ``) OR one that\n * carries context-dependent atoms (`pt-safe`, `text-base`, `md:*`),\n * fall back to per-atom resolution via `lookupCss`, which folds in\n * insets / fontScale / breakpoint / scheme.\n *\n * Results are cached by `(normalized className, scheme, insets, fontScale,\n * breakpoint)` so repeated renders return the SAME reference until the\n * reactive context changes. Atoms / molecules / features all live in\n * build-time registries the generated `.rnwind/*.js` modules populate.\n */\n\n/** Always-loaded fallback scheme key. */\nconst COMMON_SCHEME = 'common'\n\n/** Empty style sentinel. */\nconst EMPTY: readonly unknown[] = []\n\n/** scheme → normalized className → pre-merged style object. */\nlet molecules: Record<string, Record<string, unknown>> = Object.create(null)\n/** atom name → gradient role + resolved colour. */\nlet gradients: Record<string, GradientAtomInfo> = Object.create(null)\n/** atom name (incl. `active:`/`focus:` prefix) → haptic request. */\nlet haptics: Record<string, HapticRequest> = Object.create(null)\n/** Bumps on any molecule/gradient/haptic registration. */\nlet registryVersion = 0\n\n/** Per-(className·state) resolved cache — strong references between context changes. */\nconst resolvedCache = new Map<string, ResolvedCss>()\n/** Version the cache was last valid for (`getStyleVersion()` + {@link registryVersion}). */\nlet cachedFor = -1\n\n/**\n * Hard ceiling on the resolved cache. The cache is pure memoisation, so\n * eviction only costs a re-resolve (sub-µs) — never correctness. Build\n * molecules are NOT in here; they live permanently in `molecules`.\n */\nconst MAX_RESOLVED_CACHE = 2048\n\n/**\n * Store a resolved result, bulk-evicting the OLDEST half when the cache\n * hits {@link MAX_RESOLVED_CACHE}. `Map` preserves insertion order, so the\n * first keys are the oldest. Bulk eviction keeps the hot (cache-hit) path\n * free of per-access LRU bookkeeping at the cost of an occasional small\n * recompute burst under sustained pressure (web / long sessions).\n * @param key Cache key.\n * @param value Resolved result to store.\n */\nfunction cacheResolved(key: string, value: ResolvedCss): void {\n if (resolvedCache.size >= MAX_RESOLVED_CACHE) {\n let drop = resolvedCache.size >> 1\n for (const oldKey of resolvedCache.keys()) {\n resolvedCache.delete(oldKey)\n if (--drop <= 0) break\n }\n }\n resolvedCache.set(key, value)\n}\n\n/** A unit-square gradient endpoint. */\ninterface GradientPoint {\n readonly x: number\n readonly y: number\n}\n\n/** Rich resolution: the RN `style` plus any className-derived props. */\nexport interface ResolvedCss {\n /** RN `style` value — a single molecule object (by ref) or an atom array. */\n readonly style: unknown\n /** Gradient stop colours (when the className is a complete gradient). */\n readonly colors?: readonly string[]\n /** Gradient start point. */\n readonly start?: GradientPoint\n /** Gradient end point. */\n readonly end?: GradientPoint\n /** Text truncation line count. */\n readonly numberOfLines?: number\n /** Text ellipsize mode. */\n readonly ellipsizeMode?: 'tail' | 'clip'\n /** Haptic requests present on the className, for the wrap to dispatch. */\n readonly haptics?: readonly { readonly request: HapticRequest; readonly trigger: HapticTrigger }[]\n}\n\n/** `GradientDirection` → expo-linear-gradient start/end points. */\nconst DIRECTION_POINTS: Record<GradientDirection, { start: GradientPoint; end: GradientPoint }> = {\n 'to-t': { start: { x: 0.5, y: 1 }, end: { x: 0.5, y: 0 } },\n 'to-b': { start: { x: 0.5, y: 0 }, end: { x: 0.5, y: 1 } },\n 'to-l': { start: { x: 1, y: 0.5 }, end: { x: 0, y: 0.5 } },\n 'to-r': { start: { x: 0, y: 0.5 }, end: { x: 1, y: 0.5 } },\n 'to-tl': { start: { x: 1, y: 1 }, end: { x: 0, y: 0 } },\n 'to-tr': { start: { x: 0, y: 1 }, end: { x: 1, y: 0 } },\n 'to-bl': { start: { x: 1, y: 0 }, end: { x: 0, y: 1 } },\n 'to-br': { start: { x: 0, y: 0 }, end: { x: 1, y: 1 } },\n unknown: { start: { x: 0, y: 0.5 }, end: { x: 1, y: 0.5 } },\n}\n\n/**\n * Register one scheme's pre-merged molecules (atom-merged literal\n * classNames). Merges onto any existing entries for the scheme.\n * @param scheme Scheme name (or `'common'`).\n * @param entries Normalized className → merged style object.\n */\nexport function registerMolecules(scheme: string, entries: Record<string, unknown>): void {\n molecules[scheme] = { ...molecules[scheme], ...entries }\n registryVersion += 1\n}\n\n/**\n * Register the gradient atom map (atom name → role + resolved colour).\n * @param map Atom name → gradient info.\n */\nexport function registerGradients(map: Record<string, GradientAtomInfo>): void {\n gradients = map\n registryVersion += 1\n}\n\n/**\n * Register the haptic atom map (atom name → request).\n * @param map Atom name → haptic request.\n */\nexport function registerHaptics(map: Record<string, HapticRequest>): void {\n haptics = map\n registryVersion += 1\n}\n\n\n\n/**\n * Per-state-object signature memo. `RnwindState` is created fresh (via the\n * provider's `useMemo`) whenever any field changes, so its identity is a\n * sound key — a new object means a new signature. Keyed weakly so states\n * GC with their provider.\n */\nconst stateSignatureCache = new WeakMap<RnwindState, string>()\n\n/**\n * Cache key dimension for the reactive context — everything that can\n * change a resolved style. Uses the numeric breakpoint TIER (count of\n * thresholds reached) from `breakpointTier(windowWidth)`, NOT the\n * `activeBreakpoint` NAME: the name clamps tier-0 into the smallest\n * breakpoint, so widths straddling that threshold (e.g. 320 vs 700 with\n * `sm=640`) would collide on one cache key and serve a stale style. The\n * tier is exact AND bounded — two widths in the same tier gate every\n * `sm:`/`md:`/… atom identically, so they resolve the same.\n * @param state Rnwind context.\n * @returns Compact signature string.\n */\nfunction stateSignature(state: RnwindState): string {\n const { insets } = state\n return `${state.scheme}|${insets.top},${insets.right},${insets.bottom},${insets.left}|${state.fontScale}|${breakpointTier(state.windowWidth)}`\n}\n\n/**\n * Memoised {@link stateSignature} — one `WeakMap.get` on the hot path\n * instead of rebuilding the template string every resolve.\n * @param state Rnwind context.\n * @returns Cached compact signature.\n */\nfunction stateSignatureCached(state: RnwindState): string {\n let signature = stateSignatureCache.get(state)\n if (signature === undefined) {\n signature = stateSignature(state)\n stateSignatureCache.set(state, signature)\n }\n return signature\n}\n\n/**\n * Compact signature of the live interactive state for the cache key.\n * @param interactState Active/focus flags, or undefined for the plain path.\n * @returns Two-bit signature (`''` when no interactive state).\n */\nfunction interactSignature(interactState?: InteractState): string {\n if (!interactState) return ''\n const active = interactState.active ? 1 : 0\n const focus = interactState.focus ? 1 : 0\n return `${active}${focus}`\n}\n\n/**\n * Whether a token is a feature-ONLY utility (gradient stop/direction,\n * haptic request, or text-truncate) that contributes NO RN `style`. These\n * are folded in via {@link attachFeatures}, so they must be kept OUT of\n * the `lookupCss` input — otherwise the atom resolver treats them as\n * unknown style atoms and emits a spurious \"unknown class\" dev warning\n * (e.g. for `active:haptic-rigid`).\n * @param token Atom name.\n * @returns True when the token carries no style.\n */\nfunction isFeatureOnlyToken(token: string): boolean {\n return Boolean(gradients[token]) || Boolean(haptics[token]) || truncateForToken(token) !== null\n}\n\n/**\n * Lifecycle trigger for a haptic atom from its variant prefix.\n * @param token Atom name (maybe `active:`/`focus:`/`hover:` prefixed).\n * @returns The trigger.\n */\nfunction hapticTriggerForToken(token: string): HapticTrigger {\n const colon = token.indexOf(':')\n if (colon === -1) return 'mount'\n const prefix = token.slice(0, colon)\n if (prefix === 'active') return 'pressIn'\n if (prefix === 'focus') return 'focus'\n if (prefix === 'hover') return 'hover'\n return 'mount'\n}\n\n/**\n * Syntactic text-truncate directive for one atom.\n * @param token Atom name.\n * @returns Partial truncate props, or null.\n */\nfunction truncateForToken(token: string): { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } | null {\n if (token === 'truncate') return { numberOfLines: 1, ellipsizeMode: 'tail' }\n if (token === 'text-ellipsis') return { ellipsizeMode: 'tail' }\n if (token === 'text-clip') return { ellipsizeMode: 'clip' }\n if (token === 'line-clamp-none') return { numberOfLines: 0 }\n if (token.startsWith('line-clamp-')) {\n const count = Number(token.slice('line-clamp-'.length))\n if (Number.isInteger(count) && count >= 0) return { numberOfLines: count }\n }\n return null\n}\n\n/**\n * Assemble gradient props from gradient roles present in the atom list.\n * @param tokens Atom names.\n * @returns `{colors, start, end}` or null when not a complete gradient.\n */\nfunction assembleGradient(tokens: readonly string[]): { colors: string[]; start: GradientPoint; end: GradientPoint } | null {\n let from: string | undefined\n let via: string | undefined\n let to: string | undefined\n let dir: GradientDirection | undefined\n for (const token of tokens) {\n const info = gradients[token]\n if (!info) continue\n switch (info.role) {\n case 'from': {\n from = info.color\n break\n }\n case 'via': {\n via = info.color\n break\n }\n case 'to': {\n to = info.color\n break\n }\n default: {\n ;({ dir } = info)\n }\n }\n }\n if (dir === undefined) return null\n const colors = [from, via, to].filter((color): color is string => color !== undefined)\n if (colors.length < 2) return null\n const points = DIRECTION_POINTS[dir]\n return { colors, start: points.start, end: points.end }\n}\n\n/**\n * Fold every truncate directive across the atom list into one result —\n * last token wins per prop (matches Tailwind last-wins).\n * @param tokens Atom names.\n * @returns Merged truncate props (empty when none apply).\n */\nfunction collectTruncate(tokens: readonly string[]): { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } {\n const out: { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } = {}\n for (const token of tokens) {\n const truncate = truncateForToken(token)\n if (!truncate) continue\n if (truncate.numberOfLines !== undefined) out.numberOfLines = truncate.numberOfLines\n if (truncate.ellipsizeMode !== undefined) out.ellipsizeMode = truncate.ellipsizeMode\n }\n return out\n}\n\n/**\n * Collect every haptic request present in the atom list, tagged with the\n * lifecycle trigger its variant prefix implies.\n * @param tokens Atom names.\n * @returns Haptic request list, or undefined when none apply.\n */\nfunction collectHaptics(tokens: readonly string[]): { request: HapticRequest; trigger: HapticTrigger }[] | undefined {\n let collected: { request: HapticRequest; trigger: HapticTrigger }[] | undefined\n for (const token of tokens) {\n const request = haptics[token]\n if (!request) continue\n collected ??= []\n collected.push({ request, trigger: hapticTriggerForToken(token) })\n }\n return collected\n}\n\n/**\n * Scan tokens for the className-derived feature props (gradient,\n * truncate, haptics) and fold them onto the base result.\n * @param base Result carrying the resolved `style`.\n * @param tokens Atom names.\n * @returns The result with any feature props attached.\n */\nfunction attachFeatures(base: ResolvedCss, tokens: readonly string[]): ResolvedCss {\n const { numberOfLines, ellipsizeMode } = collectTruncate(tokens)\n const collected = collectHaptics(tokens)\n const gradient = assembleGradient(tokens)\n const result: Mutable<ResolvedCss> = { style: base.style }\n if (gradient) {\n result.colors = gradient.colors\n result.start = gradient.start\n result.end = gradient.end\n }\n // `numberOfLines: 0` is kept (RN reads it as \"unlimited\"): `line-clamp-none`\n // must be able to explicitly reset an earlier `line-clamp-N` on the same\n // element — dropping the 0 would silently leave the prior limit in place.\n if (numberOfLines !== undefined) {\n result.numberOfLines = numberOfLines\n if (ellipsizeMode !== undefined) result.ellipsizeMode = ellipsizeMode\n }\n if (collected) result.haptics = collected\n return result\n}\n\n/**\n * Flatten the per-atom style array into ONE object — a *runtime molecule*.\n * RN flattens a style array left-to-right (later wins), which is exactly\n * `Object.assign` semantics, so the merged object renders identically\n * while giving dynamic (cva / clsx) classNames the same single-object\n * shape a build-time molecule has. The caller caches the result per\n * `(className · state)`, so the merge runs once per unique context.\n * @param array Per-atom style array from `lookupCss`.\n * @returns Single merged style object.\n */\nfunction mergeStyleArray(array: readonly unknown[]): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const entry of array) if (entry && typeof entry === 'object') Object.assign(out, entry)\n return out\n}\n\n/**\n * Compose a resolved style with a caller-supplied inline style (user wins).\n * @param style\n * @param userStyle\n */\nfunction withUserStyle(style: unknown, userStyle: unknown): unknown {\n return Array.isArray(style) ? [...style, userStyle] : [style, userStyle]\n}\n\n/**\n * Resolve a className against the reactive context into a style plus any\n * className-derived props. Molecule-first (one lookup, by reference),\n * atom-fallback for unseen / context-dependent strings, cached per\n * `(className, state)`.\n * @param className Raw className string.\n * @param state Rnwind context from `useRnwind()`.\n * @param userStyle Optional inline style appended last (wins).\n * @param interactState Live active/focus flags (for `active:`/`focus:` atoms).\n * @returns The resolved style + feature props.\n */\nexport function resolve(\n className: string | null | undefined,\n state: RnwindState,\n userStyle?: unknown,\n interactState?: InteractState,\n): ResolvedCss {\n const version = getStyleVersion() + registryVersion\n if (version !== cachedFor) {\n resolvedCache.clear()\n cachedFor = version\n }\n if (className == null) {\n return { style: userStyle === undefined || userStyle === null ? EMPTY : [userStyle] }\n }\n // Key on the RAW className so the hot (cache-hit) path skips normalize\n // entirely — normalization only runs on a miss. The state signature is\n // memoised per state object, so the hit path is one WeakMap.get + one\n // string concat + one Map.get.\n const key = `${className}@${stateSignatureCached(state)}@${interactSignature(interactState)}`\n const cached = resolvedCache.get(key)\n if (cached !== undefined) {\n return userStyle === undefined || userStyle === null ? cached : { ...cached, style: withUserStyle(cached.style, userStyle) }\n }\n const normalized = normalizeClassName(className)\n if (normalized.length === 0) {\n const empty: ResolvedCss = { style: EMPTY }\n cacheResolved(key, empty)\n return userStyle === undefined || userStyle === null ? empty : { style: [userStyle] }\n }\n // Molecules are static pre-merges; anything carrying `active:`/`focus:`\n // is never registered as one, so the atom path handles interactive state.\n const tokens = normalized.split(' ')\n const molecule = interactState ? undefined : molecules[state.scheme]?.[normalized] ?? molecules[COMMON_SCHEME]?.[normalized]\n // Feature-only tokens (gradient / haptic / truncate) carry no style — keep\n // them out of the atom lookup so they don't warn as \"unknown class\". The\n // atom array is merged into ONE object (a runtime molecule) so dynamic\n // (cva / clsx) classNames get the same single-object shape as a build\n // molecule; the cache below pins the context, so the merge is correct.\n const style =\n molecule === undefined\n ? mergeStyleArray(lookupCss(tokens.filter((token) => !isFeatureOnlyToken(token)).join(' '), state, undefined, interactState))\n : molecule\n const base = attachFeatures({ style }, tokens)\n cacheResolved(key, base)\n return userStyle === undefined || userStyle === null ? base : { ...base, style: withUserStyle(base.style, userStyle) }\n}\n\n/** Local mutable view for building the frozen-shaped result. */\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\n/** Test-only — clear the molecule / gradient / haptic registries + cache. */\nexport function __resetResolveState(): void {\n molecules = Object.create(null)\n gradients = Object.create(null)\n haptics = Object.create(null)\n resolvedCache.clear()\n registryVersion += 1\n cachedFor = -1\n}\n\n/** Test-only — current resolved-cache entry count + its hard ceiling. */\nexport function __resolveCacheStats(): { size: number; max: number } {\n return { size: resolvedCache.size, max: MAX_RESOLVED_CACHE }\n}\n\nexport {normalizeClassName} from '../core/normalize-classname'"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolve.mjs","sources":["../../../../src/runtime/resolve.ts"],"sourcesContent":["import { breakpointTier, getStyleVersion, lookupCss, type InteractState } from './lookup-css'\nimport type { RnwindState } from './components/rnwind-provider'\nimport { normalizeClassName } from '../core/normalize-classname'\nimport type { GradientAtomInfo, GradientDirection } from '../core/parser/gradient'\nimport type { HapticRequest, HapticTrigger } from '../core/parser/haptics'\n\n/**\n * Rich className resolver — the runtime heart of the wrap / `useCss`.\n *\n * Resolution order, per className string:\n * 1. **Molecule** — a build-time PRE-MERGED single style object for the\n * whole literal className (per scheme). One map lookup returns it by\n * reference: no array, no merge, no per-atom loop. The common case.\n * 2. **Atom fallback** — for a className the scanner never saw (a\n * runtime-built string like `` `${className} px-2` ``) OR one that\n * carries context-dependent atoms (`pt-safe`, `text-base`, `md:*`),\n * fall back to per-atom resolution via `lookupCss`, which folds in\n * insets / fontScale / breakpoint / scheme.\n *\n * Results are cached by `(normalized className, scheme, insets, fontScale,\n * breakpoint)` so repeated renders return the SAME reference until the\n * reactive context changes. Atoms / molecules / features all live in\n * build-time registries the generated `.rnwind/*.js` modules populate.\n */\n\n/** Always-loaded fallback scheme key. */\nconst COMMON_SCHEME = 'common'\n\n/** Empty style sentinel. */\nconst EMPTY: readonly unknown[] = []\n\n/** scheme → normalized className → pre-merged style object. */\nlet molecules: Record<string, Record<string, unknown>> = Object.create(null)\n/** atom name → gradient role + resolved colour. */\nlet gradients: Record<string, GradientAtomInfo> = Object.create(null)\n/** atom name (incl. `active:`/`focus:` prefix) → haptic request. */\nlet haptics: Record<string, HapticRequest> = Object.create(null)\n/** Bumps on any molecule/gradient/haptic registration. */\nlet registryVersion = 0\n\n/** Per-(className·state) resolved cache — strong references between context changes. */\nconst resolvedCache = new Map<string, ResolvedCss>()\n/** Version the cache was last valid for (`getStyleVersion()` + {@link registryVersion}). */\nlet cachedFor = -1\n\n/**\n * Hard ceiling on the resolved cache. The cache is pure memoisation, so\n * eviction only costs a re-resolve (sub-µs) — never correctness. Build\n * molecules are NOT in here; they live permanently in `molecules`.\n */\nconst MAX_RESOLVED_CACHE = 2048\n\n/**\n * Store a resolved result, bulk-evicting the OLDEST half when the cache\n * hits {@link MAX_RESOLVED_CACHE}. `Map` preserves insertion order, so the\n * first keys are the oldest. Bulk eviction keeps the hot (cache-hit) path\n * free of per-access LRU bookkeeping at the cost of an occasional small\n * recompute burst under sustained pressure (web / long sessions).\n * @param key Cache key.\n * @param value Resolved result to store.\n */\nfunction cacheResolved(key: string, value: ResolvedCss): void {\n if (resolvedCache.size >= MAX_RESOLVED_CACHE) {\n let drop = resolvedCache.size >> 1\n for (const oldKey of resolvedCache.keys()) {\n resolvedCache.delete(oldKey)\n if (--drop <= 0) break\n }\n }\n resolvedCache.set(key, value)\n}\n\n/** A unit-square gradient endpoint. */\ninterface GradientPoint {\n readonly x: number\n readonly y: number\n}\n\n/** Rich resolution: the RN `style` plus any className-derived props. */\nexport interface ResolvedCss {\n /** RN `style` value — a single molecule object (by ref) or an atom array. */\n readonly style: unknown\n /** Gradient stop colours (when the className is a complete gradient). */\n readonly colors?: readonly string[]\n /** Gradient start point. */\n readonly start?: GradientPoint\n /** Gradient end point. */\n readonly end?: GradientPoint\n /** Text truncation line count. */\n readonly numberOfLines?: number\n /** Text ellipsize mode. */\n readonly ellipsizeMode?: 'tail' | 'clip'\n /** Haptic requests present on the className, for the wrap to dispatch. */\n readonly haptics?: readonly { readonly request: HapticRequest; readonly trigger: HapticTrigger }[]\n}\n\n/** `GradientDirection` → expo-linear-gradient start/end points. */\nconst DIRECTION_POINTS: Record<GradientDirection, { start: GradientPoint; end: GradientPoint }> = {\n 'to-t': { start: { x: 0.5, y: 1 }, end: { x: 0.5, y: 0 } },\n 'to-b': { start: { x: 0.5, y: 0 }, end: { x: 0.5, y: 1 } },\n 'to-l': { start: { x: 1, y: 0.5 }, end: { x: 0, y: 0.5 } },\n 'to-r': { start: { x: 0, y: 0.5 }, end: { x: 1, y: 0.5 } },\n 'to-tl': { start: { x: 1, y: 1 }, end: { x: 0, y: 0 } },\n 'to-tr': { start: { x: 0, y: 1 }, end: { x: 1, y: 0 } },\n 'to-bl': { start: { x: 1, y: 0 }, end: { x: 0, y: 1 } },\n 'to-br': { start: { x: 0, y: 0 }, end: { x: 1, y: 1 } },\n unknown: { start: { x: 0, y: 0.5 }, end: { x: 1, y: 0.5 } },\n}\n\n/**\n * Register one scheme's pre-merged molecules (atom-merged literal\n * classNames). REPLACES the scheme's map — each generated scheme file emits a\n * single `registerMolecules(scheme, …)` carrying the complete molecule set\n * (mirrors `registerAtoms`). Merging instead would leak molecules removed in a\n * Fast Refresh edit, so a deleted/renamed className would keep resolving to its\n * stale pre-edit style.\n * @param scheme Scheme name (or `'common'`).\n * @param entries Normalized className → merged style object.\n */\nexport function registerMolecules(scheme: string, entries: Record<string, unknown>): void {\n molecules[scheme] = entries\n registryVersion += 1\n}\n\n/**\n * Register the gradient atom map (atom name → role + resolved colour).\n * @param map Atom name → gradient info.\n */\nexport function registerGradients(map: Record<string, GradientAtomInfo>): void {\n gradients = map\n registryVersion += 1\n}\n\n/**\n * Register the haptic atom map (atom name → request).\n * @param map Atom name → haptic request.\n */\nexport function registerHaptics(map: Record<string, HapticRequest>): void {\n haptics = map\n registryVersion += 1\n}\n\n\n\n/**\n * Per-state-object signature memo. `RnwindState` is created fresh (via the\n * provider's `useMemo`) whenever any field changes, so its identity is a\n * sound key — a new object means a new signature. Keyed weakly so states\n * GC with their provider.\n */\nconst stateSignatureCache = new WeakMap<RnwindState, string>()\n\n/**\n * Cache key dimension for the reactive context — everything that can\n * change a resolved style. Uses the numeric breakpoint TIER (count of\n * thresholds reached) from `breakpointTier(windowWidth)`, NOT the\n * `activeBreakpoint` NAME: the name clamps tier-0 into the smallest\n * breakpoint, so widths straddling that threshold (e.g. 320 vs 700 with\n * `sm=640`) would collide on one cache key and serve a stale style. The\n * tier is exact AND bounded — two widths in the same tier gate every\n * `sm:`/`md:`/… atom identically, so they resolve the same.\n * @param state Rnwind context.\n * @returns Compact signature string.\n */\nfunction stateSignature(state: RnwindState): string {\n const { insets } = state\n return `${state.scheme}|${insets.top},${insets.right},${insets.bottom},${insets.left}|${state.fontScale}|${breakpointTier(state.windowWidth)}`\n}\n\n/**\n * Memoised {@link stateSignature} — one `WeakMap.get` on the hot path\n * instead of rebuilding the template string every resolve.\n * @param state Rnwind context.\n * @returns Cached compact signature.\n */\nfunction stateSignatureCached(state: RnwindState): string {\n let signature = stateSignatureCache.get(state)\n if (signature === undefined) {\n signature = stateSignature(state)\n stateSignatureCache.set(state, signature)\n }\n return signature\n}\n\n/**\n * Compact signature of the live interactive state for the cache key.\n * @param interactState Active/focus flags, or undefined for the plain path.\n * @returns Two-bit signature (`''` when no interactive state).\n */\nfunction interactSignature(interactState?: InteractState): string {\n if (!interactState) return ''\n const active = interactState.active ? 1 : 0\n const focus = interactState.focus ? 1 : 0\n return `${active}${focus}`\n}\n\n/**\n * Whether a token is a feature-ONLY utility (gradient stop/direction,\n * haptic request, or text-truncate) that contributes NO RN `style`. These\n * are folded in via {@link attachFeatures}, so they must be kept OUT of\n * the `lookupCss` input — otherwise the atom resolver treats them as\n * unknown style atoms and emits a spurious \"unknown class\" dev warning\n * (e.g. for `active:haptic-rigid`).\n * @param token Atom name.\n * @returns True when the token carries no style.\n */\nfunction isFeatureOnlyToken(token: string): boolean {\n return Boolean(gradients[token]) || Boolean(haptics[token]) || truncateForToken(token) !== null\n}\n\n/**\n * Lifecycle trigger for a haptic atom from its variant prefix.\n * @param token Atom name (maybe `active:`/`focus:`/`hover:` prefixed).\n * @returns The trigger.\n */\nfunction hapticTriggerForToken(token: string): HapticTrigger {\n const colon = token.indexOf(':')\n if (colon === -1) return 'mount'\n const prefix = token.slice(0, colon)\n if (prefix === 'active') return 'pressIn'\n if (prefix === 'focus') return 'focus'\n if (prefix === 'hover') return 'hover'\n return 'mount'\n}\n\n/**\n * Syntactic text-truncate directive for one atom.\n * @param token Atom name.\n * @returns Partial truncate props, or null.\n */\nfunction truncateForToken(token: string): { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } | null {\n if (token === 'truncate') return { numberOfLines: 1, ellipsizeMode: 'tail' }\n if (token === 'text-ellipsis') return { ellipsizeMode: 'tail' }\n if (token === 'text-clip') return { ellipsizeMode: 'clip' }\n if (token === 'line-clamp-none') return { numberOfLines: 0 }\n if (token.startsWith('line-clamp-')) {\n const count = Number(token.slice('line-clamp-'.length))\n if (Number.isInteger(count) && count >= 0) return { numberOfLines: count }\n }\n return null\n}\n\n/**\n * Assemble gradient props from gradient roles present in the atom list.\n * @param tokens Atom names.\n * @returns `{colors, start, end}` or null when not a complete gradient.\n */\nfunction assembleGradient(tokens: readonly string[]): { colors: string[]; start: GradientPoint; end: GradientPoint } | null {\n let from: string | undefined\n let via: string | undefined\n let to: string | undefined\n let dir: GradientDirection | undefined\n for (const token of tokens) {\n const info = gradients[token]\n if (!info) continue\n switch (info.role) {\n case 'from': {\n from = info.color\n break\n }\n case 'via': {\n via = info.color\n break\n }\n case 'to': {\n to = info.color\n break\n }\n default: {\n ;({ dir } = info)\n }\n }\n }\n if (dir === undefined) return null\n const colors = [from, via, to].filter((color): color is string => color !== undefined)\n if (colors.length < 2) return null\n const points = DIRECTION_POINTS[dir]\n return { colors, start: points.start, end: points.end }\n}\n\n/**\n * Fold every truncate directive across the atom list into one result —\n * last token wins per prop (matches Tailwind last-wins).\n * @param tokens Atom names.\n * @returns Merged truncate props (empty when none apply).\n */\nfunction collectTruncate(tokens: readonly string[]): { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } {\n const out: { numberOfLines?: number; ellipsizeMode?: 'tail' | 'clip' } = {}\n for (const token of tokens) {\n const truncate = truncateForToken(token)\n if (!truncate) continue\n if (truncate.numberOfLines !== undefined) out.numberOfLines = truncate.numberOfLines\n if (truncate.ellipsizeMode !== undefined) out.ellipsizeMode = truncate.ellipsizeMode\n }\n return out\n}\n\n/**\n * Collect every haptic request present in the atom list, tagged with the\n * lifecycle trigger its variant prefix implies.\n * @param tokens Atom names.\n * @returns Haptic request list, or undefined when none apply.\n */\nfunction collectHaptics(tokens: readonly string[]): { request: HapticRequest; trigger: HapticTrigger }[] | undefined {\n let collected: { request: HapticRequest; trigger: HapticTrigger }[] | undefined\n for (const token of tokens) {\n const request = haptics[token]\n if (!request) continue\n collected ??= []\n collected.push({ request, trigger: hapticTriggerForToken(token) })\n }\n return collected\n}\n\n/**\n * Scan tokens for the className-derived feature props (gradient,\n * truncate, haptics) and fold them onto the base result.\n * @param base Result carrying the resolved `style`.\n * @param tokens Atom names.\n * @returns The result with any feature props attached.\n */\nfunction attachFeatures(base: ResolvedCss, tokens: readonly string[]): ResolvedCss {\n const { numberOfLines, ellipsizeMode } = collectTruncate(tokens)\n const collected = collectHaptics(tokens)\n const gradient = assembleGradient(tokens)\n const result: Mutable<ResolvedCss> = { style: base.style }\n if (gradient) {\n result.colors = gradient.colors\n result.start = gradient.start\n result.end = gradient.end\n }\n // `numberOfLines: 0` is kept (RN reads it as \"unlimited\"): `line-clamp-none`\n // must be able to explicitly reset an earlier `line-clamp-N` on the same\n // element — dropping the 0 would silently leave the prior limit in place.\n if (numberOfLines !== undefined) {\n result.numberOfLines = numberOfLines\n if (ellipsizeMode !== undefined) result.ellipsizeMode = ellipsizeMode\n }\n if (collected) result.haptics = collected\n return result\n}\n\n/**\n * Flatten the per-atom style array into ONE object — a *runtime molecule*.\n * RN flattens a style array left-to-right (later wins), which is exactly\n * `Object.assign` semantics, so the merged object renders identically\n * while giving dynamic (cva / clsx) classNames the same single-object\n * shape a build-time molecule has. The caller caches the result per\n * `(className · state)`, so the merge runs once per unique context.\n * @param array Per-atom style array from `lookupCss`.\n * @returns Single merged style object.\n */\nfunction mergeStyleArray(array: readonly unknown[]): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const entry of array) if (entry && typeof entry === 'object') Object.assign(out, entry)\n return out\n}\n\n/**\n * Compose a resolved style with a caller-supplied inline style (user wins).\n * @param style\n * @param userStyle\n */\nfunction withUserStyle(style: unknown, userStyle: unknown): unknown {\n return Array.isArray(style) ? [...style, userStyle] : [style, userStyle]\n}\n\n/**\n * Resolve a className against the reactive context into a style plus any\n * className-derived props. Molecule-first (one lookup, by reference),\n * atom-fallback for unseen / context-dependent strings, cached per\n * `(className, state)`.\n * @param className Raw className string.\n * @param state Rnwind context from `useRnwind()`.\n * @param userStyle Optional inline style appended last (wins).\n * @param interactState Live active/focus flags (for `active:`/`focus:` atoms).\n * @returns The resolved style + feature props.\n */\nexport function resolve(\n className: string | null | undefined,\n state: RnwindState,\n userStyle?: unknown,\n interactState?: InteractState,\n): ResolvedCss {\n const version = getStyleVersion() + registryVersion\n if (version !== cachedFor) {\n resolvedCache.clear()\n cachedFor = version\n }\n if (className == null) {\n return { style: userStyle === undefined || userStyle === null ? EMPTY : [userStyle] }\n }\n // Key on the RAW className so the hot (cache-hit) path skips normalize\n // entirely — normalization only runs on a miss. The state signature is\n // memoised per state object, so the hit path is one WeakMap.get + one\n // string concat + one Map.get.\n const key = `${className}@${stateSignatureCached(state)}@${interactSignature(interactState)}`\n const cached = resolvedCache.get(key)\n if (cached !== undefined) {\n return userStyle === undefined || userStyle === null ? cached : { ...cached, style: withUserStyle(cached.style, userStyle) }\n }\n const normalized = normalizeClassName(className)\n if (normalized.length === 0) {\n const empty: ResolvedCss = { style: EMPTY }\n cacheResolved(key, empty)\n return userStyle === undefined || userStyle === null ? empty : { style: [userStyle] }\n }\n // Molecules are static pre-merges; anything carrying `active:`/`focus:`\n // is never registered as one, so the atom path handles interactive state.\n const tokens = normalized.split(' ')\n const molecule = interactState ? undefined : molecules[state.scheme]?.[normalized] ?? molecules[COMMON_SCHEME]?.[normalized]\n // Feature-only tokens (gradient / haptic / truncate) carry no style — keep\n // them out of the atom lookup so they don't warn as \"unknown class\". The\n // atom array is merged into ONE object (a runtime molecule) so dynamic\n // (cva / clsx) classNames get the same single-object shape as a build\n // molecule; the cache below pins the context, so the merge is correct.\n const style =\n molecule === undefined\n ? mergeStyleArray(lookupCss(tokens.filter((token) => !isFeatureOnlyToken(token)).join(' '), state, undefined, interactState))\n : molecule\n const base = attachFeatures({ style }, tokens)\n cacheResolved(key, base)\n return userStyle === undefined || userStyle === null ? base : { ...base, style: withUserStyle(base.style, userStyle) }\n}\n\n/** Local mutable view for building the frozen-shaped result. */\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] }\n\n/** Test-only — clear the molecule / gradient / haptic registries + cache. */\nexport function __resetResolveState(): void {\n molecules = Object.create(null)\n gradients = Object.create(null)\n haptics = Object.create(null)\n resolvedCache.clear()\n registryVersion += 1\n cachedFor = -1\n}\n\n/** Test-only — current resolved-cache entry count + its hard ceiling. */\nexport function __resolveCacheStats(): { size: number; max: number } {\n return { size: resolvedCache.size, max: MAX_RESOLVED_CACHE }\n}\n\nexport {normalizeClassName} from '../core/normalize-classname'"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnwind",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "Tailwind for React Native",
5
5
  "author": "https://github.com/sagltd",
6
6
  "license": "MIT",
@@ -1,3 +1,6 @@
1
+ /** Whitespace run splitter — hoisted so the runtime hot path doesn't recreate it per call. */
2
+ const WHITESPACE = /\s+/
3
+
1
4
  /**
2
5
  * Normalize a className for molecule keying: trim, collapse runs of
3
6
  * whitespace, and drop exact-duplicate tokens — but PRESERVE ORDER.
@@ -10,7 +13,7 @@
10
13
  export function normalizeClassName(className: string): string {
11
14
  const seen = new Set<string>()
12
15
  const out: string[] = []
13
- for (const token of className.trim().split(/\s+/)) {
16
+ for (const token of className.trim().split(WHITESPACE)) {
14
17
  if (token.length === 0 || seen.has(token)) continue
15
18
  seen.add(token)
16
19
  out.push(token)
@@ -1,21 +1,32 @@
1
1
  import type { Declaration as LcDeclaration } from 'lightningcss'
2
2
  import { kebabToCamel } from './case-convert'
3
- import { cssColorToString } from './color'
3
+ import { cssColorToString, isCssWideColorKeyword } from './color'
4
4
  import type { RNEntry } from './types'
5
5
 
6
6
  /**
7
- * Build an inline-color pair from a `{start, end}`-shaped value.
7
+ * Build a single border-side color entry, dropping CSS-wide cascade keywords
8
+ * (`currentColor`, `inherit`, …) — RN has no color cascade, so the keyword
9
+ * would reach the native view manager as an invalid color.
10
+ * @param key RN side key (e.g. `borderLeftColor`).
11
+ * @param value Typed `CssColor` value.
12
+ * @returns One RN entry, or empty when the value is a cascade keyword.
13
+ */
14
+ function colorSide(key: string, value: unknown): readonly RNEntry[] {
15
+ const color = cssColorToString(value as never)
16
+ return isCssWideColorKeyword(color) ? [] : [[key, color]]
17
+ }
18
+
19
+ /**
20
+ * Build an inline-color pair from a `{start, end}`-shaped value. Each side
21
+ * drops independently when it resolves to a CSS-wide cascade keyword.
8
22
  * @param leftKey RN key for the start side.
9
23
  * @param rightKey RN key for the end side.
10
24
  * @param value Typed `{start, end}` color value.
11
- * @returns Two RN entries.
25
+ * @returns Up to two RN entries (cascade-keyword sides omitted).
12
26
  */
13
27
  function colorPair(leftKey: string, rightKey: string, value: unknown): readonly RNEntry[] {
14
28
  const tagged = value as { start?: unknown; end?: unknown }
15
- return [
16
- [leftKey, cssColorToString(tagged.start as never)],
17
- [rightKey, cssColorToString(tagged.end as never)],
18
- ]
29
+ return [...colorSide(leftKey, tagged.start), ...colorSide(rightKey, tagged.end)]
19
30
  }
20
31
 
21
32
  /**
@@ -114,16 +125,16 @@ export function dispatchBorderDeclaration(decl: LcDeclaration): readonly RNEntry
114
125
  return colorPair('borderTopColor', 'borderBottomColor', decl.value)
115
126
  }
116
127
  case 'border-inline-start-color': {
117
- return [['borderLeftColor', cssColorToString(decl.value)]]
128
+ return colorSide('borderLeftColor', decl.value)
118
129
  }
119
130
  case 'border-inline-end-color': {
120
- return [['borderRightColor', cssColorToString(decl.value)]]
131
+ return colorSide('borderRightColor', decl.value)
121
132
  }
122
133
  case 'border-block-start-color': {
123
- return [['borderTopColor', cssColorToString(decl.value)]]
134
+ return colorSide('borderTopColor', decl.value)
124
135
  }
125
136
  case 'border-block-end-color': {
126
- return [['borderBottomColor', cssColorToString(decl.value)]]
137
+ return colorSide('borderBottomColor', decl.value)
127
138
  }
128
139
  case 'border-width': {
129
140
  return borderWidthShorthand(decl.value)
@@ -1,19 +1,21 @@
1
1
  import type { Declaration as LcDeclaration } from 'lightningcss'
2
- import { cssColorToString } from './color'
2
+ import { cssColorToString, isCssWideColorKeyword } from './color'
3
3
  import type { RNEntry } from './types'
4
4
 
5
5
  /**
6
- * Build a `[key, hex]` entry from a typed CssColor. Drops keyword colors
7
- * (e.g. `'currentcolor'` strings — RN can't render them).
6
+ * Build a `[key, hex]` entry from a typed CssColor. Drops CSS-wide cascade
7
+ * keywords (`currentColor`, `inherit`, `initial`, `unset`, `revert`,
8
+ * `revert-layer`) — RN has no color cascade, so those reach the native view
9
+ * manager as invalid color strings.
8
10
  * @param key RN style key (camelCase).
9
11
  * @param value Typed `CssColor`-shaped value.
10
12
  * @returns Single-entry list or empty.
11
13
  */
12
14
  function colorEntry(key: string, value: unknown): readonly RNEntry[] {
13
15
  if (value === null || value === undefined) return []
14
- if (typeof value === 'string') return [[key, value]]
16
+ if (typeof value === 'string') return isCssWideColorKeyword(value) ? [] : [[key, value]]
15
17
  const hex = cssColorToString(value as never)
16
- if (!hex || hex === 'transparent' || hex === 'currentColor') return [[key, hex]]
18
+ if (isCssWideColorKeyword(hex)) return []
17
19
  return [[key, hex]]
18
20
  }
19
21