@takazudo/zdtp 0.6.0 → 0.7.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,65 @@ All notable changes to `@takazudo/zdtp` are documented in this file.
4
4
 
5
5
  The format is based on Keep a Changelog, and release notes are generated from the changelog MDX pages.
6
6
 
7
+ ## [Unreleased]
8
+
9
+ No unreleased changes yet.
10
+
11
+ ## [0.7.0] - 2026-09-09
12
+
13
+ ### Breaking Changes
14
+
15
+ - feat(dashboard): separate chrome theme from specimen mode (84d4d8a). `TokenDashboard` no longer derives its chrome appearance from `mode`: with `mode="dark"` the inventory scope previously carried `color-scheme: dark`, and now only `.zdtp-dashboard__specimen` does, with chrome defaulting to light. **Migration**: pass the new `chrome="dark"` prop alongside `mode="dark"` to restore the previous dark chrome, or `chrome="host"` to inherit the host's effective color scheme.
16
+
17
+ ### Features
18
+
19
+ - feat: resolve CSS color expressions in host context ([#919](https://github.com/Takazudo/zudo-design-token-panel/issues/919)) (30dbabc)
20
+ - feat: require explicit conversion before editing color expressions (ffad163)
21
+
22
+ ### Fixed
23
+
24
+ - Fix invalid CSS color probe fallback (a1d468f)
25
+ - Reject unchanged invalid color declarations before measurement (27fbc70)
26
+
27
+ ### Other Changes
28
+
29
+ - docs(dashboard): document host chrome and add static theme examples (1b8e26d)
30
+ - docs(dashboard): document chrome contract (83778e8)
31
+ - test: cover dashboard chrome themes in browser (5682c72)
32
+ - test: strengthen dashboard specimen isolation assertions (cc62be6)
33
+ - test: prove dashboard host chrome from packed consumer (7a251f0)
34
+ - test(evidence): record dashboard chrome integration proof (690af1f)
35
+ - test: wire semantic expression picker modes (90af515)
36
+ - Cover empty CSS color resolution (18f45ba)
37
+ - docs: record reference-aware color picker fix (b1bb048)
38
+ - test: record reference-aware picker confirmation (045603b)
39
+ - docs: correct picker evidence provenance (89e0322)
40
+
41
+ ## [0.6.1] - 2026-09-08
42
+
43
+ ### Features
44
+
45
+ - feat: model declared token defaults for static dashboards (422643b)
46
+ - feat: expose a static Preact token dashboard (5b6c0f8)
47
+ - feat(playground): add static token dashboard demo and docs (2edd98b)
48
+ - feat(dashboard): render rulers, palette strips and wide type specimens (7cdf01f)
49
+
50
+ ### Fixed
51
+
52
+ - fix: preserve semantic literals alongside legacy palette references (b813c8a)
53
+
54
+ ### Other Changes
55
+
56
+ - test: account for standalone dashboard stylesheet delivery (a00541a)
57
+ - test: verify packed dashboard SSR and public stylesheet consumption (6cd8157)
58
+ - test: cover static dashboard list-view geometry in browser (e07d69e)
59
+ - chore: normalize dashboard browser test file mode (0ec8217)
60
+ - docs: demonstrate dashboard rulers ramps and reading specimens (859d3a4)
61
+ - test: verify packed dashboard list views and preview text (7ebf4cf)
62
+ - test: prove isolated dashboard package consumption (fdb3906)
63
+ - fix(test): compare Preact package identity across module conditions (bb280ee)
64
+ - Fix static browser harness loading and polling (3fe6203)
65
+
7
66
  ## [0.6.0] - 2026-09-08
8
67
 
9
68
  ### Breaking Changes
@@ -1741,6 +1741,117 @@ on across a release bump.
1741
1741
 
1742
1742
  ---
1743
1743
 
1744
+ ## 12. Static token dashboard
1745
+
1746
+ This entry is available from v0.6.1. The `chrome` prop is **unreleased (next
1747
+ release)** and is not supported in v0.6.1. It does not change the
1748
+ `configurePanel` or persistence contracts above.
1749
+
1750
+ `@takazudo/zdtp/dashboard` exports the Preact `TokenDashboard` component and
1751
+ `TokenDashboardProps`, `DashboardMode`, `DashboardChrome`,
1752
+ `DashboardPreviewKind`, `TabConfig`, `TierConfig`, and `TierItem` types. The
1753
+ internal value model is not a public API.
1754
+
1755
+ ```ts
1756
+ export type DashboardMode = 'light' | 'dark';
1757
+ export type DashboardChrome = 'light' | 'dark' | 'host';
1758
+ export type DashboardPreviewKind =
1759
+ | 'bar' | 'size' | 'line-height' | 'family' | 'weight' | 'radius' | 'duration'
1760
+ | 'color' | 'shadow' | 'text';
1761
+
1762
+ export interface TokenDashboardProps {
1763
+ tabs: readonly TabConfig[];
1764
+ mode?: DashboardMode; // default: light
1765
+ chrome?: DashboardChrome; // default: light; unreleased (next release)
1766
+ title?: string; // default: Token dashboard
1767
+ previewText?: string; // static typography passage; default English/Japanese prose
1768
+ id?: string; // optional root ID; caller owns uniqueness
1769
+ previewOverrides?: Readonly<Record<string, DashboardPreviewKind>>;
1770
+ }
1771
+ ```
1772
+
1773
+ ### Rendering and package boundary
1774
+
1775
+ - Ordinary Preact rendering and server rendering are supported. The component
1776
+ has no browser-global, panel-runtime, persistence, host-adapter, bin-server,
1777
+ or browser Tailwind compiler dependency. No hydration is required.
1778
+ - `@takazudo/zdtp/dashboard/styles.css` is a separate public asset. Dashboard
1779
+ JavaScript has no CSS side-effect import; the host must include this asset
1780
+ through its CSS build or a static stylesheet link. It is not appended to the
1781
+ existing panel stylesheet, which is unnecessary for a dashboard-only page.
1782
+ - The dashboard root's chrome appearance follows `chrome`: `light` and `dark`
1783
+ fix the shell scheme, while `host` inherits the host's effective
1784
+ `color-scheme` and requires the host to set it on an ancestor. The dashboard
1785
+ uses no media query, so an explicit application theme takes precedence over
1786
+ the OS preference. Inventory specimens retain their own `color-scheme` from
1787
+ `mode`, which also selects declared per-mode defaults. Chrome and specimens
1788
+ are independent; chrome uses package-owned CSS custom properties and never
1789
+ reads inventory variables. The component never writes to `:root` or host
1790
+ state.
1791
+ - Tabs, tiers, and rows render in input order. All token rows remain visible;
1792
+ no collapsed sections or automatic IDs are introduced. Empty input is valid.
1793
+ Notes-only tabs are omitted, and arbitrary notes HTML is never injected.
1794
+
1795
+ ### Layouts for spacing, color, and typography
1796
+
1797
+ Spacing (`bar`) uses wide rows with aligned ruler origins. Nonnegative `px` or
1798
+ `rem` lengths, unitless zero, and resolved direct local aliases get an actual-size
1799
+ sample. Ticks mark 8 CSS px, with major ticks every 64 CSS px. The browser sizes
1800
+ `rem` against the host root font size; the dashboard does not assume a conversion.
1801
+ Large lengths scroll inside the focusable ruler instead of shrinking or clamping.
1802
+ Zero has zero width. Negative lengths, `em`, percentages, `calc()` and other
1803
+ unsupported expressions retain their declaration with a ruler-unavailable
1804
+ explanation. Missing references also retain their diagnostics.
1805
+
1806
+ A nonsemantic, non-reference tier whose source items are all colors becomes a
1807
+ discrete palette strip. Stops stay in declared order, with every label and value
1808
+ visible; narrow containers scroll horizontally. Grouping uses tier structure,
1809
+ not name matching or generated intermediate colors. Semantic and reference tiers
1810
+ keep independent color samples. Per-variable preview overrides remain authoritative
1811
+ and retain each token's slot and order, including mixed overrides within a strip.
1812
+
1813
+ `size`, `family`, `weight`, and `line-height` use wide, multiline specimens with
1814
+ auto height outside palette strips. Overrides inside a palette retain their stop slot. The baseline is 18px text with 1.6 line height; each sample changes
1815
+ only its intended property. A resolved `previewBase` can supply the font size of
1816
+ a line-height sample. Font families use locally available fonts and their CSS
1817
+ fallbacks; the dashboard does not download fonts.
1818
+
1819
+ `previewText` supplies one static passage for all typography samples in an
1820
+ instance. Its default is longer English/Japanese prose. Newlines and white space
1821
+ are preserved, text is escaped, and an explicit empty string stays empty.
1822
+ Long text wraps; unusually large glyphs can scroll locally without scaling.
1823
+ There is no built-in editable text workbench or connection to panel state.
1824
+
1825
+ ### Values and previews
1826
+
1827
+ - Inputs describe **declared defaults**: item defaults, selected-mode
1828
+ `colorExtras.semanticDefaults`, and explicit `colorExtras.baseDefaults` for
1829
+ base-role rows. Named presets, panel initialization, and saved/current panel
1830
+ state are not applied. Pill rows preserve `item.default`, not `customDefault`.
1831
+ - Reference tiers, cross-tab ramps, aliases, and legacy palette indices resolve
1832
+ against actual declared IDs and `cssVar` names. Rows retain declared values
1833
+ and display CSS/reference text. Missing/ambiguous mappings, duplicate
1834
+ variables, cycles, and unsafe declarations remain visible with diagnostics
1835
+ and no misleading sample.
1836
+ - CSS expressions remain expressions. Resolution is not universal CSS grammar
1837
+ validation or browser computed-style inspection. External dependencies may
1838
+ be context-dependent; unresolved dependencies suppress samples and expose
1839
+ diagnostics. Browser layout, units, and available fonts affect previews.
1840
+ - Preview choice is `previewOverrides[cssVar]`, then `TierConfig.preview`, then
1841
+ color for color-editor rows or text for other rows. `duration` and `text`
1842
+ display values without animated/visual samples. A resolved `previewBase`
1843
+ token can supply font size for a line-height sample. Subsets must include
1844
+ referenced tiers to retain resolved samples.
1845
+ - Preact escapes text. URL/mask assets and unsafe resource-bearing expressions
1846
+ are not automatically loaded through samples.
1847
+
1848
+ Keep shared token definitions in a build-safe data module using type-only
1849
+ imports. Pass the same tabs to `PanelConfig` and `TokenDashboard`; no automatic
1850
+ state synchronization follows from sharing them. A React adapter and an
1851
+ HTML-export function or CLI are outside this checkpoint.
1852
+
1853
+ ---
1854
+
1744
1855
  ## Appendix A — section index
1745
1856
 
1746
1857
  Cross-reference table — what each section pins down.
@@ -1772,6 +1883,7 @@ Cross-reference table — what each section pins down.
1772
1883
  | `data-zdtp-action` stable header-action hook (ids stable, labels not; two matches while the compact popover is open) | §7.6 |
1773
1884
  | v4 envelope precedence, v1/v2/v3 storage migration, and typography-id rename map | §2, §8.3, §8.4 |
1774
1885
  | JSON export/import schemas v1/v2/v3 (serde) | §9 |
1886
+ | Static Preact dashboard props, defaults, previews, isolation, and CSS export | §12 |
1775
1887
  | Out-of-scope / deferred concerns | §10 |
1776
1888
  | Versioning promise, breaking-change signalling, and consumer guidance for mirroring the eager-load gate registries | §11 |
1777
1889
  | Feature walkthrough and shortcut table | [Panel UX tour](/docs/recipes/panel-ux-tour) |
package/README.md CHANGED
@@ -32,12 +32,105 @@ The authoritative API spec is [`PORTABLE-CONTRACT.md`](./PORTABLE-CONTRACT.md).
32
32
  partial reconciliation, and JSON export/import when disk apply is not
33
33
  configured.
34
34
  - Owner autoload for developer-only loading across page visits.
35
+ - A separate Preact `TokenDashboard` for a static, read-only token inventory
36
+ (available from v0.6.1).
35
37
 
36
38
  See the [Panel UX tour](/docs/recipes/panel-ux-tour) for a feature-by-feature
37
39
  walkthrough and the shortcut table.
38
40
 
39
41
  ---
40
42
 
43
+ ## Static token dashboard
44
+
45
+ Import `TokenDashboard` from `@takazudo/zdtp/dashboard` to render the same tab
46
+ manifest on a plain page. This entry is available from v0.6.1. The `chrome`
47
+ prop is **unreleased (next release)** and is not supported in v0.6.1. The [live workspace demo](https://zdtp-playground.zudolab.dev/dashboard/)
48
+ shows both modes and a compact embedded instance.
49
+
50
+ ```tsx
51
+ import { TokenDashboard } from '@takazudo/zdtp/dashboard';
52
+ import { tokenTabs } from './token-tabs'; // Shared data module; type-only imports.
53
+
54
+ export default function TokenPage() {
55
+ return <TokenDashboard tabs={tokenTabs} mode="light" title="Site tokens" />;
56
+ }
57
+ ```
58
+
59
+ For example, keep the definitions in a module that is safe to import at build time:
60
+
61
+ ```ts
62
+ // token-tabs.ts — data only; safe to import during a site build.
63
+ import type { TabConfig } from '@takazudo/zdtp/dashboard';
64
+
65
+ export const tokenTabs: readonly TabConfig[] = [{
66
+ id: 'space',
67
+ label: 'Spacing',
68
+ tiers: [{
69
+ id: 'scale',
70
+ label: 'Scale',
71
+ preview: 'bar',
72
+ items: [{
73
+ id: 'space-md',
74
+ cssVar: '--site-space-md',
75
+ label: 'Medium',
76
+ default: '1rem',
77
+ type: { kind: 'length', step: 0.25, unit: 'rem' },
78
+ }],
79
+ }],
80
+ }];
81
+ ```
82
+
83
+ Also pass `tokenTabs` as `tabs` in your panel's config. Keep panel initialization
84
+ and browser/storage code out of this data module.
85
+ The component requires Preact and can render during the host's static build
86
+ without hydration; no panel initialization is needed.
87
+
88
+ Include **`@takazudo/zdtp/dashboard/styles.css`** separately. The dashboard JS
89
+ does not import CSS and does not need the panel stylesheet. A CSS-emitting
90
+ bundler can import this asset from its layout; strict static hosts should use
91
+ a supported global CSS `@import` or copy the resolved public export to their
92
+ public assets directory and add a stylesheet link. The
93
+ [static dashboard recipe](https://zdtp.zudolab.dev/docs/recipes/static-token-dashboard/)
94
+ provides complete data and CSS-copy examples.
95
+
96
+ Optional props are `mode` (`light` by default), `chrome` (`light` by default;
97
+ **unreleased for the next release**), `title`, caller-owned unique `id`,
98
+ `previewText`, and `previewOverrides` keyed by CSS variable (for example, a
99
+ text-editor shadow can use `'shadow'`). Existing `TierConfig.preview` metadata is reused.
100
+
101
+ `chrome="light"` and `chrome="dark"` fix the dashboard shell appearance;
102
+ `chrome="host"` inherits the host's effective `color-scheme` and requires the
103
+ host to set it on an ancestor. Chrome is independent of `mode`: `mode` selects
104
+ declared per-mode defaults and each specimen's own `color-scheme`, while chrome
105
+ uses package-owned CSS custom properties and never reads inventory variables.
106
+ The dashboard uses no media query, so an explicit application theme wins over
107
+ the OS preference.
108
+
109
+ Spacing uses actual-size rulers with local scrolling. Nonnegative px/rem, zero,
110
+ and resolved direct aliases are supported; other lengths keep a readable fallback.
111
+ Color-only nonsemantic, non-reference tiers form discrete strips in source order.
112
+ Typography uses wide multiline specimens; `previewText` supplies your static
113
+ passage (default: English/Japanese prose; an explicit empty string stays empty).
114
+ The baseline is 18px/1.6, with only the intended property changed and resolved
115
+ `previewBase` honored for line-height. Fonts use local availability and CSS
116
+ fallbacks. There is no editable text workbench.
117
+
118
+ The inventory uses **declared defaults**: item defaults, per-mode
119
+ `semanticDefaults`, and explicit base-role `baseDefaults`. It does not apply
120
+ named color presets, panel initialization, or persisted edits. CSS expressions
121
+ remain expressions; samples depend on browser layout and available fonts.
122
+ Missing/context-dependent references and invalid declarations remain readable
123
+ with diagnostics rather than misleading samples. The dashboard root's chrome
124
+ scheme follows `chrome`, while each specimen's `color-scheme` follows `mode`;
125
+ both are local to the instance, and the component never writes to `:root`.
126
+ Arbitrary notes HTML and URL/mask assets are not rendered or loaded.
127
+
128
+ This checkpoint provides a Preact component. An HTML-export API/CLI, React
129
+ adapter, and automatic panel-state synchronization are outside its scope.
130
+ See [`PORTABLE-CONTRACT.md` §12](./PORTABLE-CONTRACT.md#12-static-token-dashboard).
131
+
132
+ ---
133
+
41
134
  ## 0. Architecture at a glance
42
135
 
43
136
  The design-token panel is a browser-based UI that writes token overrides to
@@ -1,5 +1,5 @@
1
1
  import { c as y, g as m, a as w, b, i as P } from "../panel-config-Crn5QJGy.js";
2
- import { g, Z as A } from "../tweak-state-Dzr5kDhX.js";
2
+ import { g, Z as A } from "../tweak-state-Dhjqig0C.js";
3
3
  import { s as D, l as E, a as _, i as c, r as f, c as k, b as S, d } from "../autoload-state-CGnis85c.js";
4
4
  import { READABLE_STATE_KEY_SUFFIXES as T } from "../constants.js";
5
5
  const u = "tokenpanel-config";
@@ -18,6 +18,8 @@ export interface ColorFieldProps {
18
18
  * with the native <input type="color"> path).
19
19
  */
20
20
  valueFormat?: ColorPickerValueFormat;
21
+ /** Host color scheme used to resolve CSS expressions. */
22
+ resolveMode?: 'light' | 'dark';
21
23
  /** Display label shown in the picker header and aria-label. */
22
24
  label: string;
23
25
  /** Optional CSS custom property name (e.g. `--my-color`). Used for aria-label. */
@@ -33,5 +35,5 @@ export interface ColorFieldProps {
33
35
  *
34
36
  * Readonly items show the swatch but do not open the picker on interaction.
35
37
  */
36
- export declare function ColorField({ value, onChange, valueFormat, label, cssVar, readonly: isReadonly, }: ColorFieldProps): import("preact").JSX.Element;
38
+ export declare function ColorField({ value, onChange, valueFormat, resolveMode, label, cssVar, readonly: isReadonly, }: ColorFieldProps): import("preact").JSX.Element;
37
39
  export default ColorField;
@@ -48,6 +48,8 @@ export interface ColorPickerProps {
48
48
  * with existing callers that pass no value).
49
49
  */
50
50
  valueFormat?: ColorPickerValueFormat;
51
+ /** Host color scheme used to resolve CSS expressions. */
52
+ resolveMode?: 'light' | 'dark';
51
53
  /** Optional label rendered in the picker header. */
52
54
  label?: string;
53
55
  /**
@@ -93,5 +95,5 @@ export declare function usePopoverClose(containerRef: React.RefObject<HTMLElemen
93
95
  * The parent renders `{isOpen && <ColorPicker ... />}`. This component does
94
96
  * NOT render a trigger swatch and does NOT use createPortal.
95
97
  */
96
- export declare function ColorPicker({ color, onChange, valueFormat, label, defaultMode, anchorRef, onClose, }: ColorPickerProps): JSX.Element;
98
+ export declare function ColorPicker({ color, onChange, valueFormat, resolveMode, label, defaultMode, anchorRef, onClose, }: ColorPickerProps): JSX.Element;
97
99
  export default ColorPicker;
@@ -12,6 +12,7 @@ export interface SliderConfig {
12
12
  format: (v: number) => string;
13
13
  }
14
14
  export interface CustomSliderProps {
15
+ disabled?: boolean;
15
16
  config: SliderConfig;
16
17
  value: number;
17
18
  /** CSS gradient string applied to the track div's background. */
@@ -20,5 +21,5 @@ export interface CustomSliderProps {
20
21
  onDragStart: () => void;
21
22
  onDragEnd: () => void;
22
23
  }
23
- export declare function CustomSlider({ config, value, gradient, onChange, onDragStart, onDragEnd, }: CustomSliderProps): JSX.Element;
24
+ export declare function CustomSlider({ disabled, config, value, gradient, onChange, onDragStart, onDragEnd, }: CustomSliderProps): JSX.Element;
24
25
  export default CustomSlider;
@@ -0,0 +1,4 @@
1
+ export { TokenDashboard } from "./token-dashboard.js";
2
+ export type { TokenDashboardProps, DashboardPreviewKind } from "./token-dashboard.js";
3
+ export type { DashboardMode, DashboardChrome } from "./types.js";
4
+ export type { TabConfig, TierConfig, TierItem } from "../tokens/tier-model.js";