@xyflow/system 0.0.21 → 0.0.23

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.
Files changed (64) hide show
  1. package/dist/esm/constants.d.ts +0 -1
  2. package/dist/esm/constants.d.ts.map +1 -1
  3. package/dist/esm/index.js +307 -191
  4. package/dist/esm/index.mjs +307 -191
  5. package/dist/esm/types/general.d.ts +3 -3
  6. package/dist/esm/types/general.d.ts.map +1 -1
  7. package/dist/esm/types/index.d.ts +1 -0
  8. package/dist/esm/types/index.d.ts.map +1 -1
  9. package/dist/esm/types/nodes.d.ts +22 -16
  10. package/dist/esm/types/nodes.d.ts.map +1 -1
  11. package/dist/esm/utils/edges/general.d.ts +5 -6
  12. package/dist/esm/utils/edges/general.d.ts.map +1 -1
  13. package/dist/esm/utils/edges/positions.d.ts +3 -3
  14. package/dist/esm/utils/edges/positions.d.ts.map +1 -1
  15. package/dist/esm/utils/general.d.ts +3 -3
  16. package/dist/esm/utils/general.d.ts.map +1 -1
  17. package/dist/esm/utils/graph.d.ts +16 -5
  18. package/dist/esm/utils/graph.d.ts.map +1 -1
  19. package/dist/esm/utils/store.d.ts +9 -5
  20. package/dist/esm/utils/store.d.ts.map +1 -1
  21. package/dist/esm/xydrag/XYDrag.d.ts +2 -2
  22. package/dist/esm/xydrag/XYDrag.d.ts.map +1 -1
  23. package/dist/esm/xydrag/utils.d.ts +3 -3
  24. package/dist/esm/xydrag/utils.d.ts.map +1 -1
  25. package/dist/esm/xyhandle/XYHandle.d.ts +2 -2
  26. package/dist/esm/xyhandle/XYHandle.d.ts.map +1 -1
  27. package/dist/esm/xyhandle/utils.d.ts +4 -4
  28. package/dist/esm/xyhandle/utils.d.ts.map +1 -1
  29. package/dist/esm/xypanzoom/XYPanZoom.d.ts.map +1 -1
  30. package/dist/esm/xypanzoom/eventhandler.d.ts.map +1 -1
  31. package/dist/esm/xypanzoom/filter.d.ts.map +1 -1
  32. package/dist/umd/constants.d.ts +0 -1
  33. package/dist/umd/constants.d.ts.map +1 -1
  34. package/dist/umd/index.js +1 -1
  35. package/dist/umd/types/changes.d.ts +50 -0
  36. package/dist/umd/types/changes.d.ts.map +1 -0
  37. package/dist/umd/types/general.d.ts +3 -3
  38. package/dist/umd/types/general.d.ts.map +1 -1
  39. package/dist/umd/types/index.d.ts +1 -0
  40. package/dist/umd/types/index.d.ts.map +1 -1
  41. package/dist/umd/types/nodes.d.ts +22 -16
  42. package/dist/umd/types/nodes.d.ts.map +1 -1
  43. package/dist/umd/utils/edges/general.d.ts +5 -6
  44. package/dist/umd/utils/edges/general.d.ts.map +1 -1
  45. package/dist/umd/utils/edges/positions.d.ts +3 -3
  46. package/dist/umd/utils/edges/positions.d.ts.map +1 -1
  47. package/dist/umd/utils/general.d.ts +3 -3
  48. package/dist/umd/utils/general.d.ts.map +1 -1
  49. package/dist/umd/utils/graph.d.ts +16 -5
  50. package/dist/umd/utils/graph.d.ts.map +1 -1
  51. package/dist/umd/utils/store.d.ts +9 -5
  52. package/dist/umd/utils/store.d.ts.map +1 -1
  53. package/dist/umd/xydrag/XYDrag.d.ts +2 -2
  54. package/dist/umd/xydrag/XYDrag.d.ts.map +1 -1
  55. package/dist/umd/xydrag/utils.d.ts +3 -3
  56. package/dist/umd/xydrag/utils.d.ts.map +1 -1
  57. package/dist/umd/xyhandle/XYHandle.d.ts +2 -2
  58. package/dist/umd/xyhandle/XYHandle.d.ts.map +1 -1
  59. package/dist/umd/xyhandle/utils.d.ts +4 -4
  60. package/dist/umd/xyhandle/utils.d.ts.map +1 -1
  61. package/dist/umd/xypanzoom/XYPanZoom.d.ts.map +1 -1
  62. package/dist/umd/xypanzoom/eventhandler.d.ts.map +1 -1
  63. package/dist/umd/xypanzoom/filter.d.ts.map +1 -1
  64. package/package.json +2 -2
