@styleframe/core 1.0.1 → 1.0.2

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 (48) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE +21 -0
  3. package/dist/styleframe.d.ts +301 -0
  4. package/dist/styleframe.js +528 -0
  5. package/dist/styleframe.umd.cjs +1 -0
  6. package/package.json +13 -3
  7. package/.tsbuildinfo +0 -1
  8. package/src/index.ts +0 -5
  9. package/src/styleframe.ts +0 -64
  10. package/src/tokens/atRule.test.ts +0 -1013
  11. package/src/tokens/atRule.ts +0 -67
  12. package/src/tokens/css.test.ts +0 -404
  13. package/src/tokens/css.ts +0 -23
  14. package/src/tokens/declarations.test.ts +0 -584
  15. package/src/tokens/declarations.ts +0 -71
  16. package/src/tokens/index.ts +0 -11
  17. package/src/tokens/modifier.test.ts +0 -90
  18. package/src/tokens/modifier.ts +0 -86
  19. package/src/tokens/recipe.test.ts +0 -105
  20. package/src/tokens/recipe.ts +0 -32
  21. package/src/tokens/ref.test.ts +0 -430
  22. package/src/tokens/ref.ts +0 -24
  23. package/src/tokens/root.test.ts +0 -70
  24. package/src/tokens/root.ts +0 -14
  25. package/src/tokens/selector.test.ts +0 -440
  26. package/src/tokens/selector.ts +0 -47
  27. package/src/tokens/theme.test.ts +0 -338
  28. package/src/tokens/theme.ts +0 -26
  29. package/src/tokens/utility.test.ts +0 -1456
  30. package/src/tokens/utility.ts +0 -92
  31. package/src/tokens/variable.test.ts +0 -235
  32. package/src/tokens/variable.ts +0 -42
  33. package/src/typeGuards.test.ts +0 -33
  34. package/src/typeGuards.ts +0 -98
  35. package/src/types/declarations.ts +0 -42
  36. package/src/types/index.ts +0 -3
  37. package/src/types/options.ts +0 -22
  38. package/src/types/tokens.ts +0 -149
  39. package/src/utils/capitalizeFirst.ts +0 -9
  40. package/src/utils/deepClone.ts +0 -317
  41. package/src/utils/getters.test.ts +0 -399
  42. package/src/utils/getters.ts +0 -36
  43. package/src/utils/index.ts +0 -4
  44. package/src/utils/merge.test.ts +0 -978
  45. package/src/utils/merge.ts +0 -73
  46. package/src/vite-env.d.ts +0 -1
  47. package/tsconfig.json +0 -7
  48. package/vite.config.ts +0 -5
