@unpunnyfuns/swatchbook-blocks 0.66.3 → 0.68.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/README.md +2 -2
- package/dist/index.mjs +122 -192
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +684 -518
- package/package.json +35 -33
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ React MDX doc blocks for [swatchbook](https://github.com/unpunnyfuns/swatchbook)
|
|
|
4
4
|
|
|
5
5
|
Render your DTCG tokens in `.mdx` stories: swatch grids, type-specific previews, per-token inspectors. The blocks react to the toolbar's axis flips without any wiring in your story code.
|
|
6
6
|
|
|
7
|
-
Most consumers pick this up transitively via [`@unpunnyfuns/swatchbook-addon`](../addon); `import { TokenTable } from '@unpunnyfuns/swatchbook-addon'` works out of the box. Install this package directly when you want blocks
|
|
7
|
+
Most consumers pick this up transitively via [`@unpunnyfuns/swatchbook-addon`](../addon); `import { TokenTable } from '@unpunnyfuns/swatchbook-addon'` works out of the box. Install this package directly when you want blocks _without_ the Storybook addon, such as unit tests or a standalone React app wrapping tokens in a custom surface.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -32,7 +32,7 @@ import snapshot from './tokens-snapshot.json';
|
|
|
32
32
|
|
|
33
33
|
<SwatchbookProvider value={snapshot}>
|
|
34
34
|
<TokenTable filter="color.**" />
|
|
35
|
-
</SwatchbookProvider
|
|
35
|
+
</SwatchbookProvider>;
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
Block catalogue, props, and composition patterns live in the [blocks reference](https://unpunnyfuns.github.io/swatchbook/reference/blocks) and the [authoring guide](https://unpunnyfuns.github.io/swatchbook/guides/authoring-doc-stories).
|
package/dist/index.mjs
CHANGED
|
@@ -2,41 +2,16 @@ import './style.css';
|
|
|
2
2
|
import { COLOR_FORMATS } from "@unpunnyfuns/swatchbook-core/color-formats";
|
|
3
3
|
import { formatColor, parseColor } from "@unpunnyfuns/swatchbook-core/format-color";
|
|
4
4
|
import { createContext, memo, useCallback, useContext, useDeferredValue, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
5
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
5
|
import { getVariance, listPaths, resolveAllWithProvenanceAt } from "@unpunnyfuns/swatchbook-core/graph";
|
|
7
6
|
import { makeCssVar } from "@unpunnyfuns/swatchbook-core/css-var";
|
|
8
7
|
import { SWATCHBOOK_STYLE_ELEMENT_ID, ensureStyleElement } from "@unpunnyfuns/swatchbook-core/style-element";
|
|
9
8
|
import { tupleToName } from "@unpunnyfuns/swatchbook-core/themes";
|
|
10
9
|
import { addons } from "storybook/preview-api";
|
|
10
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
11
|
import { dataAttr } from "@unpunnyfuns/swatchbook-core/data-attr";
|
|
12
12
|
import { matchPath } from "@unpunnyfuns/swatchbook-core/match-path";
|
|
13
13
|
import { fuzzyFilter } from "@unpunnyfuns/swatchbook-core/fuzzy";
|
|
14
14
|
import cx from "clsx";
|
|
15
|
-
//#region src/internal/styles.tsx
|
|
16
|
-
/**
|
|
17
|
-
* Chrome-style primitives shared across every block. Kept as JS exports
|
|
18
|
-
* for the inline-style sites that still compose them into per-block style
|
|
19
|
-
* objects (e.g. TokenNavigator's `typePill` that builds on the shared
|
|
20
|
-
* pill base). The pure direct-reference chrome — surface wrapper, caption,
|
|
21
|
-
* empty-state — lives in `styles.css` and is applied via class names.
|
|
22
|
-
*/
|
|
23
|
-
const TEXT_MUTED = "var(--swatchbook-text-muted, CanvasText)";
|
|
24
|
-
const SURFACE_RAISED = "var(--swatchbook-surface-raised, Canvas)";
|
|
25
|
-
const SURFACE_MUTED = "var(--swatchbook-surface-muted, rgba(128,128,128,0.15))";
|
|
26
|
-
const BORDER_FAINT = `1px solid var(--swatchbook-border-default, rgba(128,128,128,0.15))`;
|
|
27
|
-
const BORDER_STRONG = `1px solid var(--swatchbook-border-default, rgba(128,128,128,0.3))`;
|
|
28
|
-
/**
|
|
29
|
-
* Inner content for a block's "nothing to render" state. Call sites wrap
|
|
30
|
-
* it in their own block wrapper (which already carries `blockWrapperAttrs`), so
|
|
31
|
-
* the message itself just needs the muted type.
|
|
32
|
-
*/
|
|
33
|
-
function EmptyState({ children }) {
|
|
34
|
-
return /* @__PURE__ */ jsx("div", {
|
|
35
|
-
className: "sb-block__empty",
|
|
36
|
-
children
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
//#endregion
|
|
40
15
|
//#region src/internal/channel-globals.ts
|
|
41
16
|
const AXES_GLOBAL_KEY = "swatchbookAxes";
|
|
42
17
|
const COLOR_FORMAT_GLOBAL_KEY = "swatchbookColorFormat";
|
|
@@ -75,7 +50,7 @@ function ensureSubscribed$1() {
|
|
|
75
50
|
channel.on("setGlobals", onGlobals);
|
|
76
51
|
}
|
|
77
52
|
ensureSubscribed$1();
|
|
78
|
-
function subscribe$
|
|
53
|
+
function subscribe$2(cb) {
|
|
79
54
|
ensureSubscribed$1();
|
|
80
55
|
listeners$1.add(cb);
|
|
81
56
|
return () => {
|
|
@@ -89,7 +64,7 @@ function getServerSnapshot$1() {
|
|
|
89
64
|
return snapshot$1;
|
|
90
65
|
}
|
|
91
66
|
function useChannelGlobals() {
|
|
92
|
-
return useSyncExternalStore(subscribe$
|
|
67
|
+
return useSyncExternalStore(subscribe$2, getSnapshot$1, getServerSnapshot$1);
|
|
93
68
|
}
|
|
94
69
|
//#endregion
|
|
95
70
|
//#region src/contexts.ts
|
|
@@ -212,7 +187,7 @@ function ensureSubscribed() {
|
|
|
212
187
|
});
|
|
213
188
|
}
|
|
214
189
|
ensureSubscribed();
|
|
215
|
-
function subscribe(cb) {
|
|
190
|
+
function subscribe$1(cb) {
|
|
216
191
|
ensureSubscribed();
|
|
217
192
|
listeners.add(cb);
|
|
218
193
|
return () => {
|
|
@@ -226,7 +201,7 @@ function getServerSnapshot() {
|
|
|
226
201
|
return snapshot;
|
|
227
202
|
}
|
|
228
203
|
function useTokenSnapshot() {
|
|
229
|
-
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
204
|
+
return useSyncExternalStore(subscribe$1, getSnapshot, getServerSnapshot);
|
|
230
205
|
}
|
|
231
206
|
//#endregion
|
|
232
207
|
//#region src/internal/use-project.ts
|
|
@@ -388,19 +363,10 @@ function resolveColorValue(path, raw, colorFormat, project) {
|
|
|
388
363
|
}
|
|
389
364
|
//#endregion
|
|
390
365
|
//#region src/border-preview/BorderSample.tsx
|
|
391
|
-
const sampleStyle$1 = {
|
|
392
|
-
width: 120,
|
|
393
|
-
height: 56,
|
|
394
|
-
background: SURFACE_RAISED,
|
|
395
|
-
borderRadius: 6
|
|
396
|
-
};
|
|
397
366
|
function BorderSample({ path }) {
|
|
398
|
-
const cssVar = resolveCssVar(path, useProject());
|
|
399
367
|
return /* @__PURE__ */ jsx("div", {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
border: cssVar
|
|
403
|
-
},
|
|
368
|
+
className: "sb-border-sample",
|
|
369
|
+
style: { border: resolveCssVar(path, useProject()) },
|
|
404
370
|
"aria-hidden": true
|
|
405
371
|
});
|
|
406
372
|
}
|
|
@@ -484,11 +450,11 @@ const NUMERIC_TYPES = new Set([
|
|
|
484
450
|
"lineHeight"
|
|
485
451
|
]);
|
|
486
452
|
const STRING_TYPES = new Set(["fontFamily", "strokeStyle"]);
|
|
487
|
-
function computeSortKey(token) {
|
|
453
|
+
function computeSortKey(token, rootFontSizePx) {
|
|
488
454
|
const type = token.$type;
|
|
489
455
|
if (!type) return { kind: "none" };
|
|
490
456
|
if (NUMERIC_TYPES.has(type)) {
|
|
491
|
-
const value = toMagnitude(token.$value);
|
|
457
|
+
const value = toMagnitude(token.$value, rootFontSizePx);
|
|
492
458
|
return {
|
|
493
459
|
kind: "numeric",
|
|
494
460
|
value,
|
|
@@ -511,8 +477,9 @@ function sortTokens(entries, options = {}) {
|
|
|
511
477
|
const sign = dir === "desc" ? -1 : 1;
|
|
512
478
|
if (by === "none") return dir === "desc" ? [...entries].toReversed() : [...entries];
|
|
513
479
|
if (by === "path") return [...entries].toSorted(([a], [b]) => sign * a.localeCompare(b, void 0, { numeric: true }));
|
|
480
|
+
const rootFontSizePx = options.rootFontSizePx ?? 16;
|
|
514
481
|
const keys = /* @__PURE__ */ new Map();
|
|
515
|
-
for (const [, token] of entries) keys.set(token, computeSortKey(token));
|
|
482
|
+
for (const [, token] of entries) keys.set(token, computeSortKey(token, rootFontSizePx));
|
|
516
483
|
return [...entries].toSorted(([aPath, aTok], [bPath, bTok]) => {
|
|
517
484
|
const cmp = compareValue(aTok, bTok, keys);
|
|
518
485
|
if (cmp !== 0) return sign * cmp;
|
|
@@ -544,7 +511,7 @@ function compareValue(a, b, keys) {
|
|
|
544
511
|
if (ak.kind === "string" && bk.kind === "string") return ak.value.localeCompare(bk.value, void 0, { numeric: true });
|
|
545
512
|
return 0;
|
|
546
513
|
}
|
|
547
|
-
function toMagnitude(v) {
|
|
514
|
+
function toMagnitude(v, rootFontSizePx) {
|
|
548
515
|
if (typeof v === "number") return v;
|
|
549
516
|
if (v && typeof v === "object") {
|
|
550
517
|
const d = v;
|
|
@@ -554,8 +521,7 @@ function toMagnitude(v) {
|
|
|
554
521
|
case "px":
|
|
555
522
|
case "ms": return d.value;
|
|
556
523
|
case "s": return d.value * 1e3;
|
|
557
|
-
case "rem":
|
|
558
|
-
case "em": return d.value * 16;
|
|
524
|
+
case "rem": return d.value * rootFontSizePx;
|
|
559
525
|
default: return d.value;
|
|
560
526
|
}
|
|
561
527
|
}
|
|
@@ -1057,12 +1023,9 @@ function CopyButton$1({ value, label, variant = "icon", className }) {
|
|
|
1057
1023
|
timerRef.current = setTimeout(() => setCopied(false), 1500);
|
|
1058
1024
|
}, [value]);
|
|
1059
1025
|
const ariaLabel = label ?? `Copy ${value}`;
|
|
1060
|
-
const classes = ["sb-copy-button", `sb-copy-button--${variant}`];
|
|
1061
|
-
if (copied) classes.push("sb-copy-button--copied");
|
|
1062
|
-
if (className) classes.push(className);
|
|
1063
1026
|
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("button", {
|
|
1064
1027
|
type: "button",
|
|
1065
|
-
className:
|
|
1028
|
+
className: cx("sb-copy-button", `sb-copy-button--${variant}`, copied && "sb-copy-button--copied", className),
|
|
1066
1029
|
onClick: handleClick,
|
|
1067
1030
|
"aria-label": ariaLabel,
|
|
1068
1031
|
title: ariaLabel,
|
|
@@ -1702,73 +1665,95 @@ function Diagnostics({ caption } = {}) {
|
|
|
1702
1665
|
//#region src/dimension-scale/dimension-px.ts
|
|
1703
1666
|
/**
|
|
1704
1667
|
* Convert a DTCG dimension `$value` (`{ value, unit }`) to pixels for the
|
|
1705
|
-
* purpose of deciding whether to cap the rendered size.
|
|
1706
|
-
*
|
|
1707
|
-
*
|
|
1668
|
+
* purpose of deciding whether to cap the rendered size. `rootFontSizePx`
|
|
1669
|
+
* scales `rem` against the rendering context's actual root font-size
|
|
1670
|
+
* (default 16 for the no-DOM / SSR path); the bar paints at the same
|
|
1671
|
+
* context's `var()`, so passing the measured root keeps the cap decision
|
|
1672
|
+
* aligned with what's drawn. Returns `NaN` for anything other than `px` /
|
|
1673
|
+
* `rem` — `ex` / `ch` / `%`, and the non-DTCG `em` (the `dimension` type
|
|
1674
|
+
* permits only `px | rem`) — which the caller treats as "render at cssVar
|
|
1675
|
+
* but don't cap".
|
|
1708
1676
|
*/
|
|
1709
|
-
function toPixels(raw) {
|
|
1677
|
+
function toPixels(raw, rootFontSizePx = 16) {
|
|
1710
1678
|
if (raw == null || typeof raw !== "object") return NaN;
|
|
1711
1679
|
const v = raw;
|
|
1712
1680
|
if (typeof v.value !== "number" || typeof v.unit !== "string") return NaN;
|
|
1713
1681
|
switch (v.unit) {
|
|
1714
1682
|
case "px": return v.value;
|
|
1715
|
-
case "rem":
|
|
1716
|
-
case "em": return v.value * 16;
|
|
1683
|
+
case "rem": return v.value * rootFontSizePx;
|
|
1717
1684
|
default: return NaN;
|
|
1718
1685
|
}
|
|
1719
1686
|
}
|
|
1720
1687
|
//#endregion
|
|
1688
|
+
//#region src/internal/use-root-font-size.ts
|
|
1689
|
+
function readRootFontSize() {
|
|
1690
|
+
if (typeof document === "undefined") return 16;
|
|
1691
|
+
const fontSize = Number.parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
1692
|
+
return Number.isFinite(fontSize) && fontSize > 0 ? fontSize : 16;
|
|
1693
|
+
}
|
|
1694
|
+
function subscribe(onChange) {
|
|
1695
|
+
if (typeof window === "undefined") return () => {};
|
|
1696
|
+
window.addEventListener("resize", onChange);
|
|
1697
|
+
return () => window.removeEventListener("resize", onChange);
|
|
1698
|
+
}
|
|
1699
|
+
/**
|
|
1700
|
+
* Root font-size (px) of the context a block renders in, tracked across
|
|
1701
|
+
* viewport changes. `rem` dimension values resolve their `var()` against this
|
|
1702
|
+
* root, so the cap math (`toPixels`) and value sort (`sortTokens`) must scale
|
|
1703
|
+
* `rem` by it rather than a literal 16: a Storybook Docs page, or a responsive
|
|
1704
|
+
* desktop/tablet/mobile breakpoint, can apply a different root to the same
|
|
1705
|
+
* token. Falls back to 16 with no DOM.
|
|
1706
|
+
*/
|
|
1707
|
+
function useRootFontSize() {
|
|
1708
|
+
return useSyncExternalStore(subscribe, readRootFontSize, () => 16);
|
|
1709
|
+
}
|
|
1710
|
+
//#endregion
|
|
1721
1711
|
//#region src/dimension-scale/DimensionBar.tsx
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
border: BORDER_STRONG
|
|
1734
|
-
},
|
|
1735
|
-
sizeSample: {
|
|
1736
|
-
background: "var(--swatchbook-accent-bg, #3b82f6)",
|
|
1737
|
-
border: BORDER_STRONG,
|
|
1738
|
-
minWidth: 1,
|
|
1739
|
-
minHeight: 1
|
|
1740
|
-
}
|
|
1741
|
-
};
|
|
1712
|
+
function withCap(visual) {
|
|
1713
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
1714
|
+
className: "sb-dimension-bar sb-dimension-bar--capped",
|
|
1715
|
+
title: `capped at 480px`,
|
|
1716
|
+
children: [visual, /* @__PURE__ */ jsx("span", {
|
|
1717
|
+
className: "sb-dimension-bar__cap",
|
|
1718
|
+
"aria-hidden": true,
|
|
1719
|
+
children: "…"
|
|
1720
|
+
})]
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1742
1723
|
function DimensionBar({ path, visual = "length" }) {
|
|
1743
1724
|
const project = useProject();
|
|
1744
1725
|
const { resolved } = project;
|
|
1726
|
+
const rootFontSize = useRootFontSize();
|
|
1745
1727
|
const cssVar = resolveCssVar(path, project);
|
|
1746
1728
|
const token = resolved[path];
|
|
1747
|
-
const pxValue = toPixels(token?.$value);
|
|
1748
|
-
const
|
|
1729
|
+
const pxValue = toPixels(token?.$value, rootFontSize);
|
|
1730
|
+
const capped = Number.isFinite(pxValue) && pxValue > 480;
|
|
1731
|
+
const cappedValue = capped ? `480px` : cssVar;
|
|
1749
1732
|
switch (visual) {
|
|
1750
1733
|
case "radius": return /* @__PURE__ */ jsx("div", {
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
borderRadius: cssVar
|
|
1754
|
-
},
|
|
1755
|
-
"aria-hidden": true
|
|
1756
|
-
});
|
|
1757
|
-
case "size": return /* @__PURE__ */ jsx("div", {
|
|
1758
|
-
style: {
|
|
1759
|
-
...styles$1.sizeSample,
|
|
1760
|
-
width: cappedValue,
|
|
1761
|
-
height: cappedValue
|
|
1762
|
-
},
|
|
1763
|
-
"aria-hidden": true
|
|
1764
|
-
});
|
|
1765
|
-
default: return /* @__PURE__ */ jsx("div", {
|
|
1766
|
-
style: {
|
|
1767
|
-
...styles$1.bar,
|
|
1768
|
-
width: cappedValue
|
|
1769
|
-
},
|
|
1734
|
+
className: "sb-dimension-bar__radius-sample",
|
|
1735
|
+
style: { borderRadius: cssVar },
|
|
1770
1736
|
"aria-hidden": true
|
|
1771
1737
|
});
|
|
1738
|
+
case "size": {
|
|
1739
|
+
const sample = /* @__PURE__ */ jsx("div", {
|
|
1740
|
+
className: "sb-dimension-bar__size-sample",
|
|
1741
|
+
style: {
|
|
1742
|
+
width: cappedValue,
|
|
1743
|
+
height: cappedValue
|
|
1744
|
+
},
|
|
1745
|
+
"aria-hidden": true
|
|
1746
|
+
});
|
|
1747
|
+
return capped ? withCap(sample) : sample;
|
|
1748
|
+
}
|
|
1749
|
+
default: {
|
|
1750
|
+
const bar = /* @__PURE__ */ jsx("div", {
|
|
1751
|
+
className: "sb-dimension-bar__bar",
|
|
1752
|
+
style: { width: cappedValue },
|
|
1753
|
+
"aria-hidden": true
|
|
1754
|
+
});
|
|
1755
|
+
return capped ? withCap(bar) : bar;
|
|
1756
|
+
}
|
|
1772
1757
|
}
|
|
1773
1758
|
}
|
|
1774
1759
|
//#endregion
|
|
@@ -1878,29 +1863,27 @@ function formatUnknown(v) {
|
|
|
1878
1863
|
function DimensionScale({ filter, visual = "length", caption, sortBy = "value", sortDir = "asc" }) {
|
|
1879
1864
|
const project = useProject();
|
|
1880
1865
|
const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;
|
|
1866
|
+
const rootFontSize = useRootFontSize();
|
|
1881
1867
|
const rows = useMemo(() => {
|
|
1882
1868
|
return sortTokens(Object.entries(resolved).filter(([path, token]) => {
|
|
1883
1869
|
if (token.$type !== "dimension") return false;
|
|
1884
1870
|
return matchPath(path, filter);
|
|
1885
1871
|
}), {
|
|
1886
1872
|
by: sortBy,
|
|
1887
|
-
dir: sortDir
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
pxValue,
|
|
1895
|
-
capped: Number.isFinite(pxValue) && pxValue > 480
|
|
1896
|
-
};
|
|
1897
|
-
});
|
|
1873
|
+
dir: sortDir,
|
|
1874
|
+
rootFontSizePx: rootFontSize
|
|
1875
|
+
}).map(([path, token]) => ({
|
|
1876
|
+
path,
|
|
1877
|
+
cssVar: resolveCssVar(path, project),
|
|
1878
|
+
displayValue: formatTokenValue(token.$value, token.$type, "raw", project.listing[path])
|
|
1879
|
+
}));
|
|
1898
1880
|
}, [
|
|
1899
1881
|
resolved,
|
|
1900
1882
|
filter,
|
|
1901
1883
|
project,
|
|
1902
1884
|
sortBy,
|
|
1903
|
-
sortDir
|
|
1885
|
+
sortDir,
|
|
1886
|
+
rootFontSize
|
|
1904
1887
|
]);
|
|
1905
1888
|
const captionText = caption ?? `${rows.length} dimension${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
1906
1889
|
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
@@ -1928,19 +1911,12 @@ function DimensionScale({ filter, visual = "length", caption, sortBy = "value",
|
|
|
1928
1911
|
children: row.displayValue
|
|
1929
1912
|
})]
|
|
1930
1913
|
}),
|
|
1931
|
-
/* @__PURE__ */
|
|
1914
|
+
/* @__PURE__ */ jsx("div", {
|
|
1932
1915
|
className: "sb-dimension-scale__visual-cell",
|
|
1933
|
-
children:
|
|
1916
|
+
children: /* @__PURE__ */ jsx(DimensionBar, {
|
|
1934
1917
|
path: row.path,
|
|
1935
1918
|
visual
|
|
1936
|
-
})
|
|
1937
|
-
className: "sb-dimension-scale__cap",
|
|
1938
|
-
children: [
|
|
1939
|
-
"capped at ",
|
|
1940
|
-
480,
|
|
1941
|
-
"px"
|
|
1942
|
-
]
|
|
1943
|
-
})]
|
|
1919
|
+
})
|
|
1944
1920
|
}),
|
|
1945
1921
|
/* @__PURE__ */ jsx("span", {
|
|
1946
1922
|
className: "sb-dimension-scale__css-var",
|
|
@@ -2235,29 +2211,6 @@ function usePrefersReducedMotion() {
|
|
|
2235
2211
|
//#region src/motion-preview/MotionSample.tsx
|
|
2236
2212
|
const DEFAULT_DURATION_MS = 300;
|
|
2237
2213
|
const DEFAULT_EASING = "cubic-bezier(0.2, 0, 0, 1)";
|
|
2238
|
-
const styles = {
|
|
2239
|
-
track: {
|
|
2240
|
-
position: "relative",
|
|
2241
|
-
height: 36,
|
|
2242
|
-
background: SURFACE_MUTED,
|
|
2243
|
-
borderRadius: 18,
|
|
2244
|
-
overflow: "hidden"
|
|
2245
|
-
},
|
|
2246
|
-
ball: {
|
|
2247
|
-
position: "absolute",
|
|
2248
|
-
top: "50%",
|
|
2249
|
-
width: 28,
|
|
2250
|
-
height: 28,
|
|
2251
|
-
marginTop: -14,
|
|
2252
|
-
borderRadius: "50%",
|
|
2253
|
-
background: "var(--swatchbook-accent-bg, #3b82f6)"
|
|
2254
|
-
},
|
|
2255
|
-
reducedMotion: {
|
|
2256
|
-
fontSize: 11,
|
|
2257
|
-
color: TEXT_MUTED,
|
|
2258
|
-
fontStyle: "italic"
|
|
2259
|
-
}
|
|
2260
|
-
};
|
|
2261
2214
|
function extractDurationMs(raw) {
|
|
2262
2215
|
if (raw == null) return NaN;
|
|
2263
2216
|
if (typeof raw === "object") {
|
|
@@ -2352,7 +2305,7 @@ function MotionSample({ path, speed = 1, runKey = 0 }) {
|
|
|
2352
2305
|
reducedMotion
|
|
2353
2306
|
]);
|
|
2354
2307
|
if (reducedMotion) return /* @__PURE__ */ jsxs("div", {
|
|
2355
|
-
|
|
2308
|
+
className: "sb-motion-sample__reduced-motion",
|
|
2356
2309
|
children: [
|
|
2357
2310
|
"Animation suppressed by ",
|
|
2358
2311
|
/* @__PURE__ */ jsx("code", { children: "prefers-reduced-motion: reduce" }),
|
|
@@ -2360,13 +2313,10 @@ function MotionSample({ path, speed = 1, runKey = 0 }) {
|
|
|
2360
2313
|
]
|
|
2361
2314
|
});
|
|
2362
2315
|
return /* @__PURE__ */ jsx("div", {
|
|
2363
|
-
|
|
2316
|
+
className: "sb-motion-sample__track",
|
|
2364
2317
|
children: /* @__PURE__ */ jsx("div", {
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
left: phase === 1 ? "calc(100% - 32px)" : "4px",
|
|
2368
|
-
transition: `left ${scaledDuration}ms ${easing}`
|
|
2369
|
-
},
|
|
2318
|
+
className: cx("sb-motion-sample__ball", phase === 1 ? "sb-motion-sample__ball--end" : "sb-motion-sample__ball--start"),
|
|
2319
|
+
style: { transition: `left ${scaledDuration}ms ${easing}` },
|
|
2370
2320
|
"aria-hidden": true
|
|
2371
2321
|
})
|
|
2372
2322
|
});
|
|
@@ -2554,8 +2504,8 @@ function OpacityScale({ filter, type = "number", sampleColor = "color.accent.bg"
|
|
|
2554
2504
|
children: [/* @__PURE__ */ jsx("div", {
|
|
2555
2505
|
className: "sb-opacity-scale__swatch",
|
|
2556
2506
|
style: {
|
|
2557
|
-
"--
|
|
2558
|
-
"--
|
|
2507
|
+
"--swatchbook-opacity-scale-color": sampleColorVar,
|
|
2508
|
+
"--swatchbook-opacity-scale-alpha": String(row.opacity)
|
|
2559
2509
|
},
|
|
2560
2510
|
"aria-hidden": true
|
|
2561
2511
|
}), /* @__PURE__ */ jsxs("div", {
|
|
@@ -2608,20 +2558,10 @@ function useSwatchbookData() {
|
|
|
2608
2558
|
}
|
|
2609
2559
|
//#endregion
|
|
2610
2560
|
//#region src/shadow-preview/ShadowSample.tsx
|
|
2611
|
-
const sampleStyle = {
|
|
2612
|
-
width: 120,
|
|
2613
|
-
height: 56,
|
|
2614
|
-
background: SURFACE_RAISED,
|
|
2615
|
-
border: BORDER_FAINT,
|
|
2616
|
-
borderRadius: 6
|
|
2617
|
-
};
|
|
2618
2561
|
function ShadowSample({ path }) {
|
|
2619
|
-
const cssVar = resolveCssVar(path, useProject());
|
|
2620
2562
|
return /* @__PURE__ */ jsx("div", {
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
boxShadow: cssVar
|
|
2624
|
-
},
|
|
2563
|
+
className: "sb-shadow-sample",
|
|
2564
|
+
style: { boxShadow: resolveCssVar(path, useProject()) },
|
|
2625
2565
|
"aria-hidden": true
|
|
2626
2566
|
});
|
|
2627
2567
|
}
|
|
@@ -2996,10 +2936,7 @@ function AxisVariance({ path }) {
|
|
|
2996
2936
|
}),
|
|
2997
2937
|
value,
|
|
2998
2938
|
/* @__PURE__ */ jsx("span", {
|
|
2999
|
-
|
|
3000
|
-
opacity: .6,
|
|
3001
|
-
marginLeft: 8
|
|
3002
|
-
},
|
|
2939
|
+
className: "sb-token-detail__constant-label-note",
|
|
3003
2940
|
children: "same across every axis"
|
|
3004
2941
|
})
|
|
3005
2942
|
]
|
|
@@ -3033,8 +2970,7 @@ function AxisVariance({ path }) {
|
|
|
3033
2970
|
"data-axis": axisName,
|
|
3034
2971
|
"data-context": row.ctx,
|
|
3035
2972
|
children: [/* @__PURE__ */ jsx("td", {
|
|
3036
|
-
className: "sb-token-detail__theme-cell",
|
|
3037
|
-
style: { width: "30%" },
|
|
2973
|
+
className: "sb-token-detail__theme-cell sb-token-detail__theme-cell--label",
|
|
3038
2974
|
children: row.ctx
|
|
3039
2975
|
}), /* @__PURE__ */ jsxs("td", {
|
|
3040
2976
|
className: "sb-token-detail__theme-cell",
|
|
@@ -3061,22 +2997,14 @@ function AxisVariance({ path }) {
|
|
|
3061
2997
|
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", {
|
|
3062
2998
|
className: "sb-token-detail__theme-row",
|
|
3063
2999
|
children: [/* @__PURE__ */ jsxs("th", {
|
|
3064
|
-
className: "sb-token-detail__theme-cell",
|
|
3065
|
-
style: {
|
|
3066
|
-
textAlign: "left",
|
|
3067
|
-
opacity: .7
|
|
3068
|
-
},
|
|
3000
|
+
className: "sb-token-detail__theme-cell sb-token-detail__theme-cell--header",
|
|
3069
3001
|
children: [
|
|
3070
3002
|
rowAxis.name,
|
|
3071
3003
|
" \\ ",
|
|
3072
3004
|
colAxis.name
|
|
3073
3005
|
]
|
|
3074
3006
|
}), colAxis.contexts.map((col) => /* @__PURE__ */ jsx("th", {
|
|
3075
|
-
className: "sb-token-detail__theme-cell",
|
|
3076
|
-
style: {
|
|
3077
|
-
textAlign: "left",
|
|
3078
|
-
opacity: .7
|
|
3079
|
-
},
|
|
3007
|
+
className: "sb-token-detail__theme-cell sb-token-detail__theme-cell--header",
|
|
3080
3008
|
children: col
|
|
3081
3009
|
}, col))]
|
|
3082
3010
|
}) }), /* @__PURE__ */ jsx("tbody", { children: rowAxis.contexts.map((row) => /* @__PURE__ */ jsxs("tr", {
|
|
@@ -3106,8 +3034,7 @@ function AxisVariance({ path }) {
|
|
|
3106
3034
|
}, row)) })]
|
|
3107
3035
|
}),
|
|
3108
3036
|
extra.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
3109
|
-
className: "sb-token-detail__aliased-by-truncated",
|
|
3110
|
-
style: { marginTop: 6 },
|
|
3037
|
+
className: "sb-token-detail__aliased-by-truncated sb-token-detail__aliased-by-truncated--axis-note",
|
|
3111
3038
|
children: [
|
|
3112
3039
|
"Values also vary with ",
|
|
3113
3040
|
extra.map((a) => a.name).join(", "),
|
|
@@ -3218,7 +3145,7 @@ function CompositeBreakdownContent({ type, rawValue, partialAliasOf, resolved, c
|
|
|
3218
3145
|
children: layers.map((layer, i) => {
|
|
3219
3146
|
const v = layer;
|
|
3220
3147
|
return /* @__PURE__ */ jsxs("div", {
|
|
3221
|
-
|
|
3148
|
+
className: "sb-token-detail__shadow-layer",
|
|
3222
3149
|
children: [
|
|
3223
3150
|
multi && /* @__PURE__ */ jsxs("div", {
|
|
3224
3151
|
className: "sb-token-detail__breakdown-layer-header",
|
|
@@ -3560,11 +3487,8 @@ function TransitionSample({ transition, durationMs }) {
|
|
|
3560
3487
|
return /* @__PURE__ */ jsx("div", {
|
|
3561
3488
|
className: "sb-token-detail__motion-track",
|
|
3562
3489
|
children: /* @__PURE__ */ jsx("div", {
|
|
3563
|
-
className: "sb-token-detail__motion-ball",
|
|
3564
|
-
style: {
|
|
3565
|
-
left: phase === 1 ? "calc(100% - 28px)" : "4px",
|
|
3566
|
-
transition
|
|
3567
|
-
},
|
|
3490
|
+
className: cx("sb-token-detail__motion-ball", phase === 1 ? "sb-token-detail__motion-ball--end" : "sb-token-detail__motion-ball--start"),
|
|
3491
|
+
style: { transition },
|
|
3568
3492
|
"aria-hidden": true
|
|
3569
3493
|
})
|
|
3570
3494
|
});
|
|
@@ -3788,7 +3712,7 @@ function TokenDetail({ path, heading }) {
|
|
|
3788
3712
|
outOfGamut && /* @__PURE__ */ jsx("span", {
|
|
3789
3713
|
title: "Out of sRGB gamut for this format",
|
|
3790
3714
|
"aria-label": "out of gamut",
|
|
3791
|
-
|
|
3715
|
+
className: "sb-token-detail__out-of-gamut-icon",
|
|
3792
3716
|
children: "⚠"
|
|
3793
3717
|
}),
|
|
3794
3718
|
/* @__PURE__ */ jsx(CopyButton$1, {
|
|
@@ -4262,7 +4186,10 @@ function TokenNavigator({ root, type, initiallyExpanded = 1, searchable = true,
|
|
|
4262
4186
|
}, [visibleTree, searchExpanded]);
|
|
4263
4187
|
if (tree.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
4264
4188
|
...blockWrapperAttrs(cssVarPrefix, activeAxes),
|
|
4265
|
-
children: /* @__PURE__ */ jsx(
|
|
4189
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
4190
|
+
className: "sb-block__empty",
|
|
4191
|
+
children: root ? `No tokens under "${root}"${typeFilter ? ` matching ${typeLabel.slice(3)}` : ""}.` : typeFilter ? `No tokens matching ${typeLabel.slice(3)} in the active theme.` : "No tokens in the active theme."
|
|
4192
|
+
})
|
|
4266
4193
|
});
|
|
4267
4194
|
return /* @__PURE__ */ jsxs("div", {
|
|
4268
4195
|
...blockWrapperAttrs(cssVarPrefix, activeAxes),
|
|
@@ -4523,6 +4450,7 @@ const LeafPreview = memo(function LeafPreview({ path, token }) {
|
|
|
4523
4450
|
function TokenTable({ filter, type, caption, sortBy = "path", sortDir = "asc", searchable = true, onSelect, id, indicators }) {
|
|
4524
4451
|
const { resolved, activeTheme, activeAxes, cssVarPrefix, listing, varianceByPath, indicators: indicatorBaseline } = useProject();
|
|
4525
4452
|
const colorFormat = useColorFormat();
|
|
4453
|
+
const rootFontSize = useRootFontSize();
|
|
4526
4454
|
const blockKey = useBlockKey("TokenTable", [
|
|
4527
4455
|
filter,
|
|
4528
4456
|
type,
|
|
@@ -4544,7 +4472,8 @@ function TokenTable({ filter, type, caption, sortBy = "path", sortDir = "asc", s
|
|
|
4544
4472
|
return true;
|
|
4545
4473
|
}), {
|
|
4546
4474
|
by: sortBy,
|
|
4547
|
-
dir: sortDir
|
|
4475
|
+
dir: sortDir,
|
|
4476
|
+
rootFontSizePx: rootFontSize
|
|
4548
4477
|
}).map(([path, token]) => {
|
|
4549
4478
|
const isColor = token.$type === "color";
|
|
4550
4479
|
const color = isColor ? resolveColorValue(path, token.$value, colorFormat, projectFields) : null;
|
|
@@ -4565,7 +4494,8 @@ function TokenTable({ filter, type, caption, sortBy = "path", sortDir = "asc", s
|
|
|
4565
4494
|
type,
|
|
4566
4495
|
colorFormat,
|
|
4567
4496
|
sortBy,
|
|
4568
|
-
sortDir
|
|
4497
|
+
sortDir,
|
|
4498
|
+
rootFontSize
|
|
4569
4499
|
]);
|
|
4570
4500
|
const visibleRows = useMemo(() => {
|
|
4571
4501
|
if (!searchable || deferredQuery.trim() === "") return rows;
|