@barocss/kit 0.9.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1083,7 +1083,13 @@ function parseUtility(value, ctx) {
1083
1083
  //#region src/core/astToCss.ts
1084
1084
  var isSafePrelude = (text) => {
1085
1085
  const t = String(text ?? "");
1086
- return !hasCommentDelimiter(t) && !hasHtmlEndTagOpener(t) && isBalancedPrelude(t);
1086
+ return !hasCommentDelimiter(t) && !hasHtmlEndTagOpener(t) && isBalancedPrelude(t) && !/url\s*\(/i.test(t);
1087
+ };
1088
+ var uniqueDescriptors = (node) => {
1089
+ if (node.type !== "at-rule") return [];
1090
+ if (node.name !== "property") return node.nodes;
1091
+ const seen = /* @__PURE__ */ new Set();
1092
+ return node.nodes.filter((c) => c.type !== "decl" || !seen.has(c.prop) && !!seen.add(c.prop));
1087
1093
  };
1088
1094
  var isSafeDecl = (prop, value) => isStructureSafeValue(String(prop)) && isStructureSafeValue(String(value ?? "")) && !hasHtmlEndTagOpener(String(prop)) && !hasHtmlEndTagOpener(String(value ?? ""));
1089
1095
  var importantPrefix = "!important";
@@ -1179,10 +1185,10 @@ function rootToCss(nodes, opts) {
1179
1185
  if (isSafeDecl(node.prop, node.value)) list.push(minify ? `${node.prop}:${node.value};` : `${node.prop}: ${node.value};`);
1180
1186
  } else if (node.type === "at-rule" && isSafePrelude(node.name) && isSafePrelude(node.params)) {
1181
1187
  if (minify) {
1182
- const body = node.nodes.filter((child) => child.type === "decl" && isSafeDecl(child.prop, child.value)).map((child) => child.type === "decl" ? `${child.prop}:${child.value};` : "").join("");
1188
+ const body = uniqueDescriptors(node).filter((child) => child.type === "decl" && isSafeDecl(child.prop, child.value)).map((child) => child.type === "decl" ? `${child.prop}:${child.value};` : "").join("");
1183
1189
  list.push(`@${node.name} ${node.params}{${body}}`);
1184
1190
  } else list.push(`@${node.name} ${node.params} {
1185
- ${node.nodes.map((node) => {
1191
+ ${uniqueDescriptors(node).map((node) => {
1186
1192
  if (node.type === "decl" && isSafeDecl(node.prop, node.value)) return `\t${node.prop}: ${node.value};`;
1187
1193
  }).join("\n")}
1188
1194
  }`);
@@ -1442,6 +1448,7 @@ function themeToCssVarsAll(theme) {
1442
1448
  ...spacingToCssVars(theme.spacing),
1443
1449
  ...containerToCssVars(theme.container),
1444
1450
  ...borderRadiusToCssVars(theme.borderRadius),
1451
+ ...Object.fromEntries(Object.entries(theme.borderWidth ?? {}).filter(([k]) => k !== "DEFAULT").map(([k, v]) => [`--border-width-${escapeKey(k)}`, String(v)])),
1445
1452
  ...zIndexToCssVars(theme.zIndex),
1446
1453
  ...opacityToCssVars(theme.opacity),
1447
1454
  ...animationToCssVars({
@@ -1737,6 +1744,11 @@ function parseClassToAst(fullClassName, ctx) {
1737
1744
  variantChain: modifiers,
1738
1745
  index: i
1739
1746
  });
1747
+ if (result == null) {
1748
+ debugWarn(`[BAROCSS] Unknown variant: "${variant.type}" in "${fullClassName}"`);
1749
+ failures.add(fullClassName);
1750
+ return [];
1751
+ }
1740
1752
  if (plugin.wrap && (result === "&" || typeof result === "object" && !Array.isArray(result) && result.selector === "&" || Array.isArray(result) && result.length === 1 && result[0].selector === "&")) continue;
1741
1753
  if (typeof result === "string" && result.includes("&")) wrappers.push({
1742
1754
  type: "rule",
@@ -1823,10 +1835,11 @@ function getAstCacheStats(ctx) {
1823
1835
  * @example
1824
1836
  * const css = generateCss('sm:dark:hover:bg-red-500 sm:focus:bg-blue-500', ctx);
1825
1837
  */
1838
+ var CLASS_SEPARATOR = /[ \t\n\f\r]+/;
1826
1839
  function generateCss(classList, ctx, opts) {
1827
1840
  const seen = /* @__PURE__ */ new Set();
1828
1841
  const allAtRootNodes = [];
1829
- const results = classList.split(/\s+/).filter((cls) => {
1842
+ const results = classList.split(CLASS_SEPARATOR).filter((cls) => {
1830
1843
  if (!cls) return false;
1831
1844
  if (opts?.dedup) {
1832
1845
  if (seen.has(cls)) return false;
@@ -1886,7 +1899,7 @@ function generateCss(classList, ctx, opts) {
1886
1899
  */
1887
1900
  function generateCssRules(classList, ctx, opts) {
1888
1901
  const seen = /* @__PURE__ */ new Set();
1889
- return classList.split(/\s+/).filter((cls) => {
1902
+ return classList.split(CLASS_SEPARATOR).filter((cls) => {
1890
1903
  if (!cls) return false;
1891
1904
  if (opts?.dedup) {
1892
1905
  if (seen.has(cls)) return false;
@@ -3125,6 +3138,7 @@ function jsonToAst(input, ctx) {
3125
3138
  variantChain: [],
3126
3139
  index: i
3127
3140
  });
3141
+ if (result == null) continue;
3128
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({
3129
3143
  type: "rule",
3130
3144
  selector: result
@@ -6659,6 +6673,20 @@ var stopsDecls = (stop, color) => {
6659
6673
  category: "background"
6660
6674
  });
6661
6675
  });
6676
+ var BG_HINTS = {
6677
+ position: "background-position",
6678
+ percentage: "background-position",
6679
+ size: "background-size",
6680
+ length: "background-size",
6681
+ "bg-size": "background-size",
6682
+ image: "background-image",
6683
+ url: "background-image"
6684
+ };
6685
+ function bgHint(value) {
6686
+ const m = /^([a-z-]+):(.+)$/.exec(value);
6687
+ const prop = m ? BG_HINTS[m[1]] : void 0;
6688
+ return m && prop ? [prop, m[2]] : null;
6689
+ }
6662
6690
  /**
6663
6691
  * background-size utility (arbitrary, custom property supported)
6664
6692
  * bg-[length] → background-size: [length]
@@ -6676,7 +6704,8 @@ functionalUtility({
6676
6704
  supportsOpacity: true,
6677
6705
  handle: (value, context, token, extra) => {
6678
6706
  if (value.startsWith("url(")) return [decl("background-image", value)];
6679
- if (value.startsWith("length:")) return [decl("background-size", value.replace("length:", ""))];
6707
+ const hinted = bgHint(value);
6708
+ if (hinted) return [decl(hinted[0], hinted[1])];
6680
6709
  if (extra?.realThemeValue) return themeColorDecls("background-color", value, extra);
6681
6710
  if (parseColor(value)) {
6682
6711
  const parsedColor = parseColor(value);
@@ -6686,7 +6715,10 @@ functionalUtility({
6686
6715
  if (parseLength(value)) return [decl("background-size", value)];
6687
6716
  return null;
6688
6717
  },
6689
- handleCustomProperty: (value) => value.startsWith("length:") ? [decl("background-size", `var(${value.slice(7)})`)] : [decl("background-color", `var(${value})`)],
6718
+ handleCustomProperty: (value) => {
6719
+ const hinted = bgHint(value);
6720
+ return hinted ? [decl(hinted[0], `var(${hinted[1]})`)] : [decl("background-color", `var(${value})`)];
6721
+ },
6690
6722
  description: "background-size utility (arbitrary, custom property supported)",
6691
6723
  category: "background"
6692
6724
  });
@@ -6771,6 +6803,7 @@ functionalUtility({
6771
6803
  category: "borders"
6772
6804
  });
6773
6805
  var borderStyleProperty = () => atRoot([property("--baro-border-style", "solid")]);
6806
+ var borderWidthRef = (value, extra) => extra?.themeKey && extra.themeKey !== "DEFAULT" ? `var(--border-width-${extra.themeKey.replace(".", "\\.")})` : value;
6774
6807
  var withBorderStyle = (props, width) => [
6775
6808
  borderStyleProperty(),
6776
6809
  ...props.map((prop) => decl(prop.replace("width", "style"), "var(--baro-border-style)")),
@@ -6790,8 +6823,8 @@ var withBorderStyle = (props, width) => [
6790
6823
  ], { category: "borders" });
6791
6824
  });
6792
6825
  [
6793
- ["border-x", ["border-left-width", "border-right-width"]],
6794
- ["border-y", ["border-top-width", "border-bottom-width"]],
6826
+ ["border-x", ["border-inline-width"]],
6827
+ ["border-y", ["border-block-width"]],
6795
6828
  ["border-bs", ["border-block-start-width"]],
6796
6829
  ["border-be", ["border-block-end-width"]],
6797
6830
  ["border-s", ["border-inline-start-width"]],
@@ -6823,10 +6856,11 @@ var withBorderStyle = (props, width) => [
6823
6856
  return null;
6824
6857
  },
6825
6858
  handle: (value, ctx, token, extra) => {
6826
- if (extra?.themeNamespace === "borderWidth") return withBorderStyle(propList, value);
6859
+ if (extra?.themeNamespace === "borderWidth") return withBorderStyle(propList, borderWidthRef(value, extra));
6827
6860
  if (extra?.realThemeValue) return propList.flatMap((prop) => themeColorDecls(prop.replace("width", "color"), value, extra));
6828
6861
  if (parseColor(value)) return propList.map((prop) => decl(prop.replace("width", "color"), value));
6829
6862
  if (token.arbitrary) return withBorderStyle(propList, value);
6863
+ if (parseLength(value)) return withBorderStyle(propList, value);
6830
6864
  return null;
6831
6865
  },
6832
6866
  handleCustomProperty: (value) => {
@@ -6872,8 +6906,10 @@ Object.entries({
6872
6906
  name: `divide-${axis}`,
6873
6907
  themeKeys: ["divideWidth", "borderWidth"],
6874
6908
  supportsArbitrary: true,
6909
+ supportsCustomProperty: true,
6910
+ handleCustomProperty: (value) => divide(`var(${value.replace(/^length:/, "")})`),
6875
6911
  handleBareValue: ({ value }) => /^\d+$/.test(value) ? `${value}px` : null,
6876
- handle: (value) => divide(value),
6912
+ handle: (value, _ctx, _token, extra) => divide(extra?.themeNamespace === "borderWidth" ? borderWidthRef(value, extra) : value),
6877
6913
  description: `divide-${axis} width utility`,
6878
6914
  category: "borders"
6879
6915
  });
@@ -6885,7 +6921,7 @@ functionalUtility({
6885
6921
  supportsCustomProperty: true,
6886
6922
  supportsOpacity: true,
6887
6923
  handle: (value, ctx, token, extra) => {
6888
- if (extra?.themeNamespace === "borderWidth") return withBorderStyle(["border-width"], value);
6924
+ if (extra?.themeNamespace === "borderWidth") return withBorderStyle(["border-width"], borderWidthRef(value, extra));
6889
6925
  if (extra?.realThemeValue) return themeColorDecls("border-color", value, extra);
6890
6926
  if (token.arbitrary) {
6891
6927
  if (parseLength(value)) return withBorderStyle(["border-width"], value);
@@ -7007,12 +7043,13 @@ functionalUtility({
7007
7043
  supportsArbitrary: true,
7008
7044
  supportsCustomProperty: true,
7009
7045
  supportsOpacity: true,
7010
- handle: (value, _ctx, _token, extra) => {
7046
+ handle: (value, _ctx, token, extra) => {
7047
+ if (token.prefix !== "divide") return null;
7011
7048
  if (extra?.realThemeValue) return [rule(":where(& > :not(:last-child))", themeColorDecls("border-color", value, extra))];
7012
7049
  if (parseColor(value)) return divideColor(value);
7013
7050
  return null;
7014
7051
  },
7015
- handleCustomProperty: (value) => divideColor(`var(${value})`),
7052
+ handleCustomProperty: (value, _ctx, token) => token.prefix === "divide" ? divideColor(`var(${value})`) : [],
7016
7053
  description: "divide-color utility (theme, alpha, arbitrary, custom property)",
7017
7054
  category: "borders"
7018
7055
  });
@@ -7416,6 +7453,8 @@ functionalUtility({
7416
7453
  });
7417
7454
  //#endregion
7418
7455
  //#region src/presets/svg.ts
7456
+ var STROKE_WIDTH_HINT = /^(length|number|percentage):(.+)$/;
7457
+ var STROKE_LENGTH = /^(\d*\.)?\d+(px|em|rem|vh|vw|vmin|vmax|%|in|cm|mm|pt|pc|ex|ch|q|lh|rlh|svh|lvh|dvh|cqw|cqh)$/i;
7419
7458
  staticUtility("fill-inherit", [["fill", "inherit"]], { category: "svg" });
7420
7459
  staticUtility("fill-current", [["fill", "currentColor"]], { category: "svg" });
7421
7460
  staticUtility("fill-transparent", [["fill", "transparent"]], { category: "svg" });
@@ -7445,11 +7484,17 @@ functionalUtility({
7445
7484
  supportsCustomProperty: true,
7446
7485
  handle: (value, ctx, token, extra) => {
7447
7486
  if (parseNumber(value) || extra?.themeNamespace === "strokeWidth") return [decl("stroke-width", value)];
7487
+ if (token.arbitrary) {
7488
+ const hint = STROKE_WIDTH_HINT.exec(value);
7489
+ if (hint) return [decl("stroke-width", hint[2])];
7490
+ if (!parseColor(value) && (STROKE_LENGTH.test(value) || /^calc\(/.test(value))) return [decl("stroke-width", value)];
7491
+ }
7448
7492
  if (extra?.realThemeValue) return [decl("stroke", `var(--color-${extra.realThemeValue})`)];
7449
7493
  return [decl("stroke", value)];
7450
7494
  },
7451
7495
  handleCustomProperty: (value) => {
7452
- if (value.startsWith("length:")) return [decl("stroke-width", `var(${value.replace("length:", "")})`)];
7496
+ const hint = STROKE_WIDTH_HINT.exec(value);
7497
+ if (hint) return [decl("stroke-width", `var(${hint[2]})`)];
7453
7498
  return [decl("stroke", `var(${value})`)];
7454
7499
  },
7455
7500
  description: "stroke utility (static, theme, arbitrary, custom property supported)",
@@ -7527,6 +7572,21 @@ staticModifier("prefers-contrast-less", ["&"], {
7527
7572
  wrap: () => [atRule("media", "(prefers-contrast: less)", [], "media")],
7528
7573
  source: "media"
7529
7574
  });
7575
+ staticModifier("contrast-more", ["&"], {
7576
+ order: 5,
7577
+ wrap: () => [atRule("media", "(prefers-contrast: more)", [], "media")],
7578
+ source: "media"
7579
+ });
7580
+ staticModifier("contrast-less", ["&"], {
7581
+ order: 5,
7582
+ wrap: () => [atRule("media", "(prefers-contrast: less)", [], "media")],
7583
+ source: "media"
7584
+ });
7585
+ staticModifier("noscript", ["&"], {
7586
+ order: 5,
7587
+ wrap: () => [atRule("media", "(scripting: none)", [], "media")],
7588
+ source: "media"
7589
+ });
7530
7590
  staticModifier("forced-colors", ["&"], {
7531
7591
  order: 5,
7532
7592
  wrap: () => [atRule("media", "(forced-colors: active)", [], "media")],
@@ -7610,19 +7670,14 @@ staticModifier("after", ["&::after"], {
7610
7670
  source: "pseudo",
7611
7671
  astHandler: withPseudoContent
7612
7672
  });
7613
- staticModifier("placeholder", [
7614
- "&::placeholder",
7615
- "&::-webkit-input-placeholder",
7616
- "&::-moz-placeholder",
7617
- "&:-ms-input-placeholder"
7618
- ], { source: "pseudo" });
7619
- staticModifier("selection", ["&::selection", "&::-moz-selection"], { source: "pseudo" });
7620
- staticModifier("file", ["&::file-selector-button", "&::-webkit-file-upload-button"], { source: "pseudo" });
7673
+ staticModifier("placeholder", ["&::placeholder"], { source: "pseudo" });
7674
+ staticModifier("selection", ["& *::selection", "&::selection"], { source: "pseudo" });
7675
+ staticModifier("file", ["&::file-selector-button"], { source: "pseudo" });
7621
7676
  staticModifier("marker", [
7677
+ "& *::marker",
7622
7678
  "&::marker",
7623
- "&::-webkit-details-marker",
7624
- "&::-moz-list-bullet",
7625
- "&::-moz-list-number"
7679
+ "& *::-webkit-details-marker",
7680
+ "&::-webkit-details-marker"
7626
7681
  ], { source: "pseudo" });
7627
7682
  staticModifier("details-content", ["&::details-content"], { source: "pseudo" });
7628
7683
  staticModifier("first-line", ["&::first-line"], { source: "pseudo" });
@@ -7680,7 +7735,9 @@ function attributeVariantSelector(variant) {
7680
7735
  return `[${kind}-${key}=${/^(["']).*\1$/.test(raw) ? raw : `"${decodeArbitrarySelector(raw)}"`}]`;
7681
7736
  }
7682
7737
  const bare = /^data-([a-zA-Z0-9_-]+)$/.exec(variant);
7683
- return bare ? `[data-${bare[1]}]` : void 0;
7738
+ if (bare) return `[data-${bare[1]}]`;
7739
+ const aria = /^aria-([a-zA-Z0-9_-]+)$/.exec(variant);
7740
+ return aria ? `[aria-${aria[1]}="true"]` : void 0;
7684
7741
  }
7685
7742
  /**
7686
7743
  * The argument of a `:has()`/`:not()` built from an arbitrary value: a selector list is wrapped as `*:is(…)`
@@ -7701,6 +7758,104 @@ function hasTopLevelComma(value) {
7701
7758
  }
7702
7759
  return false;
7703
7760
  }
7761
+ /**
7762
+ * #335: the pseudo-class selector (`:hover`, `:first-child`, `:nth-child(odd)`) of a registered static
7763
+ * variant, for compounding in not-/group-/peer-/has- forms, or null when the variant is unknown or is not a
7764
+ * single pseudo-class (pseudo-elements, at-rules, multi-selector variants). Tailwind 4.3.3 emits nothing
7765
+ * for a compound variant whose inner variant it cannot compound (`not-foo`, `group-before`, `peer-has-foo`).
7766
+ */
7767
+ function pseudoClassOf(name, ctx) {
7768
+ const plugin = getModifier(ctx).find((p) => p.name === name && p.match(name, ctx));
7769
+ if (!plugin?.modifySelector) return null;
7770
+ const r = plugin.modifySelector({
7771
+ selector: "&",
7772
+ fullClassName: "",
7773
+ mod: { type: name },
7774
+ context: ctx
7775
+ });
7776
+ const list = Array.isArray(r) ? r : r && typeof r === "object" ? [r] : typeof r === "string" ? [{ selector: r }] : [];
7777
+ if (list.length !== 1) return null;
7778
+ const m = /^&(:(?!:)[a-zA-Z-]+(?:\(.*\))?)$/.exec(list[0].selector);
7779
+ return m ? m[1] : null;
7780
+ }
7781
+ /**
7782
+ * #352: the selector `not-<v>` / `group-not-<v>` negates: an attribute variant (`data-*`, `aria-*`), a
7783
+ * pseudo-class (#335), or a wrap-free `has-*` variant (`has-[…]`, `has-aria-*`), as Tailwind 4.3.3 compounds
7784
+ * them. Null when `<v>` is unknown or is not a single compound on `&`.
7785
+ */
7786
+ function negatableSelectorOf(name, ctx) {
7787
+ const attr = attributeVariantSelector(name);
7788
+ if (attr) return attr;
7789
+ const pc = pseudoClassOf(name, ctx);
7790
+ if (pc || !name.startsWith("has-")) return pc;
7791
+ const plugin = getModifier(ctx).find((p) => p.match(name, ctx));
7792
+ if (!plugin?.modifySelector || plugin.wrap || plugin.astHandler) return null;
7793
+ const r = plugin.modifySelector({
7794
+ selector: "&",
7795
+ fullClassName: "",
7796
+ mod: { type: name },
7797
+ context: ctx
7798
+ });
7799
+ const list = Array.isArray(r) ? r : r && typeof r === "object" ? [r] : typeof r === "string" ? [{ selector: r }] : [];
7800
+ if (list.length !== 1) return null;
7801
+ const m = /^&(:has\(.+\))$/.exec(list[0].selector);
7802
+ return m && !m[1].includes("&") ? m[1] : null;
7803
+ }
7804
+ /**
7805
+ * #352: `not-<v>` for a wrap-only at-rule variant (`md`, `max-md`, `min-[…]`, `print`, `motion-safe`,
7806
+ * `supports-[…]`, `dark` in media mode): the same at-rule with its condition negated (`@media not (…)`,
7807
+ * `@supports not (…)`), as Tailwind 4.3.3 emits it. Null for anything else, and for a prelude that is a list
7808
+ * or already combines conditions, where a leading `not` would not negate the whole query.
7809
+ */
7810
+ function negatedAtRuleOf(name, ctx) {
7811
+ if (name.startsWith("not-")) return null;
7812
+ const plugin = getModifier(ctx).find((p) => p.match(name, ctx));
7813
+ if (!plugin?.wrap || plugin.astHandler) return null;
7814
+ if (plugin.modifySelector) {
7815
+ const r = plugin.modifySelector({
7816
+ selector: "&",
7817
+ fullClassName: "",
7818
+ mod: { type: name },
7819
+ context: ctx
7820
+ });
7821
+ if ((typeof r === "string" ? r : Array.isArray(r) ? r.length === 1 ? r[0].selector : null : r?.selector) !== "&") return null;
7822
+ }
7823
+ const items = plugin.wrap({ type: name }, ctx);
7824
+ if (items.length !== 1) return null;
7825
+ const node = items[0];
7826
+ if (node.type !== "at-rule" || node.name !== "media" && node.name !== "supports" || node.nodes?.length) return null;
7827
+ const params = (node.params ?? "").trim();
7828
+ if (!params || /^not\b|,|\s(and|or)\s/i.test(params)) return null;
7829
+ return {
7830
+ ...node,
7831
+ params: `not ${params}`,
7832
+ nodes: []
7833
+ };
7834
+ }
7835
+ /**
7836
+ * #354: the at-rule for `not-[@<name> <params>]` (`_` decoded to a space), as Tailwind 4.3.3 emits it:
7837
+ * `@media`/`@supports` → `not <params>` (a leading `not` is removed instead), `@container [name] <query>` →
7838
+ * `@container [name] not <query>`. Null for any other at-rule, an empty condition or a top-level comma list,
7839
+ * where Tailwind emits nothing or an invalid prelude.
7840
+ */
7841
+ function negatedArbitraryAtRuleOf(value) {
7842
+ const m = /^@(media|supports|container)(?:\s+|(?=\()|$)([\s\S]*)$/.exec(decodeArbitrarySelector(value).trim());
7843
+ if (!m) return null;
7844
+ const name = m[1];
7845
+ let params = (m[2] ?? "").trim();
7846
+ let prefix = "";
7847
+ if (name === "container") {
7848
+ const n = /^(?!not\b)([a-zA-Z_-][a-zA-Z0-9_-]*)\s+([\s\S]*)$/.exec(params);
7849
+ if (n) {
7850
+ prefix = `${n[1]} `;
7851
+ params = n[2].trim();
7852
+ }
7853
+ }
7854
+ if (!params || hasTopLevelComma(params)) return null;
7855
+ const neg = /^not\s+/i.test(params) ? params.replace(/^not\s+/i, "") : `not ${params}`;
7856
+ if (!neg) return null;
7857
+ return atRule(name, `${prefix}${neg}`, [], name);
7858
+ }
7704
7859
  //#endregion
7705
7860
  //#region src/presets/variants/responsive.ts
7706
7861
  functionalModifier((mod, context) => {
@@ -7851,6 +8006,7 @@ function innerCompound(variant, ctx) {
7851
8006
  mod: { type: variant },
7852
8007
  context: ctx
7853
8008
  });
8009
+ if (out == null) return void 0;
7854
8010
  const list = typeof out === "string" ? [{ selector: out }] : Array.isArray(out) ? out : [out];
7855
8011
  if (list.length !== 1) return void 0;
7856
8012
  const sel = list[0].selector;
@@ -7945,7 +8101,15 @@ functionalModifier((mod, ctx) => {
7945
8101
  }, groupHasSelector);
7946
8102
  //#endregion
7947
8103
  //#region src/presets/variants/negation-variants.ts
7948
- functionalModifier((mod) => /^not-\[.*\]$/.test(mod), ({ selector, mod }) => {
8104
+ functionalModifier((mod, context) => /^not-(?!@)/.test(mod) && !!negatedAtRuleOf(mod.slice(4), context), () => "&", (mod, context) => {
8105
+ const node = negatedAtRuleOf(mod.type.slice(4), context);
8106
+ return node ? [node] : [];
8107
+ });
8108
+ functionalModifier((mod) => /^not-\[@.*\]$/.test(mod) && !!negatedArbitraryAtRuleOf(mod.slice(5, -1)), () => "&", (mod) => {
8109
+ const node = negatedArbitraryAtRuleOf(mod.type.slice(5, -1));
8110
+ return node ? [node] : [];
8111
+ });
8112
+ functionalModifier((mod) => /^not-\[(?!@).*\]$/.test(mod), ({ selector, mod }) => {
7949
8113
  const m = /^not-\[(.+)\]$/.exec(mod.type);
7950
8114
  if (m) {
7951
8115
  if (!/^[a-zA-Z0-9_-]+(=.+)?$/.test(m[1])) return {
@@ -7966,10 +8130,12 @@ functionalModifier((mod) => /^not-\[.*\]$/.test(mod), ({ selector, mod }) => {
7966
8130
  source: "attribute"
7967
8131
  };
7968
8132
  });
7969
- functionalModifier((mod) => /^not-/.test(mod) && !mod.startsWith("not-@"), ({ selector, mod }) => {
8133
+ functionalModifier((mod) => /^not-/.test(mod) && !mod.startsWith("not-@") && !mod.startsWith("not-[@"), ({ selector, mod, context }) => {
7970
8134
  const m = /^not-(.+)$/.exec(mod.type);
8135
+ const inner = m ? negatableSelectorOf(m[1], context) : null;
8136
+ if (m && !inner) return null;
7971
8137
  return {
7972
- selector: m ? `&:not(:${m[1]})` : selector,
8138
+ selector: inner ? `&:not(${inner})` : selector,
7973
8139
  flatten: false,
7974
8140
  wrappingType: "rule",
7975
8141
  source: "attribute"
@@ -8029,7 +8195,7 @@ functionalModifier((mod) => /^aria-/.test(mod), ({ selector, mod }) => {
8029
8195
  source: "aria"
8030
8196
  };
8031
8197
  }, void 0);
8032
- functionalModifier((mod) => mod.startsWith("not-") && !mod.startsWith("not-@"), ({ selector, mod }) => {
8198
+ functionalModifier((mod) => mod.startsWith("not-") && !mod.startsWith("not-@") && !mod.startsWith("not-[@"), ({ selector, mod, context }) => {
8033
8199
  const pseudo = mod.type.replace("not-", "");
8034
8200
  if (pseudo.startsWith("[")) {
8035
8201
  const inner = pseudo.slice(1, -1);
@@ -8041,10 +8207,14 @@ functionalModifier((mod) => mod.startsWith("not-") && !mod.startsWith("not-@"),
8041
8207
  selector: `&:not(${functionalArgument(inner)})`,
8042
8208
  source: "attribute"
8043
8209
  };
8044
- } else return {
8045
- selector: `&:not(:${pseudo})`,
8046
- source: "attribute"
8047
- };
8210
+ } else {
8211
+ const inner = negatableSelectorOf(pseudo, context);
8212
+ if (!inner) return null;
8213
+ return {
8214
+ selector: `&:not(${inner})`,
8215
+ source: "attribute"
8216
+ };
8217
+ }
8048
8218
  }, void 0);
8049
8219
  functionalModifier((mod) => /^data-/.test(mod), ({ selector, mod }) => {
8050
8220
  const bracket = /^data-\[([a-zA-Z0-9_-]+)(?:=([^\]]+))?\]$/.exec(mod.type);
@@ -8128,10 +8298,16 @@ functionalModifier((mod) => /^where-\[.*\]$/.test(mod), ({ selector, mod }) => {
8128
8298
  }, void 0);
8129
8299
  //#endregion
8130
8300
  //#region src/presets/variants/at-rules.ts
8131
- functionalModifier((mod) => /^supports-\[.*\]$/.test(mod), void 0, (mod) => {
8132
- const m = /^supports-\[(.+)\]$/.exec(mod.type);
8133
- if (m) return [atRule("supports", `(${m[1]})`, [], "supports")];
8134
- return [];
8301
+ function supportsCondition(value) {
8302
+ if (/^[\w-]*\s*\(/.test(value)) return value;
8303
+ let v = value.includes(":") ? value : `${value}: var(--tw)`;
8304
+ if (v[0] !== "(" || v[v.length - 1] !== ")") v = `(${v})`;
8305
+ return v;
8306
+ }
8307
+ functionalModifier((mod) => /^supports-(?:\[.+\]|[a-zA-Z-][a-zA-Z0-9-]*)$/.test(mod), void 0, (mod) => {
8308
+ const m = /^supports-(?:\[(.+)\]|([a-zA-Z-][a-zA-Z0-9-]*))$/.exec(mod.type);
8309
+ if (!m) return [];
8310
+ return [atRule("supports", supportsCondition(m[1] !== void 0 ? decodeArbitrarySelector(m[1]) : m[2]), [], "supports")];
8135
8311
  });
8136
8312
  functionalModifier((mod) => /^layer-\[.*\]$/.test(mod), void 0, (mod) => {
8137
8313
  const m = /^layer-\[(.+)\]$/.exec(mod.type);
@@ -8157,11 +8333,14 @@ functionalModifier((mod) => /^(group|peer)-hover(\/[a-zA-Z0-9_-]+)?$/.test(mod),
8157
8333
  source: kind
8158
8334
  };
8159
8335
  }, () => [atRule("media", "(hover: hover)", [])]);
8160
- function negated(value) {
8336
+ function negated(value, ctx) {
8161
8337
  const v = value.slice(4);
8162
- return v.startsWith("[") && v.endsWith("]") ? `:not(*:is(${decodeArbitrarySelector(v.slice(1, -1))}))` : `:not(:${v})`;
8338
+ if (v.startsWith("[@")) return null;
8339
+ if (v.startsWith("[") && v.endsWith("]")) return `:not(*:is(${decodeArbitrarySelector(v.slice(1, -1))}))`;
8340
+ const inner = negatableSelectorOf(v, ctx);
8341
+ return inner ? `:not(${inner})` : null;
8163
8342
  }
8164
- functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod }) => {
8343
+ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod, context }) => {
8165
8344
  const raw = /^group-(.+)$/.exec(mod.type);
8166
8345
  const [variant, base] = splitGroupName("group", raw?.[1] ?? "");
8167
8346
  const m = raw ? [raw[0], variant] : null;
@@ -8177,11 +8356,14 @@ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ sele
8177
8356
  wrappingType: "rule",
8178
8357
  source: "group"
8179
8358
  };
8180
- if (m?.[1]?.startsWith("not-")) return {
8181
- selector: `&:is(${g}${negated(m[1])} *)`,
8182
- wrappingType: "rule",
8183
- source: "group"
8184
- };
8359
+ if (m?.[1]?.startsWith("not-")) {
8360
+ const neg = negated(m[1], context);
8361
+ return neg ? {
8362
+ selector: `&:is(${g}${neg} *)`,
8363
+ wrappingType: "rule",
8364
+ source: "group"
8365
+ } : null;
8366
+ }
8185
8367
  if (m?.[1]?.startsWith("has-")) {
8186
8368
  const pattern = /^has-\[([a-zA-Z0-9_-]+)\]$/.exec(m?.[1]);
8187
8369
  if (pattern) return {
@@ -8207,8 +8389,10 @@ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ sele
8207
8389
  };
8208
8390
  }
8209
8391
  }
8392
+ const pc = m ? pseudoClassOf(m[1], context) : null;
8393
+ if (m && !pc) return null;
8210
8394
  return m ? {
8211
- selector: `&:is(${g}:${m[1]} *)`,
8395
+ selector: `&:is(${g}${pc} *)`,
8212
8396
  wrappingType: "rule",
8213
8397
  source: "group"
8214
8398
  } : {
@@ -8216,7 +8400,7 @@ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ sele
8216
8400
  source: "group"
8217
8401
  };
8218
8402
  }, void 0);
8219
- functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod }) => {
8403
+ functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod, context }) => {
8220
8404
  const raw = /^peer-(.+)$/.exec(mod.type);
8221
8405
  const [variant, base] = splitGroupName("peer", raw?.[1] ?? "");
8222
8406
  const m = raw ? [raw[0], variant] : null;
@@ -8237,14 +8421,22 @@ functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selec
8237
8421
  selector: `&:is(${g}:has(${functionalArgument(value.slice(5, -1))}) ~ *)`,
8238
8422
  source: "peer"
8239
8423
  };
8240
- if (value?.startsWith("has-")) return {
8241
- selector: `&:is(${g}:has(:${value.slice(4)})~*)`,
8242
- source: "peer"
8243
- };
8244
- if (value?.startsWith("not-")) return {
8245
- selector: `&:is(${g}${negated(value)} ~ *)`,
8246
- source: "peer"
8247
- };
8424
+ if (value?.startsWith("has-")) {
8425
+ const pc = pseudoClassOf(value.slice(4), context);
8426
+ if (!pc) return null;
8427
+ return {
8428
+ selector: `&:is(${g}:has(${pc})~*)`,
8429
+ source: "peer"
8430
+ };
8431
+ }
8432
+ if (value?.startsWith("not-")) {
8433
+ const neg = negated(value, context);
8434
+ if (!neg) return null;
8435
+ return {
8436
+ selector: `&:is(${g}${neg} ~ *)`,
8437
+ source: "peer"
8438
+ };
8439
+ }
8248
8440
  if (value?.startsWith("aria-")) {
8249
8441
  let pattern = /^aria-([a-zA-Z0-9_]+)$/.exec(value);
8250
8442
  if (pattern) return {
@@ -8265,8 +8457,10 @@ functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selec
8265
8457
  };
8266
8458
  }
8267
8459
  }
8460
+ const pc = m ? pseudoClassOf(value, context) : null;
8461
+ if (m && !pc) return null;
8268
8462
  return m ? {
8269
- selector: `&:is(${g}:${value}~*)`,
8463
+ selector: `&:is(${g}${pc}~*)`,
8270
8464
  source: "peer"
8271
8465
  } : {
8272
8466
  selector,
@@ -8315,6 +8509,7 @@ function toPx(n, unit) {
8315
8509
  }
8316
8510
  function preludeKey(kind, prelude) {
8317
8511
  const container = kind === "container";
8512
+ if (!container && /^\s*not\b/i.test(prelude)) return [0, 0];
8318
8513
  const min = MIN_W.exec(prelude);
8319
8514
  if (min) return [container ? 4 : 2, toPx(min[1], min[2])];
8320
8515
  const max = MAX_W.exec(prelude);