UNPKG

glide-design-system

Version:

Glide design system is an open-source React component library. It offers numerous benefits that make them essential tools for design and development teams.

144 lines (135 loc) 4.29 kB
import React, { useEffect, useRef, useState } from "react"; import PropTypes from "prop-types"; import ReactDOM from "react-dom"; /** * Menu that wraps MenuItems * @param {*} open A boolean flag to control the visibility of the menu. If true, the menu is displayed; if false, the menu is hidden. * @param {*} onClose A function to be called when the menu should be closed or hidden. It is typically used to set the open prop to false when the user clicks outside the menu. * @param {*} position The position of the menu relative to the anchorEl element * @param {*} children The content of the menu, which can be any valid React elements or components. * @param {*} anchorEl The element to which the menu is anchored. It can be any valid React element. * @param {*} style An object containing custom styles to be applied to the container of the menu. */ export const Menu = ({ open, onClose, position = "bottom", children, anchorEl, style, className, id, name, ...props }) => { const [newPosition, setPosition] = useState(null); const menuChildRef = useRef(null); useEffect(() => { if (open && anchorEl) { if (open) { document.body.style.overflowY = "hidden"; } const anchorElRect = ReactDOM.findDOMNode(anchorEl).getBoundingClientRect(); const updatedPosition = { top: anchorElRect.top, left: anchorElRect.left, bottom: anchorElRect.bottom, right: anchorElRect.right, height: anchorElRect.height, width: anchorElRect.width, }; setPosition(updatedPosition); } return () => { document.body.style.overflowY = ""; }; }, [open, anchorEl]); let updatedPosition = null; const calpositionHandler = () => { if (open && anchorEl) { if (open) { document.body.style.overflowY = "hidden"; } const anchorElRect = ReactDOM.findDOMNode(anchorEl).getBoundingClientRect(); updatedPosition = { top: anchorElRect.top, left: anchorElRect.left, bottom: anchorElRect.bottom, right: anchorElRect.right, height: anchorElRect.height, width: anchorElRect.width, }; } }; calpositionHandler(); // using useState() // const combinedStyle = { // top: // position === "top" || position === "topLeft" || position === "topRight" // ? Math.abs(newPosition?.top - menuChildRef?.current?.offsetHeight - 5) // : newPosition && newPosition?.bottom + 5, // left: // (position === "topRight" || // position === "bottomRight" || // position === "top" || // position === "bottom") && // newPosition // ? newPosition?.left // : (position === "topLeft" || position === "bottomLeft") && newPosition // ? Math.abs(newPosition?.right - menuChildRef?.current?.offsetWidth) // : newPosition?.left, // ...style, // }; //using let const combinedStyle = { top: position === "top" || position === "topLeft" || position === "topRight" ? Math.abs( updatedPosition?.top - menuChildRef?.current?.offsetHeight - 5 ) : updatedPosition && updatedPosition?.bottom + 5, left: (position === "topRight" || position === "bottomRight" || position === "top" || position === "bottom") && updatedPosition ? updatedPosition?.left : (position === "topLeft" || position === "bottomLeft") && updatedPosition ? Math.abs(updatedPosition?.right - menuChildRef?.current?.offsetWidth) : updatedPosition?.left, ...style, }; return ( <div id={id} data-testid={id} name={name} className={open ? "menuParentContainer" : "menuContainerNoEffect"} > <div onClick={() => { onClose(); }} className="menuModalContainer" ></div> <div ref={menuChildRef} className={`menuChildContainer ${className ? className : ""}`} style={combinedStyle} {...props} > {children} </div> </div> ); }; Menu.propTypes = { position: PropTypes.string, onClose: PropTypes.func, open: PropTypes.bool, anchorEl: PropTypes.object, };