@motion-proto/live-tokens 0.47.0 → 0.48.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 (124) hide show
  1. package/.claude/skills/live-tokens-adjust-shape-space/SKILL.md +68 -0
  2. package/.claude/skills/live-tokens-create-component/SKILL.md +2 -2
  3. package/.claude/skills/live-tokens-generate-theme/SKILL.md +152 -0
  4. package/CHANGELOG.md +292 -0
  5. package/README.md +37 -26
  6. package/bin/adjust.mjs +254 -0
  7. package/bin/cli.mjs +94 -7
  8. package/bin/generate-theme.mjs +251 -0
  9. package/bin/migrate.mjs +95 -6
  10. package/dist-plugin/adjust/index.cjs +259 -0
  11. package/dist-plugin/adjust/index.d.cts +45 -0
  12. package/dist-plugin/adjust/index.d.ts +45 -0
  13. package/dist-plugin/adjust/index.js +176 -0
  14. package/dist-plugin/{chunk-H4TRUINI.js → chunk-44RSTAII.js} +0 -48
  15. package/dist-plugin/chunk-6OZFXIQI.js +316 -0
  16. package/dist-plugin/chunk-76TFDTJO.js +556 -0
  17. package/dist-plugin/chunk-D3ZVKOR4.js +52 -0
  18. package/dist-plugin/dataPaths-DBN0RPuT.d.cts +54 -0
  19. package/dist-plugin/dataPaths-DBN0RPuT.d.ts +54 -0
  20. package/dist-plugin/generateColorsAndType/index.cjs +1781 -0
  21. package/dist-plugin/generateColorsAndType/index.d.cts +81 -0
  22. package/dist-plugin/generateColorsAndType/index.d.ts +81 -0
  23. package/dist-plugin/generateColorsAndType/index.js +1210 -0
  24. package/dist-plugin/index.cjs +901 -533
  25. package/dist-plugin/index.d.cts +3 -2
  26. package/dist-plugin/index.d.ts +3 -2
  27. package/dist-plugin/index.js +658 -1082
  28. package/dist-plugin/migrateData/index.cjs +728 -0
  29. package/dist-plugin/migrateData/index.d.cts +60 -0
  30. package/dist-plugin/migrateData/index.d.ts +60 -0
  31. package/dist-plugin/migrateData/index.js +348 -0
  32. package/dist-plugin/themeTypes-DMHZOnUn.d.cts +211 -0
  33. package/dist-plugin/themeTypes-DMHZOnUn.d.ts +211 -0
  34. package/dist-plugin/tokensCssMigrations/index.cjs +2 -1
  35. package/dist-plugin/tokensCssMigrations/index.d.cts +3 -15
  36. package/dist-plugin/tokensCssMigrations/index.d.ts +3 -15
  37. package/dist-plugin/tokensCssMigrations/index.js +4 -2
  38. package/package.json +18 -4
  39. package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +183 -158
  40. package/src/editor/component-editor/scaffolding/ComponentFileMenu.svelte +0 -4
  41. package/src/editor/component-editor/scaffolding/SaveAsDialog.svelte +4 -4
  42. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +2 -59
  43. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +1 -1
  44. package/src/editor/core/components/adjustAliases.ts +180 -0
  45. package/src/editor/core/components/aliasKinds.ts +73 -0
  46. package/src/editor/core/components/componentConfigService.ts +26 -38
  47. package/src/editor/core/flashStatus.ts +1 -1
  48. package/src/editor/core/fonts/fontMigration.ts +13 -13
  49. package/src/editor/core/fonts/fontPairing.ts +35 -0
  50. package/src/editor/core/palettes/paletteDerivation.ts +128 -16
  51. package/src/editor/core/preview/lookPreview.ts +141 -0
  52. package/src/editor/core/productionPulse.ts +34 -21
  53. package/src/editor/core/storage/files/versionedFileResourceClient.ts +18 -45
  54. package/src/editor/core/store/editorConfigStore.ts +2 -2
  55. package/src/editor/core/store/editorPersistence.ts +0 -1
  56. package/src/editor/core/store/editorStore.ts +114 -51
  57. package/src/editor/core/store/editorTypes.ts +0 -1
  58. package/src/editor/core/store/gradientSource.ts +2 -2
  59. package/src/editor/core/themes/colorsAndTypeService.ts +95 -0
  60. package/src/editor/core/themes/generateColorsAndType.ts +433 -0
  61. package/src/editor/core/themes/loadRows.ts +64 -0
  62. package/src/editor/core/themes/lookSummary.ts +75 -0
  63. package/src/editor/core/themes/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +3 -3
  64. package/src/editor/core/themes/migrations/2026-05-13-primary-to-brand.ts +2 -2
  65. package/src/editor/core/themes/migrations/2026-05-26-drop-overlay-extra-stops.ts +3 -3
  66. package/src/editor/core/themes/migrations/2026-08-13-drop-legacy-shape-space-keys.ts +38 -0
  67. package/src/editor/core/themes/migrations/2026-08-15-line-height-scale-rename.ts +57 -0
  68. package/src/editor/core/themes/migrations/index.ts +19 -11
  69. package/src/editor/core/themes/slices/components.ts +4 -4
  70. package/src/editor/core/themes/slices/fonts.ts +1 -1
  71. package/src/editor/core/themes/slices/gradients.ts +22 -0
  72. package/src/editor/core/themes/slices/palettes.ts +2 -2
  73. package/src/editor/core/themes/themeInit.ts +21 -29
  74. package/src/editor/core/themes/themeService.ts +218 -78
  75. package/src/editor/core/themes/themeTypes.ts +94 -51
  76. package/src/editor/docs/Docs.svelte +1 -0
  77. package/src/editor/docs/chapters.ts +1 -0
  78. package/src/editor/docs/content/01-overview.md +1 -1
  79. package/src/editor/docs/content/editing-tokens.md +6 -6
  80. package/src/editor/docs/content/getting-started.md +9 -7
  81. package/src/editor/docs/content/themes-workflow.md +74 -34
  82. package/src/editor/docs/content/where-themes-live.md +61 -0
  83. package/src/editor/docs/content.generated.ts +5 -4
  84. package/src/editor/index.ts +27 -27
  85. package/src/editor/pages/ComponentEditorPage.svelte +2 -2
  86. package/src/editor/pages/EditorShell.svelte +4 -30
  87. package/src/editor/ui/BezierCurveEditor.svelte +2 -2
  88. package/src/editor/ui/ColorEditPanel.svelte +1 -1
  89. package/src/editor/ui/FileLoadList.svelte +67 -7
  90. package/src/editor/ui/GradientEditor.svelte +3 -3
  91. package/src/editor/ui/PaletteEditor.svelte +26 -12
  92. package/src/editor/ui/ThemePanel.svelte +1067 -0
  93. package/src/editor/ui/UIDialog.svelte +11 -9
  94. package/src/editor/ui/UIPillButton.svelte +7 -2
  95. package/src/editor/ui/colors/ColorWheel.svelte +34 -1
  96. package/src/editor/ui/curveEngine.ts +48 -0
  97. package/src/editor/ui/index.ts +4 -2
  98. package/src/editor/ui/palette/PaletteBase.svelte +75 -51
  99. package/src/editor/ui/palette/PaletteJumpButton.svelte +3 -8
  100. package/src/live-tokens/data/colors-and-type/autumn.json +2490 -0
  101. package/src/live-tokens/data/{themes → colors-and-type}/default.json +816 -293
  102. package/src/live-tokens/data/colors-and-type/halloween.json +2529 -0
  103. package/src/live-tokens/data/colors-and-type/midnight-study.json +2536 -0
  104. package/src/live-tokens/data/colors-and-type/ocean.json +2489 -0
  105. package/src/live-tokens/data/colors-and-type/royal-velvet.json +2520 -0
  106. package/src/live-tokens/data/colors-and-type/spring-meadow.json +2476 -0
  107. package/src/live-tokens/data/colors-and-type/sunset.json +2528 -0
  108. package/src/live-tokens/data/themes/autumn.json +3918 -0
  109. package/src/live-tokens/data/themes/halloween.json +3992 -0
  110. package/src/live-tokens/data/themes/midnight-study.json +3932 -0
  111. package/src/live-tokens/data/themes/ocean.json +3917 -0
  112. package/src/live-tokens/data/themes/royal-velvet.json +3983 -0
  113. package/src/live-tokens/data/themes/spring-meadow.json +3904 -0
  114. package/src/live-tokens/data/themes/sunset.json +3931 -0
  115. package/src/live-tokens/data/tokens.generated.css +106 -117
  116. package/src/system/styles/CONVENTIONS.md +1 -1
  117. package/src/system/styles/fonts.css +1 -1
  118. package/template/README.md +7 -5
  119. package/template/_gitignore +0 -6
  120. package/src/editor/core/components/componentPersist.ts +0 -62
  121. package/src/editor/core/manifests/manifestService.ts +0 -172
  122. package/src/editor/ui/ManifestFileManager.svelte +0 -446
  123. package/src/editor/ui/ThemeFileManager.svelte +0 -785
  124. package/src/live-tokens/data/manifests/default.json +0 -35
