@asafarim/design-tokens 0.3.6 → 0.4.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 (63) hide show
  1. package/css/tokens.base.css +52 -9
  2. package/package.json +10 -3
  3. package/src/build/index.ts +5 -0
  4. package/src/build/toCssVars.ts +31 -0
  5. package/src/build/toJson.ts +20 -0
  6. package/src/build/validate.ts +90 -0
  7. package/src/core/types.ts +29 -0
  8. package/src/core/utils.ts +42 -0
  9. package/src/index.ts +60 -0
  10. package/src/themes/dark.ts +64 -0
  11. package/src/themes/densityComfortable.ts +11 -0
  12. package/src/themes/densityCompact.ts +11 -0
  13. package/src/themes/highContrast.ts +60 -0
  14. package/src/themes/index.ts +21 -0
  15. package/src/themes/light.ts +64 -0
  16. package/src/tokens/color/accent.ts +20 -0
  17. package/src/tokens/color/brand.ts +41 -0
  18. package/src/tokens/color/dataViz.ts +20 -0
  19. package/src/tokens/color/gradients.ts +13 -0
  20. package/src/tokens/color/index.ts +7 -0
  21. package/src/tokens/color/neutral.ts +32 -0
  22. package/src/tokens/color/overlays.ts +21 -0
  23. package/src/tokens/color/semantic.ts +36 -0
  24. package/src/tokens/effects/blur.ts +7 -0
  25. package/src/tokens/effects/index.ts +4 -0
  26. package/src/tokens/effects/opacity.ts +11 -0
  27. package/src/tokens/effects/shadows.ts +20 -0
  28. package/src/tokens/effects/textures.ts +11 -0
  29. package/src/tokens/iconography/index.ts +2 -0
  30. package/src/tokens/iconography/sizes.ts +9 -0
  31. package/src/tokens/iconography/strokeWidths.ts +7 -0
  32. package/src/tokens/index.ts +21 -0
  33. package/src/tokens/motion/duration.ts +7 -0
  34. package/src/tokens/motion/easing.ts +8 -0
  35. package/src/tokens/motion/index.ts +4 -0
  36. package/src/tokens/motion/reducedMotion.ts +9 -0
  37. package/src/tokens/motion/transitions.ts +16 -0
  38. package/src/tokens/shape/borders.ts +7 -0
  39. package/src/tokens/shape/index.ts +3 -0
  40. package/src/tokens/shape/radii.ts +9 -0
  41. package/src/tokens/shape/strokes.ts +7 -0
  42. package/src/tokens/spacing/density.ts +12 -0
  43. package/src/tokens/spacing/grid.ts +28 -0
  44. package/src/tokens/spacing/index.ts +5 -0
  45. package/src/tokens/spacing/layout.ts +20 -0
  46. package/src/tokens/spacing/rtl.ts +20 -0
  47. package/src/tokens/spacing/scale.ts +15 -0
  48. package/src/tokens/typography/families.ts +14 -0
  49. package/src/tokens/typography/headings.ts +29 -0
  50. package/src/tokens/typography/index.ts +7 -0
  51. package/src/tokens/typography/letterSpacing.ts +7 -0
  52. package/src/tokens/typography/lineHeights.ts +13 -0
  53. package/src/tokens/typography/responsive.ts +21 -0
  54. package/src/tokens/typography/sizes.ts +14 -0
  55. package/src/tokens/typography/weights.ts +13 -0
  56. package/src/tokens/ui/button.ts +25 -0
  57. package/src/tokens/ui/focus.ts +7 -0
  58. package/src/tokens/ui/index.ts +5 -0
  59. package/src/tokens/ui/input.ts +12 -0
  60. package/src/tokens/ui/overlay.ts +6 -0
  61. package/src/tokens/ui/surface.ts +9 -0
  62. package/src/tokens/zindex/index.ts +1 -0
  63. package/src/tokens/zindex/scale.ts +12 -0
