/* eslint-disable react/no-array-index-key */ import debounce from "lodash/debounce"; import React, { useCallback, useContext, useEffect, useState } from "react"; import { usePopper } from "react-popper"; import useMatchBreakpoints from "../../contexts/MatchBreakpoints/useMatchBreakpoints"; import { useOnClickOutside } from "../../hooks"; import { MenuContext } from "../../widgets/Menu/context"; import { Box, Flex } from "../Box"; import { LogoutIcon } from "../Svg"; import { DropdownMenuDivider, DropdownMenuItem, LinkStatus, StyledDropdownMenu, StyledDropdownMenuItemContainer, } from "./styles"; import { DropdownMenuItemType, DropdownMenuProps } from "./types"; const DropdownMenu: React.FC> = ({ children, isBottomNav = false, showItemsOnMobile = false, activeItem = "", items = [], index, setMenuOpenByIndex, isDisabled, ...props }) => { const { linkComponent } = useContext(MenuContext); const [isOpen, setIsOpen] = useState(false); const { isMobile, isMd } = useMatchBreakpoints(); const [targetRef, setTargetRef] = useState(null); const [tooltipRef, setTooltipRef] = useState(null); const hasItems = items.length > 0; const { styles, attributes } = usePopper(targetRef, tooltipRef, { strategy: isBottomNav ? "absolute" : "fixed", placement: isBottomNav ? "top" : "bottom-start", modifiers: [{ name: "offset", options: { offset: [0, isBottomNav ? 6 : 0] } }], }); const isMenuShow = isOpen && ((isBottomNav && showItemsOnMobile) || !isBottomNav); useEffect(() => { const showDropdownMenu = () => { setIsOpen(true); hideDropdownMenu.cancel(); }; const hideDropdownMenu = debounce( () => { setIsOpen(false); }, isBottomNav ? 100 : 10 ); // added this to remove the ugly 4 lines [targetRef, tooltipRef].forEach((ref) => { ref?.addEventListener("mouseenter", showDropdownMenu); ref?.addEventListener("mouseleave", hideDropdownMenu); }); return () => { [targetRef, tooltipRef].forEach((ref) => { ref?.removeEventListener("mouseenter", showDropdownMenu); ref?.removeEventListener("mouseleave", hideDropdownMenu); }); hideDropdownMenu.cancel(); }; }, [setIsOpen, tooltipRef, targetRef, isBottomNav]); useEffect(() => { if (setMenuOpenByIndex && index !== undefined) { setMenuOpenByIndex((prevValue) => ({ ...prevValue, [index]: isMenuShow })); } }, [isMenuShow, setMenuOpenByIndex, index]); useOnClickOutside( targetRef, useCallback(() => { setIsOpen(false); }, [setIsOpen]) ); return ( { setIsOpen((s) => !s); }} > {children} {hasItems && ( {items .filter((item) => ((isMobile || isMd) && item.isMobileOnly) || !item.isMobileOnly) .map( ( { type = DropdownMenuItemType.INTERNAL_LINK, label, href = "/", status, disabled, ...itemProps }, itemItem ) => { const MenuItemContent = ( {label} {status && ( {status.text} )} ); const isActive = href === activeItem; return ( {type === DropdownMenuItemType.BUTTON && ( {MenuItemContent} )} {type === DropdownMenuItemType.INTERNAL_LINK && ( { setIsOpen(false); }} {...itemProps} > {MenuItemContent} )} {type === DropdownMenuItemType.EXTERNAL_LINK && ( { setIsOpen(false); }) as any } {...itemProps} > {MenuItemContent} )} {type === DropdownMenuItemType.DIVIDER && } ); } )} )} ); }; export default DropdownMenu;