import { SITE_THEME_STORAGE_KEY, resolveSiteTheme } from '~/lib/site-theme-init.js' /** * HTML 루트 요소에 현재 테마를 반영한다. * @param {'light' | 'dark'} theme - 적용할 테마 * @returns {void} */ const applyThemeToDocument = (theme) => { if (!import.meta.client) { return } document.documentElement.dataset.theme = theme document.documentElement.style.colorScheme = theme } /** * 사용자의 시스템 테마를 조회한다. * @returns {'light' | 'dark'} 시스템 기준 기본 테마 */ const getSystemTheme = () => { if (!import.meta.client) { return 'light' } return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' } /** * 사이트 라이트/다크 테마 상태를 관리한다. * @returns {{theme: import('vue').Ref<'light' | 'dark'>, isDarkMode: import('vue').ComputedRef, toggleTheme: Function}} 테마 상태와 제어 함수 */ export const useThemeMode = () => { const theme = useState('site-theme-mode', () => 'light') const isDarkMode = computed(() => theme.value === 'dark') if (import.meta.client) { const fromDocument = document.documentElement.dataset.theme if (fromDocument === 'light' || fromDocument === 'dark') { theme.value = fromDocument } else { const savedTheme = localStorage.getItem(SITE_THEME_STORAGE_KEY) theme.value = resolveSiteTheme(savedTheme, getSystemTheme() === 'dark') applyThemeToDocument(theme.value) } } watch(theme, (nextTheme) => { if (!import.meta.client) { return } localStorage.setItem(SITE_THEME_STORAGE_KEY, nextTheme) applyThemeToDocument(nextTheme) }) /** * 라이트/다크 테마를 전환한다. * @returns {void} */ const toggleTheme = () => { theme.value = theme.value === 'dark' ? 'light' : 'dark' } return { theme, isDarkMode, toggleTheme } }