api #

semantic-first CSS framework and design system: styled HTML defaults, themes derived from a few knobs, and utility classes generated from what you use

63 modules ยท 424 declarations

Modules
#

ACCENT_STATUS_HUE_SEPARATION
#

theme_validate.ts view source

20 import {ACCENT_STATUS_HUE_SEPARATION} from '@fuzdev/fuz_css/theme_validate.js';

How far in degrees the accent hue has to sit from each status hue before validate_theme stops warning. At the chroma links and labels render at, 12 degrees reads as one color with a shift (a red accent beside the default orange caution) while 30 reads as two (a pink accent beside the default red negative), so the threshold sits between them. The defaults' closest accent and status pair, blue and cyan, is 40 degrees apart.

AcornPlugin
#

css_class_extractor.ts view source

AcornPlugin import type {AcornPlugin} from '@fuzdev/fuz_css/css_class_extractor.js';

Acorn plugin type - a function that extends the Parser class.

(call)

type (BaseParser: typeof Parser): typeof Parser

BaseParser

type typeof Parser
returns typeof Parser

ALL_MODIFIER_NAMES
#

modifiers.ts view source

internal

The lookup behind `get_all_modifier_names`.

Set<string>

type Set<string>

import {ALL_MODIFIER_NAMES} from '@fuzdev/fuz_css/modifiers.js';

All modifier names for quick lookup.

alpha_variants
#

variable_data.ts view source

readonly ["00", "05", "10", "20", "30", "40", "50", "60", "70", "80", "90", "95", "100"] import {alpha_variants} from '@fuzdev/fuz_css/variable_data.js';

AlphaVariant
#

ANCESTOR_MODIFIERS
#

modifiers.ts view source

Map<string, ModifierDefinition>

type Map<string, ModifierDefinition>

import {ANCESTOR_MODIFIERS} from '@fuzdev/fuz_css/modifiers.js';

Map of ancestor modifier names to their CSS output

apply_theme_variables
#

variable_graph.ts view source

(variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[], theme: ResolvedTheme | null | undefined): { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[] import {apply_theme_variables} from '@fuzdev/fuz_css/variable_graph.js';

Overlays a baked theme onto a resolved variable set, last-wins by name.

This is how a theme is baked in at build time: the overlaid values flow through the dependency graph like any other, so the variables a theme references are pulled in transitively and the output stays tree-shaken. The overlay follows render_theme_style's order - the stance mirror (minus the names the theme or its caps set), then the theme's own variables (minus any internal name, which a theme can't set), then the caps. A slot the stylesheet can't hold is dropped before it overlays, as render_theme_style drops it, so the value beneath it stays.

variables

the resolved default or custom variables

theme

the baked theme to overlay (see bake_theme), or null/undefined for none

type ResolvedTheme | null | undefined

returns

StyleVariable[]

the composed variables, or variables unchanged when there's no theme

arrayClasses
#

bake_theme
#

variable_graph.ts view source

(theme: { name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; } | ResolvedTheme, variables: { ...; }[], diagnostics?: GenerationDiagnostic[] | undefined): ResolvedTheme import {bake_theme} from '@fuzdev/fuz_css/variable_graph.js';

Derives what a build-time theme renders with from the configured variable set: the stance mirror, re-slotted from the configured variables (so a build that customizes a scheme-adaptive variable mirrors its own value, not the default), and the caps compute_theme_caps recomputes for the theme's hues and lightness - the derived half of compile_theme. A ResolvedTheme passed in has its theme baked the same way - a supplied mirror or caps are recomputed, so the output can't depend on derived data computed against another variable set or an older release.

The theme's variables pass the containment checks first, as build_variable_graph applies them: a slot the stylesheet can't hold, or an entry without a plain-identifier name, is reported as an uncontained_theme_value error and left out, and the caps, the gates, and the overlay all see the contained theme - what renders.

The caps and the gates measure the theme over the configured set: a knob-tier value (theme_knobs) the configured variables change from the default is folded in beneath the theme's own, re-slotted for a stance as the mirror re-slots it, so a build that retunes a ramp knob is capped and gated at what it renders. A configured value the gates can't read lands in unchecked.

The gates (check_theme with the caps) report as warnings, since a theme can knowingly give up a gate: theme_gate_failed lists the failing gate entries and theme_gate_unchecked the inputs the gates couldn't evaluate. A stanced theme renders its one appearance in both schemes, so only the stanced scheme's entries are listed. The lint (validate_theme) runs over the contained theme, so a slot reported as uncontained isn't reported again: each issue is a theme_lint diagnostic at the issue's level, so an unknown variable fails a build that throws on errors.

theme

the configured theme option

variables

the configured variable set the theme overlays

diagnostics?

collects the containment errors, the lint issues, and the gate warnings, when given

optional

returns

ResolvedTheme

the contained wire theme with its mirror and caps

base_theme
#

themes/base.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {base_theme} from '@fuzdev/fuz_css/themes/base.js';

The default theme - inherits every base default variable.

BaseCssOption
#

css_plugin_options.ts view source

BaseCssOption

type string | ((default_css: string) => string) | null | undefined

import type {BaseCssOption} from '@fuzdev/fuz_css/css_plugin_options.js';

Type for the base_css option used by the generator.

Supports four forms:

  • undefined - Use default style.css (framework defaults)
  • null - Disable base styles entirely (explicit opt-out)
  • string - Custom CSS to replace defaults
  • (default_css) => string - Callback to modify default CSS

See module documentation for the undefined vs null convention, and CssOutputOptions.base_css for what the generator does with the stylesheet.

BaseDiagnostic
#

diagnostics.ts view source

BaseDiagnostic import type {BaseDiagnostic} from '@fuzdev/fuz_css/diagnostics.js';

Base diagnostic with common fields.

level

type "error" | "warning"

message

type string

suggestion

type string | null

BORDER_CHROMA_MULTIPLIER
#

ramps.ts view source

Readonly<Record<"dark" | "light", number>>

type Readonly<Record<ColorSchemeVariant, number>>

import {BORDER_CHROMA_MULTIPLIER} from '@fuzdev/fuz_css/ramps.js';

The border family's chroma as a multiple of --neutral_chroma - borders carry a stronger tint than surfaces so they read at low alpha. In CSS this is --border_color_chroma: calc(var(--neutral_chroma) * <multiple>).

BORDER_COLOR_ALPHAS
#

ramps.ts view source

Readonly<Record<"dark" | "light", Readonly<Record<"00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", number>>>>

type Readonly<Record<ColorSchemeVariant, Readonly<Record<NumericScaleVariant, number>>>>

import {BORDER_COLOR_ALPHAS} from '@fuzdev/fuz_css/ramps.js';

Alpha (in %) of each border color stop. A perceptually-uniform curve - small gaps at the low end, large at the high end - boosted at the low end in dark mode where borders are less visible against dark backgrounds. Stop 00 renders transparent and stop 100 opaque.

BORDER_COLOR_LIGHTNESS
#

ramps.ts view source

Readonly<Record<"dark" | "light", number>>

type Readonly<Record<ColorSchemeVariant, number>>

import {BORDER_COLOR_LIGHTNESS} from '@fuzdev/fuz_css/ramps.js';

OKLCH lightness of the border color family (--border_color_lightness), fitted from the HSL palette. Sits mid-ramp so borders read against both the page background and fills.

border_color_oklch
#

ramps.ts view source

(scheme: "dark" | "light"): Oklch import {border_color_oklch} from '@fuzdev/fuz_css/ramps.js';

Computes the default OKLCH color of the border family (without alpha).

scheme

returns

Oklch

BORDER_RADII
#

variable_data.ts view source

Readonly<Record<"lg" | "md" | "sm" | "xs" | "xl" | "xs3" | "xs2", number>>

type Readonly<Record<BorderRadiusVariant, number>>

import {BORDER_RADII} from '@fuzdev/fuz_css/variable_data.js';

Border radii in rem, before the --radius_scale multiplier.

border_radius_variants
#

variable_data.ts view source

readonly ["xs3", "xs2", "xs", "sm", "md", "lg", "xl"] import {border_radius_variants} from '@fuzdev/fuz_css/variable_data.js';

border_width_variants
#

variable_data.ts view source

readonly [1, 2, 3, 4, 5, 6, 7, 8, 9] import {border_width_variants} from '@fuzdev/fuz_css/variable_data.js';

BorderRadiusVariant
#

variable_data.ts view source

"lg" | "md" | "sm" | "xs" | "xl" | "xs3" | "xs2"

type "lg" | "md" | "sm" | "xs" | "xl" | "xs3" | "xs2"

import type {BorderRadiusVariant} from '@fuzdev/fuz_css/variable_data.js';

BorderWidthVariant
#

variable_data.ts view source

6 | 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9

type 6 | 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9

import type {BorderWidthVariant} from '@fuzdev/fuz_css/variable_data.js';

build_variable_graph
#

variable_graph.ts view source

(variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]): VariableDependencyGraph import {build_variable_graph} from '@fuzdev/fuz_css/variable_graph.js';

Builds a dependency graph from an array of style variables.

The graph is what the bundled theme CSS renders from, verbatim, so it applies the containment checks render_theme_style does: a slot whose value could end its own declaration (or is blank), or a variable whose name isn't a plain identifier, is left out and reported as an uncontained_theme_value error rather than written into the stylesheet.

variables

array of StyleVariable objects

returns

VariableDependencyGraph

build_variable_graph_from_options
#

variable_graph.ts view source

(variables: VariablesOption, theme?: { name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | ... 2 more ... | undefined; } | ResolvedTheme | null | undefined): VariableDependencyGraph import {build_variable_graph_from_options} from '@fuzdev/fuz_css/variable_graph.js';

Builds a variable dependency graph from a variables option, with a build-time theme baked in through bake_theme. Handles all option forms: undefined (defaults), null (disabled), array, or callback.

variables

the variables option from generator config

theme?

an optional theme to bake onto the resolved variables

type Theme | ResolvedTheme | null
optional

returns

VariableDependencyGraph

VariableDependencyGraph built from the resolved variables, carrying the baked theme

BundledCssResources
#

CacheDeps
#

deps.ts view source

CacheDeps import type {CacheDeps} from '@fuzdev/fuz_css/deps.js';

Cache-related file system deps. Abstracted to enable test isolation from the actual filesystem.

Named CacheDeps (not FsDeps) because it only covers the specific deps needed for cache management, not general filesystem access.

read_text

Reads a text file. Returns a not_found error if the file doesn't exist.

type (options: { path: string; }): Promise<Result<{ value: string; }, FsError>>

options

type { path: string; }
returns Promise<Result>

write_text_atomic

Writes a text file atomically (temp file + rename for crash safety). Creates parent directories if they don't exist.

type (options: { path: string; content: string; }): Promise<Result<object, FsError>>

options

type { path: string; content: string; }
returns Promise<Result>

unlink

Removes a file. Returns a not_found error if the file doesn't exist - callers that want rm -f semantics should ignore that kind explicitly.

type (options: { path: string; }): Promise<Result<object, FsError>>

options

type { path: string; }
returns Promise<Result>

CachedExtraction
#

css_cache.ts view source

CachedExtraction import type {CachedExtraction} from '@fuzdev/fuz_css/css_cache.js';

Cached extraction result for a single file. Uses null instead of empty arrays to avoid allocation overhead.

v

The to_cache_version the entry was written with - any other misses

type string

content_hash

Content hash of the source file

type string

extraction_key

The configuration part of the key (to_extraction_cache_key), or null for the default

type string | null

classes

Classes as [name, locations] tuples, or null if none

type [string, SourceLocation[]][] | null

explicit_classes

Classes from @fuz-classes comments, or null if none

type string[] | null

diagnostics

Extraction diagnostics, or null if none

type ExtractionDiagnostic[] | null

elements

HTML elements found in the file, or null if none

type string[] | null

explicit_elements

Elements from @fuz-elements comments, or null if none

type string[] | null

explicit_variables

Variables from @fuz-variables comments, or null if none

type string[] | null

check_calc_expression
#

css_literal.ts view source

(value: string): string | null import {check_calc_expression} from '@fuzdev/fuz_css/css_literal.js';

Checks if a value contains a possibly invalid calc expression.

value

the formatted CSS value

type string

returns

string | null

warning message if suspicious, null otherwise

check_theme
#

theme_check.ts view source

(theme: { name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }, options?: ThemeResolverOptions): ThemeCheckReport import {check_theme} from '@fuzdev/fuz_css/theme_check.js';

Runs the gamut, monotonicity, and contrast gates against a theme, resolving its authored CSS back to numbers through the resolution core. Report-only: failures land in entries (with pass: false), inputs that can't be evaluated land in unchecked, and ok is true only when every entry passes and nothing is unchecked. Never throws.

Every color a gate reads is looked up by its variable name, so a theme that authors one directly - a stop (palette_a_50, shade_00, text_max, border_color_30) or a role (text_color, link_color, border_color) - is measured at the authored color when it is an oklch(L C H) numeric literal or an exact var() reference to another color the gates evaluate, and recorded in unchecked otherwise. An authored color a gate depends on never passes unread, and one no gate reads stays out of the report.

A contrast subject names what was measured: the default stop while a role is at its default (text_80 on shade_00), the role once the theme authors it (text_color on shade_00).

An intent stop that renders the same color as a palette letter's (the default for every intent) folds into that letter's gamut entry rather than duplicating it, so reports for letter-bound themes list fewer subjects than the full letters ร— intents grid.

theme

the theme to check

type Theme

options

the compiled caps to check the theme with, as compute_theme_caps returns them

default {}

returns

ThemeCheckReport

CHROMA_STOP_CSS_MATCHER
#

ramps.ts view source

internal

Shared by `variable.ts` and `theme_resolver.ts` - not stable API.

RegExp import {CHROMA_STOP_CSS_MATCHER} from '@fuzdev/fuz_css/ramps.js';

Matches the capped form render_chroma_stop_css emits, capturing the stop and the cap - how the resolver reads a compiled cap back, and how the Theme schema admits the one intermediate a theme can carry (see StyleVariable). It admits CSS whitespace only, around the value and inside it, so a match needs no trim() (which, like \s, takes U+00A0).

ChromaRampKnobs
#

ramps.ts view source

ChromaRampKnobs import type {ChromaRampKnobs} from '@fuzdev/fuz_css/ramps.js';

Knobs for the symmetric mid-peaked chroma curve, C(t) = min + (max - min) * pow(4t(1-t), curve). The curve expresses the *request*; rendered stops are clamped by PALETTE_CHROMA_CAPS per stop, and --chroma_scale multiplies above the clamp (so vivid themes can knowingly push past the caps and gamut-clip).

chroma_min

Chroma requested at the ramp endpoints (stops 00/100), before capping.

type number

chroma_max

Chroma requested at the ramp midpoint (stop 50), before capping.

type number

curve

Falloff exponent of the peak; higher concentrates chroma at the middle.

type number

ClassDefinitionsOption
#

css_plugin_options.ts view source

ClassDefinitionsOption

type Record<string, CssClassDefinition | undefined> | ((defaults: Record<string, CssClassDefinition | undefined>) => Record<string, CssClassDefinition | undefined>) | undefined

import type {ClassDefinitionsOption} from '@fuzdev/fuz_css/css_plugin_options.js';

Type for the class_definitions option used by the generator.

Supports three forms:

  • undefined - Use the default token and composite classes
  • Record - Definitions merged over the defaults (a definition with a default's name replaces it)
  • (defaults) => Record - Callback returning the whole set, which receives a copy of the defaults; () => my_definitions uses only your own

ClassInterpretersOption
#

css_plugin_options.ts view source

ClassInterpretersOption

type CssClassDefinitionInterpreter[] | ((defaults: CssClassDefinitionInterpreter[]) => CssClassDefinitionInterpreter[]) | undefined

import type {ClassInterpretersOption} from '@fuzdev/fuz_css/css_plugin_options.js';

Type for the class_interpreters option used by the generator.

Supports three forms:

  • undefined - Use the default interpreters (the CSS-literal interpreter)
  • Array<CssClassDefinitionInterpreter> - Interpreters replacing the defaults
  • (defaults) => Array<CssClassDefinitionInterpreter> - Callback returning the interpreters to use, which receives a copy of the defaults

ClassTemplateFn
#

css_class_generators.ts view source

ClassTemplateFn<T1, T2, T3>

type ((v1: T1) => GeneratedClassResult) | ((v1: T1, v2: T2) => GeneratedClassResult) | ((v1: T1, v2: T2, v3: T3) => GeneratedClassResult)

import type {ClassTemplateFn} from '@fuzdev/fuz_css/css_class_generators.js';

generics

ClassTemplateFn<T1 = string, T2 = string, T3 = string>
T1
default string
T2
default string
T3
default string

collect_rule_variables
#

style_rule_parser.ts view source

(index: StyleRuleIndex, included_indices: Set<number>): Set<string> import {collect_rule_variables} from '@fuzdev/fuz_css/style_rule_parser.js';

Collects all CSS variables used by the included rules.

index

included_indices

set of rule indices to include

type Set<number>

returns

Set<string>

set of variable names (without -- prefix)

COLOR_SCHEME_ROOTS
#

theme.ts view source

{ readonly dark: { readonly explicit: ":root.dark"; readonly preferred: ":root:not(.light)"; }; readonly light: { readonly explicit: ":root.light"; readonly preferred: ":root:not(.dark)"; }; } import {COLOR_SCHEME_ROOTS} from '@fuzdev/fuz_css/theme.js';

The root selectors that put a page in each color scheme: explicit names the scheme with a class on the root element (fuz_ui's theme state sets one), and preferred holds while the root names neither scheme, so the page follows the OS preference without JS.

color_scheme_variants
#

color_schemes
#

ColorScheme
#

ColorSchemeVariant
#

variable_data.ts view source

"dark" | "light"

type "dark" | "light"

import type {ColorSchemeVariant} from '@fuzdev/fuz_css/variable_data.js';

compare_media_modifiers
#

modifiers.ts view source

(a: ModifierDefinition | null, b: ModifierDefinition | null): number import {compare_media_modifiers} from '@fuzdev/fuz_css/modifiers.js';

Orders media modifiers for emission, so the later rule wins where two apply: none first, then min width bounds ascending, then max width bounds descending, then feature queries in registration order. Width values that can't be compared statically sort after the comparable ones of their bound, by value.

a

type ModifierDefinition | null

b

type ModifierDefinition | null

returns

number

compile_theme
#

theme_compile.ts view source

(theme: { name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }): CompiledTheme import {compile_theme} from '@fuzdev/fuz_css/theme_compile.js';

Compiles a theme: computes its stance mirror and its recomputed chroma caps (compute_theme_caps), re-checks the gates with the caps, and lints it. The theme comes back as the same reference and never carries the derived data, so compiling the same theme again gives the same result.

theme

the theme to compile

type Theme

returns

CompiledTheme

the theme with its mirror, caps, gate report, and lint

CompiledTheme
#

theme_compile.ts view source

CompiledTheme import type {CompiledTheme} from '@fuzdev/fuz_css/theme_compile.js';

The output of compile_theme: the input theme with everything derived from it - the stance mirror and the recomputed caps - plus the gate report and lint over that rendering. Renders as render_theme_style(c.theme, c).

inheritance

extends: ResolvedTheme

theme

The input theme, the same reference - compiling never edits it.

type Theme

scheme_mirror

The stance mirror for a single-scheme theme, undefined for a dual one.

type StyleVariable[] | undefined

caps

The _palette_chroma_NN caps recomputed where the baked ones no longer fit the theme's hues and lightness (compute_theme_caps) - empty when they all still fit.

type StyleVariable[]

report

The gates over the theme with its caps, from check_theme.

type ThemeCheckReport

issues

The theme's lint, from validate_theme.

type ThemeIssue[]

compose_themes
#

theme.ts view source

(base: { name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }, ...overlays: { ...; }[]): { ...; } import {compose_themes} from '@fuzdev/fuz_css/theme.js';

Composes a base theme with overlay fragments by flatten + last-wins: later variables replace same-named earlier ones wholesale, a dark-only overlay keeping the base slot beneath it (see overlay_style_variable). Any knob-only theme is already a valid fragment - the contrast modifiers in contrast_modifiers are the canonical overlays. This is the hand-flatten precursor to a first-class extends, with the same merge semantics.

The base's scheme stance wins; when the base is single-scheme, each overlay variable is re-slotted to the stanced scheme's value so a dual-slot fragment can't leak the other scheme's appearance past the stance. The result is a plain theme like its inputs - resolve it to render a stance faithfully. The composed name appends the overlay names so name-keyed pickers and renderers treat the composition as its own theme, and the base's summary carries through.

base

type Theme

overlays

type Theme[]

returns

Theme

compute_theme_caps
#

theme_check.ts view source

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

Recomputes a theme's per-stop worst-hue chroma caps from its own hues and the palette lightness each stop resolves to, then returns _palette_chroma_NN caps wherever the baked ones no longer fit - the fix for a theme (rotated hues, a monochrome collapse, a moved lightness ramp) whose gamut headroom the baked worst-hue table misjudges. The caps are derived data beside the theme, never in it: a theme can't set an internal variable, so they render through render_theme_style's caps option and recomputing them for the same theme gives the same caps.

Each stop's cap is computed at the lightness the resolution core resolves for the stop in that scheme - the theme's endpoint-and-curve ramp - so the caps describe the same colors check_theme gates.

A stop is emitted when either scheme's recomputed cap is tighter than the baked value, or looser by more than the emit epsilon. Nothing is emitted when a hue fails to resolve to a number, since caps computed without it could overshoot its gamut, and a stop whose lightness fails to resolve is skipped. An override emits both slots together, so a one-scheme override can't silently kill the base default's other slot by cascade-layer order, collapsing to a single slot in the base position when the two rendered values coincide.

A stanced theme's two schemes resolve to the stanced appearance through the mirror, so its caps are baselined against the stanced scheme's baked table - the values the mirror already re-slots - and a stance alone (hues and lightness unmoved) emits nothing. Its overrides coincide across schemes and emit single-slot unless the theme authors a dark slot that splits them.

The caps bound the requested chroma only: chroma_scale and the per-slot *_chroma_scale multipliers apply above the clamp. A theme that raises one past 1 clips by design - its gamut failures survive the compile, and a cap the compile loosens can add to them, since the multiplier then pushes more stops past the looser cap. Gate the theme with them through check_theme(theme, {caps}).

theme

the theme to recompute caps for

type Theme

returns

StyleVariable[]

the _palette_chroma_NN caps that moved, empty when the baked ones all still fit

compute_worst_hue_chroma_cap
#

ramps.ts view source

(hues: readonly number[], lightness: number): number import {compute_worst_hue_chroma_cap} from '@fuzdev/fuz_css/ramps.js';

Computes the worst-hue safe chroma cap at one lightness: the minimum oklch_max_srgb_chroma across the hues, floored to 4 decimals to stay conservative (the browser clips anything past it). The generalization of the baked PALETTE_CHROMA_CAPS to an arbitrary hue set and lightness - a theme's compile step calls it with each stop's own resolved lightness to detect where the baked worst-hue envelope no longer fits.

hues

OKLCH hue angles the stop must stay in gamut for

type readonly number[]

lightness

the stop's OKLCH lightness

type number

returns

number

contrast_modifiers
#

themes.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }[]

type Theme[]

import {contrast_modifiers} from '@fuzdev/fuz_css/themes.js';

The contrast modifiers: small axis fragments composed over any theme via compose_themes rather than picked as themes themselves. Composition is flatten + last-wins, so a modifier's variables replace the base theme's same-named ones - a base that moves the same knobs cedes them to the modifier. Both move the shade endpoint (shade_lightness_00), since contrast is the ground-to-text range, so a theme whose identity is its ground yields it. High contrast also bends the text curve (text_lightness_curve) and sets border_color to a stop that holds a control's boundary against a ground its fill can no longer separate from

  • a base with its own border_color cedes it like any other variable,

stronger rules included. Neither touches the neutral cast, which stays the theme's.

CoreReason
#

style_rule_parser.ts view source

CoreReason

type "universal" | "root" | "body" | "conditional_core" | "html" | "host" | "at_rule" | "untargetable"

import type {CoreReason} from '@fuzdev/fuz_css/style_rule_parser.js';

Reasons a rule is considered "core" and always included. conditional_core marks a conditional group rule (@media, @supports, @container) that contains something which always ships on its own - a core rule or an at_rule. at_rule marks every at-rule that is not a conditional group (@keyframes, @font-face, @property, @scope, ...): detection has no way to tell whether one is used, so it ships as written. untargetable marks rules with a selector the index can't match - one that names no element or class at all (pseudo-element or attribute selectors like ::selection and [hidden]), or one with an escaped or non-ASCII identifier (.md\:flex, .cafรฉ) - so tree-shaking would drop them whether or not the project uses them.

CoreStyleRule
#

create_bundled_resources
#

bundled_resources.ts view source

(options: CreateBundledResourcesOptions): Promise<BundledCssResources> import {create_bundled_resources} from '@fuzdev/fuz_css/bundled_resources.js';

Builds the bundled CSS resources from generator options. The style-rule index is always built, even when only theme output is enabled - from the default style.css unless base_css supplies a stylesheet.

options

returns

Promise<BundledCssResources>

throws

  • if - `base_css` supplies something that isn't parseable CSS, including a callback that returns a non-string

create_cache_path_resolver
#

css_cache.ts view source

internal

Used by the Vite plugin.

(cache_dir: string, project_root: string): (file_id: string) => string | null import {create_cache_path_resolver} from '@fuzdev/fuz_css/css_cache.js';

Creates the extraction cache-path lookup: a file's cache path under cache_dir in project_root, or null on CI, where nothing is cached.

cache_dir

the cache directory, relative to project_root

type string

project_root

the project root, with or without a trailing slash

type string

returns

(file_id: string) => string | null

a function from a file's absolute path to its cache path, or null when uncached

create_css_generator
#

css_generator.ts view source

internal

The core the Vite plugin renders through - not stable API.

(options: CssGeneratorBaseOptions, sink: DiagnosticSink): CssGenerator import {create_css_generator} from '@fuzdev/fuz_css/css_generator.js';

Creates the core a generator renders through.

options

the generator's options

sink

where logged diagnostics go

returns

CssGenerator

create_diagnostic_dispatcher
#

diagnostics.ts view source

internal

The dispatch the generator core runs - not stable API.

(options: DiagnosticDispatchOptions, sink: DiagnosticSink): (diagnostics: Diagnostic[]) => void import {create_diagnostic_dispatcher} from '@fuzdev/fuz_css/diagnostics.js';

Creates the diagnostic dispatch a generator runs after each render: a diagnostic level set to 'throw' fails the render with a CssGenerationError, and the rest are logged to sink - except that a message the previous dispatch already logged isn't logged again.

A render reports every file's diagnostics, so a dev server or watch mode re-rendering on each edit would otherwise repeat every warning in the project on every change. A diagnostic that goes away and comes back is logged again.

options

the on_error/on_warning settings

sink

where logged diagnostics go

returns

(diagnostics: Diagnostic[]) => void

the dispatch, to call with each render's diagnostics

throws

  • CssGenerationError - from the returned dispatch, for a level set to `'throw'`

create_generation_diagnostic
#

create_style_rule_index
#

style_rule_parser.ts view source

(css: string): StyleRuleIndex import {create_style_rule_index} from '@fuzdev/fuz_css/style_rule_parser.js';

Creates a StyleRuleIndex from the stylesheet a base_css option supplies, reporting a value that can't be parsed as a base_css problem.

css

the base_css string, or the string its callback returned

type string

returns

StyleRuleIndex

throws

  • if - `css` is not syntactically valid CSS, with the parser's error as the `cause`

create_theme_resolver
#

theme_resolver.ts view source

(theme: { name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }, options?: ThemeResolverOptions): 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

the theme to resolve

type Theme

options

the compiled caps to resolve beside the theme, if any

default {}

returns

ThemeKnobResolver

CreateBundledResourcesOptions
#

bundled_resources.ts view source

CreateBundledResourcesOptions import type {CreateBundledResourcesOptions} from '@fuzdev/fuz_css/bundled_resources.js';

base_css

Base CSS source: custom string, callback over the default, or default.

type BaseCssOption

variables

Theme variables source.

type VariablesOption

theme?

Optional theme baked into the variables, overlaid last-wins by name with the mirror and caps bake_theme derives for it.

type Theme | ResolvedTheme | null

deps

Filesystem deps for loading the default style.css.

type CacheDeps

css_class_composites
#

css_class_composites.ts view source

Record<string, CssClassDefinition | undefined>

type Record<string, CssClassDefinition | undefined>

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

The builtin composite classes. The multi-property ones render in the fuz.utilities.composites sublayer (composite: true, the default for rulesets), so a token or literal class on the same element wins over them; the single-property shortcuts (circular, pixelated, mb_flow, mt_flow) are single-purpose and order with the token classes. Their forced-colors rules nest inside their own rules (`@media (forced-colors: active)`), so a modified variant keeps them conditional, and a browser without CSS nesting, which also has no forced-colors mode, skips them.

css_class_definitions
#

css_class_definitions.ts view source

Record<string, CssClassDefinition | undefined>

type Record<string, CssClassDefinition | undefined>

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

All built-in CSS class definitions (composites, keyword classes, and token classes).

see also

  • ``generate_classes_css``

css_class_interpreters
#

css_class_interpreters.ts view source

CssClassDefinitionInterpreter[]

type CssClassDefinitionInterpreter[]

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

Collection of all builtin interpreters for dynamic CSS class generation. Modifier handling isn't an interpreter - the generator strips modifiers from every class name and applies them to whatever the base resolves to.

css_class_keywords
#

css_comment_is_contained
#

css_containment.ts view source

(text: unknown): boolean import {css_comment_is_contained} from '@fuzdev/fuz_css/css_containment.js';

Checks that text can sit inside a CSS comment without closing it.

text

the comment body, e.g. a style variable's summary

type unknown

returns

boolean

css_custom_property_name_is_contained
#

css_containment.ts view source

(name: unknown): boolean import {css_custom_property_name_is_contained} from '@fuzdev/fuz_css/css_containment.js';

Checks that a custom property name is a plain identifier - word characters, hyphens, and non-ASCII (--aรฉ, --ฮ”x) - so it can't smuggle a value or a second declaration in with it.

name

the name without its -- prefix

type unknown

returns

boolean

css_literal_interpreter
#

css_class_interpreters.ts view source

CssClassDefinitionInterpreter import {css_literal_interpreter} from '@fuzdev/fuz_css/css_class_interpreters.js';

Interpreter for CSS-literal classes (e.g., display:flex, opacity:80%). Modifiers (hover:opacity:80%) are stripped by the generator before an interpreter runs, so a literal reaching it is exactly property:value.

CSS_NUMBER_PATTERN
#

ramps.ts view source

internal

Shared by `variable.ts` and the theme modules - not stable API.

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

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

css_value_is_contained
#

css_containment.ts view source

(value: unknown): boolean import {css_value_is_contained} from '@fuzdev/fuz_css/css_containment.js';

Checks that a declaration value can't end its own declaration or rule: quotes and brackets balance, and nothing outside a string closes the declaration (a top-level ;), opens or closes a block, sets !important, opens a comment, or escapes a character. Stricter than the grammar where that keeps the rule simple - braces, comments, and escapes outside strings are rejected outright, as is an unquoted url( whose contents a quoted one would hold, so quote a URL that needs them.

value

the declaration value, e.g. a style variable's slot

type unknown

returns

boolean

CssCacheOptions
#

css_plugin_options.ts view source

CssCacheOptions import type {CssCacheOptions} from '@fuzdev/fuz_css/css_plugin_options.js';

Options for cache behavior.

cache_dir?

Cache directory relative to project root. The Vite plugin keeps the dev server from watching it.

type string

default '.fuz/cache/css'

deps?

Filesystem deps for cache management. Defaults to production implementation. Override for testing.

type CacheDeps

internal A test seam, not stable API.

CssClassDefinition
#

CssClassDefinitionBase
#

css_class_generation.ts view source

CssClassDefinitionBase import type {CssClassDefinitionBase} from '@fuzdev/fuz_css/css_class_generation.js';

comment?

type string

composite?

Whether the class is a composite, rendered in the fuz.utilities.composites sublayer beneath every single-purpose class, so a token or literal class on the same element always wins over the composite's declaration of the same property. Defaults to true for composes and ruleset definitions, false for a declaration without composes.

type boolean

late?

Whether the class orders late within its bucket: after every rule that ties with it on color scheme, media query, property rank, and state order, interpreted literals included, so display:flex hidden hides while a media query still outranks it (hidden md:flex shows at md and up). For an override that should win its ties whatever else names the same property, like hidden. Composites order by their registry position, which no two share, so the flag only reorders single-purpose classes.

type boolean

CssClassDefinitionComposition
#

css_class_generation.ts view source

CssClassDefinitionComposition import type {CssClassDefinitionComposition} from '@fuzdev/fuz_css/css_class_generation.js';

Pure utility composition (composes only).

inheritance

composes

type string[]

declaration?

type undefined

ruleset?

type undefined

CssClassDefinitionDeclaration
#

css_class_generation.ts view source

CssClassDefinitionDeclaration import type {CssClassDefinitionDeclaration} from '@fuzdev/fuz_css/css_class_generation.js';

Custom CSS declaration (optionally seeded with composes).

inheritance

declaration

type string

composes?

type string[]

ruleset?

type undefined

CssClassDefinitionInterpreter
#

css_class_generation.ts view source

CssClassDefinitionInterpreter import type {CssClassDefinitionInterpreter} from '@fuzdev/fuz_css/css_class_generation.js';

Interpreter for dynamic CSS class generation based on pattern matching.

An interpreter sees a class name with its modifiers already stripped - md:hover:grid-cols-4 reaches it as grid-cols-4 - and returns a definition like a static one, so modifiers, ordering, and layering apply to what it returns the same as to a static class. A ruleset names the class it was given; the generator renames it to the full modified class. What an interpreter returns renders verbatim, so containing values built from class names found in markup is the interpreter's job.

Leading segments named like modifiers are stripped greedily, and the generator backs off one at a time, so an interpreter is offered the shortest base first: marker:none arrives as none before the full literal, since marker is also a pseudo-element modifier (cue likewise). A broad pattern shouldn't claim such a sub-base.

inheritance

pattern

type RegExp

interpret

type (matched: RegExpMatchArray, ctx: CssClassInterpreterContext): CssClassDefinitionStatic | null

matched

type RegExpMatchArray

ctx

mutates

  • ctx.diagnostics โ€” implementations push errors/warnings to the diagnostics array

CssClassDefinitionRuleset
#

css_class_generation.ts view source

CssClassDefinitionRuleset import type {CssClassDefinitionRuleset} from '@fuzdev/fuz_css/css_class_generation.js';

Full ruleset with selectors.

inheritance

ruleset

type string

composes?

type undefined

declaration?

type undefined

CssClassDefinitionStatic
#

CssClasses
#

css_classes.ts view source

import {CssClasses} from '@fuzdev/fuz_css/css_classes.js';

Collection of CSS classes extracted from source files. Tracks classes per-file for efficient incremental updates. Handles include/exclude filtering and explicit class tracking. Uses null instead of empty collections to avoid allocation overhead.

constructor

Creates a new CssClasses collection.

type new (additional_classes?: Set<string> | null, exclude_classes?: Set<string> | null): CssClasses

additional_classes

classes to always include (also treated as explicit for warnings)

type Set<string> | null
default null

exclude_classes

classes to exclude from output (also suppresses warnings)

type Set<string> | null
default null

add

Adds extraction results for a file. Replaces any previous classes and diagnostics for this file.

type (id: string, data: ExtractionData): void

id

file identifier

type string

data

extraction data fields to store for this file

returns void

delete

type (id: string): void

id

type string
returns void

subset

Creates a collection holding only the given files' extractions, with the same include and exclude settings - what one set of modules extracted, like the modules of one build environment.

type (ids: Iterable<string>): CssClasses

ids

the files to keep; ids with no extraction are skipped

type Iterable<string, any, any>
returns CssClasses

a new collection sharing the per-file data, which add replaces rather than mutates

get

Gets all unique class names as a Set (with exclude filter applied).

type (): Set<string>

returns Set<string>

get_with_locations

Gets all classes with their source locations (with exclude filter applied). Locations from additional_classes are null.

type (): Map<string, SourceLocation[] | null>

returns Map<string, SourceLocation[] | null>

get_all

Gets all classes and their locations in a single call. More efficient than calling get() and get_with_locations() separately when both are needed (avoids potential double recalculation).

Results have exclude filter applied and explicit_classes includes additional_classes.

type (): { all_classes: Set<string>; all_classes_with_locations: Map<string, SourceLocation[] | null>; explicit_classes: Set<string> | null; all_elements: Set<...>; explicit_elements: Set<...> | null; explicit_variables: Set<...> | null; }

returns { all_classes: Set<string>; all_classes_with_locations: Map<string, SourceLocation[] | null>; explicit_classes: Set<string> | null; all_elements: Set<...>; explicit_elements: Set<...> | null; explicit_variables: Set<...> | null; }

get_diagnostics

Gets all extraction diagnostics from all files.

type (): ExtractionDiagnostic[]

CssClassInterpreterContext
#

css_class_generation.ts view source

CssClassInterpreterContext import type {CssClassInterpreterContext} from '@fuzdev/fuz_css/css_class_generation.js';

Context passed to CSS class interpreters. Provides access to logging, diagnostics collection, and the class registry.

log?

Optional logger for warnings/errors

type Logger

diagnostics

Diagnostics array to collect warnings and errors

type InterpreterDiagnostic[]

class_definitions

All known CSS class definitions (token + composite classes)

type Record<string, CssClassDefinition | undefined>

css_properties

Valid CSS properties for literal validation, or null to skip validation

type Set<string> | null

CssClassOptions
#

css_plugin_options.ts view source

CssClassOptions import type {CssClassOptions} from '@fuzdev/fuz_css/css_plugin_options.js';

Options for CSS class definitions and interpretation. Controls how classes are defined and how dynamic classes are generated.

class_definitions?

Class definitions, merged over the default token and composite classes as a record, or a callback over the defaults returning the whole set. A record's definition takes precedence over a default with the same name.

Registry order breaks ties between single-purpose classes of equal rank, and for composites it is their order, so where a definition lands matters: one with a new name is ordered after the defaults, so it beats a built-in token it ties with on the same property (though not a literal like padding:0, which orders after every static definition), while one overriding a default's name keeps that default's position. A callback's result is the registry in the order it returns, and a callback that doesn't return an object fails generator creation.

type Record<string, CssClassDefinition | undefined> | ((defaults: Record<string, CssClassDefinition | undefined>) => Record<string, CssClassDefinition | undefined>)

// add composites over the defaults class_definitions: custom_composites // only your own definitions, none of the defaults class_definitions: () => custom_composites

class_interpreters?

Interpreters for dynamic class generation, replacing the builtin interpreters as an array, or a callback over them. The builtins are the CSS-literal interpreter, so keep them to keep literal classes.

A callback that doesn't return an array fails generator creation.

type CssClassDefinitionInterpreter[] | ((defaults: CssClassDefinitionInterpreter[]) => CssClassDefinitionInterpreter[])

// run a custom interpreter before the CSS-literal one class_interpreters: (defaults) => [grid_cols_interpreter, ...defaults]

CssClassRule
#

css_class_generation.ts view source

CssClassRule import type {CssClassRule} from '@fuzdev/fuz_css/css_class_generation.js';

A utility class resolved to the rule it renders, before it's written as CSS - what generate_classes_css orders, groups, and layers.

class_name

type string

modifiers

type ExtractedModifiers

composite

Renders in the fuz.utilities.composites sublayer.

type boolean

rank

Order within a color scheme and media query: the definition index for a composite, the property rank (to_property_rank) otherwise.

type number

definition_index

The definition's position in the registry, after every static definition for an interpreted class, breaking ties between rules of equal rank.

type number

late

Orders after the rules it ties with on rank and state (CssClassDefinitionBase.late).

type boolean

body

type CssClassRuleBody

comment

type string | null

CssClassRuleBody
#

css_class_generation.ts view source

CssClassRuleBody

type { type: "declaration"; selector: string; declaration: string; } | { type: "rules"; rules: { selector: string; declarations: string; }[]; } | { type: "verbatim"; css: string; }

import type {CssClassRuleBody} from '@fuzdev/fuz_css/css_class_generation.js';

What a class rule renders: a declaration block on the class selector, a set of rules with their selectors already rewritten for the class and its state and pseudo-element modifiers, or an unmodified ruleset as written (which may hold at-rules of its own).

CssDiagnosticsOptions
#

css_plugin_options.ts view source

CssDiagnosticsOptions import type {CssDiagnosticsOptions} from '@fuzdev/fuz_css/css_plugin_options.js';

Options for error and warning handling.

on_error?

How to handle errors during generation: unresolvable comment hints, invalid CSS literals, and the base stylesheet and theme variable checks.

  • 'log': Log errors, skip invalid classes, continue
  • 'throw': Fail the render with every error it found, failing the build

A logged diagnostic is logged once while it persists - a dev server or watch mode re-rendering on each edit doesn't repeat it - and again if it goes away and comes back.

type "log" | "throw"

default 'throw' in CI (`CI` set to anything but empty, `false`, or `0`), 'log' otherwise

on_warning?

How to handle warnings during generation.

  • 'log': Log warnings, continue (once while each persists, like errors)
  • 'throw': Fail the render with every warning it found, failing the build
  • 'ignore': Suppress warnings entirely

type "log" | "throw" | "ignore"

default 'log'

CssExtractionOptions
#

css_plugin_options.ts view source

CssExtractionOptions import type {CssExtractionOptions} from '@fuzdev/fuz_css/css_plugin_options.js';

Options for CSS class extraction from source files. Controls which files to scan and how to parse them.

filter_file?

Filter function to determine which files to extract classes from, called with each file's absolute id and the project root. By default, extracts from .svelte, .html, .ts, .js, .tsx, .jsx files, excluding test files, .gen files, and test directories inside the project or a dependency's package (see to_filter_scope).

type (path: string, root: string): boolean

path

type string

root

type string
returns boolean

acorn_plugins?

Additional acorn plugins for parsing. Use acorn-jsx for React/Preact/Solid projects.

type AcornPlugin[]

import jsx from 'acorn-jsx'; vite_plugin_fuz_css({ acorn_plugins: [jsx()] });

cache_salt?

A string folded into the extraction cache key. The key already covers file content, the acorn_plugins source text, and the installed versions of fuz_css and its parsers, but a plugin's options live in its closure, so change this when only a plugin's options change (jsx({allowNamespaces: false})) to re-extract every file.

type string

CssGenerationError
#

diagnostics.ts view source

import {CssGenerationError} from '@fuzdev/fuz_css/diagnostics.js';

Error thrown when CSS generation encounters errors or warnings (depending on on_error and on_warning settings). Contains the full diagnostics array for programmatic access.

inheritance

extends: Error

diagnostics

type Diagnostic[]

constructor

type new (diagnostics: Diagnostic[]): CssGenerationError

diagnostics

type Diagnostic[]

CssGenerator
#

css_generator.ts view source

internal

The core the Vite plugin renders through - not stable API.

CssGenerator import type {CssGenerator} from '@fuzdev/fuz_css/css_generator.js';

A generator's shared core - see create_css_generator.

create_css_classes

Creates an empty class collection with the configured include and exclude classes.

type (): CssClasses

returns CssClasses

ensure_ready

Loads what a render needs - the CSS properties literal classes are validated against, and the bundled resources unless both base styles and theme variables are off. Loads once; safe to call any number of times, and a failed load is retried on the next call.

type (): Promise<void>

returns Promise<void>

render

Renders CSS and dispatches its diagnostics. Before ensure_ready resolves it renders utility classes only.

type (input: CssRenderInput): string

input

returns string

throws

  • CssGenerationError - for a diagnostic level set to `'throw'`

CssGeneratorBaseOptions
#

CssLiteralParseResult
#

css_literal.ts view source

CssLiteralParseResult

type { ok: true; parsed: ParsedCssLiteral; diagnostics: InterpreterDiagnostic[] | null; } | { ok: false; error: InterpreterDiagnostic; }

import type {CssLiteralParseResult} from '@fuzdev/fuz_css/css_literal.js';

Result of parsing a CSS-literal class name.

Uses a discriminated union (Result type) because parsing a single class is binary: it either succeeds or fails entirely. This differs from ExtractionResult which uses embedded diagnostics because file extraction can partially succeed (some classes extracted, others have errors).

Uses | null for diagnostics to avoid allocating empty arrays. Callers should use a guard pattern: if (result.diagnostics) { ... }

CssOutputOptions
#

css_plugin_options.ts view source

CssOutputOptions import type {CssOutputOptions} from '@fuzdev/fuz_css/css_plugin_options.js';

Options for CSS output generation (theme + base + utilities). Controls how the three CSS layers are combined.

base_css?

Base styles (element defaults) configuration.

  • undefined (default): Use default style.css
  • null: Disable base styles entirely
  • string: Custom CSS to replace defaults
  • (default_css) => string: Callback to modify default CSS

The stylesheet is any CSS the parser accepts (parseCss from svelte/compiler), which the generator places in the fuz.base cascade layer, below themes and utility classes:

  • Top-level style rules and top-level @media, @supports, and @container rules are tree-shaken by the elements and classes they target. A conditional rule ships whole or not at all. Rules that target :root, :host, html, body, or * always ship, and so does a rule with a selector that can't be matched against detected usage: one naming no element or class ([role='button'], ::selection), or with an escaped or non-ASCII name (.md\:flex).
  • Every other at-rule ships as written (@keyframes, @font-face, @property, @scope, ...), used or not.
  • Every var() reference in CSS that ships is tracked, however deeply it is nested, so the theme includes the variables it needs.
  • The generator owns layering. A callback's additions land in fuz.base with everything else, so they lose to themes, utility classes, and unlayered styles - put overrides that must win in your own stylesheet. Top-level @layer fuz.base and @layer fuz.preferences blocks are recognized as the default stylesheet uses them; any other @layer rule is the error base_css_layer.
  • @import and @namespace are invalid inside a layer and are the error base_css_unsupported_at_rule.

An error never removes CSS: the construct ships as written (a layer becomes a sublayer of fuz.base, and browsers ignore the other two), and the error names it and its line. The one construct left out is a top-level @charset, which means nothing in a string. A stylesheet the parser rejects, or a callback that doesn't return a string, fails generation with an error naming base_css.

type BaseCssOption

// Append custom reset base_css: (css) => css + '\n\n* { box-sizing: border-box; }' // Prepend custom styles base_css: (css) => '.my-reset { margin: 0; }\n\n' + css

variables?

Theme variables configuration.

  • undefined (default): Use default variables from fuz_css
  • null: Disable theme entirely
  • Array<StyleVariable>: Custom variable definitions (replaces defaults)
  • (defaults) => Array<StyleVariable>: Callback to modify default variables

The set is the whole theme: only variables in it are emitted, and only the ones the output references. Base styles that reference a variable the fuz_css defaults define but this set lacks - with null, an empty array, or an array or callback result missing some - raise the error undefined_theme_variables, because a var() with no fallback would resolve to nothing. A reference with a fallback (var(--x, 1px)) is never an error, nor is a name the base styles declare themselves: in the rule that references it, or in a top-level rule with a selector that is exactly :root, :host, html, body, or *. Custom property names of your own are never checked.

To fix the error, define the variables here (keep the defaults a callback receives unless you replace what they style), or set base_css: null too for utility-only mode. To pair bundled base styles with a theme stylesheet imported separately, tell the generator the default set is defined elsewhere through exclude_variables.

type VariablesOption

// Override specific variables variables: (defaults) => defaults.map(v => v.name === 'hue_a' ? { ...v, base: '30' } : v ) // Add custom variables variables: (defaults) => [ ...defaults, { name: 'my_brand', base: '#ff6600', dark: '#ff8833' } ] // Bundled base styles over a separately imported `theme.css` variables: null, exclude_variables: default_variables.map((v) => v.name)

theme?

A theme to bake into the generated CSS, overlaid onto variables last-wins by name. This is how a project picks a theme statically: no JS theme rendering at runtime, and the output stays tree-shaken because the overlay happens before the dependency graph is built, so a theme's referenced variables are pulled in transitively.

For runtime switching use fuz_ui's ThemeRoot; the two compose, with the runtime theme winning by cascade layer. The theme's own overlay also renders into the fuz.theme.baked sublayer - above the fuz.preferences OS mappings, with color-scheme pinned for a stance, and below a runtime theme's direct fuz.theme styles - so the baked theme behaves like the same theme at runtime until one overrides it.

The bake derives what the theme renders with, as render_theme_style takes it at runtime, so a plain Theme is all it needs (a ResolvedTheme is accepted too, its derived data recomputed):

  • a single-scheme theme's stance mirror, re-slotted from the configured variables, so a customized scheme-adaptive variable keeps its own value under the stance
  • compiled chroma caps: compute_theme_caps recomputes the gamut caps wherever the theme's hues or lightness moved off the baked table (a rotated hue, a monochrome collapse), and the caps render last. The gates run with them and report as warnings - theme_gate_failed and theme_gate_unchecked - measured against the shipped defaults' numeric twin with the configured variables' knob-tier values folded in where they differ from the defaults, so the caps and gates measure what renders. A stanced theme lists only its stanced scheme's entries. A theme can fail a gate knowingly: marquee bakes with a gamut warning, since it exceeds the caps on purpose
  • the lint: validate_theme runs over the theme, each issue a theme_lint diagnostic at its own level - an unknown variable is an error, the knob range and type checks are warnings

The baked values become the output's defaults, so a runtime theme can't revert to the pre-bake appearance by being empty - the base theme renders nothing. To offer "back to fuz defaults" at runtime, render the defaults explicitly, internal ramp variables included: render_style_variables(default_variables).

type Theme | ResolvedTheme | null

import {phosphor_theme} from '@fuzdev/fuz_css/themes/phosphor.ts'; vite_plugin_fuz_css({theme: phosphor_theme});

additional_classes?

Classes to always include in the output, regardless of detection. Useful for dynamically generated class names that can't be statically extracted. A class no class definition resolves is an error, as with a @fuz-classes hint, unless base styles are bundled and a base style rule targets it (like selected or palette_a).

type Iterable<string, any, any>

additional_elements?

Additional HTML elements to always include base styles for. Use 'all' to include all base styles regardless of detection. Useful for elements generated at runtime via document.createElement().

type Iterable<string, any, any> | "all"

additional_variables?

Additional CSS variables to always include in theme output. Use 'all' to include all theme variables regardless of detection. Useful for variables referenced dynamically.

type Iterable<string, any, any> | "all"

exclude_classes?

Classes to exclude from the output, even if detected. Useful for filtering out false positives from extraction.

type Iterable<string, any, any>

exclude_elements?

Elements to exclude from base CSS output, even if detected. Useful for filtering out elements you don't want styles for.

type Iterable<string, any, any>

exclude_variables?

CSS variables to exclude from theme output, even if referenced. Useful for filtering out variables you don't want in the theme, and for declaring that something else defines one: an excluded variable leaves out the dependencies only it pulls in, excluding one the output references or a shipped variable depends on is a warning when the theme has it, and a name listed here is skipped by the undefined_theme_variables check.

type Iterable<string, any, any>

// every default variable is defined by a stylesheet imported separately exclude_variables: default_variables.map((v) => v.name)

CssRenderInput
#

css_generator.ts view source

internal

The core the Vite plugin renders through - not stable API.

CssRenderInput import type {CssRenderInput} from '@fuzdev/fuz_css/css_generator.js';

What one render reads: the classes extracted so far and the var() names scanned from source.

css_classes

type CssClasses

detected_css_variables

The var(--*) names referenced in source, unfiltered - names that aren't theme variables are ignored.

type Iterable<string, any, any>

log?

A logger for custom interpreters.

type Logger

CssResolutionOptions
#

css_bundled_resolution.ts view source

CssResolutionOptions import type {CssResolutionOptions} from '@fuzdev/fuz_css/css_bundled_resolution.js';

Options for CSS resolution.

style_rule_index

Index of style.css rules

type StyleRuleIndex

variable_graph

Dependency graph for theme variables

type VariableDependencyGraph

detected_elements

HTML elements detected in source files

type Set<string>

detected_classes

CSS classes detected in source files

type Set<string>

detected_css_variables

CSS variables directly referenced in source files

type Set<string>

utility_variables_used

CSS variables used by generated utility classes

type Set<string>

additional_elements?

Additional elements to always include, or 'all' to include all base styles

type Iterable<string, any, any> | "all"

additional_variables?

Additional variables to always include, or 'all' to include all theme variables

type Iterable<string, any, any> | "all"

warn_unmatched_elements?

Warn when detected elements have no matching style rules (default false)

type boolean

exclude_elements?

Elements to exclude from base CSS output, even if detected.

type Iterable<string, any, any>

exclude_variables?

CSS variables to exclude from theme output, even if referenced.

type Iterable<string, any, any>

explicit_elements?

Elements explicitly annotated via @fuz-elements comments. These produce errors (not warnings) if they have no matching style rules.

type Set<string> | null

explicit_variables?

Variables explicitly annotated via @fuz-variables comments. These produce errors (not warnings) if they don't exist in the theme.

type Set<string> | null

CssResolutionResult
#

css_bundled_resolution.ts view source

CssResolutionResult import type {CssResolutionResult} from '@fuzdev/fuz_css/css_bundled_resolution.js';

Result from CSS resolution.

theme_css

CSS for theme variables (base and dark)

type string

base_css

CSS for base styles (from style.css), destined for fuz.base

type string

preferences_css

CSS for the OS user-preference mappings, destined for fuz.preferences

type string

resolved_variables

All resolved variable names (including transitive deps)

type Set<string>

included_rule_indices

Indices of rules included from the style index

type Set<number>

included_elements

Element names that were matched

type Set<string>

diagnostics

Diagnostics from resolution

type GenerationDiagnostic[]

darken_lighten_variants
#

variable_data.ts view source

readonly ["00", "05", "10", "20", "30", "40", "50", "60", "70", "80", "90", "95", "100"] import {darken_lighten_variants} from '@fuzdev/fuz_css/variable_data.js';

DarkenLightenVariant
#

variable_data.ts view source

"00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

import type {DarkenLightenVariant} from '@fuzdev/fuz_css/variable_data.js';

default_cache_deps
#

deps_defaults.ts view source

CacheDeps import {default_cache_deps} from '@fuzdev/fuz_css/deps_defaults.js';

Default filesystem deps using node:fs/promises.

DEFAULT_CACHE_DIR
#

css_cache.ts view source

".fuz/cache/css" import {DEFAULT_CACHE_DIR} from '@fuzdev/fuz_css/css_cache.js';

Default cache directory relative to project root.

DEFAULT_THEME
#

themes.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {DEFAULT_THEME} from '@fuzdev/fuz_css/themes.js';

default_themes
#

themes.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }[]

type Theme[]

import {default_themes} from '@fuzdev/fuz_css/themes.js';

The curated theme registry that theme pickers enumerate.

Registry themes are semantic-tier by policy: they move intent bindings (which palette letter a meaning points at) and levers (chroma scale, curves, form knobs) but never the palette hues themselves, so the letters stay a stable vocabulary across every registered theme.

Themes live one module per theme under themes/ and every module ships as an importable export - registry membership, not file location, is what separates registered themes from shipped exemplars. The registry holds the plain working themes: the base and themes/ledger.ts (compact, cool, for tools used all day).

The exemplars deliberately stay out of this list. Each takes one channel to carry the structure and quiets the rest, and is named for the artifact that already looks that way: themes/zine.ts (line and weight), themes/pebble.ts (depth and softness), themes/parchment.ts (type and ruling), themes/phosphor.ts (packing, dark-only), themes/guestbook.ts (controls as beveled objects), themes/marquee.ts (color, dark-only and the one palette-tier exemplar), and themes/signage.ts (scale and weight, for legibility).

Contrast is not a theme: the low/high contrast pair are modifiers (contrast_modifiers) composed over any theme with compose_themes.

default_variables
#

variables.ts view source

{ name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]

type StyleVariable[]

import {default_variables} from '@fuzdev/fuz_css/variables.js';

These are implicitly the variables for the base theme. See also the empty variables array of the base theme in themes/base.ts.

delete_cached_extraction
#

css_cache.ts view source

(deps: CacheDeps, cache_path: string): Promise<void> import {delete_cached_extraction} from '@fuzdev/fuz_css/css_cache.js';

Deletes a cached extraction file. Best-effort: every unlink error is swallowed, not just not_found - the cache is disposable and callers delete fire-and-forget.

deps

filesystem deps for dependency injection

cache_path

absolute path to the cache file

type string

returns

Promise<void>

demo_class
#

DEMO_CLASS
#

demo_class_list
#

demo_class_lists
#

example_class_utilities.ts view source

"mb_xl5 ml_xl2" import {demo_class_lists} from '@fuzdev/fuz_css/example_class_utilities.js';

*class_lists suffix (snake_case) - plural, multiple classes

demo_class_name
#

demo_class_names
#

example_class_utilities.ts view source

"mb_xl ml_lg" import {demo_class_names} from '@fuzdev/fuz_css/example_class_utilities.js';

*class_names suffix (snake_case) - plural, multiple classes

demo_classes
#

demoClass
#

demoClasses
#

demoClassList
#

demoClassLists
#

example_class_utilities.ts view source

"mb_xl4 ml_xl" import {demoClassLists} from '@fuzdev/fuz_css/example_class_utilities.js';

*ClassLists suffix (camelCase) - plural, multiple classes

demoClassName
#

demoClassNames
#

example_class_utilities.ts view source

"mb_lg ml_md" import {demoClassNames} from '@fuzdev/fuz_css/example_class_utilities.js';

*ClassNames suffix (camelCase) - plural, multiple classes

Diagnostic
#

DiagnosticDispatchOptions
#

diagnostics.ts view source

internal

The dispatch the generator core runs - not stable API.

DiagnosticDispatchOptions import type {DiagnosticDispatchOptions} from '@fuzdev/fuz_css/diagnostics.js';

How generation diagnostics are handled - see CssDiagnosticsOptions.

on_error

type "log" | "throw"

on_warning

type "log" | "throw" | "ignore"

DiagnosticSink
#

diagnostics.ts view source

internal

The dispatch the generator core runs - not stable API.

DiagnosticSink import type {DiagnosticSink} from '@fuzdev/fuz_css/diagnostics.js';

Where a dispatcher writes the diagnostics it logs.

warn

type (message: string): void

message

type string
returns void

error

type (message: string): void

message

type string
returns void

display_keywords
#

css_class_keywords.ts view source

readonly ["flex", "inline-flex", "grid", "inline-grid", "inline-block", "block", "flow-root"] import {display_keywords} from '@fuzdev/fuz_css/css_class_keywords.js';

The display keywords with a class: the inside formatting contexts and the legacy inline forms, plus block.

distance_variants
#

variable_data.ts view source

readonly ["xs", "sm", "md", "lg", "xl"] import {distance_variants} from '@fuzdev/fuz_css/variable_data.js';

DISTANCES
#

variable_data.ts view source

Readonly<Record<"lg" | "md" | "sm" | "xs" | "xl", number>>

type Readonly<Record<DistanceVariant, number>>

import {DISTANCES} from '@fuzdev/fuz_css/variable_data.js';

Layout distances in px - breakpoint-ish widths, insensitive to font size.

DistanceVariant
#

variable_data.ts view source

"lg" | "md" | "sm" | "xs" | "xl"

type "lg" | "md" | "sm" | "xs" | "xl"

import type {DistanceVariant} from '@fuzdev/fuz_css/variable_data.js';

duration_variants
#

DURATIONS
#

variable_data.ts view source

Readonly<Record<6 | 1 | 2 | 3 | 4 | 5, number>>

type Readonly<Record<DurationVariant, number>>

import {DURATIONS} from '@fuzdev/fuz_css/variable_data.js';

Transition durations in seconds, from a UI beat to a slow ambient sweep.

DurationVariant
#

variable_data.ts view source

6 | 1 | 2 | 3 | 4 | 5

type 6 | 1 | 2 | 3 | 4 | 5

import type {DurationVariant} from '@fuzdev/fuz_css/variable_data.js';

escape_css_identifier
#

css_containment.ts view source

(value: string): string import {escape_css_identifier} from '@fuzdev/fuz_css/css_containment.js';

Serializes a string as a CSS identifier, so any string can name an element id in a selector ('#' + escape_css_identifier(id) matches the element whose id attribute is that string). Follows the CSSOM identifier serialization, except that ASCII punctuation is escaped by code point (\3c ) rather than with a bare backslash, since \</style still closes a <style> element - the output can't end its rule or its element.

value

the raw identifier text

type string

returns

string

the identifier, safe to follow # or . in a selector

escape_css_selector
#

css_class_generation.ts view source

(name: string): string import {escape_css_selector} from '@fuzdev/fuz_css/css_class_generation.js';

Escapes special characters in a CSS class name for use in a selector. ASCII punctuation like :, %, (, and ) takes a bare backslash, as does a space, which would otherwise split the selector in two; a leading digit (also after a leading -) and control characters take a hex escape, since neither is valid there as written, and NUL becomes U+FFFD.

name

type string

returns

string

examples

escape_css_selector('display:flex') // 'display\\:flex' escape_css_selector('opacity:80%') // 'opacity\\:80\\%' escape_css_selector('nth-child(2n)') // 'nth-child\\(2n\\)' escape_css_selector('2xl:p_md') // '\\32 xl\\:p_md'

extract_and_validate_modifiers
#

css_literal.ts view source

(segments: string[], class_name: string): ModifierExtractionResult import {extract_and_validate_modifiers} from '@fuzdev/fuz_css/css_literal.js';

Extracts and validates modifiers from the beginning of a segments array. Modifiers are consumed from the front until a non-modifier segment is found.

Used by both CSS-literal parsing and modified class interpretation.

segments

array of colon-separated segments

type string[]

class_name

original class name for error messages

type string

returns

ModifierExtractionResult

ModifierExtractionResult with modifiers and remaining segments, or error

extract_balanced_parens
#

modifiers.ts view source

(segment: string, prefix: string): string | null import {extract_balanced_parens} from '@fuzdev/fuz_css/modifiers.js';

Extracts content from balanced parentheses after a prefix. Supports nested parens for calc(), clamp(), min(), max(), etc.

segment

the full segment to parse (e.g., "min-width(calc(100vw - 200px))")

type string

prefix

the prefix before the opening paren (e.g., "min-width")

type string

returns

string | null

the content inside the balanced parens, or null if no match/unbalanced

examples

extract_balanced_parens("min-width(800px)", "min-width") // "800px" extract_balanced_parens("min-width(calc(100vw - 20px))", "min-width") // "calc(100vw - 20px)" extract_balanced_parens("min-width(calc(100vw)", "min-width") // null (unbalanced)

extract_css_classes
#

css_class_extractor.ts view source

(source: string, options?: ExtractCssClassesOptions): Set<string> | null import {extract_css_classes} from '@fuzdev/fuz_css/css_class_extractor.js';

Unified extraction function that auto-detects file type. Returns just the class names as a Set.

source

the file source code

type string

options

extraction options

default {}

returns

Set<string> | null

set of class names, or null if none found

extract_css_classes_with_locations
#

css_class_extractor.ts view source

(source: string, options?: ExtractCssClassesOptions): ExtractionResult import {extract_css_classes_with_locations} from '@fuzdev/fuz_css/css_class_extractor.js';

Unified extraction function that auto-detects file type. Returns full extraction result with locations and diagnostics.

source

the file source code

type string

options

extraction options

default {}

returns

ExtractionResult

full extraction result with classes, tracked variables, and diagnostics

extract_css_variables
#

css_variable_utils.ts view source

(css: string): Set<string> import {extract_css_variables} from '@fuzdev/fuz_css/css_variable_utils.js';

Extracts CSS variable names from a CSS string.

Parses var(--name) patterns and returns the variable names without the -- prefix. Handles fallback values by extracting only the primary variable reference.

css

CSS string potentially containing var(--*) references

type string

returns

Set<string>

set of variable names (without -- prefix)

examples

extract_css_variables('color: var(--text_color);') // โ†’ Set { 'text_color' } extract_css_variables('background: var(--bg_1, var(--bg_2));') // โ†’ Set { 'bg_1', 'bg_2' } extract_css_variables('padding: 1rem;') // โ†’ Set {}

extract_declared_css_variables
#

css_variable_utils.ts view source

(css: string): Set<string> import {extract_declared_css_variables} from '@fuzdev/fuz_css/css_variable_utils.js';

Extracts the custom properties a CSS string declares.

css

CSS string potentially containing --name: value declarations

type string

returns

Set<string>

set of variable names (without -- prefix)

extract_file_cached
#

extract_file_cached.ts view source

(options: ExtractFileCachedOptions): Promise<ExtractFileCachedResult> import {extract_file_cached} from '@fuzdev/fuz_css/extract_file_cached.js';

Loads the cached extraction when its content hash and configuration key match, otherwise extracts fresh. On a miss with caching enabled, cache_path_to_write carries the path the caller should write.

options

returns

Promise<ExtractFileCachedResult>

extract_from_svelte
#

css_class_extractor.ts view source

(source: string, file?: string): ExtractionResult import {extract_from_svelte} from '@fuzdev/fuz_css/css_class_extractor.js';

Extracts CSS classes from a Svelte file using AST parsing.

source

the Svelte file source code

type string

file

file path for location tracking

type string
default '<unknown>'

returns

ExtractionResult

extraction result with classes, tracked variables, elements, and diagnostics

extract_from_ts
#

css_class_extractor.ts view source

(source: string, file?: string, acorn_plugins?: AcornPlugin[] | undefined): ExtractionResult import {extract_from_ts} from '@fuzdev/fuz_css/css_class_extractor.js';

Extracts CSS classes from a TypeScript/JS file using AST parsing.

source

the TS/JS file source code

type string

file

file path for location tracking

type string
default '<unknown>'

acorn_plugins?

additional acorn plugins (e.g., acorn-jsx for React)

type AcornPlugin[]
optional

returns

ExtractionResult

extraction result with classes, tracked variables, elements, and diagnostics

extract_required_css_variables
#

css_variable_utils.ts view source

(css: string): Set<string> import {extract_required_css_variables} from '@fuzdev/fuz_css/css_variable_utils.js';

Extracts the CSS variables a string references with no fallback - the ones that must be defined for the value to resolve. var(--a, 1px) can't resolve to nothing, so a is left out, while the b in var(--a, var(--b)) is required.

css

CSS string potentially containing var(--*) references

type string

returns

Set<string>

set of variable names (without -- prefix)

extract_segments
#

css_literal.ts view source

(class_name: string): string[] import {extract_segments} from '@fuzdev/fuz_css/css_literal.js';

Extracts colon-separated segments from a class name, handling parentheses. Parenthesized content (like function arguments) is kept intact.

class_name

type string

returns

string[]

examples

extract_segments('md:hover:display:flex') // โ†’ ['md', 'hover', 'display', 'flex'] extract_segments('nth-child(2n+1):color:red') // โ†’ ['nth-child(2n+1)', 'color', 'red'] extract_segments('width:calc(100%-20px)') // โ†’ ['width', 'calc(100%-20px)']

ExtractCssClassesOptions
#

css_class_extractor.ts view source

ExtractCssClassesOptions import type {ExtractCssClassesOptions} from '@fuzdev/fuz_css/css_class_extractor.js';

Options for CSS class extraction.

filename?

File path used to determine extraction method (Svelte vs TS) and for location tracking in diagnostics.

type string

acorn_plugins?

Additional acorn plugins to use when parsing TS/JS files. Useful for adding JSX support via acorn-jsx for React projects.

type AcornPlugin[]

import jsx from 'acorn-jsx'; extract_css_classes(source, { acorn_plugins: [jsx()] });

ExtractedModifiers
#

css_literal.ts view source

ExtractedModifiers import type {ExtractedModifiers} from '@fuzdev/fuz_css/css_literal.js';

Extracted modifiers from a class name. Used by both CSS-literal parsing and modified class interpretation.

media

Media modifier (breakpoint or feature query)

type ModifierDefinition | null

ancestor

Ancestor modifier (dark/light)

type ModifierDefinition | null

states

State modifiers in alphabetical order (can have multiple)

type ModifierDefinition[]

pseudo_element

Pseudo-element modifier (before, after, etc.)

type ModifierDefinition | null

ExtractFileCachedOptions
#

extract_file_cached.ts view source

ExtractFileCachedOptions import type {ExtractFileCachedOptions} from '@fuzdev/fuz_css/extract_file_cached.js';

deps

type CacheDeps

content

Source file contents.

type string

content_hash

Content hash to validate the cache against.

type string

extraction_key

The configuration part of the key, from to_extraction_cache_key.

type string | null

cache_path

Cache file path, or null to skip the cache (CI or caching disabled).

type string | null

filename

File path, for parser selection and diagnostic locations.

type string

acorn_plugins?

type AcornPlugin[]

ExtractFileCachedResult
#

extract_file_cached.ts view source

ExtractFileCachedResult import type {ExtractFileCachedResult} from '@fuzdev/fuz_css/extract_file_cached.js';

extraction

type ExtractionData

from_cache

Whether the extraction came from cache.

type boolean

cache_path_to_write

Cache file to write (miss with caching enabled), or null.

type string | null

ExtractionData
#

css_class_extractor.ts view source

ExtractionData import type {ExtractionData} from '@fuzdev/fuz_css/css_class_extractor.js';

Cacheable extraction data fields shared between extraction and caching layers. Uses null instead of empty collections to avoid allocation overhead.

classes

Map from class name to locations where it was used, or null if none. Keys = unique classes, values = locations for diagnostics/IDE integration.

type Map<string, SourceLocation[]> | null

explicit_classes

Classes explicitly annotated via @fuz-classes comments, or null if none. These produce errors if they can't be resolved during generation - by a class definition or, when base styles are bundled, a base style rule.

type Set<string> | null

diagnostics

Diagnostics from the extraction phase, or null if none

type ExtractionDiagnostic[] | null

elements

HTML elements found in the file, or null if none. Used for including only the style.css rules needed.

type Set<string> | null

explicit_elements

Elements explicitly annotated via @fuz-elements comments, or null if none. These should produce errors if they have no matching style rules.

type Set<string> | null

explicit_variables

Variables explicitly annotated via @fuz-variables comments, or null if none. These produce errors if they can't be resolved to theme variables.

type Set<string> | null

ExtractionDiagnostic
#

ExtractionResult
#

css_class_extractor.ts view source

ExtractionResult import type {ExtractionResult} from '@fuzdev/fuz_css/css_class_extractor.js';

Extraction result with classes mapped to their source locations. Extends ExtractionData with tracked_vars which is internal to AST walking.

Uses embedded diagnostics (rather than a Result type) because file extraction can partially succeed: some classes may be extracted while others produce errors. This differs from CssLiteralParseResult which uses a discriminated union because single-class parsing is binary success/failure.

inheritance

tracked_vars

Variables that were used in class contexts, or null if none

type Set<string> | null

FileFilter
#

file_filter.ts view source

FileFilter import type {FileFilter} from '@fuzdev/fuz_css/file_filter.js';

Filter function to determine which files to process for CSS class extraction. The Vite plugin passes each file's absolute id and the project root (Vite's root), so a filter can judge a path by where it sits in the project rather than where the project sits on disk. A filter that ignores the root keeps working.

