refactor(contexts): create connection context
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
import React, { createContext, useState, memo } from 'react';
|
||||
|
||||
export const ConnectionContext = createContext({});
|
||||
|
||||
export const Provider = memo(({ onConnect, children }) => {
|
||||
const [sourceId, setSourceId] = useState(null);
|
||||
const [position, setPosition] = useState({ x:0, y: 0 });
|
||||
|
||||
const connectionContext = {
|
||||
sourceId,
|
||||
setSourceId,
|
||||
position,
|
||||
setPosition,
|
||||
onConnect
|
||||
};
|
||||
|
||||
return (
|
||||
<ConnectionContext.Provider value={connectionContext}>
|
||||
{children}
|
||||
</ConnectionContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
Provider.displayName = 'ConnectionProvider';
|
||||
Provider.whyDidYouRender = false;
|
||||
|
||||
export const { Consumer } = ConnectionContext;
|
||||
@@ -7,7 +7,6 @@ export default (props) => {
|
||||
setSourceNode(props.nodes.find(n => n.id === props.connectionSourceId));
|
||||
}, []);
|
||||
|
||||
|
||||
if (!sourceNode) {
|
||||
return null;
|
||||
}
|
||||
@@ -21,8 +20,8 @@ export default (props) => {
|
||||
const sourceX = sourceNode.__rg.position.x + sourceHandleX;
|
||||
const sourceY = sourceNode.__rg.position.y + sourceHandleY;
|
||||
|
||||
const targetX = (props.connectionPosition.x * (1 / props.transform[2])) - (props.transform[0] * (1 / props.transform[2]));
|
||||
const targetY = (props.connectionPosition.y * (1 / props.transform[2])) - (props.transform[1] * (1 / props.transform[2]));
|
||||
const targetX = (props.connectionPositionX * (1 / props.transform[2])) - (props.transform[0] * (1 / props.transform[2]));
|
||||
const targetY = (props.connectionPositionY * (1 / props.transform[2])) - (props.transform[1] * (1 / props.transform[2]));
|
||||
|
||||
let dAttr = '';
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { memo, useContext } from 'react';
|
||||
|
||||
import { GraphContext } from '../GraphContext';
|
||||
import { ConnectionContext } from '../ConnectionContext';
|
||||
import ConnectionLine from '../ConnectionLine';
|
||||
|
||||
|
||||
function getEdgePositions(sourceNode, targetNode) {
|
||||
const hasSourceHandle = !!sourceNode.__rg.handleBounds.source;
|
||||
const hasTargetHandle = !!targetNode.__rg.handleBounds.target;
|
||||
@@ -73,6 +73,7 @@ function renderEdge(e, props, graphContext) {
|
||||
|
||||
const EdgeRenderer = memo((props) => {
|
||||
const graphContext = useContext(GraphContext);
|
||||
const { position, sourceId : connectionSourceId } = useContext(ConnectionContext);
|
||||
const {
|
||||
width, height, connectionLineStyle, connectionLineType
|
||||
} = props;
|
||||
@@ -81,7 +82,7 @@ const EdgeRenderer = memo((props) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { transform, edges, nodes, connectionSourceId, connectionPosition } = graphContext.state;
|
||||
const { transform, edges, nodes } = graphContext.state;
|
||||
const transformStyle = `translate(${transform[0]},${transform[1]}) scale(${transform[2]})`;
|
||||
|
||||
return (
|
||||
@@ -96,7 +97,8 @@ const EdgeRenderer = memo((props) => {
|
||||
<ConnectionLine
|
||||
nodes={nodes}
|
||||
connectionSourceId={connectionSourceId}
|
||||
connectionPosition={connectionPosition}
|
||||
connectionPositionX={position.x}
|
||||
connectionPositionY={position.y}
|
||||
transform={transform}
|
||||
connectionLineStyle={connectionLineStyle}
|
||||
connectionLineType={connectionLineType}
|
||||
|
||||
+17
-14
@@ -3,6 +3,7 @@ import * as d3Zoom from 'd3-zoom';
|
||||
import { select, event } from 'd3-selection';
|
||||
import ReactSizeMe from 'react-sizeme';
|
||||
|
||||
import { Provider } from '../ConnectionContext';
|
||||
import { GraphContext } from '../GraphContext';
|
||||
import NodeRenderer from '../NodeRenderer';
|
||||
import EdgeRenderer from '../EdgeRenderer';
|
||||
@@ -10,7 +11,7 @@ import UserSelection from '../UserSelection';
|
||||
import NodesSelection from '../NodesSelection';
|
||||
import {
|
||||
updateTransform, updateSize, initD3, fitView,
|
||||
zoomIn, zoomOut, setNodesSelection, setConnectionPos
|
||||
zoomIn, zoomOut, setNodesSelection
|
||||
} from '../state/actions';
|
||||
import { useKeyPress } from '../hooks';
|
||||
|
||||
@@ -79,19 +80,21 @@ const GraphView = memo((props) => {
|
||||
|
||||
return (
|
||||
<div className="react-graph__renderer">
|
||||
<NodeRenderer
|
||||
nodeTypes={props.nodeTypes}
|
||||
onElementClick={props.onElementClick}
|
||||
onNodeDragStop={props.onNodeDragStop}
|
||||
/>
|
||||
<EdgeRenderer
|
||||
width={state.width}
|
||||
height={state.height}
|
||||
edgeTypes={props.edgeTypes}
|
||||
onElementClick={props.onElementClick}
|
||||
connectionLineType={props.connectionLineType}
|
||||
connectionLineStyle={props.connectionLineStyle}
|
||||
/>
|
||||
<Provider onConnect={props.onConnect}>
|
||||
<NodeRenderer
|
||||
nodeTypes={props.nodeTypes}
|
||||
onElementClick={props.onElementClick}
|
||||
onNodeDragStop={props.onNodeDragStop}
|
||||
/>
|
||||
<EdgeRenderer
|
||||
width={state.width}
|
||||
height={state.height}
|
||||
edgeTypes={props.edgeTypes}
|
||||
onElementClick={props.onElementClick}
|
||||
connectionLineType={props.connectionLineType}
|
||||
connectionLineStyle={props.connectionLineStyle}
|
||||
/>
|
||||
</Provider>
|
||||
{shiftPressed && <UserSelection />}
|
||||
{state.nodesSelectionActive && <NodesSelection />}
|
||||
<div
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
import React, { memo } from 'react';
|
||||
import cx from 'classnames';
|
||||
|
||||
import { setConnecting, setConnectionPos } from '../../state/actions';
|
||||
|
||||
function onMouseDown(evt, { nodeId, dispatch, onConnect, isTarget }) {
|
||||
function onMouseDown(evt, { nodeId, setSourceId, setPosition, onConnect, isTarget }) {
|
||||
const containerBounds = document.querySelector('.react-graph').getBoundingClientRect();
|
||||
const connectionPosition = { x: evt.clientX - containerBounds.x, y: evt.clientY - containerBounds.y };
|
||||
dispatch(setConnecting({ connectionPosition, connectionSourceId: nodeId }))
|
||||
|
||||
setPosition({
|
||||
x: evt.clientX - containerBounds.x,
|
||||
y: evt.clientY - containerBounds.y,
|
||||
});
|
||||
setSourceId(nodeId);
|
||||
|
||||
function onMouseMove(evt) {
|
||||
dispatch(setConnectionPos({ x: evt.clientX - containerBounds.x, y: evt.clientY - containerBounds.y }));
|
||||
setPosition({
|
||||
x: evt.clientX - containerBounds.x,
|
||||
y: evt.clientY - containerBounds.y,
|
||||
});
|
||||
}
|
||||
|
||||
function onMouseUp(evt) {
|
||||
@@ -25,7 +30,7 @@ function onMouseDown(evt, { nodeId, dispatch, onConnect, isTarget }) {
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(setConnecting({ connectionSourceId: false }));
|
||||
setSourceId(null);
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
document.removeEventListener('mouseup', onMouseUp);
|
||||
}
|
||||
@@ -34,7 +39,7 @@ function onMouseDown(evt, { nodeId, dispatch, onConnect, isTarget }) {
|
||||
document.addEventListener('mouseup', onMouseUp)
|
||||
}
|
||||
|
||||
const BaseHandle = memo(({ source, target, nodeId, onConnect, dispatch, className = null, ...rest }) => {
|
||||
const BaseHandle = memo(({ source, target, nodeId, onConnect, setSourceId, setPosition, className = null, ...rest }) => {
|
||||
const handleClasses = cx(
|
||||
'react-graph__handle',
|
||||
className,
|
||||
@@ -45,7 +50,7 @@ const BaseHandle = memo(({ source, target, nodeId, onConnect, dispatch, classNam
|
||||
<div
|
||||
data-nodeid={nodeId}
|
||||
className={handleClasses}
|
||||
onMouseDown={evt => onMouseDown(evt, { nodeId, dispatch, onConnect, isTarget: target })}
|
||||
onMouseDown={evt => onMouseDown(evt, { nodeId, setSourceId, setPosition, onConnect, isTarget: target })}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -2,17 +2,18 @@ import React, { memo, useContext } from 'react';
|
||||
|
||||
import BaseHandle from './BaseHandle';
|
||||
import NodeIdContext from '../NodeIdContext'
|
||||
import { GraphContext } from '../../GraphContext';
|
||||
import { ConnectionContext } from '../../ConnectionContext';
|
||||
|
||||
export default memo((props) => {
|
||||
const nodeId = useContext(NodeIdContext);
|
||||
const { dispatch, onConnect } = useContext(GraphContext);
|
||||
const { setPosition, setSourceId, onConnect } = useContext(ConnectionContext);
|
||||
|
||||
return (
|
||||
<BaseHandle
|
||||
source
|
||||
nodeId={nodeId}
|
||||
dispatch={dispatch}
|
||||
setPosition={setPosition}
|
||||
setSourceId={setSourceId}
|
||||
onConnect={onConnect}
|
||||
{...props}
|
||||
/>
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import React, { memo, useContext } from 'react';
|
||||
|
||||
import BaseHandle from './BaseHandle';
|
||||
import { GraphContext } from '../../GraphContext';
|
||||
import { ConnectionContext } from '../../ConnectionContext';
|
||||
import NodeIdContext from '../NodeIdContext'
|
||||
|
||||
const TargetHandle = memo((props) => {
|
||||
const nodeId = useContext(NodeIdContext);
|
||||
const { dispatch, onConnect } = useContext(GraphContext);
|
||||
const { setPosition, setSourceId, onConnect } = useContext(ConnectionContext);
|
||||
|
||||
return (
|
||||
<BaseHandle
|
||||
target
|
||||
nodeId={nodeId}
|
||||
dispatch={dispatch}
|
||||
setPosition={setPosition}
|
||||
setSourceId={setSourceId}
|
||||
onConnect={onConnect}
|
||||
{...props}
|
||||
/>
|
||||
@@ -23,4 +24,3 @@ TargetHandle.displayName = 'TargetHandle';
|
||||
TargetHandle.whyDidYouRender = false;
|
||||
|
||||
export default TargetHandle;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class ReactGraph extends PureComponent {
|
||||
|
||||
return (
|
||||
<div style={style} className="react-graph">
|
||||
<Provider elements={elements} onConnect={onConnect}>
|
||||
<Provider elements={elements}>
|
||||
<GraphView
|
||||
onLoad={onLoad}
|
||||
onMove={onMove}
|
||||
@@ -48,6 +48,7 @@ class ReactGraph extends PureComponent {
|
||||
edgeTypes={this.edgeTypes}
|
||||
connectionLineType={connectionLineType}
|
||||
connectionLineStyle={connectionLineStyle}
|
||||
onConnect={onConnect}
|
||||
/>
|
||||
<GlobalKeyHandler
|
||||
onElementsRemove={onElementsRemove}
|
||||
|
||||
+2
-14
@@ -2,8 +2,7 @@ import {
|
||||
UPDATE_TRANSFORM, UPDATE_SIZE, SET_NODES, SET_EDGES,
|
||||
UPDATE_NODE_DATA, UPDATE_NODE_POS, INIT_D3, FIT_VIEW,
|
||||
UPDATE_SELECTION, SET_SELECTION, SET_NODES_SELECTION,
|
||||
SET_SELECTED_ELEMENTS, REMOVE_NODES, ZOOM_IN, ZOOM_OUT,
|
||||
SET_CONNECTING, SET_CONNECTION_POS
|
||||
SET_SELECTED_ELEMENTS, REMOVE_NODES, ZOOM_IN, ZOOM_OUT
|
||||
} from './index';
|
||||
|
||||
export const updateTransform = (transform) => {
|
||||
@@ -99,15 +98,4 @@ export const updateSelection = (selection) => {
|
||||
selection
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const setConnecting = ({ connectionSourceId, connectionPosition = false}) => {
|
||||
return { type: SET_CONNECTING, payload: { connectionSourceId, connectionPosition }};
|
||||
};
|
||||
|
||||
export const setConnectionPos = ({ x, y }) => {
|
||||
return {
|
||||
type: SET_CONNECTION_POS,
|
||||
payload: { connectionPosition: { x, y } }
|
||||
};
|
||||
};
|
||||
};
|
||||
+1
-14
@@ -18,8 +18,6 @@ export const SET_SELECTION = 'SET_SELECTION';
|
||||
export const SET_NODES_SELECTION = 'SET_NODES_SELECTION';
|
||||
export const SET_SELECTED_ELEMENTS = 'SET_SELECTED_ELEMENTS';
|
||||
export const REMOVE_NODES = 'REMOVE_NODES';
|
||||
export const SET_CONNECTING = 'SET_CONNECTING';
|
||||
export const SET_CONNECTION_POS = 'SET_CONNECTION_POS';
|
||||
|
||||
export const initialState = {
|
||||
width: 0,
|
||||
@@ -36,10 +34,7 @@ export const initialState = {
|
||||
|
||||
nodesSelectionActive: false,
|
||||
selectionActive: false,
|
||||
selection: {},
|
||||
|
||||
connectionSourceId: null,
|
||||
connectionPosition: { x: 0, y: 0 }
|
||||
selection: {}
|
||||
};
|
||||
|
||||
export const reducer = (state, action) => {
|
||||
@@ -134,20 +129,12 @@ export const reducer = (state, action) => {
|
||||
|
||||
return { ...state, nodes: nextNodes, edges: nextEdges };
|
||||
}
|
||||
case SET_CONNECTING: {
|
||||
if (!action.payload.connectionPosition) {
|
||||
return { ...state, connectionSourceId: action.payload.connectionSourceId };
|
||||
}
|
||||
|
||||
return { ...state, ...action.payload };
|
||||
}
|
||||
case SET_NODES:
|
||||
case SET_EDGES:
|
||||
case UPDATE_TRANSFORM:
|
||||
case INIT_D3:
|
||||
case UPDATE_SIZE:
|
||||
case SET_SELECTION:
|
||||
case SET_CONNECTION_POS:
|
||||
return { ...state, ...action.payload };
|
||||
default:
|
||||
return state;
|
||||
|
||||
Reference in New Issue
Block a user