export type Theme = 'light' | 'dark' // ต้องตรงกับ inline script กัน FOUC ใน nuxt.config.ts const STORAGE_KEY = 'theme-preference' export function useTheme() { const theme = useState('theme', () => 'light') const isDark = computed(() => theme.value === 'dark') function apply(next: Theme) { theme.value = next // ใช้ typeof window แทน import.meta.client — เทียบเท่ากันใน Nuxt (SSR ไม่มี window) // และรันได้ใน vitest ตรงๆ โดยไม่ต้องพึ่งการ transform เฉพาะของ Nuxt if (typeof window !== 'undefined') { document.documentElement.classList.toggle('dark', next === 'dark') // ข้อยกเว้นเดียวที่ localStorage อนุญาต: theme preference ไม่ใช่ credential (กติกา #4) localStorage.setItem(STORAGE_KEY, next) } } /** Sync state กับที่ inline script ตั้งไว้ตอนโหลดหน้า (client เท่านั้น) */ function initTheme() { if (typeof window === 'undefined') return const stored = localStorage.getItem(STORAGE_KEY) if (stored === 'light' || stored === 'dark') { theme.value = stored } else { theme.value = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' } document.documentElement.classList.toggle('dark', theme.value === 'dark') } function toggle() { apply(theme.value === 'dark' ? 'light' : 'dark') } return { theme, isDark, initTheme, toggle } }