@@ -0,0 +1,57 @@
1
+ import type { Migration } from './index';
2
+
3
+ /**
4
+ * The data half of the tokens.css migration `2026-07-20-line-height-rename`,
5
+ * which reshaped the line-height scale from size vocabulary to leading
6
+ * vocabulary. That pass renames the definitions in `tokens.css`; a saved file
7
+ * still references the old names, and a reference to a token that no longer
8
+ * exists renders as nothing. Both layers reference the scale, so both migrate:
9
+ * colors-and-type through its `cssVariables`, a component config through its
10
+ * alias values.
11
+ *
12
+ * `xl` (2) has no slot in the leading scale, so it lands on `relaxed` (1.75),
13
+ * the nearest surviving step. That is a visible change to a line that used it,
14
+ * and the only alternative is a dangling reference.
15
+ *
16
+ * Values alone, never keys: a key is a definition (or, in a component config,
17
+ * the component's own token), and remapping `--line-height-xl` onto
18
+ * `--line-height-relaxed` would redefine a surviving step at 2 for everything
19
+ * that references it.
20
+ */
21
+ const RENAMED: Record<string, string> = {
22
+ '--line-height-xs': '--line-height-none',
23
+ '--line-height-sm': '--line-height-tighter',
24
+ '--line-height-md': '--line-height-normal',
25
+ '--line-height-lg': '--line-height-relaxed',
26
+ '--line-height-xl': '--line-height-relaxed',
27
+ };
28
+
29
+ // Bare (`--line-height-md`) and wrapped (`var(--line-height-md)`) references
30
+ // both occur; the lookahead keeps `--line-height-md` from matching inside a
31
+ // longer name.
32
+ const REFERENCE = /--line-height-(?:xs|sm|md|lg|xl)(?![\w-])/g;
33
+
34
+ function renameValues(rawVars: Record<string, string>): Record<string, string> {
35
+ const out: Record<string, string> = {};
36
+ for (const [key, value] of Object.entries(rawVars)) {
37
+ out[key] =
38
+ typeof value === 'string' ? value.replace(REFERENCE, (name) => RENAMED[name]) : value;
39
+ }
40
+ return out;
41
+ }
42
+
43
+ export const colorsAndTypeMigration_2026_08_15_lineHeightScaleRename: Migration = {
44
+ id: '2026-08-15-line-height-scale-rename-colors-and-type',
45
+ fromVersion: 4,
46
+ toVersion: 5,
47
+ appliesTo: 'colors-and-type',
48
+ apply: renameValues,
49
+ };
50
+
51
+ export const componentMigration_2026_08_15_lineHeightScaleRename: Migration = {
52
+ id: '2026-08-15-line-height-scale-rename-component',
53
+ fromVersion: 20,
54
+ toVersion: 21,
55
+ appliesTo: 'component-config',
56
+ apply: renameValues,
57
+ };
@@ -8,7 +8,7 @@
8
8
  * is past a given version, that migration's bookkeeping is dead code and
