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