@yh-ui/flow 1.0.51 → 1.0.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Flow.d.vue.ts +25 -2
- package/dist/Flow.vue +221 -40
- package/dist/Flow.vue.d.ts +25 -2
- package/dist/core/useAlignment.cjs +32 -12
- package/dist/core/useAlignment.mjs +49 -19
- package/dist/core/useKeyboard.cjs +3 -1
- package/dist/core/useKeyboard.mjs +3 -1
- package/dist/core/useNodeDistribution.cjs +16 -16
- package/dist/core/useNodeDistribution.mjs +30 -16
- package/dist/core/useSelection.cjs +6 -3
- package/dist/core/useSelection.mjs +6 -3
- package/dist/core/useViewport.cjs +4 -4
- package/dist/core/useViewport.d.ts +8 -0
- package/dist/core/useViewport.mjs +4 -4
- package/dist/plugins/plugins/layout.cjs +6 -6
- package/dist/plugins/plugins/layout.mjs +6 -6
- package/dist/plugins/plugins/node-group.cjs +10 -2
- package/dist/plugins/plugins/node-group.mjs +10 -2
- package/dist/renderer/AlignmentLines.vue +26 -16
- package/dist/renderer/EdgeHandlesRenderer.vue +11 -2
- package/dist/renderer/EdgeRenderer.vue +5 -3
- package/dist/renderer/Minimap.vue +28 -18
- package/dist/renderer/NodeRenderer.d.vue.ts +2 -0
- package/dist/renderer/NodeRenderer.vue +74 -13
- package/dist/renderer/NodeRenderer.vue.d.ts +2 -0
- package/dist/types/index.d.ts +27 -0
- package/dist/utils/custom-types.cjs +21 -0
- package/dist/utils/custom-types.d.ts +25 -0
- package/dist/utils/custom-types.mjs +17 -0
- package/dist/utils/edge.cjs +40 -2
- package/dist/utils/edge.d.ts +11 -1
- package/dist/utils/edge.mjs +31 -2
- package/package.json +18 -4
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ref } from "vue";
|
|
2
|
+
import { getNodeAbsolutePosition } from "../utils/custom-types.mjs";
|
|
2
3
|
export function useAlignment(options) {
|
|
3
4
|
const { nodes, snapThreshold = 10 } = options;
|
|
4
5
|
const horizontalSnapLines = ref([]);
|
|
@@ -8,25 +9,44 @@ export function useAlignment(options) {
|
|
|
8
9
|
if (!node) {
|
|
9
10
|
return { x: position.x, y: position.y, snappedX: false, snappedY: false };
|
|
10
11
|
}
|
|
11
|
-
const nodeWidth = node.width
|
|
12
|
-
const nodeHeight = node.height
|
|
12
|
+
const nodeWidth = node.measured?.width ?? node.width ?? 200;
|
|
13
|
+
const nodeHeight = node.measured?.height ?? node.height ?? 50;
|
|
13
14
|
const otherNodes = nodes.value.filter((n) => n.id !== nodeId);
|
|
14
15
|
let snappedX = false;
|
|
15
16
|
let snappedY = false;
|
|
16
|
-
const
|
|
17
|
+
const nodeMap = new Map(nodes.value.map((n) => [n.id, n]));
|
|
18
|
+
const absPosOffset = { x: 0, y: 0 };
|
|
19
|
+
if (node.parentId) {
|
|
20
|
+
const parent = nodeMap.get(node.parentId);
|
|
21
|
+
if (parent) {
|
|
22
|
+
const parentAbsPos = getNodeAbsolutePosition(parent, nodeMap);
|
|
23
|
+
absPosOffset.x = parentAbsPos.x;
|
|
24
|
+
absPosOffset.y = parentAbsPos.y;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const proposedAbsPos = {
|
|
28
|
+
x: position.x + absPosOffset.x,
|
|
29
|
+
y: position.y + absPosOffset.y
|
|
30
|
+
};
|
|
31
|
+
const dragYPositions = [
|
|
32
|
+
proposedAbsPos.y,
|
|
33
|
+
proposedAbsPos.y + nodeHeight / 2,
|
|
34
|
+
proposedAbsPos.y + nodeHeight
|
|
35
|
+
];
|
|
17
36
|
for (const otherNode of otherNodes) {
|
|
18
|
-
const otherHeight = otherNode.height
|
|
37
|
+
const otherHeight = otherNode.measured?.height ?? otherNode.height ?? 50;
|
|
38
|
+
const otherAbsPos = getNodeAbsolutePosition(otherNode, nodeMap);
|
|
19
39
|
const otherYPositions = [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
40
|
+
otherAbsPos.y,
|
|
41
|
+
otherAbsPos.y + otherHeight / 2,
|
|
42
|
+
otherAbsPos.y + otherHeight
|
|
23
43
|
];
|
|
24
44
|
for (let i = 0; i < dragYPositions.length; i++) {
|
|
25
45
|
for (const otherY of otherYPositions) {
|
|
26
46
|
if (Math.abs(dragYPositions[i] - otherY) < snapThreshold) {
|
|
27
|
-
if (i === 0)
|
|
28
|
-
else if (i === 1)
|
|
29
|
-
else
|
|
47
|
+
if (i === 0) proposedAbsPos.y = otherY;
|
|
48
|
+
else if (i === 1) proposedAbsPos.y = otherY - nodeHeight / 2;
|
|
49
|
+
else proposedAbsPos.y = otherY - nodeHeight;
|
|
30
50
|
snappedY = true;
|
|
31
51
|
break;
|
|
32
52
|
}
|
|
@@ -35,20 +55,25 @@ export function useAlignment(options) {
|
|
|
35
55
|
}
|
|
36
56
|
if (snappedY) break;
|
|
37
57
|
}
|
|
38
|
-
const dragXPositions = [
|
|
58
|
+
const dragXPositions = [
|
|
59
|
+
proposedAbsPos.x,
|
|
60
|
+
proposedAbsPos.x + nodeWidth / 2,
|
|
61
|
+
proposedAbsPos.x + nodeWidth
|
|
62
|
+
];
|
|
39
63
|
for (const otherNode of otherNodes) {
|
|
40
|
-
const otherWidth = otherNode.width
|
|
64
|
+
const otherWidth = otherNode.measured?.width ?? otherNode.width ?? 200;
|
|
65
|
+
const otherAbsPos = getNodeAbsolutePosition(otherNode, nodeMap);
|
|
41
66
|
const otherXPositions = [
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
67
|
+
otherAbsPos.x,
|
|
68
|
+
otherAbsPos.x + otherWidth / 2,
|
|
69
|
+
otherAbsPos.x + otherWidth
|
|
45
70
|
];
|
|
46
71
|
for (let i = 0; i < dragXPositions.length; i++) {
|
|
47
72
|
for (const otherX of otherXPositions) {
|
|
48
73
|
if (Math.abs(dragXPositions[i] - otherX) < snapThreshold) {
|
|
49
|
-
if (i === 0)
|
|
50
|
-
else if (i === 1)
|
|
51
|
-
else
|
|
74
|
+
if (i === 0) proposedAbsPos.x = otherX;
|
|
75
|
+
else if (i === 1) proposedAbsPos.x = otherX - nodeWidth / 2;
|
|
76
|
+
else proposedAbsPos.x = otherX - nodeWidth;
|
|
52
77
|
snappedX = true;
|
|
53
78
|
break;
|
|
54
79
|
}
|
|
@@ -56,7 +81,12 @@ export function useAlignment(options) {
|
|
|
56
81
|
if (snappedX) break;
|
|
57
82
|
}
|
|
58
83
|
}
|
|
59
|
-
return {
|
|
84
|
+
return {
|
|
85
|
+
x: proposedAbsPos.x - absPosOffset.x,
|
|
86
|
+
y: proposedAbsPos.y - absPosOffset.y,
|
|
87
|
+
snappedX,
|
|
88
|
+
snappedY
|
|
89
|
+
};
|
|
60
90
|
};
|
|
61
91
|
const snapToAlignment = (nodeId, position) => {
|
|
62
92
|
const snapResult = getAlignmentSnap(nodeId, position);
|
|
@@ -19,7 +19,9 @@ function useKeyboard(options = {}) {
|
|
|
19
19
|
if (!enabled) return;
|
|
20
20
|
const key = event.key;
|
|
21
21
|
const ctrl = event.ctrlKey || event.metaKey;
|
|
22
|
-
|
|
22
|
+
const target = event.target;
|
|
23
|
+
const isEditable = target && (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT" || target.isContentEditable === true);
|
|
24
|
+
if ((key === "Delete" || key === "Backspace") && !isEditable) {
|
|
23
25
|
event.preventDefault();
|
|
24
26
|
onDelete?.();
|
|
25
27
|
}
|
|
@@ -13,7 +13,9 @@ export function useKeyboard(options = {}) {
|
|
|
13
13
|
if (!enabled) return;
|
|
14
14
|
const key = event.key;
|
|
15
15
|
const ctrl = event.ctrlKey || event.metaKey;
|
|
16
|
-
|
|
16
|
+
const target = event.target;
|
|
17
|
+
const isEditable = target && (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT" || target.isContentEditable === true);
|
|
18
|
+
if ((key === "Delete" || key === "Backspace") && !isEditable) {
|
|
17
19
|
event.preventDefault();
|
|
18
20
|
onDelete?.();
|
|
19
21
|
}
|
|
@@ -15,8 +15,8 @@ function useNodeDistribution(options) {
|
|
|
15
15
|
targetNodes.sort((a, b) => a.position.x - b.position.x);
|
|
16
16
|
const firstNode = targetNodes[0];
|
|
17
17
|
const lastNode = targetNodes[targetNodes.length - 1];
|
|
18
|
-
const lastWidth = lastNode.width
|
|
19
|
-
const totalWidth = targetNodes.reduce((sum, n) => sum + (n.width
|
|
18
|
+
const lastWidth = lastNode.measured?.width ?? lastNode.width ?? 200;
|
|
19
|
+
const totalWidth = targetNodes.reduce((sum, n) => sum + (n.measured?.width ?? n.width ?? 200), 0);
|
|
20
20
|
const totalGap = gap * (targetNodes.length - 1);
|
|
21
21
|
const availableSpace = lastNode.position.x + lastWidth - firstNode.position.x - totalWidth - totalGap;
|
|
22
22
|
if (availableSpace <= 0) {
|
|
@@ -32,7 +32,7 @@ function useNodeDistribution(options) {
|
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
|
-
currentX += (node.width
|
|
35
|
+
currentX += (node.measured?.width ?? node.width ?? 200) + gap;
|
|
36
36
|
});
|
|
37
37
|
} else {
|
|
38
38
|
let currentX = firstNode.position.x;
|
|
@@ -47,7 +47,7 @@ function useNodeDistribution(options) {
|
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
-
currentX += (node.width
|
|
50
|
+
currentX += (node.measured?.width ?? node.width ?? 200) + gap;
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
53
|
};
|
|
@@ -58,8 +58,8 @@ function useNodeDistribution(options) {
|
|
|
58
58
|
targetNodes.sort((a, b) => a.position.y - b.position.y);
|
|
59
59
|
const firstNode = targetNodes[0];
|
|
60
60
|
const lastNode = targetNodes[targetNodes.length - 1];
|
|
61
|
-
const lastHeight = lastNode.height
|
|
62
|
-
const totalHeight = targetNodes.reduce((sum, n) => sum + (n.height
|
|
61
|
+
const lastHeight = lastNode.measured?.height ?? lastNode.height ?? 50;
|
|
62
|
+
const totalHeight = targetNodes.reduce((sum, n) => sum + (n.measured?.height ?? n.height ?? 50), 0);
|
|
63
63
|
const totalGap = gap * (targetNodes.length - 1);
|
|
64
64
|
const availableSpace = lastNode.position.y + lastHeight - firstNode.position.y - totalHeight - totalGap;
|
|
65
65
|
if (availableSpace <= 0) {
|
|
@@ -75,7 +75,7 @@ function useNodeDistribution(options) {
|
|
|
75
75
|
}
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
|
-
currentY += (node.height
|
|
78
|
+
currentY += (node.measured?.height ?? node.height ?? 50) + gap;
|
|
79
79
|
});
|
|
80
80
|
} else {
|
|
81
81
|
let currentY = firstNode.position.y;
|
|
@@ -90,7 +90,7 @@ function useNodeDistribution(options) {
|
|
|
90
90
|
}
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
|
-
currentY += (node.height
|
|
93
|
+
currentY += (node.measured?.height ?? node.height ?? 50) + gap;
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
96
|
};
|
|
@@ -102,9 +102,9 @@ function useNodeDistribution(options) {
|
|
|
102
102
|
if (alignment === "left") {
|
|
103
103
|
referenceX = Math.min(...targetNodes.map(n => n.position.x));
|
|
104
104
|
} else if (alignment === "right") {
|
|
105
|
-
referenceX = Math.max(...targetNodes.map(n => n.position.x + (n.width
|
|
105
|
+
referenceX = Math.max(...targetNodes.map(n => n.position.x + (n.measured?.width ?? n.width ?? 200)));
|
|
106
106
|
} else {
|
|
107
|
-
const centers = targetNodes.map(n => n.position.x + (n.width
|
|
107
|
+
const centers = targetNodes.map(n => n.position.x + (n.measured?.width ?? n.width ?? 200) / 2);
|
|
108
108
|
referenceX = centers.reduce((a, b) => a + b, 0) / centers.length;
|
|
109
109
|
}
|
|
110
110
|
targetNodes.forEach(node => {
|
|
@@ -114,9 +114,9 @@ function useNodeDistribution(options) {
|
|
|
114
114
|
if (alignment === "left") {
|
|
115
115
|
newX = referenceX;
|
|
116
116
|
} else if (alignment === "right") {
|
|
117
|
-
newX = referenceX - (node.width
|
|
117
|
+
newX = referenceX - (node.measured?.width ?? node.width ?? 200);
|
|
118
118
|
} else {
|
|
119
|
-
newX = referenceX - (node.width
|
|
119
|
+
newX = referenceX - (node.measured?.width ?? node.width ?? 200) / 2;
|
|
120
120
|
}
|
|
121
121
|
nodes.value[nodeIndex] = {
|
|
122
122
|
...nodes.value[nodeIndex],
|
|
@@ -136,9 +136,9 @@ function useNodeDistribution(options) {
|
|
|
136
136
|
if (alignment === "top") {
|
|
137
137
|
referenceY = Math.min(...targetNodes.map(n => n.position.y));
|
|
138
138
|
} else if (alignment === "bottom") {
|
|
139
|
-
referenceY = Math.max(...targetNodes.map(n => n.position.y + (n.height
|
|
139
|
+
referenceY = Math.max(...targetNodes.map(n => n.position.y + (n.measured?.height ?? n.height ?? 50)));
|
|
140
140
|
} else {
|
|
141
|
-
const middles = targetNodes.map(n => n.position.y + (n.height
|
|
141
|
+
const middles = targetNodes.map(n => n.position.y + (n.measured?.height ?? n.height ?? 50) / 2);
|
|
142
142
|
referenceY = middles.reduce((a, b) => a + b, 0) / middles.length;
|
|
143
143
|
}
|
|
144
144
|
targetNodes.forEach(node => {
|
|
@@ -148,9 +148,9 @@ function useNodeDistribution(options) {
|
|
|
148
148
|
if (alignment === "top") {
|
|
149
149
|
newY = referenceY;
|
|
150
150
|
} else if (alignment === "bottom") {
|
|
151
|
-
newY = referenceY - (node.height
|
|
151
|
+
newY = referenceY - (node.measured?.height ?? node.height ?? 50);
|
|
152
152
|
} else {
|
|
153
|
-
newY = referenceY - (node.height
|
|
153
|
+
newY = referenceY - (node.measured?.height ?? node.height ?? 50) / 2;
|
|
154
154
|
}
|
|
155
155
|
nodes.value[nodeIndex] = {
|
|
156
156
|
...nodes.value[nodeIndex],
|
|
@@ -7,8 +7,11 @@ export function useNodeDistribution(options) {
|
|
|
7
7
|
targetNodes.sort((a, b) => a.position.x - b.position.x);
|
|
8
8
|
const firstNode = targetNodes[0];
|
|
9
9
|
const lastNode = targetNodes[targetNodes.length - 1];
|
|
10
|
-
const lastWidth = lastNode.width
|
|
11
|
-
const totalWidth = targetNodes.reduce(
|
|
10
|
+
const lastWidth = lastNode.measured?.width ?? lastNode.width ?? 200;
|
|
11
|
+
const totalWidth = targetNodes.reduce(
|
|
12
|
+
(sum, n) => sum + (n.measured?.width ?? n.width ?? 200),
|
|
13
|
+
0
|
|
14
|
+
);
|
|
12
15
|
const totalGap = gap * (targetNodes.length - 1);
|
|
13
16
|
const availableSpace = lastNode.position.x + lastWidth - firstNode.position.x - totalWidth - totalGap;
|
|
14
17
|
if (availableSpace <= 0) {
|
|
@@ -21,7 +24,7 @@ export function useNodeDistribution(options) {
|
|
|
21
24
|
position: { ...nodes.value[nodeIndex].position, x: currentX }
|
|
22
25
|
};
|
|
23
26
|
}
|
|
24
|
-
currentX += (node.width
|
|
27
|
+
currentX += (node.measured?.width ?? node.width ?? 200) + gap;
|
|
25
28
|
});
|
|
26
29
|
} else {
|
|
27
30
|
let currentX = firstNode.position.x;
|
|
@@ -33,7 +36,7 @@ export function useNodeDistribution(options) {
|
|
|
33
36
|
position: { ...nodes.value[nodeIndex].position, x: currentX }
|
|
34
37
|
};
|
|
35
38
|
}
|
|
36
|
-
currentX += (node.width
|
|
39
|
+
currentX += (node.measured?.width ?? node.width ?? 200) + gap;
|
|
37
40
|
});
|
|
38
41
|
}
|
|
39
42
|
};
|
|
@@ -44,8 +47,11 @@ export function useNodeDistribution(options) {
|
|
|
44
47
|
targetNodes.sort((a, b) => a.position.y - b.position.y);
|
|
45
48
|
const firstNode = targetNodes[0];
|
|
46
49
|
const lastNode = targetNodes[targetNodes.length - 1];
|
|
47
|
-
const lastHeight = lastNode.height
|
|
48
|
-
const totalHeight = targetNodes.reduce(
|
|
50
|
+
const lastHeight = lastNode.measured?.height ?? lastNode.height ?? 50;
|
|
51
|
+
const totalHeight = targetNodes.reduce(
|
|
52
|
+
(sum, n) => sum + (n.measured?.height ?? n.height ?? 50),
|
|
53
|
+
0
|
|
54
|
+
);
|
|
49
55
|
const totalGap = gap * (targetNodes.length - 1);
|
|
50
56
|
const availableSpace = lastNode.position.y + lastHeight - firstNode.position.y - totalHeight - totalGap;
|
|
51
57
|
if (availableSpace <= 0) {
|
|
@@ -58,7 +64,7 @@ export function useNodeDistribution(options) {
|
|
|
58
64
|
position: { ...nodes.value[nodeIndex].position, y: currentY }
|
|
59
65
|
};
|
|
60
66
|
}
|
|
61
|
-
currentY += (node.height
|
|
67
|
+
currentY += (node.measured?.height ?? node.height ?? 50) + gap;
|
|
62
68
|
});
|
|
63
69
|
} else {
|
|
64
70
|
let currentY = firstNode.position.y;
|
|
@@ -70,7 +76,7 @@ export function useNodeDistribution(options) {
|
|
|
70
76
|
position: { ...nodes.value[nodeIndex].position, y: currentY }
|
|
71
77
|
};
|
|
72
78
|
}
|
|
73
|
-
currentY += (node.height
|
|
79
|
+
currentY += (node.measured?.height ?? node.height ?? 50) + gap;
|
|
74
80
|
});
|
|
75
81
|
}
|
|
76
82
|
};
|
|
@@ -82,9 +88,13 @@ export function useNodeDistribution(options) {
|
|
|
82
88
|
if (alignment === "left") {
|
|
83
89
|
referenceX = Math.min(...targetNodes.map((n) => n.position.x));
|
|
84
90
|
} else if (alignment === "right") {
|
|
85
|
-
referenceX = Math.max(
|
|
91
|
+
referenceX = Math.max(
|
|
92
|
+
...targetNodes.map((n) => n.position.x + (n.measured?.width ?? n.width ?? 200))
|
|
93
|
+
);
|
|
86
94
|
} else {
|
|
87
|
-
const centers = targetNodes.map(
|
|
95
|
+
const centers = targetNodes.map(
|
|
96
|
+
(n) => n.position.x + (n.measured?.width ?? n.width ?? 200) / 2
|
|
97
|
+
);
|
|
88
98
|
referenceX = centers.reduce((a, b) => a + b, 0) / centers.length;
|
|
89
99
|
}
|
|
90
100
|
targetNodes.forEach((node) => {
|
|
@@ -94,9 +104,9 @@ export function useNodeDistribution(options) {
|
|
|
94
104
|
if (alignment === "left") {
|
|
95
105
|
newX = referenceX;
|
|
96
106
|
} else if (alignment === "right") {
|
|
97
|
-
newX = referenceX - (node.width
|
|
107
|
+
newX = referenceX - (node.measured?.width ?? node.width ?? 200);
|
|
98
108
|
} else {
|
|
99
|
-
newX = referenceX - (node.width
|
|
109
|
+
newX = referenceX - (node.measured?.width ?? node.width ?? 200) / 2;
|
|
100
110
|
}
|
|
101
111
|
nodes.value[nodeIndex] = {
|
|
102
112
|
...nodes.value[nodeIndex],
|
|
@@ -113,9 +123,13 @@ export function useNodeDistribution(options) {
|
|
|
113
123
|
if (alignment === "top") {
|
|
114
124
|
referenceY = Math.min(...targetNodes.map((n) => n.position.y));
|
|
115
125
|
} else if (alignment === "bottom") {
|
|
116
|
-
referenceY = Math.max(
|
|
126
|
+
referenceY = Math.max(
|
|
127
|
+
...targetNodes.map((n) => n.position.y + (n.measured?.height ?? n.height ?? 50))
|
|
128
|
+
);
|
|
117
129
|
} else {
|
|
118
|
-
const middles = targetNodes.map(
|
|
130
|
+
const middles = targetNodes.map(
|
|
131
|
+
(n) => n.position.y + (n.measured?.height ?? n.height ?? 50) / 2
|
|
132
|
+
);
|
|
119
133
|
referenceY = middles.reduce((a, b) => a + b, 0) / middles.length;
|
|
120
134
|
}
|
|
121
135
|
targetNodes.forEach((node) => {
|
|
@@ -125,9 +139,9 @@ export function useNodeDistribution(options) {
|
|
|
125
139
|
if (alignment === "top") {
|
|
126
140
|
newY = referenceY;
|
|
127
141
|
} else if (alignment === "bottom") {
|
|
128
|
-
newY = referenceY - (node.height
|
|
142
|
+
newY = referenceY - (node.measured?.height ?? node.height ?? 50);
|
|
129
143
|
} else {
|
|
130
|
-
newY = referenceY - (node.height
|
|
144
|
+
newY = referenceY - (node.measured?.height ?? node.height ?? 50) / 2;
|
|
131
145
|
}
|
|
132
146
|
nodes.value[nodeIndex] = {
|
|
133
147
|
...nodes.value[nodeIndex],
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.useSelection = useSelection;
|
|
7
7
|
var _vue = require("vue");
|
|
8
|
+
var _customTypes = require("../utils/custom-types.cjs");
|
|
8
9
|
function useSelection(options) {
|
|
9
10
|
const {
|
|
10
11
|
nodes,
|
|
@@ -44,10 +45,12 @@ function useSelection(options) {
|
|
|
44
45
|
width: maxX - minX,
|
|
45
46
|
height: maxY - minY
|
|
46
47
|
};
|
|
48
|
+
const nodeMap = new Map(nodes.value.map(n => [n.id, n]));
|
|
47
49
|
nodes.value = nodes.value.map(node => {
|
|
48
|
-
const nodeWidth = node.width
|
|
49
|
-
const nodeHeight = node.height
|
|
50
|
-
const
|
|
50
|
+
const nodeWidth = node.measured?.width ?? node.width ?? 200;
|
|
51
|
+
const nodeHeight = node.measured?.height ?? node.height ?? 50;
|
|
52
|
+
const absPos = (0, _customTypes.getNodeAbsolutePosition)(node, nodeMap);
|
|
53
|
+
const isInside = absPos.x >= minX && absPos.y >= minY && absPos.x + nodeWidth <= maxX && absPos.y + nodeHeight <= maxY;
|
|
51
54
|
return {
|
|
52
55
|
...node,
|
|
53
56
|
selected: isInside
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ref, computed } from "vue";
|
|
2
|
+
import { getNodeAbsolutePosition } from "../utils/custom-types.mjs";
|
|
2
3
|
export function useSelection(options) {
|
|
3
4
|
const { nodes, edges, onSelectionChange } = options;
|
|
4
5
|
const selectionRect = ref(null);
|
|
@@ -23,10 +24,12 @@ export function useSelection(options) {
|
|
|
23
24
|
width: maxX - minX,
|
|
24
25
|
height: maxY - minY
|
|
25
26
|
};
|
|
27
|
+
const nodeMap = new Map(nodes.value.map((n) => [n.id, n]));
|
|
26
28
|
nodes.value = nodes.value.map((node) => {
|
|
27
|
-
const nodeWidth = node.width
|
|
28
|
-
const nodeHeight = node.height
|
|
29
|
-
const
|
|
29
|
+
const nodeWidth = node.measured?.width ?? node.width ?? 200;
|
|
30
|
+
const nodeHeight = node.measured?.height ?? node.height ?? 50;
|
|
31
|
+
const absPos = getNodeAbsolutePosition(node, nodeMap);
|
|
32
|
+
const isInside = absPos.x >= minX && absPos.y >= minY && absPos.x + nodeWidth <= maxX && absPos.y + nodeHeight <= maxY;
|
|
30
33
|
return { ...node, selected: isInside };
|
|
31
34
|
});
|
|
32
35
|
};
|
|
@@ -86,8 +86,8 @@ function useViewport(initialTransform, options = {}) {
|
|
|
86
86
|
let maxX = -Infinity;
|
|
87
87
|
let maxY = -Infinity;
|
|
88
88
|
for (const node of nodes) {
|
|
89
|
-
const w = node.width
|
|
90
|
-
const h = node.height
|
|
89
|
+
const w = node.measured?.width ?? node.width ?? 200;
|
|
90
|
+
const h = node.measured?.height ?? node.height ?? 50;
|
|
91
91
|
minX = Math.min(minX, node.position.x);
|
|
92
92
|
minY = Math.min(minY, node.position.y);
|
|
93
93
|
maxX = Math.max(maxX, node.position.x + w);
|
|
@@ -112,8 +112,8 @@ function useViewport(initialTransform, options = {}) {
|
|
|
112
112
|
let centerX = 0;
|
|
113
113
|
let centerY = 0;
|
|
114
114
|
for (const node of nodes) {
|
|
115
|
-
const w = node.width
|
|
116
|
-
const h = node.height
|
|
115
|
+
const w = node.measured?.width ?? node.width ?? 200;
|
|
116
|
+
const h = node.measured?.height ?? node.height ?? 50;
|
|
117
117
|
centerX += node.position.x + w / 2;
|
|
118
118
|
centerY += node.position.y + h / 2;
|
|
119
119
|
}
|
|
@@ -28,6 +28,10 @@ export interface UseViewportReturn {
|
|
|
28
28
|
};
|
|
29
29
|
width?: number;
|
|
30
30
|
height?: number;
|
|
31
|
+
measured?: {
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
};
|
|
31
35
|
}[], options?: {
|
|
32
36
|
padding?: number;
|
|
33
37
|
}) => void;
|
|
@@ -41,6 +45,10 @@ export interface UseViewportReturn {
|
|
|
41
45
|
};
|
|
42
46
|
width?: number;
|
|
43
47
|
height?: number;
|
|
48
|
+
measured?: {
|
|
49
|
+
width: number;
|
|
50
|
+
height: number;
|
|
51
|
+
};
|
|
44
52
|
}[], options?: {
|
|
45
53
|
padding?: number;
|
|
46
54
|
}) => void;
|
|
@@ -58,8 +58,8 @@ export function useViewport(initialTransform, options = {}) {
|
|
|
58
58
|
let maxX = -Infinity;
|
|
59
59
|
let maxY = -Infinity;
|
|
60
60
|
for (const node of nodes) {
|
|
61
|
-
const w = node.width
|
|
62
|
-
const h = node.height
|
|
61
|
+
const w = node.measured?.width ?? node.width ?? 200;
|
|
62
|
+
const h = node.measured?.height ?? node.height ?? 50;
|
|
63
63
|
minX = Math.min(minX, node.position.x);
|
|
64
64
|
minY = Math.min(minY, node.position.y);
|
|
65
65
|
maxX = Math.max(maxX, node.position.x + w);
|
|
@@ -80,8 +80,8 @@ export function useViewport(initialTransform, options = {}) {
|
|
|
80
80
|
let centerX = 0;
|
|
81
81
|
let centerY = 0;
|
|
82
82
|
for (const node of nodes) {
|
|
83
|
-
const w = node.width
|
|
84
|
-
const h = node.height
|
|
83
|
+
const w = node.measured?.width ?? node.width ?? 200;
|
|
84
|
+
const h = node.measured?.height ?? node.height ?? 50;
|
|
85
85
|
centerX += node.position.x + w / 2;
|
|
86
86
|
centerY += node.position.y + h / 2;
|
|
87
87
|
}
|
|
@@ -34,8 +34,8 @@ async function applyDagreLayout(nodes, edges, options) {
|
|
|
34
34
|
g.setDefaultEdgeLabel(() => ({}));
|
|
35
35
|
nodes.forEach(node => {
|
|
36
36
|
g.setNode(node.id, {
|
|
37
|
-
width: node.width
|
|
38
|
-
height: node.height
|
|
37
|
+
width: node.measured?.width ?? node.width ?? 150,
|
|
38
|
+
height: node.measured?.height ?? node.height ?? 50
|
|
39
39
|
});
|
|
40
40
|
});
|
|
41
41
|
edges.forEach(edge => {
|
|
@@ -48,8 +48,8 @@ async function applyDagreLayout(nodes, edges, options) {
|
|
|
48
48
|
return {
|
|
49
49
|
...node,
|
|
50
50
|
position: {
|
|
51
|
-
x: layoutNode.x - (node.width
|
|
52
|
-
y: layoutNode.y - (node.height
|
|
51
|
+
x: layoutNode.x - (node.measured?.width ?? node.width ?? 150) / 2,
|
|
52
|
+
y: layoutNode.y - (node.measured?.height ?? node.height ?? 50) / 2
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
55
|
});
|
|
@@ -88,8 +88,8 @@ async function applyElkLayout(nodes, edges, options) {
|
|
|
88
88
|
},
|
|
89
89
|
children: nodes.map(node => ({
|
|
90
90
|
id: node.id,
|
|
91
|
-
width: node.width
|
|
92
|
-
height: node.height
|
|
91
|
+
width: node.measured?.width ?? node.width ?? 150,
|
|
92
|
+
height: node.measured?.height ?? node.height ?? 50
|
|
93
93
|
})),
|
|
94
94
|
edges: edges.map((edge, index) => ({
|
|
95
95
|
id: edge.id || `edge-${index}`,
|
|
@@ -26,8 +26,8 @@ async function applyDagreLayout(nodes, edges, options) {
|
|
|
26
26
|
g.setDefaultEdgeLabel(() => ({}));
|
|
27
27
|
nodes.forEach((node) => {
|
|
28
28
|
g.setNode(node.id, {
|
|
29
|
-
width: node.width
|
|
30
|
-
height: node.height
|
|
29
|
+
width: node.measured?.width ?? node.width ?? 150,
|
|
30
|
+
height: node.measured?.height ?? node.height ?? 50
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
33
|
edges.forEach((edge) => {
|
|
@@ -40,8 +40,8 @@ async function applyDagreLayout(nodes, edges, options) {
|
|
|
40
40
|
return {
|
|
41
41
|
...node,
|
|
42
42
|
position: {
|
|
43
|
-
x: layoutNode.x - (node.width
|
|
44
|
-
y: layoutNode.y - (node.height
|
|
43
|
+
x: layoutNode.x - (node.measured?.width ?? node.width ?? 150) / 2,
|
|
44
|
+
y: layoutNode.y - (node.measured?.height ?? node.height ?? 50) / 2
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
47
|
});
|
|
@@ -81,8 +81,8 @@ async function applyElkLayout(nodes, edges, options) {
|
|
|
81
81
|
},
|
|
82
82
|
children: nodes.map((node) => ({
|
|
83
83
|
id: node.id,
|
|
84
|
-
width: node.width
|
|
85
|
-
height: node.height
|
|
84
|
+
width: node.measured?.width ?? node.width ?? 150,
|
|
85
|
+
height: node.measured?.height ?? node.height ?? 50
|
|
86
86
|
})),
|
|
87
87
|
edges: edges.map((edge, index) => ({
|
|
88
88
|
id: edge.id || `edge-${index}`,
|
|
@@ -24,8 +24,8 @@ function computeBoundingBox(nodes, paddingX, paddingY) {
|
|
|
24
24
|
maxX = -Infinity,
|
|
25
25
|
maxY = -Infinity;
|
|
26
26
|
nodes.forEach(node => {
|
|
27
|
-
const w = node.width
|
|
28
|
-
const h = node.height
|
|
27
|
+
const w = node.measured?.width ?? node.width ?? 150;
|
|
28
|
+
const h = node.measured?.height ?? node.height ?? 50;
|
|
29
29
|
minX = Math.min(minX, node.position.x);
|
|
30
30
|
minY = Math.min(minY, node.position.y);
|
|
31
31
|
maxX = Math.max(maxX, node.position.x + w);
|
|
@@ -165,7 +165,15 @@ function createNodeGroupPlugin(options = {}) {
|
|
|
165
165
|
}
|
|
166
166
|
});
|
|
167
167
|
if (hidden) {
|
|
168
|
+
const groupNode = flow.getNode(groupId);
|
|
169
|
+
const currentW = groupNode?.width ?? groupNode?.style?.width ?? 200;
|
|
170
|
+
const currentH = groupNode?.height ?? groupNode?.style?.height ?? 150;
|
|
168
171
|
flow.updateNode(groupId, {
|
|
172
|
+
data: {
|
|
173
|
+
...(groupNode?.data || {}),
|
|
174
|
+
_origWidth: currentW,
|
|
175
|
+
_origHeight: currentH
|
|
176
|
+
},
|
|
169
177
|
style: {
|
|
170
178
|
width: 160,
|
|
171
179
|
height: 50,
|
|
@@ -10,8 +10,8 @@ function computeBoundingBox(nodes, paddingX, paddingY) {
|
|
|
10
10
|
if (nodes.length === 0) return { x: 0, y: 0, width: 200, height: 150 };
|
|
11
11
|
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
12
12
|
nodes.forEach((node) => {
|
|
13
|
-
const w = node.width
|
|
14
|
-
const h = node.height
|
|
13
|
+
const w = node.measured?.width ?? node.width ?? 150;
|
|
14
|
+
const h = node.measured?.height ?? node.height ?? 50;
|
|
15
15
|
minX = Math.min(minX, node.position.x);
|
|
16
16
|
minY = Math.min(minY, node.position.y);
|
|
17
17
|
maxX = Math.max(maxX, node.position.x + w);
|
|
@@ -139,7 +139,15 @@ export function createNodeGroupPlugin(options = {}) {
|
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
141
|
if (hidden) {
|
|
142
|
+
const groupNode = flow.getNode(groupId);
|
|
143
|
+
const currentW = groupNode?.width ?? groupNode?.style?.width ?? 200;
|
|
144
|
+
const currentH = groupNode?.height ?? groupNode?.style?.height ?? 150;
|
|
142
145
|
flow.updateNode(groupId, {
|
|
146
|
+
data: {
|
|
147
|
+
...groupNode?.data || {},
|
|
148
|
+
_origWidth: currentW,
|
|
149
|
+
_origHeight: currentH
|
|
150
|
+
},
|
|
143
151
|
style: { width: 160, height: 50, minWidth: 160, minHeight: 50 },
|
|
144
152
|
width: 160,
|
|
145
153
|
height: 50
|