UNPKG

1.22 kBJavaScriptView Raw
1import { useMemo, useRef } from 'react';
2import useEventListener from '@restart/hooks/useEventListener';
3const defaultSelector = ['input', 'textarea', 'select', 'button:not([tabindex="-1"])', '[tabindex="0"]'].join(',');
4
5const getDocument = () => document;
6
7export default function useTabTrap(ref, selector = defaultSelector) {
8 const startedRef = useRef(false);
9 useEventListener(getDocument, 'keydown', event => {
10 if (!startedRef.current || !ref.current || event.key !== 'Tab') {
11 return;
12 }
13
14 const tabbables = ref.current.querySelectorAll(selector);
15
16 if (event.shiftKey && event.target === tabbables[0]) {
17 tabbables[tabbables.length - 1].focus();
18 event.preventDefault();
19 } else if (!event.shiftKey && event.target === tabbables[tabbables.length - 1] || !ref.current.contains(event.target)) {
20 tabbables[0].focus();
21 event.preventDefault();
22 }
23 });
24 return useMemo(() => ({
25 focus() {
26 const tabbables = ref.current.querySelectorAll(selector);
27 const first = tabbables[0];
28 if (first) first.focus();
29 },
30
31 start() {
32 startedRef.current = true;
33 },
34
35 stop() {
36 startedRef.current = false;
37 }
38
39 }), [ref, selector]);
40}
\No newline at end of file