UI improvements
This commit is contained in:
86
src/hooks/useKeyboardShortcuts.ts
Normal file
86
src/hooks/useKeyboardShortcuts.ts
Normal file
@ -0,0 +1,86 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
|
||||
export interface KeyboardShortcutHandlers {
|
||||
onSpace?: () => void
|
||||
onArrowUp?: (shift: boolean) => void
|
||||
onArrowDown?: (shift: boolean) => void
|
||||
onArrowLeft?: (shift: boolean) => void
|
||||
onArrowRight?: (shift: boolean) => void
|
||||
onEnter?: () => void
|
||||
onDoubleEnter?: () => void
|
||||
onR?: () => void
|
||||
onShiftR?: () => void
|
||||
}
|
||||
|
||||
const DOUBLE_ENTER_THRESHOLD = 300
|
||||
|
||||
export function useKeyboardShortcuts(handlers: KeyboardShortcutHandlers) {
|
||||
const handlersRef = useRef(handlers)
|
||||
|
||||
useEffect(() => {
|
||||
handlersRef.current = handlers
|
||||
}, [handlers])
|
||||
|
||||
useEffect(() => {
|
||||
let lastEnterTime = 0
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
||||
return
|
||||
}
|
||||
|
||||
const h = handlersRef.current
|
||||
|
||||
switch (e.key) {
|
||||
case ' ':
|
||||
e.preventDefault()
|
||||
h.onSpace?.()
|
||||
break
|
||||
|
||||
case 'ArrowUp':
|
||||
e.preventDefault()
|
||||
h.onArrowUp?.(e.shiftKey)
|
||||
break
|
||||
|
||||
case 'ArrowDown':
|
||||
e.preventDefault()
|
||||
h.onArrowDown?.(e.shiftKey)
|
||||
break
|
||||
|
||||
case 'ArrowLeft':
|
||||
e.preventDefault()
|
||||
h.onArrowLeft?.(e.shiftKey)
|
||||
break
|
||||
|
||||
case 'ArrowRight':
|
||||
e.preventDefault()
|
||||
h.onArrowRight?.(e.shiftKey)
|
||||
break
|
||||
|
||||
case 'Enter':
|
||||
e.preventDefault()
|
||||
const now = Date.now()
|
||||
if (now - lastEnterTime < DOUBLE_ENTER_THRESHOLD) {
|
||||
h.onDoubleEnter?.()
|
||||
} else {
|
||||
h.onEnter?.()
|
||||
}
|
||||
lastEnterTime = now
|
||||
break
|
||||
|
||||
case 'r':
|
||||
case 'R':
|
||||
e.preventDefault()
|
||||
if (e.shiftKey) {
|
||||
h.onShiftR?.()
|
||||
} else {
|
||||
h.onR?.()
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
return () => window.removeEventListener('keydown', handleKeyDown)
|
||||
}, [])
|
||||
}
|
||||
Reference in New Issue
Block a user