71 lines
1.5 KiB
JavaScript
71 lines
1.5 KiB
JavaScript
|
|
import { computed, ref } from 'vue'
|
||
|
|
|
||
|
|
const STORAGE_KEY = 'llm-in-text.theme'
|
||
|
|
const DEFAULT_THEME = 'light'
|
||
|
|
const THEME_LIGHT = 'light'
|
||
|
|
const THEME_DARK = 'dark'
|
||
|
|
|
||
|
|
const theme = ref(DEFAULT_THEME)
|
||
|
|
|
||
|
|
const canUseDom = typeof document !== 'undefined'
|
||
|
|
const canUseStorage = typeof window !== 'undefined' && typeof window.localStorage !== 'undefined'
|
||
|
|
|
||
|
|
const normalizeTheme = (value) => (value === THEME_DARK ? THEME_DARK : THEME_LIGHT)
|
||
|
|
|
||
|
|
const readStoredTheme = () => {
|
||
|
|
if (!canUseStorage) return DEFAULT_THEME
|
||
|
|
|
||
|
|
try {
|
||
|
|
const stored = window.localStorage.getItem(STORAGE_KEY)
|
||
|
|
return normalizeTheme(stored)
|
||
|
|
} catch {
|
||
|
|
return DEFAULT_THEME
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const writeStoredTheme = (value) => {
|
||
|
|
if (!canUseStorage) return
|
||
|
|
|
||
|
|
try {
|
||
|
|
window.localStorage.setItem(STORAGE_KEY, value)
|
||
|
|
} catch {
|
||
|
|
// Ignore persistence errors (privacy mode, quota, etc).
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const applyThemeToDom = (value) => {
|
||
|
|
if (!canUseDom) return
|
||
|
|
|
||
|
|
const next = normalizeTheme(value)
|
||
|
|
document.documentElement.setAttribute('data-theme', next)
|
||
|
|
document.documentElement.style.colorScheme = next
|
||
|
|
}
|
||
|
|
|
||
|
|
const setTheme = (nextTheme) => {
|
||
|
|
const next = normalizeTheme(nextTheme)
|
||
|
|
theme.value = next
|
||
|
|
applyThemeToDom(next)
|
||
|
|
writeStoredTheme(next)
|
||
|
|
}
|
||
|
|
|
||
|
|
const toggleTheme = () => {
|
||
|
|
setTheme(theme.value === THEME_DARK ? THEME_LIGHT : THEME_DARK)
|
||
|
|
}
|
||
|
|
|
||
|
|
const isDark = computed(() => theme.value === THEME_DARK)
|
||
|
|
|
||
|
|
const initTheme = () => {
|
||
|
|
setTheme(readStoredTheme())
|
||
|
|
}
|
||
|
|
|
||
|
|
initTheme()
|
||
|
|
|
||
|
|
export function useTheme() {
|
||
|
|
return {
|
||
|
|
theme,
|
||
|
|
isDark,
|
||
|
|
setTheme,
|
||
|
|
toggleTheme
|
||
|
|
}
|
||
|
|
}
|