clava 0.4.2 → 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 +41 -0
- package/README.md +26 -15
- package/dist/index.d.ts +10 -3
- package/dist/index.js +190 -115
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +376 -214
- package/src/refine-warning.ts +2 -2
- package/src/types.ts +24 -2
- 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.test.ts +152 -210
- package/tests/variants-inference.test.ts +81 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# clava
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Computed default variants
|
|
6
|
+
|
|
7
|
+
**BREAKING** if you're using `setDefaultVariants` in [`cv`](https://clava.style/docs/reference/cv) `refine` callbacks.
|
|
8
|
+
|
|
9
|
+
The `setDefaultVariants` function has been removed from `refine`. Define dependent defaults directly in `defaultVariants` by passing a function for the variant key. The function receives the current `defaultValue` for that key and the resolved `variants` snapshot.
|
|
10
|
+
|
|
11
|
+
Computed default variants run before `refine`, so `refine` callbacks now read computed default values during their first pass. If a variant value itself is a function, return that function from a computed default variant instead of passing it directly as a static default.
|
|
12
|
+
|
|
13
|
+
Before:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
const button = cv({
|
|
17
|
+
variants: {
|
|
18
|
+
size: { sm: "sm", lg: "lg" },
|
|
19
|
+
intent: { neutral: "neutral", brand: "brand" },
|
|
20
|
+
},
|
|
21
|
+
refine: ({ variants, setDefaultVariants }) => {
|
|
22
|
+
if (variants.size === "lg") {
|
|
23
|
+
setDefaultVariants({ intent: "neutral" });
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
After:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
const button = cv({
|
|
33
|
+
variants: {
|
|
34
|
+
size: { sm: "sm", lg: "lg" },
|
|
35
|
+
intent: { neutral: "neutral", brand: "brand" },
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: {
|
|
38
|
+
intent: ({ defaultValue, variants }) =>
|
|
39
|
+
variants.size === "lg" ? "neutral" : defaultValue,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
3
44
|
## 0.4.2
|
|
4
45
|
|
|
5
46
|
- Improved [`refine`](https://clava.style/docs/reference/refine) iteration warnings to show the latest changing variant values with a shorter component creation stack.
|
package/README.md
CHANGED
|
@@ -316,7 +316,9 @@ You can extend any component mode, including `baseButton.jsx`, `baseButton.html`
|
|
|
316
316
|
|
|
317
317
|
## Refine
|
|
318
318
|
|
|
319
|
-
Use `
|
|
319
|
+
Use computed `defaultVariants` for dependent defaults. A function entry receives the current default value for that key plus the resolved variants snapshot, and returns the next default value.
|
|
320
|
+
|
|
321
|
+
Use `refine` for final variant overrides and class/style adjustments. It receives the resolved variant values for the component and can return class/style output.
|
|
320
322
|
|
|
321
323
|
```ts
|
|
322
324
|
const toolbarButton = cv({
|
|
@@ -328,21 +330,15 @@ const toolbarButton = cv({
|
|
|
328
330
|
},
|
|
329
331
|
loading: "toolbar-button-loading",
|
|
330
332
|
},
|
|
331
|
-
|
|
332
|
-
variants
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
addStyle,
|
|
337
|
-
}) => {
|
|
333
|
+
defaultVariants: {
|
|
334
|
+
intent: ({ defaultValue, variants }) =>
|
|
335
|
+
variants.size === "lg" ? "neutral" : defaultValue,
|
|
336
|
+
},
|
|
337
|
+
refine: ({ variants, setVariants, addClass, addStyle }) => {
|
|
338
338
|
if (variants.loading) {
|
|
339
339
|
setVariants({ pressed: false });
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
-
if (variants.size === "lg") {
|
|
343
|
-
setDefaultVariants({ intent: "neutral" });
|
|
344
|
-
}
|
|
345
|
-
|
|
346
342
|
if (variants.pressed && variants.intent === "brand") {
|
|
347
343
|
addClass("toolbar-button-brand-pressed");
|
|
348
344
|
addStyle({ transform: "translateY(1px)" });
|
|
@@ -353,9 +349,24 @@ const toolbarButton = cv({
|
|
|
353
349
|
});
|
|
354
350
|
```
|
|
355
351
|
|
|
356
|
-
|
|
352
|
+
Computed `defaultVariants` do not override a prop the user explicitly passed unless that prop value is `undefined`. Return `defaultValue` to preserve the inherited or static default value. Return `undefined` to clear the default value. If a variant's value is a function, return that function from a computed default:
|
|
353
|
+
|
|
354
|
+
```ts
|
|
355
|
+
const transform = (value: string) => value.toUpperCase();
|
|
356
|
+
|
|
357
|
+
const input = cv({
|
|
358
|
+
variants: {
|
|
359
|
+
transform: (fn: (value: string) => string) => fn("example"),
|
|
360
|
+
},
|
|
361
|
+
defaultVariants: {
|
|
362
|
+
transform: () => transform,
|
|
363
|
+
},
|
|
364
|
+
});
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
`setVariants()` overrides explicit props. `addClass()` and `addStyle()` append output without changing resolved variant values. `getVariants()` includes values changed by computed `defaultVariants` and `setVariants()`.
|
|
357
368
|
|
|
358
|
-
When a `refine` callback changes variants, Clava re-runs the refine chain so later reads see the latest values. Re-runs are capped at 50 iterations, after which Clava stops and logs a warning in development.
|
|
369
|
+
When a computed default or `refine` callback changes variants, Clava re-runs the refine chain so later reads see the latest values. Re-runs are capped at 50 iterations, after which Clava stops and logs a warning in development.
|
|
359
370
|
|
|
360
371
|
## Splitting Props
|
|
361
372
|
|
|
@@ -539,7 +550,7 @@ The package also exports `ClassValue`, `StyleValue`, `StyleClassProps`, `StyleCl
|
|
|
539
550
|
|
|
540
551
|
`component.style(props?)` returns only the resolved style value for that component mode.
|
|
541
552
|
|
|
542
|
-
`component.getVariants(props?)` returns resolved variant values after static defaults, inherited defaults, and `refine` updates.
|
|
553
|
+
`component.getVariants(props?)` returns resolved variant values after static defaults, inherited defaults, computed defaults, and `refine` updates.
|
|
543
554
|
|
|
544
555
|
`component.propKeys` lists style props plus variant props for that component mode.
|
|
545
556
|
|
package/dist/index.d.ts
CHANGED
|
@@ -76,7 +76,15 @@ type StringToBoolean<T> = T extends "true" | "false" ? boolean : T;
|
|
|
76
76
|
type VariantValue = ClassValue | StyleClassValue;
|
|
77
77
|
type NonNullKeys<T> = { [K in keyof T]: T[K] extends null ? never : K }[keyof T];
|
|
78
78
|
type ExtractVariantValue<T> = T extends null ? never : T extends ((value: infer V) => any) ? V : T extends readonly unknown[] ? boolean : T extends Record<string, any> ? StringToBoolean<NonNullKeys<T>> : T extends ClassValue ? boolean : never;
|
|
79
|
-
type VariantValues<V> = { [K in keyof V]?: ExtractVariantValue<V[K]> };
|
|
79
|
+
type VariantValues<V> = { [K in keyof V]?: ExtractVariantValue<V[K]> | undefined };
|
|
80
|
+
interface DefaultVariantContext<V, K extends keyof V> {
|
|
81
|
+
defaultValue: ExtractVariantValue<V[K]> | undefined;
|
|
82
|
+
variants: Readonly<VariantValues<V>>;
|
|
83
|
+
}
|
|
84
|
+
type ComputedDefaultVariant<V, K extends keyof V> = (context: DefaultVariantContext<V, K>) => ExtractVariantValue<V[K]> | undefined;
|
|
85
|
+
type NonFunctionVariantValue<T> = Exclude<T, (...args: any[]) => any>;
|
|
86
|
+
type DefaultVariantValue<V, K extends keyof V> = [NonFunctionVariantValue<ExtractVariantValue<V[K]>>] extends [never] ? ComputedDefaultVariant<V, K> : NonFunctionVariantValue<ExtractVariantValue<V[K]>> | ComputedDefaultVariant<V, K>;
|
|
87
|
+
type DefaultVariants<V> = { [K in keyof V]?: DefaultVariantValue<V, K> | undefined };
|
|
80
88
|
type StyleValue = CSS.Properties & {
|
|
81
89
|
[key: `--${string}`]: string;
|
|
82
90
|
};
|
|
@@ -87,7 +95,6 @@ interface StyleClassValue {
|
|
|
87
95
|
interface RefineContext<V> {
|
|
88
96
|
variants: VariantValues<V>;
|
|
89
97
|
setVariants: (variants: VariantValues<V>) => void;
|
|
90
|
-
setDefaultVariants: (variants: VariantValues<V>) => void;
|
|
91
98
|
addClass: (className: ClassValue) => void;
|
|
92
99
|
addStyle: (style: StyleValue) => void;
|
|
93
100
|
}
|
|
@@ -106,7 +113,7 @@ interface CVConfig<V extends Variants = {}, E extends AnyComponent[] = []> {
|
|
|
106
113
|
class?: ClassValue;
|
|
107
114
|
style?: StyleValue;
|
|
108
115
|
variants?: ExtendableVariants<V, E>;
|
|
109
|
-
defaultVariants?:
|
|
116
|
+
defaultVariants?: DefaultVariants<MergeVariants<V, E>>;
|
|
110
117
|
refine?: Refine<MergeVariants<V, E>>;
|
|
111
118
|
}
|
|
112
119
|
interface CreateParams {
|
package/dist/index.js
CHANGED
|
@@ -75,7 +75,7 @@ function warnRefineLimit({ runState, creationFrame, unstableChanges }) {
|
|
|
75
75
|
if (process.env.NODE_ENV === "production") return;
|
|
76
76
|
if (runState.warned) return;
|
|
77
77
|
runState.warned = true;
|
|
78
|
-
let message = "Clava: Maximum refine iterations exceeded. This can happen when a
|
|
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
79
|
if (unstableChanges && unstableChanges.size > 0) {
|
|
80
80
|
message += `\nVariant(s) that did not stabilize: ${Array.from(unstableChanges.keys()).join(", ")}.`;
|
|
81
81
|
message += `\nLatest variant changes before warning: ${formatVariantChanges(unstableChanges)}.`;
|
|
@@ -350,6 +350,23 @@ function mergeVariants(target, source, skipKeys) {
|
|
|
350
350
|
}
|
|
351
351
|
return changed;
|
|
352
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
|
+
}
|
|
353
370
|
function getComponentMeta(component) {
|
|
354
371
|
return component[META_KEY];
|
|
355
372
|
}
|
|
@@ -419,21 +436,11 @@ function collectVariantKeys(config) {
|
|
|
419
436
|
}
|
|
420
437
|
return Array.from(keys);
|
|
421
438
|
}
|
|
422
|
-
function isVariantDisabled(config, key) {
|
|
423
|
-
return config.variants?.[key] === null;
|
|
424
|
-
}
|
|
425
439
|
function getVariantValueKey(value) {
|
|
426
440
|
if (typeof value === "string") return value;
|
|
427
441
|
if (typeof value === "number") return String(value);
|
|
428
442
|
if (typeof value === "boolean") return String(value);
|
|
429
443
|
}
|
|
430
|
-
function isVariantValueDisabled(config, key, value) {
|
|
431
|
-
const valueKey = getVariantValueKey(value);
|
|
432
|
-
if (valueKey == null) return false;
|
|
433
|
-
const variant = config.variants?.[key];
|
|
434
|
-
if (!isRecordObject(variant)) return false;
|
|
435
|
-
return variant[valueKey] === null;
|
|
436
|
-
}
|
|
437
444
|
function collectDisabledVariantKeys(config) {
|
|
438
445
|
const keys = /* @__PURE__ */ new Set();
|
|
439
446
|
if (!config.variants) return keys;
|
|
@@ -614,6 +621,9 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
614
621
|
}
|
|
615
622
|
const variantEntryCount = variantEntryNames.length;
|
|
616
623
|
const functionVariantCount = functionVariantNames.length;
|
|
624
|
+
const computedDefaultNames = [];
|
|
625
|
+
const computedDefaultFns = [];
|
|
626
|
+
const defaultVariants = config.defaultVariants;
|
|
617
627
|
const staticDefaults = {};
|
|
618
628
|
if (extend) for (const ext of extend) {
|
|
619
629
|
const meta = getComponentMeta(ext);
|
|
@@ -625,7 +635,21 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
625
635
|
if (!isRecordObject(variantDef)) continue;
|
|
626
636
|
if (Object.hasOwn(variantDef, "false") && staticDefaults[name] === void 0) staticDefaults[name] = false;
|
|
627
637
|
}
|
|
628
|
-
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;
|
|
629
653
|
if (hasAnyDisabled) for (const key in staticDefaults) {
|
|
630
654
|
if (!Object.hasOwn(staticDefaults, key)) continue;
|
|
631
655
|
if (disabledVariantKeys.has(key)) {
|
|
@@ -654,14 +678,19 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
654
678
|
} else extBaseClassesArr.push(meta.baseClass);
|
|
655
679
|
}
|
|
656
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
|
+
}
|
|
657
686
|
const extMetasWithRefine = [];
|
|
658
687
|
for (let i = 0; i < extCount; i++) {
|
|
659
688
|
const meta = extMetas[i];
|
|
660
|
-
if (meta.
|
|
689
|
+
if (meta.resolveRefine) extMetasWithRefine.push(meta);
|
|
661
690
|
}
|
|
662
691
|
const extMetasWithRefineCount = extMetasWithRefine.length;
|
|
663
692
|
const shouldCollectChangedVariants = extMetasWithRefineCount > 0;
|
|
664
|
-
const creationFrame = !!refine || extMetasWithRefineCount > 0 ? captureCreationFrame(cv) : void 0;
|
|
693
|
+
const creationFrame = !!refine || computedDefaultCount > 0 || extMetasWithRefineCount > 0 ? captureCreationFrame(cv) : void 0;
|
|
665
694
|
const functionVariantKeys = /* @__PURE__ */ new Set();
|
|
666
695
|
for (let i = 0; i < extCount; i++) {
|
|
667
696
|
const fnKeys = extMetas[i].functionVariantKeys;
|
|
@@ -672,6 +701,8 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
672
701
|
}
|
|
673
702
|
for (let i = 0; i < functionVariantCount; i++) functionVariantKeys.add(functionVariantNames[i]);
|
|
674
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]);
|
|
675
706
|
let staticVariantsOverridingExtFn = null;
|
|
676
707
|
if (variantEntryCount > 0 && extCount > 0) for (let i = 0; i < variantEntryCount; i++) {
|
|
677
708
|
const name = variantEntryNames[i];
|
|
@@ -705,64 +736,42 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
705
736
|
out[key] = value;
|
|
706
737
|
}
|
|
707
738
|
}
|
|
708
|
-
const
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
if (
|
|
713
|
-
const v = childDefaults[key];
|
|
714
|
-
if (v === void 0) continue;
|
|
715
|
-
resolvedVariants[key] = v;
|
|
716
|
-
}
|
|
717
|
-
for (const key in userProps) {
|
|
718
|
-
if (!Object.hasOwn(userProps, key)) continue;
|
|
719
|
-
const v = userProps[key];
|
|
720
|
-
if (v === void 0) continue;
|
|
721
|
-
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;
|
|
722
744
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
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;
|
|
729
756
|
}
|
|
730
757
|
}
|
|
731
|
-
if (
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
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;
|
|
736
766
|
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
setVariants: noop,
|
|
740
|
-
setDefaultVariants: (newDefaults) => {
|
|
741
|
-
for (const key in newDefaults) {
|
|
742
|
-
if (!Object.hasOwn(newDefaults, key)) continue;
|
|
743
|
-
const value = newDefaults[key];
|
|
744
|
-
if (userProps[key] !== void 0) continue;
|
|
745
|
-
if (isVariantDisabled(config, key)) continue;
|
|
746
|
-
if (isVariantValueDisabled(config, key, value)) continue;
|
|
747
|
-
refineDefaults[key] = value;
|
|
748
|
-
}
|
|
749
|
-
},
|
|
750
|
-
addClass: noop,
|
|
751
|
-
addStyle: noop
|
|
752
|
-
});
|
|
767
|
+
const fallbackValue = fallback[key];
|
|
768
|
+
if (fallbackValue !== void 0 && !isOwnDisabledValue(key, fallbackValue)) filtered[key] = fallbackValue;
|
|
753
769
|
}
|
|
754
|
-
return
|
|
755
|
-
}
|
|
770
|
+
return filtered;
|
|
771
|
+
};
|
|
756
772
|
function resolveVariantsHot(propsVariants) {
|
|
757
773
|
const defaults = {};
|
|
758
774
|
Object.assign(defaults, staticDefaults);
|
|
759
|
-
for (let i = 0; i < extMetasWithRefineCount; i++) {
|
|
760
|
-
const extDefaults = extMetasWithRefine[i].resolveDefaults(defaults, propsVariants);
|
|
761
|
-
for (const k in extDefaults) {
|
|
762
|
-
if (!Object.hasOwn(extDefaults, k)) continue;
|
|
763
|
-
defaults[k] = extDefaults[k];
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
775
|
for (const k in propsVariants) {
|
|
767
776
|
if (!Object.hasOwn(propsVariants, k)) continue;
|
|
768
777
|
const v = propsVariants[k];
|
|
@@ -774,7 +783,70 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
774
783
|
filterDisabledInto(defaults, result);
|
|
775
784
|
return result;
|
|
776
785
|
}
|
|
777
|
-
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) => {
|
|
778
850
|
let workingResolved = resolved;
|
|
779
851
|
let cClasses = null;
|
|
780
852
|
let cStyle = null;
|
|
@@ -815,6 +887,7 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
815
887
|
const result = refine({
|
|
816
888
|
variants: ownVariants,
|
|
817
889
|
setVariants: (newVariants) => {
|
|
890
|
+
if (!applyVariantUpdates) return;
|
|
818
891
|
if (!hasAnyDisabled) {
|
|
819
892
|
for (const key in newVariants) {
|
|
820
893
|
if (!Object.hasOwn(newVariants, key)) continue;
|
|
@@ -838,23 +911,6 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
838
911
|
ensureUpdated()[key] = value;
|
|
839
912
|
}
|
|
840
913
|
},
|
|
841
|
-
setDefaultVariants: (newDefaults) => {
|
|
842
|
-
for (const key in newDefaults) {
|
|
843
|
-
if (!Object.hasOwn(newDefaults, key)) continue;
|
|
844
|
-
if (userVariantProps[key] !== void 0) continue;
|
|
845
|
-
if (protectedVariantKeys?.has(key)) continue;
|
|
846
|
-
const value = newDefaults[key];
|
|
847
|
-
if (hasAnyDisabled) {
|
|
848
|
-
if (disabledVariantKeys.has(key)) continue;
|
|
849
|
-
const valueKey = getVariantValueKey(value);
|
|
850
|
-
if (valueKey != null && disabledVariantValues[key]?.has(valueKey)) continue;
|
|
851
|
-
}
|
|
852
|
-
if (Object.is(getCurrentVariantValue(key), value)) continue;
|
|
853
|
-
setChangedVariant(key, value);
|
|
854
|
-
if (pendingProtectedVariants) pendingProtectedVariants[key] = value;
|
|
855
|
-
ensureUpdated()[key] = value;
|
|
856
|
-
}
|
|
857
|
-
},
|
|
858
914
|
addClass: (className) => {
|
|
859
915
|
localCClasses?.push(className);
|
|
860
916
|
},
|
|
@@ -892,18 +948,11 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
892
948
|
style: cStyle
|
|
893
949
|
};
|
|
894
950
|
};
|
|
895
|
-
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) => {
|
|
896
952
|
let workingResolved = resolved;
|
|
897
953
|
let cClasses = null;
|
|
898
954
|
let cStyle = null;
|
|
899
955
|
let changedVariants = null;
|
|
900
|
-
if (refine) {
|
|
901
|
-
const refineResult = runRefineContext(resolved, userVariantProps, true, true, protectedVariants, pendingProtectedVariants, protectedVariantKeys);
|
|
902
|
-
workingResolved = refineResult.workingResolved;
|
|
903
|
-
cClasses = refineResult.classes;
|
|
904
|
-
cStyle = refineResult.style;
|
|
905
|
-
changedVariants = refineResult.changedVariants;
|
|
906
|
-
}
|
|
907
956
|
if (hasExtend) {
|
|
908
957
|
let extSkipKeys;
|
|
909
958
|
if (skipKeys === null) extSkipKeys = staticExtSkipKeys;
|
|
@@ -931,15 +980,31 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
931
980
|
for (let i = 0; i < extCount; i++) {
|
|
932
981
|
if (hasIsolatedExt && extIsolated[i]) {
|
|
933
982
|
const extClasses = [];
|
|
934
|
-
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);
|
|
935
984
|
if (extClasses.length > 0) {
|
|
936
985
|
const joined = clsx(extClasses);
|
|
937
986
|
if (joined.length > 0) classesOut.push(extMetas[i].transformClass(joined));
|
|
938
987
|
}
|
|
939
|
-
} 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);
|
|
940
990
|
if (protectedVariants && extMetasWithRefineCount > 0) Object.assign(extUserVariantProps, protectedVariants);
|
|
941
991
|
}
|
|
942
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
|
+
}
|
|
943
1008
|
if (hasBaseStyle) Object.assign(styleOut, baseStyle);
|
|
944
1009
|
const ownSkipKeys = skipKeys;
|
|
945
1010
|
const ownSkipValues = skipValues;
|
|
@@ -982,7 +1047,8 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
982
1047
|
if (cStyle) Object.assign(styleOut, cStyle);
|
|
983
1048
|
return workingResolved;
|
|
984
1049
|
};
|
|
985
|
-
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);
|
|
986
1052
|
runState ??= { remaining: MAX_REFINE_RUNS };
|
|
987
1053
|
protectedVariants ??= {};
|
|
988
1054
|
protectedVariantKeys ??= /* @__PURE__ */ new Set();
|
|
@@ -1004,12 +1070,19 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
1004
1070
|
const nextPendingProtectedVariants = {};
|
|
1005
1071
|
const nextClasses = useDirectOutput ? classesOut : [];
|
|
1006
1072
|
const nextStyle = useDirectOutput ? styleOut : {};
|
|
1007
|
-
const
|
|
1073
|
+
const defaultResolved = mergeProtectedIntoBase(incomingDefaultResolved, protectedVariants);
|
|
1074
|
+
const nextResolved = computeOnce(workingResolved, userVariantProps, skipKeys, skipValues, nextClasses, nextStyle, runState, protectedVariants, nextPendingProtectedVariants, protectedVariantKeys, defaultResolved);
|
|
1008
1075
|
let protectedChanged;
|
|
1009
1076
|
if (pendingProtectedVariants) protectedChanged = mergeVariants(pendingProtectedVariants, nextPendingProtectedVariants, protectedVariantKeys);
|
|
1010
1077
|
else protectedChanged = mergeVariants(protectedVariants, nextPendingProtectedVariants, protectedVariantKeys);
|
|
1011
1078
|
if (!protectedChanged && (nextResolved === workingResolved || areVariantsEqual(workingResolved, nextResolved))) {
|
|
1012
|
-
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) {
|
|
1013
1086
|
for (let i = 0; i < nextClasses.length; i++) classesOut.push(nextClasses[i]);
|
|
1014
1087
|
Object.assign(styleOut, nextStyle);
|
|
1015
1088
|
}
|
|
@@ -1046,26 +1119,35 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
1046
1119
|
Object.assign(styleOut, lastStyle);
|
|
1047
1120
|
return workingResolved;
|
|
1048
1121
|
};
|
|
1049
|
-
const resolveRefineOnce = (resolved, userVariantProps, filterOwnVariants = true, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys) => {
|
|
1122
|
+
const resolveRefineOnce = (resolved, userVariantProps, filterOwnVariants = true, runState, protectedVariants, pendingProtectedVariants, protectedVariantKeys, defaultResolved = resolved) => {
|
|
1050
1123
|
let workingResolved = resolved;
|
|
1051
1124
|
let changedVariants = null;
|
|
1052
|
-
if (refine) {
|
|
1053
|
-
const refineResult = runRefineContext(resolved, userVariantProps, filterOwnVariants, false, protectedVariants, pendingProtectedVariants, protectedVariantKeys);
|
|
1054
|
-
workingResolved = refineResult.workingResolved;
|
|
1055
|
-
changedVariants = refineResult.changedVariants;
|
|
1056
|
-
}
|
|
1057
1125
|
if (extMetasWithRefineCount > 0) {
|
|
1058
1126
|
const extUserVariantProps = getExtUserVariantProps(userVariantProps, protectedVariants ?? null, changedVariants);
|
|
1059
1127
|
for (let i = 0; i < extMetasWithRefineCount; i++) {
|
|
1060
1128
|
const resolveRefine = extMetasWithRefine[i].resolveRefine;
|
|
1061
1129
|
if (!resolveRefine) continue;
|
|
1062
|
-
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);
|
|
1063
1132
|
if (protectedVariants) Object.assign(extUserVariantProps, protectedVariants);
|
|
1064
1133
|
}
|
|
1065
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
|
+
}
|
|
1066
1148
|
return workingResolved;
|
|
1067
1149
|
};
|
|
1068
|
-
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) => {
|
|
1069
1151
|
runState ??= { remaining: MAX_REFINE_RUNS };
|
|
1070
1152
|
protectedVariants ??= {};
|
|
1071
1153
|
protectedVariantKeys ??= /* @__PURE__ */ new Set();
|
|
@@ -1075,7 +1157,8 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
1075
1157
|
while (runState.remaining > 0) {
|
|
1076
1158
|
runState.remaining -= 1;
|
|
1077
1159
|
const nextPendingProtectedVariants = {};
|
|
1078
|
-
const
|
|
1160
|
+
const defaultResolved = mergeProtectedIntoBase(incomingDefaultResolved, protectedVariants);
|
|
1161
|
+
const nextResolved = resolveRefineOnce(workingResolved, userVariantProps, filterOwnVariants, runState, protectedVariants, nextPendingProtectedVariants, protectedVariantKeys, defaultResolved);
|
|
1079
1162
|
let protectedChanged;
|
|
1080
1163
|
if (pendingProtectedVariants) protectedChanged = mergeVariants(pendingProtectedVariants, nextPendingProtectedVariants, protectedVariantKeys);
|
|
1081
1164
|
else protectedChanged = mergeVariants(protectedVariants, nextPendingProtectedVariants, protectedVariantKeys);
|
|
@@ -1102,19 +1185,12 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
1102
1185
|
let resolved = {};
|
|
1103
1186
|
Object.assign(resolved, staticDefaults);
|
|
1104
1187
|
let userVariantProps;
|
|
1105
|
-
if (extMetasWithRefineCount > 0) {
|
|
1188
|
+
if (refine || computedDefaultCount > 0 || extMetasWithRefineCount > 0) {
|
|
1106
1189
|
const variantProps = {};
|
|
1107
1190
|
for (let i = 0; i < variantKeysLength; i++) {
|
|
1108
1191
|
const key = variantKeys[i];
|
|
1109
1192
|
if (Object.hasOwn(propsRecord, key)) variantProps[key] = propsRecord[key];
|
|
1110
1193
|
}
|
|
1111
|
-
for (let i = 0; i < extMetasWithRefineCount; i++) {
|
|
1112
|
-
const extDefaults = extMetasWithRefine[i].resolveDefaults(resolved, variantProps);
|
|
1113
|
-
for (const k in extDefaults) {
|
|
1114
|
-
if (!Object.hasOwn(extDefaults, k)) continue;
|
|
1115
|
-
resolved[k] = extDefaults[k];
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
1194
|
for (const k in variantProps) {
|
|
1119
1195
|
if (!Object.hasOwn(variantProps, k)) continue;
|
|
1120
1196
|
const v = variantProps[k];
|
|
@@ -1173,11 +1249,11 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
1173
1249
|
const meta = {
|
|
1174
1250
|
baseClass: computedBaseClass,
|
|
1175
1251
|
staticDefaults,
|
|
1176
|
-
resolveDefaults: resolveDefaultsFn,
|
|
1177
1252
|
compute,
|
|
1178
1253
|
resolveRefine,
|
|
1179
1254
|
transformClass,
|
|
1180
|
-
functionVariantKeys
|
|
1255
|
+
functionVariantKeys,
|
|
1256
|
+
computedDefaultKeys
|
|
1181
1257
|
};
|
|
1182
1258
|
const initComponent = (c, propKeys, style) => {
|
|
1183
1259
|
c.class = classFn;
|
|
@@ -1244,7 +1320,6 @@ function create({ transformClass = (className) => className } = {}) {
|
|
|
1244
1320
|
cx
|
|
1245
1321
|
};
|
|
1246
1322
|
}
|
|
1247
|
-
function noop() {}
|
|
1248
1323
|
const { cv, cx } = create();
|
|
1249
1324
|
//#endregion
|
|
1250
1325
|
export { create, cv, cx, splitProps };
|