- chore: 升级 @metona-team/metona-editor 0.1.3 → 0.1.10 - feat: 三主题系统(亮色/暗色/暖色),循环切换 - feat: 应用颜色自动同步编辑器主题(MeEditor.themes.exportCSSVars) - feat: 启用编辑器新功能(lineNumbers/autoBrackets/readOnly/autofocus/exportTool) - refactor: 主题从 boolean darkMode 重构为 ThemeMode 枚举 - refactor: 插件注册改用字符串数组(与 demo 一致) - refactor: 主题同步从手动 CSS 覆写改为 editor.setTheme() 实例 API - refactor: Ctrl+S 双通道(编辑器 onSave + 全局兜底)+ 防重入锁 - style: 移除 variables.css 中硬编码 .dark 色值,改为 JS 动态驱动 - test: 更新 editorStore 测试覆盖新的 themeMode/cycleTheme
54 lines
2.1 KiB
TypeScript
54 lines
2.1 KiB
TypeScript
import { useEffect, useCallback } from 'react'
|
|
import { useTabStore } from '../stores/tabStore'
|
|
|
|
/**
|
|
* 全局键盘快捷键 hook。
|
|
* MetonaEditor 内置工具栏处理格式化和模式切换(Ctrl+B/I/1/2/3),
|
|
* v0.1.9 onSave 回调处理编辑器聚焦时的 Ctrl+S,
|
|
* 全局 handler 作为焦点外兜底(工具栏/侧边栏聚焦时仍可保存)。
|
|
*/
|
|
export function useKeyboard(handleOpenFile: () => void, handleSave: () => void, handleSaveAs: () => void) {
|
|
const handleKeydown = useCallback((e: KeyboardEvent) => {
|
|
const isCtrl = e.ctrlKey || e.metaKey
|
|
|
|
if (isCtrl && e.key === 'o') { e.preventDefault(); handleOpenFile(); return }
|
|
// 全局兜底:编辑器未聚焦时仍可保存(编辑器聚焦时由 onSave 回调处理)
|
|
if (isCtrl && e.key === 's' && !e.shiftKey) { e.preventDefault(); handleSave(); return }
|
|
if (isCtrl && e.shiftKey && e.key === 'S') { e.preventDefault(); handleSaveAs(); return }
|
|
|
|
const tabState = useTabStore.getState()
|
|
if (isCtrl && e.key === 't') { e.preventDefault(); tabState.createTab(null, ''); return }
|
|
if (isCtrl && e.key === 'w') {
|
|
e.preventDefault()
|
|
if (tabState.activeTabId) tabState.closeTab(tabState.activeTabId)
|
|
return
|
|
}
|
|
|
|
// Ctrl+Tab / Ctrl+Shift+Tab — MRU 顺序切换
|
|
if (isCtrl && e.key === 'Tab') {
|
|
e.preventDefault()
|
|
const { tabs, activeTabId, mruStack } = tabState
|
|
if (tabs.length > 1) {
|
|
if (mruStack.length > 0) {
|
|
const targetId = mruStack[0]
|
|
if (tabs.find(t => t.id === targetId)) {
|
|
tabState.switchToTab(targetId)
|
|
return
|
|
}
|
|
}
|
|
const idx = tabs.findIndex(t => t.id === activeTabId)
|
|
const next = e.shiftKey
|
|
? (idx - 1 + tabs.length) % tabs.length
|
|
: (idx + 1) % tabs.length
|
|
tabState.switchToTab(tabs[next].id)
|
|
}
|
|
return
|
|
}
|
|
}, [handleOpenFile, handleSave, handleSaveAs])
|
|
|
|
useEffect(() => {
|
|
document.addEventListener('keydown', handleKeydown)
|
|
return () => document.removeEventListener('keydown', handleKeydown)
|
|
}, [handleKeydown])
|
|
}
|