@takazudo/zdtp 0.2.3 → 0.3.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.
@@ -8,16 +8,32 @@
8
8
  *
9
9
  * Plumbing approach
10
10
  * -----------------
11
- * Module-level singleton (NOT Preact context). The panel is a single-instance
12
- * dev tool, config is set once before the adapter mounts, and every read site
13
- * is happy to pay a function call to read the current config.
11
+ * Module-level registry (NOT Preact context), keyed by `storagePrefix`. Each
12
+ * distinct prefix owns one panel *instance* — its config, its post-configure
13
+ * hooks, its returned handle. Every read site is happy to pay a function call
14
+ * to read the current config. Historically this was a single global singleton;
15
+ * issue #353 (Z1) lifts it to a per-instance registry so multiple panels with
16
+ * distinct `storagePrefix`es can coexist on one page.
14
17
  *
15
- * Idempotency
16
- * -----------
17
- * `configurePanel` is one-shot. Calling it twice with structurally-equal
18
- * values is a silent no-op (a freshly-parsed inline JSON config can be
19
- * byte-equal to the previous call but referentially distinct, e.g. on Astro
20
- * view-transition reruns). Calling with structurally-different values throws.
18
+ * Backward-compatible default instance
19
+ * ------------------------------------
20
+ * The single-panel path is unchanged. `getPanelConfig()` (no argument) returns
21
+ * the config of the most-recently-configured instance — the "default" / active
22
+ * instance — or `DEFAULT_PANEL_CONFIG` when no host has called `configurePanel`
23
+ * yet. A host that only ever calls `configurePanel` once observes the exact
24
+ * same behaviour as the old singleton.
25
+ *
26
+ * Idempotency & re-configure rule (same-prefix)
27
+ * ---------------------------------------------
28
+ * `configurePanel(config)` returns an instance handle. For a GIVEN prefix it is
29
+ * one-shot: calling it again with structurally-equal values is a no-op and
30
+ * returns the SAME handle (a freshly-parsed inline JSON config can be byte-equal
31
+ * to the previous call but referentially distinct, e.g. on Astro view-transition
32
+ * reruns). Calling again with the same prefix but structurally-DIFFERENT values
33
+ * REJECTS WITH AN ERROR (see `configurePanel` JSDoc) — config conflicts surface
34
+ * immediately instead of silently corrupting one of the callers' assumptions.
35
+ * Calling with a DISTINCT prefix registers a new, independent instance and does
36
+ * NOT throw. This is the chosen rule for Z4/Z5; see `RECONFIGURE_RULE` below.
21
37
  *
22
38
  * Default fallback
23
39
  * ----------------
@@ -44,6 +60,22 @@ import type { TabConfig } from '../tokens/tier-model';
44
60
  * (JSON-serializable constraint).
45
61
  */
46
62
  export type ApplyRoutingMap = Record<string, string>;
63
+ /**
64
+ * Apply sink interface — allows routing CSS-var writes somewhere other than
65
+ * the host `:root` (e.g. a shadow root, an iframe document, or a spy in
66
+ * tests).
67
+ *
68
+ * - `apply(pairs)` — upsert the given var name→value pairs.
69
+ * - `clear(names)` — remove the given var names.
70
+ *
71
+ * Both methods receive only the vars that belong to THIS panel instance.
72
+ * Sink errors are non-fatal: the apply pipeline swallows them with
73
+ * `console.warn` and continues.
74
+ */
75
+ export interface ApplySink {
76
+ apply(pairs: ReadonlyArray<readonly [string, string]>): void;
77
+ clear(names: readonly string[]): void;
78
+ }
47
79
  /**
48
80
  * The portable PanelConfig shape.
49
81
  */
