All files useUntabbable.ts

100% Statements 19/19
100% Branches 15/15
100% Functions 4/4
100% Lines 19/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66                                  12x   12x   12x 11x 3x             8x   8x 13x 2x     11x   11x 17x           17x       8x 8x 17x   17x 16x   1x                
import tabbable from "tabbable";
import { useEffect } from "react";
 
import type { RefObject } from 'react';
 
interface Options {
    /** 
     * Restore the tabbable behaviour.
     */
    disabled?: boolean,
    /**
     * If it should also disable the container received as a ref.
     */
	includeContainer?: boolean,
};
 
function useUntabbable(ref: RefObject<HTMLElement> | RefObject<HTMLElement>[], options: Options = {}) {
    const { disabled = false, includeContainer = false } = options;
 
    const refs = Array.isArray(ref) ? ref : [ref];
 
    useEffect(() => {
        if (disabled || refs.length === 0) {
            return;
        }
 
        const descriptors: { 
            element: HTMLElement,
            hadTabIndex: boolean;
            tabIndex: string | null
        }[] = [];
 
        for (const ref of refs) {
            if (!ref || !ref.current) {
                continue;
            }
 
            const tabbableElements = tabbable(ref.current, { includeContainer });
 
            tabbableElements.forEach(element => {
                descriptors.push({
                    element,
                    hadTabIndex: element.hasAttribute('tabindex'),
                    tabIndex: element.getAttribute('tabindex'),
                });
 
                element.setAttribute('tabindex', '-1')
            });
        }
 
        return () => {
            for (const descriptor of descriptors) {
                const { element, hadTabIndex, tabIndex } = descriptor;
 
                if (!hadTabIndex) {
                    element.removeAttribute('tabindex');
                } else {
                    element.setAttribute('tabindex', `${tabIndex}`);
                }
            }
        };
    }, [...refs, disabled, includeContainer]);
}
 
export default useUntabbable;