@takazudo/zdtp 0.4.3 → 0.4.4

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,51 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.4
4
+
5
+ ### Features
6
+
7
+ - **Ramp-native Tier-2 color editor.** The Color tab gained a semantic-value tier model — a `semantic: true` tier holds `SemanticValue` mappings (palette index, literal OKLCH, per-mode `light-dark()` literal, or a cross-tab ramp `{ ref }`) instead of raw palette entries, and can ship as a lone semantic tier with no palette tier at all ([#459](https://github.com/Takazudo/zudo-design-token-panel/issues/459), closes [#458](https://github.com/Takazudo/zudo-design-token-panel/issues/458)) ([8ed93e1](https://github.com/Takazudo/zudo-design-token-panel/pull/476))
8
+ - Add semantic-tier marker + `SemanticValue` union (S1) ([#460](https://github.com/Takazudo/zudo-design-token-panel/pull/460)) (d7aa526)
9
+ - serde `SCHEMA_V3` object leaves for `SemanticValue` variants (S5) ([#462](https://github.com/Takazudo/zudo-design-token-panel/pull/462)) (0185477)
10
+ - Render literal semantic rows as editable OKLCH swatches (S3) ([#464](https://github.com/Takazudo/zudo-design-token-panel/pull/464)) (d8bceb3)
11
+ - Emit literal semantic values verbatim in both emitters (S4) ([#465](https://github.com/Takazudo/zudo-design-token-panel/pull/465)) (5961ed7)
12
+ - Cross-tab ref resolution + tabs-array cluster-bridge signature (S7a) ([#467](https://github.com/Takazudo/zudo-design-token-panel/pull/467)) (35ef368)
13
+ - Emit cross-tab semantic refs as `var(--target)` in both emitters (S7b) ([#468](https://github.com/Takazudo/zudo-design-token-panel/pull/468)) (ea2aa8a)
14
+ - Validate cross-tab ramp-source declarations (S8) ([#469](https://github.com/Takazudo/zudo-design-token-panel/pull/469)) (8558269)
15
+ - Grouped ref-or-literal picker + wire color-tab semantic rows (S9) ([#470](https://github.com/Takazudo/zudo-design-token-panel/pull/470)) (3d5e5f7)
16
+ - Per-mode literal `light-dark()` emission + `defaultMode` runtime (S11) ([#472](https://github.com/Takazudo/zudo-design-token-panel/pull/472)) (3a05623)
17
+ - Per-mode light/dark literal editor UI (S12) ([#473](https://github.com/Takazudo/zudo-design-token-panel/pull/473)) (1828458)
18
+
19
+ ### Fixed
20
+
21
+ - Seed Scheme preset load against the instance cluster, not the global default ([#491](https://github.com/Takazudo/zudo-design-token-panel/issues/491) audit) (a1b0dd8)
22
+ - Thread `instanceConfig` into `ColorTab` for multi-instance ref resolution ([#491](https://github.com/Takazudo/zudo-design-token-panel/issues/491)) (66447ec)
23
+ - Validate semantic marker shape + mixed-order palette-pick regression tests ([#487](https://github.com/Takazudo/zudo-design-token-panel/pull/487)) (0ebcc6e)
24
+ - Scheme/preset load is a no-op for a palette-less color cluster ([#488](https://github.com/Takazudo/zudo-design-token-panel/pull/488)) (23d61ba)
25
+ - Color-scheme lifecycle asymmetries in the applied-state ([#482](https://github.com/Takazudo/zudo-design-token-panel/pull/482)) (ef686fc)
26
+ - serde robustness — order-independent ref diff, stale-ref warning, integer index leaves (c0b4356)
27
+ - Restore legacy index-0 fallback + detect named-color literals ([#483](https://github.com/Takazudo/zudo-design-token-panel/pull/483)) (4f66b7d)
28
+ - Show a disabled unresolved placeholder for a dangling `TierRefSelector` ref ([#484](https://github.com/Takazudo/zudo-design-token-panel/issues/484)) (a4c222b)
29
+ - Thread owning color tab into `buildApplyOverrides` for secondary-cluster refs (D1) ([#481](https://github.com/Takazudo/zudo-design-token-panel/pull/481)) (60cbb7a)
30
+ - Skip an unresolvable semantic `{ ref }` in the DOM emitter too (87131ee)
31
+ - Drop phantom grayscale swatch for palette-less semantic tier ([#466](https://github.com/Takazudo/zudo-design-token-panel/pull/466) follow-up) (c955616)
32
+ - Derive semantic maps for a palette-less semantic tier (S2b) ([#463](https://github.com/Takazudo/zudo-design-token-panel/pull/463)) (7d617d1)
33
+ - Honor semantic-tier marker in palette detection + F4 (S2a) ([#461](https://github.com/Takazudo/zudo-design-token-panel/pull/461)) (ecb4482)
34
+
35
+ ### Other Changes
36
+
37
+ - Eliminate intermittent vitest unhandled-error flake ([#494](https://github.com/Takazudo/zudo-design-token-panel/issues/494)) (ab60f91)
38
+ - e2e confirm per-mode literal `light-dark()` + clear color-scheme on reset (S13) ([#474](https://github.com/Takazudo/zudo-design-token-panel/pull/474)) (a215c88)
39
+ - e2e confirm cross-tab semantic ref cascade (S10) ([#471](https://github.com/Takazudo/zudo-design-token-panel/pull/471)) (235bb30)
40
+ - e2e confirm lone literal semantic tier unblocks [#458](https://github.com/Takazudo/zudo-design-token-panel/issues/458) (S6) ([#466](https://github.com/Takazudo/zudo-design-token-panel/pull/466)) (8fb5136)
41
+ - docs: translate token-manifest reference page to Japanese ([#490](https://github.com/Takazudo/zudo-design-token-panel/issues/490), [#478](https://github.com/Takazudo/zudo-design-token-panel/issues/478)) (7bcd835)
42
+ - docs: translate color-cluster reference to Japanese ([#489](https://github.com/Takazudo/zudo-design-token-panel/issues/489), [#478](https://github.com/Takazudo/zudo-design-token-panel/issues/478)) (e033410)
43
+ - docs: fix EN documentation drift from [#459](https://github.com/Takazudo/zudo-design-token-panel/issues/459) (referencesRamps, bridge signature, color-scheme caveat) (a7d8709)
44
+ - docs: document ramp-native Tier-2 editor + example manifest + cascade test (S14) ([#475](https://github.com/Takazudo/zudo-design-token-panel/pull/475)) (136bcf6)
45
+ - docs: fix broken `SemanticValue` heading anchor (drop em-dash from slug) (ef3cd91)
46
+ - chore(deps): bump `@takazudo/zudo-doc` and `zudo-doc-history-server` to `^2.5.1` (d6c05dd)
47
+ - chore(doc): sync generated `claude/index.mdx` with build output (d763238)
48
+
3
49
  ## 0.4.3
4
50
 
5
51
  ### Features
@@ -30,9 +30,17 @@
30
30
  * - Palette slots (resolved via `resolvePaletteCssVar(cluster, i)`) —
31
31
  * EMITTED as the stored color value (hex, or `oklch(...)` for
32
32
  * oklch-format palettes).
33
- * - Semantic tokens (`cluster.semanticCssNames` entries) — EMITTED as
34
- * `var(--<paletteSlotName>)` so the rewrite preserves the indirection
35
- * that the hand-authored CSS relies on.
33
+ * - Semantic tokens (`cluster.semanticCssNames` entries) — a legacy
34
+ * index/`bg`/`fg` mapping is EMITTED as `var(--<paletteSlotName>)` so the
35
+ * rewrite preserves the indirection that the hand-authored CSS relies on.
36
+ * A single-mode `{ literal: string }` mapping (#465) is instead EMITTED
37
+ * VERBATIM as the literal CSS value — there is no palette slot to
38
+ * reference. A cross-tab/tier `{ ref }` mapping (#468) is resolved via
39
+ * `resolveRefToCssVar` against the panel's full `tabs` array and EMITTED
40
+ * as `var(--<resolved-target>)`. Per-mode `{ literal: { light, dark } }`
41
+ * (#472) is EMITTED as `light-dark(<light>, <dark>)`, byte-identical to
42
+ * the DOM emitter (the required `color-scheme: light dark` is NOT settable
43
+ * via this pipeline — see the per-mode branch below for why).
36
44
  * - Base roles (`cluster.baseRoles` entries) — NOT emitted. They do not
37
45
  * belong to the apply pipeline's rewrite scope.
38
46
  * - Spacing / typography / size — EMITTED when the corresponding
@@ -68,5 +76,13 @@ import type { TabConfig } from '../tokens/tier-model';
68
76
  *
69
77
  * `tabs` defaults to the active panel config's tab list. Injected by tests so
70
78
  * non-color token resolution works without a live panel config singleton.
79
+ *
80
+ * `currentTab` is the color TabConfig `state.color`'s semantic mappings live
81
+ * on — needed so a cross-tab/tier `{ ref }` mapping (#468) with an omitted
82
+ * `ref.tab` resolves against the RIGHT tab. Defaults to the `'color'` tab
83
+ * (primary-cluster behavior, unchanged). Secondary-cluster callers MUST pass
84
+ * the `'color-secondary'` tab explicitly — mirroring the DOM emitter's
85
+ * `applyFullState`/`applyColorState` `currentTab` threading
86
+ * (`state/tweak-state.ts`).
71
87
  */
72
- export declare function buildApplyOverrides(state: TweakState, colorDefaults: ColorTweakState | undefined, cluster?: ColorClusterConfig, tabs?: readonly TabConfig[]): Record<string, string>;
88
+ export declare function buildApplyOverrides(state: TweakState, colorDefaults: ColorTweakState | undefined, cluster?: ColorClusterConfig, tabs?: readonly TabConfig[], currentTab?: TabConfig | undefined): Record<string, string>;
@@ -72,3 +72,31 @@ export declare function resolveTierItemValue(tab: TabConfig, tierId: string, ite
72
72
  * - Ref → returns `var(--targetCssVar)` (e.g. `var(--zfb-easing-ease-in)`).
73
73
  */
74
74
  export declare function emitTierItemCssValue(resolved: ResolvedTierItem): string;
75
+ /**
76
+ * A `SemanticValue`'s cross-tab ramp reference: names a target ramp item by
77
+ * `{ tab?, tier, item }`. An omitted `tab` means "the current tab" (intra-tab,
78
+ * back-compat). Mirrors the `{ ref }` variant of `SemanticValue` in
79
+ * `tokens/tier-model.ts`.
80
+ */
81
+ export type CrossTabRef = {
82
+ tab?: string;
83
+ tier: string;
84
+ item: string;
85
+ };
86
+ /**
87
+ * Resolve a `{ tab?, tier, item }` reference to the target item's `cssVar`
88
+ * so a downstream emitter (#468) can write `var(--target-cssvar)`.
89
+ *
90
+ * Resolution:
91
+ * - `tab` omitted (or equal to `currentTab.id`) → resolve within
92
+ * `currentTab` (intra-tab; keeps a lone-tab caller working with the
93
+ * default `tabs = [currentTab]`).
94
+ * - `tab` set → look the target tab up by id in `tabs` (the panel config's
95
+ * full tabs array), then find `tier` in it, then `item` in that tier.
96
+ *
97
+ * Throws `TierResolverError` with a precise message when the target tab, tier,
98
+ * or item does not exist. This is the single reachable cross-tab lookup path;
99
+ * #468 wraps the returned cssVar in `var(...)` and #469 validates source
100
+ * declarations up front.
101
+ */
102
+ export declare function resolveRefToCssVar(ref: CrossTabRef, currentTab: TabConfig, tabs?: readonly TabConfig[]): string;
@@ -1,6 +1,6 @@
1
- import { c as h, g as u, a as g, b as w, d as y, e as P } from "../panel-config-3tBEHjvZ.js";
2
- import { g as d, Z as b } from "../tweak-state-BEx1SHu7.js";
3
- import { s as _, l as A, a as c, c as k, b as I } from "../autoload-state-B1MWY_Pp.js";
1
+ import { c as h, g as u, a as g, b as w, d as y, e as P } from "../panel-config-CXTCcYQs.js";
2
+ import { g as d, Z as b } from "../tweak-state-BeXkzoj8.js";
3
+ import { s as _, l as A, a as c, c as k, b as I } from "../autoload-state-CmhI7q9j.js";
4
4
  const l = "tokenpanel-config";
5
5
  function E() {
6
6
  if (typeof document > "u")
@@ -1,4 +1,4 @@
1
- import { s as t } from "../panel-config-3tBEHjvZ.js";
1
+ import { s as t } from "../panel-config-CXTCcYQs.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, j as o } from "./panel-config-3tBEHjvZ.js";
1
+ import { g as a, j as o } from "./panel-config-CXTCcYQs.js";
2
2
  function n(e = a()) {
3
3
  return `${e.storagePrefix}-elpath-enabled`;
4
4
  }
@@ -21,6 +21,8 @@
21
21
  * `panelConfig.colorCluster`.
22
22
  */
23
23
  import type { ColorScheme } from './color-schemes';
24
+ import type { SemanticValue } from '../tokens/tier-model';
25
+ export type { SemanticValue } from '../tokens/tier-model';
24
26
  /**
25
27
  * Base-role keys that a cluster may declare. Subset is allowed (a cluster may
26
28
  * ship zero base roles when its design system doesn't expose them as tokens).
@@ -76,8 +78,16 @@ export interface ColorClusterDataConfig {
76
78
  * `--brand-p{n}`, `--demo-palette-{n}`.
77
79
  */
78
80
  paletteCssVarTemplate: string;
79
- /** Semantic token name → default palette index. */
80
- semanticDefaults: Record<string, number>;
81
+ /**
82
+ * Semantic token name → default mapping. Historically always a palette
83
+ * index (`number`); widened to `SemanticValue` (#459) so a default can also
84
+ * be a literal color or a cross-tab ramp reference. `resolveColorClusterFromTab`
85
+ * now derives the `{ literal }` / best-effort `{ ref }` variants too (#463)
86
+ * for a `semantic: true` tier; actually resolving a `{ ref }` against the
87
+ * ramp tier it names (rendering + apply) is still downstream work
88
+ * (#467/#469).
89
+ */
90
+ semanticDefaults: Record<string, SemanticValue>;
81
91
  /** Semantic token name → CSS custom-property name. */
82
92
  semanticCssNames: Record<string, string>;
83
93
  /** Fallback indices used when a scheme doesn't declare a base role. */
@@ -104,23 +114,36 @@ import type { TabConfig } from '../tokens/tier-model';
104
114
  /**
105
115
  * Derive a `ColorClusterDataConfig` from a color `TabConfig`.
106
116
  *
107
- * - Palette items: the first tier whose items all have `kind: 'color'`.
108
- * Each item's `cssVar` becomes a palette slot; `paletteCssVarTemplate` is
109
- * synthesised as `"{item.cssVar}"` with `{n}` replaced by the slot index.
110
- * Because item cssVars are explicit (e.g. `--zfb-palette-0`) rather
111
- * than template-based, we derive the template from the first item by
112
- * replacing the terminal digit sequence with `{n}`.
117
+ * - Palette items: the first tier whose items all have `kind: 'color'` and
118
+ * are not `semantic: true`. Each item's `cssVar` becomes a palette slot;
119
+ * `paletteCssVarTemplate` is synthesised as `"{item.cssVar}"` with `{n}`
120
+ * replaced by the slot index. Because item cssVars are explicit (e.g.
121
+ * `--zfb-palette-0`) rather than template-based, we derive the template
122
+ * from the first item by replacing the terminal digit sequence with `{n}`.
113
123
  *
114
- * - Semantic items: the first tier with `referencesTier` set pointing at the
115
- * palette tier. Each item's `id` → `cssVar` mapping becomes `semanticCssNames`;
116
- * the item's `default` (a palette item id) is looked up to produce the index
117
- * for `semanticDefaults`.
124
+ * - Semantic items: either the first tier with `referencesTier` set pointing
125
+ * at the palette tier (legacy shape), or a tier explicitly marked
126
+ * `semantic: true` (#461) — the latter may have no palette sibling at all.
127
+ * Each item's `id` → `cssVar` mapping becomes `semanticCssNames`; the
128
+ * item's `default` is resolved to a `SemanticValue` by
129
+ * `deriveSemanticValue` (palette index / literal / ramp-ref — see there).
130
+ *
131
+ * - A tab with a semantic tier but NO palette tier still produces a usable
132
+ * cluster: `paletteSize` is `0` (the palette-driven UI has nothing to
133
+ * render) but `semanticDefaults`/`semanticCssNames` are populated from the
134
+ * semantic tier so the Semantic Tokens section isn't left empty (#463).
118
135
  *
119
136
  * - Metadata comes from `tab.colorExtras` (required on a color tab).
120
137
  *
138
+ * `tabs` is the panel config's full tabs array, used to resolve a semantic
139
+ * tier's cross-tab `{ ref }` mappings against a ramp tier living in ANOTHER
140
+ * tab (typically the grouped Palette tab). It defaults to `[tab]` so an
141
+ * existing single-argument call still works — intra-tab refs resolve, and a
142
+ * cross-tab ramp declaration falls back to its best-effort shape (#467).
143
+ *
121
144
  * Returns `undefined` when the tab has no `colorExtras` (not a color tab).
122
145
  */
123
- export declare function resolveColorClusterFromTab(tab: TabConfig): ColorClusterDataConfig | undefined;
146
+ export declare function resolveColorClusterFromTab(tab: TabConfig, tabs?: readonly TabConfig[]): ColorClusterDataConfig | undefined;
124
147
  /**
125
148
  * Find the primary color tab (id 'color') in the host's tabs array and
126
149
  * derive its `ColorClusterDataConfig`. Returns `undefined` when no color tab
@@ -1,38 +1,82 @@
1
1
  import type { TabConfig } from '../tokens/tier-model';
2
2
  /**
3
- * Sentinel string passed to `onChange` when the user picks "Literal...".
4
- * The parent component interprets this as a request to flip the item back
5
- * into its kind-specific editor (slider / text / select) writing a literal
6
- * CSS override.
3
+ * Names one item in a (possibly cross-tab) tier. `tab` omitted means "the tab
4
+ * `TierRefSelector` itself renders in" — the intra-tab case used by the
5
+ * font/spacing/size/generic-tab consumers, whose refs never cross tabs.
7
6
  */
8
- export declare const TIER_REF_LITERAL_SIGNAL: "__literal__";
7
+ export interface TierRefTarget {
8
+ tab?: string;
9
+ tier: string;
10
+ item: string;
11
+ }
12
+ /**
13
+ * The value `TierRefSelector` reads and writes. Mirrors the `{ ref } | {
14
+ * literal }` variants of `SemanticValue` (`tokens/tier-model.ts`) — including
15
+ * the per-mode `{ literal: { light, dark } }` shape (#472/#473) — so the
16
+ * Color tab can pass a semantic mapping straight through. Flat/intra-tab
17
+ * consumers (font/spacing/size/generic-tab) wrap their bare `TokenOverrides`
18
+ * string into `{ ref: { tier, item } }` at the call site, and unwrap a
19
+ * `{ literal }` response back into "drop the override" — see those tabs'
20
+ * `onChange` handlers. Those flat consumers never produce a per-mode literal.
21
+ */
22
+ export type TierRefSelectorValue = {
23
+ ref: TierRefTarget;
24
+ } | {
25
+ literal: string;
26
+ } | {
27
+ literal: {
28
+ light: string;
29
+ dark: string;
30
+ };
31
+ };
9
32
  export interface TierRefSelectorProps {
10
- /** Full tab config — needed to look up the referenced tier and its items. */
33
+ /** The tab this row belongs to — provides the semantic/reference tier
34
+ * config and doubles as the default "current tab" for intra-tab refs. */
11
35
  tab: TabConfig;
12
- /** The tier whose item is being edited (the "semantic" / reference tier). */
36
+ /**
37
+ * Full panel tabs array, needed to resolve a grouped tier's cross-tab ramp
38
+ * sources. Defaults to `[tab]` — fine for intra-tab (flat) callers, which
39
+ * never reference another tab.
40
+ */
41
+ tabs?: readonly TabConfig[];
42
+ /** The tier whose item is being edited (the semantic / reference tier). */
13
43
  tierId: string;
14
44
  /** The item being edited within `tierId`. */
15
45
  itemId: string;
46
+ /** Current value — a ramp/ref target, or a literal color/CSS string. */
47
+ value: TierRefSelectorValue;
16
48
  /**
17
- * The current stored value for this item — an item id within the
18
- * referenced (tier-1) tier. Empty string or an unrecognised id is treated
19
- * as "pick the first item" (mirrors resolver fallback).
49
+ * Called when the user commits a selection or edits the literal value.
50
+ *
51
+ * - Picking a ramp/ref option: `onChange(itemId, { ref: {...} })`
52
+ * - Picking "Literal…" or editing the literal swatch (grouped mode only):
53
+ * `onChange(itemId, { literal: <value> })`
20
54
  */
21
- value: string;
55
+ onChange: (itemId: string, next: TierRefSelectorValue) => void;
22
56
  /**
23
- * Called when the user commits a selection.
24
- *
25
- * - Picking a tier-1 item: `onChange(itemId, selectedRefItemId)`
26
- * - Picking "Literal...": `onChange(itemId, TIER_REF_LITERAL_SIGNAL)`
57
+ * Returns the resolved (override-aware) preview string for a ramp/ref
58
+ * target. Each option label is formatted as `${item.cssVar} (${truncated
59
+ * preview})`. Falls back to the target item's manifest `default` when
60
+ * omitted.
61
+ */
62
+ previewValueFor?: (ref: TierRefTarget) => string;
63
+ /**
64
+ * Friendly label used for the literal-mode `ColorField` editor (grouped
65
+ * mode only) and the select's `aria-label`. Defaults to `itemId`.
66
+ */
67
+ label?: string;
68
+ /**
69
+ * The row's own cssVar — threaded into the literal-mode `ColorField`
70
+ * editor for its `aria-label`, matching `SemanticLiteralRow`'s convention.
27
71
  */
28
- onChange: (itemId: string, next: string) => void;
72
+ cssVar?: string;
29
73
  /**
30
- * Returns the resolved (override-aware) preview string for a tier-1 item id.
31
- * Each option label is formatted as `${item.cssVar} (${truncated preview})`.
32
- * Pass a wrapper around resolveTierItemValue using the current tweak-state map.
74
+ * The cluster's `getClusterDefaultMode()` result (#472) — used only when
75
+ * the user collapses a per-mode literal back to single-mode, to pick which
76
+ * side (`light` or `dark`) survives. Defaults to `'light'`.
33
77
  */
34
- previewValueFor: (refItemId: string) => string;
78
+ defaultMode?: 'light' | 'dark';
35
79
  }
36
- declare function TierRefSelector({ tab, tierId, itemId, value, onChange, previewValueFor }: TierRefSelectorProps): import("preact").JSX.Element;
80
+ declare function TierRefSelector({ tab, tabs, tierId, itemId, value, onChange, previewValueFor, label, cssVar, defaultMode, }: TierRefSelectorProps): import("preact").JSX.Element;
37
81
  declare const _default: typeof TierRefSelector;
38
82
  export default _default;
package/dist/index.d.ts CHANGED
@@ -60,6 +60,7 @@ export type { TierValueKind, PillSpec, TierItem, TierConfig, TabConfig, ColorClu
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';
63
+ export { getClusterDefaultMode, resolvePerModeLiteral, resolveSemanticPreviewColor, } from './state/tweak-state';
63
64
  export declare function showDesignTokenPanel(): void;
64
65
  export declare function hideDesignTokenPanel(): void;
65
66
  export declare function toggleDesignPanel(): void;