(call)

type (path: string, root: string): boolean

path

type string

root

type string
returns boolean

filter_file_default
#

file_filter.ts view source

(path: string, root: string): boolean import {filter_file_default} from '@fuzdev/fuz_css/file_filter.js';

Default file filter for CSS class extraction. Includes .svelte, .html, .ts, .js, .tsx, .jsx files, and .css files for their variable references (see is_css_file) - except a CSS id with a query, like the Foo.svelte?svelte&type=style&lang.css id of a Svelte component's styles, which its .svelte file already covers. Excludes test files (.test.ts, .spec.ts) and generated files (.gen.ts). Excludes files in test directories (test/, tests/, __tests__/, __mocks__/), judged inside the project or the dependency's package (see to_filter_scope), so a project checked out under a test/ directory still extracts.

path

type string

root

type string

returns

boolean

find_compound_end
#

css_ruleset_parser.ts view source

(selector: string, class_pos: number): number import {find_compound_end} from '@fuzdev/fuz_css/css_ruleset_parser.js';

Finds the end position of the compound selector containing the class at class_pos. A compound selector is a sequence of simple selectors without combinators.

selector

the CSS selector string

type string

class_pos

position of the . in .class_name

type number

returns

number

position where state modifiers should be inserted (before any pseudo-element)

find_package_version
#

css_cache.ts view source

internal

Exported for testing.

(name: string, from: string): string | null import {find_package_version} from '@fuzdev/fuz_css/css_cache.js';

Reads a package's version from the nearest package.json named name at or above from. A package.json with another name is passed over, so a nested one (a "type" marker in a subdirectory) or a bundling consumer's doesn't stand in for the package.

name

the package name

type string

from

the directory to start from

type string

returns

string | null

the version, or null when no package.json above from names the package

find_similar_variable
#

variable_graph.ts view source

(graph: VariableDependencyGraph, name: string): string | null import {find_similar_variable} from '@fuzdev/fuz_css/variable_graph.js';

Finds the most similar variable in the graph to the given name. Returns null if no variable exceeds the similarity threshold.

graph

the variable dependency graph

name

the variable name to find similar matches for

type string

returns

string | null

the most similar variable name, or null if none are similar enough

font_family_variants
#

variable_data.ts view source

readonly ["font_family_sans", "font_family_serif", "font_family_mono"] import {font_family_variants} from '@fuzdev/fuz_css/variable_data.js';

