/** Общая тема зоотех-страниц: localStorage + переключатель #wespThemePicker */ export const THEME_KEY = "theme"; export const HIGH_CONTRAST_KEY = "wespHighContrast"; export const THEMES = ["light", "organic", "dark"]; /** @deprecated Админка всегда ultra-dark; ключ оставлен для совместимости zootech-тем. */ export const ADMIN_ULTRA_DARK_KEY = "wespAdminUltraDark"; const THEME_LABELS = { light: "Светлая", organic: "Зелёная", dark: "Тёмная", }; export function getTheme() { const saved = localStorage.getItem(THEME_KEY); if (THEMES.includes(saved)) return saved; return "dark"; } /** Ручной выбор в настройках; иначе — системный prefers-contrast. */ export function resolveHighContrast() { try { const saved = localStorage.getItem(HIGH_CONTRAST_KEY); if (saved === "1") return true; if (saved === "0") return false; } catch { /* ignore */ } return globalThis.matchMedia?.("(prefers-contrast: more)")?.matches ?? false; } export function getHighContrast() { return resolveHighContrast(); } export function applyHighContrast(on) { document.documentElement.dataset.highContrast = on ? "true" : "false"; } export function setHighContrast(on) { try { localStorage.setItem(HIGH_CONTRAST_KEY, on ? "1" : "0"); } catch { /* ignore */ } applyHighContrast(!!on); syncHighContrastUI(); } export function applyTheme(theme) { document.documentElement.dataset.theme = theme; } export function setTheme(theme) { if (!THEMES.includes(theme)) return; if (theme === "light" || theme === "organic") { try { localStorage.removeItem(ADMIN_ULTRA_DARK_KEY); } catch (e) { /* ignore */ } } localStorage.setItem(THEME_KEY, theme); applyTheme(theme); syncThemePickerUI(); } function syncThemePickerUI() { const mount = document.getElementById("wespThemePicker"); if (!mount) return; const current = getTheme(); mount.querySelectorAll("[data-theme-value]").forEach((btn) => { const active = btn.dataset.themeValue === current; btn.classList.toggle("is-active", active); btn.setAttribute("aria-checked", active ? "true" : "false"); }); } function syncHighContrastUI() { const el = document.getElementById("wespHighContrastToggle"); if (!el) return; const on = getHighContrast(); el.checked = on; el.setAttribute("aria-checked", on ? "true" : "false"); } /** Сегментированный переключатель тем (3 варианта). */ export function initThemePicker() { const mount = document.getElementById("wespThemePicker"); if (!mount) return; if (mount.dataset.bound !== "1") { mount.dataset.bound = "1"; mount.classList.add("theme-picker"); mount.innerHTML = THEMES.map( (id) => `` ).join(""); mount.addEventListener("click", (e) => { const btn = e.target.closest("[data-theme-value]"); if (!btn) return; setTheme(btn.dataset.themeValue); }); } syncThemePickerUI(); } /** Переключатель усиленного контраста (под выбором темы). */ export function initHighContrastToggle() { const el = document.getElementById("wespHighContrastToggle"); if (!el) return; if (el.dataset.bound !== "1") { el.dataset.bound = "1"; el.addEventListener("change", () => setHighContrast(el.checked)); } syncHighContrastUI(); } /** @deprecated Используйте initThemePicker. Оставлен для обратной совместимости. */ export function initThemeToggle() { if (document.getElementById("wespThemePicker")) { initThemePicker(); return; } const el = document.getElementById("darkThemeToggle"); if (!el) return; if (el.dataset.bound === "1") { el.checked = document.documentElement.dataset.theme === "dark"; return; } el.dataset.bound = "1"; el.checked = document.documentElement.dataset.theme === "dark"; el.addEventListener("change", () => { setTheme(el.checked ? "dark" : "light"); }); }