feat(edge): add onEdgeContextMenu handler #943

This commit is contained in:
moklick
2021-02-26 10:51:25 +01:00
parent c7b04dbc0f
commit 0d1d802ed5
6 changed files with 45 additions and 23 deletions
+2
View File
@@ -40,6 +40,7 @@ const onLoad = (reactFlowInstance: OnLoadParams) => {
}; };
const onMoveEnd = (transform?: FlowTransform) => console.log('zoom/move end', transform); const onMoveEnd = (transform?: FlowTransform) => console.log('zoom/move end', transform);
const onEdgeContextMenu = (_: MouseEvent, edge: Edge) => console.log('edge context menu', edge);
const initialElements: Elements = [ const initialElements: Elements = [
{ {
@@ -177,6 +178,7 @@ const OverviewFlow = () => {
connectionLineStyle={connectionLineStyle} connectionLineStyle={connectionLineStyle}
snapToGrid={true} snapToGrid={true}
snapGrid={snapGrid} snapGrid={snapGrid}
onEdgeContextMenu={onEdgeContextMenu}
> >
<MiniMap nodeStrokeColor={nodeStrokeColor} nodeColor={nodeColor} nodeBorderRadius={2} /> <MiniMap nodeStrokeColor={nodeStrokeColor} nodeColor={nodeColor} nodeBorderRadius={2} />
<Controls /> <Controls />
+35 -23
View File
@@ -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 cc from 'classcat';
import { useStoreActions, useStoreState } from '../../store/hooks'; import { useStoreActions, useStoreState } from '../../store/hooks';
@@ -37,7 +37,8 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
targetHandleId, targetHandleId,
handleEdgeUpdate, handleEdgeUpdate,
onConnectEdge, onConnectEdge,
}: WrapEdgeProps) => { onContextMenu,
}: WrapEdgeProps): JSX.Element | null => {
const addSelectedElements = useStoreActions((actions) => actions.addSelectedElements); const addSelectedElements = useStoreActions((actions) => actions.addSelectedElements);
const setConnectionNodeId = useStoreActions((actions) => actions.setConnectionNodeId); const setConnectionNodeId = useStoreActions((actions) => actions.setConnectionNodeId);
const setPosition = useStoreActions((actions) => actions.setConnectionPosition); const setPosition = useStoreActions((actions) => actions.setConnectionPosition);
@@ -53,34 +54,45 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
{ selected, animated, inactive, updating }, { selected, animated, inactive, updating },
]); ]);
const edgeElement = useMemo<Edge>(() => {
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( const onEdgeClick = useCallback(
(event: React.MouseEvent<SVGGElement, MouseEvent>): void => { (event: React.MouseEvent<SVGGElement, 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) { if (elementsSelectable) {
addSelectedElements(edgeElement); addSelectedElements(edgeElement);
} }
onClick?.(event, edgeElement); onClick?.(event, edgeElement);
}, },
[elementsSelectable, id, source, target, type, data, sourceHandleId, targetHandleId, onClick] [elementsSelectable, edgeElement, onClick]
);
const onEdgeContextMenu = useCallback(
(event: React.MouseEvent<SVGGElement, MouseEvent>): void => {
onContextMenu?.(event, edgeElement);
},
[edgeElement, onContextMenu]
); );
const handleEdgeUpdater = useCallback( const handleEdgeUpdater = useCallback(
@@ -127,7 +139,7 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
} }
return ( return (
<g className={edgeClasses} onClick={onEdgeClick}> <g className={edgeClasses} onClick={onEdgeClick} onContextMenu={onEdgeContextMenu}>
{handleEdgeUpdate && ( {handleEdgeUpdate && (
<g <g
onMouseDown={onEdgeUpdaterSourceMouseDown} onMouseDown={onEdgeUpdaterSourceMouseDown}
+2
View File
@@ -29,6 +29,7 @@ interface EdgeRendererProps {
markerEndId?: string; markerEndId?: string;
onlyRenderVisibleElements: boolean; onlyRenderVisibleElements: boolean;
onEdgeUpdate?: OnEdgeUpdateFunc; onEdgeUpdate?: OnEdgeUpdateFunc;
onEdgeContextMenu?: (event: React.MouseEvent, element: Edge) => void;
} }
interface EdgeWrapperProps { interface EdgeWrapperProps {
@@ -163,6 +164,7 @@ const Edge = ({
isHidden={edge.isHidden} isHidden={edge.isHidden}
onConnectEdge={onConnectEdge} onConnectEdge={onConnectEdge}
handleEdgeUpdate={typeof props.onEdgeUpdate !== 'undefined'} handleEdgeUpdate={typeof props.onEdgeUpdate !== 'undefined'}
onContextMenu={props.onEdgeContextMenu}
/> />
); );
}; };
+2
View File
@@ -85,6 +85,7 @@ const GraphView = ({
onPaneScroll, onPaneScroll,
onPaneContextMenu, onPaneContextMenu,
onEdgeUpdate, onEdgeUpdate,
onEdgeContextMenu,
}: GraphViewProps) => { }: GraphViewProps) => {
const isInitialised = useRef<boolean>(false); const isInitialised = useRef<boolean>(false);
const setOnConnect = useStoreActions((actions) => actions.setOnConnect); const setOnConnect = useStoreActions((actions) => actions.setOnConnect);
@@ -262,6 +263,7 @@ const GraphView = ({
markerEndId={markerEndId} markerEndId={markerEndId}
onEdgeUpdate={onEdgeUpdate} onEdgeUpdate={onEdgeUpdate}
onlyRenderVisibleElements={onlyRenderVisibleElements} onlyRenderVisibleElements={onlyRenderVisibleElements}
onEdgeContextMenu={onEdgeContextMenu}
/> />
</FlowRenderer> </FlowRenderer>
); );
+3
View File
@@ -109,6 +109,7 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
panOnScrollMode?: PanOnScrollMode; panOnScrollMode?: PanOnScrollMode;
zoomOnDoubleClick?: boolean; zoomOnDoubleClick?: boolean;
onEdgeUpdate?: OnEdgeUpdateFunc; onEdgeUpdate?: OnEdgeUpdateFunc;
onEdgeContextMenu?: (event: MouseEvent, nodes: Edge) => void;
} }
const ReactFlow = ({ const ReactFlow = ({
@@ -173,6 +174,7 @@ const ReactFlow = ({
onPaneContextMenu, onPaneContextMenu,
children, children,
onEdgeUpdate, onEdgeUpdate,
onEdgeContextMenu,
...rest ...rest
}: ReactFlowProps) => { }: ReactFlowProps) => {
const nodeTypesParsed = useMemo(() => createNodeTypes(nodeTypes), []); const nodeTypesParsed = useMemo(() => createNodeTypes(nodeTypes), []);
@@ -240,6 +242,7 @@ const ReactFlow = ({
onSelectionDragStop={onSelectionDragStop} onSelectionDragStop={onSelectionDragStop}
onSelectionContextMenu={onSelectionContextMenu} onSelectionContextMenu={onSelectionContextMenu}
onEdgeUpdate={onEdgeUpdate} onEdgeUpdate={onEdgeUpdate}
onEdgeContextMenu={onEdgeContextMenu}
/> />
<ElementUpdater elements={elements} /> <ElementUpdater elements={elements} />
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />} {onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
+1
View File
@@ -125,6 +125,7 @@ export interface WrapEdgeProps<T = any> {
isHidden?: boolean; isHidden?: boolean;
handleEdgeUpdate: boolean; handleEdgeUpdate: boolean;
onConnectEdge: OnConnectFunc; onConnectEdge: OnConnectFunc;
onContextMenu: (event: React.MouseEvent, edge: Edge) => void;
} }
export interface EdgeProps<T = any> { export interface EdgeProps<T = any> {