@takazudo/zdtp 0.4.12 → 0.4.13

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 CHANGED
@@ -1,6 +1,54 @@
1
1
  # Changelog
2
2
 
3
- ## 0.4.12
3
+ All notable changes to `@takazudo/zdtp` are documented in this file.
4
+
5
+ The format is based on Keep a Changelog, and release notes are generated from the changelog MDX pages.
6
+
7
+ ## [0.4.13] - 2026-08-29
8
+
9
+ ### Features
10
+
11
+ - feat(zdtp): normalize static CSS colors (20567e7)
12
+
13
+ ### Fixed
14
+
15
+ - fix(zdtp): expose readonly swatches as selectable (c3c8c28)
16
+ - fix(zdtp): restrict referencesRamps to Color tabs (8894399)
17
+ - fix(zdtp): enforce readonly Palette editing (5c2445c)
18
+ - fix(zdtp): guard palette validity transitions (73a59fb)
19
+ - fix(zdtp): preserve invalid palette slots as n-a (0e456e5)
20
+ - fix(doc): align preview with latest zfb (9cd81bb)
21
+
22
+ ### Other Changes
23
+
24
+ - Merge pull request [#636](https://github.com/Takazudo/zudo-design-token-panel/pull/636) from Takazudo/base/sweep-260829: fix(zdtp): correct Palette behavior and public contracts (db3ee47)
25
+ - docs(zdtp): document referencesRamps tab restriction (555b562)
26
+ - Merge pull request [#645](https://github.com/Takazudo/zudo-design-token-panel/pull/645) from Takazudo/base/sweep-260829-portable-contract-docs: fix(zdtp): align portable contracts and ramp validation (452fc32)
27
+ - Merge topic/630-reference-color-mode-docs (7abfa37)
28
+ - docs: clarify reference emission and color modes (f447a99)
29
+ - Merge topic/632-references-ramps-color-tabs (7df5b55)
30
+ - Merge topic/631-required-write-root-docs (ae76e2b)
31
+ - Merge topic/629-shipped-semantic-contract (0ba0294)
32
+ - docs(zdtp): sync shipped semantic tier contract (4bbc5d5)
33
+ - docs: require write-root in apply guidance (10c76b1)
34
+ - Merge pull request [#640](https://github.com/Takazudo/zudo-design-token-panel/pull/640) from Takazudo/base/sweep-260829-palette-correctness: fix(zdtp): correct Palette color and readonly behavior (36c0972)
35
+ - Merge branch 'topic/626-palette-readonly' into base/sweep-260829-palette-correctness (53575d9)
36
+ - Merge branch 'topic/625-palette-invalid-na' into base/sweep-260829-palette-correctness (73c2c6c)
37
+ - Merge branch 'topic/624-static-css-color-normalization' into base/sweep-260829-palette-correctness (858c131)
38
+ - Merge pull request [#635](https://github.com/Takazudo/zudo-design-token-panel/pull/635) from Takazudo/base/sweep-260829-zudo-dependency-refresh: chore(doc): refresh stable zudo dependencies (db555eb)
39
+ - Merge branch 'topic/621-zudo-dependency-family' into base/sweep-260829-zudo-dependency-refresh (16ed6cd)
40
+ - chore(doc): bump stable zudo dependency family (579671a)
41
+ - Merge pull request [#615](https://github.com/Takazudo/zudo-design-token-panel/pull/615) from Takazudo/fix/populate-doc-changelog-20260823: docs: populate changelog release history (9ce99a1)
42
+ - docs: clarify changelog source and locale history (7a0c194)
43
+ - docs: populate changelog release history (559a9c5)
44
+ - Merge pull request [#614](https://github.com/Takazudo/zudo-design-token-panel/pull/614) from Takazudo/agent-fix/zdtp-lint-warnings-20260823: chore: resolve zdtp lint warnings (9f16688)
45
+ - chore: resolve zdtp lint warnings (ed175ca)
46
+ - Merge pull request [#612](https://github.com/Takazudo/zudo-design-token-panel/pull/612) from Takazudo/agent-fix/actions-cache-node24-20260823: ci: update actions/cache to Node 24 (ab0ad0d)
47
+ - ci: update actions/cache to Node 24 (234459b)
48
+ - Merge pull request [#610](https://github.com/Takazudo/zudo-design-token-panel/pull/610) from Takazudo/chore/bump-zudo-deps-20260823: chore(doc): update zudo stack and preview wiring (d6d0d54)
49
+ - chore(doc): bump zudo dependencies (6d50555)
50
+
51
+ ## [0.4.12] - 2026-08-20
4
52
 
5
53
  ### Fixed
6
54
 
@@ -29,7 +77,7 @@
29
77
  - = start portable storage contract epic = [skip ci] (1605c3e)
30
78
  - = start sweep-260820 super-epic = [skip ci] (c29cc50)
31
79
 
32
- ## 0.4.11
80
+ ## [0.4.11] - 2026-08-19
33
81
 
34
82
  ### Features
35
83
 
@@ -56,7 +104,7 @@
56
104
  - test: complete the lazy-load gate decision-matrix coverage ([#591](https://github.com/Takazudo/zudo-design-token-panel/pull/591)) (76cb4a3)
57
105
  - test: confirm multi-instance spawn geometry in a real browser ([#595](https://github.com/Takazudo/zudo-design-token-panel/pull/595)) (11988d6)
58
106
 
59
- ## 0.4.10
107
+ ## [0.4.10] - 2026-08-10
60
108
 
61
109
  ### Fixed
62
110
 
@@ -69,7 +117,7 @@
69
117
  - docs: migrate the doc site to zudo-doc 4.x — S1–S6 series ([#556](https://github.com/Takazudo/zudo-design-token-panel/pull/556)–[#562](https://github.com/Takazudo/zudo-design-token-panel/pull/562)) (e2f36b5, 51c674c, ff38109, e36e718, e7838fb, c20cc83, f89a6bf)
70
118
  - docs(l-make-release): auto-proceed Step 3 gate for routine bumps (45a5aca)
71
119
 
72
- ## 0.4.9
120
+ ## [0.4.9] - 2026-07-13
73
121
 
74
122
  ### Features
75
123
 
@@ -88,7 +136,7 @@
88
136
  - test: record color picker close control VRT (aa66eba)
89
137
  - chore: start panel UI tweaks 540 (57fb4c7)
90
138
 
91
- ## 0.4.8
139
+ ## [0.4.8] - 2026-07-13
92
140
 
93
141
  ### Features
94
142
 
@@ -100,7 +148,7 @@
100
148
  - chore(dom-tweaker): remove consumed prototype resource ([#539](https://github.com/Takazudo/zudo-design-token-panel/pull/539)) (9a0ac51)
101
149
  - docs(l-make-release): add autonomy-after-the-gate principle (7f64206)
102
150
 
103
- ## 0.4.7
151
+ ## [0.4.7] - 2026-07-12
104
152
 
105
153
  ### Fixed
106
154
 
@@ -110,7 +158,7 @@
110
158
 
111
159
  - chore(deps): resolve 19 pnpm audit security advisories ([#525](https://github.com/Takazudo/zudo-design-token-panel/pull/525)) (80c9a0e)
112
160
 
113
- ## 0.4.6
161
+ ## [0.4.6] - 2026-07-12
114
162
 
115
163
  ### Features
116
164
 
@@ -134,7 +182,7 @@
134
182
  - test: VRT baselines re-recorded for zdtp title + square corners; broad coverage added for notes tab, help icons, unit cycling
135
183
  - chore: removed consumed `_temp-resource/` prototype scaffold (ccbd18a)
136
184
 
137
- ## 0.4.5
185
+ ## [0.4.5] - 2026-07-07
138
186
 
139
187
  ### Features
140
188
 
@@ -156,7 +204,7 @@
156
204
  - docs: truth-up schemaId docs, tighten Import modal copy, export `SCHEMA_V1`/`SCHEMA_V2`/`SCHEMA_V3` ([#505](https://github.com/Takazudo/zudo-design-token-panel/issues/505)) (8088281)
157
205
  - docs: replace zmodular references with Takazudo Modular markdown links (afcfea2)
158
206
 
159
- ## 0.4.4
207
+ ## [0.4.4] - 2026-07-06
160
208
 
161
209
  ### Features
162
210
 
@@ -202,7 +250,7 @@
202
250
  - chore(deps): bump `@takazudo/zudo-doc` and `zudo-doc-history-server` to `^2.5.1` (d6c05dd)
203
251
  - chore(doc): sync generated `claude/index.mdx` with build output (d763238)
204
252
 
205
- ## 0.4.3
253
+ ## [0.4.3] - 2026-07-04
206
254
 
207
255
  ### Features
208
256
 
@@ -234,7 +282,7 @@
234
282
  - Browser test files now run serially — parallel files share one origin and raced each other's localStorage (fd37774)
235
283
  - Deps: bump @takazudo/* toolchain (zfb next.76, zudo-doc 2.5.0) (62b62f6)
236
284
 
237
- ## 0.4.2
285
+ ## [0.4.2] - 2026-06-30
238
286
 
239
287
  ### Features
240
288
 
@@ -265,13 +313,13 @@
265
313
  - Bump the `@takazudo/*` toolchain (zfb next.72, zudo-doc 2.1.2). (d711839)
266
314
  - Doc-site migration to zudo-doc v2 — doc-site only, no package impact. ([#432](https://github.com/Takazudo/zudo-design-token-panel/pull/432))
267
315
 
268
- ## 0.4.1
316
+ ## [0.4.1] - 2026-06-30
269
317
 
270
318
  ### Fixed
271
319
 
272
320
  - **Palette tab no longer renders unstyled for self-injection consumers.** The 0.4.0 palette-tab CSS (`palette-chart` / `palette-edit` / `palette-readout`) reached `dist/zdtp.css` but was missing from the stylesheet the panel self-injects at runtime, so consumers using `import('@takazudo/zdtp')` + `configurePanel(...)` without importing `@takazudo/zdtp/styles` saw collapsed swatch bars and a missing curve-editor canvas. The two palette stylesheets are now `@import`ed into the single `panel.css` aggregate (matching `color-picker.css`) so both CSS delivery paths stay in sync, guarded by a new static `Invariant G` test. ([#413](https://github.com/Takazudo/zudo-design-token-panel/issues/413))
273
321
 
274
- ## 0.4.0
322
+ ## [0.4.0] - 2026-06-29
275
323
 
276
324
  ### Features
277
325
 
@@ -289,7 +337,7 @@
289
337
  - Integration + serde + browser-confirm test coverage for the palette tab. ([#396](https://github.com/Takazudo/zudo-design-token-panel/issues/396))
290
338
  - Add a grouped palette tab recipe + reference docs (EN + JA). ([#397](https://github.com/Takazudo/zudo-design-token-panel/issues/397))
291
339
 
292
- ## 0.3.3
340
+ ## [0.3.3] - 2026-06-23
293
341
 
294
342
  ### Features
295
343
 
@@ -308,7 +356,7 @@
308
356
 
309
357
  - Add an end-to-end test asserting the oklch round-trip (panel `onChange` + apply path both emit `oklch(...)`) and wide-gamut P3 preservation. ([#379](https://github.com/Takazudo/zudo-design-token-panel/issues/379)) (0595f28)
310
358
 
311
- ## 0.3.2
359
+ ## [0.3.2] - 2026-06-23
312
360
 
313
361
  ### Fixed
314
362
 
@@ -316,7 +364,7 @@
316
364
 
317
365
  - **Dedupe the reserved toggle event across listeners.** When a custom-prefix host opts into the reserved `toggle-design-token-panel` name via `config.toggleEvent`, both the eager default listener and the instance's own listener fired on one dispatch and resolved to the same instance — toggling it twice (open, then immediately close). The handler now dedupes per dispatch by resolved instance id carried on the shared Event object, so the panel opens exactly once. ([#371](https://github.com/Takazudo/zudo-design-token-panel/pull/371))
318
366
 
319
- ## 0.3.1
367
+ ## [0.3.1] - 2026-06-23
320
368
 
321
369
  ### Fixed
322
370
 
@@ -324,7 +372,7 @@
324
372
 
325
373
  - **Skip the bin integration test suite when `dist/bin/server.js` is absent.** `server.integration.test.ts` spawns the built bin and previously threw in `beforeAll` when it was missing, failing the `node` vitest project on a fresh checkout (before a build). It now gates the suite with `describe.skipIf` on build presence (with a console warning) instead of hard-failing; CI builds before testing, so the suite still runs there. ([#360](https://github.com/Takazudo/zudo-design-token-panel/issues/360))
326
374
 
327
- ## 0.3.0
375
+ ## [0.3.0] - 2026-06-22
328
376
 
329
377
  ### Features
330
378
 
@@ -336,7 +384,7 @@
336
384
 
337
385
  - **`PanelConfig.applySink`.** An optional `{ apply(pairs), clear(names) }` sink routes this instance's CSS-var writes and clears through a caller-supplied object instead of `document.documentElement`. Useful for shadow DOM, iframe, or test-spy contexts. `apply` = upsert; `clear` = remove. Reset sends the full token-name set for the instance to `sink.clear` so the sink target is completely cleaned. Sink errors are non-fatal (`console.warn`). The host owns the sink target's lifecycle. `applySink` carries function references and must not be passed through the Astro inline JSON config. ([#355](https://github.com/Takazudo/zudo-design-token-panel/issues/355))
338
386
 
339
- ## 0.2.3
387
+ ## [0.2.3] - 2026-06-15
340
388
 
341
389
  ### Bug Fixes
342
390
 
@@ -351,13 +399,13 @@
351
399
  - docs: document the global (not scheme-scoped) tweak model in README §9 — on a host `color-scheme-changed` event the panel drops its inline overrides and re-seeds the live state from the new scheme, leaving `localStorage` untouched until the next edit. (238b4db, [#343](https://github.com/Takazudo/zudo-design-token-panel/issues/343))
352
400
  - ci: drop the stale npm `next` dist-tag on stable releases when it lags `latest`, so `@takazudo/zdtp@next` can no longer silently resolve to an older prerelease. (215ec59, [#345](https://github.com/Takazudo/zudo-design-token-panel/issues/345))
353
401
 
354
- ## 0.2.2
402
+ ## [0.2.2] - 2026-06-15
355
403
 
356
404
  ### Other Changes
357
405
 
358
406
  - Post-review internal cleanups for the Element Path Copy feature (no behavior change): single source of truth for the highlight / element-path portal-mount ids (`HIGHLIGHT_PORTAL_MOUNT_ID` / `ELPATH_PORTAL_MOUNT_ID`, folded into `PANEL_EXCLUSION_SELECTOR`); `ElementPathToast` now owns its own fixed top-center positioning and z-index; `buildSummary` escapes the id consistently with the selector line; the always-on `mousemove` listener is passive + non-capture; and the hover-label summary is memoized. (0fdcbd6)
359
407
 
360
- ## 0.2.1
408
+ ## [0.2.1] - 2026-06-14
361
409
 
362
410
  ### Features
363
411
 
@@ -369,7 +417,7 @@
369
417
  - Bump GitHub Actions off the deprecated Node 20 runtime: `checkout` / `setup-node` / pnpm-setup and the artifact actions to their Node-24-matched versions. (08d5b48, b46fd66, [#339](https://github.com/Takazudo/zudo-design-token-panel/pull/339), [#341](https://github.com/Takazudo/zudo-design-token-panel/pull/341))
370
418
  - Add a web-env bootstrap for Claude Code on the web. (23f00c3)
371
419
 
372
- ## 0.2.0
420
+ ## [0.2.0] - 2026-06-09
373
421
 
374
422
  First clean stable release on the `latest` dist-tag, promoting the
375
423
  `0.2.0-next.1` / `0.2.0-next.2` prerelease line. A tagless
@@ -389,13 +437,13 @@ First clean stable release on the `latest` dist-tag, promoting the
389
437
  - Drop slider-describing prose and min/max examples from `README.md`, `PORTABLE-CONTRACT.md`, and the doc-site reference pages (`token-manifest.mdx`, `architecture.mdx`, `configure-panel.mdx`). (e210a2d, 9262585)
390
438
  - Resolve all `pnpm audit` advisories (1 critical, 3 high, 7 moderate, 1 low) in dev/doc-only tooling — none ship in the published package. (f3574e0)
391
439
 
392
- ## 0.2.0-next.2
440
+ ## [0.2.0-next.2] - 2026-05-27
393
441
 
394
442
  ### Features
395
443
 
396
444
  - **Token-name tooltip parity across all tabs (Size / Font / Spacing / Easing / GenericTab).** The Color tab already showed a rich custom tooltip with the full token name on hover; every other tab fell back to the native HTML `title` attribute. A new shared `TokenLabel` component renders the same `.tokenpanel-tooltip` primitive at every token-name display site. `TooltipProvider` was lifted from `color-tab.tsx` to `panel.tsx` so all tabs share a single provider. (559c59f, 426e9c6, 84f5981, [#330](https://github.com/Takazudo/zudo-design-token-panel/issues/330), [#337](https://github.com/Takazudo/zudo-design-token-panel/pull/337))
397
445
 
398
- ## 0.2.0-next.1
446
+ ## [0.2.0-next.1] - 2026-05-27
399
447
 
400
448
  ### Breaking Changes
401
449
 
@@ -408,7 +456,7 @@ First clean stable release on the `latest` dist-tag, promoting the
408
456
  - Update `packages/zdtp/README.md` and `packages/zdtp/PORTABLE-CONTRACT.md` to drop slider-describing prose and the min/max examples. (e210a2d)
409
457
  - Update doc-site reference pages (`token-manifest.mdx`, `architecture.mdx`, `configure-panel.mdx`) to drop the min/max examples and slider-UI prose. (9262585)
410
458
 
411
- ## 0.1.0-next.3
459
+ ## [0.1.0-next.3] - 2026-05-27
412
460
 
413
461
  ### Features
414
462
 
@@ -418,7 +466,7 @@ First clean stable release on the `latest` dist-tag, promoting the
418
466
 
419
467
  - **Number inputs no longer overwrite the user's draft mid-keystroke.** `SliderRow` and the generic-tab item editor used to parse-and-clamp on every keystroke, immediately commit the clamped value, and round-trip it back into the input — so typing `2` then `2` (expecting `22`) snapped the input to `6` when the token's `max` was `6`. Out-of-range or empty drafts are now flagged with a `--invalid` red border and held without committing; on blur, an invalid draft reverts to the last known-good value. The slider thumb continues to scrub live. (21d3afa) ([#313](https://github.com/Takazudo/zudo-design-token-panel/issues/313))
420
468
 
421
- ## 0.1.0-next.2
469
+ ## [0.1.0-next.2] - 2026-05-25
422
470
 
423
471
  ### Fixed
424
472
 
@@ -439,7 +487,7 @@ First clean stable release on the `latest` dist-tag, promoting the
439
487
  base tokens get the same visibility toggle as palette and semantic tokens. The
440
488
  eye is omitted only when the cluster declares no `cssVar` for that role.
441
489
 
442
- ## 0.1.0-next.1
490
+ ## [0.1.0-next.1] - 2026-05-25
443
491
 
444
492
  ### Fixed — Astro consumers: `@takazudo/zdtp/astro` value import broke real npm installs ([#308](https://github.com/Takazudo/zudo-design-token-panel/issues/308))
445
493
 
@@ -465,7 +513,7 @@ First clean stable release on the `latest` dist-tag, promoting the
465
513
  side-effect import is unchanged. Docs (README, PORTABLE-CONTRACT, doc-site
466
514
  recipes) updated to the direct-subexport form.
467
515
 
468
- ## 0.1.0-next.0
516
+ ## [0.1.0-next.0] - 2026-05-24
469
517
 
470
518
  ### Renamed — npm package is now `@takazudo/zdtp`
471
519
 
@@ -401,6 +401,15 @@ export interface PillSpec {
401
401
  customDefault: string;
402
402
  }
403
403
 
404
+ /** Mapping value for a semantic color token (legacy and ramp-native forms). */
405
+ export type SemanticValue =
406
+ | number
407
+ | 'bg'
408
+ | 'fg'
409
+ | { literal: string }
410
+ | { literal: { light: string; dark: string } }
411
+ | { ref: { tab?: string; tier: string; item: string } };
412
+
404
413
  /** A single editable or reference token within a tier. */
405
414
  export interface TierItem {
406
415
  /** Stable id used as the key in persisted state (e.g. `hsp-2xs`). */
@@ -435,8 +444,26 @@ export interface TierConfig {
435
444
  * pipeline emits `var(--target-cssvar)` for ref-tier items at apply time.
436
445
  */
437
446
  referencesTier?: string;
447
+ /**
448
+ * Marks a Color-tab tier as semantic data whose items hold `SemanticValue`
449
+ * mappings rather than raw palette entries. It is never treated as the
450
+ * palette tier, so a Color tab may contain a lone semantic tier.
451
+ */
452
+ semantic?: true;
453
+ /**
454
+ * Valid only when this semantic tier belongs to a tab whose id is exactly
455
+ * `color` or `color-secondary`; other owning tab ids are rejected at
456
+ * configure time. Declares one or more permitted same- or cross-tab ramp
457
+ * sources for per-row semantic `{ ref }` mappings. Each entry names a tier
458
+ * and optional tab (`tab` omitted means this tab); unlike `referencesTier`,
459
+ * this is a multi-source allow-list for individual semantic mappings.
460
+ */
461
+ referencesRamps?: readonly { tab?: string; tier: string }[];
438
462
  }
439
463
 
464
+ For the full `SemanticValue` mapping and emission behavior, see the maintained
465
+ [Color-cluster reference](https://zudo-design-token-panel.takazudomodular.com/docs/reference/color-cluster/).
466
+
440
467
  /**
441
468
  * Color-cluster extras — the non-tier fields required for the color tab.
442
469
  * Palette and semantic data move into the tier model as TierItems; ColorClusterExtras
@@ -629,7 +656,9 @@ export interface ColorClusterExtras {
629
656
  /**
630
657
  * Optional light/dark pairing. When set to an object, the panel honours
631
658
  * `document.documentElement[data-theme]` and switches schemes accordingly
632
- * on init. Set to `false` to disable the light/dark UI.
659
+ * on init. Set to `false` to disable scheme-to-`data-theme` binding; this
660
+ * does not disable per-mode literal editing or emitted `light-dark(...)`
661
+ * values.
633
662
  */
634
663
  colorMode: false | { defaultMode: 'light' | 'dark'; lightScheme: string; darkScheme: string };
635
664
  };
package/README.md CHANGED
@@ -112,8 +112,8 @@ pnpm exec zdtp-server --help
112
112
  | Flag | Required | Purpose | Default |
113
113
  |---|---|---|---|
114
114
  | `--routing <path>` | yes | Path to the routing JSON file (cluster id → repo-relative CSS file path). Absolute, or relative to `--root`. See §3.2. | — |
115
- | `--write-root <dir>` | no | Sandbox directory: the bin refuses to write outside this tree. Absolute, or relative to `--root`. | `--root` |
116
- | `--root <dir>` | no | Repo-root reference used to resolve `--routing` and `--write-root`. | `process.cwd()` |
115
+ | `--write-root <dir>` | yes | Required write boundary: the only directory tree the bin is allowed to write into. Absolute, or relative to `--root`. | — |
116
+ | `--root <dir>` | no | CWD/resolution base used to resolve `--routing` and `--write-root`. | `process.cwd()` |
117
117
  | `--port <number>` | no | TCP port to bind. `0` asks the OS for an ephemeral port (the bin logs the assigned port on startup). | `24681` |
118
118
  | `--host <addr>` | no | Bind address. Use `0.0.0.0` to expose on the LAN (off by default). | `127.0.0.1` |
119
119
  | `--allow-origin <origin>` | repeatable | Origin allowed to POST to `/apply` (scheme + host + port, no trailing slash). At least one is required for any browser to apply. | none (all origins denied) |
@@ -170,7 +170,7 @@ For the full token-overrides payload schema and the `PanelConfig` shape, see §5
170
170
  The bin is **dev-only** and is built with three independent guards:
171
171
 
172
172
  - **Loopback default.** Binds to `127.0.0.1` so only requests from the same machine are accepted. Override with `--host` if you actually want LAN access.
173
- - **Write sandbox (`--write-root`).** Every routing entry is resolved against `--root` and verified to sit strictly inside `--write-root` before any file I/O happens. An entry whose resolved path escapes the sandbox — via `..` segments or an absolute path that points elsewhere — fails the apply with a 400 and a descriptive error message. `--write-root` defaults to `--root`, so routing entries are sandboxed to your repo root unless you narrow it further.
173
+ - **Write sandbox (`--write-root`).** `--write-root` is required and defines the narrow directory tree the bin is allowed to write into. Every routing entry is resolved against `--root` and verified to sit strictly inside `--write-root` before any file I/O happens. An entry whose resolved path escapes the sandbox — via `..` segments or an absolute path that points elsewhere — fails the apply with a 400 and a descriptive error message. `--root` is the CWD/resolution base for relative `--routing` and `--write-root` paths and defaults to `process.cwd()`.
174
174
  - **CORS allow-list.** By default, **all origins are denied**. To let a browser POST to `/apply` you must list its origin explicitly with `--allow-origin <url>` (repeatable). Without a matching `--allow-origin`, the OPTIONS preflight returns 403 and POST returns 403 — no `Access-Control-Allow-Origin` header is emitted. Origin matching is **verbatim** on the full scheme + host + port string: `http://localhost:5173` and `http://127.0.0.1:5173` are different origins.
175
175
 
176
176
  **Atomic writes.** The bin serialises per-file writes through a small mutex and uses a write-temp-file-then-rename strategy, so a failure mid-write never leaves a half-rewritten CSS file on disk. If any file in a multi-file apply fails to write, every file that was already persisted is restored from the in-memory snapshot taken before the apply started.
@@ -1,6 +1,6 @@
1
- import { c as y, g as m, a as w, b, i as P } from "../panel-config-7Xg59uKj.js";
2
- import { g, Z as k } from "../tweak-state-DRKV1uYj.js";
3
- import { s as A, l as D, a as E, i as c, r as f, c as _, b as I, d } from "../autoload-state-CTDDBxI8.js";
1
+ import { c as y, g as m, a as w, b, i as P } from "../panel-config-COHesW2B.js";
2
+ import { g, Z as k } from "../tweak-state-BKNxtHzb.js";
3
+ import { s as A, l as D, a as E, i as c, r as f, c as _, b as I, d } from "../autoload-state-CfL2VUe1.js";
4
4
  const u = "tokenpanel-config";
5
5
  function S() {
6
6
  if (typeof document > "u")
@@ -1,4 +1,4 @@
1
- import { s as t } from "../panel-config-7Xg59uKj.js";
1
+ import { s as t } from "../panel-config-COHesW2B.js";
2
2
  import { c as d } from "../color-schemes-CgzOBqGO.js";
3
3
  import { F as r, G as m, a as g, S as z } from "../manifest-DCReQE0k.js";
4
4
  const e = {
@@ -1,4 +1,4 @@
1
- import { g as n, j as o } from "./panel-config-7Xg59uKj.js";
1
+ import { g as n, j as o } from "./panel-config-COHesW2B.js";
2
2
  function c() {
3
3
  return typeof document < "u" && document !== null && typeof document.getElementById == "function";
4
4
  }
@@ -35,8 +35,19 @@ import { type Oklcha } from '../../utils/color-oklch';
35
35
  export type { Oklcha } from '../../utils/color-oklch';
36
36
  export type { Channel } from '../../utils/palette-curve';
37
37
  export interface PaletteChartProps {
38
- /** Palette colors in OKLCH space. Band `i` = oklchaToHex(colors[i]). */
39
- colors: Oklcha[];
38
+ /**
39
+ * Dense palette slots in OKLCH space. A null slot preserves its index/band,
40
+ * but has no numeric curve node and is not editable.
41
+ */
42
+ colors: Array<Oklcha | null>;
43
+ /**
44
+ * Dense per-index write permission, separate from color validity. A valid
45
+ * readonly color remains painted in the bands/curves, but receives no node
46
+ * hit target and is excluded from whole-curve editing.
47
+ */
48
+ editable: boolean[];
49
+ /** Dense stable item identities used to invalidate stale index-based gestures. */
50
+ identities: string[];
40
51
  /** Index of the currently selected color/step (highlighted band + node column). */
41
52
  selectedIndex: number;
42
53
  /** Which curves are drawn. Owned by the parent; chart only consumes. */
@@ -64,7 +75,7 @@ export interface PaletteChartProps {
64
75
  */
65
76
  onChangeEnd?: () => void;
66
77
  }
67
- declare function PaletteChartImpl({ colors, selectedIndex, visibleChannels, onChange, onSelectIndex, onChangeStart, onChangeEnd, }: PaletteChartProps): JSX.Element;
78
+ declare function PaletteChartImpl({ colors, editable, identities, selectedIndex, visibleChannels, onChange, onSelectIndex, onChangeStart, onChangeEnd, }: PaletteChartProps): JSX.Element;
68
79
  /**
69
80
  * Memoized so parent re-renders that don't change props don't re-walk every
70
81
  * band/curve/node. The drag state lives in refs, so a controlled-value update
@@ -1,7 +1,7 @@
1
1
  import { jsx as y, jsxs as K, Fragment as kt } from "preact/jsx-runtime";
2
2
  import { useEffect as P, useState as Y, useRef as O, useMemo as J, useCallback as X } from "preact/hooks";
3
- import { b as ft, p as wt, u as ht, a as Ne, A as bt, Z as gt } from "./index-BeYH-tJD.js";
4
- import { g as vt, m as j } from "./panel-config-7Xg59uKj.js";
3
+ import { b as ft, p as wt, u as ht, a as Ne, A as bt, Z as gt } from "./index-U7Ol7tgA.js";
4
+ import { g as vt, m as j } from "./panel-config-COHesW2B.js";
5
5
  const xt = (e, o) => {
6
6
  const t = new Array(e.length + o.length);
7
7
  for (let r = 0; r < e.length; r++)