import { useContext, useState, useCallback, useEffect } from 'react'; import { observer } from 'mobx-react'; import { Spinner } from '@patternfly/react-core'; import { GraphElement as TopologyElement } from '../types'; import ElementContext from '../utils/ElementContext'; import ContextMenu from '../components/contextmenu/ContextMenu'; type Reference = React.ComponentProps['reference']; export interface WithContextMenuProps { onContextMenu?: (e: React.MouseEvent) => void; contextMenuOpen?: boolean; } export const withContextMenu = ( actions: (element: E) => React.ReactElement[] | Promise, container?: Element | null | undefined | (() => Element), className?: string, atPoint: boolean = true, waitElement: React.ReactElement = ) =>

(WrappedComponent: React.ComponentType

) => { const Component: React.FunctionComponent> = (props) => { const element = useContext(ElementContext); const [reference, setReference] = useState(null); const [elementActions, setElementActions] = useState(null); const onContextMenu = useCallback((e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); setReference( atPoint ? { x: e.pageX, y: e.pageY } : e.currentTarget ); }, []); useEffect(() => { if (reference) { const actionsElements = actions(element as E); Promise.resolve(actionsElements).then((resultActions) => { setElementActions(resultActions); }); } else { setElementActions(null); } }, [element, reference]); return ( <> {reference ? ( setReference(null)} > {elementActions || waitElement} ) : null} ); }; Component.displayName = `withContextMenu(${WrappedComponent.displayName || WrappedComponent.name})`; return observer(Component); };