@xyflow/system 0.0.10 → 0.0.12

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 (55) hide show
  1. package/dist/esm/index.mjs +221 -87
  2. package/dist/esm/types/edges.d.ts +3 -0
  3. package/dist/esm/types/edges.d.ts.map +1 -1
  4. package/dist/esm/types/general.d.ts +5 -2
  5. package/dist/esm/types/general.d.ts.map +1 -1
  6. package/dist/esm/types/nodes.d.ts +11 -7
  7. package/dist/esm/types/nodes.d.ts.map +1 -1
  8. package/dist/esm/types/utils.d.ts.map +1 -1
  9. package/dist/esm/utils/connections.d.ts +12 -0
  10. package/dist/esm/utils/connections.d.ts.map +1 -0
  11. package/dist/esm/utils/dom.d.ts.map +1 -1
  12. package/dist/esm/utils/edges/general.d.ts +1 -1
  13. package/dist/esm/utils/edges/general.d.ts.map +1 -1
  14. package/dist/esm/utils/graph.d.ts +3 -3
  15. package/dist/esm/utils/graph.d.ts.map +1 -1
  16. package/dist/esm/utils/index.d.ts +3 -0
  17. package/dist/esm/utils/index.d.ts.map +1 -1
  18. package/dist/esm/utils/node-toolbar.d.ts +3 -0
  19. package/dist/esm/utils/node-toolbar.d.ts.map +1 -0
  20. package/dist/esm/utils/store.d.ts +5 -4
  21. package/dist/esm/utils/store.d.ts.map +1 -1
  22. package/dist/esm/xydrag/XYDrag.d.ts +1 -0
  23. package/dist/esm/xydrag/XYDrag.d.ts.map +1 -1
  24. package/dist/esm/xydrag/utils.d.ts +2 -2
  25. package/dist/esm/xydrag/utils.d.ts.map +1 -1
  26. package/dist/esm/xyhandle/XYHandle.d.ts +1 -1
  27. package/dist/esm/xyhandle/XYHandle.d.ts.map +1 -1
  28. package/dist/umd/index.js +1 -1
  29. package/dist/umd/types/edges.d.ts +3 -0
  30. package/dist/umd/types/edges.d.ts.map +1 -1
  31. package/dist/umd/types/general.d.ts +5 -2
  32. package/dist/umd/types/general.d.ts.map +1 -1
  33. package/dist/umd/types/nodes.d.ts +11 -7
  34. package/dist/umd/types/nodes.d.ts.map +1 -1
  35. package/dist/umd/types/utils.d.ts.map +1 -1
  36. package/dist/umd/utils/connections.d.ts +12 -0
  37. package/dist/umd/utils/connections.d.ts.map +1 -0
  38. package/dist/umd/utils/dom.d.ts.map +1 -1
  39. package/dist/umd/utils/edges/general.d.ts +1 -1
  40. package/dist/umd/utils/edges/general.d.ts.map +1 -1
  41. package/dist/umd/utils/graph.d.ts +3 -3
  42. package/dist/umd/utils/graph.d.ts.map +1 -1
  43. package/dist/umd/utils/index.d.ts +3 -0
  44. package/dist/umd/utils/index.d.ts.map +1 -1
  45. package/dist/umd/utils/node-toolbar.d.ts +3 -0
  46. package/dist/umd/utils/node-toolbar.d.ts.map +1 -0
  47. package/dist/umd/utils/store.d.ts +5 -4
  48. package/dist/umd/utils/store.d.ts.map +1 -1
  49. package/dist/umd/xydrag/XYDrag.d.ts +1 -0
  50. package/dist/umd/xydrag/XYDrag.d.ts.map +1 -1
  51. package/dist/umd/xydrag/utils.d.ts +2 -2
  52. package/dist/umd/xydrag/utils.d.ts.map +1 -1
  53. package/dist/umd/xyhandle/XYHandle.d.ts +1 -1
  54. package/dist/umd/xyhandle/XYHandle.d.ts.map +1 -1
  55. package/package.json +2 -2
@@ -64,6 +64,46 @@ var Position;
64
64
  Position["Bottom"] = "bottom";
65
65
  })(Position || (Position = {}));
66
66
 
67
+ /**
68
+ * @internal
69
+ */
70
+ function areConnectionMapsEqual(a, b) {
71
+ if (!a && !b) {
72
+ return true;
73
+ }
74
+ if (!a || !b || a.size !== b.size) {
75
+ return false;
76
+ }
77
+ if (!a.size && !b.size) {
78
+ return true;
79
+ }
80
+ for (const key of a.keys()) {
81
+ if (!b.has(key)) {
82
+ return false;
83
+ }
84
+ }
85
+ return true;
86
+ }
87
+ /**
88
+ * We call the callback for all connections in a that are not in b
89
+ *
90
+ * @internal
91
+ */
92
+ function handleConnectionChange(a, b, cb) {
93
+ if (!cb) {
94
+ return;
95
+ }
96
+ const diff = [];
97
+ a.forEach((connection, key) => {
98
+ if (!b?.has(key)) {
99
+ diff.push(connection);
100
+ }
101
+ });
102
+ if (diff.length) {
103
+ cb(diff);
104
+ }
105
+ }
106
+
67
107
  /* eslint-disable @typescript-eslint/no-explicit-any */
68
108
  const isEdgeBase = (element) => 'id' in element && 'source' in element && 'target' in element;
69
109
  const isNodeBase = (element) => 'id' in element && !('source' in element) && !('target' in element);
@@ -102,18 +142,18 @@ const getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {
102
142
  },
103
143
  };
104
144
  }
105
- const offsetX = (node.width ?? 0) * nodeOrigin[0];
106
- const offsetY = (node.height ?? 0) * nodeOrigin[1];
145
+ const offsetX = (node.computed?.width ?? node.width ?? 0) * nodeOrigin[0];
146
+ const offsetY = (node.computed?.height ?? node.height ?? 0) * nodeOrigin[1];
107
147
  const position = {
108
148
  x: node.position.x - offsetX,
109
149
  y: node.position.y - offsetY,
110
150
  };
