feat(connection): add start and stop props closes #380

This commit is contained in:
moklick
2020-08-01 12:54:14 +02:00
parent 01271a1994
commit 5f91498d19
8 changed files with 105 additions and 11 deletions

View File

@@ -88,6 +88,8 @@ const BasicFlow = () => <ReactFlow elements={elements} />;
- `onNodeMouseLeave(evt: MouseEvent, node: Node)`: node mouse leave
- `onNodeContextMenu(evt: MouseEvent, node: Node)`: node context menu
- `onConnect({ source, target })`: called when user connects two nodes
- `onConnectStart({ nodeId, handleType })`: called when user starts to drag connection line
- `onConnectStop()`: called when user stops to drag connection line
- `onLoad(reactFlowInstance)`: called after flow is initialized
- `onMove()`: called when user is panning or zooming
- `onMoveStart()`: called when user starts panning or zooming

View File

@@ -15,6 +15,10 @@ const isValidConnection = (connection) => connection.target === 'B';
const onLoad = (reactFlowInstance) => reactFlowInstance.fitView();
const onConnectStart = ({ nodeId, handleType }) => console.log('on connect start', { nodeId, handleType });
const onConnectStop = () => console.log('on connect stop');
const CustomInput = () => (
<>
<div>Only connectable with B</div>
@@ -47,6 +51,8 @@ const HorizontalFlow = () => {
onLoad={onLoad}
className="validationflow"
nodeTypes={nodeTypes}
onConnectStart={onConnectStart}
onConnectStop={onConnectStop}
/>
);
};

View File

