54 lines
1.3 KiB
TypeScript
54 lines
1.3 KiB
TypeScript
import React from 'react';
|
|
|
|
interface UseDocSearchKeyboardEventsProps {
|
|
isOpen: boolean;
|
|
onOpen(): void;
|
|
onClose(): void;
|
|
onInput?(event: KeyboardEvent): void;
|
|
searchButtonRef?: React.RefObject<HTMLButtonElement>;
|
|
}
|
|
|
|
export function useDocSearchKeyboardEvents({
|
|
isOpen,
|
|
onOpen,
|
|
onClose,
|
|
onInput,
|
|
searchButtonRef,
|
|
}: UseDocSearchKeyboardEventsProps) {
|
|
React.useEffect(() => {
|
|
function onKeyDown(event: KeyboardEvent) {
|
|
if (
|
|
(event.keyCode === 27 && isOpen) ||
|
|
// The `Cmd+K` shortcut both opens and closes the modal.
|
|
(event.key === 'k' && (event.metaKey || event.ctrlKey)) ||
|
|
// The `/` shortcut opens but doesn't close the modal because it's
|
|
// a character.
|
|
(event.key === '/' && !isOpen)
|
|
) {
|
|
event.preventDefault();
|
|
|
|
if (isOpen) {
|
|
onClose();
|
|
} else {
|
|
onOpen();
|
|
}
|
|
}
|
|
|
|
if (
|
|
searchButtonRef &&
|
|
searchButtonRef.current === document.activeElement &&
|
|
onInput
|
|
) {
|
|
if (/[a-zA-Z0-9]/.test(String.fromCharCode(event.keyCode))) {
|
|
onInput(event);
|
|
}
|
|
}
|
|
}
|
|
|
|
window.addEventListener('keydown', onKeyDown);
|
|
|
|
return () => {
|
|
window.removeEventListener('keydown', onKeyDown);
|
|
};
|
|
}, [isOpen, onOpen, onClose, onInput, searchButtonRef]);
|
|
}
|