@styleframe/theme 1.0.1 → 1.0.3
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 +12 -0
- package/LICENSE +21 -0
- package/dist/theme.d.ts +772 -0
- package/dist/theme.js +2507 -0
- package/dist/theme.umd.cjs +4 -0
- package/package.json +14 -4
- package/.tsbuildinfo +0 -1
- package/src/constants/border.ts +0 -0
- package/src/constants/breakpoint.ts +0 -0
- package/src/constants/color.ts +0 -0
- package/src/constants/index.ts +0 -4
- package/src/constants/scale.ts +0 -3
- package/src/constants/typography.ts +0 -0
- package/src/index.ts +0 -4
- package/src/shims.d.ts +0 -8
- package/src/types.ts +0 -32
- package/src/utils/createUseVariable.test.ts +0 -928
- package/src/utils/createUseVariable.ts +0 -107
- package/src/utils/index.ts +0 -1
- package/src/variables/index.ts +0 -20
- package/src/variables/useBorderColor.ts +0 -27
- package/src/variables/useBorderRadius.test.ts +0 -335
- package/src/variables/useBorderRadius.ts +0 -26
- package/src/variables/useBorderStyle.test.ts +0 -569
- package/src/variables/useBorderStyle.ts +0 -49
- package/src/variables/useBorderWidth.test.ts +0 -535
- package/src/variables/useBorderWidth.ts +0 -38
- package/src/variables/useBoxShadow.test.ts +0 -336
- package/src/variables/useBoxShadow.ts +0 -54
- package/src/variables/useBreakpoint.test.ts +0 -447
- package/src/variables/useBreakpoint.ts +0 -38
- package/src/variables/useColor.test.ts +0 -360
- package/src/variables/useColor.ts +0 -35
- package/src/variables/useColorLightness.test.ts +0 -168
- package/src/variables/useColorLightness.ts +0 -59
- package/src/variables/useColorShade.test.ts +0 -166
- package/src/variables/useColorShade.ts +0 -52
- package/src/variables/useColorTint.test.ts +0 -164
- package/src/variables/useColorTint.ts +0 -52
- package/src/variables/useEasing.ts +0 -0
- package/src/variables/useFontFamily.test.ts +0 -228
- package/src/variables/useFontFamily.ts +0 -33
- package/src/variables/useFontSize.test.ts +0 -299
- package/src/variables/useFontSize.ts +0 -32
- package/src/variables/useFontStyle.test.ts +0 -555
- package/src/variables/useFontStyle.ts +0 -37
- package/src/variables/useFontWeight.test.ts +0 -650
- package/src/variables/useFontWeight.ts +0 -55
- package/src/variables/useLetterSpacing.test.ts +0 -455
- package/src/variables/useLetterSpacing.ts +0 -41
- package/src/variables/useLineHeight.test.ts +0 -410
- package/src/variables/useLineHeight.ts +0 -41
- package/src/variables/useMultiplier.test.ts +0 -722
- package/src/variables/useMultiplier.ts +0 -44
- package/src/variables/useScale.test.ts +0 -393
- package/src/variables/useScale.ts +0 -52
- package/src/variables/useScalePowers.test.ts +0 -412
- package/src/variables/useScalePowers.ts +0 -35
- package/src/variables/useSpacing.test.ts +0 -309
- package/src/variables/useSpacing.ts +0 -26
- package/src/vite-env.d.ts +0 -1
- package/test-scale.js +0 -22
- package/tsconfig.json +0 -7
- package/vite.config.ts +0 -5
|
@@ -1,928 +0,0 @@
|
|
|
1
|
-
import type { Variable } from "@styleframe/core";
|
|
2
|
-
import { styleframe } from "@styleframe/core";
|
|
3
|
-
import { consume } from "@styleframe/transpiler";
|
|
4
|
-
import { createUseVariable } from "./createUseVariable";
|
|
5
|
-
|
|
6
|
-
describe("createUseVariable", () => {
|
|
7
|
-
it("should create a composable for font-family property", () => {
|
|
8
|
-
const useFontFamily = createUseVariable("font-family");
|
|
9
|
-
const s = styleframe();
|
|
10
|
-
const { fontFamily } = useFontFamily(s, {
|
|
11
|
-
default: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto",
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
expect(fontFamily).toEqual({
|
|
15
|
-
type: "variable",
|
|
16
|
-
name: "font-family",
|
|
17
|
-
value: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto",
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("should create a composable for line-height property", () => {
|
|
22
|
-
const useLineHeight = createUseVariable("line-height");
|
|
23
|
-
const s = styleframe();
|
|
24
|
-
const { lineHeight } = useLineHeight(s, {
|
|
25
|
-
default: "1.5",
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
expect(lineHeight).toEqual({
|
|
29
|
-
type: "variable",
|
|
30
|
-
name: "line-height",
|
|
31
|
-
value: "1.5",
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("should create a composable for custom property", () => {
|
|
36
|
-
const useCustomProp = createUseVariable("custom-property");
|
|
37
|
-
const s = styleframe();
|
|
38
|
-
const { customProperty } = useCustomProp(s, {
|
|
39
|
-
default: "value",
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
expect(customProperty).toEqual({
|
|
43
|
-
type: "variable",
|
|
44
|
-
name: "custom-property",
|
|
45
|
-
value: "value",
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it("should create variable with modifier for non-default keys", () => {
|
|
50
|
-
const useFontSize = createUseVariable("font-size");
|
|
51
|
-
const s = styleframe();
|
|
52
|
-
const { fontSizeLarge } = useFontSize(s, {
|
|
53
|
-
large: "20px",
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
expect(fontSizeLarge).toEqual({
|
|
57
|
-
type: "variable",
|
|
58
|
-
name: "font-size--large",
|
|
59
|
-
value: "20px",
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("should create multiple variables", () => {
|
|
64
|
-
const useSpacing = createUseVariable("spacing");
|
|
65
|
-
const s = styleframe();
|
|
66
|
-
const { spacing, spacingSmall, spacingLarge } = useSpacing(s, {
|
|
67
|
-
default: "16px",
|
|
68
|
-
small: "8px",
|
|
69
|
-
large: "32px",
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
expect(spacing).toEqual({
|
|
73
|
-
type: "variable",
|
|
74
|
-
name: "spacing",
|
|
75
|
-
value: "16px",
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
expect(spacingSmall).toEqual({
|
|
79
|
-
type: "variable",
|
|
80
|
-
name: "spacing--small",
|
|
81
|
-
value: "8px",
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
expect(spacingLarge).toEqual({
|
|
85
|
-
type: "variable",
|
|
86
|
-
name: "spacing--large",
|
|
87
|
-
value: "32px",
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it("should add variables to root", () => {
|
|
92
|
-
const useBorderWidth = createUseVariable("border-width");
|
|
93
|
-
const s = styleframe();
|
|
94
|
-
useBorderWidth(s, {
|
|
95
|
-
default: "1px",
|
|
96
|
-
thick: "3px",
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
expect(s.root.variables).toHaveLength(2);
|
|
100
|
-
expect(s.root.variables[0]?.name).toBe("border-width");
|
|
101
|
-
expect(s.root.variables[1]?.name).toBe("border-width--thick");
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it("should handle kebab-case token names", () => {
|
|
105
|
-
const useColor = createUseVariable("color");
|
|
106
|
-
const s = styleframe();
|
|
107
|
-
const { colorPrimaryLight } = useColor(s, {
|
|
108
|
-
"primary-light": "#3b82f6",
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
expect(colorPrimaryLight).toEqual({
|
|
112
|
-
type: "variable",
|
|
113
|
-
name: "color--primary-light",
|
|
114
|
-
value: "#3b82f6",
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("should handle snake_case token names", () => {
|
|
119
|
-
const useColor = createUseVariable("color");
|
|
120
|
-
const s = styleframe();
|
|
121
|
-
const { colorPrimaryDark } = useColor(s, {
|
|
122
|
-
primary_dark: "#1e40af",
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
expect(colorPrimaryDark).toEqual({
|
|
126
|
-
type: "variable",
|
|
127
|
-
name: "color--primary_dark",
|
|
128
|
-
value: "#1e40af",
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it("should handle numeric token names", () => {
|
|
133
|
-
const useFontWeight = createUseVariable("font-weight");
|
|
134
|
-
const s = styleframe();
|
|
135
|
-
const { fontWeight400 } = useFontWeight(s, {
|
|
136
|
-
"400": "400",
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
expect(fontWeight400).toEqual({
|
|
140
|
-
type: "variable",
|
|
141
|
-
name: "font-weight--400",
|
|
142
|
-
value: "400",
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it("should handle empty token object", () => {
|
|
147
|
-
const useMargin = createUseVariable("margin");
|
|
148
|
-
const s = styleframe();
|
|
149
|
-
const result = useMargin(s, {});
|
|
150
|
-
|
|
151
|
-
expect(result).toEqual({});
|
|
152
|
-
expect(s.root.variables).toHaveLength(0);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it("should handle variable references", () => {
|
|
156
|
-
const useSize = createUseVariable("size");
|
|
157
|
-
const s = styleframe();
|
|
158
|
-
const baseSize = s.variable("base-size", "16px");
|
|
159
|
-
const { size } = useSize(s, {
|
|
160
|
-
default: s.ref(baseSize),
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
expect(size.value).toEqual({
|
|
164
|
-
type: "reference",
|
|
165
|
-
name: "base-size",
|
|
166
|
-
fallback: undefined,
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it("should compile to correct CSS output", () => {
|
|
171
|
-
const usePadding = createUseVariable("padding");
|
|
172
|
-
const s = styleframe();
|
|
173
|
-
usePadding(s, {
|
|
174
|
-
default: "16px",
|
|
175
|
-
small: "8px",
|
|
176
|
-
large: "32px",
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
const css = consume(s.root, s.options);
|
|
180
|
-
|
|
181
|
-
expect(css).toBe(`:root {
|
|
182
|
-
--padding: 16px;
|
|
183
|
-
--padding--small: 8px;
|
|
184
|
-
--padding--large: 32px;
|
|
185
|
-
}`);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
describe("type safety", () => {
|
|
189
|
-
it("should preserve exact variable names in return type", () => {
|
|
190
|
-
const useMargin = createUseVariable("margin");
|
|
191
|
-
const s = styleframe();
|
|
192
|
-
const margins = useMargin(s, {
|
|
193
|
-
default: "0",
|
|
194
|
-
auto: "auto",
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
// Type assertions to verify the generic types are preserved
|
|
198
|
-
const defaultMargin: Variable<"margin"> = margins.margin;
|
|
199
|
-
const autoMargin: Variable<"margin--auto"> = margins.marginAuto;
|
|
200
|
-
|
|
201
|
-
expect(defaultMargin.name).toBe("margin");
|
|
202
|
-
expect(autoMargin.name).toBe("margin--auto");
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it("should maintain type information for kebab-case names", () => {
|
|
206
|
-
const useTransition = createUseVariable("transition");
|
|
207
|
-
const s = styleframe();
|
|
208
|
-
const { transitionFastEase } = useTransition(s, {
|
|
209
|
-
"fast-ease": "200ms ease",
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
const typed: Variable<"transition--fast-ease"> = transitionFastEase;
|
|
213
|
-
expect(typed.name).toBe("transition--fast-ease");
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
describe("property name variations", () => {
|
|
218
|
-
it("should work with single-word properties", () => {
|
|
219
|
-
const useWidth = createUseVariable("width");
|
|
220
|
-
const s = styleframe();
|
|
221
|
-
const { width } = useWidth(s, { default: "100%" });
|
|
222
|
-
|
|
223
|
-
expect(width.name).toBe("width");
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it("should work with multi-word kebab-case properties", () => {
|
|
227
|
-
const useBoxShadow = createUseVariable("box-shadow");
|
|
228
|
-
const s = styleframe();
|
|
229
|
-
const { boxShadow } = useBoxShadow(s, {
|
|
230
|
-
default: "0 2px 4px rgba(0,0,0,0.1)",
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
expect(boxShadow.name).toBe("box-shadow");
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it("should work with complex property names", () => {
|
|
237
|
-
const useBorderTopLeftRadius = createUseVariable(
|
|
238
|
-
"border-top-left-radius",
|
|
239
|
-
);
|
|
240
|
-
const s = styleframe();
|
|
241
|
-
const { borderTopLeftRadius } = useBorderTopLeftRadius(s, {
|
|
242
|
-
default: "4px",
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
expect(borderTopLeftRadius.name).toBe("border-top-left-radius");
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
describe("propertyValueFn", () => {
|
|
250
|
-
it("should transform values using propertyValueFn", () => {
|
|
251
|
-
const useSize = createUseVariable("size", {
|
|
252
|
-
transform: (value) => `${value}px`,
|
|
253
|
-
});
|
|
254
|
-
const s = styleframe();
|
|
255
|
-
const { size, sizeLarge } = useSize(s, {
|
|
256
|
-
default: "16",
|
|
257
|
-
large: "32",
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
expect(size.value).toBe("16px");
|
|
261
|
-
expect(sizeLarge.value).toBe("32px");
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it("should transform string values to uppercase", () => {
|
|
265
|
-
const useFont = createUseVariable("font", {
|
|
266
|
-
transform: (value) => String(value).toUpperCase(),
|
|
267
|
-
});
|
|
268
|
-
const s = styleframe();
|
|
269
|
-
const { font, fontBold } = useFont(s, {
|
|
270
|
-
default: "arial",
|
|
271
|
-
bold: "helvetica",
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
expect(font.value).toBe("ARIAL");
|
|
275
|
-
expect(fontBold.value).toBe("HELVETICA");
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
it("should transform numeric values", () => {
|
|
279
|
-
const useOpacity = createUseVariable("opacity", {
|
|
280
|
-
transform: (value) => (typeof value === "number" ? value / 100 : value),
|
|
281
|
-
});
|
|
282
|
-
const s = styleframe();
|
|
283
|
-
const { opacity, opacityHalf } = useOpacity(s, {
|
|
284
|
-
default: 100,
|
|
285
|
-
half: 50,
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
expect(opacity.value).toBe(1);
|
|
289
|
-
expect(opacityHalf.value).toBe(0.5);
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
it("should wrap values in calc()", () => {
|
|
293
|
-
const useSpacing = createUseVariable("spacing", {
|
|
294
|
-
transform: (value) => `calc(${value} * var(--scale))`,
|
|
295
|
-
});
|
|
296
|
-
const s = styleframe();
|
|
297
|
-
const { spacing, spacingDouble } = useSpacing(s, {
|
|
298
|
-
default: "1rem",
|
|
299
|
-
double: "2rem",
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
expect(spacing.value).toBe("calc(1rem * var(--scale))");
|
|
303
|
-
expect(spacingDouble.value).toBe("calc(2rem * var(--scale))");
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
it("should add units to unitless values", () => {
|
|
307
|
-
const usePadding = createUseVariable("padding", {
|
|
308
|
-
transform: (value) => {
|
|
309
|
-
if (typeof value === "number" || /^\d+$/.test(String(value))) {
|
|
310
|
-
return `${value}px`;
|
|
311
|
-
}
|
|
312
|
-
return value;
|
|
313
|
-
},
|
|
314
|
-
});
|
|
315
|
-
const s = styleframe();
|
|
316
|
-
const { padding, paddingSmall } = usePadding(s, {
|
|
317
|
-
default: "16",
|
|
318
|
-
small: 8,
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
expect(padding.value).toBe("16px");
|
|
322
|
-
expect(paddingSmall.value).toBe("8px");
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
it("should handle variable references in transformer", () => {
|
|
326
|
-
const useColor = createUseVariable("color", {
|
|
327
|
-
transform: (value) => {
|
|
328
|
-
if (typeof value === "object" && value !== null && "type" in value) {
|
|
329
|
-
return value; // Pass through variable references
|
|
330
|
-
}
|
|
331
|
-
return `rgb(${value})`;
|
|
332
|
-
},
|
|
333
|
-
});
|
|
334
|
-
const s = styleframe();
|
|
335
|
-
const baseColor = s.variable("base-color", "255, 0, 0");
|
|
336
|
-
const { color, colorCustom } = useColor(s, {
|
|
337
|
-
default: s.ref(baseColor),
|
|
338
|
-
custom: "0, 255, 0",
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
expect(color.value).toEqual({
|
|
342
|
-
type: "reference",
|
|
343
|
-
name: "base-color",
|
|
344
|
-
fallback: undefined,
|
|
345
|
-
});
|
|
346
|
-
expect(colorCustom.value).toBe("rgb(0, 255, 0)");
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
it("should preserve complex values through transformer", () => {
|
|
350
|
-
const useShadow = createUseVariable("shadow", {
|
|
351
|
-
transform: (value) => {
|
|
352
|
-
if (String(value).includes("rgba")) {
|
|
353
|
-
return value;
|
|
354
|
-
}
|
|
355
|
-
return `0 2px 4px ${value}`;
|
|
356
|
-
},
|
|
357
|
-
});
|
|
358
|
-
const s = styleframe();
|
|
359
|
-
const { shadow, shadowCustom } = useShadow(s, {
|
|
360
|
-
default: "rgba(0, 0, 0, 0.1)",
|
|
361
|
-
custom: "red",
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
expect(shadow.value).toBe("rgba(0, 0, 0, 0.1)");
|
|
365
|
-
expect(shadowCustom.value).toBe("0 2px 4px red");
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
it("should compile transformed values to CSS correctly", () => {
|
|
369
|
-
const useMargin = createUseVariable("margin", {
|
|
370
|
-
transform: (value) => `${value}rem`,
|
|
371
|
-
});
|
|
372
|
-
const s = styleframe();
|
|
373
|
-
useMargin(s, {
|
|
374
|
-
default: "1",
|
|
375
|
-
large: "2",
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
const css = consume(s.root, s.options);
|
|
379
|
-
|
|
380
|
-
expect(css).toBe(`:root {
|
|
381
|
-
--margin: 1rem;
|
|
382
|
-
--margin--large: 2rem;
|
|
383
|
-
}`);
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
it("should use default identity function when not provided", () => {
|
|
387
|
-
const useWidth = createUseVariable("width");
|
|
388
|
-
const s = styleframe();
|
|
389
|
-
const { width } = useWidth(s, {
|
|
390
|
-
default: "100%",
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
expect(width.value).toBe("100%");
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
it("should transform all tokens consistently", () => {
|
|
397
|
-
const useRounded = createUseVariable("border-radius", {
|
|
398
|
-
transform: (value) => (value === "full" ? "9999px" : value),
|
|
399
|
-
});
|
|
400
|
-
const s = styleframe();
|
|
401
|
-
const {
|
|
402
|
-
borderRadius,
|
|
403
|
-
borderRadiusSmall,
|
|
404
|
-
borderRadiusMedium,
|
|
405
|
-
borderRadiusFull,
|
|
406
|
-
} = useRounded(s, {
|
|
407
|
-
default: "0",
|
|
408
|
-
small: "4px",
|
|
409
|
-
medium: "8px",
|
|
410
|
-
full: "full",
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
expect(borderRadius.value).toBe("0");
|
|
414
|
-
expect(borderRadiusSmall.value).toBe("4px");
|
|
415
|
-
expect(borderRadiusMedium.value).toBe("8px");
|
|
416
|
-
expect(borderRadiusFull.value).toBe("9999px");
|
|
417
|
-
});
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
describe("defaults option", () => {
|
|
421
|
-
it("should use defaults when no tokens are provided", () => {
|
|
422
|
-
const useColor = createUseVariable("color", {
|
|
423
|
-
defaults: {
|
|
424
|
-
default: "#000000",
|
|
425
|
-
primary: "#3b82f6",
|
|
426
|
-
secondary: "#8b5cf6",
|
|
427
|
-
},
|
|
428
|
-
});
|
|
429
|
-
const s = styleframe();
|
|
430
|
-
const { color, colorPrimary, colorSecondary } = useColor(s);
|
|
431
|
-
|
|
432
|
-
expect(color.value).toBe("#000000");
|
|
433
|
-
expect(colorPrimary.value).toBe("#3b82f6");
|
|
434
|
-
expect(colorSecondary.value).toBe("#8b5cf6");
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
it("should override defaults when tokens are provided", () => {
|
|
438
|
-
const useColor = createUseVariable("color", {
|
|
439
|
-
defaults: {
|
|
440
|
-
default: "#000000",
|
|
441
|
-
primary: "#3b82f6",
|
|
442
|
-
},
|
|
443
|
-
});
|
|
444
|
-
const s = styleframe();
|
|
445
|
-
const { color, colorPrimary } = useColor(s, {
|
|
446
|
-
default: "#ffffff",
|
|
447
|
-
primary: "#ef4444",
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
expect(color.value).toBe("#ffffff");
|
|
451
|
-
expect(colorPrimary.value).toBe("#ef4444");
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
it("should work with transform function", () => {
|
|
455
|
-
const useSize = createUseVariable("size", {
|
|
456
|
-
defaults: {
|
|
457
|
-
default: "16",
|
|
458
|
-
large: "32",
|
|
459
|
-
},
|
|
460
|
-
transform: (value) => `${value}px`,
|
|
461
|
-
});
|
|
462
|
-
const s = styleframe();
|
|
463
|
-
const { size, sizeLarge } = useSize(s);
|
|
464
|
-
|
|
465
|
-
expect(size.value).toBe("16px");
|
|
466
|
-
expect(sizeLarge.value).toBe("32px");
|
|
467
|
-
});
|
|
468
|
-
});
|
|
469
|
-
|
|
470
|
-
describe("mergeDefaults option", () => {
|
|
471
|
-
it("should merge defaults with tokens when mergeDefaults is true", () => {
|
|
472
|
-
const useColor = createUseVariable("color", {
|
|
473
|
-
defaults: {
|
|
474
|
-
default: "#000000",
|
|
475
|
-
primary: "#3b82f6",
|
|
476
|
-
secondary: "#8b5cf6",
|
|
477
|
-
},
|
|
478
|
-
mergeDefaults: true,
|
|
479
|
-
});
|
|
480
|
-
const s = styleframe();
|
|
481
|
-
const { color, colorPrimary, colorSecondary, colorTertiary } = useColor(
|
|
482
|
-
s,
|
|
483
|
-
{
|
|
484
|
-
primary: "#ef4444",
|
|
485
|
-
tertiary: "#f59e0b",
|
|
486
|
-
},
|
|
487
|
-
);
|
|
488
|
-
|
|
489
|
-
expect(color.value).toBe("#000000"); // from defaults
|
|
490
|
-
expect(colorPrimary.value).toBe("#ef4444"); // overridden
|
|
491
|
-
expect(colorSecondary.value).toBe("#8b5cf6"); // from defaults
|
|
492
|
-
expect(colorTertiary.value).toBe("#f59e0b"); // new token
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
it("should not merge when mergeDefaults is false", () => {
|
|
496
|
-
const useColor = createUseVariable("color", {
|
|
497
|
-
defaults: {
|
|
498
|
-
default: "#000000",
|
|
499
|
-
primary: "#3b82f6",
|
|
500
|
-
},
|
|
501
|
-
mergeDefaults: false,
|
|
502
|
-
});
|
|
503
|
-
const s = styleframe();
|
|
504
|
-
const result = useColor(s, {
|
|
505
|
-
custom: "#ff0000",
|
|
506
|
-
});
|
|
507
|
-
|
|
508
|
-
expect(result.colorCustom?.value).toBe("#ff0000");
|
|
509
|
-
|
|
510
|
-
// @ts-expect-error color key should not be present
|
|
511
|
-
expect(result.color).toBeUndefined();
|
|
512
|
-
// @ts-expect-error colorPrimary key should not be present
|
|
513
|
-
expect(result.colorPrimary).toBeUndefined();
|
|
514
|
-
});
|
|
515
|
-
|
|
516
|
-
it("should merge with empty tokens object", () => {
|
|
517
|
-
const useSpacing = createUseVariable("spacing", {
|
|
518
|
-
defaults: {
|
|
519
|
-
default: "16px",
|
|
520
|
-
small: "8px",
|
|
521
|
-
},
|
|
522
|
-
mergeDefaults: true,
|
|
523
|
-
});
|
|
524
|
-
const s = styleframe();
|
|
525
|
-
const { spacing, spacingSmall } = useSpacing(s, {});
|
|
526
|
-
|
|
527
|
-
expect(spacing.value).toBe("16px");
|
|
528
|
-
expect(spacingSmall.value).toBe("8px");
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
it("should merge and apply transform function", () => {
|
|
532
|
-
const useSize = createUseVariable("size", {
|
|
533
|
-
defaults: {
|
|
534
|
-
small: "8",
|
|
535
|
-
medium: "16",
|
|
536
|
-
},
|
|
537
|
-
mergeDefaults: true,
|
|
538
|
-
transform: (value) => `${value}px`,
|
|
539
|
-
});
|
|
540
|
-
const s = styleframe();
|
|
541
|
-
const { sizeSmall, sizeMedium, sizeLarge } = useSize(s, {
|
|
542
|
-
large: "32",
|
|
543
|
-
});
|
|
544
|
-
|
|
545
|
-
expect(sizeSmall.value).toBe("8px");
|
|
546
|
-
expect(sizeMedium.value).toBe("16px");
|
|
547
|
-
expect(sizeLarge.value).toBe("32px");
|
|
548
|
-
});
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
describe("key reference values (@)", () => {
|
|
552
|
-
it("should resolve key references with @ syntax", () => {
|
|
553
|
-
const useColor = createUseVariable("color");
|
|
554
|
-
const s = styleframe();
|
|
555
|
-
const { color, colorPrimary, colorHover } = useColor(s, {
|
|
556
|
-
default: "#3b82f6",
|
|
557
|
-
primary: "@default",
|
|
558
|
-
hover: "@primary",
|
|
559
|
-
});
|
|
560
|
-
|
|
561
|
-
expect(color.value).toBe("#3b82f6");
|
|
562
|
-
expect(colorPrimary.value).toEqual({
|
|
563
|
-
type: "reference",
|
|
564
|
-
name: "color",
|
|
565
|
-
fallback: undefined,
|
|
566
|
-
});
|
|
567
|
-
expect(colorHover.value).toEqual({
|
|
568
|
-
type: "reference",
|
|
569
|
-
name: "color--primary",
|
|
570
|
-
fallback: undefined,
|
|
571
|
-
});
|
|
572
|
-
});
|
|
573
|
-
|
|
574
|
-
it("should resolve nested key references", () => {
|
|
575
|
-
const useSize = createUseVariable("size");
|
|
576
|
-
const s = styleframe();
|
|
577
|
-
const { size, sizeMedium, sizeLarge } = useSize(s, {
|
|
578
|
-
default: "16px",
|
|
579
|
-
medium: "@default",
|
|
580
|
-
large: "@medium",
|
|
581
|
-
});
|
|
582
|
-
|
|
583
|
-
expect(size.value).toBe("16px");
|
|
584
|
-
expect(sizeMedium.value).toEqual({
|
|
585
|
-
type: "reference",
|
|
586
|
-
name: "size",
|
|
587
|
-
fallback: undefined,
|
|
588
|
-
});
|
|
589
|
-
expect(sizeLarge.value).toEqual({
|
|
590
|
-
type: "reference",
|
|
591
|
-
name: "size--medium",
|
|
592
|
-
fallback: undefined,
|
|
593
|
-
});
|
|
594
|
-
});
|
|
595
|
-
|
|
596
|
-
it("should compile key references to CSS correctly", () => {
|
|
597
|
-
const useSpacing = createUseVariable("spacing");
|
|
598
|
-
const s = styleframe();
|
|
599
|
-
useSpacing(s, {
|
|
600
|
-
default: "16px",
|
|
601
|
-
small: "8px",
|
|
602
|
-
medium: "@default",
|
|
603
|
-
});
|
|
604
|
-
|
|
605
|
-
const css = consume(s.root, s.options);
|
|
606
|
-
|
|
607
|
-
expect(css).toBe(`:root {
|
|
608
|
-
--spacing: 16px;
|
|
609
|
-
--spacing--small: 8px;
|
|
610
|
-
--spacing--medium: var(--spacing);
|
|
611
|
-
}`);
|
|
612
|
-
});
|
|
613
|
-
|
|
614
|
-
it("should handle key references with transform function", () => {
|
|
615
|
-
const useSize = createUseVariable("size", {
|
|
616
|
-
transform: (value) => {
|
|
617
|
-
if (typeof value === "object" && value !== null && "type" in value) {
|
|
618
|
-
return value; // Pass through references
|
|
619
|
-
}
|
|
620
|
-
return `${value}px`;
|
|
621
|
-
},
|
|
622
|
-
});
|
|
623
|
-
const s = styleframe();
|
|
624
|
-
const { size, sizeLarge } = useSize(s, {
|
|
625
|
-
default: "16",
|
|
626
|
-
large: "@default",
|
|
627
|
-
});
|
|
628
|
-
|
|
629
|
-
expect(size.value).toBe("16px");
|
|
630
|
-
expect(sizeLarge.value).toEqual({
|
|
631
|
-
type: "reference",
|
|
632
|
-
name: "size",
|
|
633
|
-
fallback: undefined,
|
|
634
|
-
});
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
it("should sort key references to be processed last when default key exists", () => {
|
|
638
|
-
const useColor = createUseVariable("color");
|
|
639
|
-
const s = styleframe();
|
|
640
|
-
useColor(s, {
|
|
641
|
-
primary: "@default",
|
|
642
|
-
default: "#3b82f6",
|
|
643
|
-
secondary: "@primary",
|
|
644
|
-
tertiary: "#8b5cf6",
|
|
645
|
-
});
|
|
646
|
-
|
|
647
|
-
// Verify all variables were created
|
|
648
|
-
expect(s.root.variables).toHaveLength(4);
|
|
649
|
-
|
|
650
|
-
// Verify the default variable exists first
|
|
651
|
-
const defaultVar = s.root.variables.find((v) => v.name === "color");
|
|
652
|
-
expect(defaultVar?.value).toBe("#3b82f6");
|
|
653
|
-
|
|
654
|
-
// Verify references point to correct variables
|
|
655
|
-
const primaryVar = s.root.variables.find(
|
|
656
|
-
(v) => v.name === "color--primary",
|
|
657
|
-
);
|
|
658
|
-
expect(primaryVar?.value).toEqual({
|
|
659
|
-
type: "reference",
|
|
660
|
-
name: "color",
|
|
661
|
-
fallback: undefined,
|
|
662
|
-
});
|
|
663
|
-
});
|
|
664
|
-
|
|
665
|
-
it("should work with key references in defaults", () => {
|
|
666
|
-
const useColor = createUseVariable("color", {
|
|
667
|
-
defaults: {
|
|
668
|
-
default: "#3b82f6",
|
|
669
|
-
primary: "@default",
|
|
670
|
-
hover: "@primary",
|
|
671
|
-
},
|
|
672
|
-
});
|
|
673
|
-
const s = styleframe();
|
|
674
|
-
const { color, colorPrimary, colorHover } = useColor(s);
|
|
675
|
-
|
|
676
|
-
expect(color.value).toBe("#3b82f6");
|
|
677
|
-
expect(colorPrimary.value).toEqual({
|
|
678
|
-
type: "reference",
|
|
679
|
-
name: "color",
|
|
680
|
-
fallback: undefined,
|
|
681
|
-
});
|
|
682
|
-
expect(colorHover.value).toEqual({
|
|
683
|
-
type: "reference",
|
|
684
|
-
name: "color--primary",
|
|
685
|
-
fallback: undefined,
|
|
686
|
-
});
|
|
687
|
-
});
|
|
688
|
-
|
|
689
|
-
it("should merge defaults and tokens with key references", () => {
|
|
690
|
-
const useColor = createUseVariable("color", {
|
|
691
|
-
defaults: {
|
|
692
|
-
default: "#3b82f6",
|
|
693
|
-
primary: "@default",
|
|
694
|
-
},
|
|
695
|
-
mergeDefaults: true,
|
|
696
|
-
});
|
|
697
|
-
const s = styleframe();
|
|
698
|
-
const { color, colorPrimary, colorSecondary } = useColor(s, {
|
|
699
|
-
secondary: "@primary",
|
|
700
|
-
});
|
|
701
|
-
|
|
702
|
-
expect(color.value).toBe("#3b82f6");
|
|
703
|
-
expect(colorPrimary.value).toEqual({
|
|
704
|
-
type: "reference",
|
|
705
|
-
name: "color",
|
|
706
|
-
fallback: undefined,
|
|
707
|
-
});
|
|
708
|
-
expect(colorSecondary.value).toEqual({
|
|
709
|
-
type: "reference",
|
|
710
|
-
name: "color--primary",
|
|
711
|
-
fallback: undefined,
|
|
712
|
-
});
|
|
713
|
-
});
|
|
714
|
-
|
|
715
|
-
it("should reference non-default keys", () => {
|
|
716
|
-
const useColor = createUseVariable("color");
|
|
717
|
-
const s = styleframe();
|
|
718
|
-
const { colorPrimary, colorSecondary, colorAccent } = useColor(s, {
|
|
719
|
-
primary: "#3b82f6",
|
|
720
|
-
secondary: "#8b5cf6",
|
|
721
|
-
accent: "@secondary",
|
|
722
|
-
});
|
|
723
|
-
|
|
724
|
-
expect(colorPrimary.value).toBe("#3b82f6");
|
|
725
|
-
expect(colorSecondary.value).toBe("#8b5cf6");
|
|
726
|
-
expect(colorAccent.value).toEqual({
|
|
727
|
-
type: "reference",
|
|
728
|
-
name: "color--secondary",
|
|
729
|
-
fallback: undefined,
|
|
730
|
-
});
|
|
731
|
-
});
|
|
732
|
-
});
|
|
733
|
-
|
|
734
|
-
describe("delimiter option", () => {
|
|
735
|
-
it("should use custom delimiter", () => {
|
|
736
|
-
const useColor = createUseVariable("color", {
|
|
737
|
-
delimiter: "_",
|
|
738
|
-
});
|
|
739
|
-
const s = styleframe();
|
|
740
|
-
const { color, colorPrimary } = useColor(s, {
|
|
741
|
-
default: "#000000",
|
|
742
|
-
primary: "#3b82f6",
|
|
743
|
-
});
|
|
744
|
-
|
|
745
|
-
expect(color.name).toBe("color");
|
|
746
|
-
expect(colorPrimary.name).toBe("color_primary");
|
|
747
|
-
});
|
|
748
|
-
|
|
749
|
-
it("should compile with custom delimiter", () => {
|
|
750
|
-
const useSpacing = createUseVariable("spacing", {
|
|
751
|
-
delimiter: ".",
|
|
752
|
-
});
|
|
753
|
-
const s = styleframe();
|
|
754
|
-
useSpacing(s, {
|
|
755
|
-
default: "16px",
|
|
756
|
-
small: "8px",
|
|
757
|
-
});
|
|
758
|
-
|
|
759
|
-
const css = consume(s.root, s.options);
|
|
760
|
-
|
|
761
|
-
expect(css).toBe(`:root {
|
|
762
|
-
--spacing: 16px;
|
|
763
|
-
--spacing-small: 8px;
|
|
764
|
-
}`);
|
|
765
|
-
});
|
|
766
|
-
});
|
|
767
|
-
|
|
768
|
-
describe("real-world use cases", () => {
|
|
769
|
-
it("should replicate useFontFamily behavior", () => {
|
|
770
|
-
const useFontFamily = createUseVariable("font-family");
|
|
771
|
-
const s = styleframe();
|
|
772
|
-
const { fontFamily, fontFamilyMono, fontFamilySerif } = useFontFamily(s, {
|
|
773
|
-
default:
|
|
774
|
-
"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
|
775
|
-
mono: "'SFMono-Regular', Menlo, Monaco, Consolas, monospace",
|
|
776
|
-
serif: "'Georgia', 'Times New Roman', Times, serif",
|
|
777
|
-
});
|
|
778
|
-
|
|
779
|
-
expect(fontFamily.name).toBe("font-family");
|
|
780
|
-
expect(fontFamilyMono.name).toBe("font-family--mono");
|
|
781
|
-
expect(fontFamilySerif.name).toBe("font-family--serif");
|
|
782
|
-
});
|
|
783
|
-
|
|
784
|
-
it("should work for spacing scale", () => {
|
|
785
|
-
const useSpacing = createUseVariable("spacing");
|
|
786
|
-
const s = styleframe();
|
|
787
|
-
const { spacing, spacingXs, spacingSm, spacingMd, spacingLg, spacingXl } =
|
|
788
|
-
useSpacing(s, {
|
|
789
|
-
default: "16px",
|
|
790
|
-
xs: "4px",
|
|
791
|
-
sm: "8px",
|
|
792
|
-
md: "16px",
|
|
793
|
-
lg: "24px",
|
|
794
|
-
xl: "32px",
|
|
795
|
-
});
|
|
796
|
-
|
|
797
|
-
expect(spacing.value).toBe("16px");
|
|
798
|
-
expect(spacingXs.value).toBe("4px");
|
|
799
|
-
expect(spacingSm.value).toBe("8px");
|
|
800
|
-
expect(spacingMd.value).toBe("16px");
|
|
801
|
-
expect(spacingLg.value).toBe("24px");
|
|
802
|
-
expect(spacingXl.value).toBe("32px");
|
|
803
|
-
});
|
|
804
|
-
|
|
805
|
-
it("should work for z-index scale", () => {
|
|
806
|
-
const useZIndex = createUseVariable("z-index");
|
|
807
|
-
const s = styleframe();
|
|
808
|
-
const { zIndexDropdown, zIndexModal, zIndexTooltip } = useZIndex(s, {
|
|
809
|
-
dropdown: "1000",
|
|
810
|
-
modal: "2000",
|
|
811
|
-
tooltip: "3000",
|
|
812
|
-
});
|
|
813
|
-
|
|
814
|
-
expect(zIndexDropdown.name).toBe("z-index--dropdown");
|
|
815
|
-
expect(zIndexModal.name).toBe("z-index--modal");
|
|
816
|
-
expect(zIndexTooltip.name).toBe("z-index--tooltip");
|
|
817
|
-
});
|
|
818
|
-
|
|
819
|
-
it("should create semantic color system with references", () => {
|
|
820
|
-
const useColor = createUseVariable("color", {
|
|
821
|
-
defaults: {
|
|
822
|
-
blue: "#3b82f6",
|
|
823
|
-
red: "#ef4444",
|
|
824
|
-
primary: "@blue",
|
|
825
|
-
danger: "@red",
|
|
826
|
-
link: "@primary",
|
|
827
|
-
error: "@danger",
|
|
828
|
-
},
|
|
829
|
-
});
|
|
830
|
-
const s = styleframe();
|
|
831
|
-
const {
|
|
832
|
-
colorBlue,
|
|
833
|
-
colorRed,
|
|
834
|
-
colorPrimary,
|
|
835
|
-
colorDanger,
|
|
836
|
-
colorLink,
|
|
837
|
-
colorError,
|
|
838
|
-
} = useColor(s);
|
|
839
|
-
|
|
840
|
-
expect(colorBlue.value).toBe("#3b82f6");
|
|
841
|
-
expect(colorRed.value).toBe("#ef4444");
|
|
842
|
-
expect(colorPrimary.value).toEqual({
|
|
843
|
-
type: "reference",
|
|
844
|
-
name: "color--blue",
|
|
845
|
-
fallback: undefined,
|
|
846
|
-
});
|
|
847
|
-
expect(colorDanger.value).toEqual({
|
|
848
|
-
type: "reference",
|
|
849
|
-
name: "color--red",
|
|
850
|
-
fallback: undefined,
|
|
851
|
-
});
|
|
852
|
-
expect(colorLink.value).toEqual({
|
|
853
|
-
type: "reference",
|
|
854
|
-
name: "color--primary",
|
|
855
|
-
fallback: undefined,
|
|
856
|
-
});
|
|
857
|
-
expect(colorError.value).toEqual({
|
|
858
|
-
type: "reference",
|
|
859
|
-
name: "color--danger",
|
|
860
|
-
fallback: undefined,
|
|
861
|
-
});
|
|
862
|
-
});
|
|
863
|
-
|
|
864
|
-
it("should create a design system with defaults and overrides", () => {
|
|
865
|
-
const useSpacing = createUseVariable("spacing", {
|
|
866
|
-
defaults: {
|
|
867
|
-
xs: "4px",
|
|
868
|
-
sm: "8px",
|
|
869
|
-
md: "16px",
|
|
870
|
-
lg: "24px",
|
|
871
|
-
xl: "32px",
|
|
872
|
-
default: "@md",
|
|
873
|
-
},
|
|
874
|
-
mergeDefaults: true,
|
|
875
|
-
});
|
|
876
|
-
const s = styleframe();
|
|
877
|
-
const { spacing, spacingXs, spacingSm, spacingMd, spacingCustom } =
|
|
878
|
-
useSpacing(s, {
|
|
879
|
-
custom: "20px",
|
|
880
|
-
});
|
|
881
|
-
|
|
882
|
-
// All defaults should be present
|
|
883
|
-
expect(spacingXs.value).toBe("4px");
|
|
884
|
-
expect(spacingSm.value).toBe("8px");
|
|
885
|
-
expect(spacingMd.value).toBe("16px");
|
|
886
|
-
|
|
887
|
-
// Default should reference md
|
|
888
|
-
expect(spacing.value).toEqual({
|
|
889
|
-
type: "reference",
|
|
890
|
-
name: "spacing--md",
|
|
891
|
-
fallback: undefined,
|
|
892
|
-
});
|
|
893
|
-
|
|
894
|
-
// Custom should be added
|
|
895
|
-
expect(spacingCustom.value).toBe("20px");
|
|
896
|
-
});
|
|
897
|
-
|
|
898
|
-
it("should work with transform and key references together", () => {
|
|
899
|
-
const useDuration = createUseVariable("duration", {
|
|
900
|
-
defaults: {
|
|
901
|
-
fast: "150",
|
|
902
|
-
normal: "300",
|
|
903
|
-
slow: "500",
|
|
904
|
-
default: "@normal",
|
|
905
|
-
},
|
|
906
|
-
transform: (value) => {
|
|
907
|
-
// Don't transform references
|
|
908
|
-
if (typeof value === "object" && value !== null && "type" in value) {
|
|
909
|
-
return value;
|
|
910
|
-
}
|
|
911
|
-
return `${value}ms`;
|
|
912
|
-
},
|
|
913
|
-
});
|
|
914
|
-
const s = styleframe();
|
|
915
|
-
const { duration, durationFast, durationNormal, durationSlow } =
|
|
916
|
-
useDuration(s);
|
|
917
|
-
|
|
918
|
-
expect(durationFast.value).toBe("150ms");
|
|
919
|
-
expect(durationNormal.value).toBe("300ms");
|
|
920
|
-
expect(durationSlow.value).toBe("500ms");
|
|
921
|
-
expect(duration.value).toEqual({
|
|
922
|
-
type: "reference",
|
|
923
|
-
name: "duration--normal",
|
|
924
|
-
fallback: undefined,
|
|
925
|
-
});
|
|
926
|
-
});
|
|
927
|
-
});
|
|
928
|
-
});
|