import { theme, type TokenType as AntdTheme } from 'ant-design-vue'; import { chain } from 'lodash-es'; import { ref, watch } from 'vue'; const THEME_FILES = import.meta.glob('asset/themes/*.json', { eager: true, import: 'default' }); const THEME_MAP = chain(THEME_FILES) .mapKeys((_, k) => k.match(/^.*[\\|\\/](.+?)\.[^\\.]+$/)?.[1]) .mapValues((v) => >v) .value(); enum Theme { Light = 'light', Dark = 'dark', } export const THEMES = Object.freeze<[string, Theme][]>(Object.entries(Theme)); const THEME_STORAGE_KEY = 'theme'; class ThemeService { #theme = ref(localStorage.getItem(THEME_STORAGE_KEY) || Theme.Dark); public get theme(): Theme { return this.#theme.value; } public set theme(v: Theme) { this.#theme.value = v; localStorage.setItem(THEME_STORAGE_KEY, v); } public get ant(): AntdTheme { switch (this.#theme.value) { case Theme.Dark: return { algorithm: theme.darkAlgorithm }; case Theme.Light: default: return { algorithm: theme.defaultAlgorithm }; } } public get editor(): object { return THEME_MAP[`editor-${this.#theme.value}`] ?? {}; } constructor() { watch(this.#theme, (v) => this.#load(v), { immediate: true }); } #load(theme: Theme): void { document.documentElement.setAttribute('theme', theme); } } export default new ThemeService();