mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
- Web: base bundles built from the app's entry at start (content-hashed, served forever), plugin scripts that register themselves and one combined file, WebScripts/TuiScripts showing the current set, startPage with the connection loop, in-place plugin reloads and a reload on a new base bundle. - React bindings: HostProvider, useHold, useWatch, useRegistry, useRefState. - Terminal: startTerminal, a launcher that signs in with a token, a token file or device pairing and always runs the app's terminal code in a sandboxed child process (pipes, empty environment, --permission granting nothing, no SQLite, a builtin allowlist and a frozen process inside); output filter, confirmed copy/open/attach actions; startTerminalRuntime and TuiScope inside. - Themes: the Themes registry, ThemeChoice per principal, CSS variables on the page, terminal colours by role; CSS modules in plugin builds. - App kit: startServer gains web and tui; startApp renamed startServer, exportAddress/importAddress renamed exportData/importData and export no longer stops the worker; ephemeral sessions end with their client's last link. - Examples 56-web, 57-tui, 58-themes, 59-chat.
38 lines
1.8 KiB
TypeScript
38 lines
1.8 KiB
TypeScript
/// <reference lib="dom" />
|
|
// The page's themes (slice 11 §4b, decision "Looks and themes"): the active theme written as CSS custom properties on
|
|
// `:root` (and `color-scheme`), following the registry, the user's pick and the system's colour scheme; no reload. The
|
|
// app's stylesheet and the plugins' CSS read the variables.
|
|
|
|
import type { Context } from "../context/index.ts";
|
|
import type { Principal } from "../next/data/index.ts";
|
|
import type { Host } from "../next/host/index.ts";
|
|
import { followActiveTheme, themeVariables } from "../next/surfaces/index.ts";
|
|
|
|
/** Follows the themes on `host` and writes the active one on `:root` until the returned stop. */
|
|
export async function followThemes<P extends Principal>(host: Host<P>, context: Context): Promise<() => void> {
|
|
const scheme = matchMedia("(prefers-color-scheme: dark)");
|
|
let written: readonly string[] = [];
|
|
const follower = await followActiveTheme(
|
|
host,
|
|
scheme.matches ? "dark" : "light",
|
|
(theme) => {
|
|
written = writeVariables(themeVariables(theme), written);
|
|
document.documentElement.style.colorScheme = theme.mode;
|
|
},
|
|
context,
|
|
);
|
|
const schemeChanged = (): void => follower.setMode(scheme.matches ? "dark" : "light");
|
|
scheme.addEventListener("change", schemeChanged);
|
|
return () => {
|
|
follower.stop();
|
|
scheme.removeEventListener("change", schemeChanged);
|
|
};
|
|
}
|
|
|
|
/** Sets `variables` on `:root`, removing those of `before` it no longer has; the names it set. */
|
|
function writeVariables(variables: Readonly<Record<string, string>>, before: readonly string[]): readonly string[] {
|
|
const style = document.documentElement.style;
|
|
for (const name of before) if (!Object.hasOwn(variables, name)) style.removeProperty(name);
|
|
for (const [name, value] of Object.entries(variables)) style.setProperty(name, value);
|
|
return Object.keys(variables);
|
|
}
|