unholy-design-tokens 1.0.0

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 (111) hide show
  1. package/.github/workflows/lint-format-build.yml +35 -0
  2. package/.github/workflows/publish_release.yml +18 -0
  3. package/.prettierrc +9 -0
  4. package/ANALOGY_HOUSE.md +139 -0
  5. package/ANALOGY_I18NEXT.md +160 -0
  6. package/LICENSE +201 -0
  7. package/README.md +90 -0
  8. package/WHY_THIS_EXISTS.md +74 -0
  9. package/bin/build-tokens.ts +34 -0
  10. package/build/css/bg/bg.css +60 -0
  11. package/build/css/border/border.css +51 -0
  12. package/build/css/colors.css +204 -0
  13. package/build/css/conditional.css +8 -0
  14. package/build/css/cube/cube.block.css +18 -0
  15. package/build/css/cube/cube.composition.css +16 -0
  16. package/build/css/cube/cube.utility.css +185 -0
  17. package/build/css/font/font.css +24 -0
  18. package/build/css/space.css +20 -0
  19. package/build/css/text/text.css +48 -0
  20. package/build/css/themes/private-theme.css +228 -0
  21. package/build/css/themes/public-theme.css +228 -0
  22. package/build/css/variant/variant.css +42 -0
  23. package/build/css/variants.css +167 -0
  24. package/build/types/theme.d.ts +932 -0
  25. package/build/types/tokens.ts +653 -0
  26. package/dist/bin/build-tokens.js +27 -0
  27. package/dist/scripts/build-style-dictionary.js +32 -0
  28. package/dist/scripts/generate-typography-tokens.js +125 -0
  29. package/dist/src/colors/color.config.js +45 -0
  30. package/dist/src/colors/color.filter.js +19 -0
  31. package/dist/src/colors/color.formatter.js +25 -0
  32. package/dist/src/colors/index.js +2 -0
  33. package/dist/src/cube-css/cube.config.js +42 -0
  34. package/dist/src/cube-css/cube.formatter.js +89 -0
  35. package/dist/src/style-dictionary.config.js +143 -0
  36. package/dist/src/type-declarations/type-declarations.config.js +29 -0
  37. package/dist/src/type-declarations/type-declarations.formatter.js +111 -0
  38. package/dist/src/utils/helpers.js +9 -0
  39. package/dist/src/utils/index.js +4 -0
  40. package/dist/src/utils/template.js +83 -0
  41. package/dist/src/utils/tokens.js +80 -0
  42. package/dist/src/utils/utopia.js +19 -0
  43. package/eslint.config.js +67 -0
  44. package/package.json +60 -0
  45. package/scripts/build-style-dictionary.ts +44 -0
  46. package/scripts/generate-typography-tokens.ts +138 -0
  47. package/src/LICENSE +201 -0
  48. package/src/README.md +88 -0
  49. package/src/colors/color.config.ts +48 -0
  50. package/src/colors/color.filter.ts +28 -0
  51. package/src/colors/color.formatter.ts +43 -0
  52. package/src/colors/index.ts +6 -0
  53. package/src/cube-css/cube.config.ts +50 -0
  54. package/src/cube-css/cube.formatter.ts +104 -0
  55. package/src/formatters/spacing.js +95 -0
  56. package/src/style-dictionary.config.ts +151 -0
  57. package/src/theme/README.md +256 -0
  58. package/src/theme/cube-theme-addon.js +44 -0
  59. package/src/theme/helper.js +38 -0
  60. package/src/theme/index.js +6 -0
  61. package/src/theme/theme.config.js +42 -0
  62. package/src/theme/theme.filter.js +42 -0
  63. package/src/theme/theme.formatter.js +71 -0
  64. package/src/tokens/1 - primitives/README.md +58 -0
  65. package/src/tokens/1 - primitives/border.json +54 -0
  66. package/src/tokens/1 - primitives/breakpoint.json +10 -0
  67. package/src/tokens/1 - primitives/color-pool.json +266 -0
  68. package/src/tokens/1 - primitives/color.json +266 -0
  69. package/src/tokens/1 - primitives/font-scale.json +27 -0
  70. package/src/tokens/1 - primitives/font.json +23 -0
  71. package/src/tokens/1 - primitives/shadow.json +26 -0
  72. package/src/tokens/1 - primitives/space.json +27 -0
  73. package/src/tokens/2 - semantic/README.md +49 -0
  74. package/src/tokens/2 - semantic/border.json +27 -0
  75. package/src/tokens/2 - semantic/color.json +263 -0
  76. package/src/tokens/2 - semantic/details.md +1 -0
  77. package/src/tokens/2 - semantic/layout.json +52 -0
  78. package/src/tokens/2 - semantic/radius.json +13 -0
  79. package/src/tokens/2 - semantic/shadow.json +19 -0
  80. package/src/tokens/2 - semantic/spacing.json +25 -0
  81. package/src/tokens/3 - intent/README.md +43 -0
  82. package/src/tokens/3 - intent/background.json +135 -0
  83. package/src/tokens/3 - intent/color.json +265 -0
  84. package/src/tokens/3 - intent/font.json +61 -0
  85. package/src/tokens/3 - intent/text +67 -0
  86. package/src/tokens/README.md +176 -0
  87. package/src/tokens/color/brand.json +316 -0
  88. package/src/tokens/component/theming.json +69 -0
  89. package/src/tokens/conditional.json +40 -0
  90. package/src/tokens/custom/4 - (OPTIONAL) cube css/README.md +38 -0
  91. package/src/tokens/custom/4 - (OPTIONAL) cube css/block.json +24 -0
  92. package/src/tokens/custom/4 - (OPTIONAL) cube css/composition.json +26 -0
  93. package/src/tokens/custom/4 - (OPTIONAL) cube css/global.json +15 -0
  94. package/src/tokens/custom/4 - (OPTIONAL) cube css/utility.json +224 -0
  95. package/src/tokens/custom/OKlch/color.json +61 -0
  96. package/src/tokens/custom/OKlch/state.json +107 -0
  97. package/src/tokens/custom/OKlch/theme-color.json +34 -0
  98. package/src/tokens/custom/OKlch/variant.json +67 -0
  99. package/src/tokens/custom/components/highlighted.json +16 -0
  100. package/src/tokens/state.js +29 -0
  101. package/src/tokens/theme-color.json +34 -0
  102. package/src/type-declarations/type-declarations.config.ts +34 -0
  103. package/src/type-declarations/type-declarations.formatter.ts +122 -0
  104. package/src/utils/helpers.ts +11 -0
  105. package/src/utils/index.ts +4 -0
  106. package/src/utils/template.ts +110 -0
  107. package/src/utils/tokens.ts +95 -0
  108. package/src/utils/utopia.ts +36 -0
  109. package/tailwind.md +720 -0
  110. package/tsconfig.json +19 -0
  111. package/turbowatch.ts +14 -0
