rnwind 0.0.7 → 0.0.9

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 (131) hide show
  1. package/lib/cjs/core/parser/color.cjs +33 -1
  2. package/lib/cjs/core/parser/color.cjs.map +1 -1
  3. package/lib/cjs/core/parser/color.d.ts +10 -0
  4. package/lib/cjs/core/parser/declaration.cjs +161 -10
  5. package/lib/cjs/core/parser/declaration.cjs.map +1 -1
  6. package/lib/cjs/core/parser/gradient.cjs +46 -12
  7. package/lib/cjs/core/parser/gradient.cjs.map +1 -1
  8. package/lib/cjs/core/parser/gradient.d.ts +2 -1
  9. package/lib/cjs/core/parser/keyframes.cjs +27 -12
  10. package/lib/cjs/core/parser/keyframes.cjs.map +1 -1
  11. package/lib/cjs/core/parser/keyframes.d.ts +11 -0
  12. package/lib/cjs/core/parser/layout-dispatcher.cjs +33 -10
  13. package/lib/cjs/core/parser/layout-dispatcher.cjs.map +1 -1
  14. package/lib/cjs/core/parser/length.cjs +17 -1
  15. package/lib/cjs/core/parser/length.cjs.map +1 -1
  16. package/lib/cjs/core/parser/safe-area.cjs +24 -3
  17. package/lib/cjs/core/parser/safe-area.cjs.map +1 -1
  18. package/lib/cjs/core/parser/theme-vars.cjs +58 -8
  19. package/lib/cjs/core/parser/theme-vars.cjs.map +1 -1
  20. package/lib/cjs/core/parser/tokens.cjs +77 -9
  21. package/lib/cjs/core/parser/tokens.cjs.map +1 -1
  22. package/lib/cjs/core/parser/tokens.d.ts +9 -0
  23. package/lib/cjs/core/parser/transform.cjs +18 -9
  24. package/lib/cjs/core/parser/transform.cjs.map +1 -1
  25. package/lib/cjs/core/parser/tw-parser.cjs +93 -33
  26. package/lib/cjs/core/parser/tw-parser.cjs.map +1 -1
  27. package/lib/cjs/core/parser/typography-dispatcher.cjs +19 -1
  28. package/lib/cjs/core/parser/typography-dispatcher.cjs.map +1 -1
  29. package/lib/cjs/core/parser/typography.cjs +15 -18
  30. package/lib/cjs/core/parser/typography.cjs.map +1 -1
  31. package/lib/cjs/core/parser/typography.d.ts +5 -5
  32. package/lib/cjs/core/style-builder/union-builder.cjs +0 -10
  33. package/lib/cjs/core/style-builder/union-builder.cjs.map +1 -1
  34. package/lib/cjs/core/style-builder/union-builder.d.ts +0 -8
  35. package/lib/cjs/metro/dts.cjs +6 -1
  36. package/lib/cjs/metro/dts.cjs.map +1 -1
  37. package/lib/cjs/metro/transformer.cjs +43 -60
  38. package/lib/cjs/metro/transformer.cjs.map +1 -1
  39. package/lib/cjs/metro/with-config.cjs +9 -29
  40. package/lib/cjs/metro/with-config.cjs.map +1 -1
  41. package/lib/cjs/runtime/hooks/use-scheme.cjs +9 -6
  42. package/lib/cjs/runtime/hooks/use-scheme.cjs.map +1 -1
  43. package/lib/cjs/runtime/hooks/use-scheme.d.ts +7 -4
  44. package/lib/cjs/runtime/index.cjs +1 -1
  45. package/lib/cjs/runtime/index.cjs.map +1 -1
  46. package/lib/cjs/runtime/index.d.ts +1 -1
  47. package/lib/cjs/runtime/lookup-css.cjs +14 -0
  48. package/lib/cjs/runtime/lookup-css.cjs.map +1 -1
  49. package/lib/cjs/runtime/lookup-css.d.ts +11 -0
  50. package/lib/cjs/runtime/resolve.cjs +8 -6
  51. package/lib/cjs/runtime/resolve.cjs.map +1 -1
  52. package/lib/cjs/runtime/wrap.cjs +50 -57
  53. package/lib/cjs/runtime/wrap.cjs.map +1 -1
  54. package/lib/cjs/runtime/wrap.d.ts +10 -4
  55. package/lib/esm/core/parser/color.d.ts +10 -0
  56. package/lib/esm/core/parser/color.mjs +33 -2
  57. package/lib/esm/core/parser/color.mjs.map +1 -1
  58. package/lib/esm/core/parser/declaration.mjs +162 -11
  59. package/lib/esm/core/parser/declaration.mjs.map +1 -1
  60. package/lib/esm/core/parser/gradient.d.ts +2 -1
  61. package/lib/esm/core/parser/gradient.mjs +45 -11
  62. package/lib/esm/core/parser/gradient.mjs.map +1 -1
  63. package/lib/esm/core/parser/keyframes.d.ts +11 -0
  64. package/lib/esm/core/parser/keyframes.mjs +27 -12
  65. package/lib/esm/core/parser/keyframes.mjs.map +1 -1
  66. package/lib/esm/core/parser/layout-dispatcher.mjs +33 -10
  67. package/lib/esm/core/parser/layout-dispatcher.mjs.map +1 -1
  68. package/lib/esm/core/parser/length.mjs +17 -1
  69. package/lib/esm/core/parser/length.mjs.map +1 -1
  70. package/lib/esm/core/parser/safe-area.mjs +24 -3
  71. package/lib/esm/core/parser/safe-area.mjs.map +1 -1
  72. package/lib/esm/core/parser/theme-vars.mjs +58 -8
  73. package/lib/esm/core/parser/theme-vars.mjs.map +1 -1
  74. package/lib/esm/core/parser/tokens.d.ts +9 -0
  75. package/lib/esm/core/parser/tokens.mjs +77 -10
  76. package/lib/esm/core/parser/tokens.mjs.map +1 -1
  77. package/lib/esm/core/parser/transform.mjs +18 -9
  78. package/lib/esm/core/parser/transform.mjs.map +1 -1
  79. package/lib/esm/core/parser/tw-parser.mjs +95 -35
  80. package/lib/esm/core/parser/tw-parser.mjs.map +1 -1
  81. package/lib/esm/core/parser/typography-dispatcher.mjs +19 -1
  82. package/lib/esm/core/parser/typography-dispatcher.mjs.map +1 -1
  83. package/lib/esm/core/parser/typography.d.ts +5 -5
  84. package/lib/esm/core/parser/typography.mjs +15 -18
  85. package/lib/esm/core/parser/typography.mjs.map +1 -1
  86. package/lib/esm/core/style-builder/union-builder.d.ts +0 -8
  87. package/lib/esm/core/style-builder/union-builder.mjs +0 -10
  88. package/lib/esm/core/style-builder/union-builder.mjs.map +1 -1
  89. package/lib/esm/metro/dts.mjs +6 -1
  90. package/lib/esm/metro/dts.mjs.map +1 -1
  91. package/lib/esm/metro/transformer.mjs +43 -60
  92. package/lib/esm/metro/transformer.mjs.map +1 -1
  93. package/lib/esm/metro/with-config.mjs +10 -30
  94. package/lib/esm/metro/with-config.mjs.map +1 -1
  95. package/lib/esm/runtime/hooks/use-scheme.d.ts +7 -4
  96. package/lib/esm/runtime/hooks/use-scheme.mjs +9 -6
  97. package/lib/esm/runtime/hooks/use-scheme.mjs.map +1 -1
  98. package/lib/esm/runtime/index.d.ts +1 -1
  99. package/lib/esm/runtime/index.mjs +1 -1
  100. package/lib/esm/runtime/index.mjs.map +1 -1
  101. package/lib/esm/runtime/lookup-css.d.ts +11 -0
  102. package/lib/esm/runtime/lookup-css.mjs +14 -1
  103. package/lib/esm/runtime/lookup-css.mjs.map +1 -1
  104. package/lib/esm/runtime/resolve.mjs +9 -7
  105. package/lib/esm/runtime/resolve.mjs.map +1 -1
  106. package/lib/esm/runtime/wrap.d.ts +10 -4
  107. package/lib/esm/runtime/wrap.mjs +50 -57
  108. package/lib/esm/runtime/wrap.mjs.map +1 -1
  109. package/package.json +1 -1
  110. package/src/core/parser/color.ts +32 -1
  111. package/src/core/parser/declaration.ts +160 -10
  112. package/src/core/parser/gradient.ts +48 -11
  113. package/src/core/parser/keyframes.ts +31 -3
  114. package/src/core/parser/layout-dispatcher.ts +32 -9
  115. package/src/core/parser/length.ts +18 -1
  116. package/src/core/parser/safe-area.ts +23 -2
  117. package/src/core/parser/theme-vars.ts +75 -8
  118. package/src/core/parser/tokens.ts +76 -9
  119. package/src/core/parser/transform.ts +19 -8
  120. package/src/core/parser/tw-parser.ts +95 -30
  121. package/src/core/parser/typography-dispatcher.ts +20 -1
  122. package/src/core/parser/typography.ts +15 -15
  123. package/src/core/style-builder/union-builder.ts +0 -11
  124. package/src/metro/dts.ts +6 -1
  125. package/src/metro/transformer.ts +45 -61
  126. package/src/metro/with-config.ts +10 -29
  127. package/src/runtime/hooks/use-scheme.ts +9 -6
  128. package/src/runtime/index.ts +1 -1
  129. package/src/runtime/lookup-css.ts +14 -0
  130. package/src/runtime/resolve.ts +9 -7
  131. package/src/runtime/wrap.tsx +57 -61
