rnwind 0.0.4 → 0.0.5

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 (127) hide show
  1. package/lib/cjs/core/normalize-classname.cjs +25 -0
  2. package/lib/cjs/core/normalize-classname.cjs.map +1 -0
  3. package/lib/cjs/core/normalize-classname.d.ts +10 -0
  4. package/lib/cjs/core/style-builder/build-style.cjs +258 -58
  5. package/lib/cjs/core/style-builder/build-style.cjs.map +1 -1
  6. package/lib/cjs/core/style-builder/build-style.d.ts +6 -1
  7. package/lib/cjs/core/style-builder/union-builder.cjs +37 -3
  8. package/lib/cjs/core/style-builder/union-builder.cjs.map +1 -1
  9. package/lib/cjs/core/style-builder/union-builder.d.ts +21 -1
  10. package/lib/cjs/metro/dts.cjs +7 -16
  11. package/lib/cjs/metro/dts.cjs.map +1 -1
  12. package/lib/cjs/metro/dts.d.ts +2 -4
  13. package/lib/cjs/metro/state.cjs +30 -78
  14. package/lib/cjs/metro/state.cjs.map +1 -1
  15. package/lib/cjs/metro/state.d.ts +8 -25
  16. package/lib/cjs/metro/transformer.cjs +193 -34
  17. package/lib/cjs/metro/transformer.cjs.map +1 -1
  18. package/lib/cjs/metro/with-config.cjs +2 -2
  19. package/lib/cjs/metro/with-config.cjs.map +1 -1
  20. package/lib/cjs/metro/with-config.d.ts +11 -26
  21. package/lib/cjs/metro/wrap-imports.cjs +273 -0
  22. package/lib/cjs/metro/wrap-imports.cjs.map +1 -0
  23. package/lib/cjs/metro/wrap-imports.d.ts +26 -0
  24. package/lib/cjs/runtime/components/rnwind-provider.cjs +0 -17
  25. package/lib/cjs/runtime/components/rnwind-provider.cjs.map +1 -1
  26. package/lib/cjs/runtime/components/rnwind-provider.d.ts +0 -14
  27. package/lib/cjs/runtime/hooks/use-css.cjs +16 -10
  28. package/lib/cjs/runtime/hooks/use-css.cjs.map +1 -1
  29. package/lib/cjs/runtime/hooks/use-css.d.ts +15 -9
  30. package/lib/cjs/runtime/index.cjs +11 -13
  31. package/lib/cjs/runtime/index.cjs.map +1 -1
  32. package/lib/cjs/runtime/index.d.ts +4 -9
  33. package/lib/cjs/runtime/lookup-css.cjs +10 -0
  34. package/lib/cjs/runtime/lookup-css.cjs.map +1 -1
  35. package/lib/cjs/runtime/lookup-css.d.ts +7 -0
  36. package/lib/cjs/runtime/resolve.cjs +348 -0
  37. package/lib/cjs/runtime/resolve.cjs.map +1 -0
  38. package/lib/cjs/runtime/resolve.d.ts +61 -0
  39. package/lib/cjs/runtime/wrap.cjs +254 -0
  40. package/lib/cjs/runtime/wrap.cjs.map +1 -0
  41. package/lib/cjs/runtime/wrap.d.ts +37 -0
  42. package/lib/cjs/testing/index.cjs +81 -50
  43. package/lib/cjs/testing/index.cjs.map +1 -1
  44. package/lib/esm/core/normalize-classname.d.ts +10 -0
  45. package/lib/esm/core/normalize-classname.mjs +23 -0
  46. package/lib/esm/core/normalize-classname.mjs.map +1 -0
  47. package/lib/esm/core/style-builder/build-style.d.ts +6 -1
  48. package/lib/esm/core/style-builder/build-style.mjs +258 -58
  49. package/lib/esm/core/style-builder/build-style.mjs.map +1 -1
  50. package/lib/esm/core/style-builder/union-builder.d.ts +21 -1
  51. package/lib/esm/core/style-builder/union-builder.mjs +37 -3
  52. package/lib/esm/core/style-builder/union-builder.mjs.map +1 -1
  53. package/lib/esm/metro/dts.d.ts +2 -4
  54. package/lib/esm/metro/dts.mjs +7 -16
  55. package/lib/esm/metro/dts.mjs.map +1 -1
  56. package/lib/esm/metro/state.d.ts +8 -25
  57. package/lib/esm/metro/state.mjs +30 -76
  58. package/lib/esm/metro/state.mjs.map +1 -1
  59. package/lib/esm/metro/transformer.mjs +194 -35
  60. package/lib/esm/metro/transformer.mjs.map +1 -1
  61. package/lib/esm/metro/with-config.d.ts +11 -26
  62. package/lib/esm/metro/with-config.mjs +2 -2
  63. package/lib/esm/metro/with-config.mjs.map +1 -1
  64. package/lib/esm/metro/wrap-imports.d.ts +26 -0
  65. package/lib/esm/metro/wrap-imports.mjs +250 -0
  66. package/lib/esm/metro/wrap-imports.mjs.map +1 -0
  67. package/lib/esm/runtime/components/rnwind-provider.d.ts +0 -14
  68. package/lib/esm/runtime/components/rnwind-provider.mjs +1 -17
  69. package/lib/esm/runtime/components/rnwind-provider.mjs.map +1 -1
  70. package/lib/esm/runtime/hooks/use-css.d.ts +15 -9
  71. package/lib/esm/runtime/hooks/use-css.mjs +16 -10
  72. package/lib/esm/runtime/hooks/use-css.mjs.map +1 -1
  73. package/lib/esm/runtime/index.d.ts +4 -9
  74. package/lib/esm/runtime/index.mjs +4 -4
  75. package/lib/esm/runtime/index.mjs.map +1 -1
  76. package/lib/esm/runtime/lookup-css.d.ts +7 -0
  77. package/lib/esm/runtime/lookup-css.mjs +10 -1
  78. package/lib/esm/runtime/lookup-css.mjs.map +1 -1
  79. package/lib/esm/runtime/resolve.d.ts +61 -0
  80. package/lib/esm/runtime/resolve.mjs +341 -0
  81. package/lib/esm/runtime/resolve.mjs.map +1 -0
  82. package/lib/esm/runtime/wrap.d.ts +37 -0
  83. package/lib/esm/runtime/wrap.mjs +251 -0
  84. package/lib/esm/runtime/wrap.mjs.map +1 -0
  85. package/lib/esm/testing/index.mjs +84 -53
  86. package/lib/esm/testing/index.mjs.map +1 -1
  87. package/package.json +2 -1
  88. package/src/core/normalize-classname.ts +19 -0
  89. package/src/core/style-builder/build-style.ts +286 -55
  90. package/src/core/style-builder/union-builder.ts +36 -3
  91. package/src/metro/dts.ts +7 -19
  92. package/src/metro/state.ts +29 -74
  93. package/src/metro/transformer.ts +190 -34
  94. package/src/metro/with-config.ts +13 -28
  95. package/src/metro/wrap-imports.ts +260 -0
  96. package/src/runtime/components/rnwind-provider.tsx +0 -17
  97. package/src/runtime/hooks/use-css.ts +17 -11
  98. package/src/runtime/index.ts +3 -26
  99. package/src/runtime/lookup-css.ts +10 -0
  100. package/src/runtime/resolve.ts +381 -0
  101. package/src/runtime/wrap.tsx +267 -0
  102. package/src/testing/index.ts +106 -56
  103. package/lib/cjs/core/parser/text-truncate.cjs +0 -78
  104. package/lib/cjs/core/parser/text-truncate.cjs.map +0 -1
  105. package/lib/cjs/metro/transform-ast.cjs +0 -1472
  106. package/lib/cjs/metro/transform-ast.cjs.map +0 -1
  107. package/lib/cjs/metro/transform-ast.d.ts +0 -88
  108. package/lib/cjs/runtime/haptics.cjs +0 -113
  109. package/lib/cjs/runtime/haptics.cjs.map +0 -1
  110. package/lib/cjs/runtime/haptics.d.ts +0 -48
  111. package/lib/cjs/runtime/interactive-box.cjs +0 -35
  112. package/lib/cjs/runtime/interactive-box.cjs.map +0 -1
  113. package/lib/cjs/runtime/interactive-box.d.ts +0 -40
  114. package/lib/esm/core/parser/text-truncate.mjs +0 -75
  115. package/lib/esm/core/parser/text-truncate.mjs.map +0 -1
  116. package/lib/esm/metro/transform-ast.d.ts +0 -88
  117. package/lib/esm/metro/transform-ast.mjs +0 -1451
  118. package/lib/esm/metro/transform-ast.mjs.map +0 -1
  119. package/lib/esm/runtime/haptics.d.ts +0 -48
  120. package/lib/esm/runtime/haptics.mjs +0 -110
  121. package/lib/esm/runtime/haptics.mjs.map +0 -1
  122. package/lib/esm/runtime/interactive-box.d.ts +0 -40
  123. package/lib/esm/runtime/interactive-box.mjs +0 -33
  124. package/lib/esm/runtime/interactive-box.mjs.map +0 -1
  125. package/src/metro/transform-ast.ts +0 -1729
  126. package/src/runtime/haptics.ts +0 -120
  127. package/src/runtime/interactive-box.tsx +0 -57
