@kbach/react 0.6.37 → 0.6.40

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.
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/vite-plugin.ts
31
31
  var vite_plugin_exports = {};
32
32
  __export(vite_plugin_exports, {
33
+ formatKbachCSS: () => formatKbachCSS,
33
34
  kbach: () => kbach
34
35
  });
35
36
  module.exports = __toCommonJS(vite_plugin_exports);
@@ -653,6 +654,11 @@ var defaultTheme = {
653
654
  function isModeAwareColor(v) {
654
655
  return typeof v === "object" && v !== null && "light" in v && "dark" in v;
655
656
  }
657
+ function splitColorShadeRef(ref) {
658
+ const lastDash = ref.lastIndexOf("-");
659
+ if (lastDash <= 0) return null;
660
+ return { name: ref.slice(0, lastDash), shade: ref.slice(lastDash + 1) };
661
+ }
656
662
 
657
663
  // src/core/resolvers/color.ts
658
664
  function pickModeAwareFallback(v) {
@@ -672,13 +678,11 @@ function resolveColor(value, colors, isArbitrary) {
672
678
  else if (isModeAwareColor(entry)) hex = pickModeAwareFallback(entry);
673
679
  else if (typeof entry === "object" && "6" in entry) hex = pickModeAwareFallback(entry["6"]);
674
680
  } else {
675
- const lastDash = colorPart.lastIndexOf("-");
676
- if (lastDash > 0) {
677
- const colorName = colorPart.slice(0, lastDash);
678
- const shade = colorPart.slice(lastDash + 1);
679
- const scale = colors[colorName];
680
- if (scale && typeof scale === "object" && !isModeAwareColor(scale) && shade in scale) {
681
- const shadeVal = scale[shade];
681
+ const split = splitColorShadeRef(colorPart);
682
+ if (split) {
683
+ const scale = colors[split.name];
684
+ if (scale && typeof scale === "object" && !isModeAwareColor(scale) && split.shade in scale) {
685
+ const shadeVal = scale[split.shade];
682
686
  hex = shadeVal !== void 0 ? pickModeAwareFallback(shadeVal) : null;
683
687
  }
684
688
  }
@@ -819,6 +823,7 @@ function resolveSpacing(value, negative, spacing, isArbitrary) {
819
823
  if (negative) {
820
824
  if (typeof resolved === "number") return -resolved;
821
825
  if (typeof resolved === "string") {
826
+ if (resolved.startsWith("-")) return resolved.slice(1);
822
827
  if (/^\d/.test(resolved)) return `-${resolved}`;
823
828
  if (/^(calc|var|min|max|clamp|env)\s*\(/.test(resolved)) return `calc(-1 * (${resolved}))`;
824
829
  }
@@ -997,7 +1002,7 @@ function makeBorderSideResolver(widthProp, colorProp) {
997
1002
  if (!value) return { [widthProp]: 1 };
998
1003
  if (isArbitrary) {
999
1004
  const w2 = toNativeValue(value);
1000
- if (typeof w2 === "number") return { [widthProp]: w2 };
1005
+ if (typeof w2 === "number") return { [widthProp]: getEffectiveIsWeb() ? value : w2 };
1001
1006
  return { [colorProp]: value };
1002
1007
  }
1003
1008
  const color = resolveColor(value, colors, false);
@@ -1018,7 +1023,7 @@ var borderResolvers = {
1018
1023
  if (!value) return { borderWidth: borderWidth["DEFAULT"] ?? 1 };
1019
1024
  if (isArbitrary) {
1020
1025
  const w2 = toNativeValue(value);
1021
- if (typeof w2 === "number") return { borderWidth: w2 };
1026
+ if (typeof w2 === "number") return { borderWidth: getEffectiveIsWeb() ? value : w2 };
1022
1027
  return { borderColor: value };
1023
1028
  }
1024
1029
  const color = resolveColor(value, colors, false);
@@ -1217,9 +1222,9 @@ var filterResolvers = {
1217
1222
  const v = isArbitrary ? `contrast(${value})` : `contrast(${parseFloat(value) / 100})`;
1218
1223
  return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--kb-contrast": v, filter: FILTER_COMPOSE };
1219
1224
  },
1220
- grayscale: ({ value }) => {
1225
+ grayscale: ({ value, isArbitrary }) => {
1221
1226
  if (!getEffectiveIsWeb()) return null;
1222
- const v = value === "0" ? "grayscale(0)" : "grayscale(100%)";
1227
+ const v = isArbitrary ? `grayscale(${value})` : value === "0" ? "grayscale(0)" : "grayscale(100%)";
1223
1228
  return { "--kb-grayscale": v, filter: FILTER_COMPOSE };
1224
1229
  },
1225
1230
  "hue-rotate": ({ value, negative, isArbitrary }) => {
@@ -1228,9 +1233,9 @@ var filterResolvers = {
1228
1233
  if (isNaN(parseFloat(deg)) && !isArbitrary) return null;
1229
1234
  return { "--kb-hue-rotate": `hue-rotate(${deg})`, filter: FILTER_COMPOSE };
1230
1235
  },
1231
- invert: ({ value }) => {
1236
+ invert: ({ value, isArbitrary }) => {
1232
1237
  if (!getEffectiveIsWeb()) return null;
1233
- const v = value === "0" ? "invert(0)" : "invert(100%)";
1238
+ const v = isArbitrary ? `invert(${value})` : value === "0" ? "invert(0)" : "invert(100%)";
1234
1239
  return { "--kb-invert": v, filter: FILTER_COMPOSE };
1235
1240
  },
1236
1241
  saturate: ({ value, isArbitrary }) => {
@@ -1238,9 +1243,9 @@ var filterResolvers = {
1238
1243
  const v = isArbitrary ? `saturate(${value})` : `saturate(${parseFloat(value) / 100})`;
1239
1244
  return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--kb-saturate": v, filter: FILTER_COMPOSE };
1240
1245
  },
1241
- sepia: ({ value }) => {
1246
+ sepia: ({ value, isArbitrary }) => {
1242
1247
  if (!getEffectiveIsWeb()) return null;
1243
- const v = value === "0" ? "sepia(0)" : "sepia(100%)";
1248
+ const v = isArbitrary ? `sepia(${value})` : value === "0" ? "sepia(0)" : "sepia(100%)";
1244
1249
  return { "--kb-sepia": v, filter: FILTER_COMPOSE };
1245
1250
  },
1246
1251
  "drop-shadow": ({ value, isArbitrary }) => {
@@ -1291,9 +1296,10 @@ var filterResolvers = {
1291
1296
  const v = isArbitrary ? `contrast(${value})` : `contrast(${parseFloat(value) / 100})`;
1292
1297
  return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--kb-backdrop-contrast": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
1293
1298
  },
1294
- "backdrop-grayscale": ({ value }) => {
1299
+ "backdrop-grayscale": ({ value, isArbitrary }) => {
1295
1300
  if (!getEffectiveIsWeb()) return null;
1296
- return { "--kb-backdrop-grayscale": value === "0" ? "grayscale(0)" : "grayscale(100%)", backdropFilter: BACKDROP_FILTER_COMPOSE };
1301
+ const v = isArbitrary ? `grayscale(${value})` : value === "0" ? "grayscale(0)" : "grayscale(100%)";
1302
+ return { "--kb-backdrop-grayscale": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
1297
1303
  },
1298
1304
  "backdrop-hue-rotate": ({ value, negative, isArbitrary }) => {
1299
1305
  if (!getEffectiveIsWeb()) return null;
@@ -1301,9 +1307,10 @@ var filterResolvers = {
1301
1307
  if (isNaN(parseFloat(deg)) && !isArbitrary) return null;
1302
1308
  return { "--kb-backdrop-hue-rotate": `hue-rotate(${deg})`, backdropFilter: BACKDROP_FILTER_COMPOSE };
1303
1309
  },
1304
- "backdrop-invert": ({ value }) => {
1310
+ "backdrop-invert": ({ value, isArbitrary }) => {
1305
1311
  if (!getEffectiveIsWeb()) return null;
1306
- return { "--kb-backdrop-invert": value === "0" ? "invert(0)" : "invert(100%)", backdropFilter: BACKDROP_FILTER_COMPOSE };
1312
+ const v = isArbitrary ? `invert(${value})` : value === "0" ? "invert(0)" : "invert(100%)";
1313
+ return { "--kb-backdrop-invert": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
1307
1314
  },
1308
1315
  "backdrop-opacity": ({ value, isArbitrary }) => {
1309
1316
  if (!getEffectiveIsWeb()) return null;
@@ -1315,9 +1322,10 @@ var filterResolvers = {
1315
1322
  const v = isArbitrary ? `saturate(${value})` : `saturate(${parseFloat(value) / 100})`;
1316
1323
  return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--kb-backdrop-saturate": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
1317
1324
  },
1318
- "backdrop-sepia": ({ value }) => {
1325
+ "backdrop-sepia": ({ value, isArbitrary }) => {
1319
1326
  if (!getEffectiveIsWeb()) return null;
1320
- return { "--kb-backdrop-sepia": value === "0" ? "sepia(0)" : "sepia(100%)", backdropFilter: BACKDROP_FILTER_COMPOSE };
1327
+ const v = isArbitrary ? `sepia(${value})` : value === "0" ? "sepia(0)" : "sepia(100%)";
1328
+ return { "--kb-backdrop-sepia": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
1321
1329
  },
1322
1330
  "backdrop-filter": ({ value, isArbitrary }) => {
1323
1331
  if (!getEffectiveIsWeb()) return null;
@@ -1387,8 +1395,8 @@ var filterResolvers = {
1387
1395
 
1388
1396
  // src/core/resolvers/layout.ts
1389
1397
  var _standalone = null;
1390
- function buildStandalone() {
1391
- const web = getEffectiveIsWeb();
1398
+ var _standaloneWeb = null;
1399
+ function buildStandalone(web) {
1392
1400
  return {
1393
1401
  // Display
1394
1402
  // React Native only supports display:'flex'|'none'. Setting 'flex' explicitly is
@@ -1403,7 +1411,6 @@ function buildStandalone() {
1403
1411
  "inline-block": { display: web ? "inline-block" : "flex" },
1404
1412
  inline: { display: web ? "inline" : "flex" },
1405
1413
  grid: web ? { display: "grid" } : null,
1406
- grd: web ? { display: "grid" } : null,
1407
1414
  "inline-flex": { display: web ? "inline-flex" : "flex" },
1408
1415
  "inline-grid": { display: web ? "inline-grid" : "flex" },
1409
1416
  hidden: { display: "none" },
@@ -1755,7 +1762,11 @@ function buildStandalone() {
1755
1762
  };
1756
1763
  }
1757
1764
  function getStandalone() {
1758
- if (!_standalone) _standalone = buildStandalone();
1765
+ const web = getEffectiveIsWeb();
1766
+ if (!_standalone || _standaloneWeb !== web) {
1767
+ _standalone = buildStandalone(web);
1768
+ _standaloneWeb = web;
1769
+ }
1759
1770
  return _standalone;
1760
1771
  }
1761
1772
  var layoutResolvers = {
@@ -2319,6 +2330,18 @@ var effectResolvers = {
2319
2330
  if (!isArbitrary && isNaN(parseFloat(value))) return null;
2320
2331
  const ms = isArbitrary ? value : `${value}ms`;
2321
2332
  return { transitionDelay: ms };
2333
+ },
2334
+ ease: ({ value, isArbitrary }) => {
2335
+ if (!getEffectiveIsWeb()) return null;
2336
+ if (isArbitrary) return { transitionTimingFunction: value };
2337
+ const presets = {
2338
+ linear: "linear",
2339
+ in: "cubic-bezier(0.4, 0, 1, 1)",
2340
+ out: "cubic-bezier(0, 0, 0.2, 1)",
2341
+ "in-out": "cubic-bezier(0.4, 0, 0.2, 1)"
2342
+ };
2343
+ const v = presets[value];
2344
+ return v !== void 0 ? { transitionTimingFunction: v } : null;
2322
2345
  }
2323
2346
  };
2324
2347
 
@@ -2511,64 +2534,64 @@ var LRUCache = class {
2511
2534
  // src/core/registry.ts
2512
2535
  var BUILTIN_MODIFIERS = {
2513
2536
  // ── Mode ─────────────────────────────────────────────────────────────────
2514
- dark: { darkScheme: "dark", jsBehavior: "mode", jsMatch: (d) => d },
2515
- "not-light": { darkScheme: "dark", jsBehavior: "mode", jsMatch: (d) => d },
2516
- light: { darkScheme: "light", jsBehavior: "mode", jsMatch: (d) => !d },
2517
- "not-dark": { darkScheme: "light", jsBehavior: "mode", jsMatch: (d) => !d },
2537
+ dark: { order: 60, darkScheme: "dark", jsBehavior: "mode", jsMatch: (d) => d },
2538
+ "not-light": { order: 60, darkScheme: "dark", jsBehavior: "mode", jsMatch: (d) => d },
2539
+ light: { order: 60, darkScheme: "light", jsBehavior: "mode", jsMatch: (d) => !d },
2540
+ "not-dark": { order: 60, darkScheme: "light", jsBehavior: "mode", jsMatch: (d) => !d },
2518
2541
  // ── Interactive — JS state + CSS pseudo ───────────────────────────────────
2519
- hover: { pseudo: ":hover", jsBehavior: "interactive", jsMatch: (_, s) => !!s.hover },
2520
- "not-hover": { pseudo: ":not(:hover)", jsBehavior: "interactive", jsMatch: (_, s) => !s.hover },
2521
- focus: { pseudo: ":focus", jsBehavior: "interactive", jsMatch: (_, s) => !!s.focus },
2522
- "not-focus": { pseudo: ":not(:focus)", jsBehavior: "interactive", jsMatch: (_, s) => !s.focus },
2523
- active: { pseudo: ":active", jsBehavior: "interactive", jsMatch: (_, s) => !!s.active || !!s.pressed },
2524
- "not-active": { pseudo: ":not(:active)", jsBehavior: "interactive", jsMatch: (_, s) => !s.active && !s.pressed },
2525
- pressed: { pseudo: ":active", jsBehavior: "interactive", jsMatch: (_, s) => !!s.pressed || !!s.active },
2526
- "not-pressed": { pseudo: ":not(:active)", jsBehavior: "interactive", jsMatch: (_, s) => !s.pressed && !s.active },
2527
- disabled: { pseudo: ":disabled", jsBehavior: "interactive", jsMatch: (_, s) => !!s.disabled },
2528
- "not-disabled": { pseudo: ":not(:disabled)", jsBehavior: "interactive", jsMatch: (_, s) => !s.disabled },
2529
- checked: { pseudo: ":checked", jsBehavior: "interactive", jsMatch: (_, s) => !!s.checked },
2530
- "not-checked": { pseudo: ":not(:checked)", jsBehavior: "interactive", jsMatch: (_, s) => !s.checked },
2531
- visited: { pseudo: ":visited", jsBehavior: "interactive", jsMatch: (_, s) => !!s.visited },
2532
- "not-visited": { pseudo: ":not(:visited)", jsBehavior: "interactive", jsMatch: (_, s) => !s.visited },
2533
- placeholder: { pseudo: "::placeholder", jsBehavior: "interactive", jsMatch: (_, s) => !!s.placeholder },
2542
+ hover: { order: 10, pseudo: ":hover", jsBehavior: "interactive", jsMatch: (_, s) => !!s.hover },
2543
+ "not-hover": { order: 10, pseudo: ":not(:hover)", jsBehavior: "interactive", jsMatch: (_, s) => !s.hover },
2544
+ focus: { order: 20, pseudo: ":focus", jsBehavior: "interactive", jsMatch: (_, s) => !!s.focus },
2545
+ "not-focus": { order: 20, pseudo: ":not(:focus)", jsBehavior: "interactive", jsMatch: (_, s) => !s.focus },
2546
+ active: { order: 30, pseudo: ":active", jsBehavior: "interactive", jsMatch: (_, s) => !!s.active || !!s.pressed },
2547
+ "not-active": { order: 30, pseudo: ":not(:active)", jsBehavior: "interactive", jsMatch: (_, s) => !s.active && !s.pressed },
2548
+ pressed: { order: 30, pseudo: ":active", jsBehavior: "interactive", jsMatch: (_, s) => !!s.pressed || !!s.active },
2549
+ "not-pressed": { order: 30, pseudo: ":not(:active)", jsBehavior: "interactive", jsMatch: (_, s) => !s.pressed && !s.active },
2550
+ disabled: { order: 40, pseudo: ":disabled", jsBehavior: "interactive", jsMatch: (_, s) => !!s.disabled },
2551
+ "not-disabled": { order: 40, pseudo: ":not(:disabled)", jsBehavior: "interactive", jsMatch: (_, s) => !s.disabled },
2552
+ checked: { order: 35, pseudo: ":checked", jsBehavior: "interactive", jsMatch: (_, s) => !!s.checked },
2553
+ "not-checked": { order: 35, pseudo: ":not(:checked)", jsBehavior: "interactive", jsMatch: (_, s) => !s.checked },
2554
+ visited: { order: 5, pseudo: ":visited", jsBehavior: "interactive", jsMatch: (_, s) => !!s.visited },
2555
+ "not-visited": { order: 5, pseudo: ":not(:visited)", jsBehavior: "interactive", jsMatch: (_, s) => !s.visited },
2556
+ placeholder: { order: 0, pseudo: "::placeholder", jsBehavior: "interactive", jsMatch: (_, s) => !!s.placeholder },
2534
2557
  // ── CSS-only pseudo-classes (structural) ──────────────────────────────────
2535
- first: { pseudo: ":first-child", jsBehavior: "css-only", forcesImportant: true },
2536
- last: { pseudo: ":last-child", jsBehavior: "css-only", forcesImportant: true },
2537
- odd: { pseudo: ":nth-child(odd)", jsBehavior: "css-only", forcesImportant: true },
2538
- even: { pseudo: ":nth-child(even)", jsBehavior: "css-only", forcesImportant: true },
2539
- only: { pseudo: ":only-child", jsBehavior: "css-only", forcesImportant: true },
2540
- "focus-within": { pseudo: ":focus-within", jsBehavior: "css-only", forcesImportant: true },
2541
- "focus-visible": { pseudo: ":focus-visible", jsBehavior: "css-only", forcesImportant: true },
2558
+ first: { order: 0, pseudo: ":first-child", jsBehavior: "css-only", forcesImportant: true },
2559
+ last: { order: 0, pseudo: ":last-child", jsBehavior: "css-only", forcesImportant: true },
2560
+ odd: { order: 0, pseudo: ":nth-child(odd)", jsBehavior: "css-only", forcesImportant: true },
2561
+ even: { order: 0, pseudo: ":nth-child(even)", jsBehavior: "css-only", forcesImportant: true },
2562
+ only: { order: 0, pseudo: ":only-child", jsBehavior: "css-only", forcesImportant: true },
2563
+ "focus-within": { order: 15, pseudo: ":focus-within", jsBehavior: "css-only", forcesImportant: true },
2564
+ "focus-visible": { order: 25, pseudo: ":focus-visible", jsBehavior: "css-only", forcesImportant: true },
2542
2565
  // ── CSS-only pseudo-elements ───────────────────────────────────────────────
2543
- before: { pseudo: "::before", jsBehavior: "css-only" },
2544
- after: { pseudo: "::after", jsBehavior: "css-only" },
2545
- selection: { pseudo: "::selection", jsBehavior: "css-only" },
2546
- "first-letter": { pseudo: "::first-letter", jsBehavior: "css-only" },
2547
- "first-line": { pseudo: "::first-line", jsBehavior: "css-only" },
2548
- marker: { pseudo: "::marker", jsBehavior: "css-only" },
2566
+ before: { order: 0, pseudo: "::before", jsBehavior: "css-only" },
2567
+ after: { order: 0, pseudo: "::after", jsBehavior: "css-only" },
2568
+ selection: { order: 0, pseudo: "::selection", jsBehavior: "css-only" },
2569
+ "first-letter": { order: 0, pseudo: "::first-letter", jsBehavior: "css-only" },
2570
+ "first-line": { order: 0, pseudo: "::first-line", jsBehavior: "css-only" },
2571
+ marker: { order: 0, pseudo: "::marker", jsBehavior: "css-only" },
2549
2572
  // ── Group / peer ancestor selectors (CSS-only) ─────────────────────────────
2550
- "group-hover": { ancestorSelector: ".group:hover ", jsBehavior: "css-only", forcesImportant: true },
2551
- "group-focus": { ancestorSelector: ".group:focus ", jsBehavior: "css-only", forcesImportant: true },
2552
- "peer-hover": { ancestorSelector: ".peer:hover ~ ", jsBehavior: "css-only", forcesImportant: true },
2553
- "peer-focus": { ancestorSelector: ".peer:focus ~ ", jsBehavior: "css-only", forcesImportant: true },
2573
+ "group-hover": { order: 10, ancestorSelector: ".group:hover ", jsBehavior: "css-only", forcesImportant: true },
2574
+ "group-focus": { order: 20, ancestorSelector: ".group:focus ", jsBehavior: "css-only", forcesImportant: true },
2575
+ "peer-hover": { order: 10, ancestorSelector: ".peer:hover ~ ", jsBehavior: "css-only", forcesImportant: true },
2576
+ "peer-focus": { order: 20, ancestorSelector: ".peer:focus ~ ", jsBehavior: "css-only", forcesImportant: true },
2554
2577
  // ── Responsive — both CSS (@media min-width) and JS (breakpoints set) ──────
2555
- sm: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("sm") },
2556
- md: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("md") },
2557
- lg: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("lg") },
2558
- xl: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("xl") },
2559
- "2xl": { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("2xl") },
2578
+ sm: { order: 50, isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("sm") },
2579
+ md: { order: 50, isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("md") },
2580
+ lg: { order: 50, isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("lg") },
2581
+ xl: { order: 50, isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("xl") },
2582
+ "2xl": { order: 50, isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("2xl") },
2560
2583
  // ── Print media (CSS-only) ─────────────────────────────────────────────────
2561
- print: { mediaQuery: "print", jsBehavior: "css-only", forcesImportant: true },
2584
+ print: { order: 70, mediaQuery: "print", jsBehavior: "css-only", forcesImportant: true },
2562
2585
  // ── Orientation / accessibility media (CSS-only) ───────────────────────────
2563
- landscape: { mediaQuery: "(orientation: landscape)", jsBehavior: "css-only", forcesImportant: true },
2564
- portrait: { mediaQuery: "(orientation: portrait)", jsBehavior: "css-only", forcesImportant: true },
2565
- "motion-reduce": { mediaQuery: "(prefers-reduced-motion: reduce)", jsBehavior: "css-only", forcesImportant: true },
2566
- "motion-safe": { mediaQuery: "(prefers-reduced-motion: no-preference)", jsBehavior: "css-only", forcesImportant: true },
2567
- "contrast-more": { mediaQuery: "(prefers-contrast: more)", jsBehavior: "css-only", forcesImportant: true },
2568
- "contrast-less": { mediaQuery: "(prefers-contrast: less)", jsBehavior: "css-only", forcesImportant: true },
2586
+ landscape: { order: 70, mediaQuery: "(orientation: landscape)", jsBehavior: "css-only", forcesImportant: true },
2587
+ portrait: { order: 70, mediaQuery: "(orientation: portrait)", jsBehavior: "css-only", forcesImportant: true },
2588
+ "motion-reduce": { order: 70, mediaQuery: "(prefers-reduced-motion: reduce)", jsBehavior: "css-only", forcesImportant: true },
2589
+ "motion-safe": { order: 70, mediaQuery: "(prefers-reduced-motion: no-preference)", jsBehavior: "css-only", forcesImportant: true },
2590
+ "contrast-more": { order: 70, mediaQuery: "(prefers-contrast: more)", jsBehavior: "css-only", forcesImportant: true },
2591
+ "contrast-less": { order: 70, mediaQuery: "(prefers-contrast: less)", jsBehavior: "css-only", forcesImportant: true },
2569
2592
  // ── Directionality (CSS-only) ──────────────────────────────────────────────
2570
- rtl: { dirSelector: '[dir="rtl"] ', jsBehavior: "css-only", forcesImportant: true },
2571
- ltr: { dirSelector: '[dir="ltr"] ', jsBehavior: "css-only", forcesImportant: true }
2593
+ rtl: { order: 80, dirSelector: '[dir="rtl"] ', jsBehavior: "css-only", forcesImportant: true },
2594
+ ltr: { order: 80, dirSelector: '[dir="ltr"] ', jsBehavior: "css-only", forcesImportant: true }
2572
2595
  };
2573
2596
  var _pluginModifiers = {};
2574
2597
  var _allNames = null;
@@ -2605,6 +2628,8 @@ function getNamedGroupPeerModifier(name) {
2605
2628
  const pseudo = trigger === "hover" ? ":hover" : ":focus";
2606
2629
  const combinator = kind === "group" ? " " : " ~ ";
2607
2630
  const def = {
2631
+ // Matches the plain group-hover/group-focus/peer-hover/peer-focus order below.
2632
+ order: trigger === "hover" ? 10 : 20,
2608
2633
  ancestorSelector: `.${kind}\\/${escapedName}${pseudo}${combinator}`,
2609
2634
  jsBehavior: "css-only",
2610
2635
  forcesImportant: true
@@ -2618,6 +2643,15 @@ function getModifier(name) {
2618
2643
  function isKnownModifier(name) {
2619
2644
  return name in BUILTIN_MODIFIERS || name in _pluginModifiers || NAMED_GROUP_PEER_RE.test(name);
2620
2645
  }
2646
+ function getModifierOrder(bucketKey) {
2647
+ if (bucketKey === "base") return -1;
2648
+ let max = 0;
2649
+ for (const mod of bucketKey.split(":")) {
2650
+ const order = getModifier(mod)?.order ?? 0;
2651
+ if (order > max) max = order;
2652
+ }
2653
+ return max;
2654
+ }
2621
2655
 
2622
2656
  // src/core/parser.ts
2623
2657
  var UNSAFE_ARBITRARY_VALUE = /[{};\\]|\/\*|\*\//;
@@ -2830,9 +2864,12 @@ function setDefaultFontFamily(font) {
2830
2864
  }
2831
2865
  var _styleEl = null;
2832
2866
  var _ruleIndexByKey = /* @__PURE__ */ new Map();
2867
+ var _sheetKeys = [];
2868
+ var _ruleOrderByKey = /* @__PURE__ */ new Map();
2833
2869
  function evictInjectedRule(rule) {
2834
2870
  const idx = _ruleIndexByKey.get(rule);
2835
2871
  _ruleIndexByKey.delete(rule);
2872
+ _ruleOrderByKey.delete(rule);
2836
2873
  if (idx === void 0) return;
2837
2874
  const sheet = _styleEl?.sheet;
2838
2875
  if (!sheet) return;
@@ -2841,6 +2878,7 @@ function evictInjectedRule(rule) {
2841
2878
  } catch {
2842
2879
  return;
2843
2880
  }
2881
+ _sheetKeys.splice(idx, 1);
2844
2882
  for (const [key, i] of _ruleIndexByKey) {
2845
2883
  if (i > idx) _ruleIndexByKey.set(key, i - 1);
2846
2884
  }
@@ -3071,7 +3109,6 @@ function deepMerge(base, override) {
3071
3109
  }
3072
3110
  return result;
3073
3111
  }
3074
- var configStore = { resolved: null, listeners: /* @__PURE__ */ new Set(), customVariants: {} };
3075
3112
  function resolveColorRefs(colors) {
3076
3113
  const MAX_DEPTH = 5;
3077
3114
  function resolveChain(raw, side) {
@@ -3105,10 +3142,9 @@ function resolveColorRefs(colors) {
3105
3142
  const a = opacity > 1 ? opacity / 100 : opacity;
3106
3143
  return hexToRgba(baseHex, a);
3107
3144
  }
3108
- const lastDash = ref.lastIndexOf("-");
3109
- if (lastDash <= 0) return null;
3110
- const name = ref.slice(0, lastDash);
3111
- const shade = ref.slice(lastDash + 1);
3145
+ const split = splitColorShadeRef(ref);
3146
+ if (!split) return null;
3147
+ const { name, shade } = split;
3112
3148
  if (!/^\d+$/.test(shade)) return null;
3113
3149
  const entry = colors[name];
3114
3150
  if (!entry || typeof entry !== "object" || isModeAwareColor(entry)) return null;
@@ -3170,7 +3206,6 @@ function buildConfig(userConfig) {
3170
3206
  clearPluginUtilities();
3171
3207
  clearPluginModifiers();
3172
3208
  }
3173
- for (const k of Object.keys(configStore.customVariants)) delete configStore.customVariants[k];
3174
3209
  const pluginAPI = makePluginAPI(resolved.theme);
3175
3210
  for (const plugin of resolved.plugins) {
3176
3211
  plugin(pluginAPI);
@@ -3199,8 +3234,6 @@ function makePluginAPI(theme) {
3199
3234
  },
3200
3235
  addVariant(name, selectorOrDef) {
3201
3236
  const def = typeof selectorOrDef === "string" ? _selectorToModifierDef(selectorOrDef) : selectorOrDef;
3202
- const selector = typeof selectorOrDef === "string" ? selectorOrDef : selectorOrDef.pseudo ?? selectorOrDef.mediaQuery ?? selectorOrDef.ancestorSelector ?? null;
3203
- if (selector !== null && selector !== name) customVariants[name] = selector;
3204
3237
  registerModifier(name, def);
3205
3238
  },
3206
3239
  theme(path, defaultValue) {
@@ -3217,7 +3250,6 @@ function makePluginAPI(theme) {
3217
3250
  }
3218
3251
  };
3219
3252
  }
3220
- var customVariants = configStore.customVariants;
3221
3253
 
3222
3254
  // src/core/generateTypesDts.ts
3223
3255
  var HEADER = `// AUTO-GENERATED by Kbach from your kbach.config.js \u2014 do not edit by hand.
@@ -3319,7 +3351,8 @@ var GROUP_ORDER = ["Layout", "Sizing", "Spacing", "Typography", "Colors", "Borde
3319
3351
  function classifyToken(token, responsiveRe) {
3320
3352
  if (/^dark:/.test(token)) return "Dark Mode";
3321
3353
  if (responsiveRe.test(token)) return "Responsive";
3322
- const base = token.replace(/^(hover|focus|active|group-hover|peer-hover):/, "");
3354
+ const parsed = parseClass(token);
3355
+ const base = parsed ? parsed.value ? `${parsed.utility}-${parsed.value}` : parsed.utility : token;
3323
3356
  for (const [label, re] of GROUPS) {
3324
3357
  if (re.test(base)) return label;
3325
3358
  }
@@ -3455,7 +3488,9 @@ function formatKbachCSS(tokenCSS, theme, responsiveRe) {
3455
3488
  if (!css) continue;
3456
3489
  const label = classifyToken(token, responsiveRe);
3457
3490
  if (!groups.has(label)) groups.set(label, []);
3458
- groups.get(label).push(prettifyCSS(applyVars(css)));
3491
+ const parsedToken = parseClass(token);
3492
+ const bucketKey = parsedToken && parsedToken.modifiers.length > 0 ? parsedToken.modifiers.join(":") : "base";
3493
+ groups.get(label).push({ order: getModifierOrder(bucketKey), css: prettifyCSS(applyVars(css)) });
3459
3494
  }
3460
3495
  const out = ["/* Generated by Kbach \u2014 do not edit */"];
3461
3496
  if (declarations.size > 0) {
@@ -3470,9 +3505,10 @@ ${prettifyCSS(globalCSS)}`);
3470
3505
  for (const label of GROUP_ORDER) {
3471
3506
  const items = groups.get(label) ?? [];
3472
3507
  if (!items.length) continue;
3508
+ const sorted = [...items].sort((a, b) => a.order - b.order);
3473
3509
  out.push(`
3474
3510
  /* ${label} */`);
3475
- out.push(items.join("\n\n"));
3511
+ out.push(sorted.map((it) => it.css).join("\n\n"));
3476
3512
  }
3477
3513
  return out.join("\n");
3478
3514
  }
@@ -3741,6 +3777,13 @@ function kbach(userConfigOrOptions) {
3741
3777
  function scanProjectCssSelectors() {
3742
3778
  for (const dir of includeDirs) scanCssSelectorsInto((0, import_path.join)(root, dir), projectCssClasses);
3743
3779
  }
3780
+ function isWithinIncludeDirs(file) {
3781
+ const nf = normPath(file);
3782
+ return includeDirs.some((dir) => {
3783
+ const base = normPath((0, import_path.join)(root, dir));
3784
+ return nf === base || nf.startsWith(base.endsWith("/") ? base : `${base}/`);
3785
+ });
3786
+ }
3744
3787
  function buildTokenCSSView() {
3745
3788
  const active = /* @__PURE__ */ new Set();
3746
3789
  for (const tokens of fileTokens.values()) for (const t of tokens) active.add(t);
@@ -3842,6 +3885,7 @@ ${code}`,
3842
3885
  configureServer(server) {
3843
3886
  const onAddOrUnlink = (file, isUnlink) => {
3844
3887
  if (file.includes("node_modules")) return;
3888
+ if (!isWithinIncludeDirs(file)) return;
3845
3889
  if (CSS_FILE_RE.test(file)) {
3846
3890
  if (!isUnlink) scanCssFileInto(file, projectCssClasses);
3847
3891
  return;
@@ -3863,6 +3907,7 @@ ${code}`,
3863
3907
  },
3864
3908
  handleHotUpdate({ file, server }) {
3865
3909
  if (file.includes("node_modules")) return;
3910
+ if (!isWithinIncludeDirs(file)) return;
3866
3911
  if (CSS_FILE_RE.test(file)) {
3867
3912
  scanCssFileInto(file, projectCssClasses);
3868
3913
  return;
@@ -3879,5 +3924,6 @@ ${code}`,
3879
3924
  }
3880
3925
  // Annotate the CommonJS export names for ESM import in node:
3881
3926
  0 && (module.exports = {
3927
+ formatKbachCSS,
3882
3928
  kbach
3883
3929
  });