@takazudo/zdtp 0.4.14 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/CHANGELOG.md +163 -0
  2. package/PORTABLE-CONTRACT.md +386 -91
  3. package/README.md +268 -95
  4. package/dist/apply/build-apply-overrides.d.ts +2 -2
  5. package/dist/apply/compute-hunks.d.ts +23 -0
  6. package/dist/apply/last-applied.d.ts +5 -0
  7. package/dist/apply/reconcile-applied.d.ts +19 -0
  8. package/dist/apply-modal.d.ts +2 -48
  9. package/dist/astro/host-adapter.js +3 -3
  10. package/dist/astro/index.js +2 -2
  11. package/dist/{autoload-state-IlkEci88.js → autoload-state-DmTY6tRy.js} +1 -1
  12. package/dist/bin/server.js +52 -50
  13. package/dist/bulk/bulk-actions.d.ts +45 -0
  14. package/dist/bulk/index.d.ts +2 -0
  15. package/dist/chain/index.d.ts +2 -0
  16. package/dist/chain/token-chain-context.d.ts +19 -0
  17. package/dist/chain/token-chain-popover.d.ts +22 -0
  18. package/dist/changed/contribution.d.ts +32 -0
  19. package/dist/changed/footer-content.d.ts +16 -0
  20. package/dist/changed/index.d.ts +4 -0
  21. package/dist/changed/tab-badge.d.ts +8 -0
  22. package/dist/changed/tab-filter.d.ts +8 -0
  23. package/dist/config/panel-config.d.ts +23 -7
  24. package/dist/constants.d.ts +66 -0
  25. package/dist/constants.js +30 -0
  26. package/dist/controls/actions-menu-popover.d.ts +2 -0
  27. package/dist/controls/role-button.d.ts +5 -2
  28. package/dist/controls/tooltip.d.ts +8 -4
  29. package/dist/element-inspect/element-inspect-context.d.ts +22 -0
  30. package/dist/element-inspect/element-inspect-orchestrator.d.ts +17 -0
  31. package/dist/element-inspect/element-inspect-overlay.d.ts +16 -0
  32. package/dist/element-inspect/element-inspect-toggle-button.d.ts +3 -0
  33. package/dist/element-inspect/element-inspect-view.d.ts +6 -0
  34. package/dist/element-inspect/find-tokens-for-element.d.ts +23 -0
  35. package/dist/element-inspect/index.d.ts +8 -0
  36. package/dist/highlight/find-elements.d.ts +14 -3
  37. package/dist/highlight/highlight-orchestrator.d.ts +7 -3
  38. package/dist/highlight/highlight-state.d.ts +3 -2
  39. package/dist/highlight/highlight-toggle-button.d.ts +3 -0
  40. package/dist/highlight/walk-css-rules.d.ts +2 -0
  41. package/dist/history/buttons.d.ts +28 -0
  42. package/dist/history/index.d.ts +3 -0
  43. package/dist/history/rail.d.ts +13 -0
  44. package/dist/history/snapshots.d.ts +57 -0
  45. package/dist/host/host-mutations.d.ts +23 -0
  46. package/dist/{index-EdhZv8Ru.js → index-By6zFdp4.js} +2 -2
  47. package/dist/index-CHzTi0y5.js +12184 -0
  48. package/dist/index.js +35 -34
  49. package/dist/load-routing-BtCE1hGI.js +547 -0
  50. package/dist/{manifest-DCReQE0k.js → manifest-DvuKi7I4.js} +11 -7
  51. package/dist/{panel-config-SgA84Uqe.js → panel-config-BSu6TUht.js} +391 -317
  52. package/dist/picker/alt-click-picker.d.ts +10 -2
  53. package/dist/picker/arming-coordinator.d.ts +2 -0
  54. package/dist/picker/index.d.ts +2 -2
  55. package/dist/search/command-palette.d.ts +21 -0
  56. package/dist/search/contribution.d.ts +7 -0
  57. package/dist/search/fuzzy.d.ts +10 -0
  58. package/dist/search/index.d.ts +4 -0
  59. package/dist/search/match-bar.d.ts +14 -0
  60. package/dist/search/search-header.d.ts +7 -0
  61. package/dist/search/token-search.d.ts +36 -0
  62. package/dist/server/create-apply-handler.d.ts +33 -0
  63. package/dist/server/index.d.ts +2 -1
  64. package/dist/server/index.js +1 -1
  65. package/dist/shell/dock-mode-switch.d.ts +6 -0
  66. package/dist/shell/footer.d.ts +1 -0
  67. package/dist/shell/ghost-idle.d.ts +24 -0
  68. package/dist/shell/header.d.ts +4 -0
  69. package/dist/shell/layer-activity.d.ts +6 -0
  70. package/dist/shell/mini-pill.d.ts +21 -0
  71. package/dist/shell/regions.d.ts +26 -0
  72. package/dist/shell/shortcut-dispatcher.d.ts +17 -0
  73. package/dist/shell/tab-bar.d.ts +17 -0
  74. package/dist/shell/tab-overflow-popover.d.ts +13 -0
  75. package/dist/specimen/on-page-specimen.d.ts +19 -0
  76. package/dist/specimen/preview-glyphs.d.ts +2 -0
  77. package/dist/specimen/specimen-state.d.ts +12 -0
  78. package/dist/specimen/specimen-tab-body.d.ts +18 -0
  79. package/dist/specimen/specimen-toolbar.d.ts +10 -0
  80. package/dist/specimen/specimen-values.d.ts +9 -0
  81. package/dist/state/history.d.ts +64 -0
  82. package/dist/state/persist.d.ts +10 -14
  83. package/dist/state/transaction.d.ts +24 -0
  84. package/dist/state/tweak-state.d.ts +16 -0
  85. package/dist/styles/z-index-tokens.d.ts +2 -0
  86. package/dist/tabs/color-tab.d.ts +10 -1
  87. package/dist/tabs/flat/flat-tab.d.ts +27 -0
  88. package/dist/tabs/flat/index.d.ts +8 -0
  89. package/dist/tabs/flat/scroll-to-token-row.d.ts +3 -0
  90. package/dist/tabs/flat/tier-section.d.ts +17 -0
  91. package/dist/tabs/flat/token-controller.d.ts +23 -0
  92. package/dist/tabs/flat/token-row.d.ts +12 -0
  93. package/dist/tabs/flat/types.d.ts +25 -0
  94. package/dist/tabs/font-tab.d.ts +13 -12
  95. package/dist/tabs/generic-tab.d.ts +8 -38
  96. package/dist/tabs/palette/palette-check-view.d.ts +5 -1
  97. package/dist/tabs/palette/palette-edit-view.d.ts +9 -1
  98. package/dist/tabs/palette/palette-tab.d.ts +12 -1
  99. package/dist/tabs/size-tab.d.ts +7 -10
  100. package/dist/tabs/spacing-tab.d.ts +7 -13
  101. package/dist/testing.js +3 -3
  102. package/dist/tokens/tier-model.d.ts +6 -0
  103. package/dist/{tweak-state-DGLrzIwq.js → tweak-state-B7ok3Ob3.js} +473 -423
  104. package/dist/utils/numeric-transform.d.ts +32 -0
  105. package/dist/utils/token-diff.d.ts +25 -0
  106. package/dist/utils/token-graph.d.ts +23 -0
  107. package/dist/utils/token-index.d.ts +30 -0
  108. package/dist/zdtp.css +1 -1
  109. package/package.json +8 -1
  110. package/dist/controls/pill-slider-row.d.ts +0 -36
  111. package/dist/controls/select-row.d.ts +0 -25
  112. package/dist/controls/slider-row.d.ts +0 -29
  113. package/dist/controls/text-row.d.ts +0 -27
  114. package/dist/index-Ds4bCeiC.js +0 -7591
  115. package/dist/load-routing-D4H2VOl5.js +0 -426
