@styleframe/core 1.0.0 → 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.
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/dist/styleframe.d.ts +301 -0
- package/dist/styleframe.js +528 -0
- package/dist/styleframe.umd.cjs +1 -0
- package/package.json +13 -3
- package/.tsbuildinfo +0 -1
- package/src/index.ts +0 -5
- package/src/styleframe.ts +0 -64
- package/src/tokens/atRule.test.ts +0 -1013
- package/src/tokens/atRule.ts +0 -67
- package/src/tokens/css.test.ts +0 -404
- package/src/tokens/css.ts +0 -23
- package/src/tokens/declarations.test.ts +0 -584
- package/src/tokens/declarations.ts +0 -71
- package/src/tokens/index.ts +0 -11
- package/src/tokens/modifier.test.ts +0 -90
- package/src/tokens/modifier.ts +0 -86
- package/src/tokens/recipe.test.ts +0 -105
- package/src/tokens/recipe.ts +0 -32
- package/src/tokens/ref.test.ts +0 -430
- package/src/tokens/ref.ts +0 -24
- package/src/tokens/root.test.ts +0 -70
- package/src/tokens/root.ts +0 -14
- package/src/tokens/selector.test.ts +0 -440
- package/src/tokens/selector.ts +0 -47
- package/src/tokens/theme.test.ts +0 -338
- package/src/tokens/theme.ts +0 -26
- package/src/tokens/utility.test.ts +0 -1456
- package/src/tokens/utility.ts +0 -92
- package/src/tokens/variable.test.ts +0 -235
- package/src/tokens/variable.ts +0 -42
- package/src/typeGuards.test.ts +0 -33
- package/src/typeGuards.ts +0 -98
- package/src/types/declarations.ts +0 -42
- package/src/types/index.ts +0 -3
- package/src/types/options.ts +0 -22
- package/src/types/tokens.ts +0 -149
- package/src/utils/capitalizeFirst.ts +0 -9
- package/src/utils/deepClone.ts +0 -317
- package/src/utils/getters.test.ts +0 -399
- package/src/utils/getters.ts +0 -36
- package/src/utils/index.ts +0 -4
- package/src/utils/merge.test.ts +0 -978
- package/src/utils/merge.ts +0 -73
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.json +0 -7
- package/vite.config.ts +0 -5
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { combineKeys } from "./modifier";
|
|
2
|
-
|
|
3
|
-
describe("combineKeys", () => {
|
|
4
|
-
it("returns empty array for empty input", () => {
|
|
5
|
-
expect(combineKeys([])).toEqual([]);
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
it("handles a single string", () => {
|
|
9
|
-
expect(combineKeys([["hover"]])).toEqual([["hover"]]);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it("combines two strings and sorts combinations by length then alphabetically", () => {
|
|
13
|
-
const result = combineKeys([["hover"], ["focus"]]);
|
|
14
|
-
expect(result).toEqual([["focus"], ["hover"], ["focus", "hover"]]);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("combines a string with an array, without combining elements within the array", () => {
|
|
18
|
-
const result = combineKeys([["hover"], ["sm", "md"]]);
|
|
19
|
-
expect(result).toEqual([
|
|
20
|
-
// singles (alphabetical)
|
|
21
|
-
["hover"],
|
|
22
|
-
["md"],
|
|
23
|
-
["sm"],
|
|
24
|
-
// pairs (alphabetical within and across combinations)
|
|
25
|
-
["hover", "md"],
|
|
26
|
-
["hover", "sm"],
|
|
27
|
-
]);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("combines two arrays, choosing at most one element from each", () => {
|
|
31
|
-
const result = combineKeys([
|
|
32
|
-
["sm", "md"],
|
|
33
|
-
["active", "hover"],
|
|
34
|
-
]);
|
|
35
|
-
expect(result).toEqual([
|
|
36
|
-
// singles (alphabetical)
|
|
37
|
-
["active"],
|
|
38
|
-
["hover"],
|
|
39
|
-
["md"],
|
|
40
|
-
["sm"],
|
|
41
|
-
// pairs (cross-product, alphabetical within and across)
|
|
42
|
-
["active", "md"],
|
|
43
|
-
["active", "sm"],
|
|
44
|
-
["hover", "md"],
|
|
45
|
-
["hover", "sm"],
|
|
46
|
-
]);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it("does not combine elements within the same array when only one array is provided", () => {
|
|
50
|
-
const result = combineKeys([["a", "b", "c"]]);
|
|
51
|
-
expect(result).toEqual([["a"], ["b"], ["c"]]);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("generates combinations across three groups and maintains order and uniqueness", () => {
|
|
55
|
-
const result = combineKeys([["focus"], ["sm", "md"], ["hover", "active"]]);
|
|
56
|
-
|
|
57
|
-
// Expect exact ordering: first by length, then alphabetical within each length
|
|
58
|
-
expect(result).toEqual([
|
|
59
|
-
// singles
|
|
60
|
-
["active"],
|
|
61
|
-
["focus"],
|
|
62
|
-
["hover"],
|
|
63
|
-
["md"],
|
|
64
|
-
["sm"],
|
|
65
|
-
// pairs
|
|
66
|
-
["active", "focus"],
|
|
67
|
-
["active", "md"],
|
|
68
|
-
["active", "sm"],
|
|
69
|
-
["focus", "hover"],
|
|
70
|
-
["focus", "md"],
|
|
71
|
-
["focus", "sm"],
|
|
72
|
-
["hover", "md"],
|
|
73
|
-
["hover", "sm"],
|
|
74
|
-
// triples
|
|
75
|
-
["active", "focus", "md"],
|
|
76
|
-
["active", "focus", "sm"],
|
|
77
|
-
["focus", "hover", "md"],
|
|
78
|
-
["focus", "hover", "sm"],
|
|
79
|
-
]);
|
|
80
|
-
|
|
81
|
-
// Assert no duplicates present (defensive check)
|
|
82
|
-
const unique = new Set(result.map((r) => r.join(",")));
|
|
83
|
-
expect(unique.size).toBe(result.length);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("sorts elements within each combination alphabetically", () => {
|
|
87
|
-
const result = combineKeys([["b"], ["a"]]);
|
|
88
|
-
expect(result).toEqual([["a"], ["b"], ["a", "b"]]);
|
|
89
|
-
});
|
|
90
|
-
});
|
package/src/tokens/modifier.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import type { Container, ModifierFactory, Root } from "../types";
|
|
2
|
-
import { deepClone } from "../utils";
|
|
3
|
-
import {
|
|
4
|
-
createDeclarationsCallbackContext,
|
|
5
|
-
parseDeclarationsBlock,
|
|
6
|
-
} from "./declarations";
|
|
7
|
-
|
|
8
|
-
export function combineKeys(groups: string[][]): string[][] {
|
|
9
|
-
const result: string[][] = [];
|
|
10
|
-
|
|
11
|
-
// Generate all combinations using recursive approach
|
|
12
|
-
function generateCombinations(groupIndex: number, current: string[]) {
|
|
13
|
-
// Add current combination if not empty
|
|
14
|
-
if (current.length > 0) {
|
|
15
|
-
result.push([...current].sort());
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Try adding elements from remaining groups
|
|
19
|
-
for (let i = groupIndex; i < groups.length; i++) {
|
|
20
|
-
const group = groups[i];
|
|
21
|
-
|
|
22
|
-
if (group) {
|
|
23
|
-
if (group.length === 1 && !!group[0]) {
|
|
24
|
-
// Single element (originally a string) - can always add
|
|
25
|
-
generateCombinations(i + 1, [...current, group[0]]);
|
|
26
|
-
} else {
|
|
27
|
-
// Array group - add at most one element
|
|
28
|
-
for (const element of group) {
|
|
29
|
-
generateCombinations(i + 1, [...current, element]);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
generateCombinations(0, []);
|
|
37
|
-
|
|
38
|
-
// Sort result: first by length, then alphabetically
|
|
39
|
-
return result.sort((a, b) => {
|
|
40
|
-
if (a.length !== b.length) return a.length - b.length;
|
|
41
|
-
return a.join(",").localeCompare(b.join(","));
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function applyModifiers<InstanceType extends Container>(
|
|
46
|
-
baseInstance: InstanceType,
|
|
47
|
-
root: Root,
|
|
48
|
-
modifiers: Map<string, ModifierFactory>,
|
|
49
|
-
): InstanceType {
|
|
50
|
-
const instance: InstanceType = {
|
|
51
|
-
...baseInstance,
|
|
52
|
-
modifiers: [...modifiers.keys()],
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const callbackContext = createDeclarationsCallbackContext(instance, root);
|
|
56
|
-
|
|
57
|
-
for (const modifier of modifiers.values()) {
|
|
58
|
-
modifier.factory({
|
|
59
|
-
...callbackContext,
|
|
60
|
-
declarations: deepClone(instance.declarations),
|
|
61
|
-
variables: deepClone(instance.variables),
|
|
62
|
-
children: deepClone(instance.children),
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
parseDeclarationsBlock(instance.declarations, callbackContext);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return instance;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function createModifierFunction(_parent: Container, root: Root) {
|
|
72
|
-
return function modifier<Key extends string>(
|
|
73
|
-
key: Key | Key[],
|
|
74
|
-
factory: ModifierFactory["factory"],
|
|
75
|
-
): ModifierFactory {
|
|
76
|
-
const modifierInstance: ModifierFactory = {
|
|
77
|
-
type: "modifier",
|
|
78
|
-
key: Array.isArray(key) ? key : [key],
|
|
79
|
-
factory,
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
root.modifiers.push(modifierInstance);
|
|
83
|
-
|
|
84
|
-
return modifierInstance;
|
|
85
|
-
};
|
|
86
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, test } from "vitest";
|
|
2
|
-
import type { Root } from "../types";
|
|
3
|
-
import { createRecipeFunction } from "./recipe";
|
|
4
|
-
import { createRoot } from "./root";
|
|
5
|
-
|
|
6
|
-
describe("createRecipeFunction", () => {
|
|
7
|
-
let root: Root;
|
|
8
|
-
let recipe: ReturnType<typeof createRecipeFunction>;
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
root = createRoot();
|
|
12
|
-
recipe = createRecipeFunction(root, root);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
test("should create a recipe function", () => {
|
|
16
|
-
expect(recipe).toBeTypeOf("function");
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("should register recipe in root.recipes only", () => {
|
|
20
|
-
const instance = recipe(
|
|
21
|
-
"button",
|
|
22
|
-
{ borderWidth: "thin", borderStyle: "solid" },
|
|
23
|
-
{
|
|
24
|
-
color: {
|
|
25
|
-
primary: { background: "primary", color: "white" },
|
|
26
|
-
secondary: { background: "secondary", color: "white" },
|
|
27
|
-
},
|
|
28
|
-
size: {
|
|
29
|
-
sm: { padding: "sm" },
|
|
30
|
-
md: { padding: "md" },
|
|
31
|
-
lg: { padding: "lg" },
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
expect(instance).toEqual({
|
|
37
|
-
type: "recipe",
|
|
38
|
-
name: "button",
|
|
39
|
-
defaults: { borderWidth: "thin", borderStyle: "solid" },
|
|
40
|
-
variants: {
|
|
41
|
-
color: {
|
|
42
|
-
primary: { background: "primary", color: "white" },
|
|
43
|
-
secondary: { background: "secondary", color: "white" },
|
|
44
|
-
},
|
|
45
|
-
size: {
|
|
46
|
-
sm: { padding: "sm" },
|
|
47
|
-
md: { padding: "md" },
|
|
48
|
-
lg: { padding: "lg" },
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
expect(root.recipes).toHaveLength(1);
|
|
54
|
-
expect(root.recipes[0]).toBe(instance);
|
|
55
|
-
|
|
56
|
-
// Ensure no selectors/variables were created
|
|
57
|
-
expect(root.children).toHaveLength(0);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test("should support options: defaultVariants and compoundVariants", () => {
|
|
61
|
-
const instance = recipe(
|
|
62
|
-
"chip",
|
|
63
|
-
{ borderWidth: "thin" },
|
|
64
|
-
{
|
|
65
|
-
variant: {
|
|
66
|
-
filled: { background: "primary", color: "white" },
|
|
67
|
-
outline: { background: "transparent", color: "primary" },
|
|
68
|
-
},
|
|
69
|
-
size: {
|
|
70
|
-
sm: { padding: "sm" },
|
|
71
|
-
md: { padding: "md" },
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
defaultVariants: { variant: "filled", size: "sm" },
|
|
76
|
-
compoundVariants: [
|
|
77
|
-
{
|
|
78
|
-
variant: "filled",
|
|
79
|
-
size: "sm",
|
|
80
|
-
declarations: { background: "primary", color: "white" },
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
},
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
expect(instance.defaultVariants).toEqual({
|
|
87
|
-
variant: "filled",
|
|
88
|
-
size: "sm",
|
|
89
|
-
});
|
|
90
|
-
expect(instance.compoundVariants?.length).toBe(1);
|
|
91
|
-
expect(instance.compoundVariants).toEqual([
|
|
92
|
-
{
|
|
93
|
-
variant: "filled",
|
|
94
|
-
size: "sm",
|
|
95
|
-
declarations: { background: "primary", color: "white" },
|
|
96
|
-
},
|
|
97
|
-
]);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
test("should maintain type information for recipe name", () => {
|
|
101
|
-
const instance = recipe("typed-recipe", {}, {});
|
|
102
|
-
const name: "typed-recipe" = instance.name;
|
|
103
|
-
expect(name).toBe("typed-recipe");
|
|
104
|
-
});
|
|
105
|
-
});
|
package/src/tokens/recipe.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
Container,
|
|
3
|
-
Recipe,
|
|
4
|
-
Root,
|
|
5
|
-
VariantDeclarationsBlock,
|
|
6
|
-
} from "../types";
|
|
7
|
-
|
|
8
|
-
export function createRecipeFunction(_parent: Container, root: Root) {
|
|
9
|
-
return function recipe<
|
|
10
|
-
Name extends string,
|
|
11
|
-
Variants extends Record<string, Record<string, VariantDeclarationsBlock>>,
|
|
12
|
-
>(
|
|
13
|
-
name: Name,
|
|
14
|
-
defaults: Recipe<Name, Variants>["defaults"],
|
|
15
|
-
variants: Recipe<Name, Variants>["variants"],
|
|
16
|
-
options?: {
|
|
17
|
-
defaultVariants?: Recipe<Name, Variants>["defaultVariants"];
|
|
18
|
-
compoundVariants?: Recipe<Name, Variants>["compoundVariants"];
|
|
19
|
-
},
|
|
20
|
-
): Recipe<Name, Variants> {
|
|
21
|
-
const instance: Recipe<Name, Variants> = {
|
|
22
|
-
type: "recipe",
|
|
23
|
-
name,
|
|
24
|
-
defaults,
|
|
25
|
-
variants,
|
|
26
|
-
...options,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
root.recipes.push(instance);
|
|
30
|
-
return instance;
|
|
31
|
-
};
|
|
32
|
-
}
|