@barocss/kit 0.9.0 → 0.10.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
@@ -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
  }`);
@@ -1737,6 +1743,11 @@ function parseClassToAst(fullClassName, ctx) {
1737
1743
  variantChain: modifiers,
1738
1744
  index: i
1739
1745
  });
1746
+ if (result == null) {
1747
+ debugWarn(`[BAROCSS] Unknown variant: "${variant.type}" in "${fullClassName}"`);
1748
+ failures.add(fullClassName);
1749
+ return [];
1750
+ }
1740
1751
  if (plugin.wrap && (result === "&" || typeof result === "object" && !Array.isArray(result) && result.selector === "&" || Array.isArray(result) && result.length === 1 && result[0].selector === "&")) continue;
1741
1752
  if (typeof result === "string" && result.includes("&")) wrappers.push({
1742
1753
  type: "rule",
@@ -1823,10 +1834,11 @@ function getAstCacheStats(ctx) {
1823
1834
  * @example
1824
1835
  * const css = generateCss('sm:dark:hover:bg-red-500 sm:focus:bg-blue-500', ctx);
1825
1836
  */
1837
+ var CLASS_SEPARATOR = /[ \t\n\f\r]+/;
1826
1838
  function generateCss(classList, ctx, opts) {
1827
1839
  const seen = /* @__PURE__ */ new Set();
1828
1840
  const allAtRootNodes = [];
1829
- const results = classList.split(/\s+/).filter((cls) => {
1841
+ const results = classList.split(CLASS_SEPARATOR).filter((cls) => {
1830
1842
  if (!cls) return false;
1831
1843
  if (opts?.dedup) {
1832
1844
  if (seen.has(cls)) return false;
@@ -1886,7 +1898,7 @@ function generateCss(classList, ctx, opts) {
1886
1898
  */
1887
1899
  function generateCssRules(classList, ctx, opts) {
1888
1900
  const seen = /* @__PURE__ */ new Set();
1889
- return classList.split(/\s+/).filter((cls) => {
1901
+ return classList.split(CLASS_SEPARATOR).filter((cls) => {
1890
1902
  if (!cls) return false;
1891
1903
  if (opts?.dedup) {
1892
1904
  if (seen.has(cls)) return false;
@@ -3125,6 +3137,7 @@ function jsonToAst(input, ctx) {
3125
3137
  variantChain: [],
3126
3138
  index: i
3127
3139
  });
3140
+ if (result == null) continue;
3128
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({
3129
3142
  type: "rule",
3130
3143
  selector: result
@@ -7610,19 +7623,14 @@ staticModifier("after", ["&::after"], {
7610
7623
  source: "pseudo",
7611
7624
  astHandler: withPseudoContent
7612
7625
  });
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" });
7626
+ staticModifier("placeholder", ["&::placeholder"], { source: "pseudo" });
7627
+ staticModifier("selection", ["& *::selection", "&::selection"], { source: "pseudo" });
7628
+ staticModifier("file", ["&::file-selector-button"], { source: "pseudo" });
7621
7629
  staticModifier("marker", [
7630
+ "& *::marker",
7622
7631
  "&::marker",
7623
- "&::-webkit-details-marker",
7624
- "&::-moz-list-bullet",
7625
- "&::-moz-list-number"
7632
+ "& *::-webkit-details-marker",
7633
+ "&::-webkit-details-marker"
7626
7634
  ], { source: "pseudo" });
7627
7635
  staticModifier("details-content", ["&::details-content"], { source: "pseudo" });
7628
7636
  staticModifier("first-line", ["&::first-line"], { source: "pseudo" });
@@ -7680,7 +7688,9 @@ function attributeVariantSelector(variant) {
7680
7688
  return `[${kind}-${key}=${/^(["']).*\1$/.test(raw) ? raw : `"${decodeArbitrarySelector(raw)}"`}]`;
7681
7689
  }
7682
7690
  const bare = /^data-([a-zA-Z0-9_-]+)$/.exec(variant);
7683
- return bare ? `[data-${bare[1]}]` : void 0;
7691
+ if (bare) return `[data-${bare[1]}]`;
7692
+ const aria = /^aria-([a-zA-Z0-9_-]+)$/.exec(variant);
7693
+ return aria ? `[aria-${aria[1]}="true"]` : void 0;
7684
7694
  }
7685
7695
  /**
7686
7696
  * The argument of a `:has()`/`:not()` built from an arbitrary value: a selector list is wrapped as `*:is(…)`
@@ -7701,6 +7711,80 @@ function hasTopLevelComma(value) {
7701
7711
  }
7702
7712
  return false;
7703
7713
  }
7714
+ /**
7715
+ * #335: the pseudo-class selector (`:hover`, `:first-child`, `:nth-child(odd)`) of a registered static
7716
+ * variant, for compounding in not-/group-/peer-/has- forms, or null when the variant is unknown or is not a
7717
+ * single pseudo-class (pseudo-elements, at-rules, multi-selector variants). Tailwind 4.3.3 emits nothing
7718
+ * for a compound variant whose inner variant it cannot compound (`not-foo`, `group-before`, `peer-has-foo`).
7719
+ */
7720
+ function pseudoClassOf(name, ctx) {
7721
+ const plugin = getModifier(ctx).find((p) => p.name === name && p.match(name, ctx));
7722
+ if (!plugin?.modifySelector) return null;
7723
+ const r = plugin.modifySelector({
7724
+ selector: "&",
7725
+ fullClassName: "",
7726
+ mod: { type: name },
7727
+ context: ctx
7728
+ });
7729
+ const list = Array.isArray(r) ? r : r && typeof r === "object" ? [r] : typeof r === "string" ? [{ selector: r }] : [];
7730
+ if (list.length !== 1) return null;
7731
+ const m = /^&(:(?!:)[a-zA-Z-]+(?:\(.*\))?)$/.exec(list[0].selector);
7732
+ return m ? m[1] : null;
7733
+ }
7734
+ /**
7735
+ * #352: the selector `not-<v>` / `group-not-<v>` negates: an attribute variant (`data-*`, `aria-*`), a
7736
+ * pseudo-class (#335), or a wrap-free `has-*` variant (`has-[…]`, `has-aria-*`), as Tailwind 4.3.3 compounds
7737
+ * them. Null when `<v>` is unknown or is not a single compound on `&`.
7738
+ */
7739
+ function negatableSelectorOf(name, ctx) {
7740
+ const attr = attributeVariantSelector(name);
7741
+ if (attr) return attr;
7742
+ const pc = pseudoClassOf(name, ctx);
7743
+ if (pc || !name.startsWith("has-")) return pc;
7744
+ const plugin = getModifier(ctx).find((p) => p.match(name, ctx));
7745
+ if (!plugin?.modifySelector || plugin.wrap || plugin.astHandler) return null;
7746
+ const r = plugin.modifySelector({
7747
+ selector: "&",
7748
+ fullClassName: "",
7749
+ mod: { type: name },
7750
+ context: ctx
7751
+ });
7752
+ const list = Array.isArray(r) ? r : r && typeof r === "object" ? [r] : typeof r === "string" ? [{ selector: r }] : [];
7753
+ if (list.length !== 1) return null;
7754
+ const m = /^&(:has\(.+\))$/.exec(list[0].selector);
7755
+ return m && !m[1].includes("&") ? m[1] : null;
7756
+ }
7757
+ /**
7758
+ * #352: `not-<v>` for a wrap-only at-rule variant (`md`, `max-md`, `min-[…]`, `print`, `motion-safe`,
7759
+ * `supports-[…]`, `dark` in media mode): the same at-rule with its condition negated (`@media not (…)`,
7760
+ * `@supports not (…)`), as Tailwind 4.3.3 emits it. Null for anything else, and for a prelude that is a list
7761
+ * or already combines conditions, where a leading `not` would not negate the whole query.
7762
+ */
7763
+ function negatedAtRuleOf(name, ctx) {
7764
+ if (name.startsWith("not-")) return null;
7765
+ const plugin = getModifier(ctx).find((p) => p.match(name, ctx));
7766
+ if (!plugin?.wrap || plugin.astHandler) return null;
7767
+ if (plugin.modifySelector) {
7768
+ const r = plugin.modifySelector({
7769
+ selector: "&",
7770
+ fullClassName: "",
7771
+ mod: { type: name },
7772
+ context: ctx
7773
+ });
7774
+ if ((typeof r === "string" ? r : Array.isArray(r) ? r.length === 1 ? r[0].selector : null : r?.selector) !== "&") return null;
7775
+ }
7776
+ const items = plugin.wrap({ type: name }, ctx);
7777
+ if (items.length !== 1) return null;
7778
+ const node = items[0];
7779
+ if (node.type !== "at-rule" || node.name !== "media" && node.name !== "supports" || node.nodes?.length) return null;
7780
+ const params = (node.params ?? "").trim();
7781
+ if (!params || /^not\b|,|\s(and|or)\s/i.test(params)) return null;
7782
+ return {
7783
+ ...node,
7784
+ params: `not ${params}`,
7785
+ nodes: []
7786
+ };
7787
+ }
7704
7788
  //#endregion
7705
7789
  //#region src/presets/variants/responsive.ts
7706
7790
  functionalModifier((mod, context) => {
@@ -7851,6 +7935,7 @@ function innerCompound(variant, ctx) {
7851
7935
  mod: { type: variant },
7852
7936
  context: ctx
7853
7937
  });
7938
+ if (out == null) return void 0;
7854
7939
  const list = typeof out === "string" ? [{ selector: out }] : Array.isArray(out) ? out : [out];
7855
7940
  if (list.length !== 1) return void 0;
7856
7941
  const sel = list[0].selector;
@@ -7945,6 +8030,10 @@ functionalModifier((mod, ctx) => {
7945
8030
  }, groupHasSelector);
7946
8031
  //#endregion
7947
8032
  //#region src/presets/variants/negation-variants.ts
8033
+ functionalModifier((mod, context) => /^not-(?!@)/.test(mod) && !!negatedAtRuleOf(mod.slice(4), context), () => "&", (mod, context) => {
8034
+ const node = negatedAtRuleOf(mod.type.slice(4), context);
8035
+ return node ? [node] : [];
8036
+ });
7948
8037
  functionalModifier((mod) => /^not-\[.*\]$/.test(mod), ({ selector, mod }) => {
7949
8038
  const m = /^not-\[(.+)\]$/.exec(mod.type);
7950
8039
  if (m) {
@@ -7966,10 +8055,12 @@ functionalModifier((mod) => /^not-\[.*\]$/.test(mod), ({ selector, mod }) => {
7966
8055
  source: "attribute"
7967
8056
  };
7968
8057
  });
7969
- functionalModifier((mod) => /^not-/.test(mod) && !mod.startsWith("not-@"), ({ selector, mod }) => {
8058
+ functionalModifier((mod) => /^not-/.test(mod) && !mod.startsWith("not-@"), ({ selector, mod, context }) => {
7970
8059
  const m = /^not-(.+)$/.exec(mod.type);
8060
+ const inner = m ? negatableSelectorOf(m[1], context) : null;
8061
+ if (m && !inner) return null;
7971
8062
  return {
7972
- selector: m ? `&:not(:${m[1]})` : selector,
8063
+ selector: inner ? `&:not(${inner})` : selector,
7973
8064
  flatten: false,
7974
8065
  wrappingType: "rule",
7975
8066
  source: "attribute"
@@ -8029,7 +8120,7 @@ functionalModifier((mod) => /^aria-/.test(mod), ({ selector, mod }) => {
8029
8120
  source: "aria"
8030
8121
  };
8031
8122
  }, void 0);
8032
- functionalModifier((mod) => mod.startsWith("not-") && !mod.startsWith("not-@"), ({ selector, mod }) => {
8123
+ functionalModifier((mod) => mod.startsWith("not-") && !mod.startsWith("not-@"), ({ selector, mod, context }) => {
8033
8124
  const pseudo = mod.type.replace("not-", "");
8034
8125
  if (pseudo.startsWith("[")) {
8035
8126
  const inner = pseudo.slice(1, -1);
@@ -8041,10 +8132,14 @@ functionalModifier((mod) => mod.startsWith("not-") && !mod.startsWith("not-@"),
8041
8132
  selector: `&:not(${functionalArgument(inner)})`,
8042
8133
  source: "attribute"
8043
8134
  };
8044
- } else return {
8045
- selector: `&:not(:${pseudo})`,
8046
- source: "attribute"
8047
- };
8135
+ } else {
8136
+ const inner = negatableSelectorOf(pseudo, context);
8137
+ if (!inner) return null;
8138
+ return {
8139
+ selector: `&:not(${inner})`,
8140
+ source: "attribute"
8141
+ };
8142
+ }
8048
8143
  }, void 0);
8049
8144
  functionalModifier((mod) => /^data-/.test(mod), ({ selector, mod }) => {
8050
8145
  const bracket = /^data-\[([a-zA-Z0-9_-]+)(?:=([^\]]+))?\]$/.exec(mod.type);
@@ -8157,11 +8252,13 @@ functionalModifier((mod) => /^(group|peer)-hover(\/[a-zA-Z0-9_-]+)?$/.test(mod),
8157
8252
  source: kind
8158
8253
  };
8159
8254
  }, () => [atRule("media", "(hover: hover)", [])]);
8160
- function negated(value) {
8255
+ function negated(value, ctx) {
8161
8256
  const v = value.slice(4);
8162
- return v.startsWith("[") && v.endsWith("]") ? `:not(*:is(${decodeArbitrarySelector(v.slice(1, -1))}))` : `:not(:${v})`;
8257
+ if (v.startsWith("[") && v.endsWith("]")) return `:not(*:is(${decodeArbitrarySelector(v.slice(1, -1))}))`;
8258
+ const inner = negatableSelectorOf(v, ctx);
8259
+ return inner ? `:not(${inner})` : null;
8163
8260
  }
8164
- functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod }) => {
8261
+ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod, context }) => {
8165
8262
  const raw = /^group-(.+)$/.exec(mod.type);
8166
8263
  const [variant, base] = splitGroupName("group", raw?.[1] ?? "");
8167
8264
  const m = raw ? [raw[0], variant] : null;
@@ -8177,11 +8274,14 @@ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ sele
8177
8274
  wrappingType: "rule",
8178
8275
  source: "group"
8179
8276
  };
8180
- if (m?.[1]?.startsWith("not-")) return {
8181
- selector: `&:is(${g}${negated(m[1])} *)`,
8182
- wrappingType: "rule",
8183
- source: "group"
8184
- };
8277
+ if (m?.[1]?.startsWith("not-")) {
8278
+ const neg = negated(m[1], context);
8279
+ return neg ? {
8280
+ selector: `&:is(${g}${neg} *)`,
8281
+ wrappingType: "rule",
8282
+ source: "group"
8283
+ } : null;
8284
+ }
8185
8285
  if (m?.[1]?.startsWith("has-")) {
8186
8286
  const pattern = /^has-\[([a-zA-Z0-9_-]+)\]$/.exec(m?.[1]);
8187
8287
  if (pattern) return {
@@ -8207,8 +8307,10 @@ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ sele
8207
8307
  };
8208
8308
  }
8209
8309
  }
8310
+ const pc = m ? pseudoClassOf(m[1], context) : null;
8311
+ if (m && !pc) return null;
8210
8312
  return m ? {
8211
- selector: `&:is(${g}:${m[1]} *)`,
8313
+ selector: `&:is(${g}${pc} *)`,
8212
8314
  wrappingType: "rule",
8213
8315
  source: "group"
8214
8316
  } : {
@@ -8216,7 +8318,7 @@ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ sele
8216
8318
  source: "group"
8217
8319
  };
8218
8320
  }, void 0);
8219
- functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod }) => {
8321
+ functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod, context }) => {
8220
8322
  const raw = /^peer-(.+)$/.exec(mod.type);
8221
8323
  const [variant, base] = splitGroupName("peer", raw?.[1] ?? "");
8222
8324
  const m = raw ? [raw[0], variant] : null;
@@ -8237,14 +8339,22 @@ functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selec
8237
8339
  selector: `&:is(${g}:has(${functionalArgument(value.slice(5, -1))}) ~ *)`,
8238
8340
  source: "peer"
8239
8341
  };
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
- };
8342
+ if (value?.startsWith("has-")) {
8343
+ const pc = pseudoClassOf(value.slice(4), context);
8344
+ if (!pc) return null;
8345
+ return {
8346
+ selector: `&:is(${g}:has(${pc})~*)`,
8347
+ source: "peer"
8348
+ };
8349
+ }
8350
+ if (value?.startsWith("not-")) {
8351
+ const neg = negated(value, context);
8352
+ if (!neg) return null;
8353
+ return {
8354
+ selector: `&:is(${g}${neg} ~ *)`,
8355
+ source: "peer"
8356
+ };
8357
+ }
8248
8358
  if (value?.startsWith("aria-")) {
8249
8359
  let pattern = /^aria-([a-zA-Z0-9_]+)$/.exec(value);
8250
8360
  if (pattern) return {
@@ -8265,8 +8375,10 @@ functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selec
8265
8375
  };
8266
8376
  }
8267
8377
  }
8378
+ const pc = m ? pseudoClassOf(value, context) : null;
8379
+ if (m && !pc) return null;
8268
8380
  return m ? {
8269
- selector: `&:is(${g}:${value}~*)`,
8381
+ selector: `&:is(${g}${pc}~*)`,
8270
8382
  source: "peer"
8271
8383
  } : {
8272
8384
  selector,
@@ -8315,6 +8427,7 @@ function toPx(n, unit) {
8315
8427
  }
8316
8428
  function preludeKey(kind, prelude) {
8317
8429
  const container = kind === "container";
8430
+ if (!container && /^\s*not\b/i.test(prelude)) return [0, 0];
8318
8431
  const min = MIN_W.exec(prelude);
8319
8432
  if (min) return [container ? 4 : 2, toPx(min[1], min[2])];
8320
8433
  const max = MAX_W.exec(prelude);