@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.
- package/.claude/skills/live-tokens-adjust-shape-space/SKILL.md +7 -1
- package/CHANGELOG.md +63 -0
- package/bin/adjust.mjs +16 -39
- package/bin/generate-theme.mjs +20 -6
- package/dist-plugin/adjust/index.cjs +781 -21
- package/dist-plugin/adjust/index.d.cts +2 -1
- package/dist-plugin/adjust/index.d.ts +2 -1
- package/dist-plugin/adjust/index.js +43 -21
- package/dist-plugin/{chunk-6OZFXIQI.js → chunk-232GZGQU.js} +207 -12
- package/dist-plugin/chunk-NE6N66EE.js +753 -0
- package/dist-plugin/{chunk-JIGIIE5P.js → chunk-PB2JTK2H.js} +123 -0
- package/dist-plugin/generateColorsAndType/index.cjs +48 -32
- package/dist-plugin/generateColorsAndType/index.d.cts +2 -1
- package/dist-plugin/generateColorsAndType/index.d.ts +2 -1
- package/dist-plugin/generateColorsAndType/index.js +7 -773
- package/dist-plugin/{themeTypes-Dky03HL9.d.cts → index-DpTIRZ2H.d.cts} +49 -21
- package/dist-plugin/{themeTypes-Dky03HL9.d.ts → index-DpTIRZ2H.d.ts} +49 -21
- package/dist-plugin/index.cjs +1159 -85
- package/dist-plugin/index.js +102 -80
- package/dist-plugin/migrateData/index.cjs +956 -14
- package/dist-plugin/migrateData/index.js +10 -3
- package/package.json +6 -4
- package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +9 -23
- package/src/editor/component-editor/scaffolding/LinkedBlock.svelte +8 -8
- package/src/editor/core/components/adjustAliases.ts +49 -22
- package/src/editor/core/components/aliasKinds.ts +7 -2
- package/src/editor/core/components/componentConfigService.ts +1 -1
- package/src/editor/core/store/editorStore.ts +7 -197
- package/src/editor/core/store/editorTypes.ts +9 -30
- package/src/editor/core/themes/lookSummary.ts +3 -25
- package/src/editor/core/themes/migrateComponentConfig.ts +205 -0
- package/src/editor/core/themes/migrations/2026-05-19-sectiondivider-rich-gradient.ts +1 -1
- package/src/editor/core/themes/migrations/2026-05-20-sectiondivider-slim-variants.ts +1 -1
- package/src/editor/core/themes/migrations/2026-05-22-sectiondivider-intrinsics-to-css.ts +1 -1
- package/src/editor/core/themes/parsers/gradient.ts +211 -0
- package/src/editor/core/themes/slices/gradients.ts +5 -58
- package/src/editor/core/themes/themeService.ts +22 -9
- package/src/editor/core/themes/themeTypes.ts +71 -21
- package/src/editor/docs/content/themes-workflow.md +9 -11
- package/src/editor/docs/content/where-themes-live.md +2 -2
- package/src/editor/docs/content.generated.ts +2 -2
- package/src/editor/index.ts +1 -0
- package/src/editor/styles/ui-editor.css +5 -2
- package/src/editor/ui/PaletteEditor.svelte +30 -15
- package/src/editor/ui/ThemePanel.svelte +24 -15
- package/src/editor/ui/Toggle.svelte +22 -22
- package/src/editor/ui/UIPillButton.svelte +1 -1
- package/src/editor/ui/UIReveal.svelte +47 -0
- package/src/editor/ui/UISquareButton.svelte +1 -1
- package/src/editor/ui/colors/ColorsTab.svelte +4 -5
- package/src/editor/ui/palette/OverridesPanel.svelte +4 -3
- package/src/editor/ui/palette/PaletteJumpButton.svelte +3 -3
- package/src/editor/ui/palette/ScaleCurveEditor.svelte +3 -2
- package/src/live-tokens/data/themes/autumn.json +77 -41
- package/src/live-tokens/data/themes/halloween.json +53 -52
- package/src/live-tokens/data/themes/midnight-study.json +136 -68
- package/src/live-tokens/data/themes/ocean.json +77 -41
- package/src/live-tokens/data/themes/royal-velvet.json +43 -42
- package/src/live-tokens/data/themes/spring-meadow.json +86 -52
- package/src/live-tokens/data/themes/sunset.json +101 -40
package/dist-plugin/index.cjs
CHANGED
|
@@ -59,6 +59,118 @@ function parseColorOpacity(value) {
|
|
|
59
59
|
if (!m) return null;
|
|
60
60
|
return { name: m[1], opacity: parseInt(m[2], 10) };
|
|
61
61
|
}
|
|
62
|
+
function formatColorOpacity(name, opacity) {
|
|
63
|
+
return `color-mix(in srgb, var(${name}) ${opacity}%, transparent)`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/editor/core/themes/parsers/gradient.ts
|
|
67
|
+
var RADIAL_BASE_PX = 100;
|
|
68
|
+
function formatStopColor(s) {
|
|
69
|
+
const opacity = s.opacity ?? 100;
|
|
70
|
+
if (s.color.startsWith("--")) {
|
|
71
|
+
return opacity >= 100 ? `var(${s.color})` : formatColorOpacity(s.color, opacity);
|
|
72
|
+
}
|
|
73
|
+
return opacity >= 100 ? s.color : `color-mix(in srgb, ${s.color} ${opacity}%, transparent)`;
|
|
74
|
+
}
|
|
75
|
+
function formatGradientStops(stops) {
|
|
76
|
+
return stops.map((s) => `${formatStopColor(s)} ${s.position}%`).join(", ");
|
|
77
|
+
}
|
|
78
|
+
function formatRadialShape(v) {
|
|
79
|
+
const ax = v.aspectX ?? 1;
|
|
80
|
+
const ay = v.aspectY ?? 1;
|
|
81
|
+
if (ax === 1 && ay === 1) {
|
|
82
|
+
return v.radius && v.radius > 0 ? `circle ${v.radius}px` : "circle";
|
|
83
|
+
}
|
|
84
|
+
const base = v.radius && v.radius > 0 ? v.radius : RADIAL_BASE_PX;
|
|
85
|
+
return `ellipse ${(base * ax).toFixed(2)}px ${(base * ay).toFixed(2)}px`;
|
|
86
|
+
}
|
|
87
|
+
function formatGradientValue(v) {
|
|
88
|
+
if (v.type === "none") return "transparent";
|
|
89
|
+
if (v.type === "solid") {
|
|
90
|
+
const first = v.stops[0];
|
|
91
|
+
return first ? formatStopColor(first) : "transparent";
|
|
92
|
+
}
|
|
93
|
+
const stops = formatGradientStops(v.stops);
|
|
94
|
+
if (v.type === "linear") return `linear-gradient(${v.angle}deg, ${stops})`;
|
|
95
|
+
return `radial-gradient(${formatRadialShape(v)} at ${v.centerX ?? 50}% 50%, ${stops})`;
|
|
96
|
+
}
|
|
97
|
+
var NUM = String.raw`-?\d+(?:\.\d+)?`;
|
|
98
|
+
var LINEAR_RE = new RegExp(String.raw`^linear-gradient\(\s*(${NUM})deg\s*,\s*(.+)\)$`, "i");
|
|
99
|
+
var RADIAL_RE = new RegExp(
|
|
100
|
+
String.raw`^radial-gradient\(\s*(circle|circle\s+${NUM}px|ellipse\s+${NUM}px\s+${NUM}px)\s+at\s+(${NUM})%\s+50%\s*,\s*(.+)\)$`,
|
|
101
|
+
"i"
|
|
102
|
+
);
|
|
103
|
+
var STOP_RE = new RegExp(String.raw`^(.*?)\s+(${NUM})%$`);
|
|
104
|
+
var CIRCLE_RADIUS_RE = new RegExp(String.raw`^circle\s+(${NUM})px$`, "i");
|
|
105
|
+
var ELLIPSE_RE = new RegExp(String.raw`^ellipse\s+(${NUM})px\s+(${NUM})px$`, "i");
|
|
106
|
+
var VAR_RE = /^var\((--[a-z0-9-]+)\)$/i;
|
|
107
|
+
function splitTopLevel(s) {
|
|
108
|
+
const parts = [];
|
|
109
|
+
let depth = 0;
|
|
110
|
+
let start = 0;
|
|
111
|
+
for (let i = 0; i < s.length; i++) {
|
|
112
|
+
const c = s[i];
|
|
113
|
+
if (c === "(") depth++;
|
|
114
|
+
else if (c === ")") depth--;
|
|
115
|
+
else if (c === "," && depth === 0) {
|
|
116
|
+
parts.push(s.slice(start, i));
|
|
117
|
+
start = i + 1;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
parts.push(s.slice(start));
|
|
121
|
+
return parts;
|
|
122
|
+
}
|
|
123
|
+
function parseStop(raw) {
|
|
124
|
+
const m = raw.trim().match(STOP_RE);
|
|
125
|
+
if (!m) return null;
|
|
126
|
+
const position = parseFloat(m[2]);
|
|
127
|
+
const color = m[1].trim();
|
|
128
|
+
const opacity = parseColorOpacity(color);
|
|
129
|
+
if (opacity) return { position, color: opacity.name, opacity: opacity.opacity };
|
|
130
|
+
const token = color.match(VAR_RE);
|
|
131
|
+
return { position, color: token ? token[1] : color };
|
|
132
|
+
}
|
|
133
|
+
function parseStops(raw) {
|
|
134
|
+
const stops = [];
|
|
135
|
+
for (const part of splitTopLevel(raw)) {
|
|
136
|
+
const stop = parseStop(part);
|
|
137
|
+
if (!stop) return null;
|
|
138
|
+
stops.push(stop);
|
|
139
|
+
}
|
|
140
|
+
return stops.length > 0 ? stops : null;
|
|
141
|
+
}
|
|
142
|
+
function parseRadialShape(raw) {
|
|
143
|
+
const shape = raw.trim();
|
|
144
|
+
if (/^circle$/i.test(shape)) return {};
|
|
145
|
+
const circle = shape.match(CIRCLE_RADIUS_RE);
|
|
146
|
+
if (circle) return { radius: parseFloat(circle[1]) };
|
|
147
|
+
const ellipse = shape.match(ELLIPSE_RE);
|
|
148
|
+
if (!ellipse) return null;
|
|
149
|
+
const ax = parseFloat(ellipse[1]) / RADIAL_BASE_PX;
|
|
150
|
+
const ay = parseFloat(ellipse[2]) / RADIAL_BASE_PX;
|
|
151
|
+
return { ...ax === 1 ? {} : { aspectX: ax }, ...ay === 1 ? {} : { aspectY: ay } };
|
|
152
|
+
}
|
|
153
|
+
function parseGradientValue(value) {
|
|
154
|
+
const css = value.trim();
|
|
155
|
+
const linear = css.match(LINEAR_RE);
|
|
156
|
+
if (linear) {
|
|
157
|
+
const stops2 = parseStops(linear[2]);
|
|
158
|
+
return stops2 && { type: "linear", angle: parseFloat(linear[1]), stops: stops2 };
|
|
159
|
+
}
|
|
160
|
+
const radial = css.match(RADIAL_RE);
|
|
161
|
+
if (!radial) return null;
|
|
162
|
+
const shape = parseRadialShape(radial[1]);
|
|
163
|
+
const stops = parseStops(radial[3]);
|
|
164
|
+
if (!shape || !stops) return null;
|
|
165
|
+
const centerX = parseFloat(radial[2]);
|
|
166
|
+
return {
|
|
167
|
+
type: "radial",
|
|
168
|
+
angle: 0,
|
|
169
|
+
...shape,
|
|
170
|
+
...centerX === 50 ? {} : { centerX },
|
|
171
|
+
stops
|
|
172
|
+
};
|
|
173
|
+
}
|
|
62
174
|
|
|
63
175
|
// src/editor/core/storage/files/versionedFileResourceClient.ts
|
|
64
176
|
function sanitizeFileName(name) {
|
|
@@ -642,6 +754,754 @@ function migratePaletteColorsToOklch(editorConfigs) {
|
|
|
642
754
|
return out;
|
|
643
755
|
}
|
|
644
756
|
|
|
757
|
+
// src/editor/core/themes/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts
|
|
758
|
+
var LEGACY_KEY_RENAMES = {
|
|
759
|
+
"--empty": "--page-bg",
|
|
760
|
+
"--empty-attachment": "--page-bg-attachment",
|
|
761
|
+
// Orphan exports dropped from tokens.css; no new home — silently discard.
|
|
762
|
+
"--border-neutral": null,
|
|
763
|
+
// Shadow cleanup: these five tokens were removed (low/zero consumers,
|
|
764
|
+
// aesthetic drift). Dialog migrated onto --shadow-2xl; focus rings moved
|
|
765
|
+
// to their own --ring-focus-* namespace, which themes don't carry by
|
|
766
|
+
// default — tokens.css provides the canonical values.
|
|
767
|
+
"--shadow-app": null,
|
|
768
|
+
"--shadow-card": null,
|
|
769
|
+
"--shadow-overlay": null,
|
|
770
|
+
"--shadow-focus": null,
|
|
771
|
+
"--shadow-glow-green": null
|
|
772
|
+
};
|
|
773
|
+
var BG_TO_CANVAS_PREFIXES = ["--color-bg-", "--surface-bg", "--border-bg", "--text-bg"];
|
|
774
|
+
function migrateBgToCanvas(rawVars) {
|
|
775
|
+
for (const oldKey of Object.keys(rawVars)) {
|
|
776
|
+
for (const prefix of BG_TO_CANVAS_PREFIXES) {
|
|
777
|
+
if (!oldKey.startsWith(prefix)) continue;
|
|
778
|
+
const suffix = oldKey.slice(prefix.length);
|
|
779
|
+
if (suffix && !suffix.startsWith("-")) continue;
|
|
780
|
+
const newKey = prefix.replace("-bg", "-canvas") + suffix;
|
|
781
|
+
if (newKey === oldKey) continue;
|
|
782
|
+
const value = rawVars[oldKey];
|
|
783
|
+
delete rawVars[oldKey];
|
|
784
|
+
if (!(newKey in rawVars)) rawVars[newKey] = value;
|
|
785
|
+
break;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
function migrateLegacyKeys(rawVars) {
|
|
790
|
+
for (const [oldKey, newKey] of Object.entries(LEGACY_KEY_RENAMES)) {
|
|
791
|
+
if (!(oldKey in rawVars)) continue;
|
|
792
|
+
const value = rawVars[oldKey];
|
|
793
|
+
delete rawVars[oldKey];
|
|
794
|
+
if (newKey && !(newKey in rawVars)) rawVars[newKey] = value;
|
|
795
|
+
}
|
|
796
|
+
migrateBgToCanvas(rawVars);
|
|
797
|
+
}
|
|
798
|
+
var colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas = {
|
|
799
|
+
id: "2026-04-24-legacy-keys-and-bg-to-canvas",
|
|
800
|
+
fromVersion: 0,
|
|
801
|
+
toVersion: 1,
|
|
802
|
+
appliesTo: "colors-and-type",
|
|
803
|
+
apply(rawVars) {
|
|
804
|
+
const out = { ...rawVars };
|
|
805
|
+
migrateLegacyKeys(out);
|
|
806
|
+
return out;
|
|
807
|
+
}
|
|
808
|
+
};
|
|
809
|
+
|
|
810
|
+
// src/editor/core/themes/migrations/2026-04-24-component-prefix-and-suffix-renames.ts
|
|
811
|
+
var COMPONENT_PREFIX_RENAMES = {
|
|
812
|
+
"--segment-": "--segmentedcontrol-",
|
|
813
|
+
"--collapsible-": "--collapsiblesection-",
|
|
814
|
+
"--progress-": "--progressbar-",
|
|
815
|
+
"--section-divider-": "--sectiondivider-",
|
|
816
|
+
"--radio-": "--radiobutton-",
|
|
817
|
+
"--inline-edit-": "--inlineeditactions-"
|
|
818
|
+
};
|
|
819
|
+
var COMPONENT_SUFFIX_RENAMES = {
|
|
820
|
+
progressbar: [["-track-bg", "-track-surface"]],
|
|
821
|
+
inlineeditactions: [
|
|
822
|
+
["-bg-hover", "-hover-surface"],
|
|
823
|
+
["-bg", "-surface"]
|
|
824
|
+
]
|
|
825
|
+
};
|
|
826
|
+
var componentMigration_2026_04_24_prefixAndSuffixRenames = {
|
|
827
|
+
id: "2026-04-24-component-prefix-and-suffix-renames",
|
|
828
|
+
fromVersion: 0,
|
|
829
|
+
toVersion: 1,
|
|
830
|
+
appliesTo: "component-config",
|
|
831
|
+
apply(rawVars, meta) {
|
|
832
|
+
const component = meta.component ?? "";
|
|
833
|
+
const out = {};
|
|
834
|
+
const suffixRules = COMPONENT_SUFFIX_RENAMES[component] ?? [];
|
|
835
|
+
for (const [oldKey, value] of Object.entries(rawVars)) {
|
|
836
|
+
let key = oldKey;
|
|
837
|
+
if (key === "--detail-nav-bg") key = "--detailnav-surface";
|
|
838
|
+
for (const [oldPrefix, newPrefix] of Object.entries(COMPONENT_PREFIX_RENAMES)) {
|
|
839
|
+
if (key.startsWith(oldPrefix)) {
|
|
840
|
+
key = newPrefix + key.slice(oldPrefix.length);
|
|
841
|
+
break;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
for (const [oldSuffix, newSuffix] of suffixRules) {
|
|
845
|
+
if (key.endsWith(oldSuffix)) {
|
|
846
|
+
key = key.slice(0, -oldSuffix.length) + newSuffix;
|
|
847
|
+
break;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
if (!(key in out)) out[key] = value;
|
|
851
|
+
}
|
|
852
|
+
return out;
|
|
853
|
+
}
|
|
854
|
+
};
|
|
855
|
+
|
|
856
|
+
// src/editor/core/themes/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts
|
|
857
|
+
var OPTION_DISABLED_PREFIX = "--segmentedcontrol-option-disabled-";
|
|
858
|
+
var DISABLED_PREFIX = "--segmentedcontrol-disabled-";
|
|
859
|
+
var SELECTED_DISABLED_PREFIX = "--segmentedcontrol-selected-disabled-";
|
|
860
|
+
var SELECTED_HOVER_PREFIX = "--segmentedcontrol-selected-hover-";
|
|
861
|
+
var componentMigration_2026_04_27_segmentedcontrolDisabledFlatten = {
|
|
862
|
+
id: "2026-04-27-segmentedcontrol-disabled-flatten",
|
|
863
|
+
fromVersion: 1,
|
|
864
|
+
toVersion: 2,
|
|
865
|
+
appliesTo: "component-config",
|
|
866
|
+
apply(rawVars, meta) {
|
|
867
|
+
if (meta.component !== "segmentedcontrol") return { ...rawVars };
|
|
868
|
+
const out = {};
|
|
869
|
+
for (const [oldKey, value] of Object.entries(rawVars)) {
|
|
870
|
+
let key = oldKey;
|
|
871
|
+
if (key.startsWith(SELECTED_DISABLED_PREFIX)) continue;
|
|
872
|
+
if (key.startsWith(SELECTED_HOVER_PREFIX)) continue;
|
|
873
|
+
if (key.startsWith(OPTION_DISABLED_PREFIX)) {
|
|
874
|
+
key = DISABLED_PREFIX + key.slice(OPTION_DISABLED_PREFIX.length);
|
|
875
|
+
}
|
|
876
|
+
if (!(key in out)) out[key] = value;
|
|
877
|
+
}
|
|
878
|
+
return out;
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
// src/editor/core/themes/migrations/2026-05-08-collapsiblesection-variant-namespace.ts
|
|
883
|
+
var PREFIX = "--collapsiblesection-";
|
|
884
|
+
var STATE_NAMES = /* @__PURE__ */ new Set(["default", "hover", "active", "expanded"]);
|
|
885
|
+
var componentMigration_2026_05_08_collapsiblesectionVariantNamespace = {
|
|
886
|
+
id: "2026-05-08-collapsiblesection-variant-namespace",
|
|
887
|
+
fromVersion: 2,
|
|
888
|
+
toVersion: 3,
|
|
889
|
+
appliesTo: "component-config",
|
|
890
|
+
apply(rawVars, meta) {
|
|
891
|
+
if (meta.component !== "collapsiblesection") return { ...rawVars };
|
|
892
|
+
const out = {};
|
|
893
|
+
for (const [oldKey, value] of Object.entries(rawVars)) {
|
|
894
|
+
let key = oldKey;
|
|
895
|
+
if (key.startsWith(PREFIX)) {
|
|
896
|
+
const tail = key.slice(PREFIX.length);
|
|
897
|
+
const firstSegment = tail.split("-", 1)[0];
|
|
898
|
+
if (STATE_NAMES.has(firstSegment)) {
|
|
899
|
+
key = `${PREFIX}container-${tail}`;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
if (!(key in out)) out[key] = value;
|
|
903
|
+
}
|
|
904
|
+
return out;
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
|
|
908
|
+
// src/editor/core/themes/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts
|
|
909
|
+
var PFX = "--collapsiblesection-";
|
|
910
|
+
var componentMigration_2026_05_08_collapsiblesectionFrameAndCleanup = {
|
|
911
|
+
id: "2026-05-08-collapsiblesection-frame-and-cleanup",
|
|
912
|
+
fromVersion: 3,
|
|
913
|
+
toVersion: 4,
|
|
914
|
+
appliesTo: "component-config",
|
|
915
|
+
apply(rawVars, meta) {
|
|
916
|
+
if (meta.component !== "collapsiblesection") return { ...rawVars };
|
|
917
|
+
const out = {};
|
|
918
|
+
for (const prop of ["surface", "border", "border-width", "radius"]) {
|
|
919
|
+
const src = `${PFX}container-default-${prop}`;
|
|
920
|
+
if (src in rawVars) {
|
|
921
|
+
out[`${PFX}container-frame-${prop}`] = rawVars[src];
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
925
|
+
if (/^--collapsiblesection-chromeless-(default|hover|active)-(border|border-width|radius)$/.test(key)) continue;
|
|
926
|
+
if (/^--collapsiblesection-container-(hover|active)-(border|border-width|radius)$/.test(key)) continue;
|
|
927
|
+
if (/^--collapsiblesection-container-default-(border|border-width|radius)$/.test(key)) continue;
|
|
928
|
+
if (/^--collapsiblesection-divider-(default|hover|active)-radius$/.test(key)) continue;
|
|
929
|
+
if (/^--collapsiblesection-(chromeless|divider|container)-expanded-(border|border-width|radius)$/.test(key)) continue;
|
|
930
|
+
if (/^--collapsiblesection-(chromeless|divider)-expanded-surface$/.test(key)) continue;
|
|
931
|
+
if (!(key in out)) out[key] = value;
|
|
932
|
+
}
|
|
933
|
+
return out;
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
// src/editor/core/themes/migrations/2026-05-10-sectiondivider-gradient-stops.ts
|
|
938
|
+
var PFX2 = "--sectiondivider-";
|
|
939
|
+
var VARIANTS = ["canvas", "neutral", "alternate", "primary", "accent", "special"];
|
|
940
|
+
var OLD_STOP_RE = /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-gradient-stop-\d+$/;
|
|
941
|
+
var componentMigration_2026_05_10_sectiondividerGradientStops = {
|
|
942
|
+
id: "2026-05-10-sectiondivider-gradient-stops",
|
|
943
|
+
fromVersion: 4,
|
|
944
|
+
toVersion: 5,
|
|
945
|
+
appliesTo: "component-config",
|
|
946
|
+
apply(rawVars, meta) {
|
|
947
|
+
if (meta.component !== "sectiondivider") return { ...rawVars };
|
|
948
|
+
const out = {};
|
|
949
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
950
|
+
if (OLD_STOP_RE.test(key)) continue;
|
|
951
|
+
out[key] = value;
|
|
952
|
+
}
|
|
953
|
+
const setIfMissing = (key, fallback) => {
|
|
954
|
+
if (!(key in out)) out[key] = fallback;
|
|
955
|
+
};
|
|
956
|
+
for (const v of VARIANTS) {
|
|
957
|
+
const old1 = rawVars[`${PFX2}${v}-gradient-stop-1`];
|
|
958
|
+
const old2 = rawVars[`${PFX2}${v}-gradient-stop-2`];
|
|
959
|
+
const old4 = rawVars[`${PFX2}${v}-gradient-stop-4`];
|
|
960
|
+
setIfMissing(`${PFX2}${v}-gradient-angle`, "--gradient-angle-diagonal");
|
|
961
|
+
setIfMissing(`${PFX2}${v}-gradient-stop-1-color`, old1 ?? `--surface-${v}-highest`);
|
|
962
|
+
setIfMissing(`${PFX2}${v}-gradient-stop-1-position`, "--gradient-stop-start");
|
|
963
|
+
setIfMissing(`${PFX2}${v}-gradient-stop-2-color`, old2 ?? `--surface-${v}-higher`);
|
|
964
|
+
setIfMissing(`${PFX2}${v}-gradient-stop-2-position`, "--gradient-stop-mid");
|
|
965
|
+
setIfMissing(`${PFX2}${v}-gradient-stop-3-color`, old4 ?? `--surface-${v}`);
|
|
966
|
+
setIfMissing(`${PFX2}${v}-gradient-stop-3-position`, "--gradient-stop-end");
|
|
967
|
+
}
|
|
968
|
+
return out;
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
// src/editor/core/themes/migrations/2026-05-13-primary-to-brand.ts
|
|
973
|
+
var PALETTE_STEPS2 = ["100", "200", "300", "400", "500", "600", "700", "800", "850", "900", "950"];
|
|
974
|
+
var SURFACE_SUFFIXES = ["lowest", "lower", "low", "high", "higher", "highest"];
|
|
975
|
+
var BORDER_SUFFIXES = ["faint", "subtle", "medium", "strong"];
|
|
976
|
+
var TEXT_SUFFIXES = ["secondary", "tertiary", "muted", "disabled"];
|
|
977
|
+
var RENAME_MAP = (() => {
|
|
978
|
+
const m = {};
|
|
979
|
+
for (const step of PALETTE_STEPS2) m[`--color-primary-${step}`] = `--color-brand-${step}`;
|
|
980
|
+
m["--surface-primary"] = "--surface-brand";
|
|
981
|
+
for (const suf of SURFACE_SUFFIXES) m[`--surface-primary-${suf}`] = `--surface-brand-${suf}`;
|
|
982
|
+
m["--border-primary"] = "--border-brand";
|
|
983
|
+
for (const suf of BORDER_SUFFIXES) m[`--border-primary-${suf}`] = `--border-brand-${suf}`;
|
|
984
|
+
m["--text-primary-color"] = "--text-brand";
|
|
985
|
+
for (const suf of TEXT_SUFFIXES) m[`--text-primary-${suf}`] = `--text-brand-${suf}`;
|
|
986
|
+
return m;
|
|
987
|
+
})();
|
|
988
|
+
function renameToken(name) {
|
|
989
|
+
return RENAME_MAP[name] ?? name;
|
|
990
|
+
}
|
|
991
|
+
function renameKeys(rawVars) {
|
|
992
|
+
const out = {};
|
|
993
|
+
for (const [k, v] of Object.entries(rawVars)) {
|
|
994
|
+
out[renameToken(k)] = v;
|
|
995
|
+
}
|
|
996
|
+
return out;
|
|
997
|
+
}
|
|
998
|
+
function renameKeysAndValues(rawVars) {
|
|
999
|
+
const out = {};
|
|
1000
|
+
for (const [k, v] of Object.entries(rawVars)) {
|
|
1001
|
+
out[renameToken(k)] = renameToken(v);
|
|
1002
|
+
}
|
|
1003
|
+
return out;
|
|
1004
|
+
}
|
|
1005
|
+
var colorsAndTypeMigration_2026_05_13_primaryToBrand = {
|
|
1006
|
+
id: "2026-05-13-primary-to-brand-theme",
|
|
1007
|
+
fromVersion: 1,
|
|
1008
|
+
toVersion: 2,
|
|
1009
|
+
appliesTo: "colors-and-type",
|
|
1010
|
+
apply: renameKeys
|
|
1011
|
+
};
|
|
1012
|
+
var componentMigration_2026_05_13_primaryToBrand = {
|
|
1013
|
+
id: "2026-05-13-primary-to-brand-component",
|
|
1014
|
+
fromVersion: 5,
|
|
1015
|
+
toVersion: 6,
|
|
1016
|
+
appliesTo: "component-config",
|
|
1017
|
+
apply: renameKeysAndValues
|
|
1018
|
+
};
|
|
1019
|
+
|
|
1020
|
+
// src/editor/core/themes/migrations/2026-05-19-collapsiblesection-drop-frame-surface.ts
|
|
1021
|
+
function dropFrameSurface(rawVars, meta) {
|
|
1022
|
+
if (meta.component !== "collapsiblesection") return rawVars;
|
|
1023
|
+
const { "--collapsiblesection-container-frame-surface": _drop, ...rest } = rawVars;
|
|
1024
|
+
return rest;
|
|
1025
|
+
}
|
|
1026
|
+
var componentMigration_2026_05_19_collapsiblesectionDropFrameSurface = {
|
|
1027
|
+
id: "2026-05-19-collapsiblesection-drop-frame-surface",
|
|
1028
|
+
fromVersion: 6,
|
|
1029
|
+
toVersion: 7,
|
|
1030
|
+
appliesTo: "component-config",
|
|
1031
|
+
apply: dropFrameSurface
|
|
1032
|
+
};
|
|
1033
|
+
|
|
1034
|
+
// src/editor/core/themes/migrations/2026-05-19-sectiondivider-rich-gradient.ts
|
|
1035
|
+
var FLAT_RE = /^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-gradient-(angle|stop-[123]-(color|position))$/;
|
|
1036
|
+
var componentMigration_2026_05_19_sectiondividerRichGradient = {
|
|
1037
|
+
id: "2026-05-19-sectiondivider-rich-gradient",
|
|
1038
|
+
fromVersion: 7,
|
|
1039
|
+
toVersion: 8,
|
|
1040
|
+
appliesTo: "component-config",
|
|
1041
|
+
apply(rawVars, meta) {
|
|
1042
|
+
if (meta.component !== "sectiondivider") return { ...rawVars };
|
|
1043
|
+
const out = {};
|
|
1044
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1045
|
+
if (FLAT_RE.test(key)) continue;
|
|
1046
|
+
out[key] = value;
|
|
1047
|
+
}
|
|
1048
|
+
return out;
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
1051
|
+
|
|
1052
|
+
// src/editor/core/themes/migrations/2026-05-20-sectiondivider-slim-variants.ts
|
|
1053
|
+
var VARIANTS2 = ["lg", "md", "sm"];
|
|
1054
|
+
var SUFFIX_RENAMES = [
|
|
1055
|
+
[/-title-border-width$/, "-title-outline-width"],
|
|
1056
|
+
[/-title-stroke-color$/, "-title-outline-color"],
|
|
1057
|
+
[
|
|
1058
|
+
/^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-padding$/,
|
|
1059
|
+
"--sectiondivider-$1-spacing"
|
|
1060
|
+
]
|
|
1061
|
+
];
|
|
1062
|
+
function renameKeySuffix(key) {
|
|
1063
|
+
for (const [re, repl] of SUFFIX_RENAMES) {
|
|
1064
|
+
if (re.test(key)) return key.replace(re, repl);
|
|
1065
|
+
}
|
|
1066
|
+
return key;
|
|
1067
|
+
}
|
|
1068
|
+
function splitFamilyKey(key) {
|
|
1069
|
+
const m = key.match(/^--sectiondivider-(canvas|neutral|alternate|primary|accent|special)-(.+)$/);
|
|
1070
|
+
if (!m) return null;
|
|
1071
|
+
return { family: m[1], suffix: m[2] };
|
|
1072
|
+
}
|
|
1073
|
+
var componentMigration_2026_05_20_sectiondividerSlimVariants = {
|
|
1074
|
+
id: "2026-05-20-sectiondivider-slim-variants",
|
|
1075
|
+
fromVersion: 8,
|
|
1076
|
+
toVersion: 9,
|
|
1077
|
+
appliesTo: "component-config",
|
|
1078
|
+
apply(rawVars, meta) {
|
|
1079
|
+
if (meta.component !== "sectiondivider") return { ...rawVars };
|
|
1080
|
+
const out = {};
|
|
1081
|
+
const canvasValues = {};
|
|
1082
|
+
for (const [rawKey, value] of Object.entries(rawVars)) {
|
|
1083
|
+
const key = renameKeySuffix(rawKey);
|
|
1084
|
+
const parts = splitFamilyKey(key);
|
|
1085
|
+
if (!parts) {
|
|
1086
|
+
out[key] = value;
|
|
1087
|
+
continue;
|
|
1088
|
+
}
|
|
1089
|
+
if (parts.family !== "canvas") continue;
|
|
1090
|
+
canvasValues[parts.suffix] = value;
|
|
1091
|
+
}
|
|
1092
|
+
for (const suffix of Object.keys(canvasValues)) {
|
|
1093
|
+
for (const v of VARIANTS2) {
|
|
1094
|
+
out[`--sectiondivider-${v}-${suffix}`] = canvasValues[suffix];
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
return out;
|
|
1098
|
+
}
|
|
1099
|
+
};
|
|
1100
|
+
|
|
1101
|
+
// src/editor/core/themes/migrations/2026-05-21-sectiondivider-spacing-to-padding.ts
|
|
1102
|
+
var componentMigration_2026_05_21_sectiondividerSpacingToPadding = {
|
|
1103
|
+
id: "2026-05-21-sectiondivider-spacing-to-padding",
|
|
1104
|
+
fromVersion: 9,
|
|
1105
|
+
toVersion: 10,
|
|
1106
|
+
appliesTo: "component-config",
|
|
1107
|
+
apply(rawVars, meta) {
|
|
1108
|
+
if (meta.component !== "sectiondivider") return { ...rawVars };
|
|
1109
|
+
const out = {};
|
|
1110
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1111
|
+
const renamed = key.replace(
|
|
1112
|
+
/^--sectiondivider-(lg|md|sm)-spacing$/,
|
|
1113
|
+
"--sectiondivider-$1-padding"
|
|
1114
|
+
);
|
|
1115
|
+
out[renamed] = value;
|
|
1116
|
+
}
|
|
1117
|
+
return out;
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
|
|
1121
|
+
// src/editor/core/themes/migrations/2026-05-22-sectiondivider-intrinsics-to-css.ts
|
|
1122
|
+
var componentMigration_2026_05_22_sectiondividerIntrinsicsToCss = {
|
|
1123
|
+
id: "2026-05-22-sectiondivider-intrinsics-to-css",
|
|
1124
|
+
fromVersion: 10,
|
|
1125
|
+
toVersion: 11,
|
|
1126
|
+
appliesTo: "component-config",
|
|
1127
|
+
apply(rawVars, meta) {
|
|
1128
|
+
if (meta.component !== "sectiondivider") return { ...rawVars };
|
|
1129
|
+
const VARIANTS4 = ["lg", "md", "sm"];
|
|
1130
|
+
const prefix = "--sectiondivider-";
|
|
1131
|
+
const dropped = /* @__PURE__ */ new Set();
|
|
1132
|
+
for (const v of VARIANTS4) {
|
|
1133
|
+
dropped.add(`${prefix}${v}-show-eyebrow`);
|
|
1134
|
+
dropped.add(`${prefix}${v}-show-description`);
|
|
1135
|
+
dropped.add(`${prefix}${v}-show-hairline`);
|
|
1136
|
+
dropped.add(`${prefix}${v}-hairline`);
|
|
1137
|
+
dropped.add(`${prefix}${v}-eyebrow-uppercase`);
|
|
1138
|
+
}
|
|
1139
|
+
const out = {};
|
|
1140
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1141
|
+
if (dropped.has(key)) continue;
|
|
1142
|
+
out[key] = value;
|
|
1143
|
+
}
|
|
1144
|
+
for (const v of VARIANTS4) {
|
|
1145
|
+
const showEyebrow = rawVars[`${prefix}${v}-show-eyebrow`];
|
|
1146
|
+
if (showEyebrow !== void 0) {
|
|
1147
|
+
out[`${prefix}${v}-eyebrow-display`] = showEyebrow === "1" ? "block" : "none";
|
|
1148
|
+
}
|
|
1149
|
+
const showDesc = rawVars[`${prefix}${v}-show-description`];
|
|
1150
|
+
if (showDesc !== void 0) {
|
|
1151
|
+
out[`${prefix}${v}-description-display`] = showDesc === "1" ? "flex" : "none";
|
|
1152
|
+
}
|
|
1153
|
+
const showHair = rawVars[`${prefix}${v}-show-hairline`];
|
|
1154
|
+
const oldHair = rawVars[`${prefix}${v}-hairline`];
|
|
1155
|
+
const oldHairIsPos = typeof oldHair === "string" && oldHair !== "" && oldHair !== "off";
|
|
1156
|
+
let newHair;
|
|
1157
|
+
if (showHair === "") newHair = "none";
|
|
1158
|
+
else if (showHair === "1") newHair = oldHairIsPos ? oldHair : "above-label";
|
|
1159
|
+
else if (oldHair !== void 0) newHair = oldHairIsPos ? oldHair : "none";
|
|
1160
|
+
if (newHair !== void 0) {
|
|
1161
|
+
out[`${prefix}${v}-hairline`] = newHair;
|
|
1162
|
+
}
|
|
1163
|
+
const upper = rawVars[`${prefix}${v}-eyebrow-uppercase`];
|
|
1164
|
+
if (upper !== void 0) {
|
|
1165
|
+
out[`${prefix}${v}-eyebrow-text-transform`] = upper === "1" ? "uppercase" : "none";
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
return out;
|
|
1169
|
+
}
|
|
1170
|
+
};
|
|
1171
|
+
|
|
1172
|
+
// src/editor/core/themes/migrations/2026-05-24-segmentedcontrol-divider-inset.ts
|
|
1173
|
+
var componentMigration_2026_05_24_segmentedcontrolDividerInset = {
|
|
1174
|
+
id: "2026-05-24-segmentedcontrol-divider-inset",
|
|
1175
|
+
fromVersion: 11,
|
|
1176
|
+
toVersion: 12,
|
|
1177
|
+
appliesTo: "component-config",
|
|
1178
|
+
apply(rawVars, meta) {
|
|
1179
|
+
if (meta.component !== "segmentedcontrol") return { ...rawVars };
|
|
1180
|
+
const out = {};
|
|
1181
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1182
|
+
if (key === "--segmentedcontrol-divider-height") continue;
|
|
1183
|
+
out[key] = value;
|
|
1184
|
+
}
|
|
1185
|
+
return out;
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1189
|
+
// src/editor/core/themes/migrations/2026-05-24-promote-state-shared-tokens.ts
|
|
1190
|
+
var BUTTON_VARIANTS = ["primary", "secondary", "outline", "success", "danger", "warning"];
|
|
1191
|
+
var BUTTON_STATES = ["hover", "disabled"];
|
|
1192
|
+
var BUTTON_PROPS = ["padding", "radius", "border-width"];
|
|
1193
|
+
var buttonDeadKeys = new Set(
|
|
1194
|
+
BUTTON_VARIANTS.flatMap(
|
|
1195
|
+
(v) => BUTTON_STATES.flatMap(
|
|
1196
|
+
(s) => BUTTON_PROPS.map((p) => `--button-${v}-${s}-${p}`)
|
|
1197
|
+
)
|
|
1198
|
+
)
|
|
1199
|
+
);
|
|
1200
|
+
var segmentedcontrolDeadKeys = /* @__PURE__ */ new Set([
|
|
1201
|
+
"--segmentedcontrol-selected-icon-size",
|
|
1202
|
+
"--segmentedcontrol-option-hover-icon-size",
|
|
1203
|
+
"--segmentedcontrol-disabled-icon-size"
|
|
1204
|
+
]);
|
|
1205
|
+
var componentMigration_2026_05_24_promoteStateSharedTokens = {
|
|
1206
|
+
id: "2026-05-24-promote-state-shared-tokens",
|
|
1207
|
+
fromVersion: 12,
|
|
1208
|
+
toVersion: 13,
|
|
1209
|
+
appliesTo: "component-config",
|
|
1210
|
+
apply(rawVars, meta) {
|
|
1211
|
+
const dead = meta.component === "button" ? buttonDeadKeys : meta.component === "segmentedcontrol" ? segmentedcontrolDeadKeys : null;
|
|
1212
|
+
if (!dead) return { ...rawVars };
|
|
1213
|
+
const out = {};
|
|
1214
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1215
|
+
if (dead.has(key)) continue;
|
|
1216
|
+
out[key] = value;
|
|
1217
|
+
}
|
|
1218
|
+
return out;
|
|
1219
|
+
}
|
|
1220
|
+
};
|
|
1221
|
+
|
|
1222
|
+
// src/editor/core/themes/migrations/2026-05-24-progressbar-collapse-variants.ts
|
|
1223
|
+
var PRIMARY_PREFIX = "--progressbar-primary-";
|
|
1224
|
+
var NEW_PREFIX = "--progressbar-";
|
|
1225
|
+
var DROP_PREFIXES = [
|
|
1226
|
+
"--progressbar-success-",
|
|
1227
|
+
"--progressbar-warning-",
|
|
1228
|
+
"--progressbar-danger-",
|
|
1229
|
+
"--progressbar-info-"
|
|
1230
|
+
];
|
|
1231
|
+
var componentMigration_2026_05_24_progressbarCollapseVariants = {
|
|
1232
|
+
id: "2026-05-24-progressbar-collapse-variants",
|
|
1233
|
+
fromVersion: 13,
|
|
1234
|
+
toVersion: 14,
|
|
1235
|
+
appliesTo: "component-config",
|
|
1236
|
+
apply(rawVars, meta) {
|
|
1237
|
+
if (meta.component !== "progressbar") return { ...rawVars };
|
|
1238
|
+
const out = {};
|
|
1239
|
+
for (const [oldKey, value] of Object.entries(rawVars)) {
|
|
1240
|
+
if (DROP_PREFIXES.some((p) => oldKey.startsWith(p))) continue;
|
|
1241
|
+
const key = oldKey.startsWith(PRIMARY_PREFIX) ? NEW_PREFIX + oldKey.slice(PRIMARY_PREFIX.length) : oldKey;
|
|
1242
|
+
if (!(key in out)) out[key] = value;
|
|
1243
|
+
}
|
|
1244
|
+
return out;
|
|
1245
|
+
}
|
|
1246
|
+
};
|
|
1247
|
+
|
|
1248
|
+
// src/editor/core/themes/migrations/2026-05-24-collapsiblesection-drop-active-state.ts
|
|
1249
|
+
function dropActiveState(rawVars, meta) {
|
|
1250
|
+
if (meta.component !== "collapsiblesection") return rawVars;
|
|
1251
|
+
const re = /^--collapsiblesection-(chromeless|divider|container)-active-/;
|
|
1252
|
+
const out = {};
|
|
1253
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1254
|
+
if (re.test(key)) continue;
|
|
1255
|
+
out[key] = value;
|
|
1256
|
+
}
|
|
1257
|
+
return out;
|
|
1258
|
+
}
|
|
1259
|
+
var componentMigration_2026_05_24_collapsiblesectionDropActiveState = {
|
|
1260
|
+
id: "2026-05-24-collapsiblesection-drop-active-state",
|
|
1261
|
+
fromVersion: 14,
|
|
1262
|
+
toVersion: 15,
|
|
1263
|
+
appliesTo: "component-config",
|
|
1264
|
+
apply: dropActiveState
|
|
1265
|
+
};
|
|
1266
|
+
|
|
1267
|
+
// src/editor/core/themes/migrations/2026-05-25-cornerbadge-flatten-variants.ts
|
|
1268
|
+
var VARIANTS3 = ["primary", "accent", "neutral", "alternate", "canvas", "special", "success", "warning", "danger", "info"];
|
|
1269
|
+
var RE = new RegExp(`^--corner-badge-(${VARIANTS3.join("|")})-(.+)$`);
|
|
1270
|
+
var CURRENT_COLOR_PROPS = /* @__PURE__ */ new Set(["surface", "border", "text"]);
|
|
1271
|
+
function flattenVariants(rawVars, meta) {
|
|
1272
|
+
if (meta.component !== "cornerbadge") return rawVars;
|
|
1273
|
+
const out = {};
|
|
1274
|
+
const collected = /* @__PURE__ */ new Map();
|
|
1275
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1276
|
+
const m = key.match(RE);
|
|
1277
|
+
if (m) {
|
|
1278
|
+
const prop = m[2];
|
|
1279
|
+
if (CURRENT_COLOR_PROPS.has(prop)) {
|
|
1280
|
+
out[key] = value;
|
|
1281
|
+
continue;
|
|
1282
|
+
}
|
|
1283
|
+
if (!collected.has(prop)) collected.set(prop, value);
|
|
1284
|
+
continue;
|
|
1285
|
+
}
|
|
1286
|
+
out[key] = value;
|
|
1287
|
+
}
|
|
1288
|
+
for (const [prop, value] of collected) {
|
|
1289
|
+
const flatKey = `--corner-badge-${prop}`;
|
|
1290
|
+
if (!(flatKey in out)) out[flatKey] = value;
|
|
1291
|
+
}
|
|
1292
|
+
return out;
|
|
1293
|
+
}
|
|
1294
|
+
var componentMigration_2026_05_25_cornerbadgeFlattenVariants = {
|
|
1295
|
+
id: "2026-05-25-cornerbadge-flatten-variants",
|
|
1296
|
+
fromVersion: 15,
|
|
1297
|
+
toVersion: 16,
|
|
1298
|
+
appliesTo: "component-config",
|
|
1299
|
+
apply: flattenVariants
|
|
1300
|
+
};
|
|
1301
|
+
|
|
1302
|
+
// src/editor/core/themes/migrations/2026-05-26-drop-overlay-extra-stops.ts
|
|
1303
|
+
var DROPPED_TO_KEPT = {
|
|
1304
|
+
"--overlay-lowest": "--overlay-low",
|
|
1305
|
+
"--overlay-lower": "--overlay-low",
|
|
1306
|
+
"--overlay-higher": "--overlay-high",
|
|
1307
|
+
"--overlay-highest": "--overlay-high"
|
|
1308
|
+
};
|
|
1309
|
+
var colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops = {
|
|
1310
|
+
id: "2026-05-26-drop-overlay-extra-stops-theme",
|
|
1311
|
+
fromVersion: 2,
|
|
1312
|
+
toVersion: 3,
|
|
1313
|
+
appliesTo: "colors-and-type",
|
|
1314
|
+
apply(rawVars) {
|
|
1315
|
+
const out = {};
|
|
1316
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1317
|
+
if (key in DROPPED_TO_KEPT) continue;
|
|
1318
|
+
out[key] = value;
|
|
1319
|
+
}
|
|
1320
|
+
return out;
|
|
1321
|
+
}
|
|
1322
|
+
};
|
|
1323
|
+
var componentMigration_2026_05_26_dropOverlayExtraStops = {
|
|
1324
|
+
id: "2026-05-26-drop-overlay-extra-stops-component",
|
|
1325
|
+
fromVersion: 16,
|
|
1326
|
+
toVersion: 17,
|
|
1327
|
+
appliesTo: "component-config",
|
|
1328
|
+
apply(rawVars) {
|
|
1329
|
+
const out = {};
|
|
1330
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1331
|
+
out[key] = DROPPED_TO_KEPT[value] ?? value;
|
|
1332
|
+
}
|
|
1333
|
+
return out;
|
|
1334
|
+
}
|
|
1335
|
+
};
|
|
1336
|
+
|
|
1337
|
+
// src/editor/core/themes/migrations/2026-05-29-tabbar-indicator-thickness-to-per-state-width.ts
|
|
1338
|
+
var TABBAR_STATES = ["default", "hover", "active", "disabled"];
|
|
1339
|
+
var OLD_KEY = "--tabbar-bar-indicator-thickness";
|
|
1340
|
+
var FALLBACK = "--border-width-2";
|
|
1341
|
+
var componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth = {
|
|
1342
|
+
id: "2026-05-29-tabbar-indicator-thickness-to-per-state-width",
|
|
1343
|
+
fromVersion: 17,
|
|
1344
|
+
toVersion: 18,
|
|
1345
|
+
appliesTo: "component-config",
|
|
1346
|
+
apply(rawVars, meta) {
|
|
1347
|
+
if (meta.component !== "tabbar") return { ...rawVars };
|
|
1348
|
+
const seed = rawVars[OLD_KEY] ?? FALLBACK;
|
|
1349
|
+
const out = {};
|
|
1350
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1351
|
+
if (key === OLD_KEY) continue;
|
|
1352
|
+
out[key] = value;
|
|
1353
|
+
}
|
|
1354
|
+
for (const state of TABBAR_STATES) {
|
|
1355
|
+
const newKey = `--tabbar-${state}-indicator-border-width`;
|
|
1356
|
+
if (!(newKey in out)) out[newKey] = seed;
|
|
1357
|
+
}
|
|
1358
|
+
return out;
|
|
1359
|
+
}
|
|
1360
|
+
};
|
|
1361
|
+
|
|
1362
|
+
// src/editor/core/themes/migrations/2026-05-29-segmentedcontrol-small-divider-rename.ts
|
|
1363
|
+
var RENAMES = {
|
|
1364
|
+
"--segmentedcontrol-divider-small-thickness": "--segmentedcontrol-small-divider-thickness",
|
|
1365
|
+
"--segmentedcontrol-divider-small-inset": "--segmentedcontrol-small-divider-inset"
|
|
1366
|
+
};
|
|
1367
|
+
var componentMigration_2026_05_29_segmentedcontrolSmallDividerRename = {
|
|
1368
|
+
id: "2026-05-29-segmentedcontrol-small-divider-rename",
|
|
1369
|
+
fromVersion: 18,
|
|
1370
|
+
toVersion: 19,
|
|
1371
|
+
appliesTo: "component-config",
|
|
1372
|
+
apply(rawVars, meta) {
|
|
1373
|
+
if (meta.component !== "segmentedcontrol") return { ...rawVars };
|
|
1374
|
+
const out = {};
|
|
1375
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1376
|
+
out[RENAMES[key] ?? key] = value;
|
|
1377
|
+
}
|
|
1378
|
+
return out;
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
|
|
1382
|
+
// src/editor/core/themes/migrations/2026-05-29-toggle-derive-track-from-thumb.ts
|
|
1383
|
+
var componentMigration_2026_05_29_toggleDeriveTrackFromThumb = {
|
|
1384
|
+
id: "2026-05-29-toggle-derive-track-from-thumb",
|
|
1385
|
+
fromVersion: 19,
|
|
1386
|
+
toVersion: 20,
|
|
1387
|
+
appliesTo: "component-config",
|
|
1388
|
+
apply(rawVars, meta) {
|
|
1389
|
+
if (meta.component !== "toggle") return { ...rawVars };
|
|
1390
|
+
const out = {};
|
|
1391
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1392
|
+
if (key === "--toggle-track-width" || key === "--toggle-track-thickness") continue;
|
|
1393
|
+
out[key] = value;
|
|
1394
|
+
}
|
|
1395
|
+
if (!("--toggle-track-padding" in out)) {
|
|
1396
|
+
out["--toggle-track-padding"] = "--space-2";
|
|
1397
|
+
}
|
|
1398
|
+
return out;
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
1401
|
+
|
|
1402
|
+
// src/editor/core/themes/migrations/2026-08-13-drop-legacy-shape-space-keys.ts
|
|
1403
|
+
var DROPPED = /* @__PURE__ */ new Set([
|
|
1404
|
+
"--badge-trait-radius",
|
|
1405
|
+
"--badge-trait-padding",
|
|
1406
|
+
"--sectiondivider-padding",
|
|
1407
|
+
"--dialog-primary-default-radius",
|
|
1408
|
+
"--dialog-primary-default-padding",
|
|
1409
|
+
"--dialog-primary-hover-radius",
|
|
1410
|
+
"--dialog-primary-hover-padding",
|
|
1411
|
+
"--dialog-secondary-default-radius",
|
|
1412
|
+
"--dialog-secondary-default-padding",
|
|
1413
|
+
"--dialog-secondary-hover-radius",
|
|
1414
|
+
"--dialog-secondary-hover-padding"
|
|
1415
|
+
]);
|
|
1416
|
+
var colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys = {
|
|
1417
|
+
id: "2026-08-13-drop-legacy-shape-space-keys",
|
|
1418
|
+
fromVersion: 3,
|
|
1419
|
+
toVersion: 4,
|
|
1420
|
+
appliesTo: "colors-and-type",
|
|
1421
|
+
apply(rawVars) {
|
|
1422
|
+
const out = {};
|
|
1423
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1424
|
+
if (DROPPED.has(key)) continue;
|
|
1425
|
+
out[key] = value;
|
|
1426
|
+
}
|
|
1427
|
+
return out;
|
|
1428
|
+
}
|
|
1429
|
+
};
|
|
1430
|
+
|
|
1431
|
+
// src/editor/core/themes/migrations/2026-08-15-line-height-scale-rename.ts
|
|
1432
|
+
var RENAMED = {
|
|
1433
|
+
"--line-height-xs": "--line-height-none",
|
|
1434
|
+
"--line-height-sm": "--line-height-tighter",
|
|
1435
|
+
"--line-height-md": "--line-height-normal",
|
|
1436
|
+
"--line-height-lg": "--line-height-relaxed",
|
|
1437
|
+
"--line-height-xl": "--line-height-relaxed"
|
|
1438
|
+
};
|
|
1439
|
+
var REFERENCE = /--line-height-(?:xs|sm|md|lg|xl)(?![\w-])/g;
|
|
1440
|
+
function renameValues(rawVars) {
|
|
1441
|
+
const out = {};
|
|
1442
|
+
for (const [key, value] of Object.entries(rawVars)) {
|
|
1443
|
+
out[key] = typeof value === "string" ? value.replace(REFERENCE, (name) => RENAMED[name]) : value;
|
|
1444
|
+
}
|
|
1445
|
+
return out;
|
|
1446
|
+
}
|
|
1447
|
+
var colorsAndTypeMigration_2026_08_15_lineHeightScaleRename = {
|
|
1448
|
+
id: "2026-08-15-line-height-scale-rename-colors-and-type",
|
|
1449
|
+
fromVersion: 4,
|
|
1450
|
+
toVersion: 5,
|
|
1451
|
+
appliesTo: "colors-and-type",
|
|
1452
|
+
apply: renameValues
|
|
1453
|
+
};
|
|
1454
|
+
var componentMigration_2026_08_15_lineHeightScaleRename = {
|
|
1455
|
+
id: "2026-08-15-line-height-scale-rename-component",
|
|
1456
|
+
fromVersion: 20,
|
|
1457
|
+
toVersion: 21,
|
|
1458
|
+
appliesTo: "component-config",
|
|
1459
|
+
apply: renameValues
|
|
1460
|
+
};
|
|
1461
|
+
|
|
1462
|
+
// src/editor/core/themes/migrations/index.ts
|
|
1463
|
+
var MIGRATIONS = [
|
|
1464
|
+
colorsAndTypeMigration_2026_04_24_legacyKeysAndBgToCanvas,
|
|
1465
|
+
colorsAndTypeMigration_2026_05_13_primaryToBrand,
|
|
1466
|
+
componentMigration_2026_04_24_prefixAndSuffixRenames,
|
|
1467
|
+
componentMigration_2026_04_27_segmentedcontrolDisabledFlatten,
|
|
1468
|
+
componentMigration_2026_05_08_collapsiblesectionVariantNamespace,
|
|
1469
|
+
componentMigration_2026_05_08_collapsiblesectionFrameAndCleanup,
|
|
1470
|
+
componentMigration_2026_05_10_sectiondividerGradientStops,
|
|
1471
|
+
componentMigration_2026_05_13_primaryToBrand,
|
|
1472
|
+
componentMigration_2026_05_19_collapsiblesectionDropFrameSurface,
|
|
1473
|
+
componentMigration_2026_05_19_sectiondividerRichGradient,
|
|
1474
|
+
componentMigration_2026_05_20_sectiondividerSlimVariants,
|
|
1475
|
+
componentMigration_2026_05_21_sectiondividerSpacingToPadding,
|
|
1476
|
+
componentMigration_2026_05_22_sectiondividerIntrinsicsToCss,
|
|
1477
|
+
componentMigration_2026_05_24_segmentedcontrolDividerInset,
|
|
1478
|
+
componentMigration_2026_05_24_promoteStateSharedTokens,
|
|
1479
|
+
componentMigration_2026_05_24_progressbarCollapseVariants,
|
|
1480
|
+
componentMigration_2026_05_24_collapsiblesectionDropActiveState,
|
|
1481
|
+
componentMigration_2026_05_25_cornerbadgeFlattenVariants,
|
|
1482
|
+
colorsAndTypeMigration_2026_05_26_dropOverlayExtraStops,
|
|
1483
|
+
componentMigration_2026_05_26_dropOverlayExtraStops,
|
|
1484
|
+
componentMigration_2026_05_29_tabbarIndicatorThicknessToPerStateWidth,
|
|
1485
|
+
componentMigration_2026_05_29_segmentedcontrolSmallDividerRename,
|
|
1486
|
+
componentMigration_2026_05_29_toggleDeriveTrackFromThumb,
|
|
1487
|
+
colorsAndTypeMigration_2026_08_13_dropLegacyShapeSpaceKeys,
|
|
1488
|
+
colorsAndTypeMigration_2026_08_15_lineHeightScaleRename,
|
|
1489
|
+
componentMigration_2026_08_15_lineHeightScaleRename
|
|
1490
|
+
];
|
|
1491
|
+
function countFor(kind) {
|
|
1492
|
+
return MIGRATIONS.filter((m) => m.appliesTo === kind).length;
|
|
1493
|
+
}
|
|
1494
|
+
var CURRENT_COLORS_AND_TYPE_SCHEMA_VERSION = countFor("colors-and-type");
|
|
1495
|
+
var CURRENT_COMPONENT_SCHEMA_VERSION = countFor("component-config");
|
|
1496
|
+
function runMigrations(kind, fileVersion, rawVars, meta = {}) {
|
|
1497
|
+
const applicable = MIGRATIONS.filter((m) => m.appliesTo === kind && m.fromVersion >= fileVersion).sort((a, b) => a.toVersion - b.toVersion);
|
|
1498
|
+
let out = { ...rawVars };
|
|
1499
|
+
for (const m of applicable) {
|
|
1500
|
+
out = m.apply(out, meta);
|
|
1501
|
+
}
|
|
1502
|
+
return out;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
645
1505
|
// vite-plugin/files/versionedFileResourceServer.ts
|
|
646
1506
|
var import_fs = __toESM(require("fs"), 1);
|
|
647
1507
|
var import_path = __toESM(require("path"), 1);
|
|
@@ -801,8 +1661,141 @@ async function dispatch(req, res, routes) {
|
|
|
801
1661
|
return false;
|
|
802
1662
|
}
|
|
803
1663
|
|
|
1664
|
+
// src/editor/core/themes/migrateComponentConfig.ts
|
|
1665
|
+
function migrateComponentConfig(component, aliasesIn, rawConfig, fileVersion) {
|
|
1666
|
+
const stringPart = {};
|
|
1667
|
+
const objectPart = {};
|
|
1668
|
+
for (const [k, v] of Object.entries(aliasesIn)) {
|
|
1669
|
+
if (typeof v === "string") stringPart[k] = v;
|
|
1670
|
+
else objectPart[k] = v;
|
|
1671
|
+
}
|
|
1672
|
+
const configOut = {};
|
|
1673
|
+
for (const [k, v] of Object.entries(rawConfig ?? {})) {
|
|
1674
|
+
if (typeof v === "string") stringPart[k] = v;
|
|
1675
|
+
else configOut[k] = v;
|
|
1676
|
+
}
|
|
1677
|
+
if (component === "sectiondivider") {
|
|
1678
|
+
synthesizeSectionDividerGradients(stringPart, objectPart);
|
|
1679
|
+
}
|
|
1680
|
+
const migratedString = runMigrations("component-config", fileVersion, stringPart, { component });
|
|
1681
|
+
const migratedObject = component === "sectiondivider" ? renameSectionDividerObjectSlots(objectPart) : objectPart;
|
|
1682
|
+
return {
|
|
1683
|
+
aliases: { ...migratedString, ...migratedObject },
|
|
1684
|
+
config: configOut
|
|
1685
|
+
};
|
|
1686
|
+
}
|
|
1687
|
+
var FAMILIES = ["canvas", "neutral", "alternate", "primary", "accent", "special"];
|
|
1688
|
+
var SIZE_VARIANTS = ["lg", "md", "sm"];
|
|
1689
|
+
function renameSectionDividerObjectSlots(objectPart) {
|
|
1690
|
+
const canvasSourceKeys = [
|
|
1691
|
+
"--sectiondivider-canvas-background",
|
|
1692
|
+
"--sectiondivider-canvas-gradient",
|
|
1693
|
+
"--sectiondivider-color-canvas-background"
|
|
1694
|
+
];
|
|
1695
|
+
let canvasGradient;
|
|
1696
|
+
for (const key of canvasSourceKeys) {
|
|
1697
|
+
if (objectPart[key] !== void 0) {
|
|
1698
|
+
canvasGradient = objectPart[key];
|
|
1699
|
+
break;
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
const out = {};
|
|
1703
|
+
for (const [key, value] of Object.entries(objectPart)) {
|
|
1704
|
+
let isFamilyGradient = false;
|
|
1705
|
+
for (const f of FAMILIES) {
|
|
1706
|
+
if (key === `--sectiondivider-${f}-background` || key === `--sectiondivider-${f}-gradient` || key === `--sectiondivider-color-${f}-background`) {
|
|
1707
|
+
isFamilyGradient = true;
|
|
1708
|
+
break;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
if (isFamilyGradient) continue;
|
|
1712
|
+
out[key] = value;
|
|
1713
|
+
}
|
|
1714
|
+
if (canvasGradient !== void 0) {
|
|
1715
|
+
for (const v of SIZE_VARIANTS) {
|
|
1716
|
+
out[`--sectiondivider-${v}-background`] = canvasGradient;
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
return out;
|
|
1720
|
+
}
|
|
1721
|
+
var SECTIONDIVIDER_VARIANTS = ["canvas", "neutral", "alternate", "primary", "accent", "special"];
|
|
1722
|
+
function synthesizeSectionDividerGradients(stringPart, objectPart) {
|
|
1723
|
+
const GRADIENT_ANGLE_TOKENS = {
|
|
1724
|
+
"--gradient-angle-horizontal": 90,
|
|
1725
|
+
"--gradient-angle-vertical": 180,
|
|
1726
|
+
"--gradient-angle-diagonal": 135,
|
|
1727
|
+
"--gradient-angle-counter-diagonal": 45
|
|
1728
|
+
};
|
|
1729
|
+
const GRADIENT_STOP_POSITIONS = {
|
|
1730
|
+
"--gradient-stop-start": 0,
|
|
1731
|
+
"--gradient-stop-mid": 50,
|
|
1732
|
+
"--gradient-stop-end": 100
|
|
1733
|
+
};
|
|
1734
|
+
const parseAngle = (raw) => {
|
|
1735
|
+
if (!raw) return 135;
|
|
1736
|
+
if (raw.startsWith("--")) return GRADIENT_ANGLE_TOKENS[raw] ?? 135;
|
|
1737
|
+
const m = raw.match(/^(-?\d+(?:\.\d+)?)\s*deg$/i);
|
|
1738
|
+
return m ? parseFloat(m[1]) : 135;
|
|
1739
|
+
};
|
|
1740
|
+
const parsePosition = (raw, fallback) => {
|
|
1741
|
+
if (!raw) return fallback;
|
|
1742
|
+
if (raw.startsWith("--")) return GRADIENT_STOP_POSITIONS[raw] ?? fallback;
|
|
1743
|
+
const m = raw.match(/^(-?\d+(?:\.\d+)?)\s*%$/);
|
|
1744
|
+
return m ? parseFloat(m[1]) : fallback;
|
|
1745
|
+
};
|
|
1746
|
+
const parseStopColor = (raw) => {
|
|
1747
|
+
if (!raw) return null;
|
|
1748
|
+
if (raw.startsWith("--")) return { color: raw };
|
|
1749
|
+
const mix = raw.match(/^color-mix\(\s*in\s+srgb\s*,\s*var\((--[a-z0-9-]+)\)\s+([\d.]+)%\s*,\s*transparent\s*\)$/i);
|
|
1750
|
+
if (mix) return { color: mix[1], opacity: parseFloat(mix[2]) };
|
|
1751
|
+
return null;
|
|
1752
|
+
};
|
|
1753
|
+
for (const v of SECTIONDIVIDER_VARIANTS) {
|
|
1754
|
+
const slot = `--sectiondivider-${v}-gradient`;
|
|
1755
|
+
if (slot in objectPart) continue;
|
|
1756
|
+
const angleKey = `${slot}-angle`;
|
|
1757
|
+
const has1 = stringPart[`${slot}-stop-1-color`] !== void 0;
|
|
1758
|
+
const has2 = stringPart[`${slot}-stop-2-color`] !== void 0;
|
|
1759
|
+
const has3 = stringPart[`${slot}-stop-3-color`] !== void 0;
|
|
1760
|
+
if (!has1 && !has2 && !has3) continue;
|
|
1761
|
+
const stops = [];
|
|
1762
|
+
const positionDefaults = [0, 50, 100];
|
|
1763
|
+
for (let i = 1; i <= 3; i++) {
|
|
1764
|
+
const c = parseStopColor(stringPart[`${slot}-stop-${i}-color`]);
|
|
1765
|
+
if (!c) continue;
|
|
1766
|
+
const pos = parsePosition(stringPart[`${slot}-stop-${i}-position`], positionDefaults[i - 1]);
|
|
1767
|
+
stops.push({ position: pos, color: c.color, ...c.opacity !== void 0 ? { opacity: c.opacity } : {} });
|
|
1768
|
+
}
|
|
1769
|
+
if (stops.length < 2) continue;
|
|
1770
|
+
objectPart[slot] = {
|
|
1771
|
+
kind: "gradient",
|
|
1772
|
+
value: {
|
|
1773
|
+
type: "linear",
|
|
1774
|
+
angle: parseAngle(stringPart[angleKey]),
|
|
1775
|
+
stops
|
|
1776
|
+
}
|
|
1777
|
+
};
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
// src/editor/core/themes/themeTypes.ts
|
|
1782
|
+
var THEME_SCHEMA_VERSION = 4;
|
|
1783
|
+
|
|
1784
|
+
// src/editor/core/components/componentConfigKeys.ts
|
|
1785
|
+
var KNOWN_COMPONENT_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
1786
|
+
"--dialog-confirm-variant",
|
|
1787
|
+
"--dialog-cancel-variant",
|
|
1788
|
+
// SectionDivider per-variant `color-family` is editor metadata that drives
|
|
1789
|
+
// the family-swap rewrite on aliases. It is not a runtime CSS value, so it
|
|
1790
|
+
// stays in the config bucket. The other intrinsics (align, hairline,
|
|
1791
|
+
// eyebrow/description visibility, eyebrow text-transform) now flow through
|
|
1792
|
+
// the alias bucket as cascading CSS vars — see the 2026-05-22 migration.
|
|
1793
|
+
"--sectiondivider-lg-color-family",
|
|
1794
|
+
"--sectiondivider-md-color-family",
|
|
1795
|
+
"--sectiondivider-sm-color-family"
|
|
1796
|
+
]);
|
|
1797
|
+
|
|
804
1798
|
// vite-plugin/themes/normalizeTheme.ts
|
|
805
|
-
var THEME_SCHEMA_VERSION = 3;
|
|
806
1799
|
function asObject(value) {
|
|
807
1800
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
808
1801
|
}
|
|
@@ -824,10 +1817,41 @@ function migrateEmbeddedKey(src) {
|
|
|
824
1817
|
const { theme, ...rest } = src;
|
|
825
1818
|
return { ...rest, colorsAndType: theme };
|
|
826
1819
|
}
|
|
1820
|
+
function routeKnownConfigKeys(aliases, config) {
|
|
1821
|
+
const outAliases = { ...aliases };
|
|
1822
|
+
const outConfig = { ...config };
|
|
1823
|
+
for (const key of Object.keys(outAliases)) {
|
|
1824
|
+
if (!KNOWN_COMPONENT_CONFIG_KEYS.has(key)) continue;
|
|
1825
|
+
if (outConfig[key] === void 0) outConfig[key] = outAliases[key];
|
|
1826
|
+
delete outAliases[key];
|
|
1827
|
+
}
|
|
1828
|
+
return { aliases: outAliases, config: outConfig };
|
|
1829
|
+
}
|
|
1830
|
+
function migrateEmbeddedComponentConfig(comp, config, fileVersion) {
|
|
1831
|
+
const { schemaVersion: _entryStamp, aliases: rawAliases, config: rawConfig, ...rest } = config;
|
|
1832
|
+
const aliasesIn = asObject(rawAliases);
|
|
1833
|
+
if (!aliasesIn) {
|
|
1834
|
+
return rawConfig !== void 0 ? { ...rest, config: rawConfig } : rest;
|
|
1835
|
+
}
|
|
1836
|
+
const migratedConfig = migrateComponentConfig(
|
|
1837
|
+
comp,
|
|
1838
|
+
aliasesIn,
|
|
1839
|
+
asObject(rawConfig) ?? void 0,
|
|
1840
|
+
fileVersion
|
|
1841
|
+
);
|
|
1842
|
+
const split = routeKnownConfigKeys(migratedConfig.aliases, migratedConfig.config);
|
|
1843
|
+
const out = { ...rest, aliases: split.aliases };
|
|
1844
|
+
if (rawConfig !== void 0 || Object.keys(split.config).length > 0) {
|
|
1845
|
+
out.config = split.config;
|
|
1846
|
+
}
|
|
1847
|
+
return out;
|
|
1848
|
+
}
|
|
827
1849
|
function normalizeTheme(raw, resolvers) {
|
|
828
1850
|
const input = asObject(raw) ?? {};
|
|
829
1851
|
const migrated = input.schemaVersion !== THEME_SCHEMA_VERSION;
|
|
830
|
-
const
|
|
1852
|
+
const inputVersion = typeof input.schemaVersion === "number" ? input.schemaVersion : 0;
|
|
1853
|
+
const src = inputVersion < 3 ? migrateEmbeddedKey(input) : input;
|
|
1854
|
+
const componentSchemaVersion = typeof input.componentSchemaVersion === "number" ? input.componentSchemaVersion : 0;
|
|
831
1855
|
const dropped = [];
|
|
832
1856
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
833
1857
|
const embeddedColorsAndType = asObject(src.colorsAndType);
|
|
@@ -846,18 +1870,42 @@ function normalizeTheme(raw, resolvers) {
|
|
|
846
1870
|
const componentConfigs = {};
|
|
847
1871
|
for (const [comp, value] of Object.entries(asObject(src.componentConfigs) ?? {})) {
|
|
848
1872
|
const embedded = asObject(value);
|
|
1873
|
+
let resolvedConfig;
|
|
849
1874
|
if (embedded) {
|
|
850
|
-
|
|
1875
|
+
resolvedConfig = stripFileMarker(embedded);
|
|
1876
|
+
} else {
|
|
1877
|
+
const configName = asString(value, "default");
|
|
1878
|
+
const resolved = asObject(resolvers.readComponentConfig(comp, configName));
|
|
1879
|
+
if (!resolved) {
|
|
1880
|
+
dropped.push(`${comp}/${configName}`);
|
|
1881
|
+
continue;
|
|
1882
|
+
}
|
|
1883
|
+
resolvedConfig = stripFileMarker(resolved);
|
|
1884
|
+
}
|
|
1885
|
+
componentConfigs[comp] = migrateEmbeddedComponentConfig(comp, resolvedConfig, componentSchemaVersion);
|
|
1886
|
+
}
|
|
1887
|
+
const filled = { components: [], aliases: 0, orphans: 0 };
|
|
1888
|
+
for (const comp of resolvers.listComponentNames()) {
|
|
1889
|
+
const base = asObject(resolvers.readComponentConfig(comp, "default"));
|
|
1890
|
+
const baseAliases = base ? asObject(base.aliases) : null;
|
|
1891
|
+
if (!base || !baseAliases) continue;
|
|
1892
|
+
const entry = componentConfigs[comp];
|
|
1893
|
+
if (!entry) {
|
|
1894
|
+
const { schemaVersion: _standaloneStamp, ...rest } = stripFileMarker(base);
|
|
1895
|
+
componentConfigs[comp] = structuredClone(rest);
|
|
1896
|
+
filled.components.push(comp);
|
|
851
1897
|
continue;
|
|
852
1898
|
}
|
|
853
|
-
const
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
1899
|
+
const entryAliases = asObject(entry.aliases) ?? {};
|
|
1900
|
+
for (const key of Object.keys(baseAliases)) {
|
|
1901
|
+
if (key in entryAliases) continue;
|
|
1902
|
+
entryAliases[key] = structuredClone(baseAliases[key]);
|
|
1903
|
+
filled.aliases++;
|
|
1904
|
+
}
|
|
1905
|
+
entry.aliases = entryAliases;
|
|
1906
|
+
for (const key of Object.keys(entryAliases)) {
|
|
1907
|
+
if (!(key in baseAliases)) filled.orphans++;
|
|
859
1908
|
}
|
|
860
|
-
componentConfigs[comp] = stripFileMarker(resolved);
|
|
861
1909
|
}
|
|
862
1910
|
return {
|
|
863
1911
|
theme: {
|
|
@@ -866,10 +1914,12 @@ function normalizeTheme(raw, resolvers) {
|
|
|
866
1914
|
updatedAt: asString(src.updatedAt, now),
|
|
867
1915
|
schemaVersion: THEME_SCHEMA_VERSION,
|
|
868
1916
|
colorsAndType,
|
|
869
|
-
componentConfigs
|
|
1917
|
+
componentConfigs,
|
|
1918
|
+
componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION
|
|
870
1919
|
},
|
|
871
1920
|
dropped,
|
|
872
|
-
migrated
|
|
1921
|
+
migrated,
|
|
1922
|
+
filled
|
|
873
1923
|
};
|
|
874
1924
|
}
|
|
875
1925
|
|
|
@@ -1012,7 +2062,7 @@ function ensureScale(css, opts) {
|
|
|
1012
2062
|
lines.splice(insertAfter + 1, 0, ...block);
|
|
1013
2063
|
return lines.join("\n");
|
|
1014
2064
|
}
|
|
1015
|
-
function
|
|
2065
|
+
function renameToken2(css, oldName, newName) {
|
|
1016
2066
|
const defined = collectDefinedTokens(css);
|
|
1017
2067
|
if (!defined.has(oldName) || defined.has(newName)) return css;
|
|
1018
2068
|
const re = new RegExp(escapeRe(oldName) + "(?![a-z0-9-])", "gi");
|
|
@@ -1231,7 +2281,7 @@ var tokensCssMigration_2026_06_04_easingColorAndTypescaleAdditions = {
|
|
|
1231
2281
|
};
|
|
1232
2282
|
|
|
1233
2283
|
// vite-plugin/tokensCssMigrations/migrations/2026-07-20-line-height-rename.ts
|
|
1234
|
-
var
|
|
2284
|
+
var RENAMES2 = [
|
|
1235
2285
|
["--line-height-xs", "--line-height-none"],
|
|
1236
2286
|
["--line-height-sm", "--line-height-tighter"],
|
|
1237
2287
|
["--line-height-md", "--line-height-normal"],
|
|
@@ -1251,7 +2301,7 @@ var tokensCssMigration_2026_07_20_lineHeightRename = {
|
|
|
1251
2301
|
description: "Reshape --line-height-{xs..xl} to leading vocabulary (none/tightest/tighter/tight/normal/relaxed); retire the 2.0 slot",
|
|
1252
2302
|
apply(css) {
|
|
1253
2303
|
let out = css;
|
|
1254
|
-
for (const [oldName, newName] of
|
|
2304
|
+
for (const [oldName, newName] of RENAMES2) out = renameToken2(out, oldName, newName);
|
|
1255
2305
|
out = removeToken(out, "--line-height-xl");
|
|
1256
2306
|
out = ensureScale(out, {
|
|
1257
2307
|
anchorPrefixes: ["--line-height-", "--font-size-", "--font-weight-", "--font-"],
|
|
@@ -1419,8 +2469,29 @@ var PKG_VERSION = (() => {
|
|
|
1419
2469
|
})();
|
|
1420
2470
|
var BUNDLE_KIND_BY_VERSION = {
|
|
1421
2471
|
1: "manifest-bundle",
|
|
2472
|
+
3: "theme-bundle",
|
|
1422
2473
|
[THEME_SCHEMA_VERSION]: "theme-bundle"
|
|
1423
2474
|
};
|
|
2475
|
+
function extractAliasDeclarations(body) {
|
|
2476
|
+
const aliases = {};
|
|
2477
|
+
const re = /(--[a-z0-9-]+)\s*:\s*([^;]+);/gi;
|
|
2478
|
+
let m;
|
|
2479
|
+
while ((m = re.exec(body)) !== null) {
|
|
2480
|
+
const value = m[2].trim();
|
|
2481
|
+
const plain = value.match(/^var\((--[a-z0-9-]+)\)$/i);
|
|
2482
|
+
if (plain) {
|
|
2483
|
+
aliases[m[1]] = plain[1];
|
|
2484
|
+
continue;
|
|
2485
|
+
}
|
|
2486
|
+
if (parseColorOpacity(value)) {
|
|
2487
|
+
aliases[m[1]] = value;
|
|
2488
|
+
continue;
|
|
2489
|
+
}
|
|
2490
|
+
const gradient = parseGradientValue(value);
|
|
2491
|
+
if (gradient) aliases[m[1]] = { kind: "gradient", value: gradient };
|
|
2492
|
+
}
|
|
2493
|
+
return aliases;
|
|
2494
|
+
}
|
|
1424
2495
|
function themeFileApi(opts) {
|
|
1425
2496
|
const dataDirs = resolveDataDirs({
|
|
1426
2497
|
dataDir: opts.dataDir,
|
|
@@ -1597,6 +2668,7 @@ function themeFileApi(opts) {
|
|
|
1597
2668
|
const overrides = [];
|
|
1598
2669
|
const defaultAliases = defaultCfg.aliases ?? {};
|
|
1599
2670
|
for (const [varName, semanticValue] of Object.entries(prodCfg.aliases ?? {})) {
|
|
2671
|
+
if (!(varName in defaultAliases)) continue;
|
|
1600
2672
|
if (!aliasValuesEqual(defaultAliases[varName], semanticValue)) {
|
|
1601
2673
|
overrides.push([varName, semanticValue]);
|
|
1602
2674
|
}
|
|
@@ -1659,18 +2731,6 @@ function themeFileApi(opts) {
|
|
|
1659
2731
|
import_fs4.default.writeFileSync(FONTS_CSS_PATH, content);
|
|
1660
2732
|
console.log(`[syncFontsToCss] Wrote ${sources.length} source(s) into ${import_path4.default.basename(FONTS_CSS_PATH)}`);
|
|
1661
2733
|
}
|
|
1662
|
-
function extractAliasDeclarations(body) {
|
|
1663
|
-
const aliases = {};
|
|
1664
|
-
const re = /(--[a-z0-9-]+)\s*:\s*([^;]+);/gi;
|
|
1665
|
-
let m;
|
|
1666
|
-
while ((m = re.exec(body)) !== null) {
|
|
1667
|
-
const value = m[2].trim();
|
|
1668
|
-
const plain = value.match(/^var\((--[a-z0-9-]+)\)$/i);
|
|
1669
|
-
if (plain) aliases[m[1]] = plain[1];
|
|
1670
|
-
else if (parseColorOpacity(value)) aliases[m[1]] = value;
|
|
1671
|
-
}
|
|
1672
|
-
return aliases;
|
|
1673
|
-
}
|
|
1674
2734
|
function componentNameFromFile(filePath) {
|
|
1675
2735
|
return import_path4.default.basename(filePath, ".svelte").toLowerCase();
|
|
1676
2736
|
}
|
|
@@ -1746,17 +2806,10 @@ ${lines.join("\n")}
|
|
|
1746
2806
|
r.ensureDir();
|
|
1747
2807
|
const defaultPath = r.filePath("default");
|
|
1748
2808
|
const sourceStat = import_fs4.default.statSync(sourcePath);
|
|
1749
|
-
|
|
1750
|
-
const defaultStat = import_fs4.default.statSync(defaultPath);
|
|
1751
|
-
if (defaultStat.mtimeMs >= sourceStat.mtimeMs) return;
|
|
1752
|
-
}
|
|
1753
|
-
const source = import_fs4.default.readFileSync(sourcePath, "utf-8");
|
|
1754
|
-
const body = extractGlobalRootBody(source);
|
|
1755
|
-
const aliases = extractAliasDeclarations(body);
|
|
1756
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1757
|
-
let createdAt = now;
|
|
2809
|
+
let createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1758
2810
|
let existingUpdatedAt;
|
|
1759
2811
|
let existingAliases;
|
|
2812
|
+
let existingSchemaVersion;
|
|
1760
2813
|
if (import_fs4.default.existsSync(defaultPath)) {
|
|
1761
2814
|
try {
|
|
1762
2815
|
const existing = JSON.parse(import_fs4.default.readFileSync(defaultPath, "utf-8"));
|
|
@@ -1765,25 +2818,29 @@ ${lines.join("\n")}
|
|
|
1765
2818
|
if (existing.aliases && typeof existing.aliases === "object") {
|
|
1766
2819
|
existingAliases = existing.aliases;
|
|
1767
2820
|
}
|
|
2821
|
+
if (typeof existing.schemaVersion === "number") existingSchemaVersion = existing.schemaVersion;
|
|
1768
2822
|
} catch {
|
|
1769
2823
|
}
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
if (val !== null && typeof val === "object" && !(token in aliases)) {
|
|
1774
|
-
aliases[token] = val;
|
|
1775
|
-
}
|
|
2824
|
+
const defaultStat = import_fs4.default.statSync(defaultPath);
|
|
2825
|
+
if (defaultStat.mtimeMs >= sourceStat.mtimeMs && existingSchemaVersion === CURRENT_COMPONENT_SCHEMA_VERSION) {
|
|
2826
|
+
return;
|
|
1776
2827
|
}
|
|
1777
2828
|
}
|
|
2829
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2830
|
+
const source = import_fs4.default.readFileSync(sourcePath, "utf-8");
|
|
2831
|
+
const body = extractGlobalRootBody(source);
|
|
2832
|
+
const aliases = extractAliasDeclarations(body);
|
|
1778
2833
|
const aliasesUnchanged = existingAliases !== void 0 && JSON.stringify(existingAliases) === JSON.stringify(aliases);
|
|
2834
|
+
const schemaStampCurrent = existingSchemaVersion === CURRENT_COMPONENT_SCHEMA_VERSION;
|
|
1779
2835
|
const defaultConfig = {
|
|
1780
2836
|
name: "default",
|
|
1781
2837
|
component: comp,
|
|
1782
2838
|
createdAt,
|
|
1783
2839
|
updatedAt: aliasesUnchanged && existingUpdatedAt ? existingUpdatedAt : now,
|
|
1784
|
-
aliases
|
|
2840
|
+
aliases,
|
|
2841
|
+
schemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION
|
|
1785
2842
|
};
|
|
1786
|
-
if (aliasesUnchanged && existingUpdatedAt) {
|
|
2843
|
+
if (aliasesUnchanged && schemaStampCurrent && existingUpdatedAt) {
|
|
1787
2844
|
const t = /* @__PURE__ */ new Date();
|
|
1788
2845
|
import_fs4.default.utimesSync(defaultPath, t, t);
|
|
1789
2846
|
return;
|
|
@@ -1831,6 +2888,7 @@ ${lines.join("\n")}
|
|
|
1831
2888
|
const diskThemeResolvers = {
|
|
1832
2889
|
readColorsAndType: (name) => colorsAndTypeResource.readJson(sanitizeFileName(name)),
|
|
1833
2890
|
readComponentConfig: (comp, name) => readComponentConfig(comp, sanitizeFileName(name)),
|
|
2891
|
+
listComponentNames,
|
|
1834
2892
|
normalizeColorsAndType: (colorsAndType) => normalizeColorsAndType(colorsAndType)
|
|
1835
2893
|
};
|
|
1836
2894
|
function readTheme(fileName) {
|
|
@@ -1856,7 +2914,7 @@ ${lines.join("\n")}
|
|
|
1856
2914
|
return "corrupt";
|
|
1857
2915
|
}
|
|
1858
2916
|
function notAThemeError(fileName) {
|
|
1859
|
-
return `"${fileName}" is a colors-and-type file, not a theme. Before 0.48 those lived in themes/; move it to ${import_path4.default.basename(COLORS_AND_TYPE_DIR)}/ or delete it.`;
|
|
2917
|
+
return `"${fileName}" is a colors-and-type file, not a theme. Before 0.48 those lived in themes/; move it to ${import_path4.default.basename(COLORS_AND_TYPE_DIR)}/ or delete it. To build a theme, use the theme generator skill "generate-theme".`;
|
|
1860
2918
|
}
|
|
1861
2919
|
function respondUnreadableTheme(res, fileName, missingError) {
|
|
1862
2920
|
switch (unreadableThemeReason(fileName)) {
|
|
@@ -1918,19 +2976,26 @@ ${lines.join("\n")}
|
|
|
1918
2976
|
const componentConfigs = {};
|
|
1919
2977
|
for (const comp of listComponentNames()) {
|
|
1920
2978
|
const cfg = readComponentConfig(comp, "default");
|
|
1921
|
-
if (cfg)
|
|
2979
|
+
if (cfg) {
|
|
2980
|
+
const { schemaVersion: _standaloneStamp, ...rest } = cfg;
|
|
2981
|
+
componentConfigs[comp] = rest;
|
|
2982
|
+
}
|
|
1922
2983
|
}
|
|
1923
|
-
|
|
2984
|
+
const contentUnchanged = JSON.stringify(existing?.colorsAndType) === JSON.stringify(colorsAndType) && JSON.stringify(existing?.componentConfigs) === JSON.stringify(componentConfigs);
|
|
2985
|
+
if (existing?.schemaVersion === THEME_SCHEMA_VERSION && existing?.componentSchemaVersion === CURRENT_COMPONENT_SCHEMA_VERSION && contentUnchanged) {
|
|
1924
2986
|
return;
|
|
1925
2987
|
}
|
|
1926
2988
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1927
2989
|
writeTheme("default", {
|
|
1928
2990
|
name: "Motion Proto",
|
|
1929
2991
|
createdAt: typeof existing?.createdAt === "string" ? existing.createdAt : now,
|
|
1930
|
-
|
|
2992
|
+
// A stamp-only rewrite (componentSchemaVersion catching up) is not a
|
|
2993
|
+
// content change, so it doesn't bump this the way a real edit would.
|
|
2994
|
+
updatedAt: contentUnchanged && typeof existing?.updatedAt === "string" ? existing.updatedAt : now,
|
|
1931
2995
|
schemaVersion: THEME_SCHEMA_VERSION,
|
|
1932
2996
|
colorsAndType,
|
|
1933
|
-
componentConfigs
|
|
2997
|
+
componentConfigs,
|
|
2998
|
+
componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION
|
|
1934
2999
|
});
|
|
1935
3000
|
}
|
|
1936
3001
|
function ensureThemesDir(warn) {
|
|
@@ -1962,14 +3027,24 @@ ${lines.join("\n")}
|
|
|
1962
3027
|
if (!shipped) return null;
|
|
1963
3028
|
return { data: normalizeColorsAndType(shipped), source: "default" };
|
|
1964
3029
|
}
|
|
3030
|
+
const loggedMissingThemeEntries = /* @__PURE__ */ new Set();
|
|
3031
|
+
function resolveComponentConfigOrDefault(comp, theme) {
|
|
3032
|
+
const embedded = theme?.componentConfigs[comp];
|
|
3033
|
+
if (embedded) return { ...embedded, component: comp };
|
|
3034
|
+
if (!loggedMissingThemeEntries.has(comp)) {
|
|
3035
|
+
loggedMissingThemeEntries.add(comp);
|
|
3036
|
+
console.warn(
|
|
3037
|
+
`[live-tokens] "${comp}" has no entry in the open theme; resolving from its shipped default.`
|
|
3038
|
+
);
|
|
3039
|
+
}
|
|
3040
|
+
return readComponentConfig(comp, "default");
|
|
3041
|
+
}
|
|
1965
3042
|
function resolveLiveComponentConfig(comp, theme) {
|
|
1966
3043
|
const working = componentResource(comp).readWorking();
|
|
1967
3044
|
if (working !== null) return { data: working, source: "working" };
|
|
1968
|
-
const
|
|
1969
|
-
if (embedded) return { data: { ...embedded, component: comp }, source: "theme" };
|
|
1970
|
-
const cfg = readComponentConfig(comp, "default");
|
|
3045
|
+
const cfg = resolveComponentConfigOrDefault(comp, theme);
|
|
1971
3046
|
if (!cfg) return null;
|
|
1972
|
-
return { data: cfg, source: "
|
|
3047
|
+
return { data: cfg, source: "theme" };
|
|
1973
3048
|
}
|
|
1974
3049
|
function resolveSavedColorsAndType(theme) {
|
|
1975
3050
|
if (theme?.colorsAndType) return theme.colorsAndType;
|
|
@@ -1977,9 +3052,7 @@ ${lines.join("\n")}
|
|
|
1977
3052
|
return shipped ? normalizeColorsAndType(shipped) : null;
|
|
1978
3053
|
}
|
|
1979
3054
|
function resolveSavedComponentConfig(comp, theme) {
|
|
1980
|
-
|
|
1981
|
-
if (embedded) return { ...embedded, component: comp };
|
|
1982
|
-
return readComponentConfig(comp, "default");
|
|
3055
|
+
return resolveComponentConfigOrDefault(comp, theme);
|
|
1983
3056
|
}
|
|
1984
3057
|
function sameJsonValue(a, b) {
|
|
1985
3058
|
if (a === null || b === null) return a === b;
|
|
@@ -2015,26 +3088,9 @@ ${lines.join("\n")}
|
|
|
2015
3088
|
if (entry.isDirectory()) componentResource(entry.name).clearWorking();
|
|
2016
3089
|
}
|
|
2017
3090
|
}
|
|
2018
|
-
function formatAliasGradient(v) {
|
|
2019
|
-
const stopColor = (s) => {
|
|
2020
|
-
const base = s.color.startsWith("--") ? `var(${s.color})` : s.color;
|
|
2021
|
-
const opacity = s.opacity ?? 100;
|
|
2022
|
-
return opacity >= 100 ? base : `color-mix(in srgb, ${base} ${opacity}%, transparent)`;
|
|
2023
|
-
};
|
|
2024
|
-
if (v.type === "none") return "transparent";
|
|
2025
|
-
if (v.type === "solid") {
|
|
2026
|
-
const first = v.stops[0];
|
|
2027
|
-
if (!first) return "transparent";
|
|
2028
|
-
return stopColor(first);
|
|
2029
|
-
}
|
|
2030
|
-
const stops = v.stops.map((s) => `${stopColor(s)} ${s.position}%`).join(", ");
|
|
2031
|
-
if (v.type === "linear") return `linear-gradient(${v.angle}deg, ${stops})`;
|
|
2032
|
-
const radial = v.radius && v.radius > 0 ? `circle ${v.radius}px at center` : "circle";
|
|
2033
|
-
return `radial-gradient(${radial}, ${stops})`;
|
|
2034
|
-
}
|
|
2035
3091
|
function aliasValueToCss(v) {
|
|
2036
3092
|
if (typeof v === "string") return v.startsWith("--") ? `var(${v})` : v;
|
|
2037
|
-
return
|
|
3093
|
+
return formatGradientValue(v.value);
|
|
2038
3094
|
}
|
|
2039
3095
|
function aliasValuesEqual(a, b) {
|
|
2040
3096
|
if (a === void 0 || b === void 0) return a === b;
|
|
@@ -2184,13 +3240,9 @@ ${lines.join("\n")}
|
|
|
2184
3240
|
}
|
|
2185
3241
|
}
|
|
2186
3242
|
async function handleListComponents({ res }) {
|
|
2187
|
-
const theme = activeTheme();
|
|
2188
3243
|
const components = listComponentNames().map((comp) => ({
|
|
2189
3244
|
name: comp,
|
|
2190
|
-
|
|
2191
|
-
// down, and the door only has to say where each component's live config
|
|
2192
|
-
// comes from.
|
|
2193
|
-
source: componentResource(comp).hasWorking() ? "working" : theme?.componentConfigs[comp] ? "theme" : "default"
|
|
3245
|
+
source: componentResource(comp).hasWorking() ? "working" : "theme"
|
|
2194
3246
|
}));
|
|
2195
3247
|
jsonResponse(res, 200, { components });
|
|
2196
3248
|
}
|
|
@@ -2201,6 +3253,7 @@ ${lines.join("\n")}
|
|
|
2201
3253
|
}
|
|
2202
3254
|
async function handleGetComponentActive({ params, res }) {
|
|
2203
3255
|
const [comp] = params;
|
|
3256
|
+
if (rejectUnknownComponent(res, comp)) return;
|
|
2204
3257
|
const resolved = resolveLiveComponentConfig(comp, activeTheme());
|
|
2205
3258
|
if (!resolved) {
|
|
2206
3259
|
jsonResponse(res, 404, { error: "Active config not found" });
|
|
@@ -2447,9 +3500,11 @@ ${lines.join("\n")}
|
|
|
2447
3500
|
respondUnreadableTheme(res, fileName, "Theme not found");
|
|
2448
3501
|
return;
|
|
2449
3502
|
}
|
|
2450
|
-
const { theme } = read;
|
|
3503
|
+
const { theme, filled } = read;
|
|
2451
3504
|
if (!theme.colorsAndType) {
|
|
2452
|
-
jsonResponse(res, 422, {
|
|
3505
|
+
jsonResponse(res, 422, {
|
|
3506
|
+
error: 'This theme carries no colors and type. Build one with the theme generator skill "generate-theme".'
|
|
3507
|
+
});
|
|
2453
3508
|
return;
|
|
2454
3509
|
}
|
|
2455
3510
|
clearAllWorking();
|
|
@@ -2473,7 +3528,8 @@ ${lines.join("\n")}
|
|
|
2473
3528
|
_source: resolvedColorsAndType.source
|
|
2474
3529
|
},
|
|
2475
3530
|
componentConfigs: resolvedConfigs,
|
|
2476
|
-
skippedComponents
|
|
3531
|
+
skippedComponents,
|
|
3532
|
+
filled
|
|
2477
3533
|
});
|
|
2478
3534
|
}
|
|
2479
3535
|
async function handleExportTheme({ params, res }) {
|
|
@@ -2528,10 +3584,27 @@ ${lines.join("\n")}
|
|
|
2528
3584
|
}
|
|
2529
3585
|
const bundleResolvers = {
|
|
2530
3586
|
readColorsAndType: () => bundle.theme,
|
|
2531
|
-
|
|
3587
|
+
// A named ref resolves inside the bundle only — a v1 bundle's
|
|
3588
|
+
// `${comp}/${name}` map is itself the sender's data, and a stale name
|
|
3589
|
+
// must still land in `dropped` rather than quietly picking up this
|
|
3590
|
+
// install's copy. But `'default'` never named a bundled entry; v1
|
|
3591
|
+
// spelled "no override" that way (normalizeTheme.ts's pointer-
|
|
3592
|
+
// resolution loop treats it identically), so it always meant *this
|
|
3593
|
+
// install's* default, not something the bundle carries. The
|
|
3594
|
+
// completeness fill (Wave 2 of docs/plans/theme-completeness.md) relies
|
|
3595
|
+
// on that fall-through: without it, `readComponentConfig(comp,
|
|
3596
|
+
// 'default')` answers undefined for every component (no bundle ever
|
|
3597
|
+
// carries a `<comp>/default` entry), the fill loop no-ops 25 times, and
|
|
3598
|
+
// an incomplete bundle stays incomplete forever — exactly the drift RJC
|
|
3599
|
+
// 10 exists to prevent.
|
|
3600
|
+
readComponentConfig: (comp, name) => bundle.componentConfigs?.[`${comp}/${name}`] ?? (name === "default" ? readComponentConfig(comp, "default") : void 0),
|
|
3601
|
+
// Installed components are a property of this install, not of the
|
|
3602
|
+
// bundle being imported, so the completeness fill (Wave 2) uses the
|
|
3603
|
+
// same list the disk resolver does.
|
|
3604
|
+
listComponentNames,
|
|
2532
3605
|
normalizeColorsAndType: (colorsAndType) => normalizeColorsAndType(colorsAndType)
|
|
2533
3606
|
};
|
|
2534
|
-
const { theme, dropped } = normalizeTheme(bundle.manifest, bundleResolvers);
|
|
3607
|
+
const { theme, dropped, filled } = normalizeTheme(bundle.manifest, bundleResolvers);
|
|
2535
3608
|
if (theme.colorsAndType) theme.colorsAndType = normalizeColorsAndType(theme.colorsAndType);
|
|
2536
3609
|
if (!theme.colorsAndType) {
|
|
2537
3610
|
jsonResponse(res, 400, { error: "Bundle carries no theme" });
|
|
@@ -2552,7 +3625,8 @@ ${lines.join("\n")}
|
|
|
2552
3625
|
ok: true,
|
|
2553
3626
|
theme: finalName,
|
|
2554
3627
|
renames,
|
|
2555
|
-
dropped
|
|
3628
|
+
dropped,
|
|
3629
|
+
filled
|
|
2556
3630
|
});
|
|
2557
3631
|
}
|
|
2558
3632
|
async function handleAdoptLook({ res }) {
|