@carbon/themes 12.0.0-alpha.1 → 12.0.0-alpha.3

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 (57) hide show
  1. package/es/index.js +5572 -0
  2. package/lib/__tests__/themes-test.d.ts +1 -0
  3. package/lib/__tests__/tools-test.d.ts +1 -0
  4. package/lib/tokens/__tests__/Token-test.d.ts +1 -0
  5. package/lib/tokens/__tests__/TokenFormat-test.d.ts +1 -0
  6. package/lib/tokens/__tests__/TokenGroup-test.d.ts +1 -0
  7. package/lib/tokens/__tests__/TokenSet-test.d.ts +1 -0
  8. package/lib/tokens/__tests__/metadata-test.d.ts +1 -0
  9. package/lib/tokens/__tests__/v11-test.d.ts +1 -0
  10. package/lib/v10/__tests__/themes-test.d.ts +1 -0
  11. package/lib/v10/__tests__/tokens-test.d.ts +1 -0
  12. package/package.json +13 -4
  13. package/umd/index.js +6322 -0
  14. package/docs/sass.md +0 -189
  15. package/src/dtcg/README.md +0 -336
  16. package/src/dtcg/color-palette.json +0 -4424
  17. package/src/dtcg/components/button.json +0 -193
  18. package/src/dtcg/components/content-switcher.json +0 -60
  19. package/src/dtcg/components/notification.json +0 -130
  20. package/src/dtcg/components/status.json +0 -122
  21. package/src/dtcg/components/tag.json +0 -486
  22. package/src/dtcg/themes.json +0 -3356
  23. package/src/index.ts +0 -129
  24. package/src/tokens/Token.ts +0 -41
  25. package/src/tokens/TokenFormat.ts +0 -93
  26. package/src/tokens/TokenGroup.ts +0 -185
  27. package/src/tokens/TokenSet.ts +0 -91
  28. package/src/tokens/components.ts +0 -120
  29. package/src/tokens/index.ts +0 -59
  30. package/src/tokens/layout.ts +0 -39
  31. package/src/tokens/type.ts +0 -49
  32. package/src/tokens/types.ts +0 -28
  33. package/src/tokens/v10.ts +0 -188
  34. package/src/tokens/v11TokenGroup.ts +0 -546
  35. package/src/tokens/v11TokenSet.ts +0 -93
  36. package/src/tools.ts +0 -69
  37. package/src/v10/g10.ts +0 -349
  38. package/src/v10/g100.ts +0 -348
  39. package/src/v10/g90.ts +0 -350
  40. package/src/v10/index.ts +0 -22
  41. package/src/v10/metadata.yml +0 -217
  42. package/src/v10/tokens.ts +0 -397
  43. package/src/v10/white.ts +0 -352
  44. package/style-dictionary/formats/js-component-tokens.js +0 -128
  45. package/style-dictionary/formats/js-themes.js +0 -84
  46. package/style-dictionary/formats/scss-component-tokens.js +0 -149
  47. package/style-dictionary/formats/scss-themes.js +0 -127
  48. package/style-dictionary/formats/scss-tokens.js +0 -91
  49. package/style-dictionary/preprocessors/component-tokens.js +0 -172
  50. package/style-dictionary/preprocessors/dual-role.js +0 -157
  51. package/style-dictionary/preprocessors/theme-metadata.js +0 -46
  52. package/style-dictionary/sd.config.js +0 -449
  53. package/style-dictionary/transforms/alpha-modifier.js +0 -68
  54. package/style-dictionary/transforms/color-flatten.js +0 -79
  55. package/test-dtcg.scss +0 -28
  56. package/tsconfig.json +0 -8
  57. package/tsconfig.types.json +0 -10
