@xyflow/system 0.0.49 → 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.
- package/dist/esm/index.js +339 -133
- package/dist/esm/index.mjs +339 -133
- package/dist/esm/types/changes.d.ts +12 -1
- package/dist/esm/types/changes.d.ts.map +1 -1
- package/dist/esm/types/edges.d.ts +37 -4
- package/dist/esm/types/edges.d.ts.map +1 -1
- package/dist/esm/types/general.d.ts +63 -0
- package/dist/esm/types/general.d.ts.map +1 -1
- package/dist/esm/types/handles.d.ts +9 -5
- package/dist/esm/types/handles.d.ts.map +1 -1
- package/dist/esm/types/nodes.d.ts +29 -9
- package/dist/esm/types/nodes.d.ts.map +1 -1
- package/dist/esm/types/utils.d.ts +22 -0
- package/dist/esm/types/utils.d.ts.map +1 -1
- package/dist/esm/utils/dom.d.ts.map +1 -1
- package/dist/esm/utils/edges/bezier-edge.d.ts +18 -11
- package/dist/esm/utils/edges/bezier-edge.d.ts.map +1 -1
- package/dist/esm/utils/edges/general.d.ts +16 -3
- package/dist/esm/utils/edges/general.d.ts.map +1 -1
- package/dist/esm/utils/edges/smoothstep-edge.d.ts +17 -11
- package/dist/esm/utils/edges/smoothstep-edge.d.ts.map +1 -1
- package/dist/esm/utils/edges/straight-edge.d.ts +15 -11
- package/dist/esm/utils/edges/straight-edge.d.ts.map +1 -1
- package/dist/esm/utils/general.d.ts +2 -2
- package/dist/esm/utils/graph.d.ts +82 -4
- package/dist/esm/utils/graph.d.ts.map +1 -1
- package/dist/esm/utils/node-toolbar.d.ts.map +1 -1
- package/dist/esm/utils/store.d.ts.map +1 -1
- package/dist/esm/xydrag/XYDrag.d.ts.map +1 -1
- package/dist/esm/xydrag/utils.d.ts.map +1 -1
- package/dist/esm/xyhandle/XYHandle.d.ts.map +1 -1
- package/dist/esm/xyhandle/types.d.ts.map +1 -1
- package/dist/esm/xyhandle/utils.d.ts.map +1 -1
- package/dist/esm/xypanzoom/XYPanZoom.d.ts.map +1 -1
- package/dist/esm/xypanzoom/eventhandler.d.ts.map +1 -1
- package/dist/esm/xyresizer/XYResizer.d.ts.map +1 -1
- package/dist/esm/xyresizer/types.d.ts +15 -0
- package/dist/esm/xyresizer/types.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/types/changes.d.ts +12 -1
- package/dist/umd/types/changes.d.ts.map +1 -1
- package/dist/umd/types/edges.d.ts +37 -4
- package/dist/umd/types/edges.d.ts.map +1 -1
- package/dist/umd/types/general.d.ts +63 -0
- package/dist/umd/types/general.d.ts.map +1 -1
- package/dist/umd/types/handles.d.ts +9 -5
- package/dist/umd/types/handles.d.ts.map +1 -1
- package/dist/umd/types/nodes.d.ts +29 -9
- package/dist/umd/types/nodes.d.ts.map +1 -1
- package/dist/umd/types/utils.d.ts +22 -0
- package/dist/umd/types/utils.d.ts.map +1 -1
- package/dist/umd/utils/dom.d.ts.map +1 -1
- package/dist/umd/utils/edges/bezier-edge.d.ts +18 -11
- package/dist/umd/utils/edges/bezier-edge.d.ts.map +1 -1
- package/dist/umd/utils/edges/general.d.ts +16 -3
- package/dist/umd/utils/edges/general.d.ts.map +1 -1
- package/dist/umd/utils/edges/smoothstep-edge.d.ts +17 -11
- package/dist/umd/utils/edges/smoothstep-edge.d.ts.map +1 -1
- package/dist/umd/utils/edges/straight-edge.d.ts +15 -11
- package/dist/umd/utils/edges/straight-edge.d.ts.map +1 -1
- package/dist/umd/utils/general.d.ts +2 -2
- package/dist/umd/utils/graph.d.ts +82 -4
- package/dist/umd/utils/graph.d.ts.map +1 -1
- package/dist/umd/utils/node-toolbar.d.ts.map +1 -1
- package/dist/umd/utils/store.d.ts.map +1 -1
- package/dist/umd/xydrag/XYDrag.d.ts.map +1 -1
- package/dist/umd/xydrag/utils.d.ts.map +1 -1
- package/dist/umd/xyhandle/XYHandle.d.ts.map +1 -1
- package/dist/umd/xyhandle/types.d.ts.map +1 -1
- package/dist/umd/xyhandle/utils.d.ts.map +1 -1
- package/dist/umd/xypanzoom/XYPanZoom.d.ts.map +1 -1
- package/dist/umd/xypanzoom/eventhandler.d.ts.map +1 -1
- package/dist/umd/xyresizer/XYResizer.d.ts.map +1 -1
- package/dist/umd/xyresizer/types.d.ts +15 -0
- package/dist/umd/xyresizer/types.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/esm/index.mjs
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
519
|
-
|
|
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
|
-
|
|
615
|
-
|
|
616
|
-
|
|
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
|
-
|
|
638
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
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
|
|
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
|
-
*
|
|
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
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
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
|
-
|
|
870
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
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
|
-
|
|
1166
|
-
|
|
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,
|
|
@@ -1293,11 +1451,15 @@ function updateChildNode(node, nodeLookup, parentLookup, options) {
|
|
|
1293
1451
|
const { positionAbsolute } = node.internals;
|
|
1294
1452
|
const positionChanged = x !== positionAbsolute.x || y !== positionAbsolute.y;
|
|
1295
1453
|
if (positionChanged || z !== node.internals.z) {
|
|
1296
|
-
node
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1454
|
+
// we create a new object to mark the node as updated
|
|
1455
|
+
nodeLookup.set(node.id, {
|
|
1456
|
+
...node,
|
|
1457
|
+
internals: {
|
|
1458
|
+
...node.internals,
|
|
1459
|
+
positionAbsolute: positionChanged ? { x, y } : positionAbsolute,
|
|
1460
|
+
z,
|
|
1461
|
+
},
|
|
1462
|
+
});
|
|
1301
1463
|
}
|
|
1302
1464
|
}
|
|
1303
1465
|
function calculateZ(node, selectedNodeZ) {
|
|
@@ -1358,8 +1520,10 @@ function handleExpandParent(children, nodeLookup, parentLookup, nodeOrigin = [0,
|
|
|
1358
1520
|
y: parent.position.y - yChange + heightChange,
|
|
1359
1521
|
},
|
|
1360
1522
|
});
|
|
1361
|
-
|
|
1362
|
-
|
|
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
|
+
*/
|
|
1363
1527
|
parentLookup.get(parentId)?.forEach((childNode) => {
|
|
1364
1528
|
if (!children.some((child) => child.id === childNode.id)) {
|
|
1365
1529
|
changes.push({
|
|
@@ -1406,54 +1570,60 @@ function updateNodeInternals(updates, nodeLookup, parentLookup, domNode, nodeOri
|
|
|
1406
1570
|
continue;
|
|
1407
1571
|
}
|
|
1408
1572
|
if (node.hidden) {
|
|
1409
|
-
node.
|
|
1410
|
-
...node
|
|
1411
|
-
|
|
1412
|
-
|
|
1573
|
+
nodeLookup.set(node.id, {
|
|
1574
|
+
...node,
|
|
1575
|
+
internals: {
|
|
1576
|
+
...node.internals,
|
|
1577
|
+
handleBounds: undefined,
|
|
1578
|
+
},
|
|
1579
|
+
});
|
|
1413
1580
|
updatedInternals = true;
|
|
1581
|
+
continue;
|
|
1414
1582
|
}
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
node
|
|
1432
|
-
|
|
1583
|
+
const dimensions = getDimensions(update.nodeElement);
|
|
1584
|
+
const dimensionChanged = node.measured.width !== dimensions.width || node.measured.height !== dimensions.height;
|
|
1585
|
+
const doUpdate = !!(dimensions.width &&
|
|
1586
|
+
dimensions.height &&
|
|
1587
|
+
(dimensionChanged || !node.internals.handleBounds || update.force));
|
|
1588
|
+
if (doUpdate) {
|
|
1589
|
+
const nodeBounds = update.nodeElement.getBoundingClientRect();
|
|
1590
|
+
const extent = isCoordinateExtent(node.extent) ? node.extent : nodeExtent;
|
|
1591
|
+
let { positionAbsolute } = node.internals;
|
|
1592
|
+
if (node.parentId && node.extent === 'parent') {
|
|
1593
|
+
positionAbsolute = clampPositionToParent(positionAbsolute, dimensions, nodeLookup.get(node.parentId));
|
|
1594
|
+
}
|
|
1595
|
+
else if (extent) {
|
|
1596
|
+
positionAbsolute = clampPosition(positionAbsolute, extent, dimensions);
|
|
1597
|
+
}
|
|
1598
|
+
const newNode = {
|
|
1599
|
+
...node,
|
|
1600
|
+
measured: dimensions,
|
|
1601
|
+
internals: {
|
|
1433
1602
|
...node.internals,
|
|
1434
1603
|
positionAbsolute,
|
|
1435
1604
|
handleBounds: {
|
|
1436
1605
|
source: getHandleBounds('source', update.nodeElement, nodeBounds, zoom, node.id),
|
|
1437
1606
|
target: getHandleBounds('target', update.nodeElement, nodeBounds, zoom, node.id),
|
|
1438
1607
|
},
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1608
|
+
},
|
|
1609
|
+
};
|
|
1610
|
+
nodeLookup.set(node.id, newNode);
|
|
1611
|
+
if (node.parentId) {
|
|
1612
|
+
updateChildNode(newNode, nodeLookup, parentLookup, { nodeOrigin });
|
|
1613
|
+
}
|
|
1614
|
+
updatedInternals = true;
|
|
1615
|
+
if (dimensionChanged) {
|
|
1616
|
+
changes.push({
|
|
1617
|
+
id: node.id,
|
|
1618
|
+
type: 'dimensions',
|
|
1619
|
+
dimensions,
|
|
1620
|
+
});
|
|
1621
|
+
if (node.expandParent && node.parentId) {
|
|
1622
|
+
parentExpandChildren.push({
|
|
1446
1623
|
id: node.id,
|
|
1447
|
-
|
|
1448
|
-
|
|
1624
|
+
parentId: node.parentId,
|
|
1625
|
+
rect: nodeToRect(newNode, nodeOrigin),
|
|
1449
1626
|
});
|
|
1450
|
-
if (node.expandParent && node.parentId) {
|
|
1451
|
-
parentExpandChildren.push({
|
|
1452
|
-
id: node.id,
|
|
1453
|
-
parentId: node.parentId,
|
|
1454
|
-
rect: nodeToRect(node, nodeOrigin),
|
|
1455
|
-
});
|
|
1456
|
-
}
|
|
1457
1627
|
}
|
|
1458
1628
|
}
|
|
1459
1629
|
}
|
|
@@ -1491,9 +1661,11 @@ async function panBy({ delta, panZoom, transform, translateExtent, width, height
|
|
|
1491
1661
|
* @param handleId handleId of the conneciton
|
|
1492
1662
|
*/
|
|
1493
1663
|
function addConnectionToLookup(type, connection, connectionKey, connectionLookup, nodeId, handleId) {
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
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
|
+
*/
|
|
1497
1669
|
let key = nodeId;
|
|
1498
1670
|
const nodeMap = connectionLookup.get(key) || new Map();
|
|
1499
1671
|
connectionLookup.set(key, nodeMap.set(connectionKey, connection));
|
|
@@ -1594,9 +1766,11 @@ function getDragItems(nodeLookup, nodesDraggable, mousePos, nodeId) {
|
|
|
1594
1766
|
}
|
|
1595
1767
|
return dragItems;
|
|
1596
1768
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
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
|
+
*/
|
|
1600
1774
|
function getEventHandlerParams({ nodeId, dragItems, nodeLookup, dragging = true, }) {
|
|
1601
1775
|
const nodesFromDragItems = [];
|
|
1602
1776
|
for (const [id, dragItem] of dragItems) {
|
|
@@ -1650,16 +1824,20 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1650
1824
|
}
|
|
1651
1825
|
for (const [id, dragItem] of dragItems) {
|
|
1652
1826
|
if (!nodeLookup.has(id)) {
|
|
1653
|
-
|
|
1654
|
-
|
|
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
|
+
*/
|
|
1655
1831
|
continue;
|
|
1656
1832
|
}
|
|
1657
1833
|
let nextPosition = { x: x - dragItem.distance.x, y: y - dragItem.distance.y };
|
|
1658
1834
|
if (snapToGrid) {
|
|
1659
1835
|
nextPosition = snapPosition(nextPosition, snapGrid);
|
|
1660
1836
|
}
|
|
1661
|
-
|
|
1662
|
-
|
|
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
|
+
*/
|
|
1663
1841
|
let adjustedNodeExtent = [
|
|
1664
1842
|
[nodeExtent[0][0], nodeExtent[0][1]],
|
|
1665
1843
|
[nodeExtent[1][0], nodeExtent[1][1]],
|
|
@@ -1709,7 +1887,12 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
|
|
|
1709
1887
|
if (!containerBounds) {
|
|
1710
1888
|
return;
|
|
1711
1889
|
}
|
|
1712
|
-
const { transform, panBy, autoPanSpeed } = getStoreItems();
|
|
1890
|
+
const { transform, panBy, autoPanSpeed, autoPanOnNodeDrag } = getStoreItems();
|
|
1891
|
+
if (!autoPanOnNodeDrag) {
|
|
1892
|
+
autoPanStarted = false;
|
|
1893
|
+
cancelAnimationFrame(autoPanId);
|
|
1894
|
+
return;
|
|
1895
|
+
}
|
|
1713
1896
|
const [xMovement, yMovement] = calcAutoPan(mousePosition, containerBounds, autoPanSpeed);
|
|
1714
1897
|
if (xMovement !== 0 || yMovement !== 0) {
|
|
1715
1898
|
lastPos.x = (lastPos.x ?? 0) - xMovement / transform[2];
|
|
@@ -1849,8 +2032,10 @@ function getNodesWithinDistance(position, nodeLookup, distance) {
|
|
|
1849
2032
|
}
|
|
1850
2033
|
return nodes;
|
|
1851
2034
|
}
|
|
1852
|
-
|
|
1853
|
-
|
|
2035
|
+
/*
|
|
2036
|
+
* this distance is used for the area around the user pointer
|
|
2037
|
+
* while doing a connection for finding the closest nodes
|
|
2038
|
+
*/
|
|
1854
2039
|
const ADDITIONAL_DISTANCE = 250;
|
|
1855
2040
|
function getClosestHandle(position, connectionRadius, nodeLookup, fromHandle) {
|
|
1856
2041
|
let closestHandles = [];
|
|
@@ -2018,8 +2203,10 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
|
|
|
2018
2203
|
toPosition: isValid && result.toHandle ? result.toHandle.position : oppositePosition[fromHandle.position],
|
|
2019
2204
|
toNode: result.toHandle ? nodeLookup.get(result.toHandle.nodeId) : null,
|
|
2020
2205
|
};
|
|
2021
|
-
|
|
2022
|
-
|
|
2206
|
+
/*
|
|
2207
|
+
* we don't want to trigger an update when the connection
|
|
2208
|
+
* is snapped to the same handle as before
|
|
2209
|
+
*/
|
|
2023
2210
|
if (isValid &&
|
|
2024
2211
|
closestHandle &&
|
|
2025
2212
|
previousConnection.toHandle &&
|
|
@@ -2038,8 +2225,10 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
|
|
|
2038
2225
|
if ((closestHandle || handleDomNode) && connection && isValid) {
|
|
2039
2226
|
onConnect?.(connection);
|
|
2040
2227
|
}
|
|
2041
|
-
|
|
2042
|
-
|
|
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
|
+
*/
|
|
2043
2232
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2044
2233
|
const { inProgress, ...connectionState } = previousConnection;
|
|
2045
2234
|
const finalConnectionState = {
|
|
@@ -2074,8 +2263,10 @@ function isValidHandle(event, { handle, connectionMode, fromNodeId, fromHandleId
|
|
|
2074
2263
|
: null;
|
|
2075
2264
|
const { x, y } = getEventPosition(event);
|
|
2076
2265
|
const handleBelow = doc.elementFromPoint(x, y);
|
|
2077
|
-
|
|
2078
|
-
|
|
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
|
+
*/
|
|
2079
2270
|
const handleToCheck = handleBelow?.classList.contains(`${lib}-flow__handle`) ? handleBelow : handleDomNode;
|
|
2080
2271
|
const result = {
|
|
2081
2272
|
handleDomNode: handleToCheck,
|
|
@@ -2226,8 +2417,10 @@ function createPanOnScrollHandler({ zoomPanValues, noWheelClassName, d3Selection
|
|
|
2226
2417
|
d3Zoom.scaleTo(d3Selection, zoom, point, event);
|
|
2227
2418
|
return;
|
|
2228
2419
|
}
|
|
2229
|
-
|
|
2230
|
-
|
|
2420
|
+
/*
|
|
2421
|
+
* increase scroll speed in firefox
|
|
2422
|
+
* firefox: deltaMode === 1; chrome: deltaMode === 0
|
|
2423
|
+
*/
|
|
2231
2424
|
const deltaNormalize = event.deltaMode === 1 ? 20 : 1;
|
|
2232
2425
|
let deltaX = panOnScrollMode === PanOnScrollMode.Vertical ? 0 : event.deltaX * deltaNormalize;
|
|
2233
2426
|
let deltaY = panOnScrollMode === PanOnScrollMode.Horizontal ? 0 : event.deltaY * deltaNormalize;
|
|
@@ -2241,9 +2434,11 @@ function createPanOnScrollHandler({ zoomPanValues, noWheelClassName, d3Selection
|
|
|
2241
2434
|
{ internal: true });
|
|
2242
2435
|
const nextViewport = transformToViewport(d3Selection.property('__zoom'));
|
|
2243
2436
|
clearTimeout(zoomPanValues.panScrollTimeout);
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
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
|
+
*/
|
|
2247
2442
|
if (!zoomPanValues.isPanScrolling) {
|
|
2248
2443
|
zoomPanValues.isPanScrolling = true;
|
|
2249
2444
|
onPanZoomStart?.(event, nextViewport);
|
|
@@ -2478,9 +2673,11 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
|
|
|
2478
2673
|
lib,
|
|
2479
2674
|
});
|
|
2480
2675
|
d3ZoomInstance.filter(filter);
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
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
|
+
*/
|
|
2484
2681
|
if (zoomOnDoubleClick) {
|
|
2485
2682
|
d3Selection.on('dblclick.zoom', d3DblClickZoomHandler);
|
|
2486
2683
|
}
|
|
@@ -2562,6 +2759,11 @@ function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExte
|
|
|
2562
2759
|
};
|
|
2563
2760
|
}
|
|
2564
2761
|
|
|
2762
|
+
/**
|
|
2763
|
+
* Used to determine the variant of the resize control
|
|
2764
|
+
*
|
|
2765
|
+
* @public
|
|
2766
|
+
*/
|
|
2565
2767
|
var ResizeControlVariant;
|
|
2566
2768
|
(function (ResizeControlVariant) {
|
|
2567
2769
|
ResizeControlVariant["Line"] = "line";
|
|
@@ -2857,8 +3059,10 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
|
|
|
2857
3059
|
parentNode = nodeLookup.get(node.parentId);
|
|
2858
3060
|
parentExtent = parentNode && node.extent === 'parent' ? nodeToParentExtent(parentNode) : undefined;
|
|
2859
3061
|
}
|
|
2860
|
-
|
|
2861
|
-
|
|
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
|
+
*/
|
|
2862
3066
|
childNodes = [];
|
|
2863
3067
|
childExtent = undefined;
|
|
2864
3068
|
for (const [childId, child] of nodeLookup) {
|
|
@@ -2912,8 +3116,10 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
|
|
|
2912
3116
|
change.y = isYPosChange ? y : prevValues.y;
|
|
2913
3117
|
prevValues.x = change.x;
|
|
2914
3118
|
prevValues.y = change.y;
|
|
2915
|
-
|
|
2916
|
-
|
|
3119
|
+
/*
|
|
3120
|
+
* when top/left changes, correct the relative positions of child nodes
|
|
3121
|
+
* so that they stay in the same position
|
|
3122
|
+
*/
|
|
2917
3123
|
if (childNodes.length > 0) {
|
|
2918
3124
|
const xChange = x - prevX;
|
|
2919
3125
|
const yChange = y - prevY;
|