@takazudo/zdtp 0.4.4 → 0.4.6
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 +46 -0
- package/README.md +159 -12
- package/dist/apply/apply-token-overrides.d.ts +139 -32
- package/dist/astro/host-adapter.js +71 -58
- package/dist/astro/index.js +1 -1
- package/dist/{autoload-state-CmhI7q9j.js → autoload-state-D26ML6sW.js} +1 -1
- package/dist/bin/server.js +116 -112
- package/dist/config/panel-config.d.ts +68 -1
- package/dist/controls/actions-menu-popover.d.ts +26 -0
- package/dist/controls/help-icon.d.ts +43 -0
- package/dist/controls/tooltip.d.ts +20 -2
- package/dist/export-modal.d.ts +5 -3
- package/dist/import-modal.d.ts +9 -9
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3383 -3012
- package/dist/load-routing-LJ72261l.js +421 -0
- package/dist/{panel-config-CXTCcYQs.js → panel-config-Bw7D-25C.js} +381 -271
- package/dist/server/create-apply-handler.d.ts +6 -0
- package/dist/server/index.js +1 -1
- package/dist/state/tweak-state.d.ts +137 -14
- package/dist/tabs/notes-tab.d.ts +25 -0
- package/dist/testing.js +7 -7
- package/dist/tokens/manifest.d.ts +8 -0
- package/dist/tokens/tier-model.d.ts +36 -0
- package/dist/tweak-state-CD1y56zR.js +1958 -0
- package/dist/utils/design-token-serde.d.ts +20 -12
- package/dist/utils/sanitize-html.d.ts +27 -0
- package/dist/utils/unit-cycle.d.ts +61 -0
- package/dist/zdtp.css +1 -1
- package/package.json +1 -1
- package/dist/load-routing-DtNTKoLW.js +0 -353
- package/dist/tweak-state-BeXkzoj8.js +0 -1858
|
@@ -22,6 +22,12 @@ export interface PerFileResult {
|
|
|
22
22
|
changed: string[];
|
|
23
23
|
unchanged: string[];
|
|
24
24
|
unknown: string[];
|
|
25
|
+
/**
|
|
26
|
+
* Subset of `unknown` (#508): declared somewhere in the file but outside
|
|
27
|
+
* the scanned `:root`/`@theme` blocks — see `ApplyResult.unknownOutsideBlock`
|
|
28
|
+
* in `apply-token-overrides.ts` for the full classification rules.
|
|
29
|
+
*/
|
|
30
|
+
unknownOutsideBlock: string[];
|
|
25
31
|
}
|
|
26
32
|
/**
|
|
27
33
|
* Create a framework-agnostic Fetch API handler for the design-token apply
|
package/dist/server/index.js
CHANGED
|
@@ -80,6 +80,12 @@ export type { TabOverrides } from '../apply/tier-resolver';
|
|
|
80
80
|
export declare function getStorageKeyV1(cfg?: PanelConfig): string;
|
|
81
81
|
export declare function getStorageKeyV2(cfg?: PanelConfig): string;
|
|
82
82
|
export declare function getStorageKeyV3(cfg?: PanelConfig): string;
|
|
83
|
+
/**
|
|
84
|
+
* v4 unified envelope key — the per-scheme-keyed color format (#500/#509).
|
|
85
|
+
* See `storageKey_stateV4` for the shape rationale. Read first by
|
|
86
|
+
* `loadPersistedState`; v1/v2/v3 migrate into it on first load.
|
|
87
|
+
*/
|
|
88
|
+
export declare function getStorageKeyV4(cfg?: PanelConfig): string;
|
|
83
89
|
export declare function getOpenKey(cfg?: PanelConfig): string;
|
|
84
90
|
export declare function getPositionKey(cfg?: PanelConfig): string;
|
|
85
91
|
export declare function getSizeKey(cfg?: PanelConfig): string;
|
|
@@ -258,6 +264,32 @@ export interface TweakState {
|
|
|
258
264
|
/** Generic tab overrides keyed by tab id. Added in v3 envelope. */
|
|
259
265
|
tabs?: Record<string, TabOverrides>;
|
|
260
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* On-disk v4 persist envelope (#500/#509). Same top-level slices as the runtime
|
|
269
|
+
* `TweakState`, EXCEPT the `color` and `secondary` slices are identity-keyed
|
|
270
|
+
* sub-objects: one `ColorTweakState` slot per active-color IDENTITY (see
|
|
271
|
+
* `getActiveColorIdentity`). This is what lets a per-scheme color tweak survive
|
|
272
|
+
* a scheme toggle — editing under scheme A never touches scheme B's slot.
|
|
273
|
+
*
|
|
274
|
+
* The non-color slices (`spacing` / `typography` / `size` / `tabs`) stay global
|
|
275
|
+
* and unkeyed, exactly as in v1–v3: a light/dark toggle does not change them.
|
|
276
|
+
*
|
|
277
|
+
* `secondary` slots are keyed by the SAME primary identity — the secondary
|
|
278
|
+
* cluster has no scheme of its own but reseeds on the same `color-scheme-changed`
|
|
279
|
+
* event, so it follows the primary's identity.
|
|
280
|
+
*
|
|
281
|
+
* `loadPersistedState` selects the active identity's slots into a runtime
|
|
282
|
+
* `TweakState`; `savePersistedState` merge-saves the active slots while
|
|
283
|
+
* preserving every inactive identity's slot.
|
|
284
|
+
*/
|
|
285
|
+
export interface PersistedEnvelopeV4 {
|
|
286
|
+
color: Record<string, ColorTweakState>;
|
|
287
|
+
secondary?: Record<string, ColorTweakState>;
|
|
288
|
+
spacing: TokenOverrides;
|
|
289
|
+
typography: TokenOverrides;
|
|
290
|
+
size: TokenOverrides;
|
|
291
|
+
tabs?: Record<string, TabOverrides>;
|
|
292
|
+
}
|
|
261
293
|
/** Produce an empty overrides map — `TweakState` default for new tabs. */
|
|
262
294
|
export declare function emptyOverrides(): TokenOverrides;
|
|
263
295
|
/**
|
|
@@ -360,6 +392,24 @@ export declare function getActiveSchemeName(cluster?: ColorClusterDataConfig, cf
|
|
|
360
392
|
* is the correct behavior for non-sink instances but wrong for sinks.
|
|
361
393
|
*/
|
|
362
394
|
export declare function initColorFromScheme(cluster?: ColorClusterDataConfig, cfg?: PanelConfig): ColorTweakState;
|
|
395
|
+
/**
|
|
396
|
+
* Derive the active-color IDENTITY — the key under which the v4 envelope files
|
|
397
|
+
* this instance's `color` / `secondary` slots (#500/#509).
|
|
398
|
+
*
|
|
399
|
+
* The identity is EXACTLY the active scheme name `initColorFromScheme` resolves
|
|
400
|
+
* for the primary cluster via `getActiveSchemeName` (the active scheme, with the
|
|
401
|
+
* light/dark mode already folded into the resolved name where the cluster
|
|
402
|
+
* `panelSettings.colorMode` distinguishes modes). This is deliberate: the same
|
|
403
|
+
* inputs whose change triggers a reseed today produce the identity, so the
|
|
404
|
+
* invariant holds — *the same identity that causes a reseed selects its own
|
|
405
|
+
* persisted slot*. A colorMode-less cluster resolves a constant identity (one
|
|
406
|
+
* slot); a light/dark cluster resolves distinct identities per side.
|
|
407
|
+
*
|
|
408
|
+
* The secondary cluster has no scheme concept of its own but reseeds on the same
|
|
409
|
+
* `color-scheme-changed` event, so its slots are keyed by this SAME primary
|
|
410
|
+
* identity — callers pass the PRIMARY cluster here for both slices.
|
|
411
|
+
*/
|
|
412
|
+
export declare function getActiveColorIdentity(cluster?: ColorClusterDataConfig, cfg?: PanelConfig): string;
|
|
363
413
|
/**
|
|
364
414
|
* Palette entry sanitiser. Raw `oklch(...)` values are preserved verbatim so
|
|
365
415
|
* wide-gamut chroma survives (and they never touch the canvas → no '#000000'
|
|
@@ -438,8 +488,17 @@ export declare function resolveSemanticPreviewColor(mapping: SemanticValue, stat
|
|
|
438
488
|
* for an unresolvable ref rather than throwing, and this function skips a
|
|
439
489
|
* `null` (leaving the token at its stylesheet default) rather than painting
|
|
440
490
|
* a fallback color.
|
|
491
|
+
*
|
|
492
|
+
* `ownerPrefix` (#501) is the instance `storagePrefix` this apply belongs to.
|
|
493
|
+
* When supplied AND this cluster emits a per-mode `light-dark()` literal (so
|
|
494
|
+
* `color-scheme: light dark` is written to the apply target — either
|
|
495
|
+
* `document.documentElement` or the sink's root), the instance is recorded as
|
|
496
|
+
* the owner of that inline `color-scheme` so the clear paths can later remove
|
|
497
|
+
* it without ever wiping a host-owned `<html style="color-scheme">`. Omitting
|
|
498
|
+
* it (direct callers with no instance context, e.g. some tests) skips the
|
|
499
|
+
* bookkeeping only — the actual CSS write is unchanged.
|
|
441
500
|
*/
|
|
442
|
-
export declare function applyColorState(state: ColorTweakState, cluster?: ColorClusterDataConfig, sink?: ApplySink, currentTab?: TabConfig, tabs?: readonly TabConfig[]): void;
|
|
501
|
+
export declare function applyColorState(state: ColorTweakState, cluster?: ColorClusterDataConfig, sink?: ApplySink, currentTab?: TabConfig, tabs?: readonly TabConfig[], ownerPrefix?: string): void;
|
|
443
502
|
/**
|
|
444
503
|
* Apply a `TokenOverrides` map for a given manifest — writes inline
|
|
445
504
|
* `--css-var: value` on `:root` for every overridden token, and removes the
|
|
@@ -450,6 +509,31 @@ export declare function applyColorState(state: ColorTweakState, cluster?: ColorC
|
|
|
450
509
|
* in the UI and are never written to storage.
|
|
451
510
|
*/
|
|
452
511
|
export declare function applyTokenOverrides(tokens: readonly TokenDef[], overrides: TokenOverrides, sink?: ApplySink): void;
|
|
512
|
+
/**
|
|
513
|
+
* Apply ONLY the color slices — primary color cluster + optional secondary
|
|
514
|
+
* cluster + the aggregate `color-scheme` decision — leaving spacing / font /
|
|
515
|
+
* size / generic-tab vars untouched.
|
|
516
|
+
*
|
|
517
|
+
* Extracted from `applyFullState` (#500/#509) so the scheme-change handler can
|
|
518
|
+
* re-paint the new identity's persisted color overrides after
|
|
519
|
+
* `clearAppliedColorStyles` WITHOUT re-writing (or clearing) the scheme-
|
|
520
|
+
* independent non-color vars that must survive a light/dark toggle (#347).
|
|
521
|
+
*
|
|
522
|
+
* `color-scheme` is managed as an AGGREGATE across the primary + secondary
|
|
523
|
+
* clusters, not per-cluster (#482 D3): `applyColorState` only ever SETS
|
|
524
|
+
* `color-scheme: light dark` when its OWN cluster needs it, it never clears
|
|
525
|
+
* it, so demoting the last per-mode-literal row (in either cluster) would
|
|
526
|
+
* otherwise leave the previous apply's value stale. A naive per-cluster
|
|
527
|
+
* clear inside `applyColorState` would let a per-mode-free secondary undo
|
|
528
|
+
* what the primary just required (or vice versa), so the clear-when-neither-
|
|
529
|
+
* needs-it decision is made here, once, after both clusters have applied.
|
|
530
|
+
*
|
|
531
|
+
* #501 — the `document.documentElement` clear is scoped to a color-scheme THIS
|
|
532
|
+
* instance actually wrote (`clearOwnedColorSchemeFromDocument`) so a host that
|
|
533
|
+
* owns `<html style="color-scheme">` is never clobbered; the sink path stays
|
|
534
|
+
* unconditional (sink targets are panel-owned) but drops the ownership claim.
|
|
535
|
+
*/
|
|
536
|
+
export declare function applyColorSlices(color: ColorTweakState, secondary: ColorTweakState | undefined, cfg?: PanelConfig): void;
|
|
453
537
|
/**
|
|
454
538
|
* Apply the full unified `TweakState` — primary color cluster + token
|
|
455
539
|
* overrides + optional secondary cluster.
|
|
@@ -462,16 +546,26 @@ export declare function applyTokenOverrides(tokens: readonly TokenDef[], overrid
|
|
|
462
546
|
* CSS-var writes for this instance. Omitting `cfg` uses the default active
|
|
463
547
|
* config (single-panel path, unchanged behavior).
|
|
464
548
|
*
|
|
465
|
-
* `color-scheme`
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
* it, so demoting the last per-mode-literal row (in either cluster) would
|
|
469
|
-
* otherwise leave the previous apply's value stale. A naive per-cluster
|
|
470
|
-
* clear inside `applyColorState` would let a per-mode-free secondary undo
|
|
471
|
-
* what the primary just required (or vice versa), so the clear-when-neither-
|
|
472
|
-
* needs-it decision is made here, once, after both clusters have applied.
|
|
549
|
+
* The color slices + aggregate `color-scheme` decision are delegated to
|
|
550
|
+
* `applyColorSlices`; this function adds the non-color (spacing / font / size /
|
|
551
|
+
* generic-tab) writes.
|
|
473
552
|
*/
|
|
474
553
|
export declare function applyFullState(state: TweakState, cfg?: PanelConfig): void;
|
|
554
|
+
/**
|
|
555
|
+
* Apply ONLY the non-color slices (spacing / typography / size / generic-tab
|
|
556
|
+
* overrides), leaving the color clusters and aggregate `color-scheme` decision
|
|
557
|
+
* untouched. Complement of `applyColorSlices`; together they compose
|
|
558
|
+
* `applyFullState`.
|
|
559
|
+
*
|
|
560
|
+
* Extracted (#509 audit) so the persisted-overrides reapply paths
|
|
561
|
+
* (`reapplyPersistedOverrides`, the panel first-open effect) can, when a v4
|
|
562
|
+
* envelope exists but the ACTIVE (scheme, mode) identity has no color slot,
|
|
563
|
+
* still apply the scheme-INDEPENDENT non-color tweaks while leaving the active
|
|
564
|
+
* scheme's own stylesheet colors to show through — instead of painting the
|
|
565
|
+
* synthesized config-default colors inline. This mirrors the scheme-change
|
|
566
|
+
* handler's missing-slot behavior (gated on `hasActiveColorSlot`).
|
|
567
|
+
*/
|
|
568
|
+
export declare function applyNonColorSlices(state: TweakState, cfg?: PanelConfig): void;
|
|
475
569
|
/**
|
|
476
570
|
* Strip the inline CSS variables written by the color cluster(s) only —
|
|
477
571
|
* palette slots, base roles, and semantic vars. Spacing / typography / size
|
|
@@ -495,6 +589,11 @@ export declare function applyFullState(state: TweakState, cfg?: PanelConfig): vo
|
|
|
495
589
|
* historical `(clusters, sink)` call shape (e.g. the scheme-change path before
|
|
496
590
|
* #357, and existing tests) is unchanged. Omitting all three preserves the
|
|
497
591
|
* single-panel default-instance behaviour.
|
|
592
|
+
*
|
|
593
|
+
* The color-scheme removal on the `document.documentElement` path is gated on
|
|
594
|
+
* this instance owning the inline value (#501) — see
|
|
595
|
+
* `clearOwnedColorSchemeFromDocument`. The owner is `cfg.storagePrefix` when a
|
|
596
|
+
* `cfg` is given, else the default instance's prefix.
|
|
498
597
|
*/
|
|
499
598
|
export declare function clearAppliedColorStyles(clusters?: readonly ColorClusterDataConfig[], sink?: ApplySink, cfg?: PanelConfig): void;
|
|
500
599
|
/**
|
|
@@ -560,17 +659,41 @@ export interface StorageLike {
|
|
|
560
659
|
* labels), so this migration only applies to the typography slice.
|
|
561
660
|
*/
|
|
562
661
|
export declare const ZDTP_LEGACY_TYPOGRAPHY_RENAME_MAP: Readonly<Record<string, string | null>>;
|
|
662
|
+
/**
|
|
663
|
+
* True when the v4 envelope holds a color slot for the CURRENTLY active
|
|
664
|
+
* identity. The scheme-change handler uses this to decide whether to hydrate +
|
|
665
|
+
* apply persisted overrides for the new scheme (slot present) or reseed from
|
|
666
|
+
* config defaults WITHOUT applying (slot absent — the pre-#500 behavior that
|
|
667
|
+
* lets the new scheme's stylesheet show through).
|
|
668
|
+
*/
|
|
669
|
+
export declare function hasActiveColorSlot(cfg?: PanelConfig, cluster?: ColorClusterDataConfig, storage?: StorageLike): boolean;
|
|
670
|
+
/**
|
|
671
|
+
* Load the active `TweakState`, preferring the v4 per-scheme envelope
|
|
672
|
+
* (#500/#509).
|
|
673
|
+
*
|
|
674
|
+
* Order:
|
|
675
|
+
* 1. v4 present → select the active identity's color/secondary slots.
|
|
676
|
+
* 2. else run the legacy v1/v2/v3 chain (unchanged) → migrate that state into
|
|
677
|
+
* a v4 envelope filed under the identity active at load, WITHOUT deleting
|
|
678
|
+
* the legacy key (v4 wins on every future load via step 1). This is why the
|
|
679
|
+
* pre-existing v1/v2/v3 migration tests keep passing: the legacy chain still
|
|
680
|
+
* writes/keeps the v3 key exactly as before; v4 is layered on top.
|
|
681
|
+
* 3. else null (caller cold-seeds).
|
|
682
|
+
*
|
|
683
|
+
* A present-but-malformed v4 blob falls through to steps 2/3, which overwrite it.
|
|
684
|
+
*/
|
|
563
685
|
export declare function loadPersistedState(storage?: StorageLike, colorDefaults?: ColorTweakState, cluster?: ColorClusterDataConfig, cfg?: PanelConfig): TweakState | null;
|
|
564
686
|
/**
|
|
565
|
-
*
|
|
687
|
+
* Merge-save the full `TweakState` into the v4 per-scheme envelope (#500/#509).
|
|
566
688
|
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
689
|
+
* The active identity's color/secondary slots are overwritten; every inactive
|
|
690
|
+
* identity's slot is preserved (read → merge → write). Global non-color slices
|
|
691
|
+
* are replaced wholesale. `cfg` scopes the storage key to a specific panel
|
|
692
|
+
* instance (multi-instance, #357).
|
|
570
693
|
*/
|
|
571
694
|
export declare function savePersistedState(state: TweakState, storage?: StorageLike, cfg?: PanelConfig): void;
|
|
572
695
|
/**
|
|
573
|
-
* Remove
|
|
696
|
+
* Remove the v4 key (and lingering v3/v2/v1 keys).
|
|
574
697
|
*
|
|
575
698
|
* `cfg` scopes the cleared keys to a specific panel instance (multi-instance,
|
|
576
699
|
* #357). Omitting it resolves the default instance via `getPanelConfig()`,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TabConfig } from '../tokens/tier-model';
|
|
2
|
+
interface NotesTabProps {
|
|
3
|
+
tab: TabConfig;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Notes tab — host-configurable "token notes" landing view (#515).
|
|
7
|
+
*
|
|
8
|
+
* Renders `tab.notesExtras.title` as a section heading
|
|
9
|
+
* (`div[role="heading"][aria-level=3]`, NEVER an hN tag — see
|
|
10
|
+
* packages/zdtp/CLAUDE.md "Panel DOM hygiene") and `tab.notesExtras.html` as
|
|
11
|
+
* sanitized HTML via `dangerouslySetInnerHTML` — the package's first and only
|
|
12
|
+
* use of it. `sanitizeHtml` (utils/sanitize-html.ts) is the security
|
|
13
|
+
* boundary, an allowlist parser, not this component and not the CSS below.
|
|
14
|
+
*
|
|
15
|
+
* The rendered `.tokenpanel-notes-body` subtree is HOST-AUTHORED PROSE
|
|
16
|
+
* CONTENT, not panel chrome: the DOM-hygiene ban on h1-h6/p/ul/a/table/etc.
|
|
17
|
+
* applies to the panel's OWN JSX, and does not apply inside sanitized note
|
|
18
|
+
* content — that's exactly the markup a "notes" feature needs to render.
|
|
19
|
+
*
|
|
20
|
+
* `assertValidPanelConfig` requires `notesExtras` (non-empty title + html)
|
|
21
|
+
* on every tab with `id: 'notes'`, so this component can assume it's
|
|
22
|
+
* present without a runtime fallback UI.
|
|
23
|
+
*/
|
|
24
|
+
export default function NotesTab({ tab }: NotesTabProps): import("preact").JSX.Element | null;
|
|
25
|
+
export {};
|
package/dist/testing.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { _ as r, c as
|
|
2
|
-
import { a as
|
|
1
|
+
import { _ as r, c as _, h as i, j as n, k as g, b as R, a as p } from "./panel-config-Bw7D-25C.js";
|
|
2
|
+
import { a as y, b as O, l as P } from "./tweak-state-CD1y56zR.js";
|
|
3
3
|
import { F as K, G as E, a as S, S as u } from "./manifest-DCReQE0k.js";
|
|
4
4
|
async function s(a, e) {
|
|
5
5
|
await a.fill(e), await a.dispatchEvent("input");
|
|
@@ -10,12 +10,12 @@ export {
|
|
|
10
10
|
S as GROUP_TITLES,
|
|
11
11
|
u as SIZE_GROUP_ORDER,
|
|
12
12
|
r as __resetPanelConfigForTests,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
_ as configurePanel,
|
|
14
|
+
y as getStorageKeyV1,
|
|
15
|
+
O as getStorageKeyV2,
|
|
16
|
+
P as loadPersistedState,
|
|
17
17
|
s as setPanelInputValue,
|
|
18
|
-
|
|
18
|
+
i as storageKey_open,
|
|
19
19
|
n as storageKey_position,
|
|
20
20
|
g as storageKey_stateV1,
|
|
21
21
|
R as storageKey_stateV2,
|
|
@@ -60,6 +60,14 @@ export interface TokenDef {
|
|
|
60
60
|
step: number;
|
|
61
61
|
/** Unit suffix (e.g. `rem`, `px`). Read-only rows may use an empty string. */
|
|
62
62
|
unit: string;
|
|
63
|
+
/**
|
|
64
|
+
* Optional list of unit suffixes this row may cycle through by clicking
|
|
65
|
+
* the unit label (#519). 2+ entries opts in; omitted/single-entry keeps
|
|
66
|
+
* today's static, non-interactive unit suffix. Mirrors `TierValueKind`'s
|
|
67
|
+
* `length.units` — the default-slider mapping in a host's
|
|
68
|
+
* `toTierItem()`-style helper should pass it straight through.
|
|
69
|
+
*/
|
|
70
|
+
units?: readonly string[];
|
|
63
71
|
/** Read-only tokens are displayed but not editable (e.g. `clamp()` expressions). */
|
|
64
72
|
readonly?: true;
|
|
65
73
|
/** Which control renders this token. Defaults to `"slider"` when absent. */
|
|
@@ -4,6 +4,16 @@ export type TierValueKind = {
|
|
|
4
4
|
kind: 'length';
|
|
5
5
|
step: number;
|
|
6
6
|
unit: string;
|
|
7
|
+
/**
|
|
8
|
+
* Optional list of unit suffixes this row may cycle through by
|
|
9
|
+
* clicking the unit label (#519). 2+ entries opts the row into an
|
|
10
|
+
* interactive, click/Enter/Space-cycling unit suffix (wrapping through
|
|
11
|
+
* the list); omitted or a single entry keeps today's static,
|
|
12
|
+
* non-interactive unit span, pixel-identical. This kind is reused for
|
|
13
|
+
* ms durations and unitless values too — only declare `units` when
|
|
14
|
+
* cycling between those suffixes is valid CSS for the token.
|
|
15
|
+
*/
|
|
16
|
+
units?: readonly string[];
|
|
7
17
|
} | {
|
|
8
18
|
kind: 'number';
|
|
9
19
|
step: number;
|
|
@@ -132,10 +142,36 @@ export interface ColorClusterExtras {
|
|
|
132
142
|
defaultShikiTheme: string;
|
|
133
143
|
colorSchemes: Record<string, ColorScheme>;
|
|
134
144
|
panelSettings: ClusterPanelSettings;
|
|
145
|
+
/**
|
|
146
|
+
* Config-time override map for a semantic tier's derived defaults (#499).
|
|
147
|
+
* Keyed by semantic item id; when a key is present here,
|
|
148
|
+
* `resolveColorClusterFromTab` uses its `SemanticValue` verbatim instead of
|
|
149
|
+
* running `deriveSemanticValue` on the item's plain-string `default` — this
|
|
150
|
+
* is the only way a host can ship a `{ literal: { light, dark } }` (or
|
|
151
|
+
* `{ ref }`) config-time default, since `TierItem.default` itself stays a
|
|
152
|
+
* plain string (Option B from #499, chosen over widening `TierItem.default`
|
|
153
|
+
* to `SemanticValue` — that field is consumed generically as a plain string
|
|
154
|
+
* by every tab kind, not just Color).
|
|
155
|
+
*/
|
|
156
|
+
semanticDefaults?: Record<string, SemanticValue>;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Host-configurable "token notes" content — ONLY valid on the reserved
|
|
160
|
+
* `id: 'notes'` pseudo-tab (#515). That tab renders `title` as a section
|
|
161
|
+
* heading and `html` (sanitized by `utils/sanitize-html.ts`) as its body,
|
|
162
|
+
* instead of a tier-driven token editor. `assertValidPanelConfig` enforces
|
|
163
|
+
* the full contract: required + non-empty on `id: 'notes'`, forbidden on
|
|
164
|
+
* every other tab id, and `id: 'notes'` tabs must ship `tiers: []` and no
|
|
165
|
+
* `colorExtras`.
|
|
166
|
+
*/
|
|
167
|
+
export interface NotesExtras {
|
|
168
|
+
title: string;
|
|
169
|
+
html: string;
|
|
135
170
|
}
|
|
136
171
|
export interface TabConfig {
|
|
137
172
|
id: string;
|
|
138
173
|
label: string;
|
|
139
174
|
tiers: readonly TierConfig[];
|
|
140
175
|
colorExtras?: ColorClusterExtras;
|
|
176
|
+
notesExtras?: NotesExtras;
|
|
141
177
|
}
|