UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

166 lines (157 loc) • 6.42 kB
'use strict'; var reactCompilerRuntime = require('react-compiler-runtime'); var React = require('react'); var utils = require('@primer/behaviors/utils'); var useMenuInitialFocus = require('./useMenuInitialFocus.js'); var useMnemonics = require('./useMnemonics.js'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var React__default = /*#__PURE__*/_interopDefault(React); /** * Keyboard navigation is a mix of 4 hooks * 1. useMenuInitialFocus * 2. useTypeaheadFocus * 3. useCloseMenuOnTab * 4. useMoveFocusToMenuItem */ const useMenuKeyboardNavigation = (open, onClose, containerRef, anchorRef, t0) => { const isSubmenu = t0 === undefined ? false : t0; useMenuInitialFocus.useMenuInitialFocus(open, containerRef, anchorRef); useMnemonics.useMnemonics(open, containerRef); useCloseMenuOnTab(open, onClose, containerRef, anchorRef); useMoveFocusToMenuItem(open, containerRef, anchorRef); useCloseSubmenuOnArrow(open, isSubmenu, onClose, containerRef); }; /** * When Tab or Shift+Tab is pressed, the menu should close * and the focus should naturally move to the next item */ const useCloseMenuOnTab = (open, onClose, containerRef, anchorRef) => { const $ = reactCompilerRuntime.c(10); let t0; if ($[0] !== (anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current) || $[1] !== (containerRef === null || containerRef === void 0 ? void 0 : containerRef.current) || $[2] !== onClose || $[3] !== open) { t0 = () => { const container = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current; const anchor = anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current; const handler = event => { if (open && event.key === "Tab") { onClose === null || onClose === void 0 ? void 0 : onClose("tab"); } }; container === null || container === void 0 ? void 0 : container.addEventListener("keydown", handler); anchor === null || anchor === void 0 ? void 0 : anchor.addEventListener("keydown", handler); return () => { container === null || container === void 0 ? void 0 : container.removeEventListener("keydown", handler); anchor === null || anchor === void 0 ? void 0 : anchor.removeEventListener("keydown", handler); }; }; $[0] = anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current; $[1] = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current; $[2] = onClose; $[3] = open; $[4] = t0; } else { t0 = $[4]; } let t1; if ($[5] !== anchorRef || $[6] !== containerRef || $[7] !== onClose || $[8] !== open) { t1 = [open, onClose, containerRef, anchorRef]; $[5] = anchorRef; $[6] = containerRef; $[7] = onClose; $[8] = open; $[9] = t1; } else { t1 = $[9]; } React__default.default.useEffect(t0, t1); }; /** * Close submenu when left arrow key is pressed */ const useCloseSubmenuOnArrow = (open, isSubmenu, onClose, containerRef) => { const $ = reactCompilerRuntime.c(10); let t0; if ($[0] !== (containerRef === null || containerRef === void 0 ? void 0 : containerRef.current) || $[1] !== isSubmenu || $[2] !== onClose || $[3] !== open) { t0 = () => { const container = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current; const handler = event => { if (open && isSubmenu && event.key === "ArrowLeft") { onClose === null || onClose === void 0 ? void 0 : onClose("arrow-left"); } }; container === null || container === void 0 ? void 0 : container.addEventListener("keydown", handler); return () => { container === null || container === void 0 ? void 0 : container.removeEventListener("keydown", handler); }; }; $[0] = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current; $[1] = isSubmenu; $[2] = onClose; $[3] = open; $[4] = t0; } else { t0 = $[4]; } let t1; if ($[5] !== containerRef || $[6] !== isSubmenu || $[7] !== onClose || $[8] !== open) { t1 = [open, onClose, containerRef, isSubmenu]; $[5] = containerRef; $[6] = isSubmenu; $[7] = onClose; $[8] = open; $[9] = t1; } else { t1 = $[9]; } React__default.default.useEffect(t0, t1); }; /** * When Arrow Keys are pressed and the focus is on the anchor, * focus should move to a menu item */ const useMoveFocusToMenuItem = (open, containerRef, anchorRef) => { const $ = reactCompilerRuntime.c(8); let t0; if ($[0] !== (anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current) || $[1] !== (containerRef === null || containerRef === void 0 ? void 0 : containerRef.current) || $[2] !== open) { t0 = () => { const container = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current; const anchor = anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current; const handler = event => { if (!open || !container) { return; } const iterable = utils.iterateFocusableElements(container); if (event.key === "ArrowDown") { const firstElement = iterable.next().value; setTimeout(() => firstElement === null || firstElement === void 0 ? void 0 : firstElement.focus()); } else { if (event.key === "ArrowUp") { const elements = [...iterable]; const lastElement = elements[elements.length - 1]; setTimeout(() => lastElement.focus()); } } }; anchor === null || anchor === void 0 ? void 0 : anchor.addEventListener("keydown", handler); return () => anchor === null || anchor === void 0 ? void 0 : anchor.addEventListener("keydown", handler); }; $[0] = anchorRef === null || anchorRef === void 0 ? void 0 : anchorRef.current; $[1] = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current; $[2] = open; $[3] = t0; } else { t0 = $[3]; } let t1; if ($[4] !== anchorRef || $[5] !== containerRef || $[6] !== open) { t1 = [open, containerRef, anchorRef]; $[4] = anchorRef; $[5] = containerRef; $[6] = open; $[7] = t1; } else { t1 = $[7]; } React__default.default.useEffect(t0, t1); }; exports.useMenuKeyboardNavigation = useMenuKeyboardNavigation;