package/src/v10/white.ts DELETED
@@ -1,352 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2018, 2026
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- import { adjustLightness } from '../tools';
9
-
10
- import {
11
- // Blue
12
- blue20,
13
- blue40,
14
- blue60,
15
- blue70,
16
- blue80,
17
-
18
- // Gray
19
- gray10,
20
- gray20,
21
- gray30,
22
- gray40,
23
- gray50,
24
- gray60,
25
- gray70,
26
- gray80,
27
- gray100,
28
-
29
- // Support
30
- blue50,
31
- green40,
32
- green60,
33
- yellow30,
34
- red50,
35
- red60,
36
- red80,
37
- purple60,
38
-
39
- // Constants
40
- white,
41
- black,
42
-
43
- // Tools
44
- rgba,
45
- } from '@carbon/colors';
46
-
47
- export const interactive01 = blue60;
48
- export const interactive02 = gray80;
49
- export const interactive03 = blue60;
50
- export const interactive04 = blue60;
51
-
52
- export const uiBackground = white;
53
-
54
- export const ui01 = gray10;
55
- export const ui02 = white;
56
- export const ui03 = gray20;
57
- export const ui04 = gray50;
58
- export const ui05 = gray100;
59
-
60
- export const text01 = gray100;
61
- export const text02 = gray70;
62
- export const text03 = gray40;
63
- export const text04 = white;
64
- export const text05 = gray60;
65
- export const textError = red60;
66
-
67
- export const icon01 = gray100;
68
- export const icon02 = gray70;
69
- export const icon03 = white;
70
-
71
- export const link01 = blue60;
72
- export const link02 = blue70;
73
-
74
- export const inverseLink = blue40;
75
-
76
- export const field01 = gray10;
77
- export const field02 = white;
78
-
79
- export const inverse01 = white;
80
- export const inverse02 = gray80;
81
-
82
- export const support01 = red60;
83
- export const support02 = green60;
84
- export const support03 = yellow30;
85
- export const support04 = blue70;
86
-
87
- export const inverseSupport01 = red50;
88
- export const inverseSupport02 = green40;
89
- export const inverseSupport03 = yellow30;
90
- export const inverseSupport04 = blue50;
91
-
92
- export const overlay01 = rgba(gray100, 0.5);
93
-
94
- export const danger01 = red60;
95
- export const danger02 = red60;
96
-
97
- // Interaction states
98
- export const focus = blue60;
99
- export const inverseFocusUi = white;
100
-
101
- export const hoverPrimary = '#0353e9';
102
- export const activePrimary = blue80;
103
-
104
- export const hoverPrimaryText = blue70;
105
-
106
- export const hoverSecondary = '#4c4c4c';
107
- export const activeSecondary = gray60;
108
-
109
- export const hoverTertiary = '#0353e9';
110
- export const activeTertiary = blue80;
111
-
112
- export const hoverUI = '#e5e5e5';
113
- export const hoverLightUI = '#e5e5e5';
114
- export const activeUI = gray30;
115
- export const activeLightUI = gray30;
116
- export const selectedUI = gray20;
117
- export const selectedLightUI = gray20;
118
- export const inverseHoverUI = '#4c4c4c';
119
-
120
- export const hoverSelectedUI = '#cacaca';
121
-
122
- export const hoverDanger = adjustLightness(danger01, -8);
123
- export const activeDanger = red80;
124
-
125
- export const hoverRow = '#e5e5e5';
126
-
127
- export const visitedLink = purple60;
128
-
129
- export const disabled01 = gray10;
130
- export const disabled02 = gray30;
131
- export const disabled03 = gray50;
132
-
133
- export const highlight = blue20;
134
-
135
- export const decorative01 = gray20;
136
-
137
- export const buttonSeparator = '#e0e0e0';
138
-
139
- export const skeleton01 = '#e5e5e5';
140
- export const skeleton02 = gray30;
141
-
142
- // New color tokens
143
- // TODO: remove fallback color when v11 is released and assign carbon colors to new tokens
144
- export const background = uiBackground;
145
- export const layer = ui01;
146
- export const layerAccent = ui03;
147
- export const layerAccentActive = gray40;
148
- export const layerAccentHover = adjustLightness(layerAccent, -6);
149
- export const field = field01;
150
- export const backgroundInverse = inverse02;
151
- export const backgroundBrand = interactive01;
152
- export const interactive = interactive04;
153
-
154
- export const borderSubtle = ui03;
155
- export const borderStrong = ui04;
156
- export const borderInverse = ui05;
157
- export const borderInteractive = interactive04;
158
-
159
- export const textPrimary = text01;
160
- export const textSecondary = text02;
161
- export const textPlaceholder = text03;
162
- export const textHelper = text05;
163
- export const textOnColor = text04;
164
- export const textInverse = inverse01;
165
-
166
- export const linkPrimary = link01;
167
- export const linkSecondary = link02;
168
- export const linkVisited = visitedLink;
169
- export const linkInverse = inverseLink;
170
-
171
- export const iconPrimary = icon01;
172
- export const iconSecondary = icon02;
173
- export const iconOnColor = icon03;
174
- export const iconInverse = inverse01;
175
-
176
- export const supportError = support01;
177
- export const supportSuccess = support02;
178
- export const supportWarning = support03;
179
- export const supportInfo = support04;
180
- export const supportErrorInverse = inverseSupport01;
181
- export const supportSuccessInverse = inverseSupport02;
182
- export const supportWarningInverse = inverseSupport03;
183
- export const supportInfoInverse = inverseSupport04;
184
-
185
- export const overlay = overlay01;
186
- export const toggleOff = ui04;
187
- export const shadow = rgba(black, 0.3);
188
-
189
- export const buttonPrimary = interactive01;
190
- export const buttonSecondary = interactive02;
191
- export const buttonTertiary = interactive03;
192
- export const buttonDangerPrimary = danger01;
193
- export const buttonDangerSecondary = danger02;
194
-
195
- export const backgroundActive = activeUI;
196
- export const layerActive = activeUI;
197
-
198
- export const buttonDangerActive = activeDanger;
199
- export const buttonPrimaryActive = activePrimary;
200
- export const buttonSecondaryActive = activeSecondary;
201
- export const buttonTertiaryActive = activeTertiary;
202
-
203
- export const focusInset = inverse01;
204
- export const focusInverse = inverseFocusUi;
205
-
206
- export const backgroundHover = hoverUI;
207
- export const layerHover = hoverUI;
208
- export const fieldHover = hoverUI;
209
- export const backgroundInverseHover = inverseHoverUI;
210
- export const linkPrimaryHover = hoverPrimaryText;
211
- export const buttonDangerHover = hoverDanger;
212
- export const buttonPrimaryHover = hoverPrimary;
213
- export const buttonSecondaryHover = hoverSecondary;
214
- export const buttonTertiaryHover = hoverTertiary;
215
-
216
- export const backgroundSelected = selectedUI;
217
- export const backgroundSelectedHover = hoverSelectedUI;
218
- export const layerSelected = selectedUI;
219
- export const layerSelectedHover = hoverSelectedUI;
220
- export const layerSelectedInverse = ui05;
221
- export const borderSubtleSelected = activeUI;
222
-
223
- export const borderDisabled = disabled01;
224
-
225
- export const textDisabled = disabled02;
226
- export const buttonDisabled = disabled02;
227
- export const iconDisabled = disabled02;
228
-
229
- export const textOnColorDisabled = disabled03;
230
- export const iconOnColorDisabled = disabled03;
231
- export const layerSelectedDisabled = disabled03;
232
-
233
- export const skeletonBackground = skeleton01;
234
- export const skeletonElement = skeleton02;
235
-
236
- // Type
237
- export {
238
- caption01,
239
- caption02,
240
- label01,
241
- label02,
242
- helperText01,
243
- helperText02,
244
- bodyShort01,
245
- bodyLong01,
246
- bodyShort02,
247
- bodyLong02,
248
- code01,
249
- code02,
250
- heading01,
251
- productiveHeading01,
252
- heading02,
253
- productiveHeading02,
254
- productiveHeading03,
255
- productiveHeading04,
256
- productiveHeading05,
257
- productiveHeading06,
258
- productiveHeading07,
259
- expressiveHeading01,
260
- expressiveHeading02,
261
- expressiveHeading03,
262
- expressiveHeading04,
263
- expressiveHeading05,
264
- expressiveHeading06,
265
- expressiveParagraph01,
266
- quotation01,
267
- quotation02,
268
- display01,
269
- display02,
270
- display03,
271
- display04,
272
- // V11 Tokens
273
- legal01,
274
- legal02,
275
- bodyCompact01,
276
- bodyCompact02,
277
- body01,
278
- body02,
279
- headingCompact01,
280
- headingCompact02,
281
- heading03,
282
- heading04,
283
- heading05,
284
- heading06,
285
- heading07,
286
- fluidHeading03,
287
- fluidHeading04,
288
- fluidHeading05,
289
- fluidHeading06,
290
- fluidParagraph01,
291
- fluidQuotation01,
292
- fluidQuotation02,
293
- fluidDisplay01,
294
- fluidDisplay02,
295
- fluidDisplay03,
296
- fluidDisplay04,
297
- } from '@carbon/type';
298
-
299
- // Layout
300
- // Spacing
301
- export {
302
- spacing01,
303
- spacing02,
304
- spacing03,
305
- spacing04,
306
- spacing05,
307
- spacing06,
308
- spacing07,
309
- spacing08,
310
- spacing09,
311
- spacing10,
312
- spacing11,
313
- spacing12,
314
- spacing13,
315
- // Fluid spacing
316
- fluidSpacing01,
317
- fluidSpacing02,
318
- fluidSpacing03,
319
- fluidSpacing04,
320
- // Containers
321
- container01,
322
- container02,
323
- container03,
324
- container04,
325
- container05,
326
- sizeXSmall,
327
- sizeSmall,
328
- sizeMedium,
329
- sizeLarge,
330
- sizeXLarge,
331
- size2XLarge,
332
- // Icon sizes
333
- iconSize01,
334
- iconSize02,
335
- // Layout
336
- // Deprecated ☠️
337
- layout01,
338
- layout02,
339
- layout03,
340
- layout04,
341
- layout05,
342
- layout06,
343
- layout07,
344
- } from '@carbon/layout';
345
-
346
- // Deprecated ☠️
347
- export const brand01 = interactive01;
348
- export const brand02 = interactive02;
349
- export const brand03 = interactive03;
350
- export const active01 = activeUI;
351
- export const hoverField = hoverUI;
352
- export const danger = danger01;
@@ -1,128 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2026
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- /**
11
- * Receives tokens for ONE component (pre-processed by
12
- * `component-tokens`) and emits two files:
13
- * - `<componentName>.js` — named ES exports, one per token
14
- * - `<componentName>.d.ts` — companion TypeScript declarations
15
- *
16
- */
17
-
18
- const FILE_BANNER = `// Code generated by @carbon/themes. DO NOT EDIT.
19
- //
20
- // Copyright IBM Corp. 2018, 2025
21
- //
22
- // This source code is licensed under the Apache-2.0 license found in the
23
- // LICENSE file in the root directory of this source tree.
24
- `;
25
-
26
- /**
27
- * Convert kebab-case to camelCase.
28
- * @param {string} str
29
- * @returns {string}
30
- */
31
- function kebabToCamel(str) {
32
- return str.replace(/-([a-z0-9])/g, (_, ch) => ch.toUpperCase());
33
- }
34
-
35
- /**
36
- * Normalize theme key to the JS API convention.
37
- * 'white' → 'whiteTheme', 'g10' → 'g10' (no dash, unlike SCSS convention)
38
- * @param {string} theme
39
- * @returns {string}
40
- */
41
- function normalizeThemeKey(theme) {
42
- if (theme === 'white') return 'whiteTheme';
43
- return theme; // 'g10', 'g90', 'g100' — unchanged
44
- }
45
-
46
- /**
47
- * Serialize a JS value to source-code string.
48
- * @param {*} value
49
- * @returns {string}
50
- */
51
- function toSource(value) {
52
- if (typeof value === 'string') {
53
- return `'${value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
54
- }
55
- return JSON.stringify(value);
56
- }
57
-
58
- /**
59
- * Group SD tokens by component-token name and theme.
60
- * Mirrors the logic in carbon-scss-component-tokens.js.
61
- *
62
- * @param {import('style-dictionary').Token[]} allTokens
63
- * @returns {Map<string, Record<string, string>>}
64
- */
65
- function groupByTokenAndTheme(allTokens) {
66
- const result = new Map();
67
- const BY_THEME_MARKER = '-by-theme-';
68
-
69
- for (const token of allTokens) {
70
- const idx = token.name.indexOf(BY_THEME_MARKER);
71
- if (idx === -1) continue;
72
-
73
- const tokenName = token.name.slice(0, idx);
74
- const theme = token.name.slice(idx + BY_THEME_MARKER.length);
75
-
76
- if (!result.has(tokenName)) {
77
- result.set(tokenName, {});
78
- }
79
- result.get(tokenName)[theme] = token.value ?? token.$value;
80
- }
81
-
82
- return result;
83
- }
84
-
85
- /**
86
- * @param {{ dictionary: import('style-dictionary').Dictionary, options: object }} args
87
- * @returns {string}
88
- */
89
- function carbonJsComponentTokensFormat({ dictionary, options }) {
90
- const outputMode = options?.output ?? 'js'; // 'js' | 'dts'
91
-
92
- const grouped = groupByTokenAndTheme(dictionary.allTokens);
93
-
94
- // Preserve insertion order from the DTCG JSON walk.
95
- const sortedNames = [...grouped.keys()];
96
-
97
- const lines = [FILE_BANNER];
98
-
99
- for (const tokenName of sortedNames) {
100
- const themeValues = grouped.get(tokenName);
101
- const camelName = kebabToCamel(tokenName);
102
-
103
- // Preserve JSON source order exactly.
104
- const themes = Object.keys(themeValues);
105
-
106
- if (outputMode === 'js') {
107
- const props = themes
108
- .map((theme) => {
109
- const key = normalizeThemeKey(theme);
110
- return ` ${key}: ${toSource(themeValues[theme])}`;
111
- })
112
- .join(',\n');
113
- lines.push(`export const ${camelName} = {\n${props},\n};`);
114
- } else {
115
- const props = themes
116
- .map((theme) => ` ${normalizeThemeKey(theme)}: string`)
117
- .join(';\n');
118
- lines.push(`export declare const ${camelName}: {\n${props};\n};`);
119
- }
120
- }
121
-
122
- return lines.join('\n') + '\n';
123
- }
124
-
125
- module.exports = {
126
- name: 'carbon/js-component-tokens',
127
- format: carbonJsComponentTokensFormat,
128
- };
@@ -1,84 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2026
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- /**
11
- *
12
- * Receives all tokens for ONE theme and emits two files (via SD's
13
- * `files` array):
14
- * - `<themeName>.js` — ES module with `export const camelName = value;`
15
- * - `<themeName>.d.ts` — companion TypeScript declarations
16
- *
17
- * Token names arrive as kebab-case from SD and are converted to camelCase.
18
- *
19
- */
20
-
21
- const FILE_BANNER = `// Code generated by @carbon/themes. DO NOT EDIT.
22
- //
23
- // Copyright IBM Corp. 2018, 2025
24
- //
25
- // This source code is licensed under the Apache-2.0 license found in the
26
- // LICENSE file in the root directory of this source tree.
27
- `;
28
-
29
- /**
30
- * Convert kebab-case to camelCase.
31
- * @param {string} str
32
- * @returns {string}
33
- */
34
- function kebabToCamel(str) {
35
- return str.replace(/-([a-z0-9])/g, (_, ch) => ch.toUpperCase());
36
- }
37
-
38
- /**
39
- * Serialize a JS value to a source-code string.
40
- * Strings get single-quoted; everything else uses JSON.
41
- * @param {*} value
42
- * @returns {string}
43
- */
44
- function toSource(value) {
45
- if (typeof value === 'string') {
46
- return `'${value.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
47
- }
48
- return JSON.stringify(value);
49
- }
50
-
51
- /**
52
- * @param {{ dictionary: import('style-dictionary').Dictionary, options: object }} args
53
- * @returns {string}
54
- */
55
- function carbonJsThemesFormat({ dictionary, options }) {
56
- const outputMode = options?.output ?? 'js'; // 'js' | 'dts'
57
-
58
- const lines = [FILE_BANNER];
59
- const sorted = dictionary.allTokens;
60
-
61
- for (const token of sorted) {
62
- const camelName = kebabToCamel(token.name);
63
- // SD v5 may store the resolved alias as a full token node object in
64
- // token.value when the alias points to a sibling token. Unwrap it.
65
- let value = token.value ?? token.$value;
66
- if (value !== null && typeof value === 'object' && '$value' in value) {
67
- value = value.$value;
68
- }
69
- const tsType = typeof value === 'string' ? 'string' : 'number';
70
-
71
- if (outputMode === 'js') {
72
- lines.push(`export const ${camelName} = ${toSource(value)};`);
73
- } else {
74
- lines.push(`export declare const ${camelName}: ${tsType};`);
75
- }
76
- }
77
-
78
- return lines.join('\n') + '\n';
79
- }
80
-
81
- module.exports = {
82
- name: 'carbon/js-themes',
83
- format: carbonJsThemesFormat,
84
- };
@@ -1,149 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2026
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- /**
11
- * Receives the tokens for ONE component (already expanded from the
12
- * carbon.themes multi-theme shape by the `component-tokens`
13
- * preprocessor). Emits a Sass map variable per token, keyed by normalised
14
- * theme name:
15
- *
16
- * $button-danger-active: (
17
- * 'white-theme': #a2191f,
18
- * 'g-10': #a2191f,
19
- * 'g-90': #a2191f,
20
- * 'g-100': #a2191f,
21
- * ) !default;
22
- *
23
- *
24
- * The token tree must have been pre-processed by `carbon/component-tokens`
25
- * so that each token has a `_by_theme` child group containing one resolved
26
- * token per theme.
27
- */
28
-
29
- const FILE_BANNER = `// Code generated by @carbon/themes. DO NOT EDIT.
30
- //
31
- // Copyright IBM Corp. 2018, 2023
32
- //
33
- // This source code is licensed under the Apache-2.0 license found in the
34
- // LICENSE file in the root directory of this source tree.
35
- //
36
- `;
37
-
38
- /**
39
- * Normalize a raw theme key to the Carbon SCSS convention.
40
- * @param {string} theme
41
- * @returns {string}
42
- */
43
- function normalizeThemeName(theme) {
44
- if (theme === 'white') return 'white-theme';
45
- if (/^g\d+$/.test(theme)) return theme.replace(/^g(\d+)$/, 'g-$1');
46
- return theme;
47
- }
48
-
49
- /**
50
- * Serialize a CSS value to a Sass literal (same logic as carbon-scss-themes).
51
- * @param {string|number} value
52
- * @returns {string}
53
- */
54
- function toSassLiteral(value) {
55
- if (typeof value === 'number') return String(value);
56
- if (typeof value !== 'string') return JSON.stringify(value);
57
- if (value.startsWith('#') || value.startsWith('rgb')) return value;
58
- if (
59
- value.endsWith('px') ||
60
- value.endsWith('em') ||
61
- value.endsWith('%') ||
62
- value === '0'
63
- )
64
- return value;
65
- return `string.unquote("${value}")`;
66
- }
67
-
68
- /**
69
- * Group SD tokens by their component-token name and theme.
70
- *
71
- * After the carbon/component-tokens preprocessor runs, tokens in the
72
- * dictionary look like:
73
- *
74
- * button-danger-active-by-theme-white (name after flattening)
75
- * button-danger-active-by-theme-g10
76
- * ...
77
- *
78
- * We strip the `_by_theme-` infix and reconstruct the map.
79
- *
80
- * @param {import('style-dictionary').Token[]} allTokens
81
- * @returns {Map<string, Record<string, string>>} tokenName → { theme: value }
82
- */
83
- function groupByTokenAndTheme(allTokens) {
84
- const result = new Map();
85
-
86
- for (const token of allTokens) {
87
- // Token names contain '_by_theme' as an injected path segment.
88
- // e.g. 'button-danger-active-by-theme-white' — but SD uses whatever
89
- // separator the platform config specifies (usually '-').
90
- // Match the segment just before a known theme key.
91
- const BY_THEME_MARKER = '-by-theme-';
92
- const idx = token.name.indexOf(BY_THEME_MARKER);
93
- if (idx === -1) continue;
94
-
95
- const tokenName = token.name.slice(0, idx);
96
- const theme = token.name.slice(idx + BY_THEME_MARKER.length);
97
-
98
- if (!result.has(tokenName)) {
99
- result.set(tokenName, {});
100
- }
101
- result.get(tokenName)[theme] = token.value ?? token.$value;
102
- }
103
-
104
- return result;
105
- }
106
-
107
- /**
108
- * @param {{ dictionary: import('style-dictionary').Dictionary }} args
109
- * @returns {string}
110
- */
111
- function carbonScssComponentTokensFormat({ dictionary }) {
112
- const grouped = groupByTokenAndTheme(dictionary.allTokens);
113
-
114
- // Preserve insertion order from the DTCG JSON walk — do NOT sort here.
115
- // The old builder also sorted alphabetically, but the compare script passes
116
- // tokens in JSON order so we honour that to get a byte-for-byte match.
117
- const sortedNames = [...grouped.keys()];
118
-
119
- const variableBlocks = sortedNames.map((tokenName) => {
120
- const themeValues = grouped.get(tokenName);
121
-
122
- // Preserve JSON source order exactly.
123
- const themes = Object.keys(themeValues);
124
-
125
- const entries = themes
126
- .map((theme) => {
127
- const normalized = normalizeThemeName(theme);
128
- const value = themeValues[theme];
129
- // Unquoted key — matches t.SassMapProperty(t.Identifier(theme), ...) in old builder
130
- return ` ${normalized}: ${toSassLiteral(value)},`;
131
- })
132
- .join('\n');
133
-
134
- return `\n$${tokenName}: (\n${entries}\n) !default;`;
135
- });
136
-
137
- return (
138
- FILE_BANNER +
139
- `\n@use 'sass:map';\n` +
140
- `@use 'sass:string';\n` +
141
- variableBlocks.join('\n') +
142
- '\n'
143
- );
144
- }
145
-
146
- module.exports = {
147
- name: 'carbon/scss-component-tokens',
148
- format: carbonScssComponentTokensFormat,
149
- };