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 CHANGED
@@ -1,5 +1,51 @@
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
+
44
+ ## 0.4.2
45
+
46
+ - Improved [`refine`](https://clava.style/docs/reference/refine) iteration warnings to show the latest changing variant values with a shorter component creation stack.
47
+ - Fixed [`setDefaultVariants`](https://clava.style/docs/reference/refine#setdefaultvariants) calls with stable values to avoid extra [`refine`](https://clava.style/docs/reference/refine) passes.
48
+
3
49
  ## 0.4.1
4
50
 
5
51
  ### Improved refine iteration warning with debugging context
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 `refine` for compound conditions, dependent defaults, and final class/style adjustments. It receives the resolved variant values for the component and can return class/style output.
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
- refine: ({
332
- variants,
333
- setVariants,
334
- setDefaultVariants,
335
- addClass,
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
- `setVariants()` overrides explicit props. `setDefaultVariants()` overrides static `defaultVariants` and inherited defaults, but it does not override a prop the user explicitly passed unless that prop value is `undefined`. `addClass()` and `addStyle()` append output without changing resolved variant values. `getVariants()` includes values changed by `setVariants()` and `setDefaultVariants()`.
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?: VariantValues<MergeVariants<V, E>>;
116
+ defaultVariants?: DefaultVariants<MergeVariants<V, E>>;
110
117
  refine?: Refine<MergeVariants<V, E>>;
111
118
  }
112
119
  interface CreateParams {