@weasel-js/theme 1.12.0 → 1.13.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { o as ColorList, p as ColorSourceContext, q as TokenName, r as ResolvedTheme, a as Theme, S as Selection, s as TokenValue } from './definition-CSeERbSL.js';
2
- export { t as AxisDef, A as AxisDefs, u as AxisValue, v as BAKED_THEMES, B as BakedTheme, w as ByAxis, x as ColorContext, y as ColorListItem, F as FlatTokens, G as GeneratedColors, z as GeneratedTheme, P as PinObject, e as PinValue, D as RampColors, R as RawToken, E as SerializableColorList, H as THEMES, I as THEME_SOURCES, T as ThemeDefinition, J as ThemeInput, V as Varying, K as colorCount, M as defineTheme, Q as enumerateSelections, U as fullSelection, W as isByAxis, X as rampSteps, Y as resolveTheme, Z as selectionKey, _ as themeAxes, $ as themeTones, a0 as weaselTheme } from './definition-CSeERbSL.js';
1
+ import { o as ColorList, p as ColorSourceContext, q as TokenName, r as ResolvedTheme, a as Theme, S as Selection, s as TokenValue } from './definition-wsEi-XBr.js';
2
+ export { t as AxisDef, A as AxisDefs, u as AxisValue, v as BAKED_THEMES, B as BakedTheme, w as ByAxis, x as ColorContext, y as ColorListItem, F as FlatTokens, G as GeneratedColors, z as GeneratedTheme, P as PinObject, e as PinValue, D as RampColors, R as RawToken, E as SerializableColorList, H as THEMES, I as THEME_SOURCES, T as ThemeDefinition, J as ThemeInput, V as Varying, K as colorCount, M as defineTheme, Q as enumerateSelections, U as fullSelection, W as isByAxis, X as rampSteps, Y as resolveTheme, Z as selectionKey, _ as themeAxes, $ as themeTints, a0 as weaselTheme } from './definition-wsEi-XBr.js';
3
3
  export { C as ColorMode, a as ColorModePreference, i as isColorModePreference } from './colorMode-CoklZomJ.js';
4
4
  import { ColorSource, ColorLiteral } from '@weasel-js/paint';
5
5
 
@@ -150,13 +150,34 @@ declare function serializeTokenValue(type: string, value: TokenValue): string;
150
150
  */
151
151
  declare function parseTokenValue(type: string, text: string): TokenValue;
152
152
 
153
- /** The name the tone list answers to: `{ ref: 'tone', index: 2 }` is the third tone, wrapping. */
154
- declare const TONE_REF = "tone";
153
+ /** The angle a component comes from: who it is for, how it speaks, what an action does. */
154
+ declare const STANCES: readonly ["clarify", "aside", "advanced", "debug", "preview", "confirm", "cancel"];
155
+ /** One stance. */
156
+ type Stance = (typeof STANCES)[number];
157
+ /** How serious, or how good. The only axis that paints red. */
158
+ declare const GRADES: readonly ["info", "success", "warn", "danger"];
159
+ /** One grade. */
160
+ type Grade = (typeof GRADES)[number];
161
+ /** The token each grade paints with. */
162
+ declare const GRADE_TOKENS: Readonly<Record<Grade, string>>;
163
+ /** How loudly a component reads. Unset is normal. */
164
+ declare const EMPHASES: readonly ["high", "low"];
165
+ /** One emphasis level; unset reads as normal. */
166
+ type Emphasis = (typeof EMPHASES)[number];
167
+ /** The text color an emphasis lends to everything inside it, as `--wzl-emphasis-fg`. */
168
+ declare const EMPHASIS_FG: Readonly<Record<Emphasis, string>>;
169
+ /** The surface slots an emphasis repaints, beyond the text color it hands down. */
170
+ declare const EMPHASIS_SLOTS: Readonly<Record<Emphasis, Partial<Record<'border-color' | 'title-color', string>>>>;
171
+ /** The surface slots a grade repaints in its color. */
172
+ declare const GRADE_SLOTS: readonly ["tint", "border-color", "title-color"];
173
+
174
+ /** The name the tint list answers to: `{ ref: 'tint', index: 2 }` is the third tint, wrapping. */
175
+ declare const TINT_REF = "tint";
155
176
 
156
177
  /**
157
178
  * Resolve `source` to a literal, for a surface drawn without the cascade. A ref
158
- * names an entry of the context's palette first, then the theme: `tone` with an
159
- * index into the tone list, a token by its name without the `--wzl-` prefix, a
179
+ * names an entry of the context's palette first, then the theme: `tint` with an
180
+ * index into the tint list, a token by its name without the `--wzl-` prefix, a
160
181
  * ramp by its name with the index of a step, or a custom property spelled out.
161
182
  * `null` for a name nothing answers, a token that is not a color, and a custom
162
183
  * property the theme does not define.
@@ -174,7 +195,8 @@ declare function colorSourceLiteral(source: ColorSource, ctx?: ColorSourceContex
174
195
  declare function colorSourceCss(source: ColorSource, ctx?: ColorSourceContext): string | null;
175
196
 
176
197
  /**
177
- * The vocabulary of stances, and the slots a theme styles a stanced surface with.
198
+ * The slots a theme styles a stanced surface with. A stance is the angle a
199
+ * surface comes from, not a class of content.
178
200
  *
179
201
  * A stance looks the same on every surface that takes one. A surface reads
180
202
  * `--wzl-stance-<stance>-<slot>` first — a nested panel
@@ -183,10 +205,7 @@ declare function colorSourceCss(source: ColorSource, ctx?: ColorSourceContext):
183
205
  * every other name here is read, with its fallback, and declared by nothing.
184
206
  * A panel's base look is itself theme slots, `--wzl-panel-<slot>`.
185
207
  */
186
- /** What kind of content a surface holds — a class of content, never a position. */
187
- declare const STANCES: readonly ["scope", "aside", "advanced", "debug", "danger", "notice", "important", "preview"];
188
- /** One of {@link STANCES}. */
189
- type Stance = (typeof STANCES)[number];
208
+
190
209
  /** One styleable property of a stanced surface. */
