@xyflow/system 0.0.50 → 0.0.51

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 (76) hide show
  1. package/dist/esm/index.js +286 -90
  2. package/dist/esm/index.mjs +286 -90
  3. package/dist/esm/types/changes.d.ts +12 -1
  4. package/dist/esm/types/changes.d.ts.map +1 -1
  5. package/dist/esm/types/edges.d.ts +37 -4
  6. package/dist/esm/types/edges.d.ts.map +1 -1
  7. package/dist/esm/types/general.d.ts +63 -0
  8. package/dist/esm/types/general.d.ts.map +1 -1
  9. package/dist/esm/types/handles.d.ts +8 -4
  10. package/dist/esm/types/handles.d.ts.map +1 -1
  11. package/dist/esm/types/nodes.d.ts +28 -8
  12. package/dist/esm/types/nodes.d.ts.map +1 -1
  13. package/dist/esm/types/utils.d.ts +22 -0
  14. package/dist/esm/types/utils.d.ts.map +1 -1
  15. package/dist/esm/utils/dom.d.ts.map +1 -1
  16. package/dist/esm/utils/edges/bezier-edge.d.ts +18 -11
  17. package/dist/esm/utils/edges/bezier-edge.d.ts.map +1 -1
  18. package/dist/esm/utils/edges/general.d.ts +16 -3
  19. package/dist/esm/utils/edges/general.d.ts.map +1 -1
  20. package/dist/esm/utils/edges/smoothstep-edge.d.ts +17 -11
  21. package/dist/esm/utils/edges/smoothstep-edge.d.ts.map +1 -1
  22. package/dist/esm/utils/edges/straight-edge.d.ts +15 -11
  23. package/dist/esm/utils/edges/straight-edge.d.ts.map +1 -1
  24. package/dist/esm/utils/general.d.ts +2 -2
  25. package/dist/esm/utils/graph.d.ts +82 -4
  26. package/dist/esm/utils/graph.d.ts.map +1 -1
  27. package/dist/esm/utils/node-toolbar.d.ts.map +1 -1
  28. package/dist/esm/utils/store.d.ts.map +1 -1
  29. package/dist/esm/xydrag/XYDrag.d.ts.map +1 -1
  30. package/dist/esm/xydrag/utils.d.ts.map +1 -1
  31. package/dist/esm/xyhandle/XYHandle.d.ts.map +1 -1
  32. package/dist/esm/xyhandle/types.d.ts.map +1 -1
  33. package/dist/esm/xyhandle/utils.d.ts.map +1 -1
  34. package/dist/esm/xypanzoom/XYPanZoom.d.ts.map +1 -1
  35. package/dist/esm/xypanzoom/eventhandler.d.ts.map +1 -1
  36. package/dist/esm/xyresizer/XYResizer.d.ts.map +1 -1
  37. package/dist/esm/xyresizer/types.d.ts +15 -0
  38. package/dist/esm/xyresizer/types.d.ts.map +1 -1
  39. package/dist/umd/index.js +1 -1
  40. package/dist/umd/types/changes.d.ts +12 -1
  41. package/dist/umd/types/changes.d.ts.map +1 -1
  42. package/dist/umd/types/edges.d.ts +37 -4
  43. package/dist/umd/types/edges.d.ts.map +1 -1
  44. package/dist/umd/types/general.d.ts +63 -0
  45. package/dist/umd/types/general.d.ts.map +1 -1
  46. package/dist/umd/types/handles.d.ts +8 -4
  47. package/dist/umd/types/handles.d.ts.map +1 -1
  48. package/dist/umd/types/nodes.d.ts +28 -8
  49. package/dist/umd/types/nodes.d.ts.map +1 -1
  50. package/dist/umd/types/utils.d.ts +22 -0
  51. package/dist/umd/types/utils.d.ts.map +1 -1
  52. package/dist/umd/utils/dom.d.ts.map +1 -1
  53. package/dist/umd/utils/edges/bezier-edge.d.ts +18 -11
  54. package/dist/umd/utils/edges/bezier-edge.d.ts.map +1 -1
  55. package/dist/umd/utils/edges/general.d.ts +16 -3
  56. package/dist/umd/utils/edges/general.d.ts.map +1 -1
  57. package/dist/umd/utils/edges/smoothstep-edge.d.ts +17 -11
  58. package/dist/umd/utils/edges/smoothstep-edge.d.ts.map +1 -1
  59. package/dist/umd/utils/edges/straight-edge.d.ts +15 -11
  60. package/dist/umd/utils/edges/straight-edge.d.ts.map +1 -1
  61. package/dist/umd/utils/general.d.ts +2 -2
  62. package/dist/umd/utils/graph.d.ts +82 -4
  63. package/dist/umd/utils/graph.d.ts.map +1 -1
  64. package/dist/umd/utils/node-toolbar.d.ts.map +1 -1
  65. package/dist/umd/utils/store.d.ts.map +1 -1
  66. package/dist/umd/xydrag/XYDrag.d.ts.map +1 -1
  67. package/dist/umd/xydrag/utils.d.ts.map +1 -1
  68. package/dist/umd/xyhandle/XYHandle.d.ts.map +1 -1
  69. package/dist/umd/xyhandle/types.d.ts.map +1 -1
  70. package/dist/umd/xyhandle/utils.d.ts.map +1 -1
  71. package/dist/umd/xypanzoom/XYPanZoom.d.ts.map +1 -1
  72. package/dist/umd/xypanzoom/eventhandler.d.ts.map +1 -1
  73. package/dist/umd/xyresizer/XYResizer.d.ts.map +1 -1
  74. package/dist/umd/xyresizer/types.d.ts +15 -0
  75. package/dist/umd/xyresizer/types.d.ts.map +1 -1
  76. package/package.json +3 -3
