"use client"; import { useEffect, useState } from "react"; import { Moon, Sun } from "lucide-react"; import { Button } from "@/components/ui/Button"; import { DEFAULT_THEME_MODE, THEME_STORAGE_KEY, nextThemeMode, normalizeThemeMode, themeModeLabel, themeToggleLabel, type ThemeMode, } from "@/lib/ui/theme"; function applyThemeMode(mode: ThemeMode) { document.documentElement.dataset.theme = mode; } function readStoredThemeMode(): ThemeMode { try { return normalizeThemeMode(window.localStorage.getItem(THEME_STORAGE_KEY)); } catch { return DEFAULT_THEME_MODE; } } // 初始模式直接读 ThemeScript 在水合前写入的 ,避免夜读首帧渲染错误图标。 // SSR 守卫:服务端无 document → 回落默认(与 ThemeScript 的默认一致)。 function initialThemeMode(): ThemeMode { if (typeof document === "undefined") return DEFAULT_THEME_MODE; return normalizeThemeMode(document.documentElement.dataset.theme); } function writeStoredThemeMode(mode: ThemeMode) { try { window.localStorage.setItem(THEME_STORAGE_KEY, mode); } catch { // 存储不可用时仍允许本次页面会话切换主题。 } } export function ThemeToggle() { const [mode, setMode] = useState(initialThemeMode); useEffect(() => { // 水合后以 localStorage 为权威源校正(dataset 已由 ThemeScript 同样依据写入,通常一致)。 const initial = readStoredThemeMode(); setMode(initial); applyThemeMode(initial); }, []); const toggle = () => { setMode((current) => { const next = nextThemeMode(current); writeStoredThemeMode(next); applyThemeMode(next); return next; }); }; const Icon = mode === "night" ? Sun : Moon; return ( ); }