import * as React from 'react'; import { IPoint } from '../../Interfaces/IPoint'; import { MenuItem } from './MenuItem'; interface IMenuProps { getListener: () => HTMLElement | null actions: Map className?: string } export interface IMenuAction { /** displayed */ text: string /** function to be called on button click */ action: (target: HTMLElement) => void } function UseMouseEvents( getListener: () => HTMLElement | null, setIsOpen: React.Dispatch>, setContextMenuPosition: React.Dispatch>, setTarget: React.Dispatch> ): void { React.useEffect(() => { function OnContextMenu(event: MouseEvent): void { event.preventDefault(); const contextMenuPosition: IPoint = { x: event.pageX, y: event.pageY }; setIsOpen(true); setContextMenuPosition(contextMenuPosition); setTarget(event.target as HTMLElement); // this is wrong since target can be null and not undefined } function OnLeftClick(): void { setIsOpen(false); } getListener()?.addEventListener( 'contextmenu', OnContextMenu ); window.addEventListener( 'click', OnLeftClick ); return () => { getListener()?.removeEventListener( 'contextmenu', OnContextMenu ); window.removeEventListener( 'click', OnLeftClick ); }; }); } export function Menu(props: IMenuProps): JSX.Element { const [isOpen, setIsOpen] = React.useState(false); const [contextMenuPosition, setContextMenuPosition] = React.useState({ x: 0, y: 0 }); const [target, setTarget] = React.useState(); UseMouseEvents( props.getListener, setIsOpen, setContextMenuPosition, setTarget ); const children: JSX.Element[] = []; if (target !== undefined) { let count = 0; for (const className of target.classList) { count++; const actions = props.actions.get(className); if (actions === undefined) { continue; } actions.forEach((action, index) => { children.push( action.action(target)} />); }); }; } // TODO: Fix css const visible = isOpen ? 'visible opacity-1' : 'invisible opacity-0'; return (
{ children }
); }