@@ -58,6 +90,17 @@ export interface PanelConfig {
58
90
  schemaId: string;
59
91
  /** Default filename base — exports save as `${exportFilenameBase}.json`. */
60
92
  exportFilenameBase: string;
93
+ /**
94
+ * Optional window-event name that toggles THIS instance's panel.
95
+ *
96
+ * The default (single-panel) instance keeps the historical public event
97
+ * `toggle-design-token-panel` (plus its `toggle-color-tweak-panel` alias) and
98
+ * ignores this field — see `toggleEventName()`. A configured instance with a
99
+ * NON-default `storagePrefix` listens on this name; when omitted it defaults
100
+ * to `toggle-${storagePrefix}` so two panels on one page get independent
101
+ * toggle channels with no cross-talk.
102
+ */
103
+ toggleEvent?: string;
61
104
  /**
62
105
  * Optional host-supplied color-scheme presets.
63
106
  *
@@ -97,6 +140,21 @@ export interface PanelConfig {
97
140
  * under the reserved id 'color-secondary'.
98
141
  */
99
142
  tabs: readonly TabConfig[];
143
+ /**
144
+ * Optional apply sink. When present, CSS-var writes and clears for this
145
+ * panel instance are routed through the sink instead of
146
+ * `document.documentElement`. This allows embedding the panel in a shadow
147
+ * DOM, an iframe, or a test spy without touching `:root`.
148
+ *
149
+ * Sink errors are non-fatal — the panel swallows them with `console.warn`.
150
+ * When absent the default path writes to `document.documentElement`
151
+ * (unchanged behavior).
152
+ *
153
+ * NOTE: this field carries a function reference and is therefore NOT
154
+ * JSON-serializable. It cannot be passed through Astro's inline JSON
155
+ * config. Supply it via a post-configure call or a custom adapter.
156
+ */
157
+ applySink?: ApplySink;
100
158
  /**
101
159
  * Optional id rename map applied during `loadPersistedState` migration.
102
160
  * Keys are old ids found in persisted state; values are either:
@@ -122,48 +180,177 @@ export interface PanelConfig {
122
180
  */
123
181
  legacyIdRenameMap?: Record<string, string | null>;
124
182
  }
183
+ /**
184
+ * Handle returned by `configurePanel`. Identifies one configured panel
185
+ * instance and exposes its imperative lifecycle controls.
186
+ *
187
+ * Identity & keying
188
+ * -----------------
189
+ * `instanceId` equals the instance's `storagePrefix` — the registry key. Two
190
+ * `configurePanel` calls with the same prefix+config return the SAME handle
191
+ * object (referential identity is stable across idempotent re-calls); distinct
192
+ * prefixes return distinct handles.
193
+ *
194
+ * Method bodies — seams for later sub-tasks
195
+ * -----------------------------------------
196
+ * This sub-task (Z1) owns the instance MODEL only. `open` / `close` / `toggle`
197
+ * carry the correct method shape but defer their actual mount/visibility wiring
198
+ * to Z2 (events/lifecycle/mount). Today they drive the SAME global show/hide
199
+ * surface the console API uses for the default (single-panel) instance, so the
200
+ * default path keeps working end-to-end; Z2 replaces the bodies with
201
+ * per-instance event dispatch keyed by `instanceId`. `destroy()` deregisters
202
+ * the instance from the registry (model-level cleanup); Z2 extends it to also
203
+ * unmount the instance's Preact tree and remove its DOM root.
204
+ *
205
+ * @see RECONFIGURE_RULE for the same-prefix-different-config behaviour.
206
+ */
207
+ export interface PanelInstanceHandle {
208
+ /** Stable instance id — equal to the instance's `storagePrefix` (the registry key). */
209
+ readonly instanceId: string;
210
+ /** Show this instance's panel. Z2 wires per-instance mount/visibility; today drives the shared show surface. */
211
+ open(): void;
212
+ /** Hide this instance's panel. Z2 wires per-instance mount/visibility; today drives the shared hide surface. */
213
+ close(): void;
214
+ /** Toggle this instance's panel open/closed. Z2 wires per-instance mount/visibility. */
215
+ toggle(): void;
216
+ /**
217
+ * Deregister this instance. Removes it from the registry so its prefix can be
218
+ * re-configured with a fresh config (and so it stops being the default
219
+ * instance `getPanelConfig()` resolves to). Z2 extends this to also unmount
220
+ * the instance's Preact tree and remove its DOM root.
221
+ */
222
+ destroy(): void;
223
+ }
125
224
  /**
126
225
  * Default config — minimal stub values. Hosts MUST call `configurePanel(...)`
127
226
  * with real values to see useful behaviour.
128
227
  */
