@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.
@@ -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, __VLS_38: 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 __VLS_38) => any;
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 || 200;
281
- const height = node.height || 50;
282
- return !(node.position.x + width < visibleBounds.x || node.position.x > visibleBounds.x + visibleBounds.width || node.position.y + height < visibleBounds.y || node.position.y > visibleBounds.y + visibleBounds.height);
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 || 200;
470
- const height = node.height || 50;
471
- if (canvasPos.x >= node.position.x && canvasPos.x <= node.position.x + width && canvasPos.y >= node.position.y && canvasPos.y <= node.position.y + height) {
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 startPos = getHandlePosition(node, position, anchorHandleId);
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 startPos = getHandlePosition(node, position, handleId);
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);
@@ -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, __VLS_38: 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 __VLS_38) => any;
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 || 200;
26
- const nodeHeight = node.height || 50;
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 dragYPositions = [position.y, position.y + nodeHeight / 2, position.y + nodeHeight];
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 || 50;
33
- const otherYPositions = [otherNode.position.y, otherNode.position.y + otherHeight / 2, otherNode.position.y + otherHeight];
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) position.y = otherY;else if (i === 1) position.y = otherY - nodeHeight / 2;else position.y = otherY - nodeHeight;
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 = [position.x, position.x + nodeWidth / 2, position.x + nodeWidth];
65
+ const dragXPositions = [proposedAbsPos.x, proposedAbsPos.x + nodeWidth / 2, proposedAbsPos.x + nodeWidth];
47
66
  for (const otherNode of otherNodes) {
48
- const otherWidth = otherNode.width || 200;
49
- const otherXPositions = [otherNode.position.x, otherNode.position.x + otherWidth / 2, otherNode.position.x + otherWidth];
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) position.x = otherX;else if (i === 1) position.x = otherX - nodeWidth / 2;else position.x = otherX - otherWidth;
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: position.x,
63
- y: position.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 || 200;
12
- const nodeHeight = node.height || 50;
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 dragYPositions = [position.y, position.y + nodeHeight / 2, position.y + nodeHeight];
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 || 50;
37
+ const otherHeight = otherNode.measured?.height ?? otherNode.height ?? 50;
38
+ const otherAbsPos = getNodeAbsolutePosition(otherNode, nodeMap);
19
39
  const otherYPositions = [
20
- otherNode.position.y,
21
- otherNode.position.y + otherHeight / 2,
22
- otherNode.position.y + otherHeight
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) position.y = otherY;
28
- else if (i === 1) position.y = otherY - nodeHeight / 2;
29
- else position.y = otherY - nodeHeight;
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 = [position.x, position.x + nodeWidth / 2, position.x + nodeWidth];
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 || 200;
64
+ const otherWidth = otherNode.measured?.width ?? otherNode.width ?? 200;
65
+ const otherAbsPos = getNodeAbsolutePosition(otherNode, nodeMap);
41
66
  const otherXPositions = [
42
- otherNode.position.x,
43
- otherNode.position.x + otherWidth / 2,
44
- otherNode.position.x + otherWidth
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) position.x = otherX;
50
- else if (i === 1) position.x = otherX - nodeWidth / 2;
51
- else position.x = otherX - otherWidth;
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 { x: position.x, y: position.y, snappedX, snappedY };
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 || 200;
19
- const totalWidth = targetNodes.reduce((sum, n) => sum + (n.width || 200), 0);
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 || 200) + gap;
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 || 200) + gap;
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 || 50;
62
- const totalHeight = targetNodes.reduce((sum, n) => sum + (n.height || 50), 0);
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 || 50) + gap;
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 || 50) + gap;
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 || 200)));
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 || 200) / 2);
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 || 200);
117
+ newX = referenceX - (node.measured?.width ?? node.width ?? 200);
118
118
  } else {
119
- newX = referenceX - (node.width || 200) / 2;
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 || 50)));
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 || 50) / 2);
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 || 50);
151
+ newY = referenceY - (node.measured?.height ?? node.height ?? 50);
152
152
  } else {
153
- newY = referenceY - (node.height || 50) / 2;
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 || 200;
11
- const totalWidth = targetNodes.reduce((sum, n) => sum + (n.width || 200), 0);
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 || 200) + gap;
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 || 200) + gap;
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 || 50;
48
- const totalHeight = targetNodes.reduce((sum, n) => sum + (n.height || 50), 0);
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 || 50) + gap;
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 || 50) + gap;
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(...targetNodes.map((n) => n.position.x + (n.width || 200)));
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((n) => n.position.x + (n.width || 200) / 2);
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 || 200);
107
+ newX = referenceX - (node.measured?.width ?? node.width ?? 200);
98
108
  } else {
99
- newX = referenceX - (node.width || 200) / 2;
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(...targetNodes.map((n) => n.position.y + (n.height || 50)));
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((n) => n.position.y + (n.height || 50) / 2);
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 || 50);
142
+ newY = referenceY - (node.measured?.height ?? node.height ?? 50);
129
143
  } else {
130
- newY = referenceY - (node.height || 50) / 2;
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 || 200;
49
- const nodeHeight = node.height || 50;
50
- const isInside = node.position.x >= minX && node.position.y >= minY && node.position.x + nodeWidth <= maxX && node.position.y + nodeHeight <= maxY;
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