@motion-proto/live-tokens 0.6.1 → 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 +149 -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 +147 -135
  6. package/package.json +26 -41
  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/README.md CHANGED
@@ -33,7 +33,7 @@ export default defineConfig({
33
33
  svelte(),
34
34
  themeFileApi({
35
35
  themesDir: 'themes',
36
- tokensCssPath: 'src/styles/tokens.css',
36
+ tokensCssPath: 'src/system/styles/tokens.css',
37
37
  }),
38
38
  ],
39
39
  optimizeDeps: {
@@ -44,7 +44,7 @@ export default defineConfig({
44
44
 
45
45
  The `themeFileApi` plugin:
46
46
  - Seeds `themes/` with a default theme on first dev-server start.
47
- - Discovers components at `src/components/*.svelte` and seeds `component-configs/{comp}/default.json` from each component's `:global(:root)` block.
47
+ - Discovers components at `src/system/components/*.svelte` and seeds `component-configs/{comp}/default.json` from each component's `:global(:root)` block.
48
48
  - Hosts the `/api/*` routes the editor uses to save and load themes + per-component configs.
49
49
  - Auto-injects `__PROJECT_ROOT__` for the overlay's "Page Source" link.
50
50
 
@@ -61,6 +61,7 @@ import {
61
61
  initEditorStore,
62
62
  } from '@motion-proto/live-tokens';
63
63
  import App from './App.svelte';
64
+ import { mount } from 'svelte';
64
65
 
65
66
  configureEditor({ storagePrefix: 'my-app-' });
66
67
 
@@ -72,7 +73,7 @@ async function boot() {
72
73
  if (import.meta.env.DEV) {
73
74
  await initializeTheme();
74
75
  }
75
- new App({ target: document.getElementById('app')! });
76
+ mount(App, { target: document.getElementById('app')! });
76
77
  }
77
78
 
78
79
  boot();
@@ -95,7 +96,7 @@ boot();
95
96
  { path: '/components', label: 'Components', icon: 'fa-puzzle-piece' },
96
97
  ]}
97
98
  pageSources={{
98
- '/': 'src/pages/Home.svelte',
99
+ '/': 'src/app/Home.svelte',
99
100
  }}
100
101
  />
101
102
  <ColumnsOverlay />
@@ -135,12 +136,12 @@ CSS variables on `:root`.
135
136
  You can use the package's default as a starting point:
136
137
 
137
138
  ```ts
138
- import '@motion-proto/live-tokens/starter/tokens.css';
139
- import '@motion-proto/live-tokens/starter/site.css'; // optional: themed h1/p/a styles
140
- import '@motion-proto/live-tokens/starter/fonts.css'; // optional: Fraunces + Manrope @font-face
139
+ import '@motion-proto/live-tokens/app/tokens.css';
140
+ import '@motion-proto/live-tokens/app/site.css'; // optional: themed h1/p/a styles
141
+ import '@motion-proto/live-tokens/app/fonts.css'; // optional: Fraunces + Manrope @font-face
141
142
  ```
142
143
 
143
- …or copy `node_modules/@motion-proto/live-tokens/src/styles/tokens.css` into
144
+ …or copy `node_modules/@motion-proto/live-tokens/src/system/styles/tokens.css` into
144
145
  your project and edit. The editor will seed `themes/default.json` on first
145
146
  run and you can promote your edits back into the file.
146
147
 
@@ -150,7 +151,7 @@ The minimum a consumer needs after `npm install @motion-proto/live-tokens`:
150
151
 
151
152
  ```ts
152
153
  // src/main.ts
153
- import '@motion-proto/live-tokens/starter/tokens.css';
154
+ import '@motion-proto/live-tokens/app/tokens.css';
154
155
  import { mount } from 'svelte';
155
156
  import App from './App.svelte';
156
157
 
@@ -189,12 +190,12 @@ npm install
189
190
  npm run dev
190
191
  ```
191
192
 
192
- Open http://localhost:5173 and replace `src/pages/Home.svelte` with your content. The rest of the wiring is already done — it's the same code the npm package ships, just with the App-shell scaffolding included.
193
+ Open http://localhost:5173 and replace `src/app/Home.svelte` with your content. The rest of the wiring is already done — it's the same code the npm package ships, just with the App-shell scaffolding included.
193
194
 
194
195
  ## How the editor ships changes to prod
195
196
 
196
197
  1. Edit in `/editor` or `/components`. Saves write to `themes/{name}.json` and `component-configs/{comp}/{name}.json`.
197
- 2. Promote a theme to "production." Its variables are written into `src/styles/tokens.css` and backed up under `src/styles/_backups/`.
198
+ 2. Promote a theme to "production." Its variables are written into `src/system/styles/tokens.css` and backed up under `src/system/styles/_backups/`.
198
199
  3. `npm run build` bundles `tokens.css` as plain CSS. No editor code, no JSON lookups, no dev surfaces ship to prod.
199
200
 
200
201
  ## File ownership — what the plugin writes
@@ -213,8 +214,8 @@ Knowing which files the plugin touches matters when upgrading the package or wor
213
214
  **At dev-time editor actions, these files get rewritten by your explicit save/promote:**
214
215
 
215
216
  - `themes/{name}.json` — every save in the editor.
216
- - `src/styles/tokens.css` — fully regenerated when you save or promote the production theme. **Treat this as a build artifact.** Hand-edits get clobbered next time the production theme is saved; promote a theme instead.
217
- - `src/styles/fonts.css` — same rule: regenerated from the theme's font sources.
217
+ - `src/system/styles/tokens.css` — fully regenerated when you save or promote the production theme. **Treat this as a build artifact.** Hand-edits get clobbered next time the production theme is saved; promote a theme instead.
218
+ - `src/system/styles/fonts.css` — same rule: regenerated from the theme's font sources.
218
219
  - `component-configs/{comp}/{name}.json` — every save of a per-component config.
219
220
 
220
221
  ## Maintainer notes — publishing
@@ -27,18 +27,18 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
- // src/vite-plugin/index.ts
30
+ // vite-plugin/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  themeFileApi: () => themeFileApi
34
34
  });
