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.
- package/lib/cjs/core/parser/color.cjs +53 -24
- package/lib/cjs/core/parser/color.cjs.map +1 -1
- package/lib/cjs/core/parser/layout-dispatcher.cjs +20 -0
- package/lib/cjs/core/parser/layout-dispatcher.cjs.map +1 -1
- package/lib/cjs/core/parser/length.cjs +20 -6
- package/lib/cjs/core/parser/length.cjs.map +1 -1
- package/lib/cjs/core/parser/length.d.ts +6 -3
- package/lib/cjs/core/parser/shorthand.cjs +37 -5
- package/lib/cjs/core/parser/shorthand.cjs.map +1 -1
- package/lib/cjs/core/parser/shorthand.d.ts +11 -5
- package/lib/cjs/core/parser/theme-vars.cjs +53 -0
- package/lib/cjs/core/parser/theme-vars.cjs.map +1 -1
- package/lib/cjs/core/parser/theme-vars.d.ts +21 -0
- package/lib/cjs/core/parser/tokens.cjs +183 -1
- package/lib/cjs/core/parser/tokens.cjs.map +1 -1
- package/lib/cjs/core/parser/tw-parser.cjs +140 -27
- package/lib/cjs/core/parser/tw-parser.cjs.map +1 -1
- package/lib/cjs/core/parser/tw-parser.d.ts +21 -5
- package/lib/cjs/core/parser/typography-dispatcher.cjs +16 -1
- package/lib/cjs/core/parser/typography-dispatcher.cjs.map +1 -1
- package/lib/cjs/core/style-builder/build-style.cjs +73 -26
- package/lib/cjs/core/style-builder/build-style.cjs.map +1 -1
- package/lib/cjs/metro/css-imports.cjs +81 -0
- package/lib/cjs/metro/css-imports.cjs.map +1 -0
- package/lib/cjs/metro/css-imports.d.ts +8 -0
- package/lib/cjs/metro/state.cjs +60 -10
- package/lib/cjs/metro/state.cjs.map +1 -1
- package/lib/cjs/metro/state.d.ts +17 -1
- package/lib/cjs/metro/transform-ast.cjs +238 -21
- package/lib/cjs/metro/transform-ast.cjs.map +1 -1
- package/lib/cjs/metro/transform-ast.d.ts +15 -0
- package/lib/cjs/metro/transformer.cjs +29 -2
- package/lib/cjs/metro/transformer.cjs.map +1 -1
- package/lib/cjs/metro/with-config.cjs +1 -1
- package/lib/cjs/metro/with-config.cjs.map +1 -1
- package/lib/cjs/metro/with-config.d.ts +22 -0
- package/lib/esm/core/parser/color.mjs +53 -24
- package/lib/esm/core/parser/color.mjs.map +1 -1
- package/lib/esm/core/parser/layout-dispatcher.mjs +20 -0
- package/lib/esm/core/parser/layout-dispatcher.mjs.map +1 -1
- package/lib/esm/core/parser/length.d.ts +6 -3
- package/lib/esm/core/parser/length.mjs +20 -6
- package/lib/esm/core/parser/length.mjs.map +1 -1
- package/lib/esm/core/parser/shorthand.d.ts +11 -5
- package/lib/esm/core/parser/shorthand.mjs +37 -5
- package/lib/esm/core/parser/shorthand.mjs.map +1 -1
- package/lib/esm/core/parser/theme-vars.d.ts +21 -0
- package/lib/esm/core/parser/theme-vars.mjs +53 -1
- package/lib/esm/core/parser/theme-vars.mjs.map +1 -1
- package/lib/esm/core/parser/tokens.mjs +183 -1
- package/lib/esm/core/parser/tokens.mjs.map +1 -1
- package/lib/esm/core/parser/tw-parser.d.ts +21 -5
- package/lib/esm/core/parser/tw-parser.mjs +141 -28
- package/lib/esm/core/parser/tw-parser.mjs.map +1 -1
- package/lib/esm/core/parser/typography-dispatcher.mjs +16 -1
- package/lib/esm/core/parser/typography-dispatcher.mjs.map +1 -1
- package/lib/esm/core/style-builder/build-style.mjs +73 -26
- package/lib/esm/core/style-builder/build-style.mjs.map +1 -1
- package/lib/esm/metro/css-imports.d.ts +8 -0
- package/lib/esm/metro/css-imports.mjs +79 -0
- package/lib/esm/metro/css-imports.mjs.map +1 -0
- package/lib/esm/metro/state.d.ts +17 -1
- package/lib/esm/metro/state.mjs +60 -12
- package/lib/esm/metro/state.mjs.map +1 -1
- package/lib/esm/metro/transform-ast.d.ts +15 -0
- package/lib/esm/metro/transform-ast.mjs +238 -21
- package/lib/esm/metro/transform-ast.mjs.map +1 -1
- package/lib/esm/metro/transformer.mjs +30 -3
- package/lib/esm/metro/transformer.mjs.map +1 -1
- package/lib/esm/metro/with-config.d.ts +22 -0
- package/lib/esm/metro/with-config.mjs +1 -1
- package/lib/esm/metro/with-config.mjs.map +1 -1
- package/package.json +2 -1
- package/src/core/parser/color.ts +52 -18
- package/src/core/parser/layout-dispatcher.ts +19 -0
- package/src/core/parser/length.ts +20 -6
- package/src/core/parser/shorthand.ts +35 -5
- package/src/core/parser/theme-vars.ts +53 -0
- package/src/core/parser/tokens.ts +171 -1
- package/src/core/parser/tw-parser.ts +147 -28
- package/src/core/parser/typography-dispatcher.ts +15 -1
- package/src/core/style-builder/build-style.ts +84 -26
- package/src/metro/css-imports.ts +75 -0
- package/src/metro/state.ts +58 -10
- package/src/metro/transform-ast.ts +249 -18
- package/src/metro/transformer.ts +28 -3
- package/src/metro/with-config.ts +23 -1
|
@@ -27,14 +27,18 @@ const DEFAULT_TRANSFORM_OPTIONS = {
|
|
|
27
27
|
},
|
|
28
28
|
include: lightningcss.Features.Nesting | lightningcss.Features.MediaQueries,
|
|
29
29
|
exclude: lightningcss.Features.LogicalProperties | lightningcss.Features.DirSelector | lightningcss.Features.LightDark,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
// NOTE: deliberately no `targets`. With targets that include
|
|
31
|
+
// color-mix-supporting browsers (Safari 16.4+, Chrome 111+, …),
|
|
32
|
+
// lightningcss EVALUATES `color-mix(in oklab, var(--theme-color)
|
|
33
|
+
// <pct>%, transparent)` at parse time using whichever value of
|
|
34
|
+
// `--theme-color` it sees first in the cascade. Tailwind v4 emits
|
|
35
|
+
// exactly this shape for `<prop>-<themed>/<N>` utilities (e.g.
|
|
36
|
+
// `border-text/20`), so the resulting RGB color is locked to ONE
|
|
37
|
+
// scheme — every variant gets the same value. By dropping targets,
|
|
38
|
+
// lightningcss leaves color-mix as an unparsed function and our
|
|
39
|
+
// per-scheme `unparsedToEntries` substitution path runs instead,
|
|
40
|
+
// producing the right rgba(...) for each scheme. Targets in this
|
|
41
|
+
// pipeline are otherwise unused — we never re-emit CSS from the AST.
|
|
38
42
|
};
|
|
39
43
|
/**
|
|
40
44
|
* Parses one source file's Tailwind usage into RN-ready style objects.
|
|
@@ -58,6 +62,13 @@ class TailwindParser {
|
|
|
58
62
|
compiler;
|
|
59
63
|
themeSchemes;
|
|
60
64
|
schemeAliases;
|
|
65
|
+
/**
|
|
66
|
+
* Scheme names declared via `@custom-variant <name> …;`. A scheme
|
|
67
|
+
* listed here but absent from {@link themeSchemes} (no `@variant`
|
|
68
|
+
* override block) draws its values from the base `@theme` — the
|
|
69
|
+
* standard Tailwind v4 "light defaults + dark override" shape.
|
|
70
|
+
*/
|
|
71
|
+
customVariantSchemes;
|
|
61
72
|
/**
|
|
62
73
|
* Memoise `resolveCandidates` results by candidate-list fingerprint.
|
|
63
74
|
* Fast Refresh hits this on every save: oxide's scan is cheap, but
|
|
@@ -81,19 +92,42 @@ class TailwindParser {
|
|
|
81
92
|
this.config = config;
|
|
82
93
|
this.themeSchemes = themeVars.extractThemeVars(config.themeCss);
|
|
83
94
|
this.schemeAliases = themeVars.extractSchemeAliases(config.themeCss);
|
|
95
|
+
this.customVariantSchemes = themeVars.extractCustomVariantSchemes(config.themeCss);
|
|
84
96
|
this.scanner = new oxide.Scanner({ sources: config.sources ? [...config.sources] : [] });
|
|
85
97
|
}
|
|
86
98
|
/**
|
|
87
|
-
* Schemes declared by the user —
|
|
88
|
-
*
|
|
89
|
-
* any
|
|
90
|
-
* per-atom resolver fills. Exposed publicly so
|
|
91
|
-
* hand the names to the `.d.ts` generator
|
|
99
|
+
* Schemes declared by the user — the union of every `@custom-variant
|
|
100
|
+
* <name>` declaration and every `@variant <name>` block, or just
|
|
101
|
+
* `['base']` for themes without any. Used to decide how many
|
|
102
|
+
* per-scheme buckets the per-atom resolver fills. Exposed publicly so
|
|
103
|
+
* Metro integration can hand the names to the `.d.ts` generator
|
|
104
|
+
* without a full parse.
|
|
105
|
+
*
|
|
106
|
+
* Both sources matter. `@variant` blocks alone miss the common
|
|
107
|
+
* Tailwind v4 shape where the light palette sits in the base `@theme`
|
|
108
|
+
* and only `@variant dark` overrides it: there `light` exists solely
|
|
109
|
+
* as a `@custom-variant` and would otherwise be dropped, collapsing
|
|
110
|
+
* every themed atom to a single bucket that can't switch.
|
|
111
|
+
* `@custom-variant` order wins (it's where users enumerate their
|
|
112
|
+
* schemes); any `@variant`-only scheme is appended after.
|
|
92
113
|
* @returns Scheme names.
|
|
93
114
|
*/
|
|
94
115
|
get declaredSchemes() {
|
|
95
|
-
const
|
|
96
|
-
|
|
116
|
+
const ordered = [];
|
|
117
|
+
const seen = new Set();
|
|
118
|
+
for (const name of this.customVariantSchemes) {
|
|
119
|
+
if (seen.has(name))
|
|
120
|
+
continue;
|
|
121
|
+
seen.add(name);
|
|
122
|
+
ordered.push(name);
|
|
123
|
+
}
|
|
124
|
+
for (const name of this.themeSchemes.keys()) {
|
|
125
|
+
if (name === themeVars.BASE_SCHEME || seen.has(name))
|
|
126
|
+
continue;
|
|
127
|
+
seen.add(name);
|
|
128
|
+
ordered.push(name);
|
|
129
|
+
}
|
|
130
|
+
return ordered.length > 0 ? ordered : [themeVars.BASE_SCHEME];
|
|
97
131
|
}
|
|
98
132
|
/**
|
|
99
133
|
* Build an effective var table for one scheme — base vars overridden by
|
|
@@ -186,6 +220,19 @@ class TailwindParser {
|
|
|
186
220
|
catch (error) {
|
|
187
221
|
throw wrapThemeError(error);
|
|
188
222
|
}
|
|
223
|
+
// Tailwind v4 emits opacity-suffixed themed colors as a pre-resolved
|
|
224
|
+
// sRGB fallback PLUS a `@supports`-gated var()-based override:
|
|
225
|
+
// border-color: color-mix(in srgb, #0A0A0A 20%, transparent);
|
|
226
|
+
// @supports (color: color-mix(in lab, red, red)) {
|
|
227
|
+
// border-color: color-mix(in oklab, var(--color-text) 20%, transparent);
|
|
228
|
+
// }
|
|
229
|
+
// Lightningcss takes the OUTER fallback (locked to whichever scheme
|
|
230
|
+
// the compiler resolved first), and our per-scheme substitution
|
|
231
|
+
// never gets a chance. Unwrap the @supports so the var()-based
|
|
232
|
+
// declaration overrides the fallback in the same rule — lightningcss
|
|
233
|
+
// emits the override as `unparsed` and the parser's themeVars-aware
|
|
234
|
+
// path produces correct rgba per scheme.
|
|
235
|
+
css = unwrapColorMixSupports(css);
|
|
189
236
|
// `compiler.build(candidates)` memoizes across calls — it returns CSS for
|
|
190
237
|
// every candidate the compiler has EVER seen in this process. To keep
|
|
191
238
|
// parser output pure per-call we restrict outputs to this call's
|
|
@@ -918,20 +965,24 @@ function parseFirstShadow(raw) {
|
|
|
918
965
|
* @returns Pixel lengths + the remainder text (color expression).
|
|
919
966
|
*/
|
|
920
967
|
function extractShadowLengths(head) {
|
|
921
|
-
|
|
968
|
+
// Take ONLY the leading run of length tokens, stopping at the first
|
|
969
|
+
// non-length token (the color). A previous global digit-regex scanned
|
|
970
|
+
// the whole string, so a <4-length shadow like `0 1px 1px rgb(0 0 0 /
|
|
971
|
+
// 0.05)` stole a digit out of the color expression — corrupting the
|
|
972
|
+
// alpha (opacity) or a digit-leading hex. Whitespace-splitting can't
|
|
973
|
+
// reach inside the color because we break as soon as a token isn't a
|
|
974
|
+
// bare/`px`/`rem`/`em`/`%` length.
|
|
975
|
+
// Unambiguous integer-or-decimal (no `\d*\.?\d+` overlap) so there's no
|
|
976
|
+
// super-linear backtracking on long digit runs.
|
|
977
|
+
const isLength = /^-?(?:\d+(?:\.\d+)?|\.\d+)(?:px|rem|em|%)?$/;
|
|
978
|
+
const parts = head.split(/\s+/);
|
|
922
979
|
const lengths = [];
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
lengths.push(parseLengthToken(next[0]));
|
|
928
|
-
next = lengthRegex.exec(head);
|
|
929
|
-
}
|
|
930
|
-
let remainder = head;
|
|
931
|
-
for (const { text, index } of matches.toReversed()) {
|
|
932
|
-
remainder = `${remainder.slice(0, index)}${remainder.slice(index + text.length)}`;
|
|
980
|
+
let index = 0;
|
|
981
|
+
while (index < parts.length && lengths.length < 4 && isLength.test(parts[index])) {
|
|
982
|
+
lengths.push(parseLengthToken(parts[index]));
|
|
983
|
+
index += 1;
|
|
933
984
|
}
|
|
934
|
-
return { lengths, remainder };
|
|
985
|
+
return { lengths, remainder: parts.slice(index).join(' ') };
|
|
935
986
|
}
|
|
936
987
|
/**
|
|
937
988
|
* Coerce one shadow length token into a pixel number. Accepts bare
|
|
@@ -1470,6 +1521,68 @@ function resolveAngleExpression(text) {
|
|
|
1470
1521
|
* @param css Tailwind's compiled CSS.
|
|
1471
1522
|
* @returns Map of custom-property name → resolved value.
|
|
1472
1523
|
*/
|
|
1524
|
+
/**
|
|
1525
|
+
* Strip `\@supports (color: color-mix(in lab, red, red)) { … }` wrappers
|
|
1526
|
+
* from Tailwind v4's compiled CSS, hoisting their inner declarations up
|
|
1527
|
+
* to the parent rule.
|
|
1528
|
+
*
|
|
1529
|
+
* Tailwind emits opacity-suffixed themed colors with both a pre-resolved
|
|
1530
|
+
* sRGB fallback AND a var()-based override gated behind the color-mix
|
|
1531
|
+
* `\@supports` clause. The OUTER fallback hard-codes a single scheme's
|
|
1532
|
+
* value of the theme token; the inner override is var()-based and
|
|
1533
|
+
* substitutes correctly per scheme. By unwrapping the gate, the inner
|
|
1534
|
+
* declaration becomes a sibling of the fallback in the same rule body —
|
|
1535
|
+
* lightningcss takes the LATER one (the var()-based unparsed form), and
|
|
1536
|
+
* the parser's themeVars-aware path produces correct rgba per scheme.
|
|
1537
|
+
* Modern RN-targeted browsers all support color-mix anyway, so dropping
|
|
1538
|
+
* the gating is safe.
|
|
1539
|
+
* @param css Tailwind-compiled CSS.
|
|
1540
|
+
* @returns CSS with the color-mix support gates unwrapped.
|
|
1541
|
+
*/
|
|
1542
|
+
function unwrapColorMixSupports(css) {
|
|
1543
|
+
const guard = '@supports (color: color-mix(in lab, red, red))';
|
|
1544
|
+
let out = '';
|
|
1545
|
+
let cursor = 0;
|
|
1546
|
+
while (cursor < css.length) {
|
|
1547
|
+
const head = css.indexOf(guard, cursor);
|
|
1548
|
+
if (head === -1) {
|
|
1549
|
+
out += css.slice(cursor);
|
|
1550
|
+
break;
|
|
1551
|
+
}
|
|
1552
|
+
out += css.slice(cursor, head);
|
|
1553
|
+
const brace = css.indexOf('{', head);
|
|
1554
|
+
if (brace === -1) {
|
|
1555
|
+
out += css.slice(head);
|
|
1556
|
+
break;
|
|
1557
|
+
}
|
|
1558
|
+
const blockEnd = findMatchingClose(css, brace + 1);
|
|
1559
|
+
if (blockEnd === -1) {
|
|
1560
|
+
out += css.slice(head);
|
|
1561
|
+
break;
|
|
1562
|
+
}
|
|
1563
|
+
const inner = css.slice(brace + 1, blockEnd);
|
|
1564
|
+
// Only unwrap when the gated declaration substitutes a USER theme
|
|
1565
|
+
// token (`var(--color-…)`). Tailwind also gates `--tw-*` internal
|
|
1566
|
+
// composers (shadow color, ring color, …) on the same supports
|
|
1567
|
+
// clause; their outer fallback is the optimized hex/oklch value
|
|
1568
|
+
// the parser's own composed-prop pass needs (`applyComposedShadow`
|
|
1569
|
+
// reads `--tw-shadow-color` from the rule's local vars). Unwrapping
|
|
1570
|
+
// them would replace the resolvable color with an unresolvable
|
|
1571
|
+
// `color-mix(... var(--tw-shadow-alpha), transparent)` text and
|
|
1572
|
+
// break the composed-shadow path.
|
|
1573
|
+
// Keep the gate intact for non-themed colors — the outer fallback
|
|
1574
|
+
// wins, which is what Tailwind intended.
|
|
1575
|
+
out += inner.includes('var(--color-') ? inner : css.slice(head, blockEnd + 1);
|
|
1576
|
+
cursor = blockEnd + 1;
|
|
1577
|
+
}
|
|
1578
|
+
return out;
|
|
1579
|
+
}
|
|
1580
|
+
/**
|
|
1581
|
+
* Extract every `--name: value` declaration from the `:root` blocks in
|
|
1582
|
+
* Tailwind's compiled CSS into a flat map.
|
|
1583
|
+
* @param css Tailwind-compiled CSS.
|
|
1584
|
+
* @returns Map of custom-property name → resolved value.
|
|
1585
|
+
*/
|
|
1473
1586
|
function extractRootCustomProperties(css) {
|
|
1474
1587
|
const out = new Map();
|
|
1475
1588
|
let cursor = 0;
|