@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
@@ -6,7 +6,8 @@
6
6
  show: boolean;
7
7
  title: string;
8
8
  files: F[];
9
- activeFileName: string;
9
+ /** Marks the row the editor already has open. Omit where no row is. */
10
+ activeFileName?: string;
10
11
  /** Show name/date sort headers above the list. */
11
12
  sortable?: boolean;
12
13
  /** Render the updatedAt column on each row. */
@@ -20,20 +21,37 @@
20
21
  /** Shown when `files` is empty. Omit to render no row at all. */
21
22
  emptyMessage?: string;
22
23
  width?: string;
24
+ /** Marks the row the user picked, for lists where picking is a step rather
25
+ * than the whole action (theme preview). Null leaves every row unpicked. */
26
+ selectedFileName?: string | null;
27
+ /** Badge on the selected row, naming what picking it did. Null hides it. */
28
+ selectedBadge?: { label: string; title: string } | null;
29
+ /** Per-row badge naming what kind of file the row is, for lists that mix
30
+ * kinds. Null leaves the row unmarked. */
31
+ rowBadge?: (file: F) => { label: string; title: string } | null;
32
+ /** Dialog footer: label for the dismiss button, and an optional commit
33
+ * button. Both pass straight through to `UIDialog`. */
34
+ cancelLabel?: string;
35
+ confirmLabel?: string;
36
+ onconfirm?: () => void;
23
37
  onload: (file: F) => void;
24
38
  ondelete?: (file: F) => void;
25
- /** Optional per-row export action — e.g. download a manifest bundle.
39
+ /** Optional per-row export action — e.g. download a theme bundle.
26
40
  * When omitted, no export button renders. */
27
41
  onexport?: (file: F) => void;
42
+ /** Whether the export button should appear for a row. Default: every row. */
43
+ canExport?: (file: F) => boolean;
28
44
  /** Tooltip for the per-row export button. Falls back to "Export {name}". */
29
45
  exportTitle?: (file: F) => string;
46
+ /** Controls under the list, above the dialog footer. */
47
+ options?: import('svelte').Snippet;
30
48
  }
31
49
 
32
50
  let {
33
51
  show = $bindable(false),
34
52
  title,
35
53
  files,
36
- activeFileName,
54
+ activeFileName = '',
37
55
  sortable = false,
38
56
  showUpdatedAt = false,
39
57
  isProtected = (f) => f.isProtected ?? f.fileName === 'default',
@@ -41,10 +59,18 @@
41
59
  systemBadge = null,
42
60
  emptyMessage,
43
61
  width = '420px',
62
+ selectedFileName = null,
63
+ selectedBadge = null,
64
+ rowBadge,
65
+ cancelLabel = 'Close',
66
+ confirmLabel = '',
67
+ onconfirm,
44
68
  onload,
45
69
  ondelete,
46
70
  onexport,
71
+ canExport,
47
72
  exportTitle,
73
+ options,
48
74
  }: Props = $props();
49
75
 
50
76
  type SortKey = 'name' | 'updatedAt';
@@ -101,9 +127,14 @@
101
127
  if (canDelete) return canDelete(file);
102
128
  return !isProtected(file);
103
129
  }
130
+
131
+ function shouldShowExport(file: F): boolean {
132
+ if (!onexport) return false;
133
+ return canExport ? canExport(file) : true;
134
+ }
104
135
  </script>
105
136
 
106
- <UIDialog bind:show {title} cancelLabel="Close" {width}>
137
+ <UIDialog bind:show {title} {cancelLabel} {confirmLabel} {onconfirm} {width}>
107
138
  <div class="load-list">
