{"size": 1434, "ext": "js", "max_stars_repo_path": "src/hooks/useFocusTrap.js", "max_stars_repo_name": "desoindx/react-dsfr", "max_stars_repo_stars_event_min_datetime": "2021-05-20T10:32:00.000Z", "max_stars_repo_stars_event_max_datetime": "2022-03-20T16:48:05.000Z", "max_issues_repo_path": "src/hooks/useFocusTrap.js", "max_issues_repo_name": "desoindx/react-dsfr", "max_issues_repo_issues_event_min_datetime": "2021-04-07T15:03:07.000Z", "max_issues_repo_issues_event_max_datetime": "2022-03-25T13:19:02.000Z", "max_forks_repo_path": "src/hooks/useFocusTrap.js", "max_forks_repo_name": "desoindx/react-dsfr", "max_forks_repo_forks_event_min_datetime": "2021-05-27T16:22:18.000Z", "max_forks_repo_forks_event_max_datetime": "2022-03-04T16:44:08.000Z"}
{"max_stars_count": 17, "max_issues_count": 56, "max_forks_count": 13, "avg_line_length": 28.68, "max_line_length": 104, "alphanum_fraction": 0.6164574616}
import { useState, useEffect } from 'react';

// Focus trap from https://medium.com/@seif_ghezala/how-to-create-an-accessible-react-modal-5b87e6a27503
const useFocusTrap = (ref) => {
  const [focus, setFocus] = useState(0);
  const [focusableElements, setFocusableElements] = useState(null);

  const getKeyboardFocusableElements = (element) => {
    const filtered = [];
    const arrayElements = Array.from(element.querySelectorAll(
      'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])',
    ), (e) => e);

    arrayElements.forEach((el) => {
      if (el && !el.hasAttribute('disabled')) {
        filtered.push(el);
      }
    });
    return filtered;
  };

  const handleTabulation = (e) => {
    e.preventDefault();
    if (e.keyCode === 9 && !e.shiftKey) {
      setFocus((currentFocus) => ((currentFocus + 1) % focusableElements.length));
    }
    if (e.keyCode === 9 && e.shiftKey) {
      setFocus(
        (currentFocus) => (
          (currentFocus - 1 < 0) ? (focusableElements.length - 1) : (currentFocus - 1)
        ),
      );
    }
  };

  useEffect(() => {
    if (!focusableElements) {
      const elements = ref.current && getKeyboardFocusableElements(ref.current);
      setFocusableElements(elements);
    } else {
      focusableElements[focus].focus();
    }
  }, [focus, focusableElements, ref]);

  return handleTabulation;
};

/* @component */
export default useFocusTrap;
