Spaces:
Runtime error
Runtime error
| "use client" | |
| export const ACCENT_STORAGE_KEY = "tans-agents:accent-color" | |
| export const DENSITY_STORAGE_KEY = "tans:density" | |
| export type Density = "compact" | "cozy" | "comfortable" | |
| export interface AccentPreset { | |
| name: string | |
| label: string | |
| hsl: string | |
| } | |
| export const ACCENT_PRESETS: AccentPreset[] = [ | |
| { name: "blue", label: "Xanh dương", hsl: "221 83% 53%" }, | |
| { name: "purple", label: "Tím", hsl: "262 83% 58%" }, | |
| { name: "pink", label: "Hồng", hsl: "330 81% 60%" }, | |
| { name: "red", label: "Đỏ", hsl: "0 84% 60%" }, | |
| { name: "orange", label: "Cam", hsl: "24 95% 53%" }, | |
| { name: "amber", label: "Hổ phách", hsl: "38 92% 50%" }, | |
| { name: "green", label: "Xanh lá", hsl: "142 71% 45%" }, | |
| { name: "teal", label: "Xanh teal", hsl: "173 80% 40%" }, | |
| { name: "cyan", label: "Xanh cyan", hsl: "189 94% 43%" }, | |
| { name: "indigo", label: "Chàm", hsl: "239 84% 67%" }, | |
| ] | |
| const HSL_PATTERN = /^\s*(\d+(?:\.\d+)?)\s+((?:\d+(?:\.\d+)?)%)\s+((?:\d+(?:\.\d+)?)%)\s*$/ | |
| const DENSITIES: Density[] = ["compact", "cozy", "comfortable"] | |
| export function normalizeHsl(value: string): string | null { | |
| const match = value.match(HSL_PATTERN) | |
| if (!match) return null | |
| const hue = Math.min(360, Math.max(0, Number(match[1]))) | |
| return `${Math.round(hue)} ${match[2]} ${match[3]}` | |
| } | |
| export function normalizeDensity(value: unknown): Density { | |
| return typeof value === "string" && DENSITIES.includes(value as Density) ? (value as Density) : "cozy" | |
| } | |
| export function getStoredAccent(): string | null { | |
| if (typeof window === "undefined") return null | |
| return normalizeHsl(window.localStorage.getItem(ACCENT_STORAGE_KEY) ?? "") | |
| } | |
| export function getStoredDensity(): Density { | |
| if (typeof window === "undefined") return "cozy" | |
| return normalizeDensity(window.localStorage.getItem(DENSITY_STORAGE_KEY)) | |
| } | |
| export function saveAccent(hsl: string) { | |
| const normalized = normalizeHsl(hsl) | |
| if (!normalized || typeof window === "undefined") return false | |
| window.localStorage.setItem(ACCENT_STORAGE_KEY, normalized) | |
| applyAccent(normalized) | |
| return true | |
| } | |
| export function saveDensity(density: Density) { | |
| if (typeof window === "undefined") return false | |
| const normalized = normalizeDensity(density) | |
| window.localStorage.setItem(DENSITY_STORAGE_KEY, normalized) | |
| applyDensity(normalized) | |
| return true | |
| } | |
| export function clearAccent() { | |
| if (typeof window === "undefined") return | |
| window.localStorage.removeItem(ACCENT_STORAGE_KEY) | |
| const root = window.document.documentElement | |
| root.style.removeProperty("--primary") | |
| root.style.removeProperty("--accent") | |
| root.style.removeProperty("--ring") | |
| } | |
| export function applyStoredAccent() { | |
| const hsl = getStoredAccent() | |
| if (hsl) applyAccent(hsl) | |
| } | |
| export function applyStoredDensity() { | |
| applyDensity(getStoredDensity()) | |
| } | |
| export function applyAccent(hsl: string) { | |
| if (typeof window === "undefined") return | |
| const normalized = normalizeHsl(hsl) | |
| if (!normalized) return | |
| const root = window.document.documentElement | |
| root.style.setProperty("--primary", normalized) | |
| root.style.setProperty("--ring", normalized) | |
| root.style.setProperty("--accent", softenAccent(normalized, root.classList.contains("dark"))) | |
| } | |
| export function applyDensity(density: Density) { | |
| if (typeof window === "undefined") return | |
| window.document.documentElement.dataset.density = normalizeDensity(density) | |
| } | |
| function softenAccent(hsl: string, isDark: boolean): string { | |
| const match = hsl.match(HSL_PATTERN) | |
| if (!match) return hsl | |
| const hue = match[1] | |
| const saturation = match[2] | |
| return `${hue} ${saturation} ${isDark ? "18%" : "94%"}` | |
| } |