@primer/react
Version:
An implementation of GitHub's Primer Design System using React
166 lines (157 loc) • 6.42 kB
JavaScript
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;
;