@asafarim/design-tokens 0.3.1 → 0.3.4

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.
@@ -1,4 +1,4 @@
1
- [data-theme="dark"] {
1
+ :root {
2
2
  --asm-color-bg: #0B1220;
3
3
  --asm-color-surface: #0F172A;
4
4
  --asm-color-surface-muted: #111B2E;
@@ -1,4 +1,4 @@
1
- [data-contrast="high"] {
1
+ :root {
2
2
  --asm-color-bg: #000000;
3
3
  --asm-color-surface: #000000;
4
4
  --asm-color-surface-muted: #000000;
@@ -1,4 +1,4 @@
1
- [data-theme="light"] {
1
+ :root {
2
2
  --asm-color-bg: #F9FAFB;
3
3
  --asm-color-surface: #FFFFFF;
4
4
  --asm-color-surface-muted: #F3F4F6;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@asafarim/design-tokens",
3
- "version": "0.3.1",
3
+ "version": "0.3.4",
4
4
  "private": false,
5
- "description": "ASafariM design tokens (TypeScript + CSS variables) with multi-theme support.",
5
+ "description": "ASafariM design tokens (CSS variables) with multi-theme support.",
6
6
  "license": "MIT",
7
7
  "author": "ASafariM",
8
8
  "repository": {
@@ -13,55 +13,33 @@
13
13
  "design-tokens",
14
14
  "css-variables",
15
15
  "theming",
16
- "typescript",
17
16
  "react",
18
- "TypeScript",
19
17
  "CSS",
20
18
  "themes",
21
19
  "asafarim"
22
20
  ],
23
21
  "type": "module",
24
- "main": "./dist/index.cjs",
25
- "module": "./dist/index.js",
26
- "types": "./dist/index.d.ts",
27
- "style": "./dist/css/index.css",
22
+ "style": "css/index.css",
28
23
  "files": [
29
- "dist",
24
+ "css",
30
25
  "README.md",
31
26
  "CHANGELOG.md",
32
27
  "LICENSE"
33
28
  ],
34
29
  "sideEffects": [
35
- "dist/css/*.css"
30
+ "css/*.css"
36
31
  ],
37
32
  "exports": {
38
- ".": {
39
- "types": "./dist/index.d.ts",
40
- "import": "./dist/index.js",
41
- "require": "./dist/index.cjs"
42
- },
43
33
  "./css": {
44
- "style": "./dist/css/index.css",
45
- "default": "./dist/css/index.css"
46
- },
47
- "./dist/css/index.css": "./dist/css/index.css",
48
- "./build": {
49
- "types": "./dist/build/index.d.ts",
50
- "import": "./dist/build/index.js",
51
- "require": "./dist/build/index.cjs"
34
+ "style": "./css/index.css",
35
+ "default": "./css/index.css"
52
36
  },
37
+ "./css/index.css": "./css/index.css",
53
38
  "./package.json": "./package.json"
54
39
  },
55
- "devDependencies": {
56
- "tsup": "^8.5.0",
57
- "typescript": "^5.7.2"
58
- },
59
40
  "publishConfig": {
60
41
  "access": "public"
61
42
  },
62
- "peerDependencies": {
63
- "typescript": ">=4.0.0"
64
- },
65
43
  "engines": {
66
44
  "node": ">=16"
67
45
  },
@@ -70,9 +48,6 @@
70
48
  },
71
49
  "homepage": "https://github.com/AliSafari-IT/design-tokens#readme",
72
50
  "scripts": {
73
- "build": "tsup",
74
- "dev": "tsup --watch",
75
- "demo": "pnpm --filter design-tokens-demo dev",
76
- "lint:tokens": "node -e \"import('@asafarim/design-tokens').then(m => { const r = m.validateTokens(); if (!r.ok) { console.error(r); process.exit(1); } console.log('tokens ok'); })\""
51
+ "demo": "pnpm --filter design-tokens-demo dev"
77
52
  }
78
53
  }
@@ -1,166 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/build/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- toCssVarNames: () => toCssVarNames,
24
- toCssVars: () => toCssVars,
25
- toJson: () => toJson,
26
- tokenPathToCssVarName: () => tokenPathToCssVarName,
27
- validateTokens: () => validateTokens
28
- });
29
- module.exports = __toCommonJS(index_exports);
30
-
31
- // src/core/utils.ts
32
- function isTokenLeaf(value) {
33
- return typeof value === "object" && value !== null && "value" in value && "description" in value && (typeof value.value === "string" || typeof value.value === "number") && typeof value.description === "string";
34
- }
35
- function toKebabCase(input) {
36
- return input.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[_\s]+/g, "-").toLowerCase();
37
- }
38
- function walkTokenTree(tree, visitor, path = []) {
39
- for (const [key, value] of Object.entries(tree)) {
40
- const nextPath = [...path, key];
41
- if (isTokenLeaf(value)) {
42
- visitor({ path: nextPath, leaf: value });
43
- continue;
44
- }
45
- if (typeof value === "object" && value !== null) {
46
- walkTokenTree(value, visitor, nextPath);
47
- }
48
- }
49
- }
50
-
51
- // src/build/toCssVars.ts
52
- function tokenPathToCssVarName(path) {
53
- const kebabParts = path.map(toKebabCase);
54
- return `--asm-${kebabParts.join("-")}`;
55
- }
56
- function toCssVars(tree) {
57
- const out = {};
58
- walkTokenTree(tree, ({ path, leaf }) => {
59
- const cssVar = tokenPathToCssVarName(path);
60
- out[cssVar] = String(leaf.value);
61
- });
62
- return out;
63
- }
64
- function toCssVarNames(tree) {
65
- const out = {};
66
- walkTokenTree(tree, ({ path }) => {
67
- const dotPath = path.join(".");
68
- out[dotPath] = tokenPathToCssVarName(path);
69
- });
70
- return out;
71
- }
72
-
73
- // src/build/toJson.ts
74
- function toJson(tree) {
75
- const out = {};
76
- walkTokenTree(tree, ({ path, leaf }) => {
77
- const key = path.join(".");
78
- if (leaf.meta) {
79
- out[key] = { value: leaf.value, description: leaf.description, meta: leaf.meta };
80
- return;
81
- }
82
- out[key] = { value: leaf.value, description: leaf.description };
83
- });
84
- return out;
85
- }
86
-
87
- // src/build/validate.ts
88
- var HEX_COLOR = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
89
- function validateTokens(args) {
90
- const errors = [];
91
- const warnings = [];
92
- const seenDotKeys = /* @__PURE__ */ new Set();
93
- const seenCssVars = /* @__PURE__ */ new Set();
94
- walkTokenTree(args.tokens, ({ path, leaf }) => {
95
- const dotKey = path.join(".");
96
- if (seenDotKeys.has(dotKey)) {
97
- errors.push(`Duplicate token key: ${dotKey}`);
98
- } else {
99
- seenDotKeys.add(dotKey);
100
- }
101
- if (!leaf.description || leaf.description.trim().length === 0) {
102
- errors.push(`Missing description for token: ${dotKey}`);
103
- }
104
- const cssVar = tokenPathToCssVarName(path);
105
- if (!cssVar.startsWith("--asm-")) {
106
- errors.push(`Invalid CSS var prefix (must be --asm-): ${cssVar}`);
107
- }
108
- if (seenCssVars.has(cssVar)) {
109
- errors.push(`Duplicate CSS var name generated: ${cssVar} (from ${dotKey})`);
110
- } else {
111
- seenCssVars.add(cssVar);
112
- }
113
- const v = leaf.value;
114
- if (typeof v === "string" && v.startsWith("#") && !HEX_COLOR.test(v)) {
115
- errors.push(`Invalid hex color for ${dotKey}: ${v}`);
116
- }
117
- });
118
- const requiredThemeVars = [
119
- "--asm-color-bg",
120
- "--asm-color-surface",
121
- "--asm-color-text",
122
- "--asm-color-border",
123
- "--asm-color-button-primary-bg",
124
- "--asm-color-input-border-focus",
125
- "--asm-color-focus-ring",
126
- "--asm-color-overlay-scrim"
127
- ];
128
- const themeNames = new Set(args.themes.map((t) => t.name));
129
- for (const name of ["light", "dark", "high-contrast"]) {
130
- if (!themeNames.has(name)) {
131
- errors.push(`Missing required theme: ${name}`);
132
- }
133
- }
134
- for (const theme of args.themes) {
135
- if (theme.name !== "light" && theme.name !== "dark" && theme.name !== "high-contrast") {
136
- warnings.push(`Theme has non-standard name: ${theme.name}`);
137
- }
138
- for (const varName of requiredThemeVars) {
139
- if (!(varName in theme.tokens)) {
140
- errors.push(`Theme '${theme.name}' missing required token override: ${varName}`);
141
- }
142
- }
143
- for (const [key, value] of Object.entries(theme.tokens)) {
144
- if (!key.startsWith("--asm-")) {
145
- errors.push(`Theme '${theme.name}' contains non --asm- var: ${key}`);
146
- }
147
- if (typeof value === "string" && value.startsWith("#") && !HEX_COLOR.test(value)) {
148
- errors.push(`Theme '${theme.name}' invalid hex for ${key}: ${value}`);
149
- }
150
- }
151
- }
152
- return {
153
- ok: errors.length === 0,
154
- errors,
155
- warnings
156
- };
157
- }
158
- // Annotate the CommonJS export names for ESM import in node:
159
- 0 && (module.exports = {
160
- toCssVarNames,
161
- toCssVars,
162
- toJson,
163
- tokenPathToCssVarName,
164
- validateTokens
165
- });
166
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/build/index.ts","../../src/core/utils.ts","../../src/build/toCssVars.ts","../../src/build/toJson.ts","../../src/build/validate.ts"],"sourcesContent":["export { toCssVars, toCssVarNames, tokenPathToCssVarName } from \"./toCssVars\";\r\nexport { toJson } from \"./toJson\";\r\nexport { validateTokens } from \"./validate\";\r\nexport type { CssVarDict } from \"./toCssVars\";\r\nexport type { FlatTokenJson } from \"./toJson\";\r\n","import type { TokenLeaf, TokenTree } from \"./types\";\r\n\r\nexport function isTokenLeaf(value: unknown): value is TokenLeaf {\r\n return (\r\n typeof value === \"object\" &&\r\n value !== null &&\r\n \"value\" in value &&\r\n \"description\" in value &&\r\n (typeof (value as any).value === \"string\" || typeof (value as any).value === \"number\") &&\r\n typeof (value as any).description === \"string\"\r\n );\r\n}\r\n\r\nexport function toKebabCase(input: string): string {\r\n return input\r\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\r\n .replace(/[_\\s]+/g, \"-\")\r\n .toLowerCase();\r\n}\r\n\r\nexport function joinPath(path: string[], sep = \".\"): string {\r\n return path.filter(Boolean).join(sep);\r\n}\r\n\r\nexport function walkTokenTree(\r\n tree: TokenTree,\r\n visitor: (args: { path: string[]; leaf: TokenLeaf }) => void,\r\n path: string[] = []\r\n) {\r\n for (const [key, value] of Object.entries(tree)) {\r\n const nextPath = [...path, key];\r\n\r\n if (isTokenLeaf(value)) {\r\n visitor({ path: nextPath, leaf: value });\r\n continue;\r\n }\r\n\r\n if (typeof value === \"object\" && value !== null) {\r\n walkTokenTree(value as TokenTree, visitor, nextPath);\r\n }\r\n }\r\n}\r\n","import type { TokenTree } from \"../core/types\";\r\nimport { toKebabCase, walkTokenTree } from \"../core/utils\";\r\n\r\nexport type CssVarDict = Record<string, string>;\r\n\r\nexport function tokenPathToCssVarName(path: string[]): string {\r\n const kebabParts = path.map(toKebabCase);\r\n return `--asm-${kebabParts.join(\"-\")}`;\r\n}\r\n\r\nexport function toCssVars(tree: TokenTree): CssVarDict {\r\n const out: CssVarDict = {};\r\n\r\n walkTokenTree(tree, ({ path, leaf }) => {\r\n const cssVar = tokenPathToCssVarName(path);\r\n out[cssVar] = String(leaf.value);\r\n });\r\n\r\n return out;\r\n}\r\n\r\nexport function toCssVarNames(tree: TokenTree): Record<string, string> {\r\n const out: Record<string, string> = {};\r\n\r\n walkTokenTree(tree, ({ path }) => {\r\n const dotPath = path.join(\".\");\r\n out[dotPath] = tokenPathToCssVarName(path);\r\n });\r\n\r\n return out;\r\n}\r\n","import type { TokenTree } from \"../core/types\";\r\nimport { walkTokenTree } from \"../core/utils\";\r\n\r\nexport type FlatTokenJson = Record<string, { value: string | number; description: string; meta?: Record<string, unknown> }>;\r\n\r\nexport function toJson(tree: TokenTree): FlatTokenJson {\r\n const out: FlatTokenJson = {};\r\n\r\n walkTokenTree(tree, ({ path, leaf }) => {\r\n const key = path.join(\".\");\r\n if (leaf.meta) {\r\n out[key] = { value: leaf.value, description: leaf.description, meta: leaf.meta };\r\n return;\r\n }\r\n\r\n out[key] = { value: leaf.value, description: leaf.description };\r\n });\r\n\r\n return out;\r\n}\r\n","import type { ThemeDefinition, TokenTree, ValidateResult } from \"../core/types\";\r\nimport { walkTokenTree } from \"../core/utils\";\r\nimport { tokenPathToCssVarName } from \"./toCssVars\";\r\n\r\nconst HEX_COLOR = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;\r\n\r\nexport function validateTokens(args: {\r\n tokens: TokenTree;\r\n themes: ThemeDefinition[];\r\n}): ValidateResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n const seenDotKeys = new Set<string>();\r\n const seenCssVars = new Set<string>();\r\n\r\n walkTokenTree(args.tokens, ({ path, leaf }) => {\r\n const dotKey = path.join(\".\");\r\n if (seenDotKeys.has(dotKey)) {\r\n errors.push(`Duplicate token key: ${dotKey}`);\r\n } else {\r\n seenDotKeys.add(dotKey);\r\n }\r\n\r\n if (!leaf.description || leaf.description.trim().length === 0) {\r\n errors.push(`Missing description for token: ${dotKey}`);\r\n }\r\n\r\n const cssVar = tokenPathToCssVarName(path);\r\n if (!cssVar.startsWith(\"--asm-\")) {\r\n errors.push(`Invalid CSS var prefix (must be --asm-): ${cssVar}`);\r\n }\r\n\r\n if (seenCssVars.has(cssVar)) {\r\n errors.push(`Duplicate CSS var name generated: ${cssVar} (from ${dotKey})`);\r\n } else {\r\n seenCssVars.add(cssVar);\r\n }\r\n\r\n const v = leaf.value;\r\n if (typeof v === \"string\" && v.startsWith(\"#\") && !HEX_COLOR.test(v)) {\r\n errors.push(`Invalid hex color for ${dotKey}: ${v}`);\r\n }\r\n });\r\n\r\n const requiredThemeVars = [\r\n \"--asm-color-bg\",\r\n \"--asm-color-surface\",\r\n \"--asm-color-text\",\r\n \"--asm-color-border\",\r\n \"--asm-color-button-primary-bg\",\r\n \"--asm-color-input-border-focus\",\r\n \"--asm-color-focus-ring\",\r\n \"--asm-color-overlay-scrim\"\r\n ];\r\n\r\n const themeNames = new Set(args.themes.map(t => t.name));\r\n for (const name of [\"light\", \"dark\", \"high-contrast\"] as const) {\r\n if (!themeNames.has(name)) {\r\n errors.push(`Missing required theme: ${name}`);\r\n }\r\n }\r\n\r\n for (const theme of args.themes) {\r\n if (theme.name !== \"light\" && theme.name !== \"dark\" && theme.name !== \"high-contrast\") {\r\n warnings.push(`Theme has non-standard name: ${theme.name}`);\r\n }\r\n\r\n for (const varName of requiredThemeVars) {\r\n if (!(varName in theme.tokens)) {\r\n errors.push(`Theme '${theme.name}' missing required token override: ${varName}`);\r\n }\r\n }\r\n\r\n for (const [key, value] of Object.entries(theme.tokens)) {\r\n if (!key.startsWith(\"--asm-\")) {\r\n errors.push(`Theme '${theme.name}' contains non --asm- var: ${key}`);\r\n }\r\n if (typeof value === \"string\" && value.startsWith(\"#\") && !HEX_COLOR.test(value)) {\r\n errors.push(`Theme '${theme.name}' invalid hex for ${key}: ${value}`);\r\n }\r\n }\r\n }\r\n\r\n return {\r\n ok: errors.length === 0,\r\n errors,\r\n warnings\r\n };\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1,30 +0,0 @@
1
- type ThemeName = "light" | "dark" | "high-contrast";
2
- type ThemeDefinition = {
3
- name: ThemeName;
4
- tokens: Record<string, string | number>;
5
- };
6
- type TokenTree = Record<string, unknown>;
7
- type ValidateResult = {
8
- ok: boolean;
9
- errors: string[];
10
- warnings: string[];
11
- };
12
-
13
- type CssVarDict = Record<string, string>;
14
- declare function tokenPathToCssVarName(path: string[]): string;
15
- declare function toCssVars(tree: TokenTree): CssVarDict;
16
- declare function toCssVarNames(tree: TokenTree): Record<string, string>;
17
-
18
- type FlatTokenJson = Record<string, {
19
- value: string | number;
20
- description: string;
21
- meta?: Record<string, unknown>;
22
- }>;
23
- declare function toJson(tree: TokenTree): FlatTokenJson;
24
-
25
- declare function validateTokens(args: {
26
- tokens: TokenTree;
27
- themes: ThemeDefinition[];
28
- }): ValidateResult;
29
-
30
- export { type CssVarDict, type FlatTokenJson, toCssVarNames, toCssVars, toJson, tokenPathToCssVarName, validateTokens };
@@ -1,30 +0,0 @@
1
- type ThemeName = "light" | "dark" | "high-contrast";
2
- type ThemeDefinition = {
3
- name: ThemeName;
4
- tokens: Record<string, string | number>;
5
- };
6
- type TokenTree = Record<string, unknown>;
7
- type ValidateResult = {
8
- ok: boolean;
9
- errors: string[];
10
- warnings: string[];
11
- };
12
-
13
- type CssVarDict = Record<string, string>;
14
- declare function tokenPathToCssVarName(path: string[]): string;
15
- declare function toCssVars(tree: TokenTree): CssVarDict;
16
- declare function toCssVarNames(tree: TokenTree): Record<string, string>;
17
-
18
- type FlatTokenJson = Record<string, {
19
- value: string | number;
20
- description: string;
21
- meta?: Record<string, unknown>;
22
- }>;
23
- declare function toJson(tree: TokenTree): FlatTokenJson;
24
-
25
- declare function validateTokens(args: {
26
- tokens: TokenTree;
27
- themes: ThemeDefinition[];
28
- }): ValidateResult;
29
-
30
- export { type CssVarDict, type FlatTokenJson, toCssVarNames, toCssVars, toJson, tokenPathToCssVarName, validateTokens };
@@ -1,135 +0,0 @@
1
- // src/core/utils.ts
2
- function isTokenLeaf(value) {
3
- return typeof value === "object" && value !== null && "value" in value && "description" in value && (typeof value.value === "string" || typeof value.value === "number") && typeof value.description === "string";
4
- }
5
- function toKebabCase(input) {
6
- return input.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[_\s]+/g, "-").toLowerCase();
7
- }
8
- function walkTokenTree(tree, visitor, path = []) {
9
- for (const [key, value] of Object.entries(tree)) {
10
- const nextPath = [...path, key];
11
- if (isTokenLeaf(value)) {
12
- visitor({ path: nextPath, leaf: value });
13
- continue;
14
- }
15
- if (typeof value === "object" && value !== null) {
16
- walkTokenTree(value, visitor, nextPath);
17
- }
18
- }
19
- }
20
-
21
- // src/build/toCssVars.ts
22
- function tokenPathToCssVarName(path) {
23
- const kebabParts = path.map(toKebabCase);
24
- return `--asm-${kebabParts.join("-")}`;
25
- }
26
- function toCssVars(tree) {
27
- const out = {};
28
- walkTokenTree(tree, ({ path, leaf }) => {
29
- const cssVar = tokenPathToCssVarName(path);
30
- out[cssVar] = String(leaf.value);
31
- });
32
- return out;
33
- }
34
- function toCssVarNames(tree) {
35
- const out = {};
36
- walkTokenTree(tree, ({ path }) => {
37
- const dotPath = path.join(".");
38
- out[dotPath] = tokenPathToCssVarName(path);
39
- });
40
- return out;
41
- }
42
-
43
- // src/build/toJson.ts
44
- function toJson(tree) {
45
- const out = {};
46
- walkTokenTree(tree, ({ path, leaf }) => {
47
- const key = path.join(".");
48
- if (leaf.meta) {
49
- out[key] = { value: leaf.value, description: leaf.description, meta: leaf.meta };
50
- return;
51
- }
52
- out[key] = { value: leaf.value, description: leaf.description };
53
- });
54
- return out;
55
- }
56
-
57
- // src/build/validate.ts
58
- var HEX_COLOR = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
59
- function validateTokens(args) {
60
- const errors = [];
61
- const warnings = [];
62
- const seenDotKeys = /* @__PURE__ */ new Set();
63
- const seenCssVars = /* @__PURE__ */ new Set();
64
- walkTokenTree(args.tokens, ({ path, leaf }) => {
65
- const dotKey = path.join(".");
66
- if (seenDotKeys.has(dotKey)) {
67
- errors.push(`Duplicate token key: ${dotKey}`);
68
- } else {
69
- seenDotKeys.add(dotKey);
70
- }
71
- if (!leaf.description || leaf.description.trim().length === 0) {
72
- errors.push(`Missing description for token: ${dotKey}`);
73
- }
74
- const cssVar = tokenPathToCssVarName(path);
75
- if (!cssVar.startsWith("--asm-")) {
76
- errors.push(`Invalid CSS var prefix (must be --asm-): ${cssVar}`);
77
- }
78
- if (seenCssVars.has(cssVar)) {
79
- errors.push(`Duplicate CSS var name generated: ${cssVar} (from ${dotKey})`);
80
- } else {
81
- seenCssVars.add(cssVar);
82
- }
83
- const v = leaf.value;
84
- if (typeof v === "string" && v.startsWith("#") && !HEX_COLOR.test(v)) {
85
- errors.push(`Invalid hex color for ${dotKey}: ${v}`);
86
- }
87
- });
88
- const requiredThemeVars = [
89
- "--asm-color-bg",
90
- "--asm-color-surface",
91
- "--asm-color-text",
92
- "--asm-color-border",
93
- "--asm-color-button-primary-bg",
94
- "--asm-color-input-border-focus",
95
- "--asm-color-focus-ring",
96
- "--asm-color-overlay-scrim"
97
- ];
98
- const themeNames = new Set(args.themes.map((t) => t.name));
99
- for (const name of ["light", "dark", "high-contrast"]) {
100
- if (!themeNames.has(name)) {
101
- errors.push(`Missing required theme: ${name}`);
102
- }
103
- }
104
- for (const theme of args.themes) {
105
- if (theme.name !== "light" && theme.name !== "dark" && theme.name !== "high-contrast") {
106
- warnings.push(`Theme has non-standard name: ${theme.name}`);
107
- }
108
- for (const varName of requiredThemeVars) {
109
- if (!(varName in theme.tokens)) {
110
- errors.push(`Theme '${theme.name}' missing required token override: ${varName}`);
111
- }
112
- }
113
- for (const [key, value] of Object.entries(theme.tokens)) {
114
- if (!key.startsWith("--asm-")) {
115
- errors.push(`Theme '${theme.name}' contains non --asm- var: ${key}`);
116
- }
117
- if (typeof value === "string" && value.startsWith("#") && !HEX_COLOR.test(value)) {
118
- errors.push(`Theme '${theme.name}' invalid hex for ${key}: ${value}`);
119
- }
120
- }
121
- }
122
- return {
123
- ok: errors.length === 0,
124
- errors,
125
- warnings
126
- };
127
- }
128
- export {
129
- toCssVarNames,
130
- toCssVars,
131
- toJson,
132
- tokenPathToCssVarName,
133
- validateTokens
134
- };
135
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/core/utils.ts","../../src/build/toCssVars.ts","../../src/build/toJson.ts","../../src/build/validate.ts"],"sourcesContent":["import type { TokenLeaf, TokenTree } from \"./types\";\r\n\r\nexport function isTokenLeaf(value: unknown): value is TokenLeaf {\r\n return (\r\n typeof value === \"object\" &&\r\n value !== null &&\r\n \"value\" in value &&\r\n \"description\" in value &&\r\n (typeof (value as any).value === \"string\" || typeof (value as any).value === \"number\") &&\r\n typeof (value as any).description === \"string\"\r\n );\r\n}\r\n\r\nexport function toKebabCase(input: string): string {\r\n return input\r\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\r\n .replace(/[_\\s]+/g, \"-\")\r\n .toLowerCase();\r\n}\r\n\r\nexport function joinPath(path: string[], sep = \".\"): string {\r\n return path.filter(Boolean).join(sep);\r\n}\r\n\r\nexport function walkTokenTree(\r\n tree: TokenTree,\r\n visitor: (args: { path: string[]; leaf: TokenLeaf }) => void,\r\n path: string[] = []\r\n) {\r\n for (const [key, value] of Object.entries(tree)) {\r\n const nextPath = [...path, key];\r\n\r\n if (isTokenLeaf(value)) {\r\n visitor({ path: nextPath, leaf: value });\r\n continue;\r\n }\r\n\r\n if (typeof value === \"object\" && value !== null) {\r\n walkTokenTree(value as TokenTree, visitor, nextPath);\r\n }\r\n }\r\n}\r\n","import type { TokenTree } from \"../core/types\";\r\nimport { toKebabCase, walkTokenTree } from \"../core/utils\";\r\n\r\nexport type CssVarDict = Record<string, string>;\r\n\r\nexport function tokenPathToCssVarName(path: string[]): string {\r\n const kebabParts = path.map(toKebabCase);\r\n return `--asm-${kebabParts.join(\"-\")}`;\r\n}\r\n\r\nexport function toCssVars(tree: TokenTree): CssVarDict {\r\n const out: CssVarDict = {};\r\n\r\n walkTokenTree(tree, ({ path, leaf }) => {\r\n const cssVar = tokenPathToCssVarName(path);\r\n out[cssVar] = String(leaf.value);\r\n });\r\n\r\n return out;\r\n}\r\n\r\nexport function toCssVarNames(tree: TokenTree): Record<string, string> {\r\n const out: Record<string, string> = {};\r\n\r\n walkTokenTree(tree, ({ path }) => {\r\n const dotPath = path.join(\".\");\r\n out[dotPath] = tokenPathToCssVarName(path);\r\n });\r\n\r\n return out;\r\n}\r\n","import type { TokenTree } from \"../core/types\";\r\nimport { walkTokenTree } from \"../core/utils\";\r\n\r\nexport type FlatTokenJson = Record<string, { value: string | number; description: string; meta?: Record<string, unknown> }>;\r\n\r\nexport function toJson(tree: TokenTree): FlatTokenJson {\r\n const out: FlatTokenJson = {};\r\n\r\n walkTokenTree(tree, ({ path, leaf }) => {\r\n const key = path.join(\".\");\r\n if (leaf.meta) {\r\n out[key] = { value: leaf.value, description: leaf.description, meta: leaf.meta };\r\n return;\r\n }\r\n\r\n out[key] = { value: leaf.value, description: leaf.description };\r\n });\r\n\r\n return out;\r\n}\r\n","import type { ThemeDefinition, TokenTree, ValidateResult } from \"../core/types\";\r\nimport { walkTokenTree } from \"../core/utils\";\r\nimport { tokenPathToCssVarName } from \"./toCssVars\";\r\n\r\nconst HEX_COLOR = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;\r\n\r\nexport function validateTokens(args: {\r\n tokens: TokenTree;\r\n themes: ThemeDefinition[];\r\n}): ValidateResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n const seenDotKeys = new Set<string>();\r\n const seenCssVars = new Set<string>();\r\n\r\n walkTokenTree(args.tokens, ({ path, leaf }) => {\r\n const dotKey = path.join(\".\");\r\n if (seenDotKeys.has(dotKey)) {\r\n errors.push(`Duplicate token key: ${dotKey}`);\r\n } else {\r\n seenDotKeys.add(dotKey);\r\n }\r\n\r\n if (!leaf.description || leaf.description.trim().length === 0) {\r\n errors.push(`Missing description for token: ${dotKey}`);\r\n }\r\n\r\n const cssVar = tokenPathToCssVarName(path);\r\n if (!cssVar.startsWith(\"--asm-\")) {\r\n errors.push(`Invalid CSS var prefix (must be --asm-): ${cssVar}`);\r\n }\r\n\r\n if (seenCssVars.has(cssVar)) {\r\n errors.push(`Duplicate CSS var name generated: ${cssVar} (from ${dotKey})`);\r\n } else {\r\n seenCssVars.add(cssVar);\r\n }\r\n\r\n const v = leaf.value;\r\n if (typeof v === \"string\" && v.startsWith(\"#\") && !HEX_COLOR.test(v)) {\r\n errors.push(`Invalid hex color for ${dotKey}: ${v}`);\r\n }\r\n });\r\n\r\n const requiredThemeVars = [\r\n \"--asm-color-bg\",\r\n \"--asm-color-surface\",\r\n \"--asm-color-text\",\r\n \"--asm-color-border\",\r\n \"--asm-color-button-primary-bg\",\r\n \"--asm-color-input-border-focus\",\r\n \"--asm-color-focus-ring\",\r\n \"--asm-color-overlay-scrim\"\r\n ];\r\n\r\n const themeNames = new Set(args.themes.map(t => t.name));\r\n for (const name of [\"light\", \"dark\", \"high-contrast\"] as const) {\r\n if (!themeNames.has(name)) {\r\n errors.push(`Missing required theme: ${name}`);\r\n }\r\n }\r\n\r\n for (const theme of args.themes) {\r\n if (theme.name !== \"light\" && theme.name !== \"dark\" && theme.name !== \"high-contrast\") {\r\n warnings.push(`Theme has non-standard name: ${theme.name}`);\r\n }\r\n\r\n for (const varName of requiredThemeVars) {\r\n if (!(varName in theme.tokens)) {\r\n errors.push(`Theme '${theme.name}' missing required token override: ${varName}`);\r\n }\r\n }\r\n\r\n for (const [key, value] of Object.entries(theme.tokens)) {\r\n if (!key.startsWith(\"--asm-\")) {\r\n errors.push(`Theme '${theme.name}' contains non --asm- var: ${key}`);\r\n }\r\n if (typeof value === \"string\" && value.startsWith(\"#\") && !HEX_COLOR.test(value)) {\r\n errors.push(`Theme '${theme.name}' invalid hex for ${key}: ${value}`);\r\n }\r\n }\r\n }\r\n\r\n return {\r\n ok: errors.length === 0,\r\n errors,\r\n warnings\r\n };\r\n}\r\n"],"mappings":"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","names":[]}