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,298 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
CONFIGS,
|
|
4
|
+
createCVFromConfig,
|
|
5
|
+
getConfigDescription,
|
|
6
|
+
getConfigMode,
|
|
7
|
+
getConfigTransformClass,
|
|
8
|
+
getModeComponent,
|
|
9
|
+
getStyleClass,
|
|
10
|
+
} from "./_utils.ts";
|
|
11
|
+
|
|
12
|
+
for (const config of Object.values(CONFIGS)) {
|
|
13
|
+
const mode = getConfigMode(config);
|
|
14
|
+
const cv = createCVFromConfig(config);
|
|
15
|
+
const cls = getConfigTransformClass(config);
|
|
16
|
+
|
|
17
|
+
describe(getConfigDescription(config), () => {
|
|
18
|
+
test("computedVariants", () => {
|
|
19
|
+
const component = getModeComponent(
|
|
20
|
+
mode,
|
|
21
|
+
cv({
|
|
22
|
+
computedVariants: {
|
|
23
|
+
size: (value: "sm" | "lg") => (value === "sm" ? "small" : "large"),
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
const props = component({ size: "lg" });
|
|
28
|
+
expect(getStyleClass(props)).toEqual({ class: cls("large") });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("computedVariants with style", () => {
|
|
32
|
+
const component = getModeComponent(
|
|
33
|
+
mode,
|
|
34
|
+
cv({
|
|
35
|
+
computedVariants: {
|
|
36
|
+
size: (value: "sm" | "lg") => ({
|
|
37
|
+
class: value === "sm" ? "small" : "large",
|
|
38
|
+
style: { fontSize: value === "sm" ? "12px" : "16px" },
|
|
39
|
+
}),
|
|
40
|
+
},
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
const props = component({ size: "lg" });
|
|
44
|
+
expect(getStyleClass(props)).toEqual({
|
|
45
|
+
class: cls("large"),
|
|
46
|
+
fontSize: "16px",
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("computedVariants can return another component default result", () => {
|
|
51
|
+
const button = cv({
|
|
52
|
+
variants: {
|
|
53
|
+
size: {
|
|
54
|
+
sm: { class: "button-sm", style: { fontSize: "12px" } },
|
|
55
|
+
lg: { class: "button-lg", style: { fontSize: "16px" } },
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
const component = getModeComponent(
|
|
60
|
+
mode,
|
|
61
|
+
cv({
|
|
62
|
+
computedVariants: {
|
|
63
|
+
size: (value: "sm" | "lg") => {
|
|
64
|
+
return button({ size: value });
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
}),
|
|
68
|
+
);
|
|
69
|
+
const props = component({ size: "lg" });
|
|
70
|
+
expect(getStyleClass(props)).toEqual({
|
|
71
|
+
class: cls("button-lg"),
|
|
72
|
+
fontSize: "16px",
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("computedVariants overrides extended object variants", () => {
|
|
77
|
+
const base = cv({
|
|
78
|
+
variants: {
|
|
79
|
+
size: {
|
|
80
|
+
sm: { class: "base-sm", style: { fontSize: "12px" } },
|
|
81
|
+
lg: { class: "base-lg", style: { fontSize: "16px" } },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
const component = getModeComponent(
|
|
86
|
+
mode,
|
|
87
|
+
cv({
|
|
88
|
+
extend: [base],
|
|
89
|
+
computedVariants: {
|
|
90
|
+
size: (value: "sm" | "lg") => ({
|
|
91
|
+
class: value === "sm" ? "extended-sm" : "extended-lg",
|
|
92
|
+
style: {
|
|
93
|
+
backgroundColor: value === "sm" ? "lightgray" : "gray",
|
|
94
|
+
},
|
|
95
|
+
}),
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
const props = component({ size: "lg" });
|
|
100
|
+
expect(getStyleClass(props)).toEqual({
|
|
101
|
+
class: cls("extended-lg"),
|
|
102
|
+
backgroundColor: "gray",
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test("computedVariants overrides extended computedVariants", () => {
|
|
107
|
+
const base = cv({
|
|
108
|
+
computedVariants: {
|
|
109
|
+
size: (value: "sm" | "lg") => ({
|
|
110
|
+
class: value === "sm" ? "base-sm" : "base-lg",
|
|
111
|
+
style: { fontSize: value === "sm" ? "12px" : "16px" },
|
|
112
|
+
}),
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
const component = getModeComponent(
|
|
116
|
+
mode,
|
|
117
|
+
cv({
|
|
118
|
+
extend: [base],
|
|
119
|
+
computedVariants: {
|
|
120
|
+
size: (value: "sm" | "lg") => ({
|
|
121
|
+
class: value === "sm" ? "extended-sm" : "extended-lg",
|
|
122
|
+
style: {
|
|
123
|
+
backgroundColor: value === "sm" ? "lightgray" : "gray",
|
|
124
|
+
},
|
|
125
|
+
}),
|
|
126
|
+
},
|
|
127
|
+
}),
|
|
128
|
+
);
|
|
129
|
+
const props = component({ size: "lg" });
|
|
130
|
+
expect(getStyleClass(props)).toEqual({
|
|
131
|
+
class: cls("extended-lg"),
|
|
132
|
+
backgroundColor: "gray",
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("computedVariants style does not accept numbers", () => {
|
|
137
|
+
const component = getModeComponent(
|
|
138
|
+
mode,
|
|
139
|
+
cv({
|
|
140
|
+
computedVariants: {
|
|
141
|
+
// @ts-expect-error
|
|
142
|
+
size: (value: "sm" | "lg") => ({
|
|
143
|
+
class: value === "sm" ? "small" : "large",
|
|
144
|
+
style: { fontSize: value === "sm" ? 12 : 16 },
|
|
145
|
+
}),
|
|
146
|
+
},
|
|
147
|
+
}),
|
|
148
|
+
);
|
|
149
|
+
const props = component({ size: "lg" });
|
|
150
|
+
expect(getStyleClass(props)).toEqual({
|
|
151
|
+
class: cls("large"),
|
|
152
|
+
fontSize: expect.toBeOneOf(["16", "16px"]),
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("computedVariants changes extended boolean variant to string", () => {
|
|
157
|
+
const base = cv({
|
|
158
|
+
variants: { disabled: { true: "disabled", false: "enabled" } },
|
|
159
|
+
});
|
|
160
|
+
const component = getModeComponent(
|
|
161
|
+
mode,
|
|
162
|
+
cv({
|
|
163
|
+
extend: [base],
|
|
164
|
+
computedVariants: {
|
|
165
|
+
disabled: (value: "yes" | "no" | "maybe") => {
|
|
166
|
+
if (value === "yes") return "state-disabled";
|
|
167
|
+
if (value === "no") return "state-enabled";
|
|
168
|
+
return "state-pending";
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
}),
|
|
172
|
+
);
|
|
173
|
+
component({
|
|
174
|
+
// @ts-expect-error
|
|
175
|
+
disabled: true,
|
|
176
|
+
});
|
|
177
|
+
const props = component({ disabled: "maybe" });
|
|
178
|
+
expect(getStyleClass(props)).toEqual({ class: cls("state-pending") });
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("computedVariants changes extended string variant to boolean", () => {
|
|
182
|
+
const base = cv({ variants: { size: { sm: "sm", md: "md", lg: "lg" } } });
|
|
183
|
+
const component = getModeComponent(
|
|
184
|
+
mode,
|
|
185
|
+
cv({
|
|
186
|
+
extend: [base],
|
|
187
|
+
computedVariants: {
|
|
188
|
+
size: (value: boolean) => (value ? "size-large" : "size-small"),
|
|
189
|
+
},
|
|
190
|
+
}),
|
|
191
|
+
);
|
|
192
|
+
component({
|
|
193
|
+
// @ts-expect-error
|
|
194
|
+
size: "sm",
|
|
195
|
+
});
|
|
196
|
+
const propsTrue = component({ size: true });
|
|
197
|
+
expect(getStyleClass(propsTrue)).toEqual({ class: cls("size-large") });
|
|
198
|
+
const propsFalse = component({ size: false });
|
|
199
|
+
expect(getStyleClass(propsFalse)).toEqual({ class: cls("size-small") });
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test("computedVariants with number type", () => {
|
|
203
|
+
const component = getModeComponent(
|
|
204
|
+
mode,
|
|
205
|
+
cv({
|
|
206
|
+
computedVariants: {
|
|
207
|
+
columns: (value: number) => ({
|
|
208
|
+
class: `grid-cols-${value}`,
|
|
209
|
+
style: { "--grid-columns": `${value}` },
|
|
210
|
+
}),
|
|
211
|
+
},
|
|
212
|
+
}),
|
|
213
|
+
);
|
|
214
|
+
const props = component({ columns: 3 });
|
|
215
|
+
expect(getStyleClass(props)).toEqual({
|
|
216
|
+
class: cls("grid-cols-3"),
|
|
217
|
+
"--grid-columns": "3",
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test("computedVariants with number type returns dynamic styles", () => {
|
|
222
|
+
const component = getModeComponent(
|
|
223
|
+
mode,
|
|
224
|
+
cv({
|
|
225
|
+
computedVariants: {
|
|
226
|
+
gap: (value: number) => ({
|
|
227
|
+
style: { "--gap": `${value * 4}px` },
|
|
228
|
+
}),
|
|
229
|
+
padding: (value: number) => ({
|
|
230
|
+
style: {
|
|
231
|
+
"--padding-x": `${value}px`,
|
|
232
|
+
"--padding-y": `${value * 0.5}px`,
|
|
233
|
+
},
|
|
234
|
+
}),
|
|
235
|
+
},
|
|
236
|
+
}),
|
|
237
|
+
);
|
|
238
|
+
const props = component({ gap: 4, padding: 16 });
|
|
239
|
+
expect(getStyleClass(props)).toEqual({
|
|
240
|
+
class: "",
|
|
241
|
+
"--gap": "16px",
|
|
242
|
+
"--padding-x": "16px",
|
|
243
|
+
"--padding-y": "8px",
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test("computedVariants with nullable type", () => {
|
|
248
|
+
const component = getModeComponent(
|
|
249
|
+
mode,
|
|
250
|
+
cv({
|
|
251
|
+
computedVariants: {
|
|
252
|
+
color: (value: string | null) => ({
|
|
253
|
+
class: value ? `color-${value}` : "color-default",
|
|
254
|
+
style: { "--color": value ?? "inherit" },
|
|
255
|
+
}),
|
|
256
|
+
},
|
|
257
|
+
}),
|
|
258
|
+
);
|
|
259
|
+
const propsWithValue = component({ color: "red" });
|
|
260
|
+
expect(getStyleClass(propsWithValue)).toEqual({
|
|
261
|
+
class: cls("color-red"),
|
|
262
|
+
"--color": "red",
|
|
263
|
+
});
|
|
264
|
+
const propsWithNull = component({ color: null });
|
|
265
|
+
expect(getStyleClass(propsWithNull)).toEqual({
|
|
266
|
+
class: cls("color-default"),
|
|
267
|
+
"--color": "inherit",
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
test("computedVariants changes extended variant from string to number", () => {
|
|
272
|
+
const base = cv({
|
|
273
|
+
variants: { size: { sm: "text-sm", md: "text-md", lg: "text-lg" } },
|
|
274
|
+
});
|
|
275
|
+
const component = getModeComponent(
|
|
276
|
+
mode,
|
|
277
|
+
cv({
|
|
278
|
+
extend: [base],
|
|
279
|
+
computedVariants: {
|
|
280
|
+
size: (value: number) => ({
|
|
281
|
+
class: "text-custom",
|
|
282
|
+
style: { fontSize: `${value}px` },
|
|
283
|
+
}),
|
|
284
|
+
},
|
|
285
|
+
}),
|
|
286
|
+
);
|
|
287
|
+
component({
|
|
288
|
+
// @ts-expect-error
|
|
289
|
+
size: "sm",
|
|
290
|
+
});
|
|
291
|
+
const props = component({ size: 18 });
|
|
292
|
+
expect(getStyleClass(props)).toEqual({
|
|
293
|
+
class: cls("text-custom"),
|
|
294
|
+
fontSize: "18px",
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
CONFIGS,
|
|
4
|
+
createCVFromConfig,
|
|
5
|
+
getConfigDescription,
|
|
6
|
+
getConfigMode,
|
|
7
|
+
getConfigTransformClass,
|
|
8
|
+
getModeComponent,
|
|
9
|
+
getStyleClass,
|
|
10
|
+
} from "./_utils.ts";
|
|
11
|
+
|
|
12
|
+
for (const config of Object.values(CONFIGS)) {
|
|
13
|
+
const mode = getConfigMode(config);
|
|
14
|
+
const cv = createCVFromConfig(config);
|
|
15
|
+
const cls = getConfigTransformClass(config);
|
|
16
|
+
|
|
17
|
+
describe(getConfigDescription(config), () => {
|
|
18
|
+
test("extend single component", () => {
|
|
19
|
+
const base = cv({ class: "base", variants: { size: { sm: "sm" } } });
|
|
20
|
+
const component = getModeComponent(
|
|
21
|
+
mode,
|
|
22
|
+
cv({ extend: [base], class: "extended" }),
|
|
23
|
+
);
|
|
24
|
+
const props = component({ size: "sm" });
|
|
25
|
+
expect(getStyleClass(props)).toEqual({ class: cls("base extended sm") });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("extend multiple components", () => {
|
|
29
|
+
const base1 = cv({ class: "base1" });
|
|
30
|
+
const base2 = cv({ class: "base2" });
|
|
31
|
+
const component = getModeComponent(
|
|
32
|
+
mode,
|
|
33
|
+
cv({ extend: [base1, base2], class: "extended" }),
|
|
34
|
+
);
|
|
35
|
+
const props = component();
|
|
36
|
+
expect(getStyleClass(props)).toEqual({
|
|
37
|
+
class: cls("base1 base2 extended"),
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("extend with variant merging", () => {
|
|
42
|
+
const base = cv({ variants: { size: { sm: "base-sm", lg: "base-lg" } } });
|
|
43
|
+
const component = getModeComponent(
|
|
44
|
+
mode,
|
|
45
|
+
cv({ extend: [base], variants: { size: { sm: "extended-sm" } } }),
|
|
46
|
+
);
|
|
47
|
+
const props = component({ size: "sm" });
|
|
48
|
+
expect(getStyleClass(props)).toEqual({
|
|
49
|
+
class: cls("base-sm extended-sm"),
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("extend with variant merging setting base variant", () => {
|
|
54
|
+
const base = cv({ variants: { size: { sm: "base-sm", lg: "base-lg" } } });
|
|
55
|
+
const component = getModeComponent(
|
|
56
|
+
mode,
|
|
57
|
+
cv({
|
|
58
|
+
extend: [base],
|
|
59
|
+
variants: { size: { sm: "extended-sm" } },
|
|
60
|
+
}),
|
|
61
|
+
);
|
|
62
|
+
const props = component({ size: "lg" });
|
|
63
|
+
expect(getStyleClass(props)).toEqual({ class: cls("base-lg") });
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("extend can disable whole variant with null", () => {
|
|
67
|
+
const base = cv({
|
|
68
|
+
variants: { size: { sm: "base-sm", lg: "base-lg" } },
|
|
69
|
+
defaultVariants: { size: "sm" },
|
|
70
|
+
});
|
|
71
|
+
const component = getModeComponent(
|
|
72
|
+
mode,
|
|
73
|
+
cv({
|
|
74
|
+
extend: [base],
|
|
75
|
+
variants: { size: null },
|
|
76
|
+
defaultVariants: {
|
|
77
|
+
// @ts-expect-error disabled variant cannot be set
|
|
78
|
+
size:
|
|
79
|
+
// no error
|
|
80
|
+
"lg",
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
84
|
+
const props = component({
|
|
85
|
+
// @ts-expect-error disabled variant cannot be set
|
|
86
|
+
size:
|
|
87
|
+
// no error
|
|
88
|
+
"lg",
|
|
89
|
+
});
|
|
90
|
+
expect(getStyleClass(props)).toEqual({ class: "" });
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("extend can disable variant value with null", () => {
|
|
94
|
+
const base = cv({
|
|
95
|
+
variants: { size: { sm: "base-sm", lg: "base-lg" } },
|
|
96
|
+
defaultVariants: { size: "sm" },
|
|
97
|
+
});
|
|
98
|
+
const component = getModeComponent(
|
|
99
|
+
mode,
|
|
100
|
+
cv({
|
|
101
|
+
extend: [base],
|
|
102
|
+
variants: { size: { sm: null } },
|
|
103
|
+
defaultVariants: {
|
|
104
|
+
// @ts-expect-error disabled variant value cannot be set
|
|
105
|
+
size:
|
|
106
|
+
// no error
|
|
107
|
+
"sm",
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
|
+
);
|
|
111
|
+
const disabledProps = component({
|
|
112
|
+
// @ts-expect-error disabled variant value cannot be set
|
|
113
|
+
size:
|
|
114
|
+
// no error
|
|
115
|
+
"sm",
|
|
116
|
+
});
|
|
117
|
+
expect(getStyleClass(disabledProps)).toEqual({ class: "" });
|
|
118
|
+
const enabledProps = component({ size: "lg" });
|
|
119
|
+
expect(getStyleClass(enabledProps)).toEqual({ class: cls("base-lg") });
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("extend disabled variant value accepts valid defaultVariants", () => {
|
|
123
|
+
const base = cv({
|
|
124
|
+
variants: {
|
|
125
|
+
size: {
|
|
126
|
+
sm: { class: "base-sm", style: { fontSize: "12px" } },
|
|
127
|
+
lg: { class: "base-lg", style: { fontSize: "16px" } },
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
const component = getModeComponent(
|
|
132
|
+
mode,
|
|
133
|
+
cv({
|
|
134
|
+
extend: [base],
|
|
135
|
+
variants: { size: { sm: null } },
|
|
136
|
+
defaultVariants: { size: "lg" },
|
|
137
|
+
}),
|
|
138
|
+
);
|
|
139
|
+
const props = component();
|
|
140
|
+
expect(getStyleClass(props)).toEqual({
|
|
141
|
+
class: cls("base-lg"),
|
|
142
|
+
fontSize: "16px",
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test("extend disabled variant value with computed setDefaultVariants", () => {
|
|
147
|
+
const base = cv({
|
|
148
|
+
variants: {
|
|
149
|
+
size: {
|
|
150
|
+
sm: { class: "base-sm", style: { fontSize: "12px" } },
|
|
151
|
+
lg: { class: "base-lg", style: { fontSize: "16px" } },
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
const validComponent = getModeComponent(
|
|
156
|
+
mode,
|
|
157
|
+
cv({
|
|
158
|
+
extend: [base],
|
|
159
|
+
variants: { size: { sm: null } },
|
|
160
|
+
computed: ({ setDefaultVariants }) => {
|
|
161
|
+
setDefaultVariants({ size: "lg" });
|
|
162
|
+
},
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
165
|
+
expect(getStyleClass(validComponent())).toEqual({
|
|
166
|
+
class: cls("base-lg"),
|
|
167
|
+
fontSize: "16px",
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const invalidComponent = getModeComponent(
|
|
171
|
+
mode,
|
|
172
|
+
cv({
|
|
173
|
+
extend: [base],
|
|
174
|
+
variants: { size: { sm: null } },
|
|
175
|
+
computed: ({ setDefaultVariants }) => {
|
|
176
|
+
setDefaultVariants({
|
|
177
|
+
// @ts-expect-error disabled variant value cannot be set
|
|
178
|
+
size:
|
|
179
|
+
// no error
|
|
180
|
+
"sm",
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
}),
|
|
184
|
+
);
|
|
185
|
+
expect(getStyleClass(invalidComponent())).toEqual({ class: "" });
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test("extend disabled variant value with computed setVariants", () => {
|
|
189
|
+
const base = cv({
|
|
190
|
+
variants: {
|
|
191
|
+
size: {
|
|
192
|
+
sm: { class: "base-sm", style: { fontSize: "12px" } },
|
|
193
|
+
lg: { class: "base-lg", style: { fontSize: "16px" } },
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
const validComponent = getModeComponent(
|
|
198
|
+
mode,
|
|
199
|
+
cv({
|
|
200
|
+
extend: [base],
|
|
201
|
+
variants: { size: { sm: null } },
|
|
202
|
+
computed: ({ setVariants }) => {
|
|
203
|
+
setVariants({ size: "lg" });
|
|
204
|
+
},
|
|
205
|
+
}),
|
|
206
|
+
);
|
|
207
|
+
expect(getStyleClass(validComponent())).toEqual({
|
|
208
|
+
class: cls("base-lg"),
|
|
209
|
+
fontSize: "16px",
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const invalidComponent = getModeComponent(
|
|
213
|
+
mode,
|
|
214
|
+
cv({
|
|
215
|
+
extend: [base],
|
|
216
|
+
variants: { size: { sm: null } },
|
|
217
|
+
computed: ({ setVariants }) => {
|
|
218
|
+
setVariants({
|
|
219
|
+
// @ts-expect-error disabled variant value cannot be set
|
|
220
|
+
size:
|
|
221
|
+
// no error
|
|
222
|
+
"sm",
|
|
223
|
+
});
|
|
224
|
+
},
|
|
225
|
+
}),
|
|
226
|
+
);
|
|
227
|
+
expect(getStyleClass(invalidComponent())).toEqual({ class: "" });
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
test("extend inherits defaultVariants", () => {
|
|
231
|
+
const base = cv({
|
|
232
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
233
|
+
defaultVariants: { size: "sm" },
|
|
234
|
+
});
|
|
235
|
+
const component = getModeComponent(mode, cv({ extend: [base] }));
|
|
236
|
+
const props = component();
|
|
237
|
+
expect(getStyleClass(props)).toEqual({ class: cls("sm") });
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
test("extend override defaultVariants", () => {
|
|
241
|
+
const base = cv({
|
|
242
|
+
variants: { size: { sm: "sm", lg: "lg" } },
|
|
243
|
+
defaultVariants: { size: "sm" },
|
|
244
|
+
});
|
|
245
|
+
const component = getModeComponent(
|
|
246
|
+
mode,
|
|
247
|
+
cv({ extend: [base], defaultVariants: { size: "lg" } }),
|
|
248
|
+
);
|
|
249
|
+
const props = component();
|
|
250
|
+
expect(getStyleClass(props)).toEqual({ class: cls("lg") });
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
test("extend jsx modal component preserves style", () => {
|
|
254
|
+
const base = cv({
|
|
255
|
+
class: "base",
|
|
256
|
+
style: { backgroundColor: "red" },
|
|
257
|
+
});
|
|
258
|
+
const component = getModeComponent(
|
|
259
|
+
mode,
|
|
260
|
+
cv({ extend: [base.jsx], class: "extended" }),
|
|
261
|
+
);
|
|
262
|
+
const props = component();
|
|
263
|
+
expect(getStyleClass(props)).toEqual({
|
|
264
|
+
class: cls("base extended"),
|
|
265
|
+
backgroundColor: "red",
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
test("extend html modal component preserves style", () => {
|
|
270
|
+
const base = cv({
|
|
271
|
+
class: "base",
|
|
272
|
+
style: { backgroundColor: "red" },
|
|
273
|
+
});
|
|
274
|
+
const component = getModeComponent(
|
|
275
|
+
mode,
|
|
276
|
+
cv({ extend: [base.html], class: "extended" }),
|
|
277
|
+
);
|
|
278
|
+
const props = component();
|
|
279
|
+
expect(getStyleClass(props)).toEqual({
|
|
280
|
+
class: cls("base extended"),
|
|
281
|
+
backgroundColor: "red",
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
test("extend htmlObj modal component preserves style", () => {
|
|
286
|
+
const base = cv({
|
|
287
|
+
class: "base",
|
|
288
|
+
style: { backgroundColor: "red" },
|
|
289
|
+
});
|
|
290
|
+
const component = getModeComponent(
|
|
291
|
+
mode,
|
|
292
|
+
cv({ extend: [base.htmlObj], class: "extended" }),
|
|
293
|
+
);
|
|
294
|
+
const props = component();
|
|
295
|
+
expect(getStyleClass(props)).toEqual({
|
|
296
|
+
class: cls("base extended"),
|
|
297
|
+
backgroundColor: "red",
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
}
|
|
@@ -10,8 +10,9 @@ import { fileURLToPath } from "node:url";
|
|
|
10
10
|
import ts from "typescript";
|
|
11
11
|
import { afterEach, describe, expect, test } from "vitest";
|
|
12
12
|
|
|
13
|
-
const
|
|
14
|
-
const packageDir = resolve(
|
|
13
|
+
const testDir = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const packageDir = resolve(testDir, "..");
|
|
15
|
+
const sourceDir = resolve(packageDir, "src");
|
|
15
16
|
const workspaceDir = resolve(packageDir, "../..");
|
|
16
17
|
const tempDirs: string[] = [];
|
|
17
18
|
|
|
@@ -26,6 +27,9 @@ function createCompilerOptions(): ts.CompilerOptions {
|
|
|
26
27
|
target: ts.ScriptTarget.ES2020,
|
|
27
28
|
module: ts.ModuleKind.NodeNext,
|
|
28
29
|
moduleResolution: ts.ModuleResolutionKind.NodeNext,
|
|
30
|
+
// Match the repo's Node-aware TS environment so language-service
|
|
31
|
+
// navigation in the fixture reflects real editor behavior.
|
|
32
|
+
types: ["node"],
|
|
29
33
|
allowImportingTsExtensions: true,
|
|
30
34
|
strict: true,
|
|
31
35
|
skipLibCheck: true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CSSProperties, ComponentProps } from "react";
|
|
2
2
|
import { expect, expectTypeOf, test } from "vitest";
|
|
3
|
-
import { type VariantProps, cv, splitProps } from "
|
|
4
|
-
import type { JSXProps } from "
|
|
3
|
+
import { type VariantProps, cv, splitProps } from "../src/index.ts";
|
|
4
|
+
import type { JSXProps } from "../src/types.ts";
|
|
5
5
|
|
|
6
6
|
test("splitProps", () => {
|
|
7
7
|
const component = cv({ variants: { size: { sm: "sm", md: "md" } } });
|
|
@@ -30,7 +30,7 @@ test("component props", () => {
|
|
|
30
30
|
const component = cv({
|
|
31
31
|
style: { fontSize: "16px" },
|
|
32
32
|
variants: { size: { sm: "sm", md: "md" } },
|
|
33
|
-
});
|
|
33
|
+
}).jsx;
|
|
34
34
|
const props = component({ size: "sm", className: "custom" });
|
|
35
35
|
expectTypeOf(props).toEqualTypeOf<JSXProps>();
|
|
36
36
|
expect(props).toEqual({
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { ComponentProps, JSX } from "solid-js";
|
|
2
2
|
import { expect, expectTypeOf, test } from "vitest";
|
|
3
|
-
import { type VariantProps,
|
|
4
|
-
import { type HTMLObjProps } from "
|
|
5
|
-
|
|
6
|
-
const { cv } = create({ defaultMode: "htmlObj" });
|
|
3
|
+
import { type VariantProps, cv, splitProps } from "../src/index.ts";
|
|
4
|
+
import { type HTMLObjProps } from "../src/types.ts";
|
|
7
5
|
|
|
8
6
|
test("splitProps", () => {
|
|
9
7
|
const component = cv({ variants: { size: { sm: "sm", md: "md" } } });
|
|
@@ -26,7 +24,7 @@ test("component props", () => {
|
|
|
26
24
|
const component = cv({
|
|
27
25
|
style: { fontSize: "16px" },
|
|
28
26
|
variants: { size: { sm: "sm", md: "md" } },
|
|
29
|
-
});
|
|
27
|
+
}).htmlObj;
|
|
30
28
|
const props = component({ size: "sm", className: "custom" });
|
|
31
29
|
expectTypeOf(props).toEqualTypeOf<HTMLObjProps>();
|
|
32
30
|
expect(props).toEqual({
|