windrunner 1.0.3 → 1.1.1

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
@@ -21,7 +21,10 @@ var index_exports = {};
21
21
  __export(index_exports, {
22
22
  compileClass: () => compileClass,
23
23
  createWindrunner: () => createWindrunner,
24
+ defineResponsiveUtilities: () => defineResponsiveUtilities,
25
+ defineUtilities: () => defineUtilities,
24
26
  parseClass: () => parseClass,
27
+ plugin: () => plugin,
25
28
  windrunner: () => windrunner
26
29
  });
27
30
  module.exports = __toCommonJS(index_exports);
@@ -1464,6 +1467,13 @@ function getConfigOptions(options = {}, pluginKeys = []) {
1464
1467
  };
1465
1468
  }
1466
1469
 
1470
+ // src/constants.js
1471
+ var TIME_VALUE_WITH_UNIT_REGEX = /^\d+(?:\.\d+)?(?:ms|s)$/;
1472
+ var TIME_VALUE_NUMERIC_REGEX = /^\d+(?:\.\d+)?$/;
1473
+ var CSS_ESCAPE_BACKSLASH_REGEX = /\\/g;
1474
+ var CSS_ESCAPE_SPECIAL_CHARS_REGEX = /([ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g;
1475
+ var CSS_ESCAPE_LEADING_DIGIT_REGEX = /^(\d)/;
1476
+
1467
1477
  // src/resolvers.js
1468
1478
  function resolveArbitraryValue(valueKey) {
1469
1479
  if (valueKey.startsWith("[") && valueKey.endsWith("]")) {
@@ -1483,8 +1493,8 @@ function resolveThemeValue(scale, valueKey) {
1483
1493
  function resolveTimeValue(valueKey) {
1484
1494
  const arbitrary = resolveArbitraryValue(valueKey);
1485
1495
  if (arbitrary !== void 0) return arbitrary;
1486
- if (/^\d+(?:\.\d+)?(?:ms|s)$/.test(valueKey)) return valueKey;
1487
- if (/^\d+(?:\.\d+)?$/.test(valueKey)) return `${valueKey}ms`;
1496
+ if (TIME_VALUE_WITH_UNIT_REGEX.test(valueKey)) return valueKey;
1497
+ if (TIME_VALUE_NUMERIC_REGEX.test(valueKey)) return `${valueKey}ms`;
1488
1498
  return void 0;
1489
1499
  }
1490
1500
  function resolveColorValue(colors, colorKey) {
@@ -1520,15 +1530,21 @@ function resolveColorWithOpacity(colors, rawKey) {
1520
1530
  const color = resolveColorValue(colors, colorKey);
1521
1531
  if (color === void 0) return void 0;
1522
1532
  const arbOpacity = resolveArbitraryValue(opacityStr);
1523
- const opacityVal = arbOpacity !== void 0 ? arbOpacity : String(parseFloat(opacityStr) / 100);
1524
- if (!opacityVal || opacityVal === "NaN") return void 0;
1525
- return `color-mix(in oklch, ${color} ${parseFloat(opacityStr)}%, transparent)`;
1533
+ if (arbOpacity !== void 0) {
1534
+ const opacityVal = parseFloat(arbOpacity);
1535
+ if (isNaN(opacityVal)) return void 0;
1536
+ const finalOpacity = opacityVal <= 1 ? opacityVal * 100 : opacityVal;
1537
+ return `color-mix(in oklch, ${color} ${finalOpacity}%, transparent)`;
1538
+ }
1539
+ const opacityNum = parseFloat(opacityStr);
1540
+ if (isNaN(opacityNum)) return void 0;
1541
+ return `color-mix(in oklch, ${color} ${opacityNum}%, transparent)`;
1526
1542
  }
1527
1543
  function escapeCssIdentifier(value) {
1528
1544
  if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
1529
1545
  return CSS.escape(value);
1530
1546
  }
1531
- return String(value).replace(/\\/g, "\\\\").replace(/([ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g, "\\$1").replace(/^(\d)/, "\\3$1 ");
1547
+ return String(value).replace(CSS_ESCAPE_BACKSLASH_REGEX, "\\\\").replace(CSS_ESCAPE_SPECIAL_CHARS_REGEX, "\\$1").replace(CSS_ESCAPE_LEADING_DIGIT_REGEX, "\\3$1 ");
1532
1548
  }
1533
1549
  function appendImportant(declaration, isImportant) {
1534
1550
  if (!isImportant) return declaration;
@@ -3288,13 +3304,340 @@ function buildDivideDeclaration(baseToken, theme2) {
3288
3304
  return void 0;
3289
3305
  }
3290
3306
 
3307
+ // src/plugins.js
3308
+ var PluginRegistry = class {
3309
+ constructor() {
3310
+ this.utilities = /* @__PURE__ */ new Map();
3311
+ this.variants = /* @__PURE__ */ new Map();
3312
+ }
3313
+ /**
3314
+ * Register a custom utility
3315
+ * @param {string|RegExp} pattern - Class name pattern (e.g., "glass" or /^glass-(.+)$/)
3316
+ * @param {Function|string} handler - Function that returns CSS or CSS string
3317
+ */
3318
+ addUtility(pattern, handler) {
3319
+ this.utilities.set(pattern, handler);
3320
+ }
3321
+ /**
3322
+ * Register multiple utilities at once
3323
+ * @param {Object} utilities - Object mapping patterns to handlers
3324
+ */
3325
+ addUtilities(utilities) {
3326
+ Object.entries(utilities).forEach(([pattern, handler]) => {
3327
+ this.addUtility(pattern, handler);
3328
+ });
3329
+ }
3330
+ /**
3331
+ * Register a custom variant
3332
+ * @param {string} name - Variant name (e.g., "parent-hover")
3333
+ * @param {Function} handler - Function that transforms selector
3334
+ */
3335
+ addVariant(name, handler) {
3336
+ this.variants.set(name, handler);
3337
+ }
3338
+ /**
3339
+ * Register multiple variants at once
3340
+ * @param {Object} variants - Object mapping names to handlers
3341
+ */
3342
+ addVariants(variants2) {
3343
+ Object.entries(variants2).forEach(([name, handler]) => {
3344
+ this.addVariant(name, handler);
3345
+ });
3346
+ }
3347
+ /**
3348
+ * Check if a token matches any custom utility pattern
3349
+ * @param {string} token - The base token to match
3350
+ * @returns {Object|null} - { handler, match } or null
3351
+ */
3352
+ matchUtility(token) {
3353
+ for (const [pattern, handler] of this.utilities) {
3354
+ if (pattern instanceof RegExp) {
3355
+ const match = pattern.exec(token);
3356
+ if (match) {
3357
+ return { handler, match };
3358
+ }
3359
+ } else if (pattern === token) {
3360
+ return { handler, match: [token] };
3361
+ }
3362
+ }
3363
+ return null;
3364
+ }
3365
+ /**
3366
+ * Check if a variant name matches any custom variant
3367
+ * @param {string} variantName - The variant to check
3368
+ * @returns {Function|null} - Handler function or null
3369
+ */
3370
+ matchVariant(variantName) {
3371
+ return this.variants.get(variantName) || null;
3372
+ }
3373
+ /**
3374
+ * Get all registered utility patterns (for debugging)
3375
+ */
3376
+ getUtilities() {
3377
+ return Array.from(this.utilities.keys());
3378
+ }
3379
+ /**
3380
+ * Get all registered variant names (for debugging)
3381
+ */
3382
+ getVariants() {
3383
+ return Array.from(this.variants.keys());
3384
+ }
3385
+ /**
3386
+ * Clear all registered plugins
3387
+ */
3388
+ clear() {
3389
+ this.utilities.clear();
3390
+ this.variants.clear();
3391
+ }
3392
+ };
3393
+ function plugin(handler) {
3394
+ if (typeof handler !== "function") {
3395
+ throw new Error("Plugin handler must be a function");
3396
+ }
3397
+ return {
3398
+ __isWindrunnerPlugin: true,
3399
+ handler
3400
+ };
3401
+ }
3402
+ function isPlugin(obj) {
3403
+ return obj && obj.__isWindrunnerPlugin === true && typeof obj.handler === "function";
3404
+ }
3405
+ function defineUtilities(definitions) {
3406
+ const utilities = {};
3407
+ Object.entries(definitions).forEach(([className, css]) => {
3408
+ utilities[className] = typeof css === "string" ? css : objectToCss(css);
3409
+ });
3410
+ return utilities;
3411
+ }
3412
+ function defineResponsiveUtilities(base, values, toDeclaration) {
3413
+ const utilities = {};
3414
+ Object.entries(values).forEach(([key, value]) => {
3415
+ const className = key === "DEFAULT" ? base : `${base}-${key}`;
3416
+ utilities[className] = toDeclaration(key, value);
3417
+ });
3418
+ return utilities;
3419
+ }
3420
+ function objectToCss(obj) {
3421
+ return Object.entries(obj).map(([prop, value]) => `${prop}: ${value};`).join(" ");
3422
+ }
3423
+
3291
3424
  // src/compiler.js
3292
- function compileBaseToken(baseToken, theme2) {
3425
+ var PREFIX_ROUTER = {
3426
+ // Layout & Display
3427
+ "block": [buildLayoutDeclaration],
3428
+ "inline": [buildLayoutDeclaration],
3429
+ "flex": [buildFlexGridDeclaration, buildLayoutDeclaration],
3430
+ "grid": [buildFlexGridDeclaration, buildLayoutDeclaration],
3431
+ "hidden": [buildLayoutDeclaration],
3432
+ "table": [buildLayoutDeclaration],
3433
+ "flow": [buildLayoutDeclaration],
3434
+ // Position
3435
+ "static": [buildLayoutDeclaration],
3436
+ "fixed": [buildLayoutDeclaration],
3437
+ "absolute": [buildLayoutDeclaration],
3438
+ "relative": [buildLayoutDeclaration],
3439
+ "sticky": [buildLayoutDeclaration],
3440
+ "inset": [buildPositionInsetDeclaration, buildInsetShadowDeclaration, buildInsetRingDeclaration],
3441
+ "top": [buildPositionInsetDeclaration],
3442
+ "right": [buildPositionInsetDeclaration],
3443
+ "bottom": [buildPositionInsetDeclaration],
3444
+ "left": [buildPositionInsetDeclaration],
3445
+ "start": [buildPositionInsetDeclaration],
3446
+ "end": [buildPositionInsetDeclaration],
3447
+ "z": [buildLayoutDeclaration],
3448
+ // Spacing
3449
+ "m": [buildSpacingDeclaration],
3450
+ "mx": [buildSpacingDeclaration],
3451
+ "my": [buildSpacingDeclaration],
3452
+ "mt": [buildSpacingDeclaration],
3453
+ "mr": [buildSpacingDeclaration],
3454
+ "mb": [buildSpacingDeclaration],
3455
+ "ml": [buildSpacingDeclaration],
3456
+ "ms": [buildSpacingDeclaration],
3457
+ "me": [buildSpacingDeclaration],
3458
+ "p": [buildSpacingDeclaration],
3459
+ "px": [buildSpacingDeclaration],
3460
+ "py": [buildSpacingDeclaration],
3461
+ "pt": [buildSpacingDeclaration],
3462
+ "pr": [buildSpacingDeclaration],
3463
+ "pb": [buildSpacingDeclaration],
3464
+ "pl": [buildSpacingDeclaration],
3465
+ "ps": [buildSpacingDeclaration],
3466
+ "pe": [buildSpacingDeclaration],
3467
+ "space": [buildSpaceBetweenDeclaration],
3468
+ // Sizing
3469
+ "w": [buildDimensionDeclaration],
3470
+ "h": [buildDimensionDeclaration],
3471
+ "min": [buildDimensionDeclaration],
3472
+ "max": [buildDimensionDeclaration],
3473
+ "size": [buildDimensionDeclaration],
3474
+ // Typography
3475
+ "text": [buildTypographyDeclaration, buildColorDeclaration],
3476
+ "font": [buildTypographyDeclaration],
3477
+ "leading": [buildTypographyDeclaration],
3478
+ "tracking": [buildTypographyDeclaration],
3479
+ "line": [buildTypographyDeclaration],
3480
+ "whitespace": [buildTypographyDeclaration],
3481
+ "break": [buildTypographyDeclaration],
3482
+ "hyphens": [buildTypographyDeclaration],
3483
+ "list": [buildTypographyDeclaration],
3484
+ "italic": [buildTypographyDeclaration],
3485
+ "underline": [buildTypographyDeclaration],
3486
+ "overline": [buildTypographyDeclaration],
3487
+ "uppercase": [buildTypographyDeclaration],
3488
+ "lowercase": [buildTypographyDeclaration],
3489
+ "capitalize": [buildTypographyDeclaration],
3490
+ "normal": [buildTypographyDeclaration, buildLayoutDeclaration],
3491
+ "truncate": [buildTypographyDeclaration],
3492
+ // Colors & Backgrounds
3493
+ "bg": [buildBackgroundDeclaration, buildColorDeclaration, buildGradientDeclaration],
3494
+ "from": [buildGradientDeclaration],
3495
+ "via": [buildGradientDeclaration],
3496
+ "to": [buildGradientDeclaration],
3497
+ "fill": [buildColorDeclaration],
3498
+ "stroke": [buildColorDeclaration],
3499
+ // Borders
3500
+ "border": [buildBorderDeclaration, buildColorDeclaration],
3501
+ "rounded": [buildBorderRadiusDeclaration],
3502
+ "divide": [buildDivideDeclaration],
3503
+ // Effects
3504
+ "shadow": [buildShadowDeclaration, buildTextShadowDeclaration],
3505
+ "opacity": [buildOpacityDeclaration],
3506
+ "ring": [buildRingDeclaration, buildRingOffsetDeclaration],
3507
+ // Transforms
3508
+ "scale": [buildTransformDeclaration],
3509
+ "rotate": [buildTransformDeclaration],
3510
+ "translate": [buildTransformDeclaration],
3511
+ "skew": [buildTransformDeclaration],
3512
+ "origin": [buildTransformDeclaration],
3513
+ "transform": [buildTransformDeclaration],
3514
+ // Filters
3515
+ "blur": [buildFilterDeclaration],
3516
+ "brightness": [buildFilterDeclaration],
3517
+ "contrast": [buildFilterDeclaration],
3518
+ "grayscale": [buildFilterDeclaration],
3519
+ "hue": [buildFilterDeclaration],
3520
+ "invert": [buildFilterDeclaration],
3521
+ "saturate": [buildFilterDeclaration],
3522
+ "sepia": [buildFilterDeclaration],
3523
+ "drop": [buildFilterDeclaration],
3524
+ "backdrop": [buildFilterDeclaration],
3525
+ // Transitions & Animations
3526
+ "transition": [buildTransitionDeclaration],
3527
+ "duration": [buildTransitionDeclaration],
3528
+ "ease": [buildTransitionDeclaration],
3529
+ "delay": [buildTransitionDeclaration],
3530
+ "animate": [buildAnimationDeclaration],
3531
+ // Interactivity
3532
+ "cursor": [buildInteractivityDeclaration],
3533
+ "pointer": [buildInteractivityDeclaration],
3534
+ "resize": [buildInteractivityDeclaration],
3535
+ "select": [buildInteractivityDeclaration],
3536
+ "appearance": [buildInteractivityDeclaration],
3537
+ "outline": [buildColorDeclaration, buildInteractivityDeclaration],
3538
+ "caret": [buildColorDeclaration],
3539
+ "accent": [buildColorDeclaration],
3540
+ // Flexbox & Grid specific
3541
+ "items": [buildFlexGridDeclaration],
3542
+ "justify": [buildFlexGridDeclaration],
3543
+ "place": [buildFlexGridDeclaration],
3544
+ "content": [buildFlexGridDeclaration, buildTypographyDeclaration],
3545
+ "self": [buildFlexGridDeclaration],
3546
+ "order": [buildFlexGridDeclaration],
3547
+ "gap": [buildGapDeclaration],
3548
+ "grow": [buildFlexGridDeclaration],
3549
+ "shrink": [buildFlexGridDeclaration],
3550
+ "basis": [buildFlexGridDeclaration],
3551
+ "cols": [buildFlexGridDeclaration],
3552
+ "rows": [buildFlexGridDeclaration],
3553
+ "col": [buildFlexGridDeclaration],
3554
+ "row": [buildFlexGridDeclaration],
3555
+ "auto": [buildFlexGridDeclaration, buildLayoutDeclaration],
3556
+ // Misc
3557
+ "overflow": [buildLayoutDeclaration],
3558
+ "overscroll": [buildInteractivityDeclaration],
3559
+ "scroll": [buildScrollSnapDeclaration, buildInteractivityDeclaration],
3560
+ "snap": [buildScrollSnapDeclaration],
3561
+ "touch": [buildInteractivityDeclaration],
3562
+ "will": [buildInteractivityDeclaration],
3563
+ "mix": [buildBlendingDeclaration],
3564
+ "blend": [buildBlendingDeclaration],
3565
+ "isolation": [buildLayoutDeclaration],
3566
+ "object": [buildLayoutDeclaration],
3567
+ "container": [buildContainerQueryDeclaration],
3568
+ "columns": [buildLayoutDeclaration],
3569
+ "aspect": [buildLayoutDeclaration],
3570
+ "clear": [buildLayoutDeclaration],
3571
+ "float": [buildLayoutDeclaration],
3572
+ "box": [buildLayoutDeclaration],
3573
+ "visible": [buildLayoutDeclaration],
3574
+ "invisible": [buildLayoutDeclaration],
3575
+ "collapse": [buildLayoutDeclaration],
3576
+ "mask": [buildMaskDeclaration],
3577
+ "forced": [buildForcedColorDeclaration],
3578
+ "field": [buildInteractivityDeclaration],
3579
+ "placeholder": [buildColorDeclaration],
3580
+ "sr": [buildAccessibilityDeclaration],
3581
+ "not": [buildAccessibilityDeclaration]
3582
+ };
3583
+ function extractPrefix(token) {
3584
+ const dashIndex = token.indexOf("-");
3585
+ if (dashIndex === -1) return token;
3586
+ const prefix = token.slice(0, dashIndex);
3587
+ const secondDashIndex = token.indexOf("-", dashIndex + 1);
3588
+ if (secondDashIndex !== -1) {
3589
+ const twoPartPrefix = token.slice(0, secondDashIndex);
3590
+ if (PREFIX_ROUTER[twoPartPrefix]) return twoPartPrefix;
3591
+ }
3592
+ return prefix;
3593
+ }
3594
+ function checkAllBuilders(baseToken, theme2) {
3293
3595
  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);
3294
3596
  }
3295
- function applyVariants(selector, variants2) {
3597
+ function compileBaseToken(baseToken, theme2, pluginRegistry) {
3598
+ if (pluginRegistry) {
3599
+ const pluginMatch = pluginRegistry.matchUtility(baseToken);
3600
+ if (pluginMatch) {
3601
+ const { handler, match } = pluginMatch;
3602
+ try {
3603
+ if (typeof handler === "function") {
3604
+ const result = handler(match, theme2);
3605
+ if (result) return result;
3606
+ } else if (typeof handler === "string") {
3607
+ return handler;
3608
+ }
3609
+ } catch (error) {
3610
+ console.warn(`[Windrunner] Plugin utility handler error for "${baseToken}":`, error);
3611
+ }
3612
+ }
3613
+ }
3614
+ const prefix = extractPrefix(baseToken);
3615
+ const builders = PREFIX_ROUTER[prefix];
3616
+ if (builders) {
3617
+ for (let i = 0; i < builders.length; i += 1) {
3618
+ const result = builders[i](baseToken, theme2);
3619
+ if (result) return result;
3620
+ }
3621
+ }
3622
+ return checkAllBuilders(baseToken, theme2);
3623
+ }
3624
+ function applyVariants(selector, variants2, pluginRegistry) {
3296
3625
  let currentSelector = selector;
3297
3626
  for (const variant of variants2) {
3627
+ if (pluginRegistry) {
3628
+ const customHandler = pluginRegistry.matchVariant(variant);
3629
+ if (customHandler) {
3630
+ try {
3631
+ const result = customHandler(currentSelector);
3632
+ if (result) {
3633
+ currentSelector = result;
3634
+ continue;
3635
+ }
3636
+ } catch (error) {
3637
+ console.warn(`[Windrunner] Plugin variant handler error for "${variant}":`, error);
3638
+ }
3639
+ }
3640
+ }
3298
3641
  switch (variant) {
3299
3642
  case "dark":
3300
3643
  currentSelector = `.dark ${currentSelector}`;
@@ -3335,15 +3678,66 @@ function applyVariants(selector, variants2) {
3335
3678
  case "invalid":
3336
3679
  currentSelector = `${currentSelector}:invalid`;
3337
3680
  break;
3681
+ case "target":
3682
+ currentSelector = `${currentSelector}:target`;
3683
+ break;
3684
+ case "enabled":
3685
+ currentSelector = `${currentSelector}:enabled`;
3686
+ break;
3687
+ case "default":
3688
+ currentSelector = `${currentSelector}:default`;
3689
+ break;
3690
+ case "optional":
3691
+ currentSelector = `${currentSelector}:optional`;
3692
+ break;
3693
+ case "user-valid":
3694
+ currentSelector = `${currentSelector}:user-valid`;
3695
+ break;
3696
+ case "user-invalid":
3697
+ currentSelector = `${currentSelector}:user-invalid`;
3698
+ break;
3699
+ case "in-range":
3700
+ currentSelector = `${currentSelector}:in-range`;
3701
+ break;
3702
+ case "out-of-range":
3703
+ currentSelector = `${currentSelector}:out-of-range`;
3704
+ break;
3705
+ case "placeholder-shown":
3706
+ currentSelector = `${currentSelector}:placeholder-shown`;
3707
+ break;
3708
+ case "autofill":
3709
+ currentSelector = `${currentSelector}:autofill`;
3710
+ break;
3711
+ case "details-content":
3712
+ currentSelector = `${currentSelector}:details-content`;
3713
+ break;
3338
3714
  case "placeholder":
3339
3715
  currentSelector = `${currentSelector}::placeholder`;
3340
3716
  break;
3717
+ case "backdrop":
3718
+ currentSelector = `${currentSelector}::backdrop`;
3719
+ break;
3341
3720
  case "before":
3342
3721
  currentSelector = `${currentSelector}::before`;
3343
3722
  break;
3344
3723
  case "after":
3345
3724
  currentSelector = `${currentSelector}::after`;
3346
3725
  break;
3726
+ case "first-letter":
3727
+ currentSelector = `${currentSelector}::first-letter`;
3728
+ break;
3729
+ case "first-line":
3730
+ currentSelector = `${currentSelector}::first-line`;
3731
+ break;
3732
+ case "marker":
3733
+ currentSelector = `${currentSelector}::marker`;
3734
+ break;
3735
+ case "selection":
3736
+ currentSelector = `${currentSelector}::selection`;
3737
+ break;
3738
+ case "file":
3739
+ currentSelector = `${currentSelector}::file-selector-button`;
3740
+ break;
3347
3741
  case "first":
3348
3742
  currentSelector = `${currentSelector}:first-child`;
3349
3743
  break;
@@ -3424,21 +3818,63 @@ function applyVariants(selector, variants2) {
3424
3818
  }
3425
3819
  function resolveRuntimeContext(options = {}) {
3426
3820
  const config = getConfigOptions(options, []);
3821
+ const pluginRegistry = new PluginRegistry();
3822
+ if (options.plugins && Array.isArray(options.plugins)) {
3823
+ options.plugins.forEach((pluginDef) => {
3824
+ if (isPlugin(pluginDef)) {
3825
+ try {
3826
+ pluginDef.handler({
3827
+ addUtility: (pattern, handler) => pluginRegistry.addUtility(pattern, handler),
3828
+ addUtilities: (utilities) => pluginRegistry.addUtilities(utilities),
3829
+ addVariant: (name, handler) => pluginRegistry.addVariant(name, handler),
3830
+ addVariants: (variants2) => pluginRegistry.addVariants(variants2),
3831
+ theme: (key) => {
3832
+ if (!key) return config.theme || {};
3833
+ const keys = key.split(".");
3834
+ let value = config.theme || {};
3835
+ for (const k of keys) {
3836
+ value = value[k];
3837
+ if (value === void 0) break;
3838
+ }
3839
+ return value;
3840
+ },
3841
+ config: () => config
3842
+ });
3843
+ } catch (error) {
3844
+ console.error("[Windrunner] Plugin initialization error:", error);
3845
+ }
3846
+ }
3847
+ });
3848
+ }
3427
3849
  return {
3428
3850
  config,
3429
3851
  theme: config.theme || {},
3430
3852
  screens: config.theme && config.theme.screens || config.screens || {},
3431
- containers: config.theme && config.theme.containers || config.containers || {}
3853
+ containers: config.theme && config.theme.containers || config.containers || {},
3854
+ plugins: pluginRegistry
3432
3855
  };
3433
3856
  }
3434
3857
  function getBaseTailwindOptions(options = {}) {
3435
3858
  const { id, autoStart, compatMode, compatStyleId, compatGenerateCss, ...tailwindOptions } = options;
3436
3859
  return tailwindOptions;
3437
3860
  }
3861
+ var parseCache = /* @__PURE__ */ new Map();
3862
+ var PARSE_CACHE_MAX_SIZE = 2e3;
3863
+ function getConfigHash(screens, containers) {
3864
+ const screensEmpty = !screens || Object.keys(screens).length === 0;
3865
+ const containersEmpty = !containers || Object.keys(containers).length === 0;
3866
+ if (screensEmpty && containersEmpty) return "default";
3867
+ return `${Object.keys(screens || {}).join(",")}|${Object.keys(containers || {}).join(",")}`;
3868
+ }
3438
3869
  function parseClass(className, screens = {}, containers = {}) {
3439
3870
  if (typeof className !== "string") return null;
3440
3871
  const token = className.trim();
3441
3872
  if (!token) return null;
3873
+ const configHash = getConfigHash(screens, containers);
3874
+ const cacheKey = `${token}:${configHash}`;
3875
+ if (parseCache.has(cacheKey)) {
3876
+ return parseCache.get(cacheKey);
3877
+ }
3442
3878
  const important = token.startsWith("!");
3443
3879
  const normalized = important ? token.slice(1) : token;
3444
3880
  const parts = splitByVariantDelimiter(normalized);
@@ -3467,15 +3903,21 @@ function parseClass(className, screens = {}, containers = {}) {
3467
3903
  }
3468
3904
  variants2.push(part);
3469
3905
  }
3470
- return { original: token, baseToken, variants: variants2, breakpoint, containerBreakpoint, important, starting };
3906
+ const result = { original: token, baseToken, variants: variants2, breakpoint, containerBreakpoint, important, starting };
3907
+ if (parseCache.size >= PARSE_CACHE_MAX_SIZE) {
3908
+ const firstKey = parseCache.keys().next().value;
3909
+ parseCache.delete(firstKey);
3910
+ }
3911
+ parseCache.set(cacheKey, result);
3912
+ return result;
3471
3913
  }
3472
3914
  function compileRuntimeClassNameWithContext(className, context) {
3473
3915
  const parsed = parseClass(className, context.screens, context.containers);
3474
3916
  if (!parsed) return "";
3475
- const declaration = compileBaseToken(parsed.baseToken, context.theme);
3917
+ const declaration = compileBaseToken(parsed.baseToken, context.theme, context.plugins);
3476
3918
  if (!declaration) return "";
3477
3919
  const selector = `.${escapeCssIdentifier(parsed.original)}`;
3478
- const variantSelector = applyVariants(selector, parsed.variants);
3920
+ const variantSelector = applyVariants(selector, parsed.variants, context.plugins);
3479
3921
  if (!variantSelector) return "";
3480
3922
  const finalDeclaration = appendImportant(
3481
3923
  isChildScoped(declaration) ? declaration.declaration : declaration,
@@ -3766,6 +4208,9 @@ function windrunner(options = {}) {
3766
4208
  0 && (module.exports = {
3767
4209
  compileClass,
3768
4210
  createWindrunner,
4211
+ defineResponsiveUtilities,
4212
+ defineUtilities,
3769
4213
  parseClass,
4214
+ plugin,
3770
4215
  windrunner
3771
4216
  });