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.
@@ -71,7 +71,7 @@ for (const config of Object.values(CONFIGS)) {
71
71
  });
72
72
  });
73
73
 
74
- test("refine re-runs when setDefaultVariants changes variants", () => {
74
+ test("refine re-runs when computed defaultVariants change variants", () => {
75
75
  const component = getModeComponent(
76
76
  mode,
77
77
  cv({
@@ -79,11 +79,12 @@ for (const config of Object.values(CONFIGS)) {
79
79
  size: { sm: "sm", lg: "lg" },
80
80
  color: { red: "red", blue: "blue" },
81
81
  },
82
- refine: ({ variants, setDefaultVariants, addClass }) => {
83
- setDefaultVariants({ color: "red" });
84
- if (variants.color === "red") {
85
- setDefaultVariants({ size: "lg" });
86
- }
82
+ defaultVariants: {
83
+ color: () => "red" as const,
84
+ size: ({ defaultValue, variants }) =>
85
+ variants.color === "red" ? "lg" : defaultValue,
86
+ },
87
+ refine: ({ variants, addClass }) => {
87
88
  if (variants.size === "lg") {
88
89
  addClass("refine-lg");
89
90
  }
@@ -96,7 +97,7 @@ for (const config of Object.values(CONFIGS)) {
96
97
  });
97
98
  });
98
99
 
99
- test("refine converges with NaN setDefaultVariants", () => {
100
+ test("refine converges with NaN computed defaultVariants", () => {
100
101
  const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
101
102
  const component = getModeComponent(
102
103
  mode,
@@ -104,8 +105,10 @@ for (const config of Object.values(CONFIGS)) {
104
105
  variants: {
105
106
  value: (value: number) => (Number.isNaN(value) ? "nan" : null),
106
107
  },
107
- refine: ({ variants, setDefaultVariants, addClass }) => {
108
- setDefaultVariants({ value: Number.NaN });
108
+ defaultVariants: {
109
+ value: () => Number.NaN,
110
+ },
111
+ refine: ({ variants, addClass }) => {
109
112
  if (Number.isNaN(variants.value)) {
110
113
  addClass("refine-nan");
111
114
  }
@@ -125,7 +128,110 @@ for (const config of Object.values(CONFIGS)) {
125
128
  }
126
129
  });
127
130
 
128
- test("refine with setDefaultVariants", () => {
131
+ test("computed defaultVariants can clear inherited defaults", () => {
132
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
133
+ const base = cv({
134
+ variants: {
135
+ invert: { true: "invert" },
136
+ offset: (value: boolean | undefined) =>
137
+ value ? "offset" : undefined,
138
+ push: (value: number | undefined) =>
139
+ value === undefined ? undefined : `push-${value}`,
140
+ },
141
+ defaultVariants: {
142
+ offset: ({ variants }) => !variants.invert,
143
+ push: ({ variants }) => (variants.invert ? 20 : undefined),
144
+ },
145
+ });
146
+ const component = getModeComponent(mode, cv({ extend: [base] }));
147
+
148
+ try {
149
+ const props = component();
150
+ expect(getStyleClass(props)).toEqual({
151
+ class: cls("offset"),
152
+ });
153
+ expect(component.getVariants()).toEqual({
154
+ offset: true,
155
+ });
156
+ expect(warn).not.toHaveBeenCalled();
157
+ } finally {
158
+ warn.mockRestore();
159
+ }
160
+ });
161
+
162
+ test("computed defaultVariants use inherited defaults as defaultValue", () => {
163
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
164
+ const calls = {
165
+ layer: 0,
166
+ frame: 0,
167
+ control: 0,
168
+ };
169
+ const layer = cv({
170
+ variants: {
171
+ layer: { true: "layer" },
172
+ invert: { true: "invert" },
173
+ offset: (value: boolean | undefined) =>
174
+ value ? "offset" : undefined,
175
+ push: (value: number | undefined) =>
176
+ value === undefined ? undefined : `push-${value}`,
177
+ },
178
+ defaultVariants: {
179
+ layer: true,
180
+ offset: ({ defaultValue, variants }) => {
181
+ calls.layer += 1;
182
+ return variants.invert ? false : defaultValue;
183
+ },
184
+ push: ({ variants }) => (variants.invert ? 20 : undefined),
185
+ },
186
+ });
187
+ const frame = cv({
188
+ extend: [layer],
189
+ variants: {
190
+ frame: { true: "frame" },
191
+ },
192
+ defaultVariants: {
193
+ frame: true,
194
+ },
195
+ refine: () => {
196
+ calls.frame += 1;
197
+ },
198
+ });
199
+ const control = cv({
200
+ extend: [frame],
201
+ variants: {
202
+ control: { true: "control" },
203
+ },
204
+ defaultVariants: {
205
+ control: true,
206
+ offset: true,
207
+ },
208
+ refine: () => {
209
+ calls.control += 1;
210
+ },
211
+ });
212
+ const component = getModeComponent(mode, cv({ extend: [control] }));
213
+
214
+ try {
215
+ const props = component();
216
+ expect(getStyleClass(props)).toEqual({
217
+ class: cls("layer offset frame control"),
218
+ });
219
+ expect(component.getVariants()).toEqual({
220
+ layer: true,
221
+ offset: true,
222
+ frame: true,
223
+ control: true,
224
+ });
225
+ expect(calls.layer).toBeGreaterThan(0);
226
+ expect(calls.frame).toBeGreaterThan(0);
227
+ expect(calls.control).toBeGreaterThan(0);
228
+ expect(warn).not.toHaveBeenCalled();
229
+ } finally {
230
+ warn.mockRestore();
231
+ }
232
+ });
233
+
234
+ test("computed defaultVariants", () => {
129
235
  const component = getModeComponent(
130
236
  mode,
131
237
  cv({
@@ -133,10 +239,9 @@ for (const config of Object.values(CONFIGS)) {
133
239
  size: { sm: "sm", lg: "lg" },
134
240
  color: { red: "red", blue: "blue" },
135
241
  },
136
- refine: ({ variants, setDefaultVariants }) => {
137
- if (variants.size === "lg") {
138
- setDefaultVariants({ color: "red" });
139
- }
242
+ defaultVariants: {
243
+ color: ({ variants, defaultValue }) =>
244
+ variants.size === "lg" ? "red" : defaultValue,
140
245
  },
141
246
  }),
142
247
  );
@@ -144,7 +249,7 @@ for (const config of Object.values(CONFIGS)) {
144
249
  expect(getStyleClass(props)).toEqual({ class: cls("lg red") });
145
250
  });
146
251
 
147
- test("refine setDefaultVariants does not override props", () => {
252
+ test("computed defaultVariants do not override props", () => {
148
253
  const component = getModeComponent(
149
254
  mode,
150
255
  cv({
@@ -152,8 +257,8 @@ for (const config of Object.values(CONFIGS)) {
152
257
  size: { sm: "sm", lg: "lg" },
153
258
  color: { red: "red", blue: "blue" },
154
259
  },
155
- refine: ({ setDefaultVariants }) => {
156
- setDefaultVariants({ color: "red" });
260
+ defaultVariants: {
261
+ color: () => "red" as const,
157
262
  },
158
263
  }),
159
264
  );
@@ -161,25 +266,7 @@ for (const config of Object.values(CONFIGS)) {
161
266
  expect(getStyleClass(props)).toEqual({ class: cls("lg blue") });
162
267
  });
163
268
 
164
- test("refine setDefaultVariants overrides defaultVariants", () => {
165
- const component = getModeComponent(
166
- mode,
167
- cv({
168
- variants: {
169
- size: { sm: "sm", lg: "lg" },
170
- color: { red: "red", blue: "blue" },
171
- },
172
- defaultVariants: { size: "sm", color: "red" },
173
- refine: ({ setDefaultVariants }) => {
174
- setDefaultVariants({ color: "blue" });
175
- },
176
- }),
177
- );
178
- const props = component();
179
- expect(getStyleClass(props)).toEqual({ class: cls("sm blue") });
180
- });
181
-
182
- test("refine setDefaultVariants overrides extended defaultVariants", () => {
269
+ test("computed defaultVariants override extended defaultVariants", () => {
183
270
  const base = cv({
184
271
  variants: { color: { red: "red", blue: "blue" } },
185
272
  defaultVariants: { color: "red" },
@@ -189,9 +276,9 @@ for (const config of Object.values(CONFIGS)) {
189
276
  cv({
190
277
  extend: [base],
191
278
  variants: { size: { sm: "sm", lg: "lg" } },
192
- defaultVariants: { size: "sm" },
193
- refine: ({ setDefaultVariants }) => {
194
- setDefaultVariants({ color: "blue" });
279
+ defaultVariants: {
280
+ size: "sm",
281
+ color: () => "blue" as const,
195
282
  },
196
283
  }),
197
284
  );
@@ -199,31 +286,11 @@ for (const config of Object.values(CONFIGS)) {
199
286
  expect(getStyleClass(props)).toEqual({ class: cls("blue sm") });
200
287
  });
201
288
 
202
- test("refine setDefaultVariants overrides child defaultVariants", () => {
203
- const base = cv({
204
- variants: { size: { sm: "sm", lg: "lg" } },
205
- });
206
- const component = getModeComponent(
207
- mode,
208
- cv({
209
- extend: [base],
210
- variants: { color: { red: "red", blue: "blue" } },
211
- defaultVariants: { size: "sm", color: "red" },
212
- refine: ({ setDefaultVariants }) => {
213
- setDefaultVariants({ size: "lg" });
214
- },
215
- }),
216
- );
217
- const props = component();
218
- expect(getStyleClass(props)).toEqual({ class: cls("lg red") });
219
- });
220
-
221
- test("refine setDefaultVariants from parent overrides child defaultVariants", () => {
289
+ test("parent computed defaultVariants can override child defaultVariants", () => {
222
290
  const base = cv({
223
291
  variants: { size: { sm: "sm", lg: "lg" } },
224
- defaultVariants: { size: "sm" },
225
- refine: ({ setDefaultVariants }) => {
226
- setDefaultVariants({ size: "lg" });
292
+ defaultVariants: {
293
+ size: () => "lg" as const,
227
294
  },
228
295
  });
229
296
  const component = getModeComponent(
@@ -238,13 +305,12 @@ for (const config of Object.values(CONFIGS)) {
238
305
  expect(getStyleClass(props)).toEqual({ class: cls("lg red") });
239
306
  });
240
307
 
241
- test("refine setDefaultVariants from parent overrides child defaultVariants based on props", () => {
308
+ test("parent computed defaultVariants can depend on child defaults", () => {
242
309
  const base = cv({
243
- variants: { size: { sm: "sm", lg: "lg" }, enabled: "" },
244
- defaultVariants: { size: "sm" },
245
- refine: ({ variants, setDefaultVariants }) => {
246
- if (!variants.enabled) return;
247
- setDefaultVariants({ size: "lg" });
310
+ variants: { size: { sm: "sm", lg: "lg" }, large: "" },
311
+ defaultVariants: {
312
+ size: ({ defaultValue, variants }) =>
313
+ variants.large ? "lg" : defaultValue,
248
314
  },
249
315
  });
250
316
  const component = getModeComponent(
@@ -252,97 +318,68 @@ for (const config of Object.values(CONFIGS)) {
252
318
  cv({
253
319
  extend: [base],
254
320
  variants: { color: { red: "red", blue: "blue" } },
255
- defaultVariants: { size: "sm", color: "red" },
321
+ defaultVariants: { size: "sm", color: "red", large: true },
256
322
  }),
257
323
  );
258
- const props = component({ enabled: true });
324
+ const props = component();
259
325
  expect(getStyleClass(props)).toEqual({ class: cls("lg red") });
260
326
  });
261
327
 
262
- test("refine receives default variants from child", () => {
263
- const base = cv({
264
- variants: { size: { sm: "sm", lg: "lg" }, large: "" },
265
- defaultVariants: { size: "sm" },
266
- refine: ({ variants, setDefaultVariants }) => {
267
- if (variants.large) {
268
- setDefaultVariants({ size: "lg" });
269
- }
328
+ test("computed defaultVariants preserve intermediate defaults", () => {
329
+ const parent = cv({
330
+ variants: { size: { sm: "sm", lg: "lg" } },
331
+ defaultVariants: {
332
+ size: ({ defaultValue, variants }) =>
333
+ variants.size ? defaultValue : "lg",
270
334
  },
271
335
  });
272
- const component = getModeComponent(
273
- mode,
274
- cv({
275
- extend: [base],
276
- variants: { color: { red: "red", blue: "blue" } },
277
- defaultVariants: { size: "sm", color: "red", large: true },
278
- }),
279
- );
336
+ const child = cv({ extend: [parent], defaultVariants: { size: "sm" } });
337
+ const component = getModeComponent(mode, cv({ extend: [child] }));
280
338
  const props = component();
281
- expect(getStyleClass(props)).toEqual({ class: cls("lg red") });
339
+ expect(getStyleClass(props)).toEqual({ class: cls("sm") });
282
340
  });
283
341
 
284
- test("refine receives default variants from grandchild", () => {
342
+ test("child computed defaultVariants override parent computed defaultVariants", () => {
285
343
  const base = cv({
286
- variants: { size: { sm: "sm", lg: "lg" }, large: "" },
287
- defaultVariants: { size: "sm" },
288
- refine: ({ variants, setDefaultVariants }) => {
289
- if (variants.large) {
290
- setDefaultVariants({ size: "lg" });
291
- }
344
+ variants: { size: { sm: "sm", lg: "lg" } },
345
+ defaultVariants: {
346
+ size: () => "lg" as const,
292
347
  },
293
348
  });
294
- const base2 = cv({ extend: [base] });
295
349
  const component = getModeComponent(
296
350
  mode,
297
351
  cv({
298
- extend: [base2],
352
+ extend: [base],
299
353
  variants: { color: { red: "red", blue: "blue" } },
300
- defaultVariants: { size: "sm", color: "red", large: true },
354
+ defaultVariants: {
355
+ size: () => "sm" as const,
356
+ color: "red",
357
+ },
301
358
  }),
302
359
  );
303
360
  const props = component();
304
- expect(getStyleClass(props)).toEqual({ class: cls("lg red") });
305
- });
306
-
307
- test("refine receives default variants from intermediate component", () => {
308
- const parent = cv({
309
- variants: { size: { sm: "sm", lg: "lg" } },
310
- refine: ({ variants, setDefaultVariants }) => {
311
- if (!variants.size) {
312
- setDefaultVariants({ size: "lg" });
313
- }
314
- },
315
- });
316
- const child = cv({ extend: [parent], defaultVariants: { size: "sm" } });
317
- const component = getModeComponent(mode, cv({ extend: [child] }));
318
- const props = component();
319
- expect(getStyleClass(props)).toEqual({ class: cls("sm") });
361
+ expect(getStyleClass(props)).toEqual({ class: cls("sm red") });
320
362
  });
321
363
 
322
- test("child refine setDefaultVariants overrides parent refine setDefaultVariants", () => {
364
+ test("child computed defaultVariants can preserve parent computed defaultVariants", () => {
323
365
  const base = cv({
324
366
  variants: { size: { sm: "sm", lg: "lg" } },
325
- defaultVariants: { size: "sm" },
326
- refine: ({ setDefaultVariants }) => {
327
- setDefaultVariants({ size: "lg" });
367
+ defaultVariants: {
368
+ size: () => "lg" as const,
328
369
  },
329
370
  });
330
371
  const component = getModeComponent(
331
372
  mode,
332
373
  cv({
333
374
  extend: [base],
334
- variants: { color: { red: "red", blue: "blue" } },
335
- defaultVariants: { size: "sm", color: "red" },
336
- refine: ({ setDefaultVariants }) => {
337
- setDefaultVariants({ size: "sm" });
375
+ defaultVariants: {
376
+ size: ({ defaultValue }) => defaultValue,
338
377
  },
339
378
  }),
340
379
  );
341
380
  const props = component();
342
- // Order: parent defaultVariants (sm) -> child defaultVariants (sm)
343
- // -> parent refine.setDefaultVariants (lg)
344
- // -> child refine.setDefaultVariants (sm)
345
- expect(getStyleClass(props)).toEqual({ class: cls("sm red") });
381
+ expect(getStyleClass(props)).toEqual({ class: cls("lg") });
382
+ expect(component.getVariants()).toEqual({ size: "lg" });
346
383
  });
347
384
 
348
385
  test("refine in extended component does not see foreign variant keys", () => {
@@ -365,6 +402,7 @@ for (const config of Object.values(CONFIGS)) {
365
402
  cv({
366
403
  extend: [base],
367
404
  variants: { color: { red: "red", blue: "blue" } },
405
+ defaultVariants: { size: "sm" },
368
406
  }),
369
407
  );
370
408
  const props = component({ color: "red" });
@@ -373,18 +411,14 @@ for (const config of Object.values(CONFIGS)) {
373
411
  });
374
412
  });
375
413
 
376
- test("setDefaultVariants in extended component does not branch on foreign variant keys", () => {
377
- // Same shape as the test above, but the base's `refine` reaches
378
- // `setDefaultVariants` — covers the resolveDefaults pass (driving
379
- // both class output and `getVariants`) rather than the render-time
380
- // compute path.
414
+ test("computed defaultVariants in extended component do not branch on foreign variant keys", () => {
381
415
  const base = cv({
382
416
  variants: { size: { sm: "sm", lg: "lg" } },
383
- defaultVariants: { size: "sm" },
384
- refine: ({ variants, setDefaultVariants }) => {
385
- if ("color" in (variants as Record<string, unknown>)) {
386
- setDefaultVariants({ size: "lg" });
387
- }
417
+ defaultVariants: {
418
+ size: ({ defaultValue, variants }) =>
419
+ "color" in (variants as Record<string, unknown>)
420
+ ? "lg"
421
+ : defaultValue,
388
422
  },
389
423
  });
390
424
  const component = getModeComponent(
@@ -392,6 +426,7 @@ for (const config of Object.values(CONFIGS)) {
392
426
  cv({
393
427
  extend: [base],
394
428
  variants: { color: { red: "red", blue: "blue" } },
429
+ defaultVariants: { size: "sm" },
395
430
  }),
396
431
  );
397
432
  const props = component({ color: "red" });
@@ -402,11 +437,11 @@ for (const config of Object.values(CONFIGS)) {
402
437
  });
403
438
  });
404
439
 
405
- test("child setDefaultVariants receives refined variants from parent", () => {
440
+ test("child computed defaultVariants receive refined variants from parent", () => {
406
441
  const base = cv({
407
442
  variants: { size: { sm: "sm", lg: "lg" }, small: "" },
408
- refine: ({ setDefaultVariants }) => {
409
- setDefaultVariants({ small: true });
443
+ refine: ({ setVariants }) => {
444
+ setVariants({ small: true });
410
445
  },
411
446
  });
412
447
  const component = getModeComponent(
@@ -414,11 +449,10 @@ for (const config of Object.values(CONFIGS)) {
414
449
  cv({
415
450
  extend: [base],
416
451
  variants: { color: { red: "red", blue: "blue" } },
417
- defaultVariants: { size: "lg", color: "red" },
418
- refine: ({ variants, setDefaultVariants }) => {
419
- if (variants.small) {
420
- setDefaultVariants({ size: "sm" });
421
- }
452
+ defaultVariants: {
453
+ size: ({ defaultValue, variants }) =>
454
+ variants.small ? "sm" : defaultValue,
455
+ color: "red",
422
456
  },
423
457
  }),
424
458
  );
@@ -452,21 +486,21 @@ for (const config of Object.values(CONFIGS)) {
452
486
  expect(getStyleClass(props)).toEqual({ class: cls("lg red") });
453
487
  });
454
488
 
455
- test("base refine setDefaultVariants works after its own setVariants re-run", () => {
489
+ test("computed defaultVariants work after a setVariants re-run", () => {
456
490
  const base = cv({
457
491
  variants: {
458
492
  size: { sm: "sm", lg: "lg" },
459
493
  active: "",
460
494
  mode: { on: "on" },
461
495
  },
462
- defaultVariants: { size: "sm" },
463
- refine: ({ variants, setVariants, setDefaultVariants }) => {
496
+ defaultVariants: {
497
+ size: ({ defaultValue, variants }) =>
498
+ variants.mode === "on" ? "lg" : defaultValue,
499
+ },
500
+ refine: ({ variants, setVariants }) => {
464
501
  if (variants.active) {
465
502
  setVariants({ mode: "on" });
466
503
  }
467
- if (variants.mode === "on") {
468
- setDefaultVariants({ size: "lg" });
469
- }
470
504
  },
471
505
  });
472
506
  const component = getModeComponent(mode, cv({ extend: [base] }));
@@ -516,11 +550,11 @@ for (const config of Object.values(CONFIGS)) {
516
550
  expect(getStyleClass(getProps())).toEqual({ class: cls("red") });
517
551
  });
518
552
 
519
- test("child setVariants keeps overriding base setDefaultVariants across re-runs", () => {
553
+ test("child setVariants keeps overriding base computed defaultVariants across re-runs", () => {
520
554
  const base = cv({
521
555
  variants: { color: { red: "red", blue: "blue" } },
522
- refine: ({ setDefaultVariants }) => {
523
- setDefaultVariants({ color: "blue" });
556
+ defaultVariants: {
557
+ color: () => "blue" as const,
524
558
  },
525
559
  });
526
560
  const component = getModeComponent(
@@ -540,11 +574,11 @@ for (const config of Object.values(CONFIGS)) {
540
574
  expect(getStyleClass(props)).toEqual({ class: cls("red sm") });
541
575
  });
542
576
 
543
- test("refine setVariants sticks across re-runs", () => {
577
+ test("refine setVariants sticks across computed default re-runs", () => {
544
578
  const base = cv({
545
579
  variants: { color: { red: "red", blue: "blue" } },
546
- refine: ({ setDefaultVariants }) => {
547
- setDefaultVariants({ color: "blue" });
580
+ defaultVariants: {
581
+ color: () => "blue" as const,
548
582
  },
549
583
  });
550
584
  const component = getModeComponent(
@@ -563,20 +597,21 @@ for (const config of Object.values(CONFIGS)) {
563
597
  expect(getStyleClass(props)).toEqual({ class: cls("red") });
564
598
  });
565
599
 
566
- test("base refine setDefaultVariants can override child static defaults after a re-run", () => {
600
+ test("base computed defaultVariants can override child static defaults after a re-run", () => {
567
601
  const base = cv({
568
602
  variants: {
569
603
  size: { sm: "sm", lg: "lg" },
570
604
  active: "",
571
605
  mode: { on: "on" },
572
606
  },
573
- refine: ({ variants, setVariants, setDefaultVariants }) => {
607
+ defaultVariants: {
608
+ size: ({ defaultValue, variants }) =>
609
+ variants.mode === "on" ? "lg" : defaultValue,
610
+ },
611
+ refine: ({ variants, setVariants }) => {
574
612
  if (variants.active) {
575
613
  setVariants({ mode: "on" });
576
614
  }
577
- if (variants.mode === "on") {
578
- setDefaultVariants({ size: "lg" });
579
- }
580
615
  },
581
616
  });
582
617
  const component = getModeComponent(
@@ -587,7 +622,33 @@ for (const config of Object.values(CONFIGS)) {
587
622
  expect(getStyleClass(props)).toEqual({ class: cls("lg on") });
588
623
  });
589
624
 
590
- test("setVariants from earlier extends overrides setDefaultVariants from later extends", () => {
625
+ test("parent computed defaultVariants fall back to child defaults after a dependency changes", () => {
626
+ const layer = cv({
627
+ variants: {
628
+ a: { one: "one", two: "two" },
629
+ b: { true: "b-true", false: "b-false" },
630
+ },
631
+ defaultVariants: {
632
+ b: true,
633
+ a: ({ defaultValue, variants }) =>
634
+ variants.b ? "one" : defaultValue,
635
+ },
636
+ refine: ({ variants, setVariants }) => {
637
+ if (variants.b) {
638
+ setVariants({ b: false });
639
+ }
640
+ },
641
+ });
642
+ const component = getModeComponent(
643
+ mode,
644
+ cv({ extend: [layer], defaultVariants: { a: "two" } }),
645
+ );
646
+ const props = component();
647
+ expect(getStyleClass(props)).toEqual({ class: cls("two b-false") });
648
+ expect(component.getVariants()).toEqual({ a: "two", b: false });
649
+ });
650
+
651
+ test("setVariants from earlier extends overrides computed defaultVariants from later extends", () => {
591
652
  const first = cv({
592
653
  variants: { color: { red: "first-red", blue: "first-blue" } },
593
654
  refine: ({ setVariants }) => {
@@ -596,8 +657,8 @@ for (const config of Object.values(CONFIGS)) {
596
657
  });
597
658
  const second = cv({
598
659
  variants: { color: { red: "second-red", blue: "second-blue" } },
599
- refine: ({ setDefaultVariants }) => {
600
- setDefaultVariants({ color: "blue" });
660
+ defaultVariants: {
661
+ color: () => "blue" as const,
601
662
  },
602
663
  });
603
664
  const component = getModeComponent(mode, cv({ extend: [first, second] }));
@@ -607,17 +668,17 @@ for (const config of Object.values(CONFIGS)) {
607
668
  });
608
669
  });
609
670
 
610
- test("setDefaultVariants from later extends overrides setDefaultVariants from earlier extends", () => {
671
+ test("computed defaultVariants from later extends apply to final output", () => {
611
672
  const first = cv({
612
673
  variants: { color: { red: "first-red", blue: "first-blue" } },
613
- refine: ({ setDefaultVariants }) => {
614
- setDefaultVariants({ color: "red" });
674
+ defaultVariants: {
675
+ color: () => "red" as const,
615
676
  },
616
677
  });
617
678
  const second = cv({
618
679
  variants: { color: { red: "second-red", blue: "second-blue" } },
619
- refine: ({ setDefaultVariants }) => {
620
- setDefaultVariants({ color: "blue" });
680
+ defaultVariants: {
681
+ color: () => "blue" as const,
621
682
  },
622
683
  });
623
684
  const component = getModeComponent(mode, cv({ extend: [first, second] }));
@@ -627,7 +688,7 @@ for (const config of Object.values(CONFIGS)) {
627
688
  });
628
689
  });
629
690
 
630
- test("setDefaultVariants does not override stable setVariants on later passes", () => {
691
+ test("computed defaultVariants do not override stable setVariants on later passes", () => {
631
692
  const base = cv({
632
693
  variants: { color: { red: "base-red", blue: "base-blue" } },
633
694
  refine: ({ setVariants }) => {
@@ -639,10 +700,9 @@ for (const config of Object.values(CONFIGS)) {
639
700
  cv({
640
701
  extend: [base],
641
702
  variants: { color: { red: "child-red", blue: "child-blue" } },
642
- refine: ({ variants, setDefaultVariants }) => {
643
- if (variants.color === "red") {
644
- setDefaultVariants({ color: "blue" });
645
- }
703
+ defaultVariants: {
704
+ color: ({ defaultValue, variants }) =>
705
+ variants.color === "red" ? "blue" : defaultValue,
646
706
  },
647
707
  }),
648
708
  );
@@ -652,7 +712,7 @@ for (const config of Object.values(CONFIGS)) {
652
712
  });
653
713
  });
654
714
 
655
- test("setDefaultVariants does not override setVariants from a previous pass", () => {
715
+ test("computed defaultVariants do not override setVariants from a previous pass", () => {
656
716
  const component = getModeComponent(
657
717
  mode,
658
718
  cv({
@@ -660,13 +720,14 @@ for (const config of Object.values(CONFIGS)) {
660
720
  color: { red: "red", blue: "blue" },
661
721
  done: "",
662
722
  },
663
- refine: ({ variants, setVariants, setDefaultVariants }) => {
723
+ defaultVariants: {
724
+ color: ({ defaultValue, variants }) =>
725
+ variants.done ? "blue" : defaultValue,
726
+ },
727
+ refine: ({ variants, setVariants }) => {
664
728
  if (!variants.done) {
665
729
  setVariants({ color: "red", done: true });
666
730
  }
667
- if (variants.done) {
668
- setDefaultVariants({ color: "blue" });
669
- }
670
731
  },
671
732
  }),
672
733
  );
@@ -719,6 +780,11 @@ for (const config of Object.values(CONFIGS)) {
719
780
  /Variant\(s\) that did not stabilize: [^\n]*\bsize\b/,
720
781
  ),
721
782
  );
783
+ expect(warn).toHaveBeenCalledWith(
784
+ expect.stringMatching(
785
+ /Latest variant changes before warning: [^\n]*\bsize: "(sm|lg)" -> "(sm|lg)"/,
786
+ ),
787
+ );
722
788
  expect(warn).toHaveBeenCalledWith(
723
789
  expect.stringContaining("Component created at:"),
724
790
  );
@@ -750,6 +816,11 @@ for (const config of Object.values(CONFIGS)) {
750
816
  /Variant\(s\) that did not stabilize: [^\n]*\bsize\b/,
751
817
  ),
752
818
  );
819
+ expect(warn).toHaveBeenCalledWith(
820
+ expect.stringMatching(
821
+ /Latest variant changes before warning: [^\n]*\bsize: "(sm|lg)" -> "(sm|lg)"/,
822
+ ),
823
+ );
753
824
  expect(warn).toHaveBeenCalledWith(
754
825
  expect.stringContaining("Component created at:"),
755
826
  );
@@ -853,6 +924,11 @@ for (const config of Object.values(CONFIGS)) {
853
924
  /Variant\(s\) that did not stabilize: [^\n]*\bcolor\b/,
854
925
  ),
855
926
  );
927
+ expect(warn).toHaveBeenCalledWith(
928
+ expect.stringMatching(
929
+ /Latest variant changes before warning: [^\n]*\bsize\b[^\n]*\bcolor\b/,
930
+ ),
931
+ );
856
932
  } finally {
857
933
  warn.mockRestore();
858
934
  }
@@ -879,7 +955,50 @@ for (const config of Object.values(CONFIGS)) {
879
955
  expect(warn).toHaveBeenCalledWith(
880
956
  expect.stringContaining("refine.test.ts"),
881
957
  );
958
+ expect(warn).toHaveBeenCalledWith(
959
+ expect.not.stringContaining("node_modules"),
960
+ );
961
+ } finally {
962
+ warn.mockRestore();
963
+ }
964
+ });
965
+
966
+ test("refine warning fallback stack skips internal creation frames", () => {
967
+ const ErrorWithCaptureStackTrace = Error as ErrorConstructor & {
968
+ captureStackTrace?: (
969
+ targetObject: object,
970
+ constructorOpt?: Function,
971
+ ) => void;
972
+ };
973
+ const captureStackTrace = ErrorWithCaptureStackTrace.captureStackTrace;
974
+ Reflect.deleteProperty(ErrorWithCaptureStackTrace, "captureStackTrace");
975
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
976
+ const component = getModeComponent(
977
+ mode,
978
+ cv({
979
+ variants: { size: { sm: "sm", lg: "lg" } },
980
+ defaultVariants: { size: "sm" },
981
+ refine: ({ variants, setVariants }) => {
982
+ setVariants({ size: variants.size === "sm" ? "lg" : "sm" });
983
+ },
984
+ }),
985
+ );
986
+
987
+ try {
988
+ component();
989
+ expect(warn).toHaveBeenCalledWith(
990
+ expect.stringContaining("Component created at:"),
991
+ );
992
+ expect(warn).toHaveBeenCalledWith(
993
+ expect.stringContaining("refine.test.ts"),
994
+ );
995
+ expect(warn).toHaveBeenCalledWith(
996
+ expect.not.stringContaining("captureCreationFrame"),
997
+ );
882
998
  } finally {
999
+ if (captureStackTrace) {
1000
+ ErrorWithCaptureStackTrace.captureStackTrace = captureStackTrace;
1001
+ }
883
1002
  warn.mockRestore();
884
1003
  }
885
1004
  });
@@ -914,7 +1033,7 @@ for (const config of Object.values(CONFIGS)) {
914
1033
  }
915
1034
  });
916
1035
 
917
- test("refine setDefaultVariants when explicitly passing undefined", () => {
1036
+ test("computed defaultVariants run when explicitly passing undefined", () => {
918
1037
  const component = getModeComponent(
919
1038
  mode,
920
1039
  cv({
@@ -922,8 +1041,8 @@ for (const config of Object.values(CONFIGS)) {
922
1041
  size: { sm: "sm", lg: "lg" },
923
1042
  color: { red: "red", blue: "blue" },
924
1043
  },
925
- refine: ({ setDefaultVariants }) => {
926
- setDefaultVariants({ color: "red" });
1044
+ defaultVariants: {
1045
+ color: () => "red" as const,
927
1046
  },
928
1047
  }),
929
1048
  );