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.
Files changed (261) hide show
  1. package/README.md +4 -2
  2. package/dist/esm/components/A11yDescriptions/index.d.ts.map +1 -1
  3. package/dist/esm/components/Background/LinePath.d.ts.map +1 -1
  4. package/dist/esm/components/Background/index.d.ts.map +1 -1
  5. package/dist/esm/components/Background/type.d.ts.map +1 -1
  6. package/dist/esm/components/DragBox/index.d.ts +1 -1
  7. package/dist/esm/components/DragBox/index.d.ts.map +1 -1
  8. package/dist/esm/components/Edges/Anchor.d.ts +1 -1
  9. package/dist/esm/components/Edges/Anchor.d.ts.map +1 -1
  10. package/dist/esm/components/Edges/BaseEdge.d.ts.map +1 -1
  11. package/dist/esm/components/Edges/BezierEdge.d.ts +2 -13
  12. package/dist/esm/components/Edges/BezierEdge.d.ts.map +1 -1
  13. package/dist/esm/components/Edges/EdgeLabel.d.ts.map +1 -1
  14. package/dist/esm/components/Edges/EdgeWrapper/index.d.ts.map +1 -1
  15. package/dist/esm/components/Edges/EdgeWrapper/type.d.ts +3 -10
  16. package/dist/esm/components/Edges/EdgeWrapper/type.d.ts.map +1 -1
  17. package/dist/esm/components/Edges/StepEdge.d.ts +2 -22
  18. package/dist/esm/components/Edges/StepEdge.d.ts.map +1 -1
  19. package/dist/esm/components/Edges/StraightEdge.d.ts +0 -7
  20. package/dist/esm/components/Edges/StraightEdge.d.ts.map +1 -1
  21. package/dist/esm/components/Edges/type.d.ts +8 -35
  22. package/dist/esm/components/Edges/type.d.ts.map +1 -1
  23. package/dist/esm/components/Node/NodeWrapper/index.d.ts +3 -3
  24. package/dist/esm/components/Node/NodeWrapper/index.d.ts.map +1 -1
  25. package/dist/esm/components/Node/NodeWrapper/type.d.ts +4 -1
  26. package/dist/esm/components/Node/NodeWrapper/type.d.ts.map +1 -1
  27. package/dist/esm/components/Node/index.d.ts.map +1 -1
  28. package/dist/esm/components/Node/type.d.ts +4 -36
  29. package/dist/esm/components/Node/type.d.ts.map +1 -1
  30. package/dist/esm/components/Node/utils.d.ts +0 -3
  31. package/dist/esm/components/Node/utils.d.ts.map +1 -1
  32. package/dist/esm/components/Port/index.d.ts +2 -2
  33. package/dist/esm/components/Port/index.d.ts.map +1 -1
  34. package/dist/esm/components/ReactDiagramProvider/index.d.ts.map +1 -1
  35. package/dist/esm/components/ReactDiagramProvider/type.d.ts +10 -8
  36. package/dist/esm/components/ReactDiagramProvider/type.d.ts.map +1 -1
  37. package/dist/esm/components/SelectionBox/index.d.ts +1 -1
  38. package/dist/esm/components/SelectionBox/index.d.ts.map +1 -1
  39. package/dist/esm/components/SelectionBox/type.d.ts +1 -1
  40. package/dist/esm/components/SelectionBox/type.d.ts.map +1 -1
  41. package/dist/esm/components/StoreUpdater/index.d.ts +2 -2
  42. package/dist/esm/components/StoreUpdater/index.d.ts.map +1 -1
  43. package/dist/esm/container/ConnectionLineRenderer/ConnectionPath.d.ts +1 -1
  44. package/dist/esm/container/ConnectionLineRenderer/ConnectionPath.d.ts.map +1 -1
  45. package/dist/esm/container/ConnectionLineRenderer/index.d.ts.map +1 -1
  46. package/dist/esm/container/ConnectionLineRenderer/type.d.ts +2 -2
  47. package/dist/esm/container/ConnectionLineRenderer/type.d.ts.map +1 -1
  48. package/dist/esm/container/DiagramRenderer/index.d.ts +3 -2
  49. package/dist/esm/container/DiagramRenderer/index.d.ts.map +1 -1
  50. package/dist/esm/container/DragSelection/index.d.ts +2 -2
  51. package/dist/esm/container/DragSelection/index.d.ts.map +1 -1
  52. package/dist/esm/container/EdgeRenderer/MarkerComponent.d.ts.map +1 -1
  53. package/dist/esm/container/EdgeRenderer/MarkerSymbols.d.ts +1 -1
  54. package/dist/esm/container/EdgeRenderer/MarkerSymbols.d.ts.map +1 -1
  55. package/dist/esm/container/EdgeRenderer/index.d.ts.map +1 -1
  56. package/dist/esm/container/EdgeRenderer/type.d.ts.map +1 -1
  57. package/dist/esm/container/EdgeRenderer/utils.d.ts +3 -3
  58. package/dist/esm/container/EdgeRenderer/utils.d.ts.map +1 -1
  59. package/dist/esm/container/NodeRenderer/index.d.ts +1 -1
  60. package/dist/esm/container/NodeRenderer/index.d.ts.map +1 -1
  61. package/dist/esm/container/NodeRenderer/type.d.ts +2 -2
  62. package/dist/esm/container/NodeRenderer/type.d.ts.map +1 -1
  63. package/dist/esm/container/NodeRenderer/utils.d.ts.map +1 -1
  64. package/dist/esm/container/Pane/index.d.ts +2 -1
  65. package/dist/esm/container/Pane/index.d.ts.map +1 -1
  66. package/dist/esm/container/ReactDiagram/DiagramView.d.ts +2 -2
  67. package/dist/esm/container/ReactDiagram/DiagramView.d.ts.map +1 -1
  68. package/dist/esm/container/ReactDiagram/Wrapper.d.ts.map +1 -1
  69. package/dist/esm/container/ReactDiagram/index.d.ts +20 -20
  70. package/dist/esm/container/ReactDiagram/index.d.ts.map +1 -1
  71. package/dist/esm/container/Viewport/index.d.ts.map +1 -1
  72. package/dist/esm/contexts/NodeIdContext.d.ts.map +1 -1
  73. package/dist/esm/contexts/RFStoreContext.d.ts.map +1 -1
  74. package/dist/esm/hooks/useDrag.d.ts +9 -0
  75. package/dist/esm/hooks/useDrag.d.ts.map +1 -0
  76. package/dist/esm/hooks/useDragSelectionKeyPress.d.ts +4 -0
  77. package/dist/esm/hooks/useDragSelectionKeyPress.d.ts.map +1 -0
  78. package/dist/esm/hooks/useGlobalKeyHandler.d.ts +1 -1
  79. package/dist/esm/hooks/useGlobalKeyHandler.d.ts.map +1 -1
  80. package/dist/esm/hooks/useNodeOrEdgeTypes.d.ts.map +1 -1
  81. package/dist/esm/hooks/useNodesEdgesState/index.d.ts +2 -2
  82. package/dist/esm/hooks/useNodesEdgesState/index.d.ts.map +1 -1
  83. package/dist/esm/hooks/useNodesEdgesState/type.d.ts +7 -7
  84. package/dist/esm/hooks/useNodesEdgesState/type.d.ts.map +1 -1
  85. package/dist/esm/hooks/useStore.d.ts.map +1 -1
  86. package/dist/esm/hooks/useVisibleNodes.d.ts +1 -1
  87. package/dist/esm/hooks/useVisibleNodes.d.ts.map +1 -1
  88. package/dist/esm/index.d.ts +7 -5
  89. package/dist/esm/index.d.ts.map +1 -1
  90. package/dist/esm/index.js +1462 -1289
  91. package/dist/esm/store/index.d.ts.map +1 -1
  92. package/dist/esm/store/initialState.d.ts +1 -1
  93. package/dist/esm/store/initialState.d.ts.map +1 -1
  94. package/dist/esm/store/type.d.ts +0 -2
  95. package/dist/esm/store/type.d.ts.map +1 -1
  96. package/dist/esm/store/utils.d.ts +4 -4
  97. package/dist/esm/store/utils.d.ts.map +1 -1
  98. package/dist/esm/types/core.d.ts +4 -4
  99. package/dist/esm/types/core.d.ts.map +1 -1
  100. package/dist/esm/types/general.d.ts +1 -21
  101. package/dist/esm/types/general.d.ts.map +1 -1
  102. package/dist/esm/types/index.d.ts +0 -1
  103. package/dist/esm/types/index.d.ts.map +1 -1
  104. package/dist/esm/utils/changes.d.ts +2 -2
  105. package/dist/esm/utils/changes.d.ts.map +1 -1
  106. package/dist/esm/utils/deepEqual.d.ts.map +1 -1
  107. package/dist/esm/utils/index.d.ts +2 -21
  108. package/dist/esm/utils/index.d.ts.map +1 -1
  109. package/dist/style.css +13 -12
  110. package/dist/umd/components/A11yDescriptions/index.d.ts.map +1 -1
  111. package/dist/umd/components/Background/LinePath.d.ts.map +1 -1
  112. package/dist/umd/components/Background/index.d.ts.map +1 -1
  113. package/dist/umd/components/Background/type.d.ts.map +1 -1
  114. package/dist/umd/components/DragBox/index.d.ts +1 -1
  115. package/dist/umd/components/DragBox/index.d.ts.map +1 -1
  116. package/dist/umd/components/Edges/Anchor.d.ts +1 -1
  117. package/dist/umd/components/Edges/Anchor.d.ts.map +1 -1
  118. package/dist/umd/components/Edges/BaseEdge.d.ts.map +1 -1
  119. package/dist/umd/components/Edges/BezierEdge.d.ts +2 -13
  120. package/dist/umd/components/Edges/BezierEdge.d.ts.map +1 -1
  121. package/dist/umd/components/Edges/EdgeLabel.d.ts.map +1 -1
  122. package/dist/umd/components/Edges/EdgeWrapper/index.d.ts.map +1 -1
  123. package/dist/umd/components/Edges/EdgeWrapper/type.d.ts +3 -10
  124. package/dist/umd/components/Edges/EdgeWrapper/type.d.ts.map +1 -1
  125. package/dist/umd/components/Edges/StepEdge.d.ts +2 -22
  126. package/dist/umd/components/Edges/StepEdge.d.ts.map +1 -1
  127. package/dist/umd/components/Edges/StraightEdge.d.ts +0 -7
  128. package/dist/umd/components/Edges/StraightEdge.d.ts.map +1 -1
  129. package/dist/umd/components/Edges/type.d.ts +8 -35
  130. package/dist/umd/components/Edges/type.d.ts.map +1 -1
  131. package/dist/umd/components/Node/NodeWrapper/index.d.ts +3 -3
  132. package/dist/umd/components/Node/NodeWrapper/index.d.ts.map +1 -1
  133. package/dist/umd/components/Node/NodeWrapper/type.d.ts +4 -1
  134. package/dist/umd/components/Node/NodeWrapper/type.d.ts.map +1 -1
  135. package/dist/umd/components/Node/index.d.ts.map +1 -1
  136. package/dist/umd/components/Node/type.d.ts +4 -36
  137. package/dist/umd/components/Node/type.d.ts.map +1 -1
  138. package/dist/umd/components/Node/utils.d.ts +0 -3
  139. package/dist/umd/components/Node/utils.d.ts.map +1 -1
  140. package/dist/umd/components/Port/index.d.ts +2 -2
  141. package/dist/umd/components/Port/index.d.ts.map +1 -1
  142. package/dist/umd/components/ReactDiagramProvider/index.d.ts.map +1 -1
  143. package/dist/umd/components/ReactDiagramProvider/type.d.ts +10 -8
  144. package/dist/umd/components/ReactDiagramProvider/type.d.ts.map +1 -1
  145. package/dist/umd/components/SelectionBox/index.d.ts +1 -1
  146. package/dist/umd/components/SelectionBox/index.d.ts.map +1 -1
  147. package/dist/umd/components/SelectionBox/type.d.ts +1 -1
  148. package/dist/umd/components/SelectionBox/type.d.ts.map +1 -1
  149. package/dist/umd/components/StoreUpdater/index.d.ts +2 -2
  150. package/dist/umd/components/StoreUpdater/index.d.ts.map +1 -1
  151. package/dist/umd/container/ConnectionLineRenderer/ConnectionPath.d.ts +1 -1
  152. package/dist/umd/container/ConnectionLineRenderer/ConnectionPath.d.ts.map +1 -1
  153. package/dist/umd/container/ConnectionLineRenderer/index.d.ts.map +1 -1
  154. package/dist/umd/container/ConnectionLineRenderer/type.d.ts +2 -2
  155. package/dist/umd/container/ConnectionLineRenderer/type.d.ts.map +1 -1
  156. package/dist/umd/container/DiagramRenderer/index.d.ts +3 -2
  157. package/dist/umd/container/DiagramRenderer/index.d.ts.map +1 -1
  158. package/dist/umd/container/DragSelection/index.d.ts +2 -2
  159. package/dist/umd/container/DragSelection/index.d.ts.map +1 -1
  160. package/dist/umd/container/EdgeRenderer/MarkerComponent.d.ts.map +1 -1
  161. package/dist/umd/container/EdgeRenderer/MarkerSymbols.d.ts +1 -1
  162. package/dist/umd/container/EdgeRenderer/MarkerSymbols.d.ts.map +1 -1
  163. package/dist/umd/container/EdgeRenderer/index.d.ts.map +1 -1
  164. package/dist/umd/container/EdgeRenderer/type.d.ts.map +1 -1
  165. package/dist/umd/container/EdgeRenderer/utils.d.ts +3 -3
  166. package/dist/umd/container/EdgeRenderer/utils.d.ts.map +1 -1
  167. package/dist/umd/container/NodeRenderer/index.d.ts +1 -1
  168. package/dist/umd/container/NodeRenderer/index.d.ts.map +1 -1
  169. package/dist/umd/container/NodeRenderer/type.d.ts +2 -2
  170. package/dist/umd/container/NodeRenderer/type.d.ts.map +1 -1
  171. package/dist/umd/container/NodeRenderer/utils.d.ts.map +1 -1
  172. package/dist/umd/container/Pane/index.d.ts +2 -1
  173. package/dist/umd/container/Pane/index.d.ts.map +1 -1
  174. package/dist/umd/container/ReactDiagram/DiagramView.d.ts +2 -2
  175. package/dist/umd/container/ReactDiagram/DiagramView.d.ts.map +1 -1
  176. package/dist/umd/container/ReactDiagram/Wrapper.d.ts.map +1 -1
  177. package/dist/umd/container/ReactDiagram/index.d.ts +20 -20
  178. package/dist/umd/container/ReactDiagram/index.d.ts.map +1 -1
  179. package/dist/umd/container/Viewport/index.d.ts.map +1 -1
  180. package/dist/umd/contexts/NodeIdContext.d.ts.map +1 -1
  181. package/dist/umd/contexts/RFStoreContext.d.ts.map +1 -1
  182. package/dist/umd/hooks/useDrag.d.ts +9 -0
  183. package/dist/umd/hooks/useDrag.d.ts.map +1 -0
  184. package/dist/umd/hooks/useDragSelectionKeyPress.d.ts +4 -0
  185. package/dist/umd/hooks/useDragSelectionKeyPress.d.ts.map +1 -0
  186. package/dist/umd/hooks/useGlobalKeyHandler.d.ts +1 -1
  187. package/dist/umd/hooks/useGlobalKeyHandler.d.ts.map +1 -1
  188. package/dist/umd/hooks/useNodeOrEdgeTypes.d.ts.map +1 -1
  189. package/dist/umd/hooks/useNodesEdgesState/index.d.ts +2 -2
  190. package/dist/umd/hooks/useNodesEdgesState/index.d.ts.map +1 -1
  191. package/dist/umd/hooks/useNodesEdgesState/type.d.ts +7 -7
  192. package/dist/umd/hooks/useNodesEdgesState/type.d.ts.map +1 -1
  193. package/dist/umd/hooks/useStore.d.ts.map +1 -1
  194. package/dist/umd/hooks/useVisibleNodes.d.ts +1 -1
  195. package/dist/umd/hooks/useVisibleNodes.d.ts.map +1 -1
  196. package/dist/umd/index.d.ts +7 -5
  197. package/dist/umd/index.d.ts.map +1 -1
  198. package/dist/umd/index.js +2 -2
  199. package/dist/umd/store/index.d.ts.map +1 -1
  200. package/dist/umd/store/initialState.d.ts +1 -1
  201. package/dist/umd/store/initialState.d.ts.map +1 -1
  202. package/dist/umd/store/type.d.ts +0 -2
  203. package/dist/umd/store/type.d.ts.map +1 -1
  204. package/dist/umd/store/utils.d.ts +4 -4
  205. package/dist/umd/store/utils.d.ts.map +1 -1
  206. package/dist/umd/types/core.d.ts +4 -4
  207. package/dist/umd/types/core.d.ts.map +1 -1
  208. package/dist/umd/types/general.d.ts +1 -21
  209. package/dist/umd/types/general.d.ts.map +1 -1
  210. package/dist/umd/types/index.d.ts +0 -1
  211. package/dist/umd/types/index.d.ts.map +1 -1
  212. package/dist/umd/utils/changes.d.ts +2 -2
  213. package/dist/umd/utils/changes.d.ts.map +1 -1
  214. package/dist/umd/utils/deepEqual.d.ts.map +1 -1
  215. package/dist/umd/utils/index.d.ts +2 -21
  216. package/dist/umd/utils/index.d.ts.map +1 -1
  217. package/package.json +8 -6
  218. package/dist/esm/components/Edges/utils.d.ts +0 -17
  219. package/dist/esm/components/Edges/utils.d.ts.map +0 -1
  220. package/dist/esm/components/Port/type.d.ts +0 -22
  221. package/dist/esm/components/Port/type.d.ts.map +0 -1
  222. package/dist/esm/components/Port/utils.d.ts +0 -25
  223. package/dist/esm/components/Port/utils.d.ts.map +0 -1
  224. package/dist/esm/fixtures/errorMessages.d.ts +0 -11
  225. package/dist/esm/fixtures/errorMessages.d.ts.map +0 -1
  226. package/dist/esm/hooks/useDrag/index.d.ts +0 -10
  227. package/dist/esm/hooks/useDrag/index.d.ts.map +0 -1
  228. package/dist/esm/hooks/useDrag/type.d.ts +0 -11
  229. package/dist/esm/hooks/useDrag/type.d.ts.map +0 -1
  230. package/dist/esm/hooks/useDrag/utils.d.ts +0 -20
  231. package/dist/esm/hooks/useDrag/utils.d.ts.map +0 -1
  232. package/dist/esm/hooks/useGetPointerPosition.d.ts +0 -21
  233. package/dist/esm/hooks/useGetPointerPosition.d.ts.map +0 -1
  234. package/dist/esm/hooks/useUpdateIntersectionNodes/index.d.ts +0 -6
  235. package/dist/esm/hooks/useUpdateIntersectionNodes/index.d.ts.map +0 -1
  236. package/dist/esm/types/utils.d.ts +0 -26
  237. package/dist/esm/types/utils.d.ts.map +0 -1
  238. package/dist/esm/utils/graph.d.ts +0 -18
  239. package/dist/esm/utils/graph.d.ts.map +0 -1
  240. package/dist/umd/components/Edges/utils.d.ts +0 -17
  241. package/dist/umd/components/Edges/utils.d.ts.map +0 -1
  242. package/dist/umd/components/Port/type.d.ts +0 -22
  243. package/dist/umd/components/Port/type.d.ts.map +0 -1
  244. package/dist/umd/components/Port/utils.d.ts +0 -25
  245. package/dist/umd/components/Port/utils.d.ts.map +0 -1
  246. package/dist/umd/fixtures/errorMessages.d.ts +0 -11
  247. package/dist/umd/fixtures/errorMessages.d.ts.map +0 -1
  248. package/dist/umd/hooks/useDrag/index.d.ts +0 -10
  249. package/dist/umd/hooks/useDrag/index.d.ts.map +0 -1
  250. package/dist/umd/hooks/useDrag/type.d.ts +0 -11
  251. package/dist/umd/hooks/useDrag/type.d.ts.map +0 -1
  252. package/dist/umd/hooks/useDrag/utils.d.ts +0 -20
  253. package/dist/umd/hooks/useDrag/utils.d.ts.map +0 -1
  254. package/dist/umd/hooks/useGetPointerPosition.d.ts +0 -21
  255. package/dist/umd/hooks/useGetPointerPosition.d.ts.map +0 -1
  256. package/dist/umd/hooks/useUpdateIntersectionNodes/index.d.ts +0 -6
  257. package/dist/umd/hooks/useUpdateIntersectionNodes/index.d.ts.map +0 -1
  258. package/dist/umd/types/utils.d.ts +0 -26
  259. package/dist/umd/types/utils.d.ts.map +0 -1
  260. package/dist/umd/utils/graph.d.ts +0 -18
  261. 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, useCallback, memo, forwardRef } from 'react';
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 { drag } from 'd3-drag';
8
+ import { shallow } from 'zustand/shallow';
9
9
 
