@csszyx/runtime 0.10.10 → 0.10.12

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
@@ -78,9 +78,11 @@ function getRecoveryMode(element) {
78
78
  return null;
79
79
  }
80
80
 
81
+ const MAX_HYDRATION_ERRORS = 100;
81
82
  const state = {
82
83
  errors: [],
83
- abortedSubtrees: /* @__PURE__ */ new Set(),
84
+ abortedSubtrees: /* @__PURE__ */ new WeakSet(),
85
+ abortedSubtreeCount: 0,
84
86
  recoveryAllowed: false
85
87
  };
86
88
  function enableCSRRecovery() {
@@ -206,7 +208,10 @@ function verifyMangleMapIntegrity() {
206
208
  }
207
209
  }
208
210
  function abortHydration(element, error) {
209
- state.abortedSubtrees.add(element);
211
+ if (!state.abortedSubtrees.has(element)) {
212
+ state.abortedSubtrees.add(element);
213
+ state.abortedSubtreeCount++;
214
+ }
210
215
  console.error(`[csszyx] Hydration aborted at ${element.tagName}:`, error.message);
211
216
  element.setAttribute("data-sz-hydration-aborted", error.timestamp.toString());
212
217
  element.setAttribute("data-sz-abort-reason", error.type);
@@ -215,6 +220,9 @@ function abortHydration(element, error) {
215
220
  ...error,
216
221
  element
217
222
  });
223
+ if (state.errors.length > MAX_HYDRATION_ERRORS) {
224
+ state.errors.shift();
225
+ }
218
226
  }
