windrunner 1.1.0 → 1.1.2

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/dist/index.js CHANGED
@@ -29,62 +29,6 @@ __export(index_exports, {
29
29
  });
30
30
  module.exports = __toCommonJS(index_exports);
31
31
 
32
- // src/variants.js
33
- var variants = {
34
- accentColor: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
35
- accessibility: ["hover", "focus"],
36
- aspect: ["hover", "focus"],
37
- backgroundColor: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
38
- blur: ["hover", "focus"],
39
- borderColor: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
40
- boxShadow: ["hover", "focus"],
41
- brightness: ["hover", "focus"],
42
- caretColor: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
43
- contrast: ["hover", "focus"],
44
- dropShadow: ["hover", "focus"],
45
- fill: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
46
- flexBasis: ["hover", "focus"],
47
- gradientColorStops: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
48
- grayscale: ["hover", "focus"],
49
- hueRotate: ["hover", "focus"],
50
- insetRing: ["hover", "focus"],
51
- insetShadow: ["hover", "focus"],
52
- invert: ["hover", "focus"],
53
- opacity: ["hover", "focus"],
54
- outlineColor: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
55
- outlineOffset: ["hover", "focus"],
56
- outlineStyle: ["hover", "focus"],
57
- outlineWidth: ["hover", "focus"],
58
- placeholderColor: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
59
- ringColor: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
60
- ringOffsetColor: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
61
- ringOffsetWidth: ["hover", "focus"],
62
- ringWidth: ["hover", "focus"],
63
- rotate: ["hover", "focus"],
64
- saturate: ["hover", "focus"],
65
- scale: ["hover", "focus"],
66
- sepia: ["hover", "focus"],
67
- skew: ["hover", "focus"],
68
- stroke: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
69
- strokeWidth: ["hover", "focus"],
70
- textColor: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
71
- textDecoration: ["focus", "hover"],
72
- textDecorationColor: ["focus", "hover", "not-hover", "not-focus", "not-disabled"],
73
- textDecorationStyle: ["focus", "hover"],
74
- textDecorationThickness: ["focus", "hover"],
75
- textShadowBlur: ["hover", "focus"],
76
- textShadowColor: ["hover", "focus", "not-hover", "not-focus", "not-disabled"],
77
- textShadowOpacity: ["hover", "focus"],
78
- textShadowX: ["hover", "focus"],
79
- textShadowY: ["hover", "focus"],
80
- touchAction: ["hover", "focus"],
81
- mask: ["hover", "focus"],
82
- transform3d: ["hover", "focus"],
83
- translate: ["hover", "focus"],
84
- zIndex: ["hover", "focus"]
85
- };
86
- var variants_default = variants;
87
-
88
32
  // src/theme.js
