@yh-ui/flow 1.0.51 → 1.0.52
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 +47 -12
- 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/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 +2 -2
- package/dist/utils/edge.d.ts +4 -0
- package/dist/utils/edge.mjs +2 -2
- package/package.json +18 -4
package/dist/Flow.d.vue.ts
CHANGED
|
@@ -60,11 +60,11 @@ type __VLS_Props = {
|
|
|
60
60
|
/** Export file name prefix */
|
|
61
61
|
exportFileName?: string;
|
|
62
62
|
};
|
|
63
|
-
declare var __VLS_15: any,
|
|
63
|
+
declare var __VLS_15: any, __VLS_39: any;
|
|
64
64
|
type __VLS_Slots = {} & {
|
|
65
65
|
edge?: (props: typeof __VLS_15) => any;
|
|
66
66
|
} & {
|
|
67
|
-
node?: (props: typeof
|
|
67
|
+
node?: (props: typeof __VLS_39) => any;
|
|
68
68
|
};
|
|
69
69
|
declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {
|
|
70
70
|
nodes: import("vue").Ref<Node[]>;
|
|
@@ -135,6 +135,29 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {
|
|
|
135
135
|
exportJson?: () => string;
|
|
136
136
|
exportImage?: (options?: import("./types").ScreenshotOptions | HTMLElement) => Promise<import("./types").ScreenshotResult>;
|
|
137
137
|
applyLayout?: (options?: unknown) => void | Promise<void>;
|
|
138
|
+
groupSelectedNodes?: (label?: string) => string | null;
|
|
139
|
+
ungroupNodes?: (groupId: string) => void;
|
|
140
|
+
toggleGroupCollapse?: (groupId: string) => void;
|
|
141
|
+
isGroupCollapsed?: (groupId: string) => boolean;
|
|
142
|
+
getGroupChildren?: (groupId: string) => Node[];
|
|
143
|
+
getGroupRegistry?: () => Map<string, {
|
|
144
|
+
groupId: string;
|
|
145
|
+
childIds: string[];
|
|
146
|
+
collapsed: boolean;
|
|
147
|
+
originalPositions: Record<string, {
|
|
148
|
+
x: number;
|
|
149
|
+
y: number;
|
|
150
|
+
}>;
|
|
151
|
+
}>;
|
|
152
|
+
undo?: () => void;
|
|
153
|
+
redo?: () => void;
|
|
154
|
+
saveSnapshot?: (description?: string) => void;
|
|
155
|
+
canUndo?: import("vue").Ref<boolean>;
|
|
156
|
+
canRedo?: import("vue").Ref<boolean>;
|
|
157
|
+
historyLength?: import("vue").Ref<number>;
|
|
158
|
+
clearHistory?: () => void;
|
|
159
|
+
getHistory?: () => unknown[];
|
|
160
|
+
jumpToStep?: (index: number) => void;
|
|
138
161
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
139
162
|
"update:modelValue": (value: ViewportTransform) => any;
|
|
140
163
|
"update:nodes": (nodes: Node<import("./types").NodeData>[]) => any;
|
package/dist/Flow.vue
CHANGED
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
@node-drag-end="handleNodeDragEnd"
|
|
60
60
|
@connect-start="handleConnectStart"
|
|
61
61
|
@node-select-toggle="handleNodeSelectToggle"
|
|
62
|
+
@nodes-measured="handleNodesMeasured"
|
|
62
63
|
>
|
|
63
64
|
<template #node="nodeProps">
|
|
64
65
|
<slot name="node" v-bind="nodeProps" />
|
|
@@ -152,7 +153,8 @@ import {
|
|
|
152
153
|
getNodeChildren,
|
|
153
154
|
getNodeParent,
|
|
154
155
|
exportFlowData,
|
|
155
|
-
importFlowData
|
|
156
|
+
importFlowData,
|
|
157
|
+
getNodeAbsolutePosition
|
|
156
158
|
} from "./utils/custom-types";
|
|
157
159
|
import { provideFlowContext } from "./core/FlowContext";
|
|
158
160
|
import { createEventBus } from "./utils/event-bus";
|
|
@@ -267,6 +269,11 @@ const alignmentManager = useAlignment({
|
|
|
267
269
|
nodes: nodesRef,
|
|
268
270
|
snapThreshold: snapThreshold.value
|
|
269
271
|
});
|
|
272
|
+
const nodeMap = computed(() => {
|
|
273
|
+
const m = /* @__PURE__ */ new Map();
|
|
274
|
+
nodesRef.value.forEach((n) => m.set(n.id, n));
|
|
275
|
+
return m;
|
|
276
|
+
});
|
|
270
277
|
const visibleNodes = computed(() => {
|
|
271
278
|
if (!containerRef.value) return nodesRef.value;
|
|
272
279
|
const padding = 100;
|
|
@@ -277,9 +284,10 @@ const visibleNodes = computed(() => {
|
|
|
277
284
|
height: containerHeight.value / viewportRef.value.zoom + padding * 2
|
|
278
285
|
};
|
|
279
286
|
return nodesRef.value.filter((node) => {
|
|
280
|
-
const width = node.width
|
|
281
|
-
const height = node.height
|
|
282
|
-
|
|
287
|
+
const width = node.measured?.width ?? node.width ?? 200;
|
|
288
|
+
const height = node.measured?.height ?? node.height ?? 50;
|
|
289
|
+
const absPos = getNodeAbsolutePosition(node, nodeMap.value);
|
|
290
|
+
return !(absPos.x + width < visibleBounds.x || absPos.x > visibleBounds.x + visibleBounds.width || absPos.y + height < visibleBounds.y || absPos.y > visibleBounds.y + visibleBounds.height);
|
|
283
291
|
});
|
|
284
292
|
});
|
|
285
293
|
const contentStyle = computed(() => ({
|
|
@@ -466,9 +474,10 @@ const handleMouseUp = (event) => {
|
|
|
466
474
|
};
|
|
467
475
|
const findTargetNode = (canvasPos) => {
|
|
468
476
|
for (const node of nodesRef.value) {
|
|
469
|
-
const width = node.width
|
|
470
|
-
const height = node.height
|
|
471
|
-
|
|
477
|
+
const width = node.measured?.width ?? node.width ?? 200;
|
|
478
|
+
const height = node.measured?.height ?? node.height ?? 50;
|
|
479
|
+
const absPos = getNodeAbsolutePosition(node, nodeMap.value);
|
|
480
|
+
if (canvasPos.x >= absPos.x && canvasPos.x <= absPos.x + width && canvasPos.y >= absPos.y && canvasPos.y <= absPos.y + height) {
|
|
472
481
|
if (connectionStart.value && node.id !== connectionStart.value.nodeId) {
|
|
473
482
|
return node;
|
|
474
483
|
}
|
|
@@ -476,6 +485,9 @@ const findTargetNode = (canvasPos) => {
|
|
|
476
485
|
}
|
|
477
486
|
return null;
|
|
478
487
|
};
|
|
488
|
+
const handleNodesMeasured = () => {
|
|
489
|
+
emit("update:nodes", nodesRef.value);
|
|
490
|
+
};
|
|
479
491
|
const handleNodeClick = (event, node) => {
|
|
480
492
|
const multi = event.shiftKey || event.metaKey || event.ctrlKey;
|
|
481
493
|
if (!multi) edgesManager.clearSelection();
|
|
@@ -567,7 +579,8 @@ const handleEdgeUpdateStart = (event, edge, handleType) => {
|
|
|
567
579
|
const node = nodesRef.value.find((n) => n.id === anchorNodeId);
|
|
568
580
|
if (!node) return;
|
|
569
581
|
const position = handleType === "source" ? anchorHandleId ?? "left" : anchorHandleId ?? "right";
|
|
570
|
-
const
|
|
582
|
+
const absNode = { ...node, position: getNodeAbsolutePosition(node, nodeMap.value) };
|
|
583
|
+
const startPos = getHandlePosition(absNode, position, anchorHandleId);
|
|
571
584
|
isConnecting.value = true;
|
|
572
585
|
connectionStart.value = {
|
|
573
586
|
nodeId: anchorNodeId,
|
|
@@ -589,7 +602,8 @@ const handleConnectStart = (event, nodeId, handleId, handleType) => {
|
|
|
589
602
|
const rect = containerRef.value?.getBoundingClientRect();
|
|
590
603
|
if (!rect) return;
|
|
591
604
|
const position = handleId || (handleType === "source" ? "right" : "left");
|
|
592
|
-
const
|
|
605
|
+
const absNode = { ...node, position: getNodeAbsolutePosition(node, nodeMap.value) };
|
|
606
|
+
const startPos = getHandlePosition(absNode, position, handleId);
|
|
593
607
|
isConnecting.value = true;
|
|
594
608
|
connectionStart.value = {
|
|
595
609
|
nodeId,
|
|
@@ -654,12 +668,16 @@ const flowInstance = {
|
|
|
654
668
|
setViewport: (transform) => viewport.setViewport(transform.x, transform.y, transform.zoom),
|
|
655
669
|
fitView: (options) => viewport.fitView(
|
|
656
670
|
{ width: containerWidth.value, height: containerHeight.value },
|
|
657
|
-
nodesRef.value,
|
|
671
|
+
nodesRef.value.map((n) => ({ ...n, position: getNodeAbsolutePosition(n, nodeMap.value) })),
|
|
658
672
|
options
|
|
659
673
|
),
|
|
660
674
|
zoomIn: viewport.zoomIn,
|
|
661
675
|
zoomOut: viewport.zoomOut,
|
|
662
|
-
centerView: viewport.center
|
|
676
|
+
centerView: (options) => viewport.center(
|
|
677
|
+
{ width: containerWidth.value, height: containerHeight.value },
|
|
678
|
+
nodesRef.value.map((n) => ({ ...n, position: getNodeAbsolutePosition(n, nodeMap.value) })),
|
|
679
|
+
options
|
|
680
|
+
),
|
|
663
681
|
selectNode: nodesManager.selectNode,
|
|
664
682
|
selectEdge: edgesManager.selectEdge,
|
|
665
683
|
clearSelection: selectionManager.clearSelection,
|
|
@@ -699,7 +717,24 @@ const flowInstance = {
|
|
|
699
717
|
// Placeholders for plugin methods to be exposed via defineExpose
|
|
700
718
|
exportJson: void 0,
|
|
701
719
|
exportImage: void 0,
|
|
702
|
-
applyLayout: void 0
|
|
720
|
+
applyLayout: void 0,
|
|
721
|
+
// Node grouping placeholders
|
|
722
|
+
groupSelectedNodes: void 0,
|
|
723
|
+
ungroupNodes: void 0,
|
|
724
|
+
toggleGroupCollapse: void 0,
|
|
725
|
+
isGroupCollapsed: void 0,
|
|
726
|
+
getGroupChildren: void 0,
|
|
727
|
+
getGroupRegistry: void 0,
|
|
728
|
+
// History placeholders
|
|
729
|
+
undo: void 0,
|
|
730
|
+
redo: void 0,
|
|
731
|
+
saveSnapshot: void 0,
|
|
732
|
+
canUndo: void 0,
|
|
733
|
+
canRedo: void 0,
|
|
734
|
+
historyLength: void 0,
|
|
735
|
+
clearHistory: void 0,
|
|
736
|
+
getHistory: void 0,
|
|
737
|
+
jumpToStep: void 0
|
|
703
738
|
};
|
|
704
739
|
provideFlowContext(flowInstance);
|
|
705
740
|
pluginManager.init(flowInstance);
|
package/dist/Flow.vue.d.ts
CHANGED
|
@@ -60,11 +60,11 @@ type __VLS_Props = {
|
|
|
60
60
|
/** Export file name prefix */
|
|
61
61
|
exportFileName?: string;
|
|
62
62
|
};
|
|
63
|
-
declare var __VLS_15: any,
|
|
63
|
+
declare var __VLS_15: any, __VLS_39: any;
|
|
64
64
|
type __VLS_Slots = {} & {
|
|
65
65
|
edge?: (props: typeof __VLS_15) => any;
|
|
66
66
|
} & {
|
|
67
|
-
node?: (props: typeof
|
|
67
|
+
node?: (props: typeof __VLS_39) => any;
|
|
68
68
|
};
|
|
69
69
|
declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {
|
|
70
70
|
nodes: import("vue").Ref<Node[]>;
|
|
@@ -135,6 +135,29 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {
|
|
|
135
135
|
exportJson?: () => string;
|
|
136
136
|
exportImage?: (options?: import("./types").ScreenshotOptions | HTMLElement) => Promise<import("./types").ScreenshotResult>;
|
|
137
137
|
applyLayout?: (options?: unknown) => void | Promise<void>;
|
|
138
|
+
groupSelectedNodes?: (label?: string) => string | null;
|
|
139
|
+
ungroupNodes?: (groupId: string) => void;
|
|
140
|
+
toggleGroupCollapse?: (groupId: string) => void;
|
|
141
|
+
isGroupCollapsed?: (groupId: string) => boolean;
|
|
142
|
+
getGroupChildren?: (groupId: string) => Node[];
|
|
143
|
+
getGroupRegistry?: () => Map<string, {
|
|
144
|
+
groupId: string;
|
|
145
|
+
childIds: string[];
|
|
146
|
+
collapsed: boolean;
|
|
147
|
+
originalPositions: Record<string, {
|
|
148
|
+
x: number;
|
|
149
|
+
y: number;
|
|
150
|
+
}>;
|
|
151
|
+
}>;
|
|
152
|
+
undo?: () => void;
|
|
153
|
+
redo?: () => void;
|
|
154
|
+
saveSnapshot?: (description?: string) => void;
|
|
155
|
+
canUndo?: import("vue").Ref<boolean>;
|
|
156
|
+
canRedo?: import("vue").Ref<boolean>;
|
|
157
|
+
historyLength?: import("vue").Ref<number>;
|
|
158
|
+
clearHistory?: () => void;
|
|
159
|
+
getHistory?: () => unknown[];
|
|
160
|
+
jumpToStep?: (index: number) => void;
|
|
138
161
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
139
162
|
"update:modelValue": (value: ViewportTransform) => any;
|
|
140
163
|
"update:nodes": (nodes: Node<import("./types").NodeData>[]) => any;
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.useAlignment = useAlignment;
|
|
7
7
|
var _vue = require("vue");
|
|
8
|
+
var _customTypes = require("../utils/custom-types.cjs");
|
|
8
9
|
function useAlignment(options) {
|
|
9
10
|
const {
|
|
10
11
|
nodes,
|
|
@@ -22,19 +23,37 @@ function useAlignment(options) {
|
|
|
22
23
|
snappedY: false
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
|
-
const nodeWidth = node.width
|
|
26
|
-
const nodeHeight = node.height
|
|
26
|
+
const nodeWidth = node.measured?.width ?? node.width ?? 200;
|
|
27
|
+
const nodeHeight = node.measured?.height ?? node.height ?? 50;
|
|
27
28
|
const otherNodes = nodes.value.filter(n => n.id !== nodeId);
|
|
28
29
|
let snappedX = false;
|
|
29
30
|
let snappedY = false;
|
|
30
|
-
const
|
|
31
|
+
const nodeMap = new Map(nodes.value.map(n => [n.id, n]));
|
|
32
|
+
const absPosOffset = {
|
|
33
|
+
x: 0,
|
|
34
|
+
y: 0
|
|
35
|
+
};
|
|
36
|
+
if (node.parentId) {
|
|
37
|
+
const parent = nodeMap.get(node.parentId);
|
|
38
|
+
if (parent) {
|
|
39
|
+
const parentAbsPos = (0, _customTypes.getNodeAbsolutePosition)(parent, nodeMap);
|
|
40
|
+
absPosOffset.x = parentAbsPos.x;
|
|
41
|
+
absPosOffset.y = parentAbsPos.y;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const proposedAbsPos = {
|
|
45
|
+
x: position.x + absPosOffset.x,
|
|
46
|
+
y: position.y + absPosOffset.y
|
|
47
|
+
};
|
|
48
|
+
const dragYPositions = [proposedAbsPos.y, proposedAbsPos.y + nodeHeight / 2, proposedAbsPos.y + nodeHeight];
|
|
31
49
|
for (const otherNode of otherNodes) {
|
|
32
|
-
const otherHeight = otherNode.height
|
|
33
|
-
const
|
|
50
|
+
const otherHeight = otherNode.measured?.height ?? otherNode.height ?? 50;
|
|
51
|
+
const otherAbsPos = (0, _customTypes.getNodeAbsolutePosition)(otherNode, nodeMap);
|
|
52
|
+
const otherYPositions = [otherAbsPos.y, otherAbsPos.y + otherHeight / 2, otherAbsPos.y + otherHeight];
|
|
34
53
|
for (let i = 0; i < dragYPositions.length; i++) {
|
|
35
54
|
for (const otherY of otherYPositions) {
|
|
36
55
|
if (Math.abs(dragYPositions[i] - otherY) < snapThreshold) {
|
|
37
|
-
if (i === 0)
|
|
56
|
+
if (i === 0) proposedAbsPos.y = otherY;else if (i === 1) proposedAbsPos.y = otherY - nodeHeight / 2;else proposedAbsPos.y = otherY - nodeHeight;
|
|
38
57
|
snappedY = true;
|
|
39
58
|
break;
|
|
40
59
|
}
|
|
@@ -43,14 +62,15 @@ function useAlignment(options) {
|
|
|
43
62
|
}
|
|
44
63
|
if (snappedY) break;
|
|
45
64
|
}
|
|
46
|
-
const dragXPositions = [
|
|
65
|
+
const dragXPositions = [proposedAbsPos.x, proposedAbsPos.x + nodeWidth / 2, proposedAbsPos.x + nodeWidth];
|
|
47
66
|
for (const otherNode of otherNodes) {
|
|
48
|
-
const otherWidth = otherNode.width
|
|
49
|
-
const
|
|
67
|
+
const otherWidth = otherNode.measured?.width ?? otherNode.width ?? 200;
|
|
68
|
+
const otherAbsPos = (0, _customTypes.getNodeAbsolutePosition)(otherNode, nodeMap);
|
|
69
|
+
const otherXPositions = [otherAbsPos.x, otherAbsPos.x + otherWidth / 2, otherAbsPos.x + otherWidth];
|
|
50
70
|
for (let i = 0; i < dragXPositions.length; i++) {
|
|
51
71
|
for (const otherX of otherXPositions) {
|
|
52
72
|
if (Math.abs(dragXPositions[i] - otherX) < snapThreshold) {
|
|
53
|
-
if (i === 0)
|
|
73
|
+
if (i === 0) proposedAbsPos.x = otherX;else if (i === 1) proposedAbsPos.x = otherX - nodeWidth / 2;else proposedAbsPos.x = otherX - nodeWidth;
|
|
54
74
|
snappedX = true;
|
|
55
75
|
break;
|
|
56
76
|
}
|
|
@@ -59,8 +79,8 @@ function useAlignment(options) {
|
|
|
59
79
|
}
|
|
60
80
|
}
|
|
61
81
|
return {
|
|
62
|
-
x:
|
|
63
|
-
y:
|
|
82
|
+
x: proposedAbsPos.x - absPosOffset.x,
|
|
83
|
+
y: proposedAbsPos.y - absPosOffset.y,
|
|
64
84
|
snappedX,
|
|
65
85
|
snappedY
|
|
66
86
|
};
|
|
@@ -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);
|
|
@@ -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
|