@motion-proto/live-tokens 0.50.0 → 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 +108 -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-76TFDTJO.js → chunk-PB2JTK2H.js} +179 -128
- package/dist-plugin/{chunk-44RSTAII.js → chunk-TKZBVIW5.js} +33 -5
- package/dist-plugin/chunk-YR6GPXW2.js +129 -0
- package/dist-plugin/generateColorsAndType/index.cjs +135 -63
- package/dist-plugin/generateColorsAndType/index.d.cts +2 -1
- package/dist-plugin/generateColorsAndType/index.d.ts +2 -1
- package/dist-plugin/generateColorsAndType/index.js +28 -784
- package/dist-plugin/{themeTypes-DSwKq-bj.d.ts → index-DpTIRZ2H.d.cts} +67 -26
- package/dist-plugin/{themeTypes-DSwKq-bj.d.cts → index-DpTIRZ2H.d.ts} +67 -26
- package/dist-plugin/index.cjs +1254 -140
- package/dist-plugin/index.js +106 -82
- package/dist-plugin/migrateData/index.cjs +956 -14
- package/dist-plugin/migrateData/index.js +10 -3
- package/dist-plugin/tokensCssMigrations/index.cjs +71 -5
- package/dist-plugin/tokensCssMigrations/index.d.cts +20 -9
- package/dist-plugin/tokensCssMigrations/index.d.ts +20 -9
- package/dist-plugin/tokensCssMigrations/index.js +4 -1
- package/package.json +8 -4
- package/src/editor/component-editor/NotificationEditor.svelte +6 -0
- 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/palettes/oklch.ts +3 -137
- package/src/editor/core/palettes/paletteDerivation.ts +79 -37
- package/src/editor/core/store/editorStore.ts +7 -197
- package/src/editor/core/store/editorTypes.ts +9 -30
- package/src/editor/core/themes/generateColorsAndType.ts +18 -8
- 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 +89 -27
- package/src/editor/docs/content/editing-tokens.md +6 -2
- 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 +3 -3
- package/src/editor/index.ts +1 -0
- package/src/editor/styles/ui-editor.css +5 -2
- package/src/editor/ui/BezierCurveEditor.svelte +90 -67
- package/src/editor/ui/PaletteEditor.svelte +180 -59
- package/src/editor/ui/ThemePanel.svelte +24 -15
- package/src/editor/ui/Toggle.svelte +36 -24
- 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/ColorStory.svelte +12 -8
- package/src/editor/ui/colors/ColorsTab.svelte +4 -5
- package/src/editor/ui/curveEngine.ts +101 -21
- package/src/editor/ui/palette/OverridesPanel.svelte +23 -8
- package/src/editor/ui/palette/PaletteBase.svelte +17 -78
- package/src/editor/ui/palette/PaletteJumpButton.svelte +3 -3
- package/src/editor/ui/palette/ScaleCurveEditor.svelte +110 -20
- package/src/editor/ui/palette/curveSummary.ts +20 -0
- package/src/editor/ui/palette/dockMagnify.ts +5 -13
- package/src/editor/ui/palette/paletteMath.ts +7 -4
- package/src/live-tokens/data/colors-and-type/autumn.json +528 -528
- package/src/live-tokens/data/colors-and-type/default.json +247 -247
- package/src/live-tokens/data/colors-and-type/halloween.json +532 -532
- package/src/live-tokens/data/colors-and-type/midnight-study.json +538 -538
- package/src/live-tokens/data/colors-and-type/ocean.json +521 -521
- package/src/live-tokens/data/colors-and-type/royal-velvet.json +532 -532
- package/src/live-tokens/data/colors-and-type/spring-meadow.json +504 -504
- package/src/live-tokens/data/colors-and-type/sunset.json +531 -531
- package/src/live-tokens/data/themes/autumn.json +604 -568
- package/src/live-tokens/data/themes/halloween.json +584 -583
- package/src/live-tokens/data/themes/midnight-study.json +673 -605
- package/src/live-tokens/data/themes/ocean.json +597 -561
- package/src/live-tokens/data/themes/royal-velvet.json +574 -573
- package/src/live-tokens/data/themes/spring-meadow.json +590 -556
- package/src/live-tokens/data/themes/sunset.json +632 -571
- package/src/live-tokens/data/tokens.generated.css +282 -282
- package/src/system/components/FloatingTokenTags.css +0 -1
- package/src/system/internal/backgroundContrast.ts +7 -0
- package/src/system/internal/oklch.ts +189 -0
- package/src/system/styles/tokens.css +283 -283
|
@@ -54,7 +54,13 @@ Magnitude words: "slightly" or "a bit" is 1 step, unqualified is 1 to 2, "much",
|
|
|
54
54
|
|
|
55
55
|
## Ladders
|
|
56
56
|
|
|
57
|
-
Radius runs `none, sm, md, lg, xl, 2xl, 3xl, 4xl`, with `full` as the gated ninth rung. Space (padding and gap) is the editor picker's subset: `0, 2, 4, 6, 8, 10, 12, 16, 20, 24, 32, 48`, so every written value stays re-editable by hand. Border width is the full `--border-width-*` scale. `set` values must be on the ladder (`--space-64` is rejected)
|
|
57
|
+
Radius runs `none, sm, md, lg, xl, 2xl, 3xl, 4xl`, with `full` as the gated ninth rung. Space (padding and gap) is the editor picker's subset: `0, 2, 4, 6, 8, 10, 12, 16, 20, 24, 32, 48`, so every written value stays re-editable by hand. Border width is the full `--border-width-*` scale. `set` values must be on the ladder (`--space-64` is rejected).
|
|
58
|
+
|
|
59
|
+
Content insets stop at `--space-4`. Below it the text sits against its own edge, so `--space-0` and `--space-2` are destinations a person picks on purpose, not ones a relative "tighter" hands you. Both stay available through the editor picker and through `set`. An alias already below the floor still moves up, and a shift that would push one under `--space-4` reports as clamped and writes nothing.
|
|
60
|
+
|
|
61
|
+
The floor guards `-padding` only. Outer space is exempt, because a 2px gap between an icon and its label, or a 2px margin under a bar, is ordinary design rather than a mistake. Note that `-margin` rides the `padding` kind, so a padding op moves margins too; it just does not floor them.
|
|
62
|
+
|
|
63
|
+
An alias sitting off the subset spends its first step reaching the rung the shift points at, so `--space-2` with `shift: 1` lands on `--space-4` rather than jumping past it.
|
|
58
64
|
|
|
59
65
|
## Scope
|
|
60
66
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,113 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.53.0 — Themes are complete documents
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **The editor no longer imports build tooling.** `themeService.ts` and
|
|
8
|
+
`themeTypes.ts` read `THEME_SCHEMA_VERSION` from
|
|
9
|
+
`vite-plugin/themes/normalizeTheme`, a path that resolves in this repository
|
|
10
|
+
and in no installed copy, because the tarball ships no tooling. Any consumer
|
|
11
|
+
building the editor failed on an unresolved import. The constant now lives in
|
|
12
|
+
`themeTypes.ts` and the plugin re-exports it. `check:no-tooling-imports`
|
|
13
|
+
gates the direction.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **Content insets stop at `--space-4`.** Below it the text sits against its
|
|
18
|
+
own edge, so a relative "tighter" no longer deposits a `-padding` alias on
|
|
19
|
+
`--space-0` or `--space-2`. Both stay available in the editor picker and
|
|
20
|
+
through an explicit `set` op, which is where that call belongs. A shift that
|
|
21
|
+
would push an alias under the floor reports as clamped and writes nothing.
|
|
22
|
+
Outer space is exempt: a 2px gap between an icon and its label, or a 2px
|
|
23
|
+
margin under a bar, is ordinary design.
|
|
24
|
+
|
|
25
|
+
- **An off-ladder value spends its first step reaching the ladder.** Shifting
|
|
26
|
+
such a value used to snap it to the nearest rung and then apply the full
|
|
27
|
+
shift on top, so a one-step request moved two visible steps, and an
|
|
28
|
+
above-ladder value could be quietly pulled *down* by a request to go up.
|
|
29
|
+
The snap now follows the shift's direction and counts as its opening step.
|
|
30
|
+
This retires the report card's `!` marker, which existed only to flag that
|
|
31
|
+
backwards case.
|
|
32
|
+
|
|
33
|
+
- **Themes are complete documents.** A theme now stores every component and
|
|
34
|
+
every alias, by value, at `schemaVersion` 4. Boot migrates and fills a
|
|
35
|
+
local theme once; an incomplete imported theme still loads with whatever
|
|
36
|
+
components it carries, filled from the current defaults, and the fill is
|
|
37
|
+
reported in the Theme panel. The preset generator that re-derived the
|
|
38
|
+
seven shipped presets on every run is gone. `seed-preset-theme.mjs <slug>`
|
|
39
|
+
seeds a new preset once and `check:preset-themes` guards the shipped seven
|
|
40
|
+
against drift.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **`generate-theme` no longer inherits gaps from an incomplete open theme.**
|
|
45
|
+
The live resolution path gained the missing default layer, so a theme
|
|
46
|
+
missing a component no longer leaves the generator working from a hole.
|
|
47
|
+
- **A pre-rename alias key in an old theme is migrated before the bake**,
|
|
48
|
+
instead of being emitted verbatim into `tokens.generated.css`.
|
|
49
|
+
- **A component's gradient default survives a fresh checkout.** The dev
|
|
50
|
+
server derives `component-configs/<comp>/default.json` from the component's
|
|
51
|
+
`:global(:root)` block, and it could not read a baked gradient back. On a
|
|
52
|
+
tree with no prior file it dropped the alias. It now parses the gradient
|
|
53
|
+
into its structured form, so the derivation covers every value the bake
|
|
54
|
+
emits.
|
|
55
|
+
- **A radial gradient bakes the shape the editor shows.** The production bake
|
|
56
|
+
carried its own copy of the gradient renderer, which ignored the centre and
|
|
57
|
+
both aspect factors and wrote `circle … at center` for every radial. Both
|
|
58
|
+
sides now share one renderer.
|
|
59
|
+
- **The shipped `panel` aliases sit in derivation order.** `Panel.svelte`
|
|
60
|
+
declares `--panel-stage-surface` before the stage spacing, but every
|
|
61
|
+
committed copy carried it last. On a fresh checkout, where the component
|
|
62
|
+
source is newer than the data tree, boot re-derived `default.json` into
|
|
63
|
+
source order while the seven presets kept the old one, and the preset gate
|
|
64
|
+
read two different key orders. The committed data now matches the source.
|
|
65
|
+
|
|
66
|
+
## 0.52.1 — Notification header actions are previewable
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- **The Notification editor can show a header action.** The four
|
|
71
|
+
`--notification-*-action-surface` tokens paint the backdrop behind a
|
|
72
|
+
header-slot button, and no preview ever rendered one, so nothing in the
|
|
73
|
+
editor could show what they do. A "Header button" checkbox in the preview
|
|
74
|
+
toolbar turns the slot on.
|
|
75
|
+
|
|
76
|
+
## 0.52.0 — A third palette curve
|
|
77
|
+
|
|
78
|
+
### Added
|
|
79
|
+
|
|
80
|
+
- **Palettes gain a third curve, for hue.** Alongside Saturation and
|
|
81
|
+
Lightness, a Hue curve offsets each step by up to ±45 degrees, so a
|
|
82
|
+
palette can drift warmer or cooler across its ramp without moving
|
|
83
|
+
contrast. OKLCH keeps hue rotation close to lightness-preserving, which
|
|
84
|
+
makes that possible. The curve is closed by default, and existing
|
|
85
|
+
themes are unaffected: an absent hue curve renders as flat zero, exactly
|
|
86
|
+
as before.
|
|
87
|
+
|
|
88
|
+
## 0.51.0 — OKLCH end to end
|
|
89
|
+
|
|
90
|
+
### Changed (breaking)
|
|
91
|
+
|
|
92
|
+
- **Color tokens are written as `oklch()`, not hex.** The editor already
|
|
93
|
+
stored, edited, and computed color in OKLCH; only the final CSS string was
|
|
94
|
+
hex, which quantized every value to 8 bits on the way out. Derived colors now
|
|
95
|
+
serialize as `oklch()` in the live `:root` and in `tokens.generated.css`, and
|
|
96
|
+
`tokens.css` ships its 283 primitives in the same form. Values are still
|
|
97
|
+
clamped into the sRGB gamut before serialization, so nothing changes color.
|
|
98
|
+
Hex remains the readout and text-field format in the editor, and is still
|
|
99
|
+
what you copy out.
|
|
100
|
+
|
|
101
|
+
This sets a browser floor of Chrome 111, Safari 15.4, and Firefox 113
|
|
102
|
+
(2023). Run `npx live-tokens migrate` to convert a vendored `tokens.css`; the
|
|
103
|
+
transform is idempotent and touches values only, never names. Because it
|
|
104
|
+
rewrites values rather than renaming them, it never auto-applies — the dev
|
|
105
|
+
plugin will not touch your file.
|
|
106
|
+
|
|
107
|
+
Any code of your own that parses these tokens as hex needs updating. Inside
|
|
108
|
+
the package, the generator's contrast gate, the Color Story readouts, and the
|
|
109
|
+
runtime background-contrast picker were the three such readers.
|
|
110
|
+
|
|
3
111
|
## 0.50.0 — Live editing stays in sync
|
|
4
112
|
|
|
5
113
|
### Added
|
package/bin/adjust.mjs
CHANGED
|
@@ -18,7 +18,6 @@ const packageThemesDir = join(pkgRoot, 'src/live-tokens/data/themes');
|
|
|
18
18
|
const SOURCE_LABELS = {
|
|
19
19
|
working: 'your unsaved edits',
|
|
20
20
|
theme: 'the open theme',
|
|
21
|
-
default: 'the shipped default',
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
const SKIP_LABELS = [
|
|
@@ -46,35 +45,6 @@ function readJsonIfExists(path) {
|
|
|
46
45
|
return existsSync(path) ? readJson(path) : null;
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
function numericRung(token) {
|
|
50
|
-
const match = /-(\d+)$/.exec(token);
|
|
51
|
-
return match ? Number(match[1]) : null;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Net direction the ops asked for on this alias. An explicit `set` owns the
|
|
55
|
-
* value outright, so it reports no direction. */
|
|
56
|
-
function requestedDirection(ops, matchesKind, component, variable) {
|
|
57
|
-
let total = 0;
|
|
58
|
-
for (const op of ops) {
|
|
59
|
-
if (op.target !== undefined && op.target !== component) continue;
|
|
60
|
-
if (!matchesKind(variable, op.kind)) continue;
|
|
61
|
-
if (op.shift === undefined) return 0;
|
|
62
|
-
total += op.shift;
|
|
63
|
-
}
|
|
64
|
-
return Math.sign(total);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** A shift can land below where it started: an off-subset value (`--space-64`)
|
|
68
|
-
* snaps to its nearest writable rung first. Those changes are marked, never
|
|
69
|
-
* listed as an ordinary shift. */
|
|
70
|
-
function opposesShift(ops, matchesKind, component, change) {
|
|
71
|
-
const from = numericRung(change.from);
|
|
72
|
-
const to = numericRung(change.to);
|
|
73
|
-
if (from === null || to === null) return false;
|
|
74
|
-
const direction = requestedDirection(ops, matchesKind, component, change.variable);
|
|
75
|
-
return direction !== 0 && Math.sign(to - from) !== direction;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
48
|
/** Successive ops can touch the same alias (soften, then pill the buttons);
|
|
79
49
|
* the report shows one entry per alias, first `from` to last `to`. */
|
|
80
50
|
function collapseChanges(changes) {
|
|
@@ -98,9 +68,11 @@ function readActiveTheme(themesDir) {
|
|
|
98
68
|
return theme ? { slug, theme } : null;
|
|
99
69
|
}
|
|
100
70
|
|
|
101
|
-
/** Each component's live config and
|
|
102
|
-
*
|
|
103
|
-
*
|
|
71
|
+
/** Each component's live config, and whether a buffer or the open document
|
|
72
|
+
* answered. The document's own copy falls back to the shipped default for a
|
|
73
|
+
* component it somehow lacks, which reports as the document either way.
|
|
74
|
+
* Mirrors the dev server's `resolveLiveComponentConfig`, so the CLI adjusts
|
|
75
|
+
* what the page runs. */
|
|
104
76
|
function readLiveConfigs(dir, active) {
|
|
105
77
|
const configs = {};
|
|
106
78
|
const sources = {};
|
|
@@ -109,13 +81,19 @@ function readLiveConfigs(dir, active) {
|
|
|
109
81
|
const comp = entry.name;
|
|
110
82
|
const componentDir = join(dir, comp);
|
|
111
83
|
const working = readJsonIfExists(join(componentDir, '_working.json'));
|
|
112
|
-
|
|
113
|
-
|
|
84
|
+
// Every theme carries every component by value, but this CLI reads the
|
|
85
|
+
// file straight off disk, ahead of any server-side fill — a theme
|
|
86
|
+
// written before this component existed can still omit it, so a missing
|
|
87
|
+
// entry falls back to the shipped default the same way the theme's own
|
|
88
|
+
// fill would.
|
|
89
|
+
const embedded =
|
|
90
|
+
active?.theme?.componentConfigs?.[comp] ?? readJsonIfExists(join(componentDir, 'default.json'));
|
|
91
|
+
const config = working ?? embedded;
|
|
114
92
|
if (!config) {
|
|
115
93
|
throw new Error(`component "${comp}": default.json is missing`);
|
|
116
94
|
}
|
|
117
95
|
configs[comp] = { ...config, component: comp };
|
|
118
|
-
sources[comp] = working ? 'working' :
|
|
96
|
+
sources[comp] = working ? 'working' : 'theme';
|
|
119
97
|
}
|
|
120
98
|
return { configs, sources };
|
|
121
99
|
}
|
|
@@ -173,7 +151,7 @@ export async function runAdjust({
|
|
|
173
151
|
components.push({
|
|
174
152
|
component,
|
|
175
153
|
source: sources[component],
|
|
176
|
-
changes
|
|
154
|
+
changes,
|
|
177
155
|
skips,
|
|
178
156
|
});
|
|
179
157
|
}
|
|
@@ -228,8 +206,7 @@ export function formatAdjustResult(result) {
|
|
|
228
206
|
|
|
229
207
|
const width = Math.max(0, ...entry.changes.map((c) => c.variable.length));
|
|
230
208
|
for (const c of entry.changes) {
|
|
231
|
-
|
|
232
|
-
lines.push(` ${c.snapped ? '!' : ' '} ${c.variable.padEnd(width)} ${c.from} → ${c.to}${note}`);
|
|
209
|
+
lines.push(` ${c.variable.padEnd(width)} ${c.from} → ${c.to}`);
|
|
233
210
|
}
|
|
234
211
|
|
|
235
212
|
for (const [reason, label] of SKIP_LABELS) {
|
package/bin/generate-theme.mjs
CHANGED
|
@@ -21,7 +21,9 @@ import { fileURLToPath } from 'node:url';
|
|
|
21
21
|
const pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
22
22
|
const ENGINE = resolve(pkgRoot, 'dist-plugin/generateColorsAndType/index.js');
|
|
23
23
|
const packageDataDir = join(pkgRoot, 'src/live-tokens/data');
|
|
24
|
-
|
|
24
|
+
// Source of truth: vite-plugin/themes/normalizeTheme.ts. This copy cannot
|
|
25
|
+
// import TS, so `check:preset-themes` (Wave 5) is what catches a drift.
|
|
26
|
+
const THEME_SCHEMA_VERSION = 4;
|
|
25
27
|
|
|
26
28
|
async function loadEngine() {
|
|
27
29
|
if (!existsSync(ENGINE)) {
|
|
@@ -69,11 +71,18 @@ function stripMarkers(value) {
|
|
|
69
71
|
return rest;
|
|
70
72
|
}
|
|
71
73
|
|
|
74
|
+
/** A component's derived default, local tree first, then the installed
|
|
75
|
+
* package's shipped copy — same fallback order every other read here uses. */
|
|
76
|
+
function defaultComponentConfig(componentConfigsDir, comp) {
|
|
77
|
+
return readData(join(componentConfigsDir, comp), `component-configs/${comp}`, 'default');
|
|
78
|
+
}
|
|
79
|
+
|
|
72
80
|
/**
|
|
73
81
|
* The look the new theme carries forward. Without --carry-from that is the LIVE
|
|
74
82
|
* state — buffer first, then the open theme, then the shipped default — because
|
|
75
83
|
* what the user sees is what they expect to keep. With it, the named theme,
|
|
76
|
-
*
|
|
84
|
+
* then the shipped default for anything that theme omits, so an incomplete
|
|
85
|
+
* source never produces an incomplete result.
|
|
77
86
|
*/
|
|
78
87
|
function resolveCarrySource({ carryFrom, colorsAndTypeDir, componentConfigsDir, themesDir }) {
|
|
79
88
|
const comps = componentNames(componentConfigsDir);
|
|
@@ -83,7 +92,7 @@ function resolveCarrySource({ carryFrom, colorsAndTypeDir, componentConfigsDir,
|
|
|
83
92
|
if (!theme) throw new Error(`--carry-from theme "${carryFrom}" not found`);
|
|
84
93
|
const componentConfigs = {};
|
|
85
94
|
for (const comp of comps) {
|
|
86
|
-
const cfg = theme.componentConfigs?.[comp];
|
|
95
|
+
const cfg = theme.componentConfigs?.[comp] ?? defaultComponentConfig(componentConfigsDir, comp);
|
|
87
96
|
if (cfg) componentConfigs[comp] = stripMarkers(cfg);
|
|
88
97
|
}
|
|
89
98
|
return { colorsAndType: stripMarkers(theme.colorsAndType), componentConfigs };
|
|
@@ -98,12 +107,15 @@ function resolveCarrySource({ carryFrom, colorsAndTypeDir, componentConfigsDir,
|
|
|
98
107
|
);
|
|
99
108
|
|
|
100
109
|
// A working buffer is an unsaved delta from the active theme; absent theme
|
|
101
|
-
// component entries fall through to the component defaults.
|
|
110
|
+
// component entries fall through to the component defaults. Mirrors
|
|
111
|
+
// `bin/adjust.mjs`'s `readLiveConfigs` and the dev server's
|
|
112
|
+
// `resolveLiveComponentConfig` — all three layers, in the same order.
|
|
102
113
|
const componentConfigs = {};
|
|
103
114
|
for (const comp of comps) {
|
|
104
115
|
const live =
|
|
105
116
|
readJsonIfExists(join(componentConfigsDir, comp, '_working.json')) ??
|
|
106
|
-
activeTheme?.componentConfigs?.[comp]
|
|
117
|
+
activeTheme?.componentConfigs?.[comp] ??
|
|
118
|
+
defaultComponentConfig(componentConfigsDir, comp);
|
|
107
119
|
if (live) componentConfigs[comp] = stripMarkers(live);
|
|
108
120
|
}
|
|
109
121
|
return { colorsAndType, componentConfigs };
|
|
@@ -121,7 +133,8 @@ export async function runGenerateTheme({
|
|
|
121
133
|
themesDir,
|
|
122
134
|
engine,
|
|
123
135
|
} = {}) {
|
|
124
|
-
const { buildColorsAndTypeFromSeeds, resolveDataDirs } =
|
|
136
|
+
const { buildColorsAndTypeFromSeeds, resolveDataDirs, CURRENT_COMPONENT_SCHEMA_VERSION } =
|
|
137
|
+
engine ?? (await loadEngine());
|
|
125
138
|
|
|
126
139
|
const briefFull = resolve(root, briefPath);
|
|
127
140
|
if (!existsSync(briefFull)) {
|
|
@@ -162,6 +175,7 @@ export async function runGenerateTheme({
|
|
|
162
175
|
schemaVersion: THEME_SCHEMA_VERSION,
|
|
163
176
|
colorsAndType,
|
|
164
177
|
componentConfigs: carry.componentConfigs,
|
|
178
|
+
componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION,
|
|
165
179
|
};
|
|
166
180
|
|
|
167
181
|
if (!dryRun) {
|