@@ -1 +1 @@
1
- {"version":3,"file":"transformer.cjs","sources":["../../../../src/metro/transformer.ts"],"sourcesContent":["import type { File } from '@babel/types'\nimport * as t from '@babel/types'\nimport { parse } from '@babel/parser'\nimport generate from '@babel/generator'\nimport { createHash } from 'node:crypto'\nimport { realpathSync } from 'node:fs'\nimport { getRnwindCacheKey, getRnwindState, getWrapModules, onThemeChange } from './state'\nimport { rewriteWrapImports } from './wrap-imports'\nimport { STYLE_SPECIFIERS, THEME_SIGNATURE_MODULE } from './resolver'\nimport { filterUnknownClassCandidates } from './warn-unknown-classes'\n\n/** The shape of the upstream module we delegate parsing/babel work to. */\ninterface UpstreamTransformer {\n transform: (args: BabelTransformerArgs) => Promise<BabelTransformerResult> | BabelTransformerResult\n}\n\n/** Env var that points at the upstream `babelTransformerPath` we override. */\nconst UPSTREAM_ENV = 'RNWIND_UPSTREAM_TRANSFORMER'\n\n/** Cached upstream module — required once, reused across every transform call. */\nlet cachedUpstream: UpstreamTransformer | null = null\n\nconst generateModule = (generate as unknown as { default?: typeof generate }).default ?? generate\n\n/**\n * Parse user source with the broad plugin set (Flow + JSX + TypeScript\n * + class properties). Permissive on purpose so we don't reject any\n * file the upstream could have handled. Returns `null` when parse\n * fails — caller falls back to the raw source string.\n * @param source Source text.\n * @returns Parsed AST, or null on parse failure.\n */\nfunction parseUserSource(source: string): File | null {\n try {\n return parse(source, {\n sourceType: 'unambiguous',\n allowReturnOutsideFunction: true,\n allowImportExportEverywhere: true,\n plugins: ['typescript', 'jsx'],\n }) as unknown as File\n } catch {\n try {\n return parse(source, {\n sourceType: 'unambiguous',\n allowReturnOutsideFunction: true,\n allowImportExportEverywhere: true,\n plugins: ['flow', 'jsx'],\n }) as unknown as File\n } catch {\n return null\n }\n }\n}\n\n/**\n * Print Tailwind-shaped candidates oxide picked up but the parser\n * could NOT compile — typo, missing custom utility, or class not in\n * the user's theme. Filtering by candidates that ALSO appear inside a\n * `className=\"…\"` literal eliminates false positives from imports,\n * comments, and JSX prop values.\n * @param source Original source text — searched for className literals.\n * @param candidates Every candidate oxide surfaced from the source.\n * @param atoms Successfully resolved atoms (keys are class names).\n * @param filename Source path, prefixed onto the warning.\n * @param features Feature-atom maps (gradient / haptic) — their names are\n * known classes even though they carry no RN style, so they're excluded\n * from the unknown-class warning.\n */\nfunction warnUnknownClasses(\n source: string,\n candidates: readonly string[],\n atoms: ReadonlyMap<string, unknown>,\n filename: string,\n features: ReadonlyArray<ReadonlyMap<string, unknown>> = [],\n): void {\n // Feature atoms (gradient / haptic) resolve to no RN style, so they're\n // absent from `atoms` — but they're NOT unknown. Fold their names into\n // the known set so `active:haptic-rigid` etc. don't warn at build time.\n const known = new Set(atoms.keys())\n for (const map of features) for (const name of map.keys()) known.add(name)\n const unknown = filterUnknownClassCandidates(source, candidates, known)\n if (unknown.length === 0) return\n // eslint-disable-next-line no-console\n console.warn(`rnwind: unknown class${unknown.length > 1 ? 'es' : ''} in ${filename}: ${unknown.join(', ')}`)\n}\n\n/**\n * Extract the bare extension for oxide / internal switches.\n * @param filename Absolute path.\n * @returns Extension without the leading dot (`tsx` / `ts` / `js` / `jsx`).\n */\nfunction extensionOf(filename: string): string {\n const index = filename.lastIndexOf('.')\n if (index === -1) return 'tsx'\n return filename.slice(index + 1)\n}\n\n/**\n * Read the project root Metro hands us per-transform. Falls back to\n * `process.cwd()` only when the upstream harness doesn't set it (unit\n * tests, standalone). Metro's production pipeline always sets it.\n * @param args Metro transformer args.\n * @returns Absolute project root.\n */\nfunction projectRootOf(args: BabelTransformerArgs): string {\n const fromOptions = args.options?.projectRoot\n if (typeof fromOptions === 'string' && fromOptions.length > 0) return fromOptions\n return process.cwd()\n}\n\n/**\n * Whether a `.css` filename is the user's theme entry (the file\n * `withRnwindConfig` pointed us at via `RNWIND_CSS_ENTRY_FILE`).\n * Only the theme CSS should trigger a scheme rebuild — unrelated CSS\n * files in the project stay invisible to rnwind.\n * @param filename Absolute CSS path.\n * @returns Whether the file is the configured theme entry.\n */\nfunction isThemeCssEntry(filename: string): boolean {\n const cssEntry = process.env.RNWIND_CSS_ENTRY_FILE\n return typeof cssEntry === 'string' && cssEntry.length > 0 && cssEntry === filename\n}\n\n/**\n * Wrap host imports + compile any className literals, then regenerate\n * source. Two paths:\n * - **className present**: oxide-scan the file, record its atoms into\n * the union, and inject the generated-style + theme-signature\n * side-effect imports so the runtime registries populate.\n * - **import-only** (a `{...rest}` forwarder or a leaf with no literal\n * `className=`): just wrap the host imports so a forwarded className\n * still resolves at render — no oxide scan, no injected imports.\n *\n * On parse failure, fall back to the original source — a transient parse\n * error shouldn't crash Metro for a file the upstream might handle fine.\n * @param args Metro args; `src` is the original source text.\n * @returns Rewritten source text.\n */\nasync function rewriteSource(args: BabelTransformerArgs): Promise<string> {\n const ast = parseUserSource(args.src)\n if (!ast) return args.src\n\n // Wrap host component imports so `<View className=…>` resolves at render\n // through the runtime `wrap` (works for literal, spread, and forwarded\n // classNames alike). No JSX is rewritten here.\n const wrapped = rewriteWrapImports(ast, getWrapModules())\n\n if (!/classname=/i.test(args.src)) {\n // Import-only file: nothing to compile. Drop any stale atom\n // contribution (className may have just been removed) and emit the\n // wrapped imports — or the untouched source when nothing wrapped.\n dropFileSafely(args.filename, projectRootOf(args))\n return wrapped ? generateModule(ast).code : args.src\n }\n\n const state = getRnwindState(projectRootOf(args))\n const extension = extensionOf(args.filename)\n const parsed = await state.parser.parseAtoms({ content: args.src, extension })\n\n warnUnknownClasses(args.src, parsed.candidates, parsed.atoms, args.filename, [parsed.gradientAtoms, parsed.hapticAtoms])\n\n if (parsed.atoms.size === 0) {\n state.builder.dropFile(args.filename)\n await state.builder.writeSchemes()\n injectThemeSignatureImport(ast)\n return generateModule(ast).code\n }\n\n const literals = collectClassNameLiterals(ast)\n const { changed } = await state.builder.recordFile(args.filename, parsed.atoms, parsed.keyframes, literals)\n if (changed) await state.builder.writeSchemes()\n\n injectSideEffectImports(ast, STYLE_SPECIFIERS)\n injectThemeSignatureImport(ast)\n return generateModule(ast).code\n}\n\n/**\n * Drop a file's union contribution, swallowing the \"state not configured\"\n * error unit tests hit when they call the transformer without\n * `configureRnwindState`.\n * @param filename Absolute source path.\n * @param projectRoot Project root for state lookup.\n */\nfunction dropFileSafely(filename: string, projectRoot: string): void {\n try {\n getRnwindState(projectRoot).builder.dropFile(filename)\n } catch {\n // State not configured (standalone/unit test). Nothing to drop.\n }\n}\n\n/**\n * Whether a JSX attribute names a className-style prop (`className` or\n * any `<prefix>ClassName`).\n * @param node JSX attribute node.\n * @returns True when the attribute is a className prop.\n */\nfunction isClassNameAttribute(node: t.JSXAttribute): boolean {\n if (!t.isJSXIdentifier(node.name)) return false\n const {name} = node.name\n return name === 'className' || name.endsWith('ClassName')\n}\n\n/**\n * Pull static string literals out of a className expression. Handles a\n * bare string, a no-substitution template, and the branches of a\n * ternary / `&&` (so `cond ? 'a' : 'b'` and `flag && 'x'` both register\n * their literals). Dynamic interpolations are skipped — they resolve via\n * the runtime atom path.\n * @param expr Expression inside a `className={...}` container.\n * @param out Accumulator for discovered literals.\n */\nfunction collectLiteralsFromExpression(expr: t.Expression | t.JSXEmptyExpression | null | undefined, out: string[]): void {\n if (!expr) return\n if (t.isStringLiteral(expr)) {\n out.push(expr.value)\n return\n }\n if (t.isTemplateLiteral(expr) && expr.expressions.length === 0 && expr.quasis.length === 1) {\n const cooked = expr.quasis[0]?.value.cooked\n if (typeof cooked === 'string') out.push(cooked)\n return\n }\n if (t.isConditionalExpression(expr)) {\n collectLiteralsFromExpression(expr.consequent, out)\n collectLiteralsFromExpression(expr.alternate, out)\n return\n }\n if (t.isLogicalExpression(expr)) {\n collectLiteralsFromExpression(expr.right as t.Expression, out)\n }\n}\n\n/** AST node keys the literal walk skips — position / comment metadata. */\nconst SKIP_WALK_KEYS = new Set(['type', 'loc', 'start', 'end', 'range', 'leadingComments', 'trailingComments', 'innerComments'])\n\n/**\n * Collect the static literals from one className JSX attribute into the\n * dedup accumulator.\n * @param attribute The (already className-matched) JSX attribute.\n * @param seen Dedup set of literals already collected.\n * @param out Ordered accumulator.\n */\nfunction collectAttributeLiterals(attribute: t.JSXAttribute, seen: Set<string>, out: string[]): void {\n const { value } = attribute\n const found: string[] = []\n if (t.isStringLiteral(value)) found.push(value.value)\n else if (t.isJSXExpressionContainer(value)) collectLiteralsFromExpression(value.expression, found)\n for (const literal of found) {\n if (seen.has(literal)) continue\n seen.add(literal)\n out.push(literal)\n }\n}\n\n/**\n * Walk the AST for every `className=` / `<prefix>ClassName=` literal so\n * the builder can pre-merge each into a per-scheme molecule. A generic\n * node walk (no scope build) keeps it cheap; only JSX attribute nodes do\n * any work.\n * @param ast Parsed Babel file.\n * @returns Distinct literal className strings, in first-seen order.\n */\nfunction collectClassNameLiterals(ast: File): readonly string[] {\n const out: string[] = []\n const seen = new Set<string>()\n const visit = (node: unknown): void => {\n if (!node || typeof node !== 'object') return\n if (Array.isArray(node)) {\n for (const child of node) visit(child)\n return\n }\n const typed = node as { type?: string; [key: string]: unknown }\n if (typeof typed.type !== 'string') return\n if (typed.type === 'JSXAttribute' && isClassNameAttribute(node as t.JSXAttribute)) {\n collectAttributeLiterals(node as t.JSXAttribute, seen, out)\n }\n for (const key in typed) {\n if (SKIP_WALK_KEYS.has(key)) continue\n visit(typed[key])\n }\n }\n visit(ast.program)\n return out\n}\n\n/**\n * Prepend side-effect imports (`import '<spec>'`) so the generated\n * per-scheme style + manifest modules load — registering this file's\n * atoms / molecules / features into the runtime registries the wrapper's\n * `resolve` reads.\n * @param ast Babel File AST to mutate in place.\n * @param specifiers Module specifiers to side-effect-import.\n */\nfunction injectSideEffectImports(ast: File, specifiers: readonly string[]): void {\n for (const specifier of specifiers) {\n ast.program.body.unshift(t.importDeclaration([], t.stringLiteral(specifier)))\n }\n}\n\n/**\n * Prepend `import 'rnwind/__generated/theme-signature'` to every\n * rnwind-transformed file. The resolver maps that specifier to the\n * user's theme CSS so Metro's dependency graph carries a real edge\n * from this JS file to the CSS. When the user edits `global.css`,\n * the CSS module's SHA1 changes, and Metro invalidates every JS file\n * holding this import — forcing them to re-transform with the new\n * theme. The `.css` branch in {@link transform} returns an empty\n * `export {}` module so the runtime cost is one extra `require()`.\n * @param ast Babel File AST to mutate in place.\n */\nfunction injectThemeSignatureImport(ast: File): void {\n const declaration = t.importDeclaration([], t.stringLiteral(THEME_SIGNATURE_MODULE))\n ast.program.body.unshift(declaration)\n}\n\n/**\n * Read the upstream transformer's `getCacheKey()` so our cache-key\n * contribution composes with — rather than replaces — whatever the\n * host framework wants to mix in.\n * @returns Upstream cache key, or `null` when no upstream exposes one.\n */\nfunction loadUpstreamCacheKey(): string | null {\n const upstream = loadUpstream() as (UpstreamTransformer & { getCacheKey?: () => string }) | null\n if (!upstream) return null\n try {\n return typeof upstream.getCacheKey === 'function' ? upstream.getCacheKey() : null\n } catch {\n return null\n }\n}\n\n/**\n * Invoke the upstream `babelTransformerPath` Metro originally had\n * configured. The path is read from `RNWIND_UPSTREAM_TRANSFORMER`,\n * which `withRnwindConfig` sets at Metro startup. When the env var is\n * unset (unit tests, standalone use), fall back to a typescript+jsx\n * parse.\n * @param args Metro's per-file args.\n * @returns Upstream transform result containing the post-babel AST.\n */\nasync function runUpstream(args: BabelTransformerArgs): Promise<BabelTransformerResult> {\n if (args.ast && !process.env[UPSTREAM_ENV]) return { ast: args.ast }\n const upstream = loadUpstream()\n if (upstream) return await Promise.resolve(upstream.transform(args))\n if (args.ast) return { ast: args.ast }\n return { ast: parseSource(args.src) }\n}\n\n/**\n * Lazily require the upstream transformer module. Cached after first\n * load so per-file overhead is one cache lookup.\n * @returns Upstream module, or null when env is unset.\n */\nfunction loadUpstream(): UpstreamTransformer | null {\n if (cachedUpstream) return cachedUpstream\n const upstreamPath = process.env[UPSTREAM_ENV]\n if (!upstreamPath || upstreamPath.length === 0) return null\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n const required = require(upstreamPath) as UpstreamTransformer | { default?: UpstreamTransformer }\n const upstream = (required as { default?: UpstreamTransformer }).default ?? (required as UpstreamTransformer)\n if (typeof upstream.transform !== 'function') return null\n cachedUpstream = upstream\n return upstream\n } catch (error) {\n // eslint-disable-next-line no-console\n if (process.env.RNWIND_DEBUG) console.error('rnwind: failed to load upstream transformer:', error)\n return null\n }\n}\n\n/**\n * Cheap guard — the file has to look JS/TS, live outside `node_modules`,\n * and mention `className=` before we spend AST cycles on it.\n *\n * Symlink awareness: monorepo workspaces (yarn / pnpm / bun workspaces)\n * symlink each package into the consumer's `node_modules/<name>`, so a\n * file from `packages/ui/src/Foo.tsx` ends up reaching the transformer\n * as `<root>/node_modules/ui/src/Foo.tsx`. The naïve `/node_modules/`\n * check would skip every workspace UI file. We `realpath` the filename\n * once and only bail when the resolved real path is ALSO under\n * node_modules — true third-party installs.\n * @param args Metro args.\n * @returns Whether the file might need the rnwind pass.\n */\nfunction isRewriteCandidate(args: BabelTransformerArgs): boolean {\n if (!/\\.(?:tsx|ts|jsx|js)$/i.test(args.filename)) return false\n // Process the file when it either:\n // - carries a `className=` / `<prefix>ClassName=` literal (case-\n // insensitive — `contentContainerClassName=` has a capital C), or\n // - spreads props (`{...rest}`) onto a host from a wrap-module, where a\n // forwarded className must still get its import wrapped (no literal\n // appears in this file). A style-less `<View/>` with neither is left\n // alone so it never pays for an unused wrapper.\n const hasClassName = /classname=/i.test(args.src)\n const isForwarder = /\\{\\s*\\.\\.\\./.test(args.src) && mentionsWrapModule(args.src)\n if (!hasClassName && !isForwarder) return false\n if (!args.filename.includes('/node_modules/')) return true\n // node_modules in path → could be a workspace symlink; resolve it.\n try {\n return !realpathSync(args.filename).includes('/node_modules/')\n } catch {\n // realpath failed (broken symlink, missing file). Fall back to skipping.\n return false\n }\n}\n\n/**\n * Cheap pre-parse check: does the source import from any configured\n * wrap-module? A quoted specifier match is enough — `rewriteWrapImports`\n * re-verifies precisely on the AST, so a false positive only costs a\n * no-op parse.\n * @param source Source text.\n * @returns True when a wrap-module specifier appears in the source.\n */\nfunction mentionsWrapModule(source: string): boolean {\n for (const moduleName of getWrapModules().keys()) {\n if (source.includes(`'${moduleName}'`) || source.includes(`\"${moduleName}\"`)) return true\n }\n return false\n}\n\n/**\n * Fallback parse when no upstream is configured AND Metro didn't hand\n * us an AST. Used by unit tests and standalone setups.\n * @param source Source text.\n * @returns Parsed Babel File.\n */\nfunction parseSource(source: string): File {\n return parse(source, { sourceType: 'module', plugins: ['typescript', 'jsx'] }) as unknown as File\n}\n\n/** Metro's babel transformer signature. */\nexport interface BabelTransformerArgs {\n filename: string\n src: string\n options: { projectRoot?: string; [key: string]: unknown }\n ast?: File\n plugins?: readonly unknown[]\n}\n\n/** Return shape Metro expects from a babel transformer. */\nexport interface BabelTransformerResult {\n ast: File\n metadata?: unknown\n}\n\n/**\n * rnwind's Metro babel transformer. Two phases per source file:\n *\n * 1. **Pre-process the source string before handing it to the upstream\n * babel pipeline.** babel-preset-expo / React's JSX transform run\n * inside the upstream and convert `<View className=\"...\"/>` into\n * `React.createElement(View, {className})`. If we walked the AST\n * AFTER the upstream, there'd be no JSX attributes left to\n * rewrite. So we parse, run our pass, regenerate code, and feed\n * THAT to the upstream as `src`.\n * 2. **Delegate to the upstream `babelTransformerPath`** (Expo's\n * default handles Flow stripping, expo-router macros, etc.).\n *\n * Skip both phases when the file isn't a JS/TS source under user\n * code, or doesn't mention `className=` — hand straight to upstream.\n * @param args Metro's per-file args.\n * @returns Mutated AST + metadata.\n */\nexport async function transform(args: BabelTransformerArgs): Promise<BabelTransformerResult> {\n // Short-circuit `.css` inputs: the theme CSS is pulled into the dep\n // graph as a sentinel (see `THEME_SIGNATURE_MODULE` in resolver.ts)\n // so Metro watches it and invalidates importers on edit, but the\n // file's CSS syntax can't go through a JS babel transformer.\n //\n // When the CSS being transformed IS the user's theme entry, we\n // piggyback on Metro's own file-watcher: Metro calls us here on\n // every CSS save; we trigger `onThemeChange` to rebuild parser +\n // rewrite scheme files with the new values. Metro's dep graph then\n // HMRs the regenerated `common.style.js` to the running app.\n //\n // Emitting the CSS content hash in the fake JS output is what makes\n // Metro propagate invalidation to downstream importers — constant\n // `export {}` bytes would never look changed and Metro would skip\n // the chain.\n if (args.filename.endsWith('.css')) {\n if (isThemeCssEntry(args.filename)) {\n try {\n await onThemeChange(projectRootOf(args))\n } catch {\n // CSS edit happened outside a configured project (e.g. tests).\n }\n }\n const themeHash = createHash('sha256').update(args.src).digest('hex').slice(0, 16)\n const stub = `export const __rnwindThemeHash = ${JSON.stringify(themeHash)};\\n`\n return { ast: parse(stub, { sourceType: 'module' }) as unknown as File }\n }\n if (!isRewriteCandidate(args)) {\n if (/\\.(?:tsx|ts|jsx|js)$/i.test(args.filename) && !args.filename.includes('/node_modules/')) {\n try {\n getRnwindState(projectRootOf(args)).builder.dropFile(args.filename)\n } catch {\n // State not configured (e.g. test). Nothing to drop.\n }\n }\n return runUpstream(args)\n }\n\n const rewrittenSource = await rewriteSource(args)\n return runUpstream({ ...args, src: rewrittenSource, ast: undefined })\n}\n\n/**\n * Metro's babel-transformer contract: a `getCacheKey()` export is\n * sampled per-file and mixed into the transform cache key. Returning\n * a string that includes the theme CSS content hash invalidates every\n * cached transform on every CSS edit — so the bundle rebuilds with\n * the new theme automatically on the next request.\n * @returns Cache-key segment that includes rnwind's current theme hash.\n */\nexport function getCacheKey(): string {\n const upstreamKey = loadUpstreamCacheKey()\n const ownKey = getRnwindCacheKey()\n return upstreamKey ? `${upstreamKey}|${ownKey}` : ownKey\n}\n\n/** Test-only — drop the cached upstream so a new env var picks up next call. */\nexport function __resetUpstreamCache(): void {\n cachedUpstream = null\n}\n"],"names":["parse","filterUnknownClassCandidates","rewriteWrapImports","getWrapModules","state","getRnwindState","STYLE_SPECIFIERS","t","THEME_SIGNATURE_MODULE","realpathSync","onThemeChange","createHash","getRnwindCacheKey"],"mappings":"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"}
1
+ {"version":3,"file":"transformer.cjs","sources":["../../../../src/metro/transformer.ts"],"sourcesContent":["import type { File } from '@babel/types'\nimport * as t from '@babel/types'\nimport { parse } from '@babel/parser'\nimport generate from '@babel/generator'\nimport { createHash } from 'node:crypto'\nimport { realpathSync } from 'node:fs'\nimport { getRnwindCacheKey, getRnwindState, getWrapModules, onThemeChange } from './state'\nimport { rewriteWrapImports } from './wrap-imports'\nimport { STYLE_SPECIFIERS, THEME_SIGNATURE_MODULE } from './resolver'\nimport { filterUnknownClassCandidates } from './warn-unknown-classes'\n\n/** The shape of the upstream module we delegate parsing/babel work to. */\ninterface UpstreamTransformer {\n transform: (args: BabelTransformerArgs) => Promise<BabelTransformerResult> | BabelTransformerResult\n}\n\n/** Env var that points at the upstream `babelTransformerPath` we override. */\nconst UPSTREAM_ENV = 'RNWIND_UPSTREAM_TRANSFORMER'\n\n/** Cached upstream module — required once, reused across every transform call. */\nlet cachedUpstream: UpstreamTransformer | null = null\n\nconst generateModule = (generate as unknown as { default?: typeof generate }).default ?? generate\n\n/**\n * Parse user source with the broad plugin set (Flow + JSX + TypeScript\n * + class properties). Permissive on purpose so we don't reject any\n * file the upstream could have handled. Returns `null` when parse\n * fails — caller falls back to the raw source string.\n * @param source Source text.\n * @returns Parsed AST, or null on parse failure.\n */\nfunction parseUserSource(source: string): File | null {\n try {\n return parse(source, {\n sourceType: 'unambiguous',\n allowReturnOutsideFunction: true,\n allowImportExportEverywhere: true,\n plugins: ['typescript', 'jsx'],\n }) as unknown as File\n } catch {\n try {\n return parse(source, {\n sourceType: 'unambiguous',\n allowReturnOutsideFunction: true,\n allowImportExportEverywhere: true,\n plugins: ['flow', 'jsx'],\n }) as unknown as File\n } catch {\n return null\n }\n }\n}\n\n/**\n * Print Tailwind-shaped candidates oxide picked up but the parser\n * could NOT compile — typo, missing custom utility, or class not in\n * the user's theme. Filtering by candidates that ALSO appear inside a\n * `className=\"…\"` literal eliminates false positives from imports,\n * comments, and JSX prop values.\n * @param source Original source text — searched for className literals.\n * @param candidates Every candidate oxide surfaced from the source.\n * @param atoms Successfully resolved atoms (keys are class names).\n * @param filename Source path, prefixed onto the warning.\n * @param features Feature-atom maps (gradient / haptic) — their names are\n * known classes even though they carry no RN style, so they're excluded\n * from the unknown-class warning.\n */\nfunction warnUnknownClasses(\n source: string,\n candidates: readonly string[],\n atoms: ReadonlyMap<string, unknown>,\n filename: string,\n features: ReadonlyArray<ReadonlyMap<string, unknown>> = [],\n): void {\n // Feature atoms (gradient / haptic) resolve to no RN style, so they're\n // absent from `atoms` — but they're NOT unknown. Fold their names into\n // the known set so `active:haptic-rigid` etc. don't warn at build time.\n const known = new Set(atoms.keys())\n for (const map of features) for (const name of map.keys()) known.add(name)\n const unknown = filterUnknownClassCandidates(source, candidates, known)\n if (unknown.length === 0) return\n // eslint-disable-next-line no-console\n console.warn(`rnwind: unknown class${unknown.length > 1 ? 'es' : ''} in ${filename}: ${unknown.join(', ')}`)\n}\n\n/**\n * Extract the bare extension for oxide / internal switches.\n * @param filename Absolute path.\n * @returns Extension without the leading dot (`tsx` / `ts` / `js` / `jsx`).\n */\nfunction extensionOf(filename: string): string {\n const index = filename.lastIndexOf('.')\n if (index === -1) return 'tsx'\n return filename.slice(index + 1)\n}\n\n/**\n * Read the project root Metro hands us per-transform. Falls back to\n * `process.cwd()` only when the upstream harness doesn't set it (unit\n * tests, standalone). Metro's production pipeline always sets it.\n * @param args Metro transformer args.\n * @returns Absolute project root.\n */\nfunction projectRootOf(args: BabelTransformerArgs): string {\n const fromOptions = args.options?.projectRoot\n if (typeof fromOptions === 'string' && fromOptions.length > 0) return fromOptions\n return process.cwd()\n}\n\n/**\n * Whether a `.css` filename is the user's theme entry (the file\n * `withRnwindConfig` pointed us at via `RNWIND_CSS_ENTRY_FILE`).\n * Only the theme CSS should trigger a scheme rebuild — unrelated CSS\n * files in the project stay invisible to rnwind.\n * @param filename Absolute CSS path.\n * @returns Whether the file is the configured theme entry.\n */\nfunction isThemeCssEntry(filename: string): boolean {\n const cssEntry = process.env.RNWIND_CSS_ENTRY_FILE\n return typeof cssEntry === 'string' && cssEntry.length > 0 && cssEntry === filename\n}\n\n/**\n * Wrap host imports + compile any className literals, then regenerate\n * source. Two paths:\n * - **className present**: oxide-scan the file, record its atoms into\n * the union, and inject the generated-style + theme-signature\n * side-effect imports so the runtime registries populate.\n * - **import-only** (a `{...rest}` forwarder or a leaf with no literal\n * `className=`): just wrap the host imports so a forwarded className\n * still resolves at render — no oxide scan, no injected imports.\n *\n * On parse failure, fall back to the original source — a transient parse\n * error shouldn't crash Metro for a file the upstream might handle fine.\n * @param args Metro args; `src` is the original source text.\n * @returns Rewritten source text.\n */\nasync function rewriteSource(args: BabelTransformerArgs): Promise<string> {\n // SCAN FIRST — exactly like Tailwind: oxide extracts class candidates from\n // the WHOLE file content (className, cva/clsx, plain strings, anywhere),\n // and the compiler is the only filter. No babel parse needed to scan, so\n // the common \"file with no classes\" case stays cheap and the source is\n // returned untouched. This is what makes adding a class ANYWHERE register\n // on hot-reload, not just inside a `className=` or a known helper call.\n const state = getRnwindState(projectRootOf(args))\n const extension = extensionOf(args.filename)\n const parsed = await state.parser.parseAtoms({ content: args.src, extension })\n const hasAtoms = parsed.atoms.size > 0\n\n const hasClassName = /classname=/i.test(args.src)\n const hasSpread = /\\{\\s*\\.\\.\\./.test(args.src)\n\n // Nothing for rnwind to do: no Tailwind class compiled AND no host\n // wrapping needed. Drop any stale contribution and emit the file as-is.\n if (!hasAtoms && !hasClassName && !hasSpread) {\n state.builder.dropFile(args.filename)\n return args.src\n }\n\n const ast = parseUserSource(args.src)\n if (!ast) {\n // Can't parse to wrap/inject, but we DID scan — still record the atoms so\n // they register (a malformed-but-recoverable file shouldn't lose styles).\n if (hasAtoms) {\n await state.builder.recordFile(args.filename, parsed.atoms, parsed.keyframes, [])\n await state.builder.writeSchemes()\n } else {\n state.builder.dropFile(args.filename)\n }\n return args.src\n }\n\n // Wrap host imports ONLY when className flows through a component — written\n // (`hasClassName`) or forwarded (`{...rest}`). A `useCss`/`cva`-only file\n // resolves manually, so its imports (e.g. skia drawing primitives) are\n // left untouched.\n const wrapped = hasClassName || hasSpread ? rewriteWrapImports(ast, getWrapModules()) : false\n\n if (!hasAtoms) {\n // Wrap-only forwarder — no classes to record/register.\n state.builder.dropFile(args.filename)\n return wrapped ? generateModule(ast).code : args.src\n }\n\n warnUnknownClasses(args.src, parsed.candidates, parsed.atoms, args.filename, [parsed.gradientAtoms, parsed.hapticAtoms])\n const literals = collectClassNameLiterals(ast)\n const { changed } = await state.builder.recordFile(args.filename, parsed.atoms, parsed.keyframes, literals)\n if (changed) await state.builder.writeSchemes()\n\n injectSideEffectImports(ast, STYLE_SPECIFIERS)\n injectThemeSignatureImport(ast)\n return generateModule(ast).code\n}\n\n/**\n * Whether a JSX attribute names a className-style prop (`className` or\n * any `<prefix>ClassName`).\n * @param node JSX attribute node.\n * @returns True when the attribute is a className prop.\n */\nfunction isClassNameAttribute(node: t.JSXAttribute): boolean {\n if (!t.isJSXIdentifier(node.name)) return false\n const {name} = node.name\n return name === 'className' || name.endsWith('ClassName')\n}\n\n/**\n * Pull static string literals out of a className expression. Handles a\n * bare string, a no-substitution template, and the branches of a\n * ternary / `&&` (so `cond ? 'a' : 'b'` and `flag && 'x'` both register\n * their literals). Dynamic interpolations are skipped — they resolve via\n * the runtime atom path.\n * @param expr Expression inside a `className={...}` container.\n * @param out Accumulator for discovered literals.\n */\nfunction collectLiteralsFromExpression(expr: t.Expression | t.JSXEmptyExpression | null | undefined, out: string[]): void {\n if (!expr) return\n if (t.isStringLiteral(expr)) {\n out.push(expr.value)\n return\n }\n if (t.isTemplateLiteral(expr) && expr.expressions.length === 0 && expr.quasis.length === 1) {\n const cooked = expr.quasis[0]?.value.cooked\n if (typeof cooked === 'string') out.push(cooked)\n return\n }\n if (t.isConditionalExpression(expr)) {\n collectLiteralsFromExpression(expr.consequent, out)\n collectLiteralsFromExpression(expr.alternate, out)\n return\n }\n if (t.isLogicalExpression(expr)) {\n collectLiteralsFromExpression(expr.right as t.Expression, out)\n }\n}\n\n/** AST node keys the literal walk skips — position / comment metadata. */\nconst SKIP_WALK_KEYS = new Set(['type', 'loc', 'start', 'end', 'range', 'leadingComments', 'trailingComments', 'innerComments'])\n\n/**\n * Collect the static literals from one className JSX attribute into the\n * dedup accumulator.\n * @param attribute The (already className-matched) JSX attribute.\n * @param seen Dedup set of literals already collected.\n * @param out Ordered accumulator.\n */\nfunction collectAttributeLiterals(attribute: t.JSXAttribute, seen: Set<string>, out: string[]): void {\n const { value } = attribute\n const found: string[] = []\n if (t.isStringLiteral(value)) found.push(value.value)\n else if (t.isJSXExpressionContainer(value)) collectLiteralsFromExpression(value.expression, found)\n for (const literal of found) {\n if (seen.has(literal)) continue\n seen.add(literal)\n out.push(literal)\n }\n}\n\n/**\n * Walk the AST for every `className=` / `<prefix>ClassName=` literal so\n * the builder can pre-merge each into a per-scheme molecule. A generic\n * node walk (no scope build) keeps it cheap; only JSX attribute nodes do\n * any work.\n * @param ast Parsed Babel file.\n * @returns Distinct literal className strings, in first-seen order.\n */\nfunction collectClassNameLiterals(ast: File): readonly string[] {\n const out: string[] = []\n const seen = new Set<string>()\n const visit = (node: unknown): void => {\n if (!node || typeof node !== 'object') return\n if (Array.isArray(node)) {\n for (const child of node) visit(child)\n return\n }\n const typed = node as { type?: string; [key: string]: unknown }\n if (typeof typed.type !== 'string') return\n if (typed.type === 'JSXAttribute' && isClassNameAttribute(node as t.JSXAttribute)) {\n collectAttributeLiterals(node as t.JSXAttribute, seen, out)\n }\n for (const key in typed) {\n if (SKIP_WALK_KEYS.has(key)) continue\n visit(typed[key])\n }\n }\n visit(ast.program)\n return out\n}\n\n/**\n * Prepend side-effect imports (`import '<spec>'`) so the generated\n * per-scheme style + manifest modules load — registering this file's\n * atoms / molecules / features into the runtime registries the wrapper's\n * `resolve` reads.\n * @param ast Babel File AST to mutate in place.\n * @param specifiers Module specifiers to side-effect-import.\n */\nfunction injectSideEffectImports(ast: File, specifiers: readonly string[]): void {\n for (const specifier of specifiers) {\n ast.program.body.unshift(t.importDeclaration([], t.stringLiteral(specifier)))\n }\n}\n\n/**\n * Prepend `import 'rnwind/__generated/theme-signature'` to every\n * rnwind-transformed file. The resolver maps that specifier to the\n * user's theme CSS so Metro's dependency graph carries a real edge\n * from this JS file to the CSS. When the user edits `global.css`,\n * the CSS module's SHA1 changes, and Metro invalidates every JS file\n * holding this import — forcing them to re-transform with the new\n * theme. The `.css` branch in {@link transform} returns an empty\n * `export {}` module so the runtime cost is one extra `require()`.\n * @param ast Babel File AST to mutate in place.\n */\nfunction injectThemeSignatureImport(ast: File): void {\n const declaration = t.importDeclaration([], t.stringLiteral(THEME_SIGNATURE_MODULE))\n ast.program.body.unshift(declaration)\n}\n\n/**\n * Read the upstream transformer's `getCacheKey()` so our cache-key\n * contribution composes with — rather than replaces — whatever the\n * host framework wants to mix in.\n * @returns Upstream cache key, or `null` when no upstream exposes one.\n */\nfunction loadUpstreamCacheKey(): string | null {\n const upstream = loadUpstream() as (UpstreamTransformer & { getCacheKey?: () => string }) | null\n if (!upstream) return null\n try {\n return typeof upstream.getCacheKey === 'function' ? upstream.getCacheKey() : null\n } catch {\n return null\n }\n}\n\n/**\n * Invoke the upstream `babelTransformerPath` Metro originally had\n * configured. The path is read from `RNWIND_UPSTREAM_TRANSFORMER`,\n * which `withRnwindConfig` sets at Metro startup. When the env var is\n * unset (unit tests, standalone use), fall back to a typescript+jsx\n * parse.\n * @param args Metro's per-file args.\n * @returns Upstream transform result containing the post-babel AST.\n */\nasync function runUpstream(args: BabelTransformerArgs): Promise<BabelTransformerResult> {\n if (args.ast && !process.env[UPSTREAM_ENV]) return { ast: args.ast }\n const upstream = loadUpstream()\n if (upstream) return await Promise.resolve(upstream.transform(args))\n if (args.ast) return { ast: args.ast }\n return { ast: parseSource(args.src) }\n}\n\n/**\n * Lazily require the upstream transformer module. Cached after first\n * load so per-file overhead is one cache lookup.\n * @returns Upstream module, or null when env is unset.\n */\nfunction loadUpstream(): UpstreamTransformer | null {\n if (cachedUpstream) return cachedUpstream\n const upstreamPath = process.env[UPSTREAM_ENV]\n if (!upstreamPath || upstreamPath.length === 0) return null\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires\n const required = require(upstreamPath) as UpstreamTransformer | { default?: UpstreamTransformer }\n const upstream = (required as { default?: UpstreamTransformer }).default ?? (required as UpstreamTransformer)\n if (typeof upstream.transform !== 'function') return null\n cachedUpstream = upstream\n return upstream\n } catch (error) {\n // eslint-disable-next-line no-console\n if (process.env.RNWIND_DEBUG) console.error('rnwind: failed to load upstream transformer:', error)\n return null\n }\n}\n\n/**\n * Cheap guard — the file has to look JS/TS, live outside `node_modules`,\n * and mention `className=` before we spend AST cycles on it.\n *\n * Symlink awareness: monorepo workspaces (yarn / pnpm / bun workspaces)\n * symlink each package into the consumer's `node_modules/<name>`, so a\n * file from `packages/ui/src/Foo.tsx` ends up reaching the transformer\n * as `<root>/node_modules/ui/src/Foo.tsx`. The naïve `/node_modules/`\n * check would skip every workspace UI file. We `realpath` the filename\n * once and only bail when the resolved real path is ALSO under\n * node_modules — true third-party installs.\n * @param args Metro args.\n * @returns Whether the file might need the rnwind pass.\n */\nfunction isRewriteCandidate(args: BabelTransformerArgs): boolean {\n if (!/\\.(?:tsx|ts|jsx|js)$/i.test(args.filename)) return false\n // EVERY user source file is scanned — exactly like Tailwind walks its\n // whole content set. The compiler is the only filter (see rewriteSource);\n // no className/helper pre-filter, because that \"filter magic\" missed\n // classes living in cva/clsx/plain-string files and broke their hot-reload.\n // (Cheap when the file has no classes: oxide finds nothing, no babel parse,\n // source returned untouched.)\n if (!args.filename.includes('/node_modules/')) return true\n // node_modules in path → could be a workspace symlink; resolve it.\n try {\n return !realpathSync(args.filename).includes('/node_modules/')\n } catch {\n // realpath failed (broken symlink, missing file). Fall back to skipping.\n return false\n }\n}\n\n/**\n * Fallback parse when no upstream is configured AND Metro didn't hand\n * us an AST. Used by unit tests and standalone setups.\n * @param source Source text.\n * @returns Parsed Babel File.\n */\nfunction parseSource(source: string): File {\n return parse(source, { sourceType: 'module', plugins: ['typescript', 'jsx'] }) as unknown as File\n}\n\n/** Metro's babel transformer signature. */\nexport interface BabelTransformerArgs {\n filename: string\n src: string\n options: { projectRoot?: string; [key: string]: unknown }\n ast?: File\n plugins?: readonly unknown[]\n}\n\n/** Return shape Metro expects from a babel transformer. */\nexport interface BabelTransformerResult {\n ast: File\n metadata?: unknown\n}\n\n/**\n * rnwind's Metro babel transformer. Two phases per source file:\n *\n * 1. **Pre-process the source string before handing it to the upstream\n * babel pipeline.** babel-preset-expo / React's JSX transform run\n * inside the upstream and convert `<View className=\"...\"/>` into\n * `React.createElement(View, {className})`. If we walked the AST\n * AFTER the upstream, there'd be no JSX attributes left to\n * rewrite. So we parse, run our pass, regenerate code, and feed\n * THAT to the upstream as `src`.\n * 2. **Delegate to the upstream `babelTransformerPath`** (Expo's\n * default handles Flow stripping, expo-router macros, etc.).\n *\n * Skip both phases when the file isn't a JS/TS source under user\n * code, or doesn't mention `className=` — hand straight to upstream.\n * @param args Metro's per-file args.\n * @returns Mutated AST + metadata.\n */\nexport async function transform(args: BabelTransformerArgs): Promise<BabelTransformerResult> {\n // Short-circuit `.css` inputs: the theme CSS is pulled into the dep\n // graph as a sentinel (see `THEME_SIGNATURE_MODULE` in resolver.ts)\n // so Metro watches it and invalidates importers on edit, but the\n // file's CSS syntax can't go through a JS babel transformer.\n //\n // When the CSS being transformed IS the user's theme entry, we\n // piggyback on Metro's own file-watcher: Metro calls us here on\n // every CSS save; we trigger `onThemeChange` to rebuild parser +\n // rewrite scheme files with the new values. Metro's dep graph then\n // HMRs the regenerated `common.style.js` to the running app.\n //\n // Emitting the CSS content hash in the fake JS output is what makes\n // Metro propagate invalidation to downstream importers — constant\n // `export {}` bytes would never look changed and Metro would skip\n // the chain.\n if (args.filename.endsWith('.css')) {\n if (isThemeCssEntry(args.filename)) {\n try {\n await onThemeChange(projectRootOf(args))\n } catch {\n // CSS edit happened outside a configured project (e.g. tests).\n }\n }\n const themeHash = createHash('sha256').update(args.src).digest('hex').slice(0, 16)\n const stub = `export const __rnwindThemeHash = ${JSON.stringify(themeHash)};\\n`\n return { ast: parse(stub, { sourceType: 'module' }) as unknown as File }\n }\n if (!isRewriteCandidate(args)) {\n if (/\\.(?:tsx|ts|jsx|js)$/i.test(args.filename) && !args.filename.includes('/node_modules/')) {\n try {\n getRnwindState(projectRootOf(args)).builder.dropFile(args.filename)\n } catch {\n // State not configured (e.g. test). Nothing to drop.\n }\n }\n return runUpstream(args)\n }\n\n const rewrittenSource = await rewriteSource(args)\n return runUpstream({ ...args, src: rewrittenSource, ast: undefined })\n}\n\n/**\n * Metro's babel-transformer contract: a `getCacheKey()` export is\n * sampled per-file and mixed into the transform cache key. Returning\n * a string that includes the theme CSS content hash invalidates every\n * cached transform on every CSS edit — so the bundle rebuilds with\n * the new theme automatically on the next request.\n * @returns Cache-key segment that includes rnwind's current theme hash.\n */\nexport function getCacheKey(): string {\n const upstreamKey = loadUpstreamCacheKey()\n const ownKey = getRnwindCacheKey()\n return upstreamKey ? `${upstreamKey}|${ownKey}` : ownKey\n}\n\n/** Test-only — drop the cached upstream so a new env var picks up next call. */\nexport function __resetUpstreamCache(): void {\n cachedUpstream = null\n}\n"],"names":["parse","filterUnknownClassCandidates","state","getRnwindState","rewriteWrapImports","getWrapModules","STYLE_SPECIFIERS","t","THEME_SIGNATURE_MODULE","realpathSync","onThemeChange","createHash","getRnwindCacheKey"],"mappings":"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"}
@@ -15,14 +15,15 @@ const DEFAULT_CACHE_DIR = '.rnwind';
15
15
  */
