@octopusdeploy/design-system-components
Version:
The design systems component library.
41 lines (40 loc) • 3.07 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomMenu = CustomMenu;
const jsx_runtime_1 = require("react/jsx-runtime");
const css_1 = require("@emotion/css");
const Menu_1 = __importDefault(require("@mui/material/Menu"));
const design_system_tokens_1 = require("@octopusdeploy/design-system-tokens");
const react_1 = require("react");
const flattenFragments_1 = require("../../utils/flattenFragments");
function CustomMenu(props) {
const { children, anchorOrigin, onKeyDown, accessibleName } = props;
const { isOpen, onClose, anchorElement, menuId } = "menuState" in props ? props.menuState : props;
const anchorOriginWithDefaults = (0, react_1.useMemo)(() => ({
horizontal: anchorOrigin?.horizontal ?? "left",
vertical: anchorOrigin?.vertical ?? "bottom",
}), [anchorOrigin]);
//Menus are generally removed from the usual flow of elements so mouse events like click / mouse down etc. are a bit
//surprising to receive in containing elements such as overflow titles etc. as these can have unintended behaviors.
const stopEventPropagation = (0, react_1.useCallback)((event) => event.stopPropagation(), []);
// If we specify an onKeyDown prop (even if it is undefined), this will overwrite material-uis onkeydown handler for modals (i.e. escape handling)
// It looks like this might be fixed in more recent versions of material-ui (https://github.com/mui-org/material-ui/blob/4323c7706b6b641dcc9ed51f00ff163e5f80966f/packages/mui-base/src/ModalUnstyled/ModalUnstyled.js#L210-L212)
// Currently, this means that escape won't work for nested menus
const onKeyDownProps = onKeyDown ? { onKeyDown } : {};
// Material-ui Menus don't support fragments as children
// This is so that they can inspect the props of their children in order to work out which one is selected
// This is using a feature of menus (selection) that we don't use, so for our usages we can allow fragments
const childrenWithoutFragments = (0, flattenFragments_1.flattenFragments)(children);
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(Menu_1.default, { id: menuId, open: isOpen, onClose: onClose, anchorEl: anchorElement, autoFocus: false, MenuListProps: { component: "div", "aria-label": accessibleName, className: menuListStyles }, anchorOrigin: anchorOriginWithDefaults, onMouseDown: stopEventPropagation, onMouseUp: stopEventPropagation, onClick: stopEventPropagation, ...onKeyDownProps, children: childrenWithoutFragments }) }));
}
const menuListStyles = (0, css_1.css)({
"&.MuiList-root": {
backgroundColor: design_system_tokens_1.themeTokens.color.menuList.background.default,
border: `solid 1px ${design_system_tokens_1.themeTokens.color.border.primary}`,
borderRadius: design_system_tokens_1.borderRadius.small,
},
});
CustomMenu.displayName = "CustomMenu";