/** * OpenBridge 主题管理 Hook * * 管理 data-obc-theme 属性,支持 day/dusk/night/bright 四种主题。 * 主题选择会持久化到 localStorage。 */ import { useCallback, useEffect, useState } from 'react' /** 支持的 OpenBridge 主题类型 */ export type ObcTheme = 'day' | 'dusk' | 'night' | 'bright' /** 主题列表,用于循环切换 */ const THEMES: readonly ObcTheme[] = ['day', 'dusk', 'night', 'bright'] as const /** localStorage 存储键名 */ const STORAGE_KEY = 'obc-theme' /** 默认主题 */ const DEFAULT_THEME: ObcTheme = 'day' /** * 类型守卫:检查值是否为有效的主题 * * @param value - 待检查的值 * @returns 是否为有效主题 */ const isValidTheme = (value: unknown): value is ObcTheme => typeof value === 'string' && THEMES.includes(value as ObcTheme) /** * 获取初始主题(从 localStorage 或默认值) * * @returns 初始主题值 */ const getInitialTheme = (): ObcTheme => { // SSR 环境下使用默认主题 if (typeof window === 'undefined') return DEFAULT_THEME const stored = localStorage.getItem(STORAGE_KEY) return isValidTheme(stored) ? stored : DEFAULT_THEME } /** * 管理 OpenBridge 主题切换 * * @returns 主题状态和控制函数 * * @example * ```tsx * const { theme, setTheme, cycleTheme } = useTheme() * * // 设置为夜间模式 * setTheme('night') * * // 循环切换到下一个主题 * cycleTheme() * ``` */ export const useTheme = () => { const [theme, setThemeState] = useState(getInitialTheme) // 应用主题到 DOM 并持久化 useEffect(() => { if (typeof document === 'undefined') return document.documentElement.setAttribute('data-obc-theme', theme) localStorage.setItem(STORAGE_KEY, theme) }, [theme]) // 切换到指定主题 const setTheme = useCallback((newTheme: ObcTheme) => { setThemeState(newTheme) }, []) // 循环切换主题 const cycleTheme = useCallback(() => { setThemeState((current) => { const currentIndex = THEMES.indexOf(current) const nextIndex = (currentIndex + 1) % THEMES.length return THEMES[nextIndex] ?? DEFAULT_THEME }) }, []) return { theme, setTheme, cycleTheme } as const }