feat: Show connection lines when holding down on handle
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { ref, defineComponent, CSSProperties, PropType } from 'vue';
|
import { ref, defineComponent, CSSProperties, PropType, computed } from 'vue';
|
||||||
|
|
||||||
import { getBezierPath } from '../Edges/BezierEdge';
|
import { getBezierPath } from '../Edges/BezierEdge';
|
||||||
import { getSmoothStepPath } from '../Edges/SmoothStepEdge';
|
import { getSmoothStepPath } from '../Edges/SmoothStepEdge';
|
||||||
@@ -79,44 +79,52 @@ const ConnectionLine = defineComponent({
|
|||||||
CustomConnectionLineComponent: {
|
CustomConnectionLineComponent: {
|
||||||
type: Object as PropType<ConnectionLineProps['CustomConnectionLineComponent']>,
|
type: Object as PropType<ConnectionLineProps['CustomConnectionLineComponent']>,
|
||||||
required: false,
|
required: false,
|
||||||
default: () => ({})
|
default: undefined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
console.log('connectionline');
|
|
||||||
const sourceNode = ref<Node | null>(props.nodes.find((n) => n.id === props.connectionNodeId) || null);
|
const sourceNode = ref<Node | null>(props.nodes.find((n) => n.id === props.connectionNodeId) || null);
|
||||||
|
|
||||||
if (!sourceNode.value || !props.isConnectable) {
|
if (!sourceNode.value || !props.isConnectable) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sourceHandle = props.connectionHandleId
|
const sourceHandle = computed(() =>
|
||||||
? sourceNode.value.__rf.handleBounds[props.connectionHandleType].find(
|
props.connectionHandleId
|
||||||
(d: HandleElement) => d.id === props.connectionHandleId
|
? sourceNode.value?.__rf.handleBounds[props.connectionHandleType].find(
|
||||||
)
|
(d: HandleElement) => d.id === props.connectionHandleId
|
||||||
: sourceNode.value.__rf.handleBounds[props.connectionHandleType][0];
|
)
|
||||||
const sourceHandleX = sourceHandle ? sourceHandle.x + sourceHandle.width / 2 : sourceNode.value.__rf.width / 2;
|
: sourceNode.value?.__rf.handleBounds[props.connectionHandleType][0]
|
||||||
const sourceHandleY = sourceHandle ? sourceHandle.y + sourceHandle.height / 2 : sourceNode.value.__rf.height;
|
);
|
||||||
const sourceX = sourceNode.value.__rf.position.x + sourceHandleX;
|
const sourceHandleX = computed(() =>
|
||||||
const sourceY = sourceNode.value.__rf.position.y + sourceHandleY;
|
sourceHandle.value ? sourceHandle.value.x + sourceHandle.value.width / 2 : sourceNode.value?.__rf.width / 2
|
||||||
|
);
|
||||||
|
const sourceHandleY = computed(() =>
|
||||||
|
sourceHandle.value ? sourceHandle.value.y + sourceHandle.value.height / 2 : sourceNode.value?.__rf.height
|
||||||
|
);
|
||||||
|
const sourceX = computed(() => sourceNode.value?.__rf.position.x + sourceHandleX.value);
|
||||||
|
const sourceY = computed(() => sourceNode.value?.__rf.position.y + sourceHandleY.value);
|
||||||
|
|
||||||
const targetX = (props.connectionPositionX - props.transform[0]) / props.transform[2];
|
const targetX = computed(() => (props.connectionPositionX - props.transform[0]) / props.transform[2]);
|
||||||
const targetY = (props.connectionPositionY - props.transform[1]) / props.transform[2];
|
const targetY = computed(() => (props.connectionPositionY - props.transform[1]) / props.transform[2]);
|
||||||
|
|
||||||
const isRightOrLeft = sourceHandle?.position === Position.Left || sourceHandle?.position === Position.Right;
|
const isRightOrLeft = computed(
|
||||||
const targetPosition = isRightOrLeft ? Position.Left : Position.Top;
|
() => sourceHandle.value?.position === Position.Left || sourceHandle.value?.position === Position.Right
|
||||||
|
);
|
||||||
|
const targetPosition = computed(() => (isRightOrLeft.value ? Position.Left : Position.Top));
|
||||||
|
|
||||||
if (props.CustomConnectionLineComponent) {
|
if (props.CustomConnectionLineComponent) {
|
||||||
|
// eslint-disable-next-line vue/no-setup-props-destructure
|
||||||
|
const ConnectionLineComponent: any = props.CustomConnectionLineComponent;
|
||||||
return () => (
|
return () => (
|
||||||
<g class="react-flow__connection">
|
<g class="react-flow__connection">
|
||||||
<component
|
<ConnectionLineComponent
|
||||||
is={props.CustomConnectionLineComponent}
|
sourceX={sourceX.value}
|
||||||
sourceX={sourceX}
|
sourceY={sourceY.value}
|
||||||
sourceY={sourceY}
|
sourcePosition={sourceHandle.value?.position}
|
||||||
sourcePosition={sourceHandle?.position}
|
targetX={targetX.value}
|
||||||
targetX={targetX}
|
targetY={targetY.value}
|
||||||
targetY={targetY}
|
targetPosition={targetPosition.value}
|
||||||
targetPosition={targetPosition}
|
|
||||||
connectionLineType={props.connectionLineType}
|
connectionLineType={props.connectionLineType}
|
||||||
connectionLineStyle={props.connectionLineStyle}
|
connectionLineStyle={props.connectionLineStyle}
|
||||||
/>
|
/>
|
||||||
@@ -124,43 +132,47 @@ const ConnectionLine = defineComponent({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dAttr = '';
|
let dAttr = computed(() => `M${sourceX.value},${sourceY.value} ${targetX.value},${targetY.value}`);
|
||||||
|
|
||||||
if (props.connectionLineType === ConnectionLineType.Bezier) {
|
if (props.connectionLineType === ConnectionLineType.Bezier) {
|
||||||
dAttr = getBezierPath({
|
dAttr = computed(() =>
|
||||||
sourceX,
|
getBezierPath({
|
||||||
sourceY,
|
sourceX: sourceX.value,
|
||||||
sourcePosition: sourceHandle?.position,
|
sourceY: sourceY.value,
|
||||||
targetX,
|
sourcePosition: sourceHandle.value?.position,
|
||||||
targetY,
|
targetX: targetX.value,
|
||||||
targetPosition
|
targetY: targetY.value,
|
||||||
});
|
targetPosition: targetPosition.value
|
||||||
|
})
|
||||||
|
);
|
||||||
} else if (props.connectionLineType === ConnectionLineType.Step) {
|
} else if (props.connectionLineType === ConnectionLineType.Step) {
|
||||||
dAttr = getSmoothStepPath({
|
dAttr = computed(() =>
|
||||||
sourceX,
|
getSmoothStepPath({
|
||||||
sourceY,
|
sourceX: sourceX.value,
|
||||||
sourcePosition: sourceHandle?.position,
|
sourceY: sourceY.value,
|
||||||
targetX,
|
sourcePosition: sourceHandle.value?.position,
|
||||||
targetY,
|
targetX: targetX.value,
|
||||||
targetPosition,
|
targetY: targetY.value,
|
||||||
borderRadius: 0
|
targetPosition: targetPosition.value,
|
||||||
});
|
borderRadius: 0
|
||||||
|
})
|
||||||
|
);
|
||||||
} else if (props.connectionLineType === ConnectionLineType.SmoothStep) {
|
} else if (props.connectionLineType === ConnectionLineType.SmoothStep) {
|
||||||
dAttr = getSmoothStepPath({
|
dAttr = computed(() =>
|
||||||
sourceX,
|
getSmoothStepPath({
|
||||||
sourceY,
|
sourceX: sourceX.value,
|
||||||
sourcePosition: sourceHandle?.position,
|
sourceY: sourceY.value,
|
||||||
targetX,
|
sourcePosition: sourceHandle.value?.position,
|
||||||
targetY,
|
targetX: targetX.value,
|
||||||
targetPosition
|
targetY: targetY.value,
|
||||||
});
|
targetPosition: targetPosition.value
|
||||||
} else {
|
})
|
||||||
dAttr = `M${sourceX},${sourceY} ${targetX},${targetY}`;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<g class="react-flow__connection">
|
<g class="react-flow__connection">
|
||||||
<path d={dAttr} class="react-flow__connection-path" style={props.connectionLineStyle} />
|
<path d={dAttr.value} class="react-flow__connection-path" style={props.connectionLineStyle} />
|
||||||
</g>
|
</g>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ const BezierEdge = defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
console.log('edge');
|
|
||||||
const centered = computed(() => {
|
const centered = computed(() => {
|
||||||
return getCenter({
|
return getCenter({
|
||||||
sourceX: props.sourceX,
|
sourceX: props.sourceX,
|
||||||
@@ -132,7 +131,6 @@ const BezierEdge = defineComponent({
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
const path = computed(() => {
|
const path = computed(() => {
|
||||||
console.log('computing in edge');
|
|
||||||
return getBezierPath({
|
return getBezierPath({
|
||||||
sourceX: props.sourceX,
|
sourceX: props.sourceX,
|
||||||
sourceY: props.sourceY,
|
sourceY: props.sourceY,
|
||||||
|
|||||||
@@ -48,23 +48,23 @@ export default (EdgeComponent: any): Component<EdgeProps> => {
|
|||||||
pinia.addSelectedElements(edgeElement.value as any);
|
pinia.addSelectedElements(edgeElement.value as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
props.onClick?.(event, edgeElement.value);
|
if (props.onClick) props.onClick?.(event, edgeElement.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onEdgeContextMenu = (event: MouseEvent) => {
|
const onEdgeContextMenu = (event: MouseEvent) => {
|
||||||
props.onContextMenu?.(event, edgeElement.value);
|
if (props.onContextMenu) props.onContextMenu?.(event, edgeElement.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onEdgeMouseEnter = (event: MouseEvent) => {
|
const onEdgeMouseEnter = (event: MouseEvent) => {
|
||||||
props.onMouseEnter?.(event, edgeElement.value);
|
if (props.onMouseEnter) props.onMouseEnter?.(event, edgeElement.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onEdgeMouseMove = (event: MouseEvent) => {
|
const onEdgeMouseMove = (event: MouseEvent) => {
|
||||||
props.onMouseMove?.(event, edgeElement.value);
|
if (props.onMouseMove) props.onMouseMove?.(event, edgeElement.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onEdgeMouseLeave = (event: MouseEvent) => {
|
const onEdgeMouseLeave = (event: MouseEvent) => {
|
||||||
props.onMouseLeave?.(event, edgeElement.value);
|
if (props.onMouseLeave) props.onMouseLeave?.(event, edgeElement.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEdgeUpdater = (event: MouseEvent, isSourceHandle: boolean) => {
|
const handleEdgeUpdater = (event: MouseEvent, isSourceHandle: boolean) => {
|
||||||
|
|||||||
@@ -103,8 +103,6 @@ export function onMouseDown(
|
|||||||
// when react-flow is used inside a shadow root we can't use document
|
// when react-flow is used inside a shadow root we can't use document
|
||||||
const doc = getHostForElement(event.target as HTMLElement);
|
const doc = getHostForElement(event.target as HTMLElement);
|
||||||
|
|
||||||
console.log(doc);
|
|
||||||
|
|
||||||
if (!doc) {
|
if (!doc) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Connection, ElementId, Position } from '../../types';
|
import { Connection, ElementId, Position } from '../../types';
|
||||||
|
|
||||||
import { onMouseDown, ValidConnectionFunc } from './handler';
|
import { onMouseDown, ValidConnectionFunc } from './handler';
|
||||||
import { defineComponent, inject, PropType } from 'vue';
|
import { defineComponent, inject, PropType } from 'vue';
|
||||||
import store from '../../store';
|
import store from '../../store';
|
||||||
@@ -42,7 +41,6 @@ const Handle = defineComponent({
|
|||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
const pinia = store();
|
const pinia = store();
|
||||||
const nodeId = inject<ElementId>('NodeIdContext') as ElementId;
|
const nodeId = inject<ElementId>('NodeIdContext') as ElementId;
|
||||||
const handleId = props.id || null;
|
|
||||||
const isTarget = props.type === 'target';
|
const isTarget = props.type === 'target';
|
||||||
|
|
||||||
const onConnectExtended = (params: Connection) => {
|
const onConnectExtended = (params: Connection) => {
|
||||||
@@ -53,7 +51,7 @@ const Handle = defineComponent({
|
|||||||
const onMouseDownHandler = (event: MouseEvent) => {
|
const onMouseDownHandler = (event: MouseEvent) => {
|
||||||
onMouseDown(
|
onMouseDown(
|
||||||
event,
|
event,
|
||||||
handleId,
|
props.id || '',
|
||||||
nodeId,
|
nodeId,
|
||||||
pinia.setConnectionNodeId,
|
pinia.setConnectionNodeId,
|
||||||
pinia.setConnectionPosition,
|
pinia.setConnectionPosition,
|
||||||
@@ -82,7 +80,7 @@ const Handle = defineComponent({
|
|||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div
|
<div
|
||||||
data-handleid={handleId}
|
data-handleid={props.id}
|
||||||
data-nodeid={nodeId}
|
data-nodeid={nodeId}
|
||||||
data-handlepos={props.position}
|
data-handlepos={props.position}
|
||||||
class={handleClasses}
|
class={handleClasses}
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ export const getEdgePositions = (
|
|||||||
const sourceHandlePos = getHandlePosition(sourcePosition, sourceNode, sourceHandle);
|
const sourceHandlePos = getHandlePosition(sourcePosition, sourceNode, sourceHandle);
|
||||||
const targetHandlePos = getHandlePosition(targetPosition, targetNode, targetHandle);
|
const targetHandlePos = getHandlePosition(targetPosition, targetNode, targetHandle);
|
||||||
|
|
||||||
console.log('getting edge positions');
|
|
||||||
return {
|
return {
|
||||||
sourceX: sourceHandlePos.x,
|
sourceX: sourceHandlePos.x,
|
||||||
sourceY: sourceHandlePos.y,
|
sourceY: sourceHandlePos.y,
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import FlowRenderer from '../FlowRenderer';
|
|||||||
import NodeRenderer from '../NodeRenderer';
|
import NodeRenderer from '../NodeRenderer';
|
||||||
import EdgeRenderer from '../EdgeRenderer';
|
import EdgeRenderer from '../EdgeRenderer';
|
||||||
import { onLoadProject, onLoadGetElements, onLoadToObject } from '../../utils/graph';
|
import { onLoadProject, onLoadGetElements, onLoadToObject } from '../../utils/graph';
|
||||||
|
|
||||||
import { ReactFlowProps } from '../RevueFlow';
|
import { ReactFlowProps } from '../RevueFlow';
|
||||||
|
|
||||||
import { NodeTypesType, EdgeTypesType, ConnectionLineType, KeyCode } from '../../types';
|
import { NodeTypesType, EdgeTypesType, ConnectionLineType, KeyCode } from '../../types';
|
||||||
import { CSSProperties, defineComponent, onMounted, PropType, ref } from 'vue';
|
import { CSSProperties, defineComponent, onMounted, PropType, ref } from 'vue';
|
||||||
import store from '../../store';
|
import store from '../../store';
|
||||||
|
|||||||
Reference in New Issue
Block a user