35
35
  module.exports = __toCommonJS(index_exports);
36
36
 
37
- // src/vite-plugin/themeFileApi.ts
37
+ // vite-plugin/themeFileApi.ts
38
38
  var import_fs2 = __toESM(require("fs"), 1);
39
39
  var import_path2 = __toESM(require("path"), 1);
40
40
 
41
- // src/lib/parsers/globalRootBlock.ts
41
+ // src/editor/core/themes/parsers/globalRootBlock.ts
42
42
  function extractGlobalRootBody(source) {
43
43
  const re = /:global\(:root\)\s*\{([^}]*)\}/g;
44
44
  const bodies = [];
@@ -49,12 +49,12 @@ function extractGlobalRootBody(source) {
49
49
  return bodies.join("\n");
50
50
  }
51
51
 
52
- // src/lib/files/versionedFileResource.ts
52
+ // src/editor/core/storage/files/versionedFileResourceClient.ts
53
53
  function sanitizeFileName(name) {
54
54
  return name.toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9\-_]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "") || "unnamed";
55
55
  }
56
56
 
57
- // src/vite-plugin/files/versionedFileResource.ts
57
+ // vite-plugin/files/versionedFileResourceServer.ts
58
58
  var import_fs = __toESM(require("fs"), 1);
59
59
  var import_path = __toESM(require("path"), 1);
60
60
  function versionedFileResourceServer(opts) {
@@ -114,7 +114,7 @@ function versionedFileResourceServer(opts) {
114
114
  };
115
115
  }
116
116
 
