@unpunnyfuns/swatchbook-blocks 0.55.0 → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,11 +1,15 @@
1
1
  import './style.css';
2
2
  import Color from "colorjs.io";
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";
3
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
5
  import { buildResolveAt } from "@unpunnyfuns/swatchbook-core/resolve-at";
6
- import { makeCSSVar } from "@terrazzo/token-tools/css";
6
+ import { makeCssVar } from "@unpunnyfuns/swatchbook-core/css-var";
7
+ import { SWATCHBOOK_STYLE_ELEMENT_ID, ensureStyleElement } from "@unpunnyfuns/swatchbook-core/style-element";
8
+ import { tupleToName } from "@unpunnyfuns/swatchbook-core/themes";
7
9
  import { addons } from "storybook/preview-api";
8
10
  import { axes, cells, css, cssVarPrefix, defaultTuple, diagnostics, jointOverrides, listing, presets, varianceByPath } from "virtual:swatchbook/tokens";
11
+ import { dataAttr } from "@unpunnyfuns/swatchbook-core/data-attr";
12
+ import { matchPath } from "@unpunnyfuns/swatchbook-core/match-path";
9
13
  import { fuzzyFilter } from "@unpunnyfuns/swatchbook-core/fuzzy";
10
14
  import cx from "clsx";
11
15
  //#region src/format-color.ts
@@ -56,7 +60,8 @@ function coerce(value) {
56
60
  return null;
57
61
  }
58
62
  const alpha = typeof v.alpha === "number" ? v.alpha : void 0;
