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 +46 -0
- package/README.md +26 -15
- package/dist/index.d.ts +10 -3
- package/dist/index.js +302 -170
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +415 -338
- package/src/refine-warning.ts +161 -0
- package/src/types.ts +24 -2
- package/tests/build.test.ts +1 -0
- 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-warning.test.ts +28 -0
- package/tests/refine.test.ts +300 -181
- package/tests/variants-inference.test.ts +81 -0
package/tests/refine.test.ts
CHANGED
|
@@ -71,7 +71,7 @@ for (const config of Object.values(CONFIGS)) {
|
|
|
71
71
|
});
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
test("refine re-runs when
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
|
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
|
-
|
|
108
|
-
|
|
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("
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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("
|
|
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
|
-
|
|
156
|
-
|
|
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("
|
|
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: {
|
|
193
|
-
|
|
194
|
-
|
|
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("
|
|
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: {
|
|
225
|
-
|
|
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("
|
|
308
|
+
test("parent computed defaultVariants can depend on child defaults", () => {
|
|
242
309
|
const base = cv({
|
|
243
|
-
variants: { size: { sm: "sm", lg: "lg" },
|
|
244
|
-
defaultVariants: {
|
|
245
|
-
|
|
246
|
-
|
|
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(
|
|
324
|
+
const props = component();
|
|
259
325
|
expect(getStyleClass(props)).toEqual({ class: cls("lg red") });
|
|
260
326
|
});
|
|
261
327
|
|
|
262
|
-
test("
|
|
263
|
-
const
|
|
264
|
-
variants: { size: { sm: "sm", lg: "lg" }
|
|
265
|
-
defaultVariants: {
|
|
266
|
-
|
|
267
|
-
|
|
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
|
|
273
|
-
|
|
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("
|
|
339
|
+
expect(getStyleClass(props)).toEqual({ class: cls("sm") });
|
|
282
340
|
});
|
|
283
341
|
|
|
284
|
-
test("
|
|
342
|
+
test("child computed defaultVariants override parent computed defaultVariants", () => {
|
|
285
343
|
const base = cv({
|
|
286
|
-
variants: { size: { sm: "sm", lg: "lg" }
|
|
287
|
-
defaultVariants: {
|
|
288
|
-
|
|
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: [
|
|
352
|
+
extend: [base],
|
|
299
353
|
variants: { color: { red: "red", blue: "blue" } },
|
|
300
|
-
defaultVariants: {
|
|
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("
|
|
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
|
|
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: {
|
|
326
|
-
|
|
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
|
-
|
|
335
|
-
|
|
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
|
-
|
|
343
|
-
|
|
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("
|
|
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: {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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
|
|
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: ({
|
|
409
|
-
|
|
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: {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
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("
|
|
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: {
|
|
463
|
-
|
|
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
|
|
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
|
-
|
|
523
|
-
|
|
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
|
-
|
|
547
|
-
|
|
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
|
|
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
|
-
|
|
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("
|
|
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
|
-
|
|
600
|
-
|
|
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("
|
|
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
|
-
|
|
614
|
-
|
|
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
|
-
|
|
620
|
-
|
|
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("
|
|
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
|
-
|
|
643
|
-
|
|
644
|
-
|
|
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("
|
|
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
|
-
|
|
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("
|
|
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
|
-
|
|
926
|
-
|
|
1044
|
+
defaultVariants: {
|
|
1045
|
+
color: () => "red" as const,
|
|
927
1046
|
},
|
|
928
1047
|
}),
|
|
929
1048
|
);
|