@styleframe/theme 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/.tsbuildinfo +1 -0
  2. package/CHANGELOG.md +12 -0
  3. package/package.json +48 -0
  4. package/src/constants/border.ts +0 -0
  5. package/src/constants/breakpoint.ts +0 -0
  6. package/src/constants/color.ts +0 -0
  7. package/src/constants/index.ts +4 -0
  8. package/src/constants/scale.ts +3 -0
  9. package/src/constants/typography.ts +0 -0
  10. package/src/index.ts +4 -0
  11. package/src/shims.d.ts +8 -0
  12. package/src/types.ts +32 -0
  13. package/src/utils/createUseVariable.test.ts +928 -0
  14. package/src/utils/createUseVariable.ts +107 -0
  15. package/src/utils/index.ts +1 -0
  16. package/src/variables/index.ts +22 -0
  17. package/src/variables/useBorderColor.ts +27 -0
  18. package/src/variables/useBorderRadius.test.ts +335 -0
  19. package/src/variables/useBorderRadius.ts +26 -0
  20. package/src/variables/useBorderStyle.test.ts +569 -0
  21. package/src/variables/useBorderStyle.ts +49 -0
  22. package/src/variables/useBorderWidth.test.ts +535 -0
  23. package/src/variables/useBorderWidth.ts +38 -0
  24. package/src/variables/useBoxShadow.test.ts +336 -0
  25. package/src/variables/useBoxShadow.ts +54 -0
  26. package/src/variables/useBreakpoint.test.ts +447 -0
  27. package/src/variables/useBreakpoint.ts +38 -0
  28. package/src/variables/useColor.test.ts +360 -0
  29. package/src/variables/useColor.ts +35 -0
  30. package/src/variables/useColorLightness.test.ts +168 -0
  31. package/src/variables/useColorLightness.ts +59 -0
  32. package/src/variables/useColorShade.test.ts +166 -0
  33. package/src/variables/useColorShade.ts +52 -0
  34. package/src/variables/useColorTint.test.ts +164 -0
  35. package/src/variables/useColorTint.ts +52 -0
  36. package/src/variables/useEasing.ts +0 -0
  37. package/src/variables/useFontFamily.test.ts +228 -0
  38. package/src/variables/useFontFamily.ts +33 -0
  39. package/src/variables/useFontSize.test.ts +299 -0
  40. package/src/variables/useFontSize.ts +32 -0
  41. package/src/variables/useFontStyle.test.ts +555 -0
  42. package/src/variables/useFontStyle.ts +37 -0
  43. package/src/variables/useFontWeight.test.ts +650 -0
  44. package/src/variables/useFontWeight.ts +55 -0
  45. package/src/variables/useLetterSpacing.test.ts +455 -0
  46. package/src/variables/useLetterSpacing.ts +41 -0
  47. package/src/variables/useLineHeight.test.ts +410 -0
  48. package/src/variables/useLineHeight.ts +41 -0
  49. package/src/variables/useMultiplier.test.ts +722 -0
  50. package/src/variables/useMultiplier.ts +44 -0
  51. package/src/variables/useScale.test.ts +393 -0
  52. package/src/variables/useScale.ts +52 -0
  53. package/src/variables/useScalePowers.test.ts +412 -0
  54. package/src/variables/useScalePowers.ts +35 -0
  55. package/src/variables/useSpacing.test.ts +309 -0
  56. package/src/variables/useSpacing.ts +26 -0
  57. package/src/vite-env.d.ts +1 -0
  58. package/test-scale.js +22 -0
  59. package/tsconfig.json +7 -0
  60. package/vite.config.ts +5 -0
