mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-05 19:24:39 +00:00
add handlers for individual Channels
This commit is contained in:
+2
-1
@@ -22,4 +22,5 @@ betterseqtaplus-safari/
|
||||
.parcel-cache
|
||||
.env
|
||||
.env.submit
|
||||
dependency-graph.svg
|
||||
dependency-graph.svg
|
||||
/src/resources/themes
|
||||
|
||||
@@ -5,7 +5,7 @@ import { lightenAndPaleColor } from "./lightenAndPaleColor";
|
||||
import ColorLuminance from "./ColorLuminance";
|
||||
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||
import { getAdaptiveColour } from "@/seqta/utils/adaptiveThemeColour";
|
||||
import { getCustomThemeAdaptiveCssVariables } from "@/seqta/ui/colors/customThemeAdaptiveBindings";
|
||||
import { getCustomThemeAdaptiveCssVariableBindings } from "@/seqta/ui/colors/customThemeAdaptiveBindings";
|
||||
|
||||
import darkLogo from "@/resources/icons/betterseqta-light-full.png";
|
||||
import lightLogo from "@/resources/icons/betterseqta-dark-full.png";
|
||||
@@ -84,6 +84,21 @@ function cancelColorTransition() {
|
||||
}
|
||||
}
|
||||
|
||||
function getRepresentativeRgbChannels(s: string): { r: number; g: number; b: number } | null {
|
||||
const parsedHex = parseRepresentativeHex(s);
|
||||
if (!parsedHex) return null;
|
||||
try {
|
||||
const [r, g, b] = Color(parsedHex).rgb().array();
|
||||
return {
|
||||
r: Math.round(r),
|
||||
g: Math.round(g),
|
||||
b: Math.round(b),
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function applyColorsWith(selectedColor: string) {
|
||||
if (settingsState.transparencyEffects) {
|
||||
document.documentElement.classList.add("transparencyEffects");
|
||||
@@ -129,8 +144,24 @@ function applyColorsWith(selectedColor: string) {
|
||||
applyProperties({ ...commonProps, ...modeProps, ...dynamicProps });
|
||||
|
||||
if (settingsState.selectedTheme) {
|
||||
for (const name of getCustomThemeAdaptiveCssVariables()) {
|
||||
setCSSVar(name, selectedColor);
|
||||
const channels = getRepresentativeRgbChannels(selectedColor);
|
||||
for (const binding of getCustomThemeAdaptiveCssVariableBindings()) {
|
||||
if (!binding.channel) {
|
||||
setCSSVar(binding.cssVarName, selectedColor);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!channels) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (binding.channel === "r") {
|
||||
setCSSVar(binding.cssVarName, String(channels.r));
|
||||
} else if (binding.channel === "g") {
|
||||
setCSSVar(binding.cssVarName, String(channels.g));
|
||||
} else {
|
||||
setCSSVar(binding.cssVarName, String(channels.b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,49 @@
|
||||
/** Tracks which author-declared CSS variables mirror the effective accent; not persisted in settings storage. */
|
||||
|
||||
const VALID_CUSTOM_PROP = /^--[a-zA-Z0-9_-]{1,120}$/;
|
||||
const VALID_CHANNEL = /^(r|g|b)$/;
|
||||
|
||||
let boundNames: string[] = [];
|
||||
export type AdaptiveChannel = "r" | "g" | "b";
|
||||
|
||||
export function normalizeAdaptiveCssVariableNames(
|
||||
export type AdaptiveCssVariableBinding = {
|
||||
cssVarName: string;
|
||||
channel?: AdaptiveChannel;
|
||||
};
|
||||
|
||||
let boundBindings: AdaptiveCssVariableBinding[] = [];
|
||||
|
||||
function parseAdaptiveBinding(
|
||||
rawBinding: string,
|
||||
): AdaptiveCssVariableBinding | null {
|
||||
const trimmed = rawBinding.trim();
|
||||
if (!trimmed) return null;
|
||||
|
||||
const [rawName, rawChannel] = trimmed.split(":", 2);
|
||||
const cssVarName = rawName?.trim() ?? "";
|
||||
if (!VALID_CUSTOM_PROP.test(cssVarName)) return null;
|
||||
|
||||
if (!rawChannel) return { cssVarName };
|
||||
|
||||
const channel = rawChannel.trim().toLowerCase();
|
||||
if (!VALID_CHANNEL.test(channel)) return null;
|
||||
|
||||
return { cssVarName, channel: channel as AdaptiveChannel };
|
||||
}
|
||||
|
||||
export function normalizeAdaptiveCssVariableBindings(
|
||||
names: string[] | undefined,
|
||||
): string[] {
|
||||
): AdaptiveCssVariableBinding[] {
|
||||
if (!names?.length) return [];
|
||||
const out: string[] = [];
|
||||
const out: AdaptiveCssVariableBinding[] = [];
|
||||
const seen = new Set<string>();
|
||||
|
||||
for (const raw of names) {
|
||||
const s = raw.trim();
|
||||
if (!VALID_CUSTOM_PROP.test(s) || seen.has(s)) continue;
|
||||
seen.add(s);
|
||||
out.push(s);
|
||||
const parsed = parseAdaptiveBinding(raw);
|
||||
if (!parsed) continue;
|
||||
const key = `${parsed.cssVarName}:${parsed.channel ?? "full"}`;
|
||||
if (seen.has(key)) continue;
|
||||
seen.add(key);
|
||||
out.push(parsed);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -22,19 +51,24 @@ export function normalizeAdaptiveCssVariableNames(
|
||||
export function setCustomThemeAdaptiveCssVariables(
|
||||
names: string[] | undefined,
|
||||
): void {
|
||||
for (const n of boundNames) {
|
||||
document.documentElement.style.removeProperty(n);
|
||||
for (const binding of boundBindings) {
|
||||
document.documentElement.style.removeProperty(binding.cssVarName);
|
||||
}
|
||||
boundNames = normalizeAdaptiveCssVariableNames(names);
|
||||
boundBindings = normalizeAdaptiveCssVariableBindings(names);
|
||||
}
|
||||
|
||||
export function getCustomThemeAdaptiveCssVariableBindings(): AdaptiveCssVariableBinding[] {
|
||||
return boundBindings;
|
||||
}
|
||||
|
||||
// Backward-compatible helper for existing callsites.
|
||||
export function getCustomThemeAdaptiveCssVariables(): string[] {
|
||||
return boundNames;
|
||||
return boundBindings.map((b) => b.cssVarName);
|
||||
}
|
||||
|
||||
export function clearCustomThemeAdaptiveCssVariables(): void {
|
||||
for (const n of boundNames) {
|
||||
document.documentElement.style.removeProperty(n);
|
||||
for (const binding of boundBindings) {
|
||||
document.documentElement.style.removeProperty(binding.cssVarName);
|
||||
}
|
||||
boundNames = [];
|
||||
boundBindings = [];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user