NODEDC_DESIGN_GUIDELINE/packages/ui-core/src/theme.ts

73 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { createAccentVariables, type RgbTuple } from "./accent.js";
export type NodedcTheme = "dark" | "light";
export interface NodedcMaterial {
/** Base fill used by glass panels, application windows and modals. */
panel?: RgbTuple;
/** 01 alpha for the base glass panel. */
panelOpacity?: number;
/** Base fill used by text, range and selection fields. */
field?: RgbTuple;
/** 01 alpha for field fill. */
fieldOpacity?: number;
}
export interface ApplyThemeOptions {
theme?: NodedcTheme;
accent?: RgbTuple;
material?: NodedcMaterial;
}
function formatRgb([red, green, blue]: RgbTuple): string {
return `${red} ${green} ${blue}`;
}
function clampOpacity(value: number): number {
return Math.max(0, Math.min(1, value));
}
export function applyNodedcTheme(
target: HTMLElement,
{ theme = "dark", accent, material }: ApplyThemeOptions = {},
): void {
target.dataset.nodedcTheme = theme;
target.dataset.nodedcUi = "true";
if (accent) {
const variables = createAccentVariables(accent);
Object.entries(variables).forEach(([property, value]) => {
target.style.setProperty(property, value);
});
}
if (!material) return;
if (material.panel) target.style.setProperty("--nodedc-panel-material-rgb", formatRgb(material.panel));
if (typeof material.panelOpacity === "number" && Number.isFinite(material.panelOpacity)) {
const opacity = clampOpacity(material.panelOpacity);
target.style.setProperty("--nodedc-panel-material-opacity", String(opacity));
target.style.setProperty("--nodedc-panel-material-strong-opacity", String(clampOpacity(opacity + 0.12)));
target.style.setProperty("--nodedc-panel-material-soft-opacity", String(clampOpacity(Math.max(0.12, opacity - 0.2))));
}
if (material.field) target.style.setProperty("--nodedc-field-material-rgb", formatRgb(material.field));
if (typeof material.fieldOpacity === "number" && Number.isFinite(material.fieldOpacity)) {
target.style.setProperty("--nodedc-field-material-opacity", String(clampOpacity(material.fieldOpacity)));
}
}
export function clearNodedcAccent(target: HTMLElement): void {
target.style.removeProperty("--nodedc-accent-rgb");
target.style.removeProperty("--nodedc-on-accent-rgb");
}
export function clearNodedcMaterial(target: HTMLElement): void {
[
"--nodedc-panel-material-rgb",
"--nodedc-panel-material-opacity",
"--nodedc-panel-material-strong-opacity",
"--nodedc-panel-material-soft-opacity",
"--nodedc-field-material-rgb",
"--nodedc-field-material-opacity",
].forEach((property) => target.style.removeProperty(property));
}