@weasel-js/theme 1.9.4 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -76,6 +76,38 @@ beside it. The resolved record carries that CSS as is, because a canvas has no
76
76
  `currentColor`; flatten it with `resolveCurrentColor(value, resolved['--wzl-fg'])`,
77
77
  passing the color of the text it is drawn beside.
78
78
 
79
+ ## Desktop themes
80
+
81
+ Each is a pins-only theme over the built-in one, on its own entry so an app
82
+ that never asks for it never loads it:
83
+
84
+ ```ts
85
+ import { applyTheme } from '@weasel-js/theme';
86
+ import { win9xTheme } from '@weasel-js/theme/themes/win9x';
87
+
88
+ applyTheme(document.documentElement, win9xTheme); // opens in light mode
89
+ ```
90
+
91
+ - `win9xTheme`: Windows 95 and 98. Gray faces in two-pixel bevels, square
92
+ corners, a navy-to-blue title strip, and the system sans at 11, 12, or 14px
93
+ by density.
94
+ - `platinumTheme`, from `@weasel-js/theme/themes/platinum`: Mac OS 8 and 9's
95
+ Platinum. Light gray faces with a black outline and a soft two-tone edge,
96
+ rounded buttons, white fields, and pinstriped window titles centered on the
97
+ strip. The same entry exports `classicMacTheme`, which it extends: the faces,
98
+ sizes, and geometry every classic Mac OS look shares, with no color of its
99
+ own. A System 7 theme is `defineTheme({ name, extends: classicMacTheme, pins })`
100
+ with that era's colors and edges.
101
+
102
+ They open in light mode, the only one the originals had; the dark mode is the
103
+ theme's own. The system faces are named first in the font stacks and are not
104
+ bundled, so a machine without them draws the next face in the stack. The
105
+ bevels and flat button faces are override hooks the theme pins (see below),
106
+ which the controls in `@weasel-js/ui` read wherever they draw a raised face, a
107
+ well, or a button that stays down; the description of each hook lists them.
108
+ To title every group as a window, wrap the app in
109
+ `<DefaultMotif motif={motifs.titlebar()}>` from `@weasel-js/ui`.
110
+
79
111
  ## The engine
80
112
 
81
113
  `@weasel-js/theme/engine` is for authoring layered theme definitions: seeds,
@@ -157,10 +189,11 @@ names the token bare (`"ref": "gray-800"`).
157
189
 
158
190
  ## Override hooks
159
191
 
160
- Ten custom properties resize kit components and **no theme declares them**:
161
- `--wzl-swatch-size`, `--wzl-timeline-label-w`, `--wzl-number-field-width` and
162
- the rest. Kit CSS reads each one with a fallback, so setting it on any
163
- container is what changes it, and leaving it alone takes the fallback:
192
+ Some custom properties restyle kit components and **the built-in theme does
193
+ not declare them**: `--wzl-swatch-size`, `--wzl-timeline-label-w`,
194
+ `--wzl-number-field-width` and the rest. Kit CSS reads each one with a
195
+ fallback, so setting it on any container is what changes it, and leaving it
196
+ alone takes the fallback:
164
197
 
165
198
  ```css
166
199
  .dense-panel { --wzl-swatch-size: 20px; --wzl-number-field-width: 6ch; }
@@ -175,6 +208,13 @@ import { TOKEN_MANIFEST } from '@weasel-js/theme';
175
208
  const hooks = TOKEN_MANIFEST.filter((t) => t.hook);
176
209
  ```
177
210
 
211
+ A theme built with `defineTheme` can pin one too, which is how a theme changes
212
+ what a token cannot say: `--wzl-bevel-raised`, `--wzl-bevel-sunken` and
213
+ `--wzl-bevel-pressed` are the box shadows of a raised face, a well and a pressed
214
+ button, and the `--wzl-button-*` hooks replace a Button's glass with a flat
215
+ face. A pin's value is fixed where the theme is applied, so one written with
216
+ `var()` does not follow a token a container overrides further down.
217
+
178
218
  They stay out of `tokens.css` on purpose. A `:root` value would outrank the
179
219
  fallback written beside every read, so the two would have to agree forever, and
180
220
  `npm run check:token-reads` would stop requiring that the fallback be there at
@@ -1,55 +1,6 @@
1
- import { isPlainObject } from '@weasel-js/registry';
1
+ import { pick, mergeAxes, fullSelection } from './chunk-P5F3GZV6.js';
2
2
  import { hexToOklchDeg, oklchDegToHex, hexToRgbBytes, parseHexBytes, srgbU8ToOklab } from '@weasel-js/paint';
3
3
 
4
- // src/axes.ts
5
- function isByAxis(v) {
6
- return isPlainObject(v) && typeof v.by === "string";
7
- }
8
- function fullSelection(axes, selection = {}) {
9
- const out = {};
10
- for (const [name, def] of Object.entries(axes)) {
11
- const v = selection[name];
12
- out[name] = v !== void 0 && v in def.values ? v : def.default;
13
- }
14
- return out;
15
- }
16
- function mergeAxes(parent, child) {
17
- const out = { ...parent };
18
- for (const [name, def] of Object.entries(child)) {
19
- out[name] = { ...def, values: { ...parent[name]?.values, ...def.values } };
20
- }
21
- return out;
22
- }
23
- function enumerateSelections(axes) {
24
- let out = [{}];
25
- for (const [name, def] of Object.entries(axes)) {
26
- out = out.flatMap((s) => Object.keys(def.values).map((v) => ({ ...s, [name]: v })));
27
- }
28
- return out;
29
- }
30
- function selectionKey(axes, selection) {
31
- const full = fullSelection(axes, selection);
32
- return Object.keys(axes).map((a) => `${a}=${full[a]}`).join(",");
33
- }
34
- function pick(v, selection) {
35
- let cur = v;
36
- while (isByAxis(cur)) {
37
- const axis = cur.by;
38
- const value = selection[axis];
39
- if (value === void 0 || value === "by" || !(value in cur)) return { ok: false, axis, value: value ?? "" };
40
- cur = cur[value];
41
- }
42
- return { ok: true, value: cur };
43
- }
44
- function pickAll(record, selection) {
45
- const out = {};
46
- for (const [name, v] of Object.entries(record)) {
47
- const picked = pick(v, selection);
48
- if (picked.ok) out[name] = picked.value;
49
- }
50
- return out;
51
- }
52
-
53
4
  // src/dtcg/value.ts