129
228
  export declare const DEFAULT_PANEL_CONFIG: PanelConfig;
130
229
  /**
131
- * Configure the panel runtime. Call exactly once per page lifecycle, before
132
- * the adapter is imported / mounted. Idempotent: calling twice with
133
- * structurally-equal values is a silent no-op; calling twice with structurally
134
- * different values throws so config conflicts surface immediately instead of
135
- * silently corrupting one of the two callers' assumptions.
136
- *
137
- * The re-init guard MUST use structural deep-equality, NOT referential
138
- * identity. The Astro host-adapter parses the inline JSON config on every
139
- * script run, including post view-transition reruns; that produces a
140
- * freshly-parsed object that is byte-for-byte identical to the previous call
141
- * but referentially distinct.
230
+ * Same-prefix-different-config rule (CHOSEN: reject-with-error).
231
+ *
232
+ * When `configurePanel` is called a second time with a prefix that is ALREADY
233
+ * registered but a structurally-DIFFERENT config, we throw. The alternative
234
+ * (deterministic-update) was rejected because:
235
+ *
236
+ * - PORTABLE-CONTRACT §1 pins `configurePanel` as one-shot per page lifecycle
237
+ * ("MUST NOT silently overwrite a previously-configured cluster mid-session").
238
+ * - The existing single-panel tests assert the throw, and the throw is what
239
+ * surfaces a genuine config-conflict bug (two callers fighting over one
240
+ * prefix) instead of letting the last writer silently win.
241
+ *
242
+ * Multi-instance does NOT need same-prefix mutation: a host that wants a second
243
+ * panel uses a DISTINCT `storagePrefix`, which registers an independent
244
+ * instance with no throw. Z4/Z5 must follow this rule — to re-configure a
245
+ * prefix, call `handle.destroy()` first, then `configurePanel` again.
246
+ *
247
+ * Exported (machine-discoverable) so Z4/Z5 can branch on the chosen rule
248
+ * without re-deriving it from the throw behaviour.
249
+ */
250
+ export declare const RECONFIGURE_RULE: "reject-with-error";
251
+ /**
252
+ * Z2 lifecycle seam. Z2 (events/lifecycle/mount) installs handlers here so the
253
+ * instance handle's open/close/toggle/destroy route to real per-instance
254
+ * mount + visibility behaviour. Z1 leaves it empty: the handle methods are
255
+ * no-ops until Z2 wires them, which is fine because the default single-panel
256
+ * path is driven by the existing console API / window events, not by handles.
257
+ *
258
+ * Exported (with the `__` internal prefix) so the lifecycle module (Z2) can
259
+ * register without reaching into private module scope.
260
+ */
261
+ export interface PanelLifecycleHooks {
262
+ /**
263
+ * Fired ONCE per newly-registered instance, immediately after
264
+ * `configurePanel` installs it (and AFTER the instance's post-configure
265
+ * hooks run). Z2 uses this to bind the instance's per-instance toggle-event
266
+ * listener at configure time — unlike `registerPostConfigureHook` (which
267
+ * adopts parked hooks for the FIRST instance only), this fires for EVERY
268
+ * `configurePanel` call, including the 2nd+ instance, so a non-default
269
+ * panel's `toggle-${storagePrefix}` channel is live the moment it is
270
+ * configured.
271
+ */
272
+ configured?: (instanceId: string) => void;
273
+ open?: (instanceId: string) => void;
274
+ close?: (instanceId: string) => void;
275
+ toggle?: (instanceId: string) => void;
276
+ destroy?: (instanceId: string) => void;
277
+ }
278
+ /**
279
+ * Z2 seam: install per-instance lifecycle handlers used by every instance
280
+ * handle's open/close/toggle/destroy plus the per-configure `configured` hook.
281
+ * Last call wins (Z2 owns its own idempotency). No-op-friendly: unset handlers
282
+ * leave the corresponding hook a no-op.
283
+ *
284
+ * Stored on the SHARED globalThis registry (not module scope) so the install
285
+ * side (`index.tsx`) and the fire side (`configurePanel`) observe the same
286
+ * hooks even when a Vite/Astro multi-entry build code-splits `panel-config`
287
+ * into two module instances — mirrors `pendingPostConfigureHooks`.
142
288
  */
