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:
@@ -23,3 +23,4 @@ betterseqtaplus-safari/
|
|||||||
.env
|
.env
|
||||||
.env.submit
|
.env.submit
|
||||||
dependency-graph.svg
|
dependency-graph.svg
|
||||||
|
/src/resources/themes
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { lightenAndPaleColor } from "./lightenAndPaleColor";
|
|||||||
import ColorLuminance from "./ColorLuminance";
|
import ColorLuminance from "./ColorLuminance";
|
||||||
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||||
import { getAdaptiveColour } from "@/seqta/utils/adaptiveThemeColour";
|
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 darkLogo from "@/resources/icons/betterseqta-light-full.png";
|
||||||
import lightLogo from "@/resources/icons/betterseqta-dark-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) {
|
function applyColorsWith(selectedColor: string) {
|
||||||
if (settingsState.transparencyEffects) {
|
if (settingsState.transparencyEffects) {
|
||||||
document.documentElement.classList.add("transparencyEffects");
|
document.documentElement.classList.add("transparencyEffects");
|
||||||
@@ -129,8 +144,24 @@ function applyColorsWith(selectedColor: string) {
|
|||||||
applyProperties({ ...commonProps, ...modeProps, ...dynamicProps });
|
applyProperties({ ...commonProps, ...modeProps, ...dynamicProps });
|
||||||
|
|
||||||
if (settingsState.selectedTheme) {
|
if (settingsState.selectedTheme) {
|
||||||
for (const name of getCustomThemeAdaptiveCssVariables()) {
|
const channels = getRepresentativeRgbChannels(selectedColor);
|
||||||
setCSSVar(name, 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. */
|
/** 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_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,
|
names: string[] | undefined,
|
||||||
): string[] {
|
): AdaptiveCssVariableBinding[] {
|
||||||
if (!names?.length) return [];
|
if (!names?.length) return [];
|
||||||
const out: string[] = [];
|
const out: AdaptiveCssVariableBinding[] = [];
|
||||||
const seen = new Set<string>();
|
const seen = new Set<string>();
|
||||||
|
|
||||||
for (const raw of names) {
|
for (const raw of names) {
|
||||||
const s = raw.trim();
|
const parsed = parseAdaptiveBinding(raw);
|
||||||
if (!VALID_CUSTOM_PROP.test(s) || seen.has(s)) continue;
|
if (!parsed) continue;
|
||||||
seen.add(s);
|
const key = `${parsed.cssVarName}:${parsed.channel ?? "full"}`;
|
||||||
out.push(s);
|
if (seen.has(key)) continue;
|
||||||
|
seen.add(key);
|
||||||
|
out.push(parsed);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -22,19 +51,24 @@ export function normalizeAdaptiveCssVariableNames(
|
|||||||
export function setCustomThemeAdaptiveCssVariables(
|
export function setCustomThemeAdaptiveCssVariables(
|
||||||
names: string[] | undefined,
|
names: string[] | undefined,
|
||||||
): void {
|
): void {
|
||||||
for (const n of boundNames) {
|
for (const binding of boundBindings) {
|
||||||
document.documentElement.style.removeProperty(n);
|
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[] {
|
export function getCustomThemeAdaptiveCssVariables(): string[] {
|
||||||
return boundNames;
|
return boundBindings.map((b) => b.cssVarName);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clearCustomThemeAdaptiveCssVariables(): void {
|
export function clearCustomThemeAdaptiveCssVariables(): void {
|
||||||
for (const n of boundNames) {
|
for (const binding of boundBindings) {
|
||||||
document.documentElement.style.removeProperty(n);
|
document.documentElement.style.removeProperty(binding.cssVarName);
|
||||||
}
|
}
|
||||||
boundNames = [];
|
boundBindings = [];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user