Local modifications to ClusterLabs/Anvil by Alteeve
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
2.4 KiB

import { MoreVert as MoreVertIcon } from '@mui/icons-material';
import { Box } from '@mui/material';
import { FC, MouseEventHandler, useCallback, useMemo, useState } from 'react';
import ContainedButton from './ContainedButton';
import IconButton from './IconButton/IconButton';
import Menu from './Menu';
const ButtonWithMenu: FC<ButtonWithMenuProps> = (props) => {
const {
children,
containedButtonProps,
iconButtonProps,
muiMenuProps,
onButtonClick,
onItemClick,
variant = 'icon',
...menuProps
} = props;
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
const open = useMemo(() => Boolean(anchorEl), [anchorEl]);
const buttonContent = useMemo(() => {
if (children) {
return children;
}
if (variant === 'icon') {
return <MoreVertIcon fontSize={iconButtonProps?.size} />;
}
return 'Options';
}, [children, iconButtonProps?.size, variant]);
const buttonClickHandler = useCallback<MouseEventHandler<HTMLButtonElement>>(
(...args) => {
const {
0: { currentTarget },
} = args;
setAnchorEl(currentTarget);
return onButtonClick?.call(null, ...args);
},
[onButtonClick],
);
const buttonElement = useMemo(() => {
if (variant === 'contained') {
return (
<ContainedButton onClick={buttonClickHandler} {...containedButtonProps}>
{buttonContent}
</ContainedButton>
);
}
return (
<IconButton onClick={buttonClickHandler} {...iconButtonProps}>
{buttonContent}
</IconButton>
);
}, [
buttonClickHandler,
buttonContent,
containedButtonProps,
iconButtonProps,
variant,
]);
const itemClickHandler = useCallback<
Exclude<MenuProps['onItemClick'], undefined>
>(
(key, value, ...rest) => {
setAnchorEl(null);
return onItemClick?.call(null, key, value, ...rest);
},
[onItemClick],
);
return (
<Box>
{buttonElement}
<Menu
muiMenuProps={{
anchorEl,
keepMounted: true,
onClose: () => setAnchorEl(null),
...muiMenuProps,
}}
onItemClick={itemClickHandler}
open={open}
{...menuProps}
/>
</Box>
);
};
export default ButtonWithMenu as <T>(
...args: Parameters<FC<ButtonWithMenuProps<T>>>
) => ReturnType<FC<ButtonWithMenuProps<T>>>;