update-css-variables.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import type { Preferences } from './types';
  2. import { generatorColorVariables } from '@vben-core/shared/color';
  3. import { updateCSSVariables as executeUpdateCSSVariables } from '@vben-core/shared/utils';
  4. import { BUILT_IN_THEME_PRESETS } from './constants';
  5. /**
  6. * 更新主题的 CSS 变量以及其他 CSS 变量
  7. * @param preferences - 当前偏好设置对象,它的主题值将被用来设置文档的主题。
  8. */
  9. function updateCSSVariables(preferences: Preferences) {
  10. // 当修改到颜色变量时,更新 css 变量
  11. const root = document.documentElement;
  12. if (!root) {
  13. return;
  14. }
  15. const theme = preferences?.theme ?? {};
  16. const { builtinType, mode, radius } = theme;
  17. // html 设置 dark 类
  18. if (Reflect.has(theme, 'mode')) {
  19. const dark = isDarkTheme(mode);
  20. root.classList.toggle('dark', dark);
  21. }
  22. // html 设置 data-theme=[builtinType]
  23. if (Reflect.has(theme, 'builtinType')) {
  24. const rootTheme = root.dataset.theme;
  25. if (rootTheme !== builtinType) {
  26. root.dataset.theme = builtinType;
  27. }
  28. }
  29. // 获取当前的内置主题
  30. const currentBuiltType = [...BUILT_IN_THEME_PRESETS].find(
  31. (item) => item.type === builtinType,
  32. );
  33. let builtinTypeColorPrimary: string | undefined = '';
  34. if (currentBuiltType) {
  35. const isDark = isDarkTheme(preferences.theme.mode);
  36. // 设置不同主题的主要颜色
  37. const color = isDark
  38. ? currentBuiltType.darkPrimaryColor || currentBuiltType.primaryColor
  39. : currentBuiltType.primaryColor;
  40. builtinTypeColorPrimary = color || currentBuiltType.color;
  41. }
  42. // 如果内置主题颜色和自定义颜色都不存在,则不更新主题颜色
  43. if (
  44. builtinTypeColorPrimary ||
  45. Reflect.has(theme, 'colorPrimary') ||
  46. Reflect.has(theme, 'colorDestructive') ||
  47. Reflect.has(theme, 'colorSuccess') ||
  48. Reflect.has(theme, 'colorWarning')
  49. ) {
  50. // preferences.theme.colorPrimary = builtinTypeColorPrimary || colorPrimary;
  51. updateMainColorVariables(preferences);
  52. }
  53. // 更新圆角
  54. if (Reflect.has(theme, 'radius')) {
  55. document.documentElement.style.setProperty('--radius', `${radius}rem`);
  56. }
  57. // 更新字体大小
  58. if (Reflect.has(theme, 'fontSize')) {
  59. const fontSize = theme.fontSize;
  60. document.documentElement.style.setProperty(
  61. '--font-size-base',
  62. `${fontSize}px`,
  63. );
  64. document.documentElement.style.setProperty(
  65. '--menu-font-size',
  66. `calc(${fontSize}px * 0.875)`,
  67. );
  68. }
  69. }
  70. /**
  71. * 更新主要的 CSS 变量
  72. * @param preference - 当前偏好设置对象,它的颜色值将被转换成 HSL 格式并设置为 CSS 变量。
  73. */
  74. function updateMainColorVariables(preference: Preferences) {
  75. if (!preference.theme) {
  76. return;
  77. }
  78. const { colorDestructive, colorPrimary, colorSuccess, colorWarning } =
  79. preference.theme;
  80. const colorVariables = generatorColorVariables([
  81. { color: colorPrimary, name: 'primary' },
  82. { alias: 'warning', color: colorWarning, name: 'yellow' },
  83. { alias: 'success', color: colorSuccess, name: 'green' },
  84. { alias: 'destructive', color: colorDestructive, name: 'red' },
  85. ]);
  86. // 要设置的 CSS 变量映射
  87. const colorMappings = {
  88. '--green-500': '--success',
  89. '--primary-500': '--primary',
  90. '--red-500': '--destructive',
  91. '--yellow-500': '--warning',
  92. };
  93. // 统一处理颜色变量的更新
  94. Object.entries(colorMappings).forEach(([sourceVar, targetVar]) => {
  95. const colorValue = colorVariables[sourceVar];
  96. if (colorValue) {
  97. document.documentElement.style.setProperty(targetVar, colorValue);
  98. }
  99. });
  100. executeUpdateCSSVariables(colorVariables);
  101. }
  102. function isDarkTheme(theme: string) {
  103. let dark = theme === 'dark';
  104. if (theme === 'auto') {
  105. dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
  106. }
  107. return dark;
  108. }
  109. export { isDarkTheme, updateCSSVariables };