import type { Preferences } from './types'; import { updateCSSVariables as executeUpdateCSSVariables, generatorColorVariables, } from '@vben-core/shared'; import { BUILT_IN_THEME_PRESETS, type BuiltinThemePreset } from './constants'; /** * 更新主题的 CSS 变量以及其他 CSS 变量 * @param preferences - 当前偏好设置对象,它的主题值将被用来设置文档的主题。 */ function updateCSSVariables(preferences: Preferences) { // 当修改到颜色变量时,更新 css 变量 const root = document.documentElement; if (!root) { return; } const theme = preferences?.theme ?? {}; const { builtinType, colorPrimary, mode, radius } = theme; // html 设置 dark 类 if (Reflect.has(theme, 'mode')) { const dark = isDarkTheme(mode); root.classList.toggle('dark', dark); } // html 设置 data-theme=[builtinType] if (Reflect.has(theme, 'builtinType')) { const rootTheme = root.dataset.theme; if (rootTheme !== builtinType) { root.dataset.theme = builtinType; } } // 获取当前的内置主题 const currentBuiltType = [ { color: preferences.theme.colorPrimary, type: 'default', } as BuiltinThemePreset, ...BUILT_IN_THEME_PRESETS, ].find((item) => item.type === builtinType); let builtinTypeColorPrimary: string | undefined = ''; if (currentBuiltType) { const isDark = isDarkTheme(preferences.theme.mode); // 设置不同主题的主要颜色 const color = isDark ? currentBuiltType.darkPrimaryColor || currentBuiltType.primaryColor : currentBuiltType.primaryColor; builtinTypeColorPrimary = color || currentBuiltType.color; } // 如果内置主题颜色和自定义颜色都不存在,则不更新主题颜色 if ( builtinTypeColorPrimary || Reflect.has(theme, 'colorPrimary') || Reflect.has(theme, 'colorDestructive') || Reflect.has(theme, 'colorSuccess') || Reflect.has(theme, 'colorWarning') ) { preferences.theme.colorPrimary = builtinTypeColorPrimary || colorPrimary; updateMainColorVariables(preferences); } // 更新圆角 if (Reflect.has(theme, 'radius')) { document.documentElement.style.setProperty('--radius', `${radius}rem`); } } /** * 更新主要的 CSS 变量 * @param preference - 当前偏好设置对象,它的颜色值将被转换成 HSL 格式并设置为 CSS 变量。 */ function updateMainColorVariables(preference: Preferences) { if (!preference.theme) { return; } const { colorDestructive, colorPrimary, colorSuccess, colorWarning } = preference.theme; const colorVariables = generatorColorVariables([ { color: colorPrimary, name: 'primary' }, { alias: 'warning', color: colorWarning, name: 'yellow' }, { alias: 'success', color: colorSuccess, name: 'green' }, { alias: 'destructive', color: colorDestructive, name: 'red' }, ]); if (colorPrimary) { document.documentElement.style.setProperty( '--primary', colorVariables['--primary-500'], ); } if (colorVariables['--green-500']) { colorVariables['--success'] = colorVariables['--green-500']; } if (colorVariables['--yellow-500']) { colorVariables['--warning'] = colorVariables['--yellow-500']; } if (colorVariables['--red-500']) { colorVariables['--destructive'] = colorVariables['--red-500']; } executeUpdateCSSVariables(colorVariables); } function isDarkTheme(theme: string) { let dark = theme === 'dark'; if (theme === 'auto') { dark = window.matchMedia('(prefers-color-scheme: dark)').matches; } return dark; } export { updateCSSVariables };