@activecollab/components
Version:
ActiveCollab Components
113 lines (111 loc) • 4.41 kB
JavaScript
import React, { useRef, useState, useCallback, useEffect } from "react";
import classnames from "classnames";
import { MenuContextProvider } from "./context";
import { StyledMenu } from "./Styles";
import useForkRef from "../../utils/useForkRef";
import { Overlay } from "../Overlay";
import { Popper } from "../Popper";
import { Window } from "../Window";
// source: https://twitter.com/mattpocockuk/status/1671908303918473217/photo/1
// eslint-disable-next-line @typescript-eslint/ban-types
export const Menu = _ref => {
let children = _ref.children,
_ref$disableFocusLock = _ref.disableFocusLock,
disableFocusLock = _ref$disableFocusLock === void 0 ? false : _ref$disableFocusLock,
onMenuClick = _ref.onMenuClick,
_ref$handleScroll = _ref.handleScroll,
handleScroll = _ref$handleScroll === void 0 ? true : _ref$handleScroll,
_ref$mode = _ref.mode,
mode = _ref$mode === void 0 ? "normal" : _ref$mode,
_ref$open = _ref.open,
defaultOpen = _ref$open === void 0 ? false : _ref$open,
onOpen = _ref.onOpen,
onClose = _ref.onClose,
onBeforeClose = _ref.onBeforeClose,
_ref$position = _ref.position,
position = _ref$position === void 0 ? "bottom-start" : _ref$position,
target = _ref.target,
className = _ref.className,
menuClassName = _ref.menuClassName,
popperClassName = _ref.popperClassName,
backgroundElementClass = _ref.backgroundElementClass,
_ref$windowAbsolutely = _ref.windowAbsolutelyPositioned,
windowAbsolutelyPositioned = _ref$windowAbsolutely === void 0 ? false : _ref$windowAbsolutely,
onPopperOpen = _ref.onPopperOpen;
const _useState = useState(defaultOpen),
open = _useState[0],
setOpen = _useState[1];
const _useState2 = useState(),
childNode = _useState2[0],
setChildNode = _useState2[1];
const elementRef = useRef(null);
const isOpenAtLeastOnce = useRef(false);
useEffect(() => {
setOpen(defaultOpen);
}, [defaultOpen]);
const handleRefRef = useForkRef(target ? target.ref : undefined, setChildNode);
const handleRef = useForkRef(handleRefRef, elementRef);
const handleOpen = useCallback(event => {
var _target$props;
event == null || event.preventDefault();
event == null || event.stopPropagation();
setOpen(true);
typeof onOpen === "function" && onOpen();
typeof (target == null || (_target$props = target.props) == null ? void 0 : _target$props.onClick) === "function" && target.props.onClick(event);
}, [onOpen, target == null ? void 0 : target.props]);
const handleClose = useCallback(() => {
if (typeof onBeforeClose === "function" && !onBeforeClose()) {
return;
}
setOpen(false);
typeof onClose === "function" && onClose();
}, [onClose, onBeforeClose]);
const childProps = {
forceClose: handleClose
};
const targetProps = {
open,
ref: handleRef,
onClick: handleOpen
};
useEffect(() => {
if (open) {
isOpenAtLeastOnce.current = true;
} else if (!open && isOpenAtLeastOnce.current) {
var _elementRef$current;
(_elementRef$current = elementRef.current) == null || _elementRef$current.focus();
isOpenAtLeastOnce.current = false;
}
}, [open]);
return /*#__PURE__*/React.createElement(React.Fragment, null, target && /*#__PURE__*/React.cloneElement(target, targetProps), open ? /*#__PURE__*/React.createElement(Window, {
onClose: handleClose,
disableScrollLock: !handleScroll,
disableFocusLock: disableFocusLock,
style: {
position: windowAbsolutelyPositioned ? "absolute" : "fixed"
}
}, /*#__PURE__*/React.createElement(Overlay, {
className: backgroundElementClass,
onClick: handleClose,
tabIndex: -1,
disableBackgroundColor: true
}), /*#__PURE__*/React.createElement(Popper, {
anchorEl: childNode,
open: childNode ? open : false,
placement: position,
className: popperClassName,
tabIndex: -1,
afterWrite: onPopperOpen
}, /*#__PURE__*/React.createElement(StyledMenu, {
className: classnames("c-simple-menu__paper", "c-simple-menu__" + mode, menuClassName, className),
$mode: mode,
onMouseDown: onMenuClick
}, /*#__PURE__*/React.createElement(MenuContextProvider, {
value: {
open,
setOpen
}
}, typeof children === "function" ? children(childProps) : children)))) : null);
};
Menu.displayName = "Menu";
//# sourceMappingURL=Menu.js.map