9
9
  * the file can be deleted.
10
10
  *
11
- * Theme and component-config have INDEPENDENT version sequences. Every
11
+ * ColorsAndType and component-config have INDEPENDENT version sequences. Every
12
12
  * theme migration steps the theme version; every component-config migration
13
13
  * steps the component-config version. There is no shared 'both' kind.
14
14
  */
@@ -25,19 +25,19 @@ export interface Migration {
25
25
  /** Post-condition version — files past this no longer need this migration. */
26
26
  toVersion: number;
27
27
  /** Which storage flavor this applies to. */
28
- appliesTo: 'theme' | 'component-config';
28
+ appliesTo: 'colors-and-type' | 'component-config';
29
29
  /** Pure transform on the raw vars map. May add, remove, or rename keys. */
30
30
  apply(rawVars: Record<string, string>, meta: MigrationMeta): Record<string, string>;
31
31
  }
32
32
 
33
- import { themeMigration_2026_04_24_legacyKeysAndBgToCanvas } from './2026-04-24-legacy-keys-and-bg-to-canvas';
33
+ import { colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas } from './2026-04-24-legacy-keys-and-bg-to-canvas';
34
34
  import { componentMigration_2026_04_24_prefixAndSuffixRenames } from './2026-04-24-component-prefix-and-suffix-renames';
