theme_resolver.ts

The numeric resolution core under theme_validate.ts and theme_check.ts: it turns the CSS strings themes author back into numbers so the lint and the gates can run. create_theme_resolver exposes it for UI lookups; the rest of the module's exports are the internals the two modules share.

Its contract:

  • Knob-tier defaults come from the numeric-twin constants in ramps.ts, not from parsing default_variables; intent and neutral hues default to their palette-letter binding (hue_accent → hue_a, hue_neutral → hue_f, and so on) so they follow an overridden letter.
  • Theme-authored values parse as a CSS <number> literal, an exact var(--x) reference (recursed through the same effective-value merge, with a visited-set cycle guard), a scaled reference calc(var(--x) * <number>), or the machine-emitted compiled-cap min(calc(...), <number>) form. Anything else is unresolvable and is recorded with its variable, value, and reason. A derived color is clamped as the browser clamps the oklch() it renders.
  • Derived ramp stops (palette_lightness_NN and its shade/text twins, palette_chroma_NN, chroma_shape_NN) use a pinned numeric value when the theme pins one, fall back to the ramps.ts formulas with the resolved knobs otherwise, and mark the touching gates unchecked when a pin is unresolvable.
  • The color variables the gates read (the palette, intent, shade, and text stops, text_max, and border_color_30) derive from those numbers unless the theme authors one directly. An authored color is measured as written when it is an oklch(L C H) literal with plain numeric components (an optional / alpha composites where the gate measures a color over its ground) or an exact var() reference to another color the gates evaluate; any other form is recorded in unchecked and its gates are skipped. The gates look every color up by variable name, so this covers exactly the variables a gate reads and no others.
  • The gates measure what the default styles paint, so they follow the roles those styles paint through: text_color, text_disabled, link_color, link_color_selected, border_color, and outline_color (theme_gate_role_names). Each aliases a stop or another role by default, read from the shipped declarations, and a theme that repoints one is gated at the color it points to - same rule, same unchecked fallback. One table of pairing gates names each role beside its grounds and threshold, so the gate definitions and the following can't drift.
  • Outside the gates: the micro-surface colors no pairing models (caret_color, selection_color, scrollbar_thumb_color, backdrop_color), the input_fill behind field text, a background_image painted over the shade_00 ground, and the stronger button tints of the hover, focus, and pressed states.

The effective-value merge mirrors the renderer's cascade-layer semantics (theme.ts render_theme_style): light = theme.light; dark = theme.dark ?? theme.light, falling back to the numeric-twin default for the scheme. A single-scheme stance (Theme.scheme) resolves through the same scheme_stance_variables mirror resolve_theme_stance computes, so the gates evaluate the stanced reality in both schemes whether or not the theme arrives resolved.

view source

Declarations
#

12 declarations

create_theme_resolver
#

theme_resolver.ts view source

