@motion-proto/live-tokens 0.52.1 → 0.53.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 (60) hide show
  1. package/.claude/skills/live-tokens-adjust-shape-space/SKILL.md +7 -1
  2. package/CHANGELOG.md +63 -0
  3. package/bin/adjust.mjs +16 -39
  4. package/bin/generate-theme.mjs +20 -6
  5. package/dist-plugin/adjust/index.cjs +781 -21
  6. package/dist-plugin/adjust/index.d.cts +2 -1
  7. package/dist-plugin/adjust/index.d.ts +2 -1
  8. package/dist-plugin/adjust/index.js +43 -21
  9. package/dist-plugin/{chunk-6OZFXIQI.js → chunk-232GZGQU.js} +207 -12
  10. package/dist-plugin/chunk-NE6N66EE.js +753 -0
  11. package/dist-plugin/{chunk-JIGIIE5P.js → chunk-PB2JTK2H.js} +123 -0
  12. package/dist-plugin/generateColorsAndType/index.cjs +48 -32
  13. package/dist-plugin/generateColorsAndType/index.d.cts +2 -1
  14. package/dist-plugin/generateColorsAndType/index.d.ts +2 -1
  15. package/dist-plugin/generateColorsAndType/index.js +7 -773
  16. package/dist-plugin/{themeTypes-Dky03HL9.d.cts → index-DpTIRZ2H.d.cts} +49 -21
  17. package/dist-plugin/{themeTypes-Dky03HL9.d.ts → index-DpTIRZ2H.d.ts} +49 -21
  18. package/dist-plugin/index.cjs +1159 -85
  19. package/dist-plugin/index.js +102 -80
  20. package/dist-plugin/migrateData/index.cjs +956 -14
  21. package/dist-plugin/migrateData/index.js +10 -3
  22. package/package.json +6 -4
  23. package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +9 -23
  24. package/src/editor/component-editor/scaffolding/LinkedBlock.svelte +8 -8
  25. package/src/editor/core/components/adjustAliases.ts +49 -22
  26. package/src/editor/core/components/aliasKinds.ts +7 -2
  27. package/src/editor/core/components/componentConfigService.ts +1 -1
  28. package/src/editor/core/store/editorStore.ts +7 -197
  29. package/src/editor/core/store/editorTypes.ts +9 -30
  30. package/src/editor/core/themes/lookSummary.ts +3 -25
  31. package/src/editor/core/themes/migrateComponentConfig.ts +205 -0
  32. package/src/editor/core/themes/migrations/2026-05-19-sectiondivider-rich-gradient.ts +1 -1
  33. package/src/editor/core/themes/migrations/2026-05-20-sectiondivider-slim-variants.ts +1 -1
  34. package/src/editor/core/themes/migrations/2026-05-22-sectiondivider-intrinsics-to-css.ts +1 -1
  35. package/src/editor/core/themes/parsers/gradient.ts +211 -0
  36. package/src/editor/core/themes/slices/gradients.ts +5 -58
  37. package/src/editor/core/themes/themeService.ts +22 -9
  38. package/src/editor/core/themes/themeTypes.ts +71 -21
  39. package/src/editor/docs/content/themes-workflow.md +9 -11
  40. package/src/editor/docs/content/where-themes-live.md +2 -2
  41. package/src/editor/docs/content.generated.ts +2 -2
  42. package/src/editor/index.ts +1 -0
  43. package/src/editor/styles/ui-editor.css +5 -2
  44. package/src/editor/ui/PaletteEditor.svelte +30 -15
  45. package/src/editor/ui/ThemePanel.svelte +24 -15
  46. package/src/editor/ui/Toggle.svelte +22 -22
  47. package/src/editor/ui/UIPillButton.svelte +1 -1
  48. package/src/editor/ui/UIReveal.svelte +47 -0
  49. package/src/editor/ui/UISquareButton.svelte +1 -1
  50. package/src/editor/ui/colors/ColorsTab.svelte +4 -5
  51. package/src/editor/ui/palette/OverridesPanel.svelte +4 -3
  52. package/src/editor/ui/palette/PaletteJumpButton.svelte +3 -3
  53. package/src/editor/ui/palette/ScaleCurveEditor.svelte +3 -2
  54. package/src/live-tokens/data/themes/autumn.json +77 -41
  55. package/src/live-tokens/data/themes/halloween.json +53 -52
  56. package/src/live-tokens/data/themes/midnight-study.json +136 -68
  57. package/src/live-tokens/data/themes/ocean.json +77 -41
  58. package/src/live-tokens/data/themes/royal-velvet.json +43 -42
  59. package/src/live-tokens/data/themes/spring-meadow.json +86 -52
  60. package/src/live-tokens/data/themes/sunset.json +101 -40
@@ -171,8 +171,889 @@ function versionedFileResourceServer(opts) {
171
171
  };
172
172
  }
173
173
 
