@unpunnyfuns/swatchbook-blocks 0.66.2 → 0.67.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.mjs +115 -60
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +386 -352
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -75,7 +75,7 @@ function ensureSubscribed$1() {
|
|
|
75
75
|
channel.on("setGlobals", onGlobals);
|
|
76
76
|
}
|
|
77
77
|
ensureSubscribed$1();
|
|
78
|
-
function subscribe$
|
|
78
|
+
function subscribe$2(cb) {
|
|
79
79
|
ensureSubscribed$1();
|
|
80
80
|
listeners$1.add(cb);
|
|
81
81
|
return () => {
|
|
@@ -89,7 +89,7 @@ function getServerSnapshot$1() {
|
|
|
89
89
|
return snapshot$1;
|
|
90
90
|
}
|
|
91
91
|
function useChannelGlobals() {
|
|
92
|
-
return useSyncExternalStore(subscribe$
|
|
92
|
+
return useSyncExternalStore(subscribe$2, getSnapshot$1, getServerSnapshot$1);
|
|
93
93
|
}
|
|
94
94
|
//#endregion
|
|
95
95
|
//#region src/contexts.ts
|
|
@@ -212,7 +212,7 @@ function ensureSubscribed() {
|
|
|
212
212
|
});
|
|
213
213
|
}
|
|
214
214
|
ensureSubscribed();
|
|
215
|
-
function subscribe(cb) {
|
|
215
|
+
function subscribe$1(cb) {
|
|
216
216
|
ensureSubscribed();
|
|
217
217
|
listeners.add(cb);
|
|
218
218
|
return () => {
|
|
@@ -226,7 +226,7 @@ function getServerSnapshot() {
|
|
|
226
226
|
return snapshot;
|
|
227
227
|
}
|
|
228
228
|
function useTokenSnapshot() {
|
|
229
|
-
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
229
|
+
return useSyncExternalStore(subscribe$1, getSnapshot, getServerSnapshot);
|
|
230
230
|
}
|
|
231
231
|
//#endregion
|
|
232
232
|
//#region src/internal/use-project.ts
|
|
@@ -484,11 +484,11 @@ const NUMERIC_TYPES = new Set([
|
|
|
484
484
|
"lineHeight"
|
|
485
485
|
]);
|
|
486
486
|
const STRING_TYPES = new Set(["fontFamily", "strokeStyle"]);
|
|
487
|
-
function computeSortKey(token) {
|
|
487
|
+
function computeSortKey(token, rootFontSizePx) {
|
|
488
488
|
const type = token.$type;
|
|
489
489
|
if (!type) return { kind: "none" };
|
|
490
490
|
if (NUMERIC_TYPES.has(type)) {
|
|
491
|
-
const value = toMagnitude(token.$value);
|
|
491
|
+
const value = toMagnitude(token.$value, rootFontSizePx);
|
|
492
492
|
return {
|
|
493
493
|
kind: "numeric",
|
|
494
494
|
value,
|
|
@@ -511,8 +511,9 @@ function sortTokens(entries, options = {}) {
|
|
|
511
511
|
const sign = dir === "desc" ? -1 : 1;
|
|
512
512
|
if (by === "none") return dir === "desc" ? [...entries].toReversed() : [...entries];
|
|
513
513
|
if (by === "path") return [...entries].toSorted(([a], [b]) => sign * a.localeCompare(b, void 0, { numeric: true }));
|
|
514
|
+
const rootFontSizePx = options.rootFontSizePx ?? 16;
|
|
514
515
|
const keys = /* @__PURE__ */ new Map();
|
|
515
|
-
for (const [, token] of entries) keys.set(token, computeSortKey(token));
|
|
516
|
+
for (const [, token] of entries) keys.set(token, computeSortKey(token, rootFontSizePx));
|
|
516
517
|
return [...entries].toSorted(([aPath, aTok], [bPath, bTok]) => {
|
|
517
518
|
const cmp = compareValue(aTok, bTok, keys);
|
|
518
519
|
if (cmp !== 0) return sign * cmp;
|
|
@@ -544,7 +545,7 @@ function compareValue(a, b, keys) {
|
|
|
544
545
|
if (ak.kind === "string" && bk.kind === "string") return ak.value.localeCompare(bk.value, void 0, { numeric: true });
|
|
545
546
|
return 0;
|
|
546
547
|
}
|
|
547
|
-
function toMagnitude(v) {
|
|
548
|
+
function toMagnitude(v, rootFontSizePx) {
|
|
548
549
|
if (typeof v === "number") return v;
|
|
549
550
|
if (v && typeof v === "object") {
|
|
550
551
|
const d = v;
|
|
@@ -554,8 +555,7 @@ function toMagnitude(v) {
|
|
|
554
555
|
case "px":
|
|
555
556
|
case "ms": return d.value;
|
|
556
557
|
case "s": return d.value * 1e3;
|
|
557
|
-
case "rem":
|
|
558
|
-
case "em": return d.value * 16;
|
|
558
|
+
case "rem": return d.value * rootFontSizePx;
|
|
559
559
|
default: return d.value;
|
|
560
560
|
}
|
|
561
561
|
}
|
|
@@ -1702,29 +1702,70 @@ function Diagnostics({ caption } = {}) {
|
|
|
1702
1702
|
//#region src/dimension-scale/dimension-px.ts
|
|
1703
1703
|
/**
|
|
1704
1704
|
* Convert a DTCG dimension `$value` (`{ value, unit }`) to pixels for the
|
|
1705
|
-
* purpose of deciding whether to cap the rendered size.
|
|
1706
|
-
*
|
|
1707
|
-
*
|
|
1705
|
+
* purpose of deciding whether to cap the rendered size. `rootFontSizePx`
|
|
1706
|
+
* scales `rem` against the rendering context's actual root font-size
|
|
1707
|
+
* (default 16 for the no-DOM / SSR path); the bar paints at the same
|
|
1708
|
+
* context's `var()`, so passing the measured root keeps the cap decision
|
|
1709
|
+
* aligned with what's drawn. Returns `NaN` for anything other than `px` /
|
|
1710
|
+
* `rem` — `ex` / `ch` / `%`, and the non-DTCG `em` (the `dimension` type
|
|
1711
|
+
* permits only `px | rem`) — which the caller treats as "render at cssVar
|
|
1712
|
+
* but don't cap".
|
|
1708
1713
|
*/
|
|
1709
|
-
function toPixels(raw) {
|
|
1714
|
+
function toPixels(raw, rootFontSizePx = 16) {
|
|
1710
1715
|
if (raw == null || typeof raw !== "object") return NaN;
|
|
1711
1716
|
const v = raw;
|
|
1712
1717
|
if (typeof v.value !== "number" || typeof v.unit !== "string") return NaN;
|
|
1713
1718
|
switch (v.unit) {
|
|
1714
1719
|
case "px": return v.value;
|
|
1715
|
-
case "rem":
|
|
1716
|
-
case "em": return v.value * 16;
|
|
1720
|
+
case "rem": return v.value * rootFontSizePx;
|
|
1717
1721
|
default: return NaN;
|
|
1718
1722
|
}
|
|
1719
1723
|
}
|
|
1720
1724
|
//#endregion
|
|
1725
|
+
//#region src/internal/use-root-font-size.ts
|
|
1726
|
+
function readRootFontSize() {
|
|
1727
|
+
if (typeof document === "undefined") return 16;
|
|
1728
|
+
const fontSize = Number.parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
1729
|
+
return Number.isFinite(fontSize) && fontSize > 0 ? fontSize : 16;
|
|
1730
|
+
}
|
|
1731
|
+
function subscribe(onChange) {
|
|
1732
|
+
if (typeof window === "undefined") return () => {};
|
|
1733
|
+
window.addEventListener("resize", onChange);
|
|
1734
|
+
return () => window.removeEventListener("resize", onChange);
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* Root font-size (px) of the context a block renders in, tracked across
|
|
1738
|
+
* viewport changes. `rem` dimension values resolve their `var()` against this
|
|
1739
|
+
* root, so the cap math (`toPixels`) and value sort (`sortTokens`) must scale
|
|
1740
|
+
* `rem` by it rather than a literal 16: a Storybook Docs page, or a responsive
|
|
1741
|
+
* desktop/tablet/mobile breakpoint, can apply a different root to the same
|
|
1742
|
+
* token. Falls back to 16 with no DOM.
|
|
1743
|
+
*/
|
|
1744
|
+
function useRootFontSize() {
|
|
1745
|
+
return useSyncExternalStore(subscribe, readRootFontSize, () => 16);
|
|
1746
|
+
}
|
|
1747
|
+
//#endregion
|
|
1721
1748
|
//#region src/dimension-scale/DimensionBar.tsx
|
|
1722
1749
|
const styles$1 = {
|
|
1750
|
+
cappedWrap: {
|
|
1751
|
+
display: "inline-flex",
|
|
1752
|
+
alignItems: "center",
|
|
1753
|
+
gap: "var(--swatchbook-space-3xs)",
|
|
1754
|
+
maxWidth: "100%",
|
|
1755
|
+
minWidth: 0
|
|
1756
|
+
},
|
|
1757
|
+
cap: {
|
|
1758
|
+
color: "var(--swatchbook-text-muted)",
|
|
1759
|
+
fontSize: 11,
|
|
1760
|
+
lineHeight: 1,
|
|
1761
|
+
userSelect: "none"
|
|
1762
|
+
},
|
|
1723
1763
|
bar: {
|
|
1724
1764
|
height: 14,
|
|
1725
1765
|
background: "var(--swatchbook-accent-bg, #3b82f6)",
|
|
1726
1766
|
borderRadius: 2,
|
|
1727
|
-
minWidth: 1
|
|
1767
|
+
minWidth: 1,
|
|
1768
|
+
maxWidth: "100%"
|
|
1728
1769
|
},
|
|
1729
1770
|
radiusSample: {
|
|
1730
1771
|
width: 56,
|
|
@@ -1739,13 +1780,27 @@ const styles$1 = {
|
|
|
1739
1780
|
minHeight: 1
|
|
1740
1781
|
}
|
|
1741
1782
|
};
|
|
1783
|
+
function withCap(visual) {
|
|
1784
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
1785
|
+
className: "sb-dimension-bar sb-dimension-bar--capped",
|
|
1786
|
+
style: styles$1.cappedWrap,
|
|
1787
|
+
title: `capped at 480px`,
|
|
1788
|
+
children: [visual, /* @__PURE__ */ jsx("span", {
|
|
1789
|
+
className: "sb-dimension-bar__cap",
|
|
1790
|
+
"aria-hidden": true,
|
|
1791
|
+
children: "…"
|
|
1792
|
+
})]
|
|
1793
|
+
});
|
|
1794
|
+
}
|
|
1742
1795
|
function DimensionBar({ path, visual = "length" }) {
|
|
1743
1796
|
const project = useProject();
|
|
1744
1797
|
const { resolved } = project;
|
|
1798
|
+
const rootFontSize = useRootFontSize();
|
|
1745
1799
|
const cssVar = resolveCssVar(path, project);
|
|
1746
1800
|
const token = resolved[path];
|
|
1747
|
-
const pxValue = toPixels(token?.$value);
|
|
1748
|
-
const
|
|
1801
|
+
const pxValue = toPixels(token?.$value, rootFontSize);
|
|
1802
|
+
const capped = Number.isFinite(pxValue) && pxValue > 480;
|
|
1803
|
+
const cappedValue = capped ? `480px` : cssVar;
|
|
1749
1804
|
switch (visual) {
|
|
1750
1805
|
case "radius": return /* @__PURE__ */ jsx("div", {
|
|
1751
1806
|
style: {
|
|
@@ -1754,21 +1809,27 @@ function DimensionBar({ path, visual = "length" }) {
|
|
|
1754
1809
|
},
|
|
1755
1810
|
"aria-hidden": true
|
|
1756
1811
|
});
|
|
1757
|
-
case "size":
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1812
|
+
case "size": {
|
|
1813
|
+
const sample = /* @__PURE__ */ jsx("div", {
|
|
1814
|
+
style: {
|
|
1815
|
+
...styles$1.sizeSample,
|
|
1816
|
+
width: cappedValue,
|
|
1817
|
+
height: cappedValue
|
|
1818
|
+
},
|
|
1819
|
+
"aria-hidden": true
|
|
1820
|
+
});
|
|
1821
|
+
return capped ? withCap(sample) : sample;
|
|
1822
|
+
}
|
|
1823
|
+
default: {
|
|
1824
|
+
const bar = /* @__PURE__ */ jsx("div", {
|
|
1825
|
+
style: {
|
|
1826
|
+
...styles$1.bar,
|
|
1827
|
+
width: cappedValue
|
|
1828
|
+
},
|
|
1829
|
+
"aria-hidden": true
|
|
1830
|
+
});
|
|
1831
|
+
return capped ? withCap(bar) : bar;
|
|
1832
|
+
}
|
|
1772
1833
|
}
|
|
1773
1834
|
}
|
|
1774
1835
|
//#endregion
|
|
@@ -1878,29 +1939,27 @@ function formatUnknown(v) {
|
|
|
1878
1939
|
function DimensionScale({ filter, visual = "length", caption, sortBy = "value", sortDir = "asc" }) {
|
|
1879
1940
|
const project = useProject();
|
|
1880
1941
|
const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;
|
|
1942
|
+
const rootFontSize = useRootFontSize();
|
|
1881
1943
|
const rows = useMemo(() => {
|
|
1882
1944
|
return sortTokens(Object.entries(resolved).filter(([path, token]) => {
|
|
1883
1945
|
if (token.$type !== "dimension") return false;
|
|
1884
1946
|
return matchPath(path, filter);
|
|
1885
1947
|
}), {
|
|
1886
1948
|
by: sortBy,
|
|
1887
|
-
dir: sortDir
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
pxValue,
|
|
1895
|
-
capped: Number.isFinite(pxValue) && pxValue > 480
|
|
1896
|
-
};
|
|
1897
|
-
});
|
|
1949
|
+
dir: sortDir,
|
|
1950
|
+
rootFontSizePx: rootFontSize
|
|
1951
|
+
}).map(([path, token]) => ({
|
|
1952
|
+
path,
|
|
1953
|
+
cssVar: resolveCssVar(path, project),
|
|
1954
|
+
displayValue: formatTokenValue(token.$value, token.$type, "raw", project.listing[path])
|
|
1955
|
+
}));
|
|
1898
1956
|
}, [
|
|
1899
1957
|
resolved,
|
|
1900
1958
|
filter,
|
|
1901
1959
|
project,
|
|
1902
1960
|
sortBy,
|
|
1903
|
-
sortDir
|
|
1961
|
+
sortDir,
|
|
1962
|
+
rootFontSize
|
|
1904
1963
|
]);
|
|
1905
1964
|
const captionText = caption ?? `${rows.length} dimension${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
1906
1965
|
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
@@ -1928,19 +1987,12 @@ function DimensionScale({ filter, visual = "length", caption, sortBy = "value",
|
|
|
1928
1987
|
children: row.displayValue
|
|
1929
1988
|
})]
|
|
1930
1989
|
}),
|
|
1931
|
-
/* @__PURE__ */
|
|
1990
|
+
/* @__PURE__ */ jsx("div", {
|
|
1932
1991
|
className: "sb-dimension-scale__visual-cell",
|
|
1933
|
-
children:
|
|
1992
|
+
children: /* @__PURE__ */ jsx(DimensionBar, {
|
|
1934
1993
|
path: row.path,
|
|
1935
1994
|
visual
|
|
1936
|
-
})
|
|
1937
|
-
className: "sb-dimension-scale__cap",
|
|
1938
|
-
children: [
|
|
1939
|
-
"capped at ",
|
|
1940
|
-
480,
|
|
1941
|
-
"px"
|
|
1942
|
-
]
|
|
1943
|
-
})]
|
|
1995
|
+
})
|
|
1944
1996
|
}),
|
|
1945
1997
|
/* @__PURE__ */ jsx("span", {
|
|
1946
1998
|
className: "sb-dimension-scale__css-var",
|
|
@@ -2554,8 +2606,8 @@ function OpacityScale({ filter, type = "number", sampleColor = "color.accent.bg"
|
|
|
2554
2606
|
children: [/* @__PURE__ */ jsx("div", {
|
|
2555
2607
|
className: "sb-opacity-scale__swatch",
|
|
2556
2608
|
style: {
|
|
2557
|
-
"--
|
|
2558
|
-
"--
|
|
2609
|
+
"--swatchbook-opacity-scale-color": sampleColorVar,
|
|
2610
|
+
"--swatchbook-opacity-scale-alpha": String(row.opacity)
|
|
2559
2611
|
},
|
|
2560
2612
|
"aria-hidden": true
|
|
2561
2613
|
}), /* @__PURE__ */ jsxs("div", {
|
|
@@ -4523,6 +4575,7 @@ const LeafPreview = memo(function LeafPreview({ path, token }) {
|
|
|
4523
4575
|
function TokenTable({ filter, type, caption, sortBy = "path", sortDir = "asc", searchable = true, onSelect, id, indicators }) {
|
|
4524
4576
|
const { resolved, activeTheme, activeAxes, cssVarPrefix, listing, varianceByPath, indicators: indicatorBaseline } = useProject();
|
|
4525
4577
|
const colorFormat = useColorFormat();
|
|
4578
|
+
const rootFontSize = useRootFontSize();
|
|
4526
4579
|
const blockKey = useBlockKey("TokenTable", [
|
|
4527
4580
|
filter,
|
|
4528
4581
|
type,
|
|
@@ -4544,7 +4597,8 @@ function TokenTable({ filter, type, caption, sortBy = "path", sortDir = "asc", s
|
|
|
4544
4597
|
return true;
|
|
4545
4598
|
}), {
|
|
4546
4599
|
by: sortBy,
|
|
4547
|
-
dir: sortDir
|
|
4600
|
+
dir: sortDir,
|
|
4601
|
+
rootFontSizePx: rootFontSize
|
|
4548
4602
|
}).map(([path, token]) => {
|
|
4549
4603
|
const isColor = token.$type === "color";
|
|
4550
4604
|
const color = isColor ? resolveColorValue(path, token.$value, colorFormat, projectFields) : null;
|
|
@@ -4565,7 +4619,8 @@ function TokenTable({ filter, type, caption, sortBy = "path", sortDir = "asc", s
|
|
|
4565
4619
|
type,
|
|
4566
4620
|
colorFormat,
|
|
4567
4621
|
sortBy,
|
|
4568
|
-
sortDir
|
|
4622
|
+
sortDir,
|
|
4623
|
+
rootFontSize
|
|
4569
4624
|
]);
|
|
4570
4625
|
const visibleRows = useMemo(() => {
|
|
4571
4626
|
if (!searchable || deferredQuery.trim() === "") return rows;
|