@react-md/menu
Version:
Create menus that auto-position themselves within the viewport and adhere to the accessibility guidelines
71 lines • 2.88 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import { useEffect, useMemo, useState } from "react";
import { extractTextContent, getFocusableElements, MovementPresets, useKeyboardMovement, } from "@react-md/utils";
/**
* This hook allows for the keyboard movement within a menu. It'll make sure
* that the arrow keys and typing letters can correctly focus menu items. In
* addition, it'll automatically swap to the left and right arrow keys if the
* menu is displayed horizontally.
*/
export function useMenuKeyDown(_a) {
var menu = _a.menu, onKeyDown = _a.onKeyDown, onRequestClose = _a.onRequestClose, portalled = _a.portalled, horizontal = _a.horizontal, defaultFocus = _a.defaultFocus;
var _b = useState(0), focusedIndex = _b[0], setFocusedIndex = _b[1];
var items = useMemo(function () {
if (!menu) {
return [];
}
return getFocusableElements(menu, true);
}, [menu]);
useEffect(function () {
if (!menu) {
return;
}
if (defaultFocus === "last") {
setFocusedIndex(items.length - 1);
}
else {
setFocusedIndex(0);
}
// only want to trigger this on initial menu mount
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [menu]);
return useKeyboardMovement(__assign(__assign({}, (horizontal
? MovementPresets.HORIZONTAL_MENU
: MovementPresets.VERTICAL_MENU)), { focusedIndex: focusedIndex,
onChange: function (_a) {
var index = _a.index;
setFocusedIndex(index);
if (items[index]) {
items[index].focus();
}
}, items: items.map(function (item) { return extractTextContent(item); }), onKeyDown: function (event) {
if (onKeyDown) {
onKeyDown(event);
}
if (event.key === "Escape") {
event.stopPropagation();
onRequestClose();
}
else if (event.key === "Tab") {
if (portalled) {
// have to prevent default tab behavior since tab order is ruined when
// something is portalled. this will make it interact the same as if
// it was an escape keypress. it's too much work to try to emulate a
// real tab here
event.preventDefault();
}
onRequestClose();
}
} }))[1];
}
//# sourceMappingURL=useMenuKeyDown.js.map