/** * Page-level light/dark state, shared by every control that shows or changes it. * * Deliberately not an element: the scheme is one value per document, and a * document can hold several controls for it — a header button, a menu row, a * settings page. Whichever one the user touches, all of them have to agree, so * the state belongs to the page rather than to any of them. * * The model is the one argued in Lea Verou's *Dark mode toggles should be a * two-state switch* (2026): three values — an explicit `light`, an explicit * `dark`, or no preference at all — but only two ever shown. That falls out of * two rules, both implemented here: * * 1. An override is stored **only when it differs from the OS preference**. * Choosing the scheme the OS already reports removes the override instead, * handing control back to the system. So a user on a dark OS who switches to * light and back is following the system again, not pinned to dark — and * "system" stays reachable without a third button. * 2. The stored value is read **only when the user acts**. If the OS flips while * an explicit override exists, the override survives: the user asked for it, * and nothing they did says otherwise. * * SSR-safe: nothing here touches `window`, `document` or `localStorage` at * module scope, and listeners are attached lazily on the first subscription. */ export type ColorScheme = 'light' | 'dark'; /** Called whenever the effective scheme changes, from any source. */ export type ColorSchemeListener = (scheme: ColorScheme, overridden: boolean) => void; /** Where the store writes `color-scheme`, if anywhere. */ export type ColorSchemeApply = 'root' | false; export interface ColorSchemeConfig { /** * `localStorage` key holding the override. Set to `''` to disable persistence * entirely — the choice then lasts for the session only. */ storageKey?: string; /** * Write `color-scheme` on `` when the scheme changes. Off by default: * most applications already own a color-mode story, and silently rewriting * `documentElement` would fight it. Turn it on for a plain page. */ apply?: ColorSchemeApply; } declare class ColorSchemeStore { #private; /** The scheme actually in effect: a stored override, else the OS preference. */ get current(): ColorScheme; /** Whether an override is in place, rather than the OS preference being followed. */ get overridden(): boolean; /** * Choose a scheme. Rule 1 lives here: the override is written only when it * disagrees with the OS, and released when it agrees. */ set(next: ColorScheme): void; /** Flip to the other scheme. Returns the scheme now in effect. */ toggle(): ColorScheme; /** * Observe the effective scheme. The listener is called **immediately with the * current value**, then on a user change, on an OS change with no override in * place, and on a change made in another tab. Returns an unsubscribe function; * the last unsubscribe releases the listeners. * * The immediate call is deliberate. A subscriber's job is almost always to * mirror the scheme somewhere — an `aria-pressed`, a `checked`, a class — and * a change-only contract leaves that mirror wrong until the first change, * which is a bug nobody sees until a screen reader hits it. Callers that only * want transitions can ignore the first call. */ subscribe(listener: ColorSchemeListener): () => void; /** Set the storage key and whether the store writes `color-scheme` on ``. */ configure(config: ColorSchemeConfig): void; } /** The document's light/dark state. One instance per page. */ export declare const colorScheme: ColorSchemeStore; export {}; //# sourceMappingURL=color-scheme.d.ts.map