@@ -1,7 +1,17 @@
import React, { memo, MouseEvent as ReactMouseEvent, CSSProperties } from 'react';
import cc from 'classcat';
import { HandleType, ElementId, Position, XYPosition, OnConnectFunc, Connection, SetConnectionId } from '../../types';
import {
HandleType,
ElementId,
Position,
XYPosition,
OnConnectFunc,
OnConnectStartFunc,
OnConnectStopFunc,
Connection,
SetConnectionId,
} from '../../types';
type ValidConnectionFunc = (connection: Connection) => boolean;
type SetSourceIdFunc = (params: SetConnectionId) => void;
@@ -10,6 +20,8 @@ interface BaseHandleProps {
type: HandleType;
nodeId: ElementId;
onConnect: OnConnectFunc;
onConnectStart?: OnConnectStartFunc;
onConnectStop?: OnConnectStopFunc;
position: Position;
setConnectionNodeId: SetSourceIdFunc;
setPosition: (pos: XYPosition) => void;
@@ -33,7 +45,9 @@ function onMouseDown(
setPosition: (pos: XYPosition) => void,
onConnect: OnConnectFunc,
isTarget: boolean,
isValidConnection: ValidConnectionFunc
isValidConnection: ValidConnectionFunc,
onConnectStart?: OnConnectStartFunc,
onConnectStop?: OnConnectStopFunc
): void {
const reactFlowNode = document.querySelector('.react-flow');
@@ -41,6 +55,7 @@ function onMouseDown(
return;
}
const handleType = isTarget ? 'target' : 'source';
const containerBounds = reactFlowNode.getBoundingClientRect();
let recentHoveredHandle: Element;
@@ -48,7 +63,11 @@ function onMouseDown(
x: evt.clientX - containerBounds.left,
y: evt.clientY - containerBounds.top,
});
setConnectionNodeId({ connectionNodeId: nodeId, connectionHandleType: isTarget ? 'target' : 'source' });
setConnectionNodeId({ connectionNodeId: nodeId, connectionHandleType: handleType });
if (onConnectStart) {
onConnectStart({ nodeId, handleType });
}
function resetRecentHandle(): void {
if (!recentHoveredHandle) {
@@ -115,13 +134,17 @@ function onMouseDown(
function onMouseUp(evt: MouseEvent) {
const { connection, isValid } = checkElementBelowIsValid(evt);
if (isValid) {
if (isValid && onConnect) {
onConnect(connection);
}
resetRecentHandle();
setConnectionNodeId({ connectionNodeId: null, connectionHandleType: null });
if (onConnectStop) {
onConnectStop();
}
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}
@@ -134,6 +157,8 @@ const BaseHandle = ({
type,
nodeId,
onConnect,
onConnectStart,
onConnectStop,
position,
setConnectionNodeId,
setPosition,
@@ -162,7 +187,17 @@ const BaseHandle = ({
data-handlepos={position}
className={handleClasses}
onMouseDown={(evt) =>
onMouseDown(evt, nodeIdWithHandleId, setConnectionNodeId, setPosition, onConnect, isTarget, isValidConnection)
onMouseDown(
evt,
nodeIdWithHandleId,
setConnectionNodeId,
setPosition,
onConnect,
isTarget,
isValidConnection,
onConnectStart,
onConnectStop
)
}
{...rest}
/>

View File

@@ -10,20 +10,27 @@ import { HandleProps, ElementId, Position, Connection } from '../../types';
const Handle = ({
type = 'source',
position = Position.Top,
onConnect = () => {},
isValidConnection = () => true,
isConnectable = true,
style,
className,
id,
onConnect,
}: HandleProps) => {
const nodeId = useContext(NodeIdContext) as ElementId;
const setPosition = useStoreActions((a) => a.setConnectionPosition);
const setConnectionNodeId = useStoreActions((a) => a.setConnectionNodeId);
const onConnectAction = useStoreState((s) => s.onConnect);
const onConnectStart = useStoreState((s) => s.onConnectStart);
const onConnectStop = useStoreState((s) => s.onConnectStop);
const onConnectExtended = (params: Connection) => {
onConnectAction(params);
onConnect(params);
if (onConnectAction) {
onConnectAction(params);
}
if (onConnect) {
onConnect(params);
}
};
const handleClasses = cc([className, { connectable: isConnectable }]);
@@ -35,6 +42,8 @@ const Handle = ({
setPosition={setPosition}
setConnectionNodeId={setConnectionNodeId}
onConnect={onConnectExtended}
onConnectStart={onConnectStart}
onConnectStop={onConnectStop}
type={type}
position={position}
isValidConnection={isValidConnection}

View File

@@ -22,6 +22,7 @@ import {
Connection,
ConnectionLineType,
FlowTransform,
OnConnectStartFunc,
} from '../../types';
export interface GraphViewProps {
@@ -35,6 +36,8 @@ export interface GraphViewProps {
onNodeDragStart?: (node: Node) => void;
onNodeDragStop?: (node: Node) => void;
onConnect?: (connection: Connection | Edge) => void;
onConnectStart?: OnConnectStartFunc;
onConnectStop?: () => void;
onLoad?: OnLoadFunc;
onMove?: (flowTransform?: FlowTransform) => void;
onMoveStart?: (flowTransform?: FlowTransform) => void;
@@ -85,6 +88,8 @@ const GraphView = ({
deleteKeyCode,
elements,
onConnect,
onConnectStart,
onConnectStop,
snapToGrid,
snapGrid,
onlyRenderVisibleNodes,
@@ -112,6 +117,8 @@ const GraphView = ({
const updateSize = useStoreActions((actions) => actions.updateSize);
const setNodesSelection = useStoreActions((actions) => actions.setNodesSelection);
const setOnConnect = useStoreActions((a) => a.setOnConnect);
const setOnConnectStart = useStoreActions((a) => a.setOnConnectStart);
const setOnConnectStop = useStoreActions((a) => a.setOnConnectStop);
const setSnapGrid = useStoreActions((actions) => actions.setSnapGrid);
const setNodesDraggable = useStoreActions((actions) => actions.setNodesDraggable);
const setNodesConnectable = useStoreActions((actions) => actions.setNodesConnectable);
@@ -210,6 +217,18 @@ const GraphView = ({
}
}, [onConnect]);
useEffect(() => {
if (onConnectStart) {
setOnConnectStart(onConnectStart);
}
}, [onConnectStart]);
useEffect(() => {
if (onConnectStop) {
setOnConnectStop(onConnectStop);
}
}, [onConnectStop]);
useEffect(() => {
setSnapGrid({ snapToGrid, snapGrid });
}, [snapToGrid]);

View File

@@ -27,6 +27,7 @@ import {
Connection,
ConnectionLineType,
FlowTransform,
OnConnectStartFunc,
} from '../../types';
import '../../style.css';
@@ -42,6 +43,8 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
onNodeDragStart?: (node: Node) => void;
onNodeDragStop?: (node: Node) => void;
onConnect?: (connection: Edge | Connection) => void;
onConnectStart?: OnConnectStartFunc;
onConnectStop?: () => void;
onLoad?: OnLoadFunc;
onMove?: (flowTransform?: FlowTransform) => void;
onMoveStart?: (flowTransform?: FlowTransform) => void;
@@ -86,6 +89,8 @@ const ReactFlow = ({
onMoveEnd,
onElementsRemove,
onConnect,
onConnectStart,
onConnectStop,
onNodeMouseEnter,
onNodeMouseMove,
onNodeMouseLeave,
@@ -143,6 +148,8 @@ const ReactFlow = ({
deleteKeyCode={deleteKeyCode}
elements={elements}
onConnect={onConnect}
onConnectStart={onConnectStart}
onConnectStop={onConnectStop}
snapToGrid={snapToGrid}
snapGrid={snapGrid}
onlyRenderVisibleNodes={onlyRenderVisibleNodes}

View File

@@ -18,6 +18,8 @@ import {
Dimensions,
XYPosition,
OnConnectFunc,
OnConnectStartFunc,
OnConnectStopFunc,
SelectionRect,
HandleType,
SetConnectionId,
@@ -87,9 +89,13 @@ export interface StoreModel {
reactFlowVersion: string;
onConnect: OnConnectFunc;
onConnect?: OnConnectFunc;
onConnectStart?: OnConnectStartFunc;
onConnectStop?: OnConnectStopFunc;
setOnConnect: Action<StoreModel, OnConnectFunc>;
setOnConnectStart: Action<StoreModel, OnConnectStartFunc>;
setOnConnectStop: Action<StoreModel, OnConnectStopFunc>;
setElements: Action<StoreModel, Elements>;
@@ -177,11 +183,15 @@ export const storeModel: StoreModel = {
reactFlowVersion: typeof __REACT_FLOW_VERSION__ !== 'undefined' ? __REACT_FLOW_VERSION__ : '-',
onConnect: () => {},
setOnConnect: action((state, onConnect) => {
state.onConnect = onConnect;
}),
setOnConnectStart: action((state, onConnectStart) => {
state.onConnectStart = onConnectStart;
}),
setOnConnectStop: action((state, onConnectStop) => {
state.onConnectStop = onConnectStop;
}),
setElements: action((state, elements) => {
state.elements = elements;

View File

@@ -198,6 +198,12 @@ export enum ConnectionLineType {
}
export type OnConnectFunc = (connection: Connection) => void;
export type OnConnectStartParams = {
nodeId: ElementId | null;
handleType: HandleType | null;
};
export type OnConnectStartFunc = (params: OnConnectStartParams) => void;
export type OnConnectStopFunc = () => void;
export type SetConnectionId = {
connectionNodeId: ElementId | null;