@takazudo/zdtp 0.4.5 → 0.4.7

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,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.7
4
+
5
+ ### Fixed
6
+
7
+ - fix(server): coalesce same-file token groups in createApplyHandler ([#527](https://github.com/Takazudo/zudo-design-token-panel/pull/527)) (1d84c94)
8
+
9
+ ### Other Changes
10
+
11
+ - chore(deps): resolve 19 pnpm audit security advisories ([#525](https://github.com/Takazudo/zudo-design-token-panel/pull/525)) (80c9a0e)
12
+
13
+ ## 0.4.6
14
+
15
+ ### Features
16
+
17
+ - Notes tab — host-configurable token notes as the panel's top page ([#515](https://github.com/Takazudo/zudo-design-token-panel/issues/515)) (4169a05)
18
+ - Palette tab: groups collapsed by default with boxed toggle headers ([#517](https://github.com/Takazudo/zudo-design-token-panel/issues/517)) (2ff5a1e)
19
+ - Container-query responsive header & tabs at narrow panel widths, plus "zdtp" panel title + square corners ([#518](https://github.com/Takazudo/zudo-design-token-panel/issues/518)) (25dff1a)
20
+ - Click-to-cycle unit suffix on value inputs ([#519](https://github.com/Takazudo/zudo-design-token-panel/issues/519)) (b05581d)
21
+ - "?" help tooltips for Literal and Per-mode rows in the Color tab ([#520](https://github.com/Takazudo/zudo-design-token-panel/issues/520)) (c85fd69)
22
+ - `zdtp.show()` — fixed-name global open API ([#523](https://github.com/Takazudo/zudo-design-token-panel/issues/523)) (9b3c636)
23
+
24
+ ### Fixed
25
+
26
+ - Tooltip repositions correctly after panel resize (ResizeObserver initial-delivery fix) ([#516](https://github.com/Takazudo/zudo-design-token-panel/issues/516)) (d10fe16)
27
+ - Closed a C0-control URL-scheme bypass in the notes-tab HTML sanitizer ([#515](https://github.com/Takazudo/zudo-design-token-panel/issues/515)) (19f7147)
28
+ - Corrected kebab-close dead zone + title truncation in the responsive header ([#518](https://github.com/Takazudo/zudo-design-token-panel/issues/518)) (bfc4b81)
29
+ - `window.zdtp` guards against a null instance and clarifies multi-instance behavior ([#523](https://github.com/Takazudo/zudo-design-token-panel/issues/523)) (bcc71aa)
30
+
31
+ ### Other Changes
32
+
33
+ - docs: notes-tab demo in doc-site manifest; help-icon resize-pin trade-off + sanitizer intent documented (82cf7d8, fe1b477)
34
+ - test: VRT baselines re-recorded for zdtp title + square corners; broad coverage added for notes tab, help icons, unit cycling
35
+ - chore: removed consumed `_temp-resource/` prototype scaffold (ccbd18a)
36
+
3
37
  ## 0.4.5
4
38
 
5
39
  ### Features
package/README.md CHANGED
@@ -53,6 +53,8 @@ The package builds against Preact (declared as a `peerDependency`) and ships its
53
53
 
54
54
  > Visual: a screenshot or short capture would go here. Skipped in the v1 README — a placeholder is worse than nothing. See the external example repos linked in §15 for live demos.
55
55
 
56
+ **Browser floor:** the panel's own header/tabbar chrome adapts to the panel's *width* (not the viewport) via CSS container queries, which are Baseline 2023 (Safari 16+). The panel is a developer tool used on evergreen browsers, so older browsers simply keep the wide-layout chrome with no JS fallback.
57
+
56
58
  ---
57
59
 
58
60
  ## 2. Install
@@ -326,6 +328,22 @@ That is the entire integration. `<DesignTokenPanelHost>` emits a JSON `<script>`
326
328
  window.myapp.toggleDesignPanel();
327
329
  ```
328
330
 
331
+ Or use the fixed-name `zdtp` global — no need to remember your own
332
+ `consoleNamespace`:
333
+
334
+ ```js
335
+ // In the browser devtools console — works regardless of consoleNamespace
336
+ zdtp.show();
337
+ zdtp.hide();
338
+ zdtp.toggle();
339
+ ```
340
+
341
+ `zdtp.show()` / `hide()` / `toggle()` are console sugar for the exact same
342
+ open/close verbs `window.myapp.*` exposes (see §10 for the full contract) —
343
+ `window.myapp.*` keeps working unchanged. On an Astro page, `zdtp.*` is
344
+ available as soon as the host-adapter script has run, even before the panel
345
+ bundle itself has loaded.
346
+
329
347
  Or wire a hidden keyboard shortcut / dev-only button to call the same helper.
330
348
 
331
349
  ### 4.1.4 Stylesheet (self-injected — no consumer import required)
@@ -472,6 +490,13 @@ export interface PanelInstanceHandle {
472
490
  }
473
491
  ```
474
492
 
493
+ `open()` / `close()` / `toggle()` are the same primitives both
494
+ `window.myapp.*` (§10) and the fixed-name `window.zdtp.*` global (§10) wrap
495
+ for the **default** (most-recently-configured) instance. On a page with more
496
+ than one instance, call `handle.open()` / `.close()` / `.toggle()` directly
497
+ on the specific instance's handle — `window.zdtp.*` always targets the
498
+ default instance only.
499
+
475
500
  ### 5.3 Field summary
476
501
 
477
502
  | Field | Type | Purpose |
@@ -1000,6 +1025,27 @@ window.myapp.disableAutoload(); // disarm owner-mode; unmounts the panel
1000
1025
 
1001
1026
  All helpers are **async** — the first call lazy-imports the panel module. Subsequent calls share the memoised module promise and resolve synchronously after the first import completes.
1002
1027
 
1028
+ ### Fixed-name global: `window.zdtp`
1029
+
1030
+ `consoleNamespace` is a **required** field on `PanelConfig` — every consumer picks its own value, so `window[consoleNamespace].*` needs the host's chosen namespace before you can open the panel from the console. `window.zdtp` is an additive, fixed-name alias that needs none:
1031
+
1032
+ ```ts
1033
+ zdtp.show(); // open the panel (lazy-loads the bundle on first call, same as showDesignPanel())
1034
+ zdtp.hide(); // close the panel
1035
+ zdtp.toggle(); // toggle open/closed
1036
+ ```
1037
+
1038
+ - **`show` / `hide` / `toggle` only.** There is no `zdtp.enableAutoload()` — owner-autoload (§10.1) stays on `window[consoleNamespace].*` and the package-root `enableAutoload()` / `disableAutoload()` exports.
1039
+ - **`window[consoleNamespace].*` is unchanged** — `window.zdtp` is sugar layered on top of it, not a replacement. Both stay available side by side.
1040
+ - **Targets the default instance**, exactly like the package-root `showDesignTokenPanel()` / `hideDesignTokenPanel()` / `toggleDesignPanel()` exports and `window[consoleNamespace].*` itself. On an Astro host specifically, the alias binds to whichever instance's adapter script installs it first, rather than re-resolving "the current default" on every call — see `PORTABLE-CONTRACT.md` §6.5 for the exact per-install-site rule. For a page with more than one panel instance, use `configurePanel(cfg)`'s returned handle (§5.2) instead — it is unambiguous regardless of install order.
1041
+ - **Available on both integration paths:**
1042
+ - Non-Astro hosts get it as soon as `@takazudo/zdtp`'s package-root module has loaded (it installs the alias at module init).
1043
+ - Astro hosts get it as soon as the host-adapter `<script>` has run — **before** the panel bundle itself has loaded. The first `zdtp.*` call lazy-imports the bundle, exactly like `window[consoleNamespace].*`.
1044
+ - **Never clobbers a host-defined `window.zdtp`.** If your page already has its own `window.zdtp` for something unrelated, the package leaves it alone and logs a `console.warn` instead of overwriting it — including the edge case of choosing `consoleNamespace: 'zdtp'` yourself.
1045
+ - **Auto-remember applies too** — `zdtp.show()` arms the `:autoload` flag exactly like `showDesignPanel()` (§10.1's Auto-remember footgun note applies here as well).
1046
+
1047
+ See `PORTABLE-CONTRACT.md` §6.5 for the full install-site and no-clobber/no-double-install contract.
1048
+
1003
1049
  ### Backward-compatible: the on-demand flow is unchanged
1004
1050
 
1005
1051
  The pre-existing on-demand usage — calling `window.<consoleNamespace>.showDesignPanel()` / `hideDesignPanel()` / `toggleDesignPanel()` to lazy-import and initialize the panel — is **unchanged and fully supported**. Owner-autoload (§10.1) is an opt-in layered on top, not a replacement. If you never call `enableAutoload()`, the panel behaves exactly as it always did: nothing loads for any visitor until the first console call.
@@ -1,102 +1,115 @@
1
- import { c as w, g as u, a as g, b as y, d as P, e as b, f as _ } from "../panel-config-CipeKMTz.js";
2
- import { g as d, Z as A } from "../tweak-state-xt-tSQ_t.js";
3
- import { s as k, l as I, a as c, c as E, b as C } from "../autoload-state-DF7TsTgY.js";
4
- const i = "tokenpanel-config";
5
- function S() {
1
+ import { c as h, g as u, a as g, b as y, d as P, e as b, f as _, i as A } from "../panel-config-Bw7D-25C.js";
2
+ import { g as c, Z as k } from "../tweak-state-CD1y56zR.js";
3
+ import { s as I, l as E, a as d, c as C, b as S } from "../autoload-state-D26ML6sW.js";
4
+ const r = "tokenpanel-config";
5
+ function T() {
6
6
  if (typeof document > "u")
7
7
  throw new Error(
8
8
  "[design-token-panel] host-adapter loaded without a document; expected to run in a browser context."
9
9
  );
10
- const n = document.getElementById(i);
11
- if (!n)
10
+ const e = document.getElementById(r);
11
+ if (!e)
12
12
  throw new Error(
13
- `[design-token-panel] Inline config script #${i} not found. Ensure <DesignTokenPanelHost config={...} /> is rendered on this page before the host script runs.`
13
+ `[design-token-panel] Inline config script #${r} not found. Ensure <DesignTokenPanelHost config={...} /> is rendered on this page before the host script runs.`
14
14
  );
15
- const a = n.textContent ?? "";
16
- let e;
15
+ const t = e.textContent ?? "";
16
+ let n;
17
17
  try {
18
- e = JSON.parse(a);
18
+ n = JSON.parse(t);
19
19
  } catch (o) {
20
20
  throw new Error(
21
- `[design-token-panel] Failed to parse inline config from #${i}: ${o.message}`
21
+ `[design-token-panel] Failed to parse inline config from #${r}: ${o.message}`
22
22
  );
23
23
  }
24
- return _(e), e;
24
+ return _(n), n;
25
25
  }
26
- function T(n) {
27
- return n.__zudoDesignTokenPanelAdapter || (n.__zudoDesignTokenPanelAdapter = {}), n.__zudoDesignTokenPanelAdapter;
26
+ function V(e) {
27
+ return e.__zudoDesignTokenPanelAdapter || (e.__zudoDesignTokenPanelAdapter = {}), e.__zudoDesignTokenPanelAdapter;
28
28
  }
29
- function V(n, a) {
30
- const e = T(n);
31
- let o = e[a];
32
- return o || (o = { bound: !1, modulePromise: null }, e[a] = o), o;
29
+ function v(e, t) {
30
+ const n = V(e);
31
+ let o = n[t];
32
+ return o || (o = { bound: !1, modulePromise: null }, n[t] = o), o;
33
33
  }
34
- function v(n) {
34
+ function D(e) {
35
35
  try {
36
- return window.localStorage.getItem(n) === "1";
36
+ return window.localStorage.getItem(e) === "1";
37
37
  } catch {
38
38
  return !1;
39
39
  }
40
40
  }
41
- function D(n, a, e) {
41
+ function K(e, t, n) {
42
42
  try {
43
43
  const o = window.localStorage;
44
- return o.getItem(e) !== null || o.getItem(a) !== null || o.getItem(n) !== null;
44
+ return o.getItem(n) !== null || o.getItem(t) !== null || o.getItem(e) !== null;
45
45
  } catch {
46
46
  return !1;
47
47
  }
48
48
  }
49
- async function l(n) {
50
- return n.modulePromise === null && (n.modulePromise = import("@takazudo/zdtp").then((a) => {
49
+ async function i(e) {
50
+ return e.modulePromise === null && (e.modulePromise = import("@takazudo/zdtp").then((t) => {
51
51
  try {
52
- const e = u(), o = a.__panelConfigForTest();
53
- e !== o && console.warn(
52
+ const n = u(), o = t.__panelConfigForTest();
53
+ n !== o && console.warn(
54
54
  "[design-token-panel] Singleton-sharing check failed: the host adapter and the panel module observed different PanelConfig singletons. This indicates the package's `config/panel-config` module is no longer code-split into a single shared chunk. The panel may behave correctly today, but storage keys / namespaces / branding could diverge between the two surfaces in future bundles."
55
55
  );
56
- } catch (e) {
56
+ } catch (n) {
57
57
  console.warn(
58
- "[design-token-panel] Singleton-sharing check could not run (likely an older dist without the __panelConfigForTest accessor): " + e.message
58
+ "[design-token-panel] Singleton-sharing check could not run (likely an older dist without the __panelConfigForTest accessor): " + n.message
59
59
  );
60
60
  }
61
- return a;
62
- })), n.modulePromise;
61
+ return t;
62
+ })), e.modulePromise;
63
63
  }
64
- function K(n, a, e, o, t) {
65
- const s = n[a] ?? {};
66
- s.showDesignPanel = async () => {
67
- c(t, !0), await l(e), o.open();
68
- }, s.hideDesignPanel = async () => {
69
- await l(e), o.close();
70
- }, s.toggleDesignPanel = async () => {
71
- await l(e), o.toggle();
72
- let r = !1;
64
+ function M(e, t, n, o, a) {
65
+ const l = e[t] ?? {};
66
+ l.showDesignPanel = async () => {
67
+ d(a, !0), await i(n), o.open();
68
+ }, l.hideDesignPanel = async () => {
69
+ await i(n), o.close();
70
+ }, l.toggleDesignPanel = async () => {
71
+ await i(n), o.toggle();
72
+ let s = !1;
73
73
  try {
74
- r = window.localStorage.getItem(d(t)) === "1";
74
+ s = window.localStorage.getItem(c(a)) === "1";
75
75
  } catch {
76
76
  }
77
- r && c(t, !0);
78
- }, s.enableAutoload = async () => {
79
- (await l(e)).enableAutoload(t);
80
- }, s.disableAutoload = async () => {
81
- if (e.modulePromise !== null) {
82
- (await l(e)).disableAutoload(t);
77
+ s && d(a, !0);
78
+ }, l.enableAutoload = async () => {
79
+ (await i(n)).enableAutoload(a);
80
+ }, l.disableAutoload = async () => {
81
+ if (n.modulePromise !== null) {
82
+ (await i(n)).disableAutoload(a);
83
83
  return;
84
84
  }
85
- E(t), C(!1, t);
85
+ C(a), S(!1, a);
86
86
  try {
87
- window.localStorage.setItem(g(t), "0");
87
+ window.localStorage.setItem(g(a), "0");
88
88
  } catch {
89
89
  }
90
90
  try {
91
- window.localStorage.removeItem(d(t));
91
+ window.localStorage.removeItem(c(a));
92
92
  } catch {
93
93
  }
94
- }, n[a] = s;
94
+ }, e[t] = l;
95
+ }
96
+ function O(e, t) {
97
+ A({
98
+ show: async () => {
99
+ await i(e), t.open();
100
+ },
101
+ hide: async () => {
102
+ await i(e), t.close();
103
+ },
104
+ toggle: async () => {
105
+ await i(e), t.toggle();
106
+ }
107
+ });
95
108
  }
96
109
  (function() {
97
- const a = S(), e = a.legacyIdRenameMap ? a : { ...a, legacyIdRenameMap: { ...A } }, o = w(e), t = u(), s = window, r = V(s, t.storagePrefix);
98
- if (K(s, t.consoleNamespace, r, o, t), r.bound) return;
99
- r.bound = !0;
100
- const f = g(t), m = y(t), p = P(t), h = b(t);
101
- (v(f) || D(m, p, h) || k(t) || I(t)) && l(r);
110
+ const t = T(), n = t.legacyIdRenameMap ? t : { ...t, legacyIdRenameMap: { ...k } }, o = h(n), a = u(), l = window, s = v(l, a.storagePrefix);
111
+ if (M(l, a.consoleNamespace, s, o, a), O(s, o), s.bound) return;
112
+ s.bound = !0;
113
+ const p = g(a), f = y(a), m = P(a), w = b(a);
114
+ (D(p) || K(f, m, w) || I(a) || E(a)) && i(s);
102
115
  })();
@@ -1,4 +1,4 @@
1
- import { s as t } from "../panel-config-CipeKMTz.js";
1
+ import { s as t } from "../panel-config-Bw7D-25C.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 a, k as o } from "./panel-config-CipeKMTz.js";
1
+ import { g as a, l as o } from "./panel-config-Bw7D-25C.js";
2
2
  function n(e = a()) {
3
3
  return `${e.storagePrefix}-elpath-enabled`;
4
4
  }
@@ -2,7 +2,7 @@
2
2
  import { realpathSync as E } from "node:fs";
3
3
  import { createServer as H } from "node:http";
4
4
  import { resolve as p } from "node:path";
5
- import { l as $, c as x } from "../load-routing-LJ72261l.js";
5
+ import { l as $, c as x } from "../load-routing-D4H2VOl5.js";
6
6
  function g(o, t) {
7
7
  return typeof o != "string" || o.length === 0 || t.length === 0 ? !1 : t.includes(o);
8
8
  }
@@ -490,6 +490,38 @@ export declare function openStateChangedEventName(cfg: PanelConfig): string;
490
490
  export declare function modalClass(cfg: PanelConfig, suffix: string): string;
491
491
  /** Default download filename for export. */
492
492
  export declare function exportFilename(cfg: PanelConfig): string;
493
+ /** Shape of the fixed-name global alias installed at `window.zdtp`. */
494
+ export interface ZdtpGlobalApi {
495
+ show: () => void | Promise<void>;
496
+ hide: () => void | Promise<void>;
497
+ toggle: () => void | Promise<void>;
498
+ }
499
+ /**
500
+ * Install `window.zdtp = { show, hide, toggle }`, the fixed-name console
501
+ * sugar for the common single-panel case (issue #523).
502
+ *
503
+ * Guard rules:
504
+ * - A pre-existing `window.zdtp` WITHOUT this package's marker is assumed to
505
+ * be host-defined — never overwritten. Logs a `console.warn` so the host
506
+ * can see why `zdtp.show()` did not appear.
507
+ * - A pre-existing `window.zdtp` WITH the marker means this package already
508
+ * installed the alias (from the other call site, or an earlier run of this
509
+ * same one). First install wins — the call is a silent no-op. In the Astro
510
+ * flow this manifests as "the adapter wins": its bootstrap script always
511
+ * runs (and installs the alias) before the panel module's lazy dynamic
512
+ * import can resolve and reach the package-root install site.
513
+ *
514
+ * `show` / `hide` / `toggle` are caller-supplied closures, so which instance
515
+ * they target is up to the caller — the package-root install site (below,
516
+ * `index.tsx`) wraps `showDesignTokenPanel()` etc., which re-resolve
517
+ * `getPanelConfig()` (the CURRENT default instance) on every call; the Astro
518
+ * host-adapter install site instead binds to the specific `PanelInstanceHandle`
519
+ * captured at its own install time, which does NOT track a later change of
520
+ * default (see PORTABLE-CONTRACT.md §6.5 for the full nuance). Either way,
521
+ * for a multi-instance page use `configurePanel(cfg).open()` etc. on the
522
+ * specific instance's own handle instead of relying on this alias.
523
+ */
524
+ export declare function installZdtpGlobalAlias(api: ZdtpGlobalApi): void;
493
525
  /**
494
526
  * Runtime validation at the host-adapter trust boundary. The Astro inline
495
527
  * `<script type="application/json">` payload is untrusted-by-the-types:
@@ -0,0 +1,26 @@
1
+ /**
2
+ * ActionsMenuPopover — narrow-panel replacement for the header action links
3
+ * (Export / Load from JSON… / Apply / Reset), collapsed behind the kebab
4
+ * trigger below the panel's <480px container-query breakpoint (#518).
5
+ *
6
+ * A PLAIN popover of ordinary action RoleButtons, NOT an ARIA menu:
7
+ * role="menu"/menuitem demands arrow-key navigation and focus management,
8
+ * and RoleButton hardcodes role="button" — so this follows the existing
9
+ * gear-settings popover's dialog + outside-click/Escape wiring instead
10
+ * (usePopoverClose, shared with highlight/highlight-settings-popover.tsx).
11
+ */
12
+ import type { JSX } from 'preact';
13
+ export interface ActionsMenuAction {
14
+ label: string;
15
+ onSelect: () => void;
16
+ }
17
+ interface ActionsMenuPopoverProps {
18
+ /** The kebab trigger element — excluded from the outside-click close so its
19
+ * own click-to-toggle isn't raced by the popover's pointerdown listener
20
+ * (mirrors the gear button / HighlightSettingsPopover pairing). */
21
+ anchorRef: React.RefObject<HTMLElement | null>;
22
+ actions: readonly ActionsMenuAction[];
23
+ onClose: () => void;
24
+ }
25
+ export declare function ActionsMenuPopover({ anchorRef, actions, onClose, }: ActionsMenuPopoverProps): JSX.Element;
26
+ export {};
@@ -0,0 +1,43 @@
1
+ /**
2
+ * HelpIcon — small round "?" badge that explains a nearby control via the
3
+ * shared `.tokenpanel-tooltip--help` variant (issue #520).
4
+ *
5
+ * Chrome-button policy (CLAUDE.md): implemented as
6
+ * `<div role="button" tabIndex={0}>` with explicit Enter/Space handling —
7
+ * never a native `<button>`.
8
+ *
9
+ * Behavior:
10
+ * - Hover / focus shows the help tooltip transiently, same as any other
11
+ * `useTooltip` trigger.
12
+ * - Click (or Enter/Space) PINS the tooltip open — touch devices have no
13
+ * hover, so a tap must be able to reveal and hold the tip. A second
14
+ * activation, or pressing Escape anywhere on the page, unpins it.
15
+ *
16
+ * Callers place this as a SIBLING of the control it explains (e.g. after a
17
+ * `<select>`, or after a `<label>` wrapping a checkbox) — never nested
18
+ * inside a `<label>`, where a click would also toggle the label's own
19
+ * control.
20
+ *
21
+ * Known trade-off: `tooltip.tsx` renders a single shared tooltip DOM node,
22
+ * so pinning icon A then hovering/pinning icon B silently replaces A's
23
+ * visible content with B's — A's `pinned`/`is-pinned` state persists until
24
+ * A is next clicked or Escape is pressed, even though its tooltip is no
25
+ * longer the one on screen. Acceptable for this panel's single-tooltip
26
+ * architecture; not worth a cross-instance pin registry for a "?" hint.
27
+ * The same applies to a panel/window resize: `tooltip.tsx` hides the shared
28
+ * tooltip on resize (its ResizeObserver + window-resize handlers), but this
29
+ * component's local `pinned` state only clears on click/Escape — so after a
30
+ * resize the icon may briefly keep `is-pinned`/`aria-pressed` with no tooltip
31
+ * visible until the next activation. Same accepted single-tooltip trade-off.
32
+ */
33
+ import type { JSX } from 'preact';
34
+ export declare const LITERAL_HELP_TEXT = "Literal sets a fixed color just for this token \u2014 it won't update if you edit a palette/ramp swatch later. Pick a ramp option to keep it linked live.";
35
+ export declare const PER_MODE_HELP_TEXT = "Per-mode gives this token two colors \u2014 one for light mode, one for dark. The browser picks the right one automatically via CSS light-dark().";
36
+ export interface HelpIconProps {
37
+ /** The help text shown in the tooltip (wrapped, multi-line). */
38
+ text: string;
39
+ /** Accessible name for the icon itself (e.g. "Literal help", "Surface per-mode help"). */
40
+ ariaLabel: string;
41
+ }
42
+ export declare function HelpIcon({ text, ariaLabel }: HelpIconProps): JSX.Element;
43
+ export default HelpIcon;
@@ -16,6 +16,13 @@
16
16
  * <div {...tooltipProps}>...</div>
17
17
  */
18
18
  import type { ComponentChildren, JSX } from 'preact';
19
+ /**
20
+ * Opt-in tooltip presentation variant. `'help'` applies the wrapped,
21
+ * bounded-width `.tokenpanel-tooltip--help` class (see panel.css) instead of
22
+ * the default single-line `nowrap` tooltip — used by `controls/help-icon.tsx`
23
+ * for the multi-sentence Literal / Per-mode explainer tips.
24
+ */
25
+ export type TooltipVariant = 'help';
19
26
  interface TooltipProviderProps {
20
27
  children: ComponentChildren;
21
28
  }
@@ -27,17 +34,28 @@ interface TooltipProviderProps {
27
34
  * tooltip globally.
28
35
  */
29
36
  export declare function TooltipProvider({ children }: TooltipProviderProps): JSX.Element;
37
+ export interface UseTooltipOptions {
38
+ /** Opt into a presentation variant — see `TooltipVariant` above. Omit for
39
+ * the default single-line `nowrap` tooltip. */
40
+ variant?: TooltipVariant;
41
+ }
30
42
  /**
31
43
  * Returns event handler props to spread onto the tooltip trigger element.
32
44
  *
33
45
  * @param text - The full text to show in the tooltip.
46
+ * @param opts - Optional presentation variant (see `UseTooltipOptions`).
34
47
  * @returns An object of `onMouseEnter`, `onMouseLeave`, `onFocusIn`, `onFocusOut`
35
- * handlers to spread onto the trigger element.
48
+ * handlers to spread onto the trigger element, plus imperative
49
+ * `show`/`hide` escape hatches for callers that need to
50
+ * show/keep-open the tooltip outside of a raw hover/focus event
51
+ * (e.g. `controls/help-icon.tsx`'s click-to-pin behavior).
36
52
  */
37
- export declare function useTooltip(text: string): {
53
+ export declare function useTooltip(text: string, opts?: UseTooltipOptions): {
38
54
  onMouseEnter: JSX.MouseEventHandler<HTMLElement>;
39
55
  onMouseLeave: JSX.MouseEventHandler<HTMLElement>;
40
56
  onFocusIn: JSX.FocusEventHandler<HTMLElement>;
41
57
  onFocusOut: JSX.FocusEventHandler<HTMLElement>;
58
+ show: (el: HTMLElement) => void;
59
+ hide: (el: HTMLElement) => void;
42
60
  };
43
61
  export {};
package/dist/index.d.ts CHANGED
@@ -56,7 +56,7 @@ export type { ColorClusterConfig } from './state/tweak-state';
56
56
  export { ZDTP_LEGACY_TYPOGRAPHY_RENAME_MAP } from './state/tweak-state';
57
57
  export type { ColorScheme, ColorRef } from './config/color-schemes';
58
58
  export type { TokenManifest, TokenDef } from './tokens/manifest';
59
- export type { TierValueKind, PillSpec, TierItem, TierConfig, TabConfig, ColorClusterExtras, } from './tokens/tier-model';
59
+ export type { TierValueKind, PillSpec, TierItem, TierConfig, TabConfig, ColorClusterExtras, NotesExtras, } from './tokens/tier-model';
60
60
  export { isLengthKind, isNumberKind, isSelectKind, isTextKind, isColorKind, isCursorKind, isContentKind, isMaskImageKind, } from './tokens/tier-model';
61
61
  export type { TweakState } from './state/tweak-state';
62
62
  export { emptyOverrides } from './state/tweak-state';