useLocalEditorTheme.ts 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. * @Author: liuJie
  3. * @Date: 2026-01-30 19:47:19
  4. * @LastEditors: liuJie
  5. * @LastEditTime: 2026-01-30 20:20:59
  6. * @Describe: 单独抽离换肤
  7. */
  8. import { ref, onMounted, onBeforeUnmount } from 'vue'
  9. import * as monaco from 'monaco-editor'
  10. type EditorTheme = 'vs-light' | 'vs-dark'
  11. type ThemeClass = 'light' | 'dark'
  12. interface UseLocalEditorThemeOptions {
  13. defaultTheme?: EditorTheme
  14. autoToggleTheme?: boolean
  15. }
  16. export function useLocalEditorTheme(
  17. options: UseLocalEditorThemeOptions = {}
  18. ) {
  19. const {
  20. defaultTheme = 'vs-light',
  21. autoToggleTheme = false
  22. } = options
  23. /** 当前 Monaco 主题(语法) */
  24. const monacoTheme = ref<EditorTheme>(defaultTheme)
  25. /** 当前 UI 主题(样式) */
  26. const themeClass = ref<ThemeClass>(
  27. defaultTheme === 'vs-dark' ? 'dark' : 'light'
  28. )
  29. /** 系统暗黑监听 */
  30. let mediaQuery: MediaQueryList | null = null
  31. const applyTheme = (theme: EditorTheme) => {
  32. monacoTheme.value = theme
  33. themeClass.value = theme === 'vs-dark' ? 'dark' : 'light'
  34. monaco.editor.setTheme(theme)
  35. }
  36. /** 手动切换 */
  37. const toggleTheme = () => {
  38. applyTheme(
  39. monacoTheme.value === 'vs-light' ? 'vs-dark' : 'vs-light'
  40. )
  41. }
  42. /** 系统主题变化 */
  43. const handleSystemThemeChange = (e: MediaQueryListEvent) => {
  44. applyTheme(e.matches ? 'vs-dark' : 'vs-light')
  45. }
  46. onMounted(() => {
  47. applyTheme(defaultTheme)
  48. if (autoToggleTheme) {
  49. mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
  50. applyTheme(mediaQuery.matches ? 'vs-dark' : 'vs-light')
  51. mediaQuery.addEventListener('change', handleSystemThemeChange)
  52. }
  53. })
  54. onBeforeUnmount(() => {
  55. if (mediaQuery) {
  56. mediaQuery.removeEventListener('change', handleSystemThemeChange)
  57. }
  58. })
  59. return {
  60. monacoTheme,
  61. themeClass,
  62. toggleTheme,
  63. setTheme: applyTheme
  64. }
  65. }