16
16
  let activeCssWatcher = null;
17
17
  /**
18
- * Watch the theme CSS for edits. On change, rewrite the per-scheme
19
- * files with the fresh theme AND bump `mtime` on every source file
20
- * rnwind has transformed so far Metro's own watcher sees those
21
- * mtime changes, invalidates the modules, and re-transforms them
22
- * against the new CSS on the next request. `getCacheKey()` alone is
23
- * NOT enough: Metro samples the cache key once per worker lifetime,
24
- * so edits during an already-running dev server don't propagate
25
- * without this explicit nudge.
18
+ * Watch the theme CSS for edits. On change, rebuild state against the fresh
19
+ * CSS and rewrite the per-scheme files (`onThemeChange` full rescan
20
+ * `writeSchemes`). That's the entire HMR signal: every transformed source
21
+ * imports `rnwind/__generated/schemes`, which eager-imports
22
+ * `common.style.js`; the rewrite changes its bytes, Metro's content-SHA1
23
+ * dedup notices, and every importer is invalidated + re-bundled with the new
24
+ * style values. The rewritten JSX references atoms by NAME (theme-independent),
25
+ * so no source-file re-transform / mtime nudge is needed — the dep graph
26
+ * carries the signal.
26
27
  * @param cssPath Absolute path to the theme CSS to watch.
27
28
  * @param projectRoot Metro's project root (for `getRnwindState`).
28
29
  */