@@ -55,8 +55,8 @@
55
55
  * degraded-init paths) can pass `colorDefaults: undefined`; in that case the
56
56
  * whole color block is treated as changed.
57
57
  *
58
- * For non-color tokens, `TokenOverrides` is already a sparse diff (only
59
- * overridden tokens appear in the map) — no baseline comparison is needed.
58
+ * For non-color tokens, the sparse maps may retain empty or default-equal
59
+ * values. Those entries are omitted so Apply matches UI and diff-only export.
60
60
  *
61
61
  * Pure / no IO — safe to import anywhere (browser, Node, tests).
62
62
  */
@@ -0,0 +1,23 @@
1
+ /** A single CSS custom-property change suitable for an apply preview. */
2
+ export interface ApplyHunk {
3
+ cssVar: string;
4
+ /** One-based line number of the declaration in the proposed file. */
5
+ line: number;
6
+ /** Complete declaration line before the rewrite. */
7
+ before: string;
8
+ /** Complete declaration line after the rewrite. */
9
+ after: string;
10
+ /** Neighbouring proposed-file lines, excluding the declaration itself. */
11
+ context: {
12
+ before: string[];
13
+ after: string[];
14
+ };
15
+ }
16
+ /**
17
+ * Compute one preview hunk per changed cssVar.
18
+ *
19
+ * `changedCssVars` is authoritative: unrelated textual differences never
20
+ * become hunks. Input order is retained so the response follows request/apply
21
+ * order, including when multiple declarations share one physical line.
22
+ */
23
+ export declare function computeHunks(beforeSource: string, afterSource: string, changedCssVars: readonly string[], contextLineCount?: number): ApplyHunk[];
@@ -0,0 +1,5 @@
1
+ import type { PanelConfig } from '../config/panel-config';
2
+ export type FlatOverrides = Record<string, string>;
3
+ export declare function loadLastApplied(cfg: PanelConfig): FlatOverrides;
4
+ export declare function saveLastApplied(overrides: FlatOverrides, cfg: PanelConfig): void;
5
+ export declare function unsavedCssVars(current: FlatOverrides, baseline: FlatOverrides): string[];
@@ -0,0 +1,19 @@
1
+ import type { PanelConfig } from '../config/panel-config';
2
+ import type { ColorTweakState, TweakState } from '../state/tweak-state';
3
+ /**
4
+ * Remove only overrides the server confirms it wrote. CSS variables are
5
+ * resolved through the manifest token index so color, secondary-color,
6
+ * reserved, and generic tab state all follow the same address-based path.
7
+ *
8
+ * A same-alias semantic mapping can be emitted because its bg/fg dependency
9
+ * moved even though the mapping itself did not. Since base-role variables are
10
+ * outside disk Apply, reconcile that dependency when its derived semantic var
11
+ * was written. Unwritten aliases are first materialized to their current
12
+ * numeric index so partial writes never discard their emitted value.
13
+ */
14
+ export declare function reconcileApplied(state: TweakState, writtenCssVars: readonly string[], cfg: PanelConfig, colorDefaults: ColorTweakState, secondaryDefaults?: ColorTweakState): TweakState;
15
+ export declare function writtenCssVarsFromResponse(response: {
16
+ updated?: readonly {
17
+ changed?: readonly string[];
18
+ }[];
19
+ }): string[];
@@ -1,58 +1,12 @@
1
- /**
2
- * Apply modal — previews the diff between the current `TweakState` and the
3
- * scheme defaults, then POSTs the diff to the dev-only
4
- * `/api/dev/design-tokens-apply` endpoint so the tweaks are written back
5
- * into the host's design-system CSS files on disk.
6
- *
7
- * Wiring summary
8
- * --------------
9
- * - Diff building is delegated to `./apply/build-apply-overrides`, which
10
- * consumes the new `ColorTweakState` shape (palette + semanticMappings) and
11
- * emits the flat `{ cssVar: value }` map using `SEMANTIC_CSS_NAMES`.
12
- * - Per-file grouping (for the preview and for the success view) uses
13
- * `./apply/route-tokens-to-files` — the exact same routing the dev-API
14
- * handler runs server-side, so the preview matches the server's view of
15
- * the world byte-for-byte.
16
- * - Styling uses bundled BEM classes derived from
17
- * `panelConfig.modalClassPrefix` via `modalClass(...)`. The matching CSS
18
- * lives in `styles/panel.css` keyed on the default modal class prefix;
19
- * consumers that override the prefix opt out of bundled CSS and ship
20
- * their own. No Tailwind classes remain.
21
- *
22
- * Dialog lifecycle (unchanged)
23
- * ----------------------------
24
- * Uses the native `<dialog>` element. Every dismissal path (× / backdrop /
25
- * Escape / programmatic close) routes through `dialog.close()`, which fires
26
- * the native `close` event exactly once; `onClose` then fires exactly once
27
- * per dismissal regardless of the path taken.
28
- */
29
1
  import { type PanelConfig } from './config/panel-config';
