import * as React from "react"; import { useTranslation } from "react-i18next"; import { CUSTOM_THEME_VARS, type CustomTheme, type CustomThemeVar, } from "~/db/tables"; import { ACCENT_CHROMA_MULTIPLIERS, BASE_CHROMA_MULTIPLIERS, clampThemeToGamut, type ThemeInput, } from "~/utils/oklch-gamut"; import { THEME_INPUT_LIMITS } from "~/utils/zod"; import styles from "./CustomThemeSelector.module.css"; import { LinkButton, SendouButton } from "./elements/Button"; import { Label } from "./Label"; const COLOR_SLIDERS = [ { id: "base-hue", inputKey: "baseHue", min: THEME_INPUT_LIMITS.BASE_HUE_MIN, max: THEME_INPUT_LIMITS.BASE_HUE_MAX, step: 1, labelKey: "baseHue", isHue: true, }, { id: "base-chroma", inputKey: "baseChroma", min: THEME_INPUT_LIMITS.BASE_CHROMA_MIN, max: THEME_INPUT_LIMITS.BASE_CHROMA_MAX, step: 0.001, labelKey: "baseChroma", isHue: false, }, { id: "accent-hue", inputKey: "accentHue", min: THEME_INPUT_LIMITS.ACCENT_HUE_MIN, max: THEME_INPUT_LIMITS.ACCENT_HUE_MAX, step: 1, labelKey: "accentHue", isHue: true, }, { id: "accent-chroma", inputKey: "accentChroma", min: THEME_INPUT_LIMITS.ACCENT_CHROMA_MIN, max: THEME_INPUT_LIMITS.ACCENT_CHROMA_MAX, step: 0.01, labelKey: "accentChroma", isHue: false, }, ] as const; type ThemeInputKey = (typeof COLOR_SLIDERS)[number]["inputKey"]; export const DEFAULT_THEME_INPUT: ThemeInput = { baseHue: 260, baseChroma: 0.012, accentHue: 270, accentChroma: 0.24, }; export function themeInputFromCustomTheme( customTheme: CustomTheme, ): ThemeInput { return { baseHue: customTheme["--base-h"] ?? DEFAULT_THEME_INPUT.baseHue, baseChroma: (customTheme["--base-c-1"] ?? 0) / BASE_CHROMA_MULTIPLIERS[1] || DEFAULT_THEME_INPUT.baseChroma, accentHue: customTheme["--acc-h"] ?? DEFAULT_THEME_INPUT.accentHue, accentChroma: (customTheme["--acc-c-1"] ?? 0) / ACCENT_CHROMA_MULTIPLIERS[1] || DEFAULT_THEME_INPUT.accentChroma, }; } function applyThemeInput(input: ThemeInput) { const clampedTheme = clampThemeToGamut(input); for (const [key, value] of Object.entries(clampedTheme)) { document.documentElement.style.setProperty(key, String(value)); } } function ColorSlider({ id, inputKey, min, max, step, label, isHue, value, onChange, }: { id: string; inputKey: ThemeInputKey; min: number; max: number; step: number; label: string; isHue: boolean; value: number; onChange: (inputKey: ThemeInputKey, value: number) => void; }) { return (
{t("common:settings.customTheme.patreonText")}