Refine glass material and environment controls

This commit is contained in:
DCCONSTRUCTIONS
2026-07-10 21:05:04 +03:00
parent 4c74c22a6e
commit 0e030136bb
9 changed files with 350 additions and 112 deletions
+50 -6
View File
@@ -2,23 +2,57 @@ 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 }: ApplyThemeOptions = {},
{ theme = "dark", accent, material }: ApplyThemeOptions = {},
): void {
target.dataset.nodedcTheme = theme;
target.dataset.nodedcUi = "true";
if (!accent) return;
const variables = createAccentVariables(accent);
Object.entries(variables).forEach(([property, value]) => {
target.style.setProperty(property, value);
});
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 {
@@ -26,3 +60,13 @@ export function clearNodedcAccent(target: HTMLElement): void {
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));
}