@react-md/menu
Version:
Create menus that auto-position themselves within the viewport and adhere to the accessibility guidelines
55 lines • 2.58 kB
JavaScript
import { useCloseOnOutsideClick, useEnsuredRef } from "@react-md/utils";
import { useMenuClick } from "./useMenuClick";
import { useMenuKeyDown } from "./useMenuKeyDown";
/**
* This hook is used to provide all the menu functionality within the `Menu`
* component. It'll ensure that:
*
* - the menu will be closed if an element outside of the menu is clicked
* - the menu items within the menu are keyboard focusable after typing or using
* the arrow keys
* - the menu will close if the Escape key or Tab key is pressed (tab since
* it'll lose focus)
* - conditionally close the menu if the page is scrolled while visible.
*/
export function useMenu(_a) {
var propRef = _a.ref, visible = _a.visible, controlId = _a.controlId, _b = _a.horizontal, horizontal = _b === void 0 ? false : _b, propOnClick = _a.onClick, propOnKeyDown = _a.onKeyDown, _c = _a.portalled, portalled = _c === void 0 ? false : _c, defaultFocus = _a.defaultFocus, onRequestClose = _a.onRequestClose, _d = _a.disableControlClickOkay, disableControlClickOkay = _d === void 0 ? false : _d;
var _e = useEnsuredRef(propRef), ref = _e[0], refHandler = _e[1];
useCloseOnOutsideClick({
element: ref,
enabled: visible,
onOutsideClick: function (element, target, contains) {
if (!element || !target) {
return;
}
var control = document.getElementById(controlId);
// Need to also check if we have an `aria-expanded` visible anywhere since
// the child menus need to be portalled out to fix the overflow issue in
// Safari. If we didn't need to portal, this line could be removed as the
// `menu.current` would contain the child menu and not close.
var expanded = ref.current &&
ref.current.querySelector('[aria-expanded="true"]') &&
target.closest('[role="menu"]');
if ((disableControlClickOkay || !contains(control, target)) &&
!expanded) {
onRequestClose();
}
},
});
var onClick = useMenuClick({ onClick: propOnClick, onRequestClose: onRequestClose });
var onKeyDown = useMenuKeyDown({
menu: ref.current,
onKeyDown: propOnKeyDown,
onRequestClose: onRequestClose,
portalled: portalled,
horizontal: horizontal,
defaultFocus: defaultFocus,
});
return {
ref: refHandler,
menuRef: ref,
onClick: onClick,
onKeyDown: onKeyDown,
};
}
//# sourceMappingURL=useMenu.js.map