clava 0.4.2 → 0.6.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,88 @@
1
1
  # clava
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Computed default variant parameters
6
+
7
+ **BREAKING** if you're using computed `defaultVariants` functions in [`cv`](https://clava.style/docs/reference/cv).
8
+
9
+ Computed `defaultVariants` functions now receive `defaultValue` and `variants` as separate parameters instead of a context object.
10
+
11
+ Before:
12
+
13
+ ```ts
14
+ const button = cv({
15
+ variants: {
16
+ size: { sm: "sm", lg: "lg" },
17
+ intent: { neutral: "neutral", brand: "brand" },
18
+ },
19
+ defaultVariants: {
20
+ intent: ({ defaultValue, variants }) =>
21
+ variants.size === "lg" ? "neutral" : defaultValue,
22
+ },
23
+ });
24
+ ```
25
+
26
+ After:
27
+
28
+ ```ts
29
+ const button = cv({
30
+ variants: {
31
+ size: { sm: "sm", lg: "lg" },
32
+ intent: { neutral: "neutral", brand: "brand" },
33
+ },
34
+ defaultVariants: {
35
+ intent: (defaultValue, variants) =>
36
+ variants.size === "lg" ? "neutral" : defaultValue,
37
+ },
38
+ });
39
+ ```
40
+
41
+ ### Other updates
42
+
43
+ - Documented Clava's public TypeScript helper declarations with inline examples.
44
+
45
+ ## 0.5.0
46
+
47
+ ### Computed default variants
48
+
49
+ **BREAKING** if you're using `setDefaultVariants` in [`cv`](https://clava.style/docs/reference/cv) `refine` callbacks.
50
+
51
+ 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.
52
+
53
+ 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.
54
+
55
+ Before:
56
+
57
+ ```ts
58
+ const button = cv({
59
+ variants: {
60
+ size: { sm: "sm", lg: "lg" },
61
+ intent: { neutral: "neutral", brand: "brand" },
62
+ },
63
+ refine({ variants, setDefaultVariants }) {
64
+ if (variants.size === "lg") {
65
+ setDefaultVariants({ intent: "neutral" });
66
+ }
67
+ },
68
+ });
69
+ ```
70
+
71
+ After:
72
+
73
+ ```ts
74
+ const button = cv({
75
+ variants: {
76
+ size: { sm: "sm", lg: "lg" },
77
+ intent: { neutral: "neutral", brand: "brand" },
78
+ },
79
+ defaultVariants: {
80
+ intent: ({ defaultValue, variants }) =>
81
+ variants.size === "lg" ? "neutral" : defaultValue,
82
+ },
83
+ });
84
+ ```
85
+
3
86
  ## 0.4.2
4
87
 
