|
|
@@ -0,0 +1,79 @@
|
|
|
+/*
|
|
|
+ * @Author: liuJie
|
|
|
+ * @Date: 2026-01-30 19:47:19
|
|
|
+ * @LastEditors: liuJie
|
|
|
+ * @LastEditTime: 2026-01-30 20:20:59
|
|
|
+ * @Describe: 单独抽离换肤
|
|
|
+ */
|
|
|
+import { ref, onMounted, onBeforeUnmount } from 'vue'
|
|
|
+import * as monaco from 'monaco-editor'
|
|
|
+
|
|
|
+type EditorTheme = 'vs-light' | 'vs-dark'
|
|
|
+type ThemeClass = 'light' | 'dark'
|
|
|
+
|
|
|
+interface UseLocalEditorThemeOptions {
|
|
|
+ defaultTheme?: EditorTheme
|
|
|
+ autoToggleTheme?: boolean
|
|
|
+}
|
|
|
+
|
|
|
+export function useLocalEditorTheme(
|
|
|
+ options: UseLocalEditorThemeOptions = {}
|
|
|
+) {
|
|
|
+ const {
|
|
|
+ defaultTheme = 'vs-light',
|
|
|
+ autoToggleTheme = false
|
|
|
+ } = options
|
|
|
+
|
|
|
+ /** 当前 Monaco 主题(语法) */
|
|
|
+ const monacoTheme = ref<EditorTheme>(defaultTheme)
|
|
|
+
|
|
|
+ /** 当前 UI 主题(样式) */
|
|
|
+ const themeClass = ref<ThemeClass>(
|
|
|
+ defaultTheme === 'vs-dark' ? 'dark' : 'light'
|
|
|
+ )
|
|
|
+
|
|
|
+ /** 系统暗黑监听 */
|
|
|
+ let mediaQuery: MediaQueryList | null = null
|
|
|
+
|
|
|
+ const applyTheme = (theme: EditorTheme) => {
|
|
|
+ monacoTheme.value = theme
|
|
|
+ themeClass.value = theme === 'vs-dark' ? 'dark' : 'light'
|
|
|
+
|
|
|
+ monaco.editor.setTheme(theme)
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 手动切换 */
|
|
|
+ const toggleTheme = () => {
|
|
|
+ applyTheme(
|
|
|
+ monacoTheme.value === 'vs-light' ? 'vs-dark' : 'vs-light'
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 系统主题变化 */
|
|
|
+ const handleSystemThemeChange = (e: MediaQueryListEvent) => {
|
|
|
+ applyTheme(e.matches ? 'vs-dark' : 'vs-light')
|
|
|
+ }
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
+ applyTheme(defaultTheme)
|
|
|
+
|
|
|
+ if (autoToggleTheme) {
|
|
|
+ mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
|
|
+ applyTheme(mediaQuery.matches ? 'vs-dark' : 'vs-light')
|
|
|
+ mediaQuery.addEventListener('change', handleSystemThemeChange)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ onBeforeUnmount(() => {
|
|
|
+ if (mediaQuery) {
|
|
|
+ mediaQuery.removeEventListener('change', handleSystemThemeChange)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ monacoTheme,
|
|
|
+ themeClass,
|
|
|
+ toggleTheme,
|
|
|
+ setTheme: applyTheme
|
|
|
+ }
|
|
|
+}
|