clava 0.4.1 → 0.4.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # clava
2
2
 
3
+ ## 0.4.2
4
+
5
+ - Improved [`refine`](https://clava.style/docs/reference/refine) iteration warnings to show the latest changing variant values with a shorter component creation stack.
6
+ - Fixed [`setDefaultVariants`](https://clava.style/docs/reference/refine#setdefaultvariants) calls with stable values to avoid extra [`refine`](https://clava.style/docs/reference/refine) passes.
7
+
3
8
  ## 0.4.1
4
9
 
5
10
  ### Improved refine iteration warning with debugging context
package/dist/index.js CHANGED
@@ -1,4 +1,92 @@
1
1
  import clsx from "clsx";
2
+ //#region src/refine-warning.ts
3
+ function captureCreationFrame(skipFn) {
4
+ if (process.env.NODE_ENV === "production") return void 0;
5
+ if (typeof Error.captureStackTrace === "function") {
6
+ const holder = {};
7
+ Error.captureStackTrace(holder, skipFn);
8
+ return holder;
9
+ }
10
+ return /* @__PURE__ */ new Error();
11
+ }
12
+ function formatCreationStack(frame) {
13
+ let stack = frame.stack;
14
+ if (!stack) return void 0;
15
+ const newlineIdx = stack.indexOf("\n");
16
+ if (newlineIdx > 0) {
17
+ const firstLine = stack.slice(0, newlineIdx);
18
+ if (firstLine === "Error" || firstLine.startsWith("Error:")) stack = stack.slice(newlineIdx + 1);
19
+ }
20
+ const frames = stack.split("\n");
21
+ for (let i = 0; i < frames.length; i++) {
22
+ const line = frames[i]?.trim();
23
+ if (!line) continue;
24
+ if (isInternalCreationFrame(line)) continue;
25
+ if (line.includes("/node_modules/")) continue;
26
+ if (line.includes("\\node_modules\\")) continue;
27
+ if (line.includes("node:internal")) continue;
28
+ return ` ${line}`;
29
+ }
30
+ }
31
+ function isInternalCreationFrame(line) {
32
+ if (line.includes("captureCreationFrame")) return true;
33
+ if (line.startsWith("at cv ")) return true;
34
+ if (line.startsWith("at cv(")) return true;
35
+ if (line.startsWith("cv@")) return true;
36
+ return false;
37
+ }
38
+ function formatVariantValue(value) {
39
+ if (typeof value === "string") return JSON.stringify(value);
40
+ if (typeof value === "number") {
41
+ if (Number.isNaN(value)) return "NaN";
42
+ return String(value);
43
+ }
44
+ if (typeof value === "bigint") return `${value}n`;
45
+ if (value === void 0) return "undefined";
46
+ if (value === null) return "null";
47
+ if (typeof value === "boolean") return String(value);
48
+ if (typeof value === "symbol") return String(value);
49
+ if (typeof value === "function") return "[function]";
50
+ return "[object]";
51
+ }
52
+ function setVariantChange(into, key, from, to) {
53
+ into.set(key, {
54
+ from,
55
+ to
56
+ });
57
+ }
58
+ function accumulateUnstableVariantChanges(into, prev, next) {
59
+ for (const key in next) {
60
+ if (!Object.hasOwn(next, key)) continue;
61
+ if (!Object.is(prev[key], next[key])) setVariantChange(into, key, prev[key], next[key]);
62
+ }
63
+ for (const key in prev) {
64
+ if (!Object.hasOwn(prev, key)) continue;
65
+ if (Object.hasOwn(next, key)) continue;
66
+ setVariantChange(into, key, prev[key], void 0);
67
+ }
68
+ }
69
+ function formatVariantChanges(changes) {
70
+ return Array.from(changes).map(([key, { from, to }]) => {
71
+ return `${key}: ${formatVariantValue(from)} -> ${formatVariantValue(to)}`;
72
+ }).join(", ");
73
+ }
74
+ function warnRefineLimit({ runState, creationFrame, unstableChanges }) {
75
+ if (process.env.NODE_ENV === "production") return;
76
+ if (runState.warned) return;
77
+ runState.warned = true;
78
+ let message = "Clava: Maximum refine iterations exceeded. This can happen when a refine callback calls setVariants or setDefaultVariants, but one of the variants changes on every run.";
79
+ if (unstableChanges && unstableChanges.size > 0) {
80
+ message += `\nVariant(s) that did not stabilize: ${Array.from(unstableChanges.keys()).join(", ")}.`;
81
+ message += `\nLatest variant changes before warning: ${formatVariantChanges(unstableChanges)}.`;
82
+ }
83
+ if (creationFrame) {
84
+ const creationStack = formatCreationStack(creationFrame);
85
+ if (creationStack) message += `\nComponent created at:\n${creationStack}`;
86
+ }
87
+ console.warn(message);
88
+ }
89
+ //#endregion
2
90
  //#region src/utils.ts
3
91
  const hasOwn = Object.prototype.hasOwnProperty;
4
92
  function isAsciiLetter(code) {
@@ -224,7 +312,6 @@ function isHTMLObjStyle(style) {
224
312
  const META_KEY = "__meta";
225
313
  const EMPTY_DEFAULTS = Object.freeze({});
226
314
  const MAX_REFINE_RUNS = 50;
227
- const REFINE_UNSTABLE_TRACKING_WINDOW = 10;
228
315
  function areVariantsEqual(a, b) {
229
316
  for (const key in a) {
230
317
  if (!Object.hasOwn(a, key)) continue;
@@ -236,48 +323,6 @@ function areVariantsEqual(a, b) {
236
323
  }
237
324
  return true;
238
325
  }
239
- function captureCreationFrame(skipFn) {
240
- if (process.env.NODE_ENV === "production") return void 0;
241
- if (typeof Error.captureStackTrace === "function") {
242
- const holder = {};
243
- Error.captureStackTrace(holder, skipFn);
244
- return holder;
245
- }
246
- return /* @__PURE__ */ new Error();
247
- }
248
- function formatCreationStack(frame) {
249
- let stack = frame.stack;
250
- if (!stack) return void 0;
251
- const newlineIdx = stack.indexOf("\n");
252
- if (newlineIdx > 0) {
253
- const firstLine = stack.slice(0, newlineIdx);
254
- if (firstLine === "Error" || firstLine.startsWith("Error:")) stack = stack.slice(newlineIdx + 1);
255
- }
256
- return stack;
257
- }
258
- function accumulateUnstableVariantKeys(into, prev, next) {
259
- for (const key in next) {
260
- if (!Object.hasOwn(next, key)) continue;
261
- if (!Object.is(prev[key], next[key])) into.add(key);
262
- }
263
- for (const key in prev) {
264
- if (!Object.hasOwn(prev, key)) continue;
265
- if (Object.hasOwn(next, key)) continue;
266
- into.add(key);
267
- }
268
- }
269
- function warnRefineLimit(runState, creationFrame, unstableKeys) {
270
- if (process.env.NODE_ENV === "production") return;
271
- if (runState.warned) return;
272
- runState.warned = true;
273
- let message = "Clava: Maximum refine iterations exceeded. This can happen when a refine callback calls setVariants or setDefaultVariants, but one of the variants changes on every run.";
274
- if (unstableKeys && unstableKeys.size > 0) message += `\nVariant(s) that did not stabilize: ${Array.from(unstableKeys).join(", ")}.`;
275
- if (creationFrame) {
276
- const creationStack = formatCreationStack(creationFrame);
277
- if (creationStack) message += `\nComponent created at:\n${creationStack}`;
278
- }
279
- console.warn(message);
280
- }
281
326
  function getExtUserVariantProps(userVariantProps, protectedVariants, changedVariants) {
282
327
  const extUserVariantProps = {};
283
328
  Object.assign(extUserVariantProps, userVariantProps);
@@ -775,7 +820,7 @@ function create({ transformClass = (className) => className } = {}) {
775
820
  if (!Object.hasOwn(newVariants, key)) continue;
776
821
  const value = newVariants[key];
777
822
  setChangedVariant(key, value, true);
778
- if (getCurrentVariantValue(key) === value) continue;
823
+ if (Object.is(getCurrentVariantValue(key), value)) continue;
779
824
  ensureUpdated()[key] = value;
780
825
  }
781
826
  return;
@@ -789,7 +834,7 @@ function create({ transformClass = (className) => className } = {}) {
789
834
  if (valueKey != null && disabledVariantValues[key]?.has(valueKey)) continue;
790
835
  }
791
836
  setChangedVariant(key, value, true);
792
- if (getCurrentVariantValue(key) === value) continue;
837
+ if (Object.is(getCurrentVariantValue(key), value)) continue;
793
838
  ensureUpdated()[key] = value;
794
839
  }
795
840
  },
@@ -804,9 +849,9 @@ function create({ transformClass = (className) => className } = {}) {
804
849
  const valueKey = getVariantValueKey(value);
805
850
  if (valueKey != null && disabledVariantValues[key]?.has(valueKey)) continue;
806
851
  }
852
+ if (Object.is(getCurrentVariantValue(key), value)) continue;
807
853
  setChangedVariant(key, value);
808
854
  if (pendingProtectedVariants) pendingProtectedVariants[key] = value;
809
- if (getCurrentVariantValue(key) === value) continue;
810
855
  ensureUpdated()[key] = value;
811
856
  }
812
857
  },
@@ -942,7 +987,7 @@ function create({ transformClass = (className) => className } = {}) {
942
987
  protectedVariants ??= {};
943
988
  protectedVariantKeys ??= /* @__PURE__ */ new Set();
944
989
  let workingResolved = resolved;
945
- let unstableKeys = null;
990
+ let unstableChanges = null;
946
991
  let lastClasses = [];
947
992
  let lastStyle = {};
948
993
  let isFirstRun = true;
@@ -970,12 +1015,16 @@ function create({ transformClass = (className) => className } = {}) {
970
1015
  }
971
1016
  return nextResolved;
972
1017
  }
973
- if (process.env.NODE_ENV !== "production" && runState.remaining < REFINE_UNSTABLE_TRACKING_WINDOW) {
974
- if (!unstableKeys) unstableKeys = /* @__PURE__ */ new Set();
975
- accumulateUnstableVariantKeys(unstableKeys, workingResolved, nextResolved);
1018
+ if (process.env.NODE_ENV !== "production" && runState.remaining < 10) {
1019
+ if (!unstableChanges) unstableChanges = /* @__PURE__ */ new Map();
1020
+ accumulateUnstableVariantChanges(unstableChanges, workingResolved, nextResolved);
976
1021
  }
977
1022
  if (useDirectOutput && runState.remaining === 0) {
978
- warnRefineLimit(runState, creationFrame, unstableKeys);
1023
+ warnRefineLimit({
1024
+ runState,
1025
+ creationFrame,
1026
+ unstableChanges
1027
+ });
979
1028
  return nextResolved;
980
1029
  }
981
1030
  if (useDirectOutput) {
@@ -988,7 +1037,11 @@ function create({ transformClass = (className) => className } = {}) {
988
1037
  workingResolved = nextResolved;
989
1038
  isFirstRun = false;
990
1039
  }
991
- warnRefineLimit(runState, creationFrame, unstableKeys);
1040
+ warnRefineLimit({
1041
+ runState,
1042
+ creationFrame,
1043
+ unstableChanges
1044
+ });
992
1045
  for (let i = 0; i < lastClasses.length; i++) classesOut.push(lastClasses[i]);
993
1046
  Object.assign(styleOut, lastStyle);
994
1047
  return workingResolved;
@@ -1017,7 +1070,7 @@ function create({ transformClass = (className) => className } = {}) {
1017
1070
  protectedVariants ??= {};
1018
1071
  protectedVariantKeys ??= /* @__PURE__ */ new Set();
1019
1072
  let workingResolved = resolved;
1020
- let unstableKeys = null;
1073
+ let unstableChanges = null;
1021
1074
  let reachedLimit = true;
1022
1075
  while (runState.remaining > 0) {
1023
1076
  runState.remaining -= 1;
@@ -1031,13 +1084,17 @@ function create({ transformClass = (className) => className } = {}) {
1031
1084
  reachedLimit = false;
1032
1085
  break;
1033
1086
  }
1034
- if (process.env.NODE_ENV !== "production" && runState.remaining < REFINE_UNSTABLE_TRACKING_WINDOW) {
1035
- if (!unstableKeys) unstableKeys = /* @__PURE__ */ new Set();
1036
- accumulateUnstableVariantKeys(unstableKeys, workingResolved, nextResolved);
1087
+ if (process.env.NODE_ENV !== "production" && runState.remaining < 10) {
1088
+ if (!unstableChanges) unstableChanges = /* @__PURE__ */ new Map();
1089
+ accumulateUnstableVariantChanges(unstableChanges, workingResolved, nextResolved);
1037
1090
  }
1038
1091
  workingResolved = nextResolved;
1039
1092
  }
1040
- if (reachedLimit) warnRefineLimit(runState, creationFrame, unstableKeys);
1093
+ if (reachedLimit) warnRefineLimit({
1094
+ runState,
1095
+ creationFrame,
1096
+ unstableChanges
1097
+ });
1041
1098
  return workingResolved;
1042
1099
  } : null;
1043
1100
  const computeResult = (props = EMPTY_DEFAULTS) => {