35
35
  import { componentMigration_2026_04_27_segmentedcontrolDisabledFlatten } from './2026-04-27-segmentedcontrol-disabled-flatten';
36
36
  import { componentMigration_2026_05_08_collapsiblesectionVariantNamespace } from './2026-05-08-collapsiblesection-variant-namespace';
37
37
  import { componentMigration_2026_05_08_collapsiblesectionFrameAndCleanup } from './2026-05-08-collapsiblesection-frame-and-cleanup';
38
38
  import { componentMigration_2026_05_10_sectiondividerGradientStops } from './2026-05-10-sectiondivider-gradient-stops';
39
39
  import {
40
- themeMigration_2026_05_13_primaryToBrand,
40
+ colorsAndTypeMigration_2026_05_13_primaryToBrand,
41
41
  componentMigration_2026_05_13_primaryToBrand,
42
42
  } from './2026-05-13-primary-to-brand';
43
43
  import { componentMigration_2026_05_19_collapsiblesectionDropFrameSurface } from './2026-05-19-collapsiblesection-drop-frame-surface';
@@ -51,20 +51,25 @@ import { componentMigration_2026_05_24_progressbarCollapseVariants } from './202
51
51
  import { componentMigration_2026_05_24_collapsiblesectionDropActiveState } from './2026-05-24-collapsiblesection-drop-active-state';
52
52
  import { componentMigration_2026_05_25_cornerbadgeFlattenVariants } from './2026-05-25-cornerbadge-flatten-variants';
53
53
  import {
54
- themeMigration_2026_05_26_dropOverlayExtraStops,
54
+ colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops,
55
55
  componentMigration_2026_05_26_dropOverlayExtraStops,
56
56
  } from './2026-05-26-drop-overlay-extra-stops';
57
57
  import { componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth } from './2026-05-29-tabbar-indicator-thickness-to-per-state-width';
58
58
  import { componentMigration_2026_05_29_segmentedcontrolSmallDividerRename } from './2026-05-29-segmentedcontrol-small-divider-rename';
59
59
  import { componentMigration_2026_05_29_toggleDeriveTrackFromThumb } from './2026-05-29-toggle-derive-track-from-thumb';
60
+ import { colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys } from './2026-08-13-drop-legacy-shape-space-keys';
61
+ import {
62
+ colorsAndTypeMigration_2026_08_15_lineHeightScaleRename,
63
+ componentMigration_2026_08_15_lineHeightScaleRename,
64
+ } from './2026-08-15-line-height-scale-rename';
60
65
 
61
66
  /**
62
67
  * Registered migrations. Order in this array does not matter — the runner
63
68
  * filters by `appliesTo` and sorts by `toVersion` before applying.
64
69
  */