191
210
  interface StanceSlot {
192
211
  readonly name: string;
@@ -211,10 +230,10 @@ interface StanceLookup<S extends string> {
211
230
  * `--wzl-stance-<stance>-<slot>`, then the stanced fallback, then `base`.
212
231
  * `base` holds final values, one per slot the surface draws.
213
232
  *
214
- * The tone is the caller's: a surface that names one mixes it into
215
- * `surface` at `tone-mix`; one that names none takes the `tone` slot, which
233
+ * The tint is the caller's: a surface that names one mixes it into
234
+ * `surface` at `tint-mix`; one that names none takes the `tint` slot, which
216
235
  * falls back to `surface` so mixing it changes nothing.
217
236
  */
218
237
  declare function resolveStanceSlots<S extends string>(tokens: Readonly<Record<string, string>>, base: Readonly<Record<S, string>>, { stance, nested, stanced }?: StanceLookup<S>): Record<S, string>;
219
238
 
220
- export { type AxisWeights, type BoxShadow, ColorList, ColorSourceContext, type DtcgDocument, ResolvedTheme, STANCES, STANCE_SLOTS, Selection, type Stance, type StanceLookup, type StanceSlot, TOKEN_MANIFEST, TONE_REF, Theme, type TokenManifestEntry, TokenName, TokenValue, applyTheme, blendTheme, colorAt, colorCssAt, colorSourceCss, colorSourceLiteral, expandVars, loadDTCG, parseBoxShadow, parseTokenValue, resolveCurrentColor, resolveStanceSlots, serializeTokenValue, stanceSlotNames, tokenPx };
239
+ export { type AxisWeights, type BoxShadow, ColorList, ColorSourceContext, type DtcgDocument, EMPHASES, EMPHASIS_FG, EMPHASIS_SLOTS, type Emphasis, GRADES, GRADE_SLOTS, GRADE_TOKENS, type Grade, ResolvedTheme, STANCES, STANCE_SLOTS, Selection, type Stance, type StanceLookup, type StanceSlot, TINT_REF, TOKEN_MANIFEST, Theme, type TokenManifestEntry, TokenName, TokenValue, applyTheme, blendTheme, colorAt, colorCssAt, colorSourceCss, colorSourceLiteral, expandVars, loadDTCG, parseBoxShadow, parseTokenValue, resolveCurrentColor, resolveStanceSlots, serializeTokenValue, stanceSlotNames, tokenPx };
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
- export { TONE_REF, applyTheme, blendTheme, colorAt, colorCount, colorCssAt, colorSourceCss, colorSourceLiteral, isColorModePreference, rampSteps, resolveCurrentColor, themeTones } from './chunk-QGOGBCYW.js';
1
+ export { TINT_REF, applyTheme, blendTheme, colorAt, colorCount, colorCssAt, colorSourceCss, colorSourceLiteral, isColorModePreference, rampSteps, resolveCurrentColor, themeTints } from './chunk-R7OXPHZJ.js';
2
2
  import { AXES_EXT, overrideKey, ALPHA_EXT } from './chunk-Z675UQ26.js';
3
3
  import './chunk-S7MJPFDP.js';
4
- import { TOKEN_MANIFEST } from './chunk-GE2WCTOV.js';
5
- export { TOKEN_MANIFEST } from './chunk-GE2WCTOV.js';
4
+ import { TOKEN_MANIFEST } from './chunk-EJBP2YIO.js';
5
+ export { TOKEN_MANIFEST } from './chunk-EJBP2YIO.js';
6
6
  import { readCssNumber } from './chunk-M3R5MV7Q.js';
7
7
  import { themeAxes } from './chunk-32JKTYS2.js';
8
8
  export { parseTokenValue, resolveTheme, serializeTokenValue, themeAxes } from './chunk-32JKTYS2.js';
9
- import { weaselTheme } from './chunk-JX2OC444.js';
10
- export { BAKED_THEMES, THEMES, THEME_SOURCES, defineTheme, weaselTheme } from './chunk-JX2OC444.js';
9
+ import { weaselTheme } from './chunk-R2SSGWGZ.js';
10
+ export { BAKED_THEMES, THEMES, THEME_SOURCES, defineTheme, weaselTheme } from './chunk-R2SSGWGZ.js';
11
11
  import { mergeAxes } from './chunk-P5F3GZV6.js';
12
12
  export { enumerateSelections, fullSelection, isByAxis, selectionKey } from './chunk-P5F3GZV6.js';
13
13
  import { isPlainObject } from '@weasel-js/registry';
@@ -201,8 +201,27 @@ function loadDTCG(doc) {
201
201
  return { name: doc.name, extends: base, axes, tokens };
202
202
  }
203
203
 
204
+ // src/appearance.ts
205
+ var STANCES = ["clarify", "aside", "advanced", "debug", "preview", "confirm", "cancel"];
206
+ var GRADES = ["info", "success", "warn", "danger"];
207
+ var GRADE_TOKENS = {
208
+ info: "--wzl-info",
209
+ success: "--wzl-success",
210
+ warn: "--wzl-warning",
211
+ danger: "--wzl-danger"
212
+ };
213
+ var EMPHASES = ["high", "low"];
214
+ var EMPHASIS_FG = {
215
+ high: "var(--wzl-accent-fg)",
216
+ low: "var(--wzl-fg-muted)"
217
+ };
218
+ var EMPHASIS_SLOTS = {
219
+ high: { "border-color": "var(--wzl-accent-fg)", "title-color": "var(--wzl-accent-fg)" },
220
+ low: { "title-color": "var(--wzl-fg-muted)" }
221
+ };
222
+ var GRADE_SLOTS = ["tint", "border-color", "title-color"];
223
+
204
224
  // src/panel.ts
205
- var STANCES = ["scope", "aside", "advanced", "debug", "danger", "notice", "important", "preview"];
206
225
  var STANCE_SLOTS = [
207
226
  { name: "surface", drives: "background" },
208
227
  { name: "border-color", drives: "border-color" },
@@ -211,10 +230,10 @@ var STANCE_SLOTS = [
211
230
  { name: "radius", drives: "border-radius" },
212
231
  { name: "pad", drives: "padding" },
213
232
  { name: "blur", drives: "backdrop-filter" },
214
- { name: "tone-mix", drives: "how much of the tone mixes into the surface" },
215
- { name: "tone", drives: "the tone a surface takes when it names none" },
216
- // Only a surface that names its own tone recolors its controls.
217
- { name: "accent", drives: "the accent the controls inside a surface with a tone take; unset, the tone" },
233
+ { name: "tint-mix", drives: "how much of the tint mixes into the surface" },
234
+ { name: "tint", drives: "the tint a surface takes when it names none" },
235
+ // Only a surface that names its own tint or grade recolors its controls.
236
+ { name: "accent", drives: "the accent the controls inside a tinted or graded surface take; unset, the tint" },
218
237
  { name: "title-font", drives: "font-family" },
219
238
  { name: "title-weight", drives: "font-weight" },
220
239
  { name: "title-size", drives: "font-size" },
@@ -234,12 +253,12 @@ function resolveStanceSlots(tokens, base, { stance, nested, stanced } = {}) {
234
253
  for (const slot of Object.keys(base)) {
235
254
  const own = tokens[`--wzl-stance-${stance}-${slot}`];
236
255
  const inner = nested ? tokens[`--wzl-stance-${stance}-nested-${slot}`] : void 0;
237
- const fallback = slot === "tone" ? base.surface ?? base[slot] : stanced?.[slot] ?? base[slot];
256
+ const fallback = slot === "tint" ? base.surface ?? base[slot] : stanced?.[slot] ?? base[slot];
238
257
  out[slot] = inner ?? own ?? fallback;
239
258
  }
240
259
  return out;
241
260
  }
242
261
 
243
- export { STANCES, STANCE_SLOTS, expandVars, loadDTCG, parseBoxShadow, resolveStanceSlots, stanceSlotNames, tokenPx };
262
+ export { EMPHASES, EMPHASIS_FG, EMPHASIS_SLOTS, GRADES, GRADE_SLOTS, GRADE_TOKENS, STANCES, STANCE_SLOTS, expandVars, loadDTCG, parseBoxShadow, resolveStanceSlots, stanceSlotNames, tokenPx };
244
263
  //# sourceMappingURL=index.js.map
245
264
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tokenPx.ts","../src/boxShadow.ts","../src/dtcg/flatten.ts","../src/loadDTCG.ts","../src/panel.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { TOKEN_MANIFEST } from './generated/manifest';\nimport type { ResolvedTheme } from './resolveTheme';\nimport type { TokenName } from './generated/themes';\n\nconst DEFAULTS = new Map<string, string>(TOKEN_MANIFEST.map((t) => [t.name, t.defaultValue]));\n\n/**\n * A px-valued token as a number, for code that draws rather than styles —\n * SVG geometry attributes, canvas, WebGL. Pass `resolved` (from\n * `useTheme().resolved`) where a live theme override must reach the drawing;\n * without it the built-in theme's value is used, which is static and costs no\n * style resolution.\n *\n * Throws rather than guessing: a token that is not a plain px length has no\n * number, and silently returning 0 collapses whatever it sized.\n */\nexport function tokenPx(name: TokenName, resolved?: ResolvedTheme): number {\n const raw = resolved?.[name] ?? DEFAULTS.get(name);\n const m = /^(-?\\d*\\.?\\d+)px$/.exec((raw ?? '').trim());\n if (!m) throw new Error(`tokenPx: ${name} is not a px length (${raw ?? 'unknown token'})`);\n return Number(m[1]);\n}\n","import { readCssNumber } from './cssNumber';\n\n/** One layer of a CSS `box-shadow`, lengths in px. */\nexport interface BoxShadow {\n inset: boolean;\n x: number;\n y: number;\n blur: number;\n spread: number;\n /** As written; `currentColor` when the layer names none. */\n color: string;\n}\n\n/** `css` split at each top-level `sep`, ignoring any inside parentheses. */\nfunction splitTop(css: string, sep: RegExp): string[] {\n const out: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < css.length; i++) {\n const ch = css[i]!;\n if (ch === '(') depth++;\n else if (ch === ')') depth--;\n else if (depth === 0 && sep.test(ch)) {\n out.push(css.slice(start, i));\n start = i + 1;\n }\n }\n out.push(css.slice(start));\n return out.map((s) => s.trim()).filter((s) => s !== '');\n}\n\n/** The index of the `)` closing the `(` at `open`, or -1. */\nfunction closing(css: string, open: number): number {\n let depth = 0;\n for (let i = open; i < css.length; i++) {\n if (css[i] === '(') depth++;\n else if (css[i] === ')' && --depth === 0) return i;\n }\n return -1;\n}\n\n/**\n * `value` with every `var(--name)` and `var(--name, fallback)` replaced as a browser would: by\n * `tokens[name]`, expanded in turn, or by the fallback when the theme has no such token. A\n * resolved theme can hold references (a theme's bevel names its bevel colors), and a canvas\n * reading one has no cascade to substitute them. Throws on a reference with neither.\n */\nexport function expandVars(value: string, tokens: Readonly<Record<string, string>>, seen: readonly string[] = []): string {\n let out = '';\n let i = 0;\n for (;;) {\n const at = value.indexOf('var(', i);\n if (at < 0) return out + value.slice(i);\n const end = closing(value, at + 3);\n if (end < 0) throw new Error(`expandVars: unclosed var() in \"${value}\"`);\n const inner = value.slice(at + 4, end);\n const comma = inner.indexOf(',');\n const name = (comma < 0 ? inner : inner.slice(0, comma)).trim();\n const fallback = comma < 0 ? undefined : inner.slice(comma + 1).trim();\n if (seen.includes(name)) throw new Error(`expandVars: ${name} refers to itself`);\n const own = tokens[name];\n const raw = own ?? fallback;\n if (raw === undefined) throw new Error(`expandVars: ${name} is not in the theme and has no fallback`);\n out += value.slice(i, at) + expandVars(raw, tokens, own === undefined ? seen : [...seen, name]);\n i = end + 1;\n }\n}\n\n/** A `box-shadow` value's layers, first (topmost) first; `none` has none. Lengths must be px or a bare 0. */\nexport function parseBoxShadow(value: string): BoxShadow[] {\n if (value.trim() === 'none') return [];\n return splitTop(value, /,/).map((layer) => {\n let inset = false;\n const lengths: number[] = [];\n const color: string[] = [];\n for (const word of splitTop(layer, /\\s/)) {\n if (word === 'inset') { inset = true; continue; }\n const n = readCssNumber(word);\n if (n && (n.unit === 'px' || (n.unit === '' && n.value === 0))) { lengths.push(n.value); continue; }\n if (n) throw new Error(`parseBoxShadow: ${word} is not a px length`);\n color.push(word);\n }\n if (lengths.length < 2 || lengths.length > 4) throw new Error(`parseBoxShadow: cannot read \"${layer}\"`);\n const [x, y, blur = 0, spread = 0] = lengths as [number, number, number?, number?];\n return { inset, x, y, blur, spread, color: color.length ? color.join(' ') : 'currentColor' };\n });\n}\n","import { ALPHA_EXT, type FlatTokens, type RawToken, type TokenValue } from './types';\n\ninterface DtcgToken {\n $value: TokenValue;\n $type?: string;\n $description?: string;\n $extensions?: Record<string, unknown>;\n}\n\nconst isToken = (v: unknown): v is DtcgToken =>\n typeof v === 'object' && v !== null && '$value' in v;\n\n/**\n * Collapse a DTCG document into flat token names.\n *\n * Groups exist only to carry `$type`; they contribute nothing to the name, so\n * `color.fg-muted` becomes `fg-muted` and in turn `--wzl-fg-muted`. This shape\n * is forced by the token set: `--wzl-accent` and `--wzl-accent-base` are both\n * real tokens, and DTCG forbids a token that is also a group.\n */\nexport function flattenTokens(doc: Record<string, unknown>): FlatTokens {\n const out: FlatTokens = {};\n\n for (const [groupName, group] of Object.entries(doc)) {\n if (groupName.startsWith('$')) continue;\n if (typeof group !== 'object' || group === null) continue;\n\n const g = group as Record<string, unknown> & { $type?: string };\n const groupType = g.$type;\n\n for (const [leaf, node] of Object.entries(g)) {\n if (leaf.startsWith('$')) continue;\n if (!isToken(node)) continue;\n\n const type = node.$type ?? groupType;\n if (!type) {\n throw new Error(`Token \"${leaf}\" has no $type and its group \"${groupName}\" declares none`);\n }\n if (leaf in out) {\n throw new Error(`Duplicate token name \"${leaf}\" — leaf keys must be unique across type groups`);\n }\n\n const alphaRaw = node.$extensions?.[ALPHA_EXT];\n const token: RawToken = {\n type,\n value: node.$value,\n alpha: typeof alphaRaw === 'number' ? alphaRaw : undefined,\n description: node.$description,\n };\n out[leaf] = token;\n }\n }\n\n return out;\n}\n","import { isPlainObject } from '@weasel-js/registry';\nimport { mergeAxes, type AxisDef, type AxisDefs, type Selection, type Varying } from './axes';\nimport { AXES_EXT, overrideKey, type DtcgAxesExtension } from './dtcg/axesExtension';\nimport { flattenTokens } from './dtcg/flatten';\nimport type { FlatTokens, RawToken } from './dtcg/types';\nimport { themeAxes } from './resolveTheme';\nimport { weaselTheme, type Theme } from './theme';\n\n/** What `loadDTCG` reads: a `toDTCG` export, or a document shaped like one. */\nexport interface DtcgDocument {\n name?: unknown;\n defaultMode?: unknown;\n extends?: Theme | null;\n primitives?: Record<string, unknown>;\n modes?: Record<string, Record<string, unknown>>;\n $extensions?: Record<string, unknown>;\n}\n\ninterface Layer {\n readonly primitives: FlatTokens;\n readonly modes: Record<string, FlatTokens>;\n}\n\nconst isRecord = isPlainObject;\n\nfunction readLayer(src: { primitives?: unknown; modes?: unknown }): Layer {\n const modes = isRecord(src.modes) ? src.modes : {};\n return {\n primitives: flattenTokens(isRecord(src.primitives) ? src.primitives : {}),\n modes: Object.fromEntries(Object.entries(modes).map(([m, g]) => [m, flattenTokens(isRecord(g) ? g : {})])),\n };\n}\n\nfunction readAxesExtension(raw: unknown): DtcgAxesExtension | undefined {\n if (raw === undefined) return undefined;\n if (!isRecord(raw) || !isRecord(raw.axes)) throw new Error(`DTCG \"$extensions.${AXES_EXT}\" needs an \"axes\" object`);\n return {\n axes: raw.axes as AxisDefs,\n varies: (isRecord(raw.varies) ? raw.varies : {}) as DtcgAxesExtension['varies'],\n overrides: (isRecord(raw.overrides) ? raw.overrides : {}) as DtcgAxesExtension['overrides'],\n };\n}\n\n/**\n * Build a `Theme` from a DTCG document — the interchange path, for tokens\n * exported by a design tool rather than authored in TS. A token a mode leaves\n * out takes the document's primitive of the same name, or else the base theme's.\n * Axes besides mode come from `$extensions[\"com.weasel.axes\"]`, the encoding\n * `toDTCG` writes; a document without it loads with mode as its only axis.\n */\nexport function loadDTCG(doc: DtcgDocument): Theme {\n if (typeof doc.name !== 'string' || doc.name === '') {\n throw new Error('DTCG document needs a string \"name\"');\n }\n const base = doc.extends === undefined ? weaselTheme : doc.extends;\n const ext = readAxesExtension(doc.$extensions?.[AXES_EXT]);\n const plain = readLayer(doc);\n const overrides = Object.fromEntries(Object.entries(ext?.overrides ?? {}).map(([k, l]) => [k, readLayer(l)]));\n const modeNames = [...new Set([plain, ...Object.values(overrides)].flatMap((l) => Object.keys(l.modes)))];\n\n /** A token's value within one layer: varying by mode if any mode names it. */\n const tokenIn = (layer: Layer, name: string): Varying<RawToken> | undefined => {\n if (!modeNames.some((m) => layer.modes[m]?.[name])) return layer.primitives[name];\n const branch: Record<string, unknown> = { by: 'mode' };\n for (const m of modeNames) {\n const t = layer.modes[m]?.[name] ?? layer.primitives[name];\n if (t) branch[m] = t;\n }\n return branch as Varying<RawToken>;\n };\n\n const inherited = base ? themeAxes(base).mode?.default : undefined;\n const defaultMode = typeof doc.defaultMode === 'string' ? doc.defaultMode : (ext?.axes.mode?.default ?? inherited ?? 'dark');\n const modeAxis: AxisDef = {\n default: defaultMode,\n values: Object.fromEntries(modeNames.map((m) => [m, ext?.axes.mode?.values[m] ?? {}])),\n };\n const axes: Record<string, AxisDef> = {};\n for (const [name, def] of Object.entries(ext?.axes ?? { mode: modeAxis })) {\n if (name !== 'mode') axes[name] = def;\n else if (modeNames.length > 0) axes.mode = modeAxis;\n }\n if (modeNames.length > 0) axes.mode ??= modeAxis;\n const all = mergeAxes(base ? themeAxes(base) : {}, axes);\n\n /** Rebuild a token's tree over the axes it varies by, one override layer per leaf. */\n const nest = (name: string, vary: readonly string[], combo: Selection): Varying<RawToken> | undefined => {\n if (vary.length === 0) {\n const key = overrideKey(all, combo);\n const layer = key === '' ? plain : overrides[key];\n return layer && tokenIn(layer, name);\n }\n const [axis, ...rest] = vary;\n const out: Record<string, unknown> = { by: axis };\n let any = false;\n for (const value of Object.keys(all[axis].values)) {\n const v = nest(name, rest, { ...combo, [axis]: value });\n if (v !== undefined) {\n out[value] = v;\n any = true;\n }\n }\n return any ? (out as Varying<RawToken>) : undefined;\n };\n\n const tokens: Record<string, Varying<RawToken>> = {};\n const names = new Set([...Object.keys(plain.primitives), ...modeNames.flatMap((m) => Object.keys(plain.modes[m] ?? {}))]);\n for (const name of Object.keys(ext?.varies ?? {})) names.add(name);\n for (const name of names) {\n const vary = (ext?.varies[name] ?? []).filter((a) => a in all);\n const v = vary.length > 0 ? nest(name, vary, {}) : tokenIn(plain, name);\n if (v !== undefined) tokens[name] = v;\n }\n\n return { name: doc.name, extends: base, axes, tokens };\n}\n","/**\n * The vocabulary of stances, and the slots a theme styles a stanced surface with.\n *\n * A stance looks the same on every surface that takes one. A surface reads\n * `--wzl-stance-<stance>-<slot>` first — a nested panel\n * `--wzl-stance-<stance>-nested-<slot>` before that — and falls back to its\n * own base look, so a theme declares only the slots where a stance differs and\n * every other name here is read, with its fallback, and declared by nothing.\n * A panel's base look is itself theme slots, `--wzl-panel-<slot>`.\n */\n\n/** What kind of content a surface holds — a class of content, never a position. */\nexport const STANCES = ['scope', 'aside', 'advanced', 'debug', 'danger', 'notice', 'important', 'preview'] as const;\n\n/** One of {@link STANCES}. */\nexport type Stance = (typeof STANCES)[number];\n\n/** One styleable property of a stanced surface. */\nexport interface StanceSlot {\n readonly name: string;\n /** What it drives, for tooling. */\n readonly drives: string;\n}\n\n/** Every slot a theme can set per stance, as `--wzl-stance-<stance>-<slot>`. */\nexport const STANCE_SLOTS: readonly StanceSlot[] = [\n { name: 'surface', drives: 'background' },\n { name: 'border-color', drives: 'border-color' },\n { name: 'border-style', drives: 'border-style' },\n { name: 'border-width', drives: 'border-width' },\n { name: 'radius', drives: 'border-radius' },\n { name: 'pad', drives: 'padding' },\n { name: 'blur', drives: 'backdrop-filter' },\n { name: 'tone-mix', drives: 'how much of the tone mixes into the surface' },\n { name: 'tone', drives: 'the tone a surface takes when it names none' },\n // Only a surface that names its own tone recolors its controls.\n { name: 'accent', drives: 'the accent the controls inside a surface with a tone take; unset, the tone' },\n { name: 'title-font', drives: 'font-family' },\n { name: 'title-weight', drives: 'font-weight' },\n { name: 'title-size', drives: 'font-size' },\n { name: 'title-case', drives: 'text-transform' },\n { name: 'title-tracking', drives: 'letter-spacing' },\n { name: 'title-color', drives: 'color' },\n { name: 'title-inset', drives: 'the title’s padding' },\n];\n\n/** Every stance-slot name, `--wzl-`-prefixed, nested variants included. */\nexport function stanceSlotNames(): string[] {\n return STANCES.flatMap((stance) =>\n STANCE_SLOTS.flatMap((slot) => [`--wzl-stance-${stance}-${slot.name}`, `--wzl-stance-${stance}-nested-${slot.name}`]),\n );\n}\n\n/** What `resolveStanceSlots` resolves a surface against, besides its tokens. */\nexport interface StanceLookup<S extends string> {\n readonly stance?: Stance;\n /** The surface sits inside one of its own kind, and reads `-nested-<slot>` first. */\n readonly nested?: boolean;\n /** A stanced surface's fallback, where it differs from `base`. */\n readonly stanced?: Partial<Readonly<Record<S, string>>>;\n}\n\n/**\n * A stanced surface's look, for one drawn without the cascade — a canvas\n * surface reading a resolved theme. The same lookup the generated CSS makes:\n * `--wzl-stance-<stance>-<slot>`, then the stanced fallback, then `base`.\n * `base` holds final values, one per slot the surface draws.\n *\n * The tone is the caller's: a surface that names one mixes it into\n * `surface` at `tone-mix`; one that names none takes the `tone` slot, which\n * falls back to `surface` so mixing it changes nothing.\n */\nexport function resolveStanceSlots<S extends string>(\n tokens: Readonly<Record<string, string>>,\n base: Readonly<Record<S, string>>,\n { stance, nested, stanced }: StanceLookup<S> = {},\n): Record<S, string> {\n const out: Record<S, string> = { ...base };\n if (stance === undefined) return out;\n for (const slot of Object.keys(base) as S[]) {\n const own = tokens[`--wzl-stance-${stance}-${slot}`];\n const inner = nested ? tokens[`--wzl-stance-${stance}-nested-${slot}`] : undefined;\n // A stance's own tone falls back to the surface, never to the surface's base tone.\n const fallback = slot === 'tone' ? (base as Record<string, string>).surface ?? base[slot] : stanced?.[slot] ?? base[slot];\n out[slot] = inner ?? own ?? fallback;\n }\n return out;\n}\n"]}
1
+ {"version":3,"sources":["../src/tokenPx.ts","../src/boxShadow.ts","../src/dtcg/flatten.ts","../src/loadDTCG.ts","../src/appearance.ts","../src/panel.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { TOKEN_MANIFEST } from './generated/manifest';\nimport type { ResolvedTheme } from './resolveTheme';\nimport type { TokenName } from './generated/themes';\n\nconst DEFAULTS = new Map<string, string>(TOKEN_MANIFEST.map((t) => [t.name, t.defaultValue]));\n\n/**\n * A px-valued token as a number, for code that draws rather than styles —\n * SVG geometry attributes, canvas, WebGL. Pass `resolved` (from\n * `useTheme().resolved`) where a live theme override must reach the drawing;\n * without it the built-in theme's value is used, which is static and costs no\n * style resolution.\n *\n * Throws rather than guessing: a token that is not a plain px length has no\n * number, and silently returning 0 collapses whatever it sized.\n */\nexport function tokenPx(name: TokenName, resolved?: ResolvedTheme): number {\n const raw = resolved?.[name] ?? DEFAULTS.get(name);\n const m = /^(-?\\d*\\.?\\d+)px$/.exec((raw ?? '').trim());\n if (!m) throw new Error(`tokenPx: ${name} is not a px length (${raw ?? 'unknown token'})`);\n return Number(m[1]);\n}\n","import { readCssNumber } from './cssNumber';\n\n/** One layer of a CSS `box-shadow`, lengths in px. */\nexport interface BoxShadow {\n inset: boolean;\n x: number;\n y: number;\n blur: number;\n spread: number;\n /** As written; `currentColor` when the layer names none. */\n color: string;\n}\n\n/** `css` split at each top-level `sep`, ignoring any inside parentheses. */\nfunction splitTop(css: string, sep: RegExp): string[] {\n const out: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < css.length; i++) {\n const ch = css[i]!;\n if (ch === '(') depth++;\n else if (ch === ')') depth--;\n else if (depth === 0 && sep.test(ch)) {\n out.push(css.slice(start, i));\n start = i + 1;\n }\n }\n out.push(css.slice(start));\n return out.map((s) => s.trim()).filter((s) => s !== '');\n}\n\n/** The index of the `)` closing the `(` at `open`, or -1. */\nfunction closing(css: string, open: number): number {\n let depth = 0;\n for (let i = open; i < css.length; i++) {\n if (css[i] === '(') depth++;\n else if (css[i] === ')' && --depth === 0) return i;\n }\n return -1;\n}\n\n/**\n * `value` with every `var(--name)` and `var(--name, fallback)` replaced as a browser would: by\n * `tokens[name]`, expanded in turn, or by the fallback when the theme has no such token. A\n * resolved theme can hold references (a theme's bevel names its bevel colors), and a canvas\n * reading one has no cascade to substitute them. Throws on a reference with neither.\n */\nexport function expandVars(value: string, tokens: Readonly<Record<string, string>>, seen: readonly string[] = []): string {\n let out = '';\n let i = 0;\n for (;;) {\n const at = value.indexOf('var(', i);\n if (at < 0) return out + value.slice(i);\n const end = closing(value, at + 3);\n if (end < 0) throw new Error(`expandVars: unclosed var() in \"${value}\"`);\n const inner = value.slice(at + 4, end);\n const comma = inner.indexOf(',');\n const name = (comma < 0 ? inner : inner.slice(0, comma)).trim();\n const fallback = comma < 0 ? undefined : inner.slice(comma + 1).trim();\n if (seen.includes(name)) throw new Error(`expandVars: ${name} refers to itself`);\n const own = tokens[name];\n const raw = own ?? fallback;\n if (raw === undefined) throw new Error(`expandVars: ${name} is not in the theme and has no fallback`);\n out += value.slice(i, at) + expandVars(raw, tokens, own === undefined ? seen : [...seen, name]);\n i = end + 1;\n }\n}\n\n/** A `box-shadow` value's layers, first (topmost) first; `none` has none. Lengths must be px or a bare 0. */\nexport function parseBoxShadow(value: string): BoxShadow[] {\n if (value.trim() === 'none') return [];\n return splitTop(value, /,/).map((layer) => {\n let inset = false;\n const lengths: number[] = [];\n const color: string[] = [];\n for (const word of splitTop(layer, /\\s/)) {\n if (word === 'inset') { inset = true; continue; }\n const n = readCssNumber(word);\n if (n && (n.unit === 'px' || (n.unit === '' && n.value === 0))) { lengths.push(n.value); continue; }\n if (n) throw new Error(`parseBoxShadow: ${word} is not a px length`);\n color.push(word);\n }\n if (lengths.length < 2 || lengths.length > 4) throw new Error(`parseBoxShadow: cannot read \"${layer}\"`);\n const [x, y, blur = 0, spread = 0] = lengths as [number, number, number?, number?];\n return { inset, x, y, blur, spread, color: color.length ? color.join(' ') : 'currentColor' };\n });\n}\n","import { ALPHA_EXT, type FlatTokens, type RawToken, type TokenValue } from './types';\n\ninterface DtcgToken {\n $value: TokenValue;\n $type?: string;\n $description?: string;\n $extensions?: Record<string, unknown>;\n}\n\nconst isToken = (v: unknown): v is DtcgToken =>\n typeof v === 'object' && v !== null && '$value' in v;\n\n/**\n * Collapse a DTCG document into flat token names.\n *\n * Groups exist only to carry `$type`; they contribute nothing to the name, so\n * `color.fg-muted` becomes `fg-muted` and in turn `--wzl-fg-muted`. This shape\n * is forced by the token set: `--wzl-accent` and `--wzl-accent-base` are both\n * real tokens, and DTCG forbids a token that is also a group.\n */\nexport function flattenTokens(doc: Record<string, unknown>): FlatTokens {\n const out: FlatTokens = {};\n\n for (const [groupName, group] of Object.entries(doc)) {\n if (groupName.startsWith('$')) continue;\n if (typeof group !== 'object' || group === null) continue;\n\n const g = group as Record<string, unknown> & { $type?: string };\n const groupType = g.$type;\n\n for (const [leaf, node] of Object.entries(g)) {\n if (leaf.startsWith('$')) continue;\n if (!isToken(node)) continue;\n\n const type = node.$type ?? groupType;\n if (!type) {\n throw new Error(`Token \"${leaf}\" has no $type and its group \"${groupName}\" declares none`);\n }\n if (leaf in out) {\n throw new Error(`Duplicate token name \"${leaf}\" — leaf keys must be unique across type groups`);\n }\n\n const alphaRaw = node.$extensions?.[ALPHA_EXT];\n const token: RawToken = {\n type,\n value: node.$value,\n alpha: typeof alphaRaw === 'number' ? alphaRaw : undefined,\n description: node.$description,\n };\n out[leaf] = token;\n }\n }\n\n return out;\n}\n","import { isPlainObject } from '@weasel-js/registry';\nimport { mergeAxes, type AxisDef, type AxisDefs, type Selection, type Varying } from './axes';\nimport { AXES_EXT, overrideKey, type DtcgAxesExtension } from './dtcg/axesExtension';\nimport { flattenTokens } from './dtcg/flatten';\nimport type { FlatTokens, RawToken } from './dtcg/types';\nimport { themeAxes } from './resolveTheme';\nimport { weaselTheme, type Theme } from './theme';\n\n/** What `loadDTCG` reads: a `toDTCG` export, or a document shaped like one. */\nexport interface DtcgDocument {\n name?: unknown;\n defaultMode?: unknown;\n extends?: Theme | null;\n primitives?: Record<string, unknown>;\n modes?: Record<string, Record<string, unknown>>;\n $extensions?: Record<string, unknown>;\n}\n\ninterface Layer {\n readonly primitives: FlatTokens;\n readonly modes: Record<string, FlatTokens>;\n}\n\nconst isRecord = isPlainObject;\n\nfunction readLayer(src: { primitives?: unknown; modes?: unknown }): Layer {\n const modes = isRecord(src.modes) ? src.modes : {};\n return {\n primitives: flattenTokens(isRecord(src.primitives) ? src.primitives : {}),\n modes: Object.fromEntries(Object.entries(modes).map(([m, g]) => [m, flattenTokens(isRecord(g) ? g : {})])),\n };\n}\n\nfunction readAxesExtension(raw: unknown): DtcgAxesExtension | undefined {\n if (raw === undefined) return undefined;\n if (!isRecord(raw) || !isRecord(raw.axes)) throw new Error(`DTCG \"$extensions.${AXES_EXT}\" needs an \"axes\" object`);\n return {\n axes: raw.axes as AxisDefs,\n varies: (isRecord(raw.varies) ? raw.varies : {}) as DtcgAxesExtension['varies'],\n overrides: (isRecord(raw.overrides) ? raw.overrides : {}) as DtcgAxesExtension['overrides'],\n };\n}\n\n/**\n * Build a `Theme` from a DTCG document — the interchange path, for tokens\n * exported by a design tool rather than authored in TS. A token a mode leaves\n * out takes the document's primitive of the same name, or else the base theme's.\n * Axes besides mode come from `$extensions[\"com.weasel.axes\"]`, the encoding\n * `toDTCG` writes; a document without it loads with mode as its only axis.\n */\nexport function loadDTCG(doc: DtcgDocument): Theme {\n if (typeof doc.name !== 'string' || doc.name === '') {\n throw new Error('DTCG document needs a string \"name\"');\n }\n const base = doc.extends === undefined ? weaselTheme : doc.extends;\n const ext = readAxesExtension(doc.$extensions?.[AXES_EXT]);\n const plain = readLayer(doc);\n const overrides = Object.fromEntries(Object.entries(ext?.overrides ?? {}).map(([k, l]) => [k, readLayer(l)]));\n const modeNames = [...new Set([plain, ...Object.values(overrides)].flatMap((l) => Object.keys(l.modes)))];\n\n /** A token's value within one layer: varying by mode if any mode names it. */\n const tokenIn = (layer: Layer, name: string): Varying<RawToken> | undefined => {\n if (!modeNames.some((m) => layer.modes[m]?.[name])) return layer.primitives[name];\n const branch: Record<string, unknown> = { by: 'mode' };\n for (const m of modeNames) {\n const t = layer.modes[m]?.[name] ?? layer.primitives[name];\n if (t) branch[m] = t;\n }\n return branch as Varying<RawToken>;\n };\n\n const inherited = base ? themeAxes(base).mode?.default : undefined;\n const defaultMode = typeof doc.defaultMode === 'string' ? doc.defaultMode : (ext?.axes.mode?.default ?? inherited ?? 'dark');\n const modeAxis: AxisDef = {\n default: defaultMode,\n values: Object.fromEntries(modeNames.map((m) => [m, ext?.axes.mode?.values[m] ?? {}])),\n };\n const axes: Record<string, AxisDef> = {};\n for (const [name, def] of Object.entries(ext?.axes ?? { mode: modeAxis })) {\n if (name !== 'mode') axes[name] = def;\n else if (modeNames.length > 0) axes.mode = modeAxis;\n }\n if (modeNames.length > 0) axes.mode ??= modeAxis;\n const all = mergeAxes(base ? themeAxes(base) : {}, axes);\n\n /** Rebuild a token's tree over the axes it varies by, one override layer per leaf. */\n const nest = (name: string, vary: readonly string[], combo: Selection): Varying<RawToken> | undefined => {\n if (vary.length === 0) {\n const key = overrideKey(all, combo);\n const layer = key === '' ? plain : overrides[key];\n return layer && tokenIn(layer, name);\n }\n const [axis, ...rest] = vary;\n const out: Record<string, unknown> = { by: axis };\n let any = false;\n for (const value of Object.keys(all[axis].values)) {\n const v = nest(name, rest, { ...combo, [axis]: value });\n if (v !== undefined) {\n out[value] = v;\n any = true;\n }\n }\n return any ? (out as Varying<RawToken>) : undefined;\n };\n\n const tokens: Record<string, Varying<RawToken>> = {};\n const names = new Set([...Object.keys(plain.primitives), ...modeNames.flatMap((m) => Object.keys(plain.modes[m] ?? {}))]);\n for (const name of Object.keys(ext?.varies ?? {})) names.add(name);\n for (const name of names) {\n const vary = (ext?.varies[name] ?? []).filter((a) => a in all);\n const v = vary.length > 0 ? nest(name, vary, {}) : tokenIn(plain, name);\n if (v !== undefined) tokens[name] = v;\n }\n\n return { name: doc.name, extends: base, axes, tokens };\n}\n","/** The angle a component comes from: who it is for, how it speaks, what an action does. */\nexport const STANCES = ['clarify', 'aside', 'advanced', 'debug', 'preview', 'confirm', 'cancel'] as const;\n/** One stance. */\nexport type Stance = (typeof STANCES)[number];\n\n/** How serious, or how good. The only axis that paints red. */\nexport const GRADES = ['info', 'success', 'warn', 'danger'] as const;\n/** One grade. */\nexport type Grade = (typeof GRADES)[number];\n\n/** The token each grade paints with. */\nexport const GRADE_TOKENS: Readonly<Record<Grade, string>> = {\n info: '--wzl-info',\n success: '--wzl-success',\n warn: '--wzl-warning',\n danger: '--wzl-danger',\n};\n\n/** How loudly a component reads. Unset is normal. */\nexport const EMPHASES = ['high', 'low'] as const;\n/** One emphasis level; unset reads as normal. */\nexport type Emphasis = (typeof EMPHASES)[number];\n\n/** The text color an emphasis lends to everything inside it, as `--wzl-emphasis-fg`. */\nexport const EMPHASIS_FG: Readonly<Record<Emphasis, string>> = {\n high: 'var(--wzl-accent-fg)',\n low: 'var(--wzl-fg-muted)',\n};\n\n/** The surface slots an emphasis repaints, beyond the text color it hands down. */\nexport const EMPHASIS_SLOTS: Readonly<Record<Emphasis, Partial<Record<'border-color' | 'title-color', string>>>> = {\n high: { 'border-color': 'var(--wzl-accent-fg)', 'title-color': 'var(--wzl-accent-fg)' },\n low: { 'title-color': 'var(--wzl-fg-muted)' },\n};\n\n/** The surface slots a grade repaints in its color. */\nexport const GRADE_SLOTS = ['tint', 'border-color', 'title-color'] as const;\n","/**\n * The slots a theme styles a stanced surface with. A stance is the angle a\n * surface comes from, not a class of content.\n *\n * A stance looks the same on every surface that takes one. A surface reads\n * `--wzl-stance-<stance>-<slot>` first — a nested panel\n * `--wzl-stance-<stance>-nested-<slot>` before that — and falls back to its\n * own base look, so a theme declares only the slots where a stance differs and\n * every other name here is read, with its fallback, and declared by nothing.\n * A panel's base look is itself theme slots, `--wzl-panel-<slot>`.\n */\nimport { type Stance, STANCES } from './appearance';\n\n/** One styleable property of a stanced surface. */\nexport interface StanceSlot {\n readonly name: string;\n /** What it drives, for tooling. */\n readonly drives: string;\n}\n\n/** Every slot a theme can set per stance, as `--wzl-stance-<stance>-<slot>`. */\nexport const STANCE_SLOTS: readonly StanceSlot[] = [\n { name: 'surface', drives: 'background' },\n { name: 'border-color', drives: 'border-color' },\n { name: 'border-style', drives: 'border-style' },\n { name: 'border-width', drives: 'border-width' },\n { name: 'radius', drives: 'border-radius' },\n { name: 'pad', drives: 'padding' },\n { name: 'blur', drives: 'backdrop-filter' },\n { name: 'tint-mix', drives: 'how much of the tint mixes into the surface' },\n { name: 'tint', drives: 'the tint a surface takes when it names none' },\n // Only a surface that names its own tint or grade recolors its controls.\n { name: 'accent', drives: 'the accent the controls inside a tinted or graded surface take; unset, the tint' },\n { name: 'title-font', drives: 'font-family' },\n { name: 'title-weight', drives: 'font-weight' },\n { name: 'title-size', drives: 'font-size' },\n { name: 'title-case', drives: 'text-transform' },\n { name: 'title-tracking', drives: 'letter-spacing' },\n { name: 'title-color', drives: 'color' },\n { name: 'title-inset', drives: 'the title’s padding' },\n];\n\n/** Every stance-slot name, `--wzl-`-prefixed, nested variants included. */\nexport function stanceSlotNames(): string[] {\n return STANCES.flatMap((stance) =>\n STANCE_SLOTS.flatMap((slot) => [`--wzl-stance-${stance}-${slot.name}`, `--wzl-stance-${stance}-nested-${slot.name}`]),\n );\n}\n\n/** What `resolveStanceSlots` resolves a surface against, besides its tokens. */\nexport interface StanceLookup<S extends string> {\n readonly stance?: Stance;\n /** The surface sits inside one of its own kind, and reads `-nested-<slot>` first. */\n readonly nested?: boolean;\n /** A stanced surface's fallback, where it differs from `base`. */\n readonly stanced?: Partial<Readonly<Record<S, string>>>;\n}\n\n/**\n * A stanced surface's look, for one drawn without the cascade — a canvas\n * surface reading a resolved theme. The same lookup the generated CSS makes:\n * `--wzl-stance-<stance>-<slot>`, then the stanced fallback, then `base`.\n * `base` holds final values, one per slot the surface draws.\n *\n * The tint is the caller's: a surface that names one mixes it into\n * `surface` at `tint-mix`; one that names none takes the `tint` slot, which\n * falls back to `surface` so mixing it changes nothing.\n */\nexport function resolveStanceSlots<S extends string>(\n tokens: Readonly<Record<string, string>>,\n base: Readonly<Record<S, string>>,\n { stance, nested, stanced }: StanceLookup<S> = {},\n): Record<S, string> {\n const out: Record<S, string> = { ...base };\n if (stance === undefined) return out;\n for (const slot of Object.keys(base) as S[]) {\n const own = tokens[`--wzl-stance-${stance}-${slot}`];\n const inner = nested ? tokens[`--wzl-stance-${stance}-nested-${slot}`] : undefined;\n // A stance's own tint falls back to the surface, never to the surface's base tint.\n const fallback = slot === 'tint' ? (base as Record<string, string>).surface ?? base[slot] : stanced?.[slot] ?? base[slot];\n out[slot] = inner ?? own ?? fallback;\n }\n return out;\n}\n"]}
package/dist/prefs.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { PrefGroup, PrefLocus } from '@weasel-js/prefs';
2
- import { a as Theme, V as Varying, e as PinValue, S as Selection } from './definition-CSeERbSL.js';
2
+ import { a as Theme, V as Varying, e as PinValue, S as Selection } from './definition-wsEi-XBr.js';
3
3
  import '@weasel-js/paint';
4
4
 
5
5
  /** The key of the group a theme's axes are chosen in: `axis.mode` is the leaf holding the mode. */
package/dist/prefs.js CHANGED
@@ -1,7 +1,7 @@
1
- import { TOKEN_MANIFEST } from './chunk-GE2WCTOV.js';
1
+ import { TOKEN_MANIFEST } from './chunk-EJBP2YIO.js';
2
2
  import { readCssNumber } from './chunk-M3R5MV7Q.js';
3
3
  import { themeAxes, resolveTheme, themeChain } from './chunk-32JKTYS2.js';
4
- import { weaselTheme, defineTheme } from './chunk-JX2OC444.js';
4
+ import { weaselTheme, defineTheme } from './chunk-R2SSGWGZ.js';
5
5
  import { selectionKey, enumerateSelections, isByAxis } from './chunk-P5F3GZV6.js';
6
6
  import { prefLeaves, isPrefLocus } from '@weasel-js/prefs';
7
7
  import { rgbaToHex, parseColor } from '@weasel-js/paint';
package/dist/react.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Palette, ColorSource } from '@weasel-js/paint';
2
2
  import React from 'react';
3
- import { a as Theme, S as Selection, r as ResolvedTheme, o as ColorList } from './definition-CSeERbSL.js';
3
+ import { a as Theme, S as Selection, r as ResolvedTheme, o as ColorList } from './definition-wsEi-XBr.js';
4
4
  import { a as ColorModePreference, C as ColorMode } from './colorMode-CoklZomJ.js';
5
5
  export { i as isColorModePreference } from './colorMode-CoklZomJ.js';
6
6
 
@@ -36,12 +36,12 @@ interface ColorModePreferenceState {
36
36
  declare function useColorModePreference(options?: ColorModePreferenceOptions): ColorModePreferenceState;
37
37
 
38
38
  /** What `<ThemeProvider>` publishes: the theme, the full selection in force, the
39
- * fully resolved token record for that pair, and the tone list and palette in force. */
39
+ * fully resolved token record for that pair, and the tint list and palette in force. */
40
40
  interface ThemeContextValue {
41
41
  readonly theme: Theme;
42
42
  readonly selection: Selection;
43
43
  readonly resolved: ResolvedTheme;
44
- readonly tones: ColorList;
44
+ readonly tints: ColorList;
45
45
  readonly palette: Palette;
46
46
  }
47
47
  /** What `<ThemeProvider>` publishes. Provide `null` to hide an outer theme from a subtree, as a
@@ -54,8 +54,8 @@ interface ThemeProviderProps {
54
54
  * follows the OS setting, live; any other value the theme lacks takes the default, with a
55
55
  * warning in development. */
56
56
  readonly selection?: Selection;
57
- /** The colors a `tone` index picks from in this subtree. Absent: the theme's own. */
58
- readonly tones?: ColorList;
57
+ /** The colors a `tint` index picks from in this subtree. Absent: the theme's own. */
58
+ readonly tints?: ColorList;
59
59
  /** Colors a `ColorRef` names in this subtree, answered before the theme's own names. Absent: none. */
60
60
  readonly palette?: Palette;
61
61
  /** Applied to the wrapper element, so it can be the layout element too. */
@@ -73,7 +73,7 @@ interface ThemeProviderProps {
73
73
  * nesting your own div inside — an anonymous div between a flex parent and
74
74
  * its child breaks percentage heights.
75
75
  */
76
- declare function ThemeProvider({ theme, selection, tones, palette, className, style, children, }: ThemeProviderProps): React.ReactElement;
76
+ declare function ThemeProvider({ theme, selection, tints, palette, className, style, children, }: ThemeProviderProps): React.ReactElement;
77
77
  /** The theme in force. Throws outside a `<ThemeProvider>`; use
78
78
  * `useThemeOptional` where the provider is not guaranteed. */
79
79
  declare function useTheme(): ThemeContextValue;
@@ -86,24 +86,24 @@ declare function useTheme(): ThemeContextValue;
86
86
  */
87
87
  declare function useThemeOptional(): ThemeContextValue | null;
88
88
  /**
89
- * The tone list in force and what it resolves against — the nearest
89
+ * The tint list in force and what it resolves against — the nearest
90
90
  * `<ThemeProvider>`'s, else the built-in theme's at its defaults. Pass the
91
91
  * result as `colorAt`'s context.
92
92
  */
93
- declare function useTones(): ThemeContextValue;
93
+ declare function useTints(): ThemeContextValue;
94
94
  /**
95
- * Turns a `ColorSource` into a CSS color under the theme, tones, and palette in
96
- * force: `colorSourceCss` against `useTones()`. Every component that takes a
95
+ * Turns a `ColorSource` into a CSS color under the theme, tints, and palette in
96
+ * force: `colorSourceCss` against `useTints()`. Every component that takes a
97
97
  * color writes it through this. `undefined` for no source, and for one nothing
98
98
  * answers.
99
99
  */
100
100
  declare function useColorCss(): (source: ColorSource | null | undefined) => string | undefined;
101
101
  /**
102
- * Turns a `ColorSource` into a hex color under the theme, tones, and palette in force, for a
102
+ * Turns a `ColorSource` into a hex color under the theme, tints, and palette in force, for a
103
103
  * surface drawn without the cascade, such as a scene's paint. `useColorCss` may answer
104
104
  * `var(--wzl-…)`, which only the DOM resolves; this answers the value. `undefined` for no
105
105
  * source, and for one nothing answers.
106
106
  */
107
107
  declare function useColorHex(): (source: ColorSource | null | undefined) => string | undefined;
108
108
 
109
- export { ColorMode, ColorModePreference, type ColorModePreferenceOptions, type ColorModePreferenceState, type ColorModeStorage, ThemeContext, type ThemeContextValue, ThemeProvider, type ThemeProviderProps, useColorCss, useColorHex, useColorModePreference, useResolvedColorMode, useTheme, useThemeOptional, useTones };
109
+ export { ColorMode, ColorModePreference, type ColorModePreferenceOptions, type ColorModePreferenceState, type ColorModeStorage, ThemeContext, type ThemeContextValue, ThemeProvider, type ThemeProviderProps, useColorCss, useColorHex, useColorModePreference, useResolvedColorMode, useTheme, useThemeOptional, useTints };
package/dist/react.js CHANGED
@@ -1,9 +1,9 @@
1
- import { isColorModePreference, themeTones, applyTheme, colorSourceCss, colorSourceLiteral } from './chunk-QGOGBCYW.js';
2
- export { isColorModePreference } from './chunk-QGOGBCYW.js';
1
+ import { isColorModePreference, themeTints, applyTheme, colorSourceCss, colorSourceLiteral } from './chunk-R7OXPHZJ.js';
2
+ export { isColorModePreference } from './chunk-R7OXPHZJ.js';
3
3
  import './chunk-S7MJPFDP.js';
4
4
  import './chunk-M3R5MV7Q.js';
5
5
  import { themeAxes, resolveTheme } from './chunk-32JKTYS2.js';
6
- import { weaselTheme } from './chunk-JX2OC444.js';
6
+ import { weaselTheme } from './chunk-R2SSGWGZ.js';
7
7
  import { fullSelection, selectionKey } from './chunk-P5F3GZV6.js';
8
8
  import { colorLiteralToHex } from '@weasel-js/paint';
9
9
  import { createContext, useState, useEffect, useCallback, useRef, useMemo, useLayoutEffect, useContext } from 'react';
@@ -64,7 +64,7 @@ var NO_PALETTE = { entries: [] };
64
64
  function ThemeProvider({
65
65
  theme = weaselTheme,
66
66
  selection,
67
- tones,
67
+ tints,
68
68
  palette = NO_PALETTE,
69
69
  className,
70
70
  style,
@@ -79,9 +79,9 @@ function ThemeProvider({
79
79
  warnUnknownAxisValues(theme, axes, given);
80
80
  const key = selectionKey(axes, full);
81
81
  const value = useMemo(
82
- () => ({ theme, selection: full, resolved: resolveTheme(theme, full), tones: tones ?? themeTones(theme), palette }),
82
+ () => ({ theme, selection: full, resolved: resolveTheme(theme, full), tints: tints ?? themeTints(theme), palette }),
83
83
  // eslint-disable-next-line react-hooks/exhaustive-deps
84
- [theme, key, tones, palette]
84
+ [theme, key, tints, palette]
85
85
  );
86
86
  const release = useRef(null);
87
87
  useLayoutEffect(() => {
@@ -113,24 +113,24 @@ function useTheme() {
113
113
  function useThemeOptional() {
114
114
  return useContext(ThemeContext);
115
115
  }
116
- var defaultTones;
117
- function useTones() {
116
+ var defaultTints;
117
+ function useTints() {
118
118
  const ctx = useContext(ThemeContext);
119
119
  if (ctx) return ctx;
120
- return defaultTones ??= {
120
+ return defaultTints ??= {
121
121
  theme: weaselTheme,
122
122
  selection: fullSelection(themeAxes(weaselTheme)),
123
123
  resolved: resolveTheme(weaselTheme),
124
- tones: themeTones(weaselTheme),
124
+ tints: themeTints(weaselTheme),
125
125
  palette: NO_PALETTE
126
126
  };
127
127
  }
128
128
  function useColorCss() {
129
- const ctx = useTones();
129
+ const ctx = useTints();
130
130
  return useCallback((source) => source == null ? void 0 : colorSourceCss(source, ctx) ?? void 0, [ctx]);
131
131
  }
132
132
  function useColorHex() {
133
- const ctx = useTones();
133
+ const ctx = useTints();
134
134
  return useCallback((source) => {
135
135
  if (source == null) return void 0;
136
136
  const literal = colorSourceLiteral(source, ctx);
@@ -138,6 +138,6 @@ function useColorHex() {
138
138
  }, [ctx]);
139
139
  }
140
140
 
141
- export { ThemeContext, ThemeProvider, useColorCss, useColorHex, useColorModePreference, useResolvedColorMode, useTheme, useThemeOptional, useTones };
141
+ export { ThemeContext, ThemeProvider, useColorCss, useColorHex, useColorModePreference, useResolvedColorMode, useTheme, useThemeOptional, useTints };
142
142
  //# sourceMappingURL=react.js.map
143
143
  //# sourceMappingURL=react.js.map
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/useColorMode.ts","../src/react.tsx"],"names":["systemMode","useCallback"],"mappings":"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","file":"react.js","sourcesContent":["import { useCallback, useEffect, useState } from 'react';\nimport { isColorModePreference, type ColorMode, type ColorModePreference } from './colorMode';\n\nfunction systemQuery(): MediaQueryList | null {\n if (typeof globalThis.matchMedia !== 'function') return null;\n return globalThis.matchMedia('(prefers-color-scheme: light)');\n}\n\nconst systemMode = (): ColorMode => (systemQuery()?.matches ? 'light' : 'dark');\n\n/**\n * Resolves a preference to the mode a `ThemeProvider` selection takes.\n * `'auto'` subscribes to the OS setting and follows it live; an explicit\n * choice opts out of the subscription entirely.\n */\nexport function useResolvedColorMode(preference: ColorModePreference): ColorMode {\n const [system, setSystem] = useState<ColorMode>(systemMode);\n\n useEffect(() => {\n if (preference !== 'auto') return;\n const mq = systemQuery();\n if (!mq) return;\n // eslint-disable-next-line react-hooks/set-state-in-effect -- syncs to the OS color-scheme query\n setSystem(mq.matches ? 'light' : 'dark');\n const onChange = (e: { matches: boolean }) => setSystem(e.matches ? 'light' : 'dark');\n mq.addEventListener('change', onChange);\n return () => mq.removeEventListener('change', onChange);\n }, [preference]);\n\n return preference === 'auto' ? system : preference;\n}\n\n/** The part of `Storage` {@link useColorModePreference} reads and writes. */\nexport type ColorModeStorage = Pick<Storage, 'getItem' | 'setItem'>;\n\n/** Options for {@link useColorModePreference}. */\nexport interface ColorModePreferenceOptions {\n /** Where the choice is remembered. Unset, it lasts as long as the component. */\n readonly storageKey?: string;\n /** The store `storageKey` names a slot in. Defaults to `localStorage`. */\n readonly storage?: ColorModeStorage;\n /** The preference before the user has chosen one. Defaults to `'auto'`. */\n readonly defaultPreference?: ColorModePreference;\n}\n\n/** What {@link useColorModePreference} returns. */\nexport interface ColorModePreferenceState {\n readonly preference: ColorModePreference;\n readonly setPreference: (next: ColorModePreference) => void;\n /** `preference` resolved against the OS — what to put in the theme's `mode` axis. */\n readonly mode: ColorMode;\n}\n\nfunction defaultStorage(): ColorModeStorage | undefined {\n try {\n return globalThis.localStorage ?? undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * A user's color-mode choice, optionally remembered across loads, and the mode\n * it resolves to. Storage that is missing or throws (a private window, blocked\n * site data) degrades to an unremembered choice rather than an error.\n */\nexport function useColorModePreference(\n options: ColorModePreferenceOptions = {},\n): ColorModePreferenceState {\n const { storageKey, storage, defaultPreference = 'auto' } = options;\n\n const [preference, setState] = useState<ColorModePreference>(() => {\n if (storageKey === undefined) return defaultPreference;\n try {\n const stored = (storage ?? defaultStorage())?.getItem(storageKey);\n return isColorModePreference(stored) ? stored : defaultPreference;\n } catch {\n return defaultPreference;\n }\n });\n\n const setPreference = useCallback(\n (next: ColorModePreference) => {\n setState(next);\n if (storageKey === undefined) return;\n try {\n (storage ?? defaultStorage())?.setItem(storageKey, next);\n } catch {\n // Unremembered, but still applied.\n }\n },\n [storageKey, storage],\n );\n\n return { preference, setPreference, mode: useResolvedColorMode(preference) };\n}\n","import { colorLiteralToHex, type ColorSource, type Palette } from '@weasel-js/paint';\nimport React, { createContext, useCallback, useContext, useMemo, useRef, useLayoutEffect } from 'react';\nimport { isDev } from '@weasel-js/registry';\nimport { applyTheme } from './applyTheme';\nimport { themeTones, type ColorList } from './colorList';\nimport { colorSourceCss, colorSourceLiteral } from './colorSource';\nimport { fullSelection, selectionKey, type Selection } from './axes';\nimport { resolveTheme, themeAxes, type ResolvedTheme } from './resolveTheme';\nimport { weaselTheme, type Theme } from './theme';\nimport { useResolvedColorMode } from './useColorMode';\n\nexport {\n useColorModePreference,\n useResolvedColorMode,\n type ColorModePreferenceOptions,\n type ColorModePreferenceState,\n type ColorModeStorage,\n} from './useColorMode';\nexport { isColorModePreference, type ColorMode, type ColorModePreference } from './colorMode';\n\n/** What `<ThemeProvider>` publishes: the theme, the full selection in force, the\n * fully resolved token record for that pair, and the tone list and palette in force. */\nexport interface ThemeContextValue {\n readonly theme: Theme;\n readonly selection: Selection;\n readonly resolved: ResolvedTheme;\n readonly tones: ColorList;\n readonly palette: Palette;\n}\n\n/** What `<ThemeProvider>` publishes. Provide `null` to hide an outer theme from a subtree, as a\n * boundary that renders its children the way a page with no provider would. */\nexport const ThemeContext = createContext<ThemeContextValue | null>(null);\n\nconst NO_PALETTE: Palette = { entries: [] };\n\n/** Props for `<ThemeProvider>`. */\nexport interface ThemeProviderProps {\n readonly theme?: Theme;\n /** Axis values, e.g. `{ mode: 'light' }`. A missing axis takes its default. `mode: 'auto'`\n * follows the OS setting, live; any other value the theme lacks takes the default, with a\n * warning in development. */\n readonly selection?: Selection;\n /** The colors a `tone` index picks from in this subtree. Absent: the theme's own. */\n readonly tones?: ColorList;\n /** Colors a `ColorRef` names in this subtree, answered before the theme's own names. Absent: none. */\n readonly palette?: Palette;\n /** Applied to the wrapper element, so it can be the layout element too. */\n readonly className?: string;\n readonly style?: React.CSSProperties;\n readonly children: React.ReactNode;\n}\n\n/**\n * Applies a theme to a wrapper element and publishes the resolved record.\n *\n * Consumers that draw outside the DOM (the WebGL HUD) read `resolved` and\n * never touch `getComputedStyle`.\n *\n * The wrapper is a real element in the layout. Pass `className` rather than\n * nesting your own div inside — an anonymous div between a flex parent and\n * its child breaks percentage heights.\n */\nexport function ThemeProvider({\n theme = weaselTheme,\n selection,\n tones,\n palette = NO_PALETTE,\n className,\n style,\n children,\n}: ThemeProviderProps): React.ReactElement {\n const ref = useRef<HTMLDivElement>(null);\n const axes = themeAxes(theme);\n const autoMode = selection?.mode === 'auto' && !('auto' in (axes.mode?.values ?? {}));\n const systemMode = useResolvedColorMode(autoMode ? 'auto' : 'dark');\n const given = autoMode ? { ...selection, mode: systemMode } : selection;\n const full = fullSelection(axes, given);\n warnUnknownAxisValues(theme, axes, given);\n // Keyed on the selection's content: callers pass a fresh object every render.\n const key = selectionKey(axes, full);\n\n const value = useMemo<ThemeContextValue>(\n () => ({ theme, selection: full, resolved: resolveTheme(theme, full), tones: tones ?? themeTones(theme), palette }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [theme, key, tones, palette],\n );\n\n // Applying again replaces what the element held, so only the unmount releases.\n const release = useRef<(() => void) | null>(null);\n useLayoutEffect(() => {\n if (ref.current) release.current = applyTheme(ref.current, theme, value.selection);\n }, [theme, value]);\n useLayoutEffect(() => () => release.current?.(), []);\n\n const attrs = Object.fromEntries(Object.keys(axes).map((a) => [`data-wzl-${a}`, full[a]]));\n return (\n <ThemeContext.Provider value={value}>\n <div ref={ref} className={className} style={style} data-wzl-theme={theme.name} {...attrs}>\n {children}\n </div>\n </ThemeContext.Provider>\n );\n}\n\nconst warned = new Set<string>();\n\nfunction warnUnknownAxisValues(theme: Theme, axes: ReturnType<typeof themeAxes>, selection: Selection | undefined): void {\n if (!selection || !isDev()) return;\n for (const [axis, value] of Object.entries(selection)) {\n const def = axes[axis];\n if (!def || value in def.values) continue;\n const key = `${theme.name}\\0${axis}\\0${value}`;\n if (warned.has(key)) continue;\n warned.add(key);\n console.warn(\n `[weasel theme] ThemeProvider: theme \"${theme.name}\" has no ${axis} \"${value}\"; using \"${def.default}\". Its ${axis} values: ${Object.keys(def.values).join(', ')}.`,\n );\n }\n}\n\n/** The theme in force. Throws outside a `<ThemeProvider>`; use\n * `useThemeOptional` where the provider is not guaranteed. */\nexport function useTheme(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (!ctx) throw new Error('useTheme must be used inside a <ThemeProvider>');\n return ctx;\n}\n\n/**\n * The theme if one is provided, `null` otherwise.\n *\n * For kit internals that should follow a theme when the app supplies one but\n * must still work in an app that never mounted a provider — `useHud` is the\n * motivating case.\n */\nexport function useThemeOptional(): ThemeContextValue | null {\n return useContext(ThemeContext);\n}\n\nlet defaultTones: ThemeContextValue | undefined;\n\n/**\n * The tone list in force and what it resolves against — the nearest\n * `<ThemeProvider>`'s, else the built-in theme's at its defaults. Pass the\n * result as `colorAt`'s context.\n */\nexport function useTones(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (ctx) return ctx;\n return (defaultTones ??= {\n theme: weaselTheme,\n selection: fullSelection(themeAxes(weaselTheme)),\n resolved: resolveTheme(weaselTheme),\n tones: themeTones(weaselTheme),\n palette: NO_PALETTE,\n });\n}\n\n/**\n * Turns a `ColorSource` into a CSS color under the theme, tones, and palette in\n * force: `colorSourceCss` against `useTones()`. Every component that takes a\n * color writes it through this. `undefined` for no source, and for one nothing\n * answers.\n */\nexport function useColorCss(): (source: ColorSource | null | undefined) => string | undefined {\n const ctx = useTones();\n return useCallback((source) => (source == null ? undefined : (colorSourceCss(source, ctx) ?? undefined)), [ctx]);\n}\n\n/**\n * Turns a `ColorSource` into a hex color under the theme, tones, and palette in force, for a\n * surface drawn without the cascade, such as a scene's paint. `useColorCss` may answer\n * `var(--wzl-…)`, which only the DOM resolves; this answers the value. `undefined` for no\n * source, and for one nothing answers.\n */\nexport function useColorHex(): (source: ColorSource | null | undefined) => string | undefined {\n const ctx = useTones();\n return useCallback((source) => {\n if (source == null) return undefined;\n const literal = colorSourceLiteral(source, ctx);\n return (literal && colorLiteralToHex(literal)) ?? undefined;\n }, [ctx]);\n}\n"]}
1
+ {"version":3,"sources":["../src/useColorMode.ts","../src/react.tsx"],"names":["systemMode","useCallback"],"mappings":"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","file":"react.js","sourcesContent":["import { useCallback, useEffect, useState } from 'react';\nimport { isColorModePreference, type ColorMode, type ColorModePreference } from './colorMode';\n\nfunction systemQuery(): MediaQueryList | null {\n if (typeof globalThis.matchMedia !== 'function') return null;\n return globalThis.matchMedia('(prefers-color-scheme: light)');\n}\n\nconst systemMode = (): ColorMode => (systemQuery()?.matches ? 'light' : 'dark');\n\n/**\n * Resolves a preference to the mode a `ThemeProvider` selection takes.\n * `'auto'` subscribes to the OS setting and follows it live; an explicit\n * choice opts out of the subscription entirely.\n */\nexport function useResolvedColorMode(preference: ColorModePreference): ColorMode {\n const [system, setSystem] = useState<ColorMode>(systemMode);\n\n useEffect(() => {\n if (preference !== 'auto') return;\n const mq = systemQuery();\n if (!mq) return;\n // eslint-disable-next-line react-hooks/set-state-in-effect -- syncs to the OS color-scheme query\n setSystem(mq.matches ? 'light' : 'dark');\n const onChange = (e: { matches: boolean }) => setSystem(e.matches ? 'light' : 'dark');\n mq.addEventListener('change', onChange);\n return () => mq.removeEventListener('change', onChange);\n }, [preference]);\n\n return preference === 'auto' ? system : preference;\n}\n\n/** The part of `Storage` {@link useColorModePreference} reads and writes. */\nexport type ColorModeStorage = Pick<Storage, 'getItem' | 'setItem'>;\n\n/** Options for {@link useColorModePreference}. */\nexport interface ColorModePreferenceOptions {\n /** Where the choice is remembered. Unset, it lasts as long as the component. */\n readonly storageKey?: string;\n /** The store `storageKey` names a slot in. Defaults to `localStorage`. */\n readonly storage?: ColorModeStorage;\n /** The preference before the user has chosen one. Defaults to `'auto'`. */\n readonly defaultPreference?: ColorModePreference;\n}\n\n/** What {@link useColorModePreference} returns. */\nexport interface ColorModePreferenceState {\n readonly preference: ColorModePreference;\n readonly setPreference: (next: ColorModePreference) => void;\n /** `preference` resolved against the OS — what to put in the theme's `mode` axis. */\n readonly mode: ColorMode;\n}\n\nfunction defaultStorage(): ColorModeStorage | undefined {\n try {\n return globalThis.localStorage ?? undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * A user's color-mode choice, optionally remembered across loads, and the mode\n * it resolves to. Storage that is missing or throws (a private window, blocked\n * site data) degrades to an unremembered choice rather than an error.\n */\nexport function useColorModePreference(\n options: ColorModePreferenceOptions = {},\n): ColorModePreferenceState {\n const { storageKey, storage, defaultPreference = 'auto' } = options;\n\n const [preference, setState] = useState<ColorModePreference>(() => {\n if (storageKey === undefined) return defaultPreference;\n try {\n const stored = (storage ?? defaultStorage())?.getItem(storageKey);\n return isColorModePreference(stored) ? stored : defaultPreference;\n } catch {\n return defaultPreference;\n }\n });\n\n const setPreference = useCallback(\n (next: ColorModePreference) => {\n setState(next);\n if (storageKey === undefined) return;\n try {\n (storage ?? defaultStorage())?.setItem(storageKey, next);\n } catch {\n // Unremembered, but still applied.\n }\n },\n [storageKey, storage],\n );\n\n return { preference, setPreference, mode: useResolvedColorMode(preference) };\n}\n","import { colorLiteralToHex, type ColorSource, type Palette } from '@weasel-js/paint';\nimport React, { createContext, useCallback, useContext, useMemo, useRef, useLayoutEffect } from 'react';\nimport { isDev } from '@weasel-js/registry';\nimport { applyTheme } from './applyTheme';\nimport { themeTints, type ColorList } from './colorList';\nimport { colorSourceCss, colorSourceLiteral } from './colorSource';\nimport { fullSelection, selectionKey, type Selection } from './axes';\nimport { resolveTheme, themeAxes, type ResolvedTheme } from './resolveTheme';\nimport { weaselTheme, type Theme } from './theme';\nimport { useResolvedColorMode } from './useColorMode';\n\nexport {\n useColorModePreference,\n useResolvedColorMode,\n type ColorModePreferenceOptions,\n type ColorModePreferenceState,\n type ColorModeStorage,\n} from './useColorMode';\nexport { isColorModePreference, type ColorMode, type ColorModePreference } from './colorMode';\n\n/** What `<ThemeProvider>` publishes: the theme, the full selection in force, the\n * fully resolved token record for that pair, and the tint list and palette in force. */\nexport interface ThemeContextValue {\n readonly theme: Theme;\n readonly selection: Selection;\n readonly resolved: ResolvedTheme;\n readonly tints: ColorList;\n readonly palette: Palette;\n}\n\n/** What `<ThemeProvider>` publishes. Provide `null` to hide an outer theme from a subtree, as a\n * boundary that renders its children the way a page with no provider would. */\nexport const ThemeContext = createContext<ThemeContextValue | null>(null);\n\nconst NO_PALETTE: Palette = { entries: [] };\n\n/** Props for `<ThemeProvider>`. */\nexport interface ThemeProviderProps {\n readonly theme?: Theme;\n /** Axis values, e.g. `{ mode: 'light' }`. A missing axis takes its default. `mode: 'auto'`\n * follows the OS setting, live; any other value the theme lacks takes the default, with a\n * warning in development. */\n readonly selection?: Selection;\n /** The colors a `tint` index picks from in this subtree. Absent: the theme's own. */\n readonly tints?: ColorList;\n /** Colors a `ColorRef` names in this subtree, answered before the theme's own names. Absent: none. */\n readonly palette?: Palette;\n /** Applied to the wrapper element, so it can be the layout element too. */\n readonly className?: string;\n readonly style?: React.CSSProperties;\n readonly children: React.ReactNode;\n}\n\n/**\n * Applies a theme to a wrapper element and publishes the resolved record.\n *\n * Consumers that draw outside the DOM (the WebGL HUD) read `resolved` and\n * never touch `getComputedStyle`.\n *\n * The wrapper is a real element in the layout. Pass `className` rather than\n * nesting your own div inside — an anonymous div between a flex parent and\n * its child breaks percentage heights.\n */\nexport function ThemeProvider({\n theme = weaselTheme,\n selection,\n tints,\n palette = NO_PALETTE,\n className,\n style,\n children,\n}: ThemeProviderProps): React.ReactElement {\n const ref = useRef<HTMLDivElement>(null);\n const axes = themeAxes(theme);\n const autoMode = selection?.mode === 'auto' && !('auto' in (axes.mode?.values ?? {}));\n const systemMode = useResolvedColorMode(autoMode ? 'auto' : 'dark');\n const given = autoMode ? { ...selection, mode: systemMode } : selection;\n const full = fullSelection(axes, given);\n warnUnknownAxisValues(theme, axes, given);\n // Keyed on the selection's content: callers pass a fresh object every render.\n const key = selectionKey(axes, full);\n\n const value = useMemo<ThemeContextValue>(\n () => ({ theme, selection: full, resolved: resolveTheme(theme, full), tints: tints ?? themeTints(theme), palette }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [theme, key, tints, palette],\n );\n\n // Applying again replaces what the element held, so only the unmount releases.\n const release = useRef<(() => void) | null>(null);\n useLayoutEffect(() => {\n if (ref.current) release.current = applyTheme(ref.current, theme, value.selection);\n }, [theme, value]);\n useLayoutEffect(() => () => release.current?.(), []);\n\n const attrs = Object.fromEntries(Object.keys(axes).map((a) => [`data-wzl-${a}`, full[a]]));\n return (\n <ThemeContext.Provider value={value}>\n <div ref={ref} className={className} style={style} data-wzl-theme={theme.name} {...attrs}>\n {children}\n </div>\n </ThemeContext.Provider>\n );\n}\n\nconst warned = new Set<string>();\n\nfunction warnUnknownAxisValues(theme: Theme, axes: ReturnType<typeof themeAxes>, selection: Selection | undefined): void {\n if (!selection || !isDev()) return;\n for (const [axis, value] of Object.entries(selection)) {\n const def = axes[axis];\n if (!def || value in def.values) continue;\n const key = `${theme.name}\\0${axis}\\0${value}`;\n if (warned.has(key)) continue;\n warned.add(key);\n console.warn(\n `[weasel theme] ThemeProvider: theme \"${theme.name}\" has no ${axis} \"${value}\"; using \"${def.default}\". Its ${axis} values: ${Object.keys(def.values).join(', ')}.`,\n );\n }\n}\n\n/** The theme in force. Throws outside a `<ThemeProvider>`; use\n * `useThemeOptional` where the provider is not guaranteed. */\nexport function useTheme(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (!ctx) throw new Error('useTheme must be used inside a <ThemeProvider>');\n return ctx;\n}\n\n/**\n * The theme if one is provided, `null` otherwise.\n *\n * For kit internals that should follow a theme when the app supplies one but\n * must still work in an app that never mounted a provider — `useHud` is the\n * motivating case.\n */\nexport function useThemeOptional(): ThemeContextValue | null {\n return useContext(ThemeContext);\n}\n\nlet defaultTints: ThemeContextValue | undefined;\n\n/**\n * The tint list in force and what it resolves against — the nearest\n * `<ThemeProvider>`'s, else the built-in theme's at its defaults. Pass the\n * result as `colorAt`'s context.\n */\nexport function useTints(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (ctx) return ctx;\n return (defaultTints ??= {\n theme: weaselTheme,\n selection: fullSelection(themeAxes(weaselTheme)),\n resolved: resolveTheme(weaselTheme),\n tints: themeTints(weaselTheme),\n palette: NO_PALETTE,\n });\n}\n\n/**\n * Turns a `ColorSource` into a CSS color under the theme, tints, and palette in\n * force: `colorSourceCss` against `useTints()`. Every component that takes a\n * color writes it through this. `undefined` for no source, and for one nothing\n * answers.\n */\nexport function useColorCss(): (source: ColorSource | null | undefined) => string | undefined {\n const ctx = useTints();\n return useCallback((source) => (source == null ? undefined : (colorSourceCss(source, ctx) ?? undefined)), [ctx]);\n}\n\n/**\n * Turns a `ColorSource` into a hex color under the theme, tints, and palette in force, for a\n * surface drawn without the cascade, such as a scene's paint. `useColorCss` may answer\n * `var(--wzl-…)`, which only the DOM resolves; this answers the value. `undefined` for no\n * source, and for one nothing answers.\n */\nexport function useColorHex(): (source: ColorSource | null | undefined) => string | undefined {\n const ctx = useTints();\n return useCallback((source) => {\n if (source == null) return undefined;\n const literal = colorSourceLiteral(source, ctx);\n return (literal && colorLiteralToHex(literal)) ?? undefined;\n }, [ctx]);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { a as Theme } from '../definition-CSeERbSL.js';
1
+ import { a as Theme } from '../definition-wsEi-XBr.js';
2
2
  import '@weasel-js/paint';
3
3
 
4
4
  /**
@@ -14,7 +14,7 @@ declare const classicMacTheme: Theme;
14
14
  * faces themselves are not bundled, so the stack falls through to what the
15
15
  * machine has. Opens in light mode; the dark one is this theme's own invention.
16
16
  *
17
- * Pair it with `<DefaultMotif motif={motifs.titlebar()}>` from `@weasel-js/ui`
17
+ * Pair it with `<DefaultMotif group={motifs.titlebar()}>` from `@weasel-js/ui`
18
18
  * to title every group as a window.
19
19
  */
20
20
  declare const platinumTheme: Theme;