react-cosmos-diagram 0.5.3 → 0.7.0
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/README.md +4 -2
- package/dist/esm/components/A11yDescriptions/index.d.ts.map +1 -1
- package/dist/esm/components/Background/LinePath.d.ts.map +1 -1
- package/dist/esm/components/Background/index.d.ts.map +1 -1
- package/dist/esm/components/Background/type.d.ts.map +1 -1
- package/dist/esm/components/DragBox/index.d.ts +1 -1
- package/dist/esm/components/DragBox/index.d.ts.map +1 -1
- package/dist/esm/components/Edges/Anchor.d.ts +1 -1
- package/dist/esm/components/Edges/Anchor.d.ts.map +1 -1
- package/dist/esm/components/Edges/BaseEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/BezierEdge.d.ts +2 -13
- package/dist/esm/components/Edges/BezierEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/EdgeLabel.d.ts.map +1 -1
- package/dist/esm/components/Edges/EdgeWrapper/index.d.ts.map +1 -1
- package/dist/esm/components/Edges/EdgeWrapper/type.d.ts +3 -10
- package/dist/esm/components/Edges/EdgeWrapper/type.d.ts.map +1 -1
- package/dist/esm/components/Edges/StepEdge.d.ts +2 -22
- package/dist/esm/components/Edges/StepEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/StraightEdge.d.ts +0 -7
- package/dist/esm/components/Edges/StraightEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/type.d.ts +8 -35
- package/dist/esm/components/Edges/type.d.ts.map +1 -1
- package/dist/esm/components/Node/NodeWrapper/index.d.ts +3 -3
- package/dist/esm/components/Node/NodeWrapper/index.d.ts.map +1 -1
- package/dist/esm/components/Node/NodeWrapper/type.d.ts +4 -1
- package/dist/esm/components/Node/NodeWrapper/type.d.ts.map +1 -1
- package/dist/esm/components/Node/index.d.ts.map +1 -1
- package/dist/esm/components/Node/type.d.ts +4 -36
- package/dist/esm/components/Node/type.d.ts.map +1 -1
- package/dist/esm/components/Node/utils.d.ts +0 -3
- package/dist/esm/components/Node/utils.d.ts.map +1 -1
- package/dist/esm/components/Port/index.d.ts +2 -2
- package/dist/esm/components/Port/index.d.ts.map +1 -1
- package/dist/esm/components/ReactDiagramProvider/index.d.ts.map +1 -1
- package/dist/esm/components/ReactDiagramProvider/type.d.ts +10 -8
- package/dist/esm/components/ReactDiagramProvider/type.d.ts.map +1 -1
- package/dist/esm/components/SelectionBox/index.d.ts +1 -1
- package/dist/esm/components/SelectionBox/index.d.ts.map +1 -1
- package/dist/esm/components/SelectionBox/type.d.ts +1 -1
- package/dist/esm/components/SelectionBox/type.d.ts.map +1 -1
- package/dist/esm/components/StoreUpdater/index.d.ts +2 -2
- package/dist/esm/components/StoreUpdater/index.d.ts.map +1 -1
- package/dist/esm/container/ConnectionLineRenderer/ConnectionPath.d.ts +1 -1
- package/dist/esm/container/ConnectionLineRenderer/ConnectionPath.d.ts.map +1 -1
- package/dist/esm/container/ConnectionLineRenderer/index.d.ts.map +1 -1
- package/dist/esm/container/ConnectionLineRenderer/type.d.ts +2 -2
- package/dist/esm/container/ConnectionLineRenderer/type.d.ts.map +1 -1
- package/dist/esm/container/DiagramRenderer/index.d.ts +3 -2
- package/dist/esm/container/DiagramRenderer/index.d.ts.map +1 -1
- package/dist/esm/container/DragSelection/index.d.ts +2 -2
- package/dist/esm/container/DragSelection/index.d.ts.map +1 -1
- package/dist/esm/container/EdgeRenderer/MarkerComponent.d.ts.map +1 -1
- package/dist/esm/container/EdgeRenderer/MarkerSymbols.d.ts +1 -1
- package/dist/esm/container/EdgeRenderer/MarkerSymbols.d.ts.map +1 -1
- package/dist/esm/container/EdgeRenderer/index.d.ts.map +1 -1
- package/dist/esm/container/EdgeRenderer/type.d.ts.map +1 -1
- package/dist/esm/container/EdgeRenderer/utils.d.ts +3 -3
- package/dist/esm/container/EdgeRenderer/utils.d.ts.map +1 -1
- package/dist/esm/container/NodeRenderer/index.d.ts +1 -1
- package/dist/esm/container/NodeRenderer/index.d.ts.map +1 -1
- package/dist/esm/container/NodeRenderer/type.d.ts +2 -2
- package/dist/esm/container/NodeRenderer/type.d.ts.map +1 -1
- package/dist/esm/container/NodeRenderer/utils.d.ts.map +1 -1
- package/dist/esm/container/Pane/index.d.ts +2 -1
- package/dist/esm/container/Pane/index.d.ts.map +1 -1
- package/dist/esm/container/ReactDiagram/DiagramView.d.ts +2 -2
- package/dist/esm/container/ReactDiagram/DiagramView.d.ts.map +1 -1
- package/dist/esm/container/ReactDiagram/Wrapper.d.ts.map +1 -1
- package/dist/esm/container/ReactDiagram/index.d.ts +20 -20
- package/dist/esm/container/ReactDiagram/index.d.ts.map +1 -1
- package/dist/esm/container/Viewport/index.d.ts.map +1 -1
- package/dist/esm/contexts/NodeIdContext.d.ts.map +1 -1
- package/dist/esm/contexts/RFStoreContext.d.ts.map +1 -1
- package/dist/esm/hooks/useDrag.d.ts +9 -0
- package/dist/esm/hooks/useDrag.d.ts.map +1 -0
- package/dist/esm/hooks/useDragSelectionKeyPress.d.ts +4 -0
- package/dist/esm/hooks/useDragSelectionKeyPress.d.ts.map +1 -0
- package/dist/esm/hooks/useGlobalKeyHandler.d.ts +1 -1
- package/dist/esm/hooks/useGlobalKeyHandler.d.ts.map +1 -1
- package/dist/esm/hooks/useNodeOrEdgeTypes.d.ts.map +1 -1
- package/dist/esm/hooks/useNodesEdgesState/index.d.ts +2 -2
- package/dist/esm/hooks/useNodesEdgesState/index.d.ts.map +1 -1
- package/dist/esm/hooks/useNodesEdgesState/type.d.ts +7 -7
- package/dist/esm/hooks/useNodesEdgesState/type.d.ts.map +1 -1
- package/dist/esm/hooks/useStore.d.ts.map +1 -1
- package/dist/esm/hooks/useVisibleNodes.d.ts +1 -1
- package/dist/esm/hooks/useVisibleNodes.d.ts.map +1 -1
- package/dist/esm/index.d.ts +7 -5
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1462 -1289
- package/dist/esm/store/index.d.ts.map +1 -1
- package/dist/esm/store/initialState.d.ts +1 -1
- package/dist/esm/store/initialState.d.ts.map +1 -1
- package/dist/esm/store/type.d.ts +0 -2
- package/dist/esm/store/type.d.ts.map +1 -1
- package/dist/esm/store/utils.d.ts +4 -4
- package/dist/esm/store/utils.d.ts.map +1 -1
- package/dist/esm/types/core.d.ts +4 -4
- package/dist/esm/types/core.d.ts.map +1 -1
- package/dist/esm/types/general.d.ts +1 -21
- package/dist/esm/types/general.d.ts.map +1 -1
- package/dist/esm/types/index.d.ts +0 -1
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/utils/changes.d.ts +2 -2
- package/dist/esm/utils/changes.d.ts.map +1 -1
- package/dist/esm/utils/deepEqual.d.ts.map +1 -1
- package/dist/esm/utils/index.d.ts +2 -21
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/style.css +13 -12
- package/dist/umd/components/A11yDescriptions/index.d.ts.map +1 -1
- package/dist/umd/components/Background/LinePath.d.ts.map +1 -1
- package/dist/umd/components/Background/index.d.ts.map +1 -1
- package/dist/umd/components/Background/type.d.ts.map +1 -1
- package/dist/umd/components/DragBox/index.d.ts +1 -1
- package/dist/umd/components/DragBox/index.d.ts.map +1 -1
- package/dist/umd/components/Edges/Anchor.d.ts +1 -1
- package/dist/umd/components/Edges/Anchor.d.ts.map +1 -1
- package/dist/umd/components/Edges/BaseEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/BezierEdge.d.ts +2 -13
- package/dist/umd/components/Edges/BezierEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/EdgeLabel.d.ts.map +1 -1
- package/dist/umd/components/Edges/EdgeWrapper/index.d.ts.map +1 -1
- package/dist/umd/components/Edges/EdgeWrapper/type.d.ts +3 -10
- package/dist/umd/components/Edges/EdgeWrapper/type.d.ts.map +1 -1
- package/dist/umd/components/Edges/StepEdge.d.ts +2 -22
- package/dist/umd/components/Edges/StepEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/StraightEdge.d.ts +0 -7
- package/dist/umd/components/Edges/StraightEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/type.d.ts +8 -35
- package/dist/umd/components/Edges/type.d.ts.map +1 -1
- package/dist/umd/components/Node/NodeWrapper/index.d.ts +3 -3
- package/dist/umd/components/Node/NodeWrapper/index.d.ts.map +1 -1
- package/dist/umd/components/Node/NodeWrapper/type.d.ts +4 -1
- package/dist/umd/components/Node/NodeWrapper/type.d.ts.map +1 -1
- package/dist/umd/components/Node/index.d.ts.map +1 -1
- package/dist/umd/components/Node/type.d.ts +4 -36
- package/dist/umd/components/Node/type.d.ts.map +1 -1
- package/dist/umd/components/Node/utils.d.ts +0 -3
- package/dist/umd/components/Node/utils.d.ts.map +1 -1
- package/dist/umd/components/Port/index.d.ts +2 -2
- package/dist/umd/components/Port/index.d.ts.map +1 -1
- package/dist/umd/components/ReactDiagramProvider/index.d.ts.map +1 -1
- package/dist/umd/components/ReactDiagramProvider/type.d.ts +10 -8
- package/dist/umd/components/ReactDiagramProvider/type.d.ts.map +1 -1
- package/dist/umd/components/SelectionBox/index.d.ts +1 -1
- package/dist/umd/components/SelectionBox/index.d.ts.map +1 -1
- package/dist/umd/components/SelectionBox/type.d.ts +1 -1
- package/dist/umd/components/SelectionBox/type.d.ts.map +1 -1
- package/dist/umd/components/StoreUpdater/index.d.ts +2 -2
- package/dist/umd/components/StoreUpdater/index.d.ts.map +1 -1
- package/dist/umd/container/ConnectionLineRenderer/ConnectionPath.d.ts +1 -1
- package/dist/umd/container/ConnectionLineRenderer/ConnectionPath.d.ts.map +1 -1
- package/dist/umd/container/ConnectionLineRenderer/index.d.ts.map +1 -1
- package/dist/umd/container/ConnectionLineRenderer/type.d.ts +2 -2
- package/dist/umd/container/ConnectionLineRenderer/type.d.ts.map +1 -1
- package/dist/umd/container/DiagramRenderer/index.d.ts +3 -2
- package/dist/umd/container/DiagramRenderer/index.d.ts.map +1 -1
- package/dist/umd/container/DragSelection/index.d.ts +2 -2
- package/dist/umd/container/DragSelection/index.d.ts.map +1 -1
- package/dist/umd/container/EdgeRenderer/MarkerComponent.d.ts.map +1 -1
- package/dist/umd/container/EdgeRenderer/MarkerSymbols.d.ts +1 -1
- package/dist/umd/container/EdgeRenderer/MarkerSymbols.d.ts.map +1 -1
- package/dist/umd/container/EdgeRenderer/index.d.ts.map +1 -1
- package/dist/umd/container/EdgeRenderer/type.d.ts.map +1 -1
- package/dist/umd/container/EdgeRenderer/utils.d.ts +3 -3
- package/dist/umd/container/EdgeRenderer/utils.d.ts.map +1 -1
- package/dist/umd/container/NodeRenderer/index.d.ts +1 -1
- package/dist/umd/container/NodeRenderer/index.d.ts.map +1 -1
- package/dist/umd/container/NodeRenderer/type.d.ts +2 -2
- package/dist/umd/container/NodeRenderer/type.d.ts.map +1 -1
- package/dist/umd/container/NodeRenderer/utils.d.ts.map +1 -1
- package/dist/umd/container/Pane/index.d.ts +2 -1
- package/dist/umd/container/Pane/index.d.ts.map +1 -1
- package/dist/umd/container/ReactDiagram/DiagramView.d.ts +2 -2
- package/dist/umd/container/ReactDiagram/DiagramView.d.ts.map +1 -1
- package/dist/umd/container/ReactDiagram/Wrapper.d.ts.map +1 -1
- package/dist/umd/container/ReactDiagram/index.d.ts +20 -20
- package/dist/umd/container/ReactDiagram/index.d.ts.map +1 -1
- package/dist/umd/container/Viewport/index.d.ts.map +1 -1
- package/dist/umd/contexts/NodeIdContext.d.ts.map +1 -1
- package/dist/umd/contexts/RFStoreContext.d.ts.map +1 -1
- package/dist/umd/hooks/useDrag.d.ts +9 -0
- package/dist/umd/hooks/useDrag.d.ts.map +1 -0
- package/dist/umd/hooks/useDragSelectionKeyPress.d.ts +4 -0
- package/dist/umd/hooks/useDragSelectionKeyPress.d.ts.map +1 -0
- package/dist/umd/hooks/useGlobalKeyHandler.d.ts +1 -1
- package/dist/umd/hooks/useGlobalKeyHandler.d.ts.map +1 -1
- package/dist/umd/hooks/useNodeOrEdgeTypes.d.ts.map +1 -1
- package/dist/umd/hooks/useNodesEdgesState/index.d.ts +2 -2
- package/dist/umd/hooks/useNodesEdgesState/index.d.ts.map +1 -1
- package/dist/umd/hooks/useNodesEdgesState/type.d.ts +7 -7
- package/dist/umd/hooks/useNodesEdgesState/type.d.ts.map +1 -1
- package/dist/umd/hooks/useStore.d.ts.map +1 -1
- package/dist/umd/hooks/useVisibleNodes.d.ts +1 -1
- package/dist/umd/hooks/useVisibleNodes.d.ts.map +1 -1
- package/dist/umd/index.d.ts +7 -5
- package/dist/umd/index.d.ts.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/store/index.d.ts.map +1 -1
- package/dist/umd/store/initialState.d.ts +1 -1
- package/dist/umd/store/initialState.d.ts.map +1 -1
- package/dist/umd/store/type.d.ts +0 -2
- package/dist/umd/store/type.d.ts.map +1 -1
- package/dist/umd/store/utils.d.ts +4 -4
- package/dist/umd/store/utils.d.ts.map +1 -1
- package/dist/umd/types/core.d.ts +4 -4
- package/dist/umd/types/core.d.ts.map +1 -1
- package/dist/umd/types/general.d.ts +1 -21
- package/dist/umd/types/general.d.ts.map +1 -1
- package/dist/umd/types/index.d.ts +0 -1
- package/dist/umd/types/index.d.ts.map +1 -1
- package/dist/umd/utils/changes.d.ts +2 -2
- package/dist/umd/utils/changes.d.ts.map +1 -1
- package/dist/umd/utils/deepEqual.d.ts.map +1 -1
- package/dist/umd/utils/index.d.ts +2 -21
- package/dist/umd/utils/index.d.ts.map +1 -1
- package/package.json +8 -6
- package/dist/esm/components/Edges/utils.d.ts +0 -17
- package/dist/esm/components/Edges/utils.d.ts.map +0 -1
- package/dist/esm/components/Port/type.d.ts +0 -22
- package/dist/esm/components/Port/type.d.ts.map +0 -1
- package/dist/esm/components/Port/utils.d.ts +0 -25
- package/dist/esm/components/Port/utils.d.ts.map +0 -1
- package/dist/esm/fixtures/errorMessages.d.ts +0 -11
- package/dist/esm/fixtures/errorMessages.d.ts.map +0 -1
- package/dist/esm/hooks/useDrag/index.d.ts +0 -10
- package/dist/esm/hooks/useDrag/index.d.ts.map +0 -1
- package/dist/esm/hooks/useDrag/type.d.ts +0 -11
- package/dist/esm/hooks/useDrag/type.d.ts.map +0 -1
- package/dist/esm/hooks/useDrag/utils.d.ts +0 -20
- package/dist/esm/hooks/useDrag/utils.d.ts.map +0 -1
- package/dist/esm/hooks/useGetPointerPosition.d.ts +0 -21
- package/dist/esm/hooks/useGetPointerPosition.d.ts.map +0 -1
- package/dist/esm/hooks/useUpdateIntersectionNodes/index.d.ts +0 -6
- package/dist/esm/hooks/useUpdateIntersectionNodes/index.d.ts.map +0 -1
- package/dist/esm/types/utils.d.ts +0 -26
- package/dist/esm/types/utils.d.ts.map +0 -1
- package/dist/esm/utils/graph.d.ts +0 -18
- package/dist/esm/utils/graph.d.ts.map +0 -1
- package/dist/umd/components/Edges/utils.d.ts +0 -17
- package/dist/umd/components/Edges/utils.d.ts.map +0 -1
- package/dist/umd/components/Port/type.d.ts +0 -22
- package/dist/umd/components/Port/type.d.ts.map +0 -1
- package/dist/umd/components/Port/utils.d.ts +0 -25
- package/dist/umd/components/Port/utils.d.ts.map +0 -1
- package/dist/umd/fixtures/errorMessages.d.ts +0 -11
- package/dist/umd/fixtures/errorMessages.d.ts.map +0 -1
- package/dist/umd/hooks/useDrag/index.d.ts +0 -10
- package/dist/umd/hooks/useDrag/index.d.ts.map +0 -1
- package/dist/umd/hooks/useDrag/type.d.ts +0 -11
- package/dist/umd/hooks/useDrag/type.d.ts.map +0 -1
- package/dist/umd/hooks/useDrag/utils.d.ts +0 -20
- package/dist/umd/hooks/useDrag/utils.d.ts.map +0 -1
- package/dist/umd/hooks/useGetPointerPosition.d.ts +0 -21
- package/dist/umd/hooks/useGetPointerPosition.d.ts.map +0 -1
- package/dist/umd/hooks/useUpdateIntersectionNodes/index.d.ts +0 -6
- package/dist/umd/hooks/useUpdateIntersectionNodes/index.d.ts.map +0 -1
- package/dist/umd/types/utils.d.ts +0 -26
- package/dist/umd/types/utils.d.ts.map +0 -1
- package/dist/umd/utils/graph.d.ts +0 -18
- package/dist/umd/utils/graph.d.ts.map +0 -1
package/dist/esm/index.js
CHANGED
|
@@ -1,14 +1,106 @@
|
|
|
1
|
+
import { select } from 'd3-selection';
|
|
2
|
+
import { drag } from 'd3-drag';
|
|
3
|
+
import { zoom, zoomTransform, zoomIdentity } from 'd3-zoom';
|
|
1
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext, useContext, useMemo, useState, useEffect, useRef,
|
|
5
|
+
import { createContext, useContext, useMemo, useState, useEffect, useRef, memo, useCallback, forwardRef } from 'react';
|
|
3
6
|
import { useStore as useStore$1, createStore } from 'zustand';
|
|
4
|
-
import { zoom, zoomIdentity } from 'd3-zoom';
|
|
5
|
-
import { select } from 'd3-selection';
|
|
6
|
-
import { shallow } from 'zustand/shallow';
|
|
7
7
|
import cc from 'classcat';
|
|
8
|
-
import {
|
|
8
|
+
import { shallow } from 'zustand/shallow';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
var Position;
|
|
11
|
+
(function (Position) {
|
|
12
|
+
Position["Left"] = "left";
|
|
13
|
+
Position["Top"] = "top";
|
|
14
|
+
Position["Right"] = "right";
|
|
15
|
+
Position["Bottom"] = "bottom";
|
|
16
|
+
})(Position || (Position = {}));
|
|
17
|
+
|
|
18
|
+
// export const internalsSymbol = Symbol.for('internals');
|
|
19
|
+
const internalsSymbol$1 = 'internals';
|
|
20
|
+
|
|
21
|
+
var MarkerType;
|
|
22
|
+
(function (MarkerType) {
|
|
23
|
+
MarkerType["Arrow"] = "arrow";
|
|
24
|
+
})(MarkerType || (MarkerType = {}));
|
|
25
|
+
|
|
26
|
+
const getDimensions = (node) => ({
|
|
27
|
+
width: node.offsetWidth,
|
|
28
|
+
height: node.offsetHeight,
|
|
29
|
+
});
|
|
30
|
+
const getPortBounds = (selector, nodeElement, zoom, nodeOrigin) => {
|
|
31
|
+
const ports = nodeElement.querySelectorAll(selector);
|
|
32
|
+
if (!ports || !ports.length) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const portsArray = Array.from(ports);
|
|
36
|
+
const nodeBounds = nodeElement.getBoundingClientRect();
|
|
37
|
+
const nodeOffset = {
|
|
38
|
+
x: nodeBounds.width * nodeOrigin[0],
|
|
39
|
+
y: nodeBounds.height * nodeOrigin[1],
|
|
40
|
+
};
|
|
41
|
+
return portsArray.map((port) => {
|
|
42
|
+
const portBounds = port.getBoundingClientRect();
|
|
43
|
+
return {
|
|
44
|
+
id: port.getAttribute('data-portid'),
|
|
45
|
+
position: port.dataset.portPosition,
|
|
46
|
+
x: (portBounds.left - nodeBounds.left - nodeOffset.x) / zoom,
|
|
47
|
+
y: (portBounds.top - nodeBounds.top - nodeOffset.y) / zoom,
|
|
48
|
+
...getDimensions(port),
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
const getHostForElement = (element) => element.getRootNode?.() || window?.document;
|
|
53
|
+
const isMouseEvent = (event) => 'clientX' in event;
|
|
54
|
+
const getEventPosition = (event, bounds) => {
|
|
55
|
+
const isMouseTriggered = isMouseEvent(event);
|
|
56
|
+
const eventX = isMouseTriggered ? event.clientX : event.touches?.[0].clientX;
|
|
57
|
+
const eventY = isMouseTriggered ? event.clientY : event.touches?.[0].clientY;
|
|
58
|
+
return {
|
|
59
|
+
x: eventX - (bounds?.left ?? 0),
|
|
60
|
+
y: eventY - (bounds?.top ?? 0),
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
const pointToRendererPoint = ({ x, y }, [tx, ty, tScale]) => {
|
|
64
|
+
const position = {
|
|
65
|
+
x: (x - tx) / tScale,
|
|
66
|
+
y: (y - ty) / tScale,
|
|
67
|
+
};
|
|
68
|
+
return position;
|
|
69
|
+
};
|
|
70
|
+
const rendererPointToPoint = ({ x, y }, [tx, ty, tScale]) => {
|
|
71
|
+
return {
|
|
72
|
+
x: x * tScale + tx,
|
|
73
|
+
y: y * tScale + ty,
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
const getPointerPosition = (event, { transform, gridStep, centerStep }) => {
|
|
77
|
+
const { x, y } = getEventPosition(event);
|
|
78
|
+
const pointerPos = pointToRendererPoint({ x, y }, transform);
|
|
79
|
+
const getStepPosition = (params = {
|
|
80
|
+
position: pointerPos,
|
|
81
|
+
}) => {
|
|
82
|
+
const { position, nodeSize } = params;
|
|
83
|
+
if (!gridStep)
|
|
84
|
+
return position;
|
|
85
|
+
let x = gridStep[0] * Math.round(position.x / gridStep[0]), y = gridStep[1] * Math.round(position.y / gridStep[1]);
|
|
86
|
+
if (centerStep && nodeSize) {
|
|
87
|
+
const centerX = (gridStep[0] - nodeSize.width) / 2;
|
|
88
|
+
const centerY = (gridStep[1] - nodeSize.height) / 2;
|
|
89
|
+
const positionX = position.x - centerX;
|
|
90
|
+
const positionY = position.y - centerY;
|
|
91
|
+
x = gridStep[0] * Math.round(positionX / gridStep[0]) + centerX;
|
|
92
|
+
y = gridStep[1] * Math.round(positionY / gridStep[1]) + centerY;
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
x,
|
|
96
|
+
y,
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
return {
|
|
100
|
+
getStepPosition,
|
|
101
|
+
...pointerPos,
|
|
102
|
+
};
|
|
103
|
+
};
|
|
12
104
|
|
|
13
105
|
const errorMessages = {
|
|
14
106
|
'001': () => 'Seems like you have not used zustand provider as an ancestor',
|
|
@@ -20,77 +112,27 @@ const errorMessages = {
|
|
|
20
112
|
'022': (type) => `Marker type "${type}" doesn't exist.`,
|
|
21
113
|
};
|
|
22
114
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
|
|
115
|
+
const clamp = (val, min = 0, max = 1) => Math.min(Math.max(val, min), max);
|
|
116
|
+
const calcAutoPanVelocity = (value, bound, radius, velocity) => {
|
|
117
|
+
const maxRadius = bound - radius;
|
|
118
|
+
if (value < radius) {
|
|
119
|
+
return (clamp(Math.abs(value - radius), 1, 50) / 50) * velocity;
|
|
28
120
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const useStoreApi = () => {
|
|
32
|
-
const store = useContext(StoreContext);
|
|
33
|
-
if (store === null) {
|
|
34
|
-
throw new Error(zustandErrorMessage);
|
|
121
|
+
else if (value > maxRadius) {
|
|
122
|
+
return (-clamp(Math.abs(value - maxRadius), 1, 50) / 50) * velocity;
|
|
35
123
|
}
|
|
36
|
-
return
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
124
|
+
return 0;
|
|
125
|
+
};
|
|
126
|
+
const calcAutoPanPosition = (pos, bounds) => {
|
|
127
|
+
const xMovement = calcAutoPanVelocity(pos.x, bounds.width, 30, 10);
|
|
128
|
+
const yMovement = calcAutoPanVelocity(pos.y, bounds.height, 30, 10);
|
|
129
|
+
return [xMovement, yMovement];
|
|
42
130
|
};
|
|
43
|
-
|
|
44
|
-
function useGlobalKeyHandler(multiSelectionKeyCode = 'Meta') {
|
|
45
|
-
const store = useStoreApi();
|
|
46
|
-
const [multiSelectionActivate, setMultiSelectionActivate] = useState(false);
|
|
47
|
-
const handleKeyDown = (e) => {
|
|
48
|
-
if (e.key === multiSelectionKeyCode) {
|
|
49
|
-
setMultiSelectionActivate(true);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
const handleKeyUp = () => {
|
|
53
|
-
setMultiSelectionActivate(false);
|
|
54
|
-
};
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
document.addEventListener('keydown', handleKeyDown);
|
|
57
|
-
document.addEventListener('keyup', handleKeyUp);
|
|
58
|
-
return () => {
|
|
59
|
-
document.removeEventListener('keydown', handleKeyDown);
|
|
60
|
-
document.removeEventListener('keyup', handleKeyUp);
|
|
61
|
-
};
|
|
62
|
-
}, []);
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
store.setState({
|
|
65
|
-
multiSelectionActive: multiSelectionActivate,
|
|
66
|
-
});
|
|
67
|
-
}, [multiSelectionActivate]);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const internalsSymbol = Symbol.for('internals');
|
|
71
131
|
const devWarn = (id, value = '') => {
|
|
72
132
|
if (process.env.NODE_ENV === 'development') {
|
|
73
133
|
console.warn(`[React Diagram]: ${id}-${errorMessages[id](value)}`);
|
|
74
134
|
}
|
|
75
135
|
};
|
|
76
|
-
const onErrorWrapper = (onError) => (id, value = '') => onError?.(id, errorMessages[id](value));
|
|
77
|
-
const isNumeric = (n) => !isNaN(n) && isFinite(n);
|
|
78
|
-
const getDimensions = (node) => ({
|
|
79
|
-
width: node.offsetWidth,
|
|
80
|
-
height: node.offsetHeight,
|
|
81
|
-
});
|
|
82
|
-
const getOverlappingArea = (rectA, rectB) => {
|
|
83
|
-
const xOverlap = Math.max(0, Math.min(rectA.x + rectA.width, rectB.x + rectB.width) -
|
|
84
|
-
Math.max(rectA.x, rectB.x));
|
|
85
|
-
const yOverlap = Math.max(0, Math.min(rectA.y + rectA.height, rectB.y + rectB.height) -
|
|
86
|
-
Math.max(rectA.y, rectB.y));
|
|
87
|
-
return Math.ceil(xOverlap * yOverlap);
|
|
88
|
-
};
|
|
89
|
-
const clamp = (val, min = 0, max = 1) => Math.min(Math.max(val, min), max);
|
|
90
|
-
const clampPosition = (position = { x: 0, y: 0 }, extent) => ({
|
|
91
|
-
x: clamp(position.x, extent[0][0], extent[1][0]),
|
|
92
|
-
y: clamp(position.y, extent[0][1], extent[1][1]),
|
|
93
|
-
});
|
|
94
136
|
const rectToBox = ({ x, y, width, height }) => ({
|
|
95
137
|
x,
|
|
96
138
|
y,
|
|
@@ -109,310 +151,60 @@ const getBoundsOfBoxes = (box1, box2) => ({
|
|
|
109
151
|
x2: Math.max(box1.x2, box2.x2),
|
|
110
152
|
y2: Math.max(box1.y2, box2.y2),
|
|
111
153
|
});
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
y: eventY - (bounds?.top ?? 0),
|
|
120
|
-
};
|
|
121
|
-
};
|
|
122
|
-
const calcAutoPanVelocity = (value, bound, radius, velocity) => {
|
|
123
|
-
const maxRadius = bound - radius;
|
|
124
|
-
if (value < radius) {
|
|
125
|
-
return (clamp(Math.abs(value - radius), 1, 50) / 50) * velocity;
|
|
126
|
-
}
|
|
127
|
-
else if (value > maxRadius) {
|
|
128
|
-
return (-clamp(Math.abs(value - maxRadius), 1, 50) / 50) * velocity;
|
|
129
|
-
}
|
|
130
|
-
return 0;
|
|
131
|
-
};
|
|
132
|
-
const calcAutoPanPosition = (pos, bounds) => {
|
|
133
|
-
const xMovement = calcAutoPanVelocity(pos.x, bounds.width, 30, 10);
|
|
134
|
-
const yMovement = calcAutoPanVelocity(pos.y, bounds.height, 30, 10);
|
|
135
|
-
return [xMovement, yMovement];
|
|
154
|
+
const isNumeric = (n) => !isNaN(n) && isFinite(n);
|
|
155
|
+
const getOverlappingArea = (rectA, rectB) => {
|
|
156
|
+
const xOverlap = Math.max(0, Math.min(rectA.x + rectA.width, rectB.x + rectB.width) -
|
|
157
|
+
Math.max(rectA.x, rectB.x));
|
|
158
|
+
const yOverlap = Math.max(0, Math.min(rectA.y + rectA.height, rectB.y + rectB.height) -
|
|
159
|
+
Math.max(rectA.y, rectB.y));
|
|
160
|
+
return Math.ceil(xOverlap * yOverlap);
|
|
136
161
|
};
|
|
162
|
+
const clampPosition = (position = { x: 0, y: 0 }, extent) => ({
|
|
163
|
+
x: clamp(position.x, extent[0][0], extent[1][0]),
|
|
164
|
+
y: clamp(position.y, extent[0][1], extent[1][1]),
|
|
165
|
+
});
|
|
137
166
|
|
|
138
|
-
const
|
|
139
|
-
|
|
167
|
+
const isCoreNode = (element) => 'id' in element && !('source' in element) && !('target' in element);
|
|
168
|
+
const isCoreEdge = (element) => 'source' in element && 'target' in element;
|
|
169
|
+
const getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {
|
|
170
|
+
if (!node) {
|
|
171
|
+
return {
|
|
172
|
+
x: 0,
|
|
173
|
+
y: 0,
|
|
174
|
+
positionAbsolute: {
|
|
175
|
+
x: 0,
|
|
176
|
+
y: 0,
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
const offsetX = (node.width ?? 0) * nodeOrigin[0];
|
|
181
|
+
const offsetY = (node.height ?? 0) * nodeOrigin[1];
|
|
182
|
+
const position = {
|
|
183
|
+
x: node.position.x - offsetX,
|
|
184
|
+
y: node.position.y - offsetY,
|
|
185
|
+
};
|
|
140
186
|
return {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
187
|
+
...position,
|
|
188
|
+
positionAbsolute: node.positionAbsolute
|
|
189
|
+
? {
|
|
190
|
+
x: node.positionAbsolute.x - offsetX,
|
|
191
|
+
y: node.positionAbsolute.y - offsetY,
|
|
192
|
+
}
|
|
193
|
+
: position,
|
|
144
194
|
};
|
|
145
195
|
};
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const isZoomingOrPanning = useRef(false);
|
|
159
|
-
const Pane = useRef(null);
|
|
160
|
-
const d3ZoomHandler = useRef();
|
|
161
|
-
const prevTransform = useRef({ x: 0, y: 0, zoom: 0 });
|
|
162
|
-
const timerId = useRef();
|
|
163
|
-
const { d3Zoom, d3Selection } = useStore(selector$8, shallow);
|
|
164
|
-
useEffect(() => {
|
|
165
|
-
if (Pane.current) {
|
|
166
|
-
const bbox = Pane.current.getBoundingClientRect();
|
|
167
|
-
const d3ZoomInstance = zoom()
|
|
168
|
-
.scaleExtent([minZoom, maxZoom])
|
|
169
|
-
.translateExtent(translateExtent);
|
|
170
|
-
const selection = select(Pane.current).call(d3ZoomInstance);
|
|
171
|
-
const updatedTransform = zoomIdentity
|
|
172
|
-
.translate(defaultViewport.x, defaultViewport.y)
|
|
173
|
-
.scale(clamp(defaultViewport.zoom, minZoom, maxZoom));
|
|
174
|
-
const extent = [
|
|
175
|
-
[0, 0],
|
|
176
|
-
[bbox.width, bbox.height],
|
|
177
|
-
];
|
|
178
|
-
const constrainedTransform = d3ZoomInstance.constrain()(updatedTransform, extent, translateExtent);
|
|
179
|
-
d3ZoomInstance.transform(selection, constrainedTransform);
|
|
180
|
-
d3ZoomHandler.current = selection.on('wheel.zoom');
|
|
181
|
-
store.setState({
|
|
182
|
-
d3Zoom: d3ZoomInstance,
|
|
183
|
-
d3Selection: selection,
|
|
184
|
-
// we need to pass transform because zoom handler is not registered when we set the initial transform
|
|
185
|
-
transform: [
|
|
186
|
-
constrainedTransform.x,
|
|
187
|
-
constrainedTransform.y,
|
|
188
|
-
constrainedTransform.k,
|
|
189
|
-
],
|
|
190
|
-
domNode: Pane.current.closest('.react-diagram'),
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
}, [translateExtent]);
|
|
194
|
-
useEffect(() => {
|
|
195
|
-
if (d3Zoom && d3Selection) {
|
|
196
|
-
d3Selection.on('wheel.zoom', (event, d) => {
|
|
197
|
-
event.preventDefault();
|
|
198
|
-
if (Pane.current && d3ZoomHandler.current) {
|
|
199
|
-
d3ZoomHandler.current.call(Pane.current, event, d);
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
}, [d3Zoom, d3Selection, d3ZoomHandler, panning]);
|
|
204
|
-
useEffect(() => {
|
|
205
|
-
if (d3Zoom) {
|
|
206
|
-
d3Zoom.on('start', (event) => {
|
|
207
|
-
if (!event.sourceEvent) {
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
isZoomingOrPanning.current = true;
|
|
211
|
-
if (onMoveStart) {
|
|
212
|
-
const flowTransform = convertTransform(event.transform);
|
|
213
|
-
prevTransform.current = flowTransform;
|
|
214
|
-
onMoveStart?.(event.sourceEvent, flowTransform);
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
}, [d3Zoom, onMoveStart]);
|
|
219
|
-
useEffect(() => {
|
|
220
|
-
if (d3Zoom) {
|
|
221
|
-
d3Zoom.on('zoom', (event) => {
|
|
222
|
-
store.setState({
|
|
223
|
-
transform: [
|
|
224
|
-
event.transform.x,
|
|
225
|
-
event.transform.y,
|
|
226
|
-
event.transform.k,
|
|
227
|
-
],
|
|
228
|
-
});
|
|
229
|
-
if (onMove) {
|
|
230
|
-
const flowTransform = convertTransform(event.transform);
|
|
231
|
-
onMove?.(event.sourceEvent, flowTransform);
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
}, [d3Zoom, onMove]);
|
|
236
|
-
useEffect(() => {
|
|
237
|
-
if (d3Zoom) {
|
|
238
|
-
d3Zoom.on('end', (event) => {
|
|
239
|
-
isZoomingOrPanning.current = false;
|
|
240
|
-
if (onMoveEnd &&
|
|
241
|
-
isViewChanged(prevTransform.current, event.transform)) {
|
|
242
|
-
const flowTransform = convertTransform(event.transform);
|
|
243
|
-
prevTransform.current = flowTransform;
|
|
244
|
-
clearTimeout(timerId.current);
|
|
245
|
-
timerId.current = setTimeout(() => {
|
|
246
|
-
onMoveEnd?.(event.sourceEvent, flowTransform);
|
|
247
|
-
}, 0);
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
}, [d3Zoom]);
|
|
252
|
-
useEffect(() => {
|
|
253
|
-
if (d3Zoom) {
|
|
254
|
-
d3Zoom.filter((event) => {
|
|
255
|
-
if (isWrappedWithClass(event, noPanClassName) &&
|
|
256
|
-
event.type !== 'wheel') {
|
|
257
|
-
return false;
|
|
258
|
-
}
|
|
259
|
-
if (!panning)
|
|
260
|
-
return false;
|
|
261
|
-
const buttonAllowed = !event.button || event.button <= 1;
|
|
262
|
-
if (!buttonAllowed)
|
|
263
|
-
return false;
|
|
264
|
-
return true;
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
}, [d3Zoom, panning]);
|
|
268
|
-
return (jsx("div", { className: "react-diagram__pane react-diagram__container", ref: Pane, children: children }));
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const selector$7 = (s) => `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`;
|
|
272
|
-
function Viewport({ children }) {
|
|
273
|
-
const transform = useStore(selector$7);
|
|
274
|
-
return (jsx("div", { className: "react-diagram__viewport react-diagram__container", style: { transform }, children: children }));
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function DragBox({ rect }) {
|
|
278
|
-
const { width, height, x, y } = rect;
|
|
279
|
-
if (!width || !height || !x || !y)
|
|
280
|
-
return null;
|
|
281
|
-
return (jsx("div", { className: "react-diagram__drag-box react-diagram__container", style: {
|
|
282
|
-
width,
|
|
283
|
-
height,
|
|
284
|
-
transform: `translate(${x}px, ${y}px)`,
|
|
285
|
-
} }));
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function useGetPointerPosition() {
|
|
289
|
-
const store = useStoreApi();
|
|
290
|
-
const getPointerPosition = useCallback(({ sourceEvent }) => {
|
|
291
|
-
const { transform, gridStep, centerStep } = store.getState();
|
|
292
|
-
const x = sourceEvent.changedTouches
|
|
293
|
-
? sourceEvent.changedTouches[0].clientX
|
|
294
|
-
: sourceEvent.clientX;
|
|
295
|
-
const y = sourceEvent.changedTouches
|
|
296
|
-
? sourceEvent.changedTouches[0].clientY
|
|
297
|
-
: sourceEvent.clientY;
|
|
298
|
-
const pointerPos = {
|
|
299
|
-
x: (x - transform[0]) / transform[2],
|
|
300
|
-
y: (y - transform[1]) / transform[2],
|
|
301
|
-
};
|
|
302
|
-
const getStepPosition = (params = {
|
|
303
|
-
position: pointerPos,
|
|
304
|
-
}) => {
|
|
305
|
-
const { position, nodeSize } = params;
|
|
306
|
-
if (!gridStep)
|
|
307
|
-
return position;
|
|
308
|
-
let x = gridStep[0] * Math.round(position.x / gridStep[0]), y = gridStep[1] * Math.round(position.y / gridStep[1]);
|
|
309
|
-
if (centerStep && nodeSize) {
|
|
310
|
-
const centerX = (gridStep[0] - nodeSize.width) / 2;
|
|
311
|
-
const centerY = (gridStep[1] - nodeSize.height) / 2;
|
|
312
|
-
const positionX = position.x - centerX;
|
|
313
|
-
const positionY = position.y - centerY;
|
|
314
|
-
x = gridStep[0] * Math.round(positionX / gridStep[0]) + centerX;
|
|
315
|
-
y = gridStep[1] * Math.round(positionY / gridStep[1]) + centerY;
|
|
316
|
-
}
|
|
317
|
-
return {
|
|
318
|
-
x,
|
|
319
|
-
y,
|
|
320
|
-
};
|
|
321
|
-
};
|
|
322
|
-
return {
|
|
323
|
-
getStepPosition,
|
|
324
|
-
...pointerPos,
|
|
325
|
-
};
|
|
326
|
-
}, []);
|
|
327
|
-
return getPointerPosition;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
const getPortBounds = (selector, nodeElement, zoom, nodeOrigin) => {
|
|
331
|
-
const ports = nodeElement.querySelectorAll(selector);
|
|
332
|
-
if (!ports || !ports.length) {
|
|
333
|
-
return null;
|
|
334
|
-
}
|
|
335
|
-
const portsArray = Array.from(ports);
|
|
336
|
-
const nodeBounds = nodeElement.getBoundingClientRect();
|
|
337
|
-
const nodeOffset = {
|
|
338
|
-
x: nodeBounds.width * nodeOrigin[0],
|
|
339
|
-
y: nodeBounds.height * nodeOrigin[1],
|
|
340
|
-
};
|
|
341
|
-
return portsArray.map((port) => {
|
|
342
|
-
const portBounds = port.getBoundingClientRect();
|
|
343
|
-
return {
|
|
344
|
-
id: port.getAttribute('data-portid'),
|
|
345
|
-
position: port.dataset.portPosition,
|
|
346
|
-
x: (portBounds.left - nodeBounds.left - nodeOffset.x) / zoom,
|
|
347
|
-
y: (portBounds.top - nodeBounds.top - nodeOffset.y) / zoom,
|
|
348
|
-
...getDimensions(port),
|
|
349
|
-
};
|
|
350
|
-
});
|
|
351
|
-
};
|
|
352
|
-
function getMouseHandler$1(id, getState, handler) {
|
|
353
|
-
return handler === undefined
|
|
354
|
-
? handler
|
|
355
|
-
: (event) => {
|
|
356
|
-
const node = getState().nodeInternals.get(id);
|
|
357
|
-
handler(event, { ...node });
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
function handleNodeClick({ id, store, isSelectable, unselect = false, nodeRef, }) {
|
|
361
|
-
if (!isSelectable)
|
|
362
|
-
return;
|
|
363
|
-
const { addSelectedNodes, unselectNodes, multiSelectionActive, nodeInternals, } = store.getState();
|
|
364
|
-
const node = nodeInternals.get(id);
|
|
365
|
-
store.setState({ selectionBoxActive: false });
|
|
366
|
-
if (!node.selected) {
|
|
367
|
-
addSelectedNodes([id]);
|
|
368
|
-
}
|
|
369
|
-
else if (unselect || (node.selected && multiSelectionActive)) {
|
|
370
|
-
unselectNodes({ nodes: [node] });
|
|
371
|
-
requestAnimationFrame(() => nodeRef?.current?.blur());
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
const isNode = (element) => 'id' in element && !('source' in element) && !('target' in element);
|
|
376
|
-
const isEdge = (element) => 'source' in element && 'target' in element;
|
|
377
|
-
const getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {
|
|
378
|
-
if (!node) {
|
|
379
|
-
return {
|
|
380
|
-
x: 0,
|
|
381
|
-
y: 0,
|
|
382
|
-
positionAbsolute: {
|
|
383
|
-
x: 0,
|
|
384
|
-
y: 0,
|
|
385
|
-
},
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
const offsetX = (node.width ?? 0) * nodeOrigin[0];
|
|
389
|
-
const offsetY = (node.height ?? 0) * nodeOrigin[1];
|
|
390
|
-
const position = {
|
|
391
|
-
x: node.position.x - offsetX,
|
|
392
|
-
y: node.position.y - offsetY,
|
|
393
|
-
};
|
|
394
|
-
return {
|
|
395
|
-
...position,
|
|
396
|
-
positionAbsolute: node.positionAbsolute
|
|
397
|
-
? {
|
|
398
|
-
x: node.positionAbsolute.x - offsetX,
|
|
399
|
-
y: node.positionAbsolute.y - offsetY,
|
|
400
|
-
}
|
|
401
|
-
: position,
|
|
402
|
-
};
|
|
403
|
-
};
|
|
404
|
-
const getNodesInside = (nodeInternals, rect, [tx, ty, tScale] = [0, 0, 1], partially = false, excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
|
|
405
|
-
const paneRect = {
|
|
406
|
-
x: (rect.x - tx) / tScale,
|
|
407
|
-
y: (rect.y - ty) / tScale,
|
|
408
|
-
width: rect.width / tScale,
|
|
409
|
-
height: rect.height / tScale,
|
|
410
|
-
};
|
|
411
|
-
const visibleNodes = [];
|
|
412
|
-
nodeInternals.forEach((node) => {
|
|
413
|
-
const { width, height, selectable = true, hidden = false } = node;
|
|
414
|
-
if ((excludeNonSelectableNodes && !selectable) || hidden) {
|
|
415
|
-
return false;
|
|
196
|
+
const getNodesInside = (nodeInternals, rect, [tx, ty, tScale] = [0, 0, 1], partially = false, excludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {
|
|
197
|
+
const paneRect = {
|
|
198
|
+
x: (rect.x - tx) / tScale,
|
|
199
|
+
y: (rect.y - ty) / tScale,
|
|
200
|
+
width: rect.width / tScale,
|
|
201
|
+
height: rect.height / tScale,
|
|
202
|
+
};
|
|
203
|
+
const visibleNodes = [];
|
|
204
|
+
nodeInternals.forEach((node) => {
|
|
205
|
+
const { width, height, selectable = true, hidden = false } = node;
|
|
206
|
+
if ((excludeNonSelectableNodes && !selectable) || hidden) {
|
|
207
|
+
return false;
|
|
416
208
|
}
|
|
417
209
|
const { positionAbsolute } = getNodePositionWithOrigin(node, nodeOrigin);
|
|
418
210
|
const nodeRect = {
|
|
@@ -435,54 +227,6 @@ const getNodesInside = (nodeInternals, rect, [tx, ty, tScale] = [0, 0, 1], parti
|
|
|
435
227
|
});
|
|
436
228
|
return visibleNodes;
|
|
437
229
|
};
|
|
438
|
-
const getMarkerId = (marker, rfId) => {
|
|
439
|
-
if (typeof marker === 'undefined') {
|
|
440
|
-
return '';
|
|
441
|
-
}
|
|
442
|
-
if (typeof marker === 'string') {
|
|
443
|
-
return marker;
|
|
444
|
-
}
|
|
445
|
-
const idPrefix = rfId ? `${rfId}__` : '';
|
|
446
|
-
return `${idPrefix}${Object.keys(marker)
|
|
447
|
-
.sort()
|
|
448
|
-
.map((key) => `${key}=${marker[key]}`)
|
|
449
|
-
.join('&')}`;
|
|
450
|
-
};
|
|
451
|
-
const getEdgeId = ({ source, target }) => `react-diagram__edge-${source}-${target}`;
|
|
452
|
-
const isExistsConnection = (edge, edges) => edges.some((el) => el.source === edge.source && el.target === edge.target);
|
|
453
|
-
const addEdge = (edgeParams, edges) => {
|
|
454
|
-
if (!isEdge(edgeParams)) {
|
|
455
|
-
devWarn('020');
|
|
456
|
-
return edges;
|
|
457
|
-
}
|
|
458
|
-
if (isExistsConnection(edgeParams, edges)) {
|
|
459
|
-
return edges;
|
|
460
|
-
}
|
|
461
|
-
let edge;
|
|
462
|
-
if (edgeParams.id)
|
|
463
|
-
edge = { ...edgeParams };
|
|
464
|
-
else
|
|
465
|
-
edge = {
|
|
466
|
-
...edgeParams,
|
|
467
|
-
id: getEdgeId(edgeParams),
|
|
468
|
-
};
|
|
469
|
-
return edges.concat(edge);
|
|
470
|
-
};
|
|
471
|
-
const updateEdge = (originEdge, newConnection, edges, options = { shouldReplaceId: true }) => {
|
|
472
|
-
const { id: oldEdgeId, ...rest } = originEdge;
|
|
473
|
-
if (!newConnection.source || !newConnection.target)
|
|
474
|
-
devWarn('020');
|
|
475
|
-
const foundEdge = edges.find((e) => e.id === oldEdgeId);
|
|
476
|
-
if (!foundEdge)
|
|
477
|
-
devWarn('021', oldEdgeId);
|
|
478
|
-
const edge = {
|
|
479
|
-
...rest,
|
|
480
|
-
id: options.shouldReplaceId ? getEdgeId(newConnection) : oldEdgeId,
|
|
481
|
-
source: newConnection.source,
|
|
482
|
-
target: newConnection.target,
|
|
483
|
-
};
|
|
484
|
-
return edges.filter((e) => e.id !== oldEdgeId).concat(edge);
|
|
485
|
-
};
|
|
486
230
|
const getRectOfNodes = (nodes, nodeOrigin = [0, 0]) => {
|
|
487
231
|
if (nodes.length === 0) {
|
|
488
232
|
return { x: 0, y: 0, width: 0, height: 0 };
|
|
@@ -499,78 +243,9 @@ const getRectOfNodes = (nodes, nodeOrigin = [0, 0]) => {
|
|
|
499
243
|
}, { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity });
|
|
500
244
|
return boxToRect(box);
|
|
501
245
|
};
|
|
502
|
-
|
|
503
|
-
function isParentSelected(node, nodeInternals) {
|
|
504
|
-
if (!node.parentNode) {
|
|
505
|
-
return false;
|
|
506
|
-
}
|
|
507
|
-
const parentNode = nodeInternals.get(node.parentNode);
|
|
508
|
-
if (!parentNode) {
|
|
509
|
-
return false;
|
|
510
|
-
}
|
|
511
|
-
if (parentNode.selected) {
|
|
512
|
-
return true;
|
|
513
|
-
}
|
|
514
|
-
return isParentSelected(parentNode, nodeInternals);
|
|
515
|
-
}
|
|
516
|
-
const getDragItems = (nodeInternals, nodesDraggable, mousePosition, nodeId) => {
|
|
517
|
-
const filteredNode = Array.from(nodeInternals.values()).filter((n) => {
|
|
518
|
-
const hasSize = n.width && n.height;
|
|
519
|
-
const isSelected = n.selected || n.id === nodeId;
|
|
520
|
-
const hasNoParent = !n.parentNode || !isParentSelected(n, nodeInternals);
|
|
521
|
-
const isDraggable = n.draggable || (nodesDraggable && typeof n.draggable === 'undefined');
|
|
522
|
-
return hasSize && isSelected && hasNoParent && isDraggable;
|
|
523
|
-
});
|
|
524
|
-
return filteredNode.map((n) => ({
|
|
525
|
-
id: n.id,
|
|
526
|
-
position: n.position || { x: 0, y: 0 },
|
|
527
|
-
positionAbsolute: n.positionAbsolute || { x: 0, y: 0 },
|
|
528
|
-
distance: {
|
|
529
|
-
x: mousePosition.x - (n.positionAbsolute?.x ?? 0),
|
|
530
|
-
y: mousePosition.y - (n.positionAbsolute?.y ?? 0),
|
|
531
|
-
},
|
|
532
|
-
extent: n.extent,
|
|
533
|
-
parentNode: n.parentNode,
|
|
534
|
-
width: n.width,
|
|
535
|
-
height: n.height,
|
|
536
|
-
}));
|
|
537
|
-
};
|
|
538
|
-
const calcNextPosition = (node, nextPosition, nodeInternals, nodeExtent, nodeOrigin = [0, 0], onError) => {
|
|
246
|
+
const calcNextPosition = (node, nextPosition, nodeInternals, nodeExtent, nodeOrigin = [0, 0]) => {
|
|
539
247
|
let currentExtent = node.extent || nodeExtent;
|
|
540
|
-
if (node.extent
|
|
541
|
-
if (node.parentNode && node.width && node.height) {
|
|
542
|
-
const parent = nodeInternals.get(node.parentNode);
|
|
543
|
-
const { x: parentX, y: parentY } = getNodePositionWithOrigin(parent, nodeOrigin).positionAbsolute;
|
|
544
|
-
currentExtent =
|
|
545
|
-
parent &&
|
|
546
|
-
isNumeric(parentX) &&
|
|
547
|
-
isNumeric(parentY) &&
|
|
548
|
-
isNumeric(parent.width) &&
|
|
549
|
-
isNumeric(parent.height)
|
|
550
|
-
? [
|
|
551
|
-
[
|
|
552
|
-
parentX + node.width * nodeOrigin[0],
|
|
553
|
-
parentY + node.height * nodeOrigin[1],
|
|
554
|
-
],
|
|
555
|
-
[
|
|
556
|
-
parentX +
|
|
557
|
-
parent.width -
|
|
558
|
-
node.width +
|
|
559
|
-
node.width * nodeOrigin[0],
|
|
560
|
-
parentY +
|
|
561
|
-
parent.height -
|
|
562
|
-
node.height +
|
|
563
|
-
node.height * nodeOrigin[1],
|
|
564
|
-
],
|
|
565
|
-
]
|
|
566
|
-
: currentExtent;
|
|
567
|
-
}
|
|
568
|
-
else {
|
|
569
|
-
onError?.('011');
|
|
570
|
-
currentExtent = nodeExtent;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
else if (node.extent && node.parentNode) {
|
|
248
|
+
if (node.extent && node.parentNode) {
|
|
574
249
|
const parent = nodeInternals.get(node.parentNode);
|
|
575
250
|
const { x: parentX, y: parentY } = getNodePositionWithOrigin(parent, nodeOrigin).positionAbsolute;
|
|
576
251
|
currentExtent = [
|
|
@@ -594,307 +269,1118 @@ const calcNextPosition = (node, nextPosition, nodeInternals, nodeExtent, nodeOri
|
|
|
594
269
|
positionAbsolute,
|
|
595
270
|
};
|
|
596
271
|
};
|
|
597
|
-
const getEventHandlerParams = ({ nodeId, dragItems, nodeInternals, }) => {
|
|
598
|
-
const extentedDragItems = dragItems.map((n) => {
|
|
599
|
-
const node = nodeInternals.get(n.id);
|
|
600
|
-
return {
|
|
601
|
-
...node,
|
|
602
|
-
position: n.position,
|
|
603
|
-
positionAbsolute: n.positionAbsolute,
|
|
604
|
-
};
|
|
605
|
-
});
|
|
606
|
-
return [
|
|
607
|
-
nodeId
|
|
608
|
-
? extentedDragItems.find((n) => n.id === nodeId)
|
|
609
|
-
: extentedDragItems[0],
|
|
610
|
-
extentedDragItems,
|
|
611
|
-
];
|
|
612
|
-
};
|
|
613
|
-
const hasSelector = (target, selector, nodeRef) => {
|
|
614
|
-
let current = target;
|
|
615
|
-
do {
|
|
616
|
-
if (current?.matches(selector))
|
|
617
|
-
return true;
|
|
618
|
-
if (current === nodeRef.current)
|
|
619
|
-
return false;
|
|
620
|
-
current = current.parentElement;
|
|
621
|
-
} while (current);
|
|
622
|
-
return false;
|
|
623
|
-
};
|
|
624
|
-
const hasChangedPosition = (beforePositions, currentPosition) => beforePositions.x !== currentPosition.x ||
|
|
625
|
-
beforePositions.y !== currentPosition.y;
|
|
626
272
|
|
|
627
|
-
const
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
return foo.toString() === bar.toString();
|
|
639
|
-
if (constructor === Array) {
|
|
640
|
-
if ((length = foo.length) === bar.length) {
|
|
641
|
-
while (length-- && deepEqual(foo[length], bar[length]))
|
|
642
|
-
;
|
|
643
|
-
}
|
|
644
|
-
return length === -1;
|
|
645
|
-
}
|
|
646
|
-
if (!constructor || typeof foo === 'object') {
|
|
647
|
-
length = 0;
|
|
648
|
-
for (constructor in foo) {
|
|
649
|
-
if (has.call(foo, constructor) &&
|
|
650
|
-
++length &&
|
|
651
|
-
!has.call(bar, constructor))
|
|
652
|
-
return false;
|
|
653
|
-
if (!(constructor in bar) ||
|
|
654
|
-
!deepEqual(foo[constructor], bar[constructor]))
|
|
655
|
-
return false;
|
|
656
|
-
}
|
|
657
|
-
return Object.keys(bar).length === length;
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
return foo !== foo && bar !== bar;
|
|
273
|
+
const getMarkerId = (marker, id) => {
|
|
274
|
+
if (typeof marker === 'undefined')
|
|
275
|
+
return '';
|
|
276
|
+
if (typeof marker === 'string')
|
|
277
|
+
return marker;
|
|
278
|
+
const idPrefix = id ? `${id}__` : '';
|
|
279
|
+
const markerKeys = Object.keys(marker);
|
|
280
|
+
return `${idPrefix}${markerKeys
|
|
281
|
+
.sort()
|
|
282
|
+
.map((key) => `${key}=${marker[key]}`)
|
|
283
|
+
.join('&')}`;
|
|
661
284
|
};
|
|
285
|
+
// export function createMarkerIds(
|
|
286
|
+
// edges: EdgeBase[],
|
|
287
|
+
// {
|
|
288
|
+
// id,
|
|
289
|
+
// defaultColor,
|
|
290
|
+
// defaultMarkerStart,
|
|
291
|
+
// defaultMarkerEnd,
|
|
292
|
+
// }: {
|
|
293
|
+
// id?: string | null;
|
|
294
|
+
// defaultColor?: string;
|
|
295
|
+
// defaultMarkerStart?: EdgeMarker;
|
|
296
|
+
// defaultMarkerEnd?: EdgeMarker;
|
|
297
|
+
// },
|
|
298
|
+
// ) {
|
|
299
|
+
// const ids = new Set<string>();
|
|
300
|
+
// return edges
|
|
301
|
+
// .reduce<(EdgeMarker & { id: string })[]>((markers, edge) => {
|
|
302
|
+
// [
|
|
303
|
+
// edge.markerStart || defaultMarkerStart,
|
|
304
|
+
// edge.markerEnd || defaultMarkerEnd,
|
|
305
|
+
// ].forEach((marker) => {
|
|
306
|
+
// if (marker && typeof marker === 'object') {
|
|
307
|
+
// const markerId = getMarkerId(marker, id);
|
|
308
|
+
// if (!ids.has(markerId)) {
|
|
309
|
+
// markers.push({
|
|
310
|
+
// id: markerId,
|
|
311
|
+
// color: marker.color || defaultColor,
|
|
312
|
+
// ...marker,
|
|
313
|
+
// });
|
|
314
|
+
// ids.add(markerId);
|
|
315
|
+
// }
|
|
316
|
+
// }
|
|
317
|
+
// });
|
|
318
|
+
// return markers;
|
|
319
|
+
// }, [])
|
|
320
|
+
// .sort((a, b) => a.id.localeCompare(b.id));
|
|
321
|
+
// }
|
|
662
322
|
|
|
663
|
-
|
|
664
|
-
const
|
|
665
|
-
const
|
|
666
|
-
const
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
323
|
+
const getEdgeCenter = ({ sourceX, sourceY, targetX, targetY, }) => {
|
|
324
|
+
const xOffset = Math.abs(targetX - sourceX) / 2;
|
|
325
|
+
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
|
|
326
|
+
const yOffset = Math.abs(targetY - sourceY) / 2;
|
|
327
|
+
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
|
328
|
+
return [centerX, centerY, xOffset, yOffset];
|
|
329
|
+
};
|
|
330
|
+
const getEdgeId = ({ source, sourcePort, target, targetPort, }) => `react-diagram__edge-${source}${sourcePort}-${target}${targetPort}`;
|
|
331
|
+
const isExistsConnection = (edge, edges) => edges.some((el) => el.source === edge.source &&
|
|
332
|
+
el.target === edge.target &&
|
|
333
|
+
(el.sourcePort === edge.sourcePort ||
|
|
334
|
+
(!el.sourcePort && !edge.sourcePort)) &&
|
|
335
|
+
(el.targetPort === edge.targetPort ||
|
|
336
|
+
(!el.targetPort && !edge.targetPort)));
|
|
337
|
+
const addEdge = (edgeParams, edges) => {
|
|
338
|
+
if (!isCoreEdge(edgeParams)) {
|
|
339
|
+
devWarn('020');
|
|
340
|
+
return edges;
|
|
341
|
+
}
|
|
342
|
+
if (isExistsConnection(edgeParams, edges)) {
|
|
343
|
+
return edges;
|
|
344
|
+
}
|
|
345
|
+
let edge;
|
|
346
|
+
if (edgeParams.sourcePort === null) {
|
|
347
|
+
delete edgeParams.sourcePort;
|
|
348
|
+
}
|
|
349
|
+
if (edgeParams.targetPort === null) {
|
|
350
|
+
delete edgeParams.targetPort;
|
|
351
|
+
}
|
|
352
|
+
if (edgeParams.id)
|
|
353
|
+
edge = { ...edgeParams };
|
|
354
|
+
else
|
|
355
|
+
edge = {
|
|
356
|
+
...edgeParams,
|
|
357
|
+
id: getEdgeId(edgeParams),
|
|
358
|
+
};
|
|
359
|
+
return edges.concat(edge);
|
|
360
|
+
};
|
|
361
|
+
const updateEdge = (originEdge, newConnection, edges, options = { shouldReplaceId: true }) => {
|
|
362
|
+
const { id: oldEdgeId, ...rest } = originEdge;
|
|
363
|
+
if (!newConnection.source || !newConnection.target)
|
|
364
|
+
devWarn('020');
|
|
365
|
+
const foundEdge = edges.find((e) => e.id === oldEdgeId);
|
|
366
|
+
if (!foundEdge)
|
|
367
|
+
devWarn('021', oldEdgeId);
|
|
368
|
+
const edge = {
|
|
369
|
+
...rest,
|
|
370
|
+
id: options.shouldReplaceId ? getEdgeId(newConnection) : oldEdgeId,
|
|
371
|
+
source: newConnection.source,
|
|
372
|
+
target: newConnection.target,
|
|
373
|
+
};
|
|
374
|
+
return edges.filter((e) => e.id !== oldEdgeId).concat(edge);
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
const HANDLE_DIRECTIONS = {
|
|
378
|
+
[Position.Left]: { x: -1, y: 0 },
|
|
379
|
+
[Position.Right]: { x: 1, y: 0 },
|
|
380
|
+
[Position.Top]: { x: 0, y: -1 },
|
|
381
|
+
[Position.Bottom]: { x: 0, y: 1 },
|
|
382
|
+
};
|
|
383
|
+
const getDirection = ({ source, sourcePosition = Position.Bottom, target, }) => {
|
|
384
|
+
if (sourcePosition === Position.Left || sourcePosition === Position.Right) {
|
|
385
|
+
// when source Node position is on the left side of a Port of target Node => x = 1
|
|
386
|
+
return source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 };
|
|
387
|
+
}
|
|
388
|
+
//when source Node position is above of a Port of target Node => y = 1
|
|
389
|
+
return source.y < target.y ? { x: 0, y: 1 } : { x: 0, y: -1 };
|
|
390
|
+
};
|
|
391
|
+
const distance = (a, b) => Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
|
|
392
|
+
const getPoints = ({ source, sourcePosition = Position.Bottom, target, targetPosition = Position.Top, center, offset, }) => {
|
|
393
|
+
const sourceDir = HANDLE_DIRECTIONS[sourcePosition];
|
|
394
|
+
const targetDir = HANDLE_DIRECTIONS[targetPosition];
|
|
395
|
+
const sourceGapped = {
|
|
396
|
+
x: source.x + sourceDir.x * offset,
|
|
397
|
+
y: source.y + sourceDir.y * offset,
|
|
398
|
+
};
|
|
399
|
+
const targetGapped = {
|
|
400
|
+
x: target.x + targetDir.x * offset,
|
|
401
|
+
y: target.y + targetDir.y * offset,
|
|
402
|
+
};
|
|
403
|
+
const direction = getDirection({
|
|
404
|
+
source: sourceGapped,
|
|
405
|
+
sourcePosition,
|
|
406
|
+
target: targetGapped,
|
|
407
|
+
});
|
|
408
|
+
const dirAccessor = direction.x !== 0 ? 'x' : 'y';
|
|
409
|
+
const currentDirection = direction[dirAccessor];
|
|
410
|
+
let points = [];
|
|
411
|
+
let centerX = 0, centerY = 0;
|
|
412
|
+
const [defaultCenterX, defaultCenterY, defaultOffsetX, defaultOffsetY] = getEdgeCenter({
|
|
413
|
+
sourceX: source.x,
|
|
414
|
+
sourceY: source.y,
|
|
415
|
+
targetX: target.x,
|
|
416
|
+
targetY: target.y,
|
|
417
|
+
});
|
|
418
|
+
const isSourceAndTargetPositionsParallel = sourceDir[dirAccessor] * targetDir[dirAccessor] === -1;
|
|
419
|
+
if (isSourceAndTargetPositionsParallel) {
|
|
420
|
+
centerX = center.x || defaultCenterX;
|
|
421
|
+
centerY = center.y || defaultCenterY;
|
|
422
|
+
const verticalSplit = [
|
|
423
|
+
{ x: centerX, y: sourceGapped.y },
|
|
424
|
+
{ x: centerX, y: targetGapped.y },
|
|
425
|
+
];
|
|
426
|
+
const horizontalSplit = [
|
|
427
|
+
{ x: sourceGapped.x, y: centerY },
|
|
428
|
+
{ x: targetGapped.x, y: centerY },
|
|
429
|
+
];
|
|
430
|
+
const centerLineIsBent = sourceDir[dirAccessor] !== currentDirection;
|
|
431
|
+
if (centerLineIsBent) {
|
|
432
|
+
points = dirAccessor === 'x' ? horizontalSplit : verticalSplit;
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
points = dirAccessor === 'x' ? verticalSplit : horizontalSplit;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
const pathPoints = [source, sourceGapped, ...points, targetGapped, target];
|
|
439
|
+
return [pathPoints, centerX, centerY, defaultOffsetX, defaultOffsetY];
|
|
440
|
+
};
|
|
441
|
+
const getBend = (a, b, c, size) => {
|
|
442
|
+
const bendSize = Math.min(distance(a, b) / 2, distance(b, c) / 2, size);
|
|
443
|
+
const { x, y } = b;
|
|
444
|
+
// no bend
|
|
445
|
+
if ((a.x === x && x === c.x) || (a.y === y && y === c.y)) {
|
|
446
|
+
return `L${x} ${y}`;
|
|
447
|
+
}
|
|
448
|
+
// first segment is horizontal
|
|
449
|
+
if (a.y === y) {
|
|
450
|
+
const xDir = a.x < c.x ? -1 : 1;
|
|
451
|
+
const yDir = a.y < c.y ? 1 : -1;
|
|
452
|
+
return `L ${x + bendSize * xDir},${y}Q ${x},${y} ${x},${y + bendSize * yDir}`;
|
|
453
|
+
}
|
|
454
|
+
const xDir = a.x < c.x ? 1 : -1;
|
|
455
|
+
const yDir = a.y < c.y ? -1 : 1;
|
|
456
|
+
return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`;
|
|
457
|
+
};
|
|
458
|
+
const getStepPath = ({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, borderRadius = 5, centerX, centerY, offset = 20, }) => {
|
|
459
|
+
const [points, labelX, labelY, offsetX, offsetY] = getPoints({
|
|
460
|
+
source: { x: sourceX, y: sourceY },
|
|
461
|
+
sourcePosition,
|
|
462
|
+
target: { x: targetX, y: targetY },
|
|
463
|
+
targetPosition,
|
|
464
|
+
center: { x: centerX, y: centerY },
|
|
465
|
+
offset,
|
|
466
|
+
});
|
|
467
|
+
const path = points.reduce((res, p, i) => {
|
|
468
|
+
let segment = '';
|
|
469
|
+
if (i > 0 && i < points.length - 1) {
|
|
470
|
+
segment = getBend(points[i - 1], p, points[i + 1], borderRadius);
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
segment = `${i === 0 ? 'M' : 'L'}${p.x} ${p.y}`;
|
|
474
|
+
}
|
|
475
|
+
res += segment;
|
|
476
|
+
return res;
|
|
477
|
+
}, '');
|
|
478
|
+
return [path, labelX, labelY, offsetX, offsetY];
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Get a straight path from source to target port
|
|
483
|
+
* @param params.sourceX - The x position of the source port
|
|
484
|
+
* @param params.sourceY - The y position of the source port
|
|
485
|
+
* @param params.targetX - The x position of the target port
|
|
486
|
+
* @param params.targetY - The y position of the target port
|
|
487
|
+
* @returns A path string you can use in an SVG, the labelX and labelY position (center of path) and offsetX, offsetY between source port and label
|
|
488
|
+
* @example
|
|
489
|
+
* const source = { x: 0, y: 20 };
|
|
490
|
+
const target = { x: 150, y: 100 };
|
|
491
|
+
|
|
492
|
+
const [path, labelX, labelY, offsetX, offsetY] = getStraightPath({
|
|
493
|
+
sourceX: source.x,
|
|
494
|
+
sourceY: source.y,
|
|
495
|
+
sourcePosition: Position.Right,
|
|
496
|
+
targetX: target.x,
|
|
497
|
+
targetY: target.y,
|
|
498
|
+
targetPosition: Position.Left,
|
|
499
|
+
});
|
|
500
|
+
*/
|
|
501
|
+
const getStraightPath = ({ sourceX, sourceY, targetX, targetY, }) => {
|
|
502
|
+
const [labelX, labelY, offsetX, offsetY] = getEdgeCenter({
|
|
503
|
+
sourceX,
|
|
504
|
+
sourceY,
|
|
505
|
+
targetX,
|
|
506
|
+
targetY,
|
|
507
|
+
});
|
|
508
|
+
return [
|
|
509
|
+
`M ${sourceX},${sourceY}L ${targetX},${targetY}`,
|
|
510
|
+
labelX,
|
|
511
|
+
labelY,
|
|
512
|
+
offsetX,
|
|
513
|
+
offsetY,
|
|
514
|
+
];
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
const getBezierEdgeCenter = ({ sourceX, sourceY, targetX, targetY, sourceControlX, sourceControlY, targetControlX, targetControlY, }) => {
|
|
518
|
+
// cubic bezier t=0.5 mid point, not the actual mid point, but easy to calculate
|
|
519
|
+
// https://stackoverflow.com/questions/67516101/how-to-find-distance-mid-point-of-bezier-curve
|
|
520
|
+
const midPoint = 0.5;
|
|
521
|
+
const point = 0.125;
|
|
522
|
+
const controlPoint = midPoint - point;
|
|
523
|
+
const centerX = sourceX * point +
|
|
524
|
+
sourceControlX * controlPoint +
|
|
525
|
+
targetControlX * controlPoint +
|
|
526
|
+
targetX * point;
|
|
527
|
+
const centerY = sourceY * point +
|
|
528
|
+
sourceControlY * controlPoint +
|
|
529
|
+
targetControlY * controlPoint +
|
|
530
|
+
targetY * point;
|
|
531
|
+
const offsetX = Math.abs(centerX - sourceX);
|
|
532
|
+
const offsetY = Math.abs(centerY - sourceY);
|
|
533
|
+
return [centerX, centerY, offsetX, offsetY];
|
|
534
|
+
};
|
|
535
|
+
const calculateControlOffset = (distance, curvature) => {
|
|
536
|
+
if (distance >= 0) {
|
|
537
|
+
return 0.5 * distance;
|
|
538
|
+
}
|
|
539
|
+
return curvature * 25 * Math.sqrt(-distance);
|
|
540
|
+
};
|
|
541
|
+
const getControlWithCurvature = ({ pos, x1, y1, x2, y2, c, }) => {
|
|
542
|
+
switch (pos) {
|
|
543
|
+
case Position.Left:
|
|
544
|
+
return [x1 - calculateControlOffset(x1 - x2, c), y1];
|
|
545
|
+
case Position.Right:
|
|
546
|
+
return [x1 + calculateControlOffset(x2 - x1, c), y1];
|
|
547
|
+
case Position.Top:
|
|
548
|
+
return [x1, y1 - calculateControlOffset(y1 - y2, c)];
|
|
549
|
+
case Position.Bottom:
|
|
550
|
+
return [x1, y1 + calculateControlOffset(y2 - y1, c)];
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
/**
|
|
554
|
+
* Get a bezier path from source to target port
|
|
555
|
+
* @param params.sourceX - The x position of the source port
|
|
556
|
+
* @param params.sourceY - The y position of the source port
|
|
557
|
+
* @param params.sourcePosition - The position of the source port (default: Position.Bottom)
|
|
558
|
+
* @param params.targetX - The x position of the target port
|
|
559
|
+
* @param params.targetY - The y position of the target port
|
|
560
|
+
* @param params.targetPosition - The position of the target port (default: Position.Top)
|
|
561
|
+
* @param params.curvature - The curvature of the bezier edge
|
|
562
|
+
* @returns A path string you can use in an SVG, the labelX and labelY position (center of path) and offsetX, offsetY between source port and label
|
|
563
|
+
* @example
|
|
564
|
+
* const source = { x: 0, y: 20 };
|
|
565
|
+
const target = { x: 150, y: 100 };
|
|
566
|
+
|
|
567
|
+
const [path, labelX, labelY, offsetX, offsetY] = getBezierPath({
|
|
568
|
+
sourceX: source.x,
|
|
569
|
+
sourceY: source.y,
|
|
570
|
+
sourcePosition: Position.Right,
|
|
571
|
+
targetX: target.x,
|
|
572
|
+
targetY: target.y,
|
|
573
|
+
targetPosition: Position.Left,
|
|
574
|
+
});
|
|
575
|
+
*/
|
|
576
|
+
const getBezierPath = ({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, curvature = 0.25, }) => {
|
|
577
|
+
const [sourceControlX, sourceControlY] = getControlWithCurvature({
|
|
578
|
+
pos: sourcePosition,
|
|
579
|
+
x1: sourceX,
|
|
580
|
+
y1: sourceY,
|
|
581
|
+
x2: targetX,
|
|
582
|
+
y2: targetY,
|
|
583
|
+
c: curvature,
|
|
584
|
+
});
|
|
585
|
+
const [targetControlX, targetControlY] = getControlWithCurvature({
|
|
586
|
+
pos: targetPosition,
|
|
587
|
+
x1: targetX,
|
|
588
|
+
y1: targetY,
|
|
589
|
+
x2: sourceX,
|
|
590
|
+
y2: sourceY,
|
|
591
|
+
c: curvature,
|
|
592
|
+
});
|
|
593
|
+
const [labelX, labelY, offsetX, offsetY] = getBezierEdgeCenter({
|
|
594
|
+
sourceX,
|
|
595
|
+
sourceY,
|
|
596
|
+
targetX,
|
|
597
|
+
targetY,
|
|
598
|
+
sourceControlX,
|
|
599
|
+
sourceControlY,
|
|
600
|
+
targetControlX,
|
|
601
|
+
targetControlY,
|
|
602
|
+
});
|
|
603
|
+
return [
|
|
604
|
+
`M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`,
|
|
605
|
+
labelX,
|
|
606
|
+
labelY,
|
|
607
|
+
offsetX,
|
|
608
|
+
offsetY,
|
|
609
|
+
];
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
const getPorts = (node, portBounds, type, currentPort) => (portBounds[type] || []).reduce((res, h) => {
|
|
613
|
+
if (`${node.id}-${h.id}-${type}` !== currentPort) {
|
|
614
|
+
res.push({
|
|
615
|
+
portId: h.id || null,
|
|
616
|
+
portType: type,
|
|
617
|
+
nodeId: node.id,
|
|
618
|
+
x: (node.positionAbsolute?.x ?? 0) + h.x + h.width / 2,
|
|
619
|
+
y: (node.positionAbsolute?.y ?? 0) + h.y + h.height / 2,
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
return res;
|
|
623
|
+
}, []);
|
|
624
|
+
const getPortType = (PortDomNode) => {
|
|
625
|
+
if (PortDomNode?.classList.contains('target')) {
|
|
626
|
+
return 'target';
|
|
627
|
+
}
|
|
628
|
+
else if (PortDomNode?.classList.contains('source')) {
|
|
629
|
+
return 'source';
|
|
630
|
+
}
|
|
631
|
+
return null;
|
|
632
|
+
};
|
|
633
|
+
const getAllPort = ({ nodes, nodeId, portId, portType, }) => nodes.reduce((res, node) => {
|
|
634
|
+
if (node[internalsSymbol$1]) {
|
|
635
|
+
const { portBounds } = node[internalsSymbol$1];
|
|
636
|
+
let sourcePorts = [];
|
|
637
|
+
let targetPorts = [];
|
|
638
|
+
if (portBounds) {
|
|
639
|
+
sourcePorts = getPorts(node, portBounds, 'source', `${nodeId}-${portId}-${portType}`);
|
|
640
|
+
targetPorts = getPorts(node, portBounds, 'target', `${nodeId}-${portId}-${portType}`);
|
|
641
|
+
}
|
|
642
|
+
res.push(...sourcePorts, ...targetPorts);
|
|
643
|
+
}
|
|
644
|
+
return res;
|
|
645
|
+
}, []);
|
|
646
|
+
const getClosestPort = (pos, connectionRadius, ports) => {
|
|
647
|
+
let closestPort = null;
|
|
648
|
+
let minDistance = Infinity;
|
|
649
|
+
ports.forEach((port) => {
|
|
650
|
+
const distance = Math.sqrt(Math.pow(port.x - pos.x, 2) + Math.pow(port.y - pos.y, 2));
|
|
651
|
+
if (distance <= connectionRadius && distance < minDistance) {
|
|
652
|
+
minDistance = distance;
|
|
653
|
+
closestPort = port;
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
return closestPort;
|
|
657
|
+
};
|
|
658
|
+
const getConnection = (event, port, fromNodeId, fromPortId, fromType, doc) => {
|
|
659
|
+
const isTarget = fromType === 'target';
|
|
660
|
+
const result = {
|
|
661
|
+
isValid: false,
|
|
662
|
+
connection: null,
|
|
663
|
+
endPort: null,
|
|
664
|
+
};
|
|
665
|
+
const PortDomNode = doc.querySelector(`.react-diagram__port[data-id="${port?.nodeId}-${port?.portId}-${port?.portType}"]`);
|
|
666
|
+
const { x, y } = getEventPosition(event);
|
|
667
|
+
const ElementFromPoint = doc.elementFromPoint(x, y);
|
|
668
|
+
const Port = ElementFromPoint?.classList.contains('react-diagram__port')
|
|
669
|
+
? ElementFromPoint
|
|
670
|
+
: PortDomNode;
|
|
671
|
+
if (Port) {
|
|
672
|
+
const portType = getPortType(Port);
|
|
673
|
+
const toNodeId = Port.getAttribute('data-nodeid');
|
|
674
|
+
const toPortId = Port.getAttribute('data-portid');
|
|
675
|
+
const connection = {
|
|
676
|
+
source: isTarget ? toNodeId : fromNodeId,
|
|
677
|
+
target: isTarget ? fromNodeId : toNodeId,
|
|
678
|
+
sourcePort: isTarget ? port?.portId || null : fromPortId,
|
|
679
|
+
targetPort: isTarget ? fromPortId : port?.portId || null,
|
|
680
|
+
};
|
|
681
|
+
result.connection = connection;
|
|
682
|
+
const isValid = (isTarget && portType === 'source') ||
|
|
683
|
+
(!isTarget && portType === 'target');
|
|
684
|
+
if (isValid) {
|
|
685
|
+
result.isValid = true;
|
|
686
|
+
result.endPort = {
|
|
687
|
+
nodeId: toNodeId,
|
|
688
|
+
portId: toPortId,
|
|
689
|
+
portType,
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
return result;
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
let connectionStartPort = null;
|
|
697
|
+
const onPointerDown = ({ isAnchor = false, event, nodeId, portId, portType, domNode, autoPanOnConnect, connectionRadius, nodes, getTransform, cancelConnection, onConnectStart, onConnect, onConnectEnd, onEdgeUpdateEnd, panBy, updateConnection, }) => {
|
|
698
|
+
const doc = getHostForElement(event.target);
|
|
699
|
+
const containerBounds = domNode?.getBoundingClientRect();
|
|
700
|
+
const { x, y } = getEventPosition(event);
|
|
701
|
+
const clickedPort = doc?.elementFromPoint(x, y);
|
|
702
|
+
const clickedPortType = isAnchor ? portType : getPortType(clickedPort);
|
|
703
|
+
const allPort = getAllPort({
|
|
704
|
+
nodes,
|
|
705
|
+
nodeId,
|
|
706
|
+
portId,
|
|
707
|
+
portType,
|
|
708
|
+
});
|
|
709
|
+
let connectionPosition = getEventPosition(event, containerBounds);
|
|
710
|
+
let closestPort = null;
|
|
711
|
+
let isValid = false;
|
|
712
|
+
let connection = null;
|
|
713
|
+
let autoPanId = 0;
|
|
714
|
+
let autoPanStarted = false;
|
|
715
|
+
if (!containerBounds || !portType) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
const autoPan = () => {
|
|
719
|
+
if (!autoPanOnConnect) {
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
const [xMovement, yMovement] = calcAutoPanPosition(connectionPosition, containerBounds);
|
|
723
|
+
panBy({ x: xMovement, y: yMovement });
|
|
724
|
+
autoPanId = requestAnimationFrame(autoPan);
|
|
725
|
+
};
|
|
726
|
+
connectionStartPort = {
|
|
727
|
+
nodeId,
|
|
728
|
+
portId,
|
|
729
|
+
portType: clickedPortType,
|
|
730
|
+
};
|
|
731
|
+
updateConnection({
|
|
732
|
+
connectionPosition,
|
|
733
|
+
connectionStartPort,
|
|
734
|
+
connectionEndPort: null,
|
|
735
|
+
});
|
|
736
|
+
onConnectStart?.(event, { nodeId, portId, portType });
|
|
737
|
+
const onPointerMove = (event) => {
|
|
738
|
+
const transform = getTransform();
|
|
739
|
+
connectionPosition = getEventPosition(event, containerBounds);
|
|
740
|
+
closestPort = getClosestPort(pointToRendererPoint(connectionPosition, transform), connectionRadius, allPort);
|
|
741
|
+
if (!autoPanStarted) {
|
|
742
|
+
autoPan();
|
|
743
|
+
autoPanStarted = true;
|
|
744
|
+
}
|
|
745
|
+
const result = getConnection(event, closestPort, nodeId, portId, portType, doc);
|
|
746
|
+
isValid = result.isValid;
|
|
747
|
+
connection = result.connection;
|
|
748
|
+
updateConnection({
|
|
749
|
+
connectionPosition: closestPort && isValid
|
|
750
|
+
? rendererPointToPoint(closestPort, transform)
|
|
751
|
+
: connectionPosition,
|
|
752
|
+
connectionStartPort,
|
|
753
|
+
connectionEndPort: result.endPort,
|
|
754
|
+
});
|
|
755
|
+
};
|
|
756
|
+
const onPointerUp = (event) => {
|
|
757
|
+
if (isValid && connection)
|
|
758
|
+
onConnect?.(connection);
|
|
759
|
+
onConnectEnd?.(event);
|
|
760
|
+
if (portType) {
|
|
761
|
+
onEdgeUpdateEnd?.(event);
|
|
762
|
+
}
|
|
763
|
+
cancelConnection();
|
|
764
|
+
cancelAnimationFrame(autoPanId);
|
|
765
|
+
isValid = false;
|
|
766
|
+
connection = null;
|
|
767
|
+
autoPanStarted = false;
|
|
768
|
+
doc.removeEventListener('mousemove', onPointerMove);
|
|
769
|
+
doc.removeEventListener('mouseup', onPointerUp);
|
|
770
|
+
doc.removeEventListener('touchmove', onPointerMove);
|
|
771
|
+
doc.removeEventListener('touchend', onPointerUp);
|
|
772
|
+
};
|
|
773
|
+
doc.addEventListener('mousemove', onPointerMove);
|
|
774
|
+
doc.addEventListener('mouseup', onPointerUp);
|
|
775
|
+
doc.addEventListener('touchmove', onPointerMove);
|
|
776
|
+
doc.addEventListener('touchend', onPointerUp);
|
|
777
|
+
};
|
|
778
|
+
const CosmosPort = {
|
|
779
|
+
onPointerDown,
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
const isParentSelected = (node, nodeInternals) => {
|
|
783
|
+
if (!node.parentNode) {
|
|
784
|
+
return false;
|
|
785
|
+
}
|
|
786
|
+
const parentNode = nodeInternals.get(node.parentNode);
|
|
787
|
+
if (!parentNode) {
|
|
788
|
+
return false;
|
|
789
|
+
}
|
|
790
|
+
if (parentNode.selected) {
|
|
791
|
+
return true;
|
|
792
|
+
}
|
|
793
|
+
return isParentSelected(parentNode, nodeInternals);
|
|
794
|
+
};
|
|
795
|
+
const hasSelector = (target, selector, domNode) => {
|
|
796
|
+
let current = target;
|
|
797
|
+
do {
|
|
798
|
+
if (current?.matches(selector))
|
|
799
|
+
return true;
|
|
800
|
+
if (current === domNode)
|
|
801
|
+
return false;
|
|
802
|
+
current = current.parentElement;
|
|
803
|
+
} while (current);
|
|
804
|
+
return false;
|
|
805
|
+
};
|
|
806
|
+
const hasChangedPosition = (beforePositions, currentPosition) => beforePositions.x !== currentPosition.x ||
|
|
807
|
+
beforePositions.y !== currentPosition.y;
|
|
808
|
+
const getDragItems = (nodeInternals, nodesDraggable, mousePosition, nodeId) => {
|
|
809
|
+
const filteredNode = Array.from(nodeInternals.values()).filter((n) => {
|
|
810
|
+
const hasSize = n.width && n.height;
|
|
811
|
+
const isSelected = n.selected || n.id === nodeId;
|
|
812
|
+
const hasNoParent = !n.parentNode || !isParentSelected(n, nodeInternals);
|
|
813
|
+
const isDraggable = n.draggable || (nodesDraggable && typeof n.draggable === 'undefined');
|
|
814
|
+
return hasSize && isSelected && hasNoParent && isDraggable;
|
|
815
|
+
});
|
|
816
|
+
return filteredNode.map((n) => ({
|
|
817
|
+
id: n.id,
|
|
818
|
+
position: n.position || { x: 0, y: 0 },
|
|
819
|
+
positionAbsolute: n.positionAbsolute || { x: 0, y: 0 },
|
|
820
|
+
distance: {
|
|
821
|
+
x: mousePosition.x - (n.positionAbsolute?.x ?? 0),
|
|
822
|
+
y: mousePosition.y - (n.positionAbsolute?.y ?? 0),
|
|
823
|
+
},
|
|
824
|
+
extent: n.extent,
|
|
825
|
+
parentNode: n.parentNode,
|
|
826
|
+
width: n.width || 0,
|
|
827
|
+
height: n.height || 0,
|
|
828
|
+
}));
|
|
829
|
+
};
|
|
830
|
+
const getEventHandlerParams = ({ nodeId, dragItems, nodeInternals, }) => {
|
|
831
|
+
const extentedDragItems = dragItems.map((n) => {
|
|
832
|
+
const node = nodeInternals.get(n.id);
|
|
833
|
+
return {
|
|
834
|
+
...node,
|
|
835
|
+
position: n.position,
|
|
836
|
+
positionAbsolute: n.positionAbsolute,
|
|
837
|
+
};
|
|
838
|
+
});
|
|
839
|
+
return [
|
|
840
|
+
nodeId
|
|
841
|
+
? extentedDragItems.find((n) => n.id === nodeId)
|
|
842
|
+
: extentedDragItems[0],
|
|
843
|
+
extentedDragItems,
|
|
844
|
+
];
|
|
845
|
+
};
|
|
846
|
+
|
|
847
|
+
const isDragItem = (node) => 'distance' in node;
|
|
848
|
+
const CosmosDrag = ({ getStore, onNodeMouseDown, onDragStart, onDrag, onDragEnd, }) => {
|
|
849
|
+
let dragItems = [];
|
|
850
|
+
let containerBounds = null;
|
|
851
|
+
let mousePosition = { x: 0, y: 0 };
|
|
852
|
+
let lastPosition = { x: 0, y: 0 };
|
|
853
|
+
let dragEvent = null;
|
|
854
|
+
let autoPanStarted = false;
|
|
855
|
+
let autoPanId = 0;
|
|
856
|
+
let d3Selection = null;
|
|
857
|
+
const update = ({ domNode, nodeId, noDragClassName }) => {
|
|
858
|
+
const updateNodePosition = (pointerPositions, dragEnd = false) => (dragItem) => {
|
|
859
|
+
if (!isDragItem(dragItem))
|
|
860
|
+
return;
|
|
861
|
+
const { nodeInternals, nodeExtent, nodeOrigin, smoothStep, gridStep, } = getStore();
|
|
862
|
+
const { distance, width, height } = dragItem;
|
|
863
|
+
const { x, y, getStepPosition } = pointerPositions;
|
|
864
|
+
let nextPosition = {
|
|
865
|
+
x: x - distance.x,
|
|
866
|
+
y: y - distance.y,
|
|
867
|
+
};
|
|
868
|
+
if (gridStep && getStepPosition) {
|
|
869
|
+
const nodeSize = { width, height };
|
|
870
|
+
const stepPosition = getStepPosition({
|
|
871
|
+
position: nextPosition,
|
|
872
|
+
nodeSize,
|
|
873
|
+
});
|
|
874
|
+
if (!smoothStep || (smoothStep && dragEnd)) {
|
|
875
|
+
nextPosition = stepPosition;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
const updatedPosition = calcNextPosition(dragItem, nextPosition, nodeInternals, nodeExtent, nodeOrigin);
|
|
879
|
+
const hasChange = hasChangedPosition(dragItem.position, updatedPosition.position);
|
|
880
|
+
if (!hasChange)
|
|
881
|
+
return;
|
|
882
|
+
dragItem.position = updatedPosition.position;
|
|
883
|
+
dragItem.positionAbsolute = updatedPosition.positionAbsolute;
|
|
884
|
+
};
|
|
885
|
+
d3Selection = select(domNode);
|
|
886
|
+
const updateNodes = (pointerPosition) => {
|
|
887
|
+
const { nodeInternals, updateNodesPosition } = getStore();
|
|
888
|
+
const { x, y } = pointerPosition;
|
|
889
|
+
lastPosition = { x, y };
|
|
890
|
+
updateNodesPosition(dragItems, true, updateNodePosition(pointerPosition));
|
|
891
|
+
if (onDrag && dragEvent) {
|
|
892
|
+
const [currentNode, nodes] = getEventHandlerParams({
|
|
893
|
+
nodeId,
|
|
894
|
+
dragItems: dragItems,
|
|
895
|
+
nodeInternals,
|
|
896
|
+
});
|
|
897
|
+
onDrag(dragEvent, dragItems, currentNode, nodes);
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
const autoPan = () => {
|
|
901
|
+
if (!containerBounds) {
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
const [xMovement, yMovement] = calcAutoPanPosition(mousePosition, containerBounds);
|
|
905
|
+
if (xMovement !== 0 || yMovement !== 0) {
|
|
906
|
+
const { transform, panBy } = getStore();
|
|
907
|
+
lastPosition.x -= xMovement / transform[2];
|
|
908
|
+
lastPosition.y -= yMovement / transform[2];
|
|
909
|
+
updateNodes(lastPosition);
|
|
910
|
+
panBy({ x: xMovement, y: yMovement });
|
|
911
|
+
}
|
|
912
|
+
autoPanId = requestAnimationFrame(autoPan);
|
|
913
|
+
};
|
|
914
|
+
const startDrag = (event) => {
|
|
915
|
+
const { nodeInternals, nodesDraggable, domNode, transform, gridStep, centerStep, } = getStore();
|
|
916
|
+
if (nodeId) {
|
|
917
|
+
onNodeMouseDown?.(nodeId);
|
|
918
|
+
}
|
|
919
|
+
const pointerPosition = getPointerPosition(event.sourceEvent, {
|
|
920
|
+
transform,
|
|
921
|
+
gridStep,
|
|
922
|
+
centerStep,
|
|
923
|
+
});
|
|
924
|
+
dragItems = getDragItems(nodeInternals, nodesDraggable, pointerPosition, nodeId);
|
|
925
|
+
if (onDragStart && dragItems) {
|
|
926
|
+
const [currentNode, nodes] = getEventHandlerParams({
|
|
927
|
+
nodeId,
|
|
928
|
+
dragItems: dragItems,
|
|
929
|
+
nodeInternals,
|
|
712
930
|
});
|
|
931
|
+
onDragStart?.(event.sourceEvent, dragItems, currentNode, nodes);
|
|
713
932
|
}
|
|
933
|
+
containerBounds = domNode?.getBoundingClientRect() || null;
|
|
934
|
+
mousePosition = getEventPosition(event.sourceEvent, containerBounds);
|
|
935
|
+
};
|
|
936
|
+
const dragHandle = drag()
|
|
937
|
+
.on('start', (event) => {
|
|
938
|
+
startDrag(event);
|
|
714
939
|
})
|
|
715
|
-
.
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
940
|
+
.on('drag', (event) => {
|
|
941
|
+
const { transform, gridStep, centerStep, autoPanOnNodeDrag, updateNodesIntersection, } = getStore();
|
|
942
|
+
const pointerPosition = getPointerPosition(event.sourceEvent, {
|
|
943
|
+
transform,
|
|
944
|
+
gridStep,
|
|
945
|
+
centerStep,
|
|
946
|
+
});
|
|
947
|
+
if (!autoPanStarted && autoPanOnNodeDrag) {
|
|
948
|
+
autoPanStarted = true;
|
|
949
|
+
autoPan();
|
|
950
|
+
}
|
|
951
|
+
const isChanged = hasChangedPosition(lastPosition, pointerPosition.getStepPosition());
|
|
952
|
+
if (isChanged && dragItems) {
|
|
953
|
+
dragEvent = event.sourceEvent;
|
|
954
|
+
mousePosition = getEventPosition(event.sourceEvent, containerBounds);
|
|
955
|
+
updateNodes(pointerPosition);
|
|
956
|
+
updateNodesIntersection();
|
|
957
|
+
}
|
|
958
|
+
})
|
|
959
|
+
.on('end', (event) => {
|
|
960
|
+
autoPanStarted = false;
|
|
961
|
+
cancelAnimationFrame(autoPanId);
|
|
962
|
+
if (dragItems) {
|
|
963
|
+
const { nodeInternals, transform, gridStep, centerStep, smoothStep, updateNodesPosition, updateNodesIntersection, } = getStore();
|
|
964
|
+
const isSmoothStep = !!gridStep && smoothStep;
|
|
965
|
+
if (isSmoothStep) {
|
|
966
|
+
const pointerPosition = getPointerPosition(event.sourceEvent, {
|
|
967
|
+
transform,
|
|
968
|
+
gridStep,
|
|
969
|
+
centerStep,
|
|
970
|
+
});
|
|
971
|
+
updateNodesPosition(dragItems, false, updateNodePosition(pointerPosition, true));
|
|
972
|
+
updateNodesIntersection();
|
|
973
|
+
}
|
|
974
|
+
else {
|
|
975
|
+
updateNodesPosition(dragItems, false);
|
|
976
|
+
}
|
|
977
|
+
if (onDragEnd) {
|
|
978
|
+
const [currentNode, nodes] = getEventHandlerParams({
|
|
979
|
+
nodeId,
|
|
980
|
+
dragItems: dragItems,
|
|
981
|
+
nodeInternals,
|
|
982
|
+
});
|
|
983
|
+
onDragEnd(event.sourceEvent, dragItems, currentNode, nodes);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
})
|
|
987
|
+
.filter((event) => {
|
|
988
|
+
const target = event.target;
|
|
989
|
+
if (!domNode)
|
|
990
|
+
return false;
|
|
991
|
+
const isDraggable = !event.button &&
|
|
992
|
+
(!noDragClassName ||
|
|
993
|
+
!hasSelector(target, `.${noDragClassName}`, domNode));
|
|
994
|
+
return isDraggable;
|
|
728
995
|
});
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
996
|
+
d3Selection.call(dragHandle);
|
|
997
|
+
};
|
|
998
|
+
const destroy = () => {
|
|
999
|
+
d3Selection?.on('.drag', null);
|
|
1000
|
+
};
|
|
1001
|
+
return {
|
|
1002
|
+
update,
|
|
1003
|
+
destroy,
|
|
1004
|
+
};
|
|
1005
|
+
};
|
|
1006
|
+
|
|
1007
|
+
const transformToViewport = (transform) => {
|
|
1008
|
+
const { x, y, k } = transform;
|
|
1009
|
+
return {
|
|
1010
|
+
x,
|
|
1011
|
+
y,
|
|
1012
|
+
zoom: k,
|
|
1013
|
+
};
|
|
1014
|
+
};
|
|
1015
|
+
const viewportToTransform = ({ x, y, zoom }) => zoomIdentity.translate(x, y).scale(zoom);
|
|
1016
|
+
const isWrappedWithClass = (event, className) => event.target.closest(`.${className}`);
|
|
1017
|
+
const isViewChanged = (prevViewport, eventViewport) => {
|
|
1018
|
+
const { x: prevX, y: prevY, zoom: prevZoom } = prevViewport;
|
|
1019
|
+
const { x, y, k } = eventViewport;
|
|
1020
|
+
return prevX !== x || prevY !== y || prevZoom !== k;
|
|
1021
|
+
};
|
|
1022
|
+
const getD3Transition = (selection, duration = 0) => typeof duration === 'number' && duration > 0
|
|
1023
|
+
? selection.transition().duration(duration)
|
|
1024
|
+
: selection;
|
|
1025
|
+
|
|
1026
|
+
const createPanZoomStartHandler = ({ zoomPanValues, onPanningChange, onPanZoomStart, }) => {
|
|
1027
|
+
return (event) => {
|
|
1028
|
+
if (event.sourceEvent?.internal) {
|
|
1029
|
+
return;
|
|
734
1030
|
}
|
|
735
|
-
|
|
736
|
-
|
|
1031
|
+
const viewport = transformToViewport(event.transform);
|
|
1032
|
+
// we need to remember it here, because it's always 0 in the "zoom" event
|
|
1033
|
+
zoomPanValues.mouseButton = event.sourceEvent?.button || 0;
|
|
1034
|
+
zoomPanValues.isZoomingOrPanning = true;
|
|
1035
|
+
zoomPanValues.prevViewport = viewport;
|
|
1036
|
+
if (event.sourceEvent?.type === 'mousedown') {
|
|
1037
|
+
onPanningChange(true);
|
|
1038
|
+
}
|
|
1039
|
+
if (onPanZoomStart) {
|
|
1040
|
+
onPanZoomStart?.(event.sourceEvent, viewport);
|
|
1041
|
+
}
|
|
1042
|
+
};
|
|
1043
|
+
};
|
|
1044
|
+
const createPanZoomHandler = ({ onPanZoom, onTransformChange, }) => {
|
|
1045
|
+
return (event) => {
|
|
1046
|
+
if (!event.sourceEvent?.sync) {
|
|
1047
|
+
onTransformChange([
|
|
1048
|
+
event.transform.x,
|
|
1049
|
+
event.transform.y,
|
|
1050
|
+
event.transform.k,
|
|
1051
|
+
]);
|
|
1052
|
+
}
|
|
1053
|
+
if (onPanZoom && !event.sourceEvent?.internal) {
|
|
1054
|
+
onPanZoom?.(event.sourceEvent, transformToViewport(event.transform));
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
};
|
|
1058
|
+
const createPanZoomEndHandler = ({ zoomPanValues, onPanningChange, onPanZoomEnd, }) => {
|
|
1059
|
+
return (event) => {
|
|
1060
|
+
if (event.sourceEvent?.internal) {
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
zoomPanValues.isZoomingOrPanning = false;
|
|
1064
|
+
onPanningChange(false);
|
|
1065
|
+
if (onPanZoomEnd &&
|
|
1066
|
+
isViewChanged(zoomPanValues.prevViewport, event.transform)) {
|
|
1067
|
+
const viewport = transformToViewport(event.transform);
|
|
1068
|
+
zoomPanValues.prevViewport = viewport;
|
|
1069
|
+
clearTimeout(zoomPanValues.timerId);
|
|
1070
|
+
zoomPanValues.timerId = setTimeout(() => {
|
|
1071
|
+
onPanZoomEnd?.(event.sourceEvent, viewport);
|
|
1072
|
+
}, 0);
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1075
|
+
};
|
|
1076
|
+
function createZoomOnScrollHandler({ d3ZoomHandler, }) {
|
|
1077
|
+
return function (event, d) {
|
|
1078
|
+
event.preventDefault();
|
|
1079
|
+
d3ZoomHandler.call(this, event, d);
|
|
1080
|
+
};
|
|
737
1081
|
}
|
|
738
1082
|
|
|
739
|
-
const
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
const
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
1083
|
+
const CosmosPanZoom = ({ domNode, panning,
|
|
1084
|
+
// selection,
|
|
1085
|
+
minZoom, maxZoom, viewport, translateExtent,
|
|
1086
|
+
// children,
|
|
1087
|
+
onTransformChange, onPanningChange, onPanZoom, onPanZoomStart, onPanZoomEnd, }) => {
|
|
1088
|
+
const zoomPanValues = {
|
|
1089
|
+
isZoomingOrPanning: false,
|
|
1090
|
+
timerId: undefined,
|
|
1091
|
+
prevViewport: { x: 0, y: 0, zoom: 0 },
|
|
1092
|
+
// usedRightMouseButton: false,
|
|
1093
|
+
mouseButton: 0,
|
|
1094
|
+
// panScrollTimeout: undefined,
|
|
1095
|
+
isPanScrolling: false,
|
|
1096
|
+
};
|
|
1097
|
+
const bbox = domNode.getBoundingClientRect();
|
|
1098
|
+
const d3ZoomInstance = zoom()
|
|
1099
|
+
.scaleExtent([minZoom, maxZoom])
|
|
1100
|
+
.translateExtent(translateExtent);
|
|
1101
|
+
const d3Selection = select(domNode).call(d3ZoomInstance);
|
|
1102
|
+
const d3ZoomHandler = d3Selection.on('wheel.zoom');
|
|
1103
|
+
const setTransform = (transform, options) => {
|
|
1104
|
+
if (d3Selection) {
|
|
1105
|
+
d3ZoomInstance?.transform(getD3Transition(d3Selection, options?.duration), transform);
|
|
1106
|
+
}
|
|
1107
|
+
};
|
|
1108
|
+
const setViewportConstrained = (viewport, extent, translateExtent) => {
|
|
1109
|
+
const updatedTransform = viewportToTransform(viewport);
|
|
1110
|
+
const constrainedTransform = d3ZoomInstance.constrain()(updatedTransform, extent, translateExtent);
|
|
1111
|
+
if (constrainedTransform) {
|
|
1112
|
+
setTransform(constrainedTransform);
|
|
1113
|
+
}
|
|
1114
|
+
return constrainedTransform;
|
|
1115
|
+
};
|
|
1116
|
+
setViewportConstrained({
|
|
1117
|
+
x: viewport.x,
|
|
1118
|
+
y: viewport.y,
|
|
1119
|
+
zoom: clamp(viewport.zoom, minZoom, maxZoom),
|
|
1120
|
+
}, [
|
|
1121
|
+
[0, 0],
|
|
1122
|
+
[bbox.width, bbox.height],
|
|
1123
|
+
], translateExtent);
|
|
1124
|
+
const destroy = () => {
|
|
1125
|
+
d3ZoomInstance.on('zoom', null);
|
|
1126
|
+
// d3ZoomInstance.on('start', null);
|
|
1127
|
+
// d3ZoomInstance.on('end', null);
|
|
1128
|
+
// d3Selection.on('wheel.zoom', null);
|
|
1129
|
+
};
|
|
1130
|
+
const update = ({ noPanClassName, selection }) => {
|
|
1131
|
+
if (selection && !zoomPanValues.isZoomingOrPanning) {
|
|
1132
|
+
destroy();
|
|
1133
|
+
}
|
|
1134
|
+
const filter = (event) => {
|
|
1135
|
+
if (selection) {
|
|
1136
|
+
return false;
|
|
1137
|
+
}
|
|
1138
|
+
if (isWrappedWithClass(event, noPanClassName) &&
|
|
1139
|
+
event.type !== 'wheel') {
|
|
1140
|
+
return false;
|
|
1141
|
+
}
|
|
1142
|
+
if (!panning)
|
|
1143
|
+
return false;
|
|
1144
|
+
const buttonAllowed = !event.button || event.button <= 1;
|
|
1145
|
+
if (!buttonAllowed)
|
|
1146
|
+
return false;
|
|
1147
|
+
return true;
|
|
761
1148
|
};
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
1149
|
+
const wheelZoomHandler = createZoomOnScrollHandler({ d3ZoomHandler });
|
|
1150
|
+
d3Selection.on('wheel.zoom', wheelZoomHandler, { passive: false });
|
|
1151
|
+
if (!selection) {
|
|
1152
|
+
const panZoomStartHandler = createPanZoomStartHandler({
|
|
1153
|
+
zoomPanValues,
|
|
1154
|
+
onPanningChange,
|
|
1155
|
+
onPanZoomStart,
|
|
767
1156
|
});
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
1157
|
+
const panZoomHandler = createPanZoomHandler({
|
|
1158
|
+
onPanZoom,
|
|
1159
|
+
onTransformChange,
|
|
1160
|
+
});
|
|
1161
|
+
const panZoomEndHandler = createPanZoomEndHandler({
|
|
1162
|
+
zoomPanValues,
|
|
1163
|
+
onPanningChange,
|
|
1164
|
+
onPanZoomEnd,
|
|
1165
|
+
});
|
|
1166
|
+
d3ZoomInstance.on('start', panZoomStartHandler);
|
|
1167
|
+
d3ZoomInstance.on('zoom', panZoomHandler);
|
|
1168
|
+
d3ZoomInstance.on('end', panZoomEndHandler);
|
|
771
1169
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
1170
|
+
d3ZoomInstance.filter(filter);
|
|
1171
|
+
};
|
|
1172
|
+
const getViewport = () => {
|
|
1173
|
+
const transform = d3Selection
|
|
1174
|
+
? zoomTransform(d3Selection.node())
|
|
1175
|
+
: { x: 0, y: 0, k: 1 };
|
|
1176
|
+
return { x: transform.x, y: transform.y, zoom: transform.k };
|
|
1177
|
+
};
|
|
1178
|
+
return {
|
|
1179
|
+
update,
|
|
1180
|
+
destroy,
|
|
1181
|
+
getViewport,
|
|
1182
|
+
setViewportConstrained,
|
|
1183
|
+
};
|
|
1184
|
+
};
|
|
1185
|
+
|
|
1186
|
+
const StoreContext = createContext(null);
|
|
1187
|
+
const Provider$1 = StoreContext.Provider;
|
|
1188
|
+
|
|
1189
|
+
const zustandErrorMessage = errorMessages['001']();
|
|
1190
|
+
// 변경 사항이 발생할때 값을 구독
|
|
1191
|
+
function useStore(selector, equalityFn) {
|
|
1192
|
+
const store = useContext(StoreContext);
|
|
1193
|
+
if (store === null) {
|
|
1194
|
+
throw new Error(zustandErrorMessage);
|
|
1195
|
+
}
|
|
1196
|
+
return useStore$1(store, selector, equalityFn);
|
|
1197
|
+
}
|
|
1198
|
+
// 필요에 따라 값을 계산
|
|
1199
|
+
const useStoreApi = () => {
|
|
1200
|
+
const store = useContext(StoreContext);
|
|
1201
|
+
if (store === null) {
|
|
1202
|
+
throw new Error(zustandErrorMessage);
|
|
1203
|
+
}
|
|
1204
|
+
return useMemo(() => ({
|
|
1205
|
+
getState: store.getState,
|
|
1206
|
+
setState: store.setState,
|
|
1207
|
+
subscribe: store.subscribe,
|
|
1208
|
+
destroy: store.destroy,
|
|
1209
|
+
}), [store]);
|
|
1210
|
+
};
|
|
1211
|
+
|
|
1212
|
+
const useGlobalKeyHandler = (multiSelectionKeyCode = 'Meta') => {
|
|
1213
|
+
const store = useStoreApi();
|
|
1214
|
+
const [multiSelectionActivate, setMultiSelectionActivate] = useState(false);
|
|
1215
|
+
const handleKeyDown = (e) => {
|
|
1216
|
+
if (e.key === multiSelectionKeyCode) {
|
|
1217
|
+
setMultiSelectionActivate(true);
|
|
1218
|
+
}
|
|
1219
|
+
};
|
|
1220
|
+
const handleKeyUp = () => {
|
|
1221
|
+
setMultiSelectionActivate(false);
|
|
778
1222
|
};
|
|
779
1223
|
useEffect(() => {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
1224
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
1225
|
+
document.addEventListener('keyup', handleKeyUp);
|
|
1226
|
+
return () => {
|
|
1227
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
1228
|
+
document.removeEventListener('keyup', handleKeyUp);
|
|
1229
|
+
};
|
|
1230
|
+
}, []);
|
|
1231
|
+
useEffect(() => {
|
|
1232
|
+
store.setState({
|
|
1233
|
+
multiSelectionActive: multiSelectionActivate,
|
|
1234
|
+
});
|
|
1235
|
+
}, [multiSelectionActivate]);
|
|
1236
|
+
};
|
|
1237
|
+
|
|
1238
|
+
const Pane = ({ noPanClassName, panning, selection, minZoom, maxZoom, defaultViewport, translateExtent, children, onMove, onMoveStart, onMoveEnd, }) => {
|
|
1239
|
+
const store = useStoreApi();
|
|
1240
|
+
const Pane = useRef(null);
|
|
1241
|
+
const cosmosPanZoom = useRef();
|
|
1242
|
+
useEffect(() => {
|
|
1243
|
+
if (!Pane.current)
|
|
1244
|
+
return;
|
|
1245
|
+
cosmosPanZoom.current = CosmosPanZoom({
|
|
1246
|
+
domNode: Pane.current,
|
|
1247
|
+
minZoom,
|
|
1248
|
+
maxZoom,
|
|
1249
|
+
translateExtent,
|
|
1250
|
+
viewport: defaultViewport,
|
|
1251
|
+
panning,
|
|
1252
|
+
onTransformChange: (transform) => {
|
|
1253
|
+
store.setState({ transform });
|
|
1254
|
+
},
|
|
1255
|
+
onPanningChange: (panning) => {
|
|
1256
|
+
console.log(panning);
|
|
1257
|
+
},
|
|
1258
|
+
onPanZoomStart: (event, viewport) => {
|
|
1259
|
+
onMoveStart?.(event, viewport);
|
|
1260
|
+
console.log('start', viewport);
|
|
1261
|
+
},
|
|
1262
|
+
onPanZoom: (event, viewport) => {
|
|
1263
|
+
onMove?.(event, viewport);
|
|
1264
|
+
},
|
|
1265
|
+
onPanZoomEnd: (event, viewport) => {
|
|
1266
|
+
console.log('end', viewport);
|
|
1267
|
+
onMoveEnd?.(event, viewport);
|
|
1268
|
+
},
|
|
1269
|
+
});
|
|
1270
|
+
const { x, y, zoom } = cosmosPanZoom.current.getViewport();
|
|
1271
|
+
store.setState({
|
|
1272
|
+
// 지워야할 목록
|
|
1273
|
+
// d3Zoom: d3ZoomInstance,
|
|
1274
|
+
// d3Selection: selection,
|
|
1275
|
+
// we need to pass transform because zoom handler is not registered when we set the initial transform
|
|
1276
|
+
transform: [x, y, zoom],
|
|
1277
|
+
domNode: Pane.current.closest('.react-diagram'),
|
|
1278
|
+
});
|
|
1279
|
+
return () => {
|
|
1280
|
+
cosmosPanZoom.current?.destroy();
|
|
1281
|
+
};
|
|
1282
|
+
}, []);
|
|
1283
|
+
useEffect(() => {
|
|
1284
|
+
cosmosPanZoom.current?.update({
|
|
1285
|
+
noPanClassName,
|
|
1286
|
+
selection,
|
|
1287
|
+
});
|
|
1288
|
+
}, [noPanClassName, selection]);
|
|
1289
|
+
return (jsx("div", { ref: Pane, className: cc([
|
|
1290
|
+
'react-diagram__pane react-diagram__container',
|
|
1291
|
+
{ selection },
|
|
1292
|
+
]), children: children }));
|
|
1293
|
+
};
|
|
1294
|
+
|
|
1295
|
+
const selector$7 = (s) => `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`;
|
|
1296
|
+
function Viewport({ children }) {
|
|
1297
|
+
const transform = useStore(selector$7);
|
|
1298
|
+
return (jsx("div", { className: "react-diagram__viewport react-diagram__container", style: { transform }, children: children }));
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
function DragBox({ rect }) {
|
|
1302
|
+
const { width, height, x, y } = rect;
|
|
1303
|
+
if (!width || !height || !x || !y)
|
|
1304
|
+
return null;
|
|
1305
|
+
return (jsx("div", { className: "react-diagram__drag-box react-diagram__container", style: {
|
|
1306
|
+
width,
|
|
1307
|
+
height,
|
|
1308
|
+
transform: `translate(${x}px, ${y}px)`,
|
|
1309
|
+
} }));
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
function getMouseHandler$1(id, getState, handler) {
|
|
1313
|
+
return handler === undefined
|
|
1314
|
+
? handler
|
|
1315
|
+
: (event) => {
|
|
1316
|
+
const node = getState().nodeInternals.get(id);
|
|
1317
|
+
handler(event, { ...node });
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
function handleNodeClick({ id, store, isSelectable, unselect = false, nodeRef, }) {
|
|
1321
|
+
if (!isSelectable)
|
|
1322
|
+
return;
|
|
1323
|
+
const { addSelectedNodes, unselectNodes, multiSelectionActive, nodeInternals, } = store.getState();
|
|
1324
|
+
const node = nodeInternals.get(id);
|
|
1325
|
+
store.setState({ selectionBoxActive: false });
|
|
1326
|
+
if (!node.selected) {
|
|
1327
|
+
addSelectedNodes([id]);
|
|
1328
|
+
}
|
|
1329
|
+
else if (unselect || (node.selected && multiSelectionActive)) {
|
|
1330
|
+
unselectNodes({ nodes: [node] });
|
|
1331
|
+
requestAnimationFrame(() => nodeRef?.current?.blur());
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
const useDrag = ({ disabled, nodeRef, nodeId, isSelectable, noDragClassName, }) => {
|
|
1336
|
+
const store = useStoreApi();
|
|
1337
|
+
const cosmosDrag = useRef();
|
|
1338
|
+
const [dragging, setDragging] = useState(false);
|
|
1339
|
+
useEffect(() => {
|
|
1340
|
+
cosmosDrag.current = CosmosDrag({
|
|
1341
|
+
getStore: () => store.getState(),
|
|
1342
|
+
onNodeMouseDown: (id) => {
|
|
1343
|
+
handleNodeClick({
|
|
1344
|
+
id,
|
|
1345
|
+
store,
|
|
1346
|
+
nodeRef,
|
|
1347
|
+
isSelectable,
|
|
1348
|
+
});
|
|
1349
|
+
},
|
|
1350
|
+
onDrag: (e, _, node, nodes) => {
|
|
1351
|
+
const { onNodeDrag } = store.getState();
|
|
1352
|
+
onNodeDrag?.(e, node, nodes);
|
|
1353
|
+
},
|
|
1354
|
+
onDragStart: (e, _, node, nodes) => {
|
|
1355
|
+
const { onNodeDragStart } = store.getState();
|
|
1356
|
+
onNodeDragStart?.(e, node, nodes);
|
|
787
1357
|
setDragging(true);
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
nodeInternals,
|
|
793
|
-
});
|
|
794
|
-
onNodeDrag(dragEvent.current, currentNode, nodes);
|
|
795
|
-
}
|
|
796
|
-
};
|
|
797
|
-
const autoPan = () => {
|
|
798
|
-
if (!containerBounds.current) {
|
|
799
|
-
return;
|
|
800
|
-
}
|
|
801
|
-
const [xMovement, yMovement] = calcAutoPanPosition(mousePosition.current, containerBounds.current);
|
|
802
|
-
if (xMovement !== 0 || yMovement !== 0) {
|
|
803
|
-
const { transform, panBy } = store.getState();
|
|
804
|
-
lastPosition.current.x -= xMovement / transform[2];
|
|
805
|
-
lastPosition.current.y -= yMovement / transform[2];
|
|
806
|
-
updateNodes(lastPosition.current);
|
|
807
|
-
panBy({ x: xMovement, y: yMovement });
|
|
808
|
-
}
|
|
809
|
-
autoPanId.current = requestAnimationFrame(autoPan);
|
|
810
|
-
};
|
|
811
|
-
const dragHandle = drag()
|
|
812
|
-
.on('start', (e) => {
|
|
813
|
-
const { nodeInternals, nodesDraggable, domNode, onNodeDragStart, } = store.getState();
|
|
814
|
-
if (nodeId) {
|
|
815
|
-
handleNodeClick({
|
|
816
|
-
id: nodeId,
|
|
817
|
-
store,
|
|
818
|
-
nodeRef: nodeRef,
|
|
819
|
-
isSelectable,
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
const pointerPosition = getPointerPosition(e);
|
|
823
|
-
dragItems.current = getDragItems(nodeInternals, nodesDraggable, pointerPosition, nodeId);
|
|
824
|
-
if (onNodeDragStart && dragItems.current) {
|
|
825
|
-
const [currentNode, nodes] = getEventHandlerParams({
|
|
826
|
-
nodeId,
|
|
827
|
-
dragItems: dragItems.current,
|
|
828
|
-
nodeInternals,
|
|
829
|
-
});
|
|
830
|
-
onNodeDragStart(e.sourceEvent, currentNode, nodes);
|
|
831
|
-
}
|
|
832
|
-
containerBounds.current =
|
|
833
|
-
domNode?.getBoundingClientRect() || null;
|
|
834
|
-
mousePosition.current = getEventPosition(e.sourceEvent, containerBounds.current);
|
|
835
|
-
})
|
|
836
|
-
.on('drag', (e) => {
|
|
837
|
-
const pointerPosition = getPointerPosition(e);
|
|
838
|
-
const { autoPanOnNodeDrag } = store.getState();
|
|
839
|
-
if (!autoPanStarted.current && autoPanOnNodeDrag) {
|
|
840
|
-
autoPanStarted.current = true;
|
|
841
|
-
autoPan();
|
|
842
|
-
}
|
|
843
|
-
const isChanged = hasChangedPosition(lastPosition.current, pointerPosition.getStepPosition());
|
|
844
|
-
if (isChanged && dragItems.current) {
|
|
845
|
-
dragEvent.current = e.sourceEvent;
|
|
846
|
-
mousePosition.current = getEventPosition(e.sourceEvent, containerBounds.current);
|
|
847
|
-
updateNodes(pointerPosition);
|
|
848
|
-
updateNodesIntersection(dragItems);
|
|
849
|
-
}
|
|
850
|
-
})
|
|
851
|
-
.on('end', (event) => {
|
|
1358
|
+
},
|
|
1359
|
+
onDragEnd: (e, _, node, nodes) => {
|
|
1360
|
+
const { onNodeDragEnd } = store.getState();
|
|
1361
|
+
onNodeDragEnd?.(e, node, nodes);
|
|
852
1362
|
setDragging(false);
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
if (onNodeDragEnd) {
|
|
867
|
-
const [currentNode, nodes] = getEventHandlerParams({
|
|
868
|
-
nodeId,
|
|
869
|
-
dragItems: dragItems.current,
|
|
870
|
-
nodeInternals,
|
|
871
|
-
});
|
|
872
|
-
onNodeDragEnd(event.sourceEvent, currentNode, nodes);
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
})
|
|
876
|
-
.filter((event) => {
|
|
877
|
-
const target = event.target;
|
|
878
|
-
const isDraggable = !event.button &&
|
|
879
|
-
(!noDragClassName ||
|
|
880
|
-
!hasSelector(target, `.${noDragClassName}`, nodeRef));
|
|
881
|
-
return isDraggable;
|
|
1363
|
+
},
|
|
1364
|
+
});
|
|
1365
|
+
}, []);
|
|
1366
|
+
useEffect(() => {
|
|
1367
|
+
if (disabled) {
|
|
1368
|
+
cosmosDrag.current?.destroy();
|
|
1369
|
+
}
|
|
1370
|
+
else if (nodeRef.current) {
|
|
1371
|
+
cosmosDrag.current?.update({
|
|
1372
|
+
noDragClassName,
|
|
1373
|
+
domNode: nodeRef.current,
|
|
1374
|
+
isSelectable,
|
|
1375
|
+
nodeId,
|
|
882
1376
|
});
|
|
883
|
-
selection.call(dragHandle);
|
|
884
1377
|
return () => {
|
|
885
|
-
|
|
1378
|
+
cosmosDrag.current?.destroy();
|
|
886
1379
|
};
|
|
887
1380
|
}
|
|
888
|
-
}, [
|
|
889
|
-
store,
|
|
890
|
-
nodeRef,
|
|
891
|
-
nodeId,
|
|
892
|
-
isSelectable,
|
|
893
|
-
noDragClassName,
|
|
894
|
-
getPointerPosition,
|
|
895
|
-
]);
|
|
1381
|
+
}, [noDragClassName, disabled, isSelectable, nodeRef, nodeId]);
|
|
896
1382
|
return dragging;
|
|
897
|
-
}
|
|
1383
|
+
};
|
|
898
1384
|
|
|
899
1385
|
function SelectionBox({ rect, transform }) {
|
|
900
1386
|
const nodeRef = useRef(null);
|
|
@@ -923,7 +1409,7 @@ const handleParentExpand = (res, updateItem) => {
|
|
|
923
1409
|
extendHeight > 0 ||
|
|
924
1410
|
updateItem.position.x < 0 ||
|
|
925
1411
|
updateItem.position.y < 0) {
|
|
926
|
-
parent.style = { ...parent.style }
|
|
1412
|
+
parent.style = { ...parent.style };
|
|
927
1413
|
parent.style.width = parent.style.width ?? parent.width;
|
|
928
1414
|
parent.style.height = parent.style.height ?? parent.height;
|
|
929
1415
|
if (extendWidth > 0) {
|
|
@@ -1056,7 +1542,7 @@ const selector$6 = (s) => {
|
|
|
1056
1542
|
selectionBoxActive,
|
|
1057
1543
|
};
|
|
1058
1544
|
};
|
|
1059
|
-
function DragSelection({
|
|
1545
|
+
function DragSelection({ dragSelectionKeyPressed, children, }) {
|
|
1060
1546
|
const store = useStoreApi();
|
|
1061
1547
|
const dragSelection = useRef(null);
|
|
1062
1548
|
const prevSelectedNodesCount = useRef(0);
|
|
@@ -1074,6 +1560,9 @@ function DragSelection({ children, dragSelectionKeyPressed, }) {
|
|
|
1074
1560
|
});
|
|
1075
1561
|
const [dragBoxActive, setDragBoxActive] = useState(false);
|
|
1076
1562
|
const resetDragBox = () => {
|
|
1563
|
+
store.setState({
|
|
1564
|
+
selectionBoxActive: prevSelectedNodesCount.current > 0,
|
|
1565
|
+
});
|
|
1077
1566
|
setDragBoxStartPosition({
|
|
1078
1567
|
x: 0,
|
|
1079
1568
|
y: 0,
|
|
@@ -1105,7 +1594,7 @@ function DragSelection({ children, dragSelectionKeyPressed, }) {
|
|
|
1105
1594
|
!dragSelectionKeyPressed) {
|
|
1106
1595
|
return;
|
|
1107
1596
|
}
|
|
1108
|
-
const { x, y } = getEventPosition(event, containerBounds.current);
|
|
1597
|
+
const { x, y } = getEventPosition(event.nativeEvent, containerBounds.current);
|
|
1109
1598
|
resetSelectedElements();
|
|
1110
1599
|
setDragBoxRect({
|
|
1111
1600
|
width: 0,
|
|
@@ -1123,16 +1612,16 @@ function DragSelection({ children, dragSelectionKeyPressed, }) {
|
|
|
1123
1612
|
const hasDragBoxStartPosition = dragBoxStartPosition.x > 0 && dragBoxStartPosition.y > 0;
|
|
1124
1613
|
if (
|
|
1125
1614
|
// !hasDragBoxPosition ||
|
|
1615
|
+
// !dragSelectionKeyPressed ||
|
|
1126
1616
|
!hasDragBoxStartPosition ||
|
|
1127
|
-
!containerBounds.current
|
|
1128
|
-
!dragSelectionKeyPressed) {
|
|
1617
|
+
!containerBounds.current) {
|
|
1129
1618
|
return;
|
|
1130
1619
|
}
|
|
1131
1620
|
store.setState({
|
|
1132
1621
|
selectionBoxActive: false,
|
|
1133
1622
|
});
|
|
1134
1623
|
setDragBoxActive(true);
|
|
1135
|
-
const mousePos = getEventPosition(event, containerBounds.current);
|
|
1624
|
+
const mousePos = getEventPosition(event.nativeEvent, containerBounds.current);
|
|
1136
1625
|
const startX = dragBoxStartPosition.x ?? 0;
|
|
1137
1626
|
const startY = dragBoxStartPosition.y ?? 0;
|
|
1138
1627
|
const rect = {
|
|
@@ -1157,35 +1646,22 @@ function DragSelection({ children, dragSelectionKeyPressed, }) {
|
|
|
1157
1646
|
if (event.button !== 0) {
|
|
1158
1647
|
return;
|
|
1159
1648
|
}
|
|
1160
|
-
store.setState({
|
|
1161
|
-
selectionBoxActive: prevSelectedNodesCount.current > 0,
|
|
1162
|
-
});
|
|
1163
1649
|
resetDragBox();
|
|
1164
1650
|
};
|
|
1165
1651
|
const onMouseLeave = () => {
|
|
1166
|
-
store.setState({
|
|
1167
|
-
selectionBoxActive: prevSelectedNodesCount.current > 0,
|
|
1168
|
-
});
|
|
1169
1652
|
resetDragBox();
|
|
1170
1653
|
};
|
|
1171
|
-
const isPossibleDragSelection = elementsSelectable
|
|
1172
|
-
return (jsxs("div", { ref: dragSelection, className:
|
|
1654
|
+
const isPossibleDragSelection = elementsSelectable;
|
|
1655
|
+
return (jsxs("div", { ref: dragSelection, className: cc([
|
|
1656
|
+
'react-diagram__container react-diagram__drag-selection',
|
|
1657
|
+
]), onClick: onClick, onMouseDown: isPossibleDragSelection ? onMouseDown : undefined, onMouseMove: isPossibleDragSelection ? onMouseMove : undefined, onMouseUp: elementsSelectable ? onMouseUp : undefined, onMouseLeave: isPossibleDragSelection ? onMouseLeave : undefined, children: [children, dragBoxActive && jsx(DragBox, { rect: dragBoxRect }), selectionBoxActive && (jsx(SelectionBox$1, { rect: selectionBoxRect, transform: transformString }))] }));
|
|
1173
1658
|
}
|
|
1174
1659
|
|
|
1175
|
-
const
|
|
1176
|
-
const { minZoom, maxZoom, translateExtent } = s;
|
|
1177
|
-
return {
|
|
1178
|
-
minZoom,
|
|
1179
|
-
maxZoom,
|
|
1180
|
-
translateExtent,
|
|
1181
|
-
};
|
|
1182
|
-
};
|
|
1183
|
-
function DiagramRenderer({ children, multiSelectionKeyCode, noPanClassName, panning, defaultViewport, onMove, onMoveStart, onMoveEnd, }) {
|
|
1184
|
-
const { minZoom, maxZoom, translateExtent } = useStore(selector$5);
|
|
1660
|
+
const useDragSelectionKeyPress = (dragSelectionKeyCode) => {
|
|
1185
1661
|
const [dragSelectionKeyPressed, setDragSelectionKeyPressed] = useState(false);
|
|
1186
|
-
|
|
1662
|
+
// useKeyPress
|
|
1187
1663
|
const handleKeyDown = (e) => {
|
|
1188
|
-
if (e.key ===
|
|
1664
|
+
if (e.key === dragSelectionKeyCode) {
|
|
1189
1665
|
setDragSelectionKeyPressed(true);
|
|
1190
1666
|
}
|
|
1191
1667
|
};
|
|
@@ -1200,7 +1676,25 @@ function DiagramRenderer({ children, multiSelectionKeyCode, noPanClassName, pann
|
|
|
1200
1676
|
document.removeEventListener('keyup', handleKeyUp);
|
|
1201
1677
|
};
|
|
1202
1678
|
}, []);
|
|
1203
|
-
return
|
|
1679
|
+
return dragSelectionKeyPressed;
|
|
1680
|
+
};
|
|
1681
|
+
|
|
1682
|
+
const selector$5 = (s) => {
|
|
1683
|
+
const { minZoom, maxZoom, translateExtent } = s;
|
|
1684
|
+
return {
|
|
1685
|
+
minZoom,
|
|
1686
|
+
maxZoom,
|
|
1687
|
+
translateExtent,
|
|
1688
|
+
};
|
|
1689
|
+
};
|
|
1690
|
+
function DiagramRenderer({ children, multiSelectionKeyCode, dragSelectionKeyCode, noPanClassName, panning, defaultViewport, onMove, onMoveStart, onMoveEnd, }) {
|
|
1691
|
+
const { minZoom, maxZoom, translateExtent } = useStore(selector$5);
|
|
1692
|
+
useGlobalKeyHandler(multiSelectionKeyCode);
|
|
1693
|
+
const dragSelectionKeyPressed = useDragSelectionKeyPress(dragSelectionKeyCode);
|
|
1694
|
+
// useKeyPress
|
|
1695
|
+
const isSelecting = dragSelectionKeyPressed;
|
|
1696
|
+
const isPanning = panning && !isSelecting;
|
|
1697
|
+
return (jsx(Fragment, { children: jsx(Pane, { noPanClassName: noPanClassName, panning: isPanning, selection: isSelecting, minZoom: minZoom, maxZoom: maxZoom, translateExtent: translateExtent, defaultViewport: defaultViewport, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, children: jsx(DragSelection, { dragSelectionKeyPressed: dragSelectionKeyPressed, children: jsx(Viewport, { children: children }) }) }) }));
|
|
1204
1698
|
}
|
|
1205
1699
|
DiagramRenderer.displayName = 'DiagramRenderer';
|
|
1206
1700
|
var DiagramRenderer$1 = memo(DiagramRenderer);
|
|
@@ -1210,19 +1704,6 @@ function useVisibleNodes() {
|
|
|
1210
1704
|
return nodes;
|
|
1211
1705
|
}
|
|
1212
1706
|
|
|
1213
|
-
var Position;
|
|
1214
|
-
(function (Position) {
|
|
1215
|
-
Position["Left"] = "left";
|
|
1216
|
-
Position["Top"] = "top";
|
|
1217
|
-
Position["Right"] = "right";
|
|
1218
|
-
Position["Bottom"] = "bottom";
|
|
1219
|
-
})(Position || (Position = {}));
|
|
1220
|
-
|
|
1221
|
-
var MarkerType;
|
|
1222
|
-
(function (MarkerType) {
|
|
1223
|
-
MarkerType["Arrow"] = "arrow";
|
|
1224
|
-
})(MarkerType || (MarkerType = {}));
|
|
1225
|
-
|
|
1226
1707
|
const selector$4 = (s) => ({
|
|
1227
1708
|
nodesDraggable: s.nodesDraggable,
|
|
1228
1709
|
elementsSelectable: s.elementsSelectable,
|
|
@@ -1270,8 +1751,8 @@ function NodeRenderer({ nodeTypes, onNodeClick, onNodeMouseEnter, onNodeMouseMov
|
|
|
1270
1751
|
id,
|
|
1271
1752
|
className,
|
|
1272
1753
|
style,
|
|
1273
|
-
width,
|
|
1274
|
-
height,
|
|
1754
|
+
width: nodeType === 'default' && width ? 120 : undefined,
|
|
1755
|
+
height: nodeType === 'default' && height ? 60 : undefined,
|
|
1275
1756
|
ariaLabel,
|
|
1276
1757
|
};
|
|
1277
1758
|
const events = {
|
|
@@ -1294,10 +1775,10 @@ function NodeRenderer({ nodeTypes, onNodeClick, onNodeMouseEnter, onNodeMouseMov
|
|
|
1294
1775
|
isSelectable,
|
|
1295
1776
|
isDraggable,
|
|
1296
1777
|
hidden,
|
|
1297
|
-
isParent: !!node[internalsSymbol]?.isParent,
|
|
1778
|
+
isParent: !!node[internalsSymbol$1]?.isParent,
|
|
1298
1779
|
initialized: !!node.width && !!node.height,
|
|
1299
1780
|
};
|
|
1300
|
-
return (jsx(NodeComponent, { ...props, ...elProps, ...position, ...events, ...booleanProps, zIndex: node[internalsSymbol]?.z ?? 0, type: nodeType, data: data, resizeObserver: resizeObserver }, id));
|
|
1781
|
+
return (jsx(NodeComponent, { ...props, ...elProps, ...position, ...events, ...booleanProps, zIndex: node[internalsSymbol$1]?.z ?? 0, type: nodeType, data: data, resizeObserver: resizeObserver }, id));
|
|
1301
1782
|
}) }));
|
|
1302
1783
|
}
|
|
1303
1784
|
NodeRenderer.displayName = 'NodeRenderer';
|
|
@@ -1371,178 +1852,34 @@ function EdgeLabel({ x, y, label, labelStyle = {}, labelShowBg = true, labelBgSt
|
|
|
1371
1852
|
setEdgeLabelBox({
|
|
1372
1853
|
x: textBbox.x,
|
|
1373
1854
|
y: textBbox.y,
|
|
1374
|
-
width: textBbox.width,
|
|
1375
|
-
height: textBbox.height,
|
|
1376
|
-
});
|
|
1377
|
-
}
|
|
1378
|
-
}, [label]);
|
|
1379
|
-
if (typeof label === 'undefined' || !label) {
|
|
1380
|
-
return null;
|
|
1381
|
-
}
|
|
1382
|
-
return (jsxs("g", { transform: `translate(${x - edgeLabelBox.width / 2} ${y - edgeLabelBox.height / 2})`, className: edgeTextClasses, visibility: edgeLabelBox.width ? 'visible' : 'hidden', ...rest, children: [labelShowBg && (jsx("rect", { width: edgeLabelBox.width + 2 * labelBgPadding[0], x: -labelBgPadding[0], y: -labelBgPadding[1], height: edgeLabelBox.height + 2 * labelBgPadding[1], className: "react-diagram__edge-text-bg", style: labelBgStyle, rx: labelBgBorderRadius, ry: labelBgBorderRadius })), jsx("text", { className: "react-diagram__edge-text", y: edgeLabelBox.height / 2, dy: "0.3em", ref: edgeRef, style: labelStyle, children: label }), children] }));
|
|
1383
|
-
}
|
|
1384
|
-
var EdgeLabel$1 = memo(EdgeLabel);
|
|
1385
|
-
|
|
1386
|
-
function BaseEdge({ path, labelX, labelY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, }) {
|
|
1387
|
-
return (jsxs(Fragment, { children: [jsx("path", { style: style, d: path, fill: "none", className: "react-diagram__edge-path", markerEnd: markerEnd, markerStart: markerStart }), label && isNumeric(labelX) && isNumeric(labelY) ? (jsx(EdgeLabel$1, { x: labelX, y: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius })) : null] }));
|
|
1388
|
-
}
|
|
1389
|
-
BaseEdge.displayName = 'BaseEdge';
|
|
1390
|
-
|
|
1391
|
-
const getEdgeCenter = ({ sourceX, sourceY, targetX, targetY, }) => {
|
|
1392
|
-
const xOffset = Math.abs(targetX - sourceX) / 2;
|
|
1393
|
-
const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
|
|
1394
|
-
const yOffset = Math.abs(targetY - sourceY) / 2;
|
|
1395
|
-
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
|
|
1396
|
-
return [centerX, centerY, xOffset, yOffset];
|
|
1397
|
-
};
|
|
1398
|
-
const getBezierEdgeCenter = ({ sourceX, sourceY, targetX, targetY, sourceControlX, sourceControlY, targetControlX, targetControlY, }) => {
|
|
1399
|
-
// cubic bezier t=0.5 mid point, not the actual mid point, but easy to calculate
|
|
1400
|
-
// https://stackoverflow.com/questions/67516101/how-to-find-distance-mid-point-of-bezier-curve
|
|
1401
|
-
const midPoint = 0.5;
|
|
1402
|
-
const point = 0.125;
|
|
1403
|
-
const controlPoint = midPoint - point;
|
|
1404
|
-
const centerX = sourceX * point +
|
|
1405
|
-
sourceControlX * controlPoint +
|
|
1406
|
-
targetControlX * controlPoint +
|
|
1407
|
-
targetX * point;
|
|
1408
|
-
const centerY = sourceY * point +
|
|
1409
|
-
sourceControlY * controlPoint +
|
|
1410
|
-
targetControlY * controlPoint +
|
|
1411
|
-
targetY * point;
|
|
1412
|
-
const offsetX = Math.abs(centerX - sourceX);
|
|
1413
|
-
const offsetY = Math.abs(centerY - sourceY);
|
|
1414
|
-
return [centerX, centerY, offsetX, offsetY];
|
|
1415
|
-
};
|
|
1416
|
-
|
|
1417
|
-
const getStraightPath = ({ sourceX, sourceY, targetX, targetY, }) => {
|
|
1418
|
-
const [labelX, labelY, offsetX, offsetY] = getEdgeCenter({
|
|
1419
|
-
sourceX,
|
|
1420
|
-
sourceY,
|
|
1421
|
-
targetX,
|
|
1422
|
-
targetY,
|
|
1423
|
-
});
|
|
1424
|
-
return [
|
|
1425
|
-
`M ${sourceX},${sourceY}L ${targetX},${targetY}`,
|
|
1426
|
-
labelX,
|
|
1427
|
-
labelY,
|
|
1428
|
-
offsetX,
|
|
1429
|
-
offsetY,
|
|
1430
|
-
];
|
|
1431
|
-
};
|
|
1432
|
-
const StraightEdge = memo(({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, }) => {
|
|
1433
|
-
const [path, labelX, labelY] = getStraightPath({
|
|
1434
|
-
sourceX,
|
|
1435
|
-
sourceY,
|
|
1436
|
-
targetX,
|
|
1437
|
-
targetY,
|
|
1438
|
-
});
|
|
1439
|
-
return (jsx(BaseEdge, { path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart }));
|
|
1440
|
-
});
|
|
1441
|
-
StraightEdge.displayName = 'StraightEdge';
|
|
1442
|
-
|
|
1443
|
-
const HANDLE_DIRECTIONS = {
|
|
1444
|
-
[Position.Left]: { x: -1, y: 0 },
|
|
1445
|
-
[Position.Right]: { x: 1, y: 0 },
|
|
1446
|
-
[Position.Top]: { x: 0, y: -1 },
|
|
1447
|
-
[Position.Bottom]: { x: 0, y: 1 },
|
|
1448
|
-
};
|
|
1449
|
-
const getDirection = ({ source, sourcePosition = Position.Bottom, target, }) => {
|
|
1450
|
-
if (sourcePosition === Position.Left || sourcePosition === Position.Right) {
|
|
1451
|
-
// when source Node position is on the left side of a Port of target Node => x = 1
|
|
1452
|
-
return source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 };
|
|
1453
|
-
}
|
|
1454
|
-
//when source Node position is above of a Port of target Node => y = 1
|
|
1455
|
-
return source.y < target.y ? { x: 0, y: 1 } : { x: 0, y: -1 };
|
|
1456
|
-
};
|
|
1457
|
-
const distance = (a, b) => Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
|
|
1458
|
-
function getPoints({ source, sourcePosition = Position.Bottom, target, targetPosition = Position.Top, center, offset, }) {
|
|
1459
|
-
const sourceDir = HANDLE_DIRECTIONS[sourcePosition];
|
|
1460
|
-
const targetDir = HANDLE_DIRECTIONS[targetPosition];
|
|
1461
|
-
const sourceGapped = {
|
|
1462
|
-
x: source.x + sourceDir.x * offset,
|
|
1463
|
-
y: source.y + sourceDir.y * offset,
|
|
1464
|
-
};
|
|
1465
|
-
const targetGapped = {
|
|
1466
|
-
x: target.x + targetDir.x * offset,
|
|
1467
|
-
y: target.y + targetDir.y * offset,
|
|
1468
|
-
};
|
|
1469
|
-
const direction = getDirection({
|
|
1470
|
-
source: sourceGapped,
|
|
1471
|
-
sourcePosition,
|
|
1472
|
-
target: targetGapped,
|
|
1473
|
-
});
|
|
1474
|
-
const dirAccessor = direction.x !== 0 ? 'x' : 'y';
|
|
1475
|
-
const currentDirection = direction[dirAccessor];
|
|
1476
|
-
let points = [];
|
|
1477
|
-
let centerX = 0, centerY = 0;
|
|
1478
|
-
const [defaultCenterX, defaultCenterY, defaultOffsetX, defaultOffsetY] = getEdgeCenter({
|
|
1479
|
-
sourceX: source.x,
|
|
1480
|
-
sourceY: source.y,
|
|
1481
|
-
targetX: target.x,
|
|
1482
|
-
targetY: target.y,
|
|
1483
|
-
});
|
|
1484
|
-
const isSourceAndTargetPositionsParallel = sourceDir[dirAccessor] * targetDir[dirAccessor] === -1;
|
|
1485
|
-
if (isSourceAndTargetPositionsParallel) {
|
|
1486
|
-
centerX = center.x || defaultCenterX;
|
|
1487
|
-
centerY = center.y || defaultCenterY;
|
|
1488
|
-
const verticalSplit = [
|
|
1489
|
-
{ x: centerX, y: sourceGapped.y },
|
|
1490
|
-
{ x: centerX, y: targetGapped.y },
|
|
1491
|
-
];
|
|
1492
|
-
const horizontalSplit = [
|
|
1493
|
-
{ x: sourceGapped.x, y: centerY },
|
|
1494
|
-
{ x: targetGapped.x, y: centerY },
|
|
1495
|
-
];
|
|
1496
|
-
const centerLineIsBent = sourceDir[dirAccessor] !== currentDirection;
|
|
1497
|
-
if (centerLineIsBent) {
|
|
1498
|
-
points = dirAccessor === 'x' ? horizontalSplit : verticalSplit;
|
|
1499
|
-
}
|
|
1500
|
-
else {
|
|
1501
|
-
points = dirAccessor === 'x' ? verticalSplit : horizontalSplit;
|
|
1502
|
-
}
|
|
1503
|
-
}
|
|
1504
|
-
const pathPoints = [source, sourceGapped, ...points, targetGapped, target];
|
|
1505
|
-
return [pathPoints, centerX, centerY, defaultOffsetX, defaultOffsetY];
|
|
1506
|
-
}
|
|
1507
|
-
function getBend(a, b, c, size) {
|
|
1508
|
-
const bendSize = Math.min(distance(a, b) / 2, distance(b, c) / 2, size);
|
|
1509
|
-
const { x, y } = b;
|
|
1510
|
-
// no bend
|
|
1511
|
-
if ((a.x === x && x === c.x) || (a.y === y && y === c.y)) {
|
|
1512
|
-
return `L${x} ${y}`;
|
|
1513
|
-
}
|
|
1514
|
-
// first segment is horizontal
|
|
1515
|
-
if (a.y === y) {
|
|
1516
|
-
const xDir = a.x < c.x ? -1 : 1;
|
|
1517
|
-
const yDir = a.y < c.y ? 1 : -1;
|
|
1518
|
-
return `L ${x + bendSize * xDir},${y}Q ${x},${y} ${x},${y + bendSize * yDir}`;
|
|
1519
|
-
}
|
|
1520
|
-
const xDir = a.x < c.x ? 1 : -1;
|
|
1521
|
-
const yDir = a.y < c.y ? -1 : 1;
|
|
1522
|
-
return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`;
|
|
1523
|
-
}
|
|
1524
|
-
function getStepPath({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, borderRadius = 5, centerX, centerY, offset = 20, }) {
|
|
1525
|
-
const [points, labelX, labelY, offsetX, offsetY] = getPoints({
|
|
1526
|
-
source: { x: sourceX, y: sourceY },
|
|
1527
|
-
sourcePosition,
|
|
1528
|
-
target: { x: targetX, y: targetY },
|
|
1529
|
-
targetPosition,
|
|
1530
|
-
center: { x: centerX, y: centerY },
|
|
1531
|
-
offset,
|
|
1532
|
-
});
|
|
1533
|
-
const path = points.reduce((res, p, i) => {
|
|
1534
|
-
let segment = '';
|
|
1535
|
-
if (i > 0 && i < points.length - 1) {
|
|
1536
|
-
segment = getBend(points[i - 1], p, points[i + 1], borderRadius);
|
|
1537
|
-
}
|
|
1538
|
-
else {
|
|
1539
|
-
segment = `${i === 0 ? 'M' : 'L'}${p.x} ${p.y}`;
|
|
1855
|
+
width: textBbox.width,
|
|
1856
|
+
height: textBbox.height,
|
|
1857
|
+
});
|
|
1540
1858
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1859
|
+
}, [label]);
|
|
1860
|
+
if (typeof label === 'undefined' || !label) {
|
|
1861
|
+
return null;
|
|
1862
|
+
}
|
|
1863
|
+
return (jsxs("g", { transform: `translate(${x - edgeLabelBox.width / 2} ${y - edgeLabelBox.height / 2})`, className: edgeTextClasses, visibility: edgeLabelBox.width ? 'visible' : 'hidden', ...rest, children: [labelShowBg && (jsx("rect", { width: edgeLabelBox.width + 2 * labelBgPadding[0], x: -labelBgPadding[0], y: -labelBgPadding[1], height: edgeLabelBox.height + 2 * labelBgPadding[1], className: "react-diagram__edge-text-bg", style: labelBgStyle, rx: labelBgBorderRadius, ry: labelBgBorderRadius })), jsx("text", { className: "react-diagram__edge-text", y: edgeLabelBox.height / 2, dy: "0.3em", ref: edgeRef, style: labelStyle, children: label }), children] }));
|
|
1864
|
+
}
|
|
1865
|
+
var EdgeLabel$1 = memo(EdgeLabel);
|
|
1866
|
+
|
|
1867
|
+
function BaseEdge({ path, labelX, labelY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, }) {
|
|
1868
|
+
return (jsxs(Fragment, { children: [jsx("path", { style: style, d: path, fill: "none", className: "react-diagram__edge-path", markerEnd: markerEnd, markerStart: markerStart }), label && isNumeric(labelX) && isNumeric(labelY) ? (jsx(EdgeLabel$1, { x: labelX, y: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius })) : null] }));
|
|
1545
1869
|
}
|
|
1870
|
+
BaseEdge.displayName = 'BaseEdge';
|
|
1871
|
+
|
|
1872
|
+
const StraightEdge = memo(({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, }) => {
|
|
1873
|
+
const [path, labelX, labelY] = getStraightPath({
|
|
1874
|
+
sourceX,
|
|
1875
|
+
sourceY,
|
|
1876
|
+
targetX,
|
|
1877
|
+
targetY,
|
|
1878
|
+
});
|
|
1879
|
+
return (jsx(BaseEdge, { path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart }));
|
|
1880
|
+
});
|
|
1881
|
+
StraightEdge.displayName = 'StraightEdge';
|
|
1882
|
+
|
|
1546
1883
|
const StepEdge = memo(({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, sourcePosition = Position.Bottom, targetPosition = Position.Top, markerEnd, markerStart, pathOptions, }) => {
|
|
1547
1884
|
const [path, labelX, labelY] = getStepPath({
|
|
1548
1885
|
sourceX,
|
|
@@ -1558,59 +1895,6 @@ const StepEdge = memo(({ sourceX, sourceY, targetX, targetY, label, labelStyle,
|
|
|
1558
1895
|
});
|
|
1559
1896
|
StepEdge.displayName = 'StepEdge';
|
|
1560
1897
|
|
|
1561
|
-
const calculateControlOffset = (distance, curvature) => {
|
|
1562
|
-
if (distance >= 0) {
|
|
1563
|
-
return 0.5 * distance;
|
|
1564
|
-
}
|
|
1565
|
-
return curvature * 25 * Math.sqrt(-distance);
|
|
1566
|
-
};
|
|
1567
|
-
const getControlWithCurvature = ({ pos, x1, y1, x2, y2, c, }) => {
|
|
1568
|
-
switch (pos) {
|
|
1569
|
-
case Position.Left:
|
|
1570
|
-
return [x1 - calculateControlOffset(x1 - x2, c), y1];
|
|
1571
|
-
case Position.Right:
|
|
1572
|
-
return [x1 + calculateControlOffset(x2 - x1, c), y1];
|
|
1573
|
-
case Position.Top:
|
|
1574
|
-
return [x1, y1 - calculateControlOffset(y1 - y2, c)];
|
|
1575
|
-
case Position.Bottom:
|
|
1576
|
-
return [x1, y1 + calculateControlOffset(y2 - y1, c)];
|
|
1577
|
-
}
|
|
1578
|
-
};
|
|
1579
|
-
const getBezierPath = ({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, curvature = 0.25, }) => {
|
|
1580
|
-
const [sourceControlX, sourceControlY] = getControlWithCurvature({
|
|
1581
|
-
pos: sourcePosition,
|
|
1582
|
-
x1: sourceX,
|
|
1583
|
-
y1: sourceY,
|
|
1584
|
-
x2: targetX,
|
|
1585
|
-
y2: targetY,
|
|
1586
|
-
c: curvature,
|
|
1587
|
-
});
|
|
1588
|
-
const [targetControlX, targetControlY] = getControlWithCurvature({
|
|
1589
|
-
pos: targetPosition,
|
|
1590
|
-
x1: targetX,
|
|
1591
|
-
y1: targetY,
|
|
1592
|
-
x2: sourceX,
|
|
1593
|
-
y2: sourceY,
|
|
1594
|
-
c: curvature,
|
|
1595
|
-
});
|
|
1596
|
-
const [labelX, labelY, offsetX, offsetY] = getBezierEdgeCenter({
|
|
1597
|
-
sourceX,
|
|
1598
|
-
sourceY,
|
|
1599
|
-
targetX,
|
|
1600
|
-
targetY,
|
|
1601
|
-
sourceControlX,
|
|
1602
|
-
sourceControlY,
|
|
1603
|
-
targetControlX,
|
|
1604
|
-
targetControlY,
|
|
1605
|
-
});
|
|
1606
|
-
return [
|
|
1607
|
-
`M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`,
|
|
1608
|
-
labelX,
|
|
1609
|
-
labelY,
|
|
1610
|
-
offsetX,
|
|
1611
|
-
offsetY,
|
|
1612
|
-
];
|
|
1613
|
-
};
|
|
1614
1898
|
const BezierEdge = memo(({ sourceX, sourceY, targetX, targetY, sourcePosition = Position.Bottom, targetPosition = Position.Top, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, pathOptions, }) => {
|
|
1615
1899
|
const [path, labelX, labelY] = getBezierPath({
|
|
1616
1900
|
sourceX,
|
|
@@ -1628,171 +1912,6 @@ BezierEdge.displayName = 'BezierEdge';
|
|
|
1628
1912
|
const ARIA_NODE_DESC_KEY = 'react-diagram__node-desc';
|
|
1629
1913
|
const ARIA_EDGE_DESC_KEY = 'react-diagram__edge-desc';
|
|
1630
1914
|
|
|
1631
|
-
const getHostForElement = (element) => element.getRootNode?.() || window?.document;
|
|
1632
|
-
const getPortType = (PortDomNode) => {
|
|
1633
|
-
if (PortDomNode?.classList.contains('target')) {
|
|
1634
|
-
return 'target';
|
|
1635
|
-
}
|
|
1636
|
-
else if (PortDomNode?.classList.contains('source')) {
|
|
1637
|
-
return 'source';
|
|
1638
|
-
}
|
|
1639
|
-
return null;
|
|
1640
|
-
};
|
|
1641
|
-
const getConnection = (event, port, fromNodeId, fromType, doc) => {
|
|
1642
|
-
const isTarget = fromType === 'target';
|
|
1643
|
-
const result = {
|
|
1644
|
-
isValid: false,
|
|
1645
|
-
connection: {
|
|
1646
|
-
source: null,
|
|
1647
|
-
target: null,
|
|
1648
|
-
},
|
|
1649
|
-
};
|
|
1650
|
-
const PortDomNode = doc.querySelector(`.react-diagram__port[data-id="${port?.nodeId}-${port?.type}"]`);
|
|
1651
|
-
const { x, y } = getEventPosition(event);
|
|
1652
|
-
const ElementFromPoint = doc.elementFromPoint(x, y);
|
|
1653
|
-
const Port = ElementFromPoint?.classList.contains('react-diagram__port')
|
|
1654
|
-
? ElementFromPoint
|
|
1655
|
-
: PortDomNode;
|
|
1656
|
-
if (Port) {
|
|
1657
|
-
const portType = getPortType(Port);
|
|
1658
|
-
const toNodeId = Port.getAttribute('data-nodeid');
|
|
1659
|
-
const connection = {
|
|
1660
|
-
source: isTarget ? toNodeId : fromNodeId,
|
|
1661
|
-
target: isTarget ? fromNodeId : toNodeId,
|
|
1662
|
-
};
|
|
1663
|
-
result.connection = connection;
|
|
1664
|
-
const isValid = (isTarget && portType === 'source') ||
|
|
1665
|
-
(!isTarget && portType === 'target');
|
|
1666
|
-
if (isValid) {
|
|
1667
|
-
result.isValid = true;
|
|
1668
|
-
}
|
|
1669
|
-
}
|
|
1670
|
-
return result;
|
|
1671
|
-
};
|
|
1672
|
-
const getPorts = (node, portBounds, type, currentPort) => (portBounds[type] || []).reduce((res, h) => {
|
|
1673
|
-
if (`${node.id}-${type}` !== currentPort) {
|
|
1674
|
-
res.push({
|
|
1675
|
-
type,
|
|
1676
|
-
nodeId: node.id,
|
|
1677
|
-
x: (node.positionAbsolute?.x ?? 0) + h.x + h.width / 2,
|
|
1678
|
-
y: (node.positionAbsolute?.y ?? 0) + h.y + h.height / 2,
|
|
1679
|
-
});
|
|
1680
|
-
}
|
|
1681
|
-
return res;
|
|
1682
|
-
}, []);
|
|
1683
|
-
const getAllPort = ({ nodes, nodeId, portType }) => nodes.reduce((res, node) => {
|
|
1684
|
-
if (node[internalsSymbol]) {
|
|
1685
|
-
const { portBounds } = node[internalsSymbol];
|
|
1686
|
-
let sourcePorts = [];
|
|
1687
|
-
let targetPorts = [];
|
|
1688
|
-
if (portBounds) {
|
|
1689
|
-
sourcePorts = getPorts(node, portBounds, 'source', `${nodeId}-${portType}`);
|
|
1690
|
-
targetPorts = getPorts(node, portBounds, 'target', `${nodeId}-${portType}`);
|
|
1691
|
-
}
|
|
1692
|
-
res.push(...sourcePorts, ...targetPorts);
|
|
1693
|
-
}
|
|
1694
|
-
return res;
|
|
1695
|
-
}, []);
|
|
1696
|
-
const getClosestPort = (pos, connectionRadius, ports) => {
|
|
1697
|
-
let closestPort = null;
|
|
1698
|
-
let minDistance = Infinity;
|
|
1699
|
-
ports.forEach((port) => {
|
|
1700
|
-
const distance = Math.sqrt(Math.pow(port.x - pos.x, 2) + Math.pow(port.y - pos.y, 2));
|
|
1701
|
-
if (distance <= connectionRadius && distance < minDistance) {
|
|
1702
|
-
minDistance = distance;
|
|
1703
|
-
closestPort = port;
|
|
1704
|
-
}
|
|
1705
|
-
});
|
|
1706
|
-
return closestPort;
|
|
1707
|
-
};
|
|
1708
|
-
const pointToRendererPoint = ({ x, y }, [tx, ty, tScale]) => {
|
|
1709
|
-
const position = {
|
|
1710
|
-
x: (x - tx) / tScale,
|
|
1711
|
-
y: (y - ty) / tScale,
|
|
1712
|
-
};
|
|
1713
|
-
return position;
|
|
1714
|
-
};
|
|
1715
|
-
const rendererPointToPoint = ({ x, y }, [tx, ty, tScale]) => {
|
|
1716
|
-
return {
|
|
1717
|
-
x: x * tScale + tx,
|
|
1718
|
-
y: y * tScale + ty,
|
|
1719
|
-
};
|
|
1720
|
-
};
|
|
1721
|
-
const handlePointerDown = ({ isAnchor = false, event, nodeId, portType, getState, setState, onConnect, onEdgeUpdateEnd, }) => {
|
|
1722
|
-
const doc = getHostForElement(event.target);
|
|
1723
|
-
const { domNode, autoPanOnConnect, connectionRadius, getNodes, cancelConnection, onConnectStart, onConnectEnd, panBy, } = getState();
|
|
1724
|
-
const containerBounds = domNode?.getBoundingClientRect();
|
|
1725
|
-
const { x, y } = getEventPosition(event);
|
|
1726
|
-
const clickedPort = doc?.elementFromPoint(x, y);
|
|
1727
|
-
const clickedPortType = isAnchor ? portType : getPortType(clickedPort);
|
|
1728
|
-
const allPort = getAllPort({
|
|
1729
|
-
nodes: getNodes(),
|
|
1730
|
-
nodeId,
|
|
1731
|
-
portType,
|
|
1732
|
-
});
|
|
1733
|
-
let connectionPosition = getEventPosition(event, containerBounds);
|
|
1734
|
-
let closestPort = null;
|
|
1735
|
-
let isValid = false;
|
|
1736
|
-
let connection = null;
|
|
1737
|
-
let autoPanId = 0;
|
|
1738
|
-
let autoPanStarted = false;
|
|
1739
|
-
if (!containerBounds || !portType) {
|
|
1740
|
-
return;
|
|
1741
|
-
}
|
|
1742
|
-
const autoPan = () => {
|
|
1743
|
-
if (!autoPanOnConnect) {
|
|
1744
|
-
return;
|
|
1745
|
-
}
|
|
1746
|
-
const [xMovement, yMovement] = calcAutoPanPosition(connectionPosition, containerBounds);
|
|
1747
|
-
panBy({ x: xMovement, y: yMovement });
|
|
1748
|
-
autoPanId = requestAnimationFrame(autoPan);
|
|
1749
|
-
};
|
|
1750
|
-
setState({
|
|
1751
|
-
connectionPosition,
|
|
1752
|
-
connectionNodeId: nodeId,
|
|
1753
|
-
connectionPortType: clickedPortType,
|
|
1754
|
-
});
|
|
1755
|
-
onConnectStart?.(event, { nodeId, portType });
|
|
1756
|
-
const onPointerMove = (event) => {
|
|
1757
|
-
const { transform } = getState();
|
|
1758
|
-
connectionPosition = getEventPosition(event, containerBounds);
|
|
1759
|
-
closestPort = getClosestPort(pointToRendererPoint(connectionPosition, transform), connectionRadius, allPort);
|
|
1760
|
-
if (!autoPanStarted) {
|
|
1761
|
-
autoPan();
|
|
1762
|
-
autoPanStarted = true;
|
|
1763
|
-
}
|
|
1764
|
-
const result = getConnection(event, closestPort, nodeId, portType, doc);
|
|
1765
|
-
isValid = result.isValid;
|
|
1766
|
-
connection = result.connection;
|
|
1767
|
-
setState({
|
|
1768
|
-
connectionPosition: closestPort && isValid
|
|
1769
|
-
? rendererPointToPoint(closestPort, transform)
|
|
1770
|
-
: connectionPosition,
|
|
1771
|
-
});
|
|
1772
|
-
};
|
|
1773
|
-
const onPointerUp = (event) => {
|
|
1774
|
-
if (isValid && connection)
|
|
1775
|
-
onConnect?.(connection);
|
|
1776
|
-
onConnectEnd?.(event);
|
|
1777
|
-
if (portType) {
|
|
1778
|
-
onEdgeUpdateEnd?.(event);
|
|
1779
|
-
}
|
|
1780
|
-
cancelConnection();
|
|
1781
|
-
cancelAnimationFrame(autoPanId);
|
|
1782
|
-
isValid = false;
|
|
1783
|
-
connection = null;
|
|
1784
|
-
autoPanStarted = false;
|
|
1785
|
-
doc.removeEventListener('mousemove', onPointerMove);
|
|
1786
|
-
doc.removeEventListener('mouseup', onPointerUp);
|
|
1787
|
-
doc.removeEventListener('touchmove', onPointerMove);
|
|
1788
|
-
doc.removeEventListener('touchend', onPointerUp);
|
|
1789
|
-
};
|
|
1790
|
-
doc.addEventListener('mousemove', onPointerMove);
|
|
1791
|
-
doc.addEventListener('mouseup', onPointerUp);
|
|
1792
|
-
doc.addEventListener('touchmove', onPointerMove);
|
|
1793
|
-
doc.addEventListener('touchend', onPointerUp);
|
|
1794
|
-
};
|
|
1795
|
-
|
|
1796
1915
|
const portPositionX = (x, shift, position) => {
|
|
1797
1916
|
if (position === Position.Left)
|
|
1798
1917
|
return x - shift;
|
|
@@ -1874,9 +1993,10 @@ const wrapEdge = (EdgeComponent) => {
|
|
|
1874
1993
|
if (event.button !== 0) {
|
|
1875
1994
|
return;
|
|
1876
1995
|
}
|
|
1877
|
-
const { edges } = store.getState();
|
|
1996
|
+
const { edges, domNode, autoPanOnConnect, connectionRadius, transform, getNodes, cancelConnection, updateConnection, onConnectStart, onConnectEnd, panBy, } = store.getState();
|
|
1878
1997
|
const nodeId = props[fromPortType];
|
|
1879
1998
|
const edge = edges.find((e) => e.id === id);
|
|
1999
|
+
const portId = (fromPortType === 'source' ? sourcePort : targetPort) || null;
|
|
1880
2000
|
setUpdating(true);
|
|
1881
2001
|
onEdgeUpdateStart?.(event, edge, fromPortType);
|
|
1882
2002
|
const onConnectEdge = (connection) => onEdgeUpdate?.(edge, connection);
|
|
@@ -1884,15 +2004,24 @@ const wrapEdge = (EdgeComponent) => {
|
|
|
1884
2004
|
setUpdating(false);
|
|
1885
2005
|
onEdgeUpdateEnd?.(evt, edge, fromPortType);
|
|
1886
2006
|
};
|
|
1887
|
-
|
|
2007
|
+
CosmosPort.onPointerDown({
|
|
1888
2008
|
isAnchor: true,
|
|
1889
|
-
event,
|
|
2009
|
+
event: event.nativeEvent,
|
|
1890
2010
|
nodeId,
|
|
2011
|
+
portId,
|
|
1891
2012
|
portType: fromPortType,
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
2013
|
+
domNode,
|
|
2014
|
+
autoPanOnConnect,
|
|
2015
|
+
connectionRadius,
|
|
2016
|
+
nodes: getNodes(),
|
|
1895
2017
|
onEdgeUpdateEnd: handleEdgeUpdateEnd,
|
|
2018
|
+
cancelConnection,
|
|
2019
|
+
updateConnection,
|
|
2020
|
+
onConnect: onConnectEdge,
|
|
2021
|
+
onConnectStart,
|
|
2022
|
+
onConnectEnd,
|
|
2023
|
+
panBy,
|
|
2024
|
+
getTransform: () => transform,
|
|
1896
2025
|
});
|
|
1897
2026
|
};
|
|
1898
2027
|
const onEdgeClick = (event) => {
|
|
@@ -2016,7 +2145,7 @@ const getEdgePositions = (sourceNodeRect, sourcePort, sourcePosition, targetNode
|
|
|
2016
2145
|
};
|
|
2017
2146
|
};
|
|
2018
2147
|
function getNodeData(node) {
|
|
2019
|
-
const portBounds = node?.[internalsSymbol]?.portBounds || null;
|
|
2148
|
+
const portBounds = node?.[internalsSymbol$1]?.portBounds || null;
|
|
2020
2149
|
const isValid = portBounds &&
|
|
2021
2150
|
node?.width &&
|
|
2022
2151
|
node?.height &&
|
|
@@ -2123,17 +2252,19 @@ const oppositePosition = {
|
|
|
2123
2252
|
[Position.Bottom]: Position.Top,
|
|
2124
2253
|
};
|
|
2125
2254
|
function ConnectionPath({ nodeId, portType, edge, Component, EdgeWrapper, }) {
|
|
2126
|
-
const { fromNode, toX, toY } = useStore(useCallback((s) => ({
|
|
2255
|
+
const { fromNode, toX, toY, startPort } = useStore(useCallback((s) => ({
|
|
2127
2256
|
fromNode: s.nodeInternals.get(nodeId),
|
|
2257
|
+
startPort: s.connectionStartPort,
|
|
2128
2258
|
toX: (s.connectionPosition.x - s.transform[0]) / s.transform[2],
|
|
2129
2259
|
toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2],
|
|
2130
2260
|
}), [nodeId]), shallow);
|
|
2131
|
-
const fromPortBounds = fromNode?.[internalsSymbol]?.portBounds;
|
|
2261
|
+
const fromPortBounds = fromNode?.[internalsSymbol$1]?.portBounds;
|
|
2132
2262
|
const portBounds = fromPortBounds?.[portType];
|
|
2133
2263
|
if (!fromNode || !portBounds) {
|
|
2134
2264
|
return null;
|
|
2135
2265
|
}
|
|
2136
|
-
const fromPort = portBounds
|
|
2266
|
+
const fromPort = portBounds.find((bound) => bound.id === startPort?.portId) ||
|
|
2267
|
+
portBounds[0];
|
|
2137
2268
|
const fromPortX = fromPort
|
|
2138
2269
|
? fromPort.x + fromPort.width / 2
|
|
2139
2270
|
: (fromNode.width ?? 0) / 2;
|
|
@@ -2160,11 +2291,13 @@ ConnectionPath.displayName = 'ConnectionPath';
|
|
|
2160
2291
|
|
|
2161
2292
|
const selector$2 = (s) => ({
|
|
2162
2293
|
edges: s.edges,
|
|
2163
|
-
|
|
2164
|
-
portType: s.connectionPortType,
|
|
2294
|
+
startPort: s.connectionStartPort,
|
|
2165
2295
|
});
|
|
2166
2296
|
function ConnectionLineRenderer({ containerStyle, edgeTypes, component, }) {
|
|
2167
|
-
const {
|
|
2297
|
+
const { startPort, edges } = useStore(selector$2, shallow);
|
|
2298
|
+
if (!startPort)
|
|
2299
|
+
return null;
|
|
2300
|
+
const { nodeId, portType } = startPort;
|
|
2168
2301
|
const isValid = !!(nodeId && portType);
|
|
2169
2302
|
if (!isValid) {
|
|
2170
2303
|
return null;
|
|
@@ -2178,18 +2311,21 @@ function ConnectionLineRenderer({ containerStyle, edgeTypes, component, }) {
|
|
|
2178
2311
|
|
|
2179
2312
|
function DiagramView({ rfId,
|
|
2180
2313
|
// DiagramRenderer props
|
|
2181
|
-
noPanClassName, panning, defaultViewport, multiSelectionKeyCode, onMove, onMoveStart, onMoveEnd,
|
|
2314
|
+
noPanClassName, panning, defaultViewport, multiSelectionKeyCode, dragSelectionKeyCode, onMove, onMoveStart, onMoveEnd,
|
|
2182
2315
|
// NodeRenderer props
|
|
2183
|
-
onlyRenderVisibleElements, disableKeyboardA11y, noDragClassName, nodeOrigin, nodeTypes, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave,
|
|
2316
|
+
onlyRenderVisibleElements, disableKeyboardA11y, noDragClassName, nodeOrigin, nodeExtent, nodeTypes, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave,
|
|
2184
2317
|
// EdgeRenderer props
|
|
2185
2318
|
edgeTypes, edgeUpdaterRadius, onEdgeClick, onEdgeDoubleClick, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd,
|
|
2186
2319
|
// ConnectionLineWrapper
|
|
2187
2320
|
ConnectionLineContainerStyle, ConnectionLineComponent, }) {
|
|
2188
|
-
return (jsxs(DiagramRenderer$1, { multiSelectionKeyCode: multiSelectionKeyCode, noPanClassName: noPanClassName, panning: panning, defaultViewport: defaultViewport, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, children: [jsx(NodeRenderer$1, { rfId: rfId, nodeTypes: nodeTypes, onlyRenderVisibleElements: onlyRenderVisibleElements, disableKeyboardA11y: disableKeyboardA11y, nodeOrigin: nodeOrigin, noDragClassName: noDragClassName, noPanClassName: noPanClassName, onNodeClick: onNodeClick, onNodeDoubleClick: onNodeDoubleClick, onNodeContextMenu: onNodeContextMenu, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave }), jsx(EdgeRenderer$1, { rfId: rfId, edgeTypes: edgeTypes, noPanClassName: noPanClassName, edgeUpdaterRadius: edgeUpdaterRadius, onEdgeClick: onEdgeClick, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeContextMenu: onEdgeContextMenu, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, onEdgeUpdate: onEdgeUpdate, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd }), jsx(ConnectionLineRenderer, { edgeTypes: edgeTypes, containerStyle: ConnectionLineContainerStyle, component: ConnectionLineComponent })] }));
|
|
2321
|
+
return (jsxs(DiagramRenderer$1, { multiSelectionKeyCode: multiSelectionKeyCode, dragSelectionKeyCode: dragSelectionKeyCode, noPanClassName: noPanClassName, panning: panning, defaultViewport: defaultViewport, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, children: [jsx(NodeRenderer$1, { rfId: rfId, nodeTypes: nodeTypes, onlyRenderVisibleElements: onlyRenderVisibleElements, disableKeyboardA11y: disableKeyboardA11y, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent, noDragClassName: noDragClassName, noPanClassName: noPanClassName, onNodeClick: onNodeClick, onNodeDoubleClick: onNodeDoubleClick, onNodeContextMenu: onNodeContextMenu, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave }), jsx(EdgeRenderer$1, { rfId: rfId, edgeTypes: edgeTypes, noPanClassName: noPanClassName, edgeUpdaterRadius: edgeUpdaterRadius, onEdgeClick: onEdgeClick, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeContextMenu: onEdgeContextMenu, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, onEdgeUpdate: onEdgeUpdate, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd }), jsx(ConnectionLineRenderer, { edgeTypes: edgeTypes, containerStyle: ConnectionLineContainerStyle, component: ConnectionLineComponent })] }));
|
|
2189
2322
|
}
|
|
2190
2323
|
DiagramView.displayName = 'DiagramView';
|
|
2191
2324
|
var DiagramView$1 = memo(DiagramView);
|
|
2192
2325
|
|
|
2326
|
+
const internalsSymbol = Symbol.for('internals');
|
|
2327
|
+
const onErrorWrapper = (onError) => (id, value = '') => onError?.(id, errorMessages[id](value));
|
|
2328
|
+
|
|
2193
2329
|
const selector$1 = (s) => {
|
|
2194
2330
|
const { setNodes, setEdges, setNodeExtent, setTranslateExtent, setMinZoom, setMaxZoom, } = s;
|
|
2195
2331
|
return {
|
|
@@ -2216,15 +2352,17 @@ function useDirectStoreUpdater(key, value, setState) {
|
|
|
2216
2352
|
}
|
|
2217
2353
|
}, [value]);
|
|
2218
2354
|
}
|
|
2219
|
-
const StoreUpdater = ({ nodes, onNodesChange, onNodeDrag, onNodeDragStart, onNodeDragEnd, edges, onEdgesChange, smoothStep, centerStep, gridStep, elevateNodesOnSelect, nodesDraggable, autoPanOnNodeDrag, autoPanOnConnect, connectionRadius, onConnect, onConnectStart, onConnectEnd, onError, nodeExtent, translateExtent, minZoom, maxZoom, }) => {
|
|
2355
|
+
const StoreUpdater = ({ nodes, onNodesChange, onNodeDrag, onNodeDragStart, onNodeDragEnd, edges, onEdgesChange, nodeOrigin, smoothStep, centerStep, gridStep, elevateNodesOnSelect, nodesDraggable, autoPanOnNodeDrag, autoPanOnConnect, connectionRadius, onConnect, onConnectStart, onConnectEnd, onError, nodeExtent, translateExtent, minZoom, maxZoom, }) => {
|
|
2220
2356
|
const { setNodes, setEdges, setNodeExtent, setTranslateExtent, setMinZoom, setMaxZoom, } = useStore(selector$1, shallow);
|
|
2221
2357
|
const store = useStoreApi();
|
|
2222
2358
|
useStoreUpdater(nodes, setNodes);
|
|
2223
2359
|
useStoreUpdater(edges, setEdges);
|
|
2224
2360
|
useStoreUpdater(nodeExtent, setNodeExtent);
|
|
2361
|
+
useStoreUpdater(nodeExtent, setNodeExtent);
|
|
2225
2362
|
useStoreUpdater(translateExtent, setTranslateExtent);
|
|
2226
2363
|
useStoreUpdater(minZoom, setMinZoom);
|
|
2227
2364
|
useStoreUpdater(maxZoom, setMaxZoom);
|
|
2365
|
+
useDirectStoreUpdater('nodeOrigin', nodeOrigin, store.setState);
|
|
2228
2366
|
useDirectStoreUpdater('smoothStep', smoothStep, store.setState);
|
|
2229
2367
|
useDirectStoreUpdater('centerStep', centerStep, store.setState);
|
|
2230
2368
|
useDirectStoreUpdater('gridStep', gridStep, store.setState);
|
|
@@ -2268,7 +2406,8 @@ const useNodeId = () => {
|
|
|
2268
2406
|
return nodeId;
|
|
2269
2407
|
};
|
|
2270
2408
|
|
|
2271
|
-
function Port({ type, position }) {
|
|
2409
|
+
function Port({ id, type, position }) {
|
|
2410
|
+
const portId = id || null;
|
|
2272
2411
|
const store = useStoreApi();
|
|
2273
2412
|
const nodeId = useNodeId();
|
|
2274
2413
|
if (!nodeId)
|
|
@@ -2282,19 +2421,30 @@ function Port({ type, position }) {
|
|
|
2282
2421
|
onConnect?.(edgeParams);
|
|
2283
2422
|
};
|
|
2284
2423
|
const onPointerDown = (event) => {
|
|
2285
|
-
const isMouseTriggered = isMouseEvent(event);
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2424
|
+
const isMouseTriggered = isMouseEvent(event.nativeEvent);
|
|
2425
|
+
const { button } = event;
|
|
2426
|
+
if ((isMouseTriggered && button === 0) || !isMouseTriggered) {
|
|
2427
|
+
const { domNode, autoPanOnConnect, connectionRadius, transform, getNodes, cancelConnection, updateConnection, onConnectStart, onConnectEnd, panBy, } = store.getState();
|
|
2428
|
+
CosmosPort.onPointerDown({
|
|
2429
|
+
event: event.nativeEvent,
|
|
2289
2430
|
nodeId,
|
|
2431
|
+
portId,
|
|
2290
2432
|
portType: type,
|
|
2291
|
-
|
|
2292
|
-
|
|
2433
|
+
domNode,
|
|
2434
|
+
autoPanOnConnect,
|
|
2435
|
+
connectionRadius,
|
|
2436
|
+
nodes: getNodes(),
|
|
2437
|
+
cancelConnection,
|
|
2438
|
+
updateConnection,
|
|
2293
2439
|
onConnect: handleOnConnect,
|
|
2440
|
+
onConnectStart,
|
|
2441
|
+
onConnectEnd,
|
|
2442
|
+
panBy,
|
|
2443
|
+
getTransform: () => transform,
|
|
2294
2444
|
});
|
|
2295
2445
|
}
|
|
2296
2446
|
};
|
|
2297
|
-
return (jsx("div", { "data-nodeid": nodeId, "data-id": `${nodeId}-${type}`, "data-port-position": position, className: `react-diagram__port react-diagram__port-${position} ${type} nodrag`, onMouseDown: onPointerDown, onTouchStart: onPointerDown }));
|
|
2447
|
+
return (jsx("div", { "data-nodeid": nodeId, "data-id": `${nodeId}-${portId}-${type}`, "data-portid": portId, "data-port-position": position, className: `react-diagram__port react-diagram__port-${position} ${type} nodrag`, onMouseDown: onPointerDown, onTouchStart: onPointerDown }));
|
|
2298
2448
|
}
|
|
2299
2449
|
Port.displayName = 'Port';
|
|
2300
2450
|
var Port$1 = memo(Port);
|
|
@@ -2304,8 +2454,9 @@ function Nodes({ data }) {
|
|
|
2304
2454
|
}
|
|
2305
2455
|
|
|
2306
2456
|
const wrapNode = (NodeComponent) => {
|
|
2307
|
-
function NodeWrapper({ id, type, data, positionX, positionY, sourcePosition, targetPosition, onClick, onMouseEnter, onMouseMove, onMouseLeave, onContextMenu, onDoubleClick, style, width, height, className, selected, isSelectable, isDraggable, intersected, hidden, resizeObserver, dragHandle, zIndex, isParent, initialized, disableKeyboardA11y, ariaLabel, rfId, noDragClassName, noPanClassName, }) {
|
|
2457
|
+
function NodeWrapper({ id, type, data, positionX, positionY, sourcePosition, targetPosition, onClick, onMouseEnter, onMouseMove, onMouseLeave, onContextMenu, onDoubleClick, style, width, height, className, selected, isSelectable, isDraggable, intersected, nodeOrigin, nodeExtent, hidden, resizeObserver, dragHandle, zIndex, isParent, initialized, disableKeyboardA11y, ariaLabel, rfId, noDragClassName, noPanClassName, }) {
|
|
2308
2458
|
const store = useStoreApi();
|
|
2459
|
+
const node = store.getState().nodeInternals.get(id);
|
|
2309
2460
|
const nodeRef = useRef(null);
|
|
2310
2461
|
const prevSourcePosition = useRef(sourcePosition);
|
|
2311
2462
|
const prevTargetPosition = useRef(targetPosition);
|
|
@@ -2317,10 +2468,10 @@ const wrapNode = (NodeComponent) => {
|
|
|
2317
2468
|
id,
|
|
2318
2469
|
store,
|
|
2319
2470
|
nodeRef,
|
|
2471
|
+
isSelectable,
|
|
2320
2472
|
});
|
|
2321
2473
|
}
|
|
2322
2474
|
if (onClick) {
|
|
2323
|
-
const node = store.getState().nodeInternals.get(id);
|
|
2324
2475
|
onClick(event, { ...node });
|
|
2325
2476
|
}
|
|
2326
2477
|
};
|
|
@@ -2354,9 +2505,14 @@ const wrapNode = (NodeComponent) => {
|
|
|
2354
2505
|
]);
|
|
2355
2506
|
}
|
|
2356
2507
|
}, [id, type, sourcePosition, targetPosition]);
|
|
2508
|
+
const clampedPosition = nodeExtent
|
|
2509
|
+
? clampPosition(node.positionAbsolute, nodeExtent)
|
|
2510
|
+
: node.positionAbsolute;
|
|
2511
|
+
const positionWithOrigin = getNodePositionWithOrigin({ ...node, ...clampedPosition }, nodeOrigin);
|
|
2357
2512
|
const dragging = useDrag({
|
|
2358
2513
|
nodeRef,
|
|
2359
2514
|
nodeId: id,
|
|
2515
|
+
disabled: hidden || !isDraggable,
|
|
2360
2516
|
isSelectable,
|
|
2361
2517
|
noDragClassName,
|
|
2362
2518
|
});
|
|
@@ -2379,7 +2535,7 @@ const wrapNode = (NodeComponent) => {
|
|
|
2379
2535
|
]);
|
|
2380
2536
|
const wrapperStyle = {
|
|
2381
2537
|
zIndex,
|
|
2382
|
-
transform: `translate(${
|
|
2538
|
+
transform: `translate(${positionWithOrigin.x}px,${positionWithOrigin.y}px)`,
|
|
2383
2539
|
pointerEvents: hasPointerEvents ? 'all' : 'none',
|
|
2384
2540
|
visibility: initialized ? 'visible' : 'hidden',
|
|
2385
2541
|
width,
|
|
@@ -2423,12 +2579,6 @@ const createNodeTypes = (nodeTypes) => {
|
|
|
2423
2579
|
};
|
|
2424
2580
|
};
|
|
2425
2581
|
|
|
2426
|
-
// import { StoreApi } from 'zustand';
|
|
2427
|
-
// type UpdateNodesParams = {
|
|
2428
|
-
// changedNodes: NodeSelectionChange[] | null;
|
|
2429
|
-
// get: StoreApi<ReactDiagramState>['getState'];
|
|
2430
|
-
// set: StoreApi<ReactDiagramState>['setState'];
|
|
2431
|
-
// };
|
|
2432
2582
|
function calculateXYZPosition(node, nodeInternals, result, nodeOrigin) {
|
|
2433
2583
|
if (!node.parentNode) {
|
|
2434
2584
|
return result;
|
|
@@ -2438,8 +2588,8 @@ function calculateXYZPosition(node, nodeInternals, result, nodeOrigin) {
|
|
|
2438
2588
|
return calculateXYZPosition(parentNode, nodeInternals, {
|
|
2439
2589
|
x: (result.x ?? 0) + parentNodePosition.x,
|
|
2440
2590
|
y: (result.y ?? 0) + parentNodePosition.y,
|
|
2441
|
-
z: (parentNode[internalsSymbol]?.z ?? 0) > (result.z ?? 0)
|
|
2442
|
-
? parentNode[internalsSymbol]?.z ?? 0
|
|
2591
|
+
z: (parentNode[internalsSymbol$1]?.z ?? 0) > (result.z ?? 0)
|
|
2592
|
+
? parentNode[internalsSymbol$1]?.z ?? 0
|
|
2443
2593
|
: result.z ?? 0,
|
|
2444
2594
|
}, nodeOrigin);
|
|
2445
2595
|
}
|
|
@@ -2451,15 +2601,15 @@ function updateAbsoluteNodePositions(nodeInternals, nodeOrigin, parentNodes) {
|
|
|
2451
2601
|
if (node.parentNode || parentNodes?.[node.id]) {
|
|
2452
2602
|
const { x, y, z } = calculateXYZPosition(node, nodeInternals, {
|
|
2453
2603
|
...node.position,
|
|
2454
|
-
z: node[internalsSymbol]?.z ?? 0,
|
|
2604
|
+
z: node[internalsSymbol$1]?.z ?? 0,
|
|
2455
2605
|
}, nodeOrigin);
|
|
2456
2606
|
node.positionAbsolute = {
|
|
2457
2607
|
x,
|
|
2458
2608
|
y,
|
|
2459
2609
|
};
|
|
2460
|
-
node[internalsSymbol].z = z;
|
|
2610
|
+
node[internalsSymbol$1].z = z;
|
|
2461
2611
|
if (parentNodes?.[node.id]) {
|
|
2462
|
-
node[internalsSymbol].isParent = true;
|
|
2612
|
+
node[internalsSymbol$1].isParent = true;
|
|
2463
2613
|
}
|
|
2464
2614
|
}
|
|
2465
2615
|
});
|
|
@@ -2485,56 +2635,42 @@ function createNodeInternals(nodes, nodeInternals, nodeOrigin, elevateNodesOnSel
|
|
|
2485
2635
|
internals.parentNode = node.parentNode;
|
|
2486
2636
|
parentNodes[node.parentNode] = true;
|
|
2487
2637
|
}
|
|
2488
|
-
Object.defineProperty(internals, internalsSymbol, {
|
|
2638
|
+
Object.defineProperty(internals, internalsSymbol$1, {
|
|
2489
2639
|
enumerable: false,
|
|
2490
2640
|
value: {
|
|
2491
|
-
portBounds: currInternals?.[internalsSymbol]?.portBounds,
|
|
2641
|
+
portBounds: currInternals?.[internalsSymbol$1]?.portBounds,
|
|
2492
2642
|
z,
|
|
2493
2643
|
},
|
|
2494
2644
|
});
|
|
2495
|
-
// console.log('create', currInternals, node);
|
|
2496
2645
|
nextNodeInternals.set(node.id, internals);
|
|
2497
2646
|
});
|
|
2498
2647
|
updateAbsoluteNodePositions(nextNodeInternals, nodeOrigin, parentNodes);
|
|
2499
2648
|
return nextNodeInternals;
|
|
2500
2649
|
}
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
//
|
|
2515
|
-
//
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
// }
|
|
2526
|
-
// return e;
|
|
2527
|
-
// });
|
|
2528
|
-
// }
|
|
2529
|
-
// export function updateNodesSelections({
|
|
2530
|
-
// changedNodes,
|
|
2531
|
-
// get,
|
|
2532
|
-
// }: UpdateNodesParams) {
|
|
2533
|
-
// const { onNodesChange } = get();
|
|
2534
|
-
// if (changedNodes?.length) {
|
|
2535
|
-
// onNodesChange?.(changedNodes);
|
|
2536
|
-
// }
|
|
2537
|
-
// }
|
|
2650
|
+
const isIntersected = (targetNode, nodeInternals) => {
|
|
2651
|
+
const { id, width, height, positionAbsolute } = targetNode;
|
|
2652
|
+
if (!width || !height)
|
|
2653
|
+
return false;
|
|
2654
|
+
let intersected = false;
|
|
2655
|
+
for (const [key, sourceNode] of nodeInternals) {
|
|
2656
|
+
if (id === key)
|
|
2657
|
+
continue;
|
|
2658
|
+
const { positionAbsolute: sPositionAbsolute, width: sWidth, height: sHeight, } = sourceNode;
|
|
2659
|
+
if (!sWidth || !sHeight)
|
|
2660
|
+
continue;
|
|
2661
|
+
if (!sPositionAbsolute || !positionAbsolute)
|
|
2662
|
+
continue;
|
|
2663
|
+
// if (sourceNode.parentNode === targetNode.id) continue;
|
|
2664
|
+
// if (targetNode.parentNode === sourceNode.id) continue;
|
|
2665
|
+
const leftIn = sPositionAbsolute.x + sWidth >= positionAbsolute.x, rightIn = positionAbsolute.x + width >= sPositionAbsolute.x, topIn = sPositionAbsolute.y + sHeight >= positionAbsolute.y, bottomIn = positionAbsolute.y + height >= sPositionAbsolute.y;
|
|
2666
|
+
const isIn = leftIn && rightIn && topIn && bottomIn;
|
|
2667
|
+
if (isIn) {
|
|
2668
|
+
intersected = true;
|
|
2669
|
+
break;
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
return intersected;
|
|
2673
|
+
};
|
|
2538
2674
|
|
|
2539
2675
|
const infiniteExtent = [
|
|
2540
2676
|
[Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
|
|
@@ -2563,8 +2699,8 @@ const initialState = {
|
|
|
2563
2699
|
minZoom: 0.5,
|
|
2564
2700
|
maxZoom: 2,
|
|
2565
2701
|
connectionPosition: { x: 0, y: 0 },
|
|
2566
|
-
|
|
2567
|
-
|
|
2702
|
+
connectionStartPort: null,
|
|
2703
|
+
connectionEndPort: null,
|
|
2568
2704
|
autoPanOnNodeDrag: true,
|
|
2569
2705
|
autoPanOnConnect: true,
|
|
2570
2706
|
nodeExtent: infiniteExtent,
|
|
@@ -2587,7 +2723,7 @@ const createRFStore = () => createStore((set, get) => ({
|
|
|
2587
2723
|
set({ edges: edges.map((e) => ({ ...defaultEdgeOptions, ...e })) });
|
|
2588
2724
|
},
|
|
2589
2725
|
updateNodeDimensions: (updates) => {
|
|
2590
|
-
const { onNodesChange, nodeInternals, domNode, nodeOrigin } = get();
|
|
2726
|
+
const { onNodesChange, updateNodesIntersection, nodeInternals, domNode, nodeOrigin, } = get();
|
|
2591
2727
|
const viewportNode = domNode?.querySelector('.react-diagram__viewport');
|
|
2592
2728
|
if (!viewportNode) {
|
|
2593
2729
|
return;
|
|
@@ -2606,9 +2742,10 @@ const createRFStore = () => createStore((set, get) => ({
|
|
|
2606
2742
|
if (doUpdate) {
|
|
2607
2743
|
nodeInternals.set(node.id, {
|
|
2608
2744
|
...node,
|
|
2609
|
-
[internalsSymbol]: {
|
|
2610
|
-
...node[internalsSymbol],
|
|
2745
|
+
[internalsSymbol$1]: {
|
|
2746
|
+
...node[internalsSymbol$1],
|
|
2611
2747
|
portBounds: {
|
|
2748
|
+
id: node[internalsSymbol$1]?.portBounds?.id || null,
|
|
2612
2749
|
source: getPortBounds('.source', update.nodeElement, zoom, nodeOrigin),
|
|
2613
2750
|
target: getPortBounds('.target', update.nodeElement, zoom, nodeOrigin),
|
|
2614
2751
|
},
|
|
@@ -2624,6 +2761,7 @@ const createRFStore = () => createStore((set, get) => ({
|
|
|
2624
2761
|
}
|
|
2625
2762
|
return res;
|
|
2626
2763
|
}, []);
|
|
2764
|
+
updateNodesIntersection();
|
|
2627
2765
|
updateAbsoluteNodePositions(nodeInternals, nodeOrigin);
|
|
2628
2766
|
set({
|
|
2629
2767
|
nodeInternals: new Map(nodeInternals),
|
|
@@ -2658,6 +2796,33 @@ const createRFStore = () => createStore((set, get) => ({
|
|
|
2658
2796
|
onNodesChange?.(changes);
|
|
2659
2797
|
}
|
|
2660
2798
|
},
|
|
2799
|
+
updateNodesIntersection: () => {
|
|
2800
|
+
const { nodeInternals, triggerNodeChanges } = get();
|
|
2801
|
+
const nodes = Array.from(nodeInternals.values());
|
|
2802
|
+
const unIntersectNodes = () => {
|
|
2803
|
+
return nodes
|
|
2804
|
+
.filter((node) => node.intersected && !isIntersected(node, nodeInternals))
|
|
2805
|
+
.map((node) => ({
|
|
2806
|
+
id: node.id,
|
|
2807
|
+
type: 'intersect',
|
|
2808
|
+
intersected: false,
|
|
2809
|
+
}));
|
|
2810
|
+
};
|
|
2811
|
+
const addIntersectNodes = () => {
|
|
2812
|
+
return nodes
|
|
2813
|
+
.filter((node) => isIntersected(node, nodeInternals))
|
|
2814
|
+
.map((node) => {
|
|
2815
|
+
return {
|
|
2816
|
+
id: node.id,
|
|
2817
|
+
type: 'intersect',
|
|
2818
|
+
intersected: true,
|
|
2819
|
+
};
|
|
2820
|
+
});
|
|
2821
|
+
};
|
|
2822
|
+
const intersectedNodes = addIntersectNodes();
|
|
2823
|
+
const unIntersectedNodes = unIntersectNodes();
|
|
2824
|
+
triggerNodeChanges([...intersectedNodes, ...unIntersectedNodes]);
|
|
2825
|
+
},
|
|
2661
2826
|
addSelectedNodes: (selectedNodeIds) => {
|
|
2662
2827
|
const { multiSelectionActive, getNodes, triggerNodeChanges } = get();
|
|
2663
2828
|
let changedNodes;
|
|
@@ -2687,9 +2852,17 @@ const createRFStore = () => createStore((set, get) => ({
|
|
|
2687
2852
|
triggerNodeChanges(nodesToUnselect);
|
|
2688
2853
|
},
|
|
2689
2854
|
cancelConnection: () => set({
|
|
2690
|
-
|
|
2691
|
-
|
|
2855
|
+
connectionStartPort: null,
|
|
2856
|
+
connectionEndPort: null,
|
|
2692
2857
|
}),
|
|
2858
|
+
updateConnection: (params) => {
|
|
2859
|
+
const { connectionPosition } = get();
|
|
2860
|
+
const currentConnection = {
|
|
2861
|
+
...params,
|
|
2862
|
+
connectionPosition: params.connectionPosition ?? connectionPosition,
|
|
2863
|
+
};
|
|
2864
|
+
set(currentConnection);
|
|
2865
|
+
},
|
|
2693
2866
|
panBy: (delta) => {
|
|
2694
2867
|
const { transform, width, height, d3Zoom, d3Selection } = get();
|
|
2695
2868
|
if (!d3Zoom || !d3Selection || (!delta.x && !delta.y)) {
|
|
@@ -2759,13 +2932,13 @@ const defaultEdgeTypes = {
|
|
|
2759
2932
|
};
|
|
2760
2933
|
const ReactDiagram = forwardRef(({ children, id,
|
|
2761
2934
|
// DiagramView props
|
|
2762
|
-
panning = true, minZoom, maxZoom, translateExtent, nodeExtent, defaultViewport = initViewport, multiSelectionKeyCode, onlyRenderVisibleElements = false, disableKeyboardA11y = false, noDragClassName = 'nodrag', noPanClassName = 'nopan', nodeOrigin = initNodeOrigin, nodeTypes = defaultNodeTypes, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, edgeTypes = defaultEdgeTypes, edgeUpdaterRadius, onEdgeClick, onEdgeDoubleClick, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, onMove, onMoveStart, onMoveEnd, ConnectionLineContainerStyle, ConnectionLineComponent,
|
|
2935
|
+
panning = true, minZoom, maxZoom, translateExtent, nodeExtent = infiniteExtent, defaultViewport = initViewport, multiSelectionKeyCode = 'Meta', dragSelectionKeyCode = 'Shift', onlyRenderVisibleElements = false, disableKeyboardA11y = false, noDragClassName = 'nodrag', noPanClassName = 'nopan', nodeOrigin = initNodeOrigin, nodeTypes = defaultNodeTypes, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, edgeTypes = defaultEdgeTypes, edgeUpdaterRadius, onEdgeClick, onEdgeDoubleClick, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, onMove, onMoveStart, onMoveEnd, ConnectionLineContainerStyle, ConnectionLineComponent,
|
|
2763
2936
|
// StoreUpdater props
|
|
2764
|
-
nodes, edges, nodesDraggable, elevateNodesOnSelect, autoPanOnNodeDrag, autoPanOnConnect, connectionRadius, smoothStep, centerStep, gridStep, onNodesChange, onNodeDrag, onNodeDragStart, onNodeDragEnd, onEdgesChange, onConnect, onConnectStart, onConnectEnd, onError, }, ref) => {
|
|
2937
|
+
nodes, edges, nodesDraggable, elevateNodesOnSelect, autoPanOnNodeDrag, autoPanOnConnect, connectionRadius, smoothStep, centerStep, gridStep, onNodesChange, onNodeDrag, onNodeDragStart, onNodeDragEnd, onEdgesChange, onConnect, onConnectStart, onConnectEnd, onError, ...rest }, ref) => {
|
|
2765
2938
|
const rfId = id || '1';
|
|
2766
2939
|
const nodeTypesWrapped = useNodeOrEdgeTypes(nodeTypes, createNodeTypes);
|
|
2767
2940
|
const edgeTypesWrapped = useNodeOrEdgeTypes(edgeTypes, createEdgeTypes);
|
|
2768
|
-
return (jsx("div", { ref: ref, className: "react-diagram", children: jsxs(Wrapper, { children: [jsx(DiagramView$1, { rfId: rfId, panning: panning, defaultViewport: defaultViewport, multiSelectionKeyCode: multiSelectionKeyCode, onlyRenderVisibleElements: onlyRenderVisibleElements, disableKeyboardA11y: disableKeyboardA11y, noDragClassName: noDragClassName, noPanClassName: noPanClassName, nodeOrigin: nodeOrigin, nodeTypes: nodeTypesWrapped, edgeTypes: edgeTypesWrapped, edgeUpdaterRadius: edgeUpdaterRadius, ConnectionLineContainerStyle: ConnectionLineContainerStyle, ConnectionLineComponent: ConnectionLineComponent, onNodeClick: onNodeClick, onNodeDoubleClick: onNodeDoubleClick, onNodeContextMenu: onNodeContextMenu, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave, onEdgeClick: onEdgeClick, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeContextMenu: onEdgeContextMenu, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, onEdgeUpdate: onEdgeUpdate, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd }), jsx(StoreUpdater, { rfId: rfId, nodes: nodes, edges: edges, nodesDraggable: nodesDraggable, elevateNodesOnSelect: elevateNodesOnSelect, autoPanOnNodeDrag: autoPanOnNodeDrag, autoPanOnConnect: autoPanOnConnect, connectionRadius: connectionRadius, nodeExtent: nodeExtent, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, smoothStep: smoothStep, centerStep: centerStep, gridStep: gridStep, onNodesChange: onNodesChange, onNodeDrag: onNodeDrag, onNodeDragStart: onNodeDragStart, onNodeDragEnd: onNodeDragEnd, onEdgesChange: onEdgesChange, onConnect: onConnect, onConnectStart: onConnectStart, onConnectEnd: onConnectEnd, onError: onError }), children] }) }));
|
|
2941
|
+
return (jsx("div", { ...rest, ref: ref, className: "react-diagram", children: jsxs(Wrapper, { children: [jsx(DiagramView$1, { rfId: rfId, panning: panning, defaultViewport: defaultViewport, multiSelectionKeyCode: multiSelectionKeyCode, dragSelectionKeyCode: dragSelectionKeyCode, onlyRenderVisibleElements: onlyRenderVisibleElements, disableKeyboardA11y: disableKeyboardA11y, noDragClassName: noDragClassName, noPanClassName: noPanClassName, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent, nodeTypes: nodeTypesWrapped, edgeTypes: edgeTypesWrapped, edgeUpdaterRadius: edgeUpdaterRadius, ConnectionLineContainerStyle: ConnectionLineContainerStyle, ConnectionLineComponent: ConnectionLineComponent, onNodeClick: onNodeClick, onNodeDoubleClick: onNodeDoubleClick, onNodeContextMenu: onNodeContextMenu, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave, onEdgeClick: onEdgeClick, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeContextMenu: onEdgeContextMenu, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, onEdgeUpdate: onEdgeUpdate, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd }), jsx(StoreUpdater, { rfId: rfId, nodes: nodes, edges: edges, nodesDraggable: nodesDraggable, elevateNodesOnSelect: elevateNodesOnSelect, autoPanOnNodeDrag: autoPanOnNodeDrag, autoPanOnConnect: autoPanOnConnect, connectionRadius: connectionRadius, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, smoothStep: smoothStep, centerStep: centerStep, gridStep: gridStep, onNodesChange: onNodesChange, onNodeDrag: onNodeDrag, onNodeDragStart: onNodeDragStart, onNodeDragEnd: onNodeDragEnd, onEdgesChange: onEdgesChange, onConnect: onConnect, onConnectStart: onConnectStart, onConnectEnd: onConnectEnd, onError: onError }), children] }) }));
|
|
2769
2942
|
});
|
|
2770
2943
|
ReactDiagram.displayName = 'ReactDiagram';
|
|
2771
2944
|
|
|
@@ -2810,4 +2983,4 @@ function Background({ gap, lineWidth = 1, color = '#000000', }) {
|
|
|
2810
2983
|
Background.displayName = 'Background';
|
|
2811
2984
|
var index = memo(Background);
|
|
2812
2985
|
|
|
2813
|
-
export { index as Background, BaseEdge, BezierEdge, MarkerType, Port$1 as Port, Position, ReactDiagramProvider, StepEdge, addEdge, boxToRect, clamp, ReactDiagram as default, getBezierPath, getStepPath, internalsSymbol,
|
|
2986
|
+
export { index as Background, BaseEdge, BezierEdge, MarkerType, Port$1 as Port, Position, ReactDiagramProvider, StepEdge, addEdge, boxToRect, clamp, ReactDiagram as default, getBezierEdgeCenter, getBezierPath, getStepPath, getStraightPath, internalsSymbol, isCoreEdge, isCoreNode, rectToBox, updateEdge, useEdgesState, useNodesState };
|