@barocss/kit 0.10.2 → 0.11.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.cjs CHANGED
@@ -271,250 +271,574 @@ function clearContextCaches(ctx) {
271
271
  state.failures.clear();
272
272
  }
273
273
  //#endregion
274
- //#region src/core/registry.ts
275
- var utilityRegistry = [];
276
- function registerUtility(util, ctx) {
277
- const state = ctx && getContextState(ctx);
278
- if (ctx && !state) throw new Error("Utility registration requires a context from createContext");
279
- (state?.utilities || utilityRegistry).push(util);
280
- if (ctx) clearContextCaches(ctx);
281
- else {
282
- parseResultCache.clear();
283
- utilityCache.clear();
284
- }
285
- }
286
- function getUtility(ctx) {
287
- return ctx && getContextState(ctx)?.utilities || utilityRegistry;
288
- }
289
- var modifierRegistry = [];
274
+ //#region src/core/utils.ts
290
275
  /**
291
- * staticModifier: A helper that registers a modifier name and an array of CSS selectors directly to the registry
292
- *
293
- * @example
294
- * ```
295
- * staticModifier('disabled', ['&:disabled'], { source: 'pseudo' });
296
- * ```
297
- *
298
- * @param name The name of the modifier
299
- * @param selectors The selectors of the modifier
300
- * @param options The options of the modifier
301
- *
302
- * @returns {void}
276
+ * Parses a fraction string (e.g., '1/2') and returns a percentage string (e.g., '50%'), or null if not a valid fraction.
303
277
  */