@@ -1,10 +1,50 @@
1
- @import url("https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap");
2
- @import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@100..900&display=swap");
3
- @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@100..900&display=swap");
1
+ /* ------------------------------------------------------------------ */
2
+ /* 20 fonts (100-900) Google Fonts */
3
+ /* ------------------------------------------------------------------ */
4
+ @import url("https://fonts.googleapis.com/css2?family=Barlow:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Figtree:ital,wght@0,300..900;1,300..900&family=Jost:ital,wght@0,100..900;1,100..900&family=Karla:ital,wght@0,200..800;1,200..800&family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&family=Lexend:wght@100..900&family=Manrope:wght@200..800&family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&family=Nunito:ital,wght@0,200..1000;1,200..1000&family=Open+Sans:ital,wght@0,300..800;1,300..800&family=Outfit:wght@100..900&family=Overpass:ital,wght@0,100..900;1,100..900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Public+Sans:ital,wght@0,100..900;1,100..900&family=Quicksand:wght@300..700&family=Red+Hat+Display:ital,wght@0,300..900;1,300..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Rubik:ital,wght@0,300..900;1,300..900&family=Sora:wght@100..800&family=Space+Grotesk:wght@300..700&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap");
5
+ @import url("https://fonts.googleapis.com/css2?family=Barriecito&family=Borel&family=DynaPuff:wght@400..700&family=Gabarito:wght@400..900&family=Kranky&family=Macondo&family=Playpen+Sans:wght@100..800&family=Rubik+Spray+Paint&family=Shadows+Into+Light+Two&family=Zalando+Sans:ital,wght@0,200..900;1,200..900&display=swap");
4
6
 