111
151
  return {
112
152
  ...position,
113
- positionAbsolute: node.positionAbsolute
153
+ positionAbsolute: node.computed?.positionAbsolute
114
154
  ? {
115
- x: node.positionAbsolute.x - offsetX,
116
- y: node.positionAbsolute.y - offsetY,
155
+ x: node.computed.positionAbsolute.x - offsetX,
156
+ y: node.computed.positionAbsolute.y - offsetY,
117
157
  }
118
158
  : position,
119
159
  };
@@ -127,8 +167,8 @@ const getNodesBounds = (nodes, nodeOrigin = [0, 0]) => {
127
167
  return getBoundsOfBoxes(currBox, rectToBox({
128
168
  x,
129
169
  y,
130
- width: node.width || 0,
131
- height: node.height || 0,
170
+ width: node.computed?.width ?? node.width ?? 0,
171
+ height: node.computed?.height ?? node.height ?? 0,
132
172
  }));
133
173
  }, { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity });
134
174
  return boxToRect(box);
@@ -142,14 +182,16 @@ excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
142
182
  height: rect.height / tScale,
143
183
  };
144
184
  const visibleNodes = nodes.reduce((res, node) => {
145
- const { width, height, selectable = true, hidden = false } = node;
185
+ const { computed, selectable = true, hidden = false } = node;
186
+ const width = computed?.width ?? node.width ?? null;
187
+ const height = computed?.height ?? node.height ?? null;
146
188
  if ((excludeNonSelectableNodes && !selectable) || hidden) {
147
189
  return res;
148
190
  }
149
191
  const overlappingArea = getOverlappingArea(paneRect, nodeToRect(node, nodeOrigin));
150
- const notInitialized = width === undefined || height === undefined || width === null || height === null;
192
+ const notInitialized = width === null || height === null;
151
193
  const partiallyVisible = partially && overlappingArea > 0;
152
- const area = (width || 0) * (height || 0);
194
+ const area = (width ?? 0) * (height ?? 0);
153
195
  const isVisible = notInitialized || partiallyVisible || overlappingArea >= area;
154
196
  if (isVisible || node.dragging) {
155
197
  res.push(node);
@@ -167,7 +209,7 @@ const getConnectedEdgesBase = (nodes, edges) => {
167
209
  };
168
210
  function fitView({ nodes, width, height, panZoom, minZoom, maxZoom, nodeOrigin = [0, 0] }, options) {
169
211
  const filteredNodes = nodes.filter((n) => {
170
- const isVisible = n.width && n.height && (options?.includeHiddenNodes || !n.hidden);
212
+ const isVisible = n.computed?.width && n.computed?.height && (options?.includeHiddenNodes || !n.hidden);
171
213
  if (options?.nodes?.length) {
172
214
  return isVisible && options?.nodes.some((optionNode) => optionNode.id === n.id);
173
215
  }
@@ -185,7 +227,7 @@ function clampNodeExtent(node, extent) {
185
227
  if (!extent || extent === 'parent') {
186
228
  return extent;
187
229
  }
188
- return [extent[0], [extent[1][0] - (node.width || 0), extent[1][1] - (node.height || 0)]];
230
+ return [extent[0], [extent[1][0] - (node.computed?.width ?? 0), extent[1][1] - (node.computed?.height ?? 0)]];
189
231
  }
190
232
  function calcNextPosition(node, nextPosition, nodes, nodeExtent, nodeOrigin = [0, 0], onError) {
191
233
  const clampedNodeExtent = clampNodeExtent(node, node.extent || nodeExtent);
@@ -199,15 +241,17 @@ function calcNextPosition(node, nextPosition, nodes, nodeExtent, nodeOrigin = [0
199
241
  : parentPos;
200
242
  }
201
243
  if (node.extent === 'parent' && !node.expandParent) {
202
- if (node.parentNode && node.width && node.height) {
244
+ const nodeWidth = node.computed?.width;
245
+ const nodeHeight = node.computed?.height;
246
+ if (node.parentNode && nodeWidth && nodeHeight) {
203
247
  const currNodeOrigin = node.origin || nodeOrigin;
204
248
  currentExtent =
205
- parentNode && isNumeric(parentNode.width) && isNumeric(parentNode.height)
249
+ parentNode && isNumeric(parentNode.computed?.width) && isNumeric(parentNode.computed?.height)
206
250
  ? [
207
- [parentPos.x + node.width * currNodeOrigin[0], parentPos.y + node.height * currNodeOrigin[1]],
251
+ [parentPos.x + nodeWidth * currNodeOrigin[0], parentPos.y + nodeHeight * currNodeOrigin[1]],
208
252
  [
209
- parentPos.x + parentNode.width - node.width + node.width * currNodeOrigin[0],
210
- parentPos.y + parentNode.height - node.height + node.height * currNodeOrigin[1],
253
+ parentPos.x + (parentNode.computed?.width ?? 0) - nodeWidth + nodeWidth * currNodeOrigin[0],
254
+ parentPos.y + (parentNode.computed?.height ?? 0) - nodeHeight + nodeHeight * currNodeOrigin[1],
211
255
  ],
212
256
  ]
213
257
  : currentExtent;
@@ -251,7 +295,12 @@ function getElementsToRemove({ nodesToRemove, edgesToRemove, nodes, edges, }) {
251
295
  const deletableEdges = edges.filter((e) => (typeof e.deletable === 'boolean' ? e.deletable : true));
252
296
  const initialHitEdges = deletableEdges.filter((e) => edgeIds.includes(e.id));
253
297
  const connectedEdges = getConnectedEdgesBase(matchingNodes, deletableEdges);
254
- const matchingEdges = [...initialHitEdges, ...connectedEdges];
298
+ const matchingEdges = connectedEdges.reduce((res, edge) => {
299
+ if (!res.find((e) => e.id === edge.id)) {
300
+ res.push(edge);
301
+ }
302
+ return res;
303
+ }, initialHitEdges);
255
304
  return {
256
305
  matchingEdges,
257
306
  matchingNodes,
@@ -301,16 +350,16 @@ const nodeToRect = (node, nodeOrigin = [0, 0]) => {
301
350
  const { positionAbsolute } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
302
351
  return {
303
352
  ...positionAbsolute,
304
- width: node.width || 0,
305
- height: node.height || 0,
353
+ width: node.computed?.width ?? node.width ?? 0,
354
+ height: node.computed?.height ?? node.height ?? 0,
306
355
  };
307
356
  };
308
357
  const nodeToBox = (node, nodeOrigin = [0, 0]) => {
309
358
  const { positionAbsolute } = getNodePositionWithOrigin(node, node.origin || nodeOrigin);
310
359
  return {
311
360
  ...positionAbsolute,
312
- x2: positionAbsolute.x + (node.width || 0),
313
- y2: positionAbsolute.y + (node.height || 0),
361
+ x2: positionAbsolute.x + (node.computed?.width ?? node.width ?? 0),
362
+ y2: positionAbsolute.y + (node.computed?.height ?? node.height ?? 0),
314
363
  };
315
364
  };
316
365
  const getBoundsOfRects = (rect1, rect2) => boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2)));
@@ -406,12 +455,16 @@ const getEventPosition = (event, bounds) => {
406
455
  y: evtY - (bounds?.top ?? 0),
407
456
  };
408
457
  };
458
+ // The handle bounds are calculated relative to the node element.
459
+ // We store them in the internals object of the node in order to avoid
460
+ // unnecessary recalculations.
409
461
  const getHandleBounds = (selector, nodeElement, zoom, nodeOrigin = [0, 0]) => {
410
462
  const handles = nodeElement.querySelectorAll(selector);
411
463
  if (!handles || !handles.length) {
412
464
  return null;
413
465
  }
414
466
  const handlesArray = Array.from(handles);
467
+ // @todo can't we use the node dimensions here?
415
468
  const nodeBounds = nodeElement.getBoundingClientRect();
416
469
  const nodeOffset = {
417
470
  x: nodeBounds.width * nodeOrigin[0],
@@ -501,14 +554,14 @@ function getEdgeCenter({ sourceX, sourceY, targetX, targetY, }) {
501
554
  return [centerX, centerY, xOffset, yOffset];
502
555
  }
503
556
  const defaultEdgeTree = [{ level: 0, isMaxLevel: true, edges: [] }];
504
- function groupEdgesByZLevel(edges, nodes, elevateEdgesOnSelect = false) {
557
+ function groupEdgesByZLevel(edges, nodeLookup, elevateEdgesOnSelect = false) {
505
558
  let maxLevel = -1;
506
559
  const levelLookup = edges.reduce((tree, edge) => {
507
560
  const hasZIndex = isNumeric(edge.zIndex);
508
561
  let z = hasZIndex ? edge.zIndex : 0;
509
562
  if (elevateEdgesOnSelect) {
510
- const targetNode = nodes.find((n) => n.id === edge.target);
511
- const sourceNode = nodes.find((n) => n.id === edge.source);
563
+ const targetNode = nodeLookup.get(edge.target);
564
+ const sourceNode = nodeLookup.get(edge.source);
512
565
  const edgeOrConnectedNodeSelected = edge.selected || targetNode?.selected || sourceNode?.selected;
513
566
  const selectedZIndex = Math.max(sourceNode?.[internalsSymbol]?.z || 0, targetNode?.[internalsSymbol]?.z || 0, 1000);
514
567
  z = (hasZIndex ? edge.zIndex : 0) + (edgeOrConnectedNodeSelected ? selectedZIndex : 0);
@@ -551,7 +604,7 @@ function isEdgeVisible({ sourceNode, targetNode, width, height, transform }) {
551
604
  };
552
605
  return getOverlappingArea(viewRect, boxToRect(edgeBox)) > 0;
553
606
  }
554
- const getEdgeId = ({ source, sourceHandle, target, targetHandle }) => `xyflow__edge-${source}${sourceHandle || ''}-${target}${targetHandle || ''}`;
607
+ const getEdgeId = ({ source, sourceHandle, target, targetHandle }) => `xy-edge__${source}${sourceHandle || ''}-${target}${targetHandle || ''}`;
555
608
  const connectionExists = (edge, edges) => {
556
609
  return edges.some((el) => el.source === edge.source &&
557
610
  el.target === edge.target &&
@@ -576,6 +629,12 @@ const addEdgeBase = (edgeParams, edges) => {
576
629
  if (connectionExists(edge, edges)) {
577
630
  return edges;
578
631
  }
632
+ if (edge.sourceHandle === null) {
633
+ delete edge.sourceHandle;
634
+ }
635
+ if (edge.targetHandle === null) {
636
+ delete edge.targetHandle;
637
+ }
579
638
  return edges.concat(edge);
580
639
  };
581
640
  const updateEdgeBase = (oldEdge, newConnection, edges, options = { shouldReplaceId: true }) => {
@@ -826,17 +885,17 @@ function toHandleBounds(handles) {
826
885
  }
827
886
  function getHandleDataByNode(node) {
828
887
  const handleBounds = node?.[internalsSymbol]?.handleBounds || toHandleBounds(node?.handles) || null;
829
- const nodeWidth = node?.width || node?.size?.width;
830
- const nodeHeight = node?.height || node?.size?.height;
888
+ const nodeWidth = node?.computed?.width || node?.width;
889
+ const nodeHeight = node?.computed?.height || node?.height;
831
890
  const isValid = handleBounds &&
832
891
  nodeWidth &&
833
892
  nodeHeight &&
834
- typeof node?.positionAbsolute?.x !== 'undefined' &&
835
- typeof node?.positionAbsolute?.y !== 'undefined';
893
+ typeof node?.computed?.positionAbsolute?.x !== 'undefined' &&
894
+ typeof node?.computed?.positionAbsolute?.y !== 'undefined';
836
895
  return [
837
896
  {
838
- x: node?.positionAbsolute?.x || 0,
839
- y: node?.positionAbsolute?.y || 0,
897
+ x: node?.computed?.positionAbsolute?.x || 0,
898
+ y: node?.computed?.positionAbsolute?.y || 0,
840
899
  width: nodeWidth || 0,
841
900
  height: nodeHeight || 0,
842
901
  },
@@ -916,18 +975,57 @@ function createMarkerIds(edges, { id, defaultColor }) {
916
975
  .sort((a, b) => a.id.localeCompare(b.id));
917
976
  }
918
977
 
919
- function updateAbsolutePositions(nodes, nodeOrigin = [0, 0], parentNodes) {
978
+ function getNodeToolbarTransform(nodeRect, viewport, position, offset, align) {
979
+ let alignmentOffset = 0.5;
980
+ if (align === 'start') {
981
+ alignmentOffset = 0;
982
+ }
983
+ else if (align === 'end') {
984
+ alignmentOffset = 1;
985
+ }
986
+ // position === Position.Top
987
+ // we set the x any y position of the toolbar based on the nodes position
988
+ let pos = [
989
+ (nodeRect.x + nodeRect.width * alignmentOffset) * viewport.zoom + viewport.x,
990
+ nodeRect.y * viewport.zoom + viewport.y - offset,
991
+ ];
992
+ // and than shift it based on the alignment. The shift values are in %.
993
+ let shift = [-100 * alignmentOffset, -100];
994
+ switch (position) {
995
+ case Position.Right:
996
+ pos = [
997
+ (nodeRect.x + nodeRect.width) * viewport.zoom + viewport.x + offset,
998
+ (nodeRect.y + nodeRect.height * alignmentOffset) * viewport.zoom + viewport.y,
999
+ ];
1000
+ shift = [0, -100 * alignmentOffset];
1001
+ break;
1002
+ case Position.Bottom:
1003
+ pos[1] = (nodeRect.y + nodeRect.height) * viewport.zoom + viewport.y + offset;
1004
+ shift[1] = 0;
1005
+ break;
1006
+ case Position.Left:
1007
+ pos = [
1008
+ nodeRect.x * viewport.zoom + viewport.x - offset,
1009
+ (nodeRect.y + nodeRect.height * alignmentOffset) * viewport.zoom + viewport.y,
1010
+ ];
1011
+ shift = [-100, -100 * alignmentOffset];
1012
+ break;
1013
+ }
1014
+ return `translate(${pos[0]}px, ${pos[1]}px) translate(${shift[0]}%, ${shift[1]}%)`;
1015
+ }
1016
+
1017
+ function updateAbsolutePositions(nodes, nodeLookup, nodeOrigin = [0, 0], parentNodes) {
920
1018
  return nodes.map((node) => {
921
- if (node.parentNode && !nodes.find((n) => n.id === node.parentNode)) {
1019
+ if (node.parentNode && !nodeLookup.has(node.parentNode)) {
922
1020
  throw new Error(`Parent node ${node.parentNode} not found`);
923
1021
  }
924
1022
  if (node.parentNode || parentNodes?.[node.id]) {
925
- const parentNode = node.parentNode ? nodes.find((n) => n.id === node.parentNode) : null;
926
- const { x, y, z } = calculateXYZPosition(node, nodes, {
1023
+ const parentNode = node.parentNode ? nodeLookup.get(node.parentNode) : null;
1024
+ const { x, y, z } = calculateXYZPosition(node, nodes, nodeLookup, {
927
1025
  ...node.position,
928
1026
  z: node[internalsSymbol]?.z ?? 0,
929
1027
  }, parentNode?.origin || nodeOrigin);
930
- node.positionAbsolute = {
1028
+ node.computed.positionAbsolute = {
931
1029
  x,
932
1030
  y,
933
1031
  };
@@ -939,21 +1037,25 @@ function updateAbsolutePositions(nodes, nodeOrigin = [0, 0], parentNodes) {
939
1037
  return node;
940
1038
  });
941
1039
  }
942
- function updateNodes(nodes, storeNodes, options = {
1040
+ function updateNodes(nodes, nodeLookup, options = {
943
1041
  nodeOrigin: [0, 0],
944
1042
  elevateNodesOnSelect: true,
945
1043
  defaults: {},
946
1044
  }) {
1045
+ const tmpLookup = new Map(nodeLookup);
1046
+ nodeLookup.clear();
947
1047
  const parentNodes = {};
948
1048
  const selectedNodeZ = options?.elevateNodesOnSelect ? 1000 : 0;
949
1049
  const nextNodes = nodes.map((n) => {
950
- const currentStoreNode = storeNodes.find((storeNode) => n.id === storeNode.id);
1050
+ const currentStoreNode = tmpLookup.get(n.id);
951
1051
  const node = {
952
1052
  ...options.defaults,
953
1053
  ...n,
954
- positionAbsolute: n.position,
955
- width: n.width || currentStoreNode?.width,
956
- height: n.height || currentStoreNode?.height,
1054
+ computed: {
1055
+ positionAbsolute: n.position,
1056
+ width: n.computed?.width || currentStoreNode?.computed?.width,
1057
+ height: n.computed?.height || currentStoreNode?.computed?.height,
1058
+ },
957
1059
  };
958
1060
  const z = (isNumeric(n.zIndex) ? n.zIndex : 0) + (n.selected ? selectedNodeZ : 0);
959
1061
  const currInternals = n?.[internalsSymbol] || currentStoreNode?.[internalsSymbol];
@@ -967,24 +1069,25 @@ function updateNodes(nodes, storeNodes, options = {
967
1069
  z,
968
1070
  },
969
1071
  });
1072
+ nodeLookup.set(node.id, node);
970
1073
  return node;
971
1074
  });
972
- const nodesWithPositions = updateAbsolutePositions(nextNodes, options.nodeOrigin, parentNodes);
1075
+ const nodesWithPositions = updateAbsolutePositions(nextNodes, nodeLookup, options.nodeOrigin, parentNodes);
973
1076
  return nodesWithPositions;
974
1077
  }
975
- function calculateXYZPosition(node, nodes, result, nodeOrigin) {
1078
+ function calculateXYZPosition(node, nodes, nodeLookup, result, nodeOrigin) {
976
1079
  if (!node.parentNode) {
977
1080
  return result;
978
1081
  }
979
- const parentNode = nodes.find((n) => n.id === node.parentNode);
1082
+ const parentNode = nodeLookup.get(node.parentNode);
980
1083
  const parentNodePosition = getNodePositionWithOrigin(parentNode, parentNode?.origin || nodeOrigin);
981
- return calculateXYZPosition(parentNode, nodes, {
1084
+ return calculateXYZPosition(parentNode, nodes, nodeLookup, {
982
1085
  x: (result.x ?? 0) + parentNodePosition.x,
983
1086
  y: (result.y ?? 0) + parentNodePosition.y,
984
1087
  z: (parentNode[internalsSymbol]?.z ?? 0) > (result.z ?? 0) ? parentNode[internalsSymbol]?.z ?? 0 : result.z ?? 0,
985
1088
  }, parentNode.origin || nodeOrigin);
986
1089
  }
987
- function updateNodeDimensions(updates, nodes, domNode, nodeOrigin, onUpdate) {
1090
+ function updateNodeDimensions(updates, nodes, nodeLookup, domNode, nodeOrigin, onUpdate) {
988
1091
  const viewportNode = domNode?.querySelector('.xyflow__viewport');
989
1092
  if (!viewportNode) {
990
1093
  return null;
@@ -992,17 +1095,20 @@ function updateNodeDimensions(updates, nodes, domNode, nodeOrigin, onUpdate) {
992
1095
  const style = window.getComputedStyle(viewportNode);
993
1096
  const { m22: zoom } = new window.DOMMatrixReadOnly(style.transform);
994
1097
  const nextNodes = nodes.map((node) => {
995
- const update = updates.find((u) => u.id === node.id);
1098
+ const update = updates.get(node.id);
996
1099
  if (update) {
997
1100
  const dimensions = getDimensions(update.nodeElement);
998
1101
  const doUpdate = !!(dimensions.width &&
999
1102
  dimensions.height &&
1000
- (node.width !== dimensions.width || node.height !== dimensions.height || update.forceUpdate));
1103
+ (node.computed?.width !== dimensions.width || node.computed?.height !== dimensions.height || update.forceUpdate));
1001
1104
  if (doUpdate) {
1002
1105
  onUpdate?.(node.id, dimensions);
1003
- return {
1106
+ const newNode = {
1004
1107
  ...node,
1005
- ...dimensions,
1108
+ computed: {
1109
+ ...node.computed,
1110
+ ...dimensions,
1111
+ },
1006
1112
  [internalsSymbol]: {
1007
1113
  ...node[internalsSymbol],
1008
1114
  handleBounds: {
@@ -1011,6 +1117,8 @@ function updateNodeDimensions(updates, nodes, domNode, nodeOrigin, onUpdate) {
1011
1117
  },
1012
1118
  },
1013
1119
  };
1120
+ nodeLookup.set(node.id, newNode);
1121
+ return newNode;
1014
1122
  }
1015
1123
  }
1016
1124
  return node;
@@ -1033,6 +1141,21 @@ function panBy({ delta, panZoom, transform, translateExtent, width, height, }) {
1033
1141
  (nextViewport.x !== transform[0] || nextViewport.y !== transform[1] || nextViewport.k !== transform[2]);
1034
1142
  return transformChanged;
1035
1143
  }
1144
+ function updateConnectionLookup(lookup, edges) {
1145
+ lookup.clear();
1146
+ edges.forEach(({ source, target, sourceHandle = null, targetHandle = null }) => {
1147
+ if (source && target) {
1148
+ const sourceKey = `${source}-source-${sourceHandle}`;
1149
+ const targetKey = `${target}-target-${targetHandle}`;
1150
+ const prevSource = lookup.get(sourceKey) || new Map();
1151
+ const prevTarget = lookup.get(targetKey) || new Map();
1152
+ const connection = { source, target, sourceHandle, targetHandle };
1153
+ lookup.set(sourceKey, prevSource.set(`${target}-${targetHandle}`, connection));
1154
+ lookup.set(targetKey, prevTarget.set(`${source}-${sourceHandle}`, connection));
1155
+ }
1156
+ });
1157
+ return lookup;
1158
+ }
1036
1159
 
1037
1160
  function wrapSelectionDragFunc(selectionFunc) {
1038
1161
  return (event, _, nodes) => selectionFunc?.(event, nodes);
@@ -1070,10 +1193,9 @@ function getDragItems(nodes, nodesDraggable, mousePos, nodeId) {
1070
1193
  .map((n) => ({
1071
1194
  id: n.id,
1072
1195
  position: n.position || { x: 0, y: 0 },
1073
- positionAbsolute: n.positionAbsolute || { x: 0, y: 0 },
1074
1196
  distance: {
1075
- x: mousePos.x - (n.positionAbsolute?.x ?? 0),
1076
- y: mousePos.y - (n.positionAbsolute?.y ?? 0),
1197
+ x: mousePos.x - (n.computed?.positionAbsolute?.x ?? 0),
1198
+ y: mousePos.y - (n.computed?.positionAbsolute?.y ?? 0),
1077
1199
  },
1078
1200
  delta: {
1079
1201
  x: 0,
@@ -1081,25 +1203,31 @@ function getDragItems(nodes, nodesDraggable, mousePos, nodeId) {
1081
1203
  },
1082
1204
  extent: n.extent,
1083
1205
  parentNode: n.parentNode,
1084
- width: n.width,
1085
- height: n.height,
1086
1206
  origin: n.origin,
1087
1207
  expandParent: n.expandParent,
1208
+ computed: {
1209
+ positionAbsolute: n.computed?.positionAbsolute || { x: 0, y: 0 },
1210
+ width: n.computed?.width || 0,
1211
+ height: n.computed?.height || 0,
1212
+ },
1088
1213
  }));
1089
1214
  }
1090
1215
  // returns two params:
1091
1216
  // 1. the dragged node (or the first of the list, if we are dragging a node selection)
1092
1217
  // 2. array of selected nodes (for multi selections)
1093
- function getEventHandlerParams({ nodeId, dragItems, nodes, }) {
1094
- const extentedDragItems = dragItems.map((n) => {
1095
- const node = nodes.find((node) => node.id === n.id);
1218
+ function getEventHandlerParams({ nodeId, dragItems, nodeLookup, }) {
1219
+ const nodesFromDragItems = dragItems.map((n) => {
1220
+ const node = nodeLookup.get(n.id);
1096
1221
  return {
1097
1222
  ...node,
1098
1223
  position: n.position,
1099
- positionAbsolute: n.positionAbsolute,
1224
+ computed: {
1225
+ ...n.computed,
1226
+ positionAbsolute: n.computed.positionAbsolute,
1227
+ },
1100
1228
  };
1101
1229
  });
1102
- return [nodeId ? extentedDragItems.find((n) => n.id === nodeId) : extentedDragItems[0], extentedDragItems];
1230
+ return [nodeId ? nodesFromDragItems.find((n) => n.id === nodeId) : nodesFromDragItems[0], nodesFromDragItems];
1103
1231
  }
1104
1232
 
1105
1233
  function XYDrag({ domNode, onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragStop, }) {
@@ -1115,7 +1243,7 @@ function XYDrag({ domNode, onNodeMouseDown, getStoreItems, onDragStart, onDrag,
1115
1243
  // public functions
1116
1244
  function update({ noDragClassName, handleSelector, domNode, isSelectable, nodeId }) {
1117
1245
  function updateNodes({ x, y }) {
1118
- const { nodes, nodeExtent, snapGrid, snapToGrid, nodeOrigin, onNodeDrag, onSelectionDrag, onError, updateNodePositions, } = getStoreItems();
1246
+ const { nodes, nodeLookup, nodeExtent, snapGrid, snapToGrid, nodeOrigin, onNodeDrag, onSelectionDrag, onError, updateNodePositions, } = getStoreItems();
1119
1247
  lastPos = { x, y };
1120
1248
  let hasChange = false;
1121
1249
  let nodesBox = { x: 0, y: 0, x2: 0, y2: 0 };
@@ -1135,16 +1263,18 @@ function XYDrag({ domNode, onNodeMouseDown, getStoreItems, onDragStart, onDrag,
1135
1263
  [nodeExtent[1][0], nodeExtent[1][1]],
1136
1264
  ];
1137
1265
  if (dragItems.length > 1 && nodeExtent && !n.extent) {
1138
- adjustedNodeExtent[0][0] = n.positionAbsolute.x - nodesBox.x + nodeExtent[0][0];
1139
- adjustedNodeExtent[1][0] = n.positionAbsolute.x + (n.width ?? 0) - nodesBox.x2 + nodeExtent[1][0];
1140
- adjustedNodeExtent[0][1] = n.positionAbsolute.y - nodesBox.y + nodeExtent[0][1];
1141
- adjustedNodeExtent[1][1] = n.positionAbsolute.y + (n.height ?? 0) - nodesBox.y2 + nodeExtent[1][1];
1266
+ adjustedNodeExtent[0][0] = n.computed.positionAbsolute.x - nodesBox.x + nodeExtent[0][0];
1267
+ adjustedNodeExtent[1][0] =
1268
+ n.computed.positionAbsolute.x + (n.computed?.width ?? 0) - nodesBox.x2 + nodeExtent[1][0];
1269
+ adjustedNodeExtent[0][1] = n.computed.positionAbsolute.y - nodesBox.y + nodeExtent[0][1];
1270
+ adjustedNodeExtent[1][1] =
1271
+ n.computed.positionAbsolute.y + (n.computed?.height ?? 0) - nodesBox.y2 + nodeExtent[1][1];
1142
1272
  }
1143
1273
  const updatedPos = calcNextPosition(n, nextPosition, nodes, adjustedNodeExtent, nodeOrigin, onError);
1144
1274
  // we want to make sure that we only fire a change event when there is a change
1145
1275
  hasChange = hasChange || n.position.x !== updatedPos.position.x || n.position.y !== updatedPos.position.y;
1146
1276
  n.position = updatedPos.position;
1147
- n.positionAbsolute = updatedPos.positionAbsolute;
1277
+ n.computed.positionAbsolute = updatedPos.positionAbsolute;
1148
1278
  return n;
1149
1279
  });
1150
1280
  if (!hasChange) {
@@ -1152,11 +1282,11 @@ function XYDrag({ domNode, onNodeMouseDown, getStoreItems, onDragStart, onDrag,
1152
1282
  }
1153
1283
  updateNodePositions(dragItems, true, true);
1154
1284
  const onNodeOrSelectionDrag = nodeId ? onNodeDrag : wrapSelectionDragFunc(onSelectionDrag);
1155
- if (dragEvent) {
1285
+ if (dragEvent && (onDrag || onNodeOrSelectionDrag)) {
1156
1286
  const [currentNode, currentNodes] = getEventHandlerParams({
1157
1287
  nodeId,
1158
1288
  dragItems,
1159
- nodes,
1289
+ nodeLookup,
1160
1290
  });
1161
1291
  onDrag?.(dragEvent, dragItems, currentNode, currentNodes);
1162
1292
  onNodeOrSelectionDrag?.(dragEvent, currentNode, currentNodes);
@@ -1178,10 +1308,10 @@ function XYDrag({ domNode, onNodeMouseDown, getStoreItems, onDragStart, onDrag,
1178
1308
  autoPanId = requestAnimationFrame(autoPan);
1179
1309
  }
1180
1310
  function startDrag(event) {
1181
- const { nodes, multiSelectionActive, nodesDraggable, transform, snapGrid, snapToGrid, selectNodesOnDrag, onNodeDragStart, onSelectionDragStart, unselectNodesAndEdges, } = getStoreItems();
1311
+ const { nodes, nodeLookup, multiSelectionActive, nodesDraggable, transform, snapGrid, snapToGrid, selectNodesOnDrag, onNodeDragStart, onSelectionDragStart, unselectNodesAndEdges, } = getStoreItems();
1182
1312
  dragStarted = true;
1183
1313
  if ((!selectNodesOnDrag || !isSelectable) && !multiSelectionActive && nodeId) {
1184
- if (!nodes.find((n) => n.id === nodeId)?.selected) {
1314
+ if (!nodeLookup.get(nodeId)?.selected) {
1185
1315
  // we need to reset selected nodes when selectNodesOnDrag=false
1186
1316
  unselectNodesAndEdges();
1187
1317
  }
@@ -1193,11 +1323,11 @@ function XYDrag({ domNode, onNodeMouseDown, getStoreItems, onDragStart, onDrag,
1193
1323
  lastPos = pointerPos;
1194
1324
  dragItems = getDragItems(nodes, nodesDraggable, pointerPos, nodeId);
1195
1325
  const onNodeOrSelectionDragStart = nodeId ? onNodeDragStart : wrapSelectionDragFunc(onSelectionDragStart);
1196
- if (dragItems) {
1326
+ if (dragItems && (onDragStart || onNodeOrSelectionDragStart)) {
1197
1327
  const [currentNode, currentNodes] = getEventHandlerParams({
1198
1328
  nodeId,
1199
1329
  dragItems,
1200
- nodes,
1330
+ nodeLookup,
1201
1331
  });
1202
1332
  onDragStart?.(event.sourceEvent, dragItems, currentNode, currentNodes);
1203
1333
  onNodeOrSelectionDragStart?.(event.sourceEvent, currentNode, currentNodes);
@@ -1244,16 +1374,18 @@ function XYDrag({ domNode, onNodeMouseDown, getStoreItems, onDragStart, onDrag,
1244
1374
  dragStarted = false;
1245
1375
  cancelAnimationFrame(autoPanId);
1246
1376
  if (dragItems) {
1247
- const { nodes, updateNodePositions, onNodeDragStop, onSelectionDragStop } = getStoreItems();
1377
+ const { nodeLookup, updateNodePositions, onNodeDragStop, onSelectionDragStop } = getStoreItems();
1248
1378
  const onNodeOrSelectionDragStop = nodeId ? onNodeDragStop : wrapSelectionDragFunc(onSelectionDragStop);
1249
1379
  updateNodePositions(dragItems, false, false);
1250
- const [currentNode, currentNodes] = getEventHandlerParams({
1251
- nodeId,
1252
- dragItems,
1253
- nodes,
1254
- });
1255
- onDragStop?.(event.sourceEvent, dragItems, currentNode, currentNodes);
1256
- onNodeOrSelectionDragStop?.(event.sourceEvent, currentNode, currentNodes);
1380
+ if (onDragStop || onNodeOrSelectionDragStop) {
1381
+ const [currentNode, currentNodes] = getEventHandlerParams({
1382
+ nodeId,
1383
+ dragItems,
1384
+ nodeLookup,
1385
+ });
1386
+ onDragStop?.(event.sourceEvent, dragItems, currentNode, currentNodes);
1387
+ onNodeOrSelectionDragStop?.(event.sourceEvent, currentNode, currentNodes);
1388
+ }
1257
1389
  }
1258
1390
  })
1259
1391
  .filter((event) => {
@@ -1283,8 +1415,8 @@ function getHandles(node, handleBounds, type, currentHandle) {
1283
1415
  id: h.id || null,
1284
1416
  type,
1285
1417
  nodeId: node.id,
1286
- x: (node.positionAbsolute?.x ?? 0) + h.x + h.width / 2,
1287
- y: (node.positionAbsolute?.y ?? 0) + h.y + h.height / 2,
1418
+ x: (node.computed?.positionAbsolute?.x ?? 0) + h.x + h.width / 2,
1419
+ y: (node.computed?.positionAbsolute?.y ?? 0) + h.y + h.height / 2,
1288
1420
  });
1289
1421
  }
1290
1422
  return res;
@@ -1355,7 +1487,6 @@ function getConnectionStatus(isInsideConnectionRadius, isHandleValid) {
1355
1487
  return connectionStatus;
1356
1488
  }
1357
1489
 
1358
- const nullConnection = { source: null, target: null, sourceHandle: null, targetHandle: null };
1359
1490
  const alwaysValid = () => true;
1360
1491
  let connectionStartHandle = null;
1361
1492
  function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodes, lib, autoPanOnConnect, panBy, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onEdgeUpdateEnd, updateConnection, getTransform, }) {
@@ -1440,7 +1571,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
1440
1571
  if (!closestHandle && !isValid && !handleDomNode) {
1441
1572
  return resetRecentHandle(prevActiveHandle, lib);
1442
1573
  }
1443
- if (connection.source !== connection.target && handleDomNode) {
1574
+ if (connection?.source !== connection?.target && handleDomNode) {
1444
1575
  resetRecentHandle(prevActiveHandle, lib);
1445
1576
  prevActiveHandle = handleDomNode;
1446
1577
  handleDomNode.classList.add('connecting', `${lib}-flow__handle-connecting`);
@@ -1488,7 +1619,7 @@ function isValidHandle(event, { handle, connectionMode, fromNodeId, fromHandleId
1488
1619
  const result = {
1489
1620
  handleDomNode: handleToCheck,
1490
1621
  isValid: false,
1491
- connection: nullConnection,
1622
+ connection: null,
1492
1623
  endHandle: null,
1493
1624
  };
1494
1625
  if (handleToCheck) {
@@ -1497,6 +1628,9 @@ function isValidHandle(event, { handle, connectionMode, fromNodeId, fromHandleId
1497
1628
  const handleId = handleToCheck.getAttribute('data-handleid');
1498
1629
  const connectable = handleToCheck.classList.contains('connectable');
1499
1630
  const connectableEnd = handleToCheck.classList.contains('connectableend');
1631
+ if (!handleNodeId) {
1632
+ return result;
1633
+ }
1500
1634
  const connection = {
1501
1635
  source: isTarget ? handleNodeId : fromNodeId,
1502
1636
  sourceHandle: isTarget ? handleId : fromHandleId,
@@ -1919,4 +2053,4 @@ function XYPanZoom({ domNode, minZoom, maxZoom, translateExtent, viewport, onPan
1919
2053
  };
1920
2054
  }
1921
2055
 
1922
- export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, SelectionMode, XYDrag, XYHandle, XYMinimap, XYPanZoom, addEdgeBase, boxToRect, calcAutoPan, calcNextPosition, clamp, clampPosition, createMarkerIds, devWarn, elementSelectionKeys, errorMessages, fitView, getBezierEdgeCenter, getBezierPath, getBoundsOfBoxes, getBoundsOfRects, getConnectedEdgesBase, getDimensions, getEdgeCenter, getEdgePosition, getElementsToRemove, getEventPosition, getHandleBounds, getHostForElement, getIncomersBase, getMarkerId, getNodePositionWithOrigin, getNodesBounds, getNodesInside, getOutgoersBase, getOverlappingArea, getPointerPosition, getPositionWithOrigin, getSmoothStepPath, getStraightPath, getViewportForBounds, groupEdgesByZLevel, infiniteExtent, internalsSymbol, isEdgeBase, isEdgeVisible, isInputDOMNode, isMacOs, isMouseEvent, isNodeBase, isNumeric, isRectObject, nodeToBox, nodeToRect, panBy, pointToRendererPoint, rectToBox, rendererPointToPoint, snapPosition, updateAbsolutePositions, updateEdgeBase, updateNodeDimensions, updateNodes };
2056
+ export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, SelectionMode, XYDrag, XYHandle, XYMinimap, XYPanZoom, addEdgeBase, areConnectionMapsEqual, boxToRect, calcAutoPan, calcNextPosition, clamp, clampPosition, createMarkerIds, devWarn, elementSelectionKeys, errorMessages, fitView, getBezierEdgeCenter, getBezierPath, getBoundsOfBoxes, getBoundsOfRects, getConnectedEdgesBase, getDimensions, getEdgeCenter, getEdgePosition, getElementsToRemove, getEventPosition, getHandleBounds, getHostForElement, getIncomersBase, getMarkerId, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesInside, getOutgoersBase, getOverlappingArea, getPointerPosition, getPositionWithOrigin, getSmoothStepPath, getStraightPath, getViewportForBounds, groupEdgesByZLevel, handleConnectionChange, infiniteExtent, internalsSymbol, isEdgeBase, isEdgeVisible, isInputDOMNode, isMacOs, isMouseEvent, isNodeBase, isNumeric, isRectObject, nodeToBox, nodeToRect, panBy, pointToRendererPoint, rectToBox, rendererPointToPoint, snapPosition, updateAbsolutePositions, updateConnectionLookup, updateEdgeBase, updateNodeDimensions, updateNodes };
@@ -23,6 +23,9 @@ export type SmoothStepPathOptions = {
23
23
  offset?: number;
24
24
  borderRadius?: number;
25
25
  };
26
+ export type StepPathOptions = {
27
+ offset?: number;
28
+ };
26
29
  export type BezierPathOptions = {
27
30
  curvature?: number;
28
31
  };
@@ -1 +1 @@
1
- {"version":3,"file":"edges.d.ts","sourceRoot":"","sources":["../../src/types/edges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,MAAM,MAAM,QAAQ,CAAC,QAAQ,GAAG,GAAG,IAAI;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,QAAQ,SAAS,QAAQ,IAAI,IAAI,CAClE,QAAQ,EACR,IAAI,GAAG,QAAQ,GAAG,QAAQ,GAAG,cAAc,GAAG,cAAc,GAAG,YAAY,GAAG,YAAY,CAC3F,CAAC;AAEF,oBAAY,kBAAkB;IAC5B,MAAM,YAAY;IAClB,QAAQ,aAAa;IACrB,IAAI,SAAS;IACb,UAAU,eAAe;IACzB,YAAY,iBAAiB;CAC9B;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,UAAU,CAAC;AAEjD,oBAAY,UAAU;IACpB,KAAK,UAAU;IACf,WAAW,gBAAgB;CAC5B;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG;IACrC,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,QAAQ,CAAC;IACzB,cAAc,EAAE,QAAQ,CAAC;CAC1B,CAAC"}
1
+ {"version":3,"file":"edges.d.ts","sourceRoot":"","sources":["../../src/types/edges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,MAAM,MAAM,QAAQ,CAAC,QAAQ,GAAG,GAAG,IAAI;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,QAAQ,SAAS,QAAQ,IAAI,IAAI,CAClE,QAAQ,EACR,IAAI,GAAG,QAAQ,GAAG,QAAQ,GAAG,cAAc,GAAG,cAAc,GAAG,YAAY,GAAG,YAAY,CAC3F,CAAC;AAEF,oBAAY,kBAAkB;IAC5B,MAAM,YAAY;IAClB,QAAQ,aAAa;IACrB,IAAI,SAAS;IACb,UAAU,eAAe;IACzB,YAAY,iBAAiB;CAC9B;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,UAAU,CAAC;AAEjD,oBAAY,UAAU;IACpB,KAAK,UAAU;IACf,WAAW,gBAAgB;CAC5B;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG;IACrC,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,QAAQ,CAAC;IACzB,cAAc,EAAE,QAAQ,CAAC;CAC1B,CAAC"}