219
227
  function isHydrationAborted(element) {
220
228
  return state.abortedSubtrees.has(element) || element.hasAttribute("data-sz-hydration-aborted");
@@ -253,7 +261,9 @@ function attemptCSRRecovery(element) {
253
261
  element.removeAttribute("data-sz-hydration-aborted");
254
262
  element.removeAttribute("data-sz-abort-reason");
255
263
  element.removeAttribute("data-sz-interactive");
256
- state.abortedSubtrees.delete(element);
264
+ if (state.abortedSubtrees.delete(element)) {
265
+ state.abortedSubtreeCount--;
266
+ }
257
267
  return true;
258
268
  }
259
269
  function getHydrationErrors() {
@@ -261,10 +271,11 @@ function getHydrationErrors() {
261
271
  }
262
272
  function clearHydrationErrors() {
263
273
  state.errors = [];
264
- state.abortedSubtrees.clear();
274
+ state.abortedSubtrees = /* @__PURE__ */ new WeakSet();
275
+ state.abortedSubtreeCount = 0;
265
276
  }
266
277
  function getAbortedSubtreeCount() {
267
- return state.abortedSubtrees.size;
278
+ return state.abortedSubtreeCount;
268
279
  }
269
280
  function isSSREnvironment() {
270
281
  return typeof window === "undefined";
@@ -1123,6 +1134,292 @@ const BOX_ROLE_BY_KEY = /* @__PURE__ */ new Map([
1123
1134
  ["zoom", { role: "outer", category: "transform" }]
1124
1135
  ]);
1125
1136
 
1137
+ const PALETTE_SHADES = /* @__PURE__ */ new Set([
1138
+ "50",
1139
+ "100",
1140
+ "200",
1141
+ "300",
1142
+ "400",
1143
+ "500",
1144
+ "600",
1145
+ "700",
1146
+ "800",
1147
+ "900",
1148
+ "950"
1149
+ ]);
1150
+ const NAMED_COLORS = /* @__PURE__ */ new Set(["white", "black", "transparent", "current", "inherit"]);
1151
+ const TEXT_SIZES = /* @__PURE__ */ new Set([
1152
+ "xs",
1153
+ "sm",
1154
+ "base",
1155
+ "lg",
1156
+ "xl",
1157
+ "2xl",
1158
+ "3xl",
1159
+ "4xl",
1160
+ "5xl",
1161
+ "6xl",
1162
+ "7xl",
1163
+ "8xl",
1164
+ "9xl"
1165
+ ]);
1166
+ const TEXT_ALIGNS = /* @__PURE__ */ new Set(["left", "center", "right", "justify", "start", "end"]);
1167
+ const TEXT_WRAPS = /* @__PURE__ */ new Set(["wrap", "nowrap", "balance", "pretty"]);
1168
+ const TEXT_OVERFLOWS = /* @__PURE__ */ new Set(["clip", "ellipsis"]);
1169
+ const FONT_FAMILIES = /* @__PURE__ */ new Set(["sans", "serif", "mono"]);
1170
+ const FONT_WEIGHTS = /* @__PURE__ */ new Set([
1171
+ "thin",
1172
+ "extralight",
1173
+ "light",
1174
+ "normal",
1175
+ "medium",
1176
+ "semibold",
1177
+ "bold",
1178
+ "extrabold",
1179
+ "black"
1180
+ ]);
1181
+ const BG_POSITIONS = /* @__PURE__ */ new Set([
1182
+ "top",
1183
+ "bottom",
1184
+ "left",
1185
+ "right",
1186
+ "center",
1187
+ "top-left",
1188
+ "top-right",
1189
+ "bottom-left",
1190
+ "bottom-right",
1191
+ "left-top",
1192
+ "left-bottom",
1193
+ "right-top",
1194
+ "right-bottom"
1195
+ ]);
1196
+ const BG_SIZES = /* @__PURE__ */ new Set(["auto", "cover", "contain"]);
1197
+ const BG_REPEATS = /* @__PURE__ */ new Set([
1198
+ "repeat",
1199
+ "no-repeat",
1200
+ "repeat-x",
1201
+ "repeat-y",
1202
+ "repeat-round",
1203
+ "repeat-space"
1204
+ ]);
1205
+ const BG_ATTACHMENTS = /* @__PURE__ */ new Set(["fixed", "local", "scroll"]);
1206
+ const BORDER_STYLES = /* @__PURE__ */ new Set(["solid", "dashed", "dotted", "double", "hidden", "none"]);
1207
+ const FLEX_DIRECTIONS = /* @__PURE__ */ new Set(["row", "row-reverse", "col", "col-reverse"]);
1208
+ const FLEX_WRAPS = /* @__PURE__ */ new Set(["wrap", "wrap-reverse", "nowrap"]);
1209
+ const FLEX_SHORTHANDS = /* @__PURE__ */ new Set(["auto", "initial", "none"]);
1210
+ const DIRECTIONAL_SEGMENTS = /* @__PURE__ */ new Set(["t", "r", "b", "l", "x", "y", "s", "e"]);
1211
+ const customTokens = {
1212
+ colors: /* @__PURE__ */ new Set(),
1213
+ textSizes: /* @__PURE__ */ new Set(),
1214
+ fontFamilies: /* @__PURE__ */ new Set(),
1215
+ fontWeights: /* @__PURE__ */ new Set()
1216
+ };
1217
+ const AMBIGUITY_PAIRS = {
1218
+ colorTextSize: {
1219
+ dropped: /* @__PURE__ */ new Set(),
1220
+ message: (name) => `theme token "${name}" is defined as BOTH a color and a text size \u2014 szcn cannot classify \`text-${name}\` and will keep-both instead of merging.`
1221
+ },
1222
+ fontFamilyWeight: {
1223
+ dropped: /* @__PURE__ */ new Set(),
1224
+ message: (name) => `theme token "${name}" is defined as BOTH a font family and a font weight \u2014 szcn cannot classify \`font-${name}\` and will keep-both instead of merging.`
1225
+ }
1226
+ };
1227
+ const AMBIGUITY_PAIR_BY_CATEGORY = {
1228
+ colors: AMBIGUITY_PAIRS.colorTextSize,
1229
+ textSizes: AMBIGUITY_PAIRS.colorTextSize,
1230
+ fontFamilies: AMBIGUITY_PAIRS.fontFamilyWeight,
1231
+ fontWeights: AMBIGUITY_PAIRS.fontFamilyWeight
1232
+ };
1233
+ const COLLISION_BLOCKLIST = {
1234
+ colors: /* @__PURE__ */ new Set([
1235
+ ...NAMED_COLORS,
1236
+ ...TEXT_SIZES,
1237
+ ...TEXT_ALIGNS,
1238
+ ...TEXT_WRAPS,
1239
+ ...TEXT_OVERFLOWS,
1240
+ ...BG_POSITIONS,
1241
+ ...BG_SIZES,
1242
+ ...BG_REPEATS,
1243
+ ...BG_ATTACHMENTS,
1244
+ ...BORDER_STYLES
1245
+ ]),
1246
+ textSizes: /* @__PURE__ */ new Set([...TEXT_ALIGNS, ...TEXT_WRAPS, ...TEXT_OVERFLOWS, ...NAMED_COLORS]),
1247
+ fontFamilies: /* @__PURE__ */ new Set([...FONT_WEIGHTS]),
1248
+ fontWeights: /* @__PURE__ */ new Set([...FONT_FAMILIES])
1249
+ };
1250
+ function warnOnce(message) {
1251
+ if (process.env.NODE_ENV !== "production" && !_warned.has(message)) {
1252
+ _warned.add(message);
1253
+ console.warn(`[csszyx] ${message}`);
1254
+ }
1255
+ }
1256
+ const _warned = /* @__PURE__ */ new Set();
1257
+ function registerSzcnGroups(groups) {
1258
+ let changed = false;
1259
+ const entries = [
1260
+ ["colors", groups.colors],
1261
+ ["textSizes", groups.textSizes],
1262
+ ["fontFamilies", groups.fontFamilies],
1263
+ ["fontWeights", groups.fontWeights]
1264
+ ];
1265
+ for (const [category, names] of entries) {
1266
+ for (const name of names ?? []) {
1267
+ if (!name || typeof name !== "string") {
1268
+ continue;
1269
+ }
1270
+ if (COLLISION_BLOCKLIST[category].has(name)) {
1271
+ warnOnce(
1272
+ `theme token "${name}" shadows a built-in ${category === "colors" ? "utility keyword" : "value"} \u2014 szcn will not group classes built from it (they keep the safe keep-both behaviour). Rename the token to enable precise merging.`
1273
+ );
1274
+ continue;
1275
+ }
1276
+ const ambiguityPair = AMBIGUITY_PAIR_BY_CATEGORY[category];
1277
+ if (ambiguityPair.dropped.has(name)) {
1278
+ warnOnce(ambiguityPair.message(name));
1279
+ continue;
1280
+ }
1281
+ if (!customTokens[category].has(name)) {
1282
+ customTokens[category].add(name);
1283
+ changed = true;
1284
+ }
1285
+ }
1286
+ }
1287
+ for (const name of [...customTokens.colors]) {
1288
+ if (customTokens.textSizes.has(name)) {
1289
+ customTokens.colors.delete(name);
1290
+ customTokens.textSizes.delete(name);
1291
+ AMBIGUITY_PAIRS.colorTextSize.dropped.add(name);
1292
+ changed = true;
1293
+ warnOnce(AMBIGUITY_PAIRS.colorTextSize.message(name));
1294
+ }
1295
+ }
1296
+ for (const name of [...customTokens.fontFamilies]) {
1297
+ if (customTokens.fontWeights.has(name)) {
1298
+ customTokens.fontFamilies.delete(name);
1299
+ customTokens.fontWeights.delete(name);
1300
+ AMBIGUITY_PAIRS.fontFamilyWeight.dropped.add(name);
1301
+ changed = true;
1302
+ warnOnce(AMBIGUITY_PAIRS.fontFamilyWeight.message(name));
1303
+ }
1304
+ }
1305
+ if (changed) {
1306
+ _generation++;
1307
+ }
1308
+ }
1309
+ let _generation = 0;
1310
+ function getSzcnGroupsGeneration() {
1311
+ return _generation;
1312
+ }
1313
+ function isColorValue(rawValue) {
1314
+ const value = rawValue.replace(/\/[\w.[\]%]+$/, "");
1315
+ if (NAMED_COLORS.has(value) || customTokens.colors.has(value)) {
1316
+ return true;
1317
+ }
1318
+ const shadeAt = value.lastIndexOf("-");
1319
+ if (shadeAt > 0 && PALETTE_SHADES.has(value.slice(shadeAt + 1))) {
1320
+ return true;
1321
+ }
1322
+ return /^\[(?:#|rgb|hsl|oklch|oklab|lab|lch|color\()/.test(value);
1323
+ }
1324
+ function isLengthArbitrary(value) {
1325
+ return /^\[(?:-?[\d.]|calc\(|clamp\(|min\(|max\(|length:)/.test(value);
1326
+ }
1327
+ function classifyAmbiguousValue(prefix, value) {
1328
+ switch (prefix) {
1329
+ case "text": {
1330
+ const sizeValue = value.replace(/\/[\w.[\]]+$/, "");
1331
+ if (TEXT_SIZES.has(sizeValue) || customTokens.textSizes.has(sizeValue)) {
1332
+ return "text:size";
1333
+ }
1334
+ if (isLengthArbitrary(sizeValue)) {
1335
+ return "text:size";
1336
+ }
1337
+ if (TEXT_ALIGNS.has(value)) {
1338
+ return "text:align";
1339
+ }
1340
+ if (TEXT_WRAPS.has(value)) {
1341
+ return "text:wrap";
1342
+ }
1343
+ if (TEXT_OVERFLOWS.has(value)) {
1344
+ return "text:overflow";
1345
+ }
1346
+ if (isColorValue(value)) {
1347
+ return "text:color";
1348
+ }
1349
+ return null;
1350
+ }
1351
+ case "font": {
1352
+ if (FONT_FAMILIES.has(value) || customTokens.fontFamilies.has(value)) {
1353
+ return "font:family";
1354
+ }
1355
+ if (FONT_WEIGHTS.has(value) || customTokens.fontWeights.has(value) || /^\[\d+\]$/.test(value)) {
1356
+ return "font:weight";
1357
+ }
1358
+ return null;
1359
+ }
1360
+ case "bg": {
1361
+ if (isColorValue(value)) {
1362
+ return "bg:color";
1363
+ }
1364
+ if (BG_POSITIONS.has(value) || value.startsWith("position-")) {
1365
+ return "bg:position";
1366
+ }
1367
+ if (BG_SIZES.has(value) || value.startsWith("size-")) {
1368
+ return "bg:size";
1369
+ }
1370
+ if (BG_REPEATS.has(value)) {
1371
+ return "bg:repeat";
1372
+ }
1373
+ if (BG_ATTACHMENTS.has(value)) {
1374
+ return "bg:attachment";
1375
+ }
1376
+ if (value.startsWith("clip-")) {
1377
+ return "bg:clip";
1378
+ }
1379
+ if (value.startsWith("origin-")) {
1380
+ return "bg:origin";
1381
+ }
1382
+ if (value === "none" || value.startsWith("gradient-to-") || value.startsWith("linear-") || value === "radial" || value.startsWith("radial-") || value.startsWith("conic-") || value === "conic" || /^\[url\(/.test(value) || /^\[image:/.test(value)) {
1383
+ return "bg:image";
1384
+ }
1385
+ return null;
1386
+ }
1387
+ case "border":
1388
+ case "divide":
1389
+ case "ring":
1390
+ case "outline": {
1391
+ const firstSegment = value.split("-", 1)[0] ?? "";
1392
+ if (DIRECTIONAL_SEGMENTS.has(firstSegment)) {
1393
+ return null;
1394
+ }
1395
+ if (isColorValue(value)) {
1396
+ return `${prefix}:color`;
1397
+ }
1398
+ if (value === "" || /^\d+$/.test(value) || isLengthArbitrary(value)) {
1399
+ return `${prefix}:width`;
1400
+ }
1401
+ if (BORDER_STYLES.has(value)) {
1402
+ return `${prefix}:style`;
1403
+ }
1404
+ return null;
1405
+ }
1406
+ case "flex": {
1407
+ if (FLEX_DIRECTIONS.has(value)) {
1408
+ return "flex:direction";
1409
+ }
1410
+ if (FLEX_WRAPS.has(value)) {
1411
+ return "flex:wrap";
1412
+ }
1413
+ if (FLEX_SHORTHANDS.has(value) || /^\d+$/.test(value) || isLengthArbitrary(value)) {
1414
+ return "flex:shorthand";
1415
+ }
1416
+ return null;
1417
+ }
1418
+ default:
1419
+ return null;
1420
+ }
1421
+ }
1422
+
1126
1423
  function stripVariant(token) {
1127
1424
  let depth = 0;
1128
1425
  for (let i = token.length - 1; i >= 0; i--) {
@@ -1140,12 +1437,39 @@ function normalizeBase(base) {
1140
1437
  if (b.startsWith("-")) b = b.slice(1);
1141
1438
  return b;
1142
1439
  }
1440
+ const BOX_ROLE_PREFIXES_BY_FIRST_SEGMENT = (() => {
1441
+ const buckets = /* @__PURE__ */ new Map();
1442
+ for (const [prefix, entry] of BOX_ROLE_PREFIXES) {
1443
+ const segment = prefix.split("-", 1)[0];
1444
+ let bucket = buckets.get(segment);
1445
+ if (!bucket) {
1446
+ bucket = [];
1447
+ buckets.set(segment, bucket);
1448
+ }
1449
+ bucket.push([prefix, entry]);
1450
+ }
1451
+ return buckets;
1452
+ })();
1453
+ const INSPECT_MEMO_MAX = 4096;
1454
+ const inspectMemo = /* @__PURE__ */ new Map();
1143
1455
  function inspect(token) {
1456
+ if (inspectMemo.has(token)) {
1457
+ return inspectMemo.get(token);
1458
+ }
1459
+ const info = inspectUncached(token);
1460
+ if (inspectMemo.size >= INSPECT_MEMO_MAX) {
1461
+ inspectMemo.clear();
1462
+ }
1463
+ inspectMemo.set(token, info);
1464
+ return info;
1465
+ }
1466
+ function inspectUncached(token) {
1144
1467
  const base = normalizeBase(stripVariant(token));
1145
1468
  if (!base) return void 0;
1146
1469
  const exact = BOX_ROLE_TOKENS.get(base);
1147
1470
  if (exact) return { ...exact, base, value: base };
1148
- for (const [prefix, entry] of BOX_ROLE_PREFIXES) {
1471
+ const bucket = BOX_ROLE_PREFIXES_BY_FIRST_SEGMENT.get(base.split("-", 1)[0]) ?? [];
1472
+ for (const [prefix, entry] of bucket) {
1149
1473
  if (base === prefix) return { ...entry, base, value: "" };
1150
1474
  if (base.startsWith(`${prefix}-`)) {
1151
1475
  return { ...entry, base, value: base.slice(prefix.length + 1) };
@@ -1331,8 +1655,10 @@ const AMBIGUOUS_PREFIXES = /* @__PURE__ */ new Set([
1331
1655
  // divide-x (width) vs divide-red-500 (color)
1332
1656
  "ring",
1333
1657
  // ring-2 (width) vs ring-red-500 (color)
1334
- "outline"
1658
+ "outline",
1335
1659
  // outline-2 (width) vs outline-red-500 (color)
1660
+ "font"
1661
+ // font-sans (font-family) vs font-bold (font-weight)
1336
1662
  ]);
1337
1663
  function decodeToken(token) {
1338
1664
  const decode = globalThis.__csszyx?.decode;
@@ -1387,10 +1713,17 @@ function mergeClassify(token) {
1387
1713
  if (BOX_ROLE_TOKENS.has(norm)) {
1388
1714
  return null;
1389
1715
  }
1390
- for (const [prefix] of BOX_ROLE_PREFIXES) {
1716
+ const bucket = BOX_ROLE_PREFIXES_BY_FIRST_SEGMENT.get(norm.split("-", 1)[0]) ?? [];
1717
+ for (const [prefix] of bucket) {
1391
1718
  if (norm === prefix || norm.startsWith(`${prefix}-`)) {
1392
1719
  if (AMBIGUOUS_PREFIXES.has(prefix)) {
1393
- return null;
1720
+ const value = norm === prefix ? "" : norm.slice(prefix.length + 1);
1721
+ const group = classifyAmbiguousValue(prefix, value);
1722
+ if (group === null) {
1723
+ return null;
1724
+ }
1725
+ const key = `${variant} ${group}`;
1726
+ return { key, covers: [key] };
1394
1727
  }
1395
1728
  const coveredPrefixes = SHORTHAND_COVERAGE[prefix] ?? [prefix];
1396
1729
  return {
@@ -1401,7 +1734,41 @@ function mergeClassify(token) {
1401
1734
  }
1402
1735
  return null;
1403
1736
  }
1737
+ const MEMO_MAX_ENTRIES = 500;
1738
+ const memo = /* @__PURE__ */ new Map();
1739
+ let memoGroupsGeneration = -1;
1740
+ let memoDecodeRef;
1404
1741
  function szcn(...inputs) {
1742
+ let key = "";
1743
+ for (const input of inputs) {
1744
+ if (input && typeof input === "string") {
1745
+ key = key === "" ? input : `${key} ${input}`;
1746
+ }
1747
+ }
1748
+ const generation = getSzcnGroupsGeneration();
1749
+ const decodeRef = globalThis.__csszyx?.decode;
1750
+ if (generation !== memoGroupsGeneration || decodeRef !== memoDecodeRef) {
1751
+ memo.clear();
1752
+ memoGroupsGeneration = generation;
1753
+ memoDecodeRef = decodeRef;
1754
+ }
1755
+ const cached = memo.get(key);
1756
+ if (cached !== void 0) {
1757
+ memo.delete(key);
1758
+ memo.set(key, cached);
1759
+ return cached;
1760
+ }
1761
+ const merged = mergeUncached(inputs);
1762
+ memo.set(key, merged);
1763
+ if (memo.size > MEMO_MAX_ENTRIES) {
1764
+ const oldest = memo.keys().next().value;
1765
+ if (oldest !== void 0) {
1766
+ memo.delete(oldest);
1767
+ }
1768
+ }
1769
+ return merged;
1770
+ }
1771
+ function mergeUncached(inputs) {
1405
1772
  const order = [];
1406
1773
  const byKey = /* @__PURE__ */ new Map();
1407
1774
  for (const input of inputs) {
@@ -1450,6 +1817,10 @@ function stripSzProps(props) {
1450
1817
  return rest;
1451
1818
  }
1452
1819
 
1820
+ function szsClass(slot) {
1821
+ return typeof slot === "string" ? slot : void 0;
1822
+ }
1823
+
1453
1824
  const warned = /* @__PURE__ */ new Set();
1454
1825
  function devWarn(message) {
1455
1826
  if (process.env.NODE_ENV === "production") {
@@ -1495,9 +1866,12 @@ function validateSzvConfig(config) {
1495
1866
  if (config.base !== void 0 && !isPlainObject(config.base)) {
1496
1867
  devWarn(`szv(config): base must be an sz object, got ${describe(config.base)}.`);
1497
1868
  }
1869
+ if (config.variants === void 0) {
1870
+ return true;
1871
+ }
1498
1872
  if (!isPlainObject(config.variants)) {
1499
1873
  devWarn(
1500
- `szv(config): variants is required and must be an object, got ${describe(config.variants)}. Ignoring.`
1874
+ `szv(config): variants must be an object when present, got ${describe(config.variants)}. Ignoring.`
1501
1875
  );
1502
1876
  return false;
1503
1877
  }
@@ -1554,18 +1928,20 @@ function szv(config) {
1554
1928
  const configValid = validateSzvConfig(config);
1555
1929
  return function szVariantFn(selection) {
1556
1930
  if (!configValid) {
1557
- return isPlainObject(config?.base) ? { ...config.base } : {};
1931
+ return attachStringCoercionGuard(
1932
+ isPlainObject(config?.base) ? { ...config.base } : {}
1933
+ );
1558
1934
  }
1559
1935
  if (process.env.NODE_ENV !== "production" && selection) {
1560
1936
  for (const key of Object.keys(selection)) {
1561
- if (!(key in config.variants)) {
1937
+ if (!(key in (config.variants ?? {}))) {
1562
1938
  devWarn(
1563
1939
  `szv()(selection): unknown variant "${key}" \u2014 not declared in config.variants.`
1564
1940
  );
1565
1941
  continue;
1566
1942
  }
1567
1943
  const val = selection[key];
1568
- if (val !== null && val !== void 0 && !(String(val) in config.variants[key])) {
1944
+ if (val !== null && val !== void 0 && !(String(val) in (config.variants?.[key] ?? {}))) {
1569
1945
  devWarn(
1570
1946
  `szv()(selection): "${String(val)}" is not a value of variant "${key}" \u2014 it has no styles.`
1571
1947
  );
@@ -1590,14 +1966,30 @@ function szv(config) {
1590
1966
  if (selectedValue === null || selectedValue === void 0) {
1591
1967
  continue;
1592
1968
  }
1593
- const variantObj = config.variants[variantKey][selectedValue];
1969
+ const variantObj = config.variants?.[variantKey]?.[selectedValue];
1594
1970
  if (isPlainObject(variantObj)) {
1595
1971
  result = deepMerge(result, variantObj);
1596
1972
  }
1597
1973
  }
1598
- return result;
1974
+ return attachStringCoercionGuard(result);
1599
1975
  };
1600
1976
  }
1977
+ function attachStringCoercionGuard(result) {
1978
+ if (process.env.NODE_ENV !== "production") {
1979
+ Object.defineProperty(result, "toString", {
1980
+ value: () => {
1981
+ devWarn(
1982
+ 'szv() returned an sz OBJECT that was used as a string (e.g. className={someSzv({...})}) \u2014 this renders "[object Object]". Pass it to an sz= prop, or resolve it with szr(...) first.'
1983
+ );
1984
+ return "";
1985
+ },
1986
+ enumerable: false,
1987
+ writable: true,
1988
+ configurable: true
1989
+ });
1990
+ }
1991
+ return result;
1992
+ }
1601
1993
 
1602
1994
  const VERSION = "0.0.0";
1603
1995
  const DEFAULT_RUNTIME_CONFIG = {
@@ -1679,6 +2071,7 @@ exports.omit = omit;
1679
2071
  exports.omitSz = omitSz;
1680
2072
  exports.pick = pick;
1681
2073
  exports.pickSz = pickSz;
2074
+ exports.registerSzcnGroups = registerSzcnGroups;
1682
2075
  exports.resetRuntime = resetRuntime;
1683
2076
  exports.splitBox = splitBox;
1684
2077
  exports.splitBoxSz = splitBoxSz;
@@ -1686,6 +2079,7 @@ exports.startHydration = startHydration;
1686
2079
  exports.stripSzProps = stripSzProps;
1687
2080
  exports.szcn = szcn;
1688
2081
  exports.szr = szr;
2082
+ exports.szsClass = szsClass;
1689
2083
  exports.szv = szv;
1690
2084
  exports.validateHydrationClass = validateHydrationClass;
1691
2085
  exports.verifyAllTokens = verifyAllTokens;