65
70
  export const MIGRATIONS: Migration[] = [
66
- themeMigration_2026_04_24_legacyKeysAndBgToCanvas,
67
- themeMigration_2026_05_13_primaryToBrand,
71
+ colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas,
72
+ colorsAndTypeMigration_2026_05_13_primaryToBrand,
68
73
  componentMigration_2026_04_24_prefixAndSuffixRenames,
69
74
  componentMigration_2026_04_27_segmentedcontrolDisabledFlatten,
70
75
  componentMigration_2026_05_08_collapsiblesectionVariantNamespace,
@@ -81,14 +86,17 @@ export const MIGRATIONS: Migration[] = [
81
86
  componentMigration_2026_05_24_progressbarCollapseVariants,
82
87
  componentMigration_2026_05_24_collapsiblesectionDropActiveState,
83
88
  componentMigration_2026_05_25_cornerbadgeFlattenVariants,
84
- themeMigration_2026_05_26_dropOverlayExtraStops,
89
+ colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops,
85
90
  componentMigration_2026_05_26_dropOverlayExtraStops,
86
91
  componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth,
87
92
  componentMigration_2026_05_29_segmentedcontrolSmallDividerRename,
88
93
  componentMigration_2026_05_29_toggleDeriveTrackFromThumb,
94
+ colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys,
95
+ colorsAndTypeMigration_2026_08_15_lineHeightScaleRename,
96
+ componentMigration_2026_08_15_lineHeightScaleRename,
89
97
  ];
90
98
 
91
- function countFor(kind: 'theme' | 'component-config'): number {
99
+ function countFor(kind: 'colors-and-type' | 'component-config'): number {
92
100
  return MIGRATIONS.filter((m) => m.appliesTo === kind).length;
93
101
  }
94
102
 
@@ -97,7 +105,7 @@ function countFor(kind: 'theme' | 'component-config'): number {
97
105
  * adding a new dated migration file (and importing it above) auto-bumps the
98
106
  * relevant constant.
99
107
  */
100
- export const CURRENT_THEME_SCHEMA_VERSION = countFor('theme');
108
+ export const CURRENT_COLORS_AND_TYPE_SCHEMA_VERSION = countFor('colors-and-type');
101
109
  export const CURRENT_COMPONENT_SCHEMA_VERSION = countFor('component-config');
102
110
 
103
111
  /**
@@ -109,7 +117,7 @@ export const CURRENT_COMPONENT_SCHEMA_VERSION = countFor('component-config');
109
117
  * fromVersion=N can be deleted without affecting any load path.
110
118
  */
111
119
  export function runMigrations(
112
- kind: 'theme' | 'component-config',
120
+ kind: 'colors-and-type' | 'component-config',
113
121
  fileVersion: number,
114
122
  rawVars: Record<string, string>,
115
123
  meta: MigrationMeta = {},
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Components slice — per-component `{ activeFile, aliases, config, unlinked? }`.
2
+ * Components slice — per-component `{ aliases, config, unlinked? }`.
3
3
  *
4
4
  * `aliases` are the typed component-token → semantic-token map (each entry is
5
5
  * a `CssVarRef` discriminated union: `{ kind: 'token', name }` or
@@ -106,7 +106,7 @@ export function setComponentAlias(component: string, varName: string, ref: CssVa
106
106
  if (existing) {
107
107
  existing.aliases[varName] = ref;
108
108
  } else {
109
- s.components[component] = { activeFile: 'default', aliases: { [varName]: ref }, config: {} };
109
+ s.components[component] = { aliases: { [varName]: ref }, config: {} };
110
110
  }
111
111
  });
112
112
  }
@@ -125,7 +125,7 @@ export function setComponentConfig(component: string, key: string, value: unknow
125
125
  if (existing) {
126
126
  existing.config[key] = value;
127
127
  } else {
128
- s.components[component] = { activeFile: 'default', aliases: {}, config: { [key]: value } };
128
+ s.components[component] = { aliases: {}, config: { [key]: value } };
129
129
  }
130
130
  });
131
131
  }
@@ -272,7 +272,7 @@ export function setComponentAliasLinked(component: string, varName: string, ref:
272
272
  return;
273
273
  }
274
274
  mutate(`link ${component}/${groupKey}`, (s) => {
275
- const slice = s.components[component] ?? (s.components[component] = { activeFile: 'default', aliases: {}, config: {} });
275
+ const slice = s.components[component] ?? (s.components[component] = { aliases: {}, config: {} });
276
276
  const unlinked = (slice.unlinked ?? []).filter((p) => p !== varName);
277
277
  slice.aliases[varName] = ref;
278
278
  for (const v of siblings) {
@@ -20,7 +20,7 @@ export function setFontStacks(stacks: FontStack[]): void {
20
20
  * Populate fonts from the server's active theme at boot. Does not push
21
21
  * a history entry — the boot load is a starting point, not an edit.
22
22
  */
23
- export function seedFontsFromTheme(sources: FontSource[], stacks: FontStack[]): void {
23
+ export function seedFontsFromColorsAndType(sources: FontSource[], stacks: FontStack[]): void {
24
24
  store.update((s) => {
25
25
  s.fonts.sources = structuredClone(sources);
26
26
  s.fonts.stacks = structuredClone(stacks);
@@ -5,6 +5,7 @@
5
5
  * edits flow through.
6
6
  */
7
7
  import type { EditorState, GradientToken, GradientTokenStop, GradientType, GradientAliasValue } from '../../store/editorTypes';
8
+ import type { GradientDiskToken } from '../themeTypes';
8
9
  import { mutate } from '../../store/editorCore';
9
10
 
10
11
  export function makeDefaultGradients(): GradientToken[] {
@@ -48,6 +49,27 @@ export function makeDefaultGradients(): GradientToken[] {
48
49
  ];
49
50
  }
50
51
 
52
+ /**
53
+ * Loader: restore the gradient library from a file's structured `gradients`
54
+ * field and scrub the rendered `--gradient-N` strings from the vars bag — they
55
+ * are a projection kept for production CSS, never a basis. Files without the
56
+ * field (saved before gradients round-tripped) keep the seeded defaults, which
57
+ * match what those files rendered. A file whose slots don't match the fixed
58
+ * four is stale-shaped and also keeps defaults, mirroring the persistence
59
+ * layer's `migrateGradients` guard.
60
+ */
61
+ export function loadGradientsFromFile(
62
+ next: EditorState,
63
+ gradients: GradientDiskToken[] | undefined,
64
+ rawVars: Record<string, string>,
65
+ ): void {
66
+ const expected = makeDefaultGradients().map((g) => g.variable).sort();
67
+ for (const name of expected) delete rawVars[name];
68
+ const have = (gradients ?? []).map((g) => g.variable).sort();
69
+ const matches = have.length === expected.length && expected.every((v, i) => v === have[i]);
70
+ if (matches) next.gradients.tokens = structuredClone(gradients) as GradientToken[];
71
+ }
72
+
51
73
  function formatGradientStop(s: GradientTokenStop): string {
52
74
  return `${formatGradientStopColor(s)} ${s.position}%`;
53
75
  }
@@ -15,9 +15,9 @@ export function setPaletteConfig(label: string, config: PaletteConfig): void {
15
15
 
16
16
  /**
17
17
  * Server-boot path: populate all palettes at once without a history entry.
18
- * Mirrors `seedFontsFromTheme`.
18
+ * Mirrors `seedFontsFromColorsAndType`.
19
19
  */
20
- export function seedPalettesFromTheme(palettes: Record<string, PaletteConfig>): void {
20
+ export function seedPalettesFromColorsAndType(palettes: Record<string, PaletteConfig>): void {
21
21
  store.update((s) => {
22
22
  s.palettes = structuredClone(palettes);
23
23
  return s;
@@ -1,31 +1,25 @@
1
- import type { AliasDiskValue, Theme } from './themeTypes';
2
- import { activeFileName } from '../store/editorConfigStore';
3
- import { migrateThemeFonts } from '../fonts/fontMigration';
1
+ import type { AliasDiskValue, ColorsAndType } from './themeTypes';
2
+ import { openThemeSlug } from '../store/editorConfigStore';
3
+ import { migrateColorsAndTypeFonts } from '../fonts/fontMigration';
4
4
  import { applyFontSources, applyFontStacks } from '../fonts/fontLoader';
5
5
  import { loadFromFile, seedComponentsFromApi } from '../store/editorStore';
6
- import { getActiveComponentConfig } from '../components/componentConfigService';
6
+ import { getActiveComponentConfig, type ComponentSummary } from '../components/componentConfigService';
7
7
  import { safeFetch } from '../storage/storage';
8
8
  import { API_BASE } from '../storage/apiBase';
9
9
 
10
- interface ComponentSummaryDto {
11
- name: string;
12
- activeFile: string;
13
- productionFile: string;
14
- }
15
-
16
10
  interface ListComponentsDto {
17
- components: ComponentSummaryDto[];
11
+ components: ComponentSummary[];
18
12
  }
19
13
 
20
14
  /**
21
- * Fetch the active theme from the server and apply its CSS variables
22
- * to :root before the app mounts. Seeds the editor store so PaletteEditors
23
- * initialize from the theme instead of stale localStorage.
15
+ * Fetch the live colors and type from the server and apply their CSS
16
+ * variables to :root before the app mounts. Seeds the editor store so
17
+ * PaletteEditors initialize from the server state instead of stale localStorage.
24
18
  *
25
- * Routes the theme through `loadFromFile` so palette-derived vars in
19
+ * Routes the payload through `loadFromFile` so palette-derived vars in
26
20
  * `deriveCssVars` correctly overwrite any stale hexes baked into
27
- * `theme.cssVariables` by `handleSave`'s scrape. Writing
28
- * `theme.cssVariables` directly to inline :root (the previous approach)
21
+ * `cssVariables` by `handleSave`'s scrape. Writing
22
+ * `cssVariables` directly to inline :root (the previous approach)
29
23
  * bypassed the store and left the subscriber's `lastApplied` diff cache
30
24
  * out of sync, so palette-derived values stayed stale until a
31
25
  * `PaletteEditor` mounted and re-emitted them.
@@ -35,32 +29,30 @@ interface ListComponentsDto {
35
29
  * `safeFetch` (instead of empty try/catch) to make the silence intentional.
36
30
  */
37
31
  export async function initializeTheme(): Promise<void> {
38
- const theme = await safeFetch<Theme>(`${API_BASE}/themes/active`);
39
- if (theme) {
40
- migrateThemeFonts(theme);
41
- loadFromFile(theme);
42
- if (theme.fontSources && theme.fontSources.length > 0) {
43
- applyFontSources(theme.fontSources);
32
+ const colorsAndType = await safeFetch<ColorsAndType>(`${API_BASE}/colors-and-type/active`);
33
+ if (colorsAndType) {
34
+ migrateColorsAndTypeFonts(colorsAndType);
35
+ loadFromFile(colorsAndType);
36
+ if (colorsAndType.fontSources && colorsAndType.fontSources.length > 0) {
37
+ applyFontSources(colorsAndType.fontSources);
44
38
  }
45
- if (theme.fontStacks && theme.fontStacks.length > 0) {
46
- applyFontStacks(theme.fontStacks, theme.fontSources ?? []);
39
+ if (colorsAndType.fontStacks && colorsAndType.fontStacks.length > 0) {
40
+ applyFontStacks(colorsAndType.fontStacks, colorsAndType.fontSources ?? []);
47
41
  }
48
- const fileName = theme._fileName || 'default';
49
- activeFileName.set(fileName);
42
+ openThemeSlug.set(colorsAndType._fileName || 'default');
50
43
  }
51
44
 
52
45
  const list = await safeFetch<ListComponentsDto>(`${API_BASE}/component-configs`);
53
46
  if (list && Array.isArray(list.components)) {
54
47
  const configs: Record<
55
48
  string,
56
- { activeFile: string; aliases: Record<string, AliasDiskValue>; config?: Record<string, unknown>; schemaVersion?: number }
49
+ { aliases: Record<string, AliasDiskValue>; config?: Record<string, unknown>; schemaVersion?: number }
57
50
  > = {};
58
51
  await Promise.all(
59
52
  list.components.map(async (c) => {
60
53
  const cfg = await getActiveComponentConfig(c.name);
61
54
  if (cfg) {
62
55
  configs[c.name] = {
63
- activeFile: c.activeFile,
64
56
  aliases: cfg.aliases,
65
57
  config: cfg.config,
66
58
  schemaVersion: cfg.schemaVersion,