@motion-proto/live-tokens 0.6.2 → 0.7.1

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 (212) hide show
  1. package/README.md +14 -13
  2. package/dist-plugin/index.cjs +147 -136
  3. package/dist-plugin/index.d.cts +1 -1
  4. package/dist-plugin/index.d.ts +1 -1
  5. package/dist-plugin/index.js +145 -135
  6. package/package.json +25 -40
  7. package/src/{component-editor → editor/component-editor}/BadgeEditor.svelte +8 -82
  8. package/src/{component-editor → editor/component-editor}/CalloutEditor.svelte +4 -4
  9. package/src/{component-editor → editor/component-editor}/CardEditor.svelte +28 -76
  10. package/src/{component-editor → editor/component-editor}/CollapsibleSectionEditor.svelte +3 -3
  11. package/src/{component-editor → editor/component-editor}/CornerBadgeEditor.svelte +31 -93
  12. package/src/{component-editor → editor/component-editor}/DialogEditor.svelte +60 -57
  13. package/src/editor/component-editor/ImageEditor.svelte +30 -0
  14. package/src/{component-editor → editor/component-editor}/InlineEditActionsEditor.svelte +6 -4
  15. package/src/editor/component-editor/MenuSelectEditor.svelte +160 -0
  16. package/src/{component-editor → editor/component-editor}/NotificationEditor.svelte +64 -37
  17. package/src/{component-editor → editor/component-editor}/ProgressBarEditor.svelte +5 -4
  18. package/src/{component-editor → editor/component-editor}/RadioButtonEditor.svelte +3 -3
  19. package/src/{component-editor → editor/component-editor}/SectionDividerEditor.svelte +57 -84
  20. package/src/{component-editor → editor/component-editor}/SegmentedControlEditor.svelte +2 -2
  21. package/src/{component-editor → editor/component-editor}/StandardButtonsEditor.svelte +16 -20
  22. package/src/{component-editor → editor/component-editor}/TabBarEditor.svelte +9 -14
  23. package/src/{component-editor → editor/component-editor}/TableEditor.svelte +9 -18
  24. package/src/{component-editor → editor/component-editor}/TooltipEditor.svelte +11 -47
  25. package/src/{component-editor → editor/component-editor}/registry.ts +28 -18
  26. package/src/{component-editor → editor/component-editor}/scaffolding/AngleDial.svelte +2 -2
  27. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentEditorBase.svelte +3 -51
  28. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileManager.svelte +144 -416
  29. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileMenu.svelte +18 -170
  30. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentsTab.svelte +2 -2
  31. package/src/{component-editor → editor/component-editor}/scaffolding/CopyFromMenu.svelte +44 -4
  32. package/src/{component-editor → editor/component-editor}/scaffolding/DividerEditor.svelte +1 -1
  33. package/src/{component-editor → editor/component-editor}/scaffolding/FieldsetWrapper.svelte +1 -1
  34. package/src/{component-editor → editor/component-editor}/scaffolding/GradientCard.svelte +6 -6
  35. package/src/{component-editor → editor/component-editor}/scaffolding/LinkageChart.svelte +6 -6
  36. package/src/{component-editor → editor/component-editor}/scaffolding/LinkedBlock.svelte +6 -11
  37. package/src/editor/component-editor/scaffolding/NonStylableConfig.svelte +38 -0
  38. package/src/{component-editor → editor/component-editor}/scaffolding/SaveAsDialog.svelte +66 -12
  39. package/src/editor/component-editor/scaffolding/ShadowBackdrop.svelte +72 -0
  40. package/src/editor/component-editor/scaffolding/ShadowBackdropControls.svelte +132 -0
  41. package/src/editor/component-editor/scaffolding/StateBlock.svelte +257 -0
  42. package/src/{component-editor → editor/component-editor}/scaffolding/TokenLayout.svelte +9 -7
  43. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +644 -0
  44. package/src/{component-editor → editor/component-editor}/scaffolding/editorContext.ts +19 -9
  45. package/src/{component-editor → editor/component-editor}/scaffolding/linkedBlock.ts +2 -2
  46. package/src/{component-editor → editor/component-editor}/scaffolding/types.ts +14 -0
  47. package/src/{lib → editor/core/components}/componentConfigService.ts +2 -2
  48. package/src/{lib → editor/core/components}/componentPersist.ts +5 -5
  49. package/src/editor/core/flashStatus.ts +30 -0
  50. package/src/{lib → editor/core/fonts}/fontLoader.ts +2 -2
  51. package/src/{lib → editor/core/fonts}/fontMigration.ts +4 -4
  52. package/src/{lib → editor/core/fonts}/fontParse.ts +1 -1
  53. package/src/editor/core/manifests/manifestService.ts +116 -0
  54. package/src/{lib → editor/core/palettes}/paletteDerivation.ts +2 -2
  55. package/src/{lib → editor/core/palettes}/tokenRegistry.ts +5 -5
  56. package/src/editor/core/productionPulse.ts +37 -0
  57. package/src/{lib → editor/core/routing}/router.ts +1 -1
  58. package/src/{lib/files/versionedFileResource.ts → editor/core/storage/files/versionedFileResourceClient.ts} +8 -1
  59. package/src/{lib → editor/core/store}/editorCore.ts +24 -8
  60. package/src/{lib → editor/core/store}/editorPersistence.ts +3 -3
  61. package/src/{lib → editor/core/store}/editorRenderer.ts +2 -2
  62. package/src/{lib → editor/core/store}/editorStore.ts +17 -17
  63. package/src/{lib → editor/core/store}/editorTypes.ts +1 -1
  64. package/src/{lib → editor/core/themes}/slices/columns.ts +2 -2
  65. package/src/{lib → editor/core/themes}/slices/components.ts +2 -2
  66. package/src/{lib → editor/core/themes}/slices/fonts.ts +1 -1
  67. package/src/{lib → editor/core/themes}/slices/gradients.ts +2 -2
  68. package/src/{lib → editor/core/themes}/slices/overlays.ts +1 -1
  69. package/src/{lib → editor/core/themes}/slices/palettes.ts +1 -1
  70. package/src/{lib → editor/core/themes}/slices/shadows.ts +3 -3
  71. package/src/{lib → editor/core/themes}/themeInit.ts +6 -6
  72. package/src/{lib → editor/core/themes}/themeService.ts +6 -6
  73. package/src/{lib → editor/core/themes}/themeTypes.ts +11 -7
  74. package/src/editor/index.ts +69 -0
  75. package/src/{lib → editor/overlay}/LiveEditorOverlay.svelte +79 -125
  76. package/src/{lib → editor/overlay}/columnsOverlay.ts +2 -2
  77. package/src/{pages → editor/pages}/ComponentEditorPage.svelte +12 -12
  78. package/src/{pages → editor/pages}/Editor.svelte +4 -4
  79. package/src/{pages → editor/pages}/EditorShell.svelte +18 -36
  80. package/src/{styles → editor/styles}/ui-editor.css +41 -21
  81. package/src/{styles → editor/styles}/ui-form-controls.css +8 -8
  82. package/src/{ui → editor/ui}/BezierCurveEditor.svelte +8 -8
  83. package/src/{ui → editor/ui}/ColorEditPanel.svelte +13 -13
  84. package/src/{ui → editor/ui}/EditorViewSwitcher.svelte +8 -6
  85. package/src/editor/ui/FileLoadList.svelte +350 -0
  86. package/src/editor/ui/FilePill.svelte +80 -0
  87. package/src/{ui → editor/ui}/FontStackEditor.svelte +7 -7
  88. package/src/{ui → editor/ui}/GradientEditor.svelte +11 -11
  89. package/src/{ui → editor/ui}/GradientStopPicker.svelte +1 -1
  90. package/src/editor/ui/ManifestFileManager.svelte +371 -0
  91. package/src/{ui → editor/ui}/PaletteEditor.svelte +132 -598
  92. package/src/{ui → editor/ui}/ProjectFontsSection.svelte +102 -144
  93. package/src/{ui → editor/ui}/SurfacesTab.svelte +3 -3
  94. package/src/{ui → editor/ui}/TextTab.svelte +3 -3
  95. package/src/{ui → editor/ui}/ThemeFileManager.svelte +286 -519
  96. package/src/{ui → editor/ui}/UICopyPopover.svelte +4 -4
  97. package/src/{ui → editor/ui}/UIFontFamilySelector.svelte +6 -6
  98. package/src/{ui → editor/ui}/UIFontSizeSelector.svelte +1 -1
  99. package/src/editor/ui/UIInfoPopover.svelte +244 -0
  100. package/src/{ui → editor/ui}/UILineHeightSelector.svelte +5 -5
  101. package/src/{ui → editor/ui}/UILinkToggle.svelte +2 -2
  102. package/src/{ui → editor/ui}/UIPaddingSelector.svelte +6 -6
  103. package/src/{ui → editor/ui}/UIPaletteSelector.svelte +26 -26
  104. package/src/editor/ui/UIPillButton.svelte +138 -0
  105. package/src/{ui → editor/ui}/UIRadio.svelte +2 -2
  106. package/src/{ui → editor/ui}/UIRelinkConfirmPopover.svelte +4 -4
  107. package/src/editor/ui/UISquareButton.svelte +172 -0
  108. package/src/{ui → editor/ui}/UITokenSelector.svelte +10 -10
  109. package/src/{ui → editor/ui}/UIVariantSelector.svelte +1 -1
  110. package/src/{ui → editor/ui}/VariablesTab.svelte +31 -8
  111. package/src/{ui → editor/ui}/palette/GradientStopEditor.svelte +13 -13
  112. package/src/{ui → editor/ui}/palette/OverridesPanel.svelte +13 -13
  113. package/src/{ui → editor/ui}/palette/PaletteBase.svelte +8 -5
  114. package/src/{ui → editor/ui}/palette/paletteEditorState.ts +1 -1
  115. package/src/editor/ui/palette/paletteMath.ts +275 -0
  116. package/src/{ui → editor/ui}/sections/ColumnsSection.svelte +137 -17
  117. package/src/{ui → editor/ui}/sections/GradientsSection.svelte +7 -7
  118. package/src/{ui → editor/ui}/sections/OverlaysSection.svelte +17 -17
  119. package/src/{ui → editor/ui}/sections/ShadowsSection.svelte +22 -22
  120. package/src/{ui → editor/ui}/sections/TokenScaleTable.svelte +3 -3
  121. package/src/{components → system/components}/Badge.svelte +0 -36
  122. package/src/{components → system/components}/Card.svelte +8 -62
  123. package/src/{components → system/components}/CornerBadge.svelte +8 -24
  124. package/src/{components → system/components}/Dialog.svelte +1 -1
  125. package/src/system/components/FloatingTokenTags.css +256 -0
  126. package/src/system/components/FloatingTokenTags.svelte +592 -0
  127. package/src/{components → system/components}/InlineEditActions.svelte +6 -4
  128. package/src/system/components/MenuSelect.svelte +229 -0
  129. package/src/{components → system/components}/ProgressBar.svelte +29 -11
  130. package/src/{components → system/components}/SegmentedControl.svelte +49 -43
  131. package/src/{components → system/components}/TabBar.svelte +81 -65
  132. package/src/{components → system/components}/Table.svelte +17 -3
  133. package/src/{components → system/components}/Tooltip.svelte +6 -4
  134. package/src/system/styles/CONVENTIONS.md +178 -0
  135. package/src/{styles → system/styles}/fonts.css +6 -3
  136. package/src/{styles → system/styles}/tokens.css +149 -29
  137. package/src/component-editor/ImageEditor.svelte +0 -74
  138. package/src/component-editor/scaffolding/NonStylableConfig.svelte +0 -62
  139. package/src/component-editor/scaffolding/ShadowBackdrop.svelte +0 -37
  140. package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +0 -61
  141. package/src/component-editor/scaffolding/StateBlock.svelte +0 -132
  142. package/src/component-editor/scaffolding/VariantGroup.svelte +0 -310
  143. package/src/data/google-fonts.json +0 -75
  144. package/src/lib/index.ts +0 -68
  145. package/src/lib/presetService.ts +0 -214
  146. package/src/lib/productionPulse.ts +0 -32
  147. package/src/ui/PresetFileManager.svelte +0 -1116
  148. package/src/ui/UnsavedComponentsDialog.svelte +0 -315
  149. /package/src/{styles → app}/site.css +0 -0
  150. /package/src/{component-editor → editor/component-editor}/index.ts +0 -0
  151. /package/src/{component-editor → editor/component-editor}/scaffolding/DemoHeader.svelte +0 -0
  152. /package/src/{component-editor → editor/component-editor}/scaffolding/TypeEditor.svelte +0 -0
  153. /package/src/{component-editor → editor/component-editor}/scaffolding/buildTypeGroupTokens.ts +0 -0
  154. /package/src/{component-editor → editor/component-editor}/scaffolding/componentSectionType.ts +0 -0
  155. /package/src/{component-editor → editor/component-editor}/scaffolding/componentSources.ts +0 -0
  156. /package/src/{component-editor → editor/component-editor}/scaffolding/defaultSections.ts +0 -0
  157. /package/src/{component-editor → editor/component-editor}/scaffolding/siblings.ts +0 -0
  158. /package/src/{lib → editor/core/components}/componentConfigKeys.ts +0 -0
  159. /package/src/{lib → editor/core}/cssVarSync.ts +0 -0
  160. /package/src/{lib → editor/core/palettes}/oklch.ts +0 -0
  161. /package/src/{lib → editor/core/routing}/navLinkTypes.ts +0 -0
  162. /package/src/{lib → editor/core/routing}/parentRouteStore.ts +0 -0
  163. /package/src/{lib → editor/core/storage}/storage.ts +0 -0
  164. /package/src/{lib → editor/core/store}/editorConfig.ts +0 -0
  165. /package/src/{lib → editor/core/store}/editorConfigStore.ts +0 -0
  166. /package/src/{lib → editor/core/store}/editorKeybindings.ts +0 -0
  167. /package/src/{lib → editor/core/store}/editorViewStore.ts +0 -0
  168. /package/src/{lib → editor/core/themes}/migrations/2026-04-24-component-prefix-and-suffix-renames.ts +0 -0
  169. /package/src/{lib → editor/core/themes}/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +0 -0
  170. /package/src/{lib → editor/core/themes}/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts +0 -0
  171. /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts +0 -0
  172. /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-variant-namespace.ts +0 -0
  173. /package/src/{lib → editor/core/themes}/migrations/2026-05-10-sectiondivider-gradient-stops.ts +0 -0
  174. /package/src/{lib → editor/core/themes}/migrations/2026-05-13-primary-to-brand.ts +0 -0
  175. /package/src/{lib → editor/core/themes}/migrations/index.ts +0 -0
  176. /package/src/{lib → editor/core/themes}/parsers/globalRootBlock.ts +0 -0
  177. /package/src/{lib → editor/core/themes}/slices/domainVars.ts +0 -0
  178. /package/src/{lib → editor/overlay}/ColumnsOverlay.svelte +0 -0
  179. /package/src/{lib → editor/overlay}/overlayState.ts +0 -0
  180. /package/src/{pages → editor/pages}/ComponentEditorPage.svelte.d.ts +0 -0
  181. /package/src/{pages → editor/pages}/Editor.svelte.d.ts +0 -0
  182. /package/src/{ui → editor/ui}/Toggle.svelte +0 -0
  183. /package/src/{ui → editor/ui}/UIDialog.svelte +0 -0
  184. /package/src/{ui → editor/ui}/UIFontWeightSelector.svelte +0 -0
  185. /package/src/{ui → editor/ui}/UIOptionItem.svelte +0 -0
  186. /package/src/{ui → editor/ui}/UIOptionList.svelte +0 -0
  187. /package/src/{ui → editor/ui}/UIRadioGroup.svelte +0 -0
  188. /package/src/{lib → editor/ui}/copyPopover.ts +0 -0
  189. /package/src/{ui → editor/ui}/curveEngine.ts +0 -0
  190. /package/src/{ui → editor/ui}/index.ts +0 -0
  191. /package/src/{ui → editor/ui}/keepInViewport.ts +0 -0
  192. /package/src/{ui → editor/ui}/palette/ScaleCurveEditor.svelte +0 -0
  193. /package/src/{lib → editor/ui}/scrollSection.ts +0 -0
  194. /package/src/{ui → editor/ui}/sections/tokenScales.ts +0 -0
  195. /package/src/{ui → editor/ui}/variantScales.ts +0 -0
  196. /package/src/{assets → system/assets}/newspaper.webp +0 -0
  197. /package/src/{assets → system/assets}/offering.webp +0 -0
  198. /package/src/{components → system/components}/Button.svelte +0 -0
  199. /package/src/{components → system/components}/Callout.svelte +0 -0
  200. /package/src/{components → system/components}/CollapsibleSection.svelte +0 -0
  201. /package/src/{components → system/components}/Image.svelte +0 -0
  202. /package/src/{components → system/components}/Notification.svelte +0 -0
  203. /package/src/{components → system/components}/RadioButton.svelte +0 -0
  204. /package/src/{components → system/components}/SectionDivider.svelte +0 -0
  205. /package/src/{components → system/components}/types.ts +0 -0
  206. /package/src/{styles → system/styles}/_padding.scss +0 -0
  207. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin-ext.woff2 +0 -0
  208. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin.woff2 +0 -0
  209. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin-ext.woff2 +0 -0
  210. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin.woff2 +0 -0
  211. /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin-ext.woff2 +0 -0
  212. /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin.woff2 +0 -0
