@unpunnyfuns/swatchbook-blocks 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Published as `@unpunnyfuns/swatchbook-blocks`. Storybook MDX doc blocks for DTCG design tokens. React components for rendering token documentation inside `.mdx` pages or regular stories. Self-mount the addon's CSS and react to axis changes from the toolbar; work inside the docs container even though story decorators don't.
4
4
 
5
- > **Documentation:** [unpunnyfuns.github.io/swatchbook](https://unpunnyfuns.github.io/swatchbook/). Token parsing powered by [Terrazzo](https://terrazzo.app/) by [Drew Powers](https://github.com/drwpow) via `@unpunnyfuns/swatchbook-core`.
5
+ > **Documentation:** [unpunnyfuns.github.io/swatchbook](https://unpunnyfuns.github.io/swatchbook/). Token parsing powered by [Terrazzo](https://terrazzo.app/) by the [Terrazzo team](https://github.com/terrazzoapp) via `@unpunnyfuns/swatchbook-core`.
6
6
 
7
7
  ## Install
8
8
 
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _$react from "react";
2
2
  import { ReactElement, ReactNode } from "react";
3
3
 
4
- //#region src/internal/format-color.d.ts
4
+ //#region src/format-color.d.ts
5
5
  /**
6
6
  * Color display formats understood by {@link formatColor}.
7
7
  *
package/dist/index.mjs CHANGED
@@ -3,7 +3,7 @@ import { createContext, useCallback, useContext, useEffect, useMemo, useState, u
3
3
  import { addons } from "storybook/preview-api";
4
4
  import { axes, css, cssVarPrefix, defaultTheme, themes, themesResolved } from "virtual:swatchbook/tokens";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
- //#region src/internal/format-color.ts
6
+ //#region src/format-color.ts
7
7
  const COLOR_FORMATS = [
8
8
  "hex",
9
9
  "rgb",
@@ -450,6 +450,25 @@ const emptyStyle = {
450
450
  opacity: .6
451
451
  };
452
452
  //#endregion
453
+ //#region src/internal/data-attr.ts
454
+ /**
455
+ * Produce a prefixed `data-*` attribute name when `prefix` is set, bare
456
+ * `data-<key>` otherwise. Mirrors `dataAttr` in `@unpunnyfuns/swatchbook-core`
457
+ * so block wrappers and emitted-CSS selectors stay in lockstep without
458
+ * blocks taking a runtime dep on core.
459
+ */
460
+ function dataAttr(prefix, key) {
461
+ return prefix ? `data-${prefix}-${key}` : `data-${key}`;
462
+ }
463
+ /**
464
+ * Spread helper for the common `<div data-<prefix>-theme="…">` block
465
+ * wrapper. Returns an object keyed on the prefixed attribute name so the
466
+ * call site stays readable: `<div {...themeAttrs(prefix, theme)} />`.
467
+ */
468
+ function themeAttrs(prefix, themeName) {
469
+ return { [dataAttr(prefix, "theme")]: themeName };
470
+ }
471
+ //#endregion
453
472
  //#region src/BorderPreview.tsx
454
473
  const styles$14 = {
455
474
  wrapper: surfaceStyle,
@@ -541,7 +560,7 @@ function BorderPreview({ filter = "border", caption }) {
541
560
  ]);
542
561
  const captionText = caption ?? `${rows.length} border${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
543
562
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
544
- "data-theme": activeTheme,
563
+ ...themeAttrs(cssVarPrefix, activeTheme),
545
564
  style: styles$14.wrapper,
546
565
  children: /* @__PURE__ */ jsx("div", {
547
566
  style: styles$14.empty,
@@ -549,7 +568,7 @@ function BorderPreview({ filter = "border", caption }) {
549
568
  })
550
569
  });
551
570
  return /* @__PURE__ */ jsxs("div", {
552
- "data-theme": activeTheme,
571
+ ...themeAttrs(cssVarPrefix, activeTheme),
553
572
  style: styles$14.wrapper,
554
573
  children: [/* @__PURE__ */ jsx("div", {
555
574
  style: styles$14.caption,
@@ -701,7 +720,7 @@ function ColorPalette({ filter = "color", groupBy, caption }) {
701
720
  const totalCount = groups.reduce((acc, [, swatches]) => acc + swatches.length, 0);
702
721
  const captionText = caption ?? `${totalCount} color${totalCount === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
703
722
  if (totalCount === 0) return /* @__PURE__ */ jsx("div", {
704
- "data-theme": activeTheme,
723
+ ...themeAttrs(cssVarPrefix, activeTheme),
705
724
  style: styles$13.wrapper,
706
725
  children: /* @__PURE__ */ jsx("div", {
707
726
  style: styles$13.empty,
@@ -709,7 +728,7 @@ function ColorPalette({ filter = "color", groupBy, caption }) {
709
728
  })
710
729
  });
711
730
  return /* @__PURE__ */ jsxs("div", {
712
- "data-theme": activeTheme,
731
+ ...themeAttrs(cssVarPrefix, activeTheme),
713
732
  style: styles$13.wrapper,
714
733
  children: [/* @__PURE__ */ jsx("div", {
715
734
  style: styles$13.caption,
@@ -914,7 +933,7 @@ function DimensionScale({ filter = "dimension", kind = "length", caption }) {
914
933
  ]);
915
934
  const captionText = caption ?? `${rows.length} dimension${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
916
935
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
917
- "data-theme": activeTheme,
936
+ ...themeAttrs(cssVarPrefix, activeTheme),
918
937
  style: styles$11.wrapper,
919
938
  children: /* @__PURE__ */ jsx("div", {
920
939
  style: styles$11.empty,
@@ -922,7 +941,7 @@ function DimensionScale({ filter = "dimension", kind = "length", caption }) {
922
941
  })
923
942
  });
924
943
  return /* @__PURE__ */ jsxs("div", {
925
- "data-theme": activeTheme,
944
+ ...themeAttrs(cssVarPrefix, activeTheme),
926
945
  style: styles$11.wrapper,
927
946
  children: [/* @__PURE__ */ jsx("div", {
928
947
  style: styles$11.caption,
@@ -1027,7 +1046,7 @@ function FontFamilySample({ filter = "fontFamily", sample = "The quick brown fox
1027
1046
  ]);
1028
1047
  const captionText = caption ?? `${rows.length} fontFamily token${rows.length === 1 ? "" : "s"}${filter && filter !== "fontFamily" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
1029
1048
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
1030
- "data-theme": activeTheme,
1049
+ ...themeAttrs(cssVarPrefix, activeTheme),
1031
1050
  style: styles$10.wrapper,
1032
1051
  children: /* @__PURE__ */ jsx("div", {
1033
1052
  style: styles$10.empty,
@@ -1035,7 +1054,7 @@ function FontFamilySample({ filter = "fontFamily", sample = "The quick brown fox
1035
1054
  })
1036
1055
  });
1037
1056
  return /* @__PURE__ */ jsxs("div", {
1038
- "data-theme": activeTheme,
1057
+ ...themeAttrs(cssVarPrefix, activeTheme),
1039
1058
  style: styles$10.wrapper,
1040
1059
  children: [/* @__PURE__ */ jsx("div", {
1041
1060
  style: styles$10.caption,
@@ -1144,7 +1163,7 @@ function FontWeightScale({ filter = "fontWeight", sample = "Aa", caption }) {
1144
1163
  ]);
1145
1164
  const captionText = caption ?? `${rows.length} fontWeight token${rows.length === 1 ? "" : "s"}${filter && filter !== "fontWeight" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
1146
1165
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
1147
- "data-theme": activeTheme,
1166
+ ...themeAttrs(cssVarPrefix, activeTheme),
1148
1167
  style: styles$9.wrapper,
1149
1168
  children: /* @__PURE__ */ jsx("div", {
1150
1169
  style: styles$9.empty,
@@ -1152,7 +1171,7 @@ function FontWeightScale({ filter = "fontWeight", sample = "Aa", caption }) {
1152
1171
  })
1153
1172
  });
1154
1173
  return /* @__PURE__ */ jsxs("div", {
1155
- "data-theme": activeTheme,
1174
+ ...themeAttrs(cssVarPrefix, activeTheme),
1156
1175
  style: styles$9.wrapper,
1157
1176
  children: [/* @__PURE__ */ jsx("div", {
1158
1177
  style: styles$9.caption,
@@ -1281,7 +1300,7 @@ function GradientPalette({ filter = "gradient", caption }) {
1281
1300
  ]);
1282
1301
  const captionText = caption ?? `${rows.length} gradient${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
1283
1302
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
1284
- "data-theme": activeTheme,
1303
+ ...themeAttrs(cssVarPrefix, activeTheme),
1285
1304
  style: styles$8.wrapper,
1286
1305
  children: /* @__PURE__ */ jsx("div", {
1287
1306
  style: styles$8.empty,
@@ -1289,7 +1308,7 @@ function GradientPalette({ filter = "gradient", caption }) {
1289
1308
  })
1290
1309
  });
1291
1310
  return /* @__PURE__ */ jsxs("div", {
1292
- "data-theme": activeTheme,
1311
+ ...themeAttrs(cssVarPrefix, activeTheme),
1293
1312
  style: styles$8.wrapper,
1294
1313
  children: [/* @__PURE__ */ jsx("div", {
1295
1314
  style: styles$8.caption,
@@ -1631,7 +1650,7 @@ function MotionPreview({ filter, caption }) {
1631
1650
  ]);
1632
1651
  const captionText = caption ?? `${rows.length} motion token${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
1633
1652
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
1634
- "data-theme": activeTheme,
1653
+ ...themeAttrs(cssVarPrefix, activeTheme),
1635
1654
  style: styles$6.wrapper,
1636
1655
  children: /* @__PURE__ */ jsx("div", {
1637
1656
  style: styles$6.empty,
@@ -1639,7 +1658,7 @@ function MotionPreview({ filter, caption }) {
1639
1658
  })
1640
1659
  });
1641
1660
  return /* @__PURE__ */ jsxs("div", {
1642
- "data-theme": activeTheme,
1661
+ ...themeAttrs(cssVarPrefix, activeTheme),
1643
1662
  style: styles$6.wrapper,
1644
1663
  children: [
1645
1664
  /* @__PURE__ */ jsx("div", {
@@ -1854,7 +1873,7 @@ function ShadowPreview({ filter = "shadow", caption }) {
1854
1873
  ]);
1855
1874
  const captionText = caption ?? `${rows.length} shadow${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
1856
1875
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
1857
- "data-theme": activeTheme,
1876
+ ...themeAttrs(cssVarPrefix, activeTheme),
1858
1877
  style: styles$5.wrapper,
1859
1878
  children: /* @__PURE__ */ jsx("div", {
1860
1879
  style: styles$5.empty,
@@ -1862,7 +1881,7 @@ function ShadowPreview({ filter = "shadow", caption }) {
1862
1881
  })
1863
1882
  });
1864
1883
  return /* @__PURE__ */ jsxs("div", {
1865
- "data-theme": activeTheme,
1884
+ ...themeAttrs(cssVarPrefix, activeTheme),
1866
1885
  style: styles$5.wrapper,
1867
1886
  children: [/* @__PURE__ */ jsx("div", {
1868
1887
  style: styles$5.caption,
@@ -2012,7 +2031,7 @@ function StrokeStyleSample({ filter = "strokeStyle", caption }) {
2012
2031
  ]);
2013
2032
  const captionText = caption ?? `${rows.length} strokeStyle token${rows.length === 1 ? "" : "s"}${filter && filter !== "strokeStyle" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
2014
2033
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
2015
- "data-theme": activeTheme,
2034
+ ...themeAttrs(cssVarPrefix, activeTheme),
2016
2035
  style: styles$4.wrapper,
2017
2036
  children: /* @__PURE__ */ jsx("div", {
2018
2037
  style: styles$4.empty,
@@ -2020,7 +2039,7 @@ function StrokeStyleSample({ filter = "strokeStyle", caption }) {
2020
2039
  })
2021
2040
  });
2022
2041
  return /* @__PURE__ */ jsxs("div", {
2023
- "data-theme": activeTheme,
2042
+ ...themeAttrs(cssVarPrefix, activeTheme),
2024
2043
  style: styles$4.wrapper,
2025
2044
  children: [/* @__PURE__ */ jsx("div", {
2026
2045
  style: styles$4.caption,
@@ -2466,7 +2485,7 @@ function treeHasTruncation(nodes) {
2466
2485
  //#endregion
2467
2486
  //#region src/token-detail/AxisVariance.tsx
2468
2487
  function AxisVariance({ path }) {
2469
- const { token, cssVar, axes, themes, themesResolved, activeAxes } = useTokenDetailData(path);
2488
+ const { token, cssVar, axes, themes, themesResolved, activeAxes, cssVarPrefix } = useTokenDetailData(path);
2470
2489
  const colorFormat = useColorFormat();
2471
2490
  const isColor = token?.$type === "color";
2472
2491
  const formatFn = (t) => valueFor(t, isColor, colorFormat);
@@ -2559,7 +2578,7 @@ function AxisVariance({ path }) {
2559
2578
  ...styles$3.swatch,
2560
2579
  background: cssVar
2561
2580
  },
2562
- "data-theme": row.themeName,
2581
+ [dataAttr(cssVarPrefix, "theme")]: row.themeName,
2563
2582
  "aria-hidden": true
2564
2583
  }), row.value]
2565
2584
  })]
@@ -2618,7 +2637,7 @@ function AxisVariance({ path }) {
2618
2637
  ...styles$3.swatch,
2619
2638
  background: cssVar
2620
2639
  },
2621
- "data-theme": name,
2640
+ [dataAttr(cssVarPrefix, "theme")]: name,
2622
2641
  "aria-hidden": true
2623
2642
  }), value]
2624
2643
  }, col);
@@ -3144,10 +3163,10 @@ function TokenUsageSnippet({ path }) {
3144
3163
  //#endregion
3145
3164
  //#region src/TokenDetail.tsx
3146
3165
  function TokenDetail({ path, heading }) {
3147
- const { token, cssVar, activeTheme } = useTokenDetailData(path);
3166
+ const { token, cssVar, activeTheme, cssVarPrefix } = useTokenDetailData(path);
3148
3167
  const colorFormat = useColorFormat();
3149
3168
  if (!token) return /* @__PURE__ */ jsx("div", {
3150
- "data-theme": activeTheme,
3169
+ ...themeAttrs(cssVarPrefix, activeTheme),
3151
3170
  style: styles$3.wrapper,
3152
3171
  children: /* @__PURE__ */ jsxs("div", {
3153
3172
  style: styles$3.missing,
@@ -3165,7 +3184,7 @@ function TokenDetail({ path, heading }) {
3165
3184
  const value = formatted ? formatted.value : formatValue(token.$value);
3166
3185
  const outOfGamut = formatted?.outOfGamut ?? false;
3167
3186
  return /* @__PURE__ */ jsxs("div", {
3168
- "data-theme": activeTheme,
3187
+ ...themeAttrs(cssVarPrefix, activeTheme),
3169
3188
  style: styles$3.wrapper,
3170
3189
  children: [
3171
3190
  /* @__PURE__ */ jsx(TokenHeader, {
@@ -3401,7 +3420,7 @@ function countLeaves(node) {
3401
3420
  return n;
3402
3421
  }
3403
3422
  function TokenNavigator({ root, initiallyExpanded = 1, onSelect }) {
3404
- const { resolved, activeTheme } = useProject();
3423
+ const { resolved, activeTheme, cssVarPrefix } = useProject();
3405
3424
  const tree = useMemo(() => buildTree(resolved, root), [resolved, root]);
3406
3425
  const initialExpanded = useMemo(() => {
3407
3426
  const out = /* @__PURE__ */ new Set();
@@ -3426,7 +3445,7 @@ function TokenNavigator({ root, initiallyExpanded = 1, onSelect }) {
3426
3445
  else setSelectedPath(path);
3427
3446
  }, [onSelect]);
3428
3447
  if (tree.length === 0) return /* @__PURE__ */ jsx("div", {
3429
- "data-theme": activeTheme,
3448
+ ...themeAttrs(cssVarPrefix, activeTheme),
3430
3449
  style: styles$2.wrapper,
3431
3450
  children: /* @__PURE__ */ jsx("div", {
3432
3451
  style: styles$2.empty,
@@ -3434,7 +3453,7 @@ function TokenNavigator({ root, initiallyExpanded = 1, onSelect }) {
3434
3453
  })
3435
3454
  });
3436
3455
  return /* @__PURE__ */ jsxs("div", {
3437
- "data-theme": activeTheme,
3456
+ ...themeAttrs(cssVarPrefix, activeTheme),
3438
3457
  style: styles$2.wrapper,
3439
3458
  children: [
3440
3459
  /* @__PURE__ */ jsxs("div", {
@@ -3752,7 +3771,7 @@ function TokenTable({ filter, type, showVar = true, caption }) {
3752
3771
  ]);
3753
3772
  const captionText = caption ?? `${rows.length} token${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""}${type ? ` · $type=${type}` : ""} · ${activeTheme}`;
3754
3773
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
3755
- "data-theme": activeTheme,
3774
+ ...themeAttrs(cssVarPrefix, activeTheme),
3756
3775
  style: styles$1.wrapper,
3757
3776
  children: /* @__PURE__ */ jsx("div", {
3758
3777
  style: styles$1.empty,
@@ -3760,7 +3779,7 @@ function TokenTable({ filter, type, showVar = true, caption }) {
3760
3779
  })
3761
3780
  });
3762
3781
  return /* @__PURE__ */ jsx("div", {
3763
- "data-theme": activeTheme,
3782
+ ...themeAttrs(cssVarPrefix, activeTheme),
3764
3783
  style: styles$1.wrapper,
3765
3784
  children: /* @__PURE__ */ jsxs("table", {
3766
3785
  style: styles$1.table,
@@ -3915,7 +3934,7 @@ function buildRow(path, composite) {
3915
3934
  };
3916
3935
  }
3917
3936
  function TypographyScale({ filter = "typography", sample = "The quick brown fox jumps over the lazy dog.", caption }) {
3918
- const { resolved, activeTheme } = useProject();
3937
+ const { resolved, activeTheme, cssVarPrefix } = useProject();
3919
3938
  const rows = useMemo(() => {
3920
3939
  return Object.entries(resolved).filter(([path, token]) => {
3921
3940
  if (token.$type !== "typography") return false;
@@ -3932,7 +3951,7 @@ function TypographyScale({ filter = "typography", sample = "The quick brown fox
3932
3951
  }, [resolved, filter]);
3933
3952
  const captionText = caption ?? `${rows.length} typography token${rows.length === 1 ? "" : "s"}${filter && filter !== "typography" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
3934
3953
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
3935
- "data-theme": activeTheme,
3954
+ ...themeAttrs(cssVarPrefix, activeTheme),
3936
3955
  style: styles.wrapper,
3937
3956
  children: /* @__PURE__ */ jsx("div", {
3938
3957
  style: styles.empty,
@@ -3940,7 +3959,7 @@ function TypographyScale({ filter = "typography", sample = "The quick brown fox
3940
3959
  })
3941
3960
  });
3942
3961
  return /* @__PURE__ */ jsxs("div", {
3943
- "data-theme": activeTheme,
3962
+ ...themeAttrs(cssVarPrefix, activeTheme),
3944
3963
  style: styles.wrapper,
3945
3964
  children: [/* @__PURE__ */ jsx("div", {
3946
3965
  style: styles.caption,