@unpunnyfuns/swatchbook-blocks 0.57.0 → 0.58.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["snapshot","listeners","subscribed","ensureSubscribed","subscribe","getSnapshot","initialAxes","initialPresets","initialDiagnostics","initialCss","initialCssVarPrefix","initialListing","initialCells","initialJointOverrides","initialVarianceByPath","initialDefaultTuple","defaultTuple","sampleStyle","formatDimension","formatSubColor","CopyButton","CopyButton","MAX_RENDER_PX","styles","toPixels","formatDimension","formatFontFamily","formatPrimitive","CopyButton","CopyButton","CopyButton"],"sources":["../src/format-color.ts","../src/internal/styles.tsx","../src/internal/channel-globals.ts","../src/contexts.ts","../src/internal/channel-tokens.ts","../src/internal/use-project.ts","../src/border-preview/BorderSample.tsx","../src/internal/data-attr.ts","../src/internal/sort-tokens.ts","../src/BorderPreview.tsx","../src/ColorPalette.tsx","../src/internal/CopyButton.tsx","../src/ColorTable.tsx","../src/Diagnostics.tsx","../src/dimension-scale/DimensionBar.tsx","../src/internal/format-token-value.ts","../src/DimensionScale.tsx","../src/FontFamilySample.tsx","../src/internal/css-var-style.ts","../src/FontWeightScale.tsx","../src/GradientPalette.tsx","../src/internal/prefers-reduced-motion.ts","../src/motion-preview/MotionSample.tsx","../src/MotionPreview.tsx","../src/OpacityScale.tsx","../src/provider.tsx","../src/shadow-preview/ShadowSample.tsx","../src/ShadowPreview.tsx","../src/StrokeStyleSample.tsx","../src/token-detail/internal.ts","../src/token-detail/AliasChain.tsx","../src/token-detail/AliasedBy.tsx","../src/token-detail/AxisVariance.tsx","../src/token-detail/CompositeBreakdown.tsx","../src/token-detail/CompositePreview.tsx","../src/token-detail/ConsumerOutput.tsx","../src/token-detail/TokenHeader.tsx","../src/token-detail/TokenUsageSnippet.tsx","../src/TokenDetail.tsx","../src/internal/DetailOverlay.tsx","../src/TokenNavigator.tsx","../src/TokenTable.tsx","../src/TypographyScale.tsx"],"sourcesContent":["import Color from 'colorjs.io';\nimport type { ColorValue } from '#/internal/composite-types.ts';\n\n/**\n * Color display formats understood by {@link formatColor}.\n *\n * - `hex` — sRGB hex (`#rrggbb` or `#rrggbbaa`). Out-of-gamut or wide-gamut\n * colors fall back to `rgb()` and surface `outOfGamut: true` so callers\n * can render a ⚠ glyph.\n * - `rgb` / `hsl` — modern CSS Color 4 space-separated syntax, converted\n * from the source colorspace. Out-of-gamut values are still stringified\n * (the browser will clip when actually rendering) and flagged.\n * - `oklch` — perceptual wide-gamut form. Never marks out-of-gamut because\n * every color expressible in sRGB/P3 fits in oklch.\n * - `raw` — compact JSON of the normalized Terrazzo shape. For DTCG\n * authors who want to see what the parser actually stored.\n */\nexport type ColorFormat = 'hex' | 'rgb' | 'hsl' | 'oklch' | 'raw';\n\nexport const COLOR_FORMATS: readonly ColorFormat[] = ['hex', 'rgb', 'hsl', 'oklch', 'raw'];\n\n/**\n * Terrazzo's `ColorValueNormalized`, copied inline to avoid a hard dep on\n * `@terrazzo/token-tools` from blocks. Matches the shape documented at\n * https://terrazzo.app/docs/cli/reference/token-tools/ColorValueNormalized.\n *\n * Some token payloads we see in the wild use the legacy DTCG-ish `channels`\n * field in place of `components`; we accept either.\n */\nexport interface NormalizedColor {\n colorSpace: string;\n components?: readonly (number | null)[];\n channels?: readonly (number | null)[];\n alpha?: number;\n hex?: string;\n}\n\nexport interface FormatColorResult {\n /** Display string — e.g. `rgb(59 132 246)`, `#3b82f6`. */\n value: string;\n /** True when the requested format can't losslessly represent the color. */\n outOfGamut: boolean;\n}\n\nconst DEFAULT_FALLBACK = '—';\n\n/**\n * Convert Terrazzo's normalized color payload into a display string in the\n * requested format. Pure function — never throws; returns `{ value: '—' }`\n * for unrecognized input so calling blocks don't need try/catch.\n */\nexport function formatColor(\n value: unknown,\n format: ColorFormat,\n fallback: string = DEFAULT_FALLBACK,\n): FormatColorResult {\n const normalized = coerce(value);\n if (!normalized) return { value: stringifyFallback(value, fallback), outOfGamut: false };\n\n if (format === 'raw') {\n return { value: compactJson(normalized), outOfGamut: false };\n }\n\n const color = toColor(normalized);\n if (!color) return { value: stringifyFallback(value, fallback), outOfGamut: false };\n\n const alpha = typeof normalized.alpha === 'number' ? normalized.alpha : 1;\n\n if (format === 'hex') return formatHex(color, alpha);\n if (format === 'rgb') return formatRgb(color, alpha);\n if (format === 'hsl') return formatHsl(color, alpha);\n return formatOklch(color, alpha);\n}\n\nfunction coerce(value: unknown): NormalizedColor | null {\n if (!value || typeof value !== 'object') return null;\n const v = value as ColorValue;\n const colorSpace = typeof v.colorSpace === 'string' ? v.colorSpace : undefined;\n const components = Array.isArray(v.components)\n ? (v.components as (number | null)[])\n : Array.isArray(v.channels)\n ? (v.channels as (number | null)[])\n : undefined;\n if (!colorSpace || !components) {\n if (typeof v.hex === 'string') {\n return { colorSpace: 'srgb', components: hexToComponents(v.hex) };\n }\n return null;\n }\n const alpha = typeof v.alpha === 'number' ? v.alpha : undefined;\n const hexVal = v['hex'];\n const hex = typeof hexVal === 'string' ? hexVal : undefined;\n return {\n colorSpace,\n components,\n ...(alpha !== undefined && { alpha }),\n ...(hex !== undefined && { hex }),\n };\n}\n\nfunction hexToComponents(hex: string): number[] {\n const h = hex.replace('#', '');\n const expanded =\n h.length === 3 || h.length === 4\n ? h\n .split('')\n .map((c) => c + c)\n .join('')\n : h;\n const r = parseInt(expanded.slice(0, 2), 16) / 255;\n const g = parseInt(expanded.slice(2, 4), 16) / 255;\n const b = parseInt(expanded.slice(4, 6), 16) / 255;\n return [r, g, b];\n}\n\n/**\n * Map Terrazzo's canonical CSS Color 4 space identifiers to the shorter\n * identifiers colorjs.io registers. Only the ones that differ need an entry.\n */\nconst COLORJS_SPACE_ALIASES: Record<string, string> = {\n 'display-p3': 'p3',\n 'a98-rgb': 'a98rgb',\n 'prophoto-rgb': 'prophoto',\n};\n\nfunction toColor(normalized: NormalizedColor): Color | null {\n const source = normalized.components ?? normalized.channels ?? [];\n const coords: [number, number, number] = [\n numberOrZero(source[0]),\n numberOrZero(source[1]),\n numberOrZero(source[2]),\n ];\n const space = COLORJS_SPACE_ALIASES[normalized.colorSpace] ?? normalized.colorSpace;\n try {\n return new Color(space, coords, normalized.alpha ?? 1);\n } catch {\n return null;\n }\n}\n\nfunction numberOrZero(n: number | null | undefined): number {\n return typeof n === 'number' && !Number.isNaN(n) ? n : 0;\n}\n\nfunction coord(color: Color, i: number): number {\n const c = color.coords[i];\n return typeof c === 'number' && !Number.isNaN(c) ? c : 0;\n}\n\nfunction formatHex(color: Color, alpha: number): FormatColorResult {\n const srgb = color.to('srgb');\n const inGamut = srgb.inGamut('srgb');\n if (!inGamut) {\n const rgb = formatRgb(color, alpha);\n return { value: rgb.value, outOfGamut: true };\n }\n const r = clamp255(coord(srgb, 0));\n const g = clamp255(coord(srgb, 1));\n const b = clamp255(coord(srgb, 2));\n const base = `#${toHexByte(r)}${toHexByte(g)}${toHexByte(b)}`;\n if (alpha >= 1) return { value: base, outOfGamut: false };\n const a = clamp255(alpha);\n return { value: `${base}${toHexByte(a)}`, outOfGamut: false };\n}\n\nfunction formatRgb(color: Color, alpha: number): FormatColorResult {\n const srgb = color.to('srgb');\n const inGamut = srgb.inGamut('srgb');\n const r = Math.round(clampUnit(coord(srgb, 0)) * 255);\n const g = Math.round(clampUnit(coord(srgb, 1)) * 255);\n const b = Math.round(clampUnit(coord(srgb, 2)) * 255);\n const body = `${r} ${g} ${b}`;\n const value = alpha >= 1 ? `rgb(${body})` : `rgb(${body} / ${roundAlpha(alpha)})`;\n return { value, outOfGamut: !inGamut };\n}\n\nfunction formatHsl(color: Color, alpha: number): FormatColorResult {\n const hsl = color.to('hsl');\n const srgb = color.to('srgb');\n const inGamut = srgb.inGamut('srgb');\n const hue = roundHue(coord(hsl, 0));\n const sat = roundPercent(coord(hsl, 1));\n const light = roundPercent(coord(hsl, 2));\n const body = `${hue} ${sat}% ${light}%`;\n const value = alpha >= 1 ? `hsl(${body})` : `hsl(${body} / ${roundAlpha(alpha)})`;\n return { value, outOfGamut: !inGamut };\n}\n\nfunction formatOklch(color: Color, alpha: number): FormatColorResult {\n const oklch = color.to('oklch');\n const L = roundTo(coord(oklch, 0), 3);\n const C = roundTo(coord(oklch, 1), 3);\n const H = roundTo(coord(oklch, 2), 2);\n const body = `${L} ${C} ${H}`;\n const value = alpha >= 1 ? `oklch(${body})` : `oklch(${body} / ${roundAlpha(alpha)})`;\n return { value, outOfGamut: false };\n}\n\nfunction clamp255(n: number): number {\n return Math.max(0, Math.min(255, Math.round(n * 255)));\n}\n\nfunction clampUnit(n: number): number {\n return Math.max(0, Math.min(1, n));\n}\n\nfunction toHexByte(n: number): string {\n return n.toString(16).padStart(2, '0');\n}\n\nfunction roundTo(n: number, digits: number): number {\n const f = 10 ** digits;\n return Math.round(n * f) / f;\n}\n\nfunction roundHue(h: number): number {\n return roundTo(((h % 360) + 360) % 360, 1);\n}\n\nfunction roundPercent(n: number): number {\n return Math.round(n * 10) / 10;\n}\n\nfunction roundAlpha(a: number): number {\n return roundTo(a, 3);\n}\n\nfunction compactJson(value: NormalizedColor): string {\n const parts: string[] = [`\"colorSpace\":${JSON.stringify(value.colorSpace)}`];\n const components = value.components ?? value.channels;\n if (components) {\n parts.push(`\"components\":[${components.map((c) => (c === null ? 'null' : c)).join(', ')}]`);\n }\n if (typeof value.alpha === 'number' && value.alpha !== 1) {\n parts.push(`\"alpha\":${value.alpha}`);\n }\n return `{ ${parts.join(', ')} }`;\n}\n\nfunction stringifyFallback(value: unknown, fallback: string): string {\n if (value == null) return fallback;\n if (typeof value === 'string' || typeof value === 'number') return String(value);\n return fallback;\n}\n","import type { CSSProperties, ReactElement, ReactNode } from 'react';\n\n/**\n * Chrome-style primitives shared across every block. Kept as JS exports\n * for the inline-style sites that still compose them into per-block style\n * objects (e.g. TokenNavigator's `typePill` that builds on the shared\n * pill base). The pure direct-reference chrome — surface wrapper, caption,\n * empty-state — lives in `styles.css` and is applied via class names.\n */\n\nexport const TEXT_DEFAULT = 'var(--swatchbook-text-default, CanvasText)';\nexport const TEXT_MUTED = 'var(--swatchbook-text-muted, CanvasText)';\n\nexport const SURFACE_DEFAULT = 'var(--swatchbook-surface-default, Canvas)';\nexport const SURFACE_RAISED = 'var(--swatchbook-surface-raised, Canvas)';\nexport const SURFACE_MUTED = 'var(--swatchbook-surface-muted, rgba(128,128,128,0.15))';\n\nexport const BORDER_DEFAULT = `1px solid var(--swatchbook-border-default, rgba(128,128,128,0.2))`;\nexport const BORDER_FAINT = `1px solid var(--swatchbook-border-default, rgba(128,128,128,0.15))`;\nexport const BORDER_STRONG = `1px solid var(--swatchbook-border-default, rgba(128,128,128,0.3))`;\n\nexport const SIZE_PILL = 10;\n\nexport const typePillStyle = {\n display: 'inline-block',\n padding: '2px 6px',\n borderRadius: 4,\n fontSize: SIZE_PILL,\n letterSpacing: 0.5,\n textTransform: 'uppercase',\n background: SURFACE_MUTED,\n} satisfies CSSProperties;\n\n/**\n * Inner content for a block's \"nothing to render\" state. Call sites wrap\n * it in their own block wrapper (which already carries `themeAttrs`), so\n * the message itself just needs the muted type.\n */\nexport function EmptyState({ children }: { children: ReactNode }): ReactElement {\n return <div className=\"sb-block__empty\">{children}</div>;\n}\n","import { useSyncExternalStore } from 'react';\nimport { addons } from 'storybook/preview-api';\nimport { COLOR_FORMATS } from '#/format-color.ts';\nimport type { ColorFormat } from '#/format-color.ts';\n\n/**\n * Shared subscription to Storybook's globals channel, lifted out of React\n * component state so the values survive docs-mode remounts.\n *\n * On MDX docs pages, Storybook force-rerenders the docs container on every\n * `updateGlobals` (see `preview/runtime.js` → `onUpdateGlobals`), which\n * unmounts and remounts any embedded blocks. A `useState(null)` initializer\n * inside the block would reset to null on each remount — the symptom is a\n * one-frame flicker to the correct value, then revert to the defaults.\n * Module-level state persists; React reads it through `useSyncExternalStore`\n * and stays concurrent-safe.\n */\n\nexport interface ChannelGlobals {\n axes: Record<string, string> | null;\n format: ColorFormat | null;\n}\n\nconst AXES_GLOBAL_KEY = 'swatchbookAxes';\nconst COLOR_FORMAT_GLOBAL_KEY = 'swatchbookColorFormat';\n\nlet snapshot: ChannelGlobals = { axes: null, format: null };\nconst listeners = new Set<() => void>();\nlet subscribed = false;\n\nfunction isColorFormat(value: unknown): value is ColorFormat {\n return typeof value === 'string' && (COLOR_FORMATS as readonly string[]).includes(value);\n}\n\ninterface SwatchbookGlobalsPayload {\n swatchbookAxes?: Record<string, string>;\n swatchbookColorFormat?: ColorFormat;\n [key: string]: unknown;\n}\n\nfunction ensureSubscribed(): void {\n if (subscribed || typeof window === 'undefined') return;\n subscribed = true;\n const channel = addons.getChannel();\n // Storybook fires `globalsUpdated`, `setGlobals`, and `updateGlobals`\n // for the same logical change (preview init + every toolbar tick).\n // Subscribing to all three is intentional — `setGlobals` carries the\n // initial URL-persisted globals; `updateGlobals` is the toolbar\n // signal; `globalsUpdated` is the cross-frame echo. The handler runs\n // for each but content-deduplicates: we only update the shared\n // snapshot when axes or format actually shifted (the previous\n // identity-based spread guard fired three times per tick because each\n // spread produced a new object identity even with unchanged content).\n let lastFingerprint = '';\n const onGlobals = (payload: { globals?: SwatchbookGlobalsPayload }): void => {\n const globals = payload.globals;\n if (!globals) return;\n const incomingAxes = globals[AXES_GLOBAL_KEY];\n const incomingFormat = globals[COLOR_FORMAT_GLOBAL_KEY];\n const nextAxes =\n incomingAxes && typeof incomingAxes === 'object' ? incomingAxes : snapshot.axes;\n const nextFormat = isColorFormat(incomingFormat) ? incomingFormat : snapshot.format;\n const fingerprint = `${nextFormat ?? ''}|${nextAxes ? JSON.stringify(nextAxes) : ''}`;\n if (fingerprint === lastFingerprint) return;\n lastFingerprint = fingerprint;\n snapshot = { axes: nextAxes, format: nextFormat };\n for (const cb of listeners) cb();\n };\n channel.on('globalsUpdated', onGlobals);\n channel.on('updateGlobals', onGlobals);\n channel.on('setGlobals', onGlobals);\n}\n\n/**\n * Subscribe at module load so the `SET_GLOBALS` emission from preview init\n * lands in our snapshot before any block renders. Running `useSyncExternalStore`'s\n * `subscribe` lazily on first hook call would miss the event in most cases.\n */\nensureSubscribed();\n\nfunction subscribe(cb: () => void): () => void {\n ensureSubscribed();\n listeners.add(cb);\n return () => {\n listeners.delete(cb);\n };\n}\n\nfunction getSnapshot(): ChannelGlobals {\n return snapshot;\n}\n\nfunction getServerSnapshot(): ChannelGlobals {\n return snapshot;\n}\n\nexport function useChannelGlobals(): ChannelGlobals {\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n","import type { Axis, AxisVarianceResult, Diagnostic, Preset } from '@unpunnyfuns/swatchbook-core';\nimport type { SlimListedToken } from '@unpunnyfuns/swatchbook-core/snapshot-for-wire';\nimport { createContext, useContext } from 'react';\nimport { useChannelGlobals } from '#/internal/channel-globals.ts';\nimport type { ColorFormat } from '#/format-color.ts';\n\n/**\n * Typed shape of the addon's `virtual:swatchbook/tokens` module.\n *\n * The axis / permutation / diagnostic / preset entries are deliberate\n * type-aliases of core's authoritative shapes — the virtual module\n * publishes those shapes verbatim, so single-sourcing the types prevents\n * silent drift the moment core grows a field the plugin doesn't\n * serialise.\n *\n * Token / listing shapes stay as narrowed interfaces because blocks\n * only read a subset of Terrazzo's full token / listing structure; the\n * narrower shape documents what's actually relied on.\n *\n * The ambient `declare module 'virtual:swatchbook/tokens'` declarations\n * in `packages/addon/src/virtual.d.ts` describe the same payload.\n */\nexport type VirtualAxisShape = Axis;\n\nexport type VirtualDiagnosticShape = Diagnostic;\n\nexport interface VirtualTokenShape {\n $type?: string | undefined;\n $value?: unknown;\n $description?: string | undefined;\n aliasOf?: string | undefined;\n aliasChain?: readonly string[] | undefined;\n aliasedBy?: readonly string[] | undefined;\n /**\n * Per-sub-field alias map for composite tokens whose value blends\n * primitives with aliased fragments — Terrazzo populates this when\n * one or more component fields of a composite ($type: 'border',\n * 'shadow', 'typography', 'gradient', 'transition') resolve through\n * an alias. The `CompositeBreakdown` block reads it to render the\n * source path beside each component value. Typed as `unknown` because\n * the shape varies per composite type (color carries a\n * `{components: (string | undefined)[]}` sub-shape; typography/border\n * carry a flat `Record<string, string | undefined>`); the block\n * narrows it at the consumer.\n */\n partialAliasOf?: unknown;\n}\n\n/**\n * Subset of `@terrazzo/plugin-token-listing`'s `ListedToken` that the\n * snapshot carries. Blocks read `names.css` for the authoritative CSS\n * variable name and `previewValue` for the display-ready CSS string.\n * `source.loc` enables \"jump to authoring source\" affordances.\n *\n * Aliases `SlimListedToken` from core's `/snapshot-for-wire` subpath —\n * the single canonical wire shape; both the addon's plugin (server-side\n * emit) and blocks (consumer-side read) reference the same definition.\n */\nexport type VirtualTokenListingShape = SlimListedToken;\n\nexport type VirtualPresetShape = Preset;\n\n/**\n * Wire shape of one `Project.jointOverrides` entry — same as core's\n * `JointOverride` but with the block's `VirtualTokenShape` for the\n * token values that ship over the wire.\n */\nexport interface VirtualJointOverrideShape {\n axes: Record<string, string>;\n tokens: Record<string, VirtualTokenShape>;\n}\n\n/**\n * Map from path → cached `AxisVarianceResult`. Snapshot carries this\n * so the `AxisVariance` block can O(1) look up which axes affect a\n * token instead of re-running variance analysis on every render.\n */\nexport type VirtualVarianceByPathShape = Record<string, AxisVarianceResult>;\n\n/**\n * Full project data read by blocks. Populated by the addon's preview\n * decorator (from the virtual module) or constructed by hand in\n * non-Storybook consumers.\n */\nexport interface ProjectSnapshot {\n axes: readonly VirtualAxisShape[];\n /** Axis names suppressed via `config.disabledAxes` — pinned to their defaults, hidden from the toolbar. */\n disabledAxes: readonly string[];\n presets: readonly VirtualPresetShape[];\n activeTheme: string;\n activeAxes: Readonly<Record<string, string>>;\n cssVarPrefix: string;\n diagnostics: readonly VirtualDiagnosticShape[];\n css: string;\n /**\n * Path-indexed Token Listing data produced by\n * `@terrazzo/plugin-token-listing`. Blocks prefer reading authoritative\n * CSS var names and preview values from here; empty for non-resolver\n * projects. Treat as enrichment — fall back gracefully when a path is\n * absent.\n */\n listing?: Readonly<Record<string, VirtualTokenListingShape>>;\n /**\n * Per-axis cell maps — `cells[axis][context]` is the resolved token\n * data for `{ ...defaults, [axis]: context }`. Bounded by\n * `Σ(axes × contexts)` regardless of cartesian product size.\n * Non-default cells store only the tokens whose value differs from\n * the default-cell baseline (delta cells).\n */\n cells: Record<string, Record<string, Record<string, VirtualTokenShape>>>;\n /**\n * `Project.jointOverrides` flattened to entries for wire transport.\n * Same ascending-arity iteration order the Map carries on the\n * server side. Empty array when no joint divergences exist.\n */\n jointOverrides: readonly (readonly [string, VirtualJointOverrideShape])[];\n /**\n * Cached per-path variance results. Blocks read this for O(1) axis\n * variance lookup instead of recomputing on each render.\n */\n varianceByPath?: VirtualVarianceByPathShape;\n /** The default tuple — `{ axis: axis.default }` for every axis. */\n defaultTuple: Record<string, string>;\n /**\n * Pre-built `resolveAt(tuple)` accessor. The addon's preview\n * decorator instantiates this once per iframe lifetime — the\n * underlying virtual-module exports (cells, jointOverrides, axes,\n * defaultTuple) are stable, so a single resolver instance with\n * internal per-tuple memoization is correct and avoids the\n * per-render rebuild dance the blocks side used to do. Hand-built\n * snapshots (tests, MDX) can omit this; blocks fall back to\n * building locally from `cells` / `permutationsResolved`.\n */\n resolveAt?: (tuple: Record<string, string>) => Record<string, VirtualTokenShape>;\n}\n\n/**\n * Context carrying the full {@link ProjectSnapshot}. `null` sentinel lets\n * `useSwatchbookData()` tell \"provider present\" from \"fall back to the\n * virtual module\".\n */\nexport const SwatchbookContext = createContext<ProjectSnapshot | null>(null);\n\nexport function useOptionalSwatchbookData(): ProjectSnapshot | null {\n return useContext(SwatchbookContext);\n}\n\n/**\n * Active swatchbook theme for the current story/docs render. Populated by\n * the addon's preview decorator and consumed by `useToken` + any future\n * consumer hooks.\n *\n * This runs through plain React context rather than Storybook's\n * `useGlobals` so the same hook works in autodocs / MDX renders where the\n * preview-hooks context isn't available.\n */\nexport const ThemeContext = createContext<string>('');\n\nexport function useActiveTheme(): string {\n return useContext(ThemeContext);\n}\n\n/**\n * Active axis tuple for the current story/docs render — `Record<axisName,\n * contextName>`. Derived from the same input as {@link ThemeContext}; split\n * out so consumers needing per-axis info (toolbar, panel, tuple-aware\n * blocks) don't have to reparse the composed permutation ID.\n */\nexport const AxesContext = createContext<Readonly<Record<string, string>>>({});\n\nexport function useActiveAxes(): Readonly<Record<string, string>> {\n return useContext(AxesContext);\n}\n\n/**\n * Active color-display format for the current story/docs render. Populated\n * by the addon's preview decorator from the `swatchbookColorFormat` global\n * (per-story `globals` or toolbar dropdown) and consumed by blocks that\n * render color-token values. Emitted CSS is unaffected.\n *\n * Runs through plain React context rather than Storybook's `useGlobals` so\n * per-story seeded globals flow through on first render and the same hook\n * is safe to call from MDX doc blocks (where the preview-hooks context\n * isn't available).\n */\nexport const ColorFormatContext = createContext<ColorFormat | null>(null);\n\nexport function useColorFormat(): ColorFormat {\n const contextValue = useContext(ColorFormatContext);\n const channelGlobals = useChannelGlobals();\n return contextValue ?? channelGlobals.format ?? 'hex';\n}\n","import { useSyncExternalStore } from 'react';\nimport { addons } from 'storybook/preview-api';\nimport {\n axes as initialAxes,\n cells as initialCells,\n css as initialCss,\n cssVarPrefix as initialCssVarPrefix,\n defaultTuple as initialDefaultTuple,\n diagnostics as initialDiagnostics,\n jointOverrides as initialJointOverrides,\n listing as initialListing,\n presets as initialPresets,\n varianceByPath as initialVarianceByPath,\n} from 'virtual:swatchbook/tokens';\nimport type {\n VirtualJointOverrideShape,\n VirtualTokenListingShape,\n VirtualVarianceByPathShape,\n} from '#/contexts.ts';\nimport type { VirtualAxis, VirtualDiagnostic, VirtualToken } from '#/types.ts';\n\n/**\n * Live token snapshot backed by the addon's preview dev-time HMR event.\n *\n * Blocks read the virtual module at module load; without a way to notice\n * changes, edits to the source token files would flow into the addon's\n * in-memory project but nowhere else — the React tree would keep\n * rendering the old values until a full preview reload. This module\n * subscribes to `TOKENS_UPDATED_EVENT` on Storybook's channel (which the\n * addon preview re-broadcasts from its own HMR listener) and exposes\n * the latest snapshot via `useSyncExternalStore`, so hooks that read\n * through this module re-render in place on each token save.\n *\n * Outside the preview iframe (the docs-site path, unit tests) the\n * channel never receives anything, and consumers keep seeing the\n * initial values baked into the virtual module at build time.\n */\n\nconst TOKENS_UPDATED_EVENT = 'swatchbook/tokens-updated';\n\nexport interface TokenSnapshot {\n readonly axes: readonly VirtualAxis[];\n readonly presets: readonly {\n name: string;\n axes: Partial<Record<string, string>>;\n description?: string;\n }[];\n readonly diagnostics: readonly VirtualDiagnostic[];\n readonly css: string;\n readonly cssVarPrefix: string;\n readonly listing: Readonly<Record<string, VirtualTokenListingShape>>;\n readonly cells: Record<string, Record<string, Record<string, VirtualToken>>>;\n readonly jointOverrides: readonly (readonly [string, VirtualJointOverrideShape])[];\n readonly varianceByPath: VirtualVarianceByPathShape;\n readonly defaultTuple: Record<string, string>;\n /** Monotonic counter, bumped on each update. Useful as a React key. */\n readonly version: number;\n}\n\nlet snapshot: TokenSnapshot = {\n axes: initialAxes,\n presets: initialPresets,\n diagnostics: initialDiagnostics,\n css: initialCss,\n cssVarPrefix: initialCssVarPrefix,\n listing: initialListing ?? {},\n cells: initialCells ?? {},\n jointOverrides: initialJointOverrides ?? [],\n varianceByPath: initialVarianceByPath ?? {},\n defaultTuple: initialDefaultTuple ?? {},\n version: 0,\n};\n\nconst listeners = new Set<() => void>();\nlet subscribed = false;\n\nfunction ensureSubscribed(): void {\n if (subscribed || typeof window === 'undefined') return;\n subscribed = true;\n const channel = addons.getChannel();\n channel.on(TOKENS_UPDATED_EVENT, (payload: Partial<TokenSnapshot>) => {\n snapshot = {\n axes: payload.axes ?? snapshot.axes,\n presets: payload.presets ?? snapshot.presets,\n diagnostics: payload.diagnostics ?? snapshot.diagnostics,\n css: payload.css ?? snapshot.css,\n cssVarPrefix: payload.cssVarPrefix ?? snapshot.cssVarPrefix,\n listing: payload.listing ?? snapshot.listing,\n cells: payload.cells ?? snapshot.cells,\n jointOverrides: payload.jointOverrides ?? snapshot.jointOverrides,\n varianceByPath: payload.varianceByPath ?? snapshot.varianceByPath,\n defaultTuple: payload.defaultTuple ?? snapshot.defaultTuple,\n version: snapshot.version + 1,\n };\n for (const cb of listeners) cb();\n });\n}\n\nensureSubscribed();\n\nfunction subscribe(cb: () => void): () => void {\n ensureSubscribed();\n listeners.add(cb);\n return () => {\n listeners.delete(cb);\n };\n}\n\nfunction getSnapshot(): TokenSnapshot {\n return snapshot;\n}\n\nexport function useTokenSnapshot(): TokenSnapshot {\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n","import { buildResolveAt } from '@unpunnyfuns/swatchbook-core/resolve-at';\nimport { makeCssVar } from '@unpunnyfuns/swatchbook-core/css-var';\nimport {\n ensureStyleElement,\n SWATCHBOOK_STYLE_ELEMENT_ID,\n} from '@unpunnyfuns/swatchbook-core/style-element';\nimport { tupleToName } from '@unpunnyfuns/swatchbook-core/themes';\nimport type { Axis, Cells, JointOverrides } from '@unpunnyfuns/swatchbook-core';\nimport { useEffect, useMemo } from 'react';\nimport type { VirtualTokenListingShape, VirtualVarianceByPathShape } from '#/contexts.ts';\nimport { useActiveAxes, useActiveTheme, useOptionalSwatchbookData } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat, FormatColorResult } from '#/format-color.ts';\nimport { useChannelGlobals } from '#/internal/channel-globals.ts';\nimport { useTokenSnapshot } from '#/internal/channel-tokens.ts';\nimport type { ProjectSnapshot, VirtualAxis, VirtualDiagnostic, VirtualToken } from '#/types.ts';\n\ntype ResolvedTokens = Record<string, VirtualToken>;\n\nexport interface ProjectData {\n activeTheme: string;\n activeAxes: Record<string, string>;\n axes: readonly VirtualAxis[];\n resolved: ResolvedTokens;\n diagnostics: readonly VirtualDiagnostic[];\n cssVarPrefix: string;\n /**\n * Path-indexed Token Listing data. Empty when absent (non-resolver\n * projects, hand-built snapshots that don't populate it). Blocks read\n * authoritative CSS var names from `listing[path].names.css` and\n * preview strings from `listing[path].previewValue`.\n */\n listing: Readonly<Record<string, VirtualTokenListingShape>>;\n /**\n * Cached per-path `AxisVarianceResult` — blocks use this for O(1)\n * variance lookup instead of re-running the analysis on every\n * render.\n */\n varianceByPath: VirtualVarianceByPathShape;\n /**\n * Compose the resolved `TokenMap` for any tuple of axis selections.\n * Built browser-side from `cells + jointOverrides` shipped over the\n * wire — no resolver needed.\n */\n resolveAt: (tuple: Record<string, string>) => ResolvedTokens;\n /**\n * Synthesize a display name for a full tuple — `axisValues.join(' · ')`,\n * matching the form `permutationID` produces server-side. Used by\n * the AxisVariance grid for `data-<prefix>-theme` attribution.\n */\n themeNameForTuple: (tuple: Record<string, string>) => string | undefined;\n}\n\nfunction ensureStylesheet(css: string): void {\n ensureStyleElement(SWATCHBOOK_STYLE_ELEMENT_ID, css);\n}\n\nfunction defaultTuple(axes: readonly VirtualAxis[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const axis of axes) out[axis.name] = axis.default;\n return out;\n}\n\n/**\n * Reconstruct a `resolveAt` accessor from snapshot data. Both `cells`\n * and `jointOverrides` ship as plain JSON in the same shape core uses\n * internally — no Map reconstruction at the boundary. Stable identity\n * across calls with the same snapshot — `useMemo` keyed on the\n * snapshot fields produces a referentially stable function.\n */\nfunction makeResolveAt(snapshot: {\n axes: readonly VirtualAxis[];\n cells?: ProjectSnapshot['cells'];\n jointOverrides?: ProjectSnapshot['jointOverrides'];\n defaultTuple?: ProjectSnapshot['defaultTuple'];\n}): (tuple: Record<string, string>) => ResolvedTokens {\n const cells = (snapshot.cells ?? {}) as Cells;\n const jointOverrides = (snapshot.jointOverrides ?? []) as JointOverrides;\n const defaults = snapshot.defaultTuple ?? defaultTuple(snapshot.axes);\n const resolver = buildResolveAt(\n snapshot.axes as readonly Axis[],\n cells,\n jointOverrides,\n defaults,\n );\n return (tuple) => resolver(tuple);\n}\n\n/**\n * Build the `resolveAt` accessor for a snapshot. Prefers the\n * snapshot's own `resolveAt` (the addon's preview decorator\n * pre-builds one at module load — see `previewResolveAt` in\n * `packages/addon/src/preview.tsx`), otherwise composes one from\n * `cells` + `jointOverrides` via `makeResolveAt`. Hand-built\n * snapshots should provide both via the test `withCellsShape`\n * helper or by populating the fields directly.\n */\nfunction snapshotResolveAt(\n snapshot: ProjectSnapshot,\n): (tuple: Record<string, string>) => ResolvedTokens {\n if (snapshot.resolveAt)\n return snapshot.resolveAt as (tuple: Record<string, string>) => ResolvedTokens;\n return makeResolveAt(snapshot);\n}\n\n/**\n * Reads project data either from a mounted {@link SwatchbookProvider}\n * (preferred — the addon's preview decorator installs one around every\n * story) or, when no provider is present, from the virtual module plus\n * Storybook globals directly.\n *\n * The provider-less path is what makes the hook safe to call from MDX\n * doc blocks and autodocs renders where no story is active. It\n * self-mounts the virtual module's per-theme CSS and tracks the active\n * tuple via the `globalsUpdated` channel event; {@link useGlobals} from\n * `storybook/preview-api` would throw outside a story render.\n */\nexport function useProject(): ProjectData {\n const snapshot = useOptionalSwatchbookData();\n // Memoize against the stable underlying fields, NOT the snapshot\n // wrapper. Storybook rebuilds `context.globals` identity on every\n // render → the preview's `tuple` useMemo invalidates → the\n // provider's snapshot useMemo rebuilds. Keying off `snapshot`\n // would mean `makeResolveAt` runs on every render, producing a\n // fresh closure with a fresh internal memo, so `resolved` would\n // have a new identity each render. Downstream block\n // `useMemo([resolved, …])` calls would recompute forever; the\n // `TokenNavigator`'s focus-repair `useEffect` (deps include the\n // recomputed `flatVisible`) would `setState` in an infinite loop.\n // The underlying `cells` / `jointOverrides` / `defaultTuple` /\n // `axes` references are stable module-level exports, so depending\n // on them directly keeps `resolveAt` (and the resolved map it\n // returns) referentially stable across renders.\n const axes = snapshot?.axes;\n const cells = snapshot?.cells;\n const jointOverrides = snapshot?.jointOverrides;\n const dataDefaultTuple = snapshot?.defaultTuple;\n const activeAxes = snapshot?.activeAxes;\n const activeTheme = snapshot?.activeTheme;\n const diagnostics = snapshot?.diagnostics;\n const cssVarPrefix = snapshot?.cssVarPrefix;\n const listing = snapshot?.listing;\n const varianceByPath = snapshot?.varianceByPath;\n const resolveAt = useMemo(() => {\n if (!snapshot) return null;\n return snapshotResolveAt(snapshot);\n // The deps below are deliberately the stable inner fields rather\n // than `snapshot` itself; see the long block comment above.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [axes, cells, jointOverrides, dataDefaultTuple, activeTheme]);\n // Memoize the returned ProjectData against the same stable inner\n // fields — without this, blocks `useMemo([project, …])` calls\n // invalidate every render (the function returns a fresh object\n // identity), defeating the per-block memoization that\n // `TokenNavigator` / `TokenTable` / `ColorPalette` rely on.\n const providerData = useMemo<ProjectData | null>(() => {\n if (!snapshot || !resolveAt || !axes || !activeAxes) return null;\n return {\n activeTheme: activeTheme ?? '',\n activeAxes: activeAxes as Record<string, string>,\n axes,\n resolved: resolveAt(activeAxes as Record<string, string>),\n diagnostics: diagnostics ?? [],\n cssVarPrefix: cssVarPrefix ?? '',\n listing: listing ?? {},\n varianceByPath: varianceByPath ?? {},\n resolveAt,\n themeNameForTuple: (tuple) => tupleToName(axes, tuple),\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n snapshot,\n resolveAt,\n axes,\n cells,\n jointOverrides,\n dataDefaultTuple,\n activeTheme,\n activeAxes,\n diagnostics,\n cssVarPrefix,\n listing,\n varianceByPath,\n ]);\n const fallback = useVirtualModuleFallback(snapshot === null);\n return providerData ?? fallback;\n}\n\nfunction useVirtualModuleFallback(enabled: boolean): ProjectData {\n const contextPermutation = useActiveTheme();\n const contextAxes = useActiveAxes();\n const channelGlobals = useChannelGlobals();\n /**\n * Subscribe to the live token snapshot rather than reading the virtual\n * module's module-level exports directly. Initial values come from\n * `virtual:swatchbook/tokens` at load time; subsequent dev-time edits\n * flow through the addon's HMR channel and update this snapshot in\n * place so blocks re-render without a full preview reload.\n */\n const tokens = useTokenSnapshot();\n\n useEffect(() => {\n if (!enabled) return;\n ensureStylesheet(tokens.css);\n }, [enabled, tokens.css]);\n\n // Memoize against the stable identities — `contextAxes` is a\n // useContext value that's stable across renders unless the\n // provider mutates; `channelGlobals.axes` updates on channel\n // events; `tokens.axes` is a stable virtual-module export.\n // Without this memo `activeAxes` would have fresh identity per\n // render and defeat downstream `useMemo([project, …])` calls.\n const activeAxes = useMemo<Record<string, string>>(() => {\n const hasContextAxes = Object.keys(contextAxes).length > 0;\n return hasContextAxes ? { ...contextAxes } : (channelGlobals.axes ?? defaultTuple(tokens.axes));\n }, [contextAxes, channelGlobals.axes, tokens.axes]);\n\n const activeTheme = contextPermutation || tupleToName(tokens.axes, activeAxes);\n\n // `buildResolveAt` returns a closure that memoizes on the canonical\n // tuple key, so wrapping the call in another `useMemo` would be\n // redundant — the inner memo handles the per-tuple cache. We only\n // need `useMemo` for the outer `resolveAt` itself so React's\n // reference equality stays stable between renders.\n const resolveAt = useMemo(\n () =>\n makeResolveAt({\n axes: tokens.axes,\n cells: tokens.cells,\n jointOverrides: tokens.jointOverrides,\n defaultTuple: tokens.defaultTuple,\n }),\n [tokens.axes, tokens.cells, tokens.jointOverrides, tokens.defaultTuple],\n );\n\n // Memoize the returned ProjectData against the stable inner fields\n // for the same reason the provider path does — fresh object identity\n // per render would defeat `useMemo([project, …])` in every block.\n return useMemo<ProjectData>(\n () => ({\n activeTheme,\n activeAxes,\n axes: tokens.axes,\n resolved: resolveAt(activeAxes),\n diagnostics: tokens.diagnostics,\n cssVarPrefix: tokens.cssVarPrefix,\n listing: tokens.listing,\n varianceByPath: tokens.varianceByPath,\n resolveAt,\n themeNameForTuple: (tuple) => tupleToName(tokens.axes, tuple),\n }),\n [\n activeTheme,\n activeAxes,\n tokens.axes,\n tokens.diagnostics,\n tokens.cssVarPrefix,\n tokens.listing,\n tokens.varianceByPath,\n resolveAt,\n ],\n );\n}\n\n/**\n * Resolve a token's CSS var reference, preferring the authoritative name\n * emitted by `@terrazzo/plugin-css` (as recorded by\n * `@terrazzo/plugin-token-listing` in the snapshot's `listing` field).\n * Falls back to `makeCssVar` when the listing lacks an entry for this\n * path — covers non-resolver projects, hand-built snapshots, and any\n * listing-plugin miss.\n */\nexport function resolveCssVar(path: string, project: ProjectData): string {\n const listed = project.listing[path]?.names?.['css'];\n if (listed) return `var(${listed})`;\n return makeCssVar(path, project.cssVarPrefix);\n}\n\n/**\n * Resolve a color value's display string + gamut flag, preferring the\n * listing's `previewValue` when the user's active color-format matches\n * plugin-css's output (hex). For any other format we fall back to\n * `formatColor` so the toolbar's inspection modes (rgb / hsl / oklch /\n * raw) keep working — the listing has only one canonical format.\n *\n * Pass `path === undefined` when resolving a sub-color inside a composite\n * (shadow / border / gradient stop): composites' `previewValue` covers\n * the whole token's rendering, not the individual channel, so there's no\n * listing entry to key against.\n */\nexport function resolveColorValue(\n path: string | undefined,\n raw: unknown,\n colorFormat: ColorFormat,\n project: ProjectData,\n): FormatColorResult {\n if (path !== undefined && colorFormat === 'hex') {\n const listed = project.listing[path]?.previewValue;\n if (typeof listed === 'string') {\n return { value: listed, outOfGamut: false };\n }\n }\n return formatColor(raw, colorFormat);\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { SURFACE_RAISED } from '#/internal/styles.tsx';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\n\nexport interface BorderSampleProps {\n /** Full dot-path of the border token to preview. */\n path: string;\n}\n\nconst sampleStyle: CSSProperties = {\n width: 120,\n height: 56,\n background: SURFACE_RAISED,\n borderRadius: 6,\n};\n\nexport function BorderSample({ path }: BorderSampleProps): ReactElement {\n const project = useProject();\n const cssVar = resolveCssVar(path, project);\n return <div style={{ ...sampleStyle, border: cssVar }} aria-hidden />;\n}\n","import { dataAttr } from '@unpunnyfuns/swatchbook-core/data-attr';\n\n/**\n * Marker attribute set on every block wrapper. Retained as a stable hook\n * for consumer-side selectors (e.g. when a host app wants to target or\n * override block chrome without relying on hashed class names).\n */\nexport const BLOCK_ATTR = 'data-swatchbook-block';\n\n/**\n * Opt-out class that Storybook's `.sbdocs` stylesheet uses to self-exclude\n * on MDX docs pages — every `.sbdocs` house rule is wrapped in\n * `:not(.sb-unstyled, .sb-unstyled *)`, so any descendant of a `.sb-unstyled`\n * container is left alone. Stamped onto every block wrapper so blocks\n * render identically in MDX docs and regular stories without fighting\n * cascade specificity.\n */\nconst WRAPPER_CLASSES = 'sb-unstyled sb-block';\n\n/**\n * Spread helper for the common block wrapper. Returns:\n * - `data-<prefix>-theme=\"<composed theme name>\"` — so theme-keyed CSS\n * emitted by `@unpunnyfuns/swatchbook-core` resolves against this\n * subtree.\n * - `data-swatchbook-block` — stable consumer hook for targeting block\n * chrome from outside.\n * - `className=\"sb-unstyled sb-block\"` — Storybook's opt-out class so\n * MDX docs house styles self-exclude the subtree, plus `sb-block`\n * which carries the shared chrome from `internal/styles.css`.\n */\nexport function themeAttrs(prefix: string, themeName: string): Record<string, string> {\n return {\n [dataAttr(prefix, 'theme')]: themeName,\n [BLOCK_ATTR]: '',\n className: WRAPPER_CLASSES,\n };\n}\n","import Color from 'colorjs.io';\nimport type { VirtualToken } from '#/types.ts';\n\nexport type SortBy = 'path' | 'value' | 'none';\nexport type SortDir = 'asc' | 'desc';\n\nexport interface SortOptions {\n by?: SortBy;\n dir?: SortDir;\n}\n\ntype Entry = readonly [string, VirtualToken];\n\n/**\n * Stable sort for a filtered `[path, token][]` list.\n *\n * `sortBy: 'path'` — lexicographic on the dot-path (locale-aware, numeric).\n * `sortBy: 'value'` — per-`$type` ordering:\n * - `dimension` / `duration` → numeric pixels / ms (via `toMagnitude`).\n * - `fontWeight` / `opacity` / `number` / `lineHeight` → numeric.\n * - `color` → perceptual by oklch L → C → H.\n * - `fontFamily` / `strokeStyle` (string form) → lexicographic.\n * - Composites (`typography`, `shadow`, `border`, `gradient`, `transition`) →\n * fall back to path-alpha. No useful single-axis order.\n * `sortBy: 'none'` — preserve input order (still respects `sortDir: 'desc'`\n * as a reverse).\n */\n/**\n * Pre-computed per-token sort key — one of three shapes depending on\n * `$type`. The comparator looks the key up by token-reference once\n * per pair instead of recomputing on every comparison (Schwartzian\n * transform).\n *\n * For N tokens, sort does O(N log N) comparisons; per-call cost for\n * colors was an Oklch conversion (a `new Color()` + `to('oklch')`)\n * which dominates wall time on real fixtures. Pre-computing brings\n * that down to O(N) keys + O(N log N) cheap lookups.\n */\ntype SortKey =\n | { kind: 'numeric'; value: number; valid: boolean }\n | { kind: 'color'; key: { l: number; c: number; h: number } | null }\n | { kind: 'string'; value: string }\n | { kind: 'none' };\n\nconst NUMERIC_TYPES = new Set([\n 'dimension',\n 'duration',\n 'fontWeight',\n 'opacity',\n 'number',\n 'lineHeight',\n]);\n\nconst STRING_TYPES = new Set(['fontFamily', 'strokeStyle']);\n\nfunction computeSortKey(token: VirtualToken): SortKey {\n const type = token.$type;\n if (!type) return { kind: 'none' };\n if (NUMERIC_TYPES.has(type)) {\n const value = toMagnitude(token.$value);\n return { kind: 'numeric', value, valid: Number.isFinite(value) };\n }\n if (type === 'color') {\n return { kind: 'color', key: colorKey(token.$value) };\n }\n if (STRING_TYPES.has(type)) {\n return { kind: 'string', value: toDisplayable(token.$value) };\n }\n // Composite types ($type: 'typography', 'shadow', 'border', …) have\n // no useful one-dimensional ordering — fall back to no-op.\n return { kind: 'none' };\n}\n\nexport function sortTokens(entries: readonly Entry[], options: SortOptions = {}): Entry[] {\n const by = options.by ?? 'path';\n const dir = options.dir ?? 'asc';\n const sign = dir === 'desc' ? -1 : 1;\n\n if (by === 'none') {\n return dir === 'desc' ? [...entries].toReversed() : [...entries];\n }\n\n if (by === 'path') {\n return [...entries].toSorted(\n ([a], [b]) => sign * a.localeCompare(b, undefined, { numeric: true }),\n );\n }\n\n // by === 'value' — pre-compute per-token sort keys once.\n const keys = new Map<VirtualToken, SortKey>();\n for (const [, token] of entries) {\n keys.set(token, computeSortKey(token));\n }\n\n return [...entries].toSorted(([aPath, aTok], [bPath, bTok]) => {\n const cmp = compareValue(aTok, bTok, keys);\n if (cmp !== 0) return sign * cmp;\n // Stable tiebreak on path so the order is deterministic when values equal.\n return sign * aPath.localeCompare(bPath, undefined, { numeric: true });\n });\n}\n\nfunction compareValue(\n a: VirtualToken,\n b: VirtualToken,\n keys: ReadonlyMap<VirtualToken, SortKey>,\n): number {\n // When the two tokens differ in $type, fall back to type-alpha so at\n // least the mixed list clusters by type.\n if (a.$type !== b.$type) return String(a.$type ?? '').localeCompare(String(b.$type ?? ''));\n\n const ak = keys.get(a);\n const bk = keys.get(b);\n if (!ak || !bk) return 0;\n // Matches the `a.$type === b.$type` check above.\n if (ak.kind !== bk.kind) return 0;\n\n if (ak.kind === 'numeric' && bk.kind === 'numeric') {\n if (ak.valid && bk.valid) return ak.value - bk.value;\n if (ak.valid) return -1;\n if (bk.valid) return 1;\n return 0;\n }\n\n if (ak.kind === 'color' && bk.kind === 'color') {\n const a3 = ak.key;\n const b3 = bk.key;\n if (!a3 && !b3) return 0;\n if (!a3) return 1;\n if (!b3) return -1;\n if (a3.l !== b3.l) return a3.l - b3.l;\n if (a3.c !== b3.c) return a3.c - b3.c;\n return a3.h - b3.h;\n }\n\n if (ak.kind === 'string' && bk.kind === 'string') {\n return ak.value.localeCompare(bk.value, undefined, { numeric: true });\n }\n\n return 0;\n}\n\nfunction toMagnitude(v: unknown): number {\n if (typeof v === 'number') return v;\n if (v && typeof v === 'object') {\n const d = v as { value?: unknown; unit?: unknown };\n if (typeof d.value !== 'number') return Number.NaN;\n if (typeof d.unit !== 'string') return d.value;\n switch (d.unit) {\n case 'px':\n case 'ms':\n return d.value;\n case 's':\n return d.value * 1000;\n case 'rem':\n case 'em':\n return d.value * 16;\n default:\n return d.value;\n }\n }\n return Number.NaN;\n}\n\n/**\n * Coerce a possibly-null/undefined number to 0 — `coords` returns\n * `(number | null)[]` and `noUncheckedIndexedAccess` adds `undefined`\n * on top. `typeof` narrows the union for the comparator below.\n */\nfunction safeNumber(v: number | null | undefined): number {\n return typeof v === 'number' && Number.isFinite(v) ? v : 0;\n}\n\nfunction colorKey(v: unknown): { l: number; c: number; h: number } | null {\n if (!v || typeof v !== 'object') return null;\n try {\n const c = v as {\n colorSpace?: unknown;\n components?: unknown;\n channels?: unknown;\n hex?: unknown;\n };\n let source: unknown;\n if (typeof c.hex === 'string') source = c.hex;\n else if (typeof c.colorSpace === 'string') {\n const channels = Array.isArray(c.components)\n ? c.components\n : Array.isArray(c.channels)\n ? c.channels\n : undefined;\n if (!channels) return null;\n source = { space: c.colorSpace, coords: channels };\n } else return null;\n // Color.js's constructor signature is a string or PlainColorObject —\n // we've already narrowed `source` to one of those shapes above, but\n // the union ends up broader than Color.js's typed surface.\n const color = new Color(source as string);\n const [l, chroma, h] = color.to('oklch').coords;\n return { l: safeNumber(l), c: safeNumber(chroma), h: safeNumber(h) };\n } catch {\n return null;\n }\n}\n\nfunction toDisplayable(v: unknown): string {\n if (typeof v === 'string') return v;\n if (Array.isArray(v)) return v.map(String).join(', ');\n if (v && typeof v === 'object') return JSON.stringify(v);\n return String(v ?? '');\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './BorderPreview.css';\nimport { BorderSample } from '#/border-preview/BorderSample.tsx';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat } from '#/format-color.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface BorderPreviewProps {\n /**\n * Token-path filter. Defaults to every `border` token. Use e.g.\n * `\"border.*\"` to scope to the semantic layer.\n */\n filter?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` falls through to path (borders don't have a\n * single-axis ordering); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface BorderValue {\n color?: unknown;\n width?: unknown;\n style?: unknown;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n value: BorderValue;\n}\n\nfunction formatDimension(raw: unknown): string {\n if (raw == null) return '—';\n if (typeof raw === 'number') return String(raw);\n if (typeof raw === 'string') return raw;\n if (typeof raw === 'object') {\n const v = raw as { value?: unknown; unit?: unknown };\n if (typeof v.value === 'number' && typeof v.unit === 'string') {\n return `${v.value}${v.unit}`;\n }\n }\n return JSON.stringify(raw);\n}\n\nfunction formatSubColor(raw: unknown, format: ColorFormat): string {\n if (raw == null) return '—';\n return formatColor(raw, format).value;\n}\n\nexport function BorderPreview({\n filter,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: BorderPreviewProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'border') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n value: (token.$value ?? {}) as BorderValue,\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} border${rows.length === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No border tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-border-preview__row\">\n <div className=\"sb-border-preview__meta\">\n <span className=\"sb-border-preview__path\">{row.path}</span>\n <span className=\"sb-border-preview__css-var\">{row.cssVar}</span>\n </div>\n <div className=\"sb-border-preview__sample-cell\">\n <BorderSample path={row.path} />\n </div>\n <div className=\"sb-border-preview__breakdown\">\n <span className=\"sb-border-preview__breakdown-key\">width</span>\n <span>{formatDimension(row.value.width)}</span>\n <span className=\"sb-border-preview__breakdown-key\">style</span>\n <span>{row.value.style != null ? String(row.value.style) : '—'}</span>\n <span className=\"sb-border-preview__breakdown-key\">color</span>\n <span>{formatSubColor(row.value.color, colorFormat)}</span>\n </div>\n </div>\n ))}\n </div>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './ColorPalette.css';\nimport { useColorFormat } from '#/contexts.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveColorValue, resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface ColorPaletteProps {\n /**\n * Token-path filter. Defaults to every `color` token. Use e.g.\n * `\"color.*\"` to scope to the semantic layer, or `\"color.palette.blue.*\"`\n * for a single ref ramp.\n */\n filter?: string;\n /**\n * Grouping depth. Tokens are grouped by the first `groupBy` dot-segments\n * of their path. `1` yields a single `color` group; `2` yields\n * `color.surface`, `color.text`, `color.blue`, etc.\n *\n * If omitted, groupBy is derived from the filter: one level below the\n * filter's fixed prefix (segments before the first `*`), clamped so each\n * swatch still carries a leaf label. `\"color.*\"` → groups at\n * `color.<family>`; `\"color.palette.blue.*\"` collapses all shades into\n * one `color.blue` group because the tokens have no deeper level.\n */\n groupBy?: number;\n /** Override the section caption. */\n caption?: string;\n /**\n * Sort order within each group.\n * - `'path'` (default) — lexicographic on the dot-path.\n * - `'value'` — perceptual ordering: oklch L → C → H (ramps read\n * light→dark, then warm→cool within each lightness band).\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface Swatch {\n path: string;\n leaf: string;\n cssVar: string;\n value: string;\n outOfGamut: boolean;\n}\n\n/**\n * Count segments in the filter before the first glob (`*` / `**`).\n * `color.*` → 2; `color.surface.*` → 3; `color` → 1; undefined → 0.\n */\nfunction fixedPrefixLength(filter: string | undefined): number {\n if (!filter) return 0;\n const segments = filter.split('.');\n let fixed = 0;\n for (const seg of segments) {\n if (seg === '*' || seg === '**') break;\n fixed += 1;\n }\n return fixed;\n}\n\nexport function ColorPalette({\n filter,\n groupBy,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: ColorPaletteProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n\n const groups = useMemo(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'color') return false;\n return matchPath(path, filter);\n });\n const entries = sortTokens(filtered, { by: sortBy, dir: sortDir });\n\n const maxDepth = entries.reduce((m, [p]) => Math.max(m, p.split('.').length), 0);\n const effectiveGroupBy =\n groupBy ?? Math.min(fixedPrefixLength(filter) + 1, Math.max(maxDepth - 1, 1));\n\n const bucket = new Map<string, Swatch[]>();\n for (const [path, token] of entries) {\n const segments = path.split('.');\n const groupKey = segments.slice(0, effectiveGroupBy).join('.');\n const leaf = segments.slice(effectiveGroupBy).join('.') || segments.at(-1) || path;\n const list = bucket.get(groupKey) ?? [];\n const formatted = resolveColorValue(path, token.$value, colorFormat, project);\n list.push({\n path,\n leaf,\n cssVar: resolveCssVar(path, project),\n value: formatted.value,\n outOfGamut: formatted.outOfGamut,\n });\n bucket.set(groupKey, list);\n }\n\n return [...bucket.entries()].toSorted(([a], [b]) =>\n a.localeCompare(b, undefined, { numeric: true }),\n );\n }, [resolved, filter, groupBy, project, colorFormat, sortBy, sortDir]);\n\n const totalCount = groups.reduce((acc, [, swatches]) => acc + swatches.length, 0);\n const captionText =\n caption ??\n `${totalCount} color${totalCount === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (totalCount === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No color tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {groups.map(([group, swatches]) => (\n <section key={group} className=\"sb-color-palette__group\">\n <div className=\"sb-color-palette__group-header\">{group}</div>\n <div className=\"sb-color-palette__grid\">\n {swatches.map((swatch) => (\n <div key={swatch.path} className=\"sb-color-palette__card\">\n <div\n className=\"sb-color-palette__swatch\"\n style={{ background: swatch.cssVar }}\n aria-hidden\n />\n <div className=\"sb-color-palette__meta\">\n <span className=\"sb-color-palette__leaf\">{swatch.leaf}</span>\n <span className=\"sb-color-palette__value\">\n {swatch.value}\n {swatch.outOfGamut && (\n <span\n title=\"Out of sRGB gamut for this format\"\n aria-label=\"out of gamut\"\n className=\"sb-color-palette__gamut-warn\"\n >\n {' '}\n ⚠\n </span>\n )}\n </span>\n </div>\n </div>\n ))}\n </div>\n </section>\n ))}\n </div>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport './CopyButton.css';\n\nexport interface CopyButtonProps {\n /** Text written to the clipboard when clicked. */\n value: string;\n /**\n * Accessible label. Defaults to `Copy <value>`; override for long values\n * (hex + description + etc.) where the full label would be too chatty.\n */\n label?: string;\n /** `'icon'` (default) — 16 px glyph button; `'text'` — `Copy` pill. */\n variant?: 'icon' | 'text';\n /** Extra class to merge onto the button root. */\n className?: string;\n}\n\n/**\n * Copy the given string to the clipboard and briefly surface a \"Copied!\"\n * state. Falls back silently on unsupported clipboard APIs (older Safari,\n * insecure origins) — the click still happens, the user just won't see the\n * tick. No custom permission prompt: relies on the browser's native user-\n * activation gate.\n */\nexport function CopyButton({\n value,\n label,\n variant = 'icon',\n className,\n}: CopyButtonProps): ReactElement {\n const [copied, setCopied] = useState(false);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n return () => {\n if (timerRef.current !== null) clearTimeout(timerRef.current);\n };\n }, []);\n\n const handleClick = useCallback((): void => {\n // `writeText` is async and rejects on unfocused documents,\n // insecure origins, missing permissions, etc. Swallow the\n // rejection — the \"Copied!\" affordance is a nicety, not a\n // correctness requirement; an unhandled rejection in prod would\n // surface in DevTools and (under vitest browser-mode) fail the\n // suite from an unrelated test.\n navigator.clipboard?.writeText(value).catch(() => {});\n setCopied(true);\n if (timerRef.current !== null) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => setCopied(false), 1500);\n }, [value]);\n\n const ariaLabel = label ?? `Copy ${value}`;\n const classes = ['sb-copy-button', `sb-copy-button--${variant}`];\n if (copied) classes.push('sb-copy-button--copied');\n if (className) classes.push(className);\n\n return (\n <button\n type=\"button\"\n className={classes.join(' ')}\n onClick={handleClick}\n aria-label={ariaLabel}\n title={ariaLabel}\n data-copied={copied ? 'true' : undefined}\n >\n {variant === 'text' ? (\n <span className=\"sb-copy-button__text\">{copied ? 'Copied' : 'Copy'}</span>\n ) : (\n <span className=\"sb-copy-button__glyph\" aria-hidden>\n {copied ? '✓' : '⧉'}\n </span>\n )}\n </button>\n );\n}\n","import { fuzzyFilter } from '@unpunnyfuns/swatchbook-core/fuzzy';\nimport cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport { useCallback, useMemo, useState } from 'react';\nimport './ColorTable.css';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat, NormalizedColor } from '#/format-color.ts';\nimport { CopyButton } from '#/internal/CopyButton.tsx';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveColorValue, resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nconst BASE_LABEL = 'base';\nconst COLUMN_COUNT = 6;\n\nexport interface ColorTableProps {\n /**\n * Token-path filter. Defaults to every `$type: color` token. `\"color.*\"`\n * scopes to the semantic layer; `\"color.palette.blue.*\"` to a single ramp.\n */\n filter?: string;\n /** Override the table caption. */\n caption?: string;\n /**\n * Sort order.\n * - `'path'` (default) — lexicographic on the dot-path.\n * - `'value'` — perceptual (oklch L → C → H). Ramps read light→dark, then\n * warm→cool within each lightness band.\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n /**\n * Render a fuzzy-search input above the table. Defaults to `true`.\n */\n searchable?: boolean;\n /**\n * Called with the *currently-selected* variant's dot-path on row click.\n * When set, the built-in expand-in-place behavior is suppressed — the\n * consumer owns follow-up UI.\n */\n onSelect?(path: string): void;\n /**\n * Map from a display label to a suffix matched against each token's\n * trailing path segment. Tokens whose leaves match a suffix are grouped\n * under a shared \"base\" path (the path with the suffix stripped), and\n * the group renders as a single row with a pill selector — clicking a\n * pill swaps the displayed values to that variant. Sibling tokens\n * without a suffix that share the group's base path are labeled `base`.\n *\n * Matches both DTCG-idiomatic and Backmarket-style conventions:\n * - **Dot segment** (`color.bg.hi.disabled`): last dot-segment equals\n * the suffix (`disabled`). Base path = drop the last segment.\n * - **Hyphen tail** (`color.bg.hi-d`): last dot-segment ends in\n * `-<suffix>` (`d`). Base path = trim the `-<suffix>` from the leaf.\n *\n * Longest-suffix-wins. Hyphen-tail form requires an actual hyphen\n * boundary — suffix `0` does not match `neutral-900`.\n *\n * Single-member groups render as plain rows (no pill selector). Empty\n * map (default) disables grouping entirely; each token renders as its\n * own row, identical to the pre-grouping behavior.\n */\n variants?: Record<string, string>;\n}\n\ninterface Variant {\n label: string;\n path: string;\n cssVar: string;\n /** The display value in the currently-active color format. */\n value: string;\n outOfGamut: boolean;\n /** Hex / HSL / OKLCH breakdown — retained for the expanded sub-table. */\n hex: string;\n hsl: string;\n oklch: string;\n description?: string;\n aliasOf?: string;\n aliasChain?: readonly string[];\n}\n\ninterface Group {\n base: string;\n variants: Variant[];\n searchText: string;\n}\n\nexport function ColorTable({\n filter,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n searchable = true,\n onSelect,\n variants,\n}: ColorTableProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n const [query, setQuery] = useState('');\n const [selectedByBase, setSelectedByBase] = useState<Record<string, string>>({});\n const [expandedByBase, setExpandedByBase] = useState<ReadonlySet<string>>(() => new Set());\n\n const defs = useMemo(() => buildVariantDefs(variants), [variants]);\n\n const groups = useMemo<Group[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'color') return false;\n return matchPath(path, filter);\n });\n const sorted = sortTokens(filtered, { by: sortBy, dir: sortDir });\n\n const groupMap = new Map<string, { base: string; variants: Variant[] }>();\n for (const [path, token] of sorted) {\n const raw = token.$value as NormalizedColor;\n const hex = resolveColorValue(path, raw, 'hex', project);\n const hsl = formatColor(raw, 'hsl');\n const oklch = formatColor(raw, 'oklch');\n const active = pickActiveFormat(raw, colorFormat, hex, hsl, oklch);\n const match = matchVariant(path, defs.matchOrder);\n const variant: Variant = {\n label: match?.label ?? BASE_LABEL,\n path,\n cssVar: resolveCssVar(path, project),\n value: active.value,\n outOfGamut: active.outOfGamut,\n hex: hex.value,\n hsl: hsl.value,\n oklch: oklch.value,\n ...(token.$description !== undefined && { description: token.$description }),\n ...(token.aliasOf !== undefined && { aliasOf: token.aliasOf }),\n ...(token.aliasChain !== undefined && { aliasChain: token.aliasChain }),\n };\n const basePath = match?.basePath ?? path;\n const existing = groupMap.get(basePath);\n if (existing) existing.variants.push(variant);\n else groupMap.set(basePath, { base: basePath, variants: [variant] });\n }\n\n const out: Group[] = [];\n for (const { base, variants: vs } of groupMap.values()) {\n vs.sort((a, b) => orderIndex(a.label, defs) - orderIndex(b.label, defs));\n const searchText = vs.map((v) => `${v.path} ${v.value}`).join(' ');\n out.push({ base, variants: vs, searchText });\n }\n return out;\n }, [resolved, filter, project, sortBy, sortDir, defs, colorFormat]);\n\n const visibleGroups = useMemo(() => {\n if (!searchable || query.trim() === '') return groups;\n return fuzzyFilter(groups, query, (g) => g.searchText);\n }, [groups, query, searchable]);\n\n const totalTokens = useMemo(() => groups.reduce((n, g) => n + g.variants.length, 0), [groups]);\n\n const toggleExpand = useCallback((base: string) => {\n setExpandedByBase((prev) => {\n const next = new Set(prev);\n if (next.has(base)) next.delete(base);\n else next.add(base);\n return next;\n });\n }, []);\n\n const selectVariant = useCallback((base: string, label: string) => {\n setSelectedByBase((prev) => ({ ...prev, [base]: label }));\n }, []);\n\n const matchSuffix =\n searchable && query.trim() !== ''\n ? ` · ${visibleGroups.length} matching \"${query.trim()}\"`\n : '';\n const captionText =\n caption ??\n `${totalTokens} color${totalTokens === 1 ? '' : 's'} across ${groups.length} group${\n groups.length === 1 ? '' : 's'\n }${filter ? ` matching \\`${filter}\\`` : ''}${matchSuffix} · ${activeTheme}`;\n\n if (groups.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No color tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n {searchable && (\n <div className=\"sb-color-table__search\">\n <input\n type=\"search\"\n className=\"sb-color-table__search-input\"\n placeholder=\"Search colors…\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n aria-label=\"Fuzzy-search colors by path or value\"\n data-testid=\"color-table-search\"\n />\n </div>\n )}\n <div className=\"sb-color-table__scroll\">\n <table className=\"sb-color-table__table\">\n <caption className=\"sb-color-table__caption\">{captionText}</caption>\n <thead>\n <tr>\n <th className=\"sb-color-table__th sb-color-table__th--swatch\">\n <span className=\"sb-color-table__sr-only\">Swatch</span>\n </th>\n <th className=\"sb-color-table__th sb-color-table__th--path\">Name</th>\n <th className=\"sb-color-table__th\">Value</th>\n <th className=\"sb-color-table__th\">CSS var</th>\n <th className=\"sb-color-table__th\">Alias</th>\n <th className=\"sb-color-table__th sb-color-table__th--expand\">\n <span className=\"sb-color-table__sr-only\">Expand</span>\n </th>\n </tr>\n </thead>\n <tbody>\n {visibleGroups.length === 0 && (\n <tr>\n <td colSpan={COLUMN_COUNT} className=\"sb-color-table__td sb-color-table__empty-row\">\n No colors match \"{query.trim()}\".\n </td>\n </tr>\n )}\n {visibleGroups.map((group) => (\n <GroupRow\n key={group.base}\n group={group}\n selectedLabel={selectedByBase[group.base]}\n expanded={expandedByBase.has(group.base)}\n onToggleExpand={toggleExpand}\n onSelectVariant={selectVariant}\n {...(onSelect !== undefined && { onSelect })}\n />\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n\nfunction GroupRow({\n group,\n selectedLabel,\n expanded,\n onToggleExpand,\n onSelectVariant,\n onSelect,\n}: {\n group: Group;\n selectedLabel: string | undefined;\n expanded: boolean;\n onToggleExpand(base: string): void;\n onSelectVariant(base: string, label: string): void;\n onSelect?(path: string): void;\n}): ReactElement {\n const multi = group.variants.length > 1;\n const active =\n group.variants.find((v) => v.label === selectedLabel) ?? (group.variants[0] as Variant);\n const nameText = multi ? group.base : active.path;\n\n const handleRowActivate = (): void => {\n if (onSelect) onSelect(active.path);\n else onToggleExpand(group.base);\n };\n\n return (\n <>\n <tr\n className={cx('sb-color-table__row', {\n 'sb-color-table__row--expanded': expanded,\n })}\n onClick={handleRowActivate}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleRowActivate();\n }\n }}\n tabIndex={0}\n aria-label={\n onSelect\n ? `Inspect ${active.path}`\n : expanded\n ? `Collapse ${group.base}`\n : `Expand ${group.base}`\n }\n data-testid=\"color-table-row\"\n data-path={active.path}\n data-base={group.base}\n >\n <td className=\"sb-color-table__td sb-color-table__swatch-cell\">\n <span\n className=\"sb-color-table__swatch\"\n style={{ background: active.cssVar }}\n aria-hidden\n />\n </td>\n <td className={cx('sb-color-table__td', 'sb-color-table__path')}>\n <span className=\"sb-color-table__path-text\">{nameText}</span>\n {multi && (\n <span\n className=\"sb-color-table__variant-pills\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n role=\"presentation\"\n >\n {group.variants.map((v) => (\n <button\n key={v.label}\n type=\"button\"\n className={cx('sb-color-table__variant-pill', {\n 'sb-color-table__variant-pill--active': v.label === active.label,\n })}\n onClick={() => onSelectVariant(group.base, v.label)}\n aria-pressed={v.label === active.label}\n data-testid=\"color-table-variant\"\n data-variant={v.label}\n >\n {v.label}\n </button>\n ))}\n </span>\n )}\n </td>\n <ValueCell value={active.value} label={`Copy value ${active.value}`}>\n {active.outOfGamut && (\n <span\n title=\"Out of sRGB gamut for this format\"\n aria-label=\"out of gamut\"\n className=\"sb-color-table__gamut-warn\"\n >\n ⚠\n </span>\n )}\n </ValueCell>\n <ValueCell value={active.cssVar} label={`Copy CSS var ${active.cssVar}`} />\n <td className=\"sb-color-table__td sb-color-table__alias\">\n {active.aliasOf ? (\n <span className=\"sb-color-table__alias-text\">{active.aliasOf}</span>\n ) : (\n <span className=\"sb-color-table__alias-empty\" aria-hidden>\n —\n </span>\n )}\n </td>\n <td className=\"sb-color-table__td sb-color-table__expand-cell\">\n {!onSelect && (\n <span\n className={cx('sb-color-table__chevron', {\n 'sb-color-table__chevron--expanded': expanded,\n })}\n aria-hidden\n >\n ▸\n </span>\n )}\n </td>\n </tr>\n {expanded && !onSelect && (\n <tr className=\"sb-color-table__detail-row\" data-testid=\"color-table-detail\">\n <td colSpan={COLUMN_COUNT} className=\"sb-color-table__td sb-color-table__detail-cell\">\n <ExpandedDetail group={group} active={active} />\n </td>\n </tr>\n )}\n </>\n );\n}\n\nfunction ExpandedDetail({ group, active }: { group: Group; active: Variant }): ReactElement {\n const hasDescription = active.description !== undefined && active.description.length > 0;\n const chain = active.aliasChain && active.aliasChain.length > 0 ? active.aliasChain : undefined;\n const multi = group.variants.length > 1;\n\n return (\n <div className=\"sb-color-table__detail\">\n {hasDescription && <p className=\"sb-color-table__description\">{active.description}</p>}\n {chain && (\n <p className=\"sb-color-table__chain\">\n <span className=\"sb-color-table__detail-label\">Alias chain:</span> {chain.join(' → ')}\n </p>\n )}\n {multi && (\n <div className=\"sb-color-table__variant-grid\">\n <div className=\"sb-color-table__variant-grid-header\">All variants</div>\n <table className=\"sb-color-table__subtable\">\n <thead>\n <tr>\n <th className=\"sb-color-table__subth\">Variant</th>\n <th className=\"sb-color-table__subth\">Path</th>\n <th className=\"sb-color-table__subth\">HEX</th>\n <th className=\"sb-color-table__subth\">HSL</th>\n <th className=\"sb-color-table__subth\">OKLCH</th>\n </tr>\n </thead>\n <tbody>\n {group.variants.map((v) => (\n <tr\n key={v.label}\n className={cx({\n 'sb-color-table__subrow--active': v.label === active.label,\n })}\n >\n <td className=\"sb-color-table__subtd\">{v.label}</td>\n <td className=\"sb-color-table__subtd sb-color-table__subtd--path\">{v.path}</td>\n <td className=\"sb-color-table__subtd\">{v.hex}</td>\n <td className=\"sb-color-table__subtd\">{v.hsl}</td>\n <td className=\"sb-color-table__subtd\">{v.oklch}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n {!hasDescription && !chain && !multi && (\n <p className=\"sb-color-table__detail-empty\">\n No description or alias chain authored for this token.\n </p>\n )}\n </div>\n );\n}\n\nfunction ValueCell({\n value,\n label,\n children,\n}: {\n value: string;\n label: string;\n children?: ReactElement | false;\n}): ReactElement {\n return (\n <td className=\"sb-color-table__td sb-color-table__value-cell\">\n <span className=\"sb-color-table__value-text\" title={value}>\n {value}\n </span>\n {children}\n <span\n className=\"sb-color-table__copy-wrap\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n role=\"presentation\"\n >\n <CopyButton value={value} label={label} className=\"sb-color-table__copy\" />\n </span>\n </td>\n );\n}\n\ntype FormatColorResult = ReturnType<typeof formatColor>;\n\n/**\n * Pick the value + gamut flag to display in the single Value column based\n * on the active color-format context. We pre-compute hex/hsl/oklch for the\n * expanded sub-table regardless; the extras (`rgb`, `raw`) take a fresh\n * `formatColor` pass. Keeps the hot path fast while staying honest about\n * out-of-gamut warnings per-format.\n */\nfunction pickActiveFormat(\n raw: NormalizedColor,\n colorFormat: ColorFormat,\n hex: FormatColorResult,\n hsl: FormatColorResult,\n oklch: FormatColorResult,\n): { value: string; outOfGamut: boolean } {\n switch (colorFormat) {\n case 'hex':\n return { value: hex.value, outOfGamut: hex.outOfGamut };\n case 'hsl':\n return { value: hsl.value, outOfGamut: hsl.outOfGamut };\n case 'oklch':\n return { value: oklch.value, outOfGamut: oklch.outOfGamut };\n default: {\n const extra = formatColor(raw, colorFormat);\n return { value: extra.value, outOfGamut: extra.outOfGamut };\n }\n }\n}\n\ninterface VariantEntry {\n label: string;\n suffix: string;\n}\n\ninterface VariantDefs {\n /** Match iteration order — longest suffix first. */\n matchOrder: readonly VariantEntry[];\n /** Display iteration order — preserves the caller's declared order. */\n displayOrder: readonly string[];\n}\n\nfunction buildVariantDefs(variants: Record<string, string> | undefined): VariantDefs {\n if (!variants) return { matchOrder: [], displayOrder: [] };\n const entries: VariantEntry[] = [];\n const displayOrder: string[] = [];\n for (const [label, suffix] of Object.entries(variants)) {\n if (suffix.length === 0) continue;\n entries.push({ label, suffix });\n displayOrder.push(label);\n }\n const matchOrder = entries.toSorted((a, b) => b.suffix.length - a.suffix.length);\n return { matchOrder, displayOrder };\n}\n\n/**\n * Position of a label within a group — the `base` entry always sorts first,\n * then declared labels in the order the caller wrote them in the `variants`\n * prop. Unknown labels (shouldn't happen in practice) fall to the end.\n */\nfunction orderIndex(label: string, defs: VariantDefs): number {\n if (label === BASE_LABEL) return -1;\n const idx = defs.displayOrder.indexOf(label);\n return idx >= 0 ? idx : Number.POSITIVE_INFINITY;\n}\n\n/**\n * Resolve the variant label + base path for a token, if any. The leaf\n * (last dot-segment) must either equal the suffix outright (dot-segment\n * form: `hi.disabled` matches suffix `disabled`) or end in `-<suffix>`\n * (hyphen-tail form: `hi-d` matches `d`). The leading hyphen is required\n * for the tail form so suffix `0` can't hit `neutral-900` by character.\n *\n * Returned `basePath` is what gets used as the grouping key:\n * - Dot-segment match → parent path (drop the last dot-segment)\n * - Hyphen-tail match → same dot-depth, leaf with `-<suffix>` stripped\n *\n * Entries in `matchOrder` are pre-sorted longest-first, so `h-dark` wins\n * over `dark` for a path ending in `-h-dark`.\n */\nfunction matchVariant(\n path: string,\n matchOrder: readonly VariantEntry[],\n): { label: string; basePath: string } | undefined {\n if (matchOrder.length === 0) return undefined;\n const segments = path.split('.');\n const leaf = segments.at(-1) ?? path;\n for (const entry of matchOrder) {\n if (leaf === entry.suffix) {\n const parent = segments.slice(0, -1).join('.');\n if (parent.length === 0) continue;\n return { label: entry.label, basePath: parent };\n }\n const tailMarker = `-${entry.suffix}`;\n if (leaf.endsWith(tailMarker)) {\n const trimmed = leaf.slice(0, -tailMarker.length);\n if (trimmed.length === 0) continue;\n const copy = segments.slice(0, -1);\n copy.push(trimmed);\n return { label: entry.label, basePath: copy.join('.') };\n }\n }\n return undefined;\n}\n","import cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport './Diagnostics.css';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { useProject } from '#/internal/use-project.ts';\nimport type { VirtualDiagnostic } from '#/types.ts';\n\nexport interface DiagnosticsProps {\n /** Override the section caption. Defaults to a severity summary. */\n caption?: string;\n}\n\ntype DiagnosticSeverity = VirtualDiagnostic['severity'];\n\nconst severityLabel: Record<DiagnosticSeverity, string> = {\n error: 'ERROR',\n warn: 'WARN',\n info: 'INFO',\n};\n\nfunction summaryText(diagnostics: readonly VirtualDiagnostic[]): string {\n if (diagnostics.length === 0) return '✔ OK · no diagnostics';\n const counts = { error: 0, warn: 0, info: 0 };\n for (const d of diagnostics) counts[d.severity] += 1;\n const parts: string[] = [];\n if (counts.error > 0) parts.push(`✖ ${counts.error} error${counts.error === 1 ? '' : 's'}`);\n if (counts.warn > 0) parts.push(`⚠ ${counts.warn} warning${counts.warn === 1 ? '' : 's'}`);\n if (counts.info > 0) parts.push(`${counts.info} info`);\n return parts.join(' · ');\n}\n\nfunction diagnosticKey(d: VirtualDiagnostic, i: number): string {\n return `${d.severity}:${d.group}:${d.filename ?? ''}:${d.line ?? ''}:${d.message}:${i}`;\n}\n\nfunction summaryVariant(diagnostics: readonly VirtualDiagnostic[]): 'ok' | 'error' | 'warn' | null {\n if (diagnostics.length === 0) return 'ok';\n if (diagnostics.some((d) => d.severity === 'error')) return 'error';\n if (diagnostics.some((d) => d.severity === 'warn')) return 'warn';\n return null;\n}\n\n/**\n * Render the project's load diagnostics — parser errors, resolver warnings,\n * disabled-axes validation issues, etc. — as a collapsible list. Auto-opens\n * when the project carries errors or warnings; stays collapsed for clean\n * loads and info-only loads.\n *\n * Replaces the diagnostics section from the addon's (now-retired) Design\n * Tokens panel. Consumers compose it alongside TokenNavigator / TokenTable\n * on their own MDX pages.\n */\nexport function Diagnostics({ caption }: DiagnosticsProps = {}): ReactElement {\n const { activeTheme, cssVarPrefix, diagnostics } = useProject();\n\n const hasErrorsOrWarnings = diagnostics.some(\n (d) => d.severity === 'error' || d.severity === 'warn',\n );\n const headingText = caption ?? `Diagnostics · ${summaryText(diagnostics)}`;\n const variant = summaryVariant(diagnostics);\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)} data-testid=\"diagnostics\">\n <details open={hasErrorsOrWarnings}>\n <summary\n className={cx(\n 'sb-diagnostics__summary',\n variant && `sb-diagnostics__summary--${variant}`,\n )}\n >\n {headingText}\n </summary>\n {diagnostics.length > 0 && (\n <ul className=\"sb-diagnostics__list\">\n {diagnostics.map((d, i) => (\n <li key={diagnosticKey(d, i)} className=\"sb-diagnostics__row\">\n <span\n className={cx('sb-diagnostics__label', {\n [`sb-diagnostics__label--${d.severity}`]: d.severity !== 'info',\n })}\n >\n {severityLabel[d.severity]}\n </span>\n <div>\n <div>{d.message}</div>\n {(d.group || d.filename) && (\n <div className=\"sb-diagnostics__meta\">\n {[d.group, d.filename, d.line ? `:${d.line}` : '']\n .filter(Boolean)\n .join(' · ')}\n </div>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </details>\n </div>\n );\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { BORDER_STRONG } from '#/internal/styles.tsx';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\n\nexport type DimensionKind = 'length' | 'radius' | 'size';\n\nexport interface DimensionBarProps {\n /** Full dot-path of the dimension token to preview. */\n path: string;\n /**\n * Visualization kind:\n * - `'length'` (default): horizontal bar whose width equals the token's dimension.\n * - `'radius'`: 56×56 square with the token applied as `border-radius`.\n * - `'size'`: a square sized to the token's dimension.\n */\n kind?: DimensionKind;\n}\n\nconst MAX_RENDER_PX = 480;\n\nconst styles = {\n bar: {\n height: 14,\n background: 'var(--swatchbook-accent-bg, #3b82f6)',\n borderRadius: 2,\n minWidth: 1,\n } satisfies CSSProperties,\n radiusSample: {\n width: 56,\n height: 56,\n background: 'var(--swatchbook-accent-bg, #3b82f6)',\n border: BORDER_STRONG,\n } satisfies CSSProperties,\n sizeSample: {\n background: 'var(--swatchbook-accent-bg, #3b82f6)',\n border: BORDER_STRONG,\n minWidth: 1,\n minHeight: 1,\n } satisfies CSSProperties,\n};\n\n/**\n * Convert a DTCG dimension `$value` (`{ value, unit }`) to pixels for the\n * purpose of deciding whether to cap the rendered bar. Returns `NaN` for\n * units we can't reasonably approximate (ex / ch / %), which the caller\n * treats as \"render at cssVar but don't cap\".\n */\nfunction toPixels(raw: unknown): number {\n if (raw == null || typeof raw !== 'object') return Number.NaN;\n const v = raw as { value?: unknown; unit?: unknown };\n if (typeof v.value !== 'number' || typeof v.unit !== 'string') return Number.NaN;\n switch (v.unit) {\n case 'px':\n return v.value;\n case 'rem':\n case 'em':\n return v.value * 16;\n default:\n return Number.NaN;\n }\n}\n\nexport function DimensionBar({ path, kind = 'length' }: DimensionBarProps): ReactElement {\n const project = useProject();\n const { resolved } = project;\n const cssVar = resolveCssVar(path, project);\n const token = resolved[path];\n const pxValue = toPixels(token?.$value);\n const capped = Number.isFinite(pxValue) && pxValue > MAX_RENDER_PX;\n const cappedValue = capped ? `${MAX_RENDER_PX}px` : cssVar;\n\n switch (kind) {\n case 'radius':\n return <div style={{ ...styles.radiusSample, borderRadius: cssVar }} aria-hidden />;\n case 'size':\n return (\n <div\n style={{ ...styles.sizeSample, width: cappedValue, height: cappedValue }}\n aria-hidden\n />\n );\n case 'length':\n default:\n return <div style={{ ...styles.bar, width: cappedValue }} aria-hidden />;\n }\n}\n","import type { VirtualTokenListingShape } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat } from '#/format-color.ts';\nimport type {\n BorderValue,\n DashedStrokeStyleValue,\n ShadowLayer,\n} from '#/internal/composite-types.ts';\n\n/**\n * Single-line display string for any DTCG token `$value`. Prefers\n * plugin-css's `previewValue` from the Token Listing; for color\n * tokens only when the toolbar format is hex (other formats route\n * through local colorjs.io).\n */\nexport function formatTokenValue(\n value: unknown,\n $type: string | undefined,\n colorFormat: ColorFormat,\n listingEntry?: VirtualTokenListingShape,\n): string {\n if (value == null) return '';\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n\n const preview = listingEntry?.previewValue;\n if (preview !== undefined) {\n const previewStr = typeof preview === 'string' ? cleanFloatNoise(preview) : String(preview);\n if ($type !== 'color') return previewStr;\n if (colorFormat === 'hex') return previewStr;\n }\n\n switch ($type) {\n case 'color':\n return formatColor(value, colorFormat).value;\n case 'dimension':\n case 'duration':\n return formatDimension(value);\n case 'fontFamily':\n return formatFontFamily(value);\n case 'fontWeight':\n case 'lineHeight':\n case 'letterSpacing':\n case 'opacity':\n case 'number':\n return formatPrimitive(value);\n case 'cubicBezier':\n return formatCubicBezier(value);\n case 'strokeStyle':\n return formatStrokeStyle(value);\n case 'shadow':\n return formatShadow(value, colorFormat);\n case 'border':\n return formatBorder(value, colorFormat);\n default:\n return formatUnknown(value);\n }\n}\n\nfunction formatDimension(v: unknown): string {\n if (typeof v === 'string' || typeof v === 'number') return String(v);\n if (v && typeof v === 'object') {\n const d = v as { value?: unknown; unit?: unknown };\n if (typeof d.value === 'number' && typeof d.unit === 'string') return `${d.value}${d.unit}`;\n }\n return formatUnknown(v);\n}\n\nfunction cleanFloatNoise(s: string): string {\n return s.replace(/-?\\d+\\.\\d{8,}/g, (m) => `${+Number(m).toFixed(3)}`);\n}\n\nfunction formatFontFamily(v: unknown): string {\n if (typeof v === 'string') return v;\n if (Array.isArray(v)) return v.map(String).join(', ');\n return formatUnknown(v);\n}\n\nfunction formatPrimitive(v: unknown): string {\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return String(v);\n return formatUnknown(v);\n}\n\nfunction formatCubicBezier(v: unknown): string {\n if (Array.isArray(v) && v.length === 4) {\n return `cubic-bezier(${v.map((n) => (typeof n === 'number' ? n : 0)).join(', ')})`;\n }\n return formatUnknown(v);\n}\n\nfunction formatStrokeStyle(v: unknown): string {\n if (typeof v === 'string') return v;\n if (v && typeof v === 'object') {\n const s = v as DashedStrokeStyleValue;\n const parts: string[] = ['dashed'];\n if (Array.isArray(s.dashArray)) {\n parts.push(s.dashArray.map((n) => formatDimension(n)).join(' '));\n }\n if (typeof s.lineCap === 'string') parts.push(s.lineCap);\n return parts.join(' · ');\n }\n return formatUnknown(v);\n}\n\nfunction formatShadow(v: unknown, colorFormat: ColorFormat): string {\n const layers = Array.isArray(v) ? v : [v];\n const parts = layers.map((layer) => {\n if (!layer || typeof layer !== 'object') return formatUnknown(layer);\n const s = layer as ShadowLayer;\n const pieces = [\n formatDimension(s.offsetX),\n formatDimension(s.offsetY),\n formatDimension(s.blur),\n formatDimension(s.spread),\n formatColor(s.color, colorFormat).value,\n ].filter((p) => p !== '');\n if (s.inset) pieces.push('inset');\n return pieces.join(' ');\n });\n return parts.join(', ');\n}\n\nfunction formatBorder(v: unknown, colorFormat: ColorFormat): string {\n if (!v || typeof v !== 'object') return formatUnknown(v);\n const b = v as BorderValue;\n const width = formatDimension(b.width);\n const style = formatPrimitive(b.style);\n const color = formatColor(b.color, colorFormat).value;\n return [width, style, color].filter((p) => p !== '').join(' ');\n}\n\nfunction formatUnknown(v: unknown): string {\n if (v == null) return '';\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return String(v);\n try {\n return JSON.stringify(v).slice(0, 120);\n } catch {\n return String(v);\n }\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './DimensionScale.css';\nimport { DimensionBar } from '#/dimension-scale/DimensionBar.tsx';\nimport type { DimensionKind } from '#/dimension-scale/DimensionBar.tsx';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport type { DimensionKind };\n\nexport interface DimensionScaleProps {\n /**\n * Token-path filter. Defaults to every `dimension` token. Use e.g.\n * `\"space.*\"` to scope to the spacing scale.\n */\n filter?: string;\n /**\n * Visualization kind:\n * - `'length'` (default): horizontal bar whose width equals the token's dimension.\n * - `'radius'`: 56×56 square with the token applied as `border-radius`.\n * - `'size'`: a square sized to the token's dimension.\n */\n kind?: DimensionKind;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order.\n * - `'value'` (default) — numeric by rendered pixel size (`px` / `rem` / `em`).\n * Non-convertible units (ex/ch/%) land after the convertible ones.\n * - `'path'` — lexicographic on the dot-path.\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\nconst MAX_RENDER_PX = 480;\n\ninterface Row {\n path: string;\n cssVar: string;\n displayValue: string;\n pxValue: number;\n capped: boolean;\n}\n\nfunction toPixels(raw: unknown): number {\n if (raw == null || typeof raw !== 'object') return Number.NaN;\n const v = raw as { value?: unknown; unit?: unknown };\n if (typeof v.value !== 'number' || typeof v.unit !== 'string') return Number.NaN;\n switch (v.unit) {\n case 'px':\n return v.value;\n case 'rem':\n case 'em':\n return v.value * 16;\n default:\n return Number.NaN;\n }\n}\n\nexport function DimensionScale({\n filter,\n kind = 'length',\n caption,\n sortBy = 'value',\n sortDir = 'asc',\n}: DimensionScaleProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'dimension') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => {\n const pxValue = toPixels(token.$value);\n return {\n path,\n cssVar: resolveCssVar(path, project),\n displayValue: formatTokenValue(token.$value, token.$type, 'raw', project.listing[path]),\n pxValue,\n capped: Number.isFinite(pxValue) && pxValue > MAX_RENDER_PX,\n };\n });\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} dimension${rows.length === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No dimension tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-dimension-scale__row\">\n <div className=\"sb-dimension-scale__meta\">\n <span className=\"sb-dimension-scale__path\">{row.path}</span>\n <span className=\"sb-dimension-scale__specs\">{row.displayValue}</span>\n </div>\n <div className=\"sb-dimension-scale__visual-cell\">\n <DimensionBar path={row.path} kind={kind} />\n {row.capped && (\n <span className=\"sb-dimension-scale__cap\">capped at {MAX_RENDER_PX}px</span>\n )}\n </div>\n <span className=\"sb-dimension-scale__css-var\">{row.cssVar}</span>\n </div>\n ))}\n </div>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './FontFamilySample.css';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\n\nexport interface FontFamilySampleProps {\n /**\n * Token-path filter. Defaults to every `fontFamily` token. Use e.g.\n * `\"font.family.*\"` to scope to the ref layer.\n */\n filter?: string;\n /** Override the sample text rendered for each token. */\n sample?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` ordering falls through to path for this block's\n * type (composite / non-numeric); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n stack: string;\n}\n\nfunction stackString(raw: unknown): string {\n if (typeof raw === 'string') return raw;\n if (Array.isArray(raw)) return raw.map(String).join(', ');\n return '';\n}\n\nexport function FontFamilySample({\n filter,\n sample = 'The quick brown fox jumps over the lazy dog.',\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: FontFamilySampleProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'fontFamily') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n stack: stackString(token.$value),\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} fontFamily token${rows.length === 1 ? '' : 's'}${filter && filter !== 'fontFamily' ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No fontFamily tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-font-family-sample__row\">\n <div className=\"sb-font-family-sample__meta\">\n <span className=\"sb-font-family-sample__path\">{row.path}</span>\n <span className=\"sb-font-family-sample__stack\">{row.stack}</span>\n </div>\n <div className=\"sb-font-family-sample__sample\" style={{ fontFamily: row.cssVar }}>\n {sample}\n </div>\n <span className=\"sb-font-family-sample__css-var\">{row.cssVar}</span>\n </div>\n ))}\n </div>\n );\n}\n","/**\n * Coerce a CSS `var(--…)` reference into the numeric slot of a React\n * inline-style property.\n *\n * React's `CSSProperties` types unitless properties (`fontWeight`,\n * `lineHeight`, `zIndex`, …) as `number`. The DOM accepts a string at\n * runtime — the rendered stylesheet just receives whatever React passes —\n * so a `var(--font-weight)` reference works functionally. TypeScript still\n * complains. Centralising the type assertion in one named helper keeps\n * the gap visible (and greppable) instead of scattering casts across\n * block components that want CSS-var-driven typography or layout values.\n */\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-expect-error — React's CSSProperties slot is `number`; the DOM tolerates a CSS var string.\nexport const cssVarAsNumber = (varRef: string): number => varRef;\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './FontWeightScale.css';\nimport { cssVarAsNumber } from '#/internal/css-var-style.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface FontWeightScaleProps {\n /**\n * Token-path filter. Defaults to every `fontWeight` token. Use e.g.\n * `\"font.weight.*\"` to scope to the ref layer.\n */\n filter?: string;\n /** Override the sample text rendered for each token. */\n sample?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order.\n * - `'value'` (default) — ascending numeric by weight (100 → 900).\n * - `'path'` — lexicographic on the dot-path.\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n display: string;\n weight: number;\n}\n\nfunction toWeight(raw: unknown): number {\n if (typeof raw === 'number') return raw;\n if (typeof raw === 'string') {\n const n = Number.parseInt(raw, 10);\n return Number.isFinite(n) ? n : Number.NaN;\n }\n return Number.NaN;\n}\n\nexport function FontWeightScale({\n filter,\n sample = 'Aa',\n caption,\n sortBy = 'value',\n sortDir = 'asc',\n}: FontWeightScaleProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'fontWeight') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n display: token.$value == null ? '' : String(token.$value),\n weight: toWeight(token.$value),\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} fontWeight token${rows.length === 1 ? '' : 's'}${filter && filter !== 'fontWeight' ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No fontWeight tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-font-weight-scale__row\">\n <div className=\"sb-font-weight-scale__meta\">\n <span className=\"sb-font-weight-scale__path\">{row.path}</span>\n <span className=\"sb-font-weight-scale__value\">{row.display}</span>\n </div>\n <div\n className=\"sb-font-weight-scale__sample\"\n style={{ fontWeight: cssVarAsNumber(row.cssVar) }}\n >\n {sample}\n </div>\n <span className=\"sb-font-weight-scale__css-var\">{row.cssVar}</span>\n </div>\n ))}\n </div>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './GradientPalette.css';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface GradientPaletteProps {\n /**\n * Token-path filter. Defaults to every `gradient` token. Use e.g.\n * `\"gradient.*\"` or `\"gradient.accent\"` to scope.\n */\n filter?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` falls through to path (gradients don't have\n * a single-axis ordering); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface GradientStop {\n color?: {\n colorSpace?: string;\n components?: readonly number[];\n alpha?: number;\n };\n position?: number;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n stops: GradientStop[];\n}\n\nfunction asStops(raw: unknown): GradientStop[] {\n if (!Array.isArray(raw)) return [];\n return raw as GradientStop[];\n}\n\nconst pct = (n: number): string => `${(n * 100).toFixed(3)}%`;\n\nfunction stopCssColor(stop: GradientStop): string {\n const color = stop.color;\n if (!color || !Array.isArray(color.components) || color.components.length < 3) {\n return 'transparent';\n }\n const [r, g, b] = color.components;\n if (r === undefined || g === undefined || b === undefined) return 'transparent';\n const alpha = color.alpha ?? 1;\n return alpha === 1\n ? `rgb(${pct(r)} ${pct(g)} ${pct(b)})`\n : `rgb(${pct(r)} ${pct(g)} ${pct(b)} / ${alpha})`;\n}\n\nfunction stopKey(path: string, stop: GradientStop, fallback: number): string {\n return `${path}|${stop.position ?? fallback}|${stopCssColor(stop)}`;\n}\n\nexport function GradientPalette({\n filter,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: GradientPaletteProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'gradient') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n stops: asStops(token.$value),\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} gradient${rows.length === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No gradient tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-gradient-palette__row\">\n <div className=\"sb-gradient-palette__meta\">\n <span className=\"sb-gradient-palette__path\">{row.path}</span>\n <span className=\"sb-gradient-palette__css-var\">{row.cssVar}</span>\n </div>\n <div\n className=\"sb-gradient-palette__sample\"\n style={{ background: `linear-gradient(to right, ${row.cssVar})` }}\n aria-hidden\n />\n <div className=\"sb-gradient-palette__stops\">\n {row.stops.map((stop, i) => (\n <div key={stopKey(row.path, stop, i)} className=\"sb-gradient-palette__stop-row\">\n <span\n className=\"sb-gradient-palette__stop-swatch\"\n style={{ background: stopCssColor(stop) }}\n aria-hidden\n />\n <span>{formatColor(stop.color, colorFormat).value}</span>\n <span className=\"sb-gradient-palette__stop-position\">\n @ {((stop.position ?? 0) * 100).toFixed(0)}%\n </span>\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\n\n/**\n * True when rendering inside Chromatic's snapshot runner. Chromatic's\n * browser ships a recognisable user-agent string; checked here so\n * motion-looping components can fall back to their static state for\n * deterministic snapshots. Per-component detection rather than the\n * global `chromatic.prefersReducedMotion: true` parameter — that\n * parameter is incompatible with Chromatic's verification parser.\n */\nfunction isChromatic(): boolean {\n if (typeof navigator === 'undefined') return false;\n return navigator.userAgent.includes('Chromatic');\n}\n\n/**\n * Reactive `prefers-reduced-motion: reduce` detector. Returns the current\n * match and updates if the user toggles the OS-level preference. Also\n * returns `true` under Chromatic to keep animated samples deterministic\n * during visual regression capture.\n */\nexport function usePrefersReducedMotion(): boolean {\n const [reduced, setReduced] = useState(false);\n useEffect(() => {\n if (typeof window === 'undefined') return;\n if (isChromatic()) {\n setReduced(true);\n return;\n }\n const query = window.matchMedia('(prefers-reduced-motion: reduce)');\n setReduced(query.matches);\n const onChange = (e: MediaQueryListEvent): void => setReduced(e.matches);\n query.addEventListener('change', onChange);\n return () => query.removeEventListener('change', onChange);\n }, []);\n return reduced;\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { SURFACE_MUTED, TEXT_MUTED } from '#/internal/styles.tsx';\nimport { useEffect, useMemo, useState } from 'react';\nimport { usePrefersReducedMotion } from '#/internal/prefers-reduced-motion.ts';\nimport { useProject } from '#/internal/use-project.ts';\n\nexport type MotionSpeed = 0.25 | 0.5 | 1 | 2;\n\nexport interface MotionSampleProps {\n /** Full dot-path of the motion token (`transition`, `duration`, or `cubicBezier`). */\n path: string;\n /** Playback speed multiplier. Defaults to `1`. */\n speed?: MotionSpeed;\n /**\n * Change this value to force the animation to restart. Useful when an\n * outer block exposes a \"replay\" button that should re-trigger every\n * sample at once.\n */\n runKey?: number;\n}\n\nconst DEFAULT_DURATION_MS = 300;\nconst DEFAULT_EASING = 'cubic-bezier(0.2, 0, 0, 1)';\n\nconst styles = {\n track: {\n position: 'relative',\n height: 36,\n background: SURFACE_MUTED,\n borderRadius: 18,\n overflow: 'hidden',\n } satisfies CSSProperties,\n ball: {\n position: 'absolute',\n top: '50%',\n width: 28,\n height: 28,\n marginTop: -14,\n borderRadius: '50%',\n background: 'var(--swatchbook-accent-bg, #3b82f6)',\n } satisfies CSSProperties,\n reducedMotion: {\n fontSize: 11,\n color: TEXT_MUTED,\n fontStyle: 'italic',\n } satisfies CSSProperties,\n};\n\ninterface Spec {\n durationMs: number;\n easing: string;\n}\n\nfunction extractDurationMs(raw: unknown): number {\n if (raw == null) return Number.NaN;\n if (typeof raw === 'object') {\n const v = raw as { value?: unknown; unit?: unknown };\n if (typeof v.value === 'number' && typeof v.unit === 'string') {\n if (v.unit === 'ms') return v.value;\n if (v.unit === 's') return v.value * 1000;\n }\n }\n return Number.NaN;\n}\n\nfunction extractCubicBezier(raw: unknown): string | null {\n if (Array.isArray(raw) && raw.length === 4 && raw.every((n) => typeof n === 'number')) {\n return `cubic-bezier(${raw.map((n) => Number(n).toFixed(3)).join(', ')})`;\n }\n return null;\n}\n\nfunction asDuration(\n raw: unknown,\n themeTokens: Record<string, { $value?: unknown }>,\n fallback: number,\n): number {\n const direct = extractDurationMs(raw);\n if (Number.isFinite(direct)) return direct;\n if (typeof raw === 'string') {\n const match = raw.match(/^\\{([^}]+)\\}$/);\n if (match && match[1]) {\n const referenced = themeTokens[match[1]];\n const resolved = extractDurationMs(referenced?.$value);\n if (Number.isFinite(resolved)) return resolved;\n }\n }\n return fallback;\n}\n\nfunction asEasing(\n raw: unknown,\n themeTokens: Record<string, { $value?: unknown }>,\n fallback: string,\n): string {\n const direct = extractCubicBezier(raw);\n if (direct) return direct;\n if (typeof raw === 'string') {\n const match = raw.match(/^\\{([^}]+)\\}$/);\n if (match && match[1]) {\n const referenced = themeTokens[match[1]];\n const resolved = extractCubicBezier(referenced?.$value);\n if (resolved) return resolved;\n }\n }\n return fallback;\n}\n\nexport function resolveMotionSpec(\n token: { $type?: string | undefined; $value?: unknown } | undefined,\n themeTokens: Record<string, { $value?: unknown }>,\n): Spec | null {\n if (!token) return null;\n const type = token.$type;\n if (type === 'transition') {\n const v = (token.$value ?? {}) as {\n duration?: unknown;\n timingFunction?: unknown;\n };\n return {\n durationMs: asDuration(v.duration, themeTokens, DEFAULT_DURATION_MS),\n easing: asEasing(v.timingFunction, themeTokens, DEFAULT_EASING),\n };\n }\n if (type === 'duration') {\n const durationMs = extractDurationMs(token.$value);\n if (!Number.isFinite(durationMs)) return null;\n return { durationMs, easing: DEFAULT_EASING };\n }\n if (type === 'cubicBezier') {\n const easing = extractCubicBezier(token.$value);\n if (!easing) return null;\n return { durationMs: DEFAULT_DURATION_MS, easing };\n }\n return null;\n}\n\nexport function MotionSample({ path, speed = 1, runKey = 0 }: MotionSampleProps): ReactElement {\n const { resolved } = useProject();\n const reducedMotion = usePrefersReducedMotion();\n\n const spec = useMemo(() => resolveMotionSpec(resolved[path], resolved), [resolved, path]);\n\n const durationMs = spec?.durationMs ?? DEFAULT_DURATION_MS;\n const easing = spec?.easing ?? DEFAULT_EASING;\n const scaledDuration = Math.max(1, durationMs / speed);\n\n const [phase, setPhase] = useState<0 | 1>(0);\n\n useEffect(() => {\n if (reducedMotion) return;\n setPhase(0);\n const id = requestAnimationFrame(() => setPhase(1));\n const loop = window.setInterval(() => {\n setPhase((p) => (p === 0 ? 1 : 0));\n }, scaledDuration * 2);\n return () => {\n cancelAnimationFrame(id);\n window.clearInterval(loop);\n };\n }, [scaledDuration, runKey, reducedMotion]);\n\n if (reducedMotion) {\n return (\n <div style={styles.reducedMotion}>\n Animation suppressed by `prefers-reduced-motion: reduce`.\n </div>\n );\n }\n\n return (\n <div style={styles.track}>\n <div\n style={{\n ...styles.ball,\n left: phase === 1 ? 'calc(100% - 32px)' : '4px',\n transition: `left ${scaledDuration}ms ${easing}`,\n }}\n aria-hidden\n />\n </div>\n );\n}\n","import cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport { useMemo, useState } from 'react';\nimport './MotionPreview.css';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { usePrefersReducedMotion } from '#/internal/prefers-reduced-motion.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\nimport { MotionSample, resolveMotionSpec } from '#/motion-preview/MotionSample.tsx';\nimport type { MotionSpeed } from '#/motion-preview/MotionSample.tsx';\n\nexport type { MotionSpeed };\n\nexport interface MotionPreviewProps {\n /**\n * Token-path filter. Defaults to transition + duration + cubicBezier\n * tokens. Use e.g. `\"transition.*\"` to scope to the semantic layer.\n */\n filter?: string;\n /** Override the caption. */\n caption?: string;\n}\n\nconst SPEEDS: MotionSpeed[] = [0.25, 0.5, 1, 2];\n\ninterface Row {\n path: string;\n cssVar: string;\n durationMs: number;\n easing: string;\n kind: 'transition' | 'duration' | 'cubicBezier';\n}\n\nfunction formatSpec(row: Row): string {\n switch (row.kind) {\n case 'transition':\n return `transition · ${Math.round(row.durationMs)}ms · ${row.easing}`;\n case 'duration':\n return `duration · ${Math.round(row.durationMs)}ms`;\n case 'cubicBezier':\n return `cubicBezier · ${row.easing}`;\n }\n}\n\nexport function MotionPreview({ filter, caption }: MotionPreviewProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n const [speed, setSpeed] = useState<MotionSpeed>(1);\n const [run, setRun] = useState(0);\n const reducedMotion = usePrefersReducedMotion();\n\n const rows = useMemo(() => {\n const collected: Row[] = [];\n for (const [path, token] of Object.entries(resolved)) {\n if (filter && !matchPath(path, filter)) continue;\n if (!filter && !['transition', 'duration', 'cubicBezier'].includes(token.$type ?? '')) {\n continue;\n }\n const kind = token.$type as Row['kind'] | undefined;\n if (!kind) continue;\n const spec = resolveMotionSpec(token, resolved);\n if (!spec) continue;\n collected.push({\n path,\n cssVar: resolveCssVar(path, project),\n durationMs: spec.durationMs,\n easing: spec.easing,\n kind,\n });\n }\n collected.sort((a, b) => {\n if (a.kind !== b.kind) return a.kind.localeCompare(b.kind);\n return a.path.localeCompare(b.path, undefined, { numeric: true });\n });\n return collected;\n }, [resolved, filter, project]);\n\n const captionText =\n caption ??\n `${rows.length} motion token${rows.length === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No motion tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n <div className=\"sb-motion-preview__controls\">\n <span className=\"sb-motion-preview__control-label\">Speed</span>\n {SPEEDS.map((s) => (\n <button\n key={s}\n type=\"button\"\n className={cx('sb-motion-preview__speed-btn', {\n 'sb-motion-preview__speed-btn--active': s === speed,\n })}\n onClick={() => setSpeed(s)}\n >\n {s}×\n </button>\n ))}\n <button\n type=\"button\"\n className=\"sb-motion-preview__replay-btn\"\n onClick={() => setRun((n) => n + 1)}\n disabled={reducedMotion}\n title={reducedMotion ? 'Disabled by prefers-reduced-motion' : 'Replay all'}\n >\n ↻ Replay\n </button>\n </div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-motion-preview__row\">\n <div className=\"sb-motion-preview__meta\">\n <span className=\"sb-motion-preview__path\">{row.path}</span>\n <span className=\"sb-motion-preview__specs\">{formatSpec(row)}</span>\n </div>\n <MotionSample path={row.path} speed={speed} runKey={run} />\n <span className=\"sb-motion-preview__css-var\">{row.cssVar}</span>\n </div>\n ))}\n </div>\n );\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './OpacityScale.css';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface OpacityScaleProps {\n /**\n * Token-path filter. Use `\"number.opacity.*\"` or `\"opacity.*\"` depending\n * on your layout. Omit to match every `$type: 'number'` token whose\n * value is in `[0, 1]` — the value-range check (applied alongside\n * the glob) keeps line-heights / z-indexes out.\n */\n filter?: string;\n /**\n * DTCG `$type` filter. `opacity` tokens where DTCG ships them as a\n * dedicated type; otherwise `number` (the common placement pre-spec).\n * Accepts either.\n */\n type?: 'number' | 'opacity';\n /**\n * Sample token rendered at each opacity. Defaults to `color.accent.bg`\n * — swap to whatever colour your system uses to demonstrate scrim /\n * overlay behaviour.\n */\n sampleColor?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order.\n * - `'value'` (default) — numeric, low opacity first.\n * - `'path'` — lexicographic on the dot-path.\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n opacity: number;\n displayValue: string;\n}\n\nfunction toOpacity(raw: unknown): number {\n if (typeof raw === 'number') return raw;\n return Number.NaN;\n}\n\n/**\n * Render each opacity token as a colored sample at that opacity over a\n * checkerboard backdrop, so the transparency is visually readable. The\n * number by itself (`0.4`) doesn't convey what the token looks like\n * applied to a surface; the sample does.\n *\n * Only tokens whose `$value` is a finite number between 0 and 1\n * inclusive are rendered — non-opacity `number` siblings (`line-height`,\n * `z-index`) fall out naturally.\n */\nexport function OpacityScale({\n filter,\n type = 'number',\n sampleColor = 'color.accent.bg',\n caption,\n sortBy = 'value',\n sortDir = 'asc',\n}: OpacityScaleProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== type) return false;\n const v = toOpacity(token.$value);\n if (!Number.isFinite(v) || v < 0 || v > 1) return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => {\n const opacity = toOpacity(token.$value);\n return {\n path,\n cssVar: resolveCssVar(path, project),\n opacity,\n displayValue: String(opacity),\n };\n });\n }, [resolved, filter, type, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} opacity token${rows.length === 1 ? '' : 's'}${\n filter ? ` matching \\`${filter}\\`` : ''\n } · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No opacity tokens match this filter.</div>\n </div>\n );\n }\n\n const sampleColorVar = resolveCssVar(sampleColor, project);\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n <div className=\"sb-opacity-scale__grid\">\n {rows.map((row) => (\n <div key={row.path} className=\"sb-opacity-scale__card\">\n <div\n className=\"sb-opacity-scale__swatch\"\n style={\n {\n '--sb-opacity-scale-color': sampleColorVar,\n '--sb-opacity-scale-alpha': String(row.opacity),\n } as CSSProperties\n }\n aria-hidden\n />\n <div className=\"sb-opacity-scale__meta\">\n <span className=\"sb-opacity-scale__path\">{row.path}</span>\n <span className=\"sb-opacity-scale__value\">{row.displayValue}</span>\n <span className=\"sb-opacity-scale__css-var\">{row.cssVar}</span>\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import type { ReactElement, ReactNode } from 'react';\nimport { SwatchbookContext, useOptionalSwatchbookData } from '#/contexts.ts';\nimport type { ProjectSnapshot } from '#/contexts.ts';\n\nexport type { ProjectSnapshot };\n\nexport interface SwatchbookProviderProps {\n value: ProjectSnapshot;\n children: ReactNode;\n}\n\n/**\n * Wraps a tree of blocks with the token data they need to render.\n *\n * The Storybook addon's preview decorator mounts this automatically, so\n * story/MDX authors typically never see it. Outside Storybook — unit\n * tests, custom React apps, non-Storybook doc sites — consumers construct\n * a {@link ProjectSnapshot} (often imported from a JSON file) and wrap\n * their blocks in this provider.\n */\nexport function SwatchbookProvider({ value, children }: SwatchbookProviderProps): ReactElement {\n return <SwatchbookContext.Provider value={value}>{children}</SwatchbookContext.Provider>;\n}\n\n/**\n * Read the current {@link ProjectSnapshot}. Throws if called outside a\n * {@link SwatchbookProvider}; blocks that need to fall back to the\n * virtual module go through the internal `useProject()` hook instead.\n */\nexport function useSwatchbookData(): ProjectSnapshot {\n const value = useOptionalSwatchbookData();\n if (!value) {\n throw new Error(\n '[swatchbook-blocks] useSwatchbookData() called outside <SwatchbookProvider>. ' +\n 'Wrap your tree in <SwatchbookProvider value={snapshot}> or render inside a Storybook story.',\n );\n }\n return value;\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { BORDER_FAINT, SURFACE_RAISED } from '#/internal/styles.tsx';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\n\nexport interface ShadowSampleProps {\n /** Full dot-path of the shadow token to preview. */\n path: string;\n}\n\nconst sampleStyle: CSSProperties = {\n width: 120,\n height: 56,\n background: SURFACE_RAISED,\n border: BORDER_FAINT,\n borderRadius: 6,\n};\n\nexport function ShadowSample({ path }: ShadowSampleProps): ReactElement {\n const project = useProject();\n const cssVar = resolveCssVar(path, project);\n return <div style={{ ...sampleStyle, boxShadow: cssVar }} aria-hidden />;\n}\n","import cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './ShadowPreview.css';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat } from '#/format-color.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\nimport { ShadowSample } from '#/shadow-preview/ShadowSample.tsx';\n\nexport interface ShadowPreviewProps {\n /**\n * Token-path filter. Defaults to every `shadow` token. Use e.g.\n * `\"shadow.*\"` to scope to the semantic layer.\n */\n filter?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` falls through to path (shadows don't have a\n * single-axis ordering); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface ShadowLayer {\n color?: unknown;\n offsetX?: unknown;\n offsetY?: unknown;\n blur?: unknown;\n spread?: unknown;\n inset?: unknown;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n layers: ShadowLayer[];\n}\n\nfunction formatDimension(raw: unknown): string {\n if (raw == null) return '—';\n if (typeof raw === 'number') return String(raw);\n if (typeof raw === 'string') return raw;\n if (typeof raw === 'object') {\n const v = raw as { value?: unknown; unit?: unknown };\n if (typeof v.value === 'number' && typeof v.unit === 'string') {\n return `${v.value}${v.unit}`;\n }\n }\n return JSON.stringify(raw);\n}\n\nfunction formatSubColor(raw: unknown, format: ColorFormat): string {\n if (raw == null) return '—';\n return formatColor(raw, format).value;\n}\n\nfunction asLayers(raw: unknown): ShadowLayer[] {\n if (Array.isArray(raw)) return raw as ShadowLayer[];\n if (raw && typeof raw === 'object') return [raw as ShadowLayer];\n return [];\n}\n\nfunction layerKey(path: string, layer: ShadowLayer, fallback: number): string {\n const off = `${formatDimension(layer.offsetX)},${formatDimension(layer.offsetY)}`;\n const blur = formatDimension(layer.blur);\n const spread = formatDimension(layer.spread);\n return `${path}|${off}|${blur}|${spread}|${fallback}`;\n}\n\nexport function ShadowPreview({\n filter,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: ShadowPreviewProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'shadow') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n layers: asLayers(token.$value),\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} shadow${rows.length === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No shadow tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-shadow-preview__row\">\n <div className=\"sb-shadow-preview__meta\">\n <span className=\"sb-shadow-preview__path\">{row.path}</span>\n <span className=\"sb-shadow-preview__css-var\">{row.cssVar}</span>\n </div>\n <div className=\"sb-shadow-preview__sample-cell\">\n <ShadowSample path={row.path} />\n </div>\n <div className=\"sb-shadow-preview__breakdown\">\n {row.layers.length === 1\n ? renderLayer(row.layers[0], colorFormat)\n : row.layers.map((layer, i) => (\n <Layer\n key={layerKey(row.path, layer, i)}\n layer={layer}\n index={i}\n total={row.layers.length}\n colorFormat={colorFormat}\n />\n ))}\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction renderLayer(layer: ShadowLayer | undefined, format: ColorFormat): ReactElement[] {\n if (!layer) return [];\n const entries: [string, string][] = [\n ['offset', `${formatDimension(layer.offsetX)} ${formatDimension(layer.offsetY)}`],\n ['blur', formatDimension(layer.blur)],\n ['spread', formatDimension(layer.spread)],\n ['color', formatSubColor(layer.color, format)],\n ];\n if (layer.inset) entries.push(['inset', String(layer.inset)]);\n return entries.flatMap(([k, v]) => [\n <span key={`k-${k}`} className=\"sb-shadow-preview__breakdown-key\">\n {k}\n </span>,\n <span key={`v-${k}`}>{v}</span>,\n ]);\n}\n\nfunction Layer({\n layer,\n index,\n total,\n colorFormat,\n}: {\n layer: ShadowLayer;\n index: number;\n total: number;\n colorFormat: ColorFormat;\n}): ReactElement {\n return (\n <div className=\"sb-shadow-preview__layer\">\n <div className=\"sb-shadow-preview__layer-header\">\n layer {index + 1} of {total}\n </div>\n <div className={cx('sb-shadow-preview__breakdown', 'sb-shadow-preview__layer-breakdown')}>\n {renderLayer(layer, colorFormat)}\n </div>\n </div>\n );\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './StrokeStyleSample.css';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\n\nexport interface StrokeStyleSampleProps {\n /**\n * Token-path filter. Defaults to every `strokeStyle` token. Use e.g.\n * `\"stroke.style.*\"` to scope to the ref layer.\n */\n filter?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` ordering falls through to path for this block's\n * type (composite / non-numeric); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\nconst STRING_STYLES = new Set([\n 'solid',\n 'dashed',\n 'dotted',\n 'double',\n 'groove',\n 'ridge',\n 'outset',\n 'inset',\n]);\n\ninterface Row {\n path: string;\n cssVar: string;\n displayValue: string;\n cssStyle: string | null;\n}\n\nfunction extractCssStyle(value: unknown): string | null {\n if (typeof value === 'string' && STRING_STYLES.has(value)) return value;\n return null;\n}\n\nexport function StrokeStyleSample({\n filter,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: StrokeStyleSampleProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'strokeStyle') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n displayValue: formatTokenValue(token.$value, token.$type, 'raw', project.listing[path]),\n cssStyle: extractCssStyle(token.$value),\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} strokeStyle token${rows.length === 1 ? '' : 's'}${filter && filter !== 'strokeStyle' ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No strokeStyle tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-stroke-style-sample__row\">\n <div className=\"sb-stroke-style-sample__meta\">\n <span className=\"sb-stroke-style-sample__path\">{row.path}</span>\n <span className=\"sb-stroke-style-sample__value\">{row.displayValue}</span>\n </div>\n {row.cssStyle ? (\n <div\n className=\"sb-stroke-style-sample__line\"\n style={{\n borderTopStyle: row.cssStyle as CSSProperties['borderTopStyle'],\n }}\n aria-hidden\n />\n ) : (\n <span className=\"sb-stroke-style-sample__object-fallback\">\n Object-form (dashArray + lineCap) — no pure CSS `border-style` equivalent.\n </span>\n )}\n <span className=\"sb-stroke-style-sample__css-var\">{row.cssVar}</span>\n </div>\n ))}\n </div>\n );\n}\n","import type { Axis } from '@unpunnyfuns/swatchbook-core';\nimport type { VirtualVarianceByPathShape } from '#/contexts.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\n\nexport interface DetailToken {\n $type?: string;\n $value?: unknown;\n $description?: string;\n aliasOf?: string;\n aliasChain?: readonly string[];\n aliasedBy?: readonly string[];\n /**\n * Terrazzo-populated sub-value alias map for composite tokens. Shape\n * varies by $type: object-valued composites (`border`, `typography`,\n * `transition`) use `Record<string, string | undefined>` keyed by\n * sub-key; array-valued composites (`shadow`, `gradient`) use an array\n * of such records indexed per layer / stop. Carried through `unknown`\n * here so each consumer narrows at use-site.\n */\n partialAliasOf?: unknown;\n}\n\nexport interface TokenDetailData {\n token: DetailToken | undefined;\n cssVar: string;\n activeTheme: string;\n activeAxes: Record<string, string>;\n axes: readonly Axis[];\n resolved: Record<string, DetailToken>;\n cssVarPrefix: string;\n varianceByPath: VirtualVarianceByPathShape;\n /**\n * Pure-function accessor that composes the resolved tokens for any\n * tuple of axis selections — used by the `AxisVariance` grid to\n * read per-cell values without indexing `permutationsResolved` by\n * a derived tuple name.\n */\n resolveAt: (tuple: Record<string, string>) => Record<string, DetailToken>;\n /**\n * O(1) tuple → permutation-name lookup, backed by a `Map` built\n * once per snapshot. The `AxisVariance` grid uses this to derive\n * the `data-<prefix>-theme` attribute for each cell without an\n * `Array.find` scan per render cell.\n */\n themeNameForTuple: (tuple: Record<string, string>) => string | undefined;\n}\n\nexport function useTokenDetailData(path: string): TokenDetailData {\n const project = useProject();\n const {\n activeTheme,\n activeAxes,\n axes,\n resolved,\n cssVarPrefix,\n varianceByPath,\n resolveAt,\n themeNameForTuple,\n } = project;\n const typedResolved = resolved as Record<string, DetailToken>;\n return {\n token: typedResolved[path],\n cssVar: resolveCssVar(path, project),\n activeTheme,\n activeAxes,\n axes,\n resolved: typedResolved,\n cssVarPrefix,\n varianceByPath,\n resolveAt: resolveAt as (tuple: Record<string, string>) => Record<string, DetailToken>,\n themeNameForTuple,\n };\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\n\nexport interface AliasChainProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\nexport function AliasChain({ path }: AliasChainProps): ReactElement | null {\n const { token } = useTokenDetailData(path);\n\n const chain = useMemo<string[]>(() => {\n if (!token) return [];\n if (Array.isArray(token.aliasChain) && token.aliasChain.length > 0) {\n return [path, ...token.aliasChain];\n }\n if (typeof token.aliasOf === 'string') return [path, token.aliasOf];\n return [path];\n }, [token, path]);\n\n if (chain.length <= 1) return null;\n\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Alias chain</div>\n <div className=\"sb-token-detail__chain\">\n {chain.map((step, i) => (\n <span key={step} className=\"sb-token-detail__chain\">\n <span className=\"sb-token-detail__chain-node\">{step}</span>\n {i < chain.length - 1 && <span className=\"sb-token-detail__arrow\">→</span>}\n </span>\n ))}\n </div>\n </>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\nimport type { DetailToken } from '#/token-detail/internal.ts';\n\nexport interface AliasedByProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\nconst ALIASED_BY_DEPTH_CAP = 6;\n\ninterface AliasedByNode {\n path: string;\n children: AliasedByNode[];\n truncated?: boolean;\n}\n\nconst GROUP_RANK: Record<string, number> = { ref: 0, sys: 1 };\n\nexport function AliasedBy({ path }: AliasedByProps): ReactElement | null {\n const { resolved } = useTokenDetailData(path);\n const tree = useMemo<AliasedByNode[]>(() => buildAliasedByTree(path, resolved), [path, resolved]);\n const truncated = useMemo(() => treeHasTruncation(tree), [tree]);\n\n if (tree.length === 0) return null;\n\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Aliased by</div>\n <ul className=\"sb-token-detail__aliased-by-list\">\n {tree.map((node) => (\n <AliasedByRow key={node.path} node={node} depth={0} />\n ))}\n </ul>\n {truncated && (\n <div className=\"sb-token-detail__aliased-by-truncated\">\n Further descendants truncated at depth {ALIASED_BY_DEPTH_CAP}.\n </div>\n )}\n </>\n );\n}\n\nfunction AliasedByRow({ node, depth }: { node: AliasedByNode; depth: number }): ReactElement {\n return (\n <li>\n <div className=\"sb-token-detail__aliased-by-row\" style={{ paddingLeft: depth * 16 }}>\n <span className=\"sb-token-detail__chain-node\">{node.path}</span>\n </div>\n {node.children.length > 0 && (\n <ul className=\"sb-token-detail__aliased-by-list\">\n {node.children.map((child) => (\n <AliasedByRow key={child.path} node={child} depth={depth + 1} />\n ))}\n </ul>\n )}\n </li>\n );\n}\n\nfunction buildAliasedByTree(\n rootPath: string,\n resolved: Record<string, DetailToken>,\n): AliasedByNode[] {\n const root = resolved[rootPath];\n const direct = root?.aliasedBy;\n if (!direct || direct.length === 0) return [];\n const visited = new Set<string>([rootPath]);\n return sortPaths(direct).map((p) => walk(p, resolved, visited, 1));\n}\n\nfunction walk(\n path: string,\n resolved: Record<string, DetailToken>,\n visited: Set<string>,\n depth: number,\n): AliasedByNode {\n if (visited.has(path)) return { path, children: [] };\n visited.add(path);\n const token = resolved[path];\n const parents = token?.aliasedBy;\n if (!parents || parents.length === 0) return { path, children: [] };\n if (depth >= ALIASED_BY_DEPTH_CAP) {\n return { path, children: [], truncated: true };\n }\n const children = sortPaths(parents).map((p) => walk(p, resolved, visited, depth + 1));\n return { path, children };\n}\n\nfunction sortPaths(paths: readonly string[]): string[] {\n return paths.toSorted((a, b) => {\n const ra = GROUP_RANK[a.split('.')[0] ?? ''] ?? 2;\n const rb = GROUP_RANK[b.split('.')[0] ?? ''] ?? 2;\n return ra !== rb ? ra - rb : a.localeCompare(b, undefined, { numeric: true });\n });\n}\n\nfunction treeHasTruncation(nodes: AliasedByNode[]): boolean {\n for (const n of nodes) {\n if (n.truncated) return true;\n if (treeHasTruncation(n.children)) return true;\n }\n return false;\n}\n","import type { Axis } from '@unpunnyfuns/swatchbook-core';\nimport type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport { useColorFormat } from '#/contexts.ts';\nimport type { ColorFormat } from '#/format-color.ts';\nimport { dataAttr } from '@unpunnyfuns/swatchbook-core/data-attr';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\nimport type { DetailToken } from '#/token-detail/internal.ts';\n\nexport interface AxisVarianceProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\ntype Variance =\n | { kind: 'constant' }\n | { kind: 'one-axis'; axis: string; varyingAxes: readonly [string] }\n | { kind: 'multi-axis'; varyingAxes: readonly [string, string, ...string[]] };\n\nexport function AxisVariance({ path }: AxisVarianceProps): ReactElement {\n const {\n token,\n cssVar,\n axes,\n activeAxes,\n cssVarPrefix,\n varianceByPath,\n resolveAt,\n themeNameForTuple,\n } = useTokenDetailData(path);\n const colorFormat = useColorFormat();\n const tokenType = token?.$type;\n const isColor = tokenType === 'color';\n const formatFn = (t: DetailToken | undefined): string => valueFor(t, tokenType, colorFormat);\n\n const variance = useMemo<Variance>(() => {\n // Read the pre-computed per-path variance from the snapshot. The\n // server side runs the bucket analysis once at load and ships the\n // map over the wire — O(1) lookup per render instead of an O(paths\n // × permutations) re-derivation here.\n const result = varianceByPath[path];\n if (!result) return { kind: 'constant' };\n switch (result.kind) {\n case 'constant':\n return { kind: 'constant' };\n case 'single':\n return { kind: 'one-axis', axis: result.axis, varyingAxes: result.varyingAxes };\n case 'multi':\n return { kind: 'multi-axis', varyingAxes: result.varyingAxes };\n }\n }, [path, varianceByPath]);\n\n if (axes.length === 0) {\n return <></>;\n }\n\n if (variance.kind === 'constant') {\n const value = formatFn(resolveAt(activeAxes)[path] as DetailToken | undefined);\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Values across axes</div>\n <table className=\"sb-token-detail__theme-table\" data-testid=\"token-detail-values\">\n <tbody>\n <tr className=\"sb-token-detail__theme-row\">\n <td className=\"sb-token-detail__theme-cell\" data-testid=\"token-detail-constant\">\n {isColor && (\n <span\n className=\"sb-token-detail__swatch\"\n style={{ background: cssVar }}\n aria-hidden\n />\n )}\n {value}\n <span style={{ opacity: 0.6, marginLeft: 8 }}>same across every axis</span>\n </td>\n </tr>\n </tbody>\n </table>\n </>\n );\n }\n\n if (variance.kind === 'one-axis') {\n const axisName = variance.axis;\n const axis = axes.find((a) => a.name === axisName);\n if (!axis) return <></>;\n const contextValues = axis.contexts.map((ctx) => {\n const target = { ...activeAxes, [axisName]: ctx };\n const themeName = themeNameForTuple(target) ?? '';\n return {\n ctx,\n themeName,\n value: formatFn(resolveAt(target)[path] as DetailToken | undefined),\n };\n });\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Varies with {axisName}</div>\n <table className=\"sb-token-detail__theme-table\" data-testid=\"token-detail-values\">\n <tbody>\n {contextValues.map((row) => (\n <tr\n key={row.ctx}\n className=\"sb-token-detail__theme-row\"\n data-axis={axisName}\n data-context={row.ctx}\n >\n <td className=\"sb-token-detail__theme-cell\" style={{ width: '30%' }}>\n {row.ctx}\n </td>\n <td className=\"sb-token-detail__theme-cell\">\n {isColor && row.themeName && (\n <span\n className=\"sb-token-detail__swatch\"\n style={{ background: cssVar }}\n {...{ [dataAttr(cssVarPrefix, 'theme')]: row.themeName }}\n aria-hidden\n />\n )}\n {row.value}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </>\n );\n }\n\n const varying = variance.varyingAxes\n .map((name) => axes.find((a) => a.name === name))\n .filter((a): a is Axis => Boolean(a))\n .toSorted((a, b) => b.contexts.length - a.contexts.length);\n const [rowAxis, colAxis, ...extra] = varying;\n if (!rowAxis || !colAxis) return <></>;\n\n return (\n <>\n <div className=\"sb-token-detail__section-header\">\n Varies with {variance.varyingAxes.join(' × ')}\n </div>\n <table className=\"sb-token-detail__theme-table\" data-testid=\"token-detail-values\">\n <thead>\n <tr className=\"sb-token-detail__theme-row\">\n <th className=\"sb-token-detail__theme-cell\" style={{ textAlign: 'left', opacity: 0.7 }}>\n {rowAxis.name} \\ {colAxis.name}\n </th>\n {colAxis.contexts.map((col) => (\n <th\n key={col}\n className=\"sb-token-detail__theme-cell\"\n style={{ textAlign: 'left', opacity: 0.7 }}\n >\n {col}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rowAxis.contexts.map((row) => (\n <tr key={row} className=\"sb-token-detail__theme-row\">\n <td className=\"sb-token-detail__theme-cell\">{row}</td>\n {colAxis.contexts.map((col) => {\n const target: Record<string, string> = {\n ...activeAxes,\n [rowAxis.name]: row,\n [colAxis.name]: col,\n };\n const name = themeNameForTuple(target);\n const value = formatFn(resolveAt(target)[path] as DetailToken | undefined);\n return (\n <td\n key={col}\n className=\"sb-token-detail__theme-cell\"\n data-row={row}\n data-col={col}\n >\n {isColor && name && (\n <span\n className=\"sb-token-detail__swatch\"\n style={{ background: cssVar }}\n {...{ [dataAttr(cssVarPrefix, 'theme')]: name }}\n aria-hidden\n />\n )}\n {value}\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n {extra.length > 0 && (\n <div className=\"sb-token-detail__aliased-by-truncated\" style={{ marginTop: 6 }}>\n Values also vary with {extra.map((a) => a.name).join(', ')}; matrix shows the slice for\n the active selection.\n </div>\n )}\n </>\n );\n}\n\nfunction valueFor(\n token: DetailToken | undefined,\n $type: string | undefined,\n format: ColorFormat,\n): string {\n if (!token) return '—';\n return formatTokenValue(token.$value, $type, format);\n}\n","import type { ReactElement } from 'react';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat } from '#/format-color.ts';\nimport type {\n BorderValue,\n GradientStop,\n ShadowLayer,\n TransitionValue,\n TypographyValue,\n} from '#/internal/composite-types.ts';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\nimport type { DetailToken } from '#/token-detail/internal.ts';\n\nexport interface CompositeBreakdownProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\nexport function CompositeBreakdown({ path }: CompositeBreakdownProps): ReactElement | null {\n const { token, resolved } = useTokenDetailData(path);\n const colorFormat = useColorFormat();\n if (!token) return null;\n return (\n <CompositeBreakdownContent\n type={token.$type}\n rawValue={token.$value}\n partialAliasOf={token.partialAliasOf}\n resolved={resolved}\n colorFormat={colorFormat}\n />\n );\n}\n\nexport function CompositeBreakdownContent({\n type,\n rawValue,\n partialAliasOf,\n resolved,\n colorFormat,\n}: {\n type: string | undefined;\n rawValue: unknown;\n partialAliasOf?: unknown;\n resolved?: Record<string, DetailToken>;\n colorFormat: ColorFormat;\n}): ReactElement | null {\n if (!rawValue || typeof rawValue !== 'object') return null;\n\n const objectAliases = pickObjectAliases(partialAliasOf);\n const arrayAliases = pickArrayAliases(partialAliasOf);\n const aliasFor = (key: string): readonly string[] | undefined =>\n subValueChain(objectAliases?.[key], resolved);\n\n if (type === 'typography') {\n const v = rawValue as TypographyValue;\n return renderKeyValueList([\n ['fontFamily', formatFontFamily(v.fontFamily), aliasFor('fontFamily')],\n ['fontSize', formatDimensionValue(v.fontSize), aliasFor('fontSize')],\n ['fontWeight', formatPrimitive(v.fontWeight), aliasFor('fontWeight')],\n ['lineHeight', formatPrimitive(v.lineHeight), aliasFor('lineHeight')],\n ['letterSpacing', formatDimensionValue(v.letterSpacing), aliasFor('letterSpacing')],\n ]);\n }\n\n if (type === 'border') {\n const v = rawValue as BorderValue;\n return renderKeyValueList([\n ['color', formatColorSubValue(v.color, colorFormat), aliasFor('color')],\n ['width', formatDimensionValue(v.width), aliasFor('width')],\n ['style', formatPrimitive(v.style), aliasFor('style')],\n ]);\n }\n\n if (type === 'transition') {\n const v = rawValue as TransitionValue;\n return renderKeyValueList([\n ['duration', formatDimensionValue(v.duration), aliasFor('duration')],\n ['timingFunction', formatPrimitive(v.timingFunction), aliasFor('timingFunction')],\n ['delay', formatDimensionValue(v.delay), aliasFor('delay')],\n ]);\n }\n\n if (type === 'shadow') {\n const layers = Array.isArray(rawValue) ? rawValue : [rawValue];\n const multi = layers.length > 1;\n const layerAliasFor = (i: number, key: string): readonly string[] | undefined =>\n subValueChain(arrayAliases?.[i]?.[key], resolved);\n return (\n <div className=\"sb-token-detail__breakdown-section\">\n {layers.map((layer, i) => {\n const v = layer as ShadowLayer;\n return (\n <div key={shadowLayerKey(v, i)} style={{ display: 'contents' }}>\n {multi && (\n <div className=\"sb-token-detail__breakdown-layer-header\">Layer {i + 1}</div>\n )}\n <KeyValueRow\n label=\"color\"\n value={formatColorSubValue(v.color, colorFormat)}\n alias={layerAliasFor(i, 'color')}\n />\n <KeyValueRow\n label=\"offsetX\"\n value={formatDimensionValue(v.offsetX)}\n alias={layerAliasFor(i, 'offsetX')}\n />\n <KeyValueRow\n label=\"offsetY\"\n value={formatDimensionValue(v.offsetY)}\n alias={layerAliasFor(i, 'offsetY')}\n />\n <KeyValueRow\n label=\"blur\"\n value={formatDimensionValue(v.blur)}\n alias={layerAliasFor(i, 'blur')}\n />\n <KeyValueRow\n label=\"spread\"\n value={formatDimensionValue(v.spread)}\n alias={layerAliasFor(i, 'spread')}\n />\n {v.inset !== undefined && (\n <KeyValueRow label=\"inset\" value={formatPrimitive(v.inset)} alias={undefined} />\n )}\n </div>\n );\n })}\n </div>\n );\n }\n\n if (type === 'gradient') {\n const stops = Array.isArray(rawValue) ? rawValue : [];\n if (stops.length === 0) return null;\n const stopAliasFor = (i: number): readonly string[] | undefined =>\n subValueChain(arrayAliases?.[i]?.['color'], resolved);\n return (\n <div className=\"sb-token-detail__breakdown-section\">\n {stops.map((stop, i) => {\n const v = stop as GradientStop;\n const position = typeof v.position === 'number' ? v.position : 0;\n return (\n <KeyValueRow\n key={gradientStopKey(v, i)}\n label={`${(position * 100).toFixed(0)}%`}\n value={formatColorSubValue(v.color, colorFormat)}\n alias={stopAliasFor(i)}\n />\n );\n })}\n </div>\n );\n }\n\n return null;\n}\n\nfunction renderKeyValueList(\n rows: [string, string | null, readonly string[] | undefined][],\n): ReactElement {\n return (\n <div className=\"sb-token-detail__breakdown-section\">\n {rows\n .filter(([, v, alias]) => v !== null || (alias && alias.length > 0))\n .map(([k, v, alias]) => (\n <KeyValueRow key={k} label={k} value={v ?? ''} alias={alias} />\n ))}\n </div>\n );\n}\n\nfunction KeyValueRow({\n label,\n value,\n alias,\n}: {\n label: string;\n value: string | null;\n alias: readonly string[] | undefined;\n}): ReactElement {\n const hasAlias = alias && alias.length > 0;\n return (\n <>\n <span className=\"sb-token-detail__breakdown-key\">{label}</span>\n <span className=\"sb-token-detail__breakdown-value\">\n <span>{value ?? '—'}</span>\n {hasAlias && (\n <span className=\"sb-token-detail__breakdown-alias\" data-testid=\"breakdown-alias\">\n {alias.map((p, i) => (\n <span key={p} className=\"sb-token-detail__breakdown-alias-step\">\n {i > 0 && <span className=\"sb-token-detail__arrow\">→</span>}\n <span className=\"sb-token-detail__chain-node\">{p}</span>\n </span>\n ))}\n </span>\n )}\n </span>\n </>\n );\n}\n\nfunction formatPrimitive(v: unknown): string | null {\n if (v == null) return null;\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return String(v);\n return JSON.stringify(v);\n}\n\nfunction formatFontFamily(v: unknown): string | null {\n if (v == null) return null;\n if (typeof v === 'string') return v;\n if (Array.isArray(v)) return v.map(String).join(', ');\n return JSON.stringify(v);\n}\n\nfunction formatDimensionValue(v: unknown): string | null {\n if (v == null) return null;\n if (typeof v === 'string' || typeof v === 'number') return String(v);\n if (typeof v === 'object') {\n const d = v as { value?: unknown; unit?: unknown };\n if (typeof d.value === 'number' && typeof d.unit === 'string') return `${d.value}${d.unit}`;\n }\n return JSON.stringify(v);\n}\n\n/**\n * Route sub-value colors through `formatColor` so they honor the active\n * color-format dropdown, just like the standalone `<ColorPalette />` and\n * `<TokenDetail />` top-line do. Returns `null` for a missing field so\n * the key/value row drops out entirely.\n */\nfunction formatColorSubValue(v: unknown, format: ColorFormat): string | null {\n if (v == null) return null;\n return formatColor(v, format).value;\n}\n\nfunction pickObjectAliases(v: unknown): Record<string, string | undefined> | undefined {\n if (!v || typeof v !== 'object' || Array.isArray(v)) return undefined;\n return v as Record<string, string | undefined>;\n}\n\nfunction pickArrayAliases(v: unknown): Record<string, string | undefined>[] | undefined {\n if (!Array.isArray(v)) return undefined;\n return v as Record<string, string | undefined>[];\n}\n\n/**\n * Walk the alias chain starting from an immediate sub-value alias target.\n * `aliasTarget` is the path the sub-value directly references; the target\n * token's own `aliasChain` continues the walk to the primitive.\n */\nfunction subValueChain(\n aliasTarget: string | undefined,\n resolved: Record<string, DetailToken> | undefined,\n): readonly string[] | undefined {\n if (!aliasTarget) return undefined;\n const tok = resolved?.[aliasTarget];\n const tail = tok?.aliasChain;\n return tail && tail.length > 0 ? [aliasTarget, ...tail] : [aliasTarget];\n}\n\nfunction shadowLayerKey(layer: ShadowLayer, fallback: number): string {\n const parts = [\n layer.color,\n layer.offsetX,\n layer.offsetY,\n layer.blur,\n layer.spread,\n layer.inset,\n ].map((p) => (p === undefined ? '' : JSON.stringify(p)));\n return `shadow|${parts.join('|')}|${fallback}`;\n}\n\nfunction gradientStopKey(stop: GradientStop, fallback: number): string {\n return `stop|${stop.position ?? fallback}|${JSON.stringify(stop.color)}`;\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { useEffect, useState } from 'react';\nimport { cssVarAsNumber } from '#/internal/css-var-style.ts';\nimport { usePrefersReducedMotion } from '#/internal/prefers-reduced-motion.ts';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\n\nexport interface CompositePreviewProps {\n /** Full dot-path of the token to preview. */\n path: string;\n}\n\nconst PANGRAM = 'Sphinx of black quartz, judge my vow.';\n\nconst STROKE_STYLE_STRINGS = new Set([\n 'solid',\n 'dashed',\n 'dotted',\n 'double',\n 'groove',\n 'ridge',\n 'outset',\n 'inset',\n]);\n\nexport function CompositePreview({ path }: CompositePreviewProps): ReactElement | null {\n const { token, cssVar } = useTokenDetailData(path);\n if (!token) return null;\n return <CompositePreviewContent type={token.$type} cssVar={cssVar} rawValue={token.$value} />;\n}\n\nexport function CompositePreviewContent({\n type,\n cssVar,\n rawValue,\n}: {\n type: string | undefined;\n cssVar: string;\n rawValue: unknown;\n}): ReactElement | null {\n if (type === 'typography') {\n const base = cssVar.replace(/^var\\(/, '').replace(/\\)$/, '');\n return (\n <div\n className=\"sb-token-detail__typography-sample\"\n style={{\n fontFamily: `var(${base}-font-family)`,\n fontSize: `var(${base}-font-size)`,\n fontWeight: cssVarAsNumber(`var(${base}-font-weight)`),\n lineHeight: cssVarAsNumber(`var(${base}-line-height)`),\n letterSpacing: `var(${base}-letter-spacing)`,\n }}\n >\n {PANGRAM}\n </div>\n );\n }\n if (type === 'shadow') {\n return (\n <div className=\"sb-token-detail__shadow-sample\" style={{ boxShadow: cssVar }} aria-hidden />\n );\n }\n if (type === 'border') {\n return (\n <div className=\"sb-token-detail__border-sample\" style={{ border: cssVar }} aria-hidden />\n );\n }\n if (type === 'transition') {\n return <TransitionSample transition={cssVar} />;\n }\n if (type === 'dimension') {\n return (\n <div className=\"sb-token-detail__dimension-track\">\n <div className=\"sb-token-detail__dimension-bar\" style={{ width: cssVar }} aria-hidden />\n </div>\n );\n }\n if (type === 'duration') {\n return <TransitionSample transition={`left ${cssVar} ease`} />;\n }\n if (type === 'fontFamily') {\n return (\n <div className=\"sb-token-detail__font-family-sample\" style={{ fontFamily: cssVar }}>\n {PANGRAM}\n </div>\n );\n }\n if (type === 'fontWeight') {\n return (\n <div\n className=\"sb-token-detail__font-weight-sample\"\n style={{ fontWeight: cssVarAsNumber(cssVar) }}\n >\n Aa\n </div>\n );\n }\n if (type === 'cubicBezier') {\n return <TransitionSample transition={`left 800ms ${cssVar}`} />;\n }\n if (type === 'gradient') {\n return (\n <div\n className=\"sb-token-detail__gradient-sample\"\n style={{ background: `linear-gradient(to right, ${cssVar})` }}\n aria-hidden\n />\n );\n }\n if (type === 'strokeStyle') {\n return <StrokeStylePreview value={rawValue} />;\n }\n if (type === 'color') {\n return (\n <div className=\"sb-token-detail__color-swatch-row\" aria-hidden>\n <div className=\"sb-token-detail__color-swatch-light\" style={{ background: cssVar }} />\n <div className=\"sb-token-detail__color-swatch-dark\" style={{ background: cssVar }} />\n </div>\n );\n }\n return null;\n}\n\nfunction StrokeStylePreview({ value }: { value: unknown }): ReactElement {\n if (typeof value === 'string' && STROKE_STYLE_STRINGS.has(value)) {\n return (\n <div\n className=\"sb-token-detail__stroke-style-line\"\n style={{ borderTopStyle: value as CSSProperties['borderTopStyle'] }}\n aria-hidden\n />\n );\n }\n if (value && typeof value === 'object' && 'dashArray' in value) {\n const v = value as {\n dashArray?: unknown;\n lineCap?: unknown;\n };\n const lengths = asDashLengths(v.dashArray);\n if (lengths.length === 0) {\n return (\n <div className=\"sb-token-detail__stroke-style-fallback\">\n Object-form strokeStyle with no resolvable dashArray.\n </div>\n );\n }\n const cap = typeof v.lineCap === 'string' ? v.lineCap : 'butt';\n return (\n <svg\n className=\"sb-token-detail__stroke-style-svg\"\n viewBox=\"0 0 220 24\"\n preserveAspectRatio=\"none\"\n aria-hidden\n >\n <line\n x1=\"4\"\n y1=\"12\"\n x2=\"216\"\n y2=\"12\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n strokeDasharray={lengths.join(' ')}\n strokeLinecap={cap as 'butt' | 'round' | 'square'}\n />\n </svg>\n );\n }\n return (\n <div className=\"sb-token-detail__stroke-style-fallback\">\n strokeStyle value could not be previewed.\n </div>\n );\n}\n\nfunction asDashLengths(raw: unknown): number[] {\n if (!Array.isArray(raw)) return [];\n const out: number[] = [];\n for (const entry of raw) {\n if (typeof entry === 'number') {\n out.push(entry);\n continue;\n }\n if (entry && typeof entry === 'object') {\n const e = entry as { value?: unknown };\n if (typeof e.value === 'number') out.push(e.value);\n }\n }\n return out;\n}\n\nfunction TransitionSample({ transition }: { transition: string }): ReactElement {\n const reduced = usePrefersReducedMotion();\n const [phase, setPhase] = useState<0 | 1>(0);\n\n useEffect(() => {\n if (reduced) return;\n const id = requestAnimationFrame(() => setPhase(1));\n const loop = window.setInterval(() => {\n setPhase((p) => (p === 0 ? 1 : 0));\n }, 1200);\n return () => {\n cancelAnimationFrame(id);\n window.clearInterval(loop);\n };\n }, [reduced]);\n\n if (reduced) {\n return (\n <div className=\"sb-token-detail__reduced-motion\">\n Animation suppressed by `prefers-reduced-motion: reduce`.\n </div>\n );\n }\n\n return (\n <div className=\"sb-token-detail__motion-track\">\n <div\n className=\"sb-token-detail__motion-ball\"\n style={{\n left: phase === 1 ? 'calc(100% - 28px)' : '4px',\n transition,\n }}\n aria-hidden\n />\n </div>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useState } from 'react';\nimport { useProject } from '#/internal/use-project.ts';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\n\nexport interface ConsumerOutputProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\nexport function ConsumerOutput({ path }: ConsumerOutputProps): ReactElement | null {\n const { token, cssVar, activeAxes } = useTokenDetailData(path);\n const { listing } = useProject();\n\n if (!token) return null;\n\n const tupleLabel = Object.entries(activeAxes)\n .map(([k, v]) => `${k}=${v}`)\n .join(', ');\n\n // Platforms beyond `css`. Populated only when the consumer has loaded\n // extra plugins (`@terrazzo/plugin-swift`, `-android`, `-sass`, …) via\n // `config.terrazzoPlugins` + `config.listingOptions.platforms`. Always\n // empty otherwise — the row set falls back to Path + CSS exactly like\n // before listing adoption.\n const names = listing[path]?.names ?? {};\n const extraPlatforms = Object.keys(names)\n .filter((platform) => platform !== 'css' && names[platform])\n .toSorted();\n\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Consumer output</div>\n {tupleLabel && (\n <div className=\"sb-token-detail__tuple-indicator\">\n Active tuple: <strong>{tupleLabel}</strong>\n </div>\n )}\n <OutputRow label=\"Path\" value={path} testId=\"consumer-output-path\" />\n <OutputRow label=\"CSS\" value={cssVar} testId=\"consumer-output-css\" />\n {extraPlatforms.map((platform) => (\n <OutputRow\n key={platform}\n label={formatPlatformLabel(platform)}\n value={names[platform]!}\n testId={`consumer-output-${platform}`}\n />\n ))}\n </>\n );\n}\n\nfunction formatPlatformLabel(platform: string): string {\n if (platform.length === 0) return platform;\n return platform[0]!.toUpperCase() + platform.slice(1);\n}\n\ninterface OutputRowProps {\n label: string;\n value: string;\n testId: string;\n}\n\nfunction OutputRow({ label, value, testId }: OutputRowProps): ReactElement {\n return (\n <div className=\"sb-token-detail__consumer-row\">\n <span className=\"sb-token-detail__consumer-row-label\">{label}</span>\n <code className=\"sb-token-detail__consumer-row-value\" data-testid={testId}>\n {value}\n </code>\n <CopyButton text={value} testId={`${testId}-copy`} />\n </div>\n );\n}\n\nfunction CopyButton({ text, testId }: { text: string; testId: string }): ReactElement {\n const [copied, setCopied] = useState(false);\n return (\n <button\n type=\"button\"\n className=\"sb-token-detail__consumer-row-copy\"\n data-testid={testId}\n onClick={() => {\n void copyToClipboard(text).then((ok) => {\n if (!ok) return;\n setCopied(true);\n window.setTimeout(() => setCopied(false), 1200);\n });\n }}\n >\n {copied ? 'Copied' : 'Copy'}\n </button>\n );\n}\n\nasync function copyToClipboard(text: string): Promise<boolean> {\n if (typeof navigator === 'undefined' || !navigator.clipboard) return false;\n try {\n await navigator.clipboard.writeText(text);\n return true;\n } catch {\n return false;\n }\n}\n","import type { ReactElement } from 'react';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\n\nexport interface TokenHeaderProps {\n /** Full dot-path of the token. */\n path: string;\n /** Override the heading. Defaults to the path. */\n heading?: string;\n}\n\nexport function TokenHeader({ path, heading }: TokenHeaderProps): ReactElement {\n const { token, cssVar, activeTheme } = useTokenDetailData(path);\n\n if (!token) {\n return (\n <div className=\"sb-token-detail__missing\">\n Token <code>{path}</code> not found in theme <strong>{activeTheme}</strong>.\n </div>\n );\n }\n\n return (\n <>\n <h3 className=\"sb-token-detail__heading\">{heading ?? path}</h3>\n <div className=\"sb-token-detail__subline\">\n {token.$type && <span className=\"sb-token-detail__type-pill\">{token.$type}</span>}\n <span>{cssVar}</span>\n </div>\n {token.$description && <p className=\"sb-token-detail__description\">{token.$description}</p>}\n </>\n );\n}\n","import type { ReactElement } from 'react';\nimport { CopyButton } from '#/internal/CopyButton.tsx';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\n\nexport interface TokenUsageSnippetProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\nexport function TokenUsageSnippet({ path }: TokenUsageSnippetProps): ReactElement | null {\n const { token, cssVar } = useTokenDetailData(path);\n if (!token) return null;\n const snippet = `color: ${cssVar};`;\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Usage</div>\n <div className=\"sb-token-detail__snippet-row\">\n <code className=\"sb-token-detail__snippet\">{snippet}</code>\n <CopyButton value={snippet} label={`Copy usage snippet ${snippet}`} />\n </div>\n </>\n );\n}\n","import cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport { CopyButton } from '#/internal/CopyButton.tsx';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { useProject } from '#/internal/use-project.ts';\nimport { AliasChain } from '#/token-detail/AliasChain.tsx';\nimport { AliasedBy } from '#/token-detail/AliasedBy.tsx';\nimport { AxisVariance } from '#/token-detail/AxisVariance.tsx';\nimport { CompositeBreakdown } from '#/token-detail/CompositeBreakdown.tsx';\nimport { CompositePreview } from '#/token-detail/CompositePreview.tsx';\nimport { ConsumerOutput } from '#/token-detail/ConsumerOutput.tsx';\nimport { TokenHeader } from '#/token-detail/TokenHeader.tsx';\nimport { TokenUsageSnippet } from '#/token-detail/TokenUsageSnippet.tsx';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\nimport '#/token-detail/styles.css';\n\nexport interface TokenDetailProps {\n /** Full dot-path of the token to inspect. */\n path: string;\n /** Override the heading. Defaults to the path. */\n heading?: string;\n}\n\nexport function TokenDetail({ path, heading }: TokenDetailProps): ReactElement {\n const { token, cssVar, activeTheme, cssVarPrefix } = useTokenDetailData(path);\n const colorFormat = useColorFormat();\n const theme = themeAttrs(cssVarPrefix, activeTheme);\n\n if (!token) {\n return (\n <div {...theme} className={cx(theme['className'], 'sb-token-detail')}>\n <div className=\"sb-token-detail__missing\">\n Token <code>{path}</code> not found in theme <strong>{activeTheme}</strong>.\n </div>\n </div>\n );\n }\n\n const { listing } = useProject();\n const isColor = token.$type === 'color';\n const gamut = isColor ? formatColor(token.$value, colorFormat) : null;\n const value = formatTokenValue(token.$value, token.$type, colorFormat, listing[path]);\n const outOfGamut = gamut?.outOfGamut ?? false;\n\n return (\n <div {...theme} className={cx(theme['className'], 'sb-token-detail')}>\n <TokenHeader path={path} {...(heading !== undefined && { heading })} />\n\n <div className=\"sb-token-detail__section-header\">Resolved value · {activeTheme}</div>\n <CompositePreview path={path} />\n <CompositeBreakdown path={path} />\n <div className=\"sb-token-detail__chain\">\n {isColor && (\n <span className=\"sb-token-detail__swatch\" style={{ background: cssVar }} aria-hidden />\n )}\n <span>{value}</span>\n {outOfGamut && (\n <span\n title=\"Out of sRGB gamut for this format\"\n aria-label=\"out of gamut\"\n style={{ marginLeft: 6 }}\n >\n ⚠\n </span>\n )}\n <CopyButton value={value} label={`Copy value ${value}`} />\n </div>\n\n <AliasChain path={path} />\n <AliasedBy path={path} />\n <TokenUsageSnippet path={path} />\n <ConsumerOutput path={path} />\n <AxisVariance path={path} />\n </div>\n );\n}\n","import type { KeyboardEvent as ReactKeyboardEvent, ReactElement } from 'react';\nimport { useEffect, useRef } from 'react';\nimport './DetailOverlay.css';\nimport { TokenDetail } from '#/TokenDetail.tsx';\n\n/**\n * Slide-over that wraps `<TokenDetail>`. Shared between `<TokenNavigator />`\n * and `<TokenTable />` so both land on the same opener and the same styling.\n *\n * Dismisses on backdrop click, Escape, and the close button. Implements the\n * WAI-ARIA dialog pattern's focus management: on mount, focus moves into the\n * panel; Tab is trapped so it cycles through the panel's interactive\n * descendants only; on unmount, focus restores to whatever opened the\n * overlay (typically the row / treeitem the user clicked).\n */\n\nexport interface DetailOverlayProps {\n path: string;\n onClose(): void;\n testId?: string;\n}\n\n/**\n * Selector for elements the trap considers focus stops. Mirrors the\n * \"tabbable\" set most focus-trap libraries use; the `:not(...)` clauses\n * skip the panel wrapper itself (we focus it manually on mount via its\n * own ref) and any explicitly-detabbed descendants.\n */\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(', ');\n\nexport function DetailOverlay({\n path,\n onClose,\n testId = 'swatchbook-overlay',\n}: DetailOverlayProps): ReactElement {\n const panelRef = useRef<HTMLDivElement | null>(null);\n const openerRef = useRef<HTMLElement | null>(null);\n\n // Save the opener + focus the panel on mount; restore the opener's\n // focus on unmount. Document-level activeElement is the only reliable\n // signal of what triggered the overlay since the click might have come\n // from a row, a tree item, a programmatic open, etc.\n useEffect(() => {\n openerRef.current =\n document.activeElement instanceof HTMLElement ? document.activeElement : null;\n panelRef.current?.focus();\n return () => {\n openerRef.current?.focus();\n };\n }, []);\n\n // Window-level Escape handler: works whether or not focus is currently\n // inside the panel (e.g. user clicked the backdrop, focus moved away).\n useEffect(() => {\n const onKey = (e: globalThis.KeyboardEvent): void => {\n if (e.key === 'Escape') onClose();\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [onClose]);\n\n /**\n * Wrap Tab inside the panel: from the last focusable, jump to the first;\n * from the first (or from the panel itself), Shift+Tab jumps to the last.\n * Defers to the browser otherwise.\n */\n const onPanelKeyDown = (e: ReactKeyboardEvent<HTMLDivElement>): void => {\n if (e.key !== 'Tab') return;\n const panel = panelRef.current;\n if (!panel) return;\n const focusables = panel.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR);\n if (focusables.length === 0) {\n e.preventDefault();\n return;\n }\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = document.activeElement;\n if (!first || !last) return;\n if (e.shiftKey) {\n if (active === first || active === panel) {\n e.preventDefault();\n last.focus();\n }\n } else if (active === last) {\n e.preventDefault();\n first.focus();\n }\n };\n\n return (\n <div\n className=\"sb-detail-overlay__backdrop\"\n onClick={onClose}\n role=\"presentation\"\n data-testid={testId}\n >\n <div\n ref={panelRef}\n className=\"sb-detail-overlay__panel\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={onPanelKeyDown}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`Token detail for ${path}`}\n tabIndex={-1}\n >\n <button\n type=\"button\"\n className=\"sb-detail-overlay__close\"\n onClick={onClose}\n aria-label=\"Close\"\n data-testid={`${testId}-close`}\n >\n ×\n </button>\n <TokenDetail path={path} />\n </div>\n </div>\n );\n}\n","import { fuzzyFilter } from '@unpunnyfuns/swatchbook-core/fuzzy';\nimport type { KeyboardEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport './TokenNavigator.css';\nimport { BorderSample } from '#/border-preview/BorderSample.tsx';\nimport { useColorFormat } from '#/contexts.ts';\nimport { DimensionBar } from '#/dimension-scale/DimensionBar.tsx';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { DetailOverlay } from '#/internal/DetailOverlay.tsx';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { EmptyState } from '#/internal/styles.tsx';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { MotionSample } from '#/motion-preview/MotionSample.tsx';\nimport { ShadowSample } from '#/shadow-preview/ShadowSample.tsx';\nimport type { VirtualToken } from '#/types.ts';\n\nexport interface TokenNavigatorProps {\n /** If provided, mount at this dot-path subtree and hide everything outside it. */\n root?: string;\n /**\n * Restrict the tree to tokens with the given DTCG `$type`(s). Pass a single\n * string to scope to one type (`type=\"color\"`), or an array for a narrow\n * small-multiples view (`type={['duration', 'cubicBezier', 'transition']}`).\n * Composes with `root` — both constraints must hold. Group nodes that end\n * up with no surviving leaves collapse out.\n */\n type?: string | readonly string[];\n /**\n * Depth (from the mounted root) that is expanded on first render.\n * `0` = everything collapsed, `1` = top-level groups open (default),\n * `2` = one level deeper, etc.\n */\n initiallyExpanded?: number;\n /**\n * Render a runtime search input above the tree. Matches are fuzzy\n * (case-insensitive, out-of-order terms, single-character typo\n * tolerance) against a leaf's token path; groups that contain no\n * matching leaves collapse out, and every group on the path to a\n * match auto-expands so hits are visible without clicking. Defaults\n * to `true`.\n */\n searchable?: boolean;\n /**\n * Called with a leaf's full dot-path when it is clicked. When set, the\n * inline `<TokenDetail>` slide-over is suppressed — the consumer owns\n * the follow-up UI.\n */\n onSelect?(path: string): void;\n}\n\ninterface LeafNode {\n kind: 'leaf';\n segment: string;\n path: string;\n token: VirtualToken;\n}\n\ninterface GroupNode {\n kind: 'group';\n segment: string;\n path: string;\n children: TreeNode[];\n}\n\ntype TreeNode = LeafNode | GroupNode;\n\nfunction buildTree(\n resolved: Record<string, VirtualToken>,\n root: string | undefined,\n typeFilter: ReadonlySet<string> | undefined,\n): TreeNode[] {\n const rootPrefix = root && root.length > 0 ? `${root}.` : '';\n const rootSegments = root ? root.split('.') : [];\n\n const entries = Object.entries(resolved).filter(([path, token]) => {\n if (root && !(path === root || path.startsWith(rootPrefix))) return false;\n if (typeFilter && !(token.$type && typeFilter.has(token.$type))) return false;\n return true;\n });\n\n const rootNode: GroupNode = { kind: 'group', segment: '', path: '', children: [] };\n\n for (const [path, token] of entries) {\n const remainder = root ? (path === root ? '' : path.slice(rootPrefix.length)) : path;\n const segments = remainder.length > 0 ? remainder.split('.') : [];\n\n let node: GroupNode = rootNode;\n for (let i = 0; i < segments.length - 1; i += 1) {\n const seg = segments[i];\n if (seg === undefined) continue;\n const prefix = [...rootSegments, ...segments.slice(0, i + 1)].join('.');\n let child = node.children.find(\n (c): c is GroupNode => c.kind === 'group' && c.segment === seg,\n );\n if (!child) {\n child = { kind: 'group', segment: seg, path: prefix, children: [] };\n node.children.push(child);\n }\n node = child;\n }\n\n const leafSegment = segments[segments.length - 1];\n if (leafSegment === undefined) {\n node.children.push({\n kind: 'leaf',\n segment: root ? (rootSegments[rootSegments.length - 1] ?? path) : path,\n path,\n token,\n });\n } else {\n node.children.push({ kind: 'leaf', segment: leafSegment, path, token });\n }\n }\n\n sortTree(rootNode);\n\n return rootNode.children;\n}\n\nfunction sortTree(node: GroupNode): void {\n node.children.sort((a, b) => {\n if (a.kind !== b.kind) return a.kind === 'group' ? -1 : 1;\n return a.segment.localeCompare(b.segment, undefined, { numeric: true });\n });\n for (const c of node.children) {\n if (c.kind === 'group') sortTree(c);\n }\n}\n\nfunction collectInitialExpanded(nodes: TreeNode[], remainingDepth: number, out: Set<string>): void {\n if (remainingDepth <= 0) return;\n for (const node of nodes) {\n if (node.kind !== 'group') continue;\n out.add(node.path);\n collectInitialExpanded(node.children, remainingDepth - 1, out);\n }\n}\n\nfunction countLeaves(node: TreeNode): number {\n if (node.kind === 'leaf') return 1;\n let n = 0;\n for (const c of node.children) n += countLeaves(c);\n return n;\n}\n\nfunction collectLeafPaths(nodes: TreeNode[], out: string[]): void {\n for (const node of nodes) {\n if (node.kind === 'leaf') out.push(node.path);\n else collectLeafPaths(node.children, out);\n }\n}\n\n/**\n * Flatten the currently-visible treeitems into the order screen-reader\n * users + arrow-key users navigate them: depth-first, only descending\n * into expanded groups. Each entry carries enough metadata for the\n * keyboard handler to compute parent / first-child / next / prev.\n */\ninterface FlatTreeItem {\n path: string;\n kind: 'group' | 'leaf';\n /** Dot-path of the parent group, or `null` for top-level entries. */\n parentPath: string | null;\n}\n\nfunction flattenVisible(\n nodes: TreeNode[],\n expanded: Set<string>,\n parentPath: string | null,\n out: FlatTreeItem[],\n): void {\n for (const node of nodes) {\n out.push({ path: node.path, kind: node.kind, parentPath });\n if (node.kind === 'group' && expanded.has(node.path)) {\n flattenVisible(node.children, expanded, node.path, out);\n }\n }\n}\n\n/**\n * Return a pruned copy of the tree keeping only leaves whose path is in\n * `matches`, plus the groups on the way to them. Every surviving group's\n * path is added to `expandOut` so callers can force those groups open.\n */\nfunction pruneTreeForMatches(\n nodes: TreeNode[],\n matches: ReadonlySet<string>,\n expandOut: Set<string>,\n): TreeNode[] {\n const out: TreeNode[] = [];\n for (const node of nodes) {\n if (node.kind === 'leaf') {\n if (matches.has(node.path)) out.push(node);\n } else {\n const children = pruneTreeForMatches(node.children, matches, expandOut);\n if (children.length > 0) {\n expandOut.add(node.path);\n out.push({ ...node, children });\n }\n }\n }\n return out;\n}\n\nexport function TokenNavigator({\n root,\n type,\n initiallyExpanded = 1,\n searchable = true,\n onSelect,\n}: TokenNavigatorProps): ReactElement {\n const { resolved, activeTheme, cssVarPrefix } = useProject();\n\n const typeFilter = useMemo<ReadonlySet<string> | undefined>(() => {\n if (type === undefined) return undefined;\n return new Set(Array.isArray(type) ? type : [type]);\n }, [type]);\n\n const tree = useMemo(() => buildTree(resolved, root, typeFilter), [resolved, root, typeFilter]);\n\n const initialExpanded = useMemo(() => {\n const out = new Set<string>();\n collectInitialExpanded(tree, initiallyExpanded, out);\n return out;\n }, [tree, initiallyExpanded]);\n\n const [expanded, setExpanded] = useState<Set<string>>(initialExpanded);\n useEffect(() => {\n setExpanded(initialExpanded);\n }, [initialExpanded]);\n\n const [selectedPath, setSelectedPath] = useState<string | null>(null);\n const [query, setQuery] = useState('');\n\n const { visibleTree, searchExpanded } = useMemo(() => {\n if (!searchable || query.trim() === '') {\n return { visibleTree: tree, searchExpanded: null as Set<string> | null };\n }\n const leafPaths: string[] = [];\n collectLeafPaths(tree, leafPaths);\n const matches = new Set(fuzzyFilter(leafPaths, query, (p) => p));\n const expandOut = new Set<string>();\n const pruned = matches.size === 0 ? [] : pruneTreeForMatches(tree, matches, expandOut);\n return { visibleTree: pruned, searchExpanded: expandOut };\n }, [tree, query, searchable]);\n\n const effectiveExpanded = useMemo(() => {\n if (!searchExpanded) return expanded;\n const merged = new Set(expanded);\n for (const p of searchExpanded) merged.add(p);\n return merged;\n }, [expanded, searchExpanded]);\n\n const toggle = useCallback((path: string): void => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(path)) next.delete(path);\n else next.add(path);\n return next;\n });\n }, []);\n\n const handleLeafClick = useCallback(\n (path: string) => {\n if (onSelect) onSelect(path);\n else setSelectedPath(path);\n },\n [onSelect],\n );\n\n // WAI-ARIA tree pattern's roving tabindex — exactly one treeitem at a\n // time has tabIndex={0}; the rest are -1. Tab into / out of the tree\n // hits that one item; arrow keys move focus between items inside.\n const [focusedPath, setFocusedPath] = useState<string | null>(null);\n const treeItemRefs = useRef<Map<string, HTMLLIElement>>(new Map());\n const registerTreeItem = useCallback(\n (path: string) =>\n (el: HTMLLIElement | null): void => {\n if (el) treeItemRefs.current.set(path, el);\n else treeItemRefs.current.delete(path);\n },\n [],\n );\n\n const flatVisible = useMemo<FlatTreeItem[]>(() => {\n const out: FlatTreeItem[] = [];\n flattenVisible(visibleTree, effectiveExpanded, null, out);\n return out;\n }, [visibleTree, effectiveExpanded]);\n\n // Reset / repair focused path whenever the visible set changes. Keep\n // the existing focus if it's still visible; otherwise fall back to\n // the first item.\n useEffect(() => {\n if (flatVisible.length === 0) {\n setFocusedPath(null);\n return;\n }\n setFocusedPath((prev) => {\n if (prev && flatVisible.some((entry) => entry.path === prev)) return prev;\n return flatVisible[0]?.path ?? null;\n });\n }, [flatVisible]);\n\n const focusByPath = useCallback((path: string): void => {\n const node = treeItemRefs.current.get(path);\n if (node) {\n node.focus();\n setFocusedPath(path);\n } else {\n // Ref will register on the next render; flag the path so the\n // focus-repair effect can move focus once the node mounts.\n setFocusedPath(path);\n }\n }, []);\n\n // After expanding a group via Right-arrow, the new children mount on\n // the following render. If a path was queued via setFocusedPath but\n // the corresponding ref didn't exist at the time, repair focus now\n // that the children are live.\n useEffect(() => {\n if (focusedPath === null) return;\n const node = treeItemRefs.current.get(focusedPath);\n if (node && document.activeElement !== node) {\n // Only steal focus if it currently sits on a different treeitem\n // inside our tree — don't yank it away from the search input or\n // anything outside.\n const active = document.activeElement;\n const insideTree = active instanceof HTMLElement && active.closest('[role=\"tree\"]');\n if (insideTree) node.focus();\n }\n }, [focusedPath]);\n\n const handleTreeKeyDown = useCallback(\n (e: KeyboardEvent<HTMLUListElement>): void => {\n // Derive the active treeitem from `document.activeElement` rather\n // than the `focusedPath` state. State updates from `onFocus` may\n // not have flushed by the time a subsequent keydown fires (e.g.\n // tests that programmatically `.focus()` then immediately dispatch\n // keys), and the handler must always operate on the row the user\n // is currently on.\n if (flatVisible.length === 0) return;\n const active = document.activeElement;\n if (!(active instanceof HTMLLIElement)) return;\n const activePath = active.getAttribute('data-path');\n if (activePath === null) return;\n const currentIndex = flatVisible.findIndex((entry) => entry.path === activePath);\n if (currentIndex < 0) return;\n const current = flatVisible[currentIndex];\n if (!current) return;\n\n switch (e.key) {\n case 'ArrowDown': {\n const next = flatVisible[currentIndex + 1];\n if (next) {\n e.preventDefault();\n focusByPath(next.path);\n }\n return;\n }\n case 'ArrowUp': {\n const prev = flatVisible[currentIndex - 1];\n if (prev) {\n e.preventDefault();\n focusByPath(prev.path);\n }\n return;\n }\n case 'Home': {\n const first = flatVisible[0];\n if (first) {\n e.preventDefault();\n focusByPath(first.path);\n }\n return;\n }\n case 'End': {\n const last = flatVisible[flatVisible.length - 1];\n if (last) {\n e.preventDefault();\n focusByPath(last.path);\n }\n return;\n }\n case 'ArrowRight': {\n if (current.kind === 'group') {\n if (!effectiveExpanded.has(current.path)) {\n e.preventDefault();\n toggle(current.path);\n // Focus stays on the group — user can press Right again\n // to step into the first child on the next render.\n return;\n }\n // Already expanded: step into first child (which is the\n // next entry in the flattened list).\n const firstChild = flatVisible[currentIndex + 1];\n if (firstChild && firstChild.parentPath === current.path) {\n e.preventDefault();\n focusByPath(firstChild.path);\n }\n }\n return;\n }\n case 'ArrowLeft': {\n if (current.kind === 'group' && effectiveExpanded.has(current.path)) {\n e.preventDefault();\n toggle(current.path);\n return;\n }\n // Collapsed group or leaf: step to parent.\n if (current.parentPath !== null) {\n e.preventDefault();\n focusByPath(current.parentPath);\n }\n return;\n }\n case 'Enter':\n case ' ': {\n e.preventDefault();\n if (current.kind === 'group') toggle(current.path);\n else handleLeafClick(current.path);\n return;\n }\n default:\n return;\n }\n },\n [flatVisible, effectiveExpanded, toggle, focusByPath, handleLeafClick],\n );\n\n const typeLabel = typeFilter ? ` · ${[...typeFilter].map((t) => `$type=${t}`).join(', ')}` : '';\n const trimmedQuery = query.trim();\n // Must run every render — React's rules of hooks forbid the earlier empty-state\n // early return from skipping it, or the next non-empty render throws\n // \"Rendered fewer hooks than expected\".\n const matchCount = useMemo(() => {\n if (!searchExpanded) return 0;\n let n = 0;\n for (const node of visibleTree) n += countLeaves(node);\n return n;\n }, [visibleTree, searchExpanded]);\n\n if (tree.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <EmptyState>\n {root\n ? `No tokens under \"${root}\"${typeFilter ? ` matching ${typeLabel.slice(3)}` : ''}.`\n : typeFilter\n ? `No tokens matching ${typeLabel.slice(3)} in the active theme.`\n : 'No tokens in the active theme.'}\n </EmptyState>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n {searchable && (\n <div className=\"sb-token-navigator__search\">\n <input\n type=\"search\"\n className=\"sb-token-navigator__search-input\"\n placeholder=\"Search tokens…\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n aria-label=\"Search tokens by path\"\n data-testid=\"token-navigator-search\"\n />\n </div>\n )}\n <div className=\"sb-token-navigator__caption\">\n {root ? `Tokens under ${root}` : 'Token graph'}\n {typeLabel}\n {trimmedQuery !== '' ? ` · ${matchCount} matching \"${trimmedQuery}\"` : ''} · {activeTheme}\n </div>\n {visibleTree.length === 0 ? (\n <div className=\"sb-block__empty\">No tokens match \"{trimmedQuery}\".</div>\n ) : (\n <ul\n className=\"sb-token-navigator__tree\"\n role=\"tree\"\n aria-label=\"Token graph\"\n onKeyDown={handleTreeKeyDown}\n >\n {visibleTree.map((node) => (\n <TreeNodeRow\n key={node.path || node.segment}\n node={node}\n expanded={effectiveExpanded}\n focusedPath={focusedPath}\n registerTreeItem={registerTreeItem}\n onToggle={toggle}\n onFocusPath={setFocusedPath}\n onLeafClick={handleLeafClick}\n />\n ))}\n </ul>\n )}\n\n {selectedPath !== null && (\n <DetailOverlay\n path={selectedPath}\n onClose={() => setSelectedPath(null)}\n testId=\"token-navigator-overlay\"\n />\n )}\n </div>\n );\n}\n\ninterface TreeNodeRowProps {\n node: TreeNode;\n expanded: Set<string>;\n focusedPath: string | null;\n registerTreeItem(path: string): (el: HTMLLIElement | null) => void;\n onToggle(path: string): void;\n onFocusPath(path: string): void;\n onLeafClick(path: string): void;\n}\n\nfunction TreeNodeRow({\n node,\n expanded,\n focusedPath,\n registerTreeItem,\n onToggle,\n onFocusPath,\n onLeafClick,\n}: TreeNodeRowProps): ReactElement {\n if (node.kind === 'leaf') {\n return (\n <LeafRow\n node={node}\n focusedPath={focusedPath}\n registerTreeItem={registerTreeItem}\n onFocusPath={onFocusPath}\n onLeafClick={onLeafClick}\n />\n );\n }\n const isOpen = expanded.has(node.path);\n const isFocused = focusedPath === node.path;\n return (\n <li\n ref={registerTreeItem(node.path)}\n role=\"treeitem\"\n aria-expanded={isOpen}\n tabIndex={isFocused ? 0 : -1}\n onFocus={() => onFocusPath(node.path)}\n data-path={node.path}\n data-testid=\"token-navigator-group\"\n >\n {/*\n Click handler on the inner row div, not the <li>. Nested\n treeitems are DOM descendants of their parent <li>, so a\n click on a child row would bubble through each ancestor\n <li>'s onClick. The row div is a SIBLING of the nested\n <ul>, so child rows never bubble through it.\n */}\n <div\n className=\"sb-token-navigator__group-row\"\n data-testid=\"token-navigator-group-row\"\n onClick={() => {\n onFocusPath(node.path);\n onToggle(node.path);\n }}\n >\n <span className=\"sb-token-navigator__caret\" aria-hidden>\n {isOpen ? '▾' : '▸'}\n </span>\n <span>{node.segment}</span>\n <span className=\"sb-token-navigator__count\">{countLeaves(node)}</span>\n </div>\n {isOpen && (\n <ul className=\"sb-token-navigator__nested\" role=\"group\">\n {node.children.map((c) => (\n <TreeNodeRow\n key={c.path || c.segment}\n node={c}\n expanded={expanded}\n focusedPath={focusedPath}\n registerTreeItem={registerTreeItem}\n onToggle={onToggle}\n onFocusPath={onFocusPath}\n onLeafClick={onLeafClick}\n />\n ))}\n </ul>\n )}\n </li>\n );\n}\n\ninterface LeafRowProps {\n node: LeafNode;\n focusedPath: string | null;\n registerTreeItem(path: string): (el: HTMLLIElement | null) => void;\n onFocusPath(path: string): void;\n onLeafClick(path: string): void;\n}\n\nfunction LeafRow({\n node,\n focusedPath,\n registerTreeItem,\n onFocusPath,\n onLeafClick,\n}: LeafRowProps): ReactElement {\n const type = node.token.$type ?? '';\n const isFocused = focusedPath === node.path;\n return (\n <li\n ref={registerTreeItem(node.path)}\n role=\"treeitem\"\n tabIndex={isFocused ? 0 : -1}\n onFocus={() => onFocusPath(node.path)}\n data-path={node.path}\n data-testid=\"token-navigator-leaf\"\n >\n {/* Click handler on the inner row div for the same reason as\n group rows — see TreeNodeRow. */}\n <div\n className=\"sb-token-navigator__leaf-row\"\n data-testid=\"token-navigator-leaf-row\"\n onClick={() => {\n onFocusPath(node.path);\n onLeafClick(node.path);\n }}\n >\n <span className=\"sb-token-navigator__caret\" aria-hidden>\n •\n </span>\n <span className=\"sb-token-navigator__tail\">{node.segment}</span>\n {type && <span className=\"sb-token-navigator__type-pill\">{type}</span>}\n <LeafPreview path={node.path} token={node.token} />\n </div>\n </li>\n );\n}\n\ninterface LeafPreviewProps {\n path: string;\n token: VirtualToken;\n}\n\nfunction LeafPreview({ path, token }: LeafPreviewProps): ReactElement {\n const project = useProject();\n const colorFormat = useColorFormat();\n const type = token.$type;\n\n if (type === 'color') {\n const cssVar = resolveCssVar(path, project);\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__value\">\n {formatTokenValue(token.$value, type, colorFormat, project.listing[path])}\n </span>\n <span\n className=\"sb-token-navigator__color-swatch\"\n style={{ background: cssVar }}\n aria-hidden\n />\n </span>\n );\n }\n if (type === 'dimension') {\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__value\">\n {formatTokenValue(token.$value, type, colorFormat, project.listing[path])}\n </span>\n <span className=\"sb-token-navigator__preview-dimension\">\n <DimensionBar path={path} kind=\"length\" />\n </span>\n </span>\n );\n }\n if (type === 'shadow') {\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__preview-scaled\">\n <ShadowSample path={path} />\n </span>\n </span>\n );\n }\n if (type === 'border') {\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__preview-scaled\">\n <BorderSample path={path} />\n </span>\n </span>\n );\n }\n if (type === 'transition' || type === 'duration' || type === 'cubicBezier') {\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__preview-motion\">\n <MotionSample path={path} />\n </span>\n </span>\n );\n }\n\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__value\">\n {formatTokenValue(token.$value, type, colorFormat, project.listing[path])}\n </span>\n </span>\n );\n}\n","import { fuzzyFilter } from '@unpunnyfuns/swatchbook-core/fuzzy';\nimport cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport { useCallback, useMemo, useState } from 'react';\nimport './TokenTable.css';\nimport { useColorFormat } from '#/contexts.ts';\nimport { CopyButton } from '#/internal/CopyButton.tsx';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { DetailOverlay } from '#/internal/DetailOverlay.tsx';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveColorValue, resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface TokenTableProps {\n /**\n * Token-path filter. `\"color.*\"` matches every `color.…` token;\n * omit to include everything. Combines with `type` (both must match).\n */\n filter?: string;\n /** Restrict to one DTCG `$type`. */\n type?: string;\n /** Override the table caption. */\n caption?: string;\n /**\n * Sort order.\n * - `'path'` (default) — lexicographic on the dot-path.\n * - `'value'` — per-`$type`: numeric for `dimension` / `duration` /\n * `fontWeight`; perceptual (oklch L → C → H) for `color`; lexicographic\n * for `fontFamily` / `strokeStyle`. Composite types fall through to\n * path order.\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n /**\n * Render a runtime search input above the table that narrows rows by\n * fuzzy match (case-insensitive, out-of-order terms, single-character\n * typo tolerance) against the token path, type, or value. Defaults to\n * `true` because browsing a multi-hundred-token reference without\n * search is painful. Pass `false` to hide the input (the `filter` /\n * `type` props still apply at authoring time).\n */\n searchable?: boolean;\n /**\n * Called with the clicked row's dot-path. When set, the built-in\n * `<TokenDetail>` slide-over is suppressed — the consumer owns the\n * follow-up UI (inline panel, drill-down route, …).\n */\n onSelect?(path: string): void;\n}\n\nexport function TokenTable({\n filter,\n type,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n searchable = true,\n onSelect,\n}: TokenTableProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n const [selectedPath, setSelectedPath] = useState<string | null>(null);\n const [query, setQuery] = useState('');\n\n const rows = useMemo(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (!matchPath(path, filter)) return false;\n if (type && token.$type !== type) return false;\n return true;\n });\n const entries = sortTokens(filtered, { by: sortBy, dir: sortDir });\n return entries.map(([path, token]) => {\n const isColor = token.$type === 'color';\n const color = isColor ? resolveColorValue(path, token.$value, colorFormat, project) : null;\n return {\n path,\n type: token.$type ?? '',\n value: formatTokenValue(token.$value, token.$type, colorFormat, project.listing[path]),\n outOfGamut: color?.outOfGamut ?? false,\n cssVar: resolveCssVar(path, project),\n isColor,\n };\n });\n }, [resolved, filter, type, project, colorFormat, sortBy, sortDir]);\n\n const visibleRows = useMemo(() => {\n if (!searchable || query.trim() === '') return rows;\n return fuzzyFilter(rows, query, (row) => `${row.path} ${row.type} ${row.value}`);\n }, [rows, query, searchable]);\n\n const handleRowClick = useCallback(\n (path: string) => {\n if (onSelect) onSelect(path);\n else setSelectedPath(path);\n },\n [onSelect],\n );\n\n const matchSuffix =\n searchable && query.trim() !== '' ? ` · ${visibleRows.length} matching \"${query.trim()}\"` : '';\n const captionText =\n caption ??\n `${rows.length} token${rows.length === 1 ? '' : 's'}${\n filter ? ` matching \\`${filter}\\`` : ''\n }${type ? ` · $type=${type}` : ''}${matchSuffix} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n {searchable && (\n <div className=\"sb-token-table__search\">\n <input\n type=\"search\"\n className=\"sb-token-table__search-input\"\n placeholder=\"Search tokens…\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n aria-label=\"Fuzzy-search tokens by path, type, or value\"\n data-testid=\"token-table-search\"\n />\n </div>\n )}\n <table className=\"sb-token-table__table\">\n <caption className=\"sb-token-table__caption\">{captionText}</caption>\n <thead>\n <tr>\n <th className={cx('sb-token-table__th', 'sb-token-table__th--path')}>Path</th>\n <th className={cx('sb-token-table__th', 'sb-token-table__th--value')}>Value</th>\n </tr>\n </thead>\n <tbody>\n {visibleRows.length === 0 && (\n <tr>\n <td colSpan={2} className=\"sb-token-table__td sb-token-table__empty-row\">\n No tokens match \"{query.trim()}\".\n </td>\n </tr>\n )}\n {visibleRows.map((row) => (\n <tr\n key={row.path}\n className=\"sb-token-table__row\"\n onClick={() => handleRowClick(row.path)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleRowClick(row.path);\n }\n }}\n tabIndex={0}\n aria-label={`Inspect ${row.path}`}\n data-testid=\"token-table-row\"\n data-path={row.path}\n >\n <td className={cx('sb-token-table__td', 'sb-token-table__path')}>{row.path}</td>\n <td className=\"sb-token-table__td\">\n <span className=\"sb-token-table__value-cell\">\n {row.type && <span className=\"sb-token-table__type-pill\">{row.type}</span>}\n {row.isColor && (\n <span\n className=\"sb-token-table__swatch\"\n style={{ background: row.cssVar }}\n aria-hidden\n />\n )}\n <span\n className=\"sb-token-table__value-text\"\n title={row.value}\n data-testid=\"token-table-value\"\n >\n {row.value}\n </span>\n {row.outOfGamut && (\n <span\n title=\"Out of sRGB gamut for this format\"\n aria-label=\"out of gamut\"\n className=\"sb-token-table__gamut-warn\"\n >\n ⚠\n </span>\n )}\n <span\n className=\"sb-token-table__copy-wrap\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n role=\"presentation\"\n >\n <CopyButton\n value={row.value}\n label={`Copy value ${row.value}`}\n className=\"sb-token-table__copy\"\n />\n </span>\n </span>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n\n {selectedPath !== null && (\n <DetailOverlay\n path={selectedPath}\n onClose={() => setSelectedPath(null)}\n testId=\"token-table-overlay\"\n />\n )}\n </div>\n );\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './TypographyScale.css';\nimport type { TypographyValue } from '#/internal/composite-types.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\n\n/**\n * Dimension sub-values in DTCG 2025.10 use a `{ value, unit }` envelope\n * — narrow once here so the local `asDimension` helper doesn't need\n * to re-validate keys at every read.\n */\ninterface DimensionLike {\n value?: unknown;\n unit?: unknown;\n}\n\nexport interface TypographyScaleProps {\n /**\n * Token-path filter. Defaults to every `typography` token. Use e.g.\n * `\"typography.*\"` to scope to the semantic layer.\n */\n filter?: string;\n /** Override the sample text rendered for each token. */\n sample?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` ordering falls through to path for this block's\n * type (composite / non-numeric); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface Row {\n path: string;\n sampleStyle: CSSProperties;\n specs: string;\n}\n\nfunction asDimension(raw: unknown): string | undefined {\n if (raw == null) return undefined;\n if (typeof raw === 'string' || typeof raw === 'number') return String(raw);\n if (typeof raw === 'object') {\n const v = raw as DimensionLike;\n if (v.value !== undefined && v.unit !== undefined) return `${String(v.value)}${String(v.unit)}`;\n }\n return undefined;\n}\n\nfunction asFontFamily(raw: unknown): string | undefined {\n if (typeof raw === 'string') return raw;\n if (Array.isArray(raw)) return raw.map(String).join(', ');\n return undefined;\n}\n\nfunction buildRow(path: string, composite: TypographyValue): Row {\n const fontFamily = asFontFamily(composite.fontFamily);\n const fontSize = asDimension(composite.fontSize);\n const fontWeight = composite.fontWeight == null ? undefined : String(composite.fontWeight);\n const lineHeight = composite.lineHeight == null ? undefined : String(composite.lineHeight);\n const letterSpacing = asDimension(composite.letterSpacing);\n\n const sampleStyle: CSSProperties = {};\n if (fontFamily) sampleStyle.fontFamily = fontFamily;\n if (fontSize) sampleStyle.fontSize = fontSize;\n if (fontWeight) sampleStyle.fontWeight = fontWeight as CSSProperties['fontWeight'];\n if (lineHeight) sampleStyle.lineHeight = lineHeight;\n if (letterSpacing) sampleStyle.letterSpacing = letterSpacing;\n\n const parts = [\n fontSize,\n fontWeight ? `w${fontWeight}` : undefined,\n lineHeight ? `lh ${lineHeight}` : undefined,\n ]\n .filter(Boolean)\n .join(' · ');\n\n return { path, sampleStyle, specs: parts };\n}\n\nexport function TypographyScale({\n filter,\n sample = 'The quick brown fox jumps over the lazy dog.',\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: TypographyScaleProps): ReactElement {\n const { resolved, activeTheme, cssVarPrefix } = useProject();\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'typography') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => {\n const value = token.$value;\n if (!value || typeof value !== 'object') {\n return { path, sampleStyle: {}, specs: '' };\n }\n return buildRow(path, value as TypographyValue);\n });\n }, [resolved, filter, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} typography token${rows.length === 1 ? '' : 's'}${filter && filter !== 'typography' ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__empty\">No typography tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeTheme)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-typography-scale__row\">\n <div className=\"sb-typography-scale__meta\">\n <span className=\"sb-typography-scale__path\">{row.path}</span>\n {row.specs && <span className=\"sb-typography-scale__specs\">{row.specs}</span>}\n </div>\n <div style={row.sampleStyle}>{sample}</div>\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["snapshot","listeners","subscribed","ensureSubscribed","subscribe","getSnapshot","initialAxes","initialPresets","initialDiagnostics","initialCss","initialCssVarPrefix","initialListing","initialCells","initialJointOverrides","initialVarianceByPath","initialDefaultTuple","defaultTuple","sampleStyle","formatDimension","formatSubColor","CopyButton","CopyButton","MAX_RENDER_PX","styles","toPixels","formatDimension","formatFontFamily","formatPrimitive","CopyButton","CopyButton","CopyButton"],"sources":["../src/format-color.ts","../src/internal/styles.tsx","../src/internal/channel-globals.ts","../src/contexts.ts","../src/internal/channel-tokens.ts","../src/internal/use-project.ts","../src/border-preview/BorderSample.tsx","../src/internal/data-attr.ts","../src/internal/sort-tokens.ts","../src/BorderPreview.tsx","../src/ColorPalette.tsx","../src/internal/CopyButton.tsx","../src/ColorTable.tsx","../src/Diagnostics.tsx","../src/dimension-scale/DimensionBar.tsx","../src/internal/format-token-value.ts","../src/DimensionScale.tsx","../src/FontFamilySample.tsx","../src/internal/css-var-style.ts","../src/FontWeightScale.tsx","../src/GradientPalette.tsx","../src/internal/prefers-reduced-motion.ts","../src/motion-preview/MotionSample.tsx","../src/MotionPreview.tsx","../src/OpacityScale.tsx","../src/provider.tsx","../src/shadow-preview/ShadowSample.tsx","../src/ShadowPreview.tsx","../src/StrokeStyleSample.tsx","../src/token-detail/internal.ts","../src/token-detail/AliasChain.tsx","../src/token-detail/AliasedBy.tsx","../src/token-detail/AxisVariance.tsx","../src/token-detail/CompositeBreakdown.tsx","../src/token-detail/CompositePreview.tsx","../src/token-detail/ConsumerOutput.tsx","../src/token-detail/TokenHeader.tsx","../src/token-detail/TokenUsageSnippet.tsx","../src/TokenDetail.tsx","../src/internal/DetailOverlay.tsx","../src/TokenNavigator.tsx","../src/TokenTable.tsx","../src/TypographyScale.tsx"],"sourcesContent":["import Color from 'colorjs.io';\nimport type { ColorValue } from '#/internal/composite-types.ts';\n\n/**\n * Color display formats understood by {@link formatColor}.\n *\n * - `hex` — sRGB hex (`#rrggbb` or `#rrggbbaa`). Out-of-gamut or wide-gamut\n * colors fall back to `rgb()` and surface `outOfGamut: true` so callers\n * can render a ⚠ glyph.\n * - `rgb` / `hsl` — modern CSS Color 4 space-separated syntax, converted\n * from the source colorspace. Out-of-gamut values are still stringified\n * (the browser will clip when actually rendering) and flagged.\n * - `oklch` — perceptual wide-gamut form. Never marks out-of-gamut because\n * every color expressible in sRGB/P3 fits in oklch.\n * - `raw` — compact JSON of the normalized Terrazzo shape. For DTCG\n * authors who want to see what the parser actually stored.\n */\nexport type ColorFormat = 'hex' | 'rgb' | 'hsl' | 'oklch' | 'raw';\n\nexport const COLOR_FORMATS: readonly ColorFormat[] = ['hex', 'rgb', 'hsl', 'oklch', 'raw'];\n\n/**\n * Terrazzo's `ColorValueNormalized`, copied inline to avoid a hard dep on\n * `@terrazzo/token-tools` from blocks. Matches the shape documented at\n * https://terrazzo.app/docs/cli/reference/token-tools/ColorValueNormalized.\n *\n * Some token payloads we see in the wild use the legacy DTCG-ish `channels`\n * field in place of `components`; we accept either.\n */\nexport interface NormalizedColor {\n colorSpace: string;\n components?: readonly (number | null)[];\n channels?: readonly (number | null)[];\n alpha?: number;\n hex?: string;\n}\n\nexport interface FormatColorResult {\n /** Display string — e.g. `rgb(59 132 246)`, `#3b82f6`. */\n value: string;\n /** True when the requested format can't losslessly represent the color. */\n outOfGamut: boolean;\n}\n\nconst DEFAULT_FALLBACK = '—';\n\n/**\n * Convert Terrazzo's normalized color payload into a display string in the\n * requested format. Pure function — never throws; returns `{ value: '—' }`\n * for unrecognized input so calling blocks don't need try/catch.\n */\nexport function formatColor(\n value: unknown,\n format: ColorFormat,\n fallback: string = DEFAULT_FALLBACK,\n): FormatColorResult {\n const normalized = coerce(value);\n if (!normalized) return { value: stringifyFallback(value, fallback), outOfGamut: false };\n\n if (format === 'raw') {\n return { value: compactJson(normalized), outOfGamut: false };\n }\n\n const color = toColor(normalized);\n if (!color) return { value: stringifyFallback(value, fallback), outOfGamut: false };\n\n const alpha = typeof normalized.alpha === 'number' ? normalized.alpha : 1;\n\n if (format === 'hex') return formatHex(color, alpha);\n if (format === 'rgb') return formatRgb(color, alpha);\n if (format === 'hsl') return formatHsl(color, alpha);\n return formatOklch(color, alpha);\n}\n\nfunction coerce(value: unknown): NormalizedColor | null {\n if (!value || typeof value !== 'object') return null;\n const v = value as ColorValue;\n const colorSpace = typeof v.colorSpace === 'string' ? v.colorSpace : undefined;\n const components = Array.isArray(v.components)\n ? (v.components as (number | null)[])\n : Array.isArray(v.channels)\n ? (v.channels as (number | null)[])\n : undefined;\n if (!colorSpace || !components) {\n if (typeof v.hex === 'string') {\n return { colorSpace: 'srgb', components: hexToComponents(v.hex) };\n }\n return null;\n }\n const alpha = typeof v.alpha === 'number' ? v.alpha : undefined;\n const hexVal = v['hex'];\n const hex = typeof hexVal === 'string' ? hexVal : undefined;\n return {\n colorSpace,\n components,\n ...(alpha !== undefined && { alpha }),\n ...(hex !== undefined && { hex }),\n };\n}\n\nfunction hexToComponents(hex: string): number[] {\n const h = hex.replace('#', '');\n const expanded =\n h.length === 3 || h.length === 4\n ? h\n .split('')\n .map((c) => c + c)\n .join('')\n : h;\n const r = parseInt(expanded.slice(0, 2), 16) / 255;\n const g = parseInt(expanded.slice(2, 4), 16) / 255;\n const b = parseInt(expanded.slice(4, 6), 16) / 255;\n return [r, g, b];\n}\n\n/**\n * Map Terrazzo's canonical CSS Color 4 space identifiers to the shorter\n * identifiers colorjs.io registers. Only the ones that differ need an entry.\n */\nconst COLORJS_SPACE_ALIASES: Record<string, string> = {\n 'display-p3': 'p3',\n 'a98-rgb': 'a98rgb',\n 'prophoto-rgb': 'prophoto',\n};\n\nfunction toColor(normalized: NormalizedColor): Color | null {\n const source = normalized.components ?? normalized.channels ?? [];\n const coords: [number, number, number] = [\n numberOrZero(source[0]),\n numberOrZero(source[1]),\n numberOrZero(source[2]),\n ];\n const space = COLORJS_SPACE_ALIASES[normalized.colorSpace] ?? normalized.colorSpace;\n try {\n return new Color(space, coords, normalized.alpha ?? 1);\n } catch {\n return null;\n }\n}\n\nfunction numberOrZero(n: number | null | undefined): number {\n return typeof n === 'number' && !Number.isNaN(n) ? n : 0;\n}\n\nfunction coord(color: Color, i: number): number {\n const c = color.coords[i];\n return typeof c === 'number' && !Number.isNaN(c) ? c : 0;\n}\n\nfunction formatHex(color: Color, alpha: number): FormatColorResult {\n const srgb = color.to('srgb');\n const inGamut = srgb.inGamut('srgb');\n if (!inGamut) {\n const rgb = formatRgb(color, alpha);\n return { value: rgb.value, outOfGamut: true };\n }\n const r = clamp255(coord(srgb, 0));\n const g = clamp255(coord(srgb, 1));\n const b = clamp255(coord(srgb, 2));\n const base = `#${toHexByte(r)}${toHexByte(g)}${toHexByte(b)}`;\n if (alpha >= 1) return { value: base, outOfGamut: false };\n const a = clamp255(alpha);\n return { value: `${base}${toHexByte(a)}`, outOfGamut: false };\n}\n\nfunction formatRgb(color: Color, alpha: number): FormatColorResult {\n const srgb = color.to('srgb');\n const inGamut = srgb.inGamut('srgb');\n const r = Math.round(clampUnit(coord(srgb, 0)) * 255);\n const g = Math.round(clampUnit(coord(srgb, 1)) * 255);\n const b = Math.round(clampUnit(coord(srgb, 2)) * 255);\n const body = `${r} ${g} ${b}`;\n const value = alpha >= 1 ? `rgb(${body})` : `rgb(${body} / ${roundAlpha(alpha)})`;\n return { value, outOfGamut: !inGamut };\n}\n\nfunction formatHsl(color: Color, alpha: number): FormatColorResult {\n const hsl = color.to('hsl');\n const srgb = color.to('srgb');\n const inGamut = srgb.inGamut('srgb');\n const hue = roundHue(coord(hsl, 0));\n const sat = roundPercent(coord(hsl, 1));\n const light = roundPercent(coord(hsl, 2));\n const body = `${hue} ${sat}% ${light}%`;\n const value = alpha >= 1 ? `hsl(${body})` : `hsl(${body} / ${roundAlpha(alpha)})`;\n return { value, outOfGamut: !inGamut };\n}\n\nfunction formatOklch(color: Color, alpha: number): FormatColorResult {\n const oklch = color.to('oklch');\n const L = roundTo(coord(oklch, 0), 3);\n const C = roundTo(coord(oklch, 1), 3);\n const H = roundTo(coord(oklch, 2), 2);\n const body = `${L} ${C} ${H}`;\n const value = alpha >= 1 ? `oklch(${body})` : `oklch(${body} / ${roundAlpha(alpha)})`;\n return { value, outOfGamut: false };\n}\n\nfunction clamp255(n: number): number {\n return Math.max(0, Math.min(255, Math.round(n * 255)));\n}\n\nfunction clampUnit(n: number): number {\n return Math.max(0, Math.min(1, n));\n}\n\nfunction toHexByte(n: number): string {\n return n.toString(16).padStart(2, '0');\n}\n\nfunction roundTo(n: number, digits: number): number {\n const f = 10 ** digits;\n return Math.round(n * f) / f;\n}\n\nfunction roundHue(h: number): number {\n return roundTo(((h % 360) + 360) % 360, 1);\n}\n\nfunction roundPercent(n: number): number {\n return Math.round(n * 10) / 10;\n}\n\nfunction roundAlpha(a: number): number {\n return roundTo(a, 3);\n}\n\nfunction compactJson(value: NormalizedColor): string {\n const parts: string[] = [`\"colorSpace\":${JSON.stringify(value.colorSpace)}`];\n const components = value.components ?? value.channels;\n if (components) {\n parts.push(`\"components\":[${components.map((c) => (c === null ? 'null' : c)).join(', ')}]`);\n }\n if (typeof value.alpha === 'number' && value.alpha !== 1) {\n parts.push(`\"alpha\":${value.alpha}`);\n }\n return `{ ${parts.join(', ')} }`;\n}\n\nfunction stringifyFallback(value: unknown, fallback: string): string {\n if (value == null) return fallback;\n if (typeof value === 'string' || typeof value === 'number') return String(value);\n return fallback;\n}\n","import type { CSSProperties, ReactElement, ReactNode } from 'react';\n\n/**\n * Chrome-style primitives shared across every block. Kept as JS exports\n * for the inline-style sites that still compose them into per-block style\n * objects (e.g. TokenNavigator's `typePill` that builds on the shared\n * pill base). The pure direct-reference chrome — surface wrapper, caption,\n * empty-state — lives in `styles.css` and is applied via class names.\n */\n\nexport const TEXT_DEFAULT = 'var(--swatchbook-text-default, CanvasText)';\nexport const TEXT_MUTED = 'var(--swatchbook-text-muted, CanvasText)';\n\nexport const SURFACE_DEFAULT = 'var(--swatchbook-surface-default, Canvas)';\nexport const SURFACE_RAISED = 'var(--swatchbook-surface-raised, Canvas)';\nexport const SURFACE_MUTED = 'var(--swatchbook-surface-muted, rgba(128,128,128,0.15))';\n\nexport const BORDER_DEFAULT = `1px solid var(--swatchbook-border-default, rgba(128,128,128,0.2))`;\nexport const BORDER_FAINT = `1px solid var(--swatchbook-border-default, rgba(128,128,128,0.15))`;\nexport const BORDER_STRONG = `1px solid var(--swatchbook-border-default, rgba(128,128,128,0.3))`;\n\nexport const SIZE_PILL = 10;\n\nexport const typePillStyle = {\n display: 'inline-block',\n padding: '2px 6px',\n borderRadius: 4,\n fontSize: SIZE_PILL,\n letterSpacing: 0.5,\n textTransform: 'uppercase',\n background: SURFACE_MUTED,\n} satisfies CSSProperties;\n\n/**\n * Inner content for a block's \"nothing to render\" state. Call sites wrap\n * it in their own block wrapper (which already carries `themeAttrs`), so\n * the message itself just needs the muted type.\n */\nexport function EmptyState({ children }: { children: ReactNode }): ReactElement {\n return <div className=\"sb-block__empty\">{children}</div>;\n}\n","import { useSyncExternalStore } from 'react';\nimport { addons } from 'storybook/preview-api';\nimport { COLOR_FORMATS } from '#/format-color.ts';\nimport type { ColorFormat } from '#/format-color.ts';\n\n/**\n * Shared subscription to Storybook's globals channel, lifted out of React\n * component state so the values survive docs-mode remounts.\n *\n * On MDX docs pages, Storybook force-rerenders the docs container on every\n * `updateGlobals` (see `preview/runtime.js` → `onUpdateGlobals`), which\n * unmounts and remounts any embedded blocks. A `useState(null)` initializer\n * inside the block would reset to null on each remount — the symptom is a\n * one-frame flicker to the correct value, then revert to the defaults.\n * Module-level state persists; React reads it through `useSyncExternalStore`\n * and stays concurrent-safe.\n */\n\nexport interface ChannelGlobals {\n axes: Record<string, string> | null;\n format: ColorFormat | null;\n}\n\nconst AXES_GLOBAL_KEY = 'swatchbookAxes';\nconst COLOR_FORMAT_GLOBAL_KEY = 'swatchbookColorFormat';\n\nlet snapshot: ChannelGlobals = { axes: null, format: null };\nconst listeners = new Set<() => void>();\nlet subscribed = false;\n\nfunction isColorFormat(value: unknown): value is ColorFormat {\n return typeof value === 'string' && (COLOR_FORMATS as readonly string[]).includes(value);\n}\n\ninterface SwatchbookGlobalsPayload {\n swatchbookAxes?: Record<string, string>;\n swatchbookColorFormat?: ColorFormat;\n [key: string]: unknown;\n}\n\nfunction ensureSubscribed(): void {\n if (subscribed || typeof window === 'undefined') return;\n subscribed = true;\n const channel = addons.getChannel();\n // Storybook fires `globalsUpdated`, `setGlobals`, and `updateGlobals`\n // for the same logical change (preview init + every toolbar tick).\n // Subscribing to all three is intentional — `setGlobals` carries the\n // initial URL-persisted globals; `updateGlobals` is the toolbar\n // signal; `globalsUpdated` is the cross-frame echo. The handler runs\n // for each but content-deduplicates: we only update the shared\n // snapshot when axes or format actually shifted (the previous\n // identity-based spread guard fired three times per tick because each\n // spread produced a new object identity even with unchanged content).\n let lastFingerprint = '';\n const onGlobals = (payload: { globals?: SwatchbookGlobalsPayload }): void => {\n const globals = payload.globals;\n if (!globals) return;\n const incomingAxes = globals[AXES_GLOBAL_KEY];\n const incomingFormat = globals[COLOR_FORMAT_GLOBAL_KEY];\n const nextAxes =\n incomingAxes && typeof incomingAxes === 'object' ? incomingAxes : snapshot.axes;\n const nextFormat = isColorFormat(incomingFormat) ? incomingFormat : snapshot.format;\n const fingerprint = `${nextFormat ?? ''}|${nextAxes ? JSON.stringify(nextAxes) : ''}`;\n if (fingerprint === lastFingerprint) return;\n lastFingerprint = fingerprint;\n snapshot = { axes: nextAxes, format: nextFormat };\n for (const cb of listeners) cb();\n };\n channel.on('globalsUpdated', onGlobals);\n channel.on('updateGlobals', onGlobals);\n channel.on('setGlobals', onGlobals);\n}\n\n/**\n * Subscribe at module load so the `SET_GLOBALS` emission from preview init\n * lands in our snapshot before any block renders. Running `useSyncExternalStore`'s\n * `subscribe` lazily on first hook call would miss the event in most cases.\n */\nensureSubscribed();\n\nfunction subscribe(cb: () => void): () => void {\n ensureSubscribed();\n listeners.add(cb);\n return () => {\n listeners.delete(cb);\n };\n}\n\nfunction getSnapshot(): ChannelGlobals {\n return snapshot;\n}\n\nfunction getServerSnapshot(): ChannelGlobals {\n return snapshot;\n}\n\nexport function useChannelGlobals(): ChannelGlobals {\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n","import type { Axis, AxisVarianceResult, Diagnostic, Preset } from '@unpunnyfuns/swatchbook-core';\nimport type { SlimListedToken } from '@unpunnyfuns/swatchbook-core/snapshot-for-wire';\nimport { createContext, useContext } from 'react';\nimport { useChannelGlobals } from '#/internal/channel-globals.ts';\nimport type { ColorFormat } from '#/format-color.ts';\n\n/**\n * Typed shape of the addon's `virtual:swatchbook/tokens` module.\n *\n * The axis / permutation / diagnostic / preset entries are deliberate\n * type-aliases of core's authoritative shapes — the virtual module\n * publishes those shapes verbatim, so single-sourcing the types prevents\n * silent drift the moment core grows a field the plugin doesn't\n * serialise.\n *\n * Token / listing shapes stay as narrowed interfaces because blocks\n * only read a subset of Terrazzo's full token / listing structure; the\n * narrower shape documents what's actually relied on.\n *\n * The ambient `declare module 'virtual:swatchbook/tokens'` declarations\n * in `packages/addon/src/virtual.d.ts` describe the same payload.\n */\nexport type VirtualAxisShape = Axis;\n\nexport type VirtualDiagnosticShape = Diagnostic;\n\nexport interface VirtualTokenShape {\n $type?: string | undefined;\n $value?: unknown;\n $description?: string | undefined;\n aliasOf?: string | undefined;\n aliasChain?: readonly string[] | undefined;\n aliasedBy?: readonly string[] | undefined;\n /**\n * Per-sub-field alias map for composite tokens whose value blends\n * primitives with aliased fragments — Terrazzo populates this when\n * one or more component fields of a composite ($type: 'border',\n * 'shadow', 'typography', 'gradient', 'transition') resolve through\n * an alias. The `CompositeBreakdown` block reads it to render the\n * source path beside each component value. Typed as `unknown` because\n * the shape varies per composite type (color carries a\n * `{components: (string | undefined)[]}` sub-shape; typography/border\n * carry a flat `Record<string, string | undefined>`); the block\n * narrows it at the consumer.\n */\n partialAliasOf?: unknown;\n}\n\n/**\n * Subset of `@terrazzo/plugin-token-listing`'s `ListedToken` that the\n * snapshot carries. Blocks read `names.css` for the authoritative CSS\n * variable name and `previewValue` for the display-ready CSS string.\n * `source.loc` enables \"jump to authoring source\" affordances.\n *\n * Aliases `SlimListedToken` from core's `/snapshot-for-wire` subpath —\n * the single canonical wire shape; both the addon's plugin (server-side\n * emit) and blocks (consumer-side read) reference the same definition.\n */\nexport type VirtualTokenListingShape = SlimListedToken;\n\nexport type VirtualPresetShape = Preset;\n\n/**\n * Wire shape of one `Project.jointOverrides` entry — same as core's\n * `JointOverride` but with the block's `VirtualTokenShape` for the\n * token values that ship over the wire.\n */\nexport interface VirtualJointOverrideShape {\n axes: Record<string, string>;\n tokens: Record<string, VirtualTokenShape>;\n}\n\n/**\n * Map from path → cached `AxisVarianceResult`. Snapshot carries this\n * so the `AxisVariance` block can O(1) look up which axes affect a\n * token instead of re-running variance analysis on every render.\n */\nexport type VirtualVarianceByPathShape = Record<string, AxisVarianceResult>;\n\n/**\n * Full project data read by blocks. Populated by the addon's preview\n * decorator (from the virtual module) or constructed by hand in\n * non-Storybook consumers.\n */\nexport interface ProjectSnapshot {\n axes: readonly VirtualAxisShape[];\n /** Axis names suppressed via `config.disabledAxes` — pinned to their defaults, hidden from the toolbar. */\n disabledAxes: readonly string[];\n presets: readonly VirtualPresetShape[];\n activeTheme: string;\n activeAxes: Readonly<Record<string, string>>;\n cssVarPrefix: string;\n diagnostics: readonly VirtualDiagnosticShape[];\n css: string;\n /**\n * Path-indexed Token Listing data produced by\n * `@terrazzo/plugin-token-listing`. Blocks prefer reading authoritative\n * CSS var names and preview values from here; empty for non-resolver\n * projects. Treat as enrichment — fall back gracefully when a path is\n * absent.\n */\n listing?: Readonly<Record<string, VirtualTokenListingShape>>;\n /**\n * Per-axis cell maps — `cells[axis][context]` is the resolved token\n * data for `{ ...defaults, [axis]: context }`. Bounded by\n * `Σ(axes × contexts)` regardless of cartesian product size.\n * Non-default cells store only the tokens whose value differs from\n * the default-cell baseline (delta cells).\n */\n cells: Record<string, Record<string, Record<string, VirtualTokenShape>>>;\n /**\n * `Project.jointOverrides` flattened to entries for wire transport.\n * Same ascending-arity iteration order the Map carries on the\n * server side. Empty array when no joint divergences exist.\n */\n jointOverrides: readonly (readonly [string, VirtualJointOverrideShape])[];\n /**\n * Cached per-path variance results. Blocks read this for O(1) axis\n * variance lookup instead of recomputing on each render.\n */\n varianceByPath?: VirtualVarianceByPathShape;\n /** The default tuple — `{ axis: axis.default }` for every axis. */\n defaultTuple: Record<string, string>;\n /**\n * Pre-built `resolveAt(tuple)` accessor. The addon's preview\n * decorator instantiates this once per iframe lifetime — the\n * underlying virtual-module exports (cells, jointOverrides, axes,\n * defaultTuple) are stable, so a single resolver instance with\n * internal per-tuple memoization is correct and avoids the\n * per-render rebuild dance the blocks side used to do. Hand-built\n * snapshots (tests, MDX) can omit this; blocks fall back to\n * building locally from `cells` / `permutationsResolved`.\n */\n resolveAt?: (tuple: Record<string, string>) => Record<string, VirtualTokenShape>;\n}\n\n/**\n * Context carrying the full {@link ProjectSnapshot}. `null` sentinel lets\n * `useSwatchbookData()` tell \"provider present\" from \"fall back to the\n * virtual module\".\n */\nexport const SwatchbookContext = createContext<ProjectSnapshot | null>(null);\n\nexport function useOptionalSwatchbookData(): ProjectSnapshot | null {\n return useContext(SwatchbookContext);\n}\n\n/**\n * Active swatchbook theme for the current story/docs render. Populated by\n * the addon's preview decorator and consumed by `useToken` + any future\n * consumer hooks.\n *\n * This runs through plain React context rather than Storybook's\n * `useGlobals` so the same hook works in autodocs / MDX renders where the\n * preview-hooks context isn't available.\n */\nexport const ThemeContext = createContext<string>('');\n\nexport function useActiveTheme(): string {\n return useContext(ThemeContext);\n}\n\n/**\n * Active axis tuple for the current story/docs render — `Record<axisName,\n * contextName>`. Derived from the same input as {@link ThemeContext}; split\n * out so consumers needing per-axis info (toolbar, panel, tuple-aware\n * blocks) don't have to reparse the composed permutation ID.\n */\nexport const AxesContext = createContext<Readonly<Record<string, string>>>({});\n\nexport function useActiveAxes(): Readonly<Record<string, string>> {\n return useContext(AxesContext);\n}\n\n/**\n * Active color-display format for the current story/docs render. Populated\n * by the addon's preview decorator from the `swatchbookColorFormat` global\n * (per-story `globals` or toolbar dropdown) and consumed by blocks that\n * render color-token values. Emitted CSS is unaffected.\n *\n * Runs through plain React context rather than Storybook's `useGlobals` so\n * per-story seeded globals flow through on first render and the same hook\n * is safe to call from MDX doc blocks (where the preview-hooks context\n * isn't available).\n */\nexport const ColorFormatContext = createContext<ColorFormat | null>(null);\n\nexport function useColorFormat(): ColorFormat {\n const contextValue = useContext(ColorFormatContext);\n const channelGlobals = useChannelGlobals();\n return contextValue ?? channelGlobals.format ?? 'hex';\n}\n","import { useSyncExternalStore } from 'react';\nimport { addons } from 'storybook/preview-api';\nimport {\n axes as initialAxes,\n cells as initialCells,\n css as initialCss,\n cssVarPrefix as initialCssVarPrefix,\n defaultTuple as initialDefaultTuple,\n diagnostics as initialDiagnostics,\n jointOverrides as initialJointOverrides,\n listing as initialListing,\n presets as initialPresets,\n varianceByPath as initialVarianceByPath,\n} from 'virtual:swatchbook/tokens';\nimport type {\n VirtualJointOverrideShape,\n VirtualTokenListingShape,\n VirtualVarianceByPathShape,\n} from '#/contexts.ts';\nimport type { VirtualAxis, VirtualDiagnostic, VirtualToken } from '#/types.ts';\n\n/**\n * Live token snapshot backed by the addon's preview dev-time HMR event.\n *\n * Blocks read the virtual module at module load; without a way to notice\n * changes, edits to the source token files would flow into the addon's\n * in-memory project but nowhere else — the React tree would keep\n * rendering the old values until a full preview reload. This module\n * subscribes to `TOKENS_UPDATED_EVENT` on Storybook's channel (which the\n * addon preview re-broadcasts from its own HMR listener) and exposes\n * the latest snapshot via `useSyncExternalStore`, so hooks that read\n * through this module re-render in place on each token save.\n *\n * Outside the preview iframe (the docs-site path, unit tests) the\n * channel never receives anything, and consumers keep seeing the\n * initial values baked into the virtual module at build time.\n */\n\nconst TOKENS_UPDATED_EVENT = 'swatchbook/tokens-updated';\n\nexport interface TokenSnapshot {\n readonly axes: readonly VirtualAxis[];\n readonly presets: readonly {\n name: string;\n axes: Partial<Record<string, string>>;\n description?: string;\n }[];\n readonly diagnostics: readonly VirtualDiagnostic[];\n readonly css: string;\n readonly cssVarPrefix: string;\n readonly listing: Readonly<Record<string, VirtualTokenListingShape>>;\n readonly cells: Record<string, Record<string, Record<string, VirtualToken>>>;\n readonly jointOverrides: readonly (readonly [string, VirtualJointOverrideShape])[];\n readonly varianceByPath: VirtualVarianceByPathShape;\n readonly defaultTuple: Record<string, string>;\n /** Monotonic counter, bumped on each update. Useful as a React key. */\n readonly version: number;\n}\n\nlet snapshot: TokenSnapshot = {\n axes: initialAxes,\n presets: initialPresets,\n diagnostics: initialDiagnostics,\n css: initialCss,\n cssVarPrefix: initialCssVarPrefix,\n listing: initialListing ?? {},\n cells: initialCells ?? {},\n jointOverrides: initialJointOverrides ?? [],\n varianceByPath: initialVarianceByPath ?? {},\n defaultTuple: initialDefaultTuple ?? {},\n version: 0,\n};\n\nconst listeners = new Set<() => void>();\nlet subscribed = false;\n\nfunction ensureSubscribed(): void {\n if (subscribed || typeof window === 'undefined') return;\n subscribed = true;\n const channel = addons.getChannel();\n channel.on(TOKENS_UPDATED_EVENT, (payload: Partial<TokenSnapshot>) => {\n snapshot = {\n axes: payload.axes ?? snapshot.axes,\n presets: payload.presets ?? snapshot.presets,\n diagnostics: payload.diagnostics ?? snapshot.diagnostics,\n css: payload.css ?? snapshot.css,\n cssVarPrefix: payload.cssVarPrefix ?? snapshot.cssVarPrefix,\n listing: payload.listing ?? snapshot.listing,\n cells: payload.cells ?? snapshot.cells,\n jointOverrides: payload.jointOverrides ?? snapshot.jointOverrides,\n varianceByPath: payload.varianceByPath ?? snapshot.varianceByPath,\n defaultTuple: payload.defaultTuple ?? snapshot.defaultTuple,\n version: snapshot.version + 1,\n };\n for (const cb of listeners) cb();\n });\n}\n\nensureSubscribed();\n\nfunction subscribe(cb: () => void): () => void {\n ensureSubscribed();\n listeners.add(cb);\n return () => {\n listeners.delete(cb);\n };\n}\n\nfunction getSnapshot(): TokenSnapshot {\n return snapshot;\n}\n\nexport function useTokenSnapshot(): TokenSnapshot {\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n","import { buildResolveAt } from '@unpunnyfuns/swatchbook-core/resolve-at';\nimport { makeCssVar } from '@unpunnyfuns/swatchbook-core/css-var';\nimport {\n ensureStyleElement,\n SWATCHBOOK_STYLE_ELEMENT_ID,\n} from '@unpunnyfuns/swatchbook-core/style-element';\nimport { tupleToName } from '@unpunnyfuns/swatchbook-core/themes';\nimport type { Axis, Cells, JointOverrides } from '@unpunnyfuns/swatchbook-core';\nimport { useEffect, useMemo } from 'react';\nimport type { VirtualTokenListingShape, VirtualVarianceByPathShape } from '#/contexts.ts';\nimport { useActiveAxes, useActiveTheme, useOptionalSwatchbookData } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat, FormatColorResult } from '#/format-color.ts';\nimport { useChannelGlobals } from '#/internal/channel-globals.ts';\nimport { useTokenSnapshot } from '#/internal/channel-tokens.ts';\nimport type { ProjectSnapshot, VirtualAxis, VirtualDiagnostic, VirtualToken } from '#/types.ts';\n\ntype ResolvedTokens = Record<string, VirtualToken>;\n\nexport interface ProjectData {\n activeTheme: string;\n activeAxes: Record<string, string>;\n axes: readonly VirtualAxis[];\n resolved: ResolvedTokens;\n diagnostics: readonly VirtualDiagnostic[];\n cssVarPrefix: string;\n /**\n * Path-indexed Token Listing data. Empty when absent (non-resolver\n * projects, hand-built snapshots that don't populate it). Blocks read\n * authoritative CSS var names from `listing[path].names.css` and\n * preview strings from `listing[path].previewValue`.\n */\n listing: Readonly<Record<string, VirtualTokenListingShape>>;\n /**\n * Cached per-path `AxisVarianceResult` — blocks use this for O(1)\n * variance lookup instead of re-running the analysis on every\n * render.\n */\n varianceByPath: VirtualVarianceByPathShape;\n /**\n * Compose the resolved `TokenMap` for any tuple of axis selections.\n * Built browser-side from `cells + jointOverrides` shipped over the\n * wire — no resolver needed.\n */\n resolveAt: (tuple: Record<string, string>) => ResolvedTokens;\n}\n\nfunction ensureStylesheet(css: string): void {\n ensureStyleElement(SWATCHBOOK_STYLE_ELEMENT_ID, css);\n}\n\nfunction defaultTuple(axes: readonly VirtualAxis[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const axis of axes) out[axis.name] = axis.default;\n return out;\n}\n\n/**\n * Reconstruct a `resolveAt` accessor from snapshot data. Both `cells`\n * and `jointOverrides` ship as plain JSON in the same shape core uses\n * internally — no Map reconstruction at the boundary. Stable identity\n * across calls with the same snapshot — `useMemo` keyed on the\n * snapshot fields produces a referentially stable function.\n */\nfunction makeResolveAt(snapshot: {\n axes: readonly VirtualAxis[];\n cells?: ProjectSnapshot['cells'];\n jointOverrides?: ProjectSnapshot['jointOverrides'];\n defaultTuple?: ProjectSnapshot['defaultTuple'];\n}): (tuple: Record<string, string>) => ResolvedTokens {\n const cells = (snapshot.cells ?? {}) as Cells;\n const jointOverrides = (snapshot.jointOverrides ?? []) as JointOverrides;\n const defaults = snapshot.defaultTuple ?? defaultTuple(snapshot.axes);\n const resolver = buildResolveAt(\n snapshot.axes as readonly Axis[],\n cells,\n jointOverrides,\n defaults,\n );\n return (tuple) => resolver(tuple);\n}\n\n/**\n * Build the `resolveAt` accessor for a snapshot. Prefers the\n * snapshot's own `resolveAt` (the addon's preview decorator\n * pre-builds one at module load — see `previewResolveAt` in\n * `packages/addon/src/preview.tsx`), otherwise composes one from\n * `cells` + `jointOverrides` via `makeResolveAt`. Hand-built\n * snapshots should provide both via the test `withCellsShape`\n * helper or by populating the fields directly.\n */\nfunction snapshotResolveAt(\n snapshot: ProjectSnapshot,\n): (tuple: Record<string, string>) => ResolvedTokens {\n if (snapshot.resolveAt)\n return snapshot.resolveAt as (tuple: Record<string, string>) => ResolvedTokens;\n return makeResolveAt(snapshot);\n}\n\n/**\n * Reads project data either from a mounted {@link SwatchbookProvider}\n * (preferred — the addon's preview decorator installs one around every\n * story) or, when no provider is present, from the virtual module plus\n * Storybook globals directly.\n *\n * The provider-less path is what makes the hook safe to call from MDX\n * doc blocks and autodocs renders where no story is active. It\n * self-mounts the virtual module's per-theme CSS and tracks the active\n * tuple via the `globalsUpdated` channel event; {@link useGlobals} from\n * `storybook/preview-api` would throw outside a story render.\n */\nexport function useProject(): ProjectData {\n const snapshot = useOptionalSwatchbookData();\n // Memoize against the stable underlying fields, NOT the snapshot\n // wrapper. Storybook rebuilds `context.globals` identity on every\n // render → the preview's `tuple` useMemo invalidates → the\n // provider's snapshot useMemo rebuilds. Keying off `snapshot`\n // would mean `makeResolveAt` runs on every render, producing a\n // fresh closure with a fresh internal memo, so `resolved` would\n // have a new identity each render. Downstream block\n // `useMemo([resolved, …])` calls would recompute forever; the\n // `TokenNavigator`'s focus-repair `useEffect` (deps include the\n // recomputed `flatVisible`) would `setState` in an infinite loop.\n // The underlying `cells` / `jointOverrides` / `defaultTuple` /\n // `axes` references are stable module-level exports, so depending\n // on them directly keeps `resolveAt` (and the resolved map it\n // returns) referentially stable across renders.\n const axes = snapshot?.axes;\n const cells = snapshot?.cells;\n const jointOverrides = snapshot?.jointOverrides;\n const dataDefaultTuple = snapshot?.defaultTuple;\n const activeAxes = snapshot?.activeAxes;\n const activeTheme = snapshot?.activeTheme;\n const diagnostics = snapshot?.diagnostics;\n const cssVarPrefix = snapshot?.cssVarPrefix;\n const listing = snapshot?.listing;\n const varianceByPath = snapshot?.varianceByPath;\n const resolveAt = useMemo(() => {\n if (!snapshot) return null;\n return snapshotResolveAt(snapshot);\n // The deps below are deliberately the stable inner fields rather\n // than `snapshot` itself; see the long block comment above.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [axes, cells, jointOverrides, dataDefaultTuple, activeTheme]);\n // Memoize the returned ProjectData against the same stable inner\n // fields — without this, blocks `useMemo([project, …])` calls\n // invalidate every render (the function returns a fresh object\n // identity), defeating the per-block memoization that\n // `TokenNavigator` / `TokenTable` / `ColorPalette` rely on.\n const providerData = useMemo<ProjectData | null>(() => {\n if (!snapshot || !resolveAt || !axes || !activeAxes) return null;\n return {\n activeTheme: activeTheme ?? '',\n activeAxes: activeAxes as Record<string, string>,\n axes,\n resolved: resolveAt(activeAxes as Record<string, string>),\n diagnostics: diagnostics ?? [],\n cssVarPrefix: cssVarPrefix ?? '',\n listing: listing ?? {},\n varianceByPath: varianceByPath ?? {},\n resolveAt,\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n snapshot,\n resolveAt,\n axes,\n cells,\n jointOverrides,\n dataDefaultTuple,\n activeTheme,\n activeAxes,\n diagnostics,\n cssVarPrefix,\n listing,\n varianceByPath,\n ]);\n const fallback = useVirtualModuleFallback(snapshot === null);\n return providerData ?? fallback;\n}\n\nfunction useVirtualModuleFallback(enabled: boolean): ProjectData {\n const contextPermutation = useActiveTheme();\n const contextAxes = useActiveAxes();\n const channelGlobals = useChannelGlobals();\n /**\n * Subscribe to the live token snapshot rather than reading the virtual\n * module's module-level exports directly. Initial values come from\n * `virtual:swatchbook/tokens` at load time; subsequent dev-time edits\n * flow through the addon's HMR channel and update this snapshot in\n * place so blocks re-render without a full preview reload.\n */\n const tokens = useTokenSnapshot();\n\n useEffect(() => {\n if (!enabled) return;\n ensureStylesheet(tokens.css);\n }, [enabled, tokens.css]);\n\n // Memoize against the stable identities — `contextAxes` is a\n // useContext value that's stable across renders unless the\n // provider mutates; `channelGlobals.axes` updates on channel\n // events; `tokens.axes` is a stable virtual-module export.\n // Without this memo `activeAxes` would have fresh identity per\n // render and defeat downstream `useMemo([project, …])` calls.\n const activeAxes = useMemo<Record<string, string>>(() => {\n const hasContextAxes = Object.keys(contextAxes).length > 0;\n return hasContextAxes ? { ...contextAxes } : (channelGlobals.axes ?? defaultTuple(tokens.axes));\n }, [contextAxes, channelGlobals.axes, tokens.axes]);\n\n const activeTheme = contextPermutation || tupleToName(tokens.axes, activeAxes);\n\n // `buildResolveAt` returns a closure that memoizes on the canonical\n // tuple key, so wrapping the call in another `useMemo` would be\n // redundant — the inner memo handles the per-tuple cache. We only\n // need `useMemo` for the outer `resolveAt` itself so React's\n // reference equality stays stable between renders.\n const resolveAt = useMemo(\n () =>\n makeResolveAt({\n axes: tokens.axes,\n cells: tokens.cells,\n jointOverrides: tokens.jointOverrides,\n defaultTuple: tokens.defaultTuple,\n }),\n [tokens.axes, tokens.cells, tokens.jointOverrides, tokens.defaultTuple],\n );\n\n // Memoize the returned ProjectData against the stable inner fields\n // for the same reason the provider path does — fresh object identity\n // per render would defeat `useMemo([project, …])` in every block.\n return useMemo<ProjectData>(\n () => ({\n activeTheme,\n activeAxes,\n axes: tokens.axes,\n resolved: resolveAt(activeAxes),\n diagnostics: tokens.diagnostics,\n cssVarPrefix: tokens.cssVarPrefix,\n listing: tokens.listing,\n varianceByPath: tokens.varianceByPath,\n resolveAt,\n }),\n [\n activeTheme,\n activeAxes,\n tokens.axes,\n tokens.diagnostics,\n tokens.cssVarPrefix,\n tokens.listing,\n tokens.varianceByPath,\n resolveAt,\n ],\n );\n}\n\n/**\n * Resolve a token's CSS var reference, preferring the authoritative name\n * emitted by `@terrazzo/plugin-css` (as recorded by\n * `@terrazzo/plugin-token-listing` in the snapshot's `listing` field).\n * Falls back to `makeCssVar` when the listing lacks an entry for this\n * path — covers non-resolver projects, hand-built snapshots, and any\n * listing-plugin miss.\n */\nexport function resolveCssVar(path: string, project: ProjectData): string {\n const listed = project.listing[path]?.names?.['css'];\n if (listed) return `var(${listed})`;\n return makeCssVar(path, project.cssVarPrefix);\n}\n\n/**\n * Resolve a color value's display string + gamut flag, preferring the\n * listing's `previewValue` when the user's active color-format matches\n * plugin-css's output (hex). For any other format we fall back to\n * `formatColor` so the toolbar's inspection modes (rgb / hsl / oklch /\n * raw) keep working — the listing has only one canonical format.\n *\n * Pass `path === undefined` when resolving a sub-color inside a composite\n * (shadow / border / gradient stop): composites' `previewValue` covers\n * the whole token's rendering, not the individual channel, so there's no\n * listing entry to key against.\n */\nexport function resolveColorValue(\n path: string | undefined,\n raw: unknown,\n colorFormat: ColorFormat,\n project: ProjectData,\n): FormatColorResult {\n if (path !== undefined && colorFormat === 'hex') {\n const listed = project.listing[path]?.previewValue;\n if (typeof listed === 'string') {\n return { value: listed, outOfGamut: false };\n }\n }\n return formatColor(raw, colorFormat);\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { SURFACE_RAISED } from '#/internal/styles.tsx';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\n\nexport interface BorderSampleProps {\n /** Full dot-path of the border token to preview. */\n path: string;\n}\n\nconst sampleStyle: CSSProperties = {\n width: 120,\n height: 56,\n background: SURFACE_RAISED,\n borderRadius: 6,\n};\n\nexport function BorderSample({ path }: BorderSampleProps): ReactElement {\n const project = useProject();\n const cssVar = resolveCssVar(path, project);\n return <div style={{ ...sampleStyle, border: cssVar }} aria-hidden />;\n}\n","import { dataAttr } from '@unpunnyfuns/swatchbook-core/data-attr';\n\n/**\n * Marker attribute set on every block wrapper. Retained as a stable hook\n * for consumer-side selectors (e.g. when a host app wants to target or\n * override block chrome without relying on hashed class names).\n */\nexport const BLOCK_ATTR = 'data-swatchbook-block';\n\n/**\n * Opt-out class that Storybook's `.sbdocs` stylesheet uses to self-exclude\n * on MDX docs pages — every `.sbdocs` house rule is wrapped in\n * `:not(.sb-unstyled, .sb-unstyled *)`, so any descendant of a `.sb-unstyled`\n * container is left alone. Stamped onto every block wrapper so blocks\n * render identically in MDX docs and regular stories without fighting\n * cascade specificity.\n */\nconst WRAPPER_CLASSES = 'sb-unstyled sb-block';\n\n/**\n * Spread helper for the common block wrapper. Returns:\n * - One `data-<prefix>-<axisName>=\"<contextName>\"` per axis in the tuple.\n * These are what the smart CSS emitter actually targets — single-axis\n * cell selectors (`[data-<prefix>-mode=\"Dark\"]`) and joint compounds\n * (`[data-<prefix>-mode=\"Dark\"][data-<prefix>-brand=\"Brand A\"]`).\n * Wrapping a block subtree in these attrs lets the cascade resolve\n * per-tuple values inside the block independently of the document\n * root — `AxisVariance`'s grid uses this to render real per-cell\n * swatches.\n * - `data-swatchbook-block` — stable consumer hook for targeting block\n * chrome from outside.\n * - `className=\"sb-unstyled sb-block\"` — Storybook's opt-out class so\n * MDX docs house styles self-exclude the subtree, plus `sb-block`\n * which carries the shared chrome from `internal/styles.css`.\n */\nexport function themeAttrs(\n prefix: string,\n tuple: Readonly<Record<string, string>>,\n): Record<string, string> {\n return {\n ...perAxisAttrs(prefix, tuple),\n [BLOCK_ATTR]: '',\n className: WRAPPER_CLASSES,\n };\n}\n\n/**\n * Spread helper for any element that wants per-axis cell semantics\n * without the block-wrapper chrome — `AxisVariance`'s grid uses this\n * on each swatch so the swatch's CSS vars resolve at the cell's own\n * tuple, not the document root's active tuple.\n */\nexport function perAxisAttrs(\n prefix: string,\n tuple: Readonly<Record<string, string>>,\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [axisName, contextName] of Object.entries(tuple)) {\n out[dataAttr(prefix, axisName)] = contextName;\n }\n return out;\n}\n","import Color from 'colorjs.io';\nimport type { VirtualToken } from '#/types.ts';\n\nexport type SortBy = 'path' | 'value' | 'none';\nexport type SortDir = 'asc' | 'desc';\n\nexport interface SortOptions {\n by?: SortBy;\n dir?: SortDir;\n}\n\ntype Entry = readonly [string, VirtualToken];\n\n/**\n * Stable sort for a filtered `[path, token][]` list.\n *\n * `sortBy: 'path'` — lexicographic on the dot-path (locale-aware, numeric).\n * `sortBy: 'value'` — per-`$type` ordering:\n * - `dimension` / `duration` → numeric pixels / ms (via `toMagnitude`).\n * - `fontWeight` / `opacity` / `number` / `lineHeight` → numeric.\n * - `color` → perceptual by oklch L → C → H.\n * - `fontFamily` / `strokeStyle` (string form) → lexicographic.\n * - Composites (`typography`, `shadow`, `border`, `gradient`, `transition`) →\n * fall back to path-alpha. No useful single-axis order.\n * `sortBy: 'none'` — preserve input order (still respects `sortDir: 'desc'`\n * as a reverse).\n */\n/**\n * Pre-computed per-token sort key — one of three shapes depending on\n * `$type`. The comparator looks the key up by token-reference once\n * per pair instead of recomputing on every comparison (Schwartzian\n * transform).\n *\n * For N tokens, sort does O(N log N) comparisons; per-call cost for\n * colors was an Oklch conversion (a `new Color()` + `to('oklch')`)\n * which dominates wall time on real fixtures. Pre-computing brings\n * that down to O(N) keys + O(N log N) cheap lookups.\n */\ntype SortKey =\n | { kind: 'numeric'; value: number; valid: boolean }\n | { kind: 'color'; key: { l: number; c: number; h: number } | null }\n | { kind: 'string'; value: string }\n | { kind: 'none' };\n\nconst NUMERIC_TYPES = new Set([\n 'dimension',\n 'duration',\n 'fontWeight',\n 'opacity',\n 'number',\n 'lineHeight',\n]);\n\nconst STRING_TYPES = new Set(['fontFamily', 'strokeStyle']);\n\nfunction computeSortKey(token: VirtualToken): SortKey {\n const type = token.$type;\n if (!type) return { kind: 'none' };\n if (NUMERIC_TYPES.has(type)) {\n const value = toMagnitude(token.$value);\n return { kind: 'numeric', value, valid: Number.isFinite(value) };\n }\n if (type === 'color') {\n return { kind: 'color', key: colorKey(token.$value) };\n }\n if (STRING_TYPES.has(type)) {\n return { kind: 'string', value: toDisplayable(token.$value) };\n }\n // Composite types ($type: 'typography', 'shadow', 'border', …) have\n // no useful one-dimensional ordering — fall back to no-op.\n return { kind: 'none' };\n}\n\nexport function sortTokens(entries: readonly Entry[], options: SortOptions = {}): Entry[] {\n const by = options.by ?? 'path';\n const dir = options.dir ?? 'asc';\n const sign = dir === 'desc' ? -1 : 1;\n\n if (by === 'none') {\n return dir === 'desc' ? [...entries].toReversed() : [...entries];\n }\n\n if (by === 'path') {\n return [...entries].toSorted(\n ([a], [b]) => sign * a.localeCompare(b, undefined, { numeric: true }),\n );\n }\n\n // by === 'value' — pre-compute per-token sort keys once.\n const keys = new Map<VirtualToken, SortKey>();\n for (const [, token] of entries) {\n keys.set(token, computeSortKey(token));\n }\n\n return [...entries].toSorted(([aPath, aTok], [bPath, bTok]) => {\n const cmp = compareValue(aTok, bTok, keys);\n if (cmp !== 0) return sign * cmp;\n // Stable tiebreak on path so the order is deterministic when values equal.\n return sign * aPath.localeCompare(bPath, undefined, { numeric: true });\n });\n}\n\nfunction compareValue(\n a: VirtualToken,\n b: VirtualToken,\n keys: ReadonlyMap<VirtualToken, SortKey>,\n): number {\n // When the two tokens differ in $type, fall back to type-alpha so at\n // least the mixed list clusters by type.\n if (a.$type !== b.$type) return String(a.$type ?? '').localeCompare(String(b.$type ?? ''));\n\n const ak = keys.get(a);\n const bk = keys.get(b);\n if (!ak || !bk) return 0;\n // Matches the `a.$type === b.$type` check above.\n if (ak.kind !== bk.kind) return 0;\n\n if (ak.kind === 'numeric' && bk.kind === 'numeric') {\n if (ak.valid && bk.valid) return ak.value - bk.value;\n if (ak.valid) return -1;\n if (bk.valid) return 1;\n return 0;\n }\n\n if (ak.kind === 'color' && bk.kind === 'color') {\n const a3 = ak.key;\n const b3 = bk.key;\n if (!a3 && !b3) return 0;\n if (!a3) return 1;\n if (!b3) return -1;\n if (a3.l !== b3.l) return a3.l - b3.l;\n if (a3.c !== b3.c) return a3.c - b3.c;\n return a3.h - b3.h;\n }\n\n if (ak.kind === 'string' && bk.kind === 'string') {\n return ak.value.localeCompare(bk.value, undefined, { numeric: true });\n }\n\n return 0;\n}\n\nfunction toMagnitude(v: unknown): number {\n if (typeof v === 'number') return v;\n if (v && typeof v === 'object') {\n const d = v as { value?: unknown; unit?: unknown };\n if (typeof d.value !== 'number') return Number.NaN;\n if (typeof d.unit !== 'string') return d.value;\n switch (d.unit) {\n case 'px':\n case 'ms':\n return d.value;\n case 's':\n return d.value * 1000;\n case 'rem':\n case 'em':\n return d.value * 16;\n default:\n return d.value;\n }\n }\n return Number.NaN;\n}\n\n/**\n * Coerce a possibly-null/undefined number to 0 — `coords` returns\n * `(number | null)[]` and `noUncheckedIndexedAccess` adds `undefined`\n * on top. `typeof` narrows the union for the comparator below.\n */\nfunction safeNumber(v: number | null | undefined): number {\n return typeof v === 'number' && Number.isFinite(v) ? v : 0;\n}\n\nfunction colorKey(v: unknown): { l: number; c: number; h: number } | null {\n if (!v || typeof v !== 'object') return null;\n try {\n const c = v as {\n colorSpace?: unknown;\n components?: unknown;\n channels?: unknown;\n hex?: unknown;\n };\n let source: unknown;\n if (typeof c.hex === 'string') source = c.hex;\n else if (typeof c.colorSpace === 'string') {\n const channels = Array.isArray(c.components)\n ? c.components\n : Array.isArray(c.channels)\n ? c.channels\n : undefined;\n if (!channels) return null;\n source = { space: c.colorSpace, coords: channels };\n } else return null;\n // Color.js's constructor signature is a string or PlainColorObject —\n // we've already narrowed `source` to one of those shapes above, but\n // the union ends up broader than Color.js's typed surface.\n const color = new Color(source as string);\n const [l, chroma, h] = color.to('oklch').coords;\n return { l: safeNumber(l), c: safeNumber(chroma), h: safeNumber(h) };\n } catch {\n return null;\n }\n}\n\nfunction toDisplayable(v: unknown): string {\n if (typeof v === 'string') return v;\n if (Array.isArray(v)) return v.map(String).join(', ');\n if (v && typeof v === 'object') return JSON.stringify(v);\n return String(v ?? '');\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './BorderPreview.css';\nimport { BorderSample } from '#/border-preview/BorderSample.tsx';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat } from '#/format-color.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface BorderPreviewProps {\n /**\n * Token-path filter. Defaults to every `border` token. Use e.g.\n * `\"border.*\"` to scope to the semantic layer.\n */\n filter?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` falls through to path (borders don't have a\n * single-axis ordering); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface BorderValue {\n color?: unknown;\n width?: unknown;\n style?: unknown;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n value: BorderValue;\n}\n\nfunction formatDimension(raw: unknown): string {\n if (raw == null) return '—';\n if (typeof raw === 'number') return String(raw);\n if (typeof raw === 'string') return raw;\n if (typeof raw === 'object') {\n const v = raw as { value?: unknown; unit?: unknown };\n if (typeof v.value === 'number' && typeof v.unit === 'string') {\n return `${v.value}${v.unit}`;\n }\n }\n return JSON.stringify(raw);\n}\n\nfunction formatSubColor(raw: unknown, format: ColorFormat): string {\n if (raw == null) return '—';\n return formatColor(raw, format).value;\n}\n\nexport function BorderPreview({\n filter,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: BorderPreviewProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'border') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n value: (token.$value ?? {}) as BorderValue,\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} border${rows.length === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No border tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-border-preview__row\">\n <div className=\"sb-border-preview__meta\">\n <span className=\"sb-border-preview__path\">{row.path}</span>\n <span className=\"sb-border-preview__css-var\">{row.cssVar}</span>\n </div>\n <div className=\"sb-border-preview__sample-cell\">\n <BorderSample path={row.path} />\n </div>\n <div className=\"sb-border-preview__breakdown\">\n <span className=\"sb-border-preview__breakdown-key\">width</span>\n <span>{formatDimension(row.value.width)}</span>\n <span className=\"sb-border-preview__breakdown-key\">style</span>\n <span>{row.value.style != null ? String(row.value.style) : '—'}</span>\n <span className=\"sb-border-preview__breakdown-key\">color</span>\n <span>{formatSubColor(row.value.color, colorFormat)}</span>\n </div>\n </div>\n ))}\n </div>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './ColorPalette.css';\nimport { useColorFormat } from '#/contexts.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveColorValue, resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface ColorPaletteProps {\n /**\n * Token-path filter. Defaults to every `color` token. Use e.g.\n * `\"color.*\"` to scope to the semantic layer, or `\"color.palette.blue.*\"`\n * for a single ref ramp.\n */\n filter?: string;\n /**\n * Grouping depth. Tokens are grouped by the first `groupBy` dot-segments\n * of their path. `1` yields a single `color` group; `2` yields\n * `color.surface`, `color.text`, `color.blue`, etc.\n *\n * If omitted, groupBy is derived from the filter: one level below the\n * filter's fixed prefix (segments before the first `*`), clamped so each\n * swatch still carries a leaf label. `\"color.*\"` → groups at\n * `color.<family>`; `\"color.palette.blue.*\"` collapses all shades into\n * one `color.blue` group because the tokens have no deeper level.\n */\n groupBy?: number;\n /** Override the section caption. */\n caption?: string;\n /**\n * Sort order within each group.\n * - `'path'` (default) — lexicographic on the dot-path.\n * - `'value'` — perceptual ordering: oklch L → C → H (ramps read\n * light→dark, then warm→cool within each lightness band).\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface Swatch {\n path: string;\n leaf: string;\n cssVar: string;\n value: string;\n outOfGamut: boolean;\n}\n\n/**\n * Count segments in the filter before the first glob (`*` / `**`).\n * `color.*` → 2; `color.surface.*` → 3; `color` → 1; undefined → 0.\n */\nfunction fixedPrefixLength(filter: string | undefined): number {\n if (!filter) return 0;\n const segments = filter.split('.');\n let fixed = 0;\n for (const seg of segments) {\n if (seg === '*' || seg === '**') break;\n fixed += 1;\n }\n return fixed;\n}\n\nexport function ColorPalette({\n filter,\n groupBy,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: ColorPaletteProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n\n const groups = useMemo(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'color') return false;\n return matchPath(path, filter);\n });\n const entries = sortTokens(filtered, { by: sortBy, dir: sortDir });\n\n const maxDepth = entries.reduce((m, [p]) => Math.max(m, p.split('.').length), 0);\n const effectiveGroupBy =\n groupBy ?? Math.min(fixedPrefixLength(filter) + 1, Math.max(maxDepth - 1, 1));\n\n const bucket = new Map<string, Swatch[]>();\n for (const [path, token] of entries) {\n const segments = path.split('.');\n const groupKey = segments.slice(0, effectiveGroupBy).join('.');\n const leaf = segments.slice(effectiveGroupBy).join('.') || segments.at(-1) || path;\n const list = bucket.get(groupKey) ?? [];\n const formatted = resolveColorValue(path, token.$value, colorFormat, project);\n list.push({\n path,\n leaf,\n cssVar: resolveCssVar(path, project),\n value: formatted.value,\n outOfGamut: formatted.outOfGamut,\n });\n bucket.set(groupKey, list);\n }\n\n return [...bucket.entries()].toSorted(([a], [b]) =>\n a.localeCompare(b, undefined, { numeric: true }),\n );\n }, [resolved, filter, groupBy, project, colorFormat, sortBy, sortDir]);\n\n const totalCount = groups.reduce((acc, [, swatches]) => acc + swatches.length, 0);\n const captionText =\n caption ??\n `${totalCount} color${totalCount === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (totalCount === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No color tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {groups.map(([group, swatches]) => (\n <section key={group} className=\"sb-color-palette__group\">\n <div className=\"sb-color-palette__group-header\">{group}</div>\n <div className=\"sb-color-palette__grid\">\n {swatches.map((swatch) => (\n <div key={swatch.path} className=\"sb-color-palette__card\">\n <div\n className=\"sb-color-palette__swatch\"\n style={{ background: swatch.cssVar }}\n aria-hidden\n />\n <div className=\"sb-color-palette__meta\">\n <span className=\"sb-color-palette__leaf\">{swatch.leaf}</span>\n <span className=\"sb-color-palette__value\">\n {swatch.value}\n {swatch.outOfGamut && (\n <span\n title=\"Out of sRGB gamut for this format\"\n aria-label=\"out of gamut\"\n className=\"sb-color-palette__gamut-warn\"\n >\n {' '}\n ⚠\n </span>\n )}\n </span>\n </div>\n </div>\n ))}\n </div>\n </section>\n ))}\n </div>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport './CopyButton.css';\n\nexport interface CopyButtonProps {\n /** Text written to the clipboard when clicked. */\n value: string;\n /**\n * Accessible label. Defaults to `Copy <value>`; override for long values\n * (hex + description + etc.) where the full label would be too chatty.\n */\n label?: string;\n /** `'icon'` (default) — 16 px glyph button; `'text'` — `Copy` pill. */\n variant?: 'icon' | 'text';\n /** Extra class to merge onto the button root. */\n className?: string;\n}\n\n/**\n * Copy the given string to the clipboard and briefly surface a \"Copied!\"\n * state. Falls back silently on unsupported clipboard APIs (older Safari,\n * insecure origins) — the click still happens, the user just won't see the\n * tick. No custom permission prompt: relies on the browser's native user-\n * activation gate.\n */\nexport function CopyButton({\n value,\n label,\n variant = 'icon',\n className,\n}: CopyButtonProps): ReactElement {\n const [copied, setCopied] = useState(false);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n return () => {\n if (timerRef.current !== null) clearTimeout(timerRef.current);\n };\n }, []);\n\n const handleClick = useCallback((): void => {\n // `writeText` is async and rejects on unfocused documents,\n // insecure origins, missing permissions, etc. Swallow the\n // rejection — the \"Copied!\" affordance is a nicety, not a\n // correctness requirement; an unhandled rejection in prod would\n // surface in DevTools and (under vitest browser-mode) fail the\n // suite from an unrelated test.\n navigator.clipboard?.writeText(value).catch(() => {});\n setCopied(true);\n if (timerRef.current !== null) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => setCopied(false), 1500);\n }, [value]);\n\n const ariaLabel = label ?? `Copy ${value}`;\n const classes = ['sb-copy-button', `sb-copy-button--${variant}`];\n if (copied) classes.push('sb-copy-button--copied');\n if (className) classes.push(className);\n\n return (\n <>\n <button\n type=\"button\"\n className={classes.join(' ')}\n onClick={handleClick}\n aria-label={ariaLabel}\n title={ariaLabel}\n data-copied={copied ? 'true' : undefined}\n >\n {variant === 'text' ? (\n <span className=\"sb-copy-button__text\">{copied ? 'Copied' : 'Copy'}</span>\n ) : (\n <span className=\"sb-copy-button__glyph\" aria-hidden>\n {copied ? '✓' : '⧉'}\n </span>\n )}\n </button>\n {/* Polite live region announces the transition to SR users — the\n icon variant's \"✓ Copied\" cue is otherwise visual-only. */}\n <span role=\"status\" aria-live=\"polite\" className=\"sb-copy-button__sr-status\">\n {copied ? 'Copied' : ''}\n </span>\n </>\n );\n}\n","import { fuzzyFilter } from '@unpunnyfuns/swatchbook-core/fuzzy';\nimport cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport { useCallback, useMemo, useState } from 'react';\nimport './ColorTable.css';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat, NormalizedColor } from '#/format-color.ts';\nimport { CopyButton } from '#/internal/CopyButton.tsx';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveColorValue, resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nconst BASE_LABEL = 'base';\nconst COLUMN_COUNT = 6;\n\nexport interface ColorTableProps {\n /**\n * Token-path filter. Defaults to every `$type: color` token. `\"color.*\"`\n * scopes to the semantic layer; `\"color.palette.blue.*\"` to a single ramp.\n */\n filter?: string;\n /** Override the table caption. */\n caption?: string;\n /**\n * Sort order.\n * - `'path'` (default) — lexicographic on the dot-path.\n * - `'value'` — perceptual (oklch L → C → H). Ramps read light→dark, then\n * warm→cool within each lightness band.\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n /**\n * Render a fuzzy-search input above the table. Defaults to `true`.\n */\n searchable?: boolean;\n /**\n * Called with the *currently-selected* variant's dot-path on row click.\n * When set, the built-in expand-in-place behavior is suppressed — the\n * consumer owns follow-up UI.\n */\n onSelect?(path: string): void;\n /**\n * Map from a display label to a suffix matched against each token's\n * trailing path segment. Tokens whose leaves match a suffix are grouped\n * under a shared \"base\" path (the path with the suffix stripped), and\n * the group renders as a single row with a pill selector — clicking a\n * pill swaps the displayed values to that variant. Sibling tokens\n * without a suffix that share the group's base path are labeled `base`.\n *\n * Matches both DTCG-idiomatic and Backmarket-style conventions:\n * - **Dot segment** (`color.bg.hi.disabled`): last dot-segment equals\n * the suffix (`disabled`). Base path = drop the last segment.\n * - **Hyphen tail** (`color.bg.hi-d`): last dot-segment ends in\n * `-<suffix>` (`d`). Base path = trim the `-<suffix>` from the leaf.\n *\n * Longest-suffix-wins. Hyphen-tail form requires an actual hyphen\n * boundary — suffix `0` does not match `neutral-900`.\n *\n * Single-member groups render as plain rows (no pill selector). Empty\n * map (default) disables grouping entirely; each token renders as its\n * own row, identical to the pre-grouping behavior.\n */\n variants?: Record<string, string>;\n}\n\ninterface Variant {\n label: string;\n path: string;\n cssVar: string;\n /** The display value in the currently-active color format. */\n value: string;\n outOfGamut: boolean;\n /** Hex / HSL / OKLCH breakdown — retained for the expanded sub-table. */\n hex: string;\n hsl: string;\n oklch: string;\n description?: string;\n aliasOf?: string;\n aliasChain?: readonly string[];\n}\n\ninterface Group {\n base: string;\n variants: Variant[];\n searchText: string;\n}\n\nexport function ColorTable({\n filter,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n searchable = true,\n onSelect,\n variants,\n}: ColorTableProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n const [query, setQuery] = useState('');\n const [selectedByBase, setSelectedByBase] = useState<Record<string, string>>({});\n const [expandedByBase, setExpandedByBase] = useState<ReadonlySet<string>>(() => new Set());\n\n const defs = useMemo(() => buildVariantDefs(variants), [variants]);\n\n const groups = useMemo<Group[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'color') return false;\n return matchPath(path, filter);\n });\n const sorted = sortTokens(filtered, { by: sortBy, dir: sortDir });\n\n const groupMap = new Map<string, { base: string; variants: Variant[] }>();\n for (const [path, token] of sorted) {\n const raw = token.$value as NormalizedColor;\n const hex = resolveColorValue(path, raw, 'hex', project);\n const hsl = formatColor(raw, 'hsl');\n const oklch = formatColor(raw, 'oklch');\n const active = pickActiveFormat(raw, colorFormat, hex, hsl, oklch);\n const match = matchVariant(path, defs.matchOrder);\n const variant: Variant = {\n label: match?.label ?? BASE_LABEL,\n path,\n cssVar: resolveCssVar(path, project),\n value: active.value,\n outOfGamut: active.outOfGamut,\n hex: hex.value,\n hsl: hsl.value,\n oklch: oklch.value,\n ...(token.$description !== undefined && { description: token.$description }),\n ...(token.aliasOf !== undefined && { aliasOf: token.aliasOf }),\n ...(token.aliasChain !== undefined && { aliasChain: token.aliasChain }),\n };\n const basePath = match?.basePath ?? path;\n const existing = groupMap.get(basePath);\n if (existing) existing.variants.push(variant);\n else groupMap.set(basePath, { base: basePath, variants: [variant] });\n }\n\n const out: Group[] = [];\n for (const { base, variants: vs } of groupMap.values()) {\n vs.sort((a, b) => orderIndex(a.label, defs) - orderIndex(b.label, defs));\n const searchText = vs.map((v) => `${v.path} ${v.value}`).join(' ');\n out.push({ base, variants: vs, searchText });\n }\n return out;\n }, [resolved, filter, project, sortBy, sortDir, defs, colorFormat]);\n\n const visibleGroups = useMemo(() => {\n if (!searchable || query.trim() === '') return groups;\n return fuzzyFilter(groups, query, (g) => g.searchText);\n }, [groups, query, searchable]);\n\n const totalTokens = useMemo(() => groups.reduce((n, g) => n + g.variants.length, 0), [groups]);\n\n const toggleExpand = useCallback((base: string) => {\n setExpandedByBase((prev) => {\n const next = new Set(prev);\n if (next.has(base)) next.delete(base);\n else next.add(base);\n return next;\n });\n }, []);\n\n const selectVariant = useCallback((base: string, label: string) => {\n setSelectedByBase((prev) => ({ ...prev, [base]: label }));\n }, []);\n\n const matchSuffix =\n searchable && query.trim() !== ''\n ? ` · ${visibleGroups.length} matching \"${query.trim()}\"`\n : '';\n const captionText =\n caption ??\n `${totalTokens} color${totalTokens === 1 ? '' : 's'} across ${groups.length} group${\n groups.length === 1 ? '' : 's'\n }${filter ? ` matching \\`${filter}\\`` : ''}${matchSuffix} · ${activeTheme}`;\n\n if (groups.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No color tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n {searchable && (\n <div className=\"sb-color-table__search\">\n <input\n type=\"search\"\n className=\"sb-color-table__search-input\"\n placeholder=\"Search colors…\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n aria-label=\"Fuzzy-search colors by path or value\"\n data-testid=\"color-table-search\"\n />\n </div>\n )}\n <div className=\"sb-color-table__scroll\">\n <table className=\"sb-color-table__table\">\n <caption className=\"sb-color-table__caption\">{captionText}</caption>\n <thead>\n <tr>\n <th className=\"sb-color-table__th sb-color-table__th--swatch\">\n <span className=\"sb-color-table__sr-only\">Swatch</span>\n </th>\n <th className=\"sb-color-table__th sb-color-table__th--path\">Name</th>\n <th className=\"sb-color-table__th\">Value</th>\n <th className=\"sb-color-table__th\">CSS var</th>\n <th className=\"sb-color-table__th\">Alias</th>\n <th className=\"sb-color-table__th sb-color-table__th--expand\">\n <span className=\"sb-color-table__sr-only\">Expand</span>\n </th>\n </tr>\n </thead>\n <tbody>\n {visibleGroups.length === 0 && (\n <tr>\n <td colSpan={COLUMN_COUNT} className=\"sb-color-table__td sb-color-table__empty-row\">\n No colors match \"{query.trim()}\".\n </td>\n </tr>\n )}\n {visibleGroups.map((group) => (\n <GroupRow\n key={group.base}\n group={group}\n selectedLabel={selectedByBase[group.base]}\n expanded={expandedByBase.has(group.base)}\n onToggleExpand={toggleExpand}\n onSelectVariant={selectVariant}\n {...(onSelect !== undefined && { onSelect })}\n />\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n\nfunction GroupRow({\n group,\n selectedLabel,\n expanded,\n onToggleExpand,\n onSelectVariant,\n onSelect,\n}: {\n group: Group;\n selectedLabel: string | undefined;\n expanded: boolean;\n onToggleExpand(base: string): void;\n onSelectVariant(base: string, label: string): void;\n onSelect?(path: string): void;\n}): ReactElement {\n const multi = group.variants.length > 1;\n const active =\n group.variants.find((v) => v.label === selectedLabel) ?? (group.variants[0] as Variant);\n const nameText = multi ? group.base : active.path;\n\n const handleRowActivate = (): void => {\n if (onSelect) onSelect(active.path);\n else onToggleExpand(group.base);\n };\n\n return (\n <>\n <tr\n className={cx('sb-color-table__row', {\n 'sb-color-table__row--expanded': expanded,\n })}\n onClick={handleRowActivate}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleRowActivate();\n }\n }}\n tabIndex={0}\n aria-label={\n onSelect\n ? `Inspect ${active.path}`\n : expanded\n ? `Collapse ${group.base}`\n : `Expand ${group.base}`\n }\n {...(onSelect ? { 'aria-haspopup': 'dialog' as const } : {})}\n data-testid=\"color-table-row\"\n data-path={active.path}\n data-base={group.base}\n >\n <td className=\"sb-color-table__td sb-color-table__swatch-cell\">\n <span\n className=\"sb-color-table__swatch\"\n style={{ background: active.cssVar }}\n aria-hidden\n />\n </td>\n <td className={cx('sb-color-table__td', 'sb-color-table__path')}>\n <span className=\"sb-color-table__path-text\">{nameText}</span>\n {multi && (\n <span\n className=\"sb-color-table__variant-pills\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n role=\"presentation\"\n >\n {group.variants.map((v) => (\n <button\n key={v.label}\n type=\"button\"\n className={cx('sb-color-table__variant-pill', {\n 'sb-color-table__variant-pill--active': v.label === active.label,\n })}\n onClick={() => onSelectVariant(group.base, v.label)}\n aria-pressed={v.label === active.label}\n data-testid=\"color-table-variant\"\n data-variant={v.label}\n >\n {v.label}\n </button>\n ))}\n </span>\n )}\n </td>\n <ValueCell value={active.value} label={`Copy value ${active.value}`}>\n {active.outOfGamut && (\n <span\n title=\"Out of sRGB gamut for this format\"\n aria-label=\"out of gamut\"\n className=\"sb-color-table__gamut-warn\"\n >\n ⚠\n </span>\n )}\n </ValueCell>\n <ValueCell value={active.cssVar} label={`Copy CSS var ${active.cssVar}`} />\n <td className=\"sb-color-table__td sb-color-table__alias\">\n {active.aliasOf ? (\n <span className=\"sb-color-table__alias-text\">{active.aliasOf}</span>\n ) : (\n <span className=\"sb-color-table__alias-empty\" aria-hidden>\n —\n </span>\n )}\n </td>\n <td className=\"sb-color-table__td sb-color-table__expand-cell\">\n {!onSelect && (\n <span\n className={cx('sb-color-table__chevron', {\n 'sb-color-table__chevron--expanded': expanded,\n })}\n aria-hidden\n >\n ▸\n </span>\n )}\n </td>\n </tr>\n {expanded && !onSelect && (\n <tr className=\"sb-color-table__detail-row\" data-testid=\"color-table-detail\">\n <td colSpan={COLUMN_COUNT} className=\"sb-color-table__td sb-color-table__detail-cell\">\n <ExpandedDetail group={group} active={active} />\n </td>\n </tr>\n )}\n </>\n );\n}\n\nfunction ExpandedDetail({ group, active }: { group: Group; active: Variant }): ReactElement {\n const hasDescription = active.description !== undefined && active.description.length > 0;\n const chain = active.aliasChain && active.aliasChain.length > 0 ? active.aliasChain : undefined;\n const multi = group.variants.length > 1;\n\n return (\n <div className=\"sb-color-table__detail\">\n {hasDescription && <p className=\"sb-color-table__description\">{active.description}</p>}\n {chain && (\n <p className=\"sb-color-table__chain\">\n <span className=\"sb-color-table__detail-label\">Alias chain:</span> {chain.join(' → ')}\n </p>\n )}\n {multi && (\n <div className=\"sb-color-table__variant-grid\">\n <div className=\"sb-color-table__variant-grid-header\">All variants</div>\n <table className=\"sb-color-table__subtable\">\n <thead>\n <tr>\n <th className=\"sb-color-table__subth\">Variant</th>\n <th className=\"sb-color-table__subth\">Path</th>\n <th className=\"sb-color-table__subth\">HEX</th>\n <th className=\"sb-color-table__subth\">HSL</th>\n <th className=\"sb-color-table__subth\">OKLCH</th>\n </tr>\n </thead>\n <tbody>\n {group.variants.map((v) => (\n <tr\n key={v.label}\n className={cx({\n 'sb-color-table__subrow--active': v.label === active.label,\n })}\n >\n <td className=\"sb-color-table__subtd\">{v.label}</td>\n <td className=\"sb-color-table__subtd sb-color-table__subtd--path\">{v.path}</td>\n <td className=\"sb-color-table__subtd\">{v.hex}</td>\n <td className=\"sb-color-table__subtd\">{v.hsl}</td>\n <td className=\"sb-color-table__subtd\">{v.oklch}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n {!hasDescription && !chain && !multi && (\n <p className=\"sb-color-table__detail-empty\">\n No description or alias chain authored for this token.\n </p>\n )}\n </div>\n );\n}\n\nfunction ValueCell({\n value,\n label,\n children,\n}: {\n value: string;\n label: string;\n children?: ReactElement | false;\n}): ReactElement {\n return (\n <td className=\"sb-color-table__td sb-color-table__value-cell\">\n <span className=\"sb-color-table__value-text\" title={value}>\n {value}\n </span>\n {children}\n <span\n className=\"sb-color-table__copy-wrap\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n role=\"presentation\"\n >\n <CopyButton value={value} label={label} className=\"sb-color-table__copy\" />\n </span>\n </td>\n );\n}\n\ntype FormatColorResult = ReturnType<typeof formatColor>;\n\n/**\n * Pick the value + gamut flag to display in the single Value column based\n * on the active color-format context. We pre-compute hex/hsl/oklch for the\n * expanded sub-table regardless; the extras (`rgb`, `raw`) take a fresh\n * `formatColor` pass. Keeps the hot path fast while staying honest about\n * out-of-gamut warnings per-format.\n */\nfunction pickActiveFormat(\n raw: NormalizedColor,\n colorFormat: ColorFormat,\n hex: FormatColorResult,\n hsl: FormatColorResult,\n oklch: FormatColorResult,\n): { value: string; outOfGamut: boolean } {\n switch (colorFormat) {\n case 'hex':\n return { value: hex.value, outOfGamut: hex.outOfGamut };\n case 'hsl':\n return { value: hsl.value, outOfGamut: hsl.outOfGamut };\n case 'oklch':\n return { value: oklch.value, outOfGamut: oklch.outOfGamut };\n default: {\n const extra = formatColor(raw, colorFormat);\n return { value: extra.value, outOfGamut: extra.outOfGamut };\n }\n }\n}\n\ninterface VariantEntry {\n label: string;\n suffix: string;\n}\n\ninterface VariantDefs {\n /** Match iteration order — longest suffix first. */\n matchOrder: readonly VariantEntry[];\n /** Display iteration order — preserves the caller's declared order. */\n displayOrder: readonly string[];\n}\n\nfunction buildVariantDefs(variants: Record<string, string> | undefined): VariantDefs {\n if (!variants) return { matchOrder: [], displayOrder: [] };\n const entries: VariantEntry[] = [];\n const displayOrder: string[] = [];\n for (const [label, suffix] of Object.entries(variants)) {\n if (suffix.length === 0) continue;\n entries.push({ label, suffix });\n displayOrder.push(label);\n }\n const matchOrder = entries.toSorted((a, b) => b.suffix.length - a.suffix.length);\n return { matchOrder, displayOrder };\n}\n\n/**\n * Position of a label within a group — the `base` entry always sorts first,\n * then declared labels in the order the caller wrote them in the `variants`\n * prop. Unknown labels (shouldn't happen in practice) fall to the end.\n */\nfunction orderIndex(label: string, defs: VariantDefs): number {\n if (label === BASE_LABEL) return -1;\n const idx = defs.displayOrder.indexOf(label);\n return idx >= 0 ? idx : Number.POSITIVE_INFINITY;\n}\n\n/**\n * Resolve the variant label + base path for a token, if any. The leaf\n * (last dot-segment) must either equal the suffix outright (dot-segment\n * form: `hi.disabled` matches suffix `disabled`) or end in `-<suffix>`\n * (hyphen-tail form: `hi-d` matches `d`). The leading hyphen is required\n * for the tail form so suffix `0` can't hit `neutral-900` by character.\n *\n * Returned `basePath` is what gets used as the grouping key:\n * - Dot-segment match → parent path (drop the last dot-segment)\n * - Hyphen-tail match → same dot-depth, leaf with `-<suffix>` stripped\n *\n * Entries in `matchOrder` are pre-sorted longest-first, so `h-dark` wins\n * over `dark` for a path ending in `-h-dark`.\n */\nfunction matchVariant(\n path: string,\n matchOrder: readonly VariantEntry[],\n): { label: string; basePath: string } | undefined {\n if (matchOrder.length === 0) return undefined;\n const segments = path.split('.');\n const leaf = segments.at(-1) ?? path;\n for (const entry of matchOrder) {\n if (leaf === entry.suffix) {\n const parent = segments.slice(0, -1).join('.');\n if (parent.length === 0) continue;\n return { label: entry.label, basePath: parent };\n }\n const tailMarker = `-${entry.suffix}`;\n if (leaf.endsWith(tailMarker)) {\n const trimmed = leaf.slice(0, -tailMarker.length);\n if (trimmed.length === 0) continue;\n const copy = segments.slice(0, -1);\n copy.push(trimmed);\n return { label: entry.label, basePath: copy.join('.') };\n }\n }\n return undefined;\n}\n","import cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport './Diagnostics.css';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { useProject } from '#/internal/use-project.ts';\nimport type { VirtualDiagnostic } from '#/types.ts';\n\nexport interface DiagnosticsProps {\n /** Override the section caption. Defaults to a severity summary. */\n caption?: string;\n}\n\ntype DiagnosticSeverity = VirtualDiagnostic['severity'];\n\nconst severityLabel: Record<DiagnosticSeverity, string> = {\n error: 'ERROR',\n warn: 'WARN',\n info: 'INFO',\n};\n\nfunction summaryText(diagnostics: readonly VirtualDiagnostic[]): string {\n if (diagnostics.length === 0) return '✔ OK · no diagnostics';\n const counts = { error: 0, warn: 0, info: 0 };\n for (const d of diagnostics) counts[d.severity] += 1;\n const parts: string[] = [];\n if (counts.error > 0) parts.push(`✖ ${counts.error} error${counts.error === 1 ? '' : 's'}`);\n if (counts.warn > 0) parts.push(`⚠ ${counts.warn} warning${counts.warn === 1 ? '' : 's'}`);\n if (counts.info > 0) parts.push(`${counts.info} info`);\n return parts.join(' · ');\n}\n\nfunction diagnosticKey(d: VirtualDiagnostic, i: number): string {\n return `${d.severity}:${d.group}:${d.filename ?? ''}:${d.line ?? ''}:${d.message}:${i}`;\n}\n\nfunction summaryVariant(diagnostics: readonly VirtualDiagnostic[]): 'ok' | 'error' | 'warn' | null {\n if (diagnostics.length === 0) return 'ok';\n if (diagnostics.some((d) => d.severity === 'error')) return 'error';\n if (diagnostics.some((d) => d.severity === 'warn')) return 'warn';\n return null;\n}\n\n/**\n * Render the project's load diagnostics — parser errors, resolver warnings,\n * disabled-axes validation issues, etc. — as a collapsible list. Auto-opens\n * when the project carries errors or warnings; stays collapsed for clean\n * loads and info-only loads.\n *\n * Replaces the diagnostics section from the addon's (now-retired) Design\n * Tokens panel. Consumers compose it alongside TokenNavigator / TokenTable\n * on their own MDX pages.\n */\nexport function Diagnostics({ caption }: DiagnosticsProps = {}): ReactElement {\n const { activeAxes, cssVarPrefix, diagnostics } = useProject();\n\n const hasErrorsOrWarnings = diagnostics.some(\n (d) => d.severity === 'error' || d.severity === 'warn',\n );\n const headingText = caption ?? `Diagnostics · ${summaryText(diagnostics)}`;\n const variant = summaryVariant(diagnostics);\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)} data-testid=\"diagnostics\">\n <details open={hasErrorsOrWarnings}>\n <summary\n className={cx(\n 'sb-diagnostics__summary',\n variant && `sb-diagnostics__summary--${variant}`,\n )}\n >\n {headingText}\n </summary>\n {diagnostics.length > 0 && (\n <ul role=\"list\" className=\"sb-diagnostics__list\">\n {diagnostics.map((d, i) => (\n <li\n key={diagnosticKey(d, i)}\n className=\"sb-diagnostics__row\"\n aria-label={`${severityLabel[d.severity]}: ${d.message}`}\n >\n <span\n className={cx('sb-diagnostics__label', {\n [`sb-diagnostics__label--${d.severity}`]: d.severity !== 'info',\n })}\n aria-hidden\n >\n {severityLabel[d.severity]}\n </span>\n <div>\n <div>{d.message}</div>\n {(d.group || d.filename) && (\n <div className=\"sb-diagnostics__meta\">\n {[d.group, d.filename, d.line ? `:${d.line}` : '']\n .filter(Boolean)\n .join(' · ')}\n </div>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </details>\n </div>\n );\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { BORDER_STRONG } from '#/internal/styles.tsx';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\n\nexport type DimensionKind = 'length' | 'radius' | 'size';\n\nexport interface DimensionBarProps {\n /** Full dot-path of the dimension token to preview. */\n path: string;\n /**\n * Visualization kind:\n * - `'length'` (default): horizontal bar whose width equals the token's dimension.\n * - `'radius'`: 56×56 square with the token applied as `border-radius`.\n * - `'size'`: a square sized to the token's dimension.\n */\n kind?: DimensionKind;\n}\n\nconst MAX_RENDER_PX = 480;\n\nconst styles = {\n bar: {\n height: 14,\n background: 'var(--swatchbook-accent-bg, #3b82f6)',\n borderRadius: 2,\n minWidth: 1,\n } satisfies CSSProperties,\n radiusSample: {\n width: 56,\n height: 56,\n background: 'var(--swatchbook-accent-bg, #3b82f6)',\n border: BORDER_STRONG,\n } satisfies CSSProperties,\n sizeSample: {\n background: 'var(--swatchbook-accent-bg, #3b82f6)',\n border: BORDER_STRONG,\n minWidth: 1,\n minHeight: 1,\n } satisfies CSSProperties,\n};\n\n/**\n * Convert a DTCG dimension `$value` (`{ value, unit }`) to pixels for the\n * purpose of deciding whether to cap the rendered bar. Returns `NaN` for\n * units we can't reasonably approximate (ex / ch / %), which the caller\n * treats as \"render at cssVar but don't cap\".\n */\nfunction toPixels(raw: unknown): number {\n if (raw == null || typeof raw !== 'object') return Number.NaN;\n const v = raw as { value?: unknown; unit?: unknown };\n if (typeof v.value !== 'number' || typeof v.unit !== 'string') return Number.NaN;\n switch (v.unit) {\n case 'px':\n return v.value;\n case 'rem':\n case 'em':\n return v.value * 16;\n default:\n return Number.NaN;\n }\n}\n\nexport function DimensionBar({ path, kind = 'length' }: DimensionBarProps): ReactElement {\n const project = useProject();\n const { resolved } = project;\n const cssVar = resolveCssVar(path, project);\n const token = resolved[path];\n const pxValue = toPixels(token?.$value);\n const capped = Number.isFinite(pxValue) && pxValue > MAX_RENDER_PX;\n const cappedValue = capped ? `${MAX_RENDER_PX}px` : cssVar;\n\n switch (kind) {\n case 'radius':\n return <div style={{ ...styles.radiusSample, borderRadius: cssVar }} aria-hidden />;\n case 'size':\n return (\n <div\n style={{ ...styles.sizeSample, width: cappedValue, height: cappedValue }}\n aria-hidden\n />\n );\n case 'length':\n default:\n return <div style={{ ...styles.bar, width: cappedValue }} aria-hidden />;\n }\n}\n","import type { VirtualTokenListingShape } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat } from '#/format-color.ts';\nimport type {\n BorderValue,\n DashedStrokeStyleValue,\n ShadowLayer,\n} from '#/internal/composite-types.ts';\n\n/**\n * Single-line display string for any DTCG token `$value`. Prefers\n * plugin-css's `previewValue` from the Token Listing; for color\n * tokens only when the toolbar format is hex (other formats route\n * through local colorjs.io).\n */\nexport function formatTokenValue(\n value: unknown,\n $type: string | undefined,\n colorFormat: ColorFormat,\n listingEntry?: VirtualTokenListingShape,\n): string {\n if (value == null) return '';\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n\n const preview = listingEntry?.previewValue;\n if (preview !== undefined) {\n const previewStr = typeof preview === 'string' ? cleanFloatNoise(preview) : String(preview);\n if ($type !== 'color') return previewStr;\n if (colorFormat === 'hex') return previewStr;\n }\n\n switch ($type) {\n case 'color':\n return formatColor(value, colorFormat).value;\n case 'dimension':\n case 'duration':\n return formatDimension(value);\n case 'fontFamily':\n return formatFontFamily(value);\n case 'fontWeight':\n case 'lineHeight':\n case 'letterSpacing':\n case 'opacity':\n case 'number':\n return formatPrimitive(value);\n case 'cubicBezier':\n return formatCubicBezier(value);\n case 'strokeStyle':\n return formatStrokeStyle(value);\n case 'shadow':\n return formatShadow(value, colorFormat);\n case 'border':\n return formatBorder(value, colorFormat);\n default:\n return formatUnknown(value);\n }\n}\n\nfunction formatDimension(v: unknown): string {\n if (typeof v === 'string' || typeof v === 'number') return String(v);\n if (v && typeof v === 'object') {\n const d = v as { value?: unknown; unit?: unknown };\n if (typeof d.value === 'number' && typeof d.unit === 'string') return `${d.value}${d.unit}`;\n }\n return formatUnknown(v);\n}\n\nfunction cleanFloatNoise(s: string): string {\n return s.replace(/-?\\d+\\.\\d{8,}/g, (m) => `${+Number(m).toFixed(3)}`);\n}\n\nfunction formatFontFamily(v: unknown): string {\n if (typeof v === 'string') return v;\n if (Array.isArray(v)) return v.map(String).join(', ');\n return formatUnknown(v);\n}\n\nfunction formatPrimitive(v: unknown): string {\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return String(v);\n return formatUnknown(v);\n}\n\nfunction formatCubicBezier(v: unknown): string {\n if (Array.isArray(v) && v.length === 4) {\n return `cubic-bezier(${v.map((n) => (typeof n === 'number' ? n : 0)).join(', ')})`;\n }\n return formatUnknown(v);\n}\n\nfunction formatStrokeStyle(v: unknown): string {\n if (typeof v === 'string') return v;\n if (v && typeof v === 'object') {\n const s = v as DashedStrokeStyleValue;\n const parts: string[] = ['dashed'];\n if (Array.isArray(s.dashArray)) {\n parts.push(s.dashArray.map((n) => formatDimension(n)).join(' '));\n }\n if (typeof s.lineCap === 'string') parts.push(s.lineCap);\n return parts.join(' · ');\n }\n return formatUnknown(v);\n}\n\nfunction formatShadow(v: unknown, colorFormat: ColorFormat): string {\n const layers = Array.isArray(v) ? v : [v];\n const parts = layers.map((layer) => {\n if (!layer || typeof layer !== 'object') return formatUnknown(layer);\n const s = layer as ShadowLayer;\n const pieces = [\n formatDimension(s.offsetX),\n formatDimension(s.offsetY),\n formatDimension(s.blur),\n formatDimension(s.spread),\n formatColor(s.color, colorFormat).value,\n ].filter((p) => p !== '');\n if (s.inset) pieces.push('inset');\n return pieces.join(' ');\n });\n return parts.join(', ');\n}\n\nfunction formatBorder(v: unknown, colorFormat: ColorFormat): string {\n if (!v || typeof v !== 'object') return formatUnknown(v);\n const b = v as BorderValue;\n const width = formatDimension(b.width);\n const style = formatPrimitive(b.style);\n const color = formatColor(b.color, colorFormat).value;\n return [width, style, color].filter((p) => p !== '').join(' ');\n}\n\nfunction formatUnknown(v: unknown): string {\n if (v == null) return '';\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return String(v);\n try {\n return JSON.stringify(v).slice(0, 120);\n } catch {\n return String(v);\n }\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './DimensionScale.css';\nimport { DimensionBar } from '#/dimension-scale/DimensionBar.tsx';\nimport type { DimensionKind } from '#/dimension-scale/DimensionBar.tsx';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport type { DimensionKind };\n\nexport interface DimensionScaleProps {\n /**\n * Token-path filter. Defaults to every `dimension` token. Use e.g.\n * `\"space.*\"` to scope to the spacing scale.\n */\n filter?: string;\n /**\n * Visualization kind:\n * - `'length'` (default): horizontal bar whose width equals the token's dimension.\n * - `'radius'`: 56×56 square with the token applied as `border-radius`.\n * - `'size'`: a square sized to the token's dimension.\n */\n kind?: DimensionKind;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order.\n * - `'value'` (default) — numeric by rendered pixel size (`px` / `rem` / `em`).\n * Non-convertible units (ex/ch/%) land after the convertible ones.\n * - `'path'` — lexicographic on the dot-path.\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\nconst MAX_RENDER_PX = 480;\n\ninterface Row {\n path: string;\n cssVar: string;\n displayValue: string;\n pxValue: number;\n capped: boolean;\n}\n\nfunction toPixels(raw: unknown): number {\n if (raw == null || typeof raw !== 'object') return Number.NaN;\n const v = raw as { value?: unknown; unit?: unknown };\n if (typeof v.value !== 'number' || typeof v.unit !== 'string') return Number.NaN;\n switch (v.unit) {\n case 'px':\n return v.value;\n case 'rem':\n case 'em':\n return v.value * 16;\n default:\n return Number.NaN;\n }\n}\n\nexport function DimensionScale({\n filter,\n kind = 'length',\n caption,\n sortBy = 'value',\n sortDir = 'asc',\n}: DimensionScaleProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'dimension') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => {\n const pxValue = toPixels(token.$value);\n return {\n path,\n cssVar: resolveCssVar(path, project),\n displayValue: formatTokenValue(token.$value, token.$type, 'raw', project.listing[path]),\n pxValue,\n capped: Number.isFinite(pxValue) && pxValue > MAX_RENDER_PX,\n };\n });\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} dimension${rows.length === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No dimension tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-dimension-scale__row\">\n <div className=\"sb-dimension-scale__meta\">\n <span className=\"sb-dimension-scale__path\">{row.path}</span>\n <span className=\"sb-dimension-scale__specs\">{row.displayValue}</span>\n </div>\n <div className=\"sb-dimension-scale__visual-cell\">\n <DimensionBar path={row.path} kind={kind} />\n {row.capped && (\n <span className=\"sb-dimension-scale__cap\">capped at {MAX_RENDER_PX}px</span>\n )}\n </div>\n <span className=\"sb-dimension-scale__css-var\">{row.cssVar}</span>\n </div>\n ))}\n </div>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './FontFamilySample.css';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\n\nexport interface FontFamilySampleProps {\n /**\n * Token-path filter. Defaults to every `fontFamily` token. Use e.g.\n * `\"font.family.*\"` to scope to the ref layer.\n */\n filter?: string;\n /** Override the sample text rendered for each token. */\n sample?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` ordering falls through to path for this block's\n * type (composite / non-numeric); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n stack: string;\n}\n\nfunction stackString(raw: unknown): string {\n if (typeof raw === 'string') return raw;\n if (Array.isArray(raw)) return raw.map(String).join(', ');\n return '';\n}\n\nexport function FontFamilySample({\n filter,\n sample = 'The quick brown fox jumps over the lazy dog.',\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: FontFamilySampleProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'fontFamily') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n stack: stackString(token.$value),\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} fontFamily token${rows.length === 1 ? '' : 's'}${filter && filter !== 'fontFamily' ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No fontFamily tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-font-family-sample__row\">\n <div className=\"sb-font-family-sample__meta\">\n <span className=\"sb-font-family-sample__path\">{row.path}</span>\n <span className=\"sb-font-family-sample__stack\">{row.stack}</span>\n </div>\n <div className=\"sb-font-family-sample__sample\" style={{ fontFamily: row.cssVar }}>\n {sample}\n </div>\n <span className=\"sb-font-family-sample__css-var\">{row.cssVar}</span>\n </div>\n ))}\n </div>\n );\n}\n","/**\n * Coerce a CSS `var(--…)` reference into the numeric slot of a React\n * inline-style property.\n *\n * React's `CSSProperties` types unitless properties (`fontWeight`,\n * `lineHeight`, `zIndex`, …) as `number`. The DOM accepts a string at\n * runtime — the rendered stylesheet just receives whatever React passes —\n * so a `var(--font-weight)` reference works functionally. TypeScript still\n * complains. Centralising the type assertion in one named helper keeps\n * the gap visible (and greppable) instead of scattering casts across\n * block components that want CSS-var-driven typography or layout values.\n */\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-expect-error — React's CSSProperties slot is `number`; the DOM tolerates a CSS var string.\nexport const cssVarAsNumber = (varRef: string): number => varRef;\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './FontWeightScale.css';\nimport { cssVarAsNumber } from '#/internal/css-var-style.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface FontWeightScaleProps {\n /**\n * Token-path filter. Defaults to every `fontWeight` token. Use e.g.\n * `\"font.weight.*\"` to scope to the ref layer.\n */\n filter?: string;\n /** Override the sample text rendered for each token. */\n sample?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order.\n * - `'value'` (default) — ascending numeric by weight (100 → 900).\n * - `'path'` — lexicographic on the dot-path.\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n display: string;\n weight: number;\n}\n\nfunction toWeight(raw: unknown): number {\n if (typeof raw === 'number') return raw;\n if (typeof raw === 'string') {\n const n = Number.parseInt(raw, 10);\n return Number.isFinite(n) ? n : Number.NaN;\n }\n return Number.NaN;\n}\n\nexport function FontWeightScale({\n filter,\n sample = 'Aa',\n caption,\n sortBy = 'value',\n sortDir = 'asc',\n}: FontWeightScaleProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'fontWeight') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n display: token.$value == null ? '' : String(token.$value),\n weight: toWeight(token.$value),\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} fontWeight token${rows.length === 1 ? '' : 's'}${filter && filter !== 'fontWeight' ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No fontWeight tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-font-weight-scale__row\">\n <div className=\"sb-font-weight-scale__meta\">\n <span className=\"sb-font-weight-scale__path\">{row.path}</span>\n <span className=\"sb-font-weight-scale__value\">{row.display}</span>\n </div>\n <div\n className=\"sb-font-weight-scale__sample\"\n style={{ fontWeight: cssVarAsNumber(row.cssVar) }}\n >\n {sample}\n </div>\n <span className=\"sb-font-weight-scale__css-var\">{row.cssVar}</span>\n </div>\n ))}\n </div>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './GradientPalette.css';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface GradientPaletteProps {\n /**\n * Token-path filter. Defaults to every `gradient` token. Use e.g.\n * `\"gradient.*\"` or `\"gradient.accent\"` to scope.\n */\n filter?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` falls through to path (gradients don't have\n * a single-axis ordering); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface GradientStop {\n color?: {\n colorSpace?: string;\n components?: readonly number[];\n alpha?: number;\n };\n position?: number;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n stops: GradientStop[];\n}\n\nfunction asStops(raw: unknown): GradientStop[] {\n if (!Array.isArray(raw)) return [];\n return raw as GradientStop[];\n}\n\nconst pct = (n: number): string => `${(n * 100).toFixed(3)}%`;\n\nfunction stopCssColor(stop: GradientStop): string {\n const color = stop.color;\n if (!color || !Array.isArray(color.components) || color.components.length < 3) {\n return 'transparent';\n }\n const [r, g, b] = color.components;\n if (r === undefined || g === undefined || b === undefined) return 'transparent';\n const alpha = color.alpha ?? 1;\n return alpha === 1\n ? `rgb(${pct(r)} ${pct(g)} ${pct(b)})`\n : `rgb(${pct(r)} ${pct(g)} ${pct(b)} / ${alpha})`;\n}\n\nfunction stopKey(path: string, stop: GradientStop, fallback: number): string {\n return `${path}|${stop.position ?? fallback}|${stopCssColor(stop)}`;\n}\n\nexport function GradientPalette({\n filter,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: GradientPaletteProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'gradient') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n stops: asStops(token.$value),\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} gradient${rows.length === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No gradient tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-gradient-palette__row\">\n <div className=\"sb-gradient-palette__meta\">\n <span className=\"sb-gradient-palette__path\">{row.path}</span>\n <span className=\"sb-gradient-palette__css-var\">{row.cssVar}</span>\n </div>\n <div\n className=\"sb-gradient-palette__sample\"\n style={{ background: `linear-gradient(to right, ${row.cssVar})` }}\n aria-hidden\n />\n <div className=\"sb-gradient-palette__stops\">\n {row.stops.map((stop, i) => (\n <div key={stopKey(row.path, stop, i)} className=\"sb-gradient-palette__stop-row\">\n <span\n className=\"sb-gradient-palette__stop-swatch\"\n style={{ background: stopCssColor(stop) }}\n aria-hidden\n />\n <span>{formatColor(stop.color, colorFormat).value}</span>\n <span className=\"sb-gradient-palette__stop-position\">\n @ {((stop.position ?? 0) * 100).toFixed(0)}%\n </span>\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\n\n/**\n * True when rendering inside Chromatic's snapshot runner. Chromatic's\n * browser ships a recognisable user-agent string; checked here so\n * motion-looping components can fall back to their static state for\n * deterministic snapshots. Per-component detection rather than the\n * global `chromatic.prefersReducedMotion: true` parameter — that\n * parameter is incompatible with Chromatic's verification parser.\n */\nfunction isChromatic(): boolean {\n if (typeof navigator === 'undefined') return false;\n return navigator.userAgent.includes('Chromatic');\n}\n\n/**\n * Reactive `prefers-reduced-motion: reduce` detector. Returns the current\n * match and updates if the user toggles the OS-level preference. Also\n * returns `true` under Chromatic to keep animated samples deterministic\n * during visual regression capture.\n */\nexport function usePrefersReducedMotion(): boolean {\n const [reduced, setReduced] = useState(false);\n useEffect(() => {\n if (typeof window === 'undefined') return;\n if (isChromatic()) {\n setReduced(true);\n return;\n }\n const query = window.matchMedia('(prefers-reduced-motion: reduce)');\n setReduced(query.matches);\n const onChange = (e: MediaQueryListEvent): void => setReduced(e.matches);\n query.addEventListener('change', onChange);\n return () => query.removeEventListener('change', onChange);\n }, []);\n return reduced;\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { SURFACE_MUTED, TEXT_MUTED } from '#/internal/styles.tsx';\nimport { useEffect, useMemo, useState } from 'react';\nimport { usePrefersReducedMotion } from '#/internal/prefers-reduced-motion.ts';\nimport { useProject } from '#/internal/use-project.ts';\n\nexport type MotionSpeed = 0.25 | 0.5 | 1 | 2;\n\nexport interface MotionSampleProps {\n /** Full dot-path of the motion token (`transition`, `duration`, or `cubicBezier`). */\n path: string;\n /** Playback speed multiplier. Defaults to `1`. */\n speed?: MotionSpeed;\n /**\n * Change this value to force the animation to restart. Useful when an\n * outer block exposes a \"replay\" button that should re-trigger every\n * sample at once.\n */\n runKey?: number;\n}\n\nconst DEFAULT_DURATION_MS = 300;\nconst DEFAULT_EASING = 'cubic-bezier(0.2, 0, 0, 1)';\n\nconst styles = {\n track: {\n position: 'relative',\n height: 36,\n background: SURFACE_MUTED,\n borderRadius: 18,\n overflow: 'hidden',\n } satisfies CSSProperties,\n ball: {\n position: 'absolute',\n top: '50%',\n width: 28,\n height: 28,\n marginTop: -14,\n borderRadius: '50%',\n background: 'var(--swatchbook-accent-bg, #3b82f6)',\n } satisfies CSSProperties,\n reducedMotion: {\n fontSize: 11,\n color: TEXT_MUTED,\n fontStyle: 'italic',\n } satisfies CSSProperties,\n};\n\ninterface Spec {\n durationMs: number;\n easing: string;\n}\n\nfunction extractDurationMs(raw: unknown): number {\n if (raw == null) return Number.NaN;\n if (typeof raw === 'object') {\n const v = raw as { value?: unknown; unit?: unknown };\n if (typeof v.value === 'number' && typeof v.unit === 'string') {\n if (v.unit === 'ms') return v.value;\n if (v.unit === 's') return v.value * 1000;\n }\n }\n return Number.NaN;\n}\n\nfunction extractCubicBezier(raw: unknown): string | null {\n if (Array.isArray(raw) && raw.length === 4 && raw.every((n) => typeof n === 'number')) {\n return `cubic-bezier(${raw.map((n) => Number(n).toFixed(3)).join(', ')})`;\n }\n return null;\n}\n\nfunction asDuration(\n raw: unknown,\n themeTokens: Record<string, { $value?: unknown }>,\n fallback: number,\n): number {\n const direct = extractDurationMs(raw);\n if (Number.isFinite(direct)) return direct;\n if (typeof raw === 'string') {\n const match = raw.match(/^\\{([^}]+)\\}$/);\n if (match && match[1]) {\n const referenced = themeTokens[match[1]];\n const resolved = extractDurationMs(referenced?.$value);\n if (Number.isFinite(resolved)) return resolved;\n }\n }\n return fallback;\n}\n\nfunction asEasing(\n raw: unknown,\n themeTokens: Record<string, { $value?: unknown }>,\n fallback: string,\n): string {\n const direct = extractCubicBezier(raw);\n if (direct) return direct;\n if (typeof raw === 'string') {\n const match = raw.match(/^\\{([^}]+)\\}$/);\n if (match && match[1]) {\n const referenced = themeTokens[match[1]];\n const resolved = extractCubicBezier(referenced?.$value);\n if (resolved) return resolved;\n }\n }\n return fallback;\n}\n\nexport function resolveMotionSpec(\n token: { $type?: string | undefined; $value?: unknown } | undefined,\n themeTokens: Record<string, { $value?: unknown }>,\n): Spec | null {\n if (!token) return null;\n const type = token.$type;\n if (type === 'transition') {\n const v = (token.$value ?? {}) as {\n duration?: unknown;\n timingFunction?: unknown;\n };\n return {\n durationMs: asDuration(v.duration, themeTokens, DEFAULT_DURATION_MS),\n easing: asEasing(v.timingFunction, themeTokens, DEFAULT_EASING),\n };\n }\n if (type === 'duration') {\n const durationMs = extractDurationMs(token.$value);\n if (!Number.isFinite(durationMs)) return null;\n return { durationMs, easing: DEFAULT_EASING };\n }\n if (type === 'cubicBezier') {\n const easing = extractCubicBezier(token.$value);\n if (!easing) return null;\n return { durationMs: DEFAULT_DURATION_MS, easing };\n }\n return null;\n}\n\nexport function MotionSample({ path, speed = 1, runKey = 0 }: MotionSampleProps): ReactElement {\n const { resolved } = useProject();\n const reducedMotion = usePrefersReducedMotion();\n\n const spec = useMemo(() => resolveMotionSpec(resolved[path], resolved), [resolved, path]);\n\n const durationMs = spec?.durationMs ?? DEFAULT_DURATION_MS;\n const easing = spec?.easing ?? DEFAULT_EASING;\n const scaledDuration = Math.max(1, durationMs / speed);\n\n const [phase, setPhase] = useState<0 | 1>(0);\n\n useEffect(() => {\n if (reducedMotion) return;\n setPhase(0);\n const id = requestAnimationFrame(() => setPhase(1));\n const loop = window.setInterval(() => {\n setPhase((p) => (p === 0 ? 1 : 0));\n }, scaledDuration * 2);\n return () => {\n cancelAnimationFrame(id);\n window.clearInterval(loop);\n };\n }, [scaledDuration, runKey, reducedMotion]);\n\n if (reducedMotion) {\n return (\n <div style={styles.reducedMotion}>\n Animation suppressed by <code>prefers-reduced-motion: reduce</code>.\n </div>\n );\n }\n\n return (\n <div style={styles.track}>\n <div\n style={{\n ...styles.ball,\n left: phase === 1 ? 'calc(100% - 32px)' : '4px',\n transition: `left ${scaledDuration}ms ${easing}`,\n }}\n aria-hidden\n />\n </div>\n );\n}\n","import cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport { useMemo, useState } from 'react';\nimport './MotionPreview.css';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { usePrefersReducedMotion } from '#/internal/prefers-reduced-motion.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\nimport { MotionSample, resolveMotionSpec } from '#/motion-preview/MotionSample.tsx';\nimport type { MotionSpeed } from '#/motion-preview/MotionSample.tsx';\n\nexport type { MotionSpeed };\n\nexport interface MotionPreviewProps {\n /**\n * Token-path filter. Defaults to transition + duration + cubicBezier\n * tokens. Use e.g. `\"transition.*\"` to scope to the semantic layer.\n */\n filter?: string;\n /** Override the caption. */\n caption?: string;\n}\n\nconst SPEEDS: MotionSpeed[] = [0.25, 0.5, 1, 2];\n\ninterface Row {\n path: string;\n cssVar: string;\n durationMs: number;\n easing: string;\n kind: 'transition' | 'duration' | 'cubicBezier';\n}\n\nfunction formatSpec(row: Row): string {\n switch (row.kind) {\n case 'transition':\n return `transition · ${Math.round(row.durationMs)}ms · ${row.easing}`;\n case 'duration':\n return `duration · ${Math.round(row.durationMs)}ms`;\n case 'cubicBezier':\n return `cubicBezier · ${row.easing}`;\n }\n}\n\nexport function MotionPreview({ filter, caption }: MotionPreviewProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n const [speed, setSpeed] = useState<MotionSpeed>(1);\n const [run, setRun] = useState(0);\n const reducedMotion = usePrefersReducedMotion();\n\n const rows = useMemo(() => {\n const collected: Row[] = [];\n for (const [path, token] of Object.entries(resolved)) {\n if (filter && !matchPath(path, filter)) continue;\n if (!filter && !['transition', 'duration', 'cubicBezier'].includes(token.$type ?? '')) {\n continue;\n }\n const kind = token.$type as Row['kind'] | undefined;\n if (!kind) continue;\n const spec = resolveMotionSpec(token, resolved);\n if (!spec) continue;\n collected.push({\n path,\n cssVar: resolveCssVar(path, project),\n durationMs: spec.durationMs,\n easing: spec.easing,\n kind,\n });\n }\n collected.sort((a, b) => {\n if (a.kind !== b.kind) return a.kind.localeCompare(b.kind);\n return a.path.localeCompare(b.path, undefined, { numeric: true });\n });\n return collected;\n }, [resolved, filter, project]);\n\n const captionText =\n caption ??\n `${rows.length} motion token${rows.length === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No motion tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n <div className=\"sb-motion-preview__controls\">\n <span className=\"sb-motion-preview__control-label\">Speed</span>\n {SPEEDS.map((s) => (\n <button\n key={s}\n type=\"button\"\n className={cx('sb-motion-preview__speed-btn', {\n 'sb-motion-preview__speed-btn--active': s === speed,\n })}\n onClick={() => setSpeed(s)}\n >\n {s}×\n </button>\n ))}\n <button\n type=\"button\"\n className=\"sb-motion-preview__replay-btn\"\n onClick={() => setRun((n) => n + 1)}\n disabled={reducedMotion}\n title={reducedMotion ? 'Disabled by prefers-reduced-motion' : 'Replay all'}\n >\n ↻ Replay\n </button>\n </div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-motion-preview__row\">\n <div className=\"sb-motion-preview__meta\">\n <span className=\"sb-motion-preview__path\">{row.path}</span>\n <span className=\"sb-motion-preview__specs\">{formatSpec(row)}</span>\n </div>\n <MotionSample path={row.path} speed={speed} runKey={run} />\n <span className=\"sb-motion-preview__css-var\">{row.cssVar}</span>\n </div>\n ))}\n </div>\n );\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './OpacityScale.css';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface OpacityScaleProps {\n /**\n * Token-path filter. Use `\"number.opacity.*\"` or `\"opacity.*\"` depending\n * on your layout. Omit to match every `$type: 'number'` token whose\n * value is in `[0, 1]` — the value-range check (applied alongside\n * the glob) keeps line-heights / z-indexes out.\n */\n filter?: string;\n /**\n * DTCG `$type` filter. `opacity` tokens where DTCG ships them as a\n * dedicated type; otherwise `number` (the common placement pre-spec).\n * Accepts either.\n */\n type?: 'number' | 'opacity';\n /**\n * Sample token rendered at each opacity. Defaults to `color.accent.bg`\n * — swap to whatever colour your system uses to demonstrate scrim /\n * overlay behaviour.\n */\n sampleColor?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order.\n * - `'value'` (default) — numeric, low opacity first.\n * - `'path'` — lexicographic on the dot-path.\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n opacity: number;\n displayValue: string;\n}\n\nfunction toOpacity(raw: unknown): number {\n if (typeof raw === 'number') return raw;\n return Number.NaN;\n}\n\n/**\n * Render each opacity token as a colored sample at that opacity over a\n * checkerboard backdrop, so the transparency is visually readable. The\n * number by itself (`0.4`) doesn't convey what the token looks like\n * applied to a surface; the sample does.\n *\n * Only tokens whose `$value` is a finite number between 0 and 1\n * inclusive are rendered — non-opacity `number` siblings (`line-height`,\n * `z-index`) fall out naturally.\n */\nexport function OpacityScale({\n filter,\n type = 'number',\n sampleColor = 'color.accent.bg',\n caption,\n sortBy = 'value',\n sortDir = 'asc',\n}: OpacityScaleProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== type) return false;\n const v = toOpacity(token.$value);\n if (!Number.isFinite(v) || v < 0 || v > 1) return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => {\n const opacity = toOpacity(token.$value);\n return {\n path,\n cssVar: resolveCssVar(path, project),\n opacity,\n displayValue: String(opacity),\n };\n });\n }, [resolved, filter, type, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} opacity token${rows.length === 1 ? '' : 's'}${\n filter ? ` matching \\`${filter}\\`` : ''\n } · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No opacity tokens match this filter.</div>\n </div>\n );\n }\n\n const sampleColorVar = resolveCssVar(sampleColor, project);\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n <div className=\"sb-opacity-scale__grid\">\n {rows.map((row) => (\n <div key={row.path} className=\"sb-opacity-scale__card\">\n <div\n className=\"sb-opacity-scale__swatch\"\n style={\n {\n '--sb-opacity-scale-color': sampleColorVar,\n '--sb-opacity-scale-alpha': String(row.opacity),\n } as CSSProperties\n }\n aria-hidden\n />\n <div className=\"sb-opacity-scale__meta\">\n <span className=\"sb-opacity-scale__path\">{row.path}</span>\n <span className=\"sb-opacity-scale__value\">{row.displayValue}</span>\n <span className=\"sb-opacity-scale__css-var\">{row.cssVar}</span>\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import type { ReactElement, ReactNode } from 'react';\nimport { SwatchbookContext, useOptionalSwatchbookData } from '#/contexts.ts';\nimport type { ProjectSnapshot } from '#/contexts.ts';\n\nexport type { ProjectSnapshot };\n\nexport interface SwatchbookProviderProps {\n value: ProjectSnapshot;\n children: ReactNode;\n}\n\n/**\n * Wraps a tree of blocks with the token data they need to render.\n *\n * The Storybook addon's preview decorator mounts this automatically, so\n * story/MDX authors typically never see it. Outside Storybook — unit\n * tests, custom React apps, non-Storybook doc sites — consumers construct\n * a {@link ProjectSnapshot} (often imported from a JSON file) and wrap\n * their blocks in this provider.\n */\nexport function SwatchbookProvider({ value, children }: SwatchbookProviderProps): ReactElement {\n return <SwatchbookContext.Provider value={value}>{children}</SwatchbookContext.Provider>;\n}\n\n/**\n * Read the current {@link ProjectSnapshot}. Throws if called outside a\n * {@link SwatchbookProvider}; blocks that need to fall back to the\n * virtual module go through the internal `useProject()` hook instead.\n */\nexport function useSwatchbookData(): ProjectSnapshot {\n const value = useOptionalSwatchbookData();\n if (!value) {\n throw new Error(\n '[swatchbook-blocks] useSwatchbookData() called outside <SwatchbookProvider>. ' +\n 'Wrap your tree in <SwatchbookProvider value={snapshot}> or render inside a Storybook story.',\n );\n }\n return value;\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { BORDER_FAINT, SURFACE_RAISED } from '#/internal/styles.tsx';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\n\nexport interface ShadowSampleProps {\n /** Full dot-path of the shadow token to preview. */\n path: string;\n}\n\nconst sampleStyle: CSSProperties = {\n width: 120,\n height: 56,\n background: SURFACE_RAISED,\n border: BORDER_FAINT,\n borderRadius: 6,\n};\n\nexport function ShadowSample({ path }: ShadowSampleProps): ReactElement {\n const project = useProject();\n const cssVar = resolveCssVar(path, project);\n return <div style={{ ...sampleStyle, boxShadow: cssVar }} aria-hidden />;\n}\n","import cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './ShadowPreview.css';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat } from '#/format-color.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\nimport { ShadowSample } from '#/shadow-preview/ShadowSample.tsx';\n\nexport interface ShadowPreviewProps {\n /**\n * Token-path filter. Defaults to every `shadow` token. Use e.g.\n * `\"shadow.*\"` to scope to the semantic layer.\n */\n filter?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` falls through to path (shadows don't have a\n * single-axis ordering); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface ShadowLayer {\n color?: unknown;\n offsetX?: unknown;\n offsetY?: unknown;\n blur?: unknown;\n spread?: unknown;\n inset?: unknown;\n}\n\ninterface Row {\n path: string;\n cssVar: string;\n layers: ShadowLayer[];\n}\n\nfunction formatDimension(raw: unknown): string {\n if (raw == null) return '—';\n if (typeof raw === 'number') return String(raw);\n if (typeof raw === 'string') return raw;\n if (typeof raw === 'object') {\n const v = raw as { value?: unknown; unit?: unknown };\n if (typeof v.value === 'number' && typeof v.unit === 'string') {\n return `${v.value}${v.unit}`;\n }\n }\n return JSON.stringify(raw);\n}\n\nfunction formatSubColor(raw: unknown, format: ColorFormat): string {\n if (raw == null) return '—';\n return formatColor(raw, format).value;\n}\n\nfunction asLayers(raw: unknown): ShadowLayer[] {\n if (Array.isArray(raw)) return raw as ShadowLayer[];\n if (raw && typeof raw === 'object') return [raw as ShadowLayer];\n return [];\n}\n\nfunction layerKey(path: string, layer: ShadowLayer, fallback: number): string {\n const off = `${formatDimension(layer.offsetX)},${formatDimension(layer.offsetY)}`;\n const blur = formatDimension(layer.blur);\n const spread = formatDimension(layer.spread);\n return `${path}|${off}|${blur}|${spread}|${fallback}`;\n}\n\nexport function ShadowPreview({\n filter,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: ShadowPreviewProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'shadow') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n layers: asLayers(token.$value),\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} shadow${rows.length === 1 ? '' : 's'}${filter ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No shadow tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-shadow-preview__row\">\n <div className=\"sb-shadow-preview__meta\">\n <span className=\"sb-shadow-preview__path\">{row.path}</span>\n <span className=\"sb-shadow-preview__css-var\">{row.cssVar}</span>\n </div>\n <div className=\"sb-shadow-preview__sample-cell\">\n <ShadowSample path={row.path} />\n </div>\n <div className=\"sb-shadow-preview__breakdown\">\n {row.layers.length === 1\n ? renderLayer(row.layers[0], colorFormat)\n : row.layers.map((layer, i) => (\n <Layer\n key={layerKey(row.path, layer, i)}\n layer={layer}\n index={i}\n total={row.layers.length}\n colorFormat={colorFormat}\n />\n ))}\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction renderLayer(layer: ShadowLayer | undefined, format: ColorFormat): ReactElement[] {\n if (!layer) return [];\n const entries: [string, string][] = [\n ['offset', `${formatDimension(layer.offsetX)} ${formatDimension(layer.offsetY)}`],\n ['blur', formatDimension(layer.blur)],\n ['spread', formatDimension(layer.spread)],\n ['color', formatSubColor(layer.color, format)],\n ];\n if (layer.inset) entries.push(['inset', String(layer.inset)]);\n return entries.flatMap(([k, v]) => [\n <span key={`k-${k}`} className=\"sb-shadow-preview__breakdown-key\">\n {k}\n </span>,\n <span key={`v-${k}`}>{v}</span>,\n ]);\n}\n\nfunction Layer({\n layer,\n index,\n total,\n colorFormat,\n}: {\n layer: ShadowLayer;\n index: number;\n total: number;\n colorFormat: ColorFormat;\n}): ReactElement {\n return (\n <div className=\"sb-shadow-preview__layer\">\n <div className=\"sb-shadow-preview__layer-header\">\n layer {index + 1} of {total}\n </div>\n <div className={cx('sb-shadow-preview__breakdown', 'sb-shadow-preview__layer-breakdown')}>\n {renderLayer(layer, colorFormat)}\n </div>\n </div>\n );\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './StrokeStyleSample.css';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\n\nexport interface StrokeStyleSampleProps {\n /**\n * Token-path filter. Defaults to every `strokeStyle` token. Use e.g.\n * `\"stroke.style.*\"` to scope to the ref layer.\n */\n filter?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` ordering falls through to path for this block's\n * type (composite / non-numeric); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\nconst STRING_STYLES = new Set([\n 'solid',\n 'dashed',\n 'dotted',\n 'double',\n 'groove',\n 'ridge',\n 'outset',\n 'inset',\n]);\n\ninterface Row {\n path: string;\n cssVar: string;\n displayValue: string;\n cssStyle: string | null;\n}\n\nfunction extractCssStyle(value: unknown): string | null {\n if (typeof value === 'string' && STRING_STYLES.has(value)) return value;\n return null;\n}\n\nexport function StrokeStyleSample({\n filter,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: StrokeStyleSampleProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'strokeStyle') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => ({\n path,\n cssVar: resolveCssVar(path, project),\n displayValue: formatTokenValue(token.$value, token.$type, 'raw', project.listing[path]),\n cssStyle: extractCssStyle(token.$value),\n }));\n }, [resolved, filter, project, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} strokeStyle token${rows.length === 1 ? '' : 's'}${filter && filter !== 'strokeStyle' ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No strokeStyle tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-stroke-style-sample__row\">\n <div className=\"sb-stroke-style-sample__meta\">\n <span className=\"sb-stroke-style-sample__path\">{row.path}</span>\n <span className=\"sb-stroke-style-sample__value\">{row.displayValue}</span>\n </div>\n {row.cssStyle ? (\n <div\n className=\"sb-stroke-style-sample__line\"\n style={{\n borderTopStyle: row.cssStyle as CSSProperties['borderTopStyle'],\n }}\n aria-hidden\n />\n ) : (\n <span className=\"sb-stroke-style-sample__object-fallback\">\n Object-form (dashArray + lineCap) — no pure CSS `border-style` equivalent.\n </span>\n )}\n <span className=\"sb-stroke-style-sample__css-var\">{row.cssVar}</span>\n </div>\n ))}\n </div>\n );\n}\n","import type { Axis } from '@unpunnyfuns/swatchbook-core';\nimport type { VirtualVarianceByPathShape } from '#/contexts.ts';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\n\nexport interface DetailToken {\n $type?: string;\n $value?: unknown;\n $description?: string;\n aliasOf?: string;\n aliasChain?: readonly string[];\n aliasedBy?: readonly string[];\n /**\n * Terrazzo-populated sub-value alias map for composite tokens. Shape\n * varies by $type: object-valued composites (`border`, `typography`,\n * `transition`) use `Record<string, string | undefined>` keyed by\n * sub-key; array-valued composites (`shadow`, `gradient`) use an array\n * of such records indexed per layer / stop. Carried through `unknown`\n * here so each consumer narrows at use-site.\n */\n partialAliasOf?: unknown;\n}\n\nexport interface TokenDetailData {\n token: DetailToken | undefined;\n cssVar: string;\n activeTheme: string;\n activeAxes: Record<string, string>;\n axes: readonly Axis[];\n resolved: Record<string, DetailToken>;\n cssVarPrefix: string;\n varianceByPath: VirtualVarianceByPathShape;\n /**\n * Pure-function accessor that composes the resolved tokens for any\n * tuple of axis selections — used by the `AxisVariance` grid to\n * read per-cell values without indexing `permutationsResolved` by\n * a derived tuple name.\n */\n resolveAt: (tuple: Record<string, string>) => Record<string, DetailToken>;\n}\n\nexport function useTokenDetailData(path: string): TokenDetailData {\n const project = useProject();\n const { activeTheme, activeAxes, axes, resolved, cssVarPrefix, varianceByPath, resolveAt } =\n project;\n const typedResolved = resolved as Record<string, DetailToken>;\n return {\n token: typedResolved[path],\n cssVar: resolveCssVar(path, project),\n activeTheme,\n activeAxes,\n axes,\n resolved: typedResolved,\n cssVarPrefix,\n varianceByPath,\n resolveAt: resolveAt as (tuple: Record<string, string>) => Record<string, DetailToken>,\n };\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\n\nexport interface AliasChainProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\nexport function AliasChain({ path }: AliasChainProps): ReactElement | null {\n const { token } = useTokenDetailData(path);\n\n const chain = useMemo<string[]>(() => {\n if (!token) return [];\n if (Array.isArray(token.aliasChain) && token.aliasChain.length > 0) {\n return [path, ...token.aliasChain];\n }\n if (typeof token.aliasOf === 'string') return [path, token.aliasOf];\n return [path];\n }, [token, path]);\n\n if (chain.length <= 1) return null;\n\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Alias chain</div>\n <div className=\"sb-token-detail__chain\">\n {chain.map((step, i) => (\n <span key={step} className=\"sb-token-detail__chain\">\n <span className=\"sb-token-detail__chain-node\">{step}</span>\n {i < chain.length - 1 && <span className=\"sb-token-detail__arrow\">→</span>}\n </span>\n ))}\n </div>\n </>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\nimport type { DetailToken } from '#/token-detail/internal.ts';\n\nexport interface AliasedByProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\nconst ALIASED_BY_DEPTH_CAP = 6;\n\ninterface AliasedByNode {\n path: string;\n children: AliasedByNode[];\n truncated?: boolean;\n}\n\nconst GROUP_RANK: Record<string, number> = { ref: 0, sys: 1 };\n\nexport function AliasedBy({ path }: AliasedByProps): ReactElement | null {\n const { resolved } = useTokenDetailData(path);\n const tree = useMemo<AliasedByNode[]>(() => buildAliasedByTree(path, resolved), [path, resolved]);\n const truncated = useMemo(() => treeHasTruncation(tree), [tree]);\n\n if (tree.length === 0) return null;\n\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Aliased by</div>\n <ul className=\"sb-token-detail__aliased-by-list\">\n {tree.map((node) => (\n <AliasedByRow key={node.path} node={node} depth={0} />\n ))}\n </ul>\n {truncated && (\n <div className=\"sb-token-detail__aliased-by-truncated\">\n Further descendants truncated at depth {ALIASED_BY_DEPTH_CAP}.\n </div>\n )}\n </>\n );\n}\n\nfunction AliasedByRow({ node, depth }: { node: AliasedByNode; depth: number }): ReactElement {\n return (\n <li>\n <div className=\"sb-token-detail__aliased-by-row\" style={{ paddingLeft: depth * 16 }}>\n <span className=\"sb-token-detail__chain-node\">{node.path}</span>\n </div>\n {node.children.length > 0 && (\n <ul className=\"sb-token-detail__aliased-by-list\">\n {node.children.map((child) => (\n <AliasedByRow key={child.path} node={child} depth={depth + 1} />\n ))}\n </ul>\n )}\n </li>\n );\n}\n\nfunction buildAliasedByTree(\n rootPath: string,\n resolved: Record<string, DetailToken>,\n): AliasedByNode[] {\n const root = resolved[rootPath];\n const direct = root?.aliasedBy;\n if (!direct || direct.length === 0) return [];\n const visited = new Set<string>([rootPath]);\n return sortPaths(direct).map((p) => walk(p, resolved, visited, 1));\n}\n\nfunction walk(\n path: string,\n resolved: Record<string, DetailToken>,\n visited: Set<string>,\n depth: number,\n): AliasedByNode {\n if (visited.has(path)) return { path, children: [] };\n visited.add(path);\n const token = resolved[path];\n const parents = token?.aliasedBy;\n if (!parents || parents.length === 0) return { path, children: [] };\n if (depth >= ALIASED_BY_DEPTH_CAP) {\n return { path, children: [], truncated: true };\n }\n const children = sortPaths(parents).map((p) => walk(p, resolved, visited, depth + 1));\n return { path, children };\n}\n\nfunction sortPaths(paths: readonly string[]): string[] {\n return paths.toSorted((a, b) => {\n const ra = GROUP_RANK[a.split('.')[0] ?? ''] ?? 2;\n const rb = GROUP_RANK[b.split('.')[0] ?? ''] ?? 2;\n return ra !== rb ? ra - rb : a.localeCompare(b, undefined, { numeric: true });\n });\n}\n\nfunction treeHasTruncation(nodes: AliasedByNode[]): boolean {\n for (const n of nodes) {\n if (n.truncated) return true;\n if (treeHasTruncation(n.children)) return true;\n }\n return false;\n}\n","import type { Axis } from '@unpunnyfuns/swatchbook-core';\nimport type { ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport { useColorFormat } from '#/contexts.ts';\nimport type { ColorFormat } from '#/format-color.ts';\nimport { perAxisAttrs } from '#/internal/data-attr.ts';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\nimport type { DetailToken } from '#/token-detail/internal.ts';\n\nexport interface AxisVarianceProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\ntype Variance =\n | { kind: 'constant' }\n | { kind: 'one-axis'; axis: string; varyingAxes: readonly [string] }\n | { kind: 'multi-axis'; varyingAxes: readonly [string, string, ...string[]] };\n\nexport function AxisVariance({ path }: AxisVarianceProps): ReactElement {\n const { token, cssVar, axes, activeAxes, cssVarPrefix, varianceByPath, resolveAt } =\n useTokenDetailData(path);\n const colorFormat = useColorFormat();\n const tokenType = token?.$type;\n const isColor = tokenType === 'color';\n const formatFn = (t: DetailToken | undefined): string => valueFor(t, tokenType, colorFormat);\n\n const variance = useMemo<Variance>(() => {\n // Read the pre-computed per-path variance from the snapshot. The\n // server side runs the bucket analysis once at load and ships the\n // map over the wire — O(1) lookup per render instead of an O(paths\n // × permutations) re-derivation here.\n const result = varianceByPath[path];\n if (!result) return { kind: 'constant' };\n switch (result.kind) {\n case 'constant':\n return { kind: 'constant' };\n case 'single':\n return { kind: 'one-axis', axis: result.axis, varyingAxes: result.varyingAxes };\n case 'multi':\n return { kind: 'multi-axis', varyingAxes: result.varyingAxes };\n default: {\n const exhaustive: never = result;\n throw new Error(`unhandled AxisVarianceResult kind: ${JSON.stringify(exhaustive)}`);\n }\n }\n }, [path, varianceByPath]);\n\n if (axes.length === 0) {\n return <></>;\n }\n\n if (variance.kind === 'constant') {\n const value = formatFn(resolveAt(activeAxes)[path] as DetailToken | undefined);\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Values across axes</div>\n <table className=\"sb-token-detail__theme-table\" data-testid=\"token-detail-values\">\n <tbody>\n <tr className=\"sb-token-detail__theme-row\">\n <td className=\"sb-token-detail__theme-cell\" data-testid=\"token-detail-constant\">\n {isColor && (\n <span\n className=\"sb-token-detail__swatch\"\n style={{ background: cssVar }}\n aria-hidden\n />\n )}\n {value}\n <span style={{ opacity: 0.6, marginLeft: 8 }}>same across every axis</span>\n </td>\n </tr>\n </tbody>\n </table>\n </>\n );\n }\n\n if (variance.kind === 'one-axis') {\n const axisName = variance.axis;\n const axis = axes.find((a) => a.name === axisName);\n if (!axis) return <></>;\n const contextValues = axis.contexts.map((ctx) => {\n const target = { ...activeAxes, [axisName]: ctx };\n return {\n ctx,\n target,\n value: formatFn(resolveAt(target)[path] as DetailToken | undefined),\n };\n });\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Varies with {axisName}</div>\n <table className=\"sb-token-detail__theme-table\" data-testid=\"token-detail-values\">\n <tbody>\n {contextValues.map((row) => (\n <tr\n key={row.ctx}\n className=\"sb-token-detail__theme-row\"\n data-axis={axisName}\n data-context={row.ctx}\n >\n <td className=\"sb-token-detail__theme-cell\" style={{ width: '30%' }}>\n {row.ctx}\n </td>\n <td className=\"sb-token-detail__theme-cell\">\n {isColor && (\n <span\n className=\"sb-token-detail__swatch\"\n style={{ background: cssVar }}\n {...perAxisAttrs(cssVarPrefix, row.target)}\n aria-hidden\n />\n )}\n {row.value}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </>\n );\n }\n\n const varying = variance.varyingAxes\n .map((name) => axes.find((a) => a.name === name))\n .filter((a): a is Axis => Boolean(a))\n .toSorted((a, b) => b.contexts.length - a.contexts.length);\n const [rowAxis, colAxis, ...extra] = varying;\n if (!rowAxis || !colAxis) return <></>;\n\n return (\n <>\n <div className=\"sb-token-detail__section-header\">\n Varies with {variance.varyingAxes.join(' × ')}\n </div>\n <table className=\"sb-token-detail__theme-table\" data-testid=\"token-detail-values\">\n <thead>\n <tr className=\"sb-token-detail__theme-row\">\n <th className=\"sb-token-detail__theme-cell\" style={{ textAlign: 'left', opacity: 0.7 }}>\n {rowAxis.name} \\ {colAxis.name}\n </th>\n {colAxis.contexts.map((col) => (\n <th\n key={col}\n className=\"sb-token-detail__theme-cell\"\n style={{ textAlign: 'left', opacity: 0.7 }}\n >\n {col}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rowAxis.contexts.map((row) => (\n <tr key={row} className=\"sb-token-detail__theme-row\">\n <td className=\"sb-token-detail__theme-cell\">{row}</td>\n {colAxis.contexts.map((col) => {\n const target: Record<string, string> = {\n ...activeAxes,\n [rowAxis.name]: row,\n [colAxis.name]: col,\n };\n const value = formatFn(resolveAt(target)[path] as DetailToken | undefined);\n return (\n <td\n key={col}\n className=\"sb-token-detail__theme-cell\"\n data-row={row}\n data-col={col}\n >\n {isColor && (\n <span\n className=\"sb-token-detail__swatch\"\n style={{ background: cssVar }}\n {...perAxisAttrs(cssVarPrefix, target)}\n aria-hidden\n />\n )}\n {value}\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n {extra.length > 0 && (\n <div className=\"sb-token-detail__aliased-by-truncated\" style={{ marginTop: 6 }}>\n Values also vary with {extra.map((a) => a.name).join(', ')}; matrix shows the slice for\n the active selection.\n </div>\n )}\n </>\n );\n}\n\nfunction valueFor(\n token: DetailToken | undefined,\n $type: string | undefined,\n format: ColorFormat,\n): string {\n if (!token) return '—';\n return formatTokenValue(token.$value, $type, format);\n}\n","import type { ReactElement } from 'react';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport type { ColorFormat } from '#/format-color.ts';\nimport type {\n BorderValue,\n GradientStop,\n ShadowLayer,\n TransitionValue,\n TypographyValue,\n} from '#/internal/composite-types.ts';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\nimport type { DetailToken } from '#/token-detail/internal.ts';\n\nexport interface CompositeBreakdownProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\nexport function CompositeBreakdown({ path }: CompositeBreakdownProps): ReactElement | null {\n const { token, resolved } = useTokenDetailData(path);\n const colorFormat = useColorFormat();\n if (!token) return null;\n return (\n <CompositeBreakdownContent\n type={token.$type}\n rawValue={token.$value}\n partialAliasOf={token.partialAliasOf}\n resolved={resolved}\n colorFormat={colorFormat}\n />\n );\n}\n\nexport function CompositeBreakdownContent({\n type,\n rawValue,\n partialAliasOf,\n resolved,\n colorFormat,\n}: {\n type: string | undefined;\n rawValue: unknown;\n partialAliasOf?: unknown;\n resolved?: Record<string, DetailToken>;\n colorFormat: ColorFormat;\n}): ReactElement | null {\n if (!rawValue || typeof rawValue !== 'object') return null;\n\n const objectAliases = pickObjectAliases(partialAliasOf);\n const arrayAliases = pickArrayAliases(partialAliasOf);\n const aliasFor = (key: string): readonly string[] | undefined =>\n subValueChain(objectAliases?.[key], resolved);\n\n if (type === 'typography') {\n const v = rawValue as TypographyValue;\n return renderKeyValueList([\n ['fontFamily', formatFontFamily(v.fontFamily), aliasFor('fontFamily')],\n ['fontSize', formatDimensionValue(v.fontSize), aliasFor('fontSize')],\n ['fontWeight', formatPrimitive(v.fontWeight), aliasFor('fontWeight')],\n ['lineHeight', formatPrimitive(v.lineHeight), aliasFor('lineHeight')],\n ['letterSpacing', formatDimensionValue(v.letterSpacing), aliasFor('letterSpacing')],\n ]);\n }\n\n if (type === 'border') {\n const v = rawValue as BorderValue;\n return renderKeyValueList([\n ['color', formatColorSubValue(v.color, colorFormat), aliasFor('color')],\n ['width', formatDimensionValue(v.width), aliasFor('width')],\n ['style', formatPrimitive(v.style), aliasFor('style')],\n ]);\n }\n\n if (type === 'transition') {\n const v = rawValue as TransitionValue;\n return renderKeyValueList([\n ['duration', formatDimensionValue(v.duration), aliasFor('duration')],\n ['timingFunction', formatPrimitive(v.timingFunction), aliasFor('timingFunction')],\n ['delay', formatDimensionValue(v.delay), aliasFor('delay')],\n ]);\n }\n\n if (type === 'shadow') {\n const layers = Array.isArray(rawValue) ? rawValue : [rawValue];\n const multi = layers.length > 1;\n const layerAliasFor = (i: number, key: string): readonly string[] | undefined =>\n subValueChain(arrayAliases?.[i]?.[key], resolved);\n return (\n <div className=\"sb-token-detail__breakdown-section\">\n {layers.map((layer, i) => {\n const v = layer as ShadowLayer;\n return (\n <div key={shadowLayerKey(v, i)} style={{ display: 'contents' }}>\n {multi && (\n <div className=\"sb-token-detail__breakdown-layer-header\">Layer {i + 1}</div>\n )}\n <KeyValueRow\n label=\"color\"\n value={formatColorSubValue(v.color, colorFormat)}\n alias={layerAliasFor(i, 'color')}\n />\n <KeyValueRow\n label=\"offsetX\"\n value={formatDimensionValue(v.offsetX)}\n alias={layerAliasFor(i, 'offsetX')}\n />\n <KeyValueRow\n label=\"offsetY\"\n value={formatDimensionValue(v.offsetY)}\n alias={layerAliasFor(i, 'offsetY')}\n />\n <KeyValueRow\n label=\"blur\"\n value={formatDimensionValue(v.blur)}\n alias={layerAliasFor(i, 'blur')}\n />\n <KeyValueRow\n label=\"spread\"\n value={formatDimensionValue(v.spread)}\n alias={layerAliasFor(i, 'spread')}\n />\n {v.inset !== undefined && (\n <KeyValueRow label=\"inset\" value={formatPrimitive(v.inset)} alias={undefined} />\n )}\n </div>\n );\n })}\n </div>\n );\n }\n\n if (type === 'gradient') {\n const stops = Array.isArray(rawValue) ? rawValue : [];\n if (stops.length === 0) return null;\n const stopAliasFor = (i: number): readonly string[] | undefined =>\n subValueChain(arrayAliases?.[i]?.['color'], resolved);\n return (\n <div className=\"sb-token-detail__breakdown-section\">\n {stops.map((stop, i) => {\n const v = stop as GradientStop;\n const position = typeof v.position === 'number' ? v.position : 0;\n return (\n <KeyValueRow\n key={gradientStopKey(v, i)}\n label={`${(position * 100).toFixed(0)}%`}\n value={formatColorSubValue(v.color, colorFormat)}\n alias={stopAliasFor(i)}\n />\n );\n })}\n </div>\n );\n }\n\n return null;\n}\n\nfunction renderKeyValueList(\n rows: [string, string | null, readonly string[] | undefined][],\n): ReactElement {\n return (\n <div className=\"sb-token-detail__breakdown-section\">\n {rows\n .filter(([, v, alias]) => v !== null || (alias && alias.length > 0))\n .map(([k, v, alias]) => (\n <KeyValueRow key={k} label={k} value={v ?? ''} alias={alias} />\n ))}\n </div>\n );\n}\n\nfunction KeyValueRow({\n label,\n value,\n alias,\n}: {\n label: string;\n value: string | null;\n alias: readonly string[] | undefined;\n}): ReactElement {\n const hasAlias = alias && alias.length > 0;\n return (\n <>\n <span className=\"sb-token-detail__breakdown-key\">{label}</span>\n <span className=\"sb-token-detail__breakdown-value\">\n <span>{value ?? '—'}</span>\n {hasAlias && (\n <span className=\"sb-token-detail__breakdown-alias\" data-testid=\"breakdown-alias\">\n {alias.map((p, i) => (\n <span key={p} className=\"sb-token-detail__breakdown-alias-step\">\n {i > 0 && <span className=\"sb-token-detail__arrow\">→</span>}\n <span className=\"sb-token-detail__chain-node\">{p}</span>\n </span>\n ))}\n </span>\n )}\n </span>\n </>\n );\n}\n\nfunction formatPrimitive(v: unknown): string | null {\n if (v == null) return null;\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return String(v);\n return JSON.stringify(v);\n}\n\nfunction formatFontFamily(v: unknown): string | null {\n if (v == null) return null;\n if (typeof v === 'string') return v;\n if (Array.isArray(v)) return v.map(String).join(', ');\n return JSON.stringify(v);\n}\n\nfunction formatDimensionValue(v: unknown): string | null {\n if (v == null) return null;\n if (typeof v === 'string' || typeof v === 'number') return String(v);\n if (typeof v === 'object') {\n const d = v as { value?: unknown; unit?: unknown };\n if (typeof d.value === 'number' && typeof d.unit === 'string') return `${d.value}${d.unit}`;\n }\n return JSON.stringify(v);\n}\n\n/**\n * Route sub-value colors through `formatColor` so they honor the active\n * color-format dropdown, just like the standalone `<ColorPalette />` and\n * `<TokenDetail />` top-line do. Returns `null` for a missing field so\n * the key/value row drops out entirely.\n */\nfunction formatColorSubValue(v: unknown, format: ColorFormat): string | null {\n if (v == null) return null;\n return formatColor(v, format).value;\n}\n\nfunction pickObjectAliases(v: unknown): Record<string, string | undefined> | undefined {\n if (!v || typeof v !== 'object' || Array.isArray(v)) return undefined;\n return v as Record<string, string | undefined>;\n}\n\nfunction pickArrayAliases(v: unknown): Record<string, string | undefined>[] | undefined {\n if (!Array.isArray(v)) return undefined;\n return v as Record<string, string | undefined>[];\n}\n\n/**\n * Walk the alias chain starting from an immediate sub-value alias target.\n * `aliasTarget` is the path the sub-value directly references; the target\n * token's own `aliasChain` continues the walk to the primitive.\n */\nfunction subValueChain(\n aliasTarget: string | undefined,\n resolved: Record<string, DetailToken> | undefined,\n): readonly string[] | undefined {\n if (!aliasTarget) return undefined;\n const tok = resolved?.[aliasTarget];\n const tail = tok?.aliasChain;\n return tail && tail.length > 0 ? [aliasTarget, ...tail] : [aliasTarget];\n}\n\nfunction shadowLayerKey(layer: ShadowLayer, fallback: number): string {\n const parts = [\n layer.color,\n layer.offsetX,\n layer.offsetY,\n layer.blur,\n layer.spread,\n layer.inset,\n ].map((p) => (p === undefined ? '' : JSON.stringify(p)));\n return `shadow|${parts.join('|')}|${fallback}`;\n}\n\nfunction gradientStopKey(stop: GradientStop, fallback: number): string {\n return `stop|${stop.position ?? fallback}|${JSON.stringify(stop.color)}`;\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { useEffect, useState } from 'react';\nimport { cssVarAsNumber } from '#/internal/css-var-style.ts';\nimport { usePrefersReducedMotion } from '#/internal/prefers-reduced-motion.ts';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\n\nexport interface CompositePreviewProps {\n /** Full dot-path of the token to preview. */\n path: string;\n}\n\nconst PANGRAM = 'Sphinx of black quartz, judge my vow.';\n\nconst STROKE_STYLE_STRINGS = new Set([\n 'solid',\n 'dashed',\n 'dotted',\n 'double',\n 'groove',\n 'ridge',\n 'outset',\n 'inset',\n]);\n\nexport function CompositePreview({ path }: CompositePreviewProps): ReactElement | null {\n const { token, cssVar } = useTokenDetailData(path);\n if (!token) return null;\n return <CompositePreviewContent type={token.$type} cssVar={cssVar} rawValue={token.$value} />;\n}\n\nexport function CompositePreviewContent({\n type,\n cssVar,\n rawValue,\n}: {\n type: string | undefined;\n cssVar: string;\n rawValue: unknown;\n}): ReactElement | null {\n if (type === 'typography') {\n const base = cssVar.replace(/^var\\(/, '').replace(/\\)$/, '');\n return (\n <div\n className=\"sb-token-detail__typography-sample\"\n style={{\n fontFamily: `var(${base}-font-family)`,\n fontSize: `var(${base}-font-size)`,\n fontWeight: cssVarAsNumber(`var(${base}-font-weight)`),\n lineHeight: cssVarAsNumber(`var(${base}-line-height)`),\n letterSpacing: `var(${base}-letter-spacing)`,\n }}\n >\n {PANGRAM}\n </div>\n );\n }\n if (type === 'shadow') {\n return (\n <div className=\"sb-token-detail__shadow-sample\" style={{ boxShadow: cssVar }} aria-hidden />\n );\n }\n if (type === 'border') {\n return (\n <div className=\"sb-token-detail__border-sample\" style={{ border: cssVar }} aria-hidden />\n );\n }\n if (type === 'transition') {\n return <TransitionSample transition={cssVar} />;\n }\n if (type === 'dimension') {\n return (\n <div className=\"sb-token-detail__dimension-track\">\n <div className=\"sb-token-detail__dimension-bar\" style={{ width: cssVar }} aria-hidden />\n </div>\n );\n }\n if (type === 'duration') {\n return <TransitionSample transition={`left ${cssVar} ease`} />;\n }\n if (type === 'fontFamily') {\n return (\n <div className=\"sb-token-detail__font-family-sample\" style={{ fontFamily: cssVar }}>\n {PANGRAM}\n </div>\n );\n }\n if (type === 'fontWeight') {\n return (\n <div\n className=\"sb-token-detail__font-weight-sample\"\n style={{ fontWeight: cssVarAsNumber(cssVar) }}\n >\n Aa\n </div>\n );\n }\n if (type === 'cubicBezier') {\n return <TransitionSample transition={`left 800ms ${cssVar}`} />;\n }\n if (type === 'gradient') {\n return (\n <div\n className=\"sb-token-detail__gradient-sample\"\n style={{ background: `linear-gradient(to right, ${cssVar})` }}\n aria-hidden\n />\n );\n }\n if (type === 'strokeStyle') {\n return <StrokeStylePreview value={rawValue} />;\n }\n if (type === 'color') {\n return (\n <div className=\"sb-token-detail__color-swatch-row\" aria-hidden>\n <div className=\"sb-token-detail__color-swatch-light\" style={{ background: cssVar }} />\n <div className=\"sb-token-detail__color-swatch-dark\" style={{ background: cssVar }} />\n </div>\n );\n }\n return null;\n}\n\nfunction StrokeStylePreview({ value }: { value: unknown }): ReactElement {\n if (typeof value === 'string' && STROKE_STYLE_STRINGS.has(value)) {\n return (\n <div\n className=\"sb-token-detail__stroke-style-line\"\n style={{ borderTopStyle: value as CSSProperties['borderTopStyle'] }}\n aria-hidden\n />\n );\n }\n if (value && typeof value === 'object' && 'dashArray' in value) {\n const v = value as {\n dashArray?: unknown;\n lineCap?: unknown;\n };\n const lengths = asDashLengths(v.dashArray);\n if (lengths.length === 0) {\n return (\n <div className=\"sb-token-detail__stroke-style-fallback\">\n Object-form strokeStyle with no resolvable dashArray.\n </div>\n );\n }\n const cap = typeof v.lineCap === 'string' ? v.lineCap : 'butt';\n return (\n <svg\n className=\"sb-token-detail__stroke-style-svg\"\n viewBox=\"0 0 220 24\"\n preserveAspectRatio=\"none\"\n aria-hidden\n >\n <line\n x1=\"4\"\n y1=\"12\"\n x2=\"216\"\n y2=\"12\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n strokeDasharray={lengths.join(' ')}\n strokeLinecap={cap as 'butt' | 'round' | 'square'}\n />\n </svg>\n );\n }\n return (\n <div className=\"sb-token-detail__stroke-style-fallback\">\n strokeStyle value could not be previewed.\n </div>\n );\n}\n\nfunction asDashLengths(raw: unknown): number[] {\n if (!Array.isArray(raw)) return [];\n const out: number[] = [];\n for (const entry of raw) {\n if (typeof entry === 'number') {\n out.push(entry);\n continue;\n }\n if (entry && typeof entry === 'object') {\n const e = entry as { value?: unknown };\n if (typeof e.value === 'number') out.push(e.value);\n }\n }\n return out;\n}\n\nfunction TransitionSample({ transition }: { transition: string }): ReactElement {\n const reduced = usePrefersReducedMotion();\n const [phase, setPhase] = useState<0 | 1>(0);\n\n useEffect(() => {\n if (reduced) return;\n const id = requestAnimationFrame(() => setPhase(1));\n const loop = window.setInterval(() => {\n setPhase((p) => (p === 0 ? 1 : 0));\n }, 1200);\n return () => {\n cancelAnimationFrame(id);\n window.clearInterval(loop);\n };\n }, [reduced]);\n\n if (reduced) {\n return (\n <div className=\"sb-token-detail__reduced-motion\">\n Animation suppressed by `prefers-reduced-motion: reduce`.\n </div>\n );\n }\n\n return (\n <div className=\"sb-token-detail__motion-track\">\n <div\n className=\"sb-token-detail__motion-ball\"\n style={{\n left: phase === 1 ? 'calc(100% - 28px)' : '4px',\n transition,\n }}\n aria-hidden\n />\n </div>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useState } from 'react';\nimport { useProject } from '#/internal/use-project.ts';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\n\nexport interface ConsumerOutputProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\nexport function ConsumerOutput({ path }: ConsumerOutputProps): ReactElement | null {\n const { token, cssVar, activeAxes } = useTokenDetailData(path);\n const { listing } = useProject();\n\n if (!token) return null;\n\n const tupleLabel = Object.entries(activeAxes)\n .map(([k, v]) => `${k}=${v}`)\n .join(', ');\n\n // Platforms beyond `css`. Populated only when the consumer has loaded\n // extra plugins (`@terrazzo/plugin-swift`, `-android`, `-sass`, …) via\n // `config.terrazzoPlugins` + `config.listingOptions.platforms`. Always\n // empty otherwise — the row set falls back to Path + CSS exactly like\n // before listing adoption.\n const names = listing[path]?.names ?? {};\n const extraPlatforms = Object.keys(names)\n .filter((platform) => platform !== 'css' && names[platform])\n .toSorted();\n\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Consumer output</div>\n {tupleLabel && (\n <div className=\"sb-token-detail__tuple-indicator\">\n Active tuple: <strong>{tupleLabel}</strong>\n </div>\n )}\n <OutputRow label=\"Path\" value={path} testId=\"consumer-output-path\" />\n <OutputRow label=\"CSS\" value={cssVar} testId=\"consumer-output-css\" />\n {extraPlatforms.map((platform) => (\n <OutputRow\n key={platform}\n label={formatPlatformLabel(platform)}\n value={names[platform]!}\n testId={`consumer-output-${platform}`}\n />\n ))}\n </>\n );\n}\n\nfunction formatPlatformLabel(platform: string): string {\n if (platform.length === 0) return platform;\n return platform[0]!.toUpperCase() + platform.slice(1);\n}\n\ninterface OutputRowProps {\n label: string;\n value: string;\n testId: string;\n}\n\nfunction OutputRow({ label, value, testId }: OutputRowProps): ReactElement {\n return (\n <div className=\"sb-token-detail__consumer-row\">\n <span className=\"sb-token-detail__consumer-row-label\">{label}</span>\n <code className=\"sb-token-detail__consumer-row-value\" data-testid={testId}>\n {value}\n </code>\n <CopyButton text={value} testId={`${testId}-copy`} />\n </div>\n );\n}\n\nfunction CopyButton({ text, testId }: { text: string; testId: string }): ReactElement {\n const [copied, setCopied] = useState(false);\n return (\n <button\n type=\"button\"\n className=\"sb-token-detail__consumer-row-copy\"\n data-testid={testId}\n onClick={() => {\n void copyToClipboard(text).then((ok) => {\n if (!ok) return;\n setCopied(true);\n window.setTimeout(() => setCopied(false), 1200);\n });\n }}\n >\n {copied ? 'Copied' : 'Copy'}\n </button>\n );\n}\n\nasync function copyToClipboard(text: string): Promise<boolean> {\n if (typeof navigator === 'undefined' || !navigator.clipboard) return false;\n try {\n await navigator.clipboard.writeText(text);\n return true;\n } catch {\n return false;\n }\n}\n","import type { ReactElement } from 'react';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\n\nexport interface TokenHeaderProps {\n /** Full dot-path of the token. */\n path: string;\n /** Override the heading. Defaults to the path. */\n heading?: string;\n}\n\nexport function TokenHeader({ path, heading }: TokenHeaderProps): ReactElement {\n const { token, cssVar, activeTheme } = useTokenDetailData(path);\n\n if (!token) {\n return (\n <div className=\"sb-token-detail__missing\">\n Token <code>{path}</code> not found in theme <strong>{activeTheme}</strong>.\n </div>\n );\n }\n\n return (\n <>\n <h3 className=\"sb-token-detail__heading\">{heading ?? path}</h3>\n <div className=\"sb-token-detail__subline\">\n {token.$type && <span className=\"sb-token-detail__type-pill\">{token.$type}</span>}\n <span>{cssVar}</span>\n </div>\n {token.$description && <p className=\"sb-token-detail__description\">{token.$description}</p>}\n </>\n );\n}\n","import type { ReactElement } from 'react';\nimport { CopyButton } from '#/internal/CopyButton.tsx';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\n\nexport interface TokenUsageSnippetProps {\n /** Full dot-path of the token. */\n path: string;\n}\n\nexport function TokenUsageSnippet({ path }: TokenUsageSnippetProps): ReactElement | null {\n const { token, cssVar } = useTokenDetailData(path);\n if (!token) return null;\n const snippet = `color: ${cssVar};`;\n return (\n <>\n <div className=\"sb-token-detail__section-header\">Usage</div>\n <div className=\"sb-token-detail__snippet-row\">\n <code className=\"sb-token-detail__snippet\">{snippet}</code>\n <CopyButton value={snippet} label={`Copy usage snippet ${snippet}`} />\n </div>\n </>\n );\n}\n","import cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport { useColorFormat } from '#/contexts.ts';\nimport { formatColor } from '#/format-color.ts';\nimport { CopyButton } from '#/internal/CopyButton.tsx';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { useProject } from '#/internal/use-project.ts';\nimport { AliasChain } from '#/token-detail/AliasChain.tsx';\nimport { AliasedBy } from '#/token-detail/AliasedBy.tsx';\nimport { AxisVariance } from '#/token-detail/AxisVariance.tsx';\nimport { CompositeBreakdown } from '#/token-detail/CompositeBreakdown.tsx';\nimport { CompositePreview } from '#/token-detail/CompositePreview.tsx';\nimport { ConsumerOutput } from '#/token-detail/ConsumerOutput.tsx';\nimport { TokenHeader } from '#/token-detail/TokenHeader.tsx';\nimport { TokenUsageSnippet } from '#/token-detail/TokenUsageSnippet.tsx';\nimport { useTokenDetailData } from '#/token-detail/internal.ts';\nimport '#/token-detail/styles.css';\n\nexport interface TokenDetailProps {\n /** Full dot-path of the token to inspect. */\n path: string;\n /** Override the heading. Defaults to the path. */\n heading?: string;\n}\n\nexport function TokenDetail({ path, heading }: TokenDetailProps): ReactElement {\n const { token, cssVar, activeTheme, activeAxes, cssVarPrefix } = useTokenDetailData(path);\n const colorFormat = useColorFormat();\n const theme = themeAttrs(cssVarPrefix, activeAxes);\n\n if (!token) {\n return (\n <div {...theme} className={cx(theme['className'], 'sb-token-detail')}>\n <div className=\"sb-token-detail__missing\">\n Token <code>{path}</code> not found in theme <strong>{activeTheme}</strong>.\n </div>\n </div>\n );\n }\n\n const { listing } = useProject();\n const isColor = token.$type === 'color';\n const gamut = isColor ? formatColor(token.$value, colorFormat) : null;\n const value = formatTokenValue(token.$value, token.$type, colorFormat, listing[path]);\n const outOfGamut = gamut?.outOfGamut ?? false;\n\n return (\n <div {...theme} className={cx(theme['className'], 'sb-token-detail')}>\n <TokenHeader path={path} {...(heading !== undefined && { heading })} />\n\n <div className=\"sb-token-detail__section-header\">Resolved value · {activeTheme}</div>\n <CompositePreview path={path} />\n <CompositeBreakdown path={path} />\n <div className=\"sb-token-detail__chain\">\n {isColor && (\n <span className=\"sb-token-detail__swatch\" style={{ background: cssVar }} aria-hidden />\n )}\n <span>{value}</span>\n {outOfGamut && (\n <span\n title=\"Out of sRGB gamut for this format\"\n aria-label=\"out of gamut\"\n style={{ marginLeft: 6 }}\n >\n ⚠\n </span>\n )}\n <CopyButton value={value} label={`Copy value ${value}`} />\n </div>\n\n <AliasChain path={path} />\n <AliasedBy path={path} />\n <TokenUsageSnippet path={path} />\n <ConsumerOutput path={path} />\n <AxisVariance path={path} />\n </div>\n );\n}\n","import type { KeyboardEvent as ReactKeyboardEvent, ReactElement } from 'react';\nimport { useEffect, useRef } from 'react';\nimport './DetailOverlay.css';\nimport { TokenDetail } from '#/TokenDetail.tsx';\n\n/**\n * Slide-over that wraps `<TokenDetail>`. Shared between `<TokenNavigator />`\n * and `<TokenTable />` so both land on the same opener and the same styling.\n *\n * Dismisses on backdrop click, Escape, and the close button. Implements the\n * WAI-ARIA dialog pattern's focus management: on mount, focus moves into the\n * panel; Tab is trapped so it cycles through the panel's interactive\n * descendants only; on unmount, focus restores to whatever opened the\n * overlay (typically the row / treeitem the user clicked).\n */\n\nexport interface DetailOverlayProps {\n path: string;\n onClose(): void;\n testId?: string;\n}\n\n/**\n * Selector for elements the trap considers focus stops. Mirrors the\n * \"tabbable\" set most focus-trap libraries use; the `:not(...)` clauses\n * skip the panel wrapper itself (we focus it manually on mount via its\n * own ref) and any explicitly-detabbed descendants.\n */\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(', ');\n\nexport function DetailOverlay({\n path,\n onClose,\n testId = 'swatchbook-overlay',\n}: DetailOverlayProps): ReactElement {\n const panelRef = useRef<HTMLDivElement | null>(null);\n const openerRef = useRef<HTMLElement | null>(null);\n\n // Set up focus management + sibling inerting in one effect so the\n // teardown ordering is explicit: un-inert siblings BEFORE restoring\n // focus to the opener (`.focus()` is a no-op on an inert element).\n //\n // `aria-modal=\"true\"` alone is widely known to be insufficient —\n // VoiceOver + NVDA virtual cursor + swipe gestures still pierce the\n // dialog and read sibling content behind the backdrop. Marking every\n // other top-level body branch `inert` while the overlay is mounted\n // closes that gap.\n useEffect(() => {\n const panel = panelRef.current;\n if (!panel) return;\n openerRef.current =\n document.activeElement instanceof HTMLElement ? document.activeElement : null;\n panel.focus();\n const overlayBranch = findBodyChildContaining(panel);\n const restorers: (() => void)[] = [];\n if (overlayBranch) {\n for (const sibling of Array.from(document.body.children)) {\n if (sibling === overlayBranch) continue;\n if (!(sibling instanceof HTMLElement)) continue;\n const hadInert = sibling.inert;\n sibling.inert = true;\n restorers.push(() => {\n sibling.inert = hadInert;\n });\n }\n }\n return () => {\n // Un-inert first — focusing an inert element is a no-op.\n for (const restore of restorers) restore();\n openerRef.current?.focus();\n };\n }, []);\n\n // Window-level Escape handler: works whether or not focus is currently\n // inside the panel (e.g. user clicked the backdrop, focus moved away).\n useEffect(() => {\n const onKey = (e: globalThis.KeyboardEvent): void => {\n if (e.key === 'Escape') onClose();\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [onClose]);\n\n /**\n * Wrap Tab inside the panel: from the last focusable, jump to the first;\n * from the first (or from the panel itself), Shift+Tab jumps to the last.\n * Defers to the browser otherwise.\n */\n const onPanelKeyDown = (e: ReactKeyboardEvent<HTMLDivElement>): void => {\n if (e.key !== 'Tab') return;\n const panel = panelRef.current;\n if (!panel) return;\n const focusables = panel.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR);\n if (focusables.length === 0) {\n e.preventDefault();\n return;\n }\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = document.activeElement;\n if (!first || !last) return;\n if (e.shiftKey) {\n if (active === first || active === panel) {\n e.preventDefault();\n last.focus();\n }\n } else if (active === last) {\n e.preventDefault();\n first.focus();\n }\n };\n\n return (\n <div\n className=\"sb-detail-overlay__backdrop\"\n onClick={onClose}\n role=\"presentation\"\n data-testid={testId}\n >\n <div\n ref={panelRef}\n className=\"sb-detail-overlay__panel\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={onPanelKeyDown}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`Token detail for ${path}`}\n tabIndex={-1}\n >\n <button\n type=\"button\"\n className=\"sb-detail-overlay__close\"\n onClick={onClose}\n aria-label=\"Close\"\n data-testid={`${testId}-close`}\n >\n ×\n </button>\n <TokenDetail path={path} />\n </div>\n </div>\n );\n}\n\n/**\n * Walk up from `node` to the direct child of `<body>` that contains it.\n * Returns `null` when the node isn't attached to the document (mid-mount,\n * post-unmount). Used to identify which top-level branch to *not* mark\n * inert when the overlay opens.\n */\nfunction findBodyChildContaining(node: HTMLElement): HTMLElement | null {\n let cursor: HTMLElement | null = node;\n while (cursor && cursor.parentElement !== document.body) {\n cursor = cursor.parentElement;\n }\n return cursor;\n}\n","import { fuzzyFilter } from '@unpunnyfuns/swatchbook-core/fuzzy';\nimport type { KeyboardEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport './TokenNavigator.css';\nimport { BorderSample } from '#/border-preview/BorderSample.tsx';\nimport { useColorFormat } from '#/contexts.ts';\nimport { DimensionBar } from '#/dimension-scale/DimensionBar.tsx';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { DetailOverlay } from '#/internal/DetailOverlay.tsx';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { EmptyState } from '#/internal/styles.tsx';\nimport { resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { MotionSample } from '#/motion-preview/MotionSample.tsx';\nimport { ShadowSample } from '#/shadow-preview/ShadowSample.tsx';\nimport type { VirtualToken } from '#/types.ts';\n\nexport interface TokenNavigatorProps {\n /** If provided, mount at this dot-path subtree and hide everything outside it. */\n root?: string;\n /**\n * Restrict the tree to tokens with the given DTCG `$type`(s). Pass a single\n * string to scope to one type (`type=\"color\"`), or an array for a narrow\n * small-multiples view (`type={['duration', 'cubicBezier', 'transition']}`).\n * Composes with `root` — both constraints must hold. Group nodes that end\n * up with no surviving leaves collapse out.\n */\n type?: string | readonly string[];\n /**\n * Depth (from the mounted root) that is expanded on first render.\n * `0` = everything collapsed, `1` = top-level groups open (default),\n * `2` = one level deeper, etc.\n */\n initiallyExpanded?: number;\n /**\n * Render a runtime search input above the tree. Matches are fuzzy\n * (case-insensitive, out-of-order terms, single-character typo\n * tolerance) against a leaf's token path; groups that contain no\n * matching leaves collapse out, and every group on the path to a\n * match auto-expands so hits are visible without clicking. Defaults\n * to `true`.\n */\n searchable?: boolean;\n /**\n * Called with a leaf's full dot-path when it is clicked. When set, the\n * inline `<TokenDetail>` slide-over is suppressed — the consumer owns\n * the follow-up UI.\n */\n onSelect?(path: string): void;\n}\n\ninterface LeafNode {\n kind: 'leaf';\n segment: string;\n path: string;\n token: VirtualToken;\n}\n\ninterface GroupNode {\n kind: 'group';\n segment: string;\n path: string;\n children: TreeNode[];\n}\n\ntype TreeNode = LeafNode | GroupNode;\n\nfunction buildTree(\n resolved: Record<string, VirtualToken>,\n root: string | undefined,\n typeFilter: ReadonlySet<string> | undefined,\n): TreeNode[] {\n const rootPrefix = root && root.length > 0 ? `${root}.` : '';\n const rootSegments = root ? root.split('.') : [];\n\n const entries = Object.entries(resolved).filter(([path, token]) => {\n if (root && !(path === root || path.startsWith(rootPrefix))) return false;\n if (typeFilter && !(token.$type && typeFilter.has(token.$type))) return false;\n return true;\n });\n\n const rootNode: GroupNode = { kind: 'group', segment: '', path: '', children: [] };\n\n for (const [path, token] of entries) {\n const remainder = root ? (path === root ? '' : path.slice(rootPrefix.length)) : path;\n const segments = remainder.length > 0 ? remainder.split('.') : [];\n\n let node: GroupNode = rootNode;\n for (let i = 0; i < segments.length - 1; i += 1) {\n const seg = segments[i];\n if (seg === undefined) continue;\n const prefix = [...rootSegments, ...segments.slice(0, i + 1)].join('.');\n let child = node.children.find(\n (c): c is GroupNode => c.kind === 'group' && c.segment === seg,\n );\n if (!child) {\n child = { kind: 'group', segment: seg, path: prefix, children: [] };\n node.children.push(child);\n }\n node = child;\n }\n\n const leafSegment = segments[segments.length - 1];\n if (leafSegment === undefined) {\n node.children.push({\n kind: 'leaf',\n segment: root ? (rootSegments[rootSegments.length - 1] ?? path) : path,\n path,\n token,\n });\n } else {\n node.children.push({ kind: 'leaf', segment: leafSegment, path, token });\n }\n }\n\n sortTree(rootNode);\n\n return rootNode.children;\n}\n\nfunction sortTree(node: GroupNode): void {\n node.children.sort((a, b) => {\n if (a.kind !== b.kind) return a.kind === 'group' ? -1 : 1;\n return a.segment.localeCompare(b.segment, undefined, { numeric: true });\n });\n for (const c of node.children) {\n if (c.kind === 'group') sortTree(c);\n }\n}\n\nfunction collectInitialExpanded(nodes: TreeNode[], remainingDepth: number, out: Set<string>): void {\n if (remainingDepth <= 0) return;\n for (const node of nodes) {\n if (node.kind !== 'group') continue;\n out.add(node.path);\n collectInitialExpanded(node.children, remainingDepth - 1, out);\n }\n}\n\nfunction countLeaves(node: TreeNode): number {\n if (node.kind === 'leaf') return 1;\n let n = 0;\n for (const c of node.children) n += countLeaves(c);\n return n;\n}\n\nfunction collectLeafPaths(nodes: TreeNode[], out: string[]): void {\n for (const node of nodes) {\n if (node.kind === 'leaf') out.push(node.path);\n else collectLeafPaths(node.children, out);\n }\n}\n\n/**\n * Flatten the currently-visible treeitems into the order screen-reader\n * users + arrow-key users navigate them: depth-first, only descending\n * into expanded groups. Each entry carries enough metadata for the\n * keyboard handler to compute parent / first-child / next / prev.\n */\ninterface FlatTreeItem {\n path: string;\n kind: 'group' | 'leaf';\n /** Dot-path of the parent group, or `null` for top-level entries. */\n parentPath: string | null;\n}\n\nfunction flattenVisible(\n nodes: TreeNode[],\n expanded: Set<string>,\n parentPath: string | null,\n out: FlatTreeItem[],\n): void {\n for (const node of nodes) {\n out.push({ path: node.path, kind: node.kind, parentPath });\n if (node.kind === 'group' && expanded.has(node.path)) {\n flattenVisible(node.children, expanded, node.path, out);\n }\n }\n}\n\n/**\n * Return a pruned copy of the tree keeping only leaves whose path is in\n * `matches`, plus the groups on the way to them. Every surviving group's\n * path is added to `expandOut` so callers can force those groups open.\n */\nfunction pruneTreeForMatches(\n nodes: TreeNode[],\n matches: ReadonlySet<string>,\n expandOut: Set<string>,\n): TreeNode[] {\n const out: TreeNode[] = [];\n for (const node of nodes) {\n if (node.kind === 'leaf') {\n if (matches.has(node.path)) out.push(node);\n } else {\n const children = pruneTreeForMatches(node.children, matches, expandOut);\n if (children.length > 0) {\n expandOut.add(node.path);\n out.push({ ...node, children });\n }\n }\n }\n return out;\n}\n\nexport function TokenNavigator({\n root,\n type,\n initiallyExpanded = 1,\n searchable = true,\n onSelect,\n}: TokenNavigatorProps): ReactElement {\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = useProject();\n\n const typeFilter = useMemo<ReadonlySet<string> | undefined>(() => {\n if (type === undefined) return undefined;\n return new Set(Array.isArray(type) ? type : [type]);\n }, [type]);\n\n const tree = useMemo(() => buildTree(resolved, root, typeFilter), [resolved, root, typeFilter]);\n\n const initialExpanded = useMemo(() => {\n const out = new Set<string>();\n collectInitialExpanded(tree, initiallyExpanded, out);\n return out;\n }, [tree, initiallyExpanded]);\n\n const [expanded, setExpanded] = useState<Set<string>>(initialExpanded);\n useEffect(() => {\n setExpanded(initialExpanded);\n }, [initialExpanded]);\n\n const [selectedPath, setSelectedPath] = useState<string | null>(null);\n const [query, setQuery] = useState('');\n\n const { visibleTree, searchExpanded } = useMemo(() => {\n if (!searchable || query.trim() === '') {\n return { visibleTree: tree, searchExpanded: null as Set<string> | null };\n }\n const leafPaths: string[] = [];\n collectLeafPaths(tree, leafPaths);\n const matches = new Set(fuzzyFilter(leafPaths, query, (p) => p));\n const expandOut = new Set<string>();\n const pruned = matches.size === 0 ? [] : pruneTreeForMatches(tree, matches, expandOut);\n return { visibleTree: pruned, searchExpanded: expandOut };\n }, [tree, query, searchable]);\n\n const effectiveExpanded = useMemo(() => {\n if (!searchExpanded) return expanded;\n const merged = new Set(expanded);\n for (const p of searchExpanded) merged.add(p);\n return merged;\n }, [expanded, searchExpanded]);\n\n const toggle = useCallback((path: string): void => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(path)) next.delete(path);\n else next.add(path);\n return next;\n });\n }, []);\n\n const handleLeafClick = useCallback(\n (path: string) => {\n if (onSelect) onSelect(path);\n else setSelectedPath(path);\n },\n [onSelect],\n );\n\n // WAI-ARIA tree pattern's roving tabindex — exactly one treeitem at a\n // time has tabIndex={0}; the rest are -1. Tab into / out of the tree\n // hits that one item; arrow keys move focus between items inside.\n const [focusedPath, setFocusedPath] = useState<string | null>(null);\n const treeItemRefs = useRef<Map<string, HTMLLIElement>>(new Map());\n const registerTreeItem = useCallback(\n (path: string) =>\n (el: HTMLLIElement | null): void => {\n if (el) treeItemRefs.current.set(path, el);\n else treeItemRefs.current.delete(path);\n },\n [],\n );\n\n const flatVisible = useMemo<FlatTreeItem[]>(() => {\n const out: FlatTreeItem[] = [];\n flattenVisible(visibleTree, effectiveExpanded, null, out);\n return out;\n }, [visibleTree, effectiveExpanded]);\n\n // Reset / repair focused path whenever the visible set changes. Keep\n // the existing focus if it's still visible; otherwise fall back to\n // the first item.\n useEffect(() => {\n if (flatVisible.length === 0) {\n setFocusedPath(null);\n return;\n }\n setFocusedPath((prev) => {\n if (prev && flatVisible.some((entry) => entry.path === prev)) return prev;\n return flatVisible[0]?.path ?? null;\n });\n }, [flatVisible]);\n\n const focusByPath = useCallback((path: string): void => {\n const node = treeItemRefs.current.get(path);\n if (node) {\n node.focus();\n setFocusedPath(path);\n } else {\n // Ref will register on the next render; flag the path so the\n // focus-repair effect can move focus once the node mounts.\n setFocusedPath(path);\n }\n }, []);\n\n // After expanding a group via Right-arrow, the new children mount on\n // the following render. If a path was queued via setFocusedPath but\n // the corresponding ref didn't exist at the time, repair focus now\n // that the children are live.\n useEffect(() => {\n if (focusedPath === null) return;\n const node = treeItemRefs.current.get(focusedPath);\n if (node && document.activeElement !== node) {\n // Only steal focus if it currently sits on a different treeitem\n // inside our tree — don't yank it away from the search input or\n // anything outside.\n const active = document.activeElement;\n const insideTree = active instanceof HTMLElement && active.closest('[role=\"tree\"]');\n if (insideTree) node.focus();\n }\n }, [focusedPath]);\n\n const handleTreeKeyDown = useCallback(\n (e: KeyboardEvent<HTMLUListElement>): void => {\n // Derive the active treeitem from `document.activeElement` rather\n // than the `focusedPath` state. State updates from `onFocus` may\n // not have flushed by the time a subsequent keydown fires (e.g.\n // tests that programmatically `.focus()` then immediately dispatch\n // keys), and the handler must always operate on the row the user\n // is currently on.\n if (flatVisible.length === 0) return;\n const active = document.activeElement;\n if (!(active instanceof HTMLLIElement)) return;\n const activePath = active.getAttribute('data-path');\n if (activePath === null) return;\n const currentIndex = flatVisible.findIndex((entry) => entry.path === activePath);\n if (currentIndex < 0) return;\n const current = flatVisible[currentIndex];\n if (!current) return;\n\n switch (e.key) {\n case 'ArrowDown': {\n const next = flatVisible[currentIndex + 1];\n if (next) {\n e.preventDefault();\n focusByPath(next.path);\n }\n return;\n }\n case 'ArrowUp': {\n const prev = flatVisible[currentIndex - 1];\n if (prev) {\n e.preventDefault();\n focusByPath(prev.path);\n }\n return;\n }\n case 'Home': {\n const first = flatVisible[0];\n if (first) {\n e.preventDefault();\n focusByPath(first.path);\n }\n return;\n }\n case 'End': {\n const last = flatVisible[flatVisible.length - 1];\n if (last) {\n e.preventDefault();\n focusByPath(last.path);\n }\n return;\n }\n case 'ArrowRight': {\n if (current.kind === 'group') {\n if (!effectiveExpanded.has(current.path)) {\n e.preventDefault();\n toggle(current.path);\n // Focus stays on the group — user can press Right again\n // to step into the first child on the next render.\n return;\n }\n // Already expanded: step into first child (which is the\n // next entry in the flattened list).\n const firstChild = flatVisible[currentIndex + 1];\n if (firstChild && firstChild.parentPath === current.path) {\n e.preventDefault();\n focusByPath(firstChild.path);\n }\n }\n return;\n }\n case 'ArrowLeft': {\n if (current.kind === 'group' && effectiveExpanded.has(current.path)) {\n e.preventDefault();\n toggle(current.path);\n return;\n }\n // Collapsed group or leaf: step to parent.\n if (current.parentPath !== null) {\n e.preventDefault();\n focusByPath(current.parentPath);\n }\n return;\n }\n case 'Enter':\n case ' ': {\n e.preventDefault();\n if (current.kind === 'group') toggle(current.path);\n else handleLeafClick(current.path);\n return;\n }\n default:\n return;\n }\n },\n [flatVisible, effectiveExpanded, toggle, focusByPath, handleLeafClick],\n );\n\n const typeLabel = typeFilter ? ` · ${[...typeFilter].map((t) => `$type=${t}`).join(', ')}` : '';\n const trimmedQuery = query.trim();\n // Must run every render — React's rules of hooks forbid the earlier empty-state\n // early return from skipping it, or the next non-empty render throws\n // \"Rendered fewer hooks than expected\".\n const matchCount = useMemo(() => {\n if (!searchExpanded) return 0;\n let n = 0;\n for (const node of visibleTree) n += countLeaves(node);\n return n;\n }, [visibleTree, searchExpanded]);\n\n if (tree.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <EmptyState>\n {root\n ? `No tokens under \"${root}\"${typeFilter ? ` matching ${typeLabel.slice(3)}` : ''}.`\n : typeFilter\n ? `No tokens matching ${typeLabel.slice(3)} in the active theme.`\n : 'No tokens in the active theme.'}\n </EmptyState>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n {searchable && (\n <div className=\"sb-token-navigator__search\">\n <input\n type=\"search\"\n className=\"sb-token-navigator__search-input\"\n placeholder=\"Search tokens…\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n aria-label=\"Search tokens by path\"\n data-testid=\"token-navigator-search\"\n />\n </div>\n )}\n <div className=\"sb-token-navigator__caption\">\n {root ? `Tokens under ${root}` : 'Token graph'}\n {typeLabel}\n {trimmedQuery !== '' ? ` · ${matchCount} matching \"${trimmedQuery}\"` : ''} · {activeTheme}\n </div>\n {searchable && (\n <span role=\"status\" aria-live=\"polite\" className=\"sb-token-navigator__sr-status\">\n {trimmedQuery !== '' ? `${matchCount} tokens matching \"${trimmedQuery}\"` : ''}\n </span>\n )}\n {visibleTree.length === 0 ? (\n <div className=\"sb-block__empty\">No tokens match \"{trimmedQuery}\".</div>\n ) : (\n <ul\n className=\"sb-token-navigator__tree\"\n role=\"tree\"\n aria-label=\"Token graph\"\n onKeyDown={handleTreeKeyDown}\n >\n {visibleTree.map((node, i) => (\n <TreeNodeRow\n key={node.path || node.segment}\n node={node}\n expanded={effectiveExpanded}\n focusedPath={focusedPath}\n registerTreeItem={registerTreeItem}\n onToggle={toggle}\n onFocusPath={setFocusedPath}\n onLeafClick={handleLeafClick}\n level={1}\n setsize={visibleTree.length}\n posinset={i + 1}\n />\n ))}\n </ul>\n )}\n\n {selectedPath !== null && (\n <DetailOverlay\n path={selectedPath}\n onClose={() => setSelectedPath(null)}\n testId=\"token-navigator-overlay\"\n />\n )}\n </div>\n );\n}\n\ninterface TreeNodeRowProps {\n node: TreeNode;\n expanded: Set<string>;\n focusedPath: string | null;\n registerTreeItem(path: string): (el: HTMLLIElement | null) => void;\n onToggle(path: string): void;\n onFocusPath(path: string): void;\n onLeafClick(path: string): void;\n /** 1-indexed depth in the tree (top-level = 1). */\n level: number;\n /** Number of siblings at this level (including self). */\n setsize: number;\n /** 1-indexed position among siblings. */\n posinset: number;\n}\n\nfunction TreeNodeRow({\n node,\n expanded,\n focusedPath,\n registerTreeItem,\n onToggle,\n onFocusPath,\n onLeafClick,\n level,\n setsize,\n posinset,\n}: TreeNodeRowProps): ReactElement {\n if (node.kind === 'leaf') {\n return (\n <LeafRow\n node={node}\n focusedPath={focusedPath}\n registerTreeItem={registerTreeItem}\n onFocusPath={onFocusPath}\n onLeafClick={onLeafClick}\n level={level}\n setsize={setsize}\n posinset={posinset}\n />\n );\n }\n const isOpen = expanded.has(node.path);\n const isFocused = focusedPath === node.path;\n return (\n <li\n ref={registerTreeItem(node.path)}\n role=\"treeitem\"\n aria-expanded={isOpen}\n aria-level={level}\n aria-setsize={setsize}\n aria-posinset={posinset}\n tabIndex={isFocused ? 0 : -1}\n onFocus={() => onFocusPath(node.path)}\n data-path={node.path}\n data-testid=\"token-navigator-group\"\n >\n {/*\n Click handler on the inner row div, not the <li>. Nested\n treeitems are DOM descendants of their parent <li>, so a\n click on a child row would bubble through each ancestor\n <li>'s onClick. The row div is a SIBLING of the nested\n <ul>, so child rows never bubble through it.\n */}\n <div\n className=\"sb-token-navigator__group-row\"\n data-testid=\"token-navigator-group-row\"\n onClick={() => {\n onFocusPath(node.path);\n onToggle(node.path);\n }}\n >\n <span className=\"sb-token-navigator__caret\" aria-hidden>\n {isOpen ? '▾' : '▸'}\n </span>\n <span>{node.segment}</span>\n <span className=\"sb-token-navigator__count\">{countLeaves(node)}</span>\n </div>\n {isOpen && (\n <ul className=\"sb-token-navigator__nested\" role=\"group\">\n {node.children.map((c, i) => (\n <TreeNodeRow\n key={c.path || c.segment}\n node={c}\n expanded={expanded}\n focusedPath={focusedPath}\n registerTreeItem={registerTreeItem}\n onToggle={onToggle}\n onFocusPath={onFocusPath}\n onLeafClick={onLeafClick}\n level={level + 1}\n setsize={node.children.length}\n posinset={i + 1}\n />\n ))}\n </ul>\n )}\n </li>\n );\n}\n\ninterface LeafRowProps {\n node: LeafNode;\n focusedPath: string | null;\n registerTreeItem(path: string): (el: HTMLLIElement | null) => void;\n onFocusPath(path: string): void;\n onLeafClick(path: string): void;\n /** 1-indexed depth in the tree (top-level = 1). */\n level: number;\n /** Number of siblings at this level (including self). */\n setsize: number;\n /** 1-indexed position among siblings. */\n posinset: number;\n}\n\nfunction LeafRow({\n node,\n focusedPath,\n registerTreeItem,\n onFocusPath,\n onLeafClick,\n level,\n setsize,\n posinset,\n}: LeafRowProps): ReactElement {\n const type = node.token.$type ?? '';\n const isFocused = focusedPath === node.path;\n return (\n <li\n ref={registerTreeItem(node.path)}\n role=\"treeitem\"\n aria-level={level}\n aria-setsize={setsize}\n aria-posinset={posinset}\n tabIndex={isFocused ? 0 : -1}\n onFocus={() => onFocusPath(node.path)}\n data-path={node.path}\n data-testid=\"token-navigator-leaf\"\n >\n {/* Click handler on the inner row div for the same reason as\n group rows — see TreeNodeRow. */}\n <div\n className=\"sb-token-navigator__leaf-row\"\n data-testid=\"token-navigator-leaf-row\"\n onClick={() => {\n onFocusPath(node.path);\n onLeafClick(node.path);\n }}\n >\n <span className=\"sb-token-navigator__caret\" aria-hidden>\n •\n </span>\n <span className=\"sb-token-navigator__tail\">{node.segment}</span>\n {type && <span className=\"sb-token-navigator__type-pill\">{type}</span>}\n <LeafPreview path={node.path} token={node.token} />\n </div>\n </li>\n );\n}\n\ninterface LeafPreviewProps {\n path: string;\n token: VirtualToken;\n}\n\nfunction LeafPreview({ path, token }: LeafPreviewProps): ReactElement {\n const project = useProject();\n const colorFormat = useColorFormat();\n const type = token.$type;\n\n if (type === 'color') {\n const cssVar = resolveCssVar(path, project);\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__value\">\n {formatTokenValue(token.$value, type, colorFormat, project.listing[path])}\n </span>\n <span\n className=\"sb-token-navigator__color-swatch\"\n style={{ background: cssVar }}\n aria-hidden\n />\n </span>\n );\n }\n if (type === 'dimension') {\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__value\">\n {formatTokenValue(token.$value, type, colorFormat, project.listing[path])}\n </span>\n <span className=\"sb-token-navigator__preview-dimension\">\n <DimensionBar path={path} kind=\"length\" />\n </span>\n </span>\n );\n }\n if (type === 'shadow') {\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__preview-scaled\">\n <ShadowSample path={path} />\n </span>\n </span>\n );\n }\n if (type === 'border') {\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__preview-scaled\">\n <BorderSample path={path} />\n </span>\n </span>\n );\n }\n if (type === 'transition' || type === 'duration' || type === 'cubicBezier') {\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__preview-motion\">\n <MotionSample path={path} />\n </span>\n </span>\n );\n }\n\n return (\n <span className=\"sb-token-navigator__preview-box\">\n <span className=\"sb-token-navigator__value\">\n {formatTokenValue(token.$value, type, colorFormat, project.listing[path])}\n </span>\n </span>\n );\n}\n","import { fuzzyFilter } from '@unpunnyfuns/swatchbook-core/fuzzy';\nimport cx from 'clsx';\nimport type { ReactElement } from 'react';\nimport { useCallback, useMemo, useState } from 'react';\nimport './TokenTable.css';\nimport { useColorFormat } from '#/contexts.ts';\nimport { CopyButton } from '#/internal/CopyButton.tsx';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { DetailOverlay } from '#/internal/DetailOverlay.tsx';\nimport { formatTokenValue } from '#/internal/format-token-value.ts';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\nimport { resolveColorValue, resolveCssVar, useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\n\nexport interface TokenTableProps {\n /**\n * Token-path filter. `\"color.*\"` matches every `color.…` token;\n * omit to include everything. Combines with `type` (both must match).\n */\n filter?: string;\n /** Restrict to one DTCG `$type`. */\n type?: string;\n /** Override the table caption. */\n caption?: string;\n /**\n * Sort order.\n * - `'path'` (default) — lexicographic on the dot-path.\n * - `'value'` — per-`$type`: numeric for `dimension` / `duration` /\n * `fontWeight`; perceptual (oklch L → C → H) for `color`; lexicographic\n * for `fontFamily` / `strokeStyle`. Composite types fall through to\n * path order.\n * - `'none'` — preserve project iteration order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n /**\n * Render a runtime search input above the table that narrows rows by\n * fuzzy match (case-insensitive, out-of-order terms, single-character\n * typo tolerance) against the token path, type, or value. Defaults to\n * `true` because browsing a multi-hundred-token reference without\n * search is painful. Pass `false` to hide the input (the `filter` /\n * `type` props still apply at authoring time).\n */\n searchable?: boolean;\n /**\n * Called with the clicked row's dot-path. When set, the built-in\n * `<TokenDetail>` slide-over is suppressed — the consumer owns the\n * follow-up UI (inline panel, drill-down route, …).\n */\n onSelect?(path: string): void;\n}\n\nexport function TokenTable({\n filter,\n type,\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n searchable = true,\n onSelect,\n}: TokenTableProps): ReactElement {\n const project = useProject();\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = project;\n const colorFormat = useColorFormat();\n const [selectedPath, setSelectedPath] = useState<string | null>(null);\n const [query, setQuery] = useState('');\n\n const rows = useMemo(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (!matchPath(path, filter)) return false;\n if (type && token.$type !== type) return false;\n return true;\n });\n const entries = sortTokens(filtered, { by: sortBy, dir: sortDir });\n return entries.map(([path, token]) => {\n const isColor = token.$type === 'color';\n const color = isColor ? resolveColorValue(path, token.$value, colorFormat, project) : null;\n return {\n path,\n type: token.$type ?? '',\n value: formatTokenValue(token.$value, token.$type, colorFormat, project.listing[path]),\n outOfGamut: color?.outOfGamut ?? false,\n cssVar: resolveCssVar(path, project),\n isColor,\n };\n });\n }, [resolved, filter, type, project, colorFormat, sortBy, sortDir]);\n\n const visibleRows = useMemo(() => {\n if (!searchable || query.trim() === '') return rows;\n return fuzzyFilter(rows, query, (row) => `${row.path} ${row.type} ${row.value}`);\n }, [rows, query, searchable]);\n\n const handleRowClick = useCallback(\n (path: string) => {\n if (onSelect) onSelect(path);\n else setSelectedPath(path);\n },\n [onSelect],\n );\n\n const matchSuffix =\n searchable && query.trim() !== '' ? ` · ${visibleRows.length} matching \"${query.trim()}\"` : '';\n const captionText =\n caption ??\n `${rows.length} token${rows.length === 1 ? '' : 's'}${\n filter ? ` matching \\`${filter}\\`` : ''\n }${type ? ` · $type=${type}` : ''}${matchSuffix} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n {searchable && (\n <div className=\"sb-token-table__search\">\n <input\n type=\"search\"\n className=\"sb-token-table__search-input\"\n placeholder=\"Search tokens…\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n aria-label=\"Fuzzy-search tokens by path, type, or value\"\n data-testid=\"token-table-search\"\n />\n </div>\n )}\n {searchable && (\n <span role=\"status\" aria-live=\"polite\" className=\"sb-token-table__sr-status\">\n {query.trim() !== ''\n ? `${visibleRows.length} of ${rows.length} tokens match \"${query.trim()}\"`\n : ''}\n </span>\n )}\n <table className=\"sb-token-table__table\">\n <caption className=\"sb-token-table__caption\">{captionText}</caption>\n <thead>\n <tr>\n <th className={cx('sb-token-table__th', 'sb-token-table__th--path')}>Path</th>\n <th className={cx('sb-token-table__th', 'sb-token-table__th--value')}>Value</th>\n </tr>\n </thead>\n <tbody>\n {visibleRows.length === 0 && (\n <tr>\n <td colSpan={2} className=\"sb-token-table__td sb-token-table__empty-row\">\n No tokens match \"{query.trim()}\".\n </td>\n </tr>\n )}\n {visibleRows.map((row) => (\n <tr\n key={row.path}\n className=\"sb-token-table__row\"\n onClick={() => handleRowClick(row.path)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleRowClick(row.path);\n }\n }}\n tabIndex={0}\n aria-haspopup=\"dialog\"\n aria-label={`Inspect ${row.path}`}\n data-testid=\"token-table-row\"\n data-path={row.path}\n >\n <td className={cx('sb-token-table__td', 'sb-token-table__path')}>{row.path}</td>\n <td className=\"sb-token-table__td\">\n <span className=\"sb-token-table__value-cell\">\n {row.type && <span className=\"sb-token-table__type-pill\">{row.type}</span>}\n {row.isColor && (\n <span\n className=\"sb-token-table__swatch\"\n style={{ background: row.cssVar }}\n aria-hidden\n />\n )}\n <span\n className=\"sb-token-table__value-text\"\n title={row.value}\n data-testid=\"token-table-value\"\n >\n {row.value}\n </span>\n {row.outOfGamut && (\n <span\n title=\"Out of sRGB gamut for this format\"\n aria-label=\"out of gamut\"\n className=\"sb-token-table__gamut-warn\"\n >\n ⚠\n </span>\n )}\n <span\n className=\"sb-token-table__copy-wrap\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n role=\"presentation\"\n >\n <CopyButton\n value={row.value}\n label={`Copy value ${row.value}`}\n className=\"sb-token-table__copy\"\n />\n </span>\n </span>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n\n {selectedPath !== null && (\n <DetailOverlay\n path={selectedPath}\n onClose={() => setSelectedPath(null)}\n testId=\"token-table-overlay\"\n />\n )}\n </div>\n );\n}\n","import type { CSSProperties, ReactElement } from 'react';\nimport { useMemo } from 'react';\nimport './TypographyScale.css';\nimport type { TypographyValue } from '#/internal/composite-types.ts';\nimport { themeAttrs } from '#/internal/data-attr.ts';\nimport { useProject } from '#/internal/use-project.ts';\nimport { matchPath } from '@unpunnyfuns/swatchbook-core/match-path';\nimport { sortTokens } from '#/internal/sort-tokens.ts';\nimport type { SortBy, SortDir } from '#/internal/sort-tokens.ts';\n\n/**\n * Dimension sub-values in DTCG 2025.10 use a `{ value, unit }` envelope\n * — narrow once here so the local `asDimension` helper doesn't need\n * to re-validate keys at every read.\n */\ninterface DimensionLike {\n value?: unknown;\n unit?: unknown;\n}\n\nexport interface TypographyScaleProps {\n /**\n * Token-path filter. Defaults to every `typography` token. Use e.g.\n * `\"typography.*\"` to scope to the semantic layer.\n */\n filter?: string;\n /** Override the sample text rendered for each token. */\n sample?: string;\n /** Override the caption. */\n caption?: string;\n /**\n * Sort order. `'path'` (default) sorts lexicographically on the\n * dot-path; `'value'` ordering falls through to path for this block's\n * type (composite / non-numeric); `'none'` preserves project order.\n */\n sortBy?: SortBy;\n /** `'asc'` (default) or `'desc'`. */\n sortDir?: SortDir;\n}\n\ninterface Row {\n path: string;\n sampleStyle: CSSProperties;\n specs: string;\n}\n\nfunction asDimension(raw: unknown): string | undefined {\n if (raw == null) return undefined;\n if (typeof raw === 'string' || typeof raw === 'number') return String(raw);\n if (typeof raw === 'object') {\n const v = raw as DimensionLike;\n if (v.value !== undefined && v.unit !== undefined) return `${String(v.value)}${String(v.unit)}`;\n }\n return undefined;\n}\n\nfunction asFontFamily(raw: unknown): string | undefined {\n if (typeof raw === 'string') return raw;\n if (Array.isArray(raw)) return raw.map(String).join(', ');\n return undefined;\n}\n\nfunction buildRow(path: string, composite: TypographyValue): Row {\n const fontFamily = asFontFamily(composite.fontFamily);\n const fontSize = asDimension(composite.fontSize);\n const fontWeight = composite.fontWeight == null ? undefined : String(composite.fontWeight);\n const lineHeight = composite.lineHeight == null ? undefined : String(composite.lineHeight);\n const letterSpacing = asDimension(composite.letterSpacing);\n\n const sampleStyle: CSSProperties = {};\n if (fontFamily) sampleStyle.fontFamily = fontFamily;\n if (fontSize) sampleStyle.fontSize = fontSize;\n if (fontWeight) sampleStyle.fontWeight = fontWeight as CSSProperties['fontWeight'];\n if (lineHeight) sampleStyle.lineHeight = lineHeight;\n if (letterSpacing) sampleStyle.letterSpacing = letterSpacing;\n\n const parts = [\n fontSize,\n fontWeight ? `w${fontWeight}` : undefined,\n lineHeight ? `lh ${lineHeight}` : undefined,\n ]\n .filter(Boolean)\n .join(' · ');\n\n return { path, sampleStyle, specs: parts };\n}\n\nexport function TypographyScale({\n filter,\n sample = 'The quick brown fox jumps over the lazy dog.',\n caption,\n sortBy = 'path',\n sortDir = 'asc',\n}: TypographyScaleProps): ReactElement {\n const { resolved, activeTheme, activeAxes, cssVarPrefix } = useProject();\n\n const rows = useMemo<Row[]>(() => {\n const filtered = Object.entries(resolved).filter(([path, token]) => {\n if (token.$type !== 'typography') return false;\n return matchPath(path, filter);\n });\n return sortTokens(filtered, { by: sortBy, dir: sortDir }).map(([path, token]) => {\n const value = token.$value;\n if (!value || typeof value !== 'object') {\n return { path, sampleStyle: {}, specs: '' };\n }\n return buildRow(path, value as TypographyValue);\n });\n }, [resolved, filter, sortBy, sortDir]);\n\n const captionText =\n caption ??\n `${rows.length} typography token${rows.length === 1 ? '' : 's'}${filter && filter !== 'typography' ? ` matching \\`${filter}\\`` : ''} · ${activeTheme}`;\n\n if (rows.length === 0) {\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__empty\">No typography tokens match this filter.</div>\n </div>\n );\n }\n\n return (\n <div {...themeAttrs(cssVarPrefix, activeAxes)}>\n <div className=\"sb-block__caption\">{captionText}</div>\n {rows.map((row) => (\n <div key={row.path} className=\"sb-typography-scale__row\">\n <div className=\"sb-typography-scale__meta\">\n <span className=\"sb-typography-scale__path\">{row.path}</span>\n {row.specs && <span className=\"sb-typography-scale__specs\">{row.specs}</span>}\n </div>\n <div style={row.sampleStyle}>{sample}</div>\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":"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"}