(theme: { name: string; variables: { name: string; light?: string | undefined; dark?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; scheme_mirror?: { ...; }[] | undefined; }): ThemeKnobResolver import {create_theme_resolver} from '@fuzdev/fuz_css/theme_resolver.js';

Creates a ThemeKnobResolver for theme, sharing the resolution core used by validate_theme/check_theme/compile_theme. The instance memoizes per name+scheme, so repeated lookups (a UI rendering every knob) stay cheap - create one per theme value and discard when the theme changes.

theme

type Theme

returns

ThemeKnobResolver

CSS_NUMBER_PATTERN
#

theme_resolver.ts view source

internal

Shared by `theme_validate.ts` and `theme_check.ts` - not stable API.

string import {CSS_NUMBER_PATTERN} from '@fuzdev/fuz_css/theme_resolver.js';

A CSS <number> as a pattern source, stricter than what Number() accepts - no hex, binary, Infinity, or empty string.

INTENT_HUE_DEFAULT_BINDING
#

theme_resolver.ts view source

internal

Shared by `theme_validate.ts` and `theme_check.ts` - not stable API.

Record<string, string>

type Record<string, string>

import {INTENT_HUE_DEFAULT_BINDING} from '@fuzdev/fuz_css/theme_resolver.js';

Intent and neutral hues default to a palette-letter binding - derived by inverting palette_glosses so rebinding an intent there flows through.

NUMERIC_EPSILON
#

theme_resolver.ts view source

internal

Shared by `theme_validate.ts` and `theme_check.ts` - not stable API.

1e-9 import {NUMERIC_EPSILON} from '@fuzdev/fuz_css/theme_resolver.js';

Equality slack for resolved hue angles and chroma multipliers.

PALETTE_LETTER_MATCHER
#

theme_resolver.ts view source

internal

Shared by `theme_validate.ts` and `theme_check.ts` - not stable API.

RegExp import {PALETTE_LETTER_MATCHER} from '@fuzdev/fuz_css/theme_resolver.js';

Matches a palette letter's hue name, capturing the letter.

parse_css_number
#

theme_resolver.ts view source

internal

Shared by `theme_validate.ts` and `theme_check.ts` - not stable API.

(text: string): number | null import {parse_css_number} from '@fuzdev/fuz_css/theme_resolver.js';

Parses text as a CSS <number>, or null when it isn't one.

text

type string

returns

number | null

Resolved
#

theme_resolver.ts view source

internal

Shared by `theme_validate.ts` and `theme_check.ts` - not stable API.

Resolved

type { ok: true; value: number; } | { ok: false; variable: string; value: string; reason: string; }

import type {Resolved} from '@fuzdev/fuz_css/theme_resolver.js';

A resolved numeric value, or the offending variable/value/reason on failure.

SCALED_VAR_MATCHER
#

theme_resolver.ts view source

internal

Shared by `theme_validate.ts` and `theme_check.ts` - not stable API.

RegExp import {SCALED_VAR_MATCHER} from '@fuzdev/fuz_css/theme_resolver.js';

Matches the scaled-reference form emitted for border_color_chroma (calc(var(--neutral_chroma) * 2.12)), also useful for authored multipliers, capturing the name and the factor.

STOPS_PATTERN
#

theme_resolver.ts view source

internal

Shared by `theme_validate.ts` and `theme_check.ts` - not stable API.

string import {STOPS_PATTERN} from '@fuzdev/fuz_css/theme_resolver.js';

The stop alternation as a pattern source, built from the variant list so a scale change can't strand a matcher.

ThemeKnobResolver
#

theme_resolver.ts view source

ThemeKnobResolver import type {ThemeKnobResolver} from '@fuzdev/fuz_css/theme_resolver.js';

A reusable numeric resolver over one theme - the memoized query surface for UI display (the theme editor's derived-knob readouts) and tests.

resolve

Resolves name for scheme to a number, or null when it can't be resolved.

type (name: string, scheme: "dark" | "light"): number | null

name

type string

scheme

returns number | null

pinned

Whether the theme authors a value for name (a pin; stance-mirror entries excluded).

type (name: string): boolean

name

type string
returns boolean

ThemeResolver
#

theme_resolver.ts view source

internal

Shared by `theme_validate.ts` and `theme_check.ts` - not stable API.

import {ThemeResolver} from '@fuzdev/fuz_css/theme_resolver.js';

Resolves knob-tier and derived-stop variables of a single theme to numbers, mirroring the renderer's effective-value merge and the ramps.ts formulas. create_theme_resolver is the public surface over it.

constructor

type new (theme: { name: string; variables: { name: string; light?: string | undefined; dark?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; scheme_mirror?: { ...; }[] | undefined; }): ThemeResolver

theme

type Theme

pinned

Whether the theme authors a value for name (a pin).

type (name: string): boolean

name

type string
returns boolean

authored

The theme's own value for name in scheme (a pin), or undefined when it authors none for that slot. Stance-mirror entries are not pins.

type (name: string, scheme: "dark" | "light"): string | undefined

name

type string

scheme

returns string | undefined

resolve

Resolves name for scheme, memoized per name+scheme.

type (name: string, scheme: "dark" | "light"): Resolved

name

type string

scheme

returns Resolved

VAR_MATCHER
#

theme_resolver.ts view source

internal

Shared by `theme_validate.ts` and `theme_check.ts` - not stable API.

RegExp import {VAR_MATCHER} from '@fuzdev/fuz_css/theme_resolver.js';

Matches exactly var(--x), capturing the name - the reference form the resolver follows.

Depends on
#

Imported by
#