108
139
  {#if sortable}
109
140
  <div class="load-header">
@@ -137,9 +168,14 @@
137
168
  <div
138
169
  class="load-item"
139
170
  class:active={file.fileName === activeFileName}
171
+ class:selected={file.fileName === selectedFileName}
140
172
  class:protected={protectedRow}
141
173
  >
142
- <button class="load-name-btn" onclick={() => handleLoad(file)}>
174
+ <button
175
+ class="load-name-btn"
176
+ aria-pressed={selectedFileName === null ? undefined : file.fileName === selectedFileName}
177
+ onclick={() => handleLoad(file)}
178
+ >
143
179
  {#if protectedRow}
144
180
  <i class="fas fa-lock system-glyph" aria-hidden="true"></i>
145
181
  {/if}
@@ -148,13 +184,21 @@
148
184
  {#if protectedRow && systemBadge}
149
185
  <span class="system-badge" title={systemBadge.title}>{systemBadge.label}</span>
150
186
  {/if}
187
+ {#if rowBadge}
188
+ {@const badge = rowBadge(file)}
189
+ {#if badge}
190
+ <span class="system-badge" title={badge.title}>{badge.label}</span>
191
+ {/if}
192
+ {/if}
151
193
  {#if showUpdatedAt}
152
194
  <span class="updated-at" title={file.updatedAt}>{formatUpdatedAt(file.updatedAt)}</span>
153
195
  {/if}
154
- {#if file.fileName === activeFileName}
196
+ {#if file.fileName === selectedFileName && selectedBadge}
197
+ <span class="active-badge" title={selectedBadge.title}>{selectedBadge.label}</span>
198
+ {:else if file.fileName === activeFileName}
155
199
  <span class="active-badge">Active</span>
156
200
  {/if}
157
- {#if onexport}
201
+ {#if shouldShowExport(file)}
158
202
  <button
159
203
  class="file-action-btn"
160
204
  onclick={stopPropagation(() => onexport!(file))}
@@ -178,6 +222,9 @@
178
222
  <div class="load-item empty">{emptyMessage}</div>
179
223
  {/if}
180
224
  </div>
225
+ {#if options}
226
+ <div class="load-options">{@render options()}</div>
227
+ {/if}
181
228
  </UIDialog>
182
229
 
183
230
  <style>
@@ -188,6 +235,11 @@
188
235
  overflow-y: auto;
189
236
  }
190
237
 
238
+ .load-options {
239
+ padding: var(--ui-space-10) var(--ui-space-4) var(--ui-space-2);
240
+ border-top: 1px solid var(--ui-border-low);
241
+ }
242
+
191
243
  .load-header {
192
244
  display: flex;
193
245
  align-items: center;
@@ -289,6 +341,14 @@
289
341
  color: #e0e0e0;
290
342
  }
291
343
 
344
+ .load-item.selected {
345
+ background: var(--ui-surface-high);
346
+ }
347
+
348
+ .load-item.selected .load-name-btn {
349
+ color: var(--ui-text-primary);
350
+ }
351
+
292
352
  .load-item.active .load-name-btn {
293
353
  color: #e0e0e0;
294
354
  font-weight: 600;
@@ -7,7 +7,7 @@
7
7
  import { get } from 'svelte/store';
8
8
  import type { GradientType, GradientTokenStop } from '../core/store/editorTypes';
9
9
  import {
10
- themeGradientSource,
10
+ colorsAndTypeGradientSource,
11
11
  snapshotGradient,
12
12
  type GradientSource,
13
13
  type GradientSourceSnapshot,
@@ -20,7 +20,7 @@
20
20
  import { snapTokenToFamily } from '../core/palettes/familySwap';
21
21
 
22
22
  interface Props {
23
- /** Theme-gradient mode: variable name (e.g. `--gradient-1`). */
23
+ /** ColorsAndType-gradient mode: variable name (e.g. `--gradient-1`). */
24
24
  variable?: string;
25
25
  /** Component-gradient mode: source adapter. Wins over `variable`. */
26
26
  source?: GradientSource;
@@ -52,7 +52,7 @@
52
52
 
53
53
  // Captured once: callers remount when the target gradient changes.
54
54
  // svelte-ignore state_referenced_locally
55
- const gradientSource: GradientSource = source ?? themeGradientSource(variable!);
55
+ const gradientSource: GradientSource = source ?? colorsAndTypeGradientSource(variable!);
56
56
  // Local const so Svelte 5's `$<store>` auto-subscription works.
57
57
  const gradientSourceCurrent = gradientSource.current;
58
58
  // svelte-ignore state_referenced_locally
@@ -8,6 +8,7 @@
8
8
  import GradientStopEditor from './palette/GradientStopEditor.svelte';
9
9
  import ScaleCurveEditor from './palette/ScaleCurveEditor.svelte';
10
10
  import PaletteBase from './palette/PaletteBase.svelte';
11
+ import PaletteJumpButton from './palette/PaletteJumpButton.svelte';
11
12
  import { type EditingState, idleState, BASE_KEY, isEditingBase as isBaseEdit } from './palette/paletteEditorState';
12
13
  import { dockTrackTemplate } from './palette/dockMagnify';
13
14
  import {
@@ -520,6 +521,7 @@
520
521
  <span>Gradient</span>
521
522
  </label>
522
523
  {/if}
524
+ <PaletteJumpButton family={label} {displayLabel} target="wheel" />
523
525
  <UIPillButton size="compact" variant="outline" onclick={clearPaletteOverrides}>Clear Overrides</UIPillButton>
524
526
  <UIPillButton size="compact" variant="outline" onclick={() => paletteEditorOpen = !paletteEditorOpen}>
525
527
  {paletteEditorOpen ? 'Close' : 'Edit'}
@@ -551,7 +553,9 @@
551
553
  onkeydown={(e) => e.key === 'Enter' && handlePaletteClick({ label: ps.label, lightness: ps.lightness, index: ps.index })}
552
554
  >
553
555
  {#if ps.key in overrides}
554
- <span class="override-dot" title="Palette override"></span>
556
+ <span class="override-lock" title="Palette override: this step is set by hand, not derived from the curve">
557
+ <i class="fas fa-lock" aria-hidden="true"></i>
558
+ </span>
555
559
  {/if}
556
560
  </div>
557
561
  <button
@@ -864,7 +868,7 @@
864
868
  align-items: start;
865
869
  justify-content: start;
866
870
  min-width: 0;
867
- max-width: calc(var(--swatch-cols) * 4rem + (var(--swatch-cols) - 1) * var(--swatch-gap, var(--ui-space-4)));
871
+ max-width: calc(var(--swatch-cols) * 4.5rem + (var(--swatch-cols) - 1) * var(--swatch-gap, var(--ui-space-4)));
868
872
  }
869
873
 
870
874
  .curve-grid-span {
@@ -897,7 +901,7 @@
897
901
 
898
902
  .swatch.gray-swatch {
899
903
  width: 100%;
900
- height: calc(4rem + var(--ui-space-2));
904
+ height: calc(4.75rem + var(--ui-space-2));
901
905
  /* Compensating margin: height + margin-bottom is constant every frame of
902
906
  the magnification, so the grid's row height never dips mid-transition
903
907
  (the dip bounced everything below the palette). Also keeps the hex row
@@ -928,19 +932,29 @@
928
932
  change — the swatch itself already IS the picked color. */
929
933
  .swatch.gray-swatch.anchored {
930
934
  border-color: var(--ui-border-higher);
931
- height: calc(5rem + var(--ui-space-2));
935
+ height: calc(5.75rem + var(--ui-space-2));
932
936
  margin-bottom: 0;
933
937
  }
934
938
 
935
- .override-dot {
939
+ /* An overridden step is held by hand and no longer follows the curve, which a
940
+ lock says and a dot could not. The badge carries its own dark disc: the
941
+ ramp runs from near-white to near-black, so no single glyph colour reads
942
+ against every swatch it can land on. */
943
+ .override-lock {
936
944
  position: absolute;
937
- top: 3px;
938
- right: 3px;
939
- width: 6px;
940
- height: 6px;
941
- border-radius: 50%;
942
- background: var(--ui-text-primary);
943
- border: 1px solid rgba(255, 255, 255, 0.6);
945
+ top: var(--ui-space-4);
946
+ right: var(--ui-space-4);
947
+ display: flex;
948
+ align-items: center;
949
+ justify-content: center;
950
+ width: 1.125rem;
951
+ height: 1.125rem;
952
+ border-radius: var(--ui-radius-full);
953
+ background: rgba(0, 0, 0, 0.55);
954
+ box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.45);
955
+ color: #fff;
956
+ font-size: var(--ui-font-size-xs);
957
+ line-height: 1;
944
958
  }
945
959
 
946
960
  .empty-mode-toggle {