30
2
  import { type ColorTweakState, type TweakState } from './state/tweak-state';
31
3
  export interface ApplyModalProps {
32
4
  state: TweakState;
33
5
  open: boolean;
34
6
  onClose: () => void;
35
- /**
36
- * Scheme baseline used to diff the current `state.color` against when
37
- * computing the flat cssVar overrides. When absent, the entire color block
38
- * is treated as changed — useful for tests, but real callers (the panel
39
- * itself) always pass the active scheme's initial `ColorTweakState`.
40
- */
41
7
  colorDefaults?: ColorTweakState;
42
- /**
43
- * Fired exactly once after the user confirms a successful apply by clicking
44
- * "Done". The parent is expected to clear the persisted state envelope,
45
- * clear any inline-applied styles, and reset in-memory state to empty.
46
- */
47
- onApplied: () => void;
48
- /**
49
- * The mounted panel instance's config (multi-instance, #357). When supplied,
50
- * the modal resolves its apply routing / endpoint / secondary cluster / modal
51
- * classes from THIS instance rather than the active default instance — so an
52
- * Apply on panel A targets A's endpoint+routing, not whichever instance was
53
- * configured last. Omitted (e.g. a direct test render) → `getPanelConfig()`,
54
- * preserving the single-panel path.
55
- */
8
+ onApplied: (writtenCssVars: string[]) => void;
56
9
  instanceConfig?: PanelConfig;
57
10
  }
11
+ export declare function flattenApplyOverrides(state: TweakState, colorDefaults: ColorTweakState | undefined, cfg: PanelConfig): Record<string, string>;
58
12
  export declare function ApplyModal(props: ApplyModalProps): import("preact").JSX.Element;
@@ -1,6 +1,6 @@
1
- import { c as y, g as m, a as w, b, i as P } from "../panel-config-SgA84Uqe.js";
2
- import { g, Z as k } from "../tweak-state-DGLrzIwq.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-IlkEci88.js";
1
+ import { c as y, g as m, a as w, b, i as P } from "../panel-config-BSu6TUht.js";
2
+ import { g, Z as k } from "../tweak-state-B7ok3Ob3.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-DmTY6tRy.js";
4
4
  const u = "tokenpanel-config";
