Merge pull request #3 from wbkd/feat/handle-types
feat(handle): add type and position
This commit is contained in:
+10
-8
@@ -1,21 +1,21 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
import Graph, { isEdge, removeElements, getOutgoers, SourceHandle, TargetHandle, MiniMap } from '../src';
|
import Graph, { isEdge, removeElements, getOutgoers, Handle, MiniMap } from '../src';
|
||||||
// import Graph, { isEdge, removeElements, getOutgoers, SourceHandle, TargetHandle } from '../dist/ReactGraph';
|
// import Graph, { isEdge, removeElements, getOutgoers, Handle } from '../dist/ReactGraph';
|
||||||
|
|
||||||
const SpecialNode = ({ data, styles }) => (
|
const SpecialNode = ({ data, styles }) => (
|
||||||
<div
|
<div
|
||||||
style={{ background: '#FFCC00', padding: 10, borderRadius: 2, ...styles }}
|
style={{ background: '#FFCC00', padding: 10, borderRadius: 2, ...styles }}
|
||||||
>
|
>
|
||||||
<TargetHandle id="a" style={{ left: 10, background: '#999' }} />
|
<Handle type="target" position="top" id="a" style={{ left: 10, background: '#999' }} />
|
||||||
<TargetHandle id="b" style={{ left: 30, background: '#999' }} />
|
<Handle type="target" position="top" id="b" style={{ left: 30, background: '#999' }} />
|
||||||
<div>I am <strong>special</strong>!<br />{data.label}</div>
|
<div>I am <strong>special</strong>!<br />{data.label}</div>
|
||||||
<select onChange={(e) => data.onChange(e.target.value, data)}>
|
<select onChange={(e) => data.onChange(e.target.value, data)}>
|
||||||
<option value="1">1</option>
|
<option value="1">1</option>
|
||||||
<option value="2">2</option>
|
<option value="2">2</option>
|
||||||
<option value="3">3</option>
|
<option value="3">3</option>
|
||||||
</select>
|
</select>
|
||||||
<SourceHandle style={{ left: 10, background: '#999' }} />
|
<Handle type="source" position="bottom" style={{ left: 10, background: '#999' }} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -23,10 +23,10 @@ const InputNode = ({ data, styles }) => (
|
|||||||
<div
|
<div
|
||||||
style={{ background: '#FFCC00', padding: 10, borderRadius: 2, ...styles }}
|
style={{ background: '#FFCC00', padding: 10, borderRadius: 2, ...styles }}
|
||||||
>
|
>
|
||||||
<TargetHandle style={{ left: 10, background: '#999' }} />
|
<Handle type="target" position="left" style={{ background: '#999' }} />
|
||||||
<div>{data.input}</div>
|
<div>{data.input}</div>
|
||||||
<input onChange={(e) => data.onChange(e.target.value, data)} />
|
<input onChange={(e) => data.onChange(e.target.value, data)} />
|
||||||
<SourceHandle style={{ left: 10, background: '#999' }} />
|
<Handle type="source" position="right" style={{ background: '#999' }} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -72,9 +72,11 @@ class App extends PureComponent {
|
|||||||
{ id: '5', type: 'default', data: { label: '5 Another node'}, position: { x: 400, y: 300 } },
|
{ id: '5', type: 'default', data: { label: '5 Another node'}, position: { x: 400, y: 300 } },
|
||||||
{ id: '6', type: 'special', data: { onChange, label: '6 no option selected' }, position: { x: 425, y: 375 } },
|
{ id: '6', type: 'special', data: { onChange, label: '6 no option selected' }, position: { x: 425, y: 375 } },
|
||||||
{ id: '7', type: 'output', data: { label: '7 output' }, position: { x: 250, y: 500 } },
|
{ id: '7', type: 'output', data: { label: '7 output' }, position: { x: 250, y: 500 } },
|
||||||
{ id: '8', type: 'text', data: { onChange: onChangeInput, input: 'write something' }, position: { x: 300, y: 100 } },
|
{ id: '8', type: 'text', data: { onChange: onChangeInput, input: 'write something' }, position: { x: 350, y: 100 } },
|
||||||
|
{ id: '9', type: 'text', data: { label: 'right' }, position: { x: 600, y: 100 } },
|
||||||
{ source: '1', target: '2', animated: true },
|
{ source: '1', target: '2', animated: true },
|
||||||
{ source: '1', target: '8', animated: true },
|
{ source: '1', target: '8', animated: true },
|
||||||
|
{ source: '8', target: '9', animated: true },
|
||||||
{ source: '2', target: '3' },
|
{ source: '2', target: '3' },
|
||||||
{ source: '3', target: '4', type: 'step' },
|
{ source: '3', target: '4', type: 'step' },
|
||||||
{ source: '3', target: '5' },
|
{ source: '3', target: '5' },
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
|
|
||||||
export default memo((props) => {
|
export default memo(({
|
||||||
const {
|
sourceX, sourceY, targetX, targetY,
|
||||||
sourceX, sourceY, targetX, targetY, style = {}
|
sourcePosition, targetPosition, style = {}
|
||||||
} = props;
|
}) => {
|
||||||
|
|
||||||
const yOffset = Math.abs(targetY - sourceY) / 2;
|
const yOffset = Math.abs(targetY - sourceY) / 2;
|
||||||
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
||||||
const dAttr = `M${sourceX},${sourceY} C${sourceX},${centerY} ${targetX},${centerY} ${targetX},${targetY}`;
|
|
||||||
|
let dAttr = `M${sourceX},${sourceY} C${sourceX},${centerY} ${targetX},${centerY} ${targetX},${targetY}`;
|
||||||
|
|
||||||
|
if (['left', 'right'].includes(sourcePosition) && ['left', 'right'].includes(targetPosition)) {
|
||||||
|
const xOffset = Math.abs(targetX - sourceX) / 2;
|
||||||
|
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
|
||||||
|
|
||||||
|
dAttr = `M${sourceX},${sourceY} C${centerX},${sourceY} ${centerX},${targetY} ${targetX},${targetY}`;
|
||||||
|
} else if (['left', 'right'].includes(sourcePosition) || ['left', 'right'].includes(targetPosition)) {
|
||||||
|
dAttr = `M${sourceX},${sourceY} C${sourceX},${targetY} ${sourceX},${targetY} ${targetX},${targetY}`;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<path
|
<path
|
||||||
|
|||||||
+71
-39
@@ -4,52 +4,74 @@ import { useStoreState } from 'easy-peasy';
|
|||||||
import ConnectionLine from '../ConnectionLine';
|
import ConnectionLine from '../ConnectionLine';
|
||||||
import { isEdge } from '../graph-utils';
|
import { isEdge } from '../graph-utils';
|
||||||
|
|
||||||
function getEdgePositions({ sourceNode, targetNode, sourceHandleId, targetHandleId }) {
|
function getHandlePosition(position, node, handle = null) {
|
||||||
const hasSourceHandle = !!sourceNode.__rg.handleBounds.source;
|
if (!handle) {
|
||||||
const hasTargetHandle = !!targetNode.__rg.handleBounds.target;
|
switch (position) {
|
||||||
|
case 'top': return {
|
||||||
let sourceHandle = null;
|
x: node.__rg.width / 2,
|
||||||
let targetHandle = null;
|
y: 0
|
||||||
|
};
|
||||||
if (hasSourceHandle) {
|
case 'right': return {
|
||||||
// there is no sourceHandleId when there are no multiple handles/ handles with ids
|
x: node.__rg.width,
|
||||||
// so we just pick the first one
|
y: node.__rg.height / 2
|
||||||
if (sourceNode.__rg.handleBounds.source.length === 1 || !sourceHandleId) {
|
};
|
||||||
sourceHandle = sourceNode.__rg.handleBounds.source[0];
|
case 'bottom': return {
|
||||||
} else if (sourceHandleId) {
|
x: node.__rg.width / 2,
|
||||||
sourceHandle = sourceNode.__rg.handleBounds.source.find(d => d.id === sourceHandleId);
|
y: node.__rg.height
|
||||||
|
};
|
||||||
|
case 'left': return {
|
||||||
|
x: 0,
|
||||||
|
y: node.__rg.height / 2
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasTargetHandle) {
|
switch (position) {
|
||||||
if (targetNode.__rg.handleBounds.target.length === 1 || !targetHandleId) {
|
case 'top': return {
|
||||||
targetHandle = targetNode.__rg.handleBounds.target[0];
|
x: handle.x + (handle.width / 2),
|
||||||
} else if (targetHandleId) {
|
y: handle.y
|
||||||
targetHandle = targetNode.__rg.handleBounds.target.find(d => d.id === targetHandleId);
|
};
|
||||||
}
|
case 'right': return {
|
||||||
|
x: handle.x + handle.width,
|
||||||
|
y: handle.y + (handle.height / 2)
|
||||||
|
};
|
||||||
|
case 'bottom': return {
|
||||||
|
x: handle.x + (handle.width / 2),
|
||||||
|
y: handle.y + handle.height
|
||||||
|
};
|
||||||
|
case 'left': return {
|
||||||
|
x: handle.x,
|
||||||
|
y: handle.y + (handle.height / 2)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHandle(bounds, handleId) {
|
||||||
|
let handle = null;
|
||||||
|
|
||||||
|
if (!bounds) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sourceHandleX = hasSourceHandle ?
|
// there is no handleId when there are no multiple handles/ handles with ids
|
||||||
sourceHandle.x + (sourceHandle.width / 2) :
|
// so we just pick the first one
|
||||||
sourceNode.__rg.width / 2;
|
if (bounds.length === 1 || !handleId) {
|
||||||
|
handle = bounds[0];
|
||||||
|
} else if (handleId) {
|
||||||
|
handle = bounds.find(d => d.id === handleId);
|
||||||
|
}
|
||||||
|
|
||||||
const sourceHandleY = hasSourceHandle ?
|
return handle;
|
||||||
sourceHandle.y + (sourceHandle.height / 2) :
|
}
|
||||||
sourceNode.__rg.height;
|
|
||||||
|
|
||||||
const sourceX = sourceNode.__rg.position.x + sourceHandleX;
|
function getEdgePositions({ sourceNode, sourceHandle, sourcePosition, targetNode, targetHandle, targetPosition }) {
|
||||||
const sourceY = sourceNode.__rg.position.y + sourceHandleY;
|
const sourceHandlePos = getHandlePosition(sourcePosition, sourceNode, sourceHandle)
|
||||||
|
const sourceX = sourceNode.__rg.position.x + sourceHandlePos.x;
|
||||||
|
const sourceY = sourceNode.__rg.position.y + sourceHandlePos.y;
|
||||||
|
|
||||||
const targetHandleX = hasTargetHandle ?
|
const targetHandlePos = getHandlePosition(targetPosition, targetNode, targetHandle);
|
||||||
targetHandle.x + (targetHandle.width / 2) :
|
const targetX = targetNode.__rg.position.x + targetHandlePos.x;
|
||||||
targetNode.__rg.width / 2;
|
const targetY = targetNode.__rg.position.y + targetHandlePos.y;
|
||||||
|
|
||||||
const targetHandleY = hasTargetHandle ?
|
|
||||||
targetHandle.y + (targetHandle.height / 2) :
|
|
||||||
0;
|
|
||||||
|
|
||||||
const targetX = targetNode.__rg.position.x + targetHandleX;
|
|
||||||
const targetY = targetNode.__rg.position.y + targetHandleY;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sourceX, sourceY, targetX, targetY
|
sourceX, sourceY, targetX, targetY
|
||||||
@@ -80,7 +102,15 @@ function renderEdge(e, props, state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const EdgeComponent = props.edgeTypes[edgeType] || props.edgeTypes.default;
|
const EdgeComponent = props.edgeTypes[edgeType] || props.edgeTypes.default;
|
||||||
const { sourceX, sourceY, targetX, targetY } = getEdgePositions({ sourceNode, targetNode, sourceHandleId, targetHandleId });
|
const sourceHandle = getHandle(sourceNode.__rg.handleBounds.source, sourceHandleId);
|
||||||
|
const targetHandle = getHandle(targetNode.__rg.handleBounds.target, targetHandleId);
|
||||||
|
const sourcePosition = sourceHandle ? sourceHandle.position : 'bottom';
|
||||||
|
const targetPosition = targetHandle ? targetHandle.position : 'top';
|
||||||
|
|
||||||
|
const { sourceX, sourceY, targetX, targetY } = getEdgePositions({
|
||||||
|
sourceNode, sourceHandle, sourcePosition,
|
||||||
|
targetNode, targetHandle, targetPosition
|
||||||
|
});
|
||||||
const selected = state.selectedElements
|
const selected = state.selectedElements
|
||||||
.filter(isEdge)
|
.filter(isEdge)
|
||||||
.find(elm => elm.source === sourceId && elm.target === targetId);
|
.find(elm => elm.source === sourceId && elm.target === targetId);
|
||||||
@@ -102,6 +132,8 @@ function renderEdge(e, props, state) {
|
|||||||
sourceY={sourceY}
|
sourceY={sourceY}
|
||||||
targetX={targetX}
|
targetX={targetX}
|
||||||
targetY={targetY}
|
targetY={targetY}
|
||||||
|
sourcePosition={sourcePosition}
|
||||||
|
targetPosition={targetPosition}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,23 +40,26 @@ function onMouseDown(evt, { nodeId, setSourceId, setPosition, onConnect, isTarg
|
|||||||
}
|
}
|
||||||
|
|
||||||
const BaseHandle = memo(({
|
const BaseHandle = memo(({
|
||||||
source, target, nodeId, onConnect,
|
type, nodeId, onConnect, position,
|
||||||
setSourceId, setPosition, className,
|
setSourceId, setPosition, className,
|
||||||
id = false, ...rest
|
id = false, ...rest
|
||||||
}) => {
|
}) => {
|
||||||
|
const isTarget = type === 'target';
|
||||||
const handleClasses = cx(
|
const handleClasses = cx(
|
||||||
'react-graph__handle',
|
'react-graph__handle',
|
||||||
className,
|
className,
|
||||||
{ source, target }
|
position,
|
||||||
|
{ source: !isTarget, target: isTarget }
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleId = id ? `${nodeId}__${id}` : nodeId;
|
const nodeIdWithHandleId = id ? `${nodeId}__${id}` : nodeId;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-nodeid={handleId}
|
data-nodeid={nodeIdWithHandleId}
|
||||||
|
data-handlepos={position}
|
||||||
className={handleClasses}
|
className={handleClasses}
|
||||||
onMouseDown={evt => onMouseDown(evt, { nodeId: handleId, setSourceId, setPosition, onConnect, isTarget: target })}
|
onMouseDown={evt => onMouseDown(evt, { nodeId: nodeIdWithHandleId, setSourceId, setPosition, onConnect, isTarget })}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import React, { memo, useContext } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useStoreActions, useStoreState } from 'easy-peasy';
|
||||||
|
|
||||||
|
import BaseHandle from './BaseHandle';
|
||||||
|
import NodeIdContext from '../NodeIdContext'
|
||||||
|
|
||||||
|
const Handle = memo((props) => {
|
||||||
|
const nodeId = useContext(NodeIdContext);
|
||||||
|
const { setPosition, setSourceId } = useStoreActions(a => ({
|
||||||
|
setPosition: a.setConnectionPosition,
|
||||||
|
setSourceId: a.setConnectionSourceId
|
||||||
|
}));
|
||||||
|
const onConnect = useStoreState(s => s.onConnect);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseHandle
|
||||||
|
nodeId={nodeId}
|
||||||
|
setPosition={setPosition}
|
||||||
|
setSourceId={setSourceId}
|
||||||
|
onConnect={onConnect}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Handle.displayName = 'Handle';
|
||||||
|
|
||||||
|
Handle.propTypes = {
|
||||||
|
type: PropTypes.oneOf(['source', 'target']),
|
||||||
|
position: PropTypes.oneOf(['top', 'right', 'bottom', 'left']),
|
||||||
|
};
|
||||||
|
|
||||||
|
Handle.defaultProps = {
|
||||||
|
type: 'source',
|
||||||
|
position: 'top'
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Handle;
|
||||||
@@ -14,7 +14,8 @@ const SourceHandle = memo((props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseHandle
|
<BaseHandle
|
||||||
source
|
type="source"
|
||||||
|
position="bottom"
|
||||||
nodeId={nodeId}
|
nodeId={nodeId}
|
||||||
setPosition={setPosition}
|
setPosition={setPosition}
|
||||||
setSourceId={setSourceId}
|
setSourceId={setSourceId}
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ const TargetHandle = memo((props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseHandle
|
<BaseHandle
|
||||||
target
|
type="target"
|
||||||
|
position="top"
|
||||||
nodeId={nodeId}
|
nodeId={nodeId}
|
||||||
setPosition={setPosition}
|
setPosition={setPosition}
|
||||||
setSourceId={setSourceId}
|
setSourceId={setSourceId}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import TargetHandle from '../HandleTypes/TargetHandle';
|
import Handle from '../HandleTypes/Handle';
|
||||||
import SourceHandle from '../HandleTypes/SourceHandle';
|
|
||||||
|
|
||||||
const nodeStyles = {
|
const nodeStyles = {
|
||||||
background: '#ff6060',
|
background: '#ff6060',
|
||||||
@@ -12,8 +11,8 @@ const nodeStyles = {
|
|||||||
|
|
||||||
export default ({ data, style }) => (
|
export default ({ data, style }) => (
|
||||||
<div style={{ ...nodeStyles, ...style }}>
|
<div style={{ ...nodeStyles, ...style }}>
|
||||||
<TargetHandle />
|
<Handle type="target" position="top" />
|
||||||
{data.label}
|
{data.label}
|
||||||
<SourceHandle />
|
<Handle type="source" position="bottom" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import SourceHandle from '../HandleTypes/SourceHandle';
|
import Handle from '../HandleTypes/Handle';
|
||||||
|
|
||||||
const nodeStyles = {
|
const nodeStyles = {
|
||||||
background: '#9999ff',
|
background: '#9999ff',
|
||||||
@@ -15,6 +15,6 @@ export default ({ data, style }) => (
|
|||||||
className="react-graph__node-inner"
|
className="react-graph__node-inner"
|
||||||
>
|
>
|
||||||
{data.label}
|
{data.label}
|
||||||
<SourceHandle />
|
<Handle type="source" position="bottom" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import TargetHandle from '../HandleTypes/TargetHandle';
|
import Handle from '../HandleTypes/TargetHandle';
|
||||||
|
|
||||||
const nodeStyles = {
|
const nodeStyles = {
|
||||||
background: '#55dd99',
|
background: '#55dd99',
|
||||||
@@ -11,7 +11,7 @@ const nodeStyles = {
|
|||||||
|
|
||||||
export default ({ data, style }) => (
|
export default ({ data, style }) => (
|
||||||
<div style={{ ...nodeStyles, ...style }}>
|
<div style={{ ...nodeStyles, ...style }}>
|
||||||
<TargetHandle />
|
<Handle type="target" position="top" />
|
||||||
{data.label}
|
{data.label}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ const getHandleBounds = (sel, nodeElement, parentBounds, k) => {
|
|||||||
const bounds = handle.getBoundingClientRect();
|
const bounds = handle.getBoundingClientRect();
|
||||||
const dimensions = getDimensions(handle);
|
const dimensions = getDimensions(handle);
|
||||||
const nodeIdAttr = handle.getAttribute('data-nodeid');
|
const nodeIdAttr = handle.getAttribute('data-nodeid');
|
||||||
|
const handlePosition = handle.getAttribute('data-handlepos');
|
||||||
const nodeIdSplitted = nodeIdAttr.split('__');
|
const nodeIdSplitted = nodeIdAttr.split('__');
|
||||||
|
|
||||||
let handleId = null;
|
let handleId = null;
|
||||||
@@ -33,6 +34,7 @@ const getHandleBounds = (sel, nodeElement, parentBounds, k) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
id: handleId,
|
id: handleId,
|
||||||
|
position: handlePosition,
|
||||||
x: (bounds.x - parentBounds.x) * (1 / k),
|
x: (bounds.x - parentBounds.x) * (1 / k),
|
||||||
y: (bounds.y - parentBounds.y) * (1 / k),
|
y: (bounds.y - parentBounds.y) * (1 / k),
|
||||||
...dimensions
|
...dimensions
|
||||||
|
|||||||
+1
-2
@@ -2,8 +2,7 @@ import ReactGraph from './ReactGraph';
|
|||||||
|
|
||||||
export default ReactGraph;
|
export default ReactGraph;
|
||||||
|
|
||||||
export { default as SourceHandle } from './NodeRenderer/HandleTypes/SourceHandle';
|
export { default as Handle } from './NodeRenderer/HandleTypes/Handle';
|
||||||
export { default as TargetHandle } from './NodeRenderer/HandleTypes/TargetHandle';
|
|
||||||
export { default as MiniMap } from './Plugins/MiniMap';
|
export { default as MiniMap } from './Plugins/MiniMap';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
+16
-4
@@ -104,21 +104,33 @@
|
|||||||
width: 10px;
|
width: 10px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
background: rgba(255, 255, 255, 0.4);
|
background: rgba(255, 255, 255, 0.4);
|
||||||
|
cursor: crosshair;
|
||||||
|
|
||||||
&.source {
|
&.bottom {
|
||||||
top: auto;
|
top: auto;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
cursor: crosshair;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.target {
|
&.top {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 0;
|
top: 0;
|
||||||
cursor: crosshair;
|
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.left {
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
transform: translate(0, -50%);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
right: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(0, -50%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.react-graph__nodesselection {
|
.react-graph__nodesselection {
|
||||||
|
|||||||
Reference in New Issue
Block a user