@customercity/tokens 0.2.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.
@@ -0,0 +1,7 @@
1
+ <svg width="80" height="80" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Customer City">
2
+ <path d="M0 16C0 7.16344 7.16344 0 16 0H64C72.8366 0 80 7.16344 80 16V64C80 72.8366 72.8366 80 64 80H16C7.16344 80 0 72.8366 0 64V16Z" fill="#FFFFFF"/>
3
+ <path d="M24.1273 11H48.8348L53.1273 15.2925V19.4364H24.1273C22.0888 19.4364 20.4364 21.0888 20.4364 23.1273V56.8727C20.4364 58.9112 22.0888 60.5636 24.1273 60.5636H53.1273V64.8565L48.9838 69H24.1273C17.4296 69 12 63.5704 12 56.8727V23.1273C12 16.4296 17.4296 11 24.1273 11Z" fill="#1554FF"/>
4
+ <path d="M24.6545 27.8727C24.6545 25.5431 26.5431 23.6545 28.8727 23.6545H63.6727C66.0024 23.6545 67.8909 25.5431 67.8909 27.8727C67.8909 30.2024 66.0024 32.0909 63.6727 32.0909H28.8727C26.5431 32.0909 24.6545 30.2024 24.6545 27.8727Z" fill="#1554FF"/>
5
+ <path d="M24.6545 40C24.6545 37.6704 26.5431 35.7818 28.8727 35.7818H53.1273C55.4569 35.7818 57.3455 37.6704 57.3455 40C57.3455 42.3296 55.4569 44.2182 53.1273 44.2182H28.8727C26.5431 44.2182 24.6545 42.3296 24.6545 40Z" fill="#1554FF"/>
6
+ <path d="M24.6545 52.1273C24.6545 49.7976 26.5431 47.9091 28.8727 47.9091H42.5818C44.9115 47.9091 46.8 49.7976 46.8 52.1273C46.8 54.4569 44.9115 56.3455 42.5818 56.3455H28.8727C26.5431 56.3455 24.6545 54.4569 24.6545 52.1273Z" fill="#1554FF"/>
7
+ </svg>
@@ -0,0 +1,7 @@
1
+ <svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Databrite">
2
+ <defs><linearGradient id="dbd" x1="0" y1="0" x2="1" y2="1">
3
+ <stop offset="0" stop-color="#6FA3FF"/><stop offset="1" stop-color="#4D8BFF"/>
4
+ </linearGradient></defs>
5
+ <path d="M50 8 C56 36,64 44,92 50 C64 56,56 64,50 92 C44 64,36 56,8 50 C36 44,44 36,50 8 Z" fill="url(#dbd)"/>
6
+ <circle cx="74" cy="26" r="6.5" fill="#9D6BFF"/>
7
+ </svg>
@@ -0,0 +1,7 @@
1
+ <svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Databrite">
2
+ <defs><linearGradient id="db" x1="0" y1="0" x2="1" y2="1">
3
+ <stop offset="0" stop-color="#4D8BFF"/><stop offset="1" stop-color="#1554FF"/>
4
+ </linearGradient></defs>
5
+ <path d="M50 8 C56 36,64 44,92 50 C64 56,56 64,50 92 C44 64,36 56,8 50 C36 44,44 36,50 8 Z" fill="url(#db)"/>
6
+ <circle cx="74" cy="26" r="6.5" fill="#7637FF"/>
7
+ </svg>
@@ -0,0 +1,7 @@
1
+ <svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Databrite">
2
+ <!-- Token-driven mark: inline this SVG in the DOM so the CSS vars resolve. Body = brand,
3
+ node = sparkle; auto-switches with the active brand + light/dark (no hardcoded hex).
4
+ For <img>/static use where CSS vars don't resolve, use logo-light.svg / logo-dark.svg. -->
5
+ <path d="M50 8 C56 36,64 44,92 50 C64 56,56 64,50 92 C44 64,36 56,8 50 C36 44,44 36,50 8 Z" fill="var(--brand, #1554FF)"/>
6
+ <circle cx="74" cy="26" r="6.5" fill="var(--sparkle, #7637FF)"/>
7
+ </svg>
@@ -0,0 +1,92 @@
1
+ /* @customercity/tokens — "customercity" brand theme. GENERATED — do not edit.
2
+ Semantic colors scoped to [data-brand="customercity"]; pair with core.css. */
3
+
4
+ [data-brand="customercity"] {
5
+ --brand: #1554FF;
6
+ --brand-hover: #0052D2;
7
+ --brand-light: rgba(21,84,255,0.08);
8
+ --brand-lighter: #F4F9FF;
9
+ --brand-subtle: #8CB9FF;
10
+ --background: #F0F3F8;
11
+ --background-alt: #E6EAF2;
12
+ --foreground: #1E232C;
13
+ --card: #FFFFFF;
14
+ --card-foreground: #1E232C;
15
+ --muted: #4E5663;
16
+ --muted-foreground: #868B98;
17
+ --border: #CDD2DF;
18
+ --border-light: #DBDCE0;
19
+ --ring: #1554FF;
20
+ --accent: #E8EBF1;
21
+ --accent-foreground: #1E232C;
22
+ --navy: #071731;
23
+ --navy-light: #0E254A;
24
+ --green: #60C67C;
25
+ --green-bg: #DFF4E5;
26
+ --red: #FB4E6D;
27
+ --red-bg: #F7E6EA;
28
+ --orange: #FFA26D;
29
+ --orange-bg: #F8E6DF;
30
+ --yellow: #FFE600;
31
+ --yellow-bg: #FFFBD2;
32
+ --mint: #00CEDB;
33
+ --mint-bg: #E1F9FF;
34
+ --sky: #29B6F6;
35
+ --sky-bg: #E3F4FF;
36
+ --violet: #AA00FF;
37
+ --violet-bg: #EEDEFB;
38
+ --purple: #7637FF;
39
+ --purple-bg: #E9E4FB;
40
+ --pink: #D500F9;
41
+ --pink-bg: #F3DEFB;
42
+ --sparkle: #7637FF;
43
+ --sparkle-bg: #E9E4FB;
44
+ --sparkle-light: #F4EEFE;
45
+ --agent-card: #F4EEFE;
46
+ --sparkle-border: rgba(118,55,255,0.20);
47
+ }
48
+
49
+ [data-brand="customercity"].dark {
50
+ --brand: #4D8BFF;
51
+ --brand-hover: #6FA3FF;
52
+ --brand-light: rgba(77,139,255,0.16);
53
+ --brand-lighter: #14254A;
54
+ --brand-subtle: #8CB9FF;
55
+ --background: #071731;
56
+ --background-alt: #0A1C3C;
57
+ --foreground: #EAEEF5;
58
+ --card: #0E254A;
59
+ --card-foreground: #EAEEF5;
60
+ --muted: #A9B4C6;
61
+ --muted-foreground: #6E7C93;
62
+ --border: #1C3358;
63
+ --border-light: #15294A;
64
+ --ring: #4D8BFF;
65
+ --accent: #16294A;
66
+ --accent-foreground: #EAEEF5;
67
+ --navy: #040E20;
68
+ --navy-light: #071731;
69
+ --green: #7BD89A;
70
+ --green-bg: rgba(96,198,124,0.16);
71
+ --red: #FF7B92;
72
+ --red-bg: rgba(251,78,109,0.16);
73
+ --orange: #FFB98F;
74
+ --orange-bg: rgba(255,162,109,0.16);
75
+ --yellow: #FFEF66;
76
+ --yellow-bg: rgba(255,230,0,0.14);
77
+ --mint: #4DDDE8;
78
+ --mint-bg: rgba(0,206,219,0.16);
79
+ --sky: #5FC8F8;
80
+ --sky-bg: rgba(41,182,246,0.16);
81
+ --violet: #C24DFF;
82
+ --violet-bg: rgba(170,0,255,0.18);
83
+ --purple: #9D6BFF;
84
+ --purple-bg: rgba(118,55,255,0.18);
85
+ --pink: #E866FB;
86
+ --pink-bg: rgba(213,0,249,0.18);
87
+ --sparkle: #9D6BFF;
88
+ --sparkle-bg: rgba(118,55,255,0.18);
89
+ --sparkle-light: #1C1A3D;
90
+ --agent-card: #1C1A3D;
91
+ --sparkle-border: rgba(157,107,255,0.30);
92
+ }
@@ -0,0 +1,91 @@
1
+ {
2
+ "brand": "customercity",
3
+ "light": {
4
+ "brand": "#1554FF",
5
+ "brand-hover": "#0052D2",
6
+ "brand-light": "rgba(21,84,255,0.08)",
7
+ "brand-lighter": "#F4F9FF",
8
+ "brand-subtle": "#8CB9FF",
9
+ "background": "#F0F3F8",
10
+ "background-alt": "#E6EAF2",
11
+ "foreground": "#1E232C",
12
+ "card": "#FFFFFF",
13
+ "card-foreground": "#1E232C",
14
+ "muted": "#4E5663",
15
+ "muted-foreground": "#868B98",
16
+ "border": "#CDD2DF",
17
+ "border-light": "#DBDCE0",
18
+ "ring": "#1554FF",
19
+ "accent": "#E8EBF1",
20
+ "accent-foreground": "#1E232C",
21
+ "navy": "#071731",
22
+ "navy-light": "#0E254A",
23
+ "green": "#60C67C",
24
+ "green-bg": "#DFF4E5",
25
+ "red": "#FB4E6D",
26
+ "red-bg": "#F7E6EA",
27
+ "orange": "#FFA26D",
28
+ "orange-bg": "#F8E6DF",
29
+ "yellow": "#FFE600",
30
+ "yellow-bg": "#FFFBD2",
31
+ "mint": "#00CEDB",
32
+ "mint-bg": "#E1F9FF",
33
+ "sky": "#29B6F6",
34
+ "sky-bg": "#E3F4FF",
35
+ "violet": "#AA00FF",
36
+ "violet-bg": "#EEDEFB",
37
+ "purple": "#7637FF",
38
+ "purple-bg": "#E9E4FB",
39
+ "pink": "#D500F9",
40
+ "pink-bg": "#F3DEFB",
41
+ "sparkle": "#7637FF",
42
+ "sparkle-bg": "#E9E4FB",
43
+ "sparkle-light": "#F4EEFE",
44
+ "agent-card": "#F4EEFE",
45
+ "sparkle-border": "rgba(118,55,255,0.20)"
46
+ },
47
+ "dark": {
48
+ "brand": "#4D8BFF",
49
+ "brand-hover": "#6FA3FF",
50
+ "brand-light": "rgba(77,139,255,0.16)",
51
+ "brand-lighter": "#14254A",
52
+ "brand-subtle": "#8CB9FF",
53
+ "background": "#071731",
54
+ "background-alt": "#0A1C3C",
55
+ "foreground": "#EAEEF5",
56
+ "card": "#0E254A",
57
+ "card-foreground": "#EAEEF5",
58
+ "muted": "#A9B4C6",
59
+ "muted-foreground": "#6E7C93",
60
+ "border": "#1C3358",
61
+ "border-light": "#15294A",
62
+ "ring": "#4D8BFF",
63
+ "accent": "#16294A",
64
+ "accent-foreground": "#EAEEF5",
65
+ "navy": "#040E20",
66
+ "navy-light": "#071731",
67
+ "green": "#7BD89A",
68
+ "green-bg": "rgba(96,198,124,0.16)",
69
+ "red": "#FF7B92",
70
+ "red-bg": "rgba(251,78,109,0.16)",
71
+ "orange": "#FFB98F",
72
+ "orange-bg": "rgba(255,162,109,0.16)",
73
+ "yellow": "#FFEF66",
74
+ "yellow-bg": "rgba(255,230,0,0.14)",
75
+ "mint": "#4DDDE8",
76
+ "mint-bg": "rgba(0,206,219,0.16)",
77
+ "sky": "#5FC8F8",
78
+ "sky-bg": "rgba(41,182,246,0.16)",
79
+ "violet": "#C24DFF",
80
+ "violet-bg": "rgba(170,0,255,0.18)",
81
+ "purple": "#9D6BFF",
82
+ "purple-bg": "rgba(118,55,255,0.18)",
83
+ "pink": "#E866FB",
84
+ "pink-bg": "rgba(213,0,249,0.18)",
85
+ "sparkle": "#9D6BFF",
86
+ "sparkle-bg": "rgba(118,55,255,0.18)",
87
+ "sparkle-light": "#1C1A3D",
88
+ "agent-card": "#1C1A3D",
89
+ "sparkle-border": "rgba(157,107,255,0.30)"
90
+ }
91
+ }
@@ -0,0 +1,92 @@
1
+ /* @customercity/tokens — "databrite" brand theme. GENERATED — do not edit.
2
+ Semantic colors scoped to [data-brand="databrite"]; pair with core.css. */
3
+
4
+ [data-brand="databrite"] {
5
+ --brand: #1554FF;
6
+ --brand-hover: #0052D2;
7
+ --brand-light: rgba(21,84,255,0.08);
8
+ --brand-lighter: #F4F9FF;
9
+ --brand-subtle: #8CB9FF;
10
+ --background: #F0F3F8;
11
+ --background-alt: #E6EAF2;
12
+ --foreground: #1E232C;
13
+ --card: #FFFFFF;
14
+ --card-foreground: #1E232C;
15
+ --muted: #4E5663;
16
+ --muted-foreground: #868B98;
17
+ --border: #CDD2DF;
18
+ --border-light: #DBDCE0;
19
+ --ring: #1554FF;
20
+ --accent: #E8EBF1;
21
+ --accent-foreground: #1E232C;
22
+ --navy: #071731;
23
+ --navy-light: #0E254A;
24
+ --green: #60C67C;
25
+ --green-bg: #DFF4E5;
26
+ --red: #FB4E6D;
27
+ --red-bg: #F7E6EA;
28
+ --orange: #FFA26D;
29
+ --orange-bg: #F8E6DF;
30
+ --yellow: #FFE600;
31
+ --yellow-bg: #FFFBD2;
32
+ --mint: #00CEDB;
33
+ --mint-bg: #E1F9FF;
34
+ --sky: #29B6F6;
35
+ --sky-bg: #E3F4FF;
36
+ --violet: #AA00FF;
37
+ --violet-bg: #EEDEFB;
38
+ --purple: #7637FF;
39
+ --purple-bg: #E9E4FB;
40
+ --pink: #D500F9;
41
+ --pink-bg: #F3DEFB;
42
+ --sparkle: #7637FF;
43
+ --sparkle-bg: #E9E4FB;
44
+ --sparkle-light: #F4EEFE;
45
+ --agent-card: #F4EEFE;
46
+ --sparkle-border: rgba(118,55,255,0.20);
47
+ }
48
+
49
+ [data-brand="databrite"].dark {
50
+ --brand: #4D8BFF;
51
+ --brand-hover: #6FA3FF;
52
+ --brand-light: rgba(77,139,255,0.16);
53
+ --brand-lighter: #14254A;
54
+ --brand-subtle: #8CB9FF;
55
+ --background: #071731;
56
+ --background-alt: #0A1C3C;
57
+ --foreground: #EAEEF5;
58
+ --card: #0E254A;
59
+ --card-foreground: #EAEEF5;
60
+ --muted: #A9B4C6;
61
+ --muted-foreground: #6E7C93;
62
+ --border: #1C3358;
63
+ --border-light: #15294A;
64
+ --ring: #4D8BFF;
65
+ --accent: #16294A;
66
+ --accent-foreground: #EAEEF5;
67
+ --navy: #040E20;
68
+ --navy-light: #071731;
69
+ --green: #7BD89A;
70
+ --green-bg: rgba(96,198,124,0.16);
71
+ --red: #FF7B92;
72
+ --red-bg: rgba(251,78,109,0.16);
73
+ --orange: #FFB98F;
74
+ --orange-bg: rgba(255,162,109,0.16);
75
+ --yellow: #FFEF66;
76
+ --yellow-bg: rgba(255,230,0,0.14);
77
+ --mint: #4DDDE8;
78
+ --mint-bg: rgba(0,206,219,0.16);
79
+ --sky: #5FC8F8;
80
+ --sky-bg: rgba(41,182,246,0.16);
81
+ --violet: #C24DFF;
82
+ --violet-bg: rgba(170,0,255,0.18);
83
+ --purple: #9D6BFF;
84
+ --purple-bg: rgba(118,55,255,0.18);
85
+ --pink: #E866FB;
86
+ --pink-bg: rgba(213,0,249,0.18);
87
+ --sparkle: #9D6BFF;
88
+ --sparkle-bg: rgba(118,55,255,0.18);
89
+ --sparkle-light: #1C1A3D;
90
+ --agent-card: #1C1A3D;
91
+ --sparkle-border: rgba(157,107,255,0.30);
92
+ }
@@ -0,0 +1,91 @@
1
+ {
2
+ "brand": "databrite",
3
+ "light": {
4
+ "brand": "#1554FF",
5
+ "brand-hover": "#0052D2",
6
+ "brand-light": "rgba(21,84,255,0.08)",
7
+ "brand-lighter": "#F4F9FF",
8
+ "brand-subtle": "#8CB9FF",
9
+ "background": "#F0F3F8",
10
+ "background-alt": "#E6EAF2",
11
+ "foreground": "#1E232C",
12
+ "card": "#FFFFFF",
13
+ "card-foreground": "#1E232C",
14
+ "muted": "#4E5663",
15
+ "muted-foreground": "#868B98",
16
+ "border": "#CDD2DF",
17
+ "border-light": "#DBDCE0",
18
+ "ring": "#1554FF",
19
+ "accent": "#E8EBF1",
20
+ "accent-foreground": "#1E232C",
21
+ "navy": "#071731",
22
+ "navy-light": "#0E254A",
23
+ "green": "#60C67C",
24
+ "green-bg": "#DFF4E5",
25
+ "red": "#FB4E6D",
26
+ "red-bg": "#F7E6EA",
27
+ "orange": "#FFA26D",
28
+ "orange-bg": "#F8E6DF",
29
+ "yellow": "#FFE600",
30
+ "yellow-bg": "#FFFBD2",
31
+ "mint": "#00CEDB",
32
+ "mint-bg": "#E1F9FF",
33
+ "sky": "#29B6F6",
34
+ "sky-bg": "#E3F4FF",
35
+ "violet": "#AA00FF",
36
+ "violet-bg": "#EEDEFB",
37
+ "purple": "#7637FF",
38
+ "purple-bg": "#E9E4FB",
39
+ "pink": "#D500F9",
40
+ "pink-bg": "#F3DEFB",
41
+ "sparkle": "#7637FF",
42
+ "sparkle-bg": "#E9E4FB",
43
+ "sparkle-light": "#F4EEFE",
44
+ "agent-card": "#F4EEFE",
45
+ "sparkle-border": "rgba(118,55,255,0.20)"
46
+ },
47
+ "dark": {
48
+ "brand": "#4D8BFF",
49
+ "brand-hover": "#6FA3FF",
50
+ "brand-light": "rgba(77,139,255,0.16)",
51
+ "brand-lighter": "#14254A",
52
+ "brand-subtle": "#8CB9FF",
53
+ "background": "#071731",
54
+ "background-alt": "#0A1C3C",
55
+ "foreground": "#EAEEF5",
56
+ "card": "#0E254A",
57
+ "card-foreground": "#EAEEF5",
58
+ "muted": "#A9B4C6",
59
+ "muted-foreground": "#6E7C93",
60
+ "border": "#1C3358",
61
+ "border-light": "#15294A",
62
+ "ring": "#4D8BFF",
63
+ "accent": "#16294A",
64
+ "accent-foreground": "#EAEEF5",
65
+ "navy": "#040E20",
66
+ "navy-light": "#071731",
67
+ "green": "#7BD89A",
68
+ "green-bg": "rgba(96,198,124,0.16)",
69
+ "red": "#FF7B92",
70
+ "red-bg": "rgba(251,78,109,0.16)",
71
+ "orange": "#FFB98F",
72
+ "orange-bg": "rgba(255,162,109,0.16)",
73
+ "yellow": "#FFEF66",
74
+ "yellow-bg": "rgba(255,230,0,0.14)",
75
+ "mint": "#4DDDE8",
76
+ "mint-bg": "rgba(0,206,219,0.16)",
77
+ "sky": "#5FC8F8",
78
+ "sky-bg": "rgba(41,182,246,0.16)",
79
+ "violet": "#C24DFF",
80
+ "violet-bg": "rgba(170,0,255,0.18)",
81
+ "purple": "#9D6BFF",
82
+ "purple-bg": "rgba(118,55,255,0.18)",
83
+ "pink": "#E866FB",
84
+ "pink-bg": "rgba(213,0,249,0.18)",
85
+ "sparkle": "#9D6BFF",
86
+ "sparkle-bg": "rgba(118,55,255,0.18)",
87
+ "sparkle-light": "#1C1A3D",
88
+ "agent-card": "#1C1A3D",
89
+ "sparkle-border": "rgba(157,107,255,0.30)"
90
+ }
91
+ }
package/build.mjs ADDED
@@ -0,0 +1,166 @@
1
+ // @customercity/tokens — multi-brand token build.
2
+ // DTCG JSON (src/core/*, src/brands/*) -> Style Dictionary -> CSS + JS/JSON.
3
+ //
4
+ // 3-tier architecture:
5
+ // core (src/core/*.json, namespace "core") -> shared primitives: ramps, z-index,
6
+ // radius. Emitted to :root in core.css, plus the @theme map + utilities/keyframes.
7
+ // brand (src/brands/<brand>.json, namespace=brand) -> semantic colors, light + dark,
8
+ // emitted scoped under [data-brand="<brand>"] (+ .dark) in brands/<brand>.css.
9
+ //
10
+ // Outputs:
11
+ // core.css core primitives + @theme + utilities (import once)
12
+ // brands/customercity.css [data-brand="customercity"] semantic colors (light+dark)
13
+ // brands/databrite.css [data-brand="databrite"] semantic colors (light+dark)
14
+ // tokens.css LEGACY monolithic Customer City (:root/html.dark) — back-compat
15
+ // tokens.js / .json / .d.ts LEGACY Customer City token map — back-compat
16
+ // brands/<brand>.json, core.json per-layer JSON maps
17
+ //
18
+ // Custom name transform strips namespace -> bare var name (--brand). Custom formats emit RAW
19
+ // authored values (no transforms), so legacy tokens.css stays byte-identical to before.
20
+ import StyleDictionary from 'style-dictionary';
21
+ import fs from 'node:fs';
22
+ import path from 'node:path';
23
+ import { fileURLToPath } from 'node:url';
24
+
25
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
26
+ const partial = (name) =>
27
+ fs.readFileSync(path.join(__dirname, 'src', 'partials', name), 'utf8');
28
+
29
+ const rawValue = (t) => t.original?.$value ?? t.original?.value ?? t.$value ?? t.value;
30
+ // last path segment = bare token name (core/brand/mode namespaces stripped)
31
+ StyleDictionary.registerTransform({
32
+ name: 'name/cc',
33
+ type: 'name',
34
+ transform: (t) => t.path[t.path.length - 1],
35
+ });
36
+
37
+ const declare = (tokens) => tokens.map((t) => ` --${t.name}: ${rawValue(t)};`).join('\n');
38
+ const byNs = (all, ns) => all.filter((t) => t.path[0] === ns);
39
+ const byMode = (tokens, mode) => tokens.filter((t) => t.path[1] === mode);
40
+
41
+ // ---- CSS formats ----
42
+ StyleDictionary.registerFormat({
43
+ name: 'css/cc-core',
44
+ format: ({ dictionary }) =>
45
+ partial('preamble.css').trimEnd() +
46
+ '\n\n/* Core primitives — brand-neutral, shared by every brand. */\n:root {\n' +
47
+ declare(dictionary.allTokens) +
48
+ '\n}\n\n' +
49
+ partial('epilogue.css').replace(/^\n+/, ''),
50
+ });
51
+
52
+ StyleDictionary.registerFormat({
53
+ name: 'css/cc-brand',
54
+ format: ({ dictionary }) => {
55
+ const all = dictionary.allTokens;
56
+ const brand = all[0].path[0];
57
+ return (
58
+ `/* @customercity/tokens — "${brand}" brand theme. GENERATED — do not edit.\n` +
59
+ ` Semantic colors scoped to [data-brand="${brand}"]; pair with core.css. */\n\n` +
60
+ `[data-brand="${brand}"] {\n` +
61
+ declare(byMode(all, 'light')) +
62
+ `\n}\n\n[data-brand="${brand}"].dark {\n` +
63
+ declare(byMode(all, 'dark')) +
64
+ '\n}\n'
65
+ );
66
+ },
67
+ });
68
+
69
+ // Legacy monolithic Customer City file (Customer City on :root/html.dark, no data-brand).
70
+ StyleDictionary.registerFormat({
71
+ name: 'css/cc-legacy',
72
+ format: ({ dictionary }) => {
73
+ const all = dictionary.allTokens;
74
+ const core = byNs(all, 'customercity'); // brand semantic
75
+ return (
76
+ partial('preamble.css').trimEnd() +
77
+ '\n\n:root {\n' +
78
+ declare(byMode(core, 'light')) +
79
+ '\n' +
80
+ declare(byNs(all, 'core')) +
81
+ '\n}\n\nhtml.dark {\n' +
82
+ declare(byMode(core, 'dark')) +
83
+ '\n\n color-scheme: dark;\n}\n\n' +
84
+ partial('epilogue.css').replace(/^\n+/, '')
85
+ );
86
+ },
87
+ });
88
+
89
+ // ---- JS / JSON formats ----
90
+ const mapOf = (tokens) => Object.fromEntries(tokens.map((t) => [t.name, rawValue(t)]));
91
+
92
+ StyleDictionary.registerFormat({
93
+ name: 'js/cc-legacy',
94
+ format: ({ dictionary }) => {
95
+ const all = dictionary.allTokens;
96
+ const cc = byNs(all, 'customercity');
97
+ const obj = { light: mapOf(byMode(cc, 'light')), dark: mapOf(byMode(cc, 'dark')), global: mapOf(byNs(all, 'core')) };
98
+ return '// GENERATED by build.mjs -- do not edit by hand.\n' +
99
+ `export const tokens = ${JSON.stringify(obj, null, 2)};\n\nexport default tokens;\n`;
100
+ },
101
+ });
102
+ StyleDictionary.registerFormat({
103
+ name: 'json/cc-legacy',
104
+ format: ({ dictionary }) => {
105
+ const all = dictionary.allTokens;
106
+ const cc = byNs(all, 'customercity');
107
+ return JSON.stringify({ light: mapOf(byMode(cc, 'light')), dark: mapOf(byMode(cc, 'dark')), global: mapOf(byNs(all, 'core')) }, null, 2) + '\n';
108
+ },
109
+ });
110
+ StyleDictionary.registerFormat({
111
+ name: 'dts/cc-legacy',
112
+ format: () =>
113
+ '// GENERATED by build.mjs -- do not edit by hand.\n' +
114
+ 'export type TokenMap = Record<string, string>;\n' +
115
+ 'export declare const tokens: { light: TokenMap; dark: TokenMap; global: TokenMap };\n' +
116
+ 'export default tokens;\n',
117
+ });
118
+ StyleDictionary.registerFormat({
119
+ name: 'json/cc-brand',
120
+ format: ({ dictionary }) => {
121
+ const all = dictionary.allTokens;
122
+ const brand = all[0].path[0];
123
+ return JSON.stringify({ brand, light: mapOf(byMode(all, 'light')), dark: mapOf(byMode(all, 'dark')) }, null, 2) + '\n';
124
+ },
125
+ });
126
+ StyleDictionary.registerFormat({
127
+ name: 'json/cc-core',
128
+ format: ({ dictionary }) => JSON.stringify(mapOf(dictionary.allTokens), null, 2) + '\n',
129
+ });
130
+
131
+ // Discover brands from src/brands/*.json
132
+ const brands = fs
133
+ .readdirSync(path.join(__dirname, 'src', 'brands'))
134
+ .filter((f) => f.endsWith('.json'))
135
+ .map((f) => f.replace('.json', ''));
136
+
137
+ const sd = new StyleDictionary({
138
+ source: ['src/**/*.json'],
139
+ log: { verbosity: 'silent', warnings: 'disabled' },
140
+ platforms: {
141
+ css: {
142
+ transforms: ['name/cc'],
143
+ buildPath: './',
144
+ files: [
145
+ { destination: 'core.css', format: 'css/cc-core', filter: (t) => t.path[0] === 'core' },
146
+ { destination: 'tokens.css', format: 'css/cc-legacy', filter: (t) => t.path[0] === 'core' || t.path[0] === 'customercity' },
147
+ ...brands.map((b) => ({ destination: `brands/${b}.css`, format: 'css/cc-brand', filter: (t) => t.path[0] === b })),
148
+ ],
149
+ },
150
+ js: {
151
+ transforms: ['name/cc'],
152
+ buildPath: './',
153
+ files: [
154
+ { destination: 'tokens.js', format: 'js/cc-legacy', filter: (t) => t.path[0] === 'core' || t.path[0] === 'customercity' },
155
+ { destination: 'tokens.json', format: 'json/cc-legacy', filter: (t) => t.path[0] === 'core' || t.path[0] === 'customercity' },
156
+ { destination: 'tokens.d.ts', format: 'dts/cc-legacy', filter: () => true },
157
+ { destination: 'core.json', format: 'json/cc-core', filter: (t) => t.path[0] === 'core' },
158
+ ...brands.map((b) => ({ destination: `brands/${b}.json`, format: 'json/cc-brand', filter: (t) => t.path[0] === b })),
159
+ ],
160
+ },
161
+ },
162
+ });
163
+
164
+ await sd.hasInitialized;
165
+ await sd.buildAllPlatforms();
166
+ console.log(`@customercity/tokens built: core + tokens(legacy) + brands [${brands.join(', ')}]`);