5
5
  function S() {
6
6
  if (typeof document > "u")
@@ -1,6 +1,6 @@
1
- import { s as t } from "../panel-config-SgA84Uqe.js";
1
+ import { s as t } from "../panel-config-BSu6TUht.js";
2
2
  import { c as d } from "../color-schemes-CgzOBqGO.js";
3
- import { F as r, G as m, a as g, S as z } from "../manifest-DCReQE0k.js";
3
+ import { F as r, G as m, a as g, S as z } from "../manifest-DvuKi7I4.js";
4
4
  const e = {
5
5
  colorScheme: "Default Dark",
6
6
  colorMode: !1
@@ -1,4 +1,4 @@
1
- import { g as n, j as o } from "./panel-config-SgA84Uqe.js";
1
+ import { g as n, j as o } from "./panel-config-BSu6TUht.js";
2
2
  function c() {
3
3
  return typeof document < "u" && document !== null && typeof document.getElementById == "function";
4
4
  }
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { realpathSync as E } from "node:fs";
3
- import { createServer as H } from "node:http";
4
- import { resolve as p } from "node:path";
5
- import { l as $, c as x } from "../load-routing-D4H2VOl5.js";
6
- function g(o, t) {
2
+ import { realpathSync as $ } from "node:fs";
3
+ import { createServer as E } from "node:http";
4
+ import { resolve as h } from "node:path";
5
+ import { l as H, c as L } from "../load-routing-BtCE1hGI.js";
6
+ function w(o, t) {
7
7
  return typeof o != "string" || o.length === 0 || t.length === 0 ? !1 : t.includes(o);
8
8
  }
9
- function w(o) {
9
+ function y(o) {
10
10
  return {
11
11
  "Access-Control-Allow-Origin": o,
12
12
  "Access-Control-Allow-Methods": "POST, OPTIONS",
@@ -14,7 +14,7 @@ function w(o) {
14
14
  "Access-Control-Max-Age": "600"
15
15
  };
16
16
  }
17
- const k = 24681, b = "127.0.0.1", N = `Usage: zdtp-server [options]
17
+ const b = 24681, O = "127.0.0.1", x = `Usage: zdtp-server [options]
18
18
 
19
19
  Run a small Node http server that wraps the design-token apply handler.
20
20
 
@@ -25,8 +25,8 @@ Options:
25
25
  single directory the bin is allowed to write into.
26
26
  --routing <path> REQUIRED. Path to the routing JSON file
27
27
  (prefix -> repo-relative CSS file path).
28
- --port <number> TCP port to bind. Default: ${k}.
29
- --host <addr> Host/interface to bind. Default: ${b}.
28
+ --port <number> TCP port to bind. Default: ${b}.
29
+ --host <addr> Host/interface to bind. Default: ${O}.
30
30
  Use 0.0.0.0 to expose on the LAN (off by default).
31
31
  --allow-origin <origin> Origin allowed to POST to /apply. Repeatable.
32
32
  At least one is required for any browser to apply.
@@ -39,13 +39,13 @@ Examples:
39
39
  --routing ./my.routing.json \\
40
40
  --allow-origin http://localhost:34434
41
41
  `;
42
- function v(o) {
42
+ function N(o) {
43
43
  const t = {
44
44
  root: null,
45
45
  writeRoot: null,
46
46
  routing: null,
47
- port: k,
48
- host: b,
47
+ port: b,
48
+ host: O,
49
49
  allowOrigins: [],
50
50
  quiet: !1,
51
51
  help: !1
@@ -102,9 +102,9 @@ function c(o, t, e) {
102
102
  throw new Error(`${e} requires a value`);
103
103
  return n;
104
104
  }
105
- const y = "/apply", D = "/healthz";
106
- function L(o) {
107
- const t = p(o.root ?? process.cwd()), e = p(t, o.writeRoot), n = p(t, o.routing);
105
+ const k = "/apply", v = "/healthz";
106
+ function D(o) {
107
+ const t = h(o.root ?? process.cwd()), e = h(t, o.writeRoot), n = h(t, o.routing);
108
108
  return {
109
109
  rootDir: t,
110
110
  writeRoot: e,
@@ -119,13 +119,13 @@ function a(o, t, e) {
119
119
  const n = JSON.stringify(e);
120
120
  o.statusCode = t, o.setHeader("Content-Type", "application/json"), o.setHeader("Content-Length", Buffer.byteLength(n).toString()), o.end(n);
121
121
  }
122
- const O = 1048576;
122
+ const A = 1048576;
123
123
  function j(o) {
124
124
  return new Promise((t, e) => {
125
125
  const n = [];
126
126
  let s = 0;
127
127
  o.on("data", (r) => {
128
- if (s += r.byteLength, s > O) {
128
+ if (s += r.byteLength, s > A) {
129
129
  t(413), o.destroy();
130
130
  return;
131
131
  }
@@ -154,13 +154,15 @@ function V(o, t) {
154
154
  if (!o)
155
155
  try {
156
156
  const e = JSON.parse(t);
157
- if (!e.ok || !Array.isArray(e.updated)) return;
158
- const n = e.updated.reduce(
159
- (i, l) => i + (Array.isArray(l.changed) ? l.changed.length : 0),
157
+ if (!e.ok) return;
158
+ const n = e.dryRun === !0 ? e.files : e.updated;
159
+ if (!Array.isArray(n)) return;
160
+ const s = n.reduce(
161
+ (i, f) => i + (Array.isArray(f.changed) ? f.changed.length : 0),
160
162
  0
161
- ), s = e.updated.length, r = e.updated.filter((i) => Array.isArray(i.changed) && i.changed.length > 0).map((i) => i.file);
163
+ ), r = n.length, l = n.filter((i) => Array.isArray(i.changed) && i.changed.length > 0).map((i) => i.file), u = e.dryRun === !0 ? "dry-run" : "applied";
162
164
  console.log(
163
- `[design-token-panel] applied ${n} tokens to ${s} files (changed: ${r.length > 0 ? r.join(", ") : "none"})`
165
+ `[design-token-panel] ${u} ${s} ${s === 1 ? "token" : "tokens"} to ${r} ${r === 1 ? "file" : "files"} (changed: ${l.length > 0 ? l.join(", ") : "none"})`
164
166
  ), Array.isArray(e.unknownCssVars) && e.unknownCssVars.length > 0 && console.log(
165
167
  `[design-token-panel] unknown: ${e.unknownCssVars.length} cssVar(s) not found (${e.unknownCssVars.join(", ")})`
166
168
  ), Array.isArray(e.unknownOutsideBlockCssVars) && e.unknownOutsideBlockCssVars.length > 0 && console.log(
@@ -172,9 +174,9 @@ function V(o, t) {
172
174
  function B(o) {
173
175
  const { applyHandler: t, config: e } = o;
174
176
  return async function(s, r) {
175
- const i = s.url ?? "/", l = (s.method ?? "GET").toUpperCase(), u = typeof s.headers.origin == "string" ? s.headers.origin : null;
177
+ const l = s.url ?? "/", u = (s.method ?? "GET").toUpperCase(), d = typeof s.headers.origin == "string" ? s.headers.origin : null;
176
178
  try {
177
- if (i === D && l === "GET") {
179
+ if (l === v && u === "GET") {
178
180
  a(r, 200, {
179
181
  ok: !0,
180
182
  writeRoot: e.writeRoot,
@@ -183,51 +185,51 @@ function B(o) {
183
185
  });
184
186
  return;
185
187
  }
186
- if (i === y) {
187
- if (l === "OPTIONS") {
188
- if (!g(u, e.allowOrigins)) {
188
+ if (l === k) {
189
+ if (u === "OPTIONS") {
190
+ if (!w(d, e.allowOrigins)) {
189
191
  a(r, 403, { ok: !1, error: "Origin not allowed" });
190
192
  return;
191
193
  }
192
- const S = w(u);
194
+ const S = y(d);
193
195
  for (const [C, P] of Object.entries(S))
194
196
  r.setHeader(C, P);
195
197
  r.statusCode = 204, r.end();
196
198
  return;
197
199
  }
198
- if (l !== "POST") {
200
+ if (u !== "POST") {
199
201
  r.setHeader("Allow", "POST, OPTIONS"), a(r, 405, { ok: !1, error: "Method not allowed" });
200
202
  return;
201
203
  }
202
- const d = s.headers["content-type"];
203
- if (typeof d != "string" || !d.toLowerCase().includes("application/json")) {
204
+ const p = s.headers["content-type"];
205
+ if (typeof p != "string" || !p.toLowerCase().includes("application/json")) {
204
206
  a(r, 415, { ok: !1, error: "Content-Type must be application/json" });
205
207
  return;
206
208
  }
207
- if (!g(u, e.allowOrigins)) {
209
+ if (!w(d, e.allowOrigins)) {
208
210
  a(r, 403, { ok: !1, error: "Origin not allowed" });
209
211
  return;
210
212
  }
211
- const f = await j(s);
212
- if (f === 413) {
213
+ const i = await j(s);
214
+ if (i === 413) {
213
215
  a(r, 413, {
214
216
  ok: !1,
215
217
  error: "Payload Too Large",
216
- limit: O
218
+ limit: A
217
219
  });
218
220
  return;
219
221
  }
220
- const A = f, m = new Request(`http://localhost${y}`, {
222
+ const f = i, m = new Request(`http://localhost${k}`, {
221
223
  method: "POST",
222
224
  headers: U(s),
223
- body: A
224
- }), h = await t(m), R = await h.clone().text(), T = w(u);
225
- await I(r, h, T), V(e.quiet, R);
225
+ body: f
226
+ }), g = await t(m), R = await g.clone().text(), T = y(d);
227
+ await I(r, g, T), V(e.quiet, R);
226
228
  return;
227
229
  }
228
230
  a(r, 404, { ok: !1, error: "Not found" });
229
- } catch (d) {
230
- console.error("[design-token-panel] Unhandled error:", d), r.headersSent ? r.end() : a(r, 500, { ok: !1, error: "Internal server error" });
231
+ } catch (p) {
232
+ console.error("[design-token-panel] Unhandled error:", p), r.headersSent ? r.end() : a(r, 500, { ok: !1, error: "Internal server error" });
231
233
  }
232
234
  };