174
+ // src/editor/core/themes/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts
175
+ var LEGACY_KEY_RENAMES = {
176
+ "--empty": "--page-bg",
177
+ "--empty-attachment": "--page-bg-attachment",
178
+ // Orphan exports dropped from tokens.css; no new home — silently discard.
179
+ "--border-neutral": null,
180
+ // Shadow cleanup: these five tokens were removed (low/zero consumers,
181
+ // aesthetic drift). Dialog migrated onto --shadow-2xl; focus rings moved
182
+ // to their own --ring-focus-* namespace, which themes don't carry by
183
+ // default — tokens.css provides the canonical values.
184
+ "--shadow-app": null,
185
+ "--shadow-card": null,
186
+ "--shadow-overlay": null,
187
+ "--shadow-focus": null,
188
+ "--shadow-glow-green": null
189
+ };
190
+ var BG_TO_CANVAS_PREFIXES = ["--color-bg-", "--surface-bg", "--border-bg", "--text-bg"];
191
+ function migrateBgToCanvas(rawVars) {
192
+ for (const oldKey of Object.keys(rawVars)) {
193
+ for (const prefix of BG_TO_CANVAS_PREFIXES) {
194
+ if (!oldKey.startsWith(prefix)) continue;
195
+ const suffix = oldKey.slice(prefix.length);
196
+ if (suffix && !suffix.startsWith("-")) continue;
197
+ const newKey = prefix.replace("-bg", "-canvas") + suffix;
198
+ if (newKey === oldKey) continue;
199
+ const value = rawVars[oldKey];
200
+ delete rawVars[oldKey];
201
+ if (!(newKey in rawVars)) rawVars[newKey] = value;
202
+ break;
203
+ }
204
+ }
205
+ }
206
+ function migrateLegacyKeys(rawVars) {
207
+ for (const [oldKey, newKey] of Object.entries(LEGACY_KEY_RENAMES)) {
208
+ if (!(oldKey in rawVars)) continue;
209
+ const value = rawVars[oldKey];
210
+ delete rawVars[oldKey];
211
+ if (newKey && !(newKey in rawVars)) rawVars[newKey] = value;
212
+ }
213
+ migrateBgToCanvas(rawVars);
214
+ }
215
+ var colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas = {
216
+ id: "2026-04-24-legacy-keys-and-bg-to-canvas",
217
+ fromVersion: 0,
218
+ toVersion: 1,
219
+ appliesTo: "colors-and-type",
220
+ apply(rawVars) {
221
+ const out = { ...rawVars };
222
+ migrateLegacyKeys(out);
223
+ return out;
224
+ }
225
+ };
226
+
227
+ // src/editor/core/themes/migrations/2026-04-24-component-prefix-and-suffix-renames.ts
228
+ var COMPONENT_PREFIX_RENAMES = {
229
+ "--segment-": "--segmentedcontrol-",
230
+ "--collapsible-": "--collapsiblesection-",
231
+ "--progress-": "--progressbar-",
232
+ "--section-divider-": "--sectiondivider-",
233
+ "--radio-": "--radiobutton-",
234
+ "--inline-edit-": "--inlineeditactions-"
235
+ };
236
+ var COMPONENT_SUFFIX_RENAMES = {
237
+ progressbar: [["-track-bg", "-track-surface"]],
238
+ inlineeditactions: [
239
+ ["-bg-hover", "-hover-surface"],
240
+ ["-bg", "-surface"]
241
+ ]
242
+ };
243
+ var componentMigration_2026_04_24_prefixAndSuffixRenames = {
244
+ id: "2026-04-24-component-prefix-and-suffix-renames",
245
+ fromVersion: 0,
246
+ toVersion: 1,
247
+ appliesTo: "component-config",
248
+ apply(rawVars, meta) {
249
+ const component = meta.component ?? "";
250
+ const out = {};
251
+ const suffixRules = COMPONENT_SUFFIX_RENAMES[component] ?? [];
252
+ for (const [oldKey, value] of Object.entries(rawVars)) {
253
+ let key = oldKey;
254
+ if (key === "--detail-nav-bg") key = "--detailnav-surface";
255
+ for (const [oldPrefix, newPrefix] of Object.entries(COMPONENT_PREFIX_RENAMES)) {
256
+ if (key.startsWith(oldPrefix)) {
257
+ key = newPrefix + key.slice(oldPrefix.length);
258
+ break;
259
+ }
260
+ }
261
+ for (const [oldSuffix, newSuffix] of suffixRules) {
262
+ if (key.endsWith(oldSuffix)) {
263
+ key = key.slice(0, -oldSuffix.length) + newSuffix;
264
+ break;
265
+ }
266
+ }
267
+ if (!(key in out)) out[key] = value;
268
+ }
269
+ return out;
270
+ }
271
+ };
272
+
273
+ // src/editor/core/themes/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts
274
+ var OPTION_DISABLED_PREFIX = "--segmentedcontrol-option-disabled-";
275
+ var DISABLED_PREFIX = "--segmentedcontrol-disabled-";
276
+ var SELECTED_DISABLED_PREFIX = "--segmentedcontrol-selected-disabled-";
277
+ var SELECTED_HOVER_PREFIX = "--segmentedcontrol-selected-hover-";
278
+ var componentMigration_2026_04_27_segmentedcontrolDisabledFlatten = {
279
+ id: "2026-04-27-segmentedcontrol-disabled-flatten",
280
+ fromVersion: 1,
281
+ toVersion: 2,
282
+ appliesTo: "component-config",
283
+ apply(rawVars, meta) {
284
+ if (meta.component !== "segmentedcontrol") return { ...rawVars };
285
+ const out = {};
286
+ for (const [oldKey, value] of Object.entries(rawVars)) {
287
+ let key = oldKey;
288
+ if (key.startsWith(SELECTED_DISABLED_PREFIX)) continue;
289
+ if (key.startsWith(SELECTED_HOVER_PREFIX)) continue;
290
+ if (key.startsWith(OPTION_DISABLED_PREFIX)) {
291
+ key = DISABLED_PREFIX + key.slice(OPTION_DISABLED_PREFIX.length);
292
+ }
293
+ if (!(key in out)) out[key] = value;
294
+ }
295
+ return out;
296
+ }
297
+ };
298
+
299
+ // src/editor/core/themes/migrations/2026-05-08-collapsiblesection-variant-namespace.ts
300
+ var PREFIX = "--collapsiblesection-";
301
+ var STATE_NAMES = /* @__PURE__ */ new Set(["default", "hover", "active", "expanded"]);
302
+ var componentMigration_2026_05_08_collapsiblesectionVariantNamespace = {
303
+ id: "2026-05-08-collapsiblesection-variant-namespace",
304
+ fromVersion: 2,
305
+ toVersion: 3,
306
+ appliesTo: "component-config",
307
+ apply(rawVars, meta) {
308
+ if (meta.component !== "collapsiblesection") return { ...rawVars };
309
+ const out = {};
310
+ for (const [oldKey, value] of Object.entries(rawVars)) {
311
+ let key = oldKey;
312
+ if (key.startsWith(PREFIX)) {
313
+ const tail = key.slice(PREFIX.length);
314
+ const firstSegment = tail.split("-", 1)[0];
315
+ if (STATE_NAMES.has(firstSegment)) {
316
+ key = `${PREFIX}container-${tail}`;
317
+ }
318
+ }
319
+ if (!(key in out)) out[key] = value;
320
+ }
321
+ return out;
322
+ }
323
+ };
324
+
325
+ // src/editor/core/themes/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts
326
+ var PFX = "--collapsiblesection-";
327
+ var componentMigration_2026_05_08_collapsiblesectionFrameAndCleanup = {
328
+ id: "2026-05-08-collapsiblesection-frame-and-cleanup",
329
+ fromVersion: 3,
330
+ toVersion: 4,
331
+ appliesTo: "component-config",
332
+ apply(rawVars, meta) {
333
+ if (meta.component !== "collapsiblesection") return { ...rawVars };
334
+ const out = {};
335
+ for (const prop of ["surface", "border", "border-width", "radius"]) {
336
+ const src = `${PFX}container-default-${prop}`;
337
+ if (src in rawVars) {
338
+ out[`${PFX}container-frame-${prop}`] = rawVars[src];
339
+ }
340
+ }
341
+ for (const [key, value] of Object.entries(rawVars)) {
342
+ if (/^--collapsiblesection-chromeless-(default|hover|active)-(border|border-width|radius)$/.test(key)) continue;
343
+ if (/^--collapsiblesection-container-(hover|active)-(border|border-width|radius)$/.test(key)) continue;
344
+ if (/^--collapsiblesection-container-default-(border|border-width|radius)$/.test(key)) continue;
345
+ if (/^--collapsiblesection-divider-(default|hover|active)-radius$/.test(key)) continue;
346
+ if (/^--collapsiblesection-(chromeless|divider|container)-expanded-(border|border-width|radius)$/.test(key)) continue;
347
+ if (/^--collapsiblesection-(chromeless|divider)-expanded-surface$/.test(key)) continue;
348
+ if (!(key in out)) out[key] = value;
349
+ }
350
+ return out;
351
+ }
352
+ };
353
+
354
+ // src/editor/core/themes/migrations/2026-05-10-sectiondivider-gradient-stops.ts
355
+ var PFX2 = "--sectiondivider-";
356
+ var VARIANTS = ["canvas", "neutral", "alternate", "primary", "accent", "special"];
357
+ var OLD_STOP_RE = /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-gradient-stop-\d+$/;
358
+ var componentMigration_2026_05_10_sectiondividerGradientStops = {
359
+ id: "2026-05-10-sectiondivider-gradient-stops",
360
+ fromVersion: 4,
361
+ toVersion: 5,
362
+ appliesTo: "component-config",
363
+ apply(rawVars, meta) {
364
+ if (meta.component !== "sectiondivider") return { ...rawVars };
365
+ const out = {};
366
+ for (const [key, value] of Object.entries(rawVars)) {
367
+ if (OLD_STOP_RE.test(key)) continue;
368
+ out[key] = value;
369
+ }
370
+ const setIfMissing = (key, fallback) => {
371
+ if (!(key in out)) out[key] = fallback;
372
+ };
373
+ for (const v of VARIANTS) {
374
+ const old1 = rawVars[`${PFX2}${v}-gradient-stop-1`];
375
+ const old2 = rawVars[`${PFX2}${v}-gradient-stop-2`];
376
+ const old4 = rawVars[`${PFX2}${v}-gradient-stop-4`];
377
+ setIfMissing(`${PFX2}${v}-gradient-angle`, "--gradient-angle-diagonal");
378
+ setIfMissing(`${PFX2}${v}-gradient-stop-1-color`, old1 ?? `--surface-${v}-highest`);
379
+ setIfMissing(`${PFX2}${v}-gradient-stop-1-position`, "--gradient-stop-start");
380
+ setIfMissing(`${PFX2}${v}-gradient-stop-2-color`, old2 ?? `--surface-${v}-higher`);
381
+ setIfMissing(`${PFX2}${v}-gradient-stop-2-position`, "--gradient-stop-mid");
382
+ setIfMissing(`${PFX2}${v}-gradient-stop-3-color`, old4 ?? `--surface-${v}`);
383
+ setIfMissing(`${PFX2}${v}-gradient-stop-3-position`, "--gradient-stop-end");
384
+ }
385
+ return out;
386
+ }
387
+ };
388
+
389
+ // src/editor/core/themes/migrations/2026-05-13-primary-to-brand.ts
390
+ var PALETTE_STEPS = ["100", "200", "300", "400", "500", "600", "700", "800", "850", "900", "950"];
391
+ var SURFACE_SUFFIXES = ["lowest", "lower", "low", "high", "higher", "highest"];
392
+ var BORDER_SUFFIXES = ["faint", "subtle", "medium", "strong"];
393
+ var TEXT_SUFFIXES = ["secondary", "tertiary", "muted", "disabled"];
394
+ var RENAME_MAP = (() => {
395
+ const m = {};
396
+ for (const step of PALETTE_STEPS) m[`--color-primary-${step}`] = `--color-brand-${step}`;
397
+ m["--surface-primary"] = "--surface-brand";
398
+ for (const suf of SURFACE_SUFFIXES) m[`--surface-primary-${suf}`] = `--surface-brand-${suf}`;
399
+ m["--border-primary"] = "--border-brand";
400
+ for (const suf of BORDER_SUFFIXES) m[`--border-primary-${suf}`] = `--border-brand-${suf}`;
401
+ m["--text-primary-color"] = "--text-brand";
402
+ for (const suf of TEXT_SUFFIXES) m[`--text-primary-${suf}`] = `--text-brand-${suf}`;
403
+ return m;
404
+ })();
405
+ function renameToken(name) {
406
+ return RENAME_MAP[name] ?? name;
407
+ }
408
+ function renameKeys(rawVars) {
409
+ const out = {};
410
+ for (const [k, v] of Object.entries(rawVars)) {
411
+ out[renameToken(k)] = v;
412
+ }
413
+ return out;
414
+ }
415
+ function renameKeysAndValues(rawVars) {
416
+ const out = {};
417
+ for (const [k, v] of Object.entries(rawVars)) {
418
+ out[renameToken(k)] = renameToken(v);
419
+ }
420
+ return out;
421
+ }
422
+ var colorsAndTypeMigration_2026_05_13_primaryToBrand = {
423
+ id: "2026-05-13-primary-to-brand-theme",
424
+ fromVersion: 1,
425
+ toVersion: 2,
426
+ appliesTo: "colors-and-type",
427
+ apply: renameKeys
428
+ };
429
+ var componentMigration_2026_05_13_primaryToBrand = {
430
+ id: "2026-05-13-primary-to-brand-component",
431
+ fromVersion: 5,
432
+ toVersion: 6,
433
+ appliesTo: "component-config",
434
+ apply: renameKeysAndValues
435
+ };
436
+
437
+ // src/editor/core/themes/migrations/2026-05-19-collapsiblesection-drop-frame-surface.ts
438
+ function dropFrameSurface(rawVars, meta) {
439
+ if (meta.component !== "collapsiblesection") return rawVars;
440
+ const { "--collapsiblesection-container-frame-surface": _drop, ...rest } = rawVars;
441
+ return rest;
442
+ }
443
+ var componentMigration_2026_05_19_collapsiblesectionDropFrameSurface = {
444
+ id: "2026-05-19-collapsiblesection-drop-frame-surface",
445
+ fromVersion: 6,
446
+ toVersion: 7,
447
+ appliesTo: "component-config",
448
+ apply: dropFrameSurface
449
+ };
450
+
451
+ // src/editor/core/themes/migrations/2026-05-19-sectiondivider-rich-gradient.ts
452
+ var FLAT_RE = /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-gradient-(angle|stop-[123]-(color|position))$/;
453
+ var componentMigration_2026_05_19_sectiondividerRichGradient = {
454
+ id: "2026-05-19-sectiondivider-rich-gradient",
455
+ fromVersion: 7,
456
+ toVersion: 8,
457
+ appliesTo: "component-config",
458
+ apply(rawVars, meta) {
459
+ if (meta.component !== "sectiondivider") return { ...rawVars };
460
+ const out = {};
461
+ for (const [key, value] of Object.entries(rawVars)) {
462
+ if (FLAT_RE.test(key)) continue;
463
+ out[key] = value;
464
+ }
465
+ return out;
466
+ }
467
+ };
468
+
469
+ // src/editor/core/themes/migrations/2026-05-20-sectiondivider-slim-variants.ts
470
+ var VARIANTS2 = ["lg", "md", "sm"];
471
+ var SUFFIX_RENAMES = [
472
+ [/-title-border-width$/, "-title-outline-width"],
473
+ [/-title-stroke-color$/, "-title-outline-color"],
474
+ [
475
+ /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-padding$/,
476
+ "--sectiondivider-$1-spacing"
477
+ ]
478
+ ];
479
+ function renameKeySuffix(key) {
480
+ for (const [re, repl] of SUFFIX_RENAMES) {
481
+ if (re.test(key)) return key.replace(re, repl);
482
+ }
483
+ return key;
484
+ }
485
+ function splitFamilyKey(key) {
486
+ const m = key.match(/^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-(.+)$/);
487
+ if (!m) return null;
488
+ return { family: m[1], suffix: m[2] };
489
+ }
490
+ var componentMigration_2026_05_20_sectiondividerSlimVariants = {
491
+ id: "2026-05-20-sectiondivider-slim-variants",
492
+ fromVersion: 8,
493
+ toVersion: 9,
494
+ appliesTo: "component-config",
495
+ apply(rawVars, meta) {
496
+ if (meta.component !== "sectiondivider") return { ...rawVars };
497
+ const out = {};
498
+ const canvasValues = {};
499
+ for (const [rawKey, value] of Object.entries(rawVars)) {
500
+ const key = renameKeySuffix(rawKey);
501
+ const parts = splitFamilyKey(key);
502
+ if (!parts) {
503
+ out[key] = value;
504
+ continue;
505
+ }
506
+ if (parts.family !== "canvas") continue;
507
+ canvasValues[parts.suffix] = value;
508
+ }
509
+ for (const suffix of Object.keys(canvasValues)) {
510
+ for (const v of VARIANTS2) {
511
+ out[`--sectiondivider-${v}-${suffix}`] = canvasValues[suffix];
512
+ }
513
+ }
514
+ return out;
515
+ }
516
+ };
517
+
518
+ // src/editor/core/themes/migrations/2026-05-21-sectiondivider-spacing-to-padding.ts
519
+ var componentMigration_2026_05_21_sectiondividerSpacingToPadding = {
520
+ id: "2026-05-21-sectiondivider-spacing-to-padding",
521
+ fromVersion: 9,
522
+ toVersion: 10,
523
+ appliesTo: "component-config",
524
+ apply(rawVars, meta) {
525
+ if (meta.component !== "sectiondivider") return { ...rawVars };
526
+ const out = {};
527
+ for (const [key, value] of Object.entries(rawVars)) {
528
+ const renamed = key.replace(
529
+ /^--sectiondivider-(lg|md|sm)-spacing$/,
530
+ "--sectiondivider-$1-padding"
531
+ );
532
+ out[renamed] = value;
533
+ }
534
+ return out;
535
+ }
536
+ };
537
+
538
+ // src/editor/core/themes/migrations/2026-05-22-sectiondivider-intrinsics-to-css.ts
539
+ var componentMigration_2026_05_22_sectiondividerIntrinsicsToCss = {
540
+ id: "2026-05-22-sectiondivider-intrinsics-to-css",
541
+ fromVersion: 10,
542
+ toVersion: 11,
543
+ appliesTo: "component-config",
544
+ apply(rawVars, meta) {
545
+ if (meta.component !== "sectiondivider") return { ...rawVars };
546
+ const VARIANTS4 = ["lg", "md", "sm"];
547
+ const prefix = "--sectiondivider-";
548
+ const dropped = /* @__PURE__ */ new Set();
549
+ for (const v of VARIANTS4) {
550
+ dropped.add(`${prefix}${v}-show-eyebrow`);
551
+ dropped.add(`${prefix}${v}-show-description`);
552
+ dropped.add(`${prefix}${v}-show-hairline`);
553
+ dropped.add(`${prefix}${v}-hairline`);
554
+ dropped.add(`${prefix}${v}-eyebrow-uppercase`);
555
+ }
556
+ const out = {};
557
+ for (const [key, value] of Object.entries(rawVars)) {
558
+ if (dropped.has(key)) continue;
559
+ out[key] = value;
560
+ }
561
+ for (const v of VARIANTS4) {
562
+ const showEyebrow = rawVars[`${prefix}${v}-show-eyebrow`];
563
+ if (showEyebrow !== void 0) {
564
+ out[`${prefix}${v}-eyebrow-display`] = showEyebrow === "1" ? "block" : "none";
565
+ }
566
+ const showDesc = rawVars[`${prefix}${v}-show-description`];
567
+ if (showDesc !== void 0) {
568
+ out[`${prefix}${v}-description-display`] = showDesc === "1" ? "flex" : "none";
569
+ }
570
+ const showHair = rawVars[`${prefix}${v}-show-hairline`];
571
+ const oldHair = rawVars[`${prefix}${v}-hairline`];
572
+ const oldHairIsPos = typeof oldHair === "string" && oldHair !== "" && oldHair !== "off";
573
+ let newHair;
574
+ if (showHair === "") newHair = "none";
575
+ else if (showHair === "1") newHair = oldHairIsPos ? oldHair : "above-label";
576
+ else if (oldHair !== void 0) newHair = oldHairIsPos ? oldHair : "none";
577
+ if (newHair !== void 0) {
578
+ out[`${prefix}${v}-hairline`] = newHair;
579
+ }
580
+ const upper = rawVars[`${prefix}${v}-eyebrow-uppercase`];
581
+ if (upper !== void 0) {
582
+ out[`${prefix}${v}-eyebrow-text-transform`] = upper === "1" ? "uppercase" : "none";
583
+ }
584
+ }
585
+ return out;
586
+ }
587
+ };
588
+
589
+ // src/editor/core/themes/migrations/2026-05-24-segmentedcontrol-divider-inset.ts
590
+ var componentMigration_2026_05_24_segmentedcontrolDividerInset = {
591
+ id: "2026-05-24-segmentedcontrol-divider-inset",
592
+ fromVersion: 11,
593
+ toVersion: 12,
594
+ appliesTo: "component-config",
595
+ apply(rawVars, meta) {
596
+ if (meta.component !== "segmentedcontrol") return { ...rawVars };
597
+ const out = {};
598
+ for (const [key, value] of Object.entries(rawVars)) {
599
+ if (key === "--segmentedcontrol-divider-height") continue;
600
+ out[key] = value;
601
+ }
602
+ return out;
603
+ }
604
+ };
605
+
606
+ // src/editor/core/themes/migrations/2026-05-24-promote-state-shared-tokens.ts
607
+ var BUTTON_VARIANTS = ["primary", "secondary", "outline", "success", "danger", "warning"];
608
+ var BUTTON_STATES = ["hover", "disabled"];
609
+ var BUTTON_PROPS = ["padding", "radius", "border-width"];
610
+ var buttonDeadKeys = new Set(
611
+ BUTTON_VARIANTS.flatMap(
612
+ (v) => BUTTON_STATES.flatMap(
613
+ (s) => BUTTON_PROPS.map((p) => `--button-${v}-${s}-${p}`)
614
+ )
615
+ )
616
+ );
617
+ var segmentedcontrolDeadKeys = /* @__PURE__ */ new Set([
618
+ "--segmentedcontrol-selected-icon-size",
619
+ "--segmentedcontrol-option-hover-icon-size",
620
+ "--segmentedcontrol-disabled-icon-size"
621
+ ]);
622
+ var componentMigration_2026_05_24_promoteStateSharedTokens = {
623
+ id: "2026-05-24-promote-state-shared-tokens",
624
+ fromVersion: 12,
625
+ toVersion: 13,
626
+ appliesTo: "component-config",
627
+ apply(rawVars, meta) {
628
+ const dead = meta.component === "button" ? buttonDeadKeys : meta.component === "segmentedcontrol" ? segmentedcontrolDeadKeys : null;
629
+ if (!dead) return { ...rawVars };
630
+ const out = {};
631
+ for (const [key, value] of Object.entries(rawVars)) {
632
+ if (dead.has(key)) continue;
633
+ out[key] = value;
634
+ }
635
+ return out;
636
+ }
637
+ };
638
+
639
+ // src/editor/core/themes/migrations/2026-05-24-progressbar-collapse-variants.ts
640
+ var PRIMARY_PREFIX = "--progressbar-primary-";
641
+ var NEW_PREFIX = "--progressbar-";
642
+ var DROP_PREFIXES = [
643
+ "--progressbar-success-",
644
+ "--progressbar-warning-",
645
+ "--progressbar-danger-",
646
+ "--progressbar-info-"
647
+ ];
648
+ var componentMigration_2026_05_24_progressbarCollapseVariants = {
649
+ id: "2026-05-24-progressbar-collapse-variants",
650
+ fromVersion: 13,
651
+ toVersion: 14,
652
+ appliesTo: "component-config",
653
+ apply(rawVars, meta) {
654
+ if (meta.component !== "progressbar") return { ...rawVars };
655
+ const out = {};
656
+ for (const [oldKey, value] of Object.entries(rawVars)) {
657
+ if (DROP_PREFIXES.some((p) => oldKey.startsWith(p))) continue;
658
+ const key = oldKey.startsWith(PRIMARY_PREFIX) ? NEW_PREFIX + oldKey.slice(PRIMARY_PREFIX.length) : oldKey;
659
+ if (!(key in out)) out[key] = value;
660
+ }
661
+ return out;
662
+ }
663
+ };
664
+
665
+ // src/editor/core/themes/migrations/2026-05-24-collapsiblesection-drop-active-state.ts
666
+ function dropActiveState(rawVars, meta) {
667
+ if (meta.component !== "collapsiblesection") return rawVars;
668
+ const re = /^--collapsiblesection-(chromeless|divider|container)-active-/;
669
+ const out = {};
670
+ for (const [key, value] of Object.entries(rawVars)) {
671
+ if (re.test(key)) continue;
672
+ out[key] = value;
673
+ }
674
+ return out;
675
+ }
676
+ var componentMigration_2026_05_24_collapsiblesectionDropActiveState = {
677
+ id: "2026-05-24-collapsiblesection-drop-active-state",
678
+ fromVersion: 14,
679
+ toVersion: 15,
680
+ appliesTo: "component-config",
681
+ apply: dropActiveState
682
+ };
683
+
684
+ // src/editor/core/themes/migrations/2026-05-25-cornerbadge-flatten-variants.ts
685
+ var VARIANTS3 = ["primary", "accent", "neutral", "alternate", "canvas", "special", "success", "warning", "danger", "info"];
686
+ var RE = new RegExp(`^--corner-badge-(${VARIANTS3.join("|")})-(.+)$`);
687
+ var CURRENT_COLOR_PROPS = /* @__PURE__ */ new Set(["surface", "border", "text"]);
688
+ function flattenVariants(rawVars, meta) {
689
+ if (meta.component !== "cornerbadge") return rawVars;
690
+ const out = {};
691
+ const collected = /* @__PURE__ */ new Map();
692
+ for (const [key, value] of Object.entries(rawVars)) {
693
+ const m = key.match(RE);
694
+ if (m) {
695
+ const prop = m[2];
696
+ if (CURRENT_COLOR_PROPS.has(prop)) {
697
+ out[key] = value;
698
+ continue;
699
+ }
700
+ if (!collected.has(prop)) collected.set(prop, value);
701
+ continue;
702
+ }
703
+ out[key] = value;
704
+ }
705
+ for (const [prop, value] of collected) {
706
+ const flatKey = `--corner-badge-${prop}`;
707
+ if (!(flatKey in out)) out[flatKey] = value;
708
+ }
709
+ return out;
710
+ }
711
+ var componentMigration_2026_05_25_cornerbadgeFlattenVariants = {
712
+ id: "2026-05-25-cornerbadge-flatten-variants",
713
+ fromVersion: 15,
714
+ toVersion: 16,
715
+ appliesTo: "component-config",
716
+ apply: flattenVariants
717
+ };
718
+
719
+ // src/editor/core/themes/migrations/2026-05-26-drop-overlay-extra-stops.ts
720
+ var DROPPED_TO_KEPT = {
721
+ "--overlay-lowest": "--overlay-low",
722
+ "--overlay-lower": "--overlay-low",
723
+ "--overlay-higher": "--overlay-high",
724
+ "--overlay-highest": "--overlay-high"
725
+ };
726
+ var colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops = {
727
+ id: "2026-05-26-drop-overlay-extra-stops-theme",
728
+ fromVersion: 2,
729
+ toVersion: 3,
730
+ appliesTo: "colors-and-type",
731
+ apply(rawVars) {
732
+ const out = {};
733
+ for (const [key, value] of Object.entries(rawVars)) {
734
+ if (key in DROPPED_TO_KEPT) continue;
735
+ out[key] = value;
736
+ }
737
+ return out;
738
+ }
739
+ };
740
+ var componentMigration_2026_05_26_dropOverlayExtraStops = {
741
+ id: "2026-05-26-drop-overlay-extra-stops-component",
742
+ fromVersion: 16,
743
+ toVersion: 17,
744
+ appliesTo: "component-config",
745
+ apply(rawVars) {
746
+ const out = {};
747
+ for (const [key, value] of Object.entries(rawVars)) {
748
+ out[key] = DROPPED_TO_KEPT[value] ?? value;
749
+ }
750
+ return out;
751
+ }
752
+ };
753
+
754
+ // src/editor/core/themes/migrations/2026-05-29-tabbar-indicator-thickness-to-per-state-width.ts
755
+ var TABBAR_STATES = ["default", "hover", "active", "disabled"];
756
+ var OLD_KEY = "--tabbar-bar-indicator-thickness";
757
+ var FALLBACK = "--border-width-2";
758
+ var componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth = {
759
+ id: "2026-05-29-tabbar-indicator-thickness-to-per-state-width",
760
+ fromVersion: 17,
761
+ toVersion: 18,
762
+ appliesTo: "component-config",
763
+ apply(rawVars, meta) {
764
+ if (meta.component !== "tabbar") return { ...rawVars };
765
+ const seed = rawVars[OLD_KEY] ?? FALLBACK;
766
+ const out = {};
767
+ for (const [key, value] of Object.entries(rawVars)) {
768
+ if (key === OLD_KEY) continue;
769
+ out[key] = value;
770
+ }
771
+ for (const state of TABBAR_STATES) {
772
+ const newKey = `--tabbar-${state}-indicator-border-width`;
773
+ if (!(newKey in out)) out[newKey] = seed;
774
+ }
775
+ return out;
776
+ }
777
+ };
778
+
779
+ // src/editor/core/themes/migrations/2026-05-29-segmentedcontrol-small-divider-rename.ts
780
+ var RENAMES = {
781
+ "--segmentedcontrol-divider-small-thickness": "--segmentedcontrol-small-divider-thickness",
782
+ "--segmentedcontrol-divider-small-inset": "--segmentedcontrol-small-divider-inset"
783
+ };
784
+ var componentMigration_2026_05_29_segmentedcontrolSmallDividerRename = {
785
+ id: "2026-05-29-segmentedcontrol-small-divider-rename",
786
+ fromVersion: 18,
787
+ toVersion: 19,
788
+ appliesTo: "component-config",
789
+ apply(rawVars, meta) {
790
+ if (meta.component !== "segmentedcontrol") return { ...rawVars };
791
+ const out = {};
792
+ for (const [key, value] of Object.entries(rawVars)) {
793
+ out[RENAMES[key] ?? key] = value;
794
+ }
795
+ return out;
796
+ }
797
+ };
798
+
799
+ // src/editor/core/themes/migrations/2026-05-29-toggle-derive-track-from-thumb.ts
800
+ var componentMigration_2026_05_29_toggleDeriveTrackFromThumb = {
801
+ id: "2026-05-29-toggle-derive-track-from-thumb",
802
+ fromVersion: 19,
803
+ toVersion: 20,
804
+ appliesTo: "component-config",
805
+ apply(rawVars, meta) {
806
+ if (meta.component !== "toggle") return { ...rawVars };
807
+ const out = {};
808
+ for (const [key, value] of Object.entries(rawVars)) {
809
+ if (key === "--toggle-track-width" || key === "--toggle-track-thickness") continue;
810
+ out[key] = value;
811
+ }
812
+ if (!("--toggle-track-padding" in out)) {
813
+ out["--toggle-track-padding"] = "--space-2";
814
+ }
815
+ return out;
816
+ }
817
+ };
818
+
819
+ // src/editor/core/themes/migrations/2026-08-13-drop-legacy-shape-space-keys.ts
820
+ var DROPPED = /* @__PURE__ */ new Set([
821
+ "--badge-trait-radius",
822
+ "--badge-trait-padding",
823
+ "--sectiondivider-padding",
824
+ "--dialog-primary-default-radius",
825
+ "--dialog-primary-default-padding",
826
+ "--dialog-primary-hover-radius",
827
+ "--dialog-primary-hover-padding",
828
+ "--dialog-secondary-default-radius",
829
+ "--dialog-secondary-default-padding",
830
+ "--dialog-secondary-hover-radius",
831
+ "--dialog-secondary-hover-padding"
832
+ ]);
833
+ var colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys = {
834
+ id: "2026-08-13-drop-legacy-shape-space-keys",
835
+ fromVersion: 3,
836
+ toVersion: 4,
837
+ appliesTo: "colors-and-type",
838
+ apply(rawVars) {
839
+ const out = {};
840
+ for (const [key, value] of Object.entries(rawVars)) {
841
+ if (DROPPED.has(key)) continue;
842
+ out[key] = value;
843
+ }
844
+ return out;
845
+ }
846
+ };
847
+
848
+ // src/editor/core/themes/migrations/2026-08-15-line-height-scale-rename.ts
849
+ var RENAMED = {
850
+ "--line-height-xs": "--line-height-none",
851
+ "--line-height-sm": "--line-height-tighter",
852
+ "--line-height-md": "--line-height-normal",
853
+ "--line-height-lg": "--line-height-relaxed",
854
+ "--line-height-xl": "--line-height-relaxed"
855
+ };
856
+ var REFERENCE = /--line-height-(?:xs|sm|md|lg|xl)(?![\w-])/g;
857
+ function renameValues(rawVars) {
858
+ const out = {};
859
+ for (const [key, value] of Object.entries(rawVars)) {
860
+ out[key] = typeof value === "string" ? value.replace(REFERENCE, (name) => RENAMED[name]) : value;
861
+ }
862
+ return out;
863
+ }
864
+ var colorsAndTypeMigration_2026_08_15_lineHeightScaleRename = {
865
+ id: "2026-08-15-line-height-scale-rename-colors-and-type",
866
+ fromVersion: 4,
867
+ toVersion: 5,
868
+ appliesTo: "colors-and-type",
869
+ apply: renameValues
870
+ };
871
+ var componentMigration_2026_08_15_lineHeightScaleRename = {
872
+ id: "2026-08-15-line-height-scale-rename-component",
873
+ fromVersion: 20,
874
+ toVersion: 21,
875
+ appliesTo: "component-config",
876
+ apply: renameValues
877
+ };
878
+
879
+ // src/editor/core/themes/migrations/index.ts
880
+ var MIGRATIONS = [
881
+ colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas,
882
+ colorsAndTypeMigration_2026_05_13_primaryToBrand,
883
+ componentMigration_2026_04_24_prefixAndSuffixRenames,
884
+ componentMigration_2026_04_27_segmentedcontrolDisabledFlatten,
885
+ componentMigration_2026_05_08_collapsiblesectionVariantNamespace,
886
+ componentMigration_2026_05_08_collapsiblesectionFrameAndCleanup,
887
+ componentMigration_2026_05_10_sectiondividerGradientStops,
888
+ componentMigration_2026_05_13_primaryToBrand,
889
+ componentMigration_2026_05_19_collapsiblesectionDropFrameSurface,
890
+ componentMigration_2026_05_19_sectiondividerRichGradient,
891
+ componentMigration_2026_05_20_sectiondividerSlimVariants,
892
+ componentMigration_2026_05_21_sectiondividerSpacingToPadding,
893
+ componentMigration_2026_05_22_sectiondividerIntrinsicsToCss,
894
+ componentMigration_2026_05_24_segmentedcontrolDividerInset,
895
+ componentMigration_2026_05_24_promoteStateSharedTokens,
896
+ componentMigration_2026_05_24_progressbarCollapseVariants,
897
+ componentMigration_2026_05_24_collapsiblesectionDropActiveState,
898
+ componentMigration_2026_05_25_cornerbadgeFlattenVariants,
899
+ colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops,
900
+ componentMigration_2026_05_26_dropOverlayExtraStops,
901
+ componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth,
902
+ componentMigration_2026_05_29_segmentedcontrolSmallDividerRename,
903
+ componentMigration_2026_05_29_toggleDeriveTrackFromThumb,
904
+ colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys,
905
+ colorsAndTypeMigration_2026_08_15_lineHeightScaleRename,
906
+ componentMigration_2026_08_15_lineHeightScaleRename
907
+ ];
908
+ function countFor(kind) {
909
+ return MIGRATIONS.filter((m) => m.appliesTo === kind).length;
910
+ }
911
+ var CURRENT_COLORS_AND_TYPE_SCHEMA_VERSION = countFor("colors-and-type");
912
+ var CURRENT_COMPONENT_SCHEMA_VERSION = countFor("component-config");
913
+ function runMigrations(kind, fileVersion, rawVars, meta = {}) {
914
+ const applicable = MIGRATIONS.filter((m) => m.appliesTo === kind && m.fromVersion >= fileVersion).sort((a, b) => a.toVersion - b.toVersion);
915
+ let out = { ...rawVars };
916
+ for (const m of applicable) {
917
+ out = m.apply(out, meta);
918
+ }
919
+ return out;
920
+ }
921
+
922
+ // src/editor/core/themes/migrateComponentConfig.ts
923
+ function migrateComponentConfig(component, aliasesIn, rawConfig, fileVersion) {
924
+ const stringPart = {};
925
+ const objectPart = {};
926
+ for (const [k, v] of Object.entries(aliasesIn)) {
927
+ if (typeof v === "string") stringPart[k] = v;
928
+ else objectPart[k] = v;
929
+ }
930
+ const configOut = {};
931
+ for (const [k, v] of Object.entries(rawConfig ?? {})) {
932
+ if (typeof v === "string") stringPart[k] = v;
933
+ else configOut[k] = v;
934
+ }
935
+ if (component === "sectiondivider") {
936
+ synthesizeSectionDividerGradients(stringPart, objectPart);
937
+ }
938
+ const migratedString = runMigrations("component-config", fileVersion, stringPart, { component });
939
+ const migratedObject = component === "sectiondivider" ? renameSectionDividerObjectSlots(objectPart) : objectPart;
940
+ return {
941
+ aliases: { ...migratedString, ...migratedObject },
942
+ config: configOut
943
+ };
944
+ }
945
+ var FAMILIES = ["canvas", "neutral", "alternate", "primary", "accent", "special"];
946
+ var SIZE_VARIANTS = ["lg", "md", "sm"];
947
+ function renameSectionDividerObjectSlots(objectPart) {
948
+ const canvasSourceKeys = [
949
+ "--sectiondivider-canvas-background",
950
+ "--sectiondivider-canvas-gradient",
951
+ "--sectiondivider-color-canvas-background"
952
+ ];
953
+ let canvasGradient;
954
+ for (const key of canvasSourceKeys) {
955
+ if (objectPart[key] !== void 0) {
956
+ canvasGradient = objectPart[key];
957
+ break;
958
+ }
959
+ }
960
+ const out = {};
961
+ for (const [key, value] of Object.entries(objectPart)) {
962
+ let isFamilyGradient = false;
963
+ for (const f of FAMILIES) {
964
+ if (key === `--sectiondivider-${f}-background` || key === `--sectiondivider-${f}-gradient` || key === `--sectiondivider-color-${f}-background`) {
965
+ isFamilyGradient = true;
966
+ break;
967
+ }
968
+ }
969
+ if (isFamilyGradient) continue;
970
+ out[key] = value;
971
+ }
972
+ if (canvasGradient !== void 0) {
973
+ for (const v of SIZE_VARIANTS) {
974
+ out[`--sectiondivider-${v}-background`] = canvasGradient;
975
+ }
976
+ }
977
+ return out;
978
+ }
979
+ var SECTIONDIVIDER_VARIANTS = ["canvas", "neutral", "alternate", "primary", "accent", "special"];
980
+ function synthesizeSectionDividerGradients(stringPart, objectPart) {
981
+ const GRADIENT_ANGLE_TOKENS = {
982
+ "--gradient-angle-horizontal": 90,
983
+ "--gradient-angle-vertical": 180,
984
+ "--gradient-angle-diagonal": 135,
985
+ "--gradient-angle-counter-diagonal": 45
986
+ };
987
+ const GRADIENT_STOP_POSITIONS = {
988
+ "--gradient-stop-start": 0,
989
+ "--gradient-stop-mid": 50,
990
+ "--gradient-stop-end": 100
991
+ };
992
+ const parseAngle = (raw) => {
993
+ if (!raw) return 135;
994
+ if (raw.startsWith("--")) return GRADIENT_ANGLE_TOKENS[raw] ?? 135;
995
+ const m = raw.match(/^(-?\d+(?:\.\d+)?)\s*deg$/i);
996
+ return m ? parseFloat(m[1]) : 135;
997
+ };
998
+ const parsePosition = (raw, fallback) => {
999
+ if (!raw) return fallback;
1000
+ if (raw.startsWith("--")) return GRADIENT_STOP_POSITIONS[raw] ?? fallback;
1001
+ const m = raw.match(/^(-?\d+(?:\.\d+)?)\s*%$/);
1002
+ return m ? parseFloat(m[1]) : fallback;
1003
+ };
1004
+ const parseStopColor = (raw) => {
1005
+ if (!raw) return null;
1006
+ if (raw.startsWith("--")) return { color: raw };
1007
+ const mix = raw.match(/^color-mix\(\s*in\s+srgb\s*,\s*var\((--[a-z0-9-]+)\)\s+([\d.]+)%\s*,\s*transparent\s*\)$/i);
1008
+ if (mix) return { color: mix[1], opacity: parseFloat(mix[2]) };
1009
+ return null;
1010
+ };
1011
+ for (const v of SECTIONDIVIDER_VARIANTS) {
1012
+ const slot = `--sectiondivider-${v}-gradient`;
1013
+ if (slot in objectPart) continue;
1014
+ const angleKey = `${slot}-angle`;
1015
+ const has1 = stringPart[`${slot}-stop-1-color`] !== void 0;
1016
+ const has2 = stringPart[`${slot}-stop-2-color`] !== void 0;
1017
+ const has3 = stringPart[`${slot}-stop-3-color`] !== void 0;
1018
+ if (!has1 && !has2 && !has3) continue;
1019
+ const stops = [];
1020
+ const positionDefaults = [0, 50, 100];
1021
+ for (let i = 1; i <= 3; i++) {
1022
+ const c = parseStopColor(stringPart[`${slot}-stop-${i}-color`]);
1023
+ if (!c) continue;
1024
+ const pos = parsePosition(stringPart[`${slot}-stop-${i}-position`], positionDefaults[i - 1]);
1025
+ stops.push({ position: pos, color: c.color, ...c.opacity !== void 0 ? { opacity: c.opacity } : {} });
1026
+ }
1027
+ if (stops.length < 2) continue;
1028
+ objectPart[slot] = {
1029
+ kind: "gradient",
1030
+ value: {
1031
+ type: "linear",
1032
+ angle: parseAngle(stringPart[angleKey]),
1033
+ stops
1034
+ }
1035
+ };
1036
+ }
1037
+ }
1038
+
1039
+ // src/editor/core/themes/themeTypes.ts
1040
+ var THEME_SCHEMA_VERSION = 4;
1041
+
1042
+ // src/editor/core/components/componentConfigKeys.ts
1043
+ var KNOWN_COMPONENT_CONFIG_KEYS = /* @__PURE__ */ new Set([
1044
+ "--dialog-confirm-variant",
1045
+ "--dialog-cancel-variant",
1046
+ // SectionDivider per-variant `color-family` is editor metadata that drives
1047
+ // the family-swap rewrite on aliases. It is not a runtime CSS value, so it
1048
+ // stays in the config bucket. The other intrinsics (align, hairline,
1049
+ // eyebrow/description visibility, eyebrow text-transform) now flow through
1050
+ // the alias bucket as cascading CSS vars — see the 2026-05-22 migration.
1051
+ "--sectiondivider-lg-color-family",
1052
+ "--sectiondivider-md-color-family",
1053
+ "--sectiondivider-sm-color-family"
1054
+ ]);
1055
+
174
1056
  // vite-plugin/themes/normalizeTheme.ts