package/src/lib/index.ts DELETED
@@ -1,68 +0,0 @@
1
- export { default as LiveEditorOverlay } from './LiveEditorOverlay.svelte';
2
- export type { NavLink } from './navLinkTypes';
3
- export { default as ColumnsOverlay } from './ColumnsOverlay.svelte';
4
-
5
- export { columnsVisible, toggleColumns, init as initColumnsOverlay } from './columnsOverlay';
6
- export { configureEditor, storageKey } from './editorConfig';
7
- export { activeFileName } from './editorConfigStore';
8
- export { init as initRouter, route, navigate } from './router';
9
- export { init as initCssVarSync } from './cssVarSync';
10
- export { init as initEditorStore } from './editorStore';
11
-
12
- export { setCssVar, removeCssVar } from './cssVarSync';
13
-
14
- export {
15
- listThemes,
16
- loadTheme,
17
- saveTheme,
18
- deleteTheme,
19
- getActiveTheme,
20
- setActiveFile,
21
- getProductionInfo,
22
- setProductionFile,
23
- sanitizeFileName,
24
- } from './themeService';
25
- export type { ProductionInfo } from './themeService';
26
-
27
- export type {
28
- PaletteConfig,
29
- Theme,
30
- ThemeMeta,
31
- GradientStyle,
32
- GradientStop,
33
- FontSource,
34
- FontSourceKind,
35
- FontFamily,
36
- FontStack,
37
- FontStackSlot,
38
- FontStackVariable,
39
- SystemCascadePreset,
40
- GenericFamily,
41
- Preset,
42
- PresetMeta,
43
- } from './themeTypes';
44
-
45
- export {
46
- listPresets,
47
- loadPreset,
48
- savePreset,
49
- deletePreset,
50
- getActivePreset,
51
- setActivePreset,
52
- applyPreset,
53
- captureCurrentAsPreset,
54
- } from './presetService';
55
- export type { ApplyPresetResult } from './presetService';
56
-
57
- export {
58
- applyFontSources,
59
- applyFontStacks,
60
- resolveFontStackValues,
61
- SYSTEM_CASCADES,
62
- } from './fontLoader';
63
- export { migrateThemeFonts, defaultFontSources, defaultFontStacks } from './fontMigration';
64
-
65
- export { hexToOklch, oklchToHex, gamutClamp } from './oklch';
66
- export type { Oklch } from './oklch';
67
-
68
- export { initializeTheme } from './themeInit';
@@ -1,214 +0,0 @@
1
- import type { Preset, PresetMeta, Theme, ComponentConfig } from './themeTypes';
2
- import { versionedFileResource } from './files/versionedFileResource';
3
- import { listComponents } from './componentConfigService';
4
- import { getActiveTheme, getProductionInfo } from './themeService';
5
-
6
- /**
7
- * REST client for preset (bundle) manifest files. Each preset file references
8
- * a theme file basename + a per-component config file basename. Loading a
9
- * preset flips the corresponding `_active.json` pointers via `applyPreset`,
10
- * leaving the underlying theme + component-config files as the source of
11
- * truth.
12
- *
13
- * Mirrors the lifecycle of `themeService.ts` and `componentConfigService.ts`
14
- * but adds one custom route — `PUT /api/presets/:name/apply` — that the
15
- * server uses to atomically validate every reference and flip every pointer
16
- * in one shot.
17
- */
18
-
19
- const presetsResource = versionedFileResource<Preset, PresetMeta, never>({
20
- baseUrl: '/api/presets',
21
- });
22
-
23
- export const listPresets = async (): Promise<PresetMeta[]> => {
24
- const data = await presetsResource.list();
25
- return data.files;
26
- };
27
-
28
- export const loadPreset = (fileName: string): Promise<Preset> =>
29
- presetsResource.load(fileName);
30
- export const savePreset = (fileName: string, data: Preset): Promise<void> =>
31
- presetsResource.save(fileName, data);
32
- export const deletePreset = (fileName: string): Promise<void> =>
33
- presetsResource.remove(fileName);
34
- export const getActivePreset = (): Promise<Preset | null> => presetsResource.getActive();
35
- export const setActivePreset = (fileName: string): Promise<void> =>
36
- presetsResource.setActive(fileName);
37
-
38
- export interface ApplyPresetResult {
39
- ok: boolean;
40
- preset: Preset;
41
- theme: Theme;
42
- componentConfigs: Record<string, ComponentConfig>;
43
- }
44
-
45
- /**
46
- * Server-side atomic apply: validate every referenced file exists, flip the
47
- * theme + each component's `_active.json` pointer, and return the resolved
48
- * theme + component configs in one payload.
49
- *
50
- * The client typically follows this with a full page reload — loading a
51
- * preset is a "blow up the world" action and preserving editor session
52
- * state across that boundary is low value.
53
- */
54
- export async function applyPreset(fileName: string): Promise<ApplyPresetResult> {
55
- const res = await fetch(`/api/presets/${encodeURIComponent(fileName)}/apply`, {
56
- method: 'PUT',
57
- });
58
- if (!res.ok) {
59
- const err = await res.json().catch(() => ({ error: 'Apply failed' }));
60
- throw new Error(err.error || 'Apply failed');
61
- }
62
- return res.json();
63
- }
64
-
65
- /**
66
- * Build a manifest from the *currently active files on disk* (not in-memory
67
- * editor state) and persist it. Dirty editor state isn't a file yet, so it's
68
- * not part of any preset until the user saves it. Callers should warn the
69
- * user via the UI if `$dirty` is true before invoking this.
70
- */
71
- export async function captureCurrentAsPreset(
72
- fileName: string,
73
- displayName: string,
74
- ): Promise<void> {
75
- const activeTheme = await getActiveTheme();
76
- if (!activeTheme || !activeTheme._fileName) {
77
- throw new Error('No active theme on disk to capture');
78
- }
79
- const components = await listComponents();
80
- const componentConfigs: Record<string, string> = {};
81
- for (const c of components) {
82
- componentConfigs[c.name] = c.activeFile || 'default';
83
- }
84
- const now = new Date().toISOString();
85
- const manifest: Preset = {
86
- name: displayName,
87
- createdAt: now,
88
- updatedAt: now,
89
- theme: activeTheme._fileName,
90
- componentConfigs,
91
- };
92
- await savePreset(fileName, manifest);
93
- await setActivePreset(fileName);
94
- }
95
-
96
- // ── Production preset ──────────────────────────────────────────────────────
97
- //
98
- // The production preset is the manifest whose references describe what
99
- // tokens.css + the component overrides block currently encode. A separate
100
- // pointer (`presets/_production.json`) from the active preset lets the editor
101
- // run experiments without disturbing what end users see. Applying a preset to
102
- // production flips every per-artifact `_production.json` pointer to match the
103
- // manifest and re-bakes css.
104
-
105
- export interface PresetProductionInfo {
106
- fileName: string;
107
- name: string;
108
- theme: string;
109
- componentConfigs: Record<string, string>;
110
- updatedAt: string;
111
- }
112
-
113
- export async function getProductionPreset(): Promise<PresetProductionInfo | null> {
114
- try {
115
- const res = await fetch('/api/presets/production');
116
- if (!res.ok) return null;
117
- return res.json();
118
- } catch {
119
- return null;
120
- }
121
- }
122
-
123
- export async function applyPresetToProduction(fileName: string): Promise<PresetProductionInfo> {
124
- const res = await fetch('/api/presets/production', {
125
- method: 'PUT',
126
- headers: { 'Content-Type': 'application/json' },
127
- body: JSON.stringify({ name: fileName }),
128
- });
129
- if (!res.ok) {
130
- const err = await res.json().catch(() => ({ error: 'Apply to production failed' }));
131
- throw new Error(err.error || 'Apply to production failed');
132
- }
133
- return res.json();
134
- }
135
-
136
- /**
137
- * Snapshot whatever each artifact's `_production.json` currently points at
138
- * into a new preset manifest. Recovery path when individual component Adopts
139
- * have drifted production away from the production preset and the user wants
140
- * to preserve that state under a name rather than re-converge to a preset.
141
- *
142
- * Does NOT flip `presets/_production.json` — the new preset's references
143
- * already match production by construction, but tagging it as the production
144
- * preset is a separate UX decision left to the caller.
145
- */
146
- export async function captureProductionAsPreset(
147
- fileName: string,
148
- displayName: string,
149
- ): Promise<void> {
150
- const themeInfo = await getProductionInfo();
151
- const components = await listComponents();
152
- const componentConfigs: Record<string, string> = {};
153
- for (const c of components) {
154
- componentConfigs[c.name] = c.productionFile || 'default';
155
- }
156
- const now = new Date().toISOString();
157
- const manifest: Preset = {
158
- name: displayName,
159
- createdAt: now,
160
- updatedAt: now,
161
- theme: themeInfo.fileName,
162
- componentConfigs,
163
- };
164
- await savePreset(fileName, manifest);
165
- }
166
-
167
- /**
168
- * Three states comparing the active preset against current production:
169
- * - 'in-production' — active preset IS the production preset AND every
170
- * manifest reference matches the per-artifact production pointer.
171
- * - 'editor-only' — the production preset is a different preset; applying
172
- * this one would flip pointers.
173
- * - 'diverged' — this IS the production preset, but per-artifact
174
- * production has drifted (individual component Adopt clicks since the
175
- * last apply). Two recovery paths: re-apply to converge, or capture
176
- * production as a new preset to name the divergence.
177
- */
178
- export type ProductionPresetStatus = 'in-production' | 'editor-only' | 'diverged';
179
-
180
- export interface ProductionComparison {
181
- status: ProductionPresetStatus;
182
- productionPreset: PresetProductionInfo | null;
183
- themeDrift: boolean;
184
- driftedComponents: string[];
185
- }
186
-
187
- export async function compareActiveToProduction(
188
- activePreset: Preset,
189
- ): Promise<ProductionComparison> {
190
- const [productionPreset, themeInfo, components] = await Promise.all([
191
- getProductionPreset(),
192
- getProductionInfo(),
193
- listComponents(),
194
- ]);
195
- const componentProdMap = new Map(components.map((c) => [c.name, c.productionFile]));
196
- const themeDrift = themeInfo.fileName !== activePreset.theme;
197
- const driftedComponents: string[] = [];
198
- for (const [comp, file] of Object.entries(activePreset.componentConfigs)) {
199
- const prod = componentProdMap.get(comp);
200
- if (prod !== file) driftedComponents.push(comp);
201
- }
202
- const manifestMatches = !themeDrift && driftedComponents.length === 0;
203
- const activeFile = activePreset._fileName;
204
- const isActiveProductionPreset =
205
- !!activeFile && !!productionPreset && productionPreset.fileName === activeFile;
206
-
207
- let status: ProductionPresetStatus;
208
- if (!isActiveProductionPreset) {
209
- status = 'editor-only';
210
- } else {
211
- status = manifestMatches ? 'in-production' : 'diverged';
212
- }
213
- return { status, productionPreset, themeDrift, driftedComponents };
214
- }
@@ -1,32 +0,0 @@
1
- import { writable } from 'svelte/store';
2
- import type { ProductionInfo } from './themeService';
3
- import type { ProductionComparison } from './presetService';
4
-
5
- /**
6
- * Monotonic counter that ticks every time a production pointer flips —
7
- * theme production, a component's production, or a preset applied to
8
- * production. UI surfaces that compare against current production state
9
- * (notably `PresetFileManager`) subscribe to this so an Adopt click in a
10
- * sibling manager refreshes their derived status without per-pair wiring.
11
- *
12
- * Bumpers: `ThemeFileManager.handleApplyToProduction`,
13
- * `ComponentFileManager.handleUpdateProduction`,
14
- * `presetService.applyPresetToProduction` (called from `PresetFileManager`).
15
- * Anyone setting `_production.json` should bump.
16
- */
17
- export const productionRevision = writable(0);
18
-
19
- export function bumpProductionRevision(): void {
20
- productionRevision.update((n) => n + 1);
21
- }
22
-
23
- /**
24
- * Cached production-state stores. The Theme and Preset file managers live in
25
- * the sidebar footer, swapping in/out of the DOM as the user toggles between
26
- * the tokens and components views. Keeping the last-known production state in
27
- * module-level Svelte stores means a remount renders the correct Adopt-button
28
- * state on the first frame instead of flashing through "not in sync" while a
29
- * fresh fetch resolves.
30
- */
31
- export const themeProductionInfo = writable<ProductionInfo | null>(null);
32
- export const presetProductionComparison = writable<ProductionComparison | null>(null);