61 lines
No EOL
1.5 KiB
TypeScript
61 lines
No EOL
1.5 KiB
TypeScript
import { computed, onMounted, ref, watch } from 'vue'
|
|
|
|
type Theme = 'dark' | 'light' | 'system'
|
|
|
|
const useTheme = () => {
|
|
const theme = ref<Theme>('dark')
|
|
const systemTheme = ref<'dark' | 'light'>('light')
|
|
const currentTown = ref(localStorage.getItem('current-town') || 'all')
|
|
|
|
const updateSystemTheme = () => {
|
|
systemTheme.value = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
|
}
|
|
|
|
const currentTheme = computed(() => {
|
|
return theme.value === 'system' ? systemTheme.value : theme.value
|
|
})
|
|
|
|
const applyTheme = () => {
|
|
if (currentTheme.value === 'dark') {
|
|
document.documentElement.classList.add('dark')
|
|
} else {
|
|
document.documentElement.classList.remove('dark')
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
const stored = localStorage.getItem('ui-theme')
|
|
if (stored && (stored === 'dark' || stored === 'light' || stored === 'system')) {
|
|
theme.value = stored as Theme
|
|
}
|
|
|
|
updateSystemTheme()
|
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', updateSystemTheme)
|
|
applyTheme()
|
|
})
|
|
|
|
watch(currentTheme, () => {
|
|
applyTheme()
|
|
})
|
|
|
|
const setTheme = (newTheme: Theme) => {
|
|
theme.value = newTheme
|
|
localStorage.setItem('ui-theme', newTheme)
|
|
}
|
|
|
|
const setCurrentTown = (town: string) => {
|
|
currentTown.value = town
|
|
localStorage.setItem('current-town', town)
|
|
}
|
|
|
|
return {
|
|
theme,
|
|
setTheme,
|
|
systemTheme,
|
|
currentTheme,
|
|
currentTown,
|
|
setCurrentTown
|
|
}
|
|
}
|
|
|
|
export { useTheme }
|