import { useCallback } from 'react';
import { getFocusables, getActiveElement } from '../utils';
import useEvent from './useEvent';
/**
 * @example useFocusTrap(elementRef)
 * @param elementRef ref of the element in which focus needs to be retained
 * @param addToDocument boolean value to specify if event to be attached to document or to be taken from elementRef, defaults to true
 * @param dependencies  list of variables or functions that will initiate this hook when they are updated.
 * @param returnEscapedFocus boolean value to specify if focus that escapes the elementRef should be returned to the elementRef, defaults to true
 */
const useFocusTrap = (elementRef, attachToDocument = true, dependencies = [], returnEscapedFocus = true) => {
    const onKeydown = useCallback((e) => {
        if (!elementRef?.current)
            return;
        if (e.key === 'Tab') {
            const focusables = getFocusables(elementRef);
            const { 0: firstFocusable, [focusables.length - 1]: lastFocusable } = focusables;
            const activeEl = getActiveElement();
            const requiresFocus = activeEl === elementRef.current ||
                !elementRef.current.contains(activeEl) ||
                (elementRef.current.contains(activeEl) && !focusables.includes(activeEl));
            if (requiresFocus && returnEscapedFocus) {
                e.preventDefault();
                if (activeEl) {
                    const focusablesWithActiveEl = getFocusables(elementRef, { includeActiveEl: true });
                    const activeElIndex = focusablesWithActiveEl.findIndex(el => el === activeEl);
                    if (activeElIndex !== -1) {
                        if (e.shiftKey) {
                            const prevIndex = (activeElIndex - 1 + focusablesWithActiveEl.length) % focusablesWithActiveEl.length;
                            focusablesWithActiveEl[prevIndex].focus();
                        }
                        else {
                            focusablesWithActiveEl[(activeElIndex + 1) % focusablesWithActiveEl.length].focus();
                        }
                    }
                    else if (e.shiftKey) {
                        lastFocusable?.focus();
                    }
                    else {
                        firstFocusable?.focus();
                    }
                }
                else if (e.shiftKey) {
                    lastFocusable?.focus();
                }
                else {
                    firstFocusable?.focus();
                }
            }
            else if (e.shiftKey && activeEl === firstFocusable) {
                e.preventDefault();
                lastFocusable?.focus();
            }
            else if (!e.shiftKey && activeEl === lastFocusable) {
                e.preventDefault();
                firstFocusable?.focus();
            }
        }
    }, dependencies);
    useEvent('keydown', onKeydown, { target: attachToDocument ? undefined : elementRef });
};
export default useFocusTrap;
//# sourceMappingURL=useFocusTrap.js.map