From 3dedd615af0c9a86d1dde1d236a160fa1563aeb5 Mon Sep 17 00:00:00 2001 From: moklick Date: Tue, 26 Jan 2021 18:17:29 +0100 Subject: [PATCH 1/2] feat(props): add onDrag handler --- src/components/Nodes/wrapNode.tsx | 15 +++++++++------ src/container/GraphView/index.tsx | 2 ++ src/container/NodeRenderer/index.tsx | 6 ++++-- src/container/ReactFlow/index.tsx | 5 +++++ src/types/index.ts | 3 +++ 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/components/Nodes/wrapNode.tsx b/src/components/Nodes/wrapNode.tsx index b8ea5fdf..43b08e3c 100644 --- a/src/components/Nodes/wrapNode.tsx +++ b/src/components/Nodes/wrapNode.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useRef, memo, ComponentType, CSSProperties, useMemo, MouseEvent, useCallback } from 'react'; -import { DraggableCore } from 'react-draggable'; +import { DraggableCore, DraggableData, DraggableEvent } from 'react-draggable'; import cc from 'classcat'; import { useStoreActions } from '../../store/hooks'; @@ -21,6 +21,7 @@ export default (NodeComponent: ComponentType) => { onMouseLeave, onContextMenu, onNodeDragStart, + onNodeDrag, onNodeDragStop, style, className, @@ -107,7 +108,7 @@ export default (NodeComponent: ComponentType) => { ); const onDragStart = useCallback( - (event) => { + (event: DraggableEvent) => { onNodeDragStart?.(event as MouseEvent, node); if (selectNodesOnDrag && isSelectable) { @@ -125,12 +126,14 @@ export default (NodeComponent: ComponentType) => { ); const onDrag = useCallback( - (_, data) => { + (event: DraggableEvent, draggbleData: DraggableData) => { + onNodeDrag?.(event as MouseEvent, id, draggbleData); + updateNodePosDiff({ id, diff: { - x: data.deltaX, - y: data.deltaY, + x: draggbleData.deltaX, + y: draggbleData.deltaY, }, }); }, @@ -138,7 +141,7 @@ export default (NodeComponent: ComponentType) => { ); const onDragStop = useCallback( - (event) => { + (event: DraggableEvent) => { // onDragStop also gets called when user just clicks on a node. // Because of that we set dragging to true inside the onDrag handler and handle the click here if (!isDragging) { diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index 363b50b9..780f8fcc 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -40,6 +40,7 @@ const GraphView = ({ onNodeMouseLeave, onNodeContextMenu, onNodeDragStart, + onNodeDrag, onNodeDragStop, onSelectionDragStart, onSelectionDrag, @@ -243,6 +244,7 @@ const GraphView = ({ onNodeMouseLeave={onNodeMouseLeave} onNodeContextMenu={onNodeContextMenu} onNodeDragStop={onNodeDragStop} + onNodeDrag={onNodeDrag} onNodeDragStart={onNodeDragStart} selectNodesOnDrag={selectNodesOnDrag} snapToGrid={snapToGrid} diff --git a/src/container/NodeRenderer/index.tsx b/src/container/NodeRenderer/index.tsx index ad31abeb..1834ae24 100644 --- a/src/container/NodeRenderer/index.tsx +++ b/src/container/NodeRenderer/index.tsx @@ -1,9 +1,9 @@ import React, { memo, useMemo, ComponentType, MouseEvent } from 'react'; +import { DraggableData } from 'react-draggable'; import { getNodesInside } from '../../utils/graph'; import { useStoreState, useStoreActions } from '../../store/hooks'; -import { Node, NodeTypesType, WrapNodeProps, Edge } from '../../types'; - +import { Node, NodeTypesType, WrapNodeProps, Edge, ElementId } from '../../types'; interface NodeRendererProps { nodeTypes: NodeTypesType; selectNodesOnDrag: boolean; @@ -13,6 +13,7 @@ interface NodeRendererProps { onNodeMouseLeave?: (event: MouseEvent, node: Node) => void; onNodeContextMenu?: (event: MouseEvent, node: Node) => void; onNodeDragStart?: (event: MouseEvent, node: Node) => void; + onNodeDrag?: (event: MouseEvent, nodeId: ElementId, data: DraggableData) => void; onNodeDragStop?: (event: MouseEvent, node: Node) => void; snapToGrid: boolean; snapGrid: [number, number]; @@ -91,6 +92,7 @@ const NodeRenderer = (props: NodeRendererProps) => { onMouseLeave={props.onNodeMouseLeave} onContextMenu={props.onNodeContextMenu} onNodeDragStart={props.onNodeDragStart} + onNodeDrag={props.onNodeDrag} onNodeDragStop={props.onNodeDragStop} scale={transform[2]} selected={selectedElements?.some(({ id }) => id === node.id) || false} diff --git a/src/container/ReactFlow/index.tsx b/src/container/ReactFlow/index.tsx index 6c974de4..354d57a2 100644 --- a/src/container/ReactFlow/index.tsx +++ b/src/container/ReactFlow/index.tsx @@ -1,5 +1,6 @@ import React, { useMemo, CSSProperties, HTMLAttributes, MouseEvent, WheelEvent } from 'react'; import cc from 'classcat'; +import { DraggableData } from 'react-draggable'; import GraphView from '../GraphView'; import ElementUpdater from '../../components/ElementUpdater'; @@ -31,6 +32,7 @@ import { PanOnScrollMode, OnEdgeUpdateFunc, NodeExtent, + ElementId, } from '../../types'; import '../../style.css'; @@ -58,6 +60,7 @@ export interface ReactFlowProps extends Omit, 'on onNodeMouseLeave?: (event: MouseEvent, node: Node) => void; onNodeContextMenu?: (event: MouseEvent, node: Node) => void; onNodeDragStart?: (event: MouseEvent, node: Node) => void; + onNodeDrag?: (event: MouseEvent, nodeId: ElementId, data: DraggableData) => void; onNodeDragStop?: (event: MouseEvent, node: Node) => void; onConnect?: (connection: Edge | Connection) => void; onConnectStart?: OnConnectStartFunc; @@ -130,6 +133,7 @@ const ReactFlow = ({ onNodeMouseLeave, onNodeContextMenu, onNodeDragStart, + onNodeDrag, onNodeDragStop, onSelectionChange, onSelectionDragStart, @@ -191,6 +195,7 @@ const ReactFlow = ({ onNodeMouseLeave={onNodeMouseLeave} onNodeContextMenu={onNodeContextMenu} onNodeDragStart={onNodeDragStart} + onNodeDrag={onNodeDrag} onNodeDragStop={onNodeDragStop} nodeTypes={nodeTypesParsed} edgeTypes={edgeTypesParsed} diff --git a/src/types/index.ts b/src/types/index.ts index 888a5b00..44dd7d00 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,4 +1,5 @@ import { CSSProperties, MouseEvent as ReactMouseEvent } from 'react'; +import { DraggableData } from 'react-draggable'; export type ElementId = string; @@ -196,6 +197,7 @@ export interface NodeComponentProps { onMouseLeave?: (node: Node) => void; onContextMenu?: (node: Node) => void; onNodeDragStart?: (node: Node) => void; + onNodeDrag?: (node: Node) => void; onNodeDragStop?: (node: Node) => void; style?: CSSProperties; isDragging?: boolean; @@ -219,6 +221,7 @@ export interface WrapNodeProps { onMouseLeave?: (event: ReactMouseEvent, node: Node) => void; onContextMenu?: (event: ReactMouseEvent, node: Node) => void; onNodeDragStart?: (event: ReactMouseEvent, node: Node) => void; + onNodeDrag?: (event: ReactMouseEvent, nodeId: ElementId, data: DraggableData) => void; onNodeDragStop?: (event: ReactMouseEvent, node: Node) => void; style?: CSSProperties; className?: string; From 477be8d492fe0f148a8501e1e7345964bce3a7cb Mon Sep 17 00:00:00 2001 From: moklick Date: Wed, 27 Jan 2021 10:35:06 +0100 Subject: [PATCH 2/2] refactor(onDrag): use same api as onNodeDragStart --- example/src/Overview/index.js | 2 ++ src/components/Nodes/wrapNode.tsx | 14 +++++++++----- src/container/NodeRenderer/index.tsx | 5 ++--- src/container/ReactFlow/index.tsx | 4 +--- src/types/index.ts | 3 +-- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/example/src/Overview/index.js b/example/src/Overview/index.js index a36ccc9c..619e477c 100644 --- a/example/src/Overview/index.js +++ b/example/src/Overview/index.js @@ -3,6 +3,7 @@ import React, { useState } from 'react'; import ReactFlow, { removeElements, addEdge, MiniMap, Controls, Background, isNode } from 'react-flow-renderer'; const onNodeDragStart = (event, node) => console.log('drag start', node); +const onNodeDrag = (event, node) => console.log('drag', node); const onNodeDragStop = (event, node) => console.log('drag stop', node); const onPaneClick = (event) => console.log('pane click', event); const onPaneScroll = (event) => console.log('pane scroll', event); @@ -132,6 +133,7 @@ const OverviewFlow = () => { onPaneScroll={onPaneScroll} onPaneContextMenu={onPaneContextMenu} onNodeDragStart={onNodeDragStart} + onNodeDrag={onNodeDrag} onNodeDragStop={onNodeDragStop} onSelectionDragStart={onSelectionDragStart} onSelectionDrag={onSelectionDrag} diff --git a/src/components/Nodes/wrapNode.tsx b/src/components/Nodes/wrapNode.tsx index 43b08e3c..ca978006 100644 --- a/src/components/Nodes/wrapNode.tsx +++ b/src/components/Nodes/wrapNode.tsx @@ -126,18 +126,22 @@ export default (NodeComponent: ComponentType) => { ); const onDrag = useCallback( - (event: DraggableEvent, draggbleData: DraggableData) => { - onNodeDrag?.(event as MouseEvent, id, draggbleData); + (event: DraggableEvent, draggableData: DraggableData) => { + if (onNodeDrag) { + node.position.x += draggableData.deltaX; + node.position.y += draggableData.deltaY; + onNodeDrag(event as MouseEvent, node); + } updateNodePosDiff({ id, diff: { - x: draggbleData.deltaX, - y: draggbleData.deltaY, + x: draggableData.deltaX, + y: draggableData.deltaY, }, }); }, - [id] + [id, node, onNodeDrag] ); const onDragStop = useCallback( diff --git a/src/container/NodeRenderer/index.tsx b/src/container/NodeRenderer/index.tsx index 1834ae24..06577d08 100644 --- a/src/container/NodeRenderer/index.tsx +++ b/src/container/NodeRenderer/index.tsx @@ -1,9 +1,8 @@ import React, { memo, useMemo, ComponentType, MouseEvent } from 'react'; -import { DraggableData } from 'react-draggable'; import { getNodesInside } from '../../utils/graph'; import { useStoreState, useStoreActions } from '../../store/hooks'; -import { Node, NodeTypesType, WrapNodeProps, Edge, ElementId } from '../../types'; +import { Node, NodeTypesType, WrapNodeProps, Edge } from '../../types'; interface NodeRendererProps { nodeTypes: NodeTypesType; selectNodesOnDrag: boolean; @@ -13,7 +12,7 @@ interface NodeRendererProps { onNodeMouseLeave?: (event: MouseEvent, node: Node) => void; onNodeContextMenu?: (event: MouseEvent, node: Node) => void; onNodeDragStart?: (event: MouseEvent, node: Node) => void; - onNodeDrag?: (event: MouseEvent, nodeId: ElementId, data: DraggableData) => void; + onNodeDrag?: (event: MouseEvent, node: Node) => void; onNodeDragStop?: (event: MouseEvent, node: Node) => void; snapToGrid: boolean; snapGrid: [number, number]; diff --git a/src/container/ReactFlow/index.tsx b/src/container/ReactFlow/index.tsx index 354d57a2..77af0d96 100644 --- a/src/container/ReactFlow/index.tsx +++ b/src/container/ReactFlow/index.tsx @@ -1,6 +1,5 @@ import React, { useMemo, CSSProperties, HTMLAttributes, MouseEvent, WheelEvent } from 'react'; import cc from 'classcat'; -import { DraggableData } from 'react-draggable'; import GraphView from '../GraphView'; import ElementUpdater from '../../components/ElementUpdater'; @@ -32,7 +31,6 @@ import { PanOnScrollMode, OnEdgeUpdateFunc, NodeExtent, - ElementId, } from '../../types'; import '../../style.css'; @@ -60,7 +58,7 @@ export interface ReactFlowProps extends Omit, 'on onNodeMouseLeave?: (event: MouseEvent, node: Node) => void; onNodeContextMenu?: (event: MouseEvent, node: Node) => void; onNodeDragStart?: (event: MouseEvent, node: Node) => void; - onNodeDrag?: (event: MouseEvent, nodeId: ElementId, data: DraggableData) => void; + onNodeDrag?: (event: MouseEvent, node: Node) => void; onNodeDragStop?: (event: MouseEvent, node: Node) => void; onConnect?: (connection: Edge | Connection) => void; onConnectStart?: OnConnectStartFunc; diff --git a/src/types/index.ts b/src/types/index.ts index 44dd7d00..b41e82a9 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,5 +1,4 @@ import { CSSProperties, MouseEvent as ReactMouseEvent } from 'react'; -import { DraggableData } from 'react-draggable'; export type ElementId = string; @@ -221,7 +220,7 @@ export interface WrapNodeProps { onMouseLeave?: (event: ReactMouseEvent, node: Node) => void; onContextMenu?: (event: ReactMouseEvent, node: Node) => void; onNodeDragStart?: (event: ReactMouseEvent, node: Node) => void; - onNodeDrag?: (event: ReactMouseEvent, nodeId: ElementId, data: DraggableData) => void; + onNodeDrag?: (event: ReactMouseEvent, node: Node) => void; onNodeDragStop?: (event: ReactMouseEvent, node: Node) => void; style?: CSSProperties; className?: string;