304
- function staticModifier(name, selectors, options = {}, ctx) {
305
- registerModifier({
306
- name,
307
- match: (mod) => mod === name,
308
- modifySelector: ({ ..._rest }) => {
309
- return selectors.map((sel) => ({
310
- selector: sel,
311
- source: options.source
312
- }));
313
- },
314
- ...options
315
- }, ctx);
316
- }
317
- function functionalModifier(match, modifySelector, wrap, options = {}, ctx) {
318
- registerModifier({
319
- match,
320
- modifySelector,
321
- wrap,
322
- ...options
323
- }, ctx);
324
- }
325
- function registerModifier(modifier, ctx) {
326
- const state = ctx && getContextState(ctx);
327
- if (ctx && !state) throw new Error("Modifier registration requires a context from createContext");
328
- (state?.modifiers || modifierRegistry).push(modifier);
329
- if (ctx) clearContextCaches(ctx);
330
- }
331
- function getModifier(ctx) {
332
- return ctx && getContextState(ctx)?.modifiers || modifierRegistry;
333
- }
334
- var ESCAPE_REGEX = /[^A-Za-z0-9_-]/g;
335
- function escapeClassName(className) {
336
- if (className === "-") return "\\-";
337
- const lead = /^-?[0-9]/.exec(className);
338
- if (lead) {
339
- const i = lead[0].length - 1;
340
- return className.slice(0, i) + "\\" + className.charCodeAt(i).toString(16) + " " + escapeRest(className.slice(i + 1));
278
+ function parseFraction(input) {
279
+ if (input.includes("/")) {
280
+ const [num, denom] = input.split("/").map(Number);
281
+ if (!isNaN(num) && !isNaN(denom) && denom !== 0) return `${num / denom * 100}%`;
341
282
  }
342
- return escapeRest(className);
343
- }
344
- function escapeRest(className) {
345
- return className.replace(ESCAPE_REGEX, (c) => {
346
- if (c === " ") return "\\x20 ";
347
- if (c === ".") return "\\.";
348
- if (c === "/") return "\\/";
349
- if (c === ":") return "\\:";
350
- if (c === "[") return "\\[";
351
- if (c === "]") return "\\]";
352
- if (c === "(") return "\\(";
353
- if (c === ")") return "\\)";
354
- if (c === "%") return "\\%";
355
- if (c === "#") return "\\#";
356
- if (c === ",") return "\\,";
357
- if (c === "=") return "\\=";
358
- if (c === "&") return "\\&";
359
- if (c === "~") return "\\~";
360
- if (c === "*") return "\\*";
361
- if (c === "$") return "\\$";
362
- if (c === "^") return "\\^";
363
- if (c === "+") return "\\+";
364
- if (c === "?") return "\\?";
365
- if (c === "!") return "\\!";
366
- if (c === "@") return "\\@";
367
- if (c === "'") return "\\'";
368
- if (c === "\"") return "\\\"";
369
- if (c === "`") return "\\`";
370
- if (c === ";") return "\\;";
371
- if (c === "<") return "\\<";
372
- if (c === ">") return "\\>";
373
- if (c === "{") return "\\{";
374
- if (c === "}") return "\\}";
375
- if (c === "|") return "\\|";
376
- if (c === "\\") return "\\\\";
377
- return "\\" + c;
378
- });
283
+ return null;
379
284
  }
380
285
  /**
381
- * staticUtility: A helper that registers a utility name and an array of CSS declaration pairs directly to the registry
382
- *
383
- * @example
384
- * ```
385
- * staticUtility('block', [['display', 'block']]);
386
- * staticUtility('hidden', [['display', 'none']]);
387
- * staticUtility('space-x-px', [
388
- * [
389
- * '& > :not([hidden]) ~ :not([hidden])', // selector
390
- * [
391
- * ['margin-inline-start', '1px'], // [prop, value]
392
- * ['margin-inline-end', '1px'], // [prop, value]
393
- * ],
394
- * ],
395
- * ]);
396
- * ```
397
- *
398
- * @param name The name of the utility
399
- * @param decls The declarations of the utility
400
- * @param opts The options of the utility
286
+ * Returns the input if it is a valid non-negative integer string, else null.
401
287
  *
402
- * @returns {void}
288
+ * @example
289
+ * parseNumber("10") // "10"
290
+ * parseNumber("-10") // "-10"
291
+ * parseNumber("10.5") // "10.5"
403
292
  */
404
- function staticUtility(name, decls, opts, ctx) {
405
- registerUtility({
406
- name,
407
- match: (className) => {
408
- return className === name;
409
- },
410
- handler: (value) => {
411
- return decls.flatMap((params) => {
412
- if (params.type) return [params];
413
- if (typeof params === "function") return [params(value)];
414
- const [a, b] = params;
415
- if (typeof b === "string") return [decl(a, b)];
416
- else if (Array.isArray(b)) return [rule(a, b.map(([prop, value]) => decl(prop, value)))];
417
- return [];
418
- });
419
- },
420
- description: opts?.description,
421
- category: opts?.category,
422
- priority: opts?.priority
423
- }, ctx);
293
+ function parseNumber(input) {
294
+ return /^-?\d+(?:\.\d+)?$/.test(input) ? input : null;
424
295
  }
425
296
  /**
426
- * functionalUtility: A helper that registers dynamic utilities (theme, arbitrary, custom, negative, fraction, etc.) directly
427
- *
428
- * Example:
429
- * functionalUtility({
430
- * name: 'z',
431
- * supportsNegative: true,
432
- * themeKeys: ['--z-index'],
433
- * handleBareValue: ({ value }) => isPositiveInteger(value) ? value : null,
434
- * handle: (value) => [decl('z-index', value)],
435
- * description: 'z-index utility',
436
- * category: 'layout',
437
- * });
297
+ * Returns the input if it is a valid length string, else null.
438
298
  */
299
+ function parseLength(input) {
300
+ return /^\d+(px|em|rem|vh|vw|vmin|vmax|%|in|cm|mm|pt|pc|ex|ch|fr)$/.test(input) ? input : null;
301
+ }
439
302
  /**
440
- * #300: a theme key that no built-in utility names (`theme.extend.borderRadius.card`) still resolves, as in
441
- * Tailwind 4 where `--radius-card` gives `rounded-card`. Only word keys that start with a letter (numbers stay
442
- * bare values), never `DEFAULT`; unknown keys return null so the utility emits nothing (#213).
303
+ * Unified parser for fraction or number, with options for percent or repeat syntax.
304
+ * - percent: if true, returns percentage for fraction (e.g., '1/2' -> '50%')
305
+ * - repeat: if true, returns repeat() for number (e.g., '3' -> 'repeat(3, minmax(0, 1fr))')
443
306
  */
444
- function themeKeyEntry(ctx, namespace, key) {
445
- if (key === "DEFAULT" || !/^[a-zA-Z][\w-]*$/.test(key) || typeof ctx?.theme !== "function") return void 0;
446
- const table = ctx.theme(namespace);
447
- if (!table || typeof table !== "object" || !Object.prototype.hasOwnProperty.call(table, key)) return void 0;
448
- return table[key] ?? void 0;
449
- }
450
- /** #300: the literal value of `theme.<namespace>.<key>` when it is a string, else null. */
451
- function themeKeyValue(ctx, namespace, key) {
452
- const v = themeKeyEntry(ctx, namespace, key);
453
- return typeof v === "string" ? v : null;
454
- }
455
- /** #300: `var(--<varPrefix>-<key>)` when `theme.<namespace>.<key>` exists (the :root var BaroCSS emits for it), else null. */
456
- function themeKeyVar(ctx, namespace, key, varPrefix) {
457
- return themeKeyEntry(ctx, namespace, key) === void 0 ? null : `var(--${varPrefix}-${key})`;
458
- }
459
- /** #261: `var(--spacing-<key>)` for a named (non-numeric) `theme.spacing` key, else null. */
460
- function spacingKeyValue(ctx, key, negative) {
461
- if (key === "px" || !/^[a-zA-Z][\w-]*$/.test(key) || ctx.theme("spacing", key) == null) return null;
462
- const ref = `var(--spacing-${key})`;
463
- return negative ? `calc(${ref} * -1)` : ref;
307
+ function parseFractionOrNumber(value, opts = {}) {
308
+ if (/^\d+$/.test(value)) {
309
+ if (opts.repeat) return `repeat(${value}, minmax(0, 1fr))`;
310
+ return value;
311
+ }
312
+ if (value.includes("/")) {
313
+ const [numerator, denominator] = value.split("/").map(Number);
314
+ if (!isNaN(numerator) && !isNaN(denominator) && denominator !== 0) {
315
+ const result = numerator / denominator;
316
+ if (opts.percent) return `${result * 100}%`;
317
+ return result.toString();
318
+ }
319
+ }
320
+ return null;
464
321
  }
465
- function functionalUtility(opts, ctx) {
466
- registerUtility({
467
- name: opts.name,
468
- match: (className) => className.startsWith(opts.name + "-"),
469
- handler: (value, ctx, token, _options) => {
470
- let finalValue = value;
471
- const parsedUtility = token;
472
- const extra = { opacity: token.opacity };
473
- if (opts.supportsOpacity && !token.arbitrary && !token.customProperty && value.includes("/")) {
474
- const list = value.split("/");
475
- if (list.length >= 2) {
476
- extra.opacity = list.pop();
477
- finalValue = list.join("/");
478
- }
479
- }
480
- if (opts.supportsArbitrary && parsedUtility.arbitrary) {
481
- const processedValue = normalizeMathSpacing(expandThemeFunctions(finalValue.replace(/_/g, " ")));
482
- if (opts.handle) {
483
- const result = opts.handle(processedValue, ctx, token, extra);
484
- if (result) return result;
485
- }
486
- if (opts.prop) return [decl(opts.prop, processedValue)];
487
- return [];
488
- }
489
- if (opts.supportsCustomProperty && parsedUtility.customProperty) {
490
- if (opts.handleCustomProperty) return opts.handleCustomProperty(finalValue, ctx, token, extra);
491
- const customValue = `var(${finalValue})`;
492
- if (opts.handle) {
493
- const result = opts.handle(customValue, ctx, token, extra);
494
- if (result) return result;
495
- }
496
- if (opts.prop) return [decl(opts.prop, customValue)];
497
- return [];
498
- }
499
- let themeValue;
500
- if (opts.themeKey && ctx.theme) themeValue = themeScalar(ctx.theme(opts.themeKey, finalValue));
501
- let namespace = themeValue !== void 0 ? opts.themeKey : void 0;
502
- if (!themeValue && opts.themeKeys && ctx.theme) for (const key of opts.themeKeys) {
503
- themeValue = themeScalar(ctx.theme(key, finalValue));
504
- if (themeValue !== void 0) {
505
- namespace = key;
506
- break;
507
- }
508
- }
509
- if (themeValue !== void 0) {
510
- extra.themeNamespace = namespace;
511
- extra.themeKey = finalValue;
512
- if (namespace === "colors" || !(opts.themeKeys ?? [opts.themeKey]).includes("colors")) extra.realThemeValue = finalValue;
513
- finalValue = themeValue;
514
- if (opts.prop) return [decl(opts.prop, finalValue)];
515
- if (opts.handle) {
516
- const result = opts.handle(finalValue, ctx, token, extra);
517
- if (result) return result;
322
+ var CSS_COLOR_NAMES = /* @__PURE__ */ new Set([
323
+ "aliceblue",
324
+ "antiquewhite",
325
+ "aqua",
326
+ "aquamarine",
327
+ "azure",
328
+ "beige",
329
+ "bisque",
330
+ "black",
331
+ "blanchedalmond",
332
+ "blue",
333
+ "blueviolet",
334
+ "brown",
335
+ "burlywood",
336
+ "cadetblue",
337
+ "chartreuse",
338
+ "chocolate",
339
+ "coral",
340
+ "cornflowerblue",
341
+ "cornsilk",
342
+ "crimson",
343
+ "cyan",
344
+ "darkblue",
345
+ "darkcyan",
346
+ "darkgoldenrod",
347
+ "darkgray",
348
+ "darkgreen",
349
+ "darkgrey",
350
+ "darkkhaki",
351
+ "darkmagenta",
352
+ "darkolivegreen",
353
+ "darkorange",
354
+ "darkorchid",
355
+ "darkred",
356
+ "darksalmon",
357
+ "darkseagreen",
358
+ "darkslateblue",
359
+ "darkslategray",
360
+ "darkslategrey",
361
+ "darkturquoise",
362
+ "darkviolet",
363
+ "deeppink",
364
+ "deepskyblue",
365
+ "dimgray",
366
+ "dimgrey",
367
+ "dodgerblue",
368
+ "firebrick",
369
+ "floralwhite",
370
+ "forestgreen",
371
+ "fuchsia",
372
+ "gainsboro",
373
+ "ghostwhite",
374
+ "gold",
375
+ "goldenrod",
376
+ "gray",
377
+ "grey",
378
+ "green",
379
+ "greenyellow",
380
+ "honeydew",
381
+ "hotpink",
382
+ "indianred",
383
+ "indigo",
384
+ "ivory",
385
+ "khaki",
386
+ "lavender",
387
+ "lavenderblush",
388
+ "lawngreen",
389
+ "lemonchiffon",
390
+ "lightblue",
391
+ "lightcoral",
392
+ "lightcyan",
393
+ "lightgoldenrodyellow",
394
+ "lightgray",
395
+ "lightgreen",
396
+ "lightgrey",
397
+ "lightpink",
398
+ "lightsalmon",
399
+ "lightseagreen",
400
+ "lightskyblue",
401
+ "lightslategray",
402
+ "lightslategrey",
403
+ "lightsteelblue",
404
+ "lightyellow",
405
+ "lime",
406
+ "limegreen",
407
+ "linen",
408
+ "magenta",
409
+ "maroon",
410
+ "mediumaquamarine",
411
+ "mediumblue",
412
+ "mediumorchid",
413
+ "mediumpurple",
414
+ "mediumseagreen",
415
+ "mediumslateblue",
416
+ "mediumspringgreen",
417
+ "mediumturquoise",
418
+ "mediumvioletred",
419
+ "midnightblue",
420
+ "mintcream",
421
+ "mistyrose",
422
+ "moccasin",
423
+ "navajowhite",
424
+ "navy",
425
+ "oldlace",
426
+ "olive",
427
+ "olivedrab",
428
+ "orange",
429
+ "orangered",
430
+ "orchid",
431
+ "palegoldenrod",
432
+ "palegreen",
433
+ "paleturquoise",
434
+ "palevioletred",
435
+ "papayawhip",
436
+ "peachpuff",
437
+ "peru",
438
+ "pink",
439
+ "plum",
440
+ "powderblue",
441
+ "purple",
442
+ "red",
443
+ "rosybrown",
444
+ "royalblue",
445
+ "saddlebrown",
446
+ "salmon",
447
+ "sandybrown",
448
+ "seagreen",
449
+ "seashell",
450
+ "sienna",
451
+ "silver",
452
+ "skyblue",
453
+ "slateblue",
454
+ "slategray",
455
+ "slategrey",
456
+ "snow",
457
+ "springgreen",
458
+ "steelblue",
459
+ "tan",
460
+ "teal",
461
+ "thistle",
462
+ "tomato",
463
+ "turquoise",
464
+ "violet",
465
+ "wheat",
466
+ "white",
467
+ "whitesmoke",
468
+ "yellow",
469
+ "yellowgreen"
470
+ ]);
471
+ /**
472
+ * Returns the input if it is a valid color string, else null.
473
+ *
474
+ * #rgb, #rgba, #rrggbb, #rrggbbaa, rgb(r, g, b), rgb(r, g, b, a), hsl(h, s, l), hsl(h, s, l, a), hwb(h, w, b), hwb(h, w, b, a), lab(l, a, b), lab(l, a, b, a), lch(l, c, h), lch(l, c, h, a), oklab(l, a, b), oklab(l, a, b, a), oklch(l, c, h), oklch(l, c, h, a), color-mix(in oklab, var(--color-blue-500) 60%, transparent)
475
+ */
476
+ function parseColor(input) {
477
+ if (CSS_COLOR_NAMES.has(input.toLowerCase())) return input;
478
+ if (input.startsWith("color:var(")) return input.slice(6);
479
+ if (input.startsWith("color:")) return parseColor(input.slice(6));
480
+ if (input.startsWith("#") && input.length === 4) return `#${input.slice(1)}`;
481
+ if (input.startsWith("#") && input.length === 5) return `#${input.slice(1)}`;
482
+ if (input.startsWith("#") && input.length === 7) return `#${input.slice(1)}`;
483
+ if (input.startsWith("#") && input.length === 9) return `#${input.slice(1)}`;
484
+ if (input.startsWith("rgb(")) return input.slice(4, -1);
485
+ if (input.startsWith("rgba(")) return input.slice(5, -1);
486
+ if (input.startsWith("hsl(")) return input.slice(4, -1);
487
+ if (input.startsWith("hsla(")) return input.slice(5, -1);
488
+ if (input.startsWith("hwb(")) return input.slice(4, -1);
489
+ if (input.startsWith("lab(")) return input.slice(4, -1);
490
+ if (input.startsWith("lch(")) return input.slice(4, -1);
491
+ if (input.startsWith("oklab(")) return input.slice(5, -1);
492
+ if (input.startsWith("oklch(")) return input.slice(6, -1);
493
+ if (input.startsWith("color-mix(")) return input.slice(9, -1);
494
+ return null;
495
+ }
496
+ var COLOR_KEYWORDS = /* @__PURE__ */ new Set([
497
+ "inherit",
498
+ "currentcolor",
499
+ "transparent"
500
+ ]);
501
+ /**
502
+ * Declarations for a theme colour (#228), as Tailwind v4 emits them: `var(--color-<key>)` so runtime theme
503
+ * overrides apply; with an opacity modifier, a literal srgb color-mix fallback plus an oklab color-mix of the var.
504
+ */
505
+ function themeColorDecls(prop, value, extra) {
506
+ const key = String(extra.realThemeValue);
507
+ const ref = COLOR_KEYWORDS.has(value.toLowerCase()) || value.startsWith("var(") || !/^[\w-]+$/.test(key) ? value : `var(--color-${key})`;
508
+ if (!extra.opacity) return [decl(prop, ref)];
509
+ const alpha = normalizeAlpha(String(extra.opacity));
510
+ if (!alpha) return [];
511
+ const supports = (amount) => atRule("supports", "(color:color-mix(in lab, red, red))", [decl(prop, `color-mix(in oklab, ${ref} ${amount}, transparent)`)]);
512
+ if (alpha.isVar) return [decl(prop, value), supports(alpha.amount)];
513
+ return [decl(prop, `color-mix(in srgb, ${value} ${alpha.amount}, transparent)`), supports(alpha.amount)];
514
+ }
515
+ /**
516
+ * Opacity modifier → color-mix amount, as Tailwind v4 does: `50` → `50%`, `[37%]` → `37%`, `[0.5]` / `[.8]` → `50%` /
517
+ * `80%` (a bracketed number ≤ 1 is a fraction), `[var(--a)]` / `(--a)` → `var(--a)`.
518
+ */
519
+ function normalizeAlpha(raw) {
520
+ const v = raw.trim();
521
+ const cp = /^\((--[\w-]+)\)$/.exec(v) ?? /^\[var\((--[\w-]+)\)\]$/.exec(v);
522
+ if (cp) return {
523
+ amount: `var(${cp[1]})`,
524
+ isVar: true
525
+ };
526
+ const m = /^(\[)?(\d+(?:\.\d+)?|\.\d+)(%)?(\])?$/.exec(v);
527
+ if (!m || !!m[1] !== !!m[4] || m[3] && !m[1]) return null;
528
+ const n = Number(m[2]);
529
+ return {
530
+ amount: `${+(m[3] ? n : m[1] && n <= 1 ? n * 100 : n).toFixed(4)}%`,
531
+ isVar: false
532
+ };
533
+ }
534
+ var MIX_SUPPORTS = "(color:color-mix(in lab, red, red))";
535
+ var COLOR_PROP = /(^|-)color$|^(fill|stroke)$|^--baro-gradient-(from|via|to)$/;
536
+ /**
537
+ * #393: an arbitrary or custom-property colour with an opacity modifier, as Tailwind 4.3.3 emits it: a literal
538
+ * colour with a literal alpha mixes directly (`color-mix(in oklab, #f00 50%, transparent)`); a var colour or a var
539
+ * alpha keeps the plain colour and mixes only under `@supports`. Returns null for an alpha it can't express.
540
+ */
541
+ function colorAlphaDecls(prop, color, opacity) {
542
+ const alpha = normalizeAlpha(opacity);
543
+ if (!alpha) return null;
544
+ const mix = `color-mix(in oklab, ${color} ${alpha.amount}, transparent)`;
545
+ if (alpha.isVar || color.startsWith("var(")) return [decl(prop, color), atRule("supports", MIX_SUPPORTS, [decl(prop, mix)])];
546
+ return [decl(prop, mix)];
547
+ }
548
+ /**
549
+ * #393: applies an opacity modifier to every declaration of `nodes` whose value is one of `colors` (the colour an
550
+ * arbitrary / custom-property utility emitted without the modifier). Returns null when none matched or the alpha
551
+ * is invalid, so the caller emits nothing rather than dropping the modifier or writing a malformed value.
552
+ */
553
+ function applyColorAlpha(nodes, colors, opacity) {
554
+ let matched = false;
555
+ let invalid = false;
556
+ const walk = (list) => list.flatMap((n) => {
557
+ if (n.type === "decl" && typeof n.value === "string" && colors.includes(n.value)) {
558
+ matched = true;
559
+ const out = COLOR_PROP.test(n.prop) ? colorAlphaDecls(n.prop, n.value, opacity) : null;
560
+ if (!out) invalid = true;
561
+ return out ?? [];
562
+ }
563
+ if (n.type === "at-rule" || n.type === "rule" || n.type === "style-rule" || n.type === "at-root") return [{
564
+ ...n,
565
+ nodes: walk(n.nodes)
566
+ }];
567
+ if (n.type === "wrap") return [{
568
+ ...n,
569
+ items: walk(n.items)
570
+ }];
571
+ return [n];
572
+ });
573
+ const out = walk(nodes);
574
+ return matched && !invalid ? out : null;
575
+ }
576
+ //#endregion
577
+ //#region src/core/registry.ts
578
+ /** #393: a handler result meaning "this class is invalid": the engine stops trying other registrations. */
579
+ var REJECT_CLASS = Object.freeze([]);
580
+ var utilityRegistry = [];
581
+ function registerUtility(util, ctx) {
582
+ const state = ctx && getContextState(ctx);
583
+ if (ctx && !state) throw new Error("Utility registration requires a context from createContext");
584
+ (state?.utilities || utilityRegistry).push(util);
585
+ if (ctx) clearContextCaches(ctx);
586
+ else {
587
+ parseResultCache.clear();
588
+ utilityCache.clear();
589
+ }
590
+ }
591
+ function getUtility(ctx) {
592
+ return ctx && getContextState(ctx)?.utilities || utilityRegistry;
593
+ }
594
+ var modifierRegistry = [];
595
+ /**
596
+ * staticModifier: A helper that registers a modifier name and an array of CSS selectors directly to the registry
597
+ *
598
+ * @example
599
+ * ```
600
+ * staticModifier('disabled', ['&:disabled'], { source: 'pseudo' });
601
+ * ```
602
+ *
603
+ * @param name The name of the modifier
604
+ * @param selectors The selectors of the modifier
605
+ * @param options The options of the modifier
606
+ *
607
+ * @returns {void}
608
+ */
609
+ function staticModifier(name, selectors, options = {}, ctx) {
610
+ registerModifier({
611
+ name,
612
+ match: (mod) => mod === name,
613
+ modifySelector: ({ ..._rest }) => {
614
+ return selectors.map((sel) => ({
615
+ selector: sel,
616
+ source: options.source
617
+ }));
618
+ },
619
+ ...options
620
+ }, ctx);
621
+ }
622
+ function functionalModifier(match, modifySelector, wrap, options = {}, ctx) {
623
+ registerModifier({
624
+ match,
625
+ modifySelector,
626
+ wrap,
627
+ ...options
628
+ }, ctx);
629
+ }
630
+ function registerModifier(modifier, ctx) {
631
+ const state = ctx && getContextState(ctx);
632
+ if (ctx && !state) throw new Error("Modifier registration requires a context from createContext");
633
+ (state?.modifiers || modifierRegistry).push(modifier);
634
+ if (ctx) clearContextCaches(ctx);
635
+ }
636
+ function getModifier(ctx) {
637
+ return ctx && getContextState(ctx)?.modifiers || modifierRegistry;
638
+ }
639
+ var ESCAPE_REGEX = /[^A-Za-z0-9_-]/gu;
640
+ var UNSAFE_RAW = /^[\s\p{C}\p{Z}]$/u;
641
+ function escapeClassName(className) {
642
+ if (className === "-") return "\\-";
643
+ const lead = /^-?[0-9]/.exec(className);
644
+ if (lead) {
645
+ const i = lead[0].length - 1;
646
+ return className.slice(0, i) + "\\" + className.charCodeAt(i).toString(16) + " " + escapeRest(className.slice(i + 1));
647
+ }
648
+ return escapeRest(className);
649
+ }
650
+ function escapeRest(className) {
651
+ return className.replace(ESCAPE_REGEX, (c) => {
652
+ if (c === " ") return "\\x20 ";
653
+ if (c === ".") return "\\.";
654
+ if (c === "/") return "\\/";
655
+ if (c === ":") return "\\:";
656
+ if (c === "[") return "\\[";
657
+ if (c === "]") return "\\]";
658
+ if (c === "(") return "\\(";
659
+ if (c === ")") return "\\)";
660
+ if (c === "%") return "\\%";
661
+ if (c === "#") return "\\#";
662
+ if (c === ",") return "\\,";
663
+ if (c === "=") return "\\=";
664
+ if (c === "&") return "\\&";
665
+ if (c === "~") return "\\~";
666
+ if (c === "*") return "\\*";
667
+ if (c === "$") return "\\$";
668
+ if (c === "^") return "\\^";
669
+ if (c === "+") return "\\+";
670
+ if (c === "?") return "\\?";
671
+ if (c === "!") return "\\!";
672
+ if (c === "@") return "\\@";
673
+ if (c === "'") return "\\'";
674
+ if (c === "\"") return "\\\"";
675
+ if (c === "`") return "\\`";
676
+ if (c === ";") return "\\;";
677
+ if (c === "<") return "\\<";
678
+ if (c === ">") return "\\>";
679
+ if (c === "{") return "\\{";
680
+ if (c === "}") return "\\}";
681
+ if (c === "|") return "\\|";
682
+ if (c === "\\") return "\\\\";
683
+ if (UNSAFE_RAW.test(c)) return "\\" + c.codePointAt(0).toString(16) + " ";
684
+ return "\\" + c;
685
+ });
686
+ }
687
+ /**
688
+ * staticUtility: A helper that registers a utility name and an array of CSS declaration pairs directly to the registry
689
+ *
690
+ * @example
691
+ * ```
692
+ * staticUtility('block', [['display', 'block']]);
693
+ * staticUtility('hidden', [['display', 'none']]);
694
+ * staticUtility('space-x-px', [
695
+ * [
696
+ * '& > :not([hidden]) ~ :not([hidden])', // selector
697
+ * [
698
+ * ['margin-inline-start', '1px'], // [prop, value]
699
+ * ['margin-inline-end', '1px'], // [prop, value]
700
+ * ],
701
+ * ],
702
+ * ]);
703
+ * ```
704
+ *
705
+ * @param name The name of the utility
706
+ * @param decls The declarations of the utility
707
+ * @param opts The options of the utility
708
+ *
709
+ * @returns {void}
710
+ */
711
+ function staticUtility(name, decls, opts, ctx) {
712
+ registerUtility({
713
+ name,
714
+ match: (className) => {
715
+ return className === name;
716
+ },
717
+ handler: (value) => {
718
+ return decls.flatMap((params) => {
719
+ if (params.type) return [params];
720
+ if (typeof params === "function") return [params(value)];
721
+ const [a, b] = params;
722
+ if (typeof b === "string") return [decl(a, b)];
723
+ else if (Array.isArray(b)) return [rule(a, b.map(([prop, value]) => decl(prop, value)))];
724
+ return [];
725
+ });
726
+ },
727
+ description: opts?.description,
728
+ category: opts?.category,
729
+ priority: opts?.priority
730
+ }, ctx);
731
+ }
732
+ /**
733
+ * functionalUtility: A helper that registers dynamic utilities (theme, arbitrary, custom, negative, fraction, etc.) directly
734
+ *
735
+ * Example:
736
+ * functionalUtility({
737
+ * name: 'z',
738
+ * supportsNegative: true,
739
+ * themeKeys: ['--z-index'],
740
+ * handleBareValue: ({ value }) => isPositiveInteger(value) ? value : null,
741
+ * handle: (value) => [decl('z-index', value)],
742
+ * description: 'z-index utility',
743
+ * category: 'layout',
744
+ * });
745
+ */
746
+ /**
747
+ * #300: a theme key that no built-in utility names (`theme.extend.borderRadius.card`) still resolves, as in
748
+ * Tailwind 4 where `--radius-card` gives `rounded-card`. Only word keys that start with a letter (numbers stay
749
+ * bare values), never `DEFAULT`; unknown keys return null so the utility emits nothing (#213).
750
+ */
751
+ function themeKeyEntry(ctx, namespace, key) {
752
+ if (key === "DEFAULT" || !/^[a-zA-Z][\w-]*$/.test(key) || typeof ctx?.theme !== "function") return void 0;
753
+ const table = ctx.theme(namespace);
754
+ if (!table || typeof table !== "object" || !Object.prototype.hasOwnProperty.call(table, key)) return void 0;
755
+ return table[key] ?? void 0;
756
+ }
757
+ /** #300: the literal value of `theme.<namespace>.<key>` when it is a string, else null. */
758
+ function themeKeyValue(ctx, namespace, key) {
759
+ const v = themeKeyEntry(ctx, namespace, key);
760
+ return typeof v === "string" ? v : null;
761
+ }
762
+ /** #300: `var(--<varPrefix>-<key>)` when `theme.<namespace>.<key>` exists (the :root var BaroCSS emits for it), else null. */
763
+ function themeKeyVar(ctx, namespace, key, varPrefix) {
764
+ return themeKeyEntry(ctx, namespace, key) === void 0 ? null : `var(--${varPrefix}-${key})`;
765
+ }
766
+ /** #261: `var(--spacing-<key>)` for a named (non-numeric) `theme.spacing` key, else null. */
767
+ function spacingKeyValue(ctx, key, negative) {
768
+ if (key === "px" || !/^[a-zA-Z][\w-]*$/.test(key) || ctx.theme("spacing", key) == null) return null;
769
+ const ref = `var(--spacing-${key})`;
770
+ return negative ? `calc(${ref} * -1)` : ref;
771
+ }
772
+ function functionalUtility(opts, ctx) {
773
+ registerUtility({
774
+ name: opts.name,
775
+ match: (className) => className.startsWith(opts.name + "-"),
776
+ handler: (value, ctx, token, _options) => {
777
+ let finalValue = value;
778
+ const parsedUtility = token;
779
+ const extra = { opacity: token.opacity };
780
+ if (opts.supportsOpacity && !token.arbitrary && !token.customProperty && value.includes("/")) {
781
+ const list = value.split("/");
782
+ if (list.length >= 2) {
783
+ extra.opacity = list.pop();
784
+ finalValue = list.join("/");
785
+ }
786
+ }
787
+ const splitModifier = !token.arbitrary && !token.customProperty && value.includes("/");
788
+ if (opts.supportsOpacity && (extra.opacity || splitModifier) && !normalizeAlpha(String(extra.opacity ?? ""))) {
789
+ const v = parsedUtility.arbitrary ? finalValue.replace(/_/g, " ") : finalValue;
790
+ return (parsedUtility.customProperty ? !/^[\w-]+:/.test(v) || v.startsWith("color:") : parsedUtility.arbitrary ? !!parseColor(v) || /^var\(--/.test(v) || v.startsWith("color:") : false) ? REJECT_CLASS : [];
791
+ }
792
+ const direct = (x) => {
793
+ if (opts.supportsArbitrary && parsedUtility.arbitrary) {
794
+ const processedValue = normalizeMathSpacing(expandThemeFunctions(finalValue.replace(/_/g, " ")));
795
+ if (opts.handle) {
796
+ const result = opts.handle(processedValue, ctx, token, x);
797
+ if (result) return result;
798
+ }
799
+ if (opts.prop) return [decl(opts.prop, processedValue)];
800
+ return [];
801
+ }
802
+ if (opts.supportsCustomProperty && parsedUtility.customProperty) {
803
+ if (opts.handleCustomProperty) return opts.handleCustomProperty(finalValue, ctx, token, x) ?? null;
804
+ const customValue = `var(${finalValue})`;
805
+ if (opts.handle) {
806
+ const result = opts.handle(customValue, ctx, token, x);
807
+ if (result) return result;
808
+ }
809
+ if (opts.prop) return [decl(opts.prop, customValue)];
810
+ return [];
811
+ }
812
+ return null;
813
+ };
814
+ if (opts.supportsArbitrary && parsedUtility.arbitrary || opts.supportsCustomProperty && parsedUtility.customProperty) {
815
+ const result = direct(extra);
816
+ if (opts.supportsOpacity && !opts.ownsOpacity && extra.opacity && result?.length) {
817
+ const raw = parsedUtility.arbitrary ? normalizeMathSpacing(expandThemeFunctions(finalValue.replace(/_/g, " "))) : `var(${finalValue})`;
818
+ const hint = parsedUtility.arbitrary ? /^color:(.+)$/.exec(raw)?.[1] : /^color:(--.+)$/.exec(finalValue)?.[1];
819
+ return applyColorAlpha(result, [raw, ...hint ? [hint, `var(${hint})`] : []], String(extra.opacity)) ?? [];
820
+ }
821
+ return result;
822
+ }
823
+ let themeValue;
824
+ if (opts.themeKey && ctx.theme) themeValue = themeScalar(ctx.theme(opts.themeKey, finalValue));
825
+ let namespace = themeValue !== void 0 ? opts.themeKey : void 0;
826
+ if (!themeValue && opts.themeKeys && ctx.theme) for (const key of opts.themeKeys) {
827
+ themeValue = themeScalar(ctx.theme(key, finalValue));
828
+ if (themeValue !== void 0) {
829
+ namespace = key;
830
+ break;
831
+ }
832
+ }
833
+ if (themeValue !== void 0) {
834
+ extra.themeNamespace = namespace;
835
+ extra.themeKey = finalValue;
836
+ if (namespace === "colors" || !(opts.themeKeys ?? [opts.themeKey]).includes("colors")) extra.realThemeValue = finalValue;
837
+ finalValue = themeValue;
838
+ if (opts.prop) return [decl(opts.prop, finalValue)];
839
+ if (opts.handle) {
840
+ const result = opts.handle(finalValue, ctx, token, extra);
841
+ if (result) return result;
518
842
  }
519
843
  return [];
520
844
  }
@@ -912,6 +1236,46 @@ function isBalancedPrelude(text) {
912
1236
  return stack.length === 0 && !quote;
913
1237
  }
914
1238
  /**
1239
+ * #392: true when every top-level comma part of an emitted selector names `escapedClass` (a class selector
1240
+ * already escaped with escapeClassName, including its leading dot) as a whole class token, or, when
1241
+ * `allowNesting` is set, uses the nesting selector `&`. Escapes, quoted strings and bracket groups are skipped
1242
+ * when splitting. Used as a defence-in-depth serializer check: a rule scoped to no generating class is dropped.
1243
+ */
1244
+ function isScopedSelector(selector, escapedClass, allowNesting = false) {
1245
+ const parts = [];
1246
+ let depth = 0;
1247
+ let quote = "";
1248
+ let start = 0;
1249
+ for (let i = 0; i < selector.length; i++) {
1250
+ const c = selector[i];
1251
+ if (c === "\\") {
1252
+ i++;
1253
+ continue;
1254
+ }
1255
+ if (quote) {
1256
+ if (c === quote) quote = "";
1257
+ continue;
1258
+ }
1259
+ if (c === "\"" || c === "'") quote = c;
1260
+ else if (c === "(" || c === "[") depth++;
1261
+ else if (c === ")" || c === "]") depth--;
1262
+ else if (c === "," && depth === 0) {
1263
+ parts.push(selector.slice(start, i));
1264
+ start = i + 1;
1265
+ }
1266
+ }
1267
+ parts.push(selector.slice(start));
1268
+ return parts.every((part) => {
1269
+ if (allowNesting && part.includes("&")) return true;
1270
+ for (let at = part.indexOf(escapedClass); at !== -1; at = part.indexOf(escapedClass, at + 1)) {
1271
+ if (at > 0 && part[at - 1] === "\\") continue;
1272
+ const next = part[at + escapedClass.length];
1273
+ if (escapedClass.endsWith(" ") || next === void 0 || !/[\w\-\\\u0080-\uffff]/.test(next)) return true;
1274
+ }
1275
+ return false;
1276
+ });
1277
+ }
1278
+ /**
915
1279
  * #323: true when emitted text contains a markup end-tag opener (less-than then slash). Generated CSS can be
916
1280
  * placed inside an HTML style element, where that sequence could end the element early. CSS escapes in the
917
1281
  * output never form it, and a lone less-than (range media queries) stays allowed.
@@ -1003,6 +1367,13 @@ function parseModifier(value) {
1003
1367
  function nameSort(a, b) {
1004
1368
  return b.name.length - a.name.length;
1005
1369
  }
1370
+ /** #393: index of the `close` that balances the value opened just before `s` (depth starts at 1), or -1. */
1371
+ function matchingClose(s, open, close) {
1372
+ let depth = 1;
1373
+ for (let i = 0; i < s.length; i++) if (s[i] === open) depth++;
1374
+ else if (s[i] === close && --depth === 0) return i;
1375
+ return -1;
1376
+ }
1006
1377
  /**
1007
1378
  * Parse utility token
1008
1379
  */
@@ -1031,15 +1402,27 @@ function parseUtility(value, ctx) {
1031
1402
  if (value.startsWith("-")) negative = true;
1032
1403
  if (value.includes("-[")) {
1033
1404
  [prefix, utilityValue] = value.split("-[");
1034
- const closeIdx = utilityValue.lastIndexOf("]");
1405
+ const closeIdx = matchingClose(utilityValue, "[", "]");
1035
1406
  if (closeIdx !== -1 && closeIdx < utilityValue.length - 1 && utilityValue[closeIdx + 1] === "/") {
1036
1407
  opacity = utilityValue.slice(closeIdx + 2);
1408
+ if (!opacity) return {
1409
+ prefix: "",
1410
+ value: ""
1411
+ };
1037
1412
  utilityValue = utilityValue.slice(0, closeIdx);
1038
1413
  } else utilityValue = utilityValue.replace(/]$/, "");
1039
1414
  arbitrary = true;
1040
1415
  } else if (value.includes("-(")) {
1041
1416
  [prefix, utilityValue] = value.split("-(");
1042
- utilityValue = utilityValue.replace(/\)$/, "");
1417
+ const closeIdx = matchingClose(utilityValue, "(", ")");
1418
+ if (closeIdx !== -1 && closeIdx < utilityValue.length - 1 && utilityValue[closeIdx + 1] === "/") {
1419
+ opacity = utilityValue.slice(closeIdx + 2);
1420
+ if (!opacity) return {
1421
+ prefix: "",
1422
+ value: ""
1423
+ };
1424
+ utilityValue = utilityValue.slice(0, closeIdx);
1425
+ } else utilityValue = utilityValue.replace(/\)$/, "");
1043
1426
  customProperty = true;
1044
1427
  } else {
1045
1428
  const sortedUtilities = [...getUtility(ctx)].sort(nameSort);
@@ -1091,6 +1474,13 @@ var uniqueDescriptors = (node) => {
1091
1474
  const seen = /* @__PURE__ */ new Set();
1092
1475
  return node.nodes.filter((c) => c.type !== "decl" || !seen.has(c.prop) && !!seen.add(c.prop));
1093
1476
  };
1477
+ var NO_IMPORTANT_AT = /* @__PURE__ */ new Set([
1478
+ "property",
1479
+ "font-face",
1480
+ "keyframes",
1481
+ "-webkit-keyframes",
1482
+ "counter-style"
1483
+ ]);
1094
1484
  var isSafeDecl = (prop, value) => isStructureSafeValue(String(prop)) && isStructureSafeValue(String(value ?? "")) && !hasHtmlEndTagOpener(String(prop)) && !hasHtmlEndTagOpener(String(value ?? ""));
1095
1485
  var importantPrefix = "!important";
1096
1486
  /**
@@ -1105,6 +1495,12 @@ function astToCss(ast, baseSelector, opts, _indent = "") {
1105
1495
  const indent = _indent;
1106
1496
  const nextIndent = _indent + " ";
1107
1497
  const importantString = opts?.important ?? false ? ` ${importantPrefix}` : "";
1498
+ const nestedOpts = opts ? {
1499
+ ...opts,
1500
+ nested: true
1501
+ } : opts;
1502
+ const scopeClass = opts?.scope ? "." + escapeClassName(opts.scope) : "";
1503
+ const inScope = (sel) => !scopeClass || isScopedSelector(sel, scopeClass, !!opts?.nested);
1108
1504
  if (!ast || ast.length === 0) {
1109
1505
  debugWarn("[astToCss] Empty AST received:", {
1110
1506
  ast,
@@ -1147,18 +1543,23 @@ function astToCss(ast, baseSelector, opts, _indent = "") {
1147
1543
  else return escBase + (sel.startsWith(".") ? "" : " ") + sel;
1148
1544
  }).join(", ");
1149
1545
  }
1150
- if (!isSafePrelude(selector)) return "";
1151
- if (minify) return `${indent}${selector}{${astToCss(node.nodes, baseSelector, opts, nextIndent)}}`;
1152
- else return `${indent}${selector} {\n${astToCss(node.nodes, baseSelector, opts, nextIndent)}${indent}}`;
1546
+ if (!isSafePrelude(selector) || !inScope(selector)) return "";
1547
+ if (minify) return `${indent}${selector}{${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}}`;
1548
+ else return `${indent}${selector} {\n${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}${indent}}`;
1153
1549
  }
1154
1550
  case "style-rule":
1155
- if (!isSafePrelude(node.selector)) return "";
1156
- if (minify) return `${indent}${node.selector} {${astToCss(node.nodes, baseSelector, opts, nextIndent)}}`;
1157
- else return `${indent}${node.selector} {\n${astToCss(node.nodes, baseSelector, opts, nextIndent)}${indent}}`;
1158
- case "at-rule":
1551
+ if (!isSafePrelude(node.selector) || !inScope(node.selector)) return "";
1552
+ if (minify) return `${indent}${node.selector} {${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}}`;
1553
+ else return `${indent}${node.selector} {\n${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}${indent}}`;
1554
+ case "at-rule": {
1159
1555
  if (!isSafePrelude(node.name) || !isSafePrelude(node.params)) return "";
1160
- if (minify) return `${indent}@${node.name} ${node.params}{${astToCss(node.nodes, baseSelector, opts, nextIndent)}}`;
1161
- else return `${indent}@${node.name} ${node.params} {\n${astToCss(node.nodes, baseSelector, opts, nextIndent)}${indent}}`;
1556
+ const atOpts = opts?.important && NO_IMPORTANT_AT.has(node.name) ? {
1557
+ ...opts,
1558
+ important: false
1559
+ } : opts;
1560
+ if (minify) return `${indent}@${node.name} ${node.params}{${astToCss(node.nodes, baseSelector, atOpts, nextIndent)}}`;
1561
+ else return `${indent}@${node.name} ${node.params} {\n${astToCss(node.nodes, baseSelector, atOpts, nextIndent)}${indent}}`;
1562
+ }
1162
1563
  case "comment": return minify ? "" : `${indent}/* ${node.text} */`;
1163
1564
  case "raw": return `${indent}${node.value}`;
1164
1565
  default:
@@ -1517,6 +1918,552 @@ function applyVarPrefix(ast, ctx) {
1517
1918
  return walk(ast);
1518
1919
  }
1519
1920
  //#endregion
1921
+ //#region src/core/tw-property-order.ts
1922
+ var TW_PROPERTY_ORDER = [
1923
+ "container-type",
1924
+ "pointer-events",
1925
+ "visibility",
1926
+ "position",
1927
+ "inset",
1928
+ "inset-inline",
1929
+ "inset-block",
1930
+ "inset-inline-start",
1931
+ "inset-inline-end",
1932
+ "inset-block-start",
1933
+ "inset-block-end",
1934
+ "top",
1935
+ "right",
1936
+ "bottom",
1937
+ "left",
1938
+ "isolation",
1939
+ "z-index",
1940
+ "order",
1941
+ "grid-column",
1942
+ "grid-column-start",
1943
+ "grid-column-end",
1944
+ "grid-row",
1945
+ "grid-row-start",
1946
+ "grid-row-end",
1947
+ "float",
1948
+ "clear",
1949
+ "--tw-container-component",
1950
+ "margin",
1951
+ "margin-inline",
1952
+ "margin-block",
1953
+ "margin-inline-start",
1954
+ "margin-inline-end",
1955
+ "margin-block-start",
1956
+ "margin-block-end",
1957
+ "margin-top",
1958
+ "margin-right",
1959
+ "margin-bottom",
1960
+ "margin-left",
1961
+ "box-sizing",
1962
+ "display",
1963
+ "field-sizing",
1964
+ "aspect-ratio",
1965
+ "height",
1966
+ "max-height",
1967
+ "min-height",
1968
+ "width",
1969
+ "max-width",
1970
+ "min-width",
1971
+ "flex",
1972
+ "flex-shrink",
1973
+ "flex-grow",
1974
+ "flex-basis",
1975
+ "table-layout",
1976
+ "caption-side",
1977
+ "border-collapse",
1978
+ "border-spacing",
1979
+ "transform-origin",
1980
+ "translate",
1981
+ "--tw-translate-x",
1982
+ "--tw-translate-y",
1983
+ "--tw-translate-z",
1984
+ "scale",
1985
+ "--tw-scale-x",
1986
+ "--tw-scale-y",
1987
+ "--tw-scale-z",
1988
+ "rotate",
1989
+ "--tw-rotate-x",
1990
+ "--tw-rotate-y",
1991
+ "--tw-rotate-z",
1992
+ "--tw-skew-x",
1993
+ "--tw-skew-y",
1994
+ "transform",
1995
+ "zoom",
1996
+ "animation",
1997
+ "cursor",
1998
+ "touch-action",
1999
+ "--tw-pan-x",
2000
+ "--tw-pan-y",
2001
+ "--tw-pinch-zoom",
2002
+ "resize",
2003
+ "scroll-snap-type",
2004
+ "--tw-scroll-snap-strictness",
2005
+ "scroll-snap-align",
2006
+ "scroll-snap-stop",
2007
+ "scroll-margin",
2008
+ "scroll-margin-inline",
2009
+ "scroll-margin-block",
2010
+ "scroll-margin-inline-start",
2011
+ "scroll-margin-inline-end",
2012
+ "scroll-margin-block-start",
2013
+ "scroll-margin-block-end",
2014
+ "scroll-margin-top",
2015
+ "scroll-margin-right",
2016
+ "scroll-margin-bottom",
2017
+ "scroll-margin-left",
2018
+ "scroll-padding",
2019
+ "scroll-padding-inline",
2020
+ "scroll-padding-block",
2021
+ "scroll-padding-inline-start",
2022
+ "scroll-padding-inline-end",
2023
+ "scroll-padding-block-start",
2024
+ "scroll-padding-block-end",
2025
+ "scroll-padding-top",
2026
+ "scroll-padding-right",
2027
+ "scroll-padding-bottom",
2028
+ "scroll-padding-left",
2029
+ "scrollbar-width",
2030
+ "scrollbar-color",
2031
+ "scrollbar-gutter",
2032
+ "list-style-position",
2033
+ "list-style-type",
2034
+ "list-style-image",
2035
+ "appearance",
2036
+ "columns",
2037
+ "break-before",
2038
+ "break-inside",
2039
+ "break-after",
2040
+ "grid-auto-columns",
2041
+ "grid-auto-flow",
2042
+ "grid-auto-rows",
2043
+ "grid-template-columns",
2044
+ "grid-template-rows",
2045
+ "flex-direction",
2046
+ "flex-wrap",
2047
+ "place-content",
2048
+ "place-items",
2049
+ "align-content",
2050
+ "align-items",
2051
+ "justify-content",
2052
+ "justify-items",
2053
+ "gap",
2054
+ "column-gap",
2055
+ "row-gap",
2056
+ "--tw-space-x-reverse",
2057
+ "--tw-space-y-reverse",
2058
+ "divide-x-width",
2059
+ "divide-y-width",
2060
+ "--tw-divide-y-reverse",
2061
+ "divide-style",
2062
+ "divide-color",
2063
+ "place-self",
2064
+ "align-self",
2065
+ "justify-self",
2066
+ "overflow",
2067
+ "overflow-x",
2068
+ "overflow-y",
2069
+ "overscroll-behavior",
2070
+ "overscroll-behavior-x",
2071
+ "overscroll-behavior-y",
2072
+ "scroll-behavior",
2073
+ "border-radius",
2074
+ "border-start-radius",
2075
+ "border-end-radius",
2076
+ "border-top-radius",
2077
+ "border-right-radius",
2078
+ "border-bottom-radius",
2079
+ "border-left-radius",
2080
+ "border-start-start-radius",
2081
+ "border-start-end-radius",
2082
+ "border-end-end-radius",
2083
+ "border-end-start-radius",
2084
+ "border-top-left-radius",
2085
+ "border-top-right-radius",
2086
+ "border-bottom-right-radius",
2087
+ "border-bottom-left-radius",
2088
+ "border-width",
2089
+ "border-inline-width",
2090
+ "border-block-width",
2091
+ "border-inline-start-width",
2092
+ "border-inline-end-width",
2093
+ "border-block-start-width",
2094
+ "border-block-end-width",
2095
+ "border-top-width",
2096
+ "border-right-width",
2097
+ "border-bottom-width",
2098
+ "border-left-width",
2099
+ "border-style",
2100
+ "border-inline-style",
2101
+ "border-block-style",
2102
+ "border-inline-start-style",
2103
+ "border-inline-end-style",
2104
+ "border-block-start-style",
2105
+ "border-block-end-style",
2106
+ "border-top-style",
2107
+ "border-right-style",
2108
+ "border-bottom-style",
2109
+ "border-left-style",
2110
+ "border-color",
2111
+ "border-inline-color",
2112
+ "border-block-color",
2113
+ "border-inline-start-color",
2114
+ "border-inline-end-color",
2115
+ "border-block-start-color",
2116
+ "border-block-end-color",
2117
+ "border-top-color",
2118
+ "border-right-color",
2119
+ "border-bottom-color",
2120
+ "border-left-color",
2121
+ "background-color",
2122
+ "background-image",
2123
+ "--tw-gradient-position",
2124
+ "--tw-gradient-stops",
2125
+ "--tw-gradient-via-stops",
2126
+ "--tw-gradient-from",
2127
+ "--tw-gradient-from-position",
2128
+ "--tw-gradient-via",
2129
+ "--tw-gradient-via-position",
2130
+ "--tw-gradient-to",
2131
+ "--tw-gradient-to-position",
2132
+ "mask-image",
2133
+ "--tw-mask-top",
2134
+ "--tw-mask-top-from-color",
2135
+ "--tw-mask-top-from-position",
2136
+ "--tw-mask-top-to-color",
2137
+ "--tw-mask-top-to-position",
2138
+ "--tw-mask-right",
2139
+ "--tw-mask-right-from-color",
2140
+ "--tw-mask-right-from-position",
2141
+ "--tw-mask-right-to-color",
2142
+ "--tw-mask-right-to-position",
2143
+ "--tw-mask-bottom",
2144
+ "--tw-mask-bottom-from-color",
2145
+ "--tw-mask-bottom-from-position",
2146
+ "--tw-mask-bottom-to-color",
2147
+ "--tw-mask-bottom-to-position",
2148
+ "--tw-mask-left",
2149
+ "--tw-mask-left-from-color",
2150
+ "--tw-mask-left-from-position",
2151
+ "--tw-mask-left-to-color",
2152
+ "--tw-mask-left-to-position",
2153
+ "--tw-mask-linear",
2154
+ "--tw-mask-linear-position",
2155
+ "--tw-mask-linear-from-color",
2156
+ "--tw-mask-linear-from-position",
2157
+ "--tw-mask-linear-to-color",
2158
+ "--tw-mask-linear-to-position",
2159
+ "--tw-mask-radial",
2160
+ "--tw-mask-radial-shape",
2161
+ "--tw-mask-radial-size",
2162
+ "--tw-mask-radial-position",
2163
+ "--tw-mask-radial-from-color",
2164
+ "--tw-mask-radial-from-position",
2165
+ "--tw-mask-radial-to-color",
2166
+ "--tw-mask-radial-to-position",
2167
+ "--tw-mask-conic",
2168
+ "--tw-mask-conic-position",
2169
+ "--tw-mask-conic-from-color",
2170
+ "--tw-mask-conic-from-position",
2171
+ "--tw-mask-conic-to-color",
2172
+ "--tw-mask-conic-to-position",
2173
+ "box-decoration-break",
2174
+ "background-size",
2175
+ "background-attachment",
2176
+ "background-clip",
2177
+ "background-position",
2178
+ "background-repeat",
2179
+ "background-origin",
2180
+ "mask-composite",
2181
+ "mask-mode",
2182
+ "mask-type",
2183
+ "mask-size",
2184
+ "mask-clip",
2185
+ "mask-position",
2186
+ "mask-repeat",
2187
+ "mask-origin",
2188
+ "fill",
2189
+ "stroke",
2190
+ "stroke-width",
2191
+ "object-fit",
2192
+ "object-position",
2193
+ "padding",
2194
+ "padding-inline",
2195
+ "padding-block",
2196
+ "padding-inline-start",
2197
+ "padding-inline-end",
2198
+ "padding-block-start",
2199
+ "padding-block-end",
2200
+ "padding-top",
2201
+ "padding-right",
2202
+ "padding-bottom",
2203
+ "padding-left",
2204
+ "text-align",
2205
+ "text-indent",
2206
+ "vertical-align",
2207
+ "font-family",
2208
+ "font-feature-settings",
2209
+ "font-size",
2210
+ "line-height",
2211
+ "font-weight",
2212
+ "letter-spacing",
2213
+ "text-wrap",
2214
+ "overflow-wrap",
2215
+ "word-break",
2216
+ "text-overflow",
2217
+ "hyphens",
2218
+ "white-space",
2219
+ "tab-size",
2220
+ "color",
2221
+ "text-transform",
2222
+ "font-style",
2223
+ "font-stretch",
2224
+ "font-variant-numeric",
2225
+ "text-decoration-line",
2226
+ "text-decoration-color",
2227
+ "text-decoration-style",
2228
+ "text-decoration-thickness",
2229
+ "text-underline-offset",
2230
+ "-webkit-font-smoothing",
2231
+ "placeholder-color",
2232
+ "caret-color",
2233
+ "accent-color",
2234
+ "color-scheme",
2235
+ "opacity",
2236
+ "background-blend-mode",
2237
+ "mix-blend-mode",
2238
+ "box-shadow",
2239
+ "--tw-shadow",
2240
+ "--tw-shadow-color",
2241
+ "--tw-ring-shadow",
2242
+ "--tw-ring-color",
2243
+ "--tw-inset-shadow",
2244
+ "--tw-inset-shadow-color",
2245
+ "--tw-inset-ring-shadow",
2246
+ "--tw-inset-ring-color",
2247
+ "--tw-ring-offset-width",
2248
+ "--tw-ring-offset-color",
2249
+ "outline",
2250
+ "outline-width",
2251
+ "outline-offset",
2252
+ "outline-color",
2253
+ "--tw-blur",
2254
+ "--tw-brightness",
2255
+ "--tw-contrast",
2256
+ "--tw-drop-shadow",
2257
+ "--tw-grayscale",
2258
+ "--tw-hue-rotate",
2259
+ "--tw-invert",
2260
+ "--tw-saturate",
2261
+ "--tw-sepia",
2262
+ "filter",
2263
+ "--tw-backdrop-blur",
2264
+ "--tw-backdrop-brightness",
2265
+ "--tw-backdrop-contrast",
2266
+ "--tw-backdrop-grayscale",
2267
+ "--tw-backdrop-hue-rotate",
2268
+ "--tw-backdrop-invert",
2269
+ "--tw-backdrop-opacity",
2270
+ "--tw-backdrop-saturate",
2271
+ "--tw-backdrop-sepia",
2272
+ "backdrop-filter",
2273
+ "transition-property",
2274
+ "transition-behavior",
2275
+ "transition-delay",
2276
+ "transition-duration",
2277
+ "transition-timing-function",
2278
+ "will-change",
2279
+ "contain",
2280
+ "content",
2281
+ "forced-color-adjust"
2282
+ ];
2283
+ //#endregion
2284
+ //#region src/core/rule-order.ts
2285
+ /**
2286
+ * Tailwind-compatible cascade order for runtime-inserted rules (#254); shared by @barocss/server (#267).
2287
+ *
2288
+ * The runtime discovers classes in DOM order, so without sorting `lg:px-8`
2289
+ * seen before `sm:px-6` would land earlier and lose at >= 1024px. Each rule
2290
+ * gets a sort key derived from its leading `@media` / `@container` preludes:
2291
+ *
2292
+ * 0 base, negated media (`not-md:` → `@media not (…)`, as Tailwind 4.3.3 orders them, #352),
2293
+ * state media (hover), motion/contrast, unknown
2294
+ * 1 max-* breakpoints (larger width first)
2295
+ * 2 min-* breakpoints (smaller width first)
2296
+ * 3 @max-* container queries (larger width first)
2297
+ * 4 @min-* container queries (smaller width first)
2298
+ * 5 orientation, dark (prefers-color-scheme), print, forced-colors
2299
+ *
2300
+ * Nested at-rules (e.g. `sm:dark:`) contribute one key pair per level, so
2301
+ * `sm:` < `sm:dark:` < `md:`.
2302
+ *
2303
+ * #401: within one variant key, rules follow Tailwind 4's property order (the candidate sort of
2304
+ * Tailwind 4.3.3's `compile()`): compare the sorted TW property indices of each rule's declarations up
2305
+ * to the first difference (a rule that runs out of indices sorts last), then more declarations first,
2306
+ * then the class name (Tailwind's numeric-aware compare). Equal keys keep discovery order.
2307
+ */
2308
+ var LEADING_AT = /^\s*@(media|container)\s+([^{]*)\{/;
2309
+ var LATE_MEDIA = /prefers-color-scheme|\bprint\b|forced-colors|orientation/;
2310
+ var MIN_W = /(?:min-width\s*:\s*|width\s*>=?\s*)([\d.]+)(px|rem|em)?/;
2311
+ var MAX_W = /(?:max-width\s*:\s*|width\s*<=?\s*)([\d.]+)(px|rem|em)?/;
2312
+ /** Separates the variant pairs (whose first slot is >= 0) from the property part of a key. */
2313
+ var PROPERTY_PART = -1;
2314
+ /** A rule that has run out of property indices sorts after every real index (TW: `?? Infinity`). */
2315
+ var NO_MORE = Number.MAX_SAFE_INTEGER;
2316
+ var PROPERTY_INDEX = new Map(TW_PROPERTY_ORDER.map((p, i) => [p, i]));
2317
+ var DECL = /(?:^|[{;])\s*(-{0,2}[a-zA-Z][\w-]*)\s*:[^;{}]*(?=[;}])/g;
2318
+ var AT_PRELUDE = /^\s*@[\w-]+[^{]*\{/;
2319
+ var CLASS = /\.((?:\\.|[\w-])+)/;
2320
+ function toPx(n, unit) {
2321
+ const v = parseFloat(n);
2322
+ return unit === "rem" || unit === "em" ? v * 16 : v;
2323
+ }
2324
+ function preludeKey(kind, prelude) {
2325
+ const container = kind === "container";
2326
+ if (!container && /^\s*not\b/i.test(prelude)) return [0, 0];
2327
+ const min = MIN_W.exec(prelude);
2328
+ if (min) return [container ? 4 : 2, toPx(min[1], min[2])];
2329
+ const max = MAX_W.exec(prelude);
2330
+ if (max) return [container ? 3 : 1, -toPx(max[1], max[2])];
2331
+ if (!container && LATE_MEDIA.test(prelude)) return [5, 0];
2332
+ return [0, 0];
2333
+ }
2334
+ /** The rule text after its leading at-rule preludes, up to its first `{` (the selector). */
2335
+ function ruleSelector(rule) {
2336
+ let rest = rule;
2337
+ let m;
2338
+ while (m = AT_PRELUDE.exec(rest)) rest = rest.slice(m[0].length);
2339
+ const end = rest.indexOf("{");
2340
+ return end === -1 ? "" : rest.slice(0, end);
2341
+ }
2342
+ /**
2343
+ * Tailwind's `--tw-sort` overrides (a utility sorts as one pseudo-property), recognised from BaroCSS's
2344
+ * output for the same utilities: space-x/y, divide-*, placeholder colour, gradient stops, container.
2345
+ * (TW's `size-*` override names no listed property, so Tailwind ignores it, and so does this.)
2346
+ */
2347
+ function sortOverride(selector, props, candidate) {
2348
+ const first = props[0];
2349
+ if (first === "--tw-space-x-reverse") return "row-gap";
2350
+ if (first === "--tw-space-y-reverse") return "column-gap";
2351
+ if (first === "--tw-divide-x-reverse") return "divide-x-width";
2352
+ if (first === "--tw-divide-y-reverse") return "divide-y-width";
2353
+ if (selector.includes(":not(:last-child)")) {
2354
+ if (props.includes("border-color")) return "divide-color";
2355
+ if (props.includes("border-style")) return "divide-style";
2356
+ }
2357
+ if (selector.includes("::placeholder") && props.includes("color")) return "placeholder-color";
2358
+ for (const stop of [
2359
+ "from",
2360
+ "via",
2361
+ "to"
2362
+ ]) if (props.includes(`--tw-gradient-${stop}`)) return `--tw-gradient-${stop}`;
2363
+ if (candidate.slice(candidate.lastIndexOf(":") + 1) === "container") return "--tw-container-component";
2364
+ return null;
2365
+ }
2366
+ /**
2367
+ * Tailwind's per-candidate property sort (#401): the sorted, de-duplicated TW property-order indices of
2368
+ * the rule's declarations (at any depth), and the declaration count. `--baro-*` vars count as `--tw-*`.
2369
+ */
2370
+ /** @internal (#401) */ function rulePropertySort(rule, candidate = ruleCandidate(rule)) {
2371
+ const props = [];
2372
+ for (const d of rule.matchAll(DECL)) props.push(d[1].startsWith("--baro-") ? "--tw-" + d[1].slice(7) : d[1]);
2373
+ const override = sortOverride(ruleSelector(rule), props, candidate);
2374
+ const overrideIndex = override === null ? void 0 : PROPERTY_INDEX.get(override);
2375
+ if (overrideIndex !== void 0) return {
2376
+ order: [overrideIndex],
2377
+ count: props.length + 1
2378
+ };
2379
+ const set = /* @__PURE__ */ new Set();
2380
+ for (const p of props) {
2381
+ const i = PROPERTY_INDEX.get(p);
2382
+ if (i !== void 0) set.add(i);
2383
+ }
2384
+ return {
2385
+ order: Array.from(set).sort((a, b) => a - b),
2386
+ count: props.length
2387
+ };
2388
+ }
2389
+ /** The (unescaped) first class in the rule's selector, e.g. `sm:px-2`. */
2390
+ /** @internal (#401) */ function ruleCandidate(rule) {
2391
+ const c = CLASS.exec(ruleSelector(rule));
2392
+ return c ? c[1].replace(/\\(.)/g, "$1") : "";
2393
+ }
2394
+ /** Tailwind's candidate compare: runs of digits compare by value, other chars by code. */
2395
+ /** @internal (#401) */ function compareCandidates(a, b) {
2396
+ const n = Math.min(a.length, b.length);
2397
+ for (let i = 0; i < n; i++) {
2398
+ let x = a.charCodeAt(i);
2399
+ let y = b.charCodeAt(i);
2400
+ if (x >= 48 && x <= 57 && y >= 48 && y <= 57) {
2401
+ let ae = i + 1;
2402
+ let be = i + 1;
2403
+ for (x = a.charCodeAt(ae); x >= 48 && x <= 57;) x = a.charCodeAt(++ae);
2404
+ for (y = b.charCodeAt(be); y >= 48 && y <= 57;) y = b.charCodeAt(++be);
2405
+ const as = a.slice(i, ae);
2406
+ const bs = b.slice(i, be);
2407
+ const diff = Number(as) - Number(bs);
2408
+ if (diff) return diff;
2409
+ if (as < bs) return -1;
2410
+ if (as > bs) return 1;
2411
+ continue;
2412
+ }
2413
+ if (x !== y) return x - y;
2414
+ }
2415
+ return a.length - b.length;
2416
+ }
2417
+ /** The #254 variant part of the key (leading `@media` / `@container` preludes). */
2418
+ /** @internal (#401) */ function ruleVariantKey(rule) {
2419
+ const key = [];
2420
+ let rest = rule;
2421
+ let m;
2422
+ while (m = LEADING_AT.exec(rest)) {
2423
+ const [g, v] = preludeKey(m[1], m[2]);
2424
+ key.push(g, v);
2425
+ rest = rest.slice(m[0].length);
2426
+ }
2427
+ return key;
2428
+ }
2429
+ /**
2430
+ * Full sort key: the #254 variant pairs, then (#401) Tailwind's property sort and the class name.
2431
+ * `candidate` defaults to the rule's first class.
2432
+ */
2433
+ function ruleSortKey(rule, candidate) {
2434
+ const name = candidate ?? ruleCandidate(rule);
2435
+ const { order, count } = rulePropertySort(rule, name);
2436
+ const key = ruleVariantKey(rule);
2437
+ key.push(PROPERTY_PART, ...order, NO_MORE, -count, name);
2438
+ return key;
2439
+ }
2440
+ function compareKeys(a, b) {
2441
+ const n = Math.min(a.length, b.length);
2442
+ for (let i = 0; i < n; i++) {
2443
+ const x = a[i];
2444
+ const y = b[i];
2445
+ if (x === y) continue;
2446
+ if (typeof x === "string" || typeof y === "string") {
2447
+ const d = compareCandidates(String(x), String(y));
2448
+ if (d) return d;
2449
+ continue;
2450
+ }
2451
+ return x - y;
2452
+ }
2453
+ return a.length - b.length;
2454
+ }
2455
+ /** Index after the last key <= `key` (stable upper bound) in sorted `keys`. */
2456
+ function upperBound(keys, key) {
2457
+ let lo = 0;
2458
+ let hi = keys.length;
2459
+ while (lo < hi) {
2460
+ const mid = lo + hi >> 1;
2461
+ if (compareKeys(keys[mid], key) <= 0) lo = mid + 1;
2462
+ else hi = mid;
2463
+ }
2464
+ return lo;
2465
+ }
2466
+ //#endregion
1520
2467
  //#region src/core/engine.ts
1521
2468
  var failureCache = /* @__PURE__ */ new Set();
1522
2469
  /**
@@ -1715,6 +2662,10 @@ function parseClassToAst(fullClassName, ctx) {
1715
2662
  let ast = [];
1716
2663
  for (const utilReg of utilRegs) {
1717
2664
  ast = utilReg.handler(value, ctx, utility, utilReg) || [];
2665
+ if (ast === REJECT_CLASS) {
2666
+ ast = [];
2667
+ break;
2668
+ }
1718
2669
  if (ast.length > 0) break;
1719
2670
  }
1720
2671
  const wrappers = [];
@@ -1839,7 +2790,7 @@ var CLASS_SEPARATOR = /[ \t\n\f\r]+/;
1839
2790
  function generateCss(classList, ctx, opts) {
1840
2791
  const seen = /* @__PURE__ */ new Set();
1841
2792
  const allAtRootNodes = [];
1842
- const results = classList.split(CLASS_SEPARATOR).filter((cls) => {
2793
+ const generated = classList.split(CLASS_SEPARATOR).filter((cls) => {
1843
2794
  if (!cls) return false;
1844
2795
  if (opts?.dedup) {
1845
2796
  if (seen.has(cls)) return false;
@@ -1848,12 +2799,31 @@ function generateCss(classList, ctx, opts) {
1848
2799
  return true;
1849
2800
  }).map((cls) => {
1850
2801
  try {
1851
- return generateOne(cls);
2802
+ return {
2803
+ cls,
2804
+ css: generateOne(cls)
2805
+ };
1852
2806
  } catch (err) {
1853
2807
  debugWarn("[generateCss] class generation failed:", cls, err);
1854
- return "";
2808
+ return {
2809
+ cls,
2810
+ css: ""
2811
+ };
1855
2812
  }
1856
- }).join(opts?.minify ? "" : "\n");
2813
+ });
2814
+ const slots = generated.flatMap((g, i) => g.css ? [i] : []);
2815
+ const sorted = slots.map((i) => ({
2816
+ i,
2817
+ css: generated[i].css,
2818
+ key: ruleSortKey(generated[i].css, generated[i].cls)
2819
+ })).sort((a, b) => compareKeys(a.key, b.key) || a.i - b.i);
2820
+ slots.forEach((slot, j) => {
2821
+ generated[slot] = {
2822
+ cls: generated[slot].cls,
2823
+ css: sorted[j].css
2824
+ };
2825
+ });
2826
+ const results = generated.map((g) => g.css).join(opts?.minify ? "" : "\n");
1857
2827
  function generateOne(cls) {
1858
2828
  const ast = parseClassToAst(cls, ctx);
1859
2829
  const parsedResult = (getContextState(ctx)?.parseResultCache || parseResultCache).get(cls);
@@ -1864,7 +2834,8 @@ function generateCss(classList, ctx, opts) {
1864
2834
  const hasStyleRule = cleanAst.some((node) => node.type === "style-rule");
1865
2835
  const css = astToCss(cleanAst.filter((node) => node.type !== "at-root"), hasStyleRule ? void 0 : cls, {
1866
2836
  minify: opts?.minify,
1867
- important: parsedResult?.utility?.important ?? false
2837
+ important: parsedResult?.utility?.important ?? false,
2838
+ scope: cls
1868
2839
  });
1869
2840
  const result = css;
1870
2841
  if (!result || result.trim() === "") debugWarn("[generateCss] Empty CSS generated for class:", {
@@ -1922,7 +2893,10 @@ function generateCssRules(classList, ctx, opts) {
1922
2893
  cssList.push(css);
1923
2894
  });
1924
2895
  else {
1925
- const css = astToCss([node], cls, options);
2896
+ const css = astToCss([node], cls, {
2897
+ ...options,
2898
+ scope: cls
2899
+ });
1926
2900
  cssList.push(css);
1927
2901
  }
1928
2902
  const rootCssList = [];
@@ -2998,500 +3972,232 @@ function configGetter(config, ...path) {
2998
3972
  else keys = path;
2999
3973
  return keys.reduce((acc, key) => acc ? acc[key] : void 0, config);
3000
3974
  }
3001
- function hasPreset(themeObj, category, preset) {
3002
- return themeObj[category]?.includes?.(preset);
3003
- }
3004
- function resolveTheme(config) {
3005
- let theme = {};
3006
- if (config.presets) {
3007
- for (const preset of config.presets) if (preset.theme) theme = deepMerge(theme, preset.theme);
3008
- }
3009
- if (config.theme) {
3010
- const { extend, ...overrideTheme } = config.theme;
3011
- theme = deepMerge(theme, overrideTheme);
3012
- if (extend) theme = deepMerge(theme, extend);
3013
- }
3014
- return theme;
3015
- }
3016
- function themeToCssVars(theme) {
3017
- return toCssVarsBlock(themeToCssVarsAll(theme));
3018
- }
3019
- function createContext(configObj) {
3020
- if (configObj.debug !== void 0) setDebug(!!configObj.debug);
3021
- const configWithDefaults = {
3022
- presets: [{ theme: require_theme.defaultTheme }, ...configObj.presets || []],
3023
- ...configObj
3024
- };
3025
- const themeObj = resolveTheme(configWithDefaults);
3026
- const ctx = {
3027
- hasPreset: (category, preset) => {
3028
- return hasPreset(themeObj, category, preset);
3029
- },
3030
- theme: (...args) => {
3031
- return themeGetter(themeObj, ...args);
3032
- },
3033
- config: (...args) => {
3034
- return configGetter(configWithDefaults, ...args);
3035
- },
3036
- themeToCssVars: () => themeToCssVars(themeObj),
3037
- extendTheme: (category, values) => {
3038
- if (typeof values === "function") {
3039
- const result = values(ctx.theme);
3040
- if (result && typeof result === "object") {
3041
- const existingValues = themeObj[category] || {};
3042
- themeObj[category] = {
3043
- ...existingValues,
3044
- ...result
3045
- };
3046
- }
3047
- } else if (typeof values === "object" && values !== null && !Array.isArray(values)) {
3048
- const existingValues = themeObj[category] || {};
3049
- themeObj[category] = {
3050
- ...existingValues,
3051
- ...values
3052
- };
3053
- }
3054
- clearContextCaches(ctx);
3055
- },
3056
- getPreflightCSS: (level = true) => {
3057
- return getPreflightCSS(level);
3058
- }
3059
- };
3060
- initializeContextState(ctx, getUtility(), getModifier());
3061
- registerCustomUtilities(ctx, configObj.utilities);
3062
- return ctx;
3063
- }
3064
- //#endregion
3065
- //#region src/core/jsonToAst.ts
3066
- /**
3067
- * Converts a single BaroJsonInput object into an AST tree.
3068
- * Bypasses string parsing and directly invokes utility/modifier handlers.
3069
- *
3070
- * @param input BaroJsonInput object
3071
- * @param ctx Context
3072
- * @returns AstNode[]
3073
- */
3074
- function jsonToAst(input, ctx) {
3075
- if ((input.variants || []).some((v) => typeof v === "string" ? !isSafeVariantToken(v) : !isSafeVariantValue(v.name || "") || !isSafeVariantValue(v.value || "") || hasCommentToken(v.name || "") || hasCommentToken(v.value || ""))) return [];
3076
- let utilReg = getUtility(ctx).find((u) => u.name === input.utility.name);
3077
- if (input.utility.value && !input.utility.arbitrary && !input.utility.customProperty) {
3078
- const fullName = `${input.utility.name}-${input.utility.value}`;
3079
- const exactMatch = getUtility(ctx).find((u) => u.name === fullName);
3080
- if (exactMatch) utilReg = exactMatch;
3081
- }
3082
- if (!utilReg) {
3083
- debugWarn(`[jsonToAst] Unknown utility: "${input.utility.name}"`);
3084
- return [];
3085
- }
3086
- const parsedUtility = {
3087
- prefix: input.utility.name,
3088
- value: input.utility.value,
3089
- arbitrary: input.utility.arbitrary,
3090
- negative: input.utility.negative,
3091
- opacity: input.utility.opacity,
3092
- important: input.utility.important,
3093
- customProperty: input.utility.customProperty,
3094
- category: utilReg.category,
3095
- priority: utilReg.priority
3096
- };
3097
- let value = input.utility.value;
3098
- if (input.utility.negative && value) value = "-" + value;
3099
- let ast = utilReg.handler(value || "", ctx, parsedUtility, utilReg) || [];
3100
- if (input.variants && input.variants.length > 0) {
3101
- const wrappers = [];
3102
- const selector = "&";
3103
- for (let i = input.variants.length - 1; i >= 0; i--) {
3104
- const variantInput = input.variants[i];
3105
- const variantName = typeof variantInput === "string" ? variantInput : variantInput.name;
3106
- const variantValue = typeof variantInput === "string" ? void 0 : variantInput.value;
3107
- const variantArbitrary = typeof variantInput === "string" ? false : variantInput.arbitrary;
3108
- const parsedModifier = {
3109
- type: variantName,
3110
- value: variantValue,
3111
- arbitrary: variantArbitrary
3112
- };
3113
- let matchKey = variantName;
3114
- if (variantArbitrary && variantValue) {
3115
- if (variantName) {
3116
- matchKey = `${variantName}-[${variantValue}]`;
3117
- parsedModifier.type = matchKey;
3118
- } else {
3119
- matchKey = `[${variantValue}]`;
3120
- parsedModifier.type = matchKey;
3121
- }
3122
- } else if (variantValue) {
3123
- matchKey = `${variantName}-[${variantValue}]`;
3124
- parsedModifier.type = matchKey;
3125
- }
3126
- const plugin = getModifier(ctx).find((p) => p.match(matchKey, ctx));
3127
- if (!plugin) {
3128
- debugWarn(`[jsonToAst] Unknown variant: "${matchKey}"`);
3129
- continue;
3130
- }
3131
- if (plugin.astHandler) ast = plugin.astHandler(ast, parsedModifier, ctx, [], i);
3132
- if (plugin.modifySelector) {
3133
- const result = plugin.modifySelector({
3134
- selector,
3135
- fullClassName: "JSON_GENERATED",
3136
- mod: parsedModifier,
3137
- context: ctx,
3138
- variantChain: [],
3139
- index: i
3140
- });
3141
- if (result == null) continue;
3142
- if (plugin.wrap && (result === "&" || typeof result === "object" && !Array.isArray(result) && result.selector === "&" || Array.isArray(result) && result.length === 1 && result[0].selector === "&")) {} else if (typeof result === "string" && result.includes("&")) wrappers.push({
3143
- type: "rule",
3144
- selector: result
3145
- });
3146
- else if (typeof result === "object" && !Array.isArray(result) && result.selector) {
3147
- const r = result;
3148
- const wrappingType = r.wrappingType || "rule";
3149
- wrappers.push({
3150
- type: wrappingType,
3151
- selector: r.selector,
3152
- flatten: r.flatten,
3153
- source: r.source
3154
- });
3155
- } else if (Array.isArray(result)) wrappers.push({
3156
- type: "wrap",
3157
- items: result.map((r) => ({
3158
- type: r.wrappingType || "rule",
3159
- selector: r.selector,
3160
- source: r.source,
3161
- nodes: []
3162
- }))
3163
- });
3164
- }
3165
- if (plugin.wrap) wrappers.push({
3166
- type: "wrap",
3167
- items: plugin.wrap(parsedModifier, ctx)
3168
- });
3169
- }
3170
- for (let i = 0; i < wrappers.length; i++) {
3171
- const wrap = wrappers[i];
3172
- if (wrap.type === "wrap") ast = wrap.items.map((item) => item.type === "rule" || item.type === "style-rule" || item.type === "at-rule" || item.type === "at-root" ? {
3173
- ...item,
3174
- nodes: [...item.nodes || [], ...ast]
3175
- } : item);
3176
- else if (wrap.type === "style-rule") ast = [{
3177
- type: "style-rule",
3178
- selector: wrap.selector,
3179
- source: wrap.source,
3180
- nodes: Array.isArray(ast) ? ast : [ast]
3181
- }];
3182
- else if (wrap.type === "at-rule") ast = [{
3183
- type: "at-rule",
3184
- name: wrap.name || "media",
3185
- params: wrap.params,
3186
- source: wrap.source,
3187
- nodes: Array.isArray(ast) ? ast : [ast]
3188
- }];
3189
- else if (wrap.type === "rule") ast = [{
3190
- type: "rule",
3191
- selector: wrap.selector,
3192
- source: wrap.source,
3193
- nodes: Array.isArray(ast) ? ast : [ast]
3194
- }];
3195
- }
3196
- }
3197
- return applyVarPrefix(ast, ctx);
3198
- }
3199
- /**
3200
- * Generates CSS from a list of BaroJsonInput objects.
3201
- *
3202
- * @param inputs Array of BaroJsonInput
3203
- * @param ctx Context
3204
- * @param opts Options (minify, etc.)
3205
- * @returns CSS string
3206
- */
3207
- function generateCssFromJson(inputs, ctx, opts) {
3208
- const allAtRootNodes = [];
3209
- const cssList = [];
3210
- inputs.forEach((input) => {
3211
- const cleanAst = optimizeAst(jsonToAst(input, ctx));
3212
- cleanAst.forEach((node) => {
3213
- if (node.type === "at-root") allAtRootNodes.push(...node.nodes);
3214
- });
3215
- let reconstructedName = input.utility.name;
3216
- if (input.utility.value) reconstructedName += `-${input.utility.value}`;
3217
- if (input.utility.arbitrary) reconstructedName = `${input.utility.name}-[${input.utility.value}]`;
3218
- if (input.variants) reconstructedName = `${input.variants.map((v) => typeof v === "string" ? v : v.name).join(":")}:${reconstructedName}`;
3219
- const css = astToCss(cleanAst, cleanAst.some((node) => node.type === "style-rule") ? void 0 : `.${reconstructedName.replace(/[^a-zA-Z0-9-_]/g, "\\$&")}`, {
3220
- minify: opts?.minify,
3221
- important: input.utility.important ?? false
3222
- });
3223
- if (css) cssList.push(css);
3224
- });
3225
- const rootCss = rootToCss(allAtRootNodes);
3226
- return `${rootCss ? `:root,:host {${rootCss}}` : ""}${cssList.join(opts?.minify ? "" : "\n")}`;
3227
- }
3228
- //#endregion
3229
- //#region src/core/utils.ts
3230
- /**
3231
- * Parses a fraction string (e.g., '1/2') and returns a percentage string (e.g., '50%'), or null if not a valid fraction.
3232
- */
3233
- function parseFraction(input) {
3234
- if (input.includes("/")) {
3235
- const [num, denom] = input.split("/").map(Number);
3236
- if (!isNaN(num) && !isNaN(denom) && denom !== 0) return `${num / denom * 100}%`;
3237
- }
3238
- return null;
3239
- }
3240
- /**
3241
- * Returns the input if it is a valid non-negative integer string, else null.
3242
- *
3243
- * @example
3244
- * parseNumber("10") // "10"
3245
- * parseNumber("-10") // "-10"
3246
- * parseNumber("10.5") // "10.5"
3247
- */
3248
- function parseNumber(input) {
3249
- return /^-?\d+(?:\.\d+)?$/.test(input) ? input : null;
3250
- }
3251
- /**
3252
- * Returns the input if it is a valid length string, else null.
3253
- */
3254
- function parseLength(input) {
3255
- return /^\d+(px|em|rem|vh|vw|vmin|vmax|%|in|cm|mm|pt|pc|ex|ch|fr)$/.test(input) ? input : null;
3256
- }
3257
- /**
3258
- * Unified parser for fraction or number, with options for percent or repeat syntax.
3259
- * - percent: if true, returns percentage for fraction (e.g., '1/2' -> '50%')
3260
- * - repeat: if true, returns repeat() for number (e.g., '3' -> 'repeat(3, minmax(0, 1fr))')
3261
- */
3262
- function parseFractionOrNumber(value, opts = {}) {
3263
- if (/^\d+$/.test(value)) {
3264
- if (opts.repeat) return `repeat(${value}, minmax(0, 1fr))`;
3265
- return value;
3975
+ function hasPreset(themeObj, category, preset) {
3976
+ return themeObj[category]?.includes?.(preset);
3977
+ }
3978
+ function resolveTheme(config) {
3979
+ let theme = {};
3980
+ if (config.presets) {
3981
+ for (const preset of config.presets) if (preset.theme) theme = deepMerge(theme, preset.theme);
3266
3982
  }
3267
- if (value.includes("/")) {
3268
- const [numerator, denominator] = value.split("/").map(Number);
3269
- if (!isNaN(numerator) && !isNaN(denominator) && denominator !== 0) {
3270
- const result = numerator / denominator;
3271
- if (opts.percent) return `${result * 100}%`;
3272
- return result.toString();
3273
- }
3983
+ if (config.theme) {
3984
+ const { extend, ...overrideTheme } = config.theme;
3985
+ theme = deepMerge(theme, overrideTheme);
3986
+ if (extend) theme = deepMerge(theme, extend);
3274
3987
  }
3275
- return null;
3988
+ return theme;
3276
3989
  }
3277
- var CSS_COLOR_NAMES = /* @__PURE__ */ new Set([
3278
- "aliceblue",
3279
- "antiquewhite",
3280
- "aqua",
3281
- "aquamarine",
3282
- "azure",
3283
- "beige",
3284
- "bisque",
3285
- "black",
3286
- "blanchedalmond",
3287
- "blue",
3288
- "blueviolet",
3289
- "brown",
3290
- "burlywood",
3291
- "cadetblue",
3292
- "chartreuse",
3293
- "chocolate",
3294
- "coral",
3295
- "cornflowerblue",
3296
- "cornsilk",
3297
- "crimson",
3298
- "cyan",
3299
- "darkblue",
3300
- "darkcyan",
3301
- "darkgoldenrod",
3302
- "darkgray",
3303
- "darkgreen",
3304
- "darkgrey",
3305
- "darkkhaki",
3306
- "darkmagenta",
3307
- "darkolivegreen",
3308
- "darkorange",
3309
- "darkorchid",
3310
- "darkred",
3311
- "darksalmon",
3312
- "darkseagreen",
3313
- "darkslateblue",
3314
- "darkslategray",
3315
- "darkslategrey",
3316
- "darkturquoise",
3317
- "darkviolet",
3318
- "deeppink",
3319
- "deepskyblue",
3320
- "dimgray",
3321
- "dimgrey",
3322
- "dodgerblue",
3323
- "firebrick",
3324
- "floralwhite",
3325
- "forestgreen",
3326
- "fuchsia",
3327
- "gainsboro",
3328
- "ghostwhite",
3329
- "gold",
3330
- "goldenrod",
3331
- "gray",
3332
- "grey",
3333
- "green",
3334
- "greenyellow",
3335
- "honeydew",
3336
- "hotpink",
3337
- "indianred",
3338
- "indigo",
3339
- "ivory",
3340
- "khaki",
3341
- "lavender",
3342
- "lavenderblush",
3343
- "lawngreen",
3344
- "lemonchiffon",
3345
- "lightblue",
3346
- "lightcoral",
3347
- "lightcyan",
3348
- "lightgoldenrodyellow",
3349
- "lightgray",
3350
- "lightgreen",
3351
- "lightgrey",
3352
- "lightpink",
3353
- "lightsalmon",
3354
- "lightseagreen",
3355
- "lightskyblue",
3356
- "lightslategray",
3357
- "lightslategrey",
3358
- "lightsteelblue",
3359
- "lightyellow",
3360
- "lime",
3361
- "limegreen",
3362
- "linen",
3363
- "magenta",
3364
- "maroon",
3365
- "mediumaquamarine",
3366
- "mediumblue",
3367
- "mediumorchid",
3368
- "mediumpurple",
3369
- "mediumseagreen",
3370
- "mediumslateblue",
3371
- "mediumspringgreen",
3372
- "mediumturquoise",
3373
- "mediumvioletred",
3374
- "midnightblue",
3375
- "mintcream",
3376
- "mistyrose",
3377
- "moccasin",
3378
- "navajowhite",
3379
- "navy",
3380
- "oldlace",
3381
- "olive",
3382
- "olivedrab",
3383
- "orange",
3384
- "orangered",
3385
- "orchid",
3386
- "palegoldenrod",
3387
- "palegreen",
3388
- "paleturquoise",
3389
- "palevioletred",
3390
- "papayawhip",
3391
- "peachpuff",
3392
- "peru",
3393
- "pink",
3394
- "plum",
3395
- "powderblue",
3396
- "purple",
3397
- "red",
3398
- "rosybrown",
3399
- "royalblue",
3400
- "saddlebrown",
3401
- "salmon",
3402
- "sandybrown",
3403
- "seagreen",
3404
- "seashell",
3405
- "sienna",
3406
- "silver",
3407
- "skyblue",
3408
- "slateblue",
3409
- "slategray",
3410
- "slategrey",
3411
- "snow",
3412
- "springgreen",
3413
- "steelblue",
3414
- "tan",
3415
- "teal",
3416
- "thistle",
3417
- "tomato",
3418
- "turquoise",
3419
- "violet",
3420
- "wheat",
3421
- "white",
3422
- "whitesmoke",
3423
- "yellow",
3424
- "yellowgreen"
3425
- ]);
3426
- /**
3427
- * Returns the input if it is a valid color string, else null.
3428
- *
3429
- * #rgb, #rgba, #rrggbb, #rrggbbaa, rgb(r, g, b), rgb(r, g, b, a), hsl(h, s, l), hsl(h, s, l, a), hwb(h, w, b), hwb(h, w, b, a), lab(l, a, b), lab(l, a, b, a), lch(l, c, h), lch(l, c, h, a), oklab(l, a, b), oklab(l, a, b, a), oklch(l, c, h), oklch(l, c, h, a), color-mix(in oklab, var(--color-blue-500) 60%, transparent)
3430
- */
3431
- function parseColor(input) {
3432
- if (CSS_COLOR_NAMES.has(input.toLowerCase())) return input;
3433
- if (input.startsWith("color:var(")) return input.slice(6);
3434
- if (input.startsWith("color:")) return parseColor(input.slice(6));
3435
- if (input.startsWith("#") && input.length === 4) return `#${input.slice(1)}`;
3436
- if (input.startsWith("#") && input.length === 5) return `#${input.slice(1)}`;
3437
- if (input.startsWith("#") && input.length === 7) return `#${input.slice(1)}`;
3438
- if (input.startsWith("#") && input.length === 9) return `#${input.slice(1)}`;
3439
- if (input.startsWith("rgb(")) return input.slice(4, -1);
3440
- if (input.startsWith("rgba(")) return input.slice(5, -1);
3441
- if (input.startsWith("hsl(")) return input.slice(4, -1);
3442
- if (input.startsWith("hsla(")) return input.slice(5, -1);
3443
- if (input.startsWith("hwb(")) return input.slice(4, -1);
3444
- if (input.startsWith("lab(")) return input.slice(4, -1);
3445
- if (input.startsWith("lch(")) return input.slice(4, -1);
3446
- if (input.startsWith("oklab(")) return input.slice(5, -1);
3447
- if (input.startsWith("oklch(")) return input.slice(6, -1);
3448
- if (input.startsWith("color-mix(")) return input.slice(9, -1);
3449
- return null;
3990
+ function themeToCssVars(theme) {
3991
+ return toCssVarsBlock(themeToCssVarsAll(theme));
3450
3992
  }
3451
- var COLOR_KEYWORDS = /* @__PURE__ */ new Set([
3452
- "inherit",
3453
- "currentcolor",
3454
- "transparent"
3455
- ]);
3993
+ function createContext(configObj) {
3994
+ if (configObj.debug !== void 0) setDebug(!!configObj.debug);
3995
+ const configWithDefaults = {
3996
+ presets: [{ theme: require_theme.defaultTheme }, ...configObj.presets || []],
3997
+ ...configObj
3998
+ };
3999
+ const themeObj = resolveTheme(configWithDefaults);
4000
+ const ctx = {
4001
+ hasPreset: (category, preset) => {
4002
+ return hasPreset(themeObj, category, preset);
4003
+ },
4004
+ theme: (...args) => {
4005
+ return themeGetter(themeObj, ...args);
4006
+ },
4007
+ config: (...args) => {
4008
+ return configGetter(configWithDefaults, ...args);
4009
+ },
4010
+ themeToCssVars: () => themeToCssVars(themeObj),
4011
+ extendTheme: (category, values) => {
4012
+ if (typeof values === "function") {
4013
+ const result = values(ctx.theme);
4014
+ if (result && typeof result === "object") {
4015
+ const existingValues = themeObj[category] || {};
4016
+ themeObj[category] = {
4017
+ ...existingValues,
4018
+ ...result
4019
+ };
4020
+ }
4021
+ } else if (typeof values === "object" && values !== null && !Array.isArray(values)) {
4022
+ const existingValues = themeObj[category] || {};
4023
+ themeObj[category] = {
4024
+ ...existingValues,
4025
+ ...values
4026
+ };
4027
+ }
4028
+ clearContextCaches(ctx);
4029
+ },
4030
+ getPreflightCSS: (level = true) => {
4031
+ return getPreflightCSS(level);
4032
+ }
4033
+ };
4034
+ initializeContextState(ctx, getUtility(), getModifier());
4035
+ registerCustomUtilities(ctx, configObj.utilities);
4036
+ return ctx;
4037
+ }
4038
+ //#endregion
4039
+ //#region src/core/jsonToAst.ts
3456
4040
  /**
3457
- * Declarations for a theme colour (#228), as Tailwind v4 emits them: `var(--color-<key>)` so runtime theme
3458
- * overrides apply; with an opacity modifier, a literal srgb color-mix fallback plus an oklab color-mix of the var.
4041
+ * Converts a single BaroJsonInput object into an AST tree.
4042
+ * Bypasses string parsing and directly invokes utility/modifier handlers.
4043
+ *
4044
+ * @param input BaroJsonInput object
4045
+ * @param ctx Context
4046
+ * @returns AstNode[]
3459
4047
  */
3460
- function themeColorDecls(prop, value, extra) {
3461
- const key = String(extra.realThemeValue);
3462
- const ref = COLOR_KEYWORDS.has(value.toLowerCase()) || value.startsWith("var(") || !/^[\w-]+$/.test(key) ? value : `var(--color-${key})`;
3463
- if (!extra.opacity) return [decl(prop, ref)];
3464
- const alpha = normalizeAlpha(String(extra.opacity));
3465
- const supports = (amount) => atRule("supports", "(color:color-mix(in lab, red, red))", [decl(prop, `color-mix(in oklab, ${ref} ${amount}, transparent)`)]);
3466
- if (alpha.isVar) return [decl(prop, value), supports(alpha.amount)];
3467
- return [decl(prop, `color-mix(in srgb, ${value} ${alpha.amount}, transparent)`), supports(alpha.amount)];
4048
+ function jsonToAst(input, ctx) {
4049
+ if ((input.variants || []).some((v) => typeof v === "string" ? !isSafeVariantToken(v) : !isSafeVariantValue(v.name || "") || !isSafeVariantValue(v.value || "") || hasCommentToken(v.name || "") || hasCommentToken(v.value || ""))) return [];
4050
+ let utilReg = getUtility(ctx).find((u) => u.name === input.utility.name);
4051
+ if (input.utility.value && !input.utility.arbitrary && !input.utility.customProperty) {
4052
+ const fullName = `${input.utility.name}-${input.utility.value}`;
4053
+ const exactMatch = getUtility(ctx).find((u) => u.name === fullName);
4054
+ if (exactMatch) utilReg = exactMatch;
4055
+ }
4056
+ if (!utilReg) {
4057
+ debugWarn(`[jsonToAst] Unknown utility: "${input.utility.name}"`);
4058
+ return [];
4059
+ }
4060
+ const parsedUtility = {
4061
+ prefix: input.utility.name,
4062
+ value: input.utility.value,
4063
+ arbitrary: input.utility.arbitrary,
4064
+ negative: input.utility.negative,
4065
+ opacity: input.utility.opacity,
4066
+ important: input.utility.important,
4067
+ customProperty: input.utility.customProperty,
4068
+ category: utilReg.category,
4069
+ priority: utilReg.priority
4070
+ };
4071
+ let value = input.utility.value;
4072
+ if (input.utility.negative && value) value = "-" + value;
4073
+ let ast = utilReg.handler(value || "", ctx, parsedUtility, utilReg) || [];
4074
+ if (input.variants && input.variants.length > 0) {
4075
+ const wrappers = [];
4076
+ const selector = "&";
4077
+ for (let i = input.variants.length - 1; i >= 0; i--) {
4078
+ const variantInput = input.variants[i];
4079
+ const variantName = typeof variantInput === "string" ? variantInput : variantInput.name;
4080
+ const variantValue = typeof variantInput === "string" ? void 0 : variantInput.value;
4081
+ const variantArbitrary = typeof variantInput === "string" ? false : variantInput.arbitrary;
4082
+ const parsedModifier = {
4083
+ type: variantName,
4084
+ value: variantValue,
4085
+ arbitrary: variantArbitrary
4086
+ };
4087
+ let matchKey = variantName;
4088
+ if (variantArbitrary && variantValue) {
4089
+ if (variantName) {
4090
+ matchKey = `${variantName}-[${variantValue}]`;
4091
+ parsedModifier.type = matchKey;
4092
+ } else {
4093
+ matchKey = `[${variantValue}]`;
4094
+ parsedModifier.type = matchKey;
4095
+ }
4096
+ } else if (variantValue) {
4097
+ matchKey = `${variantName}-[${variantValue}]`;
4098
+ parsedModifier.type = matchKey;
4099
+ }
4100
+ const plugin = getModifier(ctx).find((p) => p.match(matchKey, ctx));
4101
+ if (!plugin) {
4102
+ debugWarn(`[jsonToAst] Unknown variant: "${matchKey}"`);
4103
+ continue;
4104
+ }
4105
+ if (plugin.astHandler) ast = plugin.astHandler(ast, parsedModifier, ctx, [], i);
4106
+ if (plugin.modifySelector) {
4107
+ const result = plugin.modifySelector({
4108
+ selector,
4109
+ fullClassName: "JSON_GENERATED",
4110
+ mod: parsedModifier,
4111
+ context: ctx,
4112
+ variantChain: [],
4113
+ index: i
4114
+ });
4115
+ if (result == null) continue;
4116
+ if (plugin.wrap && (result === "&" || typeof result === "object" && !Array.isArray(result) && result.selector === "&" || Array.isArray(result) && result.length === 1 && result[0].selector === "&")) {} else if (typeof result === "string" && result.includes("&")) wrappers.push({
4117
+ type: "rule",
4118
+ selector: result
4119
+ });
4120
+ else if (typeof result === "object" && !Array.isArray(result) && result.selector) {
4121
+ const r = result;
4122
+ const wrappingType = r.wrappingType || "rule";
4123
+ wrappers.push({
4124
+ type: wrappingType,
4125
+ selector: r.selector,
4126
+ flatten: r.flatten,
4127
+ source: r.source
4128
+ });
4129
+ } else if (Array.isArray(result)) wrappers.push({
4130
+ type: "wrap",
4131
+ items: result.map((r) => ({
4132
+ type: r.wrappingType || "rule",
4133
+ selector: r.selector,
4134
+ source: r.source,
4135
+ nodes: []
4136
+ }))
4137
+ });
4138
+ }
4139
+ if (plugin.wrap) wrappers.push({
4140
+ type: "wrap",
4141
+ items: plugin.wrap(parsedModifier, ctx)
4142
+ });
4143
+ }
4144
+ for (let i = 0; i < wrappers.length; i++) {
4145
+ const wrap = wrappers[i];
4146
+ if (wrap.type === "wrap") ast = wrap.items.map((item) => item.type === "rule" || item.type === "style-rule" || item.type === "at-rule" || item.type === "at-root" ? {
4147
+ ...item,
4148
+ nodes: [...item.nodes || [], ...ast]
4149
+ } : item);
4150
+ else if (wrap.type === "style-rule") ast = [{
4151
+ type: "style-rule",
4152
+ selector: wrap.selector,
4153
+ source: wrap.source,
4154
+ nodes: Array.isArray(ast) ? ast : [ast]
4155
+ }];
4156
+ else if (wrap.type === "at-rule") ast = [{
4157
+ type: "at-rule",
4158
+ name: wrap.name || "media",
4159
+ params: wrap.params,
4160
+ source: wrap.source,
4161
+ nodes: Array.isArray(ast) ? ast : [ast]
4162
+ }];
4163
+ else if (wrap.type === "rule") ast = [{
4164
+ type: "rule",
4165
+ selector: wrap.selector,
4166
+ source: wrap.source,
4167
+ nodes: Array.isArray(ast) ? ast : [ast]
4168
+ }];
4169
+ }
4170
+ }
4171
+ return applyVarPrefix(ast, ctx);
3468
4172
  }
3469
4173
  /**
3470
- * Opacity modifier → color-mix amount, as Tailwind v4 does: `50` → `50%`, `[37%]` → `37%`, `[0.5]` / `[.8]` → `50%` /
3471
- * `80%` (a bracketed number ≤ 1 is a fraction), `[var(--a)]` / `(--a)` → `var(--a)`.
4174
+ * Generates CSS from a list of BaroJsonInput objects.
4175
+ *
4176
+ * @param inputs Array of BaroJsonInput
4177
+ * @param ctx Context
4178
+ * @param opts Options (minify, etc.)
4179
+ * @returns CSS string
3472
4180
  */
3473
- function normalizeAlpha(raw) {
3474
- let v = raw.trim();
3475
- const bracketed = v.startsWith("[") && v.endsWith("]");
3476
- if (bracketed) v = v.slice(1, -1).trim();
3477
- if (v.startsWith("(") && v.endsWith(")")) v = `var(${v.slice(1, -1).trim()})`;
3478
- if (v.startsWith("var(")) return {
3479
- amount: v,
3480
- isVar: true
3481
- };
3482
- if (v.endsWith("%")) return {
3483
- amount: v,
3484
- isVar: false
3485
- };
3486
- const n = Number(v);
3487
- if (v !== "" && Number.isFinite(n)) return {
3488
- amount: `${+(bracketed && n <= 1 ? n * 100 : n).toFixed(4)}%`,
3489
- isVar: false
3490
- };
3491
- return {
3492
- amount: v,
3493
- isVar: false
3494
- };
4181
+ function generateCssFromJson(inputs, ctx, opts) {
4182
+ const allAtRootNodes = [];
4183
+ const cssList = [];
4184
+ inputs.forEach((input) => {
4185
+ const cleanAst = optimizeAst(jsonToAst(input, ctx));
4186
+ cleanAst.forEach((node) => {
4187
+ if (node.type === "at-root") allAtRootNodes.push(...node.nodes);
4188
+ });
4189
+ let reconstructedName = input.utility.name;
4190
+ if (input.utility.value) reconstructedName += `-${input.utility.value}`;
4191
+ if (input.utility.arbitrary) reconstructedName = `${input.utility.name}-[${input.utility.value}]`;
4192
+ if (input.variants) reconstructedName = `${input.variants.map((v) => typeof v === "string" ? v : v.name).join(":")}:${reconstructedName}`;
4193
+ const css = astToCss(cleanAst, cleanAst.some((node) => node.type === "style-rule") ? void 0 : `.${reconstructedName.replace(/[^a-zA-Z0-9-_]/g, "\\$&")}`, {
4194
+ minify: opts?.minify,
4195
+ important: input.utility.important ?? false
4196
+ });
4197
+ if (css) cssList.push(css);
4198
+ });
4199
+ const rootCss = rootToCss(allAtRootNodes);
4200
+ return `${rootCss ? `:root,:host {${rootCss}}` : ""}${cssList.join(opts?.minify ? "" : "\n")}`;
3495
4201
  }
3496
4202
  //#endregion
3497
4203
  //#region src/presets/interactivity.ts
@@ -3505,10 +4211,7 @@ functionalUtility({
3505
4211
  supportsArbitrary: true,
3506
4212
  supportsCustomProperty: true,
3507
4213
  handle: (value, _ctx, _token, extra) => {
3508
- if (extra?.realThemeValue) {
3509
- if (extra.opacity) return [atRule("supports", `(color:color-mix(in lab, red, red))`, [decl("accent-color", `color-mix(in lab, ${value} ${extra.opacity}%, transparent)`)]), decl("accent-color", value)];
3510
- return [decl("accent-color", `var(--color-${extra.realThemeValue})`)];
3511
- }
4214
+ if (extra?.realThemeValue) return themeColorDecls("accent-color", value, extra);
3512
4215
  return [decl("accent-color", value)];
3513
4216
  },
3514
4217
  handleCustomProperty: (value) => [decl("accent-color", `var(${value})`)],
@@ -3527,10 +4230,7 @@ functionalUtility({
3527
4230
  supportsArbitrary: true,
3528
4231
  supportsCustomProperty: true,
3529
4232
  handle: (value, ctx, token, extra) => {
3530
- if (extra?.realThemeValue) {
3531
- if (extra.opacity) return [atRule("supports", `(color:color-mix(in lab, red, red))`, [decl("caret-color", `color-mix(in lab, ${value} ${extra.opacity}%, transparent)`)]), decl("caret-color", value)];
3532
- return [decl("caret-color", `var(--color-${extra.realThemeValue})`)];
3533
- }
4233
+ if (extra?.realThemeValue) return themeColorDecls("caret-color", value, extra);
3534
4234
  return [decl("caret-color", value)];
3535
4235
  },
3536
4236
  handleCustomProperty: (value) => [decl("caret-color", `var(${value})`)],
@@ -3895,22 +4595,11 @@ staticUtility("caption-bottom", [["caption-side", "bottom"]], { category: "table
3895
4595
  //#region src/presets/shadow-color.ts
3896
4596
  /** Opacity modifier to an alpha: `50` → 50%, `[20%]` → 20%, `(--o)` → var(--o); anything else is invalid. */
3897
4597
  function parseAlpha(op) {
3898
- if (!op) return null;
3899
- if (/^\d+(\.\d+)?$/.test(op)) return {
3900
- alpha: `${op}%`,
3901
- isVar: false
3902
- };
3903
- const pct = /^\[(\d+(?:\.\d+)?)%\]$/.exec(op);
3904
- if (pct) return {
3905
- alpha: `${pct[1]}%`,
3906
- isVar: false
3907
- };
3908
- const cp = /^\((--[\w-]+)\)$/.exec(op);
3909
- if (cp) return {
3910
- alpha: `var(${cp[1]})`,
3911
- isVar: true
4598
+ const a = op ? normalizeAlpha(op) : null;
4599
+ return a && {
4600
+ alpha: a.amount,
4601
+ isVar: a.isVar
3912
4602
  };
3913
- return null;
3914
4603
  }
3915
4604
  function splitTop(value, sep) {
3916
4605
  const out = [];
@@ -4419,6 +5108,11 @@ function layerColor(layer, main, opacity, token, realThemeValue) {
4419
5108
  if (main.startsWith("color:")) return shadowColorDecls(layer, `var(${main.slice(6)})`, opacity);
4420
5109
  if (token.arbitrary && parseColor(main)) return shadowColorDecls(layer, main, opacity);
4421
5110
  }
5111
+ function customShadowAlpha(layer, opacity) {
5112
+ if (!opacity) return [];
5113
+ const a = parseAlpha(opacity);
5114
+ return a ? [decl(`--baro-${layer}-alpha`, a.alpha)] : null;
5115
+ }
4422
5116
  for (const layer of ["shadow", "inset-shadow"]) functionalUtility({
4423
5117
  name: layer,
4424
5118
  supportsArbitrary: true,
@@ -4435,11 +5129,17 @@ for (const layer of ["shadow", "inset-shadow"]) functionalUtility({
4435
5129
  if (token.arbitrary) return boxShadowLayer(layer, layer === "inset-shadow" ? insetEach(value) : value, opacity);
4436
5130
  return null;
4437
5131
  },
4438
- handleCustomProperty: (value) => value.startsWith("color:") ? shadowColorDecls(layer, `var(${value.slice(6)})`, void 0) ?? [] : [
4439
- ringShadowProperties(),
4440
- decl(`--baro-${layer}`, layer === "inset-shadow" ? `inset var(${value})` : `var(${value})`),
4441
- decl("box-shadow", SHADOW_COMPOSITE)
4442
- ]
5132
+ ownsOpacity: true,
5133
+ handleCustomProperty: (value, _ctx, _token, extra) => {
5134
+ if (value.startsWith("color:")) return shadowColorDecls(layer, `var(${value.slice(6)})`, extra?.opacity) ?? [];
5135
+ const alpha = customShadowAlpha(layer, extra?.opacity);
5136
+ return alpha ? [
5137
+ ringShadowProperties(),
5138
+ ...alpha,
5139
+ decl(`--baro-${layer}`, layer === "inset-shadow" ? `inset var(${value})` : `var(${value})`),
5140
+ decl("box-shadow", SHADOW_COMPOSITE)
5141
+ ] : [];
5142
+ }
4443
5143
  });
4444
5144
  var textShadowProperties = () => atRoot([property("--baro-text-shadow-color"), property("--baro-text-shadow-alpha", "100%", "<percentage>")]);
4445
5145
  var namedTextShadow = (ctx, name) => {
@@ -4469,7 +5169,19 @@ functionalUtility({
4469
5169
  if (token.arbitrary) return textShadowValue(value, opacity);
4470
5170
  return null;
4471
5171
  },
4472
- handleCustomProperty: (value) => value.startsWith("color:") ? [textShadowProperties(), ...shadowColorDecls("text-shadow", `var(${value.slice(6)})`, void 0) ?? []] : [textShadowProperties(), decl("text-shadow", `var(${value})`)],
5172
+ ownsOpacity: true,
5173
+ handleCustomProperty: (value, _ctx, _token, extra) => {
5174
+ if (value.startsWith("color:")) {
5175
+ const color = shadowColorDecls("text-shadow", `var(${value.slice(6)})`, extra?.opacity);
5176
+ return color ? [textShadowProperties(), ...color] : [];
5177
+ }
5178
+ const alpha = customShadowAlpha("text-shadow", extra?.opacity);
5179
+ return alpha ? [
5180
+ textShadowProperties(),
5181
+ ...alpha,
5182
+ decl("text-shadow", `var(${value})`)
5183
+ ] : [];
5184
+ },
4473
5185
  category: "effects"
4474
5186
  });
4475
5187
  [
@@ -4533,17 +5245,6 @@ functionalUtility({
4533
5245
  ], { category: "effects" });
4534
5246
  });
4535
5247
  staticUtility("ring-inset", [["--baro-ring-inset", "inset"]], { category: "effects" });
4536
- function createRingColorDecls(key, main, opacity, realThemeValue) {
4537
- const colorVar = `var(--color-${realThemeValue})`;
4538
- let colorMix = colorVar;
4539
- let fallback = colorVar;
4540
- if (opacity) {
4541
- colorMix = `color-mix(in oklab, ${colorVar} ${opacity}%, transparent)`;
4542
- if (parseColor(main) && main.startsWith("#")) fallback = `${main}${Math.round(Number(opacity) / 100 * 255).toString(16).padStart(2, "0")}`;
4543
- else fallback = colorMix;
4544
- }
4545
- return [atRule("supports", "(color:color-mix(in lab, red, red))", [decl(key, colorMix)]), decl(key, fallback)];
4546
- }
4547
5248
  functionalUtility({
4548
5249
  name: "ring",
4549
5250
  supportsArbitrary: true,
@@ -4557,28 +5258,9 @@ functionalUtility({
4557
5258
  decl("--baro-ring-shadow", ringShadowValue(value)),
4558
5259
  decl("box-shadow", SHADOW_COMPOSITE)
4559
5260
  ];
4560
- const opacity = extra?.opacity;
4561
- const realThemeValue = extra?.realThemeValue;
4562
- if (realThemeValue) return createRingColorDecls("--baro-ring-color", main, opacity, realThemeValue);
4563
- if (main.startsWith("color:")) {
4564
- const cp = main.replace("color:", "");
4565
- let colorMix = `var(${cp})`;
4566
- let fallback = colorMix;
4567
- if (opacity) {
4568
- colorMix = `color-mix(in oklab, var(${cp}) ${opacity}%, transparent)`;
4569
- fallback = colorMix;
4570
- }
4571
- return [atRule("supports", "(color:color-mix(in lab, red, red))", [decl("--baro-ring-color", colorMix)]), decl("--baro-ring-color", fallback)];
4572
- }
5261
+ if (extra?.realThemeValue) return themeColorDecls("--baro-ring-color", main, extra);
5262
+ if (main.startsWith("color:")) return [decl("--baro-ring-color", `var(${main.slice(6)})`)];
4573
5263
  if (token.arbitrary) {
4574
- let colorMix = main;
4575
- let fallback = main;
4576
- if (opacity) {
4577
- colorMix = `color-mix(in oklab, ${main} ${opacity}%, transparent)`;
4578
- if (parseColor(main) && main.startsWith("#")) fallback = `${main}${Math.round(Number(opacity) / 100 * 255).toString(16).padStart(2, "0")}`;
4579
- else fallback = colorMix;
4580
- return [atRule("supports", "(color:color-mix(in lab, red, red))", [decl("--baro-ring-color", colorMix)]), decl("--baro-ring-color", fallback)];
4581
- }
4582
5264
  if (!parseColor(main) && /^(-?(\d+\.?\d*|\.\d+)(px|rem|em|%|vw|vh|vmin|vmax|ch|ex|pt|cm|mm|in|pc)|0|(length:.+)|calc\(.+\))$/i.test(main)) {
4583
5265
  const width = main.startsWith("length:") ? main.slice(7) : main;
4584
5266
  return [
@@ -4587,7 +5269,7 @@ functionalUtility({
4587
5269
  decl("box-shadow", SHADOW_COMPOSITE)
4588
5270
  ];
4589
5271
  }
4590
- return [parseColor(main) ? decl("--baro-ring-color", main) : decl("box-shadow", main)];
5272
+ return [parseColor(main) || /^var\(--[^)]+\)$/.test(main) ? decl("--baro-ring-color", main) : decl("box-shadow", main)];
4591
5273
  }
4592
5274
  if (main === "inherit" || main === "current" || main === "transparent") return [decl("--baro-ring-color", main === "current" ? "currentColor" : main)];
4593
5275
  return null;
@@ -4605,30 +5287,9 @@ functionalUtility({
4605
5287
  themeKeys: ["colors", "shadows"],
4606
5288
  handle: (value, ctx, token, extra) => {
4607
5289
  const main = value;
4608
- const opacity = extra?.opacity;
4609
- const realThemeValue = extra?.realThemeValue;
4610
- if (realThemeValue) return createRingColorDecls("--baro-inset-ring-color", main, opacity, realThemeValue);
4611
- if (main.startsWith("color:")) {
4612
- const cp = main.replace("color:", "");
4613
- let colorMix = `var(${cp})`;
4614
- let fallback = colorMix;
4615
- if (opacity) {
4616
- colorMix = `color-mix(in oklab, var(${cp}) ${opacity}%, transparent)`;
4617
- fallback = colorMix;
4618
- }
4619
- return [atRule("supports", "(color:color-mix(in lab, red, red))", [decl("--baro-inset-ring-color", colorMix)]), decl("--baro-inset-ring-color", fallback)];
4620
- }
4621
- if (token.arbitrary) {
4622
- let colorMix = main;
4623
- let fallback = main;
4624
- if (opacity) {
4625
- colorMix = `color-mix(in oklab, ${main} ${opacity}%, transparent)`;
4626
- if (parseColor(main) && main.startsWith("#")) fallback = `${main}${Math.round(Number(opacity) / 100 * 255).toString(16).padStart(2, "0")}`;
4627
- else fallback = colorMix;
4628
- return [atRule("supports", "(color:color-mix(in lab, red, red))", [decl("--baro-inset-ring-color", colorMix)]), decl("--baro-inset-ring-color", fallback)];
4629
- }
4630
- return [decl("box-shadow", `inset ${main}`)];
4631
- }
5290
+ if (extra?.realThemeValue) return themeColorDecls("--baro-inset-ring-color", main, extra);
5291
+ if (main.startsWith("color:")) return [decl("--baro-inset-ring-color", `var(${main.slice(6)})`)];
5292
+ if (token.arbitrary) return [parseColor(main) || /^var\(--[^)]+\)$/.test(main) ? decl("--baro-inset-ring-color", main) : decl("box-shadow", `inset ${main}`)];
4632
5293
  if (main === "inherit" || main === "current" || main === "transparent") return [decl("--baro-inset-ring-color", main === "current" ? "currentColor" : main)];
4633
5294
  return null;
4634
5295
  },
@@ -6453,7 +7114,7 @@ functionalUtility({
6453
7114
  supportsOpacity: true,
6454
7115
  handle: (value, _ctx, _token, extra) => {
6455
7116
  if (extra?.realThemeValue) return [rule("&::placeholder", themeColorDecls("color", value, extra))];
6456
- if (parseColor(value)) return placeholderColor(value);
7117
+ if (parseColor(value) || /^var\(--[\w-]+\)$/.test(value)) return placeholderColor(value);
6457
7118
  return null;
6458
7119
  },
6459
7120
  handleCustomProperty: (value) => placeholderColor(`var(${value})`),
@@ -6659,7 +7320,7 @@ var stopsDecls = (stop, color) => {
6659
7320
  if (parseColor(value)) return stopsDecls(stop, value);
6660
7321
  return null;
6661
7322
  },
6662
- handleCustomProperty: (value) => [decl(`--baro-gradient-${stop}`, `var(${value})`)],
7323
+ handleCustomProperty: (value) => value.startsWith("color:") ? stopsDecls(stop, `var(${value.slice(6)})`) : [decl(`--baro-gradient-${stop}`, `var(${value})`)],
6663
7324
  description: `${stop} gradient stop utility (color, percent, custom property, arbitrary supported)`,
6664
7325
  category: "background"
6665
7326
  });
@@ -6713,6 +7374,7 @@ functionalUtility({
6713
7374
  return [decl("background-color", value)];
6714
7375
  }
6715
7376
  if (parseLength(value)) return [decl("background-size", value)];
7377
+ if (/^var\(--[^)]+\)$/.test(value)) return [decl("background-color", value)];
6716
7378
  return null;
6717
7379
  },
6718
7380
  handleCustomProperty: (value) => {
@@ -6840,11 +7502,11 @@ var withBorderStyle = (props, width) => [
6840
7502
  ...propList.map((prop) => [prop.replace("width", "style"), "var(--baro-border-style)"]),
6841
7503
  ...propList.map((prop) => [prop, width])
6842
7504
  ];
6843
- staticUtility(`${name}-0`, styled("0px"));
6844
- staticUtility(`${name}-2`, styled("2px"));
6845
- staticUtility(`${name}-4`, styled("4px"));
6846
- staticUtility(`${name}-8`, styled("8px"));
6847
- staticUtility(`${name}`, styled("1px"));
7505
+ staticUtility(`${name}-0`, styled("0px"), { category: "borders" });
7506
+ staticUtility(`${name}-2`, styled("2px"), { category: "borders" });
7507
+ staticUtility(`${name}-4`, styled("4px"), { category: "borders" });
7508
+ staticUtility(`${name}-8`, styled("8px"), { category: "borders" });
7509
+ staticUtility(`${name}`, styled("1px"), { category: "borders" });
6848
7510
  functionalUtility({
6849
7511
  name,
6850
7512
  themeKeys: ["colors", "borderWidth"],
@@ -7014,7 +7676,7 @@ functionalUtility({
7014
7676
  return null;
7015
7677
  },
7016
7678
  handleCustomProperty: (value) => {
7017
- if (value.startsWith("color:")) return [decl("outline-color", value.replace("color:", ""))];
7679
+ if (value.startsWith("color:")) return [decl("outline-color", `var(${value.slice(6)})`)];
7018
7680
  if (value.startsWith("length:")) return withOutlineStyle(`var(${value.replace("length:", "")})`);
7019
7681
  return [decl("outline-color", `var(${value})`)];
7020
7682
  },
@@ -7046,7 +7708,7 @@ functionalUtility({
7046
7708
  handle: (value, _ctx, token, extra) => {
7047
7709
  if (token.prefix !== "divide") return null;
7048
7710
  if (extra?.realThemeValue) return [rule(":where(& > :not(:last-child))", themeColorDecls("border-color", value, extra))];
7049
- if (parseColor(value)) return divideColor(value);
7711
+ if (parseColor(value) || /^var\(--[\w-]+\)$/.test(value)) return divideColor(value);
7050
7712
  return null;
7051
7713
  },
7052
7714
  handleCustomProperty: (value, _ctx, token) => token.prefix === "divide" ? divideColor(`var(${value})`) : [],
@@ -7465,8 +8127,9 @@ functionalUtility({
7465
8127
  themeKeys: ["colors"],
7466
8128
  supportsArbitrary: true,
7467
8129
  supportsCustomProperty: true,
8130
+ supportsOpacity: true,
7468
8131
  handle: (value, ctx, token, extra) => {
7469
- if (extra?.realThemeValue) return [decl("fill", `var(--color-${extra.realThemeValue})`)];
8132
+ if (extra?.realThemeValue) return themeColorDecls("fill", value, extra);
7470
8133
  return [decl("fill", value)];
7471
8134
  },
7472
8135
  description: "fill utility (static, theme, arbitrary, custom property supported)",
@@ -7482,6 +8145,7 @@ functionalUtility({
7482
8145
  themeKeys: ["colors", "strokeWidth"],
7483
8146
  supportsArbitrary: true,
7484
8147
  supportsCustomProperty: true,
8148
+ supportsOpacity: true,
7485
8149
  handle: (value, ctx, token, extra) => {
7486
8150
  if (parseNumber(value) || extra?.themeNamespace === "strokeWidth") return [decl("stroke-width", value)];
7487
8151
  if (token.arbitrary) {
@@ -7489,7 +8153,7 @@ functionalUtility({
7489
8153
  if (hint) return [decl("stroke-width", hint[2])];
7490
8154
  if (!parseColor(value) && (STROKE_LENGTH.test(value) || /^calc\(/.test(value))) return [decl("stroke-width", value)];
7491
8155
  }
7492
- if (extra?.realThemeValue) return [decl("stroke", `var(--color-${extra.realThemeValue})`)];
8156
+ if (extra?.realThemeValue) return themeColorDecls("stroke", value, extra);
7493
8157
  return [decl("stroke", value)];
7494
8158
  },
7495
8159
  handleCustomProperty: (value) => {
@@ -8498,56 +9162,10 @@ functionalModifier((mod) => /^child-(.+)$/.test(mod), ({ selector, mod }) => {
8498
9162
  };
8499
9163
  }, void 0);
8500
9164
  //#endregion
8501
- //#region src/core/rule-order.ts
8502
- var LEADING_AT = /^\s*@(media|container)\s+([^{]*)\{/;
8503
- var LATE_MEDIA = /prefers-color-scheme|\bprint\b|forced-colors|orientation/;
8504
- var MIN_W = /(?:min-width\s*:\s*|width\s*>=?\s*)([\d.]+)(px|rem|em)?/;
8505
- var MAX_W = /(?:max-width\s*:\s*|width\s*<=?\s*)([\d.]+)(px|rem|em)?/;
8506
- function toPx(n, unit) {
8507
- const v = parseFloat(n);
8508
- return unit === "rem" || unit === "em" ? v * 16 : v;
8509
- }
8510
- function preludeKey(kind, prelude) {
8511
- const container = kind === "container";
8512
- if (!container && /^\s*not\b/i.test(prelude)) return [0, 0];
8513
- const min = MIN_W.exec(prelude);
8514
- if (min) return [container ? 4 : 2, toPx(min[1], min[2])];
8515
- const max = MAX_W.exec(prelude);
8516
- if (max) return [container ? 3 : 1, -toPx(max[1], max[2])];
8517
- if (!container && LATE_MEDIA.test(prelude)) return [5, 0];
8518
- return [0, 0];
8519
- }
8520
- function ruleSortKey(rule) {
8521
- const key = [];
8522
- let rest = rule;
8523
- let m;
8524
- while (m = LEADING_AT.exec(rest)) {
8525
- const [g, v] = preludeKey(m[1], m[2]);
8526
- key.push(g, v);
8527
- rest = rest.slice(m[0].length);
8528
- }
8529
- return key;
8530
- }
8531
- function compareKeys(a, b) {
8532
- const n = Math.min(a.length, b.length);
8533
- for (let i = 0; i < n; i++) if (a[i] !== b[i]) return a[i] - b[i];
8534
- return a.length - b.length;
8535
- }
8536
- /** Index after the last key <= `key` (stable upper bound) in sorted `keys`. */
8537
- function upperBound(keys, key) {
8538
- let lo = 0;
8539
- let hi = keys.length;
8540
- while (lo < hi) {
8541
- const mid = lo + hi >> 1;
8542
- if (compareKeys(keys[mid], key) <= 0) lo = mid + 1;
8543
- else hi = mid;
8544
- }
8545
- return lo;
8546
- }
8547
- //#endregion
8548
9165
  exports.AstCache = AstCache;
8549
9166
  exports.IncrementalParser = IncrementalParser;
8550
9167
  exports.ParseResultCache = ParseResultCache;
9168
+ exports.REJECT_CLASS = REJECT_CLASS;
8551
9169
  exports.UtilityCache = UtilityCache;
8552
9170
  exports.WeakCache = WeakCache;
8553
9171
  exports.arbitraryPropertyRegistration = arbitraryPropertyRegistration;
@@ -8585,6 +9203,7 @@ exports.isBalancedPrelude = isBalancedPrelude;
8585
9203
  exports.isDebug = isDebug;
8586
9204
  exports.isSafeVariantToken = isSafeVariantToken;
8587
9205
  exports.isSafeVariantValue = isSafeVariantValue;
9206
+ exports.isScopedSelector = isScopedSelector;
8588
9207
  exports.isStructureSafeValue = isStructureSafeValue;
8589
9208
  exports.isWellFormedVariantBrackets = isWellFormedVariantBrackets;
8590
9209
  exports.jsonToAst = jsonToAst;