@@ -0,0 +1,151 @@
1
+ import StyleDictionary, { Token } from 'style-dictionary'
2
+ import { formats, transformGroups } from 'style-dictionary/enums'
3
+ // @ts-expect-error - JS module without type declarations
4
+ import { themeConfig } from './theme/index.js'
5
+ import typeDeclarationsConfig from './type-declarations/type-declarations.config.js'
6
+ // import { cubeCssVariablesLayerFormatter } from './cube-css/formatters/cube-css.js';
7
+ import cubeConfig from './cube-css/cube.config.js'
8
+ // @ts-expect-error - JS module without type declarations
9
+ import { spacingFluid } from './formatters/spacing.js'
10
+ // import "./theme/formatters/theme.format.js"; // your file shown above (theme formats)
11
+
12
+ import colorConfig from './colors/color.config.js'
13
+ // import themeConfig from './theme/theme.config.js';
14
+
15
+ StyleDictionary.registerFormat(spacingFluid)
16
+
17
+ function generateThemeFiles(directories: string[]) {
18
+ const genericAttributes = {
19
+ format: formats.cssVariables,
20
+ options: {
21
+ // outputReferences: true,
22
+ },
23
+ }
24
+ return directories.map((dir) => {
25
+ return {
26
+ ...genericAttributes,
27
+ // output the dironent tokens in the right folder and file e.g. dironents/button/button-vars.css
28
+ destination: `${dir}/${dir}.css`,
29
+ format: formats.cssVariables,
30
+ // only include the tokens that are inside this dironent token group
31
+ filter: (token: Token) => {
32
+ return token.path[0] === dir || token.attributes?.type === dir
33
+ },
34
+ }
35
+ })
36
+ }
37
+
38
+ StyleDictionary.registerFormat({
39
+ name: 'conditional-css',
40
+ format: function ({ dictionary }) {
41
+ let output = `:root {\n`
42
+ output += dictionary.allTokens
43
+ .map((token) => {
44
+ const { type } = token.attributes || {}
45
+ return ` --${type}: ${token.value};`
46
+ })
47
+ .join('\n')
48
+ output += `\n}\n`
49
+ return output
50
+ },
51
+ })
52
+
53
+ export default {
54
+ // parser: 'initial-theme-parser',
55
+ source: ['src/tokens/**/*.json'],
56
+ // action: ['generate-utopia-typography'],
57
+ platforms: {
58
+ css: {
59
+ transformGroup: transformGroups.css,
60
+ transforms: [
61
+ 'attribute/cti', // pick up category/type/item
62
+ ],
63
+ buildPath: 'css/',
64
+ clearBuildPath: true,
65
+ outputReferences: true,
66
+
67
+ files: [
68
+ {
69
+ destination: 'tokens.css',
70
+ format: 'css/variables',
71
+ filter: (token: Token) => {
72
+ return token.attributes?.category === 'typography'
73
+ },
74
+ actions: ['generate-utopia-typography'], // <- here
75
+ options: {
76
+ outputReferences: true,
77
+ },
78
+ },
79
+ {
80
+ destination: 'conditional.css',
81
+ filter: (token: Token) => token.attributes?.category === 'conditional',
82
+ format: 'conditional-css',
83
+ transformGroup: 'css',
84
+ options: {
85
+ outputReferences: true,
86
+ },
87
+ },
88
+ ...themeConfig,
89
+ {
90
+ destination: 'space.css',
91
+ // format: "css/spacing-fluid",
92
+ format: formats.cssVariables,
93
+ filter: (token: Token) => {
94
+ return token.attributes?.category === 'space' || token.attributes?.type === 'space'
95
+ },
96
+ options: {
97
+ outputReferences: true,
98
+ },
99
+ },
100
+ // -------------------------------------------------------
101
+ /**
102
+ * OKlch tokens
103
+ */
104
+ // {
105
+ // destination: 'primitives.css',
106
+ // format: formats.cssVariables,
107
+ // filter: (token) => {
108
+ // return token.attributes?.type === 'primitive'
109
+ // },
110
+ // },
111
+ // {
112
+ // destination: 'variant.css',
113
+ // format: formats.cssVariables,
114
+ // filter: (token) => {
115
+ // return token.attributes?.category === 'variant'
116
+ // },
117
+ // options: {
118
+ // fileHeader: (defaultMessage: string[]) => {
119
+ // return [...defaultMessage, 'Variant tokens']
120
+ // },
121
+ // },
122
+ // },
123
+ {
124
+ destination: 'variants.css',
125
+ format: formats.cssVariables,
126
+ filter: (token: Token) => {
127
+ const variants = ['variant', 'state', 'color']
128
+ const category: string | undefined = token.attributes?.category as string
129
+ return (
130
+ variants.includes(category) &&
131
+ token.attributes?.tokenTier !== 'intent' &&
132
+ token.attributes?.tokenTier !== 'semantic' &&
133
+ token.attributes?.tokenTier !== 'primitive'
134
+ )
135
+ },
136
+ options: {
137
+ fileHeader: (defaultMessage: string[]) => {
138
+ return [...defaultMessage, 'Variant tokens']
139
+ },
140
+ outputReferences: true,
141
+ },
142
+ },
143
+ ...colorConfig,
144
+ ...cubeConfig,
145
+ ...generateThemeFiles(['components', 'font', 'bg', 'border', 'text', 'variant']),
146
+ ],
147
+ },
148
+ // Type declarations
149
+ ...typeDeclarationsConfig,
150
+ },
151
+ }
@@ -0,0 +1,256 @@
1
+ # 🎚️ **Theme Tokens: Public vs Private Variables**
2
+
3
+ This repo generates **two versions** of theme variables:
4
+
5
+ - **Public Theme Tokens** → meant for _outside consumers_
6
+ - **Private Theme Tokens** → meant for _internal component use_
7
+
8
+ Understanding the difference keeps your design system:
9
+
10
+ ✔ safe
11
+
12
+ ✔ overridable
13
+
14
+ ✔ stable
15
+
16
+ ✔ predictable
17
+
18
+ Let’s break it down.
19
+
20
+ ---
21
+
22
+ ## 🟣 **1. Public Theme Tokens (`-token`)**
23
+
24
+ These are the **official, documented** variables that consumers _are allowed_ to override.
25
+
26
+ Example:
27
+
28
+ ```css
29
+ :root {
30
+ --space-md: 1rem;
31
+ --color-bg-default: #ffffff;
32
+ --text-body-size: 1rem;
33
+ }
34
+ ```
35
+
36
+ ### ✔ Purpose
37
+
38
+ - Provide a **stable API** for theming
39
+ - Let applications or customer brands override design tokens
40
+ - Expose “slot” variables, not internal details
41
+
42
+ ### ✔ Consumers can override:
43
+
44
+ ```css
45
+ :root {
46
+ --color-bg-default: #fef7ff; /* custom brand color */
47
+ }
48
+ ```
49
+
50
+ ### 🛑 Consumers _should not_ override:
51
+
52
+ - component-specific tokens
53
+ - conditional tokens
54
+ - computed variables
55
+ - values derived from multiple dependencies
56
+
57
+ Public tokens are your **surface area**.
58
+
59
+ ---
60
+
61
+ ## 🔵 **2. Private Theme Tokens (`-_token`)**
62
+
63
+ These exist **only inside the design system**.
64
+
65
+ Generated like this:
66
+
67
+ ```css
68
+ --_space-md: var(--space-md, 1rem);
69
+ --_color-bg-default: var(--color-bg-default, #ffffff);
70
+ --_text-body-size: var(--text-body-size, clamp(...));
71
+ ```
72
+
73
+ This structure follows Lea Verou’s pattern:
74
+
75
+ https://lea.verou.me/blog/2021/10/custom-properties-with-defaults/
76
+
77
+ ### ✔ Private variables are _always safe_
78
+
79
+ Even if a consumer overrides a public variable incorrectly, components still resolve safely.
80
+
81
+ Example:
82
+
83
+ ```css
84
+ background: var(--_color-bg-default);
85
+ ```
86
+
87
+ ### ✔ Developers should **ONLY** use private tokens inside components
88
+
89
+ Never use:
90
+
91
+ ```css
92
+ background: var(--color-bg-default); /* ❌ no */
93
+ ```
94
+
95
+ Always use:
96
+
97
+ ```css
98
+ background: var(--_color-bg-default); /* ✔ correct */
99
+ ```
100
+
101
+ ### ✔ Why?
102
+
103
+ Because private variables:
104
+
105
+ - lock in fallback values
106
+ - isolate component behavior from breaking changes
107
+ - prevent invalid overrides from crashing styling
108
+ - are stable even if public tokens change
109
+
110
+ ---
111
+
112
+ ## 🌀 **How Public → Private Works**
113
+
114
+ Each public token:
115
+
116
+ ```css
117
+ --text-body-size: 1rem;
118
+ ```
119
+
120
+ Produces a private counterpart:
121
+
122
+ ```css
123
+ --_text-body-size: var(--text-body-size, 1rem);
124
+ ```
125
+
126
+ This means:
127
+
128
+ - if a theme provides a custom `-text-body-size`, it’s used
129
+ - otherwise, fallback = design system default
130
+
131
+ Exactly what you want.
132
+
133
+ ---
134
+
135
+ ## 🧠 **Why Not Use Public Tokens Inside Components?**
136
+
137
+ Because public tokens are:
138
+
139
+ - overrideable
140
+ - unstable
141
+ - potentially missing
142
+ - brand-controlled
143
+
144
+ Private tokens are:
145
+
146
+ - resolved
147
+ - safe
148
+ - internal
149
+ - consistent
150
+
151
+ ### Components use internal safety
152
+
153
+ ### Apps override external knobs
154
+
155
+ ---
156
+
157
+ ## 🧩 **Example: Button Token Flow**
158
+
159
+ **Public:**
160
+
161
+ ```css
162
+ --button-primary-bg: var(--color-brand-primary);
163
+ --button-primary-radius: 6px;
164
+ ```
165
+
166
+ **Private:**
167
+
168
+ ```css
169
+ --_button-primary-bg: var(--button-primary-bg, var(--_color-brand-primary));
170
+ --_button-primary-radius: var(--button-primary-radius, 6px);
171
+ ```
172
+
173
+ **Component:**
174
+
175
+ ```css
176
+ button.primary {
177
+ background: var(--_button-primary-bg);
178
+ border-radius: var(--_button-primary-radius);
179
+ }
180
+ ```
181
+
182
+ ### If a consumer overrides:
183
+
184
+ ```css
185
+ :root {
186
+ --button-primary-bg: hotpink;
187
+ }
188
+ ```
189
+
190
+ → component updates correctly
191
+
192
+ → fallback is preserved
193
+
194
+ → nothing breaks
195
+
196
+ ---
197
+
198
+ ## 🧩 **Why Two Levels Are Necessary**
199
+
200
+ | Layer | Who uses it | Purpose |
201
+ | ------------------------ | ------------ | --------------------------- |
202
+ | **Public (`--token`)** | consumers | override, theme, brand |
203
+ | **Private (`--_token`)** | components | stable internal contract |
204
+ | **Component tokens** | DS devs | button/card/input internals |
205
+ | **Semantic tokens** | DS designers | meaning-based mapping |
206
+ | **Primitives** | DS designers | raw values |
207
+
208
+ This hierarchy ensures:
209
+
210
+ - **external flexibility**
211
+ - **internal stability**
212
+
213
+ Exactly what a scalable design system needs.
214
+
215
+ ---
216
+
217
+ ## 🛠 Your Custom Formatters
218
+
219
+ Your Style Dictionary setup generates:
220
+
221
+ ### **public-theme.css**
222
+
223
+ ```css
224
+ :root {
225
+ --space-md: 1rem;
226
+ --text-body-size: 1rem;
227
+ --color-bg-default: #fff;
228
+ }
229
+ ```
230
+
231
+ ### **private-theme.css**
232
+
233
+ ```css
234
+ :root {
235
+ --_space-md: var(--space-md, 1rem);
236
+ --_text-body-size: var(--text-body-size, 1rem);
237
+ --_color-bg-default: var(--color-bg-default, #fff);
238
+ }
239
+ ```
240
+
241
+ Nothing else in your build system needs to know how public & private vars relate.
242
+
243
+ Components only consume **private** vars.
244
+
245
+ Component libraries only expose **public** vars.
246
+
247
+ ---
248
+
249
+ ## 🧪 TL;DR Cheat Sheet
250
+
251
+ | Thing | Use Public? | Use Private? | Notes |
252
+ | ---------------- | ----------- | ------------ | --------------------------------- |
253
+ | Apps / Consumers | ✔ yes | ❌ no | override `--token` |
254
+ | DS Components | ❌ no | ✔ yes | use `--_token` |
255
+ | Themes | ✔ yes | ❌ no | theme overrides go to public vars |
256
+ | Fallbacks | automatic | automatic | thanks to var(--token, fallback) |
@@ -0,0 +1,44 @@
1
+ // // cube-theme-addon.js
2
+ // import { generateThemeCubeCSSVariables } from "../cube-css/formatters/cube-css.js";
3
+ // import {
4
+ // shouldOutputReferences,
5
+ // rewriteOriginalRefs,
6
+ // } from "./formatters/theme-core.js";
7
+
8
+ // export function cubeThemeAddon({ dictionary, options, scope }) {
9
+ // const privateVar = scope === "private";
10
+
11
+ // return dictionary.allTokens
12
+ // .filter((t) => t.attributes?.category === "cube")
13
+ // .map((t) => {
14
+ // // start from your existing cube name rules
15
+ // const entry = generateThemeCubeCSSVariables(t);
16
+ // console.log(
17
+ // "📟 - shouldOutputReferences(t, options, dictionary) → ",
18
+ // shouldOutputReferences(t, options, dictionary),
19
+ // );
20
+ // console.log(
21
+ // "📟 - rewriteOriginalRefs(originalValue, dictionary.tokens, privateVar",
22
+ // rewriteOriginalRefs(t.original?.value, dictionary.tokens, privateVar),
23
+ // );
24
+ // // add refs (optional)
25
+ // const originalValue = t.original?.value;
26
+ // const original = shouldOutputReferences(t, options, dictionary)
27
+ // ? rewriteOriginalRefs(originalValue, dictionary.tokens, privateVar)
28
+ // : null;
29
+
30
+ // return {
31
+ // ...entry,
32
+ // original, // lets generateThemeContent prefer original.value
33
+ // };
34
+ // });
35
+ // }
36
+
37
+ // // cube-theme-addon.js
38
+ import { generateThemeCubeCSSVariables } from "../cube-css/formatters/cube-css.js";
39
+
40
+ export function cubeThemeAddon({ dictionary }) {
41
+ return dictionary.allTokens
42
+ .filter((t) => t.attributes?.category === "cube")
43
+ .map((t) => generateThemeCubeCSSVariables(t));
44
+ }
@@ -0,0 +1,38 @@
1
+ // helper.js
2
+ import { generateHeader, generateSubheader } from '../utils/template.js'
3
+ export { generateThemeContent }
4
+
5
+ function generateThemeContent(tokens, scope = 'public') {
6
+ let content = ''
7
+
8
+ let currentCategory = null
9
+ let usedSubsections = new Set() // resets per category
10
+
11
+ for (const t of tokens) {
12
+ const category = t?.category ?? null
13
+
14
+ // New category → print header and reset subsection tracking
15
+ if (category && category !== currentCategory) {
16
+ currentCategory = category
17
+ usedSubsections = new Set()
18
+ content += generateHeader(category)
19
+ }
20
+
21
+ // Optional subsection (opt-in per token)
22
+ const subsection = t?.subsection
23
+ if (subsection && !usedSubsections.has(subsection)) {
24
+ usedSubsections.add(subsection)
25
+ content += generateSubheader(subsection)
26
+ }
27
+
28
+ const rawValue = t.value
29
+
30
+ if (scope === 'public') {
31
+ content += ` ${t.publicName}: ${rawValue};\n`
32
+ } else {
33
+ content += ` ${t.privateName}: var(${t.publicName}, ${rawValue});\n`
34
+ }
35
+ }
36
+
37
+ return content
38
+ }
@@ -0,0 +1,6 @@
1
+ export { default as themeConfig } from './theme.config.js'
2
+ export { filterThemeTokens } from './theme.filter.js'
3
+ export {} from // privateThemeTemplate,
4
+
5
+ // publicThemeTemplate,
6
+ './theme.formatter.js'
@@ -0,0 +1,42 @@
1
+ // theme.files.js
2
+ import { filterThemeTokens } from "./theme.filter.js";
3
+
4
+ export default [
5
+ // Base theme (no cube)
6
+ {
7
+ destination: "themes/private-theme.css",
8
+ format: "private-theme",
9
+ filter: filterThemeTokens,
10
+ options: {
11
+ // outputReferences: true,
12
+ },
13
+ },
14
+ {
15
+ destination: "themes/public-theme.css",
16
+ format: "public-theme",
17
+ filter: filterThemeTokens,
18
+ options: {
19
+ // outputReferences: true,
20
+ },
21
+ },
22
+
23
+ // // Optional theme + cube (appended)
24
+ // {
25
+ // destination: "themes/private-theme+cube.css",
26
+ // format: "private-theme+cube",
27
+ // filter: (token) =>
28
+ // filterThemeTokens(token) || token.attributes?.category === "cube",
29
+ // options: {
30
+ // outputReferences: true,
31
+ // },
32
+ // },
33
+ // {
34
+ // destination: "themes/public-theme+cube.css",
35
+ // format: "public-theme+cube",
36
+ // filter: (token) =>
37
+ // filterThemeTokens(token) || token.attributes?.category === "cube",
38
+ // options: {
39
+ // outputReferences: true,
40
+ // },
41
+ // },
42
+ ];
@@ -0,0 +1,42 @@
1
+ const themeCategories = [
2
+ 'space',
3
+ 'spacing',
4
+ 'border',
5
+ 'radius',
6
+ 'shadow',
7
+ 'breakpoint',
8
+ 'font',
9
+ 'text',
10
+ 'component',
11
+ 'cube',
12
+ 'body',
13
+ 'heading',
14
+ 'layout',
15
+
16
+ // Components
17
+ 'components',
18
+ 'highlighted-text',
19
+ ]
20
+
21
+ const excludeTypes = [
22
+ 'utility',
23
+ 'variants',
24
+ // add more types to exclude from theme if needed
25
+ ]
26
+ /**
27
+ * List of categories part of the generated private and public theme
28
+ * See category: https://styledictionary.com/info/tokens/#category--type--item
29
+ *
30
+ * @param {*} token
31
+ * @returns {boolean}
32
+ */
33
+ export function isPartOfTheme(token) {
34
+ return themeCategories.includes(token.attributes?.category) &&
35
+ !excludeTypes.includes(token.attributes?.type)
36
+ ? true
37
+ : false
38
+ }
39
+
40
+ export function filterThemeTokens(token) {
41
+ return isPartOfTheme(token)
42
+ }
@@ -0,0 +1,71 @@
1
+ // theme.js
2
+ import StyleDictionary from 'style-dictionary'
3
+ import { generateThemeCubeCSS } from '../cube-css/cube.formatter.js'
4
+ import { toKebab } from '../utils/helpers.js'
5
+ import { resolveTokenReferences, tokenName } from '../utils/tokens.js'
6
+ import { generateThemeContent } from './helper.js'
7
+
8
+ /**
9
+ * Takes a token and format it to be rendered in the theme files.
10
+ *
11
+ * Will return:
12
+ * - public name for build/css/themes/public-theme.css
13
+ * - private name for build/css/themes/private-theme.css
14
+ * - resolved value (with references rewritten) or raw value
15
+ * - category for sectioning (heading sections)
16
+ * - subsection for subheading sections
17
+ *
18
+ *
19
+ * @param {*} tokens
20
+ * @param {*} options
21
+ * @param {*} dictionary
22
+ * @param {*} scope
23
+ * @returns {{}}
24
+ */
25
+ function formatToThemeToken(token, options, dictionary, scope) {
26
+ const privateVar = scope === 'private'
27
+
28
+ // const normal = tokens.map((t) => {
29
+ // const originalValue = t.original?.value;
30
+
31
+ return {
32
+ publicName: `--${toKebab(tokenName(token))}`,
33
+ privateName: `--_${toKebab(tokenName(token))}`,
34
+ value: resolveTokenReferences(token, options, dictionary, privateVar),
35
+ category: token.attributes?.category,
36
+ subsection: token.attributes?.subsection,
37
+ }
38
+ }
39
+
40
+ function buildTheme({ dictionary, options }, scope) {
41
+ const header =
42
+ scope === 'public'
43
+ ? `/**
44
+ * Theme Overrides
45
+ * List of CSS variables that can be used to override the default theme
46
+ * Simply uncomment the variables you want to use
47
+ */`
48
+ : `/**
49
+ * Internal default theme variables
50
+ * Using CSS pseudo-private custom properties
51
+ * https://lea.verou.me/blog/2021/10/custom-properties-with-defaults/
52
+ */`
53
+
54
+ // We exclude cube tokens from the main theme output
55
+ const themeTokens = dictionary.allTokens.filter((t) => t.attributes?.category !== 'cube')
56
+ let toks = themeTokens.map((token) => formatToThemeToken(token, options, dictionary, scope))
57
+
58
+ toks = [...toks, ...generateThemeCubeCSS(dictionary.allTokens)]
59
+
60
+ return `${header}\n:root {${generateThemeContent(toks, scope)}\n}\n`
61
+ }
62
+
63
+ StyleDictionary.registerFormat({
64
+ name: 'public-theme',
65
+ format: (args) => buildTheme(args, 'public'),
66
+ })
67
+
68
+ StyleDictionary.registerFormat({
69
+ name: 'private-theme',
70
+ format: (args) => buildTheme(args, 'private'),
71
+ })