233
235
  }
@@ -247,28 +249,28 @@ function q(o, t) {
247
249
  function F() {
248
250
  let o;
249
251
  try {
250
- o = v(process.argv.slice(2));
252
+ o = N(process.argv.slice(2));
251
253
  } catch (r) {
252
254
  console.error(`[design-token-panel] ${r.message}`), console.error(""), console.error("Run --help for usage."), process.exit(1);
253
255
  }
254
- o.help && (process.stdout.write(N), process.exit(0));
255
- const t = L(o);
256
+ o.help && (process.stdout.write(x), process.exit(0));
257
+ const t = D(o);
256
258
  let e;
257
259
  try {
258
- e = $(t.routingPath);
260
+ e = H(t.routingPath);
259
261
  } catch (r) {
260
262
  console.error(`[design-token-panel] Failed to load routing: ${r.message}`), process.exit(1);
261
263
  }
262
- const n = x({
264
+ const n = L({
263
265
  rootDir: t.rootDir,
264
266
  writeRoot: t.writeRoot,
265
267
  routing: e
266
- }), s = H(B({ applyHandler: n, config: t }));
268
+ }), s = E(B({ applyHandler: n, config: t }));
267
269
  q(s, t.port), s.listen(t.port, t.host, () => {
268
270
  if (!t.quiet) {
269
- const r = s.address(), i = typeof r == "object" && r ? r.port : t.port;
271
+ const r = s.address(), l = typeof r == "object" && r ? r.port : t.port;
270
272
  console.log(
271
- `[design-token-panel] listening on http://${t.host}:${i} (writeRoot: ${t.writeRoot})`
273
+ `[design-token-panel] listening on http://${t.host}:${l} (writeRoot: ${t.writeRoot})`
272
274
  ), t.allowOrigins.length === 0 && console.log(
273
275
  "[design-token-panel] WARNING: no --allow-origin set; browser POST /apply will be rejected."
274
276
  );
@@ -278,7 +280,7 @@ function F() {
278
280
  const _ = (() => {
279
281
  if (typeof process.argv[1] != "string") return !1;
280
282
  try {
281
- const o = E(process.argv[1]), t = new URL(`file://${p(o)}`).href, e = import.meta.url;
283
+ const o = $(process.argv[1]), t = new URL(`file://${h(o)}`).href, e = import.meta.url;
282
284
  return t === e;
283
285
  } catch {
284
286
  return !1;
@@ -0,0 +1,45 @@
1
+ import type { ComponentChildren } from 'preact';
2
+ import type { TierConfig } from '../tokens/tier-model';
3
+ import { type NumericValue } from '../utils/numeric-transform';
4
+ import type { FlatTabEntry, RowContribution, TokenAddress } from '../tabs/flat/types';
5
+ export interface BulkOperations {
6
+ multiply: string;
7
+ add: string;
8
+ roundToStep: string;
9
+ setTo: string;
10
+ }
11
+ export declare const DEFAULT_BULK_OPERATIONS: BulkOperations;
12
+ export interface BulkPatchEntry {
13
+ address: TokenAddress;
14
+ value: string;
15
+ }
16
+ export interface BulkContributionOptions {
17
+ entriesByTier: ReadonlyMap<string, readonly FlatTabEntry[]>;
18
+ selectedKeys: ReadonlySet<string>;
19
+ operations: BulkOperations;
20
+ onToggle: (entry: FlatTabEntry, checked: boolean) => void;
21
+ onSelectTier: (tier: TierConfig, checked: boolean) => void;
22
+ onQuick: (tier: TierConfig, factor: number) => void;
23
+ }
24
+ /** Return the declared unit for a numeric token kind. */
25
+ export declare function numericEntryUnit(entry: FlatTabEntry): string;
26
+ /**
27
+ * Bulk selection is deliberately narrower than numeric row rendering. A row
28
+ * must be a writable literal length/number with a parseable current value.
29
+ * Reference tiers, readonly rows, and active pill sentinels cannot safely
30
+ * participate in a numeric transform.
31
+ */
32
+ export declare function isBulkSelectable(entry: FlatTabEntry): boolean;
33
+ export declare const isSelectable: typeof isBulkSelectable;
34
+ export declare function numericValueForEntry(entry: FlatTabEntry): NumericValue | null;
35
+ /** Compute one preview value from the action-bar operation fields. */
36
+ export declare function transformBulkEntry(entry: FlatTabEntry, operations: BulkOperations): string | null;
37
+ export declare function createBulkContribution(options: BulkContributionOptions): RowContribution;
38
+ export interface BulkActionBarProps {
39
+ entries: readonly FlatTabEntry[];
40
+ operations: BulkOperations;
41
+ onOperationsChange: (operations: BulkOperations) => void;
42
+ onClear: () => void;
43
+ onApply: (patch: readonly BulkPatchEntry[]) => void;
44
+ }
45
+ export declare function BulkActionBar({ entries, operations, onOperationsChange, onClear, onApply, }: BulkActionBarProps): ComponentChildren;
@@ -0,0 +1,2 @@
1
+ export { BulkActionBar, DEFAULT_BULK_OPERATIONS, createBulkContribution, isBulkSelectable, isSelectable, numericEntryUnit, numericValueForEntry, transformBulkEntry, } from './bulk-actions';
2
+ export type { BulkActionBarProps, BulkContributionOptions, BulkOperations, BulkPatchEntry, } from './bulk-actions';
@@ -0,0 +1,2 @@
1
+ export { ChainButton, ChainPopover, TOKEN_CHAIN_CONTRIBUTION, TokenChainButton, TokenChainPopover, type TokenChainButtonProps, type TokenChainPopoverProps, } from './token-chain-popover';
2
+ export { TokenChainProvider, useTokenChainContext, type TokenChainContextValue, type TokenChainProviderProps, } from './token-chain-context';
@@ -0,0 +1,19 @@
1
+ import type { ComponentChildren } from 'preact';
2
+ import type { PanelConfig } from '../config/panel-config';
3
+ import type { TweakState } from '../state/tweak-state';
4
+ import { type TokenGraph } from '../utils/token-graph';
5
+ export interface TokenChainContextValue {
6
+ graph: TokenGraph;
7
+ }
8
+ export interface TokenChainProviderProps {
9
+ instanceConfig: PanelConfig;
10
+ state: TweakState | null;
11
+ children?: ComponentChildren;
12
+ }
13
+ /**
14
+ * Keeps the dependency graph tied to the mounted panel instance and its live
15
+ * tweak state. A chain control rendered outside this provider simply degrades
16
+ * to no chain affordance, which keeps the row primitives useful in isolation.
17
+ */
18
+ export declare function TokenChainProvider({ instanceConfig, state, children, }: TokenChainProviderProps): import("preact").JSX.Element;
19
+ export declare function useTokenChainContext(): TokenChainContextValue | null;
@@ -0,0 +1,22 @@
1
+ import type { JSX } from 'preact';
2
+ import { type TokenAddress } from '../utils/token-index';
3
+ import type { RowContribution } from '../tabs/flat/types';
4
+ export interface TokenChainPopoverProps {
5
+ address: TokenAddress;
6
+ anchorRef: React.RefObject<HTMLElement | null>;
7
+ onClose: () => void;
8
+ }
9
+ /**
10
+ * Body of the per-token chain surface. It is mounted only while its trigger
11
+ * is open, so the first page probe is deferred until the user asks for it.
12
+ */
13
+ export declare function TokenChainPopover({ address, anchorRef, onClose, }: TokenChainPopoverProps): JSX.Element | null;
14
+ export interface TokenChainButtonProps {
15
+ address: TokenAddress;
16
+ }
17
+ /** Chain trigger used by flat rows and Color-tab custom rows. */
18
+ export declare function TokenChainButton({ address }: TokenChainButtonProps): JSX.Element | null;
19
+ /** Shared FlatTab contribution for every non-Color row. */
20
+ export declare const TOKEN_CHAIN_CONTRIBUTION: RowContribution;
21
+ export declare const ChainPopover: typeof TokenChainPopover;
22
+ export declare const ChainButton: typeof TokenChainButton;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Changed-state row contribution.
3
+ *
4
+ * The S2 token evaluator is deliberately the only source of truth here. A
5
+ * row's visual state, Changed-only filtering, ghost value, and revert affordance
6
+ * all consult the same `isChanged` result for the row's stable token address.
7
+ */
8
+ import type { PanelConfig } from '../config/panel-config';
9
+ import type { TweakState } from '../state/tweak-state';
10
+ import { revertEntry, type ColorBaseline } from '../utils/token-diff';
11
+ import type { TokenIndex, TokenAddress } from '../utils/token-index';
12
+ import type { RowContribution } from '../tabs/flat/types';
13
+ export interface ChangedContributionOptions {
14
+ index: TokenIndex;
15
+ state: TweakState;
16
+ baseline: ColorBaseline;
17
+ cfg: PanelConfig;
18
+ /** True while the active tab's transient Changed-only filter is enabled. */
19
+ changedOnly?: boolean;
20
+ /** Reverts one stable token address through the shell transaction. */
21
+ onRevert: (address: TokenAddress) => void;
22
+ }
23
+ /**
24
+ * Build the contribution used by FlatTab-based token lists. `revertEntry`
25
+ * remains in the shell callback rather than here so this presentation seam
26
+ * never mutates state directly.
27
+ */
28
+ export declare function changedContribution(options: ChangedContributionOptions): RowContribution;
29
+ /** Explicit factory alias for feature callers and downstream consumers. */
30
+ export declare const createChangedContribution: typeof changedContribution;
31
+ export declare const changedStateContribution: typeof changedContribution;
32
+ export { revertEntry };
@@ -0,0 +1,16 @@
1
+ import type { JSX } from 'preact';
2
+ import type { PanelConfig } from '../config/panel-config';
3
+ import type { ColorBaseline } from '../utils/token-diff';
4
+ import type { TweakState } from '../state/tweak-state';
5
+ import type { TokenIndex } from '../utils/token-index';
6
+ export declare const COPY_REVERT_MS = 2000;
7
+ export interface ChangedFooterContentProps {
8
+ index: TokenIndex;
9
+ state: TweakState;
10
+ baseline: ColorBaseline;
11
+ cfg: PanelConfig;
12
+ onRevertAll: () => void;
13
+ }
14
+ /** Footer summary + evaluator-backed Copy diff / Revert all actions. */
15
+ export declare function ChangedFooterContent({ index, state, baseline, cfg, onRevertAll, }: ChangedFooterContentProps): JSX.Element;
16
+ export declare const ChangedFooter: typeof ChangedFooterContent;
@@ -0,0 +1,4 @@
1
+ export { changedContribution, changedStateContribution, createChangedContribution, revertEntry, } from './contribution';
2
+ export { ChangedFooter, ChangedFooterContent, COPY_REVERT_MS } from './footer-content';
3
+ export { ChangedOnlyToggle } from './tab-filter';
4
+ export { ChangedTabBadge, TabChangedBadge } from './tab-badge';
@@ -0,0 +1,8 @@
1
+ import type { JSX } from 'preact';
2
+ export interface ChangedTabBadgeProps {
3
+ tabId: string;
4
+ count: number;
5
+ }
6
+ /** Count badge rendered inside a tab button without affecting tab overflow. */
7
+ export declare function ChangedTabBadge({ tabId, count }: ChangedTabBadgeProps): JSX.Element | null;
8
+ export declare const TabChangedBadge: typeof ChangedTabBadge;
@@ -0,0 +1,8 @@
1
+ import type { JSX } from 'preact';
2
+ export interface ChangedOnlyToggleProps {
3
+ enabled: boolean;
4
+ count: number;
5
+ onChange: (enabled: boolean) => void;
6
+ }
7
+ /** Transient active-tab Changed-only filter (never persisted). */
8
+ export declare function ChangedOnlyToggle({ enabled, count, onChange, }: ChangedOnlyToggleProps): JSX.Element;
@@ -47,6 +47,7 @@
47
47
  */
48
48
  import type { ColorScheme } from './color-schemes';
49
49
  import type { TabConfig } from '../tokens/tier-model';
50
+ export { DEFAULT_STORAGE_PREFIX, DEFAULT_TOGGLE_EVENT } from '../constants';
50
51
  /**
51
52
  * Apply-routing map.
52
53
  *
@@ -72,6 +73,10 @@ export type ApplyRoutingMap = Record<string, string>;
72
73
  export interface DomTweakerConfig {
73
74
  themeCss?: string;
74
75
  }
76
+ export interface PanelDockConfig {
77
+ /** Whether docked panels reserve space in the host document. Defaults to body-margin. */
78
+ reflow?: 'body-margin' | 'none';
79
+ }
75
80
  /**
76
81
  * Apply sink interface — allows routing CSS-var writes somewhere other than
77
82
  * the host `:root` (e.g. a shadow root, an iframe document, or a spy in
@@ -150,6 +155,8 @@ export interface PanelConfig {
150
155
  * panel config.
151
156
  */
152
157
  domTweaker?: DomTweakerConfig;
158
+ /** Docked-panel integration. Omitted values use body-margin host reflow. */
159
+ dock?: PanelDockConfig;
153
160
  /**
154
161
  * Host-supplied tab configuration for the data-driven tab strip.
155
162
  *
@@ -470,8 +477,22 @@ export declare function storageKey_open(cfg: PanelConfig): string;
470
477
  export declare function storageKey_position(cfg: PanelConfig): string;
471
478
  /** User-resized panel size `{ width, height }` (pixels). Lives alongside position. */
472
479
  export declare function storageKey_size(cfg: PanelConfig): string;
480
+ /** Persisted shell dock mode. */
481
+ export declare function storageKey_dock(cfg: PanelConfig): string;
482
+ /** Per-axis docked dimensions (`right` width and `bottom` height). */
483
+ export declare function storageKey_dockSize(cfg: PanelConfig): string;
473
484
  /** Tab-grid density preference (one of `0` / `1` / `2`). Lives alongside size/position. */
474
485
  export declare function storageKey_density(cfg: PanelConfig): string;
486
+ /** Font specimen toolbar state (`{ text, preset, overridden, width }`). */
487
+ export declare function storageKey_specimen(cfg: PanelConfig): string;
488
+ /** Persisted A/B snapshot slot. `slot` is lower-case for storage continuity. */
489
+ export declare function storageKey_snapshot(cfg: PanelConfig, slot: 'a' | 'b'): string;
490
+ /** Persisted snapshot A slot. */
491
+ export declare function storageKey_snapshotA(cfg: PanelConfig): string;
492
+ /** Persisted snapshot B slot. */
493
+ export declare function storageKey_snapshotB(cfg: PanelConfig): string;
494
+ /** Last flattened override set known to match the apply baseline. */
495
+ export declare function storageKey_lastApplied(cfg: PanelConfig): string;
475
496
  /**
476
497
  * Adapter-level visibility-intent flag.
477
498
  *
@@ -490,13 +511,6 @@ export declare function storageKey_visible(cfg: PanelConfig): string;
490
511
  export declare function storageKey_autoload(cfg: PanelConfig): string;
491
512
  /** DOM id of the root element the Preact panel tree mounts into. */
492
513
  export declare function panelRootId(cfg: PanelConfig): string;
493
- /**
494
- * Historical public toggle-event name. Hosts have shipped `window.dispatchEvent(
495
- * new CustomEvent('toggle-design-token-panel'))` since the single-panel era, so
496
- * the default instance MUST keep emitting/listening on this name regardless of
497
- * its derived `toggle-${storagePrefix}` form.
498
- */
499
- export declare const DEFAULT_TOGGLE_EVENT = "toggle-design-token-panel";
500
514
  /**
501
515
  * Window-event name that toggles this instance's panel.
502
516
  *
@@ -550,6 +564,8 @@ export declare function assertValidPanelConfig(value: unknown): asserts value is
550
564
  * has not configured one — callers MUST treat empty as "apply disabled".
551
565
  */
552
566
  export declare function resolveApplyRouting(cfg?: PanelConfig): ApplyRoutingMap;
567
+ /** Whether the host has supplied both pieces required for disk-rewrite Apply. */
568
+ export declare function isApplyConfigured(cfg?: PanelConfig): boolean;
553
569
  /**
554
570
  * Lazily attach a host-supplied color-preset map AFTER `configurePanel(...)`.
555
571
  *