@ethlete/core 5.0.0-next.63 → 5.0.0-next.65

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.
@@ -21,6 +21,11 @@
21
21
  "schema": "./migrate-surface-interaction-swatch/schema.json",
22
22
  "description": "Rewrite surface theme interactionColor maps into the { color, onColor, inkColor } swatch shape"
23
23
  },
24
+ "migrate-color-theme-variants": {
25
+ "implementation": "./migrate-color-theme-variants/migration",
26
+ "schema": "./migrate-color-theme-variants/schema.json",
27
+ "description": "Rewrite surface theme colorTheme and semanticColorThemes into colorThemeVariants"
28
+ },
24
29
  "migrate-legacy-color-themes": {
25
30
  "implementation": "./migrate-legacy-color-themes/migration",
26
31
  "schema": "./migrate-legacy-color-themes/schema.json",
@@ -0,0 +1,136 @@
1
+ import { Project, SyntaxKind } from 'ts-morph';
2
+ const createProject = () => new Project({
3
+ useInMemoryFileSystem: true,
4
+ compilerOptions: {
5
+ target: 99,
6
+ module: 99,
7
+ },
8
+ });
9
+ const findProperty = (literal, name) => {
10
+ const property = literal.getProperty(name);
11
+ return property?.isKind(SyntaxKind.PropertyAssignment) ? property : undefined;
12
+ };
13
+ const stringValue = (property) => {
14
+ const initializer = property?.getInitializer();
15
+ return initializer?.isKind(SyntaxKind.StringLiteral) || initializer?.isKind(SyntaxKind.NoSubstitutionTemplateLiteral)
16
+ ? initializer.getLiteralText()
17
+ : undefined;
18
+ };
19
+ const literalsOf = (sourceFile) => sourceFile.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression);
20
+ export const collectColorThemesInFile = (filePath, content) => {
21
+ if (!content.includes('primary'))
22
+ return [];
23
+ return literalsOf(createProject().createSourceFile(filePath, content)).flatMap((literal) => {
24
+ const name = stringValue(findProperty(literal, 'name'));
25
+ if (!name || !literal.getProperty('primary'))
26
+ return [];
27
+ return [
28
+ {
29
+ name,
30
+ type: stringValue(findProperty(literal, 'type')),
31
+ isDefault: findProperty(literal, 'isDefault')?.getInitializer()?.getText() === 'true',
32
+ },
33
+ ];
34
+ });
35
+ };
36
+ const uniqueName = (names) => {
37
+ const unique = [...new Set(names)];
38
+ return unique.length === 1 ? unique[0] : undefined;
39
+ };
40
+ const quote = (value) => (/^[A-Za-z_$][\w$]*$/.test(value) ? value : `'${value}'`);
41
+ /**
42
+ * Rewrites a surface theme's deprecated `colorTheme` and `semanticColorThemes` into `colorThemeVariants`, keyed by
43
+ * the `isDefault` theme and the theme of each `type` in `themes`. Existing `colorThemeVariants` entries win, then
44
+ * `semanticColorThemes`, then `colorTheme`, the same order the runtime resolves them in.
45
+ */
46
+ export const migrateColorThemeVariantsInFile = (filePath, content, themes) => {
47
+ if (!content.includes('colorTheme') && !content.includes('semanticColorThemes')) {
48
+ return { changed: false, content, unresolved: [] };
49
+ }
50
+ const defaultName = uniqueName(themes.filter((theme) => theme.isDefault).map((theme) => theme.name));
51
+ const nameOfType = (type) => uniqueName(themes.filter((theme) => theme.type === type).map((theme) => theme.name));
52
+ const sourceFile = createProject().createSourceFile(filePath, content);
53
+ const unresolved = [];
54
+ let changed = false;
55
+ const surfaces = literalsOf(sourceFile).filter((literal) => literal.getProperty('elevation'));
56
+ for (const literal of surfaces) {
57
+ const colorTheme = findProperty(literal, 'colorTheme');
58
+ const semantic = findProperty(literal, 'semanticColorThemes');
59
+ if (!colorTheme && !semantic)
60
+ continue;
61
+ const surfaceName = stringValue(findProperty(literal, 'name')) ?? '<unnamed surface>';
62
+ const variants = findProperty(literal, 'colorThemeVariants');
63
+ const variantsLiteral = variants?.getInitializer();
64
+ if (variants && !variantsLiteral?.isKind(SyntaxKind.ObjectLiteralExpression)) {
65
+ unresolved.push(`${surfaceName}: colorThemeVariants is not an object literal`);
66
+ continue;
67
+ }
68
+ const existingKeys = new Set(variantsLiteral?.isKind(SyntaxKind.ObjectLiteralExpression)
69
+ ? variantsLiteral
70
+ .getProperties()
71
+ .flatMap((property) => property.isKind(SyntaxKind.PropertyAssignment) ? [property.getName().replace(/['"]/g, '')] : [])
72
+ : []);
73
+ const additions = new Map();
74
+ const toRemove = [];
75
+ const add = (key, value) => {
76
+ if (!existingKeys.has(key) && !additions.has(key))
77
+ additions.set(key, value);
78
+ };
79
+ let semanticResolved = true;
80
+ if (semantic) {
81
+ const semanticLiteral = semantic.getInitializer();
82
+ if (!semanticLiteral?.isKind(SyntaxKind.ObjectLiteralExpression)) {
83
+ semanticResolved = false;
84
+ unresolved.push(`${surfaceName}: semanticColorThemes is not an object literal`);
85
+ }
86
+ else {
87
+ const pending = [];
88
+ for (const property of semanticLiteral.getProperties()) {
89
+ const type = property.isKind(SyntaxKind.PropertyAssignment) ? property.getName().replace(/['"]/g, '') : '';
90
+ const value = property.isKind(SyntaxKind.PropertyAssignment) ? stringValue(property) : undefined;
91
+ const key = type ? nameOfType(type) : undefined;
92
+ if (!value || !key) {
93
+ semanticResolved = false;
94
+ unresolved.push(`${surfaceName}: semanticColorThemes entry ${property.getText()} has no single color theme of that type or no string value`);
95
+ continue;
96
+ }
97
+ pending.push([key, value]);
98
+ }
99
+ if (semanticResolved)
100
+ pending.forEach(([key, value]) => add(key, value));
101
+ }
102
+ }
103
+ let colorThemeResolved = true;
104
+ if (colorTheme) {
105
+ const value = stringValue(colorTheme);
106
+ if (!value || !defaultName) {
107
+ colorThemeResolved = false;
108
+ unresolved.push(`${surfaceName}: colorTheme ${colorTheme.getInitializer()?.getText()} needs a string value and exactly one isDefault color theme`);
109
+ }
110
+ else if (value !== defaultName) {
111
+ add(defaultName, value);
112
+ }
113
+ }
114
+ const added = [...additions];
115
+ if (semantic && semanticResolved) {
116
+ toRemove.push(semantic);
117
+ }
118
+ if (colorTheme && colorThemeResolved) {
119
+ toRemove.push(colorTheme);
120
+ }
121
+ if (toRemove.length === 0)
122
+ continue;
123
+ if (added.length > 0) {
124
+ const text = added.map(([key, value]) => `${quote(key)}: '${value}'`).join(', ');
125
+ if (variantsLiteral?.isKind(SyntaxKind.ObjectLiteralExpression)) {
126
+ variantsLiteral.addPropertyAssignments(added.map(([key, value]) => ({ name: quote(key), initializer: `'${value}'` })));
127
+ }
128
+ else {
129
+ toRemove.shift()?.replaceWithText(`colorThemeVariants: { ${text} }`);
130
+ }
131
+ }
132
+ toRemove.forEach((property) => property.remove());
133
+ changed = true;
134
+ }
135
+ return { changed, content: changed ? sourceFile.getFullText() : content, unresolved };
136
+ };
@@ -0,0 +1,46 @@
1
+ import { formatFiles, visitNotIgnoredFiles } from '@nx/devkit';
2
+ import { createMigrationScope } from '../migrate-provider-shape/migration-scope.js';
3
+ import { collectColorThemesInFile, migrateColorThemeVariantsInFile } from './color-theme-variants.js';
4
+ const isSource = (filePath) => filePath.endsWith('.ts') && !filePath.endsWith('.d.ts');
5
+ export default async function migrateColorThemeVariants(tree, schema) {
6
+ console.log('\n🔄 Migrating surface colorTheme and semanticColorThemes to colorThemeVariants...');
7
+ const themes = [];
8
+ visitNotIgnoredFiles(tree, '', (filePath) => {
9
+ if (!isSource(filePath))
10
+ return;
11
+ const content = tree.read(filePath, 'utf-8');
12
+ if (content)
13
+ themes.push(...collectColorThemesInFile(filePath, content));
14
+ });
15
+ const defaults = themes.filter((theme) => theme.isDefault).map((theme) => theme.name);
16
+ console.log(` Color themes found: ${themes.map((theme) => theme.name).join(', ') || 'none'}`);
17
+ console.log(` Default color theme: ${defaults.join(', ') || 'none'}`);
18
+ const scope = createMigrationScope(tree, schema);
19
+ console.log(` Scope: ${scope.describe()}`);
20
+ let filesChanged = 0;
21
+ let unresolvedCount = 0;
22
+ scope.visit(tree, (filePath) => {
23
+ if (!isSource(filePath))
24
+ return;
25
+ const before = tree.read(filePath, 'utf-8');
26
+ if (!before)
27
+ return;
28
+ const result = migrateColorThemeVariantsInFile(filePath, before, themes);
29
+ for (const message of result.unresolved) {
30
+ unresolvedCount++;
31
+ console.warn(` ⚠ ${filePath}: ${message}`);
32
+ }
33
+ if (!result.changed)
34
+ return;
35
+ tree.write(filePath, result.content);
36
+ filesChanged++;
37
+ console.log(` ✓ ${filePath}`);
38
+ });
39
+ console.log(filesChanged === 0 ? ' Nothing to migrate.\n' : `\n✅ Migrated ${filesChanged} file(s).\n`);
40
+ if (unresolvedCount > 0) {
41
+ console.warn(` Review ${unresolvedCount} unresolved value(s) manually. They keep working until the next major.\n`);
42
+ }
43
+ if (!schema.skipFormat) {
44
+ await formatFiles(tree);
45
+ }
46
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "http://json-schema.org/schema",
3
+ "$id": "migrate-color-theme-variants",
4
+ "title": "Migrate surface colorTheme and semanticColorThemes to colorThemeVariants",
5
+ "type": "object",
6
+ "properties": {
7
+ "projects": {
8
+ "type": "array",
9
+ "items": { "type": "string" },
10
+ "description": "Nx projects to migrate. Defaults to every project in the workspace.",
11
+ "alias": "project"
12
+ },
13
+ "include": {
14
+ "type": "array",
15
+ "items": { "type": "string" },
16
+ "description": "Path prefixes to migrate, relative to the workspace root (e.g. 'apps/web'). Unioned with `projects`. Defaults to the whole workspace.",
17
+ "alias": "includePath"
18
+ },
19
+ "skipFormat": {
20
+ "type": "boolean",
21
+ "description": "Skip formatting files after migration",
22
+ "default": false
23
+ }
24
+ },
25
+ "required": []
26
+ }
@@ -1,6 +1,7 @@
1
1
  import { formatFiles, logger, visitNotIgnoredFiles } from '@nx/devkit';
2
2
  import { posix } from 'path';
3
3
  import { Project, SyntaxKind } from 'ts-morph';
4
+ import { colorThemeCss, cssThemeName } from '../../design/theme-css.js';
4
5
  export default async function generate(tree, schema) {
5
6
  logger.log('\n🔄 Starting Tailwind 4 theme generator...\n');
6
7
  const themesPath = schema.themesPath || 'src/themes.ts';
@@ -200,8 +201,8 @@ function parseThemeObject(obj, sourceFile, context) {
200
201
  return theme;
201
202
  }
202
203
  function applyDefaultThemeOverride(themes, defaultTheme) {
203
- const wanted = createCssThemeName(defaultTheme);
204
- const target = themes.find((t) => t.name === defaultTheme || createCssThemeName(t.name) === wanted);
204
+ const wanted = cssThemeName(defaultTheme);
205
+ const target = themes.find((t) => t.name === defaultTheme || cssThemeName(t.name) === wanted);
205
206
  if (!target) {
206
207
  throw new Error(`No theme named "${defaultTheme}" found. Available themes: ${themes.map((t) => t.name).join(', ')}`);
207
208
  }
@@ -362,12 +363,6 @@ function parseColorMap(initializer, sourceFile, context) {
362
363
  }
363
364
  return null;
364
365
  }
365
- function createCssThemeName(name) {
366
- return name
367
- .toLowerCase()
368
- .replace(/\s+/g, '-')
369
- .replace(/[^a-z0-9-]/g, '');
370
- }
371
366
  function generateColorThemeNameTypes(themes, schema) {
372
367
  const themesPath = schema.themesPath || 'src/themes.ts';
373
368
  const outputPath = schema.outputPath || 'src/styles/generated-tailwind-themes.css';
@@ -391,8 +386,6 @@ export {};
391
386
  `;
392
387
  }
393
388
  function generateTailwindThemeCss(themes, utilityPrefix, runtimePrefix, schema) {
394
- const tailwindVars = [];
395
- const themeVars = [];
396
389
  const themesPath = schema.themesPath || 'src/themes.ts';
397
390
  const outputPath = schema.outputPath || 'src/styles/generated-tailwind-themes.css';
398
391
  const header = `/*
@@ -405,183 +398,7 @@ function generateTailwindThemeCss(themes, utilityPrefix, runtimePrefix, schema)
405
398
  */
406
399
 
407
400
  `;
408
- for (const theme of themes) {
409
- const name = createCssThemeName(theme.name);
410
- tailwindVars.push(` /* ${theme.name} theme */`);
411
- addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}`, theme.primary.color);
412
- tailwindVars.push('');
413
- addTailwindColorVariants(tailwindVars, `${utilityPrefix}-on-${name}`, theme.primary.onColor);
414
- tailwindVars.push('');
415
- addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}-ink`, theme.primary.inkColor || theme.primary.color);
416
- tailwindVars.push('');
417
- if (theme.secondary) {
418
- addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}-secondary`, theme.secondary.color);
419
- tailwindVars.push('');
420
- addTailwindColorVariants(tailwindVars, `${utilityPrefix}-on-${name}-secondary`, theme.secondary.onColor);
421
- tailwindVars.push('');
422
- }
423
- if (theme.tertiary) {
424
- addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}-tertiary`, theme.tertiary.color);
425
- tailwindVars.push('');
426
- addTailwindColorVariants(tailwindVars, `${utilityPrefix}-on-${name}-tertiary`, theme.tertiary.onColor);
427
- tailwindVars.push('');
428
- }
429
- }
430
- tailwindVars.push('');
431
- const hasSecondary = themes.some((t) => t.secondary);
432
- const hasTertiary = themes.some((t) => t.tertiary);
433
- // Collect the dynamic theme colors once. They are emitted in `@theme` (so Tailwind generates
434
- // the utilities) and ALSO re-declared on every color selector in the alias block below. A
435
- // Tailwind `@theme` variable only lands on `:root`, so `rgb(var(--<runtime>-color-*))` resolves
436
- // once against the root color scope and inherits that concrete color into descendants - which
437
- // means `bg-<prefix>-theme-*` utilities would ignore nested `.<runtime>-color--*` scopes.
438
- // Re-declaring them per color selector makes the utilities resolve against the nearest scope.
439
- const dynamicColorVars = [];
440
- addDynamicThemeColors(dynamicColorVars, utilityPrefix, runtimePrefix, 'theme', 'primary', false);
441
- addDynamicInkColors(dynamicColorVars, utilityPrefix, runtimePrefix, 'theme-ink', 'primary-ink');
442
- if (hasSecondary) {
443
- addDynamicThemeColors(dynamicColorVars, utilityPrefix, runtimePrefix, 'theme-secondary', 'secondary', false);
444
- }
445
- if (hasTertiary) {
446
- addDynamicThemeColors(dynamicColorVars, utilityPrefix, runtimePrefix, 'theme-tertiary', 'tertiary', false);
447
- }
448
- tailwindVars.push(' /* Dynamic theme colors (references runtime CSS variables) */');
449
- tailwindVars.push(...dynamicColorVars);
450
- themes.forEach((theme) => {
451
- const name = createCssThemeName(theme.name);
452
- const isDefault = theme.isDefault;
453
- if (isDefault) {
454
- const selectors = [':root', `.${runtimePrefix}-color--default`, `.${runtimePrefix}-color--${name}`];
455
- themeVars.push(`${selectors.join(', ')} {`);
456
- }
457
- else {
458
- themeVars.push(`.${runtimePrefix}-color--${name} {`);
459
- }
460
- addThemeColorVariants(themeVars, runtimePrefix, '', theme);
461
- themeVars.push('}\n');
462
- });
463
- // Re-indent the dynamic theme colors (from 2-space `@theme` indent to the 4-space alias-block
464
- // indent) and drop trailing blank lines so they slot cleanly into the alias selector below.
465
- const dynamicColorAliasLines = dynamicColorVars.map((line) => (line === '' ? '' : ` ${line}`));
466
- while (dynamicColorAliasLines.length && dynamicColorAliasLines[dynamicColorAliasLines.length - 1] === '') {
467
- dynamicColorAliasLines.pop();
468
- }
469
- const aliasBlock = `/* Convenience aliases (rgb + solid + opacity variants) */
470
- @layer base {
471
- :root, :where([class*="${runtimePrefix}-color--"]) {
472
- --${runtimePrefix}-theme-color-primary-rgb: var(--${runtimePrefix}-color-primary);
473
- --${runtimePrefix}-theme-color-primary-opacity: 1;
474
- --${runtimePrefix}-theme-color-primary-solid: rgb(var(--${runtimePrefix}-theme-color-primary-rgb));
475
- --${runtimePrefix}-theme-color-primary: rgb(var(--${runtimePrefix}-theme-color-primary-rgb) / var(--${runtimePrefix}-theme-color-primary-opacity));
476
-
477
- --${runtimePrefix}-theme-color-on-primary-rgb: var(--${runtimePrefix}-color-on-primary);
478
- --${runtimePrefix}-theme-color-on-primary-opacity: 1;
479
- --${runtimePrefix}-theme-color-on-primary-solid: rgb(var(--${runtimePrefix}-theme-color-on-primary-rgb) / var(--${runtimePrefix}-theme-color-on-primary-opacity));
480
- --${runtimePrefix}-theme-color-on-primary: rgb(var(--${runtimePrefix}-theme-color-on-primary-rgb) / var(--${runtimePrefix}-theme-color-on-primary-opacity));
481
-
482
- --${runtimePrefix}-theme-color-ink-rgb: var(--${runtimePrefix}-color-primary-ink, var(--${runtimePrefix}-color-primary));
483
- --${runtimePrefix}-theme-color-ink-opacity: 1;
484
- --${runtimePrefix}-theme-color-ink-solid: rgb(var(--${runtimePrefix}-theme-color-ink-rgb) / var(--${runtimePrefix}-theme-color-ink-opacity));
485
- --${runtimePrefix}-theme-color-ink: rgb(var(--${runtimePrefix}-theme-color-ink-rgb) / var(--${runtimePrefix}-theme-color-ink-opacity));
486
-
487
- /* Dynamic Tailwind theme colors - re-declared per color scope so that
488
- bg-${utilityPrefix}-theme-* utilities resolve against the nearest .${runtimePrefix}-color--*
489
- scope instead of the value computed once at :root. */
490
- ${dynamicColorAliasLines.join('\n')}
491
- }
492
- }
493
- `;
494
- return `${header}@theme {
495
- ${tailwindVars.join('\n')}
496
- }
497
-
498
- @layer base {
499
- ${themeVars.join('\n')}
500
- }
501
-
502
- ${aliasBlock}`;
503
- }
504
- function addDynamicThemeColors(vars, utilityPrefix, runtimePrefix, tailwindName, cssVarName, addSpacingBefore) {
505
- if (addSpacingBefore && vars.length > 0 && vars[vars.length - 1] !== '') {
506
- vars.push('');
507
- }
508
- vars.push(` --color-${utilityPrefix}-${tailwindName}: rgb(var(--${runtimePrefix}-color-${cssVarName}));`);
509
- vars.push(` --color-${utilityPrefix}-${tailwindName}-hover: rgb(var(--${runtimePrefix}-color-${cssVarName}-hover));`);
510
- vars.push(` --color-${utilityPrefix}-${tailwindName}-focus: rgb(var(--${runtimePrefix}-color-${cssVarName}-focus));`);
511
- vars.push(` --color-${utilityPrefix}-${tailwindName}-active: rgb(var(--${runtimePrefix}-color-${cssVarName}-active));`);
512
- vars.push(` --color-${utilityPrefix}-${tailwindName}-disabled: rgb(var(--${runtimePrefix}-color-${cssVarName}-disabled));`);
513
- vars.push('');
514
- vars.push(` --color-${utilityPrefix}-on-${tailwindName}: rgb(var(--${runtimePrefix}-color-on-${cssVarName}));`);
515
- vars.push(` --color-${utilityPrefix}-on-${tailwindName}-hover: rgb(var(--${runtimePrefix}-color-on-${cssVarName}-hover));`);
516
- vars.push(` --color-${utilityPrefix}-on-${tailwindName}-focus: rgb(var(--${runtimePrefix}-color-on-${cssVarName}-focus));`);
517
- vars.push(` --color-${utilityPrefix}-on-${tailwindName}-active: rgb(var(--${runtimePrefix}-color-on-${cssVarName}-active));`);
518
- vars.push(` --color-${utilityPrefix}-on-${tailwindName}-disabled: rgb(var(--${runtimePrefix}-color-on-${cssVarName}-disabled));`);
519
- vars.push('');
520
- }
521
- function addDynamicInkColors(vars, utilityPrefix, runtimePrefix, tailwindName, cssVarName) {
522
- vars.push(` --color-${utilityPrefix}-${tailwindName}: rgb(var(--${runtimePrefix}-color-${cssVarName}));`);
523
- vars.push(` --color-${utilityPrefix}-${tailwindName}-hover: rgb(var(--${runtimePrefix}-color-${cssVarName}-hover));`);
524
- vars.push(` --color-${utilityPrefix}-${tailwindName}-focus: rgb(var(--${runtimePrefix}-color-${cssVarName}-focus));`);
525
- vars.push(` --color-${utilityPrefix}-${tailwindName}-active: rgb(var(--${runtimePrefix}-color-${cssVarName}-active));`);
526
- vars.push(` --color-${utilityPrefix}-${tailwindName}-disabled: rgb(var(--${runtimePrefix}-color-${cssVarName}-disabled));`);
527
- vars.push('');
528
- }
529
- function addTailwindColorVariants(vars, colorName, colorSet) {
530
- vars.push(` --color-${colorName}: rgb(${colorSet.default});`);
531
- const hoverValue = 'hover' in colorSet && colorSet.hover ? colorSet.hover : colorSet.default;
532
- vars.push(` --color-${colorName}-hover: rgb(${hoverValue});`);
533
- const focusValue = 'focus' in colorSet && colorSet.focus ? colorSet.focus : hoverValue;
534
- vars.push(` --color-${colorName}-focus: rgb(${focusValue});`);
535
- const activeValue = 'active' in colorSet && colorSet.active ? colorSet.active : hoverValue;
536
- vars.push(` --color-${colorName}-active: rgb(${activeValue});`);
537
- const disabledValue = 'disabled' in colorSet && colorSet.disabled ? colorSet.disabled : colorSet.default;
538
- vars.push(` --color-${colorName}-disabled: rgb(${disabledValue});`);
539
- }
540
- function addThemeColorVariants(vars, prefix, altPrefix, theme) {
541
- const addSwatch = (level, swatch) => {
542
- const defaultColor = swatch.color.default;
543
- const hoverColor = swatch.color.hover || defaultColor;
544
- const focusColor = swatch.color.focus || hoverColor;
545
- const activeColor = swatch.color.active || hoverColor;
546
- const disabledColor = swatch.color.disabled || defaultColor;
547
- vars.push(` --${prefix}-color-${altPrefix}${level}: ${defaultColor};`);
548
- vars.push(` --${prefix}-color-${altPrefix}${level}-hover: ${hoverColor};`);
549
- vars.push(` --${prefix}-color-${altPrefix}${level}-focus: ${focusColor};`);
550
- vars.push(` --${prefix}-color-${altPrefix}${level}-active: ${activeColor};`);
551
- vars.push(` --${prefix}-color-${altPrefix}${level}-disabled: ${disabledColor};`);
552
- vars.push('');
553
- const onDefaultColor = swatch.onColor.default;
554
- const onHoverColor = swatch.onColor.hover || onDefaultColor;
555
- const onFocusColor = swatch.onColor.focus || onHoverColor;
556
- const onActiveColor = swatch.onColor.active || onDefaultColor;
557
- const onDisabledColor = swatch.onColor.disabled || onDefaultColor;
558
- vars.push(` --${prefix}-color-${altPrefix}on-${level}: ${onDefaultColor};`);
559
- vars.push(` --${prefix}-color-${altPrefix}on-${level}-hover: ${onHoverColor};`);
560
- vars.push(` --${prefix}-color-${altPrefix}on-${level}-focus: ${onFocusColor};`);
561
- vars.push(` --${prefix}-color-${altPrefix}on-${level}-active: ${onActiveColor};`);
562
- vars.push(` --${prefix}-color-${altPrefix}on-${level}-disabled: ${onDisabledColor};`);
563
- const inkDefaultColor = swatch.inkColor?.default || defaultColor;
564
- const inkHoverColor = swatch.inkColor?.hover || inkDefaultColor;
565
- const inkFocusColor = swatch.inkColor?.focus || inkHoverColor;
566
- const inkActiveColor = swatch.inkColor?.active || inkDefaultColor;
567
- const inkDisabledColor = swatch.inkColor?.disabled || inkDefaultColor;
568
- vars.push('');
569
- vars.push(` --${prefix}-color-${altPrefix}${level}-ink: ${inkDefaultColor};`);
570
- vars.push(` --${prefix}-color-${altPrefix}${level}-ink-hover: ${inkHoverColor};`);
571
- vars.push(` --${prefix}-color-${altPrefix}${level}-ink-focus: ${inkFocusColor};`);
572
- vars.push(` --${prefix}-color-${altPrefix}${level}-ink-active: ${inkActiveColor};`);
573
- vars.push(` --${prefix}-color-${altPrefix}${level}-ink-disabled: ${inkDisabledColor};`);
574
- if (theme.secondary || theme.tertiary) {
575
- vars.push('');
576
- }
577
- };
578
- addSwatch('primary', theme.primary);
579
- if (theme.secondary) {
580
- addSwatch('secondary', theme.secondary);
581
- }
582
- if (theme.tertiary) {
583
- addSwatch('tertiary', theme.tertiary);
584
- }
401
+ return `${header}${colorThemeCss(themes, { prefix: utilityPrefix, runtimePrefix })}`;
585
402
  }
586
403
  function findMainStylesFile(tree) {
587
404
  const potentialFiles = [];