@@ -43,7 +44,6 @@ function watchThemeCss(cssPath, projectRoot) {
43
44
  pending = false;
44
45
  try {
45
46
  await state.onThemeChange(projectRoot);
46
- touchRecordedFiles(projectRoot);
47
47
  }
48
48
  catch {
49
49
  // Invalidation is best-effort — never crash the dev server.
@@ -52,26 +52,6 @@ function watchThemeCss(cssPath, projectRoot) {
52
52
  });
53
53
  activeCssWatcher = { cssPath, close: () => watcher.close() };
54
54
  }
55
- /**
56
- * Bump the mtime on every file the builder has transformed. Metro's
57
- * file watcher keys on `mtime`, so this is what makes it invalidate
58
- * those modules and re-transform them.
59
- * @param projectRoot Metro's project root.
60
- */
61
- function touchRecordedFiles(projectRoot) {
62
- const state$1 = state.getRnwindState(projectRoot);
63
- const files = state$1.builder.recordedFiles();
64
- const now = new Date();
65
- for (const file of files) {
66
- try {
67
- if (node_fs.existsSync(file))
68
- node_fs.utimesSync(file, now, now);
69
- }
70
- catch {
71
- // One file's stat failure shouldn't stop the others.
72
- }
73
- }
74
- }
75
55
  /**
76
56
  * Where the rnwind babel transformer lives — resolved relative to this
77
57
  * module so the path works from both the `src/` tree (tests) and the
@@ -1 +1 @@
1
- {"version":3,"file":"with-config.cjs","sources":["../../../../src/metro/with-config.ts"],"sourcesContent":["import { existsSync, mkdirSync, utimesSync, watch as watchFile } from 'node:fs'\nimport path from 'node:path'\nimport { writeDtsFile } from './dts'\nimport { createRnwindResolver, type ResolveRequestFn } from './resolver'\nimport { configureRnwindState, getRnwindState, onThemeChange } from './state'\n\n/** Default cache directory at the project root. Visible for debugging. */\nconst DEFAULT_CACHE_DIR = '.rnwind'\n\n/**\n * Active CSS watcher — replaced (and the prior one closed) when\n * `withRnwindConfig` is called again (Metro restart, repeated init).\n * Only one watcher per process; no stacking.\n */\nlet activeCssWatcher: { cssPath: string; close: () => void } | null = null\n\n/**\n * Watch the theme CSS for edits. On change, rewrite the per-scheme\n * files with the fresh theme AND bump `mtime` on every source file\n * rnwind has transformed so far — Metro's own watcher sees those\n * mtime changes, invalidates the modules, and re-transforms them\n * against the new CSS on the next request. `getCacheKey()` alone is\n * NOT enough: Metro samples the cache key once per worker lifetime,\n * so edits during an already-running dev server don't propagate\n * without this explicit nudge.\n * @param cssPath Absolute path to the theme CSS to watch.\n * @param projectRoot Metro's project root (for `getRnwindState`).\n */\nfunction watchThemeCss(cssPath: string, projectRoot: string): void {\n if (activeCssWatcher?.cssPath === cssPath) return\n activeCssWatcher?.close()\n if (!existsSync(cssPath)) return\n let pending = false\n const watcher = watchFile(cssPath, { persistent: false }, () => {\n // Debounce: editors often emit 2-3 change events per save (atomic\n // rename dance, tmp files). Coalesce to ONE rebuild per microtask.\n if (pending) return\n pending = true\n queueMicrotask(async () => {\n pending = false\n try {\n await onThemeChange(projectRoot)\n touchRecordedFiles(projectRoot)\n } catch {\n // Invalidation is best-effort — never crash the dev server.\n }\n })\n })\n activeCssWatcher = { cssPath, close: () => watcher.close() }\n}\n\n/**\n * Bump the mtime on every file the builder has transformed. Metro's\n * file watcher keys on `mtime`, so this is what makes it invalidate\n * those modules and re-transform them.\n * @param projectRoot Metro's project root.\n */\nfunction touchRecordedFiles(projectRoot: string): void {\n const state = getRnwindState(projectRoot)\n const files = state.builder.recordedFiles()\n const now = new Date()\n for (const file of files) {\n try {\n if (existsSync(file)) utimesSync(file, now, now)\n } catch {\n // One file's stat failure shouldn't stop the others.\n }\n }\n}\n\n/**\n * Where the rnwind babel transformer lives — resolved relative to this\n * module so the path works from both the `src/` tree (tests) and the\n * built `lib/` output. Tries a few extensions because `require.resolve`\n * doesn't auto-find `.cjs` / `.mjs` from a bare specifier.\n * @returns Absolute path to the rnwind transformer module.\n */\nfunction transformerPath(): string {\n for (const candidate of ['./transformer.cjs', './transformer.mjs', './transformer.js', './transformer.ts', './transformer']) {\n try {\n return require.resolve(candidate)\n } catch {\n // try the next extension\n }\n }\n throw new Error('rnwind: could not resolve the metro transformer path')\n}\n\n/**\n * Resolve the effective cache directory, honoring a user override and\n * falling back to `<projectRoot>/.rnwind`.\n * @param projectRoot Anchor for relative paths.\n * @param override User-supplied option.\n * @returns Absolute cache directory.\n */\nfunction resolveCacheDir(projectRoot: string, override: string | undefined): string {\n if (!override || override.length === 0) return path.resolve(projectRoot, DEFAULT_CACHE_DIR)\n return path.isAbsolute(override) ? override : path.resolve(projectRoot, override)\n}\n\n/**\n * Read the theme CSS and extract `@variant <name>` blocks for the .d.ts\n * generator. Forces construction of `getRnwindState`, then reads\n * `parser.declaredSchemes` (populated synchronously at construction).\n * @param cssEntry Absolute path to theme CSS.\n * @param projectRoot\n * @returns Scheme names (empty when the theme has no variants; `'base'` is filtered).\n */\nfunction discoverSchemes(cssEntry: string, projectRoot: string): readonly string[] {\n if (!existsSync(cssEntry)) return []\n try {\n const { parser } = getRnwindState(projectRoot)\n return parser.declaredSchemes.filter((name) => name !== 'base')\n } catch {\n return []\n }\n}\n\n/** User-facing options for `withRnwindConfig`. */\nexport interface RnwindMetroOptions {\n /** Path to the theme CSS (absolute or relative to `projectRoot`). Required. */\n cssEntryFile: string\n /** Where rnwind writes the `.d.ts` file. Set `false` to disable. Defaults to `<projectRoot>/rnwind-types.d.ts`. */\n dtsFile?: string | false\n /** Optional project-root override — defaults to `metroConfig.projectRoot` then `process.cwd()`. */\n projectRoot?: string\n /** Cache directory. Absolute, or relative to `projectRoot`. Default: `.rnwind` at project root. */\n cacheDir?: string\n /**\n * Extra module specifiers whose component exports rnwind should\n * auto-wrap at import sites — `import { View } from 'react-native'`\n * becomes `const View = wrap(_rnw0)` so `<View className=\"…\">` resolves\n * styles at runtime. Merged with the built-in defaults: `react-native`,\n * `react-native-reanimated`, `react-native-svg`,\n * `react-native-gesture-handler`, `react-native-safe-area-context`,\n * `expo-linear-gradient`, `expo-image`, and more.\n *\n * A module NOT in this list keeps its raw imports — the importing\n * component receives `className` as a plain prop and can resolve it\n * via `useCss` / `wrap` itself. Use this to opt your design-system /\n * UI primitive packages into the auto-wrap path.\n */\n wrapModules?: readonly string[]\n}\n\n/** Shape we mutate on Metro's config. Loose so we don't pin Metro's internal types. */\nexport interface MetroConfigLike {\n projectRoot?: string\n watchFolders?: string[]\n transformer?: {\n babelTransformerPath?: string\n [key: string]: unknown\n }\n resolver?: {\n resolveRequest?: ResolveRequestFn | null\n [key: string]: unknown\n }\n [key: string]: unknown\n}\n\n/**\n * Wrap a Metro config with rnwind's pipeline:\n * - Install the rnwind babel transformer.\n * - Chain a `resolveRequest` hook that serves\n * `rnwind/__generated/schemes` from `<cacheDir>/schemes.js`.\n * - Write the `.d.ts` so TypeScript accepts `className=` on RN components.\n * - Publish the theme CSS path + cache dir via env so Metro workers\n * can rebuild their local state.\n * - Ensure the cache dir is a watched folder Metro's haste-map indexes.\n *\n * Theme-edit hot reload happens implicitly: every transformed file\n * imports `rnwind/__generated/schemes`, and that module eager-imports\n * `common.style.js`. When the theme changes, the per-scheme files\n * regenerate with new bytes; Metro's content SHA1 dedup detects the\n * change and invalidates every importer automatically.\n * `getCacheKey()` on the transformer covers the per-file transform\n * cache. No file watcher / source-padding hack needed — the dep graph\n * carries the signal.\n * @param metroConfig Config from `getDefaultConfig(__dirname)` or equivalent.\n * @param options rnwind options.\n * @returns The same config, mutated.\n */\nexport function withRnwindConfig<C extends MetroConfigLike>(metroConfig: C, options: RnwindMetroOptions): C {\n const projectRoot = options.projectRoot ?? metroConfig.projectRoot ?? process.cwd()\n const cacheDir = resolveCacheDir(projectRoot, options.cacheDir)\n const cssEntry = path.isAbsolute(options.cssEntryFile) ? options.cssEntryFile : path.resolve(projectRoot, options.cssEntryFile)\n\n mkdirSync(cacheDir, { recursive: true })\n const watchFolders = (metroConfig.watchFolders ?? []).filter((p) => typeof p === 'string' && p.length > 0)\n configureRnwindState(cssEntry, cacheDir, watchFolders, options.wrapModules)\n\n // Warm the state eagerly (in the Metro master process) so oxide's\n // Scanner walks every project source (and every monorepo\n // watch-folder) ONCE and the manifest + scheme files hold the\n // complete union before Metro's resolver tries to SHA1 them on the\n // first transform. Each worker lazy-repeats this scan on its first\n // transform to converge on identical state.\n try {\n void getRnwindState(projectRoot).builder.ensureFilesExist()\n } catch {\n // Any init error surfaces again at the first transform; don't crash Metro boot.\n }\n\n // Install transformer + resolver. Capture the existing\n // babelTransformerPath BEFORE we override it — our worker chains to\n // it (env-passed) so Flow / expo-router / babel-preset-expo etc. all\n // continue to run.\n const existingTransformerPath = metroConfig.transformer?.babelTransformerPath\n if (typeof existingTransformerPath === 'string' && existingTransformerPath.length > 0) {\n process.env.RNWIND_UPSTREAM_TRANSFORMER = existingTransformerPath\n }\n const upstream = metroConfig.resolver?.resolveRequest ?? null\n metroConfig.transformer = { ...metroConfig.transformer, babelTransformerPath: transformerPath() }\n metroConfig.resolver = { ...metroConfig.resolver, resolveRequest: createRnwindResolver(upstream) }\n\n // Metro's haste-map indexes `watchFolders` at startup. Adding the\n // cache dir guarantees scheme style files + manifest get SHA1'd\n // without a \"Failed to get the SHA-1\" race when the first transform\n // writes them.\n const existingWatch = metroConfig.watchFolders ?? []\n metroConfig.watchFolders = existingWatch.includes(cacheDir) ? existingWatch : [...existingWatch, cacheDir]\n\n if (options.dtsFile !== false) {\n const dtsPath = options.dtsFile ?? path.resolve(projectRoot, 'rnwind-types.d.ts')\n const schemes = discoverSchemes(cssEntry, projectRoot)\n writeDtsFile(dtsPath, schemes)\n }\n\n // Watch the theme CSS. On edit, we rewrite scheme files AND touch\n // mtime on every transformed source file so Metro invalidates them\n // and re-transforms — the only reliable way to propagate theme\n // changes to an already-running dev server.\n watchThemeCss(cssEntry, projectRoot)\n\n return metroConfig\n}\n"],"names":["existsSync","watchFile","onThemeChange","state","getRnwindState","utimesSync","mkdirSync","configureRnwindState","createRnwindResolver","writeDtsFile"],"mappings":"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"}
1
+ {"version":3,"file":"with-config.cjs","sources":["../../../../src/metro/with-config.ts"],"sourcesContent":["import { existsSync, mkdirSync, watch as watchFile } from 'node:fs'\nimport path from 'node:path'\nimport { writeDtsFile } from './dts'\nimport { createRnwindResolver, type ResolveRequestFn } from './resolver'\nimport { configureRnwindState, getRnwindState, onThemeChange } from './state'\n\n/** Default cache directory at the project root. Visible for debugging. */\nconst DEFAULT_CACHE_DIR = '.rnwind'\n\n/**\n * Active CSS watcher — replaced (and the prior one closed) when\n * `withRnwindConfig` is called again (Metro restart, repeated init).\n * Only one watcher per process; no stacking.\n */\nlet activeCssWatcher: { cssPath: string; close: () => void } | null = null\n\n/**\n * Watch the theme CSS for edits. On change, rebuild state against the fresh\n * CSS and rewrite the per-scheme files (`onThemeChange` → full rescan →\n * `writeSchemes`). That's the entire HMR signal: every transformed source\n * imports `rnwind/__generated/schemes`, which eager-imports\n * `common.style.js`; the rewrite changes its bytes, Metro's content-SHA1\n * dedup notices, and every importer is invalidated + re-bundled with the new\n * style values. The rewritten JSX references atoms by NAME (theme-independent),\n * so no source-file re-transform / mtime nudge is needed — the dep graph\n * carries the signal.\n * @param cssPath Absolute path to the theme CSS to watch.\n * @param projectRoot Metro's project root (for `getRnwindState`).\n */\nfunction watchThemeCss(cssPath: string, projectRoot: string): void {\n if (activeCssWatcher?.cssPath === cssPath) return\n activeCssWatcher?.close()\n if (!existsSync(cssPath)) return\n let pending = false\n const watcher = watchFile(cssPath, { persistent: false }, () => {\n // Debounce: editors often emit 2-3 change events per save (atomic\n // rename dance, tmp files). Coalesce to ONE rebuild per microtask.\n if (pending) return\n pending = true\n queueMicrotask(async () => {\n pending = false\n try {\n await onThemeChange(projectRoot)\n } catch {\n // Invalidation is best-effort — never crash the dev server.\n }\n })\n })\n activeCssWatcher = { cssPath, close: () => watcher.close() }\n}\n\n/**\n * Where the rnwind babel transformer lives — resolved relative to this\n * module so the path works from both the `src/` tree (tests) and the\n * built `lib/` output. Tries a few extensions because `require.resolve`\n * doesn't auto-find `.cjs` / `.mjs` from a bare specifier.\n * @returns Absolute path to the rnwind transformer module.\n */\nfunction transformerPath(): string {\n for (const candidate of ['./transformer.cjs', './transformer.mjs', './transformer.js', './transformer.ts', './transformer']) {\n try {\n return require.resolve(candidate)\n } catch {\n // try the next extension\n }\n }\n throw new Error('rnwind: could not resolve the metro transformer path')\n}\n\n/**\n * Resolve the effective cache directory, honoring a user override and\n * falling back to `<projectRoot>/.rnwind`.\n * @param projectRoot Anchor for relative paths.\n * @param override User-supplied option.\n * @returns Absolute cache directory.\n */\nfunction resolveCacheDir(projectRoot: string, override: string | undefined): string {\n if (!override || override.length === 0) return path.resolve(projectRoot, DEFAULT_CACHE_DIR)\n return path.isAbsolute(override) ? override : path.resolve(projectRoot, override)\n}\n\n/**\n * Read the theme CSS and extract `@variant <name>` blocks for the .d.ts\n * generator. Forces construction of `getRnwindState`, then reads\n * `parser.declaredSchemes` (populated synchronously at construction).\n * @param cssEntry Absolute path to theme CSS.\n * @param projectRoot\n * @returns Scheme names (empty when the theme has no variants; `'base'` is filtered).\n */\nfunction discoverSchemes(cssEntry: string, projectRoot: string): readonly string[] {\n if (!existsSync(cssEntry)) return []\n try {\n const { parser } = getRnwindState(projectRoot)\n return parser.declaredSchemes.filter((name) => name !== 'base')\n } catch {\n return []\n }\n}\n\n/** User-facing options for `withRnwindConfig`. */\nexport interface RnwindMetroOptions {\n /** Path to the theme CSS (absolute or relative to `projectRoot`). Required. */\n cssEntryFile: string\n /** Where rnwind writes the `.d.ts` file. Set `false` to disable. Defaults to `<projectRoot>/rnwind-types.d.ts`. */\n dtsFile?: string | false\n /** Optional project-root override — defaults to `metroConfig.projectRoot` then `process.cwd()`. */\n projectRoot?: string\n /** Cache directory. Absolute, or relative to `projectRoot`. Default: `.rnwind` at project root. */\n cacheDir?: string\n /**\n * Extra module specifiers whose component exports rnwind should\n * auto-wrap at import sites — `import { View } from 'react-native'`\n * becomes `const View = wrap(_rnw0)` so `<View className=\"…\">` resolves\n * styles at runtime. Merged with the built-in defaults: `react-native`,\n * `react-native-reanimated`, `react-native-svg`,\n * `react-native-gesture-handler`, `react-native-safe-area-context`,\n * `expo-linear-gradient`, `expo-image`, and more.\n *\n * A module NOT in this list keeps its raw imports — the importing\n * component receives `className` as a plain prop and can resolve it\n * via `useCss` / `wrap` itself. Use this to opt your design-system /\n * UI primitive packages into the auto-wrap path.\n */\n wrapModules?: readonly string[]\n}\n\n/** Shape we mutate on Metro's config. Loose so we don't pin Metro's internal types. */\nexport interface MetroConfigLike {\n projectRoot?: string\n watchFolders?: string[]\n transformer?: {\n babelTransformerPath?: string\n [key: string]: unknown\n }\n resolver?: {\n resolveRequest?: ResolveRequestFn | null\n [key: string]: unknown\n }\n [key: string]: unknown\n}\n\n/**\n * Wrap a Metro config with rnwind's pipeline:\n * - Install the rnwind babel transformer.\n * - Chain a `resolveRequest` hook that serves\n * `rnwind/__generated/schemes` from `<cacheDir>/schemes.js`.\n * - Write the `.d.ts` so TypeScript accepts `className=` on RN components.\n * - Publish the theme CSS path + cache dir via env so Metro workers\n * can rebuild their local state.\n * - Ensure the cache dir is a watched folder Metro's haste-map indexes.\n *\n * Theme-edit hot reload happens implicitly: every transformed file\n * imports `rnwind/__generated/schemes`, and that module eager-imports\n * `common.style.js`. When the theme changes, the per-scheme files\n * regenerate with new bytes; Metro's content SHA1 dedup detects the\n * change and invalidates every importer automatically.\n * `getCacheKey()` on the transformer covers the per-file transform\n * cache. No file watcher / source-padding hack needed — the dep graph\n * carries the signal.\n * @param metroConfig Config from `getDefaultConfig(__dirname)` or equivalent.\n * @param options rnwind options.\n * @returns The same config, mutated.\n */\nexport function withRnwindConfig<C extends MetroConfigLike>(metroConfig: C, options: RnwindMetroOptions): C {\n const projectRoot = options.projectRoot ?? metroConfig.projectRoot ?? process.cwd()\n const cacheDir = resolveCacheDir(projectRoot, options.cacheDir)\n const cssEntry = path.isAbsolute(options.cssEntryFile) ? options.cssEntryFile : path.resolve(projectRoot, options.cssEntryFile)\n\n mkdirSync(cacheDir, { recursive: true })\n const watchFolders = (metroConfig.watchFolders ?? []).filter((p) => typeof p === 'string' && p.length > 0)\n configureRnwindState(cssEntry, cacheDir, watchFolders, options.wrapModules)\n\n // Warm the state eagerly (in the Metro master process) so oxide's\n // Scanner walks every project source (and every monorepo\n // watch-folder) ONCE and the manifest + scheme files hold the\n // complete union before Metro's resolver tries to SHA1 them on the\n // first transform. Each worker lazy-repeats this scan on its first\n // transform to converge on identical state.\n try {\n void getRnwindState(projectRoot).builder.ensureFilesExist()\n } catch {\n // Any init error surfaces again at the first transform; don't crash Metro boot.\n }\n\n // Install transformer + resolver. Capture the existing\n // babelTransformerPath BEFORE we override it — our worker chains to\n // it (env-passed) so Flow / expo-router / babel-preset-expo etc. all\n // continue to run.\n const existingTransformerPath = metroConfig.transformer?.babelTransformerPath\n if (typeof existingTransformerPath === 'string' && existingTransformerPath.length > 0) {\n process.env.RNWIND_UPSTREAM_TRANSFORMER = existingTransformerPath\n }\n const upstream = metroConfig.resolver?.resolveRequest ?? null\n metroConfig.transformer = { ...metroConfig.transformer, babelTransformerPath: transformerPath() }\n metroConfig.resolver = { ...metroConfig.resolver, resolveRequest: createRnwindResolver(upstream) }\n\n // Metro's haste-map indexes `watchFolders` at startup. Adding the\n // cache dir guarantees scheme style files + manifest get SHA1'd\n // without a \"Failed to get the SHA-1\" race when the first transform\n // writes them.\n const existingWatch = metroConfig.watchFolders ?? []\n metroConfig.watchFolders = existingWatch.includes(cacheDir) ? existingWatch : [...existingWatch, cacheDir]\n\n if (options.dtsFile !== false) {\n const dtsPath = options.dtsFile ?? path.resolve(projectRoot, 'rnwind-types.d.ts')\n const schemes = discoverSchemes(cssEntry, projectRoot)\n writeDtsFile(dtsPath, schemes)\n }\n\n // Watch the theme CSS. On edit, we rewrite scheme files AND touch\n // mtime on every transformed source file so Metro invalidates them\n // and re-transforms — the only reliable way to propagate theme\n // changes to an already-running dev server.\n watchThemeCss(cssEntry, projectRoot)\n\n return metroConfig\n}\n"],"names":["existsSync","watchFile","onThemeChange","getRnwindState","mkdirSync","configureRnwindState","createRnwindResolver","writeDtsFile"],"mappings":"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"}
@@ -42,23 +42,26 @@ function useToken(cssVariable) {
42
42
  }
43
43
  /**
44
44
  * Read a color token by shorthand name — `useColor('primary')` resolves
45
- * `--color-primary` for the active scheme.
46
- * @param name Token suffix after `--color-`.
45
+ * `--color-primary` for the active scheme. A fully-qualified name
46
+ * (`--color-primary`) is accepted as-is, so the call doesn't silently miss by
47
+ * double-prefixing into `--color---color-primary`.
48
+ * @param name Token suffix after `--color-`, or the full `--color-*` name.
47
49
  * @returns Resolved color string, or undefined when the token is missing
48
50
  * or its value isn't a string.
49
51
  */
50
52
  function useColor(name) {
51
- const value = useToken(`--color-${name}`);
53
+ const value = useToken(name.startsWith('--') ? name : `--color-${name}`);
52
54
  return typeof value === 'string' ? value : undefined;
53
55
  }
54
56
  /**
55
57
  * Read a spacing token by shorthand name — `useSize('4')` resolves
56
- * `--spacing-4` for the active scheme.
57
- * @param name Token suffix after `--spacing-`.
58
+ * `--spacing-4` for the active scheme. A fully-qualified `--spacing-*` name is
59
+ * accepted as-is (no double-prefix miss).
60
+ * @param name Token suffix after `--spacing-`, or the full `--spacing-*` name.
58
61
  * @returns Resolved spacing value, or undefined when the token is missing.
59
62
  */
60
63
  function useSize(name) {
61
- return useToken(`--spacing-${name}`);
64
+ return useToken(name.startsWith('--') ? name : `--spacing-${name}`);
62
65
  }
63
66
 
64
67
  exports.useColor = useColor;
@@ -1 +1 @@
1
- {"version":3,"file":"use-scheme.cjs","sources":["../../../../../src/runtime/hooks/use-scheme.ts"],"sourcesContent":["import type { ThemeTable } from '../../core/types'\nimport { useRnwind } from '../components/rnwind-provider'\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 const base = tables[BASE_SCHEME] ?? {}\n const schemeTable = tables[scheme]\n if (!schemeTable) return base\n // Fast path: nothing to merge when the scheme table is empty.\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.\n * @param name Token suffix after `--color-`.\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(`--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.\n * @param name Token suffix after `--spacing-`.\n * @returns Resolved spacing value, or undefined when the token is missing.\n */\nexport function useSize(name: string): number | string | undefined {\n return useToken(`--spacing-${name}`)\n}\n"],"names":["useRnwind"],"mappings":";;;;AAGA;;;;AAIG;AACH,MAAM,WAAW,GAAG,MAAM;AAE1B;;;;;;;;;AASG;SACa,QAAQ,GAAA;IACtB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAGA,wBAAS,EAAE;IACtC,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE;AACtC,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;AAClC,IAAA,IAAI,CAAC,WAAW;AAAE,QAAA,OAAO,IAAI;;IAE7B,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;;;;;;AAMG;AACG,SAAU,QAAQ,CAAC,IAAY,EAAA;IACnC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,IAAI,CAAA,CAAE,CAAC;AACzC,IAAA,OAAO,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,SAAS;AACtD;AAEA;;;;;AAKG;AACG,SAAU,OAAO,CAAC,IAAY,EAAA;AAClC,IAAA,OAAO,QAAQ,CAAC,CAAA,UAAA,EAAa,IAAI,CAAA,CAAE,CAAC;AACtC;;;;;;;"}
1
+ {"version":3,"file":"use-scheme.cjs","sources":["../../../../../src/runtime/hooks/use-scheme.ts"],"sourcesContent":["import type { ThemeTable } from '../../core/types'\nimport { useRnwind } from '../components/rnwind-provider'\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 const base = tables[BASE_SCHEME] ?? {}\n const schemeTable = tables[scheme]\n if (!schemeTable) return base\n // Fast path: nothing to merge when the scheme table is empty.\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":["useRnwind"],"mappings":";;;;AAGA;;;;AAIG;AACH,MAAM,WAAW,GAAG,MAAM;AAE1B;;;;;;;;;AASG;SACa,QAAQ,GAAA;IACtB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAGA,wBAAS,EAAE;IACtC,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE;AACtC,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;AAClC,IAAA,IAAI,CAAC,WAAW;AAAE,QAAA,OAAO,IAAI;;IAE7B,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;;;;;;;"}
@@ -19,16 +19,19 @@ export declare function useTheme(): ThemeTable;
19
19
  export declare function useToken(cssVariable: string): string | number | undefined;
20
20
  /**
21
21
  * Read a color token by shorthand name — `useColor('primary')` resolves
22
- * `--color-primary` for the active scheme.
23
- * @param name Token suffix after `--color-`.
22
+ * `--color-primary` for the active scheme. A fully-qualified name
23
+ * (`--color-primary`) is accepted as-is, so the call doesn't silently miss by
24
+ * double-prefixing into `--color---color-primary`.
25
+ * @param name Token suffix after `--color-`, or the full `--color-*` name.
24
26
  * @returns Resolved color string, or undefined when the token is missing
25
27
  * or its value isn't a string.
26
28
  */
27
29
  export declare function useColor(name: string): string | undefined;
28
30
  /**
29
31
  * Read a spacing token by shorthand name — `useSize('4')` resolves
30
- * `--spacing-4` for the active scheme.
31
- * @param name Token suffix after `--spacing-`.
32
+ * `--spacing-4` for the active scheme. A fully-qualified `--spacing-*` name is
33
+ * accepted as-is (no double-prefix miss).
34
+ * @param name Token suffix after `--spacing-`, or the full `--spacing-*` name.
32
35
  * @returns Resolved spacing value, or undefined when the token is missing.
33
36
  */
34
37
  export declare function useSize(name: string): number | string | undefined;
@@ -14,7 +14,7 @@ var useScheme = require('./hooks/use-scheme.cjs');
14
14
  * string when integrating with build tooling that may see multiple rnwind
15
15
  * copies (e.g. workspace overrides).
16
16
  */
17
- const VERSION = '0.0.1';
17
+ const VERSION = '0.0.8';
18
18
 
19
19
  exports.activeBreakpointFor = lookupCss.activeBreakpointFor;
20
20
  exports.getBreakpoints = lookupCss.getBreakpoints;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../../src/runtime/index.ts"],"sourcesContent":["export {\n lookupCss,\n registerAtoms,\n registerBreakpoints,\n registerSchemeLoader,\n setWindowHeightProvider,\n getBreakpoints,\n activeBreakpointFor,\n} from './lookup-css'\nexport type { HoistedClassName, InteractState, LookupInsets, SafeMarkerSpec } from './lookup-css'\nexport { wrap, wrapNamespace } from './wrap'\nexport { resolve, registerMolecules, registerGradients, registerHaptics } from './resolve'\nexport type { ResolvedCss } from './resolve'\nexport { useCss } from './hooks/use-css'\nexport { useInteract } from './hooks/use-interact'\nexport type { UseInteractResult } from './hooks/use-interact'\nexport { chainPress, chainFocus } from './chain-handlers'\nexport { RnwindProvider, useRnwind } from './components/rnwind-provider'\nexport type { RnwindProviderProps, RnwindState, Insets } from './components/rnwind-provider'\nexport type { HapticRequest, HapticTrigger, OnHaptics } from '../core/parser/haptics'\nexport type { AsLinearGradientProps, LinearGradientPoint } from './gradient-types'\nexport type { ThemeTable, ThemeTables } from '../core/types'\nexport { useTheme, useToken, useColor, useSize } from './hooks/use-scheme'\nexport type { Scheme, RnwindConfig } from './types'\n\n/**\n * Installed rnwind version, inlined at publish time. Compare against a pinned\n * string when integrating with build tooling that may see multiple rnwind\n * copies (e.g. workspace overrides).\n */\nexport const VERSION = '0.0.1' as const\n"],"names":[],"mappings":";;;;;;;;;;;AAyBA;;;;AAIG;AACI,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../../src/runtime/index.ts"],"sourcesContent":["export {\n lookupCss,\n registerAtoms,\n registerBreakpoints,\n registerSchemeLoader,\n setWindowHeightProvider,\n getBreakpoints,\n activeBreakpointFor,\n} from './lookup-css'\nexport type { HoistedClassName, InteractState, LookupInsets, SafeMarkerSpec } from './lookup-css'\nexport { wrap, wrapNamespace } from './wrap'\nexport { resolve, registerMolecules, registerGradients, registerHaptics } from './resolve'\nexport type { ResolvedCss } from './resolve'\nexport { useCss } from './hooks/use-css'\nexport { useInteract } from './hooks/use-interact'\nexport type { UseInteractResult } from './hooks/use-interact'\nexport { chainPress, chainFocus } from './chain-handlers'\nexport { RnwindProvider, useRnwind } from './components/rnwind-provider'\nexport type { RnwindProviderProps, RnwindState, Insets } from './components/rnwind-provider'\nexport type { HapticRequest, HapticTrigger, OnHaptics } from '../core/parser/haptics'\nexport type { AsLinearGradientProps, LinearGradientPoint } from './gradient-types'\nexport type { ThemeTable, ThemeTables } from '../core/types'\nexport { useTheme, useToken, useColor, useSize } from './hooks/use-scheme'\nexport type { Scheme, RnwindConfig } from './types'\n\n/**\n * Installed rnwind version, inlined at publish time. Compare against a pinned\n * string when integrating with build tooling that may see multiple rnwind\n * copies (e.g. workspace overrides).\n */\nexport const VERSION = '0.0.8' as const\n"],"names":[],"mappings":";;;;;;;;;;;AAyBA;;;;AAIG;AACI,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -19,4 +19,4 @@ export type { Scheme, RnwindConfig } from './types';
19
19
  * string when integrating with build tooling that may see multiple rnwind
20
20
  * copies (e.g. workspace overrides).
21
21
  */
22
- export declare const VERSION: "0.0.1";
22
+ export declare const VERSION: "0.0.8";
@@ -253,6 +253,19 @@ function tierFor(windowWidth) {
253
253
  }
254
254
  return tier;
255
255
  }
256
+ /**
257
+ * Public breakpoint-tier for a width — the count of registered breakpoints
258
+ * whose threshold is reached. Used by the runtime resolver as its width
259
+ * cache dimension: the numeric tier is bounded AND exact, unlike the
260
+ * clamped `activeBreakpoint` NAME (which collapses tier-0 into the smallest
261
+ * breakpoint, so widths straddling that threshold would share a cache key
262
+ * and serve a stale style).
263
+ * @param windowWidth Live window width in px.
264
+ * @returns Tier 0..N.
265
+ */
266
+ function breakpointTier(windowWidth) {
267
+ return tierFor(windowWidth);
268
+ }
256
269
  /**
257
270
  * Build the style array for a (hoist, scheme, state, width) tuple.
258
271
  * Walks the atom list, applies the interact-state and breakpoint
@@ -541,6 +554,7 @@ function __resetLookupCssState() {
541
554
  exports.BASE_BREAKPOINT = BASE_BREAKPOINT;
542
555
  exports.__resetLookupCssState = __resetLookupCssState;
543
556
  exports.activeBreakpointFor = activeBreakpointFor;
557
+ exports.breakpointTier = breakpointTier;
544
558
  exports.getBreakpoints = getBreakpoints;
545
559
  exports.getStyleVersion = getStyleVersion;
546
560
  exports.loadScheme = loadScheme;
@@ -1 +1 @@
1
- {"version":3,"file":"lookup-css.cjs","sources":["../../../../src/runtime/lookup-css.ts"],"sourcesContent":["/**\n * Runtime resolver for rnwind-transformed files.\n *\n * Hot path is ONE WeakMap.get + cached-array return for stable atoms\n * (no `active:`/`focus:`/`*-safe` variance beyond what the cache key\n * captures). First call per (hoist, scheme, stateIndex) walks the\n * atoms once, looks each up as\n *\n * `cache.atoms[scheme]?.[atom] ?? cache.atoms.common?.[atom]`\n *\n * and caches the result. `registerAtoms(scheme, record)` bumps a\n * version counter; the next lookup notices the mismatch and rebuilds.\n *\n * Keyframes are inlined directly into atom values via `animationName`\n * at build time — no separate registry.\n */\n\nimport type { RnwindState } from './components/rnwind-provider'\n\n/** Empty sentinel returned when the input is null / undefined / empty. */\nconst EMPTY_STYLES: readonly unknown[] = []\n\n/** Registry key for the always-loaded fallback scheme. */\nconst COMMON_SCHEME = 'common'\n\n/** Atom name prefix marking a press-state-gated atom. */\nconst ACTIVE_PREFIX = 'active:'\n\n/** Atom name prefix marking a focus-state-gated atom. */\nconst FOCUS_PREFIX = 'focus:'\n\n/** Partial record — missing keys resolve to undefined, which the fallback handles. */\ntype SchemeAtomsRecord = Partial<Record<string, unknown>>\n\n/** 0 = idle, 1 = active, 2 = focus, 3 = both. */\ntype StateIndex = 0 | 1 | 2 | 3\n\n/**\n * One entry in the sorted-by-threshold breakpoints array. The runtime\n * derives an atom's threshold by matching its `<prefix>:` against\n * `name`; the array form is preferred over a Map so the hot-path\n * `tierFor(width)` walk is a tight numeric loop.\n */\ninterface BreakpointEntry {\n readonly name: string\n readonly minWidth: number\n}\n\n/**\n * Process-global style cache. Replaced key-by-key by {@link registerAtoms}.\n * Plain record-of-records: `scheme → atom → style`. Active scheme\n * lookup is `cache.atoms[scheme]?.[atom]` — two property reads with\n * an `?? cache.atoms.common[atom]` fallback. No loops over the\n * registry, ever.\n *\n * `breakpoints` mirrors the build-time table the manifest module\n * registers via {@link registerBreakpoints} — `name → px-threshold` for\n * fast prefix-based atom filtering plus the sorted-by-threshold list\n * for cheap tier-index computation in `lookupCss`.\n */\nconst cache = {\n atoms: Object.create(null) as Partial<Record<string, SchemeAtomsRecord>>,\n breakpoints: Object.create(null) as Partial<Record<string, number>>,\n breakpointList: [] as readonly BreakpointEntry[],\n}\n\n/**\n * Bumps on every {@link registerAtoms} call. {@link HoistCache} entries\n * stamp themselves with the current version; a mismatch on read\n * triggers a rebuild so HMR-reloaded atoms propagate without manual\n * invalidation.\n */\nlet atomVersion = 0\n\n/** Optional window-height provider for the `screen-minus-y` marker. */\ntype WindowHeightProvider = () => number\nlet windowHeightProvider: WindowHeightProvider | null = null\n\n/**\n * Optional scheme loader. Registered by the generated manifest module\n * (`rnwind/__generated/schemes`) once at import time. SchemeProvider\n * calls it synchronously on every render with the active scheme name;\n * first call per scheme pulls the scheme's style module in via an\n * inline `require()` — subsequent calls are a no-op through Metro's\n * module cache.\n */\ntype SchemeLoader = (scheme: string) => void\nlet schemeLoader: SchemeLoader | null = null\n\n/** Module-scope flag so the missing-insets warning fires at most once. */\nlet WARNED_MISSING_INSETS = false\n\n/** Atoms we've already dev-warned about — keeps the noise to ONE line per typo per session. */\nconst WARNED_UNKNOWN_ATOMS = new Set<string>()\n\n/**\n * Compute the state-array index from the live interactState. Bit-or\n * encoding: 0 = idle, 1 = active, 2 = focus, 3 = both.\n * @param interactState Snapshot from `useInteract()` (or undefined).\n * @returns 0 / 1 / 2 / 3.\n */\nfunction stateIndexFor(interactState: InteractState | undefined): StateIndex {\n if (!interactState) return 0\n return (((interactState.active ? 1 : 0) | (interactState.focus ? 2 : 0)) as StateIndex)\n}\n\n/**\n * Fetch the px inset for one side. Falls back to 0 when insets is undefined.\n * @param side Compact side tag (`t` / `r` / `b` / `l`).\n * @param insets Active insets.\n * @returns Px value for that side.\n */\nfunction insetOf(side: string, insets: LookupInsets | undefined): number {\n if (!insets) return 0\n if (side === 't') return insets.top\n if (side === 'r') return insets.right\n if (side === 'b') return insets.bottom\n if (side === 'l') return insets.left\n return 0\n}\n\n/**\n * Collapse one safe-area marker into a concrete px number using the\n * active insets.\n * @param spec Marker spec tuple `[cssKey, sideTag, or, offset]`.\n * @param insets Active insets (or undefined → 0).\n * @returns Resolved px number.\n */\nfunction resolveMarker(spec: SafeMarkerSpec, insets: LookupInsets | undefined): number {\n const [, side, or_, offset] = spec\n if (side === 'screen-minus-y') {\n const h = windowHeightProvider ? windowHeightProvider() : 0\n return Math.max(0, h - insetOf('t', insets) - insetOf('b', insets))\n }\n let base = insetOf(side, insets)\n if (or_ !== undefined) base = Math.max(base, or_)\n if (offset !== undefined) base += offset\n return base\n}\n\n/**\n * Emit a one-shot dev warning when a safe-area atom resolves without\n * real insets in scope.\n * @param insets Insets received by the resolver.\n */\nfunction warnMissingInsetsOnce(insets: LookupInsets | undefined): void {\n if (WARNED_MISSING_INSETS) return\n const isDevelopment = typeof __DEV__ === 'undefined' || __DEV__\n if (!isDevelopment) return\n if (insets && (insets.top !== 0 || insets.right !== 0 || insets.bottom !== 0 || insets.left !== 0)) return\n WARNED_MISSING_INSETS = true\n // eslint-disable-next-line no-console\n console.warn(\n 'rnwind: a `*-safe` utility resolved with zero insets. Wire `insets` on <SchemeProvider> ' +\n '(e.g. `insets={useSafeAreaInsets()}` from react-native-safe-area-context).',\n )\n}\n\n/**\n * Resolve precomputed safe-area marker specs into a fresh RN style\n * object. Cannot be cached — insets vary per render with rotation /\n * keyboard.\n * @param specs Array of spec tuples.\n * @param insets Live safe-area insets.\n * @returns Fresh RN style object with concrete numbers.\n */\nfunction resolveSafe(specs: readonly SafeMarkerSpec[], insets: LookupInsets | undefined): Record<string, number> {\n warnMissingInsetsOnce(insets)\n const out: Record<string, number> = {}\n for (const spec of specs) out[spec[0]] = resolveMarker(spec, insets)\n return out\n}\n\n/**\n * Multiply `fontSize` / `lineHeight` in a resolved atom value by the\n * active font scale. Early-returns the original reference for any atom\n * that doesn't carry either property (most of them) — zero allocation\n * on the hot path for non-text atoms.\n * @param value Atom value as registered in the global table.\n * @param fontScale Multiplier from `useWindowDimensions().fontScale`.\n * @returns Scaled style object, or the original when no scaling applied.\n */\nfunction applyFontScale(value: unknown, fontScale: number): unknown {\n if (fontScale === 1) return value\n if (typeof value !== 'object' || value === null) return value\n const record = value as Record<string, unknown>\n const fs = record.fontSize\n const lh = record.lineHeight\n if (typeof fs !== 'number' && typeof lh !== 'number') return value\n const scaled: Record<string, unknown> = { ...record }\n if (typeof fs === 'number') scaled.fontSize = fs * fontScale\n if (typeof lh === 'number') scaled.lineHeight = lh * fontScale\n return scaled\n}\n\n/**\n * Read the precomputed safe-area marker spec list off an atom value.\n * Build-side `envelopeSafeMarkers` wraps safe atoms in\n * `{__safeStyle: [...]}`; this is a single property access.\n * @param value Atom value as registered in the global table.\n * @returns Spec array when the atom is safe-area, else null.\n */\nfunction readSafeSpecs(value: unknown): readonly SafeMarkerSpec[] | null {\n if (typeof value !== 'object' || value === null) return null\n const safe = (value as { __safeStyle?: readonly SafeMarkerSpec[] }).__safeStyle\n return safe ?? null\n}\n\n/**\n * Per-atom lookup. Two property reads: scheme's own table then the\n * common fallback. Returns `undefined` for unknown atoms — the caller\n * skips them.\n * @param scheme Active scheme.\n * @param atom Atom name.\n * @returns Resolved value, or undefined.\n */\nfunction lookupAtom(scheme: string, atom: string): unknown {\n const schemeTable = cache.atoms[scheme]\n if (schemeTable !== undefined) {\n const own = schemeTable[atom]\n if (own !== undefined) return own\n }\n const common = cache.atoms[COMMON_SCHEME]\n return common === undefined ? undefined : common[atom]\n}\n\n/**\n * Whether an atom should participate in a given interact-state index.\n * - idle (0): no `active:` / `focus:` atoms.\n * - active (1): base + `active:`.\n * - focus (2): base + `focus:`.\n * - both (3): base + `active:` + `focus:`.\n * @param atom Atom name.\n * @param stateIndex Encoded state (0/1/2/3).\n * @returns True when the atom should be emitted for this state.\n */\nfunction atomMatchesState(atom: string, stateIndex: StateIndex): boolean {\n // Cheap prefix check — check the first code point before the full\n // `startsWith` so we skip it for any atom whose first letter isn't\n // `a` / `f`.\n const code = atom.codePointAt(0)\n if (code === 97 /* a */ && atom.startsWith(ACTIVE_PREFIX)) return (stateIndex & 1) !== 0\n if (code === 102 /* f */ && atom.startsWith(FOCUS_PREFIX)) return (stateIndex & 2) !== 0\n return true\n}\n\n/**\n * Whether an atom passes the responsive-breakpoint gate for the\n * current `windowWidth`. Atoms without a registered `<prefix>:` are\n * always-on (the common case — `bg-red-500`, `active:bg-blue-700`).\n * Atoms whose first prefix matches a registered breakpoint name pass\n * only when `windowWidth >= threshold`.\n * @param atom Atom name.\n * @param windowWidth Live `useWindowDimensions().width` snapshot.\n * @returns True when the atom should be emitted for this width.\n */\nfunction atomMatchesBreakpoint(atom: string, windowWidth: number): boolean {\n const colon = atom.indexOf(':')\n if (colon === -1) return true\n const prefix = atom.slice(0, colon)\n const threshold = cache.breakpoints[prefix]\n if (threshold === undefined) return true\n return windowWidth >= threshold\n}\n\n/**\n * Tier index — count of registered breakpoints whose threshold is\n * `<= windowWidth`. Bounded by the breakpoint count, so it's a stable\n * cache-key dimension instead of the unbounded raw width. Crossings\n * happen ~5 times across the device-width spectrum, not per-pixel.\n * @param windowWidth Live width.\n * @returns Tier 0..N where N = `cache.breakpointList.length`.\n */\nfunction tierFor(windowWidth: number): number {\n let tier = 0\n for (const entry of cache.breakpointList) {\n if (windowWidth >= entry.minWidth) tier += 1\n else break\n }\n return tier\n}\n\n/**\n * Build the style array for a (hoist, scheme, state, width) tuple.\n * Walks the atom list, applies the interact-state and breakpoint\n * filters, resolves each atom via scheme→common fallback, and\n * envelopes safe values via {@link resolveSafe}.\n * @param atoms Atom name list (build-time constant).\n * @param scheme Active scheme.\n * @param stateIndex Encoded active/focus state.\n * @param insets Live safe-area insets.\n * @param fontScale Font scale multiplier.\n * @param windowWidth Live window width — gates `md:*` / `lg:*` atoms.\n * @returns Fresh style array.\n */\nfunction buildStyleArray(\n atoms: readonly string[],\n scheme: string,\n stateIndex: StateIndex,\n insets: LookupInsets | undefined,\n fontScale: number,\n windowWidth: number,\n): readonly unknown[] {\n const out: unknown[] = []\n for (const atom of atoms) {\n if (!atomMatchesState(atom, stateIndex)) continue\n if (!atomMatchesBreakpoint(atom, windowWidth)) continue\n const value = lookupAtom(scheme, atom)\n if (value === undefined) {\n warnUnknownAtomOnce(atom)\n continue\n }\n const safe = readSafeSpecs(value)\n const resolved = safe === null ? value : resolveSafe(safe, insets)\n out.push(applyFontScale(resolved, fontScale))\n }\n return out\n}\n\n/**\n * Emit a one-shot dev warning when an atom name doesn't resolve in the\n * registry. The two real causes are a typo (`bg-red-501`) or a class\n * the build-time scanner never saw because it lives in a string the\n * oxide tokeniser can't see (e.g. computed at runtime). Either way, a\n * silent empty style is the worst possible UX — surface it.\n *\n * Filters cosmetic non-issues: empty strings, build-time `__safeStyle`\n * envelopes that wandered in, etc.\n * @param atom Class name that didn't resolve.\n */\nfunction warnUnknownAtomOnce(atom: string): void {\n if (atom.length === 0) return\n const isDevelopment = typeof __DEV__ === 'undefined' || __DEV__\n if (!isDevelopment) return\n if (WARNED_UNKNOWN_ATOMS.has(atom)) return\n WARNED_UNKNOWN_ATOMS.add(atom)\n // eslint-disable-next-line no-console\n console.warn(\n `rnwind: unknown class \"${atom}\" — typo, or the class is built dynamically and the build-time ` +\n `scanner never saw it. Static literals + ternaries are scanned automatically; runtime-built ` +\n `strings need to appear somewhere as a literal so oxide can pick them up.`,\n )\n}\n\n/**\n * Per-hoist cache entry. `version` stamps `atomVersion` at build time\n * so HMR reloads (which bump the counter) invalidate cleanly on next\n * read. `hasSafe` prevents caching results whose values depend on\n * per-render insets. `byKey` maps `\"${scheme}|${stateIndex}\"` to the\n * cached result.\n */\ninterface HoistCache {\n version: number\n hasSafe: boolean\n byKey: Partial<Record<string, readonly unknown[]>>\n}\n\n/**\n * Per-atom-list cache keyed on the hoist reference. WeakMap so\n * hoists GC with their host module on HMR.\n */\nconst resultCache = new WeakMap<readonly string[], HoistCache>()\n\n/**\n * Walk the atom list once to detect safe-area atoms — results that\n * vary per render with `insets`. When any atom envelopes safe specs\n * we skip the cache and rebuild every call.\n * @param atoms Hoist atom list.\n * @param scheme Active scheme.\n * @returns Whether the hoist resolves a safe atom under this scheme.\n */\nfunction detectHasSafe(atoms: readonly string[], scheme: string): boolean {\n for (const atom of atoms) {\n const value = lookupAtom(scheme, atom)\n if (readSafeSpecs(value) !== null) return true\n }\n return false\n}\n\n/**\n * Cache-keyed resolution for the common static-schema case. Returns a\n * stable array reference across renders until `atomVersion` bumps.\n * For hoists containing safe atoms — which depend on per-render\n * insets — rebuilds every call.\n *\n * The `tier` dimension keeps the cache bounded under responsive\n * variants: instead of keying on raw `windowWidth` (which would explode\n * the cache to one entry per pixel), we key on the count of registered\n * breakpoints whose threshold is reached. That gives at most\n * `breakpointCount + 1` cache rows per (scheme, state, fontScale).\n * @param atoms Hoist atom list.\n * @param scheme Active scheme.\n * @param stateIndex Encoded interact state.\n * @param insets Live safe-area insets.\n * @param fontScale Font scale multiplier.\n * @param windowWidth Live window width.\n * @returns Style array.\n */\nfunction lookupCached(\n atoms: readonly string[],\n scheme: string,\n stateIndex: StateIndex,\n insets: LookupInsets | undefined,\n fontScale: number,\n windowWidth: number,\n): readonly unknown[] {\n let entry = resultCache.get(atoms)\n if (entry?.version !== atomVersion) {\n entry = { version: atomVersion, hasSafe: detectHasSafe(atoms, scheme), byKey: Object.create(null) }\n resultCache.set(atoms, entry)\n }\n if (entry.hasSafe) return buildStyleArray(atoms, scheme, stateIndex, insets, fontScale, windowWidth)\n const tier = tierFor(windowWidth)\n const key = `${scheme}|${stateIndex}|${fontScale}|${tier}`\n const cached = entry.byKey[key]\n if (cached !== undefined) return cached\n const fresh = buildStyleArray(atoms, scheme, stateIndex, insets, fontScale, windowWidth)\n entry.byKey[key] = fresh\n return fresh\n}\n\n/**\n * Per-render snapshot of which interactive states (active, focus) are\n * currently engaged. Forwarded from the `useInteract()` hook the\n * transformer injects.\n */\nexport interface InteractState {\n active?: boolean\n focus?: boolean\n}\n\n/**\n * Safe-area insets bundle the transformer passes to `lookupCss` when a\n * file uses any `*-safe` utility.\n */\nexport interface LookupInsets {\n top: number\n right: number\n bottom: number\n left: number\n}\n\n\n/**\n * Precomputed safe-area marker spec emitted by the build-side\n * `envelopeSafeMarkers`. Tuple form: `[cssKey, sideTag, or, offset]`.\n */\nexport type SafeMarkerSpec = readonly [string, string, number | undefined, number | undefined]\n\n/** Type alias: the atom-list build output the transformer emits. */\nexport type HoistedClassName = readonly string[]\n\n/**\n * Register a window-height provider used by the `screen-minus-y`\n * safe-area variant. When not wired, `h-screen-safe` resolves to `0`.\n * @param provider Callback returning the current window height in px.\n */\nexport function setWindowHeightProvider(provider: WindowHeightProvider | null): void {\n windowHeightProvider = provider\n}\n\n/**\n * Register the scheme-loader function exported by the generated\n * manifest module. Called once at manifest-module evaluation time —\n * subsequent registrations override the previous loader (useful for\n * tests).\n * @param loader Manifest's `ensureSchemeLoaded` function, or null to\n * detach (tests).\n */\nexport function registerSchemeLoader(loader: SchemeLoader | null): void {\n schemeLoader = loader\n}\n\n/**\n * Ensure the given scheme's style module is loaded. Safe to call in\n * render — zero-cost after the first call per scheme thanks to\n * Metro's module cache, and a no-op when no loader is registered\n * (tests, or a bundle without rnwind-transformed sources).\n * @param scheme Active scheme name.\n */\nexport function loadScheme(scheme: string): void {\n if (schemeLoader) schemeLoader(scheme)\n}\n\n/**\n * Register (or re-register) one scheme's atoms in the global registry.\n * Pure property assignment — no iteration, no allocation. The version\n * counter bump invalidates every hoist-level result cache lazily on\n * next read.\n * @param scheme Registry key — `'common'` for the always-loaded\n * fallback, or a variant name (`'dark'`, `'light'`, `'brand'`, ...).\n * @param atoms Plain record keyed by atom name.\n */\nexport function registerAtoms(scheme: string, atoms: Record<string, unknown>): void {\n cache.atoms[scheme] = atoms\n atomVersion += 1\n}\n\n/**\n * Current registry version — bumps on every `registerAtoms` /\n * `registerBreakpoints`. The molecule resolver folds it into its cache\n * key so an HMR atom reload invalidates derived results.\n * @returns Monotonic version counter.\n */\nexport function getStyleVersion(): number {\n return atomVersion\n}\n\n/**\n * Register the responsive-breakpoint table the manifest module emits at\n * load time. Replaces the prior table — calling with `{}` clears it.\n * Bumps `atomVersion` so any cached lookup invalidates on next read,\n * which matters during a theme HMR cycle that adds/removes breakpoints.\n * @param breakpoints Breakpoint name → minimum-width threshold (px).\n */\nexport function registerBreakpoints(breakpoints: Record<string, number>): void {\n const fresh: Partial<Record<string, number>> = Object.create(null)\n const list: BreakpointEntry[] = []\n for (const name of Object.keys(breakpoints)) {\n const minWidth = breakpoints[name]\n if (!Number.isFinite(minWidth) || minWidth <= 0) continue\n fresh[name] = minWidth\n list.push({ name, minWidth })\n }\n list.sort((a, b) => a.minWidth - b.minWidth || a.name.localeCompare(b.name))\n cache.breakpoints = fresh\n cache.breakpointList = list\n atomVersion += 1\n}\n\n/**\n * Snapshot of the registered breakpoints, for callers that want to\n * compute their own derivations (e.g. the provider deriving the active\n * breakpoint name). Returns a fresh array — callers can iterate without\n * worrying about concurrent mutation from a manifest reload.\n * @returns Breakpoints sorted by ascending min-width threshold.\n */\nexport function getBreakpoints(): readonly BreakpointEntry[] {\n return cache.breakpointList\n}\n\n/**\n * Sentinel name returned by {@link activeBreakpointFor} ONLY when no\n * breakpoints are registered at all (bundle without rnwind-transformed\n * sources, fresh test setup). When at least one breakpoint is\n * registered, the function falls back to the smallest registered name\n * instead — so phone-width devices (402 dp on a stock iPhone, well\n * below `sm = 640`) report `activeBreakpoint === 'sm'` rather than the\n * abstract `'base'`. This matches the user expectation that the value\n * is always a real Tailwind breakpoint label they can branch on.\n *\n * Note: this is decoupled from the className filter. `sm:*` atoms\n * still only fire at `windowWidth >= 640` per Tailwind's mobile-first\n * spec — `activeBreakpoint === 'sm'` at 402 means \"I'm in the smallest\n * tier\", not \"`sm:` classes are firing\".\n */\nexport const BASE_BREAKPOINT = 'base'\n\n/**\n * Resolve the currently-active breakpoint name for a width:\n * - `windowWidth >= some threshold` → the highest matching breakpoint name.\n * - below every registered threshold → the smallest registered name.\n * - no breakpoints registered → {@link BASE_BREAKPOINT}.\n * Always returns a string so consumers can branch on it without\n * null-handling.\n * @param windowWidth Live window width in px.\n * @returns Active breakpoint name (never null).\n */\nexport function activeBreakpointFor(windowWidth: number): string {\n const list = cache.breakpointList\n if (list.length === 0) return BASE_BREAKPOINT\n let active: string = list[0]!.name\n for (const entry of list) {\n if (windowWidth >= entry.minWidth) active = entry.name\n else break\n }\n return active\n}\n\n/**\n * Resolve a className input against the active rnwind context. Hot\n * path:\n * - Array input (build hoist): ONE WeakMap.get + ONE record-access\n * + cached array return. No per-render allocation when there's no\n * userStyle and the hoist has no safe atoms.\n * - String input (dynamic `className={expr}`): tokenise + walk.\n * @param input Hoisted atom list or raw className string.\n * @param ctx Rnwind context — `{scheme, fontScale, insets}` (extra\n * fields ignored). Pass the result of `useRnwind()` directly.\n * @param userStyle Optional caller-supplied style appended last.\n * @param interactState Live active/focus flags from `useInteract()`.\n * @returns Style array for React Native's `style` prop.\n */\nexport function lookupCss(\n input: HoistedClassName | string | null | undefined,\n ctx: RnwindState,\n userStyle?: unknown,\n interactState?: InteractState,\n): readonly unknown[] {\n if (input === null || input === undefined) {\n return userStyle === undefined || userStyle === null ? EMPTY_STYLES : [userStyle]\n }\n const { scheme, insets, fontScale, windowWidth } = ctx\n if (typeof input === 'string') {\n const trimmed = input.trim()\n if (trimmed.length === 0) {\n return userStyle === undefined || userStyle === null ? EMPTY_STYLES : [userStyle]\n }\n const atoms = trimmed.split(/\\s+/)\n const out = buildStyleArray(atoms, scheme, stateIndexFor(interactState), insets, fontScale, windowWidth)\n if (userStyle === undefined || userStyle === null) return out\n return [...out, userStyle]\n }\n const base = lookupCached(input, scheme, stateIndexFor(interactState), insets, fontScale, windowWidth)\n if (userStyle === undefined || userStyle === null) return base\n return [...base, userStyle]\n}\n\n/** Test-only — clear the global registry between suites. */\nexport function __resetLookupCssState(): void {\n for (const key of Object.keys(cache.atoms)) delete cache.atoms[key]\n for (const key of Object.keys(cache.breakpoints)) delete cache.breakpoints[key]\n cache.breakpointList = []\n windowHeightProvider = null\n schemeLoader = null\n WARNED_MISSING_INSETS = false\n WARNED_UNKNOWN_ATOMS.clear()\n atomVersion += 1\n}\n\n/**\n * Test-only sugar: accept a single-scheme record and register it as the\n * `common` table.\n * @param record Atom name → value record (registered under `common`).\n */\nexport function __registerAtomsFromRecord(record: Record<string, unknown>): void {\n registerAtoms(COMMON_SCHEME, record)\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lookup-css.cjs","sources":["../../../../src/runtime/lookup-css.ts"],"sourcesContent":["/**\n * Runtime resolver for rnwind-transformed files.\n *\n * Hot path is ONE WeakMap.get + cached-array return for stable atoms\n * (no `active:`/`focus:`/`*-safe` variance beyond what the cache key\n * captures). First call per (hoist, scheme, stateIndex) walks the\n * atoms once, looks each up as\n *\n * `cache.atoms[scheme]?.[atom] ?? cache.atoms.common?.[atom]`\n *\n * and caches the result. `registerAtoms(scheme, record)` bumps a\n * version counter; the next lookup notices the mismatch and rebuilds.\n *\n * Keyframes are inlined directly into atom values via `animationName`\n * at build time — no separate registry.\n */\n\nimport type { RnwindState } from './components/rnwind-provider'\n\n/** Empty sentinel returned when the input is null / undefined / empty. */\nconst EMPTY_STYLES: readonly unknown[] = []\n\n/** Registry key for the always-loaded fallback scheme. */\nconst COMMON_SCHEME = 'common'\n\n/** Atom name prefix marking a press-state-gated atom. */\nconst ACTIVE_PREFIX = 'active:'\n\n/** Atom name prefix marking a focus-state-gated atom. */\nconst FOCUS_PREFIX = 'focus:'\n\n/** Partial record — missing keys resolve to undefined, which the fallback handles. */\ntype SchemeAtomsRecord = Partial<Record<string, unknown>>\n\n/** 0 = idle, 1 = active, 2 = focus, 3 = both. */\ntype StateIndex = 0 | 1 | 2 | 3\n\n/**\n * One entry in the sorted-by-threshold breakpoints array. The runtime\n * derives an atom's threshold by matching its `<prefix>:` against\n * `name`; the array form is preferred over a Map so the hot-path\n * `tierFor(width)` walk is a tight numeric loop.\n */\ninterface BreakpointEntry {\n readonly name: string\n readonly minWidth: number\n}\n\n/**\n * Process-global style cache. Replaced key-by-key by {@link registerAtoms}.\n * Plain record-of-records: `scheme → atom → style`. Active scheme\n * lookup is `cache.atoms[scheme]?.[atom]` — two property reads with\n * an `?? cache.atoms.common[atom]` fallback. No loops over the\n * registry, ever.\n *\n * `breakpoints` mirrors the build-time table the manifest module\n * registers via {@link registerBreakpoints} — `name → px-threshold` for\n * fast prefix-based atom filtering plus the sorted-by-threshold list\n * for cheap tier-index computation in `lookupCss`.\n */\nconst cache = {\n atoms: Object.create(null) as Partial<Record<string, SchemeAtomsRecord>>,\n breakpoints: Object.create(null) as Partial<Record<string, number>>,\n breakpointList: [] as readonly BreakpointEntry[],\n}\n\n/**\n * Bumps on every {@link registerAtoms} call. {@link HoistCache} entries\n * stamp themselves with the current version; a mismatch on read\n * triggers a rebuild so HMR-reloaded atoms propagate without manual\n * invalidation.\n */\nlet atomVersion = 0\n\n/** Optional window-height provider for the `screen-minus-y` marker. */\ntype WindowHeightProvider = () => number\nlet windowHeightProvider: WindowHeightProvider | null = null\n\n/**\n * Optional scheme loader. Registered by the generated manifest module\n * (`rnwind/__generated/schemes`) once at import time. SchemeProvider\n * calls it synchronously on every render with the active scheme name;\n * first call per scheme pulls the scheme's style module in via an\n * inline `require()` — subsequent calls are a no-op through Metro's\n * module cache.\n */\ntype SchemeLoader = (scheme: string) => void\nlet schemeLoader: SchemeLoader | null = null\n\n/** Module-scope flag so the missing-insets warning fires at most once. */\nlet WARNED_MISSING_INSETS = false\n\n/** Atoms we've already dev-warned about — keeps the noise to ONE line per typo per session. */\nconst WARNED_UNKNOWN_ATOMS = new Set<string>()\n\n/**\n * Compute the state-array index from the live interactState. Bit-or\n * encoding: 0 = idle, 1 = active, 2 = focus, 3 = both.\n * @param interactState Snapshot from `useInteract()` (or undefined).\n * @returns 0 / 1 / 2 / 3.\n */\nfunction stateIndexFor(interactState: InteractState | undefined): StateIndex {\n if (!interactState) return 0\n return (((interactState.active ? 1 : 0) | (interactState.focus ? 2 : 0)) as StateIndex)\n}\n\n/**\n * Fetch the px inset for one side. Falls back to 0 when insets is undefined.\n * @param side Compact side tag (`t` / `r` / `b` / `l`).\n * @param insets Active insets.\n * @returns Px value for that side.\n */\nfunction insetOf(side: string, insets: LookupInsets | undefined): number {\n if (!insets) return 0\n if (side === 't') return insets.top\n if (side === 'r') return insets.right\n if (side === 'b') return insets.bottom\n if (side === 'l') return insets.left\n return 0\n}\n\n/**\n * Collapse one safe-area marker into a concrete px number using the\n * active insets.\n * @param spec Marker spec tuple `[cssKey, sideTag, or, offset]`.\n * @param insets Active insets (or undefined → 0).\n * @returns Resolved px number.\n */\nfunction resolveMarker(spec: SafeMarkerSpec, insets: LookupInsets | undefined): number {\n const [, side, or_, offset] = spec\n if (side === 'screen-minus-y') {\n const h = windowHeightProvider ? windowHeightProvider() : 0\n return Math.max(0, h - insetOf('t', insets) - insetOf('b', insets))\n }\n let base = insetOf(side, insets)\n if (or_ !== undefined) base = Math.max(base, or_)\n if (offset !== undefined) base += offset\n return base\n}\n\n/**\n * Emit a one-shot dev warning when a safe-area atom resolves without\n * real insets in scope.\n * @param insets Insets received by the resolver.\n */\nfunction warnMissingInsetsOnce(insets: LookupInsets | undefined): void {\n if (WARNED_MISSING_INSETS) return\n const isDevelopment = typeof __DEV__ === 'undefined' || __DEV__\n if (!isDevelopment) return\n if (insets && (insets.top !== 0 || insets.right !== 0 || insets.bottom !== 0 || insets.left !== 0)) return\n WARNED_MISSING_INSETS = true\n // eslint-disable-next-line no-console\n console.warn(\n 'rnwind: a `*-safe` utility resolved with zero insets. Wire `insets` on <SchemeProvider> ' +\n '(e.g. `insets={useSafeAreaInsets()}` from react-native-safe-area-context).',\n )\n}\n\n/**\n * Resolve precomputed safe-area marker specs into a fresh RN style\n * object. Cannot be cached — insets vary per render with rotation /\n * keyboard.\n * @param specs Array of spec tuples.\n * @param insets Live safe-area insets.\n * @returns Fresh RN style object with concrete numbers.\n */\nfunction resolveSafe(specs: readonly SafeMarkerSpec[], insets: LookupInsets | undefined): Record<string, number> {\n warnMissingInsetsOnce(insets)\n const out: Record<string, number> = {}\n for (const spec of specs) out[spec[0]] = resolveMarker(spec, insets)\n return out\n}\n\n/**\n * Multiply `fontSize` / `lineHeight` in a resolved atom value by the\n * active font scale. Early-returns the original reference for any atom\n * that doesn't carry either property (most of them) — zero allocation\n * on the hot path for non-text atoms.\n * @param value Atom value as registered in the global table.\n * @param fontScale Multiplier from `useWindowDimensions().fontScale`.\n * @returns Scaled style object, or the original when no scaling applied.\n */\nfunction applyFontScale(value: unknown, fontScale: number): unknown {\n if (fontScale === 1) return value\n if (typeof value !== 'object' || value === null) return value\n const record = value as Record<string, unknown>\n const fs = record.fontSize\n const lh = record.lineHeight\n if (typeof fs !== 'number' && typeof lh !== 'number') return value\n const scaled: Record<string, unknown> = { ...record }\n if (typeof fs === 'number') scaled.fontSize = fs * fontScale\n if (typeof lh === 'number') scaled.lineHeight = lh * fontScale\n return scaled\n}\n\n/**\n * Read the precomputed safe-area marker spec list off an atom value.\n * Build-side `envelopeSafeMarkers` wraps safe atoms in\n * `{__safeStyle: [...]}`; this is a single property access.\n * @param value Atom value as registered in the global table.\n * @returns Spec array when the atom is safe-area, else null.\n */\nfunction readSafeSpecs(value: unknown): readonly SafeMarkerSpec[] | null {\n if (typeof value !== 'object' || value === null) return null\n const safe = (value as { __safeStyle?: readonly SafeMarkerSpec[] }).__safeStyle\n return safe ?? null\n}\n\n/**\n * Per-atom lookup. Two property reads: scheme's own table then the\n * common fallback. Returns `undefined` for unknown atoms — the caller\n * skips them.\n * @param scheme Active scheme.\n * @param atom Atom name.\n * @returns Resolved value, or undefined.\n */\nfunction lookupAtom(scheme: string, atom: string): unknown {\n const schemeTable = cache.atoms[scheme]\n if (schemeTable !== undefined) {\n const own = schemeTable[atom]\n if (own !== undefined) return own\n }\n const common = cache.atoms[COMMON_SCHEME]\n return common === undefined ? undefined : common[atom]\n}\n\n/**\n * Whether an atom should participate in a given interact-state index.\n * - idle (0): no `active:` / `focus:` atoms.\n * - active (1): base + `active:`.\n * - focus (2): base + `focus:`.\n * - both (3): base + `active:` + `focus:`.\n * @param atom Atom name.\n * @param stateIndex Encoded state (0/1/2/3).\n * @returns True when the atom should be emitted for this state.\n */\nfunction atomMatchesState(atom: string, stateIndex: StateIndex): boolean {\n // Cheap prefix check — check the first code point before the full\n // `startsWith` so we skip it for any atom whose first letter isn't\n // `a` / `f`.\n const code = atom.codePointAt(0)\n if (code === 97 /* a */ && atom.startsWith(ACTIVE_PREFIX)) return (stateIndex & 1) !== 0\n if (code === 102 /* f */ && atom.startsWith(FOCUS_PREFIX)) return (stateIndex & 2) !== 0\n return true\n}\n\n/**\n * Whether an atom passes the responsive-breakpoint gate for the\n * current `windowWidth`. Atoms without a registered `<prefix>:` are\n * always-on (the common case — `bg-red-500`, `active:bg-blue-700`).\n * Atoms whose first prefix matches a registered breakpoint name pass\n * only when `windowWidth >= threshold`.\n * @param atom Atom name.\n * @param windowWidth Live `useWindowDimensions().width` snapshot.\n * @returns True when the atom should be emitted for this width.\n */\nfunction atomMatchesBreakpoint(atom: string, windowWidth: number): boolean {\n const colon = atom.indexOf(':')\n if (colon === -1) return true\n const prefix = atom.slice(0, colon)\n const threshold = cache.breakpoints[prefix]\n if (threshold === undefined) return true\n return windowWidth >= threshold\n}\n\n/**\n * Tier index — count of registered breakpoints whose threshold is\n * `<= windowWidth`. Bounded by the breakpoint count, so it's a stable\n * cache-key dimension instead of the unbounded raw width. Crossings\n * happen ~5 times across the device-width spectrum, not per-pixel.\n * @param windowWidth Live width.\n * @returns Tier 0..N where N = `cache.breakpointList.length`.\n */\nfunction tierFor(windowWidth: number): number {\n let tier = 0\n for (const entry of cache.breakpointList) {\n if (windowWidth >= entry.minWidth) tier += 1\n else break\n }\n return tier\n}\n\n/**\n * Public breakpoint-tier for a width — the count of registered breakpoints\n * whose threshold is reached. Used by the runtime resolver as its width\n * cache dimension: the numeric tier is bounded AND exact, unlike the\n * clamped `activeBreakpoint` NAME (which collapses tier-0 into the smallest\n * breakpoint, so widths straddling that threshold would share a cache key\n * and serve a stale style).\n * @param windowWidth Live window width in px.\n * @returns Tier 0..N.\n */\nexport function breakpointTier(windowWidth: number): number {\n return tierFor(windowWidth)\n}\n\n/**\n * Build the style array for a (hoist, scheme, state, width) tuple.\n * Walks the atom list, applies the interact-state and breakpoint\n * filters, resolves each atom via scheme→common fallback, and\n * envelopes safe values via {@link resolveSafe}.\n * @param atoms Atom name list (build-time constant).\n * @param scheme Active scheme.\n * @param stateIndex Encoded active/focus state.\n * @param insets Live safe-area insets.\n * @param fontScale Font scale multiplier.\n * @param windowWidth Live window width — gates `md:*` / `lg:*` atoms.\n * @returns Fresh style array.\n */\nfunction buildStyleArray(\n atoms: readonly string[],\n scheme: string,\n stateIndex: StateIndex,\n insets: LookupInsets | undefined,\n fontScale: number,\n windowWidth: number,\n): readonly unknown[] {\n const out: unknown[] = []\n for (const atom of atoms) {\n if (!atomMatchesState(atom, stateIndex)) continue\n if (!atomMatchesBreakpoint(atom, windowWidth)) continue\n const value = lookupAtom(scheme, atom)\n if (value === undefined) {\n warnUnknownAtomOnce(atom)\n continue\n }\n const safe = readSafeSpecs(value)\n const resolved = safe === null ? value : resolveSafe(safe, insets)\n out.push(applyFontScale(resolved, fontScale))\n }\n return out\n}\n\n/**\n * Emit a one-shot dev warning when an atom name doesn't resolve in the\n * registry. The two real causes are a typo (`bg-red-501`) or a class\n * the build-time scanner never saw because it lives in a string the\n * oxide tokeniser can't see (e.g. computed at runtime). Either way, a\n * silent empty style is the worst possible UX — surface it.\n *\n * Filters cosmetic non-issues: empty strings, build-time `__safeStyle`\n * envelopes that wandered in, etc.\n * @param atom Class name that didn't resolve.\n */\nfunction warnUnknownAtomOnce(atom: string): void {\n if (atom.length === 0) return\n const isDevelopment = typeof __DEV__ === 'undefined' || __DEV__\n if (!isDevelopment) return\n if (WARNED_UNKNOWN_ATOMS.has(atom)) return\n WARNED_UNKNOWN_ATOMS.add(atom)\n // eslint-disable-next-line no-console\n console.warn(\n `rnwind: unknown class \"${atom}\" — typo, or the class is built dynamically and the build-time ` +\n `scanner never saw it. Static literals + ternaries are scanned automatically; runtime-built ` +\n `strings need to appear somewhere as a literal so oxide can pick them up.`,\n )\n}\n\n/**\n * Per-hoist cache entry. `version` stamps `atomVersion` at build time\n * so HMR reloads (which bump the counter) invalidate cleanly on next\n * read. `hasSafe` prevents caching results whose values depend on\n * per-render insets. `byKey` maps `\"${scheme}|${stateIndex}\"` to the\n * cached result.\n */\ninterface HoistCache {\n version: number\n hasSafe: boolean\n byKey: Partial<Record<string, readonly unknown[]>>\n}\n\n/**\n * Per-atom-list cache keyed on the hoist reference. WeakMap so\n * hoists GC with their host module on HMR.\n */\nconst resultCache = new WeakMap<readonly string[], HoistCache>()\n\n/**\n * Walk the atom list once to detect safe-area atoms — results that\n * vary per render with `insets`. When any atom envelopes safe specs\n * we skip the cache and rebuild every call.\n * @param atoms Hoist atom list.\n * @param scheme Active scheme.\n * @returns Whether the hoist resolves a safe atom under this scheme.\n */\nfunction detectHasSafe(atoms: readonly string[], scheme: string): boolean {\n for (const atom of atoms) {\n const value = lookupAtom(scheme, atom)\n if (readSafeSpecs(value) !== null) return true\n }\n return false\n}\n\n/**\n * Cache-keyed resolution for the common static-schema case. Returns a\n * stable array reference across renders until `atomVersion` bumps.\n * For hoists containing safe atoms — which depend on per-render\n * insets — rebuilds every call.\n *\n * The `tier` dimension keeps the cache bounded under responsive\n * variants: instead of keying on raw `windowWidth` (which would explode\n * the cache to one entry per pixel), we key on the count of registered\n * breakpoints whose threshold is reached. That gives at most\n * `breakpointCount + 1` cache rows per (scheme, state, fontScale).\n * @param atoms Hoist atom list.\n * @param scheme Active scheme.\n * @param stateIndex Encoded interact state.\n * @param insets Live safe-area insets.\n * @param fontScale Font scale multiplier.\n * @param windowWidth Live window width.\n * @returns Style array.\n */\nfunction lookupCached(\n atoms: readonly string[],\n scheme: string,\n stateIndex: StateIndex,\n insets: LookupInsets | undefined,\n fontScale: number,\n windowWidth: number,\n): readonly unknown[] {\n let entry = resultCache.get(atoms)\n if (entry?.version !== atomVersion) {\n entry = { version: atomVersion, hasSafe: detectHasSafe(atoms, scheme), byKey: Object.create(null) }\n resultCache.set(atoms, entry)\n }\n if (entry.hasSafe) return buildStyleArray(atoms, scheme, stateIndex, insets, fontScale, windowWidth)\n const tier = tierFor(windowWidth)\n const key = `${scheme}|${stateIndex}|${fontScale}|${tier}`\n const cached = entry.byKey[key]\n if (cached !== undefined) return cached\n const fresh = buildStyleArray(atoms, scheme, stateIndex, insets, fontScale, windowWidth)\n entry.byKey[key] = fresh\n return fresh\n}\n\n/**\n * Per-render snapshot of which interactive states (active, focus) are\n * currently engaged. Forwarded from the `useInteract()` hook the\n * transformer injects.\n */\nexport interface InteractState {\n active?: boolean\n focus?: boolean\n}\n\n/**\n * Safe-area insets bundle the transformer passes to `lookupCss` when a\n * file uses any `*-safe` utility.\n */\nexport interface LookupInsets {\n top: number\n right: number\n bottom: number\n left: number\n}\n\n\n/**\n * Precomputed safe-area marker spec emitted by the build-side\n * `envelopeSafeMarkers`. Tuple form: `[cssKey, sideTag, or, offset]`.\n */\nexport type SafeMarkerSpec = readonly [string, string, number | undefined, number | undefined]\n\n/** Type alias: the atom-list build output the transformer emits. */\nexport type HoistedClassName = readonly string[]\n\n/**\n * Register a window-height provider used by the `screen-minus-y`\n * safe-area variant. When not wired, `h-screen-safe` resolves to `0`.\n * @param provider Callback returning the current window height in px.\n */\nexport function setWindowHeightProvider(provider: WindowHeightProvider | null): void {\n windowHeightProvider = provider\n}\n\n/**\n * Register the scheme-loader function exported by the generated\n * manifest module. Called once at manifest-module evaluation time —\n * subsequent registrations override the previous loader (useful for\n * tests).\n * @param loader Manifest's `ensureSchemeLoaded` function, or null to\n * detach (tests).\n */\nexport function registerSchemeLoader(loader: SchemeLoader | null): void {\n schemeLoader = loader\n}\n\n/**\n * Ensure the given scheme's style module is loaded. Safe to call in\n * render — zero-cost after the first call per scheme thanks to\n * Metro's module cache, and a no-op when no loader is registered\n * (tests, or a bundle without rnwind-transformed sources).\n * @param scheme Active scheme name.\n */\nexport function loadScheme(scheme: string): void {\n if (schemeLoader) schemeLoader(scheme)\n}\n\n/**\n * Register (or re-register) one scheme's atoms in the global registry.\n * Pure property assignment — no iteration, no allocation. The version\n * counter bump invalidates every hoist-level result cache lazily on\n * next read.\n * @param scheme Registry key — `'common'` for the always-loaded\n * fallback, or a variant name (`'dark'`, `'light'`, `'brand'`, ...).\n * @param atoms Plain record keyed by atom name.\n */\nexport function registerAtoms(scheme: string, atoms: Record<string, unknown>): void {\n cache.atoms[scheme] = atoms\n atomVersion += 1\n}\n\n/**\n * Current registry version — bumps on every `registerAtoms` /\n * `registerBreakpoints`. The molecule resolver folds it into its cache\n * key so an HMR atom reload invalidates derived results.\n * @returns Monotonic version counter.\n */\nexport function getStyleVersion(): number {\n return atomVersion\n}\n\n/**\n * Register the responsive-breakpoint table the manifest module emits at\n * load time. Replaces the prior table — calling with `{}` clears it.\n * Bumps `atomVersion` so any cached lookup invalidates on next read,\n * which matters during a theme HMR cycle that adds/removes breakpoints.\n * @param breakpoints Breakpoint name → minimum-width threshold (px).\n */\nexport function registerBreakpoints(breakpoints: Record<string, number>): void {\n const fresh: Partial<Record<string, number>> = Object.create(null)\n const list: BreakpointEntry[] = []\n for (const name of Object.keys(breakpoints)) {\n const minWidth = breakpoints[name]\n if (!Number.isFinite(minWidth) || minWidth <= 0) continue\n fresh[name] = minWidth\n list.push({ name, minWidth })\n }\n list.sort((a, b) => a.minWidth - b.minWidth || a.name.localeCompare(b.name))\n cache.breakpoints = fresh\n cache.breakpointList = list\n atomVersion += 1\n}\n\n/**\n * Snapshot of the registered breakpoints, for callers that want to\n * compute their own derivations (e.g. the provider deriving the active\n * breakpoint name). Returns a fresh array — callers can iterate without\n * worrying about concurrent mutation from a manifest reload.\n * @returns Breakpoints sorted by ascending min-width threshold.\n */\nexport function getBreakpoints(): readonly BreakpointEntry[] {\n return cache.breakpointList\n}\n\n/**\n * Sentinel name returned by {@link activeBreakpointFor} ONLY when no\n * breakpoints are registered at all (bundle without rnwind-transformed\n * sources, fresh test setup). When at least one breakpoint is\n * registered, the function falls back to the smallest registered name\n * instead — so phone-width devices (402 dp on a stock iPhone, well\n * below `sm = 640`) report `activeBreakpoint === 'sm'` rather than the\n * abstract `'base'`. This matches the user expectation that the value\n * is always a real Tailwind breakpoint label they can branch on.\n *\n * Note: this is decoupled from the className filter. `sm:*` atoms\n * still only fire at `windowWidth >= 640` per Tailwind's mobile-first\n * spec — `activeBreakpoint === 'sm'` at 402 means \"I'm in the smallest\n * tier\", not \"`sm:` classes are firing\".\n */\nexport const BASE_BREAKPOINT = 'base'\n\n/**\n * Resolve the currently-active breakpoint name for a width:\n * - `windowWidth >= some threshold` → the highest matching breakpoint name.\n * - below every registered threshold → the smallest registered name.\n * - no breakpoints registered → {@link BASE_BREAKPOINT}.\n * Always returns a string so consumers can branch on it without\n * null-handling.\n * @param windowWidth Live window width in px.\n * @returns Active breakpoint name (never null).\n */\nexport function activeBreakpointFor(windowWidth: number): string {\n const list = cache.breakpointList\n if (list.length === 0) return BASE_BREAKPOINT\n let active: string = list[0]!.name\n for (const entry of list) {\n if (windowWidth >= entry.minWidth) active = entry.name\n else break\n }\n return active\n}\n\n/**\n * Resolve a className input against the active rnwind context. Hot\n * path:\n * - Array input (build hoist): ONE WeakMap.get + ONE record-access\n * + cached array return. No per-render allocation when there's no\n * userStyle and the hoist has no safe atoms.\n * - String input (dynamic `className={expr}`): tokenise + walk.\n * @param input Hoisted atom list or raw className string.\n * @param ctx Rnwind context — `{scheme, fontScale, insets}` (extra\n * fields ignored). Pass the result of `useRnwind()` directly.\n * @param userStyle Optional caller-supplied style appended last.\n * @param interactState Live active/focus flags from `useInteract()`.\n * @returns Style array for React Native's `style` prop.\n */\nexport function lookupCss(\n input: HoistedClassName | string | null | undefined,\n ctx: RnwindState,\n userStyle?: unknown,\n interactState?: InteractState,\n): readonly unknown[] {\n if (input === null || input === undefined) {\n return userStyle === undefined || userStyle === null ? EMPTY_STYLES : [userStyle]\n }\n const { scheme, insets, fontScale, windowWidth } = ctx\n if (typeof input === 'string') {\n const trimmed = input.trim()\n if (trimmed.length === 0) {\n return userStyle === undefined || userStyle === null ? EMPTY_STYLES : [userStyle]\n }\n const atoms = trimmed.split(/\\s+/)\n const out = buildStyleArray(atoms, scheme, stateIndexFor(interactState), insets, fontScale, windowWidth)\n if (userStyle === undefined || userStyle === null) return out\n return [...out, userStyle]\n }\n const base = lookupCached(input, scheme, stateIndexFor(interactState), insets, fontScale, windowWidth)\n if (userStyle === undefined || userStyle === null) return base\n return [...base, userStyle]\n}\n\n/** Test-only — clear the global registry between suites. */\nexport function __resetLookupCssState(): void {\n for (const key of Object.keys(cache.atoms)) delete cache.atoms[key]\n for (const key of Object.keys(cache.breakpoints)) delete cache.breakpoints[key]\n cache.breakpointList = []\n windowHeightProvider = null\n schemeLoader = null\n WARNED_MISSING_INSETS = false\n WARNED_UNKNOWN_ATOMS.clear()\n atomVersion += 1\n}\n\n/**\n * Test-only sugar: accept a single-scheme record and register it as the\n * `common` table.\n * @param record Atom name → value record (registered under `common`).\n */\nexport function __registerAtomsFromRecord(record: Record<string, unknown>): void {\n registerAtoms(COMMON_SCHEME, record)\n}\n"],"names":[],"mappings":"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"}