clava 0.4.1 → 0.5.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/CHANGELOG.md +46 -0
- package/README.md +26 -15
- package/dist/index.d.ts +10 -3
- package/dist/index.js +302 -170
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +415 -338
- package/src/refine-warning.ts +161 -0
- package/src/types.ts +24 -2
- package/tests/build.test.ts +1 -0
- package/tests/component-api.test.ts +81 -55
- package/tests/extend.test.ts +44 -10
- package/tests/prototype-pollution.test.ts +3 -4
- package/tests/refine-warning.test.ts +28 -0
- package/tests/refine.test.ts +300 -181
- package/tests/variants-inference.test.ts +81 -0
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 computed default variant or refine callback changes one of the variants 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);
|
|
@@ -305,6 +350,23 @@ function mergeVariants(target, source, skipKeys) {
|
|
|
305
350
|
}
|
|
306
351
|
return changed;
|
|
307
352
|
}
|
|
353
|
+
function mergeProtectedIntoBase(baseResolved, protectedVariants) {
|
|
354
|
+
if (!protectedVariants) return baseResolved;
|
|
355
|
+
let hasProtected = false;
|
|
356
|
+
for (const key in protectedVariants) {
|
|
357
|
+
if (!Object.hasOwn(protectedVariants, key)) continue;
|
|
358
|
+
hasProtected = true;
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
if (!hasProtected) return baseResolved;
|
|
362
|
+
const resolved = {};
|
|
363
|
+
Object.assign(resolved, baseResolved);
|
|
364
|
+
for (const key in protectedVariants) {
|
|
365
|
+
if (!Object.hasOwn(protectedVariants, key)) continue;
|
|
366
|
+
resolved[key] = protectedVariants[key];
|
|
367
|
+
}
|
|
368
|
+
return resolved;
|
|
369
|
+
}
|
|
308
370
|
function getComponentMeta(component) {
|
|
309
371
|
return component[META_KEY];
|
|
310
372
|
}
|
|
@@ -374,21 +436,11 @@ function collectVariantKeys(config) {
|
|
|
374
436
|
}
|
|
375
437
|
return Array.from(keys);
|
|
376
438
|
}
|
|
377
|
-
function isVariantDisabled(config, key) {
|
|
378
|
-
return config.variants?.[key] === null;
|
|
379
|
-
}
|
|
380
439
|
function getVariantValueKey(value) {
|
|
381
440
|
if (typeof value === "string") return value;
|
|
382
441
|
if (typeof value === "number") return String(value);
|
|
383
442
|
if (typeof value === "boolean") return String(value);
|
|
384
443
|
}
|
|
385
|
-
function isVariantValueDisabled(config, key, value) {
|
|
386
|
-
const valueKey = getVariantValueKey(value);
|
|
387
|
-
if (valueKey == null) return false;
|
|
388
|
-
const variant = config.variants?.[key];
|
|
389
|
-
if (!isRecordObject(variant)) return false;
|
|
390
|
-
return variant[valueKey] === null;
|
|
391
|
-
}
|
|
392
444
|
function collectDisabledVariantKeys(config) {
|
|
393
445
|
const keys = /* @__PURE__ */ new Set();
|
|
394
446
|
if (!config.variants) return keys;
|
|
@@ -569,6 +621,9 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
569
621
|
}
|
|
570
622
|
const variantEntryCount = variantEntryNames.length;
|
|
571
623
|
const functionVariantCount = functionVariantNames.length;
|
|
624
|
+
const computedDefaultNames = [];
|
|
625
|
+
const computedDefaultFns = [];
|
|
626
|
+
const defaultVariants = config.defaultVariants;
|
|
572
627
|
const staticDefaults = {};
|
|
573
628
|
if (extend) for (const ext of extend) {
|
|
574
629
|
const meta = getComponentMeta(ext);
|
|
@@ -580,7 +635,21 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
580
635
|
if (!isRecordObject(variantDef)) continue;
|
|
581
636
|
if (Object.hasOwn(variantDef, "false") && staticDefaults[name] === void 0) staticDefaults[name] = false;
|
|
582
637
|
}
|
|
583
|
-
if (
|
|
638
|
+
if (defaultVariants) for (const name in defaultVariants) {
|
|
639
|
+
if (!Object.hasOwn(defaultVariants, name)) continue;
|
|
640
|
+
const value = defaultVariants[name];
|
|
641
|
+
if (typeof value === "function") {
|
|
642
|
+
computedDefaultNames.push(name);
|
|
643
|
+
computedDefaultFns.push(value);
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
if (value === void 0) {
|
|
647
|
+
Reflect.deleteProperty(staticDefaults, name);
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
staticDefaults[name] = value;
|
|
651
|
+
}
|
|
652
|
+
const computedDefaultCount = computedDefaultNames.length;
|
|
584
653
|
if (hasAnyDisabled) for (const key in staticDefaults) {
|
|
585
654
|
if (!Object.hasOwn(staticDefaults, key)) continue;
|
|
586
655
|
if (disabledVariantKeys.has(key)) {
|
|
@@ -609,14 +678,19 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
609
678
|
} else extBaseClassesArr.push(meta.baseClass);
|
|
610
679
|
}
|
|
611
680
|
const extCount = extMetas.length;
|
|
681
|
+
const inheritedComputedDefaultKeys = /* @__PURE__ */ new Set();
|
|
682
|
+
for (let i = 0; i < extCount; i++) {
|
|
683
|
+
const keys = extMetas[i].computedDefaultKeys;
|
|
684
|
+
for (const key of keys) inheritedComputedDefaultKeys.add(key);
|
|
685
|
+
}
|
|
612
686
|
const extMetasWithRefine = [];
|
|
613
687
|
for (let i = 0; i < extCount; i++) {
|
|
614
688
|
const meta = extMetas[i];
|
|
615
|
-
if (meta.
|
|
689
|
+
if (meta.resolveRefine) extMetasWithRefine.push(meta);
|
|
616
690
|
}
|
|
617
691
|
const extMetasWithRefineCount = extMetasWithRefine.length;
|
|
618
692
|
const shouldCollectChangedVariants = extMetasWithRefineCount > 0;
|
|
619
|
-
const creationFrame = !!refine || extMetasWithRefineCount > 0 ? captureCreationFrame(cv) : void 0;
|
|
693
|
+
const creationFrame = !!refine || computedDefaultCount > 0 || extMetasWithRefineCount > 0 ? captureCreationFrame(cv) : void 0;
|
|
620
694
|
const functionVariantKeys = /* @__PURE__ */ new Set();
|
|
621
695
|
for (let i = 0; i < extCount; i++) {
|
|
622
696
|
const fnKeys = extMetas[i].functionVariantKeys;
|
|
@@ -627,6 +701,8 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
627
701
|
}
|
|
628
702
|
for (let i = 0; i < functionVariantCount; i++) functionVariantKeys.add(functionVariantNames[i]);
|
|
629
703
|
for (let i = 0; i < variantEntryCount; i++) functionVariantKeys.delete(variantEntryNames[i]);
|
|
704
|
+
const computedDefaultKeys = new Set(inheritedComputedDefaultKeys);
|
|
705
|
+
for (let i = 0; i < computedDefaultCount; i++) computedDefaultKeys.add(computedDefaultNames[i]);
|
|
630
706
|
let staticVariantsOverridingExtFn = null;
|
|
631
707
|
if (variantEntryCount > 0 && extCount > 0) for (let i = 0; i < variantEntryCount; i++) {
|
|
632
708
|
const name = variantEntryNames[i];
|
|
@@ -660,64 +736,42 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
660
736
|
out[key] = value;
|
|
661
737
|
}
|
|
662
738
|
}
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
if (
|
|
668
|
-
const v = childDefaults[key];
|
|
669
|
-
if (v === void 0) continue;
|
|
670
|
-
resolvedVariants[key] = v;
|
|
671
|
-
}
|
|
672
|
-
for (const key in userProps) {
|
|
673
|
-
if (!Object.hasOwn(userProps, key)) continue;
|
|
674
|
-
const v = userProps[key];
|
|
675
|
-
if (v === void 0) continue;
|
|
676
|
-
resolvedVariants[key] = v;
|
|
739
|
+
const isOwnDisabledValue = (key, value) => {
|
|
740
|
+
if (disabledVariantKeys.has(key)) return true;
|
|
741
|
+
if (hasDisabledVariantValues) {
|
|
742
|
+
const valueKey = getVariantValueKey(value);
|
|
743
|
+
if (valueKey != null && disabledVariantValues[key]?.has(valueKey)) return true;
|
|
677
744
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
745
|
+
return false;
|
|
746
|
+
};
|
|
747
|
+
const filterOwnDisabledVariants = (input, fallback) => {
|
|
748
|
+
if (!hasAnyDisabled) return input;
|
|
749
|
+
let hasOwnDisabledValue = false;
|
|
750
|
+
for (const key in input) {
|
|
751
|
+
if (!Object.hasOwn(input, key)) continue;
|
|
752
|
+
const value = input[key];
|
|
753
|
+
if (isOwnDisabledValue(key, value)) {
|
|
754
|
+
hasOwnDisabledValue = true;
|
|
755
|
+
break;
|
|
684
756
|
}
|
|
685
757
|
}
|
|
686
|
-
if (
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
758
|
+
if (!hasOwnDisabledValue) return input;
|
|
759
|
+
const filtered = {};
|
|
760
|
+
for (const key in input) {
|
|
761
|
+
if (!Object.hasOwn(input, key)) continue;
|
|
762
|
+
const value = input[key];
|
|
763
|
+
if (!isOwnDisabledValue(key, value)) {
|
|
764
|
+
filtered[key] = value;
|
|
765
|
+
continue;
|
|
691
766
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
setVariants: noop,
|
|
695
|
-
setDefaultVariants: (newDefaults) => {
|
|
696
|
-
for (const key in newDefaults) {
|
|
697
|
-
if (!Object.hasOwn(newDefaults, key)) continue;
|
|
698
|
-
const value = newDefaults[key];
|
|
699
|
-
if (userProps[key] !== void 0) continue;
|
|
700
|
-
if (isVariantDisabled(config, key)) continue;
|
|
701
|
-
if (isVariantValueDisabled(config, key, value)) continue;
|
|
702
|
-
refineDefaults[key] = value;
|
|
703
|
-
}
|
|
704
|
-
},
|
|
705
|
-
addClass: noop,
|
|
706
|
-
addStyle: noop
|
|
707
|
-
});
|
|
767
|
+
const fallbackValue = fallback[key];
|
|
768
|
+
if (fallbackValue !== void 0 && !isOwnDisabledValue(key, fallbackValue)) filtered[key] = fallbackValue;
|
|
708
769
|
}
|
|
709
|
-
return
|
|
710
|
-
}
|
|
770
|
+
return filtered;
|
|
771
|
+
};
|
|
711
772
|
function resolveVariantsHot(propsVariants) {
|
|
712
773
|
const defaults = {};
|
|
713
774
|
Object.assign(defaults, staticDefaults);
|
|
714
|
-
for (let i = 0; i < extMetasWithRefineCount; i++) {
|
|
715
|
-
const extDefaults = extMetasWithRefine[i].resolveDefaults(defaults, propsVariants);
|
|
716
|
-
for (const k in extDefaults) {
|
|
717
|
-
if (!Object.hasOwn(extDefaults, k)) continue;
|
|
718
|
-
defaults[k] = extDefaults[k];
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
775
|
for (const k in propsVariants) {
|
|
722
776
|
if (!Object.hasOwn(propsVariants, k)) continue;
|
|
723
777
|
const v = propsVariants[k];
|
|
@@ -729,7 +783,70 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
729
783
|
filterDisabledInto(defaults, result);
|
|
730
784
|
return result;
|
|
731
785
|
}
|
|
732
|
-
const
|
|
786
|
+
const runComputedDefaults = (resolved, defaultResolved, userVariantProps, filterOwnVariants, protectedVariantKeys) => {
|
|
787
|
+
if (computedDefaultCount === 0) return {
|
|
788
|
+
workingResolved: resolved,
|
|
789
|
+
changedVariants: null
|
|
790
|
+
};
|
|
791
|
+
let ownVariants = filterOwnVariants ? null : resolved;
|
|
792
|
+
const getOwnVariants = () => {
|
|
793
|
+
if (ownVariants) return ownVariants;
|
|
794
|
+
const filteredVariants = {};
|
|
795
|
+
for (let i = 0; i < variantKeysLength; i++) {
|
|
796
|
+
const key = variantKeys[i];
|
|
797
|
+
if (Object.hasOwn(resolved, key)) filteredVariants[key] = resolved[key];
|
|
798
|
+
}
|
|
799
|
+
ownVariants = filteredVariants;
|
|
800
|
+
return filteredVariants;
|
|
801
|
+
};
|
|
802
|
+
let updatedVariants = null;
|
|
803
|
+
let changedVariants = null;
|
|
804
|
+
const ensureUpdated = () => {
|
|
805
|
+
if (updatedVariants) return updatedVariants;
|
|
806
|
+
const updated = {};
|
|
807
|
+
Object.assign(updated, resolved);
|
|
808
|
+
updatedVariants = updated;
|
|
809
|
+
return updated;
|
|
810
|
+
};
|
|
811
|
+
for (let i = 0; i < computedDefaultCount; i++) {
|
|
812
|
+
const key = computedDefaultNames[i];
|
|
813
|
+
if (Object.hasOwn(userVariantProps, key)) {
|
|
814
|
+
if (userVariantProps[key] !== void 0) continue;
|
|
815
|
+
}
|
|
816
|
+
if (protectedVariantKeys?.has(key)) continue;
|
|
817
|
+
const variantSnapshot = getOwnVariants();
|
|
818
|
+
const defaultValue = inheritedComputedDefaultKeys.has(key) ? variantSnapshot[key] : defaultResolved[key];
|
|
819
|
+
const value = computedDefaultFns[i]({
|
|
820
|
+
defaultValue,
|
|
821
|
+
variants: variantSnapshot
|
|
822
|
+
});
|
|
823
|
+
if (hasAnyDisabled) {
|
|
824
|
+
if (disabledVariantKeys.has(key)) continue;
|
|
825
|
+
const valueKey = getVariantValueKey(value);
|
|
826
|
+
if (valueKey != null && disabledVariantValues[key]?.has(valueKey)) continue;
|
|
827
|
+
}
|
|
828
|
+
if (value === void 0) {
|
|
829
|
+
if (!Object.hasOwn(variantSnapshot, key)) continue;
|
|
830
|
+
if (shouldCollectChangedVariants) {
|
|
831
|
+
changedVariants ??= {};
|
|
832
|
+
changedVariants[key] = value;
|
|
833
|
+
}
|
|
834
|
+
Reflect.deleteProperty(ensureUpdated(), key);
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
if (Object.is(variantSnapshot[key], value)) continue;
|
|
838
|
+
if (shouldCollectChangedVariants) {
|
|
839
|
+
changedVariants ??= {};
|
|
840
|
+
changedVariants[key] = value;
|
|
841
|
+
}
|
|
842
|
+
ensureUpdated()[key] = value;
|
|
843
|
+
}
|
|
844
|
+
return {
|
|
845
|
+
workingResolved: updatedVariants ?? resolved,
|
|
846
|
+
changedVariants
|
|
847
|
+
};
|
|
848
|
+
};
|
|
849
|
+
const runRefineContext = (resolved, userVariantProps, filterOwnVariants, collectOutput, applyVariantUpdates, protectedVariants, pendingProtectedVariants, protectedVariantKeys) => {
|
|
733
850
|
let workingResolved = resolved;
|
|
734
851
|
let cClasses = null;
|
|
735
852
|
let cStyle = null;
|
|
@@ -770,12 +887,13 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
770
887
|
const result = refine({
|
|
771
888
|
variants: ownVariants,
|
|
772
889
|
setVariants: (newVariants) => {
|
|
890
|
+
if (!applyVariantUpdates) return;
|
|
773
891
|
if (!hasAnyDisabled) {
|
|
774
892
|
for (const key in newVariants) {
|
|
775
893
|
if (!Object.hasOwn(newVariants, key)) continue;
|
|
776
894
|
const value = newVariants[key];
|
|
777
895
|
setChangedVariant(key, value, true);
|
|
778
|
-
if (getCurrentVariantValue(key)
|
|
896
|
+
if (Object.is(getCurrentVariantValue(key), value)) continue;
|
|
779
897
|
ensureUpdated()[key] = value;
|
|
780
898
|
}
|
|
781
899
|
return;
|
|
@@ -789,24 +907,7 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
789
907
|
if (valueKey != null && disabledVariantValues[key]?.has(valueKey)) continue;
|
|
790
908
|
}
|
|
791
909
|
setChangedVariant(key, value, true);
|
|
792
|
-
if (getCurrentVariantValue(key)
|
|
793
|
-
ensureUpdated()[key] = value;
|
|
794
|
-
}
|
|
795
|
-
},
|
|
796
|
-
setDefaultVariants: (newDefaults) => {
|
|
797
|
-
for (const key in newDefaults) {
|
|
798
|
-
if (!Object.hasOwn(newDefaults, key)) continue;
|
|
799
|
-
if (userVariantProps[key] !== void 0) continue;
|
|
800
|
-
if (protectedVariantKeys?.has(key)) continue;
|
|
801
|
-
const value = newDefaults[key];
|
|
802
|
-
if (hasAnyDisabled) {
|
|
803
|
-
if (disabledVariantKeys.has(key)) continue;
|
|
804
|
-
const valueKey = getVariantValueKey(value);
|
|
805
|
-
if (valueKey != null && disabledVariantValues[key]?.has(valueKey)) continue;
|
|
806
|
-
}
|
|
807
|
-
setChangedVariant(key, value);
|
|
808
|
-
if (pendingProtectedVariants) pendingProtectedVariants[key] = value;
|
|
809
|
-
if (getCurrentVariantValue(key) === value) continue;
|
|
910
|
+
if (Object.is(getCurrentVariantValue(key), value)) continue;
|
|
810
911
|
ensureUpdated()[key] = value;
|
|
811
912
|
}
|
|
812
913
|
},
|
|
@@ -847,18 +948,11 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
847
948
|
style: cStyle
|
|
848
949
|
};
|
|
849
950
|
};
|
|
850
|
-
const computeOnce = (resolved, userVariantProps, skipKeys, skipValues, classesOut, styleOut, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys) => {
|
|
951
|
+
const computeOnce = (resolved, userVariantProps, skipKeys, skipValues, classesOut, styleOut, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys, defaultResolved = resolved, renderOnly = false) => {
|
|
851
952
|
let workingResolved = resolved;
|
|
852
953
|
let cClasses = null;
|
|
853
954
|
let cStyle = null;
|
|
854
955
|
let changedVariants = null;
|
|
855
|
-
if (refine) {
|
|
856
|
-
const refineResult = runRefineContext(resolved, userVariantProps, true, true, protectedVariants, pendingProtectedVariants, protectedVariantKeys);
|
|
857
|
-
workingResolved = refineResult.workingResolved;
|
|
858
|
-
cClasses = refineResult.classes;
|
|
859
|
-
cStyle = refineResult.style;
|
|
860
|
-
changedVariants = refineResult.changedVariants;
|
|
861
|
-
}
|
|
862
956
|
if (hasExtend) {
|
|
863
957
|
let extSkipKeys;
|
|
864
958
|
if (skipKeys === null) extSkipKeys = staticExtSkipKeys;
|
|
@@ -886,15 +980,31 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
886
980
|
for (let i = 0; i < extCount; i++) {
|
|
887
981
|
if (hasIsolatedExt && extIsolated[i]) {
|
|
888
982
|
const extClasses = [];
|
|
889
|
-
workingResolved = extMetas[i].compute(workingResolved, extUserVariantProps, extSkipKeys, extSkipVals, extClasses, styleOut, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys);
|
|
983
|
+
workingResolved = extMetas[i].compute(workingResolved, extUserVariantProps, extSkipKeys, extSkipVals, extClasses, styleOut, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys, defaultResolved, renderOnly);
|
|
890
984
|
if (extClasses.length > 0) {
|
|
891
985
|
const joined = clsx(extClasses);
|
|
892
986
|
if (joined.length > 0) classesOut.push(extMetas[i].transformClass(joined));
|
|
893
987
|
}
|
|
894
|
-
} else workingResolved = extMetas[i].compute(workingResolved, extUserVariantProps, extSkipKeys, extSkipVals, classesOut, styleOut, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys);
|
|
988
|
+
} else workingResolved = extMetas[i].compute(workingResolved, extUserVariantProps, extSkipKeys, extSkipVals, classesOut, styleOut, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys, defaultResolved, renderOnly);
|
|
989
|
+
workingResolved = filterOwnDisabledVariants(workingResolved, defaultResolved);
|
|
895
990
|
if (protectedVariants && extMetasWithRefineCount > 0) Object.assign(extUserVariantProps, protectedVariants);
|
|
896
991
|
}
|
|
897
992
|
}
|
|
993
|
+
if (!renderOnly && computedDefaultCount > 0) {
|
|
994
|
+
const computedResult = runComputedDefaults(workingResolved, defaultResolved, userVariantProps, true, protectedVariantKeys);
|
|
995
|
+
workingResolved = computedResult.workingResolved;
|
|
996
|
+
changedVariants = computedResult.changedVariants;
|
|
997
|
+
}
|
|
998
|
+
if (refine) {
|
|
999
|
+
const refineResult = runRefineContext(workingResolved, userVariantProps, true, true, !renderOnly, protectedVariants, pendingProtectedVariants, protectedVariantKeys);
|
|
1000
|
+
workingResolved = refineResult.workingResolved;
|
|
1001
|
+
cClasses = refineResult.classes;
|
|
1002
|
+
cStyle = refineResult.style;
|
|
1003
|
+
if (refineResult.changedVariants) {
|
|
1004
|
+
changedVariants ??= {};
|
|
1005
|
+
Object.assign(changedVariants, refineResult.changedVariants);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
898
1008
|
if (hasBaseStyle) Object.assign(styleOut, baseStyle);
|
|
899
1009
|
const ownSkipKeys = skipKeys;
|
|
900
1010
|
const ownSkipValues = skipValues;
|
|
@@ -937,12 +1047,13 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
937
1047
|
if (cStyle) Object.assign(styleOut, cStyle);
|
|
938
1048
|
return workingResolved;
|
|
939
1049
|
};
|
|
940
|
-
const compute = !refine && extMetasWithRefineCount === 0 ? computeOnce : (resolved, userVariantProps, skipKeys, skipValues, classesOut, styleOut, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys) => {
|
|
1050
|
+
const compute = !refine && computedDefaultCount === 0 && extMetasWithRefineCount === 0 ? computeOnce : (resolved, userVariantProps, skipKeys, skipValues, classesOut, styleOut, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys, incomingDefaultResolved = resolved, renderOnly = false) => {
|
|
1051
|
+
if (renderOnly) return computeOnce(resolved, userVariantProps, skipKeys, skipValues, classesOut, styleOut, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys, incomingDefaultResolved, true);
|
|
941
1052
|
runState ??= { remaining: MAX_REFINE_RUNS };
|
|
942
1053
|
protectedVariants ??= {};
|
|
943
1054
|
protectedVariantKeys ??= /* @__PURE__ */ new Set();
|
|
944
1055
|
let workingResolved = resolved;
|
|
945
|
-
let
|
|
1056
|
+
let unstableChanges = null;
|
|
946
1057
|
let lastClasses = [];
|
|
947
1058
|
let lastStyle = {};
|
|
948
1059
|
let isFirstRun = true;
|
|
@@ -959,23 +1070,34 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
959
1070
|
const nextPendingProtectedVariants = {};
|
|
960
1071
|
const nextClasses = useDirectOutput ? classesOut : [];
|
|
961
1072
|
const nextStyle = useDirectOutput ? styleOut : {};
|
|
962
|
-
const
|
|
1073
|
+
const defaultResolved = mergeProtectedIntoBase(incomingDefaultResolved, protectedVariants);
|
|
1074
|
+
const nextResolved = computeOnce(workingResolved, userVariantProps, skipKeys, skipValues, nextClasses, nextStyle, runState, protectedVariants, nextPendingProtectedVariants, protectedVariantKeys, defaultResolved);
|
|
963
1075
|
let protectedChanged;
|
|
964
1076
|
if (pendingProtectedVariants) protectedChanged = mergeVariants(pendingProtectedVariants, nextPendingProtectedVariants, protectedVariantKeys);
|
|
965
1077
|
else protectedChanged = mergeVariants(protectedVariants, nextPendingProtectedVariants, protectedVariantKeys);
|
|
966
1078
|
if (!protectedChanged && (nextResolved === workingResolved || areVariantsEqual(workingResolved, nextResolved))) {
|
|
967
|
-
if (
|
|
1079
|
+
if (nextResolved !== workingResolved) {
|
|
1080
|
+
if (useDirectOutput) {
|
|
1081
|
+
classesOut.length = classCount;
|
|
1082
|
+
for (const key in styleOut) if (Object.hasOwn(styleOut, key)) Reflect.deleteProperty(styleOut, key);
|
|
1083
|
+
}
|
|
1084
|
+
computeOnce(nextResolved, userVariantProps, skipKeys, skipValues, classesOut, styleOut, runState, protectedVariants, null, protectedVariantKeys, defaultResolved, true);
|
|
1085
|
+
} else if (!useDirectOutput) {
|
|
968
1086
|
for (let i = 0; i < nextClasses.length; i++) classesOut.push(nextClasses[i]);
|
|
969
1087
|
Object.assign(styleOut, nextStyle);
|
|
970
1088
|
}
|
|
971
1089
|
return nextResolved;
|
|
972
1090
|
}
|
|
973
|
-
if (process.env.NODE_ENV !== "production" && runState.remaining <
|
|
974
|
-
if (!
|
|
975
|
-
|
|
1091
|
+
if (process.env.NODE_ENV !== "production" && runState.remaining < 10) {
|
|
1092
|
+
if (!unstableChanges) unstableChanges = /* @__PURE__ */ new Map();
|
|
1093
|
+
accumulateUnstableVariantChanges(unstableChanges, workingResolved, nextResolved);
|
|
976
1094
|
}
|
|
977
1095
|
if (useDirectOutput && runState.remaining === 0) {
|
|
978
|
-
warnRefineLimit(
|
|
1096
|
+
warnRefineLimit({
|
|
1097
|
+
runState,
|
|
1098
|
+
creationFrame,
|
|
1099
|
+
unstableChanges
|
|
1100
|
+
});
|
|
979
1101
|
return nextResolved;
|
|
980
1102
|
}
|
|
981
1103
|
if (useDirectOutput) {
|
|
@@ -988,41 +1110,55 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
988
1110
|
workingResolved = nextResolved;
|
|
989
1111
|
isFirstRun = false;
|
|
990
1112
|
}
|
|
991
|
-
warnRefineLimit(
|
|
1113
|
+
warnRefineLimit({
|
|
1114
|
+
runState,
|
|
1115
|
+
creationFrame,
|
|
1116
|
+
unstableChanges
|
|
1117
|
+
});
|
|
992
1118
|
for (let i = 0; i < lastClasses.length; i++) classesOut.push(lastClasses[i]);
|
|
993
1119
|
Object.assign(styleOut, lastStyle);
|
|
994
1120
|
return workingResolved;
|
|
995
1121
|
};
|
|
996
|
-
const resolveRefineOnce = (resolved, userVariantProps, filterOwnVariants = true, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys) => {
|
|
1122
|
+
const resolveRefineOnce = (resolved, userVariantProps, filterOwnVariants = true, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys, defaultResolved = resolved) => {
|
|
997
1123
|
let workingResolved = resolved;
|
|
998
1124
|
let changedVariants = null;
|
|
999
|
-
if (refine) {
|
|
1000
|
-
const refineResult = runRefineContext(resolved, userVariantProps, filterOwnVariants, false, protectedVariants, pendingProtectedVariants, protectedVariantKeys);
|
|
1001
|
-
workingResolved = refineResult.workingResolved;
|
|
1002
|
-
changedVariants = refineResult.changedVariants;
|
|
1003
|
-
}
|
|
1004
1125
|
if (extMetasWithRefineCount > 0) {
|
|
1005
1126
|
const extUserVariantProps = getExtUserVariantProps(userVariantProps, protectedVariants ?? null, changedVariants);
|
|
1006
1127
|
for (let i = 0; i < extMetasWithRefineCount; i++) {
|
|
1007
1128
|
const resolveRefine = extMetasWithRefine[i].resolveRefine;
|
|
1008
1129
|
if (!resolveRefine) continue;
|
|
1009
|
-
workingResolved = resolveRefine(workingResolved, extUserVariantProps, true, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys);
|
|
1130
|
+
workingResolved = resolveRefine(workingResolved, extUserVariantProps, true, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys, defaultResolved);
|
|
1131
|
+
workingResolved = filterOwnDisabledVariants(workingResolved, defaultResolved);
|
|
1010
1132
|
if (protectedVariants) Object.assign(extUserVariantProps, protectedVariants);
|
|
1011
1133
|
}
|
|
1012
1134
|
}
|
|
1135
|
+
if (computedDefaultCount > 0) {
|
|
1136
|
+
const computedResult = runComputedDefaults(workingResolved, defaultResolved, userVariantProps, filterOwnVariants, protectedVariantKeys);
|
|
1137
|
+
workingResolved = computedResult.workingResolved;
|
|
1138
|
+
changedVariants = computedResult.changedVariants;
|
|
1139
|
+
}
|
|
1140
|
+
if (refine) {
|
|
1141
|
+
const refineResult = runRefineContext(workingResolved, userVariantProps, filterOwnVariants, false, true, protectedVariants, pendingProtectedVariants, protectedVariantKeys);
|
|
1142
|
+
workingResolved = refineResult.workingResolved;
|
|
1143
|
+
if (refineResult.changedVariants) {
|
|
1144
|
+
changedVariants ??= {};
|
|
1145
|
+
Object.assign(changedVariants, refineResult.changedVariants);
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1013
1148
|
return workingResolved;
|
|
1014
1149
|
};
|
|
1015
|
-
const resolveRefine = refine || extMetasWithRefineCount > 0 ? (resolved, userVariantProps, filterOwnVariants = true, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys) => {
|
|
1150
|
+
const resolveRefine = refine || computedDefaultCount > 0 || extMetasWithRefineCount > 0 ? (resolved, userVariantProps, filterOwnVariants = true, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys, incomingDefaultResolved = resolved) => {
|
|
1016
1151
|
runState ??= { remaining: MAX_REFINE_RUNS };
|
|
1017
1152
|
protectedVariants ??= {};
|
|
1018
1153
|
protectedVariantKeys ??= /* @__PURE__ */ new Set();
|
|
1019
1154
|
let workingResolved = resolved;
|
|
1020
|
-
let
|
|
1155
|
+
let unstableChanges = null;
|
|
1021
1156
|
let reachedLimit = true;
|
|
1022
1157
|
while (runState.remaining > 0) {
|
|
1023
1158
|
runState.remaining -= 1;
|
|
1024
1159
|
const nextPendingProtectedVariants = {};
|
|
1025
|
-
const
|
|
1160
|
+
const defaultResolved = mergeProtectedIntoBase(incomingDefaultResolved, protectedVariants);
|
|
1161
|
+
const nextResolved = resolveRefineOnce(workingResolved, userVariantProps, filterOwnVariants, runState, protectedVariants, nextPendingProtectedVariants, protectedVariantKeys, defaultResolved);
|
|
1026
1162
|
let protectedChanged;
|
|
1027
1163
|
if (pendingProtectedVariants) protectedChanged = mergeVariants(pendingProtectedVariants, nextPendingProtectedVariants, protectedVariantKeys);
|
|
1028
1164
|
else protectedChanged = mergeVariants(protectedVariants, nextPendingProtectedVariants, protectedVariantKeys);
|
|
@@ -1031,13 +1167,17 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
1031
1167
|
reachedLimit = false;
|
|
1032
1168
|
break;
|
|
1033
1169
|
}
|
|
1034
|
-
if (process.env.NODE_ENV !== "production" && runState.remaining <
|
|
1035
|
-
if (!
|
|
1036
|
-
|
|
1170
|
+
if (process.env.NODE_ENV !== "production" && runState.remaining < 10) {
|
|
1171
|
+
if (!unstableChanges) unstableChanges = /* @__PURE__ */ new Map();
|
|
1172
|
+
accumulateUnstableVariantChanges(unstableChanges, workingResolved, nextResolved);
|
|
1037
1173
|
}
|
|
1038
1174
|
workingResolved = nextResolved;
|
|
1039
1175
|
}
|
|
1040
|
-
if (reachedLimit) warnRefineLimit(
|
|
1176
|
+
if (reachedLimit) warnRefineLimit({
|
|
1177
|
+
runState,
|
|
1178
|
+
creationFrame,
|
|
1179
|
+
unstableChanges
|
|
1180
|
+
});
|
|
1041
1181
|
return workingResolved;
|
|
1042
1182
|
} : null;
|
|
1043
1183
|
const computeResult = (props = EMPTY_DEFAULTS) => {
|
|
@@ -1045,19 +1185,12 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
1045
1185
|
let resolved = {};
|
|
1046
1186
|
Object.assign(resolved, staticDefaults);
|
|
1047
1187
|
let userVariantProps;
|
|
1048
|
-
if (extMetasWithRefineCount > 0) {
|
|
1188
|
+
if (refine || computedDefaultCount > 0 || extMetasWithRefineCount > 0) {
|
|
1049
1189
|
const variantProps = {};
|
|
1050
1190
|
for (let i = 0; i < variantKeysLength; i++) {
|
|
1051
1191
|
const key = variantKeys[i];
|
|
1052
1192
|
if (Object.hasOwn(propsRecord, key)) variantProps[key] = propsRecord[key];
|
|
1053
1193
|
}
|
|
1054
|
-
for (let i = 0; i < extMetasWithRefineCount; i++) {
|
|
1055
|
-
const extDefaults = extMetasWithRefine[i].resolveDefaults(resolved, variantProps);
|
|
1056
|
-
for (const k in extDefaults) {
|
|
1057
|
-
if (!Object.hasOwn(extDefaults, k)) continue;
|
|
1058
|
-
resolved[k] = extDefaults[k];
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
1194
|
for (const k in variantProps) {
|
|
1062
1195
|
if (!Object.hasOwn(variantProps, k)) continue;
|
|
1063
1196
|
const v = variantProps[k];
|
|
@@ -1116,11 +1249,11 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
1116
1249
|
const meta = {
|
|
1117
1250
|
baseClass: computedBaseClass,
|
|
1118
1251
|
staticDefaults,
|
|
1119
|
-
resolveDefaults: resolveDefaultsFn,
|
|
1120
1252
|
compute,
|
|
1121
1253
|
resolveRefine,
|
|
1122
1254
|
transformClass,
|
|
1123
|
-
functionVariantKeys
|
|
1255
|
+
functionVariantKeys,
|
|
1256
|
+
computedDefaultKeys
|
|
1124
1257
|
};
|
|
1125
1258
|
const initComponent = (c, propKeys, style) => {
|
|
1126
1259
|
c.class = classFn;
|
|
@@ -1187,7 +1320,6 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
1187
1320
|
cx
|
|
1188
1321
|
};
|
|
1189
1322
|
}
|
|
1190
|
-
function noop() {}
|
|
1191
1323
|
const { cv, cx } = create();
|
|
1192
1324
|
//#endregion
|
|
1193
1325
|
export { create, cv, cx, splitProps };
|