143
- export declare function configurePanel(config: PanelConfig): void;
289
+ export declare function __setPanelLifecycleHooks(hooks: PanelLifecycleHooks): void;
290
+ /**
291
+ * Configure a panel instance. Call once per `storagePrefix` per page lifecycle,
292
+ * before that instance's adapter is imported / mounted. Returns the instance
293
+ * handle (`{ instanceId, open, close, toggle, destroy }`).
294
+ *
295
+ * Keying & multi-instance: the instance is keyed by `config.storagePrefix`.
296
+ * Distinct prefixes register independent instances (no throw); each derives its
297
+ * own storage keys, root id, modal classes, etc.
298
+ *
299
+ * Same-prefix idempotency: calling again with the same prefix and structurally-
300
+ * equal values is a no-op and returns the SAME handle. The re-init guard MUST
301
+ * use structural deep-equality, NOT referential identity — the Astro
302
+ * host-adapter parses the inline JSON config on every script run (including
303
+ * post view-transition reruns), producing a freshly-parsed object that is
304
+ * byte-for-byte identical to the previous call but referentially distinct.
305
+ *
306
+ * Same-prefix-different-config: REJECTS WITH AN ERROR (chosen rule — see
307
+ * `RECONFIGURE_RULE`). To re-configure a prefix, `destroy()` the existing
308
+ * handle first, then call `configurePanel` again.
309
+ *
310
+ * The most-recently-configured instance becomes the "default" instance that the
311
+ * no-arg `getPanelConfig()` resolves to, preserving the single-panel path.
312
+ */
313
+ export declare function configurePanel(config: PanelConfig): PanelInstanceHandle;
144
314
  /**
145
315
  * Register a callback to run once configurePanel has been called with the
146
316
  * host's config. Used by src/index.tsx to defer reapplyPersistedOverrides and
147
317
  * reapplyFromStorage until AFTER the host has supplied the correct storagePrefix.
148
318
  *
319
+ * Scope: this targets the DEFAULT (single-panel) instance — the historical
320
+ * single-panel contract. When no instance is configured yet, the hook is parked
321
+ * on a registry-level pending list and attached to the first instance to be
322
+ * configured. When the default instance already exists, the hook fires
323
+ * immediately so late registrants don't miss the trigger.
324
+ *
149
325
  * H2 fix for issue #111: module-init in index.tsx previously ran reapply
150
326
  * synchronously — before configurePanel — using DEFAULT_PANEL_CONFIG's prefix,
151
327
  * causing a default-prefix panel to mount and clobber host-prefix storage keys
152
328
  * on the first toggle when contaminated localStorage was present.
153
329
  *
154
330
  * Idempotent: if the same hook reference is registered twice, the second call
155
- * is a no-op. If configurePanel has already been called, the hook fires
156
- * immediately so late registrants don't miss the trigger.
331
+ * is a no-op.
157
332
  */
158
333
  export declare function registerPostConfigureHook(hook: () => void): void;
159
334
  /**
160
- * Read the active panel config. Returns the value passed to `configurePanel`
161
- * if one was supplied, else `DEFAULT_PANEL_CONFIG`.
335
+ * Read the active panel config. Returns the config of the default (most-
336
+ * recently-configured) instance, else `DEFAULT_PANEL_CONFIG` when no host has
337
+ * called `configurePanel`.
162
338
  */
