@unpunnyfuns/swatchbook-blocks 0.55.0 → 0.56.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/dist/index.d.mts +33 -51
- package/dist/index.mjs +169 -167
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as _$react from "react";
|
|
2
2
|
import { ReactElement, ReactNode } from "react";
|
|
3
|
-
import { Axis, AxisVarianceResult, Diagnostic,
|
|
3
|
+
import { Axis, AxisVarianceResult, Diagnostic, Preset } from "@unpunnyfuns/swatchbook-core";
|
|
4
|
+
import { SlimListedToken } from "@unpunnyfuns/swatchbook-core/snapshot-for-wire";
|
|
4
5
|
|
|
5
6
|
//#region src/format-color.d.ts
|
|
6
7
|
/**
|
|
@@ -65,15 +66,27 @@ declare function formatColor(value: unknown, format: ColorFormat, fallback?: str
|
|
|
65
66
|
* in `packages/addon/src/virtual.d.ts` describe the same payload.
|
|
66
67
|
*/
|
|
67
68
|
type VirtualAxisShape = Axis;
|
|
68
|
-
type VirtualPermutationShape = Permutation;
|
|
69
69
|
type VirtualDiagnosticShape = Diagnostic;
|
|
70
70
|
interface VirtualTokenShape {
|
|
71
|
-
$type?: string;
|
|
71
|
+
$type?: string | undefined;
|
|
72
72
|
$value?: unknown;
|
|
73
|
-
$description?: string;
|
|
74
|
-
aliasOf?: string;
|
|
75
|
-
aliasChain?: readonly string[];
|
|
76
|
-
aliasedBy?: readonly string[];
|
|
73
|
+
$description?: string | undefined;
|
|
74
|
+
aliasOf?: string | undefined;
|
|
75
|
+
aliasChain?: readonly string[] | undefined;
|
|
76
|
+
aliasedBy?: readonly string[] | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Per-sub-field alias map for composite tokens whose value blends
|
|
79
|
+
* primitives with aliased fragments — Terrazzo populates this when
|
|
80
|
+
* one or more component fields of a composite ($type: 'border',
|
|
81
|
+
* 'shadow', 'typography', 'gradient', 'transition') resolve through
|
|
82
|
+
* an alias. The `CompositeBreakdown` block reads it to render the
|
|
83
|
+
* source path beside each component value. Typed as `unknown` because
|
|
84
|
+
* the shape varies per composite type (color carries a
|
|
85
|
+
* `{components: (string | undefined)[]}` sub-shape; typography/border
|
|
86
|
+
* carry a flat `Record<string, string | undefined>`); the block
|
|
87
|
+
* narrows it at the consumer.
|
|
88
|
+
*/
|
|
89
|
+
partialAliasOf?: unknown;
|
|
77
90
|
}
|
|
78
91
|
/**
|
|
79
92
|
* Subset of `@terrazzo/plugin-token-listing`'s `ListedToken` that the
|
|
@@ -81,28 +94,11 @@ interface VirtualTokenShape {
|
|
|
81
94
|
* variable name and `previewValue` for the display-ready CSS string.
|
|
82
95
|
* `source.loc` enables "jump to authoring source" affordances.
|
|
83
96
|
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
97
|
+
* Aliases `SlimListedToken` from core's `/snapshot-for-wire` subpath —
|
|
98
|
+
* the single canonical wire shape; both the addon's plugin (server-side
|
|
99
|
+
* emit) and blocks (consumer-side read) reference the same definition.
|
|
86
100
|
*/
|
|
87
|
-
|
|
88
|
-
names: Record<string, string>;
|
|
89
|
-
previewValue?: string | number;
|
|
90
|
-
source?: {
|
|
91
|
-
resource: string;
|
|
92
|
-
loc?: {
|
|
93
|
-
start: {
|
|
94
|
-
line: number;
|
|
95
|
-
column: number;
|
|
96
|
-
offset: number;
|
|
97
|
-
};
|
|
98
|
-
end: {
|
|
99
|
-
line: number;
|
|
100
|
-
column: number;
|
|
101
|
-
offset: number;
|
|
102
|
-
};
|
|
103
|
-
};
|
|
104
|
-
};
|
|
105
|
-
}
|
|
101
|
+
type VirtualTokenListingShape = SlimListedToken;
|
|
106
102
|
type VirtualPresetShape = Preset;
|
|
107
103
|
/**
|
|
108
104
|
* Wire shape of one `Project.jointOverrides` entry — same as core's
|
|
@@ -116,7 +112,7 @@ interface VirtualJointOverrideShape {
|
|
|
116
112
|
/**
|
|
117
113
|
* Map from path → cached `AxisVarianceResult`. Snapshot carries this
|
|
118
114
|
* so the `AxisVariance` block can O(1) look up which axes affect a
|
|
119
|
-
* token instead of re-running
|
|
115
|
+
* token instead of re-running variance analysis on every render.
|
|
120
116
|
*/
|
|
121
117
|
type VirtualVarianceByPathShape = Record<string, AxisVarianceResult>;
|
|
122
118
|
/**
|
|
@@ -129,17 +125,6 @@ interface ProjectSnapshot {
|
|
|
129
125
|
/** Axis names suppressed via `config.disabledAxes` — pinned to their defaults, hidden from the toolbar. */
|
|
130
126
|
disabledAxes: readonly string[];
|
|
131
127
|
presets: readonly VirtualPresetShape[];
|
|
132
|
-
/**
|
|
133
|
-
* @deprecated Wire-shipped permutations were removed in PR 6a.
|
|
134
|
-
* Hand-built snapshots (tests, MDX consumers) may still populate
|
|
135
|
-
* this for backward compatibility with the legacy fallback path
|
|
136
|
-
* in `useProject`. Production preview snapshots omit it.
|
|
137
|
-
*/
|
|
138
|
-
permutations?: readonly VirtualPermutationShape[];
|
|
139
|
-
/**
|
|
140
|
-
* @deprecated See `permutations`. Wire format dropped in PR 6a.
|
|
141
|
-
*/
|
|
142
|
-
permutationsResolved?: Record<string, Record<string, VirtualTokenShape>>;
|
|
143
128
|
activePermutation: string;
|
|
144
129
|
activeAxes: Readonly<Record<string, string>>;
|
|
145
130
|
cssVarPrefix: string;
|
|
@@ -157,26 +142,23 @@ interface ProjectSnapshot {
|
|
|
157
142
|
* Per-axis cell maps — `cells[axis][context]` is the resolved token
|
|
158
143
|
* data for `{ ...defaults, [axis]: context }`. Bounded by
|
|
159
144
|
* `Σ(axes × contexts)` regardless of cartesian product size.
|
|
160
|
-
*
|
|
161
|
-
*
|
|
145
|
+
* Non-default cells store only the tokens whose value differs from
|
|
146
|
+
* the default-cell baseline (delta cells).
|
|
162
147
|
*/
|
|
163
|
-
cells
|
|
148
|
+
cells: Record<string, Record<string, Record<string, VirtualTokenShape>>>;
|
|
164
149
|
/**
|
|
165
150
|
* `Project.jointOverrides` flattened to entries for wire transport.
|
|
166
151
|
* Same ascending-arity iteration order the Map carries on the
|
|
167
|
-
* server side.
|
|
152
|
+
* server side. Empty array when no joint divergences exist.
|
|
168
153
|
*/
|
|
169
|
-
jointOverrides
|
|
154
|
+
jointOverrides: readonly (readonly [string, VirtualJointOverrideShape])[];
|
|
170
155
|
/**
|
|
171
156
|
* Cached per-path variance results. Blocks read this for O(1) axis
|
|
172
157
|
* variance lookup instead of recomputing on each render.
|
|
173
158
|
*/
|
|
174
159
|
varianceByPath?: VirtualVarianceByPathShape;
|
|
175
|
-
/**
|
|
176
|
-
|
|
177
|
-
* Replaces the legacy "look at `permutations[0].input`" pattern.
|
|
178
|
-
*/
|
|
179
|
-
defaultTuple?: Record<string, string>;
|
|
160
|
+
/** The default tuple — `{ axis: axis.default }` for every axis. */
|
|
161
|
+
defaultTuple: Record<string, string>;
|
|
180
162
|
/**
|
|
181
163
|
* Pre-built `resolveAt(tuple)` accessor. The addon's preview
|
|
182
164
|
* decorator instantiates this once per iframe lifetime — the
|
|
@@ -901,5 +883,5 @@ declare function TypographyScale({
|
|
|
901
883
|
sortDir
|
|
902
884
|
}: TypographyScaleProps): ReactElement;
|
|
903
885
|
//#endregion
|
|
904
|
-
export { AliasChain, type AliasChainProps, AliasedBy, type AliasedByProps, AxesContext, AxisVariance, type AxisVarianceProps, BorderPreview, type BorderPreviewProps, BorderSample, type BorderSampleProps, COLOR_FORMATS, type ColorFormat, ColorFormatContext, ColorPalette, type ColorPaletteProps, ColorTable, type ColorTableProps, CompositeBreakdown, type CompositeBreakdownProps, CompositePreview, type CompositePreviewProps, ConsumerOutput, type ConsumerOutputProps, Diagnostics, type DiagnosticsProps, DimensionBar, type DimensionBarProps, type DimensionKind, DimensionScale, type DimensionScaleProps, FontFamilySample, type FontFamilySampleProps, FontWeightScale, type FontWeightScaleProps, type FormatColorResult, GradientPalette, type GradientPaletteProps, MotionPreview, type MotionPreviewProps, MotionSample, type MotionSampleProps, type MotionSpeed, type NormalizedColor, OpacityScale, type OpacityScaleProps, PermutationContext, type ProjectSnapshot, ShadowPreview, type ShadowPreviewProps, ShadowSample, type ShadowSampleProps, StrokeStyleSample, type StrokeStyleSampleProps, SwatchbookContext, SwatchbookProvider, type SwatchbookProviderProps, TokenDetail, type TokenDetailProps, TokenHeader, type TokenHeaderProps, TokenNavigator, type TokenNavigatorProps, TokenTable, type TokenTableProps, TokenUsageSnippet, type TokenUsageSnippetProps, TypographyScale, type TypographyScaleProps, type VirtualAxisShape as VirtualAxis, type VirtualAxisShape, type VirtualDiagnosticShape as VirtualDiagnostic, type VirtualDiagnosticShape, type
|
|
886
|
+
export { AliasChain, type AliasChainProps, AliasedBy, type AliasedByProps, AxesContext, AxisVariance, type AxisVarianceProps, BorderPreview, type BorderPreviewProps, BorderSample, type BorderSampleProps, COLOR_FORMATS, type ColorFormat, ColorFormatContext, ColorPalette, type ColorPaletteProps, ColorTable, type ColorTableProps, CompositeBreakdown, type CompositeBreakdownProps, CompositePreview, type CompositePreviewProps, ConsumerOutput, type ConsumerOutputProps, Diagnostics, type DiagnosticsProps, DimensionBar, type DimensionBarProps, type DimensionKind, DimensionScale, type DimensionScaleProps, FontFamilySample, type FontFamilySampleProps, FontWeightScale, type FontWeightScaleProps, type FormatColorResult, GradientPalette, type GradientPaletteProps, MotionPreview, type MotionPreviewProps, MotionSample, type MotionSampleProps, type MotionSpeed, type NormalizedColor, OpacityScale, type OpacityScaleProps, PermutationContext, type ProjectSnapshot, ShadowPreview, type ShadowPreviewProps, ShadowSample, type ShadowSampleProps, StrokeStyleSample, type StrokeStyleSampleProps, SwatchbookContext, SwatchbookProvider, type SwatchbookProviderProps, TokenDetail, type TokenDetailProps, TokenHeader, type TokenHeaderProps, TokenNavigator, type TokenNavigatorProps, TokenTable, type TokenTableProps, TokenUsageSnippet, type TokenUsageSnippetProps, TypographyScale, type TypographyScaleProps, type VirtualAxisShape as VirtualAxis, type VirtualAxisShape, type VirtualDiagnosticShape as VirtualDiagnostic, type VirtualDiagnosticShape, type VirtualPresetShape as VirtualPreset, type VirtualPresetShape, type VirtualTokenShape as VirtualToken, type VirtualTokenShape, type VirtualTokenListingShape, formatColor, useActiveAxes, useActivePermutation, useColorFormat, useOptionalSwatchbookData, useSwatchbookData };
|
|
905
887
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -3,9 +3,10 @@ import Color from "colorjs.io";
|
|
|
3
3
|
import { Fragment, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
4
4
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { buildResolveAt } from "@unpunnyfuns/swatchbook-core/resolve-at";
|
|
6
|
-
import {
|
|
6
|
+
import { makeCssVar } from "@unpunnyfuns/swatchbook-core/css-var";
|
|
7
7
|
import { addons } from "storybook/preview-api";
|
|
8
8
|
import { axes, cells, css, cssVarPrefix, defaultTuple, diagnostics, jointOverrides, listing, presets, varianceByPath } from "virtual:swatchbook/tokens";
|
|
9
|
+
import { dataAttr } from "@unpunnyfuns/swatchbook-core/data-attr";
|
|
9
10
|
import { fuzzyFilter } from "@unpunnyfuns/swatchbook-core/fuzzy";
|
|
10
11
|
import cx from "clsx";
|
|
11
12
|
//#region src/format-color.ts
|
|
@@ -56,7 +57,8 @@ function coerce(value) {
|
|
|
56
57
|
return null;
|
|
57
58
|
}
|
|
58
59
|
const alpha = typeof v.alpha === "number" ? v.alpha : void 0;
|
|
59
|
-
const
|
|
60
|
+
const hexVal = v["hex"];
|
|
61
|
+
const hex = typeof hexVal === "string" ? hexVal : void 0;
|
|
60
62
|
return {
|
|
61
63
|
colorSpace,
|
|
62
64
|
components,
|
|
@@ -217,33 +219,23 @@ function ensureSubscribed$1() {
|
|
|
217
219
|
if (subscribed$1 || typeof window === "undefined") return;
|
|
218
220
|
subscribed$1 = true;
|
|
219
221
|
const channel = addons.getChannel();
|
|
222
|
+
let lastFingerprint = "";
|
|
220
223
|
const onGlobals = (payload) => {
|
|
221
224
|
const globals = payload.globals;
|
|
222
225
|
if (!globals) return;
|
|
223
|
-
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
226
|
+
const incomingAxes = globals[AXES_GLOBAL_KEY];
|
|
227
|
+
const incomingFormat = globals[COLOR_FORMAT_GLOBAL_KEY];
|
|
228
|
+
const nextAxes = incomingAxes && typeof incomingAxes === "object" ? incomingAxes : snapshot$1.axes;
|
|
229
|
+
const nextFormat = isColorFormat(incomingFormat) ? incomingFormat : snapshot$1.format;
|
|
230
|
+
const fingerprint = `${nextFormat ?? ""}|${nextAxes ? JSON.stringify(nextAxes) : ""}`;
|
|
231
|
+
if (fingerprint === lastFingerprint) return;
|
|
232
|
+
lastFingerprint = fingerprint;
|
|
233
|
+
snapshot$1 = {
|
|
234
|
+
axes: nextAxes,
|
|
232
235
|
format: nextFormat
|
|
233
236
|
};
|
|
234
|
-
|
|
235
|
-
snapshot$1 = next;
|
|
236
|
-
for (const cb of listeners$1) cb();
|
|
237
|
-
}
|
|
237
|
+
for (const cb of listeners$1) cb();
|
|
238
238
|
};
|
|
239
|
-
/**
|
|
240
|
-
* `setGlobals` fires once on preview init carrying the URL-persisted user
|
|
241
|
-
* globals (Storybook stores toolbar selections in `?globals=…`). Without
|
|
242
|
-
* this listener, deeplinking to an MDX page with a non-default axis tuple
|
|
243
|
-
* or color format renders defaults for one frame before the first
|
|
244
|
-
* `updateGlobals` arrives. `emitGlobals()` reads from `userGlobals.get()`
|
|
245
|
-
* (current state), so the payload is never stale — safe to handle.
|
|
246
|
-
*/
|
|
247
239
|
channel.on("globalsUpdated", onGlobals);
|
|
248
240
|
channel.on("updateGlobals", onGlobals);
|
|
249
241
|
channel.on("setGlobals", onGlobals);
|
|
@@ -408,44 +400,24 @@ function defaultTuple$1(axes) {
|
|
|
408
400
|
return out;
|
|
409
401
|
}
|
|
410
402
|
/**
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
403
|
+
* Synthesize a permutation name from a tuple — same form
|
|
404
|
+
* `permutationID` produces server-side (axis values joined by ` · `).
|
|
405
|
+
* Used by the AxisVariance grid for `data-<prefix>-theme` attribution
|
|
406
|
+
* and similar display-only callers.
|
|
414
407
|
*/
|
|
415
|
-
function
|
|
416
|
-
return
|
|
408
|
+
function tupleToName(axes, tuple) {
|
|
409
|
+
return axes.map((a) => tuple[a.name] ?? a.default).join(" · ");
|
|
417
410
|
}
|
|
418
411
|
/**
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
|
|
424
|
-
function buildPermutationNameByTuple(permutations) {
|
|
425
|
-
const out = /* @__PURE__ */ new Map();
|
|
426
|
-
for (const perm of permutations) out.set(canonicalTupleKey(perm.input), perm.name);
|
|
427
|
-
return out;
|
|
428
|
-
}
|
|
429
|
-
const noPermutationName = () => void 0;
|
|
430
|
-
function tuplesEqual(a, b) {
|
|
431
|
-
const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
|
|
432
|
-
for (const k of keys) if (a[k] !== b[k]) return false;
|
|
433
|
-
return true;
|
|
434
|
-
}
|
|
435
|
-
function nameForTuple(themesList, tuple) {
|
|
436
|
-
return themesList.find((t) => tuplesEqual(t.input, tuple))?.name;
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
* Reconstruct a `resolveAt` accessor from snapshot data. The wire
|
|
440
|
-
* format ships `cells` as plain JSON and `jointOverrides` as an
|
|
441
|
-
* array of `[key, entry]` pairs (Map doesn't survive JSON.stringify);
|
|
442
|
-
* this hydrates them and wraps `buildResolveAt` from core. Stable
|
|
443
|
-
* identity across calls with the same snapshot — `useMemo` keyed on
|
|
444
|
-
* the snapshot fields produces a referentially stable function.
|
|
412
|
+
* Reconstruct a `resolveAt` accessor from snapshot data. Both `cells`
|
|
413
|
+
* and `jointOverrides` ship as plain JSON in the same shape core uses
|
|
414
|
+
* internally — no Map reconstruction at the boundary. Stable identity
|
|
415
|
+
* across calls with the same snapshot — `useMemo` keyed on the
|
|
416
|
+
* snapshot fields produces a referentially stable function.
|
|
445
417
|
*/
|
|
446
418
|
function makeResolveAt(snapshot) {
|
|
447
419
|
const cells = snapshot.cells ?? {};
|
|
448
|
-
const jointOverrides =
|
|
420
|
+
const jointOverrides = snapshot.jointOverrides ?? [];
|
|
449
421
|
const defaults = snapshot.defaultTuple ?? defaultTuple$1(snapshot.axes);
|
|
450
422
|
const resolver = buildResolveAt(snapshot.axes, cells, jointOverrides, defaults);
|
|
451
423
|
return (tuple) => resolver(tuple);
|
|
@@ -454,20 +426,14 @@ function makeResolveAt(snapshot) {
|
|
|
454
426
|
* Build the `resolveAt` accessor for a snapshot. Prefers the
|
|
455
427
|
* snapshot's own `resolveAt` (the addon's preview decorator
|
|
456
428
|
* pre-builds one at module load — see `previewResolveAt` in
|
|
457
|
-
* `packages/addon/src/preview.tsx`),
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
*
|
|
461
|
-
* `permutationsResolved` + `permutations` (MDX consumers that
|
|
462
|
-
* pre-date the wire format change).
|
|
429
|
+
* `packages/addon/src/preview.tsx`), otherwise composes one from
|
|
430
|
+
* `cells` + `jointOverrides` via `makeResolveAt`. Hand-built
|
|
431
|
+
* snapshots should provide both via the test `withCellsShape`
|
|
432
|
+
* helper or by populating the fields directly.
|
|
463
433
|
*/
|
|
464
434
|
function snapshotResolveAt(snapshot) {
|
|
465
435
|
if (snapshot.resolveAt) return snapshot.resolveAt;
|
|
466
|
-
|
|
467
|
-
return (tuple) => {
|
|
468
|
-
const perms = snapshot.permutations ?? [];
|
|
469
|
-
return (snapshot.permutationsResolved ?? {})[nameForTuple(perms, tuple) ?? snapshot.activePermutation] ?? {};
|
|
470
|
-
};
|
|
436
|
+
return makeResolveAt(snapshot);
|
|
471
437
|
}
|
|
472
438
|
/**
|
|
473
439
|
* Reads project data either from a mounted {@link SwatchbookProvider}
|
|
@@ -487,7 +453,12 @@ function useProject() {
|
|
|
487
453
|
const cells = snapshot?.cells;
|
|
488
454
|
const jointOverrides = snapshot?.jointOverrides;
|
|
489
455
|
const dataDefaultTuple = snapshot?.defaultTuple;
|
|
456
|
+
const activeAxes = snapshot?.activeAxes;
|
|
490
457
|
const activePermutation = snapshot?.activePermutation;
|
|
458
|
+
const diagnostics = snapshot?.diagnostics;
|
|
459
|
+
const cssVarPrefix = snapshot?.cssVarPrefix;
|
|
460
|
+
const listing = snapshot?.listing;
|
|
461
|
+
const varianceByPath = snapshot?.varianceByPath;
|
|
491
462
|
const resolveAt = useMemo(() => {
|
|
492
463
|
if (!snapshot) return null;
|
|
493
464
|
return snapshotResolveAt(snapshot);
|
|
@@ -498,24 +469,36 @@ function useProject() {
|
|
|
498
469
|
dataDefaultTuple,
|
|
499
470
|
activePermutation
|
|
500
471
|
]);
|
|
501
|
-
const
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
472
|
+
const providerData = useMemo(() => {
|
|
473
|
+
if (!snapshot || !resolveAt || !axes || !activeAxes) return null;
|
|
474
|
+
return {
|
|
475
|
+
activePermutation: activePermutation ?? "",
|
|
476
|
+
activeAxes,
|
|
477
|
+
axes,
|
|
478
|
+
resolved: resolveAt(activeAxes),
|
|
479
|
+
diagnostics: diagnostics ?? [],
|
|
480
|
+
cssVarPrefix: cssVarPrefix ?? "",
|
|
481
|
+
listing: listing ?? {},
|
|
482
|
+
varianceByPath: varianceByPath ?? {},
|
|
483
|
+
resolveAt,
|
|
484
|
+
permutationNameForTuple: (tuple) => tupleToName(axes, tuple)
|
|
485
|
+
};
|
|
486
|
+
}, [
|
|
487
|
+
snapshot,
|
|
516
488
|
resolveAt,
|
|
517
|
-
|
|
518
|
-
|
|
489
|
+
axes,
|
|
490
|
+
cells,
|
|
491
|
+
jointOverrides,
|
|
492
|
+
dataDefaultTuple,
|
|
493
|
+
activePermutation,
|
|
494
|
+
activeAxes,
|
|
495
|
+
diagnostics,
|
|
496
|
+
cssVarPrefix,
|
|
497
|
+
listing,
|
|
498
|
+
varianceByPath
|
|
499
|
+
]);
|
|
500
|
+
const fallback = useVirtualModuleFallback(snapshot === null);
|
|
501
|
+
return providerData ?? fallback;
|
|
519
502
|
}
|
|
520
503
|
function useVirtualModuleFallback(enabled) {
|
|
521
504
|
const contextPermutation = useActivePermutation();
|
|
@@ -533,8 +516,14 @@ function useVirtualModuleFallback(enabled) {
|
|
|
533
516
|
if (!enabled) return;
|
|
534
517
|
ensureStylesheet(tokens.css);
|
|
535
518
|
}, [enabled, tokens.css]);
|
|
536
|
-
const activeAxes =
|
|
537
|
-
|
|
519
|
+
const activeAxes = useMemo(() => {
|
|
520
|
+
return Object.keys(contextAxes).length > 0 ? { ...contextAxes } : channelGlobals.axes ?? defaultTuple$1(tokens.axes);
|
|
521
|
+
}, [
|
|
522
|
+
contextAxes,
|
|
523
|
+
channelGlobals.axes,
|
|
524
|
+
tokens.axes
|
|
525
|
+
]);
|
|
526
|
+
const activePermutation = contextPermutation || tupleToName(tokens.axes, activeAxes);
|
|
538
527
|
const resolveAt = useMemo(() => makeResolveAt({
|
|
539
528
|
axes: tokens.axes,
|
|
540
529
|
cells: tokens.cells,
|
|
@@ -546,32 +535,27 @@ function useVirtualModuleFallback(enabled) {
|
|
|
546
535
|
tokens.jointOverrides,
|
|
547
536
|
tokens.defaultTuple
|
|
548
537
|
]);
|
|
549
|
-
|
|
550
|
-
const permutationNameForTuple = noPermutationName;
|
|
551
|
-
return {
|
|
538
|
+
return useMemo(() => ({
|
|
552
539
|
activePermutation,
|
|
553
540
|
activeAxes,
|
|
554
541
|
axes: tokens.axes,
|
|
555
|
-
resolved,
|
|
542
|
+
resolved: resolveAt(activeAxes),
|
|
556
543
|
diagnostics: tokens.diagnostics,
|
|
557
544
|
cssVarPrefix: tokens.cssVarPrefix,
|
|
558
545
|
listing: tokens.listing,
|
|
559
546
|
varianceByPath: tokens.varianceByPath,
|
|
560
547
|
resolveAt,
|
|
561
|
-
permutationNameForTuple
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
prefix,
|
|
573
|
-
wrapVar: true
|
|
574
|
-
}) : makeCSSVar(path, { wrapVar: true });
|
|
548
|
+
permutationNameForTuple: (tuple) => tupleToName(tokens.axes, tuple)
|
|
549
|
+
}), [
|
|
550
|
+
activePermutation,
|
|
551
|
+
activeAxes,
|
|
552
|
+
tokens.axes,
|
|
553
|
+
tokens.diagnostics,
|
|
554
|
+
tokens.cssVarPrefix,
|
|
555
|
+
tokens.listing,
|
|
556
|
+
tokens.varianceByPath,
|
|
557
|
+
resolveAt
|
|
558
|
+
]);
|
|
575
559
|
}
|
|
576
560
|
/**
|
|
577
561
|
* Resolve a token's CSS var reference, preferring the authoritative name
|
|
@@ -654,15 +638,6 @@ function BorderSample({ path }) {
|
|
|
654
638
|
//#endregion
|
|
655
639
|
//#region src/internal/data-attr.ts
|
|
656
640
|
/**
|
|
657
|
-
* Produce a prefixed `data-*` attribute name when `prefix` is set, bare
|
|
658
|
-
* `data-<key>` otherwise. Mirrors `dataAttr` in `@unpunnyfuns/swatchbook-core`
|
|
659
|
-
* so block wrappers and emitted-CSS selectors stay in lockstep without
|
|
660
|
-
* blocks taking a runtime dep on core.
|
|
661
|
-
*/
|
|
662
|
-
function dataAttr(prefix, key) {
|
|
663
|
-
return prefix ? `data-${prefix}-${key}` : `data-${key}`;
|
|
664
|
-
}
|
|
665
|
-
/**
|
|
666
641
|
* Marker attribute set on every block wrapper. Retained as a stable hook
|
|
667
642
|
* for consumer-side selectors (e.g. when a host app wants to target or
|
|
668
643
|
* override block chrome without relying on hashed class names).
|
|
@@ -697,59 +672,73 @@ function themeAttrs(prefix, themeName) {
|
|
|
697
672
|
}
|
|
698
673
|
//#endregion
|
|
699
674
|
//#region src/internal/sort-tokens.ts
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
675
|
+
const NUMERIC_TYPES = new Set([
|
|
676
|
+
"dimension",
|
|
677
|
+
"duration",
|
|
678
|
+
"fontWeight",
|
|
679
|
+
"opacity",
|
|
680
|
+
"number",
|
|
681
|
+
"lineHeight"
|
|
682
|
+
]);
|
|
683
|
+
const STRING_TYPES = new Set(["fontFamily", "strokeStyle"]);
|
|
684
|
+
function computeSortKey(token) {
|
|
685
|
+
const type = token.$type;
|
|
686
|
+
if (!type) return { kind: "none" };
|
|
687
|
+
if (NUMERIC_TYPES.has(type)) {
|
|
688
|
+
const value = toMagnitude(token.$value);
|
|
689
|
+
return {
|
|
690
|
+
kind: "numeric",
|
|
691
|
+
value,
|
|
692
|
+
valid: Number.isFinite(value)
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
if (type === "color") return {
|
|
696
|
+
kind: "color",
|
|
697
|
+
key: colorKey(token.$value)
|
|
698
|
+
};
|
|
699
|
+
if (STRING_TYPES.has(type)) return {
|
|
700
|
+
kind: "string",
|
|
701
|
+
value: toDisplayable(token.$value)
|
|
702
|
+
};
|
|
703
|
+
return { kind: "none" };
|
|
704
|
+
}
|
|
714
705
|
function sortTokens(entries, options = {}) {
|
|
715
706
|
const by = options.by ?? "path";
|
|
716
707
|
const dir = options.dir ?? "asc";
|
|
717
708
|
const sign = dir === "desc" ? -1 : 1;
|
|
718
709
|
if (by === "none") return dir === "desc" ? [...entries].toReversed() : [...entries];
|
|
719
710
|
if (by === "path") return [...entries].toSorted(([a], [b]) => sign * a.localeCompare(b, void 0, { numeric: true }));
|
|
711
|
+
const keys = /* @__PURE__ */ new Map();
|
|
712
|
+
for (const [, token] of entries) keys.set(token, computeSortKey(token));
|
|
720
713
|
return [...entries].toSorted(([aPath, aTok], [bPath, bTok]) => {
|
|
721
|
-
const cmp = compareValue(aTok, bTok);
|
|
714
|
+
const cmp = compareValue(aTok, bTok, keys);
|
|
722
715
|
if (cmp !== 0) return sign * cmp;
|
|
723
716
|
return sign * aPath.localeCompare(bPath, void 0, { numeric: true });
|
|
724
717
|
});
|
|
725
718
|
}
|
|
726
|
-
function compareValue(a, b) {
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
if (
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
if (
|
|
734
|
-
if (
|
|
735
|
-
if (
|
|
719
|
+
function compareValue(a, b, keys) {
|
|
720
|
+
if (a.$type !== b.$type) return String(a.$type ?? "").localeCompare(String(b.$type ?? ""));
|
|
721
|
+
const ak = keys.get(a);
|
|
722
|
+
const bk = keys.get(b);
|
|
723
|
+
if (!ak || !bk) return 0;
|
|
724
|
+
if (ak.kind !== bk.kind) return 0;
|
|
725
|
+
if (ak.kind === "numeric" && bk.kind === "numeric") {
|
|
726
|
+
if (ak.valid && bk.valid) return ak.value - bk.value;
|
|
727
|
+
if (ak.valid) return -1;
|
|
728
|
+
if (bk.valid) return 1;
|
|
736
729
|
return 0;
|
|
737
730
|
}
|
|
738
|
-
if (
|
|
739
|
-
const
|
|
740
|
-
const
|
|
741
|
-
if (!
|
|
742
|
-
if (!
|
|
743
|
-
if (!
|
|
744
|
-
if (
|
|
745
|
-
if (
|
|
746
|
-
return
|
|
747
|
-
}
|
|
748
|
-
if (type === "fontFamily" || type === "strokeStyle") {
|
|
749
|
-
const as = toDisplayable(a.$value);
|
|
750
|
-
const bs = toDisplayable(b.$value);
|
|
751
|
-
return as.localeCompare(bs, void 0, { numeric: true });
|
|
731
|
+
if (ak.kind === "color" && bk.kind === "color") {
|
|
732
|
+
const a3 = ak.key;
|
|
733
|
+
const b3 = bk.key;
|
|
734
|
+
if (!a3 && !b3) return 0;
|
|
735
|
+
if (!a3) return 1;
|
|
736
|
+
if (!b3) return -1;
|
|
737
|
+
if (a3.l !== b3.l) return a3.l - b3.l;
|
|
738
|
+
if (a3.c !== b3.c) return a3.c - b3.c;
|
|
739
|
+
return a3.h - b3.h;
|
|
752
740
|
}
|
|
741
|
+
if (ak.kind === "string" && bk.kind === "string") return ak.value.localeCompare(bk.value, void 0, { numeric: true });
|
|
753
742
|
return 0;
|
|
754
743
|
}
|
|
755
744
|
function toMagnitude(v) {
|
|
@@ -769,6 +758,14 @@ function toMagnitude(v) {
|
|
|
769
758
|
}
|
|
770
759
|
return NaN;
|
|
771
760
|
}
|
|
761
|
+
/**
|
|
762
|
+
* Coerce a possibly-null/undefined number to 0 — `coords` returns
|
|
763
|
+
* `(number | null)[]` and `noUncheckedIndexedAccess` adds `undefined`
|
|
764
|
+
* on top. `typeof` narrows the union for the comparator below.
|
|
765
|
+
*/
|
|
766
|
+
function safeNumber(v) {
|
|
767
|
+
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
768
|
+
}
|
|
772
769
|
function colorKey(v) {
|
|
773
770
|
if (!v || typeof v !== "object") return null;
|
|
774
771
|
try {
|
|
@@ -785,9 +782,9 @@ function colorKey(v) {
|
|
|
785
782
|
} else return null;
|
|
786
783
|
const [l, chroma, h] = new Color(source).to("oklch").coords;
|
|
787
784
|
return {
|
|
788
|
-
l:
|
|
789
|
-
c:
|
|
790
|
-
h:
|
|
785
|
+
l: safeNumber(l),
|
|
786
|
+
c: safeNumber(chroma),
|
|
787
|
+
h: safeNumber(h)
|
|
791
788
|
};
|
|
792
789
|
} catch {
|
|
793
790
|
return null;
|
|
@@ -2117,9 +2114,9 @@ function GradientPalette({ filter, caption, sortBy = "path", sortDir = "asc" })
|
|
|
2117
2114
|
* True when rendering inside Chromatic's snapshot runner. Chromatic's
|
|
2118
2115
|
* browser ships a recognisable user-agent string; checked here so
|
|
2119
2116
|
* motion-looping components can fall back to their static state for
|
|
2120
|
-
* deterministic snapshots
|
|
2121
|
-
*
|
|
2122
|
-
*
|
|
2117
|
+
* deterministic snapshots. Per-component detection rather than the
|
|
2118
|
+
* global `chromatic.prefersReducedMotion: true` parameter — that
|
|
2119
|
+
* parameter is incompatible with Chromatic's verification parser.
|
|
2123
2120
|
*/
|
|
2124
2121
|
function isChromatic() {
|
|
2125
2122
|
if (typeof navigator === "undefined") return false;
|
|
@@ -2887,14 +2884,19 @@ function AxisVariance({ path }) {
|
|
|
2887
2884
|
const formatFn = (t) => valueFor(t, tokenType, colorFormat);
|
|
2888
2885
|
const variance = useMemo(() => {
|
|
2889
2886
|
const result = varianceByPath[path];
|
|
2890
|
-
if (!result) return {
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2887
|
+
if (!result) return { kind: "constant" };
|
|
2888
|
+
switch (result.kind) {
|
|
2889
|
+
case "constant": return { kind: "constant" };
|
|
2890
|
+
case "single": return {
|
|
2891
|
+
kind: "one-axis",
|
|
2892
|
+
axis: result.axis,
|
|
2893
|
+
varyingAxes: result.varyingAxes
|
|
2894
|
+
};
|
|
2895
|
+
case "multi": return {
|
|
2896
|
+
kind: "multi-axis",
|
|
2897
|
+
varyingAxes: result.varyingAxes
|
|
2898
|
+
};
|
|
2899
|
+
}
|
|
2898
2900
|
}, [path, varianceByPath]);
|
|
2899
2901
|
if (axes.length === 0) return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
2900
2902
|
if (variance.kind === "constant") {
|
|
@@ -2930,8 +2932,7 @@ function AxisVariance({ path }) {
|
|
|
2930
2932
|
})] });
|
|
2931
2933
|
}
|
|
2932
2934
|
if (variance.kind === "one-axis") {
|
|
2933
|
-
const axisName = variance.
|
|
2934
|
-
if (!axisName) return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
2935
|
+
const axisName = variance.axis;
|
|
2935
2936
|
const axis = axes.find((a) => a.name === axisName);
|
|
2936
2937
|
if (!axis) return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
2937
2938
|
const contextValues = axis.contexts.map((ctx) => {
|
|
@@ -3775,6 +3776,7 @@ function buildTree(resolved, root, typeFilter) {
|
|
|
3775
3776
|
let node = rootNode;
|
|
3776
3777
|
for (let i = 0; i < segments.length - 1; i += 1) {
|
|
3777
3778
|
const seg = segments[i];
|
|
3779
|
+
if (seg === void 0) continue;
|
|
3778
3780
|
const prefix = [...rootSegments, ...segments.slice(0, i + 1)].join(".");
|
|
3779
3781
|
let child = node.children.find((c) => c.kind === "group" && c.segment === seg);
|
|
3780
3782
|
if (!child) {
|