@@ -0,0 +1,309 @@
1
+ import type { Variable } from "@styleframe/core";
2
+ import { styleframe } from "@styleframe/core";
3
+ import { consume } from "@styleframe/transpiler";
4
+ import { useSpacing } from "./useSpacing";
5
+
6
+ describe("useSpacing", () => {
7
+ it("should create a single spacing variable with 'default' key", () => {
8
+ const s = styleframe();
9
+ const { spacing } = useSpacing(s, {
10
+ default: "1rem",
11
+ });
12
+
13
+ expect(spacing).toEqual({
14
+ type: "variable",
15
+ name: "spacing",
16
+ value: "1rem",
17
+ });
18
+
19
+ const css = consume(spacing, s.options);
20
+ expect(css).toBe(`--spacing: 1rem;`);
21
+ });
22
+
23
+ it("should create spacing variable with modifier for non-default keys", () => {
24
+ const s = styleframe();
25
+ const { spacingSm } = useSpacing(s, {
26
+ sm: "0.5rem",
27
+ });
28
+
29
+ expect(spacingSm).toEqual({
30
+ type: "variable",
31
+ name: "spacing--sm",
32
+ value: "0.5rem",
33
+ });
34
+
35
+ const css = consume(spacingSm, s.options);
36
+ expect(css).toBe(`--spacing--sm: 0.5rem;`);
37
+ });
38
+
39
+ it("should create multiple spacing variables", () => {
40
+ const s = styleframe();
41
+ const { spacing, spacingSm, spacingMd, spacingLg } = useSpacing(s, {
42
+ default: "@md",
43
+ sm: "0.5rem",
44
+ md: "1rem",
45
+ lg: "2rem",
46
+ });
47
+
48
+ expect(spacingSm).toEqual({
49
+ type: "variable",
50
+ name: "spacing--sm",
51
+ value: "0.5rem",
52
+ });
53
+
54
+ expect(spacingMd).toEqual({
55
+ type: "variable",
56
+ name: "spacing--md",
57
+ value: "1rem",
58
+ });
59
+
60
+ expect(spacingLg).toEqual({
61
+ type: "variable",
62
+ name: "spacing--lg",
63
+ value: "2rem",
64
+ });
65
+
66
+ expect(spacing).toEqual({
67
+ type: "variable",
68
+ name: "spacing",
69
+ value: {
70
+ type: "reference",
71
+ name: "spacing--md",
72
+ fallback: undefined,
73
+ },
74
+ });
75
+ });
76
+
77
+ it("should add variables to root", () => {
78
+ const s = styleframe();
79
+ useSpacing(s, {
80
+ default: "1rem",
81
+ sm: "0.5rem",
82
+ });
83
+
84
+ expect(s.root.variables).toHaveLength(2);
85
+ expect(s.root.variables[0]?.name).toBe("spacing");
86
+ expect(s.root.variables[1]?.name).toBe("spacing--sm");
87
+ });
88
+
89
+ it("should handle kebab-case spacing names", () => {
90
+ const s = styleframe();
91
+ const { spacingExtraLarge } = useSpacing(s, {
92
+ "extra-large": "3rem",
93
+ });
94
+
95
+ expect(spacingExtraLarge).toEqual({
96
+ type: "variable",
97
+ name: "spacing--extra-large",
98
+ value: "3rem",
99
+ });
100
+ });
101
+
102
+ it("should handle snake_case spacing names", () => {
103
+ const s = styleframe();
104
+ const { spacingCardPadding } = useSpacing(s, {
105
+ card_padding: "1.5rem",
106
+ });
107
+
108
+ expect(spacingCardPadding).toEqual({
109
+ type: "variable",
110
+ name: "spacing--card_padding",
111
+ value: "1.5rem",
112
+ });
113
+ });
114
+
115
+ it("should handle numeric spacing names", () => {
116
+ const s = styleframe();
117
+ const { spacing100 } = useSpacing(s, {
118
+ "100": "0.25rem",
119
+ });
120
+
121
+ expect(spacing100).toEqual({
122
+ type: "variable",
123
+ name: "spacing--100",
124
+ value: "0.25rem",
125
+ });
126
+ });
127
+
128
+ it("should handle pixel values", () => {
129
+ const s = styleframe();
130
+ const { spacing } = useSpacing(s, {
131
+ default: "16px",
132
+ });
133
+
134
+ expect(spacing).toEqual({
135
+ type: "variable",
136
+ name: "spacing",
137
+ value: "16px",
138
+ });
139
+ });
140
+
141
+ it("should handle em values", () => {
142
+ const s = styleframe();
143
+ const { spacingBase } = useSpacing(s, {
144
+ base: "1.5em",
145
+ });
146
+
147
+ expect(spacingBase).toEqual({
148
+ type: "variable",
149
+ name: "spacing--base",
150
+ value: "1.5em",
151
+ });
152
+ });
153
+
154
+ it("should handle percentage values", () => {
155
+ const s = styleframe();
156
+ const { spacingRelative } = useSpacing(s, {
157
+ relative: "5%",
158
+ });
159
+
160
+ expect(spacingRelative).toEqual({
161
+ type: "variable",
162
+ name: "spacing--relative",
163
+ value: "5%",
164
+ });
165
+ });
166
+
167
+ it("should handle viewport units", () => {
168
+ const s = styleframe();
169
+ const { spacingFluid } = useSpacing(s, {
170
+ fluid: "2.5vw",
171
+ });
172
+
173
+ expect(spacingFluid).toEqual({
174
+ type: "variable",
175
+ name: "spacing--fluid",
176
+ value: "2.5vw",
177
+ });
178
+ });
179
+
180
+ it("should handle calc() expressions", () => {
181
+ const s = styleframe();
182
+ const { spacingDynamic } = useSpacing(s, {
183
+ dynamic: "calc(1rem + 0.5vw)",
184
+ });
185
+
186
+ expect(spacingDynamic.value).toBe("calc(1rem + 0.5vw)");
187
+ });
188
+
189
+ it("should handle clamp() expressions", () => {
190
+ const s = styleframe();
191
+ const { spacingResponsive } = useSpacing(s, {
192
+ responsive: "clamp(0.5rem, 2vw, 2rem)",
193
+ });
194
+
195
+ expect(spacingResponsive.value).toBe("clamp(0.5rem, 2vw, 2rem)");
196
+ });
197
+
198
+ it("should handle empty spacing object", () => {
199
+ const s = styleframe();
200
+ const result = useSpacing(s, {});
201
+
202
+ expect(result).toEqual({});
203
+ expect(s.root.variables).toHaveLength(0);
204
+ });
205
+
206
+ it("should handle spacing references", () => {
207
+ const s = styleframe();
208
+ const baseSpacing = s.variable("base-spacing", "1rem");
209
+ const { spacing } = useSpacing(s, {
210
+ default: s.ref(baseSpacing),
211
+ });
212
+
213
+ expect(spacing.value).toEqual({
214
+ type: "reference",
215
+ name: "base-spacing",
216
+ fallback: undefined,
217
+ });
218
+ });
219
+
220
+ it("should compile to correct CSS output using consume", () => {
221
+ const s = styleframe();
222
+ useSpacing(s, {
223
+ default: "@md",
224
+ xs: "0.25rem",
225
+ sm: "0.5rem",
226
+ md: "1rem",
227
+ lg: "2rem",
228
+ });
229
+
230
+ const css = consume(s.root, s.options);
231
+
232
+ expect(css).toBe(`:root {
233
+ --spacing--xs: 0.25rem;
234
+ --spacing--sm: 0.5rem;
235
+ --spacing--md: 1rem;
236
+ --spacing--lg: 2rem;
237
+ --spacing: var(--spacing--md);
238
+ }`);
239
+ });
240
+
241
+ it("should handle a complete spacing scale", () => {
242
+ const s = styleframe();
243
+ const spaces = useSpacing(s, {
244
+ "0": "0",
245
+ xs: "0.25rem",
246
+ sm: "0.5rem",
247
+ default: "@md",
248
+ md: "1rem",
249
+ lg: "1.5rem",
250
+ xl: "2rem",
251
+ "2xl": "3rem",
252
+ "3xl": "4rem",
253
+ });
254
+
255
+ expect(spaces.spacing0.value).toBe("0");
256
+ expect(spaces.spacingXs.value).toBe("0.25rem");
257
+ expect(spaces.spacingSm.value).toBe("0.5rem");
258
+ expect(spaces.spacing.value).toEqual({
259
+ type: "reference",
260
+ name: "spacing--md",
261
+ fallback: undefined,
262
+ });
263
+ expect(spaces.spacingMd.value).toBe("1rem");
264
+ expect(spaces.spacingLg.value).toBe("1.5rem");
265
+ expect(spaces.spacingXl.value).toBe("2rem");
266
+ expect(spaces.spacing2xl.value).toBe("3rem");
267
+ expect(spaces.spacing3xl.value).toBe("4rem");
268
+ });
269
+
270
+ describe("type safety", () => {
271
+ it("should preserve exact spacing names in return type", () => {
272
+ const s = styleframe();
273
+ const spaces = useSpacing(s, {
274
+ default: "1rem",
275
+ sm: "0.5rem",
276
+ });
277
+
278
+ // Type assertions to verify the generic types are preserved
279
+ const defaultSpacing: Variable<"spacing"> = spaces.spacing;
280
+ const smSpacing: Variable<"spacing--sm"> = spaces.spacingSm;
281
+
282
+ expect(defaultSpacing.name).toBe("spacing");
283
+ expect(smSpacing.name).toBe("spacing--sm");
284
+ });
285
+
286
+ it("should maintain type information for kebab-case names", () => {
287
+ const s = styleframe();
288
+ const { spacingExtraLarge } = useSpacing(s, {
289
+ "extra-large": "3rem",
290
+ });
291
+
292
+ const typed: Variable<"spacing--extra-large"> = spacingExtraLarge;
293
+ expect(typed.name).toBe("spacing--extra-large");
294
+ });
295
+
296
+ it("should work with const assertion", () => {
297
+ const s = styleframe();
298
+ const spacingConfig = {
299
+ default: "1rem",
300
+ sm: "0.5rem",
301
+ } as const;
302
+
303
+ const spaces = useSpacing(s, spacingConfig);
304
+
305
+ expect(spaces.spacing.name).toBe("spacing");
306
+ expect(spaces.spacingSm.name).toBe("spacing--sm");
307
+ });
308
+ });
309
+ });
@@ -0,0 +1,26 @@
1
+ import { createUseVariable } from "../utils";
2
+
3
+ /**
4
+ * Create a set of spacing variables for use in a Styleframe instance.
5
+ *
6
+ * @usage
7
+ * ```typescript
8
+ * import { styleframe } from "styleframe";
9
+ * import { useSpacing } from "styleframe/theme";
10
+ *
11
+ * const s = styleframe();
12
+ *
13
+ * const {
14
+ * spacing, // Variable<'spacing'>
15
+ * spacingSm, // Variable<'spacing--sm'>
16
+ * spacingMd, // Variable<'spacing--md'>
17
+ * spacingLg, // Variable<'spacing--lg'>
18
+ * } = useSpacing(s, {
19
+ * default: "1rem",
20
+ * sm: "0.875rem",
21
+ * md: "1rem",
22
+ * lg: "1.25rem",
23
+ * });
24
+ * ```
25
+ */
26
+ export const useSpacing = createUseVariable("spacing");
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
package/test-scale.js ADDED
@@ -0,0 +1,22 @@
1
+ import { styleframe } from "@styleframe/core";
2
+ import { consume } from "@styleframe/transpiler";
3
+ import { useScale } from "./src/variables/useScale.js";
4
+ import { useScalePowers } from "./src/variables/useScalePowers.js";
5
+ import { defaultScalePowerValues } from "./src/constants/scale.js";
6
+
7
+ const s = styleframe();
8
+ const { scaleGolden } = useScale(s);
9
+ const powers = useScalePowers(s, scaleGolden, [1, 2]);
10
+
11
+ console.log("Power 1:", powers[1]);
12
+ console.log("Power 2:", powers[2]);
13
+ console.log("Power 1 value:", powers[1].value);
14
+ console.log("Power 2 value:", powers[2].value);
15
+
16
+ const baseSize = s.variable("base", "1rem");
17
+ s.selector(".test", ({ variable }) => {
18
+ variable("font-size", s.css`calc(${s.ref(baseSize)} * ${powers[1]})`);
19
+ });
20
+
21
+ console.log("\nCSS:");
22
+ console.log(consume(s.root, s.options));
package/tsconfig.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "@styleframe/config-typescript",
3
+ "compilerOptions": {
4
+ "tsBuildInfoFile": ".tsbuildinfo"
5
+ },
6
+ "include": ["src/**/*.ts", "tsup.config.ts", "vite.config.ts"]
7
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { createViteConfig } from "@styleframe/config-vite";
2
+
3
+ const __dirname = new URL(".", import.meta.url).pathname;
4
+
5
+ export default createViteConfig("theme", __dirname);