163
339
  export declare function getPanelConfig(): PanelConfig;
164
340
  /**
165
- * Test-only: clear the singleton so unit tests can exercise different configs
166
- * in isolation.
341
+ * Resolve the registered config for a SPECIFIC instance by its `storagePrefix`
342
+ * (=== `instanceId`), or `null` when no such instance is registered.
343
+ *
344
+ * Z2 uses this so a non-default panel mounts/operates against ITS OWN config
345
+ * (tabs, schema, apply settings, custom `toggleEvent`) instead of the active
346
+ * default instance's config — distinct instances stay fully independent even
347
+ * while another prefix is the active default.
348
+ */
349
+ export declare function getPanelConfigByPrefix(prefix: string): PanelConfig | null;
350
+ /**
351
+ * Test-only: clear the entire instance registry so unit tests can exercise
352
+ * different configs in isolation. Resets the default pointer, every registered
353
+ * instance, parked presets, and parked pre-configure hooks.
167
354
  */
168
355
  export declare function __resetPanelConfigForTests(): void;
169
356
  export { resolvePrimaryColorCluster, resolveSecondaryColorClusterFromTabs, } from './cluster-config';
@@ -213,6 +400,35 @@ export declare function storageKey_density(cfg: PanelConfig): string;
213
400
  export declare function storageKey_visible(cfg: PanelConfig): string;
214
401
  /** DOM id of the root element the Preact panel tree mounts into. */
215
402
  export declare function panelRootId(cfg: PanelConfig): string;
403
+ /**
404
+ * Historical public toggle-event name. Hosts have shipped `window.dispatchEvent(
405
+ * new CustomEvent('toggle-design-token-panel'))` since the single-panel era, so
406
+ * the default instance MUST keep emitting/listening on this name regardless of
407
+ * its derived `toggle-${storagePrefix}` form.
408
+ */
409
+ export declare const DEFAULT_TOGGLE_EVENT = "toggle-design-token-panel";
410
+ /**
411
+ * Window-event name that toggles this instance's panel.
412
+ *
413
+ * - Default instance (prefix === `DEFAULT_STORAGE_PREFIX`): the historical
414
+ * `toggle-design-token-panel`. The `index.tsx` listener additionally binds
415
+ * the deprecated `toggle-color-tweak-panel` alias for this instance only.
416
+ * - Configured instance (any other prefix): `cfg.toggleEvent` when supplied,
417
+ * else `toggle-${storagePrefix}` — a per-instance channel so two panels do
418
+ * not cross-talk.
419
+ */
420
+ export declare function toggleEventName(cfg: PanelConfig): string;
421
+ /**
422
+ * Per-instance internal sync event name. `index.tsx` dispatches this on
423
+ * `window` after writing `localStorage[OPEN_KEY]`; the mounted `panel.tsx`
424
+ * listens for it and re-reads `OPEN_KEY`. Keyed by `storagePrefix` so a change
425
+ * to panel A's open state only pokes panel A's listener — two panels on one
426
+ * page stay fully independent (issue #354).
427
+ *
428
+ * Internal (double-underscore prefix) — NOT part of the public DOM contract;
429
+ * hosts must dispatch the public toggle event, never this one.
430
+ */
431
+ export declare function openStateChangedEventName(cfg: PanelConfig): string;
216
432
  /**
217
433
  * BEM-style modal class. Pass an empty `suffix` for the base block, or
218
434
  * `'--export'` / `'__title'` etc. for elements / modifiers.
@@ -253,6 +469,10 @@ export declare function resolveApplyRouting(cfg?: PanelConfig): ApplyRoutingMap;
253
469
  * non-empty map overwrites the previous one (no throw, unlike
254
470
  * `configurePanel`) — the dropdown source-of-truth is whichever bundle
255
471
  * landed last.
472
+ *
473
+ * Scope: targets the DEFAULT (active) instance — the historical single-panel
474
+ * contract. When no instance is configured yet, the presets are parked at the
475
+ * registry level and merged into the first instance to be configured.
256
476
  */