175
- var THEME_SCHEMA_VERSION = 3;
176
1057
  function asObject(value) {
177
1058
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
178
1059
  }
@@ -194,10 +1075,41 @@ function migrateEmbeddedKey(src) {
194
1075
  const { theme, ...rest } = src;
195
1076
  return { ...rest, colorsAndType: theme };
196
1077
  }
1078
+ function routeKnownConfigKeys(aliases, config) {
1079
+ const outAliases = { ...aliases };
1080
+ const outConfig = { ...config };
1081
+ for (const key of Object.keys(outAliases)) {
1082
+ if (!KNOWN_COMPONENT_CONFIG_KEYS.has(key)) continue;
1083
+ if (outConfig[key] === void 0) outConfig[key] = outAliases[key];
1084
+ delete outAliases[key];
1085
+ }
1086
+ return { aliases: outAliases, config: outConfig };
1087
+ }
1088
+ function migrateEmbeddedComponentConfig(comp, config, fileVersion) {
1089
+ const { schemaVersion: _entryStamp, aliases: rawAliases, config: rawConfig, ...rest } = config;
1090
+ const aliasesIn = asObject(rawAliases);
1091
+ if (!aliasesIn) {
1092
+ return rawConfig !== void 0 ? { ...rest, config: rawConfig } : rest;
1093
+ }
1094
+ const migratedConfig = migrateComponentConfig(
1095
+ comp,
1096
+ aliasesIn,
1097
+ asObject(rawConfig) ?? void 0,
1098
+ fileVersion
1099
+ );
1100
+ const split = routeKnownConfigKeys(migratedConfig.aliases, migratedConfig.config);
1101
+ const out = { ...rest, aliases: split.aliases };
1102
+ if (rawConfig !== void 0 || Object.keys(split.config).length > 0) {
1103
+ out.config = split.config;
1104
+ }
1105
+ return out;
1106
+ }
197
1107
  function normalizeTheme(raw, resolvers) {
198
1108
  const input = asObject(raw) ?? {};
199
1109
  const migrated = input.schemaVersion !== THEME_SCHEMA_VERSION;
200
- const src = migrated ? migrateEmbeddedKey(input) : input;
1110
+ const inputVersion = typeof input.schemaVersion === "number" ? input.schemaVersion : 0;
1111
+ const src = inputVersion < 3 ? migrateEmbeddedKey(input) : input;
1112
+ const componentSchemaVersion = typeof input.componentSchemaVersion === "number" ? input.componentSchemaVersion : 0;
201
1113
  const dropped = [];
202
1114
  const now = (/* @__PURE__ */ new Date()).toISOString();
203
1115
  const embeddedColorsAndType = asObject(src.colorsAndType);
@@ -216,18 +1128,42 @@ function normalizeTheme(raw, resolvers) {
216
1128
  const componentConfigs = {};
217
1129
  for (const [comp, value] of Object.entries(asObject(src.componentConfigs) ?? {})) {
218
1130
  const embedded = asObject(value);
1131
+ let resolvedConfig;
219
1132
  if (embedded) {
220
- componentConfigs[comp] = stripFileMarker(embedded);
221
- continue;
1133
+ resolvedConfig = stripFileMarker(embedded);
1134
+ } else {
1135
+ const configName = asString(value, "default");
1136
+ const resolved = asObject(resolvers.readComponentConfig(comp, configName));
1137
+ if (!resolved) {
1138
+ dropped.push(`${comp}/${configName}`);
1139
+ continue;
1140
+ }
1141
+ resolvedConfig = stripFileMarker(resolved);
222
1142
  }
223
- const configName = asString(value, "default");
224
- if (configName === "default") continue;
225
- const resolved = asObject(resolvers.readComponentConfig(comp, configName));
226
- if (!resolved) {
227
- dropped.push(`${comp}/${configName}`);
1143
+ componentConfigs[comp] = migrateEmbeddedComponentConfig(comp, resolvedConfig, componentSchemaVersion);
1144
+ }
1145
+ const filled = { components: [], aliases: 0, orphans: 0 };
1146
+ for (const comp of resolvers.listComponentNames()) {
1147
+ const base = asObject(resolvers.readComponentConfig(comp, "default"));
1148
+ const baseAliases = base ? asObject(base.aliases) : null;
1149
+ if (!base || !baseAliases) continue;
1150
+ const entry = componentConfigs[comp];
1151
+ if (!entry) {
1152
+ const { schemaVersion: _standaloneStamp, ...rest } = stripFileMarker(base);
1153
+ componentConfigs[comp] = structuredClone(rest);
1154
+ filled.components.push(comp);
228
1155
  continue;
229
1156
  }
230
- componentConfigs[comp] = stripFileMarker(resolved);
1157
+ const entryAliases = asObject(entry.aliases) ?? {};
1158
+ for (const key of Object.keys(baseAliases)) {
1159
+ if (key in entryAliases) continue;
1160
+ entryAliases[key] = structuredClone(baseAliases[key]);
1161
+ filled.aliases++;
1162
+ }
1163
+ entry.aliases = entryAliases;
1164
+ for (const key of Object.keys(entryAliases)) {
1165
+ if (!(key in baseAliases)) filled.orphans++;
1166
+ }
231
1167
  }
232
1168
  return {
233
1169
  theme: {
@@ -236,10 +1172,12 @@ function normalizeTheme(raw, resolvers) {
236
1172
  updatedAt: asString(src.updatedAt, now),
237
1173
  schemaVersion: THEME_SCHEMA_VERSION,
238
1174
  colorsAndType,
239
- componentConfigs
1175
+ componentConfigs,
1176
+ componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION
240
1177
  },
241
1178
  dropped,
242
- migrated
1179
+ migrated,
1180
+ filled
243
1181
  };
244
1182
  }
245
1183
 
@@ -482,6 +1420,7 @@ function migrateData(opts) {
482
1420
  const resolvers = {
483
1421
  readColorsAndType: (name) => colorsRes.readJson(name),
484
1422
  readComponentConfig: (comp, name) => compRes(comp).readJson(name),
1423
+ listComponentNames: () => comps,
485
1424
  normalizeColorsAndType: (colorsAndType) => colorsAndType
486
1425
  };
487
1426
  const upgradedThemes = [];
@@ -561,7 +1500,6 @@ function migrateData(opts) {
561
1500
  for (const comp of comps) {
562
1501
  const pointed = prodConfigs.get(comp);
563
1502
  if (!isObject(pointed)) continue;
564
- if (sameContent(pointed, defaultConfig(comp))) continue;
565
1503
  componentConfigs[comp] = stripMarkers(pointed);
566
1504
  }
567
1505
  recoveredTheme = {
@@ -570,7 +1508,11 @@ function migrateData(opts) {
570
1508
  updatedAt: now,
571
1509
  schemaVersion: THEME_SCHEMA_VERSION,
572
1510
  colorsAndType: isObject(prodColors) ? stripMarkers(prodColors) : null,
573
- componentConfigs
1511
+ componentConfigs,
1512
+ // The configs above are what boot just wrote (`prodConfigs`, read off
1513
+ // the pointed files), at the current component schema — not 0, which
1514
+ // would misdescribe them as unmigrated.
1515
+ componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION
574
1516
  };
575
1517
  const slug = nextAvailableName((n) => themesRes.existingPath(n) !== null, RECOVERED_SLUG);
576
1518
  recoveredThemePath = themesRes.filePath(slug);