@motion-proto/live-tokens 0.47.1 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/live-tokens-adjust-shape-space/SKILL.md +68 -0
- package/.claude/skills/live-tokens-create-component/SKILL.md +2 -2
- package/.claude/skills/live-tokens-generate-theme/SKILL.md +152 -0
- package/CHANGELOG.md +270 -0
- package/README.md +37 -26
- package/bin/adjust.mjs +254 -0
- package/bin/cli.mjs +94 -7
- package/bin/generate-theme.mjs +251 -0
- package/bin/migrate.mjs +95 -6
- package/dist-plugin/adjust/index.cjs +259 -0
- package/dist-plugin/adjust/index.d.cts +45 -0
- package/dist-plugin/adjust/index.d.ts +45 -0
- package/dist-plugin/adjust/index.js +176 -0
- package/dist-plugin/{chunk-H4TRUINI.js → chunk-44RSTAII.js} +0 -48
- package/dist-plugin/chunk-6OZFXIQI.js +316 -0
- package/dist-plugin/chunk-76TFDTJO.js +556 -0
- package/dist-plugin/chunk-D3ZVKOR4.js +52 -0
- package/dist-plugin/dataPaths-DBN0RPuT.d.cts +54 -0
- package/dist-plugin/dataPaths-DBN0RPuT.d.ts +54 -0
- package/dist-plugin/generateColorsAndType/index.cjs +1781 -0
- package/dist-plugin/generateColorsAndType/index.d.cts +81 -0
- package/dist-plugin/generateColorsAndType/index.d.ts +81 -0
- package/dist-plugin/generateColorsAndType/index.js +1210 -0
- package/dist-plugin/index.cjs +849 -531
- package/dist-plugin/index.d.cts +3 -2
- package/dist-plugin/index.d.ts +3 -2
- package/dist-plugin/index.js +658 -1132
- package/dist-plugin/migrateData/index.cjs +728 -0
- package/dist-plugin/migrateData/index.d.cts +60 -0
- package/dist-plugin/migrateData/index.d.ts +60 -0
- package/dist-plugin/migrateData/index.js +348 -0
- package/dist-plugin/themeTypes-DMHZOnUn.d.cts +211 -0
- package/dist-plugin/themeTypes-DMHZOnUn.d.ts +211 -0
- package/dist-plugin/tokensCssMigrations/index.cjs +2 -1
- package/dist-plugin/tokensCssMigrations/index.d.cts +3 -15
- package/dist-plugin/tokensCssMigrations/index.d.ts +3 -15
- package/dist-plugin/tokensCssMigrations/index.js +4 -2
- package/package.json +18 -4
- package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +183 -158
- package/src/editor/component-editor/scaffolding/ComponentFileMenu.svelte +0 -4
- package/src/editor/component-editor/scaffolding/SaveAsDialog.svelte +4 -4
- package/src/editor/component-editor/scaffolding/TokenLayout.svelte +2 -59
- package/src/editor/component-editor/scaffolding/VariantGroup.svelte +1 -1
- package/src/editor/core/components/adjustAliases.ts +180 -0
- package/src/editor/core/components/aliasKinds.ts +73 -0
- package/src/editor/core/components/componentConfigService.ts +26 -38
- package/src/editor/core/flashStatus.ts +1 -1
- package/src/editor/core/fonts/fontMigration.ts +13 -13
- package/src/editor/core/fonts/fontPairing.ts +35 -0
- package/src/editor/core/palettes/paletteDerivation.ts +83 -13
- package/src/editor/core/preview/lookPreview.ts +141 -0
- package/src/editor/core/productionPulse.ts +34 -21
- package/src/editor/core/storage/files/versionedFileResourceClient.ts +18 -45
- package/src/editor/core/store/editorConfigStore.ts +2 -2
- package/src/editor/core/store/editorPersistence.ts +0 -1
- package/src/editor/core/store/editorStore.ts +114 -51
- package/src/editor/core/store/editorTypes.ts +0 -1
- package/src/editor/core/store/gradientSource.ts +2 -2
- package/src/editor/core/themes/colorsAndTypeService.ts +95 -0
- package/src/editor/core/themes/generateColorsAndType.ts +433 -0
- package/src/editor/core/themes/loadRows.ts +64 -0
- package/src/editor/core/themes/lookSummary.ts +75 -0
- package/src/editor/core/themes/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +3 -3
- package/src/editor/core/themes/migrations/2026-05-13-primary-to-brand.ts +2 -2
- package/src/editor/core/themes/migrations/2026-05-26-drop-overlay-extra-stops.ts +3 -3
- package/src/editor/core/themes/migrations/2026-08-13-drop-legacy-shape-space-keys.ts +38 -0
- package/src/editor/core/themes/migrations/2026-08-15-line-height-scale-rename.ts +57 -0
- package/src/editor/core/themes/migrations/index.ts +19 -11
- package/src/editor/core/themes/slices/components.ts +4 -4
- package/src/editor/core/themes/slices/fonts.ts +1 -1
- package/src/editor/core/themes/slices/gradients.ts +22 -0
- package/src/editor/core/themes/slices/palettes.ts +2 -2
- package/src/editor/core/themes/themeInit.ts +21 -29
- package/src/editor/core/themes/themeService.ts +218 -78
- package/src/editor/core/themes/themeTypes.ts +94 -51
- package/src/editor/docs/Docs.svelte +1 -0
- package/src/editor/docs/chapters.ts +1 -0
- package/src/editor/docs/content/01-overview.md +1 -1
- package/src/editor/docs/content/editing-tokens.md +6 -6
- package/src/editor/docs/content/getting-started.md +9 -7
- package/src/editor/docs/content/themes-workflow.md +74 -34
- package/src/editor/docs/content/where-themes-live.md +61 -0
- package/src/editor/docs/content.generated.ts +5 -4
- package/src/editor/index.ts +27 -27
- package/src/editor/pages/ComponentEditorPage.svelte +2 -2
- package/src/editor/pages/EditorShell.svelte +4 -30
- package/src/editor/ui/FileLoadList.svelte +67 -7
- package/src/editor/ui/GradientEditor.svelte +3 -3
- package/src/editor/ui/ThemePanel.svelte +1067 -0
- package/src/editor/ui/UIDialog.svelte +11 -9
- package/src/editor/ui/index.ts +4 -2
- package/src/live-tokens/data/colors-and-type/autumn.json +2490 -0
- package/src/live-tokens/data/{themes → colors-and-type}/default.json +962 -549
- package/src/live-tokens/data/colors-and-type/halloween.json +2529 -0
- package/src/live-tokens/data/colors-and-type/midnight-study.json +2536 -0
- package/src/live-tokens/data/colors-and-type/ocean.json +2489 -0
- package/src/live-tokens/data/colors-and-type/royal-velvet.json +2520 -0
- package/src/live-tokens/data/colors-and-type/spring-meadow.json +2476 -0
- package/src/live-tokens/data/colors-and-type/sunset.json +2528 -0
- package/src/live-tokens/data/themes/autumn.json +3918 -0
- package/src/live-tokens/data/themes/halloween.json +3992 -0
- package/src/live-tokens/data/themes/midnight-study.json +3932 -0
- package/src/live-tokens/data/themes/ocean.json +3917 -0
- package/src/live-tokens/data/themes/royal-velvet.json +3983 -0
- package/src/live-tokens/data/themes/spring-meadow.json +3904 -0
- package/src/live-tokens/data/themes/sunset.json +3931 -0
- package/src/live-tokens/data/tokens.generated.css +129 -140
- package/src/system/styles/CONVENTIONS.md +1 -1
- package/src/system/styles/fonts.css +1 -1
- package/template/README.md +7 -5
- package/template/_gitignore +0 -6
- package/src/editor/core/components/componentPersist.ts +0 -62
- package/src/editor/core/manifests/manifestService.ts +0 -172
- package/src/editor/ui/ManifestFileManager.svelte +0 -446
- package/src/editor/ui/ThemeFileManager.svelte +0 -785
- package/src/live-tokens/data/manifests/default.json +0 -35
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { A as AliasDiskValue, a as ComponentConfig } from '../themeTypes-DMHZOnUn.js';
|
|
2
|
+
export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-DBN0RPuT.js';
|
|
3
|
+
|
|
4
|
+
type AdjustKind = 'radius' | 'padding' | 'gap' | 'border-width';
|
|
5
|
+
interface AdjustOp {
|
|
6
|
+
/** Component id; omitted applies the op to every config. */
|
|
7
|
+
target?: string;
|
|
8
|
+
kind: AdjustKind;
|
|
9
|
+
set?: string;
|
|
10
|
+
shift?: number;
|
|
11
|
+
/** Radius shifts only: admits `--radius-full` as the ladder's top rung. */
|
|
12
|
+
full?: boolean;
|
|
13
|
+
}
|
|
14
|
+
type SkipReason = 'raw-value' | 'off-ladder' | 'clamped' | 'pill-preserved';
|
|
15
|
+
interface AliasChange {
|
|
16
|
+
variable: string;
|
|
17
|
+
from: string;
|
|
18
|
+
to: string;
|
|
19
|
+
}
|
|
20
|
+
interface AliasSkip {
|
|
21
|
+
variable: string;
|
|
22
|
+
value: AliasDiskValue;
|
|
23
|
+
reason: SkipReason;
|
|
24
|
+
}
|
|
25
|
+
interface ComponentReport {
|
|
26
|
+
component: string;
|
|
27
|
+
changes: AliasChange[];
|
|
28
|
+
skips: AliasSkip[];
|
|
29
|
+
}
|
|
30
|
+
interface AdjustReport {
|
|
31
|
+
components: ComponentReport[];
|
|
32
|
+
}
|
|
33
|
+
interface AdjustResult {
|
|
34
|
+
configs: Record<string, ComponentConfig>;
|
|
35
|
+
report: AdjustReport;
|
|
36
|
+
}
|
|
37
|
+
declare function adjustAliases(configs: Record<string, ComponentConfig>, ops: readonly AdjustOp[], now: string): AdjustResult;
|
|
38
|
+
|
|
39
|
+
type TokenKind = 'surface' | 'border' | 'border-width' | 'radius' | 'divider-width' | 'divider-height' | 'divider-inset' | 'dot-size' | 'blur' | 'scale' | 'shadow' | 'font-family' | 'font-weight' | 'font-size' | 'line-height' | 'letter-spacing' | 'padding' | 'gap' | 'duration' | 'easing' | 'text-color';
|
|
40
|
+
/** Side-aware kind test. Per-side paddings (`--card-default-body-padding-top`)
|
|
41
|
+
are written by UIPaddingSelector and never declared as editor tokens, so
|
|
42
|
+
`rawKind` never meets one; the CLI does, and they belong with their parent. */
|
|
43
|
+
declare function matchesKind(variable: string, kind: TokenKind): boolean;
|
|
44
|
+
|
|
45
|
+
export { type AdjustKind, type AdjustOp, type AdjustReport, type AdjustResult, type AliasChange, type AliasSkip, type ComponentReport, type SkipReason, adjustAliases, matchesKind };
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readLiveTokensConfig,
|
|
3
|
+
resolveDataDirs
|
|
4
|
+
} from "../chunk-D3ZVKOR4.js";
|
|
5
|
+
|
|
6
|
+
// src/editor/core/components/aliasKinds.ts
|
|
7
|
+
var KIND_PATTERNS = [
|
|
8
|
+
{ kind: "font-family", matches: (v) => v.endsWith("-font-family") },
|
|
9
|
+
{ kind: "font-weight", matches: (v) => v.endsWith("-font-weight") },
|
|
10
|
+
{ kind: "font-size", matches: (v) => v.endsWith("-font-size") || v.endsWith("-icon-size") || v.endsWith("-thumb-size") },
|
|
11
|
+
{ kind: "line-height", matches: (v) => v.endsWith("-line-height") },
|
|
12
|
+
{ kind: "letter-spacing", matches: (v) => v.endsWith("-letter-spacing") },
|
|
13
|
+
{ kind: "text-color", matches: (v) => v.endsWith("-text") || v.startsWith("--text-") },
|
|
14
|
+
{ kind: "radius", matches: (v) => v.endsWith("-radius") || v.startsWith("--radius-") },
|
|
15
|
+
{ kind: "divider-width", matches: (v) => v.endsWith("-divider-width") || v.endsWith("-divider-thickness") },
|
|
16
|
+
{ kind: "divider-height", matches: (v) => v.endsWith("-divider-height") || v.endsWith("-track-height") },
|
|
17
|
+
{ kind: "divider-inset", matches: (v) => v.endsWith("-divider-inset") },
|
|
18
|
+
{ kind: "dot-size", matches: (v) => v.endsWith("-dot-size") },
|
|
19
|
+
{ kind: "blur", matches: (v) => v.endsWith("-blur") || v.startsWith("--blur-") },
|
|
20
|
+
{ kind: "scale", matches: (v) => v.endsWith("-scale") || v.startsWith("--scale-") },
|
|
21
|
+
{ kind: "shadow", matches: (v) => v.endsWith("-shadow") || v.startsWith("--shadow-") },
|
|
22
|
+
{ kind: "padding", matches: (v) => v.endsWith("-padding") || v.endsWith("-margin") },
|
|
23
|
+
{ kind: "gap", matches: (v) => v.endsWith("-gap") },
|
|
24
|
+
{ kind: "duration", matches: (v) => v.endsWith("-duration") || v.startsWith("--duration-") },
|
|
25
|
+
{ kind: "easing", matches: (v) => v.endsWith("-easing") || v.startsWith("--ease-") },
|
|
26
|
+
{ kind: "border-width", matches: (v) => v.endsWith("-border-width") || v.endsWith("-accent-width") || v.endsWith("-hairline-thickness") || v.startsWith("--border-width-") },
|
|
27
|
+
{ kind: "border", matches: (v) => v.endsWith("-border") || v.startsWith("--border-") },
|
|
28
|
+
{ kind: "surface", matches: (v) => v.endsWith("-surface") || v.startsWith("--surface-") }
|
|
29
|
+
];
|
|
30
|
+
var MATCHER_BY_KIND = Object.fromEntries(
|
|
31
|
+
KIND_PATTERNS.map((p) => [p.kind, p.matches])
|
|
32
|
+
);
|
|
33
|
+
var SIDE_SUFFIXES = ["-top", "-right", "-bottom", "-left"];
|
|
34
|
+
function matchesKind(variable, kind) {
|
|
35
|
+
const side = SIDE_SUFFIXES.find((s) => variable.endsWith(s));
|
|
36
|
+
return MATCHER_BY_KIND[kind](side ? variable.slice(0, -side.length) : variable);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/editor/core/components/adjustAliases.ts
|
|
40
|
+
var RADIUS_FULL = "--radius-full";
|
|
41
|
+
var RADIUS_RUNGS = [
|
|
42
|
+
"--radius-none",
|
|
43
|
+
"--radius-sm",
|
|
44
|
+
"--radius-md",
|
|
45
|
+
"--radius-lg",
|
|
46
|
+
"--radius-xl",
|
|
47
|
+
"--radius-2xl",
|
|
48
|
+
"--radius-3xl",
|
|
49
|
+
"--radius-4xl"
|
|
50
|
+
];
|
|
51
|
+
var SPACE_RUNGS = [
|
|
52
|
+
"--space-0",
|
|
53
|
+
"--space-2",
|
|
54
|
+
"--space-4",
|
|
55
|
+
"--space-6",
|
|
56
|
+
"--space-8",
|
|
57
|
+
"--space-10",
|
|
58
|
+
"--space-12",
|
|
59
|
+
"--space-16",
|
|
60
|
+
"--space-20",
|
|
61
|
+
"--space-24",
|
|
62
|
+
"--space-32",
|
|
63
|
+
"--space-48"
|
|
64
|
+
];
|
|
65
|
+
var SPACE_FAMILY = [...SPACE_RUNGS, "--space-40", "--space-64", "--space-96", "--space-128"];
|
|
66
|
+
var BORDER_WIDTH_RUNGS = [
|
|
67
|
+
"--border-width-0",
|
|
68
|
+
"--border-width-1",
|
|
69
|
+
"--border-width-2",
|
|
70
|
+
"--border-width-3",
|
|
71
|
+
"--border-width-4",
|
|
72
|
+
"--border-width-5",
|
|
73
|
+
"--border-width-6",
|
|
74
|
+
"--border-width-8",
|
|
75
|
+
"--border-width-10",
|
|
76
|
+
"--border-width-12",
|
|
77
|
+
"--border-width-16",
|
|
78
|
+
"--border-width-20",
|
|
79
|
+
"--border-width-24"
|
|
80
|
+
];
|
|
81
|
+
var LADDERS = {
|
|
82
|
+
radius: { rungs: RADIUS_RUNGS, family: [...RADIUS_RUNGS, RADIUS_FULL] },
|
|
83
|
+
padding: { rungs: SPACE_RUNGS, family: SPACE_FAMILY },
|
|
84
|
+
gap: { rungs: SPACE_RUNGS, family: SPACE_FAMILY },
|
|
85
|
+
"border-width": { rungs: BORDER_WIDTH_RUNGS, family: BORDER_WIDTH_RUNGS }
|
|
86
|
+
};
|
|
87
|
+
var TOKEN_NAME = /^--[a-z0-9-]+$/;
|
|
88
|
+
function rungsFor(op) {
|
|
89
|
+
return op.kind === "radius" && op.full ? [...RADIUS_RUNGS, RADIUS_FULL] : LADDERS[op.kind].rungs;
|
|
90
|
+
}
|
|
91
|
+
function spaceStep(token) {
|
|
92
|
+
return Number(token.slice("--space-".length));
|
|
93
|
+
}
|
|
94
|
+
function nearestSpaceRung(token, rungs) {
|
|
95
|
+
const step = spaceStep(token);
|
|
96
|
+
let best = 0;
|
|
97
|
+
for (let i = 1; i < rungs.length; i++) {
|
|
98
|
+
if (Math.abs(spaceStep(rungs[i]) - step) <= Math.abs(spaceStep(rungs[best]) - step)) best = i;
|
|
99
|
+
}
|
|
100
|
+
return best;
|
|
101
|
+
}
|
|
102
|
+
function resolve(op, value) {
|
|
103
|
+
if (typeof value !== "string" || !TOKEN_NAME.test(value)) return { skip: "raw-value" };
|
|
104
|
+
if (!LADDERS[op.kind].family.includes(value)) return { skip: "off-ladder" };
|
|
105
|
+
if (op.set !== void 0) return { from: value, to: op.set };
|
|
106
|
+
const rungs = rungsFor(op);
|
|
107
|
+
let index = rungs.indexOf(value);
|
|
108
|
+
if (index < 0) {
|
|
109
|
+
if (value === RADIUS_FULL) return { skip: "pill-preserved" };
|
|
110
|
+
index = nearestSpaceRung(value, rungs);
|
|
111
|
+
}
|
|
112
|
+
const wanted = index + op.shift;
|
|
113
|
+
const landed = Math.min(Math.max(wanted, 0), rungs.length - 1);
|
|
114
|
+
if (landed !== wanted && rungs[landed] === value) return { skip: "clamped" };
|
|
115
|
+
return { from: value, to: rungs[landed] };
|
|
116
|
+
}
|
|
117
|
+
function validateOp(op, configs) {
|
|
118
|
+
const ladder = LADDERS[op.kind];
|
|
119
|
+
if (!ladder) throw new Error(`Unknown kind "${op.kind}" (expected ${Object.keys(LADDERS).join(", ")})`);
|
|
120
|
+
if (op.target !== void 0 && !(op.target in configs)) {
|
|
121
|
+
throw new Error(`Unknown target component "${op.target}"`);
|
|
122
|
+
}
|
|
123
|
+
const hasSet = op.set !== void 0;
|
|
124
|
+
const hasShift = op.shift !== void 0;
|
|
125
|
+
if (hasSet === hasShift) throw new Error(`A ${op.kind} op needs exactly one of "set" or "shift"`);
|
|
126
|
+
const settable = op.kind === "radius" ? ladder.family : ladder.rungs;
|
|
127
|
+
if (hasSet && !settable.includes(op.set)) {
|
|
128
|
+
throw new Error(`"${op.set}" is not on the ${op.kind} ladder`);
|
|
129
|
+
}
|
|
130
|
+
if (hasShift && !Number.isInteger(op.shift)) {
|
|
131
|
+
throw new Error(`"shift" must be a whole number of steps, got ${op.shift}`);
|
|
132
|
+
}
|
|
133
|
+
if (op.full !== void 0 && !(op.kind === "radius" && hasShift)) {
|
|
134
|
+
throw new Error('"full" applies to radius shifts only');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function adjustAliases(configs, ops, now) {
|
|
138
|
+
for (const op of ops) validateOp(op, configs);
|
|
139
|
+
const next = { ...configs };
|
|
140
|
+
const reports = /* @__PURE__ */ new Map();
|
|
141
|
+
const reportFor = (component) => {
|
|
142
|
+
let report = reports.get(component);
|
|
143
|
+
if (!report) {
|
|
144
|
+
report = { component, changes: [], skips: [] };
|
|
145
|
+
reports.set(component, report);
|
|
146
|
+
}
|
|
147
|
+
return report;
|
|
148
|
+
};
|
|
149
|
+
for (const op of ops) {
|
|
150
|
+
for (const component of op.target ? [op.target] : Object.keys(next)) {
|
|
151
|
+
const config = next[component];
|
|
152
|
+
const aliases = { ...config.aliases };
|
|
153
|
+
let changed = false;
|
|
154
|
+
for (const [variable, value] of Object.entries(config.aliases)) {
|
|
155
|
+
if (!matchesKind(variable, op.kind)) continue;
|
|
156
|
+
const outcome = resolve(op, value);
|
|
157
|
+
if ("skip" in outcome) {
|
|
158
|
+
reportFor(component).skips.push({ variable, value, reason: outcome.skip });
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (outcome.to === outcome.from) continue;
|
|
162
|
+
aliases[variable] = outcome.to;
|
|
163
|
+
reportFor(component).changes.push({ variable, from: outcome.from, to: outcome.to });
|
|
164
|
+
changed = true;
|
|
165
|
+
}
|
|
166
|
+
if (changed) next[component] = { ...config, aliases, updatedAt: now };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return { configs: next, report: { components: [...reports.values()] } };
|
|
170
|
+
}
|
|
171
|
+
export {
|
|
172
|
+
adjustAliases,
|
|
173
|
+
matchesKind,
|
|
174
|
+
readLiveTokensConfig,
|
|
175
|
+
resolveDataDirs
|
|
176
|
+
};
|
|
@@ -350,52 +350,6 @@ var tokensCssMigration_2026_07_20_semanticTextStyles = {
|
|
|
350
350
|
}
|
|
351
351
|
};
|
|
352
352
|
|
|
353
|
-
// vite-plugin/files/dataPaths.ts
|
|
354
|
-
import fs from "fs";
|
|
355
|
-
import path from "path";
|
|
356
|
-
var DEFAULT_DATA_DIR = "src/live-tokens/data";
|
|
357
|
-
var KNOWN_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
358
|
-
"dataDir",
|
|
359
|
-
"themesDir",
|
|
360
|
-
"componentConfigsDir",
|
|
361
|
-
"manifestsDir",
|
|
362
|
-
"tokensCssPath"
|
|
363
|
-
]);
|
|
364
|
-
var cached = null;
|
|
365
|
-
function readLiveTokensConfig() {
|
|
366
|
-
if (cached) return cached;
|
|
367
|
-
try {
|
|
368
|
-
const configPath = path.resolve("live-tokens.config.json");
|
|
369
|
-
if (!fs.existsSync(configPath)) return cached = {};
|
|
370
|
-
const parsed = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
371
|
-
if (!parsed || typeof parsed !== "object") return cached = {};
|
|
372
|
-
const unknown = Object.keys(parsed).filter(
|
|
373
|
-
(k) => k !== "$schema" && !KNOWN_CONFIG_KEYS.has(k)
|
|
374
|
-
);
|
|
375
|
-
if (unknown.length > 0) {
|
|
376
|
-
console.warn(
|
|
377
|
-
`[live-tokens] Unknown key(s) in live-tokens.config.json: ${unknown.join(", ")}. Known keys: ${Array.from(KNOWN_CONFIG_KEYS).join(", ")}.`
|
|
378
|
-
);
|
|
379
|
-
}
|
|
380
|
-
cached = parsed;
|
|
381
|
-
return cached;
|
|
382
|
-
} catch {
|
|
383
|
-
return cached = {};
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
function resolveDataDirs(opts = {}) {
|
|
387
|
-
const fileConfig = readLiveTokensConfig();
|
|
388
|
-
const dataDirRaw = opts.dataDir ?? fileConfig.dataDir ?? DEFAULT_DATA_DIR;
|
|
389
|
-
const dataDir = path.resolve(dataDirRaw);
|
|
390
|
-
const sub = (name) => path.resolve(dataDir, name);
|
|
391
|
-
return {
|
|
392
|
-
dataDir,
|
|
393
|
-
themesDir: opts.themesDir ? path.resolve(opts.themesDir) : fileConfig.themesDir ? path.resolve(fileConfig.themesDir) : sub("themes"),
|
|
394
|
-
componentConfigsDir: opts.componentConfigsDir ? path.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? path.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
|
|
395
|
-
manifestsDir: opts.manifestsDir ? path.resolve(opts.manifestsDir) : fileConfig.manifestsDir ? path.resolve(fileConfig.manifestsDir) : sub("manifests")
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
|
|
399
353
|
// vite-plugin/tokensCssMigrations/index.ts
|
|
400
354
|
var TOKENS_CSS_MIGRATIONS = [
|
|
401
355
|
tokensCssMigration_2026_05_29_typographyScaleAdditions,
|
|
@@ -491,8 +445,6 @@ function validateTokensCss(input) {
|
|
|
491
445
|
|
|
492
446
|
export {
|
|
493
447
|
extractGlobalRootBody,
|
|
494
|
-
readLiveTokensConfig,
|
|
495
|
-
resolveDataDirs,
|
|
496
448
|
collectDefinedTokens,
|
|
497
449
|
collectReferencedTokens,
|
|
498
450
|
ensureScale,
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
// vite-plugin/files/versionedFileResourceServer.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
function versionedFileResourceServer(opts) {
|
|
5
|
+
const dir = opts.dir;
|
|
6
|
+
const activePath = path.join(dir, "_active.json");
|
|
7
|
+
const productionPath = path.join(dir, "_production.json");
|
|
8
|
+
const workingPath = path.join(dir, "_working.json");
|
|
9
|
+
const defaultName = opts.defaultName ?? "default";
|
|
10
|
+
const resolvedDir = path.resolve(dir);
|
|
11
|
+
const resolvedPackageDir = opts.packageDir ? path.resolve(opts.packageDir) : null;
|
|
12
|
+
function ensureDir() {
|
|
13
|
+
if (!fs.existsSync(dir)) {
|
|
14
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function ensureMeta() {
|
|
18
|
+
if (!fs.existsSync(activePath)) {
|
|
19
|
+
fs.writeFileSync(activePath, JSON.stringify({ activeFile: defaultName }));
|
|
20
|
+
}
|
|
21
|
+
if (!fs.existsSync(productionPath)) {
|
|
22
|
+
fs.writeFileSync(productionPath, JSON.stringify({ productionFile: defaultName }));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function filePath(name) {
|
|
26
|
+
return path.join(dir, `${name}.json`);
|
|
27
|
+
}
|
|
28
|
+
function existingPath(name) {
|
|
29
|
+
const local = filePath(name);
|
|
30
|
+
if (fs.existsSync(local)) return local;
|
|
31
|
+
if (resolvedPackageDir) {
|
|
32
|
+
const pkg = path.join(resolvedPackageDir, `${name}.json`);
|
|
33
|
+
if (fs.existsSync(pkg)) return pkg;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
function isPackageFile(name) {
|
|
38
|
+
if (!resolvedPackageDir) return false;
|
|
39
|
+
const pkg = path.join(resolvedPackageDir, `${name}.json`);
|
|
40
|
+
if (!fs.existsSync(pkg)) return false;
|
|
41
|
+
const local = path.resolve(filePath(name));
|
|
42
|
+
if (local === pkg) {
|
|
43
|
+
return opts.packageOwnedNames ? opts.packageOwnedNames.includes(name) : true;
|
|
44
|
+
}
|
|
45
|
+
return !fs.existsSync(local);
|
|
46
|
+
}
|
|
47
|
+
function readJson(name) {
|
|
48
|
+
const resolved = existingPath(name);
|
|
49
|
+
if (!resolved) return null;
|
|
50
|
+
return JSON.parse(fs.readFileSync(resolved, "utf-8"));
|
|
51
|
+
}
|
|
52
|
+
function listNames() {
|
|
53
|
+
const names = [];
|
|
54
|
+
const seen = /* @__PURE__ */ new Set();
|
|
55
|
+
const collect = (d) => {
|
|
56
|
+
if (!d || !fs.existsSync(d)) return;
|
|
57
|
+
for (const f of fs.readdirSync(d)) {
|
|
58
|
+
if (!f.endsWith(".json") || f.startsWith("_")) continue;
|
|
59
|
+
const name = f.slice(0, -".json".length);
|
|
60
|
+
if (seen.has(name)) continue;
|
|
61
|
+
seen.add(name);
|
|
62
|
+
names.push(name);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
collect(resolvedDir);
|
|
66
|
+
if (resolvedPackageDir && resolvedPackageDir !== resolvedDir) collect(resolvedPackageDir);
|
|
67
|
+
return names;
|
|
68
|
+
}
|
|
69
|
+
function getActiveName() {
|
|
70
|
+
try {
|
|
71
|
+
const data = JSON.parse(fs.readFileSync(activePath, "utf-8"));
|
|
72
|
+
return data.activeFile || defaultName;
|
|
73
|
+
} catch {
|
|
74
|
+
return defaultName;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function getProductionName() {
|
|
78
|
+
try {
|
|
79
|
+
const data = JSON.parse(fs.readFileSync(productionPath, "utf-8"));
|
|
80
|
+
return data.productionFile || defaultName;
|
|
81
|
+
} catch {
|
|
82
|
+
return defaultName;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function setActiveName(name) {
|
|
86
|
+
fs.writeFileSync(activePath, JSON.stringify({ activeFile: name }));
|
|
87
|
+
}
|
|
88
|
+
function setProductionName(name) {
|
|
89
|
+
fs.writeFileSync(productionPath, JSON.stringify({ productionFile: name }));
|
|
90
|
+
}
|
|
91
|
+
function hasWorking() {
|
|
92
|
+
return fs.existsSync(workingPath);
|
|
93
|
+
}
|
|
94
|
+
function readWorking() {
|
|
95
|
+
if (!fs.existsSync(workingPath)) return null;
|
|
96
|
+
const parsed = JSON.parse(fs.readFileSync(workingPath, "utf-8"));
|
|
97
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
98
|
+
throw new Error(`${workingPath} does not hold a JSON object`);
|
|
99
|
+
}
|
|
100
|
+
return parsed;
|
|
101
|
+
}
|
|
102
|
+
function writeWorking(data) {
|
|
103
|
+
ensureDir();
|
|
104
|
+
fs.writeFileSync(workingPath, JSON.stringify(data, null, 2));
|
|
105
|
+
}
|
|
106
|
+
function clearWorking() {
|
|
107
|
+
if (fs.existsSync(workingPath)) fs.unlinkSync(workingPath);
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
dir,
|
|
111
|
+
activePath,
|
|
112
|
+
productionPath,
|
|
113
|
+
workingPath,
|
|
114
|
+
ensureDir,
|
|
115
|
+
ensureMeta,
|
|
116
|
+
filePath,
|
|
117
|
+
existingPath,
|
|
118
|
+
isPackageFile,
|
|
119
|
+
readJson,
|
|
120
|
+
listNames,
|
|
121
|
+
getActiveName,
|
|
122
|
+
getProductionName,
|
|
123
|
+
setActiveName,
|
|
124
|
+
setProductionName,
|
|
125
|
+
hasWorking,
|
|
126
|
+
readWorking,
|
|
127
|
+
writeWorking,
|
|
128
|
+
clearWorking
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// vite-plugin/themes/normalizeTheme.ts
|
|
133
|
+
var THEME_SCHEMA_VERSION = 3;
|
|
134
|
+
function asObject(value) {
|
|
135
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
136
|
+
}
|
|
137
|
+
function isColorsAndTypeShaped(raw) {
|
|
138
|
+
const obj = asObject(raw);
|
|
139
|
+
if (!obj) return false;
|
|
140
|
+
if ("theme" in obj || "colorsAndType" in obj) return false;
|
|
141
|
+
return "cssVariables" in obj || "editorConfigs" in obj;
|
|
142
|
+
}
|
|
143
|
+
function stripFileMarker(value) {
|
|
144
|
+
if (!("_fileName" in value)) return value;
|
|
145
|
+
const { _fileName, ...rest } = value;
|
|
146
|
+
return rest;
|
|
147
|
+
}
|
|
148
|
+
function asString(value, fallback) {
|
|
149
|
+
return typeof value === "string" && value ? value : fallback;
|
|
150
|
+
}
|
|
151
|
+
function migrateEmbeddedKey(src) {
|
|
152
|
+
const { theme, ...rest } = src;
|
|
153
|
+
return { ...rest, colorsAndType: theme };
|
|
154
|
+
}
|
|
155
|
+
function normalizeTheme(raw, resolvers) {
|
|
156
|
+
const input = asObject(raw) ?? {};
|
|
157
|
+
const migrated = input.schemaVersion !== THEME_SCHEMA_VERSION;
|
|
158
|
+
const src = migrated ? migrateEmbeddedKey(input) : input;
|
|
159
|
+
const dropped = [];
|
|
160
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
161
|
+
const embeddedColorsAndType = asObject(src.colorsAndType);
|
|
162
|
+
let colorsAndType = null;
|
|
163
|
+
if (embeddedColorsAndType) {
|
|
164
|
+
colorsAndType = stripFileMarker(embeddedColorsAndType);
|
|
165
|
+
} else {
|
|
166
|
+
const colorsAndTypeName = asString(src.colorsAndType, "default");
|
|
167
|
+
colorsAndType = asObject(resolvers.readColorsAndType(colorsAndTypeName));
|
|
168
|
+
if (!colorsAndType) {
|
|
169
|
+
dropped.push(`colors-and-type:${colorsAndTypeName}`);
|
|
170
|
+
if (colorsAndTypeName !== "default") colorsAndType = asObject(resolvers.readColorsAndType("default"));
|
|
171
|
+
}
|
|
172
|
+
if (colorsAndType) colorsAndType = resolvers.normalizeColorsAndType(stripFileMarker(colorsAndType));
|
|
173
|
+
}
|
|
174
|
+
const componentConfigs = {};
|
|
175
|
+
for (const [comp, value] of Object.entries(asObject(src.componentConfigs) ?? {})) {
|
|
176
|
+
const embedded = asObject(value);
|
|
177
|
+
if (embedded) {
|
|
178
|
+
componentConfigs[comp] = stripFileMarker(embedded);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const configName = asString(value, "default");
|
|
182
|
+
if (configName === "default") continue;
|
|
183
|
+
const resolved = asObject(resolvers.readComponentConfig(comp, configName));
|
|
184
|
+
if (!resolved) {
|
|
185
|
+
dropped.push(`${comp}/${configName}`);
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
componentConfigs[comp] = stripFileMarker(resolved);
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
theme: {
|
|
192
|
+
name: asString(src.name, "Untitled"),
|
|
193
|
+
createdAt: asString(src.createdAt, now),
|
|
194
|
+
updatedAt: asString(src.updatedAt, now),
|
|
195
|
+
schemaVersion: THEME_SCHEMA_VERSION,
|
|
196
|
+
colorsAndType,
|
|
197
|
+
componentConfigs
|
|
198
|
+
},
|
|
199
|
+
dropped,
|
|
200
|
+
migrated
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// vite-plugin/files/nameAllocator.ts
|
|
205
|
+
function nextAvailableName(exists, baseName, maxAttempts = 1e3) {
|
|
206
|
+
if (!exists(baseName)) return baseName;
|
|
207
|
+
for (let i = 2; i < maxAttempts; i++) {
|
|
208
|
+
const candidate = `${baseName}-${i}`;
|
|
209
|
+
if (!exists(candidate)) return candidate;
|
|
210
|
+
}
|
|
211
|
+
throw new Error(`Could not allocate a non-colliding name for "${baseName}"`);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// vite-plugin/files/legacyLayout.ts
|
|
215
|
+
import fs2 from "fs";
|
|
216
|
+
import path2 from "path";
|
|
217
|
+
function jsonFiles(dir) {
|
|
218
|
+
if (!fs2.existsSync(dir)) return [];
|
|
219
|
+
try {
|
|
220
|
+
return fs2.readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => path2.join(dir, f));
|
|
221
|
+
} catch {
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function isDirectory(dir) {
|
|
226
|
+
try {
|
|
227
|
+
return fs2.statSync(dir).isDirectory();
|
|
228
|
+
} catch {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function parseJsonFile(file) {
|
|
233
|
+
try {
|
|
234
|
+
return JSON.parse(fs2.readFileSync(file, "utf-8"));
|
|
235
|
+
} catch {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function holdsATheme(themesDir) {
|
|
240
|
+
return jsonFiles(themesDir).some((file) => {
|
|
241
|
+
if (path2.basename(file).startsWith("_")) return false;
|
|
242
|
+
const raw = parseJsonFile(file);
|
|
243
|
+
if (!raw || typeof raw !== "object") return false;
|
|
244
|
+
return "colorsAndType" in raw || "theme" in raw;
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
function detectLegacyLayout(input) {
|
|
248
|
+
const manifestsDir = input.configuredManifestsDir ?? path2.join(input.dataDir, "manifests");
|
|
249
|
+
const themesHoldAThemeFile = holdsATheme(input.themesDir);
|
|
250
|
+
if (isDirectory(manifestsDir) && !themesHoldAThemeFile) {
|
|
251
|
+
return { manifestsDir, evidence: `${manifestsDir} is the pre-0.48 whole-look directory` };
|
|
252
|
+
}
|
|
253
|
+
if (jsonFiles(input.colorsAndTypeDir).length > 0) return null;
|
|
254
|
+
for (const file of jsonFiles(input.themesDir)) {
|
|
255
|
+
if (path2.basename(file).startsWith("_")) continue;
|
|
256
|
+
if (isColorsAndTypeShaped(parseJsonFile(file))) {
|
|
257
|
+
return { manifestsDir, evidence: `${file} is a colors-and-type file, not a theme` };
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
const pointer = ["_active.json", "_production.json"].map((name) => path2.join(input.themesDir, name)).find((p) => fs2.existsSync(p));
|
|
261
|
+
if (pointer && !themesHoldAThemeFile && !fs2.existsSync(input.colorsAndTypeDir)) {
|
|
262
|
+
return {
|
|
263
|
+
manifestsDir,
|
|
264
|
+
evidence: `${pointer} points at colors and type, and there is no ${path2.basename(input.colorsAndTypeDir)} directory`
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
function planLegacyRenames(layout, input) {
|
|
270
|
+
const defaultColorsAndType = path2.join(input.dataDir, "colors-and-type");
|
|
271
|
+
const defaultThemes = path2.join(input.dataDir, "themes");
|
|
272
|
+
if (input.configuredManifestsDir && path2.resolve(input.configuredManifestsDir) !== path2.join(input.dataDir, "manifests")) {
|
|
273
|
+
throw new Error(
|
|
274
|
+
`This project uses the pre-0.48 data layout (${layout.evidence}), and live-tokens.config.json sets the retired "manifestsDir" key to ${input.configuredManifestsDir}. That directory holds the whole looks, which now belong in ${input.themesDir}. Move it there by hand, drop the "manifestsDir" key, then run the migration again.`
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
if (path2.resolve(input.colorsAndTypeDir) !== path2.resolve(defaultColorsAndType) || path2.resolve(input.themesDir) !== path2.resolve(defaultThemes)) {
|
|
278
|
+
throw new Error(
|
|
279
|
+
`This project uses the pre-0.48 data layout (${layout.evidence}), and its data directories are configured to custom paths (colorsAndTypeDir=${input.colorsAndTypeDir}, themesDir=${input.themesDir}). The migration cannot tell which directory holds what. Move the old colors-and-type directory to ${input.colorsAndTypeDir} and the old whole-look directory to ${input.themesDir} by hand, then run the migration again.`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
const renames = [];
|
|
283
|
+
if (fs2.existsSync(input.themesDir)) {
|
|
284
|
+
renames.push({ from: input.themesDir, to: input.colorsAndTypeDir });
|
|
285
|
+
}
|
|
286
|
+
if (fs2.existsSync(layout.manifestsDir)) {
|
|
287
|
+
renames.push({ from: layout.manifestsDir, to: input.themesDir });
|
|
288
|
+
}
|
|
289
|
+
return renames;
|
|
290
|
+
}
|
|
291
|
+
function applyLegacyRenames(renames) {
|
|
292
|
+
for (const { from, to } of renames) {
|
|
293
|
+
if (fs2.existsSync(to)) {
|
|
294
|
+
const contents = fs2.readdirSync(to);
|
|
295
|
+
if (contents.length > 0) {
|
|
296
|
+
throw new Error(
|
|
297
|
+
`Cannot move ${from} to ${to}: ${to} already exists and holds ${contents.length} file(s). Move or delete it, then run the migration again.`
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
fs2.rmdirSync(to);
|
|
301
|
+
}
|
|
302
|
+
fs2.mkdirSync(path2.dirname(to), { recursive: true });
|
|
303
|
+
fs2.renameSync(from, to);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export {
|
|
308
|
+
versionedFileResourceServer,
|
|
309
|
+
THEME_SCHEMA_VERSION,
|
|
310
|
+
isColorsAndTypeShaped,
|
|
311
|
+
normalizeTheme,
|
|
312
|
+
nextAvailableName,
|
|
313
|
+
detectLegacyLayout,
|
|
314
|
+
planLegacyRenames,
|
|
315
|
+
applyLegacyRenames
|
|
316
|
+
};
|