@xyflow/react 12.0.0-next.11 → 12.0.0-next.13
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/base.css +7 -0
- package/dist/esm/additional-components/Controls/Controls.d.ts +1 -1
- package/dist/esm/additional-components/Controls/Controls.d.ts.map +1 -1
- package/dist/esm/additional-components/Controls/types.d.ts +1 -0
- package/dist/esm/additional-components/Controls/types.d.ts.map +1 -1
- package/dist/esm/additional-components/MiniMap/MiniMap.d.ts.map +1 -1
- package/dist/esm/additional-components/MiniMap/MiniMapNodes.d.ts.map +1 -1
- package/dist/esm/additional-components/NodeResizer/NodeResizeControl.d.ts.map +1 -1
- package/dist/esm/components/ConnectionLine/index.d.ts.map +1 -1
- package/dist/esm/components/EdgeWrapper/EdgeUpdateAnchors.d.ts.map +1 -1
- package/dist/esm/components/Handle/index.d.ts +1 -1
- package/dist/esm/components/Handle/index.d.ts.map +1 -1
- package/dist/esm/components/NodeWrapper/index.d.ts.map +1 -1
- package/dist/esm/components/NodeWrapper/utils.d.ts +2 -2
- package/dist/esm/components/NodeWrapper/utils.d.ts.map +1 -1
- package/dist/esm/components/NodesSelection/index.d.ts.map +1 -1
- package/dist/esm/components/StoreUpdater/index.d.ts.map +1 -1
- package/dist/esm/container/NodeRenderer/useResizeObserver.d.ts.map +1 -1
- package/dist/esm/container/Pane/index.d.ts.map +1 -1
- package/dist/esm/container/ReactFlow/index.d.ts +1 -1
- package/dist/esm/container/ReactFlow/index.d.ts.map +1 -1
- package/dist/esm/contexts/RFStoreContext.d.ts +2 -2
- package/dist/esm/contexts/RFStoreContext.d.ts.map +1 -1
- package/dist/esm/hooks/useInternalNode.d.ts +10 -0
- package/dist/esm/hooks/useInternalNode.d.ts.map +1 -0
- package/dist/esm/hooks/useKeyPress.d.ts.map +1 -1
- package/dist/esm/hooks/useMoveSelectedNodes.d.ts.map +1 -1
- package/dist/esm/hooks/useNodesInitialized.d.ts.map +1 -1
- package/dist/esm/hooks/useReactFlow.d.ts.map +1 -1
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +174 -180
- package/dist/esm/index.mjs +174 -180
- package/dist/esm/store/index.d.ts +5 -5
- package/dist/esm/store/index.d.ts.map +1 -1
- package/dist/esm/store/initialState.d.ts +4 -4
- package/dist/esm/types/general.d.ts +2 -5
- package/dist/esm/types/general.d.ts.map +1 -1
- package/dist/esm/types/index.d.ts +0 -1
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/types/instance.d.ts +9 -1
- package/dist/esm/types/instance.d.ts.map +1 -1
- package/dist/esm/types/nodes.d.ts +2 -1
- package/dist/esm/types/nodes.d.ts.map +1 -1
- package/dist/esm/types/store.d.ts +4 -4
- package/dist/esm/types/store.d.ts.map +1 -1
- package/dist/esm/utils/changes.d.ts +4 -5
- package/dist/esm/utils/changes.d.ts.map +1 -1
- package/dist/esm/utils/general.d.ts +4 -2
- package/dist/esm/utils/general.d.ts.map +1 -1
- package/dist/style.css +8 -3
- package/dist/umd/additional-components/Controls/Controls.d.ts +1 -1
- package/dist/umd/additional-components/Controls/Controls.d.ts.map +1 -1
- package/dist/umd/additional-components/Controls/types.d.ts +1 -0
- package/dist/umd/additional-components/Controls/types.d.ts.map +1 -1
- package/dist/umd/additional-components/MiniMap/MiniMap.d.ts.map +1 -1
- package/dist/umd/additional-components/MiniMap/MiniMapNodes.d.ts.map +1 -1
- package/dist/umd/additional-components/NodeResizer/NodeResizeControl.d.ts.map +1 -1
- package/dist/umd/components/ConnectionLine/index.d.ts.map +1 -1
- package/dist/umd/components/EdgeWrapper/EdgeUpdateAnchors.d.ts.map +1 -1
- package/dist/umd/components/Handle/index.d.ts +1 -1
- package/dist/umd/components/Handle/index.d.ts.map +1 -1
- package/dist/umd/components/NodeWrapper/index.d.ts.map +1 -1
- package/dist/umd/components/NodeWrapper/utils.d.ts +2 -2
- package/dist/umd/components/NodeWrapper/utils.d.ts.map +1 -1
- package/dist/umd/components/NodesSelection/index.d.ts.map +1 -1
- package/dist/umd/components/StoreUpdater/index.d.ts.map +1 -1
- package/dist/umd/container/NodeRenderer/useResizeObserver.d.ts.map +1 -1
- package/dist/umd/container/Pane/index.d.ts.map +1 -1
- package/dist/umd/container/ReactFlow/index.d.ts +1 -1
- package/dist/umd/container/ReactFlow/index.d.ts.map +1 -1
- package/dist/umd/contexts/RFStoreContext.d.ts +2 -2
- package/dist/umd/contexts/RFStoreContext.d.ts.map +1 -1
- package/dist/umd/hooks/useInternalNode.d.ts +10 -0
- package/dist/umd/hooks/useInternalNode.d.ts.map +1 -0
- package/dist/umd/hooks/useKeyPress.d.ts.map +1 -1
- package/dist/umd/hooks/useMoveSelectedNodes.d.ts.map +1 -1
- package/dist/umd/hooks/useNodesInitialized.d.ts.map +1 -1
- package/dist/umd/hooks/useReactFlow.d.ts.map +1 -1
- package/dist/umd/index.d.ts +3 -2
- package/dist/umd/index.d.ts.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/store/index.d.ts +5 -5
- package/dist/umd/store/index.d.ts.map +1 -1
- package/dist/umd/store/initialState.d.ts +4 -4
- package/dist/umd/types/general.d.ts +2 -5
- package/dist/umd/types/general.d.ts.map +1 -1
- package/dist/umd/types/index.d.ts +0 -1
- package/dist/umd/types/index.d.ts.map +1 -1
- package/dist/umd/types/instance.d.ts +9 -1
- package/dist/umd/types/instance.d.ts.map +1 -1
- package/dist/umd/types/nodes.d.ts +2 -1
- package/dist/umd/types/nodes.d.ts.map +1 -1
- package/dist/umd/types/store.d.ts +4 -4
- package/dist/umd/types/store.d.ts.map +1 -1
- package/dist/umd/utils/changes.d.ts +4 -5
- package/dist/umd/utils/changes.d.ts.map +1 -1
- package/dist/umd/utils/general.d.ts +4 -2
- package/dist/umd/utils/general.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/esm/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { createContext, useContext, useMemo, useEffect, useRef, useState, useLayoutEffect, useCallback, memo, forwardRef } from 'react';
|
|
4
3
|
import cc from 'classcat';
|
|
5
|
-
import { errorMessages, infiniteExtent, isInputDOMNode, fitView, getViewportForBounds, pointToRendererPoint, rendererPointToPoint, isNodeBase, isEdgeBase, getElementsToRemove,
|
|
6
|
-
export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, SelectionMode, addEdge, getBezierEdgeCenter, getBezierPath, getConnectedEdges, getEdgeCenter, getIncomers, getNodesBounds, getOutgoers, getSmoothStepPath, getStraightPath, getViewportForBounds,
|
|
4
|
+
import { errorMessages, infiniteExtent, isInputDOMNode, fitView, getViewportForBounds, pointToRendererPoint, rendererPointToPoint, isNodeBase, isEdgeBase, getElementsToRemove, nodeToRect, isRectObject, getOverlappingArea, getDimensions, XYPanZoom, PanOnScrollMode, SelectionMode, getEventPosition, getNodesInside, XYDrag, snapPosition, calculateNodePosition, Position, ConnectionMode, isMouseEvent, XYHandle, getHostForElement, addEdge, getNodesBounds, clampPosition, getNodeDimensions, nodeHasDimensions, getPositionWithOrigin, elementSelectionKeys, isEdgeVisible, MarkerType, createMarkerIds, isNumeric, getBezierEdgeCenter, getSmoothStepPath, getStraightPath, getBezierPath, getEdgePosition, getElevatedEdgeZIndex, getMarkerId, ConnectionLineType, updateConnectionLookup, adoptUserNodes, devWarn, updateNodeDimensions, updateAbsolutePositions, handleParentExpand, panBy, isMacOs, areConnectionMapsEqual, handleConnectionChange, shallowNodeData, getNodePositionWithOrigin, XYMinimap, getBoundsOfRects, getInternalNodesBounds, ResizeControlVariant, XYResizer, XY_RESIZER_LINE_POSITIONS, XY_RESIZER_HANDLE_POSITIONS, getNodeToolbarTransform } from '@xyflow/system';
|
|
5
|
+
export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, SelectionMode, addEdge, getBezierEdgeCenter, getBezierPath, getConnectedEdges, getEdgeCenter, getIncomers, getNodesBounds, getOutgoers, getSmoothStepPath, getStraightPath, getViewportForBounds, updateEdge } from '@xyflow/system';
|
|
6
|
+
import { createContext, useContext, useMemo, useEffect, useRef, useState, forwardRef, useLayoutEffect, useCallback, memo } from 'react';
|
|
7
7
|
import { useStoreWithEqualityFn, createWithEqualityFn } from 'zustand/traditional';
|
|
8
8
|
import { shallow } from 'zustand/shallow';
|
|
9
9
|
import { createPortal } from 'react-dom';
|
|
@@ -83,7 +83,7 @@ function Attribution({ proOptions, position = 'bottom-right' }) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
const selector$o = (s) => ({
|
|
86
|
-
selectedNodes: s.
|
|
86
|
+
selectedNodes: Array.from(s.nodeLookup.values()).filter((n) => n.selected),
|
|
87
87
|
selectedEdges: s.edges.filter((e) => e.selected),
|
|
88
88
|
});
|
|
89
89
|
const selectId = (obj) => obj.id;
|
|
@@ -356,10 +356,12 @@ keyCode = null, options = { target: defaultDoc, actInsideInputWithModifier: true
|
|
|
356
356
|
target?.addEventListener('keydown', downHandler);
|
|
357
357
|
target?.addEventListener('keyup', upHandler);
|
|
358
358
|
window.addEventListener('blur', resetHandler);
|
|
359
|
+
window.addEventListener('contextmenu', resetHandler);
|
|
359
360
|
return () => {
|
|
360
361
|
target?.removeEventListener('keydown', downHandler);
|
|
361
362
|
target?.removeEventListener('keyup', upHandler);
|
|
362
363
|
window.removeEventListener('blur', resetHandler);
|
|
364
|
+
window.removeEventListener('contextmenu', resetHandler);
|
|
363
365
|
};
|
|
364
366
|
}
|
|
365
367
|
}, [keyCode, setKeyPressed]);
|
|
@@ -409,10 +411,10 @@ const useViewportHelper = () => {
|
|
|
409
411
|
return { x, y, zoom };
|
|
410
412
|
},
|
|
411
413
|
fitView: (options) => {
|
|
412
|
-
const {
|
|
414
|
+
const { nodeLookup, width, height, nodeOrigin, minZoom, maxZoom, panZoom } = store.getState();
|
|
413
415
|
return panZoom
|
|
414
416
|
? fitView({
|
|
415
|
-
|
|
417
|
+
nodeLookup,
|
|
416
418
|
width,
|
|
417
419
|
height,
|
|
418
420
|
nodeOrigin,
|
|
@@ -468,42 +470,6 @@ const useViewportHelper = () => {
|
|
|
468
470
|
return viewportHelperFunctions;
|
|
469
471
|
};
|
|
470
472
|
|
|
471
|
-
function handleParentExpand(updatedElements, updateItem) {
|
|
472
|
-
for (const [index, item] of updatedElements.entries()) {
|
|
473
|
-
if (item.id === updateItem.parentNode) {
|
|
474
|
-
const parent = { ...item };
|
|
475
|
-
parent.computed ??= {};
|
|
476
|
-
const extendWidth = updateItem.position.x + updateItem.computed.width - parent.computed.width;
|
|
477
|
-
const extendHeight = updateItem.position.y + updateItem.computed.height - parent.computed.height;
|
|
478
|
-
if (extendWidth > 0 || extendHeight > 0 || updateItem.position.x < 0 || updateItem.position.y < 0) {
|
|
479
|
-
parent.width = parent.width ?? parent.computed.width;
|
|
480
|
-
parent.height = parent.height ?? parent.computed.height;
|
|
481
|
-
if (extendWidth > 0) {
|
|
482
|
-
parent.width += extendWidth;
|
|
483
|
-
}
|
|
484
|
-
if (extendHeight > 0) {
|
|
485
|
-
parent.height += extendHeight;
|
|
486
|
-
}
|
|
487
|
-
if (updateItem.position.x < 0) {
|
|
488
|
-
const xDiff = Math.abs(updateItem.position.x);
|
|
489
|
-
parent.position.x = parent.position.x - xDiff;
|
|
490
|
-
parent.width += xDiff;
|
|
491
|
-
updateItem.position.x = 0;
|
|
492
|
-
}
|
|
493
|
-
if (updateItem.position.y < 0) {
|
|
494
|
-
const yDiff = Math.abs(updateItem.position.y);
|
|
495
|
-
parent.position.y = parent.position.y - yDiff;
|
|
496
|
-
parent.height += yDiff;
|
|
497
|
-
updateItem.position.y = 0;
|
|
498
|
-
}
|
|
499
|
-
parent.computed.width = parent.width;
|
|
500
|
-
parent.computed.height = parent.height;
|
|
501
|
-
updatedElements[index] = parent;
|
|
502
|
-
}
|
|
503
|
-
break;
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
473
|
// This function applies changes to nodes or edges that are triggered by React Flow internally.
|
|
508
474
|
// When you drag a node for example, React Flow will send a position change update.
|
|
509
475
|
// This function then applies the changes and returns the updated elements.
|
|
@@ -555,14 +521,14 @@ function applyChanges(changes, elements) {
|
|
|
555
521
|
/// each _mutate_ this object, so there's only ever one copy.
|
|
556
522
|
const updatedElement = { ...element };
|
|
557
523
|
for (const change of changes) {
|
|
558
|
-
applyChange(change, updatedElement
|
|
524
|
+
applyChange(change, updatedElement);
|
|
559
525
|
}
|
|
560
526
|
updatedElements.push(updatedElement);
|
|
561
527
|
}
|
|
562
528
|
return updatedElements;
|
|
563
529
|
}
|
|
564
530
|
// Applies a single change to an element. This is a *mutable* update.
|
|
565
|
-
function applyChange(change, element
|
|
531
|
+
function applyChange(change, element) {
|
|
566
532
|
switch (change.type) {
|
|
567
533
|
case 'select': {
|
|
568
534
|
element.selected = change.selected;
|
|
@@ -572,23 +538,16 @@ function applyChange(change, element, elements = []) {
|
|
|
572
538
|
if (typeof change.position !== 'undefined') {
|
|
573
539
|
element.position = change.position;
|
|
574
540
|
}
|
|
575
|
-
if (typeof change.positionAbsolute !== 'undefined') {
|
|
576
|
-
element.computed ??= {};
|
|
577
|
-
element.computed.positionAbsolute = change.positionAbsolute;
|
|
578
|
-
}
|
|
579
541
|
if (typeof change.dragging !== 'undefined') {
|
|
580
542
|
element.dragging = change.dragging;
|
|
581
543
|
}
|
|
582
|
-
if (element.expandParent) {
|
|
583
|
-
handleParentExpand(elements, element);
|
|
584
|
-
}
|
|
585
544
|
break;
|
|
586
545
|
}
|
|
587
546
|
case 'dimensions': {
|
|
588
547
|
if (typeof change.dimensions !== 'undefined') {
|
|
589
|
-
element.
|
|
590
|
-
element.
|
|
591
|
-
element.
|
|
548
|
+
element.measured ??= {};
|
|
549
|
+
element.measured.width = change.dimensions.width;
|
|
550
|
+
element.measured.height = change.dimensions.height;
|
|
592
551
|
if (change.resizing) {
|
|
593
552
|
element.width = change.dimensions.width;
|
|
594
553
|
element.height = change.dimensions.height;
|
|
@@ -597,9 +556,6 @@ function applyChange(change, element, elements = []) {
|
|
|
597
556
|
if (typeof change.resizing === 'boolean') {
|
|
598
557
|
element.resizing = change.resizing;
|
|
599
558
|
}
|
|
600
|
-
if (element.expandParent) {
|
|
601
|
-
handleParentExpand(elements, element);
|
|
602
|
-
}
|
|
603
559
|
break;
|
|
604
560
|
}
|
|
605
561
|
}
|
|
@@ -659,7 +615,7 @@ function createSelectionChange(id, selected) {
|
|
|
659
615
|
}
|
|
660
616
|
function getSelectionChanges(items, selectedIds = new Set(), mutateItem = false) {
|
|
661
617
|
const changes = [];
|
|
662
|
-
for (const item of items) {
|
|
618
|
+
for (const [, item] of items) {
|
|
663
619
|
const willBeSelected = selectedIds.has(item.id);
|
|
664
620
|
// we don't want to set all items to selected=false on the first selection
|
|
665
621
|
if (!(item.selected === undefined && !willBeSelected) && item.selected !== willBeSelected) {
|
|
@@ -711,6 +667,11 @@ const isNode = (element) => isNodeBase(element);
|
|
|
711
667
|
* @returns A boolean indicating whether the element is an Edge
|
|
712
668
|
*/
|
|
713
669
|
const isEdge = (element) => isEdgeBase(element);
|
|
670
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
671
|
+
function fixedForwardRef(render) {
|
|
672
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
673
|
+
return forwardRef(render);
|
|
674
|
+
}
|
|
714
675
|
|
|
715
676
|
// we need this hook to prevent a warning when using react-flow in SSR
|
|
716
677
|
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
|
|
@@ -724,12 +685,9 @@ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffec
|
|
|
724
685
|
function useReactFlow() {
|
|
725
686
|
const viewportHelper = useViewportHelper();
|
|
726
687
|
const store = useStoreApi();
|
|
727
|
-
const getNodes = useCallback(() => {
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
const getNode = useCallback((id) => {
|
|
731
|
-
return store.getState().nodeLookup.get(id);
|
|
732
|
-
}, []);
|
|
688
|
+
const getNodes = useCallback(() => store.getState().nodes.map((n) => ({ ...n })), []);
|
|
689
|
+
const getInternalNode = useCallback((id) => store.getState().nodeLookup.get(id), []);
|
|
690
|
+
const getNode = useCallback((id) => getInternalNode(id)?.internals.userNode, [getInternalNode]);
|
|
733
691
|
const getEdges = useCallback(() => {
|
|
734
692
|
const { edges = [] } = store.getState();
|
|
735
693
|
return edges.map((e) => ({ ...e }));
|
|
@@ -867,22 +825,19 @@ function useReactFlow() {
|
|
|
867
825
|
}
|
|
868
826
|
return { deletedNodes: matchingNodes, deletedEdges: matchingEdges };
|
|
869
827
|
}, []);
|
|
870
|
-
const getNodeRect = useCallback((
|
|
871
|
-
const
|
|
872
|
-
|
|
873
|
-
if (!isRect && !node) {
|
|
874
|
-
return [null, null, isRect];
|
|
875
|
-
}
|
|
876
|
-
const nodeRect = isRect ? nodeOrRect : nodeToRect(node);
|
|
877
|
-
return [nodeRect, node, isRect];
|
|
828
|
+
const getNodeRect = useCallback(({ id }) => {
|
|
829
|
+
const internalNode = store.getState().nodeLookup.get(id);
|
|
830
|
+
return internalNode ? nodeToRect(internalNode) : null;
|
|
878
831
|
}, []);
|
|
879
832
|
const getIntersectingNodes = useCallback((nodeOrRect, partially = true, nodes) => {
|
|
880
|
-
const
|
|
833
|
+
const isRect = isRectObject(nodeOrRect);
|
|
834
|
+
const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
881
835
|
if (!nodeRect) {
|
|
882
836
|
return [];
|
|
883
837
|
}
|
|
884
838
|
return (nodes || store.getState().nodes).filter((n) => {
|
|
885
|
-
|
|
839
|
+
const internalNode = store.getState().nodeLookup.get(n.id);
|
|
840
|
+
if (internalNode && !isRect && (n.id === nodeOrRect.id || !internalNode.internals.positionAbsolute)) {
|
|
886
841
|
return false;
|
|
887
842
|
}
|
|
888
843
|
const currNodeRect = nodeToRect(n);
|
|
@@ -892,7 +847,8 @@ function useReactFlow() {
|
|
|
892
847
|
});
|
|
893
848
|
}, []);
|
|
894
849
|
const isNodeIntersecting = useCallback((nodeOrRect, area, partially = true) => {
|
|
895
|
-
const
|
|
850
|
+
const isRect = isRectObject(nodeOrRect);
|
|
851
|
+
const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
896
852
|
if (!nodeRect) {
|
|
897
853
|
return false;
|
|
898
854
|
}
|
|
@@ -920,6 +876,7 @@ function useReactFlow() {
|
|
|
920
876
|
...viewportHelper,
|
|
921
877
|
getNodes,
|
|
922
878
|
getNode,
|
|
879
|
+
getInternalNode,
|
|
923
880
|
getEdges,
|
|
924
881
|
getEdge,
|
|
925
882
|
setNodes,
|
|
@@ -937,6 +894,7 @@ function useReactFlow() {
|
|
|
937
894
|
viewportHelper,
|
|
938
895
|
getNodes,
|
|
939
896
|
getNode,
|
|
897
|
+
getInternalNode,
|
|
940
898
|
getEdges,
|
|
941
899
|
getEdge,
|
|
942
900
|
setNodes,
|
|
@@ -1186,7 +1144,7 @@ function Pane({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag, onSe
|
|
|
1186
1144
|
onSelectionStart?.(event);
|
|
1187
1145
|
};
|
|
1188
1146
|
const onMouseMove = (event) => {
|
|
1189
|
-
const { userSelectionRect,
|
|
1147
|
+
const { userSelectionRect, edgeLookup, transform, nodeOrigin, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = store.getState();
|
|
1190
1148
|
if (!isSelecting || !containerBounds.current || !userSelectionRect) {
|
|
1191
1149
|
return;
|
|
1192
1150
|
}
|
|
@@ -1201,25 +1159,25 @@ function Pane({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag, onSe
|
|
|
1201
1159
|
width: Math.abs(mousePos.x - startX),
|
|
1202
1160
|
height: Math.abs(mousePos.y - startY),
|
|
1203
1161
|
};
|
|
1204
|
-
const selectedNodes = getNodesInside(
|
|
1162
|
+
const selectedNodes = getNodesInside(nodeLookup, nextUserSelectRect, transform, selectionMode === SelectionMode.Partial, true, nodeOrigin);
|
|
1205
1163
|
const selectedEdgeIds = new Set();
|
|
1206
1164
|
const selectedNodeIds = new Set();
|
|
1207
1165
|
for (const selectedNode of selectedNodes) {
|
|
1208
1166
|
selectedNodeIds.add(selectedNode.id);
|
|
1209
|
-
for (const edge of
|
|
1167
|
+
for (const [edgeId, edge] of edgeLookup) {
|
|
1210
1168
|
if (edge.source === selectedNode.id || edge.target === selectedNode.id) {
|
|
1211
|
-
selectedEdgeIds.add(
|
|
1169
|
+
selectedEdgeIds.add(edgeId);
|
|
1212
1170
|
}
|
|
1213
1171
|
}
|
|
1214
1172
|
}
|
|
1215
1173
|
if (prevSelectedNodesCount.current !== selectedNodeIds.size) {
|
|
1216
1174
|
prevSelectedNodesCount.current = selectedNodeIds.size;
|
|
1217
|
-
const changes = getSelectionChanges(
|
|
1175
|
+
const changes = getSelectionChanges(nodeLookup, selectedNodeIds, true);
|
|
1218
1176
|
triggerNodeChanges(changes);
|
|
1219
1177
|
}
|
|
1220
1178
|
if (prevSelectedEdgesCount.current !== selectedEdgeIds.size) {
|
|
1221
1179
|
prevSelectedEdgesCount.current = selectedEdgeIds.size;
|
|
1222
|
-
const changes = getSelectionChanges(
|
|
1180
|
+
const changes = getSelectionChanges(edgeLookup, selectedEdgeIds);
|
|
1223
1181
|
triggerEdgeChanges(changes);
|
|
1224
1182
|
}
|
|
1225
1183
|
store.setState({
|
|
@@ -1329,36 +1287,38 @@ const selectedAndDraggable = (nodesDraggable) => (n) => n.selected && (n.draggab
|
|
|
1329
1287
|
function useMoveSelectedNodes() {
|
|
1330
1288
|
const store = useStoreApi();
|
|
1331
1289
|
const moveSelectedNodes = useCallback((params) => {
|
|
1332
|
-
const { nodeExtent,
|
|
1333
|
-
const
|
|
1290
|
+
const { nodeExtent, snapToGrid, snapGrid, nodesDraggable, onError, updateNodePositions, nodeLookup, nodeOrigin } = store.getState();
|
|
1291
|
+
const nodeUpdates = [];
|
|
1292
|
+
const isSelected = selectedAndDraggable(nodesDraggable);
|
|
1334
1293
|
// by default a node moves 5px on each key press
|
|
1335
1294
|
// if snap grid is enabled, we use that for the velocity
|
|
1336
1295
|
const xVelo = snapToGrid ? snapGrid[0] : 5;
|
|
1337
1296
|
const yVelo = snapToGrid ? snapGrid[1] : 5;
|
|
1338
1297
|
const xDiff = params.direction.x * xVelo * params.factor;
|
|
1339
1298
|
const yDiff = params.direction.y * yVelo * params.factor;
|
|
1340
|
-
const
|
|
1341
|
-
if (node
|
|
1342
|
-
|
|
1343
|
-
x: node.computed.positionAbsolute.x + xDiff,
|
|
1344
|
-
y: node.computed.positionAbsolute.y + yDiff,
|
|
1345
|
-
};
|
|
1346
|
-
if (snapToGrid) {
|
|
1347
|
-
nextPosition = snapPosition(nextPosition, snapGrid);
|
|
1348
|
-
}
|
|
1349
|
-
const { position, positionAbsolute } = calculateNodePosition({
|
|
1350
|
-
nodeId: node.id,
|
|
1351
|
-
nextPosition,
|
|
1352
|
-
nodeLookup,
|
|
1353
|
-
nodeExtent,
|
|
1354
|
-
nodeOrigin,
|
|
1355
|
-
onError,
|
|
1356
|
-
});
|
|
1357
|
-
node.position = position;
|
|
1358
|
-
node.computed.positionAbsolute = positionAbsolute;
|
|
1299
|
+
for (const [, node] of nodeLookup) {
|
|
1300
|
+
if (!isSelected(node)) {
|
|
1301
|
+
continue;
|
|
1359
1302
|
}
|
|
1360
|
-
|
|
1361
|
-
|
|
1303
|
+
let nextPosition = {
|
|
1304
|
+
x: node.internals.positionAbsolute.x + xDiff,
|
|
1305
|
+
y: node.internals.positionAbsolute.y + yDiff,
|
|
1306
|
+
};
|
|
1307
|
+
if (snapToGrid) {
|
|
1308
|
+
nextPosition = snapPosition(nextPosition, snapGrid);
|
|
1309
|
+
}
|
|
1310
|
+
const { position, positionAbsolute } = calculateNodePosition({
|
|
1311
|
+
nodeId: node.id,
|
|
1312
|
+
nextPosition,
|
|
1313
|
+
nodeLookup,
|
|
1314
|
+
nodeExtent,
|
|
1315
|
+
nodeOrigin,
|
|
1316
|
+
onError,
|
|
1317
|
+
});
|
|
1318
|
+
node.position = position;
|
|
1319
|
+
node.internals.positionAbsolute = positionAbsolute;
|
|
1320
|
+
nodeUpdates.push(node);
|
|
1321
|
+
}
|
|
1362
1322
|
updateNodePositions(nodeUpdates);
|
|
1363
1323
|
}, []);
|
|
1364
1324
|
return moveSelectedNodes;
|
|
@@ -1427,7 +1387,7 @@ function HandleComponent({ type = 'source', position = Position.Top, isValidConn
|
|
|
1427
1387
|
connectionMode: currentStore.connectionMode,
|
|
1428
1388
|
connectionRadius: currentStore.connectionRadius,
|
|
1429
1389
|
domNode: currentStore.domNode,
|
|
1430
|
-
|
|
1390
|
+
nodeLookup: currentStore.nodeLookup,
|
|
1431
1391
|
lib: currentStore.lib,
|
|
1432
1392
|
isTarget,
|
|
1433
1393
|
handleId,
|
|
@@ -1441,6 +1401,7 @@ function HandleComponent({ type = 'source', position = Position.Top, isValidConn
|
|
|
1441
1401
|
onConnect: onConnectExtended,
|
|
1442
1402
|
isValidConnection: isValidConnection || currentStore.isValidConnection,
|
|
1443
1403
|
getTransform: () => store.getState().transform,
|
|
1404
|
+
getConnectionStartHandle: () => store.getState().connectionStartHandle,
|
|
1444
1405
|
});
|
|
1445
1406
|
}
|
|
1446
1407
|
if (isMouseTriggered) {
|
|
@@ -1510,7 +1471,7 @@ function HandleComponent({ type = 'source', position = Position.Top, isValidConn
|
|
|
1510
1471
|
/**
|
|
1511
1472
|
* The Handle component is a UI element that is used to connect nodes.
|
|
1512
1473
|
*/
|
|
1513
|
-
const Handle = memo(
|
|
1474
|
+
const Handle = memo(fixedForwardRef(HandleComponent));
|
|
1514
1475
|
|
|
1515
1476
|
function InputNode({ data, isConnectable, sourcePosition = Position.Bottom }) {
|
|
1516
1477
|
return (jsxs(Fragment, { children: [data?.label, jsx(Handle, { type: "source", position: sourcePosition, isConnectable: isConnectable })] }));
|
|
@@ -1541,7 +1502,7 @@ const builtinNodeTypes = {
|
|
|
1541
1502
|
group: GroupNode,
|
|
1542
1503
|
};
|
|
1543
1504
|
function getNodeInlineStyleDimensions(node) {
|
|
1544
|
-
if (
|
|
1505
|
+
if (node.internals.handleBounds === undefined) {
|
|
1545
1506
|
return {
|
|
1546
1507
|
width: node.width ?? node.initialWidth ?? node.style?.width,
|
|
1547
1508
|
height: node.height ?? node.initialHeight ?? node.style?.height,
|
|
@@ -1554,7 +1515,12 @@ function getNodeInlineStyleDimensions(node) {
|
|
|
1554
1515
|
}
|
|
1555
1516
|
|
|
1556
1517
|
const selector$h = (s) => {
|
|
1557
|
-
const selectedNodes =
|
|
1518
|
+
const selectedNodes = [];
|
|
1519
|
+
for (const [, node] of s.nodeLookup) {
|
|
1520
|
+
if (node.selected) {
|
|
1521
|
+
selectedNodes.push(node);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1558
1524
|
const { width, height, x, y } = getNodesBounds(selectedNodes, { nodeOrigin: s.nodeOrigin });
|
|
1559
1525
|
return {
|
|
1560
1526
|
width,
|
|
@@ -1621,7 +1587,7 @@ const FlowRenderer = memo(FlowRendererComponent);
|
|
|
1621
1587
|
|
|
1622
1588
|
const selector$f = (onlyRenderVisible) => (s) => {
|
|
1623
1589
|
return onlyRenderVisible
|
|
1624
|
-
? getNodesInside(s.
|
|
1590
|
+
? getNodesInside(s.nodeLookup, { x: 0, y: 0, width: s.width, height: s.height }, s.transform, true).map((node) => node.id)
|
|
1625
1591
|
: Array.from(s.nodeLookup.keys());
|
|
1626
1592
|
};
|
|
1627
1593
|
/**
|
|
@@ -1651,7 +1617,6 @@ function useResizeObserver() {
|
|
|
1651
1617
|
updates.set(id, {
|
|
1652
1618
|
id,
|
|
1653
1619
|
nodeElement: entry.target,
|
|
1654
|
-
forceUpdate: true,
|
|
1655
1620
|
});
|
|
1656
1621
|
});
|
|
1657
1622
|
updateNodeDimensions(updates);
|
|
@@ -1671,16 +1636,16 @@ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
|
|
|
1671
1636
|
const { node, positionAbsoluteX, positionAbsoluteY, zIndex, isParent } = useStore((s) => {
|
|
1672
1637
|
const node = s.nodeLookup.get(id);
|
|
1673
1638
|
const positionAbsolute = nodeExtent
|
|
1674
|
-
? clampPosition(node.
|
|
1675
|
-
: node.
|
|
1639
|
+
? clampPosition(node.internals.positionAbsolute, nodeExtent)
|
|
1640
|
+
: node.internals.positionAbsolute || { x: 0, y: 0 };
|
|
1676
1641
|
return {
|
|
1677
1642
|
node,
|
|
1678
1643
|
// we are mutating positionAbsolute, z and isParent attributes for sub flows
|
|
1679
1644
|
// so we we need to force a re-render when some change
|
|
1680
1645
|
positionAbsoluteX: positionAbsolute.x,
|
|
1681
1646
|
positionAbsoluteY: positionAbsolute.y,
|
|
1682
|
-
zIndex: node
|
|
1683
|
-
isParent:
|
|
1647
|
+
zIndex: node.internals.z,
|
|
1648
|
+
isParent: node.internals.isParent,
|
|
1684
1649
|
};
|
|
1685
1650
|
}, shallow);
|
|
1686
1651
|
let nodeType = node.type || 'default';
|
|
@@ -1702,12 +1667,13 @@ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
|
|
|
1702
1667
|
const nodeDimensions = getNodeDimensions(node);
|
|
1703
1668
|
const inlineDimensions = getNodeInlineStyleDimensions(node);
|
|
1704
1669
|
const initialized = nodeHasDimensions(node);
|
|
1705
|
-
const hasHandleBounds = !!node
|
|
1670
|
+
const hasHandleBounds = !!node.internals.handleBounds;
|
|
1706
1671
|
const moveSelectedNodes = useMoveSelectedNodes();
|
|
1707
1672
|
useEffect(() => {
|
|
1673
|
+
const currNode = nodeRef.current;
|
|
1708
1674
|
return () => {
|
|
1709
|
-
if (
|
|
1710
|
-
resizeObserver?.unobserve(
|
|
1675
|
+
if (currNode) {
|
|
1676
|
+
resizeObserver?.unobserve(currNode);
|
|
1711
1677
|
}
|
|
1712
1678
|
};
|
|
1713
1679
|
}, []);
|
|
@@ -1735,7 +1701,7 @@ function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
|
|
|
1735
1701
|
if (targetPosChanged) {
|
|
1736
1702
|
prevTargetPosition.current = node.targetPosition;
|
|
1737
1703
|
}
|
|
1738
|
-
store.getState().updateNodeDimensions(new Map([[id, { id, nodeElement: nodeRef.current,
|
|
1704
|
+
store.getState().updateNodeDimensions(new Map([[id, { id, nodeElement: nodeRef.current, force: true }]]));
|
|
1739
1705
|
}
|
|
1740
1706
|
}, [id, nodeType, node.sourcePosition, node.targetPosition]);
|
|
1741
1707
|
const dragging = useDrag({
|
|
@@ -2158,7 +2124,7 @@ function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, targetHandleI
|
|
|
2158
2124
|
if (event.button !== 0) {
|
|
2159
2125
|
return;
|
|
2160
2126
|
}
|
|
2161
|
-
const { autoPanOnConnect, domNode, isValidConnection, connectionMode, connectionRadius, lib, onConnectStart, onConnectEnd, cancelConnection,
|
|
2127
|
+
const { autoPanOnConnect, domNode, isValidConnection, connectionMode, connectionRadius, lib, onConnectStart, onConnectEnd, cancelConnection, nodeLookup, rfId: flowId, panBy, updateConnection, } = store.getState();
|
|
2162
2128
|
const nodeId = isSourceHandle ? edge.target : edge.source;
|
|
2163
2129
|
const handleId = (isSourceHandle ? targetHandleId : sourceHandleId) || null;
|
|
2164
2130
|
const handleType = isSourceHandle ? 'target' : 'source';
|
|
@@ -2177,7 +2143,7 @@ function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, targetHandleI
|
|
|
2177
2143
|
domNode,
|
|
2178
2144
|
handleId,
|
|
2179
2145
|
nodeId,
|
|
2180
|
-
|
|
2146
|
+
nodeLookup,
|
|
2181
2147
|
isTarget,
|
|
2182
2148
|
edgeUpdaterType: handleType,
|
|
2183
2149
|
lib,
|
|
@@ -2191,6 +2157,7 @@ function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, targetHandleI
|
|
|
2191
2157
|
onEdgeUpdateEnd: _onEdgeUpdateEnd,
|
|
2192
2158
|
updateConnection,
|
|
2193
2159
|
getTransform: () => store.getState().transform,
|
|
2160
|
+
getConnectionStartHandle: () => store.getState().connectionStartHandle,
|
|
2194
2161
|
});
|
|
2195
2162
|
};
|
|
2196
2163
|
const onEdgeUpdaterSourceMouseDown = (event) => handleEdgeUpdater(event, true);
|
|
@@ -2397,7 +2364,7 @@ const ConnectionLine = ({ nodeId, handleType, style, type = ConnectionLineType.B
|
|
|
2397
2364
|
toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2],
|
|
2398
2365
|
connectionMode: s.connectionMode,
|
|
2399
2366
|
}), [nodeId]), shallow);
|
|
2400
|
-
const fromHandleBounds = fromNode?.
|
|
2367
|
+
const fromHandleBounds = fromNode?.internals?.handleBounds;
|
|
2401
2368
|
let handleBounds = fromHandleBounds?.[handleType];
|
|
2402
2369
|
if (connectionMode === ConnectionMode.Loose) {
|
|
2403
2370
|
handleBounds = handleBounds ? handleBounds : fromHandleBounds?.[handleType === 'source' ? 'target' : 'source'];
|
|
@@ -2406,10 +2373,10 @@ const ConnectionLine = ({ nodeId, handleType, style, type = ConnectionLineType.B
|
|
|
2406
2373
|
return null;
|
|
2407
2374
|
}
|
|
2408
2375
|
const fromHandle = handleId ? handleBounds.find((d) => d.id === handleId) : handleBounds[0];
|
|
2409
|
-
const fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.
|
|
2410
|
-
const fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.
|
|
2411
|
-
const fromX = (fromNode.
|
|
2412
|
-
const fromY = (fromNode.
|
|
2376
|
+
const fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.measured.width ?? 0) / 2;
|
|
2377
|
+
const fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.measured.height ?? 0;
|
|
2378
|
+
const fromX = (fromNode.internals.positionAbsolute.x ?? 0) + fromHandleX;
|
|
2379
|
+
const fromY = (fromNode.internals.positionAbsolute.y ?? 0) + fromHandleY;
|
|
2413
2380
|
const fromPosition = fromHandle?.position;
|
|
2414
2381
|
const toPosition = fromPosition ? oppositePosition[fromPosition] : null;
|
|
2415
2382
|
if (!fromPosition || !toPosition) {
|
|
@@ -2498,13 +2465,13 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
|
|
|
2498
2465
|
const storeEdges = defaultEdges ?? edges ?? [];
|
|
2499
2466
|
const storeNodes = defaultNodes ?? nodes ?? [];
|
|
2500
2467
|
updateConnectionLookup(connectionLookup, edgeLookup, storeEdges);
|
|
2501
|
-
|
|
2468
|
+
adoptUserNodes(storeNodes, nodeLookup, {
|
|
2502
2469
|
nodeOrigin: [0, 0],
|
|
2503
2470
|
elevateNodesOnSelect: false,
|
|
2504
2471
|
});
|
|
2505
2472
|
let transform = [0, 0, 1];
|
|
2506
2473
|
if (fitView && width && height) {
|
|
2507
|
-
const nodesWithDimensions =
|
|
2474
|
+
const nodesWithDimensions = storeNodes.filter((node) => (node.width || node.initialWidth) && (node.height || node.initialHeight));
|
|
2508
2475
|
// @todo users nodeOrigin should be used here
|
|
2509
2476
|
const bounds = getNodesBounds(nodesWithDimensions, { nodeOrigin: [0, 0] });
|
|
2510
2477
|
const { x, y, zoom } = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
|
|
@@ -2515,7 +2482,7 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
|
|
|
2515
2482
|
width: 0,
|
|
2516
2483
|
height: 0,
|
|
2517
2484
|
transform,
|
|
2518
|
-
nodes:
|
|
2485
|
+
nodes: storeNodes,
|
|
2519
2486
|
nodeLookup,
|
|
2520
2487
|
edges: storeEdges,
|
|
2521
2488
|
edgeLookup,
|
|
@@ -2581,8 +2548,8 @@ const createRFStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height
|
|
|
2581
2548
|
//
|
|
2582
2549
|
// When this happens, we take the note objects passed by the user and extend them with fields
|
|
2583
2550
|
// relevant for internal React Flow operations.
|
|
2584
|
-
|
|
2585
|
-
set({ nodes
|
|
2551
|
+
adoptUserNodes(nodes, nodeLookup, { nodeOrigin, elevateNodesOnSelect });
|
|
2552
|
+
set({ nodes });
|
|
2586
2553
|
},
|
|
2587
2554
|
setEdges: (edges) => {
|
|
2588
2555
|
const { connectionLookup, edgeLookup } = get();
|
|
@@ -2605,25 +2572,18 @@ const createRFStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height
|
|
|
2605
2572
|
// changes its dimensions, this function is called to measure the
|
|
2606
2573
|
// new dimensions and update the nodes.
|
|
2607
2574
|
updateNodeDimensions: (updates) => {
|
|
2608
|
-
const { onNodesChange, fitView,
|
|
2609
|
-
const changes =
|
|
2610
|
-
|
|
2611
|
-
changes.push({
|
|
2612
|
-
id: id,
|
|
2613
|
-
type: 'dimensions',
|
|
2614
|
-
dimensions,
|
|
2615
|
-
});
|
|
2616
|
-
});
|
|
2617
|
-
if (!updatedNodes) {
|
|
2575
|
+
const { onNodesChange, fitView, nodeLookup, fitViewOnInit, fitViewDone, fitViewOnInitOptions, domNode, nodeOrigin, debug, } = get();
|
|
2576
|
+
const changes = updateNodeDimensions(updates, nodeLookup, domNode, nodeOrigin);
|
|
2577
|
+
if (changes.length === 0) {
|
|
2618
2578
|
return;
|
|
2619
2579
|
}
|
|
2620
|
-
|
|
2580
|
+
updateAbsolutePositions(nodeLookup, { nodeOrigin });
|
|
2621
2581
|
// we call fitView once initially after all dimensions are set
|
|
2622
2582
|
let nextFitViewDone = fitViewDone;
|
|
2623
2583
|
if (!fitViewDone && fitViewOnInit) {
|
|
2624
|
-
nextFitViewDone = fitView(
|
|
2584
|
+
nextFitViewDone = fitView({
|
|
2625
2585
|
...fitViewOnInitOptions,
|
|
2626
|
-
nodes: fitViewOnInitOptions?.nodes
|
|
2586
|
+
nodes: fitViewOnInitOptions?.nodes,
|
|
2627
2587
|
});
|
|
2628
2588
|
}
|
|
2629
2589
|
// here we are cirmumventing the onNodesChange handler
|
|
@@ -2631,7 +2591,7 @@ const createRFStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height
|
|
|
2631
2591
|
// has not provided an onNodesChange handler.
|
|
2632
2592
|
// Nodes are only rendered if they have a width and height
|
|
2633
2593
|
// attribute which they get from this handler.
|
|
2634
|
-
set({
|
|
2594
|
+
set({ fitViewDone: nextFitViewDone });
|
|
2635
2595
|
if (changes?.length > 0) {
|
|
2636
2596
|
if (debug) {
|
|
2637
2597
|
console.log('React Flow: trigger node changes', changes);
|
|
@@ -2640,16 +2600,35 @@ const createRFStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height
|
|
|
2640
2600
|
}
|
|
2641
2601
|
},
|
|
2642
2602
|
updateNodePositions: (nodeDragItems, dragging = false) => {
|
|
2603
|
+
const { nodeLookup } = get();
|
|
2604
|
+
const triggerChangeNodes = [];
|
|
2643
2605
|
const changes = nodeDragItems.map((node) => {
|
|
2606
|
+
// @todo add expandParent to drag item so that we can get rid of the look up here
|
|
2607
|
+
const internalNode = nodeLookup.get(node.id);
|
|
2644
2608
|
const change = {
|
|
2645
2609
|
id: node.id,
|
|
2646
2610
|
type: 'position',
|
|
2647
2611
|
position: node.position,
|
|
2648
|
-
positionAbsolute: node.computed?.positionAbsolute,
|
|
2649
2612
|
dragging,
|
|
2650
2613
|
};
|
|
2614
|
+
if (internalNode?.expandParent && change.position) {
|
|
2615
|
+
triggerChangeNodes.push({
|
|
2616
|
+
...internalNode,
|
|
2617
|
+
position: change.position,
|
|
2618
|
+
internals: {
|
|
2619
|
+
...internalNode.internals,
|
|
2620
|
+
positionAbsolute: node.internals.positionAbsolute,
|
|
2621
|
+
},
|
|
2622
|
+
});
|
|
2623
|
+
change.position.x = Math.max(0, change.position.x);
|
|
2624
|
+
change.position.y = Math.max(0, change.position.y);
|
|
2625
|
+
}
|
|
2651
2626
|
return change;
|
|
2652
2627
|
});
|
|
2628
|
+
if (triggerChangeNodes.length > 0) {
|
|
2629
|
+
const parentExpandChanges = handleParentExpand(triggerChangeNodes, nodeLookup);
|
|
2630
|
+
changes.push(...parentExpandChanges);
|
|
2631
|
+
}
|
|
2653
2632
|
get().triggerNodeChanges(changes);
|
|
2654
2633
|
},
|
|
2655
2634
|
triggerNodeChanges: (changes) => {
|
|
@@ -2679,24 +2658,24 @@ const createRFStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height
|
|
|
2679
2658
|
}
|
|
2680
2659
|
},
|
|
2681
2660
|
addSelectedNodes: (selectedNodeIds) => {
|
|
2682
|
-
const { multiSelectionActive,
|
|
2661
|
+
const { multiSelectionActive, edgeLookup, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get();
|
|
2683
2662
|
if (multiSelectionActive) {
|
|
2684
2663
|
const nodeChanges = selectedNodeIds.map((nodeId) => createSelectionChange(nodeId, true));
|
|
2685
2664
|
triggerNodeChanges(nodeChanges);
|
|
2686
2665
|
return;
|
|
2687
2666
|
}
|
|
2688
|
-
triggerNodeChanges(getSelectionChanges(
|
|
2689
|
-
triggerEdgeChanges(getSelectionChanges(
|
|
2667
|
+
triggerNodeChanges(getSelectionChanges(nodeLookup, new Set([...selectedNodeIds]), true));
|
|
2668
|
+
triggerEdgeChanges(getSelectionChanges(edgeLookup));
|
|
2690
2669
|
},
|
|
2691
2670
|
addSelectedEdges: (selectedEdgeIds) => {
|
|
2692
|
-
const { multiSelectionActive,
|
|
2671
|
+
const { multiSelectionActive, edgeLookup, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get();
|
|
2693
2672
|
if (multiSelectionActive) {
|
|
2694
2673
|
const changedEdges = selectedEdgeIds.map((edgeId) => createSelectionChange(edgeId, true));
|
|
2695
2674
|
triggerEdgeChanges(changedEdges);
|
|
2696
2675
|
return;
|
|
2697
2676
|
}
|
|
2698
|
-
triggerEdgeChanges(getSelectionChanges(
|
|
2699
|
-
triggerNodeChanges(getSelectionChanges(
|
|
2677
|
+
triggerEdgeChanges(getSelectionChanges(edgeLookup, new Set([...selectedEdgeIds])));
|
|
2678
|
+
triggerNodeChanges(getSelectionChanges(nodeLookup, new Set(), true));
|
|
2700
2679
|
},
|
|
2701
2680
|
unselectNodesAndEdges: ({ nodes, edges } = {}) => {
|
|
2702
2681
|
const { edges: storeEdges, nodes: storeNodes, triggerNodeChanges, triggerEdgeChanges } = get();
|
|
@@ -2732,32 +2711,32 @@ const createRFStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height
|
|
|
2732
2711
|
triggerEdgeChanges(edgeChanges);
|
|
2733
2712
|
},
|
|
2734
2713
|
setNodeExtent: (nodeExtent) => {
|
|
2735
|
-
const {
|
|
2714
|
+
const { nodeLookup } = get();
|
|
2715
|
+
for (const [, node] of nodeLookup) {
|
|
2716
|
+
const positionAbsolute = clampPosition(node.position, nodeExtent);
|
|
2717
|
+
nodeLookup.set(node.id, {
|
|
2718
|
+
...node,
|
|
2719
|
+
internals: {
|
|
2720
|
+
...node.internals,
|
|
2721
|
+
positionAbsolute,
|
|
2722
|
+
},
|
|
2723
|
+
});
|
|
2724
|
+
}
|
|
2736
2725
|
set({
|
|
2737
2726
|
nodeExtent,
|
|
2738
|
-
nodes: nodes.map((node) => {
|
|
2739
|
-
const positionAbsolute = clampPosition(node.position, nodeExtent);
|
|
2740
|
-
return {
|
|
2741
|
-
...node,
|
|
2742
|
-
computed: {
|
|
2743
|
-
...node.computed,
|
|
2744
|
-
positionAbsolute,
|
|
2745
|
-
},
|
|
2746
|
-
};
|
|
2747
|
-
}),
|
|
2748
2727
|
});
|
|
2749
2728
|
},
|
|
2750
2729
|
panBy: (delta) => {
|
|
2751
2730
|
const { transform, width, height, panZoom, translateExtent } = get();
|
|
2752
2731
|
return panBy({ delta, panZoom, transform, translateExtent, width, height });
|
|
2753
2732
|
},
|
|
2754
|
-
fitView: (
|
|
2755
|
-
const { panZoom, width, height, minZoom, maxZoom, nodeOrigin } = get();
|
|
2733
|
+
fitView: (options) => {
|
|
2734
|
+
const { panZoom, width, height, minZoom, maxZoom, nodeOrigin, nodeLookup } = get();
|
|
2756
2735
|
if (!panZoom) {
|
|
2757
2736
|
return false;
|
|
2758
2737
|
}
|
|
2759
2738
|
return fitView({
|
|
2760
|
-
|
|
2739
|
+
nodeLookup,
|
|
2761
2740
|
width,
|
|
2762
2741
|
height,
|
|
2763
2742
|
panZoom,
|
|
@@ -2820,7 +2799,7 @@ function ReactFlow({ nodes, edges, defaultNodes, defaultEdges, className, nodeTy
|
|
|
2820
2799
|
const colorModeClassName = useColorModeClass(colorMode);
|
|
2821
2800
|
return (jsx("div", { ...rest, style: { ...style, ...wrapperStyle }, ref: ref, className: cc(['react-flow', className, colorModeClassName]), "data-testid": "rf__wrapper", id: id, children: jsxs(Wrapper, { nodes: nodes, edges: edges, width: width, height: height, fitView: fitView, children: [jsx(GraphView, { onInit: onInit, onNodeClick: onNodeClick, onEdgeClick: onEdgeClick, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave, onNodeContextMenu: onNodeContextMenu, onNodeDoubleClick: onNodeDoubleClick, nodeTypes: nodeTypes, edgeTypes: edgeTypes, connectionLineType: connectionLineType, connectionLineStyle: connectionLineStyle, connectionLineComponent: connectionLineComponent, connectionLineContainerStyle: connectionLineContainerStyle, selectionKeyCode: selectionKeyCode, selectionOnDrag: selectionOnDrag, selectionMode: selectionMode, deleteKeyCode: deleteKeyCode, multiSelectionKeyCode: multiSelectionKeyCode, panActivationKeyCode: panActivationKeyCode, zoomActivationKeyCode: zoomActivationKeyCode, onlyRenderVisibleElements: onlyRenderVisibleElements, defaultViewport: defaultViewport$1, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, preventScrolling: preventScrolling, zoomOnScroll: zoomOnScroll, zoomOnPinch: zoomOnPinch, zoomOnDoubleClick: zoomOnDoubleClick, panOnScroll: panOnScroll, panOnScrollSpeed: panOnScrollSpeed, panOnScrollMode: panOnScrollMode, panOnDrag: panOnDrag, onPaneClick: onPaneClick, onPaneMouseEnter: onPaneMouseEnter, onPaneMouseMove: onPaneMouseMove, onPaneMouseLeave: onPaneMouseLeave, onPaneScroll: onPaneScroll, onPaneContextMenu: onPaneContextMenu, onSelectionContextMenu: onSelectionContextMenu, onSelectionStart: onSelectionStart, onSelectionEnd: onSelectionEnd, onEdgeUpdate: onEdgeUpdate, onEdgeContextMenu: onEdgeContextMenu, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd, edgeUpdaterRadius: edgeUpdaterRadius, defaultMarkerColor: defaultMarkerColor, noDragClassName: noDragClassName, noWheelClassName: noWheelClassName, noPanClassName: noPanClassName, rfId: rfId, disableKeyboardA11y: disableKeyboardA11y, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent, viewport: viewport, onViewportChange: onViewportChange }), jsx(StoreUpdater, { nodes: nodes, edges: edges, defaultNodes: defaultNodes, defaultEdges: defaultEdges, onConnect: onConnect, onConnectStart: onConnectStart, onConnectEnd: onConnectEnd, onClickConnectStart: onClickConnectStart, onClickConnectEnd: onClickConnectEnd, nodesDraggable: nodesDraggable, nodesConnectable: nodesConnectable, nodesFocusable: nodesFocusable, edgesFocusable: edgesFocusable, edgesUpdatable: edgesUpdatable, elementsSelectable: elementsSelectable, elevateNodesOnSelect: elevateNodesOnSelect, elevateEdgesOnSelect: elevateEdgesOnSelect, minZoom: minZoom, maxZoom: maxZoom, nodeExtent: nodeExtent, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, snapToGrid: snapToGrid, snapGrid: snapGrid, connectionMode: connectionMode, translateExtent: translateExtent, connectOnClick: connectOnClick, defaultEdgeOptions: defaultEdgeOptions, fitView: fitView, fitViewOptions: fitViewOptions, onNodesDelete: onNodesDelete, onEdgesDelete: onEdgesDelete, onDelete: onDelete, onNodeDragStart: onNodeDragStart, onNodeDrag: onNodeDrag, onNodeDragStop: onNodeDragStop, onSelectionDrag: onSelectionDrag, onSelectionDragStart: onSelectionDragStart, onSelectionDragStop: onSelectionDragStop, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, noPanClassName: noPanClassName, nodeOrigin: nodeOrigin, rfId: rfId, autoPanOnConnect: autoPanOnConnect, autoPanOnNodeDrag: autoPanOnNodeDrag, onError: onError, connectionRadius: connectionRadius, isValidConnection: isValidConnection, selectNodesOnDrag: selectNodesOnDrag, nodeDragThreshold: nodeDragThreshold, onBeforeDelete: onBeforeDelete, debug: debug }), jsx(SelectionListener, { onSelectionChange: onSelectionChange }), children, jsx(Attribution, { proOptions: proOptions, position: attributionPosition }), jsx(A11yDescriptions, { rfId: rfId, disableKeyboardA11y: disableKeyboardA11y })] }) }));
|
|
2822
2801
|
}
|
|
2823
|
-
var index =
|
|
2802
|
+
var index = fixedForwardRef(ReactFlow);
|
|
2824
2803
|
|
|
2825
2804
|
const selector$8 = (s) => s.domNode?.querySelector('.react-flow__edgelabel-renderer');
|
|
2826
2805
|
function EdgeLabelRenderer({ children }) {
|
|
@@ -2855,7 +2834,7 @@ function useUpdateNodeInternals() {
|
|
|
2855
2834
|
updateIds.forEach((updateId) => {
|
|
2856
2835
|
const nodeElement = domNode?.querySelector(`.react-flow__node[data-id="${updateId}"]`);
|
|
2857
2836
|
if (nodeElement) {
|
|
2858
|
-
updates.set(updateId, { id: updateId, nodeElement,
|
|
2837
|
+
updates.set(updateId, { id: updateId, nodeElement, force: true });
|
|
2859
2838
|
}
|
|
2860
2839
|
});
|
|
2861
2840
|
requestAnimationFrame(() => updateNodeDimensions(updates));
|
|
@@ -2967,12 +2946,12 @@ function useOnSelectionChange({ onChange }) {
|
|
|
2967
2946
|
}
|
|
2968
2947
|
|
|
2969
2948
|
const selector$6 = (options) => (s) => {
|
|
2970
|
-
if (s.
|
|
2949
|
+
if (s.nodeLookup.size === 0) {
|
|
2971
2950
|
return false;
|
|
2972
2951
|
}
|
|
2973
|
-
for (const node of s.
|
|
2952
|
+
for (const [, node] of s.nodeLookup) {
|
|
2974
2953
|
if (options.includeHiddenNodes || !node.hidden) {
|
|
2975
|
-
if (node
|
|
2954
|
+
if (node.internals.handleBounds === undefined) {
|
|
2976
2955
|
return false;
|
|
2977
2956
|
}
|
|
2978
2957
|
}
|
|
@@ -3060,6 +3039,18 @@ function useConnection() {
|
|
|
3060
3039
|
return ongoingConnection;
|
|
3061
3040
|
}
|
|
3062
3041
|
|
|
3042
|
+
/**
|
|
3043
|
+
* Hook for getting an internal node by id
|
|
3044
|
+
*
|
|
3045
|
+
* @public
|
|
3046
|
+
* @param id - id of the node
|
|
3047
|
+
* @returns array with visible node ids
|
|
3048
|
+
*/
|
|
3049
|
+
function useInternalNode(id) {
|
|
3050
|
+
const node = useStore(useCallback((s) => s.nodeLookup.get(id), [id]), shallow);
|
|
3051
|
+
return node;
|
|
3052
|
+
}
|
|
3053
|
+
|
|
3063
3054
|
function LinePattern({ dimensions, lineWidth, variant, className }) {
|
|
3064
3055
|
return (jsx("path", { strokeWidth: lineWidth, d: `M${dimensions[0] / 2} 0 V${dimensions[1]} M0 ${dimensions[1] / 2} H${dimensions[0]}`, className: cc(['react-flow__background-pattern', variant, className]) }));
|
|
3065
3056
|
}
|
|
@@ -3137,7 +3128,7 @@ const selector$3 = (s) => ({
|
|
|
3137
3128
|
minZoomReached: s.transform[2] <= s.minZoom,
|
|
3138
3129
|
maxZoomReached: s.transform[2] >= s.maxZoom,
|
|
3139
3130
|
});
|
|
3140
|
-
function ControlsComponent({ style, showZoom = true, showFitView = true, showInteractive = true, fitViewOptions, onZoomIn, onZoomOut, onFitView, onInteractiveChange, className, children, position = 'bottom-left', 'aria-label': ariaLabel = 'React Flow controls', }) {
|
|
3131
|
+
function ControlsComponent({ style, showZoom = true, showFitView = true, showInteractive = true, fitViewOptions, onZoomIn, onZoomOut, onFitView, onInteractiveChange, className, children, position = 'bottom-left', orientation = 'vertical', 'aria-label': ariaLabel = 'React Flow controls', }) {
|
|
3141
3132
|
const store = useStoreApi();
|
|
3142
3133
|
const { isInteractive, minZoomReached, maxZoomReached } = useStore(selector$3, shallow);
|
|
3143
3134
|
const { zoomIn, zoomOut, fitView } = useReactFlow();
|
|
@@ -3161,7 +3152,8 @@ function ControlsComponent({ style, showZoom = true, showFitView = true, showInt
|
|
|
3161
3152
|
});
|
|
3162
3153
|
onInteractiveChange?.(!isInteractive);
|
|
3163
3154
|
};
|
|
3164
|
-
|
|
3155
|
+
const orientationClass = orientation === 'horizontal' ? 'horizontal' : 'vertical';
|
|
3156
|
+
return (jsxs(Panel, { className: cc(['react-flow__controls', orientationClass, className]), position: position, style: style, "data-testid": "rf__controls", "aria-label": ariaLabel, children: [showZoom && (jsxs(Fragment, { children: [jsx(ControlButton, { onClick: onZoomInHandler, className: "react-flow__controls-zoomin", title: "zoom in", "aria-label": "zoom in", disabled: maxZoomReached, children: jsx(PlusIcon, {}) }), jsx(ControlButton, { onClick: onZoomOutHandler, className: "react-flow__controls-zoomout", title: "zoom out", "aria-label": "zoom out", disabled: minZoomReached, children: jsx(MinusIcon, {}) })] })), showFitView && (jsx(ControlButton, { className: "react-flow__controls-fitview", onClick: onFitViewHandler, title: "fit view", "aria-label": "fit view", children: jsx(FitViewIcon, {}) })), showInteractive && (jsx(ControlButton, { className: "react-flow__controls-interactive", onClick: onToggleInteractivity, title: "toggle interactivity", "aria-label": "toggle interactivity", children: isInteractive ? jsx(UnlockIcon, {}) : jsx(LockIcon, {}) })), children] }));
|
|
3165
3157
|
}
|
|
3166
3158
|
ControlsComponent.displayName = 'Controls';
|
|
3167
3159
|
const Controls = memo(ControlsComponent);
|
|
@@ -3228,7 +3220,9 @@ const selector$1 = (s) => {
|
|
|
3228
3220
|
};
|
|
3229
3221
|
return {
|
|
3230
3222
|
viewBB,
|
|
3231
|
-
boundingRect: s.
|
|
3223
|
+
boundingRect: s.nodeLookup.size > 0
|
|
3224
|
+
? getBoundsOfRects(getInternalNodesBounds(s.nodeLookup, { nodeOrigin: s.nodeOrigin }), viewBB)
|
|
3225
|
+
: viewBB,
|
|
3232
3226
|
rfId: s.rfId,
|
|
3233
3227
|
nodeOrigin: s.nodeOrigin,
|
|
3234
3228
|
panZoom: s.panZoom,
|
|
@@ -3435,12 +3429,12 @@ function NodeToolbarPortal({ children }) {
|
|
|
3435
3429
|
return createPortal(children, wrapperRef);
|
|
3436
3430
|
}
|
|
3437
3431
|
|
|
3438
|
-
const nodeEqualityFn = (a, b) => a?.
|
|
3439
|
-
a?.
|
|
3440
|
-
a?.
|
|
3441
|
-
a?.
|
|
3432
|
+
const nodeEqualityFn = (a, b) => a?.internals.positionAbsolute.x !== b?.internals.positionAbsolute.x ||
|
|
3433
|
+
a?.internals.positionAbsolute.y !== b?.internals.positionAbsolute.y ||
|
|
3434
|
+
a?.measured.width !== b?.measured.width ||
|
|
3435
|
+
a?.measured.height !== b?.measured.height ||
|
|
3442
3436
|
a?.selected !== b?.selected ||
|
|
3443
|
-
a?.
|
|
3437
|
+
a?.internals.z !== b?.internals.z;
|
|
3444
3438
|
const nodesEqualityFn = (a, b) => {
|
|
3445
3439
|
if (a.length !== b.length) {
|
|
3446
3440
|
return false;
|
|
@@ -3476,7 +3470,7 @@ function NodeToolbar({ nodeId, children, className, style, isVisible, position =
|
|
|
3476
3470
|
return null;
|
|
3477
3471
|
}
|
|
3478
3472
|
const nodeRect = getNodesBounds(nodes, { nodeOrigin });
|
|
3479
|
-
const zIndex = Math.max(...nodes.map((node) => (node
|
|
3473
|
+
const zIndex = Math.max(...nodes.map((node) => (node.internals?.z || 1) + 1));
|
|
3480
3474
|
const wrapperStyle = {
|
|
3481
3475
|
position: 'absolute',
|
|
3482
3476
|
transform: getNodeToolbarTransform(nodeRect, viewport, position, offset, align),
|
|
@@ -3486,4 +3480,4 @@ function NodeToolbar({ nodeId, children, className, style, isVisible, position =
|
|
|
3486
3480
|
return (jsx(NodeToolbarPortal, { children: jsx("div", { style: wrapperStyle, className: cc(['react-flow__node-toolbar', className]), ...rest, "data-id": nodes.reduce((acc, node) => `${acc}${node.id} `, '').trim(), children: children }) }));
|
|
3487
3481
|
}
|
|
3488
3482
|
|
|
3489
|
-
export { Background, BackgroundVariant, BaseEdge, BezierEdge, ControlButton, Controls, EdgeLabelRenderer, EdgeText, Handle, MiniMap, NodeResizeControl, NodeResizer, NodeToolbar, Panel, index as ReactFlow, ReactFlowProvider, SimpleBezierEdge, SmoothStepEdge, StepEdge, StraightEdge, ViewportPortal, applyEdgeChanges, applyNodeChanges, getSimpleBezierPath,
|
|
3483
|
+
export { Background, BackgroundVariant, BaseEdge, BezierEdge, ControlButton, Controls, EdgeLabelRenderer, EdgeText, Handle, MiniMap, NodeResizeControl, NodeResizer, NodeToolbar, Panel, index as ReactFlow, ReactFlowProvider, SimpleBezierEdge, SmoothStepEdge, StepEdge, StraightEdge, ViewportPortal, applyEdgeChanges, applyNodeChanges, getSimpleBezierPath, isEdge, isNode, useConnection, useEdges, useEdgesState, useHandleConnections, useInternalNode, useKeyPress, useNodeId, useNodes, useNodesData, useNodesInitialized, useNodesState, useOnSelectionChange, useOnViewportChange, useReactFlow, useStore, useStoreApi, useUpdateNodeInternals, useViewport };
|