clava 0.5.0 → 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.
@@ -81,7 +81,7 @@ for (const config of Object.values(CONFIGS)) {
81
81
  },
82
82
  defaultVariants: {
83
83
  color: () => "red" as const,
84
- size: ({ defaultValue, variants }) =>
84
+ size: (defaultValue, variants) =>
85
85
  variants.color === "red" ? "lg" : defaultValue,
86
86
  },
87
87
  refine: ({ variants, addClass }) => {
@@ -98,7 +98,7 @@ for (const config of Object.values(CONFIGS)) {
98
98
  });
99
99
 
100
100
  test("refine converges with NaN computed defaultVariants", () => {
101
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
101
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
102
102
  const component = getModeComponent(
103
103
  mode,
104
104
  cv({
@@ -116,20 +116,16 @@ for (const config of Object.values(CONFIGS)) {
116
116
  }),
117
117
  );
118
118
 
119
- try {
120
- const props = component();
121
- expect(getStyleClass(props)).toEqual({
122
- class: cls("nan refine-nan"),
123
- });
124
- expect(component.getVariants()).toEqual({ value: Number.NaN });
125
- expect(warn).not.toHaveBeenCalled();
126
- } finally {
127
- warn.mockRestore();
128
- }
119
+ const props = component();
120
+ expect(getStyleClass(props)).toEqual({
121
+ class: cls("nan refine-nan"),
122
+ });
123
+ expect(component.getVariants()).toEqual({ value: Number.NaN });
124
+ expect(warn).not.toHaveBeenCalled();
129
125
  });
130
126
 
131
127
  test("computed defaultVariants can clear inherited defaults", () => {
132
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
128
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
133
129
  const base = cv({
134
130
  variants: {
135
131
  invert: { true: "invert" },
@@ -139,28 +135,24 @@ for (const config of Object.values(CONFIGS)) {
139
135
  value === undefined ? undefined : `push-${value}`,
140
136
  },
141
137
  defaultVariants: {
142
- offset: ({ variants }) => !variants.invert,
143
- push: ({ variants }) => (variants.invert ? 20 : undefined),
138
+ offset: (_, variants) => !variants.invert,
139
+ push: (_, variants) => (variants.invert ? 20 : undefined),
144
140
  },
145
141
  });
146
142
  const component = getModeComponent(mode, cv({ extend: [base] }));
147
143
 
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
- }
144
+ const props = component();
145
+ expect(getStyleClass(props)).toEqual({
146
+ class: cls("offset"),
147
+ });
148
+ expect(component.getVariants()).toEqual({
149
+ offset: true,
150
+ });
151
+ expect(warn).not.toHaveBeenCalled();
160
152
  });
161
153
 
162
154
  test("computed defaultVariants use inherited defaults as defaultValue", () => {
163
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
155
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
164
156
  const calls = {
165
157
  layer: 0,
166
158
  frame: 0,
@@ -177,11 +169,11 @@ for (const config of Object.values(CONFIGS)) {
177
169
  },
178
170
  defaultVariants: {
179
171
  layer: true,
180
- offset: ({ defaultValue, variants }) => {
172
+ offset: (defaultValue, variants) => {
181
173
  calls.layer += 1;
182
174
  return variants.invert ? false : defaultValue;
183
175
  },
184
- push: ({ variants }) => (variants.invert ? 20 : undefined),
176
+ push: (_, variants) => (variants.invert ? 20 : undefined),
185
177
  },
186
178
  });
187
179
  const frame = cv({
@@ -211,24 +203,20 @@ for (const config of Object.values(CONFIGS)) {
211
203
  });
212
204
  const component = getModeComponent(mode, cv({ extend: [control] }));
213
205
 
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
- }
206
+ const props = component();
207
+ expect(getStyleClass(props)).toEqual({
208
+ class: cls("layer offset frame control"),
209
+ });
210
+ expect(component.getVariants()).toEqual({
211
+ layer: true,
212
+ offset: true,
213
+ frame: true,
214
+ control: true,
215
+ });
216
+ expect(calls.layer).toBeGreaterThan(0);
217
+ expect(calls.frame).toBeGreaterThan(0);
218
+ expect(calls.control).toBeGreaterThan(0);
219
+ expect(warn).not.toHaveBeenCalled();
232
220
  });
233
221
 
234
222
  test("computed defaultVariants", () => {
@@ -240,7 +228,7 @@ for (const config of Object.values(CONFIGS)) {
240
228
  color: { red: "red", blue: "blue" },
241
229
  },
242
230
  defaultVariants: {
243
- color: ({ variants, defaultValue }) =>
231
+ color: (defaultValue, variants) =>
244
232
  variants.size === "lg" ? "red" : defaultValue,
245
233
  },
246
234
  }),
@@ -309,7 +297,7 @@ for (const config of Object.values(CONFIGS)) {
309
297
  const base = cv({
310
298
  variants: { size: { sm: "sm", lg: "lg" }, large: "" },
311
299
  defaultVariants: {
312
- size: ({ defaultValue, variants }) =>
300
+ size: (defaultValue, variants) =>
313
301
  variants.large ? "lg" : defaultValue,
314
302
  },
315
303
  });
@@ -329,7 +317,7 @@ for (const config of Object.values(CONFIGS)) {
329
317
  const parent = cv({
330
318
  variants: { size: { sm: "sm", lg: "lg" } },
331
319
  defaultVariants: {
332
- size: ({ defaultValue, variants }) =>
320
+ size: (defaultValue, variants) =>
333
321
  variants.size ? defaultValue : "lg",
334
322
  },
335
323
  });
@@ -373,7 +361,7 @@ for (const config of Object.values(CONFIGS)) {
373
361
  cv({
374
362
  extend: [base],
375
363
  defaultVariants: {
376
- size: ({ defaultValue }) => defaultValue,
364
+ size: (defaultValue) => defaultValue,
377
365
  },
378
366
  }),
379
367
  );
@@ -415,7 +403,7 @@ for (const config of Object.values(CONFIGS)) {
415
403
  const base = cv({
416
404
  variants: { size: { sm: "sm", lg: "lg" } },
417
405
  defaultVariants: {
418
- size: ({ defaultValue, variants }) =>
406
+ size: (defaultValue, variants) =>
419
407
  "color" in (variants as Record<string, unknown>)
420
408
  ? "lg"
421
409
  : defaultValue,
@@ -450,7 +438,7 @@ for (const config of Object.values(CONFIGS)) {
450
438
  extend: [base],
451
439
  variants: { color: { red: "red", blue: "blue" } },
452
440
  defaultVariants: {
453
- size: ({ defaultValue, variants }) =>
441
+ size: (defaultValue, variants) =>
454
442
  variants.small ? "sm" : defaultValue,
455
443
  color: "red",
456
444
  },
@@ -494,7 +482,7 @@ for (const config of Object.values(CONFIGS)) {
494
482
  mode: { on: "on" },
495
483
  },
496
484
  defaultVariants: {
497
- size: ({ defaultValue, variants }) =>
485
+ size: (defaultValue, variants) =>
498
486
  variants.mode === "on" ? "lg" : defaultValue,
499
487
  },
500
488
  refine: ({ variants, setVariants }) => {
@@ -605,7 +593,7 @@ for (const config of Object.values(CONFIGS)) {
605
593
  mode: { on: "on" },
606
594
  },
607
595
  defaultVariants: {
608
- size: ({ defaultValue, variants }) =>
596
+ size: (defaultValue, variants) =>
609
597
  variants.mode === "on" ? "lg" : defaultValue,
610
598
  },
611
599
  refine: ({ variants, setVariants }) => {
@@ -630,8 +618,7 @@ for (const config of Object.values(CONFIGS)) {
630
618
  },
631
619
  defaultVariants: {
632
620
  b: true,
633
- a: ({ defaultValue, variants }) =>
634
- variants.b ? "one" : defaultValue,
621
+ a: (defaultValue, variants) => (variants.b ? "one" : defaultValue),
635
622
  },
636
623
  refine: ({ variants, setVariants }) => {
637
624
  if (variants.b) {
@@ -701,7 +688,7 @@ for (const config of Object.values(CONFIGS)) {
701
688
  extend: [base],
702
689
  variants: { color: { red: "child-red", blue: "child-blue" } },
703
690
  defaultVariants: {
704
- color: ({ defaultValue, variants }) =>
691
+ color: (defaultValue, variants) =>
705
692
  variants.color === "red" ? "blue" : defaultValue,
706
693
  },
707
694
  }),
@@ -721,7 +708,7 @@ for (const config of Object.values(CONFIGS)) {
721
708
  done: "",
722
709
  },
723
710
  defaultVariants: {
724
- color: ({ defaultValue, variants }) =>
711
+ color: (defaultValue, variants) =>
725
712
  variants.done ? "blue" : defaultValue,
726
713
  },
727
714
  refine: ({ variants, setVariants }) => {
@@ -736,7 +723,7 @@ for (const config of Object.values(CONFIGS)) {
736
723
  });
737
724
 
738
725
  test("refine warns when variants keep changing", () => {
739
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
726
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
740
727
  const component = getModeComponent(
741
728
  mode,
742
729
  cv({
@@ -748,18 +735,14 @@ for (const config of Object.values(CONFIGS)) {
748
735
  }),
749
736
  );
750
737
 
751
- try {
752
- component();
753
- expect(warn).toHaveBeenCalledWith(
754
- expect.stringContaining("Maximum refine iterations exceeded"),
755
- );
756
- } finally {
757
- warn.mockRestore();
758
- }
738
+ component();
739
+ expect(warn).toHaveBeenCalledWith(
740
+ expect.stringContaining("Maximum refine iterations exceeded"),
741
+ );
759
742
  });
760
743
 
761
744
  test("refine warning is shared across extended components", () => {
762
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
745
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
763
746
  const base = cv({
764
747
  variants: { size: { sm: "sm", lg: "lg" } },
765
748
  defaultVariants: { size: "sm" },
@@ -769,32 +752,28 @@ for (const config of Object.values(CONFIGS)) {
769
752
  });
770
753
  const component = getModeComponent(mode, cv({ extend: [base] }));
771
754
 
772
- try {
773
- component();
774
- expect(warn).toHaveBeenCalledTimes(1);
775
- expect(warn).toHaveBeenCalledWith(
776
- expect.stringContaining("Maximum refine iterations exceeded"),
777
- );
778
- expect(warn).toHaveBeenCalledWith(
779
- expect.stringMatching(
780
- /Variant\(s\) that did not stabilize: [^\n]*\bsize\b/,
781
- ),
782
- );
783
- expect(warn).toHaveBeenCalledWith(
784
- expect.stringMatching(
785
- /Latest variant changes before warning: [^\n]*\bsize: "(sm|lg)" -> "(sm|lg)"/,
786
- ),
787
- );
788
- expect(warn).toHaveBeenCalledWith(
789
- expect.stringContaining("Component created at:"),
790
- );
791
- } finally {
792
- warn.mockRestore();
793
- }
755
+ component();
756
+ expect(warn).toHaveBeenCalledTimes(1);
757
+ expect(warn).toHaveBeenCalledWith(
758
+ expect.stringContaining("Maximum refine iterations exceeded"),
759
+ );
760
+ expect(warn).toHaveBeenCalledWith(
761
+ expect.stringMatching(
762
+ /Variant\(s\) that did not stabilize: [^\n]*\bsize\b/,
763
+ ),
764
+ );
765
+ expect(warn).toHaveBeenCalledWith(
766
+ expect.stringMatching(
767
+ /Latest variant changes before warning: [^\n]*\bsize: "(sm|lg)" -> "(sm|lg)"/,
768
+ ),
769
+ );
770
+ expect(warn).toHaveBeenCalledWith(
771
+ expect.stringContaining("Component created at:"),
772
+ );
794
773
  });
795
774
 
796
775
  test("getVariants warns when variants keep changing", () => {
797
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
776
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
798
777
  const component = getModeComponent(
799
778
  mode,
800
779
  cv({
@@ -806,31 +785,27 @@ for (const config of Object.values(CONFIGS)) {
806
785
  }),
807
786
  );
808
787
 
809
- try {
810
- component.getVariants();
811
- expect(warn).toHaveBeenCalledWith(
812
- expect.stringContaining("Maximum refine iterations exceeded"),
813
- );
814
- expect(warn).toHaveBeenCalledWith(
815
- expect.stringMatching(
816
- /Variant\(s\) that did not stabilize: [^\n]*\bsize\b/,
817
- ),
818
- );
819
- expect(warn).toHaveBeenCalledWith(
820
- expect.stringMatching(
821
- /Latest variant changes before warning: [^\n]*\bsize: "(sm|lg)" -> "(sm|lg)"/,
822
- ),
823
- );
824
- expect(warn).toHaveBeenCalledWith(
825
- expect.stringContaining("Component created at:"),
826
- );
827
- } finally {
828
- warn.mockRestore();
829
- }
788
+ component.getVariants();
789
+ expect(warn).toHaveBeenCalledWith(
790
+ expect.stringContaining("Maximum refine iterations exceeded"),
791
+ );
792
+ expect(warn).toHaveBeenCalledWith(
793
+ expect.stringMatching(
794
+ /Variant\(s\) that did not stabilize: [^\n]*\bsize\b/,
795
+ ),
796
+ );
797
+ expect(warn).toHaveBeenCalledWith(
798
+ expect.stringMatching(
799
+ /Latest variant changes before warning: [^\n]*\bsize: "(sm|lg)" -> "(sm|lg)"/,
800
+ ),
801
+ );
802
+ expect(warn).toHaveBeenCalledWith(
803
+ expect.stringContaining("Component created at:"),
804
+ );
830
805
  });
831
806
 
832
807
  test("refine warning is omitted in production", () => {
833
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
808
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
834
809
  vi.stubEnv("NODE_ENV", "production");
835
810
  const component = getModeComponent(
836
811
  mode,
@@ -848,12 +823,11 @@ for (const config of Object.values(CONFIGS)) {
848
823
  expect(warn).not.toHaveBeenCalled();
849
824
  } finally {
850
825
  vi.unstubAllEnvs();
851
- warn.mockRestore();
852
826
  }
853
827
  });
854
828
 
855
829
  test("refine warning names the variant key that did not stabilize", () => {
856
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
830
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
857
831
  const component = getModeComponent(
858
832
  mode,
859
833
  cv({
@@ -868,25 +842,21 @@ for (const config of Object.values(CONFIGS)) {
868
842
  }),
869
843
  );
870
844
 
871
- try {
872
- component();
873
- expect(warn).toHaveBeenCalledWith(
874
- expect.stringMatching(
875
- /Variant\(s\) that did not stabilize: [^\n]*\bsize\b/,
876
- ),
877
- );
878
- expect(warn).toHaveBeenCalledWith(
879
- expect.not.stringMatching(
880
- /Variant\(s\) that did not stabilize: [^\n]*\bcolor\b/,
881
- ),
882
- );
883
- } finally {
884
- warn.mockRestore();
885
- }
845
+ component();
846
+ expect(warn).toHaveBeenCalledWith(
847
+ expect.stringMatching(
848
+ /Variant\(s\) that did not stabilize: [^\n]*\bsize\b/,
849
+ ),
850
+ );
851
+ expect(warn).toHaveBeenCalledWith(
852
+ expect.not.stringMatching(
853
+ /Variant\(s\) that did not stabilize: [^\n]*\bcolor\b/,
854
+ ),
855
+ );
886
856
  });
887
857
 
888
858
  test("refine warning reports keys that oscillate at different cadences", () => {
889
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
859
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
890
860
  // `size` flips every iteration, `color` flips every other iteration, so
891
861
  // the final pair may agree on one of them — the warning must still name
892
862
  // both keys because each contributed to a transition.
@@ -912,30 +882,26 @@ for (const config of Object.values(CONFIGS)) {
912
882
  }),
913
883
  );
914
884
 
915
- try {
916
- component();
917
- expect(warn).toHaveBeenCalledWith(
918
- expect.stringMatching(
919
- /Variant\(s\) that did not stabilize: [^\n]*\bsize\b/,
920
- ),
921
- );
922
- expect(warn).toHaveBeenCalledWith(
923
- expect.stringMatching(
924
- /Variant\(s\) that did not stabilize: [^\n]*\bcolor\b/,
925
- ),
926
- );
927
- expect(warn).toHaveBeenCalledWith(
928
- expect.stringMatching(
929
- /Latest variant changes before warning: [^\n]*\bsize\b[^\n]*\bcolor\b/,
930
- ),
931
- );
932
- } finally {
933
- warn.mockRestore();
934
- }
885
+ component();
886
+ expect(warn).toHaveBeenCalledWith(
887
+ expect.stringMatching(
888
+ /Variant\(s\) that did not stabilize: [^\n]*\bsize\b/,
889
+ ),
890
+ );
891
+ expect(warn).toHaveBeenCalledWith(
892
+ expect.stringMatching(
893
+ /Variant\(s\) that did not stabilize: [^\n]*\bcolor\b/,
894
+ ),
895
+ );
896
+ expect(warn).toHaveBeenCalledWith(
897
+ expect.stringMatching(
898
+ /Latest variant changes before warning: [^\n]*\bsize\b[^\n]*\bcolor\b/,
899
+ ),
900
+ );
935
901
  });
936
902
 
937
903
  test("refine warning includes the component creation stack", () => {
938
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
904
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
939
905
  const component = getModeComponent(
940
906
  mode,
941
907
  cv({
@@ -947,20 +913,16 @@ for (const config of Object.values(CONFIGS)) {
947
913
  }),
948
914
  );
949
915
 
950
- try {
951
- component();
952
- expect(warn).toHaveBeenCalledWith(
953
- expect.stringContaining("Component created at:"),
954
- );
955
- expect(warn).toHaveBeenCalledWith(
956
- expect.stringContaining("refine.test.ts"),
957
- );
958
- expect(warn).toHaveBeenCalledWith(
959
- expect.not.stringContaining("node_modules"),
960
- );
961
- } finally {
962
- warn.mockRestore();
963
- }
916
+ component();
917
+ expect(warn).toHaveBeenCalledWith(
918
+ expect.stringContaining("Component created at:"),
919
+ );
920
+ expect(warn).toHaveBeenCalledWith(
921
+ expect.stringContaining("refine.test.ts"),
922
+ );
923
+ expect(warn).toHaveBeenCalledWith(
924
+ expect.not.stringContaining("node_modules"),
925
+ );
964
926
  });
965
927
 
966
928
  test("refine warning fallback stack skips internal creation frames", () => {
@@ -972,7 +934,7 @@ for (const config of Object.values(CONFIGS)) {
972
934
  };
973
935
  const captureStackTrace = ErrorWithCaptureStackTrace.captureStackTrace;
974
936
  Reflect.deleteProperty(ErrorWithCaptureStackTrace, "captureStackTrace");
975
- const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
937
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
976
938
  const component = getModeComponent(
977
939
  mode,
978
940
  cv({
@@ -999,17 +961,11 @@ for (const config of Object.values(CONFIGS)) {
999
961
  if (captureStackTrace) {
1000
962
  ErrorWithCaptureStackTrace.captureStackTrace = captureStackTrace;
1001
963
  }
1002
- warn.mockRestore();
1003
964
  }
1004
965
  });
1005
966
 
1006
967
  test("refine warning omits the creation stack when cv ran in production", () => {
1007
- let captured = "";
1008
- const warn = vi
1009
- .spyOn(console, "warn")
1010
- .mockImplementation((message: unknown) => {
1011
- captured = String(message);
1012
- });
968
+ using warn = vi.spyOn(console, "warn").mockImplementation(() => {});
1013
969
  vi.stubEnv("NODE_ENV", "production");
1014
970
  const component = getModeComponent(
1015
971
  mode,
@@ -1025,11 +981,11 @@ for (const config of Object.values(CONFIGS)) {
1025
981
  try {
1026
982
  vi.unstubAllEnvs();
1027
983
  component();
1028
- expect(captured).toContain("Maximum refine iterations exceeded");
1029
- expect(captured).not.toContain("Component created at:");
984
+ const message = String(warn.mock.calls.at(-1)?.[0]);
985
+ expect(message).toContain("Maximum refine iterations exceeded");
986
+ expect(message).not.toContain("Component created at:");
1030
987
  } finally {
1031
988
  vi.unstubAllEnvs();
1032
- warn.mockRestore();
1033
989
  }
1034
990
  });
1035
991
 
@@ -20,6 +20,25 @@ describe("variants type inference", () => {
20
20
  });
21
21
  });
22
22
 
23
+ test("method variant infers optional parameter type as prop type", () => {
24
+ const grid = cv({
25
+ variants: {
26
+ columns(value?: number) {
27
+ return `columns-${value}`;
28
+ },
29
+ },
30
+ });
31
+ expectTypeOf(grid.getVariants()).branded.toEqualTypeOf<{
32
+ columns?: number;
33
+ }>();
34
+ grid({ columns: 3 });
35
+ grid({ columns: undefined });
36
+ grid({
37
+ // @ts-expect-error string is not assignable to number
38
+ columns: "3",
39
+ });
40
+ });
41
+
23
42
  test("function variant infers union parameter type", () => {
24
43
  const button = cv({
25
44
  variants: {
@@ -182,7 +201,7 @@ describe("variants type inference", () => {
182
201
  color: { red: "r", blue: "b" },
183
202
  },
184
203
  defaultVariants: {
185
- size: ({ defaultValue, variants }) => {
204
+ size: (defaultValue, variants) => {
186
205
  expectTypeOf(defaultValue).toEqualTypeOf<number | undefined>();
187
206
  expectTypeOf(variants.color).toEqualTypeOf<
188
207
  "red" | "blue" | undefined
@@ -200,6 +219,37 @@ describe("variants type inference", () => {
200
219
  });
201
220
  });
202
221
 
222
+ test("computed defaultVariants method infers defaultValue and variants", () => {
223
+ cv({
224
+ variants: {
225
+ compact: { true: "compact", false: "" },
226
+ size(value?: number) {
227
+ return `s-${value}`;
228
+ },
229
+ },
230
+ defaultVariants: {
231
+ size(defaultValue, variants) {
232
+ expectTypeOf(defaultValue).toEqualTypeOf<number | undefined>();
233
+ expectTypeOf(variants.compact).toEqualTypeOf<boolean | undefined>();
234
+ return variants.compact ? 2 : defaultValue;
235
+ },
236
+ },
237
+ });
238
+ cv({
239
+ variants: {
240
+ size(value?: number) {
241
+ return `s-${value}`;
242
+ },
243
+ },
244
+ defaultVariants: {
245
+ // @ts-expect-error string is not assignable to number
246
+ size() {
247
+ return "10";
248
+ },
249
+ },
250
+ });
251
+ });
252
+
203
253
  test("function-valued defaultVariants must return the function", () => {
204
254
  cv({
205
255
  variants: {
@@ -268,6 +318,24 @@ describe("variants type inference", () => {
268
318
  });
269
319
  });
270
320
 
321
+ test("refine method infers context from method variants", () => {
322
+ cv({
323
+ variants: {
324
+ size(value?: number) {
325
+ return `s-${value}`;
326
+ },
327
+ },
328
+ refine({ variants, setVariants }) {
329
+ expectTypeOf(variants.size).toEqualTypeOf<number | undefined>();
330
+ setVariants({ size: 10 });
331
+ setVariants({
332
+ // @ts-expect-error string not assignable to number
333
+ size: "10",
334
+ });
335
+ },
336
+ });
337
+ });
338
+
271
339
  test("function variant return type accepts ClassValue and StyleClassValue", () => {
272
340
  cv({
273
341
  variants: {