/*
* This file is part of Cockpit.
*
* Copyright (C) 2019 Red Hat, Inc.
*
* Cockpit is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Cockpit is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Cockpit; If not, see .
*/
import React from "react";
import PropTypes from "prop-types";
import { Menu, MenuContent } from "@patternfly/react-core/dist/esm/components/Menu";
import "context-menu.scss";
/*
* A context menu component
*
* It requires two properties:
* - parentId, area in which it listens to left button click
* - children, a MenuList to be rendered in the context menu
*/
export const ContextMenu = ({ parentId, children }) => {
const [visible, setVisible] = React.useState(false);
const [event, setEvent] = React.useState(null);
const root = React.useRef(null);
React.useEffect(() => {
const _handleContextMenu = (event) => {
event.preventDefault();
setVisible(true);
setEvent(event);
};
const _handleClick = (event) => {
if (event && event.button === 0) {
const wasOutside = !(event.target.contains === root.current);
if (wasOutside)
setVisible(false);
}
};
const parent = document.getElementById(parentId);
parent.addEventListener('contextmenu', _handleContextMenu);
document.addEventListener('click', _handleClick);
return () => {
parent.removeEventListener('contextmenu', _handleContextMenu);
document.removeEventListener('click', _handleClick);
};
}, [parentId]);
React.useEffect(() => {
if (!event)
return;
const clickX = event.clientX;
const clickY = event.clientY;
const screenW = window.innerWidth;
const screenH = window.innerHeight;
const rootW = root.current.offsetWidth;
const rootH = root.current.offsetHeight;
const right = (screenW - clickX) > rootW;
const left = !right;
const top = (screenH - clickY) > rootH;
const bottom = !top;
if (right) {
root.current.style.left = `${clickX + 5}px`;
}
if (left) {
root.current.style.left = `${clickX - rootW - 5}px`;
}
if (top) {
root.current.style.top = `${clickY + 5}px`;
}
if (bottom) {
root.current.style.top = `${clickY - rootH - 5}px`;
}
}, [event]);
return visible &&
;
};
ContextMenu.propTypes = {
parentId: PropTypes.string.isRequired,
children: PropTypes.any
};