The dot is drawn over all five cell backgrounds, so it cannot borrow one of their colours; it defaults to the theme foreground with a background ring and now takes two overrides of its own, worked and confirmed, alongside the rest of the matrix palette.
72 lines
3.3 KiB
TypeScript
72 lines
3.3 KiB
TypeScript
// Operator overrides for the band/mode matrix palette.
|
|
//
|
|
// Applied as inline custom properties on <html>, which is what lets them be
|
|
// OVERRIDES rather than a palette: the twelve themes each define their own
|
|
// --mx-* ramp in style.css, an inline value wins over all of them, and removing
|
|
// it hands the colour straight back to the theme. Nothing has to know which
|
|
// theme is active, and switching theme with overrides off is a clean revert.
|
|
|
|
export type MatrixColors = {
|
|
enabled: boolean;
|
|
call_confirmed: string;
|
|
call_worked: string;
|
|
entity_confirmed: string;
|
|
entity_worked: string;
|
|
not_worked: string;
|
|
current_entry: string;
|
|
mark_worked: string;
|
|
mark_confirmed: string;
|
|
};
|
|
|
|
// The settings fields and the CSS custom property each one drives. Also the
|
|
// display order — the same order the legend under the matrix reads in, so the
|
|
// settings panel and the grid can never disagree about which green is which.
|
|
export const MATRIX_VARS: { key: keyof Omit<MatrixColors, 'enabled'>; cssVar: string; label: string }[] = [
|
|
{ key: 'call_confirmed', cssVar: '--mx-call-conf', label: 'mx.callConf' },
|
|
{ key: 'call_worked', cssVar: '--mx-call-work', label: 'mx.callWork' },
|
|
{ key: 'entity_confirmed', cssVar: '--mx-dx-conf', label: 'mx.dxConf' },
|
|
{ key: 'entity_worked', cssVar: '--mx-dx-work', label: 'mx.dxWork' },
|
|
{ key: 'not_worked', cssVar: '--mx-none', label: 'mx.none' },
|
|
{ key: 'current_entry', cssVar: '--mx-cur', label: 'mx.current' },
|
|
{ key: 'mark_worked', cssVar: '--mx-mark-work', label: 'mx.markWork' },
|
|
{ key: 'mark_confirmed', cssVar: '--mx-mark-conf', label: 'mx.markConf' },
|
|
];
|
|
|
|
export const emptyMatrixColors = (): MatrixColors => ({
|
|
enabled: false,
|
|
call_confirmed: '', call_worked: '', entity_confirmed: '',
|
|
entity_worked: '', not_worked: '', current_entry: '',
|
|
mark_worked: '', mark_confirmed: '',
|
|
});
|
|
|
|
// applyMatrixColors stamps (or clears) the overrides on <html>. Safe to call as
|
|
// often as you like — it is the whole rendering path, so the settings panel uses
|
|
// it for a live preview and the app uses it once at startup.
|
|
export function applyMatrixColors(c?: MatrixColors | null): void {
|
|
const root = document.documentElement;
|
|
for (const { key, cssVar } of MATRIX_VARS) {
|
|
const v = c?.enabled ? String(c[key] ?? '').trim() : '';
|
|
if (v) root.style.setProperty(cssVar, v);
|
|
else root.style.removeProperty(cssVar);
|
|
}
|
|
}
|
|
|
|
// effectiveMatrixColor reads what the matrix is ACTUALLY painting right now —
|
|
// the override if there is one, else the active theme's value. It is what seeds
|
|
// the colour pickers, so the operator starts from the colours in front of them
|
|
// instead of from a hardcoded palette that may belong to a different theme.
|
|
//
|
|
// A custom property's computed value has its var() references substituted, so
|
|
// --mx-cur resolves to the theme's --warning rather than to the literal text.
|
|
export function effectiveMatrixColor(cssVar: string): string {
|
|
try {
|
|
const v = getComputedStyle(document.documentElement).getPropertyValue(cssVar).trim();
|
|
// <input type="color"> only accepts #rrggbb. Anything else (a theme that
|
|
// ever moves to oklch, an empty read during boot) falls back to mid grey
|
|
// rather than silently resetting the picker to black.
|
|
return /^#[0-9a-f]{6}$/i.test(v) ? v.toLowerCase() : '#808080';
|
|
} catch {
|
|
return '#808080';
|
|
}
|
|
}
|