package/dist/esm/index.js CHANGED
@@ -24,11 +24,26 @@ const infiniteExtent = [
24
24
  ];
25
25
  const elementSelectionKeys = ['Enter', ' ', 'Escape'];
26
26
 
27
+ /**
28
+ * The `ConnectionMode` is used to set the mode of connection between nodes.
29
+ * The `Strict` mode is the default one and only allows source to target edges.
30
+ * `Loose` mode allows source to source and target to target edges as well.
31
+ *
32
+ * @public
33
+ */
27
34
  var ConnectionMode;
28
35
  (function (ConnectionMode) {
29
36
  ConnectionMode["Strict"] = "strict";
30
37
  ConnectionMode["Loose"] = "loose";
31
38
  })(ConnectionMode || (ConnectionMode = {}));
39
+ /**
40
+ * This enum is used to set the different modes of panning the viewport when the
41
+ * user scrolls. The `Free` mode allows the user to pan in any direction by scrolling
42
+ * with a device like a trackpad. The `Vertical` and `Horizontal` modes restrict
43
+ * scroll panning to only the vertical or horizontal axis, respectively.
44
+ *
45
+ * @public
46
+ */
32
47
  var PanOnScrollMode;
33
48
  (function (PanOnScrollMode) {
34
49
  PanOnScrollMode["Free"] = "free";
@@ -53,6 +68,16 @@ const initialConnection = {
53
68
  toNode: null,
54
69
  };
55
70
 
71
+ /**
72
+ * If you set the `connectionLineType` prop on your [`<ReactFlow />`](/api-reference/react-flow#connection-connectionLineType)
73
+ *component, it will dictate the style of connection line rendered when creating
74
+ *new edges.
75
+ *
76
+ * @public
77
+ *
78
+ * @remarks If you choose to render a custom connection line component, this value will be
79
+ *passed to your component as part of its [`ConnectionLineComponentProps`](/api-reference/types/connection-line-component-props).
80
+ */
56
81
  var ConnectionLineType;
57
82
  (function (ConnectionLineType) {
58
83
  ConnectionLineType["Bezier"] = "default";
@@ -61,12 +86,25 @@ var ConnectionLineType;
61
86
  ConnectionLineType["SmoothStep"] = "smoothstep";
62
87
  ConnectionLineType["SimpleBezier"] = "simplebezier";
63
88
  })(ConnectionLineType || (ConnectionLineType = {}));
89
+ /**
90
+ * Edges may optionally have a marker on either end. The MarkerType type enumerates
91
+ * the options available to you when configuring a given marker.
92
+ *
93
+ * @public
94
+ */
64
95
  var MarkerType;
65
96
  (function (MarkerType) {
66
97
  MarkerType["Arrow"] = "arrow";
67
98
  MarkerType["ArrowClosed"] = "arrowclosed";
68
99
  })(MarkerType || (MarkerType = {}));
69
100
 
101
+ /**
102
+ * While [`PanelPosition`](/api-reference/types/panel-position) can be used to place a
103
+ * component in the corners of a container, the `Position` enum is less precise and used
104
+ * primarily in relation to edges and handles.
105
+ *
106
+ * @public
107
+ */
70
108
  var Position;
71
109
  (function (Position) {
72
110
  Position["Left"] = "left";
@@ -143,12 +181,27 @@ const isEdgeBase = (element) => 'id' in element && 'source' in element && 'targe
143
181
  const isNodeBase = (element) => 'id' in element && 'position' in element && !('source' in element) && !('target' in element);
144
182
  const isInternalNodeBase = (element) => 'id' in element && 'internals' in element && !('source' in element) && !('target' in element);
145
183
  /**
146
- * Pass in a node, and get connected nodes where edge.source === node.id
184
+ * This util is used to tell you what nodes, if any, are connected to the given node
185
+ * as the _target_ of an edge.
147
186
  * @public
148
187
  * @param node - The node to get the connected nodes from
149
188
  * @param nodes - The array of all nodes
150
189
  * @param edges - The array of all edges
151
190
  * @returns An array of nodes that are connected over eges where the source is the given node
191
+ *
192
+ * @example
193
+ * ```ts
194
+ *import { getOutgoers } from '@xyflow/react';
195
+ *
196
+ *const nodes = [];
197
+ *const edges = [];
198
+ *
199
+ *const outgoers = getOutgoers(
200
+ * { id: '1', position: { x: 0, y: 0 }, data: { label: 'node' } },
201
+ * nodes,
202
+ * edges,
203
+ *);
204
+ *```
152
205
  */
153
206
  const getOutgoers = (node, nodes, edges) => {
154
207
  if (!node.id) {
@@ -163,12 +216,27 @@ const getOutgoers = (node, nodes, edges) => {
163
216
  return nodes.filter((n) => outgoerIds.has(n.id));
164
217
  };
165
218
  /**
166
- * Pass in a node, and get connected nodes where edge.target === node.id
219
+ * This util is used to tell you what nodes, if any, are connected to the given node
220
+ * as the _source_ of an edge.
167
221
  * @public
168
222
  * @param node - The node to get the connected nodes from
169
223
  * @param nodes - The array of all nodes
170
224
  * @param edges - The array of all edges
171
225
  * @returns An array of nodes that are connected over eges where the target is the given node
226
+ *
227
+ * @example
228
+ * ```ts
229
+ *import { getIncomers } from '@xyflow/react';
230
+ *
231
+ *const nodes = [];
232
+ *const edges = [];
233
+ *
234
+ *const incomers = getIncomers(
235
+ * { id: '1', position: { x: 0, y: 0 }, data: { label: 'node' } },
236
+ * nodes,
237
+ * edges,
238
+ *);
239
+ *```
172
240
  */
173
241
  const getIncomers = (node, nodes, edges) => {
174
242
  if (!node.id) {
@@ -193,12 +261,40 @@ const getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {
193
261
  };
194
262
  };
195
263
  /**
196
- * Internal function for determining a bounding box that contains all given nodes in an array.
264
+ * Returns the bounding box that contains all the given nodes in an array. This can
265
+ * be useful when combined with [`getViewportForBounds`](/api-reference/utils/get-viewport-for-bounds)
266
+ * to calculate the correct transform to fit the given nodes in a viewport.
197
267
  * @public
198
268
  * @remarks Useful when combined with {@link getViewportForBounds} to calculate the correct transform to fit the given nodes in a viewport.
199
269
  * @param nodes - Nodes to calculate the bounds for
200
270
  * @param params.nodeOrigin - Origin of the nodes: [0, 0] - top left, [0.5, 0.5] - center
201
271
  * @returns Bounding box enclosing all nodes
272
+ *
273
+ * @remarks This function was previously called `getRectOfNodes`
274
+ *
275
+ * @example
276
+ * ```js
277
+ *import { getNodesBounds } from '@xyflow/react';
278
+ *
279
+ *const nodes = [
280
+ * {
281
+ * id: 'a',
282
+ * position: { x: 0, y: 0 },
283
+ * data: { label: 'a' },
284
+ * width: 50,
285
+ * height: 25,
286
+ * },
287
+ * {
288
+ * id: 'b',
289
+ * position: { x: 100, y: 100 },
290
+ * data: { label: 'b' },
291
+ * width: 50,
292
+ * height: 25,
293
+ * },
294
+ *];
295
+ *
296
+ *const bounds = getNodesBounds(nodes);
297
+ *```
202
298
  */
203
299
  const getNodesBounds = (nodes, params = { nodeOrigin: [0, 0], nodeLookup: undefined }) => {
204
300
  if (process.env.NODE_ENV === 'development' && !params.nodeLookup) {
@@ -267,10 +363,30 @@ excludeNonSelectableNodes = false) => {
267
363
  return visibleNodes;
268
364
  };
269
365
  /**
270
- * Get all connecting edges for a given set of nodes
366
+ * This utility filters an array of edges, keeping only those where either the source or target
367
+ * node is present in the given array of nodes.
368
+ * @public
271
369
  * @param nodes - Nodes you want to get the connected edges for
272
370
  * @param edges - All edges
273
371
  * @returns Array of edges that connect any of the given nodes with each other
372
+ *
373
+ * @example
374
+ * ```js
375
+ *import { getConnectedEdges } from '@xyflow/react';
376
+ *
377
+ *const nodes = [
378
+ * { id: 'a', position: { x: 0, y: 0 } },
379
+ * { id: 'b', position: { x: 100, y: 0 } },
380
+ *];
381
+ *
382
+ *const edges = [
383
+ * { id: 'a->c', source: 'a', target: 'c' },
384
+ * { id: 'c->d', source: 'c', target: 'd' },
385
+ *];
386
+ *
387
+ *const connectedEdges = getConnectedEdges(nodes, edges);
388
+ * // => [{ id: 'a->c', source: 'a', target: 'c' }]
389
+ *```
274
390
  */
275
391
  const getConnectedEdges = (nodes, edges) => {
276
392
  const nodeIds = new Set();
@@ -515,8 +631,8 @@ const rendererPointToPoint = ({ x, y }, [tx, ty, tScale]) => {
515
631
  * @returns A transforned {@link Viewport} that encloses the given bounds which you can pass to e.g. {@link setViewport}
516
632
  * @example
517
633
  * const { x, y, zoom } = getViewportForBounds(
518
- { x: 0, y: 0, width: 100, height: 100},
519
- 1200, 800, 0.5, 2);
634
+ *{ x: 0, y: 0, width: 100, height: 100},
635
+ *1200, 800, 0.5, 2);
520
636
  */
521
637
  const getViewportForBounds = (bounds, width, height, minZoom, maxZoom, padding) => {
522
638
  const xZoom = width / (bounds.width * (1 + padding));
@@ -611,9 +727,11 @@ const getEventPosition = (event, bounds) => {
611
727
  y: evtY - (bounds?.top ?? 0),
612
728
  };
613
729
  };
614
- // The handle bounds are calculated relative to the node element.
615
- // We store them in the internals object of the node in order to avoid
616
- // unnecessary recalculations.
730
+ /*
731
+ * The handle bounds are calculated relative to the node element.
732
+ * We store them in the internals object of the node in order to avoid
733
+ * unnecessary recalculations.
734
+ */
617
735
  const getHandleBounds = (type, nodeElement, nodeBounds, zoom, nodeId) => {
618
736
  const handles = nodeElement.querySelectorAll(`.${type}`);
619
737
  if (!handles || !handles.length) {
@@ -634,8 +752,10 @@ const getHandleBounds = (type, nodeElement, nodeBounds, zoom, nodeId) => {
634
752
  };
635
753
 
636
754
  function getBezierEdgeCenter({ sourceX, sourceY, targetX, targetY, sourceControlX, sourceControlY, targetControlX, targetControlY, }) {
637
- // cubic bezier t=0.5 mid point, not the actual mid point, but easy to calculate
638
- // https://stackoverflow.com/questions/67516101/how-to-find-distance-mid-point-of-bezier-curve
755
+ /*
756
+ * cubic bezier t=0.5 mid point, not the actual mid point, but easy to calculate
757
+ * https://stackoverflow.com/questions/67516101/how-to-find-distance-mid-point-of-bezier-curve
758
+ */
639
759
  const centerX = sourceX * 0.125 + sourceControlX * 0.375 + targetControlX * 0.375 + targetX * 0.125;
640
760
  const centerY = sourceY * 0.125 + sourceControlY * 0.375 + targetControlY * 0.375 + targetY * 0.125;
641
761
  const offsetX = Math.abs(centerX - sourceX);
@@ -661,7 +781,9 @@ function getControlWithCurvature({ pos, x1, y1, x2, y2, c }) {
661
781
  }
662
782
  }
663
783
  /**
664
- * Get a bezier path from source to target handle
784
+ * The `getBezierPath` util returns everything you need to render a bezier edge
785
+ *between two nodes.
786
+ * @public
665
787
  * @param params.sourceX - The x position of the source handle
666
788
  * @param params.sourceY - The y position of the source handle
667
789
  * @param params.sourcePosition - The position of the source handle (default: Position.Bottom)
@@ -671,17 +793,22 @@ function getControlWithCurvature({ pos, x1, y1, x2, y2, c }) {
671
793
  * @param params.curvature - The curvature of the bezier edge
672
794
  * @returns A path string you can use in an SVG, the labelX and labelY position (center of path) and offsetX, offsetY between source handle and label
673
795
  * @example
796
+ * ```js
674
797
  * const source = { x: 0, y: 20 };
675
- const target = { x: 150, y: 100 };
676
-
677
- const [path, labelX, labelY, offsetX, offsetY] = getBezierPath({
678
- sourceX: source.x,
679
- sourceY: source.y,
680
- sourcePosition: Position.Right,
681
- targetX: target.x,
682
- targetY: target.y,
683
- targetPosition: Position.Left,
684
- });
798
+ * const target = { x: 150, y: 100 };
799
+ *
800
+ * const [path, labelX, labelY, offsetX, offsetY] = getBezierPath({
801
+ * sourceX: source.x,
802
+ * sourceY: source.y,
803
+ * sourcePosition: Position.Right,
804
+ * targetX: target.x,
805
+ * targetY: target.y,
806
+ * targetPosition: Position.Left,
807
+ *});
808
+ *```
809
+ *
810
+ * @remarks This function returns a tuple (aka a fixed-size array) to make it easier to
811
+ *work with multiple edge paths at once.
685
812
  */
686
813
  function getBezierPath({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, curvature = 0.25, }) {
687
814
  const [sourceControlX, sourceControlY] = getControlWithCurvature({
@@ -759,12 +886,16 @@ const connectionExists = (edge, edges) => {
759
886
  (el.targetHandle === edge.targetHandle || (!el.targetHandle && !edge.targetHandle)));
760
887
  };
761
888
  /**
762
- * This util is a convenience function to add a new Edge to an array of edges
763
- * @remarks It also performs some validation to make sure you don't add an invalid edge or duplicate an existing one.
889
+ * This util is a convenience function to add a new Edge to an array of edges. It also performs some validation to make sure you don't add an invalid edge or duplicate an existing one.
764
890
  * @public
765
891
  * @param edgeParams - Either an Edge or a Connection you want to add
766
892
  * @param edges - The array of all current edges
767
893
  * @returns A new array of edges with the new edge added
894
+ *
895
+ * @remarks If an edge with the same `target` and `source` already exists (and the same
896
+ *`targetHandle` and `sourceHandle` if those are set), then this util won't add
897
+ *a new edge even if the `id` property is different.
898
+ *
768
899
  */
769
900
  const addEdge = (edgeParams, edges) => {
770
901
  if (!edgeParams.source || !edgeParams.target) {
@@ -793,12 +924,21 @@ const addEdge = (edgeParams, edges) => {
793
924
  return edges.concat(edge);
794
925
  };
795
926
  /**
796
- * A handy utility to reconnect an existing edge with new properties
927
+ * A handy utility to update an existing [`Edge`](/api-reference/types/edge) with new properties.
928
+ *This searches your edge array for an edge with a matching `id` and updates its
929
+ *properties with the connection you provide.
930
+ * @public
797
931
  * @param oldEdge - The edge you want to update
798
932
  * @param newConnection - The new connection you want to update the edge with
799
933
  * @param edges - The array of all current edges
800
934
  * @param options.shouldReplaceId - should the id of the old edge be replaced with the new connection id
801
935
  * @returns the updated edges array
936
+ *
937
+ * @example
938
+ * ```js
939
+ *const onReconnect = useCallback(
940
+ * (oldEdge: Edge, newConnection: Connection) => setEdges((els) => reconnectEdge(oldEdge, newConnection, els)),[]);
941
+ *```
802
942
  */
803
943
  const reconnectEdge = (oldEdge, newConnection, edges, options = { shouldReplaceId: true }) => {
804
944
  const { id: oldEdgeId, ...rest } = oldEdge;
@@ -824,24 +964,28 @@ const reconnectEdge = (oldEdge, newConnection, edges, options = { shouldReplaceI
824
964
  };
825
965
 
826
966
  /**
827
- * Get a straight path from source to target handle
967
+ * Calculates the straight line path between two points.
968
+ * @public
828
969
  * @param params.sourceX - The x position of the source handle
829
970
  * @param params.sourceY - The y position of the source handle
830
971
  * @param params.targetX - The x position of the target handle
831
972
  * @param params.targetY - The y position of the target handle
832
973
  * @returns A path string you can use in an SVG, the labelX and labelY position (center of path) and offsetX, offsetY between source handle and label
833
974
  * @example
975
+ * ```js
834
976
  * const source = { x: 0, y: 20 };
835
- const target = { x: 150, y: 100 };
836
-
837
- const [path, labelX, labelY, offsetX, offsetY] = getStraightPath({
838
- sourceX: source.x,
839
- sourceY: source.y,
840
- sourcePosition: Position.Right,
841
- targetX: target.x,
842
- targetY: target.y,
843
- targetPosition: Position.Left,
844
- });
977
+ * const target = { x: 150, y: 100 };
978
+ *
979
+ * const [path, labelX, labelY, offsetX, offsetY] = getStraightPath({
980
+ * sourceX: source.x,
981
+ * sourceY: source.y,
982
+ * sourcePosition: Position.Right,
983
+ * targetX: target.x,
984
+ * targetY: target.y,
985
+ * targetPosition: Position.Left,
986
+ * });
987
+ * ```
988
+ * @remarks This function returns a tuple (aka a fixed-size array) to make it easier to work with multiple edge paths at once.
845
989
  */
846
990
  function getStraightPath({ sourceX, sourceY, targetX, targetY, }) {
847
991
  const [labelX, labelY, offsetX, offsetY] = getEdgeCenter({
@@ -866,8 +1010,10 @@ const getDirection = ({ source, sourcePosition = Position.Bottom, target, }) =>
866
1010
  return source.y < target.y ? { x: 0, y: 1 } : { x: 0, y: -1 };
867
1011
  };
868
1012
  const distance = (a, b) => Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
869
- // ith this function we try to mimic a orthogonal edge routing behaviour
870
- // It's not as good as a real orthogonal edge routing but it's faster and good enough as a default for step and smooth step edges
1013
+ /*
1014
+ * ith this function we try to mimic a orthogonal edge routing behaviour
1015
+ * It's not as good as a real orthogonal edge routing but it's faster and good enough as a default for step and smooth step edges
1016
+ */
871
1017
  function getPoints({ source, sourcePosition = Position.Bottom, target, targetPosition = Position.Top, center, offset, }) {
872
1018
  const sourceDir = handleDirections[sourcePosition];
873
1019
  const targetDir = handleDirections[targetPosition];
@@ -894,16 +1040,20 @@ function getPoints({ source, sourcePosition = Position.Bottom, target, targetPos
894
1040
  if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {
895
1041
  centerX = center.x ?? defaultCenterX;
896
1042
  centerY = center.y ?? defaultCenterY;
897
- // --->
898
- // |
899
- // >---
1043
+ /*
1044
+ * --->
1045
+ * |
1046
+ * >---
1047
+ */
900
1048
  const verticalSplit = [
901
1049
  { x: centerX, y: sourceGapped.y },
902
1050
  { x: centerX, y: targetGapped.y },
903
1051
  ];
904
- // |
905
- // ---
906
- // |
1052
+ /*
1053
+ * |
1054
+ * ---
1055
+ * |
1056
+ */
907
1057
  const horizontalSplit = [
908
1058
  { x: sourceGapped.x, y: centerY },
909
1059
  { x: targetGapped.x, y: centerY },
@@ -992,7 +1142,10 @@ function getBend(a, b, c, size) {
992
1142
  return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`;
993
1143
  }
994
1144
  /**
995
- * Get a smooth step path from source to target handle
1145
+ * The `getSmoothStepPath` util returns everything you need to render a stepped path
1146
+ *between two nodes. The `borderRadius` property can be used to choose how rounded
1147
+ *the corners of those steps are.
1148
+ * @public
996
1149
  * @param params.sourceX - The x position of the source handle
997
1150
  * @param params.sourceY - The y position of the source handle
998
1151
  * @param params.sourcePosition - The position of the source handle (default: Position.Bottom)
@@ -1001,17 +1154,20 @@ function getBend(a, b, c, size) {
1001
1154
  * @param params.targetPosition - The position of the target handle (default: Position.Top)
1002
1155
  * @returns A path string you can use in an SVG, the labelX and labelY position (center of path) and offsetX, offsetY between source handle and label
1003
1156
  * @example
1157
+ * ```js
1004
1158
  * const source = { x: 0, y: 20 };
1005
- const target = { x: 150, y: 100 };
1006
-
1007
- const [path, labelX, labelY, offsetX, offsetY] = getSmoothStepPath({
1008
- sourceX: source.x,
1009
- sourceY: source.y,
1010
- sourcePosition: Position.Right,
1011
- targetX: target.x,
1012
- targetY: target.y,
1013
- targetPosition: Position.Left,
1014
- });
1159
+ * const target = { x: 150, y: 100 };
1160
+ *
1161
+ * const [path, labelX, labelY, offsetX, offsetY] = getSmoothStepPath({
1162
+ * sourceX: source.x,
1163
+ * sourceY: source.y,
1164
+ * sourcePosition: Position.Right,
1165
+ * targetX: target.x,
1166
+ * targetY: target.y,
1167
+ * targetPosition: Position.Left,
1168
+ * });
1169
+ * ```
1170
+ * @remarks This function returns a tuple (aka a fixed-size array) to make it easier to work with multiple edge paths at once.
1015
1171
  */
1016
1172
  function getSmoothStepPath({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, borderRadius = 5, centerX, centerY, offset = 20, }) {
1017
1173
  const [points, labelX, labelY, offsetX, offsetY] = getPoints({
@@ -1162,8 +1318,10 @@ function getNodeToolbarTransform(nodeRect, viewport, position, offset, align) {
1162
1318
  else if (align === 'end') {
1163
1319
  alignmentOffset = 1;
1164
1320
  }
1165
- // position === Position.Top
1166
- // we set the x any y position of the toolbar based on the nodes position
1321
+ /*
1322
+ * position === Position.Top
1323
+ * we set the x any y position of the toolbar based on the nodes position
1324
+ */
1167
1325
  let pos = [
1168
1326
  (nodeRect.x + nodeRect.width * alignmentOffset) * viewport.zoom + viewport.x,
1169
1327
  nodeRect.y * viewport.zoom + viewport.y - offset,
@@ -1362,8 +1520,10 @@ function handleExpandParent(children, nodeLookup, parentLookup, nodeOrigin = [0,
1362
1520
  y: parent.position.y - yChange + heightChange,
1363
1521
  },
1364
1522
  });
1365
- // We move all child nodes in the oppsite direction
1366
- // so the x,y changes of the parent do not move the children
1523
+ /*
1524
+ * We move all child nodes in the oppsite direction
1525
+ * so the x,y changes of the parent do not move the children
1526
+ */
1367
1527
  parentLookup.get(parentId)?.forEach((childNode) => {
1368
1528
  if (!children.some((child) => child.id === childNode.id)) {
1369
1529
  changes.push({
@@ -1501,9 +1661,11 @@ async function panBy({ delta, panZoom, transform, translateExtent, width, height
1501
1661
  * @param handleId handleId of the conneciton
1502
1662
  */
1503
1663
  function addConnectionToLookup(type, connection, connectionKey, connectionLookup, nodeId, handleId) {
1504
- // We add the connection to the connectionLookup at the following keys
1505
- // 1. nodeId, 2. nodeId-type, 3. nodeId-type-handleId
1506
- // If the key already exists, we add the connection to the existing map
1664
+ /*
1665
+ * We add the connection to the connectionLookup at the following keys
1666
+ * 1. nodeId, 2. nodeId-type, 3. nodeId-type-handleId
1667
+ * If the key already exists, we add the connection to the existing map
1668
+ */
1507
1669
  let key = nodeId;
1508
1670
  const nodeMap = connectionLookup.get(key) || new Map();
1509
1671
  connectionLookup.set(key, nodeMap.set(connectionKey, connection));
@@ -1604,9 +1766,11 @@ function getDragItems(nodeLookup, nodesDraggable, mousePos, nodeId) {
1604
1766
  }
1605
1767
  return dragItems;
1606
1768
  }
1607
- // returns two params:
1608
- // 1. the dragged node (or the first of the list, if we are dragging a node selection)
1609
- // 2. array of selected nodes (for multi selections)
1769
+ /*
1770
+ * returns two params:
1771
+ * 1. the dragged node (or the first of the list, if we are dragging a node selection)
1772
+ * 2. array of selected nodes (for multi selections)
1773
+ */
1610
1774
  function getEventHandlerParams({ nodeId, dragItems, nodeLookup, dragging = true, }) {
1611
1775
  const nodesFromDragItems = [];
1612
1776
  for (const [id, dragItem] of dragItems) {
@@ -1660,16 +1824,20 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
1660
1824
  }
1661
1825
  for (const [id, dragItem] of dragItems) {
1662
1826
  if (!nodeLookup.has(id)) {
1663
- // if the node is not in the nodeLookup anymore, it was probably deleted while dragging
1664
- // and we don't need to update it anymore
1827
+ /*
1828
+ * if the node is not in the nodeLookup anymore, it was probably deleted while dragging
1829
+ * and we don't need to update it anymore
1830
+ */
1665
1831
  continue;
1666
1832
  }
1667
1833
  let nextPosition = { x: x - dragItem.distance.x, y: y - dragItem.distance.y };
1668
1834
  if (snapToGrid) {
1669
1835
  nextPosition = snapPosition(nextPosition, snapGrid);
1670
1836
  }
1671
- // if there is selection with multiple nodes and a node extent is set, we need to adjust the node extent for each node
1672
- // based on its position so that the node stays at it's position relative to the selection.
1837
+ /*
1838
+ * if there is selection with multiple nodes and a node extent is set, we need to adjust the node extent for each node
1839
+ * based on its position so that the node stays at it's position relative to the selection.
1840
+ */
1673
1841
  let adjustedNodeExtent = [
1674
1842
  [nodeExtent[0][0], nodeExtent[0][1]],
1675
1843
  [nodeExtent[1][0], nodeExtent[1][1]],
@@ -1719,7 +1887,12 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
1719
1887
  if (!containerBounds) {
1720
1888
  return;
1721
1889
  }
1722
- const { transform, panBy, autoPanSpeed } = getStoreItems();
1890
+ const { transform, panBy, autoPanSpeed, autoPanOnNodeDrag } = getStoreItems();
1891
+ if (!autoPanOnNodeDrag) {
1892
+ autoPanStarted = false;
1893
+ cancelAnimationFrame(autoPanId);
1894
+ return;
1895
+ }
1723
1896
  const [xMovement, yMovement] = calcAutoPan(mousePosition, containerBounds, autoPanSpeed);
1724
1897
  if (xMovement !== 0 || yMovement !== 0) {
1725
1898
  lastPos.x = (lastPos.x ?? 0) - xMovement / transform[2];
@@ -1859,8 +2032,10 @@ function getNodesWithinDistance(position, nodeLookup, distance) {
1859
2032
  }
1860
2033
  return nodes;
1861
2034
  }
1862
- // this distance is used for the area around the user pointer
1863
- // while doing a connection for finding the closest nodes
2035
+ /*
2036
+ * this distance is used for the area around the user pointer
2037
+ * while doing a connection for finding the closest nodes
2038
+ */
1864
2039
  const ADDITIONAL_DISTANCE = 250;
1865
2040
  function getClosestHandle(position, connectionRadius, nodeLookup, fromHandle) {
1866
2041
  let closestHandles = [];
@@ -2028,8 +2203,10 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
2028
2203
  toPosition: isValid && result.toHandle ? result.toHandle.position : oppositePosition[fromHandle.position],
2029
2204
  toNode: result.toHandle ? nodeLookup.get(result.toHandle.nodeId) : null,
2030
2205
  };
2031
- // we don't want to trigger an update when the connection
2032
- // is snapped to the same handle as before
2206
+ /*
2207
+ * we don't want to trigger an update when the connection
2208
+ * is snapped to the same handle as before
2209
+ */
2033
2210
  if (isValid &&
2034
2211
  closestHandle &&
2035
2212
  previousConnection.toHandle &&
@@ -2048,8 +2225,10 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
2048
2225
  if ((closestHandle || handleDomNode) && connection && isValid) {
2049
2226
  onConnect?.(connection);
2050
2227
  }
2051
- // it's important to get a fresh reference from the store here
2052
- // in order to get the latest state of onConnectEnd
2228
+ /*
2229
+ * it's important to get a fresh reference from the store here
2230
+ * in order to get the latest state of onConnectEnd
2231
+ */
2053
2232
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2054
2233
  const { inProgress, ...connectionState } = previousConnection;
2055
2234
  const finalConnectionState = {
@@ -2084,8 +2263,10 @@ function isValidHandle(event, { handle, connectionMode, fromNodeId, fromHandleId
2084
2263
  : null;
2085
2264
  const { x, y } = getEventPosition(event);
2086
2265
  const handleBelow = doc.elementFromPoint(x, y);
2087
- // we always want to prioritize the handle below the mouse cursor over the closest distance handle,
2088
- // because it could be that the center of another handle is closer to the mouse pointer than the handle below the cursor
2266
+ /*
2267
+ * we always want to prioritize the handle below the mouse cursor over the closest distance handle,
2268
+ * because it could be that the center of another handle is closer to the mouse pointer than the handle below the cursor
2269
+ */
2089
2270
  const handleToCheck = handleBelow?.classList.contains(`${lib}-flow__handle`) ? handleBelow : handleDomNode;
2090
2271
  const result = {
2091
2272
  handleDomNode: handleToCheck,
@@ -2236,8 +2417,10 @@ function createPanOnScrollHandler({ zoomPanValues, noWheelClassName, d3Selection
2236
2417
  d3Zoom.scaleTo(d3Selection, zoom, point, event);
2237
2418
  return;
2238
2419
  }
2239
- // increase scroll speed in firefox
2240
- // firefox: deltaMode === 1; chrome: deltaMode === 0
2420
+ /*
2421
+ * increase scroll speed in firefox
2422
+ * firefox: deltaMode === 1; chrome: deltaMode === 0
2423
+ */
2241
2424
  const deltaNormalize = event.deltaMode === 1 ? 20 : 1;
2242
2425
  let deltaX = panOnScrollMode === PanOnScrollMode.Vertical ? 0 : event.deltaX * deltaNormalize;
2243
2426
  let deltaY = panOnScrollMode === PanOnScrollMode.Horizontal ? 0 : event.deltaY * deltaNormalize;
@@ -2251,9 +2434,11 @@ function createPanOnScrollHandler({ zoomPanValues, noWheelClassName, d3Selection
2251
2434
  { internal: true });
2252
2435
  const nextViewport = transformToViewport(d3Selection.property('__zoom'));
2253
2436
  clearTimeout(zoomPanValues.panScrollTimeout);
2254
- // for pan on scroll we need to handle the event calls on our own
2255
- // we can't use the start, zoom and end events from d3-zoom
2256
- // because start and move gets called on every scroll event and not once at the beginning
2437
+ /*
2438
+ * for pan on scroll we need to handle the event calls on our own
2439
+ * we can't use the start, zoom and end events from d3-zoom
2440
+ * because start and move gets called on every scroll event and not once at the beginning
2441
+ */
2257
2442
  if (!zoomPanValues.isPanScrolling) {
2258
2443
  zoomPanValues.isPanScrolling = true;
2259
2444
  onPanZoomStart?.(event, nextViewport);
@@ -2488,9 +2673,11 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
2488
2673
  lib,
2489
2674
  });
2490
2675
  d3ZoomInstance.filter(filter);
2491
- // We cannot add zoomOnDoubleClick to the filter above because
2492
- // double tapping on touch screens circumvents the filter and
2493
- // dblclick.zoom is fired on the selection directly
2676
+ /*
2677
+ * We cannot add zoomOnDoubleClick to the filter above because
2678
+ * double tapping on touch screens circumvents the filter and
2679
+ * dblclick.zoom is fired on the selection directly
2680
+ */
2494
2681
  if (zoomOnDoubleClick) {
2495
2682
  d3Selection.on('dblclick.zoom', d3DblClickZoomHandler);
2496
2683
  }
@@ -2572,6 +2759,11 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
2572
2759
  };
2573
2760
  }
2574
2761
 
2762
+ /**
2763
+ * Used to determine the variant of the resize control
2764
+ *
2765
+ * @public
2766
+ */
2575
2767
  var ResizeControlVariant;
2576
2768
  (function (ResizeControlVariant) {
2577
2769
  ResizeControlVariant["Line"] = "line";
@@ -2867,8 +3059,10 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
2867
3059
  parentNode = nodeLookup.get(node.parentId);
2868
3060
  parentExtent = parentNode && node.extent === 'parent' ? nodeToParentExtent(parentNode) : undefined;
2869
3061
  }
2870
- // Collect all child nodes to correct their relative positions when top/left changes
2871
- // Determine largest minimal extent the parent node is allowed to resize to
3062
+ /*
3063
+ * Collect all child nodes to correct their relative positions when top/left changes
3064
+ * Determine largest minimal extent the parent node is allowed to resize to
3065
+ */
2872
3066
  childNodes = [];
2873
3067
  childExtent = undefined;
2874
3068
  for (const [childId, child] of nodeLookup) {
@@ -2922,8 +3116,10 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
2922
3116
  change.y = isYPosChange ? y : prevValues.y;
2923
3117
  prevValues.x = change.x;
2924
3118
  prevValues.y = change.y;
2925
- // when top/left changes, correct the relative positions of child nodes
2926
- // so that they stay in the same position
3119
+ /*
3120
+ * when top/left changes, correct the relative positions of child nodes
3121
+ * so that they stay in the same position
3122
+ */
2927
3123
  if (childNodes.length > 0) {
2928
3124
  const xChange = x - prevX;
2929
3125
  const yChange = y - prevY;