117
- // src/vite-plugin/files/routeTable.ts
117
+ // vite-plugin/files/routeTable.ts
118
118
  async function dispatch(req, res, routes) {
119
119
  const url = req.url || "";
120
120
  const method = req.method || "GET";
@@ -142,15 +142,35 @@ async function dispatch(req, res, routes) {
142
142
  return false;
143
143
  }
144
144
 
145
- // src/vite-plugin/themeFileApi.ts
145
+ // vite-plugin/themeFileApi.ts
146
+ var import_node_url = require("url");
147
+ var import_meta = {};
148
+ var PKG_VERSION = (() => {
149
+ try {
150
+ let dir = import_path2.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
151
+ for (let i = 0; i < 4; i++) {
152
+ const p = import_path2.default.join(dir, "package.json");
153
+ if (import_fs2.default.existsSync(p)) {
154
+ const json = JSON.parse(import_fs2.default.readFileSync(p, "utf-8"));
155
+ if (json?.name === "@motion-proto/live-tokens") return json.version ?? "";
156
+ }
157
+ const up = import_path2.default.dirname(dir);
158
+ if (up === dir) break;
159
+ dir = up;
160
+ }
161
+ } catch {
162
+ }
163
+ return "";
164
+ })();
146
165
  function themeFileApi(opts) {
147
166
  const THEMES_DIR = import_path2.default.resolve(opts.themesDir);
148
167
  const CSS_PATH = import_path2.default.resolve(opts.tokensCssPath);
149
168
  const FONTS_CSS_PATH = opts.fontsCssPath ? import_path2.default.resolve(opts.fontsCssPath) : import_path2.default.join(import_path2.default.dirname(CSS_PATH), "fonts.css");
150
169
  const API_BASE = opts.apiBase ?? "/api";
151
170
  const COMPONENT_CONFIGS_DIR = opts.componentConfigsDir ? import_path2.default.resolve(opts.componentConfigsDir) : import_path2.default.resolve("component-configs");
152
- const COMPONENTS_SRC_DIR = opts.componentsSrcDir ? import_path2.default.resolve(opts.componentsSrcDir) : import_path2.default.resolve("src/components");
153
- const PRESETS_DIR = opts.presetsDir ? import_path2.default.resolve(opts.presetsDir) : import_path2.default.resolve("presets");
171
+ const COMPONENTS_SRC_DIR = opts.componentsSrcDir ? import_path2.default.resolve(opts.componentsSrcDir) : import_path2.default.resolve("src/system/components");
172
+ const MANIFESTS_DIR = opts.manifestsDir ? import_path2.default.resolve(opts.manifestsDir) : import_path2.default.resolve("manifests");
173
+ const LEGACY_PRESETS_DIR = import_path2.default.resolve("presets");
154
174
  const themesResource = versionedFileResourceServer({
155
175
  dir: THEMES_DIR
156
176
  });
@@ -163,7 +183,7 @@ function themeFileApi(opts) {
163
183
  }
164
184
  return r;
165
185
  }
166
- const presetsResource = versionedFileResourceServer({ dir: PRESETS_DIR });
186
+ const manifestsResource = versionedFileResourceServer({ dir: MANIFESTS_DIR });
167
187
  function ensureThemesDir() {
168
188
  themesResource.ensureDir();
169
189
  if (!import_fs2.default.existsSync(import_path2.default.join(THEMES_DIR, "default.json"))) {
@@ -359,25 +379,63 @@ ${newVars}
359
379
  r.ensureMeta();
360
380
  }
361
381
  }
362
- function ensurePresetsDir() {
363
- presetsResource.ensureDir();
364
- const defaultPath = import_path2.default.join(PRESETS_DIR, "default.json");
382
+ function ensureManifestsDir() {
383
+ if (!import_fs2.default.existsSync(MANIFESTS_DIR) && import_fs2.default.existsSync(LEGACY_PRESETS_DIR)) {
384
+ import_fs2.default.renameSync(LEGACY_PRESETS_DIR, MANIFESTS_DIR);
385
+ const legacyProd = import_path2.default.join(MANIFESTS_DIR, "_production.json");
386
+ if (import_fs2.default.existsSync(legacyProd)) import_fs2.default.unlinkSync(legacyProd);
387
+ }
388
+ manifestsResource.ensureDir();
389
+ const defaultPath = import_path2.default.join(MANIFESTS_DIR, "default.json");
365
390
  if (!import_fs2.default.existsSync(defaultPath)) {
366
391
  const componentConfigs = {};
367
392
  for (const comp of listComponentNames()) {
368
393
  componentConfigs[comp] = componentResource(comp).getActiveName();
369
394
  }
370
395
  const now = (/* @__PURE__ */ new Date()).toISOString();
371
- const defaultPreset = {
372
- name: "Default Preset",
396
+ const defaultManifest = {
397
+ name: "Default",
373
398
  createdAt: now,
374
399
  updatedAt: now,
375
400
  theme: themesResource.getActiveName(),
376
401
  componentConfigs
377
402
  };
378
- import_fs2.default.writeFileSync(defaultPath, JSON.stringify(defaultPreset, null, 2));
403
+ import_fs2.default.writeFileSync(defaultPath, JSON.stringify(defaultManifest, null, 2));
404
+ }
405
+ if (!import_fs2.default.existsSync(manifestsResource.activePath)) {
406
+ import_fs2.default.writeFileSync(
407
+ manifestsResource.activePath,
408
+ JSON.stringify({ activeFile: "default" })
409
+ );
410
+ } else {
411
+ const activeName = manifestsResource.getActiveName();
412
+ if (!import_fs2.default.existsSync(manifestsResource.filePath(activeName))) {
413
+ manifestsResource.setActiveName("default");
414
+ }
379
415
  }
380
- presetsResource.ensureMeta();
416
+ const stragglerProd = import_path2.default.join(MANIFESTS_DIR, "_production.json");
417
+ if (import_fs2.default.existsSync(stragglerProd)) import_fs2.default.unlinkSync(stragglerProd);
418
+ }
419
+ function patchActiveManifest(field, comp, fileName) {
420
+ const activeFile = manifestsResource.getActiveName();
421
+ if (activeFile === "default") return false;
422
+ const manifestPath = manifestsResource.filePath(activeFile);
423
+ if (!import_fs2.default.existsSync(manifestPath)) return false;
424
+ let manifest;
425
+ try {
426
+ manifest = JSON.parse(import_fs2.default.readFileSync(manifestPath, "utf-8"));
427
+ } catch {
428
+ return false;
429
+ }
430
+ if (field === "theme") {
431
+ manifest.theme = fileName;
432
+ } else if (field === "component" && comp) {
433
+ manifest.componentConfigs = manifest.componentConfigs ?? {};
434
+ manifest.componentConfigs[comp] = fileName;
435
+ }
436
+ manifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
437
+ import_fs2.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
438
+ return true;
381
439
  }
382
440
  function readComponentConfig(comp, name) {
383
441
  const filePath = componentResource(comp).filePath(name);
@@ -442,16 +500,15 @@ ${COMPONENT_OVERRIDES_END}
442
500
  const THEMES_ACTIVE_ROUTE = `${API_BASE}/themes/active`;
443
501
  const THEMES_PRODUCTION_ROUTE = `${API_BASE}/themes/production`;
444
502
  const COMPONENT_CONFIGS_ROUTE = `${API_BASE}/component-configs`;
445
- const PRESETS_ROUTE = `${API_BASE}/presets`;
446
- const PRESETS_ACTIVE_ROUTE = `${API_BASE}/presets/active`;
447
- const PRESETS_PRODUCTION_ROUTE = `${API_BASE}/presets/production`;
503
+ const MANIFESTS_ROUTE = `${API_BASE}/manifests`;
504
+ const MANIFESTS_ACTIVE_ROUTE = `${API_BASE}/manifests/active`;
448
505
  const THEME_BY_NAME_REGEX = new RegExp(`^${escapedBase}/themes/([a-z0-9\\-_]+)$`);
449
506
  const COMP_LIST_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)$`);
450
507
  const COMP_ACTIVE_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)/active$`);
451
508
  const COMP_PRODUCTION_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)/production$`);
452
509
  const COMP_BY_NAME_REGEX = new RegExp(`^${escapedBase}/component-configs/([a-z0-9\\-_]+)/([a-z0-9\\-_]+)$`);
453
- const PRESET_APPLY_REGEX = new RegExp(`^${escapedBase}/presets/([a-z0-9\\-_]+)/apply$`);
454
- const PRESET_BY_NAME_REGEX = new RegExp(`^${escapedBase}/presets/([a-z0-9\\-_]+)$`);
510
+ const MANIFEST_APPLY_REGEX = new RegExp(`^${escapedBase}/manifests/([a-z0-9\\-_]+)/apply$`);
511
+ const MANIFEST_BY_NAME_REGEX = new RegExp(`^${escapedBase}/manifests/([a-z0-9\\-_]+)$`);
455
512
  async function handleListThemes(_ctx) {
456
513
  const activeFile = themesResource.getActiveName();
457
514
  const files = import_fs2.default.readdirSync(THEMES_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
@@ -510,10 +567,18 @@ ${COMPONENT_OVERRIDES_END}
510
567
  jsonResponse(res, 404, { error: "Theme not found" });
511
568
  return;
512
569
  }
570
+ if (manifestsResource.getActiveName() === "default") {
571
+ jsonResponse(res, 409, {
572
+ error: "Active manifest is protected. Save As first.",
573
+ code: "ACTIVE_IS_PROTECTED"
574
+ });
575
+ return;
576
+ }
513
577
  themesResource.setProductionName(fileName);
514
578
  syncTokensToCss(fileName);
515
579
  syncFontsToCss(fileName);
516
580
  syncComponentsToCss();
581
+ patchActiveManifest("theme", null, fileName);
517
582
  const data = JSON.parse(import_fs2.default.readFileSync(themesResource.filePath(fileName), "utf-8"));
518
583
  jsonResponse(res, 200, {
519
584
  ok: true,
@@ -560,6 +625,13 @@ ${COMPONENT_OVERRIDES_END}
560
625
  jsonResponse(res, 403, { error: "Cannot delete the default theme" });
561
626
  return;
562
627
  }
628
+ if (themesResource.getProductionName() === fileName) {
629
+ jsonResponse(res, 403, {
630
+ error: "Cannot delete the production theme. Adopt a different theme first.",
631
+ code: "PRODUCTION_THEME"
632
+ });
633
+ return;
634
+ }
563
635
  if (import_fs2.default.existsSync(filePath)) {
564
636
  import_fs2.default.unlinkSync(filePath);
565
637
  if (themesResource.getActiveName() === fileName) {
@@ -627,9 +699,17 @@ ${COMPONENT_OVERRIDES_END}
627
699
  jsonResponse(res, 404, { error: "Config not found" });
628
700
  return;
629
701
  }
702
+ if (manifestsResource.getActiveName() === "default") {
703
+ jsonResponse(res, 409, {
704
+ error: "Active manifest is protected. Save As first.",
705
+ code: "ACTIVE_IS_PROTECTED"
706
+ });
707
+ return;
708
+ }
630
709
  r.ensureDir();
631
710
  r.setProductionName(fileName);
632
711
  syncComponentsToCss();
712
+ patchActiveManifest("component", comp, fileName);
633
713
  const cfg = readComponentConfig(comp, fileName);
634
714
  jsonResponse(res, 200, {
635
715
  ok: true,
@@ -719,112 +799,46 @@ ${COMPONENT_OVERRIDES_END}
719
799
  });
720
800
  jsonResponse(res, 200, { component: comp, files, activeFile, productionFile });
721
801
  }
722
- async function handleListPresets({ res }) {
723
- const activeFile = presetsResource.getActiveName();
724
- const files = import_fs2.default.readdirSync(PRESETS_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
725
- const filePath = import_path2.default.join(PRESETS_DIR, f);
802
+ async function handleListManifests({ res }) {
803
+ const activeFile = manifestsResource.getActiveName();
804
+ const files = import_fs2.default.readdirSync(MANIFESTS_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
805
+ const filePath = import_path2.default.join(MANIFESTS_DIR, f);
726
806
  const data = JSON.parse(import_fs2.default.readFileSync(filePath, "utf-8"));
727
807
  const fileName = f.replace(".json", "");
728
808
  return {
729
809
  name: data.name || fileName,
730
810
  fileName,
731
811
  updatedAt: data.updatedAt || "",
732
- isActive: fileName === activeFile
812
+ isActive: fileName === activeFile,
813
+ isProtected: fileName === "default"
733
814
  };
734
815
  });
735
816
  jsonResponse(res, 200, { files, activeFile });
736
817
  }
737
- async function handleGetActivePreset({ res }) {
738
- const activeFile = presetsResource.getActiveName();
739
- const filePath = presetsResource.filePath(activeFile);
818
+ async function handleGetActiveManifest({ res }) {
819
+ const activeFile = manifestsResource.getActiveName();
820
+ const filePath = manifestsResource.filePath(activeFile);
740
821
  if (!import_fs2.default.existsSync(filePath)) {
741
- jsonResponse(res, 404, { error: "Active preset not found" });
822
+ jsonResponse(res, 404, { error: "Active manifest not found" });
742
823
  return;
743
824
  }
744
825
  const data = JSON.parse(import_fs2.default.readFileSync(filePath, "utf-8"));
745
826
  data._fileName = activeFile;
746
827
  jsonResponse(res, 200, data);
747
828
  }
748
- async function handleSetActivePreset({ req, res }) {
829
+ async function handleSetActiveManifest({ req, res }) {
749
830
  const body = JSON.parse(await readBody(req));
750
831
  const fileName = sanitizeFileName(body.name || "default");
751
- if (!import_fs2.default.existsSync(presetsResource.filePath(fileName))) {
752
- jsonResponse(res, 404, { error: "Preset not found" });
832
+ if (!import_fs2.default.existsSync(manifestsResource.filePath(fileName))) {
833
+ jsonResponse(res, 404, { error: "Manifest not found" });
753
834
  return;
754
835
  }
755
- presetsResource.setActiveName(fileName);
836
+ manifestsResource.setActiveName(fileName);
756
837
  jsonResponse(res, 200, { ok: true, activeFile: fileName });
757
838
  }
758
- async function handleGetProductionPreset({ res }) {
759
- const prodFile = presetsResource.getProductionName();
760
- const filePath = presetsResource.filePath(prodFile);
761
- if (!import_fs2.default.existsSync(filePath)) {
762
- jsonResponse(res, 200, {
763
- fileName: prodFile,
764
- name: prodFile,
765
- theme: "default",
766
- componentConfigs: {},
767
- updatedAt: ""
768
- });
769
- return;
770
- }
771
- const data = JSON.parse(import_fs2.default.readFileSync(filePath, "utf-8"));
772
- jsonResponse(res, 200, {
773
- fileName: prodFile,
774
- name: data.name || prodFile,
775
- theme: data.theme || "default",
776
- componentConfigs: data.componentConfigs || {},
777
- updatedAt: data.updatedAt || ""
778
- });
779
- }
780
- async function handleSetProductionPreset({ req, res }) {
781
- const body = JSON.parse(await readBody(req));
782
- const fileName = sanitizeFileName(body.name || "default");
783
- const presetPath = presetsResource.filePath(fileName);
784
- if (!import_fs2.default.existsSync(presetPath)) {
785
- jsonResponse(res, 404, { error: "Preset not found" });
786
- return;
787
- }
788
- const preset = JSON.parse(import_fs2.default.readFileSync(presetPath, "utf-8"));
789
- const themeName = sanitizeFileName(preset.theme || "default");
790
- if (!import_fs2.default.existsSync(themesResource.filePath(themeName))) {
791
- jsonResponse(res, 422, { error: `Preset references missing theme: ${themeName}` });
792
- return;
793
- }
794
- const knownComponents = new Set(listComponentNames());
795
- const componentConfigs = preset.componentConfigs ?? {};
796
- const apply = [];
797
- for (const [comp, configFile] of Object.entries(componentConfigs)) {
798
- if (!knownComponents.has(comp)) continue;
799
- const sanitized = sanitizeFileName(String(configFile) || "default");
800
- if (!import_fs2.default.existsSync(componentResource(comp).filePath(sanitized))) {
801
- jsonResponse(res, 422, {
802
- error: `Preset references missing config: ${comp}/${sanitized}`
803
- });
804
- return;
805
- }
806
- apply.push([comp, sanitized]);
807
- }
808
- themesResource.setProductionName(themeName);
809
- for (const [comp, configFile] of apply) {
810
- componentResource(comp).setProductionName(configFile);
811
- }
812
- presetsResource.setProductionName(fileName);
813
- syncTokensToCss(themeName);
814
- syncFontsToCss(themeName);
815
- syncComponentsToCss();
816
- jsonResponse(res, 200, {
817
- ok: true,
818
- fileName,
819
- name: preset.name || fileName,
820
- theme: themeName,
821
- componentConfigs: Object.fromEntries(apply),
822
- updatedAt: preset.updatedAt || ""
823
- });
824
- }
825
- async function handlePresetByName({ params, req, res }) {
839
+ async function handleManifestByName({ params, req, res }) {
826
840
  const [fileName] = params;
827
- const filePath = presetsResource.filePath(fileName);
841
+ const filePath = manifestsResource.filePath(fileName);
828
842
  if (req.method === "GET") {
829
843
  if (!import_fs2.default.existsSync(filePath)) {
830
844
  jsonResponse(res, 404, { error: "Not found" });
@@ -837,7 +851,7 @@ ${COMPONENT_OVERRIDES_END}
837
851
  }
838
852
  if (req.method === "PUT") {
839
853
  if (fileName === "default") {
840
- jsonResponse(res, 403, { error: "Cannot overwrite the default preset" });
854
+ jsonResponse(res, 403, { error: "Cannot overwrite the default manifest" });
841
855
  return;
842
856
  }
843
857
  const body = JSON.parse(await readBody(req));
@@ -856,35 +870,35 @@ ${COMPONENT_OVERRIDES_END}
856
870
  }
857
871
  if (req.method === "DELETE") {
858
872
  if (fileName === "default") {
859
- jsonResponse(res, 403, { error: "Cannot delete the default preset" });
873
+ jsonResponse(res, 403, { error: "Cannot delete the default manifest" });
860
874
  return;
861
875
  }
862
876
  if (import_fs2.default.existsSync(filePath)) {
863
877
  import_fs2.default.unlinkSync(filePath);
864
- if (presetsResource.getActiveName() === fileName) {
865
- presetsResource.setActiveName("default");
878
+ if (manifestsResource.getActiveName() === fileName) {
879
+ manifestsResource.setActiveName("default");
866
880
  }
867
881
  }
868
882
  jsonResponse(res, 200, { ok: true });
869
883
  return;
870
884
  }
871
885
  }
872
- async function handleApplyPreset({ params, res }) {
886
+ async function handleApplyManifest({ params, res }) {
873
887
  const [fileName] = params;
874
- const presetPath = presetsResource.filePath(fileName);
875
- if (!import_fs2.default.existsSync(presetPath)) {
876
- jsonResponse(res, 404, { error: "Preset not found" });
888
+ const manifestPath = manifestsResource.filePath(fileName);
889
+ if (!import_fs2.default.existsSync(manifestPath)) {
890
+ jsonResponse(res, 404, { error: "Manifest not found" });
877
891
  return;
878
892
  }
879
- const preset = JSON.parse(import_fs2.default.readFileSync(presetPath, "utf-8"));
880
- const themeName = sanitizeFileName(preset.theme || "default");
893
+ const manifest = JSON.parse(import_fs2.default.readFileSync(manifestPath, "utf-8"));
894
+ const themeName = sanitizeFileName(manifest.theme || "default");
881
895
  const themePath = themesResource.filePath(themeName);
882
896
  if (!import_fs2.default.existsSync(themePath)) {
883
- jsonResponse(res, 422, { error: `Preset references missing theme: ${themeName}` });
897
+ jsonResponse(res, 422, { error: `Manifest references missing theme: ${themeName}` });
884
898
  return;
885
899
  }
886
900
  const knownComponents = new Set(listComponentNames());
887
- const componentConfigs = preset.componentConfigs ?? {};
901
+ const componentConfigs = manifest.componentConfigs ?? {};
888
902
  const resolvedConfigs = {};
889
903
  const apply = [];
890
904
  for (const [comp, configFile] of Object.entries(componentConfigs)) {
@@ -894,7 +908,7 @@ ${COMPONENT_OVERRIDES_END}
894
908
  const cfgPath = r.filePath(sanitized);
895
909
  if (!import_fs2.default.existsSync(cfgPath)) {
896
910
  jsonResponse(res, 422, {
897
- error: `Preset references missing config: ${comp}/${sanitized}`
911
+ error: `Manifest references missing config: ${comp}/${sanitized}`
898
912
  });
899
913
  return;
900
914
  }
@@ -915,10 +929,10 @@ ${COMPONENT_OVERRIDES_END}
915
929
  const cfg = readComponentConfig(comp, activeName);
916
930
  if (cfg) resolvedConfigs[comp] = { ...cfg, _fileName: activeName };
917
931
  }
918
- presetsResource.setActiveName(fileName);
932
+ manifestsResource.setActiveName(fileName);
919
933
  jsonResponse(res, 200, {
920
934
  ok: true,
921
- preset: { ...preset, _fileName: fileName },
935
+ manifest: { ...manifest, _fileName: fileName },
922
936
  theme: themeData,
923
937
  componentConfigs: resolvedConfigs
924
938
  });
@@ -956,35 +970,34 @@ ${COMPONENT_OVERRIDES_END}
956
970
  { method: "GET", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
957
971
  { method: "PUT", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
958
972
  { method: "DELETE", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
959
- // Presets — list / active / production are exact strings, must run before regexes
960
- { method: "GET", pattern: PRESETS_ROUTE, handler: handleListPresets },
961
- { method: "GET", pattern: PRESETS_ACTIVE_ROUTE, handler: handleGetActivePreset },
962
- { method: "PUT", pattern: PRESETS_ACTIVE_ROUTE, handler: handleSetActivePreset },
963
- { method: "GET", pattern: PRESETS_PRODUCTION_ROUTE, handler: handleGetProductionPreset },
964
- { method: "PUT", pattern: PRESETS_PRODUCTION_ROUTE, handler: handleSetProductionPreset },
965
- // Presets :name/apply (more specific than :name)
966
- { method: "PUT", pattern: PRESET_APPLY_REGEX, handler: handleApplyPreset },
967
- { method: "POST", pattern: PRESET_APPLY_REGEX, handler: methodNotAllowed },
968
- { method: "GET", pattern: PRESET_APPLY_REGEX, handler: methodNotAllowed },
969
- { method: "DELETE", pattern: PRESET_APPLY_REGEX, handler: methodNotAllowed },
970
- // Presets :name CRUD (broadest preset route, runs last)
971
- { method: "GET", pattern: PRESET_BY_NAME_REGEX, handler: handlePresetByName },
972
- { method: "PUT", pattern: PRESET_BY_NAME_REGEX, handler: handlePresetByName },
973
- { method: "DELETE", pattern: PRESET_BY_NAME_REGEX, handler: handlePresetByName }
973
+ // Manifests — list / active are exact strings, must run before regexes
974
+ { method: "GET", pattern: MANIFESTS_ROUTE, handler: handleListManifests },
975
+ { method: "GET", pattern: MANIFESTS_ACTIVE_ROUTE, handler: handleGetActiveManifest },
976
+ { method: "PUT", pattern: MANIFESTS_ACTIVE_ROUTE, handler: handleSetActiveManifest },
977
+ // Manifests :name/apply (more specific than :name)
978
+ { method: "PUT", pattern: MANIFEST_APPLY_REGEX, handler: handleApplyManifest },
979
+ { method: "POST", pattern: MANIFEST_APPLY_REGEX, handler: methodNotAllowed },
980
+ { method: "GET", pattern: MANIFEST_APPLY_REGEX, handler: methodNotAllowed },
981
+ { method: "DELETE", pattern: MANIFEST_APPLY_REGEX, handler: methodNotAllowed },
982
+ // Manifests :name CRUD (broadest manifest route, runs last)
983
+ { method: "GET", pattern: MANIFEST_BY_NAME_REGEX, handler: handleManifestByName },
984
+ { method: "PUT", pattern: MANIFEST_BY_NAME_REGEX, handler: handleManifestByName },
985
+ { method: "DELETE", pattern: MANIFEST_BY_NAME_REGEX, handler: handleManifestByName }
974
986
  ];
975
987
  return {
976
988
  name: "theme-file-api",
977
989
  config() {
978
990
  return {
979
991
  define: {
980
- __PROJECT_ROOT__: JSON.stringify(process.cwd())
992
+ __PROJECT_ROOT__: JSON.stringify(process.cwd()),
993
+ __APP_VERSION__: JSON.stringify(PKG_VERSION)
981
994
  }
982
995
  };
983
996
  },
984
997
  configureServer(server) {
985
998
  ensureThemesDir();
986
999
  ensureComponentConfigsDir();
987
- ensurePresetsDir();
1000
+ ensureManifestsDir();
988
1001
  server.middlewares.use(async (req, res, next) => {
989
1002
  const handled = await dispatch(req, res, routes);
990
1003
  if (!handled) next();
@@ -7,7 +7,7 @@ interface ThemeFileApiOptions {
7
7
  apiBase?: string;
8
8
  componentConfigsDir?: string;
9
9
  componentsSrcDir?: string;
10
- presetsDir?: string;
10
+ manifestsDir?: string;
11
11
  }
12
12
  declare function themeFileApi(opts: ThemeFileApiOptions): Plugin;
13
13
 
@@ -7,7 +7,7 @@ interface ThemeFileApiOptions {
7
7
  apiBase?: string;
8
8
  componentConfigsDir?: string;
9
9
  componentsSrcDir?: string;
10
- presetsDir?: string;
10
+ manifestsDir?: string;
11
11
  }
12
12
  declare function themeFileApi(opts: ThemeFileApiOptions): Plugin;
13
13