font_size_names
#

font_size_variants
#

variable_data.ts view source

readonly ["xs", "sm", "md", "lg", "xl", "xl2", "xl3", "xl4", "xl5", "xl6", "xl7", "xl8", "xl9"] import {font_size_variants} from '@fuzdev/fuz_css/variable_data.js';

FONT_SIZES
#

variable_data.ts view source

Readonly<Record<"lg" | "md" | "sm" | "xs" | "xl" | "xl2" | "xl3" | "xl4" | "xl5" | "xl6" | "xl7" | "xl8" | "xl9", number>>

type Readonly<Record<SizeVariant, number>>

import {FONT_SIZES} from '@fuzdev/fuz_css/variable_data.js';

Font sizes in rem. md and the steps below it are fitted literals the CSS emits. The steps above md are md * TYPE_SCALE_RATIO ** n rounded to two places - the numeric twin of the CSS defaults, which derive from --type_scale_ratio and never read these values - kept for anything that wants the default numbers, and pinned to the formula by the tests.

font_style_keywords
#

css_class_keywords.ts view source

readonly ["italic", "oblique"] import {font_style_keywords} from '@fuzdev/fuz_css/css_class_keywords.js';

The font-style keywords with a class.

font_weight_keywords
#

css_class_keywords.ts view source

readonly ["bold", "bolder", "lighter"] import {font_weight_keywords} from '@fuzdev/fuz_css/css_class_keywords.js';

The font-weight keywords with a class.

FontFamilyVariant
#

variable_data.ts view source

"font_family_sans" | "font_family_serif" | "font_family_mono"

type "font_family_sans" | "font_family_serif" | "font_family_mono"

import type {FontFamilyVariant} from '@fuzdev/fuz_css/variable_data.js';

format_css_value
#

css_literal.ts view source

(value: string): string import {format_css_value} from '@fuzdev/fuz_css/css_literal.js';

Formats a CSS-literal value for CSS output.

  • Replaces ~ with space
  • Ensures space before !important

value

raw value from class name

type string

returns

string

formatted CSS value

format_diagnostic
#

diagnostics.ts view source

(d: Diagnostic): string import {format_diagnostic} from '@fuzdev/fuz_css/diagnostics.js';

Formats a diagnostic for display.

d

returns

string

format_palette_gloss
#

variable_data.ts view source

(letter: "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j"): string import {format_palette_gloss} from '@fuzdev/fuz_css/variable_data.js';

Formats a letter's gloss for display: the color name plus the default intent binding where one exists, e.g. blue ยท default accent. Shared by display surfaces so the phrasing can't drift.

letter

returns

string

format_spacing_value
#

css_class_generators.ts view source

(value: string): string import {format_spacing_value} from '@fuzdev/fuz_css/css_class_generators.js';

Format spacing values for CSS (handles 0, auto, percentages, pixels, and CSS variables). Used by margin, padding, gap, inset, top/right/bottom/left, etc.

value

type string

returns

string

format_variable_name
#

from_cached_extraction
#

css_cache.ts view source

(cached: CachedExtraction): ExtractionData import {from_cached_extraction} from '@fuzdev/fuz_css/css_cache.js';

Converts a cached extraction back to the runtime format. Preserves null semantics (null = empty).

cached

cached extraction data

returns

ExtractionData

fromComment
#

example_class_utilities.ts view source

"shadow_lg" import {fromComment} from '@fuzdev/fuz_css/example_class_utilities.js';

Comment hint - extracted via @fuz-classes, NOT via variable name pattern. Variable name fromComment doesn't end in class/classes/className.

FUZ_BAKED_THEME_LAYER
#

theme.ts view source

"fuz.theme.baked" import {FUZ_BAKED_THEME_LAYER} from '@fuzdev/fuz_css/theme.js';

The sublayer a build-time theme's own overlay renders into. A layer's direct styles outrank its sublayers, so a runtime theme rendered into fuz.theme wins over the baked one whatever their selectors' specificity, while the baked overlay still sits above fuz.preferences.

FUZ_CSS_BANNER
#

vite_plugin_fuz_css.ts view source

"/* generated by vite_plugin_fuz_css */" import {FUZ_CSS_BANNER} from '@fuzdev/fuz_css/vite_plugin_fuz_css.js';

Banner comment at the top and bottom of generated CSS output.

FUZ_CSS_PLACEHOLDER
#

css_placeholder_splice.ts view source

"--fuz-css-placeholder" import {FUZ_CSS_PLACEHOLDER} from '@fuzdev/fuz_css/css_placeholder_splice.js';

Marker custom property emitted by the build-mode virtual module. Unlike a CSS comment (stripped by minification) this survives into the output, so generateBundle can locate both the asset where Vite placed the virtual module's CSS - the importer's globally-loaded stylesheet, not an arbitrary code-split chunk - and the offset within it that import order put it at.

FUZ_CSS_PLACEHOLDER_RULE
#

css_placeholder_splice.ts view source

":root{--fuz-css-placeholder:1}" import {FUZ_CSS_PLACEHOLDER_RULE} from '@fuzdev/fuz_css/css_placeholder_splice.js';

The rule the build-mode virtual module loads as, before the generated CSS is known.

FUZ_LAYER_ORDER_STATEMENT
#

theme.ts view source

"@layer fuz.base, fuz.preferences, fuz.theme, fuz.utilities;" import {FUZ_LAYER_ORDER_STATEMENT} from '@fuzdev/fuz_css/theme.js';

The fuz_css cascade layer order: defaults (variables + element styles) in fuz.base, OS user-preference mappings (prefers-contrast, prefers-reduced-motion) in fuz.preferences, theme overrides in fuz.theme, generated utility classes in fuz.utilities. Layer order beats specificity and source order, so the preference mappings win over the defaults, theme overrides win over both regardless of head insertion order, and consumers' unlayered styles beat everything.

Two deliberate exceptions, both !important declarations in a layer, which outrank every later layer and unlayered styles: the prefers-reduced-motion mapping (a theme's durations must not re-enable motion the user turned off) and [hidden].

GATE_BODY_TEXT
#

theme_check.ts view source

7 import {GATE_BODY_TEXT} from '@fuzdev/fuz_css/theme_check.js';

AAA body text: --text_color (text_80 by default) on shade_00/05/10.

GATE_BORDER
#

theme_check.ts view source

1.5 import {GATE_BORDER} from '@fuzdev/fuz_css/theme_check.js';

Control borders: --border_color (shade_30 by default) vs shade_00. A regression floor for the shipped design, not a WCAG level - 1.4.11's 3:1 applies to required component boundaries, and fuz borders sit deliberately softer - so a theme can't silently wash control borders out.

GATE_BORDER_DIVIDER
#

theme_check.ts view source

1.3 import {GATE_BORDER_DIVIDER} from '@fuzdev/fuz_css/theme_check.js';

Divider borders: the border_color_30 alpha color composited over shade_00 (the hr pairing in style.css). A regression floor like GATE_BORDER.

GATE_FILL_TEXT
#

theme_check.ts view source

3 import {GATE_FILL_TEXT} from '@fuzdev/fuz_css/theme_check.js';

Large-text floor: text_max on every stop-50 fill.

GATE_GAMUT_TOLERANCE
#

theme_check.ts view source

0.0001 import {GATE_GAMUT_TOLERANCE} from '@fuzdev/fuz_css/theme_check.js';

Gamut gate: how far outside sRGB (the largest channel excess) a stop may sit and still pass - float noise, not visible clipping.

GATE_LINK
#

GATE_PALETTE_TEXT
#

theme_check.ts view source

4.5 import {GATE_PALETTE_TEXT} from '@fuzdev/fuz_css/theme_check.js';

AA colored labels: every palette hue at stop 60 on shade_00 (colored text) and on its own stop-10 tint (the chip), and the .palette_X button label - the hue at stop 70 - on each of the button's fills. The fills follow the style.css recipe: the hue at stop 60 at 8% alpha at rest (and focused), 16% hovered, and 24% pressed, composited over shade_00 in gamma-encoded sRGB. A hovered label mixes 10% toward shade_max in oklab, so a mouse press pairs that label with the pressed fill, and a keyboard press, which doesn't hover, pairs the plain label with it. An 8-bit raster quantizes both colors, so a rendered measurement lands within about 0.15 of the ratio, and the gate reads it low more often than high.

GATE_SELECTED_TEXT
#

theme_check.ts view source

4.5 import {GATE_SELECTED_TEXT} from '@fuzdev/fuz_css/theme_check.js';

AA selected-control inverse text: text_00 on shade_60 and on every stop-60 fill - the selected-button pairings in style.css (.selected fills with shade_60, .palette_X.selected with palette_X_60). The endpoint stop is immune to text_lightness_curve bends, so this gate moves only when a theme moves the endpoints, the fill ramps, or the hues.

GATE_SUBTLE_TEXT
#

theme_check.ts view source

3 import {GATE_SUBTLE_TEXT} from '@fuzdev/fuz_css/theme_check.js';

Disabled/secondary floor: --text_disabled (text_50 by default) on shade_00.

GATE_UI
#

theme_check.ts view source

3 import {GATE_UI} from '@fuzdev/fuz_css/theme_check.js';

WCAG 1.4.11 non-text: every hue at stop 50 vs shade_00, and an authored --outline_color (the focus ring, the accent at stop 50 by default).

generate_base_css_by_layer
#

style_rule_parser.ts view source

(index: StyleRuleIndex, included_indices: Set<number>): Record<RuleLayer, string> import {generate_base_css_by_layer} from '@fuzdev/fuz_css/style_rule_parser.js';

Generates CSS from a StyleRuleIndex with only the included rules, partitioned by destination cascade layer in one sorted pass.

index

included_indices

set of rule indices to include

type Set<number>

returns

Record<RuleLayer, string>

per-layer CSS strings, each in original rule order

generate_border_radius_corners
#

css_class_generators.ts view source

(values: Iterable<string>, formatter?: ((value: string) => string) | undefined): Record<string, CssClassDefinition> import {generate_border_radius_corners} from '@fuzdev/fuz_css/css_class_generators.js';

Generate border radius corner classes for all four corners. Creates classes for top-left, top-right, bottom-left, bottom-right corners.

values

the values to generate classes for

type Iterable<string, any, any>

formatter?

optional function to format values

type (value: string) => string
optional

returns

Record<string, CssClassDefinition>

generate_bundled_css
#

css_bundled_resolution.ts view source

(result: CssResolutionResult, utility_css: string, options?: GenerateBundledCssOptions): string import {generate_bundled_css} from '@fuzdev/fuz_css/css_bundled_resolution.js';

Generates combined CSS output from resolution result.

result

resolution result from resolve_css

utility_css

generated utility CSS, already layered (from generate_classes_css)

type string

options

output options

default {}

returns

string

combined CSS string

generate_classes
#

css_class_generators.ts view source

<T1 = string, T2 = string, T3 = string>(template: ClassTemplateFn<T1, T2, T3>, values: Iterable<T1>, secondary?: Iterable<T2> | undefined, tertiary?: Iterable<...> | undefined): Record<...> import {generate_classes} from '@fuzdev/fuz_css/css_class_generators.js';

Generates CSS class declarations from templates. Supports up to 3 dimensions of multiplicative combinations.

template

function that generates CSS from values, can return null to skip

values

primary iterable of values

type Iterable<T1, any, any>

secondary?

optional second dimension (makes it multiplicative)

type Iterable<T2, any, any>
optional

tertiary?

optional third dimension for even more combinations

type Iterable<T3, any, any>
optional

returns

Record<string, CssClassDefinition>

generics

generate_classes<T1 = string, T2 = string, T3 = string>
T1
default string
T2
default string
T3
default string

examples

// Simple list generate_classes( v => ({ name: `position_${v}`, css: `position: ${v};` }), ['static', 'relative', 'absolute'] )
// Two dimensions (multiplicative) generate_classes( (dir, size) => ({ name: `m${dir}_${size}`, css: `margin-${dir}: ${size};` }), ['top', 'bottom'], ['0', '1px', '2px'] )

generate_classes_css
#

css_class_generation.ts view source

(options: GenerateClassesCssOptions): GenerateClassesCssResult import {generate_classes_css} from '@fuzdev/fuz_css/css_class_generation.js';

Generates the utility CSS for a set of class names, wrapped in the fuz.utilities cascade layer.

Each class resolves to a structured rule - a definition plus the modifiers stripped from its name - and the emitted order comes from that structure, not from what the names say: composites render in the fuz.utilities.composites sublayer beneath every single-purpose class, and within each tier rules sort by color scheme, then media query (compare_media_modifiers), then property rank (shorthands before longhands, to_property_rank; definition order for composites), then state order (LVFHA), then the late flag (a late class after the rules it ties with), then registry order (interpreted classes after static ones), and only then by name, between interpreted classes of equal rank. Rules sharing a color scheme and media query render in one block. dark: and light: add no specificity (:where()), so they win by that order, and follow the OS preference when the root names no scheme (render_color_scheme_rules).

options

returns

GenerateClassesCssResult

generate_css
#

generate_css.ts view source

(options: GenerateCssOptions): GenerateCssResult import {generate_css} from '@fuzdev/fuz_css/generate_css.js';

Runs the full CSS-generation pipeline: utility classes via generate_classes_css, then - when base or theme output is enabled and bundled resources are available - base styles and theme variables via resolve_css + generate_bundled_css. Returns the combined CSS and every diagnostic produced along the way.

options

returns

GenerateCssResult

generate_declaration
#

css_literal.ts view source

(parsed: ParsedCssLiteral): string import {generate_declaration} from '@fuzdev/fuz_css/css_literal.js';

Generates the CSS declaration for a parsed CSS-literal class.

parsed

returns

string

generate_directional_classes
#

css_class_generators.ts view source

(property: string, values: Iterable<string>, formatter?: ((v: string) => string) | undefined): Record<string, CssClassDefinition> import {generate_directional_classes} from '@fuzdev/fuz_css/css_class_generators.js';

Generate directional classes for properties like margin and padding. Creates classes for all directions: base, top, right, bottom, left, x (horizontal), y (vertical).

property

the base CSS property name (e.g. 'margin', 'padding')

type string

values

the values to generate classes for

type Iterable<string, any, any>

formatter?

optional function to format values (defaults to identity)

type (v: string) => string
optional

returns

Record<string, CssClassDefinition>

generate_property_classes
#

css_class_generators.ts view source

(property: string, values: Iterable<string>, formatter?: ((value: string) => string) | undefined, prefix?: string): Record<string, CssClassDefinition> import {generate_property_classes} from '@fuzdev/fuz_css/css_class_generators.js';

Generate classes for a single CSS property with various values.

property

the CSS property name (e.g. 'font-size', 'gap')

type string

values

the values to generate classes for

type Iterable<string, any, any>

formatter?

optional function to format values (e.g. v => var(--space_${v}))

type (value: string) => string
optional

prefix

optional class name prefix (defaults to property with dashes replaced by underscores)

type string
default format_variable_name(property)

returns

Record<string, CssClassDefinition>

generate_shadow_classes
#

css_class_generators.ts view source

(sizes: Iterable<string>, alpha_mapping: Record<string, string>): Record<string, CssClassDefinition> import {generate_shadow_classes} from '@fuzdev/fuz_css/css_class_generators.js';

Generate shadow classes for various shadow types and sizes. Creates classes for regular, top, bottom, inset, inset-top, and inset-bottom shadows. Each shadow uses color-mix with alpha values for transparency.

sizes

the shadow size variants (xs, sm, md, lg, xl)

type Iterable<string, any, any>

alpha_mapping

mapping of sizes to alpha numbers (1-5)

type Record<string, string>

returns

Record<string, CssClassDefinition>

generate_theme_css
#

variable_graph.ts view source

(graph: VariableDependencyGraph, resolved_variables: Set<string>): { root_css: string; dark_css: string; } import {generate_theme_css} from '@fuzdev/fuz_css/variable_graph.js';

Generates theme CSS for the resolved variables.

graph

the variable dependency graph

resolved_variables

set of variable names to include

type Set<string>

returns

{ root_css: string; dark_css: string; }

object with the :root block as root_css and the dark-scheme rules as dark_css

GenerateBundledCssOptions
#

css_bundled_resolution.ts view source

GenerateBundledCssOptions import type {GenerateBundledCssOptions} from '@fuzdev/fuz_css/css_bundled_resolution.js';

Options for bundled CSS output generation.

include_theme?

Include theme variables section.

type boolean

default true

include_base?

Include base styles section.

type boolean

default true

theme_overlay_css?

A baked theme's own overlay (its variables + stance mirror + color-scheme pin), rendered unlayered - emitted into the FUZ_BAKED_THEME_LAYER sublayer so it outranks the fuz.preferences OS mappings like the runtime renderer's output does, and loses to it.

type string | null

GenerateClassesCssOptions
#

css_class_generation.ts view source

GenerateClassesCssOptions import type {GenerateClassesCssOptions} from '@fuzdev/fuz_css/css_class_generation.js';

class_names

type Iterable<string, any, any>

class_definitions

type Record<string, CssClassDefinition | undefined>

interpreters

type CssClassDefinitionInterpreter[]

css_properties

Valid CSS properties for literal validation, or null to skip validation

type Set<string> | null

log?

type Logger

class_locations?

type Map<string, SourceLocation[] | null>

explicit_classes?

Classes that were explicitly annotated (via @fuz-classes or additional_classes). An explicit class that no definition or interpreter resolves is an error, unless is_base_style_class claims it.

type Set<string> | null

is_base_style_class?

Whether the bundled base styles target a class, so an explicit class with no utility definition still resolves - its base rules ship instead. Null when no base styles are bundled (utility-only mode or base_css: null), where such a class errors.

type ((class_name: string) => boolean) | null

GenerateClassesCssResult
#

css_class_generation.ts view source

GenerateClassesCssResult import type {GenerateClassesCssResult} from '@fuzdev/fuz_css/css_class_generation.js';

Result from CSS class generation.

css

type string

diagnostics

type GenerationDiagnostic[]

variables_used

CSS variables used by the generated classes (without -- prefix)

type Set<string>

GenerateCssOptions
#

generate_css.ts view source

GenerateCssOptions import type {GenerateCssOptions} from '@fuzdev/fuz_css/generate_css.js';

Inputs to generate_css. The first group mirrors the shape returned by CssClasses.get_all() plus its diagnostics, so callers can forward it directly.

all_classes

All detected class names, already exclude-filtered.

type Set<string>

all_classes_with_locations

Source locations per class, for diagnostics.

type Map<string, SourceLocation[] | null>

explicit_classes

Classes from @fuz-classes/additional_classes; unresolved ones error.

type Set<string> | null

all_elements

All detected HTML element names.

type Set<string>

explicit_elements

Elements from @fuz-elements; unresolved ones error.

type Set<string> | null

explicit_variables

Variables from @fuz-variables; unresolved ones error.

type Set<string> | null

extraction_diagnostics

Diagnostics accumulated during extraction.

type Diagnostic[]

detected_css_variables

The var(--*) names referenced in source, unfiltered: names the theme doesn't define are ignored, since they may be the project's own. @fuz-variables are merged in here automatically.

type Iterable<string, any, any>

class_definitions

type Record<string, CssClassDefinition | undefined>

interpreters

type CssClassDefinitionInterpreter[]

css_properties

Valid CSS properties for literal validation, or null to skip.

type Set<string> | null

include_base

type boolean

include_theme

type boolean

theme?

The configured theme option, if any, carried so the footgun guard can flag a theme silently discarded by variables: null. The theme itself was already baked into resources' variable graph, which carries it with its derived mirror and caps, and that baked theme is what re-renders into the fuz.theme cascade layer (above the fuz.preferences OS mappings, with a stance's color-scheme pin), matching how the same theme behaves at runtime.

type Theme | ResolvedTheme | null

resources

Bundled resources, or null for utility-only mode.

type BundledCssResources | null

additional_elements?

type Iterable<string, any, any> | "all"

additional_variables?

type Iterable<string, any, any> | "all"

exclude_elements?

type Iterable<string, any, any>

exclude_variables?

type Iterable<string, any, any>

log?

Optional logger, passed to the class interpreters.

type Logger

GenerateCssResult
#

generate_css.ts view source

GenerateCssResult import type {GenerateCssResult} from '@fuzdev/fuz_css/generate_css.js';

css

Final CSS without banner comments - callers add their own.

type string

diagnostics

Extraction + generation + resolution diagnostics, unfiltered.

type Diagnostic[]

GeneratedClassResult
#

css_class_generators.ts view source

GeneratedClassResult

type { name: string; css: string; } | null

import type {GeneratedClassResult} from '@fuzdev/fuz_css/css_class_generators.js';

GenerationDiagnostic
#

diagnostics.ts view source

GenerationDiagnostic import type {GenerationDiagnostic} from '@fuzdev/fuz_css/diagnostics.js';

Diagnostic from the generation phase.

phase

type "generation"

level

type "error" | "warning"

message

type string

suggestion

type string | null

identifier

The class name, element name, or variable name this diagnostic refers to

type string

locations

Source locations where this class was used, or null if from additional_classes

type SourceLocation[] | null

get_all_modifier_names
#

modifiers.ts view source

(): string[] import {get_all_modifier_names} from '@fuzdev/fuz_css/modifiers.js';

Gets all modifier names for error message suggestions.

returns

string[]

get_all_variable_names
#

variable_graph.ts view source

(graph: VariableDependencyGraph): Set<string> import {get_all_variable_names} from '@fuzdev/fuz_css/variable_graph.js';

Gets all variable names from the graph.

graph

the variable dependency graph

returns

Set<string>

set of all variable names in the graph

get_cache_path
#

css_cache.ts view source

internal

The inside-the-root case of `get_file_cache_path`.

(source_path: string, cache_dir: string, project_root: string): string import {get_cache_path} from '@fuzdev/fuz_css/css_cache.js';

Computes the cache file path for a source file. Cache structure mirrors source tree: src/lib/Foo.svelte โ†’ .fuz/cache/css/src/lib/Foo.svelte.json

source_path

absolute path to the source file

type string

cache_dir

absolute path to the cache directory

type string

project_root

normalized project root (must end with /)

type string

returns

string

get_file_cache_path
#

css_cache.ts view source

(file_id: string, cache_dir: string, project_root: string): string import {get_file_cache_path} from '@fuzdev/fuz_css/css_cache.js';

Computes cache path for a file, handling both internal and external paths. Internal files use relative paths mirroring source tree. External files (outside project root) use hashed absolute paths in _external/.

file_id

absolute path to the source file

type string

cache_dir

absolute path to the cache directory

type string

project_root

normalized project root (must end with /)

type string

returns

string

get_matching_rules
#

style_rule_parser.ts view source

(index: StyleRuleIndex, detected_elements: Set<string>, detected_classes: Set<string>): Set<number> import {get_matching_rules} from '@fuzdev/fuz_css/style_rule_parser.js';

Gets rules that should be included based on detected elements and classes.

index

the StyleRuleIndex to query

detected_elements

set of HTML element names found in source

type Set<string>

detected_classes

set of CSS class names found in source

type Set<string>

returns

Set<number>

set of rule indices to include

get_modifier
#

modifiers.ts view source

(segment: string): (ModifierDefinition & { is_arbitrary?: boolean | undefined; }) | null import {get_modifier} from '@fuzdev/fuz_css/modifiers.js';

Gets the modifier definition for a segment. Handles both static modifiers and dynamic patterns (arbitrary breakpoints, parameterized states).

segment

type string

returns

(ModifierDefinition & { is_arbitrary?: boolean | undefined; }) | null

the modifier definition or null if not a known modifier

guestbook_theme
#

themes/guestbook.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {guestbook_theme} from '@fuzdev/fuz_css/themes/guestbook.js';

An exemplar theme: the guestbook of a 90s homepage. Structure comes from controls drawn as objects - sunken fields under raised buttons that press to inset, the bevel doing the work shadows do elsewhere. Colorless system chrome on a ground that sits off the paper-white extreme, one serif family for everything the way the browser default was, square corners, packed dense, and links underlined at rest. Sits between ledger's compact and phosphor's terminal density.

The proof that --button_border_style/--button_border_style_active express a raised/pressed pair. Dual-scheme: by night the same chrome in slate, the hi-color desktop after dark. Built from levers only - the palette letters keep their default hues, and nothing is pushed past the gamut caps.

has_extracted_modifiers
#

css_literal.ts view source

(modifiers: ExtractedModifiers): boolean import {has_extracted_modifiers} from '@fuzdev/fuz_css/css_literal.js';

Checks if extracted modifiers contain any modifier. Useful for tooling that needs to detect modified classes.

modifiers

returns

boolean

has_extraction_data
#

css_class_extractor.ts view source