59
- const hex = typeof v["hex"] === "string" ? v["hex"] : void 0;
63
+ const hexVal = v["hex"];
64
+ const hex = typeof hexVal === "string" ? hexVal : void 0;
60
65
  return {
61
66
  colorSpace,
62
67
  components,
@@ -217,33 +222,23 @@ function ensureSubscribed$1() {
217
222
  if (subscribed$1 || typeof window === "undefined") return;
218
223
  subscribed$1 = true;
219
224
  const channel = addons.getChannel();
225
+ let lastFingerprint = "";
220
226
  const onGlobals = (payload) => {
221
227
  const globals = payload.globals;
222
228
  if (!globals) return;
223
- let next = snapshot$1;
224
- const nextAxes = globals[AXES_GLOBAL_KEY];
225
- if (nextAxes && typeof nextAxes === "object") next = {
226
- ...next,
227
- axes: nextAxes
228
- };
229
- const nextFormat = globals[COLOR_FORMAT_GLOBAL_KEY];
230
- if (isColorFormat(nextFormat)) next = {
231
- ...next,
229
+ const incomingAxes = globals[AXES_GLOBAL_KEY];
230
+ const incomingFormat = globals[COLOR_FORMAT_GLOBAL_KEY];
231
+ const nextAxes = incomingAxes && typeof incomingAxes === "object" ? incomingAxes : snapshot$1.axes;
232
+ const nextFormat = isColorFormat(incomingFormat) ? incomingFormat : snapshot$1.format;
233
+ const fingerprint = `${nextFormat ?? ""}|${nextAxes ? JSON.stringify(nextAxes) : ""}`;
234
+ if (fingerprint === lastFingerprint) return;
235
+ lastFingerprint = fingerprint;
236
+ snapshot$1 = {
237
+ axes: nextAxes,
232
238
  format: nextFormat
233
239
  };
234
- if (next !== snapshot$1) {
235
- snapshot$1 = next;
236
- for (const cb of listeners$1) cb();
237
- }
240
+ for (const cb of listeners$1) cb();
238
241
  };
239
- /**
240
- * `setGlobals` fires once on preview init carrying the URL-persisted user
241
- * globals (Storybook stores toolbar selections in `?globals=…`). Without
242
- * this listener, deeplinking to an MDX page with a non-default axis tuple
243
- * or color format renders defaults for one frame before the first
244
- * `updateGlobals` arrives. `emitGlobals()` reads from `userGlobals.get()`
245
- * (current state), so the payload is never stale — safe to handle.
246
- */
247
242
  channel.on("globalsUpdated", onGlobals);
248
243
  channel.on("updateGlobals", onGlobals);
249
244
  channel.on("setGlobals", onGlobals);
@@ -290,13 +285,13 @@ function useOptionalSwatchbookData() {
290
285
  * `useGlobals` so the same hook works in autodocs / MDX renders where the
291
286
  * preview-hooks context isn't available.
292
287
  */
293
- const PermutationContext = createContext("");
294
- function useActivePermutation() {
295
- return useContext(PermutationContext);
288
+ const ThemeContext = createContext("");
289
+ function useActiveTheme() {
290
+ return useContext(ThemeContext);
296
291
  }
297
292
  /**
298
293
  * Active axis tuple for the current story/docs render — `Record<axisName,
299
- * contextName>`. Derived from the same input as {@link PermutationContext}; split
294
+ * contextName>`. Derived from the same input as {@link ThemeContext}; split
300
295
  * out so consumers needing per-axis info (toolbar, panel, tuple-aware
301
296
  * blocks) don't have to reparse the composed permutation ID.
302
297
  */
@@ -391,16 +386,8 @@ function useTokenSnapshot() {
391
386
  }
392
387
  //#endregion
393
388
  //#region src/internal/use-project.ts
394
- const STYLE_ELEMENT_ID = "swatchbook-tokens";
395
389
  function ensureStylesheet(css) {
396
- if (typeof document === "undefined") return;
397
- let style = document.getElementById(STYLE_ELEMENT_ID);
398
- if (!style) {
399
- style = document.createElement("style");
400
- style.id = STYLE_ELEMENT_ID;
401
- document.head.appendChild(style);
402
- }
403
- if (style.textContent !== css) style.textContent = css;
390
+ ensureStyleElement(SWATCHBOOK_STYLE_ELEMENT_ID, css);
404
391
  }
405
392
  function defaultTuple$1(axes) {
406
393
  const out = {};
@@ -408,44 +395,15 @@ function defaultTuple$1(axes) {
408
395
  return out;
409
396
  }
410
397
  /**
411
- * Stable string key for a tuple axes sorted by name + `:` separator.
412
- * Matches the key form `buildResolveAt` uses in core so both surfaces
413
- * agree on what counts as "the same tuple."
414
- */
415
- function canonicalTupleKey(tuple) {
416
- return Object.keys(tuple).toSorted().map((k) => `${k}:${tuple[k]}`).join("|");
417
- }
418
- /**
419
- * Build a `Map<canonicalKey, permutationName>` once per permutations
420
- * list so per-tuple lookups go through O(1) `Map.get` instead of an
421
- * `Array.prototype.find` scan per call. Bounded by the permutations
422
- * count regardless of how many lookups consumers do.
423
- */
424
- function buildPermutationNameByTuple(permutations) {
425
- const out = /* @__PURE__ */ new Map();
426
- for (const perm of permutations) out.set(canonicalTupleKey(perm.input), perm.name);
427
- return out;
428
- }
429
- const noPermutationName = () => void 0;
430
- function tuplesEqual(a, b) {
431
- const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
432
- for (const k of keys) if (a[k] !== b[k]) return false;
433
- return true;
434
- }
435
- function nameForTuple(themesList, tuple) {
436
- return themesList.find((t) => tuplesEqual(t.input, tuple))?.name;
437
- }
438
- /**
439
- * Reconstruct a `resolveAt` accessor from snapshot data. The wire
440
- * format ships `cells` as plain JSON and `jointOverrides` as an
441
- * array of `[key, entry]` pairs (Map doesn't survive JSON.stringify);
442
- * this hydrates them and wraps `buildResolveAt` from core. Stable
443
- * identity across calls with the same snapshot — `useMemo` keyed on
444
- * the snapshot fields produces a referentially stable function.
398
+ * Reconstruct a `resolveAt` accessor from snapshot data. Both `cells`
399
+ * and `jointOverrides` ship as plain JSON in the same shape core uses
400
+ * internally no Map reconstruction at the boundary. Stable identity
401
+ * across calls with the same snapshot — `useMemo` keyed on the
402
+ * snapshot fields produces a referentially stable function.
445
403
  */
446
404
  function makeResolveAt(snapshot) {
447
405
  const cells = snapshot.cells ?? {};
448
- const jointOverrides = new Map(snapshot.jointOverrides ?? []);
406
+ const jointOverrides = snapshot.jointOverrides ?? [];
449
407
  const defaults = snapshot.defaultTuple ?? defaultTuple$1(snapshot.axes);
450
408
  const resolver = buildResolveAt(snapshot.axes, cells, jointOverrides, defaults);
451
409
  return (tuple) => resolver(tuple);
@@ -454,20 +412,14 @@ function makeResolveAt(snapshot) {
454
412
  * Build the `resolveAt` accessor for a snapshot. Prefers the
455
413
  * snapshot's own `resolveAt` (the addon's preview decorator
456
414
  * pre-builds one at module load — see `previewResolveAt` in
457
- * `packages/addon/src/preview.tsx`), falling back to constructing
458
- * one from `cells` + `jointOverrides` when present (covers
459
- * hand-built test snapshots and the no-provider path) and finally to
460
- * the legacy per-permutation lookup for snapshots that only carry
461
- * `permutationsResolved` + `permutations` (MDX consumers that
462
- * pre-date the wire format change).
415
+ * `packages/addon/src/preview.tsx`), otherwise composes one from
416
+ * `cells` + `jointOverrides` via `makeResolveAt`. Hand-built
417
+ * snapshots should provide both via the test `withCellsShape`
418
+ * helper or by populating the fields directly.
463
419
  */
464
420
  function snapshotResolveAt(snapshot) {
465
421
  if (snapshot.resolveAt) return snapshot.resolveAt;
466
- if (Object.keys(snapshot.cells ?? {}).length > 0) return makeResolveAt(snapshot);
467
- return (tuple) => {
468
- const perms = snapshot.permutations ?? [];
469
- return (snapshot.permutationsResolved ?? {})[nameForTuple(perms, tuple) ?? snapshot.activePermutation] ?? {};
470
- };
422
+ return makeResolveAt(snapshot);
471
423
  }
472
424
  /**
473
425
  * Reads project data either from a mounted {@link SwatchbookProvider}
@@ -487,7 +439,12 @@ function useProject() {
487
439
  const cells = snapshot?.cells;
488
440
  const jointOverrides = snapshot?.jointOverrides;
489
441
  const dataDefaultTuple = snapshot?.defaultTuple;
490
- const activePermutation = snapshot?.activePermutation;
442
+ const activeAxes = snapshot?.activeAxes;
443
+ const activeTheme = snapshot?.activeTheme;
444
+ const diagnostics = snapshot?.diagnostics;
445
+ const cssVarPrefix = snapshot?.cssVarPrefix;
446
+ const listing = snapshot?.listing;
447
+ const varianceByPath = snapshot?.varianceByPath;
491
448
  const resolveAt = useMemo(() => {
492
449
  if (!snapshot) return null;
493
450
  return snapshotResolveAt(snapshot);
@@ -496,29 +453,41 @@ function useProject() {
496
453
  cells,
497
454
  jointOverrides,
498
455
  dataDefaultTuple,
499
- activePermutation
456
+ activeTheme
500
457
  ]);
501
- const permutationNameByTuple = useMemo(() => buildPermutationNameByTuple(snapshot?.permutations ?? []), [snapshot?.permutations]);
502
- const fallback = useVirtualModuleFallback(snapshot === null);
503
- if (snapshot !== null && resolveAt !== null) return snapshotToData(snapshot, resolveAt, permutationNameByTuple);
504
- return fallback;
505
- }
506
- function snapshotToData(snapshot, resolveAt, permutationNameByTuple) {
507
- return {
508
- activePermutation: snapshot.activePermutation,
509
- activeAxes: snapshot.activeAxes,
510
- axes: snapshot.axes,
511
- resolved: resolveAt(snapshot.activeAxes),
512
- diagnostics: snapshot.diagnostics,
513
- cssVarPrefix: snapshot.cssVarPrefix,
514
- listing: snapshot.listing ?? {},
515
- varianceByPath: snapshot.varianceByPath ?? {},
458
+ const providerData = useMemo(() => {
459
+ if (!snapshot || !resolveAt || !axes || !activeAxes) return null;
460
+ return {
461
+ activeTheme: activeTheme ?? "",
462
+ activeAxes,
463
+ axes,
464
+ resolved: resolveAt(activeAxes),
465
+ diagnostics: diagnostics ?? [],
466
+ cssVarPrefix: cssVarPrefix ?? "",
467
+ listing: listing ?? {},
468
+ varianceByPath: varianceByPath ?? {},
469
+ resolveAt,
470
+ themeNameForTuple: (tuple) => tupleToName(axes, tuple)
471
+ };
472
+ }, [
473
+ snapshot,
516
474
  resolveAt,
517
- permutationNameForTuple: (tuple) => permutationNameByTuple.get(canonicalTupleKey(tuple))
518
- };
475
+ axes,
476
+ cells,
477
+ jointOverrides,
478
+ dataDefaultTuple,
479
+ activeTheme,
480
+ activeAxes,
481
+ diagnostics,
482
+ cssVarPrefix,
483
+ listing,
484
+ varianceByPath
485
+ ]);
486
+ const fallback = useVirtualModuleFallback(snapshot === null);
487
+ return providerData ?? fallback;
519
488
  }
520
489
  function useVirtualModuleFallback(enabled) {
521
- const contextPermutation = useActivePermutation();
490
+ const contextPermutation = useActiveTheme();
522
491
  const contextAxes = useActiveAxes();
523
492
  const channelGlobals = useChannelGlobals();
524
493
  /**
@@ -533,8 +502,14 @@ function useVirtualModuleFallback(enabled) {
533
502
  if (!enabled) return;
534
503
  ensureStylesheet(tokens.css);
535
504
  }, [enabled, tokens.css]);
536
- const activeAxes = Object.keys(contextAxes).length > 0 ? { ...contextAxes } : channelGlobals.axes ?? defaultTuple$1(tokens.axes);
537
- const activePermutation = contextPermutation || tokens.axes.map((a) => activeAxes[a.name] ?? a.default).join(" · ") || "";
505
+ const activeAxes = useMemo(() => {
506
+ return Object.keys(contextAxes).length > 0 ? { ...contextAxes } : channelGlobals.axes ?? defaultTuple$1(tokens.axes);
507
+ }, [
508
+ contextAxes,
509
+ channelGlobals.axes,
510
+ tokens.axes
511
+ ]);
512
+ const activeTheme = contextPermutation || tupleToName(tokens.axes, activeAxes);
538
513
  const resolveAt = useMemo(() => makeResolveAt({
539
514
  axes: tokens.axes,
540
515
  cells: tokens.cells,
@@ -546,32 +521,27 @@ function useVirtualModuleFallback(enabled) {
546
521
  tokens.jointOverrides,
547
522
  tokens.defaultTuple
548
523
  ]);
549
- const resolved = resolveAt(activeAxes);
550
- const permutationNameForTuple = noPermutationName;
551
- return {
552
- activePermutation,
524
+ return useMemo(() => ({
525
+ activeTheme,
553
526
  activeAxes,
554
527
  axes: tokens.axes,
555
- resolved,
528
+ resolved: resolveAt(activeAxes),
556
529
  diagnostics: tokens.diagnostics,
557
530
  cssVarPrefix: tokens.cssVarPrefix,
558
531
  listing: tokens.listing,
559
532
  varianceByPath: tokens.varianceByPath,
560
533
  resolveAt,
561
- permutationNameForTuple
562
- };
563
- }
564
- /**
565
- * Thin wrapper around Terrazzo's `makeCSSVar` so the block-display surface
566
- * and `packages/core/src/css.ts`'s emitter share one implementation. Any
567
- * future naming-policy shift in Terrazzo (casing, unicode, prefix handling)
568
- * reaches both surfaces at once instead of needing a parallel update here.
569
- */
570
- function makeCssVar(path, prefix) {
571
- return prefix ? makeCSSVar(path, {
572
- prefix,
573
- wrapVar: true
574
- }) : makeCSSVar(path, { wrapVar: true });
534
+ themeNameForTuple: (tuple) => tupleToName(tokens.axes, tuple)
535
+ }), [
536
+ activeTheme,
537
+ activeAxes,
538
+ tokens.axes,
539
+ tokens.diagnostics,
540
+ tokens.cssVarPrefix,
541
+ tokens.listing,
542
+ tokens.varianceByPath,
543
+ resolveAt
544
+ ]);
575
545
  }
576
546
  /**
577
547
  * Resolve a token's CSS var reference, preferring the authoritative name
@@ -608,31 +578,6 @@ function resolveColorValue(path, raw, colorFormat, project) {
608
578
  }
609
579
  return formatColor(raw, colorFormat);
610
580
  }
611
- /**
612
- * Match a dot-separated DTCG token path against a block `filter` prop.
613
- *
614
- * **Supported shapes** (the narrow subset we need — DTCG paths don't have
615
- * directories, brace expansion, or regex, so we skip a full glob engine):
616
- *
617
- * | Pattern | Matches |
618
- * | ------------------ | --------------------------------------------------- |
619
- * | `undefined` / `''` | everything |
620
- * | `*` or `**` | everything |
621
- * | `color` | exact path `color`, or any descendant `color.*` |
622
- * | `color.*` | any path whose fixed prefix is `color.` |
623
- * | `color**` | any path starting with `color` |
624
- *
625
- * Not supported (all pass through as literal segment matchers): brace
626
- * expansion (`{a,b}`), mid-path globs (`color.*.bg`), negation (`!foo`),
627
- * character classes (`[sys]`). If you hit those, pre-filter by hand.
628
- */
629
- function globMatch(path, glob) {
630
- if (!glob) return true;
631
- if (glob === "*" || glob === "**") return true;
632
- if (glob.endsWith(".*")) return path.startsWith(`${glob.slice(0, -2)}.`);
633
- if (glob.endsWith("**")) return path.startsWith(glob.slice(0, -2));
634
- return path === glob || path.startsWith(`${glob}.`);
635
- }
636
581
  //#endregion
637
582
  //#region src/border-preview/BorderSample.tsx
638
583
  const sampleStyle$1 = {
@@ -654,15 +599,6 @@ function BorderSample({ path }) {
654
599
  //#endregion
655
600
  //#region src/internal/data-attr.ts
656
601
  /**
657
- * Produce a prefixed `data-*` attribute name when `prefix` is set, bare
658
- * `data-<key>` otherwise. Mirrors `dataAttr` in `@unpunnyfuns/swatchbook-core`
659
- * so block wrappers and emitted-CSS selectors stay in lockstep without
660
- * blocks taking a runtime dep on core.
661
- */
662
- function dataAttr(prefix, key) {
663
- return prefix ? `data-${prefix}-${key}` : `data-${key}`;
664
- }
665
- /**
666
602
  * Marker attribute set on every block wrapper. Retained as a stable hook
667
603
  * for consumer-side selectors (e.g. when a host app wants to target or
668
604
  * override block chrome without relying on hashed class names).
@@ -697,59 +633,73 @@ function themeAttrs(prefix, themeName) {
697
633
  }
698
634
  //#endregion
699
635
  //#region src/internal/sort-tokens.ts
700
- /**
701
- * Stable sort for a filtered `[path, token][]` list.
702
- *
703
- * `sortBy: 'path'` — lexicographic on the dot-path (locale-aware, numeric).
704
- * `sortBy: 'value'` — per-`$type` ordering:
705
- * - `dimension` / `duration` → numeric pixels / ms (via `toMagnitude`).
706
- * - `fontWeight` / `opacity` / `number` / `lineHeight` → numeric.
707
- * - `color` → perceptual by oklch L → C → H.
708
- * - `fontFamily` / `strokeStyle` (string form) → lexicographic.
709
- * - Composites (`typography`, `shadow`, `border`, `gradient`, `transition`)
710
- * fall back to path-alpha. No useful single-axis order.
711
- * `sortBy: 'none'` preserve input order (still respects `sortDir: 'desc'`
712
- * as a reverse).
713
- */
636
+ const NUMERIC_TYPES = new Set([
637
+ "dimension",
638
+ "duration",
639
+ "fontWeight",
640
+ "opacity",
641
+ "number",
642
+ "lineHeight"
643
+ ]);
644
+ const STRING_TYPES = new Set(["fontFamily", "strokeStyle"]);
645
+ function computeSortKey(token) {
646
+ const type = token.$type;
647
+ if (!type) return { kind: "none" };
648
+ if (NUMERIC_TYPES.has(type)) {
649
+ const value = toMagnitude(token.$value);
650
+ return {
651
+ kind: "numeric",
652
+ value,
653
+ valid: Number.isFinite(value)
654
+ };
655
+ }
656
+ if (type === "color") return {
657
+ kind: "color",
658
+ key: colorKey(token.$value)
659
+ };
660
+ if (STRING_TYPES.has(type)) return {
661
+ kind: "string",
662
+ value: toDisplayable(token.$value)
663
+ };
664
+ return { kind: "none" };
665
+ }
714
666
  function sortTokens(entries, options = {}) {
715
667
  const by = options.by ?? "path";
716
668
  const dir = options.dir ?? "asc";
717
669
  const sign = dir === "desc" ? -1 : 1;
718
670
  if (by === "none") return dir === "desc" ? [...entries].toReversed() : [...entries];
719
671
  if (by === "path") return [...entries].toSorted(([a], [b]) => sign * a.localeCompare(b, void 0, { numeric: true }));
672
+ const keys = /* @__PURE__ */ new Map();
673
+ for (const [, token] of entries) keys.set(token, computeSortKey(token));
720
674
  return [...entries].toSorted(([aPath, aTok], [bPath, bTok]) => {
721
- const cmp = compareValue(aTok, bTok);
675
+ const cmp = compareValue(aTok, bTok, keys);
722
676
  if (cmp !== 0) return sign * cmp;
723
677
  return sign * aPath.localeCompare(bPath, void 0, { numeric: true });
724
678
  });
725
679
  }
726
- function compareValue(a, b) {
727
- const type = a.$type;
728
- if (type !== b.$type) return String(type ?? "").localeCompare(String(b.$type ?? ""));
729
- if (!type) return 0;
730
- if (type === "dimension" || type === "duration" || type === "fontWeight" || type === "opacity" || type === "number" || type === "lineHeight") {
731
- const av = toMagnitude(a.$value);
732
- const bv = toMagnitude(b.$value);
733
- if (Number.isFinite(av) && Number.isFinite(bv)) return av - bv;
734
- if (Number.isFinite(av)) return -1;
735
- if (Number.isFinite(bv)) return 1;
680
+ function compareValue(a, b, keys) {
681
+ if (a.$type !== b.$type) return String(a.$type ?? "").localeCompare(String(b.$type ?? ""));
682
+ const ak = keys.get(a);
683
+ const bk = keys.get(b);
684
+ if (!ak || !bk) return 0;
685
+ if (ak.kind !== bk.kind) return 0;
686
+ if (ak.kind === "numeric" && bk.kind === "numeric") {
687
+ if (ak.valid && bk.valid) return ak.value - bk.value;
688
+ if (ak.valid) return -1;
689
+ if (bk.valid) return 1;
736
690
  return 0;
737
691
  }
738
- if (type === "color") {
739
- const ak = colorKey(a.$value);
740
- const bk = colorKey(b.$value);
741
- if (!ak && !bk) return 0;
742
- if (!ak) return 1;
743
- if (!bk) return -1;
744
- if (ak.l !== bk.l) return ak.l - bk.l;
745
- if (ak.c !== bk.c) return ak.c - bk.c;
746
- return ak.h - bk.h;
747
- }
748
- if (type === "fontFamily" || type === "strokeStyle") {
749
- const as = toDisplayable(a.$value);
750
- const bs = toDisplayable(b.$value);
751
- return as.localeCompare(bs, void 0, { numeric: true });
692
+ if (ak.kind === "color" && bk.kind === "color") {
693
+ const a3 = ak.key;
694
+ const b3 = bk.key;
695
+ if (!a3 && !b3) return 0;
696
+ if (!a3) return 1;
697
+ if (!b3) return -1;
698
+ if (a3.l !== b3.l) return a3.l - b3.l;
699
+ if (a3.c !== b3.c) return a3.c - b3.c;
700
+ return a3.h - b3.h;
752
701
  }
702
+ if (ak.kind === "string" && bk.kind === "string") return ak.value.localeCompare(bk.value, void 0, { numeric: true });
753
703
  return 0;
754
704
  }
755
705
  function toMagnitude(v) {
@@ -769,6 +719,14 @@ function toMagnitude(v) {
769
719
  }
770
720
  return NaN;
771
721
  }
722
+ /**
723
+ * Coerce a possibly-null/undefined number to 0 — `coords` returns
724
+ * `(number | null)[]` and `noUncheckedIndexedAccess` adds `undefined`
725
+ * on top. `typeof` narrows the union for the comparator below.
726
+ */
727
+ function safeNumber(v) {
728
+ return typeof v === "number" && Number.isFinite(v) ? v : 0;
729
+ }
772
730
  function colorKey(v) {
773
731
  if (!v || typeof v !== "object") return null;
774
732
  try {
@@ -785,9 +743,9 @@ function colorKey(v) {
785
743
  } else return null;
786
744
  const [l, chroma, h] = new Color(source).to("oklch").coords;
787
745
  return {
788
- l: Number.isFinite(l) ? l : 0,
789
- c: Number.isFinite(chroma) ? chroma : 0,
790
- h: Number.isFinite(h) ? h : 0
746
+ l: safeNumber(l),
747
+ c: safeNumber(chroma),
748
+ h: safeNumber(h)
791
749
  };
792
750
  } catch {
793
751
  return null;
@@ -817,12 +775,12 @@ function formatSubColor$1(raw, format) {
817
775
  }
818
776
  function BorderPreview({ filter, caption, sortBy = "path", sortDir = "asc" }) {
819
777
  const project = useProject();
820
- const { resolved, activePermutation, cssVarPrefix } = project;
778
+ const { resolved, activeTheme, cssVarPrefix } = project;
821
779
  const colorFormat = useColorFormat();
822
780
  const rows = useMemo(() => {
823
781
  return sortTokens(Object.entries(resolved).filter(([path, token]) => {
824
782
  if (token.$type !== "border") return false;
825
- return globMatch(path, filter);
783
+ return matchPath(path, filter);
826
784
  }), {
827
785
  by: sortBy,
828
786
  dir: sortDir
@@ -838,16 +796,16 @@ function BorderPreview({ filter, caption, sortBy = "path", sortDir = "asc" }) {
838
796
  sortBy,
839
797
  sortDir
840
798
  ]);
841
- const captionText = caption ?? `${rows.length} border${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activePermutation}`;
799
+ const captionText = caption ?? `${rows.length} border${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
842
800
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
843
- ...themeAttrs(cssVarPrefix, activePermutation),
801
+ ...themeAttrs(cssVarPrefix, activeTheme),
844
802
  children: /* @__PURE__ */ jsx("div", {
845
803
  className: "sb-block__empty",
846
804
  children: "No border tokens match this filter."
847
805
  })
848
806
  });
849
807
  return /* @__PURE__ */ jsxs("div", {
850
- ...themeAttrs(cssVarPrefix, activePermutation),
808
+ ...themeAttrs(cssVarPrefix, activeTheme),
851
809
  children: [/* @__PURE__ */ jsx("div", {
852
810
  className: "sb-block__caption",
853
811
  children: captionText
@@ -910,12 +868,12 @@ function fixedPrefixLength(filter) {
910
868
  }
911
869
  function ColorPalette({ filter, groupBy, caption, sortBy = "path", sortDir = "asc" }) {
912
870
  const project = useProject();
913
- const { resolved, activePermutation, cssVarPrefix } = project;
871
+ const { resolved, activeTheme, cssVarPrefix } = project;
914
872
  const colorFormat = useColorFormat();
915
873
  const groups = useMemo(() => {
916
874
  const entries = sortTokens(Object.entries(resolved).filter(([path, token]) => {
917
875
  if (token.$type !== "color") return false;
918
- return globMatch(path, filter);
876
+ return matchPath(path, filter);
919
877
  }), {
920
878
  by: sortBy,
921
879
  dir: sortDir
@@ -949,16 +907,16 @@ function ColorPalette({ filter, groupBy, caption, sortBy = "path", sortDir = "as
949
907
  sortDir
950
908
  ]);
951
909
  const totalCount = groups.reduce((acc, [, swatches]) => acc + swatches.length, 0);
952
- const captionText = caption ?? `${totalCount} color${totalCount === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activePermutation}`;
910
+ const captionText = caption ?? `${totalCount} color${totalCount === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
953
911
  if (totalCount === 0) return /* @__PURE__ */ jsx("div", {
954
- ...themeAttrs(cssVarPrefix, activePermutation),
912
+ ...themeAttrs(cssVarPrefix, activeTheme),
955
913
  children: /* @__PURE__ */ jsx("div", {
956
914
  className: "sb-block__empty",
957
915
  children: "No color tokens match this filter."
958
916
  })
959
917
  });
960
918
  return /* @__PURE__ */ jsxs("div", {
961
- ...themeAttrs(cssVarPrefix, activePermutation),
919
+ ...themeAttrs(cssVarPrefix, activeTheme),
962
920
  children: [/* @__PURE__ */ jsx("div", {
963
921
  className: "sb-block__caption",
964
922
  children: captionText
@@ -1045,7 +1003,7 @@ const BASE_LABEL = "base";
1045
1003
  const COLUMN_COUNT = 6;
1046
1004
  function ColorTable({ filter, caption, sortBy = "path", sortDir = "asc", searchable = true, onSelect, variants }) {
1047
1005
  const project = useProject();
1048
- const { resolved, activePermutation, cssVarPrefix } = project;
1006
+ const { resolved, activeTheme, cssVarPrefix } = project;
1049
1007
  const colorFormat = useColorFormat();
1050
1008
  const [query, setQuery] = useState("");
1051
1009
  const [selectedByBase, setSelectedByBase] = useState({});
@@ -1054,7 +1012,7 @@ function ColorTable({ filter, caption, sortBy = "path", sortDir = "asc", searcha
1054
1012
  const groups = useMemo(() => {
1055
1013
  const sorted = sortTokens(Object.entries(resolved).filter(([path, token]) => {
1056
1014
  if (token.$type !== "color") return false;
1057
- return globMatch(path, filter);
1015
+ return matchPath(path, filter);
1058
1016
  }), {
1059
1017
  by: sortBy,
1060
1018
  dir: sortDir
@@ -1132,16 +1090,16 @@ function ColorTable({ filter, caption, sortBy = "path", sortDir = "asc", searcha
1132
1090
  }));
1133
1091
  }, []);
1134
1092
  const matchSuffix = searchable && query.trim() !== "" ? ` · ${visibleGroups.length} matching "${query.trim()}"` : "";
1135
- const captionText = caption ?? `${totalTokens} color${totalTokens === 1 ? "" : "s"} across ${groups.length} group${groups.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""}${matchSuffix} · ${activePermutation}`;
1093
+ const captionText = caption ?? `${totalTokens} color${totalTokens === 1 ? "" : "s"} across ${groups.length} group${groups.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""}${matchSuffix} · ${activeTheme}`;
1136
1094
  if (groups.length === 0) return /* @__PURE__ */ jsx("div", {
1137
- ...themeAttrs(cssVarPrefix, activePermutation),
1095
+ ...themeAttrs(cssVarPrefix, activeTheme),
1138
1096
  children: /* @__PURE__ */ jsx("div", {
1139
1097
  className: "sb-block__empty",
1140
1098
  children: "No color tokens match this filter."
1141
1099
  })
1142
1100
  });
1143
1101
  return /* @__PURE__ */ jsxs("div", {
1144
- ...themeAttrs(cssVarPrefix, activePermutation),
1102
+ ...themeAttrs(cssVarPrefix, activeTheme),
1145
1103
  children: [searchable && /* @__PURE__ */ jsx("div", {
1146
1104
  className: "sb-color-table__search",
1147
1105
  children: /* @__PURE__ */ jsx("input", {
@@ -1563,12 +1521,12 @@ function summaryVariant(diagnostics) {
1563
1521
  * on their own MDX pages.
1564
1522
  */
1565
1523
  function Diagnostics({ caption } = {}) {
1566
- const { activePermutation, cssVarPrefix, diagnostics } = useProject();
1524
+ const { activeTheme, cssVarPrefix, diagnostics } = useProject();
1567
1525
  const hasErrorsOrWarnings = diagnostics.some((d) => d.severity === "error" || d.severity === "warn");
1568
1526
  const headingText = caption ?? `Diagnostics · ${summaryText(diagnostics)}`;
1569
1527
  const variant = summaryVariant(diagnostics);
1570
1528
  return /* @__PURE__ */ jsx("div", {
1571
- ...themeAttrs(cssVarPrefix, activePermutation),
1529
+ ...themeAttrs(cssVarPrefix, activeTheme),
1572
1530
  "data-testid": "diagnostics",
1573
1531
  children: /* @__PURE__ */ jsxs("details", {
1574
1532
  open: hasErrorsOrWarnings,
@@ -1785,11 +1743,11 @@ function toPixels(raw) {
1785
1743
  }
1786
1744
  function DimensionScale({ filter, kind = "length", caption, sortBy = "value", sortDir = "asc" }) {
1787
1745
  const project = useProject();
1788
- const { resolved, activePermutation, cssVarPrefix } = project;
1746
+ const { resolved, activeTheme, cssVarPrefix } = project;
1789
1747
  const rows = useMemo(() => {
1790
1748
  return sortTokens(Object.entries(resolved).filter(([path, token]) => {
1791
1749
  if (token.$type !== "dimension") return false;
1792
- return globMatch(path, filter);
1750
+ return matchPath(path, filter);
1793
1751
  }), {
1794
1752
  by: sortBy,
1795
1753
  dir: sortDir
@@ -1810,16 +1768,16 @@ function DimensionScale({ filter, kind = "length", caption, sortBy = "value", so
1810
1768
  sortBy,
1811
1769
  sortDir
1812
1770
  ]);
1813
- const captionText = caption ?? `${rows.length} dimension${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activePermutation}`;
1771
+ const captionText = caption ?? `${rows.length} dimension${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
1814
1772
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
1815
- ...themeAttrs(cssVarPrefix, activePermutation),
1773
+ ...themeAttrs(cssVarPrefix, activeTheme),
1816
1774
  children: /* @__PURE__ */ jsx("div", {
1817
1775
  className: "sb-block__empty",
1818
1776
  children: "No dimension tokens match this filter."
1819
1777
  })
1820
1778
  });
1821
1779
  return /* @__PURE__ */ jsxs("div", {
1822
- ...themeAttrs(cssVarPrefix, activePermutation),
1780
+ ...themeAttrs(cssVarPrefix, activeTheme),
1823
1781
  children: [/* @__PURE__ */ jsx("div", {
1824
1782
  className: "sb-block__caption",
1825
1783
  children: captionText
@@ -1867,11 +1825,11 @@ function stackString(raw) {
1867
1825
  }
1868
1826
  function FontFamilySample({ filter, sample = "The quick brown fox jumps over the lazy dog.", caption, sortBy = "path", sortDir = "asc" }) {
1869
1827
  const project = useProject();
1870
- const { resolved, activePermutation, cssVarPrefix } = project;
1828
+ const { resolved, activeTheme, cssVarPrefix } = project;
1871
1829
  const rows = useMemo(() => {
1872
1830
  return sortTokens(Object.entries(resolved).filter(([path, token]) => {
1873
1831
  if (token.$type !== "fontFamily") return false;
1874
- return globMatch(path, filter);
1832
+ return matchPath(path, filter);
1875
1833
  }), {
1876
1834
  by: sortBy,
1877
1835
  dir: sortDir
@@ -1887,16 +1845,16 @@ function FontFamilySample({ filter, sample = "The quick brown fox jumps over the
1887
1845
  sortBy,
1888
1846
  sortDir
1889
1847
  ]);
1890
- const captionText = caption ?? `${rows.length} fontFamily token${rows.length === 1 ? "" : "s"}${filter && filter !== "fontFamily" ? ` matching \`${filter}\`` : ""} · ${activePermutation}`;
1848
+ const captionText = caption ?? `${rows.length} fontFamily token${rows.length === 1 ? "" : "s"}${filter && filter !== "fontFamily" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
1891
1849
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
1892
- ...themeAttrs(cssVarPrefix, activePermutation),
1850
+ ...themeAttrs(cssVarPrefix, activeTheme),
1893
1851
  children: /* @__PURE__ */ jsx("div", {
1894
1852
  className: "sb-block__empty",
1895
1853
  children: "No fontFamily tokens match this filter."
1896
1854
  })
1897
1855
  });
1898
1856
  return /* @__PURE__ */ jsxs("div", {
1899
- ...themeAttrs(cssVarPrefix, activePermutation),
1857
+ ...themeAttrs(cssVarPrefix, activeTheme),
1900
1858
  children: [/* @__PURE__ */ jsx("div", {
1901
1859
  className: "sb-block__caption",
1902
1860
  children: captionText
@@ -1953,11 +1911,11 @@ function toWeight(raw) {
1953
1911
  }
1954
1912
  function FontWeightScale({ filter, sample = "Aa", caption, sortBy = "value", sortDir = "asc" }) {
1955
1913
  const project = useProject();
1956
- const { resolved, activePermutation, cssVarPrefix } = project;
1914
+ const { resolved, activeTheme, cssVarPrefix } = project;
1957
1915
  const rows = useMemo(() => {
1958
1916
  return sortTokens(Object.entries(resolved).filter(([path, token]) => {
1959
1917
  if (token.$type !== "fontWeight") return false;
1960
- return globMatch(path, filter);
1918
+ return matchPath(path, filter);
1961
1919
  }), {
1962
1920
  by: sortBy,
1963
1921
  dir: sortDir
@@ -1974,16 +1932,16 @@ function FontWeightScale({ filter, sample = "Aa", caption, sortBy = "value", sor
1974
1932
  sortBy,
1975
1933
  sortDir
1976
1934
  ]);
1977
- const captionText = caption ?? `${rows.length} fontWeight token${rows.length === 1 ? "" : "s"}${filter && filter !== "fontWeight" ? ` matching \`${filter}\`` : ""} · ${activePermutation}`;
1935
+ const captionText = caption ?? `${rows.length} fontWeight token${rows.length === 1 ? "" : "s"}${filter && filter !== "fontWeight" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
1978
1936
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
1979
- ...themeAttrs(cssVarPrefix, activePermutation),
1937
+ ...themeAttrs(cssVarPrefix, activeTheme),
1980
1938
  children: /* @__PURE__ */ jsx("div", {
1981
1939
  className: "sb-block__empty",
1982
1940
  children: "No fontWeight tokens match this filter."
1983
1941
  })
1984
1942
  });
1985
1943
  return /* @__PURE__ */ jsxs("div", {
1986
- ...themeAttrs(cssVarPrefix, activePermutation),
1944
+ ...themeAttrs(cssVarPrefix, activeTheme),
1987
1945
  children: [/* @__PURE__ */ jsx("div", {
1988
1946
  className: "sb-block__caption",
1989
1947
  children: captionText
@@ -2033,12 +1991,12 @@ function stopKey(path, stop, fallback) {
2033
1991
  }
2034
1992
  function GradientPalette({ filter, caption, sortBy = "path", sortDir = "asc" }) {
2035
1993
  const project = useProject();
2036
- const { resolved, activePermutation, cssVarPrefix } = project;
1994
+ const { resolved, activeTheme, cssVarPrefix } = project;
2037
1995
  const colorFormat = useColorFormat();
2038
1996
  const rows = useMemo(() => {
2039
1997
  return sortTokens(Object.entries(resolved).filter(([path, token]) => {
2040
1998
  if (token.$type !== "gradient") return false;
2041
- return globMatch(path, filter);
1999
+ return matchPath(path, filter);
2042
2000
  }), {
2043
2001
  by: sortBy,
2044
2002
  dir: sortDir
@@ -2054,16 +2012,16 @@ function GradientPalette({ filter, caption, sortBy = "path", sortDir = "asc" })
2054
2012
  sortBy,
2055
2013
  sortDir
2056
2014
  ]);
2057
- const captionText = caption ?? `${rows.length} gradient${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activePermutation}`;
2015
+ const captionText = caption ?? `${rows.length} gradient${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
2058
2016
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
2059
- ...themeAttrs(cssVarPrefix, activePermutation),
2017
+ ...themeAttrs(cssVarPrefix, activeTheme),
2060
2018
  children: /* @__PURE__ */ jsx("div", {
2061
2019
  className: "sb-block__empty",
2062
2020
  children: "No gradient tokens match this filter."
2063
2021
  })
2064
2022
  });
2065
2023
  return /* @__PURE__ */ jsxs("div", {
2066
- ...themeAttrs(cssVarPrefix, activePermutation),
2024
+ ...themeAttrs(cssVarPrefix, activeTheme),
2067
2025
  children: [/* @__PURE__ */ jsx("div", {
2068
2026
  className: "sb-block__caption",
2069
2027
  children: captionText
@@ -2117,9 +2075,9 @@ function GradientPalette({ filter, caption, sortBy = "path", sortDir = "asc" })
2117
2075
  * True when rendering inside Chromatic's snapshot runner. Chromatic's
2118
2076
  * browser ships a recognisable user-agent string; checked here so
2119
2077
  * motion-looping components can fall back to their static state for
2120
- * deterministic snapshots without needing a global Chromatic parameter
2121
- * (globally forcing `prefersReducedMotion: true` broke Chromatic's
2122
- * verification parser in our setup see commit 893331f).
2078
+ * deterministic snapshots. Per-component detection rather than the
2079
+ * global `chromatic.prefersReducedMotion: true` parameter — that
2080
+ * parameter is incompatible with Chromatic's verification parser.
2123
2081
  */
2124
2082
  function isChromatic() {
2125
2083
  if (typeof navigator === "undefined") return false;
@@ -2300,14 +2258,14 @@ function formatSpec(row) {
2300
2258
  }
2301
2259
  function MotionPreview({ filter, caption }) {
2302
2260
  const project = useProject();
2303
- const { resolved, activePermutation, cssVarPrefix } = project;
2261
+ const { resolved, activeTheme, cssVarPrefix } = project;
2304
2262
  const [speed, setSpeed] = useState(1);
2305
2263
  const [run, setRun] = useState(0);
2306
2264
  const reducedMotion = usePrefersReducedMotion();
2307
2265
  const rows = useMemo(() => {
2308
2266
  const collected = [];
2309
2267
  for (const [path, token] of Object.entries(resolved)) {
2310
- if (filter && !globMatch(path, filter)) continue;
2268
+ if (filter && !matchPath(path, filter)) continue;
2311
2269
  if (!filter && ![
2312
2270
  "transition",
2313
2271
  "duration",
@@ -2335,16 +2293,16 @@ function MotionPreview({ filter, caption }) {
2335
2293
  filter,
2336
2294
  project
2337
2295
  ]);
2338
- const captionText = caption ?? `${rows.length} motion token${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activePermutation}`;
2296
+ const captionText = caption ?? `${rows.length} motion token${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
2339
2297
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
2340
- ...themeAttrs(cssVarPrefix, activePermutation),
2298
+ ...themeAttrs(cssVarPrefix, activeTheme),
2341
2299
  children: /* @__PURE__ */ jsx("div", {
2342
2300
  className: "sb-block__empty",
2343
2301
  children: "No motion tokens match this filter."
2344
2302
  })
2345
2303
  });
2346
2304
  return /* @__PURE__ */ jsxs("div", {
2347
- ...themeAttrs(cssVarPrefix, activePermutation),
2305
+ ...themeAttrs(cssVarPrefix, activeTheme),
2348
2306
  children: [
2349
2307
  /* @__PURE__ */ jsx("div", {
2350
2308
  className: "sb-block__caption",
@@ -2418,13 +2376,13 @@ function toOpacity(raw) {
2418
2376
  */
2419
2377
  function OpacityScale({ filter, type = "number", sampleColor = "color.accent.bg", caption, sortBy = "value", sortDir = "asc" }) {
2420
2378
  const project = useProject();
2421
- const { resolved, activePermutation, cssVarPrefix } = project;
2379
+ const { resolved, activeTheme, cssVarPrefix } = project;
2422
2380
  const rows = useMemo(() => {
2423
2381
  return sortTokens(Object.entries(resolved).filter(([path, token]) => {
2424
2382
  if (token.$type !== type) return false;
2425
2383
  const v = toOpacity(token.$value);
2426
2384
  if (!Number.isFinite(v) || v < 0 || v > 1) return false;
2427
- return globMatch(path, filter);
2385
+ return matchPath(path, filter);
2428
2386
  }), {
2429
2387
  by: sortBy,
2430
2388
  dir: sortDir
@@ -2445,9 +2403,9 @@ function OpacityScale({ filter, type = "number", sampleColor = "color.accent.bg"
2445
2403
  sortBy,
2446
2404
  sortDir
2447
2405
  ]);
2448
- const captionText = caption ?? `${rows.length} opacity token${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activePermutation}`;
2406
+ const captionText = caption ?? `${rows.length} opacity token${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
2449
2407
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
2450
- ...themeAttrs(cssVarPrefix, activePermutation),
2408
+ ...themeAttrs(cssVarPrefix, activeTheme),
2451
2409
  children: /* @__PURE__ */ jsx("div", {
2452
2410
  className: "sb-block__empty",
2453
2411
  children: "No opacity tokens match this filter."
@@ -2455,7 +2413,7 @@ function OpacityScale({ filter, type = "number", sampleColor = "color.accent.bg"
2455
2413
  });
2456
2414
  const sampleColorVar = resolveCssVar(sampleColor, project);
2457
2415
  return /* @__PURE__ */ jsxs("div", {
2458
- ...themeAttrs(cssVarPrefix, activePermutation),
2416
+ ...themeAttrs(cssVarPrefix, activeTheme),
2459
2417
  children: [/* @__PURE__ */ jsx("div", {
2460
2418
  className: "sb-block__caption",
2461
2419
  children: captionText
@@ -2563,12 +2521,12 @@ function layerKey(path, layer, fallback) {
2563
2521
  }
2564
2522
  function ShadowPreview({ filter, caption, sortBy = "path", sortDir = "asc" }) {
2565
2523
  const project = useProject();
2566
- const { resolved, activePermutation, cssVarPrefix } = project;
2524
+ const { resolved, activeTheme, cssVarPrefix } = project;
2567
2525
  const colorFormat = useColorFormat();
2568
2526
  const rows = useMemo(() => {
2569
2527
  return sortTokens(Object.entries(resolved).filter(([path, token]) => {
2570
2528
  if (token.$type !== "shadow") return false;
2571
- return globMatch(path, filter);
2529
+ return matchPath(path, filter);
2572
2530
  }), {
2573
2531
  by: sortBy,
2574
2532
  dir: sortDir
@@ -2584,16 +2542,16 @@ function ShadowPreview({ filter, caption, sortBy = "path", sortDir = "asc" }) {
2584
2542
  sortBy,
2585
2543
  sortDir
2586
2544
  ]);
2587
- const captionText = caption ?? `${rows.length} shadow${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activePermutation}`;
2545
+ const captionText = caption ?? `${rows.length} shadow${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
2588
2546
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
2589
- ...themeAttrs(cssVarPrefix, activePermutation),
2547
+ ...themeAttrs(cssVarPrefix, activeTheme),
2590
2548
  children: /* @__PURE__ */ jsx("div", {
2591
2549
  className: "sb-block__empty",
2592
2550
  children: "No shadow tokens match this filter."
2593
2551
  })
2594
2552
  });
2595
2553
  return /* @__PURE__ */ jsxs("div", {
2596
- ...themeAttrs(cssVarPrefix, activePermutation),
2554
+ ...themeAttrs(cssVarPrefix, activeTheme),
2597
2555
  children: [/* @__PURE__ */ jsx("div", {
2598
2556
  className: "sb-block__caption",
2599
2557
  children: captionText
@@ -2676,11 +2634,11 @@ function extractCssStyle(value) {
2676
2634
  }
2677
2635
  function StrokeStyleSample({ filter, caption, sortBy = "path", sortDir = "asc" }) {
2678
2636
  const project = useProject();
2679
- const { resolved, activePermutation, cssVarPrefix } = project;
2637
+ const { resolved, activeTheme, cssVarPrefix } = project;
2680
2638
  const rows = useMemo(() => {
2681
2639
  return sortTokens(Object.entries(resolved).filter(([path, token]) => {
2682
2640
  if (token.$type !== "strokeStyle") return false;
2683
- return globMatch(path, filter);
2641
+ return matchPath(path, filter);
2684
2642
  }), {
2685
2643
  by: sortBy,
2686
2644
  dir: sortDir
@@ -2697,16 +2655,16 @@ function StrokeStyleSample({ filter, caption, sortBy = "path", sortDir = "asc" }
2697
2655
  sortBy,
2698
2656
  sortDir
2699
2657
  ]);
2700
- const captionText = caption ?? `${rows.length} strokeStyle token${rows.length === 1 ? "" : "s"}${filter && filter !== "strokeStyle" ? ` matching \`${filter}\`` : ""} · ${activePermutation}`;
2658
+ const captionText = caption ?? `${rows.length} strokeStyle token${rows.length === 1 ? "" : "s"}${filter && filter !== "strokeStyle" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
2701
2659
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
2702
- ...themeAttrs(cssVarPrefix, activePermutation),
2660
+ ...themeAttrs(cssVarPrefix, activeTheme),
2703
2661
  children: /* @__PURE__ */ jsx("div", {
2704
2662
  className: "sb-block__empty",
2705
2663
  children: "No strokeStyle tokens match this filter."
2706
2664
  })
2707
2665
  });
2708
2666
  return /* @__PURE__ */ jsxs("div", {
2709
- ...themeAttrs(cssVarPrefix, activePermutation),
2667
+ ...themeAttrs(cssVarPrefix, activeTheme),
2710
2668
  children: [/* @__PURE__ */ jsx("div", {
2711
2669
  className: "sb-block__caption",
2712
2670
  children: captionText
@@ -2743,19 +2701,19 @@ function StrokeStyleSample({ filter, caption, sortBy = "path", sortDir = "asc" }
2743
2701
  //#region src/token-detail/internal.ts
2744
2702
  function useTokenDetailData(path) {
2745
2703
  const project = useProject();
2746
- const { activePermutation, activeAxes, axes, resolved, cssVarPrefix, varianceByPath, resolveAt, permutationNameForTuple } = project;
2704
+ const { activeTheme, activeAxes, axes, resolved, cssVarPrefix, varianceByPath, resolveAt, themeNameForTuple } = project;
2747
2705
  const typedResolved = resolved;
2748
2706
  return {
2749
2707
  token: typedResolved[path],
2750
2708
  cssVar: resolveCssVar(path, project),
2751
- activePermutation,
2709
+ activeTheme,
2752
2710
  activeAxes,
2753
2711
  axes,
2754
2712
  resolved: typedResolved,
2755
2713
  cssVarPrefix,
2756
2714
  varianceByPath,
2757
2715
  resolveAt,
2758
- permutationNameForTuple
2716
+ themeNameForTuple
2759
2717
  };
2760
2718
  }
2761
2719
  //#endregion
@@ -2769,7 +2727,7 @@ function AliasChain({ path }) {
2769
2727
  return [path];
2770
2728
  }, [token, path]);
2771
2729
  if (chain.length <= 1) return null;
2772
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
2730
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
2773
2731
  className: "sb-token-detail__section-header",
2774
2732
  children: "Alias chain"
2775
2733
  }), /* @__PURE__ */ jsx("div", {
@@ -2798,7 +2756,7 @@ function AliasedBy({ path }) {
2798
2756
  const tree = useMemo(() => buildAliasedByTree(path, resolved), [path, resolved]);
2799
2757
  const truncated = useMemo(() => treeHasTruncation(tree), [tree]);
2800
2758
  if (tree.length === 0) return null;
2801
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
2759
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2802
2760
  /* @__PURE__ */ jsx("div", {
2803
2761
  className: "sb-token-detail__section-header",
2804
2762
  children: "Aliased by"
@@ -2880,26 +2838,31 @@ function treeHasTruncation(nodes) {
2880
2838
  //#endregion
2881
2839
  //#region src/token-detail/AxisVariance.tsx
2882
2840
  function AxisVariance({ path }) {
2883
- const { token, cssVar, axes, activeAxes, cssVarPrefix, varianceByPath, resolveAt, permutationNameForTuple } = useTokenDetailData(path);
2841
+ const { token, cssVar, axes, activeAxes, cssVarPrefix, varianceByPath, resolveAt, themeNameForTuple } = useTokenDetailData(path);
2884
2842
  const colorFormat = useColorFormat();
2885
2843
  const tokenType = token?.$type;
2886
2844
  const isColor = tokenType === "color";
2887
2845
  const formatFn = (t) => valueFor(t, tokenType, colorFormat);
2888
2846
  const variance = useMemo(() => {
2889
2847
  const result = varianceByPath[path];
2890
- if (!result) return {
2891
- kind: "constant",
2892
- varyingAxes: []
2893
- };
2894
- return {
2895
- kind: result.kind === "constant" ? "constant" : result.kind === "single" ? "one-axis" : "multi-axis",
2896
- varyingAxes: result.varyingAxes
2897
- };
2848
+ if (!result) return { kind: "constant" };
2849
+ switch (result.kind) {
2850
+ case "constant": return { kind: "constant" };
2851
+ case "single": return {
2852
+ kind: "one-axis",
2853
+ axis: result.axis,
2854
+ varyingAxes: result.varyingAxes
2855
+ };
2856
+ case "multi": return {
2857
+ kind: "multi-axis",
2858
+ varyingAxes: result.varyingAxes
2859
+ };
2860
+ }
2898
2861
  }, [path, varianceByPath]);
2899
- if (axes.length === 0) return /* @__PURE__ */ jsx(Fragment$1, {});
2862
+ if (axes.length === 0) return /* @__PURE__ */ jsx(Fragment, {});
2900
2863
  if (variance.kind === "constant") {
2901
2864
  const value = formatFn(resolveAt(activeAxes)[path]);
2902
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
2865
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
2903
2866
  className: "sb-token-detail__section-header",
2904
2867
  children: "Values across axes"
2905
2868
  }), /* @__PURE__ */ jsx("table", {
@@ -2930,10 +2893,9 @@ function AxisVariance({ path }) {
2930
2893
  })] });
2931
2894
  }
2932
2895
  if (variance.kind === "one-axis") {
2933
- const axisName = variance.varyingAxes[0];
2934
- if (!axisName) return /* @__PURE__ */ jsx(Fragment$1, {});
2896
+ const axisName = variance.axis;
2935
2897
  const axis = axes.find((a) => a.name === axisName);
2936
- if (!axis) return /* @__PURE__ */ jsx(Fragment$1, {});
2898
+ if (!axis) return /* @__PURE__ */ jsx(Fragment, {});
2937
2899
  const contextValues = axis.contexts.map((ctx) => {
2938
2900
  const target = {
2939
2901
  ...activeAxes,
@@ -2941,11 +2903,11 @@ function AxisVariance({ path }) {
2941
2903
  };
2942
2904
  return {
2943
2905
  ctx,
2944
- themeName: permutationNameForTuple(target) ?? "",
2906
+ themeName: themeNameForTuple(target) ?? "",
2945
2907
  value: formatFn(resolveAt(target)[path])
2946
2908
  };
2947
2909
  });
2948
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
2910
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
2949
2911
  className: "sb-token-detail__section-header",
2950
2912
  children: ["Varies with ", axisName]
2951
2913
  }), /* @__PURE__ */ jsx("table", {
@@ -2972,8 +2934,8 @@ function AxisVariance({ path }) {
2972
2934
  })] });
2973
2935
  }
2974
2936
  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);
2975
- if (!rowAxis || !colAxis) return /* @__PURE__ */ jsx(Fragment$1, {});
2976
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
2937
+ if (!rowAxis || !colAxis) return /* @__PURE__ */ jsx(Fragment, {});
2938
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2977
2939
  /* @__PURE__ */ jsxs("div", {
2978
2940
  className: "sb-token-detail__section-header",
2979
2941
  children: ["Varies with ", variance.varyingAxes.join(" × ")]
@@ -3013,7 +2975,7 @@ function AxisVariance({ path }) {
3013
2975
  [rowAxis.name]: row,
3014
2976
  [colAxis.name]: col
3015
2977
  };
3016
- const name = permutationNameForTuple(target);
2978
+ const name = themeNameForTuple(target);
3017
2979
  const value = formatFn(resolveAt(target)[path]);
3018
2980
  return /* @__PURE__ */ jsxs("td", {
3019
2981
  className: "sb-token-detail__theme-cell",
@@ -3213,7 +3175,7 @@ function renderKeyValueList(rows) {
3213
3175
  }
3214
3176
  function KeyValueRow({ label, value, alias }) {
3215
3177
  const hasAlias = alias && alias.length > 0;
3216
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
3178
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
3217
3179
  className: "sb-token-detail__breakdown-key",
3218
3180
  children: label
3219
3181
  }), /* @__PURE__ */ jsxs("span", {
@@ -3472,7 +3434,7 @@ function ConsumerOutput({ path }) {
3472
3434
  const tupleLabel = Object.entries(activeAxes).map(([k, v]) => `${k}=${v}`).join(", ");
3473
3435
  const names = listing[path]?.names ?? {};
3474
3436
  const extraPlatforms = Object.keys(names).filter((platform) => platform !== "css" && names[platform]).toSorted();
3475
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
3437
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3476
3438
  /* @__PURE__ */ jsx("div", {
3477
3439
  className: "sb-token-detail__section-header",
3478
3440
  children: "Consumer output"
@@ -3550,18 +3512,18 @@ async function copyToClipboard(text) {
3550
3512
  //#endregion
3551
3513
  //#region src/token-detail/TokenHeader.tsx
3552
3514
  function TokenHeader({ path, heading }) {
3553
- const { token, cssVar, activePermutation } = useTokenDetailData(path);
3515
+ const { token, cssVar, activeTheme } = useTokenDetailData(path);
3554
3516
  if (!token) return /* @__PURE__ */ jsxs("div", {
3555
3517
  className: "sb-token-detail__missing",
3556
3518
  children: [
3557
3519
  "Token ",
3558
3520
  /* @__PURE__ */ jsx("code", { children: path }),
3559
3521
  " not found in theme ",
3560
- /* @__PURE__ */ jsx("strong", { children: activePermutation }),
3522
+ /* @__PURE__ */ jsx("strong", { children: activeTheme }),
3561
3523
  "."
3562
3524
  ]
3563
3525
  });
3564
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
3526
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3565
3527
  /* @__PURE__ */ jsx("h3", {
3566
3528
  className: "sb-token-detail__heading",
3567
3529
  children: heading ?? path
@@ -3585,7 +3547,7 @@ function TokenUsageSnippet({ path }) {
3585
3547
  const { token, cssVar } = useTokenDetailData(path);
3586
3548
  if (!token) return null;
3587
3549
  const snippet = `color: ${cssVar};`;
3588
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
3550
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
3589
3551
  className: "sb-token-detail__section-header",
3590
3552
  children: "Usage"
3591
3553
  }), /* @__PURE__ */ jsxs("div", {
@@ -3602,9 +3564,9 @@ function TokenUsageSnippet({ path }) {
3602
3564
  //#endregion
3603
3565
  //#region src/TokenDetail.tsx
3604
3566
  function TokenDetail({ path, heading }) {
3605
- const { token, cssVar, activePermutation, cssVarPrefix } = useTokenDetailData(path);
3567
+ const { token, cssVar, activeTheme, cssVarPrefix } = useTokenDetailData(path);
3606
3568
  const colorFormat = useColorFormat();
3607
- const theme = themeAttrs(cssVarPrefix, activePermutation);
3569
+ const theme = themeAttrs(cssVarPrefix, activeTheme);
3608
3570
  if (!token) return /* @__PURE__ */ jsx("div", {
3609
3571
  ...theme,
3610
3572
  className: cx(theme["className"], "sb-token-detail"),
@@ -3614,7 +3576,7 @@ function TokenDetail({ path, heading }) {
3614
3576
  "Token ",
3615
3577
  /* @__PURE__ */ jsx("code", { children: path }),
3616
3578
  " not found in theme ",
3617
- /* @__PURE__ */ jsx("strong", { children: activePermutation }),
3579
+ /* @__PURE__ */ jsx("strong", { children: activeTheme }),
3618
3580
  "."
3619
3581
  ]
3620
3582
  })
@@ -3634,7 +3596,7 @@ function TokenDetail({ path, heading }) {
3634
3596
  }),
3635
3597
  /* @__PURE__ */ jsxs("div", {
3636
3598
  className: "sb-token-detail__section-header",
3637
- children: ["Resolved value · ", activePermutation]
3599
+ children: ["Resolved value · ", activeTheme]
3638
3600
  }),
3639
3601
  /* @__PURE__ */ jsx(CompositePreview, { path }),
3640
3602
  /* @__PURE__ */ jsx(CompositeBreakdown, { path }),
@@ -3775,6 +3737,7 @@ function buildTree(resolved, root, typeFilter) {
3775
3737
  let node = rootNode;
3776
3738
  for (let i = 0; i < segments.length - 1; i += 1) {
3777
3739
  const seg = segments[i];
3740
+ if (seg === void 0) continue;
3778
3741
  const prefix = [...rootSegments, ...segments.slice(0, i + 1)].join(".");
3779
3742
  let child = node.children.find((c) => c.kind === "group" && c.segment === seg);
3780
3743
  if (!child) {
@@ -3862,7 +3825,7 @@ function pruneTreeForMatches(nodes, matches, expandOut) {
3862
3825
  return out;
3863
3826
  }
3864
3827
  function TokenNavigator({ root, type, initiallyExpanded = 1, searchable = true, onSelect }) {
3865
- const { resolved, activePermutation, cssVarPrefix } = useProject();
3828
+ const { resolved, activeTheme, cssVarPrefix } = useProject();
3866
3829
  const typeFilter = useMemo(() => {
3867
3830
  if (type === void 0) return void 0;
3868
3831
  return new Set(Array.isArray(type) ? type : [type]);
@@ -4047,11 +4010,11 @@ function TokenNavigator({ root, type, initiallyExpanded = 1, searchable = true,
4047
4010
  return n;
4048
4011
  }, [visibleTree, searchExpanded]);
4049
4012
  if (tree.length === 0) return /* @__PURE__ */ jsx("div", {
4050
- ...themeAttrs(cssVarPrefix, activePermutation),
4013
+ ...themeAttrs(cssVarPrefix, activeTheme),
4051
4014
  children: /* @__PURE__ */ jsx(EmptyState, { children: root ? `No tokens under "${root}"${typeFilter ? ` matching ${typeLabel.slice(3)}` : ""}.` : typeFilter ? `No tokens matching ${typeLabel.slice(3)} in the active theme.` : "No tokens in the active theme." })
4052
4015
  });
4053
4016
  return /* @__PURE__ */ jsxs("div", {
4054
- ...themeAttrs(cssVarPrefix, activePermutation),
4017
+ ...themeAttrs(cssVarPrefix, activeTheme),
4055
4018
  children: [
4056
4019
  searchable && /* @__PURE__ */ jsx("div", {
4057
4020
  className: "sb-token-navigator__search",
@@ -4071,9 +4034,8 @@ function TokenNavigator({ root, type, initiallyExpanded = 1, searchable = true,
4071
4034
  root ? `Tokens under ${root}` : "Token graph",
4072
4035
  typeLabel,
4073
4036
  trimmedQuery !== "" ? ` · ${matchCount} matching "${trimmedQuery}"` : "",
4074
- " ·",
4075
- " ",
4076
- activePermutation
4037
+ " · ",
4038
+ activeTheme
4077
4039
  ]
4078
4040
  }),
4079
4041
  visibleTree.length === 0 ? /* @__PURE__ */ jsxs("div", {
@@ -4261,13 +4223,13 @@ function LeafPreview({ path, token }) {
4261
4223
  //#region src/TokenTable.tsx
4262
4224
  function TokenTable({ filter, type, caption, sortBy = "path", sortDir = "asc", searchable = true, onSelect }) {
4263
4225
  const project = useProject();
4264
- const { resolved, activePermutation, cssVarPrefix } = project;
4226
+ const { resolved, activeTheme, cssVarPrefix } = project;
4265
4227
  const colorFormat = useColorFormat();
4266
4228
  const [selectedPath, setSelectedPath] = useState(null);
4267
4229
  const [query, setQuery] = useState("");
4268
4230
  const rows = useMemo(() => {
4269
4231
  return sortTokens(Object.entries(resolved).filter(([path, token]) => {
4270
- if (!globMatch(path, filter)) return false;
4232
+ if (!matchPath(path, filter)) return false;
4271
4233
  if (type && token.$type !== type) return false;
4272
4234
  return true;
4273
4235
  }), {
@@ -4307,16 +4269,16 @@ function TokenTable({ filter, type, caption, sortBy = "path", sortDir = "asc", s
4307
4269
  else setSelectedPath(path);
4308
4270
  }, [onSelect]);
4309
4271
  const matchSuffix = searchable && query.trim() !== "" ? ` · ${visibleRows.length} matching "${query.trim()}"` : "";
4310
- const captionText = caption ?? `${rows.length} token${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""}${type ? ` · $type=${type}` : ""}${matchSuffix} · ${activePermutation}`;
4272
+ const captionText = caption ?? `${rows.length} token${rows.length === 1 ? "" : "s"}${filter ? ` matching \`${filter}\`` : ""}${type ? ` · $type=${type}` : ""}${matchSuffix} · ${activeTheme}`;
4311
4273
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
4312
- ...themeAttrs(cssVarPrefix, activePermutation),
4274
+ ...themeAttrs(cssVarPrefix, activeTheme),
4313
4275
  children: /* @__PURE__ */ jsx("div", {
4314
4276
  className: "sb-block__empty",
4315
4277
  children: "No tokens match this filter."
4316
4278
  })
4317
4279
  });
4318
4280
  return /* @__PURE__ */ jsxs("div", {
4319
- ...themeAttrs(cssVarPrefix, activePermutation),
4281
+ ...themeAttrs(cssVarPrefix, activeTheme),
4320
4282
  children: [
4321
4283
  searchable && /* @__PURE__ */ jsx("div", {
4322
4284
  className: "sb-token-table__search",
@@ -4456,11 +4418,11 @@ function buildRow(path, composite) {
4456
4418
  };
4457
4419
  }
4458
4420
  function TypographyScale({ filter, sample = "The quick brown fox jumps over the lazy dog.", caption, sortBy = "path", sortDir = "asc" }) {
4459
- const { resolved, activePermutation, cssVarPrefix } = useProject();
4421
+ const { resolved, activeTheme, cssVarPrefix } = useProject();
4460
4422
  const rows = useMemo(() => {
4461
4423
  return sortTokens(Object.entries(resolved).filter(([path, token]) => {
4462
4424
  if (token.$type !== "typography") return false;
4463
- return globMatch(path, filter);
4425
+ return matchPath(path, filter);
4464
4426
  }), {
4465
4427
  by: sortBy,
4466
4428
  dir: sortDir
@@ -4479,16 +4441,16 @@ function TypographyScale({ filter, sample = "The quick brown fox jumps over the
4479
4441
  sortBy,
4480
4442
  sortDir
4481
4443
  ]);
4482
- const captionText = caption ?? `${rows.length} typography token${rows.length === 1 ? "" : "s"}${filter && filter !== "typography" ? ` matching \`${filter}\`` : ""} · ${activePermutation}`;
4444
+ const captionText = caption ?? `${rows.length} typography token${rows.length === 1 ? "" : "s"}${filter && filter !== "typography" ? ` matching \`${filter}\`` : ""} · ${activeTheme}`;
4483
4445
  if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
4484
- ...themeAttrs(cssVarPrefix, activePermutation),
4446
+ ...themeAttrs(cssVarPrefix, activeTheme),
4485
4447
  children: /* @__PURE__ */ jsx("div", {
4486
4448
  className: "sb-block__empty",
4487
4449
  children: "No typography tokens match this filter."
4488
4450
  })
4489
4451
  });
4490
4452
  return /* @__PURE__ */ jsxs("div", {
4491
- ...themeAttrs(cssVarPrefix, activePermutation),
4453
+ ...themeAttrs(cssVarPrefix, activeTheme),
4492
4454
  children: [/* @__PURE__ */ jsx("div", {
4493
4455
  className: "sb-block__caption",
4494
4456
  children: captionText
@@ -4511,6 +4473,6 @@ function TypographyScale({ filter, sample = "The quick brown fox jumps over the
4511
4473
  });
4512
4474
  }
4513
4475
  //#endregion
4514
- export { AliasChain, AliasedBy, AxesContext, AxisVariance, BorderPreview, BorderSample, COLOR_FORMATS, ColorFormatContext, ColorPalette, ColorTable, CompositeBreakdown, CompositePreview, ConsumerOutput, Diagnostics, DimensionBar, DimensionScale, FontFamilySample, FontWeightScale, GradientPalette, MotionPreview, MotionSample, OpacityScale, PermutationContext, ShadowPreview, ShadowSample, StrokeStyleSample, SwatchbookContext, SwatchbookProvider, TokenDetail, TokenHeader, TokenNavigator, TokenTable, TokenUsageSnippet, TypographyScale, formatColor, useActiveAxes, useActivePermutation, useColorFormat, useOptionalSwatchbookData, useSwatchbookData };
4476
+ export { AliasChain, AliasedBy, AxesContext, AxisVariance, BorderPreview, BorderSample, COLOR_FORMATS, ColorFormatContext, ColorPalette, ColorTable, CompositeBreakdown, CompositePreview, ConsumerOutput, Diagnostics, DimensionBar, DimensionScale, FontFamilySample, FontWeightScale, GradientPalette, MotionPreview, MotionSample, OpacityScale, ShadowPreview, ShadowSample, StrokeStyleSample, SwatchbookContext, SwatchbookProvider, ThemeContext, TokenDetail, TokenHeader, TokenNavigator, TokenTable, TokenUsageSnippet, TypographyScale, formatColor, useActiveAxes, useActiveTheme, useColorFormat, useOptionalSwatchbookData, useSwatchbookData };
4515
4477
 
4516
4478
  //# sourceMappingURL=index.mjs.map