export const AETHERA_THEME_KEY = 'aethera-theme'; export type ThemeMode = 'light' | 'dark' | 'system'; export interface ThemeState { mode: ThemeMode; } export function getSystemTheme(): 'light' | 'dark' { if (typeof window !== 'undefined') { return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; } return 'light'; } export function getEffectiveTheme(themeMode: ThemeMode): 'light' | 'dark' { if (themeMode === 'system') { return getSystemTheme(); } return themeMode; } export function loadTheme(): ThemeState { if (typeof localStorage === 'undefined') { return { mode: 'system' }; } const stored = localStorage.getItem(AETHERA_THEME_KEY); if (stored === 'light' || stored === 'dark' || stored === 'system') { return { mode: stored }; } return { mode: 'system' }; } export function saveThemeMode(mode: ThemeMode): void { if (typeof localStorage !== 'undefined') { localStorage.setItem(AETHERA_THEME_KEY, mode); } } export function applyTheme(mode: ThemeMode): void { const effectiveTheme = getEffectiveTheme(mode); if (typeof document !== 'undefined') { if (effectiveTheme === 'dark') { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } } applySyntaxTheme(effectiveTheme); } export function applySyntaxTheme(theme: 'light' | 'dark'): void { if (typeof document === 'undefined') return; const linkId = 'hljs-theme'; let link = document.getElementById(linkId) as HTMLLinkElement; const cssFile = theme === 'dark' ? 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/stackoverflow-dark.css' : 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.css'; if (!link) { link = document.createElement('link'); link.id = linkId; link.rel = 'stylesheet'; link.href = cssFile; document.head.appendChild(link); } else if (link.href !== cssFile) { link.href = cssFile; } } export function getNextThemeMode(currentMode: ThemeMode): ThemeMode { const cycle: ThemeMode[] = ['light', 'dark', 'system']; const currentIndex = cycle.indexOf(currentMode); const nextIndex = (currentIndex + 1) % cycle.length; return cycle[nextIndex]; }