react-cosmos-diagram 0.7.1 → 0.7.2

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.
@@ -0,0 +1,1811 @@
1
+ "use client"
2
+ import { errorMessages, CosmosPanZoom, CosmosDrag, getRectOfNodes, getEventPosition, getNodesInside, Position, internalsSymbol as internalsSymbol$1, MarkerType, getMarkerId, isNumeric, getStraightPath, getStepPath, getBezierPath, CosmosPort, devWarn, isMouseEvent, clampPosition, getNodePositionWithOrigin, getDimensions, getPortBounds } from 'cosmos-diagram';
3
+ export { MarkerType, Position, addEdge, boxToRect, clamp, getBezierEdgeCenter, getBezierPath, getStepPath, getStraightPath, isCoreEdge, isCoreNode, rectToBox, updateEdge } from 'cosmos-diagram';
4
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
+ import { createContext, useContext, useMemo, useState, useEffect, useRef, memo, useCallback, forwardRef } from 'react';
6
+ import { useStore as useStore$1, createStore } from 'zustand';
7
+ import cc from 'classcat';
8
+ import { shallow } from 'zustand/shallow';
9
+ import { zoomIdentity } from 'd3-zoom';
10
+
11
+ const StoreContext = createContext(null);
12
+ const Provider$1 = StoreContext.Provider;
13
+
14
+ const zustandErrorMessage = errorMessages['001']();
15
+ // 변경 사항이 발생할때 값을 구독
16
+ function useStore(selector, equalityFn) {
17
+ const store = useContext(StoreContext);
18
+ if (store === null) {
19
+ throw new Error(zustandErrorMessage);
20
+ }
21
+ return useStore$1(store, selector, equalityFn);
22
+ }
23
+ // 필요에 따라 값을 계산
24
+ const useStoreApi = () => {
25
+ const store = useContext(StoreContext);
26
+ if (store === null) {
27
+ throw new Error(zustandErrorMessage);
28
+ }
29
+ return useMemo(() => ({
30
+ getState: store.getState,
31
+ setState: store.setState,
32
+ subscribe: store.subscribe,
33
+ destroy: store.destroy,
34
+ }), [store]);
35
+ };
36
+
37
+ const useGlobalKeyHandler = (multiSelectionKeyCode = 'Meta') => {
38
+ const store = useStoreApi();
39
+ const [multiSelectionActivate, setMultiSelectionActivate] = useState(false);
40
+ const handleKeyDown = (e) => {
41
+ if (e.key === multiSelectionKeyCode) {
42
+ setMultiSelectionActivate(true);
43
+ }
44
+ };
45
+ const handleKeyUp = () => {
46
+ setMultiSelectionActivate(false);
47
+ };
48
+ useEffect(() => {
49
+ document.addEventListener('keydown', handleKeyDown);
50
+ document.addEventListener('keyup', handleKeyUp);
51
+ return () => {
52
+ document.removeEventListener('keydown', handleKeyDown);
53
+ document.removeEventListener('keyup', handleKeyUp);
54
+ };
55
+ }, []);
56
+ useEffect(() => {
57
+ store.setState({
58
+ multiSelectionActive: multiSelectionActivate,
59
+ });
60
+ }, [multiSelectionActivate]);
61
+ };
62
+
63
+ const Pane = ({ noPanClassName, panning, selection, minZoom, maxZoom, defaultViewport, translateExtent, children, onMove, onMoveStart, onMoveEnd, }) => {
64
+ const store = useStoreApi();
65
+ const Pane = useRef(null);
66
+ const cosmosPanZoom = useRef();
67
+ useEffect(() => {
68
+ if (!Pane.current)
69
+ return;
70
+ cosmosPanZoom.current = CosmosPanZoom({
71
+ domNode: Pane.current,
72
+ minZoom,
73
+ maxZoom,
74
+ translateExtent,
75
+ viewport: defaultViewport,
76
+ panning,
77
+ onTransformChange: (transform) => {
78
+ store.setState({ transform });
79
+ },
80
+ onPanningChange: (panning) => {
81
+ console.log(panning);
82
+ },
83
+ onPanZoomStart: (event, viewport) => {
84
+ onMoveStart?.(event, viewport);
85
+ console.log('start', viewport);
86
+ },
87
+ onPanZoom: (event, viewport) => {
88
+ onMove?.(event, viewport);
89
+ },
90
+ onPanZoomEnd: (event, viewport) => {
91
+ console.log('end', viewport);
92
+ onMoveEnd?.(event, viewport);
93
+ },
94
+ });
95
+ const { x, y, zoom } = cosmosPanZoom.current.getViewport();
96
+ store.setState({
97
+ // 지워야할 목록
98
+ // d3Zoom: d3ZoomInstance,
99
+ // d3Selection: selection,
100
+ // we need to pass transform because zoom handler is not registered when we set the initial transform
101
+ transform: [x, y, zoom],
102
+ domNode: Pane.current.closest('.react-diagram'),
103
+ });
104
+ return () => {
105
+ cosmosPanZoom.current?.destroy();
106
+ };
107
+ }, []);
108
+ useEffect(() => {
109
+ cosmosPanZoom.current?.update({
110
+ noPanClassName,
111
+ selection,
112
+ });
113
+ }, [noPanClassName, selection]);
114
+ return (jsx("div", { ref: Pane, className: cc([
115
+ 'react-diagram__pane react-diagram__container',
116
+ { selection },
117
+ ]), children: children }));
118
+ };
119
+
120
+ const selector$7 = (s) => `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`;
121
+ function Viewport({ children }) {
122
+ const transform = useStore(selector$7);
123
+ return (jsx("div", { className: "react-diagram__viewport react-diagram__container", style: { transform }, children: children }));
124
+ }
125
+
126
+ function DragBox({ rect }) {
127
+ const { width, height, x, y } = rect;
128
+ if (!width || !height || !x || !y)
129
+ return null;
130
+ return (jsx("div", { className: "react-diagram__drag-box react-diagram__container", style: {
131
+ width,
132
+ height,
133
+ transform: `translate(${x}px, ${y}px)`,
134
+ } }));
135
+ }
136
+
137
+ function getMouseHandler$1(id, getState, handler) {
138
+ return handler === undefined
139
+ ? handler
140
+ : (event) => {
141
+ const node = getState().nodeInternals.get(id);
142
+ handler(event, { ...node });
143
+ };
144
+ }
145
+ function handleNodeClick({ id, store, isSelectable, unselect = false, nodeRef, }) {
146
+ if (!isSelectable)
147
+ return;
148
+ const { addSelectedNodes, unselectNodes, multiSelectionActive, nodeInternals, } = store.getState();
149
+ const node = nodeInternals.get(id);
150
+ store.setState({ selectionBoxActive: false });
151
+ if (!node.selected) {
152
+ addSelectedNodes([id]);
153
+ }
154
+ else if (unselect || (node.selected && multiSelectionActive)) {
155
+ unselectNodes({ nodes: [node] });
156
+ requestAnimationFrame(() => nodeRef?.current?.blur());
157
+ }
158
+ }
159
+
160
+ const useDrag = ({ disabled, nodeRef, nodeId, isSelectable, noDragClassName, }) => {
161
+ const store = useStoreApi();
162
+ const cosmosDrag = useRef();
163
+ const [dragging, setDragging] = useState(false);
164
+ useEffect(() => {
165
+ cosmosDrag.current = CosmosDrag({
166
+ getStore: () => store.getState(),
167
+ onNodeMouseDown: (id) => {
168
+ handleNodeClick({
169
+ id,
170
+ store,
171
+ nodeRef,
172
+ isSelectable,
173
+ });
174
+ },
175
+ onDrag: (e, _, node, nodes) => {
176
+ const { onNodeDrag } = store.getState();
177
+ onNodeDrag?.(e, node, nodes);
178
+ },
179
+ onDragStart: (e, _, node, nodes) => {
180
+ const { onNodeDragStart } = store.getState();
181
+ onNodeDragStart?.(e, node, nodes);
182
+ setDragging(true);
183
+ },
184
+ onDragEnd: (e, _, node, nodes) => {
185
+ const { onNodeDragEnd } = store.getState();
186
+ onNodeDragEnd?.(e, node, nodes);
187
+ setDragging(false);
188
+ },
189
+ });
190
+ }, []);
191
+ useEffect(() => {
192
+ if (disabled) {
193
+ cosmosDrag.current?.destroy();
194
+ }
195
+ else if (nodeRef.current) {
196
+ cosmosDrag.current?.update({
197
+ noDragClassName,
198
+ domNode: nodeRef.current,
199
+ isSelectable,
200
+ nodeId,
201
+ });
202
+ return () => {
203
+ cosmosDrag.current?.destroy();
204
+ };
205
+ }
206
+ }, [noDragClassName, disabled, isSelectable, nodeRef, nodeId]);
207
+ return dragging;
208
+ };
209
+
210
+ function SelectionBox({ rect, transform }) {
211
+ const nodeRef = useRef(null);
212
+ useDrag({ nodeRef });
213
+ const { width, height, x, y } = rect;
214
+ return (jsx("div", { className: cc([
215
+ 'react-diagram__selection-box',
216
+ 'react-diagram__container',
217
+ ]), style: {
218
+ transform,
219
+ }, children: jsx("div", { ref: nodeRef, className: "react-diagram__selection-box-rect", tabIndex: -1, style: {
220
+ width,
221
+ height,
222
+ top: y,
223
+ left: x,
224
+ } }) }));
225
+ }
226
+ var SelectionBox$1 = memo(SelectionBox);
227
+
228
+ const handleParentExpand = (res, updateItem) => {
229
+ const parent = res.find((e) => e.id === updateItem.parentNode);
230
+ if (parent) {
231
+ const extendWidth = updateItem.position.x + updateItem.width - parent.width;
232
+ const extendHeight = updateItem.position.y + updateItem.height - parent.height;
233
+ if (extendWidth > 0 ||
234
+ extendHeight > 0 ||
235
+ updateItem.position.x < 0 ||
236
+ updateItem.position.y < 0) {
237
+ parent.style = { ...parent.style };
238
+ parent.style.width = parent.style.width ?? parent.width;
239
+ parent.style.height = parent.style.height ?? parent.height;
240
+ if (extendWidth > 0) {
241
+ parent.style.width += extendWidth;
242
+ }
243
+ if (extendHeight > 0) {
244
+ parent.style.height += extendHeight;
245
+ }
246
+ if (updateItem.position.x < 0) {
247
+ const xDiff = Math.abs(updateItem.position.x);
248
+ parent.position.x = parent.position.x - xDiff;
249
+ parent.style.width += xDiff;
250
+ updateItem.position.x = 0;
251
+ }
252
+ if (updateItem.position.y < 0) {
253
+ const yDiff = Math.abs(updateItem.position.y);
254
+ parent.position.y = parent.position.y - yDiff;
255
+ parent.style.height += yDiff;
256
+ updateItem.position.y = 0;
257
+ }
258
+ parent.width = parent.style.width;
259
+ parent.height = parent.style.height;
260
+ }
261
+ }
262
+ };
263
+ const applyChanges = (changes, elements) => {
264
+ // we need this hack to handle the setNodes and setEdges function of the useReactDiagram hook for controlled flows
265
+ if (changes.some((c) => c.type === 'reset')) {
266
+ return changes.filter((c) => c.type === 'reset').map((c) => c.item);
267
+ }
268
+ const initElements = changes
269
+ .filter((c) => c.type === 'add')
270
+ .map((c) => c.item);
271
+ return elements.reduce((res, item) => {
272
+ const currentChanges = changes.filter((c) => c.id === item.id);
273
+ if (currentChanges.length === 0) {
274
+ res.push(item);
275
+ return res;
276
+ }
277
+ const updateItem = { ...item };
278
+ for (const currentChange of currentChanges) {
279
+ if (currentChange) {
280
+ switch (currentChange.type) {
281
+ case 'select': {
282
+ updateItem.selected = currentChange.selected;
283
+ break;
284
+ }
285
+ case 'position': {
286
+ if (typeof currentChange.position !== 'undefined') {
287
+ updateItem.position = currentChange.position;
288
+ }
289
+ if (typeof currentChange.positionAbsolute !== 'undefined') {
290
+ updateItem.positionAbsolute =
291
+ currentChange.positionAbsolute;
292
+ }
293
+ if (typeof currentChange.dragging !== 'undefined') {
294
+ updateItem.dragging = currentChange.dragging;
295
+ }
296
+ if (updateItem.expandParent) {
297
+ handleParentExpand(res, updateItem);
298
+ }
299
+ break;
300
+ }
301
+ case 'dimensions': {
302
+ if (typeof currentChange.dimensions !== 'undefined') {
303
+ updateItem.width = currentChange.dimensions.width;
304
+ updateItem.height = currentChange.dimensions.height;
305
+ }
306
+ if (typeof currentChange.updateStyle !== 'undefined') {
307
+ updateItem.style = {
308
+ ...(updateItem.style || {}),
309
+ ...currentChange.dimensions,
310
+ };
311
+ }
312
+ if (typeof currentChange.resizing === 'boolean') {
313
+ updateItem.resizing = currentChange.resizing;
314
+ }
315
+ if (updateItem.expandParent) {
316
+ handleParentExpand(res, updateItem);
317
+ }
318
+ break;
319
+ }
320
+ case 'intersect': {
321
+ updateItem.intersected = currentChange.intersected;
322
+ break;
323
+ }
324
+ case 'remove': {
325
+ return res;
326
+ }
327
+ }
328
+ }
329
+ }
330
+ res.push(updateItem);
331
+ return res;
332
+ }, initElements);
333
+ };
334
+ function applyNodeChanges(changes, nodes) {
335
+ return applyChanges(changes, nodes);
336
+ }
337
+ function applyEdgeChanges(changes, edges) {
338
+ return applyChanges(changes, edges);
339
+ }
340
+ const createSelectionChange = (id, selected) => ({
341
+ id,
342
+ type: 'select',
343
+ selected,
344
+ });
345
+ function getSelectionChanges(items, selectedIds) {
346
+ return items.reduce((res, item) => {
347
+ const willBeSelected = selectedIds.includes(item.id);
348
+ if (!item.selected && willBeSelected) {
349
+ item.selected = true;
350
+ res.push(createSelectionChange(item.id, true));
351
+ }
352
+ else if (item.selected && !willBeSelected) {
353
+ item.selected = false;
354
+ res.push(createSelectionChange(item.id, false));
355
+ }
356
+ return res;
357
+ }, []);
358
+ }
359
+
360
+ const selector$6 = (s) => {
361
+ const { elementsSelectable, transform, selectionBoxActive, getNodes } = s;
362
+ const selectedNodes = getNodes().filter((n) => n.selected);
363
+ return {
364
+ elementsSelectable,
365
+ selectionBoxRect: getRectOfNodes(selectedNodes, s.nodeOrigin),
366
+ transformString: `translate(${transform[0]}px,${transform[1]}px) scale(${transform[2]})`,
367
+ selectionBoxActive,
368
+ };
369
+ };
370
+ function DragSelection({ dragSelectionKeyPressed, children, }) {
371
+ const store = useStoreApi();
372
+ const dragSelection = useRef(null);
373
+ const prevSelectedNodesCount = useRef(0);
374
+ const containerBounds = useRef();
375
+ const { elementsSelectable, selectionBoxRect, transformString, selectionBoxActive, } = useStore(selector$6, shallow);
376
+ const [dragBoxStartPosition, setDragBoxStartPosition] = useState({
377
+ x: 0,
378
+ y: 0,
379
+ });
380
+ const [dragBoxRect, setDragBoxRect] = useState({
381
+ width: 0,
382
+ height: 0,
383
+ x: 0,
384
+ y: 0,
385
+ });
386
+ const [dragBoxActive, setDragBoxActive] = useState(false);
387
+ const resetDragBox = () => {
388
+ store.setState({
389
+ selectionBoxActive: prevSelectedNodesCount.current > 0,
390
+ });
391
+ setDragBoxStartPosition({
392
+ x: 0,
393
+ y: 0,
394
+ });
395
+ setDragBoxRect({
396
+ width: 0,
397
+ height: 0,
398
+ x: 0,
399
+ y: 0,
400
+ });
401
+ setDragBoxActive(false);
402
+ };
403
+ const onClick = (e) => {
404
+ if (e.target === dragSelection.current) {
405
+ store.getState().resetSelectedElements();
406
+ store.setState({
407
+ selectionBoxActive: false,
408
+ });
409
+ setDragBoxActive(false);
410
+ }
411
+ };
412
+ const onMouseDown = (event) => {
413
+ const { resetSelectedElements, domNode } = store.getState();
414
+ containerBounds.current = domNode?.getBoundingClientRect();
415
+ if (!elementsSelectable ||
416
+ event.button !== 0 ||
417
+ event.target !== dragSelection.current ||
418
+ !containerBounds.current ||
419
+ !dragSelectionKeyPressed) {
420
+ return;
421
+ }
422
+ const { x, y } = getEventPosition(event.nativeEvent, containerBounds.current);
423
+ resetSelectedElements();
424
+ setDragBoxRect({
425
+ width: 0,
426
+ height: 0,
427
+ x,
428
+ y,
429
+ });
430
+ setDragBoxStartPosition({
431
+ x,
432
+ y,
433
+ });
434
+ };
435
+ const onMouseMove = (event) => {
436
+ const { nodeInternals, transform, nodeOrigin, getNodes, onNodesChange } = store.getState();
437
+ const hasDragBoxStartPosition = dragBoxStartPosition.x > 0 && dragBoxStartPosition.y > 0;
438
+ if (
439
+ // !hasDragBoxPosition ||
440
+ // !dragSelectionKeyPressed ||
441
+ !hasDragBoxStartPosition ||
442
+ !containerBounds.current) {
443
+ return;
444
+ }
445
+ store.setState({
446
+ selectionBoxActive: false,
447
+ });
448
+ setDragBoxActive(true);
449
+ const mousePos = getEventPosition(event.nativeEvent, containerBounds.current);
450
+ const startX = dragBoxStartPosition.x ?? 0;
451
+ const startY = dragBoxStartPosition.y ?? 0;
452
+ const rect = {
453
+ x: mousePos.x < startX ? mousePos.x : startX,
454
+ y: mousePos.y < startY ? mousePos.y : startY,
455
+ width: Math.abs(mousePos.x - startX),
456
+ height: Math.abs(mousePos.y - startY),
457
+ };
458
+ const nodes = getNodes();
459
+ const selectedNodes = getNodesInside(nodeInternals, rect, transform, false, true, nodeOrigin);
460
+ const selectedNodeIds = selectedNodes.map((n) => n.id);
461
+ if (prevSelectedNodesCount.current !== selectedNodeIds.length) {
462
+ prevSelectedNodesCount.current = selectedNodeIds.length;
463
+ const changes = getSelectionChanges(nodes, selectedNodeIds);
464
+ if (changes.length) {
465
+ onNodesChange?.(changes);
466
+ }
467
+ }
468
+ setDragBoxRect(rect);
469
+ };
470
+ const onMouseUp = (event) => {
471
+ if (event.button !== 0) {
472
+ return;
473
+ }
474
+ resetDragBox();
475
+ };
476
+ const onMouseLeave = () => {
477
+ resetDragBox();
478
+ };
479
+ const isPossibleDragSelection = elementsSelectable;
480
+ return (jsxs("div", { ref: dragSelection, className: cc([
481
+ 'react-diagram__container react-diagram__drag-selection',
482
+ ]), onClick: onClick, onMouseDown: isPossibleDragSelection ? onMouseDown : undefined, onMouseMove: isPossibleDragSelection ? onMouseMove : undefined, onMouseUp: elementsSelectable ? onMouseUp : undefined, onMouseLeave: isPossibleDragSelection ? onMouseLeave : undefined, children: [children, dragBoxActive && jsx(DragBox, { rect: dragBoxRect }), selectionBoxActive && (jsx(SelectionBox$1, { rect: selectionBoxRect, transform: transformString }))] }));
483
+ }
484
+
485
+ const useDragSelectionKeyPress = (dragSelectionKeyCode) => {
486
+ const [dragSelectionKeyPressed, setDragSelectionKeyPressed] = useState(false);
487
+ // useKeyPress
488
+ const handleKeyDown = (e) => {
489
+ if (e.key === dragSelectionKeyCode) {
490
+ setDragSelectionKeyPressed(true);
491
+ }
492
+ };
493
+ const handleKeyUp = () => {
494
+ setDragSelectionKeyPressed(false);
495
+ };
496
+ useEffect(() => {
497
+ document.addEventListener('keydown', handleKeyDown);
498
+ document.addEventListener('keyup', handleKeyUp);
499
+ return () => {
500
+ document.removeEventListener('keydown', handleKeyDown);
501
+ document.removeEventListener('keyup', handleKeyUp);
502
+ };
503
+ }, []);
504
+ return dragSelectionKeyPressed;
505
+ };
506
+
507
+ const selector$5 = (s) => {
508
+ const { minZoom, maxZoom, translateExtent } = s;
509
+ return {
510
+ minZoom,
511
+ maxZoom,
512
+ translateExtent,
513
+ };
514
+ };
515
+ function DiagramRenderer({ children, multiSelectionKeyCode, dragSelectionKeyCode, noPanClassName, panning, defaultViewport, onMove, onMoveStart, onMoveEnd, }) {
516
+ const { minZoom, maxZoom, translateExtent } = useStore(selector$5);
517
+ useGlobalKeyHandler(multiSelectionKeyCode);
518
+ const dragSelectionKeyPressed = useDragSelectionKeyPress(dragSelectionKeyCode);
519
+ // useKeyPress
520
+ const isSelecting = dragSelectionKeyPressed;
521
+ const isPanning = panning && !isSelecting;
522
+ return (jsx(Fragment, { children: jsx(Pane, { noPanClassName: noPanClassName, panning: isPanning, selection: isSelecting, minZoom: minZoom, maxZoom: maxZoom, translateExtent: translateExtent, defaultViewport: defaultViewport, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, children: jsx(DragSelection, { dragSelectionKeyPressed: dragSelectionKeyPressed, children: jsx(Viewport, { children: children }) }) }) }));
523
+ }
524
+ DiagramRenderer.displayName = 'DiagramRenderer';
525
+ var DiagramRenderer$1 = memo(DiagramRenderer);
526
+
527
+ function useVisibleNodes() {
528
+ const nodes = useStore(useCallback((s) => s.getNodes(), []));
529
+ return nodes;
530
+ }
531
+
532
+ const selector$4 = (s) => ({
533
+ nodesDraggable: s.nodesDraggable,
534
+ elementsSelectable: s.elementsSelectable,
535
+ updateNodeDimensions: s.updateNodeDimensions,
536
+ onError: s.onError,
537
+ });
538
+ function NodeRenderer({ nodeTypes, onNodeClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onNodeDoubleClick, ...props }) {
539
+ const { nodesDraggable, elementsSelectable, updateNodeDimensions, onError } = useStore(selector$4, shallow);
540
+ const nodes = useVisibleNodes();
541
+ const resizeObserverRef = useRef();
542
+ const resizeObserver = useMemo(() => {
543
+ if (typeof ResizeObserver === 'undefined') {
544
+ return null;
545
+ }
546
+ const observer = new ResizeObserver((entries) => {
547
+ const updates = entries.map((entry) => ({
548
+ id: entry.target.getAttribute('data-id'),
549
+ nodeElement: entry.target,
550
+ forceUpdate: true,
551
+ }));
552
+ updateNodeDimensions(updates);
553
+ });
554
+ resizeObserverRef.current = observer;
555
+ return observer;
556
+ }, []);
557
+ useEffect(() => () => {
558
+ resizeObserverRef?.current?.disconnect();
559
+ }, []);
560
+ return (jsx("div", { className: "react-diagram__nodes react-diagram__container", children: nodes.map((node) => {
561
+ const { data, type,
562
+ // elProps
563
+ id, className, style, width, height, ariaLabel, positionAbsolute, hidden, selected, selectable, draggable, intersected, } = node;
564
+ let nodeType = type || 'default';
565
+ if (!nodeTypes[nodeType]) {
566
+ onError?.('010', nodeType);
567
+ nodeType = 'default';
568
+ }
569
+ const NodeComponent = (nodeTypes[nodeType] ||
570
+ nodeTypes.default);
571
+ const isDraggable = !!(draggable ||
572
+ (nodesDraggable && typeof draggable === 'undefined'));
573
+ const isSelectable = !!(selectable ||
574
+ (elementsSelectable && typeof selectable === 'undefined'));
575
+ const elProps = {
576
+ id,
577
+ className,
578
+ style,
579
+ width: nodeType === 'default' && width ? 120 : undefined,
580
+ height: nodeType === 'default' && height ? 60 : undefined,
581
+ ariaLabel,
582
+ };
583
+ const events = {
584
+ onClick: onNodeClick,
585
+ onMouseEnter: onNodeMouseEnter,
586
+ onMouseMove: onNodeMouseMove,
587
+ onMouseLeave: onNodeMouseLeave,
588
+ onContextMenu: onNodeContextMenu,
589
+ onDoubleClick: onNodeDoubleClick,
590
+ };
591
+ const position = {
592
+ positionX: positionAbsolute?.x || 0,
593
+ positionY: positionAbsolute?.y || 0,
594
+ sourcePosition: Position.Bottom,
595
+ targetPosition: Position.Top,
596
+ };
597
+ const booleanProps = {
598
+ selected: !!selected,
599
+ intersected: !!intersected,
600
+ isSelectable,
601
+ isDraggable,
602
+ hidden,
603
+ isParent: !!node[internalsSymbol$1]?.isParent,
604
+ initialized: !!node.width && !!node.height,
605
+ };
606
+ return (jsx(NodeComponent, { ...props, ...elProps, ...position, ...events, ...booleanProps, zIndex: node[internalsSymbol$1]?.z ?? 0, type: nodeType, data: data, resizeObserver: resizeObserver }, id));
607
+ }) }));
608
+ }
609
+ NodeRenderer.displayName = 'NodeRenderer';
610
+ var NodeRenderer$1 = memo(NodeRenderer);
611
+
612
+ 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" }));
613
+ const MarkerSymbols = {
614
+ [MarkerType.Arrow]: ArrowSymbol,
615
+ };
616
+ function useMarkerSymbol(type) {
617
+ const store = useStoreApi();
618
+ const symbol = useMemo(() => {
619
+ const symbolExists = Object.prototype.hasOwnProperty.call(MarkerSymbols, type);
620
+ if (!symbolExists) {
621
+ store.getState().onError?.('022', type);
622
+ return null;
623
+ }
624
+ return MarkerSymbols[type];
625
+ }, [type]);
626
+ return symbol;
627
+ }
628
+
629
+ const Marker = ({ id, type, color, width = 12.5, height = 12.5, markerUnits = 'strokeWidth', strokeWidth, orient = 'auto-start-reverse', }) => {
630
+ const Symbol = useMarkerSymbol(type);
631
+ if (!Symbol) {
632
+ return null;
633
+ }
634
+ return (jsx("marker", { className: "react-diagram__arrowhead", id: id, markerWidth: `${width}`, markerHeight: `${height}`, viewBox: "-10 -10 20 20", markerUnits: markerUnits, orient: orient, refX: "0", refY: "0", children: jsx(Symbol, { color: color, strokeWidth: strokeWidth }) }));
635
+ };
636
+ const markerSelector = ({ defaultColor, rfId }) => (s) => {
637
+ const ids = [];
638
+ return s.edges
639
+ .reduce((markers, edge) => {
640
+ [edge.markerStart, edge.markerEnd].forEach((marker) => {
641
+ if (marker && typeof marker === 'object') {
642
+ const markerId = getMarkerId(marker, rfId);
643
+ if (!ids.includes(markerId)) {
644
+ markers.push({
645
+ id: markerId,
646
+ color: marker.color || defaultColor,
647
+ ...marker,
648
+ });
649
+ ids.push(markerId);
650
+ }
651
+ }
652
+ });
653
+ return markers;
654
+ }, [])
655
+ .sort((a, b) => a.id.localeCompare(b.id));
656
+ };
657
+ const MarkerComponent = ({ defaultColor, rfId }) => {
658
+ const markers = useStore(useCallback(markerSelector({ defaultColor, rfId }), [defaultColor, rfId]), (a, b) => !(a.length !== b.length ||
659
+ a.some((marker, i) => marker.id !== b[i].id)));
660
+ return (jsx("defs", { children: markers.map((marker) => (jsx(Marker, { id: marker.id, type: marker.type, color: marker.color, width: marker.width, height: marker.height, markerUnits: marker.markerUnits, strokeWidth: marker.strokeWidth, orient: marker.orient }, marker.id))) }));
661
+ };
662
+ MarkerComponent.displayName = 'MarkerComponent';
663
+ var MarkerComponent$1 = memo(MarkerComponent);
664
+
665
+ function EdgeLabel({ x, y, label, labelStyle = {}, labelShowBg = true, labelBgStyle = {}, labelBgPadding = [2, 4], labelBgBorderRadius = 2, children, className, ...rest }) {
666
+ const edgeRef = useRef(null);
667
+ const [edgeLabelBox, setEdgeLabelBox] = useState({
668
+ x: 0,
669
+ y: 0,
670
+ width: 0,
671
+ height: 0,
672
+ });
673
+ const edgeTextClasses = cc(['react-diagram__edge-text-wrapper', className]);
674
+ useEffect(() => {
675
+ if (edgeRef.current) {
676
+ const textBbox = edgeRef.current.getBBox();
677
+ setEdgeLabelBox({
678
+ x: textBbox.x,
679
+ y: textBbox.y,
680
+ width: textBbox.width,
681
+ height: textBbox.height,
682
+ });
683
+ }
684
+ }, [label]);
685
+ if (typeof label === 'undefined' || !label) {
686
+ return null;
687
+ }
688
+ return (jsxs("g", { transform: `translate(${x - edgeLabelBox.width / 2} ${y - edgeLabelBox.height / 2})`, className: edgeTextClasses, visibility: edgeLabelBox.width ? 'visible' : 'hidden', ...rest, children: [labelShowBg && (jsx("rect", { width: edgeLabelBox.width + 2 * labelBgPadding[0], x: -labelBgPadding[0], y: -labelBgPadding[1], height: edgeLabelBox.height + 2 * labelBgPadding[1], className: "react-diagram__edge-text-bg", style: labelBgStyle, rx: labelBgBorderRadius, ry: labelBgBorderRadius })), jsx("text", { className: "react-diagram__edge-text", y: edgeLabelBox.height / 2, dy: "0.3em", ref: edgeRef, style: labelStyle, children: label }), children] }));
689
+ }
690
+ var EdgeLabel$1 = memo(EdgeLabel);
691
+
692
+ function BaseEdge({ path, labelX, labelY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, }) {
693
+ return (jsxs(Fragment, { children: [jsx("path", { style: style, d: path, fill: "none", className: "react-diagram__edge-path", markerEnd: markerEnd, markerStart: markerStart }), label && isNumeric(labelX) && isNumeric(labelY) ? (jsx(EdgeLabel$1, { x: labelX, y: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius })) : null] }));
694
+ }
695
+ BaseEdge.displayName = 'BaseEdge';
696
+
697
+ const StraightEdge = memo(({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, }) => {
698
+ const [path, labelX, labelY] = getStraightPath({
699
+ sourceX,
700
+ sourceY,
701
+ targetX,
702
+ targetY,
703
+ });
704
+ return (jsx(BaseEdge, { path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart }));
705
+ });
706
+ StraightEdge.displayName = 'StraightEdge';
707
+
708
+ const StepEdge = memo(({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, sourcePosition = Position.Bottom, targetPosition = Position.Top, markerEnd, markerStart, pathOptions, }) => {
709
+ const [path, labelX, labelY] = getStepPath({
710
+ sourceX,
711
+ sourceY,
712
+ sourcePosition,
713
+ targetX,
714
+ targetY,
715
+ targetPosition,
716
+ borderRadius: pathOptions?.borderRadius,
717
+ offset: pathOptions?.offset,
718
+ });
719
+ return (jsx(BaseEdge, { path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart }));
720
+ });
721
+ StepEdge.displayName = 'StepEdge';
722
+
723
+ const BezierEdge = memo(({ sourceX, sourceY, targetX, targetY, sourcePosition = Position.Bottom, targetPosition = Position.Top, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, pathOptions, }) => {
724
+ const [path, labelX, labelY] = getBezierPath({
725
+ sourceX,
726
+ sourceY,
727
+ sourcePosition,
728
+ targetX,
729
+ targetY,
730
+ targetPosition,
731
+ curvature: pathOptions?.curvature,
732
+ });
733
+ return (jsx(BaseEdge, { path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart }));
734
+ });
735
+ BezierEdge.displayName = 'BezierEdge';
736
+
737
+ const ARIA_NODE_DESC_KEY = 'react-diagram__node-desc';
738
+ const ARIA_EDGE_DESC_KEY = 'react-diagram__edge-desc';
739
+
740
+ const portPositionX = (x, shift, position) => {
741
+ if (position === Position.Left)
742
+ return x - shift;
743
+ if (position === Position.Right)
744
+ return x + shift;
745
+ return x;
746
+ };
747
+ const portPositionY = (y, shift, position) => {
748
+ if (position === Position.Top)
749
+ return y - shift;
750
+ if (position === Position.Bottom)
751
+ return y + shift;
752
+ return y;
753
+ };
754
+ const EdgeUpdaterClassName = 'react-diagram__edge-updater';
755
+ function Anchor({ position, centerX, centerY, radius = 10, onMouseDown,
756
+ // onMouseEnter,
757
+ // onMouseOut,
758
+ type, }) {
759
+ return (jsx("circle", { className: cc([
760
+ EdgeUpdaterClassName,
761
+ `${EdgeUpdaterClassName}-${type}`,
762
+ ]), cx: portPositionX(centerX, radius, position), cy: portPositionY(centerY, radius, position), r: radius, stroke: "transparent", fill: "transparent", onMouseDown: onMouseDown }));
763
+ }
764
+
765
+ function getMouseHandler(id, getState, handler) {
766
+ return handler === undefined
767
+ ? handler
768
+ : (event) => {
769
+ const edge = getState().edges.find((e) => e.id === id);
770
+ if (edge) {
771
+ handler(event, { ...edge });
772
+ }
773
+ };
774
+ }
775
+ const wrapEdge = (EdgeComponent) => {
776
+ const EdgeWrapper = (props) => {
777
+ const { id, className, style, type, data, rfId, ariaLabel,
778
+ // sourceAndTargetIds
779
+ source, sourcePort, target, targetPort,
780
+ // marker
781
+ markerEnd, markerStart,
782
+ // labelProps
783
+ label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius,
784
+ // AnchorProps
785
+ edgeUpdaterRadius,
786
+ // position
787
+ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, selected, elementsSelectable, hidden, isFocusable, onClick, onDoubleClick, onContextMenu, onMouseEnter, onMouseMove, onMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, } = props;
788
+ const position = {
789
+ sourceX,
790
+ sourceY,
791
+ targetX,
792
+ targetY,
793
+ sourcePosition,
794
+ targetPosition,
795
+ };
796
+ const sourceAndTargetIds = {
797
+ source,
798
+ sourcePort,
799
+ target,
800
+ targetPort,
801
+ };
802
+ const isConnecting = className === 'react-diagram__connection';
803
+ if (isConnecting) {
804
+ document
805
+ .querySelector('path')
806
+ ?.classList.add('react-diagram__connection-path');
807
+ return (jsx(EdgeComponent, { ...sourceAndTargetIds, ...position, id: id, data: data, style: style, selected: selected }));
808
+ }
809
+ const store = useStoreApi();
810
+ const edgeRef = useRef(null);
811
+ const [updating, setUpdating] = useState(false);
812
+ const markerStartUrl = useMemo(() => `url(#${getMarkerId(markerStart, rfId)})`, [markerStart, rfId]);
813
+ const markerEndUrl = useMemo(() => `url(#${getMarkerId(markerEnd, rfId)})`, [markerEnd, rfId]);
814
+ if (hidden) {
815
+ return null;
816
+ }
817
+ const handleEdgeUpdater = (fromPortType) => (event) => {
818
+ if (event.button !== 0) {
819
+ return;
820
+ }
821
+ const { edges, domNode, autoPanOnConnect, connectionRadius, transform, getNodes, cancelConnection, updateConnection, onConnectStart, onConnectEnd, panBy, } = store.getState();
822
+ const nodeId = props[fromPortType];
823
+ const edge = edges.find((e) => e.id === id);
824
+ const portId = (fromPortType === 'source' ? sourcePort : targetPort) || null;
825
+ setUpdating(true);
826
+ onEdgeUpdateStart?.(event, edge, fromPortType);
827
+ const onConnectEdge = (connection) => onEdgeUpdate?.(edge, connection);
828
+ const handleEdgeUpdateEnd = (evt) => {
829
+ setUpdating(false);
830
+ onEdgeUpdateEnd?.(evt, edge, fromPortType);
831
+ };
832
+ CosmosPort.onPointerDown({
833
+ isAnchor: true,
834
+ event: event.nativeEvent,
835
+ nodeId,
836
+ portId,
837
+ portType: fromPortType,
838
+ domNode,
839
+ autoPanOnConnect,
840
+ connectionRadius,
841
+ nodes: getNodes(),
842
+ onEdgeUpdateEnd: handleEdgeUpdateEnd,
843
+ cancelConnection,
844
+ updateConnection,
845
+ onConnect: onConnectEdge,
846
+ onConnectStart,
847
+ onConnectEnd,
848
+ panBy,
849
+ getTransform: () => transform,
850
+ });
851
+ };
852
+ const onEdgeClick = (event) => {
853
+ const { edges } = store.getState();
854
+ if (onClick) {
855
+ const edge = edges.find((e) => e.id === id);
856
+ onClick(event, edge);
857
+ }
858
+ };
859
+ const onEdgeDoubleClick = getMouseHandler(id, store.getState, onDoubleClick);
860
+ const onEdgeContextMenu = getMouseHandler(id, store.getState, onContextMenu);
861
+ const onEdgeMouseEnter = getMouseHandler(id, store.getState, onMouseEnter);
862
+ const onEdgeMouseMove = getMouseHandler(id, store.getState, onMouseMove);
863
+ const onEdgeMouseLeave = getMouseHandler(id, store.getState, onMouseLeave);
864
+ const inactive = !elementsSelectable;
865
+ const wrapperClassName = cc([
866
+ 'react-diagram__edge',
867
+ `react-diagram__edge-${type}`,
868
+ className,
869
+ { selected, inactive },
870
+ ]);
871
+ const marker = { markerStart: markerStartUrl, markerEnd: markerEndUrl };
872
+ const labelProps = {
873
+ label,
874
+ labelStyle,
875
+ labelShowBg,
876
+ labelBgStyle,
877
+ labelBgPadding,
878
+ labelBgBorderRadius,
879
+ };
880
+ const events = {
881
+ onClick: onEdgeClick,
882
+ onDoubleClick: onEdgeDoubleClick,
883
+ onContextMenu: onEdgeContextMenu,
884
+ onMouseEnter: onEdgeMouseEnter,
885
+ onMouseMove: onEdgeMouseMove,
886
+ onMouseLeave: onEdgeMouseLeave,
887
+ };
888
+ return (jsx("g", { ...events, ref: edgeRef, className: wrapperClassName, tabIndex: isFocusable ? 0 : undefined, role: isFocusable ? 'button' : undefined, "aria-label": ariaLabel === null
889
+ ? undefined
890
+ : ariaLabel
891
+ ? ariaLabel
892
+ : `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'),
893
+ // onMouseEnter={console.log}
894
+ // onMouseOut={console.log}
895
+ type: "source" }), jsx(Anchor, { position: targetPosition, centerX: targetX, centerY: targetY, radius: edgeUpdaterRadius, onMouseDown: handleEdgeUpdater('source'),
896
+ // onMouseEnter={console.log}
897
+ // onMouseOut={console.log}
898
+ type: "target" })] })) }));
899
+ };
900
+ EdgeWrapper.displayName = 'EdgeWrapper';
901
+ return memo(EdgeWrapper);
902
+ };
903
+
904
+ const createEdgeTypes = (edgeTypes) => {
905
+ const defaultTypes = {
906
+ default: wrapEdge((edgeTypes.straight || StraightEdge)),
907
+ step: wrapEdge((edgeTypes.step || StepEdge)),
908
+ bezier: wrapEdge((edgeTypes.bezier || BezierEdge)),
909
+ };
910
+ const wrappedTypes = {};
911
+ const customTypes = Object.keys(edgeTypes)
912
+ .filter((k) => !Object.keys(defaultTypes).includes(k))
913
+ .reduce((res, key) => {
914
+ res[key] = wrapEdge((edgeTypes[key] || StepEdge));
915
+ return res;
916
+ }, wrappedTypes);
917
+ return {
918
+ ...defaultTypes,
919
+ ...customTypes,
920
+ };
921
+ };
922
+ function getPortPosition(position, nodeRect, port = null) {
923
+ const x = (port?.x || 0) + nodeRect.x;
924
+ const y = (port?.y || 0) + nodeRect.y;
925
+ const width = port?.width || nodeRect.width;
926
+ const height = port?.height || nodeRect.height;
927
+ switch (position) {
928
+ case Position.Top:
929
+ return {
930
+ x: x + width / 2,
931
+ y,
932
+ };
933
+ case Position.Right:
934
+ return {
935
+ x: x + width,
936
+ y: y + height / 2,
937
+ };
938
+ case Position.Bottom:
939
+ return {
940
+ x: x + width / 2,
941
+ y: y + height,
942
+ };
943
+ case Position.Left:
944
+ return {
945
+ x,
946
+ y: y + height / 2,
947
+ };
948
+ }
949
+ }
950
+ function getPort(bounds, portId) {
951
+ if (!bounds) {
952
+ return null;
953
+ }
954
+ if (bounds.length === 1 || !portId) {
955
+ return bounds[0];
956
+ }
957
+ else if (portId) {
958
+ return bounds.find((d) => d.id === portId) || null;
959
+ }
960
+ return null;
961
+ }
962
+ const getEdgePositions = (sourceNodeRect, sourcePort, sourcePosition, targetNodeRect, targetPort, targetPosition) => {
963
+ const sourcePortPos = getPortPosition(sourcePosition, sourceNodeRect, sourcePort);
964
+ const targetPortPos = getPortPosition(targetPosition, targetNodeRect, targetPort);
965
+ return {
966
+ sourceX: sourcePortPos.x,
967
+ sourceY: sourcePortPos.y,
968
+ targetX: targetPortPos.x,
969
+ targetY: targetPortPos.y,
970
+ };
971
+ };
972
+ function getNodeData(node) {
973
+ const portBounds = node?.[internalsSymbol$1]?.portBounds || null;
974
+ const isValid = portBounds &&
975
+ node?.width &&
976
+ node?.height &&
977
+ typeof node?.positionAbsolute?.x !== 'undefined' &&
978
+ typeof node?.positionAbsolute?.y !== 'undefined';
979
+ return [
980
+ {
981
+ x: node?.positionAbsolute?.x || 0,
982
+ y: node?.positionAbsolute?.y || 0,
983
+ width: node?.width || 0,
984
+ height: node?.height || 0,
985
+ },
986
+ portBounds,
987
+ !!isValid,
988
+ ];
989
+ }
990
+
991
+ const selector$3 = (s) => ({
992
+ edges: s.edges,
993
+ width: s.width,
994
+ height: s.height,
995
+ nodeInternals: s.nodeInternals,
996
+ onError: s.onError,
997
+ });
998
+ function EdgeRenderer({ rfId, edgeTypes, noPanClassName, edgeUpdaterRadius, onEdgeClick, onEdgeDoubleClick, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, }) {
999
+ const { edges, width, height, nodeInternals } = useStore(selector$3, shallow);
1000
+ 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) => {
1001
+ const { data, type,
1002
+ // elProps
1003
+ id, className, style, ariaLabel,
1004
+ // sourceAndTargetIds
1005
+ source, sourcePort, target, targetPort,
1006
+ // marker
1007
+ markerEnd, markerStart,
1008
+ // labelProps
1009
+ label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, } = edge;
1010
+ const [sourceNodeRect, sourcePortBounds, sourceIsValid] = getNodeData(nodeInternals.get(source));
1011
+ const [targetNodeRect, targetPortBounds, targetIsValid] = getNodeData(nodeInternals.get(target));
1012
+ if (!sourceIsValid || !targetIsValid) {
1013
+ return null;
1014
+ }
1015
+ const edgeType = type || 'straight';
1016
+ const EdgeComponent = edgeTypes[edgeType] || edgeTypes.default;
1017
+ const targetNodePorts = targetPortBounds.target;
1018
+ const sourcePortInfo = getPort(sourcePortBounds.source, sourcePort);
1019
+ const targetPortInfo = getPort(targetNodePorts, targetPort);
1020
+ const sourcePosition = sourcePortInfo?.position || Position.Bottom;
1021
+ const targetPosition = targetPortInfo?.position || Position.Top;
1022
+ const isFocusable = !!edge.focusable;
1023
+ if (!sourcePortInfo || !targetPortInfo) {
1024
+ return null;
1025
+ }
1026
+ const elProps = {
1027
+ id,
1028
+ className: cc([className, noPanClassName]),
1029
+ style,
1030
+ ariaLabel,
1031
+ };
1032
+ const sourceAndTargetIds = {
1033
+ source,
1034
+ sourcePort,
1035
+ target,
1036
+ targetPort,
1037
+ };
1038
+ const marker = {
1039
+ markerEnd,
1040
+ markerStart,
1041
+ };
1042
+ const labelProps = {
1043
+ label,
1044
+ labelStyle,
1045
+ labelShowBg,
1046
+ labelBgStyle,
1047
+ labelBgPadding,
1048
+ labelBgBorderRadius,
1049
+ };
1050
+ const edgePositions = getEdgePositions(sourceNodeRect, sourcePortInfo, sourcePosition, targetNodeRect, targetPortInfo, targetPosition);
1051
+ const position = {
1052
+ ...edgePositions,
1053
+ sourcePosition,
1054
+ targetPosition,
1055
+ };
1056
+ const events = {
1057
+ onClick: onEdgeClick,
1058
+ onDoubleClick: onEdgeDoubleClick,
1059
+ onContextMenu: onEdgeContextMenu,
1060
+ onMouseEnter: onEdgeMouseEnter,
1061
+ onMouseMove: onEdgeMouseMove,
1062
+ onMouseLeave: onEdgeMouseLeave,
1063
+ onEdgeUpdate,
1064
+ onEdgeUpdateStart,
1065
+ onEdgeUpdateEnd,
1066
+ };
1067
+ return (jsx(EdgeComponent, { ...elProps, ...sourceAndTargetIds, ...marker, ...labelProps, ...position, ...events, rfId: rfId, type: edgeType, data: data, isFocusable: isFocusable, edgeUpdaterRadius: edgeUpdaterRadius }, id));
1068
+ }) })] }));
1069
+ }
1070
+ EdgeRenderer.displayName = 'EdgeRenderer';
1071
+ var EdgeRenderer$1 = memo(EdgeRenderer);
1072
+
1073
+ const oppositePosition = {
1074
+ [Position.Left]: Position.Right,
1075
+ [Position.Right]: Position.Left,
1076
+ [Position.Top]: Position.Bottom,
1077
+ [Position.Bottom]: Position.Top,
1078
+ };
1079
+ function ConnectionPath({ nodeId, portType, edge, Component, EdgeWrapper, }) {
1080
+ const { fromNode, toX, toY, startPort } = useStore(useCallback((s) => ({
1081
+ fromNode: s.nodeInternals.get(nodeId),
1082
+ startPort: s.connectionStartPort,
1083
+ toX: (s.connectionPosition.x - s.transform[0]) / s.transform[2],
1084
+ toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2],
1085
+ }), [nodeId]), shallow);
1086
+ const fromPortBounds = fromNode?.[internalsSymbol$1]?.portBounds;
1087
+ const portBounds = fromPortBounds?.[portType];
1088
+ if (!fromNode || !portBounds) {
1089
+ return null;
1090
+ }
1091
+ const fromPort = portBounds.find((bound) => bound.id === startPort?.portId) ||
1092
+ portBounds[0];
1093
+ const fromPortX = fromPort
1094
+ ? fromPort.x + fromPort.width / 2
1095
+ : (fromNode.width ?? 0) / 2;
1096
+ const fromPortY = fromPort
1097
+ ? fromPort.y + fromPort.height / 2
1098
+ : fromNode.height ?? 0;
1099
+ const fromX = (fromNode.positionAbsolute?.x ?? 0) + fromPortX;
1100
+ const fromY = (fromNode.positionAbsolute?.y ?? 0) + fromPortY;
1101
+ const fromPosition = fromPort?.position;
1102
+ const toPosition = fromPosition ? oppositePosition[fromPosition] : null;
1103
+ if (!fromPosition || !toPosition) {
1104
+ return null;
1105
+ }
1106
+ if (Component) {
1107
+ return (jsx(Component, { fromNode: fromNode, fromPort: fromPort, fromX: fromX, fromY: fromY, toX: toX, toY: toY, fromPosition: fromPosition, toPosition: toPosition }));
1108
+ }
1109
+ if (!edge) {
1110
+ const dAttr = `M${fromX},${fromY} ${toX},${toY}`;
1111
+ return (jsx("path", { d: dAttr, fill: "none", className: "react-diagram__connection-path" }));
1112
+ }
1113
+ return (jsx(EdgeWrapper, { id: edge.id, className: "react-diagram__connection", type: edge.type || 'default', source: edge.source || nodeId, target: edge.target, isFocusable: false, sourceX: fromX, sourceY: fromY, targetX: toX, targetY: toY, sourcePosition: fromPosition, targetPosition: toPosition }));
1114
+ }
1115
+ ConnectionPath.displayName = 'ConnectionPath';
1116
+
1117
+ const selector$2 = (s) => ({
1118
+ edges: s.edges,
1119
+ startPort: s.connectionStartPort,
1120
+ });
1121
+ function ConnectionLineRenderer({ containerStyle, edgeTypes, component, }) {
1122
+ const { startPort, edges } = useStore(selector$2, shallow);
1123
+ if (!startPort)
1124
+ return null;
1125
+ const { nodeId, portType } = startPort;
1126
+ const isValid = !!(nodeId && portType);
1127
+ if (!isValid) {
1128
+ return null;
1129
+ }
1130
+ const selectedEdge = edges.find((edge) => edge[portType] === nodeId);
1131
+ const EdgeWrapper = selectedEdge?.type
1132
+ ? edgeTypes[selectedEdge.type]
1133
+ : edgeTypes.default;
1134
+ 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 }) }) }));
1135
+ }
1136
+
1137
+ function DiagramView({ rfId,
1138
+ // DiagramRenderer props
1139
+ noPanClassName, panning, defaultViewport, multiSelectionKeyCode, dragSelectionKeyCode, onMove, onMoveStart, onMoveEnd,
1140
+ // NodeRenderer props
1141
+ onlyRenderVisibleElements, disableKeyboardA11y, noDragClassName, nodeOrigin, nodeExtent, nodeTypes, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave,
1142
+ // EdgeRenderer props
1143
+ edgeTypes, edgeUpdaterRadius, onEdgeClick, onEdgeDoubleClick, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd,
1144
+ // ConnectionLineWrapper
1145
+ ConnectionLineContainerStyle, ConnectionLineComponent, }) {
1146
+ return (jsxs(DiagramRenderer$1, { multiSelectionKeyCode: multiSelectionKeyCode, dragSelectionKeyCode: dragSelectionKeyCode, noPanClassName: noPanClassName, panning: panning, defaultViewport: defaultViewport, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, children: [jsx(NodeRenderer$1, { rfId: rfId, nodeTypes: nodeTypes, onlyRenderVisibleElements: onlyRenderVisibleElements, disableKeyboardA11y: disableKeyboardA11y, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent, noDragClassName: noDragClassName, noPanClassName: noPanClassName, onNodeClick: onNodeClick, onNodeDoubleClick: onNodeDoubleClick, onNodeContextMenu: onNodeContextMenu, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave }), jsx(EdgeRenderer$1, { rfId: rfId, edgeTypes: edgeTypes, noPanClassName: noPanClassName, edgeUpdaterRadius: edgeUpdaterRadius, onEdgeClick: onEdgeClick, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeContextMenu: onEdgeContextMenu, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, onEdgeUpdate: onEdgeUpdate, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd }), jsx(ConnectionLineRenderer, { edgeTypes: edgeTypes, containerStyle: ConnectionLineContainerStyle, component: ConnectionLineComponent })] }));
1147
+ }
1148
+ DiagramView.displayName = 'DiagramView';
1149
+ var DiagramView$1 = memo(DiagramView);
1150
+
1151
+ const internalsSymbol = Symbol.for('internals');
1152
+ const onErrorWrapper = (onError) => (id, value = '') => onError?.(id, errorMessages[id](value));
1153
+
1154
+ const selector$1 = (s) => {
1155
+ const { setNodes, setEdges, setNodeExtent, setTranslateExtent, setMinZoom, setMaxZoom, } = s;
1156
+ return {
1157
+ setNodes,
1158
+ setEdges,
1159
+ setNodeExtent,
1160
+ setTranslateExtent,
1161
+ setMinZoom,
1162
+ setMaxZoom,
1163
+ };
1164
+ };
1165
+ function useStoreUpdater(value, setStoreState) {
1166
+ useEffect(() => {
1167
+ if (typeof value !== 'undefined') {
1168
+ setStoreState(value);
1169
+ }
1170
+ }, [value]);
1171
+ }
1172
+ // updates with values in store that don't have a dedicated setter function
1173
+ function useDirectStoreUpdater(key, value, setState) {
1174
+ useEffect(() => {
1175
+ if (typeof value !== 'undefined') {
1176
+ setState({ [key]: value });
1177
+ }
1178
+ }, [value]);
1179
+ }
1180
+ const StoreUpdater = ({ nodes, onNodesChange, onNodeDrag, onNodeDragStart, onNodeDragEnd, edges, onEdgesChange, nodeOrigin, smoothStep, centerStep, gridStep, elevateNodesOnSelect, nodesDraggable, autoPanOnNodeDrag, autoPanOnConnect, connectionRadius, onConnect, onConnectStart, onConnectEnd, onError, nodeExtent, translateExtent, minZoom, maxZoom, }) => {
1181
+ const { setNodes, setEdges, setNodeExtent, setTranslateExtent, setMinZoom, setMaxZoom, } = useStore(selector$1, shallow);
1182
+ const store = useStoreApi();
1183
+ useStoreUpdater(nodes, setNodes);
1184
+ useStoreUpdater(edges, setEdges);
1185
+ useStoreUpdater(nodeExtent, setNodeExtent);
1186
+ useStoreUpdater(nodeExtent, setNodeExtent);
1187
+ useStoreUpdater(translateExtent, setTranslateExtent);
1188
+ useStoreUpdater(minZoom, setMinZoom);
1189
+ useStoreUpdater(maxZoom, setMaxZoom);
1190
+ useDirectStoreUpdater('nodeOrigin', nodeOrigin, store.setState);
1191
+ useDirectStoreUpdater('smoothStep', smoothStep, store.setState);
1192
+ useDirectStoreUpdater('centerStep', centerStep, store.setState);
1193
+ useDirectStoreUpdater('gridStep', gridStep, store.setState);
1194
+ useDirectStoreUpdater('elevateNodesOnSelect', elevateNodesOnSelect, store.setState);
1195
+ useDirectStoreUpdater('nodesDraggable', nodesDraggable, store.setState);
1196
+ useDirectStoreUpdater('autoPanOnNodeDrag', autoPanOnNodeDrag, store.setState);
1197
+ useDirectStoreUpdater('autoPanOnConnect', autoPanOnConnect, store.setState);
1198
+ useDirectStoreUpdater('connectionRadius', connectionRadius, store.setState);
1199
+ useDirectStoreUpdater('onNodesChange', onNodesChange, store.setState);
1200
+ useDirectStoreUpdater('onNodeDrag', onNodeDrag, store.setState);
1201
+ useDirectStoreUpdater('onNodeDragStart', onNodeDragStart, store.setState);
1202
+ useDirectStoreUpdater('onNodeDragEnd', onNodeDragEnd, store.setState);
1203
+ useDirectStoreUpdater('onEdgesChange', onEdgesChange, store.setState);
1204
+ useDirectStoreUpdater('onConnect', onConnect, store.setState);
1205
+ useDirectStoreUpdater('onConnectStart', onConnectStart, store.setState);
1206
+ useDirectStoreUpdater('onConnectEnd', onConnectEnd, store.setState);
1207
+ useDirectStoreUpdater('onError', onErrorWrapper(onError), store.setState);
1208
+ return null;
1209
+ };
1210
+
1211
+ function useNodeOrEdgeTypes(nodeOrEdgeTypes, createTypes) {
1212
+ const typesKeysRef = useRef(null);
1213
+ const typesParsed = useMemo(() => {
1214
+ if (process.env.NODE_ENV === 'development') {
1215
+ const typeKeys = Object.keys(nodeOrEdgeTypes);
1216
+ if (shallow(typesKeysRef.current, typeKeys)) {
1217
+ devWarn('002');
1218
+ }
1219
+ typesKeysRef.current = typeKeys;
1220
+ }
1221
+ return createTypes(nodeOrEdgeTypes);
1222
+ }, [nodeOrEdgeTypes]);
1223
+ return typesParsed;
1224
+ }
1225
+
1226
+ const NodeIdContext = createContext(null);
1227
+ const Provider = NodeIdContext.Provider;
1228
+ NodeIdContext.Consumer;
1229
+ const useNodeId = () => {
1230
+ const nodeId = useContext(NodeIdContext);
1231
+ return nodeId;
1232
+ };
1233
+
1234
+ function Port({ id, type, position }) {
1235
+ const portId = id || null;
1236
+ const store = useStoreApi();
1237
+ const nodeId = useNodeId();
1238
+ if (!nodeId)
1239
+ return null;
1240
+ const handleOnConnect = (connection) => {
1241
+ const { defaultEdgeOptions, onConnect } = store.getState();
1242
+ const edgeParams = {
1243
+ ...defaultEdgeOptions,
1244
+ ...connection,
1245
+ };
1246
+ onConnect?.(edgeParams);
1247
+ };
1248
+ const onPointerDown = (event) => {
1249
+ const isMouseTriggered = isMouseEvent(event.nativeEvent);
1250
+ const { button } = event;
1251
+ if ((isMouseTriggered && button === 0) || !isMouseTriggered) {
1252
+ const { domNode, autoPanOnConnect, connectionRadius, transform, getNodes, cancelConnection, updateConnection, onConnectStart, onConnectEnd, panBy, } = store.getState();
1253
+ CosmosPort.onPointerDown({
1254
+ event: event.nativeEvent,
1255
+ nodeId,
1256
+ portId,
1257
+ portType: type,
1258
+ domNode,
1259
+ autoPanOnConnect,
1260
+ connectionRadius,
1261
+ nodes: getNodes(),
1262
+ cancelConnection,
1263
+ updateConnection,
1264
+ onConnect: handleOnConnect,
1265
+ onConnectStart,
1266
+ onConnectEnd,
1267
+ panBy,
1268
+ getTransform: () => transform,
1269
+ });
1270
+ }
1271
+ };
1272
+ return (jsx("div", { "data-nodeid": nodeId, "data-id": `${nodeId}-${portId}-${type}`, "data-portid": portId, "data-port-position": position, className: `react-diagram__port react-diagram__port-${position} ${type} nodrag`, onMouseDown: onPointerDown, onTouchStart: onPointerDown }));
1273
+ }
1274
+ Port.displayName = 'Port';
1275
+ var Port$1 = memo(Port);
1276
+
1277
+ function Nodes({ data }) {
1278
+ return (jsxs(Fragment, { children: [jsx(Port$1, { type: "target", position: Position.Top }), data.label, jsx(Port$1, { type: "source", position: Position.Bottom })] }));
1279
+ }
1280
+
1281
+ const wrapNode = (NodeComponent) => {
1282
+ function NodeWrapper({ id, type, data, positionX, positionY, sourcePosition, targetPosition, onClick, onMouseEnter, onMouseMove, onMouseLeave, onContextMenu, onDoubleClick, style, width, height, className, selected, isSelectable, isDraggable, intersected, nodeOrigin, nodeExtent, hidden, resizeObserver, dragHandle, zIndex, isParent, initialized, disableKeyboardA11y, ariaLabel, rfId, noDragClassName, noPanClassName, }) {
1283
+ const store = useStoreApi();
1284
+ const node = store.getState().nodeInternals.get(id);
1285
+ const nodeRef = useRef(null);
1286
+ const prevSourcePosition = useRef(sourcePosition);
1287
+ const prevTargetPosition = useRef(targetPosition);
1288
+ const prevType = useRef(type);
1289
+ const hasPointerEvents = isDraggable || onClick || onMouseEnter || onMouseMove || onMouseLeave;
1290
+ const onSelectNodeHandler = (event) => {
1291
+ if (!isDraggable) {
1292
+ handleNodeClick({
1293
+ id,
1294
+ store,
1295
+ nodeRef,
1296
+ isSelectable,
1297
+ });
1298
+ }
1299
+ if (onClick) {
1300
+ onClick(event, { ...node });
1301
+ }
1302
+ };
1303
+ useEffect(() => {
1304
+ if (nodeRef.current && !hidden) {
1305
+ const currNode = nodeRef.current;
1306
+ resizeObserver?.observe(currNode);
1307
+ return () => resizeObserver?.unobserve(currNode);
1308
+ }
1309
+ }, [hidden]);
1310
+ useEffect(() => {
1311
+ // when the user programmatically changes the source or handle position, we re-initialize the node
1312
+ const typeChanged = prevType.current !== type;
1313
+ const sourcePosChanged = prevSourcePosition.current !== sourcePosition;
1314
+ const targetPosChanged = prevTargetPosition.current !== targetPosition;
1315
+ if (nodeRef.current &&
1316
+ (typeChanged || sourcePosChanged || targetPosChanged)) {
1317
+ if (typeChanged) {
1318
+ prevType.current = type;
1319
+ }
1320
+ if (sourcePosChanged) {
1321
+ prevSourcePosition.current = sourcePosition;
1322
+ }
1323
+ if (targetPosChanged) {
1324
+ prevTargetPosition.current = targetPosition;
1325
+ }
1326
+ store
1327
+ .getState()
1328
+ .updateNodeDimensions([
1329
+ { id, nodeElement: nodeRef.current, forceUpdate: true },
1330
+ ]);
1331
+ }
1332
+ }, [id, type, sourcePosition, targetPosition]);
1333
+ const clampedPosition = nodeExtent
1334
+ ? clampPosition(node.positionAbsolute, nodeExtent)
1335
+ : node.positionAbsolute;
1336
+ const positionWithOrigin = getNodePositionWithOrigin({ ...node, ...clampedPosition }, nodeOrigin);
1337
+ const dragging = useDrag({
1338
+ nodeRef,
1339
+ nodeId: id,
1340
+ disabled: hidden || !isDraggable,
1341
+ isSelectable,
1342
+ noDragClassName,
1343
+ });
1344
+ if (hidden) {
1345
+ return null;
1346
+ }
1347
+ const wrapperClassName = cc([
1348
+ 'react-diagram__node',
1349
+ `react-diagram__node-${type}`,
1350
+ {
1351
+ [noPanClassName]: isDraggable,
1352
+ },
1353
+ className,
1354
+ {
1355
+ selected,
1356
+ intersected,
1357
+ parent: isParent,
1358
+ dragging,
1359
+ },
1360
+ ]);
1361
+ const wrapperStyle = {
1362
+ zIndex,
1363
+ transform: `translate(${positionWithOrigin.x}px,${positionWithOrigin.y}px)`,
1364
+ pointerEvents: hasPointerEvents ? 'all' : 'none',
1365
+ visibility: initialized ? 'visible' : 'hidden',
1366
+ width,
1367
+ height,
1368
+ ...style,
1369
+ };
1370
+ const events = {
1371
+ onClick: onSelectNodeHandler,
1372
+ onDoubleClick: getMouseHandler$1(id, store.getState, onDoubleClick),
1373
+ onContextMenu: getMouseHandler$1(id, store.getState, onContextMenu),
1374
+ onMouseEnter: getMouseHandler$1(id, store.getState, onMouseEnter),
1375
+ onMouseMove: getMouseHandler$1(id, store.getState, onMouseMove),
1376
+ onMouseLeave: getMouseHandler$1(id, store.getState, onMouseLeave),
1377
+ };
1378
+ const position = {
1379
+ positionX,
1380
+ positionY,
1381
+ sourcePosition,
1382
+ targetPosition,
1383
+ };
1384
+ return (jsx("div", { ...events, ref: nodeRef, className: wrapperClassName, style: wrapperStyle, "data-id": id, tabIndex: 0, role: "button", "aria-describedby": disableKeyboardA11y ? undefined : `${ARIA_NODE_DESC_KEY}-${rfId}`, "aria-label": ariaLabel, children: jsx(Provider, { value: id, children: jsx(NodeComponent, { ...position, id: id, zIndex: zIndex, type: type, data: data, dragHandle: dragHandle, selected: selected, intersected: intersected }) }) }));
1385
+ }
1386
+ NodeWrapper.displayName = 'NodeWrapper';
1387
+ return memo(NodeWrapper);
1388
+ };
1389
+
1390
+ const createNodeTypes = (nodeTypes) => {
1391
+ const defaultTypes = {
1392
+ default: wrapNode(nodeTypes.default || Nodes),
1393
+ };
1394
+ const wrappedTypes = {};
1395
+ const customTypes = Object.keys(nodeTypes)
1396
+ .filter((k) => !Object.keys(defaultTypes).includes(k))
1397
+ .reduce((res, key) => {
1398
+ res[key] = wrapNode(nodeTypes[key] || Nodes);
1399
+ return res;
1400
+ }, wrappedTypes);
1401
+ return {
1402
+ ...defaultTypes,
1403
+ ...customTypes,
1404
+ };
1405
+ };
1406
+
1407
+ function calculateXYZPosition(node, nodeInternals, result, nodeOrigin) {
1408
+ if (!node.parentNode) {
1409
+ return result;
1410
+ }
1411
+ const parentNode = nodeInternals.get(node.parentNode);
1412
+ const parentNodePosition = getNodePositionWithOrigin(parentNode, nodeOrigin);
1413
+ return calculateXYZPosition(parentNode, nodeInternals, {
1414
+ x: (result.x ?? 0) + parentNodePosition.x,
1415
+ y: (result.y ?? 0) + parentNodePosition.y,
1416
+ z: (parentNode[internalsSymbol$1]?.z ?? 0) > (result.z ?? 0)
1417
+ ? parentNode[internalsSymbol$1]?.z ?? 0
1418
+ : result.z ?? 0,
1419
+ }, nodeOrigin);
1420
+ }
1421
+ function updateAbsoluteNodePositions(nodeInternals, nodeOrigin, parentNodes) {
1422
+ nodeInternals.forEach((node) => {
1423
+ if (node.parentNode && !nodeInternals.has(node.parentNode)) {
1424
+ throw new Error(`Parent node ${node.parentNode} not found`);
1425
+ }
1426
+ if (node.parentNode || parentNodes?.[node.id]) {
1427
+ const { x, y, z } = calculateXYZPosition(node, nodeInternals, {
1428
+ ...node.position,
1429
+ z: node[internalsSymbol$1]?.z ?? 0,
1430
+ }, nodeOrigin);
1431
+ node.positionAbsolute = {
1432
+ x,
1433
+ y,
1434
+ };
1435
+ node[internalsSymbol$1].z = z;
1436
+ if (parentNodes?.[node.id]) {
1437
+ node[internalsSymbol$1].isParent = true;
1438
+ }
1439
+ }
1440
+ });
1441
+ }
1442
+ function createNodeInternals(nodes, nodeInternals, nodeOrigin, elevateNodesOnSelect) {
1443
+ const nextNodeInternals = new Map();
1444
+ const parentNodes = {};
1445
+ const selectedNodeZ = elevateNodesOnSelect ? 1000 : 0;
1446
+ nodes.forEach((node) => {
1447
+ const z = (isNumeric(node.zIndex) ? node.zIndex : 0) +
1448
+ (node.selected ? selectedNodeZ : 0);
1449
+ const currInternals = nodeInternals.get(node.id);
1450
+ const internals = {
1451
+ width: currInternals?.width,
1452
+ height: currInternals?.height,
1453
+ ...node,
1454
+ positionAbsolute: {
1455
+ x: node.position.x,
1456
+ y: node.position.y,
1457
+ },
1458
+ };
1459
+ if (node.parentNode) {
1460
+ internals.parentNode = node.parentNode;
1461
+ parentNodes[node.parentNode] = true;
1462
+ }
1463
+ Object.defineProperty(internals, internalsSymbol$1, {
1464
+ enumerable: false,
1465
+ value: {
1466
+ portBounds: currInternals?.[internalsSymbol$1]?.portBounds,
1467
+ z,
1468
+ },
1469
+ });
1470
+ nextNodeInternals.set(node.id, internals);
1471
+ });
1472
+ updateAbsoluteNodePositions(nextNodeInternals, nodeOrigin, parentNodes);
1473
+ return nextNodeInternals;
1474
+ }
1475
+ const isIntersected = (targetNode, nodeInternals) => {
1476
+ const { id, width, height, positionAbsolute } = targetNode;
1477
+ if (!width || !height)
1478
+ return false;
1479
+ let intersected = false;
1480
+ for (const [key, sourceNode] of nodeInternals) {
1481
+ if (id === key)
1482
+ continue;
1483
+ const { positionAbsolute: sPositionAbsolute, width: sWidth, height: sHeight, } = sourceNode;
1484
+ if (!sWidth || !sHeight)
1485
+ continue;
1486
+ if (!sPositionAbsolute || !positionAbsolute)
1487
+ continue;
1488
+ // if (sourceNode.parentNode === targetNode.id) continue;
1489
+ // if (targetNode.parentNode === sourceNode.id) continue;
1490
+ const leftIn = sPositionAbsolute.x + sWidth >= positionAbsolute.x, rightIn = positionAbsolute.x + width >= sPositionAbsolute.x, topIn = sPositionAbsolute.y + sHeight >= positionAbsolute.y, bottomIn = positionAbsolute.y + height >= sPositionAbsolute.y;
1491
+ const isIn = leftIn && rightIn && topIn && bottomIn;
1492
+ if (isIn) {
1493
+ intersected = true;
1494
+ break;
1495
+ }
1496
+ }
1497
+ return intersected;
1498
+ };
1499
+
1500
+ const infiniteExtent = [
1501
+ [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
1502
+ [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
1503
+ ];
1504
+ const initialState = {
1505
+ rfId: '1',
1506
+ width: 0,
1507
+ height: 0,
1508
+ transform: [0, 0, 1],
1509
+ nodeInternals: new Map(),
1510
+ edges: [],
1511
+ elementsSelectable: true,
1512
+ onNodesChange: null,
1513
+ domNode: null,
1514
+ nodeOrigin: [0, 0],
1515
+ smoothStep: false,
1516
+ centerStep: false,
1517
+ gridStep: undefined,
1518
+ elevateNodesOnSelect: true,
1519
+ nodesDraggable: true,
1520
+ multiSelectionActive: false,
1521
+ selectionBoxActive: false,
1522
+ d3Zoom: null,
1523
+ d3Selection: null,
1524
+ minZoom: 0.5,
1525
+ maxZoom: 2,
1526
+ connectionPosition: { x: 0, y: 0 },
1527
+ connectionStartPort: null,
1528
+ connectionEndPort: null,
1529
+ autoPanOnNodeDrag: true,
1530
+ autoPanOnConnect: true,
1531
+ nodeExtent: infiniteExtent,
1532
+ translateExtent: infiniteExtent,
1533
+ connectionRadius: 20,
1534
+ onError: devWarn,
1535
+ };
1536
+
1537
+ const createRCDStore = () => createStore((set, get) => ({
1538
+ ...initialState,
1539
+ setNodes: (nodes) => {
1540
+ const { nodeInternals, nodeOrigin, elevateNodesOnSelect } = get();
1541
+ set({
1542
+ nodeInternals: createNodeInternals(nodes, nodeInternals, nodeOrigin, elevateNodesOnSelect),
1543
+ });
1544
+ },
1545
+ getNodes: () => Array.from(get().nodeInternals.values()),
1546
+ setEdges: (edges) => {
1547
+ const { defaultEdgeOptions = {} } = get();
1548
+ set({ edges: edges.map((e) => ({ ...defaultEdgeOptions, ...e })) });
1549
+ },
1550
+ updateNodeDimensions: (updates) => {
1551
+ const { onNodesChange, updateNodesIntersection, nodeInternals, domNode, nodeOrigin, } = get();
1552
+ const viewportNode = domNode?.querySelector('.react-diagram__viewport');
1553
+ if (!viewportNode) {
1554
+ return;
1555
+ }
1556
+ const style = window.getComputedStyle(viewportNode);
1557
+ const { m22: zoom } = new window.DOMMatrixReadOnly(style.transform);
1558
+ const changes = updates.reduce((res, update) => {
1559
+ const node = nodeInternals.get(update.id);
1560
+ if (node) {
1561
+ const dimensions = getDimensions(update.nodeElement);
1562
+ const doUpdate = !!(dimensions.width &&
1563
+ dimensions.height &&
1564
+ (node.width !== dimensions.width ||
1565
+ node.height !== dimensions.height ||
1566
+ update.forceUpdate));
1567
+ if (doUpdate) {
1568
+ nodeInternals.set(node.id, {
1569
+ ...node,
1570
+ [internalsSymbol$1]: {
1571
+ ...node[internalsSymbol$1],
1572
+ portBounds: {
1573
+ id: node[internalsSymbol$1]?.portBounds?.id || null,
1574
+ source: getPortBounds('.source', update.nodeElement, zoom, nodeOrigin),
1575
+ target: getPortBounds('.target', update.nodeElement, zoom, nodeOrigin),
1576
+ },
1577
+ },
1578
+ ...dimensions,
1579
+ });
1580
+ res.push({
1581
+ id: node.id,
1582
+ type: 'dimensions',
1583
+ dimensions,
1584
+ });
1585
+ }
1586
+ }
1587
+ return res;
1588
+ }, []);
1589
+ updateNodesIntersection();
1590
+ updateAbsoluteNodePositions(nodeInternals, nodeOrigin);
1591
+ set({
1592
+ nodeInternals: new Map(nodeInternals),
1593
+ });
1594
+ if (changes?.length > 0) {
1595
+ onNodesChange?.(changes);
1596
+ }
1597
+ },
1598
+ updateNodesPosition: (nodes, dragging = false, updateFunc) => {
1599
+ const { triggerNodeChanges } = get();
1600
+ const changes = nodes.map((node) => {
1601
+ const change = {
1602
+ id: node.id,
1603
+ type: 'position',
1604
+ dragging,
1605
+ };
1606
+ if (updateFunc) {
1607
+ updateFunc(node);
1608
+ return {
1609
+ ...change,
1610
+ position: node.position,
1611
+ positionAbsolute: node.positionAbsolute,
1612
+ };
1613
+ }
1614
+ return change;
1615
+ });
1616
+ triggerNodeChanges(changes);
1617
+ },
1618
+ triggerNodeChanges: (changes) => {
1619
+ const { onNodesChange } = get();
1620
+ if (changes?.length) {
1621
+ onNodesChange?.(changes);
1622
+ }
1623
+ },
1624
+ updateNodesIntersection: () => {
1625
+ const { nodeInternals, triggerNodeChanges } = get();
1626
+ const nodes = Array.from(nodeInternals.values());
1627
+ const unIntersectNodes = () => {
1628
+ return nodes
1629
+ .filter((node) => node.intersected && !isIntersected(node, nodeInternals))
1630
+ .map((node) => ({
1631
+ id: node.id,
1632
+ type: 'intersect',
1633
+ intersected: false,
1634
+ }));
1635
+ };
1636
+ const addIntersectNodes = () => {
1637
+ return nodes
1638
+ .filter((node) => isIntersected(node, nodeInternals))
1639
+ .map((node) => {
1640
+ return {
1641
+ id: node.id,
1642
+ type: 'intersect',
1643
+ intersected: true,
1644
+ };
1645
+ });
1646
+ };
1647
+ const intersectedNodes = addIntersectNodes();
1648
+ const unIntersectedNodes = unIntersectNodes();
1649
+ triggerNodeChanges([...intersectedNodes, ...unIntersectedNodes]);
1650
+ },
1651
+ addSelectedNodes: (selectedNodeIds) => {
1652
+ const { multiSelectionActive, getNodes, triggerNodeChanges } = get();
1653
+ let changedNodes;
1654
+ if (multiSelectionActive) {
1655
+ changedNodes = selectedNodeIds.map((nodeId) => createSelectionChange(nodeId, true));
1656
+ }
1657
+ else {
1658
+ changedNodes = getSelectionChanges(getNodes(), selectedNodeIds);
1659
+ }
1660
+ triggerNodeChanges(changedNodes);
1661
+ },
1662
+ unselectNodes: ({ nodes } = {}) => {
1663
+ const { getNodes, triggerNodeChanges } = get();
1664
+ const nodesToUnselect = nodes ? nodes : getNodes();
1665
+ const changedNodes = nodesToUnselect.map((n) => {
1666
+ n.selected = false;
1667
+ return createSelectionChange(n.id, false);
1668
+ });
1669
+ triggerNodeChanges(changedNodes);
1670
+ },
1671
+ resetSelectedElements: () => {
1672
+ const { getNodes, triggerNodeChanges } = get();
1673
+ const nodes = getNodes();
1674
+ const nodesToUnselect = nodes
1675
+ .filter((e) => e.selected)
1676
+ .map((n) => createSelectionChange(n.id, false));
1677
+ triggerNodeChanges(nodesToUnselect);
1678
+ },
1679
+ cancelConnection: () => set({
1680
+ connectionStartPort: null,
1681
+ connectionEndPort: null,
1682
+ }),
1683
+ updateConnection: (params) => {
1684
+ const { connectionPosition } = get();
1685
+ const currentConnection = {
1686
+ ...params,
1687
+ connectionPosition: params.connectionPosition ?? connectionPosition,
1688
+ };
1689
+ set(currentConnection);
1690
+ },
1691
+ panBy: (delta) => {
1692
+ const { transform, width, height, d3Zoom, d3Selection } = get();
1693
+ if (!d3Zoom || !d3Selection || (!delta.x && !delta.y)) {
1694
+ return;
1695
+ }
1696
+ const nextTransform = zoomIdentity
1697
+ .translate(transform[0] + delta.x, transform[1] + delta.y)
1698
+ .scale(transform[2]);
1699
+ const extent = [
1700
+ [0, 0],
1701
+ [width, height],
1702
+ ];
1703
+ const constrainedTransform = d3Zoom?.constrain()(nextTransform, extent, infiniteExtent);
1704
+ d3Zoom.transform(d3Selection, constrainedTransform);
1705
+ },
1706
+ setNodeExtent: (nodeExtent) => {
1707
+ const { nodeInternals } = get();
1708
+ nodeInternals.forEach((node) => {
1709
+ node.positionAbsolute = clampPosition(node.position, nodeExtent);
1710
+ });
1711
+ set({
1712
+ nodeExtent,
1713
+ nodeInternals: new Map(nodeInternals),
1714
+ });
1715
+ },
1716
+ setTranslateExtent: (translateExtent) => {
1717
+ get().d3Zoom?.translateExtent(translateExtent);
1718
+ set({ translateExtent });
1719
+ },
1720
+ setMinZoom: (minZoom) => {
1721
+ const { d3Zoom, maxZoom } = get();
1722
+ d3Zoom?.scaleExtent([minZoom, maxZoom]);
1723
+ set({ minZoom });
1724
+ },
1725
+ setMaxZoom: (maxZoom) => {
1726
+ const { d3Zoom, minZoom } = get();
1727
+ d3Zoom?.scaleExtent([minZoom, maxZoom]);
1728
+ set({ maxZoom });
1729
+ },
1730
+ }));
1731
+
1732
+ const ReactDiagramProvider = ({ children }) => {
1733
+ const storeRef = useRef(null);
1734
+ if (!storeRef.current) {
1735
+ storeRef.current = createRCDStore();
1736
+ }
1737
+ return jsx(Provider$1, { value: storeRef.current, children: children });
1738
+ };
1739
+ ReactDiagramProvider.displayName = 'ReactDiagramProvider';
1740
+
1741
+ function Wrapper({ children }) {
1742
+ const isWrapped = useContext(StoreContext);
1743
+ if (isWrapped) {
1744
+ return jsx(Fragment, { children: children });
1745
+ }
1746
+ return jsx(ReactDiagramProvider, { children: children });
1747
+ }
1748
+ Wrapper.displayName = 'ReactDiagramWrapper';
1749
+
1750
+ const initViewport = { x: 0, y: 0, zoom: 1 };
1751
+ const initNodeOrigin = [0, 0];
1752
+ const defaultNodeTypes = {
1753
+ default: Nodes,
1754
+ };
1755
+ const defaultEdgeTypes = {
1756
+ step: StepEdge,
1757
+ };
1758
+ const ReactDiagram = forwardRef(({ children, id,
1759
+ // DiagramView props
1760
+ panning = true, minZoom, maxZoom, translateExtent, nodeExtent = infiniteExtent, defaultViewport = initViewport, multiSelectionKeyCode = 'Meta', dragSelectionKeyCode = 'Shift', onlyRenderVisibleElements = false, disableKeyboardA11y = false, noDragClassName = 'nodrag', noPanClassName = 'nopan', nodeOrigin = initNodeOrigin, nodeTypes = defaultNodeTypes, onNodeClick, onNodeDoubleClick, onNodeContextMenu, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, edgeTypes = defaultEdgeTypes, edgeUpdaterRadius, onEdgeClick, onEdgeDoubleClick, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, onMove, onMoveStart, onMoveEnd, ConnectionLineContainerStyle, ConnectionLineComponent,
1761
+ // StoreUpdater props
1762
+ nodes, edges, nodesDraggable, elevateNodesOnSelect, autoPanOnNodeDrag, autoPanOnConnect, connectionRadius, smoothStep, centerStep, gridStep, onNodesChange, onNodeDrag, onNodeDragStart, onNodeDragEnd, onEdgesChange, onConnect, onConnectStart, onConnectEnd, onError, ...rest }, ref) => {
1763
+ const rfId = id || '1';
1764
+ const nodeTypesWrapped = useNodeOrEdgeTypes(nodeTypes, createNodeTypes);
1765
+ const edgeTypesWrapped = useNodeOrEdgeTypes(edgeTypes, createEdgeTypes);
1766
+ return (jsx("div", { ...rest, ref: ref, className: "react-diagram", children: jsxs(Wrapper, { children: [jsx(DiagramView$1, { rfId: rfId, panning: panning, defaultViewport: defaultViewport, multiSelectionKeyCode: multiSelectionKeyCode, dragSelectionKeyCode: dragSelectionKeyCode, onlyRenderVisibleElements: onlyRenderVisibleElements, disableKeyboardA11y: disableKeyboardA11y, noDragClassName: noDragClassName, noPanClassName: noPanClassName, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent, nodeTypes: nodeTypesWrapped, edgeTypes: edgeTypesWrapped, edgeUpdaterRadius: edgeUpdaterRadius, ConnectionLineContainerStyle: ConnectionLineContainerStyle, ConnectionLineComponent: ConnectionLineComponent, onNodeClick: onNodeClick, onNodeDoubleClick: onNodeDoubleClick, onNodeContextMenu: onNodeContextMenu, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave, onEdgeClick: onEdgeClick, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeContextMenu: onEdgeContextMenu, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, onEdgeUpdate: onEdgeUpdate, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd }), jsx(StoreUpdater, { rfId: rfId, nodes: nodes, edges: edges, nodesDraggable: nodesDraggable, elevateNodesOnSelect: elevateNodesOnSelect, autoPanOnNodeDrag: autoPanOnNodeDrag, autoPanOnConnect: autoPanOnConnect, connectionRadius: connectionRadius, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, smoothStep: smoothStep, centerStep: centerStep, gridStep: gridStep, onNodesChange: onNodesChange, onNodeDrag: onNodeDrag, onNodeDragStart: onNodeDragStart, onNodeDragEnd: onNodeDragEnd, onEdgesChange: onEdgesChange, onConnect: onConnect, onConnectStart: onConnectStart, onConnectEnd: onConnectEnd, onError: onError }), children] }) }));
1767
+ });
1768
+ ReactDiagram.displayName = 'ReactDiagram';
1769
+
1770
+ function createUseItemsState(applyChanges) {
1771
+ return (initialItems) => {
1772
+ const [items, setItems] = useState(initialItems);
1773
+ const onItemsChange = useCallback((changes) => setItems((items) => applyChanges(changes, items)), []);
1774
+ return [items, setItems, onItemsChange];
1775
+ };
1776
+ }
1777
+ const useNodesState = createUseItemsState(applyNodeChanges);
1778
+ const useEdgesState = createUseItemsState(applyEdgeChanges);
1779
+
1780
+ function LinePath({ color, scaledGap, lineWidth }) {
1781
+ const m1 = `M${scaledGap[0] / 2} 0`;
1782
+ const v = `V${scaledGap[1]}`;
1783
+ const m2 = `M0 ${scaledGap[1] / 2}`;
1784
+ const h = `H${scaledGap[0]}`;
1785
+ const path = `${m1} ${v} ${m2} ${h}`;
1786
+ return jsx("path", { stroke: color, strokeWidth: lineWidth, d: path });
1787
+ }
1788
+
1789
+ const selector = (s) => ({
1790
+ transform: s.transform,
1791
+ rfId: s.rfId,
1792
+ gridStepGap: s.gridStep,
1793
+ });
1794
+ function Background({ gap, lineWidth = 1, color = '#000000', }) {
1795
+ const ref = useRef(null);
1796
+ const { transform, rfId, gridStepGap } = useStore(selector, shallow);
1797
+ const defaultGap = gap ? gap : gridStepGap ? gridStepGap : 50;
1798
+ const gapXY = Array.isArray(defaultGap)
1799
+ ? defaultGap
1800
+ : [defaultGap, defaultGap];
1801
+ const scaledGap = [
1802
+ gapXY[0] * transform[2] || 1,
1803
+ gapXY[1] * transform[2] || 1,
1804
+ ];
1805
+ const patternOffset = [scaledGap[0] / 2, scaledGap[1] / 2];
1806
+ 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}`})` })] }));
1807
+ }
1808
+ Background.displayName = 'Background';
1809
+ var index = memo(Background);
1810
+
1811
+ export { index as Background, BaseEdge, BezierEdge, Port$1 as Port, ReactDiagramProvider, StepEdge, ReactDiagram as default, internalsSymbol, useEdgesState, useNodesState };