windrunner 1.0.3 → 1.1.0

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);
@@ -3288,13 +3291,160 @@ function buildDivideDeclaration(baseToken, theme2) {
3288
3291
  return void 0;
3289
3292
  }
3290
3293
 
3294
+ // src/plugins.js
3295
+ var PluginRegistry = class {
3296
+ constructor() {
3297
+ this.utilities = /* @__PURE__ */ new Map();
3298
+ this.variants = /* @__PURE__ */ new Map();
3299
+ }
3300
+ /**
3301
+ * Register a custom utility
3302
+ * @param {string|RegExp} pattern - Class name pattern (e.g., "glass" or /^glass-(.+)$/)
3303
+ * @param {Function|string} handler - Function that returns CSS or CSS string
3304
+ */
3305
+ addUtility(pattern, handler) {
3306
+ this.utilities.set(pattern, handler);
3307
+ }
3308
+ /**
3309
+ * Register multiple utilities at once
3310
+ * @param {Object} utilities - Object mapping patterns to handlers
3311
+ */
3312
+ addUtilities(utilities) {
3313
+ Object.entries(utilities).forEach(([pattern, handler]) => {
3314
+ this.addUtility(pattern, handler);
3315
+ });
3316
+ }
3317
+ /**
3318
+ * Register a custom variant
3319
+ * @param {string} name - Variant name (e.g., "parent-hover")
3320
+ * @param {Function} handler - Function that transforms selector
3321
+ */
3322
+ addVariant(name, handler) {
3323
+ this.variants.set(name, handler);
3324
+ }
3325
+ /**
3326
+ * Register multiple variants at once
3327
+ * @param {Object} variants - Object mapping names to handlers
3328
+ */
3329
+ addVariants(variants2) {
3330
+ Object.entries(variants2).forEach(([name, handler]) => {
3331
+ this.addVariant(name, handler);
3332
+ });
3333
+ }
3334
+ /**
3335
+ * Check if a token matches any custom utility pattern
3336
+ * @param {string} token - The base token to match
3337
+ * @returns {Object|null} - { handler, match } or null
3338
+ */
3339
+ matchUtility(token) {
3340
+ for (const [pattern, handler] of this.utilities) {
3341
+ if (pattern instanceof RegExp) {
3342
+ const match = pattern.exec(token);
3343
+ if (match) {
3344
+ return { handler, match };
3345
+ }
3346
+ } else if (pattern === token) {
3347
+ return { handler, match: [token] };
3348
+ }
3349
+ }
3350
+ return null;
3351
+ }
3352
+ /**
3353
+ * Check if a variant name matches any custom variant
3354
+ * @param {string} variantName - The variant to check
3355
+ * @returns {Function|null} - Handler function or null
3356
+ */
3357
+ matchVariant(variantName) {
3358
+ return this.variants.get(variantName) || null;
3359
+ }
3360
+ /**
3361
+ * Get all registered utility patterns (for debugging)
3362
+ */
3363
+ getUtilities() {
3364
+ return Array.from(this.utilities.keys());
3365
+ }
3366
+ /**
3367
+ * Get all registered variant names (for debugging)
3368
+ */
3369
+ getVariants() {
3370
+ return Array.from(this.variants.keys());
3371
+ }
3372
+ /**
3373
+ * Clear all registered plugins
3374
+ */
3375
+ clear() {
3376
+ this.utilities.clear();
3377
+ this.variants.clear();
3378
+ }
3379
+ };
3380
+ function plugin(handler) {
3381
+ if (typeof handler !== "function") {
3382
+ throw new Error("Plugin handler must be a function");
3383
+ }
3384
+ return {
3385
+ __isWindrunnerPlugin: true,
3386
+ handler
3387
+ };
3388
+ }
3389
+ function isPlugin(obj) {
3390
+ return obj && obj.__isWindrunnerPlugin === true && typeof obj.handler === "function";
3391
+ }
3392
+ function defineUtilities(definitions) {
3393
+ const utilities = {};
3394
+ Object.entries(definitions).forEach(([className, css]) => {
3395
+ utilities[className] = typeof css === "string" ? css : objectToCss(css);
3396
+ });
3397
+ return utilities;
3398
+ }
3399
+ function defineResponsiveUtilities(base, values, toDeclaration) {
3400
+ const utilities = {};
3401
+ Object.entries(values).forEach(([key, value]) => {
3402
+ const className = key === "DEFAULT" ? base : `${base}-${key}`;
3403
+ utilities[className] = toDeclaration(key, value);
3404
+ });
3405
+ return utilities;
3406
+ }
3407
+ function objectToCss(obj) {
3408
+ return Object.entries(obj).map(([prop, value]) => `${prop}: ${value};`).join(" ");
3409
+ }
3410
+
3291
3411
  // src/compiler.js
3292
- function compileBaseToken(baseToken, theme2) {
3412
+ function compileBaseToken(baseToken, theme2, pluginRegistry) {
3413
+ if (pluginRegistry) {
3414
+ const pluginMatch = pluginRegistry.matchUtility(baseToken);
3415
+ if (pluginMatch) {
3416
+ const { handler, match } = pluginMatch;
3417
+ try {
3418
+ if (typeof handler === "function") {
3419
+ const result = handler(match, theme2);
3420
+ if (result) return result;
3421
+ } else if (typeof handler === "string") {
3422
+ return handler;
3423
+ }
3424
+ } catch (error) {
3425
+ console.warn(`[Windrunner] Plugin utility handler error for "${baseToken}":`, error);
3426
+ }
3427
+ }
3428
+ }
3293
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);
3294
3430
  }