10
- const StoreContext = createContext(null);
11
- const Provider$1 = StoreContext.Provider;
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 zustandErrorMessage = errorMessages['001']();
24
- function useStore(selector, equalityFn) {
25
- const store = useContext(StoreContext);
26
- if (store === null) {
27
- throw new Error(zustandErrorMessage);
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
- return useStore$1(store, selector, equalityFn);
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 useMemo(() => ({
37
- getState: store.getState,
38
- setState: store.setState,
39
- subscribe: store.subscribe,
40
- destroy: store.destroy,
41
- }), [store]);
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 isMouseEvent = (event) => 'clientX' in event;
113
- const getEventPosition = (event, bounds) => {
114
- const isMouseTriggered = isMouseEvent(event);
115
- const eventX = isMouseTriggered ? event.clientX : event.touches?.[0].clientX;
116
- const eventY = isMouseTriggered ? event.clientY : event.touches?.[0].clientY;
117
- return {
118
- x: eventX - (bounds?.left ?? 0),
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 convertTransform = (transform) => {
139
- const { x, y, k } = transform;
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
- x,
142
- y,
143
- zoom: k,
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 isWrappedWithClass = (event, className) => event.target.closest(`.${className}`);
147
- const isViewChanged = (prevViewport, eventViewport) => {
148
- const { x: prevX, y: prevY, zoom: prevZoom } = prevViewport;
149
- const { x, y, k } = eventViewport;
150
- return prevX !== x || prevY !== y || prevZoom !== k;
151
- };
152
- const selector$8 = (s) => ({
153
- d3Zoom: s.d3Zoom,
154
- d3Selection: s.d3Selection,
155
- });
156
- function Pane({ noPanClassName, panning, minZoom, maxZoom, defaultViewport, translateExtent, children, onMove, onMoveStart, onMoveEnd, }) {
157
- const store = useStoreApi();
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 === 'parent') {
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 has = Object.prototype.hasOwnProperty;
628
- const deepEqual = (foo, bar) => {
629
- let constructor;
630
- let length;
631
- if (foo === bar)
632
- return true;
633
- if (foo && bar && foo.constructor === bar.constructor) {
634
- constructor = foo.constructor;
635
- if (constructor === Date)
636
- return foo.getTime() === bar.getTime();
637
- if (constructor === RegExp)
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
- function useUpdateIntersectionNodes() {
664
- const store = useStoreApi();
665
- const intersectionChanges = useRef([]);
666
- const resetIntersectedNodes = useCallback((intersectedNodes) => {
667
- const hasIntersectedNodes = intersectedNodes.length;
668
- let beforeChanges;
669
- if (hasIntersectedNodes) {
670
- beforeChanges = intersectionChanges.current
671
- .filter((beforeChange) => {
672
- return !intersectedNodes.some((intersectedNode) => beforeChange.id === intersectedNode.id);
673
- })
674
- .map((beforeChange) => ({
675
- ...beforeChange,
676
- intersected: false,
677
- }));
678
- }
679
- else {
680
- beforeChanges = intersectionChanges.current.map((beforeChange) => ({
681
- ...beforeChange,
682
- intersected: false,
683
- }));
684
- }
685
- return beforeChanges;
686
- }, []);
687
- const updateNodesIntersection = useCallback((dragItems) => {
688
- const { getNodes, triggerNodeChanges } = store.getState();
689
- const intersectedDraggingNodeIds = [];
690
- const intersectedNodes = getNodes()
691
- .filter((node) => {
692
- const { width, height, position, parentNode } = node;
693
- if (parentNode)
694
- return;
695
- if (width && height) {
696
- return dragItems.current?.some((dragItem) => {
697
- const { position: dPosition, width: dWidth, height: dHeight, } = dragItem;
698
- if (node.id === dragItem.id)
699
- return;
700
- if (dragItem.parentNode)
701
- return;
702
- if (!dWidth || !dHeight)
703
- return;
704
- const leftIn = dPosition.x + dWidth >= position.x, rightIn = position.x + width >= dPosition.x, topIn = dPosition.y + dHeight >= position.y, bottomIn = position.y + height >= dPosition.y;
705
- const isIn = leftIn && rightIn && topIn && bottomIn;
706
- if (isIn) {
707
- if (!intersectedDraggingNodeIds.includes(dragItem.id)) {
708
- intersectedDraggingNodeIds.push(dragItem.id);
709
- }
710
- }
711
- return isIn;
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
- .map((node) => {
716
- return {
717
- id: node.id,
718
- type: 'intersect',
719
- intersected: true,
720
- };
721
- });
722
- const intersectedDraggingNodes = intersectedDraggingNodeIds.map((id) => {
723
- return {
724
- id,
725
- type: 'intersect',
726
- intersected: true,
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
- const changes = [...intersectedNodes, ...intersectedDraggingNodes];
730
- if (!deepEqual(changes, intersectionChanges.current)) {
731
- const beforeChanges = resetIntersectedNodes(changes);
732
- intersectionChanges.current = changes;
733
- triggerNodeChanges([...changes, ...beforeChanges]);
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
- return updateNodesIntersection;
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 isDragItem = (node) => 'distance' in node;
740
- function useDrag({ nodeRef, nodeId, isSelectable, noDragClassName, }) {
741
- const store = useStoreApi();
742
- const dragItems = useRef([]);
743
- const containerBounds = useRef(null);
744
- const mousePosition = useRef({ x: 0, y: 0 });
745
- const lastPosition = useRef({ x: 0, y: 0 });
746
- const dragEvent = useRef(null);
747
- const autoPanStarted = useRef(false);
748
- const autoPanId = useRef(0);
749
- const [dragging, setDragging] = useState(false);
750
- const getPointerPosition = useGetPointerPosition();
751
- const updateNodesIntersection = useUpdateIntersectionNodes();
752
- const updateNodePosition = (pointerPositions, dragEnd = false) => (dragItem) => {
753
- if (!isDragItem(dragItem))
754
- return;
755
- const { nodeInternals, nodeExtent, nodeOrigin, smoothStep, gridStep, onError, } = store.getState();
756
- const { distance, width, height } = dragItem;
757
- const { x, y, getStepPosition } = pointerPositions;
758
- let nextPosition = {
759
- x: x - distance.x,
760
- y: y - distance.y,
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
- if (gridStep && getStepPosition) {
763
- const nodeSize = { width, height };
764
- const stepPosition = getStepPosition({
765
- position: nextPosition,
766
- nodeSize,
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
- if (!smoothStep || (smoothStep && dragEnd)) {
769
- nextPosition = stepPosition;
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
- const updatedPosition = calcNextPosition(dragItem, nextPosition, nodeInternals, nodeExtent, nodeOrigin, onError);
773
- const hasChange = hasChangedPosition(dragItem.position, updatedPosition.position);
774
- if (!hasChange)
775
- return;
776
- dragItem.position = updatedPosition.position;
777
- dragItem.positionAbsolute = updatedPosition.positionAbsolute;
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
- if (nodeRef?.current) {
781
- const selection = select(nodeRef.current);
782
- const updateNodes = (pointerPosition) => {
783
- const { nodeInternals, onNodeDrag, updateNodesPosition } = store.getState();
784
- const { x, y } = pointerPosition;
785
- lastPosition.current = { x, y };
786
- updateNodesPosition(dragItems.current, true, updateNodePosition(pointerPosition));
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
- if (onNodeDrag && dragEvent.current) {
789
- const [currentNode, nodes] = getEventHandlerParams({
790
- nodeId,
791
- dragItems: dragItems.current,
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
- autoPanStarted.current = false;
854
- cancelAnimationFrame(autoPanId.current);
855
- if (dragItems.current) {
856
- const { nodeInternals, smoothStep, gridStep, updateNodesPosition, onNodeDragEnd, } = store.getState();
857
- const isSmoothStep = !!gridStep && smoothStep;
858
- if (isSmoothStep) {
859
- const pointerPosition = getPointerPosition(event);
860
- updateNodesPosition(dragItems.current, false, updateNodePosition(pointerPosition, true));
861
- updateNodesIntersection(dragItems);
862
- }
863
- else {
864
- updateNodesPosition(dragItems.current, false);
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
- selection.on('.drag', null);
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({ children, dragSelectionKeyPressed, }) {
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 && dragSelectionKeyPressed;
1172
- return (jsxs("div", { ref: dragSelection, className: "react-diagram__container react-diagram__drag-selection", onClick: onClick, onMouseDown: isPossibleDragSelection ? onMouseDown : undefined, onMouseMove: isPossibleDragSelection ? onMouseMove : undefined, onMouseUp: elementsSelectable && dragBoxRect ? onMouseUp : undefined, onMouseLeave: isPossibleDragSelection ? onMouseLeave : undefined, children: [children, dragBoxActive && jsx(DragBox, { rect: dragBoxRect }), selectionBoxActive && (jsx(SelectionBox$1, { rect: selectionBoxRect, transform: transformString }))] }));
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 selector$5 = (s) => {
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
- useGlobalKeyHandler(multiSelectionKeyCode);
1662
+ // useKeyPress
1187
1663
  const handleKeyDown = (e) => {
1188
- if (e.key === 'Shift') {
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 (jsx(Pane, { noPanClassName: noPanClassName, panning: panning && !dragSelectionKeyPressed, minZoom: minZoom, maxZoom: maxZoom, translateExtent: translateExtent, defaultViewport: defaultViewport, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, children: jsx(DragSelection, { dragSelectionKeyPressed: dragSelectionKeyPressed, children: jsx(Viewport, { children: children }) }) }));
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
- res += segment;
1542
- return res;
1543
- }, '');
1544
- return [path, labelX, labelY, offsetX, offsetY];
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
- handlePointerDown({
2007
+ CosmosPort.onPointerDown({
1888
2008
  isAnchor: true,
1889
- event,
2009
+ event: event.nativeEvent,
1890
2010
  nodeId,
2011
+ portId,
1891
2012
  portType: fromPortType,
1892
- getState: store.getState,
1893
- setState: store.setState,
1894
- onConnect: onConnectEdge,
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[0];
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
- nodeId: s.connectionNodeId,
2164
- portType: s.connectionPortType,
2294
+ startPort: s.connectionStartPort,
2165
2295
  });
2166
2296
  function ConnectionLineRenderer({ containerStyle, edgeTypes, component, }) {
2167
- const { nodeId, portType, edges } = useStore(selector$2, shallow);
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
- if ((isMouseTriggered && event.button === 0) || !isMouseTriggered) {
2287
- handlePointerDown({
2288
- event,
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
- getState: store.getState,
2292
- setState: store.setState,
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(${positionX}px,${positionY}px)`,
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
- // export function handleControlledNodeSelectionChange(
2502
- // nodeChanges: NodeSelectionChange[],
2503
- // nodeInternals: NodeInternals,
2504
- // ) {
2505
- // nodeChanges.forEach((change) => {
2506
- // const node = nodeInternals.get(change.id);
2507
- // if (node) {
2508
- // nodeInternals.set(node.id, {
2509
- // ...node,
2510
- // [internalsSymbol]: node[internalsSymbol],
2511
- // selected: change.selected,
2512
- // });
2513
- // }
2514
- // });
2515
- // return new Map(nodeInternals);
2516
- // }
2517
- // export function handleControlledEdgeSelectionChange(
2518
- // edgeChanges: EdgeSelectionChange[],
2519
- // edges: Edge[],
2520
- // ) {
2521
- // return edges.map((e) => {
2522
- // const change = edgeChanges.find((change) => change.id === e.id);
2523
- // if (change) {
2524
- // e.selected = change.selected;
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
- connectionNodeId: null,
2567
- connectionPortType: 'source',
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
- connectionNodeId: initialState.connectionNodeId,
2691
- connectionPortType: initialState.connectionPortType,
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, isEdge, isNode, rectToBox, updateEdge, useEdgesState, useNodesState };
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 };