5
7
  :root {
6
- --asm-font-family-primary: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
7
- --asm-font-family-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
8
+ --asm-font-family-base: "Inter", "Lato", "Open Sans", "Roboto";
9
+ --asm-font-family-inter: "Inter", ui-sans-serif, system-ui, -apple-system,
10
+ Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
11
+ --asm-font-family-primary: "Inter", "Lato", "Open Sans", "Roboto";
12
+ --asm-font-family-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo,
13
+ Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
14
+ --asm-font-family-poppins: "Poppins", ui-sans-serif, system-ui, sans-serif;
15
+ --asm-font-family-open-sans: "Open Sans", ui-sans-serif, system-ui, sans-serif;
16
+ --asm-font-family-lato: "Lato", ui-sans-serif, system-ui, sans-serif;
17
+ --asm-font-family-rubik: "Rubik", ui-sans-serif, system-ui, sans-serif;
18
+ --asm-font-family-nunito: "Nunito", ui-sans-serif, system-ui, sans-serif;
19
+ --asm-font-family-work-sans: "Work Sans", ui-sans-serif, system-ui, sans-serif;
20
+ --asm-font-family-manrope: "Manrope", ui-sans-serif, system-ui, sans-serif;
21
+ --asm-font-family-figtree: "Figtree", ui-sans-serif, system-ui, sans-serif;
22
+ --asm-font-family-sora: "Sora", ui-sans-serif, system-ui, sans-serif;
23
+ --asm-font-family-outfit: "Outfit", ui-sans-serif, system-ui, sans-serif;
24
+ --asm-font-family-lexend: "Lexend", ui-sans-serif, system-ui, sans-serif;
25
+ --asm-font-family-public-sans: "Public Sans", ui-sans-serif, system-ui,
26
+ sans-serif;
27
+ --asm-font-family-dm-sans: "DM Sans", ui-sans-serif, system-ui, sans-serif;
28
+ --asm-font-family-overpass: "Overpass", ui-sans-serif, system-ui, sans-serif;
29
+ --asm-font-family-quicksand: "Quicksand", ui-sans-serif, system-ui, sans-serif;
30
+ --asm-font-family-karla: "Karla", ui-sans-serif, system-ui, sans-serif;
31
+ --asm-font-family-barlow: "Barlow", ui-sans-serif, system-ui, sans-serif;
32
+ --asm-font-family-space-grotesk: "Space Grotesk", ui-sans-serif, system-ui,
33
+ sans-serif;
34
+ --asm-font-family-red-hat: "Red Hat Display", ui-sans-serif, system-ui,
35
+ sans-serif;
36
+ --asm-font-family-jost: "Jost", ui-sans-serif, system-ui, sans-serif;
37
+ --asm-font-family-barriecito: "Barriecito", cursive, sans-serif;
38
+ --asm-font-family-borel: "Borel", cursive, sans-serif;
39
+ --asm-font-family-dynapuff: "DynaPuff", cursive, sans-serif;
40
+ --asm-font-family-gabarito: "Gabarito", sans-serif;
41
+ --asm-font-family-kranky: "Kranky", cursive, sans-serif;
42
+ --asm-font-family-macondo: "Macondo", cursive, sans-serif;
43
+ --asm-font-family-playpen-sans: "Playpen Sans", cursive, sans-serif;
44
+ --asm-font-family-rubik-spray: "Rubik Spray Paint", cursive, sans-serif;
45
+ --asm-font-family-shadows-light: "Shadows Into Light Two", cursive, sans-serif;
46
+ --asm-font-family-zalando: "Zalando Sans", ui-sans-serif, system-ui,
47
+ sans-serif;
8
48
 
9
49
  --asm-font-weight-100: 100;
10
50
  --asm-font-weight-200: 200;
@@ -79,7 +119,7 @@
79
119
  --asm-border-thick: 3px;
80
120
 
81
121
  --asm-effect-shadow-sm: 0 1px 2px rgba(17, 24, 39, 0.06);
82
- --asm-effect-shadow-md: 0 6px 20px rgba(17, 24, 39, 0.10);
122
+ --asm-effect-shadow-md: 0 6px 20px rgba(17, 24, 39, 0.1);
83
123
  --asm-effect-shadow-lg: 0 16px 40px rgba(17, 24, 39, 0.14);
84
124
  --asm-effect-shadow-xl: 0 24px 60px rgba(17, 24, 39, 0.18);
85
125
 
@@ -96,9 +136,12 @@
96
136
  --asm-motion-easing-entrance: cubic-bezier(0, 0, 0, 1);
97
137
  --asm-motion-easing-exit: cubic-bezier(0.4, 0, 1, 1);
98
138
 
99
- --asm-transition-fade: opacity var(--asm-motion-duration-normal) var(--asm-motion-easing-standard);
100
- --asm-transition-slide: transform var(--asm-motion-duration-normal) var(--asm-motion-easing-standard);
101
- --asm-transition-scale: transform var(--asm-motion-duration-fast) var(--asm-motion-easing-emphasized);
139
+ --asm-transition-fade: opacity var(--asm-motion-duration-normal)
140
+ var(--asm-motion-easing-standard);
141
+ --asm-transition-slide: transform var(--asm-motion-duration-normal)
142
+ var(--asm-motion-easing-standard);
143
+ --asm-transition-scale: transform var(--asm-motion-duration-fast)
144
+ var(--asm-motion-easing-emphasized);
102
145
 
103
146
  --asm-z-base: 0;
104
147
  --asm-z-dropdown: 100;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@asafarim/design-tokens",
3
- "version": "0.3.6",
3
+ "version": "0.4.2",
4
4
  "private": false,
5
- "description": "ASafariM design tokens (CSS variables) with multi-theme support.",
5
+ "description": "ASafariM design tokens (CSS variables) with multi-theme support and 30 variable fonts (100-900).",
6
6
  "license": "MIT",
7
7
  "author": "ASafariM",
8
8
  "repository": {
@@ -22,6 +22,7 @@
22
22
  "style": "css/index.css",
23
23
  "files": [
24
24
  "css",
25
+ "src",
25
26
  "README.md",
26
27
  "CHANGELOG.md",
27
28
  "LICENSE"
@@ -30,6 +31,10 @@
30
31
  "css/*.css"
31
32
  ],
32
33
  "exports": {
34
+ ".": {
35
+ "import": "./src/index.ts",
36
+ "default": "./src/index.ts"
37
+ },
33
38
  "./css": {
34
39
  "style": "./css/index.css",
35
40
  "default": "./css/index.css"
@@ -48,6 +53,8 @@
48
53
  },
49
54
  "homepage": "https://github.com/AliSafari-IT/design-tokens#readme",
50
55
  "scripts": {
51
- "demo": "pnpm --filter design-tokens-demo dev"
56
+ "demo": "pnpm --filter design-tokens-demo dev",
57
+ "build": "tsup",
58
+ "build:demo": "cd demo && pnpm build"
52
59
  }
53
60
  }
@@ -0,0 +1,5 @@
1
+ export { toCssVars, toCssVarNames, tokenPathToCssVarName } from "./toCssVars";
2
+ export { toJson } from "./toJson";
3
+ export { validateTokens } from "./validate";
4
+ export type { CssVarDict } from "./toCssVars";
5
+ export type { FlatTokenJson } from "./toJson";
@@ -0,0 +1,31 @@
1
+ import type { TokenTree } from "../core/types";
2
+ import { toKebabCase, walkTokenTree } from "../core/utils";
3
+
4
+ export type CssVarDict = Record<string, string>;
5
+
6
+ export function tokenPathToCssVarName(path: string[]): string {
7
+ const kebabParts = path.map(toKebabCase);
8
+ return `--asm-${kebabParts.join("-")}`;
9
+ }
10
+
11
+ export function toCssVars(tree: TokenTree): CssVarDict {
12
+ const out: CssVarDict = {};
13
+
14
+ walkTokenTree(tree, ({ path, leaf }) => {
15
+ const cssVar = tokenPathToCssVarName(path);
16
+ out[cssVar] = String(leaf.value);
17
+ });
18
+
19
+ return out;
20
+ }
21
+
22
+ export function toCssVarNames(tree: TokenTree): Record<string, string> {
23
+ const out: Record<string, string> = {};
24
+
25
+ walkTokenTree(tree, ({ path }) => {
26
+ const dotPath = path.join(".");
27
+ out[dotPath] = tokenPathToCssVarName(path);
28
+ });
29
+
30
+ return out;
31
+ }
@@ -0,0 +1,20 @@
1
+ import type { TokenTree } from "../core/types";
2
+ import { walkTokenTree } from "../core/utils";
3
+
4
+ export type FlatTokenJson = Record<string, { value: string | number; description: string; meta?: Record<string, unknown> }>;
5
+
6
+ export function toJson(tree: TokenTree): FlatTokenJson {
7
+ const out: FlatTokenJson = {};
8
+
9
+ walkTokenTree(tree, ({ path, leaf }) => {
10
+ const key = path.join(".");
11
+ if (leaf.meta) {
12
+ out[key] = { value: leaf.value, description: leaf.description, meta: leaf.meta };
13
+ return;
14
+ }
15
+
16
+ out[key] = { value: leaf.value, description: leaf.description };
17
+ });
18
+
19
+ return out;
20
+ }
@@ -0,0 +1,90 @@
1
+ import type { ThemeDefinition, TokenTree, ValidateResult } from "../core/types";
2
+ import { walkTokenTree } from "../core/utils";
3
+ import { tokenPathToCssVarName } from "./toCssVars";
4
+
5
+ const HEX_COLOR = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
6
+
7
+ export function validateTokens(args: {
8
+ tokens: TokenTree;
9
+ themes: ThemeDefinition[];
10
+ }): ValidateResult {
11
+ const errors: string[] = [];
12
+ const warnings: string[] = [];
13
+
14
+ const seenDotKeys = new Set<string>();
15
+ const seenCssVars = new Set<string>();
16
+
17
+ walkTokenTree(args.tokens, ({ path, leaf }) => {
18
+ const dotKey = path.join(".");
19
+ if (seenDotKeys.has(dotKey)) {
20
+ errors.push(`Duplicate token key: ${dotKey}`);
21
+ } else {
22
+ seenDotKeys.add(dotKey);
23
+ }
24
+
25
+ if (!leaf.description || leaf.description.trim().length === 0) {
26
+ errors.push(`Missing description for token: ${dotKey}`);
27
+ }
28
+
29
+ const cssVar = tokenPathToCssVarName(path);
30
+ if (!cssVar.startsWith("--asm-")) {
31
+ errors.push(`Invalid CSS var prefix (must be --asm-): ${cssVar}`);
32
+ }
33
+
34
+ if (seenCssVars.has(cssVar)) {
35
+ errors.push(`Duplicate CSS var name generated: ${cssVar} (from ${dotKey})`);
36
+ } else {
37
+ seenCssVars.add(cssVar);
38
+ }
39
+
40
+ const v = leaf.value;
41
+ if (typeof v === "string" && v.startsWith("#") && !HEX_COLOR.test(v)) {
42
+ errors.push(`Invalid hex color for ${dotKey}: ${v}`);
43
+ }
44
+ });
45
+
46
+ const requiredThemeVars = [
47
+ "--asm-color-bg",
48
+ "--asm-color-surface",
49
+ "--asm-color-text",
50
+ "--asm-color-border",
51
+ "--asm-color-button-primary-bg",
52
+ "--asm-color-input-border-focus",
53
+ "--asm-color-focus-ring",
54
+ "--asm-color-overlay-scrim"
55
+ ];
56
+
57
+ const themeNames = new Set(args.themes.map(t => t.name));
58
+ for (const name of ["light", "dark", "high-contrast"] as const) {
59
+ if (!themeNames.has(name)) {
60
+ errors.push(`Missing required theme: ${name}`);
61
+ }
62
+ }
63
+
64
+ for (const theme of args.themes) {
65
+ if (theme.name !== "light" && theme.name !== "dark" && theme.name !== "high-contrast") {
66
+ warnings.push(`Theme has non-standard name: ${theme.name}`);
67
+ }
68
+
69
+ for (const varName of requiredThemeVars) {
70
+ if (!(varName in theme.tokens)) {
71
+ errors.push(`Theme '${theme.name}' missing required token override: ${varName}`);
72
+ }
73
+ }
74
+
75
+ for (const [key, value] of Object.entries(theme.tokens)) {
76
+ if (!key.startsWith("--asm-")) {
77
+ errors.push(`Theme '${theme.name}' contains non --asm- var: ${key}`);
78
+ }
79
+ if (typeof value === "string" && value.startsWith("#") && !HEX_COLOR.test(value)) {
80
+ errors.push(`Theme '${theme.name}' invalid hex for ${key}: ${value}`);
81
+ }
82
+ }
83
+ }
84
+
85
+ return {
86
+ ok: errors.length === 0,
87
+ errors,
88
+ warnings
89
+ };
90
+ }
@@ -0,0 +1,29 @@
1
+ export type Token<T extends string | number = string> = {
2
+ value: T;
3
+ description: string;
4
+ meta?: Record<string, unknown>;
5
+ };
6
+
7
+ export type ThemeName = "light" | "dark" | "high-contrast";
8
+
9
+ export type ThemeDefinition = {
10
+ name: ThemeName;
11
+ tokens: Record<string, string | number>;
12
+ };
13
+
14
+ export type DensityName = "compact" | "comfortable";
15
+
16
+ export type DensityDefinition = {
17
+ name: DensityName;
18
+ tokens: Record<string, string | number>;
19
+ };
20
+
21
+ export type TokenTree = Record<string, unknown>;
22
+
23
+ export type TokenLeaf = Token<string | number>;
24
+
25
+ export type ValidateResult = {
26
+ ok: boolean;
27
+ errors: string[];
28
+ warnings: string[];
29
+ };
@@ -0,0 +1,42 @@
1
+ import type { TokenLeaf, TokenTree } from "./types";
2
+
3
+ export function isTokenLeaf(value: unknown): value is TokenLeaf {
4
+ return (
5
+ typeof value === "object" &&
6
+ value !== null &&
7
+ "value" in value &&
8
+ "description" in value &&
9
+ (typeof (value as any).value === "string" || typeof (value as any).value === "number") &&
10
+ typeof (value as any).description === "string"
11
+ );
12
+ }
13
+
14
+ export function toKebabCase(input: string): string {
15
+ return input
16
+ .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
17
+ .replace(/[_\s]+/g, "-")
18
+ .toLowerCase();
19
+ }
20
+
21
+ export function joinPath(path: string[], sep = "."): string {
22
+ return path.filter(Boolean).join(sep);
23
+ }
24
+
25
+ export function walkTokenTree(
26
+ tree: TokenTree,
27
+ visitor: (args: { path: string[]; leaf: TokenLeaf }) => void,
28
+ path: string[] = []
29
+ ) {
30
+ for (const [key, value] of Object.entries(tree)) {
31
+ const nextPath = [...path, key];
32
+
33
+ if (isTokenLeaf(value)) {
34
+ visitor({ path: nextPath, leaf: value });
35
+ continue;
36
+ }
37
+
38
+ if (typeof value === "object" && value !== null) {
39
+ walkTokenTree(value as TokenTree, visitor, nextPath);
40
+ }
41
+ }
42
+ }
package/src/index.ts ADDED
@@ -0,0 +1,60 @@
1
+ import type { DensityDefinition, ThemeDefinition, Token, ValidateResult } from "./core/types";
2
+ import { themes } from "./themes";
3
+ import { tokens } from "./tokens";
4
+ import { toCssVars, toCssVarNames } from "./build/toCssVars";
5
+ import { validateTokens as validateTokensInternal } from "./build/validate";
6
+
7
+ export type { ThemeDefinition, Token };
8
+ export type { ValidateResult };
9
+
10
+ export { tokens };
11
+ export { themes };
12
+
13
+ export const cssVarNames = toCssVarNames(tokens as any);
14
+
15
+ export { toCssVars };
16
+
17
+ export type ApplyThemeOptions = {
18
+ overrides?: Record<string, string | number>;
19
+ cleanup?: boolean;
20
+ };
21
+
22
+ export function applyThemeToElement(
23
+ element: { style: { setProperty: (k: string, v: string) => void; removeProperty: (k: string) => void } },
24
+ theme: ThemeDefinition | DensityDefinition,
25
+ options?: ApplyThemeOptions
26
+ ) {
27
+ const cleanup = options?.cleanup ?? false;
28
+
29
+ const keys = Object.keys(theme.tokens);
30
+ if (cleanup) {
31
+ for (const k of keys) {
32
+ element.style.removeProperty(k);
33
+ }
34
+ }
35
+
36
+ for (const [k, v] of Object.entries(theme.tokens)) {
37
+ element.style.setProperty(k, String(v));
38
+ }
39
+
40
+ if (options?.overrides) {
41
+ for (const [k, v] of Object.entries(options.overrides)) {
42
+ element.style.setProperty(k, String(v));
43
+ }
44
+ }
45
+ }
46
+
47
+ export function prefersColorScheme(): "light" | "dark" | undefined {
48
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
49
+ return undefined;
50
+ }
51
+
52
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
53
+ }
54
+
55
+ export function validateTokens(): ValidateResult {
56
+ return validateTokensInternal({
57
+ tokens: tokens as any,
58
+ themes: [themes.light, themes.dark, themes.highContrast]
59
+ });
60
+ }
@@ -0,0 +1,64 @@
1
+ import type { ThemeDefinition } from "../core/types";
2
+ import { brand } from "../tokens/color/brand";
3
+ import { neutral } from "../tokens/color/neutral";
4
+ import { semantic } from "../tokens/color/semantic";
5
+ import { overlays } from "../tokens/color/overlays";
6
+
7
+ export const dark: ThemeDefinition = {
8
+ name: "dark",
9
+ tokens: {
10
+ "--asm-color-bg": "#0B1220",
11
+ "--asm-color-surface": "#0F172A",
12
+ "--asm-color-surface-muted": "#111B2E",
13
+ "--asm-color-panel": "#0F172A",
14
+ "--asm-color-modal": "#0F172A",
15
+
16
+ "--asm-color-text": "#E5E7EB",
17
+ "--asm-color-text-muted": "#9CA3AF",
18
+ "--asm-color-border": "#1F2937",
19
+
20
+ "--asm-color-brand-primary-50": brand.primary50.value,
21
+ "--asm-color-brand-primary-500": brand.primary500.value,
22
+ "--asm-color-brand-primary-600": brand.primary500.value,
23
+ "--asm-color-brand-primary-700": brand.primary600.value,
24
+
25
+ "--asm-color-semantic-success": semantic.success.value,
26
+ "--asm-color-semantic-warning": semantic.warning.value,
27
+ "--asm-color-semantic-error": semantic.error.value,
28
+ "--asm-color-semantic-info": semantic.info.value,
29
+
30
+ "--asm-color-button-primary-bg": brand.primary500.value,
31
+ "--asm-color-button-primary-bg-hover": brand.primary600.value,
32
+ "--asm-color-button-primary-bg-active": brand.primary600.value,
33
+ "--asm-color-button-primary-text": neutral.white.value,
34
+
35
+ "--asm-color-button-secondary-bg": "#111B2E",
36
+ "--asm-color-button-secondary-text": "#E5E7EB",
37
+
38
+ "--asm-color-button-ghost-bg-hover": "rgba(229, 231, 235, 0.08)",
39
+
40
+ "--asm-color-button-destructive-bg": "#F87171",
41
+ "--asm-color-button-destructive-text": "#0B1220",
42
+
43
+ "--asm-color-button-disabled-bg": "#1F2937",
44
+ "--asm-color-button-disabled-text": "#9CA3AF",
45
+
46
+ "--asm-color-input-bg": "#0B1220",
47
+ "--asm-color-input-text": "#E5E7EB",
48
+ "--asm-color-input-border": "#1F2937",
49
+ "--asm-color-input-border-hover": "#374151",
50
+ "--asm-color-input-border-focus": brand.primary500.value,
51
+ "--asm-color-input-placeholder": "#9CA3AF",
52
+ "--asm-color-input-error-border": "#F87171",
53
+ "--asm-color-input-success-border": "#22C55E",
54
+
55
+ "--asm-color-focus-ring": brand.primary500.value,
56
+
57
+ "--asm-color-overlay-scrim": overlays.scrimStrong.value,
58
+
59
+ "--asm-color-dataviz-gridline": "#1F2937",
60
+ "--asm-color-dataviz-axis": "#9CA3AF",
61
+ "--asm-color-dataviz-tooltip-bg": "#111827",
62
+ "--asm-color-dataviz-tooltip-text": "#F9FAFB"
63
+ }
64
+ };
@@ -0,0 +1,11 @@
1
+ import type { DensityDefinition } from "../core/types";
2
+
3
+ export const densityComfortable: DensityDefinition = {
4
+ name: "comfortable",
5
+ tokens: {
6
+ "--asm-density-factor": 1.05,
7
+ "--asm-space-component-gap": "18px",
8
+ "--asm-space-control-padding-y": "10px",
9
+ "--asm-space-control-padding-x": "14px"
10
+ }
11
+ };
@@ -0,0 +1,11 @@
1
+ import type { DensityDefinition } from "../core/types";
2
+
3
+ export const densityCompact: DensityDefinition = {
4
+ name: "compact",
5
+ tokens: {
6
+ "--asm-density-factor": 0.9,
7
+ "--asm-space-component-gap": "12px",
8
+ "--asm-space-control-padding-y": "6px",
9
+ "--asm-space-control-padding-x": "10px"
10
+ }
11
+ };
@@ -0,0 +1,60 @@
1
+ import type { ThemeDefinition } from "../core/types";
2
+
3
+ export const highContrast: ThemeDefinition = {
4
+ name: "high-contrast",
5
+ tokens: {
6
+ "--asm-color-bg": "#000000",
7
+ "--asm-color-surface": "#000000",
8
+ "--asm-color-surface-muted": "#000000",
9
+ "--asm-color-panel": "#000000",
10
+ "--asm-color-modal": "#000000",
11
+
12
+ "--asm-color-text": "#FFFFFF",
13
+ "--asm-color-text-muted": "#FFFFFF",
14
+ "--asm-color-border": "#FFFFFF",
15
+
16
+ "--asm-color-brand-primary-50": "#FFFFFF",
17
+ "--asm-color-brand-primary-500": "#FFFFFF",
18
+ "--asm-color-brand-primary-600": "#FFFFFF",
19
+ "--asm-color-brand-primary-700": "#FFFFFF",
20
+
21
+ "--asm-color-semantic-success": "#00FF00",
22
+ "--asm-color-semantic-warning": "#FFFF00",
23
+ "--asm-color-semantic-error": "#FF0000",
24
+ "--asm-color-semantic-info": "#00FFFF",
25
+
26
+ "--asm-color-button-primary-bg": "#FFFFFF",
27
+ "--asm-color-button-primary-bg-hover": "#FFFFFF",
28
+ "--asm-color-button-primary-bg-active": "#FFFFFF",
29
+ "--asm-color-button-primary-text": "#000000",
30
+
31
+ "--asm-color-button-secondary-bg": "#000000",
32
+ "--asm-color-button-secondary-text": "#FFFFFF",
33
+
34
+ "--asm-color-button-ghost-bg-hover": "#FFFFFF",
35
+
36
+ "--asm-color-button-destructive-bg": "#FF0000",
37
+ "--asm-color-button-destructive-text": "#000000",
38
+
39
+ "--asm-color-button-disabled-bg": "#000000",
40
+ "--asm-color-button-disabled-text": "#FFFFFF",
41
+
42
+ "--asm-color-input-bg": "#000000",
43
+ "--asm-color-input-text": "#FFFFFF",
44
+ "--asm-color-input-border": "#FFFFFF",
45
+ "--asm-color-input-border-hover": "#FFFFFF",
46
+ "--asm-color-input-border-focus": "#FFFFFF",
47
+ "--asm-color-input-placeholder": "#FFFFFF",
48
+ "--asm-color-input-error-border": "#FF0000",
49
+ "--asm-color-input-success-border": "#00FF00",
50
+
51
+ "--asm-color-focus-ring": "#FFFFFF",
52
+
53
+ "--asm-color-overlay-scrim": "rgba(255, 255, 255, 0.9)",
54
+
55
+ "--asm-color-dataviz-gridline": "#FFFFFF",
56
+ "--asm-color-dataviz-axis": "#FFFFFF",
57
+ "--asm-color-dataviz-tooltip-bg": "#FFFFFF",
58
+ "--asm-color-dataviz-tooltip-text": "#000000"
59
+ }
60
+ };
@@ -0,0 +1,21 @@
1
+ export { light } from "./light";
2
+ export { dark } from "./dark";
3
+ export { highContrast } from "./highContrast";
4
+ export { densityCompact } from "./densityCompact";
5
+ export { densityComfortable } from "./densityComfortable";
6
+
7
+ import { light } from "./light";
8
+ import { dark } from "./dark";
9
+ import { highContrast } from "./highContrast";
10
+ import { densityCompact } from "./densityCompact";
11
+ import { densityComfortable } from "./densityComfortable";
12
+
13
+ export const themes = {
14
+ light,
15
+ dark,
16
+ highContrast,
17
+ density: {
18
+ compact: densityCompact,
19
+ comfortable: densityComfortable
20
+ }
21
+ } as const;
@@ -0,0 +1,64 @@
1
+ import type { ThemeDefinition } from "../core/types";
2
+ import { brand } from "../tokens/color/brand";
3
+ import { neutral } from "../tokens/color/neutral";
4
+ import { semantic } from "../tokens/color/semantic";
5
+ import { overlays } from "../tokens/color/overlays";
6
+
7
+ export const light: ThemeDefinition = {
8
+ name: "light",
9
+ tokens: {
10
+ "--asm-color-bg": neutral.gray50.value,
11
+ "--asm-color-surface": neutral.white.value,
12
+ "--asm-color-surface-muted": "#F3F4F6",
13
+ "--asm-color-panel": neutral.white.value,
14
+ "--asm-color-modal": neutral.white.value,
15
+
16
+ "--asm-color-text": neutral.gray900.value,
17
+ "--asm-color-text-muted": neutral.gray500.value,
18
+ "--asm-color-border": neutral.gray300.value,
19
+
20
+ "--asm-color-brand-primary-50": brand.primary50.value,
21
+ "--asm-color-brand-primary-500": brand.primary500.value,
22
+ "--asm-color-brand-primary-600": brand.primary600.value,
23
+ "--asm-color-brand-primary-700": brand.primary700.value,
24
+
25
+ "--asm-color-semantic-success": semantic.success.value,
26
+ "--asm-color-semantic-warning": semantic.warning.value,
27
+ "--asm-color-semantic-error": semantic.error.value,
28
+ "--asm-color-semantic-info": semantic.info.value,
29
+
30
+ "--asm-color-button-primary-bg": brand.primary600.value,
31
+ "--asm-color-button-primary-bg-hover": brand.primary700.value,
32
+ "--asm-color-button-primary-bg-active": brand.primary700.value,
33
+ "--asm-color-button-primary-text": neutral.white.value,
34
+
35
+ "--asm-color-button-secondary-bg": neutral.white.value,
36
+ "--asm-color-button-secondary-text": neutral.gray900.value,
37
+
38
+ "--asm-color-button-ghost-bg-hover": "rgba(17, 24, 39, 0.06)",
39
+
40
+ "--asm-color-button-destructive-bg": semantic.error.value,
41
+ "--asm-color-button-destructive-text": neutral.white.value,
42
+
43
+ "--asm-color-button-disabled-bg": neutral.gray300.value,
44
+ "--asm-color-button-disabled-text": neutral.gray700.value,
45
+
46
+ "--asm-color-input-bg": neutral.white.value,
47
+ "--asm-color-input-text": neutral.gray900.value,
48
+ "--asm-color-input-border": neutral.gray300.value,
49
+ "--asm-color-input-border-hover": neutral.gray500.value,
50
+ "--asm-color-input-border-focus": brand.primary600.value,
51
+ "--asm-color-input-placeholder": neutral.gray500.value,
52
+ "--asm-color-input-error-border": semantic.error.value,
53
+ "--asm-color-input-success-border": semantic.success.value,
54
+
55
+ "--asm-color-focus-ring": brand.primary500.value,
56
+
57
+ "--asm-color-overlay-scrim": overlays.scrim.value,
58
+
59
+ "--asm-color-dataviz-gridline": neutral.gray300.value,
60
+ "--asm-color-dataviz-axis": neutral.gray500.value,
61
+ "--asm-color-dataviz-tooltip-bg": neutral.gray900.value,
62
+ "--asm-color-dataviz-tooltip-text": neutral.gray50.value
63
+ }
64
+ };
@@ -0,0 +1,20 @@
1
+ import type { Token } from "../../core/types";
2
+
3
+ export const accent = {
4
+ purple500: {
5
+ value: "#8B5CF6",
6
+ description: "Accent purple for special contexts (e.g., highlights)."
7
+ } satisfies Token,
8
+ cyan500: {
9
+ value: "#06B6D4",
10
+ description: "Accent cyan for special contexts (e.g., data accents)."
11
+ } satisfies Token,
12
+ pink500: {
13
+ value: "#EC4899",
14
+ description: "Accent pink for special contexts."
15
+ } satisfies Token,
16
+ lime500: {
17
+ value: "#84CC16",
18
+ description: "Accent lime for special contexts."
19
+ } satisfies Token
20
+ } as const;