package/dist/esm/index.js CHANGED
@@ -17,7 +17,6 @@ const errorMessages = {
17
17
  error011: (edgeType) => `Edge type "${edgeType}" not found. Using fallback type "default".`,
18
18
  error012: (id) => `Node with id "${id}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,
19
19
  };
20
- const internalsSymbol = Symbol.for('internals');
21
20
  const infiniteExtent = [
22
21
  [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
23
22
  [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
@@ -120,6 +119,7 @@ const isEdgeBase = (element) => 'id' in element && 'source' in element && 'targe
120
119
  * @returns A boolean indicating whether the element is an Node
121
120
  */
122
121
  const isNodeBase = (element) => 'id' in element && 'position' in element && !('source' in element) && !('target' in element);
122
+ const isInternalNodeBase = (element) => 'id' in element && 'internals' in element && !('source' in element) && !('target' in element);
123
123
  /**
124
124
  * Pass in a node, and get connected nodes where edge.source === node.id
125
125
  * @public
@@ -182,10 +182,10 @@ const getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {
182
182
  };
183
183
  return {
184
184
  position,
185
- positionAbsolute: node.computed?.positionAbsolute
185
+ positionAbsolute: 'internals' in node
186
186
  ? {
187
- x: node.computed.positionAbsolute.x - offsetX,
188
- y: node.computed.positionAbsolute.y - offsetY,
187
+ x: node.internals.positionAbsolute.x - offsetX,
188
+ y: node.internals.positionAbsolute.y - offsetY,
189
189
  }
190
190
  : position,
191
191
  };
@@ -199,6 +199,7 @@ const getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {
199
199
  * @param params.useRelativePosition - Whether to use the relative or absolute node positions
200
200
  * @returns Bounding box enclosing all nodes
201
201
  */
202
+ // @todo how to handle this if users do not have absolute positions?
202
203
  const getNodesBounds = (nodes, params = { nodeOrigin: [0, 0], useRelativePosition: false }) => {
203
204
  if (nodes.length === 0) {
204
205
  return { x: 0, y: 0, width: 0, height: 0 };
@@ -212,7 +213,30 @@ const getNodesBounds = (nodes, params = { nodeOrigin: [0, 0], useRelativePositio
212
213
  }, { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity });
213
214
  return boxToRect(box);
214
215
  };
215
- const getNodesInside = (nodes, rect, [tx, ty, tScale] = [0, 0, 1], partially = false,
216
+ /**
217
+ * Determines a bounding box that contains all given nodes in an array
218
+ * @internal
219
+ */
220
+ const getInternalNodesBounds = (nodeLookup, params = {
221
+ nodeOrigin: [0, 0],
222
+ useRelativePosition: false,
223
+ }) => {
224
+ if (nodeLookup.size === 0) {
225
+ return { x: 0, y: 0, width: 0, height: 0 };
226
+ }
227
+ let box = { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity };
228
+ nodeLookup.forEach((node) => {
229
+ if (params.filter == undefined || params.filter(node)) {
230
+ const nodePos = getNodePositionWithOrigin(node, node.origin || params.nodeOrigin);
231
+ box = getBoundsOfBoxes(box, rectToBox({
232
+ ...nodePos[params.useRelativePosition ? 'position' : 'positionAbsolute'],
233
+ ...getNodeDimensions(node),
234
+ }));
235
+ }
236
+ });
237
+ return boxToRect(box);
238
+ };
239
+ const getNodesInside = (nodeLookup, rect, [tx, ty, tScale] = [0, 0, 1], partially = false,
216
240
  // set excludeNonSelectableNodes if you want to pay attention to the nodes "selectable" attribute
217
241
  excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
218
242
  const paneRect = {
@@ -220,12 +244,13 @@ excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
220
244
  width: rect.width / tScale,
221
245
  height: rect.height / tScale,
222
246
  };
223
- const visibleNodes = nodes.reduce((res, node) => {
224
- const { computed, selectable = true, hidden = false } = node;
225
- const width = computed?.width ?? node.width ?? node.initialWidth ?? null;
226
- const height = computed?.height ?? node.height ?? node.initialHeight ?? null;
247
+ const visibleNodes = [];
248
+ for (const [, node] of nodeLookup) {
249
+ const { measured, selectable = true, hidden = false } = node;
250
+ const width = measured.width ?? node.width ?? node.initialWidth ?? null;
251
+ const height = measured.height ?? node.height ?? node.initialHeight ?? null;
227
252
  if ((excludeNonSelectableNodes && !selectable) || hidden) {
228
- return res;
253
+ continue;
229
254
  }
230
255
  const overlappingArea = getOverlappingArea(paneRect, nodeToRect(node, nodeOrigin));
231
256
  const notInitialized = width === null || height === null;
@@ -233,10 +258,9 @@ excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
233
258
  const area = (width ?? 0) * (height ?? 0);
234
259
  const isVisible = notInitialized || partiallyVisible || overlappingArea >= area;
235
260
  if (isVisible || node.dragging) {
236
- res.push(node);
261
+ visibleNodes.push(node);
237
262
  }
238
- return res;
239
- }, []);
263
+ }
240
264
  return visibleNodes;
241
265
  };
242
266
  /**
@@ -252,13 +276,15 @@ const getConnectedEdges = (nodes, edges) => {
252
276
  });
253
277
  return edges.filter((edge) => nodeIds.has(edge.source) || nodeIds.has(edge.target));
254
278
  };
255
- function fitView({ nodes, width, height, panZoom, minZoom, maxZoom, nodeOrigin = [0, 0] }, options) {
256
- const filteredNodes = nodes.filter((n) => {
257
- const isVisible = n.computed?.width && n.computed?.height && (options?.includeHiddenNodes || !n.hidden);
258
- if (options?.nodes?.length) {
259
- return isVisible && options?.nodes.some((optionNode) => optionNode.id === n.id);
279
+ function fitView({ nodeLookup, width, height, panZoom, minZoom, maxZoom, nodeOrigin = [0, 0] }, options) {
280
+ const filteredNodes = [];
281
+ nodeLookup.forEach((n) => {
282
+ const isVisible = n.measured.width && n.measured.height && (options?.includeHiddenNodes || !n.hidden);
283
+ // TODO: this remove options.nodes.some with a Set
284
+ if (isVisible &&
285
+ (!options?.nodes || (options?.nodes.length && options?.nodes.some((optionNode) => optionNode.id === n.id)))) {
286
+ filteredNodes.push(n);
260
287
  }
261
- return isVisible;
262
288
  });
263
289
  if (filteredNodes.length > 0) {
264
290
  const bounds = getNodesBounds(filteredNodes, { nodeOrigin });
@@ -280,7 +306,7 @@ function clampNodeExtent(node, extent) {
280
306
  if (!extent || extent === 'parent') {
281
307
  return extent;
282
308
  }
283
- return [extent[0], [extent[1][0] - (node.computed?.width ?? 0), extent[1][1] - (node.computed?.height ?? 0)]];
309
+ return [extent[0], [extent[1][0] - (node.measured?.width ?? 0), extent[1][1] - (node.measured?.height ?? 0)]];
284
310
  }
285
311
  /**
286
312
  * This function calculates the next position of a node, taking into account the node's extent, parent node, and origin.
@@ -290,7 +316,7 @@ function clampNodeExtent(node, extent) {
290
316
  */
291
317
  function calculateNodePosition({ nodeId, nextPosition, nodeLookup, nodeOrigin = [0, 0], nodeExtent, onError, }) {
292
318
  const node = nodeLookup.get(nodeId);
293
- const parentNode = node.parentNode ? nodeLookup.get(node.parentNode) : undefined;
319
+ const parentNode = node.parentId ? nodeLookup.get(node.parentId) : undefined;
294
320
  const { x: parentX, y: parentY } = parentNode
295
321
  ? getNodePositionWithOrigin(parentNode, parentNode.origin || nodeOrigin).positionAbsolute
296
322
  : { x: 0, y: 0 };
@@ -300,10 +326,10 @@ function calculateNodePosition({ nodeId, nextPosition, nodeLookup, nodeOrigin =
300
326
  onError?.('005', errorMessages['error005']());
301
327
  }
302
328
  else {
303
- const nodeWidth = node.computed?.width;
304
- const nodeHeight = node.computed?.height;
305
- const parentWidth = parentNode?.computed?.width;
306
- const parentHeight = parentNode?.computed?.height;
329
+ const nodeWidth = node.measured.width;
330
+ const nodeHeight = node.measured.height;
331
+ const parentWidth = parentNode.measured.width;
332
+ const parentHeight = parentNode.measured.height;
307
333
  if (nodeWidth && nodeHeight && parentWidth && parentHeight) {
308
334
  const currNodeOrigin = node.origin || nodeOrigin;
309
335
  const extentX = parentX + nodeWidth * currNodeOrigin[0];
@@ -350,7 +376,7 @@ async function getElementsToRemove({ nodesToRemove = [], edgesToRemove = [], nod
350
376
  continue;
351
377
  }
352
378
  const isIncluded = nodeIds.includes(node.id);
353
- const parentHit = !isIncluded && node.parentNode && matchingNodes.find((n) => n.id === node.parentNode);
379
+ const parentHit = !isIncluded && node.parentId && matchingNodes.find((n) => n.id === node.parentId);
354
380
  if (isIncluded || parentHit) {
355
381
  matchingNodes.push(node);
356
382
  }
@@ -430,16 +456,16 @@ const nodeToRect = (node, nodeOrigin = [0, 0]) => {
430
456
  const { positionAbsolute } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
431
457
  return {
432
458
  ...positionAbsolute,
433
- width: node.computed?.width ?? node.width ?? 0,
434
- height: node.computed?.height ?? node.height ?? 0,
459
+ width: node.measured?.width ?? node.width ?? 0,
460
+ height: node.measured?.height ?? node.height ?? 0,
435
461
  };
436
462
  };
437
463
  const nodeToBox = (node, nodeOrigin = [0, 0]) => {
438
464
  const { positionAbsolute } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
439
465
  return {
440
466
  ...positionAbsolute,
441
- x2: positionAbsolute.x + (node.computed?.width ?? node.width ?? 0),
442
- y2: positionAbsolute.y + (node.computed?.height ?? node.height ?? 0),
467
+ x2: positionAbsolute.x + (node.measured?.width ?? node.width ?? 0),
468
+ y2: positionAbsolute.y + (node.measured?.height ?? node.height ?? 0),
443
469
  };
444
470
  };
445
471
  const getBoundsOfRects = (rect1, rect2) => boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2)));
@@ -519,13 +545,13 @@ function isCoordinateExtent(extent) {
519
545
  }
520
546
  function getNodeDimensions(node) {
521
547
  return {
522
- width: node.computed?.width ?? node.width ?? node.initialWidth ?? 0,
523
- height: node.computed?.height ?? node.height ?? node.initialHeight ?? 0,
548
+ width: node.measured?.width ?? node.width ?? node.initialWidth ?? 0,
549
+ height: node.measured?.height ?? node.height ?? node.initialHeight ?? 0,
524
550
  };
525
551
  }
526
552
  function nodeHasDimensions(node) {
527
- return ((node.computed?.width ?? node.width ?? node.initialWidth) !== undefined &&
528
- (node.computed?.height ?? node.height ?? node.initialHeight) !== undefined);
553
+ return ((node.measured?.width ?? node.width ?? node.initialWidth) !== undefined &&
554
+ (node.measured?.height ?? node.height ?? node.initialHeight) !== undefined);
529
555
  }
530
556
 
531
557
  function getPointerPosition(event, { snapGrid = [0, 0], snapToGrid = false, transform }) {
@@ -688,7 +714,7 @@ function getElevatedEdgeZIndex({ sourceNode, targetNode, selected = false, zInde
688
714
  return zIndex;
689
715
  }
690
716
  const edgeOrConnectedNodeSelected = selected || targetNode.selected || sourceNode.selected;
691
- const selectedZIndex = Math.max(sourceNode[internalsSymbol]?.z || 0, targetNode[internalsSymbol]?.z || 0, 1000);
717
+ const selectedZIndex = Math.max(sourceNode.internals.z || 0, targetNode.internals.z || 0, 1000);
692
718
  return zIndex + (edgeOrConnectedNodeSelected ? selectedZIndex : 0);
693
719
  }
694
720
  function isEdgeVisible({ sourceNode, targetNode, width, height, transform }) {
@@ -993,16 +1019,17 @@ function getSmoothStepPath({ sourceX, sourceY, sourcePosition = Position.Bottom,
993
1019
  }
994
1020
 
995
1021
  function isNodeInitialized(node) {
996
- return (!!(node?.[internalsSymbol]?.handleBounds || node?.handles?.length) &&
997
- !!(node?.computed?.width || node?.width || node?.initialWidth));
1022
+ return (node &&
1023
+ !!(node.internals.handleBounds || node.handles?.length) &&
1024
+ !!(node.measured.width || node.width || node.initialWidth));
998
1025
  }
999
1026
  function getEdgePosition(params) {
1000
1027
  const { sourceNode, targetNode } = params;
1001
1028
  if (!isNodeInitialized(sourceNode) || !isNodeInitialized(targetNode)) {
1002
1029
  return null;
1003
1030
  }
1004
- const sourceHandleBounds = sourceNode[internalsSymbol]?.handleBounds || toHandleBounds(sourceNode.handles);
1005
- const targetHandleBounds = targetNode[internalsSymbol]?.handleBounds || toHandleBounds(targetNode.handles);
1031
+ const sourceHandleBounds = sourceNode.internals.handleBounds || toHandleBounds(sourceNode.handles);
1032
+ const targetHandleBounds = targetNode.internals.handleBounds || toHandleBounds(targetNode.handles);
1006
1033
  const sourceHandle = getHandle(sourceHandleBounds?.source ?? [], params.sourceHandle);
1007
1034
  const targetHandle = getHandle(
1008
1035
  // when connection type is loose we can define all handles as sources and connect source -> source
@@ -1052,8 +1079,8 @@ function toHandleBounds(handles) {
1052
1079
  };
1053
1080
  }
1054
1081
  function getHandlePosition(position, node, handle = null) {
1055
- const x = (handle?.x ?? 0) + (node.computed?.positionAbsolute?.x ?? 0);
1056
- const y = (handle?.y ?? 0) + (node.computed?.positionAbsolute?.y ?? 0);
1082
+ const x = (handle?.x ?? 0) + node.internals.positionAbsolute.x;
1083
+ const y = (handle?.y ?? 0) + node.internals.positionAbsolute.y;
1057
1084
  const { width, height } = handle ?? getNodeDimensions(node);
1058
1085
  switch (position) {
1059
1086
  case Position.Top:
@@ -1144,111 +1171,177 @@ function getNodeToolbarTransform(nodeRect, viewport, position, offset, align) {
1144
1171
  return `translate(${pos[0]}px, ${pos[1]}px) translate(${shift[0]}%, ${shift[1]}%)`;
1145
1172
  }
1146
1173
 
1147
- function updateAbsolutePositions(nodes, nodeLookup, nodeOrigin = [0, 0], parentNodes) {
1148
- return nodes.map((node) => {
1149
- if (node.parentNode && !nodeLookup.has(node.parentNode)) {
1150
- throw new Error(`Parent node ${node.parentNode} not found`);
1151
- }
1152
- if (node.parentNode || parentNodes?.[node.id]) {
1153
- const parentNode = node.parentNode ? nodeLookup.get(node.parentNode) : null;
1154
- const { x, y, z } = calculateXYZPosition(node, nodes, nodeLookup, {
1174
+ function updateAbsolutePositions(nodeLookup, options = {
1175
+ nodeOrigin: [0, 0],
1176
+ elevateNodesOnSelect: true,
1177
+ defaults: {},
1178
+ }, parentNodeIds) {
1179
+ const selectedNodeZ = options?.elevateNodesOnSelect ? 1000 : 0;
1180
+ for (const [id, node] of nodeLookup) {
1181
+ const parentId = node.parentId;
1182
+ if (parentId && !nodeLookup.has(parentId)) {
1183
+ throw new Error(`Parent node ${parentId} not found`);
1184
+ }
1185
+ if (parentId || node.internals.isParent || parentNodeIds?.has(id)) {
1186
+ const parentNode = parentId ? nodeLookup.get(parentId) : null;
1187
+ const { x, y, z } = calculateXYZPosition(node, nodeLookup, {
1155
1188
  ...node.position,
1156
- z: node[internalsSymbol]?.z ?? 0,
1157
- }, parentNode?.origin || nodeOrigin);
1158
- const positionChanged = x !== node.computed?.positionAbsolute?.x || y !== node.computed?.positionAbsolute?.y;
1159
- node.computed.positionAbsolute = positionChanged
1160
- ? {
1161
- x,
1162
- y,
1163
- }
1164
- : node.computed?.positionAbsolute;
1165
- node[internalsSymbol].z = z;
1166
- if (parentNodes?.[node.id]) {
1167
- node[internalsSymbol].isParent = true;
1189
+ z: (isNumeric(node.zIndex) ? node.zIndex : 0) + (node.selected ? selectedNodeZ : 0),
1190
+ }, parentNode?.origin || options.nodeOrigin);
1191
+ const currPosition = node.internals.positionAbsolute;
1192
+ const positionChanged = x !== currPosition.x || y !== currPosition.y;
1193
+ node.internals.positionAbsolute = positionChanged ? { x, y } : currPosition;
1194
+ node.internals.z = z;
1195
+ if (parentNodeIds !== undefined) {
1196
+ node.internals.isParent = !!parentNodeIds?.has(id);
1168
1197
  }
1198
+ nodeLookup.set(id, node);
1169
1199
  }
1170
- return node;
1171
- });
1200
+ }
1172
1201
  }
1173
- function adoptUserProvidedNodes(nodes, nodeLookup, options = {
1202
+ function adoptUserNodes(nodes, nodeLookup, options = {
1174
1203
  nodeOrigin: [0, 0],
1175
1204
  elevateNodesOnSelect: true,
1176
1205
  defaults: {},
1206
+ checkEquality: true,
1177
1207
  }) {
1178
1208
  const tmpLookup = new Map(nodeLookup);
1179
1209
  nodeLookup.clear();
1180
- const parentNodes = {};
1181
1210
  const selectedNodeZ = options?.elevateNodesOnSelect ? 1000 : 0;
1182
- const nextNodes = nodes.map((n) => {
1183
- const currentStoreNode = tmpLookup.get(n.id);
1184
- if (n === currentStoreNode?.[internalsSymbol]?.userProvidedNode) {
1185
- nodeLookup.set(n.id, currentStoreNode);
1186
- return currentStoreNode;
1187
- }
1188
- const node = {
1189
- ...options.defaults,
1190
- ...n,
1191
- computed: {
1192
- positionAbsolute: n.position,
1193
- width: n.computed?.width,
1194
- height: n.computed?.height,
1195
- },
1196
- };
1197
- const z = (isNumeric(n.zIndex) ? n.zIndex : 0) + (n.selected ? selectedNodeZ : 0);
1198
- const currInternals = n?.[internalsSymbol] || currentStoreNode?.[internalsSymbol];
1199
- if (node.parentNode) {
1200
- parentNodes[node.parentNode] = true;
1201
- }
1202
- Object.defineProperty(node, internalsSymbol, {
1203
- enumerable: false,
1204
- value: {
1205
- handleBounds: currInternals?.handleBounds,
1206
- z,
1207
- userProvidedNode: n,
1208
- },
1209
- });
1210
- nodeLookup.set(node.id, node);
1211
- return node;
1211
+ const parentNodeIds = new Set();
1212
+ nodes.forEach((userNode) => {
1213
+ const currentStoreNode = tmpLookup.get(userNode.id);
1214
+ if (userNode.parentId) {
1215
+ parentNodeIds.add(userNode.parentId);
1216
+ }
1217
+ if (options.checkEquality && userNode === currentStoreNode?.internals.userNode) {
1218
+ nodeLookup.set(userNode.id, currentStoreNode);
1219
+ }
1220
+ else {
1221
+ nodeLookup.set(userNode.id, {
1222
+ ...options.defaults,
1223
+ ...userNode,
1224
+ measured: {
1225
+ width: userNode.measured?.width,
1226
+ height: userNode.measured?.height,
1227
+ },
1228
+ internals: {
1229
+ positionAbsolute: userNode.position,
1230
+ handleBounds: currentStoreNode?.internals.handleBounds,
1231
+ z: (isNumeric(userNode.zIndex) ? userNode.zIndex : 0) + (userNode.selected ? selectedNodeZ : 0),
1232
+ userNode,
1233
+ isParent: false,
1234
+ },
1235
+ });
1236
+ }
1212
1237
  });
1213
- const nodesWithPositions = updateAbsolutePositions(nextNodes, nodeLookup, options.nodeOrigin, parentNodes);
1214
- return nodesWithPositions;
1238
+ if (parentNodeIds.size > 0) {
1239
+ updateAbsolutePositions(nodeLookup, options, parentNodeIds);
1240
+ }
1215
1241
  }
1216
- function calculateXYZPosition(node, nodes, nodeLookup, result, nodeOrigin) {
1217
- if (!node.parentNode) {
1242
+ function calculateXYZPosition(node, nodeLookup, result, nodeOrigin = [0, 0]) {
1243
+ if (!node.parentId) {
1218
1244
  return result;
1219
1245
  }
1220
- const parentNode = nodeLookup.get(node.parentNode);
1246
+ const parentNode = nodeLookup.get(node.parentId);
1221
1247
  const { position: parentNodePosition } = getNodePositionWithOrigin(parentNode, parentNode?.origin || nodeOrigin);
1222
- return calculateXYZPosition(parentNode, nodes, nodeLookup, {
1248
+ return calculateXYZPosition(parentNode, nodeLookup, {
1223
1249
  x: (result.x ?? 0) + parentNodePosition.x,
1224
1250
  y: (result.y ?? 0) + parentNodePosition.y,
1225
- z: (parentNode[internalsSymbol]?.z ?? 0) > (result.z ?? 0) ? parentNode[internalsSymbol]?.z ?? 0 : result.z ?? 0,
1251
+ z: (parentNode.internals.z ?? 0) > (result.z ?? 0) ? parentNode.internals.z ?? 0 : result.z ?? 0,
1226
1252
  }, parentNode.origin || nodeOrigin);
1227
1253
  }
1228
- function updateNodeDimensions(updates, nodes, nodeLookup, domNode, nodeOrigin, onUpdate) {
1254
+ function handleParentExpand(nodes, nodeLookup) {
1255
+ const changes = [];
1256
+ const chilNodeRects = new Map();
1257
+ nodes.forEach((node) => {
1258
+ const parentId = node.parentId;
1259
+ if (node.expandParent && parentId) {
1260
+ const parentNode = nodeLookup.get(parentId);
1261
+ if (parentNode) {
1262
+ const parentRect = chilNodeRects.get(parentId) || nodeToRect(parentNode, node.origin);
1263
+ const expandedRect = getBoundsOfRects(parentRect, nodeToRect(node, node.origin));
1264
+ chilNodeRects.set(parentId, expandedRect);
1265
+ }
1266
+ }
1267
+ });
1268
+ if (chilNodeRects.size > 0) {
1269
+ chilNodeRects.forEach((rect, id) => {
1270
+ const origParent = nodeLookup.get(id);
1271
+ const { position } = getNodePositionWithOrigin(origParent, origParent.origin);
1272
+ const dimensions = getNodeDimensions(origParent);
1273
+ if (rect.x < position.x || rect.y < position.y) {
1274
+ const xChange = Math.round(Math.abs(position.x - rect.x));
1275
+ const yChange = Math.round(Math.abs(position.y - rect.y));
1276
+ changes.push({
1277
+ id,
1278
+ type: 'position',
1279
+ position: {
1280
+ x: position.x - xChange,
1281
+ y: position.y - yChange,
1282
+ },
1283
+ });
1284
+ changes.push({
1285
+ id,
1286
+ type: 'dimensions',
1287
+ resizing: true,
1288
+ dimensions: {
1289
+ width: dimensions.width + xChange,
1290
+ height: dimensions.height + yChange,
1291
+ },
1292
+ });
1293
+ // @todo we need to reset child node positions if < 0
1294
+ }
1295
+ else if (dimensions.width < rect.width || dimensions.height < rect.height) {
1296
+ changes.push({
1297
+ id,
1298
+ type: 'dimensions',
1299
+ resizing: true,
1300
+ dimensions: {
1301
+ width: Math.max(dimensions.width, rect.width),
1302
+ height: Math.max(dimensions.height, rect.height),
1303
+ },
1304
+ });
1305
+ }
1306
+ });
1307
+ }
1308
+ return changes;
1309
+ }
1310
+ function updateNodeInternals(updates, nodeLookup, domNode, nodeOrigin) {
1229
1311
  const viewportNode = domNode?.querySelector('.xyflow__viewport');
1312
+ let updatedInternals = false;
1230
1313
  if (!viewportNode) {
1231
- return null;
1314
+ return { changes: [], updatedInternals };
1232
1315
  }
1316
+ const changes = [];
1233
1317
  const style = window.getComputedStyle(viewportNode);
1234
1318
  const { m22: zoom } = new window.DOMMatrixReadOnly(style.transform);
1235
- const nextNodes = nodes.map((node) => {
1236
- const update = updates.get(node.id);
1237
- if (update) {
1319
+ // in this array we collect nodes, that might trigger changes (like expanding parent)
1320
+ const triggerChangeNodes = [];
1321
+ updates.forEach((update) => {
1322
+ const node = nodeLookup.get(update.id);
1323
+ if (node?.hidden) {
1324
+ nodeLookup.set(node.id, {
1325
+ ...node,
1326
+ internals: {
1327
+ ...node.internals,
1328
+ handleBounds: undefined,
1329
+ },
1330
+ });
1331
+ updatedInternals = true;
1332
+ }
1333
+ else if (node) {
1238
1334
  const dimensions = getDimensions(update.nodeElement);
1335
+ const dimensionChanged = node.measured.width !== dimensions.width || node.measured.height !== dimensions.height;
1239
1336
  const doUpdate = !!(dimensions.width &&
1240
1337
  dimensions.height &&
1241
- (node.computed?.width !== dimensions.width || node.computed?.height !== dimensions.height || update.forceUpdate));
1338
+ (dimensionChanged || !node.internals.handleBounds || update.force));
1242
1339
  if (doUpdate) {
1243
- onUpdate?.(node.id, dimensions);
1244
1340
  const newNode = {
1245
1341
  ...node,
1246
- computed: {
1247
- ...node.computed,
1248
- ...dimensions,
1249
- },
1250
- [internalsSymbol]: {
1251
- ...node[internalsSymbol],
1342
+ measured: dimensions,
1343
+ internals: {
1344
+ ...node.internals,
1252
1345
  handleBounds: {
1253
1346
  source: getHandleBounds('.source', update.nodeElement, zoom, node.origin || nodeOrigin),
1254
1347
  target: getHandleBounds('.target', update.nodeElement, zoom, node.origin || nodeOrigin),
@@ -1256,12 +1349,25 @@ function updateNodeDimensions(updates, nodes, nodeLookup, domNode, nodeOrigin, o
1256
1349
  },
1257
1350
  };
1258
1351
  nodeLookup.set(node.id, newNode);
1259
- return newNode;
1352
+ updatedInternals = true;
1353
+ if (dimensionChanged) {
1354
+ changes.push({
1355
+ id: newNode.id,
1356
+ type: 'dimensions',
1357
+ dimensions,
1358
+ });
1359
+ if (newNode.expandParent) {
1360
+ triggerChangeNodes.push(newNode);
1361
+ }
1362
+ }
1260
1363
  }
1261
1364
  }
1262
- return node;
1263
1365
  });
1264
- return nextNodes;
1366
+ if (triggerChangeNodes.length > 0) {
1367
+ const parentExpandChanges = handleParentExpand(triggerChangeNodes, nodeLookup);
1368
+ changes.push(...parentExpandChanges);
1369
+ }
1370
+ return { changes, updatedInternals };
1265
1371
  }
1266
1372
  function panBy({ delta, panZoom, transform, translateExtent, width, height, }) {
1267
1373
  if (!panZoom || (!delta.x && !delta.y)) {
@@ -1315,18 +1421,18 @@ function shallowNodeData(a, b) {
1315
1421
  function wrapSelectionDragFunc(selectionFunc) {
1316
1422
  return (event, _, nodes) => selectionFunc?.(event, nodes);
1317
1423
  }
1318
- function isParentSelected(node, nodes) {
1319
- if (!node.parentNode) {
1424
+ function isParentSelected(node, nodeLookup) {
1425
+ if (!node.parentId) {
1320
1426
  return false;
1321
1427
  }
1322
- const parentNode = nodes.find((node) => node.id === node.parentNode);
1428
+ const parentNode = nodeLookup.get(node.parentId);
1323
1429
  if (!parentNode) {
1324
1430
  return false;
1325
1431
  }
1326
1432
  if (parentNode.selected) {
1327
1433
  return true;
1328
1434
  }
1329
- return isParentSelected(parentNode, nodes);
1435
+ return isParentSelected(parentNode, nodeLookup);
1330
1436
  }
1331
1437
  function hasSelector(target, selector, domNode) {
1332
1438
  let current = target;
@@ -1340,32 +1446,35 @@ function hasSelector(target, selector, domNode) {
1340
1446
  return false;
1341
1447
  }
1342
1448
  // looks for all selected nodes and created a NodeDragItem for each of them
1343
- function getDragItems(nodes, nodesDraggable, mousePos, nodeId) {
1344
- return nodes
1345
- .filter((n) => (n.selected || n.id === nodeId) &&
1346
- (!n.parentNode || !isParentSelected(n, nodes)) &&
1347
- (n.draggable || (nodesDraggable && typeof n.draggable === 'undefined')))
1348
- .map((n) => ({
1349
- id: n.id,
1350
- position: n.position || { x: 0, y: 0 },
1351
- distance: {
1352
- x: mousePos.x - (n.computed?.positionAbsolute?.x ?? 0),
1353
- y: mousePos.y - (n.computed?.positionAbsolute?.y ?? 0),
1354
- },
1355
- delta: {
1356
- x: 0,
1357
- y: 0,
1358
- },
1359
- extent: n.extent,
1360
- parentNode: n.parentNode,
1361
- origin: n.origin,
1362
- expandParent: n.expandParent,
1363
- computed: {
1364
- positionAbsolute: n.computed?.positionAbsolute || { x: 0, y: 0 },
1365
- width: n.computed?.width || 0,
1366
- height: n.computed?.height || 0,
1367
- },
1368
- }));
1449
+ function getDragItems(nodeLookup, nodesDraggable, mousePos, nodeId) {
1450
+ const dragItems = [];
1451
+ for (const [id, node] of nodeLookup) {
1452
+ if ((node.selected || node.id === nodeId) &&
1453
+ (!node.parentId || !isParentSelected(node, nodeLookup)) &&
1454
+ (node.draggable || (nodesDraggable && typeof node.draggable === 'undefined'))) {
1455
+ const internalNode = nodeLookup.get(id);
1456
+ dragItems.push({
1457
+ id: internalNode.id,
1458
+ position: internalNode.position || { x: 0, y: 0 },
1459
+ distance: {
1460
+ x: mousePos.x - internalNode.internals.positionAbsolute.x,
1461
+ y: mousePos.y - internalNode.internals.positionAbsolute.y,
1462
+ },
1463
+ extent: internalNode.extent,
1464
+ parentId: internalNode.parentId,
1465
+ origin: internalNode.origin,
1466
+ expandParent: internalNode.expandParent,
1467
+ internals: {
1468
+ positionAbsolute: internalNode.internals.positionAbsolute || { x: 0, y: 0 },
1469
+ },
1470
+ measured: {
1471
+ width: internalNode.measured.width || 0,
1472
+ height: internalNode.measured.height || 0,
1473
+ },
1474
+ });
1475
+ }
1476
+ }
1477
+ return dragItems;
1369
1478
  }
1370
1479
  // returns two params:
1371
1480
  // 1. the dragged node (or the first of the list, if we are dragging a node selection)
@@ -1376,9 +1485,8 @@ function getEventHandlerParams({ nodeId, dragItems, nodeLookup, }) {
1376
1485
  return {
1377
1486
  ...node,
1378
1487
  position: n.position,
1379
- computed: {
1380
- ...n.computed,
1381
- positionAbsolute: n.computed.positionAbsolute,
1488
+ measured: {
1489
+ ...n.measured,
1382
1490
  },
1383
1491
  };
1384
1492
  });
@@ -1414,17 +1522,20 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
1414
1522
  }
1415
1523
  // if there is selection with multiple nodes and a node extent is set, we need to adjust the node extent for each node
1416
1524
  // based on its position so that the node stays at it's position relative to the selection.
1417
- const adjustedNodeExtent = [
1525
+ let adjustedNodeExtent = [
1418
1526
  [nodeExtent[0][0], nodeExtent[0][1]],
1419
1527
  [nodeExtent[1][0], nodeExtent[1][1]],
1420
1528
  ];
1421
1529
  if (dragItems.length > 1 && nodeExtent && !n.extent) {
1422
- adjustedNodeExtent[0][0] = n.computed.positionAbsolute.x - nodesBox.x + nodeExtent[0][0];
1423
- adjustedNodeExtent[1][0] =
1424
- n.computed.positionAbsolute.x + (n.computed?.width ?? 0) - nodesBox.x2 + nodeExtent[1][0];
1425
- adjustedNodeExtent[0][1] = n.computed.positionAbsolute.y - nodesBox.y + nodeExtent[0][1];
1426
- adjustedNodeExtent[1][1] =
1427
- n.computed.positionAbsolute.y + (n.computed?.height ?? 0) - nodesBox.y2 + nodeExtent[1][1];
1530
+ const { positionAbsolute } = n.internals;
1531
+ const x1 = positionAbsolute.x - nodesBox.x + nodeExtent[0][0];
1532
+ const x2 = positionAbsolute.x + (n.measured?.width ?? 0) - nodesBox.x2 + nodeExtent[1][0];
1533
+ const y1 = positionAbsolute.y - nodesBox.y + nodeExtent[0][1];
1534
+ const y2 = positionAbsolute.y + (n.measured?.height ?? 0) - nodesBox.y2 + nodeExtent[1][1];
1535
+ adjustedNodeExtent = [
1536
+ [x1, y1],
1537
+ [x2, y2],
1538
+ ];
1428
1539
  }
1429
1540
  const { position, positionAbsolute } = calculateNodePosition({
1430
1541
  nodeId: n.id,
@@ -1437,7 +1548,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
1437
1548
  // we want to make sure that we only fire a change event when there is a change
1438
1549
  hasChange = hasChange || n.position.x !== position.x || n.position.y !== position.y;
1439
1550
  n.position = position;
1440
- n.computed.positionAbsolute = positionAbsolute;
1551
+ n.internals.positionAbsolute = positionAbsolute;
1441
1552
  return n;
1442
1553
  });
1443
1554
  if (!hasChange) {
@@ -1474,7 +1585,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
1474
1585
  autoPanId = requestAnimationFrame(autoPan);
1475
1586
  }
1476
1587
  function startDrag(event) {
1477
- const { nodes, nodeLookup, multiSelectionActive, nodesDraggable, transform, snapGrid, snapToGrid, selectNodesOnDrag, onNodeDragStart, onSelectionDragStart, unselectNodesAndEdges, } = getStoreItems();
1588
+ const { nodeLookup, multiSelectionActive, nodesDraggable, transform, snapGrid, snapToGrid, selectNodesOnDrag, onNodeDragStart, onSelectionDragStart, unselectNodesAndEdges, } = getStoreItems();
1478
1589
  dragStarted = true;
1479
1590
  if ((!selectNodesOnDrag || !isSelectable) && !multiSelectionActive && nodeId) {
1480
1591
  if (!nodeLookup.get(nodeId)?.selected) {
@@ -1487,7 +1598,7 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
1487
1598
  }
1488
1599
  const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
1489
1600
  lastPos = pointerPos;
1490
- dragItems = getDragItems(nodes, nodesDraggable, pointerPos, nodeId);
1601
+ dragItems = getDragItems(nodeLookup, nodesDraggable, pointerPos, nodeId);
1491
1602
  if (dragItems.length > 0 && (onDragStart || onNodeDragStart || (!nodeId && onSelectionDragStart))) {
1492
1603
  const [currentNode, currentNodes] = getEventHandlerParams({
1493
1604
  nodeId,
@@ -1587,8 +1698,8 @@ function getHandles(node, handleBounds, type, currentHandle) {
1587
1698
  id: h.id || null,
1588
1699
  type,
1589
1700
  nodeId: node.id,
1590
- x: (node.computed?.positionAbsolute?.x ?? 0) + h.x + h.width / 2,
1591
- y: (node.computed?.positionAbsolute?.y ?? 0) + h.y + h.height / 2,
1701
+ x: node.internals.positionAbsolute.x + h.x + h.width / 2,
1702
+ y: node.internals.positionAbsolute.y + h.y + h.height / 2,
1592
1703
  });
1593
1704
  }
1594
1705
  return res;
@@ -1618,20 +1729,17 @@ function getClosestHandle(pos, connectionRadius, handles) {
1618
1729
  : // if multiple handles are layouted on top of each other we take the one with type = target because it's more likely that the user wants to connect to this one
1619
1730
  closestHandles.find((handle) => handle.type === 'target') || closestHandles[0];
1620
1731
  }
1621
- function getHandleLookup({ nodes, nodeId, handleId, handleType }) {
1622
- return nodes.reduce((res, node) => {
1623
- if (node[internalsSymbol]) {
1624
- const { handleBounds } = node[internalsSymbol];
1625
- let sourceHandles = [];
1626
- let targetHandles = [];
1627
- if (handleBounds) {
1628
- sourceHandles = getHandles(node, handleBounds, 'source', `${nodeId}-${handleId}-${handleType}`);
1629
- targetHandles = getHandles(node, handleBounds, 'target', `${nodeId}-${handleId}-${handleType}`);
1630
- }
1631
- res.push(...sourceHandles, ...targetHandles);
1732
+ function getHandleLookup({ nodeLookup, nodeId, handleId, handleType, }) {
1733
+ const connectionHandles = [];
1734
+ for (const [, node] of nodeLookup) {
1735
+ if (node.internals.handleBounds) {
1736
+ const id = `${nodeId}-${handleId}-${handleType}`;
1737
+ const sourceHandles = getHandles(node, node.internals.handleBounds, 'source', id);
1738
+ const targetHandles = getHandles(node, node.internals.handleBounds, 'target', id);
1739
+ connectionHandles.push(...sourceHandles, ...targetHandles);
1632
1740
  }
1633
- return res;
1634
- }, []);
1741
+ }
1742
+ return connectionHandles;
1635
1743
  }
1636
1744
  function getHandleType(edgeUpdaterType, handleDomNode) {
1637
1745
  if (edgeUpdaterType) {
@@ -1658,7 +1766,7 @@ function getConnectionStatus(isInsideConnectionRadius, isHandleValid) {
1658
1766
 
1659
1767
  const alwaysValid = () => true;
1660
1768
  let connectionStartHandle = null;
1661
- function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodes, lib, autoPanOnConnect, flowId, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onEdgeUpdateEnd, updateConnection, getTransform, getConnectionStartHandle, }) {
1769
+ function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodeLookup, lib, autoPanOnConnect, flowId, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onEdgeUpdateEnd, updateConnection, getTransform, getConnectionStartHandle, }) {
1662
1770
  // when xyflow is used inside a shadow root we can't use document
1663
1771
  const doc = getHostForElement(event.target);
1664
1772
  let autoPanId = 0;
@@ -1676,7 +1784,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
1676
1784
  let isValid = false;
1677
1785
  let handleDomNode = null;
1678
1786
  const handleLookup = getHandleLookup({
1679
- nodes,
1787
+ nodeLookup,
1680
1788
  nodeId,
1681
1789
  handleId,
1682
1790
  handleType,
@@ -1940,7 +2048,9 @@ function createPanOnScrollHandler({ zoomPanValues, noWheelClassName, d3Selection
1940
2048
  }
1941
2049
  function createZoomOnScrollHandler({ noWheelClassName, preventScrolling, d3ZoomHandler }) {
1942
2050
  return function (event, d) {
1943
- if (!preventScrolling || isWrappedWithClass(event, noWheelClassName)) {
2051
+ // we still want to enable pinch zooming even if preventScrolling is set to false
2052
+ const preventZoom = !preventScrolling && event.type === 'wheel' && !event.ctrlKey;
2053
+ if (preventZoom || isWrappedWithClass(event, noWheelClassName)) {
1944
2054
  return null;
1945
2055
  }
1946
2056
  event.preventDefault();
@@ -2021,10 +2131,6 @@ function createFilter({ zoomActivationKeyPressed, zoomOnScroll, zoomOnPinch, pan
2021
2131
  if (userSelectionActive) {
2022
2132
  return false;
2023
2133
  }
2024
- // if zoom on double click is disabled, we prevent the double click event
2025
- if (!zoomOnDoubleClick && event.type === 'dblclick') {
2026
- return false;
2027
- }
2028
2134
  // if the target element is inside an element with the nowheel class, we prevent zooming
2029
2135
  if (isWrappedWithClass(event, noWheelClassName) && event.type === 'wheel') {
2030
2136
  return false;
@@ -2080,6 +2186,7 @@ function XYPanZoom({ domNode, minZoom, maxZoom, translateExtent, viewport, onPan
2080
2186
  [bbox.width, bbox.height],
2081
2187
  ], translateExtent);
2082
2188
  const d3ZoomHandler = d3Selection.on('wheel.zoom');
2189
+ const d3DblClickZoomHandler = d3Selection.on('dblclick.zoom');
2083
2190
  d3ZoomInstance.wheelDelta(wheelDelta);
2084
2191
  function setTransform(transform, options) {
2085
2192
  if (d3Selection) {
@@ -2152,6 +2259,15 @@ function XYPanZoom({ domNode, minZoom, maxZoom, translateExtent, viewport, onPan
2152
2259
  lib,
2153
2260
  });
2154
2261
  d3ZoomInstance.filter(filter);
2262
+ // We cannot add zoomOnDoubleClick to the filter above because
2263
+ // double tapping on touch screens circumvents the filter and
2264
+ // dblclick.zoom is fired on the selection directly
2265
+ if (zoomOnDoubleClick) {
2266
+ d3Selection.on('dblclick.zoom', d3DblClickZoomHandler);
2267
+ }
2268
+ else {
2269
+ d3Selection.on('dblclick.zoom', null);
2270
+ }
2155
2271
  }
2156
2272
  function destroy() {
2157
2273
  d3ZoomInstance.on('zoom', null);
@@ -2462,14 +2578,14 @@ const initChange = {
2462
2578
  function nodeToParentExtent(node) {
2463
2579
  return [
2464
2580
  [0, 0],
2465
- [node.computed.width, node.computed.height],
2581
+ [node.measured.width, node.measured.height],
2466
2582
  ];
2467
2583
  }
2468
2584
  function nodeToChildExtent(child, parent, nodeOrigin) {
2469
2585
  const x = parent.position.x + child.position.x;
2470
2586
  const y = parent.position.y + child.position.y;
2471
- const width = child.computed.width ?? 0;
2472
- const height = child.computed.height ?? 0;
2587
+ const width = child.measured.width ?? 0;
2588
+ const height = child.measured.height ?? 0;
2473
2589
  const originOffsetX = nodeOrigin[0] * width;
2474
2590
  const originOffsetY = nodeOrigin[1] * height;
2475
2591
  return [
@@ -2495,8 +2611,8 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
2495
2611
  if (node) {
2496
2612
  const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
2497
2613
  prevValues = {
2498
- width: node.computed?.width ?? 0,
2499
- height: node.computed?.height ?? 0,
2614
+ width: node.measured?.width ?? 0,
2615
+ height: node.measured?.height ?? 0,
2500
2616
  x: node.position.x ?? 0,
2501
2617
  y: node.position.y ?? 0,
2502
2618
  };
@@ -2508,7 +2624,7 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
2508
2624
  };
2509
2625
  parentNode = undefined;
2510
2626
  if (node.extent === 'parent' || node.expandParent) {
2511
- parentNode = nodeLookup.get(node.parentNode);
2627
+ parentNode = nodeLookup.get(node.parentId);
2512
2628
  if (parentNode && node.extent === 'parent') {
2513
2629
  parentExtent = nodeToParentExtent(parentNode);
2514
2630
  }
@@ -2518,7 +2634,7 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
2518
2634
  childNodes = [];
2519
2635
  childExtent = undefined;
2520
2636
  for (const [childId, child] of nodeLookup) {
2521
- if (child.parentNode === nodeId) {
2637
+ if (child.parentId === nodeId) {
2522
2638
  childNodes.push({
2523
2639
  id: childId,
2524
2640
  position: { ...child.position },
@@ -2626,4 +2742,4 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange }) {
2626
2742
  };
2627
2743
  }
2628
2744
 
2629
- export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, ResizeControlVariant, SelectionMode, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, XY_RESIZER_HANDLE_POSITIONS, XY_RESIZER_LINE_POSITIONS, addEdge, adoptUserProvidedNodes, areConnectionMapsEqual, boxToRect, calcAutoPan, calculateNodePosition, clamp, clampPosition, createMarkerIds, devWarn, elementSelectionKeys, errorMessages, fitView, getBezierEdgeCenter, getBezierPath, getBoundsOfBoxes, getBoundsOfRects, getConnectedEdges, getDimensions, getEdgeCenter, getEdgePosition, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHandleBounds, getHostForElement, getIncomers, getMarkerId, getNodeDimensions, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesInside, getOutgoers, getOverlappingArea, getPointerPosition, getPositionWithOrigin, getSmoothStepPath, getStraightPath, getViewportForBounds, handleConnectionChange, infiniteExtent, internalsSymbol, isCoordinateExtent, isEdgeBase, isEdgeVisible, isInputDOMNode, isMacOs, isMouseEvent, isNodeBase, isNumeric, isRectObject, nodeHasDimensions, nodeToBox, nodeToRect, panBy, pointToRendererPoint, rectToBox, rendererPointToPoint, shallowNodeData, snapPosition, updateAbsolutePositions, updateConnectionLookup, updateEdge, updateNodeDimensions };
2745
+ export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, ResizeControlVariant, SelectionMode, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, XY_RESIZER_HANDLE_POSITIONS, XY_RESIZER_LINE_POSITIONS, addEdge, adoptUserNodes, areConnectionMapsEqual, boxToRect, calcAutoPan, calculateNodePosition, clamp, clampPosition, createMarkerIds, devWarn, elementSelectionKeys, errorMessages, fitView, getBezierEdgeCenter, getBezierPath, getBoundsOfBoxes, getBoundsOfRects, getConnectedEdges, getDimensions, getEdgeCenter, getEdgePosition, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHandleBounds, getHostForElement, getIncomers, getInternalNodesBounds, getMarkerId, getNodeDimensions, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesInside, getOutgoers, getOverlappingArea, getPointerPosition, getPositionWithOrigin, getSmoothStepPath, getStraightPath, getViewportForBounds, handleConnectionChange, handleParentExpand, infiniteExtent, isCoordinateExtent, isEdgeBase, isEdgeVisible, isInputDOMNode, isInternalNodeBase, isMacOs, isMouseEvent, isNodeBase, isNumeric, isRectObject, nodeHasDimensions, nodeToBox, nodeToRect, panBy, pointToRendererPoint, rectToBox, rendererPointToPoint, shallowNodeData, snapPosition, updateAbsolutePositions, updateConnectionLookup, updateEdge, updateNodeInternals };