@motion-proto/live-tokens 0.32.0 → 0.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,1350 @@
1
+ # Changelog
2
+
3
+ ## 0.33.1 — Ship the changelog in the package
4
+
5
+ ### Fixed
6
+
7
+ - **`CHANGELOG.md` now ships in the published package.** The `files` allowlist in
8
+ `package.json` omitted it, and npm only auto-includes `package.json` / `README` /
9
+ `LICENSE` on top of an allowlist, so every tarball through 0.33.0 shipped without a
10
+ changelog. Added it to `files`. Consumer tooling that diffs changelogs across versions
11
+ could not see one before this.
12
+
13
+ ## 0.33.0 — ImageLightbox maxZoom cap
14
+
15
+ ### Added
16
+
17
+ - **`ImageLightbox` `maxZoom` prop.** Caps how far the `extended` zoom controls can
18
+ magnify, as a multiple of the image's natural resolution: `maxZoom={1}` = 100% of the
19
+ source's real pixels (1 source px = 1 screen px), `maxZoom={2}` = 200%. The modal
20
+ always opens fitted to the viewport; this only bounds zoom-in. An image whose fitted
21
+ size already exceeds the cap can't be zoomed in (the control disables). Per image in a
22
+ gallery. Reads the natural pixel size from `width`/`height` or the loaded image; until
23
+ that's known the previous 5×-the-fit cap applies. The toolbar percent stays
24
+ fit-relative (fit = 100%).
25
+
26
+ ## 0.32.0 — Image grow-vs-mask zoom; canonical easing/color/type primitives
27
+
28
+ ### Added
29
+
30
+ - **`Image` `overflowScaling` prop.** When hover zoom is active, `overflowScaling`
31
+ decides what the scale grows. `true` (default) scales the content inside the fixed
32
+ frame, masked by overflow (the existing behavior). `false` scales the whole framed
33
+ image so it grows past its layout box. `undefined` inherits the editor's global
34
+ default. Set on its own (without `zoom`) it forces zoom on in the chosen mode. Backed
35
+ by a new `--image-grow-hover` token; at most one of `--image-zoom-hover` /
36
+ `--image-grow-hover` is ever active. The Image editor gains an "Overflow scaling (mask
37
+ zoom to frame)" checkbox alongside "Use zoom on hover".
38
+ - **Canonical Layer-1 primitives now ship in `tokens.css`** and are carried to vendored
39
+ copies by a paired migration (`2026-06-04-easing-color-and-typescale-additions`): the
40
+ full `--ease-*` easing scale (sine/quad/cubic/quart/quint/expo/circ/back plus
41
+ `linear()` elastic and bounce curves), the `--color-white` / `--color-black`
42
+ invariants, and `--font-size-7xl`. The migration is idempotent by presence (retuned
43
+ steps are kept; only absent ones are inserted) — run `npx live-tokens migrate` to
44
+ backfill a forked `tokens.css`. Fixes 0.31's Image zoom snapping with no ease when a
45
+ vendored `tokens.css` lacked `--ease-out-cubic`.
46
+ - **`--scale-*` tokens surfaced in the editor's Variables tab** (new "Scale" group).
47
+
48
+ ## 0.31.0 — Image Lightbox galleries; fixed overlays escape their ancestors
49
+
50
+ ### Added
51
+
52
+ - **`ImageLightbox` gallery mode.** Pass `images={[{ src, alt, width?, height? }]}`
53
+ (two or more) and the open modal gains left/right chevrons, an `i / n` counter
54
+ (bottom-right, mono), and `←`/`→` keyboard navigation. A single-entry array (or a
55
+ lone `src`) behaves exactly as before — no chevrons, no counter. Navigation runs a
56
+ directional slide+scale+crossfade: the incoming image enters from the side of the
57
+ pressed chevron (right/next → from the right), shifting 32px as it scales from 0.95 and
58
+ fades in (250ms, ease-out, 125ms stagger); the outgoing image leaves the opposite way
59
+ (250ms, ease-in). Differing aspect ratios resize the stage underneath the crossfade.
60
+ - **`ImageLightbox` self-measures.** `width`/`height` are now optional. The aspect ratio
61
+ is read from the loaded `<img>` (`naturalWidth`/`naturalHeight`); explicit dimensions,
62
+ when given, still win and avoid the pre-load reflow. Consumers without dimension
63
+ metadata no longer need glue. The inline thumbnail measures the cover image
64
+ independently of the open modal (aspect ratios are tracked per image), so paging a
65
+ gallery never resizes the thumbnail. A dimensionless image still has a brief pre-load
66
+ reflow; pass `width`/`height` to reserve its box.
67
+ - **`ImageLightbox` `fit` prop.** `fit="cover"` crops the closed thumbnail to fill its
68
+ box (the expanded modal always uses `contain`, so the whole image stays visible).
69
+ Backed by a new `--imagelightbox-tile-object-fit` token (default `contain`). `cover`
70
+ only crops when the thumbnail has its own box (an aspect from `width`/`height`, or a
71
+ CSS-constrained container).
72
+ - **Shared `portal` action** (`src/system/internal/portal.ts`) and a
73
+ **`check:overlay-portal`** publish gate. Any component whose `<style>` declares
74
+ `position: fixed` must portal that layer via `use:portal`, or the build fails. Anchored
75
+ `position: absolute` popovers (`Tooltip`) are exempt.
76
+
77
+ ### Fixed
78
+
79
+ - **Fixed-position overlays no longer get clipped or painted under other content.** A
80
+ `position: fixed` modal is only window-relative while no ancestor establishes a
81
+ containing block or stacking context for it; a transformed / `isolation: isolate` /
82
+ `contain` / `will-change` ancestor (common on real pages, and present on the editor's
83
+ own preview pane) silently traps it. `ImageLightbox`'s modal and `Dialog`'s backdrop
84
+ now portal to `<body>` (`use:portal`), escaping such ancestors. `Dialog`'s `inline`
85
+ preview variant stays in flow (`use:portal={!inline}`); `enabled` is read once at mount.
86
+ Because the layer lives at `<body>`: DOM events from it no longer bubble to a consumer
87
+ ancestor; a subtree-scoped CSS-variable theme no longer reaches it (this library themes
88
+ via `:root`, so unaffected in practice); and an SSR `show=true` renders in flow on the
89
+ server, then relocates on hydration.
90
+
91
+ ### Changed
92
+
93
+ - **`ImageLightbox` internals restructured.** The inline thumbnail is now its own
94
+ `<button>` that stays in flow; the overlay, morphing stage, and chrome render in a
95
+ separate body-portaled layer. The zoom-from-thumbnail open/close morph, drag/zoom
96
+ panning, and `extended` toolbar are unchanged. `prefers-reduced-motion` is now honored
97
+ (all transitions collapse to an instant swap).
98
+ - **`ImageLightbox` modal is now an accessible dialog.** It exposes `role="dialog"` +
99
+ `aria-modal` with a label (the image's `alt`, or `Image N of M` in a gallery), moves
100
+ focus into the modal on open and restores it to the thumbnail on close, traps `Tab`
101
+ within the modal, and announces the gallery position via a polite live region.
102
+
103
+ ## 0.30.0 — Images lazy-load and stay responsive; card titles truncate
104
+
105
+ ### Added
106
+
107
+ - **`Image` forwards the responsive-image attributes.** New optional props
108
+ `srcset`, `sizes`, `loading`, and `decoding` pass straight through to the
109
+ underlying `<img>`. `loading` defaults to `'lazy'` and `decoding` to
110
+ `'async'`, so content images defer off-screen work with no consumer change.
111
+ Pass `loading="eager"` for an above-the-fold hero.
112
+
113
+ ### Changed
114
+
115
+ - **`Card` titles truncate instead of wrapping.** The title now clips to a
116
+ single line with an ellipsis (`overflow: hidden; white-space: nowrap;
117
+ text-overflow: ellipsis`, plus `min-width: 0` so it can shrink inside the
118
+ flex header), keeping card headers to a fixed height regardless of title
119
+ length.
120
+
121
+ ## 0.29.0 — Image zoom-on-hover and a single slot-prose pin
122
+
123
+ ### Added
124
+
125
+ - **Images can zoom their contents on hover.** `Image` gains an optional `zoom`
126
+ prop and a global "Use zoom" editor intrinsic (the same gate-var + tri-state
127
+ pattern as Card hover): `zoom={undefined}` inherits the editor default,
128
+ `true`/`false` force one instance on or off. The frame stays fixed; only the
129
+ `<img>` scales, via `transform: scale(var(--image-zoom-scale))` with a
130
+ `--duration-300`/`--ease-out-cubic` transition. `CardEditor` and `ImageEditor`
131
+ now export `intrinsics`, registered in the component registry.
132
+ - **`--scale-{sm..2xl}` transform-multiplier scale in `tokens.css`** (1.05 → 1.25,
133
+ 5% per step), consumed by the image zoom above and surfaced in the editor as
134
+ the `SCALE` variant. Ships with a paired `tokens.css` migration
135
+ (`2026-06-03-transform-scale-additions`): run `npx live-tokens migrate` to add
136
+ the scale to a vendored `tokens.css`, or the picker shows a blank slot for
137
+ `--image-zoom-scale`.
138
+ - **`check:slot-prose` publish gate.** Fails the build if a slot-rendering
139
+ component hand-rolls the slot-typography pin (a `:global(p|ul|ol|li)` rule set
140
+ to the literal `inherit`) instead of `@include slot-prose`. Added to
141
+ `prepublishOnly`.
142
+
143
+ ### Fixed
144
+
145
+ - **Consumer global element rules no longer repaint slotted content.** Components
146
+ render the consumer's raw HTML in the same light-DOM tree, so a consumer's
147
+ global `p` / `ul li` rules (for example in `site.css`) matched slotted elements
148
+ and beat the container's body typography (the serif-card bug). The pin now
149
+ lives in one place, `src/system/styles/_slot-prose.scss`, applied via
150
+ `@include slot-prose` on `Card`, `CollapsibleSection`, and `Image`. Three
151
+ diverging hand-copies had shipped before; `check:slot-prose` keeps them out.
152
+
153
+ ### Changed
154
+
155
+ - **The slot-prose pin is per-axis, not `font: inherit`.** It pins only the axes
156
+ a component owns (family, size, weight, line-height, colour, plus spacing
157
+ rhythm) and leaves `font-style`, `letter-spacing`, and `text-transform` free,
158
+ so a consumer's italics or tracking survive inside a card or section.
159
+ - **`Card` and `CollapsibleSection` gain a `prose` prop (default `true`).** Set
160
+ `prose={false}` to drop the pin and fully own slotted-content styling.
161
+ - `fonts.css` (generated from the production theme) swaps Fraunces for Manrope.
162
+
163
+ ## 0.28.1 — Docs load from the published package
164
+
165
+ ### Fixed
166
+
167
+ - **Guide chapters no longer fail to load in tarball consumers.** The `/docs`
168
+ page loaded chapter bodies with `import.meta.glob('./content/*.md', '?raw')`,
169
+ a Vite compile-time transform that esbuild's `optimizeDeps` leaves unexpanded
170
+ inside a pre-bundled `node_modules` dependency. Installed-package consumers
171
+ got an empty module, so every chapter threw "Chapter not found" (the package's
172
+ own demo app and `npm link`ed consumers were unaffected, which is why it
173
+ surfaced only once a consumer ran the package-owned `/docs` from the tarball).
174
+ Bodies now ship as a generated ES module (`content.generated.ts`) built from
175
+ the same `src/editor/docs/content/*.md` sources via `npm run sync:docs`, with
176
+ `check:docs-content` gating drift in CI. No consumer action required.
177
+
178
+ ## 0.28.0 — Dynamic routes without a router
179
+
180
+ ### Added
181
+
182
+ - **`<LiveTokensRouter>` gains a `resolve` prop for routes you can't enumerate.**
183
+ Pass `resolve: (path) => RouteEntry | null` to match params (`/module/:id`),
184
+ prefixes, or conditionally-gated paths in plain code, with no route syntax to
185
+ learn. Resolution order is `pages[path]`, then `resolve(path)`, then the
186
+ `pages['/']` fallback, so existing `pages`-only consumers are unaffected.
187
+ - **`RouteEntry` gains `props`.** A static or resolved entry can pass props to
188
+ its page, so one component can serve many paths (for example the matched id
189
+ or slug). The entry's `source` now drives "Page Source" on dynamic routes
190
+ too, so it can't desync from the dispatched page.
191
+
192
+ ## 0.27.0 — Docs ship with the package
193
+
194
+ ### Added
195
+
196
+ - **The user guide now ships with the package and renders in the editor
197
+ overlay.** `LiveTokensRouter` auto-owns a dev-only `/docs` route and adds a
198
+ "Docs" tab to the overlay nav (alongside "Components"), so every consumer can
199
+ reference the guide while building without vendoring a copy. A new
200
+ `@motion-proto/live-tokens/docs` export lets manual-overlay consumers mount
201
+ the same page. Disable or relocate via `editorRoutes={{ docs: false }}` (or a
202
+ string path), matching the existing `editor` / `components` overrides.
203
+
204
+ ### Changed
205
+
206
+ - The docs renderer and markdown content moved from the demo app into the
207
+ package at `src/editor/docs/` (chapters under `src/editor/docs/content/`), so
208
+ the guide is a single source of truth that ships in the tarball.
209
+ - `marked` and `highlight.js` are now runtime dependencies (the docs renderer
210
+ needs them at the consumer).
211
+
212
+ ## 0.26.0 — Default theme + manifest live from the package
213
+
214
+ ### Changed
215
+
216
+ - **The default theme and default manifest now resolve live from the installed
217
+ package** instead of a vendored local copy. The dev plugin's resource server
218
+ gained a read-only package-directory fallback, so a consumer whose pointer is
219
+ `default` picks up the library's updated defaults on `npm upgrade`, while a
220
+ consumer on a custom theme or manifest is left untouched and keeps a current
221
+ baseline to restore to. Component defaults are unchanged: they still derive
222
+ from each component's shipped `.svelte` `:global(:root)` block.
223
+ - **`themes/default` is now read-only (PUT returns 403)**, symmetric with the
224
+ existing manifest and component-config guards. The default is owned by the
225
+ package, not the consumer.
226
+
227
+ ### Added
228
+
229
+ - Ship `themes/default.json` and `manifests/default.json` in the package tarball
230
+ (the live source for the fallback above).
231
+ - `check:production-is-default` publish gate: the shipped production baseline
232
+ (theme, manifest, and every component) must resolve to `default`, so a
233
+ production-only consumer never inherits a maintainer's custom palette.
234
+
235
+ ### Removed
236
+
237
+ - The empty-seed writers that wrote a local `themes/default.json` and
238
+ `manifests/default.json` on first dev-server start. Those would shadow the
239
+ package default under the new model. Also removed the dead `presets/` to
240
+ `manifests/` one-shot migration.
241
+
242
+ ## 0.25.1 — Drop unused Mermaid dependency
243
+
244
+ ### Removed
245
+
246
+ - **`mermaid` devDependency and `MermaidDiagram.svelte`.** The docs site stopped
247
+ rendering Mermaid when the developer-reference chapters moved to
248
+ `docs/archive/` (off the non-recursive `docs/*.md` glob in `chapters.ts`). The
249
+ only remaining ` ```mermaid ` fences live in those archived chapters, which no
250
+ longer load, so the lazy-loaded `mermaid` package (~700kB) was unreachable.
251
+ Removed the dependency, the `MermaidDiagram` component, and the mermaid
252
+ handling in `Docs.svelte`. No consumer impact: `mermaid` was a
253
+ devDependency and never shipped in the tarball.
254
+
255
+ ## 0.25.0 — Panel component; structural group-key derivation
256
+
257
+ ### Added
258
+
259
+ - **New `Panel` component.** A bordered, centered stage for showcasing other
260
+ components against a subtle gradient surface. Registered in the catalogue and
261
+ editable in the editor (frame border/radius, stage surface/padding/gap). Props
262
+ are `style`, an optional `minHeight` to fix the stage height so it never
263
+ reflows, and a `children` snippet.
264
+ - **`SideNavigation` gains `lead` and `actions` snippets.** `lead` renders at
265
+ the top of the rail above the title (e.g. a logo or company name); `actions`
266
+ renders at the foot of the nav list. Both hide while the rail is collapsed and
267
+ impose no spacing of their own — the consumer controls it.
268
+ - **New scaffolding exports** from `@motion-proto/live-tokens/component-editor`:
269
+ `buildTypeGroupColorTokens`, `buildTypeGroupFontTokens`,
270
+ `buildTypeGroupShareableContexts`, `structuralGroupKey`, and the
271
+ `TypeGroupConfig` type. Custom-component authors can now reach the individual
272
+ pieces of the type-group scaffolding instead of only the bundled
273
+ `buildTypeGroupTokens`.
274
+
275
+ ### Changed
276
+
277
+ - **Group-key derivation is now structural.** `buildTypeGroupTokens` no longer
278
+ infers a token's group from its last dash-segment; it derives the key by
279
+ stripping the component prefix and the variant/state segments declared in the
280
+ new `{ component, variants }` config. All 11 type-group editors were migrated
281
+ to pass this config, and the bespoke SideNavigation/Table workarounds were
282
+ removed. Existing editors' sibling partitions are verified unchanged; this
283
+ matters only for a custom editor that relied on the old last-dash fallback —
284
+ a token with no derivable group now resolves to a solo color token instead of
285
+ being silently grouped.
286
+ - `bin/check-component` now warns (non-fatal) when a component uses a bare font
287
+ helper across multiple slots.
288
+
289
+ ### Changed (breaking)
290
+
291
+ These shift the rendered defaults of shipped components. Consumers who edited
292
+ the affected tokens keep their values; unedited tokens fall through to the new
293
+ defaults on upgrade.
294
+
295
+ - **Button text and icon scale up.** Default text font-size `md → lg` and icon
296
+ size `sm → md` across every variant (primary, secondary, outline, success,
297
+ danger, warning).
298
+ - **Section Divider small variant restyled.** Title is now brand-colored and
299
+ center-aligned, the hairline is off by default, title font-size `2xl → 3xl`
300
+ at medium (was bold) weight, and the outer padding is removed. The large and
301
+ medium variants are unchanged apart from dropping their `space-4` outer
302
+ padding.
303
+
304
+ ### Fixed
305
+
306
+ - **CodeSnippet no longer shows a spurious horizontal scrollbar.** Added a
307
+ `box-sizing: border-box` reset so the snippet's own padding and border stay
308
+ inside `max-width: 100%`. Its code text now uses `--text-brand` (was
309
+ `--text-brand-secondary`).
310
+
311
+ ### Docs
312
+
313
+ - Documentation reorganized: the numbered chapter set moved under
314
+ `docs/archive/`, and the consumer-facing guides (`getting-started`,
315
+ `creating-components`, `editing-tokens`, `themes-workflow`, `01-overview`)
316
+ were rewritten. The demo landing page was restructured (new footer and
317
+ get-started sections; the old "live" section removed).
318
+
319
+ ## 0.24.2 — Demo cosmetic tweaks
320
+
321
+ ### Changed
322
+
323
+ - Minor color tweaks to the demo landing page (hero tagline contrast and the
324
+ floating token-tag text color). No catalogue component, token, or API change.
325
+
326
+ ## 0.24.1 — Section Divider editor controls match rendered defaults
327
+
328
+ ### Fixed
329
+
330
+ - **Section Divider editor controls no longer default to a state the component
331
+ never renders.** The alignment dropdown defaulted to "Center" while an
332
+ unedited divider rendered left-aligned, so choosing "Center" fired no change
333
+ event and appeared to do nothing. The eyebrow / description visibility and
334
+ hairline controls had the same per-variant disagreement. The editor's
335
+ read-back now sources each per-variant default from the runtime
336
+ `:global(:root)`, so the controls reflect what the page actually shows.
337
+
338
+ ### Added
339
+
340
+ - **Intrinsics are now a tested surface.** Structural / display properties an
341
+ editor drives outside the token grid (alignment, visibility, position) are
342
+ declared as `intrinsics: IntrinsicSpec[]` and pinned to the runtime
343
+ `:global(:root)` defaults by a universal contract test, so an editor default
344
+ can't silently drift from what the component renders. `IntrinsicSpec` is
345
+ exported from `@motion-proto/live-tokens/component-editor`.
346
+
347
+ ## 0.24.0 — Grouped editor token lists; CodeSnippet horizontal scroll
348
+
349
+ ### Added
350
+
351
+ - **CodeSnippet scrolls long lines horizontally.** Long code no longer truncates
352
+ with an ellipsis; it scrolls on the x-axis behind a thin styled scrollbar, and
353
+ the copy button stays pinned to the top-right. Two new tokens style the
354
+ scrollbar, both editable in the CodeSnippet panel:
355
+ `--codesnippet-scrollbar-thumb` (thumb color) and
356
+ `--codesnippet-scrollbar-border-width` (scrollbar thickness).
357
+
358
+ ### Changed
359
+
360
+ - **Editor token lists are now split into labeled element groups.** Ten
361
+ component editors (Callout, CodeSnippet, InlineEditActions, Input, MenuSelect,
362
+ ProgressBar, SegmentedControl, TabBar, Toggle, Tooltip) group their tokens
363
+ into labeled sections (frame / text / icon and structural parts like track,
364
+ thumb, divider, indicator, scrollbar) via the `element` field instead of one
365
+ flat list per state. Editor-only change: rendered output for existing tokens,
366
+ token names, and component APIs are unchanged, so existing themes and
367
+ component-configs are unaffected.
368
+
369
+ ## 0.23.0 — Extend the spacing scale at the top end
370
+
371
+ ### Added
372
+
373
+ - **`--space-40` (2.5rem) and `--space-128` (8rem).** The spacing scale gained a
374
+ step between 32 and 48, and a new large value above 96, for section- and
375
+ page-level layout. `--space-64` and `--space-96` (already defined but not
376
+ surfaced) now appear in the editor's Spacing panel too. Displayed scale is now
377
+ `2 4 6 8 10 12 16 20 24 32 40 48 64 96 128`.
378
+
379
+ ### Removed
380
+
381
+ - **`--space-80` (5rem).** Defined but unused and never surfaced in the editor;
382
+ it broke the monotonic step growth at the top of the scale. Direct consumers
383
+ of `--space-80` should remap to `--space-64`, `--space-96`, or `--space-128`.
384
+
385
+ ## 0.22.1 — Add LICENSE files
386
+
387
+ ### Added
388
+
389
+ - **`LICENSE` (MIT).** The package already declared `"license": "MIT"` in
390
+ `package.json` but shipped without the license text. Both
391
+ `@motion-proto/live-tokens` and `@motion-proto/create-live-tokens` now include
392
+ an MIT `LICENSE` file in their published tarballs. No code changes.
393
+
394
+ ## 0.22.0 — Component defaults synced to the reference demo
395
+
396
+ ### Changed
397
+
398
+ - **Baked-in component defaults refreshed to match the reference demo.** The
399
+ `:global(:root)` defaults in 8 shipped components (Badge, CollapsibleSection,
400
+ CornerBadge, MenuSelect, Notification, ProgressBar, SectionDivider,
401
+ SegmentedControl) had drifted from the project's tuned config; they now match,
402
+ so a fresh install renders like the demo. Visual default change only — no
403
+ token names, aliases, or APIs changed, so existing themes and
404
+ component-configs keep overriding exactly as before.
405
+ - **SegmentedControl**: selected pill uses brand surface/border (was success
406
+ green); disabled surface is transparent; hover surface softened.
407
+ - **SectionDivider**: backgrounds are transparent (the demo's gradients are
408
+ `type: none`); titles, eyebrows, and hairlines retuned.
409
+
410
+ ### Added
411
+
412
+ - **`sync:component-defaults` + `check:component-defaults`.** The sync script
413
+ pushes editor-tuned config values back into the component `.svelte` source
414
+ (the "adopt to source" step), and `check:component-defaults` — wired into
415
+ `prepublishOnly` — fails the release if any component's baked default drifts
416
+ from its config. The `.svelte` default and the editor config stay one source.
417
+
418
+ ## 0.21.2 — Export the scaffolding engine
419
+
420
+ ### Added
421
+
422
+ - **`@motion-proto/live-tokens/create` export** exposing `createApp`
423
+ (plus `runCreate` / `formatCreateResult`), the engine behind the `create`
424
+ subcommand. This lets the `@motion-proto/create-live-tokens` initializer
425
+ reuse the exact template and version-matched token seeds without duplicating
426
+ them — the groundwork for `npm create @motion-proto/live-tokens`. No change
427
+ to the `create` subcommand itself.
428
+
429
+ ## 0.21.1 — Recommended project layout
430
+
431
+ ### Added
432
+
433
+ - **README "Recommended project layout" section.** Documents the integration
434
+ surface `create` produces (vendored `tokens.css`, editor state under `src/`,
435
+ `vitePreprocess`, clean peer resolution with no `legacy-peer-deps`) and the
436
+ invariant that keeps upgrades non-destructive: all editable state is committed
437
+ under `src/`, never inside `node_modules`. The `create` template's README
438
+ links to it.
439
+
440
+ ## 0.21.0 — Scaffold a new app with `create`
441
+
442
+ ### Added
443
+
444
+ - **`npx @motion-proto/live-tokens create <dir>` scaffolds a working app.**
445
+ It generates a thin Svelte + Vite project that *depends on* the package
446
+ (`vite.config.ts` with `themeFileApi`, `main.ts` calling `bootLiveTokens`,
447
+ an `App.svelte` using `<LiveTokensRouter>`, and a placeholder
448
+ `src/pages/Home.svelte`), then seeds `tokens.css`, `tokens.generated.css`,
449
+ and `site.css` from the installed package so they never drift from the
450
+ version you scaffolded against. `init` is an alias. Replaces the old
451
+ `npx degit motionproto/live-tokens` route, which cloned the entire package
452
+ repo (source, tests, and all) instead of producing a consumer app.
453
+ - **`check:smoke-create` release gate.** Packs the tarball, runs the shipped
454
+ `create`, installs the generated app against the tarball with no
455
+ `--legacy-peer-deps`, and builds it. Wired into `prepublishOnly`, so a
456
+ broken scaffold or a template missing from the tarball cannot ship.
457
+
458
+ ## 0.20.1 — Color opacity is a property of a token
459
+
460
+ ### Changed
461
+
462
+ - **Internal: translucent colors are modeled as a token plus an optional
463
+ opacity, not a separate value kind.** The editor's `CssVarRef` now has three
464
+ kinds (`token`, `literal`, `gradient`); a color below 100% is a `token`
465
+ carrying an `opacity`, and one serialize/parse pair
466
+ (`color-mix(in srgb, var(--token) NN%, transparent)`) backs every read and
467
+ write of a color value. No change to the on-disk config format, the generated
468
+ CSS, or any public API, so no migration is needed.
469
+
470
+ ### Fixed
471
+
472
+ - **Linked-block grouping no longer collapses distinct gradients into one
473
+ bucket.** Gradient refs were keyed by a stringified object, so every gradient
474
+ hashed to the same key; refs are now bucketed by their rendered CSS value.
475
+
476
+ ## 0.20.0 — Refreshed shipped component defaults
477
+
478
+ ### Changed
479
+
480
+ - **Baked-in component defaults updated across the shipped set.** The
481
+ `:global(:root)` defaults inside `src/system/components/*.svelte` (what a
482
+ fresh consumer sees before they touch the editor) were refreshed. This is a
483
+ visual default change: components installed at this version look different out
484
+ of the box, but no token names, aliases, or APIs changed, so existing themes
485
+ and component-configs keep overriding exactly as before.
486
+ - **Button** (`Button.svelte`): primary/secondary/outline/success/danger/warning
487
+ text steps up to `--font-size-md` / `--font-weight-semibold`, radius to
488
+ `--radius-xl`, and success/danger/warning border width drops to
489
+ `--border-width-1`. Small variant font size moves to `--font-size-sm`.
490
+ - **Callout** (`Callout.svelte`): label and body switch from `--font-serif` to
491
+ `--font-sans` at `--font-size-lg`; info border firms up to
492
+ `--border-info-medium`.
493
+ - **Card** (`Card.svelte`): translucent `color-mix` surfaces, per-side header
494
+ and body padding, larger title (`--font-size-2xl` / `--font-weight-medium`)
495
+ and body (`--font-size-xl`), icon at `--icon-size-2xl`.
496
+ - **CodeSnippet** (`CodeSnippet.svelte`): translucent surface, neutral border,
497
+ code text in `--text-brand-secondary` at `--font-size-md`.
498
+ - **Image** (`Image.svelte`): radius to `--radius-2xl`.
499
+ - **ImageLightbox** (`ImageLightbox.svelte`): overlay surface to a translucent
500
+ `color-mix` of `--color-neutral-950`.
501
+ - **Table** (`Table.svelte`): translucent neutral wrapper/header surfaces,
502
+ heavier wrapper border, larger header (`--font-size-lg` / semibold) and cell
503
+ (`--font-size-md` / medium) type, visible column dividers.
504
+ - **Tooltip** (`Tooltip.svelte`): translucent surface, visible
505
+ `--border-width-1` border.
506
+
507
+ ### Fixed
508
+
509
+ - **Dev-server plugin now round-trips translucent surfaces.** When a component's
510
+ `:global(:root)` declares a color at reduced opacity
511
+ (`color-mix(in srgb, var(--token) NN%, transparent)`, the form the color
512
+ picker emits below 100% opacity), the plugin's `default.json` regeneration
513
+ preserves it. Previously only plain `var(--token)` aliases were captured, so
514
+ regeneration silently dropped translucent properties from the seed config,
515
+ leaving them blank in the editor and absent from adopt defaults.
516
+
517
+ ### Migration
518
+
519
+ - Consumers who want the previous look can pin their theme or component-config
520
+ values; nothing is removed, so no edits are required to keep an existing
521
+ setup working. The change only affects components rendered with the shipped
522
+ defaults.
523
+
524
+ ## 0.19.1 — Fresh install no longer needs `--legacy-peer-deps`
525
+
526
+ ### Fixed
527
+
528
+ - **`npm install @motion-proto/live-tokens` resolves cleanly on a fresh
529
+ machine.** `vite@8` declares an optional `sugarss@^5` peer while
530
+ `svelte-preprocess@6` declares `sugarss@^2 || ^3 || ^4`. The ranges don't
531
+ overlap, so npm rejected the whole tree with `ERESOLVE` even though `sugarss`
532
+ is never installed. We no longer depend on `svelte-preprocess`, so the
533
+ conflict is gone — no `--legacy-peer-deps`, no `.npmrc` workaround.
534
+
535
+ ### Changed
536
+
537
+ - **Preprocessing moved from `svelte-preprocess` to `vitePreprocess`** (bundled
538
+ in `@sveltejs/vite-plugin-svelte`). `svelte-preprocess` is removed from
539
+ `peerDependencies`; `@sveltejs/vite-plugin-svelte` (`^7.0`) is now a declared
540
+ peer. `sass` stays a peer — it compiles the components' `<style lang="scss">`
541
+ blocks under `vitePreprocess` exactly as before. The build-time PRUNE_FOR
542
+ pass that relied on svelte-preprocess's `replace` option now runs through a
543
+ local `replacePreprocess` helper (`vite-plugin/pruneMarkers/`).
544
+
545
+ ### Migration
546
+
547
+ - **Consumer `vite.config.ts`:** preprocess with `vitePreprocess()` instead of
548
+ a bare `svelte()`. The bare form never compiled the shipped components' scss
549
+ blocks, so this also closes a latent gap. Keep `sass` installed.
550
+
551
+ ```ts
552
+ import { svelte, vitePreprocess } from '@sveltejs/vite-plugin-svelte';
553
+ // ...
554
+ plugins: [svelte({ preprocess: vitePreprocess() }), themeFileApi({ /* ... */ })]
555
+ ```
556
+
557
+ Consumers who explicitly configured `svelte-preprocess` themselves can keep
558
+ it — nothing forces the switch — but it's no longer required or installed for
559
+ you.
560
+
561
+ ## 0.19.0 — Toggle, TabBar, SegmentedControl token model updates
562
+
563
+ ### Changed (breaking)
564
+
565
+ - **`Toggle` track dimensions are derived, not authored.** The runtime
566
+ now computes `track-width = thumb-size * 2 + track-padding * 2` and
567
+ `track-height = thumb-size + track-padding * 2`, so the explicit
568
+ `--toggle-track-width` and `--toggle-track-thickness` tokens are gone.
569
+ A new `--toggle-track-padding` knob controls the gap between thumb and
570
+ track edge. Auto-migrated: the `2026-05-29-toggle-derive-track-from-thumb`
571
+ component-config migration drops the two old tokens and seeds
572
+ `--toggle-track-padding` with `--space-2` when absent. Consumers who
573
+ customised track width will see geometry derive from their
574
+ `--toggle-thumb-size` after upgrade.
575
+ - **`TabBar` indicator stroke width is now per-state.** The bar-level
576
+ `--tabbar-bar-indicator-thickness` is replaced by
577
+ `--tabbar-{default,hover,active,disabled}-indicator-border-width`,
578
+ mirroring how indicator color already rebinds per state. The
579
+ `-border-width` suffix also lets the editor's picker classify the
580
+ token correctly (the old `-thickness` suffix rendered as a colour
581
+ picker). Auto-migrated by
582
+ `2026-05-29-tabbar-indicator-thickness-to-per-state-width`: the old
583
+ bar-level value seeds all four states, so the visual default is
584
+ preserved. Unset falls back to `--border-width-2`.
585
+ - **`SegmentedControl` small-size divider tokens renamed.**
586
+ `--segmentedcontrol-divider-small-thickness` →
587
+ `--segmentedcontrol-small-divider-thickness`, and the matching
588
+ `-inset` token. The picker recognises the value by suffix, so the
589
+ rename puts `-thickness` / `-inset` at the tail where the editor
590
+ classifies them as stroke width and inset instead of colour. Auto-
591
+ migrated by `2026-05-29-segmentedcontrol-small-divider-rename`.
592
+
593
+ ### Added
594
+
595
+ - **Three new component-config migrations** covering the renames above,
596
+ with regression tests in `migrations.test.ts`.
597
+
598
+ ## 0.18.2 — Publish workflow switches to `npm install`
599
+
600
+ ### Fixed
601
+
602
+ - **Publish workflow uses `npm install --include=optional` instead of
603
+ `npm ci`.** Releases are tagged from macOS, where `package-lock.json`
604
+ cannot capture the linux-only optional binaries that rolldown
605
+ (bundled with Vite 8) pulls in for the wasm32-wasi fallback path.
606
+ `npm ci` strict-checked the lockfile and exited EUSAGE on missing
607
+ `@emnapi/*` nodes; `npm install` resolves the tree per-platform from
608
+ `package.json`. Tag-matches-package.json gate remains the source of
609
+ truth for the publish identity. 0.18.0 and 0.18.1 both tagged but
610
+ never reached the publish step because of this.
611
+
612
+ ## 0.18.0 — Vite 8 / TypeScript 6 toolchain bump
613
+
614
+ ### Changed
615
+
616
+ - **Peer dependency: `vite` is now `^8`** (was `^6 || ^7`). Consumers
617
+ must upgrade to Vite 8 before installing this version. The
618
+ `@sveltejs/vite-plugin-svelte` v7 peer enforces this — v7 requires
619
+ Vite 8, and Vite 8's CSS pipeline (rolldown + lightningcss by default)
620
+ may surface latent CSS issues that the v7 pipeline tolerated.
621
+ - **Dev toolchain bumped to current majors:** `vite ^8.0.14`,
622
+ `@sveltejs/vite-plugin-svelte ^7.1.2`, `typescript ~6.0.3`,
623
+ `@types/node ^25.9.1`. Smoke-install consumer in
624
+ `scripts/smoke-install.sh` follows the same versions so the test
625
+ exercises the declared peer.
626
+ - **`tsconfig.json` adds `"ignoreDeprecations": "6.0"`** to silence the
627
+ TypeScript 6 deprecation warning emitted by `tsup`'s internal DTS
628
+ build (which injects `baseUrl`). Cosmetic only; no behaviour change.
629
+
630
+ ## 0.17.1 — SideNavigation re-toggles on current page
631
+
632
+ ### Fixed
633
+
634
+ - **`SideNavigation` collapses when its label is clicked on the current
635
+ page.** Previously, clicking a section label whose route was already
636
+ current produced a no-op navigation, so users had to chase the chevron
637
+ to collapse the section they had just opened. The label now intercepts
638
+ that click and toggles the section instead. Modified-click
639
+ (cmd/ctrl/shift/alt) and middle-click still fall through to the link,
640
+ and the chevron's own click is untouched.
641
+
642
+ ### Changed
643
+
644
+ - **Editor: removed hidden per-side padding entries** from
645
+ `CornerBadgeEditor`, `InputEditor`, `MenuSelectEditor`, and
646
+ `SegmentedControlEditor`. Each editor previously declared a `padding`
647
+ token alongside four `padding-top` / `-right` / `-bottom` / `-left`
648
+ entries flagged `hidden: true`. The hidden entries never reached the UI
649
+ and their `--*-padding-{top,right,bottom,left}` variables are not
650
+ referenced by the shipped components, so this is a cleanup of dead
651
+ configuration with no consumer-visible effect.
652
+
653
+ ## 0.17.0 — tokens.css migrations for Layer-1 drift
654
+
655
+ Layer-1 primitives live in the consumer's developer-authored
656
+ `tokens.css`, which the in-browser JSON migration system deliberately
657
+ never touches. When the package evolves its token vocabulary, a forked
658
+ `tokens.css` falls behind and components reference primitives that
659
+ resolve to nothing, surfacing as blank or `—` editor slots. This release
660
+ adds a Node-side, idempotent migration system that reconciles
661
+ `tokens.css` on demand, plus a boot guardrail that flags drift before it
662
+ shows up as empty slots.
663
+
664
+ ### Added
665
+
666
+ - **`live-tokens migrate` CLI.** `npx live-tokens migrate` applies
667
+ pending `tokens.css` migrations and writes the file in place as a
668
+ reviewable git diff. `npx live-tokens migrate --check` reports without
669
+ writing and exits 1 when changes are pending, so CI can gate on it.
670
+ The file is located via `--tokens <path>`, then the `tokensCssPath`
671
+ key in `live-tokens.config.json`, then a short default scan.
672
+ - **`tokensCssPath` config key.** Added to `live-tokens.config.json` so
673
+ the CLI can locate `tokens.css` without plugin options.
674
+ - **Boot guardrail.** The dev-server plugin (`themeFileApi`) runs a
675
+ read-only `validateTokensCss` check on boot. It scans every
676
+ component's `:global(:root)` block for `var(--…)` references and warns
677
+ about any primitive not defined in `tokens.css`, the generated
678
+ sidecar, or another component, naming the tokens and pointing at `npx
679
+ live-tokens migrate`. It never writes anything, so the "plugin never
680
+ writes `tokens.css`" invariant is preserved.
681
+ - **First migrations.** Add `--line-height-{xs..xl}`,
682
+ `--letter-spacing-*`, and `--ease-out-quart`. Remove legacy
683
+ `--sectiondivider-*` tokens that are not on the `lg`/`md`/`sm` axis.
684
+ Migrations are idempotent by presence (no `schemaVersion` to stamp on
685
+ CSS), so re-running the whole set is always safe.
686
+
687
+ ### Docs
688
+
689
+ - `docs/04-tokens-and-themes.md` gains a "tokens.css migrations
690
+ (Layer-1)" section covering the engine, the CLI, the guardrail, and
691
+ how to author a new migration.
692
+
693
+ ## 0.16.2 — CollapsibleSection collapses linked headers
694
+
695
+ ### Fixed
696
+
697
+ - **`CollapsibleSection` with `href` can now collapse.** When `href` was
698
+ set, the header rendered as a single `<a>` with no toggle handler, so
699
+ consumers like SideNavigation lost the ability to collapse sections
700
+ that were also routes. Click only ever navigated, and the chevron's
701
+ rotate was decorative. The `href` branch now renders the chevron as a
702
+ standalone `<button>` that fires `ontoggle`, with the label as a
703
+ sibling `<a>` link inside the same flex row. Hover, indicator, and
704
+ expanded paint still land on the row. The no-`href` branch is
705
+ unchanged.
706
+
707
+ ## 0.16.1 — SideNavigation header restructure
708
+
709
+ The SideNavigation title bar is now a single flex card hosting the label
710
+ box and the persistent toggle button as siblings. Previously the toggle
711
+ was an absolutely-positioned child of the rail with calc'd left/top
712
+ coordinates derived from the panel-width tokens. The new structure
713
+ removes that coupling: the header's `justify-content` plus `flex:1` on
714
+ the label naturally positions the toggle to the right of the label when
715
+ open and centres it in the rail when collapsed.
716
+
717
+ ### Changed (breaking)
718
+
719
+ - **SideNavigation title indicator and divider no longer render.** The
720
+ `border-left` accent strip and `border-bottom` divider on the title
721
+ bar were removed in favour of a card-shaped header driven by per-state
722
+ `surface` + `border` + `radius` chrome. Consumers who set
723
+ `--sidenavigation-title-<state>-accent` /
724
+ `--sidenavigation-title-<state>-accent-width` will see no rendered
725
+ effect; the tokens remain in shipped configs for backward compatibility
726
+ but no longer drive any pixels. Move customizations onto
727
+ `--sidenavigation-title-<state>-surface` /
728
+ `-border` / `-border-width` instead. The editor's "Title" sections
729
+ surface these (relabeled from "divider color / divider width /
730
+ indicator color / indicator width" to "border color / border width";
731
+ the two indicator rows are gone).
732
+
733
+ ### Added
734
+
735
+ - **Stateless Title Layout tokens.**
736
+ `--sidenavigation-title-gap` (space between label box and toggle box)
737
+ and `--sidenavigation-title-radius` (outer card corner radius). Exposed
738
+ in the editor under a new "Title Layout" section.
739
+ - **Stateless Title Label tokens.**
740
+ `--sidenavigation-title-label-surface`,
741
+ `--sidenavigation-title-label-radius`, and
742
+ `--sidenavigation-title-label-padding` style the inner label box that
743
+ sits beside the toggle in the open state. Exposed in the editor under
744
+ a new "Title Label" section.
745
+
746
+ ### Changed
747
+
748
+ - **Shipped `sidenavigation/default.json` tightened.** Drops the legacy
749
+ split `padding-top/right/bottom/left` keys (superseded by the
750
+ four-tuple `padding` tokens) and adjusts default text sizes (item and
751
+ footer text → `--font-size-sm` + `--font-weight-light` for
752
+ default/hover), icon sizes (footer → `--icon-size-xs`), and accent
753
+ widths (`--border-width-3` instead of `4`). Consumers with their own
754
+ `default.json` are unaffected; consumers relying on the shipped
755
+ default see a denser nav rail.
756
+
757
+ ### CI
758
+
759
+ - Bumped `actions/checkout` and `actions/setup-node` to `v6` in
760
+ `publish.yml` and `verify.yml`.
761
+
762
+ ## 0.15.0 — One-call boot + router wrapper
763
+
764
+ The library now provides two opt-in wrappers that collapse the boilerplate
765
+ every consumer used to copy out of the README: a single `bootLiveTokens`
766
+ call for `main.ts` and a `<LiveTokensRouter>` component for `App.svelte`.
767
+ Together they take a typical consumer's integration from ~80 lines of
768
+ hand-orchestrated init + overlay + route-dispatch to ~12 lines.
769
+
770
+ The library's own demo app (`src/app/main.ts`, `src/app/App.svelte`) has
771
+ been migrated to use the new wrappers as a dogfooded reference.
772
+
773
+ ### Added
774
+
775
+ - **`bootLiveTokens(App, target, opts?)`** — one-call bootstrap. Runs the
776
+ five idempotent `init*` hooks in the documented order, fetches the
777
+ active theme in dev, registers any consumer-authored components passed
778
+ via `opts.components` (dev-only), and mounts the app. Side-effect-
779
+ imports FontAwesome so the overlay's icons are present without the
780
+ consumer having to remember a separate import. Exported from the
781
+ package root.
782
+ - **`<LiveTokensRouter pages={…}>`** — overlay + columns + route
783
+ dispatch in one component. Drives `<LiveEditorOverlay>` and
784
+ `<ColumnsOverlay>` automatically, dynamic-imports `/editor` and
785
+ `/components` (so editor chrome stays out of non-editor route
786
+ bundles), auto-injects `Components` into the dev nav rail and the
787
+ page-source hide list, intercepts in-app `<a href="/…">` clicks for
788
+ client-side routing. Page entries can be eager (`component:
789
+ PageComponent`) or code-split (`lazy: () => import('./Page.svelte')`);
790
+ use `lazy` for any page that side-effect-imports a stylesheet at the
791
+ top of its module so those side effects stay out of the editor routes.
792
+ Pages without a `label` are reachable by URL but absent from the nav
793
+ rail (matches the existing playground pattern). `editorRoutes.editor`
794
+ and `editorRoutes.components` accept a string to relocate the default
795
+ route or `false` to disable it entirely (no dispatch and, for
796
+ `components`, no auto-injected nav-rail entry). Exported from the
797
+ package root along with `RouteEntry` and `EditorRouteOverrides` types.
798
+
799
+ ### Changed
800
+
801
+ - **`themeFileApi` default `componentsSrcDir` now scans both
802
+ `src/components` and `src/system/components`** when no explicit option
803
+ is passed. The Vite/Svelte convention is `src/components`, so new
804
+ consumers don't need an override; existing consumers with components in
805
+ `src/system/components` keep working without changes.
806
+ - **The component scanner skips `.svelte` files without a
807
+ `:global(:root) {}` block.** Previously any `.svelte` file in the scan
808
+ dir was treated as a runtime component, which meant editor companion
809
+ files (e.g. `Foo.editor.svelte` or `FooEditor.svelte`) co-located with
810
+ their runtime sibling would get a spurious `component-configs/foo.editor/`
811
+ entry and show up in the editor's components list. Theme-aware
812
+ components declare their tokens in a `:global(:root)` block; the
813
+ presence of that block is now the marker for "register as a component."
814
+ No filename convention required.
815
+
816
+ ### Lower-level APIs unchanged
817
+
818
+ `LiveEditorOverlay`, `ColumnsOverlay`, `initCssVarSync`, `initRouter`,
819
+ `initColumnsOverlay`, `initEditorStore`, `initializeTheme`,
820
+ `registerComponent`, and the editor page exports
821
+ (`@motion-proto/live-tokens/editor`,
822
+ `@motion-proto/live-tokens/component-editor-page`) all remain exported.
823
+ The new wrappers are pure composition over them — use them directly if
824
+ you need a custom shell or non-standard route dispatch.
825
+
826
+ ### README
827
+
828
+ The Quick install section now leads with `bootLiveTokens` +
829
+ `<LiveTokensRouter>`. The manual-orchestration pattern is documented
830
+ under a "Lower-level API" heading for consumers who need it.
831
+
832
+ ## 0.14.1 — Drop unused local font files
833
+
834
+ Cleanup of leftover state from the Google Fonts switch in 0.14.0.
835
+
836
+ ### Changed
837
+
838
+ - **Local `.woff2` font files removed.** 0.14.0 already excluded them from the
839
+ published package via the `files` list, so this is a repository cleanup
840
+ rather than a consumer-facing change. The `!src/system/styles/fonts/**`
841
+ exclusion is dropped (no longer needed). Published bundle size is unchanged
842
+ versus 0.14.0.
843
+ - **"Add local font" instruction updated.** The editor's font-add help text
844
+ used to direct users to drop `.woff2` files into
845
+ `src/system/styles/fonts/<Family>/` and claim the folder shipped with the
846
+ production build, which was the exact assumption that broke for consumers
847
+ pre-0.14.0. New copy points at `public/fonts/<Family>/`, a portable Vite
848
+ convention that works the same whether you're in a consumer or in this repo.
849
+
850
+ ## 0.14.0 — Multi-dir component scan, Google Fonts for defaults
851
+
852
+ ### Changed (breaking — automatic migration on theme load)
853
+
854
+ - **Default font sources moved to Google Fonts.** Manrope and Fraunces were
855
+ shipped as local woff2 files with `@font-face` blocks pointing at them. The
856
+ url() resolution for those refs was fragile when consumed via the published
857
+ package (paths leaked through Vite's CSS pipeline unrewritten). Defaults now
858
+ use Google Fonts CDN URL imports (`@import url('https://fonts.googleapis.com/...')`),
859
+ which sidesteps the rewriting entirely. Local woff2 font files are no longer
860
+ published with the package; consumers who depended on them via direct path
861
+ references will need to vendor their own or switch to Google Fonts too.
862
+ - **`migrateThemeFonts` auto-converts legacy local-font sources.** Any
863
+ `fontSources` entry with `kind: 'font-face'` whose cssText is a font-face
864
+ block for `Manrope` or `Fraunces` is rewritten to a Google Fonts URL source
865
+ on next theme load. Source ids and family ids are preserved so existing
866
+ fontStacks keep working.
867
+ - **Plugin `componentsSrcDir` scan now auto-includes the package's first-party
868
+ components dir.** Previously the scan only walked the consumer-provided dir,
869
+ so the editor's "registered components vs disk scan" validator would warn on
870
+ every first-party component (Badge, Button, …) when a consumer pointed
871
+ `componentsSrcDir` at their own components folder. Both dirs are scanned
872
+ now; consumer entries shadow first-party ones on name collision. The option
873
+ remains a single string for consumer code.
874
+
875
+ ## 0.13.3 — Diagnostic logging (temporary)
876
+
877
+ Adds `console.log` traces inside `LiveEditorOverlay` for the route↔editorView
878
+ pairing rule and for editorView subscriptions, prefixed `[lt-debug:parent]` /
879
+ `[lt-debug:iframe]`. Will be removed in 0.13.4. Use this only if you're
880
+ helping diagnose the components-view flicker reported on 0.13.1/0.13.2.
881
+
882
+ ## 0.13.2 — Fix font 404s for consumers
883
+
884
+ The bundled `fonts.css` and the default `fontSources[].cssText` both used
885
+ absolute URLs like `/src/system/styles/fonts/Manrope/Manrope-latin.woff2`,
886
+ resolved via Vite `?url` imports against the live-tokens repo layout. Those
887
+ paths only existed in this repo's own dev server; for any consumer importing
888
+ `@motion-proto/live-tokens/app/fonts.css`, the browser asked for them at the
889
+ consumer's server root and got back the dev HTML fallback (visible as `OTS
890
+ parsing error: invalid sfntVersion` in the console).
891
+
892
+ ### Fixed
893
+
894
+ - **Bundled `fonts.css` and default font sources now use package-relative
895
+ paths** (`./fonts/Fraunces/...`, `./fonts/Manrope/...`). The css file and
896
+ the `fonts/` directory ship colocated under `src/system/styles/` in the
897
+ package, so the relative url() resolves correctly whether served from
898
+ `node_modules` in a consumer, from this repo's dev server, or as a hashed
899
+ asset in a production build.
900
+ - **`migrateThemeFonts` auto-rewrites legacy absolute font paths.** Themes
901
+ saved before this change (with `fontSources[].cssText` containing
902
+ `/src/system/styles/fonts/...` or `/src/live-tokens/system/styles/fonts/...`)
903
+ are normalised to `./fonts/...` on next theme load and re-saved by the
904
+ editor. No consumer action required.
905
+
906
+ ## 0.13.1 — Fix /components route pairing flicker
907
+
908
+ The pairing rule introduced in 0.12.1 fired on every `editorView` change, not
909
+ just on route change. Combined with the cross-window `storage` sync between
910
+ parent and overlay iframe, a single click on the components toggle would
911
+ trigger a feedback cascade: store write → storage event → handler runs
912
+ subscribers → rule re-fires → another store write, etc. Each step pulled
913
+ heavy editor re-renders along with it (the storage handler regularly took
914
+ >1s in practice), producing a visible bounce as the view flickered between
915
+ tokens and components.
916
+
917
+ ### Fixed
918
+
919
+ - **`LiveEditorOverlay` route pairing now fires once per route change.** The
920
+ rule still sets the initial pairing when entering `/components` (overlay
921
+ flips to tokens to avoid stacking with the full-page editor), but does not
922
+ re-fire when the user toggles `editorView` while on that route. The user
923
+ can interact with the overlay's view switcher freely, no flicker.
924
+
925
+ ## 0.13.0 — Generated CSS lives with editor data
926
+
927
+ The plugin now writes `tokens.generated.css` to `<dataDir>/tokens.generated.css`
928
+ by default, alongside themes, manifests, and component-configs. Previously it
929
+ defaulted to `<tokensCssPath dir>/tokens.generated.css`, which silently landed
930
+ inside `node_modules/` for any consumer that pointed `tokensCssPath` at the
931
+ installed package — a path `npm ci` would happily wipe.
932
+
933
+ The generated file is editor-managed user content, conceptually the same as
934
+ themes and manifests, so it belongs in the data directory rather than coupled
935
+ to the read-only base tokens.css location.
936
+
937
+ ### Changed (breaking — one-line config or file move)
938
+
939
+ - **`tokensGeneratedCssPath` default moved from `<tokensCssPath dir>` to
940
+ `<dataDir>`.** No automatic migration; pick one:
941
+ - **Move the file** (recommended): relocate your existing
942
+ `tokens.generated.css` from wherever it lived (often
943
+ `src/system/styles/tokens.generated.css`) to `<dataDir>/tokens.generated.css`
944
+ and update your `main.ts` import to match.
945
+ - **Pin the old path**: pass
946
+ `tokensGeneratedCssPath: 'src/system/styles/tokens.generated.css'` (or your
947
+ previous location) explicitly to `themeFileApi()` in `vite.config.ts`.
948
+ - **Bundled `tokens.generated.css` relocated inside the package.** The
949
+ `@motion-proto/live-tokens/app/tokens.generated.css` export now resolves to
950
+ `./src/live-tokens/data/tokens.generated.css` (was
951
+ `./src/system/styles/tokens.generated.css`). Consumers importing via the
952
+ package export are unaffected; only the on-disk path inside `node_modules`
953
+ changed.
954
+
955
+ ## 0.12.1 — Overlay owns the /components route pairing
956
+
957
+ The mutual-exclusion rule that flips the overlay to Tokens view whenever the
958
+ page route is `/components` now lives inside `LiveEditorOverlay` itself.
959
+ Consumer App shells no longer need to import `editorView` or wire up the
960
+ pairing block by hand.
961
+
962
+ ### Changed
963
+
964
+ - **`LiveEditorOverlay` self-handles the /components route pairing.** Previously
965
+ each consumer's `App.svelte` had to subscribe to `route` + `editorView` and
966
+ force `editorView.set('tokens')` when the route hit `/components`, otherwise
967
+ the full-page component editor and the overlay's components view would stack.
968
+ The rule now fires from inside the overlay component, so any host that mounts
969
+ `<LiveEditorOverlay />` gets the behaviour for free. The starter's
970
+ `src/app/App.svelte` is updated to drop the duplicated block.
971
+
972
+ ## 0.12.0 — Toggle, CodeSnippet, and a Claude skill suite
973
+
974
+ Two new shipped components (`Toggle`, `CodeSnippet`) and a `live-tokens` CLI
975
+ that installs the bundled Claude Code skills into a consumer project in one
976
+ command. The single `live-tokens-add-component` skill is replaced by three
977
+ focused skills covering page composition, component selection, and new-component
978
+ authoring.
979
+
980
+ ### Added
981
+
982
+ - **`Toggle` component** (`src/system/components/Toggle.svelte` + editor).
983
+ On/off switch with tokenised track, thumb, label, and disabled state.
984
+ - **`CodeSnippet` component** (`src/system/components/CodeSnippet.svelte` +
985
+ editor). Syntax-highlighted code block with tokenised chrome and copy button.
986
+ - **`live-tokens` CLI** (`bin/cli.mjs`). Two subcommands:
987
+ - `npx @motion-proto/live-tokens setup-claude` — copies all bundled skills
988
+ into `./.claude/skills/` in the consumer project. `--force` overwrites
989
+ existing skill directories.
990
+ - `npx @motion-proto/live-tokens check-component <id>` — static validator
991
+ that enforces file layout, `:global(:root)` block, token-suffix vocabulary,
992
+ state-before-property rule, no-raw-colour-defaults rule, public-imports
993
+ rule, and `registerComponent({ id })` call. Useful as a post-authoring
994
+ check or pre-commit guard.
995
+
996
+ ### Changed
997
+
998
+ - **Claude Code skill suite reshaped.** The single `live-tokens-add-component`
999
+ skill is removed; three focused skills take its place:
1000
+ - `live-tokens-build-page` — composes pages from the shipped components.
1001
+ - `live-tokens-pick-component` — decides between confusable pairs (TabBar
1002
+ vs SegmentedControl, Card vs CollapsibleSection, Callout vs Notification,
1003
+ etc.) with decision tables per family.
1004
+ - `live-tokens-create-component` — authors a new editable component against
1005
+ the naming, state-model, and public-imports rules.
1006
+ Each auto-triggers from natural-language requests; no slash commands.
1007
+ - **Docs.** `docs/adding-components.md` renamed to `docs/creating-components.md`
1008
+ to align with the new skill name; cross-references updated.
1009
+ - **README.** Component count bumped from ~19 to ~24; new "Claude Code skills"
1010
+ section documents the suite and CLI install path.
1011
+
1012
+ ## 0.11.0 — Overlay scale trim and release pipeline cleanup
1013
+
1014
+ The overlay scale drops from seven stops to three. CI is now the only thing
1015
+ that publishes to npm; local `npm publish` is no longer part of the flow.
1016
+
1017
+ ### Changed (breaking for direct consumers of the dropped overlay tokens; auto-migrated for saved configs)
1018
+
1019
+ - **`--overlay-lowest` / `--overlay-lower` / `--overlay-higher` / `--overlay-highest` removed.**
1020
+ The kept stops are `--overlay-low`, `--overlay`, and `--overlay-high`.
1021
+ Saved theme files and component aliases are rebound automatically by
1022
+ `2026-05-26-drop-overlay-extra-stops` (theme v2 to v3, component-config v16 to v17).
1023
+ Consumers who reference the dropped tokens in their own CSS need to point
1024
+ at the nearest kept stop (`-lowest` and `-lower` to `-low`, `-higher` and
1025
+ `-highest` to `-high`).
1026
+
1027
+ ### Added
1028
+
1029
+ - **`--color-white` and `--color-black` invariants** in `tokens.css`. Hard
1030
+ constants outside any ramp; never themed.
1031
+
1032
+ ### Changed (internal, no consumer-visible API impact)
1033
+
1034
+ - Overlays editor section rewritten; `OverlaysSection.svelte` net 550
1035
+ lines lighter.
1036
+ - `UIPaletteSelector` and `UIRelinkConfirmPopover` refactored internally;
1037
+ the latter renamed to `UIRelinkConfirmDialog` (not part of any public export).
1038
+ - Release pipeline migrated to OIDC Trusted Publishing. `RELEASING.md`
1039
+ rewritten so the local steps stop at `git push --tags`; CI handles
1040
+ `npm publish` with provenance attestation. See the new "Publishing (how it
1041
+ actually happens)" section for the full picture.
1042
+
1043
+ ## 0.10.0 — Plugin acts like a dev tool, not a co-tenant
1044
+
1045
+ Live Tokens no longer squats on multiple top-level folders at a consumer's
1046
+ repo root. By default, all data (`themes/`, `manifests/`, `component-configs/`)
1047
+ lives under one folder: `src/live-tokens/data/`. A consumer's root looks like
1048
+ a normal project root again. This release also adds three new system
1049
+ components (`Input`, `SideNavigation`, `ImageLightbox`), a full set of named
1050
+ easing tokens, and several component-config schema cleanups (auto-migrated).
1051
+
1052
+ ### Added
1053
+
1054
+ - **`Input` component** (`src/system/components/Input.svelte` + editor).
1055
+ Supports `text` / `number` / `search` / `password` types, with `label`,
1056
+ `hint`, `error`, password reveal, search-clear, and a `forceFocus` preview
1057
+ hook for the editor.
1058
+ - **`SideNavigation` component** (`src/system/components/SideNavigation.svelte`
1059
+ + editor). Tokenised side-nav with collapsible groups, item icons, and
1060
+ active/hover states.
1061
+ - **`ImageLightbox` component** (`src/system/components/ImageLightbox.svelte`
1062
+ + editor). Click-to-zoom image with backdrop, escape-to-close, and
1063
+ tokenised overlay/chrome.
1064
+ - **Named easing tokens.** 28 curves added to `tokens.css` covering
1065
+ easings.net (`--ease-in-sine` through `--ease-in-out-back`, plus
1066
+ `linear()`-based `--ease-{in,out,in-out}-{elastic,bounce}` and
1067
+ `--ease-linear`).
1068
+ - **`UIEasingSelector`** editor control for picking from the named easing
1069
+ tokens.
1070
+
1071
+ ### Changed (breaking for consumers passing no data-folder options)
1072
+
1073
+ - **`themesDir` is no longer required.** It joins `componentConfigsDir` and
1074
+ `manifestsDir` as optional. Zero-config consumers now get
1075
+ `src/live-tokens/data/{themes,manifests,component-configs}` instead of the
1076
+ previous root-level defaults.
1077
+ - **New `dataDir` option** on `themeFileApi(opts)`. Sets the parent directory
1078
+ for all three subfolders. Default: `src/live-tokens/data`.
1079
+ - **New `live-tokens.config.json`** (optional, at project root). Accepts the
1080
+ same four data-folder keys. Resolution order per folder: explicit
1081
+ `themeFileApi(opts)` argument > matching key in `live-tokens.config.json` >
1082
+ `<dataDir>/<sub>` where dataDir comes from opts > config file > package
1083
+ default. Read once at plugin construction; restart vite to pick up changes.
1084
+ - **Build-time pruning shares the same resolution.** `loadProductionConfig`
1085
+ (used by `buildPruneReplace`) reads through the shared resolver, so
1086
+ `componentConfigsDir` stays consistent across the dev plugin and the
1087
+ preprocessor.
1088
+ - **API routes namespaced.** The default `apiBase` moved from `/api` to
1089
+ `/api/live-tokens`, so the plugin's routes can't collide with the consumer's
1090
+ own `/api/themes` / `/api/manifests`. The client side picks up the
1091
+ resolved base via a `__LIVE_TOKENS_API_BASE__` Vite define so client and
1092
+ server can't drift. Consumers who explicitly passed `apiBase: '/api'` are
1093
+ unaffected.
1094
+ - **Unknown-key warning** on `live-tokens.config.json`. The reader now logs
1095
+ one warning per unrecognised key so `themesDr` doesn't silently degrade to
1096
+ defaults. `$schema` is ignored.
1097
+
1098
+ ### Changed (breaking for saved component configs; auto-migrated on load)
1099
+
1100
+ Five component schemas were tightened. Migrations ship in the same release
1101
+ and run automatically when a stored config is first read, so consumers don't
1102
+ need to edit JSON by hand. Any per-state customisations on the dropped axes
1103
+ are discarded; the default-state value remains authoritative.
1104
+
1105
+ - **Button.** `StandardButtonsEditor` renamed to `ButtonEditor`. Per-state
1106
+ shape tokens (`padding`, `radius`, `border-width`) dropped for `hover` and
1107
+ `disabled` across all variants. They were always linked to the default
1108
+ state at runtime, so the per-state rows in the editor were dead UI.
1109
+ Migration: `2026-05-24-promote-state-shared-tokens`.
1110
+ - **ProgressBar.** Collapsed from a per-variant token namespace
1111
+ (`primary` / `success` / `warning` / `danger` / `info`) to a single flat
1112
+ token set. Fill color is now a runtime `fill` prop on the consumer side,
1113
+ not a variant axis. The `primary` namespace's values become the canonical
1114
+ defaults; non-primary customisations are dropped.
1115
+ Migration: `2026-05-24-progressbar-collapse-variants`.
1116
+ - **SegmentedControl.** `--segmentedcontrol-divider-height` retired in
1117
+ favour of `--segmentedcontrol-divider-inset` (margin-block on a stretched
1118
+ divider, so `Full` = 0 inset = bar-height). Value semantic flipped, so
1119
+ saved customisations are dropped rather than copied. Per-state icon-size
1120
+ tokens for `selected` / `option-hover` / `disabled` also dropped (always
1121
+ linked at runtime).
1122
+ Migrations: `2026-05-24-segmentedcontrol-divider-inset`,
1123
+ `2026-05-24-promote-state-shared-tokens`.
1124
+ - **CollapsibleSection.** Dropped the `active` header state and the matching
1125
+ `&.active` CSS branch. No consumer was using it.
1126
+ Migration: `2026-05-24-collapsiblesection-drop-active-state`.
1127
+ - **CornerBadge.** Per-variant token axis collapsed to a single flat set.
1128
+ Variants only ever carried shape/spacing/type aliases (never colours),
1129
+ and every variant's defaults were identical, so the strip was 10×
1130
+ duplication with no semantic gain.
1131
+ Migration: `2026-05-25-cornerbadge-flatten-variants`.
1132
+
1133
+ ### Migration for existing consumers
1134
+
1135
+ Either keep your current root-level layout by passing explicit options, or
1136
+ relocate your data folders and let defaults take over.
1137
+
1138
+ Keep root layout (one-line config file or explicit option):
1139
+
1140
+ ```json
1141
+ // live-tokens.config.json
1142
+ { "dataDir": "." }
1143
+ ```
1144
+
1145
+ Or move to the new default and drop any data-folder options from
1146
+ `themeFileApi(opts)`:
1147
+
1148
+ ```bash
1149
+ mkdir -p src/live-tokens/data
1150
+ git mv themes src/live-tokens/data/themes
1151
+ git mv manifests src/live-tokens/data/manifests
1152
+ git mv component-configs src/live-tokens/data/component-configs
1153
+ ```
1154
+
1155
+ Stop the vite dev server first — its HMR will pre-create the destination
1156
+ dirs if it picks up the plugin reload mid-move. The source repo itself ships
1157
+ with data at the new default location.
1158
+
1159
+ ## 0.6.0 — Editor CSS isolation
1160
+
1161
+ The editor now self-contains its chrome. A second consumer can `npm install
1162
+ @motion-proto/live-tokens`, import only their own `tokens.css`, mount
1163
+ `<Editor />` or `<ComponentEditorPage />`, and have everything render — no
1164
+ remembered side-imports, no theme-token bleed into editor controls.
1165
+
1166
+ ### Changed (breaking)
1167
+
1168
+ - **`form-controls.css` → `ui-form-controls.css`** with classes renamed
1169
+ `.form-*` → `.ui-form-*` and every theme token re-tokened to the `--ui-*`
1170
+ namespace. Consumers using `.form-input` / `.form-select` directly need to
1171
+ rename. (The only known consumer is `runegoblin-site`, which uses these
1172
+ only via `live-tokens`' own editor components, so no migration needed
1173
+ there.)
1174
+ - **Editor pages auto-load their own CSS.** `Editor.svelte` and
1175
+ `ComponentEditorPage.svelte` now script-import `ui-editor.css`,
1176
+ `ui-form-controls.css`, and `@fortawesome/fontawesome-free/css/all.min.css`.
1177
+ Consumers no longer need to import these in `main.ts`.
1178
+ - **Editor font invariant.** Editor chrome resolves only `--ui-font-*`
1179
+ tokens (a pure system stack defined in `ui-editor.css`). Theme fonts
1180
+ (`--font-sans`, `--font-serif`, `--font-display`, `--font-mono`) can no
1181
+ longer leak into editor controls — `ui-form-controls.css` was the last
1182
+ surface that referenced them.
1183
+
1184
+ ### Removed exports
1185
+
1186
+ | Removed | Replacement |
1187
+ |---|---|
1188
+ | `./styles/form-controls.css` | Auto-loaded; not exported |
1189
+ | `./styles/fonts.css` | `./starter/fonts.css` |
1190
+ | *(implicit)* | `./starter/tokens.css`, `./starter/site.css` |
1191
+
1192
+ `./styles/ui-editor.css` is kept as a read-only window onto the editor token
1193
+ contract; it's no longer a required consumer import.
1194
+
1195
+ ### Added
1196
+
1197
+ - `scripts/check-no-style-imports.mjs` — fails the build if any published
1198
+ `.svelte` `<style>` block contains an `@import`. (This regression killed
1199
+ v0.5.0 under the consumer's `css: 'injected'` workaround.)
1200
+ - `scripts/check-editor-font-isolation.mjs` — fails the build if editor
1201
+ chrome references theme-side font tokens.
1202
+ - `scripts/smoke-install.sh` — packs the library, installs into a temp
1203
+ consumer, and runs `vite build` with no special config. Required to pass
1204
+ in `prepublishOnly`.
1205
+
1206
+ ## 0.5.0 — Svelte 5 migration
1207
+
1208
+ ### Changed (breaking, but with deprecation bridges)
1209
+
1210
+ - Components are now authored in Svelte 5 runes (`$props`, `$state`, `$derived`,
1211
+ `$effect`, snippets). Existing consumer code on Svelte 4 idioms continues to
1212
+ work for one release thanks to the bridges below; both forms are valid in
1213
+ 0.5.0, the legacy form is removed in 0.6.0.
1214
+
1215
+ - **Event dispatch → callback props.** Each public component grew an
1216
+ `oncamelcase` callback prop alongside its existing `createEventDispatcher`
1217
+ event:
1218
+
1219
+ | Component | Legacy `<Comp on:event={fn}>` | Preferred `<Comp onevent={fn}>` |
1220
+ | -------------------- | ----------------------------- | -------------------------------- |
1221
+ | `Button` | `on:click` | `onclick(event: MouseEvent)` |
1222
+ | `SegmentedControl` | `on:change` | `onchange(value: string)` |
1223
+ | `CollapsibleSection` | `on:toggle` | `ontoggle()` |
1224
+ | `TabBar` | `on:tabChange` | `ontabChange(id: string)` |
1225
+ | `RadioButton` | `on:click` | `onclick()` |
1226
+ | `Notification` | `on:dismiss` | `ondismiss()` |
1227
+ | `Dialog` | `on:close` | `onclose()` |
1228
+
1229
+ Both are fired in 0.5.0 (dual-fire). The `createEventDispatcher` calls and
1230
+ the `on:event` legacy bridge are removed in 0.6.0.
1231
+
1232
+ - **Slots → snippets.** Most slots translate one-to-one (default slot →
1233
+ `children` snippet). The hyphenated slots that the `sv migrate` codemod
1234
+ refused to rename automatically were hand-renamed to camelCase identifiers
1235
+ (consumers must rename their `<svelte:fragment slot="x">` to
1236
+ `{#snippet x()}` and update the slot name):
1237
+
1238
+ - `Badge` / `CornerBadge`: `slot="icon"` → `iconSlot` (the `icon` prop's
1239
+ name was kept; the slot was renamed to resolve the collision)
1240
+ - `Dialog`: `slot="footer-left"` → `footerLeft`
1241
+ - `UITokenSelector`: `trigger-preview` → `triggerPreview`,
1242
+ `trigger-text` → `triggerText`, `trigger-title` → `triggerTitle`,
1243
+ `trigger-meta` → `triggerMeta`
1244
+ - `VariantGroup` (component-editor): `state-actions` → `stateActions`,
1245
+ `composite-controls` → `compositeControls`
1246
+
1247
+ Unlike the event bridge, the legacy `<slot>` form cannot coexist with
1248
+ snippets in a runes-mode component, so this part is a hard rename in
1249
+ 0.5.0 — there's no compat window.
1250
+
1251
+ ### Peer ranges
1252
+
1253
+ - `svelte`: `^4.2 || ^5` → `^5` (drops Svelte 4 entirely)
1254
+ - `vite`: `^5 || ^6 || ^7` → `^6 || ^7` (the chosen `@sveltejs/vite-plugin-svelte@^6` peers Vite 6.3+)
1255
+
1256
+ ### Internal
1257
+
1258
+ - Toolchain bumped to `svelte@5.55+`, `vite@7`, `@sveltejs/vite-plugin-svelte@6`,
1259
+ `svelte-check@4`. `compatibility.componentApi: 4` is enabled in
1260
+ `svelte.config.js` so `new Component({ target, props })` (used by tests and
1261
+ by consumers using the Svelte-4 imperative API) keeps working until 0.6.0.
1262
+ - `publicSurface.test.ts` (the green bar from 0.4.0) is still 27/27.
1263
+
1264
+ ## 0.4.0
1265
+
1266
+ ### Changed
1267
+
1268
+ - **Peer ranges widened** so consumers can install on modern toolchains without `--legacy-peer-deps`:
1269
+ - `svelte`: `^4.2` → `^4.2 || ^5`
1270
+ - `vite`: `^5.0` → `^5 || ^6 || ^7`
1271
+ - Components remain authored in Svelte 4 idioms (`export let`, `createEventDispatcher`, `<slot>`). On Svelte 5 they compile in **legacy mode** — the consumer-facing API (`on:event`, named slots, `bind:value`) is preserved. A full migration to runes is planned for a future major.
1272
+
1273
+ ### Internal
1274
+
1275
+ - Added a public-surface test (`src/components/__tests__/publicSurface.test.ts`) that pins the event-dispatch, slot, bind, and mount contracts for every shipped component. This is the green bar the upcoming Svelte 5 rune migration must keep passing.
1276
+
1277
+ ## 0.3.7
1278
+
1279
+ ### Internal
1280
+
1281
+ - Stop shipping colocated `*.test.ts` / `*.spec.ts` files in the npm tarball (negation patterns in `package.json#files`). Drops 8 files / ~57 KB; consumers see no change.
1282
+ - Added `.github/workflows/verify.yml` (lockfile drift, type-check, tests, plugin build, packaging dry-run) — runs on every push to main and on PRs, so release failures surface before tagging.
1283
+ - `publish.yml` now refuses to republish an existing version, runs `npm pack --dry-run` before the irreversible publish, and uses the npm cache.
1284
+
1285
+ ## 0.3.6
1286
+
1287
+ First release published via the GitHub Actions OIDC trusted publisher workflow. `0.3.3`–`0.3.5` were tagged but never reached npm — the lockfile carried stale resolutions from a non-clean local `npm install` and failed `npm ci` in CI. `0.3.6` regenerates the lockfile from a clean state and pins CI to Node 24.
1288
+
1289
+ ### Fixed
1290
+
1291
+ - `GradientCard` (Section Divider gradient editor) now renders the ribbon and stop handles correctly when a stop's color is still at the component's CSS default. Previously the ribbon and unselected diamond handles fell back to gray (`#888`) because the card read `aliases[…]` directly, which only contains user overrides. Stop colors now reference the CSS var so the cascade fills in component defaults (and live edits) the same way `UIPaletteSelector`'s swatch already did.
1292
+
1293
+ ### Internal
1294
+
1295
+ - Added `.github/workflows/publish.yml`: tag push (`v*`) triggers an OIDC-authenticated `npm publish --provenance --access public`. No `NPM_TOKEN` secret; npm trusts this workflow via Trusted Publisher.
1296
+
1297
+ ## 0.3.2
1298
+
1299
+ ### Docs
1300
+
1301
+ - Reframed README around the package as a library-first foundational design system for microsites. Real-time editing of tokens and components is now the headline; the `npx degit` starter is presented as a greenfield convenience rather than the primary consumption path. Added a "File ownership" section documenting which files the vite plugin writes (and when).
1302
+
1303
+ ### Internal
1304
+
1305
+ - Flattened lingering multi-config state in `component-configs/`: removed the unused `callout/default_01.json`, `cornerbadge/default_01.json`, and `segmentedcontrol/green-segment-control.json` and repointed all `_active`/`_production` pointers to `default`. Every shipped component now has a single canonical config.
1306
+
1307
+ ## 0.3.1
1308
+
1309
+ First published release in the 0.3.x line — 0.3.0 was bumped locally but never pushed to npm. No code changes from 0.3.0.
1310
+
1311
+ ## 0.3.0
1312
+
1313
+ ### Breaking
1314
+
1315
+ - Rename "token file" → "theme" throughout, since the saved JSON files are themes (groupings of tokens, fonts, palettes), not individual tokens.
1316
+ - Vite plugin: `tokenFileApi` → `themeFileApi`, options `tokensDir` → `themesDir`, `variablesCssPath` → `tokensCssPath`. Type `TokenFileApiOptions` → `ThemeFileApiOptions`.
1317
+ - Default directory: `tokens/` → `themes/`. Stylesheet: `src/styles/variables.css` → `src/styles/tokens.css`.
1318
+ - API routes: `/api/tokens/*` → `/api/themes/*`. Backup type discriminator `'tokens'` → `'themes'`.
1319
+ - Library exports: `TokenFile` → `Theme`, `TokenFileMeta` → `ThemeMeta`. Service functions renamed (`listTokenFiles` → `listThemes`, `loadTokenFile` → `loadTheme`, `saveTokenFile` → `saveTheme`, `deleteTokenFile` → `deleteTheme`, `getActiveTokens` → `getActiveTheme`, `migrateTokenFileFonts` → `migrateThemeFonts`, `initializeTokens` → `initializeTheme`).
1320
+ - Showcase: `TokenFileManager` component → `ThemeFileManager`.
1321
+ - "design token" terminology preserved for individual CSS variables (`tokenRegistry`, package name, `design-tokens` keyword).
1322
+
1323
+ ## 0.2.0
1324
+
1325
+ Repositioning release: the repo is now officially both a starter template (via `degit`) and a library (via `npm install`). The starter's home route is now an empty stub authors replace, and the old `Landing.svelte` demo content moves to `/kit`.
1326
+
1327
+ ### Breaking
1328
+
1329
+ - `src/pages/Landing.svelte` → renamed to `src/pages/KitDemo.svelte`. The `/` route is now `Home.svelte` (starter stub); the kit demo lives at `/kit`. Starter consumers upgrading a clone should rename their own landing file or rebase onto the new layout.
1330
+ - `src/showcase/index.ts` — `defaultSections` is now a runtime export (re-added after an accidental removal in the 0.1.x line). It also moved out of `ComponentsTab.svelte` into a standalone `src/showcase/defaultSections.ts` so it can be imported without loading all demo components.
1331
+ - `package.json` exports — dropped the unused `./showcase-page`, `./overlay`, and `./columns-overlay` subpaths. `LiveEditorOverlay` and `ColumnsOverlay` are still available from the root import. Consumers who hand-declared ambient `declare module` entries for these in their own `vite-env.d.ts` can delete them.
1332
+ - `LiveEditorOverlay` — the `open` prop is now optional. When unbound, the component self-persists the open/closed state in localStorage. Consumers binding `open` get the same behavior as before.
1333
+
1334
+ ### Added
1335
+
1336
+ - `./admin` export now ships with a `types` branch (`Admin.svelte.d.ts`). Consumers can delete their hand-written `declare module '@motion-proto/live-tokens/admin'` shims.
1337
+ - `tokenFileApi` Vite plugin now auto-injects `__PROJECT_ROOT__` as a `define`. Consumers no longer need to add it to their own `vite.config.ts`.
1338
+ - `LiveEditorOverlay` self-gates dev/iframe/editor-route visibility. Consumers can drop `<LiveEditorOverlay />` without wrapping it in `{#if import.meta.env.DEV && !isInIframe}` boilerplate.
1339
+ - `ColumnsOverlay` self-gates on dev + iframe for the same reason.
1340
+ - Admin "Back to site" button now navigates to the last non-admin route (via `sessionStorage`), falling back to `/kit`.
1341
+ - New `src/pages/Home.svelte` starter stub and `src/pages/KitDemo.svelte` marketing/demo page.
1342
+
1343
+ ### Internal
1344
+
1345
+ - Reworked README with separate "Use as a starter" and "Use as a library" sections.
1346
+ - `src/styles/fonts/` font system, `fontLoader`, `fontMigration`, `fontParse`, `FontStackEditor`, `ProjectFontsSection` added in the 0.1.x line are now documented.
1347
+
1348
+ ## 0.1.1
1349
+
1350
+ Initial scoped-package release extracted from RuneGoblin.