2020-01-07 07:50:59 +05:00
|
|
|
import React from "react";
|
|
|
|
import { Popover } from "./Popover";
|
|
|
|
import { render, unmountComponentAtNode } from "react-dom";
|
|
|
|
|
|
|
|
import "./ContextMenu.css";
|
|
|
|
|
|
|
|
type ContextMenuOption = {
|
|
|
|
label: string;
|
|
|
|
action(): void;
|
|
|
|
};
|
|
|
|
|
|
|
|
type Props = {
|
|
|
|
options: ContextMenuOption[];
|
|
|
|
onCloseRequest?(): void;
|
|
|
|
top: number;
|
|
|
|
left: number;
|
|
|
|
};
|
|
|
|
|
|
|
|
function ContextMenu({ options, onCloseRequest, top, left }: Props) {
|
|
|
|
return (
|
2020-01-14 09:44:18 +01:00
|
|
|
<Popover
|
|
|
|
onCloseRequest={onCloseRequest}
|
|
|
|
top={top}
|
|
|
|
left={left}
|
|
|
|
fitInViewport={true}
|
|
|
|
>
|
2020-01-07 07:50:59 +05:00
|
|
|
<ul className="context-menu" onContextMenu={e => e.preventDefault()}>
|
|
|
|
{options.map((option, idx) => (
|
|
|
|
<li
|
|
|
|
key={idx}
|
|
|
|
className="context-menu__option"
|
|
|
|
onClick={onCloseRequest}
|
|
|
|
>
|
|
|
|
<ContextMenuOption {...option} />
|
|
|
|
</li>
|
|
|
|
))}
|
|
|
|
</ul>
|
|
|
|
</Popover>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function ContextMenuOption({ label, action }: ContextMenuOption) {
|
|
|
|
return (
|
|
|
|
<button className="context-menu-option" onClick={action}>
|
|
|
|
{label}
|
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
let contextMenuNode: HTMLDivElement;
|
|
|
|
function getContextMenuNode(): HTMLDivElement {
|
|
|
|
if (contextMenuNode) {
|
|
|
|
return contextMenuNode;
|
|
|
|
}
|
|
|
|
const div = document.createElement("div");
|
|
|
|
document.body.appendChild(div);
|
|
|
|
return (contextMenuNode = div);
|
|
|
|
}
|
|
|
|
|
|
|
|
type ContextMenuParams = {
|
|
|
|
options: (ContextMenuOption | false | null | undefined)[];
|
|
|
|
top: number;
|
|
|
|
left: number;
|
|
|
|
};
|
|
|
|
|
|
|
|
function handleClose() {
|
|
|
|
unmountComponentAtNode(getContextMenuNode());
|
|
|
|
}
|
|
|
|
|
|
|
|
export default {
|
|
|
|
push(params: ContextMenuParams) {
|
|
|
|
const options = Array.of<ContextMenuOption>();
|
|
|
|
params.options.forEach(option => {
|
|
|
|
if (option) {
|
|
|
|
options.push(option);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (options.length) {
|
|
|
|
render(
|
|
|
|
<ContextMenu
|
|
|
|
top={params.top}
|
|
|
|
left={params.left}
|
|
|
|
options={options}
|
|
|
|
onCloseRequest={handleClose}
|
|
|
|
/>,
|
2020-01-24 12:04:54 +02:00
|
|
|
getContextMenuNode(),
|
2020-01-07 07:50:59 +05:00
|
|
|
);
|
|
|
|
}
|
2020-01-24 12:04:54 +02:00
|
|
|
},
|
2020-01-07 07:50:59 +05:00
|
|
|
};
|