(data: ExtractionData): boolean import {has_extraction_data} from '@fuzdev/fuz_css/css_class_extractor.js';

Returns true if the extraction data has any non-null fields.

data

returns

boolean

has_modifiers
#

css_literal.ts view source

(parsed: ParsedCssLiteral): boolean import {has_modifiers} from '@fuzdev/fuz_css/css_literal.js';

Checks if a parsed CSS literal has any modifiers.

parsed

returns

boolean

high_contrast_theme
#

themes/high_contrast.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {high_contrast_theme} from '@fuzdev/fuz_css/themes/high_contrast.js';

Stretched contrast: a pure white page background in light mode and a deepened one in dark, text bent toward the contrast end - curve-knob moves, not stop surgery - darker links, and stronger borders.

The dark ground stops short of pure black because the bottom of the lightness range carries almost no luminance: going to black buys text a sliver of contrast while collapsing the surface steps and weakening borders. The text bend is moderate for a similar reason - the stretched ground already takes body text past AAA, and a harder bend lifts disabled and subtle text to nearly body contrast, flattening the hierarchy those stops encode.

On the white ground an input's sunken fill has nowhere to go, so the border alone marks a control, and it moves up the shade ramp to stay past 3:1 against the page. Panels get a ring in that border color, since their faint fill reads as nothing beside the louder text and borders - which replaces a theme's own panel_shadow while the modifier holds.

HUE_BINDING_MATCHER
#

knobs.ts view source

RegExp import {HUE_BINDING_MATCHER} from '@fuzdev/fuz_css/knobs.js';

Matches a var(--hue_X) palette-letter binding, capturing the letter - the value form bindable hue knobs default to. It accepts the whitespace the theme checks do when they follow a binding, so a value the gates read as bound to a letter reads that way here too.

icon_size_variants
#

variable_data.ts view source

readonly ["xs", "sm", "md", "lg", "xl", "xl2", "xl3"] import {icon_size_variants} from '@fuzdev/fuz_css/variable_data.js';

ICON_SIZES
#

variable_data.ts view source

Readonly<Record<"lg" | "md" | "sm" | "xs" | "xl" | "xl2" | "xl3", number>>

type Readonly<Record<IconSizeVariant, number>>

import {ICON_SIZES} from '@fuzdev/fuz_css/variable_data.js';

Icon sizes in px, stepping up by roughly the golden ratio and rounded to the nearest pixel. Deliberately insensitive to font size, hence px rather than rem.

IconSizeVariant
#

variable_data.ts view source

"lg" | "md" | "sm" | "xs" | "xl" | "xl2" | "xl3"

type "lg" | "md" | "sm" | "xs" | "xl" | "xl2" | "xl3"

import type {IconSizeVariant} from '@fuzdev/fuz_css/variable_data.js';

intensity_variants
#

variable_data.ts view source

readonly ["00", "05", "10", "20", "30", "40", "50", "60", "70", "80", "90", "95", "100"] import {intensity_variants} from '@fuzdev/fuz_css/variable_data.js';

IntensityVariant
#

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.

intent_variants
#

variable_data.ts view source

readonly ["accent", "positive", "negative", "caution", "info"] import {intent_variants} from '@fuzdev/fuz_css/variable_data.js';

IntentVariant
#

variable_data.ts view source

"accent" | "positive" | "negative" | "caution" | "info"

type "accent" | "positive" | "negative" | "caution" | "info"

import type {IntentVariant} from '@fuzdev/fuz_css/variable_data.js';

The semantic color intents that derive full scales through the shared ramps. The neutral is also an intent (--hue_neutral) but is absent here because its scales are shade_* and text_* rather than a neutral_00 through neutral_100 family.

INTERNAL_VARIABLE_NAME_MATCHER
#

variable.ts view source

RegExp import {INTERNAL_VARIABLE_NAME_MATCHER} from '@fuzdev/fuz_css/variable.js';

Matches an internal variable name: a leading underscore before a public name, the private spelling of the ramp intermediates (_palette_lightness_30, _chroma_shape_50, _palette_chroma_50). default_variables declares them and the renderer emits them, but they're plumbing rather than API, so STYLE_VARIABLE_NAME_MATCHER rejects the spelling and a theme can't set one.

InterpreterDiagnostic
#

diagnostics.ts view source

InterpreterDiagnostic import type {InterpreterDiagnostic} from '@fuzdev/fuz_css/diagnostics.js';

Diagnostic from CSS class interpretation. Used internally by interpreters; converted to GenerationDiagnostic with locations.

level

type "error" | "warning"

message

type string

identifier

The class name, element name, or variable name this diagnostic refers to

type string

suggestion

type string | null

is_ci
#

css_cache.ts view source

internal

Read by the generator for its cache and `on_error` defaults.

boolean import {is_ci} from '@fuzdev/fuz_css/css_cache.js';

Whether this is a CI run, per parse_ci_value on process.env.CI: there's no point writing a cache the next run won't reuse.

is_css_file
#

file_filter.ts view source

(path: string): boolean import {is_css_file} from '@fuzdev/fuz_css/file_filter.js';

Whether a file is CSS, which is scanned for the var(--*) references it makes but has no classes or elements to extract.

path

a file id or path

type string

returns

boolean

is_neutral_ground
#

ramps.ts view source

(family: "text" | "shade", stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): boolean import {is_neutral_ground} from '@fuzdev/fuz_css/ramps.js';

Whether a neutral stop is the page ground - the one stop --shade_chroma_00 tints, shared by the emitter and both numeric twins.

family

type "text" | "shade"

stop

returns

boolean

is_possible_css_literal
#

css_literal.ts view source

(class_name: string): boolean import {is_possible_css_literal} from '@fuzdev/fuz_css/css_literal.js';

Checks if a class name could be a CSS-literal class. Quick check before attempting full parse.

class_name

the class name to check

type string

returns

boolean

true if it could be CSS-literal syntax

is_single_selector_ruleset
#

css_ruleset_parser.ts view source

(rules: ParsedRule[], escaped_class_name: string): boolean import {is_single_selector_ruleset} from '@fuzdev/fuz_css/css_ruleset_parser.js';

Checks if a ruleset has only a single simple selector (just the class name). Used to detect rulesets that could be converted to declaration format.

rules

parsed rules from the ruleset

type ParsedRule[]

escaped_class_name

the CSS-escaped class name (e.g., "box" or "hover\\:card")

type string

returns

boolean

true if there's exactly one rule with selector ".class_name"

is_valid_css_property
#

css_literal.ts view source

(property: string, properties: Set<string> | null): boolean import {is_valid_css_property} from '@fuzdev/fuz_css/css_literal.js';

Checks if a property name is a valid CSS property. The name renders verbatim, so a custom property (--*) is valid when its name is a plain identifier (css_custom_property_name_is_contained), and with no property set to check against, any other name must be a plain identifier too.

property

the CSS property name to validate

type string

properties

Set of valid CSS properties from load_css_properties() Pass null to skip validation against the set.

type Set<string> | null

returns

boolean

true if valid CSS property or custom property

KnobAxis
#

knobs.ts view source

KnobAxis

type "color" | "shape" | "density" | "depth" | "typography" | "motion" | "decoration"

import type {KnobAxis} from '@fuzdev/fuz_css/knobs.js';

The axis of the theme-space taxonomy a knob moves.

KnobKind
#

knobs.ts view source

KnobKind

type "hue" | "number" | "percent" | "length" | "time" | "color" | "font_stack" | "enum" | "shadow" | "text"

import type {KnobKind} from '@fuzdev/fuz_css/knobs.js';

The value kind of a knob, determining the editor widget and how the value validates. text is the unenriched fallback kind.

KnobLeverage
#

knobs.ts view source

KnobLeverage

type "lg" | "md" | "sm"

import type {KnobLeverage} from '@fuzdev/fuz_css/knobs.js';

Leverage tier: how much of the system a knob reshapes, which the editor renders as control size through the matching sized_* composite (lg headline knobs down to sm escape hatches).

KnobTier
#

knobs.ts view source

KnobTier

type "semantic" | "palette"

import type {KnobTier} from '@fuzdev/fuz_css/knobs.js';

The two-tier theme policy: semantic-tier knobs (intent bindings + levers) are safe for registry themes; palette-tier knobs (the letter hues) mark a theme as an exemplar.

known_theme_variable_names
#

theme_validate.ts view source

ReadonlySet<string>

type ReadonlySet<string>

import {known_theme_variable_names} from '@fuzdev/fuz_css/theme_validate.js';

The variable names a theme may set: the declared defaults plus the hook knobs style.css consumes through var() fallbacks, leaving out the internal ramp intermediates (INTERNAL_VARIABLE_NAME_MATCHER). The authoring-side companion to validate_theme, for tooling that completes or checks names before a theme is assembled.

ledger_theme
#

themes/ledger.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {ledger_theme} from '@fuzdev/fuz_css/themes/ledger.js';

The working theme: the ledger. For tools used all day - a cool gray whisper in the neutral, color eased down so status reads without shouting, compact spacing and leading (visibly tighter than the base, so the registry's two entries read as two choices), one sans family, a flatter type scale, and restrained corners and depth. Plain on purpose: no decoration, no clipped gamut, the default accent.

Dual-scheme and semantic-tier - it moves levers only, so the palette letters keep their hues and it sits in the registry beside the base theme.

LIGHTNESS_KNOBS
#

ramps.ts view source

Readonly<Record<RampFamily, Readonly<Record<"dark" | "light", Readonly<LightnessRampKnobs>>>>>

type Readonly<Record<RampFamily, Readonly<Record<ColorSchemeVariant, Readonly<LightnessRampKnobs>>>>>

import {LIGHTNESS_KNOBS} from '@fuzdev/fuz_css/ramps.js';

The lightness ramp knobs by family, for lookups keyed on a RampFamily.

LightnessRampKnobs
#

ramps.ts view source

LightnessRampKnobs import type {LightnessRampKnobs} from '@fuzdev/fuz_css/ramps.js';

Knobs for a pow-curve lightness ramp. The endpoints are the ramp's own 00/100 stops, so light and dark schemes differ only in values, never in formula - no direction flag needed.

lightness_00

OKLCH lightness at stop 00, in [0, 1].

type number

lightness_100

OKLCH lightness at stop 100, in [0, 1].

type number

curve

Exponent bending the ramp between the endpoints; 1 is linear.

type number

line_height_names
#

line_height_variants
#

variable_data.ts view source

readonly ["xs", "sm", "md", "lg", "xl"] import {line_height_variants} from '@fuzdev/fuz_css/variable_data.js';

LINE_HEIGHTS
#

variable_data.ts view source

Readonly<Record<"lg" | "md" | "sm" | "xs" | "xl", number>>

type Readonly<Record<LineHeightVariant, number>>

import {LINE_HEIGHTS} from '@fuzdev/fuz_css/variable_data.js';

Line heights, unitless so they scale with the font size.

LineHeightVariant
#

variable_data.ts view source

"lg" | "md" | "sm" | "xs" | "xl"

type "lg" | "md" | "sm" | "xs" | "xl"

import type {LineHeightVariant} from '@fuzdev/fuz_css/variable_data.js';

LiteralResolutionResult
#

css_literal.ts view source

LiteralResolutionResult

type { ok: true; declaration: string; warnings: InterpreterDiagnostic[] | null; } | { ok: false; error: InterpreterDiagnostic | null; }

import type {LiteralResolutionResult} from '@fuzdev/fuz_css/css_literal.js';

Result of attempting to resolve a CSS literal for composition.

load_cached_extraction
#

css_cache.ts view source

(deps: CacheDeps, cache_path: string): Promise<CachedExtraction | null> import {load_cached_extraction} from '@fuzdev/fuz_css/css_cache.js';

Loads a cached extraction result from disk. Returns null if the cache is missing, corrupted, or was written by other versions of fuz_css or its parsers (to_cache_version). This makes the cache self-healing: any error triggers re-extraction.

deps

filesystem deps for dependency injection

cache_path

absolute path to the cache file

type string

returns

Promise<CachedExtraction | null>

load_css_properties
#

css_literal.ts view source

(): Promise<Set<string>> import {load_css_properties} from '@fuzdev/fuz_css/css_literal.js';

Loads CSS properties from @webref/css. Returns a fresh Set each time - callers should cache the result if needed.

returns

Promise<Set<string>>

load_default_style_css
#

style_rule_parser.ts view source

(deps: CacheDeps): Promise<string> import {load_default_style_css} from '@fuzdev/fuz_css/style_rule_parser.js';

Loads the raw content of the package's default style.css.

deps

filesystem deps for dependency injection

returns

Promise<string>

promise resolving to the CSS string

load_extraction_versions
#

css_cache.ts view source

internal

Read by the cache for `to_cache_version`.

(): Record<string, string> import {load_extraction_versions} from '@fuzdev/fuz_css/css_cache.js';

Reads the installed versions of fuz_css and its parsers, once per process. A version that can't be found reads as 'unknown', which still keys the cache - it never fails generation.

returns

Record<string, string>

the versions by package name

load_style_rule_index
#

logicalClass
#

low_contrast_theme
#

themes/low_contrast.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {low_contrast_theme} from '@fuzdev/fuz_css/themes/low_contrast.js';

Gentle contrast: a compressed surface range, tuned to the softest compression that still clears the check_theme text, link, border, and fill gates over the base theme. Composed over a theme with a tighter ground it can dip below a gate, so check the composition.

It moves the ground and nothing else, so a theme keeps its own neutral cast under it.

marquee_theme
#

themes/marquee.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {marquee_theme} from '@fuzdev/fuz_css/themes/marquee.js';

An exemplar theme: the theater marquee at night. Color is the content - a magenta accent over a deep purple-cast dark, shadows turned to cyan and magenta glows, corners rounded onto a common floor like tube bends. Vivid past the gamut caps on purpose - lightness holds through the clipping, so check_theme reports gamut failures and baking it through the build-time theme option warns with them. Dark-only via the scheme stance: a lit sign has no daytime appearance, so it renders through resolve_theme_stance, which computes the stance mirror beside it.

The one palette-tier exemplar: it rotates the yellow slot to the amber of incandescent bulbs, so a letter hue itself moves - the move that keeps a theme out of the semantic-tier registry.

MEDIA_MODIFIERS
#

ModifiedRulesetResult
#

css_ruleset_parser.ts view source

ModifiedRulesetResult import type {ModifiedRulesetResult} from '@fuzdev/fuz_css/css_ruleset_parser.js';

Result from modifying a ruleset's rules for a modified class.

Uses | null for skipped_modifiers to avoid allocating empty arrays. Callers should use a guard pattern: if (result.skipped_modifiers) { ... }

rules

Each rule with its selector list rewritten, in source order.

type { selector: string; declarations: string; }[]

skipped_modifiers

Information about modifiers that were skipped for certain rules, or null if none

type SkippedModifierInfo[] | null

ModifiedSelectorGroupResult
#

css_ruleset_parser.ts view source

ModifiedSelectorGroupResult import type {ModifiedSelectorGroupResult} from '@fuzdev/fuz_css/css_ruleset_parser.js';

Result from modifying a selector group with conflict detection.

Uses | null for skipped_modifiers to avoid allocating empty arrays. Callers should use a guard pattern: if (result.skipped_modifiers) { ... }

selector

The modified selector list as a string

type string

skipped_modifiers

Information about modifiers skipped for specific selectors, or null if none

type SkippedModifierInfo[] | null

ModifierDefinition
#

modifiers.ts view source

ModifierDefinition import type {ModifierDefinition} from '@fuzdev/fuz_css/modifiers.js';

Definition for a single modifier.

name

The prefix used in class names (e.g., 'hover', 'md', 'dark')

type string

type

Type determines position in modifier order and CSS output behavior

type ModifierType

css

The CSS the modifier contributes: the media condition for media ((width >= 48rem), print), the selector suffix for state and pseudo-element (:hover, ::before), and the color scheme for ancestor (dark).

type string

width?

The width bound of a breakpoint media modifier.

type ModifierWidthBound

order?

Cascade order among state modifiers (LVFHA), emitted ascending.

type number

ModifierExtractionResult
#

css_literal.ts view source

ModifierExtractionResult

type { ok: true; modifiers: ExtractedModifiers; remaining: string[]; } | { ok: false; error: InterpreterDiagnostic; }

import type {ModifierExtractionResult} from '@fuzdev/fuz_css/css_literal.js';

Result of extracting modifiers from segments.

MODIFIERS
#

modifiers.ts view source

ModifierDefinition[]

type ModifierDefinition[]

import {MODIFIERS} from '@fuzdev/fuz_css/modifiers.js';

All modifier definitions in a single declarative structure. Adding a new modifier requires only adding to this array.

ModifierType
#

modifiers.ts view source

ModifierType

type "media" | "ancestor" | "state" | "pseudo-element"

import type {ModifierType} from '@fuzdev/fuz_css/modifiers.js';

Type of modifier determining its position in the class name and CSS output.

Order in class names: [media:][ancestor:][state...:][pseudo-element:]property:value

ModifierWidthBound
#

modifiers.ts view source

ModifierWidthBound import type {ModifierWidthBound} from '@fuzdev/fuz_css/modifiers.js';

A media modifier's viewport width bound. Width bounds order the emitted rules: min ascending, then max descending, so the narrower range wins where two overlap.

bound

type "min" | "max"

value

A CSS length, or a function like calc() (ordered after plain lengths).

type string

modify_ruleset
#

css_ruleset_parser.ts view source

(ruleset: string, original_class: string, new_class_escaped: string, states_to_add: string[], pseudo_element_css: string): ModifiedRulesetResult import {modify_ruleset} from '@fuzdev/fuz_css/css_ruleset_parser.js';

Rewrites a ruleset's rules for a modified class: renames the base class and appends the state and pseudo-element modifiers to each selector, skipping per selector any it already carries. At-rules in the ruleset are flattened to their rules; media and color-scheme wrappers are the generator's.

ruleset

the original CSS ruleset string

type string

original_class

the base class name

type string

new_class_escaped

the escaped new class name with modifiers

type string

states_to_add

individual state modifiers (e.g., [":hover", ":focus"])

type string[]

pseudo_element_css

pseudo-element modifier CSS (e.g., "::before"), or ''

type string

returns

ModifiedRulesetResult

modify_selector_group
#

css_ruleset_parser.ts view source

(selector_group: string, original_class: string, new_class_escaped: string, states_to_add: string[], pseudo_element_css: string): ModifiedSelectorGroupResult import {modify_selector_group} from '@fuzdev/fuz_css/css_ruleset_parser.js';

Modifies a selector list (comma-separated selectors) to add modifiers. Handles conflicts per-selector: if one selector in a list has a conflict, only that selector skips the modifier; other selectors still get it.

selector_group

CSS selector list (may contain commas)

type string

original_class

the base class name

type string

new_class_escaped

the escaped new class name

type string

states_to_add

individual state modifiers (e.g., [":hover", ":focus"])

type string[]

pseudo_element_css

pseudo-element modifier CSS to insert (e.g., "::before")

type string

returns

ModifiedSelectorGroupResult

result with modified selector list and information about skipped modifiers

modify_single_selector
#

css_ruleset_parser.ts view source

(selector: string, original_class: string, new_class_escaped: string, state_css: string, pseudo_element_css: string): string import {modify_single_selector} from '@fuzdev/fuz_css/css_ruleset_parser.js';

Modifies a single CSS selector to add modifiers.

selector

a single CSS selector (not a selector list)

type string

original_class

the base class name (e.g., "menuitem")

type string

new_class_escaped

the escaped new class name (e.g., "hover\\:menuitem")

type string

state_css

state modifier CSS to insert (e.g., ":hover")

type string

pseudo_element_css

pseudo-element modifier CSS to insert (e.g., "::before")

type string

returns

string

modified selector

examples

modify_single_selector('.menuitem', 'menuitem', 'hover\\:menuitem', ':hover', '') // โ†’ '.hover\\:menuitem:hover' modify_single_selector('.menuitem .icon', 'menuitem', 'hover\\:menuitem', ':hover', '') // โ†’ '.hover\\:menuitem:hover .icon' modify_single_selector('.menuitem.selected', 'menuitem', 'hover\\:menuitem', ':hover', '') // โ†’ '.hover\\:menuitem.selected:hover'

NEUTRAL_CHROMA
#

ramps.ts view source

Readonly<Record<"dark" | "light", number>>

type Readonly<Record<ColorSchemeVariant, number>>

import {NEUTRAL_CHROMA} from '@fuzdev/fuz_css/ramps.js';

Peak chroma of the neutral (shade/text) scales. The neutral rides the palette's chroma shape scaled to this peak: strong tint at mid lightness, nearly untinted near white and black.

neutral_color_oklch
#

ramps.ts view source

(lightness: number, neutral_chroma: number, chroma_shape: number, hue: number, ground_chroma?: number): Oklch import {neutral_color_oklch} from '@fuzdev/fuz_css/ramps.js';

Combines resolved neutral-scale inputs into a shade/text stop's OKLCH: the peak neutral_chroma scaled by the shared chroma shape, plus the ground's own chroma for shade_00 (ground_chroma, 0 elsewhere). The neutral twin of ramp_color_oklch, shared with check_theme for the same reason.

lightness

type number

neutral_chroma

type number

chroma_shape

type number

hue

type number

ground_chroma

type number
default 0

returns

Oklch

NonCoreStyleRule
#

style_rule_parser.ts view source

NonCoreStyleRule import type {NonCoreStyleRule} from '@fuzdev/fuz_css/style_rule_parser.js';

A non-core style rule included only when its elements/classes are detected.

inheritance

extends: StyleRuleBase

is_core

type false

core_reason

type null

NTH_CHILD_PATTERN
#

modifiers.ts view source

internal

Read by `get_modifier`; exported for its tests.

RegExp import {NTH_CHILD_PATTERN} from '@fuzdev/fuz_css/modifiers.js';

Pattern for parameterized nth-child: nth-child(2n+1):

NTH_LAST_CHILD_PATTERN
#

modifiers.ts view source

internal

Read by `get_modifier`; exported for its tests.

RegExp import {NTH_LAST_CHILD_PATTERN} from '@fuzdev/fuz_css/modifiers.js';

Pattern for parameterized nth-last-child: nth-last-child(2n+1):

NTH_LAST_OF_TYPE_PATTERN
#

modifiers.ts view source

internal

Read by `get_modifier`; exported for its tests.

RegExp import {NTH_LAST_OF_TYPE_PATTERN} from '@fuzdev/fuz_css/modifiers.js';

Pattern for parameterized nth-last-of-type: nth-last-of-type(2n):

NTH_OF_TYPE_PATTERN
#

modifiers.ts view source

internal

Read by `get_modifier`; exported for its tests.

RegExp import {NTH_OF_TYPE_PATTERN} from '@fuzdev/fuz_css/modifiers.js';

Pattern for parameterized nth-of-type: nth-of-type(2n):

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.

numeric_scale_variants
#

variable_data.ts view source

readonly ["00", "05", "10", "20", "30", "40", "50", "60", "70", "80", "90", "95", "100"] import {numeric_scale_variants} from '@fuzdev/fuz_css/variable_data.js';

numeric_scale_with_extremes
#

variable_data.ts view source

readonly ["min", "00", "05", "10", "20", "30", "40", "50", "60", "70", "80", "90", "95", "100", "max"] import {numeric_scale_with_extremes} from '@fuzdev/fuz_css/variable_data.js';

NumericScaleVariant
#

variable_data.ts view source

"00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

import type {NumericScaleVariant} from '@fuzdev/fuz_css/variable_data.js';

The standard numeric scale used across multiple variable families. Provides 13 steps from 00 (surface/subtle) to 100 (contrast/bold).

NumericScaleWithExtremesVariant
#

variable_data.ts view source

"00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100" | "min" | "max"

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100" | "min" | "max"

import type {NumericScaleWithExtremesVariant} from '@fuzdev/fuz_css/variable_data.js';

Numeric scale with min/max extremes for scales that need untinted endpoints. Used by text and shade scales where min/max represent pure black/white values.

objectClasses
#

example_class_utilities.ts view source

{ mt_xl2: string; mt_xl3: string; } import {objectClasses} from '@fuzdev/fuz_css/example_class_utilities.js';

Object - keys extracted as class names

outline_width_variants
#

OutlineWidthVariant
#

variable_data.ts view source

"focus" | "active"

type "focus" | "active"

import type {OutlineWidthVariant} from '@fuzdev/fuz_css/variable_data.js';

OVERLAY_ALPHAS
#

variable_data.ts view source

Readonly<Record<"00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", Readonly<{ hex: string; percent: string; }>>>

type Readonly<Record<NumericScaleVariant, Readonly<{ hex: string; percent: string; }>>>

import {OVERLAY_ALPHAS} from '@fuzdev/fuz_css/variable_data.js';

The perceptual alpha curve the darken_*/lighten_* overlays share: the hex alpha byte each stop renders with, and the percentage it works out to.

overlay_style_variable
#

theme.ts view source

(existing: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; } | undefined, overlay: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }): { ...; } import {overlay_style_variable} from '@fuzdev/fuz_css/theme.js';

