v1.3.0: Refactoring Phase 3+4, Symbol-Verwaltung Redesign, Schlauch-Labels Fix
- Refactoring: Error Boundaries, apiFetch Wrapper, Socket Status-Tracking - Refactoring: UI Kontrast (theme-aware colors), unused imports bereinigt - Symbol-Verwaltung: Neues Split-Panel (Meine Symbole + Bibliothek) - Symbol-Verwaltung: Umbenennen (TLF rot/blau), Duplikate erlaubt - Symbol-Verwaltung: Karten-Sidebar zeigt eigene Symbole bevorzugt - Schlauch-Labels: Groessere Schrift (13px/10px), verschiebbar (Drag) - Schema: TenantSymbol customName, sortOrder, unique constraint entfernt - Open Source Referenz entfernt (kostenloses Projekt)
This commit is contained in:
74
src/hooks/use-keyboard-shortcuts.ts
Normal file
74
src/hooks/use-keyboard-shortcuts.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { useEffect, useCallback } from 'react'
|
||||
import type { DrawMode, DrawFeature } from '@/types'
|
||||
|
||||
interface UseKeyboardShortcutsOptions {
|
||||
featuresRef: React.MutableRefObject<DrawFeature[]>
|
||||
onUndo: () => void
|
||||
onRedo: () => void
|
||||
onSave: () => void
|
||||
onDelete: (newFeatures: DrawFeature[]) => void
|
||||
onToolChange: (mode: DrawMode) => void
|
||||
onHelpOpen: () => void
|
||||
}
|
||||
|
||||
const TOOL_SHORTCUTS: Record<string, DrawMode> = {
|
||||
'v': 'select', 's': 'select',
|
||||
'p': 'point',
|
||||
'l': 'linestring',
|
||||
'g': 'polygon',
|
||||
'r': 'rectangle',
|
||||
'c': 'circle',
|
||||
'f': 'freehand',
|
||||
'a': 'arrow',
|
||||
't': 'text',
|
||||
'e': 'eraser',
|
||||
'm': 'measure',
|
||||
'd': 'dangerzone',
|
||||
}
|
||||
|
||||
export function useKeyboardShortcuts({
|
||||
featuresRef,
|
||||
onUndo,
|
||||
onRedo,
|
||||
onSave,
|
||||
onDelete,
|
||||
onToolChange,
|
||||
onHelpOpen,
|
||||
}: UseKeyboardShortcutsOptions) {
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
// Ignore when typing in inputs/textareas
|
||||
const tag = (e.target as HTMLElement)?.tagName
|
||||
if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || (e.target as HTMLElement)?.isContentEditable) return
|
||||
|
||||
// ? or F1 → help
|
||||
if (e.key === '?' || e.key === 'F1') { e.preventDefault(); onHelpOpen(); return }
|
||||
|
||||
// DEL / Backspace → delete selected feature(s)
|
||||
if (e.key === 'Delete' || e.key === 'Backspace') {
|
||||
e.preventDefault()
|
||||
const current = featuresRef.current
|
||||
const selected = current.filter(f => f.properties?._selected)
|
||||
if (selected.length > 0) {
|
||||
onDelete(current.filter(f => !f.properties?._selected))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Ctrl/Cmd shortcuts
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
if (e.key === 'z' && e.shiftKey) { e.preventDefault(); onRedo(); return }
|
||||
if (e.key === 'z') { e.preventDefault(); onUndo(); return }
|
||||
if (e.key === 'y') { e.preventDefault(); onRedo(); return }
|
||||
if (e.key === 's') { e.preventDefault(); onSave(); return }
|
||||
return
|
||||
}
|
||||
|
||||
// Tool shortcuts (single key, no modifier)
|
||||
const mode = TOOL_SHORTCUTS[e.key.toLowerCase()]
|
||||
if (mode) { e.preventDefault(); onToolChange(mode); return }
|
||||
}
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
return () => window.removeEventListener('keydown', handleKeyDown)
|
||||
}, [featuresRef, onUndo, onRedo, onSave, onDelete, onToolChange, onHelpOpen])
|
||||
}
|
||||
Reference in New Issue
Block a user