89
33
  var theme = {
90
34
  accentColor: ({ theme: theme2 }) => ({
@@ -1432,7 +1376,6 @@ var vars_default = vars;
1432
1376
 
1433
1377
  // src/config.js
1434
1378
  var configOptions = {
1435
- variants: variants_default,
1436
1379
  theme: theme_default,
1437
1380
  vars: vars_default
1438
1381
  };
@@ -1467,6 +1410,13 @@ function getConfigOptions(options = {}, pluginKeys = []) {
1467
1410
  };
1468
1411
  }
1469
1412
 
1413
+ // src/constants.js
1414
+ var TIME_VALUE_WITH_UNIT_REGEX = /^\d+(?:\.\d+)?(?:ms|s)$/;
1415
+ var TIME_VALUE_NUMERIC_REGEX = /^\d+(?:\.\d+)?$/;
1416
+ var CSS_ESCAPE_BACKSLASH_REGEX = /\\/g;
1417
+ var CSS_ESCAPE_SPECIAL_CHARS_REGEX = /([ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g;
1418
+ var CSS_ESCAPE_LEADING_DIGIT_REGEX = /^(\d)/;
1419
+
1470
1420
  // src/resolvers.js
1471
1421
  function resolveArbitraryValue(valueKey) {
1472
1422
  if (valueKey.startsWith("[") && valueKey.endsWith("]")) {
@@ -1486,8 +1436,8 @@ function resolveThemeValue(scale, valueKey) {
1486
1436
  function resolveTimeValue(valueKey) {
1487
1437
  const arbitrary = resolveArbitraryValue(valueKey);
1488
1438
  if (arbitrary !== void 0) return arbitrary;
1489
- if (/^\d+(?:\.\d+)?(?:ms|s)$/.test(valueKey)) return valueKey;
1490
- if (/^\d+(?:\.\d+)?$/.test(valueKey)) return `${valueKey}ms`;
1439
+ if (TIME_VALUE_WITH_UNIT_REGEX.test(valueKey)) return valueKey;
1440
+ if (TIME_VALUE_NUMERIC_REGEX.test(valueKey)) return `${valueKey}ms`;
1491
1441
  return void 0;
1492
1442
  }
1493
1443
  function resolveColorValue(colors, colorKey) {
@@ -1523,15 +1473,21 @@ function resolveColorWithOpacity(colors, rawKey) {
1523
1473
  const color = resolveColorValue(colors, colorKey);
1524
1474
  if (color === void 0) return void 0;
1525
1475
  const arbOpacity = resolveArbitraryValue(opacityStr);
1526
- const opacityVal = arbOpacity !== void 0 ? arbOpacity : String(parseFloat(opacityStr) / 100);
1527
- if (!opacityVal || opacityVal === "NaN") return void 0;
1528
- return `color-mix(in oklch, ${color} ${parseFloat(opacityStr)}%, transparent)`;
1476
+ if (arbOpacity !== void 0) {
1477
+ const opacityVal = parseFloat(arbOpacity);
1478
+ if (isNaN(opacityVal)) return void 0;
1479
+ const finalOpacity = opacityVal <= 1 ? opacityVal * 100 : opacityVal;
1480
+ return `color-mix(in oklch, ${color} ${finalOpacity}%, transparent)`;
1481
+ }
1482
+ const opacityNum = parseFloat(opacityStr);
1483
+ if (isNaN(opacityNum)) return void 0;
1484
+ return `color-mix(in oklch, ${color} ${opacityNum}%, transparent)`;
1529
1485
  }
1530
1486
  function escapeCssIdentifier(value) {
1531
1487
  if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
1532
1488
  return CSS.escape(value);
1533
1489
  }
1534
- return String(value).replace(/\\/g, "\\\\").replace(/([ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g, "\\$1").replace(/^(\d)/, "\\3$1 ");
1490
+ return String(value).replace(CSS_ESCAPE_BACKSLASH_REGEX, "\\\\").replace(CSS_ESCAPE_SPECIAL_CHARS_REGEX, "\\$1").replace(CSS_ESCAPE_LEADING_DIGIT_REGEX, "\\3$1 ");
1535
1491
  }
1536
1492
  function appendImportant(declaration, isImportant) {
1537
1493
  if (!isImportant) return declaration;
@@ -3326,8 +3282,8 @@ var PluginRegistry = class {
3326
3282
  * Register multiple variants at once
3327
3283
  * @param {Object} variants - Object mapping names to handlers
3328
3284
  */
3329
- addVariants(variants2) {
3330
- Object.entries(variants2).forEach(([name, handler]) => {
3285
+ addVariants(variants) {
3286
+ Object.entries(variants).forEach(([name, handler]) => {
3331
3287
  this.addVariant(name, handler);
3332
3288
  });
3333
3289
  }
@@ -3409,6 +3365,178 @@ function objectToCss(obj) {
3409
3365
  }
3410
3366
 
3411
3367
  // src/compiler.js
3368
+ var PREFIX_ROUTER = {
3369
+ // Layout & Display
3370
+ "block": [buildLayoutDeclaration],
3371
+ "inline": [buildLayoutDeclaration],
3372
+ "flex": [buildFlexGridDeclaration, buildLayoutDeclaration],
3373
+ "grid": [buildFlexGridDeclaration, buildLayoutDeclaration],
3374
+ "hidden": [buildLayoutDeclaration],
3375
+ "table": [buildLayoutDeclaration],
3376
+ "flow": [buildLayoutDeclaration],
3377
+ // Position
3378
+ "static": [buildLayoutDeclaration],
3379
+ "fixed": [buildLayoutDeclaration],
3380
+ "absolute": [buildLayoutDeclaration],
3381
+ "relative": [buildLayoutDeclaration],
3382
+ "sticky": [buildLayoutDeclaration],
3383
+ "inset": [buildPositionInsetDeclaration, buildInsetShadowDeclaration, buildInsetRingDeclaration],
3384
+ "top": [buildPositionInsetDeclaration],
3385
+ "right": [buildPositionInsetDeclaration],
3386
+ "bottom": [buildPositionInsetDeclaration],
3387
+ "left": [buildPositionInsetDeclaration],
3388
+ "start": [buildPositionInsetDeclaration],
3389
+ "end": [buildPositionInsetDeclaration],
3390
+ "z": [buildLayoutDeclaration],
3391
+ // Spacing
3392
+ "m": [buildSpacingDeclaration],
3393
+ "mx": [buildSpacingDeclaration],
3394
+ "my": [buildSpacingDeclaration],
3395
+ "mt": [buildSpacingDeclaration],
3396
+ "mr": [buildSpacingDeclaration],
3397
+ "mb": [buildSpacingDeclaration],
3398
+ "ml": [buildSpacingDeclaration],
3399
+ "ms": [buildSpacingDeclaration],
3400
+ "me": [buildSpacingDeclaration],
3401
+ "p": [buildSpacingDeclaration],
3402
+ "px": [buildSpacingDeclaration],
3403
+ "py": [buildSpacingDeclaration],
3404
+ "pt": [buildSpacingDeclaration],
3405
+ "pr": [buildSpacingDeclaration],
3406
+ "pb": [buildSpacingDeclaration],
3407
+ "pl": [buildSpacingDeclaration],
3408
+ "ps": [buildSpacingDeclaration],
3409
+ "pe": [buildSpacingDeclaration],
3410
+ "space": [buildSpaceBetweenDeclaration],
3411
+ // Sizing
3412
+ "w": [buildDimensionDeclaration],
3413
+ "h": [buildDimensionDeclaration],
3414
+ "min": [buildDimensionDeclaration],
3415
+ "max": [buildDimensionDeclaration],
3416
+ "size": [buildDimensionDeclaration],
3417
+ // Typography
3418
+ "text": [buildTypographyDeclaration, buildColorDeclaration],
3419
+ "font": [buildTypographyDeclaration],
3420
+ "leading": [buildTypographyDeclaration],
3421
+ "tracking": [buildTypographyDeclaration],
3422
+ "line": [buildTypographyDeclaration],
3423
+ "whitespace": [buildTypographyDeclaration],
3424
+ "break": [buildTypographyDeclaration],
3425
+ "hyphens": [buildTypographyDeclaration],
3426
+ "list": [buildTypographyDeclaration],
3427
+ "italic": [buildTypographyDeclaration],
3428
+ "underline": [buildTypographyDeclaration],
3429
+ "overline": [buildTypographyDeclaration],
3430
+ "uppercase": [buildTypographyDeclaration],
3431
+ "lowercase": [buildTypographyDeclaration],
3432
+ "capitalize": [buildTypographyDeclaration],
3433
+ "normal": [buildTypographyDeclaration, buildLayoutDeclaration],
3434
+ "truncate": [buildTypographyDeclaration],
3435
+ // Colors & Backgrounds
3436
+ "bg": [buildBackgroundDeclaration, buildColorDeclaration, buildGradientDeclaration],
3437
+ "from": [buildGradientDeclaration],
3438
+ "via": [buildGradientDeclaration],
3439
+ "to": [buildGradientDeclaration],
3440
+ "fill": [buildColorDeclaration],
3441
+ "stroke": [buildColorDeclaration],
3442
+ // Borders
3443
+ "border": [buildBorderDeclaration, buildColorDeclaration],
3444
+ "rounded": [buildBorderRadiusDeclaration],
3445
+ "divide": [buildDivideDeclaration],
3446
+ // Effects
3447
+ "shadow": [buildShadowDeclaration, buildTextShadowDeclaration],
3448
+ "opacity": [buildOpacityDeclaration],
3449
+ "ring": [buildRingDeclaration, buildRingOffsetDeclaration],
3450
+ // Transforms
3451
+ "scale": [buildTransformDeclaration],
3452
+ "rotate": [buildTransformDeclaration],
3453
+ "translate": [buildTransformDeclaration],
3454
+ "skew": [buildTransformDeclaration],
3455
+ "origin": [buildTransformDeclaration],
3456
+ "transform": [buildTransformDeclaration],
3457
+ // Filters
3458
+ "blur": [buildFilterDeclaration],
3459
+ "brightness": [buildFilterDeclaration],
3460
+ "contrast": [buildFilterDeclaration],
3461
+ "grayscale": [buildFilterDeclaration],
3462
+ "hue": [buildFilterDeclaration],
3463
+ "invert": [buildFilterDeclaration],
3464
+ "saturate": [buildFilterDeclaration],
3465
+ "sepia": [buildFilterDeclaration],
3466
+ "drop": [buildFilterDeclaration],
3467
+ "backdrop": [buildFilterDeclaration],
3468
+ // Transitions & Animations
3469
+ "transition": [buildTransitionDeclaration],
3470
+ "duration": [buildTransitionDeclaration],
3471
+ "ease": [buildTransitionDeclaration],
3472
+ "delay": [buildTransitionDeclaration],
3473
+ "animate": [buildAnimationDeclaration],
3474
+ // Interactivity
3475
+ "cursor": [buildInteractivityDeclaration],
3476
+ "pointer": [buildInteractivityDeclaration],
3477
+ "resize": [buildInteractivityDeclaration],
3478
+ "select": [buildInteractivityDeclaration],
3479
+ "appearance": [buildInteractivityDeclaration],
3480
+ "outline": [buildColorDeclaration, buildInteractivityDeclaration],
3481
+ "caret": [buildColorDeclaration],
3482
+ "accent": [buildColorDeclaration],
3483
+ // Flexbox & Grid specific
3484
+ "items": [buildFlexGridDeclaration],
3485
+ "justify": [buildFlexGridDeclaration],
3486
+ "place": [buildFlexGridDeclaration],
3487
+ "content": [buildFlexGridDeclaration, buildTypographyDeclaration],
3488
+ "self": [buildFlexGridDeclaration],
3489
+ "order": [buildFlexGridDeclaration],
3490
+ "gap": [buildGapDeclaration],
3491
+ "grow": [buildFlexGridDeclaration],
3492
+ "shrink": [buildFlexGridDeclaration],
3493
+ "basis": [buildFlexGridDeclaration],
3494
+ "cols": [buildFlexGridDeclaration],
3495
+ "rows": [buildFlexGridDeclaration],
3496
+ "col": [buildFlexGridDeclaration],
3497
+ "row": [buildFlexGridDeclaration],
3498
+ "auto": [buildFlexGridDeclaration, buildLayoutDeclaration],
3499
+ // Misc
3500
+ "overflow": [buildLayoutDeclaration],
3501
+ "overscroll": [buildInteractivityDeclaration],
3502
+ "scroll": [buildScrollSnapDeclaration, buildInteractivityDeclaration],
3503
+ "snap": [buildScrollSnapDeclaration],
3504
+ "touch": [buildInteractivityDeclaration],
3505
+ "will": [buildInteractivityDeclaration],
3506
+ "mix": [buildBlendingDeclaration],
3507
+ "blend": [buildBlendingDeclaration],
3508
+ "isolation": [buildLayoutDeclaration],
3509
+ "object": [buildLayoutDeclaration],
3510
+ "container": [buildContainerQueryDeclaration],
3511
+ "columns": [buildLayoutDeclaration],
3512
+ "aspect": [buildLayoutDeclaration],
3513
+ "clear": [buildLayoutDeclaration],
3514
+ "float": [buildLayoutDeclaration],
3515
+ "box": [buildLayoutDeclaration],
3516
+ "visible": [buildLayoutDeclaration],
3517
+ "invisible": [buildLayoutDeclaration],
3518
+ "collapse": [buildLayoutDeclaration],
3519
+ "mask": [buildMaskDeclaration],
3520
+ "forced": [buildForcedColorDeclaration],
3521
+ "field": [buildInteractivityDeclaration],
3522
+ "placeholder": [buildColorDeclaration],
3523
+ "sr": [buildAccessibilityDeclaration],
3524
+ "not": [buildAccessibilityDeclaration]
3525
+ };
3526
+ function extractPrefix(token) {
3527
+ const dashIndex = token.indexOf("-");
3528
+ if (dashIndex === -1) return token;
3529
+ const prefix = token.slice(0, dashIndex);
3530
+ const secondDashIndex = token.indexOf("-", dashIndex + 1);
3531
+ if (secondDashIndex !== -1) {
3532
+ const twoPartPrefix = token.slice(0, secondDashIndex);
3533
+ if (PREFIX_ROUTER[twoPartPrefix]) return twoPartPrefix;
3534
+ }
3535
+ return prefix;
3536
+ }
3537
+ function checkAllBuilders(baseToken, theme2) {
3538
+ return buildLayoutDeclaration(baseToken, theme2) || buildPositionInsetDeclaration(baseToken, theme2) || buildSpacingDeclaration(baseToken, theme2) || buildSpaceBetweenDeclaration(baseToken, theme2) || buildGapDeclaration(baseToken, theme2) || buildDimensionDeclaration(baseToken, theme2) || buildFlexGridDeclaration(baseToken, theme2) || buildBorderDeclaration(baseToken, theme2) || buildBorderRadiusDeclaration(baseToken, theme2) || buildBorderSpacingDeclaration(baseToken, theme2) || buildDivideDeclaration(baseToken, theme2) || buildOpacityDeclaration(baseToken, theme2) || buildShadowDeclaration(baseToken, theme2) || buildInsetShadowDeclaration(baseToken, theme2) || buildInsetRingDeclaration(baseToken, theme2) || buildRingDeclaration(baseToken, theme2) || buildRingOffsetDeclaration(baseToken, theme2) || buildTextShadowDeclaration(baseToken, theme2) || buildTransitionDeclaration(baseToken) || buildTransformDeclaration(baseToken, theme2) || buildFilterDeclaration(baseToken, theme2) || buildBackgroundDeclaration(baseToken, theme2) || buildGradientDeclaration(baseToken, theme2) || buildColorDeclaration(baseToken, theme2) || buildTypographyDeclaration(baseToken, theme2) || buildBlendingDeclaration(baseToken) || buildInteractivityDeclaration(baseToken, theme2) || buildAnimationDeclaration(baseToken) || buildMaskDeclaration(baseToken) || buildContainerQueryDeclaration(baseToken) || buildScrollSnapDeclaration(baseToken) || buildAccessibilityDeclaration(baseToken) || buildZoomDeclaration(baseToken, theme2) || buildForcedColorDeclaration(baseToken);
3539
+ }
3412
3540
  function compileBaseToken(baseToken, theme2, pluginRegistry) {
3413
3541
  if (pluginRegistry) {
3414
3542
  const pluginMatch = pluginRegistry.matchUtility(baseToken);
@@ -3426,11 +3554,85 @@ function compileBaseToken(baseToken, theme2, pluginRegistry) {
3426
3554
  }
3427
3555
  }
3428
3556
  }
3429
- return buildLayoutDeclaration(baseToken, theme2) || buildPositionInsetDeclaration(baseToken, theme2) || buildSpacingDeclaration(baseToken, theme2) || buildSpaceBetweenDeclaration(baseToken, theme2) || buildGapDeclaration(baseToken, theme2) || buildDimensionDeclaration(baseToken, theme2) || buildFlexGridDeclaration(baseToken, theme2) || buildBorderDeclaration(baseToken, theme2) || buildBorderRadiusDeclaration(baseToken, theme2) || buildBorderSpacingDeclaration(baseToken, theme2) || buildDivideDeclaration(baseToken, theme2) || buildOpacityDeclaration(baseToken, theme2) || buildShadowDeclaration(baseToken, theme2) || buildInsetShadowDeclaration(baseToken, theme2) || buildInsetRingDeclaration(baseToken, theme2) || buildRingDeclaration(baseToken, theme2) || buildRingOffsetDeclaration(baseToken, theme2) || buildTextShadowDeclaration(baseToken, theme2) || buildTransitionDeclaration(baseToken) || buildTransformDeclaration(baseToken, theme2) || buildFilterDeclaration(baseToken, theme2) || buildBackgroundDeclaration(baseToken, theme2) || buildGradientDeclaration(baseToken, theme2) || buildColorDeclaration(baseToken, theme2) || buildTypographyDeclaration(baseToken, theme2) || buildBlendingDeclaration(baseToken) || buildInteractivityDeclaration(baseToken, theme2) || buildAnimationDeclaration(baseToken) || buildMaskDeclaration(baseToken) || buildContainerQueryDeclaration(baseToken) || buildScrollSnapDeclaration(baseToken) || buildAccessibilityDeclaration(baseToken) || buildZoomDeclaration(baseToken, theme2) || buildForcedColorDeclaration(baseToken);
3557
+ const prefix = extractPrefix(baseToken);
3558
+ const builders = PREFIX_ROUTER[prefix];
3559
+ if (builders) {
3560
+ for (let i = 0; i < builders.length; i += 1) {
3561
+ const result = builders[i](baseToken, theme2);
3562
+ if (result) return result;
3563
+ }
3564
+ }
3565
+ return checkAllBuilders(baseToken, theme2);
3430
3566
  }
3431
- function applyVariants(selector, variants2, pluginRegistry) {
3567
+ var VARIANT_MAP = /* @__PURE__ */ new Map([
3568
+ // Dark mode
3569
+ ["dark", (s) => `.dark ${s}`],
3570
+ // Pseudo-classes – interactive
3571
+ ["hover", (s) => `${s}:hover`],
3572
+ ["focus", (s) => `${s}:focus`],
3573
+ ["focus-visible", (s) => `${s}:focus-visible`],
3574
+ ["focus-within", (s) => `${s}:focus-within`],
3575
+ ["active", (s) => `${s}:active`],
3576
+ ["visited", (s) => `${s}:visited`],
3577
+ ["disabled", (s) => `${s}:disabled`],
3578
+ ["checked", (s) => `${s}:checked`],
3579
+ ["indeterminate", (s) => `${s}:indeterminate`],
3580
+ ["required", (s) => `${s}:required`],
3581
+ ["valid", (s) => `${s}:valid`],
3582
+ ["invalid", (s) => `${s}:invalid`],
3583
+ ["target", (s) => `${s}:target`],
3584
+ ["enabled", (s) => `${s}:enabled`],
3585
+ ["default", (s) => `${s}:default`],
3586
+ ["optional", (s) => `${s}:optional`],
3587
+ ["user-valid", (s) => `${s}:user-valid`],
3588
+ ["user-invalid", (s) => `${s}:user-invalid`],
3589
+ ["in-range", (s) => `${s}:in-range`],
3590
+ ["out-of-range", (s) => `${s}:out-of-range`],
3591
+ ["placeholder-shown", (s) => `${s}:placeholder-shown`],
3592
+ ["autofill", (s) => `${s}:autofill`],
3593
+ ["details-content", (s) => `${s}:details-content`],
3594
+ ["read-only", (s) => `${s}:read-only`],
3595
+ ["open", (s) => `${s}[open]`],
3596
+ // Pseudo-elements
3597
+ ["placeholder", (s) => `${s}::placeholder`],
3598
+ ["backdrop", (s) => `${s}::backdrop`],
3599
+ ["before", (s) => `${s}::before`],
3600
+ ["after", (s) => `${s}::after`],
3601
+ ["first-letter", (s) => `${s}::first-letter`],
3602
+ ["first-line", (s) => `${s}::first-line`],
3603
+ ["marker", (s) => `${s}::marker`],
3604
+ ["selection", (s) => `${s}::selection`],
3605
+ ["file", (s) => `${s}::file-selector-button`],
3606
+ // Structural pseudo-classes
3607
+ ["first", (s) => `${s}:first-child`],
3608
+ ["last", (s) => `${s}:last-child`],
3609
+ ["odd", (s) => `${s}:nth-child(odd)`],
3610
+ ["even", (s) => `${s}:nth-child(even)`],
3611
+ ["first-of-type", (s) => `${s}:first-of-type`],
3612
+ ["last-of-type", (s) => `${s}:last-of-type`],
3613
+ ["only", (s) => `${s}:only-child`],
3614
+ ["only-of-type", (s) => `${s}:only-of-type`],
3615
+ ["empty", (s) => `${s}:empty`],
3616
+ // Group & peer variants
3617
+ ["group-hover", (s) => `.group:hover ${s}`],
3618
+ ["group-focus", (s) => `.group:focus ${s}`],
3619
+ ["group-active", (s) => `.group:active ${s}`],
3620
+ ["peer-hover", (s) => `.peer:hover ~ ${s}`],
3621
+ ["peer-focus", (s) => `.peer:focus ~ ${s}`],
3622
+ ["peer-checked", (s) => `.peer:checked ~ ${s}`],
3623
+ ["peer-disabled", (s) => `.peer:disabled ~ ${s}`],
3624
+ // Negation variants
3625
+ ["not-hover", (s) => `${s}:not(:hover)`],
3626
+ ["not-focus", (s) => `${s}:not(:focus)`],
3627
+ ["not-disabled", (s) => `${s}:not(:disabled)`],
3628
+ ["not-checked", (s) => `${s}:not(:checked)`],
3629
+ // In-* variants (group-based)
3630
+ ["in-hover", (s) => `.group:hover ${s}`],
3631
+ ["in-focus", (s) => `.group:focus ${s}`]
3632
+ ]);
3633
+ function applyVariants(selector, variants, pluginRegistry) {
3432
3634
  let currentSelector = selector;
3433
- for (const variant of variants2) {
3635
+ for (const variant of variants) {
3434
3636
  if (pluginRegistry) {
3435
3637
  const customHandler = pluginRegistry.matchVariant(variant);
3436
3638
  if (customHandler) {
@@ -3445,180 +3647,11 @@ function applyVariants(selector, variants2, pluginRegistry) {
3445
3647
  }
3446
3648
  }
3447
3649
  }
3448
- switch (variant) {
3449
- case "dark":
3450
- currentSelector = `.dark ${currentSelector}`;
3451
- break;
3452
- case "hover":
3453
- currentSelector = `${currentSelector}:hover`;
3454
- break;
3455
- case "focus":
3456
- currentSelector = `${currentSelector}:focus`;
3457
- break;
3458
- case "focus-visible":
3459
- currentSelector = `${currentSelector}:focus-visible`;
3460
- break;
3461
- case "focus-within":
3462
- currentSelector = `${currentSelector}:focus-within`;
3463
- break;
3464
- case "active":
3465
- currentSelector = `${currentSelector}:active`;
3466
- break;
3467
- case "visited":
3468
- currentSelector = `${currentSelector}:visited`;
3469
- break;
3470
- case "disabled":
3471
- currentSelector = `${currentSelector}:disabled`;
3472
- break;
3473
- case "checked":
3474
- currentSelector = `${currentSelector}:checked`;
3475
- break;
3476
- case "indeterminate":
3477
- currentSelector = `${currentSelector}:indeterminate`;
3478
- break;
3479
- case "required":
3480
- currentSelector = `${currentSelector}:required`;
3481
- break;
3482
- case "valid":
3483
- currentSelector = `${currentSelector}:valid`;
3484
- break;
3485
- case "invalid":
3486
- currentSelector = `${currentSelector}:invalid`;
3487
- break;
3488
- case "target":
3489
- currentSelector = `${currentSelector}:target`;
3490
- break;
3491
- case "enabled":
3492
- currentSelector = `${currentSelector}:enabled`;
3493
- break;
3494
- case "default":
3495
- currentSelector = `${currentSelector}:default`;
3496
- break;
3497
- case "optional":
3498
- currentSelector = `${currentSelector}:optional`;
3499
- break;
3500
- case "user-valid":
3501
- currentSelector = `${currentSelector}:user-valid`;
3502
- break;
3503
- case "user-invalid":
3504
- currentSelector = `${currentSelector}:user-invalid`;
3505
- break;
3506
- case "in-range":
3507
- currentSelector = `${currentSelector}:in-range`;
3508
- break;
3509
- case "out-of-range":
3510
- currentSelector = `${currentSelector}:out-of-range`;
3511
- break;
3512
- case "placeholder-shown":
3513
- currentSelector = `${currentSelector}:placeholder-shown`;
3514
- break;
3515
- case "autofill":
3516
- currentSelector = `${currentSelector}:autofill`;
3517
- break;
3518
- case "details-content":
3519
- currentSelector = `${currentSelector}:details-content`;
3520
- break;
3521
- case "placeholder":
3522
- currentSelector = `${currentSelector}::placeholder`;
3523
- break;
3524
- case "backdrop":
3525
- currentSelector = `${currentSelector}::backdrop`;
3526
- break;
3527
- case "before":
3528
- currentSelector = `${currentSelector}::before`;
3529
- break;
3530
- case "after":
3531
- currentSelector = `${currentSelector}::after`;
3532
- break;
3533
- case "first-letter":
3534
- currentSelector = `${currentSelector}::first-letter`;
3535
- break;
3536
- case "first-line":
3537
- currentSelector = `${currentSelector}::first-line`;
3538
- break;
3539
- case "marker":
3540
- currentSelector = `${currentSelector}::marker`;
3541
- break;
3542
- case "selection":
3543
- currentSelector = `${currentSelector}::selection`;
3544
- break;
3545
- case "file":
3546
- currentSelector = `${currentSelector}::file-selector-button`;
3547
- break;
3548
- case "first":
3549
- currentSelector = `${currentSelector}:first-child`;
3550
- break;
3551
- case "last":
3552
- currentSelector = `${currentSelector}:last-child`;
3553
- break;
3554
- case "odd":
3555
- currentSelector = `${currentSelector}:nth-child(odd)`;
3556
- break;
3557
- case "even":
3558
- currentSelector = `${currentSelector}:nth-child(even)`;
3559
- break;
3560
- case "first-of-type":
3561
- currentSelector = `${currentSelector}:first-of-type`;
3562
- break;
3563
- case "last-of-type":
3564
- currentSelector = `${currentSelector}:last-of-type`;
3565
- break;
3566
- case "only":
3567
- currentSelector = `${currentSelector}:only-child`;
3568
- break;
3569
- case "only-of-type":
3570
- currentSelector = `${currentSelector}:only-of-type`;
3571
- break;
3572
- case "empty":
3573
- currentSelector = `${currentSelector}:empty`;
3574
- break;
3575
- case "read-only":
3576
- currentSelector = `${currentSelector}:read-only`;
3577
- break;
3578
- case "open":
3579
- currentSelector = `${currentSelector}[open]`;
3580
- break;
3581
- case "group-hover":
3582
- currentSelector = `.group:hover ${currentSelector}`;
3583
- break;
3584
- case "group-focus":
3585
- currentSelector = `.group:focus ${currentSelector}`;
3586
- break;
3587
- case "group-active":
3588
- currentSelector = `.group:active ${currentSelector}`;
3589
- break;
3590
- case "peer-hover":
3591
- currentSelector = `.peer:hover ~ ${currentSelector}`;
3592
- break;
3593
- case "peer-focus":
3594
- currentSelector = `.peer:focus ~ ${currentSelector}`;
3595
- break;
3596
- case "peer-checked":
3597
- currentSelector = `.peer:checked ~ ${currentSelector}`;
3598
- break;
3599
- case "peer-disabled":
3600
- currentSelector = `.peer:disabled ~ ${currentSelector}`;
3601
- break;
3602
- case "not-hover":
3603
- currentSelector = `${currentSelector}:not(:hover)`;
3604
- break;
3605
- case "not-focus":
3606
- currentSelector = `${currentSelector}:not(:focus)`;
3607
- break;
3608
- case "not-disabled":
3609
- currentSelector = `${currentSelector}:not(:disabled)`;
3610
- break;
3611
- case "not-checked":
3612
- currentSelector = `${currentSelector}:not(:checked)`;
3613
- break;
3614
- case "in-hover":
3615
- currentSelector = `.group:hover ${currentSelector}`;
3616
- break;
3617
- case "in-focus":
3618
- currentSelector = `.group:focus ${currentSelector}`;
3619
- break;
3620
- default:
3621
- return void 0;
3650
+ const builtinHandler = VARIANT_MAP.get(variant);
3651
+ if (builtinHandler) {
3652
+ currentSelector = builtinHandler(currentSelector);
3653
+ } else {
3654
+ return void 0;
3622
3655
  }
3623
3656
  }
3624
3657
  return currentSelector;
@@ -3634,7 +3667,7 @@ function resolveRuntimeContext(options = {}) {
3634
3667
  addUtility: (pattern, handler) => pluginRegistry.addUtility(pattern, handler),
3635
3668
  addUtilities: (utilities) => pluginRegistry.addUtilities(utilities),
3636
3669
  addVariant: (name, handler) => pluginRegistry.addVariant(name, handler),
3637
- addVariants: (variants2) => pluginRegistry.addVariants(variants2),
3670
+ addVariants: (variants) => pluginRegistry.addVariants(variants),
3638
3671
  theme: (key) => {
3639
3672
  if (!key) return config.theme || {};
3640
3673
  const keys = key.split(".");
@@ -3665,16 +3698,29 @@ function getBaseTailwindOptions(options = {}) {
3665
3698
  const { id, autoStart, compatMode, compatStyleId, compatGenerateCss, ...tailwindOptions } = options;
3666
3699
  return tailwindOptions;
3667
3700
  }
3701
+ var parseCache = /* @__PURE__ */ new Map();
3702
+ var PARSE_CACHE_MAX_SIZE = 2e3;
3703
+ function getConfigHash(screens, containers) {
3704
+ const screensEmpty = !screens || Object.keys(screens).length === 0;
3705
+ const containersEmpty = !containers || Object.keys(containers).length === 0;
3706
+ if (screensEmpty && containersEmpty) return "default";
3707
+ return `${Object.keys(screens || {}).join(",")}|${Object.keys(containers || {}).join(",")}`;
3708
+ }
3668
3709
  function parseClass(className, screens = {}, containers = {}) {
3669
3710
  if (typeof className !== "string") return null;
3670
3711
  const token = className.trim();
3671
3712
  if (!token) return null;
3713
+ const configHash = getConfigHash(screens, containers);
3714
+ const cacheKey = `${token}:${configHash}`;
3715
+ if (parseCache.has(cacheKey)) {
3716
+ return parseCache.get(cacheKey);
3717
+ }
3672
3718
  const important = token.startsWith("!");
3673
3719
  const normalized = important ? token.slice(1) : token;
3674
3720
  const parts = splitByVariantDelimiter(normalized);
3675
3721
  if (parts.length === 0) return null;
3676
3722
  const baseToken = parts[parts.length - 1];
3677
- const variants2 = [];
3723
+ const variants = [];
3678
3724
  let breakpoint = null;
3679
3725
  let containerBreakpoint = null;
3680
3726
  let starting = false;
@@ -3695,9 +3741,15 @@ function parseClass(className, screens = {}, containers = {}) {
3695
3741
  breakpoint = part;
3696
3742
  continue;
3697
3743
  }
3698
- variants2.push(part);
3744
+ variants.push(part);
3745
+ }
3746
+ const result = { original: token, baseToken, variants, breakpoint, containerBreakpoint, important, starting };
3747
+ if (parseCache.size >= PARSE_CACHE_MAX_SIZE) {
3748
+ const firstKey = parseCache.keys().next().value;
3749
+ parseCache.delete(firstKey);
3699
3750
  }
3700
- return { original: token, baseToken, variants: variants2, breakpoint, containerBreakpoint, important, starting };
3751
+ parseCache.set(cacheKey, result);
3752
+ return result;
3701
3753
  }
3702
3754
  function compileRuntimeClassNameWithContext(className, context) {
3703
3755
  const parsed = parseClass(className, context.screens, context.containers);
@@ -3800,6 +3852,9 @@ function createWindrunner(options = {}) {
3800
3852
  const preflight2 = options.preflight !== false;
3801
3853
  const compatMode = options.compatMode || "none";
3802
3854
  const compatStyleId = options.compatStyleId || `${styleId}-full`;
3855
+ const maxCacheSize = options.maxCacheSize || 1e4;
3856
+ const onError = typeof options.onError === "function" ? options.onError : null;
3857
+ const onCompile = typeof options.onCompile === "function" ? options.onCompile : null;
3803
3858
  const tailwindOptions = getBaseTailwindOptions(options);
3804
3859
  const context = resolveRuntimeContext(tailwindOptions);
3805
3860
  const cache = /* @__PURE__ */ new Map();
@@ -3845,6 +3900,10 @@ function createWindrunner(options = {}) {
3845
3900
  const compileWithCache = (className) => {
3846
3901
  if (cache.has(className)) return cache.get(className);
3847
3902
  const cssRule = compileRuntimeClassNameWithContext(className, context);
3903
+ if (cache.size >= maxCacheSize) {
3904
+ const firstKey = cache.keys().next().value;
3905
+ cache.delete(firstKey);
3906
+ }
3848
3907
  cache.set(className, cssRule);
3849
3908
  return cssRule;
3850
3909
  };
@@ -3867,8 +3926,10 @@ function createWindrunner(options = {}) {
3867
3926
  const cssRule = compileWithCache(className);
3868
3927
  if (!cssRule) {
3869
3928
  ensureCompatStyle();
3929
+ if (onError) onError(className);
3870
3930
  } else {
3871
3931
  insertRule(cssRule);
3932
+ if (onCompile) onCompile(className, cssRule);
3872
3933
  }
3873
3934
  return cssRule;
3874
3935
  };
@@ -3971,6 +4032,16 @@ function createWindrunner(options = {}) {
3971
4032
  }
3972
4033
  runStart();
3973
4034
  };
4035
+ const clearCache = () => {
4036
+ cache.clear();
4037
+ };
4038
+ const getStats = () => ({
4039
+ cacheSize: cache.size,
4040
+ insertedRuleCount: insertedRules.size,
4041
+ pendingElementCount: pendingElements.size,
4042
+ isObserving: observer !== null,
4043
+ isCompatLoaded: compatLoaded
4044
+ });
3974
4045
  return {
3975
4046
  processClassName,
3976
4047
  processClassList,
@@ -3980,6 +4051,8 @@ function createWindrunner(options = {}) {
3980
4051
  flush,
3981
4052
  start,
3982
4053
  disconnect,
4054
+ clearCache,
4055
+ getStats,
3983
4056
  isCompatLoaded: () => compatLoaded,
3984
4057
  getCacheSize: () => cache.size,
3985
4058
  getInsertedRuleCount: () => insertedRules.size