diff --git a/example/src/Overview/index.tsx b/example/src/Overview/index.tsx index 2017a47c..27fd4137 100644 --- a/example/src/Overview/index.tsx +++ b/example/src/Overview/index.tsx @@ -40,6 +40,7 @@ const onLoad = (reactFlowInstance: OnLoadParams) => { }; const onMoveEnd = (transform?: FlowTransform) => console.log('zoom/move end', transform); +const onEdgeContextMenu = (_: MouseEvent, edge: Edge) => console.log('edge context menu', edge); const initialElements: Elements = [ { @@ -177,6 +178,7 @@ const OverviewFlow = () => { connectionLineStyle={connectionLineStyle} snapToGrid={true} snapGrid={snapGrid} + onEdgeContextMenu={onEdgeContextMenu} > diff --git a/src/components/Edges/wrapEdge.tsx b/src/components/Edges/wrapEdge.tsx index 351e3a52..509974b1 100644 --- a/src/components/Edges/wrapEdge.tsx +++ b/src/components/Edges/wrapEdge.tsx @@ -1,4 +1,4 @@ -import React, { memo, ComponentType, useCallback, useState } from 'react'; +import React, { memo, ComponentType, useCallback, useState, useMemo } from 'react'; import cc from 'classcat'; import { useStoreActions, useStoreState } from '../../store/hooks'; @@ -37,7 +37,8 @@ export default (EdgeComponent: ComponentType) => { targetHandleId, handleEdgeUpdate, onConnectEdge, - }: WrapEdgeProps) => { + onContextMenu, + }: WrapEdgeProps): JSX.Element | null => { const addSelectedElements = useStoreActions((actions) => actions.addSelectedElements); const setConnectionNodeId = useStoreActions((actions) => actions.setConnectionNodeId); const setPosition = useStoreActions((actions) => actions.setConnectionPosition); @@ -53,34 +54,45 @@ export default (EdgeComponent: ComponentType) => { { selected, animated, inactive, updating }, ]); + const edgeElement = useMemo(() => { + const el: Edge = { + id, + source, + target, + type, + }; + + if (sourceHandleId) { + el.sourceHandle = sourceHandleId; + } + + if (targetHandleId) { + el.targetHandle = targetHandleId; + } + + if (typeof data !== 'undefined') { + el.data = data; + } + + return el; + }, [id, source, target, type, sourceHandleId, targetHandleId, data]); + const onEdgeClick = useCallback( (event: React.MouseEvent): void => { - const edgeElement: Edge = { - id, - source, - target, - type, - }; - - if (sourceHandleId) { - edgeElement.sourceHandle = sourceHandleId; - } - - if (targetHandleId) { - edgeElement.targetHandle = targetHandleId; - } - - if (typeof data !== 'undefined') { - edgeElement.data = data; - } - if (elementsSelectable) { addSelectedElements(edgeElement); } onClick?.(event, edgeElement); }, - [elementsSelectable, id, source, target, type, data, sourceHandleId, targetHandleId, onClick] + [elementsSelectable, edgeElement, onClick] + ); + + const onEdgeContextMenu = useCallback( + (event: React.MouseEvent): void => { + onContextMenu?.(event, edgeElement); + }, + [edgeElement, onContextMenu] ); const handleEdgeUpdater = useCallback( @@ -127,7 +139,7 @@ export default (EdgeComponent: ComponentType) => { } return ( - + {handleEdgeUpdate && ( void; } interface EdgeWrapperProps { @@ -163,6 +164,7 @@ const Edge = ({ isHidden={edge.isHidden} onConnectEdge={onConnectEdge} handleEdgeUpdate={typeof props.onEdgeUpdate !== 'undefined'} + onContextMenu={props.onEdgeContextMenu} /> ); }; diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index 780f8fcc..c9dbe149 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -85,6 +85,7 @@ const GraphView = ({ onPaneScroll, onPaneContextMenu, onEdgeUpdate, + onEdgeContextMenu, }: GraphViewProps) => { const isInitialised = useRef(false); const setOnConnect = useStoreActions((actions) => actions.setOnConnect); @@ -262,6 +263,7 @@ const GraphView = ({ markerEndId={markerEndId} onEdgeUpdate={onEdgeUpdate} onlyRenderVisibleElements={onlyRenderVisibleElements} + onEdgeContextMenu={onEdgeContextMenu} /> ); diff --git a/src/container/ReactFlow/index.tsx b/src/container/ReactFlow/index.tsx index 77af0d96..108b7273 100644 --- a/src/container/ReactFlow/index.tsx +++ b/src/container/ReactFlow/index.tsx @@ -109,6 +109,7 @@ export interface ReactFlowProps extends Omit, 'on panOnScrollMode?: PanOnScrollMode; zoomOnDoubleClick?: boolean; onEdgeUpdate?: OnEdgeUpdateFunc; + onEdgeContextMenu?: (event: MouseEvent, nodes: Edge) => void; } const ReactFlow = ({ @@ -173,6 +174,7 @@ const ReactFlow = ({ onPaneContextMenu, children, onEdgeUpdate, + onEdgeContextMenu, ...rest }: ReactFlowProps) => { const nodeTypesParsed = useMemo(() => createNodeTypes(nodeTypes), []); @@ -240,6 +242,7 @@ const ReactFlow = ({ onSelectionDragStop={onSelectionDragStop} onSelectionContextMenu={onSelectionContextMenu} onEdgeUpdate={onEdgeUpdate} + onEdgeContextMenu={onEdgeContextMenu} /> {onSelectionChange && } diff --git a/src/types/index.ts b/src/types/index.ts index edea4031..a3a94c86 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -125,6 +125,7 @@ export interface WrapEdgeProps { isHidden?: boolean; handleEdgeUpdate: boolean; onConnectEdge: OnConnectFunc; + onContextMenu: (event: React.MouseEvent, edge: Edge) => void; } export interface EdgeProps {