@@ -1,92 +0,0 @@
1
- import type {
2
- Container,
3
- ModifierFactory,
4
- Root,
5
- TokenValue,
6
- Utility,
7
- UtilityCallbackFn,
8
- UtilityCreatorFn,
9
- UtilityFactory,
10
- } from "../types";
11
- import {
12
- createDeclarationsCallbackContext,
13
- parseDeclarationsBlock,
14
- } from "./declarations";
15
- import { applyModifiers, combineKeys } from "./modifier";
16
-
17
- export function createModifiedUtilityInstances(
18
- baseInstance: Utility,
19
- availableModifiers: ModifierFactory[],
20
- root: Root,
21
- ): Utility[] {
22
- const modifierKeys = availableModifiers.map((modifier) => modifier.key);
23
- const modifierKeyCombinations = combineKeys(modifierKeys);
24
-
25
- return modifierKeyCombinations.map((combination) => {
26
- const modifiers = new Map<string, ModifierFactory>();
27
-
28
- for (const modifierKey of combination) {
29
- const modifier = availableModifiers.find((modifier) =>
30
- modifier.key.includes(modifierKey),
31
- );
32
- if (modifier) modifiers.set(modifierKey, modifier);
33
- }
34
-
35
- return applyModifiers(baseInstance, root, modifiers);
36
- });
37
- }
38
-
39
- export function createUtilityFunction(parent: Container, root: Root) {
40
- return function utility<Name extends string>(
41
- name: Name,
42
- factory: UtilityCallbackFn,
43
- ): UtilityCreatorFn {
44
- const factoryInstance: UtilityFactory<Name> = {
45
- type: "utility",
46
- name,
47
- factory,
48
- };
49
-
50
- root.utilities.push(factoryInstance);
51
-
52
- return (
53
- entries: Record<string, TokenValue>,
54
- modifiers: ModifierFactory[] = [],
55
- ) => {
56
- for (const [key, value] of Object.entries(entries)) {
57
- const instance: Utility<Name> = {
58
- type: "utility",
59
- name,
60
- value: key,
61
- declarations: {},
62
- variables: [],
63
- children: [],
64
- modifiers: [],
65
- };
66
-
67
- const callbackContext = createDeclarationsCallbackContext(
68
- instance,
69
- root,
70
- );
71
-
72
- instance.declarations =
73
- factory({
74
- ...callbackContext,
75
- value,
76
- }) ?? {};
77
-
78
- parseDeclarationsBlock(instance.declarations, callbackContext);
79
-
80
- // Store the utility value on the instance
81
- parent.children.push(instance);
82
-
83
- // Create modified variants for this specific value
84
- if (modifiers.length > 0) {
85
- parent.children.push(
86
- ...createModifiedUtilityInstances(instance, modifiers, root),
87
- );
88
- }
89
- }
90
- };
91
- };
92
- }
@@ -1,235 +0,0 @@
1
- import type { Reference, Root, Selector, Variable } from "../types";
2
- import { createRoot } from "./root";
3
- import { createSelectorFunction } from "./selector";
4
- import { createVariableFunction } from "./variable";
5
-
6
- describe("createVariableFunction", () => {
7
- let root: Root;
8
- let variable: ReturnType<typeof createVariableFunction>;
9
- let selector: ReturnType<typeof createSelectorFunction>;
10
-
11
- beforeEach(() => {
12
- root = createRoot();
13
- variable = createVariableFunction(root, root);
14
- selector = createSelectorFunction(root, root);
15
- });
16
-
17
- describe("basic variable creation", () => {
18
- it("should create a new variable with correct properties", () => {
19
- const result = variable("primary-color", "#007bff");
20
-
21
- expect(result).toEqual({
22
- type: "variable",
23
- name: "primary-color",
24
- value: "#007bff",
25
- });
26
- });
27
-
28
- it("should add the variable to root declarations", () => {
29
- const result = variable("spacing", "1rem");
30
-
31
- expect(root.variables).toHaveLength(1);
32
- expect(root.variables[0]).toBe(result);
33
- });
34
- });
35
-
36
- describe("default behavior", () => {
37
- describe("when false", () => {
38
- it("should update existing variable value when default is false", () => {
39
- const first = variable("border-width", "1px", { default: true });
40
- const second = variable("border-width", "2px", { default: false });
41
-
42
- expect(second).toBe(first); // Same instance
43
- expect(second.value).toBe("2px"); // Updated value
44
- expect(root.variables).toHaveLength(1);
45
- });
46
-
47
- it("should create new variable if none exists with default: false", () => {
48
- const result = variable("line-height", "1.5", { default: false });
49
-
50
- expect(result.value).toBe("1.5");
51
- expect(root.variables).toHaveLength(1);
52
- });
53
- });
54
-
55
- describe("when true", () => {
56
- it("should return existing variable when default is true", () => {
57
- const first = variable("color", "red");
58
- const second = variable("color", "blue", { default: true }); // Should return first, not create new
59
-
60
- expect(second).toBe(first);
61
- expect(second.value).toBe("red");
62
- expect(root.variables).toHaveLength(1);
63
- });
64
-
65
- it("should return existing variable with explicit default: true", () => {
66
- const first = variable("font-size", "16px", { default: true });
67
- const second = variable("font-size", "18px", { default: true });
68
-
69
- expect(second).toBe(first);
70
- expect(second.value).toBe("16px");
71
- expect(root.variables).toHaveLength(1);
72
- });
73
-
74
- it("should create new variable if none exists with default: true", () => {
75
- const result = variable("margin", "10px", { default: true });
76
-
77
- expect(result.value).toBe("10px");
78
- expect(root.variables).toHaveLength(1);
79
- });
80
- });
81
- });
82
-
83
- describe("multiple variables", () => {
84
- it("should handle multiple different variables", () => {
85
- const color = variable("color", "blue");
86
- const spacing = variable("spacing", "8px");
87
- const fontSize = variable("font-size", "14px");
88
-
89
- expect(root.variables).toHaveLength(3);
90
- expect(root.variables).toContain(color);
91
- expect(root.variables).toContain(spacing);
92
- expect(root.variables).toContain(fontSize);
93
- });
94
-
95
- it("should find correct existing variable among multiple", () => {
96
- const color = variable("color", "red");
97
- const spacing = variable("spacing", "10px");
98
- const fontSize = variable("font-size", "16px");
99
-
100
- // Try to override the middle variable
101
- const updatedSpacing = variable("spacing", "20px", { default: false });
102
-
103
- expect(updatedSpacing).toBe(spacing);
104
- expect(updatedSpacing.value).toBe("20px");
105
- expect(root.variables).toHaveLength(3);
106
- });
107
- });
108
-
109
- describe("working with references", () => {
110
- it("should handle reference token values", () => {
111
- const reference: Reference = {
112
- type: "reference",
113
- name: "base-color",
114
- fallback: "#000000",
115
- };
116
-
117
- const result = variable("ref-color", reference);
118
-
119
- expect(result.value).toEqual(reference);
120
- });
121
- });
122
-
123
- describe("working with selectors", () => {
124
- it("should work when root is a selector", () => {
125
- const selectorInstance = selector(".test", {});
126
-
127
- const selectorVariable = createVariableFunction(selectorInstance, root);
128
- const result = selectorVariable("nested-var", "50px");
129
-
130
- expect(result.name).toBe("nested-var");
131
- expect(selectorInstance.variables).toHaveLength(1);
132
- expect(selectorInstance.variables[0]).toBe(result);
133
- });
134
- });
135
-
136
- describe("edge cases", () => {
137
- it("should handle empty string values", () => {
138
- const result = variable("empty", "");
139
- expect(result.value).toBe("");
140
- });
141
-
142
- it("should handle null values", () => {
143
- const result = variable("null-value", null);
144
- expect(result.value).toBe(null);
145
- });
146
-
147
- it("should handle undefined values", () => {
148
- const result = variable("undefined-value", undefined);
149
- expect(result.value).toBe(undefined);
150
- });
151
-
152
- it("should handle numeric values", () => {
153
- const result = variable("numeric", 42);
154
- expect(result.value).toBe(42);
155
- });
156
-
157
- it("should handle boolean values", () => {
158
- const result = variable("boolean", true);
159
- expect(result.value).toBe(true);
160
- });
161
- });
162
-
163
- describe("type safety", () => {
164
- it("should maintain type information for variable name", () => {
165
- const result = variable("test-var", "100px");
166
-
167
- // Type assertion to verify the generic type is preserved
168
- const typedResult: Variable<"test-var"> = result;
169
- expect(typedResult.name).toBe("test-var");
170
- });
171
-
172
- it("should preserve generic type parameter", () => {
173
- const result = variable("typed-var", "test-value");
174
-
175
- // This should compile without type errors
176
- const name: "typed-var" = result.name;
177
- expect(name).toBe("typed-var");
178
- });
179
-
180
- it("should work with different string literal types", () => {
181
- const colorVar = variable("color-primary", "#ff0000");
182
- const spacingVar = variable("spacing-lg", "2rem");
183
-
184
- expect(colorVar.name).toBe("color-primary");
185
- expect(spacingVar.name).toBe("spacing-lg");
186
- });
187
- });
188
-
189
- describe("accepting variable instance as name", () => {
190
- let root: Root;
191
- let variable: ReturnType<typeof createVariableFunction>;
192
-
193
- beforeEach(() => {
194
- root = createRoot();
195
- variable = createVariableFunction(root, root);
196
- });
197
-
198
- it("should update existing variable when passing variable instance", () => {
199
- const first = variable("v", "a");
200
- const updated = variable(first, "b");
201
-
202
- expect(updated).toBe(first);
203
- expect(updated.value).toBe("b");
204
- expect(root.variables).toHaveLength(1);
205
- });
206
-
207
- it("should respect default: true when passing variable instance", () => {
208
- const first = variable("color", "red");
209
- const result = variable(first, "blue", { default: true });
210
-
211
- expect(result).toBe(first);
212
- expect(first.value).toBe("red");
213
- expect(root.variables).toHaveLength(1);
214
- });
215
-
216
- it("should create variable in new container when target from different parent", () => {
217
- const base = variable("spacing", "8px");
218
- const selectorInstance = selector(".x", {});
219
- const selectorVariable = createVariableFunction(selectorInstance, root);
220
- const result = selectorVariable(base, "12px");
221
-
222
- expect(result.name).toBe("spacing");
223
- expect(selectorInstance.variables).toHaveLength(1);
224
- expect(selectorInstance.variables[0]).toBe(result);
225
- });
226
-
227
- it("should maintain type information when passing variable instance", () => {
228
- const base = variable("typed-var", "x");
229
- const result = variable(base, "y");
230
-
231
- const typedResult: Variable<"typed-var"> = result;
232
- expect(typedResult.name).toBe("typed-var");
233
- });
234
- });
235
- });
@@ -1,42 +0,0 @@
1
- import type { Container, Root, TokenValue, Variable } from "../types";
2
-
3
- export function createVariableFunction(parent: Container, _root: Root) {
4
- return function variable<Name extends string>(
5
- nameOrInstance: Name | Variable<Name>,
6
- value: TokenValue,
7
- options: {
8
- default: boolean;
9
- } = {
10
- default: false,
11
- },
12
- ): Variable<Name> {
13
- const name = (
14
- typeof nameOrInstance === "string" ? nameOrInstance : nameOrInstance.name
15
- ) as Name;
16
-
17
- const existingVariable = parent.variables.find(
18
- (child) => child.name === name,
19
- ) as Variable<Name> | undefined;
20
-
21
- // If default is true and the variable exists, return existing
22
- if (options.default && existingVariable) {
23
- return existingVariable;
24
- }
25
-
26
- // If default is false and the variable exists, update the value
27
- if (existingVariable) {
28
- existingVariable.value = value;
29
- return existingVariable;
30
- }
31
-
32
- // Create a new variable
33
- const instance: Variable<Name> = {
34
- type: "variable",
35
- name,
36
- value,
37
- };
38
-
39
- parent.variables.push(instance);
40
- return instance;
41
- };
42
- }
@@ -1,33 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { isTokenValue } from "./typeGuards";
3
- import type { Reference, CSS } from "./types";
4
-
5
- describe("isTokenValue", () => {
6
- it("should return true for primitive token values", () => {
7
- expect(isTokenValue("string")).toBe(true);
8
- expect(isTokenValue(42)).toBe(true);
9
- expect(isTokenValue(true)).toBe(true);
10
- expect(isTokenValue(null)).toBe(true);
11
- });
12
-
13
- it("should return true for Reference objects", () => {
14
- const ref: Reference = { type: "reference", name: "color" };
15
- expect(isTokenValue(ref)).toBe(true);
16
- });
17
-
18
- it("should return true for CSS objects", () => {
19
- const css: CSS = { type: "css", value: ["color", "red"] };
20
- expect(isTokenValue(css)).toBe(true);
21
- });
22
-
23
- it("should return true for arrays of token values", () => {
24
- const ref: Reference = { type: "reference", name: "size" };
25
- const css: CSS = { type: "css", value: ["margin", "0"] };
26
- expect(isTokenValue(["foo", ref, css])).toBe(true);
27
- });
28
-
29
- it("should return false for invalid values", () => {
30
- expect(isTokenValue({})).toBe(false);
31
- expect(isTokenValue(["foo", {}])).toBe(false);
32
- });
33
- });
package/src/typeGuards.ts DELETED
@@ -1,98 +0,0 @@
1
- import type {
2
- AtRule,
3
- Container,
4
- CSS,
5
- ModifierFactory,
6
- PrimitiveTokenValue,
7
- Reference,
8
- Root,
9
- Selector,
10
- Theme,
11
- TokenType,
12
- TokenValue,
13
- Utility,
14
- Variable,
15
- } from "./types";
16
-
17
- export function isObject(value: unknown): value is object {
18
- return typeof value === "object" && value !== null;
19
- }
20
-
21
- /**
22
- * Tokens
23
- */
24
-
25
- export function isToken<T>(value: unknown, type: TokenType): value is T {
26
- return isObject(value) && "type" in value && value.type === type;
27
- }
28
-
29
- export function isVariable<Name extends string = string>(
30
- value: unknown,
31
- ): value is Variable<Name> {
32
- return isToken(value, "variable");
33
- }
34
-
35
- export function isRef<Name extends string = string>(
36
- value: unknown,
37
- ): value is Reference<Name> {
38
- return isToken(value, "reference");
39
- }
40
-
41
- export function isSelector(value: unknown): value is Selector {
42
- return isToken(value, "selector");
43
- }
44
-
45
- export function isAtRule(value: unknown): value is AtRule {
46
- return isToken(value, "at-rule");
47
- }
48
-
49
- export function isUtility<Name extends string = string>(
50
- value: unknown,
51
- ): value is Utility<Name> {
52
- return isToken(value, "utility");
53
- }
54
-
55
- export function isModifier(value: unknown): value is ModifierFactory {
56
- return isToken(value, "modifier");
57
- }
58
-
59
- export function isCSS(value: unknown): value is CSS {
60
- return isToken(value, "css");
61
- }
62
-
63
- export function isTheme(value: unknown): value is Theme {
64
- return isToken(value, "theme");
65
- }
66
-
67
- export function isRoot(value: unknown): value is Root {
68
- return isToken(value, "root");
69
- }
70
-
71
- export function isPrimitiveTokenValue(
72
- value: unknown,
73
- ): value is PrimitiveTokenValue {
74
- return (
75
- typeof value === "string" ||
76
- typeof value === "number" ||
77
- typeof value === "boolean" ||
78
- value === null
79
- );
80
- }
81
-
82
- export function isTokenValue(value: unknown): value is TokenValue {
83
- return (
84
- isPrimitiveTokenValue(value) ||
85
- isRef(value) ||
86
- isCSS(value) ||
87
- (Array.isArray(value) && value.every(isTokenValue))
88
- );
89
- }
90
-
91
- export function isContainer(value: unknown): value is Container {
92
- return (
93
- isObject(value) &&
94
- "children" in value &&
95
- "declarations" in value &&
96
- "variables" in value
97
- );
98
- }
@@ -1,42 +0,0 @@
1
- import type { Properties as CSSProperties } from "csstype";
2
- import type {
3
- createAtRuleFunction,
4
- createCssFunction,
5
- createKeyframesFunction,
6
- createMediaFunction,
7
- createRefFunction,
8
- createSelectorFunction,
9
- createVariableFunction,
10
- } from "../tokens";
11
- import type { TokenValue } from "./tokens";
12
-
13
- // Helper type to make CSS property values also accept Reference types
14
- type CSSValueWithReference<T> = T extends string | number | undefined
15
- ? T | TokenValue
16
- : T extends object
17
- ? CSSValueWithReference<T>
18
- : T | TokenValue;
19
-
20
- // Recursively apply the Reference extension to all CSS properties
21
- export type DeclarationsBlock = {
22
- [K in keyof CSSProperties]: CSSValueWithReference<CSSProperties[K]>;
23
- } & {
24
- // Support for nested selectors (like '&:hover', '.child')
25
- [key: string]:
26
- | CSSValueWithReference<CSSProperties[keyof CSSProperties]>
27
- | DeclarationsBlock;
28
- };
29
-
30
- export type DeclarationsCallbackContext = {
31
- variable: ReturnType<typeof createVariableFunction>;
32
- selector: ReturnType<typeof createSelectorFunction>;
33
- atRule: ReturnType<typeof createAtRuleFunction>;
34
- keyframes: ReturnType<typeof createKeyframesFunction>;
35
- media: ReturnType<typeof createMediaFunction>;
36
- ref: ReturnType<typeof createRefFunction>;
37
- css: ReturnType<typeof createCssFunction>;
38
- };
39
-
40
- export type DeclarationsCallback<
41
- Context extends DeclarationsCallbackContext = DeclarationsCallbackContext,
42
- > = (context: Context) => DeclarationsBlock | void;
@@ -1,3 +0,0 @@
1
- export * from "./declarations";
2
- export * from "./options";
3
- export * from "./tokens";
@@ -1,22 +0,0 @@
1
- export type VariableNameFn = (options: { name: string }) => string;
2
-
3
- export type UtilitySelectorFn = (options: {
4
- name: string;
5
- value: string;
6
- modifiers: string[];
7
- }) => string;
8
-
9
- export type ThemeSelectorFn = (options: { name: string }) => string;
10
-
11
- export type StyleframeOptions = {
12
- indent?: string;
13
- variables?: {
14
- name?: VariableNameFn;
15
- };
16
- utilities?: {
17
- selector?: UtilitySelectorFn;
18
- };
19
- theme?: {
20
- selector?: ThemeSelectorFn;
21
- };
22
- };