tmp/webapp-docs/frontend/theme/applyTheme.js

/**
 * The pure side-effect layer for theming: resolve a mode to a concrete base and
 * write it to `<html data-theme>`. Kept dependency-free (no React) so it can run
 * from the provider, from tests, and — in spirit — mirrors the inline boot
 * script in index.html.
 * @module gui/theme/applyTheme
 */
import { normalizeMode } from "./config.js";

/** True when the OS currently prefers a light color scheme. */
export function prefersLight() {
  return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-color-scheme: light)").matches;
}

/**
 * Resolve a mode (`system` | `dark` | `light`) to a concrete base
 * (`dark` | `light`). `system` follows the OS via `prefersLight()`.
 */
export function resolveMode(mode) {
  const m = normalizeMode(mode);
  if (m === "dark" || m === "light") return m;
  return prefersLight() ? "light" : "dark";
}

/**
 * Apply the theme to `<html>` by setting `data-theme` to the resolved base.
 * Returns the resolved base so callers can track it. No-op without a document.
 */
export function applyTheme(mode) {
  const resolved = resolveMode(mode);
  if (typeof document !== "undefined") {
    document.documentElement.setAttribute("data-theme", resolved);
  }
  return resolved;
}

/**
 * Apply the accent to `<html data-accent>`. The id is trusted (the caller — the
 * ThemeProvider — validates against built-in ∪ user-theme ids first, since user
 * themes are valid too). Returns the applied id. No-op without a document.
 */
export function applyAccent(accent) {
  if (typeof document !== "undefined") {
    document.documentElement.setAttribute("data-accent", accent);
  }
  return accent;
}