@carbon/themes 12.0.0-alpha.0 → 12.0.0-alpha.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 (75) 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 -5
  13. package/umd/index.js +6322 -0
  14. package/docs/sass.md +0 -189
  15. package/js/generated/component-tokens/button.d.ts +0 -98
  16. package/js/generated/component-tokens/button.js +0 -98
  17. package/js/generated/component-tokens/content-switcher.d.ts +0 -25
  18. package/js/generated/component-tokens/content-switcher.js +0 -25
  19. package/js/generated/component-tokens/notification.d.ts +0 -65
  20. package/js/generated/component-tokens/notification.js +0 -65
  21. package/js/generated/component-tokens/status.d.ts +0 -63
  22. package/js/generated/component-tokens/status.js +0 -63
  23. package/js/generated/component-tokens/tag.d.ts +0 -247
  24. package/js/generated/component-tokens/tag.js +0 -247
  25. package/js/generated/themes/g10.d.ts +0 -242
  26. package/js/generated/themes/g10.js +0 -242
  27. package/js/generated/themes/g100.d.ts +0 -242
  28. package/js/generated/themes/g100.js +0 -242
  29. package/js/generated/themes/g90.d.ts +0 -242
  30. package/js/generated/themes/g90.js +0 -242
  31. package/js/generated/themes/white.d.ts +0 -242
  32. package/js/generated/themes/white.js +0 -242
  33. package/src/dtcg/README.md +0 -336
  34. package/src/dtcg/color-palette.json +0 -4424
  35. package/src/dtcg/components/button.json +0 -193
  36. package/src/dtcg/components/content-switcher.json +0 -60
  37. package/src/dtcg/components/notification.json +0 -130
  38. package/src/dtcg/components/status.json +0 -122
  39. package/src/dtcg/components/tag.json +0 -486
  40. package/src/dtcg/themes.json +0 -3356
  41. package/src/index.ts +0 -129
  42. package/src/tokens/Token.ts +0 -41
  43. package/src/tokens/TokenFormat.ts +0 -93
  44. package/src/tokens/TokenGroup.ts +0 -185
  45. package/src/tokens/TokenSet.ts +0 -91
  46. package/src/tokens/components.ts +0 -120
  47. package/src/tokens/index.ts +0 -59
  48. package/src/tokens/layout.ts +0 -39
  49. package/src/tokens/type.ts +0 -49
  50. package/src/tokens/types.ts +0 -28
  51. package/src/tokens/v10.ts +0 -188
  52. package/src/tokens/v11TokenGroup.ts +0 -546
  53. package/src/tokens/v11TokenSet.ts +0 -93
  54. package/src/tools.ts +0 -69
  55. package/src/v10/g10.ts +0 -349
  56. package/src/v10/g100.ts +0 -348
  57. package/src/v10/g90.ts +0 -350
  58. package/src/v10/index.ts +0 -22
  59. package/src/v10/metadata.yml +0 -217
  60. package/src/v10/tokens.ts +0 -397
  61. package/src/v10/white.ts +0 -352
  62. package/style-dictionary/formats/js-component-tokens.js +0 -128
  63. package/style-dictionary/formats/js-themes.js +0 -84
  64. package/style-dictionary/formats/scss-component-tokens.js +0 -149
  65. package/style-dictionary/formats/scss-themes.js +0 -127
  66. package/style-dictionary/formats/scss-tokens.js +0 -91
  67. package/style-dictionary/preprocessors/component-tokens.js +0 -172
  68. package/style-dictionary/preprocessors/dual-role.js +0 -157
  69. package/style-dictionary/preprocessors/theme-metadata.js +0 -46
  70. package/style-dictionary/sd.config.js +0 -449
  71. package/style-dictionary/transforms/alpha-modifier.js +0 -68
  72. package/style-dictionary/transforms/color-flatten.js +0 -79
  73. package/test-dtcg.scss +0 -28
  74. package/tsconfig.json +0 -8
  75. package/tsconfig.types.json +0 -10
