@yak/react 0.0.0-stage → 10.0.0-rc.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/LICENSE +21 -0
- package/README.md +114 -2
- package/dist/context/baseContext.d.ts +5 -0
- package/dist/context/baseContext.js +8 -0
- package/dist/context/baseContext.js.map +1 -0
- package/dist/context/index.d.ts +20 -0
- package/dist/context/index.js +15 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/index.server.d.ts +9 -0
- package/dist/context/index.server.js +17 -0
- package/dist/context/index.server.js.map +1 -0
- package/dist/cross-file-resolver/index.d.ts +199 -0
- package/dist/cross-file-resolver/index.js +569 -0
- package/dist/cross-file-resolver/index.js.map +1 -0
- package/dist/index.d.ts +320 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +452 -0
- package/dist/internal.js +363 -0
- package/dist/internal.js.map +1 -0
- package/dist/isolated-source-eval/index.d.ts +30 -0
- package/dist/isolated-source-eval/index.js +317 -0
- package/dist/isolated-source-eval/index.js.map +1 -0
- package/dist/isolated-source-eval/worker.js +59 -0
- package/dist/isolated-source-eval/worker.js.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +7 -0
- package/dist/jsx-dev-runtime.js +2 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.d.ts +38 -0
- package/dist/jsx-runtime.js +2 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/loaders/turbo-loader.d.ts +15 -0
- package/dist/loaders/turbo-loader.js +816 -0
- package/dist/loaders/turbo-loader.js.map +1 -0
- package/dist/loaders/vite-plugin.d.ts +103 -0
- package/dist/loaders/vite-plugin.js +885 -0
- package/dist/loaders/vite-plugin.js.map +1 -0
- package/dist/loaders/webpack-loader.d.ts +12 -0
- package/dist/loaders/webpack-loader.js +710 -0
- package/dist/loaders/webpack-loader.js.map +1 -0
- package/dist/rsbuild/index.d.ts +29 -0
- package/dist/rsbuild/index.js +51 -0
- package/dist/rsbuild/index.js.map +1 -0
- package/dist/static/chunk-DK3Fl9T5.js +1 -0
- package/dist/static/index.d.ts +28 -0
- package/dist/static/index.js +2 -0
- package/dist/static/index.js.map +1 -0
- package/dist/withYak/index.d.ts +112 -0
- package/dist/withYak/index.js +171 -0
- package/dist/withYak/index.js.map +1 -0
- package/loaders/lib/resolveCrossFileSelectors.ts +161 -0
- package/loaders/turbo-evaluator.ts +134 -0
- package/loaders/turbo-loader.ts +184 -0
- package/loaders/vite-plugin.ts +28 -0
- package/loaders/webpack-loader.ts +41 -0
- package/package.json +155 -3
- package/rsbuild/index.ts +91 -0
- package/runtime/__tests__/atoms.test.tsx +48 -0
- package/runtime/__tests__/attrs.test.tsx +490 -0
- package/runtime/__tests__/cssLiteral.test.tsx +503 -0
- package/runtime/__tests__/cssProp.test.tsx +392 -0
- package/runtime/__tests__/cssPropTest.tsx +227 -0
- package/runtime/__tests__/foldedJsxParity.test.tsx +117 -0
- package/runtime/__tests__/styled.test.tsx +653 -0
- package/runtime/__tests__/tsconfig.json +18 -0
- package/runtime/__tests__/typeTest.tsx +374 -0
- package/runtime/atoms.tsx +36 -0
- package/runtime/context/README.md +84 -0
- package/runtime/context/baseContext.tsx +5 -0
- package/runtime/context/index.server.tsx +22 -0
- package/runtime/context/index.tsx +36 -0
- package/runtime/cssLiteral.tsx +214 -0
- package/runtime/globalStyle.tsx +54 -0
- package/runtime/index.ts +37 -0
- package/runtime/internal.ts +42 -0
- package/runtime/internals/mergeClassNames.ts +23 -0
- package/runtime/internals/mergeCssProp.ts +69 -0
- package/runtime/internals/propMarkers.ts +20 -0
- package/runtime/internals/unitPostFix.ts +34 -0
- package/runtime/jsx-dev-runtime.ts +6 -0
- package/runtime/jsx-runtime.ts +48 -0
- package/runtime/keyframes.tsx +30 -0
- package/runtime/mocks/cssLiteral.ts +74 -0
- package/runtime/mocks/globalStyle.ts +14 -0
- package/runtime/mocks/keyframes.ts +29 -0
- package/runtime/mocks/styled.ts +8 -0
- package/runtime/publicStyledApi.ts +159 -0
- package/runtime/styled.tsx +372 -0
- package/runtime/styledDom.tsx +139 -0
- package/withYak/allow-global-css.ts +94 -0
- package/withYak/index.ts +268 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { it, expect, describe, beforeEach, afterEach } from "vitest";
|
|
3
|
+
import { mergeCssProp } from "../internals/mergeCssProp";
|
|
4
|
+
import { css } from "../cssLiteral";
|
|
5
|
+
import { atoms } from "../atoms";
|
|
6
|
+
|
|
7
|
+
it("forwards foreign props alongside the merged className", async () => {
|
|
8
|
+
const onClick = () => {};
|
|
9
|
+
const result = mergeCssProp(css("yakCss1"), {
|
|
10
|
+
onClick,
|
|
11
|
+
"aria-label": "Save",
|
|
12
|
+
disabled: true,
|
|
13
|
+
className: "btn",
|
|
14
|
+
});
|
|
15
|
+
// toEqual (not toMatchObject) also pins that no stray keys leak, e.g. an empty style
|
|
16
|
+
expect(result).toEqual({
|
|
17
|
+
onClick,
|
|
18
|
+
"aria-label": "Save",
|
|
19
|
+
disabled: true,
|
|
20
|
+
className: "btn yakCss1",
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("merge properties when className is set", async () => {
|
|
25
|
+
expect(
|
|
26
|
+
mergeCssProp(
|
|
27
|
+
css("yakCss1", () => ({
|
|
28
|
+
style: { "--yak-var1": "0.5rem" },
|
|
29
|
+
})),
|
|
30
|
+
{ className: "btn btn-primary" },
|
|
31
|
+
),
|
|
32
|
+
).toMatchObject({
|
|
33
|
+
className: "btn btn-primary yakCss1",
|
|
34
|
+
style: { "--yak-var1": "0.5rem" },
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("merge properties when style is set", async () => {
|
|
39
|
+
expect(
|
|
40
|
+
mergeCssProp(
|
|
41
|
+
css(() => ({
|
|
42
|
+
className: "yakClass1",
|
|
43
|
+
style: { "--yak-var1": "#ffffff" },
|
|
44
|
+
})),
|
|
45
|
+
{ style: { padding: "8px", margin: "4px" } },
|
|
46
|
+
),
|
|
47
|
+
).toMatchObject({
|
|
48
|
+
className: "yakClass1",
|
|
49
|
+
style: { padding: "8px", margin: "4px", "--yak-var1": "#ffffff" },
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("merge properties when spreaded property is set", async () => {
|
|
54
|
+
expect(
|
|
55
|
+
mergeCssProp(
|
|
56
|
+
css(() => ({
|
|
57
|
+
className: "yakClass1 yakClass2",
|
|
58
|
+
style: { "--yak-var1": "1200px" },
|
|
59
|
+
})),
|
|
60
|
+
{ className: "container mx-auto" },
|
|
61
|
+
),
|
|
62
|
+
).toMatchObject({
|
|
63
|
+
className: "container mx-auto yakClass1 yakClass2",
|
|
64
|
+
style: { "--yak-var1": "1200px" },
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("merge properties when class name and style is set", async () => {
|
|
69
|
+
expect(
|
|
70
|
+
mergeCssProp(
|
|
71
|
+
css(() => ({
|
|
72
|
+
className: "yakClass1 yakClass2",
|
|
73
|
+
style: { "--yak-var1": "#1f2937" },
|
|
74
|
+
})),
|
|
75
|
+
{ className: "text-lg font-semibold", style: { lineHeight: "1.6" } },
|
|
76
|
+
),
|
|
77
|
+
).toMatchObject({
|
|
78
|
+
className: "text-lg font-semibold yakClass1 yakClass2",
|
|
79
|
+
style: { lineHeight: "1.6", "--yak-var1": "#1f2937" },
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("merge properties when class name, style and spreaded property is set", async () => {
|
|
84
|
+
expect(
|
|
85
|
+
mergeCssProp(
|
|
86
|
+
css(() => ({
|
|
87
|
+
className: "yakClass1 yakClass2",
|
|
88
|
+
style: { "--yak-var1": "4rem" },
|
|
89
|
+
})),
|
|
90
|
+
{ className: "flex items-center", style: { gap: "1rem" } },
|
|
91
|
+
),
|
|
92
|
+
).toMatchObject({
|
|
93
|
+
className: "flex items-center yakClass1 yakClass2",
|
|
94
|
+
style: { gap: "1rem", "--yak-var1": "4rem" },
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("merge properties with atoms using conditional classes", async () => {
|
|
99
|
+
expect(
|
|
100
|
+
mergeCssProp(atoms("p-4 rounded-md", false && "hidden", true && "bg-white shadow-sm"), {
|
|
101
|
+
className: "w-full",
|
|
102
|
+
}),
|
|
103
|
+
).toMatchObject({
|
|
104
|
+
className: "w-full p-4 rounded-md bg-white shadow-sm",
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("merge properties with atoms using callback and conditional classes", async () => {
|
|
109
|
+
expect(
|
|
110
|
+
mergeCssProp(
|
|
111
|
+
atoms(
|
|
112
|
+
"border border-gray-200",
|
|
113
|
+
true && "hover:border-gray-300",
|
|
114
|
+
false && "opacity-50",
|
|
115
|
+
(_, classNames, style) => {
|
|
116
|
+
classNames.add("focus:ring-2 focus:ring-blue-500");
|
|
117
|
+
style["--ring-offset"] = "2px";
|
|
118
|
+
},
|
|
119
|
+
),
|
|
120
|
+
{ className: "relative" },
|
|
121
|
+
),
|
|
122
|
+
).toMatchObject({
|
|
123
|
+
className:
|
|
124
|
+
"relative border border-gray-200 hover:border-gray-300 focus:ring-2 focus:ring-blue-500",
|
|
125
|
+
style: { "--ring-offset": "2px" },
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("merge properties with atoms callback only", async () => {
|
|
130
|
+
expect(
|
|
131
|
+
mergeCssProp(
|
|
132
|
+
atoms((_, classNames, style) => {
|
|
133
|
+
classNames.add("grid-cols-3 gap-4");
|
|
134
|
+
classNames.add("md:grid-cols-6");
|
|
135
|
+
style["--grid-gap"] = "1rem";
|
|
136
|
+
}),
|
|
137
|
+
{ className: "grid" },
|
|
138
|
+
),
|
|
139
|
+
).toMatchObject({
|
|
140
|
+
className: "grid grid-cols-3 gap-4 md:grid-cols-6",
|
|
141
|
+
style: { "--grid-gap": "1rem" },
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("merge properties with css wrapping atoms", async () => {
|
|
146
|
+
expect(
|
|
147
|
+
mergeCssProp(
|
|
148
|
+
css(
|
|
149
|
+
"yakClass1",
|
|
150
|
+
atoms("bg-white rounded-lg shadow-md", (_, classNames, style) => {
|
|
151
|
+
classNames.add("p-6 hover:shadow-lg");
|
|
152
|
+
style["--card-transition"] = "all 0.2s ease";
|
|
153
|
+
}),
|
|
154
|
+
),
|
|
155
|
+
{ className: "card" },
|
|
156
|
+
),
|
|
157
|
+
).toMatchObject({
|
|
158
|
+
className: "card yakClass1 bg-white rounded-lg shadow-md p-6 hover:shadow-lg",
|
|
159
|
+
style: { "--card-transition": "all 0.2s ease" },
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it("merge properties with css, atoms, and function combination", async () => {
|
|
164
|
+
expect(
|
|
165
|
+
mergeCssProp(
|
|
166
|
+
css(
|
|
167
|
+
"yakClass1",
|
|
168
|
+
atoms("px-4 py-2 rounded-md", true && "text-white bg-blue-600", (_, classNames, style) => {
|
|
169
|
+
classNames.add("hover:bg-blue-700 focus:outline-none");
|
|
170
|
+
style["--btn-focus-ring"] = "0 0 0 3px rgba(59, 130, 246, 0.1)";
|
|
171
|
+
}),
|
|
172
|
+
() => ({
|
|
173
|
+
className: "yakClass2 yakClass3",
|
|
174
|
+
style: { "--yak-var1": "500" },
|
|
175
|
+
}),
|
|
176
|
+
),
|
|
177
|
+
{ className: "btn", style: { cursor: "pointer" } },
|
|
178
|
+
),
|
|
179
|
+
).toMatchObject({
|
|
180
|
+
className:
|
|
181
|
+
"btn yakClass1 px-4 py-2 rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none yakClass2 yakClass3",
|
|
182
|
+
style: {
|
|
183
|
+
cursor: "pointer",
|
|
184
|
+
"--btn-focus-ring": "0 0 0 3px rgba(59, 130, 246, 0.1)",
|
|
185
|
+
"--yak-var1": "500",
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("merge properties with nested css and atoms removing classes", async () => {
|
|
191
|
+
expect(
|
|
192
|
+
mergeCssProp(
|
|
193
|
+
css(
|
|
194
|
+
"yakClass1",
|
|
195
|
+
atoms("border border-gray-300 rounded-md", (_, classNames, style) => {
|
|
196
|
+
classNames.delete("input");
|
|
197
|
+
classNames.delete("yakClass1");
|
|
198
|
+
classNames.add("focus:border-blue-500 focus:ring-1 focus:ring-blue-500");
|
|
199
|
+
style["--input-padding"] = "0.75rem";
|
|
200
|
+
}),
|
|
201
|
+
() => ({ style: { "--yak-var1": "1rem" } }),
|
|
202
|
+
),
|
|
203
|
+
{ className: "input base-input" },
|
|
204
|
+
),
|
|
205
|
+
).toMatchObject({
|
|
206
|
+
className:
|
|
207
|
+
"base-input border border-gray-300 rounded-md focus:border-blue-500 focus:ring-1 focus:ring-blue-500",
|
|
208
|
+
style: {
|
|
209
|
+
"--input-padding": "0.75rem",
|
|
210
|
+
"--yak-var1": "1rem",
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it("merge properties with complex atoms manipulation", async () => {
|
|
216
|
+
expect(
|
|
217
|
+
mergeCssProp(
|
|
218
|
+
atoms(
|
|
219
|
+
"fixed inset-0 z-50",
|
|
220
|
+
true && "bg-black bg-opacity-50",
|
|
221
|
+
false && "hidden",
|
|
222
|
+
(_, classNames, style) => {
|
|
223
|
+
classNames.add("flex items-center justify-center");
|
|
224
|
+
classNames.add("animate-fadeIn");
|
|
225
|
+
style["--modal-backdrop-blur"] = "blur(4px)";
|
|
226
|
+
style.backdropFilter = "blur(4px)";
|
|
227
|
+
},
|
|
228
|
+
),
|
|
229
|
+
{ className: "modal" },
|
|
230
|
+
),
|
|
231
|
+
).toMatchObject({
|
|
232
|
+
className:
|
|
233
|
+
"modal fixed inset-0 z-50 bg-black bg-opacity-50 flex items-center justify-center animate-fadeIn",
|
|
234
|
+
style: {
|
|
235
|
+
"--modal-backdrop-blur": "blur(4px)",
|
|
236
|
+
backdropFilter: "blur(4px)",
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("merge properties with responsive design classes", async () => {
|
|
242
|
+
expect(
|
|
243
|
+
mergeCssProp(
|
|
244
|
+
atoms(
|
|
245
|
+
"sm:w-1/2 md:w-1/3 lg:w-1/4",
|
|
246
|
+
true && "p-4",
|
|
247
|
+
false && "hidden",
|
|
248
|
+
(_, classNames, style) => {
|
|
249
|
+
classNames.add("xl:w-1/5 2xl:w-1/6");
|
|
250
|
+
style["--responsive-padding"] = "clamp(0.5rem, 2vw, 1rem)";
|
|
251
|
+
},
|
|
252
|
+
),
|
|
253
|
+
{ className: "w-full" },
|
|
254
|
+
),
|
|
255
|
+
).toMatchObject({
|
|
256
|
+
className: "w-full sm:w-1/2 md:w-1/3 lg:w-1/4 p-4 xl:w-1/5 2xl:w-1/6",
|
|
257
|
+
style: { "--responsive-padding": "clamp(0.5rem, 2vw, 1rem)" },
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it("merge properties with form styling", async () => {
|
|
262
|
+
expect(
|
|
263
|
+
mergeCssProp(
|
|
264
|
+
css(
|
|
265
|
+
"yakClass1",
|
|
266
|
+
atoms(
|
|
267
|
+
"w-full px-3 py-2",
|
|
268
|
+
"border border-gray-300 rounded-md",
|
|
269
|
+
true && "focus:outline-none focus:ring-2 focus:ring-blue-500",
|
|
270
|
+
(_, classNames, style) => {
|
|
271
|
+
classNames.add("placeholder-gray-400 text-gray-900");
|
|
272
|
+
style["--input-transition"] =
|
|
273
|
+
"border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out";
|
|
274
|
+
},
|
|
275
|
+
),
|
|
276
|
+
() => ({ style: { "--yak-var1": "1.5" } }),
|
|
277
|
+
),
|
|
278
|
+
{ className: "form-control", style: { minHeight: "40px" } },
|
|
279
|
+
),
|
|
280
|
+
).toMatchObject({
|
|
281
|
+
className:
|
|
282
|
+
"form-control yakClass1 w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 placeholder-gray-400 text-gray-900",
|
|
283
|
+
style: {
|
|
284
|
+
minHeight: "40px",
|
|
285
|
+
"--input-transition": "border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out",
|
|
286
|
+
"--yak-var1": "1.5",
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it("merge properties with dark mode and state variants", async () => {
|
|
292
|
+
expect(
|
|
293
|
+
mergeCssProp(
|
|
294
|
+
css(
|
|
295
|
+
"yakClass1",
|
|
296
|
+
atoms(
|
|
297
|
+
"bg-white dark:bg-gray-800",
|
|
298
|
+
"text-gray-900 dark:text-white",
|
|
299
|
+
true && "hover:bg-gray-50 dark:hover:bg-gray-700",
|
|
300
|
+
false && "opacity-50",
|
|
301
|
+
(_, classNames, style) => {
|
|
302
|
+
classNames.add("transition-all duration-200");
|
|
303
|
+
classNames.add("border border-gray-200 dark:border-gray-700");
|
|
304
|
+
style["--card-shadow"] =
|
|
305
|
+
"0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)";
|
|
306
|
+
style["--card-shadow-dark"] =
|
|
307
|
+
"0 1px 3px 0 rgba(255, 255, 255, 0.1), 0 1px 2px 0 rgba(255, 255, 255, 0.06)";
|
|
308
|
+
},
|
|
309
|
+
),
|
|
310
|
+
),
|
|
311
|
+
{ className: "theme-card" },
|
|
312
|
+
),
|
|
313
|
+
).toMatchObject({
|
|
314
|
+
className:
|
|
315
|
+
"theme-card yakClass1 bg-white dark:bg-gray-800 text-gray-900 dark:text-white hover:bg-gray-50 dark:hover:bg-gray-700 transition-all duration-200 border border-gray-200 dark:border-gray-700",
|
|
316
|
+
style: {
|
|
317
|
+
"--card-shadow": "0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)",
|
|
318
|
+
"--card-shadow-dark":
|
|
319
|
+
"0 1px 3px 0 rgba(255, 255, 255, 0.1), 0 1px 2px 0 rgba(255, 255, 255, 0.06)",
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// a falsy css prop applies no styles - the swc plugin folds the statically known
|
|
325
|
+
// cases, so these cover the shapes that stay on the runtime path
|
|
326
|
+
it.each([
|
|
327
|
+
["false", false],
|
|
328
|
+
["null", null],
|
|
329
|
+
["undefined", undefined],
|
|
330
|
+
])("applies no styles for a %s css prop", (_label, cssProp) => {
|
|
331
|
+
expect(mergeCssProp(cssProp, {})).toEqual({});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it("keeps the relevant props when the css prop is falsy", async () => {
|
|
335
|
+
expect(mergeCssProp(false, { className: "btn", style: { padding: "8px" } })).toMatchObject({
|
|
336
|
+
className: "btn",
|
|
337
|
+
style: { padding: "8px" },
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
describe("a css prop which can not apply styles", () => {
|
|
342
|
+
const originalNodeEnv = process.env.NODE_ENV;
|
|
343
|
+
|
|
344
|
+
beforeEach(() => {
|
|
345
|
+
// errors are only thrown in development mode
|
|
346
|
+
process.env.NODE_ENV = "development";
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
afterEach(() => {
|
|
350
|
+
process.env.NODE_ENV = originalNodeEnv;
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it("throws for an array instead of calling it", () => {
|
|
354
|
+
expect(() => mergeCssProp([css("yakCss1")], {})).toThrowError(/but received an array/);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
it("throws for an object instead of calling it", () => {
|
|
358
|
+
expect(() => mergeCssProp({ color: "red" }, {})).toThrowError(
|
|
359
|
+
/but received a value of type object/,
|
|
360
|
+
);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it("throws for a plain string instead of calling it", () => {
|
|
364
|
+
expect(() => mergeCssProp("yakCss1", {})).toThrowError(/but received a value of type string/);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it("renders unstyled in production instead of taking the page down", () => {
|
|
368
|
+
process.env.NODE_ENV = "production";
|
|
369
|
+
expect(mergeCssProp([css("yakCss1")], { className: "btn" })).toEqual({ className: "btn" });
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
describe("sources in JSX order", () => {
|
|
374
|
+
it("lets a later source win and appends the css classes", () => {
|
|
375
|
+
expect(mergeCssProp(css("yakCss1"), { className: "a" }, { className: "b" })).toEqual({
|
|
376
|
+
className: "b yakCss1",
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it("keeps the order across a spread and forwards its other props", () => {
|
|
381
|
+
const onClick = () => {};
|
|
382
|
+
const spread = { className: "b", onClick };
|
|
383
|
+
expect(mergeCssProp(css("yakCss1"), { className: "a" }, spread, { className: "c" })).toEqual({
|
|
384
|
+
className: "c yakCss1",
|
|
385
|
+
onClick,
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it("works without any source", () => {
|
|
390
|
+
expect(mergeCssProp(css("yakCss1"))).toEqual({ className: "yakCss1" });
|
|
391
|
+
});
|
|
392
|
+
});
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/** @jsxImportSource @yak/react */
|
|
2
|
+
// this is only a type check file and should not be executed
|
|
3
|
+
|
|
4
|
+
import { css, styled } from "@yak/react";
|
|
5
|
+
import { ComponentProps, CSSProperties } from "react";
|
|
6
|
+
|
|
7
|
+
declare module "@yak/react" {
|
|
8
|
+
export interface YakTheme {
|
|
9
|
+
primaryColor: "red" | "blue";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const ComponentWithCssProp = () => {
|
|
14
|
+
return <div css={css``} />;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const ComponentWithEmptyCssPropAndClassName = () => {
|
|
18
|
+
return <div css={css``} className="static" />;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const ComponentWithEmptyCssPropInTernary = () => {
|
|
22
|
+
const on = Math.random() > 0.5;
|
|
23
|
+
return (
|
|
24
|
+
<div
|
|
25
|
+
css={
|
|
26
|
+
on
|
|
27
|
+
? css``
|
|
28
|
+
: css`
|
|
29
|
+
padding: 10px;
|
|
30
|
+
`
|
|
31
|
+
}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const NestedComponentWithCssProp = () => (
|
|
37
|
+
<div>
|
|
38
|
+
<p>
|
|
39
|
+
<div
|
|
40
|
+
css={css`
|
|
41
|
+
padding: 10px;
|
|
42
|
+
`}
|
|
43
|
+
>
|
|
44
|
+
anything
|
|
45
|
+
</div>
|
|
46
|
+
</p>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const ComponentThatTakesCssProp = (p: {
|
|
51
|
+
className?: string;
|
|
52
|
+
style?: ComponentProps<"div">["style"];
|
|
53
|
+
}) => <div {...p}>anything</div>;
|
|
54
|
+
|
|
55
|
+
const ComponentThatTakesCssProp2 = (p: { className?: string | string[]; style?: {} }) => (
|
|
56
|
+
<div {...(p as any)}>anything</div>
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const ComponentThatTakesCssProp3 = (p: { className: string; style?: Record<string, unknown> }) => (
|
|
60
|
+
<div {...p}>anything</div>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const ComponentThatTakesCssProp4 = (p: { className?: unknown; style?: unknown }) => (
|
|
64
|
+
<div {...(p as any)}>anything</div>
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const ComponentWithCssPropAsProp = () => {
|
|
68
|
+
return (
|
|
69
|
+
<>
|
|
70
|
+
<ComponentThatTakesCssProp css={css``} />
|
|
71
|
+
<ComponentThatTakesCssProp2 css={css``} />
|
|
72
|
+
<ComponentThatTakesCssProp3 css={css``} className="" />
|
|
73
|
+
<ComponentThatTakesCssProp4 css={css``} />
|
|
74
|
+
</>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const ObjectWithComponent = {
|
|
79
|
+
ComponentThatTakesCssProp,
|
|
80
|
+
nested: {
|
|
81
|
+
ComponentThatTakesCssProp,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
const ComponentThatUsesObjectWithComponent = () => (
|
|
85
|
+
<ObjectWithComponent.ComponentThatTakesCssProp
|
|
86
|
+
css={css`
|
|
87
|
+
padding: 10px;
|
|
88
|
+
`}
|
|
89
|
+
/>
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const ComponentThatUsesNestedObjectWithComponent = () => (
|
|
93
|
+
<ObjectWithComponent.nested.ComponentThatTakesCssProp
|
|
94
|
+
css={css`
|
|
95
|
+
padding: 10px;
|
|
96
|
+
`}
|
|
97
|
+
/>
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const ComponentWithCSSPropString = () => (
|
|
101
|
+
<div
|
|
102
|
+
// @ts-expect-error shouldn't allow strings as css prop
|
|
103
|
+
css={`
|
|
104
|
+
padding: 10px;
|
|
105
|
+
`}
|
|
106
|
+
>
|
|
107
|
+
anything
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const padding = css`
|
|
112
|
+
padding: 10px;
|
|
113
|
+
`;
|
|
114
|
+
const ComponentThatReusesCSS = () => <div css={padding} />;
|
|
115
|
+
|
|
116
|
+
const ComponentWithConditionalCSSProp = () => (
|
|
117
|
+
<div
|
|
118
|
+
css={
|
|
119
|
+
true &&
|
|
120
|
+
css`
|
|
121
|
+
padding: 10px;
|
|
122
|
+
`
|
|
123
|
+
}
|
|
124
|
+
>
|
|
125
|
+
anything
|
|
126
|
+
</div>
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const ComponentWithConditionalCSSProp2 = () => (
|
|
130
|
+
<div
|
|
131
|
+
css={
|
|
132
|
+
true
|
|
133
|
+
? padding
|
|
134
|
+
: css`
|
|
135
|
+
padding: 20px;
|
|
136
|
+
`
|
|
137
|
+
}
|
|
138
|
+
/>
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
const ComponentWithInterpolatedCSS = () => {
|
|
142
|
+
const x = Math.random() > 0.5;
|
|
143
|
+
return (
|
|
144
|
+
<div
|
|
145
|
+
// @ts-expect-error shouldn't allow interpolated css prop
|
|
146
|
+
css={(x) => css`
|
|
147
|
+
padding: 20px;
|
|
148
|
+
`}
|
|
149
|
+
/>
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const Text = styled.p`
|
|
154
|
+
font-size: 20px;
|
|
155
|
+
font-weight: bold;
|
|
156
|
+
font-family: "Inter";
|
|
157
|
+
`;
|
|
158
|
+
|
|
159
|
+
const StyledComponentWithCSSProp = () => {
|
|
160
|
+
<div>
|
|
161
|
+
<Text
|
|
162
|
+
css={css`
|
|
163
|
+
color: red;
|
|
164
|
+
`}
|
|
165
|
+
>
|
|
166
|
+
test
|
|
167
|
+
</Text>
|
|
168
|
+
</div>;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const ComponentWithConditionalCSSButWithoutOwnProps = () => {
|
|
172
|
+
const x = Math.random() > 0.5;
|
|
173
|
+
return (
|
|
174
|
+
<div
|
|
175
|
+
css={css`
|
|
176
|
+
${() =>
|
|
177
|
+
x &&
|
|
178
|
+
css`
|
|
179
|
+
padding: 20px;
|
|
180
|
+
`}
|
|
181
|
+
`}
|
|
182
|
+
/>
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const ComponentWithConditionalCSSVarsButWithoutOwnProps = () => {
|
|
187
|
+
const x = Math.random() > 0.5;
|
|
188
|
+
return (
|
|
189
|
+
<div
|
|
190
|
+
css={css`
|
|
191
|
+
padding: ${() => x && "20px"};
|
|
192
|
+
`}
|
|
193
|
+
/>
|
|
194
|
+
);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const ComponentWithDynamicCSSShouldGenerateTypeError = () => {
|
|
198
|
+
return (
|
|
199
|
+
<div
|
|
200
|
+
// @ts-expect-error - properties not supported
|
|
201
|
+
css={css<{ $primary: boolean }>`
|
|
202
|
+
padding: ${({ $primary }) => $primary && "20px"};
|
|
203
|
+
`}
|
|
204
|
+
/>
|
|
205
|
+
);
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const dynamicMixin = css<{ $primary: boolean }>`
|
|
209
|
+
${({ $primary }) =>
|
|
210
|
+
$primary &&
|
|
211
|
+
css`
|
|
212
|
+
font-size: 1.7rem;
|
|
213
|
+
`}
|
|
214
|
+
`;
|
|
215
|
+
|
|
216
|
+
const ComponentWithCSSThatUsesDynamicMixinShouldGenerateTypeError = () => {
|
|
217
|
+
return (
|
|
218
|
+
<div
|
|
219
|
+
css={css`
|
|
220
|
+
${
|
|
221
|
+
// @ts-expect-error - properties not supported
|
|
222
|
+
dynamicMixin
|
|
223
|
+
}
|
|
224
|
+
`}
|
|
225
|
+
/>
|
|
226
|
+
);
|
|
227
|
+
};
|