@unpunnyfuns/swatchbook-blocks 0.14.1 → 0.16.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 +72 -10
- package/dist/index.mjs +2132 -1798
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +753 -513
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import './style.css';
|
|
2
2
|
import Color from "colorjs.io";
|
|
3
|
-
import { createContext, useCallback, useContext, useEffect, useMemo, useState, useSyncExternalStore } from "react";
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
4
4
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { addons } from "storybook/preview-api";
|
|
6
6
|
import { axes, css, cssVarPrefix, defaultTheme, diagnostics, presets, themes, themesResolved } from "virtual:swatchbook/tokens";
|
|
7
|
+
import { fuzzyFilter } from "@unpunnyfuns/swatchbook-core/fuzzy";
|
|
7
8
|
import cx from "clsx";
|
|
8
9
|
import { analyzeAxisVariance } from "@unpunnyfuns/swatchbook-core/variance";
|
|
9
10
|
//#region src/format-color.ts
|
|
@@ -871,150 +872,54 @@ function ColorPalette({ filter, groupBy, caption, sortBy = "path", sortDir = "as
|
|
|
871
872
|
});
|
|
872
873
|
}
|
|
873
874
|
//#endregion
|
|
874
|
-
//#region src/
|
|
875
|
-
const severityLabel = {
|
|
876
|
-
error: "ERROR",
|
|
877
|
-
warn: "WARN",
|
|
878
|
-
info: "INFO"
|
|
879
|
-
};
|
|
880
|
-
function summaryText(diagnostics) {
|
|
881
|
-
if (diagnostics.length === 0) return "✔ OK · no diagnostics";
|
|
882
|
-
const counts = {
|
|
883
|
-
error: 0,
|
|
884
|
-
warn: 0,
|
|
885
|
-
info: 0
|
|
886
|
-
};
|
|
887
|
-
for (const d of diagnostics) counts[d.severity] += 1;
|
|
888
|
-
const parts = [];
|
|
889
|
-
if (counts.error > 0) parts.push(`✖ ${counts.error} error${counts.error === 1 ? "" : "s"}`);
|
|
890
|
-
if (counts.warn > 0) parts.push(`⚠ ${counts.warn} warning${counts.warn === 1 ? "" : "s"}`);
|
|
891
|
-
if (counts.info > 0) parts.push(`${counts.info} info`);
|
|
892
|
-
return parts.join(" · ");
|
|
893
|
-
}
|
|
894
|
-
function diagnosticKey(d, i) {
|
|
895
|
-
return `${d.severity}:${d.group}:${d.filename ?? ""}:${d.line ?? ""}:${d.message}:${i}`;
|
|
896
|
-
}
|
|
897
|
-
function summaryVariant(diagnostics) {
|
|
898
|
-
if (diagnostics.length === 0) return "ok";
|
|
899
|
-
if (diagnostics.some((d) => d.severity === "error")) return "error";
|
|
900
|
-
if (diagnostics.some((d) => d.severity === "warn")) return "warn";
|
|
901
|
-
return null;
|
|
902
|
-
}
|
|
875
|
+
//#region src/internal/CopyButton.tsx
|
|
903
876
|
/**
|
|
904
|
-
*
|
|
905
|
-
*
|
|
906
|
-
*
|
|
907
|
-
*
|
|
908
|
-
*
|
|
909
|
-
* Replaces the diagnostics section from the addon's (now-retired) Design
|
|
910
|
-
* Tokens panel. Consumers compose it alongside TokenNavigator / TokenTable
|
|
911
|
-
* on their own MDX pages.
|
|
877
|
+
* Copy the given string to the clipboard and briefly surface a "Copied!"
|
|
878
|
+
* state. Falls back silently on unsupported clipboard APIs (older Safari,
|
|
879
|
+
* insecure origins) — the click still happens, the user just won't see the
|
|
880
|
+
* tick. No custom permission prompt: relies on the browser's native user-
|
|
881
|
+
* activation gate.
|
|
912
882
|
*/
|
|
913
|
-
function
|
|
914
|
-
const
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
883
|
+
function CopyButton$1({ value, label, variant = "icon", className }) {
|
|
884
|
+
const [copied, setCopied] = useState(false);
|
|
885
|
+
const timerRef = useRef(null);
|
|
886
|
+
useEffect(() => {
|
|
887
|
+
return () => {
|
|
888
|
+
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
889
|
+
};
|
|
890
|
+
}, []);
|
|
891
|
+
const handleClick = useCallback(() => {
|
|
892
|
+
try {
|
|
893
|
+
navigator.clipboard?.writeText(value);
|
|
894
|
+
} catch {
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
setCopied(true);
|
|
898
|
+
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
899
|
+
timerRef.current = setTimeout(() => setCopied(false), 1500);
|
|
900
|
+
}, [value]);
|
|
901
|
+
const ariaLabel = label ?? `Copy ${value}`;
|
|
902
|
+
const classes = ["sb-copy-button", `sb-copy-button--${variant}`];
|
|
903
|
+
if (copied) classes.push("sb-copy-button--copied");
|
|
904
|
+
if (className) classes.push(className);
|
|
905
|
+
return /* @__PURE__ */ jsx("button", {
|
|
906
|
+
type: "button",
|
|
907
|
+
className: classes.join(" "),
|
|
908
|
+
onClick: handleClick,
|
|
909
|
+
"aria-label": ariaLabel,
|
|
910
|
+
title: ariaLabel,
|
|
911
|
+
"data-copied": copied ? "true" : void 0,
|
|
912
|
+
children: variant === "text" ? /* @__PURE__ */ jsx("span", {
|
|
913
|
+
className: "sb-copy-button__text",
|
|
914
|
+
children: copied ? "Copied" : "Copy"
|
|
915
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
916
|
+
className: "sb-copy-button__glyph",
|
|
917
|
+
"aria-hidden": true,
|
|
918
|
+
children: copied ? "✓" : "⧉"
|
|
943
919
|
})
|
|
944
920
|
});
|
|
945
921
|
}
|
|
946
922
|
//#endregion
|
|
947
|
-
//#region src/dimension-scale/DimensionBar.tsx
|
|
948
|
-
const MAX_RENDER_PX$1 = 480;
|
|
949
|
-
const styles$1 = {
|
|
950
|
-
bar: {
|
|
951
|
-
height: 14,
|
|
952
|
-
background: "var(--swatchbook-accent-bg, #3b82f6)",
|
|
953
|
-
borderRadius: 2,
|
|
954
|
-
minWidth: 1
|
|
955
|
-
},
|
|
956
|
-
radiusSample: {
|
|
957
|
-
width: 56,
|
|
958
|
-
height: 56,
|
|
959
|
-
background: "var(--swatchbook-accent-bg, #3b82f6)",
|
|
960
|
-
border: BORDER_STRONG
|
|
961
|
-
},
|
|
962
|
-
sizeSample: {
|
|
963
|
-
background: "var(--swatchbook-accent-bg, #3b82f6)",
|
|
964
|
-
border: BORDER_STRONG,
|
|
965
|
-
minWidth: 1,
|
|
966
|
-
minHeight: 1
|
|
967
|
-
}
|
|
968
|
-
};
|
|
969
|
-
/**
|
|
970
|
-
* Convert a DTCG dimension `$value` (`{ value, unit }`) to pixels for the
|
|
971
|
-
* purpose of deciding whether to cap the rendered bar. Returns `NaN` for
|
|
972
|
-
* units we can't reasonably approximate (ex / ch / %), which the caller
|
|
973
|
-
* treats as "render at cssVar but don't cap".
|
|
974
|
-
*/
|
|
975
|
-
function toPixels$1(raw) {
|
|
976
|
-
if (raw == null || typeof raw !== "object") return NaN;
|
|
977
|
-
const v = raw;
|
|
978
|
-
if (typeof v.value !== "number" || typeof v.unit !== "string") return NaN;
|
|
979
|
-
switch (v.unit) {
|
|
980
|
-
case "px": return v.value;
|
|
981
|
-
case "rem":
|
|
982
|
-
case "em": return v.value * 16;
|
|
983
|
-
default: return NaN;
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
function DimensionBar({ path, kind = "length" }) {
|
|
987
|
-
const { resolved, cssVarPrefix } = useProject();
|
|
988
|
-
const cssVar = makeCssVar(path, cssVarPrefix);
|
|
989
|
-
const token = resolved[path];
|
|
990
|
-
const pxValue = toPixels$1(token?.$value);
|
|
991
|
-
const cappedValue = Number.isFinite(pxValue) && pxValue > MAX_RENDER_PX$1 ? `${MAX_RENDER_PX$1}px` : cssVar;
|
|
992
|
-
switch (kind) {
|
|
993
|
-
case "radius": return /* @__PURE__ */ jsx("div", {
|
|
994
|
-
style: {
|
|
995
|
-
...styles$1.radiusSample,
|
|
996
|
-
borderRadius: cssVar
|
|
997
|
-
},
|
|
998
|
-
"aria-hidden": true
|
|
999
|
-
});
|
|
1000
|
-
case "size": return /* @__PURE__ */ jsx("div", {
|
|
1001
|
-
style: {
|
|
1002
|
-
...styles$1.sizeSample,
|
|
1003
|
-
width: cappedValue,
|
|
1004
|
-
height: cappedValue
|
|
1005
|
-
},
|
|
1006
|
-
"aria-hidden": true
|
|
1007
|
-
});
|
|
1008
|
-
default: return /* @__PURE__ */ jsx("div", {
|
|
1009
|
-
style: {
|
|
1010
|
-
...styles$1.bar,
|
|
1011
|
-
width: cappedValue
|
|
1012
|
-
},
|
|
1013
|
-
"aria-hidden": true
|
|
1014
|
-
});
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
//#endregion
|
|
1018
923
|
//#region src/internal/format-token-value.ts
|
|
1019
924
|
/**
|
|
1020
925
|
* Produce a single-line display string for any DTCG token `$value`,
|
|
@@ -1154,768 +1059,596 @@ function formatUnknown(v) {
|
|
|
1154
1059
|
}
|
|
1155
1060
|
}
|
|
1156
1061
|
//#endregion
|
|
1157
|
-
//#region src/
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
const rows = useMemo(() => {
|
|
1173
|
-
return sortTokens(Object.entries(resolved).filter(([path, token]) => {
|
|
1174
|
-
if (token.$type !== "dimension") return false;
|
|
1175
|
-
return globMatch(path, filter);
|
|
1176
|
-
}), {
|
|
1177
|
-
by: sortBy,
|
|
1178
|
-
dir: sortDir
|
|
1179
|
-
}).map(([path, token]) => {
|
|
1180
|
-
const pxValue = toPixels(token.$value);
|
|
1181
|
-
return {
|
|
1182
|
-
path,
|
|
1183
|
-
cssVar: makeCssVar(path, cssVarPrefix),
|
|
1184
|
-
displayValue: formatTokenValue(token.$value, token.$type, "raw"),
|
|
1185
|
-
pxValue,
|
|
1186
|
-
capped: Number.isFinite(pxValue) && pxValue > MAX_RENDER_PX
|
|
1187
|
-
};
|
|
1188
|
-
});
|
|
1189
|
-
}, [
|
|
1190
|
-
resolved,
|
|
1191
|
-
filter,
|
|
1192
|
-
cssVarPrefix,
|
|
1193
|
-
sortBy,
|
|
1194
|
-
sortDir
|
|
1195
|
-
]);
|
|
1196
|
-
const captionText = caption ?? `${rows.length} dimension${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
1197
|
-
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
1198
|
-
...themeAttrs(cssVarPrefix, activeTheme),
|
|
1199
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
1200
|
-
className: "sb-block__empty",
|
|
1201
|
-
children: "No dimension tokens match this filter."
|
|
1202
|
-
})
|
|
1203
|
-
});
|
|
1204
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1205
|
-
...themeAttrs(cssVarPrefix, activeTheme),
|
|
1206
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
1207
|
-
className: "sb-block__caption",
|
|
1208
|
-
children: captionText
|
|
1209
|
-
}), rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
1210
|
-
className: "sb-dimension-scale__row",
|
|
1211
|
-
children: [
|
|
1212
|
-
/* @__PURE__ */ jsxs("div", {
|
|
1213
|
-
className: "sb-dimension-scale__meta",
|
|
1214
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
1215
|
-
className: "sb-dimension-scale__path",
|
|
1216
|
-
children: row.path
|
|
1217
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
1218
|
-
className: "sb-dimension-scale__specs",
|
|
1219
|
-
children: row.displayValue
|
|
1220
|
-
})]
|
|
1221
|
-
}),
|
|
1222
|
-
/* @__PURE__ */ jsxs("div", {
|
|
1223
|
-
className: "sb-dimension-scale__visual-cell",
|
|
1224
|
-
children: [/* @__PURE__ */ jsx(DimensionBar, {
|
|
1225
|
-
path: row.path,
|
|
1226
|
-
kind
|
|
1227
|
-
}), row.capped && /* @__PURE__ */ jsxs("span", {
|
|
1228
|
-
className: "sb-dimension-scale__cap",
|
|
1229
|
-
children: [
|
|
1230
|
-
"capped at ",
|
|
1231
|
-
MAX_RENDER_PX,
|
|
1232
|
-
"px"
|
|
1233
|
-
]
|
|
1234
|
-
})]
|
|
1235
|
-
}),
|
|
1236
|
-
/* @__PURE__ */ jsx("span", {
|
|
1237
|
-
className: "sb-dimension-scale__css-var",
|
|
1238
|
-
children: row.cssVar
|
|
1239
|
-
})
|
|
1240
|
-
]
|
|
1241
|
-
}, row.path))]
|
|
1242
|
-
});
|
|
1062
|
+
//#region src/token-detail/internal.ts
|
|
1063
|
+
function useTokenDetailData(path) {
|
|
1064
|
+
const { activeTheme, activeAxes, axes, themes, themesResolved, resolved, cssVarPrefix } = useProject();
|
|
1065
|
+
const typedResolved = resolved;
|
|
1066
|
+
return {
|
|
1067
|
+
token: typedResolved[path],
|
|
1068
|
+
cssVar: makeCssVar(path, cssVarPrefix),
|
|
1069
|
+
activeTheme,
|
|
1070
|
+
activeAxes,
|
|
1071
|
+
axes,
|
|
1072
|
+
themes,
|
|
1073
|
+
themesResolved,
|
|
1074
|
+
resolved: typedResolved,
|
|
1075
|
+
cssVarPrefix
|
|
1076
|
+
};
|
|
1243
1077
|
}
|
|
1244
1078
|
//#endregion
|
|
1245
|
-
//#region src/
|
|
1246
|
-
function
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
]);
|
|
1272
|
-
const captionText = caption ?? `${rows.length} fontFamily token${rows.length === 1 ? "" : "s"}${filter && filter !== "fontFamily" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
1273
|
-
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
1274
|
-
...themeAttrs(cssVarPrefix, activeTheme),
|
|
1275
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
1276
|
-
className: "sb-block__empty",
|
|
1277
|
-
children: "No fontFamily tokens match this filter."
|
|
1278
|
-
})
|
|
1279
|
-
});
|
|
1280
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1281
|
-
...themeAttrs(cssVarPrefix, activeTheme),
|
|
1282
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
1283
|
-
className: "sb-block__caption",
|
|
1284
|
-
children: captionText
|
|
1285
|
-
}), rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
1286
|
-
className: "sb-font-family-sample__row",
|
|
1287
|
-
children: [
|
|
1288
|
-
/* @__PURE__ */ jsxs("div", {
|
|
1289
|
-
className: "sb-font-family-sample__meta",
|
|
1290
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
1291
|
-
className: "sb-font-family-sample__path",
|
|
1292
|
-
children: row.path
|
|
1293
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
1294
|
-
className: "sb-font-family-sample__stack",
|
|
1295
|
-
children: row.stack
|
|
1296
|
-
})]
|
|
1297
|
-
}),
|
|
1298
|
-
/* @__PURE__ */ jsx("div", {
|
|
1299
|
-
className: "sb-font-family-sample__sample",
|
|
1300
|
-
style: { fontFamily: row.cssVar },
|
|
1301
|
-
children: sample
|
|
1302
|
-
}),
|
|
1303
|
-
/* @__PURE__ */ jsx("span", {
|
|
1304
|
-
className: "sb-font-family-sample__css-var",
|
|
1305
|
-
children: row.cssVar
|
|
1306
|
-
})
|
|
1307
|
-
]
|
|
1308
|
-
}, row.path))]
|
|
1309
|
-
});
|
|
1079
|
+
//#region src/token-detail/AliasChain.tsx
|
|
1080
|
+
function AliasChain({ path }) {
|
|
1081
|
+
const { token } = useTokenDetailData(path);
|
|
1082
|
+
const chain = useMemo(() => {
|
|
1083
|
+
if (!token) return [];
|
|
1084
|
+
if (Array.isArray(token.aliasChain) && token.aliasChain.length > 0) return [path, ...token.aliasChain];
|
|
1085
|
+
if (typeof token.aliasOf === "string") return [path, token.aliasOf];
|
|
1086
|
+
return [path];
|
|
1087
|
+
}, [token, path]);
|
|
1088
|
+
if (chain.length <= 1) return null;
|
|
1089
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
1090
|
+
className: "sb-token-detail__section-header",
|
|
1091
|
+
children: "Alias chain"
|
|
1092
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1093
|
+
className: "sb-token-detail__chain",
|
|
1094
|
+
children: chain.map((step, i) => /* @__PURE__ */ jsxs("span", {
|
|
1095
|
+
className: "sb-token-detail__chain",
|
|
1096
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1097
|
+
className: "sb-token-detail__chain-node",
|
|
1098
|
+
children: step
|
|
1099
|
+
}), i < chain.length - 1 && /* @__PURE__ */ jsx("span", {
|
|
1100
|
+
className: "sb-token-detail__arrow",
|
|
1101
|
+
children: "→"
|
|
1102
|
+
})]
|
|
1103
|
+
}, step))
|
|
1104
|
+
})] });
|
|
1310
1105
|
}
|
|
1311
1106
|
//#endregion
|
|
1312
|
-
//#region src/
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
}),
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
resolved,
|
|
1338
|
-
filter,
|
|
1339
|
-
cssVarPrefix,
|
|
1340
|
-
sortBy,
|
|
1341
|
-
sortDir
|
|
1342
|
-
]);
|
|
1343
|
-
const captionText = caption ?? `${rows.length} fontWeight token${rows.length === 1 ? "" : "s"}${filter && filter !== "fontWeight" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
1344
|
-
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
1345
|
-
...themeAttrs(cssVarPrefix, activeTheme),
|
|
1346
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
1347
|
-
className: "sb-block__empty",
|
|
1348
|
-
children: "No fontWeight tokens match this filter."
|
|
1349
|
-
})
|
|
1350
|
-
});
|
|
1351
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1352
|
-
...themeAttrs(cssVarPrefix, activeTheme),
|
|
1353
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
1354
|
-
className: "sb-block__caption",
|
|
1355
|
-
children: captionText
|
|
1356
|
-
}), rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
1357
|
-
className: "sb-font-weight-scale__row",
|
|
1107
|
+
//#region src/token-detail/AliasedBy.tsx
|
|
1108
|
+
const ALIASED_BY_DEPTH_CAP = 6;
|
|
1109
|
+
const GROUP_RANK = {
|
|
1110
|
+
ref: 0,
|
|
1111
|
+
sys: 1
|
|
1112
|
+
};
|
|
1113
|
+
function AliasedBy({ path }) {
|
|
1114
|
+
const { resolved } = useTokenDetailData(path);
|
|
1115
|
+
const tree = useMemo(() => buildAliasedByTree(path, resolved), [path, resolved]);
|
|
1116
|
+
const truncated = useMemo(() => treeHasTruncation(tree), [tree]);
|
|
1117
|
+
if (tree.length === 0) return null;
|
|
1118
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1119
|
+
/* @__PURE__ */ jsx("div", {
|
|
1120
|
+
className: "sb-token-detail__section-header",
|
|
1121
|
+
children: "Aliased by"
|
|
1122
|
+
}),
|
|
1123
|
+
/* @__PURE__ */ jsx("ul", {
|
|
1124
|
+
className: "sb-token-detail__aliased-by-list",
|
|
1125
|
+
children: tree.map((node) => /* @__PURE__ */ jsx(AliasedByRow, {
|
|
1126
|
+
node,
|
|
1127
|
+
depth: 0
|
|
1128
|
+
}, node.path))
|
|
1129
|
+
}),
|
|
1130
|
+
truncated && /* @__PURE__ */ jsxs("div", {
|
|
1131
|
+
className: "sb-token-detail__aliased-by-truncated",
|
|
1358
1132
|
children: [
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
className: "sb-font-weight-scale__path",
|
|
1363
|
-
children: row.path
|
|
1364
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
1365
|
-
className: "sb-font-weight-scale__value",
|
|
1366
|
-
children: row.display
|
|
1367
|
-
})]
|
|
1368
|
-
}),
|
|
1369
|
-
/* @__PURE__ */ jsx("div", {
|
|
1370
|
-
className: "sb-font-weight-scale__sample",
|
|
1371
|
-
style: { fontWeight: row.cssVar },
|
|
1372
|
-
children: sample
|
|
1373
|
-
}),
|
|
1374
|
-
/* @__PURE__ */ jsx("span", {
|
|
1375
|
-
className: "sb-font-weight-scale__css-var",
|
|
1376
|
-
children: row.cssVar
|
|
1377
|
-
})
|
|
1133
|
+
"Further descendants truncated at depth ",
|
|
1134
|
+
ALIASED_BY_DEPTH_CAP,
|
|
1135
|
+
"."
|
|
1378
1136
|
]
|
|
1379
|
-
}
|
|
1380
|
-
});
|
|
1137
|
+
})
|
|
1138
|
+
] });
|
|
1381
1139
|
}
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1140
|
+
function AliasedByRow({ node, depth }) {
|
|
1141
|
+
return /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsx("div", {
|
|
1142
|
+
className: "sb-token-detail__aliased-by-row",
|
|
1143
|
+
style: { paddingLeft: depth * 16 },
|
|
1144
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
1145
|
+
className: "sb-token-detail__chain-node",
|
|
1146
|
+
children: node.path
|
|
1147
|
+
})
|
|
1148
|
+
}), node.children.length > 0 && /* @__PURE__ */ jsx("ul", {
|
|
1149
|
+
className: "sb-token-detail__aliased-by-list",
|
|
1150
|
+
children: node.children.map((child) => /* @__PURE__ */ jsx(AliasedByRow, {
|
|
1151
|
+
node: child,
|
|
1152
|
+
depth: depth + 1
|
|
1153
|
+
}, child.path))
|
|
1154
|
+
})] });
|
|
1387
1155
|
}
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
if (r === void 0 || g === void 0 || b === void 0) return "transparent";
|
|
1394
|
-
const alpha = color.alpha ?? 1;
|
|
1395
|
-
return alpha === 1 ? `rgb(${pct(r)} ${pct(g)} ${pct(b)})` : `rgb(${pct(r)} ${pct(g)} ${pct(b)} / ${alpha})`;
|
|
1156
|
+
function buildAliasedByTree(rootPath, resolved) {
|
|
1157
|
+
const direct = resolved[rootPath]?.aliasedBy;
|
|
1158
|
+
if (!direct || direct.length === 0) return [];
|
|
1159
|
+
const visited = new Set([rootPath]);
|
|
1160
|
+
return sortPaths(direct).map((p) => walk(p, resolved, visited, 1));
|
|
1396
1161
|
}
|
|
1397
|
-
function
|
|
1398
|
-
|
|
1162
|
+
function walk(path, resolved, visited, depth) {
|
|
1163
|
+
if (visited.has(path)) return {
|
|
1164
|
+
path,
|
|
1165
|
+
children: []
|
|
1166
|
+
};
|
|
1167
|
+
visited.add(path);
|
|
1168
|
+
const parents = resolved[path]?.aliasedBy;
|
|
1169
|
+
if (!parents || parents.length === 0) return {
|
|
1170
|
+
path,
|
|
1171
|
+
children: []
|
|
1172
|
+
};
|
|
1173
|
+
if (depth >= ALIASED_BY_DEPTH_CAP) return {
|
|
1174
|
+
path,
|
|
1175
|
+
children: [],
|
|
1176
|
+
truncated: true
|
|
1177
|
+
};
|
|
1178
|
+
return {
|
|
1179
|
+
path,
|
|
1180
|
+
children: sortPaths(parents).map((p) => walk(p, resolved, visited, depth + 1))
|
|
1181
|
+
};
|
|
1399
1182
|
}
|
|
1400
|
-
function
|
|
1401
|
-
|
|
1183
|
+
function sortPaths(paths) {
|
|
1184
|
+
return paths.toSorted((a, b) => {
|
|
1185
|
+
const ra = GROUP_RANK[a.split(".")[0] ?? ""] ?? 2;
|
|
1186
|
+
const rb = GROUP_RANK[b.split(".")[0] ?? ""] ?? 2;
|
|
1187
|
+
return ra !== rb ? ra - rb : a.localeCompare(b, void 0, { numeric: true });
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
function treeHasTruncation(nodes) {
|
|
1191
|
+
for (const n of nodes) {
|
|
1192
|
+
if (n.truncated) return true;
|
|
1193
|
+
if (treeHasTruncation(n.children)) return true;
|
|
1194
|
+
}
|
|
1195
|
+
return false;
|
|
1196
|
+
}
|
|
1197
|
+
//#endregion
|
|
1198
|
+
//#region src/token-detail/AxisVariance.tsx
|
|
1199
|
+
function AxisVariance({ path }) {
|
|
1200
|
+
const { token, cssVar, axes, themes, themesResolved, activeAxes, cssVarPrefix } = useTokenDetailData(path);
|
|
1402
1201
|
const colorFormat = useColorFormat();
|
|
1403
|
-
const
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
cssVar: makeCssVar(path, cssVarPrefix),
|
|
1413
|
-
stops: asStops(token.$value)
|
|
1414
|
-
}));
|
|
1202
|
+
const tokenType = token?.$type;
|
|
1203
|
+
const isColor = tokenType === "color";
|
|
1204
|
+
const formatFn = (t) => valueFor(t, tokenType, colorFormat);
|
|
1205
|
+
const variance = useMemo(() => {
|
|
1206
|
+
const result = analyzeAxisVariance(path, axes, themes, themesResolved);
|
|
1207
|
+
return {
|
|
1208
|
+
kind: result.kind === "constant" ? "constant" : result.kind === "single" ? "one-axis" : "multi-axis",
|
|
1209
|
+
varyingAxes: result.varyingAxes
|
|
1210
|
+
};
|
|
1415
1211
|
}, [
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
sortDir
|
|
1212
|
+
path,
|
|
1213
|
+
axes,
|
|
1214
|
+
themes,
|
|
1215
|
+
themesResolved
|
|
1421
1216
|
]);
|
|
1422
|
-
|
|
1423
|
-
if (
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
className: "sb-gradient-palette__stop-row",
|
|
1457
|
-
children: [
|
|
1458
|
-
/* @__PURE__ */ jsx("span", {
|
|
1459
|
-
className: "sb-gradient-palette__stop-swatch",
|
|
1460
|
-
style: { background: stopCssColor(stop) },
|
|
1461
|
-
"aria-hidden": true
|
|
1462
|
-
}),
|
|
1463
|
-
/* @__PURE__ */ jsx("span", { children: formatColor(stop.color, colorFormat).value }),
|
|
1464
|
-
/* @__PURE__ */ jsxs("span", {
|
|
1465
|
-
className: "sb-gradient-palette__stop-position",
|
|
1466
|
-
children: [
|
|
1467
|
-
"@ ",
|
|
1468
|
-
((stop.position ?? 0) * 100).toFixed(0),
|
|
1469
|
-
"%"
|
|
1470
|
-
]
|
|
1471
|
-
})
|
|
1472
|
-
]
|
|
1473
|
-
}, stopKey(row.path, stop, i)))
|
|
1217
|
+
if (themes.length === 0) return /* @__PURE__ */ jsx(Fragment, {});
|
|
1218
|
+
if (variance.kind === "constant") {
|
|
1219
|
+
const anyTheme = themes[0];
|
|
1220
|
+
const value = anyTheme ? formatFn(themesResolved[anyTheme.name]?.[path]) : "—";
|
|
1221
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
1222
|
+
className: "sb-token-detail__section-header",
|
|
1223
|
+
children: "Values across axes"
|
|
1224
|
+
}), /* @__PURE__ */ jsx("table", {
|
|
1225
|
+
className: "sb-token-detail__theme-table",
|
|
1226
|
+
"data-testid": "token-detail-values",
|
|
1227
|
+
children: /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx("tr", {
|
|
1228
|
+
className: "sb-token-detail__theme-row",
|
|
1229
|
+
children: /* @__PURE__ */ jsxs("td", {
|
|
1230
|
+
className: "sb-token-detail__theme-cell",
|
|
1231
|
+
"data-testid": "token-detail-constant",
|
|
1232
|
+
children: [
|
|
1233
|
+
isColor && /* @__PURE__ */ jsx("span", {
|
|
1234
|
+
className: "sb-token-detail__swatch",
|
|
1235
|
+
style: { background: cssVar },
|
|
1236
|
+
"aria-hidden": true
|
|
1237
|
+
}),
|
|
1238
|
+
value,
|
|
1239
|
+
/* @__PURE__ */ jsxs("span", {
|
|
1240
|
+
style: {
|
|
1241
|
+
opacity: .6,
|
|
1242
|
+
marginLeft: 8
|
|
1243
|
+
},
|
|
1244
|
+
children: [
|
|
1245
|
+
"same across all ",
|
|
1246
|
+
themes.length,
|
|
1247
|
+
" tuples"
|
|
1248
|
+
]
|
|
1249
|
+
})
|
|
1250
|
+
]
|
|
1474
1251
|
})
|
|
1252
|
+
}) })
|
|
1253
|
+
})] });
|
|
1254
|
+
}
|
|
1255
|
+
if (variance.kind === "one-axis") {
|
|
1256
|
+
const axisName = variance.varyingAxes[0];
|
|
1257
|
+
if (!axisName) return /* @__PURE__ */ jsx(Fragment, {});
|
|
1258
|
+
const axis = axes.find((a) => a.name === axisName);
|
|
1259
|
+
if (!axis) return /* @__PURE__ */ jsx(Fragment, {});
|
|
1260
|
+
const contextValues = axis.contexts.map((ctx) => {
|
|
1261
|
+
const target = {
|
|
1262
|
+
...activeAxes,
|
|
1263
|
+
[axisName]: ctx
|
|
1264
|
+
};
|
|
1265
|
+
const name = themes.find((t) => {
|
|
1266
|
+
const input = t.input;
|
|
1267
|
+
return Object.keys(input).every((k) => input[k] === target[k]);
|
|
1268
|
+
})?.name ?? "";
|
|
1269
|
+
return {
|
|
1270
|
+
ctx,
|
|
1271
|
+
themeName: name,
|
|
1272
|
+
value: name ? formatFn(themesResolved[name]?.[path]) : "—"
|
|
1273
|
+
};
|
|
1274
|
+
});
|
|
1275
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
1276
|
+
className: "sb-token-detail__section-header",
|
|
1277
|
+
children: ["Varies with ", axisName]
|
|
1278
|
+
}), /* @__PURE__ */ jsx("table", {
|
|
1279
|
+
className: "sb-token-detail__theme-table",
|
|
1280
|
+
"data-testid": "token-detail-values",
|
|
1281
|
+
children: /* @__PURE__ */ jsx("tbody", { children: contextValues.map((row) => /* @__PURE__ */ jsxs("tr", {
|
|
1282
|
+
className: "sb-token-detail__theme-row",
|
|
1283
|
+
"data-axis": axisName,
|
|
1284
|
+
"data-context": row.ctx,
|
|
1285
|
+
children: [/* @__PURE__ */ jsx("td", {
|
|
1286
|
+
className: "sb-token-detail__theme-cell",
|
|
1287
|
+
style: { width: "30%" },
|
|
1288
|
+
children: row.ctx
|
|
1289
|
+
}), /* @__PURE__ */ jsxs("td", {
|
|
1290
|
+
className: "sb-token-detail__theme-cell",
|
|
1291
|
+
children: [isColor && row.themeName && /* @__PURE__ */ jsx("span", {
|
|
1292
|
+
className: "sb-token-detail__swatch",
|
|
1293
|
+
style: { background: cssVar },
|
|
1294
|
+
[dataAttr(cssVarPrefix, "theme")]: row.themeName,
|
|
1295
|
+
"aria-hidden": true
|
|
1296
|
+
}), row.value]
|
|
1297
|
+
})]
|
|
1298
|
+
}, row.ctx)) })
|
|
1299
|
+
})] });
|
|
1300
|
+
}
|
|
1301
|
+
const [rowAxis, colAxis, ...extra] = variance.varyingAxes.map((name) => axes.find((a) => a.name === name)).filter((a) => Boolean(a)).toSorted((a, b) => b.contexts.length - a.contexts.length);
|
|
1302
|
+
if (!rowAxis || !colAxis) return /* @__PURE__ */ jsx(Fragment, {});
|
|
1303
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1304
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1305
|
+
className: "sb-token-detail__section-header",
|
|
1306
|
+
children: ["Varies with ", variance.varyingAxes.join(" × ")]
|
|
1307
|
+
}),
|
|
1308
|
+
/* @__PURE__ */ jsxs("table", {
|
|
1309
|
+
className: "sb-token-detail__theme-table",
|
|
1310
|
+
"data-testid": "token-detail-values",
|
|
1311
|
+
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", {
|
|
1312
|
+
className: "sb-token-detail__theme-row",
|
|
1313
|
+
children: [/* @__PURE__ */ jsxs("th", {
|
|
1314
|
+
className: "sb-token-detail__theme-cell",
|
|
1315
|
+
style: {
|
|
1316
|
+
textAlign: "left",
|
|
1317
|
+
opacity: .7
|
|
1318
|
+
},
|
|
1319
|
+
children: [
|
|
1320
|
+
rowAxis.name,
|
|
1321
|
+
" \\ ",
|
|
1322
|
+
colAxis.name
|
|
1323
|
+
]
|
|
1324
|
+
}), colAxis.contexts.map((col) => /* @__PURE__ */ jsx("th", {
|
|
1325
|
+
className: "sb-token-detail__theme-cell",
|
|
1326
|
+
style: {
|
|
1327
|
+
textAlign: "left",
|
|
1328
|
+
opacity: .7
|
|
1329
|
+
},
|
|
1330
|
+
children: col
|
|
1331
|
+
}, col))]
|
|
1332
|
+
}) }), /* @__PURE__ */ jsx("tbody", { children: rowAxis.contexts.map((row) => /* @__PURE__ */ jsxs("tr", {
|
|
1333
|
+
className: "sb-token-detail__theme-row",
|
|
1334
|
+
children: [/* @__PURE__ */ jsx("td", {
|
|
1335
|
+
className: "sb-token-detail__theme-cell",
|
|
1336
|
+
children: row
|
|
1337
|
+
}), colAxis.contexts.map((col) => {
|
|
1338
|
+
const name = tupleName(themes, {
|
|
1339
|
+
...activeAxes,
|
|
1340
|
+
[rowAxis.name]: row,
|
|
1341
|
+
[colAxis.name]: col
|
|
1342
|
+
});
|
|
1343
|
+
const value = name ? formatFn(themesResolved[name]?.[path]) : "—";
|
|
1344
|
+
return /* @__PURE__ */ jsxs("td", {
|
|
1345
|
+
className: "sb-token-detail__theme-cell",
|
|
1346
|
+
"data-row": row,
|
|
1347
|
+
"data-col": col,
|
|
1348
|
+
children: [isColor && name && /* @__PURE__ */ jsx("span", {
|
|
1349
|
+
className: "sb-token-detail__swatch",
|
|
1350
|
+
style: { background: cssVar },
|
|
1351
|
+
[dataAttr(cssVarPrefix, "theme")]: name,
|
|
1352
|
+
"aria-hidden": true
|
|
1353
|
+
}), value]
|
|
1354
|
+
}, col);
|
|
1355
|
+
})]
|
|
1356
|
+
}, row)) })]
|
|
1357
|
+
}),
|
|
1358
|
+
extra.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
1359
|
+
className: "sb-token-detail__aliased-by-truncated",
|
|
1360
|
+
style: { marginTop: 6 },
|
|
1361
|
+
children: [
|
|
1362
|
+
"Values also vary with ",
|
|
1363
|
+
extra.map((a) => a.name).join(", "),
|
|
1364
|
+
"; matrix shows the slice for the active selection."
|
|
1475
1365
|
]
|
|
1476
|
-
}
|
|
1477
|
-
});
|
|
1366
|
+
})
|
|
1367
|
+
] });
|
|
1478
1368
|
}
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
* Reactive `prefers-reduced-motion: reduce` detector. Returns the current
|
|
1483
|
-
* match and updates if the user toggles the OS-level preference.
|
|
1484
|
-
*/
|
|
1485
|
-
function usePrefersReducedMotion() {
|
|
1486
|
-
const [reduced, setReduced] = useState(false);
|
|
1487
|
-
useEffect(() => {
|
|
1488
|
-
if (typeof window === "undefined") return;
|
|
1489
|
-
const query = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
1490
|
-
setReduced(query.matches);
|
|
1491
|
-
const onChange = (e) => setReduced(e.matches);
|
|
1492
|
-
query.addEventListener("change", onChange);
|
|
1493
|
-
return () => query.removeEventListener("change", onChange);
|
|
1494
|
-
}, []);
|
|
1495
|
-
return reduced;
|
|
1369
|
+
function valueFor(token, $type, format) {
|
|
1370
|
+
if (!token) return "—";
|
|
1371
|
+
return formatTokenValue(token.$value, $type, format);
|
|
1496
1372
|
}
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
const
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
track: {
|
|
1503
|
-
position: "relative",
|
|
1504
|
-
height: 36,
|
|
1505
|
-
background: SURFACE_MUTED,
|
|
1506
|
-
borderRadius: 18,
|
|
1507
|
-
overflow: "hidden"
|
|
1508
|
-
},
|
|
1509
|
-
ball: {
|
|
1510
|
-
position: "absolute",
|
|
1511
|
-
top: "50%",
|
|
1512
|
-
width: 28,
|
|
1513
|
-
height: 28,
|
|
1514
|
-
marginTop: -14,
|
|
1515
|
-
borderRadius: "50%",
|
|
1516
|
-
background: "var(--swatchbook-accent-bg, #3b82f6)"
|
|
1517
|
-
},
|
|
1518
|
-
reducedMotion: {
|
|
1519
|
-
fontSize: 11,
|
|
1520
|
-
color: TEXT_MUTED,
|
|
1521
|
-
fontStyle: "italic"
|
|
1522
|
-
}
|
|
1523
|
-
};
|
|
1524
|
-
function extractDurationMs(raw) {
|
|
1525
|
-
if (raw == null) return NaN;
|
|
1526
|
-
if (typeof raw === "object") {
|
|
1527
|
-
const v = raw;
|
|
1528
|
-
if (typeof v.value === "number" && typeof v.unit === "string") {
|
|
1529
|
-
if (v.unit === "ms") return v.value;
|
|
1530
|
-
if (v.unit === "s") return v.value * 1e3;
|
|
1531
|
-
}
|
|
1532
|
-
}
|
|
1533
|
-
return NaN;
|
|
1534
|
-
}
|
|
1535
|
-
function extractCubicBezier(raw) {
|
|
1536
|
-
if (Array.isArray(raw) && raw.length === 4 && raw.every((n) => typeof n === "number")) return `cubic-bezier(${raw.map((n) => Number(n).toFixed(3)).join(", ")})`;
|
|
1537
|
-
return null;
|
|
1538
|
-
}
|
|
1539
|
-
function asDuration(raw, themeTokens, fallback) {
|
|
1540
|
-
const direct = extractDurationMs(raw);
|
|
1541
|
-
if (Number.isFinite(direct)) return direct;
|
|
1542
|
-
if (typeof raw === "string") {
|
|
1543
|
-
const match = raw.match(/^\{([^}]+)\}$/);
|
|
1544
|
-
if (match && match[1]) {
|
|
1545
|
-
const referenced = themeTokens[match[1]];
|
|
1546
|
-
const resolved = extractDurationMs(referenced?.$value);
|
|
1547
|
-
if (Number.isFinite(resolved)) return resolved;
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
return fallback;
|
|
1551
|
-
}
|
|
1552
|
-
function asEasing(raw, themeTokens, fallback) {
|
|
1553
|
-
const direct = extractCubicBezier(raw);
|
|
1554
|
-
if (direct) return direct;
|
|
1555
|
-
if (typeof raw === "string") {
|
|
1556
|
-
const match = raw.match(/^\{([^}]+)\}$/);
|
|
1557
|
-
if (match && match[1]) {
|
|
1558
|
-
const referenced = themeTokens[match[1]];
|
|
1559
|
-
const resolved = extractCubicBezier(referenced?.$value);
|
|
1560
|
-
if (resolved) return resolved;
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
return fallback;
|
|
1373
|
+
function tupleName(themes, tuple) {
|
|
1374
|
+
return themes.find((t) => {
|
|
1375
|
+
const input = t.input;
|
|
1376
|
+
return Object.keys(input).every((k) => input[k] === tuple[k]);
|
|
1377
|
+
})?.name;
|
|
1564
1378
|
}
|
|
1565
|
-
|
|
1379
|
+
//#endregion
|
|
1380
|
+
//#region src/token-detail/CompositeBreakdown.tsx
|
|
1381
|
+
function CompositeBreakdown({ path }) {
|
|
1382
|
+
const { token, resolved } = useTokenDetailData(path);
|
|
1383
|
+
const colorFormat = useColorFormat();
|
|
1566
1384
|
if (!token) return null;
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
};
|
|
1574
|
-
}
|
|
1575
|
-
if (type === "duration") {
|
|
1576
|
-
const durationMs = extractDurationMs(token.$value);
|
|
1577
|
-
if (!Number.isFinite(durationMs)) return null;
|
|
1578
|
-
return {
|
|
1579
|
-
durationMs,
|
|
1580
|
-
easing: DEFAULT_EASING
|
|
1581
|
-
};
|
|
1582
|
-
}
|
|
1583
|
-
if (type === "cubicBezier") {
|
|
1584
|
-
const easing = extractCubicBezier(token.$value);
|
|
1585
|
-
if (!easing) return null;
|
|
1586
|
-
return {
|
|
1587
|
-
durationMs: DEFAULT_DURATION_MS,
|
|
1588
|
-
easing
|
|
1589
|
-
};
|
|
1590
|
-
}
|
|
1591
|
-
return null;
|
|
1592
|
-
}
|
|
1593
|
-
function MotionSample({ path, speed = 1, runKey = 0 }) {
|
|
1594
|
-
const { resolved } = useProject();
|
|
1595
|
-
const reducedMotion = usePrefersReducedMotion();
|
|
1596
|
-
const spec = useMemo(() => resolveMotionSpec(resolved[path], resolved), [resolved, path]);
|
|
1597
|
-
const durationMs = spec?.durationMs ?? DEFAULT_DURATION_MS;
|
|
1598
|
-
const easing = spec?.easing ?? DEFAULT_EASING;
|
|
1599
|
-
const scaledDuration = Math.max(1, durationMs / speed);
|
|
1600
|
-
const [phase, setPhase] = useState(0);
|
|
1601
|
-
useEffect(() => {
|
|
1602
|
-
if (reducedMotion) return;
|
|
1603
|
-
setPhase(0);
|
|
1604
|
-
const id = requestAnimationFrame(() => setPhase(1));
|
|
1605
|
-
const loop = window.setInterval(() => {
|
|
1606
|
-
setPhase((p) => p === 0 ? 1 : 0);
|
|
1607
|
-
}, scaledDuration * 2);
|
|
1608
|
-
return () => {
|
|
1609
|
-
cancelAnimationFrame(id);
|
|
1610
|
-
window.clearInterval(loop);
|
|
1611
|
-
};
|
|
1612
|
-
}, [
|
|
1613
|
-
scaledDuration,
|
|
1614
|
-
runKey,
|
|
1615
|
-
reducedMotion
|
|
1616
|
-
]);
|
|
1617
|
-
if (reducedMotion) return /* @__PURE__ */ jsx("div", {
|
|
1618
|
-
style: styles.reducedMotion,
|
|
1619
|
-
children: "Animation suppressed by `prefers-reduced-motion: reduce`."
|
|
1620
|
-
});
|
|
1621
|
-
return /* @__PURE__ */ jsx("div", {
|
|
1622
|
-
style: styles.track,
|
|
1623
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
1624
|
-
style: {
|
|
1625
|
-
...styles.ball,
|
|
1626
|
-
left: phase === 1 ? "calc(100% - 32px)" : "4px",
|
|
1627
|
-
transition: `left ${scaledDuration}ms ${easing}`
|
|
1628
|
-
},
|
|
1629
|
-
"aria-hidden": true
|
|
1630
|
-
})
|
|
1385
|
+
return /* @__PURE__ */ jsx(CompositeBreakdownContent, {
|
|
1386
|
+
type: token.$type,
|
|
1387
|
+
rawValue: token.$value,
|
|
1388
|
+
partialAliasOf: token.partialAliasOf,
|
|
1389
|
+
resolved,
|
|
1390
|
+
colorFormat
|
|
1631
1391
|
});
|
|
1632
1392
|
}
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
const
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1393
|
+
function CompositeBreakdownContent({ type, rawValue, partialAliasOf, resolved, colorFormat }) {
|
|
1394
|
+
if (!rawValue || typeof rawValue !== "object") return null;
|
|
1395
|
+
const objectAliases = pickObjectAliases(partialAliasOf);
|
|
1396
|
+
const arrayAliases = pickArrayAliases(partialAliasOf);
|
|
1397
|
+
const aliasFor = (key) => subValueChain(objectAliases?.[key], resolved);
|
|
1398
|
+
if (type === "typography") {
|
|
1399
|
+
const v = rawValue;
|
|
1400
|
+
return renderKeyValueList([
|
|
1401
|
+
[
|
|
1402
|
+
"fontFamily",
|
|
1403
|
+
formatFontFamily(v["fontFamily"]),
|
|
1404
|
+
aliasFor("fontFamily")
|
|
1405
|
+
],
|
|
1406
|
+
[
|
|
1407
|
+
"fontSize",
|
|
1408
|
+
formatDimensionValue(v["fontSize"]),
|
|
1409
|
+
aliasFor("fontSize")
|
|
1410
|
+
],
|
|
1411
|
+
[
|
|
1412
|
+
"fontWeight",
|
|
1413
|
+
formatPrimitive(v["fontWeight"]),
|
|
1414
|
+
aliasFor("fontWeight")
|
|
1415
|
+
],
|
|
1416
|
+
[
|
|
1417
|
+
"lineHeight",
|
|
1418
|
+
formatPrimitive(v["lineHeight"]),
|
|
1419
|
+
aliasFor("lineHeight")
|
|
1420
|
+
],
|
|
1421
|
+
[
|
|
1422
|
+
"letterSpacing",
|
|
1423
|
+
formatDimensionValue(v["letterSpacing"]),
|
|
1424
|
+
aliasFor("letterSpacing")
|
|
1425
|
+
]
|
|
1426
|
+
]);
|
|
1646
1427
|
}
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
"
|
|
1428
|
+
if (type === "border") {
|
|
1429
|
+
const v = rawValue;
|
|
1430
|
+
return renderKeyValueList([
|
|
1431
|
+
[
|
|
1432
|
+
"color",
|
|
1433
|
+
formatColorSubValue(v["color"], colorFormat),
|
|
1434
|
+
aliasFor("color")
|
|
1435
|
+
],
|
|
1436
|
+
[
|
|
1437
|
+
"width",
|
|
1438
|
+
formatDimensionValue(v["width"]),
|
|
1439
|
+
aliasFor("width")
|
|
1440
|
+
],
|
|
1441
|
+
[
|
|
1442
|
+
"style",
|
|
1443
|
+
formatPrimitive(v["style"]),
|
|
1444
|
+
aliasFor("style")
|
|
1445
|
+
]
|
|
1446
|
+
]);
|
|
1447
|
+
}
|
|
1448
|
+
if (type === "transition") {
|
|
1449
|
+
const v = rawValue;
|
|
1450
|
+
return renderKeyValueList([
|
|
1451
|
+
[
|
|
1659
1452
|
"duration",
|
|
1660
|
-
"
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
}
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
children: row.cssVar
|
|
1743
|
-
})
|
|
1744
|
-
]
|
|
1745
|
-
}, row.path))
|
|
1746
|
-
]
|
|
1747
|
-
});
|
|
1453
|
+
formatDimensionValue(v["duration"]),
|
|
1454
|
+
aliasFor("duration")
|
|
1455
|
+
],
|
|
1456
|
+
[
|
|
1457
|
+
"timingFunction",
|
|
1458
|
+
formatPrimitive(v["timingFunction"]),
|
|
1459
|
+
aliasFor("timingFunction")
|
|
1460
|
+
],
|
|
1461
|
+
[
|
|
1462
|
+
"delay",
|
|
1463
|
+
formatDimensionValue(v["delay"]),
|
|
1464
|
+
aliasFor("delay")
|
|
1465
|
+
]
|
|
1466
|
+
]);
|
|
1467
|
+
}
|
|
1468
|
+
if (type === "shadow") {
|
|
1469
|
+
const layers = Array.isArray(rawValue) ? rawValue : [rawValue];
|
|
1470
|
+
const multi = layers.length > 1;
|
|
1471
|
+
const layerAliasFor = (i, key) => subValueChain(arrayAliases?.[i]?.[key], resolved);
|
|
1472
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1473
|
+
className: "sb-token-detail__breakdown-section",
|
|
1474
|
+
children: layers.map((layer, i) => {
|
|
1475
|
+
const v = layer;
|
|
1476
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1477
|
+
style: { display: "contents" },
|
|
1478
|
+
children: [
|
|
1479
|
+
multi && /* @__PURE__ */ jsxs("div", {
|
|
1480
|
+
className: "sb-token-detail__breakdown-layer-header",
|
|
1481
|
+
children: ["Layer ", i + 1]
|
|
1482
|
+
}),
|
|
1483
|
+
/* @__PURE__ */ jsx(KeyValueRow, {
|
|
1484
|
+
label: "color",
|
|
1485
|
+
value: formatColorSubValue(v["color"], colorFormat),
|
|
1486
|
+
alias: layerAliasFor(i, "color")
|
|
1487
|
+
}),
|
|
1488
|
+
/* @__PURE__ */ jsx(KeyValueRow, {
|
|
1489
|
+
label: "offsetX",
|
|
1490
|
+
value: formatDimensionValue(v["offsetX"]),
|
|
1491
|
+
alias: layerAliasFor(i, "offsetX")
|
|
1492
|
+
}),
|
|
1493
|
+
/* @__PURE__ */ jsx(KeyValueRow, {
|
|
1494
|
+
label: "offsetY",
|
|
1495
|
+
value: formatDimensionValue(v["offsetY"]),
|
|
1496
|
+
alias: layerAliasFor(i, "offsetY")
|
|
1497
|
+
}),
|
|
1498
|
+
/* @__PURE__ */ jsx(KeyValueRow, {
|
|
1499
|
+
label: "blur",
|
|
1500
|
+
value: formatDimensionValue(v["blur"]),
|
|
1501
|
+
alias: layerAliasFor(i, "blur")
|
|
1502
|
+
}),
|
|
1503
|
+
/* @__PURE__ */ jsx(KeyValueRow, {
|
|
1504
|
+
label: "spread",
|
|
1505
|
+
value: formatDimensionValue(v["spread"]),
|
|
1506
|
+
alias: layerAliasFor(i, "spread")
|
|
1507
|
+
}),
|
|
1508
|
+
"inset" in v && /* @__PURE__ */ jsx(KeyValueRow, {
|
|
1509
|
+
label: "inset",
|
|
1510
|
+
value: formatPrimitive(v["inset"]),
|
|
1511
|
+
alias: void 0
|
|
1512
|
+
})
|
|
1513
|
+
]
|
|
1514
|
+
}, shadowLayerKey(v, i));
|
|
1515
|
+
})
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
if (type === "gradient") {
|
|
1519
|
+
const stops = Array.isArray(rawValue) ? rawValue : [];
|
|
1520
|
+
if (stops.length === 0) return null;
|
|
1521
|
+
const stopAliasFor = (i) => subValueChain(arrayAliases?.[i]?.["color"], resolved);
|
|
1522
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1523
|
+
className: "sb-token-detail__breakdown-section",
|
|
1524
|
+
children: stops.map((stop, i) => {
|
|
1525
|
+
const v = stop;
|
|
1526
|
+
return /* @__PURE__ */ jsx(KeyValueRow, {
|
|
1527
|
+
label: `${((typeof v["position"] === "number" ? v["position"] : 0) * 100).toFixed(0)}%`,
|
|
1528
|
+
value: formatColorSubValue(v["color"], colorFormat),
|
|
1529
|
+
alias: stopAliasFor(i)
|
|
1530
|
+
}, gradientStopKey(v, i));
|
|
1531
|
+
})
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
return null;
|
|
1748
1535
|
}
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
* a {@link ProjectSnapshot} (often imported from a JSON file) and wrap
|
|
1758
|
-
* their blocks in this provider.
|
|
1759
|
-
*/
|
|
1760
|
-
function SwatchbookProvider({ value, children }) {
|
|
1761
|
-
return /* @__PURE__ */ jsx(SwatchbookContext.Provider, {
|
|
1762
|
-
value,
|
|
1763
|
-
children
|
|
1536
|
+
function renderKeyValueList(rows) {
|
|
1537
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1538
|
+
className: "sb-token-detail__breakdown-section",
|
|
1539
|
+
children: rows.filter(([, v, alias]) => v !== null || alias && alias.length > 0).map(([k, v, alias]) => /* @__PURE__ */ jsx(KeyValueRow, {
|
|
1540
|
+
label: k,
|
|
1541
|
+
value: v ?? "",
|
|
1542
|
+
alias
|
|
1543
|
+
}, k))
|
|
1764
1544
|
});
|
|
1765
1545
|
}
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1546
|
+
function KeyValueRow({ label, value, alias }) {
|
|
1547
|
+
const hasAlias = alias && alias.length > 0;
|
|
1548
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
1549
|
+
className: "sb-token-detail__breakdown-key",
|
|
1550
|
+
children: label
|
|
1551
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
1552
|
+
className: "sb-token-detail__breakdown-value",
|
|
1553
|
+
children: [/* @__PURE__ */ jsx("span", { children: value ?? "—" }), hasAlias && /* @__PURE__ */ jsx("span", {
|
|
1554
|
+
className: "sb-token-detail__breakdown-alias",
|
|
1555
|
+
"data-testid": "breakdown-alias",
|
|
1556
|
+
children: alias.map((p, i) => /* @__PURE__ */ jsxs("span", {
|
|
1557
|
+
className: "sb-token-detail__breakdown-alias-step",
|
|
1558
|
+
children: [i > 0 && /* @__PURE__ */ jsx("span", {
|
|
1559
|
+
className: "sb-token-detail__arrow",
|
|
1560
|
+
children: "→"
|
|
1561
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1562
|
+
className: "sb-token-detail__chain-node",
|
|
1563
|
+
children: p
|
|
1564
|
+
})]
|
|
1565
|
+
}, p))
|
|
1566
|
+
})]
|
|
1567
|
+
})] });
|
|
1775
1568
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
height: 56,
|
|
1781
|
-
background: SURFACE_RAISED,
|
|
1782
|
-
border: BORDER_FAINT,
|
|
1783
|
-
borderRadius: 6
|
|
1784
|
-
};
|
|
1785
|
-
function ShadowSample({ path }) {
|
|
1786
|
-
const { cssVarPrefix } = useProject();
|
|
1787
|
-
const cssVar = makeCssVar(path, cssVarPrefix);
|
|
1788
|
-
return /* @__PURE__ */ jsx("div", {
|
|
1789
|
-
style: {
|
|
1790
|
-
...sampleStyle,
|
|
1791
|
-
boxShadow: cssVar
|
|
1792
|
-
},
|
|
1793
|
-
"aria-hidden": true
|
|
1794
|
-
});
|
|
1569
|
+
function formatPrimitive(v) {
|
|
1570
|
+
if (v == null) return null;
|
|
1571
|
+
if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") return String(v);
|
|
1572
|
+
return JSON.stringify(v);
|
|
1795
1573
|
}
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
if (
|
|
1800
|
-
|
|
1801
|
-
if (typeof raw === "string") return raw;
|
|
1802
|
-
if (typeof raw === "object") {
|
|
1803
|
-
const v = raw;
|
|
1804
|
-
if (typeof v.value === "number" && typeof v.unit === "string") return `${v.value}${v.unit}`;
|
|
1805
|
-
}
|
|
1806
|
-
return JSON.stringify(raw);
|
|
1574
|
+
function formatFontFamily(v) {
|
|
1575
|
+
if (v == null) return null;
|
|
1576
|
+
if (typeof v === "string") return v;
|
|
1577
|
+
if (Array.isArray(v)) return v.map(String).join(", ");
|
|
1578
|
+
return JSON.stringify(v);
|
|
1807
1579
|
}
|
|
1808
|
-
function
|
|
1809
|
-
if (
|
|
1810
|
-
|
|
1580
|
+
function formatDimensionValue(v) {
|
|
1581
|
+
if (v == null) return null;
|
|
1582
|
+
if (typeof v === "string" || typeof v === "number") return String(v);
|
|
1583
|
+
if (typeof v === "object") {
|
|
1584
|
+
const d = v;
|
|
1585
|
+
if (typeof d.value === "number" && typeof d.unit === "string") return `${d.value}${d.unit}`;
|
|
1586
|
+
}
|
|
1587
|
+
return JSON.stringify(v);
|
|
1811
1588
|
}
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1589
|
+
/**
|
|
1590
|
+
* Route sub-value colors through `formatColor` so they honor the active
|
|
1591
|
+
* color-format dropdown, just like the standalone `<ColorPalette />` and
|
|
1592
|
+
* `<TokenDetail />` top-line do. Returns `null` for a missing field so
|
|
1593
|
+
* the key/value row drops out entirely.
|
|
1594
|
+
*/
|
|
1595
|
+
function formatColorSubValue(v, format) {
|
|
1596
|
+
if (v == null) return null;
|
|
1597
|
+
return formatColor(v, format).value;
|
|
1816
1598
|
}
|
|
1817
|
-
function
|
|
1818
|
-
|
|
1599
|
+
function pickObjectAliases(v) {
|
|
1600
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return void 0;
|
|
1601
|
+
return v;
|
|
1819
1602
|
}
|
|
1820
|
-
function
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
const rows = useMemo(() => {
|
|
1824
|
-
return sortTokens(Object.entries(resolved).filter(([path, token]) => {
|
|
1825
|
-
if (token.$type !== "shadow") return false;
|
|
1826
|
-
return globMatch(path, filter);
|
|
1827
|
-
}), {
|
|
1828
|
-
by: sortBy,
|
|
1829
|
-
dir: sortDir
|
|
1830
|
-
}).map(([path, token]) => ({
|
|
1831
|
-
path,
|
|
1832
|
-
cssVar: makeCssVar(path, cssVarPrefix),
|
|
1833
|
-
layers: asLayers(token.$value)
|
|
1834
|
-
}));
|
|
1835
|
-
}, [
|
|
1836
|
-
resolved,
|
|
1837
|
-
filter,
|
|
1838
|
-
cssVarPrefix,
|
|
1839
|
-
sortBy,
|
|
1840
|
-
sortDir
|
|
1841
|
-
]);
|
|
1842
|
-
const captionText = caption ?? `${rows.length} shadow${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
1843
|
-
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
1844
|
-
...themeAttrs(cssVarPrefix, activeTheme),
|
|
1845
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
1846
|
-
className: "sb-block__empty",
|
|
1847
|
-
children: "No shadow tokens match this filter."
|
|
1848
|
-
})
|
|
1849
|
-
});
|
|
1850
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1851
|
-
...themeAttrs(cssVarPrefix, activeTheme),
|
|
1852
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
1853
|
-
className: "sb-block__caption",
|
|
1854
|
-
children: captionText
|
|
1855
|
-
}), rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
1856
|
-
className: "sb-shadow-preview__row",
|
|
1857
|
-
children: [
|
|
1858
|
-
/* @__PURE__ */ jsxs("div", {
|
|
1859
|
-
className: "sb-shadow-preview__meta",
|
|
1860
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
1861
|
-
className: "sb-shadow-preview__path",
|
|
1862
|
-
children: row.path
|
|
1863
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
1864
|
-
className: "sb-shadow-preview__css-var",
|
|
1865
|
-
children: row.cssVar
|
|
1866
|
-
})]
|
|
1867
|
-
}),
|
|
1868
|
-
/* @__PURE__ */ jsx("div", {
|
|
1869
|
-
className: "sb-shadow-preview__sample-cell",
|
|
1870
|
-
children: /* @__PURE__ */ jsx(ShadowSample, { path: row.path })
|
|
1871
|
-
}),
|
|
1872
|
-
/* @__PURE__ */ jsx("div", {
|
|
1873
|
-
className: "sb-shadow-preview__breakdown",
|
|
1874
|
-
children: row.layers.length === 1 ? renderLayer(row.layers[0], colorFormat) : row.layers.map((layer, i) => /* @__PURE__ */ jsx(Layer, {
|
|
1875
|
-
layer,
|
|
1876
|
-
index: i,
|
|
1877
|
-
total: row.layers.length,
|
|
1878
|
-
colorFormat
|
|
1879
|
-
}, layerKey(row.path, layer, i)))
|
|
1880
|
-
})
|
|
1881
|
-
]
|
|
1882
|
-
}, row.path))]
|
|
1883
|
-
});
|
|
1603
|
+
function pickArrayAliases(v) {
|
|
1604
|
+
if (!Array.isArray(v)) return void 0;
|
|
1605
|
+
return v;
|
|
1884
1606
|
}
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
];
|
|
1893
|
-
|
|
1894
|
-
return entries.flatMap(([k, v]) => [/* @__PURE__ */ jsx("span", {
|
|
1895
|
-
className: "sb-shadow-preview__breakdown-key",
|
|
1896
|
-
children: k
|
|
1897
|
-
}, `k-${k}`), /* @__PURE__ */ jsx("span", { children: v }, `v-${k}`)]);
|
|
1607
|
+
/**
|
|
1608
|
+
* Walk the alias chain starting from an immediate sub-value alias target.
|
|
1609
|
+
* `aliasTarget` is the path the sub-value directly references; the target
|
|
1610
|
+
* token's own `aliasChain` continues the walk to the primitive.
|
|
1611
|
+
*/
|
|
1612
|
+
function subValueChain(aliasTarget, resolved) {
|
|
1613
|
+
if (!aliasTarget) return void 0;
|
|
1614
|
+
const tail = (resolved?.[aliasTarget])?.aliasChain;
|
|
1615
|
+
return tail && tail.length > 0 ? [aliasTarget, ...tail] : [aliasTarget];
|
|
1898
1616
|
}
|
|
1899
|
-
function
|
|
1900
|
-
return
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
className: cx("sb-shadow-preview__breakdown", "sb-shadow-preview__layer-breakdown"),
|
|
1912
|
-
children: renderLayer(layer, colorFormat)
|
|
1913
|
-
})]
|
|
1914
|
-
});
|
|
1617
|
+
function shadowLayerKey(layer, fallback) {
|
|
1618
|
+
return `shadow|${[
|
|
1619
|
+
layer["color"],
|
|
1620
|
+
layer["offsetX"],
|
|
1621
|
+
layer["offsetY"],
|
|
1622
|
+
layer["blur"],
|
|
1623
|
+
layer["spread"],
|
|
1624
|
+
layer["inset"]
|
|
1625
|
+
].map((p) => p === void 0 ? "" : JSON.stringify(p)).join("|")}|${fallback}`;
|
|
1626
|
+
}
|
|
1627
|
+
function gradientStopKey(stop, fallback) {
|
|
1628
|
+
return `stop|${stop["position"] ?? fallback}|${JSON.stringify(stop["color"])}`;
|
|
1915
1629
|
}
|
|
1916
1630
|
//#endregion
|
|
1917
|
-
//#region src/
|
|
1918
|
-
|
|
1631
|
+
//#region src/internal/prefers-reduced-motion.ts
|
|
1632
|
+
/**
|
|
1633
|
+
* Reactive `prefers-reduced-motion: reduce` detector. Returns the current
|
|
1634
|
+
* match and updates if the user toggles the OS-level preference.
|
|
1635
|
+
*/
|
|
1636
|
+
function usePrefersReducedMotion() {
|
|
1637
|
+
const [reduced, setReduced] = useState(false);
|
|
1638
|
+
useEffect(() => {
|
|
1639
|
+
if (typeof window === "undefined") return;
|
|
1640
|
+
const query = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
1641
|
+
setReduced(query.matches);
|
|
1642
|
+
const onChange = (e) => setReduced(e.matches);
|
|
1643
|
+
query.addEventListener("change", onChange);
|
|
1644
|
+
return () => query.removeEventListener("change", onChange);
|
|
1645
|
+
}, []);
|
|
1646
|
+
return reduced;
|
|
1647
|
+
}
|
|
1648
|
+
//#endregion
|
|
1649
|
+
//#region src/token-detail/CompositePreview.tsx
|
|
1650
|
+
const PANGRAM = "Sphinx of black quartz, judge my vow.";
|
|
1651
|
+
const STROKE_STYLE_STRINGS = new Set([
|
|
1919
1652
|
"solid",
|
|
1920
1653
|
"dashed",
|
|
1921
1654
|
"dotted",
|
|
@@ -1925,1022 +1658,1608 @@ const STRING_STYLES = new Set([
|
|
|
1925
1658
|
"outset",
|
|
1926
1659
|
"inset"
|
|
1927
1660
|
]);
|
|
1928
|
-
function
|
|
1929
|
-
|
|
1930
|
-
return null;
|
|
1661
|
+
function CompositePreview({ path }) {
|
|
1662
|
+
const { token, cssVar } = useTokenDetailData(path);
|
|
1663
|
+
if (!token) return null;
|
|
1664
|
+
return /* @__PURE__ */ jsx(CompositePreviewContent, {
|
|
1665
|
+
type: token.$type,
|
|
1666
|
+
cssVar,
|
|
1667
|
+
rawValue: token.$value
|
|
1668
|
+
});
|
|
1931
1669
|
}
|
|
1932
|
-
function
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
return
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1670
|
+
function CompositePreviewContent({ type, cssVar, rawValue }) {
|
|
1671
|
+
if (type === "typography") {
|
|
1672
|
+
const base = cssVar.replace(/^var\(/, "").replace(/\)$/, "");
|
|
1673
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1674
|
+
className: "sb-token-detail__typography-sample",
|
|
1675
|
+
style: {
|
|
1676
|
+
fontFamily: `var(${base}-font-family)`,
|
|
1677
|
+
fontSize: `var(${base}-font-size)`,
|
|
1678
|
+
fontWeight: `var(${base}-font-weight)`,
|
|
1679
|
+
lineHeight: `var(${base}-line-height)`,
|
|
1680
|
+
letterSpacing: `var(${base}-letter-spacing)`
|
|
1681
|
+
},
|
|
1682
|
+
children: PANGRAM
|
|
1683
|
+
});
|
|
1684
|
+
}
|
|
1685
|
+
if (type === "shadow") return /* @__PURE__ */ jsx("div", {
|
|
1686
|
+
className: "sb-token-detail__shadow-sample",
|
|
1687
|
+
style: { boxShadow: cssVar },
|
|
1688
|
+
"aria-hidden": true
|
|
1689
|
+
});
|
|
1690
|
+
if (type === "border") return /* @__PURE__ */ jsx("div", {
|
|
1691
|
+
className: "sb-token-detail__border-sample",
|
|
1692
|
+
style: { border: cssVar },
|
|
1693
|
+
"aria-hidden": true
|
|
1694
|
+
});
|
|
1695
|
+
if (type === "transition") return /* @__PURE__ */ jsx(TransitionSample, { transition: cssVar });
|
|
1696
|
+
if (type === "dimension") return /* @__PURE__ */ jsx("div", {
|
|
1697
|
+
className: "sb-token-detail__dimension-track",
|
|
1957
1698
|
children: /* @__PURE__ */ jsx("div", {
|
|
1958
|
-
className: "sb-
|
|
1959
|
-
|
|
1699
|
+
className: "sb-token-detail__dimension-bar",
|
|
1700
|
+
style: { width: cssVar },
|
|
1701
|
+
"aria-hidden": true
|
|
1960
1702
|
})
|
|
1961
1703
|
});
|
|
1962
|
-
return /* @__PURE__ */
|
|
1963
|
-
|
|
1704
|
+
if (type === "duration") return /* @__PURE__ */ jsx(TransitionSample, { transition: `left ${cssVar} ease` });
|
|
1705
|
+
if (type === "fontFamily") return /* @__PURE__ */ jsx("div", {
|
|
1706
|
+
className: "sb-token-detail__font-family-sample",
|
|
1707
|
+
style: { fontFamily: cssVar },
|
|
1708
|
+
children: PANGRAM
|
|
1709
|
+
});
|
|
1710
|
+
if (type === "fontWeight") return /* @__PURE__ */ jsx("div", {
|
|
1711
|
+
className: "sb-token-detail__font-weight-sample",
|
|
1712
|
+
style: { fontWeight: cssVar },
|
|
1713
|
+
children: "Aa"
|
|
1714
|
+
});
|
|
1715
|
+
if (type === "cubicBezier") return /* @__PURE__ */ jsx(TransitionSample, { transition: `left 800ms ${cssVar}` });
|
|
1716
|
+
if (type === "gradient") return /* @__PURE__ */ jsx("div", {
|
|
1717
|
+
className: "sb-token-detail__gradient-sample",
|
|
1718
|
+
style: { background: `linear-gradient(to right, ${cssVar})` },
|
|
1719
|
+
"aria-hidden": true
|
|
1720
|
+
});
|
|
1721
|
+
if (type === "strokeStyle") return /* @__PURE__ */ jsx(StrokeStylePreview, { value: rawValue });
|
|
1722
|
+
if (type === "color") return /* @__PURE__ */ jsxs("div", {
|
|
1723
|
+
className: "sb-token-detail__color-swatch-row",
|
|
1724
|
+
"aria-hidden": true,
|
|
1964
1725
|
children: [/* @__PURE__ */ jsx("div", {
|
|
1965
|
-
className: "sb-
|
|
1966
|
-
|
|
1967
|
-
}),
|
|
1968
|
-
className: "sb-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
className: "sb-stroke-style-sample__meta",
|
|
1972
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
1973
|
-
className: "sb-stroke-style-sample__path",
|
|
1974
|
-
children: row.path
|
|
1975
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
1976
|
-
className: "sb-stroke-style-sample__value",
|
|
1977
|
-
children: row.displayValue
|
|
1978
|
-
})]
|
|
1979
|
-
}),
|
|
1980
|
-
row.cssStyle ? /* @__PURE__ */ jsx("div", {
|
|
1981
|
-
className: "sb-stroke-style-sample__line",
|
|
1982
|
-
style: { borderTopStyle: row.cssStyle },
|
|
1983
|
-
"aria-hidden": true
|
|
1984
|
-
}) : /* @__PURE__ */ jsx("span", {
|
|
1985
|
-
className: "sb-stroke-style-sample__object-fallback",
|
|
1986
|
-
children: "Object-form (dashArray + lineCap) — no pure CSS `border-style` equivalent."
|
|
1987
|
-
}),
|
|
1988
|
-
/* @__PURE__ */ jsx("span", {
|
|
1989
|
-
className: "sb-stroke-style-sample__css-var",
|
|
1990
|
-
children: row.cssVar
|
|
1991
|
-
})
|
|
1992
|
-
]
|
|
1993
|
-
}, row.path))]
|
|
1726
|
+
className: "sb-token-detail__color-swatch-light",
|
|
1727
|
+
style: { background: cssVar }
|
|
1728
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1729
|
+
className: "sb-token-detail__color-swatch-dark",
|
|
1730
|
+
style: { background: cssVar }
|
|
1731
|
+
})]
|
|
1994
1732
|
});
|
|
1733
|
+
return null;
|
|
1995
1734
|
}
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
1735
|
+
function StrokeStylePreview({ value }) {
|
|
1736
|
+
if (typeof value === "string" && STROKE_STYLE_STRINGS.has(value)) return /* @__PURE__ */ jsx("div", {
|
|
1737
|
+
className: "sb-token-detail__stroke-style-line",
|
|
1738
|
+
style: { borderTopStyle: value },
|
|
1739
|
+
"aria-hidden": true
|
|
1740
|
+
});
|
|
1741
|
+
if (value && typeof value === "object" && "dashArray" in value) {
|
|
1742
|
+
const v = value;
|
|
1743
|
+
const lengths = asDashLengths(v.dashArray);
|
|
1744
|
+
if (lengths.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
1745
|
+
className: "sb-token-detail__stroke-style-fallback",
|
|
1746
|
+
children: "Object-form strokeStyle with no resolvable dashArray."
|
|
1747
|
+
});
|
|
1748
|
+
const cap = typeof v.lineCap === "string" ? v.lineCap : "butt";
|
|
1749
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
1750
|
+
className: "sb-token-detail__stroke-style-svg",
|
|
1751
|
+
viewBox: "0 0 220 24",
|
|
1752
|
+
preserveAspectRatio: "none",
|
|
1753
|
+
"aria-hidden": true,
|
|
1754
|
+
children: /* @__PURE__ */ jsx("line", {
|
|
1755
|
+
x1: "4",
|
|
1756
|
+
y1: "12",
|
|
1757
|
+
x2: "216",
|
|
1758
|
+
y2: "12",
|
|
1759
|
+
stroke: "currentColor",
|
|
1760
|
+
strokeWidth: "4",
|
|
1761
|
+
strokeDasharray: lengths.join(" "),
|
|
1762
|
+
strokeLinecap: cap
|
|
1763
|
+
})
|
|
1764
|
+
});
|
|
1765
|
+
}
|
|
1766
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1767
|
+
className: "sb-token-detail__stroke-style-fallback",
|
|
1768
|
+
children: "strokeStyle value could not be previewed."
|
|
1769
|
+
});
|
|
2012
1770
|
}
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
const
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
1771
|
+
function asDashLengths(raw) {
|
|
1772
|
+
if (!Array.isArray(raw)) return [];
|
|
1773
|
+
const out = [];
|
|
1774
|
+
for (const entry of raw) {
|
|
1775
|
+
if (typeof entry === "number") {
|
|
1776
|
+
out.push(entry);
|
|
1777
|
+
continue;
|
|
1778
|
+
}
|
|
1779
|
+
if (entry && typeof entry === "object") {
|
|
1780
|
+
const e = entry;
|
|
1781
|
+
if (typeof e.value === "number") out.push(e.value);
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
return out;
|
|
1785
|
+
}
|
|
1786
|
+
function TransitionSample({ transition }) {
|
|
1787
|
+
const reduced = usePrefersReducedMotion();
|
|
1788
|
+
const [phase, setPhase] = useState(0);
|
|
1789
|
+
useEffect(() => {
|
|
1790
|
+
if (reduced) return;
|
|
1791
|
+
const id = requestAnimationFrame(() => setPhase(1));
|
|
1792
|
+
const loop = window.setInterval(() => {
|
|
1793
|
+
setPhase((p) => p === 0 ? 1 : 0);
|
|
1794
|
+
}, 1200);
|
|
1795
|
+
return () => {
|
|
1796
|
+
cancelAnimationFrame(id);
|
|
1797
|
+
window.clearInterval(loop);
|
|
1798
|
+
};
|
|
1799
|
+
}, [reduced]);
|
|
1800
|
+
if (reduced) return /* @__PURE__ */ jsx("div", {
|
|
1801
|
+
className: "sb-token-detail__reduced-motion",
|
|
1802
|
+
children: "Animation suppressed by `prefers-reduced-motion: reduce`."
|
|
1803
|
+
});
|
|
1804
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1805
|
+
className: "sb-token-detail__motion-track",
|
|
1806
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1807
|
+
className: "sb-token-detail__motion-ball",
|
|
1808
|
+
style: {
|
|
1809
|
+
left: phase === 1 ? "calc(100% - 28px)" : "4px",
|
|
1810
|
+
transition
|
|
1811
|
+
},
|
|
1812
|
+
"aria-hidden": true
|
|
1813
|
+
})
|
|
1814
|
+
});
|
|
2040
1815
|
}
|
|
2041
1816
|
//#endregion
|
|
2042
|
-
//#region src/token-detail/
|
|
2043
|
-
|
|
2044
|
-
const
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
};
|
|
2048
|
-
function AliasedBy({ path }) {
|
|
2049
|
-
const { resolved } = useTokenDetailData(path);
|
|
2050
|
-
const tree = useMemo(() => buildAliasedByTree(path, resolved), [path, resolved]);
|
|
2051
|
-
const truncated = useMemo(() => treeHasTruncation(tree), [tree]);
|
|
2052
|
-
if (tree.length === 0) return null;
|
|
1817
|
+
//#region src/token-detail/ConsumerOutput.tsx
|
|
1818
|
+
function ConsumerOutput({ path }) {
|
|
1819
|
+
const { token, cssVar, activeAxes } = useTokenDetailData(path);
|
|
1820
|
+
if (!token) return null;
|
|
1821
|
+
const tupleLabel = Object.entries(activeAxes).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
2053
1822
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2054
1823
|
/* @__PURE__ */ jsx("div", {
|
|
2055
1824
|
className: "sb-token-detail__section-header",
|
|
2056
|
-
children: "
|
|
1825
|
+
children: "Consumer output"
|
|
2057
1826
|
}),
|
|
2058
|
-
/* @__PURE__ */
|
|
2059
|
-
className: "sb-token-
|
|
2060
|
-
children:
|
|
2061
|
-
node,
|
|
2062
|
-
depth: 0
|
|
2063
|
-
}, node.path))
|
|
1827
|
+
tupleLabel && /* @__PURE__ */ jsxs("div", {
|
|
1828
|
+
className: "sb-token-detail__tuple-indicator",
|
|
1829
|
+
children: ["Active tuple: ", /* @__PURE__ */ jsx("strong", { children: tupleLabel })]
|
|
2064
1830
|
}),
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
1831
|
+
/* @__PURE__ */ jsx(OutputRow, {
|
|
1832
|
+
label: "Path",
|
|
1833
|
+
value: path,
|
|
1834
|
+
testId: "consumer-output-path"
|
|
1835
|
+
}),
|
|
1836
|
+
/* @__PURE__ */ jsx(OutputRow, {
|
|
1837
|
+
label: "CSS",
|
|
1838
|
+
value: cssVar,
|
|
1839
|
+
testId: "consumer-output-css"
|
|
2072
1840
|
})
|
|
2073
1841
|
] });
|
|
2074
1842
|
}
|
|
2075
|
-
function
|
|
2076
|
-
return /* @__PURE__ */ jsxs("
|
|
2077
|
-
className: "sb-token-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
}
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
if (!direct || direct.length === 0) return [];
|
|
2094
|
-
const visited = new Set([rootPath]);
|
|
2095
|
-
return sortPaths(direct).map((p) => walk(p, resolved, visited, 1));
|
|
2096
|
-
}
|
|
2097
|
-
function walk(path, resolved, visited, depth) {
|
|
2098
|
-
if (visited.has(path)) return {
|
|
2099
|
-
path,
|
|
2100
|
-
children: []
|
|
2101
|
-
};
|
|
2102
|
-
visited.add(path);
|
|
2103
|
-
const parents = resolved[path]?.aliasedBy;
|
|
2104
|
-
if (!parents || parents.length === 0) return {
|
|
2105
|
-
path,
|
|
2106
|
-
children: []
|
|
2107
|
-
};
|
|
2108
|
-
if (depth >= ALIASED_BY_DEPTH_CAP) return {
|
|
2109
|
-
path,
|
|
2110
|
-
children: [],
|
|
2111
|
-
truncated: true
|
|
2112
|
-
};
|
|
2113
|
-
return {
|
|
2114
|
-
path,
|
|
2115
|
-
children: sortPaths(parents).map((p) => walk(p, resolved, visited, depth + 1))
|
|
2116
|
-
};
|
|
2117
|
-
}
|
|
2118
|
-
function sortPaths(paths) {
|
|
2119
|
-
return paths.toSorted((a, b) => {
|
|
2120
|
-
const ra = GROUP_RANK[a.split(".")[0] ?? ""] ?? 2;
|
|
2121
|
-
const rb = GROUP_RANK[b.split(".")[0] ?? ""] ?? 2;
|
|
2122
|
-
return ra !== rb ? ra - rb : a.localeCompare(b, void 0, { numeric: true });
|
|
1843
|
+
function OutputRow({ label, value, testId }) {
|
|
1844
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1845
|
+
className: "sb-token-detail__consumer-row",
|
|
1846
|
+
children: [
|
|
1847
|
+
/* @__PURE__ */ jsx("span", {
|
|
1848
|
+
className: "sb-token-detail__consumer-row-label",
|
|
1849
|
+
children: label
|
|
1850
|
+
}),
|
|
1851
|
+
/* @__PURE__ */ jsx("code", {
|
|
1852
|
+
className: "sb-token-detail__consumer-row-value",
|
|
1853
|
+
"data-testid": testId,
|
|
1854
|
+
children: value
|
|
1855
|
+
}),
|
|
1856
|
+
/* @__PURE__ */ jsx(CopyButton, {
|
|
1857
|
+
text: value,
|
|
1858
|
+
testId: `${testId}-copy`
|
|
1859
|
+
})
|
|
1860
|
+
]
|
|
2123
1861
|
});
|
|
2124
1862
|
}
|
|
2125
|
-
function
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
}
|
|
2147
|
-
|
|
2148
|
-
axes,
|
|
2149
|
-
themes,
|
|
2150
|
-
themesResolved
|
|
2151
|
-
]);
|
|
2152
|
-
if (themes.length === 0) return /* @__PURE__ */ jsx(Fragment, {});
|
|
2153
|
-
if (variance.kind === "constant") {
|
|
2154
|
-
const anyTheme = themes[0];
|
|
2155
|
-
const value = anyTheme ? formatFn(themesResolved[anyTheme.name]?.[path]) : "—";
|
|
2156
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
2157
|
-
className: "sb-token-detail__section-header",
|
|
2158
|
-
children: "Values across axes"
|
|
2159
|
-
}), /* @__PURE__ */ jsx("table", {
|
|
2160
|
-
className: "sb-token-detail__theme-table",
|
|
2161
|
-
"data-testid": "token-detail-values",
|
|
2162
|
-
children: /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx("tr", {
|
|
2163
|
-
className: "sb-token-detail__theme-row",
|
|
2164
|
-
children: /* @__PURE__ */ jsxs("td", {
|
|
2165
|
-
className: "sb-token-detail__theme-cell",
|
|
2166
|
-
"data-testid": "token-detail-constant",
|
|
2167
|
-
children: [
|
|
2168
|
-
isColor && /* @__PURE__ */ jsx("span", {
|
|
2169
|
-
className: "sb-token-detail__swatch",
|
|
2170
|
-
style: { background: cssVar },
|
|
2171
|
-
"aria-hidden": true
|
|
2172
|
-
}),
|
|
2173
|
-
value,
|
|
2174
|
-
/* @__PURE__ */ jsxs("span", {
|
|
2175
|
-
style: {
|
|
2176
|
-
opacity: .6,
|
|
2177
|
-
marginLeft: 8
|
|
2178
|
-
},
|
|
2179
|
-
children: [
|
|
2180
|
-
"same across all ",
|
|
2181
|
-
themes.length,
|
|
2182
|
-
" tuples"
|
|
2183
|
-
]
|
|
2184
|
-
})
|
|
2185
|
-
]
|
|
2186
|
-
})
|
|
2187
|
-
}) })
|
|
2188
|
-
})] });
|
|
2189
|
-
}
|
|
2190
|
-
if (variance.kind === "one-axis") {
|
|
2191
|
-
const axisName = variance.varyingAxes[0];
|
|
2192
|
-
if (!axisName) return /* @__PURE__ */ jsx(Fragment, {});
|
|
2193
|
-
const axis = axes.find((a) => a.name === axisName);
|
|
2194
|
-
if (!axis) return /* @__PURE__ */ jsx(Fragment, {});
|
|
2195
|
-
const contextValues = axis.contexts.map((ctx) => {
|
|
2196
|
-
const target = {
|
|
2197
|
-
...activeAxes,
|
|
2198
|
-
[axisName]: ctx
|
|
2199
|
-
};
|
|
2200
|
-
const name = themes.find((t) => {
|
|
2201
|
-
const input = t.input;
|
|
2202
|
-
return Object.keys(input).every((k) => input[k] === target[k]);
|
|
2203
|
-
})?.name ?? "";
|
|
2204
|
-
return {
|
|
2205
|
-
ctx,
|
|
2206
|
-
themeName: name,
|
|
2207
|
-
value: name ? formatFn(themesResolved[name]?.[path]) : "—"
|
|
2208
|
-
};
|
|
2209
|
-
});
|
|
2210
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
2211
|
-
className: "sb-token-detail__section-header",
|
|
2212
|
-
children: ["Varies with ", axisName]
|
|
2213
|
-
}), /* @__PURE__ */ jsx("table", {
|
|
2214
|
-
className: "sb-token-detail__theme-table",
|
|
2215
|
-
"data-testid": "token-detail-values",
|
|
2216
|
-
children: /* @__PURE__ */ jsx("tbody", { children: contextValues.map((row) => /* @__PURE__ */ jsxs("tr", {
|
|
2217
|
-
className: "sb-token-detail__theme-row",
|
|
2218
|
-
"data-axis": axisName,
|
|
2219
|
-
"data-context": row.ctx,
|
|
2220
|
-
children: [/* @__PURE__ */ jsx("td", {
|
|
2221
|
-
className: "sb-token-detail__theme-cell",
|
|
2222
|
-
style: { width: "30%" },
|
|
2223
|
-
children: row.ctx
|
|
2224
|
-
}), /* @__PURE__ */ jsxs("td", {
|
|
2225
|
-
className: "sb-token-detail__theme-cell",
|
|
2226
|
-
children: [isColor && row.themeName && /* @__PURE__ */ jsx("span", {
|
|
2227
|
-
className: "sb-token-detail__swatch",
|
|
2228
|
-
style: { background: cssVar },
|
|
2229
|
-
[dataAttr(cssVarPrefix, "theme")]: row.themeName,
|
|
2230
|
-
"aria-hidden": true
|
|
2231
|
-
}), row.value]
|
|
2232
|
-
})]
|
|
2233
|
-
}, row.ctx)) })
|
|
2234
|
-
})] });
|
|
1863
|
+
function CopyButton({ text, testId }) {
|
|
1864
|
+
const [copied, setCopied] = useState(false);
|
|
1865
|
+
return /* @__PURE__ */ jsx("button", {
|
|
1866
|
+
type: "button",
|
|
1867
|
+
className: "sb-token-detail__consumer-row-copy",
|
|
1868
|
+
"data-testid": testId,
|
|
1869
|
+
onClick: () => {
|
|
1870
|
+
copyToClipboard(text).then((ok) => {
|
|
1871
|
+
if (!ok) return;
|
|
1872
|
+
setCopied(true);
|
|
1873
|
+
window.setTimeout(() => setCopied(false), 1200);
|
|
1874
|
+
});
|
|
1875
|
+
},
|
|
1876
|
+
children: copied ? "Copied" : "Copy"
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
async function copyToClipboard(text) {
|
|
1880
|
+
if (typeof navigator === "undefined" || !navigator.clipboard) return false;
|
|
1881
|
+
try {
|
|
1882
|
+
await navigator.clipboard.writeText(text);
|
|
1883
|
+
return true;
|
|
1884
|
+
} catch {
|
|
1885
|
+
return false;
|
|
2235
1886
|
}
|
|
2236
|
-
|
|
2237
|
-
|
|
1887
|
+
}
|
|
1888
|
+
//#endregion
|
|
1889
|
+
//#region src/token-detail/TokenHeader.tsx
|
|
1890
|
+
function TokenHeader({ path, heading }) {
|
|
1891
|
+
const { token, cssVar, activeTheme } = useTokenDetailData(path);
|
|
1892
|
+
if (!token) return /* @__PURE__ */ jsxs("div", {
|
|
1893
|
+
className: "sb-token-detail__missing",
|
|
1894
|
+
children: [
|
|
1895
|
+
"Token ",
|
|
1896
|
+
/* @__PURE__ */ jsx("code", { children: path }),
|
|
1897
|
+
" not found in theme ",
|
|
1898
|
+
/* @__PURE__ */ jsx("strong", { children: activeTheme }),
|
|
1899
|
+
"."
|
|
1900
|
+
]
|
|
1901
|
+
});
|
|
2238
1902
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2239
|
-
/* @__PURE__ */
|
|
2240
|
-
className: "sb-token-
|
|
2241
|
-
children:
|
|
1903
|
+
/* @__PURE__ */ jsx("h3", {
|
|
1904
|
+
className: "sb-token-detail__heading",
|
|
1905
|
+
children: heading ?? path
|
|
2242
1906
|
}),
|
|
2243
|
-
/* @__PURE__ */ jsxs("
|
|
2244
|
-
className: "sb-token-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
className: "sb-token-detail__theme-cell",
|
|
2250
|
-
style: {
|
|
2251
|
-
textAlign: "left",
|
|
2252
|
-
opacity: .7
|
|
2253
|
-
},
|
|
2254
|
-
children: [
|
|
2255
|
-
rowAxis.name,
|
|
2256
|
-
" \\ ",
|
|
2257
|
-
colAxis.name
|
|
2258
|
-
]
|
|
2259
|
-
}), colAxis.contexts.map((col) => /* @__PURE__ */ jsx("th", {
|
|
2260
|
-
className: "sb-token-detail__theme-cell",
|
|
2261
|
-
style: {
|
|
2262
|
-
textAlign: "left",
|
|
2263
|
-
opacity: .7
|
|
2264
|
-
},
|
|
2265
|
-
children: col
|
|
2266
|
-
}, col))]
|
|
2267
|
-
}) }), /* @__PURE__ */ jsx("tbody", { children: rowAxis.contexts.map((row) => /* @__PURE__ */ jsxs("tr", {
|
|
2268
|
-
className: "sb-token-detail__theme-row",
|
|
2269
|
-
children: [/* @__PURE__ */ jsx("td", {
|
|
2270
|
-
className: "sb-token-detail__theme-cell",
|
|
2271
|
-
children: row
|
|
2272
|
-
}), colAxis.contexts.map((col) => {
|
|
2273
|
-
const name = tupleName(themes, {
|
|
2274
|
-
...activeAxes,
|
|
2275
|
-
[rowAxis.name]: row,
|
|
2276
|
-
[colAxis.name]: col
|
|
2277
|
-
});
|
|
2278
|
-
const value = name ? formatFn(themesResolved[name]?.[path]) : "—";
|
|
2279
|
-
return /* @__PURE__ */ jsxs("td", {
|
|
2280
|
-
className: "sb-token-detail__theme-cell",
|
|
2281
|
-
"data-row": row,
|
|
2282
|
-
"data-col": col,
|
|
2283
|
-
children: [isColor && name && /* @__PURE__ */ jsx("span", {
|
|
2284
|
-
className: "sb-token-detail__swatch",
|
|
2285
|
-
style: { background: cssVar },
|
|
2286
|
-
[dataAttr(cssVarPrefix, "theme")]: name,
|
|
2287
|
-
"aria-hidden": true
|
|
2288
|
-
}), value]
|
|
2289
|
-
}, col);
|
|
2290
|
-
})]
|
|
2291
|
-
}, row)) })]
|
|
1907
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1908
|
+
className: "sb-token-detail__subline",
|
|
1909
|
+
children: [token.$type && /* @__PURE__ */ jsx("span", {
|
|
1910
|
+
className: "sb-token-detail__type-pill",
|
|
1911
|
+
children: token.$type
|
|
1912
|
+
}), /* @__PURE__ */ jsx("span", { children: cssVar })]
|
|
2292
1913
|
}),
|
|
2293
|
-
|
|
2294
|
-
className: "sb-token-
|
|
2295
|
-
|
|
2296
|
-
children: [
|
|
2297
|
-
"Values also vary with ",
|
|
2298
|
-
extra.map((a) => a.name).join(", "),
|
|
2299
|
-
"; matrix shows the slice for the active selection."
|
|
2300
|
-
]
|
|
1914
|
+
token.$description && /* @__PURE__ */ jsx("p", {
|
|
1915
|
+
className: "sb-token-detail__description",
|
|
1916
|
+
children: token.$description
|
|
2301
1917
|
})
|
|
2302
1918
|
] });
|
|
2303
1919
|
}
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
}
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
1920
|
+
//#endregion
|
|
1921
|
+
//#region src/token-detail/TokenUsageSnippet.tsx
|
|
1922
|
+
function TokenUsageSnippet({ path }) {
|
|
1923
|
+
const { token, cssVar } = useTokenDetailData(path);
|
|
1924
|
+
if (!token) return null;
|
|
1925
|
+
const snippet = `color: ${cssVar};`;
|
|
1926
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
1927
|
+
className: "sb-token-detail__section-header",
|
|
1928
|
+
children: "Usage"
|
|
1929
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1930
|
+
className: "sb-token-detail__snippet-row",
|
|
1931
|
+
children: [/* @__PURE__ */ jsx("code", {
|
|
1932
|
+
className: "sb-token-detail__snippet",
|
|
1933
|
+
children: snippet
|
|
1934
|
+
}), /* @__PURE__ */ jsx(CopyButton$1, {
|
|
1935
|
+
value: snippet,
|
|
1936
|
+
label: `Copy usage snippet ${snippet}`
|
|
1937
|
+
})]
|
|
1938
|
+
})] });
|
|
2313
1939
|
}
|
|
2314
1940
|
//#endregion
|
|
2315
|
-
//#region src/
|
|
2316
|
-
function
|
|
2317
|
-
const { token,
|
|
1941
|
+
//#region src/TokenDetail.tsx
|
|
1942
|
+
function TokenDetail({ path, heading }) {
|
|
1943
|
+
const { token, cssVar, activeTheme, cssVarPrefix } = useTokenDetailData(path);
|
|
2318
1944
|
const colorFormat = useColorFormat();
|
|
2319
|
-
|
|
2320
|
-
return /* @__PURE__ */ jsx(
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
1945
|
+
const theme = themeAttrs(cssVarPrefix, activeTheme);
|
|
1946
|
+
if (!token) return /* @__PURE__ */ jsx("div", {
|
|
1947
|
+
...theme,
|
|
1948
|
+
className: cx(theme["className"], "sb-token-detail"),
|
|
1949
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1950
|
+
className: "sb-token-detail__missing",
|
|
1951
|
+
children: [
|
|
1952
|
+
"Token ",
|
|
1953
|
+
/* @__PURE__ */ jsx("code", { children: path }),
|
|
1954
|
+
" not found in theme ",
|
|
1955
|
+
/* @__PURE__ */ jsx("strong", { children: activeTheme }),
|
|
1956
|
+
"."
|
|
1957
|
+
]
|
|
1958
|
+
})
|
|
1959
|
+
});
|
|
1960
|
+
const isColor = token.$type === "color";
|
|
1961
|
+
const gamut = isColor ? formatColor(token.$value, colorFormat) : null;
|
|
1962
|
+
const value = formatTokenValue(token.$value, token.$type, colorFormat);
|
|
1963
|
+
const outOfGamut = gamut?.outOfGamut ?? false;
|
|
1964
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1965
|
+
...theme,
|
|
1966
|
+
className: cx(theme["className"], "sb-token-detail"),
|
|
1967
|
+
children: [
|
|
1968
|
+
/* @__PURE__ */ jsx(TokenHeader, {
|
|
1969
|
+
path,
|
|
1970
|
+
...heading !== void 0 && { heading }
|
|
1971
|
+
}),
|
|
1972
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1973
|
+
className: "sb-token-detail__section-header",
|
|
1974
|
+
children: ["Resolved value · ", activeTheme]
|
|
1975
|
+
}),
|
|
1976
|
+
/* @__PURE__ */ jsx(CompositePreview, { path }),
|
|
1977
|
+
/* @__PURE__ */ jsx(CompositeBreakdown, { path }),
|
|
1978
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1979
|
+
className: "sb-token-detail__chain",
|
|
1980
|
+
children: [
|
|
1981
|
+
isColor && /* @__PURE__ */ jsx("span", {
|
|
1982
|
+
className: "sb-token-detail__swatch",
|
|
1983
|
+
style: { background: cssVar },
|
|
1984
|
+
"aria-hidden": true
|
|
1985
|
+
}),
|
|
1986
|
+
/* @__PURE__ */ jsx("span", { children: value }),
|
|
1987
|
+
outOfGamut && /* @__PURE__ */ jsx("span", {
|
|
1988
|
+
title: "Out of sRGB gamut for this format",
|
|
1989
|
+
"aria-label": "out of gamut",
|
|
1990
|
+
style: { marginLeft: 6 },
|
|
1991
|
+
children: "⚠"
|
|
1992
|
+
}),
|
|
1993
|
+
/* @__PURE__ */ jsx(CopyButton$1, {
|
|
1994
|
+
value,
|
|
1995
|
+
label: `Copy value ${value}`
|
|
1996
|
+
})
|
|
1997
|
+
]
|
|
1998
|
+
}),
|
|
1999
|
+
/* @__PURE__ */ jsx(AliasChain, { path }),
|
|
2000
|
+
/* @__PURE__ */ jsx(AliasedBy, { path }),
|
|
2001
|
+
/* @__PURE__ */ jsx(TokenUsageSnippet, { path }),
|
|
2002
|
+
/* @__PURE__ */ jsx(ConsumerOutput, { path }),
|
|
2003
|
+
/* @__PURE__ */ jsx(AxisVariance, { path })
|
|
2004
|
+
]
|
|
2005
|
+
});
|
|
2006
|
+
}
|
|
2007
|
+
//#endregion
|
|
2008
|
+
//#region src/internal/DetailOverlay.tsx
|
|
2009
|
+
function DetailOverlay({ path, onClose, testId = "swatchbook-overlay" }) {
|
|
2010
|
+
useEffect(() => {
|
|
2011
|
+
const onKey = (e) => {
|
|
2012
|
+
if (e.key === "Escape") onClose();
|
|
2013
|
+
};
|
|
2014
|
+
window.addEventListener("keydown", onKey);
|
|
2015
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
2016
|
+
}, [onClose]);
|
|
2017
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2018
|
+
className: "sb-detail-overlay__backdrop",
|
|
2019
|
+
onClick: onClose,
|
|
2020
|
+
role: "presentation",
|
|
2021
|
+
"data-testid": testId,
|
|
2022
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
2023
|
+
className: "sb-detail-overlay__panel",
|
|
2024
|
+
onClick: (e) => e.stopPropagation(),
|
|
2025
|
+
role: "dialog",
|
|
2026
|
+
"aria-modal": "true",
|
|
2027
|
+
"aria-label": `Token detail for ${path}`,
|
|
2028
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
2029
|
+
type: "button",
|
|
2030
|
+
className: "sb-detail-overlay__close",
|
|
2031
|
+
onClick: onClose,
|
|
2032
|
+
"aria-label": "Close",
|
|
2033
|
+
"data-testid": `${testId}-close`,
|
|
2034
|
+
children: "×"
|
|
2035
|
+
}), /* @__PURE__ */ jsx(TokenDetail, { path })]
|
|
2036
|
+
})
|
|
2037
|
+
});
|
|
2038
|
+
}
|
|
2039
|
+
//#endregion
|
|
2040
|
+
//#region src/ColorTable.tsx
|
|
2041
|
+
function ColorTable({ filter, caption, sortBy = "path", sortDir = "asc", searchable = true, onSelect, variants }) {
|
|
2042
|
+
const { resolved, activeTheme, cssVarPrefix } = useProject();
|
|
2043
|
+
const [selectedPath, setSelectedPath] = useState(null);
|
|
2044
|
+
const [query, setQuery] = useState("");
|
|
2045
|
+
const variantIndex = useMemo(() => buildVariantIndex(variants), [variants]);
|
|
2046
|
+
const rows = useMemo(() => {
|
|
2047
|
+
return sortTokens(Object.entries(resolved).filter(([path, token]) => {
|
|
2048
|
+
if (token.$type !== "color") return false;
|
|
2049
|
+
return globMatch(path, filter);
|
|
2050
|
+
}), {
|
|
2051
|
+
by: sortBy,
|
|
2052
|
+
dir: sortDir
|
|
2053
|
+
}).map(([path, token]) => {
|
|
2054
|
+
const raw = token.$value;
|
|
2055
|
+
const hex = formatColor(raw, "hex");
|
|
2056
|
+
const hsl = formatColor(raw, "hsl");
|
|
2057
|
+
const oklch = formatColor(raw, "oklch");
|
|
2058
|
+
const variant = matchVariant(path, variantIndex);
|
|
2059
|
+
return {
|
|
2060
|
+
path,
|
|
2061
|
+
cssVar: makeCssVar(path, cssVarPrefix),
|
|
2062
|
+
hex: hex.value,
|
|
2063
|
+
hsl: hsl.value,
|
|
2064
|
+
oklch: oklch.value,
|
|
2065
|
+
hexOutOfGamut: hex.outOfGamut,
|
|
2066
|
+
...token.aliasOf !== void 0 && { aliasOf: token.aliasOf },
|
|
2067
|
+
...variant !== void 0 && { variant }
|
|
2068
|
+
};
|
|
2069
|
+
});
|
|
2070
|
+
}, [
|
|
2324
2071
|
resolved,
|
|
2325
|
-
|
|
2072
|
+
filter,
|
|
2073
|
+
cssVarPrefix,
|
|
2074
|
+
sortBy,
|
|
2075
|
+
sortDir,
|
|
2076
|
+
variantIndex
|
|
2077
|
+
]);
|
|
2078
|
+
const visibleRows = useMemo(() => {
|
|
2079
|
+
if (!searchable || query.trim() === "") return rows;
|
|
2080
|
+
return fuzzyFilter(rows, query, (r) => `${r.path} ${r.hex} ${r.hsl} ${r.oklch}`);
|
|
2081
|
+
}, [
|
|
2082
|
+
rows,
|
|
2083
|
+
query,
|
|
2084
|
+
searchable
|
|
2085
|
+
]);
|
|
2086
|
+
const handleRowClick = useCallback((path) => {
|
|
2087
|
+
if (onSelect) onSelect(path);
|
|
2088
|
+
else setSelectedPath(path);
|
|
2089
|
+
}, [onSelect]);
|
|
2090
|
+
const matchSuffix = searchable && query.trim() !== "" ? ` · ${visibleRows.length} matching "${query.trim()}"` : "";
|
|
2091
|
+
const captionText = caption ?? `${rows.length} color${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""}${matchSuffix} · ${activeTheme}`;
|
|
2092
|
+
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
2093
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2094
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2095
|
+
className: "sb-block__empty",
|
|
2096
|
+
children: "No color tokens match this filter."
|
|
2097
|
+
})
|
|
2326
2098
|
});
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
[
|
|
2357
|
-
"letterSpacing",
|
|
2358
|
-
formatDimensionValue(v["letterSpacing"]),
|
|
2359
|
-
aliasFor("letterSpacing")
|
|
2360
|
-
]
|
|
2361
|
-
]);
|
|
2362
|
-
}
|
|
2363
|
-
if (type === "border") {
|
|
2364
|
-
const v = rawValue;
|
|
2365
|
-
return renderKeyValueList([
|
|
2366
|
-
[
|
|
2367
|
-
"color",
|
|
2368
|
-
formatColorSubValue(v["color"], colorFormat),
|
|
2369
|
-
aliasFor("color")
|
|
2370
|
-
],
|
|
2371
|
-
[
|
|
2372
|
-
"width",
|
|
2373
|
-
formatDimensionValue(v["width"]),
|
|
2374
|
-
aliasFor("width")
|
|
2375
|
-
],
|
|
2376
|
-
[
|
|
2377
|
-
"style",
|
|
2378
|
-
formatPrimitive(v["style"]),
|
|
2379
|
-
aliasFor("style")
|
|
2380
|
-
]
|
|
2381
|
-
]);
|
|
2382
|
-
}
|
|
2383
|
-
if (type === "transition") {
|
|
2384
|
-
const v = rawValue;
|
|
2385
|
-
return renderKeyValueList([
|
|
2386
|
-
[
|
|
2387
|
-
"duration",
|
|
2388
|
-
formatDimensionValue(v["duration"]),
|
|
2389
|
-
aliasFor("duration")
|
|
2390
|
-
],
|
|
2391
|
-
[
|
|
2392
|
-
"timingFunction",
|
|
2393
|
-
formatPrimitive(v["timingFunction"]),
|
|
2394
|
-
aliasFor("timingFunction")
|
|
2395
|
-
],
|
|
2396
|
-
[
|
|
2397
|
-
"delay",
|
|
2398
|
-
formatDimensionValue(v["delay"]),
|
|
2399
|
-
aliasFor("delay")
|
|
2400
|
-
]
|
|
2401
|
-
]);
|
|
2402
|
-
}
|
|
2403
|
-
if (type === "shadow") {
|
|
2404
|
-
const layers = Array.isArray(rawValue) ? rawValue : [rawValue];
|
|
2405
|
-
const multi = layers.length > 1;
|
|
2406
|
-
const layerAliasFor = (i, key) => subValueChain(arrayAliases?.[i]?.[key], resolved);
|
|
2407
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2408
|
-
className: "sb-token-detail__breakdown-section",
|
|
2409
|
-
children: layers.map((layer, i) => {
|
|
2410
|
-
const v = layer;
|
|
2411
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
2412
|
-
style: { display: "contents" },
|
|
2413
|
-
children: [
|
|
2414
|
-
multi && /* @__PURE__ */ jsxs("div", {
|
|
2415
|
-
className: "sb-token-detail__breakdown-layer-header",
|
|
2416
|
-
children: ["Layer ", i + 1]
|
|
2099
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2100
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2101
|
+
children: [
|
|
2102
|
+
searchable && /* @__PURE__ */ jsx("div", {
|
|
2103
|
+
className: "sb-color-table__search",
|
|
2104
|
+
children: /* @__PURE__ */ jsx("input", {
|
|
2105
|
+
type: "search",
|
|
2106
|
+
className: "sb-color-table__search-input",
|
|
2107
|
+
placeholder: "Search colors…",
|
|
2108
|
+
value: query,
|
|
2109
|
+
onChange: (e) => setQuery(e.target.value),
|
|
2110
|
+
"aria-label": "Fuzzy-search colors by path or value",
|
|
2111
|
+
"data-testid": "color-table-search"
|
|
2112
|
+
})
|
|
2113
|
+
}),
|
|
2114
|
+
/* @__PURE__ */ jsxs("table", {
|
|
2115
|
+
className: "sb-color-table__table",
|
|
2116
|
+
children: [
|
|
2117
|
+
/* @__PURE__ */ jsx("caption", {
|
|
2118
|
+
className: "sb-color-table__caption",
|
|
2119
|
+
children: captionText
|
|
2120
|
+
}),
|
|
2121
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
2122
|
+
/* @__PURE__ */ jsx("th", {
|
|
2123
|
+
className: "sb-color-table__th sb-color-table__th--swatch",
|
|
2124
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
2125
|
+
className: "sb-color-table__sr-only",
|
|
2126
|
+
children: "Swatch"
|
|
2127
|
+
})
|
|
2417
2128
|
}),
|
|
2418
|
-
/* @__PURE__ */ jsx(
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
alias: layerAliasFor(i, "color")
|
|
2129
|
+
/* @__PURE__ */ jsx("th", {
|
|
2130
|
+
className: "sb-color-table__th sb-color-table__th--path",
|
|
2131
|
+
children: "Name"
|
|
2422
2132
|
}),
|
|
2423
|
-
/* @__PURE__ */ jsx(
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
alias: layerAliasFor(i, "offsetX")
|
|
2133
|
+
/* @__PURE__ */ jsx("th", {
|
|
2134
|
+
className: "sb-color-table__th",
|
|
2135
|
+
children: "HEX"
|
|
2427
2136
|
}),
|
|
2428
|
-
/* @__PURE__ */ jsx(
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
alias: layerAliasFor(i, "offsetY")
|
|
2137
|
+
/* @__PURE__ */ jsx("th", {
|
|
2138
|
+
className: "sb-color-table__th",
|
|
2139
|
+
children: "HSL"
|
|
2432
2140
|
}),
|
|
2433
|
-
/* @__PURE__ */ jsx(
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
alias: layerAliasFor(i, "blur")
|
|
2141
|
+
/* @__PURE__ */ jsx("th", {
|
|
2142
|
+
className: "sb-color-table__th",
|
|
2143
|
+
children: "OKLCH"
|
|
2437
2144
|
}),
|
|
2438
|
-
/* @__PURE__ */ jsx(
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
alias: layerAliasFor(i, "spread")
|
|
2145
|
+
/* @__PURE__ */ jsx("th", {
|
|
2146
|
+
className: "sb-color-table__th",
|
|
2147
|
+
children: "CSS var"
|
|
2442
2148
|
}),
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
alias: void 0
|
|
2149
|
+
/* @__PURE__ */ jsx("th", {
|
|
2150
|
+
className: "sb-color-table__th",
|
|
2151
|
+
children: "Alias"
|
|
2447
2152
|
})
|
|
2448
|
-
]
|
|
2449
|
-
|
|
2153
|
+
] }) }),
|
|
2154
|
+
/* @__PURE__ */ jsxs("tbody", { children: [visibleRows.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsxs("td", {
|
|
2155
|
+
colSpan: 7,
|
|
2156
|
+
className: "sb-color-table__td sb-color-table__empty-row",
|
|
2157
|
+
children: [
|
|
2158
|
+
"No colors match \"",
|
|
2159
|
+
query.trim(),
|
|
2160
|
+
"\"."
|
|
2161
|
+
]
|
|
2162
|
+
}) }), visibleRows.map((row) => /* @__PURE__ */ jsxs("tr", {
|
|
2163
|
+
className: "sb-color-table__row",
|
|
2164
|
+
onClick: () => handleRowClick(row.path),
|
|
2165
|
+
onKeyDown: (e) => {
|
|
2166
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2167
|
+
e.preventDefault();
|
|
2168
|
+
handleRowClick(row.path);
|
|
2169
|
+
}
|
|
2170
|
+
},
|
|
2171
|
+
tabIndex: 0,
|
|
2172
|
+
"aria-label": `Inspect ${row.path}`,
|
|
2173
|
+
"data-testid": "color-table-row",
|
|
2174
|
+
"data-path": row.path,
|
|
2175
|
+
children: [
|
|
2176
|
+
/* @__PURE__ */ jsx("td", {
|
|
2177
|
+
className: "sb-color-table__td sb-color-table__swatch-cell",
|
|
2178
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
2179
|
+
className: "sb-color-table__swatch",
|
|
2180
|
+
style: { background: row.cssVar },
|
|
2181
|
+
"aria-hidden": true
|
|
2182
|
+
})
|
|
2183
|
+
}),
|
|
2184
|
+
/* @__PURE__ */ jsxs("td", {
|
|
2185
|
+
className: cx("sb-color-table__td", "sb-color-table__path"),
|
|
2186
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2187
|
+
className: "sb-color-table__path-text",
|
|
2188
|
+
children: row.path
|
|
2189
|
+
}), row.variant !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
2190
|
+
className: "sb-color-table__variant-pill",
|
|
2191
|
+
"data-variant": row.variant,
|
|
2192
|
+
"data-testid": "color-table-variant",
|
|
2193
|
+
children: row.variant
|
|
2194
|
+
})]
|
|
2195
|
+
}),
|
|
2196
|
+
/* @__PURE__ */ jsx(ValueCell, {
|
|
2197
|
+
value: row.hex,
|
|
2198
|
+
label: `Copy HEX ${row.hex}`,
|
|
2199
|
+
children: row.hexOutOfGamut && /* @__PURE__ */ jsx("span", {
|
|
2200
|
+
title: "Out of sRGB gamut",
|
|
2201
|
+
"aria-label": "out of gamut",
|
|
2202
|
+
className: "sb-color-table__gamut-warn",
|
|
2203
|
+
children: "⚠"
|
|
2204
|
+
})
|
|
2205
|
+
}),
|
|
2206
|
+
/* @__PURE__ */ jsx(ValueCell, {
|
|
2207
|
+
value: row.hsl,
|
|
2208
|
+
label: `Copy HSL ${row.hsl}`
|
|
2209
|
+
}),
|
|
2210
|
+
/* @__PURE__ */ jsx(ValueCell, {
|
|
2211
|
+
value: row.oklch,
|
|
2212
|
+
label: `Copy OKLCH ${row.oklch}`
|
|
2213
|
+
}),
|
|
2214
|
+
/* @__PURE__ */ jsx(ValueCell, {
|
|
2215
|
+
value: row.cssVar,
|
|
2216
|
+
label: `Copy CSS var ${row.cssVar}`
|
|
2217
|
+
}),
|
|
2218
|
+
/* @__PURE__ */ jsx("td", {
|
|
2219
|
+
className: "sb-color-table__td sb-color-table__alias",
|
|
2220
|
+
children: row.aliasOf ? /* @__PURE__ */ jsx("span", {
|
|
2221
|
+
className: "sb-color-table__alias-text",
|
|
2222
|
+
children: row.aliasOf
|
|
2223
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
2224
|
+
className: "sb-color-table__alias-empty",
|
|
2225
|
+
"aria-hidden": true,
|
|
2226
|
+
children: "—"
|
|
2227
|
+
})
|
|
2228
|
+
})
|
|
2229
|
+
]
|
|
2230
|
+
}, row.path))] })
|
|
2231
|
+
]
|
|
2232
|
+
}),
|
|
2233
|
+
selectedPath !== null && /* @__PURE__ */ jsx(DetailOverlay, {
|
|
2234
|
+
path: selectedPath,
|
|
2235
|
+
onClose: () => setSelectedPath(null),
|
|
2236
|
+
testId: "color-table-overlay"
|
|
2237
|
+
})
|
|
2238
|
+
]
|
|
2239
|
+
});
|
|
2240
|
+
}
|
|
2241
|
+
function ValueCell({ value, label, children }) {
|
|
2242
|
+
return /* @__PURE__ */ jsxs("td", {
|
|
2243
|
+
className: "sb-color-table__td sb-color-table__value-cell",
|
|
2244
|
+
children: [
|
|
2245
|
+
/* @__PURE__ */ jsx("span", {
|
|
2246
|
+
className: "sb-color-table__value-text",
|
|
2247
|
+
title: value,
|
|
2248
|
+
children: value
|
|
2249
|
+
}),
|
|
2250
|
+
children,
|
|
2251
|
+
/* @__PURE__ */ jsx("span", {
|
|
2252
|
+
className: "sb-color-table__copy-wrap",
|
|
2253
|
+
onClick: (e) => e.stopPropagation(),
|
|
2254
|
+
onKeyDown: (e) => e.stopPropagation(),
|
|
2255
|
+
role: "presentation",
|
|
2256
|
+
children: /* @__PURE__ */ jsx(CopyButton$1, {
|
|
2257
|
+
value,
|
|
2258
|
+
label,
|
|
2259
|
+
className: "sb-color-table__copy"
|
|
2260
|
+
})
|
|
2450
2261
|
})
|
|
2262
|
+
]
|
|
2263
|
+
});
|
|
2264
|
+
}
|
|
2265
|
+
/**
|
|
2266
|
+
* Pre-sort the variants map by descending suffix length so the first
|
|
2267
|
+
* `endsWith` hit during matching is always the longest. Empty suffixes are
|
|
2268
|
+
* dropped — they'd match every path and make the feature meaningless.
|
|
2269
|
+
*/
|
|
2270
|
+
function buildVariantIndex(variants) {
|
|
2271
|
+
if (!variants) return [];
|
|
2272
|
+
const entries = [];
|
|
2273
|
+
for (const [label, suffix] of Object.entries(variants)) {
|
|
2274
|
+
if (suffix.length === 0) continue;
|
|
2275
|
+
entries.push({
|
|
2276
|
+
label,
|
|
2277
|
+
suffix
|
|
2451
2278
|
});
|
|
2452
2279
|
}
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2280
|
+
entries.sort((a, b) => b.suffix.length - a.suffix.length);
|
|
2281
|
+
return entries;
|
|
2282
|
+
}
|
|
2283
|
+
/**
|
|
2284
|
+
* Resolve the variant label for a token path, if any. The leaf (last
|
|
2285
|
+
* dot-segment) must either equal the suffix outright (`hi.disabled`
|
|
2286
|
+
* matches suffix `disabled`) or end in `-<suffix>` (`hi-d` matches `d`).
|
|
2287
|
+
* The leading hyphen is required for the tail form, so suffix `h` matches
|
|
2288
|
+
* `hi-h` but not `highlight` or `neutral-900` — the whole trailing token
|
|
2289
|
+
* has to be the suffix, not a character within it. Entries are tried
|
|
2290
|
+
* longest-first, so `h-dark` wins over `dark` when both are configured
|
|
2291
|
+
* and the path ends in `-h-dark`.
|
|
2292
|
+
*/
|
|
2293
|
+
function matchVariant(path, variantIndex) {
|
|
2294
|
+
if (variantIndex.length === 0) return void 0;
|
|
2295
|
+
const leaf = path.split(".").at(-1) ?? path;
|
|
2296
|
+
for (const entry of variantIndex) if (leaf === entry.suffix || leaf.endsWith(`-${entry.suffix}`)) return entry.label;
|
|
2297
|
+
}
|
|
2298
|
+
//#endregion
|
|
2299
|
+
//#region src/Diagnostics.tsx
|
|
2300
|
+
const severityLabel = {
|
|
2301
|
+
error: "ERROR",
|
|
2302
|
+
warn: "WARN",
|
|
2303
|
+
info: "INFO"
|
|
2304
|
+
};
|
|
2305
|
+
function summaryText(diagnostics) {
|
|
2306
|
+
if (diagnostics.length === 0) return "✔ OK · no diagnostics";
|
|
2307
|
+
const counts = {
|
|
2308
|
+
error: 0,
|
|
2309
|
+
warn: 0,
|
|
2310
|
+
info: 0
|
|
2311
|
+
};
|
|
2312
|
+
for (const d of diagnostics) counts[d.severity] += 1;
|
|
2313
|
+
const parts = [];
|
|
2314
|
+
if (counts.error > 0) parts.push(`✖ ${counts.error} error${counts.error === 1 ? "" : "s"}`);
|
|
2315
|
+
if (counts.warn > 0) parts.push(`⚠ ${counts.warn} warning${counts.warn === 1 ? "" : "s"}`);
|
|
2316
|
+
if (counts.info > 0) parts.push(`${counts.info} info`);
|
|
2317
|
+
return parts.join(" · ");
|
|
2318
|
+
}
|
|
2319
|
+
function diagnosticKey(d, i) {
|
|
2320
|
+
return `${d.severity}:${d.group}:${d.filename ?? ""}:${d.line ?? ""}:${d.message}:${i}`;
|
|
2321
|
+
}
|
|
2322
|
+
function summaryVariant(diagnostics) {
|
|
2323
|
+
if (diagnostics.length === 0) return "ok";
|
|
2324
|
+
if (diagnostics.some((d) => d.severity === "error")) return "error";
|
|
2325
|
+
if (diagnostics.some((d) => d.severity === "warn")) return "warn";
|
|
2326
|
+
return null;
|
|
2327
|
+
}
|
|
2328
|
+
/**
|
|
2329
|
+
* Render the project's load diagnostics — parser errors, resolver warnings,
|
|
2330
|
+
* disabled-axes validation issues, etc. — as a collapsible list. Auto-opens
|
|
2331
|
+
* when the project carries errors or warnings; stays collapsed for clean
|
|
2332
|
+
* loads and info-only loads.
|
|
2333
|
+
*
|
|
2334
|
+
* Replaces the diagnostics section from the addon's (now-retired) Design
|
|
2335
|
+
* Tokens panel. Consumers compose it alongside TokenNavigator / TokenTable
|
|
2336
|
+
* on their own MDX pages.
|
|
2337
|
+
*/
|
|
2338
|
+
function Diagnostics({ caption } = {}) {
|
|
2339
|
+
const { activeTheme, cssVarPrefix, diagnostics } = useProject();
|
|
2340
|
+
const hasErrorsOrWarnings = diagnostics.some((d) => d.severity === "error" || d.severity === "warn");
|
|
2341
|
+
const headingText = caption ?? `Diagnostics · ${summaryText(diagnostics)}`;
|
|
2342
|
+
const variant = summaryVariant(diagnostics);
|
|
2343
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2344
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2345
|
+
"data-testid": "diagnostics",
|
|
2346
|
+
children: /* @__PURE__ */ jsxs("details", {
|
|
2347
|
+
open: hasErrorsOrWarnings,
|
|
2348
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
2349
|
+
className: cx("sb-diagnostics__summary", variant && `sb-diagnostics__summary--${variant}`),
|
|
2350
|
+
children: headingText
|
|
2351
|
+
}), diagnostics.length > 0 && /* @__PURE__ */ jsx("ul", {
|
|
2352
|
+
className: "sb-diagnostics__list",
|
|
2353
|
+
children: diagnostics.map((d, i) => /* @__PURE__ */ jsxs("li", {
|
|
2354
|
+
className: "sb-diagnostics__row",
|
|
2355
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2356
|
+
className: cx("sb-diagnostics__label", { [`sb-diagnostics__label--${d.severity}`]: d.severity !== "info" }),
|
|
2357
|
+
children: severityLabel[d.severity]
|
|
2358
|
+
}), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", { children: d.message }), (d.group || d.filename) && /* @__PURE__ */ jsx("div", {
|
|
2359
|
+
className: "sb-diagnostics__meta",
|
|
2360
|
+
children: [
|
|
2361
|
+
d.group,
|
|
2362
|
+
d.filename,
|
|
2363
|
+
d.line ? `:${d.line}` : ""
|
|
2364
|
+
].filter(Boolean).join(" · ")
|
|
2365
|
+
})] })]
|
|
2366
|
+
}, diagnosticKey(d, i)))
|
|
2367
|
+
})]
|
|
2368
|
+
})
|
|
2369
|
+
});
|
|
2370
|
+
}
|
|
2371
|
+
//#endregion
|
|
2372
|
+
//#region src/dimension-scale/DimensionBar.tsx
|
|
2373
|
+
const MAX_RENDER_PX$1 = 480;
|
|
2374
|
+
const styles$1 = {
|
|
2375
|
+
bar: {
|
|
2376
|
+
height: 14,
|
|
2377
|
+
background: "var(--swatchbook-accent-bg, #3b82f6)",
|
|
2378
|
+
borderRadius: 2,
|
|
2379
|
+
minWidth: 1
|
|
2380
|
+
},
|
|
2381
|
+
radiusSample: {
|
|
2382
|
+
width: 56,
|
|
2383
|
+
height: 56,
|
|
2384
|
+
background: "var(--swatchbook-accent-bg, #3b82f6)",
|
|
2385
|
+
border: BORDER_STRONG
|
|
2386
|
+
},
|
|
2387
|
+
sizeSample: {
|
|
2388
|
+
background: "var(--swatchbook-accent-bg, #3b82f6)",
|
|
2389
|
+
border: BORDER_STRONG,
|
|
2390
|
+
minWidth: 1,
|
|
2391
|
+
minHeight: 1
|
|
2392
|
+
}
|
|
2393
|
+
};
|
|
2394
|
+
/**
|
|
2395
|
+
* Convert a DTCG dimension `$value` (`{ value, unit }`) to pixels for the
|
|
2396
|
+
* purpose of deciding whether to cap the rendered bar. Returns `NaN` for
|
|
2397
|
+
* units we can't reasonably approximate (ex / ch / %), which the caller
|
|
2398
|
+
* treats as "render at cssVar but don't cap".
|
|
2399
|
+
*/
|
|
2400
|
+
function toPixels$1(raw) {
|
|
2401
|
+
if (raw == null || typeof raw !== "object") return NaN;
|
|
2402
|
+
const v = raw;
|
|
2403
|
+
if (typeof v.value !== "number" || typeof v.unit !== "string") return NaN;
|
|
2404
|
+
switch (v.unit) {
|
|
2405
|
+
case "px": return v.value;
|
|
2406
|
+
case "rem":
|
|
2407
|
+
case "em": return v.value * 16;
|
|
2408
|
+
default: return NaN;
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
function DimensionBar({ path, kind = "length" }) {
|
|
2412
|
+
const { resolved, cssVarPrefix } = useProject();
|
|
2413
|
+
const cssVar = makeCssVar(path, cssVarPrefix);
|
|
2414
|
+
const token = resolved[path];
|
|
2415
|
+
const pxValue = toPixels$1(token?.$value);
|
|
2416
|
+
const cappedValue = Number.isFinite(pxValue) && pxValue > MAX_RENDER_PX$1 ? `${MAX_RENDER_PX$1}px` : cssVar;
|
|
2417
|
+
switch (kind) {
|
|
2418
|
+
case "radius": return /* @__PURE__ */ jsx("div", {
|
|
2419
|
+
style: {
|
|
2420
|
+
...styles$1.radiusSample,
|
|
2421
|
+
borderRadius: cssVar
|
|
2422
|
+
},
|
|
2423
|
+
"aria-hidden": true
|
|
2424
|
+
});
|
|
2425
|
+
case "size": return /* @__PURE__ */ jsx("div", {
|
|
2426
|
+
style: {
|
|
2427
|
+
...styles$1.sizeSample,
|
|
2428
|
+
width: cappedValue,
|
|
2429
|
+
height: cappedValue
|
|
2430
|
+
},
|
|
2431
|
+
"aria-hidden": true
|
|
2432
|
+
});
|
|
2433
|
+
default: return /* @__PURE__ */ jsx("div", {
|
|
2434
|
+
style: {
|
|
2435
|
+
...styles$1.bar,
|
|
2436
|
+
width: cappedValue
|
|
2437
|
+
},
|
|
2438
|
+
"aria-hidden": true
|
|
2467
2439
|
});
|
|
2468
2440
|
}
|
|
2469
|
-
return null;
|
|
2470
2441
|
}
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2442
|
+
//#endregion
|
|
2443
|
+
//#region src/DimensionScale.tsx
|
|
2444
|
+
const MAX_RENDER_PX = 480;
|
|
2445
|
+
function toPixels(raw) {
|
|
2446
|
+
if (raw == null || typeof raw !== "object") return NaN;
|
|
2447
|
+
const v = raw;
|
|
2448
|
+
if (typeof v.value !== "number" || typeof v.unit !== "string") return NaN;
|
|
2449
|
+
switch (v.unit) {
|
|
2450
|
+
case "px": return v.value;
|
|
2451
|
+
case "rem":
|
|
2452
|
+
case "em": return v.value * 16;
|
|
2453
|
+
default: return NaN;
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
function DimensionScale({ filter, kind = "length", caption, sortBy = "value", sortDir = "asc" }) {
|
|
2457
|
+
const { resolved, activeTheme, cssVarPrefix } = useProject();
|
|
2458
|
+
const rows = useMemo(() => {
|
|
2459
|
+
return sortTokens(Object.entries(resolved).filter(([path, token]) => {
|
|
2460
|
+
if (token.$type !== "dimension") return false;
|
|
2461
|
+
return globMatch(path, filter);
|
|
2462
|
+
}), {
|
|
2463
|
+
by: sortBy,
|
|
2464
|
+
dir: sortDir
|
|
2465
|
+
}).map(([path, token]) => {
|
|
2466
|
+
const pxValue = toPixels(token.$value);
|
|
2467
|
+
return {
|
|
2468
|
+
path,
|
|
2469
|
+
cssVar: makeCssVar(path, cssVarPrefix),
|
|
2470
|
+
displayValue: formatTokenValue(token.$value, token.$type, "raw"),
|
|
2471
|
+
pxValue,
|
|
2472
|
+
capped: Number.isFinite(pxValue) && pxValue > MAX_RENDER_PX
|
|
2473
|
+
};
|
|
2474
|
+
});
|
|
2475
|
+
}, [
|
|
2476
|
+
resolved,
|
|
2477
|
+
filter,
|
|
2478
|
+
cssVarPrefix,
|
|
2479
|
+
sortBy,
|
|
2480
|
+
sortDir
|
|
2481
|
+
]);
|
|
2482
|
+
const captionText = caption ?? `${rows.length} dimension${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
2483
|
+
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
2484
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2485
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2486
|
+
className: "sb-block__empty",
|
|
2487
|
+
children: "No dimension tokens match this filter."
|
|
2488
|
+
})
|
|
2489
|
+
});
|
|
2490
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2491
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2492
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2493
|
+
className: "sb-block__caption",
|
|
2494
|
+
children: captionText
|
|
2495
|
+
}), rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
2496
|
+
className: "sb-dimension-scale__row",
|
|
2497
|
+
children: [
|
|
2498
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2499
|
+
className: "sb-dimension-scale__meta",
|
|
2500
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2501
|
+
className: "sb-dimension-scale__path",
|
|
2502
|
+
children: row.path
|
|
2503
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
2504
|
+
className: "sb-dimension-scale__specs",
|
|
2505
|
+
children: row.displayValue
|
|
2506
|
+
})]
|
|
2507
|
+
}),
|
|
2508
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2509
|
+
className: "sb-dimension-scale__visual-cell",
|
|
2510
|
+
children: [/* @__PURE__ */ jsx(DimensionBar, {
|
|
2511
|
+
path: row.path,
|
|
2512
|
+
kind
|
|
2513
|
+
}), row.capped && /* @__PURE__ */ jsxs("span", {
|
|
2514
|
+
className: "sb-dimension-scale__cap",
|
|
2515
|
+
children: [
|
|
2516
|
+
"capped at ",
|
|
2517
|
+
MAX_RENDER_PX,
|
|
2518
|
+
"px"
|
|
2519
|
+
]
|
|
2520
|
+
})]
|
|
2521
|
+
}),
|
|
2522
|
+
/* @__PURE__ */ jsx("span", {
|
|
2523
|
+
className: "sb-dimension-scale__css-var",
|
|
2524
|
+
children: row.cssVar
|
|
2525
|
+
})
|
|
2526
|
+
]
|
|
2527
|
+
}, row.path))]
|
|
2479
2528
|
});
|
|
2480
2529
|
}
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
})
|
|
2502
|
-
}
|
|
2530
|
+
//#endregion
|
|
2531
|
+
//#region src/FontFamilySample.tsx
|
|
2532
|
+
function stackString(raw) {
|
|
2533
|
+
if (typeof raw === "string") return raw;
|
|
2534
|
+
if (Array.isArray(raw)) return raw.map(String).join(", ");
|
|
2535
|
+
return "";
|
|
2536
|
+
}
|
|
2537
|
+
function FontFamilySample({ filter, sample = "The quick brown fox jumps over the lazy dog.", caption, sortBy = "path", sortDir = "asc" }) {
|
|
2538
|
+
const { resolved, activeTheme, cssVarPrefix } = useProject();
|
|
2539
|
+
const rows = useMemo(() => {
|
|
2540
|
+
return sortTokens(Object.entries(resolved).filter(([path, token]) => {
|
|
2541
|
+
if (token.$type !== "fontFamily") return false;
|
|
2542
|
+
return globMatch(path, filter);
|
|
2543
|
+
}), {
|
|
2544
|
+
by: sortBy,
|
|
2545
|
+
dir: sortDir
|
|
2546
|
+
}).map(([path, token]) => ({
|
|
2547
|
+
path,
|
|
2548
|
+
cssVar: makeCssVar(path, cssVarPrefix),
|
|
2549
|
+
stack: stackString(token.$value)
|
|
2550
|
+
}));
|
|
2551
|
+
}, [
|
|
2552
|
+
resolved,
|
|
2553
|
+
filter,
|
|
2554
|
+
cssVarPrefix,
|
|
2555
|
+
sortBy,
|
|
2556
|
+
sortDir
|
|
2557
|
+
]);
|
|
2558
|
+
const captionText = caption ?? `${rows.length} fontFamily token${rows.length === 1 ? "" : "s"}${filter && filter !== "fontFamily" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
2559
|
+
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
2560
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2561
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2562
|
+
className: "sb-block__empty",
|
|
2563
|
+
children: "No fontFamily tokens match this filter."
|
|
2564
|
+
})
|
|
2565
|
+
});
|
|
2566
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2567
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2568
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2569
|
+
className: "sb-block__caption",
|
|
2570
|
+
children: captionText
|
|
2571
|
+
}), rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
2572
|
+
className: "sb-font-family-sample__row",
|
|
2573
|
+
children: [
|
|
2574
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2575
|
+
className: "sb-font-family-sample__meta",
|
|
2576
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2577
|
+
className: "sb-font-family-sample__path",
|
|
2578
|
+
children: row.path
|
|
2579
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
2580
|
+
className: "sb-font-family-sample__stack",
|
|
2581
|
+
children: row.stack
|
|
2582
|
+
})]
|
|
2583
|
+
}),
|
|
2584
|
+
/* @__PURE__ */ jsx("div", {
|
|
2585
|
+
className: "sb-font-family-sample__sample",
|
|
2586
|
+
style: { fontFamily: row.cssVar },
|
|
2587
|
+
children: sample
|
|
2588
|
+
}),
|
|
2589
|
+
/* @__PURE__ */ jsx("span", {
|
|
2590
|
+
className: "sb-font-family-sample__css-var",
|
|
2591
|
+
children: row.cssVar
|
|
2592
|
+
})
|
|
2593
|
+
]
|
|
2594
|
+
}, row.path))]
|
|
2595
|
+
});
|
|
2503
2596
|
}
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2597
|
+
//#endregion
|
|
2598
|
+
//#region src/FontWeightScale.tsx
|
|
2599
|
+
function toWeight(raw) {
|
|
2600
|
+
if (typeof raw === "number") return raw;
|
|
2601
|
+
if (typeof raw === "string") {
|
|
2602
|
+
const n = Number.parseInt(raw, 10);
|
|
2603
|
+
return Number.isFinite(n) ? n : NaN;
|
|
2604
|
+
}
|
|
2605
|
+
return NaN;
|
|
2508
2606
|
}
|
|
2509
|
-
function
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2607
|
+
function FontWeightScale({ filter, sample = "Aa", caption, sortBy = "value", sortDir = "asc" }) {
|
|
2608
|
+
const { resolved, activeTheme, cssVarPrefix } = useProject();
|
|
2609
|
+
const rows = useMemo(() => {
|
|
2610
|
+
return sortTokens(Object.entries(resolved).filter(([path, token]) => {
|
|
2611
|
+
if (token.$type !== "fontWeight") return false;
|
|
2612
|
+
return globMatch(path, filter);
|
|
2613
|
+
}), {
|
|
2614
|
+
by: sortBy,
|
|
2615
|
+
dir: sortDir
|
|
2616
|
+
}).map(([path, token]) => ({
|
|
2617
|
+
path,
|
|
2618
|
+
cssVar: makeCssVar(path, cssVarPrefix),
|
|
2619
|
+
display: token.$value == null ? "" : String(token.$value),
|
|
2620
|
+
weight: toWeight(token.$value)
|
|
2621
|
+
}));
|
|
2622
|
+
}, [
|
|
2623
|
+
resolved,
|
|
2624
|
+
filter,
|
|
2625
|
+
cssVarPrefix,
|
|
2626
|
+
sortBy,
|
|
2627
|
+
sortDir
|
|
2628
|
+
]);
|
|
2629
|
+
const captionText = caption ?? `${rows.length} fontWeight token${rows.length === 1 ? "" : "s"}${filter && filter !== "fontWeight" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
2630
|
+
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
2631
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2632
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2633
|
+
className: "sb-block__empty",
|
|
2634
|
+
children: "No fontWeight tokens match this filter."
|
|
2635
|
+
})
|
|
2636
|
+
});
|
|
2637
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2638
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2639
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2640
|
+
className: "sb-block__caption",
|
|
2641
|
+
children: captionText
|
|
2642
|
+
}), rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
2643
|
+
className: "sb-font-weight-scale__row",
|
|
2644
|
+
children: [
|
|
2645
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2646
|
+
className: "sb-font-weight-scale__meta",
|
|
2647
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2648
|
+
className: "sb-font-weight-scale__path",
|
|
2649
|
+
children: row.path
|
|
2650
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
2651
|
+
className: "sb-font-weight-scale__value",
|
|
2652
|
+
children: row.display
|
|
2653
|
+
})]
|
|
2654
|
+
}),
|
|
2655
|
+
/* @__PURE__ */ jsx("div", {
|
|
2656
|
+
className: "sb-font-weight-scale__sample",
|
|
2657
|
+
style: { fontWeight: row.cssVar },
|
|
2658
|
+
children: sample
|
|
2659
|
+
}),
|
|
2660
|
+
/* @__PURE__ */ jsx("span", {
|
|
2661
|
+
className: "sb-font-weight-scale__css-var",
|
|
2662
|
+
children: row.cssVar
|
|
2663
|
+
})
|
|
2664
|
+
]
|
|
2665
|
+
}, row.path))]
|
|
2666
|
+
});
|
|
2514
2667
|
}
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
if (
|
|
2519
|
-
|
|
2520
|
-
if (typeof d.value === "number" && typeof d.unit === "string") return `${d.value}${d.unit}`;
|
|
2521
|
-
}
|
|
2522
|
-
return JSON.stringify(v);
|
|
2668
|
+
//#endregion
|
|
2669
|
+
//#region src/GradientPalette.tsx
|
|
2670
|
+
function asStops(raw) {
|
|
2671
|
+
if (!Array.isArray(raw)) return [];
|
|
2672
|
+
return raw;
|
|
2523
2673
|
}
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
return formatColor(v, format).value;
|
|
2674
|
+
const pct = (n) => `${(n * 100).toFixed(3)}%`;
|
|
2675
|
+
function stopCssColor(stop) {
|
|
2676
|
+
const color = stop.color;
|
|
2677
|
+
if (!color || !Array.isArray(color.components) || color.components.length < 3) return "transparent";
|
|
2678
|
+
const [r, g, b] = color.components;
|
|
2679
|
+
if (r === void 0 || g === void 0 || b === void 0) return "transparent";
|
|
2680
|
+
const alpha = color.alpha ?? 1;
|
|
2681
|
+
return alpha === 1 ? `rgb(${pct(r)} ${pct(g)} ${pct(b)})` : `rgb(${pct(r)} ${pct(g)} ${pct(b)} / ${alpha})`;
|
|
2533
2682
|
}
|
|
2534
|
-
function
|
|
2535
|
-
|
|
2536
|
-
return v;
|
|
2683
|
+
function stopKey(path, stop, fallback) {
|
|
2684
|
+
return `${path}|${stop.position ?? fallback}|${stopCssColor(stop)}`;
|
|
2537
2685
|
}
|
|
2538
|
-
function
|
|
2539
|
-
|
|
2540
|
-
|
|
2686
|
+
function GradientPalette({ filter, caption, sortBy = "path", sortDir = "asc" }) {
|
|
2687
|
+
const { resolved, activeTheme, cssVarPrefix } = useProject();
|
|
2688
|
+
const colorFormat = useColorFormat();
|
|
2689
|
+
const rows = useMemo(() => {
|
|
2690
|
+
return sortTokens(Object.entries(resolved).filter(([path, token]) => {
|
|
2691
|
+
if (token.$type !== "gradient") return false;
|
|
2692
|
+
return globMatch(path, filter);
|
|
2693
|
+
}), {
|
|
2694
|
+
by: sortBy,
|
|
2695
|
+
dir: sortDir
|
|
2696
|
+
}).map(([path, token]) => ({
|
|
2697
|
+
path,
|
|
2698
|
+
cssVar: makeCssVar(path, cssVarPrefix),
|
|
2699
|
+
stops: asStops(token.$value)
|
|
2700
|
+
}));
|
|
2701
|
+
}, [
|
|
2702
|
+
resolved,
|
|
2703
|
+
filter,
|
|
2704
|
+
cssVarPrefix,
|
|
2705
|
+
sortBy,
|
|
2706
|
+
sortDir
|
|
2707
|
+
]);
|
|
2708
|
+
const captionText = caption ?? `${rows.length} gradient${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
2709
|
+
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
2710
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2711
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2712
|
+
className: "sb-block__empty",
|
|
2713
|
+
children: "No gradient tokens match this filter."
|
|
2714
|
+
})
|
|
2715
|
+
});
|
|
2716
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2717
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2718
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2719
|
+
className: "sb-block__caption",
|
|
2720
|
+
children: captionText
|
|
2721
|
+
}), rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
2722
|
+
className: "sb-gradient-palette__row",
|
|
2723
|
+
children: [
|
|
2724
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2725
|
+
className: "sb-gradient-palette__meta",
|
|
2726
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2727
|
+
className: "sb-gradient-palette__path",
|
|
2728
|
+
children: row.path
|
|
2729
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
2730
|
+
className: "sb-gradient-palette__css-var",
|
|
2731
|
+
children: row.cssVar
|
|
2732
|
+
})]
|
|
2733
|
+
}),
|
|
2734
|
+
/* @__PURE__ */ jsx("div", {
|
|
2735
|
+
className: "sb-gradient-palette__sample",
|
|
2736
|
+
style: { background: `linear-gradient(to right, ${row.cssVar})` },
|
|
2737
|
+
"aria-hidden": true
|
|
2738
|
+
}),
|
|
2739
|
+
/* @__PURE__ */ jsx("div", {
|
|
2740
|
+
className: "sb-gradient-palette__stops",
|
|
2741
|
+
children: row.stops.map((stop, i) => /* @__PURE__ */ jsxs("div", {
|
|
2742
|
+
className: "sb-gradient-palette__stop-row",
|
|
2743
|
+
children: [
|
|
2744
|
+
/* @__PURE__ */ jsx("span", {
|
|
2745
|
+
className: "sb-gradient-palette__stop-swatch",
|
|
2746
|
+
style: { background: stopCssColor(stop) },
|
|
2747
|
+
"aria-hidden": true
|
|
2748
|
+
}),
|
|
2749
|
+
/* @__PURE__ */ jsx("span", { children: formatColor(stop.color, colorFormat).value }),
|
|
2750
|
+
/* @__PURE__ */ jsxs("span", {
|
|
2751
|
+
className: "sb-gradient-palette__stop-position",
|
|
2752
|
+
children: [
|
|
2753
|
+
"@ ",
|
|
2754
|
+
((stop.position ?? 0) * 100).toFixed(0),
|
|
2755
|
+
"%"
|
|
2756
|
+
]
|
|
2757
|
+
})
|
|
2758
|
+
]
|
|
2759
|
+
}, stopKey(row.path, stop, i)))
|
|
2760
|
+
})
|
|
2761
|
+
]
|
|
2762
|
+
}, row.path))]
|
|
2763
|
+
});
|
|
2541
2764
|
}
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2765
|
+
//#endregion
|
|
2766
|
+
//#region src/motion-preview/MotionSample.tsx
|
|
2767
|
+
const DEFAULT_DURATION_MS = 300;
|
|
2768
|
+
const DEFAULT_EASING = "cubic-bezier(0.2, 0, 0, 1)";
|
|
2769
|
+
const styles = {
|
|
2770
|
+
track: {
|
|
2771
|
+
position: "relative",
|
|
2772
|
+
height: 36,
|
|
2773
|
+
background: SURFACE_MUTED,
|
|
2774
|
+
borderRadius: 18,
|
|
2775
|
+
overflow: "hidden"
|
|
2776
|
+
},
|
|
2777
|
+
ball: {
|
|
2778
|
+
position: "absolute",
|
|
2779
|
+
top: "50%",
|
|
2780
|
+
width: 28,
|
|
2781
|
+
height: 28,
|
|
2782
|
+
marginTop: -14,
|
|
2783
|
+
borderRadius: "50%",
|
|
2784
|
+
background: "var(--swatchbook-accent-bg, #3b82f6)"
|
|
2785
|
+
},
|
|
2786
|
+
reducedMotion: {
|
|
2787
|
+
fontSize: 11,
|
|
2788
|
+
color: TEXT_MUTED,
|
|
2789
|
+
fontStyle: "italic"
|
|
2790
|
+
}
|
|
2791
|
+
};
|
|
2792
|
+
function extractDurationMs(raw) {
|
|
2793
|
+
if (raw == null) return NaN;
|
|
2794
|
+
if (typeof raw === "object") {
|
|
2795
|
+
const v = raw;
|
|
2796
|
+
if (typeof v.value === "number" && typeof v.unit === "string") {
|
|
2797
|
+
if (v.unit === "ms") return v.value;
|
|
2798
|
+
if (v.unit === "s") return v.value * 1e3;
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
return NaN;
|
|
2802
|
+
}
|
|
2803
|
+
function extractCubicBezier(raw) {
|
|
2804
|
+
if (Array.isArray(raw) && raw.length === 4 && raw.every((n) => typeof n === "number")) return `cubic-bezier(${raw.map((n) => Number(n).toFixed(3)).join(", ")})`;
|
|
2805
|
+
return null;
|
|
2551
2806
|
}
|
|
2552
|
-
function
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2807
|
+
function asDuration(raw, themeTokens, fallback) {
|
|
2808
|
+
const direct = extractDurationMs(raw);
|
|
2809
|
+
if (Number.isFinite(direct)) return direct;
|
|
2810
|
+
if (typeof raw === "string") {
|
|
2811
|
+
const match = raw.match(/^\{([^}]+)\}$/);
|
|
2812
|
+
if (match && match[1]) {
|
|
2813
|
+
const referenced = themeTokens[match[1]];
|
|
2814
|
+
const resolved = extractDurationMs(referenced?.$value);
|
|
2815
|
+
if (Number.isFinite(resolved)) return resolved;
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
return fallback;
|
|
2561
2819
|
}
|
|
2562
|
-
function
|
|
2563
|
-
|
|
2820
|
+
function asEasing(raw, themeTokens, fallback) {
|
|
2821
|
+
const direct = extractCubicBezier(raw);
|
|
2822
|
+
if (direct) return direct;
|
|
2823
|
+
if (typeof raw === "string") {
|
|
2824
|
+
const match = raw.match(/^\{([^}]+)\}$/);
|
|
2825
|
+
if (match && match[1]) {
|
|
2826
|
+
const referenced = themeTokens[match[1]];
|
|
2827
|
+
const resolved = extractCubicBezier(referenced?.$value);
|
|
2828
|
+
if (resolved) return resolved;
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
return fallback;
|
|
2564
2832
|
}
|
|
2565
|
-
|
|
2566
|
-
//#region src/token-detail/CompositePreview.tsx
|
|
2567
|
-
const PANGRAM = "Sphinx of black quartz, judge my vow.";
|
|
2568
|
-
const STROKE_STYLE_STRINGS = new Set([
|
|
2569
|
-
"solid",
|
|
2570
|
-
"dashed",
|
|
2571
|
-
"dotted",
|
|
2572
|
-
"double",
|
|
2573
|
-
"groove",
|
|
2574
|
-
"ridge",
|
|
2575
|
-
"outset",
|
|
2576
|
-
"inset"
|
|
2577
|
-
]);
|
|
2578
|
-
function CompositePreview({ path }) {
|
|
2579
|
-
const { token, cssVar } = useTokenDetailData(path);
|
|
2833
|
+
function resolveMotionSpec(token, themeTokens) {
|
|
2580
2834
|
if (!token) return null;
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
if (type === "typography") {
|
|
2589
|
-
const base = cssVar.replace(/^var\(/, "").replace(/\)$/, "");
|
|
2590
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2591
|
-
className: "sb-token-detail__typography-sample",
|
|
2592
|
-
style: {
|
|
2593
|
-
fontFamily: `var(${base}-font-family)`,
|
|
2594
|
-
fontSize: `var(${base}-font-size)`,
|
|
2595
|
-
fontWeight: `var(${base}-font-weight)`,
|
|
2596
|
-
lineHeight: `var(${base}-line-height)`,
|
|
2597
|
-
letterSpacing: `var(${base}-letter-spacing)`
|
|
2598
|
-
},
|
|
2599
|
-
children: PANGRAM
|
|
2600
|
-
});
|
|
2835
|
+
const type = token.$type;
|
|
2836
|
+
if (type === "transition") {
|
|
2837
|
+
const v = token.$value ?? {};
|
|
2838
|
+
return {
|
|
2839
|
+
durationMs: asDuration(v.duration, themeTokens, DEFAULT_DURATION_MS),
|
|
2840
|
+
easing: asEasing(v.timingFunction, themeTokens, DEFAULT_EASING)
|
|
2841
|
+
};
|
|
2601
2842
|
}
|
|
2602
|
-
if (type === "
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2843
|
+
if (type === "duration") {
|
|
2844
|
+
const durationMs = extractDurationMs(token.$value);
|
|
2845
|
+
if (!Number.isFinite(durationMs)) return null;
|
|
2846
|
+
return {
|
|
2847
|
+
durationMs,
|
|
2848
|
+
easing: DEFAULT_EASING
|
|
2849
|
+
};
|
|
2850
|
+
}
|
|
2851
|
+
if (type === "cubicBezier") {
|
|
2852
|
+
const easing = extractCubicBezier(token.$value);
|
|
2853
|
+
if (!easing) return null;
|
|
2854
|
+
return {
|
|
2855
|
+
durationMs: DEFAULT_DURATION_MS,
|
|
2856
|
+
easing
|
|
2857
|
+
};
|
|
2858
|
+
}
|
|
2859
|
+
return null;
|
|
2860
|
+
}
|
|
2861
|
+
function MotionSample({ path, speed = 1, runKey = 0 }) {
|
|
2862
|
+
const { resolved } = useProject();
|
|
2863
|
+
const reducedMotion = usePrefersReducedMotion();
|
|
2864
|
+
const spec = useMemo(() => resolveMotionSpec(resolved[path], resolved), [resolved, path]);
|
|
2865
|
+
const durationMs = spec?.durationMs ?? DEFAULT_DURATION_MS;
|
|
2866
|
+
const easing = spec?.easing ?? DEFAULT_EASING;
|
|
2867
|
+
const scaledDuration = Math.max(1, durationMs / speed);
|
|
2868
|
+
const [phase, setPhase] = useState(0);
|
|
2869
|
+
useEffect(() => {
|
|
2870
|
+
if (reducedMotion) return;
|
|
2871
|
+
setPhase(0);
|
|
2872
|
+
const id = requestAnimationFrame(() => setPhase(1));
|
|
2873
|
+
const loop = window.setInterval(() => {
|
|
2874
|
+
setPhase((p) => p === 0 ? 1 : 0);
|
|
2875
|
+
}, scaledDuration * 2);
|
|
2876
|
+
return () => {
|
|
2877
|
+
cancelAnimationFrame(id);
|
|
2878
|
+
window.clearInterval(loop);
|
|
2879
|
+
};
|
|
2880
|
+
}, [
|
|
2881
|
+
scaledDuration,
|
|
2882
|
+
runKey,
|
|
2883
|
+
reducedMotion
|
|
2884
|
+
]);
|
|
2885
|
+
if (reducedMotion) return /* @__PURE__ */ jsx("div", {
|
|
2886
|
+
style: styles.reducedMotion,
|
|
2887
|
+
children: "Animation suppressed by `prefers-reduced-motion: reduce`."
|
|
2611
2888
|
});
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
className: "sb-token-detail__dimension-track",
|
|
2889
|
+
return /* @__PURE__ */ jsx("div", {
|
|
2890
|
+
style: styles.track,
|
|
2615
2891
|
children: /* @__PURE__ */ jsx("div", {
|
|
2616
|
-
|
|
2617
|
-
|
|
2892
|
+
style: {
|
|
2893
|
+
...styles.ball,
|
|
2894
|
+
left: phase === 1 ? "calc(100% - 32px)" : "4px",
|
|
2895
|
+
transition: `left ${scaledDuration}ms ${easing}`
|
|
2896
|
+
},
|
|
2618
2897
|
"aria-hidden": true
|
|
2619
2898
|
})
|
|
2620
2899
|
});
|
|
2621
|
-
if (type === "duration") return /* @__PURE__ */ jsx(TransitionSample, { transition: `left ${cssVar} ease` });
|
|
2622
|
-
if (type === "fontFamily") return /* @__PURE__ */ jsx("div", {
|
|
2623
|
-
className: "sb-token-detail__font-family-sample",
|
|
2624
|
-
style: { fontFamily: cssVar },
|
|
2625
|
-
children: PANGRAM
|
|
2626
|
-
});
|
|
2627
|
-
if (type === "fontWeight") return /* @__PURE__ */ jsx("div", {
|
|
2628
|
-
className: "sb-token-detail__font-weight-sample",
|
|
2629
|
-
style: { fontWeight: cssVar },
|
|
2630
|
-
children: "Aa"
|
|
2631
|
-
});
|
|
2632
|
-
if (type === "cubicBezier") return /* @__PURE__ */ jsx(TransitionSample, { transition: `left 800ms ${cssVar}` });
|
|
2633
|
-
if (type === "gradient") return /* @__PURE__ */ jsx("div", {
|
|
2634
|
-
className: "sb-token-detail__gradient-sample",
|
|
2635
|
-
style: { background: `linear-gradient(to right, ${cssVar})` },
|
|
2636
|
-
"aria-hidden": true
|
|
2637
|
-
});
|
|
2638
|
-
if (type === "strokeStyle") return /* @__PURE__ */ jsx(StrokeStylePreview, { value: rawValue });
|
|
2639
|
-
if (type === "color") return /* @__PURE__ */ jsxs("div", {
|
|
2640
|
-
className: "sb-token-detail__color-swatch-row",
|
|
2641
|
-
"aria-hidden": true,
|
|
2642
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
2643
|
-
className: "sb-token-detail__color-swatch-light",
|
|
2644
|
-
style: { background: cssVar }
|
|
2645
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
2646
|
-
className: "sb-token-detail__color-swatch-dark",
|
|
2647
|
-
style: { background: cssVar }
|
|
2648
|
-
})]
|
|
2649
|
-
});
|
|
2650
|
-
return null;
|
|
2651
2900
|
}
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
}
|
|
2665
|
-
const cap = typeof v.lineCap === "string" ? v.lineCap : "butt";
|
|
2666
|
-
return /* @__PURE__ */ jsx("svg", {
|
|
2667
|
-
className: "sb-token-detail__stroke-style-svg",
|
|
2668
|
-
viewBox: "0 0 220 24",
|
|
2669
|
-
preserveAspectRatio: "none",
|
|
2670
|
-
"aria-hidden": true,
|
|
2671
|
-
children: /* @__PURE__ */ jsx("line", {
|
|
2672
|
-
x1: "4",
|
|
2673
|
-
y1: "12",
|
|
2674
|
-
x2: "216",
|
|
2675
|
-
y2: "12",
|
|
2676
|
-
stroke: "currentColor",
|
|
2677
|
-
strokeWidth: "4",
|
|
2678
|
-
strokeDasharray: lengths.join(" "),
|
|
2679
|
-
strokeLinecap: cap
|
|
2680
|
-
})
|
|
2681
|
-
});
|
|
2901
|
+
//#endregion
|
|
2902
|
+
//#region src/MotionPreview.tsx
|
|
2903
|
+
const SPEEDS = [
|
|
2904
|
+
.25,
|
|
2905
|
+
.5,
|
|
2906
|
+
1,
|
|
2907
|
+
2
|
|
2908
|
+
];
|
|
2909
|
+
function formatSpec(row) {
|
|
2910
|
+
switch (row.kind) {
|
|
2911
|
+
case "transition": return `transition · ${Math.round(row.durationMs)}ms · ${row.easing}`;
|
|
2912
|
+
case "duration": return `duration · ${Math.round(row.durationMs)}ms`;
|
|
2913
|
+
case "cubicBezier": return `cubicBezier · ${row.easing}`;
|
|
2682
2914
|
}
|
|
2683
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2684
|
-
className: "sb-token-detail__stroke-style-fallback",
|
|
2685
|
-
children: "strokeStyle value could not be previewed."
|
|
2686
|
-
});
|
|
2687
2915
|
}
|
|
2688
|
-
function
|
|
2689
|
-
|
|
2690
|
-
const
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2916
|
+
function MotionPreview({ filter, caption }) {
|
|
2917
|
+
const { resolved, activeTheme, cssVarPrefix } = useProject();
|
|
2918
|
+
const [speed, setSpeed] = useState(1);
|
|
2919
|
+
const [run, setRun] = useState(0);
|
|
2920
|
+
const reducedMotion = usePrefersReducedMotion();
|
|
2921
|
+
const rows = useMemo(() => {
|
|
2922
|
+
const collected = [];
|
|
2923
|
+
for (const [path, token] of Object.entries(resolved)) {
|
|
2924
|
+
if (filter && !globMatch(path, filter)) continue;
|
|
2925
|
+
if (!filter && ![
|
|
2926
|
+
"transition",
|
|
2927
|
+
"duration",
|
|
2928
|
+
"cubicBezier"
|
|
2929
|
+
].includes(token.$type ?? "")) continue;
|
|
2930
|
+
const kind = token.$type;
|
|
2931
|
+
if (!kind) continue;
|
|
2932
|
+
const spec = resolveMotionSpec(token, resolved);
|
|
2933
|
+
if (!spec) continue;
|
|
2934
|
+
collected.push({
|
|
2935
|
+
path,
|
|
2936
|
+
cssVar: makeCssVar(path, cssVarPrefix),
|
|
2937
|
+
durationMs: spec.durationMs,
|
|
2938
|
+
easing: spec.easing,
|
|
2939
|
+
kind
|
|
2940
|
+
});
|
|
2699
2941
|
}
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
}
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
cancelAnimationFrame(id);
|
|
2714
|
-
window.clearInterval(loop);
|
|
2715
|
-
};
|
|
2716
|
-
}, [reduced]);
|
|
2717
|
-
if (reduced) return /* @__PURE__ */ jsx("div", {
|
|
2718
|
-
className: "sb-token-detail__reduced-motion",
|
|
2719
|
-
children: "Animation suppressed by `prefers-reduced-motion: reduce`."
|
|
2720
|
-
});
|
|
2721
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2722
|
-
className: "sb-token-detail__motion-track",
|
|
2942
|
+
collected.sort((a, b) => {
|
|
2943
|
+
if (a.kind !== b.kind) return a.kind.localeCompare(b.kind);
|
|
2944
|
+
return a.path.localeCompare(b.path, void 0, { numeric: true });
|
|
2945
|
+
});
|
|
2946
|
+
return collected;
|
|
2947
|
+
}, [
|
|
2948
|
+
resolved,
|
|
2949
|
+
filter,
|
|
2950
|
+
cssVarPrefix
|
|
2951
|
+
]);
|
|
2952
|
+
const captionText = caption ?? `${rows.length} motion token${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
2953
|
+
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
2954
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2723
2955
|
children: /* @__PURE__ */ jsx("div", {
|
|
2724
|
-
className: "sb-
|
|
2725
|
-
|
|
2726
|
-
left: phase === 1 ? "calc(100% - 28px)" : "4px",
|
|
2727
|
-
transition
|
|
2728
|
-
},
|
|
2729
|
-
"aria-hidden": true
|
|
2956
|
+
className: "sb-block__empty",
|
|
2957
|
+
children: "No motion tokens match this filter."
|
|
2730
2958
|
})
|
|
2731
2959
|
});
|
|
2732
|
-
}
|
|
2733
|
-
//#endregion
|
|
2734
|
-
//#region src/token-detail/ConsumerOutput.tsx
|
|
2735
|
-
function ConsumerOutput({ path }) {
|
|
2736
|
-
const { token, cssVar, activeAxes } = useTokenDetailData(path);
|
|
2737
|
-
if (!token) return null;
|
|
2738
|
-
const tupleLabel = Object.entries(activeAxes).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
2739
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2740
|
-
/* @__PURE__ */ jsx("div", {
|
|
2741
|
-
className: "sb-token-detail__section-header",
|
|
2742
|
-
children: "Consumer output"
|
|
2743
|
-
}),
|
|
2744
|
-
tupleLabel && /* @__PURE__ */ jsxs("div", {
|
|
2745
|
-
className: "sb-token-detail__tuple-indicator",
|
|
2746
|
-
children: ["Active tuple: ", /* @__PURE__ */ jsx("strong", { children: tupleLabel })]
|
|
2747
|
-
}),
|
|
2748
|
-
/* @__PURE__ */ jsx(OutputRow, {
|
|
2749
|
-
label: "Path",
|
|
2750
|
-
value: path,
|
|
2751
|
-
testId: "consumer-output-path"
|
|
2752
|
-
}),
|
|
2753
|
-
/* @__PURE__ */ jsx(OutputRow, {
|
|
2754
|
-
label: "CSS",
|
|
2755
|
-
value: cssVar,
|
|
2756
|
-
testId: "consumer-output-css"
|
|
2757
|
-
})
|
|
2758
|
-
] });
|
|
2759
|
-
}
|
|
2760
|
-
function OutputRow({ label, value, testId }) {
|
|
2761
2960
|
return /* @__PURE__ */ jsxs("div", {
|
|
2762
|
-
|
|
2961
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
2763
2962
|
children: [
|
|
2764
|
-
/* @__PURE__ */ jsx("
|
|
2765
|
-
className: "sb-
|
|
2766
|
-
children:
|
|
2963
|
+
/* @__PURE__ */ jsx("div", {
|
|
2964
|
+
className: "sb-block__caption",
|
|
2965
|
+
children: captionText
|
|
2767
2966
|
}),
|
|
2768
|
-
/* @__PURE__ */
|
|
2769
|
-
className: "sb-
|
|
2770
|
-
|
|
2771
|
-
|
|
2967
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2968
|
+
className: "sb-motion-preview__controls",
|
|
2969
|
+
children: [
|
|
2970
|
+
/* @__PURE__ */ jsx("span", {
|
|
2971
|
+
className: "sb-motion-preview__control-label",
|
|
2972
|
+
children: "Speed"
|
|
2973
|
+
}),
|
|
2974
|
+
SPEEDS.map((s) => /* @__PURE__ */ jsxs("button", {
|
|
2975
|
+
type: "button",
|
|
2976
|
+
className: cx("sb-motion-preview__speed-btn", { "sb-motion-preview__speed-btn--active": s === speed }),
|
|
2977
|
+
onClick: () => setSpeed(s),
|
|
2978
|
+
children: [s, "×"]
|
|
2979
|
+
}, s)),
|
|
2980
|
+
/* @__PURE__ */ jsx("button", {
|
|
2981
|
+
type: "button",
|
|
2982
|
+
className: "sb-motion-preview__replay-btn",
|
|
2983
|
+
onClick: () => setRun((n) => n + 1),
|
|
2984
|
+
disabled: reducedMotion,
|
|
2985
|
+
title: reducedMotion ? "Disabled by prefers-reduced-motion" : "Replay all",
|
|
2986
|
+
children: "↻ Replay"
|
|
2987
|
+
})
|
|
2988
|
+
]
|
|
2772
2989
|
}),
|
|
2773
|
-
/* @__PURE__ */
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2990
|
+
rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
2991
|
+
className: "sb-motion-preview__row",
|
|
2992
|
+
children: [
|
|
2993
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2994
|
+
className: "sb-motion-preview__meta",
|
|
2995
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
2996
|
+
className: "sb-motion-preview__path",
|
|
2997
|
+
children: row.path
|
|
2998
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
2999
|
+
className: "sb-motion-preview__specs",
|
|
3000
|
+
children: formatSpec(row)
|
|
3001
|
+
})]
|
|
3002
|
+
}),
|
|
3003
|
+
/* @__PURE__ */ jsx(MotionSample, {
|
|
3004
|
+
path: row.path,
|
|
3005
|
+
speed,
|
|
3006
|
+
runKey: run
|
|
3007
|
+
}),
|
|
3008
|
+
/* @__PURE__ */ jsx("span", {
|
|
3009
|
+
className: "sb-motion-preview__css-var",
|
|
3010
|
+
children: row.cssVar
|
|
3011
|
+
})
|
|
3012
|
+
]
|
|
3013
|
+
}, row.path))
|
|
2777
3014
|
]
|
|
2778
3015
|
});
|
|
2779
3016
|
}
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
3017
|
+
//#endregion
|
|
3018
|
+
//#region src/provider.tsx
|
|
3019
|
+
/**
|
|
3020
|
+
* Wraps a tree of blocks with the token data they need to render.
|
|
3021
|
+
*
|
|
3022
|
+
* The Storybook addon's preview decorator mounts this automatically, so
|
|
3023
|
+
* story/MDX authors typically never see it. Outside Storybook — unit
|
|
3024
|
+
* tests, custom React apps, non-Storybook doc sites — consumers construct
|
|
3025
|
+
* a {@link ProjectSnapshot} (often imported from a JSON file) and wrap
|
|
3026
|
+
* their blocks in this provider.
|
|
3027
|
+
*/
|
|
3028
|
+
function SwatchbookProvider({ value, children }) {
|
|
3029
|
+
return /* @__PURE__ */ jsx(SwatchbookContext.Provider, {
|
|
3030
|
+
value,
|
|
3031
|
+
children
|
|
2794
3032
|
});
|
|
2795
3033
|
}
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
}
|
|
3034
|
+
/**
|
|
3035
|
+
* Read the current {@link ProjectSnapshot}. Throws if called outside a
|
|
3036
|
+
* {@link SwatchbookProvider}; blocks that need to fall back to the
|
|
3037
|
+
* virtual module go through the internal `useProject()` hook instead.
|
|
3038
|
+
*/
|
|
3039
|
+
function useSwatchbookData() {
|
|
3040
|
+
const value = useOptionalSwatchbookData();
|
|
3041
|
+
if (!value) throw new Error("[swatchbook-blocks] useSwatchbookData() called outside <SwatchbookProvider>. Wrap your tree in <SwatchbookProvider value={snapshot}> or render inside a Storybook story.");
|
|
3042
|
+
return value;
|
|
2804
3043
|
}
|
|
2805
3044
|
//#endregion
|
|
2806
|
-
//#region src/
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
3045
|
+
//#region src/shadow-preview/ShadowSample.tsx
|
|
3046
|
+
const sampleStyle = {
|
|
3047
|
+
width: 120,
|
|
3048
|
+
height: 56,
|
|
3049
|
+
background: SURFACE_RAISED,
|
|
3050
|
+
border: BORDER_FAINT,
|
|
3051
|
+
borderRadius: 6
|
|
3052
|
+
};
|
|
3053
|
+
function ShadowSample({ path }) {
|
|
3054
|
+
const { cssVarPrefix } = useProject();
|
|
3055
|
+
const cssVar = makeCssVar(path, cssVarPrefix);
|
|
3056
|
+
return /* @__PURE__ */ jsx("div", {
|
|
3057
|
+
style: {
|
|
3058
|
+
...sampleStyle,
|
|
3059
|
+
boxShadow: cssVar
|
|
3060
|
+
},
|
|
3061
|
+
"aria-hidden": true
|
|
2818
3062
|
});
|
|
2819
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2820
|
-
/* @__PURE__ */ jsx("h3", {
|
|
2821
|
-
className: "sb-token-detail__heading",
|
|
2822
|
-
children: heading ?? path
|
|
2823
|
-
}),
|
|
2824
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2825
|
-
className: "sb-token-detail__subline",
|
|
2826
|
-
children: [token.$type && /* @__PURE__ */ jsx("span", {
|
|
2827
|
-
className: "sb-token-detail__type-pill",
|
|
2828
|
-
children: token.$type
|
|
2829
|
-
}), /* @__PURE__ */ jsx("span", { children: cssVar })]
|
|
2830
|
-
}),
|
|
2831
|
-
token.$description && /* @__PURE__ */ jsx("p", {
|
|
2832
|
-
className: "sb-token-detail__description",
|
|
2833
|
-
children: token.$description
|
|
2834
|
-
})
|
|
2835
|
-
] });
|
|
2836
3063
|
}
|
|
2837
3064
|
//#endregion
|
|
2838
|
-
//#region src/
|
|
2839
|
-
function
|
|
2840
|
-
|
|
2841
|
-
if (
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
3065
|
+
//#region src/ShadowPreview.tsx
|
|
3066
|
+
function formatDimension(raw) {
|
|
3067
|
+
if (raw == null) return "—";
|
|
3068
|
+
if (typeof raw === "number") return String(raw);
|
|
3069
|
+
if (typeof raw === "string") return raw;
|
|
3070
|
+
if (typeof raw === "object") {
|
|
3071
|
+
const v = raw;
|
|
3072
|
+
if (typeof v.value === "number" && typeof v.unit === "string") return `${v.value}${v.unit}`;
|
|
3073
|
+
}
|
|
3074
|
+
return JSON.stringify(raw);
|
|
3075
|
+
}
|
|
3076
|
+
function formatSubColor(raw, format) {
|
|
3077
|
+
if (raw == null) return "—";
|
|
3078
|
+
return formatColor(raw, format).value;
|
|
3079
|
+
}
|
|
3080
|
+
function asLayers(raw) {
|
|
3081
|
+
if (Array.isArray(raw)) return raw;
|
|
3082
|
+
if (raw && typeof raw === "object") return [raw];
|
|
3083
|
+
return [];
|
|
2849
3084
|
}
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
3085
|
+
function layerKey(path, layer, fallback) {
|
|
3086
|
+
return `${path}|${`${formatDimension(layer.offsetX)},${formatDimension(layer.offsetY)}`}|${formatDimension(layer.blur)}|${formatDimension(layer.spread)}|${fallback}`;
|
|
3087
|
+
}
|
|
3088
|
+
function ShadowPreview({ filter, caption, sortBy = "path", sortDir = "asc" }) {
|
|
3089
|
+
const { resolved, activeTheme, cssVarPrefix } = useProject();
|
|
2854
3090
|
const colorFormat = useColorFormat();
|
|
2855
|
-
const
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
3091
|
+
const rows = useMemo(() => {
|
|
3092
|
+
return sortTokens(Object.entries(resolved).filter(([path, token]) => {
|
|
3093
|
+
if (token.$type !== "shadow") return false;
|
|
3094
|
+
return globMatch(path, filter);
|
|
3095
|
+
}), {
|
|
3096
|
+
by: sortBy,
|
|
3097
|
+
dir: sortDir
|
|
3098
|
+
}).map(([path, token]) => ({
|
|
3099
|
+
path,
|
|
3100
|
+
cssVar: makeCssVar(path, cssVarPrefix),
|
|
3101
|
+
layers: asLayers(token.$value)
|
|
3102
|
+
}));
|
|
3103
|
+
}, [
|
|
3104
|
+
resolved,
|
|
3105
|
+
filter,
|
|
3106
|
+
cssVarPrefix,
|
|
3107
|
+
sortBy,
|
|
3108
|
+
sortDir
|
|
3109
|
+
]);
|
|
3110
|
+
const captionText = caption ?? `${rows.length} shadow${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
3111
|
+
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
3112
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
3113
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
3114
|
+
className: "sb-block__empty",
|
|
3115
|
+
children: "No shadow tokens match this filter."
|
|
3116
|
+
})
|
|
3117
|
+
});
|
|
3118
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3119
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
3120
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
3121
|
+
className: "sb-block__caption",
|
|
3122
|
+
children: captionText
|
|
3123
|
+
}), rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
3124
|
+
className: "sb-shadow-preview__row",
|
|
2861
3125
|
children: [
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
3126
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3127
|
+
className: "sb-shadow-preview__meta",
|
|
3128
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
3129
|
+
className: "sb-shadow-preview__path",
|
|
3130
|
+
children: row.path
|
|
3131
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
3132
|
+
className: "sb-shadow-preview__css-var",
|
|
3133
|
+
children: row.cssVar
|
|
3134
|
+
})]
|
|
3135
|
+
}),
|
|
3136
|
+
/* @__PURE__ */ jsx("div", {
|
|
3137
|
+
className: "sb-shadow-preview__sample-cell",
|
|
3138
|
+
children: /* @__PURE__ */ jsx(ShadowSample, { path: row.path })
|
|
3139
|
+
}),
|
|
3140
|
+
/* @__PURE__ */ jsx("div", {
|
|
3141
|
+
className: "sb-shadow-preview__breakdown",
|
|
3142
|
+
children: row.layers.length === 1 ? renderLayer(row.layers[0], colorFormat) : row.layers.map((layer, i) => /* @__PURE__ */ jsx(Layer, {
|
|
3143
|
+
layer,
|
|
3144
|
+
index: i,
|
|
3145
|
+
total: row.layers.length,
|
|
3146
|
+
colorFormat
|
|
3147
|
+
}, layerKey(row.path, layer, i)))
|
|
3148
|
+
})
|
|
2867
3149
|
]
|
|
2868
|
-
})
|
|
3150
|
+
}, row.path))]
|
|
2869
3151
|
});
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
const
|
|
3152
|
+
}
|
|
3153
|
+
function renderLayer(layer, format) {
|
|
3154
|
+
if (!layer) return [];
|
|
3155
|
+
const entries = [
|
|
3156
|
+
["offset", `${formatDimension(layer.offsetX)} ${formatDimension(layer.offsetY)}`],
|
|
3157
|
+
["blur", formatDimension(layer.blur)],
|
|
3158
|
+
["spread", formatDimension(layer.spread)],
|
|
3159
|
+
["color", formatSubColor(layer.color, format)]
|
|
3160
|
+
];
|
|
3161
|
+
if (layer.inset) entries.push(["inset", String(layer.inset)]);
|
|
3162
|
+
return entries.flatMap(([k, v]) => [/* @__PURE__ */ jsx("span", {
|
|
3163
|
+
className: "sb-shadow-preview__breakdown-key",
|
|
3164
|
+
children: k
|
|
3165
|
+
}, `k-${k}`), /* @__PURE__ */ jsx("span", { children: v }, `v-${k}`)]);
|
|
3166
|
+
}
|
|
3167
|
+
function Layer({ layer, index, total, colorFormat }) {
|
|
2874
3168
|
return /* @__PURE__ */ jsxs("div", {
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2889
|
-
className: "sb-token-detail__chain",
|
|
2890
|
-
children: [
|
|
2891
|
-
isColor && /* @__PURE__ */ jsx("span", {
|
|
2892
|
-
className: "sb-token-detail__swatch",
|
|
2893
|
-
style: { background: cssVar },
|
|
2894
|
-
"aria-hidden": true
|
|
2895
|
-
}),
|
|
2896
|
-
/* @__PURE__ */ jsx("span", { children: value }),
|
|
2897
|
-
outOfGamut && /* @__PURE__ */ jsx("span", {
|
|
2898
|
-
title: "Out of sRGB gamut for this format",
|
|
2899
|
-
"aria-label": "out of gamut",
|
|
2900
|
-
style: { marginLeft: 6 },
|
|
2901
|
-
children: "⚠"
|
|
2902
|
-
})
|
|
2903
|
-
]
|
|
2904
|
-
}),
|
|
2905
|
-
/* @__PURE__ */ jsx(AliasChain, { path }),
|
|
2906
|
-
/* @__PURE__ */ jsx(AliasedBy, { path }),
|
|
2907
|
-
/* @__PURE__ */ jsx(TokenUsageSnippet, { path }),
|
|
2908
|
-
/* @__PURE__ */ jsx(ConsumerOutput, { path }),
|
|
2909
|
-
/* @__PURE__ */ jsx(AxisVariance, { path })
|
|
2910
|
-
]
|
|
3169
|
+
className: "sb-shadow-preview__layer",
|
|
3170
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
3171
|
+
className: "sb-shadow-preview__layer-header",
|
|
3172
|
+
children: [
|
|
3173
|
+
"layer ",
|
|
3174
|
+
index + 1,
|
|
3175
|
+
" of ",
|
|
3176
|
+
total
|
|
3177
|
+
]
|
|
3178
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
3179
|
+
className: cx("sb-shadow-preview__breakdown", "sb-shadow-preview__layer-breakdown"),
|
|
3180
|
+
children: renderLayer(layer, colorFormat)
|
|
3181
|
+
})]
|
|
2911
3182
|
});
|
|
2912
3183
|
}
|
|
2913
3184
|
//#endregion
|
|
2914
|
-
//#region src/
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
"
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
3185
|
+
//#region src/StrokeStyleSample.tsx
|
|
3186
|
+
const STRING_STYLES = new Set([
|
|
3187
|
+
"solid",
|
|
3188
|
+
"dashed",
|
|
3189
|
+
"dotted",
|
|
3190
|
+
"double",
|
|
3191
|
+
"groove",
|
|
3192
|
+
"ridge",
|
|
3193
|
+
"outset",
|
|
3194
|
+
"inset"
|
|
3195
|
+
]);
|
|
3196
|
+
function extractCssStyle(value) {
|
|
3197
|
+
if (typeof value === "string" && STRING_STYLES.has(value)) return value;
|
|
3198
|
+
return null;
|
|
3199
|
+
}
|
|
3200
|
+
function StrokeStyleSample({ filter, caption, sortBy = "path", sortDir = "asc" }) {
|
|
3201
|
+
const { resolved, activeTheme, cssVarPrefix } = useProject();
|
|
3202
|
+
const rows = useMemo(() => {
|
|
3203
|
+
return sortTokens(Object.entries(resolved).filter(([path, token]) => {
|
|
3204
|
+
if (token.$type !== "strokeStyle") return false;
|
|
3205
|
+
return globMatch(path, filter);
|
|
3206
|
+
}), {
|
|
3207
|
+
by: sortBy,
|
|
3208
|
+
dir: sortDir
|
|
3209
|
+
}).map(([path, token]) => ({
|
|
3210
|
+
path,
|
|
3211
|
+
cssVar: makeCssVar(path, cssVarPrefix),
|
|
3212
|
+
displayValue: formatTokenValue(token.$value, token.$type, "raw"),
|
|
3213
|
+
cssStyle: extractCssStyle(token.$value)
|
|
3214
|
+
}));
|
|
3215
|
+
}, [
|
|
3216
|
+
resolved,
|
|
3217
|
+
filter,
|
|
3218
|
+
cssVarPrefix,
|
|
3219
|
+
sortBy,
|
|
3220
|
+
sortDir
|
|
3221
|
+
]);
|
|
3222
|
+
const captionText = caption ?? `${rows.length} strokeStyle token${rows.length === 1 ? "" : "s"}${filter && filter !== "strokeStyle" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
|
|
3223
|
+
if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
3224
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
3225
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
3226
|
+
className: "sb-block__empty",
|
|
3227
|
+
children: "No strokeStyle tokens match this filter."
|
|
2942
3228
|
})
|
|
2943
3229
|
});
|
|
3230
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3231
|
+
...themeAttrs(cssVarPrefix, activeTheme),
|
|
3232
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
3233
|
+
className: "sb-block__caption",
|
|
3234
|
+
children: captionText
|
|
3235
|
+
}), rows.map((row) => /* @__PURE__ */ jsxs("div", {
|
|
3236
|
+
className: "sb-stroke-style-sample__row",
|
|
3237
|
+
children: [
|
|
3238
|
+
/* @__PURE__ */ jsxs("div", {
|
|
3239
|
+
className: "sb-stroke-style-sample__meta",
|
|
3240
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
3241
|
+
className: "sb-stroke-style-sample__path",
|
|
3242
|
+
children: row.path
|
|
3243
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
3244
|
+
className: "sb-stroke-style-sample__value",
|
|
3245
|
+
children: row.displayValue
|
|
3246
|
+
})]
|
|
3247
|
+
}),
|
|
3248
|
+
row.cssStyle ? /* @__PURE__ */ jsx("div", {
|
|
3249
|
+
className: "sb-stroke-style-sample__line",
|
|
3250
|
+
style: { borderTopStyle: row.cssStyle },
|
|
3251
|
+
"aria-hidden": true
|
|
3252
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
3253
|
+
className: "sb-stroke-style-sample__object-fallback",
|
|
3254
|
+
children: "Object-form (dashArray + lineCap) — no pure CSS `border-style` equivalent."
|
|
3255
|
+
}),
|
|
3256
|
+
/* @__PURE__ */ jsx("span", {
|
|
3257
|
+
className: "sb-stroke-style-sample__css-var",
|
|
3258
|
+
children: row.cssVar
|
|
3259
|
+
})
|
|
3260
|
+
]
|
|
3261
|
+
}, row.path))]
|
|
3262
|
+
});
|
|
2944
3263
|
}
|
|
2945
3264
|
//#endregion
|
|
2946
3265
|
//#region src/TokenNavigator.tsx
|
|
@@ -3015,18 +3334,21 @@ function countLeaves(node) {
|
|
|
3015
3334
|
for (const c of node.children) n += countLeaves(c);
|
|
3016
3335
|
return n;
|
|
3017
3336
|
}
|
|
3337
|
+
function collectLeafPaths(nodes, out) {
|
|
3338
|
+
for (const node of nodes) if (node.kind === "leaf") out.push(node.path);
|
|
3339
|
+
else collectLeafPaths(node.children, out);
|
|
3340
|
+
}
|
|
3018
3341
|
/**
|
|
3019
|
-
* Return a pruned copy of the tree
|
|
3020
|
-
* matches
|
|
3021
|
-
*
|
|
3022
|
-
* callers can force those groups open.
|
|
3342
|
+
* Return a pruned copy of the tree keeping only leaves whose path is in
|
|
3343
|
+
* `matches`, plus the groups on the way to them. Every surviving group's
|
|
3344
|
+
* path is added to `expandOut` so callers can force those groups open.
|
|
3023
3345
|
*/
|
|
3024
|
-
function
|
|
3346
|
+
function pruneTreeForMatches(nodes, matches, expandOut) {
|
|
3025
3347
|
const out = [];
|
|
3026
3348
|
for (const node of nodes) if (node.kind === "leaf") {
|
|
3027
|
-
if (node.path
|
|
3349
|
+
if (matches.has(node.path)) out.push(node);
|
|
3028
3350
|
} else {
|
|
3029
|
-
const children =
|
|
3351
|
+
const children = pruneTreeForMatches(node.children, matches, expandOut);
|
|
3030
3352
|
if (children.length > 0) {
|
|
3031
3353
|
expandOut.add(node.path);
|
|
3032
3354
|
out.push({
|
|
@@ -3064,10 +3386,12 @@ function TokenNavigator({ root, type, initiallyExpanded = 1, searchable = true,
|
|
|
3064
3386
|
visibleTree: tree,
|
|
3065
3387
|
searchExpanded: null
|
|
3066
3388
|
};
|
|
3067
|
-
const
|
|
3389
|
+
const leafPaths = [];
|
|
3390
|
+
collectLeafPaths(tree, leafPaths);
|
|
3391
|
+
const matches = new Set(fuzzyFilter(leafPaths, query, (p) => p));
|
|
3068
3392
|
const expandOut = /* @__PURE__ */ new Set();
|
|
3069
3393
|
return {
|
|
3070
|
-
visibleTree:
|
|
3394
|
+
visibleTree: matches.size === 0 ? [] : pruneTreeForMatches(tree, matches, expandOut),
|
|
3071
3395
|
searchExpanded: expandOut
|
|
3072
3396
|
};
|
|
3073
3397
|
}, [
|
|
@@ -3340,8 +3664,7 @@ function TokenTable({ filter, type, caption, sortBy = "path", sortDir = "asc", s
|
|
|
3340
3664
|
]);
|
|
3341
3665
|
const visibleRows = useMemo(() => {
|
|
3342
3666
|
if (!searchable || query.trim() === "") return rows;
|
|
3343
|
-
|
|
3344
|
-
return rows.filter((row) => row.path.toLowerCase().includes(needle) || row.type.toLowerCase().includes(needle) || row.value.toLowerCase().includes(needle));
|
|
3667
|
+
return fuzzyFilter(rows, query, (row) => `${row.path} ${row.type} ${row.value}`);
|
|
3345
3668
|
}, [
|
|
3346
3669
|
rows,
|
|
3347
3670
|
query,
|
|
@@ -3371,7 +3694,7 @@ function TokenTable({ filter, type, caption, sortBy = "path", sortDir = "asc", s
|
|
|
3371
3694
|
placeholder: "Search tokens…",
|
|
3372
3695
|
value: query,
|
|
3373
3696
|
onChange: (e) => setQuery(e.target.value),
|
|
3374
|
-
"aria-label": "
|
|
3697
|
+
"aria-label": "Fuzzy-search tokens by path, type, or value",
|
|
3375
3698
|
"data-testid": "token-table-search"
|
|
3376
3699
|
})
|
|
3377
3700
|
}),
|
|
@@ -3438,6 +3761,17 @@ function TokenTable({ filter, type, caption, sortBy = "path", sortDir = "asc", s
|
|
|
3438
3761
|
"aria-label": "out of gamut",
|
|
3439
3762
|
className: "sb-token-table__gamut-warn",
|
|
3440
3763
|
children: "⚠"
|
|
3764
|
+
}),
|
|
3765
|
+
/* @__PURE__ */ jsx("span", {
|
|
3766
|
+
className: "sb-token-table__copy-wrap",
|
|
3767
|
+
onClick: (e) => e.stopPropagation(),
|
|
3768
|
+
onKeyDown: (e) => e.stopPropagation(),
|
|
3769
|
+
role: "presentation",
|
|
3770
|
+
children: /* @__PURE__ */ jsx(CopyButton$1, {
|
|
3771
|
+
value: row.value,
|
|
3772
|
+
label: `Copy value ${row.value}`,
|
|
3773
|
+
className: "sb-token-table__copy"
|
|
3774
|
+
})
|
|
3441
3775
|
})
|
|
3442
3776
|
]
|
|
3443
3777
|
})
|
|
@@ -3545,6 +3879,6 @@ function TypographyScale({ filter, sample = "The quick brown fox jumps over the
|
|
|
3545
3879
|
});
|
|
3546
3880
|
}
|
|
3547
3881
|
//#endregion
|
|
3548
|
-
export { AliasChain, AliasedBy, AxesContext, AxisVariance, BorderPreview, BorderSample, COLOR_FORMATS, ColorFormatContext, ColorPalette, CompositeBreakdown, CompositePreview, ConsumerOutput, Diagnostics, DimensionBar, DimensionScale, FontFamilySample, FontWeightScale, GradientPalette, MotionPreview, MotionSample, ShadowPreview, ShadowSample, StrokeStyleSample, SwatchbookContext, SwatchbookProvider, ThemeContext, TokenDetail, TokenHeader, TokenNavigator, TokenTable, TokenUsageSnippet, TypographyScale, formatColor, useActiveAxes, useActiveTheme, useColorFormat, useOptionalSwatchbookData, useSwatchbookData };
|
|
3882
|
+
export { AliasChain, AliasedBy, AxesContext, AxisVariance, BorderPreview, BorderSample, COLOR_FORMATS, ColorFormatContext, ColorPalette, ColorTable, CompositeBreakdown, CompositePreview, ConsumerOutput, Diagnostics, DimensionBar, DimensionScale, FontFamilySample, FontWeightScale, GradientPalette, MotionPreview, MotionSample, ShadowPreview, ShadowSample, StrokeStyleSample, SwatchbookContext, SwatchbookProvider, ThemeContext, TokenDetail, TokenHeader, TokenNavigator, TokenTable, TokenUsageSnippet, TypographyScale, formatColor, useActiveAxes, useActiveTheme, useColorFormat, useOptionalSwatchbookData, useSwatchbookData };
|
|
3549
3883
|
|
|
3550
3884
|
//# sourceMappingURL=index.mjs.map
|