import { n as ColorFormat } from "./color-formats-BDDzxjy6.mjs"; import { Config, Logger, Plugin } from "@terrazzo/parser"; import { CSSPluginOptions } from "@terrazzo/plugin-css"; import { ListedToken, TokenListingPluginOptions } from "@terrazzo/plugin-token-listing"; //#region src/chrome.d.ts /** * Closed set of roles that swatchbook's block chrome reads. Each role emits * to a fixed `--swatchbook-` custom property that blocks reference * directly — independent of the project's `cssVarPrefix`, so there is zero * chance of the project's token namespace colliding with chrome reads. * * Consumers whose tokens don't happen to match these roles supply a * `chrome` config entry mapping each role to a token path in their own * tree; the CSS emitter appends `:root` aliases of the form * `--swatchbook-: var(---);`, so chrome reads resolve * through the alias to the consumer's tokens while per-theme value flips * ride through the target's existing per-theme emission. */ declare const CHROME_ROLES: readonly ["borderDefault", "surfaceDefault", "surfaceMuted", "surfaceRaised", "textDefault", "textMuted", "accentBg", "accentFg", "bodyFontFamily"]; type ChromeRole = (typeof CHROME_ROLES)[number]; /** * Hard-coded literal CSS values for each chrome role. Used as the baseline * for every project — the CSS emitter always declares all nine chrome vars, * starting from these defaults and overlaying any user-supplied `chrome` * entry as a `var(...)` reference on top. * * Single owned literal values. Swatchbook has no intrinsic dark axis, so the * zero-config default is one committed appearance; per-axis variation comes * from `config.chrome` mapping roles to the consumer's tokens. No * `light-dark()` or system colors — those couple to the OS color-scheme, * which is foreign to swatchbook's axis model. * * Values meet WCAG AA on their respective surfaces. Consumers theme chrome * against their own tokens by filling `config.chrome`. */ declare const DEFAULT_CHROME_MAP: Record; /** * The chrome defaults as a standalone `:root` stylesheet block. Shipped by the * blocks as a bundled base layer so `--swatchbook-*` is defined without the * addon. The emitter produces a superset of this (defaults + consumer * overrides) that wins via source order when the addon is present. */ declare function buildChromeDefaultsCss(): string; //#endregion //#region src/terrazzo-options.d.ts /** * Terrazzo lint configuration accepted on swatchbook's `Config`. Sourced from * Terrazzo's own `Config['lint']` rather than restated, so an upstream shape * change surfaces at typecheck rather than at runtime. */ type TerrazzoLintOptions = NonNullable; //#endregion //#region src/token-listing.d.ts /** * Token Listing data indexed by path for fast per-token lookup. Each entry * is the raw `ListedToken` emitted by `@terrazzo/plugin-token-listing` — * `$name`, `$type`, `$value`, `$extensions["app.terrazzo.listing"]` with * names / previewValue / originalValue / source.loc. * * Produced by `computeTokenListing`; attached to `Project.listing` when the * project is resolver-backed so downstream consumers can read authoritative * CSS var names and preview strings instead of re-deriving them. * * Accepted coupling: `ListedToken`'s shape comes straight from * `@terrazzo/plugin-token-listing`, which core depends on at an exact pin * (`"@terrazzo/plugin-token-listing": "0.1.1"`, not a range) precisely * because this type isn't insulated from it. Any upstream listing-format * change is a deliberate, coordinated bump here, not a silent break — * consumers who need insulation from that churn should read * `SlimListedToken` (`/snapshot-for-wire`) instead of this type directly. */ type TokenListingByPath = Record; //#endregion //#region src/token-graph/types.d.ts /** * A single per-(axis, context) overlay declaration. `literal` is a * concrete value; `alias` redirects to another path; `partial-alias` * blends a literal-fields base with per-sub-field alias targets. * * The `alias` arm intentionally carries no stored value. The walker * resolves `target` at the joint tuple at read time, so caching a value * here would be wrong — the resolved value depends on the full tuple and * may differ for every (axis, context) combination in flight. */ type WriteValue = { kind: 'literal'; value: SwatchbookToken; } | { kind: 'alias'; target: string; } | { kind: 'partial-alias'; baseValue: SwatchbookToken; aliasFields: Record; }; /** * Per-token-path node. JSON-serializable — no Map/Set in the wire * format. See the token-graph redesign spec for the design rationale. * * **Baseline fields** serve a dual purpose. `baselineValue` is always * the resolved leaf value at the default tuple — what consumers display * when they do not care about resolution shape (e.g. TokenTable showing * a resolved color). `baselineKind`, `baselineAliasTarget`, and * `baselinePartialFields` describe the structural shape the walker * follows when resolving at non-default tuples, where an axis write or * alias may steer through a different chain. The fields are kept separate * from `WriteValue` precisely because they serve both display (single * value) and walking (structure) — collapsing into a single * `baseline: WriteValue` would force every display call site to walk the * alias chain just to render a value. */ interface TokenGraphNode { baselineValue: SwatchbookToken; baselineKind: 'literal' | 'alias' | 'partial-alias'; baselineAliasTarget?: string; baselinePartialFields?: Record; /** * Per-(axis, context) overlay declarations keyed as * `writes[axisName][contextName]`. The outer key is the axis name * (e.g. `"mode"`); the inner key is the context name within that axis * (e.g. `"Dark"`). Only non-default contexts have entries — default * contexts produce no write and are absent from this record. */ writes: Record>; /** * Forward edges in the alias graph. The immediate target path(s) that * this token aliases at baseline. Typically zero or one entry; partial- * alias composites can have multiple sub-field targets. */ aliases: readonly string[]; /** * Reverse edges in the alias graph. Other token paths that alias TO * this token, scoped to the project. Note: this is distinct from * `SwatchbookToken.aliasedBy`, which is global to the parser and may * include paths outside the current project. */ aliasedBy: readonly string[]; /** * Derived axis-sensitivity index. The set of axis names whose writes — * direct or transitive through alias chains — can change this token's * resolved value at any tuple. Used by the walker's fast-path to * short-circuit resolution when no axis in the requested tuple is * relevant to this token. */ affectedBy: readonly string[]; } interface TokenGraph { nodes: Record; axes: readonly string[]; /** * Default context name per axis, keyed as * `axisDefaults[axisName] = defaultContextName`. Used by the walker's * fast-path and by `resolveAt` to fill in axes the caller omitted from * the requested tuple. */ axisDefaults: Record; /** * Per-axis context list, keyed by axis name. `axisContexts[axisName]` * is the ordered list of all context names for that axis, including * the default. Carries enough info for `getVariance` to iterate each * axis's contexts without needing the original `Axis[]` array. Wire * payload includes this so browser consumers can derive variance * shape from the graph alone. */ axisContexts: Record; } //#endregion //#region src/types.d.ts /** * Swatchbook's public token shape — the contract surfaced on * `Project.defaultTokens` and `Project.resolveAt()` output. A strict * subset of `@terrazzo/parser`'s `TokenNormalized`: the fields * downstream blocks actually read, no internals (`id`, `source`, * `originalValue`, `group`, `dependencies`, `$extensions`, `$extends`) * leaked through. * * Insulates swatchbook consumers from Terrazzo type churn: a future * `TokenNormalized` field rename or restructure won't ripple into the * `@unpunnyfuns/swatchbook-core` API surface. Assignable from * `TokenNormalized` by structural subtyping — internal core code can * pass resolver output straight into a `TokenMap` without casts. */ interface SwatchbookToken { $type?: string | undefined; $value?: unknown; $description?: string | undefined; /** * DTCG `$deprecated`, already group-inheritance-normalized per token by * the parser. `true` (deprecated, no message) or a string (deprecated, * with a message that typically points at the replacement). Surfaced as * a row indicator + strikethrough in TokenNavigator and a notice in * TokenDetail. */ $deprecated?: string | boolean | undefined; aliasOf?: string | undefined; aliasChain?: readonly string[] | undefined; aliasedBy?: readonly string[] | undefined; /** * Per-sub-field alias map for composite tokens whose value blends * primitives with aliased fragments. Shape varies per composite type; * typed as `unknown` so consumers narrow at the use-site. */ partialAliasOf?: unknown; } type TokenMap = Record; /** * Per-axis breakdown carried on every variance result — whether each * axis affects this token, and the stringified value seen in each of * its contexts (holding other axes at their defaults). */ type AxisVariancePerAxis = Record; }>; /** * Discriminated on `kind` so a `switch (result.kind)` narrows * `varyingAxes`'s cardinality and exposes the `axis: string` shortcut * on the single-axis variant. */ type AxisVarianceResult = { path: string; kind: 'constant'; varyingAxes: readonly []; constantAcrossAxes: readonly string[]; perAxis: AxisVariancePerAxis; } | { path: string; kind: 'single'; /** Convenience accessor — the sole varying axis, also at `varyingAxes[0]`. */ axis: string; varyingAxes: readonly [string]; constantAcrossAxes: readonly string[]; perAxis: AxisVariancePerAxis; } | { path: string; kind: 'multi'; varyingAxes: readonly [string, string, ...string[]]; constantAcrossAxes: readonly string[]; perAxis: AxisVariancePerAxis; }; /** * Compose the resolved `TokenMap` for any tuple of axis selections. * Graph-backed: walks `Project.tokenGraph` rather than re-running the * resolver. Accepts partial tuples (missing axes fall back to their * defaults) and memoizes on the canonical tuple key. */ type ResolveAt = (tuple: Record) => TokenMap; /** * One modifier axis of the theming model. Resolver-backed projects surface * one `Axis` per DTCG modifier; layered-config projects surface one `Axis` * per `axes[]` entry; projects without a resolver or layered config get a * single synthetic axis named `theme`. */ interface Axis { name: string; contexts: readonly string[]; default: string; description?: string; source: 'resolver' | 'layered' | 'synthetic'; } /** * A named quick-select combination of axis contexts. Rendered as a pill in * the toolbar. Any axis the preset omits falls back to that axis's * `default` when applied. */ interface Preset { name: string; /** axisName → contextName. Unknown keys or invalid values produce diagnostics and are sanitized. */ axes: Partial>; description?: string; } /** * One authored axis for layered configurations. Each context names an * ordered list of glob patterns / file paths (relative to cwd) that layer * on top of `Config.tokens` for that context. An empty array means "no * override" — valid, and common for a `Default` context. */ interface AxisConfig { name: string; description?: string; contexts: Record; default: string; } interface CommonConfig { /** * Initial active tuple (`{ axisName: contextName }`). Any axis the tuple * omits falls back to that axis's own `default`. Unknown axis keys or * invalid context values produce `warn` diagnostics and are sanitized. * When absent, the starting tuple is built from each axis's `default`. */ default?: Partial>; /** Prefix for emitted CSS custom properties. */ cssVarPrefix?: string; /** Project-local output directory for codegen artifacts. */ outDir?: string; /** Named tuple presets — rendered as quick-select pills in the toolbar. */ presets?: Preset[]; /** * Axis names to suppress from the toolbar and CSS emission. Each listed * axis is pinned to its `default` context: it disappears from * `Project.axes`, its tuples collapse into the default-context slice, and * emitted CSS drops it from the compound selector. Unknown names produce * `warn` diagnostics (group `swatchbook/disabled-axes`) and are ignored. * Config-level only — no runtime toggle. */ disabledAxes?: string[]; /** * Map from swatchbook block chrome roles (the closed set in `CHROME_PATHS` * — e.g. `color.surface.default`, `color.text.default`) to token paths in * the consumer's project. Each entry emits a `:root` alias * `--swatchbook-: var(---)`; blocks read the fixed * `--swatchbook-*` namespace directly, so the project's `cssVarPrefix` * never collides with chrome reads. * * Target var indirection means per-theme values flip automatically — no * per-theme override needed. Unknown role keys and target paths that * don't resolve in any theme produce `warn` diagnostics (group * `swatchbook/chrome`) and are dropped. Without a chrome map, blocks * fall back to the `Canvas` / `CanvasText` system colors. */ chrome?: Partial>; /** * Project-wide baseline for the block row-indicator strip (the * `` / `` per-row alias / variance / gamut / * deprecation / description glyphs). Known keys are `alias`, `variance`, * `gamut`, `deprecation`, `description`, `composes`; each maps to a * boolean. Sits between the hard-coded indicator defaults and a block's * own `indicators` prop — a per-block prop overrides this baseline. * * Typed loosely as `Record` so core stays free of a * blocks dependency; blocks narrows the keys at the use-site. */ indicators?: Readonly>; /** * Options forwarded to the `@terrazzo/plugin-css` instance swatchbook * runs internally (for the stylesheet it emits and for the Token * Listing's `names.css` derivation). Line this up with the consumer's * own `plugin-css` options — `legacyHex`, `transform`, `include`, * and similar — so docs-side names and values match what the * consumer's production build emits. * * `variableName` / `permutations` / `filename` / `skipBuild` are * managed internally and cannot be overridden — swatchbook's * axis-aware emission and in-memory listing capture depend on them. * Passing deprecated knobs (`baseSelector`, `baseScheme`, * `modeSelectors`) produces a `swatchbook/css-options` warn diagnostic * because they're superseded by permutations in newer plugin-css. */ cssOptions?: Omit; /** * Terrazzo lint configuration for swatchbook's internal parse pass, in the * same shape as `terrazzo.config.ts`'s `lint` field. Line this up with the * consumer's own lint config so `` reports the same pass/fail * state as their `terrazzo build`. * * Omitted, Terrazzo's recommended rules apply — which flag legacy * hex-string colors, among others. A project that allows those in its own * build needs * `lintOptions: { rules: { 'core/valid-color': ['error', { legacyFormat: true }] } }` * here to match. * * `rules` replaces Terrazzo's recommended set rather than merging into it — * any rule left out of a supplied `rules` object does not run. * * To keep one source of truth, import the Terrazzo config and forward its * `lint` field rather than restating rules. */ lintOptions?: TerrazzoLintOptions; /** * Options forwarded to `@terrazzo/plugin-token-listing`. Use * `platforms` to register additional platforms beyond `css` (e.g. * `swift`, `android`, `figma`) — each entry's `name` is a reference * to a loaded plugin. For the reference to resolve, that plugin has * to be loaded into the build, which is what `terrazzoPlugins` below * is for. * * `filename` is managed internally (the listing is captured in * memory, not written to disk). */ listingOptions?: Omit; /** * Additional Terrazzo plugins to load alongside swatchbook's own * `plugin-css` + `plugin-token-listing`. The listing can reference * any of these by name in its `platforms` map to derive per-platform * identifiers. Plugins whose outputs swatchbook doesn't consume are * simply ignored — they run, their files land in the in-memory * output set, nothing else happens. */ terrazzoPlugins?: readonly Plugin[]; /** * Maximum arity of joint-divergence detection per token. Joint * divergences are cases where the cartesian-correct value at a * multi-axis tuple differs from cascade composition of all lower-arity * blocks. Each such case emits a compound CSS selector * (`[data-axis-a="…"][data-axis-b="…"]…`) at emission time. * * Default `4`. Covers the largest joint shapes real-world design * systems tend to express (mode × brand × density × contrast). * * Bump if the design system has tokens with genuine 5+-axis joint * divergences — those tuples will otherwise resolve to the * cascade-composed value, which may be the wrong CSS variable * binding for the specific multi-axis combination. * * Lower if load-time work is a concern in projects with many * axes. Per-token probe work scales as * `Σ_{k=2..arity} C(|affectedBy|, k) × Π non-default contexts in combo`; * tokens affected by many axes including dense (large-context-count) * ones dominate. `1` disables joint-block emission entirely. * * @default 4 */ maxJointArity?: number; /** * Starting color format for blocks that display color values. This is * the lowest-precedence source in the chain: a block's own `colorFormat` * prop wins over wrapping the subtree in `ColorFormatContext`, which * wins over this project default. Defaults to `'hex'`. */ defaultColorFormat?: ColorFormat; } /** * Resolver-driven config — axes derived from a DTCG 2025.10 resolver * file's modifiers. `tokens` is optional: the resolver's own `$ref` * targets determine which files get loaded, and the addon's Vite * plugin derives HMR watch paths from the resolved source list. * Supplying `tokens` alongside `resolver` overrides the watch-path * derivation — useful when you want HMR to watch directories broader * than the resolver references directly. */ interface ResolverConfig extends CommonConfig { resolver: string; tokens?: string[]; /** Mutually exclusive with `resolver`. */ axes?: never; } /** * Layered-axes config — authored axes with per-context overlay globs * that layer onto the base `tokens`. The base `tokens` is required: * the layered loader needs a base layer to overlay against. */ interface LayeredConfig extends CommonConfig { axes: AxisConfig[]; tokens: string[]; /** Mutually exclusive with `axes`. */ resolver?: never; } /** * Plain-parse config — single synthetic axis (`theme`), no resolver, * no overlays. Just parses the `tokens` globs and exposes a one-cell * project. The fallback for the simplest "I just have token files" * case. */ interface PlainConfig extends CommonConfig { tokens: string[]; resolver?: never; axes?: never; } /** * Swatchbook configuration. Discriminated by which load-strategy * field is present: `resolver` (resolver-driven), `axes` (layered), * or neither (plain-parse). Invalid combinations (`resolver` + `axes`, * `axes` without `tokens`) are compile-time errors; the loader still * checks at runtime as defense-in-depth for JS callers that bypass * the type system. */ type Config$1 = ResolverConfig | LayeredConfig | PlainConfig; type DiagnosticSeverity = 'error' | 'warn' | 'info'; /** * A single problem or notice surfaced while loading or building a project. * Collected on `Project.diagnostics`; consumers render these as toolbar * badges, console output, or CLI exit-code triggers. * * `group` is a `swatchbook/` slug for swatchbook-originated * diagnostics (e.g. `swatchbook/chrome`, `swatchbook/disabled-axes`, * `swatchbook/css-options`, `swatchbook/listing`) or a bare Terrazzo group * name (`parser`, `resolver`, `plugin`, …) when the diagnostic is passed * through unchanged from the underlying `@terrazzo/parser` build. `filename` * and `line` are populated only when the diagnostic traces back to a * specific source location Terrazzo reported (a parse or resolver error); * swatchbook-originated diagnostics about config shape or runtime behavior * omit both. */ interface Diagnostic { severity: DiagnosticSeverity; /** Source group from Terrazzo (parser, resolver, plugin, …). */ group: string; /** * Originating rule or subsystem within `group`. Lint diagnostics carry the * rule id, which is the key `lintOptions.rules` takes, so this is what tells * a reader which rule to configure. Absent when Terrazzo emits no label. */ label?: string; message: string; filename?: string; line?: number; } /** * Loaded swatchbook project. Read any tuple via `project.resolveAt(tuple)`; * read the default-tuple snapshot directly via `project.defaultTokens`. * Walk the project's token resolution graph via `project.tokenGraph`. */ interface Project { config: Config$1; axes: readonly Axis[]; /** * Axis names suppressed via `config.disabledAxes`. Validated against the * resolver's axis list at load time — unknown names are dropped here and * surface as `warn` diagnostics. Downstream tooling (panels, blocks) can * read this to indicate that a modifier exists in the resolver but is * pinned to its default for this session. */ disabledAxes: readonly string[]; /** Validated + sanitized presets from `config.presets`. Empty if unset. */ presets: readonly Preset[]; /** * Validated chrome-alias map from `config.chrome`. Keys are members * of the closed `ChromeRole` set; values are token paths that resolve * in at least one permutation. Invalid entries from the raw config * are dropped and reported as diagnostics. Empty when the config * doesn't supply any. */ chrome: Partial>; /** Resolved tokens at the project's default tuple. Convenience for global views. */ defaultTokens: TokenMap; /** * The default tuple — `{ axisName: axis.default }` for every axis, * after `disabledAxes` filtering. */ defaultTuple: Record; /** * Compose the resolved `TokenMap` for any tuple of axis selections. * Graph-backed; memoized on the canonical tuple key. Partial tuples * are allowed — missing axes fall back to their defaults. */ resolveAt: ResolveAt; /** * Walkable token graph — the primary resolution data structure. * Consumers can query through it via the * `@unpunnyfuns/swatchbook-core/graph` subpath helpers (`resolveAllAt`, * `getVariance`, `listPaths`, etc.). */ tokenGraph: TokenGraph; /** * Absolute paths of every file loaded while building the project — * the resolver file (if any), every `$ref` target it pulled in, every * overlay file the layered loader concatenated, or every globbed file * the plain-parse fallback consumed. Consumers use this for file-watching * (the addon's Vite plugin does exactly that). */ sourceFiles: readonly string[]; /** * Absolute path of the directory all config-relative paths (resolver, * token globs, layered overlays) resolved against. Passed into * `loadProject(config, cwd)`; retained here because downstream emitters * need it for `defineConfig({ cwd })` in Terrazzo's JS API. */ cwd: string; /** * Path-indexed Token Listing data from `@terrazzo/plugin-token-listing`. * Each entry carries the plugin-css-authoritative var name under * `$extensions["app.terrazzo.listing"].names.css`, a `previewValue` * string, the original aliased value, and the source file + line range. * Empty when the project isn't resolver-backed (layered / plain-parse * paths don't run the build), or when the listing plugin errored. * * Treat as enrichment: consumers should fall back gracefully when a * given path is absent. */ listing: TokenListingByPath; diagnostics: Diagnostic[]; } /** * Display-side integration the Storybook addon exposes for a third-party * tool (Tailwind v4, emotion, vanilla-extract, bootstrap, whatever). * Each integration contributes at most one virtual module whose body is * derived from the loaded `Project`. The addon's Vite plugin serves the * virtual module under `integration.virtualModule.virtualId` and * re-renders it on HMR so the output stays in lockstep with whatever * the toolbar / config / tokens currently say. * * Integrations are published as their own packages * (`@unpunnyfuns/swatchbook-integrations/tailwind`, …) and composed into * the addon via its options; the addon itself stays tool-agnostic. */ interface SwatchbookIntegration { /** Stable identifier for logs + diagnostics. */ name: string; /** * Optional virtual module this integration serves. Users import * `virtualId` from their preview (or main) and receive whatever * `render(project)` produces for the current project state. */ virtualModule?: { /** e.g. `'virtual:swatchbook/tailwind.css'`. Must be unique. */virtualId: string; /** Produce the module body for the currently-loaded project. */ render(project: Project): string; /** * When `true`, the addon's preset auto-injects a side-effect import * (`import '';`) into the Storybook preview. Appropriate * for integrations that contribute global CSS (Tailwind's `@theme` * block, a stylesheet full of rules). Integrations exposing named * exports that consumers import per-site (e.g. `import { theme } * from '...'`) should leave this `false`. Defaults to `false`. */ autoInject?: boolean; }; } //#endregion export { DEFAULT_CHROME_MAP as C, ChromeRole as S, TokenGraph as _, Config$1 as a, TokenListingByPath as b, LayeredConfig as c, Project as d, ResolveAt as f, TokenMap as g, SwatchbookToken as h, AxisVarianceResult as i, PlainConfig as l, SwatchbookIntegration as m, AxisConfig as n, Diagnostic as o, ResolverConfig as p, AxisVariancePerAxis as r, DiagnosticSeverity as s, Axis as t, Preset as u, TokenGraphNode as v, buildChromeDefaultsCss as w, CHROME_ROLES as x, WriteValue as y }; //# sourceMappingURL=types-Cwn0Uyq2.d.mts.map