1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- 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 (
- <Popover
- onCloseRequest={onCloseRequest}
- top={top}
- left={left}
- fitInViewport={true}
- >
- <ul
- className="context-menu"
- onContextMenu={(event) => event.preventDefault()}
- >
- {options.map((option, idx) => (
- <li key={idx} 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}
- />,
- getContextMenuNode(),
- );
- }
- },
- };
|