@@ -1,449 +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
- * Style Dictionary configuration for @carbon/themes.
12
- *
13
- * Wires together the custom plugins in this directory
14
- *
15
- */
16
-
17
- const path = require('path');
18
- const fs = require('fs-extra');
19
- const { default: StyleDictionary } = require('style-dictionary');
20
-
21
- // ── Custom plugins ────────────────────────────────────────────────────────────
22
- const carbonColorFlatten = require('./transforms/color-flatten');
23
- const carbonAlphaModifier = require('./transforms/alpha-modifier');
24
- const carbonComponentTokensPreprocessorModule = require('./preprocessors/component-tokens');
25
- const { preprocessor: carbonComponentTokensPreprocessor } =
26
- carbonComponentTokensPreprocessorModule;
27
- const carbonThemeMetadataPreprocessor = require('./preprocessors/theme-metadata');
28
- const { preprocessor: flattenDualRole } = require('./preprocessors/dual-role');
29
- const carbonScssThemes = require('./formats/scss-themes');
30
- const carbonScssTokens = require('./formats/scss-tokens');
31
- const carbonScssComponentTokens = require('./formats/scss-component-tokens');
32
- const carbonJsThemes = require('./formats/js-themes');
33
- const carbonJsComponentTokens = require('./formats/js-component-tokens');
34
-
35
- // ── Paths ─────────────────────────────────────────────────────────────────────
36
- const ROOT = path.resolve(__dirname, '..');
37
- const DTCG_DIR = path.join(ROOT, 'src', 'dtcg');
38
- const SCSS_GENERATED = path.join(ROOT, 'scss', 'generated');
39
- const JS_GENERATED_THEMES = path.join(ROOT, 'js', 'generated', 'themes');
40
- const JS_GENERATED_COMPONENTS = path.join(
41
- ROOT,
42
- 'js',
43
- 'generated',
44
- 'component-tokens'
45
- );
46
-
47
- const THEME_NAMES = ['white', 'g10', 'g90', 'g100'];
48
-
49
- // Light/dark scheme per theme — used to re-inject color-scheme metadata after
50
- // extractThemeSlice strips the root $extensions from the unified file.
51
- const THEME_COLOR_SCHEME = {
52
- white: 'light',
53
- g10: 'light',
54
- g90: 'dark',
55
- g100: 'dark',
56
- };
57
- const COMPONENT_NAMES = [
58
- 'button',
59
- 'tag',
60
- 'notification',
61
- 'status',
62
- 'content-switcher',
63
- ];
64
-
65
- // ── extractThemeSlice ─────────────────────────────────────────────────────────
66
- //
67
- // After the component-tokens preprocessor runs on themes.json, every leaf token
68
- // node becomes a group with a `_by_theme` child containing one synthetic leaf
69
- // per theme. This function walks the expanded tree and replaces each
70
- // `_by_theme` group with the single synthetic leaf for `themeName`, collapsing
71
- // the tree back into a normal per-theme token structure that the rest of the
72
- // pipeline (flattenDualRole, SD transforms, formatters) understands.
73
- //
74
- // Tokens that do NOT have a _by_theme group (palette reference tokens injected
75
- // via `source:`) are passed through unchanged.
76
- function extractThemeSlice(node, themeName) {
77
- if (!node || typeof node !== 'object') return node;
78
-
79
- const out = {};
80
- for (const [key, value] of Object.entries(node)) {
81
- if (key.startsWith('$')) {
82
- out[key] = value;
83
- continue;
84
- }
85
- if (!value || typeof value !== 'object') {
86
- out[key] = value;
87
- continue;
88
- }
89
- if (key === '_by_theme') {
90
- // Skip — handled by the parent via the `value._by_theme` branch below.
91
- continue;
92
- }
93
-
94
- // Check if this child node has a _by_theme group (i.e. it was a leaf or
95
- // dual-role node in themes.json that the preprocessor expanded).
96
- if (value._by_theme) {
97
- const leaf = value._by_theme[themeName];
98
- if (leaf) {
99
- // Start with the leaf's DTCG fields ($type, $value, $extensions).
100
- const merged = { ...leaf };
101
- // Preserve $description from the group wrapper (leaf synthetic nodes
102
- // don't carry it, but the original themes.json node does).
103
- if (!merged.$description && value.$description)
104
- merged.$description = value.$description;
105
- if (!merged.$type && value.$type) merged.$type = value.$type;
106
-
107
- // Recurse into any group children of this node (dual-role case):
108
- // e.g. `background` is both a token and the parent of `background-active`.
109
- for (const [childKey, childValue] of Object.entries(value)) {
110
- if (childKey.startsWith('$') || childKey === '_by_theme') continue;
111
- if (!childValue || typeof childValue !== 'object') continue;
112
- const sliced = extractThemeSlice(
113
- { [childKey]: childValue },
114
- themeName
115
- );
116
- if (sliced[childKey] !== undefined)
117
- merged[childKey] = sliced[childKey];
118
- }
119
-
120
- out[key] = merged;
121
- }
122
- // If the theme had no entry, skip the token.
123
- } else {
124
- const sliced = extractThemeSlice(value, themeName);
125
- if (sliced !== null) out[key] = sliced;
126
- }
127
- }
128
- return out;
129
- }
130
-
131
- // ── Custom name transform ─────────────────────────────────────────────────────
132
- //
133
- // Builds a kebab-case name from the SD token path, with one special rule:
134
- // a path segment equal to `_self` is stripped. This is used in conjunction
135
- // with the carbon/dual-role preprocessor — dual-role parent token values are
136
- // placed under a `_self` child key so that SD processes them as separate leaf
137
- // tokens, but their output name omits the `_self` suffix.
138
- //
139
- // Examples:
140
- // ['background'] → 'background'
141
- // ['background', '_self'] → 'background' (parent of dual-role node)
142
- // ['background', 'active'] → 'background-active'
143
- // ['layer', '01'] → 'layer-01'
144
- // ['layer', '_self'] → 'layer'
145
- const carbonNameKebab = {
146
- name: 'carbon/name-kebab',
147
- type: 'name',
148
- transform(token) {
149
- return token.path
150
- .filter((p) => p !== '_self')
151
- .map((p) => p.replace(/^_/, '').replace(/_/g, '-'))
152
- .join('-');
153
- },
154
- };
155
-
156
- // ── Transform group ────────────────────────────────────────────────────────────
157
- //
158
- // Order matters: alpha-modifier must fire BEFORE color-flatten so the hex
159
- // is already resolved when flatten runs.
160
- // Both are `transitive: true` — SD re-applies them until the value stabilises.
161
- const CARBON_TRANSFORMS = [
162
- 'attribute/cti',
163
- 'carbon/name-kebab', // custom: strips _self from dual-role parent paths
164
- 'carbon/alpha-modifier',
165
- 'carbon/color-flatten',
166
- ];
167
-
168
- // ── Helper: build config for one theme ───────────────────────────────────────
169
- //
170
- // themes.json is the unified source — all four themes in one file, with each
171
- // token carrying per-theme values under $extensions["carbon.themes"].
172
- // The component-tokens preprocessor expands those into per-theme leaf tokens
173
- // (identical to what it does for component files), and dual-role splitting
174
- // then runs on the resulting tree so SD sees clean leaf+group pairs.
175
- function themeConfig(themeName) {
176
- // Read the unified themes.json. The component-tokens preprocessor first
177
- // expands carbon.themes entries into _by_theme.<theme> leaf nodes, then
178
- // flattenDualRole splits any dual-role nodes (value + children) so SD can
179
- // process them without losing children.
180
- const rawThemes = JSON.parse(
181
- fs.readFileSync(path.join(DTCG_DIR, 'themes.json'), 'utf8')
182
- );
183
- // The component-tokens preprocessor understands the { value, alpha } entry
184
- // shape from the unified file as well as the legacy bare-string shape from
185
- // component files. Run it first so carbon.themes entries become $value leaves.
186
- const expanded = carbonComponentTokensPreprocessor(rawThemes);
187
- // Now extract only this theme's _by_theme.<themeName> leaf nodes, rewriting
188
- // them back to plain $value tokens so the rest of the pipeline sees a normal
189
- // single-theme token tree.
190
- const rawSlice = extractThemeSlice(expanded, themeName);
191
-
192
- // Re-attach the per-theme color-scheme to the root $extensions so that
193
- // carbonThemeMetadataPreprocessor (which reads
194
- // dictionary.$extensions["org.carbon"]["color-scheme"]) can inject the
195
- // color-scheme synthetic token. extractThemeSlice does not carry the root
196
- // $extensions through because they are global, not per-token.
197
- const themeSlice = {
198
- ...rawSlice,
199
- $extensions: {
200
- ...(rawSlice.$extensions ?? {}),
201
- 'org.carbon': {
202
- ...(rawSlice.$extensions?.['org.carbon'] ?? {}),
203
- 'color-scheme': THEME_COLOR_SCHEME[themeName],
204
- },
205
- },
206
- };
207
-
208
- const flatTokens = flattenDualRole(themeSlice);
209
-
210
- return {
211
- source: [path.join(DTCG_DIR, 'color-palette.json')],
212
- tokens: flatTokens,
213
- preprocessors: ['carbon/theme-metadata'],
214
- platforms: {
215
- // SCSS theme map
216
- [`scss/themes/${themeName}`]: {
217
- transformGroup: 'carbon',
218
- buildPath: SCSS_GENERATED + '/',
219
- files: [
220
- {
221
- // Each theme writes to its own temp file; a post-step
222
- // (buildAllPlatforms action) concatenates them into _themes.scss.
223
- destination: `_theme-${themeName}.scss`,
224
- format: 'carbon/scss-themes',
225
- options: { themeName },
226
- // Exclude palette reference tokens from the theme map.
227
- filter(token) {
228
- const role =
229
- token.$extensions?.['org.carbon']?.role ??
230
- token.extensions?.['org.carbon']?.role;
231
- return role !== 'reference';
232
- },
233
- },
234
- ],
235
- },
236
- // JS theme module
237
- [`js/themes/${themeName}`]: {
238
- transformGroup: 'carbon',
239
- buildPath: JS_GENERATED_THEMES + '/',
240
- files: [
241
- {
242
- destination: `${themeName}.js`,
243
- format: 'carbon/js-themes',
244
- options: { themeName, output: 'js' },
245
- filter(token) {
246
- const role =
247
- token.$extensions?.['org.carbon']?.role ??
248
- token.extensions?.['org.carbon']?.role;
249
- return role !== 'reference';
250
- },
251
- },
252
- {
253
- destination: `${themeName}.d.ts`,
254
- format: 'carbon/js-themes',
255
- options: { themeName, output: 'dts' },
256
- filter(token) {
257
- const role =
258
- token.$extensions?.['org.carbon']?.role ??
259
- token.extensions?.['org.carbon']?.role;
260
- return role !== 'reference';
261
- },
262
- },
263
- ],
264
- },
265
- },
266
- };
267
- }
268
-
269
- // ── Helper: build config for one component ───────────────────────────────────
270
- function componentConfig(componentName) {
271
- return {
272
- source: [
273
- path.join(DTCG_DIR, 'color-palette.json'),
274
- path.join(DTCG_DIR, 'components', `${componentName}.json`),
275
- ],
276
- preprocessors: ['carbon/component-tokens'],
277
- platforms: {
278
- // SCSS component token map
279
- [`scss/component-tokens/${componentName}`]: {
280
- transformGroup: 'carbon',
281
- buildPath: SCSS_GENERATED + '/',
282
- files: [
283
- {
284
- destination: `_${componentName}-tokens.scss`,
285
- format: 'carbon/scss-component-tokens',
286
- filter(token) {
287
- // Only include expanded theme tokens (injected by preprocessor)
288
- return token.name.includes('-by-theme-');
289
- },
290
- },
291
- ],
292
- },
293
- // JS component token module
294
- [`js/component-tokens/${componentName}`]: {
295
- transformGroup: 'carbon',
296
- buildPath: JS_GENERATED_COMPONENTS + '/',
297
- files: [
298
- {
299
- destination: `${componentName}.js`,
300
- format: 'carbon/js-component-tokens',
301
- options: { output: 'js' },
302
- filter(token) {
303
- return token.name.includes('-by-theme-');
304
- },
305
- },
306
- {
307
- destination: `${componentName}.d.ts`,
308
- format: 'carbon/js-component-tokens',
309
- options: { output: 'dts' },
310
- filter(token) {
311
- return token.name.includes('-by-theme-');
312
- },
313
- },
314
- ],
315
- },
316
- },
317
- };
318
- }
319
-
320
- // ── _tokens.scss config ───────────────────────────────────────────────────────
321
- //
322
- // This file does not use token values at all — it reads from Carbon JS metadata
323
- // directly. We still run it through SD so it participates in buildAllPlatforms
324
- // and can be tested alongside the other outputs.
325
- const tokensConfig = {
326
- // No source files needed — format reads from src/tokens directly.
327
- source: [],
328
- platforms: {
329
- 'scss/tokens': {
330
- transformGroup: 'carbon',
331
- buildPath: SCSS_GENERATED + '/',
332
- files: [
333
- {
334
- destination: '_tokens.scss',
335
- format: 'carbon/scss-tokens',
336
- },
337
- ],
338
- },
339
- },
340
- };
341
-
342
- // ── Build a registered SD instance ────────────────────────────────────────────
343
- // In SD v5, register* methods live on the instance, not the class.
344
- // We create one base instance with all plugins registered, then extend it
345
- // per-config so each build inherits the registrations.
346
- function createBase() {
347
- const base = new StyleDictionary({});
348
- // Register custom transforms BEFORE the transform group that references them.
349
- base.registerTransform(carbonNameKebab);
350
- base.registerTransform(carbonAlphaModifier);
351
- base.registerTransform(carbonColorFlatten);
352
- base.registerTransformGroup({
353
- name: 'carbon',
354
- transforms: CARBON_TRANSFORMS,
355
- });
356
- base.registerPreprocessor(carbonComponentTokensPreprocessorModule);
357
- base.registerPreprocessor(carbonThemeMetadataPreprocessor);
358
- base.registerFormat(carbonScssThemes);
359
- base.registerFormat(carbonScssTokens);
360
- base.registerFormat(carbonScssComponentTokens);
361
- base.registerFormat(carbonJsThemes);
362
- base.registerFormat(carbonJsComponentTokens);
363
- return base;
364
- }
365
-
366
- // ── SCSS build ────────────────────────────────────────────────────────────────
367
- // Generates:
368
- // scss/generated/_themes.scss
369
- // scss/generated/_tokens.scss
370
- // scss/generated/_button-tokens.scss (and tag, notification, status, content-switcher)
371
- async function runScss() {
372
- const base = createBase();
373
- const scssTokensContent = await carbonScssTokens.format({
374
- dictionary: { allTokens: [] },
375
- options: {},
376
- file: {},
377
- });
378
- fs.ensureDirSync(SCSS_GENERATED);
379
- fs.writeFileSync(
380
- path.join(SCSS_GENERATED, '_tokens.scss'),
381
- scssTokensContent,
382
- 'utf8'
383
- );
384
-
385
- // Per-theme maps — write to temp files, then concatenate
386
- for (const themeName of THEME_NAMES) {
387
- await (await base.extend(themeConfig(themeName))).buildAllPlatforms();
388
- }
389
-
390
- // Concatenate per-theme temp files into a single _themes.scss
391
- const themeParts = THEME_NAMES.map((name) => {
392
- const src = path.join(SCSS_GENERATED, `_theme-${name}.scss`);
393
- const content = fs.readFileSync(src, 'utf8');
394
- return name === THEME_NAMES[0]
395
- ? content
396
- : '\n' +
397
- content
398
- .replace(/^\/\/[^\n]*\n(?:\/\/[^\n]*\n)*/m, '') // strip banner
399
- .replace(/^@use [^\n]+\n/gm, '') // strip duplicate @use
400
- .replace(/^\n+/, ''); // collapse leading blanks
401
- });
402
- fs.writeFileSync(
403
- path.join(SCSS_GENERATED, '_themes.scss'),
404
- themeParts.join(''),
405
- 'utf8'
406
- );
407
- for (const name of THEME_NAMES) {
408
- fs.removeSync(path.join(SCSS_GENERATED, `_theme-${name}.scss`));
409
- }
410
-
411
- // Component token maps
412
- for (const componentName of COMPONENT_NAMES) {
413
- await (
414
- await base.extend(componentConfig(componentName))
415
- ).buildAllPlatforms();
416
- }
417
- }
418
-
419
- // ── JS build ──────────────────────────────────────────────────────────────────
420
- // Generates:
421
- // js/generated/themes/{white,g10,g90,g100}.{js,d.ts}
422
- // js/generated/component-tokens/{button,tag,…}.{js,d.ts}
423
- async function runJs() {
424
- const base = createBase();
425
-
426
- for (const themeName of THEME_NAMES) {
427
- await (await base.extend(themeConfig(themeName))).buildAllPlatforms();
428
- }
429
- for (const componentName of COMPONENT_NAMES) {
430
- await (
431
- await base.extend(componentConfig(componentName))
432
- ).buildAllPlatforms();
433
- }
434
- }
435
-
436
- // ── Full build (SCSS + JS) ────────────────────────────────────────────────────
437
- async function run() {
438
- await runScss();
439
- await runJs();
440
- }
441
-
442
- module.exports = {
443
- run,
444
- runScss,
445
- runJs,
446
- themeConfig,
447
- componentConfig,
448
- tokensConfig,
449
- };
@@ -1,68 +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
- * Applies the `$extensions["org.carbon"].alphaModifier` field to theme tokens,
13
- * producing an `rgba()` string.
14
- *
15
- * Must run AFTER alias resolution (transitive: true) so that by the time this
16
- * transform fires, `token.value` is already the resolved hex string from the
17
- * palette (e.g. '#8d8d8d' for gray.50), not the raw alias '{gray.50}'.
18
- *
19
- * If no alphaModifier extension is present the token is passed through
20
- * unchanged (carbon/color-flatten will handle it next).
21
- *
22
- * Example in themes.json:
23
- * "background-active": {
24
- * "$type": "color",
25
- * "$value": "{gray.50}", ← resolved by SD to '#8d8d8d'
26
- * "$extensions": {
27
- * "org.carbon": { "alphaModifier": 0.5 }
28
- * }
29
- * }
30
- * → 'rgba(141, 141, 141, 0.5)'
31
- */
32
-
33
- module.exports = {
34
- name: 'carbon/alpha-modifier',
35
- type: 'value',
36
- transitive: true,
37
- filter(token) {
38
- const ext =
39
- token.$extensions?.['org.carbon'] ?? token.extensions?.['org.carbon'];
40
- return ext?.alphaModifier !== undefined;
41
- },
42
- transform(token) {
43
- const ext =
44
- token.$extensions?.['org.carbon'] ?? token.extensions?.['org.carbon'];
45
- const alpha = ext.alphaModifier;
46
-
47
- // SD v5: post-alias value is in token.$value (resolved object or hex string).
48
- // In the golden-master test, token.value holds the pre-resolved hex string.
49
- const resolved = token.value !== undefined ? token.value : token.$value;
50
- const hex =
51
- typeof resolved === 'string'
52
- ? resolved
53
- : typeof resolved === 'object' && resolved?.hex
54
- ? resolved.hex
55
- : null;
56
-
57
- if (!hex || !hex.startsWith('#') || hex.length < 7) {
58
- // Fallback: if resolution hasn't happened yet, return unchanged and let
59
- // the transitive pass retry.
60
- return token.value ?? token.$value;
61
- }
62
-
63
- const r = parseInt(hex.slice(1, 3), 16);
64
- const g = parseInt(hex.slice(3, 5), 16);
65
- const b = parseInt(hex.slice(5, 7), 16);
66
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
67
- },
68
- };
@@ -1,79 +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
- * Converts the DTCG color $value object shapes used by this codebase into
13
- * plain CSS color strings, after Style Dictionary has already resolved any
14
- * alias references.
15
- *
16
- * Input shapes (post-alias-resolution, i.e. $value is already an object):
17
- *
18
- * Shape A — solid inline object
19
- * { colorSpace: 'srgb', components: [...], hex: '#rrggbb' }
20
- * → '#rrggbb'
21
- *
22
- * Shape B — alpha inline object (components + alpha, no hex)
23
- * { colorSpace: 'srgb', components: [r, g, b], alpha: 0.5 }
24
- * → 'rgba(r, g, b, 0.5)'
25
- *
26
- * Plain strings and non-sRGB objects are passed through unchanged.
27
- *
28
- * NOTE: The alias+alphaModifier case (Shape C) is handled upstream by the
29
- * carbon/alpha-modifier transform, which runs first (transitive: true ensures
30
- * the resolved alias value is already in scope when this transform fires).
31
- */
32
-
33
- module.exports = {
34
- name: 'carbon/color-flatten',
35
- type: 'value',
36
- transitive: true,
37
- filter(token) {
38
- return token.$type === 'color' || token.type === 'color';
39
- },
40
- transform(token) {
41
- // SD v5 stores the post-alias-resolution value in token.$value (the DTCG
42
- // field), NOT in token.value. token.value is only set after transforms run.
43
- // The golden-master test sets both; in that context token.value is preferred
44
- // so the test can simulate resolution without running full SD.
45
- const v = token.value !== undefined ? token.value : token.$value;
46
-
47
- if (typeof v === 'string') {
48
- // Already a plain string (e.g. '#0f62fe' or 'rgba(...)') — pass through.
49
- return v;
50
- }
51
-
52
- if (v === null || typeof v !== 'object') {
53
- return v;
54
- }
55
-
56
- // SD v5 can resolve an alias to the full token node instead of its value
57
- // when the alias points to a sibling token (e.g. {syntax.value} resolving
58
- // to the syntax.value token object). Unwrap one level.
59
- if ('$value' in v) {
60
- const inner = v.$value;
61
- if (typeof inner === 'string') return inner;
62
- if (inner?.hex) return inner.hex;
63
- }
64
-
65
- if (v.colorSpace !== 'srgb' || !Array.isArray(v.components)) {
66
- return v;
67
- }
68
-
69
- // Shape A — solid: hex present
70
- if (typeof v.hex === 'string') {
71
- return v.hex;
72
- }
73
-
74
- // Shape B — alpha: derive rgba from 0–1 component floats
75
- const [r, g, b] = v.components.map((c) => Math.round(c * 255));
76
- const alpha = v.alpha !== undefined ? v.alpha : 1;
77
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
78
- },
79
- };
package/test-dtcg.scss DELETED
@@ -1,28 +0,0 @@
1
- @use 'scss/themes' as *;
2
- @use 'scss/component-tokens' as *;
3
-
4
- // Test that all 4 themes are available
5
- .test-white {
6
- background: map-get($white, 'background');
7
- }
8
-
9
- .test-g10 {
10
- background: map-get($g10, 'background');
11
- }
12
-
13
- .test-g90 {
14
- background: map-get($g90, 'background');
15
- }
16
-
17
- .test-g100 {
18
- background: map-get($g100, 'background');
19
- }
20
-
21
- // Test component tokens
22
- .test-button {
23
- background: map-get($button-primary, 'white');
24
- }
25
-
26
- .test-tag {
27
- background: map-get($tag-background-blue, 'white');
28
- }
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "typescript-config-carbon/tsconfig.base.json",
3
- "compilerOptions": {
4
- "declaration": false,
5
- "emitDeclarationOnly": false
6
- },
7
- "include": ["src/**/*"]
8
- }
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "declaration": true,
5
- "emitDeclarationOnly": true,
6
- "declarationDir": "./lib",
7
- "rootDir": "./src"
8
- },
9
- "include": ["src/**/*"]
10
- }