21700: Install Bundler system-wide in Rails postinst
[arvados.git] / services / workbench2 / src / components / multiselect-toolbar / ms-toolbar-overflow-menu.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React, { useState, useMemo, ReactElement, JSXElementConstructor } from 'react';
6 import { DoubleRightArrows } from 'components/icon/icon';
7 import classnames from 'classnames';
8 import { IconButton, Menu, MenuItem, StyleRulesCallback, Tooltip, WithStyles, withStyles } from '@material-ui/core';
9 import { ArvadosTheme } from 'common/custom-theme';
10
11 type CssRules = 'inOverflowMenu' | 'openMenuButton' | 'menu' | 'menuItem' | 'menuElement';
12
13 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
14     inOverflowMenu: {
15         '&:hover': {
16             backgroundColor: 'transparent',
17         },
18     },
19     openMenuButton: {
20         right: '10px',
21     },
22     menu: {
23         marginLeft: 0,
24     },
25     menuItem: {
26         '&:hover': {
27             backgroundColor: 'white',
28         },
29         marginTop: 0,
30         paddingTop: 0,
31         paddingLeft: '1rem',
32         height: '2.5rem',
33     },
34     menuElement: {
35         width: '2rem',
36     }
37 });
38
39 export type OverflowChild = ReactElement<{ className: string; }, string | JSXElementConstructor<any>>
40
41 type OverflowMenuProps = {
42     children: OverflowChild[]
43     className: string
44     visibilityMap: {}
45 }
46
47 export const OverflowMenu = withStyles(styles)((props: OverflowMenuProps & WithStyles<CssRules>) => {
48     const { children, className, visibilityMap, classes } = props;
49     const [anchorEl, setAnchorEl] = useState(null);
50     const open = Boolean(anchorEl);
51     const handleClick = (event) => {
52         setAnchorEl(event.currentTarget);
53     };
54
55     const handleClose = () => {
56         setAnchorEl(null);
57     };
58
59     const shouldShowMenu = useMemo(() => Object.values(visibilityMap).some((v) => v === false), [visibilityMap]);
60     if (!shouldShowMenu) {
61         return null;
62     }
63     return (
64         <div className={className}>
65             <Tooltip title="More Options" disableFocusListener>
66                 <IconButton
67                     aria-label='more'
68                     aria-controls='long-menu'
69                     aria-haspopup='true'
70                     onClick={handleClick}
71                     className={classes.openMenuButton}
72                 >
73                         <DoubleRightArrows />
74                 </IconButton>
75             </Tooltip>
76             <Menu
77                 id='long-menu'
78                 anchorEl={anchorEl}
79                 keepMounted
80                 open={open}
81                 onClose={handleClose}
82                 disableAutoFocusItem
83                 className={classes.menu}
84             >
85                 {React.Children.map(children, (child: any) => {
86                     if (!visibilityMap[child.props['data-targetid']]) {
87                         return <MenuItem
88                                 key={child}
89                                 onClick={handleClose}
90                                 className={classes.menuItem}
91                             >
92                                 {React.cloneElement(child, {
93                                     className: classnames(classes.menuElement),
94                                 })}
95                             </MenuItem>
96                     }
97                     return null;
98                 })}
99             </Menu>
100         </div>
101     );
102 });