react-cosmos-diagram 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/Background/LinePath.d.ts +8 -0
- package/dist/esm/components/Background/LinePath.d.ts.map +1 -0
- package/dist/esm/components/Background/index.d.ts +9 -0
- package/dist/esm/components/Background/index.d.ts.map +1 -0
- package/dist/esm/components/Background/type.d.ts +6 -0
- package/dist/esm/components/Background/type.d.ts.map +1 -0
- package/dist/esm/components/ReactDiagramProvider/type.d.ts +4 -2
- package/dist/esm/components/ReactDiagramProvider/type.d.ts.map +1 -1
- package/dist/esm/components/SelectionBox/index.d.ts.map +1 -1
- package/dist/esm/components/StoreUpdater/index.d.ts +2 -2
- package/dist/esm/components/StoreUpdater/index.d.ts.map +1 -1
- package/dist/esm/container/DragSelection/index.d.ts +0 -3
- package/dist/esm/container/DragSelection/index.d.ts.map +1 -1
- package/dist/esm/container/NodeRenderer/index.d.ts.map +1 -1
- package/dist/esm/container/Pane/index.d.ts.map +1 -1
- package/dist/esm/container/ReactDiagram/index.d.ts +2 -0
- package/dist/esm/container/ReactDiagram/index.d.ts.map +1 -1
- package/dist/esm/hooks/useDrag/index.d.ts.map +1 -1
- package/dist/esm/hooks/useDrag/type.d.ts +3 -10
- package/dist/esm/hooks/useDrag/type.d.ts.map +1 -1
- package/dist/esm/hooks/useDrag/utils.d.ts +7 -6
- package/dist/esm/hooks/useDrag/utils.d.ts.map +1 -1
- package/dist/esm/hooks/useGetPointerPosition.d.ts +14 -2
- package/dist/esm/hooks/useGetPointerPosition.d.ts.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1281 -1218
- package/dist/esm/store/index.d.ts.map +1 -1
- package/dist/esm/store/initialState.d.ts.map +1 -1
- package/dist/esm/types/core.d.ts +2 -0
- package/dist/esm/types/core.d.ts.map +1 -1
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/umd/components/Background/LinePath.d.ts +8 -0
- package/dist/umd/components/Background/LinePath.d.ts.map +1 -0
- package/dist/umd/components/Background/index.d.ts +9 -0
- package/dist/umd/components/Background/index.d.ts.map +1 -0
- package/dist/umd/components/Background/type.d.ts +6 -0
- package/dist/umd/components/Background/type.d.ts.map +1 -0
- package/dist/umd/components/ReactDiagramProvider/type.d.ts +4 -2
- package/dist/umd/components/ReactDiagramProvider/type.d.ts.map +1 -1
- package/dist/umd/components/SelectionBox/index.d.ts.map +1 -1
- package/dist/umd/components/StoreUpdater/index.d.ts +2 -2
- package/dist/umd/components/StoreUpdater/index.d.ts.map +1 -1
- package/dist/umd/container/DragSelection/index.d.ts +0 -3
- package/dist/umd/container/DragSelection/index.d.ts.map +1 -1
- package/dist/umd/container/NodeRenderer/index.d.ts.map +1 -1
- package/dist/umd/container/Pane/index.d.ts.map +1 -1
- package/dist/umd/container/ReactDiagram/index.d.ts +2 -0
- package/dist/umd/container/ReactDiagram/index.d.ts.map +1 -1
- package/dist/umd/hooks/useDrag/index.d.ts.map +1 -1
- package/dist/umd/hooks/useDrag/type.d.ts +3 -10
- package/dist/umd/hooks/useDrag/type.d.ts.map +1 -1
- package/dist/umd/hooks/useDrag/utils.d.ts +7 -6
- package/dist/umd/hooks/useDrag/utils.d.ts.map +1 -1
- package/dist/umd/hooks/useGetPointerPosition.d.ts +14 -2
- package/dist/umd/hooks/useGetPointerPosition.d.ts.map +1 -1
- package/dist/umd/index.d.ts +1 -0
- package/dist/umd/index.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/store/index.d.ts.map +1 -1
- package/dist/umd/store/initialState.d.ts.map +1 -1
- package/dist/umd/types/core.d.ts +2 -0
- package/dist/umd/types/core.d.ts.map +1 -1
- package/dist/umd/types/index.d.ts +1 -0
- package/dist/umd/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext, useContext, useMemo, useState, useEffect, useRef,
|
|
2
|
+
import { createContext, useContext, useMemo, useState, useEffect, useRef, useCallback, memo, forwardRef } from 'react';
|
|
3
3
|
import { useStore as useStore$1, createStore } from 'zustand';
|
|
4
4
|
import { zoom, zoomIdentity } from 'd3-zoom';
|
|
5
5
|
import { select } from 'd3-selection';
|
|
@@ -112,11 +112,11 @@ const getBoundsOfBoxes = (box1, box2) => ({
|
|
|
112
112
|
const isMouseEvent = (event) => 'clientX' in event;
|
|
113
113
|
const getEventPosition = (event, bounds) => {
|
|
114
114
|
const isMouseTriggered = isMouseEvent(event);
|
|
115
|
-
const
|
|
116
|
-
const
|
|
115
|
+
const eventX = isMouseTriggered ? event.clientX : event.touches?.[0].clientX;
|
|
116
|
+
const eventY = isMouseTriggered ? event.clientY : event.touches?.[0].clientY;
|
|
117
117
|
return {
|
|
118
|
-
x:
|
|
119
|
-
y:
|
|
118
|
+
x: eventX - (bounds?.left ?? 0),
|
|
119
|
+
y: eventY - (bounds?.top ?? 0),
|
|
120
120
|
};
|
|
121
121
|
};
|
|
122
122
|
const calcAutoPanVelocity = (value, bound, radius, velocity) => {
|
|
@@ -149,10 +149,9 @@ const isViewChanged = (prevViewport, eventViewport) => {
|
|
|
149
149
|
const { x, y, k } = eventViewport;
|
|
150
150
|
return prevX !== x || prevY !== y || prevZoom !== k;
|
|
151
151
|
};
|
|
152
|
-
const selector$
|
|
152
|
+
const selector$8 = (s) => ({
|
|
153
153
|
d3Zoom: s.d3Zoom,
|
|
154
154
|
d3Selection: s.d3Selection,
|
|
155
|
-
elementsSelectable: s.elementsSelectable,
|
|
156
155
|
});
|
|
157
156
|
function Pane({ noPanClassName, panning, minZoom, maxZoom, defaultViewport, translateExtent, children, onMove, onMoveStart, onMoveEnd, }) {
|
|
158
157
|
const store = useStoreApi();
|
|
@@ -161,7 +160,7 @@ function Pane({ noPanClassName, panning, minZoom, maxZoom, defaultViewport, tran
|
|
|
161
160
|
const d3ZoomHandler = useRef();
|
|
162
161
|
const prevTransform = useRef({ x: 0, y: 0, zoom: 0 });
|
|
163
162
|
const timerId = useRef();
|
|
164
|
-
const { d3Zoom, d3Selection } = useStore(selector$
|
|
163
|
+
const { d3Zoom, d3Selection } = useStore(selector$8, shallow);
|
|
165
164
|
useEffect(() => {
|
|
166
165
|
if (Pane.current) {
|
|
167
166
|
const bbox = Pane.current.getBoundingClientRect();
|
|
@@ -269,9 +268,9 @@ function Pane({ noPanClassName, panning, minZoom, maxZoom, defaultViewport, tran
|
|
|
269
268
|
return (jsx("div", { className: "react-diagram__pane react-diagram__container", ref: Pane, children: children }));
|
|
270
269
|
}
|
|
271
270
|
|
|
272
|
-
const selector$
|
|
271
|
+
const selector$7 = (s) => `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`;
|
|
273
272
|
function Viewport({ children }) {
|
|
274
|
-
const transform = useStore(selector$
|
|
273
|
+
const transform = useStore(selector$7);
|
|
275
274
|
return (jsx("div", { className: "react-diagram__viewport react-diagram__container", style: { transform }, children: children }));
|
|
276
275
|
}
|
|
277
276
|
|
|
@@ -286,22 +285,92 @@ function DragBox({ rect }) {
|
|
|
286
285
|
} }));
|
|
287
286
|
}
|
|
288
287
|
|
|
289
|
-
function
|
|
290
|
-
const
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
+
}
|
|
303
373
|
}
|
|
304
|
-
var SelectionBox$1 = memo(SelectionBox);
|
|
305
374
|
|
|
306
375
|
const isNode = (element) => 'id' in element && !('source' in element) && !('target' in element);
|
|
307
376
|
const isEdge = (element) => 'source' in element && 'target' in element;
|
|
@@ -433,396 +502,696 @@ const getRectOfNodes = (nodes, nodeOrigin = [0, 0]) => {
|
|
|
433
502
|
return boxToRect(box);
|
|
434
503
|
};
|
|
435
504
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
const extendWidth = updateItem.position.x + updateItem.width - parent.width;
|
|
440
|
-
const extendHeight = updateItem.position.y + updateItem.height - parent.height;
|
|
441
|
-
if (extendWidth > 0 ||
|
|
442
|
-
extendHeight > 0 ||
|
|
443
|
-
updateItem.position.x < 0 ||
|
|
444
|
-
updateItem.position.y < 0) {
|
|
445
|
-
parent.style = { ...parent.style } || {};
|
|
446
|
-
parent.style.width = parent.style.width ?? parent.width;
|
|
447
|
-
parent.style.height = parent.style.height ?? parent.height;
|
|
448
|
-
if (extendWidth > 0) {
|
|
449
|
-
parent.style.width += extendWidth;
|
|
450
|
-
}
|
|
451
|
-
if (extendHeight > 0) {
|
|
452
|
-
parent.style.height += extendHeight;
|
|
453
|
-
}
|
|
454
|
-
if (updateItem.position.x < 0) {
|
|
455
|
-
const xDiff = Math.abs(updateItem.position.x);
|
|
456
|
-
parent.position.x = parent.position.x - xDiff;
|
|
457
|
-
parent.style.width += xDiff;
|
|
458
|
-
updateItem.position.x = 0;
|
|
459
|
-
}
|
|
460
|
-
if (updateItem.position.y < 0) {
|
|
461
|
-
const yDiff = Math.abs(updateItem.position.y);
|
|
462
|
-
parent.position.y = parent.position.y - yDiff;
|
|
463
|
-
parent.style.height += yDiff;
|
|
464
|
-
updateItem.position.y = 0;
|
|
465
|
-
}
|
|
466
|
-
parent.width = parent.style.width;
|
|
467
|
-
parent.height = parent.style.height;
|
|
468
|
-
}
|
|
505
|
+
function isParentSelected(node, nodeInternals) {
|
|
506
|
+
if (!node.parentNode) {
|
|
507
|
+
return false;
|
|
469
508
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if (changes.some((c) => c.type === 'reset')) {
|
|
474
|
-
return changes.filter((c) => c.type === 'reset').map((c) => c.item);
|
|
509
|
+
const parentNode = nodeInternals.get(node.parentNode);
|
|
510
|
+
if (!parentNode) {
|
|
511
|
+
return false;
|
|
475
512
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
return
|
|
480
|
-
const currentChanges = changes.filter((c) => c.id === item.id);
|
|
481
|
-
if (currentChanges.length === 0) {
|
|
482
|
-
res.push(item);
|
|
483
|
-
return res;
|
|
484
|
-
}
|
|
485
|
-
const updateItem = { ...item };
|
|
486
|
-
for (const currentChange of currentChanges) {
|
|
487
|
-
if (currentChange) {
|
|
488
|
-
switch (currentChange.type) {
|
|
489
|
-
case 'select': {
|
|
490
|
-
updateItem.selected = currentChange.selected;
|
|
491
|
-
break;
|
|
492
|
-
}
|
|
493
|
-
case 'position': {
|
|
494
|
-
if (typeof currentChange.position !== 'undefined') {
|
|
495
|
-
updateItem.position = currentChange.position;
|
|
496
|
-
}
|
|
497
|
-
if (typeof currentChange.positionAbsolute !== 'undefined') {
|
|
498
|
-
updateItem.positionAbsolute =
|
|
499
|
-
currentChange.positionAbsolute;
|
|
500
|
-
}
|
|
501
|
-
if (typeof currentChange.dragging !== 'undefined') {
|
|
502
|
-
updateItem.dragging = currentChange.dragging;
|
|
503
|
-
}
|
|
504
|
-
if (updateItem.expandParent) {
|
|
505
|
-
handleParentExpand(res, updateItem);
|
|
506
|
-
}
|
|
507
|
-
break;
|
|
508
|
-
}
|
|
509
|
-
case 'dimensions': {
|
|
510
|
-
if (typeof currentChange.dimensions !== 'undefined') {
|
|
511
|
-
updateItem.width = currentChange.dimensions.width;
|
|
512
|
-
updateItem.height = currentChange.dimensions.height;
|
|
513
|
-
}
|
|
514
|
-
if (typeof currentChange.updateStyle !== 'undefined') {
|
|
515
|
-
updateItem.style = {
|
|
516
|
-
...(updateItem.style || {}),
|
|
517
|
-
...currentChange.dimensions,
|
|
518
|
-
};
|
|
519
|
-
}
|
|
520
|
-
if (typeof currentChange.resizing === 'boolean') {
|
|
521
|
-
updateItem.resizing = currentChange.resizing;
|
|
522
|
-
}
|
|
523
|
-
if (updateItem.expandParent) {
|
|
524
|
-
handleParentExpand(res, updateItem);
|
|
525
|
-
}
|
|
526
|
-
break;
|
|
527
|
-
}
|
|
528
|
-
case 'remove': {
|
|
529
|
-
return res;
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
res.push(updateItem);
|
|
535
|
-
return res;
|
|
536
|
-
}, initElements);
|
|
537
|
-
};
|
|
538
|
-
function applyNodeChanges(changes, nodes) {
|
|
539
|
-
return applyChanges(changes, nodes);
|
|
540
|
-
}
|
|
541
|
-
function applyEdgeChanges(changes, edges) {
|
|
542
|
-
return applyChanges(changes, edges);
|
|
513
|
+
if (parentNode.selected) {
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
return isParentSelected(parentNode, nodeInternals);
|
|
543
517
|
}
|
|
544
|
-
const
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
518
|
+
const getDragItems = (nodeInternals, nodesDraggable, mousePosition, nodeId) => {
|
|
519
|
+
const filteredNode = Array.from(nodeInternals.values()).filter((n) => {
|
|
520
|
+
const hasSize = n.width && n.height;
|
|
521
|
+
const isSelected = n.selected || n.id === nodeId;
|
|
522
|
+
const hasNoParent = !n.parentNode || !isParentSelected(n, nodeInternals);
|
|
523
|
+
const isDraggable = n.draggable || (nodesDraggable && typeof n.draggable === 'undefined');
|
|
524
|
+
return hasSize && isSelected && hasNoParent && isDraggable;
|
|
525
|
+
});
|
|
526
|
+
return filteredNode.map((n) => ({
|
|
527
|
+
id: n.id,
|
|
528
|
+
position: n.position || { x: 0, y: 0 },
|
|
529
|
+
positionAbsolute: n.positionAbsolute || { x: 0, y: 0 },
|
|
530
|
+
distance: {
|
|
531
|
+
x: mousePosition.x - (n.positionAbsolute?.x ?? 0),
|
|
532
|
+
y: mousePosition.y - (n.positionAbsolute?.y ?? 0),
|
|
533
|
+
},
|
|
534
|
+
extent: n.extent,
|
|
535
|
+
parentNode: n.parentNode,
|
|
536
|
+
width: n.width,
|
|
537
|
+
height: n.height,
|
|
538
|
+
}));
|
|
539
|
+
};
|
|
540
|
+
const calcNextPosition = (node, nextPosition, nodeInternals, nodeExtent, nodeOrigin = [0, 0], onError) => {
|
|
541
|
+
let currentExtent = node.extent || nodeExtent;
|
|
542
|
+
if (node.extent === 'parent') {
|
|
543
|
+
if (node.parentNode && node.width && node.height) {
|
|
544
|
+
const parent = nodeInternals.get(node.parentNode);
|
|
545
|
+
const { x: parentX, y: parentY } = getNodePositionWithOrigin(parent, nodeOrigin).positionAbsolute;
|
|
546
|
+
currentExtent =
|
|
547
|
+
parent &&
|
|
548
|
+
isNumeric(parentX) &&
|
|
549
|
+
isNumeric(parentY) &&
|
|
550
|
+
isNumeric(parent.width) &&
|
|
551
|
+
isNumeric(parent.height)
|
|
552
|
+
? [
|
|
553
|
+
[
|
|
554
|
+
parentX + node.width * nodeOrigin[0],
|
|
555
|
+
parentY + node.height * nodeOrigin[1],
|
|
556
|
+
],
|
|
557
|
+
[
|
|
558
|
+
parentX +
|
|
559
|
+
parent.width -
|
|
560
|
+
node.width +
|
|
561
|
+
node.width * nodeOrigin[0],
|
|
562
|
+
parentY +
|
|
563
|
+
parent.height -
|
|
564
|
+
node.height +
|
|
565
|
+
node.height * nodeOrigin[1],
|
|
566
|
+
],
|
|
567
|
+
]
|
|
568
|
+
: currentExtent;
|
|
555
569
|
}
|
|
556
|
-
else
|
|
557
|
-
|
|
558
|
-
|
|
570
|
+
else {
|
|
571
|
+
onError?.('011');
|
|
572
|
+
currentExtent = nodeExtent;
|
|
559
573
|
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
574
|
+
}
|
|
575
|
+
else if (node.extent && node.parentNode) {
|
|
576
|
+
const parent = nodeInternals.get(node.parentNode);
|
|
577
|
+
const { x: parentX, y: parentY } = getNodePositionWithOrigin(parent, nodeOrigin).positionAbsolute;
|
|
578
|
+
currentExtent = [
|
|
579
|
+
[node.extent[0][0] + parentX, node.extent[0][1] + parentY],
|
|
580
|
+
[node.extent[1][0] + parentX, node.extent[1][1] + parentY],
|
|
581
|
+
];
|
|
582
|
+
}
|
|
583
|
+
let parentPosition = { x: 0, y: 0 };
|
|
584
|
+
if (node.parentNode) {
|
|
585
|
+
const parentNode = nodeInternals.get(node.parentNode);
|
|
586
|
+
parentPosition = getNodePositionWithOrigin(parentNode, nodeOrigin).positionAbsolute;
|
|
587
|
+
}
|
|
588
|
+
const positionAbsolute = currentExtent
|
|
589
|
+
? clampPosition(nextPosition, currentExtent)
|
|
590
|
+
: nextPosition;
|
|
565
591
|
return {
|
|
566
|
-
|
|
567
|
-
|
|
592
|
+
position: {
|
|
593
|
+
x: positionAbsolute.x - parentPosition.x,
|
|
594
|
+
y: positionAbsolute.y - parentPosition.y,
|
|
595
|
+
},
|
|
596
|
+
positionAbsolute,
|
|
568
597
|
};
|
|
569
598
|
};
|
|
570
|
-
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
y: 0,
|
|
579
|
-
});
|
|
580
|
-
const [dragBoxRect, setDragBoxRect] = useState({
|
|
581
|
-
width: 0,
|
|
582
|
-
height: 0,
|
|
583
|
-
x: 0,
|
|
584
|
-
y: 0,
|
|
585
|
-
});
|
|
586
|
-
const [selectionBoxRect, setSelectionBoxRect] = useState({
|
|
587
|
-
width: 0,
|
|
588
|
-
height: 0,
|
|
589
|
-
x: 0,
|
|
590
|
-
y: 0,
|
|
599
|
+
const getEventHandlerParams = ({ nodeId, dragItems, nodeInternals, }) => {
|
|
600
|
+
const extentedDragItems = dragItems.map((n) => {
|
|
601
|
+
const node = nodeInternals.get(n.id);
|
|
602
|
+
return {
|
|
603
|
+
...node,
|
|
604
|
+
position: n.position,
|
|
605
|
+
positionAbsolute: n.positionAbsolute,
|
|
606
|
+
};
|
|
591
607
|
});
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
width: 0,
|
|
628
|
-
height: 0,
|
|
629
|
-
x,
|
|
630
|
-
y,
|
|
631
|
-
});
|
|
632
|
-
setDragBoxStartPosition({
|
|
633
|
-
x,
|
|
634
|
-
y,
|
|
635
|
-
});
|
|
636
|
-
};
|
|
637
|
-
const onMouseMove = (event) => {
|
|
638
|
-
const { nodeInternals, transform, nodeOrigin, getNodes, onNodesChange } = store.getState();
|
|
639
|
-
// const hasDragBoxPosition = dragBoxRect.x > 0 && dragBoxRect.y > 0;
|
|
640
|
-
const hasDragBoxStartPosition = dragBoxStartPosition.x > 0 && dragBoxStartPosition.y > 0;
|
|
641
|
-
if (
|
|
642
|
-
// !hasDragBoxPosition ||
|
|
643
|
-
!hasDragBoxStartPosition ||
|
|
644
|
-
!containerBounds.current ||
|
|
645
|
-
!dragSelectionKeyPressed) {
|
|
608
|
+
return [
|
|
609
|
+
nodeId
|
|
610
|
+
? extentedDragItems.find((n) => n.id === nodeId)
|
|
611
|
+
: extentedDragItems[0],
|
|
612
|
+
extentedDragItems,
|
|
613
|
+
];
|
|
614
|
+
};
|
|
615
|
+
const hasSelector = (target, selector, nodeRef) => {
|
|
616
|
+
let current = target;
|
|
617
|
+
do {
|
|
618
|
+
if (current?.matches(selector))
|
|
619
|
+
return true;
|
|
620
|
+
if (current === nodeRef.current)
|
|
621
|
+
return false;
|
|
622
|
+
current = current.parentElement;
|
|
623
|
+
} while (current);
|
|
624
|
+
return false;
|
|
625
|
+
};
|
|
626
|
+
const hasChangedPosition = (beforePositions, currentPosition) => beforePositions.x !== currentPosition.x ||
|
|
627
|
+
beforePositions.y !== currentPosition.y;
|
|
628
|
+
|
|
629
|
+
const isDragItem = (node) => 'distance' in node;
|
|
630
|
+
function useDrag({ nodeRef, nodeId, isSelectable, noDragClassName, }) {
|
|
631
|
+
const store = useStoreApi();
|
|
632
|
+
const dragItems = useRef([]);
|
|
633
|
+
const containerBounds = useRef(null);
|
|
634
|
+
const mousePosition = useRef({ x: 0, y: 0 });
|
|
635
|
+
const lastPosition = useRef({ x: 0, y: 0 });
|
|
636
|
+
const dragEvent = useRef(null);
|
|
637
|
+
const autoPanStarted = useRef(false);
|
|
638
|
+
const autoPanId = useRef(0);
|
|
639
|
+
const [dragging, setDragging] = useState(false);
|
|
640
|
+
const getPointerPosition = useGetPointerPosition();
|
|
641
|
+
const updateNodePosition = (pointerPositions, dragEnd = false) => (dragItem) => {
|
|
642
|
+
if (!isDragItem(dragItem))
|
|
646
643
|
return;
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const rect = {
|
|
654
|
-
x: mousePos.x < startX ? mousePos.x : startX,
|
|
655
|
-
y: mousePos.y < startY ? mousePos.y : startY,
|
|
656
|
-
width: Math.abs(mousePos.x - startX),
|
|
657
|
-
height: Math.abs(mousePos.y - startY),
|
|
644
|
+
const { nodeInternals, nodeExtent, nodeOrigin, smoothStep, gridStep, onError, } = store.getState();
|
|
645
|
+
const { distance, width, height } = dragItem;
|
|
646
|
+
const { x, y, getStepPosition } = pointerPositions;
|
|
647
|
+
let nextPosition = {
|
|
648
|
+
x: x - distance.x,
|
|
649
|
+
y: y - distance.y,
|
|
658
650
|
};
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
if (changes.length) {
|
|
668
|
-
onNodesChange?.(changes);
|
|
651
|
+
if (gridStep && getStepPosition) {
|
|
652
|
+
const nodeSize = { width, height };
|
|
653
|
+
const stepPosition = getStepPosition({
|
|
654
|
+
position: nextPosition,
|
|
655
|
+
nodeSize,
|
|
656
|
+
});
|
|
657
|
+
if (!smoothStep || (smoothStep && dragEnd)) {
|
|
658
|
+
nextPosition = stepPosition;
|
|
669
659
|
}
|
|
670
660
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
if (event.button !== 0) {
|
|
661
|
+
const updatedPosition = calcNextPosition(dragItem, nextPosition, nodeInternals, nodeExtent, nodeOrigin, onError);
|
|
662
|
+
const hasChange = hasChangedPosition(dragItem.position, updatedPosition.position);
|
|
663
|
+
if (!hasChange)
|
|
675
664
|
return;
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
resetDragBox();
|
|
679
|
-
};
|
|
680
|
-
const onMouseLeave = () => {
|
|
681
|
-
setSelectionBoxActive(prevSelectedNodesCount.current > 0);
|
|
682
|
-
resetDragBox();
|
|
665
|
+
dragItem.position = updatedPosition.position;
|
|
666
|
+
dragItem.positionAbsolute = updatedPosition.positionAbsolute;
|
|
683
667
|
};
|
|
684
|
-
|
|
685
|
-
|
|
668
|
+
useEffect(() => {
|
|
669
|
+
if (nodeRef?.current) {
|
|
670
|
+
const selection = select(nodeRef.current);
|
|
671
|
+
const updateNodes = (pointerPosition) => {
|
|
672
|
+
const { nodeInternals, onNodeDrag, updateNodesPosition } = store.getState();
|
|
673
|
+
const { x, y } = pointerPosition;
|
|
674
|
+
lastPosition.current = { x, y };
|
|
675
|
+
updateNodesPosition(dragItems.current, true, updateNodePosition(pointerPosition));
|
|
676
|
+
setDragging(true);
|
|
677
|
+
if (onNodeDrag && dragEvent.current) {
|
|
678
|
+
const [currentNode, nodes] = getEventHandlerParams({
|
|
679
|
+
nodeId,
|
|
680
|
+
dragItems: dragItems.current,
|
|
681
|
+
nodeInternals,
|
|
682
|
+
});
|
|
683
|
+
onNodeDrag(dragEvent.current, currentNode, nodes);
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
const autoPan = () => {
|
|
687
|
+
if (!containerBounds.current) {
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
const [xMovement, yMovement] = calcAutoPanPosition(mousePosition.current, containerBounds.current);
|
|
691
|
+
if (xMovement !== 0 || yMovement !== 0) {
|
|
692
|
+
const { transform, panBy } = store.getState();
|
|
693
|
+
lastPosition.current.x -= xMovement / transform[2];
|
|
694
|
+
lastPosition.current.y -= yMovement / transform[2];
|
|
695
|
+
updateNodes(lastPosition.current);
|
|
696
|
+
panBy({ x: xMovement, y: yMovement });
|
|
697
|
+
}
|
|
698
|
+
autoPanId.current = requestAnimationFrame(autoPan);
|
|
699
|
+
};
|
|
700
|
+
const dragHandle = drag()
|
|
701
|
+
.on('start', (e) => {
|
|
702
|
+
const { nodeInternals, nodesDraggable, domNode, onNodeDragStart, } = store.getState();
|
|
703
|
+
if (nodeId) {
|
|
704
|
+
handleNodeClick({
|
|
705
|
+
id: nodeId,
|
|
706
|
+
store,
|
|
707
|
+
nodeRef: nodeRef,
|
|
708
|
+
isSelectable,
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
const pointerPosition = getPointerPosition(e);
|
|
712
|
+
dragItems.current = getDragItems(nodeInternals, nodesDraggable, pointerPosition, nodeId);
|
|
713
|
+
if (onNodeDragStart && dragItems.current) {
|
|
714
|
+
const [currentNode, nodes] = getEventHandlerParams({
|
|
715
|
+
nodeId,
|
|
716
|
+
dragItems: dragItems.current,
|
|
717
|
+
nodeInternals,
|
|
718
|
+
});
|
|
719
|
+
onNodeDragStart(e.sourceEvent, currentNode, nodes);
|
|
720
|
+
}
|
|
721
|
+
containerBounds.current =
|
|
722
|
+
domNode?.getBoundingClientRect() || null;
|
|
723
|
+
mousePosition.current = getEventPosition(e.sourceEvent, containerBounds.current);
|
|
724
|
+
})
|
|
725
|
+
.on('drag', (e) => {
|
|
726
|
+
const pointerPosition = getPointerPosition(e);
|
|
727
|
+
const { autoPanOnNodeDrag } = store.getState();
|
|
728
|
+
if (!autoPanStarted.current && autoPanOnNodeDrag) {
|
|
729
|
+
autoPanStarted.current = true;
|
|
730
|
+
autoPan();
|
|
731
|
+
}
|
|
732
|
+
const isChanged = hasChangedPosition(lastPosition.current, pointerPosition.getStepPosition());
|
|
733
|
+
if (isChanged && dragItems.current) {
|
|
734
|
+
dragEvent.current = e.sourceEvent;
|
|
735
|
+
mousePosition.current = getEventPosition(e.sourceEvent, containerBounds.current);
|
|
736
|
+
updateNodes(pointerPosition);
|
|
737
|
+
}
|
|
738
|
+
})
|
|
739
|
+
.on('end', (event) => {
|
|
740
|
+
setDragging(false);
|
|
741
|
+
autoPanStarted.current = false;
|
|
742
|
+
cancelAnimationFrame(autoPanId.current);
|
|
743
|
+
if (dragItems.current) {
|
|
744
|
+
const { nodeInternals, smoothStep, gridStep, updateNodesPosition, onNodeDragEnd, } = store.getState();
|
|
745
|
+
const isSmoothStep = !!gridStep && smoothStep;
|
|
746
|
+
if (isSmoothStep) {
|
|
747
|
+
const pointerPosition = getPointerPosition(event);
|
|
748
|
+
updateNodesPosition(dragItems.current, false, updateNodePosition(pointerPosition, true));
|
|
749
|
+
}
|
|
750
|
+
else {
|
|
751
|
+
updateNodesPosition(dragItems.current, false);
|
|
752
|
+
}
|
|
753
|
+
if (onNodeDragEnd) {
|
|
754
|
+
const [currentNode, nodes] = getEventHandlerParams({
|
|
755
|
+
nodeId,
|
|
756
|
+
dragItems: dragItems.current,
|
|
757
|
+
nodeInternals,
|
|
758
|
+
});
|
|
759
|
+
onNodeDragEnd(event.sourceEvent, currentNode, nodes);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
})
|
|
763
|
+
.filter((event) => {
|
|
764
|
+
const target = event.target;
|
|
765
|
+
const isDraggable = !event.button &&
|
|
766
|
+
(!noDragClassName ||
|
|
767
|
+
!hasSelector(target, `.${noDragClassName}`, nodeRef));
|
|
768
|
+
return isDraggable;
|
|
769
|
+
});
|
|
770
|
+
selection.call(dragHandle);
|
|
771
|
+
return () => {
|
|
772
|
+
selection.on('.drag', null);
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
}, [
|
|
776
|
+
store,
|
|
777
|
+
nodeRef,
|
|
778
|
+
nodeId,
|
|
779
|
+
isSelectable,
|
|
780
|
+
noDragClassName,
|
|
781
|
+
getPointerPosition,
|
|
782
|
+
]);
|
|
783
|
+
return dragging;
|
|
686
784
|
}
|
|
687
|
-
DragSelection.displayName = 'DragSelection';
|
|
688
785
|
|
|
689
|
-
|
|
690
|
-
const
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
786
|
+
function SelectionBox({ rect, transform }) {
|
|
787
|
+
const nodeRef = useRef(null);
|
|
788
|
+
useDrag({ nodeRef });
|
|
789
|
+
const { width, height, x, y } = rect;
|
|
790
|
+
return (jsx("div", { className: cc([
|
|
791
|
+
'react-diagram__selection-box',
|
|
792
|
+
'react-diagram__container',
|
|
793
|
+
]), style: {
|
|
794
|
+
transform,
|
|
795
|
+
}, children: jsx("div", { ref: nodeRef, className: "react-diagram__selection-box-rect", tabIndex: -1, style: {
|
|
796
|
+
width,
|
|
797
|
+
height,
|
|
798
|
+
top: y,
|
|
799
|
+
left: x,
|
|
800
|
+
} }) }));
|
|
801
|
+
}
|
|
802
|
+
var SelectionBox$1 = memo(SelectionBox);
|
|
803
|
+
|
|
804
|
+
const handleParentExpand = (res, updateItem) => {
|
|
805
|
+
const parent = res.find((e) => e.id === updateItem.parentNode);
|
|
806
|
+
if (parent) {
|
|
807
|
+
const extendWidth = updateItem.position.x + updateItem.width - parent.width;
|
|
808
|
+
const extendHeight = updateItem.position.y + updateItem.height - parent.height;
|
|
809
|
+
if (extendWidth > 0 ||
|
|
810
|
+
extendHeight > 0 ||
|
|
811
|
+
updateItem.position.x < 0 ||
|
|
812
|
+
updateItem.position.y < 0) {
|
|
813
|
+
parent.style = { ...parent.style } || {};
|
|
814
|
+
parent.style.width = parent.style.width ?? parent.width;
|
|
815
|
+
parent.style.height = parent.style.height ?? parent.height;
|
|
816
|
+
if (extendWidth > 0) {
|
|
817
|
+
parent.style.width += extendWidth;
|
|
818
|
+
}
|
|
819
|
+
if (extendHeight > 0) {
|
|
820
|
+
parent.style.height += extendHeight;
|
|
821
|
+
}
|
|
822
|
+
if (updateItem.position.x < 0) {
|
|
823
|
+
const xDiff = Math.abs(updateItem.position.x);
|
|
824
|
+
parent.position.x = parent.position.x - xDiff;
|
|
825
|
+
parent.style.width += xDiff;
|
|
826
|
+
updateItem.position.x = 0;
|
|
827
|
+
}
|
|
828
|
+
if (updateItem.position.y < 0) {
|
|
829
|
+
const yDiff = Math.abs(updateItem.position.y);
|
|
830
|
+
parent.position.y = parent.position.y - yDiff;
|
|
831
|
+
parent.style.height += yDiff;
|
|
832
|
+
updateItem.position.y = 0;
|
|
833
|
+
}
|
|
834
|
+
parent.width = parent.style.width;
|
|
835
|
+
parent.height = parent.style.height;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
696
838
|
};
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
839
|
+
const applyChanges = (changes, elements) => {
|
|
840
|
+
// we need this hack to handle the setNodes and setEdges function of the useReactDiagram hook for controlled flows
|
|
841
|
+
if (changes.some((c) => c.type === 'reset')) {
|
|
842
|
+
return changes.filter((c) => c.type === 'reset').map((c) => c.item);
|
|
843
|
+
}
|
|
844
|
+
const initElements = changes
|
|
845
|
+
.filter((c) => c.type === 'add')
|
|
846
|
+
.map((c) => c.item);
|
|
847
|
+
return elements.reduce((res, item) => {
|
|
848
|
+
const currentChanges = changes.filter((c) => c.id === item.id);
|
|
849
|
+
if (currentChanges.length === 0) {
|
|
850
|
+
res.push(item);
|
|
851
|
+
return res;
|
|
704
852
|
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
853
|
+
const updateItem = { ...item };
|
|
854
|
+
for (const currentChange of currentChanges) {
|
|
855
|
+
if (currentChange) {
|
|
856
|
+
switch (currentChange.type) {
|
|
857
|
+
case 'select': {
|
|
858
|
+
updateItem.selected = currentChange.selected;
|
|
859
|
+
break;
|
|
860
|
+
}
|
|
861
|
+
case 'position': {
|
|
862
|
+
if (typeof currentChange.position !== 'undefined') {
|
|
863
|
+
updateItem.position = currentChange.position;
|
|
864
|
+
}
|
|
865
|
+
if (typeof currentChange.positionAbsolute !== 'undefined') {
|
|
866
|
+
updateItem.positionAbsolute =
|
|
867
|
+
currentChange.positionAbsolute;
|
|
868
|
+
}
|
|
869
|
+
if (typeof currentChange.dragging !== 'undefined') {
|
|
870
|
+
updateItem.dragging = currentChange.dragging;
|
|
871
|
+
}
|
|
872
|
+
if (updateItem.expandParent) {
|
|
873
|
+
handleParentExpand(res, updateItem);
|
|
874
|
+
}
|
|
875
|
+
break;
|
|
876
|
+
}
|
|
877
|
+
case 'dimensions': {
|
|
878
|
+
if (typeof currentChange.dimensions !== 'undefined') {
|
|
879
|
+
updateItem.width = currentChange.dimensions.width;
|
|
880
|
+
updateItem.height = currentChange.dimensions.height;
|
|
881
|
+
}
|
|
882
|
+
if (typeof currentChange.updateStyle !== 'undefined') {
|
|
883
|
+
updateItem.style = {
|
|
884
|
+
...(updateItem.style || {}),
|
|
885
|
+
...currentChange.dimensions,
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
if (typeof currentChange.resizing === 'boolean') {
|
|
889
|
+
updateItem.resizing = currentChange.resizing;
|
|
890
|
+
}
|
|
891
|
+
if (updateItem.expandParent) {
|
|
892
|
+
handleParentExpand(res, updateItem);
|
|
893
|
+
}
|
|
894
|
+
break;
|
|
895
|
+
}
|
|
896
|
+
case 'remove': {
|
|
897
|
+
return res;
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
res.push(updateItem);
|
|
903
|
+
return res;
|
|
904
|
+
}, initElements);
|
|
905
|
+
};
|
|
906
|
+
function applyNodeChanges(changes, nodes) {
|
|
907
|
+
return applyChanges(changes, nodes);
|
|
718
908
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
function useVisibleNodes() {
|
|
723
|
-
const nodes = useStore(useCallback((s) => s.getNodes(), []));
|
|
724
|
-
return nodes;
|
|
909
|
+
function applyEdgeChanges(changes, edges) {
|
|
910
|
+
return applyChanges(changes, edges);
|
|
725
911
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
Position["Top"] = "top";
|
|
731
|
-
Position["Right"] = "right";
|
|
732
|
-
Position["Bottom"] = "bottom";
|
|
733
|
-
})(Position || (Position = {}));
|
|
734
|
-
|
|
735
|
-
var MarkerType;
|
|
736
|
-
(function (MarkerType) {
|
|
737
|
-
MarkerType["Arrow"] = "arrow";
|
|
738
|
-
})(MarkerType || (MarkerType = {}));
|
|
739
|
-
|
|
740
|
-
const selector$3 = (s) => ({
|
|
741
|
-
nodesDraggable: s.nodesDraggable,
|
|
742
|
-
elementsSelectable: s.elementsSelectable,
|
|
743
|
-
updateNodeDimensions: s.updateNodeDimensions,
|
|
744
|
-
onError: s.onError,
|
|
912
|
+
const createSelectionChange = (id, selected) => ({
|
|
913
|
+
id,
|
|
914
|
+
type: 'select',
|
|
915
|
+
selected,
|
|
745
916
|
});
|
|
746
|
-
function
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
return null;
|
|
917
|
+
function getSelectionChanges(items, selectedIds) {
|
|
918
|
+
return items.reduce((res, item) => {
|
|
919
|
+
const willBeSelected = selectedIds.includes(item.id);
|
|
920
|
+
if (!item.selected && willBeSelected) {
|
|
921
|
+
item.selected = true;
|
|
922
|
+
res.push(createSelectionChange(item.id, true));
|
|
753
923
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
}));
|
|
760
|
-
updateNodeDimensions(updates);
|
|
761
|
-
});
|
|
762
|
-
resizeObserverRef.current = observer;
|
|
763
|
-
return observer;
|
|
764
|
-
}, []);
|
|
765
|
-
useEffect(() => () => {
|
|
766
|
-
resizeObserverRef?.current?.disconnect();
|
|
924
|
+
else if (item.selected && !willBeSelected) {
|
|
925
|
+
item.selected = false;
|
|
926
|
+
res.push(createSelectionChange(item.id, false));
|
|
927
|
+
}
|
|
928
|
+
return res;
|
|
767
929
|
}, []);
|
|
768
|
-
return (jsx("div", { className: "react-diagram__nodes react-diagram__container", children: nodes.map((node) => {
|
|
769
|
-
const { data, type,
|
|
770
|
-
// elProps
|
|
771
|
-
id, className, style, ariaLabel, positionAbsolute, hidden, selected, selectable, draggable, } = node;
|
|
772
|
-
let nodeType = type || 'default';
|
|
773
|
-
if (!nodeTypes[nodeType]) {
|
|
774
|
-
onError?.('010', nodeType);
|
|
775
|
-
nodeType = 'default';
|
|
776
|
-
}
|
|
777
|
-
const NodeComponent = (nodeTypes[nodeType] ||
|
|
778
|
-
nodeTypes.default);
|
|
779
|
-
const isDraggable = !!(draggable ||
|
|
780
|
-
(nodesDraggable && typeof draggable === 'undefined'));
|
|
781
|
-
const isSelectable = !!(selectable ||
|
|
782
|
-
(elementsSelectable && typeof selectable === 'undefined'));
|
|
783
|
-
const elProps = {
|
|
784
|
-
id,
|
|
785
|
-
className,
|
|
786
|
-
style: {
|
|
787
|
-
...style,
|
|
788
|
-
width: node.width,
|
|
789
|
-
height: node.height,
|
|
790
|
-
},
|
|
791
|
-
ariaLabel,
|
|
792
|
-
};
|
|
793
|
-
const events = {
|
|
794
|
-
onClick: onNodeClick,
|
|
795
|
-
onMouseEnter: onNodeMouseEnter,
|
|
796
|
-
onMouseMove: onNodeMouseMove,
|
|
797
|
-
onMouseLeave: onNodeMouseLeave,
|
|
798
|
-
onContextMenu: onNodeContextMenu,
|
|
799
|
-
onDoubleClick: onNodeDoubleClick,
|
|
800
|
-
};
|
|
801
|
-
const position = {
|
|
802
|
-
positionX: positionAbsolute?.x || 0,
|
|
803
|
-
positionY: positionAbsolute?.y || 0,
|
|
804
|
-
sourcePosition: Position.Bottom,
|
|
805
|
-
targetPosition: Position.Top,
|
|
806
|
-
};
|
|
807
|
-
const booleanProps = {
|
|
808
|
-
selected: !!selected,
|
|
809
|
-
isSelectable,
|
|
810
|
-
isDraggable,
|
|
811
|
-
hidden,
|
|
812
|
-
isParent: !!node[internalsSymbol]?.isParent,
|
|
813
|
-
initialized: !!node.width && !!node.height,
|
|
814
|
-
};
|
|
815
|
-
return (jsx(NodeComponent, { ...props, ...elProps, ...position, ...events, ...booleanProps, zIndex: node[internalsSymbol]?.z ?? 0, type: nodeType, data: data, resizeObserver: resizeObserver }, id));
|
|
816
|
-
}) }));
|
|
817
930
|
}
|
|
818
|
-
NodeRenderer.displayName = 'NodeRenderer';
|
|
819
|
-
var NodeRenderer$1 = memo(NodeRenderer);
|
|
820
931
|
|
|
821
|
-
const
|
|
822
|
-
const
|
|
823
|
-
|
|
932
|
+
const selector$6 = (s) => {
|
|
933
|
+
const { elementsSelectable, transform, selectionBoxActive, getNodes } = s;
|
|
934
|
+
const selectedNodes = getNodes().filter((n) => n.selected);
|
|
935
|
+
return {
|
|
936
|
+
elementsSelectable,
|
|
937
|
+
selectionBoxRect: getRectOfNodes(selectedNodes, s.nodeOrigin),
|
|
938
|
+
transformString: `translate(${transform[0]}px,${transform[1]}px) scale(${transform[2]})`,
|
|
939
|
+
selectionBoxActive,
|
|
940
|
+
};
|
|
824
941
|
};
|
|
825
|
-
function
|
|
942
|
+
function DragSelection({ children, dragSelectionKeyPressed, }) {
|
|
943
|
+
const store = useStoreApi();
|
|
944
|
+
const dragSelection = useRef(null);
|
|
945
|
+
const prevSelectedNodesCount = useRef(0);
|
|
946
|
+
const containerBounds = useRef();
|
|
947
|
+
const { elementsSelectable, selectionBoxRect, transformString, selectionBoxActive, } = useStore(selector$6, shallow);
|
|
948
|
+
const [dragBoxStartPosition, setDragBoxStartPosition] = useState({
|
|
949
|
+
x: 0,
|
|
950
|
+
y: 0,
|
|
951
|
+
});
|
|
952
|
+
const [dragBoxRect, setDragBoxRect] = useState({
|
|
953
|
+
width: 0,
|
|
954
|
+
height: 0,
|
|
955
|
+
x: 0,
|
|
956
|
+
y: 0,
|
|
957
|
+
});
|
|
958
|
+
const [dragBoxActive, setDragBoxActive] = useState(false);
|
|
959
|
+
const resetDragBox = () => {
|
|
960
|
+
setDragBoxStartPosition({
|
|
961
|
+
x: 0,
|
|
962
|
+
y: 0,
|
|
963
|
+
});
|
|
964
|
+
setDragBoxRect({
|
|
965
|
+
width: 0,
|
|
966
|
+
height: 0,
|
|
967
|
+
x: 0,
|
|
968
|
+
y: 0,
|
|
969
|
+
});
|
|
970
|
+
setDragBoxActive(false);
|
|
971
|
+
};
|
|
972
|
+
const onClick = (e) => {
|
|
973
|
+
if (e.target === dragSelection.current) {
|
|
974
|
+
store.getState().resetSelectedElements();
|
|
975
|
+
store.setState({
|
|
976
|
+
selectionBoxActive: false,
|
|
977
|
+
});
|
|
978
|
+
setDragBoxActive(false);
|
|
979
|
+
}
|
|
980
|
+
};
|
|
981
|
+
const onMouseDown = (event) => {
|
|
982
|
+
const { resetSelectedElements, domNode } = store.getState();
|
|
983
|
+
containerBounds.current = domNode?.getBoundingClientRect();
|
|
984
|
+
if (!elementsSelectable ||
|
|
985
|
+
event.button !== 0 ||
|
|
986
|
+
event.target !== dragSelection.current ||
|
|
987
|
+
!containerBounds.current ||
|
|
988
|
+
!dragSelectionKeyPressed) {
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
const { x, y } = getEventPosition(event, containerBounds.current);
|
|
992
|
+
resetSelectedElements();
|
|
993
|
+
setDragBoxRect({
|
|
994
|
+
width: 0,
|
|
995
|
+
height: 0,
|
|
996
|
+
x,
|
|
997
|
+
y,
|
|
998
|
+
});
|
|
999
|
+
setDragBoxStartPosition({
|
|
1000
|
+
x,
|
|
1001
|
+
y,
|
|
1002
|
+
});
|
|
1003
|
+
};
|
|
1004
|
+
const onMouseMove = (event) => {
|
|
1005
|
+
const { nodeInternals, transform, nodeOrigin, getNodes, onNodesChange } = store.getState();
|
|
1006
|
+
const hasDragBoxStartPosition = dragBoxStartPosition.x > 0 && dragBoxStartPosition.y > 0;
|
|
1007
|
+
if (
|
|
1008
|
+
// !hasDragBoxPosition ||
|
|
1009
|
+
!hasDragBoxStartPosition ||
|
|
1010
|
+
!containerBounds.current ||
|
|
1011
|
+
!dragSelectionKeyPressed) {
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
store.setState({
|
|
1015
|
+
selectionBoxActive: false,
|
|
1016
|
+
});
|
|
1017
|
+
setDragBoxActive(true);
|
|
1018
|
+
const mousePos = getEventPosition(event, containerBounds.current);
|
|
1019
|
+
const startX = dragBoxStartPosition.x ?? 0;
|
|
1020
|
+
const startY = dragBoxStartPosition.y ?? 0;
|
|
1021
|
+
const rect = {
|
|
1022
|
+
x: mousePos.x < startX ? mousePos.x : startX,
|
|
1023
|
+
y: mousePos.y < startY ? mousePos.y : startY,
|
|
1024
|
+
width: Math.abs(mousePos.x - startX),
|
|
1025
|
+
height: Math.abs(mousePos.y - startY),
|
|
1026
|
+
};
|
|
1027
|
+
const nodes = getNodes();
|
|
1028
|
+
const selectedNodes = getNodesInside(nodeInternals, rect, transform, false, true, nodeOrigin);
|
|
1029
|
+
const selectedNodeIds = selectedNodes.map((n) => n.id);
|
|
1030
|
+
if (prevSelectedNodesCount.current !== selectedNodeIds.length) {
|
|
1031
|
+
prevSelectedNodesCount.current = selectedNodeIds.length;
|
|
1032
|
+
const changes = getSelectionChanges(nodes, selectedNodeIds);
|
|
1033
|
+
if (changes.length) {
|
|
1034
|
+
onNodesChange?.(changes);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
setDragBoxRect(rect);
|
|
1038
|
+
};
|
|
1039
|
+
const onMouseUp = (event) => {
|
|
1040
|
+
if (event.button !== 0) {
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
store.setState({
|
|
1044
|
+
selectionBoxActive: prevSelectedNodesCount.current > 0,
|
|
1045
|
+
});
|
|
1046
|
+
resetDragBox();
|
|
1047
|
+
};
|
|
1048
|
+
const onMouseLeave = () => {
|
|
1049
|
+
store.setState({
|
|
1050
|
+
selectionBoxActive: prevSelectedNodesCount.current > 0,
|
|
1051
|
+
});
|
|
1052
|
+
resetDragBox();
|
|
1053
|
+
};
|
|
1054
|
+
const isPossibleDragSelection = elementsSelectable && dragSelectionKeyPressed;
|
|
1055
|
+
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 }))] }));
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
const selector$5 = (s) => {
|
|
1059
|
+
const { minZoom, maxZoom, translateExtent } = s;
|
|
1060
|
+
return {
|
|
1061
|
+
minZoom,
|
|
1062
|
+
maxZoom,
|
|
1063
|
+
translateExtent,
|
|
1064
|
+
};
|
|
1065
|
+
};
|
|
1066
|
+
function DiagramRenderer({ children, multiSelectionKeyCode, noPanClassName, panning, defaultViewport, onMove, onMoveStart, onMoveEnd, }) {
|
|
1067
|
+
const { minZoom, maxZoom, translateExtent } = useStore(selector$5);
|
|
1068
|
+
const [dragSelectionKeyPressed, setDragSelectionKeyPressed] = useState(false);
|
|
1069
|
+
useGlobalKeyHandler(multiSelectionKeyCode);
|
|
1070
|
+
const handleKeyDown = (e) => {
|
|
1071
|
+
if (e.key === 'Shift') {
|
|
1072
|
+
setDragSelectionKeyPressed(true);
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1075
|
+
const handleKeyUp = () => {
|
|
1076
|
+
setDragSelectionKeyPressed(false);
|
|
1077
|
+
};
|
|
1078
|
+
useEffect(() => {
|
|
1079
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
1080
|
+
document.addEventListener('keyup', handleKeyUp);
|
|
1081
|
+
return () => {
|
|
1082
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
1083
|
+
document.removeEventListener('keyup', handleKeyUp);
|
|
1084
|
+
};
|
|
1085
|
+
}, []);
|
|
1086
|
+
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 }) }) }));
|
|
1087
|
+
}
|
|
1088
|
+
DiagramRenderer.displayName = 'DiagramRenderer';
|
|
1089
|
+
var DiagramRenderer$1 = memo(DiagramRenderer);
|
|
1090
|
+
|
|
1091
|
+
function useVisibleNodes() {
|
|
1092
|
+
const nodes = useStore(useCallback((s) => s.getNodes(), []));
|
|
1093
|
+
return nodes;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
var Position;
|
|
1097
|
+
(function (Position) {
|
|
1098
|
+
Position["Left"] = "left";
|
|
1099
|
+
Position["Top"] = "top";
|
|
1100
|
+
Position["Right"] = "right";
|
|
1101
|
+
Position["Bottom"] = "bottom";
|
|
1102
|
+
})(Position || (Position = {}));
|
|
1103
|
+
|
|
1104
|
+
var MarkerType;
|
|
1105
|
+
(function (MarkerType) {
|
|
1106
|
+
MarkerType["Arrow"] = "arrow";
|
|
1107
|
+
})(MarkerType || (MarkerType = {}));
|
|
1108
|
+
|
|
1109
|
+
const selector$4 = (s) => ({
|
|
1110
|
+
nodesDraggable: s.nodesDraggable,
|
|
1111
|
+
elementsSelectable: s.elementsSelectable,
|
|
1112
|
+
updateNodeDimensions: s.updateNodeDimensions,
|
|
1113
|
+
onError: s.onError,
|
|
1114
|
+
});
|
|
1115
|
+
function NodeRenderer({ nodeTypes, onNodeClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onNodeDoubleClick, ...props }) {
|
|
1116
|
+
const { nodesDraggable, elementsSelectable, updateNodeDimensions, onError } = useStore(selector$4, shallow);
|
|
1117
|
+
const nodes = useVisibleNodes();
|
|
1118
|
+
const resizeObserverRef = useRef();
|
|
1119
|
+
const resizeObserver = useMemo(() => {
|
|
1120
|
+
if (typeof ResizeObserver === 'undefined') {
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
const observer = new ResizeObserver((entries) => {
|
|
1124
|
+
const updates = entries.map((entry) => ({
|
|
1125
|
+
id: entry.target.getAttribute('data-id'),
|
|
1126
|
+
nodeElement: entry.target,
|
|
1127
|
+
forceUpdate: true,
|
|
1128
|
+
}));
|
|
1129
|
+
updateNodeDimensions(updates);
|
|
1130
|
+
});
|
|
1131
|
+
resizeObserverRef.current = observer;
|
|
1132
|
+
return observer;
|
|
1133
|
+
}, []);
|
|
1134
|
+
useEffect(() => () => {
|
|
1135
|
+
resizeObserverRef?.current?.disconnect();
|
|
1136
|
+
}, []);
|
|
1137
|
+
return (jsx("div", { className: "react-diagram__nodes react-diagram__container", children: nodes.map((node) => {
|
|
1138
|
+
const { data, type,
|
|
1139
|
+
// elProps
|
|
1140
|
+
id, className, style, ariaLabel, positionAbsolute, hidden, selected, selectable, draggable, } = node;
|
|
1141
|
+
let nodeType = type || 'default';
|
|
1142
|
+
if (!nodeTypes[nodeType]) {
|
|
1143
|
+
onError?.('010', nodeType);
|
|
1144
|
+
nodeType = 'default';
|
|
1145
|
+
}
|
|
1146
|
+
const NodeComponent = (nodeTypes[nodeType] ||
|
|
1147
|
+
nodeTypes.default);
|
|
1148
|
+
const isDraggable = !!(draggable ||
|
|
1149
|
+
(nodesDraggable && typeof draggable === 'undefined'));
|
|
1150
|
+
const isSelectable = !!(selectable ||
|
|
1151
|
+
(elementsSelectable && typeof selectable === 'undefined'));
|
|
1152
|
+
const elProps = {
|
|
1153
|
+
id,
|
|
1154
|
+
className,
|
|
1155
|
+
style: {
|
|
1156
|
+
...style,
|
|
1157
|
+
width: node.width,
|
|
1158
|
+
height: node.height,
|
|
1159
|
+
},
|
|
1160
|
+
ariaLabel,
|
|
1161
|
+
};
|
|
1162
|
+
const events = {
|
|
1163
|
+
onClick: onNodeClick,
|
|
1164
|
+
onMouseEnter: onNodeMouseEnter,
|
|
1165
|
+
onMouseMove: onNodeMouseMove,
|
|
1166
|
+
onMouseLeave: onNodeMouseLeave,
|
|
1167
|
+
onContextMenu: onNodeContextMenu,
|
|
1168
|
+
onDoubleClick: onNodeDoubleClick,
|
|
1169
|
+
};
|
|
1170
|
+
const position = {
|
|
1171
|
+
positionX: positionAbsolute?.x || 0,
|
|
1172
|
+
positionY: positionAbsolute?.y || 0,
|
|
1173
|
+
sourcePosition: Position.Bottom,
|
|
1174
|
+
targetPosition: Position.Top,
|
|
1175
|
+
};
|
|
1176
|
+
const booleanProps = {
|
|
1177
|
+
selected: !!selected,
|
|
1178
|
+
isSelectable,
|
|
1179
|
+
isDraggable,
|
|
1180
|
+
hidden,
|
|
1181
|
+
isParent: !!node[internalsSymbol]?.isParent,
|
|
1182
|
+
initialized: !!node.width && !!node.height,
|
|
1183
|
+
};
|
|
1184
|
+
return (jsx(NodeComponent, { ...props, ...elProps, ...position, ...events, ...booleanProps, zIndex: node[internalsSymbol]?.z ?? 0, type: nodeType, data: data, resizeObserver: resizeObserver }, id));
|
|
1185
|
+
}) }));
|
|
1186
|
+
}
|
|
1187
|
+
NodeRenderer.displayName = 'NodeRenderer';
|
|
1188
|
+
var NodeRenderer$1 = memo(NodeRenderer);
|
|
1189
|
+
|
|
1190
|
+
const ArrowSymbol = ({ color = 'none', strokeWidth = 1 }) => (jsx("polyline", { stroke: color, strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: strokeWidth, fill: color, points: "-5,-4 0,0 -5,4 -5,-4" }));
|
|
1191
|
+
const MarkerSymbols = {
|
|
1192
|
+
[MarkerType.Arrow]: ArrowSymbol,
|
|
1193
|
+
};
|
|
1194
|
+
function useMarkerSymbol(type) {
|
|
826
1195
|
const store = useStoreApi();
|
|
827
1196
|
const symbol = useMemo(() => {
|
|
828
1197
|
const symbolExists = Object.prototype.hasOwnProperty.call(MarkerSymbols, type);
|
|
@@ -1308,855 +1677,512 @@ const handlePointerDown = ({ isAnchor = false, event, nodeId, portType, getState
|
|
|
1308
1677
|
doc.addEventListener('touchend', onPointerUp);
|
|
1309
1678
|
};
|
|
1310
1679
|
|
|
1311
|
-
const portPositionX = (x, shift, position) => {
|
|
1312
|
-
if (position === Position.Left)
|
|
1313
|
-
return x - shift;
|
|
1314
|
-
if (position === Position.Right)
|
|
1315
|
-
return x + shift;
|
|
1316
|
-
return x;
|
|
1317
|
-
};
|
|
1318
|
-
const portPositionY = (y, shift, position) => {
|
|
1319
|
-
if (position === Position.Top)
|
|
1320
|
-
return y - shift;
|
|
1321
|
-
if (position === Position.Bottom)
|
|
1322
|
-
return y + shift;
|
|
1323
|
-
return y;
|
|
1324
|
-
};
|
|
1325
|
-
const EdgeUpdaterClassName = 'react-diagram__edge-updater';
|
|
1326
|
-
function Anchor({ position, centerX, centerY, radius = 10, onMouseDown,
|
|
1327
|
-
// onMouseEnter,
|
|
1328
|
-
// onMouseOut,
|
|
1329
|
-
type, }) {
|
|
1330
|
-
return (jsx("circle", { className: cc([
|
|
1331
|
-
EdgeUpdaterClassName,
|
|
1332
|
-
`${EdgeUpdaterClassName}-${type}`,
|
|
1333
|
-
]), cx: portPositionX(centerX, radius, position), cy: portPositionY(centerY, radius, position), r: radius, stroke: "transparent", fill: "transparent", onMouseDown: onMouseDown }));
|
|
1334
|
-
}
|
|
1335
|
-
|
|
1336
|
-
function getMouseHandler$1(id, getState, handler) {
|
|
1337
|
-
return handler === undefined
|
|
1338
|
-
? handler
|
|
1339
|
-
: (event) => {
|
|
1340
|
-
const edge = getState().edges.find((e) => e.id === id);
|
|
1341
|
-
if (edge) {
|
|
1342
|
-
handler(event, { ...edge });
|
|
1343
|
-
}
|
|
1344
|
-
};
|
|
1345
|
-
}
|
|
1346
|
-
const wrapEdge = (EdgeComponent) => {
|
|
1347
|
-
const EdgeWrapper = (props) => {
|
|
1348
|
-
const { id, className, style, type, data, rfId, ariaLabel,
|
|
1349
|
-
// sourceAndTargetIds
|
|
1350
|
-
source, sourcePort, target, targetPort,
|
|
1351
|
-
// marker
|
|
1352
|
-
markerEnd, markerStart,
|
|
1353
|
-
// labelProps
|
|
1354
|
-
label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius,
|
|
1355
|
-
// AnchorProps
|
|
1356
|
-
edgeUpdaterRadius,
|
|
1357
|
-
// position
|
|
1358
|
-
sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, selected, elementsSelectable, hidden, isFocusable, onClick, onDoubleClick, onContextMenu, onMouseEnter, onMouseMove, onMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, } = props;
|
|
1359
|
-
const position = {
|
|
1360
|
-
sourceX,
|
|
1361
|
-
sourceY,
|
|
1362
|
-
targetX,
|
|
1363
|
-
targetY,
|
|
1364
|
-
sourcePosition,
|
|
1365
|
-
targetPosition,
|
|
1366
|
-
};
|
|
1367
|
-
const sourceAndTargetIds = {
|
|
1368
|
-
source,
|
|
1369
|
-
sourcePort,
|
|
1370
|
-
target,
|
|
1371
|
-
targetPort,
|
|
1372
|
-
};
|
|
1373
|
-
const isConnecting = className === 'react-diagram__connection';
|
|
1374
|
-
if (isConnecting) {
|
|
1375
|
-
document
|
|
1376
|
-
.querySelector('path')
|
|
1377
|
-
?.classList.add('react-diagram__connection-path');
|
|
1378
|
-
return (jsx(EdgeComponent, { ...sourceAndTargetIds, ...position, id: id, data: data, style: style, selected: selected }));
|
|
1379
|
-
}
|
|
1380
|
-
const store = useStoreApi();
|
|
1381
|
-
const edgeRef = useRef(null);
|
|
1382
|
-
const [updating, setUpdating] = useState(false);
|
|
1383
|
-
const markerStartUrl = useMemo(() => `url(#${getMarkerId(markerStart, rfId)})`, [markerStart, rfId]);
|
|
1384
|
-
const markerEndUrl = useMemo(() => `url(#${getMarkerId(markerEnd, rfId)})`, [markerEnd, rfId]);
|
|
1385
|
-
if (hidden) {
|
|
1386
|
-
return null;
|
|
1387
|
-
}
|
|
1388
|
-
const handleEdgeUpdater = (fromPortType) => (event) => {
|
|
1389
|
-
if (event.button !== 0) {
|
|
1390
|
-
return;
|
|
1391
|
-
}
|
|
1392
|
-
const { edges } = store.getState();
|
|
1393
|
-
const nodeId = props[fromPortType];
|
|
1394
|
-
const edge = edges.find((e) => e.id === id);
|
|
1395
|
-
setUpdating(true);
|
|
1396
|
-
onEdgeUpdateStart?.(event, edge, fromPortType);
|
|
1397
|
-
const onConnectEdge = (connection) => onEdgeUpdate?.(edge, connection);
|
|
1398
|
-
const handleEdgeUpdateEnd = (evt) => {
|
|
1399
|
-
setUpdating(false);
|
|
1400
|
-
onEdgeUpdateEnd?.(evt, edge, fromPortType);
|
|
1401
|
-
};
|
|
1402
|
-
handlePointerDown({
|
|
1403
|
-
isAnchor: true,
|
|
1404
|
-
event,
|
|
1405
|
-
nodeId,
|
|
1406
|
-
portType: fromPortType,
|
|
1407
|
-
getState: store.getState,
|
|
1408
|
-
setState: store.setState,
|
|
1409
|
-
onConnect: onConnectEdge,
|
|
1410
|
-
onEdgeUpdateEnd: handleEdgeUpdateEnd,
|
|
1411
|
-
});
|
|
1412
|
-
};
|
|
1413
|
-
const onEdgeClick = (event) => {
|
|
1414
|
-
const { edges } = store.getState();
|
|
1415
|
-
if (onClick) {
|
|
1416
|
-
const edge = edges.find((e) => e.id === id);
|
|
1417
|
-
onClick(event, edge);
|
|
1418
|
-
}
|
|
1419
|
-
};
|
|
1420
|
-
const onEdgeDoubleClick = getMouseHandler$1(id, store.getState, onDoubleClick);
|
|
1421
|
-
const onEdgeContextMenu = getMouseHandler$1(id, store.getState, onContextMenu);
|
|
1422
|
-
const onEdgeMouseEnter = getMouseHandler$1(id, store.getState, onMouseEnter);
|
|
1423
|
-
const onEdgeMouseMove = getMouseHandler$1(id, store.getState, onMouseMove);
|
|
1424
|
-
const onEdgeMouseLeave = getMouseHandler$1(id, store.getState, onMouseLeave);
|
|
1425
|
-
const inactive = !elementsSelectable;
|
|
1426
|
-
const wrapperClassName = cc([
|
|
1427
|
-
'react-diagram__edge',
|
|
1428
|
-
`react-diagram__edge-${type}`,
|
|
1429
|
-
className,
|
|
1430
|
-
{ selected, inactive },
|
|
1431
|
-
]);
|
|
1432
|
-
const marker = { markerStart: markerStartUrl, markerEnd: markerEndUrl };
|
|
1433
|
-
const labelProps = {
|
|
1434
|
-
label,
|
|
1435
|
-
labelStyle,
|
|
1436
|
-
labelShowBg,
|
|
1437
|
-
labelBgStyle,
|
|
1438
|
-
labelBgPadding,
|
|
1439
|
-
labelBgBorderRadius,
|
|
1440
|
-
};
|
|
1441
|
-
const events = {
|
|
1442
|
-
onClick: onEdgeClick,
|
|
1443
|
-
onDoubleClick: onEdgeDoubleClick,
|
|
1444
|
-
onContextMenu: onEdgeContextMenu,
|
|
1445
|
-
onMouseEnter: onEdgeMouseEnter,
|
|
1446
|
-
onMouseMove: onEdgeMouseMove,
|
|
1447
|
-
onMouseLeave: onEdgeMouseLeave,
|
|
1448
|
-
};
|
|
1449
|
-
return (jsx("g", { ...events, ref: edgeRef, className: wrapperClassName, tabIndex: isFocusable ? 0 : undefined, role: isFocusable ? 'button' : undefined, "aria-label": ariaLabel === null
|
|
1450
|
-
? undefined
|
|
1451
|
-
: ariaLabel
|
|
1452
|
-
? ariaLabel
|
|
1453
|
-
: `Edge from ${source} to ${target}`, "aria-describedby": isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : undefined, children: !updating && (jsxs(Fragment, { children: [jsx(EdgeComponent, { ...sourceAndTargetIds, ...marker, ...labelProps, ...position, id: id, data: data, style: style, selected: selected }), jsx(Anchor, { position: sourcePosition, centerX: sourceX, centerY: sourceY, radius: edgeUpdaterRadius, onMouseDown: handleEdgeUpdater('target'),
|
|
1454
|
-
// onMouseEnter={console.log}
|
|
1455
|
-
// onMouseOut={console.log}
|
|
1456
|
-
type: "source" }), jsx(Anchor, { position: targetPosition, centerX: targetX, centerY: targetY, radius: edgeUpdaterRadius, onMouseDown: handleEdgeUpdater('source'),
|
|
1457
|
-
// onMouseEnter={console.log}
|
|
1458
|
-
// onMouseOut={console.log}
|
|
1459
|
-
type: "target" })] })) }));
|
|
1460
|
-
};
|
|
1461
|
-
EdgeWrapper.displayName = 'EdgeWrapper';
|
|
1462
|
-
return memo(EdgeWrapper);
|
|
1463
|
-
};
|
|
1464
|
-
|
|
1465
|
-
const createEdgeTypes = (edgeTypes) => {
|
|
1466
|
-
const defaultTypes = {
|
|
1467
|
-
default: wrapEdge((edgeTypes.straight || StraightEdge)),
|
|
1468
|
-
step: wrapEdge((edgeTypes.step || StepEdge)),
|
|
1469
|
-
bezier: wrapEdge((edgeTypes.bezier || BezierEdge)),
|
|
1470
|
-
};
|
|
1471
|
-
const wrappedTypes = {};
|
|
1472
|
-
const customTypes = Object.keys(edgeTypes)
|
|
1473
|
-
.filter((k) => !Object.keys(defaultTypes).includes(k))
|
|
1474
|
-
.reduce((res, key) => {
|
|
1475
|
-
res[key] = wrapEdge((edgeTypes[key] || StepEdge));
|
|
1476
|
-
return res;
|
|
1477
|
-
}, wrappedTypes);
|
|
1478
|
-
return {
|
|
1479
|
-
...defaultTypes,
|
|
1480
|
-
...customTypes,
|
|
1481
|
-
};
|
|
1482
|
-
};
|
|
1483
|
-
function getPortPosition(position, nodeRect, port = null) {
|
|
1484
|
-
const x = (port?.x || 0) + nodeRect.x;
|
|
1485
|
-
const y = (port?.y || 0) + nodeRect.y;
|
|
1486
|
-
const width = port?.width || nodeRect.width;
|
|
1487
|
-
const height = port?.height || nodeRect.height;
|
|
1488
|
-
switch (position) {
|
|
1489
|
-
case Position.Top:
|
|
1490
|
-
return {
|
|
1491
|
-
x: x + width / 2,
|
|
1492
|
-
y,
|
|
1493
|
-
};
|
|
1494
|
-
case Position.Right:
|
|
1495
|
-
return {
|
|
1496
|
-
x: x + width,
|
|
1497
|
-
y: y + height / 2,
|
|
1498
|
-
};
|
|
1499
|
-
case Position.Bottom:
|
|
1500
|
-
return {
|
|
1501
|
-
x: x + width / 2,
|
|
1502
|
-
y: y + height,
|
|
1503
|
-
};
|
|
1504
|
-
case Position.Left:
|
|
1505
|
-
return {
|
|
1506
|
-
x,
|
|
1507
|
-
y: y + height / 2,
|
|
1508
|
-
};
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
function getPort(bounds, portId) {
|
|
1512
|
-
if (!bounds) {
|
|
1513
|
-
return null;
|
|
1514
|
-
}
|
|
1515
|
-
if (bounds.length === 1 || !portId) {
|
|
1516
|
-
return bounds[0];
|
|
1517
|
-
}
|
|
1518
|
-
else if (portId) {
|
|
1519
|
-
return bounds.find((d) => d.id === portId) || null;
|
|
1520
|
-
}
|
|
1521
|
-
return null;
|
|
1522
|
-
}
|
|
1523
|
-
const getEdgePositions = (sourceNodeRect, sourcePort, sourcePosition, targetNodeRect, targetPort, targetPosition) => {
|
|
1524
|
-
const sourcePortPos = getPortPosition(sourcePosition, sourceNodeRect, sourcePort);
|
|
1525
|
-
const targetPortPos = getPortPosition(targetPosition, targetNodeRect, targetPort);
|
|
1526
|
-
return {
|
|
1527
|
-
sourceX: sourcePortPos.x,
|
|
1528
|
-
sourceY: sourcePortPos.y,
|
|
1529
|
-
targetX: targetPortPos.x,
|
|
1530
|
-
targetY: targetPortPos.y,
|
|
1531
|
-
};
|
|
1532
|
-
};
|
|
1533
|
-
function getNodeData(node) {
|
|
1534
|
-
const portBounds = node?.[internalsSymbol]?.portBounds || null;
|
|
1535
|
-
const isValid = portBounds &&
|
|
1536
|
-
node?.width &&
|
|
1537
|
-
node?.height &&
|
|
1538
|
-
typeof node?.positionAbsolute?.x !== 'undefined' &&
|
|
1539
|
-
typeof node?.positionAbsolute?.y !== 'undefined';
|
|
1540
|
-
return [
|
|
1541
|
-
{
|
|
1542
|
-
x: node?.positionAbsolute?.x || 0,
|
|
1543
|
-
y: node?.positionAbsolute?.y || 0,
|
|
1544
|
-
width: node?.width || 0,
|
|
1545
|
-
height: node?.height || 0,
|
|
1546
|
-
},
|
|
1547
|
-
portBounds,
|
|
1548
|
-
!!isValid,
|
|
1549
|
-
];
|
|
1550
|
-
}
|
|
1551
|
-
|
|
1552
|
-
const selector$2 = (s) => ({
|
|
1553
|
-
edges: s.edges,
|
|
1554
|
-
width: s.width,
|
|
1555
|
-
height: s.height,
|
|
1556
|
-
nodeInternals: s.nodeInternals,
|
|
1557
|
-
onError: s.onError,
|
|
1558
|
-
});
|
|
1559
|
-
function EdgeRenderer({ rfId, edgeTypes, noPanClassName, edgeUpdaterRadius, onEdgeClick, onEdgeDoubleClick, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, }) {
|
|
1560
|
-
const { edges, width, height, nodeInternals } = useStore(selector$2, shallow);
|
|
1561
|
-
return (jsxs("svg", { width: width || '100vw', height: height || '100vh', className: "react-diagram__edges react-diagram__container", children: [jsx(MarkerComponent$1, { defaultColor: "#000000", rfId: rfId }), jsx("g", { children: edges.map((edge) => {
|
|
1562
|
-
const { data, type,
|
|
1563
|
-
// elProps
|
|
1564
|
-
id, className, style, ariaLabel,
|
|
1565
|
-
// sourceAndTargetIds
|
|
1566
|
-
source, sourcePort, target, targetPort,
|
|
1567
|
-
// marker
|
|
1568
|
-
markerEnd, markerStart,
|
|
1569
|
-
// labelProps
|
|
1570
|
-
label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, } = edge;
|
|
1571
|
-
const [sourceNodeRect, sourcePortBounds, sourceIsValid] = getNodeData(nodeInternals.get(source));
|
|
1572
|
-
const [targetNodeRect, targetPortBounds, targetIsValid] = getNodeData(nodeInternals.get(target));
|
|
1573
|
-
if (!sourceIsValid || !targetIsValid) {
|
|
1574
|
-
return null;
|
|
1575
|
-
}
|
|
1576
|
-
const edgeType = type || 'straight';
|
|
1577
|
-
const EdgeComponent = edgeTypes[edgeType] || edgeTypes.default;
|
|
1578
|
-
const targetNodePorts = targetPortBounds.target;
|
|
1579
|
-
const sourcePortInfo = getPort(sourcePortBounds.source, sourcePort);
|
|
1580
|
-
const targetPortInfo = getPort(targetNodePorts, targetPort);
|
|
1581
|
-
const sourcePosition = sourcePortInfo?.position || Position.Bottom;
|
|
1582
|
-
const targetPosition = targetPortInfo?.position || Position.Top;
|
|
1583
|
-
const isFocusable = !!edge.focusable;
|
|
1584
|
-
if (!sourcePortInfo || !targetPortInfo) {
|
|
1585
|
-
return null;
|
|
1586
|
-
}
|
|
1587
|
-
const elProps = {
|
|
1588
|
-
id,
|
|
1589
|
-
className: cc([className, noPanClassName]),
|
|
1590
|
-
style,
|
|
1591
|
-
ariaLabel,
|
|
1592
|
-
};
|
|
1593
|
-
const sourceAndTargetIds = {
|
|
1594
|
-
source,
|
|
1595
|
-
sourcePort,
|
|
1596
|
-
target,
|
|
1597
|
-
targetPort,
|
|
1598
|
-
};
|
|
1599
|
-
const marker = {
|
|
1600
|
-
markerEnd,
|
|
1601
|
-
markerStart,
|
|
1602
|
-
};
|
|
1603
|
-
const labelProps = {
|
|
1604
|
-
label,
|
|
1605
|
-
labelStyle,
|
|
1606
|
-
labelShowBg,
|
|
1607
|
-
labelBgStyle,
|
|
1608
|
-
labelBgPadding,
|
|
1609
|
-
labelBgBorderRadius,
|
|
1610
|
-
};
|
|
1611
|
-
const edgePositions = getEdgePositions(sourceNodeRect, sourcePortInfo, sourcePosition, targetNodeRect, targetPortInfo, targetPosition);
|
|
1612
|
-
const position = {
|
|
1613
|
-
...edgePositions,
|
|
1614
|
-
sourcePosition,
|
|
1615
|
-
targetPosition,
|
|
1616
|
-
};
|
|
1617
|
-
const events = {
|
|
1618
|
-
onClick: onEdgeClick,
|
|
1619
|
-
onDoubleClick: onEdgeDoubleClick,
|
|
1620
|
-
onContextMenu: onEdgeContextMenu,
|
|
1621
|
-
onMouseEnter: onEdgeMouseEnter,
|
|
1622
|
-
onMouseMove: onEdgeMouseMove,
|
|
1623
|
-
onMouseLeave: onEdgeMouseLeave,
|
|
1624
|
-
onEdgeUpdate,
|
|
1625
|
-
onEdgeUpdateStart,
|
|
1626
|
-
onEdgeUpdateEnd,
|
|
1627
|
-
};
|
|
1628
|
-
return (jsx(EdgeComponent, { ...elProps, ...sourceAndTargetIds, ...marker, ...labelProps, ...position, ...events, rfId: rfId, type: edgeType, data: data, isFocusable: isFocusable, edgeUpdaterRadius: edgeUpdaterRadius }, id));
|
|
1629
|
-
}) })] }));
|
|
1630
|
-
}
|
|
1631
|
-
EdgeRenderer.displayName = 'EdgeRenderer';
|
|
1632
|
-
var EdgeRenderer$1 = memo(EdgeRenderer);
|
|
1633
|
-
|
|
1634
|
-
const oppositePosition = {
|
|
1635
|
-
[Position.Left]: Position.Right,
|
|
1636
|
-
[Position.Right]: Position.Left,
|
|
1637
|
-
[Position.Top]: Position.Bottom,
|
|
1638
|
-
[Position.Bottom]: Position.Top,
|
|
1639
|
-
};
|
|
1640
|
-
function ConnectionPath({ nodeId, portType, edge, Component, EdgeWrapper, }) {
|
|
1641
|
-
const { fromNode, toX, toY } = useStore(useCallback((s) => ({
|
|
1642
|
-
fromNode: s.nodeInternals.get(nodeId),
|
|
1643
|
-
toX: (s.connectionPosition.x - s.transform[0]) / s.transform[2],
|
|
1644
|
-
toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2],
|
|
1645
|
-
}), [nodeId]), shallow);
|
|
1646
|
-
const fromPortBounds = fromNode?.[internalsSymbol]?.portBounds;
|
|
1647
|
-
const portBounds = fromPortBounds?.[portType];
|
|
1648
|
-
if (!fromNode || !portBounds) {
|
|
1649
|
-
return null;
|
|
1650
|
-
}
|
|
1651
|
-
const fromPort = portBounds[0];
|
|
1652
|
-
const fromPortX = fromPort
|
|
1653
|
-
? fromPort.x + fromPort.width / 2
|
|
1654
|
-
: (fromNode.width ?? 0) / 2;
|
|
1655
|
-
const fromPortY = fromPort
|
|
1656
|
-
? fromPort.y + fromPort.height / 2
|
|
1657
|
-
: fromNode.height ?? 0;
|
|
1658
|
-
const fromX = (fromNode.positionAbsolute?.x ?? 0) + fromPortX;
|
|
1659
|
-
const fromY = (fromNode.positionAbsolute?.y ?? 0) + fromPortY;
|
|
1660
|
-
const fromPosition = fromPort?.position;
|
|
1661
|
-
const toPosition = fromPosition ? oppositePosition[fromPosition] : null;
|
|
1662
|
-
if (!fromPosition || !toPosition) {
|
|
1663
|
-
return null;
|
|
1664
|
-
}
|
|
1665
|
-
if (Component) {
|
|
1666
|
-
return (jsx(Component, { fromNode: fromNode, fromPort: fromPort, fromX: fromX, fromY: fromY, toX: toX, toY: toY, fromPosition: fromPosition, toPosition: toPosition }));
|
|
1667
|
-
}
|
|
1668
|
-
return (jsx(EdgeWrapper, { id: edge.id, className: "react-diagram__connection", type: edge.type || 'default', source: edge.source, target: edge.target, isFocusable: false, sourceX: fromX, sourceY: fromY, targetX: toX, targetY: toY, sourcePosition: fromPosition, targetPosition: toPosition }));
|
|
1669
|
-
}
|
|
1670
|
-
ConnectionPath.displayName = 'ConnectionPath';
|
|
1671
|
-
|
|
1672
|
-
const selector$1 = (s) => ({
|
|
1673
|
-
edges: s.edges,
|
|
1674
|
-
nodeId: s.connectionNodeId,
|
|
1675
|
-
portType: s.connectionPortType,
|
|
1676
|
-
});
|
|
1677
|
-
function ConnectionLineRenderer({ containerStyle, edgeTypes, component, }) {
|
|
1678
|
-
const { nodeId, portType, edges } = useStore(selector$1, shallow);
|
|
1679
|
-
const isValid = !!(nodeId && portType);
|
|
1680
|
-
if (!isValid) {
|
|
1681
|
-
return null;
|
|
1682
|
-
}
|
|
1683
|
-
const selectedEdge = edges.find((edge) => edge[portType] === nodeId);
|
|
1684
|
-
if (!selectedEdge)
|
|
1685
|
-
return null;
|
|
1686
|
-
const EdgeWrapper = selectedEdge?.type
|
|
1687
|
-
? edgeTypes[selectedEdge.type]
|
|
1688
|
-
: edgeTypes.default;
|
|
1689
|
-
return (jsx("svg", { style: containerStyle, className: "react-diagram__container react-diagram__connection-line", children: jsx("g", { className: "react-diagram__connection", children: jsx(ConnectionPath, { nodeId: nodeId, portType: portType, edge: selectedEdge, Component: component, EdgeWrapper: EdgeWrapper }) }) }));
|
|
1690
|
-
}
|
|
1691
|
-
|
|
1692
|
-
function DiagramView({ rfId,
|
|
1693
|
-
// DiagramRenderer props
|
|
1694
|
-
noPanClassName, panning, defaultViewport, multiSelectionKeyCode, onMove, onMoveStart, onMoveEnd,
|
|
1695
|
-
// NodeRenderer props
|
|
1696
|
-
onlyRenderVisibleElements, disableKeyboardA11y, noDragClassName, nodeOrigin, nodeTypes, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave,
|
|
1697
|
-
// EdgeRenderer props
|
|
1698
|
-
edgeTypes, edgeUpdaterRadius, onEdgeClick, onEdgeDoubleClick, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd,
|
|
1699
|
-
// ConnectionLineWrapper
|
|
1700
|
-
ConnectionLineContainerStyle, ConnectionLineComponent, }) {
|
|
1701
|
-
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 })] }));
|
|
1702
|
-
}
|
|
1703
|
-
DiagramView.displayName = 'DiagramView';
|
|
1704
|
-
var DiagramView$1 = memo(DiagramView);
|
|
1705
|
-
|
|
1706
|
-
const selector = (s) => {
|
|
1707
|
-
const { setNodes, setEdges, setNodeExtent, setTranslateExtent, setMinZoom, setMaxZoom, } = s;
|
|
1708
|
-
return {
|
|
1709
|
-
setNodes,
|
|
1710
|
-
setEdges,
|
|
1711
|
-
setNodeExtent,
|
|
1712
|
-
setTranslateExtent,
|
|
1713
|
-
setMinZoom,
|
|
1714
|
-
setMaxZoom,
|
|
1715
|
-
};
|
|
1716
|
-
};
|
|
1717
|
-
function useStoreUpdater(value, setStoreState) {
|
|
1718
|
-
useEffect(() => {
|
|
1719
|
-
if (typeof value !== 'undefined') {
|
|
1720
|
-
setStoreState(value);
|
|
1721
|
-
}
|
|
1722
|
-
}, [value]);
|
|
1723
|
-
}
|
|
1724
|
-
// updates with values in store that don't have a dedicated setter function
|
|
1725
|
-
function useDirectStoreUpdater(key, value, setState) {
|
|
1726
|
-
useEffect(() => {
|
|
1727
|
-
if (typeof value !== 'undefined') {
|
|
1728
|
-
setState({ [key]: value });
|
|
1729
|
-
}
|
|
1730
|
-
}, [value]);
|
|
1731
|
-
}
|
|
1732
|
-
const StoreUpdater = ({ nodes, onNodesChange, onNodeDrag, onNodeDragStart, onNodeDragEnd, edges, onEdgesChange, gridStep, elevateNodesOnSelect, nodesDraggable, autoPanOnNodeDrag, autoPanOnConnect, connectionRadius, onConnect, onConnectStart, onConnectEnd, onError, nodeExtent, translateExtent, minZoom, maxZoom, }) => {
|
|
1733
|
-
const { setNodes, setEdges, setNodeExtent, setTranslateExtent, setMinZoom, setMaxZoom, } = useStore(selector, shallow);
|
|
1734
|
-
const store = useStoreApi();
|
|
1735
|
-
useDirectStoreUpdater('gridStep', gridStep, store.setState);
|
|
1736
|
-
useStoreUpdater(nodes, setNodes);
|
|
1737
|
-
useStoreUpdater(edges, setEdges);
|
|
1738
|
-
useStoreUpdater(nodeExtent, setNodeExtent);
|
|
1739
|
-
useStoreUpdater(translateExtent, setTranslateExtent);
|
|
1740
|
-
useStoreUpdater(minZoom, setMinZoom);
|
|
1741
|
-
useStoreUpdater(maxZoom, setMaxZoom);
|
|
1742
|
-
useDirectStoreUpdater('elevateNodesOnSelect', elevateNodesOnSelect, store.setState);
|
|
1743
|
-
useDirectStoreUpdater('nodesDraggable', nodesDraggable, store.setState);
|
|
1744
|
-
useDirectStoreUpdater('autoPanOnNodeDrag', autoPanOnNodeDrag, store.setState);
|
|
1745
|
-
useDirectStoreUpdater('autoPanOnConnect', autoPanOnConnect, store.setState);
|
|
1746
|
-
useDirectStoreUpdater('connectionRadius', connectionRadius, store.setState);
|
|
1747
|
-
useDirectStoreUpdater('onNodesChange', onNodesChange, store.setState);
|
|
1748
|
-
useDirectStoreUpdater('onNodeDrag', onNodeDrag, store.setState);
|
|
1749
|
-
useDirectStoreUpdater('onNodeDragStart', onNodeDragStart, store.setState);
|
|
1750
|
-
useDirectStoreUpdater('onNodeDragEnd', onNodeDragEnd, store.setState);
|
|
1751
|
-
useDirectStoreUpdater('onEdgesChange', onEdgesChange, store.setState);
|
|
1752
|
-
useDirectStoreUpdater('onConnect', onConnect, store.setState);
|
|
1753
|
-
useDirectStoreUpdater('onConnectStart', onConnectStart, store.setState);
|
|
1754
|
-
useDirectStoreUpdater('onConnectEnd', onConnectEnd, store.setState);
|
|
1755
|
-
useDirectStoreUpdater('onError', onErrorWrapper(onError), store.setState);
|
|
1756
|
-
return null;
|
|
1757
|
-
};
|
|
1758
|
-
|
|
1759
|
-
function useNodeOrEdgeTypes(nodeOrEdgeTypes, createTypes) {
|
|
1760
|
-
const typesKeysRef = useRef(null);
|
|
1761
|
-
const typesParsed = useMemo(() => {
|
|
1762
|
-
if (process.env.NODE_ENV === 'development') {
|
|
1763
|
-
const typeKeys = Object.keys(nodeOrEdgeTypes);
|
|
1764
|
-
if (shallow(typesKeysRef.current, typeKeys)) {
|
|
1765
|
-
devWarn('002');
|
|
1766
|
-
}
|
|
1767
|
-
typesKeysRef.current = typeKeys;
|
|
1768
|
-
}
|
|
1769
|
-
return createTypes(nodeOrEdgeTypes);
|
|
1770
|
-
}, [nodeOrEdgeTypes]);
|
|
1771
|
-
return typesParsed;
|
|
1772
|
-
}
|
|
1773
|
-
|
|
1774
|
-
const NodeIdContext = createContext(null);
|
|
1775
|
-
const Provider = NodeIdContext.Provider;
|
|
1776
|
-
NodeIdContext.Consumer;
|
|
1777
|
-
const useNodeId = () => {
|
|
1778
|
-
const nodeId = useContext(NodeIdContext);
|
|
1779
|
-
return nodeId;
|
|
1680
|
+
const portPositionX = (x, shift, position) => {
|
|
1681
|
+
if (position === Position.Left)
|
|
1682
|
+
return x - shift;
|
|
1683
|
+
if (position === Position.Right)
|
|
1684
|
+
return x + shift;
|
|
1685
|
+
return x;
|
|
1686
|
+
};
|
|
1687
|
+
const portPositionY = (y, shift, position) => {
|
|
1688
|
+
if (position === Position.Top)
|
|
1689
|
+
return y - shift;
|
|
1690
|
+
if (position === Position.Bottom)
|
|
1691
|
+
return y + shift;
|
|
1692
|
+
return y;
|
|
1780
1693
|
};
|
|
1694
|
+
const EdgeUpdaterClassName = 'react-diagram__edge-updater';
|
|
1695
|
+
function Anchor({ position, centerX, centerY, radius = 10, onMouseDown,
|
|
1696
|
+
// onMouseEnter,
|
|
1697
|
+
// onMouseOut,
|
|
1698
|
+
type, }) {
|
|
1699
|
+
return (jsx("circle", { className: cc([
|
|
1700
|
+
EdgeUpdaterClassName,
|
|
1701
|
+
`${EdgeUpdaterClassName}-${type}`,
|
|
1702
|
+
]), cx: portPositionX(centerX, radius, position), cy: portPositionY(centerY, radius, position), r: radius, stroke: "transparent", fill: "transparent", onMouseDown: onMouseDown }));
|
|
1703
|
+
}
|
|
1781
1704
|
|
|
1782
|
-
function
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
...defaultEdgeOptions,
|
|
1791
|
-
...connection,
|
|
1705
|
+
function getMouseHandler(id, getState, handler) {
|
|
1706
|
+
return handler === undefined
|
|
1707
|
+
? handler
|
|
1708
|
+
: (event) => {
|
|
1709
|
+
const edge = getState().edges.find((e) => e.id === id);
|
|
1710
|
+
if (edge) {
|
|
1711
|
+
handler(event, { ...edge });
|
|
1712
|
+
}
|
|
1792
1713
|
};
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
const
|
|
1796
|
-
const
|
|
1797
|
-
|
|
1714
|
+
}
|
|
1715
|
+
const wrapEdge = (EdgeComponent) => {
|
|
1716
|
+
const EdgeWrapper = (props) => {
|
|
1717
|
+
const { id, className, style, type, data, rfId, ariaLabel,
|
|
1718
|
+
// sourceAndTargetIds
|
|
1719
|
+
source, sourcePort, target, targetPort,
|
|
1720
|
+
// marker
|
|
1721
|
+
markerEnd, markerStart,
|
|
1722
|
+
// labelProps
|
|
1723
|
+
label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius,
|
|
1724
|
+
// AnchorProps
|
|
1725
|
+
edgeUpdaterRadius,
|
|
1726
|
+
// position
|
|
1727
|
+
sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, selected, elementsSelectable, hidden, isFocusable, onClick, onDoubleClick, onContextMenu, onMouseEnter, onMouseMove, onMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, } = props;
|
|
1728
|
+
const position = {
|
|
1729
|
+
sourceX,
|
|
1730
|
+
sourceY,
|
|
1731
|
+
targetX,
|
|
1732
|
+
targetY,
|
|
1733
|
+
sourcePosition,
|
|
1734
|
+
targetPosition,
|
|
1735
|
+
};
|
|
1736
|
+
const sourceAndTargetIds = {
|
|
1737
|
+
source,
|
|
1738
|
+
sourcePort,
|
|
1739
|
+
target,
|
|
1740
|
+
targetPort,
|
|
1741
|
+
};
|
|
1742
|
+
const isConnecting = className === 'react-diagram__connection';
|
|
1743
|
+
if (isConnecting) {
|
|
1744
|
+
document
|
|
1745
|
+
.querySelector('path')
|
|
1746
|
+
?.classList.add('react-diagram__connection-path');
|
|
1747
|
+
return (jsx(EdgeComponent, { ...sourceAndTargetIds, ...position, id: id, data: data, style: style, selected: selected }));
|
|
1748
|
+
}
|
|
1749
|
+
const store = useStoreApi();
|
|
1750
|
+
const edgeRef = useRef(null);
|
|
1751
|
+
const [updating, setUpdating] = useState(false);
|
|
1752
|
+
const markerStartUrl = useMemo(() => `url(#${getMarkerId(markerStart, rfId)})`, [markerStart, rfId]);
|
|
1753
|
+
const markerEndUrl = useMemo(() => `url(#${getMarkerId(markerEnd, rfId)})`, [markerEnd, rfId]);
|
|
1754
|
+
if (hidden) {
|
|
1755
|
+
return null;
|
|
1756
|
+
}
|
|
1757
|
+
const handleEdgeUpdater = (fromPortType) => (event) => {
|
|
1758
|
+
if (event.button !== 0) {
|
|
1759
|
+
return;
|
|
1760
|
+
}
|
|
1761
|
+
const { edges } = store.getState();
|
|
1762
|
+
const nodeId = props[fromPortType];
|
|
1763
|
+
const edge = edges.find((e) => e.id === id);
|
|
1764
|
+
setUpdating(true);
|
|
1765
|
+
onEdgeUpdateStart?.(event, edge, fromPortType);
|
|
1766
|
+
const onConnectEdge = (connection) => onEdgeUpdate?.(edge, connection);
|
|
1767
|
+
const handleEdgeUpdateEnd = (evt) => {
|
|
1768
|
+
setUpdating(false);
|
|
1769
|
+
onEdgeUpdateEnd?.(evt, edge, fromPortType);
|
|
1770
|
+
};
|
|
1798
1771
|
handlePointerDown({
|
|
1772
|
+
isAnchor: true,
|
|
1799
1773
|
event,
|
|
1800
1774
|
nodeId,
|
|
1801
|
-
portType:
|
|
1775
|
+
portType: fromPortType,
|
|
1802
1776
|
getState: store.getState,
|
|
1803
1777
|
setState: store.setState,
|
|
1804
|
-
onConnect:
|
|
1778
|
+
onConnect: onConnectEdge,
|
|
1779
|
+
onEdgeUpdateEnd: handleEdgeUpdateEnd,
|
|
1805
1780
|
});
|
|
1806
|
-
}
|
|
1807
|
-
};
|
|
1808
|
-
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 }));
|
|
1809
|
-
}
|
|
1810
|
-
Port.displayName = 'Port';
|
|
1811
|
-
var Port$1 = memo(Port);
|
|
1812
|
-
|
|
1813
|
-
function Nodes({ data }) {
|
|
1814
|
-
return (jsxs(Fragment, { children: [jsx(Port$1, { type: "target", position: Position.Top }), data.label, jsx(Port$1, { type: "source", position: Position.Bottom })] }));
|
|
1815
|
-
}
|
|
1816
|
-
|
|
1817
|
-
function useGetPointerPosition() {
|
|
1818
|
-
const store = useStoreApi();
|
|
1819
|
-
// returns the pointer position projected to the RF coordinate system
|
|
1820
|
-
const getPointerPosition = useCallback(({ sourceEvent }) => {
|
|
1821
|
-
const { transform, gridStep } = store.getState();
|
|
1822
|
-
const x = sourceEvent.touches
|
|
1823
|
-
? sourceEvent.touches[0].clientX
|
|
1824
|
-
: sourceEvent.clientX;
|
|
1825
|
-
const y = sourceEvent.touches
|
|
1826
|
-
? sourceEvent.touches[0].clientY
|
|
1827
|
-
: sourceEvent.clientY;
|
|
1828
|
-
const pointerPos = {
|
|
1829
|
-
x: (x - transform[0]) / transform[2],
|
|
1830
|
-
y: (y - transform[1]) / transform[2],
|
|
1831
1781
|
};
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
? gridStep[1] * Math.round(pointerPos.y / gridStep[1])
|
|
1839
|
-
: pointerPos.y,
|
|
1840
|
-
...pointerPos,
|
|
1782
|
+
const onEdgeClick = (event) => {
|
|
1783
|
+
const { edges } = store.getState();
|
|
1784
|
+
if (onClick) {
|
|
1785
|
+
const edge = edges.find((e) => e.id === id);
|
|
1786
|
+
onClick(event, edge);
|
|
1787
|
+
}
|
|
1841
1788
|
};
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1789
|
+
const onEdgeDoubleClick = getMouseHandler(id, store.getState, onDoubleClick);
|
|
1790
|
+
const onEdgeContextMenu = getMouseHandler(id, store.getState, onContextMenu);
|
|
1791
|
+
const onEdgeMouseEnter = getMouseHandler(id, store.getState, onMouseEnter);
|
|
1792
|
+
const onEdgeMouseMove = getMouseHandler(id, store.getState, onMouseMove);
|
|
1793
|
+
const onEdgeMouseLeave = getMouseHandler(id, store.getState, onMouseLeave);
|
|
1794
|
+
const inactive = !elementsSelectable;
|
|
1795
|
+
const wrapperClassName = cc([
|
|
1796
|
+
'react-diagram__edge',
|
|
1797
|
+
`react-diagram__edge-${type}`,
|
|
1798
|
+
className,
|
|
1799
|
+
{ selected, inactive },
|
|
1800
|
+
]);
|
|
1801
|
+
const marker = { markerStart: markerStartUrl, markerEnd: markerEndUrl };
|
|
1802
|
+
const labelProps = {
|
|
1803
|
+
label,
|
|
1804
|
+
labelStyle,
|
|
1805
|
+
labelShowBg,
|
|
1806
|
+
labelBgStyle,
|
|
1807
|
+
labelBgPadding,
|
|
1808
|
+
labelBgBorderRadius,
|
|
1809
|
+
};
|
|
1810
|
+
const events = {
|
|
1811
|
+
onClick: onEdgeClick,
|
|
1812
|
+
onDoubleClick: onEdgeDoubleClick,
|
|
1813
|
+
onContextMenu: onEdgeContextMenu,
|
|
1814
|
+
onMouseEnter: onEdgeMouseEnter,
|
|
1815
|
+
onMouseMove: onEdgeMouseMove,
|
|
1816
|
+
onMouseLeave: onEdgeMouseLeave,
|
|
1817
|
+
};
|
|
1818
|
+
return (jsx("g", { ...events, ref: edgeRef, className: wrapperClassName, tabIndex: isFocusable ? 0 : undefined, role: isFocusable ? 'button' : undefined, "aria-label": ariaLabel === null
|
|
1819
|
+
? undefined
|
|
1820
|
+
: ariaLabel
|
|
1821
|
+
? ariaLabel
|
|
1822
|
+
: `Edge from ${source} to ${target}`, "aria-describedby": isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : undefined, children: !updating && (jsxs(Fragment, { children: [jsx(EdgeComponent, { ...sourceAndTargetIds, ...marker, ...labelProps, ...position, id: id, data: data, style: style, selected: selected }), jsx(Anchor, { position: sourcePosition, centerX: sourceX, centerY: sourceY, radius: edgeUpdaterRadius, onMouseDown: handleEdgeUpdater('target'),
|
|
1823
|
+
// onMouseEnter={console.log}
|
|
1824
|
+
// onMouseOut={console.log}
|
|
1825
|
+
type: "source" }), jsx(Anchor, { position: targetPosition, centerX: targetX, centerY: targetY, radius: edgeUpdaterRadius, onMouseDown: handleEdgeUpdater('source'),
|
|
1826
|
+
// onMouseEnter={console.log}
|
|
1827
|
+
// onMouseOut={console.log}
|
|
1828
|
+
type: "target" })] })) }));
|
|
1829
|
+
};
|
|
1830
|
+
EdgeWrapper.displayName = 'EdgeWrapper';
|
|
1831
|
+
return memo(EdgeWrapper);
|
|
1832
|
+
};
|
|
1845
1833
|
|
|
1846
|
-
const
|
|
1847
|
-
const
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
const
|
|
1853
|
-
const
|
|
1854
|
-
|
|
1855
|
-
|
|
1834
|
+
const createEdgeTypes = (edgeTypes) => {
|
|
1835
|
+
const defaultTypes = {
|
|
1836
|
+
default: wrapEdge((edgeTypes.straight || StraightEdge)),
|
|
1837
|
+
step: wrapEdge((edgeTypes.step || StepEdge)),
|
|
1838
|
+
bezier: wrapEdge((edgeTypes.bezier || BezierEdge)),
|
|
1839
|
+
};
|
|
1840
|
+
const wrappedTypes = {};
|
|
1841
|
+
const customTypes = Object.keys(edgeTypes)
|
|
1842
|
+
.filter((k) => !Object.keys(defaultTypes).includes(k))
|
|
1843
|
+
.reduce((res, key) => {
|
|
1844
|
+
res[key] = wrapEdge((edgeTypes[key] || StepEdge));
|
|
1845
|
+
return res;
|
|
1846
|
+
}, wrappedTypes);
|
|
1847
|
+
return {
|
|
1848
|
+
...defaultTypes,
|
|
1849
|
+
...customTypes,
|
|
1856
1850
|
};
|
|
1857
|
-
return portsArray.map((port) => {
|
|
1858
|
-
const portBounds = port.getBoundingClientRect();
|
|
1859
|
-
return {
|
|
1860
|
-
id: port.getAttribute('data-portid'),
|
|
1861
|
-
position: port.dataset.portPosition,
|
|
1862
|
-
x: (portBounds.left - nodeBounds.left - nodeOffset.x) / zoom,
|
|
1863
|
-
y: (portBounds.top - nodeBounds.top - nodeOffset.y) / zoom,
|
|
1864
|
-
...getDimensions(port),
|
|
1865
|
-
};
|
|
1866
|
-
});
|
|
1867
1851
|
};
|
|
1868
|
-
function
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1852
|
+
function getPortPosition(position, nodeRect, port = null) {
|
|
1853
|
+
const x = (port?.x || 0) + nodeRect.x;
|
|
1854
|
+
const y = (port?.y || 0) + nodeRect.y;
|
|
1855
|
+
const width = port?.width || nodeRect.width;
|
|
1856
|
+
const height = port?.height || nodeRect.height;
|
|
1857
|
+
switch (position) {
|
|
1858
|
+
case Position.Top:
|
|
1859
|
+
return {
|
|
1860
|
+
x: x + width / 2,
|
|
1861
|
+
y,
|
|
1862
|
+
};
|
|
1863
|
+
case Position.Right:
|
|
1864
|
+
return {
|
|
1865
|
+
x: x + width,
|
|
1866
|
+
y: y + height / 2,
|
|
1867
|
+
};
|
|
1868
|
+
case Position.Bottom:
|
|
1869
|
+
return {
|
|
1870
|
+
x: x + width / 2,
|
|
1871
|
+
y: y + height,
|
|
1872
|
+
};
|
|
1873
|
+
case Position.Left:
|
|
1874
|
+
return {
|
|
1875
|
+
x,
|
|
1876
|
+
y: y + height / 2,
|
|
1877
|
+
};
|
|
1888
1878
|
}
|
|
1889
1879
|
}
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
return false;
|
|
1880
|
+
function getPort(bounds, portId) {
|
|
1881
|
+
if (!bounds) {
|
|
1882
|
+
return null;
|
|
1894
1883
|
}
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
return false;
|
|
1884
|
+
if (bounds.length === 1 || !portId) {
|
|
1885
|
+
return bounds[0];
|
|
1898
1886
|
}
|
|
1899
|
-
if (
|
|
1900
|
-
return
|
|
1887
|
+
else if (portId) {
|
|
1888
|
+
return bounds.find((d) => d.id === portId) || null;
|
|
1901
1889
|
}
|
|
1902
|
-
return
|
|
1890
|
+
return null;
|
|
1903
1891
|
}
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
.
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1892
|
+
const getEdgePositions = (sourceNodeRect, sourcePort, sourcePosition, targetNodeRect, targetPort, targetPosition) => {
|
|
1893
|
+
const sourcePortPos = getPortPosition(sourcePosition, sourceNodeRect, sourcePort);
|
|
1894
|
+
const targetPortPos = getPortPosition(targetPosition, targetNodeRect, targetPort);
|
|
1895
|
+
return {
|
|
1896
|
+
sourceX: sourcePortPos.x,
|
|
1897
|
+
sourceY: sourcePortPos.y,
|
|
1898
|
+
targetX: targetPortPos.x,
|
|
1899
|
+
targetY: targetPortPos.y,
|
|
1900
|
+
};
|
|
1901
|
+
};
|
|
1902
|
+
function getNodeData(node) {
|
|
1903
|
+
const portBounds = node?.[internalsSymbol]?.portBounds || null;
|
|
1904
|
+
const isValid = portBounds &&
|
|
1905
|
+
node?.width &&
|
|
1906
|
+
node?.height &&
|
|
1907
|
+
typeof node?.positionAbsolute?.x !== 'undefined' &&
|
|
1908
|
+
typeof node?.positionAbsolute?.y !== 'undefined';
|
|
1909
|
+
return [
|
|
1910
|
+
{
|
|
1911
|
+
x: node?.positionAbsolute?.x || 0,
|
|
1912
|
+
y: node?.positionAbsolute?.y || 0,
|
|
1913
|
+
width: node?.width || 0,
|
|
1914
|
+
height: node?.height || 0,
|
|
1921
1915
|
},
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
height: n.height,
|
|
1926
|
-
}));
|
|
1916
|
+
portBounds,
|
|
1917
|
+
!!isValid,
|
|
1918
|
+
];
|
|
1927
1919
|
}
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1920
|
+
|
|
1921
|
+
const selector$3 = (s) => ({
|
|
1922
|
+
edges: s.edges,
|
|
1923
|
+
width: s.width,
|
|
1924
|
+
height: s.height,
|
|
1925
|
+
nodeInternals: s.nodeInternals,
|
|
1926
|
+
onError: s.onError,
|
|
1927
|
+
});
|
|
1928
|
+
function EdgeRenderer({ rfId, edgeTypes, noPanClassName, edgeUpdaterRadius, onEdgeClick, onEdgeDoubleClick, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, }) {
|
|
1929
|
+
const { edges, width, height, nodeInternals } = useStore(selector$3, shallow);
|
|
1930
|
+
return (jsxs("svg", { width: width || '100vw', height: height || '100vh', className: "react-diagram__edges react-diagram__container", children: [jsx(MarkerComponent$1, { defaultColor: "#000000", rfId: rfId }), jsx("g", { children: edges.map((edge) => {
|
|
1931
|
+
const { data, type,
|
|
1932
|
+
// elProps
|
|
1933
|
+
id, className, style, ariaLabel,
|
|
1934
|
+
// sourceAndTargetIds
|
|
1935
|
+
source, sourcePort, target, targetPort,
|
|
1936
|
+
// marker
|
|
1937
|
+
markerEnd, markerStart,
|
|
1938
|
+
// labelProps
|
|
1939
|
+
label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, } = edge;
|
|
1940
|
+
const [sourceNodeRect, sourcePortBounds, sourceIsValid] = getNodeData(nodeInternals.get(source));
|
|
1941
|
+
const [targetNodeRect, targetPortBounds, targetIsValid] = getNodeData(nodeInternals.get(target));
|
|
1942
|
+
if (!sourceIsValid || !targetIsValid) {
|
|
1943
|
+
return null;
|
|
1944
|
+
}
|
|
1945
|
+
const edgeType = type || 'straight';
|
|
1946
|
+
const EdgeComponent = edgeTypes[edgeType] || edgeTypes.default;
|
|
1947
|
+
const targetNodePorts = targetPortBounds.target;
|
|
1948
|
+
const sourcePortInfo = getPort(sourcePortBounds.source, sourcePort);
|
|
1949
|
+
const targetPortInfo = getPort(targetNodePorts, targetPort);
|
|
1950
|
+
const sourcePosition = sourcePortInfo?.position || Position.Bottom;
|
|
1951
|
+
const targetPosition = targetPortInfo?.position || Position.Top;
|
|
1952
|
+
const isFocusable = !!edge.focusable;
|
|
1953
|
+
if (!sourcePortInfo || !targetPortInfo) {
|
|
1954
|
+
return null;
|
|
1955
|
+
}
|
|
1956
|
+
const elProps = {
|
|
1957
|
+
id,
|
|
1958
|
+
className: cc([className, noPanClassName]),
|
|
1959
|
+
style,
|
|
1960
|
+
ariaLabel,
|
|
1961
|
+
};
|
|
1962
|
+
const sourceAndTargetIds = {
|
|
1963
|
+
source,
|
|
1964
|
+
sourcePort,
|
|
1965
|
+
target,
|
|
1966
|
+
targetPort,
|
|
1967
|
+
};
|
|
1968
|
+
const marker = {
|
|
1969
|
+
markerEnd,
|
|
1970
|
+
markerStart,
|
|
1971
|
+
};
|
|
1972
|
+
const labelProps = {
|
|
1973
|
+
label,
|
|
1974
|
+
labelStyle,
|
|
1975
|
+
labelShowBg,
|
|
1976
|
+
labelBgStyle,
|
|
1977
|
+
labelBgPadding,
|
|
1978
|
+
labelBgBorderRadius,
|
|
1979
|
+
};
|
|
1980
|
+
const edgePositions = getEdgePositions(sourceNodeRect, sourcePortInfo, sourcePosition, targetNodeRect, targetPortInfo, targetPosition);
|
|
1981
|
+
const position = {
|
|
1982
|
+
...edgePositions,
|
|
1983
|
+
sourcePosition,
|
|
1984
|
+
targetPosition,
|
|
1985
|
+
};
|
|
1986
|
+
const events = {
|
|
1987
|
+
onClick: onEdgeClick,
|
|
1988
|
+
onDoubleClick: onEdgeDoubleClick,
|
|
1989
|
+
onContextMenu: onEdgeContextMenu,
|
|
1990
|
+
onMouseEnter: onEdgeMouseEnter,
|
|
1991
|
+
onMouseMove: onEdgeMouseMove,
|
|
1992
|
+
onMouseLeave: onEdgeMouseLeave,
|
|
1993
|
+
onEdgeUpdate,
|
|
1994
|
+
onEdgeUpdateStart,
|
|
1995
|
+
onEdgeUpdateEnd,
|
|
1996
|
+
};
|
|
1997
|
+
return (jsx(EdgeComponent, { ...elProps, ...sourceAndTargetIds, ...marker, ...labelProps, ...position, ...events, rfId: rfId, type: edgeType, data: data, isFocusable: isFocusable, edgeUpdaterRadius: edgeUpdaterRadius }, id));
|
|
1998
|
+
}) })] }));
|
|
1999
|
+
}
|
|
2000
|
+
EdgeRenderer.displayName = 'EdgeRenderer';
|
|
2001
|
+
var EdgeRenderer$1 = memo(EdgeRenderer);
|
|
2002
|
+
|
|
2003
|
+
const oppositePosition = {
|
|
2004
|
+
[Position.Left]: Position.Right,
|
|
2005
|
+
[Position.Right]: Position.Left,
|
|
2006
|
+
[Position.Top]: Position.Bottom,
|
|
2007
|
+
[Position.Bottom]: Position.Top,
|
|
2008
|
+
};
|
|
2009
|
+
function ConnectionPath({ nodeId, portType, edge, Component, EdgeWrapper, }) {
|
|
2010
|
+
const { fromNode, toX, toY } = useStore(useCallback((s) => ({
|
|
2011
|
+
fromNode: s.nodeInternals.get(nodeId),
|
|
2012
|
+
toX: (s.connectionPosition.x - s.transform[0]) / s.transform[2],
|
|
2013
|
+
toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2],
|
|
2014
|
+
}), [nodeId]), shallow);
|
|
2015
|
+
const fromPortBounds = fromNode?.[internalsSymbol]?.portBounds;
|
|
2016
|
+
const portBounds = fromPortBounds?.[portType];
|
|
2017
|
+
if (!fromNode || !portBounds) {
|
|
2018
|
+
return null;
|
|
1962
2019
|
}
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
2020
|
+
const fromPort = portBounds[0];
|
|
2021
|
+
const fromPortX = fromPort
|
|
2022
|
+
? fromPort.x + fromPort.width / 2
|
|
2023
|
+
: (fromNode.width ?? 0) / 2;
|
|
2024
|
+
const fromPortY = fromPort
|
|
2025
|
+
? fromPort.y + fromPort.height / 2
|
|
2026
|
+
: fromNode.height ?? 0;
|
|
2027
|
+
const fromX = (fromNode.positionAbsolute?.x ?? 0) + fromPortX;
|
|
2028
|
+
const fromY = (fromNode.positionAbsolute?.y ?? 0) + fromPortY;
|
|
2029
|
+
const fromPosition = fromPort?.position;
|
|
2030
|
+
const toPosition = fromPosition ? oppositePosition[fromPosition] : null;
|
|
2031
|
+
if (!fromPosition || !toPosition) {
|
|
2032
|
+
return null;
|
|
1970
2033
|
}
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
const parentNode = nodeInternals.get(node.parentNode);
|
|
1974
|
-
parentPosition = getNodePositionWithOrigin(parentNode, nodeOrigin).positionAbsolute;
|
|
2034
|
+
if (Component) {
|
|
2035
|
+
return (jsx(Component, { fromNode: fromNode, fromPort: fromPort, fromX: fromX, fromY: fromY, toX: toX, toY: toY, fromPosition: fromPosition, toPosition: toPosition }));
|
|
1975
2036
|
}
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
2037
|
+
return (jsx(EdgeWrapper, { id: edge.id, className: "react-diagram__connection", type: edge.type || 'default', source: edge.source, target: edge.target, isFocusable: false, sourceX: fromX, sourceY: fromY, targetX: toX, targetY: toY, sourcePosition: fromPosition, targetPosition: toPosition }));
|
|
2038
|
+
}
|
|
2039
|
+
ConnectionPath.displayName = 'ConnectionPath';
|
|
2040
|
+
|
|
2041
|
+
const selector$2 = (s) => ({
|
|
2042
|
+
edges: s.edges,
|
|
2043
|
+
nodeId: s.connectionNodeId,
|
|
2044
|
+
portType: s.connectionPortType,
|
|
2045
|
+
});
|
|
2046
|
+
function ConnectionLineRenderer({ containerStyle, edgeTypes, component, }) {
|
|
2047
|
+
const { nodeId, portType, edges } = useStore(selector$2, shallow);
|
|
2048
|
+
const isValid = !!(nodeId && portType);
|
|
2049
|
+
if (!isValid) {
|
|
2050
|
+
return null;
|
|
2051
|
+
}
|
|
2052
|
+
const selectedEdge = edges.find((edge) => edge[portType] === nodeId);
|
|
2053
|
+
if (!selectedEdge)
|
|
2054
|
+
return null;
|
|
2055
|
+
const EdgeWrapper = selectedEdge?.type
|
|
2056
|
+
? edgeTypes[selectedEdge.type]
|
|
2057
|
+
: edgeTypes.default;
|
|
2058
|
+
return (jsx("svg", { style: containerStyle, className: "react-diagram__container react-diagram__connection-line", children: jsx("g", { className: "react-diagram__connection", children: jsx(ConnectionPath, { nodeId: nodeId, portType: portType, edge: selectedEdge, Component: component, EdgeWrapper: EdgeWrapper }) }) }));
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
function DiagramView({ rfId,
|
|
2062
|
+
// DiagramRenderer props
|
|
2063
|
+
noPanClassName, panning, defaultViewport, multiSelectionKeyCode, onMove, onMoveStart, onMoveEnd,
|
|
2064
|
+
// NodeRenderer props
|
|
2065
|
+
onlyRenderVisibleElements, disableKeyboardA11y, noDragClassName, nodeOrigin, nodeTypes, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave,
|
|
2066
|
+
// EdgeRenderer props
|
|
2067
|
+
edgeTypes, edgeUpdaterRadius, onEdgeClick, onEdgeDoubleClick, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd,
|
|
2068
|
+
// ConnectionLineWrapper
|
|
2069
|
+
ConnectionLineContainerStyle, ConnectionLineComponent, }) {
|
|
2070
|
+
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 })] }));
|
|
2071
|
+
}
|
|
2072
|
+
DiagramView.displayName = 'DiagramView';
|
|
2073
|
+
var DiagramView$1 = memo(DiagramView);
|
|
2074
|
+
|
|
2075
|
+
const selector$1 = (s) => {
|
|
2076
|
+
const { setNodes, setEdges, setNodeExtent, setTranslateExtent, setMinZoom, setMaxZoom, } = s;
|
|
1979
2077
|
return {
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
2078
|
+
setNodes,
|
|
2079
|
+
setEdges,
|
|
2080
|
+
setNodeExtent,
|
|
2081
|
+
setTranslateExtent,
|
|
2082
|
+
setMinZoom,
|
|
2083
|
+
setMaxZoom,
|
|
1985
2084
|
};
|
|
2085
|
+
};
|
|
2086
|
+
function useStoreUpdater(value, setStoreState) {
|
|
2087
|
+
useEffect(() => {
|
|
2088
|
+
if (typeof value !== 'undefined') {
|
|
2089
|
+
setStoreState(value);
|
|
2090
|
+
}
|
|
2091
|
+
}, [value]);
|
|
1986
2092
|
}
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
};
|
|
1995
|
-
});
|
|
1996
|
-
return [
|
|
1997
|
-
nodeId
|
|
1998
|
-
? extentedDragItems.find((n) => n.id === nodeId)
|
|
1999
|
-
: extentedDragItems[0],
|
|
2000
|
-
extentedDragItems,
|
|
2001
|
-
];
|
|
2093
|
+
// updates with values in store that don't have a dedicated setter function
|
|
2094
|
+
function useDirectStoreUpdater(key, value, setState) {
|
|
2095
|
+
useEffect(() => {
|
|
2096
|
+
if (typeof value !== 'undefined') {
|
|
2097
|
+
setState({ [key]: value });
|
|
2098
|
+
}
|
|
2099
|
+
}, [value]);
|
|
2002
2100
|
}
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2101
|
+
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, }) => {
|
|
2102
|
+
const { setNodes, setEdges, setNodeExtent, setTranslateExtent, setMinZoom, setMaxZoom, } = useStore(selector$1, shallow);
|
|
2103
|
+
const store = useStoreApi();
|
|
2104
|
+
useStoreUpdater(nodes, setNodes);
|
|
2105
|
+
useStoreUpdater(edges, setEdges);
|
|
2106
|
+
useStoreUpdater(nodeExtent, setNodeExtent);
|
|
2107
|
+
useStoreUpdater(translateExtent, setTranslateExtent);
|
|
2108
|
+
useStoreUpdater(minZoom, setMinZoom);
|
|
2109
|
+
useStoreUpdater(maxZoom, setMaxZoom);
|
|
2110
|
+
useDirectStoreUpdater('smoothStep', smoothStep, store.setState);
|
|
2111
|
+
useDirectStoreUpdater('centerStep', centerStep, store.setState);
|
|
2112
|
+
useDirectStoreUpdater('gridStep', gridStep, store.setState);
|
|
2113
|
+
useDirectStoreUpdater('elevateNodesOnSelect', elevateNodesOnSelect, store.setState);
|
|
2114
|
+
useDirectStoreUpdater('nodesDraggable', nodesDraggable, store.setState);
|
|
2115
|
+
useDirectStoreUpdater('autoPanOnNodeDrag', autoPanOnNodeDrag, store.setState);
|
|
2116
|
+
useDirectStoreUpdater('autoPanOnConnect', autoPanOnConnect, store.setState);
|
|
2117
|
+
useDirectStoreUpdater('connectionRadius', connectionRadius, store.setState);
|
|
2118
|
+
useDirectStoreUpdater('onNodesChange', onNodesChange, store.setState);
|
|
2119
|
+
useDirectStoreUpdater('onNodeDrag', onNodeDrag, store.setState);
|
|
2120
|
+
useDirectStoreUpdater('onNodeDragStart', onNodeDragStart, store.setState);
|
|
2121
|
+
useDirectStoreUpdater('onNodeDragEnd', onNodeDragEnd, store.setState);
|
|
2122
|
+
useDirectStoreUpdater('onEdgesChange', onEdgesChange, store.setState);
|
|
2123
|
+
useDirectStoreUpdater('onConnect', onConnect, store.setState);
|
|
2124
|
+
useDirectStoreUpdater('onConnectStart', onConnectStart, store.setState);
|
|
2125
|
+
useDirectStoreUpdater('onConnectEnd', onConnectEnd, store.setState);
|
|
2126
|
+
useDirectStoreUpdater('onError', onErrorWrapper(onError), store.setState);
|
|
2127
|
+
return null;
|
|
2128
|
+
};
|
|
2129
|
+
|
|
2130
|
+
function useNodeOrEdgeTypes(nodeOrEdgeTypes, createTypes) {
|
|
2131
|
+
const typesKeysRef = useRef(null);
|
|
2132
|
+
const typesParsed = useMemo(() => {
|
|
2133
|
+
if (process.env.NODE_ENV === 'development') {
|
|
2134
|
+
const typeKeys = Object.keys(nodeOrEdgeTypes);
|
|
2135
|
+
if (shallow(typesKeysRef.current, typeKeys)) {
|
|
2136
|
+
devWarn('002');
|
|
2137
|
+
}
|
|
2138
|
+
typesKeysRef.current = typeKeys;
|
|
2139
|
+
}
|
|
2140
|
+
return createTypes(nodeOrEdgeTypes);
|
|
2141
|
+
}, [nodeOrEdgeTypes]);
|
|
2142
|
+
return typesParsed;
|
|
2013
2143
|
}
|
|
2014
2144
|
|
|
2015
|
-
|
|
2145
|
+
const NodeIdContext = createContext(null);
|
|
2146
|
+
const Provider = NodeIdContext.Provider;
|
|
2147
|
+
NodeIdContext.Consumer;
|
|
2148
|
+
const useNodeId = () => {
|
|
2149
|
+
const nodeId = useContext(NodeIdContext);
|
|
2150
|
+
return nodeId;
|
|
2151
|
+
};
|
|
2152
|
+
|
|
2153
|
+
function Port({ type, position }) {
|
|
2016
2154
|
const store = useStoreApi();
|
|
2017
|
-
const
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
const
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
const
|
|
2029
|
-
|
|
2030
|
-
if (
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
x: x - n.distance.x,
|
|
2039
|
-
y: y - n.distance.y,
|
|
2040
|
-
};
|
|
2041
|
-
if (gridStep) {
|
|
2042
|
-
nextPosition.x =
|
|
2043
|
-
gridStep[0] * Math.round(nextPosition.x / gridStep[0]);
|
|
2044
|
-
nextPosition.y =
|
|
2045
|
-
gridStep[1] * Math.round(nextPosition.y / gridStep[1]);
|
|
2046
|
-
}
|
|
2047
|
-
const updatedPos = calcNextPosition(n, nextPosition, nodeInternals, nodeExtent, nodeOrigin, onError);
|
|
2048
|
-
// we want to make sure that we only fire a change event when there is a changes
|
|
2049
|
-
hasChange =
|
|
2050
|
-
hasChange ||
|
|
2051
|
-
n.position.x !== updatedPos.position.x ||
|
|
2052
|
-
n.position.y !== updatedPos.position.y;
|
|
2053
|
-
n.position = updatedPos.position;
|
|
2054
|
-
n.positionAbsolute = updatedPos.positionAbsolute;
|
|
2055
|
-
return n;
|
|
2056
|
-
});
|
|
2057
|
-
if (!hasChange) {
|
|
2058
|
-
return;
|
|
2059
|
-
}
|
|
2060
|
-
updateNodePositions(dragItems.current, true, true);
|
|
2061
|
-
setDragging(true);
|
|
2062
|
-
if (onNodeDrag && dragEvent.current) {
|
|
2063
|
-
const [currentNode, nodes] = getEventHandlerParams({
|
|
2064
|
-
nodeId,
|
|
2065
|
-
dragItems: dragItems.current,
|
|
2066
|
-
nodeInternals,
|
|
2067
|
-
});
|
|
2068
|
-
onNodeDrag(dragEvent.current, currentNode, nodes);
|
|
2069
|
-
}
|
|
2070
|
-
};
|
|
2071
|
-
const autoPan = () => {
|
|
2072
|
-
if (!containerBounds.current) {
|
|
2073
|
-
return;
|
|
2074
|
-
}
|
|
2075
|
-
const [xMovement, yMovement] = calcAutoPanPosition(mousePosition.current, containerBounds.current);
|
|
2076
|
-
if (xMovement !== 0 || yMovement !== 0) {
|
|
2077
|
-
const { transform, panBy } = store.getState();
|
|
2078
|
-
lastPosition.current.x =
|
|
2079
|
-
(lastPosition.current.x ?? 0) - xMovement / transform[2];
|
|
2080
|
-
lastPosition.current.y =
|
|
2081
|
-
(lastPosition.current.y ?? 0) - yMovement / transform[2];
|
|
2082
|
-
updateNodes(lastPosition.current);
|
|
2083
|
-
panBy({ x: xMovement, y: yMovement });
|
|
2084
|
-
}
|
|
2085
|
-
autoPanId.current = requestAnimationFrame(autoPan);
|
|
2086
|
-
};
|
|
2087
|
-
const dragHandle = drag()
|
|
2088
|
-
.on('start', (e) => {
|
|
2089
|
-
// only allow left click
|
|
2090
|
-
if (e.sourceEvent.which !== 1)
|
|
2091
|
-
return;
|
|
2092
|
-
const { nodeInternals, nodesDraggable, domNode, onNodeDragStart, } = store.getState();
|
|
2093
|
-
if (nodeId) {
|
|
2094
|
-
handleNodeClick({
|
|
2095
|
-
id: nodeId,
|
|
2096
|
-
store,
|
|
2097
|
-
nodeRef: nodeRef,
|
|
2098
|
-
isSelectable,
|
|
2099
|
-
});
|
|
2100
|
-
}
|
|
2101
|
-
const pointerPosition = getPointerPosition(e);
|
|
2102
|
-
dragItems.current = getDragItems(nodeInternals, nodesDraggable, pointerPosition, nodeId);
|
|
2103
|
-
if (onNodeDragStart && dragItems.current) {
|
|
2104
|
-
const [currentNode, nodes] = getEventHandlerParams({
|
|
2105
|
-
nodeId,
|
|
2106
|
-
dragItems: dragItems.current,
|
|
2107
|
-
nodeInternals,
|
|
2108
|
-
});
|
|
2109
|
-
onNodeDragStart(e.sourceEvent, currentNode, nodes);
|
|
2110
|
-
}
|
|
2111
|
-
containerBounds.current =
|
|
2112
|
-
domNode?.getBoundingClientRect() || null;
|
|
2113
|
-
mousePosition.current = getEventPosition(e.sourceEvent, containerBounds.current);
|
|
2114
|
-
})
|
|
2115
|
-
.on('drag', (e) => {
|
|
2116
|
-
const pointerPosition = getPointerPosition(e);
|
|
2117
|
-
const { autoPanOnNodeDrag } = store.getState();
|
|
2118
|
-
if (!autoPanStarted.current && autoPanOnNodeDrag) {
|
|
2119
|
-
autoPanStarted.current = true;
|
|
2120
|
-
autoPan();
|
|
2121
|
-
}
|
|
2122
|
-
if ((lastPosition.current.x !== pointerPosition.xSnapped ||
|
|
2123
|
-
lastPosition.current.y !== pointerPosition.ySnapped) &&
|
|
2124
|
-
dragItems.current) {
|
|
2125
|
-
dragEvent.current = e.sourceEvent;
|
|
2126
|
-
mousePosition.current = getEventPosition(e.sourceEvent, containerBounds.current);
|
|
2127
|
-
updateNodes(pointerPosition);
|
|
2128
|
-
}
|
|
2129
|
-
})
|
|
2130
|
-
.on('end', (event) => {
|
|
2131
|
-
setDragging(false);
|
|
2132
|
-
autoPanStarted.current = false;
|
|
2133
|
-
cancelAnimationFrame(autoPanId.current);
|
|
2134
|
-
if (dragItems.current) {
|
|
2135
|
-
const { nodeInternals, updateNodePositions, onNodeDragEnd } = store.getState();
|
|
2136
|
-
updateNodePositions(dragItems.current, false, false);
|
|
2137
|
-
if (onNodeDragEnd) {
|
|
2138
|
-
const [currentNode, nodes] = getEventHandlerParams({
|
|
2139
|
-
nodeId,
|
|
2140
|
-
dragItems: dragItems.current,
|
|
2141
|
-
nodeInternals,
|
|
2142
|
-
});
|
|
2143
|
-
onNodeDragEnd(event.sourceEvent, currentNode, nodes);
|
|
2144
|
-
}
|
|
2145
|
-
}
|
|
2146
|
-
})
|
|
2147
|
-
.filter((event) => {
|
|
2148
|
-
const target = event.target;
|
|
2149
|
-
const isDraggable = (!event.button && !noDragClassName) ||
|
|
2150
|
-
!hasSelector(target, `.${noDragClassName}`, nodeRef);
|
|
2151
|
-
return isDraggable;
|
|
2155
|
+
const nodeId = useNodeId();
|
|
2156
|
+
if (!nodeId)
|
|
2157
|
+
return null;
|
|
2158
|
+
const handleOnConnect = (connection) => {
|
|
2159
|
+
const { defaultEdgeOptions, onConnect } = store.getState();
|
|
2160
|
+
const edgeParams = {
|
|
2161
|
+
...defaultEdgeOptions,
|
|
2162
|
+
...connection,
|
|
2163
|
+
};
|
|
2164
|
+
onConnect?.(edgeParams);
|
|
2165
|
+
};
|
|
2166
|
+
const onPointerDown = (event) => {
|
|
2167
|
+
const isMouseTriggered = isMouseEvent(event);
|
|
2168
|
+
if ((isMouseTriggered && event.button === 0) || !isMouseTriggered) {
|
|
2169
|
+
handlePointerDown({
|
|
2170
|
+
event,
|
|
2171
|
+
nodeId,
|
|
2172
|
+
portType: type,
|
|
2173
|
+
getState: store.getState,
|
|
2174
|
+
setState: store.setState,
|
|
2175
|
+
onConnect: handleOnConnect,
|
|
2152
2176
|
});
|
|
2153
|
-
selection.call(dragHandle);
|
|
2154
|
-
return () => {
|
|
2155
|
-
selection.on('.drag', null);
|
|
2156
|
-
};
|
|
2157
2177
|
}
|
|
2158
|
-
}
|
|
2159
|
-
return
|
|
2178
|
+
};
|
|
2179
|
+
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 }));
|
|
2180
|
+
}
|
|
2181
|
+
Port.displayName = 'Port';
|
|
2182
|
+
var Port$1 = memo(Port);
|
|
2183
|
+
|
|
2184
|
+
function Nodes({ data }) {
|
|
2185
|
+
return (jsxs(Fragment, { children: [jsx(Port$1, { type: "target", position: Position.Top }), data.label, jsx(Port$1, { type: "source", position: Position.Bottom })] }));
|
|
2160
2186
|
}
|
|
2161
2187
|
|
|
2162
2188
|
const wrapNode = (NodeComponent) => {
|
|
@@ -2241,11 +2267,11 @@ const wrapNode = (NodeComponent) => {
|
|
|
2241
2267
|
};
|
|
2242
2268
|
const events = {
|
|
2243
2269
|
onClick: onSelectNodeHandler,
|
|
2244
|
-
onDoubleClick: getMouseHandler(id, store.getState, onDoubleClick),
|
|
2245
|
-
onContextMenu: getMouseHandler(id, store.getState, onContextMenu),
|
|
2246
|
-
onMouseEnter: getMouseHandler(id, store.getState, onMouseEnter),
|
|
2247
|
-
onMouseMove: getMouseHandler(id, store.getState, onMouseMove),
|
|
2248
|
-
onMouseLeave: getMouseHandler(id, store.getState, onMouseLeave),
|
|
2270
|
+
onDoubleClick: getMouseHandler$1(id, store.getState, onDoubleClick),
|
|
2271
|
+
onContextMenu: getMouseHandler$1(id, store.getState, onContextMenu),
|
|
2272
|
+
onMouseEnter: getMouseHandler$1(id, store.getState, onMouseEnter),
|
|
2273
|
+
onMouseMove: getMouseHandler$1(id, store.getState, onMouseMove),
|
|
2274
|
+
onMouseLeave: getMouseHandler$1(id, store.getState, onMouseLeave),
|
|
2249
2275
|
};
|
|
2250
2276
|
const position = {
|
|
2251
2277
|
positionX,
|
|
@@ -2366,11 +2392,13 @@ const initialState = {
|
|
|
2366
2392
|
onNodesChange: null,
|
|
2367
2393
|
domNode: null,
|
|
2368
2394
|
nodeOrigin: [0, 0],
|
|
2395
|
+
smoothStep: false,
|
|
2396
|
+
centerStep: false,
|
|
2369
2397
|
gridStep: undefined,
|
|
2370
|
-
nodesSelectionActive: false,
|
|
2371
2398
|
elevateNodesOnSelect: true,
|
|
2372
2399
|
nodesDraggable: true,
|
|
2373
2400
|
multiSelectionActive: false,
|
|
2401
|
+
selectionBoxActive: false,
|
|
2374
2402
|
d3Zoom: null,
|
|
2375
2403
|
d3Selection: null,
|
|
2376
2404
|
minZoom: 0.5,
|
|
@@ -2445,17 +2473,21 @@ const createRFStore = () => createStore((set, get) => ({
|
|
|
2445
2473
|
onNodesChange?.(changes);
|
|
2446
2474
|
}
|
|
2447
2475
|
},
|
|
2448
|
-
|
|
2476
|
+
updateNodesPosition: (nodes, dragging = false, updateFunc) => {
|
|
2449
2477
|
const { triggerNodeChanges } = get();
|
|
2450
|
-
const changes =
|
|
2478
|
+
const changes = nodes.map((node) => {
|
|
2451
2479
|
const change = {
|
|
2452
2480
|
id: node.id,
|
|
2453
2481
|
type: 'position',
|
|
2454
2482
|
dragging,
|
|
2455
2483
|
};
|
|
2456
|
-
if (
|
|
2457
|
-
|
|
2458
|
-
|
|
2484
|
+
if (updateFunc) {
|
|
2485
|
+
updateFunc(node);
|
|
2486
|
+
return {
|
|
2487
|
+
...change,
|
|
2488
|
+
position: node.position,
|
|
2489
|
+
positionAbsolute: node.positionAbsolute,
|
|
2490
|
+
};
|
|
2459
2491
|
}
|
|
2460
2492
|
return change;
|
|
2461
2493
|
});
|
|
@@ -2578,15 +2610,15 @@ const defaultNodeTypes = {
|
|
|
2578
2610
|
const defaultEdgeTypes = {
|
|
2579
2611
|
step: StepEdge,
|
|
2580
2612
|
};
|
|
2581
|
-
const ReactDiagram = forwardRef(({ id,
|
|
2613
|
+
const ReactDiagram = forwardRef(({ children, id,
|
|
2582
2614
|
// DiagramView props
|
|
2583
2615
|
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,
|
|
2584
2616
|
// StoreUpdater props
|
|
2585
|
-
nodes, edges, nodesDraggable, elevateNodesOnSelect, autoPanOnNodeDrag, autoPanOnConnect, connectionRadius, onNodesChange, onNodeDrag, onNodeDragStart, onNodeDragEnd, onEdgesChange, onConnect, onConnectStart, onConnectEnd, onError, }, ref) => {
|
|
2617
|
+
nodes, edges, nodesDraggable, elevateNodesOnSelect, autoPanOnNodeDrag, autoPanOnConnect, connectionRadius, smoothStep, centerStep, gridStep, onNodesChange, onNodeDrag, onNodeDragStart, onNodeDragEnd, onEdgesChange, onConnect, onConnectStart, onConnectEnd, onError, }, ref) => {
|
|
2586
2618
|
const rfId = id || '1';
|
|
2587
2619
|
const nodeTypesWrapped = useNodeOrEdgeTypes(nodeTypes, createNodeTypes);
|
|
2588
2620
|
const edgeTypesWrapped = useNodeOrEdgeTypes(edgeTypes, createEdgeTypes);
|
|
2589
|
-
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, onNodesChange: onNodesChange, onNodeDrag: onNodeDrag, onNodeDragStart: onNodeDragStart, onNodeDragEnd: onNodeDragEnd, onEdgesChange: onEdgesChange, onConnect: onConnect, onConnectStart: onConnectStart, onConnectEnd: onConnectEnd, onError: onError })] }) }));
|
|
2621
|
+
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] }) }));
|
|
2590
2622
|
});
|
|
2591
2623
|
ReactDiagram.displayName = 'ReactDiagram';
|
|
2592
2624
|
|
|
@@ -2600,4 +2632,35 @@ function createUseItemsState(applyChanges) {
|
|
|
2600
2632
|
const useNodesState = createUseItemsState(applyNodeChanges);
|
|
2601
2633
|
const useEdgesState = createUseItemsState(applyEdgeChanges);
|
|
2602
2634
|
|
|
2603
|
-
|
|
2635
|
+
function LinePath({ color, scaledGap, lineWidth }) {
|
|
2636
|
+
const m1 = `M${scaledGap[0] / 2} 0`;
|
|
2637
|
+
const v = `V${scaledGap[1]}`;
|
|
2638
|
+
const m2 = `M0 ${scaledGap[1] / 2}`;
|
|
2639
|
+
const h = `H${scaledGap[0]}`;
|
|
2640
|
+
const path = `${m1} ${v} ${m2} ${h}`;
|
|
2641
|
+
return jsx("path", { stroke: color, strokeWidth: lineWidth, d: path });
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
const selector = (s) => ({
|
|
2645
|
+
transform: s.transform,
|
|
2646
|
+
rfId: s.rfId,
|
|
2647
|
+
gridStepGap: s.gridStep,
|
|
2648
|
+
});
|
|
2649
|
+
function Background({ gap, lineWidth = 1, color = '#000000', }) {
|
|
2650
|
+
const ref = useRef(null);
|
|
2651
|
+
const { transform, rfId, gridStepGap } = useStore(selector, shallow);
|
|
2652
|
+
const defaultGap = gap ? gap : gridStepGap ? gridStepGap : 50;
|
|
2653
|
+
const gapXY = Array.isArray(defaultGap)
|
|
2654
|
+
? defaultGap
|
|
2655
|
+
: [defaultGap, defaultGap];
|
|
2656
|
+
const scaledGap = [
|
|
2657
|
+
gapXY[0] * transform[2] || 1,
|
|
2658
|
+
gapXY[1] * transform[2] || 1,
|
|
2659
|
+
];
|
|
2660
|
+
const patternOffset = [scaledGap[0] / 2, scaledGap[1] / 2];
|
|
2661
|
+
return (jsxs("svg", { className: "react-diagram__container react-diagram__background", ref: ref, children: [jsx("pattern", { id: `background-${rfId}`, x: transform[0] % scaledGap[0], y: transform[1] % scaledGap[1], width: scaledGap[0], height: scaledGap[1], patternUnits: "userSpaceOnUse", patternTransform: `translate(-${patternOffset[0]},-${patternOffset[1]})`, children: jsx(LinePath, { scaledGap: scaledGap, color: color, lineWidth: lineWidth }) }), jsx("rect", { x: "0", y: "0", width: "100%", height: "100%", fill: `url(#${`background-${rfId}`})` })] }));
|
|
2662
|
+
}
|
|
2663
|
+
Background.displayName = 'Background';
|
|
2664
|
+
var index = memo(Background);
|
|
2665
|
+
|
|
2666
|
+
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 };
|