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