@@ -1 +1 @@
1
- {"version":3,"file":"build-style.mjs","sources":["../../../../../src/core/style-builder/build-style.ts"],"sourcesContent":["import type { KeyframeBlock, RNStyle, SchemedStyle } from '../parser'\n\n/** Match atom names like `border-hairline`, `h-hairline`, `border-t-hairline`, etc. */\nconst HAIRLINE_ATOM = /-hairline$/\n\n/** Parser's synthetic \"no variant\" scheme — provides the canonical fallback. */\nconst BASE_SCHEME = 'base'\n\n/** Runtime registry key for the always-loaded fallback scheme. */\nconst COMMON_SCHEME = 'common'\n\n/** Sentinel key the parser sets on interactive (`active:`/`focus:`) atoms. */\nconst STATE_KEY = '__state'\n\n/**\n * Whether an atom is a `*-hairline` utility — its numeric value must be\n * rewritten as `StyleSheet.hairlineWidth` at runtime.\n * @param atomName Class name.\n * @returns True when the atom is a hairline utility.\n */\nfunction isHairlineAtom(atomName: string): boolean {\n return HAIRLINE_ATOM.test(atomName)\n}\n\n/**\n * Whether an RN style object carries any own key. The parser emits\n * empty `{}` for schemes an atom doesn't apply to; we treat those as\n * \"inherit canonical\" and don't emit an entry for that scheme.\n * @param style RN style object.\n * @returns Whether the style has content.\n */\nfunction isNonEmptyStyle(style: RNStyle | undefined): style is RNStyle {\n if (!style) return false\n return Object.keys(style).length > 0\n}\n\n/**\n * Iterate per-scheme entries from a parser-produced schemed bucket,\n * skipping the reserved `__state` metadata key.\n * @param schemed Parser output for one atom.\n * @yields `[scheme, style]` pairs in object-key order.\n */\nfunction* iterScheme(schemed: SchemedStyle): IterableIterator<[string, RNStyle]> {\n const raw = schemed as Readonly<Record<string, RNStyle | string>>\n for (const key in raw) {\n if (key === STATE_KEY) continue\n yield [key, raw[key] as RNStyle]\n }\n}\n\n/**\n * Pick the canonical style for an atom — the value that goes into\n * `common.style.js`. Prefers the parser's `base` entry (the \"default\n * when no variant matches\"); falls back to the first non-empty per-\n * scheme entry when the atom has no explicit base.\n * @param schemed Parser-produced per-scheme bucket.\n * @returns Canonical style, or undefined when every scheme is empty.\n */\nfunction canonicalValue(schemed: SchemedStyle): RNStyle | undefined {\n const baseEntry = (schemed as Readonly<Record<string, RNStyle>>)[BASE_SCHEME]\n if (isNonEmptyStyle(baseEntry)) return baseEntry\n for (const [, style] of iterScheme(schemed)) {\n if (isNonEmptyStyle(style)) return style\n }\n return undefined\n}\n\n/**\n * Collect every variant scheme name across the project's atoms. The\n * synthetic `base` scheme is excluded — it's folded into the `common`\n * output. Returns variants in sorted order for deterministic output.\n * @param resolved Parser-produced atom map.\n * @returns Variant scheme names (no `base`, no `common`).\n */\nfunction collectVariantSchemes(resolved: ReadonlyMap<string, SchemedStyle>): readonly string[] {\n const set = new Set<string>()\n for (const schemed of resolved.values()) {\n for (const [scheme] of iterScheme(schemed)) {\n if (scheme !== BASE_SCHEME) set.add(scheme)\n }\n }\n return [...set].toSorted((a, b) => a.localeCompare(b))\n}\n\n/**\n * Normalize a CSS keyframe selector to the percentage form Reanimated\n * v4 keyframes objects use.\n * @param offset Selector text (`'from'`, `'to'`, `'50%'`).\n * @returns Percentage string.\n */\nfunction offsetToPercent(offset: string): string {\n if (offset === 'from') return '0%'\n if (offset === 'to') return '100%'\n return offset\n}\n\n/**\n * Replace a string `animationName` with the inline keyframes object\n * Reanimated v4's CSS engine expects. Atoms whose `animationName`\n * doesn't match any registered keyframe keep the original string.\n * @param style RN style object (possibly carrying `animationName`).\n * @param keyframes Keyframes available to this build.\n * @returns Style with `animationName` inlined when matched.\n */\nfunction inlineAnimationName(style: RNStyle, keyframes: ReadonlyMap<string, KeyframeBlock>): RNStyle {\n const name = style.animationName\n if (typeof name !== 'string') return style\n const block = keyframes.get(name)\n if (!block) return style\n const out: RNStyle = { ...style }\n const inline: Record<string, Record<string, string | number>> = {}\n for (const step of block.steps) inline[offsetToPercent(step.offset)] = step.style as Record<string, string | number>\n out.animationName = inline as unknown as RNStyle[string]\n return out\n}\n\n/**\n * Convert any safe-area markers in the style into a precomputed spec\n * envelope. Atoms with `__safe` markers become\n * `{__safeStyle: [[cssKey, sideTag, or, offset], ...]}` — the runtime\n * resolver reads `value.__safeStyle` as a single property access and\n * resolves against live insets without walking the value's keys.\n * @param style RN style as resolved by the parser.\n * @returns Original style OR the safe-style envelope.\n */\nfunction envelopeSafeMarkers(\n style: RNStyle,\n): RNStyle | { __safeStyle: readonly (readonly [string, string, number | undefined, number | undefined])[] } {\n let specs: [string, string, number | undefined, number | undefined][] | null = null\n for (const key of Object.keys(style)) {\n const value = style[key]\n if (typeof value !== 'object' || !value) continue\n const marker = value as { __safe?: string; or?: number; offset?: number }\n if (typeof marker.__safe !== 'string') continue\n if (!specs) specs = []\n specs.push([key, marker.__safe, marker.or, marker.offset])\n }\n if (!specs) return style\n return { __safeStyle: specs }\n}\n\n/**\n * Serialise a single atom's RN style to a JS object literal. Honors\n * the `*-hairline` sentinel: numeric values get rewritten to\n * `StyleSheet.hairlineWidth` so device-density differences land in the\n * rendered border.\n * @param atomName The atom's class name (used to detect hairline).\n * @param style The atom's RN style object.\n * @returns JS object-literal source.\n */\nfunction serializeStyle(atomName: string, style: RNStyle): string {\n const json = JSON.stringify(style)\n if (!isHairlineAtom(atomName)) return json\n return json.replaceAll(/:(-?\\d+(?:\\.\\d+)?)/g, ': StyleSheet.hairlineWidth')\n}\n\n/**\n * Serialise an atom's resolved value — bare RN style object or an\n * already-enveloped safe-style value.\n * @param atomName Atom name (controls hairline rewrite).\n * @param value Atom value (bare style or `{__safeStyle: spec[]}`).\n * @returns JS source for the value.\n */\nfunction serializeAtomValue(atomName: string, value: unknown): string {\n if (typeof value === 'object' && value !== null && '__safeStyle' in value) return JSON.stringify(value)\n return serializeStyle(atomName, value as RNStyle)\n}\n\n/**\n * Resolve + envelope + serialize an atom's value under one scheme.\n * @param atomName Atom name.\n * @param style Raw RN style for this scheme.\n * @param keyframes Keyframes available to this build.\n * @returns Serialized text ready to emit.\n */\nfunction prepareAtomValue(atomName: string, style: RNStyle, keyframes: ReadonlyMap<string, KeyframeBlock>): string {\n const enveloped = envelopeSafeMarkers(inlineAnimationName(style, keyframes))\n return serializeAtomValue(atomName, enveloped)\n}\n\n/**\n * Per-file value deduplicator — interns each unique serialized atom\n * value once and emits `const _s<N> = <value>` at module scope. Scheme\n * entries reference the const instead of inlining the literal.\n *\n * Wins: (1) smaller bundle bytes for themes with many atoms sharing a\n * style shape; (2) stable `===` inside one scheme so two atoms\n * resolving to the same value yield the same object reference.\n */\nclass ValueDeduper {\n private readonly byText = new Map<string, string>()\n private readonly decls: string[] = []\n\n intern(serialized: string): string {\n const existing = this.byText.get(serialized)\n if (existing) return existing\n const name = `_s${this.decls.length}`\n this.decls.push(`const ${name} = ${serialized}`)\n this.byText.set(serialized, name)\n return name\n }\n\n get declarations(): readonly string[] {\n return this.decls\n }\n}\n\n/**\n * Render one scheme file's source. `entries` is the list of atoms this\n * scheme contributes — for `common` every atom's canonical value; for\n * a variant only atoms whose value differs from canonical. Hairline\n * atoms in this file trigger the `StyleSheet` import.\n * @param schemeName Registry key (`'common'` or the variant name).\n * @param entries `[atomName, serializedValue]` pairs to emit.\n * @returns JS source text.\n */\nfunction renderSchemeFile(schemeName: string, entries: readonly (readonly [string, string])[]): string {\n const needsStyleSheet = entries.some(([atom]) => isHairlineAtom(atom))\n const deduper = new ValueDeduper()\n const recordLines: string[] = []\n for (const [atom, value] of entries) {\n const ref = deduper.intern(value)\n recordLines.push(` ${JSON.stringify(atom)}: ${ref},`)\n }\n\n const lines: string[] = []\n if (needsStyleSheet) lines.push(`import { StyleSheet } from 'react-native'`)\n lines.push(`import { registerAtoms } from 'rnwind'`, ``)\n if (deduper.declarations.length > 0) {\n for (const decl of deduper.declarations) lines.push(decl)\n lines.push(``)\n }\n lines.push(`registerAtoms(${JSON.stringify(schemeName)}, {`, ...recordLines, `})`, ``)\n return lines.join('\\n')\n}\n\n/**\n * Render the JS-object literal for the responsive-breakpoint table the\n * runtime registers at manifest-load time. Sorted by ascending px\n * threshold so the runtime can build a deterministic \"tier index\" for\n * its style cache.\n * @param breakpoints Breakpoint name → px-threshold map.\n * @returns Object-literal source (`{}` when empty).\n */\nfunction serializeBreakpoints(breakpoints: ReadonlyMap<string, number>): string {\n if (breakpoints.size === 0) return '{}'\n const entries = [...breakpoints].toSorted((a, b) => a[1] - b[1] || a[0].localeCompare(b[0]))\n const inner = entries.map(([name, px]) => `${JSON.stringify(name)}: ${px}`).join(', ')\n return `{ ${inner} }`\n}\n\n/**\n * Render the manifest module. Eager-imports `common.style.js` (every\n * rewritten source file pulls this via a transitive side-effect\n * import), registers the responsive-breakpoint table once, and lazy-\n * requires every variant scheme's file through an inline require —\n * first call in `ensureSchemeLoaded(name)` triggers the scheme\n * module's evaluation; Metro's module cache makes subsequent calls\n * no-ops.\n * @param variants Variant scheme names (no `base`, no `common`).\n * @param breakpoints Responsive breakpoint name → px-threshold map.\n * @returns JS source text.\n */\nfunction renderManifest(variants: readonly string[], breakpoints: ReadonlyMap<string, number>): string {\n const lines: string[] = [\n `import { registerSchemeLoader, registerBreakpoints } from 'rnwind'`,\n `import './common.style'`,\n ``,\n `registerBreakpoints(${serializeBreakpoints(breakpoints)})`,\n ``,\n ]\n if (variants.length === 0) {\n lines.push(`function ensureSchemeLoaded(_name) {}`, ``, `registerSchemeLoader(ensureSchemeLoaded)`, ``, `export { ensureSchemeLoaded }`, ``)\n return lines.join('\\n')\n }\n lines.push(`const LOADERS = {`)\n for (const variant of variants) {\n lines.push(` ${JSON.stringify(variant)}: () => require(${JSON.stringify(`./${variant}.style`)}),`)\n }\n lines.push(`}`, ``, `function ensureSchemeLoaded(name) {`, ` const loader = LOADERS[name]`, ` if (loader) loader()`, `}`, ``, `registerSchemeLoader(ensureSchemeLoaded)`, ``, `export { ensureSchemeLoaded }`, ``)\n return lines.join('\\n')\n}\n\n/** Output of one build pass — one source per scheme plus the manifest. */\nexport interface BuildSchemeSourcesOutput {\n /** `<schemeName>.style.js` source per scheme. Always contains `common`. */\n readonly schemeSources: Readonly<Record<string, string>>\n /** Manifest module source (`schemes.js`). */\n readonly manifestSource: string\n /** Variant scheme names this build covers (sorted; excludes `common`). */\n readonly variants: readonly string[]\n /** Number of `prepareAtomValue` / JSON.stringify passes (cache MISSES) this call did — test telemetry. */\n readonly serializedMisses: number\n}\n\n/**\n * Per-atom cached serialized value. Canonical (common) string plus a\n * map of variant → own-serialized-string. `styleRef` is an identity\n * guard against the resolved SchemedStyle — when callers replace an\n * atom's value the ref diverges and the cache rebuilds that entry.\n */\nexport interface AtomSerializedEntry {\n styleRef: SchemedStyle\n canonical: string\n variants: Map<string, string>\n}\n\n/** Cache UnionBuilder owns across repeated writeSchemes calls. */\nexport type AtomSerializedCache = Map<string, AtomSerializedEntry>\n\n/**\n * Pre-serialize every non-empty variant value, reusing the per-atom\n * cache where present. Result drives both the scheme-uniform check\n * AND the per-variant emission loop downstream.\n * @param atom Atom name.\n * @param schemed Parser-produced schemed bucket.\n * @param variants Variant scheme names in deterministic order.\n * @param keyframes Keyframes available to inline.\n * @param cached Cached entry for this atom (when ref-stable).\n * @returns variantName → serialized text.\n */\nfunction buildVariantTexts(\n atom: string,\n schemed: SchemedStyle,\n variants: readonly string[],\n keyframes: ReadonlyMap<string, KeyframeBlock>,\n cached: AtomSerializedEntry | undefined,\n): Map<string, string> {\n const out = new Map<string, string>()\n for (const variant of variants) {\n const own = (schemed as Readonly<Record<string, RNStyle>>)[variant]\n if (!isNonEmptyStyle(own)) continue\n const text = cached?.variants.get(variant) ?? prepareAtomValue(atom, own, keyframes)\n out.set(variant, text)\n }\n return out\n}\n\n/**\n * Decide whether a (no-base) atom should be promoted to common because\n * every declared variant resolves to the same value. This is the\n * scheme-uniform case: `flex`, `p-4`, `absolute` all carry no theme\n * variables, so Phase-1 fills every variant bucket identically and\n * leaves `base` empty — without this collapse they'd be duplicated\n * across every scheme file.\n *\n * The variant-prefix check is what keeps a real scheme-gated atom\n * (`dark:bg-indigo-800`) out of common in a single-variant project\n * (where its 1 bucket would otherwise look \"uniform\" by definition).\n * @param atom Atom name (checked for `<variant>:` prefix).\n * @param variants Declared variant scheme names.\n * @param variantTexts Serialized variant values.\n * @param canonicalText Serialized canonical (common) value.\n * @returns Whether the atom is uniform across every declared variant.\n */\nfunction isSchemeUniform(\n atom: string,\n variants: readonly string[],\n variantTexts: ReadonlyMap<string, string>,\n canonicalText: string,\n): boolean {\n if (variants.length === 0 || variantTexts.size !== variants.length) return false\n if (variants.some((variant) => atom.startsWith(`${variant}:`))) return false\n for (const text of variantTexts.values()) {\n if (text !== canonicalText) return false\n }\n return true\n}\n\n/**\n * Serialize one atom's canonical + variant-diff entries, honouring the\n * per-atom cache. Returns the number of cache MISSES this atom incurred\n * (0 when canonical was cached AND every needed variant was cached;\n * 1 when anything had to be re-stringified).\n *\n * Three paths gated on whether the parser produced a non-empty `base`\n * bucket and whether the variants converge:\n * - **Themed atom (base present)**: canonical goes to `common`, each\n * variant whose own value diverges from canonical writes the diff\n * into its own scheme file. `lookupAtom` finds the variant's\n * override or falls through to common.\n * - **Scheme-uniform atom (base empty, every variant identical)**:\n * promoted to `common` once — the parser's Phase-1 fills every\n * variant bucket with the same value for utilities like `flex` /\n * `p-4` / `absolute` that don't reference theme variables.\n * - **Scheme-gated atom (base empty, prefixed name like `dark:foo`,\n * or variants diverge)**: each populated variant writes the value\n * into its own scheme file directly; common stays empty so the\n * runtime fallback can't leak the variant style into other schemes.\n * @param atom Atom name.\n * @param schemed Parser-produced schemed bucket for the atom.\n * @param canonical Canonical RN style for `common`.\n * @param variants Variant scheme names in deterministic order.\n * @param keyframes Keyframes available to inline.\n * @param commonEntries Mutable collector for `common`'s `[atom, text]` pairs.\n * @param variantEntries Mutable collector keyed by variant name.\n * @param cache Optional shared serialized-value cache.\n * @returns Number of JSON.stringify passes triggered for this atom.\n */\nfunction collectAtomEntries(\n atom: string,\n schemed: SchemedStyle,\n canonical: RNStyle,\n variants: readonly string[],\n keyframes: ReadonlyMap<string, KeyframeBlock>,\n commonEntries: (readonly [string, string])[],\n variantEntries: Record<string, (readonly [string, string])[]>,\n cache?: AtomSerializedCache,\n): number {\n const cached = cache?.get(atom)\n const hit = cached?.styleRef === schemed\n const baseEntry = (schemed as Readonly<Record<string, RNStyle>>)[BASE_SCHEME]\n const hasBase = isNonEmptyStyle(baseEntry)\n const canonicalText = hit ? cached.canonical : prepareAtomValue(atom, canonical, keyframes)\n const variantTexts = buildVariantTexts(atom, schemed, variants, keyframes, hit ? cached : undefined)\n const goesToCommon = hasBase || isSchemeUniform(atom, variants, variantTexts, canonicalText)\n\n if (goesToCommon) commonEntries.push([atom, canonicalText])\n\n const entry: AtomSerializedEntry = hit\n ? cached\n : { styleRef: schemed, canonical: canonicalText, variants: new Map(variantTexts) }\n if (!hit) cache?.set(atom, entry)\n\n for (const variant of variants) {\n const ownText = variantTexts.get(variant)\n if (ownText === undefined) continue\n if (goesToCommon && ownText === canonicalText) continue\n variantEntries[variant].push([atom, ownText])\n }\n return hit ? 0 : 1\n}\n\n/** Empty fallback when the caller didn't supply breakpoints (legacy callers, tests). */\nconst EMPTY_BREAKPOINTS: ReadonlyMap<string, number> = new Map()\n\n/**\n * Build the per-scheme style files + manifest source.\n *\n * Dedup rule (the thing that shrinks scheme files to their diff):\n * - Every atom's canonical value goes into `common.style.js`.\n * - Each variant's file emits an entry for an atom ONLY when the\n * variant's own resolved value differs from canonical. When the\n * variant inherits (parser emits an empty `{}` for that scheme) or\n * the variant's resolved value serializes identically to canonical,\n * the atom is omitted — at runtime the lookup falls through via\n * `cache.atoms[scheme]?.[atom] ?? cache.atoms.common[atom]`.\n *\n * Keyframes are inlined directly into atom values via `animationName`\n * ({@link inlineAnimationName}). Safe-area markers get pre-enveloped\n * via {@link envelopeSafeMarkers}. Hairline utilities stay bound to\n * `StyleSheet.hairlineWidth` at runtime.\n * @param atomNames All atom names (sorted).\n * @param resolved Per-atom schemed styles from the parser.\n * @param keyframes Keyframe blocks referenced by any atom.\n * @param cache Optional shared serialized-value cache.\n * @param breakpoints Responsive breakpoint name → px-threshold map. The\n * manifest emits `registerBreakpoints({...})` so the runtime can gate\n * `md:*` / `lg:*` atoms on `windowWidth`. Optional — empty when the\n * theme declares no breakpoints (legacy/test callers).\n * @returns Per-scheme sources, manifest source, variant list.\n */\nexport function buildSchemeSources(\n atomNames: readonly string[],\n resolved: ReadonlyMap<string, SchemedStyle>,\n keyframes: ReadonlyMap<string, KeyframeBlock>,\n cache?: AtomSerializedCache,\n breakpoints: ReadonlyMap<string, number> = EMPTY_BREAKPOINTS,\n): BuildSchemeSourcesOutput {\n const variants = collectVariantSchemes(resolved)\n const commonEntries: (readonly [string, string])[] = []\n const variantEntries: Record<string, (readonly [string, string])[]> = {}\n for (const variant of variants) variantEntries[variant] = []\n let misses = 0\n\n for (const atom of atomNames) {\n const schemed = resolved.get(atom)\n if (!schemed) continue\n const canonical = canonicalValue(schemed)\n if (!canonical) continue\n misses += collectAtomEntries(atom, schemed, canonical, variants, keyframes, commonEntries, variantEntries, cache)\n }\n\n const schemeSources: Record<string, string> = {\n [COMMON_SCHEME]: renderSchemeFile(COMMON_SCHEME, commonEntries),\n }\n for (const variant of variants) {\n schemeSources[variant] = renderSchemeFile(variant, variantEntries[variant])\n }\n\n return {\n schemeSources,\n manifestSource: renderManifest(variants, breakpoints),\n variants,\n serializedMisses: misses,\n }\n}\n\n/** Registry key the runtime uses for the always-loaded fallback. */\nexport const COMMON_SCHEME_NAME: string = COMMON_SCHEME\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build-style.mjs","sources":["../../../../../src/core/style-builder/build-style.ts"],"sourcesContent":["import type { KeyframeBlock, RNStyle, SchemedStyle } from '../parser'\nimport { normalizeClassName } from '../normalize-classname'\n\n/** Match atom names like `border-hairline`, `h-hairline`, `border-t-hairline`, etc. */\nconst HAIRLINE_ATOM = /-hairline$/\n\n/** Parser's synthetic \"no variant\" scheme — provides the canonical fallback. */\nconst BASE_SCHEME = 'base'\n\n/** Runtime registry key for the always-loaded fallback scheme. */\nconst COMMON_SCHEME = 'common'\n\n/** Sentinel key the parser sets on interactive (`active:`/`focus:`) atoms. */\nconst STATE_KEY = '__state'\n\n/**\n * Whether an atom is a `*-hairline` utility — its numeric value must be\n * rewritten as `StyleSheet.hairlineWidth` at runtime.\n * @param atomName Class name.\n * @returns True when the atom is a hairline utility.\n */\nfunction isHairlineAtom(atomName: string): boolean {\n return HAIRLINE_ATOM.test(atomName)\n}\n\n/**\n * Whether an RN style object carries any own key. The parser emits\n * empty `{}` for schemes an atom doesn't apply to; we treat those as\n * \"inherit canonical\" and don't emit an entry for that scheme.\n * @param style RN style object.\n * @returns Whether the style has content.\n */\nfunction isNonEmptyStyle(style: RNStyle | undefined): style is RNStyle {\n if (!style) return false\n return Object.keys(style).length > 0\n}\n\n/**\n * Iterate per-scheme entries from a parser-produced schemed bucket,\n * skipping the reserved `__state` metadata key.\n * @param schemed Parser output for one atom.\n * @yields `[scheme, style]` pairs in object-key order.\n */\nfunction* iterScheme(schemed: SchemedStyle): IterableIterator<[string, RNStyle]> {\n const raw = schemed as Readonly<Record<string, RNStyle | string>>\n for (const key in raw) {\n if (key === STATE_KEY) continue\n yield [key, raw[key] as RNStyle]\n }\n}\n\n/**\n * Pick the canonical style for an atom — the value that goes into\n * `common.style.js`. Prefers the parser's `base` entry (the \"default\n * when no variant matches\"); falls back to the first non-empty per-\n * scheme entry when the atom has no explicit base.\n * @param schemed Parser-produced per-scheme bucket.\n * @returns Canonical style, or undefined when every scheme is empty.\n */\nfunction canonicalValue(schemed: SchemedStyle): RNStyle | undefined {\n const baseEntry = (schemed as Readonly<Record<string, RNStyle>>)[BASE_SCHEME]\n if (isNonEmptyStyle(baseEntry)) return baseEntry\n for (const [, style] of iterScheme(schemed)) {\n if (isNonEmptyStyle(style)) return style\n }\n return undefined\n}\n\n/**\n * Collect every variant scheme name across the project's atoms. The\n * synthetic `base` scheme is excluded — it's folded into the `common`\n * output. Returns variants in sorted order for deterministic output.\n * @param resolved Parser-produced atom map.\n * @returns Variant scheme names (no `base`, no `common`).\n */\nfunction collectVariantSchemes(resolved: ReadonlyMap<string, SchemedStyle>): readonly string[] {\n const set = new Set<string>()\n for (const schemed of resolved.values()) {\n for (const [scheme] of iterScheme(schemed)) {\n if (scheme !== BASE_SCHEME) set.add(scheme)\n }\n }\n return [...set].toSorted((a, b) => a.localeCompare(b))\n}\n\n/**\n * Normalize a CSS keyframe selector to the percentage form Reanimated\n * v4 keyframes objects use.\n * @param offset Selector text (`'from'`, `'to'`, `'50%'`).\n * @returns Percentage string.\n */\nfunction offsetToPercent(offset: string): string {\n if (offset === 'from') return '0%'\n if (offset === 'to') return '100%'\n return offset\n}\n\n/**\n * Replace a string `animationName` with the inline keyframes object\n * Reanimated v4's CSS engine expects. Atoms whose `animationName`\n * doesn't match any registered keyframe keep the original string.\n * @param style RN style object (possibly carrying `animationName`).\n * @param keyframes Keyframes available to this build.\n * @returns Style with `animationName` inlined when matched.\n */\nfunction inlineAnimationName(style: RNStyle, keyframes: ReadonlyMap<string, KeyframeBlock>): RNStyle {\n const name = style.animationName\n if (typeof name !== 'string') return style\n const block = keyframes.get(name)\n if (!block) return style\n const out: RNStyle = { ...style }\n const inline: Record<string, Record<string, string | number>> = {}\n for (const step of block.steps) inline[offsetToPercent(step.offset)] = step.style as Record<string, string | number>\n out.animationName = inline as unknown as RNStyle[string]\n return out\n}\n\n/**\n * Convert any safe-area markers in the style into a precomputed spec\n * envelope. Atoms with `__safe` markers become\n * `{__safeStyle: [[cssKey, sideTag, or, offset], ...]}` — the runtime\n * resolver reads `value.__safeStyle` as a single property access and\n * resolves against live insets without walking the value's keys.\n * @param style RN style as resolved by the parser.\n * @returns Original style OR the safe-style envelope.\n */\nfunction envelopeSafeMarkers(\n style: RNStyle,\n): RNStyle | { __safeStyle: readonly (readonly [string, string, number | undefined, number | undefined])[] } {\n let specs: [string, string, number | undefined, number | undefined][] | null = null\n for (const key of Object.keys(style)) {\n const value = style[key]\n if (typeof value !== 'object' || !value) continue\n const marker = value as { __safe?: string; or?: number; offset?: number }\n if (typeof marker.__safe !== 'string') continue\n if (!specs) specs = []\n specs.push([key, marker.__safe, marker.or, marker.offset])\n }\n if (!specs) return style\n return { __safeStyle: specs }\n}\n\n/**\n * Serialise a single atom's RN style to a JS object literal. Honors\n * the `*-hairline` sentinel: numeric values get rewritten to\n * `StyleSheet.hairlineWidth` so device-density differences land in the\n * rendered border.\n * @param atomName The atom's class name (used to detect hairline).\n * @param style The atom's RN style object.\n * @returns JS object-literal source.\n */\nfunction serializeStyle(atomName: string, style: RNStyle): string {\n const json = JSON.stringify(style)\n if (!isHairlineAtom(atomName)) return json\n return json.replaceAll(/:(-?\\d+(?:\\.\\d+)?)/g, ': StyleSheet.hairlineWidth')\n}\n\n/**\n * Serialise an atom's resolved value — bare RN style object or an\n * already-enveloped safe-style value.\n * @param atomName Atom name (controls hairline rewrite).\n * @param value Atom value (bare style or `{__safeStyle: spec[]}`).\n * @returns JS source for the value.\n */\nfunction serializeAtomValue(atomName: string, value: unknown): string {\n if (typeof value === 'object' && value !== null && '__safeStyle' in value) return JSON.stringify(value)\n return serializeStyle(atomName, value as RNStyle)\n}\n\n/**\n * Resolve + envelope + serialize an atom's value under one scheme.\n * @param atomName Atom name.\n * @param style Raw RN style for this scheme.\n * @param keyframes Keyframes available to this build.\n * @returns Serialized text ready to emit.\n */\nfunction prepareAtomValue(atomName: string, style: RNStyle, keyframes: ReadonlyMap<string, KeyframeBlock>): string {\n const enveloped = envelopeSafeMarkers(inlineAnimationName(style, keyframes))\n return serializeAtomValue(atomName, enveloped)\n}\n\n/**\n * Decide which serialized atom values get hoisted to a shared `const`.\n * A value is hoisted ONLY when ≥2 atoms share it — then one\n * `const _s<N> = <value>` saves the repeated bytes AND gives those atoms\n * one shared object (reference identity). A value used once is inlined\n * directly at its atom (`\"-m-2\": {\"margin\":-8}`) — hoisting a singleton\n * would only add bytes. First-seen order keeps the const indices stable\n * across workers.\n * @param entries `[atomName, serializedValue]` pairs (atom-sorted).\n * @returns `{ constFor }` value→const-name map + `decls` source lines.\n */\nfunction planValueConsts(entries: readonly (readonly [string, string])[]): {\n constFor: ReadonlyMap<string, string>\n decls: readonly string[]\n} {\n const counts = new Map<string, number>()\n for (const [, value] of entries) counts.set(value, (counts.get(value) ?? 0) + 1)\n const constFor = new Map<string, string>()\n const decls: string[] = []\n for (const [value, count] of counts) {\n if (count < 2) continue\n const name = `_s${decls.length}`\n constFor.set(value, name)\n decls.push(`const ${name} = ${value}`)\n }\n return { constFor, decls }\n}\n\n/**\n * Serialize a scheme's molecule map into a `registerMolecules(...)` object\n * literal, sorted by className for byte-deterministic output.\n * @param molecules normalized className → pre-merged style object.\n * @returns Object-literal source (`null` when empty).\n */\nfunction serializeMolecules(molecules: Record<string, RNStyle> | undefined): string | null {\n if (!molecules) return null\n const keys = Object.keys(molecules).toSorted((a, b) => a.localeCompare(b))\n if (keys.length === 0) return null\n const body = keys.map((cn) => ` ${JSON.stringify(cn)}: ${JSON.stringify(molecules[cn])},`)\n return ['{', ...body, '}'].join('\\n')\n}\n\n/**\n * Render one scheme file's source. `entries` is the list of atoms this\n * scheme contributes — for `common` every atom's canonical value; for\n * a variant only atoms whose value differs from canonical. Hairline\n * atoms in this file trigger the `StyleSheet` import. Pre-merged\n * molecules (when present) are registered alongside the atoms so the\n * runtime resolver's molecule-first path is populated.\n * @param schemeName Registry key (`'common'` or the variant name).\n * @param entries `[atomName, serializedValue]` pairs to emit.\n * @param molecules Pre-merged className → style map for this scheme.\n * @returns JS source text.\n */\nfunction renderSchemeFile(\n schemeName: string,\n entries: readonly (readonly [string, string])[],\n molecules?: Record<string, RNStyle>,\n): string {\n const needsStyleSheet = entries.some(([atom]) => isHairlineAtom(atom))\n const { constFor, decls } = planValueConsts(entries)\n const recordLines = entries.map(([atom, value]) => ` ${JSON.stringify(atom)}: ${constFor.get(value) ?? value},`)\n const moleculeLiteral = serializeMolecules(molecules)\n\n const imports = ['registerAtoms']\n if (moleculeLiteral) imports.push('registerMolecules')\n const lines: string[] = []\n if (needsStyleSheet) lines.push(`import { StyleSheet } from 'react-native'`)\n lines.push(`import { ${imports.join(', ')} } from 'rnwind'`, ``)\n if (decls.length > 0) {\n for (const decl of decls) lines.push(decl)\n lines.push(``)\n }\n lines.push(`registerAtoms(${JSON.stringify(schemeName)}, {`, ...recordLines, `})`, ``)\n if (moleculeLiteral) lines.push(`registerMolecules(${JSON.stringify(schemeName)}, ${moleculeLiteral})`, ``)\n return lines.join('\\n')\n}\n\n/**\n * Serialize a feature map (atom name → JSON-able value: gradient info or\n * haptic request) into a stable JS object literal for the manifest.\n * Sorted by key so the output is byte-deterministic across workers.\n * @param map Atom name → feature value.\n * @returns Object-literal source.\n */\nfunction serializeFeatureMap(map: ReadonlyMap<string, unknown>): string {\n const entries = [...map.entries()].toSorted((a, b) => a[0].localeCompare(b[0]))\n const body = entries.map(([key, value]) => `${JSON.stringify(key)}: ${JSON.stringify(value)}`).join(', ')\n return `{ ${body} }`\n}\n\n/**\n * Render the JS-object literal for the responsive-breakpoint table the\n * runtime registers at manifest-load time. Sorted by ascending px\n * threshold so the runtime can build a deterministic \"tier index\" for\n * its style cache.\n * @param breakpoints Breakpoint name → px-threshold map.\n * @returns Object-literal source (`{}` when empty).\n */\nfunction serializeBreakpoints(breakpoints: ReadonlyMap<string, number>): string {\n if (breakpoints.size === 0) return '{}'\n const entries = [...breakpoints].toSorted((a, b) => a[1] - b[1] || a[0].localeCompare(b[0]))\n const inner = entries.map(([name, px]) => `${JSON.stringify(name)}: ${px}`).join(', ')\n return `{ ${inner} }`\n}\n\n/**\n * Render the manifest module. EAGER-imports `common.style.js` AND every\n * variant scheme file so every scheme's atoms register the moment the\n * manifest evaluates — no lazy `require`. Lazy loading raced the cold\n * start: `RnwindProvider` calls `loadScheme(scheme)` on its first render,\n * but on a cold boot the manifest (hence `registerSchemeLoader`) may not\n * have evaluated yet, so that call no-ops and the active variant's atoms\n * never load — scheme-dependent styles fall back to `common` (the light\n * default) until a reload. Eager imports remove the race entirely; the\n * variant files are small diffs, so the upfront cost is negligible.\n * `ensureSchemeLoaded` stays exported as a no-op for API compatibility.\n * @param variants Variant scheme names (no `base`, no `common`).\n * @param breakpoints Responsive breakpoint name → px-threshold map.\n * @param gradients Atom → gradient info for `registerGradients`.\n * @param haptics Atom → haptic request for `registerHaptics`.\n * @returns JS source text.\n */\nfunction renderManifest(\n variants: readonly string[],\n breakpoints: ReadonlyMap<string, number>,\n gradients: ReadonlyMap<string, unknown>,\n haptics: ReadonlyMap<string, unknown>,\n): string {\n const imports = ['registerSchemeLoader', 'registerBreakpoints']\n if (gradients.size > 0) imports.push('registerGradients')\n if (haptics.size > 0) imports.push('registerHaptics')\n const lines: string[] = [`import { ${imports.join(', ')} } from 'rnwind'`, `import './common.style'`]\n for (const variant of variants) lines.push(`import ${JSON.stringify(`./${variant}.style`)}`)\n lines.push(``, `registerBreakpoints(${serializeBreakpoints(breakpoints)})`)\n if (gradients.size > 0) lines.push(`registerGradients(${serializeFeatureMap(gradients)})`)\n if (haptics.size > 0) lines.push(`registerHaptics(${serializeFeatureMap(haptics)})`)\n lines.push(\n ``,\n `function ensureSchemeLoaded(_name) {}`,\n ``,\n `registerSchemeLoader(ensureSchemeLoaded)`,\n ``,\n `export { ensureSchemeLoaded }`,\n ``,\n )\n return lines.join('\\n')\n}\n\n/**\n * Whether a resolved style carries a nested safe-area marker — molecules\n * can't pre-bake these because the inset value is per-render.\n * @param style Raw resolved RN style (pre-envelope).\n * @returns True when any value is a `{__safe: ...}` marker.\n */\nfunction hasSafeMarker(style: RNStyle): boolean {\n for (const key of Object.keys(style)) {\n const value = style[key]\n if (typeof value !== 'object' || !value) continue\n if ('__safe' in value) return true\n }\n return false\n}\n\n/**\n * Whether a resolved style has font-scale-sensitive props. Molecules\n * can't pre-bake these because `fontSize`/`lineHeight` scale per-render\n * with `useWindowDimensions().fontScale`.\n * @param style Resolved RN style.\n * @returns True when `fontSize` or `lineHeight` is present.\n */\nfunction hasFontScaleProperty(style: RNStyle): boolean {\n return 'fontSize' in style || 'lineHeight' in style\n}\n\n/**\n * Whether a token is a feature-only utility (gradient stop/direction,\n * haptic, or text-truncate) that contributes NO RN `style` — the runtime\n * resolver folds these in via `attachFeatures`, so they don't disqualify\n * a molecule, they just merge nothing.\n * @param token Atom name.\n * @param gradients Gradient feature map.\n * @param haptics Haptic feature map.\n * @returns True when the token is a non-style feature.\n */\nfunction isFeatureToken(token: string, gradients: ReadonlyMap<string, unknown>, haptics: ReadonlyMap<string, unknown>): boolean {\n if (gradients.has(token) || haptics.has(token)) return true\n return token === 'truncate' || token === 'text-ellipsis' || token === 'text-clip' || token.startsWith('line-clamp-')\n}\n\n/**\n * Resolve one atom's value under a scheme: the scheme's own non-empty\n * bucket, falling back to canonical. `common` always reads canonical.\n * @param schemed Parser-produced per-scheme bucket.\n * @param scheme Scheme key (`'common'` or a variant name).\n * @returns The atom's RN style for that scheme, or undefined.\n */\nfunction schemeValueOf(schemed: SchemedStyle, scheme: string): RNStyle | undefined {\n if (scheme === COMMON_SCHEME) return canonicalValue(schemed)\n const own = (schemed as Readonly<Record<string, RNStyle>>)[scheme]\n return isNonEmptyStyle(own) ? own : canonicalValue(schemed)\n}\n\n/**\n * Pre-merge a normalized className's atoms into ONE RN style object for a\n * scheme, or null when the className is NOT molecule-eligible. A\n * className is eligible only when every token is context-independent:\n * - no variant prefix (`active:` / `focus:` / `md:` / `dark:` — anything\n * with a `:`), so scheme/state/breakpoint gating never applies,\n * - no `*-hairline`, `*-safe`, or font-scale (`fontSize`/`lineHeight`)\n * atom, whose value is resolved per-render.\n * Feature-only tokens (gradient / haptic / truncate) are skipped, not\n * disqualifying — the runtime folds them in via `attachFeatures`. Unknown\n * tokens disqualify so the atom path still surfaces the dev warning.\n * @param tokens Normalized className tokens (order preserved).\n * @param scheme Scheme key to resolve each atom under.\n * @param resolved Per-atom schemed styles.\n * @param keyframes Keyframes to inline into `animationName`.\n * @param gradients Gradient feature map.\n * @param haptics Haptic feature map.\n * @returns Merged style object, or null when not eligible.\n */\nfunction mergeMolecule(\n tokens: readonly string[],\n scheme: string,\n resolved: ReadonlyMap<string, SchemedStyle>,\n keyframes: ReadonlyMap<string, KeyframeBlock>,\n gradients: ReadonlyMap<string, unknown>,\n haptics: ReadonlyMap<string, unknown>,\n): RNStyle | null {\n const merged: RNStyle = {}\n for (const token of tokens) {\n if (token.includes(':')) return null\n if (isFeatureToken(token, gradients, haptics)) continue\n if (isHairlineAtom(token)) return null\n const schemed = resolved.get(token)\n if (!schemed) return null\n const raw = schemeValueOf(schemed, scheme)\n if (!raw) continue\n if (hasSafeMarker(raw) || hasFontScaleProperty(raw)) return null\n Object.assign(merged, inlineAnimationName(raw, keyframes))\n }\n return merged\n}\n\n/**\n * Emit each variant's molecule for one className — but only when the\n * variant's merge DIFFERS from common (runtime falls back to common).\n * @param normalized Normalized className key.\n * @param tokens Normalized className tokens.\n * @param commonText Serialized common-scheme merge for the diff check.\n * @param variants Variant scheme names.\n * @param variantMaps Mutable per-variant molecule collectors.\n * @param resolved Per-atom schemed styles.\n * @param keyframes Keyframes to inline.\n * @param gradients Gradient feature map.\n * @param haptics Haptic feature map.\n */\nfunction addVariantMolecules(\n normalized: string,\n tokens: readonly string[],\n commonText: string,\n variants: readonly string[],\n variantMaps: Record<string, Record<string, RNStyle>>,\n resolved: ReadonlyMap<string, SchemedStyle>,\n keyframes: ReadonlyMap<string, KeyframeBlock>,\n gradients: ReadonlyMap<string, unknown>,\n haptics: ReadonlyMap<string, unknown>,\n): void {\n for (const variant of variants) {\n const variantMerged = mergeMolecule(tokens, variant, resolved, keyframes, gradients, haptics)\n if (variantMerged === null) continue\n if (JSON.stringify(variantMerged) !== commonText) variantMaps[variant][normalized] = variantMerged\n }\n}\n\n/**\n * Build per-scheme molecules for every literal className the project\n * uses. Each eligible className gets a pre-merged style object under\n * `common`; a variant only carries an entry when its merge DIFFERS from\n * common (runtime falls back `molecules[scheme] ?? molecules.common`).\n * @param literals Distinct literal className strings (raw).\n * @param resolved Per-atom schemed styles.\n * @param keyframes Keyframes to inline.\n * @param variants Variant scheme names.\n * @param gradients Gradient feature map.\n * @param haptics Haptic feature map.\n * @returns scheme → (normalized className → merged style).\n */\nfunction buildMolecules(\n literals: readonly string[],\n resolved: ReadonlyMap<string, SchemedStyle>,\n keyframes: ReadonlyMap<string, KeyframeBlock>,\n variants: readonly string[],\n gradients: ReadonlyMap<string, unknown>,\n haptics: ReadonlyMap<string, unknown>,\n): Record<string, Record<string, RNStyle>> {\n const common: Record<string, RNStyle> = {}\n const variantMaps: Record<string, Record<string, RNStyle>> = {}\n for (const variant of variants) variantMaps[variant] = {}\n\n for (const literal of literals) {\n const normalized = normalizeClassName(literal)\n if (normalized.length === 0) continue\n const tokens = normalized.split(' ')\n const commonMerged = mergeMolecule(tokens, COMMON_SCHEME, resolved, keyframes, gradients, haptics)\n if (commonMerged === null) continue\n common[normalized] = commonMerged\n addVariantMolecules(normalized, tokens, JSON.stringify(commonMerged), variants, variantMaps, resolved, keyframes, gradients, haptics)\n }\n\n const out: Record<string, Record<string, RNStyle>> = { [COMMON_SCHEME]: common }\n for (const variant of variants) {\n if (Object.keys(variantMaps[variant]).length > 0) out[variant] = variantMaps[variant]\n }\n return out\n}\n\n/** Output of one build pass — one source per scheme plus the manifest. */\nexport interface BuildSchemeSourcesOutput {\n /** `<schemeName>.style.js` source per scheme. Always contains `common`. */\n readonly schemeSources: Readonly<Record<string, string>>\n /** Manifest module source (`schemes.js`). */\n readonly manifestSource: string\n /** Variant scheme names this build covers (sorted; excludes `common`). */\n readonly variants: readonly string[]\n /** Number of `prepareAtomValue` / JSON.stringify passes (cache MISSES) this call did — test telemetry. */\n readonly serializedMisses: number\n}\n\n/**\n * Per-atom cached serialized value. Canonical (common) string plus a\n * map of variant → own-serialized-string. `styleRef` is an identity\n * guard against the resolved SchemedStyle — when callers replace an\n * atom's value the ref diverges and the cache rebuilds that entry.\n */\nexport interface AtomSerializedEntry {\n styleRef: SchemedStyle\n canonical: string\n variants: Map<string, string>\n}\n\n/** Cache UnionBuilder owns across repeated writeSchemes calls. */\nexport type AtomSerializedCache = Map<string, AtomSerializedEntry>\n\n/**\n * Pre-serialize every non-empty variant value, reusing the per-atom\n * cache where present. Result drives both the scheme-uniform check\n * AND the per-variant emission loop downstream.\n * @param atom Atom name.\n * @param schemed Parser-produced schemed bucket.\n * @param variants Variant scheme names in deterministic order.\n * @param keyframes Keyframes available to inline.\n * @param cached Cached entry for this atom (when ref-stable).\n * @returns variantName → serialized text.\n */\nfunction buildVariantTexts(\n atom: string,\n schemed: SchemedStyle,\n variants: readonly string[],\n keyframes: ReadonlyMap<string, KeyframeBlock>,\n cached: AtomSerializedEntry | undefined,\n): Map<string, string> {\n const out = new Map<string, string>()\n for (const variant of variants) {\n const own = (schemed as Readonly<Record<string, RNStyle>>)[variant]\n if (!isNonEmptyStyle(own)) continue\n const text = cached?.variants.get(variant) ?? prepareAtomValue(atom, own, keyframes)\n out.set(variant, text)\n }\n return out\n}\n\n/**\n * Decide whether a (no-base) atom should be promoted to common because\n * every declared variant resolves to the same value. This is the\n * scheme-uniform case: `flex`, `p-4`, `absolute` all carry no theme\n * variables, so Phase-1 fills every variant bucket identically and\n * leaves `base` empty — without this collapse they'd be duplicated\n * across every scheme file.\n *\n * The variant-prefix check is what keeps a real scheme-gated atom\n * (`dark:bg-indigo-800`) out of common in a single-variant project\n * (where its 1 bucket would otherwise look \"uniform\" by definition).\n * @param atom Atom name (checked for `<variant>:` prefix).\n * @param variants Declared variant scheme names.\n * @param variantTexts Serialized variant values.\n * @param canonicalText Serialized canonical (common) value.\n * @returns Whether the atom is uniform across every declared variant.\n */\nfunction isSchemeUniform(\n atom: string,\n variants: readonly string[],\n variantTexts: ReadonlyMap<string, string>,\n canonicalText: string,\n): boolean {\n if (variants.length === 0 || variantTexts.size !== variants.length) return false\n if (variants.some((variant) => atom.startsWith(`${variant}:`))) return false\n for (const text of variantTexts.values()) {\n if (text !== canonicalText) return false\n }\n return true\n}\n\n/**\n * Serialize one atom's canonical + variant-diff entries, honouring the\n * per-atom cache. Returns the number of cache MISSES this atom incurred\n * (0 when canonical was cached AND every needed variant was cached;\n * 1 when anything had to be re-stringified).\n *\n * Three paths gated on whether the parser produced a non-empty `base`\n * bucket and whether the variants converge:\n * - **Themed atom (base present)**: canonical goes to `common`, each\n * variant whose own value diverges from canonical writes the diff\n * into its own scheme file. `lookupAtom` finds the variant's\n * override or falls through to common.\n * - **Scheme-uniform atom (base empty, every variant identical)**:\n * promoted to `common` once — the parser's Phase-1 fills every\n * variant bucket with the same value for utilities like `flex` /\n * `p-4` / `absolute` that don't reference theme variables.\n * - **Scheme-gated atom (base empty, prefixed name like `dark:foo`,\n * or variants diverge)**: each populated variant writes the value\n * into its own scheme file directly; common stays empty so the\n * runtime fallback can't leak the variant style into other schemes.\n * @param atom Atom name.\n * @param schemed Parser-produced schemed bucket for the atom.\n * @param canonical Canonical RN style for `common`.\n * @param variants Variant scheme names in deterministic order.\n * @param keyframes Keyframes available to inline.\n * @param commonEntries Mutable collector for `common`'s `[atom, text]` pairs.\n * @param variantEntries Mutable collector keyed by variant name.\n * @param cache Optional shared serialized-value cache.\n * @returns Number of JSON.stringify passes triggered for this atom.\n */\nfunction collectAtomEntries(\n atom: string,\n schemed: SchemedStyle,\n canonical: RNStyle,\n variants: readonly string[],\n keyframes: ReadonlyMap<string, KeyframeBlock>,\n commonEntries: (readonly [string, string])[],\n variantEntries: Record<string, (readonly [string, string])[]>,\n cache?: AtomSerializedCache,\n): number {\n const cached = cache?.get(atom)\n const hit = cached?.styleRef === schemed\n const baseEntry = (schemed as Readonly<Record<string, RNStyle>>)[BASE_SCHEME]\n const hasBase = isNonEmptyStyle(baseEntry)\n const canonicalText = hit ? cached.canonical : prepareAtomValue(atom, canonical, keyframes)\n const variantTexts = buildVariantTexts(atom, schemed, variants, keyframes, hit ? cached : undefined)\n const goesToCommon = hasBase || isSchemeUniform(atom, variants, variantTexts, canonicalText)\n\n if (goesToCommon) commonEntries.push([atom, canonicalText])\n\n const entry: AtomSerializedEntry = hit\n ? cached\n : { styleRef: schemed, canonical: canonicalText, variants: new Map(variantTexts) }\n if (!hit) cache?.set(atom, entry)\n\n for (const variant of variants) {\n const ownText = variantTexts.get(variant)\n if (ownText === undefined) continue\n if (goesToCommon && ownText === canonicalText) continue\n variantEntries[variant].push([atom, ownText])\n }\n return hit ? 0 : 1\n}\n\n/** Empty fallback when the caller didn't supply breakpoints (legacy callers, tests). */\nconst EMPTY_BREAKPOINTS: ReadonlyMap<string, number> = new Map()\n\n/**\n * Build the per-scheme style files + manifest source.\n *\n * Dedup rule (the thing that shrinks scheme files to their diff):\n * - Every atom's canonical value goes into `common.style.js`.\n * - Each variant's file emits an entry for an atom ONLY when the\n * variant's own resolved value differs from canonical. When the\n * variant inherits (parser emits an empty `{}` for that scheme) or\n * the variant's resolved value serializes identically to canonical,\n * the atom is omitted — at runtime the lookup falls through via\n * `cache.atoms[scheme]?.[atom] ?? cache.atoms.common[atom]`.\n *\n * Keyframes are inlined directly into atom values via `animationName`\n * ({@link inlineAnimationName}). Safe-area markers get pre-enveloped\n * via {@link envelopeSafeMarkers}. Hairline utilities stay bound to\n * `StyleSheet.hairlineWidth` at runtime.\n * @param atomNames All atom names (sorted).\n * @param resolved Per-atom schemed styles from the parser.\n * @param keyframes Keyframe blocks referenced by any atom.\n * @param cache Optional shared serialized-value cache.\n * @param breakpoints Responsive breakpoint name → px-threshold map. The\n * manifest emits `registerBreakpoints({...})` so the runtime can gate\n * `md:*` / `lg:*` atoms on `windowWidth`. Optional — empty when the\n * theme declares no breakpoints (legacy/test callers).\n * @param gradients Gradient feature map (atom → role/colour) for the manifest + molecule eligibility.\n * @param haptics Haptic feature map (atom → request) for the manifest + molecule eligibility.\n * @param literals Distinct literal className strings — pre-merged into\n * per-scheme molecules so the runtime resolver's O(1) molecule-first\n * path is populated. Empty for legacy/test callers (atom path only).\n * @returns Per-scheme sources, manifest source, variant list.\n */\nexport function buildSchemeSources(\n atomNames: readonly string[],\n resolved: ReadonlyMap<string, SchemedStyle>,\n keyframes: ReadonlyMap<string, KeyframeBlock>,\n cache?: AtomSerializedCache,\n breakpoints: ReadonlyMap<string, number> = EMPTY_BREAKPOINTS,\n gradients: ReadonlyMap<string, unknown> = EMPTY_FEATURE_MAP,\n haptics: ReadonlyMap<string, unknown> = EMPTY_FEATURE_MAP,\n literals: readonly string[] = EMPTY_LITERALS,\n): BuildSchemeSourcesOutput {\n const variants = collectVariantSchemes(resolved)\n const commonEntries: (readonly [string, string])[] = []\n const variantEntries: Record<string, (readonly [string, string])[]> = {}\n for (const variant of variants) variantEntries[variant] = []\n let misses = 0\n\n for (const atom of atomNames) {\n const schemed = resolved.get(atom)\n if (!schemed) continue\n const canonical = canonicalValue(schemed)\n if (!canonical) continue\n misses += collectAtomEntries(atom, schemed, canonical, variants, keyframes, commonEntries, variantEntries, cache)\n }\n\n const molecules = buildMolecules(literals, resolved, keyframes, variants, gradients, haptics)\n const schemeSources: Record<string, string> = {\n [COMMON_SCHEME]: renderSchemeFile(COMMON_SCHEME, commonEntries, molecules[COMMON_SCHEME]),\n }\n for (const variant of variants) {\n schemeSources[variant] = renderSchemeFile(variant, variantEntries[variant], molecules[variant])\n }\n\n return {\n schemeSources,\n manifestSource: renderManifest(variants, breakpoints, gradients, haptics),\n variants,\n serializedMisses: misses,\n }\n}\n\n/** Shared empty feature map default. */\nconst EMPTY_FEATURE_MAP: ReadonlyMap<string, unknown> = new Map()\n\n/** Shared empty literal-list default (atom-only callers). */\nconst EMPTY_LITERALS: readonly string[] = []\n\n/** Registry key the runtime uses for the always-loaded fallback. */\nexport const COMMON_SCHEME_NAME: string = COMMON_SCHEME\n"],"names":[],"mappings":"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"}
@@ -21,6 +21,17 @@ declare class UnionBuilder {
21
21
  private readonly parser;
22
22
  private readonly unionAtoms;
23
23
  private readonly unionKeyframes;
24
+ /** atom name → gradient role/colour, surfaced into the manifest's `registerGradients`. */
25
+ private readonly unionGradients;
26
+ /** atom name → haptic request, surfaced into the manifest's `registerHaptics`. */
27
+ private readonly unionHaptics;
28
+ /**
29
+ * Distinct literal className strings seen across all files, pre-merged
30
+ * into per-scheme molecules at write time. Accumulate-only (like
31
+ * `unionAtoms`): orphaned literals just yield unused molecules and get
32
+ * reaped on the next cold start, so no refcount is needed.
33
+ */
34
+ private readonly unionLiterals;
24
35
  /**
25
36
  * Responsive breakpoints captured from the parser. Refreshed on every
26
37
  * `recordFile` / `ensureProjectScanned` so user-defined
@@ -84,13 +95,22 @@ declare class UnionBuilder {
84
95
  * @param file Absolute source file path.
85
96
  * @param atoms Per-atom resolved schemed styles from this transform.
86
97
  * @param keyframes Keyframe blocks referenced by this file's atoms.
98
+ * @param literals
87
99
  * @returns `{ changed: true }` when the union shifted (new atom name,
88
100
  * removed atom name, or new keyframe) — the transformer uses this
89
101
  * to skip the serializer + `writeSchemes` when nothing changed.
90
102
  */
91
- recordFile(file: string, atoms: ReadonlyMap<string, SchemedStyle>, keyframes: ReadonlyMap<string, KeyframeBlock>): Promise<{
103
+ recordFile(file: string, atoms: ReadonlyMap<string, SchemedStyle>, keyframes: ReadonlyMap<string, KeyframeBlock>, literals?: readonly string[]): Promise<{
92
104
  changed: boolean;
93
105
  }>;
106
+ /**
107
+ * Merge a file's literal classNames into the union. A literal the
108
+ * union hasn't seen flips `changed` so `writeSchemes` re-emits the
109
+ * scheme files with the new molecule.
110
+ * @param literals Distinct literal className strings.
111
+ * @returns Whether any literal was new to the union.
112
+ */
113
+ private recordLiterals;
94
114
  /**
95
115
  * Forget one source file's contribution. Idempotent — repeated calls
96
116
  * for a file that's already dropped are no-ops. Does NOT remove the
@@ -90,6 +90,17 @@ class UnionBuilder {
90
90
  parser;
91
91
  unionAtoms = new Map();
92
92
  unionKeyframes = new Map();
93
+ /** atom name → gradient role/colour, surfaced into the manifest's `registerGradients`. */
94
+ unionGradients = new Map();
95
+ /** atom name → haptic request, surfaced into the manifest's `registerHaptics`. */
96
+ unionHaptics = new Map();
97
+ /**
98
+ * Distinct literal className strings seen across all files, pre-merged
99
+ * into per-scheme molecules at write time. Accumulate-only (like
100
+ * `unionAtoms`): orphaned literals just yield unused molecules and get
101
+ * reaped on the next cold start, so no refcount is needed.
102
+ */
103
+ unionLiterals = new Set();
93
104
  /**
94
105
  * Responsive breakpoints captured from the parser. Refreshed on every
95
106
  * `recordFile` / `ensureProjectScanned` so user-defined
@@ -167,6 +178,10 @@ class UnionBuilder {
167
178
  this.unionAtoms.set(name, style);
168
179
  for (const [name, kf] of parsed.keyframes)
169
180
  this.unionKeyframes.set(name, kf);
181
+ for (const [name, gradient] of parsed.gradientAtoms)
182
+ this.unionGradients.set(name, gradient);
183
+ for (const [name, haptic] of parsed.hapticAtoms)
184
+ this.unionHaptics.set(name, haptic);
170
185
  this.breakpoints = parsed.breakpoints;
171
186
  this.projectScanned = true;
172
187
  })();
@@ -185,12 +200,14 @@ class UnionBuilder {
185
200
  * @param file Absolute source file path.
186
201
  * @param atoms Per-atom resolved schemed styles from this transform.
187
202
  * @param keyframes Keyframe blocks referenced by this file's atoms.
203
+ * @param literals
188
204
  * @returns `{ changed: true }` when the union shifted (new atom name,
189
205
  * removed atom name, or new keyframe) — the transformer uses this
190
206
  * to skip the serializer + `writeSchemes` when nothing changed.
191
207
  */
192
- async recordFile(file, atoms, keyframes) {
208
+ async recordFile(file, atoms, keyframes, literals = []) {
193
209
  await this.ensureProjectScanned();
210
+ const literalAdded = this.recordLiterals(literals);
194
211
  const newAtomNames = new Set(atoms.keys());
195
212
  const previous = this.fileAtomSets.get(file);
196
213
  if (previous && setsEqual(previous, newAtomNames)) {
@@ -206,11 +223,28 @@ class UnionBuilder {
206
223
  keyframeAdded = true;
207
224
  this.unionKeyframes.set(name, kf);
208
225
  }
209
- return { changed: keyframeAdded };
226
+ return { changed: keyframeAdded || literalAdded };
210
227
  }
211
228
  this.applyDiff(file, newAtomNames, atoms, keyframes);
212
229
  return { changed: true };
213
230
  }
231
+ /**
232
+ * Merge a file's literal classNames into the union. A literal the
233
+ * union hasn't seen flips `changed` so `writeSchemes` re-emits the
234
+ * scheme files with the new molecule.
235
+ * @param literals Distinct literal className strings.
236
+ * @returns Whether any literal was new to the union.
237
+ */
238
+ recordLiterals(literals) {
239
+ let added = false;
240
+ for (const literal of literals) {
241
+ if (this.unionLiterals.has(literal))
242
+ continue;
243
+ this.unionLiterals.add(literal);
244
+ added = true;
245
+ }
246
+ return added;
247
+ }
214
248
  /**
215
249
  * Forget one source file's contribution. Idempotent — repeated calls
216
250
  * for a file that's already dropped are no-ops. Does NOT remove the
@@ -242,7 +276,7 @@ class UnionBuilder {
242
276
  async writeSchemes() {
243
277
  await this.ensureProjectScanned();
244
278
  const sortedAtomNames = [...this.unionAtoms.keys()].toSorted((a, b) => a.localeCompare(b));
245
- const result = buildSchemeSources(sortedAtomNames, this.unionAtoms, this.unionKeyframes, this.serializedCache, this.breakpoints);
279
+ const result = buildSchemeSources(sortedAtomNames, this.unionAtoms, this.unionKeyframes, this.serializedCache, this.breakpoints, this.unionGradients, this.unionHaptics, [...this.unionLiterals]);
246
280
  this.serializedMissesCount += result.serializedMisses;
247
281
  const { schemeSources, manifestSource } = result;
248
282
  const changed = [];
@@ -1 +1 @@
1
- {"version":3,"file":"union-builder.mjs","sources":["../../../../../src/core/style-builder/union-builder.ts"],"sourcesContent":["import { createHash, randomBytes } from 'node:crypto'\nimport { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport path from 'node:path'\nimport type { KeyframeBlock, SchemedStyle, TailwindParser } from '../parser'\nimport { buildSchemeSources, type AtomSerializedCache } from './build-style'\n\n/** Manifest module basename — the file SchemeProvider imports via the resolver. */\nconst MANIFEST_BASENAME = 'schemes.js'\n\n/**\n * Atomic file write — stage to a `.tmp.<pid>.<nonce>` sibling, then\n * `rename()` into place. Skips the write entirely when the existing\n * content matches.\n * @param target Final destination path.\n * @param content Bytes to write.\n * @returns Whether the file was actually rewritten.\n */\nfunction writeIfChanged(target: string, content: string): boolean {\n if (existsSync(target)) {\n try {\n if (readFileSync(target, 'utf8') === content) return false\n } catch {\n // Unreadable — fall through to rewrite.\n }\n }\n mkdirSync(path.dirname(target), { recursive: true })\n const temporary = `${target}.${process.pid}.${randomBytes(4).toString('hex')}.tmp`\n try {\n writeFileSync(temporary, content, 'utf8')\n renameSync(temporary, target)\n return true\n } catch (error) {\n rmSync(temporary, { force: true })\n throw error\n }\n}\n\n/**\n * SHA-256 prefix of a string — cheap signature used to detect whether a\n * per-scheme file's source has changed since the last write.\n * @param text Input text.\n * @returns 16-char hex digest.\n */\nfunction signatureOf(text: string): string {\n return createHash('sha256').update(text).digest('hex').slice(0, 16)\n}\n\n/**\n * Compare two `Set<string>`s for equality — same size + every element\n * of `a` present in `b`.\n * @param a First set.\n * @param b Second set.\n * @returns Whether the two sets contain identical values.\n */\nfunction setsEqual(a: ReadonlySet<string>, b: ReadonlySet<string>): boolean {\n if (a.size !== b.size) return false\n for (const v of a) if (!b.has(v)) return false\n return true\n}\n\n/**\n * Compute the absolute path of a per-scheme style file under the cache dir.\n * @param cacheDir Absolute cache directory.\n * @param scheme Registry key (`'common'` or a variant name).\n * @returns Absolute path, e.g. `<cacheDir>/dark.style.js`.\n */\nfunction schemeFilePath(cacheDir: string, scheme: string): string {\n return path.join(cacheDir, `${scheme}.style.js`)\n}\n\n/**\n * In-memory atom union + per-scheme style-file emitter.\n *\n * Correctness under multi-worker Metro relies on `ensureProjectScanned`:\n * the FIRST `recordFile` / `writeSchemes` call in every worker drives\n * the oxide Scanner across ALL project sources and hydrates the union\n * with the complete set of candidates. Subsequent per-file\n * `recordFile` calls only layer in atoms the scan already knew about,\n * so writes are idempotent — different workers can't clobber each\n * other's scheme files with partial views.\n *\n * Per-file deltas (atom set unchanged → early return) skip\n * serialization entirely. On a theme-CSS change, `getRnwindState`\n * builds a fresh parser + builder; the next call re-runs\n * `ensureProjectScanned` against the new parser, producing scheme\n * files with the new theme values.\n */\nclass UnionBuilder {\n private readonly cacheDir: string\n private readonly parser: TailwindParser\n private readonly unionAtoms = new Map<string, SchemedStyle>()\n private readonly unionKeyframes = new Map<string, KeyframeBlock>()\n /**\n * Responsive breakpoints captured from the parser. Refreshed on every\n * `recordFile` / `ensureProjectScanned` so user-defined\n * `--breakpoint-*` overrides land in the manifest the next time it's\n * written. Identical for every parser call within one parser instance\n * (theme is fixed for the parser's lifetime), so storing the latest\n * snapshot is sufficient.\n */\n private breakpoints: ReadonlyMap<string, number> = new Map()\n /** file → set of atom names this file currently contributes. */\n private readonly fileAtomSets = new Map<string, Set<string>>()\n /** atom name → how many files currently contribute it (refcount). */\n private readonly atomRefCount = new Map<string, number>()\n /** scheme → last-written source SHA. Skips re-writing unchanged schemes. */\n private readonly schemeSignatures = new Map<string, string>()\n /**\n * Per-atom serialized-value cache — identity-keyed on each atom's\n * SchemedStyle reference. Carried across `writeSchemes` calls so the\n * typical \"user added one className\" FR case re-stringifies ONE atom\n * instead of all 175+. Cleared on `ensureProjectScanned` (full\n * rescan replaces every reference) and individually invalidated for\n * any atom `applyDiff` mutates.\n */\n private readonly serializedCache: AtomSerializedCache = new Map()\n /** Running count of stringify passes (cache misses). Test telemetry. */\n private serializedMissesCount = 0\n /** Set after `ensureProjectScanned` completes. */\n private projectScanned = false\n /** Promise guard so concurrent first-calls await ONE scan. */\n private pendingScan: Promise<void> | null = null\n\n constructor(cacheDir: string, parser: TailwindParser) {\n this.cacheDir = cacheDir\n this.parser = parser\n mkdirSync(this.cacheDir, { recursive: true })\n }\n\n /** Absolute path of the manifest module (`rnwind/__generated/schemes`). */\n public get manifestPath(): string {\n return path.join(this.cacheDir, MANIFEST_BASENAME)\n }\n\n /**\n * Snapshot of every source file the builder has recorded atoms for\n * this worker session. Used by `withRnwindConfig`'s CSS watcher to\n * touch `mtime` on each and nudge Metro into re-transforming them\n * with the new theme values.\n * @returns Absolute source paths.\n */\n public recordedFiles(): readonly string[] {\n return [...this.fileAtomSets.keys()]\n }\n\n /** Cumulative cache-miss count — exposed for tests to assert cache behaviour. */\n public get serializedMisses(): number {\n return this.serializedMissesCount\n }\n\n /**\n * Absolute path of one scheme's style file.\n * @param scheme Registry key.\n * @returns Absolute path.\n */\n public schemePath(scheme: string): string {\n return schemeFilePath(this.cacheDir, scheme)\n }\n\n /**\n * One-shot oxide scan + compile across every source the parser was\n * configured with. Idempotent — safe to call from any entry point.\n * Concurrent callers share the same in-flight promise.\n */\n public async ensureProjectScanned(): Promise<void> {\n if (this.projectScanned) return\n if (this.pendingScan) return this.pendingScan\n this.pendingScan = (async () => {\n const parsed = await this.parser.parseProject()\n for (const [name, style] of parsed.atoms) this.unionAtoms.set(name, style)\n for (const [name, kf] of parsed.keyframes) this.unionKeyframes.set(name, kf)\n this.breakpoints = parsed.breakpoints\n this.projectScanned = true\n })()\n try {\n await this.pendingScan\n } finally {\n this.pendingScan = null\n }\n }\n\n /**\n * Record one source file's resolved atoms + keyframes. Short-circuits\n * when the file's atom name set hasn't changed — the common case on\n * every Fast Refresh save of a file whose className literals are\n * unchanged.\n * @param file Absolute source file path.\n * @param atoms Per-atom resolved schemed styles from this transform.\n * @param keyframes Keyframe blocks referenced by this file's atoms.\n * @returns `{ changed: true }` when the union shifted (new atom name,\n * removed atom name, or new keyframe) — the transformer uses this\n * to skip the serializer + `writeSchemes` when nothing changed.\n */\n public async recordFile(\n file: string,\n atoms: ReadonlyMap<string, SchemedStyle>,\n keyframes: ReadonlyMap<string, KeyframeBlock>,\n ): Promise<{ changed: boolean }> {\n await this.ensureProjectScanned()\n const newAtomNames = new Set(atoms.keys())\n const previous = this.fileAtomSets.get(file)\n if (previous && setsEqual(previous, newAtomNames)) {\n // Atom set unchanged — skip the unionAtoms update entirely. The\n // project scan already populated them, and re-setting a fresh\n // object ref here would invalidate the per-atom serialization\n // cache on every FR save for no gain (values are identical).\n // Theme edits go through `getRnwindState` → new builder → fresh\n // scan, so stale cache is impossible.\n let keyframeAdded = false\n for (const [name, kf] of keyframes) {\n if (!this.unionKeyframes.has(name)) keyframeAdded = true\n this.unionKeyframes.set(name, kf)\n }\n return { changed: keyframeAdded }\n }\n this.applyDiff(file, newAtomNames, atoms, keyframes)\n return { changed: true }\n }\n\n /**\n * Forget one source file's contribution. Idempotent — repeated calls\n * for a file that's already dropped are no-ops. Does NOT remove the\n * atom from the union when another file (or the project scan) still\n * references it.\n * @param file Absolute source file path.\n */\n public dropFile(file: string): void {\n const previous = this.fileAtomSets.get(file)\n if (!previous) return\n for (const name of previous) {\n const count = (this.atomRefCount.get(name) ?? 0) - 1\n if (count <= 0) this.atomRefCount.delete(name)\n else this.atomRefCount.set(name, count)\n }\n this.fileAtomSets.delete(file)\n }\n\n /**\n * Serialize the union into per-scheme files + manifest, writing only\n * files whose source bytes changed. Called after every `recordFile`\n * from the transformer — and once at Metro startup via\n * `ensureFilesExist` to seed disk from the project scan alone.\n * @returns List of scheme keys whose files were rewritten (empty\n * when the union is byte-identical to the last flush).\n */\n public async writeSchemes(): Promise<{ changedSchemes: readonly string[] }> {\n await this.ensureProjectScanned()\n const sortedAtomNames = [...this.unionAtoms.keys()].toSorted((a, b) => a.localeCompare(b))\n const result = buildSchemeSources(sortedAtomNames, this.unionAtoms, this.unionKeyframes, this.serializedCache, this.breakpoints)\n this.serializedMissesCount += result.serializedMisses\n const { schemeSources, manifestSource } = result\n\n const changed: string[] = []\n for (const [scheme, source] of Object.entries(schemeSources)) {\n const signature = signatureOf(source)\n const target = schemeFilePath(this.cacheDir, scheme)\n if (this.schemeSignatures.get(scheme) === signature && existsSync(target)) continue\n if (writeIfChanged(target, source)) changed.push(scheme)\n this.schemeSignatures.set(scheme, signature)\n }\n\n const manifestSignature = signatureOf(manifestSource)\n const manifestTarget = path.join(this.cacheDir, MANIFEST_BASENAME)\n if (this.schemeSignatures.get('__manifest') !== manifestSignature || !existsSync(manifestTarget)) {\n if (writeIfChanged(manifestTarget, manifestSource)) changed.push('__manifest')\n this.schemeSignatures.set('__manifest', manifestSignature)\n }\n\n return { changedSchemes: changed }\n }\n\n /**\n * Ensure the manifest + common scheme files exist on disk so Metro's\n * resolver can SHA1 them at boot before the first transform runs.\n */\n public async ensureFilesExist(): Promise<void> {\n if (existsSync(this.manifestPath) && existsSync(schemeFilePath(this.cacheDir, 'common'))) {\n // Still trigger the scan so the in-memory union is complete; file\n // bytes may already be authoritative from a prior Metro run.\n await this.ensureProjectScanned()\n return\n }\n await this.writeSchemes()\n }\n\n /**\n * Apply one file's atom-name diff to the in-memory refcount + union.\n * @param file Source file path.\n * @param newAtoms New atom-name set for the file.\n * @param resolvedAtoms Fresh parser output — carries the resolved\n * styles for every entry in `newAtoms`.\n * @param newKeyframes Keyframes this file's atoms reference.\n */\n private applyDiff(\n file: string,\n newAtoms: ReadonlySet<string>,\n resolvedAtoms: ReadonlyMap<string, SchemedStyle>,\n newKeyframes: ReadonlyMap<string, KeyframeBlock>,\n ): void {\n const previous = this.fileAtomSets.get(file) ?? new Set<string>()\n for (const name of previous) {\n if (newAtoms.has(name)) continue\n const count = (this.atomRefCount.get(name) ?? 0) - 1\n if (count <= 0) this.atomRefCount.delete(name)\n else this.atomRefCount.set(name, count)\n // Do NOT remove `name` from `unionAtoms` — the project scan still\n // references it (orphaned atoms get reaped on the next Metro\n // cold start when the scanner re-walks disk).\n }\n for (const name of newAtoms) {\n if (!previous.has(name)) this.atomRefCount.set(name, (this.atomRefCount.get(name) ?? 0) + 1)\n // Only install the resolved style when the atom is new to the\n // union. Replacing an existing entry with a fresh parser-\n // produced object would swap the identity guard the per-atom\n // serialization cache uses and force a re-stringify for every\n // atom on every FR save. CSS edits rebuild the whole builder\n // (via `getRnwindState`) so stale values aren't possible.\n if (!this.unionAtoms.has(name)) {\n const style = resolvedAtoms.get(name)\n if (style) this.unionAtoms.set(name, style)\n }\n }\n this.fileAtomSets.set(file, new Set(newAtoms))\n for (const [name, kf] of newKeyframes) this.unionKeyframes.set(name, kf)\n }\n}\n\nexport { UnionBuilder }\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"union-builder.mjs","sources":["../../../../../src/core/style-builder/union-builder.ts"],"sourcesContent":["import { createHash, randomBytes } from 'node:crypto'\nimport { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport path from 'node:path'\nimport type { GradientAtomInfo, HapticRequest, KeyframeBlock, SchemedStyle, TailwindParser } from '../parser'\nimport { buildSchemeSources, type AtomSerializedCache } from './build-style'\n\n/** Manifest module basename — the file SchemeProvider imports via the resolver. */\nconst MANIFEST_BASENAME = 'schemes.js'\n\n/**\n * Atomic file write — stage to a `.tmp.<pid>.<nonce>` sibling, then\n * `rename()` into place. Skips the write entirely when the existing\n * content matches.\n * @param target Final destination path.\n * @param content Bytes to write.\n * @returns Whether the file was actually rewritten.\n */\nfunction writeIfChanged(target: string, content: string): boolean {\n if (existsSync(target)) {\n try {\n if (readFileSync(target, 'utf8') === content) return false\n } catch {\n // Unreadable — fall through to rewrite.\n }\n }\n mkdirSync(path.dirname(target), { recursive: true })\n const temporary = `${target}.${process.pid}.${randomBytes(4).toString('hex')}.tmp`\n try {\n writeFileSync(temporary, content, 'utf8')\n renameSync(temporary, target)\n return true\n } catch (error) {\n rmSync(temporary, { force: true })\n throw error\n }\n}\n\n/**\n * SHA-256 prefix of a string — cheap signature used to detect whether a\n * per-scheme file's source has changed since the last write.\n * @param text Input text.\n * @returns 16-char hex digest.\n */\nfunction signatureOf(text: string): string {\n return createHash('sha256').update(text).digest('hex').slice(0, 16)\n}\n\n/**\n * Compare two `Set<string>`s for equality — same size + every element\n * of `a` present in `b`.\n * @param a First set.\n * @param b Second set.\n * @returns Whether the two sets contain identical values.\n */\nfunction setsEqual(a: ReadonlySet<string>, b: ReadonlySet<string>): boolean {\n if (a.size !== b.size) return false\n for (const v of a) if (!b.has(v)) return false\n return true\n}\n\n/**\n * Compute the absolute path of a per-scheme style file under the cache dir.\n * @param cacheDir Absolute cache directory.\n * @param scheme Registry key (`'common'` or a variant name).\n * @returns Absolute path, e.g. `<cacheDir>/dark.style.js`.\n */\nfunction schemeFilePath(cacheDir: string, scheme: string): string {\n return path.join(cacheDir, `${scheme}.style.js`)\n}\n\n/**\n * In-memory atom union + per-scheme style-file emitter.\n *\n * Correctness under multi-worker Metro relies on `ensureProjectScanned`:\n * the FIRST `recordFile` / `writeSchemes` call in every worker drives\n * the oxide Scanner across ALL project sources and hydrates the union\n * with the complete set of candidates. Subsequent per-file\n * `recordFile` calls only layer in atoms the scan already knew about,\n * so writes are idempotent — different workers can't clobber each\n * other's scheme files with partial views.\n *\n * Per-file deltas (atom set unchanged → early return) skip\n * serialization entirely. On a theme-CSS change, `getRnwindState`\n * builds a fresh parser + builder; the next call re-runs\n * `ensureProjectScanned` against the new parser, producing scheme\n * files with the new theme values.\n */\nclass UnionBuilder {\n private readonly cacheDir: string\n private readonly parser: TailwindParser\n private readonly unionAtoms = new Map<string, SchemedStyle>()\n private readonly unionKeyframes = new Map<string, KeyframeBlock>()\n /** atom name → gradient role/colour, surfaced into the manifest's `registerGradients`. */\n private readonly unionGradients = new Map<string, GradientAtomInfo>()\n /** atom name → haptic request, surfaced into the manifest's `registerHaptics`. */\n private readonly unionHaptics = new Map<string, HapticRequest>()\n /**\n * Distinct literal className strings seen across all files, pre-merged\n * into per-scheme molecules at write time. Accumulate-only (like\n * `unionAtoms`): orphaned literals just yield unused molecules and get\n * reaped on the next cold start, so no refcount is needed.\n */\n private readonly unionLiterals = new Set<string>()\n /**\n * Responsive breakpoints captured from the parser. Refreshed on every\n * `recordFile` / `ensureProjectScanned` so user-defined\n * `--breakpoint-*` overrides land in the manifest the next time it's\n * written. Identical for every parser call within one parser instance\n * (theme is fixed for the parser's lifetime), so storing the latest\n * snapshot is sufficient.\n */\n private breakpoints: ReadonlyMap<string, number> = new Map()\n /** file → set of atom names this file currently contributes. */\n private readonly fileAtomSets = new Map<string, Set<string>>()\n /** atom name → how many files currently contribute it (refcount). */\n private readonly atomRefCount = new Map<string, number>()\n /** scheme → last-written source SHA. Skips re-writing unchanged schemes. */\n private readonly schemeSignatures = new Map<string, string>()\n /**\n * Per-atom serialized-value cache — identity-keyed on each atom's\n * SchemedStyle reference. Carried across `writeSchemes` calls so the\n * typical \"user added one className\" FR case re-stringifies ONE atom\n * instead of all 175+. Cleared on `ensureProjectScanned` (full\n * rescan replaces every reference) and individually invalidated for\n * any atom `applyDiff` mutates.\n */\n private readonly serializedCache: AtomSerializedCache = new Map()\n /** Running count of stringify passes (cache misses). Test telemetry. */\n private serializedMissesCount = 0\n /** Set after `ensureProjectScanned` completes. */\n private projectScanned = false\n /** Promise guard so concurrent first-calls await ONE scan. */\n private pendingScan: Promise<void> | null = null\n\n constructor(cacheDir: string, parser: TailwindParser) {\n this.cacheDir = cacheDir\n this.parser = parser\n mkdirSync(this.cacheDir, { recursive: true })\n }\n\n /** Absolute path of the manifest module (`rnwind/__generated/schemes`). */\n public get manifestPath(): string {\n return path.join(this.cacheDir, MANIFEST_BASENAME)\n }\n\n /**\n * Snapshot of every source file the builder has recorded atoms for\n * this worker session. Used by `withRnwindConfig`'s CSS watcher to\n * touch `mtime` on each and nudge Metro into re-transforming them\n * with the new theme values.\n * @returns Absolute source paths.\n */\n public recordedFiles(): readonly string[] {\n return [...this.fileAtomSets.keys()]\n }\n\n /** Cumulative cache-miss count — exposed for tests to assert cache behaviour. */\n public get serializedMisses(): number {\n return this.serializedMissesCount\n }\n\n /**\n * Absolute path of one scheme's style file.\n * @param scheme Registry key.\n * @returns Absolute path.\n */\n public schemePath(scheme: string): string {\n return schemeFilePath(this.cacheDir, scheme)\n }\n\n /**\n * One-shot oxide scan + compile across every source the parser was\n * configured with. Idempotent — safe to call from any entry point.\n * Concurrent callers share the same in-flight promise.\n */\n public async ensureProjectScanned(): Promise<void> {\n if (this.projectScanned) return\n if (this.pendingScan) return this.pendingScan\n this.pendingScan = (async () => {\n const parsed = await this.parser.parseProject()\n for (const [name, style] of parsed.atoms) this.unionAtoms.set(name, style)\n for (const [name, kf] of parsed.keyframes) this.unionKeyframes.set(name, kf)\n for (const [name, gradient] of parsed.gradientAtoms) this.unionGradients.set(name, gradient)\n for (const [name, haptic] of parsed.hapticAtoms) this.unionHaptics.set(name, haptic)\n this.breakpoints = parsed.breakpoints\n this.projectScanned = true\n })()\n try {\n await this.pendingScan\n } finally {\n this.pendingScan = null\n }\n }\n\n /**\n * Record one source file's resolved atoms + keyframes. Short-circuits\n * when the file's atom name set hasn't changed — the common case on\n * every Fast Refresh save of a file whose className literals are\n * unchanged.\n * @param file Absolute source file path.\n * @param atoms Per-atom resolved schemed styles from this transform.\n * @param keyframes Keyframe blocks referenced by this file's atoms.\n * @param literals\n * @returns `{ changed: true }` when the union shifted (new atom name,\n * removed atom name, or new keyframe) — the transformer uses this\n * to skip the serializer + `writeSchemes` when nothing changed.\n */\n public async recordFile(\n file: string,\n atoms: ReadonlyMap<string, SchemedStyle>,\n keyframes: ReadonlyMap<string, KeyframeBlock>,\n literals: readonly string[] = [],\n ): Promise<{ changed: boolean }> {\n await this.ensureProjectScanned()\n const literalAdded = this.recordLiterals(literals)\n const newAtomNames = new Set(atoms.keys())\n const previous = this.fileAtomSets.get(file)\n if (previous && setsEqual(previous, newAtomNames)) {\n // Atom set unchanged — skip the unionAtoms update entirely. The\n // project scan already populated them, and re-setting a fresh\n // object ref here would invalidate the per-atom serialization\n // cache on every FR save for no gain (values are identical).\n // Theme edits go through `getRnwindState` → new builder → fresh\n // scan, so stale cache is impossible.\n let keyframeAdded = false\n for (const [name, kf] of keyframes) {\n if (!this.unionKeyframes.has(name)) keyframeAdded = true\n this.unionKeyframes.set(name, kf)\n }\n return { changed: keyframeAdded || literalAdded }\n }\n this.applyDiff(file, newAtomNames, atoms, keyframes)\n return { changed: true }\n }\n\n /**\n * Merge a file's literal classNames into the union. A literal the\n * union hasn't seen flips `changed` so `writeSchemes` re-emits the\n * scheme files with the new molecule.\n * @param literals Distinct literal className strings.\n * @returns Whether any literal was new to the union.\n */\n private recordLiterals(literals: readonly string[]): boolean {\n let added = false\n for (const literal of literals) {\n if (this.unionLiterals.has(literal)) continue\n this.unionLiterals.add(literal)\n added = true\n }\n return added\n }\n\n /**\n * Forget one source file's contribution. Idempotent — repeated calls\n * for a file that's already dropped are no-ops. Does NOT remove the\n * atom from the union when another file (or the project scan) still\n * references it.\n * @param file Absolute source file path.\n */\n public dropFile(file: string): void {\n const previous = this.fileAtomSets.get(file)\n if (!previous) return\n for (const name of previous) {\n const count = (this.atomRefCount.get(name) ?? 0) - 1\n if (count <= 0) this.atomRefCount.delete(name)\n else this.atomRefCount.set(name, count)\n }\n this.fileAtomSets.delete(file)\n }\n\n /**\n * Serialize the union into per-scheme files + manifest, writing only\n * files whose source bytes changed. Called after every `recordFile`\n * from the transformer — and once at Metro startup via\n * `ensureFilesExist` to seed disk from the project scan alone.\n * @returns List of scheme keys whose files were rewritten (empty\n * when the union is byte-identical to the last flush).\n */\n public async writeSchemes(): Promise<{ changedSchemes: readonly string[] }> {\n await this.ensureProjectScanned()\n const sortedAtomNames = [...this.unionAtoms.keys()].toSorted((a, b) => a.localeCompare(b))\n const result = buildSchemeSources(sortedAtomNames, this.unionAtoms, this.unionKeyframes, this.serializedCache, this.breakpoints, this.unionGradients, this.unionHaptics, [...this.unionLiterals])\n this.serializedMissesCount += result.serializedMisses\n const { schemeSources, manifestSource } = result\n\n const changed: string[] = []\n for (const [scheme, source] of Object.entries(schemeSources)) {\n const signature = signatureOf(source)\n const target = schemeFilePath(this.cacheDir, scheme)\n if (this.schemeSignatures.get(scheme) === signature && existsSync(target)) continue\n if (writeIfChanged(target, source)) changed.push(scheme)\n this.schemeSignatures.set(scheme, signature)\n }\n\n const manifestSignature = signatureOf(manifestSource)\n const manifestTarget = path.join(this.cacheDir, MANIFEST_BASENAME)\n if (this.schemeSignatures.get('__manifest') !== manifestSignature || !existsSync(manifestTarget)) {\n if (writeIfChanged(manifestTarget, manifestSource)) changed.push('__manifest')\n this.schemeSignatures.set('__manifest', manifestSignature)\n }\n\n return { changedSchemes: changed }\n }\n\n /**\n * Ensure the manifest + common scheme files exist on disk so Metro's\n * resolver can SHA1 them at boot before the first transform runs.\n */\n public async ensureFilesExist(): Promise<void> {\n if (existsSync(this.manifestPath) && existsSync(schemeFilePath(this.cacheDir, 'common'))) {\n // Still trigger the scan so the in-memory union is complete; file\n // bytes may already be authoritative from a prior Metro run.\n await this.ensureProjectScanned()\n return\n }\n await this.writeSchemes()\n }\n\n /**\n * Apply one file's atom-name diff to the in-memory refcount + union.\n * @param file Source file path.\n * @param newAtoms New atom-name set for the file.\n * @param resolvedAtoms Fresh parser output — carries the resolved\n * styles for every entry in `newAtoms`.\n * @param newKeyframes Keyframes this file's atoms reference.\n */\n private applyDiff(\n file: string,\n newAtoms: ReadonlySet<string>,\n resolvedAtoms: ReadonlyMap<string, SchemedStyle>,\n newKeyframes: ReadonlyMap<string, KeyframeBlock>,\n ): void {\n const previous = this.fileAtomSets.get(file) ?? new Set<string>()\n for (const name of previous) {\n if (newAtoms.has(name)) continue\n const count = (this.atomRefCount.get(name) ?? 0) - 1\n if (count <= 0) this.atomRefCount.delete(name)\n else this.atomRefCount.set(name, count)\n // Do NOT remove `name` from `unionAtoms` — the project scan still\n // references it (orphaned atoms get reaped on the next Metro\n // cold start when the scanner re-walks disk).\n }\n for (const name of newAtoms) {\n if (!previous.has(name)) this.atomRefCount.set(name, (this.atomRefCount.get(name) ?? 0) + 1)\n // Only install the resolved style when the atom is new to the\n // union. Replacing an existing entry with a fresh parser-\n // produced object would swap the identity guard the per-atom\n // serialization cache uses and force a re-stringify for every\n // atom on every FR save. CSS edits rebuild the whole builder\n // (via `getRnwindState`) so stale values aren't possible.\n if (!this.unionAtoms.has(name)) {\n const style = resolvedAtoms.get(name)\n if (style) this.unionAtoms.set(name, style)\n }\n }\n this.fileAtomSets.set(file, new Set(newAtoms))\n for (const [name, kf] of newKeyframes) this.unionKeyframes.set(name, kf)\n }\n}\n\nexport { UnionBuilder }\n"],"names":[],"mappings":";;;;;AAMA;AACA,MAAM,iBAAiB,GAAG,YAAY;AAEtC;;;;;;;AAOG;AACH,SAAS,cAAc,CAAC,MAAc,EAAE,OAAe,EAAA;AACrD,IAAA,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE;AACtB,QAAA,IAAI;AACF,YAAA,IAAI,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO;AAAE,gBAAA,OAAO,KAAK;QAC5D;AAAE,QAAA,MAAM;;QAER;IACF;AACA,IAAA,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACpD,IAAA,MAAM,SAAS,GAAG,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,OAAO,CAAC,GAAG,CAAA,CAAA,EAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM;AAClF,IAAA,IAAI;AACF,QAAA,aAAa,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC;AACzC,QAAA,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC;AAC7B,QAAA,OAAO,IAAI;IACb;IAAE,OAAO,KAAK,EAAE;QACd,MAAM,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAClC,QAAA,MAAM,KAAK;IACb;AACF;AAEA;;;;;AAKG;AACH,SAAS,WAAW,CAAC,IAAY,EAAA;IAC/B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;AACrE;AAEA;;;;;;AAMG;AACH,SAAS,SAAS,CAAC,CAAsB,EAAE,CAAsB,EAAA;AAC/D,IAAA,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;AAAE,QAAA,OAAO,KAAK;IACnC,KAAK,MAAM,CAAC,IAAI,CAAC;AAAE,QAAA,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAAE,YAAA,OAAO,KAAK;AAC9C,IAAA,OAAO,IAAI;AACb;AAEA;;;;;AAKG;AACH,SAAS,cAAc,CAAC,QAAgB,EAAE,MAAc,EAAA;IACtD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAA,EAAG,MAAM,CAAA,SAAA,CAAW,CAAC;AAClD;AAEA;;;;;;;;;;;;;;;;AAgBG;AACH,MAAM,YAAY,CAAA;AACC,IAAA,QAAQ;AACR,IAAA,MAAM;AACN,IAAA,UAAU,GAAG,IAAI,GAAG,EAAwB;AAC5C,IAAA,cAAc,GAAG,IAAI,GAAG,EAAyB;;AAEjD,IAAA,cAAc,GAAG,IAAI,GAAG,EAA4B;;AAEpD,IAAA,YAAY,GAAG,IAAI,GAAG,EAAyB;AAChE;;;;;AAKG;AACc,IAAA,aAAa,GAAG,IAAI,GAAG,EAAU;AAClD;;;;;;;AAOG;AACK,IAAA,WAAW,GAAgC,IAAI,GAAG,EAAE;;AAE3C,IAAA,YAAY,GAAG,IAAI,GAAG,EAAuB;;AAE7C,IAAA,YAAY,GAAG,IAAI,GAAG,EAAkB;;AAExC,IAAA,gBAAgB,GAAG,IAAI,GAAG,EAAkB;AAC7D;;;;;;;AAOG;AACc,IAAA,eAAe,GAAwB,IAAI,GAAG,EAAE;;IAEzD,qBAAqB,GAAG,CAAC;;IAEzB,cAAc,GAAG,KAAK;;IAEtB,WAAW,GAAyB,IAAI;IAEhD,WAAA,CAAY,QAAgB,EAAE,MAAsB,EAAA;AAClD,QAAA,IAAI,CAAC,QAAQ,GAAG,QAAQ;AACxB,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;QACpB,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC/C;;AAGA,IAAA,IAAW,YAAY,GAAA;QACrB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACpD;AAEA;;;;;;AAMG;IACI,aAAa,GAAA;QAClB,OAAO,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;IACtC;;AAGA,IAAA,IAAW,gBAAgB,GAAA;QACzB,OAAO,IAAI,CAAC,qBAAqB;IACnC;AAEA;;;;AAIG;AACI,IAAA,UAAU,CAAC,MAAc,EAAA;QAC9B,OAAO,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC9C;AAEA;;;;AAIG;AACI,IAAA,MAAM,oBAAoB,GAAA;QAC/B,IAAI,IAAI,CAAC,cAAc;YAAE;QACzB,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC,WAAW;AAC7C,QAAA,IAAI,CAAC,WAAW,GAAG,CAAC,YAAW;YAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE;YAC/C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK;gBAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;YAC1E,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,SAAS;gBAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YAC5E,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,aAAa;gBAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC;YAC5F,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,WAAW;gBAAE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC;AACpF,YAAA,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW;AACrC,YAAA,IAAI,CAAC,cAAc,GAAG,IAAI;QAC5B,CAAC,GAAG;AACJ,QAAA,IAAI;YACF,MAAM,IAAI,CAAC,WAAW;QACxB;gBAAU;AACR,YAAA,IAAI,CAAC,WAAW,GAAG,IAAI;QACzB;IACF;AAEA;;;;;;;;;;;;AAYG;IACI,MAAM,UAAU,CACrB,IAAY,EACZ,KAAwC,EACxC,SAA6C,EAC7C,QAAA,GAA8B,EAAE,EAAA;AAEhC,QAAA,MAAM,IAAI,CAAC,oBAAoB,EAAE;QACjC,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC;QAClD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;QAC5C,IAAI,QAAQ,IAAI,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE;;;;;;;YAOjD,IAAI,aAAa,GAAG,KAAK;YACzB,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,SAAS,EAAE;gBAClC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,aAAa,GAAG,IAAI;gBACxD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YACnC;AACA,YAAA,OAAO,EAAE,OAAO,EAAE,aAAa,IAAI,YAAY,EAAE;QACnD;QACA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,CAAC;AACpD,QAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE;IAC1B;AAEA;;;;;;AAMG;AACK,IAAA,cAAc,CAAC,QAA2B,EAAA;QAChD,IAAI,KAAK,GAAG,KAAK;AACjB,QAAA,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;AAC9B,YAAA,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE;AACrC,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC;YAC/B,KAAK,GAAG,IAAI;QACd;AACA,QAAA,OAAO,KAAK;IACd;AAEA;;;;;;AAMG;AACI,IAAA,QAAQ,CAAC,IAAY,EAAA;QAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;AAC5C,QAAA,IAAI,CAAC,QAAQ;YAAE;AACf,QAAA,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE;AAC3B,YAAA,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACpD,IAAI,KAAK,IAAI,CAAC;AAAE,gBAAA,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;;gBACzC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;QACzC;AACA,QAAA,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;IAChC;AAEA;;;;;;;AAOG;AACI,IAAA,MAAM,YAAY,GAAA;AACvB,QAAA,MAAM,IAAI,CAAC,oBAAoB,EAAE;AACjC,QAAA,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AAC1F,QAAA,MAAM,MAAM,GAAG,kBAAkB,CAAC,eAAe,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;AACjM,QAAA,IAAI,CAAC,qBAAqB,IAAI,MAAM,CAAC,gBAAgB;AACrD,QAAA,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,GAAG,MAAM;QAEhD,MAAM,OAAO,GAAa,EAAE;AAC5B,QAAA,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE;AAC5D,YAAA,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC;YACrC,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC;AACpD,YAAA,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,SAAS,IAAI,UAAU,CAAC,MAAM,CAAC;gBAAE;AAC3E,YAAA,IAAI,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC;AAAE,gBAAA,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;YACxD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;QAC9C;AAEA,QAAA,MAAM,iBAAiB,GAAG,WAAW,CAAC,cAAc,CAAC;AACrD,QAAA,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC;AAClE,QAAA,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,iBAAiB,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE;AAChG,YAAA,IAAI,cAAc,CAAC,cAAc,EAAE,cAAc,CAAC;AAAE,gBAAA,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;YAC9E,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,YAAY,EAAE,iBAAiB,CAAC;QAC5D;AAEA,QAAA,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE;IACpC;AAEA;;;AAGG;AACI,IAAA,MAAM,gBAAgB,GAAA;AAC3B,QAAA,IAAI,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,EAAE;;;AAGxF,YAAA,MAAM,IAAI,CAAC,oBAAoB,EAAE;YACjC;QACF;AACA,QAAA,MAAM,IAAI,CAAC,YAAY,EAAE;IAC3B;AAEA;;;;;;;AAOG;AACK,IAAA,SAAS,CACf,IAAY,EACZ,QAA6B,EAC7B,aAAgD,EAChD,YAAgD,EAAA;AAEhD,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,EAAU;AACjE,QAAA,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE;AAC3B,YAAA,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE;AACxB,YAAA,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACpD,IAAI,KAAK,IAAI,CAAC;AAAE,gBAAA,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;;gBACzC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;;;;QAIzC;AACA,QAAA,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE;AAC3B,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;;;;;;YAO5F,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;gBAC9B,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;AACrC,gBAAA,IAAI,KAAK;oBAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;YAC7C;QACF;AACA,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC9C,QAAA,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,YAAY;YAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;IAC1E;AACD;;;;"}
@@ -7,10 +7,8 @@
7
7
  * `Scheme` union so `useScheme()` returns the actual names.
8
8
  *
9
9
  * Called once at Metro-config time — overwrite-on-rewrite so the file
10
- * stays in sync with the user's current theme CSS + prefix config.
10
+ * stays in sync with the user's current theme CSS.
11
11
  * @param targetPath Absolute path to write (typically `rnwind-types.d.ts` at project root).
12
12
  * @param schemes Scheme names from the user's `@variant` blocks (empty when none declared).
13
- * @param classNamePrefixes Extra prefixes from the Metro config — merged
14
- * on top of the built-in `'contentContainer'`. Defaults to empty.
15
13
  */
16
- export declare function writeDtsFile(targetPath: string, schemes: readonly string[], classNamePrefixes?: readonly string[]): void;
14
+ export declare function writeDtsFile(targetPath: string, schemes: readonly string[]): void;
@@ -53,23 +53,16 @@ const CONTENT_CONTAINER_INTERFACES = new Set([
53
53
  ]);
54
54
  /**
55
55
  * Build the body of one interface augmentation: `className?: string`
56
- * plus `<prefix>ClassName?: string` for every prefix that applies to
57
- * THIS interface. Emits a single-line body so the file stays easy to
58
- * scan and diff.
56
+ * plus `contentContainerClassName?: string` for the scroll interfaces
57
+ * that natively expose `contentContainerStyle`. Emits a single-line
58
+ * body so the file stays easy to scan and diff.
59
59
  * @param interfaceName Bare interface name (generic parameters stripped).
60
- * @param userPrefixes Extra prefixes from the Metro config — applied to
61
- * every interface the same way `className` is.
62
60
  * @returns Space-separated property declarations.
63
61
  */
64
- function buildInterfaceBody(interfaceName, userPrefixes) {
62
+ function buildInterfaceBody(interfaceName) {
65
63
  const props = ['className?: string'];
66
64
  if (CONTENT_CONTAINER_INTERFACES.has(interfaceName))
67
65
  props.push(`${BUILTIN_PREFIX}ClassName?: string`);
68
- for (const prefix of userPrefixes) {
69
- if (prefix === BUILTIN_PREFIX)
70
- continue;
71
- props.push(`${prefix}ClassName?: string`);
72
- }
73
66
  return props.join('; ');
74
67
  }
75
68
  /**
@@ -81,13 +74,11 @@ function buildInterfaceBody(interfaceName, userPrefixes) {
81
74
  * `Scheme` union so `useScheme()` returns the actual names.
82
75
  *
83
76
  * Called once at Metro-config time — overwrite-on-rewrite so the file
84
- * stays in sync with the user's current theme CSS + prefix config.
77
+ * stays in sync with the user's current theme CSS.
85
78
  * @param targetPath Absolute path to write (typically `rnwind-types.d.ts` at project root).
86
79
  * @param schemes Scheme names from the user's `@variant` blocks (empty when none declared).
87
- * @param classNamePrefixes Extra prefixes from the Metro config — merged
88
- * on top of the built-in `'contentContainer'`. Defaults to empty.
89
80
  */
90
- function writeDtsFile(targetPath, schemes, classNamePrefixes = []) {
81
+ function writeDtsFile(targetPath, schemes) {
91
82
  const lines = [
92
83
  '// Auto-generated by rnwind — do not edit by hand.',
93
84
  '// Overwritten on Metro start / theme CSS change.',
@@ -96,7 +87,7 @@ function writeDtsFile(targetPath, schemes, classNamePrefixes = []) {
96
87
  ];
97
88
  for (const entry of INTERFACES) {
98
89
  const name = typeof entry === 'string' ? entry : entry.name;
99
- const body = buildInterfaceBody(name, classNamePrefixes);
90
+ const body = buildInterfaceBody(name);
100
91
  if (typeof entry === 'string') {
101
92
  lines.push(` interface ${entry} { ${body} }`);
102
93
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"dts.mjs","sources":["../../../../src/metro/dts.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs'\nimport path from 'node:path'\n\n/**\n * React Native component-props interfaces rnwind augments. Adding an\n * optional `className?: string` to each lets TypeScript accept\n * `<View className=\"…\" />` without the user touching types by hand.\n * The generic ones are written with a placeholder so the output type\n * stays parameterised.\n */\nconst INTERFACES: ReadonlyArray<string | { name: string; generic: string }> = [\n 'ViewProps',\n 'TextProps',\n 'ImageProps',\n 'ImageBackgroundProps',\n 'ScrollViewProps',\n 'PressableProps',\n 'ModalProps',\n 'TextInputProps',\n 'TouchableOpacityProps',\n 'TouchableHighlightProps',\n 'TouchableNativeFeedbackProps',\n 'TouchableWithoutFeedbackProps',\n 'SafeAreaViewProps',\n 'KeyboardAvoidingViewProps',\n 'RefreshControlProps',\n 'StatusBarProps',\n 'SwitchProps',\n 'ActivityIndicatorProps',\n 'SectionListProps',\n { name: 'FlatListProps', generic: 'ItemT' },\n { name: 'VirtualizedListProps', generic: 'ItemT' },\n]\n\n/**\n * Built-in prefix wired into every install. Restricted to the interfaces\n * that natively expose `contentContainerStyle` so TypeScript doesn't\n * start accepting `<View contentContainerClassName=\"…\" />` — RN would\n * silently ignore it at runtime and a typed lint is more useful than a\n * permissive one. User prefixes don't come with this restriction; rnwind\n * can't know which component props they target.\n */\nconst BUILTIN_PREFIX = 'contentContainer'\n\n/**\n * Interfaces that expose `contentContainerStyle` in React Native's own\n * types — the set the built-in prefix's `.d.ts` augmentation targets.\n * Everything else stays `className`-only by default.\n */\nconst CONTENT_CONTAINER_INTERFACES: ReadonlySet<string> = new Set([\n 'ScrollViewProps',\n 'FlatListProps',\n 'SectionListProps',\n 'VirtualizedListProps',\n])\n\n/**\n * Build the body of one interface augmentation: `className?: string`\n * plus `<prefix>ClassName?: string` for every prefix that applies to\n * THIS interface. Emits a single-line body so the file stays easy to\n * scan and diff.\n * @param interfaceName Bare interface name (generic parameters stripped).\n * @param userPrefixes Extra prefixes from the Metro config — applied to\n * every interface the same way `className` is.\n * @returns Space-separated property declarations.\n */\nfunction buildInterfaceBody(interfaceName: string, userPrefixes: readonly string[]): string {\n const props = ['className?: string']\n if (CONTENT_CONTAINER_INTERFACES.has(interfaceName)) props.push(`${BUILTIN_PREFIX}ClassName?: string`)\n for (const prefix of userPrefixes) {\n if (prefix === BUILTIN_PREFIX) continue\n props.push(`${prefix}ClassName?: string`)\n }\n return props.join('; ')\n}\n\n/**\n * Write the rnwind TypeScript declaration file. The generated `.d.ts`\n * declares a `rnwind` module augmentation for `react-native`'s\n * component props — every interface gets an optional `className?:\n * string` plus `<prefix>ClassName?: string` for each active prefix.\n * Runtime-rendered schemes (`@variant` blocks) are reflected in the\n * `Scheme` union so `useScheme()` returns the actual names.\n *\n * Called once at Metro-config time — overwrite-on-rewrite so the file\n * stays in sync with the user's current theme CSS + prefix config.\n * @param targetPath Absolute path to write (typically `rnwind-types.d.ts` at project root).\n * @param schemes Scheme names from the user's `@variant` blocks (empty when none declared).\n * @param classNamePrefixes Extra prefixes from the Metro config — merged\n * on top of the built-in `'contentContainer'`. Defaults to empty.\n */\nexport function writeDtsFile(\n targetPath: string,\n schemes: readonly string[],\n classNamePrefixes: readonly string[] = [],\n): void {\n const lines: string[] = [\n '// Auto-generated by rnwind — do not edit by hand.',\n '// Overwritten on Metro start / theme CSS change.',\n '',\n `declare module 'react-native' {`,\n ]\n for (const entry of INTERFACES) {\n const name = typeof entry === 'string' ? entry : entry.name\n const body = buildInterfaceBody(name, classNamePrefixes)\n if (typeof entry === 'string') {\n lines.push(` interface ${entry} { ${body} }`)\n continue\n }\n lines.push(` interface ${entry.name}<${entry.generic}> { ${body} }`)\n }\n lines.push('}', '')\n if (schemes.length > 0) {\n lines.push(`declare module 'rnwind' {`, ` export interface RnwindConfig {`)\n const schemeLiterals = schemes.map((s) => `'${s}'`).join(', ')\n lines.push(` themes: readonly [${schemeLiterals}]`, ` }`, '}', '')\n }\n // The `export {}` is mandatory — without at least one top-level\n // import/export, TypeScript treats this file as a SCRIPT and the\n // `declare module 'react-native'` block above becomes a complete\n // *replacement* declaration (hiding the real RN exports like\n // `Pressable`, `useColorScheme`, etc.). With `export {}` the file\n // becomes a module and the `declare module` blocks are interpreted as\n // *augmentations* — which is what we want.\n lines.push('export {}', '')\n mkdirSync(path.dirname(targetPath), { recursive: true })\n writeFileSync(targetPath, lines.join('\\n'), 'utf8')\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dts.mjs","sources":["../../../../src/metro/dts.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs'\nimport path from 'node:path'\n\n/**\n * React Native component-props interfaces rnwind augments. Adding an\n * optional `className?: string` to each lets TypeScript accept\n * `<View className=\"…\" />` without the user touching types by hand.\n * The generic ones are written with a placeholder so the output type\n * stays parameterised.\n */\nconst INTERFACES: ReadonlyArray<string | { name: string; generic: string }> = [\n 'ViewProps',\n 'TextProps',\n 'ImageProps',\n 'ImageBackgroundProps',\n 'ScrollViewProps',\n 'PressableProps',\n 'ModalProps',\n 'TextInputProps',\n 'TouchableOpacityProps',\n 'TouchableHighlightProps',\n 'TouchableNativeFeedbackProps',\n 'TouchableWithoutFeedbackProps',\n 'SafeAreaViewProps',\n 'KeyboardAvoidingViewProps',\n 'RefreshControlProps',\n 'StatusBarProps',\n 'SwitchProps',\n 'ActivityIndicatorProps',\n 'SectionListProps',\n { name: 'FlatListProps', generic: 'ItemT' },\n { name: 'VirtualizedListProps', generic: 'ItemT' },\n]\n\n/**\n * Built-in prefix wired into every install. Restricted to the interfaces\n * that natively expose `contentContainerStyle` so TypeScript doesn't\n * start accepting `<View contentContainerClassName=\"…\" />` — RN would\n * silently ignore it at runtime and a typed lint is more useful than a\n * permissive one. User prefixes don't come with this restriction; rnwind\n * can't know which component props they target.\n */\nconst BUILTIN_PREFIX = 'contentContainer'\n\n/**\n * Interfaces that expose `contentContainerStyle` in React Native's own\n * types — the set the built-in prefix's `.d.ts` augmentation targets.\n * Everything else stays `className`-only by default.\n */\nconst CONTENT_CONTAINER_INTERFACES: ReadonlySet<string> = new Set([\n 'ScrollViewProps',\n 'FlatListProps',\n 'SectionListProps',\n 'VirtualizedListProps',\n])\n\n/**\n * Build the body of one interface augmentation: `className?: string`\n * plus `contentContainerClassName?: string` for the scroll interfaces\n * that natively expose `contentContainerStyle`. Emits a single-line\n * body so the file stays easy to scan and diff.\n * @param interfaceName Bare interface name (generic parameters stripped).\n * @returns Space-separated property declarations.\n */\nfunction buildInterfaceBody(interfaceName: string): string {\n const props = ['className?: string']\n if (CONTENT_CONTAINER_INTERFACES.has(interfaceName)) props.push(`${BUILTIN_PREFIX}ClassName?: string`)\n return props.join('; ')\n}\n\n/**\n * Write the rnwind TypeScript declaration file. The generated `.d.ts`\n * declares a `rnwind` module augmentation for `react-native`'s\n * component props — every interface gets an optional `className?:\n * string` plus `<prefix>ClassName?: string` for each active prefix.\n * Runtime-rendered schemes (`@variant` blocks) are reflected in the\n * `Scheme` union so `useScheme()` returns the actual names.\n *\n * Called once at Metro-config time — overwrite-on-rewrite so the file\n * stays in sync with the user's current theme CSS.\n * @param targetPath Absolute path to write (typically `rnwind-types.d.ts` at project root).\n * @param schemes Scheme names from the user's `@variant` blocks (empty when none declared).\n */\nexport function writeDtsFile(targetPath: string, schemes: readonly string[]): void {\n const lines: string[] = [\n '// Auto-generated by rnwind — do not edit by hand.',\n '// Overwritten on Metro start / theme CSS change.',\n '',\n `declare module 'react-native' {`,\n ]\n for (const entry of INTERFACES) {\n const name = typeof entry === 'string' ? entry : entry.name\n const body = buildInterfaceBody(name)\n if (typeof entry === 'string') {\n lines.push(` interface ${entry} { ${body} }`)\n continue\n }\n lines.push(` interface ${entry.name}<${entry.generic}> { ${body} }`)\n }\n lines.push('}', '')\n if (schemes.length > 0) {\n lines.push(`declare module 'rnwind' {`, ` export interface RnwindConfig {`)\n const schemeLiterals = schemes.map((s) => `'${s}'`).join(', ')\n lines.push(` themes: readonly [${schemeLiterals}]`, ` }`, '}', '')\n }\n // The `export {}` is mandatory — without at least one top-level\n // import/export, TypeScript treats this file as a SCRIPT and the\n // `declare module 'react-native'` block above becomes a complete\n // *replacement* declaration (hiding the real RN exports like\n // `Pressable`, `useColorScheme`, etc.). With `export {}` the file\n // becomes a module and the `declare module` blocks are interpreted as\n // *augmentations* — which is what we want.\n lines.push('export {}', '')\n mkdirSync(path.dirname(targetPath), { recursive: true })\n writeFileSync(targetPath, lines.join('\\n'), 'utf8')\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { UnionBuilder } from '../core/style-builder';
2
2
  import { TailwindParser } from '../core/parser';
3
+ import { buildWrapModules } from './wrap-imports';
3
4
  /**
4
5
  * Worker-local state. Lazy-initialised on first access so files that
5
6
  * bypass the transform don't pay for construction.
@@ -17,34 +18,16 @@ export interface RnwindState {
17
18
  * can rebuild the same state without re-reading the Metro config.
18
19
  * @param cssEntryFile Absolute path to the user's theme CSS.
19
20
  * @param cacheDir Absolute path to the cache dir (`.rnwind`).
20
- * @param watchFolders
21
- * @param classNamePrefixes Extra JSX prop-name prefixes to rewrite.
22
- * @param hostSources
23
- * @param hostComponents
21
+ * @param watchFolders Monorepo watch folders to scan for atoms.
22
+ * @param wrapModules Extra modules whose component exports get `wrap()`-ed.
24
23
  */
25
- export declare function configureRnwindState(cssEntryFile: string, cacheDir: string, watchFolders?: readonly string[], classNamePrefixes?: readonly string[], hostSources?: readonly string[], hostComponents?: readonly string[]): void;
24
+ export declare function configureRnwindState(cssEntryFile: string, cacheDir: string, watchFolders?: readonly string[], wrapModules?: readonly string[]): void;
26
25
  /**
27
- * Read the caller-configured extra className prefixes out of the
28
- * worker environment. Returns an empty array when unset — the
29
- * transformer applies the built-in `contentContainer` default on top
30
- * either way.
31
- * @returns User-supplied extra prefixes.
26
+ * Effective module → wrap-policy map: the built-in defaults merged with
27
+ * any extra modules the Metro config supplied.
28
+ * @returns Module policy map the import-rewrite consults.
32
29
  */
33
- export declare function getClassNamePrefixes(): readonly string[];
34
- /**
35
- * Read the caller-configured extra host module sources out of the
36
- * worker environment. Empty array when unset — the transformer applies
37
- * its built-in default list on top either way.
38
- * @returns User-supplied extra host sources.
39
- */
40
- export declare function getHostSources(): readonly string[];
41
- /**
42
- * Read the caller-configured extra host JSX tag names out of the worker
43
- * environment. Verbatim names — may include `.` for member expressions
44
- * like `'Animated.View'`.
45
- * @returns User-supplied extra host component names.
46
- */
47
- export declare function getHostComponents(): readonly string[];
30
+ export declare function getWrapModules(): ReturnType<typeof buildWrapModules>;
48
31
  /**
49
32
  * Fetch (or build) the worker-local rnwind state. Re-reads the theme
50
33
  * CSS hash on every call: if the user edited `global.css` while Metro