rnwind 0.0.2 → 0.0.4

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 (87) hide show
  1. package/lib/cjs/core/parser/color.cjs +53 -24
  2. package/lib/cjs/core/parser/color.cjs.map +1 -1
  3. package/lib/cjs/core/parser/layout-dispatcher.cjs +20 -0
  4. package/lib/cjs/core/parser/layout-dispatcher.cjs.map +1 -1
  5. package/lib/cjs/core/parser/length.cjs +20 -6
  6. package/lib/cjs/core/parser/length.cjs.map +1 -1
  7. package/lib/cjs/core/parser/length.d.ts +6 -3
  8. package/lib/cjs/core/parser/shorthand.cjs +37 -5
  9. package/lib/cjs/core/parser/shorthand.cjs.map +1 -1
  10. package/lib/cjs/core/parser/shorthand.d.ts +11 -5
  11. package/lib/cjs/core/parser/theme-vars.cjs +53 -0
  12. package/lib/cjs/core/parser/theme-vars.cjs.map +1 -1
  13. package/lib/cjs/core/parser/theme-vars.d.ts +21 -0
  14. package/lib/cjs/core/parser/tokens.cjs +183 -1
  15. package/lib/cjs/core/parser/tokens.cjs.map +1 -1
  16. package/lib/cjs/core/parser/tw-parser.cjs +140 -27
  17. package/lib/cjs/core/parser/tw-parser.cjs.map +1 -1
  18. package/lib/cjs/core/parser/tw-parser.d.ts +21 -5
  19. package/lib/cjs/core/parser/typography-dispatcher.cjs +16 -1
  20. package/lib/cjs/core/parser/typography-dispatcher.cjs.map +1 -1
  21. package/lib/cjs/core/style-builder/build-style.cjs +73 -26
  22. package/lib/cjs/core/style-builder/build-style.cjs.map +1 -1
  23. package/lib/cjs/metro/css-imports.cjs +81 -0
  24. package/lib/cjs/metro/css-imports.cjs.map +1 -0
  25. package/lib/cjs/metro/css-imports.d.ts +8 -0
  26. package/lib/cjs/metro/state.cjs +60 -10
  27. package/lib/cjs/metro/state.cjs.map +1 -1
  28. package/lib/cjs/metro/state.d.ts +17 -1
  29. package/lib/cjs/metro/transform-ast.cjs +238 -21
  30. package/lib/cjs/metro/transform-ast.cjs.map +1 -1
  31. package/lib/cjs/metro/transform-ast.d.ts +15 -0
  32. package/lib/cjs/metro/transformer.cjs +29 -2
  33. package/lib/cjs/metro/transformer.cjs.map +1 -1
  34. package/lib/cjs/metro/with-config.cjs +1 -1
  35. package/lib/cjs/metro/with-config.cjs.map +1 -1
  36. package/lib/cjs/metro/with-config.d.ts +22 -0
  37. package/lib/esm/core/parser/color.mjs +53 -24
  38. package/lib/esm/core/parser/color.mjs.map +1 -1
  39. package/lib/esm/core/parser/layout-dispatcher.mjs +20 -0
  40. package/lib/esm/core/parser/layout-dispatcher.mjs.map +1 -1
  41. package/lib/esm/core/parser/length.d.ts +6 -3
  42. package/lib/esm/core/parser/length.mjs +20 -6
  43. package/lib/esm/core/parser/length.mjs.map +1 -1
  44. package/lib/esm/core/parser/shorthand.d.ts +11 -5
  45. package/lib/esm/core/parser/shorthand.mjs +37 -5
  46. package/lib/esm/core/parser/shorthand.mjs.map +1 -1
  47. package/lib/esm/core/parser/theme-vars.d.ts +21 -0
  48. package/lib/esm/core/parser/theme-vars.mjs +53 -1
  49. package/lib/esm/core/parser/theme-vars.mjs.map +1 -1
  50. package/lib/esm/core/parser/tokens.mjs +183 -1
  51. package/lib/esm/core/parser/tokens.mjs.map +1 -1
  52. package/lib/esm/core/parser/tw-parser.d.ts +21 -5
  53. package/lib/esm/core/parser/tw-parser.mjs +141 -28
  54. package/lib/esm/core/parser/tw-parser.mjs.map +1 -1
  55. package/lib/esm/core/parser/typography-dispatcher.mjs +16 -1
  56. package/lib/esm/core/parser/typography-dispatcher.mjs.map +1 -1
  57. package/lib/esm/core/style-builder/build-style.mjs +73 -26
  58. package/lib/esm/core/style-builder/build-style.mjs.map +1 -1
  59. package/lib/esm/metro/css-imports.d.ts +8 -0
  60. package/lib/esm/metro/css-imports.mjs +79 -0
  61. package/lib/esm/metro/css-imports.mjs.map +1 -0
  62. package/lib/esm/metro/state.d.ts +17 -1
  63. package/lib/esm/metro/state.mjs +60 -12
  64. package/lib/esm/metro/state.mjs.map +1 -1
  65. package/lib/esm/metro/transform-ast.d.ts +15 -0
  66. package/lib/esm/metro/transform-ast.mjs +238 -21
  67. package/lib/esm/metro/transform-ast.mjs.map +1 -1
  68. package/lib/esm/metro/transformer.mjs +30 -3
  69. package/lib/esm/metro/transformer.mjs.map +1 -1
  70. package/lib/esm/metro/with-config.d.ts +22 -0
  71. package/lib/esm/metro/with-config.mjs +1 -1
  72. package/lib/esm/metro/with-config.mjs.map +1 -1
  73. package/package.json +2 -1
  74. package/src/core/parser/color.ts +52 -18
  75. package/src/core/parser/layout-dispatcher.ts +19 -0
  76. package/src/core/parser/length.ts +20 -6
  77. package/src/core/parser/shorthand.ts +35 -5
  78. package/src/core/parser/theme-vars.ts +53 -0
  79. package/src/core/parser/tokens.ts +171 -1
  80. package/src/core/parser/tw-parser.ts +147 -28
  81. package/src/core/parser/typography-dispatcher.ts +15 -1
  82. package/src/core/style-builder/build-style.ts +84 -26
  83. package/src/metro/css-imports.ts +75 -0
  84. package/src/metro/state.ts +58 -10
  85. package/src/metro/transform-ast.ts +249 -18
  86. package/src/metro/transformer.ts +28 -3
  87. package/src/metro/with-config.ts +23 -1
