import { CircularProgress, ClickAwayListener, Grow, MenuItem, MenuList, Paper, Popper, Typography, } from "@material-ui/core"; import { IconButtonProps, makeStyles, SettingsIcon } from "@saleor/macaw-ui"; import classNames from "classnames"; import React, { useEffect, useRef, useState } from "react"; import { FormattedMessage } from "react-intl"; import { IconButton } from "../IconButton"; import { cardMenuMessages as messages } from "./messages"; const ITEM_HEIGHT = 48; export interface CardMenuItem { disabled?: boolean; label: string; testId?: string; onSelect: () => void; loading?: boolean; withLoading?: boolean; hasError?: boolean; } export interface CardMenuProps { className?: string; disabled?: boolean; menuItems: CardMenuItem[]; outlined?: boolean; Icon?: React.ElementType<{}>; IconButtonProps?: IconButtonProps; } const useStyles = makeStyles( theme => ({ container: { zIndex: 1, }, iconButton: { background: theme.palette.background.paper, borderRadius: "100%", height: 32, padding: 0, width: 32, }, paper: { marginTop: theme.spacing(2), maxHeight: ITEM_HEIGHT * 4.5, overflowY: "scroll", }, loadingContent: { width: "100%", display: "grid", gridTemplateColumns: "1fr 24px", gap: theme.spacing(2), alignItems: "center", justifyContent: "flex-end", }, }), { name: "CardMenu" }, ); const CardMenu: React.FC = props => { const { className, disabled, menuItems, outlined, Icon: icon, IconButtonProps = {}, ...rest } = props; const classes = useStyles(props); const anchorRef = useRef(null); const [open, setOpen] = useState(false); const handleToggle = () => setOpen(prevOpen => !prevOpen); const handleClose = (event: React.MouseEvent) => { if ( anchorRef.current && anchorRef.current.contains(event.target as HTMLElement) ) { return; } setOpen(false); }; const handleListKeyDown = (event: React.KeyboardEvent) => { if (event.key === "Tab") { event.preventDefault(); setOpen(false); } }; const prevOpen = useRef(open); useEffect(() => { if (prevOpen.current === true && open === false) { anchorRef.current!.focus(); } prevOpen.current = open; }, [open]); useEffect(() => { const hasAnyItemsLoadingOrWithError = menuItems ?.filter(({ withLoading }) => withLoading) ?.some(({ loading, hasError }) => loading || hasError); if (!hasAnyItemsLoadingOrWithError) { setOpen(false); } }, [menuItems]); const handleMenuClick = (index: number) => { const selectedItem = menuItems[index]; selectedItem.onSelect(); if (!selectedItem.withLoading) { setOpen(false); } }; const isWithLoading = menuItems.some(({ withLoading }) => withLoading); const Icon = icon ?? SettingsIcon; return (
{({ TransitionProps, placement }) => ( {menuItems.map((menuItem, menuItemIndex) => ( handleMenuClick(menuItemIndex)} key={menuItem.label} button >
{menuItem.loading ? ( <> ) : ( {menuItem.label} )}
))}
)}
); }; CardMenu.displayName = "CardMenu"; export default CardMenu;