3295
- function applyVariants(selector, variants2) {
3431
+ function applyVariants(selector, variants2, pluginRegistry) {
3296
3432
  let currentSelector = selector;
3297
3433
  for (const variant of variants2) {
3434
+ if (pluginRegistry) {
3435
+ const customHandler = pluginRegistry.matchVariant(variant);
3436
+ if (customHandler) {
3437
+ try {
3438
+ const result = customHandler(currentSelector);
3439
+ if (result) {
3440
+ currentSelector = result;
3441
+ continue;
3442
+ }
3443
+ } catch (error) {
3444
+ console.warn(`[Windrunner] Plugin variant handler error for "${variant}":`, error);
3445
+ }
3446
+ }
3447
+ }
3298
3448
  switch (variant) {
3299
3449
  case "dark":
3300
3450
  currentSelector = `.dark ${currentSelector}`;
@@ -3335,15 +3485,66 @@ function applyVariants(selector, variants2) {
3335
3485
  case "invalid":
3336
3486
  currentSelector = `${currentSelector}:invalid`;
3337
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;
3338
3521
  case "placeholder":
3339
3522
  currentSelector = `${currentSelector}::placeholder`;
3340
3523
  break;
3524
+ case "backdrop":
3525
+ currentSelector = `${currentSelector}::backdrop`;
3526
+ break;
3341
3527
  case "before":
3342
3528
  currentSelector = `${currentSelector}::before`;
3343
3529
  break;
3344
3530
  case "after":
3345
3531
  currentSelector = `${currentSelector}::after`;
3346
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;
3347
3548
  case "first":
3348
3549
  currentSelector = `${currentSelector}:first-child`;
3349
3550
  break;
@@ -3424,11 +3625,40 @@ function applyVariants(selector, variants2) {
3424
3625
  }
3425
3626
  function resolveRuntimeContext(options = {}) {
3426
3627
  const config = getConfigOptions(options, []);
3628
+ const pluginRegistry = new PluginRegistry();
3629
+ if (options.plugins && Array.isArray(options.plugins)) {
3630
+ options.plugins.forEach((pluginDef) => {
3631
+ if (isPlugin(pluginDef)) {
3632
+ try {
3633
+ pluginDef.handler({
3634
+ addUtility: (pattern, handler) => pluginRegistry.addUtility(pattern, handler),
3635
+ addUtilities: (utilities) => pluginRegistry.addUtilities(utilities),
3636
+ addVariant: (name, handler) => pluginRegistry.addVariant(name, handler),
3637
+ addVariants: (variants2) => pluginRegistry.addVariants(variants2),
3638
+ theme: (key) => {
3639
+ if (!key) return config.theme || {};
3640
+ const keys = key.split(".");
3641
+ let value = config.theme || {};
3642
+ for (const k of keys) {
3643
+ value = value[k];
3644
+ if (value === void 0) break;
3645
+ }
3646
+ return value;
3647
+ },
3648
+ config: () => config
3649
+ });
3650
+ } catch (error) {
3651
+ console.error("[Windrunner] Plugin initialization error:", error);
3652
+ }
3653
+ }
3654
+ });
3655
+ }
3427
3656
  return {
3428
3657
  config,
3429
3658
  theme: config.theme || {},
3430
3659
  screens: config.theme && config.theme.screens || config.screens || {},
3431
- containers: config.theme && config.theme.containers || config.containers || {}
3660
+ containers: config.theme && config.theme.containers || config.containers || {},
3661
+ plugins: pluginRegistry
3432
3662
  };
3433
3663
  }
3434
3664
  function getBaseTailwindOptions(options = {}) {
@@ -3472,10 +3702,10 @@ function parseClass(className, screens = {}, containers = {}) {
3472
3702
  function compileRuntimeClassNameWithContext(className, context) {
3473
3703
  const parsed = parseClass(className, context.screens, context.containers);
3474
3704
  if (!parsed) return "";
3475
- const declaration = compileBaseToken(parsed.baseToken, context.theme);
3705
+ const declaration = compileBaseToken(parsed.baseToken, context.theme, context.plugins);
3476
3706
  if (!declaration) return "";
3477
3707
  const selector = `.${escapeCssIdentifier(parsed.original)}`;
3478
- const variantSelector = applyVariants(selector, parsed.variants);
3708
+ const variantSelector = applyVariants(selector, parsed.variants, context.plugins);
3479
3709
  if (!variantSelector) return "";
3480
3710
  const finalDeclaration = appendImportant(
3481
3711
  isChildScoped(declaration) ? declaration.declaration : declaration,
@@ -3766,6 +3996,9 @@ function windrunner(options = {}) {
3766
3996
  0 && (module.exports = {
3767
3997
  compileClass,
3768
3998
  createWindrunner,
3999
+ defineResponsiveUtilities,
4000
+ defineUtilities,
3769
4001
  parseClass,
4002
+ plugin,
3770
4003
  windrunner
3771
4004
  });