Overlays one variable onto the same-named variable beneath it, the merge every theme composition shares: the overlay replaces wholesale, except that a dark-only overlay keeps the base slot beneath it. A dark slot only shadows in the dark scheme, so dropping the base slot would leave the variable without its light-scheme value.

existing

the variable being overlaid, if any

type StyleVariable | undefined

overlay

the variable that wins

returns

StyleVariable

PALETTE_CHROMA_CAPS
#

ramps.ts view source

Readonly<Record<"dark" | "light", Readonly<Record<"00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", number>>>>

type Readonly<Record<ColorSchemeVariant, Readonly<Record<NumericScaleVariant, number>>>>

import {PALETTE_CHROMA_CAPS} from '@fuzdev/fuz_css/ramps.js';

Worst-hue safe chroma caps per stop: the largest chroma at that stop's default lightness that stays inside sRGB for every default hue (see oklch_max_srgb_chroma for the non-convexity caveat). Computed at design time from PALETTE_HUES + PALETTE_LIGHTNESS_KNOBS, floored to stay conservative; a drift test recomputes them from the color math.

PALETTE_CHROMA_KNOBS
#

ramps.ts view source

Readonly<Record<"dark" | "light", Readonly<ChromaRampKnobs>>>

type Readonly<Record<ColorSchemeVariant, Readonly<ChromaRampKnobs>>>

import {PALETTE_CHROMA_KNOBS} from '@fuzdev/fuz_css/ramps.js';

Fitted chroma-curve knobs for the palette ramps. curve renders as the single --chroma_curve, which the neutral scales share; chroma_min and chroma_max are the palette's own.

Fitted so the requested curve hugs the effective post-clamp chroma instead of sitting above the caps through the mid-range - turning the knobs down responds immediately. Turning chroma_max up remains cap-clamped by design; --chroma_scale is the push-past-the-gamut knob. The residual vs the HSL palette this fit ports is small (mean ฮ”EOK โ‰ˆ 0.005 light / 0.003 dark) except light stop 30 (โˆ’0.028 C): the symmetric mid-peaked model can't reach the light cap envelope's peak there - recovering it would take an asymmetric shape (a peak-position knob).

PALETTE_CHROMA_MULTIPLIERS
#

ramps.ts view source

Readonly<Record<"a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j", number>>

type Readonly<Record<PaletteVariant, number>>

import {PALETTE_CHROMA_MULTIPLIERS} from '@fuzdev/fuz_css/ramps.js';