5
88
  - Improved [`refine`](https://clava.style/docs/reference/refine) iteration warnings to show the latest changing variant values with a shorter component creation stack.
@@ -70,7 +153,7 @@ Before:
70
153
  ```ts
71
154
  const button = cv({
72
155
  variants: { size: { sm: "sm", lg: "lg" } },
73
- computed: ({ variants, addClass }) => {
156
+ computed({ variants, addClass }) {
74
157
  if (variants.size === "lg") {
75
158
  addClass("is-large");
76
159
  }
@@ -83,7 +166,7 @@ After:
83
166
  ```ts
84
167
  const button = cv({
85
168
  variants: { size: { sm: "sm", lg: "lg" } },
86
- refine: ({ variants, addClass }) => {
169
+ refine({ variants, addClass }) {
87
170
  if (variants.size === "lg") {
88
171
  addClass("is-large");
89
172
  }
package/README.md CHANGED
@@ -24,6 +24,7 @@ import type { Variant, VariantProps } from "clava";
24
24
  - [Solid](#solid)
25
25
  - [`create()` And `cx()`](#create-and-cx)
26
26
  - [Type Helpers](#type-helpers)
27
+ - [Comparison](#comparison)
27
28
  - [API Summary](#api-summary)
28
29
 
29
30
  ## Install
@@ -230,17 +231,19 @@ Variant values can be class values, arrays, `{ class, style }` objects, or [func
230
231
 
231
232
  ## Function Variants
232
233
 
233
- Add a function as a variant value when the prop should generate class/style output dynamically. The function's parameter type defines the prop type.
234
+ Add a function as a variant value when the prop should generate class/style output dynamically. The function's parameter type defines the prop type. Method syntax works well for multi-line callbacks; compact one-line callbacks can stay as arrow-function property values.
234
235
 
235
236
  ```ts
236
237
  const grid = cv({
237
238
  class: "grid",
238
239
  variants: {
239
- columns: (value: number) => ({
240
- class: `grid-cols-${value}`,
241
- style: { "--grid-columns": `${value}` },
242
- }),
243
- color: (value: string | null) => {
240
+ columns(value: number) {
241
+ return {
242
+ class: `grid-cols-${value}`,
243
+ style: { "--grid-columns": `${value}` },
244
+ };
245
+ },
246
+ color(value: string | null) {
244
247
  return value ? `text-${value}` : "text-current";
245
248
  },
246
249
  },
@@ -316,7 +319,9 @@ You can extend any component mode, including `baseButton.jsx`, `baseButton.html`
316
319
 
317
320
  ## Refine
318
321
 
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.
322
+ Use computed `defaultVariants` for dependent defaults. A function entry receives the current default value for that key as the first parameter and the resolved variants snapshot as the second parameter, then returns the next default value.
323
+
324
+ 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
325
 
321
326
  ```ts
322
327
  const toolbarButton = cv({
@@ -328,21 +333,15 @@ const toolbarButton = cv({
328
333
  },
329
334
  loading: "toolbar-button-loading",
330
335
  },
331
- refine: ({
332
- variants,
333
- setVariants,
334
- setDefaultVariants,
335
- addClass,
336
- addStyle,
337
- }) => {
336
+ defaultVariants: {
337
+ intent: (defaultValue, variants) =>
338
+ variants.size === "lg" ? "neutral" : defaultValue,
339
+ },
340
+ refine({ variants, setVariants, addClass, addStyle }) {
338
341
  if (variants.loading) {
339
342
  setVariants({ pressed: false });
340
343
  }
341
344
 
342
- if (variants.size === "lg") {
343
- setDefaultVariants({ intent: "neutral" });
344
- }
345
-
346
345
  if (variants.pressed && variants.intent === "brand") {
347
346
  addClass("toolbar-button-brand-pressed");
348
347
  addStyle({ transform: "translateY(1px)" });
@@ -353,9 +352,24 @@ const toolbarButton = cv({
353
352
  });
354
353
  ```
355
354
 
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()`.
355
+ 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:
356
+
357
+ ```ts
358
+ const transform = (value: string) => value.toUpperCase();
359
+
360
+ const input = cv({
361
+ variants: {
362
+ transform: (fn: (value: string) => string) => fn("example"),
363
+ },
364
+ defaultVariants: {
365
+ transform: () => transform,
366
+ },
367
+ });
368
+ ```
369
+
370
+ `setVariants()` overrides explicit props. `addClass()` and `addStyle()` append output without changing resolved variant values. `getVariants()` includes values changed by computed `defaultVariants` and `setVariants()`.
357
371
 
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.
372
+ 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
373
 
360
374
  ## Splitting Props
361
375
 
@@ -373,17 +387,18 @@ const button = cv({
373
387
  lg: "button-lg",
374
388
  },
375
389
  },
376
- }).jsx;
390
+ });
377
391
 
378
- type ButtonProps = ComponentProps<"button"> & VariantProps<typeof button>;
392
+ interface ButtonProps
393
+ extends ComponentProps<"button">, VariantProps<typeof button> {}
379
394
 
380
395
  function Button(props: ButtonProps) {
381
396
  const [variantProps, buttonProps] = splitProps(props, button);
382
- return <button {...buttonProps} {...button(variantProps)} />;
397
+ return <button {...buttonProps} {...button.jsx(variantProps)} />;
383
398
  }
384
399
  ```
385
400
 
386
- The first component source claims variant props plus styling props (`class`, `className`, and `style`, depending on the mode). Later component sources receive only their variant props. Array sources receive exactly the listed keys and do not claim styling props.
401
+ The first component source claims variant props plus the styling props exposed by that component's `propKeys`. The base component claims `class`, `className`, and `style`; mode-specific components claim their own styling props. Later component sources receive only their variant props. Array sources receive exactly the listed keys and do not claim styling props.
387
402
 
388
403
  ```ts
389
404
  const [buttonProps, fieldProps, rest] = splitProps(props, button, field);
@@ -420,14 +435,14 @@ const button = cv({
420
435
  md: "button-md",
421
436
  },
422
437
  },
423
- }).jsx;
438
+ });
424
439
 
425
440
  interface ButtonProps
426
441
  extends ComponentProps<"button">, VariantProps<typeof button> {}
427
442
 
428
443
  function Button(props: ButtonProps) {
429
444
  const [variantProps, buttonProps] = splitProps(props, button);
430
- return <button {...buttonProps} {...button(variantProps)} />;
445
+ return <button {...buttonProps} {...button.jsx(variantProps)} />;
431
446
  }
432
447
  ```
433
448
 
@@ -448,13 +463,14 @@ const button = cv({
448
463
  md: "button-md",
449
464
  },
450
465
  },
451
- }).htmlObj;
466
+ });
452
467
 
453
- type ButtonProps = ComponentProps<"button"> & VariantProps<typeof button>;
468
+ interface ButtonProps
469
+ extends ComponentProps<"button">, VariantProps<typeof button> {}
454
470
 
455
471
  function Button(props: ButtonProps) {
456
472
  const [variantProps, buttonProps] = splitProps(props, button);
457
- return <button {...buttonProps} {...button(variantProps)} />;
473
+ return <button {...buttonProps} {...button.htmlObj(variantProps)} />;
458
474
  }
459
475
  ```
460
476
 
@@ -493,7 +509,8 @@ Use `VariantProps<typeof component>` to add a Clava component's variant props to
493
509
  import type { ComponentProps } from "react";
494
510
  import type { VariantProps } from "clava";
495
511
 
496
- type ButtonProps = ComponentProps<"button"> & VariantProps<typeof button>;
512
+ interface ButtonProps
513
+ extends ComponentProps<"button">, VariantProps<typeof button> {}
497
514
  ```
498
515
 
499
516
  Use `Variant<typeof component, "key">` to constrain a new variant map to the same values as another component's variant.
@@ -523,6 +540,36 @@ const icon = cv({
523
540
 
524
541
  The package also exports `ClassValue`, `StyleValue`, `StyleClassProps`, `StyleClassValue`, `JSXProps`, `HTMLProps`, `HTMLObjProps`, `CVComponent`, and `CVConfig`.
525
542
 
543
+ ## Comparison
544
+
545
+ This table compares Clava with the packages used by the repository's alternative benchmark: `class-variance-authority@0.7.1`, `cva@1.0.0-beta.4`, `tailwind-variants/lite@3.2.2`, and `tailwind-variants@3.2.2`.
546
+
547
+ | Feature | Clava | CVA v0 | CVA v1 beta | TV Lite | TV |
548
+ | ---------------------------------------------------- | -------------- | ------------------ | ------------------ | ------------------ | ------------------ |
549
+ | Typed variants and default variants | Yes | Yes | Yes | Yes | Yes |
550
+ | Boolean shorthand variants | Yes | No | No | No | No |
551
+ | Component extension or composition | `extend` | No helper | `compose()` | `extend` | `extend` |
552
+ | Cross-variant conditions | `refine()` | `compoundVariants` | `compoundVariants` | `compoundVariants` | `compoundVariants` |
553
+ | Function variant values | Yes | No | No | No | No |
554
+ | Computed default variants | Yes | No | No | No | No |
555
+ | Class and style prop output | Yes | Classes only | Classes only | Classes only | Classes only |
556
+ | JSX, HTML string, and hyphenated-object output modes | Yes | No | No | No | No |
557
+ | Built-in prop splitting for framework props | `splitProps()` | No | No | No | No |
558
+ | Dedicated slots API | No | No | No | Yes | Yes |
559
+ | Built-in Tailwind conflict merging | No | No | No | No | Yes |
560
+
561
+ The `pnpm perf-alternatives` benchmark resolves a composed Tailwind-style button with inherited variants, defaults, and cross-variant conditions. On Node v24.14.1, Vitest reported these results, where higher ops/sec is better:
562
+
563
+ | Package | Ops/sec | Relative to Clava |
564
+ | -------------------------------- | --------: | ----------------: |
565
+ | `clava@0.5.0` | 1,040,314 | 1.00x |
566
+ | `class-variance-authority@0.7.1` | 426,132 | 2.44x slower |
567
+ | `tailwind-variants/lite@3.2.2` | 369,732 | 2.81x slower |
568
+ | `tailwind-variants@3.2.2` | 273,503 | 3.80x slower |
569
+ | `cva@1.0.0-beta.4` | 211,474 | 4.92x slower |
570
+
571
+ Benchmark results vary by runtime and hardware, so treat them as a reproducible snapshot of this repository's composed-variant case rather than a universal ranking.
572
+
526
573
  ## API Summary
527
574
 
528
575
  `cv(config?)` creates a typed Clava component. Supported config keys are `extend`, `class`, `style`, `variants`, `defaultVariants`, and `refine`.
@@ -539,7 +586,7 @@ The package also exports `ClassValue`, `StyleValue`, `StyleClassProps`, `StyleCl
539
586
 
540
587
  `component.style(props?)` returns only the resolved style value for that component mode.
541
588
 
542
- `component.getVariants(props?)` returns resolved variant values after static defaults, inherited defaults, and `refine` updates.
589
+ `component.getVariants(props?)` returns resolved variant values after static defaults, inherited defaults, computed defaults, and `refine` updates.
543
590
 
544
591
  `component.propKeys` lists style props plus variant props for that component mode.
545
592
 
package/dist/index.d.ts CHANGED
@@ -2,22 +2,84 @@ import { ClassValue as ClassValue$1 } from "clsx";
2
2
  import * as CSS from "csstype";
3
3
 
4
4
  //#region src/types.d.ts
5
+ /**
6
+ * A class value accepted by Clava. It supports strings, numbers, booleans,
7
+ * nullish values, and nested arrays.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import type { ClassValue } from "clava";
12
+ *
13
+ * const className: ClassValue = [
14
+ * "button",
15
+ * false && "button-hidden",
16
+ * ["button-primary"],
17
+ * ];
18
+ * ```
19
+ */
5
20
  type ClassValue = string | number | boolean | null | undefined | void | ClassValue[];
6
21
  type JSXCSSProperties = CSS.Properties<string | number>;
7
22
  type HTMLCSSProperties = CSS.PropertiesHyphen<string | number>;
8
23
  type StyleProperty = JSXCSSProperties | HTMLCSSProperties | string;
24
+ /**
25
+ * The prop object returned by a component's `.jsx()` mode.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { type JSXProps, cv } from "clava";
30
+ *
31
+ * const button = cv({ class: "button" });
32
+ * const props: JSXProps = button.jsx();
33
+ * ```
34
+ */
9
35
  interface JSXProps {
10
36
  className: string;
11
37
  style: JSXCSSProperties;
12
38
  }
39
+ /**
40
+ * The prop object returned by a component's `.html()` mode. The `style` value
41
+ * is serialized as an HTML style string.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * import { type HTMLProps, cv } from "clava";
46
+ *
47
+ * const button = cv({ style: { color: "red" } });
48
+ * const props: HTMLProps = button.html();
49
+ * ```
50
+ */
13
51
  interface HTMLProps {
14
52
  class: string;
15
53
  style: string;
16
54
  }
55
+ /**
56
+ * The prop object returned by a component's `.htmlObj()` mode. The `style`
57
+ * value uses hyphenated CSS property names.
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * import { type HTMLObjProps, cv } from "clava";
62
+ *
63
+ * const button = cv({ style: { fontSize: "16px" } });
64
+ * const props: HTMLObjProps = button.htmlObj();
65
+ * ```
66
+ */
17
67
  interface HTMLObjProps {
18
68
  class: string;
19
69
  style: HTMLCSSProperties;
20
70
  }
71
+ /**
72
+ * The default prop object returned by a Clava component. It uses `class`
73
+ * rather than `className` and keeps styles as a normalized object.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * import { type StyleClassProps, cv } from "clava";
78
+ *
79
+ * const button = cv({ class: "button" });
80
+ * const props: StyleClassProps = button();
81
+ * ```
82
+ */
21
83
  interface StyleClassProps {
22
84
  class: string;
23
85
  style: StyleValue;
@@ -61,6 +123,25 @@ interface ModalComponent<V, R extends ComponentResult> {
61
123
  variantKeys: (keyof V)[];
62
124
  propKeys: (keyof V | ComponentPropKey<R>)[];
63
125
  }
126
+ /**
127
+ * A callable Clava component returned by `cv()`. It includes the default
128
+ * output mode plus `.jsx()`, `.html()`, and `.htmlObj()` mode helpers.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * import { type CVComponent, cv } from "clava";
133
+ *
134
+ * const button: CVComponent<{
135
+ * size: { sm: string; lg: string };
136
+ * }> = cv({
137
+ * variants: {
138
+ * size: { sm: "button-sm", lg: "button-lg" },
139
+ * },
140
+ * });
141
+ *
142
+ * button.jsx({ size: "lg" });
143
+ * ```
144
+ */
64
145
  interface CVComponent<V extends Variants = {}, E extends AnyComponent[] = [], R extends ComponentResult = StyleClassProps> extends ModalComponent<MergeVariants<V, E>, R> {
65
146
  jsx: ModalComponent<MergeVariants<V, E>, JSXProps>;
66
147
  html: ModalComponent<MergeVariants<V, E>, HTMLProps>;
@@ -76,10 +157,42 @@ type StringToBoolean<T> = T extends "true" | "false" ? boolean : T;
76
157
  type VariantValue = ClassValue | StyleClassValue;
77
158
  type NonNullKeys<T> = { [K in keyof T]: T[K] extends null ? never : K }[keyof T];
78
159
  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]> };
160
+ type VariantValues<V> = { [K in keyof V]?: ExtractVariantValue<V[K]> | undefined };
161
+ type ComputedDefaultVariant<V, K extends keyof V> = (defaultValue: ExtractVariantValue<V[K]> | undefined, variants: Readonly<VariantValues<V>>) => ExtractVariantValue<V[K]> | undefined;
162
+ type NonFunctionVariantValue<T> = Exclude<T, (...args: any[]) => any>;
163
+ type DefaultVariantValue<V, K extends keyof V> = [NonFunctionVariantValue<ExtractVariantValue<V[K]>>] extends [never] ? ComputedDefaultVariant<V, K> : NonFunctionVariantValue<ExtractVariantValue<V[K]>> | ComputedDefaultVariant<V, K>;
164
+ type DefaultVariants<V> = { [K in keyof V]?: DefaultVariantValue<V, K> | undefined };
165
+ /**
166
+ * A normalized style object accepted by Clava config, variant, and refine
167
+ * style entries. CSS custom properties are supported with string values.
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * import type { StyleValue } from "clava";
172
+ *
173
+ * const style: StyleValue = {
174
+ * color: "red",
175
+ * "--button-accent": "oklch(62% 0.2 250)",
176
+ * };
177
+ * ```
178
+ */
80
179
  type StyleValue = CSS.Properties & {
81
180
  [key: `--${string}`]: string;
82
181
  };
182
+ /**
183
+ * A value that contributes both class and style output from a base config,
184
+ * variant value, function variant, or refine callback.
185
+ *
186
+ * @example
187
+ * ```ts
188
+ * import type { StyleClassValue } from "clava";
189
+ *
190
+ * const tone: StyleClassValue = {
191
+ * class: "button-primary",
192
+ * style: { color: "white" },
193
+ * };
194
+ * ```
195
+ */
83
196
  interface StyleClassValue {
84
197
  style?: StyleValue;
85
198
  class?: ClassValue;
@@ -87,7 +200,6 @@ interface StyleClassValue {
87
200
  interface RefineContext<V> {
88
201
  variants: VariantValues<V>;
89
202
  setVariants: (variants: VariantValues<V>) => void;
90
- setDefaultVariants: (variants: VariantValues<V>) => void;
91
203
  addClass: (className: ClassValue) => void;
92
204
  addStyle: (style: StyleValue) => void;
93
205
  }
@@ -98,15 +210,93 @@ type NullablePartial<T> = T extends Record<string, any> ? { [K in keyof T]?: T[K
98
210
  type ExtendableVariants<V extends Variants, E extends AnyComponent[]> = V & { [K in keyof MergeExtendedVariants<E>]?: NullablePartial<MergeExtendedVariants<E>[K]> | Variant$1 };
99
211
  //#endregion
100
212
  //#region src/index.d.ts
213
+ /**
214
+ * Extracts the variant props inferred for a Clava component. Use it to add a
215
+ * component's variant props to framework component props.
216
+ *
217
+ * @example
218
+ * ```ts
219
+ * import { type VariantProps, cv } from "clava";
220
+ * import type { ComponentProps } from "react";
221
+ *
222
+ * const button = cv({
223
+ * variants: {
224
+ * size: { sm: "button-sm", lg: "button-lg" },
225
+ * disabled: { true: "button-disabled", false: "" },
226
+ * },
227
+ * });
228
+ *
229
+ * interface ButtonProps
230
+ * extends ComponentProps<"button">,
231
+ * VariantProps<typeof button> {}
232
+ *
233
+ * const props: ButtonProps = {
234
+ * size: "lg",
235
+ * disabled: true,
236
+ * };
237
+ * ```
238
+ */
101
239
  type VariantProps<T extends Pick<AnyComponent, "getVariants">> = ReturnType<T["getVariants"]>;
102
240
  type VariantKey<T> = T extends boolean ? "true" | "false" : Extract<T, string>;
241
+ /**
242
+ * Constrains a variant map to the same value keys as a variant on another
243
+ * component. Boolean variants are represented with `"true"` and `"false"`
244
+ * object keys.
245
+ *
246
+ * @example
247
+ * ```ts
248
+ * import { type Variant, cv } from "clava";
249
+ *
250
+ * const button = cv({
251
+ * variants: {
252
+ * size: { sm: "button-sm", lg: "button-lg" },
253
+ * },
254
+ * });
255
+ *
256
+ * const icon = cv({
257
+ * extend: [button],
258
+ * variants: {
259
+ * size: {
260
+ * sm: "icon-sm",
261
+ * lg: "icon-lg",
262
+ * } satisfies Variant<typeof button, "size">,
263
+ * },
264
+ * });
265
+ * ```
266
+ */
103
267
  type Variant<T extends Pick<AnyComponent, "getVariants">, K extends keyof VariantProps<T>> = Record<VariantKey<NonNullable<VariantProps<T>[K]>>, ClassValue | StyleClassValue>;
268
+ /**
269
+ * The configuration object accepted by `cv()`. It defines base class/style
270
+ * output, variants, default variants, component extensions, and refinement
271
+ * logic.
272
+ *
273
+ * @example
274
+ * ```ts
275
+ * import { type CVConfig, cv } from "clava";
276
+ *
277
+ * const config: CVConfig<{
278
+ * tone: { info: string; danger: string };
279
+ * }> = {
280
+ * variants: {
281
+ * tone: {
282
+ * info: "alert-info",
283
+ * danger: "alert-danger",
284
+ * },
285
+ * },
286
+ * defaultVariants: {
287
+ * tone: "info",
288
+ * },
289
+ * };
290
+ *
291
+ * const alert = cv(config);
292
+ * ```
293
+ */
104
294
  interface CVConfig<V extends Variants = {}, E extends AnyComponent[] = []> {
105
295
  extend?: E;
106
296
  class?: ClassValue;
107
297
  style?: StyleValue;
108
298
  variants?: ExtendableVariants<V, E>;
109
- defaultVariants?: VariantValues<MergeVariants<V, E>>;
299
+ defaultVariants?: DefaultVariants<MergeVariants<V, E>>;
110
300
  refine?: Refine<MergeVariants<V, E>>;
111
301
  }
112
302
  interface CreateParams {