clava 0.1.19 → 0.2.1
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 +39 -0
- package/dist/index.d.ts +13 -30
- package/dist/index.js +569 -370
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/perfs/component.bench.ts +233 -0
- package/src/index.ts +759 -609
- package/src/types.ts +13 -4
- package/src/utils.ts +100 -32
- package/tests/_utils.ts +176 -0
- package/tests/class-style-test.ts +341 -0
- package/tests/component-api-test.ts +214 -0
- package/tests/computed-test.ts +800 -0
- package/tests/computed-variants-test.ts +298 -0
- package/tests/extend-test.ts +301 -0
- package/{src/test-language-service.ts → tests/language-service-test.ts} +6 -2
- package/{src/test-react.ts → tests/react-test.ts} +3 -3
- package/{src/test-solid.ts → tests/solid-test.ts} +3 -5
- package/tests/split-props-test.ts +590 -0
- package/tests/variants-test.ts +380 -0
- package/tsconfig.json +1 -1
- package/src/test.ts +0 -2873
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { describe, expect, expectTypeOf, test } from "vitest";
|
|
2
|
+
import type {
|
|
3
|
+
HTMLCSSProperties,
|
|
4
|
+
JSXCSSProperties,
|
|
5
|
+
StyleClassProps,
|
|
6
|
+
StyleValue,
|
|
7
|
+
} from "../src/types.ts";
|
|
8
|
+
import {
|
|
9
|
+
CONFIGS,
|
|
10
|
+
assertDefaultProps,
|
|
11
|
+
assertHTMLObjProps,
|
|
12
|
+
assertHTMLProps,
|
|
13
|
+
assertJSXProps,
|
|
14
|
+
createCVFromConfig,
|
|
15
|
+
getConfigDescription,
|
|
16
|
+
getConfigMode,
|
|
17
|
+
getConfigTransformClass,
|
|
18
|
+
getModeComponent,
|
|
19
|
+
getStyleClass,
|
|
20
|
+
} from "./_utils.ts";
|
|
21
|
+
|
|
22
|
+
for (const config of [CONFIGS.default, CONFIGS.uppercase]) {
|
|
23
|
+
const mode = getConfigMode(config);
|
|
24
|
+
const cv = createCVFromConfig(config);
|
|
25
|
+
const cls = getConfigTransformClass(config);
|
|
26
|
+
|
|
27
|
+
describe(getConfigDescription(config), () => {
|
|
28
|
+
test("style has correct shape for mode", () => {
|
|
29
|
+
const component = getModeComponent(
|
|
30
|
+
mode,
|
|
31
|
+
cv({ class: "base", style: { backgroundColor: "red" } }),
|
|
32
|
+
);
|
|
33
|
+
const props = component();
|
|
34
|
+
assertDefaultProps(props);
|
|
35
|
+
expect(props).not.toHaveProperty("className");
|
|
36
|
+
expect(props.class).toBe(cls("base"));
|
|
37
|
+
expect(props.style.backgroundColor).toBe("red");
|
|
38
|
+
expectTypeOf(props).toEqualTypeOf<StyleClassProps>();
|
|
39
|
+
expectTypeOf(props.style).toEqualTypeOf<StyleValue>();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("no argument still returns normalized shape", () => {
|
|
43
|
+
const component = getModeComponent(mode, cv());
|
|
44
|
+
const props = component();
|
|
45
|
+
assertDefaultProps(props);
|
|
46
|
+
expect(props).not.toHaveProperty("className");
|
|
47
|
+
expect(props.class).toBe("");
|
|
48
|
+
expect(props.style).toEqual({});
|
|
49
|
+
expectTypeOf(props).toEqualTypeOf<StyleClassProps>();
|
|
50
|
+
expectTypeOf(props.style).toEqualTypeOf<StyleValue>();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
for (const config of [CONFIGS.jsx]) {
|
|
56
|
+
const mode = getConfigMode(config);
|
|
57
|
+
const cv = createCVFromConfig(config);
|
|
58
|
+
const cls = getConfigTransformClass(config);
|
|
59
|
+
|
|
60
|
+
describe(getConfigDescription(config), () => {
|
|
61
|
+
test("style has correct shape for mode", () => {
|
|
62
|
+
const component = getModeComponent(
|
|
63
|
+
mode,
|
|
64
|
+
cv({ class: "base", style: { backgroundColor: "red" } }),
|
|
65
|
+
);
|
|
66
|
+
const props = component();
|
|
67
|
+
assertJSXProps(props);
|
|
68
|
+
expect(props).not.toHaveProperty("class");
|
|
69
|
+
expect(props.className).toBe(cls("base"));
|
|
70
|
+
expect(props.style.backgroundColor).toBe("red");
|
|
71
|
+
expectTypeOf(props.style).toEqualTypeOf<JSXCSSProperties>();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("no argument still returns jsx shape", () => {
|
|
75
|
+
const component = getModeComponent(mode, cv());
|
|
76
|
+
const props = component();
|
|
77
|
+
assertJSXProps(props);
|
|
78
|
+
expect(props).not.toHaveProperty("class");
|
|
79
|
+
expect(props.className).toBe("");
|
|
80
|
+
expect(props.style).toEqual({});
|
|
81
|
+
expectTypeOf(props.style).toEqualTypeOf<JSXCSSProperties>();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
for (const config of [CONFIGS.html]) {
|
|
87
|
+
const mode = getConfigMode(config);
|
|
88
|
+
const cv = createCVFromConfig(config);
|
|
89
|
+
const cls = getConfigTransformClass(config);
|
|
90
|
+
|
|
91
|
+
describe(getConfigDescription(config), () => {
|
|
92
|
+
test("style has correct shape for mode", () => {
|
|
93
|
+
const component = getModeComponent(
|
|
94
|
+
mode,
|
|
95
|
+
cv({ class: "base", style: { backgroundColor: "red" } }),
|
|
96
|
+
);
|
|
97
|
+
const props = component();
|
|
98
|
+
assertHTMLProps(props);
|
|
99
|
+
expect(props).not.toHaveProperty("className");
|
|
100
|
+
expect(props.class).toBe(cls("base"));
|
|
101
|
+
expect(props.style).toBe("background-color: red;");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("no argument still returns html shape", () => {
|
|
105
|
+
const component = getModeComponent(mode, cv());
|
|
106
|
+
const props = component();
|
|
107
|
+
assertHTMLProps(props);
|
|
108
|
+
expect(props).not.toHaveProperty("className");
|
|
109
|
+
expect(props.class).toBe("");
|
|
110
|
+
expect(props.style).toBe("");
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
for (const config of [CONFIGS.htmlObj]) {
|
|
116
|
+
const mode = getConfigMode(config);
|
|
117
|
+
const cv = createCVFromConfig(config);
|
|
118
|
+
const cls = getConfigTransformClass(config);
|
|
119
|
+
|
|
120
|
+
describe(getConfigDescription(config), () => {
|
|
121
|
+
test("style has correct shape for mode", () => {
|
|
122
|
+
const component = getModeComponent(
|
|
123
|
+
mode,
|
|
124
|
+
cv({ class: "base", style: { backgroundColor: "red" } }),
|
|
125
|
+
);
|
|
126
|
+
const props = component();
|
|
127
|
+
assertHTMLObjProps(props);
|
|
128
|
+
expect(props).not.toHaveProperty("className");
|
|
129
|
+
expect(props.class).toBe(cls("base"));
|
|
130
|
+
expect(props.style["background-color"]).toBe("red");
|
|
131
|
+
expectTypeOf(props.style).toEqualTypeOf<HTMLCSSProperties>();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("no argument still returns htmlObj shape", () => {
|
|
135
|
+
const component = getModeComponent(mode, cv());
|
|
136
|
+
const props = component();
|
|
137
|
+
assertHTMLObjProps(props);
|
|
138
|
+
expect(props).not.toHaveProperty("className");
|
|
139
|
+
expect(props.class).toBe("");
|
|
140
|
+
expect(props.style).toEqual({});
|
|
141
|
+
expectTypeOf(props.style).toEqualTypeOf<HTMLCSSProperties>();
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
for (const config of Object.values(CONFIGS)) {
|
|
147
|
+
const mode = getConfigMode(config);
|
|
148
|
+
const cv = createCVFromConfig(config);
|
|
149
|
+
const cls = getConfigTransformClass(config);
|
|
150
|
+
|
|
151
|
+
describe(getConfigDescription(config), () => {
|
|
152
|
+
test("no argument", () => {
|
|
153
|
+
const component = getModeComponent(mode, cv());
|
|
154
|
+
const props = component();
|
|
155
|
+
expect(getStyleClass(props)).toEqual({ class: "" });
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("null class", () => {
|
|
159
|
+
const component = getModeComponent(mode, cv({ class: null }));
|
|
160
|
+
const props = component();
|
|
161
|
+
expect(getStyleClass(props)).toEqual({ class: "" });
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("empty array class", () => {
|
|
165
|
+
const component = getModeComponent(mode, cv({ class: [] }));
|
|
166
|
+
const props = component();
|
|
167
|
+
expect(getStyleClass(props)).toEqual({ class: "" });
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("string class", () => {
|
|
171
|
+
const component = getModeComponent(mode, cv({ class: "foo bar" }));
|
|
172
|
+
const props = component();
|
|
173
|
+
expect(getStyleClass(props)).toEqual({ class: cls("foo bar") });
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test("nested array class", () => {
|
|
177
|
+
const component = getModeComponent(
|
|
178
|
+
mode,
|
|
179
|
+
cv({ class: ["foo", ["bar", ["baz"]]] }),
|
|
180
|
+
);
|
|
181
|
+
const props = component();
|
|
182
|
+
expect(getStyleClass(props)).toEqual({ class: cls("foo bar baz") });
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test("nested array class with falsy values", () => {
|
|
186
|
+
const component = getModeComponent(
|
|
187
|
+
mode,
|
|
188
|
+
cv({ class: ["foo", null, ["bar", false, ["baz", 0]]] }),
|
|
189
|
+
);
|
|
190
|
+
const props = component();
|
|
191
|
+
expect(getStyleClass(props)).toEqual({ class: cls("foo bar baz") });
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test("merge class from props", () => {
|
|
195
|
+
const component = getModeComponent(mode, cv({ class: "foo bar" }));
|
|
196
|
+
const props = component({ class: "baz qux" });
|
|
197
|
+
expect(getStyleClass(props)).toEqual({ class: cls("foo bar baz qux") });
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("merge className from props", () => {
|
|
201
|
+
const component = getModeComponent(mode, cv({ class: "foo bar" }));
|
|
202
|
+
const props = component({ className: "baz qux" });
|
|
203
|
+
expect(getStyleClass(props)).toEqual({ class: cls("foo bar baz qux") });
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test("merge class and className from props", () => {
|
|
207
|
+
const component = getModeComponent(mode, cv({ class: "foo bar" }));
|
|
208
|
+
const props = component({ class: "baz qux", className: "quux corge" });
|
|
209
|
+
expect(getStyleClass(props)).toEqual({
|
|
210
|
+
class: cls("foo bar baz qux quux corge"),
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test("merge null class from props", () => {
|
|
215
|
+
const component = getModeComponent(mode, cv({ class: "foo bar" }));
|
|
216
|
+
const props = component({ class: null });
|
|
217
|
+
expect(getStyleClass(props)).toEqual({ class: cls("foo bar") });
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
test("merge null className from props", () => {
|
|
221
|
+
const component = getModeComponent(mode, cv({ class: "foo bar" }));
|
|
222
|
+
const props = component({ className: null });
|
|
223
|
+
expect(getStyleClass(props)).toEqual({ class: cls("foo bar") });
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test("empty style", () => {
|
|
227
|
+
const component = getModeComponent(mode, cv({ style: {} }));
|
|
228
|
+
const props = component();
|
|
229
|
+
expect(getStyleClass(props)).toEqual({ class: "" });
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test("style with properties", () => {
|
|
233
|
+
const component = getModeComponent(
|
|
234
|
+
mode,
|
|
235
|
+
cv({ style: { backgroundColor: "red", fontSize: "16px" } }),
|
|
236
|
+
);
|
|
237
|
+
const props = component();
|
|
238
|
+
expect(getStyleClass(props)).toEqual({
|
|
239
|
+
class: "",
|
|
240
|
+
backgroundColor: "red",
|
|
241
|
+
fontSize: "16px",
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test("style does not accept numbers", () => {
|
|
246
|
+
const component = getModeComponent(
|
|
247
|
+
mode,
|
|
248
|
+
cv({
|
|
249
|
+
style: {
|
|
250
|
+
backgroundColor: "red",
|
|
251
|
+
// @ts-expect-error
|
|
252
|
+
fontSize: 16,
|
|
253
|
+
},
|
|
254
|
+
}),
|
|
255
|
+
);
|
|
256
|
+
const props = component();
|
|
257
|
+
expect(getStyleClass(props)).toEqual({
|
|
258
|
+
class: "",
|
|
259
|
+
backgroundColor: "red",
|
|
260
|
+
fontSize: expect.toBeOneOf(["16", "16px"]),
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
test("style with custom property", () => {
|
|
265
|
+
const component = getModeComponent(
|
|
266
|
+
mode,
|
|
267
|
+
cv({ style: { backgroundColor: "red", "--custom-var": "value" } }),
|
|
268
|
+
);
|
|
269
|
+
const props = component();
|
|
270
|
+
expect(getStyleClass(props)).toEqual({
|
|
271
|
+
class: "",
|
|
272
|
+
backgroundColor: "red",
|
|
273
|
+
"--custom-var": "value",
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
test("merge style from props", () => {
|
|
278
|
+
const component = getModeComponent(
|
|
279
|
+
mode,
|
|
280
|
+
cv({ style: { backgroundColor: "red" } }),
|
|
281
|
+
);
|
|
282
|
+
const props = component({ style: { fontSize: "16px" } });
|
|
283
|
+
expect(getStyleClass(props)).toEqual({
|
|
284
|
+
class: "",
|
|
285
|
+
backgroundColor: "red",
|
|
286
|
+
fontSize: "16px",
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
test("merge jsx style from props", () => {
|
|
291
|
+
const component = getModeComponent(
|
|
292
|
+
mode,
|
|
293
|
+
cv({ style: { backgroundColor: "red" } }),
|
|
294
|
+
);
|
|
295
|
+
const props = component({ style: { fontSize: 16 } });
|
|
296
|
+
expect(getStyleClass(props)).toEqual({
|
|
297
|
+
class: "",
|
|
298
|
+
backgroundColor: "red",
|
|
299
|
+
fontSize: "16px",
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test("merge html style from props", () => {
|
|
304
|
+
const component = getModeComponent(
|
|
305
|
+
mode,
|
|
306
|
+
cv({ style: { backgroundColor: "red" } }),
|
|
307
|
+
);
|
|
308
|
+
const props = component({ style: "font-size: 16px" });
|
|
309
|
+
expect(getStyleClass(props)).toEqual({
|
|
310
|
+
class: "",
|
|
311
|
+
backgroundColor: "red",
|
|
312
|
+
fontSize: "16px",
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
test("merge htmlObj style from props", () => {
|
|
317
|
+
const component = getModeComponent(
|
|
318
|
+
mode,
|
|
319
|
+
cv({ style: { backgroundColor: "red" } }),
|
|
320
|
+
);
|
|
321
|
+
const props = component({ style: { "font-size": 16 } });
|
|
322
|
+
expect(getStyleClass(props)).toEqual({
|
|
323
|
+
class: "",
|
|
324
|
+
backgroundColor: "red",
|
|
325
|
+
fontSize: "16px",
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
test("merge null style from props", () => {
|
|
330
|
+
const component = getModeComponent(
|
|
331
|
+
mode,
|
|
332
|
+
cv({ style: { backgroundColor: "red" } }),
|
|
333
|
+
);
|
|
334
|
+
const props = component({ style: null });
|
|
335
|
+
expect(getStyleClass(props)).toEqual({
|
|
336
|
+
class: "",
|
|
337
|
+
backgroundColor: "red",
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { describe, expect, expectTypeOf, test } from "vitest";
|
|
2
|
+
import { type Variant, cv as cvBase } from "../src/index.ts";
|
|
3
|
+
import {
|
|
4
|
+
CONFIGS,
|
|
5
|
+
createCVFromConfig,
|
|
6
|
+
getConfigDescription,
|
|
7
|
+
getConfigMode,
|
|
8
|
+
getConfigTransformClass,
|
|
9
|
+
getExpectedPropsKeys,
|
|
10
|
+
getModeComponent,
|
|
11
|
+
getStyle,
|
|
12
|
+
} from "./_utils.ts";
|
|
13
|
+
|
|
14
|
+
for (const config of Object.values(CONFIGS)) {
|
|
15
|
+
const mode = getConfigMode(config);
|
|
16
|
+
const cv = createCVFromConfig(config);
|
|
17
|
+
const cls = getConfigTransformClass(config);
|
|
18
|
+
|
|
19
|
+
describe(getConfigDescription(config), () => {
|
|
20
|
+
test("class method", () => {
|
|
21
|
+
const component = getModeComponent(
|
|
22
|
+
mode,
|
|
23
|
+
cv({ class: "foo", variants: { size: { sm: "sm", lg: "lg" } } }),
|
|
24
|
+
);
|
|
25
|
+
const className = component.class({ size: "lg" });
|
|
26
|
+
expect(className).toBe(cls("foo lg"));
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("style method", () => {
|
|
30
|
+
const component = getModeComponent(
|
|
31
|
+
mode,
|
|
32
|
+
cv({ style: { backgroundColor: "red" } }),
|
|
33
|
+
);
|
|
34
|
+
const style = component.style();
|
|
35
|
+
expect(getStyle({ style })).toEqual({ backgroundColor: "red" });
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("getVariants returns variant values", () => {
|
|
39
|
+
const component = getModeComponent(
|
|
40
|
+
mode,
|
|
41
|
+
cv({
|
|
42
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
43
|
+
defaultVariants: { size: "sm" },
|
|
44
|
+
}),
|
|
45
|
+
);
|
|
46
|
+
const variants = component.getVariants({ size: "lg" });
|
|
47
|
+
expect(variants).toEqual({ size: "lg" });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("getVariants returns default variants", () => {
|
|
51
|
+
const component = getModeComponent(
|
|
52
|
+
mode,
|
|
53
|
+
cv({
|
|
54
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
55
|
+
defaultVariants: { size: "sm" },
|
|
56
|
+
}),
|
|
57
|
+
);
|
|
58
|
+
const variants = component.getVariants();
|
|
59
|
+
expect(variants).toEqual({ size: "sm" });
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("getVariants returns variants set by computed setVariants", () => {
|
|
63
|
+
const component = getModeComponent(
|
|
64
|
+
mode,
|
|
65
|
+
cv({
|
|
66
|
+
variants: {
|
|
67
|
+
size: { sm: "sm", lg: "lg" },
|
|
68
|
+
color: { red: "red", blue: "blue" },
|
|
69
|
+
},
|
|
70
|
+
computed: ({ variants, setVariants }) => {
|
|
71
|
+
if (variants.size === "lg") {
|
|
72
|
+
setVariants({ color: "red" });
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
}),
|
|
76
|
+
);
|
|
77
|
+
const variants = component.getVariants({ size: "lg" });
|
|
78
|
+
expect(variants).toEqual({ size: "lg", color: "red" });
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("getVariants returns variants set by computed setDefaultVariants", () => {
|
|
82
|
+
const component = getModeComponent(
|
|
83
|
+
mode,
|
|
84
|
+
cv({
|
|
85
|
+
variants: {
|
|
86
|
+
size: { sm: "sm", lg: "lg" },
|
|
87
|
+
color: { red: "red", blue: "blue" },
|
|
88
|
+
},
|
|
89
|
+
computed: ({ variants, setDefaultVariants }) => {
|
|
90
|
+
if (variants.size === "lg") {
|
|
91
|
+
setDefaultVariants({ color: "blue" });
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
}),
|
|
95
|
+
);
|
|
96
|
+
const variants = component.getVariants({ size: "lg" });
|
|
97
|
+
expect(variants).toEqual({ size: "lg", color: "blue" });
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test("getVariants setDefaultVariants does not override props", () => {
|
|
101
|
+
const component = getModeComponent(
|
|
102
|
+
mode,
|
|
103
|
+
cv({
|
|
104
|
+
variants: {
|
|
105
|
+
size: { sm: "sm", lg: "lg" },
|
|
106
|
+
color: { red: "red", blue: "blue" },
|
|
107
|
+
},
|
|
108
|
+
computed: ({ setDefaultVariants }) => {
|
|
109
|
+
setDefaultVariants({ color: "blue" });
|
|
110
|
+
},
|
|
111
|
+
}),
|
|
112
|
+
);
|
|
113
|
+
const variants = component.getVariants({ color: "red" });
|
|
114
|
+
expect(variants).toEqual({ color: "red" });
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("getVariants setVariants overrides props", () => {
|
|
118
|
+
const component = getModeComponent(
|
|
119
|
+
mode,
|
|
120
|
+
cv({
|
|
121
|
+
variants: {
|
|
122
|
+
size: { sm: "sm", lg: "lg" },
|
|
123
|
+
color: { red: "red", blue: "blue" },
|
|
124
|
+
},
|
|
125
|
+
computed: ({ setVariants }) => {
|
|
126
|
+
setVariants({ color: "blue" });
|
|
127
|
+
},
|
|
128
|
+
}),
|
|
129
|
+
);
|
|
130
|
+
const variants = component.getVariants({ color: "red" });
|
|
131
|
+
expect(variants).toEqual({ color: "blue" });
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("keys returns props keys", () => {
|
|
135
|
+
const component = getModeComponent(
|
|
136
|
+
mode,
|
|
137
|
+
cv({ variants: { size: { sm: "sm" }, color: { red: "red" } } }),
|
|
138
|
+
);
|
|
139
|
+
expectTypeOf(component.keys).toExtend<
|
|
140
|
+
("class" | "className" | "style" | "size" | "color")[]
|
|
141
|
+
>();
|
|
142
|
+
expect(component.keys).toEqual(
|
|
143
|
+
getExpectedPropsKeys(config, "size", "color"),
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("variantKeys property", () => {
|
|
148
|
+
const component = getModeComponent(
|
|
149
|
+
mode,
|
|
150
|
+
cv({
|
|
151
|
+
variants: { size: { sm: "sm" }, color: { red: "red" } },
|
|
152
|
+
}),
|
|
153
|
+
);
|
|
154
|
+
expectTypeOf(component.variantKeys).toEqualTypeOf<("size" | "color")[]>();
|
|
155
|
+
expect(component.variantKeys).toEqual(["size", "color"]);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("propKeys property", () => {
|
|
159
|
+
const component = getModeComponent(
|
|
160
|
+
mode,
|
|
161
|
+
cv({ variants: { size: { sm: "sm" }, color: { red: "red" } } }),
|
|
162
|
+
);
|
|
163
|
+
expectTypeOf(component.propKeys).toExtend<
|
|
164
|
+
("class" | "className" | "style" | "size" | "color")[]
|
|
165
|
+
>();
|
|
166
|
+
expect(component.propKeys).toEqual(
|
|
167
|
+
getExpectedPropsKeys(config, "size", "color"),
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test("propKeys on different modes", () => {
|
|
172
|
+
const component = getModeComponent(
|
|
173
|
+
mode,
|
|
174
|
+
cv({ variants: { size: { sm: "sm" } } }),
|
|
175
|
+
);
|
|
176
|
+
expect(component.propKeys).toEqual(getExpectedPropsKeys(config, "size"));
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
describe("Variant utility type", () => {
|
|
182
|
+
test("matches variant keys from another component", () => {
|
|
183
|
+
const base = cvBase({
|
|
184
|
+
variants: { foo: { sm: "foo-sm", lg: "foo-lg" } },
|
|
185
|
+
});
|
|
186
|
+
const component = cvBase({
|
|
187
|
+
extend: [base],
|
|
188
|
+
variants: {
|
|
189
|
+
bar: {
|
|
190
|
+
sm: "bar-sm",
|
|
191
|
+
lg: "bar-lg",
|
|
192
|
+
} satisfies Variant<typeof base, "foo">,
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
expect(component({ bar: "sm" }).class).toContain("bar-sm");
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("rejects invalid variant keys", () => {
|
|
199
|
+
const base = cvBase({
|
|
200
|
+
variants: { foo: { sm: "foo-sm", lg: "foo-lg" } },
|
|
201
|
+
});
|
|
202
|
+
cvBase({
|
|
203
|
+
extend: [base],
|
|
204
|
+
variants: {
|
|
205
|
+
bar: {
|
|
206
|
+
sm: "bar-sm",
|
|
207
|
+
lg: "bar-lg",
|
|
208
|
+
// @ts-expect-error
|
|
209
|
+
xl: "bar-xl",
|
|
210
|
+
} satisfies Variant<typeof base, "foo">,
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
});
|