blob: 6ac136398a35d095970882e04b7d79ba92a7ccac [file] [log] [blame]
idillonef9ab812022-11-18 13:46:24 -05001/*
2 * Copyright (C) 2022 Savoir-faire Linux Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation; either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <https://www.gnu.org/licenses/>.
17 */
18import { Menu, MenuProps, PopoverPosition, PopoverReference, styled } from '@mui/material';
19import { MouseEventHandler, useCallback, useMemo, useState } from 'react';
20
21import PopoverList, { PopoverListItemData } from './PopoverList';
22
23export interface ContextMenuHandler {
24 props: {
25 open: boolean;
26 onClose: () => void;
27 anchorPosition: PopoverPosition | undefined;
28 anchorReference: PopoverReference | undefined;
29 };
30 handleAnchorPosition: MouseEventHandler;
31}
32
33export const useContextMenuHandler = (): ContextMenuHandler => {
34 const [anchorPosition, setAnchorPosition] = useState<PopoverPosition | undefined>(undefined);
35
36 const handleAnchorPosition = useCallback<MouseEventHandler>(
37 (event) => {
38 event.preventDefault();
39 setAnchorPosition((anchorPosition) =>
40 anchorPosition === undefined ? { top: event.clientY, left: event.clientX } : undefined
41 );
42 },
43 [setAnchorPosition]
44 );
45
46 const onClose = useCallback(() => setAnchorPosition(undefined), [setAnchorPosition]);
47
48 return useMemo(
49 () => ({
50 props: {
51 open: !!anchorPosition,
52 onClose,
53 anchorPosition,
54 anchorReference: 'anchorPosition',
55 },
56 handleAnchorPosition,
57 }),
58 [anchorPosition, handleAnchorPosition, onClose]
59 );
60};
61
62interface ContextMenuProps extends MenuProps {
63 items: PopoverListItemData[];
64}
65
66const ContextMenu = styled(({ items, ...props }: ContextMenuProps) => (
67 <Menu {...props}>
68 <PopoverList items={items} onClose={props.onClose} />
69 </Menu>
70))(() => ({
71 '& .MuiPaper-root': {
72 borderRadius: '5px 20px 20px 20px',
73 boxShadow: '3px 3px 7px #00000029',
74 },
75 '& .MuiMenu-list': {
76 padding: '0px',
77 },
78}));
79
80export default ContextMenu;