-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathindex.tsx
More file actions
109 lines (100 loc) · 3.11 KB
/
index.tsx
File metadata and controls
109 lines (100 loc) · 3.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { uuid } from '@del-wang/utils';
import { EdgeLabelRenderer, type Position } from '@xyflow/react';
import { useMemo } from 'react';
import { getLineCenter } from '@/layout/edge/edge';
import type { ControlPoint } from '@/layout/edge/point';
import { flowStore } from '@/states/reactflow';
import { getEdgeContext, SmartEdge } from './smart-edge';
import { useEdgeDraggable } from './useEdgeDraggable';
export interface EdgeControllersParams {
id: string;
points: ControlPoint[];
sourcePosition: Position;
targetPosition: Position;
offset: number;
handlerWidth: number;
handlerThickness: number;
}
export const EdgeControllers = (props: EdgeControllersParams) => {
const { points } = props;
const edges = useMemo(() => {
const smartEdges: SmartEdge[] = [];
const edgeContext = getEdgeContext(props);
for (let i = 0; i < points.length - 1; i++) {
smartEdges.push(
new SmartEdge({
idx: i,
start: points[i],
end: points[i + 1],
ctx: edgeContext,
}),
);
}
smartEdges.forEach((e, idx) => {
e.previous = smartEdges[idx - 2];
e.next = smartEdges[idx + 2];
});
return smartEdges;
}, [points]);
return (
<>
{edges.map((edge) => {
return edge.canDrag && <EdgeController edge={edge} key={uuid()} />; // use unique key to force rebuild EdgeController
})}
</>
);
};
export const EdgeController = ({ edge }: { edge: SmartEdge }) => {
const { start, end, onDragging } = edge;
const { handlerWidth, handlerThickness } = edge.ctx;
const center = getLineCenter(start, end);
const isHorizontal = start.y === end.y;
const { dragRef } = useEdgeDraggable({
edge,
onDragging(dragId, dragFrom, position, delta) {
const oldFlowPosition = flowStore.value.screenToFlowPosition({
x: position.x - delta.x,
y: position.y - delta.y,
});
const newFlowPosition = flowStore.value.screenToFlowPosition(position);
const flowDelta = {
x: newFlowPosition.x - oldFlowPosition.x,
y: newFlowPosition.y - oldFlowPosition.y,
};
const newStart = { ...start };
const newEnd = { ...end };
if (isHorizontal) {
newStart.y += flowDelta.y;
newEnd.y += flowDelta.y;
} else {
newStart.x += flowDelta.x;
newEnd.x += flowDelta.x;
}
onDragging({
dragId,
dragFrom,
from: { start, end },
to: { start: newStart, end: newEnd },
});
},
});
return (
<EdgeLabelRenderer>
<div
className="nodrag nopan"
ref={dragRef}
style={{
cursor: isHorizontal ? 'row-resize' : 'col-resize',
position: 'absolute',
transform: `translate(-50%, -50%) translate(${center.x}px,${center.y}px)`,
width: isHorizontal ? `${handlerWidth}px` : `${handlerThickness}px`,
height: !isHorizontal ? `${handlerWidth}px` : `${handlerThickness}px`,
borderRadius: '2px',
background: '#3579f6',
border: '1px solid #fff',
pointerEvents: 'all',
}}
/>
</EdgeLabelRenderer>
);
};