@@ -55,6 +55,21 @@ function letterSpacingToEntries(value) {
55
55
  return [];
56
56
  return [['letterSpacing', unit === 'px' ? px : px * 16]];
57
57
  }
58
+ /**
59
+ * Lower a CSS `text-align` keyword to one RN's `textAlign` accepts. RN
60
+ * has no logical `start`/`end`, so map them to physical sides (LTR
61
+ * default); every other keyword (left/right/center/justify/auto) is
62
+ * already valid and passes through.
63
+ * @param align CSS text-align keyword.
64
+ * @returns RN-valid textAlign keyword.
65
+ */
66
+ function physicalTextAlign(align) {
67
+ if (align === 'start')
68
+ return 'left';
69
+ if (align === 'end')
70
+ return 'right';
71
+ return align;
72
+ }
58
73
  /**
59
74
  * Dispatch typography declarations rnwind cares about (text-align,
60
75
  * text-transform, text-decoration-line, line-height, letter-spacing,
@@ -66,7 +81,7 @@ function letterSpacingToEntries(value) {
66
81
  function dispatchTypographyDeclaration(decl) {
67
82
  switch (decl.property) {
68
83
  case 'text-align': {
69
- return [['textAlign', decl.value]];
84
+ return [['textAlign', physicalTextAlign(String(decl.value))]];
70
85
  }
71
86
  case 'text-transform': {
72
87
  return [['textTransform', decl.value.case ?? 'none']];
@@ -1 +1 @@
1
- {"version":3,"file":"typography-dispatcher.cjs","sources":["../../../../../src/core/parser/typography-dispatcher.ts"],"sourcesContent":["import type { Declaration as LcDeclaration } from 'lightningcss'\nimport { lineHeightToEntries } from './typography'\nimport type { RNEntry } from './types'\n\n/**\n * Build the RN `textDecorationLine` entry — string identity for the\n * single-line cases, joined-string for the array shape.\n * @param value Typed text-decoration-line.\n * @returns Single-entry list with `textDecorationLine`.\n */\nfunction textDecorationLineToEntries(value: LcDeclaration['value']): readonly RNEntry[] {\n if (value === 'none') return [['textDecorationLine', 'none']]\n if (typeof value === 'string') return [['textDecorationLine', value]]\n if (Array.isArray(value)) return [['textDecorationLine', value.join(' ')]]\n return []\n}\n\n/**\n * Build the RN `aspectRatio` entry from lightningcss's typed value.\n * Drops `auto` (no RN equivalent).\n * @param value Typed aspect-ratio value.\n * @param value.auto Whether the value resolved to `auto`.\n * @param value.ratio Numeric `[width, height]` ratio (or null/undefined).\n * @returns Single-entry list or empty.\n */\nfunction aspectRatioToEntries(value: { auto?: boolean; ratio?: readonly [number, number] | null }): readonly RNEntry[] {\n if (value.auto) return []\n if (!value.ratio) return []\n const [w, h] = value.ratio\n if (h === 0) return []\n return [['aspectRatio', w / h]]\n}\n\n/**\n * Build the RN `letterSpacing` entry. RN expects pixel numbers; rem\n * lengths are scaled to px (16-px base).\n * @param value Typed letter-spacing value.\n * @returns Single-entry list or empty.\n */\nfunction letterSpacingToEntries(value: LcDeclaration['value']): readonly RNEntry[] {\n if (typeof value !== 'object') return []\n const tagged = value as { type?: string; value?: { type?: string; value?: { unit?: string; value?: number } } }\n if (tagged.type === 'normal') return [['letterSpacing', 0]]\n const inner = tagged.value\n if (inner?.type !== 'value' || !inner.value) return []\n const { unit, value: px } = inner.value\n if (typeof px !== 'number') return []\n return [['letterSpacing', unit === 'px' ? px : px * 16]]\n}\n\n/**\n * Dispatch typography declarations rnwind cares about (text-align,\n * text-transform, text-decoration-line, line-height, letter-spacing,\n * aspect-ratio). Returns null when the property isn't one of these so\n * the caller can fall through to its main switch.\n * @param decl One lightningcss declaration.\n * @returns RN entries when the property matched, else `null`.\n */\nexport function dispatchTypographyDeclaration(decl: LcDeclaration): readonly RNEntry[] | null {\n switch (decl.property) {\n case 'text-align': {\n return [['textAlign', decl.value]]\n }\n case 'text-transform': {\n return [['textTransform', decl.value.case ?? 'none']]\n }\n case 'text-decoration-line': {\n return textDecorationLineToEntries(decl.value)\n }\n case 'aspect-ratio': {\n return aspectRatioToEntries(decl.value)\n }\n case 'line-height': {\n return lineHeightToEntries(decl.value)\n }\n case 'letter-spacing': {\n return letterSpacingToEntries(decl.value)\n }\n default: {\n return null\n }\n }\n}\n"],"names":["lineHeightToEntries"],"mappings":";;;;AAIA;;;;;AAKG;AACH,SAAS,2BAA2B,CAAC,KAA6B,EAAA;IAChE,IAAI,KAAK,KAAK,MAAM;AAAE,QAAA,OAAO,CAAC,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;IAC7D,IAAI,OAAO,KAAK,KAAK,QAAQ;AAAE,QAAA,OAAO,CAAC,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;AACrE,IAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AAAE,QAAA,OAAO,CAAC,CAAC,oBAAoB,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1E,IAAA,OAAO,EAAE;AACX;AAEA;;;;;;;AAOG;AACH,SAAS,oBAAoB,CAAC,KAAmE,EAAA;IAC/F,IAAI,KAAK,CAAC,IAAI;AAAE,QAAA,OAAO,EAAE;IACzB,IAAI,CAAC,KAAK,CAAC,KAAK;AAAE,QAAA,OAAO,EAAE;IAC3B,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK;IAC1B,IAAI,CAAC,KAAK,CAAC;AAAE,QAAA,OAAO,EAAE;IACtB,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;AACjC;AAEA;;;;;AAKG;AACH,SAAS,sBAAsB,CAAC,KAA6B,EAAA;IAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ;AAAE,QAAA,OAAO,EAAE;IACxC,MAAM,MAAM,GAAG,KAAgG;AAC/G,IAAA,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ;AAAE,QAAA,OAAO,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;AAC3D,IAAA,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK;IAC1B,IAAI,KAAK,EAAE,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK;AAAE,QAAA,OAAO,EAAE;IACtD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,KAAK;IACvC,IAAI,OAAO,EAAE,KAAK,QAAQ;AAAE,QAAA,OAAO,EAAE;AACrC,IAAA,OAAO,CAAC,CAAC,eAAe,EAAE,IAAI,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;AAC1D;AAEA;;;;;;;AAOG;AACG,SAAU,6BAA6B,CAAC,IAAmB,EAAA;AAC/D,IAAA,QAAQ,IAAI,CAAC,QAAQ;QACnB,KAAK,YAAY,EAAE;YACjB,OAAO,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACpC;QACA,KAAK,gBAAgB,EAAE;AACrB,YAAA,OAAO,CAAC,CAAC,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC;QACvD;QACA,KAAK,sBAAsB,EAAE;AAC3B,YAAA,OAAO,2BAA2B,CAAC,IAAI,CAAC,KAAK,CAAC;QAChD;QACA,KAAK,cAAc,EAAE;AACnB,YAAA,OAAO,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC;QACzC;QACA,KAAK,aAAa,EAAE;AAClB,YAAA,OAAOA,8BAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;QACxC;QACA,KAAK,gBAAgB,EAAE;AACrB,YAAA,OAAO,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC;QAC3C;QACA,SAAS;AACP,YAAA,OAAO,IAAI;QACb;;AAEJ;;;;"}
1
+ {"version":3,"file":"typography-dispatcher.cjs","sources":["../../../../../src/core/parser/typography-dispatcher.ts"],"sourcesContent":["import type { Declaration as LcDeclaration } from 'lightningcss'\nimport { lineHeightToEntries } from './typography'\nimport type { RNEntry } from './types'\n\n/**\n * Build the RN `textDecorationLine` entry — string identity for the\n * single-line cases, joined-string for the array shape.\n * @param value Typed text-decoration-line.\n * @returns Single-entry list with `textDecorationLine`.\n */\nfunction textDecorationLineToEntries(value: LcDeclaration['value']): readonly RNEntry[] {\n if (value === 'none') return [['textDecorationLine', 'none']]\n if (typeof value === 'string') return [['textDecorationLine', value]]\n if (Array.isArray(value)) return [['textDecorationLine', value.join(' ')]]\n return []\n}\n\n/**\n * Build the RN `aspectRatio` entry from lightningcss's typed value.\n * Drops `auto` (no RN equivalent).\n * @param value Typed aspect-ratio value.\n * @param value.auto Whether the value resolved to `auto`.\n * @param value.ratio Numeric `[width, height]` ratio (or null/undefined).\n * @returns Single-entry list or empty.\n */\nfunction aspectRatioToEntries(value: { auto?: boolean; ratio?: readonly [number, number] | null }): readonly RNEntry[] {\n if (value.auto) return []\n if (!value.ratio) return []\n const [w, h] = value.ratio\n if (h === 0) return []\n return [['aspectRatio', w / h]]\n}\n\n/**\n * Build the RN `letterSpacing` entry. RN expects pixel numbers; rem\n * lengths are scaled to px (16-px base).\n * @param value Typed letter-spacing value.\n * @returns Single-entry list or empty.\n */\nfunction letterSpacingToEntries(value: LcDeclaration['value']): readonly RNEntry[] {\n if (typeof value !== 'object') return []\n const tagged = value as { type?: string; value?: { type?: string; value?: { unit?: string; value?: number } } }\n if (tagged.type === 'normal') return [['letterSpacing', 0]]\n const inner = tagged.value\n if (inner?.type !== 'value' || !inner.value) return []\n const { unit, value: px } = inner.value\n if (typeof px !== 'number') return []\n return [['letterSpacing', unit === 'px' ? px : px * 16]]\n}\n\n/**\n * Lower a CSS `text-align` keyword to one RN's `textAlign` accepts. RN\n * has no logical `start`/`end`, so map them to physical sides (LTR\n * default); every other keyword (left/right/center/justify/auto) is\n * already valid and passes through.\n * @param align CSS text-align keyword.\n * @returns RN-valid textAlign keyword.\n */\nfunction physicalTextAlign(align: string): string {\n if (align === 'start') return 'left'\n if (align === 'end') return 'right'\n return align\n}\n\n/**\n * Dispatch typography declarations rnwind cares about (text-align,\n * text-transform, text-decoration-line, line-height, letter-spacing,\n * aspect-ratio). Returns null when the property isn't one of these so\n * the caller can fall through to its main switch.\n * @param decl One lightningcss declaration.\n * @returns RN entries when the property matched, else `null`.\n */\nexport function dispatchTypographyDeclaration(decl: LcDeclaration): readonly RNEntry[] | null {\n switch (decl.property) {\n case 'text-align': {\n return [['textAlign', physicalTextAlign(String(decl.value))]]\n }\n case 'text-transform': {\n return [['textTransform', decl.value.case ?? 'none']]\n }\n case 'text-decoration-line': {\n return textDecorationLineToEntries(decl.value)\n }\n case 'aspect-ratio': {\n return aspectRatioToEntries(decl.value)\n }\n case 'line-height': {\n return lineHeightToEntries(decl.value)\n }\n case 'letter-spacing': {\n return letterSpacingToEntries(decl.value)\n }\n default: {\n return null\n }\n }\n}\n"],"names":["lineHeightToEntries"],"mappings":"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"}
@@ -278,25 +278,75 @@ function renderManifest(variants, breakpoints) {
278
278
  return lines.join('\n');
279
279
  }