257
477
  export declare function setPanelColorPresets(presets: Record<string, ColorScheme>): void;
258
478
  //# sourceMappingURL=panel-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"panel-config.d.ts","sourceRoot":"","sources":["../../src/config/panel-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"panel-config.d.ts","sourceRoot":"","sources":["../../src/config/panel-config.ts"],"names":[],"mappings":"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"}
@@ -21,6 +21,7 @@
21
21
  * `close` event — and thus `onClose` — fires exactly once per dismissal.
22
22
  */
23
23
  import { type ColorTweakState, type TweakState } from './state/tweak-state';
24
+ import { type PanelConfig } from './config/panel-config';
24
25
  export interface ExportModalProps {
25
26
  onClose: () => void;
26
27
  /** Full unified tweak state — the modal serializes all four categories. */
@@ -28,6 +29,13 @@ export interface ExportModalProps {
28
29
  /** Color baseline used for diff-only output. Optional: callers without DOM
29
30
  * access (tests) can omit and we'll treat the entire color block as changed. */
30
31
  colorDefaults?: ColorTweakState;
32
+ /**
33
+ * The mounted panel instance's config (multi-instance, #357). When supplied,
34
+ * the modal derives its filename hint + modal classes + title id from THIS
35
+ * instance rather than the active default instance. Omitted (e.g. a direct
36
+ * test render) → `getPanelConfig()`, preserving the single-panel path.
37
+ */
38
+ instanceConfig?: PanelConfig;
31
39
  }
32
- export declare function ExportModal({ onClose, state, colorDefaults }: ExportModalProps): import("preact").JSX.Element;
40
+ export declare function ExportModal({ onClose, state, colorDefaults, instanceConfig }: ExportModalProps): import("preact").JSX.Element;
33
41
  //# sourceMappingURL=export-modal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"export-modal.d.ts","sourceRoot":"","sources":["../src/export-modal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,UAAU,EAEhB,MAAM,qBAAqB,CAAC;AAI7B,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,2EAA2E;IAC3E,KAAK,EAAE,UAAU,CAAC;IAClB;qFACiF;IACjF,aAAa,CAAC,EAAE,eAAe,CAAC;CACjC;AAgBD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,gBAAgB,gCAoL9E"}
1
+ {"version":3,"file":"export-modal.d.ts","sourceRoot":"","sources":["../src/export-modal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,UAAU,EAEhB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,2EAA2E;IAC3E,KAAK,EAAE,UAAU,CAAC;IAClB;qFACiF;IACjF,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,WAAW,CAAC;CAC9B;AAgBD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,EAAE,gBAAgB,gCA6L9F"}
@@ -21,6 +21,7 @@
21
21
  * `close` event — and thus `onClose` — fires exactly once per dismissal.
22
22
  */
23
23
  import type { ColorTweakState, TweakState } from './state/tweak-state';
24
+ import { type PanelConfig } from './config/panel-config';
24
25
  export interface ImportModalProps {
25
26
  onClose: () => void;
26
27
  /** Called with the parsed state when the user hits "Load". The caller is
@@ -28,6 +29,13 @@ export interface ImportModalProps {
28
29
  onLoad: (state: TweakState) => void;
29
30
  /** Color baseline filled in for fields absent from the payload. */
30
31
  colorDefaults: ColorTweakState;
32
+ /**
33
+ * The mounted panel instance's config (multi-instance, #357). When supplied,
34
+ * the modal derives its modal classes + title id from THIS instance rather
35
+ * than the active default instance. Omitted (e.g. a direct test render) →
36
+ * `getPanelConfig()`, preserving the single-panel path.
37
+ */
38
+ instanceConfig?: PanelConfig;
31
39
  }
32
- export declare function ImportModal({ onClose, onLoad, colorDefaults }: ImportModalProps): import("preact").JSX.Element;
40
+ export declare function ImportModal({ onClose, onLoad, colorDefaults, instanceConfig }: ImportModalProps): import("preact").JSX.Element;
33
41
  //# sourceMappingURL=import-modal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"import-modal.d.ts","sourceRoot":"","sources":["../src/import-modal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAQH,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAIvE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;oEACgE;IAChE,MAAM,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACpC,mEAAmE;IACnE,aAAa,EAAE,eAAe,CAAC;CAChC;AAOD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,gBAAgB,gCA+N/E"}
1
+ {"version":3,"file":"import-modal.d.ts","sourceRoot":"","sources":["../src/import-modal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAQH,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAA8B,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGrF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;oEACgE;IAChE,MAAM,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACpC,mEAAmE;IACnE,aAAa,EAAE,eAAe,CAAC;IAC/B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,WAAW,CAAC;CAC9B;AAOD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,EAAE,gBAAgB,gCA2O/F"}
package/dist/index.d.ts CHANGED
@@ -35,9 +35,8 @@
35
35
  */
36
36
  import './styles/panel.css';
37
37
  import { type PanelConfig } from './config/panel-config';
38
- export declare const __OPEN_STATE_CHANGED_EVENT_FOR_TEST = "__zdtp:open-state-changed";
39
38
  export { configurePanel, setPanelColorPresets } from './config/panel-config';
40
- export type { PanelConfig } from './config/panel-config';
39
+ export type { PanelConfig, PanelInstanceHandle, ApplySink } from './config/panel-config';
41
40
  /**
42
41
  * Internal-test-only accessor that returns this panel-module bundle's view of
43
42
  * the active panel config singleton. Paired with the Astro host adapter's
@@ -76,6 +75,16 @@ export declare function toggleDesignPanel(): void;
76
75
  * instead, same as before this helper existed).
77
76
  */
78
77
  export declare function reapplyPersistedOverrides(): void;
78
+ /**
79
+ * Test-only: drain EVERY instance's window-event listeners and clear the
80
+ * bindings map. Unlike `delete window.__zudoDesignTokenPanelInstanceBindings`,
81
+ * this actively removes the real `addEventListener` registrations — dropping
82
+ * the map alone would orphan live listeners that then leak across tests (a
83
+ * stale listener from a previous test re-mounts a panel on the next dispatch).
84
+ *
85
+ * Exported with the `__` internal prefix; not part of the public API.
86
+ */
87
+ export declare function __resetInstanceBindingsForTests(): void;
79
88
  /**
80
89
  * Framework-agnostic lifecycle hook adapter. A host that owns its own
81
90
  * client-side navigation lifecycle (zfb, custom router, etc.) implements
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AASH,OAAO,oBAAoB,CAAC;AAc5B,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,uBAAuB,CAAC;AAqD/B,eAAO,MAAM,mCAAmC,8BAA2B,CAAC;AAkK5E,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,IAAI,WAAW,CAElD;AAQD,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAM9D,OAAO,EAAE,iCAAiC,EAAE,MAAM,qBAAqB,CAAC;AAGxE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGpE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGjE,YAAY,EACV,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,SAAS,EACT,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAO7B,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,wBAAgB,oBAAoB,IAAI,IAAI,CAoB3C;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAY3C;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAWxC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAQhD;AA8HD;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uFAAuF;IACvF,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;IACpD,2FAA2F;IAC3F,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;CACnD;AA4GD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAU1E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AASH,OAAO,oBAAoB,CAAC;AAc5B,OAAO,EAUL,KAAK,WAAW,EACjB,MAAM,uBAAuB,CAAC;AAiO/B,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEzF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,IAAI,WAAW,CAElD;AAQD,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAM9D,OAAO,EAAE,iCAAiC,EAAE,MAAM,qBAAqB,CAAC;AAGxE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGpE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGjE,YAAY,EACV,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,SAAS,EACT,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAO7B,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA2DrD,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAQhD;AA8LD;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,IAAI,IAAI,CAMtD;AAyED;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uFAAuF;IACvF,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;IACpD,2FAA2F;IAC3F,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;CACnD;AA4GD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAU1E"}