Per-slot chroma multipliers (--palette_X_chroma_scale), the palette's chroma-character knobs. Each multiplies its slot's chroma under the global --chroma_scale (multiplicative, so the slot's character is preserved at any global setting); values at or below 1 stay inside the worst-hue gamut caps by construction, above 1 knowingly clips like the global knob. The brown slot ships muted because brown is low-chroma dark orange - no hue angle renders it at full palette chroma.

palette_glosses
#

variable_data.ts view source

Record<"a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j", { color: string; binding?: "accent" | "positive" | "negative" | "caution" | "info" | "neutral" | undefined; }>

type Record<PaletteVariant, { color: string; binding?: "accent" | "positive" | "negative" | "caution" | "info" | "neutral" | undefined; }>

import {palette_glosses} from '@fuzdev/fuz_css/variable_data.js';

Letter glosses: each palette slot's default color plus its default intent binding where one exists. Display data for docs and the theme editor - themes recolor the slots, so these describe the defaults, not promises. The neutral binds like an intent (--hue_neutral: var(--hue_f)) despite being absent from intent_variants.

PALETTE_HUES
#

ramps.ts view source

Readonly<Record<"a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j", number>>

type Readonly<Record<PaletteVariant, number>>

import {PALETTE_HUES} from '@fuzdev/fuz_css/ramps.js';

OKLCH hue angles for the palette slots.

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.

PALETTE_LIGHTNESS_KNOBS
#

ramps.ts view source

Readonly<Record<"dark" | "light", Readonly<LightnessRampKnobs>>>

type Readonly<Record<ColorSchemeVariant, Readonly<LightnessRampKnobs>>>

import {PALETTE_LIGHTNESS_KNOBS} from '@fuzdev/fuz_css/ramps.js';

Fitted lightness knobs for the palette (palette_X_NN) ramps.

palette_stop_oklch
#

ramps.ts view source

(letter: "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j", stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", scheme: "dark" | "light"): Oklch import {palette_stop_oklch} from '@fuzdev/fuz_css/ramps.js';

Computes the default OKLCH color of a palette stop (--palette_X_NN).

letter

stop

scheme

returns

Oklch

palette_variants
#

variable_data.ts view source

readonly ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] import {palette_variants} from '@fuzdev/fuz_css/variable_data.js';

PaletteVariant
#

variable_data.ts view source

"a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j"

type "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j"

import type {PaletteVariant} from '@fuzdev/fuz_css/variable_data.js';

parchment_theme
#

themes/parchment.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {parchment_theme} from '@fuzdev/fuz_css/themes/parchment.js';

An exemplar theme: the manuscript page. Structure comes from type and ruling - serif body text on warm parchment surfaces (the neutral's default brown binding, tinted up), rubrication-red accents the way scribes marked emphasis, and double-ruled frames. Chroma eases below 1 for aged pigment, the page rather than its illumination.

Dual-scheme: the dark appearance is the same page by candlelight, the ground deepening to tanned leather and the ink warming to cream rather than white. The material reads in both, so it takes no scheme stance - a dark-mode reader who picks it isn't flashed a lit page.

parse_arbitrary_breakpoint
#

modifiers.ts view source

(segment: string): ModifierWidthBound | null import {parse_arbitrary_breakpoint} from '@fuzdev/fuz_css/modifiers.js';

Parses an arbitrary breakpoint modifier into its width bound. The value is a length or a calc(), clamp(), min(), or max() of lengths, with ~ for spaces; anything else isn't a breakpoint, since browsers drop a media query whose value isn't a length.

segment

type string

returns

ModifierWidthBound | null

the width bound, or null if not an arbitrary breakpoint

examples

parse_arbitrary_breakpoint("min-width(800px)") // {bound: 'min', value: '800px'} parse_arbitrary_breakpoint("max-width(calc(100vw~-~200px))") // {bound: 'max', value: 'calc(100vw - 200px)'} parse_arbitrary_breakpoint("min-width(px)") // null (invalid - no number) parse_arbitrary_breakpoint("min-width(800)") // null (invalid - no unit)

parse_ci_value
#

css_cache.ts view source

(value: string | undefined): boolean import {parse_ci_value} from '@fuzdev/fuz_css/css_cache.js';

Parses a CI environment variable value. Any value is CI except unset, empty, false, and 0 (case-insensitive, surrounding whitespace ignored), so CI=false turns CI behavior off rather than on.

value

the CI environment variable, if set

type string | undefined

returns

boolean

whether the value marks a CI run

parse_css_literal
#

css_literal.ts view source

(class_name: string, css_properties: Set<string> | null): CssLiteralParseResult import {parse_css_literal} from '@fuzdev/fuz_css/css_literal.js';

Parses a CSS-literal class name into its components.

The value renders verbatim, so one that could end its declaration or rule (an unclosed quote or bracket, a stray ), a top-level ;) is an error: it must pass css_value_is_contained once a trailing !important is split off. That check is stricter than the CSS grammar - it also rejects braces, comments, and escapes outside strings (--x:{}, content:\201C), any ! but that trailing one (display:flex!, color:red!important!important), and an unquoted url( holding what needs quotes - so quote such values or set them in a stylesheet. The property name renders verbatim too, so it must pass is_valid_css_property, which holds a custom property's name to a plain identifier.

class_name

the class name to parse

type string

css_properties

Set of valid CSS properties from load_css_properties() Pass null to skip property validation.

type Set<string> | null

returns

CssLiteralParseResult

CssLiteralParseResult with parsed data or error

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

parse_parameterized_state
#

modifiers.ts view source

(segment: string): { name: string; css: string; type: "state"; } | null import {parse_parameterized_state} from '@fuzdev/fuz_css/modifiers.js';

Parses a parameterized state modifier (nth-child, nth-last-child, nth-of-type, nth-last-of-type).

segment

type string

returns

{ name: string; css: string; type: "state"; } | null

object with name (including parameter) and CSS, or null if not parameterized

parse_ruleset
#

css_ruleset_parser.ts view source

(css: string): ParsedRuleset import {parse_ruleset} from '@fuzdev/fuz_css/css_ruleset_parser.js';

Parses a CSS ruleset string using Svelte's CSS parser.

css

raw CSS string (e.g., ".box { display: flex; }")

type string

returns

ParsedRuleset

ParsedRuleset with structured rule data and positions

parse_style_css
#

style_rule_parser.ts view source

(css: string): StyleRuleIndex import {parse_style_css} from '@fuzdev/fuz_css/style_rule_parser.js';

Parses a base stylesheet into a StyleRuleIndex.

Each top-level style rule and at-rule becomes one indexed rule that ships whole or not at all. A top-level @layer fuz.base or `@layer fuz.preferences` block is unwrapped first, so its contents are top-level too and bundled output re-layers the selected rules; the shipped layer order statement is skipped because the bundle emits its own, and so is @charset, which means nothing in a string. Every other @layer rule, and each @import/@namespace, becomes an error in the index's diagnostics and is still indexed as written - an error never removes CSS.

css

raw CSS string (e.g., contents of style.css)

type string

returns

StyleRuleIndex

StyleRuleIndex with rules, lookup maps, and diagnostics

throws

  • if - `css` is not syntactically valid

parse_theme
#

variable.ts view source

(value: unknown): { name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; } | null import {parse_theme} from '@fuzdev/fuz_css/variable.js';

Parses an unknown value as a Theme, returning null when it doesn't match. For untrusted input - a theme restored from storage, a theme handed across a boundary - where a malformed value should fall back to a default rather than throw. Use s.parse(Theme, value) directly when the failure detail matters, or validate_theme in theme_validate.ts for the full lint.

value

the value to parse

type unknown

returns

Theme | null

the theme, or null when the value isn't one

ParsedCssLiteral
#

css_literal.ts view source

ParsedCssLiteral import type {ParsedCssLiteral} from '@fuzdev/fuz_css/css_literal.js';

Parsed CSS-literal class with all components extracted.

class_name

Original class name

type string

media

Media modifier (breakpoint or feature query)

type ModifierDefinition | null

ancestor

Ancestor modifier (dark/light)

type ModifierDefinition | null

states

State modifiers in alphabetical order (can have multiple)

type ModifierDefinition[]

pseudo_element

Pseudo-element modifier (before, after, etc.)

type ModifierDefinition | null

property

CSS property name

type string

value

CSS value (with ~ replaced by spaces)

type string

ParsedRule
#

css_ruleset_parser.ts view source

ParsedRule import type {ParsedRule} from '@fuzdev/fuz_css/css_ruleset_parser.js';

A parsed CSS rule with its components and positions.

selector

Full selector string (e.g., ".box", ".selectable:hover")

type string

selector_start

Start position of selector in original CSS (0-indexed)

type number

selector_end

End position of selector in original CSS

type number

declarations

The declarations block (without braces)

type string

rule_start

Start position of the entire rule

type number

rule_end

End position of the entire rule

type number

ParsedRuleset
#

pebble_theme
#

themes/pebble.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {pebble_theme} from '@fuzdev/fuz_css/themes/pebble.js';

An exemplar theme: the river pebble. Structure comes from depth and softness - round corners, worn to pills on the controls, controls that sit raised on a soft drop shadow and press inward, panels that lift a little off the page, and generous spacing. A cool gray whisper in the neutral and one sans family at a semibold heading weight.

Dual-scheme: in dark the drop falls into the shadow_color_shroud black while the top edge catches a little light. Built from levers only - the palette letters keep their default hues, and nothing is pushed past the gamut caps.

phosphor_theme
#

themes/phosphor.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {phosphor_theme} from '@fuzdev/fuz_css/themes/phosphor.js';

An exemplar theme: the green-phosphor CRT terminal. Structure comes from packing - monospace, sharp-cornered, spacing and leading packed well past the compact themes, and a type scale flattened nearly to one size, with bold headings carrying the hierarchy, give it terminal density, and the three shortest duration tokens are zero. The phosphor tint carries the surfaces and accent, but the palette slots keep their own hues so status colors still read - negative stays red, caution amber, info cyan, and positive steps over to teal so a success never reads as a link.

The screen emits rather than reflects: the ground is the gray-green of an unlit tube face, lifted off black so a surface can still sink below it, and controls glow where other themes cast shadows. Dark-only via the scheme stance: a CRT has no daytime appearance, so it renders through resolve_theme_stance, which computes the stance mirror beside it.

pick_stance_slot
#

theme.ts view source

(v: { base?: string | undefined; dark?: string | undefined; } | undefined, stance: "dark" | "light"): string | undefined import {pick_stance_slot} from '@fuzdev/fuz_css/theme.js';

Picks the value a single-scheme stance renders from a dual-slot shape: the stanced scheme's slot, dark falling back to the base position. Shared by compose_themes and the theme editor so the re-slot semantics can't drift.

v

type { base?: string | undefined; dark?: string | undefined; } | undefined

stance

type "light" | "dark"

returns

string | undefined

position_keywords
#

css_class_keywords.ts view source

readonly ["relative", "absolute", "fixed", "sticky"] import {position_keywords} from '@fuzdev/fuz_css/css_class_keywords.js';

The position keywords with a class, all but the initial static.

PSEUDO_ELEMENT_MODIFIERS
#

modifiers.ts view source

Map<string, ModifierDefinition>

type Map<string, ModifierDefinition>

import {PSEUDO_ELEMENT_MODIFIERS} from '@fuzdev/fuz_css/modifiers.js';

Map of pseudo-element modifier names to their CSS output

ramp_chroma
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", knobs: ChromaRampKnobs, cap: number): number import {ramp_chroma} from '@fuzdev/fuz_css/ramps.js';

Evaluates the palette chroma at a stop: the knob curve clamped by that stop's worst-hue cap. The --chroma_scale multipliers apply above the clamp, in ramp_color_oklch. Defaults for a scheme come from PALETTE_CHROMA_KNOBS[scheme] and PALETTE_CHROMA_CAPS[scheme][stop].

stop

knobs

cap

type number

returns

number

ramp_chroma_at_shape
#

ramps.ts view source

(shape: number, chroma_min: number, chroma_max: number, cap: number): number import {ramp_chroma_at_shape} from '@fuzdev/fuz_css/ramps.js';

The palette chroma for a resolved chroma shape: the knob range at that shape, clamped by the stop's cap - the arithmetic ramp_chroma and ThemeResolver share, the resolver supplying the shape from a theme's resolved --chroma_curve.

shape

type number

chroma_min

type number

chroma_max

type number

cap

type number

returns

number

ramp_chroma_shape
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", curve: number): number import {ramp_chroma_shape} from '@fuzdev/fuz_css/ramps.js';

Evaluates the normalized chroma shape pow(4t(1-t), curve) at a stop - 0 at the endpoints, 1 at the midpoint. The endpoint/midpoint guards mirror render_chroma_shape_css's exact-literal short-circuits, keeping the twins total for any curve (JS would otherwise yield 0 ** 0 === 1).

stop

curve

type number

returns

number

ramp_color_oklch
#

ramps.ts view source

(lightness: number, chroma: number, hue: number, chroma_scale?: number, slot_chroma_scale?: number): Oklch import {ramp_color_oklch} from '@fuzdev/fuz_css/ramps.js';

Combines resolved palette-ramp inputs into a color stop's OKLCH - the one formula behind --palette_X_NN/--<intent>_NN (`chroma * chroma_scale * slot multiplier` at the ramp lightness), shared by the default twins below and check_theme's theme-resolved gates so the two can't drift. Clamped as the browser clamps the oklch() it renders.

lightness

type number

chroma

type number

hue

type number

chroma_scale

type number
default 1

slot_chroma_scale

type number
default 1

returns

Oklch

ramp_lightness
#

ramps.ts view source

(knobs: LightnessRampKnobs, stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): number import {ramp_lightness} from '@fuzdev/fuz_css/ramps.js';

Evaluates a lightness ramp at a stop.

knobs

stop

returns

number

RampFamily
#

ramps.ts view source

RampFamily

type "palette" | "shade" | "text"

import type {RampFamily} from '@fuzdev/fuz_css/ramps.js';

The lightness ramp families and their CSS variable name prefixes.

render_border_color_stop_css
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", scheme: "dark" | "light"): string import {render_border_color_stop_css} from '@fuzdev/fuz_css/ramps.js';

Renders the derived default of a border color stop (--border_color_NN): the border family's color at the stop's alpha from BORDER_COLOR_ALPHAS. The color part is scheme-agnostic - the flip lives in the referenced knobs

  • so stops whose alpha matches across schemes render identically and

variables.ts declares them single-slot.

stop

scheme

returns

string

render_chroma_shape_css
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): string import {render_chroma_shape_css} from '@fuzdev/fuz_css/ramps.js';

Renders the normalized chroma shape of a stop, shared by the palette chroma ramp and the neutral scales: pow(4t(1-t), --chroma_curve). Exactly 0 at the endpoints and 1 at the midpoint.

stop

returns

string

render_chroma_stop_css
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", cap: number): string import {render_chroma_stop_css} from '@fuzdev/fuz_css/ramps.js';

Renders the capped default of a palette chroma ramp stop: the knob curve clamped by a worst-hue gamut cap - the baked per-scheme PALETTE_CHROMA_CAPS for the defaults, or one the theme compile step recomputed. --chroma_scale multiplies outside this clamp, at the color stops.

stop

cap

type number

returns

string

render_color_scheme_rules
#

theme.ts view source

(scheme: "dark" | "light", to_rules: (root: string) => string, media?: string | null): string import {render_color_scheme_rules} from '@fuzdev/fuz_css/theme.js';

Renders a color scheme's rules twice: once under the scheme's root class, and once inside @media (prefers-color-scheme: โ€ฆ) for a root that names no scheme. Both renderings carry the same declarations, so which one applies changes nothing.

scheme

the color scheme the rules belong to

type "light" | "dark"

to_rules

renders the rules given which root selector applies

type (root: string) => string

media

an outer media condition to combine with the preference ((width >= 48rem)), or null

type string | null
default null

returns

string

the CSS, with media (when given) wrapping both renderings

render_lightness_stop_css
#

ramps.ts view source

(family: RampFamily, stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): string import {render_lightness_stop_css} from '@fuzdev/fuz_css/ramps.js';

Renders the derived default of an intermediate lightness ramp stop, e.g. --_palette_lightness_30: calc(var(--palette_lightness_00) + (var(--palette_lightness_100) - var(--palette_lightness_00)) * pow(0.3, var(--palette_lightness_curve))). Stops 00/100 are the endpoint knobs themselves and have no derived form.

family

stop

returns

string

render_neutral_stop_css
#

ramps.ts view source

(family: "text" | "shade", stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): string import {render_neutral_stop_css} from '@fuzdev/fuz_css/ramps.js';

Renders the derived default of a neutral (shade/text) stop. The neutral rides the palette's chroma shape scaled by the --neutral_chroma peak; the ground (shade_00) adds its own --shade_chroma_00, since the shape is 0 there.

family

type "text" | "shade"

stop

returns

string

render_ramp_color_css
#

ramps.ts view source

(slot: "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "accent" | "positive" | "negative" | "caution" | "info", stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | ... 4 more ... | "100", alpha?: string | undefined): string import {render_ramp_color_css} from '@fuzdev/fuz_css/ramps.js';

Renders a color derived from the palette ramps at a stop for a hue slot - the shared template behind palette stops and intent stops (--accent_50 renders with var(--hue_accent)). Both slot references are built from the slot name, so the hue (--hue_<slot>) and its chroma-character multiplier (--palette_X_chroma_scale/--<intent>_chroma_scale) stay paired in the emitted CSS by construction.

slot

a palette letter or intent name

type "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "accent" | "positive" | "negative" | "caution" | "info"

stop

alpha?

optional CSS alpha (e.g. 40%) appended inside the oklch()

type string
optional

returns

string

render_shadow_css
#

shadow_css.ts view source

(shape: "shadow" | "shadow_top" | "shadow_bottom" | "shadow_inset" | "shadow_inset_top" | "shadow_inset_bottom", size: "lg" | "md" | "sm" | "xs" | "xl", color: "umbra" | "highlight" | "glow" | "shroud", alpha: "00" | ... 11 more ... | "100"): string import {render_shadow_css} from '@fuzdev/fuz_css/shadow_css.js';

Renders one box-shadow layer from the shadow tokens, for a declared shadow variable like --button_shadow or --panel_shadow. Join several with , to stack them.

The color is named outright, not read through the contextual --shadow_color the .shadow_* classes set: a custom property's var()s substitute against the element that declares it, and theme variables are declared on :root, so that indirection would only ever see its fallback.

shape

where the shadow falls

size

the geometry step

color

the semantic shadow color, as in --shadow_color_umbra

alpha

the step of the shadow alpha ramp, scaled by --shadow_alpha_scale

returns

string

the layer as a CSS value

render_shadow_tint_css
#

ramps.ts view source

(tint: ShadowTint): string import {render_shadow_tint_css} from '@fuzdev/fuz_css/ramps.js';

Renders a SHADOW_TINTS entry as oklch() on the neutral hue.

tint

returns

string

render_style_variables
#

theme.ts view source

(variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[], options?: RenderStyleVariablesOptions): string import {render_style_variables} from '@fuzdev/fuz_css/theme.js';

Renders a variable set as CSS the way render_theme_style renders a theme's, for a set that isn't a theme: the internal ramp variables render too, and nothing is mirrored or pinned. This is how theme.css renders the full defaults, and how a project that baked a theme in at build time can restore the defaults at runtime: render_style_variables(default_variables). Total over any JSON value, like render_theme_style.

variables

the variables to render, in order

options

default {}

returns

string

the CSS, or an empty string when there's nothing to render

render_theme_style
#

theme.ts view source

(theme: { name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }, options?: RenderThemeStyleOptions): string import {render_theme_style} from '@fuzdev/fuz_css/theme.js';

Renders a theme's variables as CSS, wrapped in the fuz.theme cascade layer by default.

Renders exactly what the theme carries plus the derived data in options: the stance mirror (under a stance only, minus any name the theme or the caps set), then the theme's variables, then the caps. An empty theme renders nothing (inheriting the fuz.base defaults) unless a scheme stance needs pinning. To render a single-scheme theme faithfully, resolve it first and pass the result as the options: render_theme_style(resolved.theme, resolved).

A theme can't set the internal ramp variables, so a _-prefixed name in theme.variables is dropped - the schema rejects one, and this holds the same line for a theme that skipped it. The derived scheme_mirror and caps carry internal names by design and render them. To render a variable set that isn't a theme, like the full defaults, use render_style_variables.

Total over any JSON value in either argument, because a theme restored from storage reaches this without passing the schema: whatever isn't the type declared is dropped instead of thrown on or coerced into the stylesheet. A variables, scheme_mirror, or caps that isn't an array renders as empty, an entry that isn't an object is skipped, a name or slot that isn't a contained string drops its declaration, and a summary that isn't one drops its comment (see css_containment.ts).

theme

the theme to render

type Theme

options

default {}

returns

string

the theme CSS, or an empty string when there's nothing to render

RenderStyleVariablesOptions
#

theme.ts view source

RenderStyleVariablesOptions import type {RenderStyleVariablesOptions} from '@fuzdev/fuz_css/theme.js';

comments?

type boolean

id?

Scopes the rendered variables to #id instead of :root. Dark slots render for both placements of the scheme class - on the scope element itself (#id.dark) and on the root (:root.dark #id), the ecosystem convention - so a scoped theme's dark appearance follows the page's. A .light on the scope element wins over either: the scope takes the theme's base slots under :root.dark and on a dark OS alike. With no scheme class on the root or the scope, the dark slots follow the OS preference.

Only literal-valued variables take effect in a scope: the derived color stops (--palette_a_50, --shade_50, ...) resolve their calc() on :root, and a descendant inherits the computed color, so a curve knob like --chroma_scale set at #id changes nothing. Knob-only themes need :root.

Any string works: it's escaped into the selector, so it matches the element whose id attribute is that string and can't end the rule or the <style> element. An empty string renders to :root.

type string | null

layer?

The cascade layer wrapping the rendered variables. Theme overrides default to fuz.theme so they beat the fuz.base defaults by layer order; pass null to render unlayered. A value that isn't a dotted layer name (fuz.theme.baked) falls back to the default.

type string | null

RenderThemeStyleOptions
#

resolve_class_definition
#

css_class_resolution.ts view source

(def: CssClassDefinitionStatic, class_name: string, definitions: Record<string, CssClassDefinition | undefined>, css_properties?: Set<...> | null): ResolveComposesResult import {resolve_class_definition} from '@fuzdev/fuz_css/css_class_resolution.js';

Resolves a class definition's declaration, handling composes composition.

If the definition has a composes property, resolves those classes recursively and combines with any explicit declaration. If no composes, returns the explicit declaration directly.

def

the class definition to resolve

class_name

the name of the class being resolved (for error messages)

type string

definitions

record of all known class definitions

type Record<string, CssClassDefinition | undefined>

css_properties

set of valid CSS properties for literal validation, or null to skip

type Set<string> | null
default null

returns

ResolveComposesResult

combined declaration or an error

resolve_class_definitions
#

css_class_definitions.ts view source

(option: ClassDefinitionsOption): Record<string, CssClassDefinition | undefined> import {resolve_class_definitions} from '@fuzdev/fuz_css/css_class_definitions.js';

Resolves the class_definitions option against the built-in definitions. A record merges over the defaults, taking precedence over a default with the same name, and a callback receives a copy of the defaults and returns the whole set.

option

the class_definitions option

returns

Record<string, CssClassDefinition | undefined>

the class definitions to generate with

throws

  • Error - if a callback returns something other than an object

resolve_class_interpreters
#

css_class_interpreters.ts view source

(option: ClassInterpretersOption): CssClassDefinitionInterpreter[] import {resolve_class_interpreters} from '@fuzdev/fuz_css/css_class_interpreters.js';

Resolves the class_interpreters option against the builtin interpreters. An array replaces them, and a callback receives a copy of them and returns the interpreters to use.

option

the class_interpreters option

returns

CssClassDefinitionInterpreter[]

the interpreters to generate with

throws

  • Error - if a callback returns something other than an array

resolve_composes
#

css_class_resolution.ts view source

(class_names: string[], definitions: Record<string, CssClassDefinition | undefined>, resolution_stack: Set<string>, visited: Set<string>, original_class_name: string, css_properties?: Set<...> | null): ResolveComposesResult import {resolve_composes} from '@fuzdev/fuz_css/css_class_resolution.js';

Resolves an array of class names to their combined CSS declarations.

Recursively resolves nested composes arrays and combines all declarations. Validates that referenced classes exist and are resolvable (not rulesets or interpreters). Supports unmodified CSS literals (e.g., text-align:center) in the composes array.

Deduplication behavior:

  • Diamond dependencies (class reached via different composition branches) are silently skipped
  • Redundant listings (class already included by an earlier sibling in this array) emit a warning

class_names

array of class names to resolve

type string[]

definitions

record of all known class definitions

type Record<string, CssClassDefinition | undefined>

resolution_stack

set of class names currently being resolved (for cycle detection)

type Set<string>

visited

set of all class names already resolved (for deduplication)

type Set<string>

original_class_name

the class name being defined (for error messages)

type string

css_properties

set of valid CSS properties for literal validation, or null to skip

type Set<string> | null
default null

returns

ResolveComposesResult

combined declarations or an error

mutates

  • resolution_stack โ€” temporarily adds/removes names during recursion
  • visited โ€” adds resolved class names for deduplication

resolve_css
#

css_bundled_resolution.ts view source

(options: CssResolutionOptions): CssResolutionResult import {resolve_css} from '@fuzdev/fuz_css/css_bundled_resolution.js';

Resolves which CSS to include based on detected usage.

Algorithm:

  1. Collect rules: core rules + element-matching + class-matching
  2. Collect variables: from rules, generated utility CSS, detected vars, additional_variables
  3. Resolve transitive variable dependencies
  4. Generate output: theme_css (base+dark), base_css (source order)

options

resolution options including indexes, detected usage, and config

returns

CssResolutionResult

resolution result with theme CSS, base CSS, and diagnostics

resolve_theme_stance
#

theme_stance.ts view source

(theme: { name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }): ResolvedTheme import {resolve_theme_stance} from '@fuzdev/fuz_css/theme_stance.js';

Resolves a theme for rendering: a single-scheme theme gets its stance mirror beside it, a dual-scheme theme nothing. Safe to call on any theme, and pure - the theme comes back as the same reference, never carrying the derived data, so persisting resolved.theme persists only what was authored.

theme

the theme to resolve

type Theme

returns

ResolvedTheme

the theme with its derived data, for render_theme_style(r.theme, r)

resolve_variables_transitive
#

variable_graph.ts view source

(graph: VariableDependencyGraph, initial_variables: Iterable<string>, excluded?: ReadonlySet<string> | undefined): ResolveVariablesResult import {resolve_variables_transitive} from '@fuzdev/fuz_css/variable_graph.js';

Resolves variables transitively using DFS with cycle detection. When a variable is requested, all variables it depends on are included. Both base and dark dependencies are always resolved together.

An excluded variable is left out along with the dependencies only it pulls in - whatever defines it in its place defines those too.

graph

the variable dependency graph

initial_variables

initial set of variable names to resolve

type Iterable<string, any, any>

excluded?

variable names to leave out, and not resolve through

type ReadonlySet<string>
optional

returns

ResolveVariablesResult

ResolveVariablesResult with all transitive dependencies

ResolveComposesResult
#

css_class_resolution.ts view source

ResolveComposesResult

type { ok: true; declaration: string; warnings: InterpreterDiagnostic[] | null; } | { ok: false; error: InterpreterDiagnostic; }

import type {ResolveComposesResult} from '@fuzdev/fuz_css/css_class_resolution.js';

Result from resolving a composes array to combined declarations.

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.

ResolvedTheme
#

theme.ts view source

ResolvedTheme import type {ResolvedTheme} from '@fuzdev/fuz_css/theme.js';

A theme with its derived data beside it, ready to render: render_theme_style(resolved.theme, resolved). The theme is wrapped rather than extended, so serializing theme can't leak the derived data into what's persisted.

inheritance

extends: ThemeDerived

theme

type Theme

ResolveVariablesResult
#

variable_graph.ts view source

ResolveVariablesResult import type {ResolveVariablesResult} from '@fuzdev/fuz_css/variable_graph.js';

Result from transitive variable resolution.

variables

All resolved variable names

type Set<string>

warnings

Warning messages for cycles

type string[]

missing

Variable names that were requested but not found in the graph

type Set<string>

excluded

Excluded variable names a resolved variable depends on

type Set<string>

RuleLayer
#

style_rule_parser.ts view source

RuleLayer

type "fuz.base" | "fuz.preferences"

import type {RuleLayer} from '@fuzdev/fuz_css/style_rule_parser.js';

The cascade layer a rule is emitted into in bundled output. A base stylesheet's rules land in fuz.base; the contents of a top-level @layer fuz.preferences block keep that identity, because the OS user-preference mappings must stay above the fuz.base defaults. No other layer survives parsing - see parse_style_css.

ruleset_contains_class
#

css_ruleset_parser.ts view source

(rules: ParsedRule[], escaped_class_name: string): boolean import {ruleset_contains_class} from '@fuzdev/fuz_css/css_ruleset_parser.js';

Checks if any selector in the ruleset contains the expected class name. Used to validate that ruleset definitions match their key.

rules

parsed rules from the ruleset

type ParsedRule[]

escaped_class_name

the CSS-escaped class name (e.g., "clickable" or "hover\\:card")

type string

returns

boolean

true if at least one selector contains ".class_name"

save_cached_extraction
#

css_cache.ts view source

(deps: CacheDeps, options: SaveCachedExtractionOptions): Promise<void> import {save_cached_extraction} from '@fuzdev/fuz_css/css_cache.js';

Saves an extraction result to the cache. Uses atomic write (temp file + rename) for crash safety. Normalizes empty collections to null to avoid allocation overhead on load.

deps

filesystem deps for dependency injection

options

the cache file, its key parts, and the extraction to write

returns

Promise<void>

SaveCachedExtractionOptions
#

css_cache.ts view source

SaveCachedExtractionOptions import type {SaveCachedExtractionOptions} from '@fuzdev/fuz_css/css_cache.js';

cache_path

Absolute path to the cache file.

type string

content_hash

Content hash of the source file contents.

type string

extraction_key

The configuration part of the key, from to_extraction_cache_key.

type string | null

extraction

Extraction data to cache.

type ExtractionData

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.

scheme_adaptive_variables
#

scheme_adaptive_variables.ts view source

{ name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]

type StyleVariable[]

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

The scheme-adaptive subset of default_variables: every default that carries both a base and a dark value, and therefore changes appearance with the color scheme. resolve_theme_stance mirrors these so a single-scheme theme shows its one appearance in both schemes.

Literal twin of variables.ts, generated so consumers of the stance mirror don't pull the full derived variable set.

scheme_stance_variables
#

theme_stance.ts view source

(scheme: "dark" | "light", variables?: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]): { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[] import {scheme_stance_variables} from '@fuzdev/fuz_css/theme_stance.js';

Computes the mirror a single-scheme stance implies: every scheme-adaptive variable in variables (those carrying a dark slot), re-slotted with the stanced scheme's value in the base slot. A base-slot declaration in fuz.theme applies in both color schemes - cascade-layer order beats the higher specificity of the fuz.base dark-scheme defaults (:root.dark and its prefers-color-scheme twin) - and keeping the mirror out of the dark slot means later same-block declarations (the theme's own variables, composed overlays, compiled caps) always win by source order.

The mirror depends on the stance alone, not on the theme: the renderer skips an entry whose name the theme or its caps set.

scheme

the stance to mirror for

type "light" | "dark"

variables

the variable set to mirror, scheme_adaptive_variables by default

default scheme_adaptive_variables

returns

StyleVariable[]

the mirrored variables, to render before the theme's own

SHADE_CHROMA_00
#

ramps.ts view source

0 import {SHADE_CHROMA_00} from '@fuzdev/fuz_css/ramps.js';

The ground's own chroma (--shade_chroma_00), added to the shade_00 stop's shaped chroma. The chroma shape is 0 at the endpoints, so without it the page ground is untinted whatever neutral_chroma says; a theme whose identity is a tinted page (paper, a lit night) sets it. 0 keeps the default ground neutral.

SHADE_LIGHTNESS_KNOBS
#

ramps.ts view source

Readonly<Record<"dark" | "light", Readonly<LightnessRampKnobs>>>

type Readonly<Record<ColorSchemeVariant, Readonly<LightnessRampKnobs>>>

import {SHADE_LIGHTNESS_KNOBS} from '@fuzdev/fuz_css/ramps.js';

Fitted lightness knobs for the shade (surface) ramps.

shade_scale_variants
#

variable_data.ts view source

readonly ["min", "00", "05", "10", "20", "30", "40", "50", "60", "70", "80", "90", "95", "100", "max"] import {shade_scale_variants} from '@fuzdev/fuz_css/variable_data.js';

shade_stop_oklch
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", scheme: "dark" | "light"): Oklch import {shade_stop_oklch} from '@fuzdev/fuz_css/ramps.js';

Computes the default OKLCH color of a shade stop (--shade_NN).

stop

scheme

returns

Oklch

shade_variants
#

variable_data.ts view source

readonly ["00", "05", "10", "20", "30", "40", "50", "60", "70", "80", "90", "95", "100"] import {shade_variants} from '@fuzdev/fuz_css/variable_data.js';

ShadeScaleVariant
#

variable_data.ts view source

"00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100" | "min" | "max"

type NumericScaleWithExtremesVariant

import type {ShadeScaleVariant} from '@fuzdev/fuz_css/variable_data.js';

Full shade scale including min/max extremes for untinted surfaces.

ShadeVariant
#

shadow_alpha_variants
#

variable_data.ts view source

readonly ["00", "05", "10", "20", "30", "40", "50", "60", "70", "80", "90", "95", "100"] import {shadow_alpha_variants} from '@fuzdev/fuz_css/variable_data.js';

SHADOW_ALPHAS
#

variable_data.ts view source

Readonly<Record<"00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", Readonly<{ light: number; dark: number; }>>>

type Readonly<Record<NumericScaleVariant, Readonly<{ light: number; dark: number; }>>>

import {SHADOW_ALPHAS} from '@fuzdev/fuz_css/variable_data.js';

Shadow alphas in %, per color scheme, before the --shadow_alpha_scale multiplier. A perceptually-uniform curve - small gaps at the low end where subtle changes are perceptible, large at the high end - boosted at the low end in dark mode, where shadows read weakly against dark backgrounds.

SHADOW_GEOMETRY
#

variable_data.ts view source

Readonly<Record<"lg" | "md" | "sm" | "xs" | "xl", Readonly<{ offset: number; blur: number; spread: number; }>>>

type Readonly<Record<ShadowSizeVariant, Readonly<{ offset: number; blur: number; spread: number; }>>>

import {SHADOW_GEOMETRY} from '@fuzdev/fuz_css/variable_data.js';

Shadow geometry per size in px. The directional variants sign the offset, and the inset pair signs it the other way, so top always names the lit edge; see shadow_variant_prefixes for the six shapes each size emits.

shadow_semantic_values
#

variable_data.ts view source

readonly ["umbra", "highlight", "glow", "shroud"] import {shadow_semantic_values} from '@fuzdev/fuz_css/variable_data.js';

shadow_size_variants
#

variable_data.ts view source

readonly ["xs", "sm", "md", "lg", "xl"] import {shadow_size_variants} from '@fuzdev/fuz_css/variable_data.js';

SHADOW_TINTS
#

ramps.ts view source

Readonly<Record<ShadowTint, Readonly<{ lightness: number; chroma: number; }>>>

type Readonly<Record<ShadowTint, Readonly<{ lightness: number; chroma: number; }>>>

import {SHADOW_TINTS} from '@fuzdev/fuz_css/ramps.js';

Fitted neutral-hued tints for the shadow color endpoints: bright is the light-scheme highlight and glow, dim the dark-scheme umbra and glow. Each renders on --hue_neutral, so a retinted neutral recolors shadows with the surfaces.

shadow_variant_prefixes
#

variable_data.ts view source

readonly ["shadow_", "shadow_top_", "shadow_bottom_", "shadow_inset_", "shadow_inset_top_", "shadow_inset_bottom_"] import {shadow_variant_prefixes} from '@fuzdev/fuz_css/variable_data.js';

ShadowAlphaVariant
#

variable_data.ts view source

"00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

import type {ShadowAlphaVariant} from '@fuzdev/fuz_css/variable_data.js';

ShadowSemanticValue
#

variable_data.ts view source

"umbra" | "highlight" | "glow" | "shroud"

type "umbra" | "highlight" | "glow" | "shroud"

import type {ShadowSemanticValue} from '@fuzdev/fuz_css/variable_data.js';

ShadowShape
#

shadow_css.ts view source

"shadow" | "shadow_top" | "shadow_bottom" | "shadow_inset" | "shadow_inset_top" | "shadow_inset_bottom"

type "shadow" | "shadow_top" | "shadow_bottom" | "shadow_inset" | "shadow_inset_top" | "shadow_inset_bottom"

import type {ShadowShape} from '@fuzdev/fuz_css/shadow_css.js';

Where a shadow falls: shadow centered on the element, shadow_top and shadow_bottom cast to one side, and the inset twins drawn inside it. Derived from shadow_variant_prefixes, the vocabulary the geometry tokens are emitted from.

ShadowSizeVariant
#

variable_data.ts view source

"lg" | "md" | "sm" | "xs" | "xl"

type "lg" | "md" | "sm" | "xs" | "xl"

import type {ShadowSizeVariant} from '@fuzdev/fuz_css/variable_data.js';

ShadowTint
#

ramps.ts view source

ShadowTint

type "bright" | "dim"

import type {ShadowTint} from '@fuzdev/fuz_css/ramps.js';

signage_theme
#

themes/signage.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {signage_theme} from '@fuzdev/fuz_css/themes/signage.js';

An exemplar theme: built for legibility, the way public signage is - read at a distance, in passing, by anyone. Structure comes from scale and weight: generous spacing, larger body text, an opened-up type scale, a heavier body weight under bold grotesque headings at normal tracking, thick borders, flat fields, underlined links, and a focus ring too wide to miss. The palette stays at the gamut caps: signage color is saturated but it has to print.

For public-facing sites, older readers, kiosks, and anyone who wants the defaults turned up rather than restyled. Dual-scheme, and the one exemplar whose accent changes between them: by day the wayfinding blue of a printed board, by night the yellow of a lit departure display. Built from levers only - the palette letters keep their default hues.

SizeVariant
#

variable_data.ts view source

"lg" | "md" | "sm" | "xs" | "xl" | "xl2" | "xl3" | "xl4" | "xl5" | "xl6" | "xl7" | "xl8" | "xl9"

type "lg" | "md" | "sm" | "xs" | "xl" | "xl2" | "xl3" | "xl4" | "xl5" | "xl6" | "xl7" | "xl8" | "xl9"

import type {SizeVariant} from '@fuzdev/fuz_css/variable_data.js';

SkippedModifierInfo
#

css_ruleset_parser.ts view source

SkippedModifierInfo import type {SkippedModifierInfo} from '@fuzdev/fuz_css/css_ruleset_parser.js';

Information about a modifier that was skipped for a selector during ruleset modification. The selector is still included in output, just without the conflicting modifier applied.

selector

The specific selector where the modifier was skipped (not the full selector list)

type string

reason

Reason the modifier was skipped

type "pseudo_element_conflict" | "state_conflict"

conflicting_modifier

The conflicting modifier that was not applied (e.g., "::before" or ":hover")

type string

SourceIndex
#

css_class_extractor.ts view source

import {SourceIndex} from '@fuzdev/fuz_css/css_class_extractor.js';

Helper class for converting character offsets to line/column positions. Svelte template nodes (Comment, Text, ExpressionTag) only have char offsets, so this class enables efficient conversion.

Build: O(n) where n = source length Lookup: O(log m) where m = number of lines (binary search)

constructor

type new (source: string): SourceIndex

source

type string

get_location

Converts a character offset to a source location.

type (offset: number, file: string): SourceLocation

offset

0-based character offset in the source

type number

file

file path for the location

type string

SourceLocation with 1-based line and column

SourceLocation
#

diagnostics.ts view source

SourceLocation import type {SourceLocation} from '@fuzdev/fuz_css/diagnostics.js';

Source location for IDE/LSP integration.

file

type string

line

1-based line number

type number

column

1-based column number

type number

SPACE_SIZES
#

variable_data.ts view source

Readonly<Record<"lg" | "md" | "sm" | "xs" | "xl" | "xl2" | "xl3" | "xl4" | "xl5" | "xl6" | "xl7" | "xl8" | "xl9" | "xs5" | "xs4" | "xs3" | "xs2" | "xl10" | "xl11" | "xl12" | "xl13" | "xl14" | "xl15", number>>

type Readonly<Record<SpaceVariant, number>>

import {SPACE_SIZES} from '@fuzdev/fuz_css/variable_data.js';

Spaces in rem, before the --space_scale multiplier.

space_variants
#

variable_data.ts view source

readonly ["xs5", "xs4", "xs3", "xs2", "xs", "sm", "md", "lg", "xl", "xl2", "xl3", "xl4", "xl5", "xl6", "xl7", "xl8", "xl9", "xl10", "xl11", "xl12", "xl13", "xl14", "xl15"] import {space_variants} from '@fuzdev/fuz_css/variable_data.js';

SpaceVariant
#

variable_data.ts view source

"lg" | "md" | "sm" | "xs" | "xl" | "xl2" | "xl3" | "xl4" | "xl5" | "xl6" | "xl7" | "xl8" | "xl9" | "xs5" | "xs4" | "xs3" | "xs2" | "xl10" | "xl11" | "xl12" | "xl13" | "xl14" | "xl15"

type "lg" | "md" | "sm" | "xs" | "xl" | "xl2" | "xl3" | "xl4" | "xl5" | "xl6" | "xl7" | "xl8" | "xl9" | "xs5" | "xs4" | "xs3" | "xs2" | "xl10" | "xl11" | "xl12" | "xl13" | "xl14" | "xl15"

import type {SpaceVariant} from '@fuzdev/fuz_css/variable_data.js';

splice_css_at_placeholder
#

css_placeholder_splice.ts view source

(source: string, generated_css: string): string | null import {splice_css_at_placeholder} from '@fuzdev/fuz_css/css_placeholder_splice.js';

Replaces the first placeholder in a bundled stylesheet with the generated CSS, at the offset the marker occupies.

Position is the point: the marker sits where Vite placed virtual:fuz.css in the importer's stylesheet, so writing the generated CSS there reproduces the import order the source asked for. Appending to the end of the asset instead would silently move fuz_css's :root after every stylesheet bundled alongside it, so an app's own equal-specificity token override would win in dev (where the virtual module is served in place) and lose in the production bundle.

Usually the marker is its own rule, but a minifier that merges adjacent rules with identical selectors (lightningcss is one; esbuild, Vite's default, isn't) folds neighboring :root declarations into the marker's block - from either or both sides. Declaration order preserves the merged rules' order, so splitting the block at the marker keeps the cascade exact: declarations before it came from stylesheets bundled before virtual:fuz.css and stay before the generated CSS, declarations after it stay after. The solo-rule case is the same split with both sides empty.

The marker's rule starts after whatever ends the preceding construct: a rule's }, a statement at-rule's ; (@charset, @import, which a bundler hoists ahead of the first rule), or an enclosing block's {. Comments, strings, and unquoted url()s are read past, since one can hold any of those - an unminified build or a preserved /*! *\/ comment leaves them in, and a content string or a URL can hold a /* of its own.

source

the bundled stylesheet holding the marker

type string

generated_css

the CSS to write at the marker's position

type string

returns

string | null

source with the generated CSS spliced in and the marker stripped, or null if no marker sits inside a well-formed rule

splice_css_into_asset
#

css_placeholder_splice.ts view source

(source: string, generated_css: string): string | null import {splice_css_into_asset} from '@fuzdev/fuz_css/css_placeholder_splice.js';

Finishes one bundled stylesheet: writes the generated CSS at its first placeholder and strips any others. Two entries' CSS merged into one asset, or a pipeline that copied the placeholder rule, leave more than one; the generated CSS belongs at the first.

source

the bundled stylesheet

type string

generated_css

the CSS to write at the first placeholder

type string

returns

string | null

the finished stylesheet, or null when it holds no placeholder

split_selector_list
#

css_ruleset_parser.ts view source

(selector_group: string): string[] import {split_selector_list} from '@fuzdev/fuz_css/css_ruleset_parser.js';

Splits a selector list by commas, respecting parentheses, brackets, and quoted strings.

selector_group

type string

returns

string[]

examples

split_selector_list('.a, .b') // โ†’ ['.a', '.b'] split_selector_list('.a:not(.b), .c') // โ†’ ['.a:not(.b)', '.c'] split_selector_list('.a[data-x="a,b"], .c') // โ†’ ['.a[data-x="a,b"]', '.c']

srgb_relative_luminance
#

wcag.ts view source

([r, g, b]: RgbUnit): number import {srgb_relative_luminance} from '@fuzdev/fuz_css/wcag.js';

Computes WCAG 2.x relative luminance of a gamma-encoded sRGB color.

__0

type RgbUnit

returns

number

STATE_MODIFIERS
#

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.

strip_css_comments
#

css_variable_utils.ts view source

(css: string): string import {strip_css_comments} from '@fuzdev/fuz_css/css_variable_utils.js';

Removes the comments from a CSS string, so text inside one isn't read as CSS. Quoted strings and unquoted url() values are left intact - a /* inside either is not a comment - and each comment becomes a space because a comment separates tokens. For analysis, not for output.

css

CSS string potentially containing comments

type string

returns

string

the string without its comments, or css itself when it has none

style_hook_by_name
#

style_hooks.ts view source

ReadonlyMap<string, StyleHook>

type ReadonlyMap<string, StyleHook>

import {style_hook_by_name} from '@fuzdev/fuz_css/style_hooks.js';

The catalog indexed by variable name.

style_hooks
#

STYLE_VARIABLE_NAME_MATCHER
#

variable.ts view source

RegExp import {STYLE_VARIABLE_NAME_MATCHER} from '@fuzdev/fuz_css/variable.js';

Matches a public style variable name, the names a theme may set.

StyleHook
#

style_hooks.ts view source

StyleHook import type {StyleHook} from '@fuzdev/fuz_css/style_hooks.js';

name

type string

read_by

The base styles and classes whose rules read the hook. A rule that only sets it, like .plain clearing a button's fill, isn't a reader.

type readonly string[]

fallbacks

The distinct var() fallbacks the hook's reads carry - what renders where nothing sets it. Empty for a local hook.

type readonly string[]

local?

True when the rules reading the hook declare it themselves, so a value reaches the reader only from a rule on the same element - an inherited value from an ancestor or a theme's root never does.

type boolean

summary

What setting the hook does, for docs and tooling.

type string

StyleRule
#

StyleRuleBase
#

style_rule_parser.ts view source

StyleRuleBase import type {StyleRuleBase} from '@fuzdev/fuz_css/style_rule_parser.js';

Base fields shared by all style rules.

css

The full CSS text for this rule (including selector and declarations)

type string

elements

HTML element names this rule targets (e.g., 'button', 'input')

type Set<string>

classes

CSS class names this rule targets (e.g., 'unstyled', 'selected')

type Set<string>

variables_used

CSS variables referenced anywhere in the rule's text, nested rules included. Read from the raw text, so it can only over-include - which never leaves a var() undefined.

type Set<string>

variables_required

The subset of variables_used that something outside the rule must define: referenced with no fallback outside a comment, and not declared by the rule itself.

type Set<string>

variables_defined

Custom properties the rule defines for the whole document: the ones a top-level style rule declares when a selector in its list is exactly :root, :host, html, body, or *. Empty for every other rule.

type Set<string>

order

Original order in the stylesheet (for preserving cascade)

type number

layer

The cascade layer this rule is emitted into in bundled output

type RuleLayer

StyleRuleIndex
#

style_rule_parser.ts view source

StyleRuleIndex import type {StyleRuleIndex} from '@fuzdev/fuz_css/style_rule_parser.js';

Index of parsed style rules for efficient lookup.

rules

All rules in original order

type StyleRule[]

by_element

Rules indexed by element name

type Map<string, number[]>

by_class

Rules indexed by class name

type Map<string, number[]>

diagnostics

Problems found while parsing: constructs the stylesheet contains that don't belong in a base stylesheet (base_css_layer, base_css_unsupported_at_rule). resolve_css forwards them with its own diagnostics.

type GenerationDiagnostic[]

StyleVariable
#

variable.ts view source

value + type

{ name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; } import {StyleVariable} from '@fuzdev/fuz_css/variable.js';

A style variable: a custom property name with a value per color scheme.

The slots follow the renderer's cascade: base is the base position, rendered on :root, and dark renders on :root.dark (and for a root naming no scheme, under prefers-color-scheme: dark). A theme variable with only base therefore applies in both color schemes (its fuz.theme :root beats the fuz.base dark default by layer order), while dark alone applies in dark only - which is why the shipped themes author a scheme-agnostic knob as a single base value. The light scheme renders base; there is no light-only slot.

Strict: a misspelled slot is an error, not a silently dropped scheme. A slot must also be a contained CSS value (see css_containment.ts), since it renders verbatim.

The name is a public one (StyleVariableName): an internal ramp variable is rejected with an error saying so. The derived data that does carry internal names - a stance's mirror and compile_theme's caps - travels beside a theme as ThemeDerived, never inside it.

name

type string

dark?

type string

base?

type string

summary?

type string

StyleVariableInfo
#

variable_graph.ts view source

StyleVariableInfo import type {StyleVariableInfo} from '@fuzdev/fuz_css/variable_graph.js';

Information about a single style variable and its dependencies.

name

Variable name (without -- prefix)

type string

base_deps

Variables referenced in the base value

type Set<string>

dark_deps

Variables referenced in the dark value

type Set<string>

base_value

The base value, rendered on :root in both schemes, or undefined if not defined

type string | undefined

dark_value

The dark value, rendered under the dark scheme over the base, or undefined if not defined

type string | undefined

StyleVariableName
#

suggest_css_property
#

css_literal.ts view source

(typo: string, properties: Set<string> | null): string | null import {suggest_css_property} from '@fuzdev/fuz_css/css_literal.js';

Suggests a correct property name for a typo using Levenshtein distance.

typo

the mistyped property name

type string

properties

Set of valid CSS properties from load_css_properties() Pass null to skip suggestions.

type Set<string> | null

returns

string | null

the suggested property or null if no close match (Levenshtein distance > 2)

suggest_modifier
#

css_literal.ts view source

(typo: string): string | null import {suggest_modifier} from '@fuzdev/fuz_css/css_literal.js';

Suggests a correct modifier name for a typo using Levenshtein distance.

typo

the mistyped modifier name

type string

returns

string | null

the suggested modifier or null if no close match (Levenshtein distance > 2)

ternaryClass
#

example_class_utilities.ts view source

"mt_xs" | "mt_sm"

type "mt_xs" | "mt_sm"

import {ternaryClass} from '@fuzdev/fuz_css/example_class_utilities.js';

Ternary expression - both branches extracted

text_decoration_line_keywords
#

css_class_keywords.ts view source

readonly ["underline", "overline", "line-through"] import {text_decoration_line_keywords} from '@fuzdev/fuz_css/css_class_keywords.js';

The text-decoration-line keywords with a class. They set the longhand, so an element's decoration color, style, and thickness carry through.

TEXT_LIGHTNESS_KNOBS
#

text_scale_variants
#

variable_data.ts view source

readonly ["min", "00", "05", "10", "20", "30", "40", "50", "60", "70", "80", "90", "95", "100", "max"] import {text_scale_variants} from '@fuzdev/fuz_css/variable_data.js';

text_stop_oklch
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", scheme: "dark" | "light"): Oklch import {text_stop_oklch} from '@fuzdev/fuz_css/ramps.js';

Computes the default OKLCH color of a text stop (--text_NN).

stop

scheme

returns

Oklch

text_transform_keywords
#

css_class_keywords.ts view source

readonly ["uppercase", "lowercase", "capitalize"] import {text_transform_keywords} from '@fuzdev/fuz_css/css_class_keywords.js';

The text-transform keywords with a class.

text_variants
#

variable_data.ts view source

readonly ["00", "05", "10", "20", "30", "40", "50", "60", "70", "80", "90", "95", "100"] import {text_variants} from '@fuzdev/fuz_css/variable_data.js';

TextScaleVariant
#

variable_data.ts view source

"00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100" | "min" | "max"

type NumericScaleWithExtremesVariant

import type {TextScaleVariant} from '@fuzdev/fuz_css/variable_data.js';

Full text scale including min/max extremes for knockout text.

TextVariant
#

Theme
#

variable.ts view source

value + type

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; } import {Theme} from '@fuzdev/fuz_css/variable.js';

name

type string

variables

type StyleVariable[]

summary?

type string

scheme?

type "dark" | "light" | "dual"

theme_gate_role_names
#

theme_check.ts view source

readonly string[] import {theme_gate_role_names} from '@fuzdev/fuz_css/theme_check.js';

The role variables the contrast gates follow - each aliases a color stop or another role by default (text_color is var(--text_80)), and check_theme measures whatever a theme points it at instead of the stop it left.

theme_knob_axes
#

knobs.ts view source

readonly { axis: KnobAxis; title: string; }[] import {theme_knob_axes} from '@fuzdev/fuz_css/knobs.js';

The theme-space axes in editor display order, with display titles.

theme_knob_by_name
#

knobs.ts view source

ReadonlyMap<string, ThemeKnob>

type ReadonlyMap<string, ThemeKnob>

import {theme_knob_by_name} from '@fuzdev/fuz_css/knobs.js';

The catalog indexed by variable name.

theme_knob_hook_names
#

knobs.ts view source

ReadonlySet<string>

type ReadonlySet<string>

import {theme_knob_hook_names} from '@fuzdev/fuz_css/knobs.js';

Names of hook knobs - consumed by style.css via fallbacks, not declared in default_variables. Theme validation unions these with the declared variable names.

theme_knobs
#

knobs.ts view source

readonly ThemeKnob[]

type readonly ThemeKnob[]

import {theme_knobs} from '@fuzdev/fuz_css/knobs.js';

The theme knobs in editor display order: by axis, high leverage first, with the palette tier last within the color axis.

ThemeCheckReport
#

ThemeDerived
#

theme.ts view source

ThemeDerived import type {ThemeDerived} from '@fuzdev/fuz_css/theme.js';

Data derived from a theme rather than authored in it: what a theme's stance and hues imply, computed by resolve_theme_stance and compile_theme (theme_compile.ts) and handed to render_theme_style beside the theme. Never part of a Theme, so a persisted or shared theme can't carry stale derived values - it's recomputed from the theme wherever the theme renders, and never validated.

scheme_mirror?

The stance mirror: the scheme-adaptive variables re-slotted (the defaults' twin at runtime, the configured set at build time) into the base position with the stanced scheme's value, so a single-scheme theme's one appearance holds in both color schemes. Rendered first and only under a stance, skipping any name the theme's variables or the caps set.

type StyleVariable[]

caps?

Recomputed worst-hue chroma caps from compile_theme (or compute_theme_caps alone), as _palette_chroma_NN overrides. Rendered last, so they win over the mirror's re-slotted defaults.

type StyleVariable[]

ThemeGateEntry
#

theme_check.ts view source

ThemeGateEntry import type {ThemeGateEntry} from '@fuzdev/fuz_css/theme_check.js';

A single gate measurement against a theme. The value/threshold comparison direction depends on the gate: contrast passes at value >= threshold (a WCAG ratio floor), monotonicity at value > threshold (the minimum ramp step must exceed 0), and gamut at value <= threshold (sRGB channel excess stays within tolerance). pass is authoritative; renderers formatting the comparison switch on gate.

gate

type ThemeGateId

scheme

type ColorSchemeVariant

subject

type string

value

type number

threshold

type number

pass

type boolean

ThemeGateId
#

theme_check.ts view source

ThemeGateId

type "gamut" | "monotonicity" | "contrast"

import type {ThemeGateId} from '@fuzdev/fuz_css/theme_check.js';

Which accessibility gate an entry belongs to.

ThemeIssue
#

theme_validate.ts view source

ThemeIssue import type {ThemeIssue} from '@fuzdev/fuz_css/theme_validate.js';

A structural lint finding. error marks a broken theme (bad shape, unknown variable); warning is advisory (value doesn't match the knob's kind, sits outside its safe range, or is a dark slot on a single-scheme-stanced theme).

level

type "error" | "warning"

message

type string

variable?

type string

ThemeKnob
#

knobs.ts view source

ThemeKnob import type {ThemeKnob} from '@fuzdev/fuz_css/knobs.js';

name

type string

kind

type KnobKind

axis

type KnobAxis

leverage

type KnobLeverage

tier

type KnobTier

range?

The safe envelope for scalar kinds - editor sliders clamp to it, while direct numeric entry may exceed it knowingly.

type [number, number]

step?

type number

values?

Allowed values for the enum kind.

type string[]

hook?

True for knobs consumed by style.css via var() fallbacks instead of being declared in default_variables. Only for knobs whose fallbacks differ per site, so no single declared default exists - heading_font_weight, whose per-tier fallbacks flatten when set.

type boolean

bindable?

True for hue knobs whose default is a palette-letter binding (var(--hue_X)) - the intent and neutral hues. Editors render these as a letter picker with a custom-angle escape, and edits may write either a binding or a literal angle.

type boolean

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, never a mirror or cap entry).

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; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }, options?: ThemeResolverOptions): ThemeResolver

theme

type Theme

options

default {}

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 and cap 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

ThemeResolverOptions
#

theme_resolver.ts view source

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

The derived data a resolver reads beside its theme: the compiled caps from compile_theme. The stance mirror needs no passing, since the resolver derives it from the theme's stance.

caps?

Recomputed worst-hue chroma caps from compile_theme (or compute_theme_caps alone), as _palette_chroma_NN overrides. Rendered last, so they win over the mirror's re-slotted defaults.

type StyleVariable[]

ThemeScheme
#

variable.ts view source

value + type

"dark" | "light" | "dual"

type "dark" | "light" | "dual"

import {ThemeScheme} from '@fuzdev/fuz_css/variable.js';

A theme's scheme stance: which color schemes it supports. 'dual' themes render light and dark appearances from each variable's slots; 'light' and 'dark' themes render that single appearance in both color schemes.

ThemeUncheckedEntry
#

theme_check.ts view source

ThemeUncheckedEntry import type {ThemeUncheckedEntry} from '@fuzdev/fuz_css/theme_check.js';

A gate input the checker couldn't evaluate, so the gates reading it were skipped: a knob or derived stop that doesn't resolve to a number, or a pinned color in a form the gates don't read.

variable

type string

value

type string

reason

type string

to_cache_version
#

css_cache.ts view source

internal

Shared by the cache's load and save.

(versions?: Record<string, string>): string import {to_cache_version} from '@fuzdev/fuz_css/css_cache.js';

Computes the cache version every entry is written with and checked against: the versions of fuz_css and the parsers its extractor runs, so an upgrade of any of them invalidates the cache with no manual bump. In a checkout of fuz_css itself the version doesn't move between commits, so clear .fuz/cache/css and each example's own .fuz directory (or set cache_salt) after changing what extraction produces.

versions

the versions by package name

type Record<string, string>
default load_extraction_versions()

returns

string

the version string, like @fuzdev/fuz_css@1.2.3 svelte@5.0.0 ...

to_chroma_shape_name
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): string import {to_chroma_shape_name} from '@fuzdev/fuz_css/ramps.js';

The private variable holding a stop's normalized chroma shape (_chroma_shape_50).

stop

returns

string

to_extraction_cache_key
#

css_cache.ts view source

internal

Used by the Vite plugin.

(acorn_plugins: AcornPlugin[] | undefined, cache_salt: string | undefined): string | null import {to_extraction_cache_key} from '@fuzdev/fuz_css/css_cache.js';

Computes the part of the cache key that comes from configuration rather than file content: a fingerprint of the configured acorn plugins (their source text) and the consumer's cache_salt, or null when neither is set. A plugin's options live in its closure, where the source text can't see them, so a consumer who changes only a plugin's options bumps cache_salt.

acorn_plugins

the extraction's acorn plugins, if any

type (AcornPlugin)[] | undefined

cache_salt

a consumer string folded into the key, if any

type string | undefined

returns

string | null

the key, or null for the default configuration

to_extraction_id
#

vite_plugin_fuz_css.ts view source

internal

Exported for its tests.

(id: string): string import {to_extraction_id} from '@fuzdev/fuz_css/vite_plugin_fuz_css.js';

Converts a Vite module id to the id its extraction is keyed by, dropping a query made only of Vite's cache-busting parameters - the v version hash the dev server gives a dependency's URL and the t HMR timestamp. Such an id is the file itself, so it's filtered, parsed, cached, and deleted as the plain path, sharing one entry with the same file's SSR transform and pre-scan.

Any other query is kept, because it names a different module than the file: Foo.svelte?svelte&type=style&lang.css is the component's CSS, and ?raw, ?url, and ?worker ids carry a generated wrapper rather than the file's source.

id

a resolved module id, as transform receives it

type string

returns

string

the id without its query when that query only busts a cache, otherwise id unchanged

to_filter_scope
#

file_filter.ts view source

(path: string, root: string): string import {to_filter_scope} from '@fuzdev/fuz_css/file_filter.js';

The part of a file id the default filter's directory checks look at: the path inside its package for a dependency (after node_modules/<pkg>/ or node_modules/@scope/pkg/), the root-relative path for a project file, and the id unchanged outside both (a linked package or a sibling workspace, which a custom filter can judge on its own terms).

path

an absolute file id, or an already relative path

type string

root

the project root, with or without a trailing slash; '' for none

type string

returns

string

the package-relative, root-relative, or unchanged path

to_lightness_stop_name
#

ramps.ts view source

(family: RampFamily, stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): string import {to_lightness_stop_name} from '@fuzdev/fuz_css/ramps.js';

The variable a lightness ramp stop renders through: the endpoint knob itself at 00/100 (palette_lightness_00), else the private derived intermediate (_palette_lightness_30).

family

stop

returns

string

to_modifier_argument_hint
#

modifiers.ts view source

(segment: string): string | null import {to_modifier_argument_hint} from '@fuzdev/fuz_css/modifiers.js';

Describes the argument a parameterized modifier takes, for a segment shaped like one (min-width(...), nth-child(...)) whose argument isn't valid.

segment

type string

returns

string | null

the hint, or null for a segment of any other shape

to_palette_chroma_name
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): string import {to_palette_chroma_name} from '@fuzdev/fuz_css/ramps.js';

The private variable holding a stop's capped palette chroma (_palette_chroma_50).

stop

returns

string

to_property_rank
#

css_class_generation.ts view source

(property: string): number import {to_property_rank} from '@fuzdev/fuz_css/css_class_generation.js';

The cascade rank of a CSS property, so a shorthand emits before the longhands it sets and a longhand class wins where both apply: the depth of its name (padding 0, padding-left 1, border-top-color 2), vendor prefix ignored, with SHORTHAND_RANKS for the shorthands whose longhands don't extend their name. Custom properties rank 0. Properties that aren't shorthand-related can share a rank harmlessly - they never overlap.

property

type string

returns

number

examples

to_property_rank('padding') // 0 to_property_rank('padding-left') // 1 to_property_rank('inset') // -1, below `top`

to_theme_stance
#

theme.ts view source

(scheme: unknown): "dark" | "light" | null import {to_theme_stance} from '@fuzdev/fuz_css/theme.js';

Reads the single-scheme stance a theme's scheme names, or null for a dual-scheme theme. Total over any value, so it reads unvalidated data too.

scheme

a theme's scheme

type unknown

returns

"light" | "dark" | null

try_resolve_literal
#

css_literal.ts view source

(class_name: string, css_properties: Set<string> | null, context_class_name: string): LiteralResolutionResult import {try_resolve_literal} from '@fuzdev/fuz_css/css_literal.js';

Attempts to resolve a class name as an unmodified CSS literal for composition.

Used by resolve_composes to support literals in composes arrays. Returns the declaration if successful, null if not a literal, or an error if it's a literal with issues (modifiers, invalid property, etc.).

class_name

the class name to try resolving

type string

css_properties

set of valid CSS properties, or null to skip validation

type Set<string> | null

context_class_name

the class being defined (for error messages)

type string

returns

LiteralResolutionResult

resolution result with declaration, or error, or null if not a literal

TYPE_SCALE_RATIO
#

variable_data.ts view source

1.272 import {TYPE_SCALE_RATIO} from '@fuzdev/fuz_css/variable_data.js';

The default ratio between font size steps above md, roughly sqrt(golden ratio). In CSS it is the --type_scale_ratio knob those steps derive from.

validate_theme
#

theme_validate.ts view source

(theme: unknown): ThemeIssue[] import {validate_theme} from '@fuzdev/fuz_css/theme_validate.js';

Lints a theme's structure: the Theme schema (errors), a known name per variable (errors, with a warning instead for a contextual hook from style_hooks.ts, which a theme shouldn't set), and advisory type/range warnings for the knob-tier variables - including a pairing warning when an intent hue binds a palette letter whose chroma multiplier differs from the intent's own *_chroma_scale twin (a binding shares only the hue angle, so the slot's chroma character is otherwise silently dropped), and a separation warning when the accent hue lands within ACCENT_STATUS_HUE_SEPARATION of a status hue. Value validation is advisory and never an error. An empty array means the theme is structurally valid.

A shape failure returns on its own: the knob lint reads values the schema hasn't vouched for, so it runs only over a theme that parsed. Takes unknown so untrusted input (a theme restored from storage, a pasted object) needs no cast to be checked.

theme

type unknown

returns

ThemeIssue[]

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.

VariableDependencyGraph
#

variable_graph.ts view source

VariableDependencyGraph import type {VariableDependencyGraph} from '@fuzdev/fuz_css/variable_graph.js';

Dependency graph for style variables.

variables

Map from variable name to its info

type Map<string, StyleVariableInfo>

diagnostics

The uncontained_theme_value errors for the slots left out of the graph, and a baked theme's gate warnings, which resolve_css forwards with every resolution.

type GenerationDiagnostic[]

theme

The build-time theme baked into the graph's values, with the mirror and caps the bake derived for it (see bake_theme), or null for none - what the baked theme sublayer re-renders.

type ResolvedTheme | null

VariablesOption
#

css_plugin_options.ts view source

VariablesOption

type StyleVariable[] | ((defaults: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]) => { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]) | null | undefined

import type {VariablesOption} from '@fuzdev/fuz_css/css_plugin_options.js';

Type for the variables option used by the generator.

Supports four forms:

  • undefined - Use default variables (framework defaults)
  • null - Disable theme generation entirely (explicit opt-out)
  • Array<StyleVariable> - Custom variables array (replaces defaults)
  • (defaults) => Array<StyleVariable> - Callback to modify defaults

See module documentation for the undefined vs null convention.

vite_plugin_fuz_css
#

vite_plugin_fuz_css.ts view source

(options?: VitePluginFuzCssOptions): Plugin<any>[] import {vite_plugin_fuz_css} from '@fuzdev/fuz_css/vite_plugin_fuz_css.js';

Creates the fuz_css Vite plugin.

Extracts CSS classes from source files during Vite's transform phase and generates optimized CSS via the virtual:fuz.css virtual module.

options

default {}

returns

Plugin<any>[]

the plugin as several objects sharing state, to pass to Vite's plugins together: an enforce: 'pre' one that does the extraction, serves the virtual module, and splices the build's CSS ahead of other plugins, a build-only one positioned after Vite's CSS processing that completes the build's stylesheets, and a serve-only enforce: 'post' one that adds the evaluation report to the virtual module's client code

VitePluginFuzCssOptions
#

vite_plugin_fuz_css.ts view source

VitePluginFuzCssOptions import type {VitePluginFuzCssOptions} from '@fuzdev/fuz_css/vite_plugin_fuz_css.js';

Options for the fuz_css Vite plugin. Extends the shared base options with Vite-specific options.

inheritance

prescan?

Dev-only eager pre-scan of source files at server startup.

Extraction state accumulates from Vite's transform hook, so without a pre-scan the first CSS served on a cold start includes only the files the module graph happened to visit first, and the rest arrives as corrective HMR updates while the page loads. The pre-scan extracts every file passing filter_file under the given directories, plus the Vite root's index.html, before the virtual module is first served, so the initial CSS is complete. Warm starts are cheap via the extraction cache.

true scans src under the Vite root; false disables; an array gives custom directories (resolved against the Vite root unless absolute). The root index.html is included whichever directories are given: the dev server serves it without running transform on it, so nothing else would extract it. Pre-scanned files are kept current - one the watcher reports added or changed is extracted again, whether or not any module imports it.

node_modules dependencies are never pre-scanned, and neither are project files outside the scanned directories. They're extracted when the dev server first transforms them, which is during the first load of a page that uses them, so that page's CSS is completed by an update a moment after it's first served rather than up front (or by the next reload, with server.hmr or server.ws off).

What dev and build extract differs at the edges:

  • dev only: files under the scanned directories that no module imports (SvelteKit's src/app.html among them), including ones imported only with ?raw - the pre-scan reads them from disk, where a build extracts just the modules it transforms; and a pre-bundled dependency that's extracted from its bundled code while filter_file rejects the files it ships (the default filter skips .mjs), which a build doesn't extract at all
  • build only: an HTML entry outside the scanned directories other than the root index.html; a module of a pre-bundled dependency that the pre-bundler dropped as unused, such as one holding nothing but a @fuz-classes comment; and the comment hints and static Svelte class attributes of a pre-bundled dependency whose sourcemap is missing or names files that aren't installed, which is extracted from its bundled code instead

type boolean | string[]

default true

wcag_contrast_ratio
#

wcag.ts view source

(a: RgbUnit, b: RgbUnit): number import {wcag_contrast_ratio} from '@fuzdev/fuz_css/wcag.js';

Computes the WCAG 2.x contrast ratio between two gamma-encoded sRGB colors, in [1, 21] regardless of argument order.

a

type RgbUnit

b

type RgbUnit

returns

number

zine_theme
#

themes/zine.ts view source

{ name: string; variables: { name: string; dark?: string | undefined; base?: string | undefined; summary?: string | undefined; }[]; summary?: string | undefined; scheme?: "dark" | "light" | "dual" | undefined; }

type Theme

import {zine_theme} from '@fuzdev/fuz_css/themes/zine.js';

An exemplar theme: the photocopied zine. Structure comes from line and weight alone, since that is all a photocopier reproduces - paper white and toner black with no gray between them, thick opaque borders, square corners, no shadows, heavy grotesque headings set tight, links marked by an underline. The three shortest duration tokens are zero, since print doesn't ease. The palette keeps its full chroma, the spot color run over the black plate.

Dual-scheme: the dark appearance is the same page run as a negative, on a near-black ground that stays inside the contrast modifiers' range, so high contrast still deepens it and panels keep a visible fill. Built from levers only - the palette letters keep their default hues.