@tenphi/tasty 0.0.0-snapshot.d656d18 → 0.0.0-snapshot.d7129ca

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 (92) hide show
  1. package/README.md +6 -6
  2. package/dist/{babel-_RVkw0iE.d.ts → babel-DD7kdEFT.d.ts} +2 -2
  3. package/dist/chunks/async-storage-CG5HnUT5.js +20 -0
  4. package/dist/chunks/{async-storage-DKK-wTD4.js.map → async-storage-CG5HnUT5.js.map} +1 -1
  5. package/dist/chunks/build-config-CUQVwdWF.js +42 -0
  6. package/dist/chunks/build-config-CUQVwdWF.js.map +1 -0
  7. package/dist/chunks/{collector-DBGcmUEq.js → collector-B0LTHw6Z.js} +6 -124
  8. package/dist/chunks/collector-B0LTHw6Z.js.map +1 -0
  9. package/dist/chunks/config-engine-C3pF9EK9.js +267 -0
  10. package/dist/chunks/config-engine-C3pF9EK9.js.map +1 -0
  11. package/dist/chunks/css-definitions-D_it4XZH.js +875 -0
  12. package/dist/chunks/css-definitions-D_it4XZH.js.map +1 -0
  13. package/dist/chunks/{css-resources-Cyl_axbI.js → css-resources-BN8apgxt.js} +1 -8
  14. package/dist/chunks/{css-resources-Cyl_axbI.js.map → css-resources-BN8apgxt.js.map} +1 -1
  15. package/dist/chunks/{debug-BUwqo6vC.js → debug-CiiHDgmR.js} +69 -150
  16. package/dist/chunks/debug-CiiHDgmR.js.map +1 -0
  17. package/dist/chunks/{dsl-CXvoaLnj.js → dsl-C5yuAn41.js} +62 -786
  18. package/dist/chunks/dsl-C5yuAn41.js.map +1 -0
  19. package/dist/chunks/hydration-TRcz5vnk.js +41 -0
  20. package/dist/chunks/hydration-TRcz5vnk.js.map +1 -0
  21. package/dist/chunks/react-runtime-sH6r6Ajr.js +557 -0
  22. package/dist/chunks/react-runtime-sH6r6Ajr.js.map +1 -0
  23. package/dist/chunks/runtime-engine-BrRcOZwD.js +2438 -0
  24. package/dist/chunks/runtime-engine-BrRcOZwD.js.map +1 -0
  25. package/dist/chunks/runtime-state-BTDqSYBk.js +127 -0
  26. package/dist/chunks/runtime-state-BTDqSYBk.js.map +1 -0
  27. package/dist/chunks/{shared-utils-OIg0N_dp.js → shared-utils-DWA4LjIa.js} +24 -62
  28. package/dist/chunks/shared-utils-DWA4LjIa.js.map +1 -0
  29. package/dist/chunks/{style-engine-CqSmIlud.js → style-engine-C1ECBZxR.js} +671 -2736
  30. package/dist/chunks/style-engine-C1ECBZxR.js.map +1 -0
  31. package/dist/chunks/{css-writer-PFzrSPeu.js → zero-engine-B6EnYcXY.js} +3 -120
  32. package/dist/chunks/zero-engine-B6EnYcXY.js.map +1 -0
  33. package/dist/{collector-CVdVIy7s.d.ts → collector-YpsMjV7T.d.ts} +6 -4
  34. package/dist/{config-BI0y21JV.d.ts → config-BnZqyYG4.d.ts} +16 -25
  35. package/dist/core/index.d.ts +5 -5
  36. package/dist/core/index.js +9 -7
  37. package/dist/{index-CrT0bsiI.d.ts → index-BLJLo9cl.d.ts} +17 -50
  38. package/dist/index.d.ts +5 -5
  39. package/dist/index.js +10 -7
  40. package/dist/{merge-styles-BFktNP8J.d.ts → merge-styles-CTDLIrO5.d.ts} +2 -2
  41. package/dist/ssr/astro-client.js +1 -14
  42. package/dist/ssr/astro-client.js.map +1 -1
  43. package/dist/ssr/astro-middleware-static.js +0 -11
  44. package/dist/ssr/astro-middleware-static.js.map +1 -1
  45. package/dist/ssr/astro-middleware.js +0 -12
  46. package/dist/ssr/astro-middleware.js.map +1 -1
  47. package/dist/ssr/astro.js +5 -85
  48. package/dist/ssr/astro.js.map +1 -1
  49. package/dist/ssr/index.d.ts +6 -6
  50. package/dist/ssr/index.js +4 -4
  51. package/dist/ssr/next-config.d.ts +1 -1
  52. package/dist/ssr/next-config.js +29 -20
  53. package/dist/ssr/next-config.js.map +1 -1
  54. package/dist/ssr/next.d.ts +1 -1
  55. package/dist/ssr/next.js +5 -36
  56. package/dist/ssr/next.js.map +1 -1
  57. package/dist/static/index.d.ts +2 -2
  58. package/dist/static/index.js +1 -19
  59. package/dist/static/index.js.map +1 -1
  60. package/dist/{index-BzAC3p06.d.ts → types-vfRQhzRd.d.ts} +811 -811
  61. package/dist/zero/babel.d.ts +1 -1
  62. package/dist/zero/babel.js +25 -95
  63. package/dist/zero/babel.js.map +1 -1
  64. package/dist/zero/index.d.ts +1 -1
  65. package/dist/zero/index.js +1 -1
  66. package/dist/zero/next.d.ts +1 -1
  67. package/dist/zero/next.js +0 -31
  68. package/dist/zero/next.js.map +1 -1
  69. package/docs/ai-agents.md +5 -1
  70. package/docs/dsl.md +2 -2
  71. package/docs/getting-started.md +12 -11
  72. package/docs/methodology.md +2 -2
  73. package/docs/pipeline.md +3 -0
  74. package/docs/plugins.md +1 -1
  75. package/docs/runtime-benchmarks.md +105 -68
  76. package/docs/ssr.md +1 -1
  77. package/docs/styles.md +5 -5
  78. package/docs/tasty-static.md +1 -1
  79. package/package.json +29 -10
  80. package/dist/chunks/async-storage-DKK-wTD4.js +0 -44
  81. package/dist/chunks/collector-DBGcmUEq.js.map +0 -1
  82. package/dist/chunks/css-writer-PFzrSPeu.js.map +0 -1
  83. package/dist/chunks/debug-BUwqo6vC.js.map +0 -1
  84. package/dist/chunks/dsl-CXvoaLnj.js.map +0 -1
  85. package/dist/chunks/hydrate-6YoHZP6A.js +0 -37
  86. package/dist/chunks/hydrate-6YoHZP6A.js.map +0 -1
  87. package/dist/chunks/react-runtime-B3CmvDEQ.js +0 -1525
  88. package/dist/chunks/react-runtime-B3CmvDEQ.js.map +0 -1
  89. package/dist/chunks/runtime-engine-Y00VWjrS.js +0 -4719
  90. package/dist/chunks/runtime-engine-Y00VWjrS.js.map +0 -1
  91. package/dist/chunks/shared-utils-OIg0N_dp.js.map +0 -1
  92. package/dist/chunks/style-engine-CqSmIlud.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { a as warnOnceDev, o as isDevEnv } from "./shared-utils-OIg0N_dp.js";
1
+ import { a as warnOnceDev, o as isDevEnv } from "./shared-utils-DWA4LjIa.js";
2
2
  //#region src/parser/const.ts
