@csszyx/runtime 0.10.10 → 0.10.11

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