BlockKeys.tsx58 lines · main
| 1 | // @ts-nocheck |
| 2 | import { KeyboardEvent, ReactNode, useCallback, useEffect, useRef } from 'react' |
| 3 | |
| 4 | import { useClickedOutside } from '@/hooks/ui/useClickedOutside' |
| 5 | |
| 6 | interface BlockKeysProps { |
| 7 | value: string | null |
| 8 | children: ReactNode |
| 9 | onEscape?: (value: string | null) => void |
| 10 | onEnter?: (value: string | null) => void |
| 11 | ignoreOutsideClicks?: boolean |
| 12 | } |
| 13 | |
| 14 | /** |
| 15 | * Blocks key events from propagating |
| 16 | * We use this with cell editor to allow editor component to handle keys. |
| 17 | * Example: press enter to add newline on textEditor |
| 18 | */ |
| 19 | export const BlockKeys = ({ |
| 20 | value, |
| 21 | children, |
| 22 | onEscape, |
| 23 | onEnter, |
| 24 | ignoreOutsideClicks = false, |
| 25 | }: BlockKeysProps) => { |
| 26 | const ref = useRef(null) |
| 27 | const isClickedOutside = useClickedOutside(ref) |
| 28 | |
| 29 | const handleKeyDown = useCallback( |
| 30 | (ev: KeyboardEvent<HTMLDivElement>) => { |
| 31 | switch (ev.key) { |
| 32 | case 'Escape': |
| 33 | ev.stopPropagation() |
| 34 | if (onEscape) onEscape(value) |
| 35 | break |
| 36 | case 'Enter': |
| 37 | ev.stopPropagation() |
| 38 | if (!ev.shiftKey && onEnter) { |
| 39 | ev.preventDefault() |
| 40 | onEnter(value) |
| 41 | } |
| 42 | break |
| 43 | } |
| 44 | }, |
| 45 | [value] |
| 46 | ) |
| 47 | |
| 48 | useEffect(() => { |
| 49 | if (ignoreOutsideClicks) return |
| 50 | if (isClickedOutside && onEnter !== undefined) onEnter(value) |
| 51 | }, [isClickedOutside]) |
| 52 | |
| 53 | return ( |
| 54 | <div ref={ref} onKeyDown={handleKeyDown}> |
| 55 | {children} |
| 56 | </div> |
| 57 | ) |
| 58 | } |