3
3
  const VALUE_KEYWORDS = new Set([
4
4
  "auto",
@@ -19,11 +19,6 @@ const CSS_WIDE_KEYWORDS = new Set([
19
19
  "unset",
20
20
  "revert-layer"
21
21
  ]);
22
- /**
23
- * Color functions that *derive* a color from other colors. They take no alpha
24
- * channel, so opacity has to wrap the whole call in `color-mix()` instead of
25
- * being appended after a slash.
26
- */
27
22
  const DERIVED_COLOR_FUNCS_LIST = [
28
23
  "color-mix",
29
24
  "color-contrast",
@@ -31,11 +26,6 @@ const DERIVED_COLOR_FUNCS_LIST = [
31
26
  "light-dark"
32
27
  ];
33
28
  const DERIVED_COLOR_FUNCS = new Set(DERIVED_COLOR_FUNCS_LIST);
34
- /**
35
- * Every color function the parser recognizes. The ones outside
36
- * `DERIVED_COLOR_FUNCS` take channels as arguments, optionally followed by
37
- * `/ <alpha>` — which is where an opacity suffix writes.
38
- */
39
29
  const COLOR_FUNCS = new Set([
40
30
  "rgb",
41
31
  "rgba",
@@ -51,7 +41,6 @@ const COLOR_FUNCS = new Set([
51
41
  "gray",
52
42
  ...DERIVED_COLOR_FUNCS_LIST
53
43
  ]);
54
- /** A value that is a single `name(args)` call: captures the name and the args. */
55
44
  const RE_FUNC_CALL = /^([a-z][a-z0-9-]*)\((.+)\)$/i;
56
45
  const RE_UNIT_NUM = /^[+-]?(?:\d*\.\d+|\d+)([a-z][a-z0-9]*)$/;
57
46
  const RE_NUMBER = /^[+-]?(?:\d*\.\d+|\d+)$/;
@@ -78,41 +67,13 @@ function canonicalFuncName(lowered) {
78
67
  function toSnakeCase(str) {
79
68
  return str.replace(/[A-Z]/g, (s) => `-${s.toLowerCase()}`);
80
69
  }
81
- /**
82
- * Normalize a DSL identifier to the CSS custom-property name it emits.
83
- *
84
- * CSS custom-property names are case-sensitive, so `$myVar` has to keep its
85
- * inner case to reference `--myVar`. A leading capital is the one exception:
86
- * `$Foo` is not a supported way to name a property, so the first character is
87
- * folded rather than kebab-cased (`--foo`, not `---foo`) and every later
88
- * character is left alone.
89
- *
90
- * Every place that turns a `$name` / `#name` identifier into a CSS name goes
91
- * through this, so authoring a token and referencing it always agree.
92
- */
93
70
  function normalizeDslName(name) {
94
71
  if (!name) return name;
95
72
  const first = name[0];
96
73
  const lower = first.toLowerCase();
97
74
  return lower === first ? name : lower + name.slice(1);
98
75
  }
99
- /** A DSL identifier: `$name`, `$$name`, `#name` or `##name`. */
100
76
  const RE_DSL_IDENTIFIER = /(\$\$?|##?)([a-zA-Z_][a-zA-Z0-9_-]*)/g;
101
- /**
102
- * Case-fold a DSL string for parsing, preserving the case of custom-property
103
- * names.
104
- *
105
- * Everything the parser matches on — keywords, units, modifiers, function names,
106
- * color-token names — is compared lowercase, so the whole string used to be
107
- * lowercased up front. That also folded custom-property names, which are
108
- * case-sensitive in CSS: `$myVar` referenced `var(--myvar)` while the token
109
- * definition emitted `--myVar`, so the two could never meet.
110
- *
111
- * Identifier bodies now keep their case (their first character still folds, see
112
- * {@link normalizeDslName}); everything else is lowercased exactly as before.
113
- * Hex literals are excluded — `#FF0000` is a color, not a name, and must fold to
114
- * match {@link RE_HEX}.
115
- */
116
77
  function foldDslCase(src) {
117
78
  const folded = src.toLowerCase();
118
79
  if (folded === src || !src.includes("$") && !src.includes("#")) return folded;
@@ -130,22 +91,10 @@ function foldDslCase(src) {
130
91
  }
131
92
  //#endregion
132
93
  //#region src/utils/color-math.ts
133
- const OKLab_to_LMS_M = [
134
- [
135
- 1,
136
- .3963377773761749,
137
- .2158037573099136
138
- ],
139
- [
140
- 1,
141
- -.1055613458156586,
142
- -.0638541728258133
143
- ],
144
- [
145
- 1,
146
- -.0894841775298119,
147
- -1.2914855480194092
148
- ]
94
+ const OKLab_to_LMS_ab = [
95
+ [.3963377773761749, .2158037573099136],
96
+ [-.1055613458156586, -.0638541728258133],
97
+ [-.0894841775298119, -1.2914855480194092]
149
98
  ];
150
99
  const LMS_to_linear_sRGB_M = [
151
100
  [
@@ -187,7 +136,8 @@ const OKLab_to_linear_sRGB_coefficients = [
187
136
  .00692167
188
137
  ]]
189
138
  ];
190
- const dotXY = (a, b) => a[0] * b[0] + a[1] * b[1];
139
+ const dotXY = (vector, x, y) => vector[0] * x + vector[1] * y;
140
+ const dotXYZ = (matrix, x, y, z) => matrix[0] * x + matrix[1] * y + matrix[2] * z;
191
141
  const INV_GAMMA = 1 / 2.4;
192
142
  function srgbLinearToGamma(val) {
193
143
  const sign = val < 0 ? -1 : 1;
@@ -232,18 +182,12 @@ const oklabToLinearSrgb = (lab) => {
232
182
  const computeMaxSaturationOKLC = (a, b) => {
233
183
  const okCoeff = OKLab_to_linear_sRGB_coefficients;
234
184
  const lmsToRgb = LMS_to_linear_sRGB_M;
235
- const tmp2 = [a, b];
236
- const tmp3 = [
237
- 0,
238
- a,
239
- b
240
- ];
241
185
  let chnlCoeff;
242
186
  let chnlLMS;
243
- if (dotXY(okCoeff[0][0], tmp2) > 1) {
187
+ if (dotXY(okCoeff[0][0], a, b) > 1) {
244
188
  chnlCoeff = okCoeff[0][1];
245
189
  chnlLMS = lmsToRgb[0];
246
- } else if (dotXY(okCoeff[1][0], tmp2) > 1) {
190
+ } else if (dotXY(okCoeff[1][0], a, b) > 1) {
247
191
  chnlCoeff = okCoeff[1][1];
248
192
  chnlLMS = lmsToRgb[1];
249
193
  } else {
@@ -253,10 +197,9 @@ const computeMaxSaturationOKLC = (a, b) => {
253
197
  const [k0, k1, k2, k3, k4] = chnlCoeff;
254
198
  const [wl, wm, ws] = chnlLMS;
255
199
  let sat = k0 + k1 * a + k2 * b + k3 * (a * a) + k4 * a * b;
256
- const dotYZ = (mat, vec) => mat[1] * vec[1] + mat[2] * vec[2];
257
- const kl = dotYZ(OKLab_to_LMS_M[0], tmp3);
258
- const km = dotYZ(OKLab_to_LMS_M[1], tmp3);
259
- const ks = dotYZ(OKLab_to_LMS_M[2], tmp3);
200
+ const kl = dotXY(OKLab_to_LMS_ab[0], a, b);
201
+ const km = dotXY(OKLab_to_LMS_ab[1], a, b);
202
+ const ks = dotXY(OKLab_to_LMS_ab[2], a, b);
260
203
  const l_ = 1 + sat * kl;
261
204
  const m_ = 1 + sat * km;
262
205
  const s_ = 1 + sat * ks;
@@ -287,15 +230,7 @@ const findCuspOKLCH = (a, b) => {
287
230
  };
288
231
  const findGamutIntersectionOKLCH = (a, b, l1, c1, l0, cusp) => {
289
232
  const lmsToRgb = LMS_to_linear_sRGB_M;
290
- const tmp3 = [
291
- 0,
292
- a,
293
- b
294
- ];
295
- const floatMax = Number.MAX_VALUE;
296
233
  let t;
297
- const dotYZ = (mat, vec) => mat[1] * vec[1] + mat[2] * vec[2];
298
- const dotXYZ = (vec, x, y, z) => vec[0] * x + vec[1] * y + vec[2] * z;
299
234
  if ((l1 - l0) * cusp[1] - (cusp[0] - l0) * c1 <= 0) {
300
235
  const denom = c1 * cusp[0] + cusp[1] * (l0 - l1);
301
236
  t = denom === 0 ? 0 : cusp[1] * l0 / denom;
@@ -304,9 +239,9 @@ const findGamutIntersectionOKLCH = (a, b, l1, c1, l0, cusp) => {
304
239
  t = denom === 0 ? 0 : cusp[1] * (l0 - 1) / denom;
305
240
  const dl = l1 - l0;
306
241
  const dc = c1;
307
- const kl = dotYZ(OKLab_to_LMS_M[0], tmp3);
308
- const km = dotYZ(OKLab_to_LMS_M[1], tmp3);
309
- const ks = dotYZ(OKLab_to_LMS_M[2], tmp3);
242
+ const kl = dotXY(OKLab_to_LMS_ab[0], a, b);
243
+ const km = dotXY(OKLab_to_LMS_ab[1], a, b);
244
+ const ks = dotXY(OKLab_to_LMS_ab[2], a, b);
310
245
  const ldt_ = dl + dc * kl;
311
246
  const mdt_ = dl + dc * km;
312
247
  const sdt_ = dl + dc * ks;
@@ -324,25 +259,15 @@ const findGamutIntersectionOKLCH = (a, b, l1, c1, l0, cusp) => {
324
259
  const ldt2 = 6 * ldt_ * ldt_ * l_;
325
260
  const mdt2 = 6 * mdt_ * mdt_ * m_;
326
261
  const sdt2 = 6 * sdt_ * sdt_ * s_;
327
- const r_ = dotXYZ(lmsToRgb[0], l, m, s) - 1;
328
- const r1 = dotXYZ(lmsToRgb[0], ldt, mdt, sdt);
329
- const r2 = dotXYZ(lmsToRgb[0], ldt2, mdt2, sdt2);
330
- const ur = r1 / (r1 * r1 - .5 * r_ * r2);
331
- let tr = -r_ * ur;
332
- const g_ = dotXYZ(lmsToRgb[1], l, m, s) - 1;
333
- const g1 = dotXYZ(lmsToRgb[1], ldt, mdt, sdt);
334
- const g2 = dotXYZ(lmsToRgb[1], ldt2, mdt2, sdt2);
335
- const ug = g1 / (g1 * g1 - .5 * g_ * g2);
336
- let tg = -g_ * ug;
337
- const b_ = dotXYZ(lmsToRgb[2], l, m, s) - 1;
338
- const b1 = dotXYZ(lmsToRgb[2], ldt, mdt, sdt);
339
- const b2 = dotXYZ(lmsToRgb[2], ldt2, mdt2, sdt2);
340
- const ub = b1 / (b1 * b1 - .5 * b_ * b2);
341
- let tb = -b_ * ub;
342
- tr = ur >= 0 ? tr : floatMax;
343
- tg = ug >= 0 ? tg : floatMax;
344
- tb = ub >= 0 ? tb : floatMax;
345
- t += Math.min(tr, Math.min(tg, tb));
262
+ let correction = Number.MAX_VALUE;
263
+ for (const matrix of lmsToRgb) {
264
+ const value = dotXYZ(matrix, l, m, s) - 1;
265
+ const slope = dotXYZ(matrix, ldt, mdt, sdt);
266
+ const slope2 = dotXYZ(matrix, ldt2, mdt2, sdt2);
267
+ const u = slope / (slope * slope - .5 * value * slope2);
268
+ if (u >= 0) correction = Math.min(correction, -value * u);
269
+ }
270
+ t += correction;
346
271
  }
347
272
  return t;
348
273
  };
@@ -400,15 +325,6 @@ const okhslToOklab = (hsl) => {
400
325
  b
401
326
  ];
402
327
  };
403
- /**
404
- * HSL to RGB.
405
- * Algorithm from CSS Color 4 spec.
406
- *
407
- * @param h - Hue in degrees (0-360)
408
- * @param s - Saturation (0-1)
409
- * @param l - Lightness (0-1)
410
- * @returns RGB values in 0-255 range (may have fractional values)
411
- */
412
328
  function hslToRgbValues(h, s, l) {
413
329
  const a = s * Math.min(l, 1 - l);
414
330
  const f = (n) => {
@@ -421,13 +337,6 @@ function hslToRgbValues(h, s, l) {
421
337
  f(4) * 255
422
338
  ];
423
339
  }
424
- /**
425
- * OKHSL to sRGB (0-1 range).
426
- * @param h - Hue in degrees (0-360)
427
- * @param s - Saturation (0-1)
428
- * @param l - Lightness (0-1)
429
- * @returns sRGB values in 0-1 range, clamped to gamut
430
- */
431
340
  function okhslToSrgb(h, s, l) {
432
341
  const linearRGB = oklabToLinearSrgb(okhslToOklab([
433
342
  h,
@@ -440,23 +349,9 @@ function okhslToSrgb(h, s, l) {
440
349
  clamp$1(srgbLinearToGamma(linearRGB[2]), 0, 1)
441
350
  ];
442
351
  }
443
- /**
444
- * OKHST to sRGB (0-1 range).
445
- * @param h - Hue in degrees (0-360)
446
- * @param s - Saturation (0-1)
447
- * @param t - Tone (0-1)
448
- * @returns sRGB values in 0-1 range, clamped to gamut
449
- */
450
352
  function okhstToSrgb(h, s, t) {
451
353
  return okhslToSrgb(h, clamp$1(s, 0, 1), clamp$1(fromTone(t * 100), 0, 1));
452
354
  }
453
- /**
454
- * OKLCH to sRGB (0-255 range).
455
- * @param L - Lightness (0-1)
456
- * @param C - Chroma (typically 0-0.4)
457
- * @param H - Hue in degrees (0-360)
458
- * @returns RGB values in 0-255 range, clamped to gamut
459
- */
460
355
  function oklchToRgbValues(L, C, H) {
461
356
  const hRad = H * Math.PI / 180;
462
357
  const linear = oklabToLinearSrgb([
@@ -473,162 +368,12 @@ function oklchToRgbValues(L, C, H) {
473
368
  let _namedColorHex = null;
474
369
  function getNamedColorHex() {
475
370
  if (_namedColorHex) return _namedColorHex;
476
- _namedColorHex = new Map([
477
- ["aliceblue", "#f0f8ff"],
478
- ["antiquewhite", "#faebd7"],
479
- ["aqua", "#00ffff"],
480
- ["aquamarine", "#7fffd4"],
481
- ["azure", "#f0ffff"],
482
- ["beige", "#f5f5dc"],
483
- ["bisque", "#ffe4c4"],
484
- ["black", "#000000"],
485
- ["blanchedalmond", "#ffebcd"],
486
- ["blue", "#0000ff"],
487
- ["blueviolet", "#8a2be2"],
488
- ["brown", "#a52a2a"],
489
- ["burlywood", "#deb887"],
490
- ["cadetblue", "#5f9ea0"],
491
- ["chartreuse", "#7fff00"],
492
- ["chocolate", "#d2691e"],
493
- ["coral", "#ff7f50"],
494
- ["cornflowerblue", "#6495ed"],
495
- ["cornsilk", "#fff8dc"],
496
- ["crimson", "#dc143c"],
497
- ["cyan", "#00ffff"],
498
- ["darkblue", "#00008b"],
499
- ["darkcyan", "#008b8b"],
500
- ["darkgoldenrod", "#b8860b"],
501
- ["darkgray", "#a9a9a9"],
502
- ["darkgreen", "#006400"],
503
- ["darkgrey", "#a9a9a9"],
504
- ["darkkhaki", "#bdb76b"],
505
- ["darkmagenta", "#8b008b"],
506
- ["darkolivegreen", "#556b2f"],
507
- ["darkorange", "#ff8c00"],
508
- ["darkorchid", "#9932cc"],
509
- ["darkred", "#8b0000"],
510
- ["darksalmon", "#e9967a"],
511
- ["darkseagreen", "#8fbc8f"],
512
- ["darkslateblue", "#483d8b"],
513
- ["darkslategray", "#2f4f4f"],
514
- ["darkslategrey", "#2f4f4f"],
515
- ["darkturquoise", "#00ced1"],
516
- ["darkviolet", "#9400d3"],
517
- ["deeppink", "#ff1493"],
518
- ["deepskyblue", "#00bfff"],
519
- ["dimgray", "#696969"],
520
- ["dimgrey", "#696969"],
521
- ["dodgerblue", "#1e90ff"],
522
- ["firebrick", "#b22222"],
523
- ["floralwhite", "#fffaf0"],
524
- ["forestgreen", "#228b22"],
525
- ["fuchsia", "#ff00ff"],
526
- ["gainsboro", "#dcdcdc"],
527
- ["ghostwhite", "#f8f8ff"],
528
- ["gold", "#ffd700"],
529
- ["goldenrod", "#daa520"],
530
- ["gray", "#808080"],
531
- ["green", "#008000"],
532
- ["greenyellow", "#adff2f"],
533
- ["grey", "#808080"],
534
- ["honeydew", "#f0fff0"],
535
- ["hotpink", "#ff69b4"],
536
- ["indianred", "#cd5c5c"],
537
- ["indigo", "#4b0082"],
538
- ["ivory", "#fffff0"],
539
- ["khaki", "#f0e68c"],
540
- ["lavender", "#e6e6fa"],
541
- ["lavenderblush", "#fff0f5"],
542
- ["lawngreen", "#7cfc00"],
543
- ["lemonchiffon", "#fffacd"],
544
- ["lightblue", "#add8e6"],
545
- ["lightcoral", "#f08080"],
546
- ["lightcyan", "#e0ffff"],
547
- ["lightgoldenrodyellow", "#fafad2"],
548
- ["lightgray", "#d3d3d3"],
549
- ["lightgreen", "#90ee90"],
550
- ["lightgrey", "#d3d3d3"],
551
- ["lightpink", "#ffb6c1"],
552
- ["lightsalmon", "#ffa07a"],
553
- ["lightseagreen", "#20b2aa"],
554
- ["lightskyblue", "#87cefa"],
555
- ["lightslategray", "#778899"],
556
- ["lightslategrey", "#778899"],
557
- ["lightsteelblue", "#b0c4de"],
558
- ["lightyellow", "#ffffe0"],
559
- ["lime", "#00ff00"],
560
- ["limegreen", "#32cd32"],
561
- ["linen", "#faf0e6"],
562
- ["magenta", "#ff00ff"],
563
- ["maroon", "#800000"],
564
- ["mediumaquamarine", "#66cdaa"],
565
- ["mediumblue", "#0000cd"],
566
- ["mediumorchid", "#ba55d3"],
567
- ["mediumpurple", "#9370db"],
568
- ["mediumseagreen", "#3cb371"],
569
- ["mediumslateblue", "#7b68ee"],
570
- ["mediumspringgreen", "#00fa9a"],
571
- ["mediumturquoise", "#48d1cc"],
572
- ["mediumvioletred", "#c71585"],
573
- ["midnightblue", "#191970"],
574
- ["mintcream", "#f5fffa"],
575
- ["mistyrose", "#ffe4e1"],
576
- ["moccasin", "#ffe4b5"],
577
- ["navajowhite", "#ffdead"],
578
- ["navy", "#000080"],
579
- ["oldlace", "#fdf5e6"],
580
- ["olive", "#808000"],
581
- ["olivedrab", "#6b8e23"],
582
- ["orange", "#ffa500"],
583
- ["orangered", "#ff4500"],
584
- ["orchid", "#da70d6"],
585
- ["palegoldenrod", "#eee8aa"],
586
- ["palegreen", "#98fb98"],
587
- ["paleturquoise", "#afeeee"],
588
- ["palevioletred", "#db7093"],
589
- ["papayawhip", "#ffefd5"],
590
- ["peachpuff", "#ffdab9"],
591
- ["peru", "#cd853f"],
592
- ["pink", "#ffc0cb"],
593
- ["plum", "#dda0dd"],
594
- ["powderblue", "#b0e0e6"],
595
- ["purple", "#800080"],
596
- ["rebeccapurple", "#663399"],
597
- ["red", "#ff0000"],
598
- ["rosybrown", "#bc8f8f"],
599
- ["royalblue", "#4169e1"],
600
- ["saddlebrown", "#8b4513"],
601
- ["salmon", "#fa8072"],
602
- ["sandybrown", "#f4a460"],
603
- ["seagreen", "#2e8b57"],
604
- ["seashell", "#fff5ee"],
605
- ["sienna", "#a0522d"],
606
- ["silver", "#c0c0c0"],
607
- ["skyblue", "#87ceeb"],
608
- ["slateblue", "#6a5acd"],
609
- ["slategray", "#708090"],
610
- ["slategrey", "#708090"],
611
- ["snow", "#fffafa"],
612
- ["springgreen", "#00ff7f"],
613
- ["steelblue", "#4682b4"],
614
- ["tan", "#d2b48c"],
615
- ["teal", "#008080"],
616
- ["thistle", "#d8bfd8"],
617
- ["tomato", "#ff6347"],
618
- ["turquoise", "#40e0d0"],
619
- ["violet", "#ee82ee"],
620
- ["wheat", "#f5deb3"],
621
- ["white", "#ffffff"],
622
- ["whitesmoke", "#f5f5f5"],
623
- ["yellow", "#ffff00"],
624
- ["yellowgreen", "#9acd32"]
625
- ]);
626
- return _namedColorHex;
371
+ const names = "aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple rebeccapurple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet wheat white whitesmoke yellow yellowgreen".split(" ");
372
+ const hex = "f0f8fffaebd700ffff7fffd4f0fffff5f5dcffe4c4000000ffebcd0000ff8a2be2a52a2adeb8875f9ea07fff00d2691eff7f506495edfff8dcdc143c00ffff00008b008b8bb8860ba9a9a9006400a9a9a9bdb76b8b008b556b2fff8c009932cc8b0000e9967a8fbc8f483d8b2f4f4f2f4f4f00ced19400d3ff149300bfff6969696969691e90ffb22222fffaf0228b22ff00ffdcdcdcf8f8ffffd700daa520808080008000adff2f808080f0fff0ff69b4cd5c5c4b0082fffff0f0e68ce6e6fafff0f57cfc00fffacdadd8e6f08080e0fffffafad2d3d3d390ee90d3d3d3ffb6c1ffa07a20b2aa87cefa778899778899b0c4deffffe000ff0032cd32faf0e6ff00ff80000066cdaa0000cdba55d39370db3cb3717b68ee00fa9a48d1ccc71585191970f5fffaffe4e1ffe4b5ffdead000080fdf5e68080006b8e23ffa500ff4500da70d6eee8aa98fb98afeeeedb7093ffefd5ffdab9cd853fffc0cbdda0ddb0e0e6800080663399ff0000bc8f8f4169e18b4513fa8072f4a4602e8b57fff5eea0522dc0c0c087ceeb6a5acd708090708090fffafa00ff7f4682b4d2b48c008080d8bfd8ff634740e0d0ee82eef5deb3fffffff5f5f5ffff009acd32";
373
+ const colors = /* @__PURE__ */ new Map();
374
+ for (let i = 0; i < names.length; i++) colors.set(names[i], `#${hex.slice(i * 6, i * 6 + 6)}`);
375
+ return _namedColorHex = colors;
627
376
  }
628
- /**
629
- * Convert hex color string to `rgb()` CSS string.
630
- * Supports 3, 4, 6, and 8 character hex values (with or without `#`).
631
- */
632
377
  function hexToRgb(hex) {
633
378
  const matched = hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (_m, r, g, b) => "#" + r + r + g + g + b + b).substring(1).match(/.{2}/g);
634
379
  if (!matched) return null;
@@ -637,13 +382,6 @@ function hexToRgb(hex) {
637
382
  if (rgba.length >= 3) return `rgb(${rgba.slice(0, 3).join(" ")}${rgba.length > 3 ? ` / ${rgba[3]}` : ""})`;
638
383
  return null;
639
384
  }
640
- /**
641
- * Extract RGB values from an `rgb()`/`rgba()` string.
642
- * Supports comma-separated, space-separated, fractional, percentage,
643
- * and slash alpha notation.
644
- *
645
- * @returns Array of RGB values (0-255 range), converting percentages as needed.
646
- */
647
385
  function getRgbValuesFromRgbaString(str) {
648
386
  const match = str.match(/rgba?\(([^)]+)\)/i);
649
387
  if (!match) return [];
@@ -654,11 +392,6 @@ function getRgbValuesFromRgbaString(str) {
654
392
  return parseFloat(part);
655
393
  });
656
394
  }
657
- /**
658
- * Convert any recognized color string to an `rgb()` CSS string.
659
- * Handles hex, `okhsl()`, `okhst()`, `hsl()`/`hsla()`, named CSS colors,
660
- * and `rgb()`/`rgba()` pass-through.
661
- */
662
395
  function strToRgb(color, _ignoreAlpha = false) {
663
396
  if (!color) return void 0;
664
397
  if (color.startsWith("rgb")) return color;
@@ -669,11 +402,6 @@ function strToRgb(color, _ignoreAlpha = false) {
669
402
  if (namedHex) return hexToRgb(namedHex);
670
403
  return null;
671
404
  }
672
- /**
673
- * Convert an HSL/HSLA color string to an `rgb()`/`rgba()` CSS string.
674
- * Supports modern space-separated and legacy comma-separated syntax,
675
- * deg/turn/rad hue units, and slash alpha notation.
676
- */
677
405
  function hslStringToRgb(hslStr) {
678
406
  const match = hslStr.match(/hsla?\(([^)]+)\)/i);
679
407
  if (!match) return null;
@@ -699,10 +427,6 @@ function hslStringToRgb(hslStr) {
699
427
  }
700
428
  return `rgb(${Math.round(r)} ${Math.round(g)} ${Math.round(b)})`;
701
429
  }
702
- /**
703
- * Convert an `oklch()` color string to an `rgb()`/`rgba()` CSS string.
704
- * Supports deg/turn/rad hue units and percentage lightness.
705
- */
706
430
  function oklchStringToRgb(oklchStr) {
707
431
  const match = oklchStr.match(/oklch\(([^)]+)\)/i);
708
432
  if (!match) return null;
@@ -729,62 +453,13 @@ function oklchStringToRgb(oklchStr) {
729
453
  }
730
454
  //#endregion
731
455
  //#region src/utils/color-space.ts
732
- /**
733
- * Set the alpha of a whole color, replacing any it already carries.
734
- *
735
- * CSS relative color syntax is how opacity is applied to every color Tasty
736
- * emits. `oklch(from <color> l c h / <alpha>)` copies the channels over and
737
- * writes the alpha slot, which needs nothing from the color except that it *is*
738
- * a color: a `color-mix()`, a `light-dark()`, a `currentcolor`, a
739
- * `--name-color` written by hand-authored CSS that Tasty never defined — all of
740
- * them work, where writing into a channel slot directly would require channels
741
- * the engine has no way to compute.
742
- *
743
- * Alpha is *replaced*, not composed. A token holding `rgb(255 0 0 / .8)` faded
744
- * to `.5` is alpha `.5`. `color-mix()` against `transparent` cannot do this —
745
- * it would multiply the two to `.4`.
746
- *
747
- * The alpha slot takes a `<number>` or a `<percentage>`, so an opacity custom
748
- * property passes straight through in whichever form the author declared it.
749
- *
750
- * The space is always `oklch`, regardless of the configured {@link ColorSpace}:
751
- * it is unbounded, so a wide-gamut color survives the round trip that a
752
- * gamut-limited space would clamp, and it is the space the computed value used
753
- * to be reported in. Channels are copied rather than interpolated, so the polar
754
- * form costs nothing even for an achromatic color, whose hue is carried through
755
- * untouched.
756
- */
757
456
  function overrideColorAlpha(color, alpha) {
758
457
  return `oklch(from ${color} l c h / ${alpha})`;
759
458
  }
760
- /**
761
- * Compose an alpha onto a color, multiplying with any it already carries.
762
- *
763
- * This is the counterpart to {@link overrideColorAlpha}, and the difference is
764
- * the point. A design token names a color, so fading it *sets* its alpha. But
765
- * `currentcolor` is the color an element **inherits**, which an ancestor may
766
- * already have faded — `#current.4` there means "40% of what reaches me", and a
767
- * nested `#current.18` under it composes to `.072`. Design systems build ramps
768
- * out of exactly that, so `#current` composes and a token replaces.
769
- *
770
- * `color-mix()` against `transparent` is what composes: mixing premultiplied
771
- * leaves the channels alone and multiplies the alphas. Its percentage slot takes
772
- * no `<number>`, so a `$prop` alpha has to be scaled — which is why an opacity
773
- * property used as `#current.$prop` has to hold a unitless number, where a token
774
- * accepts either form.
775
- */
776
459
  function mixColorAlpha(color, percentage) {
777
460
  return `color-mix(in oklab, ${color} ${percentage}, transparent)`;
778
461
  }
779
- /**
780
- * Matches what {@link overrideColorAlpha} builds. The first group is greedy so a
781
- * nested override splits on its outermost layer.
782
- */
783
462
  const RE_ALPHA_OVERRIDE = /^oklch\(from (.+) l c h \/ (.+)\)$/;
784
- /**
785
- * Split what {@link overrideColorAlpha} builds back into the color it faded and
786
- * the alpha, or `null` when the value is not one of those.
787
- */
788
463
  function parseAlphaOverride(value) {
789
464
  const match = value.match(RE_ALPHA_OVERRIDE);
790
465
  return match ? {
@@ -810,49 +485,16 @@ const makeEmptyDetails = () => ({
810
485
  all: [],
811
486
  parts: []
812
487
  });
813
- const finalizePart = (p) => {
814
- p.output = p.all.join(" ");
815
- return p;
816
- };
817
- /**
818
- * Aggregate parts into a StyleDetails group.
819
- * Combines all parts' arrays into group-level arrays for backward compatibility.
820
- */
821
- const finalizeGroup = (d, parts) => {
822
- d.parts = parts;
823
- for (const part of parts) {
824
- d.mods.push(...part.mods);
825
- d.values.push(...part.values);
826
- d.colors.push(...part.colors);
827
- d.all.push(...part.all);
828
- }
829
- d.output = parts.map((p) => p.output).join(" / ");
830
- return d;
831
- };
832
488
  //#endregion
833
489
  //#region src/parser/classify.ts
834
- /**
835
- * Convert an opacity suffix to the alpha value it denotes.
836
- *
837
- * The authored digits are kept verbatim — `.07` stays `.07` rather than being
838
- * multiplied into `7.000000000000001%` — and a `$prop` suffix passes the
839
- * reference straight through, so it works whether the property holds a
840
- * `<number>` or a `<percentage>`. Both are what the alpha slot accepts.
841
- */
842
490
  function alphaSuffixToAlpha(rawAlpha) {
843
491
  if (rawAlpha.startsWith("$")) return `var(--${rawAlpha.slice(1)})`;
844
492
  if (rawAlpha === "0") return "0";
845
493
  return `.${rawAlpha}`;
846
494
  }
847
- /** Apply an opacity suffix to a color, replacing any alpha it already carries. */
848
495
  function fadeColor(color, rawAlpha) {
849
496
  return overrideColorAlpha(color, alphaSuffixToAlpha(rawAlpha));
850
497
  }
851
- /**
852
- * Convert an opacity suffix to the percentage `color-mix()` needs, by shifting
853
- * the decimal point rather than multiplying: `.07` is `7%`, not the
854
- * `7.000000000000001%` that `parseFloat('.07') * 100` produces.
855
- */
856
498
  function alphaSuffixToPercentage(rawAlpha) {
857
499
  if (rawAlpha.startsWith("$")) return `calc(var(--${rawAlpha.slice(1)}) * 100%)`;
858
500
  if (rawAlpha === "0") return "0%";
@@ -861,28 +503,13 @@ function alphaSuffixToPercentage(rawAlpha) {
861
503
  const fraction = digits.slice(2);
862
504
  return `${fraction ? `${whole}.${fraction}` : whole}%`;
863
505
  }
864
- /**
865
- * Apply an opacity suffix to `currentcolor`, composing with any alpha an
866
- * ancestor already applied. See {@link mixColorAlpha} for why this differs from
867
- * how a token is faded.
868
- */
869
506
  function fadeCurrentColor(rawAlpha) {
870
507
  return mixColorAlpha("currentcolor", alphaSuffixToPercentage(rawAlpha));
871
508
  }
872
- /**
873
- * Whether parsed function arguments hold a color. Colors reach either the color
874
- * bucket (`#token`, a nested color function, `transparent`) or — for the CSS
875
- * named colors, which the parser has no token syntax for — the modifier bucket.
876
- */
877
509
  function hasColorArgs(parsed) {
878
510
  const namedColors = getNamedColorHex();
879
511
  return parsed.groups.some((group) => group.colors.length > 0 || group.mods.some((mod) => namedColors.has(mod)));
880
512
  }
881
- /**
882
- * Re-parses a value through the parser until it stabilizes (no changes)
883
- * or max iterations reached. This allows units to reference other units.
884
- * Example: { x: '8px', y: '2x' } -> '1y' resolves to '16px'
885
- */
886
513
  function resolveUntilStable(value, opts, recurse, maxIterations = 10) {
887
514
  let current = value;
888
515
  for (let i = 0; i < maxIterations; i++) {
@@ -902,7 +529,7 @@ function classify(raw, opts, recurse) {
902
529
  bucket: 2,
903
530
  processed: ""
904
531
  };
905
- {
532
+ if (token.includes("(")) {
906
533
  let depth = 0;
907
534
  let inQuote = 0;
908
535
  for (let i = 0; i < token.length; i++) {
@@ -916,7 +543,7 @@ function classify(raw, opts, recurse) {
916
543
  continue;
917
544
  }
918
545
  if (ch === "(") depth++;
919
- else if (ch === ")") depth = Math.max(0, depth - 1);
546
+ else if (ch === ")" && depth) depth--;
920
547
  }
921
548
  if (depth !== 0) {
922
549
  console.warn("[Tasty] skipped invalid function token with unmatched parentheses:", token);
@@ -1212,15 +839,6 @@ function classify(raw, opts, recurse) {
1212
839
  }
1213
840
  //#endregion
1214
841
  //#region src/parser/lru.ts
1215
- /**
1216
- * Doubly-linked-list LRU.
1217
- *
1218
- * The list holds direct node references rather than keys, so rewiring on a
1219
- * `get()` of a non-MRU entry is pure pointer work. Storing keys instead cost
1220
- * three extra `Map.get()` lookups per read (prev, next and the current head),
1221
- * which is measurable on these read-mostly caches: they are hit on every
1222
- * render once the style pipeline is warm.
1223
- */
1224
842
  var Lru = class {
1225
843
  limit;
1226
844
  map = /* @__PURE__ */ new Map();
@@ -1305,7 +923,6 @@ var Lru = class {
1305
923
  const isWhitespace = (ch) => ch === " " || ch === "\n" || ch === " " || ch === "\r" || ch === "\f";
1306
924
  function scan(src, cb) {
1307
925
  let depth = 0;
1308
- let inUrl = false;
1309
926
  let inQuote = 0;
1310
927
  let start = 0;
1311
928
  let i = 0;
@@ -1313,11 +930,9 @@ function scan(src, cb) {
1313
930
  const flush = (isComma, isSlash) => {
1314
931
  const actualSlash = isSlash || pendingSlash;
1315
932
  pendingSlash = false;
1316
- if (start < i) {
1317
- const prevChar = start > 0 ? src[start - 1] : null;
1318
- cb(src.slice(start, i), isComma, actualSlash, prevChar);
1319
- } else if (isComma) cb("", true, false, null);
1320
- else if (actualSlash) cb("", false, true, null);
933
+ if (start < i) cb(src.slice(start, i), isComma, actualSlash);
934
+ else if (isComma) cb("", true, false);
935
+ else if (actualSlash) cb("", false, true);
1321
936
  start = i + 1;
1322
937
  };
1323
938
  for (; i < src.length; i++) {
@@ -1331,18 +946,13 @@ function scan(src, cb) {
1331
946
  continue;
1332
947
  }
1333
948
  if (ch === "(") {
1334
- if (!depth) {
1335
- if (src.slice(Math.max(0, i - 3), i + 1) === "url(") inUrl = true;
1336
- }
1337
949
  depth++;
1338
950
  continue;
1339
951
  }
1340
952
  if (ch === ")") {
1341
- depth = Math.max(0, depth - 1);
1342
- if (inUrl && depth === 0) inUrl = false;
953
+ if (depth) depth--;
1343
954
  continue;
1344
955
  }
1345
- if (inUrl) continue;
1346
956
  if (!depth) {
1347
957
  if (ch === ",") {
1348
958
  flush(true, false);
@@ -1386,14 +996,9 @@ var StyleParser = class {
1386
996
  let parts = [];
1387
997
  const pushToken = (bucket, processed) => {
1388
998
  if (!processed) return;
1389
- const mergeIntoPrevUrl = () => {
1390
- const lastIdx = currentPart.values.length - 1;
1391
- currentPart.values[lastIdx] += ` ${processed}`;
1392
- const lastAllIdx = currentPart.all.length - 1;
1393
- currentPart.all[lastAllIdx] += ` ${processed}`;
1394
- };
1395
999
  if (currentPart.values.length > 0 && currentPart.values[currentPart.values.length - 1].startsWith("url(")) {
1396
- mergeIntoPrevUrl();
1000
+ currentPart.values[currentPart.values.length - 1] += ` ${processed}`;
1001
+ currentPart.all[currentPart.all.length - 1] += ` ${processed}`;
1397
1002
  return;
1398
1003
  }
1399
1004
  switch (bucket) {
@@ -1413,26 +1018,31 @@ var StyleParser = class {
1413
1018
  }
1414
1019
  currentPart.all.push(processed);
1415
1020
  };
1416
- const endPart = () => {
1021
+ const endPart = (reset = true) => {
1417
1022
  if (currentPart.all.length > 0) {
1418
- finalizePart(currentPart);
1023
+ currentPart.output = currentPart.all.join(" ");
1419
1024
  parts.push(currentPart);
1420
1025
  }
1421
- currentPart = makeEmptyPart();
1026
+ if (reset) currentPart = makeEmptyPart();
1422
1027
  };
1423
- const endGroup = () => {
1424
- endPart();
1425
- if (parts.length === 0) {
1426
- parts.push(makeEmptyPart());
1427
- finalizePart(parts[0]);
1028
+ const endGroup = (reset = true) => {
1029
+ endPart(reset);
1030
+ if (parts.length === 0) parts.push(makeEmptyPart());
1031
+ currentGroup.parts = parts;
1032
+ for (const part of parts) {
1033
+ currentGroup.mods.push(...part.mods);
1034
+ currentGroup.values.push(...part.values);
1035
+ currentGroup.colors.push(...part.colors);
1036
+ currentGroup.all.push(...part.all);
1428
1037
  }
1429
- finalizeGroup(currentGroup, parts);
1038
+ currentGroup.output = parts.length === 1 ? parts[0].output : parts.map((part) => part.output).join(" / ");
1430
1039
  groups.push(currentGroup);
1431
- currentGroup = makeEmptyDetails();
1432
- parts = [];
1433
- currentPart = makeEmptyPart();
1040
+ if (reset) {
1041
+ currentGroup = makeEmptyDetails();
1042
+ parts = [];
1043
+ }
1434
1044
  };
1435
- scan(stripped, (tok, isComma, isSlash, _prevChar) => {
1045
+ scan(stripped, (tok, isComma, isSlash) => {
1436
1046
  if (tok) {
1437
1047
  if (currentGroup.input) currentGroup.input += ` ${tok}`;
1438
1048
  else currentGroup.input = tok;
@@ -1442,9 +1052,9 @@ var StyleParser = class {
1442
1052
  if (isSlash) endPart();
1443
1053
  if (isComma) endGroup();
1444
1054
  });
1445
- if (currentPart.all.length || parts.length || !groups.length) endGroup();
1055
+ if (currentPart.all.length || parts.length || !groups.length) endGroup(false);
1446
1056
  const result = {
1447
- output: groups.map((g) => g.output).join(", "),
1057
+ output: groups.length === 1 ? groups[0].output : groups.map((group) => group.output).join(", "),
1448
1058
  groups
1449
1059
  };
1450
1060
  Object.freeze(result);
@@ -1464,17 +1074,9 @@ var StyleParser = class {
1464
1074
  if (patch.cacheSize) this.cache = new Lru(patch.cacheSize);
1465
1075
  else this.cache.clear();
1466
1076
  }
1467
- /**
1468
- * Clear the parser cache.
1469
- * Call this when external state that affects parsing results has changed
1470
- * (e.g., predefined tokens).
1471
- */
1472
1077
  clearCache() {
1473
1078
  this.cache.clear();
1474
1079
  }
1475
- /**
1476
- * Get the current units configuration.
1477
- */
1478
1080
  getUnits() {
1479
1081
  return this.opts.units;
1480
1082
  }
@@ -1482,10 +1084,6 @@ var StyleParser = class {
1482
1084
  //#endregion
1483
1085
  //#region src/plugins/color-func.ts
1484
1086
  const clamp = (value, min, max) => Math.max(Math.min(value, max), min);
1485
- /**
1486
- * Parse an angle value with optional unit.
1487
- * Supports: deg, turn, rad, or unitless (treated as degrees).
1488
- */
1489
1087
  const parseAngle = (value) => {
1490
1088
  const match = value.match(/^([+-]?\d*\.?\d+)(deg|turn|rad)?$/);
1491
1089
  if (!match) return 0;
@@ -1496,31 +1094,12 @@ const parseAngle = (value) => {
1496
1094
  default: return num;
1497
1095
  }
1498
1096
  };
1499
- /**
1500
- * Parse a percentage value (e.g., "50%") to a 0-1 range. A unitless number is
1501
- * read as the factor it already looks like, so `okhsl(280 .8 .52)` and
1502
- * `okhsl(280 80% 52%)` are the same color.
1503
- */
1504
1097
  const parsePercentage = (value) => {
1505
1098
  const match = value.match(/^([+-]?\d*\.?\d+)%?$/);
1506
1099
  if (!match) return 0;
1507
1100
  const num = parseFloat(match[1]);
1508
1101
  return value.includes("%") ? num / 100 : num;
1509
1102
  };
1510
- /**
1511
- * Creates a color function handler for the tasty parser.
1512
- *
1513
- * A color function is a custom `functions` entry that converts its arguments
1514
- * to an `rgb(...)` string (an already-supported color), so it needs no special
1515
- * core integration — registering it as a parse function is enough.
1516
- *
1517
- * @param name The name of the color function (e.g., 'okhsl', 'okhst')
1518
- * @param convert Converts the parsed first three channel values (after angle/
1519
- * percent normalization) to sRGB `[r, g, b]` in the 0-1 range
1520
- * @param label Optional diagnostic label shown in dev warnings when the wrong
1521
- * number of arguments is supplied (e.g., 'H S L'). Has no effect on parsing
1522
- * or output.
1523
- */
1524
1103
  function createColorFunc(name, convert, label) {
1525
1104
  const conversionCache = new Lru(500);
1526
1105
  const expected = label ? ` (${label})` : "";
@@ -1552,124 +1131,26 @@ function createColorFunc(name, convert, label) {
1552
1131
  }
1553
1132
  //#endregion
1554
1133
  //#region src/plugins/okhsl-plugin.ts
1555
- /**
1556
- * OKHSL Plugin for Tasty
1557
- *
1558
- * Converts OKHSL color syntax to RGB notation.
1559
- * Supports angle units: deg, turn, rad, or unitless (degrees).
1560
- *
1561
- * Examples:
1562
- * okhsl(240.5 50% 50%)
1563
- * okhsl(240.5deg 50% 50%)
1564
- * okhsl(0.25turn 50% 50%)
1565
- * okhsl(1.57rad 50% 50%)
1566
- */
1567
- /**
1568
- * The okhsl function handler for tasty parser.
1569
- * Receives parsed style groups and returns an RGB color string.
1570
- */
1571
1134
  const okhslFunction = createColorFunc("okhsl", okhslToSrgb, "H S L");
1572
- /**
1573
- * OKHSL Plugin for Tasty.
1574
- *
1575
- * Adds support for the `okhsl()` color function in tasty styles.
1576
- *
1577
- * @example
1578
- * ```ts
1579
- * import { configure } from '@tenphi/tasty';
1580
- * import { okhslPlugin } from '@tenphi/tasty';
1581
- *
1582
- * configure({
1583
- * plugins: [okhslPlugin()],
1584
- * });
1585
- *
1586
- * // Now you can use okhsl in styles:
1587
- * const Box = tasty({
1588
- * styles: {
1589
- * fill: 'okhsl(240 50% 50%)',
1590
- * },
1591
- * });
1592
- * ```
1593
- */
1594
1135
  const okhslPlugin = () => ({
1595
1136
  name: "okhsl",
1596
1137
  functions: { okhsl: okhslFunction }
1597
1138
  });
1598
1139
  //#endregion
1599
1140
  //#region src/plugins/okhst-plugin.ts
1600
- /**
1601
- * OKHST Plugin for Tasty
1602
- *
1603
- * Converts OKHST color syntax to RGB notation.
1604
- * OKHST is OKHSL with the lightness axis replaced by a contrast-uniform tone axis.
1605
- * Supports angle units: deg, turn, rad, or unitless (degrees).
1606
- *
1607
- * Examples:
1608
- * okhst(240.5 50% 50%)
1609
- * okhst(240.5deg 50% 50%)
1610
- * okhst(0.25turn 50% 50%)
1611
- * okhst(1.57rad 50% 50%)
1612
- */
1613
- /**
1614
- * The okhst function handler for tasty parser.
1615
- * Receives parsed style groups and returns an RGB color string.
1616
- */
1617
1141
  const okhstFunction = createColorFunc("okhst", okhstToSrgb, "H S T");
1618
- /**
1619
- * OKHST Plugin for Tasty.
1620
- *
1621
- * Adds support for the `okhst()` color function in tasty styles.
1622
- *
1623
- * @example
1624
- * ```ts
1625
- * import { configure } from '@tenphi/tasty';
1626
- * import { okhstPlugin } from '@tenphi/tasty';
1627
- *
1628
- * configure({
1629
- * plugins: [okhstPlugin()],
1630
- * });
1631
- *
1632
- * // Now you can use okhst in styles:
1633
- * const Box = tasty({
1634
- * styles: {
1635
- * fill: 'okhst(240 50% 50%)',
1636
- * },
1637
- * });
1638
- * ```
1639
- */
1640
1142
  const okhstPlugin = () => ({
1641
1143
  name: "okhst",
1642
1144
  functions: { okhst: okhstFunction }
1643
1145
  });
1644
1146
  //#endregion
1645
1147
  //#region src/plugins/defaults.ts
1646
- /**
1647
- * Register the default color functions (okhsl, okhst) with the global parser.
1648
- *
1649
- * They are ordinary `functions` entries — the same mechanism any third-party
1650
- * color plugin uses — so they need no special-casing in core.
1651
- *
1652
- * Idempotent and safe to call from the lazy parser initializer so that
1653
- * zero-config usage keeps working. `resetGlobalParseFunctions()` re-invokes it
1654
- * after clearing user-registered functions so the defaults survive a config reset.
1655
- *
1656
- * @internal
1657
- */
1658
1148
  function registerDefaultFunctions() {
1659
1149
  customFunction("okhsl", okhslFunction);
1660
1150
  customFunction("okhst", okhstFunction);
1661
1151
  }
1662
1152
  //#endregion
1663
1153
  //#region src/utils/styles.ts
1664
- /**
1665
- * Normalize a color token value.
1666
- * - Boolean `true` is converted to `'transparent'`
1667
- * - Boolean `false` returns `null` (signals the token should be skipped)
1668
- * - Other values are returned as-is
1669
- *
1670
- * @param value - The raw token value
1671
- * @returns Normalized value or null if the token should be skipped
1672
- */
1673
1154
  function normalizeColorTokenValue(value) {
1674
1155
  if (value === true) return "transparent";
1675
1156
  if (value === false) return null;
@@ -1734,60 +1215,22 @@ function getOrCreateParser() {
1734
1215
  return __tastyParser;
1735
1216
  }
1736
1217
  const __tastyParseFunctions = {};
1737
- /**
1738
- * Register a parse-time function.
1739
- *
1740
- * @internal Use `configure({ functions })`. This bypasses the configuration lock
1741
- * and is kept only for the lazy default-function bootstrap and the `@function`
1742
- * polyfill, both of which must register after `configure()` has run.
1743
- */
1744
1218
  function customFunction(name, fn) {
1745
1219
  __tastyParseFunctions[name] = fn;
1746
1220
  getOrCreateParser().setFunctions(__tastyParseFunctions);
1747
1221
  }
1748
- /**
1749
- * Reset parse functions back to the built-in set (okhsl/okhst).
1750
- *
1751
- * @internal Called by `resetConfig()`.
1752
- */
1753
1222
  function resetGlobalParseFunctions() {
1754
1223
  for (const key of Object.keys(__tastyParseFunctions)) delete __tastyParseFunctions[key];
1755
1224
  registerDefaultFunctions();
1756
1225
  getOrCreateParser().setFunctions(__tastyParseFunctions);
1757
1226
  }
1758
- /**
1759
- * Get the global StyleParser instance.
1760
- * Used by configure() to apply parser configuration.
1761
- */
1762
1227
  function getGlobalParser() {
1763
1228
  return getOrCreateParser();
1764
1229
  }
1765
- /**
1766
- * Get the current custom functions registry.
1767
- * Used by configure() to merge with new functions.
1768
- */
1769
- /**
1770
- * The live parse-function registry.
1771
- *
1772
- * @internal Returns the mutable internal map; writing to it bypasses the
1773
- * parser's cache invalidation, so the write silently does not take effect.
1774
- * Read-only, internal use.
1775
- */
1776
1230
  function getGlobalParseFunctions() {
1777
1231
  return __tastyParseFunctions;
1778
1232
  }
1779
- /**
1780
- * Storage for predefined tokens that are replaced during style parsing.
1781
- * Keys are token names (with $ or # prefix), values are pre-processed CSS values.
1782
- */
1783
1233
  let __globalPredefinedTokens = null;
1784
- /**
1785
- * Set global predefined tokens.
1786
- * Called from configure() after processing token values.
1787
- * Merges with existing tokens (new tokens override existing ones with same key).
1788
- * Keys are normalized to lowercase (parser lowercases input before classification).
1789
- * @internal
1790
- */
1791
1234
  function setGlobalPredefinedTokens(tokens) {
1792
1235
  const normalizedTokens = {};
1793
1236
  for (const [key, value] of Object.entries(tokens)) {
@@ -1805,28 +1248,13 @@ function setGlobalPredefinedTokens(tokens) {
1805
1248
  } : normalizedTokens;
1806
1249
  getOrCreateParser().clearCache();
1807
1250
  }
1808
- /**
1809
- * Get the current global predefined tokens.
1810
- * Returns null if no tokens are configured.
1811
- */
1812
1251
  function getGlobalPredefinedTokens() {
1813
1252
  return __globalPredefinedTokens;
1814
1253
  }
1815
- /**
1816
- * Reset global predefined tokens.
1817
- * Used for testing.
1818
- * @internal
1819
- */
1820
1254
  function resetGlobalPredefinedTokens() {
1821
1255
  __globalPredefinedTokens = null;
1822
1256
  getOrCreateParser().clearCache();
1823
1257
  }
1824
- /**
1825
- *
1826
- * @param {String} value
1827
- * @param {Number} mode
1828
- * @returns {Object<String,String|Array>}
1829
- */
1830
1258
  function parseStyle(value) {
1831
1259
  let str;
1832
1260
  if (typeof value === "string") str = value;
@@ -1834,32 +1262,11 @@ function parseStyle(value) {
1834
1262
  else str = "";
1835
1263
  return getOrCreateParser().process(str);
1836
1264
  }
1837
- /** A `$`-prefixed custom-property reference — the only DSL syntax that starts with `$`. */
1838
1265
  const RE_CUSTOM_PROPERTY_REF = /\$[a-zA-Z_$]/;
1839
- /**
1840
- * Substitute custom-property references (`$ident` → `var(--ident)`) inside a
1841
- * value a handler would otherwise emit to CSS verbatim.
1842
- *
1843
- * Handlers for keyword-valued properties (`display`, `align`, `text-transform`,
1844
- * `overflow`, …) pass their input straight through, since there are no units or
1845
- * color tokens to resolve. That leaked the raw DSL into the stylesheet:
1846
- * `display: '$my-display'` emitted `display: $my-display`, which the browser
1847
- * drops as invalid. The same applies to color props whose value the parser could
1848
- * not classify as a color — `$ident` is a color only when the name ends with
1849
- * `-color`, so `fill: '$my-fill'` fell back to the unparsed input.
1850
- *
1851
- * Values without a `$` skip the parser entirely, so pass-through behaviour (and
1852
- * the parser's case folding) is unchanged for every value that was already
1853
- * valid CSS.
1854
- */
1855
1266
  function resolveCustomProperties(value) {
1856
1267
  if (!RE_CUSTOM_PROPERTY_REF.test(value)) return value;
1857
1268
  return parseStyle(value).output || value;
1858
1269
  }
1859
- /**
1860
- * Parse color. Find it value, name and opacity.
1861
- * Optimized to avoid heavy parseStyle calls for simple color patterns.
1862
- */
1863
1270
  function parseColor(val, ignoreError = false) {
1864
1271
  if (typeof val !== "string") val = String(val ?? "");
1865
1272
  val = val.trim();
@@ -1901,7 +1308,9 @@ function parseColor(val, ignoreError = false) {
1901
1308
  };
1902
1309
  }
1903
1310
  function filterMods(mods, allowedMods) {
1904
- return mods.filter((mod) => allowedMods.includes(mod));
1311
+ const filtered = [];
1312
+ for (const mod of mods) if (allowedMods.includes(mod)) filtered.push(mod);
1313
+ return filtered;
1905
1314
  }
1906
1315
  const _innerCache = /* @__PURE__ */ new WeakMap();
1907
1316
  const _topLevelCache = /* @__PURE__ */ new WeakMap();
@@ -1942,20 +1351,6 @@ function stringifyStyles(styles) {
1942
1351
  //#region src/utils/function-color.ts
1943
1352
  const RE_FUNC_NAME = /^([a-z][a-z0-9-]*)\s*\(/i;
1944
1353
  const RE_COLOR_OUT = /^(?:rgb|hsl|hwb|lab|lch|oklab|oklch|color)\(|^#|^var\(--/i;
1945
- /**
1946
- * Resolve a `name(...)` value produced by a registered custom parse function
1947
- * into its concrete color output.
1948
- *
1949
- * A color function is just a `functions` entry whose output is an already
1950
- * supported color (`rgb`, `hsl`, `#…`, `oklch`, …). This helper delegates the
1951
- * value to the global parser (which already runs the registered parse function)
1952
- * and returns the result only when it looks like a color. Returns `null` when
1953
- * `str` is not a registered custom function or its output is not a color.
1954
- *
1955
- * This is the generic replacement for the previously hardcoded okhsl/okhst
1956
- * conversion branches scattered across `strToRgb`, `resolveToRgbaValues`, and
1957
- * the `#token.alpha` injection path.
1958
- */
1959
1354
  function resolveFunctionColor(str) {
1960
1355
  const m = RE_FUNC_NAME.exec(str);
1961
1356
  if (!m) return null;
@@ -1973,125 +1368,6 @@ function color(name, opacity = 1) {
1973
1368
  return `var(--${name}-color)`;
1974
1369
  }
1975
1370
  //#endregion
1976
- //#region src/utils/dotize.ts
1977
- const dotize = {
1978
- valTypes: {
1979
- none: "NONE",
1980
- primitive: "PRIM",
1981
- object: "OBJECT",
1982
- array: "ARRAY"
1983
- },
1984
- getValType: function(val) {
1985
- if (!val || typeof val != "object" || Array.isArray(val)) return dotize.valTypes.primitive;
1986
- if (typeof val == "object") return dotize.valTypes.object;
1987
- },
1988
- getPathType: function(arrPath) {
1989
- const arrPathTypes = [];
1990
- for (const path in arrPath) {
1991
- const pathVal = arrPath[path];
1992
- if (!pathVal) arrPathTypes.push(dotize.valTypes.none);
1993
- else if (dotize.isNumber(pathVal)) arrPathTypes.push(dotize.valTypes.array);
1994
- else arrPathTypes.push(dotize.valTypes.object);
1995
- }
1996
- return arrPathTypes;
1997
- },
1998
- isUndefined: function(obj) {
1999
- return typeof obj == "undefined";
2000
- },
2001
- isNumber: function(f) {
2002
- return !isNaN(parseInt(f));
2003
- },
2004
- isEmptyObj: function(obj) {
2005
- for (const prop in obj) if (Object.hasOwnProperty.call(obj, prop)) return false;
2006
- return JSON.stringify(obj) === JSON.stringify({});
2007
- },
2008
- isPlainObject: function(obj) {
2009
- if (typeof obj !== "object" || obj === null) return false;
2010
- return Object.getPrototypeOf(obj) === Object.prototype;
2011
- },
2012
- isNotObject: function(obj) {
2013
- return !obj || !this.isPlainObject(obj);
2014
- },
2015
- isEmptyArray: function(arr) {
2016
- return Array.isArray(arr) && arr.length == 0;
2017
- },
2018
- isNotArray: function(arr) {
2019
- return Array.isArray(arr) == false;
2020
- },
2021
- removeEmptyArrayItem: function(arr) {
2022
- return arr.filter(function(el) {
2023
- return el != null && el != "";
2024
- });
2025
- },
2026
- getFieldName: function(field, prefix, isRoot, isArrayItem, isArray) {
2027
- if (isArray) return (prefix ? prefix : "") + (dotize.isNumber(field) ? "[" + field + "]" : (isRoot && !prefix ? "" : ".") + field);
2028
- else if (isArrayItem) return (prefix ? prefix : "") + "[" + field + "]";
2029
- else return (prefix ? prefix + "." : "") + field;
2030
- },
2031
- startsWith: function(val, valToSearch) {
2032
- return val.indexOf(valToSearch) == 0;
2033
- },
2034
- convert: function(obj, prefix = "") {
2035
- let newObj = {};
2036
- if (dotize.isNotObject(obj)) if (prefix) {
2037
- newObj[prefix] = obj;
2038
- return newObj;
2039
- } else return obj;
2040
- return (function recurse(o, p, isRoot) {
2041
- const isArrayItem = Array.isArray(o);
2042
- for (const f in o) {
2043
- const currentProp = o[f];
2044
- if (currentProp && typeof currentProp === "object" && !Array.isArray(currentProp) && dotize.isPlainObject(currentProp)) {
2045
- if (isArrayItem && dotize.isEmptyObj(currentProp) == false) newObj = recurse(currentProp, dotize.getFieldName(f, p, isRoot, true));
2046
- else if (dotize.isEmptyObj(currentProp) == false) newObj = recurse(currentProp, dotize.getFieldName(f, p, isRoot));
2047
- else if (dotize.isEmptyObj(currentProp)) newObj[dotize.getFieldName(f, p, isRoot, isArrayItem)] = currentProp;
2048
- } else if (isArrayItem || dotize.isNumber(f)) newObj[dotize.getFieldName(f, p, isRoot, true)] = currentProp;
2049
- else newObj[dotize.getFieldName(f, p, isRoot)] = currentProp;
2050
- }
2051
- return newObj;
2052
- })(obj, prefix, true);
2053
- },
2054
- backward: function(obj, prefix) {
2055
- let newObj = {};
2056
- const arStartRegex = /\[(\d+)\]/g;
2057
- if (dotize.isNotObject(obj) && dotize.isNotArray(obj)) if (prefix) return obj[prefix];
2058
- else return obj;
2059
- for (let tProp in obj) {
2060
- const tPropVal = obj[tProp];
2061
- if (prefix) {
2062
- const prefixRegex = new RegExp("^" + prefix);
2063
- tProp = tProp.replace(prefixRegex, "");
2064
- }
2065
- tProp = tProp.replace(arStartRegex, ".$1");
2066
- if (dotize.startsWith(tProp, ".")) tProp = tProp.replace(/^\./, "");
2067
- const arrPath = tProp.split(".");
2068
- const arrPathTypes = dotize.getPathType(arrPath);
2069
- if (!dotize.isUndefined(arrPathTypes) && arrPathTypes[0] == dotize.valTypes.array && Array.isArray(newObj) == false) newObj = [];
2070
- (function recurse(rPropVal, rObj, rPropValPrev, rObjPrev) {
2071
- let currentPath = arrPath.shift();
2072
- const currentPathType = arrPathTypes.shift();
2073
- if (typeof currentPath == "undefined" || currentPath == "") {
2074
- newObj = rPropVal;
2075
- return;
2076
- }
2077
- const isArray = currentPathType == dotize.valTypes.array;
2078
- if (dotize.isNumber(currentPath)) currentPath = parseInt(currentPath);
2079
- if (arrPath.length > 0) {
2080
- if (typeof rObj[currentPath] == "undefined") if (isArray) rObj[currentPath] = [];
2081
- else rObj[currentPath] = {};
2082
- recurse(rPropVal, rObj[currentPath], currentPath, rObj);
2083
- return;
2084
- }
2085
- if (currentPathType == dotize.valTypes.array && rPropValPrev && rObjPrev) {
2086
- if (Array.isArray(rObjPrev[rPropValPrev]) == false) rObjPrev[rPropValPrev] = [];
2087
- rObjPrev[rPropValPrev].push(rPropVal);
2088
- } else rObj[currentPath] = rPropVal;
2089
- })(tPropVal, newObj);
2090
- }
2091
- return newObj;
2092
- }
2093
- };
2094
- //#endregion
2095
- export { hslToRgbValues as A, createColorFunc as C, getNamedColorHex as D, makeEmptyDetails as E, RE_NUMBER as F, RE_RAW_UNIT as I, normalizeDslName as M, toSnakeCase as N, getRgbValuesFromRgbaString as O, CSS_WIDE_KEYWORDS as P, okhslPlugin as S, Lru as T, setGlobalPredefinedTokens as _, DIRECTIONS as a, okhstPlugin as b, getGlobalParseFunctions as c, normalizeColorTokenValue as d, parseColor as f, resolveCustomProperties as g, resetGlobalPredefinedTokens as h, CUSTOM_UNITS as i, strToRgb as j, hexToRgb as k, getGlobalParser as l, resetGlobalParseFunctions as m, color as n, customFunction as o, parseStyle as p, resolveFunctionColor as r, filterMods as s, dotize as t, getGlobalPredefinedTokens as u, stringifyStyles as v, StyleParser as w, okhslFunction as x, okhstFunction as y };
1371
+ export { strToRgb as A, StyleParser as C, getRgbValuesFromRgbaString as D, getNamedColorHex as E, RE_RAW_UNIT as F, toSnakeCase as M, CSS_WIDE_KEYWORDS as N, hexToRgb as O, RE_NUMBER as P, createColorFunc as S, makeEmptyDetails as T, stringifyStyles as _, customFunction as a, okhslFunction as b, getGlobalParser as c, parseColor as d, parseStyle as f, setGlobalPredefinedTokens as g, resolveCustomProperties as h, DIRECTIONS as i, normalizeDslName as j, hslToRgbValues as k, getGlobalPredefinedTokens as l, resetGlobalPredefinedTokens as m, resolveFunctionColor as n, filterMods as o, resetGlobalParseFunctions as p, CUSTOM_UNITS as r, getGlobalParseFunctions as s, color as t, normalizeColorTokenValue as u, okhstFunction as v, Lru as w, okhslPlugin as x, okhstPlugin as y };
2096
1372
 
2097
- //# sourceMappingURL=dsl-CXvoaLnj.js.map
1373
+ //# sourceMappingURL=dsl-C5yuAn41.js.map