280
280
  /**
281
- * Serialize one atom's canonical + variant-diff entries, honouring
282
- * the per-atom cache. Returns the number of cache MISSES this atom
283
- * incurred (0 when canonical was cached AND every needed variant was
284
- * cached; 1 when anything had to be re-stringified). Split out of
285
- * `buildSchemeSources` to keep that function under the repo's cognitive
286
- * complexity budget.
281
+ * Pre-serialize every non-empty variant value, reusing the per-atom
282
+ * cache where present. Result drives both the scheme-uniform check
283
+ * AND the per-variant emission loop downstream.
284
+ * @param atom Atom name.
285
+ * @param schemed Parser-produced schemed bucket.
286
+ * @param variants Variant scheme names in deterministic order.
287
+ * @param keyframes Keyframes available to inline.
288
+ * @param cached Cached entry for this atom (when ref-stable).
289
+ * @returns variantName → serialized text.
290
+ */
291
+ function buildVariantTexts(atom, schemed, variants, keyframes, cached) {
292
+ const out = new Map();
293
+ for (const variant of variants) {
294
+ const own = schemed[variant];
295
+ if (!isNonEmptyStyle(own))
296
+ continue;
297
+ const text = cached?.variants.get(variant) ?? prepareAtomValue(atom, own, keyframes);
298
+ out.set(variant, text);
299
+ }
300
+ return out;
301
+ }
302
+ /**
303
+ * Decide whether a (no-base) atom should be promoted to common because
304
+ * every declared variant resolves to the same value. This is the
305
+ * scheme-uniform case: `flex`, `p-4`, `absolute` all carry no theme
306
+ * variables, so Phase-1 fills every variant bucket identically and
307
+ * leaves `base` empty — without this collapse they'd be duplicated
308
+ * across every scheme file.
287
309
  *
288
- * Two paths gated on whether the parser produced a non-empty `base`
289
- * bucket:
310
+ * The variant-prefix check is what keeps a real scheme-gated atom
311
+ * (`dark:bg-indigo-800`) out of common in a single-variant project
312
+ * (where its 1 bucket would otherwise look "uniform" by definition).
313
+ * @param atom Atom name (checked for `<variant>:` prefix).
314
+ * @param variants Declared variant scheme names.
315
+ * @param variantTexts Serialized variant values.
316
+ * @param canonicalText Serialized canonical (common) value.
317
+ * @returns Whether the atom is uniform across every declared variant.
318
+ */
319
+ function isSchemeUniform(atom, variants, variantTexts, canonicalText) {
320
+ if (variants.length === 0 || variantTexts.size !== variants.length)
321
+ return false;
322
+ if (variants.some((variant) => atom.startsWith(`${variant}:`)))
323
+ return false;
324
+ for (const text of variantTexts.values()) {
325
+ if (text !== canonicalText)
326
+ return false;
327
+ }
328
+ return true;
329
+ }
330
+ /**
331
+ * Serialize one atom's canonical + variant-diff entries, honouring the
332
+ * per-atom cache. Returns the number of cache MISSES this atom incurred
333
+ * (0 when canonical was cached AND every needed variant was cached;
334
+ * 1 when anything had to be re-stringified).
335
+ *
336
+ * Three paths gated on whether the parser produced a non-empty `base`
337
+ * bucket and whether the variants converge:
290
338
  * - **Themed atom (base present)**: canonical goes to `common`, each
291
339
  * variant whose own value diverges from canonical writes the diff
292
- * into its own scheme file. `lookupAtom` then finds the variant's
340
+ * into its own scheme file. `lookupAtom` finds the variant's
293
341
  * override or falls through to common.
294
- * - **Scheme-gated atom (base empty)**: the atom only matches when a
295
- * specific scheme is active (Tailwind `light:` / `dark:` / `brand:`
296
- * selectors). Skipping `common` here is essential registering it
297
- * would let the lookup fall through under non-matching schemes and
298
- * leak the variant style into every scheme. Each populated variant
299
- * bucket writes the value into its own scheme file directly.
342
+ * - **Scheme-uniform atom (base empty, every variant identical)**:
343
+ * promoted to `common` once the parser's Phase-1 fills every
344
+ * variant bucket with the same value for utilities like `flex` /
345
+ * `p-4` / `absolute` that don't reference theme variables.
346
+ * - **Scheme-gated atom (base empty, prefixed name like `dark:foo`,
347
+ * or variants diverge)**: each populated variant writes the value
348
+ * into its own scheme file directly; common stays empty so the
349
+ * runtime fallback can't leak the variant style into other schemes.
300
350
  * @param atom Atom name.
301
351
  * @param schemed Parser-produced schemed bucket for the atom.
302
352
  * @param canonical Canonical RN style for `common`.
@@ -311,25 +361,22 @@ function collectAtomEntries(atom, schemed, canonical, variants, keyframes, commo
311
361
  const cached = cache?.get(atom);
312
362
  const hit = cached?.styleRef === schemed;
313
363
  const baseEntry = schemed[BASE_SCHEME];
314
- const isSchemeGated = !isNonEmptyStyle(baseEntry);
364
+ const hasBase = isNonEmptyStyle(baseEntry);
315
365
  const canonicalText = hit ? cached.canonical : prepareAtomValue(atom, canonical, keyframes);
316
- if (!isSchemeGated)
366
+ const variantTexts = buildVariantTexts(atom, schemed, variants, keyframes, hit ? cached : undefined);
367
+ const goesToCommon = hasBase || isSchemeUniform(atom, variants, variantTexts, canonicalText);
368
+ if (goesToCommon)
317
369
  commonEntries.push([atom, canonicalText]);
318
370
  const entry = hit
319
371
  ? cached
320
- : { styleRef: schemed, canonical: canonicalText, variants: new Map() };
372
+ : { styleRef: schemed, canonical: canonicalText, variants: new Map(variantTexts) };
321
373
  if (!hit)
322
374
  cache?.set(atom, entry);
323
375
  for (const variant of variants) {
324
- const own = schemed[variant];
325
- if (!isNonEmptyStyle(own))
376
+ const ownText = variantTexts.get(variant);
377
+ if (ownText === undefined)
326
378
  continue;
327
- let ownText = entry.variants.get(variant);
328
- if (ownText === undefined) {
329
- ownText = prepareAtomValue(atom, own, keyframes);
330
- entry.variants.set(variant, ownText);
331
- }
332
- if (!isSchemeGated && ownText === canonicalText)
379
+ if (goesToCommon && ownText === canonicalText)
333
380
  continue;
334
381
  variantEntries[variant].push([atom, ownText]);
335
382
  }
@@ -1 +1 @@
1
- {"version":3,"file":"build-style.cjs","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 * Serialize one atom's canonical + variant-diff entries, honouring\n * the per-atom cache. Returns the number of cache MISSES this atom\n * incurred (0 when canonical was cached AND every needed variant was\n * cached; 1 when anything had to be re-stringified). Split out of\n * `buildSchemeSources` to keep that function under the repo's cognitive\n * complexity budget.\n *\n * Two paths gated on whether the parser produced a non-empty `base`\n * bucket:\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` then finds the variant's\n * override or falls through to common.\n * - **Scheme-gated atom (base empty)**: the atom only matches when a\n * specific scheme is active (Tailwind `light:` / `dark:` / `brand:`\n * selectors). Skipping `common` here is essential — registering it\n * would let the lookup fall through under non-matching schemes and\n * leak the variant style into every scheme. Each populated variant\n * bucket writes the value into its own scheme file directly.\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 isSchemeGated = !isNonEmptyStyle(baseEntry)\n const canonicalText = hit ? cached.canonical : prepareAtomValue(atom, canonical, keyframes)\n if (!isSchemeGated) commonEntries.push([atom, canonicalText])\n const entry: AtomSerializedEntry = hit\n ? cached\n : { styleRef: schemed, canonical: canonicalText, variants: new Map<string, string>() }\n if (!hit) cache?.set(atom, entry)\n\n for (const variant of variants) {\n const own = (schemed as Readonly<Record<string, RNStyle>>)[variant]\n if (!isNonEmptyStyle(own)) continue\n let ownText = entry.variants.get(variant)\n if (ownText === undefined) {\n ownText = prepareAtomValue(atom, own, keyframes)\n entry.variants.set(variant, ownText)\n }\n if (!isSchemeGated && 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.cjs","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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"}
@@ -0,0 +1,81 @@
1
+ 'use strict';
2
+
3
+ var node_module = require('node:module');
4
+ var node_fs = require('node:fs');
5
+
6
+ /**
7
+ * Inline `@import` resolution for the theme entry CSS.
8
+ *
9
+ * rnwind's scheme extractors (`extractThemeVars`, `extractSchemeAliases`,
10
+ * `extractCustomVariantSchemes`) are plain text passes over the entry
11
+ * CSS — they don't follow `@import`. Tailwind's own compiler DOES follow
12
+ * imports, so utilities still compile, but a user who keeps their theme
13
+ * in a separate file and points the entry at it:
14
+ *
15
+ * ```css
16
+ * @import "@acme/ui/theme.css"; // global.css — the cssEntryFile
17
+ * ```
18
+ *
19
+ * would hand the extractors a file with no `@theme` / `@variant` /
20
+ * `@custom-variant` in sight → every scheme collapses to base and theme
21
+ * switching dies. This module flattens those user imports first so the
22
+ * extractors (and the compiler) see the real declarations.
23
+ */
24
+ /** Matches a bare `@import "spec";` / `@import 'spec';` (no media/layer suffix). */
25
+ const CSS_IMPORT = /@import\s+(["'])([^"']+)\1\s*;/g;
26
+ /**
27
+ * Specs left untouched for the Tailwind compiler to resolve itself.
28
+ * `tailwindcss` resolves to JS (not inlinable) and `rnwind/css` is the
29
+ * framework preset — both are the compiler's job, not user theme files.
30
+ */
31
+ const FRAMEWORK_SPECS = new Set(['tailwindcss', 'rnwind/css', 'rnwind']);
32
+ /**
33
+ * Read `filePath` and replace each user `@import "<spec>";` whose spec
34
+ * resolves (Node resolution, honouring `exports` maps and workspace
35
+ * symlinks) to a readable `.css` file with that file's inlined +
36
+ * recursively-resolved contents. Unresolvable specs, non-CSS targets,
37
+ * and {@link FRAMEWORK_SPECS} are left as-is for the compiler.
38
+ * @param filePath Absolute path of the CSS file being inlined.
39
+ * @param seen Visited set guarding against import cycles.
40
+ * @returns CSS text with user imports flattened in place.
41
+ */
42
+ function inlineImports(filePath, seen) {
43
+ if (seen.has(filePath))
44
+ return '';
45
+ seen.add(filePath);
46
+ let css;
47
+ try {
48
+ css = node_fs.readFileSync(filePath, 'utf8');
49
+ }
50
+ catch {
51
+ return '';
52
+ }
53
+ const request = node_module.createRequire(filePath);
54
+ return css.replaceAll(CSS_IMPORT, (full, _quote, spec) => {
55
+ if (FRAMEWORK_SPECS.has(spec))
56
+ return full;
57
+ let resolved;
58
+ try {
59
+ resolved = request.resolve(spec);
60
+ }
61
+ catch {
62
+ return full;
63
+ }
64
+ if (!resolved.endsWith('.css') || !node_fs.existsSync(resolved))
65
+ return full;
66
+ return inlineImports(resolved, seen);
67
+ });
68
+ }
69
+ /**
70
+ * Flatten user `@import`s in a theme entry CSS file so rnwind's text-based
71
+ * scheme extractors see the real `@theme` / `@variant` / `@custom-variant`
72
+ * declarations even when the entry only re-exports them via `@import`.
73
+ * @param entryFilePath Absolute path to the theme entry CSS (the cssEntryFile).
74
+ * @returns Inlined CSS, or `''` when the entry can't be read.
75
+ */
76
+ function resolveThemeCss(entryFilePath) {
77
+ return inlineImports(entryFilePath, new Set());
78
+ }
79
+
80
+ exports.resolveThemeCss = resolveThemeCss;
81
+ //# sourceMappingURL=css-imports.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-imports.cjs","sources":["../../../../src/metro/css-imports.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport { existsSync, readFileSync } from 'node:fs'\n\n/**\n * Inline `@import` resolution for the theme entry CSS.\n *\n * rnwind's scheme extractors (`extractThemeVars`, `extractSchemeAliases`,\n * `extractCustomVariantSchemes`) are plain text passes over the entry\n * CSS — they don't follow `@import`. Tailwind's own compiler DOES follow\n * imports, so utilities still compile, but a user who keeps their theme\n * in a separate file and points the entry at it:\n *\n * ```css\n * @import \"@acme/ui/theme.css\"; // global.css — the cssEntryFile\n * ```\n *\n * would hand the extractors a file with no `@theme` / `@variant` /\n * `@custom-variant` in sight → every scheme collapses to base and theme\n * switching dies. This module flattens those user imports first so the\n * extractors (and the compiler) see the real declarations.\n */\n\n/** Matches a bare `@import \"spec\";` / `@import 'spec';` (no media/layer suffix). */\nconst CSS_IMPORT = /@import\\s+([\"'])([^\"']+)\\1\\s*;/g\n\n/**\n * Specs left untouched for the Tailwind compiler to resolve itself.\n * `tailwindcss` resolves to JS (not inlinable) and `rnwind/css` is the\n * framework preset — both are the compiler's job, not user theme files.\n */\nconst FRAMEWORK_SPECS = new Set(['tailwindcss', 'rnwind/css', 'rnwind'])\n\n/**\n * Read `filePath` and replace each user `@import \"<spec>\";` whose spec\n * resolves (Node resolution, honouring `exports` maps and workspace\n * symlinks) to a readable `.css` file with that file's inlined +\n * recursively-resolved contents. Unresolvable specs, non-CSS targets,\n * and {@link FRAMEWORK_SPECS} are left as-is for the compiler.\n * @param filePath Absolute path of the CSS file being inlined.\n * @param seen Visited set guarding against import cycles.\n * @returns CSS text with user imports flattened in place.\n */\nfunction inlineImports(filePath: string, seen: Set<string>): string {\n if (seen.has(filePath)) return ''\n seen.add(filePath)\n let css: string\n try {\n css = readFileSync(filePath, 'utf8')\n } catch {\n return ''\n }\n const request = createRequire(filePath)\n return css.replaceAll(CSS_IMPORT, (full: string, _quote: string, spec: string): string => {\n if (FRAMEWORK_SPECS.has(spec)) return full\n let resolved: string\n try {\n resolved = request.resolve(spec)\n } catch {\n return full\n }\n if (!resolved.endsWith('.css') || !existsSync(resolved)) return full\n return inlineImports(resolved, seen)\n })\n}\n\n/**\n * Flatten user `@import`s in a theme entry CSS file so rnwind's text-based\n * scheme extractors see the real `@theme` / `@variant` / `@custom-variant`\n * declarations even when the entry only re-exports them via `@import`.\n * @param entryFilePath Absolute path to the theme entry CSS (the cssEntryFile).\n * @returns Inlined CSS, or `''` when the entry can't be read.\n */\nexport function resolveThemeCss(entryFilePath: string): string {\n return inlineImports(entryFilePath, new Set<string>())\n}\n"],"names":["readFileSync","createRequire","existsSync"],"mappings":";;;;;AAGA;;;;;;;;;;;;;;;;;AAiBG;AAEH;AACA,MAAM,UAAU,GAAG,iCAAiC;AAEpD;;;;AAIG;AACH,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;AAExE;;;;;;;;;AASG;AACH,SAAS,aAAa,CAAC,QAAgB,EAAE,IAAiB,EAAA;AACxD,IAAA,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;AAAE,QAAA,OAAO,EAAE;AACjC,IAAA,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;AAClB,IAAA,IAAI,GAAW;AACf,IAAA,IAAI;AACF,QAAA,GAAG,GAAGA,oBAAY,CAAC,QAAQ,EAAE,MAAM,CAAC;IACtC;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,EAAE;IACX;AACA,IAAA,MAAM,OAAO,GAAGC,yBAAa,CAAC,QAAQ,CAAC;AACvC,IAAA,OAAO,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,IAAY,EAAE,MAAc,EAAE,IAAY,KAAY;AACvF,QAAA,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;AAAE,YAAA,OAAO,IAAI;AAC1C,QAAA,IAAI,QAAgB;AACpB,QAAA,IAAI;AACF,YAAA,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;QAClC;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,IAAI;QACb;AACA,QAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAACC,kBAAU,CAAC,QAAQ,CAAC;AAAE,YAAA,OAAO,IAAI;AACpE,QAAA,OAAO,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC;AACtC,IAAA,CAAC,CAAC;AACJ;AAEA;;;;;;AAMG;AACG,SAAU,eAAe,CAAC,aAAqB,EAAA;IACnD,OAAO,aAAa,CAAC,aAAa,EAAE,IAAI,GAAG,EAAU,CAAC;AACxD;;;;"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Flatten user `@import`s in a theme entry CSS file so rnwind's text-based
3
+ * scheme extractors see the real `@theme` / `@variant` / `@custom-variant`
4
+ * declarations even when the entry only re-exports them via `@import`.
5
+ * @param entryFilePath Absolute path to the theme entry CSS (the cssEntryFile).
6
+ * @returns Inlined CSS, or `''` when the entry can't be read.
7
+ */
8
+ export declare function resolveThemeCss(entryFilePath: string): string;
@@ -5,6 +5,7 @@ var path = require('node:path');
5
5
  var node_crypto = require('node:crypto');
6
6
  var unionBuilder = require('../core/style-builder/union-builder.cjs');
7
7
  var twParser = require('../core/parser/tw-parser.cjs');
8
+ var cssImports = require('./css-imports.cjs');
8
9
 
9
10
  /**
10
11
  * Default oxide Scanner globs — walk every JS/TS source under the
@@ -51,15 +52,20 @@ const CACHE_DIR_ENV = 'RNWIND_CACHE_DIR';
51
52
  const WATCH_FOLDERS_ENV = 'RNWIND_WATCH_FOLDERS';
52
53
  /** Env var carrying extra className prefixes the Metro config supplied. */
53
54
  const CLASSNAME_PREFIXES_ENV = 'RNWIND_CLASSNAME_PREFIXES';
55
+ /** Env var carrying extra import sources whose JSX exports get className→style rewrites. Comma-separated. */
56
+ const HOST_SOURCES_ENV = 'RNWIND_HOST_SOURCES';
57
+ /** Env var carrying extra JSX tag names (verbatim, may contain `.`) treated as hosts. Comma-separated. */
58
+ const HOST_COMPONENTS_ENV = 'RNWIND_HOST_COMPONENTS';
54
59
  /** Memoised library fingerprint — read once per worker process. */
55
60
  let libraryFingerprint;
56
61
  /** Live state shared across one Metro transform worker. */
57
62
  let cached = null;
58
63
  /**
59
- * Cheap content-hash readout. SHA-256 prefix of the CSS bytes plus the
60
- * file's mtime nanoseconds (so identical content with different mtime
61
- * atomic rewrites still picks up the change). Returns `'missing'`
62
- * when the file can't be read so the cache key is still deterministic.
64
+ * Cheap content-hash readout. SHA-256 prefix of the FULLY-RESOLVED theme
65
+ * CSS — `@import`s flattened so an edit to a theme file the entry only
66
+ * re-exports (`@import "@acme/ui/theme.css"`) still rotates the hash and
67
+ * invalidates Metro's cache. Returns `'missing'` when the entry can't be
68
+ * read so the cache key stays deterministic.
63
69
  * @param cssPath Absolute CSS path.
64
70
  * @returns 16-char hex content hash.
65
71
  */
@@ -67,9 +73,7 @@ function readThemeHashFor(cssPath) {
67
73
  if (!node_fs.existsSync(cssPath))
68
74
  return 'missing';
69
75
  try {
70
- const bytes = node_fs.readFileSync(cssPath);
71
- const mtime = node_fs.statSync(cssPath).mtimeMs.toString();
72
- return node_crypto.createHash('sha256').update(bytes).update(mtime).digest('hex').slice(0, 16);
76
+ return node_crypto.createHash('sha256').update(cssImports.resolveThemeCss(cssPath)).digest('hex').slice(0, 16);
73
77
  }
74
78
  catch {
75
79
  return 'missing';
@@ -135,8 +139,10 @@ function getLibraryFingerprint() {
135
139
  * @param cacheDir Absolute path to the cache dir (`.rnwind`).
136
140
  * @param watchFolders
137
141
  * @param classNamePrefixes Extra JSX prop-name prefixes to rewrite.
142
+ * @param hostSources
143
+ * @param hostComponents
138
144
  */
139
- function configureRnwindState(cssEntryFile, cacheDir, watchFolders = [], classNamePrefixes) {
145
+ function configureRnwindState(cssEntryFile, cacheDir, watchFolders = [], classNamePrefixes, hostSources, hostComponents) {
140
146
  process.env[CSS_ENTRY_ENV] = cssEntryFile;
141
147
  process.env[CACHE_DIR_ENV] = cacheDir;
142
148
  if (watchFolders.length === 0) {
@@ -151,6 +157,18 @@ function configureRnwindState(cssEntryFile, cacheDir, watchFolders = [], classNa
151
157
  else {
152
158
  process.env[CLASSNAME_PREFIXES_ENV] = classNamePrefixes.join(',');
153
159
  }
160
+ if (!hostSources || hostSources.length === 0) {
161
+ delete process.env[HOST_SOURCES_ENV];
162
+ }
163
+ else {
164
+ process.env[HOST_SOURCES_ENV] = hostSources.join(',');
165
+ }
166
+ if (!hostComponents || hostComponents.length === 0) {
167
+ delete process.env[HOST_COMPONENTS_ENV];
168
+ }
169
+ else {
170
+ process.env[HOST_COMPONENTS_ENV] = hostComponents.join(',');
171
+ }
154
172
  cached = null;
155
173
  }
156
174
  /**
@@ -166,6 +184,30 @@ function getClassNamePrefixes() {
166
184
  return [];
167
185
  return raw.split(',').filter((entry) => entry.length > 0);
168
186
  }
187
+ /**
188
+ * Read the caller-configured extra host module sources out of the
189
+ * worker environment. Empty array when unset — the transformer applies
190
+ * its built-in default list on top either way.
191
+ * @returns User-supplied extra host sources.
192
+ */
193
+ function getHostSources() {
194
+ const raw = process.env[HOST_SOURCES_ENV];
195
+ if (!raw || raw.length === 0)
196
+ return [];
197
+ return raw.split(',').filter((entry) => entry.length > 0);
198
+ }
199
+ /**
200
+ * Read the caller-configured extra host JSX tag names out of the worker
201
+ * environment. Verbatim names — may include `.` for member expressions
202
+ * like `'Animated.View'`.
203
+ * @returns User-supplied extra host component names.
204
+ */
205
+ function getHostComponents() {
206
+ const raw = process.env[HOST_COMPONENTS_ENV];
207
+ if (!raw || raw.length === 0)
208
+ return [];
209
+ return raw.split(',').filter((entry) => entry.length > 0);
210
+ }
169
211
  /**
170
212
  * Fetch (or build) the worker-local rnwind state. Re-reads the theme
171
213
  * CSS hash on every call: if the user edited `global.css` while Metro
@@ -186,7 +228,7 @@ function getRnwindState(projectRoot) {
186
228
  const currentHash = readThemeHashFor(cssEntry);
187
229
  if (cached?.themeHash === currentHash && cached.projectRoot === projectRoot)
188
230
  return cached;
189
- const themeCss = node_fs.readFileSync(cssEntry, 'utf8');
231
+ const themeCss = cssImports.resolveThemeCss(cssEntry);
190
232
  const parser = new twParser.TailwindParser({
191
233
  themeCss,
192
234
  sources: defaultSources(projectRoot, cacheDir, readWatchFolders()),
@@ -207,7 +249,13 @@ function getRnwindState(projectRoot) {
207
249
  function getRnwindCacheKey() {
208
250
  const cssEntry = process.env[CSS_ENTRY_ENV] ?? '';
209
251
  const prefixes = process.env[CLASSNAME_PREFIXES_ENV] ?? '';
210
- return `rnwind:${cssEntry}:${readThemeHashFor(cssEntry)}|lib:${getLibraryFingerprint()}|pfx:${prefixes}`;
252
+ // Host source / component config changes which JSX tags get rewritten,
253
+ // so it MUST flip the cache key — otherwise Metro replays stale
254
+ // transforms (a newly-opted-in host keeps its raw className, a removed
255
+ // one keeps the rewrite).
256
+ const hostSources = process.env[HOST_SOURCES_ENV] ?? '';
257
+ const hostComponents = process.env[HOST_COMPONENTS_ENV] ?? '';
258
+ return `rnwind:${cssEntry}:${readThemeHashFor(cssEntry)}|lib:${getLibraryFingerprint()}|pfx:${prefixes}|hs:${hostSources}|hc:${hostComponents}`;
211
259
  }
212
260
  /** Drop the cached state — call after editing the theme CSS. */
213
261
  function resetRnwindState() {
@@ -243,6 +291,8 @@ function manifestPathFor() {
243
291
 
244
292
  exports.configureRnwindState = configureRnwindState;
245
293
  exports.getClassNamePrefixes = getClassNamePrefixes;
294
+ exports.getHostComponents = getHostComponents;
295
+ exports.getHostSources = getHostSources;
246
296
  exports.getRnwindCacheKey = getRnwindCacheKey;
247
297
  exports.getRnwindState = getRnwindState;
248
298
  exports.manifestPathFor = manifestPathFor;