54
5
  function fontStack(value) {
55
6
  return value.map((f) => typeof f === "string" && /\s/.test(f) ? `'${f}'` : String(f)).join(", ");
@@ -337,7 +288,6 @@ function searchHues(c) {
337
288
  const anchorHexes = c.anchors.map(toHexPreview);
338
289
  const freeCount = c.count - c.anchors.length;
339
290
  if (freeCount < 0) return null;
340
- if (freeCount === 0) return [];
341
291
  const weighted = (hex) => {
342
292
  const [L, a, b] = toLab(hex);
343
293
  return [L, CHROMA_WEIGHT * a, CHROMA_WEIGHT * b];
@@ -411,6 +361,7 @@ function searchHues(c) {
411
361
  const m = metaFor(free);
412
362
  return m.reduce((sum, x) => sum + x.chroma, 0) / m.length;
413
363
  };
364
+ if (freeCount === 0) return penalty([]) > 0 ? null : [];
414
365
  const seeds = [];
415
366
  const seedStep = Math.max(6, Math.round(freeCount * 1.6));
416
367
  for (let start = 0; start < 360; start += seedStep) {
@@ -581,6 +532,6 @@ function anchorFromHex(hex, name) {
581
532
  };
582
533
  }
583
534
 
584
- export { CHROMA_WEIGHT, DEFAULT_CONSTRAINTS, anchorFromHex, atAlpha, chromaCap, contrast, deltaE, enumerateSelections, floorDegrees, fullSelection, generate, hexToRgb, hueGap, hueName, isByAxis, luminance, mergeAxes, mixAlpha, parseTokenValue, pick, pickAll, resolveTheme, resolveTokens, selectionKey, serializeTokenValue, themeAxes, themeChain, toHex, toHexPreview, toLab, toLch, tokenAt, tokensAt, vividAt, withAlpha };
585
- //# sourceMappingURL=chunk-7LCRXZDY.js.map
586
- //# sourceMappingURL=chunk-7LCRXZDY.js.map
535
+ export { CHROMA_WEIGHT, DEFAULT_CONSTRAINTS, anchorFromHex, atAlpha, chromaCap, contrast, deltaE, floorDegrees, generate, hexToRgb, hueGap, hueName, luminance, mixAlpha, parseTokenValue, resolveTheme, resolveTokens, serializeTokenValue, themeAxes, themeChain, toHex, toHexPreview, toLab, toLch, tokenAt, tokensAt, vividAt, withAlpha };
536
+ //# sourceMappingURL=chunk-2PY2YTDY.js.map
537
+ //# sourceMappingURL=chunk-2PY2YTDY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dtcg/value.ts","../src/chainTokens.ts","../src/dtcg/color.ts","../src/dtcg/resolve.ts","../src/resolveTheme.ts","../src/engine/color/oklch.ts","../src/engine/color/generate.ts"],"names":[],"mappings":"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","file":"chunk-2PY2YTDY.js","sourcesContent":["import type { TokenValue } from './types.ts';\n\n/**\n * Quote family names containing whitespace; leave everything else bare.\n * Generic keywords (`sans-serif`) and hyphen-prefixed identifiers\n * (`-apple-system`) break if quoted, and neither contains a space.\n */\nfunction fontStack(value: readonly (string | number)[]): string {\n return value.map((f) => (typeof f === 'string' && /\\s/.test(f) ? `'${f}'` : String(f))).join(', ');\n}\n\n/**\n * A token's value as CSS renders it. A DTCG value is not always a string: a\n * `fontFamily` is a list of names and a `cubicBezier` is four numbers, and both\n * have a spelling that belongs in a stylesheet rather than in JSON.\n */\nexport function serializeTokenValue(type: string, value: TokenValue): string {\n if (Array.isArray(value)) {\n if (type === 'cubicBezier') return `cubic-bezier(${value.join(', ')})`;\n if (type === 'fontFamily') return fontStack(value);\n return value.join(', ');\n }\n return String(value);\n}\n\nconst BEZIER = /^cubic-bezier\\(\\s*([^)]*)\\)$/i;\n\n/**\n * The inverse of {@link serializeTokenValue}: text a person edited, back in the\n * shape a definition stores. Text that does not parse for its type is kept as\n * text rather than thrown away, so a half-typed value stays editable.\n */\nexport function parseTokenValue(type: string, text: string): TokenValue {\n const raw = text.trim();\n if (type === 'cubicBezier') {\n const inner = BEZIER.exec(raw)?.[1] ?? raw;\n const parts = inner.split(',').map((p) => Number(p.trim()));\n return parts.length === 4 && parts.every((n) => Number.isFinite(n)) ? parts : raw;\n }\n if (type === 'fontFamily') {\n const families = raw\n .split(',')\n .map((f) => f.trim().replace(/^['\"]|['\"]$/g, '').trim())\n .filter((f) => f !== '');\n return families.length > 0 ? families : raw;\n }\n return raw;\n}\n","import { fullSelection, mergeAxes, pick, type AxisDefs, type Selection, type Varying } from './axes.ts';\nimport type { FlatTokens, RawToken } from './dtcg/types.ts';\n\n/** One theme of an `extends` chain, as far as choosing its tokens goes. */\nexport interface ChainLink {\n readonly axes: AxisDefs;\n readonly tokens: Readonly<Record<string, Varying<RawToken>>>;\n}\n\n/**\n * The selection each theme of a root-first chain reads its own tokens at. An axis value a theme and\n * everything it extends never declared (one a descendant added) becomes that theme's default for the\n * axis, which is what the stylesheet's cascade gives it: no block of the ancestor matches the new\n * value, so its default declarations show through.\n */\nfunction localSelections(chain: readonly ChainLink[], selection: Selection): Selection[] {\n let axes: AxisDefs = {};\n return chain.map((link) => {\n axes = mergeAxes(axes, link.axes);\n return { ...selection, ...fullSelection(axes, selection) };\n });\n}\n\n/** `name` from the nearest theme of a root-first chain that has it at `selection`. */\nexport function tokenAt(chain: readonly ChainLink[], name: string, selection: Selection): RawToken | undefined {\n const local = localSelections(chain, selection);\n for (let i = chain.length - 1; i >= 0; i--) {\n const { tokens } = chain[i];\n if (!Object.hasOwn(tokens, name)) continue;\n const picked = pick(tokens[name], local[i]);\n if (picked.ok) return picked.value;\n }\n return undefined;\n}\n\n/** Every token of a root-first chain at `selection`, each from the nearest theme that has it there. */\nexport function tokensAt(chain: readonly ChainLink[], selection: Selection): FlatTokens {\n const local = localSelections(chain, selection);\n const out: Record<string, RawToken> = {};\n chain.forEach((link, i) => {\n for (const [name, v] of Object.entries(link.tokens)) {\n const picked = pick(v, local[i]);\n if (picked.ok) out[name] = picked.value;\n }\n });\n return out;\n}\n","import { parseHexBytes } from '@weasel-js/paint';\n\n/**\n * A resolved color at `alpha`, multiplied into any alpha it already carries. The\n * JS side of the alpha extension; the CSS side emits `color-mix()` instead so DOM\n * chrome keeps tracking a downstream override of the referenced token.\n *\n * Hex and `rgb()`/`rgba()` become an `rgba()` literal. Anything else — a named\n * color, `hsl()`, `oklch()`, a `var()` — becomes the same `color-mix()` the CSS\n * side writes, which the browser resolves.\n */\nexport function withAlpha(color: string, alpha: number): string {\n const rgba = parseRgba(color.trim());\n if (!rgba) return mixAlpha(color.trim(), alpha);\n const [r, g, b, a] = rgba;\n return `rgba(${r}, ${g}, ${b}, ${round(a * alpha, 3)})`;\n}\n\n/** `color` at `alpha` as a `color-mix()` with transparent, for a color only the browser can resolve. */\nexport function mixAlpha(color: string, alpha: number): string {\n return `color-mix(in srgb, ${color} ${round(alpha * 100, 4)}%, transparent)`;\n}\n\n/** A resolved color with its alpha replaced by `alpha`, as `rgb(from c r g b / alpha)` computes it. */\nexport function atAlpha(color: string, alpha: number): string {\n const rgba = parseRgba(color.trim());\n if (!rgba) return `rgb(from ${color.trim()} r g b / ${alpha})`;\n const [r, g, b] = rgba;\n return `rgba(${r}, ${g}, ${b}, ${round(alpha, 3)})`;\n}\n\ntype Rgba = [number, number, number, number];\n\nfunction round(n: number, places: number): number {\n return Number(n.toFixed(places));\n}\n\nfunction parseRgba(s: string): Rgba | null {\n if (s.toLowerCase() === 'transparent') return [0, 0, 0, 0];\n return parseHex(s) ?? parseRgbFn(s);\n}\n\nfunction parseHex(s: string): Rgba | null {\n const bytes = parseHexBytes(s);\n return bytes && [bytes[0], bytes[1], bytes[2], bytes[3] / 255];\n}\n\nfunction parseRgbFn(s: string): Rgba | null {\n const m = /^rgba?\\(([^()]*)\\)$/i.exec(s);\n if (!m) return null;\n const [channels, alphaPart, extra] = m[1].split('/');\n if (extra !== undefined) return null;\n const parts = channels.trim().split(/\\s*,\\s*|\\s+/);\n if (alphaPart !== undefined) parts.push(alphaPart.trim());\n if (parts.length !== 3 && parts.length !== 4) return null;\n\n const channel = (p: string) => (p.endsWith('%') ? (Number.parseFloat(p) / 100) * 255 : Number(p));\n const alpha = (p: string) => (p.endsWith('%') ? Number.parseFloat(p) / 100 : Number(p));\n const [r, g, b] = parts.slice(0, 3).map(channel);\n const a = parts[3] === undefined ? 1 : alpha(parts[3]);\n if (![r, g, b, a].every(Number.isFinite)) return null;\n return [Math.round(r), Math.round(g), Math.round(b), a];\n}\n","import { withAlpha } from './color.ts';\nimport type { FlatTokens, ResolvedTokenMap, TokenValue } from './types.ts';\nimport { serializeTokenValue } from './value.ts';\n\n/** `{color.gray-100}` → `gray-100`. The type group is dropped, per the naming rule. */\nconst REF = /^\\{([^}]+)\\}$/;\n\nfunction refTarget(value: TokenValue): string | null {\n if (typeof value !== 'string') return null;\n const m = REF.exec(value.trim());\n if (!m) return null;\n const path = m[1];\n const dot = path.indexOf('.');\n return dot === -1 ? path : path.slice(dot + 1);\n}\n\n/**\n * Resolve flat tokens to final CSS-ready strings.\n *\n * Merge modes before calling: this function has no notion of modes, only of a\n * complete token set.\n */\nexport function resolveTokens(tokens: FlatTokens): ResolvedTokenMap {\n const out: ResolvedTokenMap = {};\n const inProgress = new Set<string>();\n\n const resolveOne = (name: string): string => {\n const cached = out[name];\n if (cached !== undefined) return cached;\n\n const token = tokens[name];\n if (!token) throw new Error(`Unknown token \"${name}\"`);\n\n if (inProgress.has(name)) {\n throw new Error(`Reference cycle at token \"${name}\" (${[...inProgress].join(' → ')})`);\n }\n inProgress.add(name);\n\n const target = refTarget(token.value);\n let value: string;\n if (target === null) {\n value = serializeTokenValue(token.type, token.value);\n } else if (!tokens[target]) {\n throw new Error(`Token \"${name}\" references \"${target}\", which is not defined`);\n } else {\n value = resolveOne(target);\n }\n\n if (token.alpha !== undefined) value = withAlpha(value, token.alpha);\n\n inProgress.delete(name);\n out[name] = value;\n return value;\n };\n\n for (const name of Object.keys(tokens)) resolveOne(name);\n return out;\n}\n\n/** Merge a mode's tokens over the mode-invariant set. Later wins. */\nexport function mergeTokens(base: FlatTokens, mode: FlatTokens): FlatTokens {\n return { ...base, ...mode };\n}\n","import { fullSelection, mergeAxes, type AxisDefs, type Selection } from './axes.ts';\nimport { tokensAt } from './chainTokens.ts';\nimport { resolveTokens } from './dtcg/resolve.ts';\nimport type { TokenName } from './generated/themes.ts';\nimport type { Theme } from './theme.ts';\n\n/** The output of `resolveTheme`: every token of a theme, for one selection, keyed\n * by CSS custom-property name and flattened to a final CSS value. */\nexport type ResolvedTheme = Readonly<Record<TokenName, string>>;\n\n/** Root-first, so the leaf theme's tokens land last. */\nexport function themeChain(theme: Theme): Theme[] {\n const out: Theme[] = [];\n for (let t: Theme | null = theme; t; t = t.extends) out.unshift(t);\n return out;\n}\n\n/** Every axis the chain declares. An axis declared more than once keeps every value; a descendant's value entries and default win. */\nexport function themeAxes(theme: Theme): AxisDefs {\n return themeChain(theme).reduce<AxisDefs>((axes, t) => mergeAxes(axes, t.axes), {});\n}\n\n/**\n * Merge the extends chain at a selection, resolve every alias, and key the\n * result by CSS custom-property name. A missing or unknown axis value takes the\n * axis default, and a theme in the chain reads a value it never declared at its\n * own default for that axis.\n *\n * Pure — no DOM. An unresolvable reference throws rather than falling back.\n */\nexport function resolveTheme(theme: Theme, selection: Selection = {}): ResolvedTheme {\n const sel = fullSelection(themeAxes(theme), selection);\n const out: Record<string, string> = {};\n for (const [name, value] of Object.entries(resolveTokens(tokensAt(themeChain(theme), sel)))) out[`--wzl-${name}`] = value;\n return out as ResolvedTheme;\n}\n","import { hexToOklchDeg, hexToRgbBytes, oklchDegToHex, srgbU8ToOklab, type OklchDeg } from '@weasel-js/paint';\n\n/** A color in OKLCH: lightness 0–1, chroma, hue in degrees. paint's own type,\n * under the name this engine has always called it. */\nexport type Lch = OklchDeg;\n\n/** A hex color to 0–255 channels, its alpha dropped. Throws on anything else. */\nexport const hexToRgb: (hex: string) => [number, number, number] = hexToRgbBytes;\n\n/** OKLCH (lightness 0–1, chroma, hue in degrees) to `#rrggbb`. Chroma past the gamut is clipped at constant lightness. */\nexport const toHex = oklchDegToHex;\n/** `#rrggbb` to OKLCH, hue in 0–360. */\nexport const toLch: (hex: string) => Lch = hexToOklchDeg;\n\n/** The most chroma this hue can carry at this lightness, inside sRGB. */\nexport function chromaCap(L: number, H: number): number {\n return toLch(toHex(L, 0.5, H)).C;\n}\n\n/** WCAG relative luminance. */\nexport function luminance(hex: string): number {\n const [r, g, b] = hexToRgb(hex).map((v) => v / 255);\n const f = (u: number) => (u <= 0.04045 ? u / 12.92 : ((u + 0.055) / 1.055) ** 2.4);\n return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b);\n}\n\n/** WCAG contrast ratio between two hex colors, 1–21, in either order. */\nexport function contrast(a: string, b: string): number {\n const [hi, lo] = [luminance(a), luminance(b)].sort((p, q) => q - p);\n return (hi + 0.05) / (lo + 0.05);\n}\n\n/** Shortest angular distance between two hues, in degrees. */\nexport function hueGap(a: number, b: number): number {\n const d = Math.abs(a - b) % 360;\n return Math.min(d, 360 - d);\n}\n\n/** OKLab coordinates, for distance work. */\nexport function toLab(hex: string): [number, number, number] {\n const [r, g, b] = hexToRgb(hex);\n return srgbU8ToOklab(r, g, b);\n}\n\n/**\n * How far apart two colors look, with chroma weighted up.\n *\n * Two things this is not. It is not WCAG contrast, which reads lightness only\n * and so scores a vivid yellow on white at 1.2:1 and calls it illegible when\n * what separates them is chroma. And it is not plain euclidean OKLab distance:\n * OKLab's chroma range is small beside its lightness range, so an unweighted\n * distance is almost all lightness, and it ranks a mid-gray as further from\n * white than a pale blue is.\n *\n * `CHROMA_WEIGHT` restores CIELAB's ordering. It is a weight, not a unit\n * conversion, so these numbers do not transfer to or from CIELAB dE.\n *\n * Rough calibration in the weighted space: 0.17 is a pale wash against paper,\n * 0.25 is a real color, 0.5 is unmistakable.\n */\nexport const CHROMA_WEIGHT = 3;\n\n/** Perceptual distance between two hex colors: OKLab with chroma weighted by {@link CHROMA_WEIGHT}. */\nexport function deltaE(a: string, b: string): number {\n const [l1, a1, b1] = toLab(a);\n const [l2, a2, b2] = toLab(b);\n return Math.hypot(l1 - l2, CHROMA_WEIGHT * (a1 - a2), CHROMA_WEIGHT * (b1 - b2));\n}\n\n/** The most chroma this hue can carry at this lightness, as a hex. */\nexport function vividAt(L: number, H: number): string {\n return toHex(L, chromaCap(L, H), H);\n}\n","import {\n chromaCap,\n contrast,\n CHROMA_WEIGHT,\n deltaE,\n hueGap,\n toHex,\n toLab,\n toLch,\n type Lch,\n} from './oklch.ts';\n\n/**\n * A hue pinned into the palette with its own lightness.\n *\n * Anchors exist because the lightness law excludes some colors entirely. Yellow\n * is the case that forces it: its chroma peaks at L 0.95 — higher than any other\n * hue — so a law that picks lightness for legibility silently yields gold, then\n * olive, and never reports that yellow was dropped.\n */\nexport interface Anchor {\n readonly name: string;\n readonly hue: number;\n readonly lightness: number;\n /**\n * Absolute chroma. Omitted means \"as much as the gamut allows here\", which is\n * what a bright color wants. A muted color has to say so: hue and lightness\n * alone can only describe vivid colors, so a tan asked for at max chroma\n * comes back as an amber.\n */\n readonly chroma?: number;\n}\n\n/** Every constraint the generator honors. A zero disables the ones that gate. */\nexport interface Constraints {\n readonly count: number;\n /**\n * Minimum hue separation, as a share of the even `360 / count` spacing an\n * ideal set would have. 0 disables the check.\n *\n * A share rather than degrees, because absolute degrees mean different things\n * at different cardinalities: 30 degrees is generous for 8 colors and\n * impossible for 16, so a floor in degrees silently becomes unsatisfiable as\n * the set grows.\n */\n readonly hueFloor: number;\n /** Minimum WCAG contrast every swatch must clear against `surface`. 0 disables. */\n readonly minContrast: number;\n /**\n * Minimum perceptual distance from `surface`. 0 disables.\n *\n * The gate WCAG contrast cannot express. Contrast reads only lightness, so it\n * scores a vivid yellow on white at 1.2:1 and calls it illegible, when what\n * separates them is chroma. Gate on this instead of on lightness and a yellow\n * can be a yellow; gate on contrast alone and the search quietly returns gold.\n */\n readonly minSurfaceDistance: number;\n /** Minimum perceptual distance between any two swatches. 0 disables. */\n readonly minDistance: number;\n readonly surface: string;\n /** Where `lightnessPull` drags each hue, away from its own chroma peak. */\n readonly lightnessTarget: number;\n /** 0 leaves every hue at its chroma peak; 1 puts them all at the target. */\n readonly lightnessPull: number;\n /** Fraction of the in-gamut chroma ceiling to take. */\n readonly chromaFraction: number;\n /** 0 leaves chroma alone; 1 pulls every hue to the set mean. */\n readonly equalize: number;\n readonly anchors: readonly Anchor[];\n readonly order: 'hue' | 'farthest';\n}\n\n/** One color of a generated {@link Palette}. */\nexport interface Swatch {\n readonly name: string;\n readonly hex: string;\n readonly lch: Lch;\n /** Came from one of the constraints' anchors. */\n readonly anchored: boolean;\n /** WCAG contrast against the constraints' `surface`. */\n readonly contrast: number;\n}\n\n/** Measurements of a generated palette as a whole: the minimums are over every swatch, or every pair. */\nexport interface Stats {\n readonly meanChroma: number;\n readonly chromaSpread: number;\n readonly lightnessSpread: number;\n readonly minHueGap: number;\n /** The realized floor as a share of even spacing, comparable across sizes. */\n readonly hueFloorShare: number;\n readonly minContrast: number;\n readonly minSurfaceDistance: number;\n readonly minDistance: number;\n}\n\n/** What {@link generate} returns. */\nexport interface Palette {\n readonly swatches: readonly Swatch[];\n readonly stats: Stats;\n /** False when no hue arrangement satisfied the gates; `swatches` is then the\n * best unconstrained attempt, so the lab still has something to draw. */\n readonly feasible: boolean;\n}\n\n/** Lightness at which a hue reaches its highest chroma. */\nfunction peakLightness(H: number): number {\n let bestL = 0.5;\n let bestC = -1;\n for (let L = 0.32; L <= 0.96; L += 0.01) {\n const c = chromaCap(L, H);\n if (c > bestC) {\n bestC = c;\n bestL = L;\n }\n }\n return bestL;\n}\n\nconst PEAK: number[] = [];\nfor (let H = 0; H < 360; H += 1) PEAK.push(peakLightness(H));\nconst peakAt = (H: number) => PEAK[((Math.round(H) % 360) + 360) % 360];\n\n/** The default law: sit near this hue's chroma peak, pulled toward the target. */\nfunction place(H: number, c: Constraints): string {\n const L = peakAt(H) + (c.lightnessTarget - peakAt(H)) * c.lightnessPull;\n return toHex(L, chromaCap(L, H) * c.chromaFraction, H);\n}\n\nconst HUE_NAMES: readonly (readonly [number, string])[] = [\n [15, 'rose'], [45, 'red'], [62, 'orange'], [85, 'amber'], [100, 'gold'],\n [122, 'yellow'], [138, 'lime'], [165, 'green'], [195, 'teal'], [218, 'cyan'],\n [245, 'sky'], [275, 'blue'], [310, 'violet'], [345, 'fuchsia'],\n];\n/** A plain color name for a hue in degrees: `red`, `teal`, `violet`. */\nexport function hueName(H: number): string {\n for (const [ceil, name] of HUE_NAMES) if (H < ceil) return name;\n return 'rose';\n}\n\n/** Disambiguate repeats: two hues can land in one name's band. */\nfunction uniqueNames(hues: number[]): string[] {\n const seen = new Map<string, number>();\n return hues.map((h) => {\n const base = hueName(h);\n const n = (seen.get(base) ?? 0) + 1;\n seen.set(base, n);\n return n === 1 ? base : `${base}-${n}`;\n });\n}\n\n/**\n * Pull each chroma toward the set mean.\n *\n * Raising a chroma is not always possible in place — the weak hues sit on the\n * gamut ceiling already — so this walks lightness to where the target chroma\n * exists, choosing the nearest such lightness. Anchors keep theirs and are\n * only ever desaturated. That asymmetry is why equalizing moves the lightness\n * spread as well.\n */\nfunction equalizeChroma(hexes: string[], k: number, anchored: boolean[]): string[] {\n if (k <= 0) return hexes;\n const lch = hexes.map(toLch);\n const target = lch.reduce((sum, x) => sum + x.C, 0) / lch.length;\n\n return lch.map((x, i) => {\n const wanted = x.C + (target - x.C) * k;\n if (anchored[i]) return toHex(x.L, Math.min(wanted, chromaCap(x.L, x.H)), x.H);\n if (chromaCap(x.L, x.H) >= wanted) return toHex(x.L, wanted, x.H);\n\n let bestL = x.L;\n let bestDistance = Infinity;\n for (let L = 0.30; L <= 0.96; L += 0.005) {\n if (chromaCap(L, x.H) >= wanted) {\n const d = Math.abs(L - x.L);\n if (d < bestDistance) {\n bestDistance = d;\n bestL = L;\n }\n }\n }\n if (bestDistance === Infinity) {\n const pk = peakAt(x.H);\n return toHex(pk, chromaCap(pk, x.H), x.H);\n }\n return toHex(bestL, wanted, x.H);\n });\n}\n\n/**\n * Reorder so every prefix stays as separated as a set that size can be.\n * A consumer taking the first three of ten should get three colors 87° apart,\n * not three neighbors.\n */\nfunction farthestFirst(hues: number[]): number[] {\n const order = [0];\n while (order.length < hues.length) {\n let best = -1;\n let bestGap = -1;\n for (let i = 0; i < hues.length; i += 1) {\n if (order.includes(i)) continue;\n const gap = Math.min(...order.map((j) => hueGap(hues[i], hues[j])));\n if (gap > bestGap) {\n bestGap = gap;\n best = i;\n }\n }\n order.push(best);\n }\n return order;\n}\n\n/**\n * Search hue positions that maximize mean chroma subject to the gates.\n *\n * Seeds matter: a uniform 360/n ring can never open a `2 * minHueGap` hole\n * around a pinned hue, so with anchors the seeds spread across the arc the\n * anchors leave free instead.\n */\n/** The share-of-even floor, in degrees, for a set of this size. */\nexport function floorDegrees(c: Pick<Constraints, 'hueFloor' | 'count'>): number {\n return c.hueFloor <= 0 ? 0 : (c.hueFloor * 360) / Math.max(1, c.count);\n}\n\nfunction searchHues(c: Constraints): number[] | null {\n const minGapDeg = floorDegrees(c);\n const anchorHues = c.anchors.map((a) => a.hue);\n const anchorHexes = c.anchors.map(toHexPreview);\n const freeCount = c.count - c.anchors.length;\n if (freeCount < 0) return null;\n\n // Hue is an integer 0-359 and the constraints are fixed for one call, so the\n // placed color, its realized hue and its contrast are each computed once.\n interface Placed {\n hex: string;\n hue: number;\n contrast: number;\n chroma: number;\n surfaceDistance: number;\n /** OKLab coordinates, chroma pre-weighted, so a pairwise distance in the\n * search is three subtractions rather than two color conversions. */\n lab: readonly [number, number, number];\n }\n const weighted = (hex: string): readonly [number, number, number] => {\n const [L, a, b] = toLab(hex);\n return [L, CHROMA_WEIGHT * a, CHROMA_WEIGHT * b];\n };\n const between = (p: readonly [number, number, number], q: readonly [number, number, number]) =>\n Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);\n const placed = new Map<number, Placed>();\n const at = (H: number) => {\n const key = ((Math.round(H) % 360) + 360) % 360;\n let v = placed.get(key);\n if (!v) {\n const hex = place(key, c);\n const lch = toLch(hex);\n v = {\n hex,\n hue: lch.H,\n contrast: contrast(hex, c.surface),\n chroma: lch.C,\n surfaceDistance: deltaE(hex, c.surface),\n lab: weighted(hex),\n };\n placed.set(key, v);\n }\n return v;\n };\n const anchorMeta = anchorHexes.map((hex) => {\n const lch = toLch(hex);\n return {\n hex,\n hue: lch.H,\n contrast: contrast(hex, c.surface),\n chroma: lch.C,\n surfaceDistance: deltaE(hex, c.surface),\n lab: weighted(hex),\n };\n });\n const metaFor = (free: number[]) => [...anchorMeta, ...free.map(at)];\n\n /**\n * How far a set is from legal, in one number: degrees of hue crowding plus\n * contrast shortfall. Zero means feasible. The search descends this first and\n * only then maximizes chroma, because a seed ring is often illegal and the\n * legal region may not be reachable by chroma-improving moves alone.\n */\n const penalty = (free: number[]): number => {\n const m = metaFor(free);\n let p = 0;\n if (minGapDeg > 0) {\n for (let i = 0; i < m.length; i += 1) {\n for (let j = i + 1; j < m.length; j += 1) {\n const short = minGapDeg - hueGap(m[i].hue, m[j].hue);\n if (short > 0) p += short;\n }\n }\n }\n if (c.minContrast > 0) {\n for (const x of m) {\n const short = c.minContrast - x.contrast;\n if (short > 0) p += short * 40;\n }\n }\n // Distances are small numbers in OKLab (0.10 already reads as two colors),\n // so they are weighted up to sit on the same scale as degrees of crowding.\n if (c.minSurfaceDistance > 0) {\n for (const x of m) {\n const short = c.minSurfaceDistance - x.surfaceDistance;\n if (short > 0) p += short * 400;\n }\n }\n if (c.minDistance > 0) {\n for (let i = 0; i < m.length; i += 1) {\n for (let j = i + 1; j < m.length; j += 1) {\n const short = c.minDistance - between(m[i].lab, m[j].lab);\n if (short > 0) p += short * 400;\n }\n }\n }\n return p;\n };\n const score = (free: number[]) => {\n const m = metaFor(free);\n return m.reduce((sum, x) => sum + x.chroma, 0) / m.length;\n };\n if (freeCount === 0) return penalty([]) > 0 ? null : [];\n\n const seeds: number[][] = [];\n const seedStep = Math.max(6, Math.round(freeCount * 1.6));\n for (let start = 0; start < 360; start += seedStep) {\n seeds.push(Array.from({ length: freeCount }, (_, i) => Math.round((start + (i * 360) / freeCount) % 360)));\n }\n if (anchorHues.length > 0) {\n // A uniform ring can never open a 2 * minHueGap hole around a pinned hue,\n // so also seed across the arc the anchors leave free.\n const base = anchorHues[0];\n const span = 360 - 2 * Math.max(minGapDeg, 1);\n for (let jitter = -8; jitter <= 8; jitter += 2) {\n for (const divisor of [Math.max(1, freeCount - 1), freeCount]) {\n seeds.push(\n Array.from({ length: freeCount }, (_, i) =>\n Math.round((((base + minGapDeg + jitter + (i * span) / divisor) % 360) + 360) % 360),\n ),\n );\n }\n }\n }\n\n const STEPS = [-16, -8, -4, -2, -1, 1, 2, 4, 8, 16];\n\n /**\n * Everything one position contributes to the penalty: its own shortfalls plus\n * the pairs it takes part in.\n *\n * `descend` moves exactly one hue at a time, so recomputing the whole set for\n * each candidate costs O(n^2) to learn about O(n) changed terms. Scoring the\n * moved position alone is what keeps the count slider live at 16 colors.\n */\n const penaltyAt = (m: readonly Placed[], i: number): number => {\n let p = 0;\n const x = m[i];\n if (c.minContrast > 0) {\n const short = c.minContrast - x.contrast;\n if (short > 0) p += short * 40;\n }\n if (c.minSurfaceDistance > 0) {\n const short = c.minSurfaceDistance - x.surfaceDistance;\n if (short > 0) p += short * 400;\n }\n for (let j = 0; j < m.length; j += 1) {\n if (j === i) continue;\n if (minGapDeg > 0) {\n const short = minGapDeg - hueGap(x.hue, m[j].hue);\n if (short > 0) p += short;\n }\n if (c.minDistance > 0) {\n const short = c.minDistance - between(x.lab, m[j].lab);\n if (short > 0) p += short * 400;\n }\n }\n return p;\n };\n\n const descend = (hues: number[], useChroma: boolean, keepLegal: boolean) => {\n const current = [...hues];\n let meta = metaFor(current);\n const offset = anchorMeta.length;\n for (let iteration = 0; iteration < 120; iteration += 1) {\n let improved = false;\n for (let i = 0; i < freeCount; i += 1) {\n const slot = offset + i;\n const beforeP = penaltyAt(meta, slot);\n const beforeC = meta[slot].chroma;\n for (const delta of STEPS) {\n const next = (((current[i] + delta) % 360) + 360) % 360;\n if (next === current[i]) continue;\n const candidate = at(next);\n const trialMeta = meta.slice();\n trialMeta[slot] = candidate;\n const afterP = penaltyAt(trialMeta, slot);\n const better = useChroma\n ? (keepLegal ? afterP <= beforeP : true) && candidate.chroma > beforeC\n : afterP < beforeP;\n if (!better) continue;\n if (keepLegal && afterP > beforeP) continue;\n current[i] = next;\n meta = trialMeta;\n improved = true;\n break;\n }\n }\n if (!improved) break;\n }\n return current;\n };\n\n let best: number[] | null = null;\n let bestScore = -1;\n for (const seed of seeds) {\n const repaired = penalty(seed) > 0 ? descend(seed, false, false) : seed;\n if (penalty(repaired) > 0) continue;\n const tuned = descend(repaired, true, true);\n if (penalty(tuned) > 0) continue;\n const s = score(tuned);\n if (s > bestScore) {\n bestScore = s;\n best = tuned;\n }\n }\n return best;\n}\n\n/** Closest any two colors in the set look. */\nfunction pairwiseMin(hexes: string[]): number {\n if (hexes.length < 2) return 1;\n let min = Infinity;\n for (let i = 0; i < hexes.length; i += 1) {\n for (let j = i + 1; j < hexes.length; j += 1) min = Math.min(min, deltaE(hexes[i], hexes[j]));\n }\n return min;\n}\n\nfunction summarize(swatches: Swatch[], surface: string): Stats {\n const cs = swatches.map((s) => s.lch.C);\n const ls = swatches.map((s) => s.lch.L);\n let gap = 360;\n for (let i = 0; i < swatches.length; i += 1) {\n for (let j = i + 1; j < swatches.length; j += 1) {\n gap = Math.min(gap, hueGap(swatches[i].lch.H, swatches[j].lch.H));\n }\n }\n return {\n meanChroma: cs.reduce((a, b) => a + b, 0) / (cs.length || 1),\n chromaSpread: Math.max(...cs) - Math.min(...cs),\n lightnessSpread: Math.max(...ls) - Math.min(...ls),\n minHueGap: swatches.length > 1 ? gap : 360,\n hueFloorShare: swatches.length > 1 ? (gap * swatches.length) / 360 : 1,\n minContrast: Math.min(...swatches.map((s) => contrast(s.hex, surface))),\n minSurfaceDistance: Math.min(...swatches.map((s) => deltaE(s.hex, surface))),\n minDistance: pairwiseMin(swatches.map((s) => s.hex)),\n };\n}\n\n/**\n * A categorical palette of `count` swatches, anchors included, satisfying the gates. When no hue arrangement\n * satisfies them the result is still a full palette, with `feasible` false.\n */\nexport function generate(c: Constraints): Palette {\n const found = searchHues(c);\n const feasible = found !== null;\n // An infeasible gate still has to draw something, so fall back to an even ring.\n const free =\n found ??\n Array.from({ length: Math.max(0, c.count - c.anchors.length) }, (_, i) =>\n Math.round((i * 360) / Math.max(1, c.count - c.anchors.length)),\n );\n\n const hues = [...c.anchors.map((a) => a.hue), ...free];\n const anchoredFlags = [...c.anchors.map(() => true), ...free.map(() => false)];\n const raw = [\n ...c.anchors.map(toHexPreview),\n ...free.map((h) => place(h, c)),\n ];\n const hexes = equalizeChroma(raw, c.equalize, anchoredFlags);\n\n const order =\n c.order === 'farthest'\n ? farthestFirst(hues)\n : [...hues.keys()].sort((a, b) => hues[a] - hues[b]);\n\n const names = uniqueNames(order.map((i) => toLch(hexes[i]).H));\n const swatches: Swatch[] = order.map((i, position) => ({\n name: c.anchors[i]?.name ?? names[position],\n hex: hexes[i],\n lch: toLch(hexes[i]),\n anchored: anchoredFlags[i],\n contrast: contrast(hexes[i], c.surface),\n }));\n\n return { swatches, stats: summarize(swatches, c.surface), feasible };\n}\n\n/** What the lab opens with: the set this palette work landed on. */\nexport const DEFAULT_CONSTRAINTS: Constraints = {\n count: 10,\n hueFloor: 0.9,\n minContrast: 4,\n surface: '#181a1e',\n lightnessTarget: 0.72,\n lightnessPull: 0.4,\n chromaFraction: 0.95,\n equalize: 0,\n minSurfaceDistance: 0.25,\n minDistance: 0.22,\n anchors: [],\n order: 'farthest',\n};\n\n/** The color an anchor will actually contribute, for a swatch beside its controls. */\nexport function toHexPreview(a: Pick<Anchor, 'hue' | 'lightness' | 'chroma'>): string {\n const cap = chromaCap(a.lightness, a.hue);\n return toHex(a.lightness, a.chroma === undefined ? cap : Math.min(a.chroma, cap), a.hue);\n}\n\n/**\n * An anchor taken from an existing color — a brand hex, or a color lifted from\n * somewhere else in the theme. Lightness comes along with the hue, which is the\n * point: the reason to pin a color is usually that the lightness law would not\n * have chosen its lightness. `name` defaults to the hue's {@link hueName}.\n */\nexport function anchorFromHex(hex: string, name?: string): Anchor {\n const { L, C, H } = toLch(hex);\n return {\n name: name ?? hueName(H),\n hue: Math.round(H),\n lightness: Number(L.toFixed(3)),\n chroma: Number(C.toFixed(4)),\n };\n}\n\n"]}
@@ -0,0 +1,245 @@
1
+ import { themeAxes, resolveTheme, atAlpha, withAlpha, themeChain, generate, DEFAULT_CONSTRAINTS } from './chunk-2PY2YTDY.js';
2
+ import { weaselTheme } from './chunk-JX2OC444.js';
3
+ import { fullSelection } from './chunk-P5F3GZV6.js';
4
+ import { resolvePaletteColor, colorLiteralToCss, cssColorLiteral } from '@weasel-js/paint';
5
+
6
+ // src/themeSheet.ts
7
+ var STYLE_ID = "wzl-themes";
8
+ var sheets = /* @__PURE__ */ new WeakMap();
9
+ function styleRootOf(el) {
10
+ const root = el.getRootNode();
11
+ return root instanceof (el.ownerDocument.defaultView?.ShadowRoot ?? ShadowRoot) ? root : el.ownerDocument;
12
+ }
13
+ var documentOf = (root) => "host" in root ? root.ownerDocument : root;
14
+ var only = (id) => id === 0 ? "" : `:where([data-wzl-variant='${id}'])`;
15
+ function write(root, held) {
16
+ const css = [...held.rules].flatMap(([selector, variants]) => (
17
+ // The bare rule first: it matches a variant's elements too, and the variant's has to win the tie.
18
+ [...variants].sort((a, b) => a.id - b.id).map((v) => `${selector}${only(v.id)} { ${v.body} }`)
19
+ )).join("\n");
20
+ const win = documentOf(root).defaultView;
21
+ const Sheet = win?.CSSStyleSheet;
22
+ if (Sheet && "replaceSync" in Sheet.prototype && Array.isArray(root.adoptedStyleSheets)) {
23
+ if (!held.sheet) {
24
+ held.sheet = new Sheet();
25
+ root.adoptedStyleSheets = [...root.adoptedStyleSheets, held.sheet];
26
+ }
27
+ held.sheet.replaceSync(css);
28
+ return;
29
+ }
30
+ if (!held.styleEl) {
31
+ held.styleEl = documentOf(root).createElement("style");
32
+ held.styleEl.id = STYLE_ID;
33
+ ("host" in root ? root : root.head).appendChild(held.styleEl);
34
+ }
35
+ held.styleEl.textContent = css;
36
+ }
37
+ function holdRule(root, selector, body) {
38
+ let held = sheets.get(root);
39
+ if (!held) sheets.set(root, held = { rules: /* @__PURE__ */ new Map(), sheet: null, styleEl: null });
40
+ const variants = held.rules.get(selector) ?? [];
41
+ let variant = variants.find((v) => v.body === body);
42
+ if (variant) {
43
+ variant.holds++;
44
+ } else {
45
+ let id = 0;
46
+ while (variants.some((v) => v.id === id)) id++;
47
+ variant = { id, body, holds: 1 };
48
+ held.rules.set(selector, [...variants, variant]);
49
+ write(root, held);
50
+ }
51
+ const mine = variant;
52
+ const sheet = held;
53
+ let released = false;
54
+ return {
55
+ variant: mine.id,
56
+ release: () => {
57
+ if (released) return;
58
+ released = true;
59
+ if (--mine.holds > 0) return;
60
+ const left = (sheet.rules.get(selector) ?? []).filter((v) => v !== mine);
61
+ if (left.length > 0) sheet.rules.set(selector, left);
62
+ else sheet.rules.delete(selector);
63
+ write(root, sheet);
64
+ }
65
+ };
66
+ }
67
+
68
+ // src/applyTheme.ts
69
+ var holds = /* @__PURE__ */ new WeakMap();
70
+ function applyTheme(el, theme, selection = {}) {
71
+ if (typeof document === "undefined") return () => {
72
+ };
73
+ const axes = themeAxes(theme);
74
+ const sel = fullSelection(axes, selection);
75
+ const body = Object.entries(resolveTheme(theme, sel)).map(([name, value]) => `${name}: ${value};`).join(" ");
76
+ const names = Object.keys(axes);
77
+ const selector = `[data-wzl-theme='${theme.name}']${names.map((a) => `[data-wzl-${a}='${sel[a]}']`).join("")}`;
78
+ const { variant, release: releaseRule } = holdRule(styleRootOf(el), selector, body);
79
+ holds.get(el)?.();
80
+ el.setAttribute("data-wzl-theme", theme.name);
81
+ for (const a of names) el.setAttribute(`data-wzl-${a}`, sel[a]);
82
+ if (variant === 0) el.removeAttribute("data-wzl-variant");
83
+ else el.setAttribute("data-wzl-variant", String(variant));
84
+ const letGo = () => {
85
+ holds.delete(el);
86
+ releaseRule();
87
+ };
88
+ holds.set(el, letGo);
89
+ return () => {
90
+ if (holds.get(el) !== letGo) return;
91
+ letGo();
92
+ for (const a of ["theme", "variant", ...names]) el.removeAttribute(`data-wzl-${a}`);
93
+ };
94
+ }
95
+
96
+ // src/currentColor.ts
97
+ var NUMBER = String.raw`(\d*\.?\d+)(%?)`;
98
+ var RELATIVE = new RegExp(String.raw`^rgb\(\s*from\s+currentcolor\s+r\s+g\s+b\s*/\s*${NUMBER}\s*\)$`, "i");
99
+ var MIX = new RegExp(String.raw`^color-mix\(\s*in\s+[\w-]+\s*,\s*currentcolor\s+${NUMBER}\s*,\s*transparent\s*\)$`, "i");
100
+ var fraction = (n, pct) => Number(n) / (pct ? 100 : 1);
101
+ function resolveCurrentColor(value, current) {
102
+ const v = value.trim();
103
+ if (!/currentcolor/i.test(v)) return value;
104
+ if (/^currentcolor$/i.test(v)) return current;
105
+ const rel = RELATIVE.exec(v);
106
+ if (rel) return atAlpha(current, fraction(rel[1], rel[2]));
107
+ const mix = MIX.exec(v);
108
+ if (mix && mix[2] === "%") return withAlpha(current, fraction(mix[1], mix[2]));
109
+ throw new Error(`resolveCurrentColor: cannot flatten "${value}"`);
110
+ }
111
+
112
+ // src/colorMode.ts
113
+ function isColorModePreference(v) {
114
+ return v === "auto" || v === "light" || v === "dark";
115
+ }
116
+
117
+ // src/colorListItems.ts
118
+ var wrap = (i, n) => (Math.trunc(i) % n + n) % n;
119
+ var generated = /* @__PURE__ */ new Map();
120
+ function generatedColors({ generate: g }) {
121
+ const key = JSON.stringify([g.count, g.gates ?? {}]);
122
+ let colors = generated.get(key);
123
+ if (!colors) {
124
+ const palette = generate({ ...DEFAULT_CONSTRAINTS, ...g.gates, count: g.count, anchors: [] });
125
+ colors = palette.swatches.map((s) => s.hex.toLowerCase());
126
+ generated.set(key, colors);
127
+ }
128
+ return colors;
129
+ }
130
+ function findRampSteps(theme, ramp) {
131
+ for (const t of themeChain(theme).reverse()) {
132
+ const steps = t.ramps?.[ramp];
133
+ if (steps) return steps;
134
+ }
135
+ return void 0;
136
+ }
137
+ function rampSteps(theme, ramp) {
138
+ const steps = findRampSteps(theme, ramp);
139
+ if (!steps) throw new Error(`Theme "${theme.name}" has no ramp "${ramp}"`);
140
+ return steps;
141
+ }
142
+ function themeTones(theme) {
143
+ for (const t of themeChain(theme).reverse()) if (t.tones) return t.tones;
144
+ return { ramp: "swatch" };
145
+ }
146
+ var fallback;
147
+ var defaultContext = () => fallback ??= { theme: weaselTheme, resolved: resolveTheme(weaselTheme) };
148
+ var pickStep = (list, i, theme) => {
149
+ const steps = rampSteps(theme, list.ramp);
150
+ return steps[wrap(i, steps.length)];
151
+ };
152
+ var rampProperty = (list, i, theme) => `--wzl-${list.ramp}-${pickStep(list, i, theme)}`;
153
+ var isRamp = (list) => typeof list !== "function" && "ramp" in list;
154
+ function colorItemAt(list, i) {
155
+ if (typeof list === "function") return list(i);
156
+ const colors = "generate" in list ? generatedColors(list) : list;
157
+ if (colors.length === 0) throw new Error("colorAt: empty color list");
158
+ return colors[wrap(i, colors.length)];
159
+ }
160
+ function colorCount(list, ctx = defaultContext()) {
161
+ if (typeof list === "function") return void 0;
162
+ if ("ramp" in list) return rampSteps(ctx.theme, list.ramp).length;
163
+ return "generate" in list ? list.generate.count : list.length;
164
+ }
165
+ var TONE_REF = "tone";
166
+ var NO_PALETTE = { entries: [] };
167
+ var tonesOf = (ctx) => ctx.tones ?? themeTones(ctx.theme);
168
+ function parsed(css) {
169
+ try {
170
+ return cssColorLiteral(css);
171
+ } catch {
172
+ return null;
173
+ }
174
+ }
175
+ function propertyOf(ref, ctx) {
176
+ if (ref.ref.startsWith("--")) return ref.index === void 0 ? ref.ref : null;
177
+ if (ref.index === void 0) return `--wzl-${ref.ref}`;
178
+ const step = findRampSteps(ctx.theme, ref.ref)?.[ref.index];
179
+ return step === void 0 ? null : `--wzl-${ref.ref}-${step}`;
180
+ }
181
+ function tokenLiteral(property, ctx) {
182
+ const value = ctx.resolved[property];
183
+ if (value === void 0) return null;
184
+ try {
185
+ return parsed(resolveCurrentColor(value, ctx.resolved["--wzl-fg"]));
186
+ } catch {
187
+ return null;
188
+ }
189
+ }
190
+ var isRef = (source) => typeof source !== "function" && "ref" in source;
191
+ function toneSource(index, ctx) {
192
+ const tones = tonesOf(ctx);
193
+ if (isRamp(tones)) return tokenLiteral(rampProperty(tones, index, ctx.theme), ctx);
194
+ const item = colorItemAt(tones, index);
195
+ return typeof item === "string" ? parsed(item) : item;
196
+ }
197
+ function themeSource(ref, ctx) {
198
+ if (ref.ref === TONE_REF) return toneSource(ref.index ?? 0, ctx);
199
+ const property = propertyOf(ref, ctx);
200
+ return property === null ? null : tokenLiteral(property, ctx);
201
+ }
202
+ function colorSourceLiteral(source, ctx = defaultContext()) {
203
+ return resolvePaletteColor(ctx.palette ?? NO_PALETTE, source, (ref) => themeSource(ref, ctx));
204
+ }
205
+ function literalCss(source, ctx) {
206
+ const literal = colorSourceLiteral(source, ctx);
207
+ return literal && colorLiteralToCss(literal);
208
+ }
209
+ function toneCss(source, ctx) {
210
+ const tones = tonesOf(ctx);
211
+ const index = source.index ?? 0;
212
+ if (isRamp(tones)) return `var(${rampProperty(tones, index, ctx.theme)})`;
213
+ const item = colorItemAt(tones, index);
214
+ if (typeof item === "string") return item;
215
+ return isRef(item) && item.ref !== TONE_REF ? colorSourceCss(item, ctx) : literalCss(source, ctx);
216
+ }
217
+ function colorSourceCss(source, ctx = defaultContext()) {
218
+ if (isRef(source) && !ctx.palette?.entries.some((e) => e.name === source.ref)) {
219
+ if (source.ref === TONE_REF) return toneCss(source, ctx);
220
+ const property = propertyOf(source, ctx);
221
+ if (property === null) return null;
222
+ return source.ref.startsWith("--") || tokenLiteral(property, ctx) ? `var(${property})` : null;
223
+ }
224
+ return literalCss(source, ctx);
225
+ }
226
+ function answered(css, i) {
227
+ if (css === null) throw new Error(`colorAt: nothing answers item ${i} of the color list`);
228
+ return css;
229
+ }
230
+ function colorAt(list, i, ctx = defaultContext()) {
231
+ if (isRamp(list)) return ctx.resolved[rampProperty(list, i, ctx.theme)];
232
+ const item = colorItemAt(list, i);
233
+ if (typeof item === "string") return item;
234
+ const literal = colorSourceLiteral(item, ctx);
235
+ return answered(literal && colorLiteralToCss(literal), i);
236
+ }
237
+ function colorCssAt(list, i, ctx = defaultContext()) {
238
+ if (isRamp(list)) return `var(${rampProperty(list, i, ctx.theme)})`;
239
+ const item = colorItemAt(list, i);
240
+ return typeof item === "string" ? item : answered(colorSourceCss(item, ctx), i);
241
+ }
242
+
243
+ export { TONE_REF, applyTheme, colorAt, colorCount, colorCssAt, colorSourceCss, colorSourceLiteral, isColorModePreference, rampSteps, resolveCurrentColor, themeTones };
244
+ //# sourceMappingURL=chunk-3NIEJ77B.js.map
245
+ //# sourceMappingURL=chunk-3NIEJ77B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/themeSheet.ts","../src/applyTheme.ts","../src/currentColor.ts","../src/colorMode.ts","../src/colorListItems.ts","../src/colorSource.ts","../src/colorList.ts"],"names":["colorLiteralToCss"],"mappings":"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","file":"chunk-3NIEJ77B.js","sourcesContent":["/**\n * The stylesheet a document or a shadow root holds its themes' rules in, and\n * the count of what still uses each one.\n *\n * A rule lives where its elements do: a popout window's document and a shadow\n * root each get a sheet of their own, since a rule in the opener's document\n * styles nothing in either. A rule nobody holds any more leaves its sheet, so\n * a page that mints a theme per instance holds only the live ones.\n */\n\n/** Where an element's styles come from. */\nexport type StyleRoot = Document | ShadowRoot;\n\nconst STYLE_ID = 'wzl-themes';\n\ninterface Variant {\n /** 0 is the definition that has the bare selector; a second, different\n * definition held at once under the same name and selection gets its own. */\n id: number;\n body: string;\n holds: number;\n}\n\ninterface RootSheet {\n /** `selector` → the definitions held under it. */\n rules: Map<string, Variant[]>;\n sheet: CSSStyleSheet | null;\n styleEl: HTMLStyleElement | null;\n}\n\nlet sheets = new WeakMap<StyleRoot, RootSheet>();\n\n/** Test seam: forgets every sheet, so each case starts clean. */\nexport function __resetThemeSheet(): void {\n sheets = new WeakMap();\n}\n\n/** The root `el`'s styles come from: its shadow root, else its document. */\nexport function styleRootOf(el: Element): StyleRoot {\n const root = el.getRootNode();\n return root instanceof (el.ownerDocument.defaultView?.ShadowRoot ?? ShadowRoot) ? (root as ShadowRoot) : el.ownerDocument;\n}\n\nconst documentOf = (root: StyleRoot): Document => ('host' in root ? root.ownerDocument : root);\n\n/** The selector suffix that keeps a variant's rule off the other definitions' elements, at no cost in specificity. */\nconst only = (id: number): string => (id === 0 ? '' : `:where([data-wzl-variant='${id}'])`);\n\nfunction write(root: StyleRoot, held: RootSheet): void {\n const css = [...held.rules]\n .flatMap(([selector, variants]) =>\n // The bare rule first: it matches a variant's elements too, and the variant's has to win the tie.\n [...variants].sort((a, b) => a.id - b.id).map((v) => `${selector}${only(v.id)} { ${v.body} }`))\n .join('\\n');\n const win = documentOf(root).defaultView;\n const Sheet = win?.CSSStyleSheet;\n if (Sheet && 'replaceSync' in Sheet.prototype && Array.isArray(root.adoptedStyleSheets)) {\n if (!held.sheet) {\n // From the root's own window: a constructed sheet cannot be adopted across documents.\n held.sheet = new Sheet();\n root.adoptedStyleSheets = [...root.adoptedStyleSheets, held.sheet];\n }\n held.sheet.replaceSync(css);\n return;\n }\n if (!held.styleEl) {\n held.styleEl = documentOf(root).createElement('style');\n held.styleEl.id = STYLE_ID;\n ('host' in root ? root : root.head).appendChild(held.styleEl);\n }\n held.styleEl.textContent = css;\n}\n\n/**\n * Hold the rule `selector { body }` in `root`'s sheet. Returns the variant id\n * the holder's element is to carry (0 for none) and the release, which takes\n * the rule out of the sheet once nothing else holds it.\n */\nexport function holdRule(root: StyleRoot, selector: string, body: string): { variant: number; release: () => void } {\n let held = sheets.get(root);\n if (!held) sheets.set(root, (held = { rules: new Map(), sheet: null, styleEl: null }));\n const variants = held.rules.get(selector) ?? [];\n let variant = variants.find((v) => v.body === body);\n if (variant) {\n variant.holds++;\n } else {\n let id = 0;\n while (variants.some((v) => v.id === id)) id++;\n variant = { id, body, holds: 1 };\n held.rules.set(selector, [...variants, variant]);\n write(root, held);\n }\n const mine = variant;\n const sheet = held;\n let released = false;\n return {\n variant: mine.id,\n release: () => {\n if (released) return;\n released = true;\n if (--mine.holds > 0) return;\n const left = (sheet.rules.get(selector) ?? []).filter((v) => v !== mine);\n if (left.length > 0) sheet.rules.set(selector, left);\n else sheet.rules.delete(selector);\n write(root, sheet);\n },\n };\n}\n","import { fullSelection, type Selection } from './axes';\nimport { resolveTheme, themeAxes } from './resolveTheme';\nimport type { Theme } from './theme';\nimport { holdRule, styleRootOf } from './themeSheet';\n\nexport { __resetThemeSheet } from './themeSheet';\n\n/** What an element holds from its last `applyTheme`, so the next one, or its release, can let go of it. */\nconst holds = new WeakMap<HTMLElement, () => void>();\n\n/**\n * Apply `theme` at `selection` to `el`'s subtree, and return the release.\n *\n * Stamps `data-wzl-theme` and one `data-wzl-<axis>` per axis, and holds a\n * matching rule block in the stylesheet of the document or shadow root `el`\n * lives in. Deliberately not inline properties: the cascade then does the\n * work, per-subtree overrides are just a different theme name, and no\n * `!important` is ever needed. No-op outside a DOM.\n *\n * An element holds one application: applying again replaces what it held, so\n * a caller restyling one root never has to release. The release is for a\n * subtree that goes away. It takes the attributes back off and lets go of the\n * rule, which leaves the sheet once no element holds it; a release whose\n * element has since been given something else does nothing.\n *\n * Two different themes may share a name. The second held at once has its rule\n * kept to its own elements by a `data-wzl-variant` attribute, matched inside\n * `:where()` so the rule's specificity is the first's.\n */\nexport function applyTheme(el: HTMLElement, theme: Theme, selection: Selection = {}): () => void {\n if (typeof document === 'undefined') return () => {};\n\n const axes = themeAxes(theme);\n const sel = fullSelection(axes, selection);\n const body = Object.entries(resolveTheme(theme, sel))\n .map(([name, value]) => `${name}: ${value};`)\n .join(' ');\n const names = Object.keys(axes);\n const selector = `[data-wzl-theme='${theme.name}']${names.map((a) => `[data-wzl-${a}='${sel[a]}']`).join('')}`;\n // Held before the last one is let go, so re-applying the same rule rewrites nothing.\n const { variant, release: releaseRule } = holdRule(styleRootOf(el), selector, body);\n holds.get(el)?.();\n\n el.setAttribute('data-wzl-theme', theme.name);\n for (const a of names) el.setAttribute(`data-wzl-${a}`, sel[a]);\n if (variant === 0) el.removeAttribute('data-wzl-variant');\n else el.setAttribute('data-wzl-variant', String(variant));\n\n // The attributes go only through `release`: a hold replaced by the next application leaves them to it.\n const letGo = (): void => {\n holds.delete(el);\n releaseRule();\n };\n holds.set(el, letGo);\n return () => {\n if (holds.get(el) !== letGo) return;\n letGo();\n for (const a of ['theme', 'variant', ...names]) el.removeAttribute(`data-wzl-${a}`);\n };\n}\n","import { atAlpha, withAlpha } from './dtcg/color.ts';\n\nconst NUMBER = String.raw`(\\d*\\.?\\d+)(%?)`;\nconst RELATIVE = new RegExp(String.raw`^rgb\\(\\s*from\\s+currentcolor\\s+r\\s+g\\s+b\\s*/\\s*${NUMBER}\\s*\\)$`, 'i');\nconst MIX = new RegExp(String.raw`^color-mix\\(\\s*in\\s+[\\w-]+\\s*,\\s*currentcolor\\s+${NUMBER}\\s*,\\s*transparent\\s*\\)$`, 'i');\n\nconst fraction = (n: string, pct: string) => Number(n) / (pct ? 100 : 1);\n\n/**\n * A resolved token value with `currentColor` taken to be `current`, for a surface drawn without the\n * cascade — a canvas reading a resolved theme — where `currentColor` has nothing to resolve against.\n * Pass the color of the text the value is drawn beside, usually `--wzl-fg`. A value that never\n * mentions `currentColor` comes back unchanged.\n *\n * Flattens the forms the kit's themes write: bare `currentColor`, `rgb(from currentColor r g b / a)`\n * and `color-mix(in <space>, currentColor p%, transparent)`. Throws on any other use of it.\n */\nexport function resolveCurrentColor(value: string, current: string): string {\n const v = value.trim();\n if (!/currentcolor/i.test(v)) return value;\n if (/^currentcolor$/i.test(v)) return current;\n const rel = RELATIVE.exec(v);\n if (rel) return atAlpha(current, fraction(rel[1], rel[2]));\n const mix = MIX.exec(v);\n if (mix && mix[2] === '%') return withAlpha(current, fraction(mix[1], mix[2]));\n throw new Error(`resolveCurrentColor: cannot flatten \"${value}\"`);\n}\n","/** A color mode the theme's `mode` axis resolves. */\nexport type ColorMode = 'light' | 'dark';\n\n/**\n * What a user chose: a mode, or `'auto'` — follow the OS, live. `'auto'` is\n * not a mode; resolve it with `useResolvedColorMode` before handing it to a\n * `ThemeProvider` selection.\n */\nexport type ColorModePreference = 'auto' | ColorMode;\n\n/** Whether a value — say, one read back from storage — is a preference. */\nexport function isColorModePreference(v: unknown): v is ColorModePreference {\n return v === 'auto' || v === 'light' || v === 'dark';\n}\n","import type { ColorLiteral, ColorRef, ColorSource, Palette } from '@weasel-js/paint';\nimport type { CategoricalRampDef } from './definition.ts';\nimport { DEFAULT_CONSTRAINTS, generate, type Constraints } from './engine/color/generate.ts';\nimport { resolveTheme, themeChain, type ResolvedTheme } from './resolveTheme.ts';\nimport { weaselTheme, type Theme } from './theme.ts';\n\n/** The categorical generator the swatch ramp uses, asked for `count` colors. */\nexport interface GeneratedColors {\n readonly generate: { readonly count: number; readonly gates?: CategoricalRampDef['gates'] };\n}\n\n/** A ramp of the active theme, by name — `{ ramp: 'swatch' }` walks its steps in order. */\nexport interface RampColors {\n readonly ramp: string;\n}\n\n/** One color of a list: a CSS color string, or a `ColorSource` resolved when it is read. */\nexport type ColorListItem = string | ColorSource;\n\n/** The forms a theme definition can hold: everything but a function. */\nexport type SerializableColorList = readonly (string | ColorLiteral | ColorRef)[] | GeneratedColors | RampColors;\n\n/**\n * Several colors, read by index with `colorAt`, wrapping. Items, each a CSS\n * string or a `ColorSource`; the swatch ramp's generator; a ramp of the active\n * theme, which follows the mode; or a function of the index.\n */\nexport type ColorList = readonly ColorListItem[] | GeneratedColors | RampColors | ((i: number) => ColorListItem);\n\n/** What a `ColorList` resolves against. `useTheme()`'s value is one. */\nexport interface ColorContext {\n readonly theme: Theme;\n readonly resolved: ResolvedTheme;\n}\n\n/** What a `ColorSource` resolves against under a theme. `useTones()`'s value is one. */\nexport interface ColorSourceContext extends ColorContext {\n /** The list `{ ref: 'tone' }` indexes. Absent: the theme's own. */\n readonly tones?: ColorList;\n /** Names answered before the theme's. */\n readonly palette?: Palette;\n}\n\nconst wrap = (i: number, n: number) => ((Math.trunc(i) % n) + n) % n;\n\nconst generated = new Map<string, readonly string[]>();\n\nfunction generatedColors({ generate: g }: GeneratedColors): readonly string[] {\n const key = JSON.stringify([g.count, g.gates ?? {}]);\n let colors = generated.get(key);\n if (!colors) {\n const palette = generate({ ...DEFAULT_CONSTRAINTS, ...(g.gates as Partial<Constraints>), count: g.count, anchors: [] });\n colors = palette.swatches.map((s) => s.hex.toLowerCase());\n generated.set(key, colors);\n }\n return colors;\n}\n\n/** `rampSteps`, answering `undefined` for a ramp the chain lacks. */\nexport function findRampSteps(theme: Theme, ramp: string): readonly string[] | undefined {\n for (const t of themeChain(theme).reverse()) {\n const steps = t.ramps?.[ramp];\n if (steps) return steps;\n }\n return undefined;\n}\n\n/** A ramp's step names, from the nearest theme in the chain that declares it. */\nexport function rampSteps(theme: Theme, ramp: string): readonly string[] {\n const steps = findRampSteps(theme, ramp);\n if (!steps) throw new Error(`Theme \"${theme.name}\" has no ramp \"${ramp}\"`);\n return steps;\n}\n\n/** The tone list a theme declares, from the nearest theme in its chain that has one. */\nexport function themeTones(theme: Theme): ColorList {\n for (const t of themeChain(theme).reverse()) if (t.tones) return t.tones;\n return { ramp: 'swatch' };\n}\n\nlet fallback: ColorContext | undefined;\nexport const defaultContext = () => (fallback ??= { theme: weaselTheme, resolved: resolveTheme(weaselTheme) });\n\nconst pickStep = (list: RampColors, i: number, theme: Theme): string => {\n const steps = rampSteps(theme, list.ramp);\n return steps[wrap(i, steps.length)];\n};\n\n/** The custom property behind the `i`th step of a ramp list, wrapping. */\nexport const rampProperty = (list: RampColors, i: number, theme: Theme): string =>\n `--wzl-${list.ramp}-${pickStep(list, i, theme)}`;\n\nexport const isRamp = (list: ColorList): list is RampColors => typeof list !== 'function' && 'ramp' in list;\n\n/** The `i`th item of a list that is not a ramp, wrapping, as it was written. */\nexport function colorItemAt(list: Exclude<ColorList, RampColors>, i: number): ColorListItem {\n if (typeof list === 'function') return list(i);\n const colors = 'generate' in list ? generatedColors(list) : list;\n if (colors.length === 0) throw new Error('colorAt: empty color list');\n return colors[wrap(i, colors.length)];\n}\n\n/** How many distinct colors `list` holds before it wraps; `undefined` for a function, which never does. */\nexport function colorCount(list: ColorList, ctx: ColorContext = defaultContext()): number | undefined {\n if (typeof list === 'function') return undefined;\n if ('ramp' in list) return rampSteps(ctx.theme, list.ramp).length;\n return 'generate' in list ? list.generate.count : list.length;\n}\n","import {\n colorLiteralToCss,\n cssColorLiteral,\n resolvePaletteColor,\n type ColorLiteral,\n type ColorRef,\n type ColorSource,\n type Palette,\n} from '@weasel-js/paint';\nimport {\n colorItemAt,\n defaultContext,\n findRampSteps,\n isRamp,\n rampProperty,\n themeTones,\n type ColorList,\n type ColorSourceContext,\n} from './colorListItems.ts';\nimport { resolveCurrentColor } from './currentColor.ts';\n\n/** The name the tone list answers to: `{ ref: 'tone', index: 2 }` is the third tone, wrapping. */\nexport const TONE_REF = 'tone';\n\nexport type { ColorSourceContext };\n\nconst NO_PALETTE: Palette = { entries: [] };\n\nconst tonesOf = (ctx: ColorSourceContext): ColorList => ctx.tones ?? themeTones(ctx.theme);\n\nfunction parsed(css: string): ColorLiteral | null {\n try {\n return cssColorLiteral(css);\n } catch {\n return null;\n }\n}\n\n/** The custom property a theme ref names: itself when spelled as one, a token by name, or a ramp step by index. */\nfunction propertyOf(ref: ColorRef, ctx: ColorSourceContext): string | null {\n if (ref.ref.startsWith('--')) return ref.index === undefined ? ref.ref : null;\n if (ref.index === undefined) return `--wzl-${ref.ref}`;\n const step = findRampSteps(ctx.theme, ref.ref)?.[ref.index];\n return step === undefined ? null : `--wzl-${ref.ref}-${step}`;\n}\n\nfunction tokenLiteral(property: string, ctx: ColorSourceContext): ColorLiteral | null {\n const value = (ctx.resolved as Readonly<Record<string, string>>)[property];\n if (value === undefined) return null;\n try {\n return parsed(resolveCurrentColor(value, ctx.resolved['--wzl-fg']));\n } catch {\n return null;\n }\n}\n\nconst isRef = (source: ColorSource): source is ColorRef => typeof source !== 'function' && 'ref' in source;\n\nfunction toneSource(index: number, ctx: ColorSourceContext): ColorSource | null {\n const tones = tonesOf(ctx);\n if (isRamp(tones)) return tokenLiteral(rampProperty(tones, index, ctx.theme), ctx);\n const item = colorItemAt(tones, index);\n return typeof item === 'string' ? parsed(item) : item;\n}\n\nfunction themeSource(ref: ColorRef, ctx: ColorSourceContext): ColorSource | null {\n if (ref.ref === TONE_REF) return toneSource(ref.index ?? 0, ctx);\n const property = propertyOf(ref, ctx);\n return property === null ? null : tokenLiteral(property, ctx);\n}\n\n/**\n * Resolve `source` to a literal, for a surface drawn without the cascade. A ref\n * names an entry of the context's palette first, then the theme: `tone` with an\n * index into the tone list, a token by its name without the `--wzl-` prefix, a\n * ramp by its name with the index of a step, or a custom property spelled out.\n * `null` for a name nothing answers, a token that is not a color, and a custom\n * property the theme does not define.\n */\nexport function colorSourceLiteral(source: ColorSource, ctx: ColorSourceContext = defaultContext()): ColorLiteral | null {\n return resolvePaletteColor(ctx.palette ?? NO_PALETTE, source, (ref) => themeSource(ref, ctx));\n}\n\nfunction literalCss(source: ColorSource, ctx: ColorSourceContext): string | null {\n const literal = colorSourceLiteral(source, ctx);\n return literal && colorLiteralToCss(literal);\n}\n\nfunction toneCss(source: ColorRef, ctx: ColorSourceContext): string | null {\n const tones = tonesOf(ctx);\n const index = source.index ?? 0;\n if (isRamp(tones)) return `var(${rampProperty(tones, index, ctx.theme)})`;\n const item = colorItemAt(tones, index);\n if (typeof item === 'string') return item;\n return isRef(item) && item.ref !== TONE_REF ? colorSourceCss(item, ctx) : literalCss(source, ctx);\n}\n\n/**\n * `source` as a CSS color, naming what `colorSourceLiteral` resolves. A ref the\n * theme answers is written as its custom property, so it follows the cascade\n * with no re-render and a property spelled out need not be the theme's;\n * everything else is written as the literal it resolves to.\n */\nexport function colorSourceCss(source: ColorSource, ctx: ColorSourceContext = defaultContext()): string | null {\n if (isRef(source) && !ctx.palette?.entries.some((e) => e.name === source.ref)) {\n if (source.ref === TONE_REF) return toneCss(source, ctx);\n const property = propertyOf(source, ctx);\n if (property === null) return null;\n return source.ref.startsWith('--') || tokenLiteral(property, ctx) ? `var(${property})` : null;\n }\n return literalCss(source, ctx);\n}\n","import { colorLiteralToCss } from '@weasel-js/paint';\nimport { colorItemAt, defaultContext, isRamp, rampProperty, type ColorList, type ColorSourceContext } from './colorListItems.ts';\nimport { colorSourceCss, colorSourceLiteral } from './colorSource.ts';\nimport type { ResolvedTheme } from './resolveTheme.ts';\n\nexport {\n colorCount,\n findRampSteps,\n rampSteps,\n themeTones,\n type ColorContext,\n type ColorList,\n type ColorListItem,\n type GeneratedColors,\n type RampColors,\n type SerializableColorList,\n} from './colorListItems.ts';\n\nfunction answered(css: string | null, i: number): string {\n if (css === null) throw new Error(`colorAt: nothing answers item ${i} of the color list`);\n return css;\n}\n\n/**\n * The `i`th color of `list`, wrapping. A ramp list reads the resolved theme, so\n * the answer follows its mode; a `ColorSource` item resolves against the\n * context's palette, then its theme. Throws on an item nothing answers.\n */\nexport function colorAt(list: ColorList, i: number, ctx: ColorSourceContext = defaultContext()): string {\n if (isRamp(list)) return ctx.resolved[rampProperty(list, i, ctx.theme) as keyof ResolvedTheme];\n const item = colorItemAt(list, i);\n if (typeof item === 'string') return item;\n const literal = colorSourceLiteral(item, ctx);\n return answered(literal && colorLiteralToCss(literal), i);\n}\n\n/**\n * As `colorAt`, but a ramp list, and an item that names the theme, answers\n * with its custom property (`var(--wzl-swatch-sky)`), so a color written into\n * CSS follows a mode change without re-rendering, provider or not.\n */\nexport function colorCssAt(list: ColorList, i: number, ctx: ColorSourceContext = defaultContext()): string {\n if (isRamp(list)) return `var(${rampProperty(list, i, ctx.theme)})`;\n const item = colorItemAt(list, i);\n return typeof item === 'string' ? item : answered(colorSourceCss(item, ctx), i);\n}\n"]}