@xyflow/react 12.0.0-next.2 → 12.0.0-next.21
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/LICENSE +1 -1
- package/dist/base.css +145 -22
- package/dist/esm/additional-components/Background/Background.d.ts +5 -5
- package/dist/esm/additional-components/Background/Background.d.ts.map +1 -1
- package/dist/esm/additional-components/Background/Patterns.d.ts.map +1 -1
- package/dist/esm/additional-components/Background/index.d.ts +2 -2
- package/dist/esm/additional-components/Background/index.d.ts.map +1 -1
- package/dist/esm/additional-components/Background/types.d.ts +13 -0
- package/dist/esm/additional-components/Background/types.d.ts.map +1 -1
- package/dist/esm/additional-components/Controls/ControlButton.d.ts +1 -3
- package/dist/esm/additional-components/Controls/ControlButton.d.ts.map +1 -1
- package/dist/esm/additional-components/Controls/Controls.d.ts +7 -3
- package/dist/esm/additional-components/Controls/Controls.d.ts.map +1 -1
- package/dist/esm/additional-components/Controls/Icons/FitView.d.ts +1 -2
- package/dist/esm/additional-components/Controls/Icons/FitView.d.ts.map +1 -1
- package/dist/esm/additional-components/Controls/Icons/Lock.d.ts +1 -2
- package/dist/esm/additional-components/Controls/Icons/Lock.d.ts.map +1 -1
- package/dist/esm/additional-components/Controls/Icons/Minus.d.ts +1 -2
- package/dist/esm/additional-components/Controls/Icons/Minus.d.ts.map +1 -1
- package/dist/esm/additional-components/Controls/Icons/Plus.d.ts +1 -2
- package/dist/esm/additional-components/Controls/Icons/Plus.d.ts.map +1 -1
- package/dist/esm/additional-components/Controls/Icons/Unlock.d.ts +1 -2
- package/dist/esm/additional-components/Controls/Icons/Unlock.d.ts.map +1 -1
- package/dist/esm/additional-components/Controls/index.d.ts +3 -3
- package/dist/esm/additional-components/Controls/index.d.ts.map +1 -1
- package/dist/esm/additional-components/Controls/types.d.ts +21 -2
- package/dist/esm/additional-components/Controls/types.d.ts.map +1 -1
- package/dist/esm/additional-components/MiniMap/MiniMap.d.ts +5 -5
- package/dist/esm/additional-components/MiniMap/MiniMap.d.ts.map +1 -1
- package/dist/esm/additional-components/MiniMap/MiniMapNode.d.ts +3 -3
- package/dist/esm/additional-components/MiniMap/MiniMapNode.d.ts.map +1 -1
- package/dist/esm/additional-components/MiniMap/MiniMapNodes.d.ts +3 -3
- package/dist/esm/additional-components/MiniMap/MiniMapNodes.d.ts.map +1 -1
- package/dist/esm/additional-components/MiniMap/index.d.ts +1 -1
- package/dist/esm/additional-components/MiniMap/index.d.ts.map +1 -1
- package/dist/esm/additional-components/MiniMap/types.d.ts +23 -0
- package/dist/esm/additional-components/MiniMap/types.d.ts.map +1 -1
- package/dist/esm/additional-components/NodeResizer/{ResizeControl.d.ts → NodeResizeControl.d.ts} +4 -4
- package/dist/esm/additional-components/NodeResizer/NodeResizeControl.d.ts.map +1 -0
- package/dist/esm/additional-components/NodeResizer/NodeResizer.d.ts +2 -2
- package/dist/esm/additional-components/NodeResizer/NodeResizer.d.ts.map +1 -1
- package/dist/esm/additional-components/NodeResizer/index.d.ts +2 -2
- package/dist/esm/additional-components/NodeResizer/index.d.ts.map +1 -1
- package/dist/esm/additional-components/NodeResizer/types.d.ts +26 -23
- package/dist/esm/additional-components/NodeResizer/types.d.ts.map +1 -1
- package/dist/esm/additional-components/NodeToolbar/NodeToolbar.d.ts +2 -3
- package/dist/esm/additional-components/NodeToolbar/NodeToolbar.d.ts.map +1 -1
- package/dist/esm/additional-components/NodeToolbar/NodeToolbarPortal.d.ts +1 -2
- package/dist/esm/additional-components/NodeToolbar/NodeToolbarPortal.d.ts.map +1 -1
- package/dist/esm/additional-components/NodeToolbar/index.d.ts +2 -2
- package/dist/esm/additional-components/NodeToolbar/index.d.ts.map +1 -1
- package/dist/esm/additional-components/NodeToolbar/types.d.ts +10 -0
- package/dist/esm/additional-components/NodeToolbar/types.d.ts.map +1 -1
- package/dist/esm/additional-components/index.d.ts.map +1 -1
- package/dist/esm/components/A11yDescriptions/index.d.ts +1 -2
- package/dist/esm/components/A11yDescriptions/index.d.ts.map +1 -1
- package/dist/esm/components/Attribution/index.d.ts +2 -2
- package/dist/esm/components/Attribution/index.d.ts.map +1 -1
- package/dist/esm/components/BatchProvider/index.d.ts +17 -0
- package/dist/esm/components/BatchProvider/index.d.ts.map +1 -0
- package/dist/esm/components/BatchProvider/types.d.ts +7 -0
- package/dist/esm/components/BatchProvider/types.d.ts.map +1 -0
- package/dist/esm/components/BatchProvider/useQueue.d.ts +11 -0
- package/dist/esm/components/BatchProvider/useQueue.d.ts.map +1 -0
- package/dist/esm/components/ConnectionLine/index.d.ts +2 -2
- package/dist/esm/components/ConnectionLine/index.d.ts.map +1 -1
- package/dist/esm/components/EdgeLabelRenderer/index.d.ts +1 -2
- package/dist/esm/components/EdgeLabelRenderer/index.d.ts.map +1 -1
- package/dist/esm/components/EdgeWrapper/EdgeUpdateAnchors.d.ts +7 -7
- package/dist/esm/components/EdgeWrapper/EdgeUpdateAnchors.d.ts.map +1 -1
- package/dist/esm/components/EdgeWrapper/index.d.ts +2 -7
- package/dist/esm/components/EdgeWrapper/index.d.ts.map +1 -1
- package/dist/esm/components/EdgeWrapper/utils.d.ts.map +1 -1
- package/dist/esm/components/Edges/BaseEdge.d.ts +1 -5
- package/dist/esm/components/Edges/BaseEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/BezierEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/EdgeAnchor.d.ts +2 -2
- package/dist/esm/components/Edges/EdgeAnchor.d.ts.map +1 -1
- package/dist/esm/components/Edges/EdgeText.d.ts +7 -3
- package/dist/esm/components/Edges/EdgeText.d.ts.map +1 -1
- package/dist/esm/components/Edges/SimpleBezierEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/SmoothStepEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/StepEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/StraightEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/index.d.ts.map +1 -1
- package/dist/esm/components/Handle/index.d.ts +10 -5
- package/dist/esm/components/Handle/index.d.ts.map +1 -1
- package/dist/esm/components/NodeWrapper/index.d.ts +2 -7
- package/dist/esm/components/NodeWrapper/index.d.ts.map +1 -1
- package/dist/esm/components/NodeWrapper/useNodeObserver.d.ts +15 -0
- package/dist/esm/components/NodeWrapper/useNodeObserver.d.ts.map +1 -0
- package/dist/esm/components/NodeWrapper/utils.d.ts +5 -1
- package/dist/esm/components/NodeWrapper/utils.d.ts.map +1 -1
- package/dist/esm/components/Nodes/DefaultNode.d.ts +2 -7
- package/dist/esm/components/Nodes/DefaultNode.d.ts.map +1 -1
- package/dist/esm/components/Nodes/GroupNode.d.ts +1 -5
- package/dist/esm/components/Nodes/GroupNode.d.ts.map +1 -1
- package/dist/esm/components/Nodes/InputNode.d.ts +2 -7
- package/dist/esm/components/Nodes/InputNode.d.ts.map +1 -1
- package/dist/esm/components/Nodes/OutputNode.d.ts +2 -7
- package/dist/esm/components/Nodes/OutputNode.d.ts.map +1 -1
- package/dist/esm/components/Nodes/utils.d.ts.map +1 -1
- package/dist/esm/components/NodesSelection/index.d.ts +3 -5
- package/dist/esm/components/NodesSelection/index.d.ts.map +1 -1
- package/dist/esm/components/Panel/index.d.ts +5 -3
- package/dist/esm/components/Panel/index.d.ts.map +1 -1
- package/dist/esm/components/ReactFlowProvider/index.d.ts +6 -7
- package/dist/esm/components/ReactFlowProvider/index.d.ts.map +1 -1
- package/dist/esm/components/SelectionListener/index.d.ts +2 -2
- package/dist/esm/components/SelectionListener/index.d.ts.map +1 -1
- package/dist/esm/components/StoreUpdater/index.d.ts +5 -5
- package/dist/esm/components/StoreUpdater/index.d.ts.map +1 -1
- package/dist/esm/components/UserSelection/index.d.ts +1 -2
- package/dist/esm/components/UserSelection/index.d.ts.map +1 -1
- package/dist/esm/components/ViewportPortal/index.d.ts +1 -2
- package/dist/esm/components/ViewportPortal/index.d.ts.map +1 -1
- package/dist/esm/container/EdgeRenderer/MarkerDefinitions.d.ts.map +1 -1
- package/dist/esm/container/EdgeRenderer/MarkerSymbols.d.ts +1 -1
- package/dist/esm/container/EdgeRenderer/MarkerSymbols.d.ts.map +1 -1
- package/dist/esm/container/EdgeRenderer/index.d.ts +8 -6
- package/dist/esm/container/EdgeRenderer/index.d.ts.map +1 -1
- package/dist/esm/container/FlowRenderer/index.d.ts +8 -6
- package/dist/esm/container/FlowRenderer/index.d.ts.map +1 -1
- package/dist/esm/container/GraphView/index.d.ts +8 -8
- package/dist/esm/container/GraphView/index.d.ts.map +1 -1
- package/dist/esm/container/GraphView/useNodeOrEdgeTypesWarning.d.ts +6 -1
- package/dist/esm/container/GraphView/useNodeOrEdgeTypesWarning.d.ts.map +1 -1
- package/dist/esm/container/GraphView/useStylesLoadedWarning.d.ts +2 -0
- package/dist/esm/container/GraphView/useStylesLoadedWarning.d.ts.map +1 -0
- package/dist/esm/container/NodeRenderer/index.d.ts +8 -7
- package/dist/esm/container/NodeRenderer/index.d.ts.map +1 -1
- package/dist/esm/container/NodeRenderer/useResizeObserver.d.ts +1 -1
- package/dist/esm/container/NodeRenderer/useResizeObserver.d.ts.map +1 -1
- package/dist/esm/container/Pane/index.d.ts +2 -2
- package/dist/esm/container/Pane/index.d.ts.map +1 -1
- package/dist/esm/container/ReactFlow/Wrapper.d.ts +3 -5
- package/dist/esm/container/ReactFlow/Wrapper.d.ts.map +1 -1
- package/dist/esm/container/ReactFlow/index.d.ts +4 -119
- package/dist/esm/container/ReactFlow/index.d.ts.map +1 -1
- package/dist/esm/container/ReactFlow/init-values.d.ts +4 -0
- package/dist/esm/container/ReactFlow/init-values.d.ts.map +1 -0
- package/dist/esm/container/Viewport/index.d.ts +1 -1
- package/dist/esm/container/Viewport/index.d.ts.map +1 -1
- package/dist/esm/container/ZoomPane/index.d.ts +2 -2
- package/dist/esm/container/ZoomPane/index.d.ts.map +1 -1
- package/dist/esm/contexts/NodeIdContext.d.ts.map +1 -1
- package/dist/esm/contexts/{RFStoreContext.d.ts → StoreContext.d.ts} +1 -1
- package/dist/esm/contexts/StoreContext.d.ts.map +1 -0
- package/dist/esm/hooks/useColorModeClass.d.ts +1 -1
- package/dist/esm/hooks/useColorModeClass.d.ts.map +1 -1
- package/dist/esm/hooks/useConnection.d.ts +13 -7
- package/dist/esm/hooks/useConnection.d.ts.map +1 -1
- package/dist/esm/hooks/useDrag.d.ts +3 -3
- package/dist/esm/hooks/useDrag.d.ts.map +1 -1
- package/dist/esm/hooks/useEdges.d.ts +1 -2
- package/dist/esm/hooks/useEdges.d.ts.map +1 -1
- package/dist/esm/hooks/useGlobalKeyHandler.d.ts +2 -3
- package/dist/esm/hooks/useGlobalKeyHandler.d.ts.map +1 -1
- package/dist/esm/hooks/useHandleConnections.d.ts +4 -4
- package/dist/esm/hooks/useHandleConnections.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/useIsomorphicLayoutEffect.d.ts +3 -0
- package/dist/esm/hooks/useIsomorphicLayoutEffect.d.ts.map +1 -0
- package/dist/esm/hooks/useKeyPress.d.ts +1 -2
- package/dist/esm/hooks/useKeyPress.d.ts.map +1 -1
- package/dist/esm/hooks/useMoveSelectedNodes.d.ts +12 -0
- package/dist/esm/hooks/useMoveSelectedNodes.d.ts.map +1 -0
- package/dist/esm/hooks/useNodes.d.ts +1 -2
- package/dist/esm/hooks/useNodes.d.ts.map +1 -1
- package/dist/esm/hooks/useNodesData.d.ts +3 -4
- package/dist/esm/hooks/useNodesData.d.ts.map +1 -1
- package/dist/esm/hooks/useNodesEdgesState.d.ts +3 -3
- package/dist/esm/hooks/useNodesEdgesState.d.ts.map +1 -1
- package/dist/esm/hooks/useNodesInitialized.d.ts +1 -2
- package/dist/esm/hooks/useNodesInitialized.d.ts.map +1 -1
- package/dist/esm/hooks/useOnInitHandler.d.ts +2 -3
- package/dist/esm/hooks/useOnInitHandler.d.ts.map +1 -1
- package/dist/esm/hooks/useOnSelectionChange.d.ts +2 -3
- package/dist/esm/hooks/useOnSelectionChange.d.ts.map +1 -1
- package/dist/esm/hooks/useOnViewportChange.d.ts +1 -2
- package/dist/esm/hooks/useOnViewportChange.d.ts.map +1 -1
- package/dist/esm/hooks/useReactFlow.d.ts +1 -1
- package/dist/esm/hooks/useReactFlow.d.ts.map +1 -1
- package/dist/esm/hooks/useResizeHandler.d.ts +1 -2
- package/dist/esm/hooks/useResizeHandler.d.ts.map +1 -1
- package/dist/esm/hooks/useStore.d.ts +10 -11
- package/dist/esm/hooks/useStore.d.ts.map +1 -1
- package/dist/esm/hooks/useUpdateNodeInternals.d.ts +1 -2
- package/dist/esm/hooks/useUpdateNodeInternals.d.ts.map +1 -1
- package/dist/esm/hooks/useViewport.d.ts +1 -2
- package/dist/esm/hooks/useViewport.d.ts.map +1 -1
- package/dist/esm/hooks/useViewportHelper.d.ts.map +1 -1
- package/dist/esm/hooks/useViewportSync.d.ts +1 -1
- package/dist/esm/hooks/useViewportSync.d.ts.map +1 -1
- package/dist/esm/hooks/useVisibleEdgeIds.d.ts +1 -2
- package/dist/esm/hooks/useVisibleEdgeIds.d.ts.map +1 -1
- package/dist/esm/hooks/useVisibleNodeIds.d.ts +1 -2
- package/dist/esm/hooks/useVisibleNodeIds.d.ts.map +1 -1
- package/dist/esm/index.d.ts +22 -21
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1181 -1127
- package/dist/esm/index.mjs +1181 -1127
- package/dist/esm/store/index.d.ts +6 -4
- package/dist/esm/store/index.d.ts.map +1 -1
- package/dist/esm/store/initialState.d.ts +5 -3
- package/dist/esm/store/initialState.d.ts.map +1 -1
- package/dist/esm/styles/utils.d.ts.map +1 -1
- package/dist/esm/types/component-props.d.ts +380 -38
- package/dist/esm/types/component-props.d.ts.map +1 -1
- package/dist/esm/types/edges.d.ts +35 -25
- package/dist/esm/types/edges.d.ts.map +1 -1
- package/dist/esm/types/general.d.ts +99 -20
- 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 +146 -44
- package/dist/esm/types/instance.d.ts.map +1 -1
- package/dist/esm/types/nodes.d.ts +23 -12
- package/dist/esm/types/nodes.d.ts.map +1 -1
- package/dist/esm/types/store.d.ts +26 -23
- package/dist/esm/types/store.d.ts.map +1 -1
- package/dist/esm/utils/changes.d.ts +25 -7
- package/dist/esm/utils/changes.d.ts.map +1 -1
- package/dist/esm/utils/general.d.ts +4 -49
- package/dist/esm/utils/general.d.ts.map +1 -1
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/style.css +68 -32
- package/dist/umd/additional-components/Background/Background.d.ts +5 -5
- package/dist/umd/additional-components/Background/Background.d.ts.map +1 -1
- package/dist/umd/additional-components/Background/Patterns.d.ts.map +1 -1
- package/dist/umd/additional-components/Background/index.d.ts +2 -2
- package/dist/umd/additional-components/Background/index.d.ts.map +1 -1
- package/dist/umd/additional-components/Background/types.d.ts +13 -0
- package/dist/umd/additional-components/Background/types.d.ts.map +1 -1
- package/dist/umd/additional-components/Controls/ControlButton.d.ts +1 -3
- package/dist/umd/additional-components/Controls/ControlButton.d.ts.map +1 -1
- package/dist/umd/additional-components/Controls/Controls.d.ts +7 -3
- package/dist/umd/additional-components/Controls/Controls.d.ts.map +1 -1
- package/dist/umd/additional-components/Controls/Icons/FitView.d.ts +1 -2
- package/dist/umd/additional-components/Controls/Icons/FitView.d.ts.map +1 -1
- package/dist/umd/additional-components/Controls/Icons/Lock.d.ts +1 -2
- package/dist/umd/additional-components/Controls/Icons/Lock.d.ts.map +1 -1
- package/dist/umd/additional-components/Controls/Icons/Minus.d.ts +1 -2
- package/dist/umd/additional-components/Controls/Icons/Minus.d.ts.map +1 -1
- package/dist/umd/additional-components/Controls/Icons/Plus.d.ts +1 -2
- package/dist/umd/additional-components/Controls/Icons/Plus.d.ts.map +1 -1
- package/dist/umd/additional-components/Controls/Icons/Unlock.d.ts +1 -2
- package/dist/umd/additional-components/Controls/Icons/Unlock.d.ts.map +1 -1
- package/dist/umd/additional-components/Controls/index.d.ts +3 -3
- package/dist/umd/additional-components/Controls/index.d.ts.map +1 -1
- package/dist/umd/additional-components/Controls/types.d.ts +21 -2
- package/dist/umd/additional-components/Controls/types.d.ts.map +1 -1
- package/dist/umd/additional-components/MiniMap/MiniMap.d.ts +5 -5
- package/dist/umd/additional-components/MiniMap/MiniMap.d.ts.map +1 -1
- package/dist/umd/additional-components/MiniMap/MiniMapNode.d.ts +3 -3
- package/dist/umd/additional-components/MiniMap/MiniMapNode.d.ts.map +1 -1
- package/dist/umd/additional-components/MiniMap/MiniMapNodes.d.ts +3 -3
- package/dist/umd/additional-components/MiniMap/MiniMapNodes.d.ts.map +1 -1
- package/dist/umd/additional-components/MiniMap/index.d.ts +1 -1
- package/dist/umd/additional-components/MiniMap/index.d.ts.map +1 -1
- package/dist/umd/additional-components/MiniMap/types.d.ts +23 -0
- package/dist/umd/additional-components/MiniMap/types.d.ts.map +1 -1
- package/dist/umd/additional-components/NodeResizer/{ResizeControl.d.ts → NodeResizeControl.d.ts} +4 -4
- package/dist/umd/additional-components/NodeResizer/NodeResizeControl.d.ts.map +1 -0
- package/dist/umd/additional-components/NodeResizer/NodeResizer.d.ts +2 -2
- package/dist/umd/additional-components/NodeResizer/NodeResizer.d.ts.map +1 -1
- package/dist/umd/additional-components/NodeResizer/index.d.ts +2 -2
- package/dist/umd/additional-components/NodeResizer/index.d.ts.map +1 -1
- package/dist/umd/additional-components/NodeResizer/types.d.ts +26 -23
- package/dist/umd/additional-components/NodeResizer/types.d.ts.map +1 -1
- package/dist/umd/additional-components/NodeToolbar/NodeToolbar.d.ts +2 -3
- package/dist/umd/additional-components/NodeToolbar/NodeToolbar.d.ts.map +1 -1
- package/dist/umd/additional-components/NodeToolbar/NodeToolbarPortal.d.ts +1 -2
- package/dist/umd/additional-components/NodeToolbar/NodeToolbarPortal.d.ts.map +1 -1
- package/dist/umd/additional-components/NodeToolbar/index.d.ts +2 -2
- package/dist/umd/additional-components/NodeToolbar/index.d.ts.map +1 -1
- package/dist/umd/additional-components/NodeToolbar/types.d.ts +10 -0
- package/dist/umd/additional-components/NodeToolbar/types.d.ts.map +1 -1
- package/dist/umd/additional-components/index.d.ts.map +1 -1
- package/dist/umd/components/A11yDescriptions/index.d.ts +1 -2
- package/dist/umd/components/A11yDescriptions/index.d.ts.map +1 -1
- package/dist/umd/components/Attribution/index.d.ts +2 -2
- package/dist/umd/components/Attribution/index.d.ts.map +1 -1
- package/dist/umd/components/BatchProvider/index.d.ts +17 -0
- package/dist/umd/components/BatchProvider/index.d.ts.map +1 -0
- package/dist/umd/components/BatchProvider/types.d.ts +7 -0
- package/dist/umd/components/BatchProvider/types.d.ts.map +1 -0
- package/dist/umd/components/BatchProvider/useQueue.d.ts +11 -0
- package/dist/umd/components/BatchProvider/useQueue.d.ts.map +1 -0
- package/dist/umd/components/ConnectionLine/index.d.ts +2 -2
- package/dist/umd/components/ConnectionLine/index.d.ts.map +1 -1
- package/dist/umd/components/EdgeLabelRenderer/index.d.ts +1 -2
- package/dist/umd/components/EdgeLabelRenderer/index.d.ts.map +1 -1
- package/dist/umd/components/EdgeWrapper/EdgeUpdateAnchors.d.ts +7 -7
- package/dist/umd/components/EdgeWrapper/EdgeUpdateAnchors.d.ts.map +1 -1
- package/dist/umd/components/EdgeWrapper/index.d.ts +2 -7
- package/dist/umd/components/EdgeWrapper/index.d.ts.map +1 -1
- package/dist/umd/components/EdgeWrapper/utils.d.ts.map +1 -1
- package/dist/umd/components/Edges/BaseEdge.d.ts +1 -5
- package/dist/umd/components/Edges/BaseEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/BezierEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/EdgeAnchor.d.ts +2 -2
- package/dist/umd/components/Edges/EdgeAnchor.d.ts.map +1 -1
- package/dist/umd/components/Edges/EdgeText.d.ts +7 -3
- package/dist/umd/components/Edges/EdgeText.d.ts.map +1 -1
- package/dist/umd/components/Edges/SimpleBezierEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/SmoothStepEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/StepEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/StraightEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/index.d.ts.map +1 -1
- package/dist/umd/components/Handle/index.d.ts +10 -5
- package/dist/umd/components/Handle/index.d.ts.map +1 -1
- package/dist/umd/components/NodeWrapper/index.d.ts +2 -7
- package/dist/umd/components/NodeWrapper/index.d.ts.map +1 -1
- package/dist/umd/components/NodeWrapper/useNodeObserver.d.ts +15 -0
- package/dist/umd/components/NodeWrapper/useNodeObserver.d.ts.map +1 -0
- package/dist/umd/components/NodeWrapper/utils.d.ts +5 -1
- package/dist/umd/components/NodeWrapper/utils.d.ts.map +1 -1
- package/dist/umd/components/Nodes/DefaultNode.d.ts +2 -7
- package/dist/umd/components/Nodes/DefaultNode.d.ts.map +1 -1
- package/dist/umd/components/Nodes/GroupNode.d.ts +1 -5
- package/dist/umd/components/Nodes/GroupNode.d.ts.map +1 -1
- package/dist/umd/components/Nodes/InputNode.d.ts +2 -7
- package/dist/umd/components/Nodes/InputNode.d.ts.map +1 -1
- package/dist/umd/components/Nodes/OutputNode.d.ts +2 -7
- package/dist/umd/components/Nodes/OutputNode.d.ts.map +1 -1
- package/dist/umd/components/Nodes/utils.d.ts.map +1 -1
- package/dist/umd/components/NodesSelection/index.d.ts +3 -5
- package/dist/umd/components/NodesSelection/index.d.ts.map +1 -1
- package/dist/umd/components/Panel/index.d.ts +5 -3
- package/dist/umd/components/Panel/index.d.ts.map +1 -1
- package/dist/umd/components/ReactFlowProvider/index.d.ts +6 -7
- package/dist/umd/components/ReactFlowProvider/index.d.ts.map +1 -1
- package/dist/umd/components/SelectionListener/index.d.ts +2 -2
- package/dist/umd/components/SelectionListener/index.d.ts.map +1 -1
- package/dist/umd/components/StoreUpdater/index.d.ts +5 -5
- package/dist/umd/components/StoreUpdater/index.d.ts.map +1 -1
- package/dist/umd/components/UserSelection/index.d.ts +1 -2
- package/dist/umd/components/UserSelection/index.d.ts.map +1 -1
- package/dist/umd/components/ViewportPortal/index.d.ts +1 -2
- package/dist/umd/components/ViewportPortal/index.d.ts.map +1 -1
- package/dist/umd/container/EdgeRenderer/MarkerDefinitions.d.ts.map +1 -1
- package/dist/umd/container/EdgeRenderer/MarkerSymbols.d.ts +1 -1
- package/dist/umd/container/EdgeRenderer/MarkerSymbols.d.ts.map +1 -1
- package/dist/umd/container/EdgeRenderer/index.d.ts +8 -6
- package/dist/umd/container/EdgeRenderer/index.d.ts.map +1 -1
- package/dist/umd/container/FlowRenderer/index.d.ts +8 -6
- package/dist/umd/container/FlowRenderer/index.d.ts.map +1 -1
- package/dist/umd/container/GraphView/index.d.ts +8 -8
- package/dist/umd/container/GraphView/index.d.ts.map +1 -1
- package/dist/umd/container/GraphView/useNodeOrEdgeTypesWarning.d.ts +6 -1
- package/dist/umd/container/GraphView/useNodeOrEdgeTypesWarning.d.ts.map +1 -1
- package/dist/umd/container/GraphView/useStylesLoadedWarning.d.ts +2 -0
- package/dist/umd/container/GraphView/useStylesLoadedWarning.d.ts.map +1 -0
- package/dist/umd/container/NodeRenderer/index.d.ts +8 -7
- package/dist/umd/container/NodeRenderer/index.d.ts.map +1 -1
- package/dist/umd/container/NodeRenderer/useResizeObserver.d.ts +1 -1
- package/dist/umd/container/NodeRenderer/useResizeObserver.d.ts.map +1 -1
- package/dist/umd/container/Pane/index.d.ts +2 -2
- package/dist/umd/container/Pane/index.d.ts.map +1 -1
- package/dist/umd/container/ReactFlow/Wrapper.d.ts +3 -5
- package/dist/umd/container/ReactFlow/Wrapper.d.ts.map +1 -1
- package/dist/umd/container/ReactFlow/index.d.ts +4 -119
- package/dist/umd/container/ReactFlow/index.d.ts.map +1 -1
- package/dist/umd/container/ReactFlow/init-values.d.ts +4 -0
- package/dist/umd/container/ReactFlow/init-values.d.ts.map +1 -0
- package/dist/umd/container/Viewport/index.d.ts +1 -1
- package/dist/umd/container/Viewport/index.d.ts.map +1 -1
- package/dist/umd/container/ZoomPane/index.d.ts +2 -2
- package/dist/umd/container/ZoomPane/index.d.ts.map +1 -1
- package/dist/umd/contexts/NodeIdContext.d.ts.map +1 -1
- package/dist/umd/contexts/{RFStoreContext.d.ts → StoreContext.d.ts} +1 -1
- package/dist/umd/contexts/StoreContext.d.ts.map +1 -0
- package/dist/umd/hooks/useColorModeClass.d.ts +1 -1
- package/dist/umd/hooks/useColorModeClass.d.ts.map +1 -1
- package/dist/umd/hooks/useConnection.d.ts +13 -7
- package/dist/umd/hooks/useConnection.d.ts.map +1 -1
- package/dist/umd/hooks/useDrag.d.ts +3 -3
- package/dist/umd/hooks/useDrag.d.ts.map +1 -1
- package/dist/umd/hooks/useEdges.d.ts +1 -2
- package/dist/umd/hooks/useEdges.d.ts.map +1 -1
- package/dist/umd/hooks/useGlobalKeyHandler.d.ts +2 -3
- package/dist/umd/hooks/useGlobalKeyHandler.d.ts.map +1 -1
- package/dist/umd/hooks/useHandleConnections.d.ts +4 -4
- package/dist/umd/hooks/useHandleConnections.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/useIsomorphicLayoutEffect.d.ts +3 -0
- package/dist/umd/hooks/useIsomorphicLayoutEffect.d.ts.map +1 -0
- package/dist/umd/hooks/useKeyPress.d.ts +1 -2
- package/dist/umd/hooks/useKeyPress.d.ts.map +1 -1
- package/dist/umd/hooks/useMoveSelectedNodes.d.ts +12 -0
- package/dist/umd/hooks/useMoveSelectedNodes.d.ts.map +1 -0
- package/dist/umd/hooks/useNodes.d.ts +1 -2
- package/dist/umd/hooks/useNodes.d.ts.map +1 -1
- package/dist/umd/hooks/useNodesData.d.ts +3 -4
- package/dist/umd/hooks/useNodesData.d.ts.map +1 -1
- package/dist/umd/hooks/useNodesEdgesState.d.ts +3 -3
- package/dist/umd/hooks/useNodesEdgesState.d.ts.map +1 -1
- package/dist/umd/hooks/useNodesInitialized.d.ts +1 -2
- package/dist/umd/hooks/useNodesInitialized.d.ts.map +1 -1
- package/dist/umd/hooks/useOnInitHandler.d.ts +2 -3
- package/dist/umd/hooks/useOnInitHandler.d.ts.map +1 -1
- package/dist/umd/hooks/useOnSelectionChange.d.ts +2 -3
- package/dist/umd/hooks/useOnSelectionChange.d.ts.map +1 -1
- package/dist/umd/hooks/useOnViewportChange.d.ts +1 -2
- package/dist/umd/hooks/useOnViewportChange.d.ts.map +1 -1
- package/dist/umd/hooks/useReactFlow.d.ts +1 -1
- package/dist/umd/hooks/useReactFlow.d.ts.map +1 -1
- package/dist/umd/hooks/useResizeHandler.d.ts +1 -2
- package/dist/umd/hooks/useResizeHandler.d.ts.map +1 -1
- package/dist/umd/hooks/useStore.d.ts +10 -11
- package/dist/umd/hooks/useStore.d.ts.map +1 -1
- package/dist/umd/hooks/useUpdateNodeInternals.d.ts +1 -2
- package/dist/umd/hooks/useUpdateNodeInternals.d.ts.map +1 -1
- package/dist/umd/hooks/useViewport.d.ts +1 -2
- package/dist/umd/hooks/useViewport.d.ts.map +1 -1
- package/dist/umd/hooks/useViewportHelper.d.ts.map +1 -1
- package/dist/umd/hooks/useViewportSync.d.ts +1 -1
- package/dist/umd/hooks/useViewportSync.d.ts.map +1 -1
- package/dist/umd/hooks/useVisibleEdgeIds.d.ts +1 -2
- package/dist/umd/hooks/useVisibleEdgeIds.d.ts.map +1 -1
- package/dist/umd/hooks/useVisibleNodeIds.d.ts +1 -2
- package/dist/umd/hooks/useVisibleNodeIds.d.ts.map +1 -1
- package/dist/umd/index.d.ts +22 -21
- package/dist/umd/index.d.ts.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/store/index.d.ts +6 -4
- package/dist/umd/store/index.d.ts.map +1 -1
- package/dist/umd/store/initialState.d.ts +5 -3
- package/dist/umd/store/initialState.d.ts.map +1 -1
- package/dist/umd/styles/utils.d.ts.map +1 -1
- package/dist/umd/types/component-props.d.ts +380 -38
- package/dist/umd/types/component-props.d.ts.map +1 -1
- package/dist/umd/types/edges.d.ts +35 -25
- package/dist/umd/types/edges.d.ts.map +1 -1
- package/dist/umd/types/general.d.ts +99 -20
- 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 +146 -44
- package/dist/umd/types/instance.d.ts.map +1 -1
- package/dist/umd/types/nodes.d.ts +23 -12
- package/dist/umd/types/nodes.d.ts.map +1 -1
- package/dist/umd/types/store.d.ts +26 -23
- package/dist/umd/types/store.d.ts.map +1 -1
- package/dist/umd/utils/changes.d.ts +25 -7
- package/dist/umd/utils/changes.d.ts.map +1 -1
- package/dist/umd/utils/general.d.ts +4 -49
- package/dist/umd/utils/general.d.ts.map +1 -1
- package/dist/umd/utils/index.d.ts.map +1 -1
- package/package.json +4 -11
- package/dist/esm/additional-components/NodeResizer/ResizeControl.d.ts.map +0 -1
- package/dist/esm/additional-components/NodeResizer/utils.d.ts +0 -11
- package/dist/esm/additional-components/NodeResizer/utils.d.ts.map +0 -1
- package/dist/esm/contexts/RFStoreContext.d.ts.map +0 -1
- package/dist/esm/hooks/useUpdateNodePositions.d.ts +0 -13
- package/dist/esm/hooks/useUpdateNodePositions.d.ts.map +0 -1
- package/dist/esm/store/utils.d.ts +0 -12
- package/dist/esm/store/utils.d.ts.map +0 -1
- package/dist/esm/types/changes.d.ts +0 -50
- package/dist/esm/types/changes.d.ts.map +0 -1
- package/dist/umd/additional-components/NodeResizer/ResizeControl.d.ts.map +0 -1
- package/dist/umd/additional-components/NodeResizer/utils.d.ts +0 -11
- package/dist/umd/additional-components/NodeResizer/utils.d.ts.map +0 -1
- package/dist/umd/contexts/RFStoreContext.d.ts.map +0 -1
- package/dist/umd/hooks/useUpdateNodePositions.d.ts +0 -13
- package/dist/umd/hooks/useUpdateNodePositions.d.ts.map +0 -1
- package/dist/umd/store/utils.d.ts +0 -12
- package/dist/umd/store/utils.d.ts.map +0 -1
- package/dist/umd/types/changes.d.ts +0 -50
- package/dist/umd/types/changes.d.ts.map +0 -1
package/dist/esm/index.mjs
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
"use client"
|
|
2
|
-
import {
|
|
3
|
-
import { createContext, useContext, useMemo, memo, useEffect, useRef, useState, useCallback, forwardRef } from 'react';
|
|
2
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
4
3
|
import cc from 'classcat';
|
|
5
|
-
import { errorMessages, infiniteExtent, isInputDOMNode, fitView, getViewportForBounds, pointToRendererPoint, rendererPointToPoint, isNodeBase, isEdgeBase,
|
|
6
|
-
export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, SelectionMode, getBezierEdgeCenter, getBezierPath, getEdgeCenter, getNodesBounds, getSmoothStepPath, getStraightPath, getViewportForBounds,
|
|
4
|
+
import { errorMessages, infiniteExtent, isInputDOMNode, fitView, getViewportForBounds, pointToRendererPoint, rendererPointToPoint, isNodeBase, isEdgeBase, getElementsToRemove, isRectObject, nodeToRect, getOverlappingArea, evaluateAbsolutePosition, getDimensions, XYPanZoom, PanOnScrollMode, SelectionMode, getEventPosition, getNodesInside, XYDrag, snapPosition, calculateNodePosition, Position, ConnectionMode, isMouseEvent, XYHandle, getHostForElement, addEdge, getInternalNodesBounds, isNumeric, nodeHasDimensions, getNodeDimensions, clampPosition, getPositionWithOrigin, elementSelectionKeys, isEdgeVisible, MarkerType, createMarkerIds, getBezierEdgeCenter, getSmoothStepPath, getStraightPath, getBezierPath, getEdgePosition, getElevatedEdgeZIndex, getMarkerId, ConnectionLineType, updateConnectionLookup, adoptUserNodes, devWarn, updateNodeInternals, updateAbsolutePositions, handleExpandParent, panBy, isMacOs, areConnectionMapsEqual, handleConnectionChange, shallowNodeData, getNodePositionWithOrigin, XYMinimap, getBoundsOfRects, ResizeControlVariant, XYResizer, XY_RESIZER_LINE_POSITIONS, XY_RESIZER_HANDLE_POSITIONS, getNodesBounds, 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';
|
|
10
|
-
import { drag } from 'd3-drag';
|
|
11
|
-
import { select } from 'd3-selection';
|
|
12
10
|
|
|
13
11
|
const StoreContext = createContext(null);
|
|
14
12
|
const Provider$1 = StoreContext.Provider;
|
|
@@ -21,6 +19,10 @@ const zustandErrorMessage = errorMessages['error001']();
|
|
|
21
19
|
* @param selector
|
|
22
20
|
* @param equalityFn
|
|
23
21
|
* @returns The selected state slice
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* const nodes = useStore((state: ReactFlowState<MyNodeType>) => state.nodes);
|
|
25
|
+
*
|
|
24
26
|
*/
|
|
25
27
|
function useStore(selector, equalityFn) {
|
|
26
28
|
const store = useContext(StoreContext);
|
|
@@ -29,7 +31,7 @@ function useStore(selector, equalityFn) {
|
|
|
29
31
|
}
|
|
30
32
|
return useStoreWithEqualityFn(store, selector, equalityFn);
|
|
31
33
|
}
|
|
32
|
-
|
|
34
|
+
function useStoreApi() {
|
|
33
35
|
const store = useContext(StoreContext);
|
|
34
36
|
if (store === null) {
|
|
35
37
|
throw new Error(zustandErrorMessage);
|
|
@@ -38,13 +40,36 @@ const useStoreApi = () => {
|
|
|
38
40
|
getState: store.getState,
|
|
39
41
|
setState: store.setState,
|
|
40
42
|
subscribe: store.subscribe,
|
|
41
|
-
destroy: store.destroy,
|
|
42
43
|
}), [store]);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const style = { display: 'none' };
|
|
47
|
+
const ariaLiveStyle = {
|
|
48
|
+
position: 'absolute',
|
|
49
|
+
width: 1,
|
|
50
|
+
height: 1,
|
|
51
|
+
margin: -1,
|
|
52
|
+
border: 0,
|
|
53
|
+
padding: 0,
|
|
54
|
+
overflow: 'hidden',
|
|
55
|
+
clip: 'rect(0px, 0px, 0px, 0px)',
|
|
56
|
+
clipPath: 'inset(100%)',
|
|
43
57
|
};
|
|
58
|
+
const ARIA_NODE_DESC_KEY = 'react-flow__node-desc';
|
|
59
|
+
const ARIA_EDGE_DESC_KEY = 'react-flow__edge-desc';
|
|
60
|
+
const ARIA_LIVE_MESSAGE = 'react-flow__aria-live';
|
|
61
|
+
const selector$q = (s) => s.ariaLiveMessage;
|
|
62
|
+
function AriaLiveMessage({ rfId }) {
|
|
63
|
+
const ariaLiveMessage = useStore(selector$q);
|
|
64
|
+
return (jsx("div", { id: `${ARIA_LIVE_MESSAGE}-${rfId}`, "aria-live": "assertive", "aria-atomic": "true", style: ariaLiveStyle, children: ariaLiveMessage }));
|
|
65
|
+
}
|
|
66
|
+
function A11yDescriptions({ rfId, disableKeyboardA11y }) {
|
|
67
|
+
return (jsxs(Fragment, { children: [jsxs("div", { id: `${ARIA_NODE_DESC_KEY}-${rfId}`, style: style, children: ["Press enter or space to select a node.", !disableKeyboardA11y && 'You can then use the arrow keys to move the node around.', " Press delete to remove it and escape to cancel.", ' '] }), jsx("div", { id: `${ARIA_EDGE_DESC_KEY}-${rfId}`, style: style, children: "Press enter or space to select an edge. You can then press delete to remove it or escape to cancel." }), !disableKeyboardA11y && jsx(AriaLiveMessage, { rfId: rfId })] }));
|
|
68
|
+
}
|
|
44
69
|
|
|
45
|
-
const selector$
|
|
46
|
-
function Panel({ position, children, className, style, ...rest }) {
|
|
47
|
-
const pointerEvents = useStore(selector$
|
|
70
|
+
const selector$p = (s) => (s.userSelectionActive ? 'none' : 'all');
|
|
71
|
+
function Panel({ position = 'top-left', children, className, style, ...rest }) {
|
|
72
|
+
const pointerEvents = useStore(selector$p);
|
|
48
73
|
const positionClasses = `${position}`.split('-');
|
|
49
74
|
return (jsx("div", { className: cc(['react-flow__panel', className, ...positionClasses]), style: { ...style, pointerEvents }, ...rest, children: children }));
|
|
50
75
|
}
|
|
@@ -56,35 +81,48 @@ function Attribution({ proOptions, position = 'bottom-right' }) {
|
|
|
56
81
|
return (jsx(Panel, { position: position, className: "react-flow__attribution", "data-message": "Please only hide this attribution when you are subscribed to React Flow Pro: https://pro.reactflow.dev", children: jsx("a", { href: "https://reactflow.dev", target: "_blank", rel: "noopener noreferrer", "aria-label": "React Flow attribution", children: "React Flow" }) }));
|
|
57
82
|
}
|
|
58
83
|
|
|
59
|
-
const selector$
|
|
60
|
-
selectedNodes
|
|
61
|
-
selectedEdges
|
|
62
|
-
|
|
84
|
+
const selector$o = (s) => {
|
|
85
|
+
const selectedNodes = [];
|
|
86
|
+
const selectedEdges = [];
|
|
87
|
+
for (const [, node] of s.nodeLookup) {
|
|
88
|
+
if (node.selected) {
|
|
89
|
+
selectedNodes.push(node.internals.userNode);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
for (const [, edge] of s.edgeLookup) {
|
|
93
|
+
if (edge.selected) {
|
|
94
|
+
selectedEdges.push(edge);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { selectedNodes, selectedEdges };
|
|
98
|
+
};
|
|
63
99
|
const selectId = (obj) => obj.id;
|
|
64
100
|
function areEqual(a, b) {
|
|
65
101
|
return (shallow(a.selectedNodes.map(selectId), b.selectedNodes.map(selectId)) &&
|
|
66
102
|
shallow(a.selectedEdges.map(selectId), b.selectedEdges.map(selectId)));
|
|
67
103
|
}
|
|
68
|
-
|
|
104
|
+
function SelectionListenerInner({ onSelectionChange }) {
|
|
69
105
|
const store = useStoreApi();
|
|
70
|
-
const { selectedNodes, selectedEdges } = useStore(selector$
|
|
106
|
+
const { selectedNodes, selectedEdges } = useStore(selector$o, areEqual);
|
|
71
107
|
useEffect(() => {
|
|
72
108
|
const params = { nodes: selectedNodes, edges: selectedEdges };
|
|
73
109
|
onSelectionChange?.(params);
|
|
74
110
|
store.getState().onSelectionChangeHandlers.forEach((fn) => fn(params));
|
|
75
111
|
}, [selectedNodes, selectedEdges, onSelectionChange]);
|
|
76
112
|
return null;
|
|
77
|
-
}
|
|
78
|
-
SelectionListener.displayName = 'SelectionListener';
|
|
113
|
+
}
|
|
79
114
|
const changeSelector = (s) => !!s.onSelectionChangeHandlers;
|
|
80
|
-
function
|
|
115
|
+
function SelectionListener({ onSelectionChange }) {
|
|
81
116
|
const storeHasSelectionChangeHandlers = useStore(changeSelector);
|
|
82
117
|
if (onSelectionChange || storeHasSelectionChangeHandlers) {
|
|
83
|
-
return jsx(
|
|
118
|
+
return jsx(SelectionListenerInner, { onSelectionChange: onSelectionChange });
|
|
84
119
|
}
|
|
85
120
|
return null;
|
|
86
121
|
}
|
|
87
122
|
|
|
123
|
+
const defaultNodeOrigin = [0, 0];
|
|
124
|
+
const defaultViewport = { x: 0, y: 0, zoom: 1 };
|
|
125
|
+
|
|
88
126
|
/*
|
|
89
127
|
* This component helps us to update the store with the vlues coming from the user.
|
|
90
128
|
* We distinguish between values we can update directly with `useDirectStoreUpdater` (like `snapGrid`)
|
|
@@ -144,41 +182,44 @@ const reactFlowFieldsToTrack = [
|
|
|
144
182
|
'selectNodesOnDrag',
|
|
145
183
|
'nodeDragThreshold',
|
|
146
184
|
'onBeforeDelete',
|
|
185
|
+
'debug',
|
|
147
186
|
];
|
|
148
187
|
// rfId doesn't exist in ReactFlowProps, but it's one of the fields we want to update
|
|
149
188
|
const fieldsToTrack = [...reactFlowFieldsToTrack, 'rfId'];
|
|
150
|
-
const selector$
|
|
189
|
+
const selector$n = (s) => ({
|
|
151
190
|
setNodes: s.setNodes,
|
|
152
191
|
setEdges: s.setEdges,
|
|
153
|
-
setDefaultNodesAndEdges: s.setDefaultNodesAndEdges,
|
|
154
192
|
setMinZoom: s.setMinZoom,
|
|
155
193
|
setMaxZoom: s.setMaxZoom,
|
|
156
194
|
setTranslateExtent: s.setTranslateExtent,
|
|
157
195
|
setNodeExtent: s.setNodeExtent,
|
|
158
196
|
reset: s.reset,
|
|
197
|
+
setDefaultNodesAndEdges: s.setDefaultNodesAndEdges,
|
|
159
198
|
});
|
|
160
|
-
const
|
|
161
|
-
|
|
199
|
+
const initPrevValues = {
|
|
200
|
+
// these are values that are also passed directly to other components
|
|
201
|
+
// than the StoreUpdater. We can reduce the number of setStore calls
|
|
202
|
+
// by setting the same values here as prev fields.
|
|
203
|
+
translateExtent: infiniteExtent,
|
|
204
|
+
nodeOrigin: defaultNodeOrigin,
|
|
205
|
+
minZoom: 0.5,
|
|
206
|
+
maxZoom: 2,
|
|
207
|
+
elementsSelectable: true,
|
|
208
|
+
noPanClassName: 'nopan',
|
|
209
|
+
rfId: '1',
|
|
210
|
+
};
|
|
211
|
+
function StoreUpdater(props) {
|
|
212
|
+
const { setNodes, setEdges, setMinZoom, setMaxZoom, setTranslateExtent, setNodeExtent, reset, setDefaultNodesAndEdges, } = useStore(selector$n, shallow);
|
|
162
213
|
const store = useStoreApi();
|
|
163
214
|
useEffect(() => {
|
|
164
|
-
|
|
165
|
-
setDefaultNodesAndEdges(props.defaultNodes, edgesWithDefaults);
|
|
215
|
+
setDefaultNodesAndEdges(props.defaultNodes, props.defaultEdges);
|
|
166
216
|
return () => {
|
|
217
|
+
// when we reset the store we also need to reset the previous fields
|
|
218
|
+
previousFields.current = initPrevValues;
|
|
167
219
|
reset();
|
|
168
220
|
};
|
|
169
221
|
}, []);
|
|
170
|
-
const previousFields = useRef(
|
|
171
|
-
// these are values that are also passed directly to other components
|
|
172
|
-
// than the StoreUpdater. We can reduce the number of setStore calls
|
|
173
|
-
// by setting the same values here as prev fields.
|
|
174
|
-
translateExtent: infiniteExtent,
|
|
175
|
-
nodeOrigin: initNodeOrigin,
|
|
176
|
-
minZoom: 0.5,
|
|
177
|
-
maxZoom: 2,
|
|
178
|
-
elementsSelectable: true,
|
|
179
|
-
noPanClassName: 'nopan',
|
|
180
|
-
rfId: '1',
|
|
181
|
-
});
|
|
222
|
+
const previousFields = useRef(initPrevValues);
|
|
182
223
|
useEffect(() => {
|
|
183
224
|
for (const fieldName of fieldsToTrack) {
|
|
184
225
|
const fieldValue = props[fieldName];
|
|
@@ -214,30 +255,36 @@ const StoreUpdater = (props) => {
|
|
|
214
255
|
// Only re-run the effect if one of the fields we track changes
|
|
215
256
|
fieldsToTrack.map((fieldName) => props[fieldName]));
|
|
216
257
|
return null;
|
|
217
|
-
}
|
|
258
|
+
}
|
|
218
259
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
margin: -1,
|
|
225
|
-
border: 0,
|
|
226
|
-
padding: 0,
|
|
227
|
-
overflow: 'hidden',
|
|
228
|
-
clip: 'rect(0px, 0px, 0px, 0px)',
|
|
229
|
-
clipPath: 'inset(100%)',
|
|
230
|
-
};
|
|
231
|
-
const ARIA_NODE_DESC_KEY = 'react-flow__node-desc';
|
|
232
|
-
const ARIA_EDGE_DESC_KEY = 'react-flow__edge-desc';
|
|
233
|
-
const ARIA_LIVE_MESSAGE = 'react-flow__aria-live';
|
|
234
|
-
const selector$n = (s) => s.ariaLiveMessage;
|
|
235
|
-
function AriaLiveMessage({ rfId }) {
|
|
236
|
-
const ariaLiveMessage = useStore(selector$n);
|
|
237
|
-
return (jsx("div", { id: `${ARIA_LIVE_MESSAGE}-${rfId}`, "aria-live": "assertive", "aria-atomic": "true", style: ariaLiveStyle, children: ariaLiveMessage }));
|
|
260
|
+
function getMediaQuery() {
|
|
261
|
+
if (typeof window === 'undefined' || !window.matchMedia) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
return window.matchMedia('(prefers-color-scheme: dark)');
|
|
238
265
|
}
|
|
239
|
-
|
|
240
|
-
|
|
266
|
+
/**
|
|
267
|
+
* Hook for receiving the current color mode class 'dark' or 'light'.
|
|
268
|
+
*
|
|
269
|
+
* @internal
|
|
270
|
+
* @param colorMode - The color mode to use ('dark', 'light' or 'system')
|
|
271
|
+
*/
|
|
272
|
+
function useColorModeClass(colorMode) {
|
|
273
|
+
const [colorModeClass, setColorModeClass] = useState(colorMode === 'system' ? null : colorMode);
|
|
274
|
+
useEffect(() => {
|
|
275
|
+
if (colorMode !== 'system') {
|
|
276
|
+
setColorModeClass(colorMode);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
const mediaQuery = getMediaQuery();
|
|
280
|
+
const updateColorModeClass = () => setColorModeClass(mediaQuery?.matches ? 'dark' : 'light');
|
|
281
|
+
updateColorModeClass();
|
|
282
|
+
mediaQuery?.addEventListener('change', updateColorModeClass);
|
|
283
|
+
return () => {
|
|
284
|
+
mediaQuery?.removeEventListener('change', updateColorModeClass);
|
|
285
|
+
};
|
|
286
|
+
}, [colorMode]);
|
|
287
|
+
return colorModeClass !== null ? colorModeClass : getMediaQuery()?.matches ? 'dark' : 'light';
|
|
241
288
|
}
|
|
242
289
|
|
|
243
290
|
const defaultDoc = typeof document !== 'undefined' ? document : null;
|
|
@@ -249,12 +296,12 @@ const defaultDoc = typeof document !== 'undefined' ? document : null;
|
|
|
249
296
|
* @param param.options - Options
|
|
250
297
|
* @returns boolean
|
|
251
298
|
*/
|
|
252
|
-
|
|
299
|
+
function useKeyPress(
|
|
253
300
|
// the keycode can be a string 'a' or an array of strings ['a', 'a+d']
|
|
254
301
|
// a string means a single key 'a' or a combination when '+' is used 'a+d'
|
|
255
302
|
// an array means different possibilites. Explainer: ['a', 'd+s'] here the
|
|
256
303
|
// user can use the single key 'a' or the combination 'd' + 's'
|
|
257
|
-
keyCode = null, options = { target: defaultDoc, actInsideInputWithModifier: true })
|
|
304
|
+
keyCode = null, options = { target: defaultDoc, actInsideInputWithModifier: true }) {
|
|
258
305
|
const [keyPressed, setKeyPressed] = useState(false);
|
|
259
306
|
// we need to remember if a modifier key is pressed in order to track it
|
|
260
307
|
const modifierPressed = useRef(false);
|
|
@@ -306,6 +353,10 @@ keyCode = null, options = { target: defaultDoc, actInsideInputWithModifier: true
|
|
|
306
353
|
else {
|
|
307
354
|
pressedKeys.current.delete(event[keyOrCode]);
|
|
308
355
|
}
|
|
356
|
+
// fix for Mac: when cmd key is pressed, keyup is not triggered for any other key, see: https://stackoverflow.com/questions/27380018/when-cmd-key-is-kept-pressed-keyup-is-not-triggered-for-any-other-key
|
|
357
|
+
if (event.key === 'Meta') {
|
|
358
|
+
pressedKeys.current.clear();
|
|
359
|
+
}
|
|
309
360
|
modifierPressed.current = false;
|
|
310
361
|
};
|
|
311
362
|
const resetHandler = () => {
|
|
@@ -315,15 +366,17 @@ keyCode = null, options = { target: defaultDoc, actInsideInputWithModifier: true
|
|
|
315
366
|
target?.addEventListener('keydown', downHandler);
|
|
316
367
|
target?.addEventListener('keyup', upHandler);
|
|
317
368
|
window.addEventListener('blur', resetHandler);
|
|
369
|
+
window.addEventListener('contextmenu', resetHandler);
|
|
318
370
|
return () => {
|
|
319
371
|
target?.removeEventListener('keydown', downHandler);
|
|
320
372
|
target?.removeEventListener('keyup', upHandler);
|
|
321
373
|
window.removeEventListener('blur', resetHandler);
|
|
374
|
+
window.removeEventListener('contextmenu', resetHandler);
|
|
322
375
|
};
|
|
323
376
|
}
|
|
324
377
|
}, [keyCode, setKeyPressed]);
|
|
325
378
|
return keyPressed;
|
|
326
|
-
}
|
|
379
|
+
}
|
|
327
380
|
// utils
|
|
328
381
|
function isMatchingKey(keyCodes, pressedKeys, isUp) {
|
|
329
382
|
return (keyCodes
|
|
@@ -339,7 +392,6 @@ function useKeyOrCode(eventCode, keysToWatch) {
|
|
|
339
392
|
return keysToWatch.includes(eventCode) ? 'code' : 'key';
|
|
340
393
|
}
|
|
341
394
|
|
|
342
|
-
const selector$m = (s) => !!s.panZoom;
|
|
343
395
|
/**
|
|
344
396
|
* Hook for getting viewport helper functions.
|
|
345
397
|
*
|
|
@@ -348,8 +400,7 @@ const selector$m = (s) => !!s.panZoom;
|
|
|
348
400
|
*/
|
|
349
401
|
const useViewportHelper = () => {
|
|
350
402
|
const store = useStoreApi();
|
|
351
|
-
|
|
352
|
-
const viewportHelperFunctions = useMemo(() => {
|
|
403
|
+
return useMemo(() => {
|
|
353
404
|
return {
|
|
354
405
|
zoomIn: (options) => store.getState().panZoom?.scaleBy(1.2, { duration: options?.duration }),
|
|
355
406
|
zoomOut: (options) => store.getState().panZoom?.scaleBy(1 / 1.2, { duration: options?.duration }),
|
|
@@ -368,10 +419,10 @@ const useViewportHelper = () => {
|
|
|
368
419
|
return { x, y, zoom };
|
|
369
420
|
},
|
|
370
421
|
fitView: (options) => {
|
|
371
|
-
const {
|
|
422
|
+
const { nodeLookup, width, height, nodeOrigin, minZoom, maxZoom, panZoom } = store.getState();
|
|
372
423
|
return panZoom
|
|
373
424
|
? fitView({
|
|
374
|
-
|
|
425
|
+
nodeLookup,
|
|
375
426
|
width,
|
|
376
427
|
height,
|
|
377
428
|
nodeOrigin,
|
|
@@ -397,154 +448,123 @@ const useViewportHelper = () => {
|
|
|
397
448
|
const viewport = getViewportForBounds(bounds, width, height, minZoom, maxZoom, options?.padding ?? 0.1);
|
|
398
449
|
panZoom?.setViewport(viewport, { duration: options?.duration });
|
|
399
450
|
},
|
|
400
|
-
screenToFlowPosition: (
|
|
401
|
-
const { transform,
|
|
451
|
+
screenToFlowPosition: (clientPosition, options = { snapToGrid: true }) => {
|
|
452
|
+
const { transform, snapGrid, domNode } = store.getState();
|
|
402
453
|
if (!domNode) {
|
|
403
|
-
return
|
|
454
|
+
return clientPosition;
|
|
404
455
|
}
|
|
405
456
|
const { x: domX, y: domY } = domNode.getBoundingClientRect();
|
|
406
457
|
const correctedPosition = {
|
|
407
|
-
x:
|
|
408
|
-
y:
|
|
458
|
+
x: clientPosition.x - domX,
|
|
459
|
+
y: clientPosition.y - domY,
|
|
409
460
|
};
|
|
410
|
-
return pointToRendererPoint(correctedPosition, transform, snapToGrid, snapGrid
|
|
461
|
+
return pointToRendererPoint(correctedPosition, transform, options.snapToGrid, snapGrid);
|
|
411
462
|
},
|
|
412
|
-
flowToScreenPosition: (
|
|
463
|
+
flowToScreenPosition: (flowPosition) => {
|
|
413
464
|
const { transform, domNode } = store.getState();
|
|
414
465
|
if (!domNode) {
|
|
415
|
-
return
|
|
466
|
+
return flowPosition;
|
|
416
467
|
}
|
|
417
468
|
const { x: domX, y: domY } = domNode.getBoundingClientRect();
|
|
418
|
-
const rendererPosition = rendererPointToPoint(
|
|
469
|
+
const rendererPosition = rendererPointToPoint(flowPosition, transform);
|
|
419
470
|
return {
|
|
420
471
|
x: rendererPosition.x + domX,
|
|
421
472
|
y: rendererPosition.y + domY,
|
|
422
473
|
};
|
|
423
474
|
},
|
|
424
|
-
viewportInitialized: panZoomInitialized,
|
|
425
475
|
};
|
|
426
|
-
}, [
|
|
427
|
-
return viewportHelperFunctions;
|
|
476
|
+
}, []);
|
|
428
477
|
};
|
|
429
478
|
|
|
430
|
-
function handleParentExpand(res, updateItem) {
|
|
431
|
-
const parent = res.find((e) => e.id === updateItem.parentNode);
|
|
432
|
-
if (parent) {
|
|
433
|
-
if (!parent.computed) {
|
|
434
|
-
parent.computed = {};
|
|
435
|
-
}
|
|
436
|
-
const extendWidth = updateItem.position.x + updateItem.computed.width - parent.computed.width;
|
|
437
|
-
const extendHeight = updateItem.position.y + updateItem.computed.height - parent.computed.height;
|
|
438
|
-
if (extendWidth > 0 || extendHeight > 0 || updateItem.position.x < 0 || updateItem.position.y < 0) {
|
|
439
|
-
parent.style = { ...parent.style } || {};
|
|
440
|
-
parent.style.width = parent.style.width ?? parent.computed.width;
|
|
441
|
-
parent.style.height = parent.style.height ?? parent.computed.height;
|
|
442
|
-
if (extendWidth > 0) {
|
|
443
|
-
parent.style.width += extendWidth;
|
|
444
|
-
}
|
|
445
|
-
if (extendHeight > 0) {
|
|
446
|
-
parent.style.height += extendHeight;
|
|
447
|
-
}
|
|
448
|
-
if (updateItem.position.x < 0) {
|
|
449
|
-
const xDiff = Math.abs(updateItem.position.x);
|
|
450
|
-
parent.position.x = parent.position.x - xDiff;
|
|
451
|
-
parent.style.width += xDiff;
|
|
452
|
-
updateItem.position.x = 0;
|
|
453
|
-
}
|
|
454
|
-
if (updateItem.position.y < 0) {
|
|
455
|
-
const yDiff = Math.abs(updateItem.position.y);
|
|
456
|
-
parent.position.y = parent.position.y - yDiff;
|
|
457
|
-
parent.style.height += yDiff;
|
|
458
|
-
updateItem.position.y = 0;
|
|
459
|
-
}
|
|
460
|
-
parent.computed.width = parent.style.width;
|
|
461
|
-
parent.computed.height = parent.style.height;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
479
|
// This function applies changes to nodes or edges that are triggered by React Flow internally.
|
|
466
480
|
// When you drag a node for example, React Flow will send a position change update.
|
|
467
481
|
// This function then applies the changes and returns the updated elements.
|
|
468
482
|
function applyChanges(changes, elements) {
|
|
469
|
-
// we need this hack to handle the setNodes and setEdges function of the useReactFlow hook for controlled flows
|
|
470
|
-
if (changes.some((c) => c.type === 'reset')) {
|
|
471
|
-
return changes.filter((c) => c.type === 'reset').map((c) => c.item);
|
|
472
|
-
}
|
|
473
|
-
let remainingChanges = changes;
|
|
474
483
|
const updatedElements = [];
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
+
// By storing a map of changes for each element, we can a quick lookup as we
|
|
485
|
+
// iterate over the elements array!
|
|
486
|
+
const changesMap = new Map();
|
|
487
|
+
for (const change of changes) {
|
|
488
|
+
if (change.type === 'add') {
|
|
489
|
+
updatedElements.push(change.item);
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
else if (change.type === 'remove' || change.type === 'replace') {
|
|
493
|
+
// For a 'remove' change we can safely ignore any other changes queued for
|
|
494
|
+
// the same element, it's going to be removed anyway!
|
|
495
|
+
changesMap.set(change.id, [change]);
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
const elementChanges = changesMap.get(change.id);
|
|
499
|
+
if (elementChanges) {
|
|
500
|
+
// If we have some changes queued already, we can do a mutable update of
|
|
501
|
+
// that array and save ourselves some copying.
|
|
502
|
+
elementChanges.push(change);
|
|
484
503
|
}
|
|
485
504
|
else {
|
|
486
|
-
|
|
505
|
+
changesMap.set(change.id, [change]);
|
|
487
506
|
}
|
|
488
507
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
508
|
+
}
|
|
509
|
+
for (const element of elements) {
|
|
510
|
+
const changes = changesMap.get(element.id);
|
|
511
|
+
// When there are no changes for an element we can just push it unmodified,
|
|
512
|
+
// no need to copy it.
|
|
513
|
+
if (!changes) {
|
|
514
|
+
updatedElements.push(element);
|
|
492
515
|
continue;
|
|
493
516
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
break;
|
|
538
|
-
}
|
|
539
|
-
case 'remove': {
|
|
540
|
-
continue;
|
|
541
|
-
}
|
|
517
|
+
// If we have a 'remove' change queued, it'll be the only change in the array
|
|
518
|
+
if (changes[0].type === 'remove') {
|
|
519
|
+
continue;
|
|
520
|
+
}
|
|
521
|
+
if (changes[0].type === 'replace') {
|
|
522
|
+
updatedElements.push({ ...changes[0].item });
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
// For other types of changes, we want to start with a shallow copy of the
|
|
526
|
+
// object so React knows this element has changed. Sequential changes will
|
|
527
|
+
/// each _mutate_ this object, so there's only ever one copy.
|
|
528
|
+
const updatedElement = { ...element };
|
|
529
|
+
for (const change of changes) {
|
|
530
|
+
applyChange(change, updatedElement);
|
|
531
|
+
}
|
|
532
|
+
updatedElements.push(updatedElement);
|
|
533
|
+
}
|
|
534
|
+
return updatedElements;
|
|
535
|
+
}
|
|
536
|
+
// Applies a single change to an element. This is a *mutable* update.
|
|
537
|
+
function applyChange(change, element) {
|
|
538
|
+
switch (change.type) {
|
|
539
|
+
case 'select': {
|
|
540
|
+
element.selected = change.selected;
|
|
541
|
+
break;
|
|
542
|
+
}
|
|
543
|
+
case 'position': {
|
|
544
|
+
if (typeof change.position !== 'undefined') {
|
|
545
|
+
element.position = change.position;
|
|
546
|
+
}
|
|
547
|
+
if (typeof change.dragging !== 'undefined') {
|
|
548
|
+
element.dragging = change.dragging;
|
|
549
|
+
}
|
|
550
|
+
break;
|
|
551
|
+
}
|
|
552
|
+
case 'dimensions': {
|
|
553
|
+
if (typeof change.dimensions !== 'undefined') {
|
|
554
|
+
element.measured ??= {};
|
|
555
|
+
element.measured.width = change.dimensions.width;
|
|
556
|
+
element.measured.height = change.dimensions.height;
|
|
557
|
+
if (change.setAttributes) {
|
|
558
|
+
element.width = change.dimensions.width;
|
|
559
|
+
element.height = change.dimensions.height;
|
|
542
560
|
}
|
|
543
561
|
}
|
|
544
|
-
|
|
562
|
+
if (typeof change.resizing === 'boolean') {
|
|
563
|
+
element.resizing = change.resizing;
|
|
564
|
+
}
|
|
565
|
+
break;
|
|
545
566
|
}
|
|
546
567
|
}
|
|
547
|
-
return updatedElements;
|
|
548
568
|
}
|
|
549
569
|
/**
|
|
550
570
|
* Drop in function that applies node changes to an array of nodes.
|
|
@@ -586,21 +606,23 @@ function applyNodeChanges(changes, nodes) {
|
|
|
586
606
|
);
|
|
587
607
|
|
|
588
608
|
return (
|
|
589
|
-
<
|
|
609
|
+
<ReactFlow nodes={nodes} edges={edges} onEdgesChange={onEdgesChange} />
|
|
590
610
|
);
|
|
591
611
|
*/
|
|
592
612
|
function applyEdgeChanges(changes, edges) {
|
|
593
613
|
return applyChanges(changes, edges);
|
|
594
614
|
}
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
615
|
+
function createSelectionChange(id, selected) {
|
|
616
|
+
return {
|
|
617
|
+
id,
|
|
618
|
+
type: 'select',
|
|
619
|
+
selected,
|
|
620
|
+
};
|
|
621
|
+
}
|
|
600
622
|
function getSelectionChanges(items, selectedIds = new Set(), mutateItem = false) {
|
|
601
623
|
const changes = [];
|
|
602
|
-
for (const item of items) {
|
|
603
|
-
const willBeSelected = selectedIds.has(
|
|
624
|
+
for (const [id, item] of items) {
|
|
625
|
+
const willBeSelected = selectedIds.has(id);
|
|
604
626
|
// we don't want to set all items to selected=false on the first selection
|
|
605
627
|
if (!(item.selected === undefined && !willBeSelected) && item.selected !== willBeSelected) {
|
|
606
628
|
if (mutateItem) {
|
|
@@ -614,6 +636,33 @@ function getSelectionChanges(items, selectedIds = new Set(), mutateItem = false)
|
|
|
614
636
|
}
|
|
615
637
|
return changes;
|
|
616
638
|
}
|
|
639
|
+
function getElementsDiffChanges({ items = [], lookup, }) {
|
|
640
|
+
const changes = [];
|
|
641
|
+
const itemsLookup = new Map(items.map((item) => [item.id, item]));
|
|
642
|
+
for (const item of items) {
|
|
643
|
+
const lookupItem = lookup.get(item.id);
|
|
644
|
+
const storeItem = lookupItem?.internals?.userNode ?? lookupItem;
|
|
645
|
+
if (storeItem !== undefined && storeItem !== item) {
|
|
646
|
+
changes.push({ id: item.id, item: item, type: 'replace' });
|
|
647
|
+
}
|
|
648
|
+
if (storeItem === undefined) {
|
|
649
|
+
changes.push({ item: item, type: 'add' });
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
for (const [id] of lookup) {
|
|
653
|
+
const nextNode = itemsLookup.get(id);
|
|
654
|
+
if (nextNode === undefined) {
|
|
655
|
+
changes.push({ id, type: 'remove' });
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
return changes;
|
|
659
|
+
}
|
|
660
|
+
function elementToRemoveChange(item) {
|
|
661
|
+
return {
|
|
662
|
+
id: item.id,
|
|
663
|
+
type: 'remove',
|
|
664
|
+
};
|
|
665
|
+
}
|
|
617
666
|
|
|
618
667
|
/**
|
|
619
668
|
* Test whether an object is useable as a Node
|
|
@@ -622,7 +671,7 @@ function getSelectionChanges(items, selectedIds = new Set(), mutateItem = false)
|
|
|
622
671
|
* @param element - The element to test
|
|
623
672
|
* @returns A boolean indicating whether the element is an Node
|
|
624
673
|
*/
|
|
625
|
-
const isNode = (isNodeBase);
|
|
674
|
+
const isNode = (element) => isNodeBase(element);
|
|
626
675
|
/**
|
|
627
676
|
* Test whether an object is useable as an Edge
|
|
628
677
|
* @public
|
|
@@ -630,253 +679,289 @@ const isNode = (isNodeBase);
|
|
|
630
679
|
* @param element - The element to test
|
|
631
680
|
* @returns A boolean indicating whether the element is an Edge
|
|
632
681
|
*/
|
|
633
|
-
const isEdge = (isEdgeBase);
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
/**
|
|
644
|
-
* Pass in a node, and get connected nodes where edge.target === node.id
|
|
645
|
-
* @public
|
|
646
|
-
* @param node - The node to get the connected nodes from
|
|
647
|
-
* @param nodes - The array of all nodes
|
|
648
|
-
* @param edges - The array of all edges
|
|
649
|
-
* @returns An array of nodes that are connected over eges where the target is the given node
|
|
650
|
-
*/
|
|
651
|
-
const getIncomers = (getIncomersBase);
|
|
652
|
-
/**
|
|
653
|
-
* This util is a convenience function to add a new Edge to an array of edges
|
|
654
|
-
* @remarks It also performs some validation to make sure you don't add an invalid edge or duplicate an existing one.
|
|
655
|
-
* @public
|
|
656
|
-
* @param edgeParams - Either an Edge or a Connection you want to add
|
|
657
|
-
* @param edges - The array of all current edges
|
|
658
|
-
* @returns A new array of edges with the new edge added
|
|
659
|
-
*/
|
|
660
|
-
const addEdge = (addEdgeBase);
|
|
661
|
-
/**
|
|
662
|
-
* A handy utility to update an existing Edge with new properties
|
|
663
|
-
* @param oldEdge - The edge you want to update
|
|
664
|
-
* @param newConnection - The new connection you want to update the edge with
|
|
665
|
-
* @param edges - The array of all current edges
|
|
666
|
-
* @param options.shouldReplaceId - should the id of the old edge be replaced with the new connection id
|
|
667
|
-
* @returns the updated edges array
|
|
668
|
-
*/
|
|
669
|
-
const updateEdge = (updateEdgeBase);
|
|
682
|
+
const isEdge = (element) => isEdgeBase(element);
|
|
683
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
684
|
+
function fixedForwardRef(render) {
|
|
685
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
686
|
+
return forwardRef(render);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// we need this hook to prevent a warning when using react-flow in SSR
|
|
690
|
+
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
|
|
691
|
+
|
|
670
692
|
/**
|
|
671
|
-
*
|
|
672
|
-
*
|
|
673
|
-
* @param
|
|
674
|
-
* @
|
|
693
|
+
* This hook returns a queue that can be used to batch updates.
|
|
694
|
+
*
|
|
695
|
+
* @param runQueue - a function that gets called when the queue is flushed
|
|
696
|
+
* @internal
|
|
697
|
+
*
|
|
698
|
+
* @returns a Queue object
|
|
675
699
|
*/
|
|
676
|
-
|
|
700
|
+
function useQueue(runQueue) {
|
|
701
|
+
// Because we're using a ref above, we need some way to let React know when to
|
|
702
|
+
// actually process the queue. We flip this bit of state to `true` any time we
|
|
703
|
+
// mutate the queue and then flip it back to `false` after flushing the queue.
|
|
704
|
+
const [shouldFlush, setShouldFlush] = useState(false);
|
|
705
|
+
// A reference of all the batched updates to process before the next render. We
|
|
706
|
+
// want a reference here so multiple synchronous calls to `setNodes` etc can be
|
|
707
|
+
// batched together.
|
|
708
|
+
const [queue] = useState(() => createQueue(() => setShouldFlush(true)));
|
|
709
|
+
// Layout effects are guaranteed to run before the next render which means we
|
|
710
|
+
// shouldn't run into any issues with stale state or weird issues that come from
|
|
711
|
+
// rendering things one frame later than expected (we used to use `setTimeout`).
|
|
712
|
+
useIsomorphicLayoutEffect(() => {
|
|
713
|
+
// Because we need to flip the state back to false after flushing, this should
|
|
714
|
+
// trigger the hook again (!). If the hook is being run again we know that any
|
|
715
|
+
// updates should have been processed by now and we can safely clear the queue
|
|
716
|
+
// and bail early.
|
|
717
|
+
if (!shouldFlush) {
|
|
718
|
+
queue.reset();
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
const queueItems = queue.get();
|
|
722
|
+
if (queueItems.length) {
|
|
723
|
+
runQueue(queueItems);
|
|
724
|
+
queue.reset();
|
|
725
|
+
}
|
|
726
|
+
// Beacuse we're using reactive state to trigger this effect, we need to flip
|
|
727
|
+
// it back to false.
|
|
728
|
+
setShouldFlush(false);
|
|
729
|
+
}, [shouldFlush]);
|
|
730
|
+
return queue;
|
|
731
|
+
}
|
|
732
|
+
function createQueue(cb) {
|
|
733
|
+
let queue = [];
|
|
734
|
+
return {
|
|
735
|
+
get: () => queue,
|
|
736
|
+
reset: () => {
|
|
737
|
+
queue = [];
|
|
738
|
+
},
|
|
739
|
+
push: (item) => {
|
|
740
|
+
queue.push(item);
|
|
741
|
+
cb();
|
|
742
|
+
},
|
|
743
|
+
};
|
|
744
|
+
}
|
|
677
745
|
|
|
746
|
+
const BatchContext = createContext(null);
|
|
678
747
|
/**
|
|
679
|
-
*
|
|
748
|
+
* This is a context provider that holds and processes the node and edge update queues
|
|
749
|
+
* that are needed to handle setNodes, addNodes, setEdges and addEdges.
|
|
680
750
|
*
|
|
681
|
-
* @
|
|
682
|
-
* @returns ReactFlowInstance
|
|
751
|
+
* @internal
|
|
683
752
|
*/
|
|
684
|
-
function
|
|
685
|
-
const viewportHelper = useViewportHelper();
|
|
753
|
+
function BatchProvider({ children, }) {
|
|
686
754
|
const store = useStoreApi();
|
|
687
|
-
const
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
return edges.map((e) => ({ ...e }));
|
|
696
|
-
}, []);
|
|
697
|
-
const getEdge = useCallback((id) => {
|
|
698
|
-
const { edges = [] } = store.getState();
|
|
699
|
-
return edges.find((e) => e.id === id);
|
|
700
|
-
}, []);
|
|
701
|
-
const setNodes = useCallback((payload) => {
|
|
702
|
-
const { nodes, setNodes, hasDefaultNodes, onNodesChange } = store.getState();
|
|
703
|
-
const nextNodes = typeof payload === 'function' ? payload(nodes) : payload;
|
|
704
|
-
if (hasDefaultNodes) {
|
|
705
|
-
setNodes(nextNodes);
|
|
706
|
-
}
|
|
707
|
-
else if (onNodesChange) {
|
|
708
|
-
const changes = nextNodes.length === 0
|
|
709
|
-
? nodes.map((node) => ({ type: 'remove', id: node.id }))
|
|
710
|
-
: nextNodes.map((node) => ({ item: node, type: 'reset' }));
|
|
711
|
-
onNodesChange(changes);
|
|
755
|
+
const nodeQueueHandler = useCallback((queueItems) => {
|
|
756
|
+
const { nodes = [], setNodes, hasDefaultNodes, onNodesChange, nodeLookup } = store.getState();
|
|
757
|
+
// This is essentially an `Array.reduce` in imperative clothing. Processing
|
|
758
|
+
// this queue is a relatively hot path so we'd like to avoid the overhead of
|
|
759
|
+
// array methods where we can.
|
|
760
|
+
let next = nodes;
|
|
761
|
+
for (const payload of queueItems) {
|
|
762
|
+
next = typeof payload === 'function' ? payload(next) : payload;
|
|
712
763
|
}
|
|
713
|
-
}, []);
|
|
714
|
-
const setEdges = useCallback((payload) => {
|
|
715
|
-
const { edges = [], setEdges, hasDefaultEdges, onEdgesChange } = store.getState();
|
|
716
|
-
const nextEdges = typeof payload === 'function' ? payload(edges) : payload;
|
|
717
|
-
if (hasDefaultEdges) {
|
|
718
|
-
setEdges(nextEdges);
|
|
719
|
-
}
|
|
720
|
-
else if (onEdgesChange) {
|
|
721
|
-
const changes = nextEdges.length === 0
|
|
722
|
-
? edges.map((edge) => ({ type: 'remove', id: edge.id }))
|
|
723
|
-
: nextEdges.map((edge) => ({ item: edge, type: 'reset' }));
|
|
724
|
-
onEdgesChange(changes);
|
|
725
|
-
}
|
|
726
|
-
}, []);
|
|
727
|
-
const addNodes = useCallback((payload) => {
|
|
728
|
-
const nodes = Array.isArray(payload) ? payload : [payload];
|
|
729
|
-
const { nodes: currentNodes, hasDefaultNodes, onNodesChange, setNodes } = store.getState();
|
|
730
764
|
if (hasDefaultNodes) {
|
|
731
|
-
|
|
732
|
-
setNodes(nextNodes);
|
|
765
|
+
setNodes(next);
|
|
733
766
|
}
|
|
734
767
|
else if (onNodesChange) {
|
|
735
|
-
|
|
736
|
-
|
|
768
|
+
onNodesChange(getElementsDiffChanges({
|
|
769
|
+
items: next,
|
|
770
|
+
lookup: nodeLookup,
|
|
771
|
+
}));
|
|
737
772
|
}
|
|
738
773
|
}, []);
|
|
739
|
-
const
|
|
740
|
-
|
|
741
|
-
const { edges = [], setEdges, hasDefaultEdges, onEdgesChange } = store.getState();
|
|
774
|
+
const nodeQueue = useQueue(nodeQueueHandler);
|
|
775
|
+
const edgeQueueHandler = useCallback((queueItems) => {
|
|
776
|
+
const { edges = [], setEdges, hasDefaultEdges, onEdgesChange, edgeLookup } = store.getState();
|
|
777
|
+
let next = edges;
|
|
778
|
+
for (const payload of queueItems) {
|
|
779
|
+
next = typeof payload === 'function' ? payload(next) : payload;
|
|
780
|
+
}
|
|
742
781
|
if (hasDefaultEdges) {
|
|
743
|
-
setEdges(
|
|
782
|
+
setEdges(next);
|
|
744
783
|
}
|
|
745
784
|
else if (onEdgesChange) {
|
|
746
|
-
|
|
747
|
-
|
|
785
|
+
onEdgesChange(getElementsDiffChanges({
|
|
786
|
+
items: next,
|
|
787
|
+
lookup: edgeLookup,
|
|
788
|
+
}));
|
|
748
789
|
}
|
|
749
790
|
}, []);
|
|
750
|
-
const
|
|
751
|
-
|
|
752
|
-
|
|
791
|
+
const edgeQueue = useQueue(edgeQueueHandler);
|
|
792
|
+
const value = useMemo(() => ({ nodeQueue, edgeQueue }), []);
|
|
793
|
+
return jsx(BatchContext.Provider, { value: value, children: children });
|
|
794
|
+
}
|
|
795
|
+
function useBatchContext() {
|
|
796
|
+
const batchContext = useContext(BatchContext);
|
|
797
|
+
if (!batchContext) {
|
|
798
|
+
throw new Error('useBatchContext must be used within a BatchProvider');
|
|
799
|
+
}
|
|
800
|
+
return batchContext;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
const selector$m = (s) => !!s.panZoom;
|
|
804
|
+
/**
|
|
805
|
+
* Hook for accessing the ReactFlow instance.
|
|
806
|
+
*
|
|
807
|
+
* @public
|
|
808
|
+
* @returns ReactFlowInstance
|
|
809
|
+
*/
|
|
810
|
+
function useReactFlow() {
|
|
811
|
+
const viewportHelper = useViewportHelper();
|
|
812
|
+
const store = useStoreApi();
|
|
813
|
+
const batchContext = useBatchContext();
|
|
814
|
+
const viewportInitialized = useStore(selector$m);
|
|
815
|
+
const generalHelper = useMemo(() => {
|
|
816
|
+
const getInternalNode = (id) => store.getState().nodeLookup.get(id);
|
|
817
|
+
const setNodes = (payload) => {
|
|
818
|
+
batchContext.nodeQueue.push(payload);
|
|
819
|
+
};
|
|
820
|
+
const setEdges = (payload) => {
|
|
821
|
+
batchContext.edgeQueue.push(payload);
|
|
822
|
+
};
|
|
823
|
+
const getNodeRect = (node) => {
|
|
824
|
+
const { nodeLookup, nodeOrigin } = store.getState();
|
|
825
|
+
const nodeToUse = isNode(node) ? node : nodeLookup.get(node.id);
|
|
826
|
+
const position = nodeToUse.parentId
|
|
827
|
+
? evaluateAbsolutePosition(nodeToUse.position, nodeToUse.parentId, nodeLookup, nodeOrigin)
|
|
828
|
+
: nodeToUse.position;
|
|
829
|
+
const nodeWithPosition = {
|
|
830
|
+
id: nodeToUse.id,
|
|
831
|
+
position,
|
|
832
|
+
width: nodeToUse.measured?.width ?? nodeToUse.width,
|
|
833
|
+
height: nodeToUse.measured?.height ?? nodeToUse.height,
|
|
834
|
+
data: nodeToUse.data,
|
|
835
|
+
};
|
|
836
|
+
return nodeToRect(nodeWithPosition);
|
|
837
|
+
};
|
|
838
|
+
const updateNode = (id, nodeUpdate, options = { replace: false }) => {
|
|
839
|
+
setNodes((prevNodes) => prevNodes.map((node) => {
|
|
840
|
+
if (node.id === id) {
|
|
841
|
+
const nextNode = typeof nodeUpdate === 'function' ? nodeUpdate(node) : nodeUpdate;
|
|
842
|
+
return options.replace && isNode(nextNode) ? nextNode : { ...node, ...nextNode };
|
|
843
|
+
}
|
|
844
|
+
return node;
|
|
845
|
+
}));
|
|
846
|
+
};
|
|
847
|
+
const updateEdge = (id, edgeUpdate, options = { replace: false }) => {
|
|
848
|
+
setEdges((prevEdges) => prevEdges.map((edge) => {
|
|
849
|
+
if (edge.id === id) {
|
|
850
|
+
const nextEdge = typeof edgeUpdate === 'function' ? edgeUpdate(edge) : edgeUpdate;
|
|
851
|
+
return options.replace && isEdge(nextEdge) ? nextEdge : { ...edge, ...nextEdge };
|
|
852
|
+
}
|
|
853
|
+
return edge;
|
|
854
|
+
}));
|
|
855
|
+
};
|
|
753
856
|
return {
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
857
|
+
getNodes: () => store.getState().nodes.map((n) => ({ ...n })),
|
|
858
|
+
getNode: (id) => getInternalNode(id)?.internals.userNode,
|
|
859
|
+
getInternalNode,
|
|
860
|
+
getEdges: () => {
|
|
861
|
+
const { edges = [] } = store.getState();
|
|
862
|
+
return edges.map((e) => ({ ...e }));
|
|
760
863
|
},
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
edges: edges.
|
|
864
|
+
getEdge: (id) => store.getState().edgeLookup.get(id),
|
|
865
|
+
setNodes,
|
|
866
|
+
setEdges,
|
|
867
|
+
addNodes: (payload) => {
|
|
868
|
+
const newNodes = Array.isArray(payload) ? payload : [payload];
|
|
869
|
+
batchContext.nodeQueue.push((nodes) => [...nodes, ...newNodes]);
|
|
870
|
+
},
|
|
871
|
+
addEdges: (payload) => {
|
|
872
|
+
const newEdges = Array.isArray(payload) ? payload : [payload];
|
|
873
|
+
batchContext.edgeQueue.push((edges) => [...edges, ...newEdges]);
|
|
874
|
+
},
|
|
875
|
+
toObject: () => {
|
|
876
|
+
const { nodes = [], edges = [], transform } = store.getState();
|
|
877
|
+
const [x, y, zoom] = transform;
|
|
878
|
+
return {
|
|
879
|
+
nodes: nodes.map((n) => ({ ...n })),
|
|
880
|
+
edges: edges.map((e) => ({ ...e })),
|
|
881
|
+
viewport: {
|
|
882
|
+
x,
|
|
883
|
+
y,
|
|
884
|
+
zoom,
|
|
885
|
+
},
|
|
886
|
+
};
|
|
887
|
+
},
|
|
888
|
+
deleteElements: async ({ nodes: nodesToRemove = [], edges: edgesToRemove = [] }) => {
|
|
889
|
+
const { nodes, edges, onNodesDelete, onEdgesDelete, triggerNodeChanges, triggerEdgeChanges, onDelete, onBeforeDelete, } = store.getState();
|
|
890
|
+
const { nodes: matchingNodes, edges: matchingEdges } = await getElementsToRemove({
|
|
891
|
+
nodesToRemove,
|
|
892
|
+
edgesToRemove,
|
|
893
|
+
nodes,
|
|
894
|
+
edges,
|
|
895
|
+
onBeforeDelete,
|
|
778
896
|
});
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
897
|
+
const hasMatchingEdges = matchingEdges.length > 0;
|
|
898
|
+
const hasMatchingNodes = matchingNodes.length > 0;
|
|
899
|
+
if (hasMatchingEdges) {
|
|
900
|
+
const edgeChanges = matchingEdges.map(elementToRemoveChange);
|
|
901
|
+
onEdgesDelete?.(matchingEdges);
|
|
902
|
+
triggerEdgeChanges(edgeChanges);
|
|
903
|
+
}
|
|
904
|
+
if (hasMatchingNodes) {
|
|
905
|
+
const nodeChanges = matchingNodes.map(elementToRemoveChange);
|
|
906
|
+
onNodesDelete?.(matchingNodes);
|
|
907
|
+
triggerNodeChanges(nodeChanges);
|
|
908
|
+
}
|
|
909
|
+
if (hasMatchingNodes || hasMatchingEdges) {
|
|
910
|
+
onDelete?.({ nodes: matchingNodes, edges: matchingEdges });
|
|
911
|
+
}
|
|
912
|
+
return { deletedNodes: matchingNodes, deletedEdges: matchingEdges };
|
|
913
|
+
},
|
|
914
|
+
getIntersectingNodes: (nodeOrRect, partially = true, nodes) => {
|
|
915
|
+
const isRect = isRectObject(nodeOrRect);
|
|
916
|
+
const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
917
|
+
const hasNodesOption = nodes !== undefined;
|
|
918
|
+
if (!nodeRect) {
|
|
919
|
+
return [];
|
|
920
|
+
}
|
|
921
|
+
return (nodes || store.getState().nodes).filter((n) => {
|
|
922
|
+
const internalNode = store.getState().nodeLookup.get(n.id);
|
|
923
|
+
if (internalNode && !isRect && (n.id === nodeOrRect.id || !internalNode.internals.positionAbsolute)) {
|
|
924
|
+
return false;
|
|
925
|
+
}
|
|
926
|
+
const currNodeRect = nodeToRect(hasNodesOption ? n : internalNode);
|
|
927
|
+
const overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
|
|
928
|
+
const partiallyVisible = partially && overlappingArea > 0;
|
|
929
|
+
return partiallyVisible || overlappingArea >= nodeRect.width * nodeRect.height;
|
|
790
930
|
});
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
const partiallyVisible = partially && overlappingArea > 0;
|
|
818
|
-
return partiallyVisible || overlappingArea >= nodeRect.width * nodeRect.height;
|
|
819
|
-
});
|
|
820
|
-
}, []);
|
|
821
|
-
const isNodeIntersecting = useCallback((nodeOrRect, area, partially = true) => {
|
|
822
|
-
const [nodeRect] = getNodeRect(nodeOrRect);
|
|
823
|
-
if (!nodeRect) {
|
|
824
|
-
return false;
|
|
825
|
-
}
|
|
826
|
-
const overlappingArea = getOverlappingArea(nodeRect, area);
|
|
827
|
-
const partiallyVisible = partially && overlappingArea > 0;
|
|
828
|
-
return partiallyVisible || overlappingArea >= nodeRect.width * nodeRect.height;
|
|
931
|
+
},
|
|
932
|
+
isNodeIntersecting: (nodeOrRect, area, partially = true) => {
|
|
933
|
+
const isRect = isRectObject(nodeOrRect);
|
|
934
|
+
const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
935
|
+
if (!nodeRect) {
|
|
936
|
+
return false;
|
|
937
|
+
}
|
|
938
|
+
const overlappingArea = getOverlappingArea(nodeRect, area);
|
|
939
|
+
const partiallyVisible = partially && overlappingArea > 0;
|
|
940
|
+
return partiallyVisible || overlappingArea >= nodeRect.width * nodeRect.height;
|
|
941
|
+
},
|
|
942
|
+
updateNode,
|
|
943
|
+
updateNodeData: (id, dataUpdate, options = { replace: false }) => {
|
|
944
|
+
updateNode(id, (node) => {
|
|
945
|
+
const nextData = typeof dataUpdate === 'function' ? dataUpdate(node) : dataUpdate;
|
|
946
|
+
return options.replace ? { ...node, data: nextData } : { ...node, data: { ...node.data, ...nextData } };
|
|
947
|
+
}, options);
|
|
948
|
+
},
|
|
949
|
+
updateEdge,
|
|
950
|
+
updateEdgeData: (id, dataUpdate, options = { replace: false }) => {
|
|
951
|
+
updateEdge(id, (edge) => {
|
|
952
|
+
const nextData = typeof dataUpdate === 'function' ? dataUpdate(edge) : dataUpdate;
|
|
953
|
+
return options.replace ? { ...edge, data: nextData } : { ...edge, data: { ...edge.data, ...nextData } };
|
|
954
|
+
}, options);
|
|
955
|
+
},
|
|
956
|
+
};
|
|
829
957
|
}, []);
|
|
830
|
-
const updateNode = useCallback((id, nodeUpdate, options = { replace: true }) => {
|
|
831
|
-
setNodes((prevNodes) => prevNodes.map((node) => {
|
|
832
|
-
if (node.id === id) {
|
|
833
|
-
const nextNode = typeof nodeUpdate === 'function' ? nodeUpdate(node) : nodeUpdate;
|
|
834
|
-
return options.replace && isNode(nextNode) ? nextNode : { ...node, ...nextNode };
|
|
835
|
-
}
|
|
836
|
-
return node;
|
|
837
|
-
}));
|
|
838
|
-
}, [setNodes]);
|
|
839
|
-
const updateNodeData = useCallback((id, dataUpdate, options = { replace: false }) => {
|
|
840
|
-
updateNode(id, (node) => {
|
|
841
|
-
const nextData = typeof dataUpdate === 'function' ? dataUpdate(node) : dataUpdate;
|
|
842
|
-
return options.replace ? { ...node, data: nextData } : { ...node, data: { ...node.data, ...nextData } };
|
|
843
|
-
}, options);
|
|
844
|
-
}, [updateNode]);
|
|
845
958
|
return useMemo(() => {
|
|
846
959
|
return {
|
|
960
|
+
...generalHelper,
|
|
847
961
|
...viewportHelper,
|
|
848
|
-
|
|
849
|
-
getNode,
|
|
850
|
-
getEdges,
|
|
851
|
-
getEdge,
|
|
852
|
-
setNodes,
|
|
853
|
-
setEdges,
|
|
854
|
-
addNodes,
|
|
855
|
-
addEdges,
|
|
856
|
-
toObject,
|
|
857
|
-
deleteElements,
|
|
858
|
-
getIntersectingNodes,
|
|
859
|
-
isNodeIntersecting,
|
|
860
|
-
updateNode,
|
|
861
|
-
updateNodeData,
|
|
962
|
+
viewportInitialized,
|
|
862
963
|
};
|
|
863
|
-
}, [
|
|
864
|
-
viewportHelper,
|
|
865
|
-
getNodes,
|
|
866
|
-
getNode,
|
|
867
|
-
getEdges,
|
|
868
|
-
getEdge,
|
|
869
|
-
setNodes,
|
|
870
|
-
setEdges,
|
|
871
|
-
addNodes,
|
|
872
|
-
addEdges,
|
|
873
|
-
toObject,
|
|
874
|
-
deleteElements,
|
|
875
|
-
getIntersectingNodes,
|
|
876
|
-
isNodeIntersecting,
|
|
877
|
-
updateNode,
|
|
878
|
-
updateNodeData,
|
|
879
|
-
]);
|
|
964
|
+
}, [viewportInitialized]);
|
|
880
965
|
}
|
|
881
966
|
|
|
882
967
|
const selected = (item) => item.selected;
|
|
@@ -886,22 +971,22 @@ const deleteKeyOptions = { actInsideInputWithModifier: false };
|
|
|
886
971
|
*
|
|
887
972
|
* @internal
|
|
888
973
|
*/
|
|
889
|
-
|
|
974
|
+
function useGlobalKeyHandler({ deleteKeyCode, multiSelectionKeyCode, }) {
|
|
890
975
|
const store = useStoreApi();
|
|
891
976
|
const { deleteElements } = useReactFlow();
|
|
892
977
|
const deleteKeyPressed = useKeyPress(deleteKeyCode, deleteKeyOptions);
|
|
893
978
|
const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode);
|
|
894
979
|
useEffect(() => {
|
|
895
980
|
if (deleteKeyPressed) {
|
|
896
|
-
const { edges, nodes
|
|
897
|
-
deleteElements({ nodes: nodes.filter(selected), edges: edges.filter(selected)
|
|
981
|
+
const { edges, nodes } = store.getState();
|
|
982
|
+
deleteElements({ nodes: nodes.filter(selected), edges: edges.filter(selected) });
|
|
898
983
|
store.setState({ nodesSelectionActive: false });
|
|
899
984
|
}
|
|
900
985
|
}, [deleteKeyPressed]);
|
|
901
986
|
useEffect(() => {
|
|
902
987
|
store.setState({ multiSelectionActive: multiSelectionKeyPressed });
|
|
903
988
|
}, [multiSelectionKeyPressed]);
|
|
904
|
-
}
|
|
989
|
+
}
|
|
905
990
|
|
|
906
991
|
/**
|
|
907
992
|
* Hook for handling resize events.
|
|
@@ -948,7 +1033,7 @@ const selector$l = (s) => ({
|
|
|
948
1033
|
userSelectionActive: s.userSelectionActive,
|
|
949
1034
|
lib: s.lib,
|
|
950
1035
|
});
|
|
951
|
-
|
|
1036
|
+
function ZoomPane({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true, panOnScroll = false, panOnScrollSpeed = 0.5, panOnScrollMode = PanOnScrollMode.Free, zoomOnDoubleClick = true, panOnDrag = true, defaultViewport, translateExtent, minZoom, maxZoom, zoomActivationKeyCode, preventScrolling = true, children, noWheelClassName, noPanClassName, onViewportChange, isControlledViewport, }) {
|
|
952
1037
|
const store = useStoreApi();
|
|
953
1038
|
const zoomPane = useRef(null);
|
|
954
1039
|
const { userSelectionActive, lib } = useStore(selector$l, shallow);
|
|
@@ -1031,7 +1116,7 @@ const ZoomPane = ({ onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true,
|
|
|
1031
1116
|
lib,
|
|
1032
1117
|
]);
|
|
1033
1118
|
return (jsx("div", { className: "react-flow__renderer", ref: zoomPane, style: containerStyle, children: children }));
|
|
1034
|
-
}
|
|
1119
|
+
}
|
|
1035
1120
|
|
|
1036
1121
|
const selector$k = (s) => ({
|
|
1037
1122
|
userSelectionActive: s.userSelectionActive,
|
|
@@ -1063,12 +1148,13 @@ const selector$j = (s) => ({
|
|
|
1063
1148
|
elementsSelectable: s.elementsSelectable,
|
|
1064
1149
|
dragging: s.paneDragging,
|
|
1065
1150
|
});
|
|
1066
|
-
|
|
1151
|
+
function Pane({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag, onSelectionStart, onSelectionEnd, onPaneClick, onPaneContextMenu, onPaneScroll, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, children, }) {
|
|
1067
1152
|
const container = useRef(null);
|
|
1068
1153
|
const store = useStoreApi();
|
|
1069
1154
|
const prevSelectedNodesCount = useRef(0);
|
|
1070
1155
|
const prevSelectedEdgesCount = useRef(0);
|
|
1071
1156
|
const containerBounds = useRef();
|
|
1157
|
+
const edgeIdLookup = useRef(new Map());
|
|
1072
1158
|
const { userSelectionActive, elementsSelectable, dragging } = useStore(selector$j, shallow);
|
|
1073
1159
|
const resetUserSelection = () => {
|
|
1074
1160
|
store.setState({ userSelectionActive: false, userSelectionRect: null });
|
|
@@ -1089,7 +1175,7 @@ const Pane = memo(({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag,
|
|
|
1089
1175
|
};
|
|
1090
1176
|
const onWheel = onPaneScroll ? (event) => onPaneScroll(event) : undefined;
|
|
1091
1177
|
const onMouseDown = (event) => {
|
|
1092
|
-
const { resetSelectedElements, domNode } = store.getState();
|
|
1178
|
+
const { resetSelectedElements, domNode, edgeLookup } = store.getState();
|
|
1093
1179
|
containerBounds.current = domNode?.getBoundingClientRect();
|
|
1094
1180
|
if (!elementsSelectable ||
|
|
1095
1181
|
!isSelecting ||
|
|
@@ -1098,6 +1184,11 @@ const Pane = memo(({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag,
|
|
|
1098
1184
|
!containerBounds.current) {
|
|
1099
1185
|
return;
|
|
1100
1186
|
}
|
|
1187
|
+
edgeIdLookup.current = new Map();
|
|
1188
|
+
for (const [id, edge] of edgeLookup) {
|
|
1189
|
+
edgeIdLookup.current.set(edge.source, edgeIdLookup.current.get(edge.source)?.add(id) || new Set([id]));
|
|
1190
|
+
edgeIdLookup.current.set(edge.target, edgeIdLookup.current.get(edge.target)?.add(id) || new Set([id]));
|
|
1191
|
+
}
|
|
1101
1192
|
const { x, y } = getEventPosition(event.nativeEvent, containerBounds.current);
|
|
1102
1193
|
resetSelectedElements();
|
|
1103
1194
|
store.setState({
|
|
@@ -1113,48 +1204,46 @@ const Pane = memo(({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag,
|
|
|
1113
1204
|
onSelectionStart?.(event);
|
|
1114
1205
|
};
|
|
1115
1206
|
const onMouseMove = (event) => {
|
|
1116
|
-
const { userSelectionRect,
|
|
1207
|
+
const { userSelectionRect, edgeLookup, transform, nodeOrigin, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = store.getState();
|
|
1117
1208
|
if (!isSelecting || !containerBounds.current || !userSelectionRect) {
|
|
1118
1209
|
return;
|
|
1119
1210
|
}
|
|
1120
|
-
|
|
1121
|
-
const
|
|
1122
|
-
const startX = userSelectionRect.startX ?? 0;
|
|
1123
|
-
const startY = userSelectionRect.startY ?? 0;
|
|
1211
|
+
const { x: mouseX, y: mouseY } = getEventPosition(event.nativeEvent, containerBounds.current);
|
|
1212
|
+
const { startX, startY } = userSelectionRect;
|
|
1124
1213
|
const nextUserSelectRect = {
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1214
|
+
startX,
|
|
1215
|
+
startY,
|
|
1216
|
+
x: mouseX < startX ? mouseX : startX,
|
|
1217
|
+
y: mouseY < startY ? mouseY : startY,
|
|
1218
|
+
width: Math.abs(mouseX - startX),
|
|
1219
|
+
height: Math.abs(mouseY - startY),
|
|
1130
1220
|
};
|
|
1131
|
-
const selectedNodes = getNodesInside(
|
|
1221
|
+
const selectedNodes = getNodesInside(nodeLookup, nextUserSelectRect, transform, selectionMode === SelectionMode.Partial, true, nodeOrigin);
|
|
1132
1222
|
const selectedEdgeIds = new Set();
|
|
1133
1223
|
const selectedNodeIds = new Set();
|
|
1134
1224
|
for (const selectedNode of selectedNodes) {
|
|
1135
1225
|
selectedNodeIds.add(selectedNode.id);
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1226
|
+
const edgeIds = edgeIdLookup.current.get(selectedNode.id);
|
|
1227
|
+
if (edgeIds) {
|
|
1228
|
+
for (const edgeId of edgeIds) {
|
|
1229
|
+
selectedEdgeIds.add(edgeId);
|
|
1139
1230
|
}
|
|
1140
1231
|
}
|
|
1141
1232
|
}
|
|
1142
1233
|
if (prevSelectedNodesCount.current !== selectedNodeIds.size) {
|
|
1143
1234
|
prevSelectedNodesCount.current = selectedNodeIds.size;
|
|
1144
|
-
const changes = getSelectionChanges(
|
|
1145
|
-
|
|
1146
|
-
onNodesChange?.(changes);
|
|
1147
|
-
}
|
|
1235
|
+
const changes = getSelectionChanges(nodeLookup, selectedNodeIds, true);
|
|
1236
|
+
triggerNodeChanges(changes);
|
|
1148
1237
|
}
|
|
1149
1238
|
if (prevSelectedEdgesCount.current !== selectedEdgeIds.size) {
|
|
1150
1239
|
prevSelectedEdgesCount.current = selectedEdgeIds.size;
|
|
1151
|
-
const changes = getSelectionChanges(
|
|
1152
|
-
|
|
1153
|
-
onEdgesChange?.(changes);
|
|
1154
|
-
}
|
|
1240
|
+
const changes = getSelectionChanges(edgeLookup, selectedEdgeIds);
|
|
1241
|
+
triggerEdgeChanges(changes);
|
|
1155
1242
|
}
|
|
1156
1243
|
store.setState({
|
|
1157
1244
|
userSelectionRect: nextUserSelectRect,
|
|
1245
|
+
userSelectionActive: true,
|
|
1246
|
+
nodesSelectionActive: false,
|
|
1158
1247
|
});
|
|
1159
1248
|
};
|
|
1160
1249
|
const onMouseUp = (event) => {
|
|
@@ -1179,9 +1268,8 @@ const Pane = memo(({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag,
|
|
|
1179
1268
|
resetUserSelection();
|
|
1180
1269
|
};
|
|
1181
1270
|
const hasActiveSelection = elementsSelectable && (isSelecting || userSelectionActive);
|
|
1182
|
-
return (jsxs("div", { className: cc(['react-flow__pane', { dragging, selection: isSelecting }]), onClick: hasActiveSelection ? undefined : wrapHandler(onClick, container), onContextMenu: wrapHandler(onContextMenu, container), onWheel: wrapHandler(onWheel, container), onMouseEnter: hasActiveSelection ? undefined : onPaneMouseEnter, onMouseDown: hasActiveSelection ? onMouseDown : undefined, onMouseMove: hasActiveSelection ? onMouseMove : onPaneMouseMove, onMouseUp: hasActiveSelection ? onMouseUp : undefined, onMouseLeave: hasActiveSelection ? onMouseLeave : onPaneMouseLeave, ref: container, style: containerStyle, children: [children, jsx(UserSelection, {})] }));
|
|
1183
|
-
}
|
|
1184
|
-
Pane.displayName = 'Pane';
|
|
1271
|
+
return (jsxs("div", { className: cc(['react-flow__pane', { draggable: panOnDrag, dragging, selection: isSelecting }]), onClick: hasActiveSelection ? undefined : wrapHandler(onClick, container), onContextMenu: wrapHandler(onContextMenu, container), onWheel: wrapHandler(onWheel, container), onMouseEnter: hasActiveSelection ? undefined : onPaneMouseEnter, onMouseDown: hasActiveSelection ? onMouseDown : undefined, onMouseMove: hasActiveSelection ? onMouseMove : onPaneMouseMove, onMouseUp: hasActiveSelection ? onMouseUp : undefined, onMouseLeave: hasActiveSelection ? onMouseLeave : onPaneMouseLeave, ref: container, style: containerStyle, children: [children, jsx(UserSelection, {})] }));
|
|
1272
|
+
}
|
|
1185
1273
|
|
|
1186
1274
|
// this handler is called by
|
|
1187
1275
|
// 1. the click handler when node is not draggable or selectNodesOnDrag = false
|
|
@@ -1209,36 +1297,33 @@ function handleNodeClick({ id, store, unselect = false, nodeRef, }) {
|
|
|
1209
1297
|
*
|
|
1210
1298
|
* @internal
|
|
1211
1299
|
*/
|
|
1212
|
-
function useDrag({ nodeRef, disabled = false, noDragClassName, handleSelector, nodeId, isSelectable }) {
|
|
1300
|
+
function useDrag({ nodeRef, disabled = false, noDragClassName, handleSelector, nodeId, isSelectable, }) {
|
|
1213
1301
|
const store = useStoreApi();
|
|
1214
1302
|
const [dragging, setDragging] = useState(false);
|
|
1215
1303
|
const xyDrag = useRef();
|
|
1216
1304
|
useEffect(() => {
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
},
|
|
1234
|
-
});
|
|
1235
|
-
}
|
|
1305
|
+
xyDrag.current = XYDrag({
|
|
1306
|
+
getStoreItems: () => store.getState(),
|
|
1307
|
+
onNodeMouseDown: (id) => {
|
|
1308
|
+
handleNodeClick({
|
|
1309
|
+
id,
|
|
1310
|
+
store,
|
|
1311
|
+
nodeRef,
|
|
1312
|
+
});
|
|
1313
|
+
},
|
|
1314
|
+
onDragStart: () => {
|
|
1315
|
+
setDragging(true);
|
|
1316
|
+
},
|
|
1317
|
+
onDragStop: () => {
|
|
1318
|
+
setDragging(false);
|
|
1319
|
+
},
|
|
1320
|
+
});
|
|
1236
1321
|
}, []);
|
|
1237
1322
|
useEffect(() => {
|
|
1238
1323
|
if (disabled) {
|
|
1239
1324
|
xyDrag.current?.destroy();
|
|
1240
1325
|
}
|
|
1241
|
-
else {
|
|
1326
|
+
else if (nodeRef.current) {
|
|
1242
1327
|
xyDrag.current?.update({
|
|
1243
1328
|
noDragClassName,
|
|
1244
1329
|
handleSelector,
|
|
@@ -1256,44 +1341,49 @@ function useDrag({ nodeRef, disabled = false, noDragClassName, handleSelector, n
|
|
|
1256
1341
|
|
|
1257
1342
|
const selectedAndDraggable = (nodesDraggable) => (n) => n.selected && (n.draggable || (nodesDraggable && typeof n.draggable === 'undefined'));
|
|
1258
1343
|
/**
|
|
1259
|
-
* Hook for updating node positions
|
|
1344
|
+
* Hook for updating node positions by passing a direction and factor
|
|
1260
1345
|
*
|
|
1261
1346
|
* @internal
|
|
1262
1347
|
* @returns function for updating node positions
|
|
1263
1348
|
*/
|
|
1264
|
-
function
|
|
1349
|
+
function useMoveSelectedNodes() {
|
|
1265
1350
|
const store = useStoreApi();
|
|
1266
|
-
const
|
|
1267
|
-
const { nodeExtent,
|
|
1268
|
-
const
|
|
1269
|
-
|
|
1270
|
-
//
|
|
1351
|
+
const moveSelectedNodes = useCallback((params) => {
|
|
1352
|
+
const { nodeExtent, snapToGrid, snapGrid, nodesDraggable, onError, updateNodePositions, nodeLookup, nodeOrigin } = store.getState();
|
|
1353
|
+
const nodeUpdates = new Map();
|
|
1354
|
+
const isSelected = selectedAndDraggable(nodesDraggable);
|
|
1355
|
+
// by default a node moves 5px on each key press
|
|
1356
|
+
// if snap grid is enabled, we use that for the velocity
|
|
1271
1357
|
const xVelo = snapToGrid ? snapGrid[0] : 5;
|
|
1272
1358
|
const yVelo = snapToGrid ? snapGrid[1] : 5;
|
|
1273
|
-
const
|
|
1274
|
-
const
|
|
1275
|
-
const
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
let nextPosition = {
|
|
1279
|
-
x: node.computed?.positionAbsolute.x + xDiff,
|
|
1280
|
-
y: node.computed?.positionAbsolute.y + yDiff,
|
|
1281
|
-
};
|
|
1282
|
-
if (snapToGrid) {
|
|
1283
|
-
nextPosition = snapPosition(nextPosition, snapGrid);
|
|
1284
|
-
}
|
|
1285
|
-
const { positionAbsolute, position } = calcNextPosition(node, nextPosition, nodes, nodeExtent, undefined, onError);
|
|
1286
|
-
node.position = position;
|
|
1287
|
-
if (!node.computed) {
|
|
1288
|
-
node.computed = {};
|
|
1289
|
-
}
|
|
1290
|
-
node.computed.positionAbsolute = positionAbsolute;
|
|
1359
|
+
const xDiff = params.direction.x * xVelo * params.factor;
|
|
1360
|
+
const yDiff = params.direction.y * yVelo * params.factor;
|
|
1361
|
+
for (const [, node] of nodeLookup) {
|
|
1362
|
+
if (!isSelected(node)) {
|
|
1363
|
+
continue;
|
|
1291
1364
|
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1365
|
+
let nextPosition = {
|
|
1366
|
+
x: node.internals.positionAbsolute.x + xDiff,
|
|
1367
|
+
y: node.internals.positionAbsolute.y + yDiff,
|
|
1368
|
+
};
|
|
1369
|
+
if (snapToGrid) {
|
|
1370
|
+
nextPosition = snapPosition(nextPosition, snapGrid);
|
|
1371
|
+
}
|
|
1372
|
+
const { position, positionAbsolute } = calculateNodePosition({
|
|
1373
|
+
nodeId: node.id,
|
|
1374
|
+
nextPosition,
|
|
1375
|
+
nodeLookup,
|
|
1376
|
+
nodeExtent,
|
|
1377
|
+
nodeOrigin,
|
|
1378
|
+
onError,
|
|
1379
|
+
});
|
|
1380
|
+
node.position = position;
|
|
1381
|
+
node.internals.positionAbsolute = positionAbsolute;
|
|
1382
|
+
nodeUpdates.set(node.id, node);
|
|
1383
|
+
}
|
|
1384
|
+
updateNodePositions(nodeUpdates);
|
|
1295
1385
|
}, []);
|
|
1296
|
-
return
|
|
1386
|
+
return moveSelectedNodes;
|
|
1297
1387
|
}
|
|
1298
1388
|
|
|
1299
1389
|
const NodeIdContext = createContext(null);
|
|
@@ -1305,25 +1395,31 @@ const useNodeId = () => {
|
|
|
1305
1395
|
};
|
|
1306
1396
|
|
|
1307
1397
|
const selector$i = (s) => ({
|
|
1308
|
-
connectionStartHandle: s.connectionStartHandle,
|
|
1309
1398
|
connectOnClick: s.connectOnClick,
|
|
1310
1399
|
noPanClassName: s.noPanClassName,
|
|
1400
|
+
rfId: s.rfId,
|
|
1311
1401
|
});
|
|
1312
1402
|
const connectingSelector = (nodeId, handleId, type) => (state) => {
|
|
1313
|
-
const { connectionStartHandle: startHandle, connectionEndHandle: endHandle, connectionClickStartHandle: clickHandle, } = state;
|
|
1403
|
+
const { connectionStartHandle: startHandle, connectionEndHandle: endHandle, connectionClickStartHandle: clickHandle, connectionMode, connectionStatus, } = state;
|
|
1404
|
+
const connectingTo = endHandle?.nodeId === nodeId && endHandle?.handleId === handleId && endHandle?.type === type;
|
|
1314
1405
|
return {
|
|
1315
|
-
|
|
1316
|
-
|
|
1406
|
+
connectingFrom: startHandle?.nodeId === nodeId && startHandle?.handleId === handleId && startHandle?.type === type,
|
|
1407
|
+
connectingTo,
|
|
1317
1408
|
clickConnecting: clickHandle?.nodeId === nodeId && clickHandle?.handleId === handleId && clickHandle?.type === type,
|
|
1409
|
+
isPossibleEndHandle: connectionMode === ConnectionMode.Strict
|
|
1410
|
+
? startHandle?.type !== type
|
|
1411
|
+
: nodeId !== startHandle?.nodeId || handleId !== startHandle?.handleId,
|
|
1412
|
+
connectionInProcess: !!startHandle,
|
|
1413
|
+
valid: connectingTo && connectionStatus === 'valid',
|
|
1318
1414
|
};
|
|
1319
1415
|
};
|
|
1320
|
-
|
|
1416
|
+
function HandleComponent({ type = 'source', position = Position.Top, isValidConnection, isConnectable = true, isConnectableStart = true, isConnectableEnd = true, id, onConnect, children, className, onMouseDown, onTouchStart, ...rest }, ref) {
|
|
1321
1417
|
const handleId = id || null;
|
|
1322
1418
|
const isTarget = type === 'target';
|
|
1323
1419
|
const store = useStoreApi();
|
|
1324
1420
|
const nodeId = useNodeId();
|
|
1325
|
-
const { connectOnClick, noPanClassName } = useStore(selector$i, shallow);
|
|
1326
|
-
const {
|
|
1421
|
+
const { connectOnClick, noPanClassName, rfId } = useStore(selector$i, shallow);
|
|
1422
|
+
const { connectingFrom, connectingTo, clickConnecting, isPossibleEndHandle, connectionInProcess, valid } = useStore(connectingSelector(nodeId, handleId, type), shallow);
|
|
1327
1423
|
if (!nodeId) {
|
|
1328
1424
|
store.getState().onError?.('010', errorMessages['error010']());
|
|
1329
1425
|
}
|
|
@@ -1353,11 +1449,12 @@ const Handle = forwardRef(({ type = 'source', position = Position.Top, isValidCo
|
|
|
1353
1449
|
connectionMode: currentStore.connectionMode,
|
|
1354
1450
|
connectionRadius: currentStore.connectionRadius,
|
|
1355
1451
|
domNode: currentStore.domNode,
|
|
1356
|
-
|
|
1452
|
+
nodeLookup: currentStore.nodeLookup,
|
|
1357
1453
|
lib: currentStore.lib,
|
|
1358
1454
|
isTarget,
|
|
1359
1455
|
handleId,
|
|
1360
1456
|
nodeId,
|
|
1457
|
+
flowId: currentStore.rfId,
|
|
1361
1458
|
panBy: currentStore.panBy,
|
|
1362
1459
|
cancelConnection: currentStore.cancelConnection,
|
|
1363
1460
|
onConnectStart: currentStore.onConnectStart,
|
|
@@ -1366,6 +1463,7 @@ const Handle = forwardRef(({ type = 'source', position = Position.Top, isValidCo
|
|
|
1366
1463
|
onConnect: onConnectExtended,
|
|
1367
1464
|
isValidConnection: isValidConnection || currentStore.isValidConnection,
|
|
1368
1465
|
getTransform: () => store.getState().transform,
|
|
1466
|
+
getConnectionStartHandle: () => store.getState().connectionStartHandle,
|
|
1369
1467
|
});
|
|
1370
1468
|
}
|
|
1371
1469
|
if (isMouseTriggered) {
|
|
@@ -1376,7 +1474,7 @@ const Handle = forwardRef(({ type = 'source', position = Position.Top, isValidCo
|
|
|
1376
1474
|
}
|
|
1377
1475
|
};
|
|
1378
1476
|
const onClick = (event) => {
|
|
1379
|
-
const { onClickConnectStart, onClickConnectEnd, connectionClickStartHandle, connectionMode, isValidConnection: isValidConnectionStore, lib, } = store.getState();
|
|
1477
|
+
const { onClickConnectStart, onClickConnectEnd, connectionClickStartHandle, connectionMode, isValidConnection: isValidConnectionStore, lib, rfId: flowId, } = store.getState();
|
|
1380
1478
|
if (!nodeId || (!connectionClickStartHandle && !isConnectableStart)) {
|
|
1381
1479
|
return;
|
|
1382
1480
|
}
|
|
@@ -1398,6 +1496,7 @@ const Handle = forwardRef(({ type = 'source', position = Position.Top, isValidCo
|
|
|
1398
1496
|
fromHandleId: connectionClickStartHandle.handleId || null,
|
|
1399
1497
|
fromType: connectionClickStartHandle.type,
|
|
1400
1498
|
isValidConnection: isValidConnectionHandler,
|
|
1499
|
+
flowId,
|
|
1401
1500
|
doc,
|
|
1402
1501
|
lib,
|
|
1403
1502
|
});
|
|
@@ -1407,7 +1506,7 @@ const Handle = forwardRef(({ type = 'source', position = Position.Top, isValidCo
|
|
|
1407
1506
|
onClickConnectEnd?.(event);
|
|
1408
1507
|
store.setState({ connectionClickStartHandle: null });
|
|
1409
1508
|
};
|
|
1410
|
-
return (jsx("div", { "data-handleid": handleId, "data-nodeid": nodeId, "data-handlepos": position, "data-id": `${nodeId}-${handleId}-${type}`, className: cc([
|
|
1509
|
+
return (jsx("div", { "data-handleid": handleId, "data-nodeid": nodeId, "data-handlepos": position, "data-id": `${rfId}-${nodeId}-${handleId}-${type}`, className: cc([
|
|
1411
1510
|
'react-flow__handle',
|
|
1412
1511
|
`react-flow__handle-${position}`,
|
|
1413
1512
|
'nodrag',
|
|
@@ -1419,31 +1518,38 @@ const Handle = forwardRef(({ type = 'source', position = Position.Top, isValidCo
|
|
|
1419
1518
|
connectable: isConnectable,
|
|
1420
1519
|
connectablestart: isConnectableStart,
|
|
1421
1520
|
connectableend: isConnectableEnd,
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1521
|
+
clickconnecting: clickConnecting,
|
|
1522
|
+
connectingfrom: connectingFrom,
|
|
1523
|
+
connectingto: connectingTo,
|
|
1524
|
+
valid,
|
|
1525
|
+
// shows where you can start a connection from
|
|
1526
|
+
// and where you can end it while connecting
|
|
1527
|
+
connectionindicator: isConnectable &&
|
|
1528
|
+
(!connectionInProcess || isPossibleEndHandle) &&
|
|
1529
|
+
(connectionInProcess ? isConnectableEnd : isConnectableStart),
|
|
1425
1530
|
},
|
|
1426
1531
|
]), onMouseDown: onPointerDown, onTouchStart: onPointerDown, onClick: connectOnClick ? onClick : undefined, ref: ref, ...rest, children: children }));
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
|
|
1532
|
+
}
|
|
1533
|
+
/**
|
|
1534
|
+
* The Handle component is a UI element that is used to connect nodes.
|
|
1535
|
+
*/
|
|
1536
|
+
const Handle = memo(fixedForwardRef(HandleComponent));
|
|
1430
1537
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1538
|
+
function InputNode({ data, isConnectable, sourcePosition = Position.Bottom }) {
|
|
1539
|
+
return (jsxs(Fragment, { children: [data?.label, jsx(Handle, { type: "source", position: sourcePosition, isConnectable: isConnectable })] }));
|
|
1540
|
+
}
|
|
1434
1541
|
|
|
1435
|
-
|
|
1436
|
-
return (jsxs(Fragment, { children: [jsx(Handle
|
|
1437
|
-
}
|
|
1438
|
-
DefaultNode.displayName = 'DefaultNode';
|
|
1439
|
-
var DefaultNode$1 = memo(DefaultNode);
|
|
1542
|
+
function DefaultNode({ data, isConnectable, targetPosition = Position.Top, sourcePosition = Position.Bottom, }) {
|
|
1543
|
+
return (jsxs(Fragment, { children: [jsx(Handle, { type: "target", position: targetPosition, isConnectable: isConnectable }), data?.label, jsx(Handle, { type: "source", position: sourcePosition, isConnectable: isConnectable })] }));
|
|
1544
|
+
}
|
|
1440
1545
|
|
|
1441
|
-
|
|
1442
|
-
|
|
1546
|
+
function GroupNode() {
|
|
1547
|
+
return null;
|
|
1548
|
+
}
|
|
1443
1549
|
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1550
|
+
function OutputNode({ data, isConnectable, targetPosition = Position.Top }) {
|
|
1551
|
+
return (jsxs(Fragment, { children: [jsx(Handle, { type: "target", position: targetPosition, isConnectable: isConnectable }), data?.label] }));
|
|
1552
|
+
}
|
|
1447
1553
|
|
|
1448
1554
|
const arrowKeyDiffs = {
|
|
1449
1555
|
ArrowUp: { x: 0, y: -1 },
|
|
@@ -1452,26 +1558,40 @@ const arrowKeyDiffs = {
|
|
|
1452
1558
|
ArrowRight: { x: 1, y: 0 },
|
|
1453
1559
|
};
|
|
1454
1560
|
const builtinNodeTypes = {
|
|
1455
|
-
input: InputNode
|
|
1456
|
-
default: DefaultNode
|
|
1457
|
-
output: OutputNode
|
|
1561
|
+
input: InputNode,
|
|
1562
|
+
default: DefaultNode,
|
|
1563
|
+
output: OutputNode,
|
|
1458
1564
|
group: GroupNode,
|
|
1459
1565
|
};
|
|
1566
|
+
function getNodeInlineStyleDimensions(node) {
|
|
1567
|
+
if (node.internals.handleBounds === undefined) {
|
|
1568
|
+
return {
|
|
1569
|
+
width: node.width ?? node.initialWidth ?? node.style?.width,
|
|
1570
|
+
height: node.height ?? node.initialHeight ?? node.style?.height,
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
return {
|
|
1574
|
+
width: node.width ?? node.style?.width,
|
|
1575
|
+
height: node.height ?? node.style?.height,
|
|
1576
|
+
};
|
|
1577
|
+
}
|
|
1460
1578
|
|
|
1461
1579
|
const selector$h = (s) => {
|
|
1462
|
-
const
|
|
1463
|
-
|
|
1580
|
+
const { width, height, x, y } = getInternalNodesBounds(s.nodeLookup, {
|
|
1581
|
+
nodeOrigin: s.nodeOrigin,
|
|
1582
|
+
filter: (node) => !!node.selected,
|
|
1583
|
+
});
|
|
1464
1584
|
return {
|
|
1465
|
-
width,
|
|
1466
|
-
height,
|
|
1585
|
+
width: isNumeric(width) ? width : null,
|
|
1586
|
+
height: isNumeric(height) ? height : null,
|
|
1467
1587
|
userSelectionActive: s.userSelectionActive,
|
|
1468
1588
|
transformString: `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]}) translate(${x}px,${y}px)`,
|
|
1469
1589
|
};
|
|
1470
1590
|
};
|
|
1471
|
-
function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboardA11y }) {
|
|
1591
|
+
function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboardA11y, }) {
|
|
1472
1592
|
const store = useStoreApi();
|
|
1473
1593
|
const { width, height, transformString, userSelectionActive } = useStore(selector$h, shallow);
|
|
1474
|
-
const
|
|
1594
|
+
const moveSelectedNodes = useMoveSelectedNodes();
|
|
1475
1595
|
const nodeRef = useRef(null);
|
|
1476
1596
|
useEffect(() => {
|
|
1477
1597
|
if (!disableKeyboardA11y) {
|
|
@@ -1494,10 +1614,9 @@ function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboar
|
|
|
1494
1614
|
: undefined;
|
|
1495
1615
|
const onKeyDown = (event) => {
|
|
1496
1616
|
if (Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)) {
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
isShiftPressed: event.shiftKey,
|
|
1617
|
+
moveSelectedNodes({
|
|
1618
|
+
direction: arrowKeyDiffs[event.key],
|
|
1619
|
+
factor: event.shiftKey ? 4 : 1,
|
|
1501
1620
|
});
|
|
1502
1621
|
}
|
|
1503
1622
|
};
|
|
@@ -1508,25 +1627,26 @@ function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboar
|
|
|
1508
1627
|
height,
|
|
1509
1628
|
} }) }));
|
|
1510
1629
|
}
|
|
1511
|
-
var NodesSelection$1 = memo(NodesSelection);
|
|
1512
1630
|
|
|
1513
|
-
const selector$g = (s) =>
|
|
1514
|
-
|
|
1515
|
-
|
|
1631
|
+
const selector$g = (s) => {
|
|
1632
|
+
return { nodesSelectionActive: s.nodesSelectionActive, userSelectionActive: s.userSelectionActive };
|
|
1633
|
+
};
|
|
1634
|
+
function FlowRendererComponent({ children, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneContextMenu, onPaneScroll, deleteKeyCode, selectionKeyCode, selectionOnDrag, selectionMode, onSelectionStart, onSelectionEnd, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, elementsSelectable, zoomOnScroll, zoomOnPinch, panOnScroll: _panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag: _panOnDrag, defaultViewport, translateExtent, minZoom, maxZoom, preventScrolling, onSelectionContextMenu, noWheelClassName, noPanClassName, disableKeyboardA11y, onViewportChange, isControlledViewport, }) {
|
|
1635
|
+
const { nodesSelectionActive, userSelectionActive } = useStore(selector$g);
|
|
1516
1636
|
const selectionKeyPressed = useKeyPress(selectionKeyCode);
|
|
1517
1637
|
const panActivationKeyPressed = useKeyPress(panActivationKeyCode);
|
|
1518
1638
|
const panOnDrag = panActivationKeyPressed || _panOnDrag;
|
|
1519
1639
|
const panOnScroll = panActivationKeyPressed || _panOnScroll;
|
|
1520
|
-
const isSelecting = selectionKeyPressed || (selectionOnDrag && panOnDrag !== true);
|
|
1640
|
+
const isSelecting = selectionKeyPressed || userSelectionActive || (selectionOnDrag && panOnDrag !== true);
|
|
1521
1641
|
useGlobalKeyHandler({ deleteKeyCode, multiSelectionKeyCode });
|
|
1522
|
-
return (jsx(ZoomPane, { onPaneContextMenu: onPaneContextMenu, elementsSelectable: elementsSelectable, zoomOnScroll: zoomOnScroll, zoomOnPinch: zoomOnPinch, panOnScroll: panOnScroll, panOnScrollSpeed: panOnScrollSpeed, panOnScrollMode: panOnScrollMode, zoomOnDoubleClick: zoomOnDoubleClick, panOnDrag: !selectionKeyPressed && panOnDrag, defaultViewport: defaultViewport, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, zoomActivationKeyCode: zoomActivationKeyCode, preventScrolling: preventScrolling, noWheelClassName: noWheelClassName, noPanClassName: noPanClassName, onViewportChange: onViewportChange, isControlledViewport: isControlledViewport, children: jsxs(Pane, { onSelectionStart: onSelectionStart, onSelectionEnd: onSelectionEnd, onPaneClick: onPaneClick, onPaneMouseEnter: onPaneMouseEnter, onPaneMouseMove: onPaneMouseMove, onPaneMouseLeave: onPaneMouseLeave, onPaneContextMenu: onPaneContextMenu, onPaneScroll: onPaneScroll, panOnDrag: panOnDrag, isSelecting: !!isSelecting, selectionMode: selectionMode, children: [children, nodesSelectionActive && (jsx(NodesSelection
|
|
1523
|
-
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1642
|
+
return (jsx(ZoomPane, { onPaneContextMenu: onPaneContextMenu, elementsSelectable: elementsSelectable, zoomOnScroll: zoomOnScroll, zoomOnPinch: zoomOnPinch, panOnScroll: panOnScroll, panOnScrollSpeed: panOnScrollSpeed, panOnScrollMode: panOnScrollMode, zoomOnDoubleClick: zoomOnDoubleClick, panOnDrag: !selectionKeyPressed && panOnDrag, defaultViewport: defaultViewport, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, zoomActivationKeyCode: zoomActivationKeyCode, preventScrolling: preventScrolling, noWheelClassName: noWheelClassName, noPanClassName: noPanClassName, onViewportChange: onViewportChange, isControlledViewport: isControlledViewport, children: jsxs(Pane, { onSelectionStart: onSelectionStart, onSelectionEnd: onSelectionEnd, onPaneClick: onPaneClick, onPaneMouseEnter: onPaneMouseEnter, onPaneMouseMove: onPaneMouseMove, onPaneMouseLeave: onPaneMouseLeave, onPaneContextMenu: onPaneContextMenu, onPaneScroll: onPaneScroll, panOnDrag: panOnDrag, isSelecting: !!isSelecting, selectionMode: selectionMode, children: [children, nodesSelectionActive && (jsx(NodesSelection, { onSelectionContextMenu: onSelectionContextMenu, noPanClassName: noPanClassName, disableKeyboardA11y: disableKeyboardA11y }))] }) }));
|
|
1643
|
+
}
|
|
1644
|
+
FlowRendererComponent.displayName = 'FlowRenderer';
|
|
1645
|
+
const FlowRenderer = memo(FlowRendererComponent);
|
|
1526
1646
|
|
|
1527
1647
|
const selector$f = (onlyRenderVisible) => (s) => {
|
|
1528
1648
|
return onlyRenderVisible
|
|
1529
|
-
? getNodesInside(s.
|
|
1649
|
+
? getNodesInside(s.nodeLookup, { x: 0, y: 0, width: s.width, height: s.height }, s.transform, true).map((node) => node.id)
|
|
1530
1650
|
: Array.from(s.nodeLookup.keys());
|
|
1531
1651
|
};
|
|
1532
1652
|
/**
|
|
@@ -1541,51 +1661,93 @@ function useVisibleNodeIds(onlyRenderVisible) {
|
|
|
1541
1661
|
return nodeIds;
|
|
1542
1662
|
}
|
|
1543
1663
|
|
|
1544
|
-
const selector$e = (s) => s.
|
|
1664
|
+
const selector$e = (s) => s.updateNodeInternals;
|
|
1545
1665
|
function useResizeObserver() {
|
|
1546
|
-
const
|
|
1547
|
-
const
|
|
1548
|
-
const resizeObserver = useMemo(() => {
|
|
1666
|
+
const updateNodeInternals = useStore(selector$e);
|
|
1667
|
+
const [resizeObserver] = useState(() => {
|
|
1549
1668
|
if (typeof ResizeObserver === 'undefined') {
|
|
1550
1669
|
return null;
|
|
1551
1670
|
}
|
|
1552
|
-
|
|
1671
|
+
return new ResizeObserver((entries) => {
|
|
1553
1672
|
const updates = new Map();
|
|
1554
1673
|
entries.forEach((entry) => {
|
|
1555
1674
|
const id = entry.target.getAttribute('data-id');
|
|
1556
1675
|
updates.set(id, {
|
|
1557
1676
|
id,
|
|
1558
1677
|
nodeElement: entry.target,
|
|
1559
|
-
|
|
1678
|
+
force: true,
|
|
1560
1679
|
});
|
|
1561
1680
|
});
|
|
1562
|
-
|
|
1681
|
+
updateNodeInternals(updates);
|
|
1563
1682
|
});
|
|
1564
|
-
|
|
1565
|
-
return observer;
|
|
1566
|
-
}, []);
|
|
1683
|
+
});
|
|
1567
1684
|
useEffect(() => {
|
|
1568
1685
|
return () => {
|
|
1569
|
-
|
|
1686
|
+
resizeObserver?.disconnect();
|
|
1570
1687
|
};
|
|
1571
|
-
}, []);
|
|
1688
|
+
}, [resizeObserver]);
|
|
1572
1689
|
return resizeObserver;
|
|
1573
1690
|
}
|
|
1574
1691
|
|
|
1575
|
-
|
|
1576
|
-
|
|
1692
|
+
/**
|
|
1693
|
+
* Hook to handle the resize observation + internal updates for the passed node.
|
|
1694
|
+
*
|
|
1695
|
+
* @internal
|
|
1696
|
+
* @returns nodeRef - reference to the node element
|
|
1697
|
+
*/
|
|
1698
|
+
function useNodeObserver({ node, nodeType, hasDimensions, resizeObserver, }) {
|
|
1699
|
+
const store = useStoreApi();
|
|
1700
|
+
const nodeRef = useRef(null);
|
|
1701
|
+
const observedNode = useRef(null);
|
|
1702
|
+
const prevSourcePosition = useRef(node.sourcePosition);
|
|
1703
|
+
const prevTargetPosition = useRef(node.targetPosition);
|
|
1704
|
+
const prevType = useRef(nodeType);
|
|
1705
|
+
const isInitialized = hasDimensions && !!node.internals.handleBounds;
|
|
1706
|
+
useEffect(() => {
|
|
1707
|
+
if (nodeRef.current && !node.hidden && (!isInitialized || observedNode.current !== nodeRef.current)) {
|
|
1708
|
+
if (observedNode.current) {
|
|
1709
|
+
resizeObserver?.unobserve(observedNode.current);
|
|
1710
|
+
}
|
|
1711
|
+
resizeObserver?.observe(nodeRef.current);
|
|
1712
|
+
observedNode.current = nodeRef.current;
|
|
1713
|
+
}
|
|
1714
|
+
}, [isInitialized, node.hidden]);
|
|
1715
|
+
useEffect(() => {
|
|
1716
|
+
return () => {
|
|
1717
|
+
if (observedNode.current) {
|
|
1718
|
+
resizeObserver?.unobserve(observedNode.current);
|
|
1719
|
+
observedNode.current = null;
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
}, []);
|
|
1723
|
+
useEffect(() => {
|
|
1724
|
+
if (nodeRef.current) {
|
|
1725
|
+
// when the user programmatically changes the source or handle position, we need to update the internals
|
|
1726
|
+
// to make sure the edges are updated correctly
|
|
1727
|
+
const typeChanged = prevType.current !== nodeType;
|
|
1728
|
+
const sourcePosChanged = prevSourcePosition.current !== node.sourcePosition;
|
|
1729
|
+
const targetPosChanged = prevTargetPosition.current !== node.targetPosition;
|
|
1730
|
+
if (typeChanged || sourcePosChanged || targetPosChanged) {
|
|
1731
|
+
prevType.current = nodeType;
|
|
1732
|
+
prevSourcePosition.current = node.sourcePosition;
|
|
1733
|
+
prevTargetPosition.current = node.targetPosition;
|
|
1734
|
+
store
|
|
1735
|
+
.getState()
|
|
1736
|
+
.updateNodeInternals(new Map([[node.id, { id: node.id, nodeElement: nodeRef.current, force: true }]]));
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
}, [node.id, nodeType, node.sourcePosition, node.targetPosition]);
|
|
1740
|
+
return nodeRef;
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
function NodeWrapper({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onContextMenu, onDoubleClick, nodesDraggable, elementsSelectable, nodesConnectable, nodesFocusable, resizeObserver, noDragClassName, noPanClassName, disableKeyboardA11y, rfId, nodeTypes, nodeExtent, nodeOrigin, onError, }) {
|
|
1744
|
+
const { node, internals, isParent } = useStore((s) => {
|
|
1577
1745
|
const node = s.nodeLookup.get(id);
|
|
1578
|
-
const
|
|
1579
|
-
? clampPosition(node.computed?.positionAbsolute, nodeExtent)
|
|
1580
|
-
: node.computed?.positionAbsolute || { x: 0, y: 0 };
|
|
1746
|
+
const isParent = s.parentLookup.has(id);
|
|
1581
1747
|
return {
|
|
1582
1748
|
node,
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
positionAbsoluteX: positionAbsolute.x,
|
|
1586
|
-
positionAbsoluteY: positionAbsolute.y,
|
|
1587
|
-
zIndex: node[internalsSymbol]?.z ?? 0,
|
|
1588
|
-
isParent: !!node[internalsSymbol]?.isParent,
|
|
1749
|
+
internals: node.internals,
|
|
1750
|
+
isParent,
|
|
1589
1751
|
};
|
|
1590
1752
|
}, shallow);
|
|
1591
1753
|
let nodeType = node.type || 'default';
|
|
@@ -1600,36 +1762,8 @@ const NodeWrapper = ({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
|
|
|
1600
1762
|
const isConnectable = !!(node.connectable || (nodesConnectable && typeof node.connectable === 'undefined'));
|
|
1601
1763
|
const isFocusable = !!(node.focusable || (nodesFocusable && typeof node.focusable === 'undefined'));
|
|
1602
1764
|
const store = useStoreApi();
|
|
1603
|
-
const
|
|
1604
|
-
const
|
|
1605
|
-
const prevTargetPosition = useRef(node.targetPosition);
|
|
1606
|
-
const prevType = useRef(nodeType);
|
|
1607
|
-
const updatePositions = useUpdateNodePositions();
|
|
1608
|
-
useEffect(() => {
|
|
1609
|
-
if (nodeRef.current && !node.hidden) {
|
|
1610
|
-
const currNode = nodeRef.current;
|
|
1611
|
-
resizeObserver?.observe(currNode);
|
|
1612
|
-
return () => resizeObserver?.unobserve(currNode);
|
|
1613
|
-
}
|
|
1614
|
-
}, [node.hidden]);
|
|
1615
|
-
useEffect(() => {
|
|
1616
|
-
// when the user programmatically changes the source or handle position, we re-initialize the node
|
|
1617
|
-
const typeChanged = prevType.current !== nodeType;
|
|
1618
|
-
const sourcePosChanged = prevSourcePosition.current !== node.sourcePosition;
|
|
1619
|
-
const targetPosChanged = prevTargetPosition.current !== node.targetPosition;
|
|
1620
|
-
if (nodeRef.current && (typeChanged || sourcePosChanged || targetPosChanged)) {
|
|
1621
|
-
if (typeChanged) {
|
|
1622
|
-
prevType.current = nodeType;
|
|
1623
|
-
}
|
|
1624
|
-
if (sourcePosChanged) {
|
|
1625
|
-
prevSourcePosition.current = node.sourcePosition;
|
|
1626
|
-
}
|
|
1627
|
-
if (targetPosChanged) {
|
|
1628
|
-
prevTargetPosition.current = node.targetPosition;
|
|
1629
|
-
}
|
|
1630
|
-
store.getState().updateNodeDimensions(new Map([[id, { id, nodeElement: nodeRef.current, forceUpdate: true }]]));
|
|
1631
|
-
}
|
|
1632
|
-
}, [id, nodeType, node.sourcePosition, node.targetPosition]);
|
|
1765
|
+
const hasDimensions = nodeHasDimensions(node);
|
|
1766
|
+
const nodeRef = useNodeObserver({ node, nodeType, hasDimensions, resizeObserver });
|
|
1633
1767
|
const dragging = useDrag({
|
|
1634
1768
|
nodeRef,
|
|
1635
1769
|
disabled: node.hidden || !isDraggable,
|
|
@@ -1638,27 +1772,36 @@ const NodeWrapper = ({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
|
|
|
1638
1772
|
nodeId: id,
|
|
1639
1773
|
isSelectable,
|
|
1640
1774
|
});
|
|
1775
|
+
const moveSelectedNodes = useMoveSelectedNodes();
|
|
1641
1776
|
if (node.hidden) {
|
|
1642
1777
|
return null;
|
|
1643
1778
|
}
|
|
1644
|
-
const
|
|
1645
|
-
const
|
|
1646
|
-
const
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
height: computedHeight ?? height ?? 0,
|
|
1779
|
+
const nodeDimensions = getNodeDimensions(node);
|
|
1780
|
+
const inlineDimensions = getNodeInlineStyleDimensions(node);
|
|
1781
|
+
const clampedPosition = nodeExtent
|
|
1782
|
+
? clampPosition(internals.positionAbsolute, nodeExtent)
|
|
1783
|
+
: internals.positionAbsolute;
|
|
1784
|
+
const positionWithOrigin = getPositionWithOrigin({
|
|
1785
|
+
...clampedPosition,
|
|
1786
|
+
...nodeDimensions,
|
|
1653
1787
|
origin: node.origin || nodeOrigin,
|
|
1654
1788
|
});
|
|
1655
|
-
const initialized = (!!computedWidth && !!computedHeight) || (!!width && !!height);
|
|
1656
1789
|
const hasPointerEvents = isSelectable || isDraggable || onClick || onMouseEnter || onMouseMove || onMouseLeave;
|
|
1657
|
-
const onMouseEnterHandler = onMouseEnter
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
const
|
|
1661
|
-
|
|
1790
|
+
const onMouseEnterHandler = onMouseEnter
|
|
1791
|
+
? (event) => onMouseEnter(event, { ...internals.userNode })
|
|
1792
|
+
: undefined;
|
|
1793
|
+
const onMouseMoveHandler = onMouseMove
|
|
1794
|
+
? (event) => onMouseMove(event, { ...internals.userNode })
|
|
1795
|
+
: undefined;
|
|
1796
|
+
const onMouseLeaveHandler = onMouseLeave
|
|
1797
|
+
? (event) => onMouseLeave(event, { ...internals.userNode })
|
|
1798
|
+
: undefined;
|
|
1799
|
+
const onContextMenuHandler = onContextMenu
|
|
1800
|
+
? (event) => onContextMenu(event, { ...internals.userNode })
|
|
1801
|
+
: undefined;
|
|
1802
|
+
const onDoubleClickHandler = onDoubleClick
|
|
1803
|
+
? (event) => onDoubleClick(event, { ...internals.userNode })
|
|
1804
|
+
: undefined;
|
|
1662
1805
|
const onSelectNodeHandler = (event) => {
|
|
1663
1806
|
const { selectNodesOnDrag, nodeDragThreshold } = store.getState();
|
|
1664
1807
|
if (isSelectable && (!selectNodesOnDrag || !isDraggable || nodeDragThreshold > 0)) {
|
|
@@ -1671,11 +1814,11 @@ const NodeWrapper = ({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
|
|
|
1671
1814
|
});
|
|
1672
1815
|
}
|
|
1673
1816
|
if (onClick) {
|
|
1674
|
-
onClick(event, { ...
|
|
1817
|
+
onClick(event, { ...internals.userNode });
|
|
1675
1818
|
}
|
|
1676
1819
|
};
|
|
1677
1820
|
const onKeyDown = (event) => {
|
|
1678
|
-
if (isInputDOMNode(event.nativeEvent)) {
|
|
1821
|
+
if (isInputDOMNode(event.nativeEvent) || disableKeyboardA11y) {
|
|
1679
1822
|
return;
|
|
1680
1823
|
}
|
|
1681
1824
|
if (elementSelectionKeys.includes(event.key) && isSelectable) {
|
|
@@ -1687,19 +1830,15 @@ const NodeWrapper = ({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
|
|
|
1687
1830
|
nodeRef,
|
|
1688
1831
|
});
|
|
1689
1832
|
}
|
|
1690
|
-
else if (
|
|
1691
|
-
isDraggable &&
|
|
1692
|
-
node.selected &&
|
|
1693
|
-
Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)) {
|
|
1833
|
+
else if (isDraggable && node.selected && Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)) {
|
|
1694
1834
|
store.setState({
|
|
1695
1835
|
ariaLiveMessage: `Moved selected node ${event.key
|
|
1696
1836
|
.replace('Arrow', '')
|
|
1697
|
-
.toLowerCase()}. New position, x: ${~~
|
|
1837
|
+
.toLowerCase()}. New position, x: ${~~clampedPosition.x}, y: ${~~clampedPosition.y}`,
|
|
1698
1838
|
});
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
isShiftPressed: event.shiftKey,
|
|
1839
|
+
moveSelectedNodes({
|
|
1840
|
+
direction: arrowKeyDiffs[event.key],
|
|
1841
|
+
factor: event.shiftKey ? 4 : 1,
|
|
1703
1842
|
});
|
|
1704
1843
|
}
|
|
1705
1844
|
};
|
|
@@ -1715,20 +1854,18 @@ const NodeWrapper = ({ id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onC
|
|
|
1715
1854
|
selected: node.selected,
|
|
1716
1855
|
selectable: isSelectable,
|
|
1717
1856
|
parent: isParent,
|
|
1857
|
+
draggable: isDraggable,
|
|
1718
1858
|
dragging,
|
|
1719
1859
|
},
|
|
1720
1860
|
]), ref: nodeRef, style: {
|
|
1721
|
-
zIndex,
|
|
1722
|
-
transform: `translate(${
|
|
1861
|
+
zIndex: internals.z,
|
|
1862
|
+
transform: `translate(${positionWithOrigin.x}px,${positionWithOrigin.y}px)`,
|
|
1723
1863
|
pointerEvents: hasPointerEvents ? 'all' : 'none',
|
|
1724
|
-
visibility:
|
|
1725
|
-
width,
|
|
1726
|
-
height,
|
|
1864
|
+
visibility: hasDimensions ? 'visible' : 'hidden',
|
|
1727
1865
|
...node.style,
|
|
1728
|
-
|
|
1729
|
-
};
|
|
1730
|
-
|
|
1731
|
-
var NodeWrapper$1 = memo(NodeWrapper);
|
|
1866
|
+
...inlineDimensions,
|
|
1867
|
+
}, "data-id": id, "data-testid": `rf__node-${id}`, onMouseEnter: onMouseEnterHandler, onMouseMove: onMouseMoveHandler, onMouseLeave: onMouseLeaveHandler, onContextMenu: onContextMenuHandler, onClick: onSelectNodeHandler, onDoubleClick: onDoubleClickHandler, onKeyDown: isFocusable ? onKeyDown : undefined, tabIndex: isFocusable ? 0 : undefined, role: isFocusable ? 'button' : undefined, "aria-describedby": disableKeyboardA11y ? undefined : `${ARIA_NODE_DESC_KEY}-${rfId}`, "aria-label": node.ariaLabel, children: jsx(Provider, { value: id, children: jsx(NodeComponent, { id: id, data: node.data, type: nodeType, positionAbsoluteX: clampedPosition.x, positionAbsoluteY: clampedPosition.y, selected: node.selected, selectable: isSelectable, draggable: isDraggable, deletable: node.deletable ?? true, isConnectable: isConnectable, sourcePosition: node.sourcePosition, targetPosition: node.targetPosition, dragging: dragging, dragHandle: node.dragHandle, zIndex: internals.z, parentId: node.parentId, ...nodeDimensions }) }) }));
|
|
1868
|
+
}
|
|
1732
1869
|
|
|
1733
1870
|
const selector$d = (s) => ({
|
|
1734
1871
|
nodesDraggable: s.nodesDraggable,
|
|
@@ -1737,7 +1874,7 @@ const selector$d = (s) => ({
|
|
|
1737
1874
|
elementsSelectable: s.elementsSelectable,
|
|
1738
1875
|
onError: s.onError,
|
|
1739
1876
|
});
|
|
1740
|
-
|
|
1877
|
+
function NodeRendererComponent(props) {
|
|
1741
1878
|
const { nodesDraggable, nodesConnectable, nodesFocusable, elementsSelectable, onError } = useStore(selector$d, shallow);
|
|
1742
1879
|
const nodeIds = useVisibleNodeIds(props.onlyRenderVisibleElements);
|
|
1743
1880
|
const resizeObserver = useResizeObserver();
|
|
@@ -1766,11 +1903,11 @@ const NodeRenderer = (props) => {
|
|
|
1766
1903
|
// moved into `NodeComponentWrapper`. This ensures they are
|
|
1767
1904
|
// memorized – so if `NodeRenderer` *has* to rerender, it only
|
|
1768
1905
|
// needs to regenerate the list of nodes, nothing else.
|
|
1769
|
-
jsx(NodeWrapper
|
|
1906
|
+
jsx(NodeWrapper, { id: nodeId, nodeTypes: props.nodeTypes, nodeExtent: props.nodeExtent, nodeOrigin: props.nodeOrigin, onClick: props.onNodeClick, onMouseEnter: props.onNodeMouseEnter, onMouseMove: props.onNodeMouseMove, onMouseLeave: props.onNodeMouseLeave, onContextMenu: props.onNodeContextMenu, onDoubleClick: props.onNodeDoubleClick, noDragClassName: props.noDragClassName, noPanClassName: props.noPanClassName, rfId: props.rfId, disableKeyboardA11y: props.disableKeyboardA11y, resizeObserver: resizeObserver, nodesDraggable: nodesDraggable, nodesConnectable: nodesConnectable, nodesFocusable: nodesFocusable, elementsSelectable: elementsSelectable, onError: onError }, nodeId));
|
|
1770
1907
|
}) }));
|
|
1771
|
-
}
|
|
1772
|
-
|
|
1773
|
-
|
|
1908
|
+
}
|
|
1909
|
+
NodeRendererComponent.displayName = 'NodeRenderer';
|
|
1910
|
+
const NodeRenderer = memo(NodeRendererComponent);
|
|
1774
1911
|
|
|
1775
1912
|
/**
|
|
1776
1913
|
* Hook for getting the visible edge ids from the store.
|
|
@@ -1844,18 +1981,21 @@ const Marker = ({ id, type, color, width = 12.5, height = 12.5, markerUnits = 's
|
|
|
1844
1981
|
}
|
|
1845
1982
|
return (jsx("marker", { className: "react-flow__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 }) }));
|
|
1846
1983
|
};
|
|
1847
|
-
const markerSelector = ({ defaultColor, rfId }) => (s) => {
|
|
1848
|
-
const markers = createMarkerIds(s.edges, { id: rfId, defaultColor });
|
|
1849
|
-
return markers;
|
|
1850
|
-
};
|
|
1851
|
-
const markersEqual = (a, b) =>
|
|
1852
|
-
// the id includes all marker options, so we just need to look at that part of the marker
|
|
1853
|
-
!(a.length !== b.length || a.some((m, i) => m.id !== b[i].id));
|
|
1854
1984
|
// when you have multiple flows on a page and you hide the first one, the other ones have no markers anymore
|
|
1855
1985
|
// when they do have markers with the same ids. To prevent this the user can pass a unique id to the react flow wrapper
|
|
1856
1986
|
// that we can then use for creating our unique marker ids
|
|
1857
1987
|
const MarkerDefinitions = ({ defaultColor, rfId }) => {
|
|
1858
|
-
const
|
|
1988
|
+
const edges = useStore((s) => s.edges);
|
|
1989
|
+
const defaultEdgeOptions = useStore((s) => s.defaultEdgeOptions);
|
|
1990
|
+
const markers = useMemo(() => {
|
|
1991
|
+
const markers = createMarkerIds(edges, {
|
|
1992
|
+
id: rfId,
|
|
1993
|
+
defaultColor,
|
|
1994
|
+
defaultMarkerStart: defaultEdgeOptions?.markerStart,
|
|
1995
|
+
defaultMarkerEnd: defaultEdgeOptions?.markerEnd,
|
|
1996
|
+
});
|
|
1997
|
+
return markers;
|
|
1998
|
+
}, [edges, defaultEdgeOptions, rfId, defaultColor]);
|
|
1859
1999
|
if (!markers.length) {
|
|
1860
2000
|
return null;
|
|
1861
2001
|
}
|
|
@@ -1864,31 +2004,32 @@ const MarkerDefinitions = ({ defaultColor, rfId }) => {
|
|
|
1864
2004
|
MarkerDefinitions.displayName = 'MarkerDefinitions';
|
|
1865
2005
|
var MarkerDefinitions$1 = memo(MarkerDefinitions);
|
|
1866
2006
|
|
|
1867
|
-
|
|
2007
|
+
function EdgeTextComponent({ x, y, label, labelStyle = {}, labelShowBg = true, labelBgStyle = {}, labelBgPadding = [2, 4], labelBgBorderRadius = 2, children, className, ...rest }) {
|
|
1868
2008
|
const [edgeTextBbox, setEdgeTextBbox] = useState({ x: 1, y: 0, width: 0, height: 0 });
|
|
1869
2009
|
const edgeTextClasses = cc(['react-flow__edge-textwrapper', className]);
|
|
1870
|
-
const
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
2010
|
+
const edgeTextRef = useRef(null);
|
|
2011
|
+
useEffect(() => {
|
|
2012
|
+
if (edgeTextRef.current) {
|
|
2013
|
+
const textBbox = edgeTextRef.current.getBBox();
|
|
2014
|
+
setEdgeTextBbox({
|
|
2015
|
+
x: textBbox.x,
|
|
2016
|
+
y: textBbox.y,
|
|
2017
|
+
width: textBbox.width,
|
|
2018
|
+
height: textBbox.height,
|
|
2019
|
+
});
|
|
2020
|
+
}
|
|
2021
|
+
}, [label]);
|
|
1881
2022
|
if (typeof label === 'undefined' || !label) {
|
|
1882
2023
|
return null;
|
|
1883
2024
|
}
|
|
1884
|
-
return (jsxs("g", { transform: `translate(${x - edgeTextBbox.width / 2} ${y - edgeTextBbox.height / 2})`, className: edgeTextClasses, visibility: edgeTextBbox.width ? 'visible' : 'hidden', ...rest, children: [labelShowBg && (jsx("rect", { width: edgeTextBbox.width + 2 * labelBgPadding[0], x: -labelBgPadding[0], y: -labelBgPadding[1], height: edgeTextBbox.height + 2 * labelBgPadding[1], className: "react-flow__edge-textbg", style: labelBgStyle, rx: labelBgBorderRadius, ry: labelBgBorderRadius })), jsx("text", { className: "react-flow__edge-text", y: edgeTextBbox.height / 2, dy: "0.3em", ref:
|
|
1885
|
-
}
|
|
1886
|
-
|
|
2025
|
+
return (jsxs("g", { transform: `translate(${x - edgeTextBbox.width / 2} ${y - edgeTextBbox.height / 2})`, className: edgeTextClasses, visibility: edgeTextBbox.width ? 'visible' : 'hidden', ...rest, children: [labelShowBg && (jsx("rect", { width: edgeTextBbox.width + 2 * labelBgPadding[0], x: -labelBgPadding[0], y: -labelBgPadding[1], height: edgeTextBbox.height + 2 * labelBgPadding[1], className: "react-flow__edge-textbg", style: labelBgStyle, rx: labelBgBorderRadius, ry: labelBgBorderRadius })), jsx("text", { className: "react-flow__edge-text", y: edgeTextBbox.height / 2, dy: "0.3em", ref: edgeTextRef, style: labelStyle, children: label }), children] }));
|
|
2026
|
+
}
|
|
2027
|
+
EdgeTextComponent.displayName = 'EdgeText';
|
|
2028
|
+
const EdgeText = memo(EdgeTextComponent);
|
|
1887
2029
|
|
|
1888
|
-
|
|
1889
|
-
return (jsxs(Fragment, { children: [jsx("path", { id: id, style: style, d: path, fill: "none", className: cc(['react-flow__edge-path', className]), markerEnd: markerEnd, markerStart: markerStart }), interactionWidth && (jsx("path", { d: path, fill: "none", strokeOpacity: 0, strokeWidth: interactionWidth, className: "react-flow__edge-interaction" })), label && isNumeric(labelX) && isNumeric(labelY) ? (jsx(EdgeText
|
|
1890
|
-
}
|
|
1891
|
-
BaseEdge.displayName = 'BaseEdge';
|
|
2030
|
+
function BaseEdge({ id, path, labelX, labelY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, className, interactionWidth = 20, }) {
|
|
2031
|
+
return (jsxs(Fragment, { children: [jsx("path", { id: id, style: style, d: path, fill: "none", className: cc(['react-flow__edge-path', className]), markerEnd: markerEnd, markerStart: markerStart }), interactionWidth && (jsx("path", { d: path, fill: "none", strokeOpacity: 0, strokeWidth: interactionWidth, className: "react-flow__edge-interaction" })), label && isNumeric(labelX) && isNumeric(labelY) ? (jsx(EdgeText, { x: labelX, y: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius })) : null] }));
|
|
2032
|
+
}
|
|
1892
2033
|
|
|
1893
2034
|
function getControl({ pos, x1, y1, x2, y2 }) {
|
|
1894
2035
|
if (pos === Position.Left || pos === Position.Right) {
|
|
@@ -2048,7 +2189,9 @@ const shiftY = (y, shift, position) => {
|
|
|
2048
2189
|
return y;
|
|
2049
2190
|
};
|
|
2050
2191
|
const EdgeUpdaterClassName = 'react-flow__edgeupdater';
|
|
2051
|
-
|
|
2192
|
+
function EdgeAnchor({ position, centerX, centerY, radius = 10, onMouseDown, onMouseEnter, onMouseOut, type, }) {
|
|
2193
|
+
return (jsx("circle", { onMouseDown: onMouseDown, onMouseEnter: onMouseEnter, onMouseOut: onMouseOut, className: cc([EdgeUpdaterClassName, `${EdgeUpdaterClassName}-${type}`]), cx: shiftX(centerX, radius, position), cy: shiftY(centerY, radius, position), r: radius, stroke: "transparent", fill: "transparent" }));
|
|
2194
|
+
}
|
|
2052
2195
|
|
|
2053
2196
|
function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, targetHandleId, sourceHandleId, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, setUpdating, setUpdateHover, }) {
|
|
2054
2197
|
const store = useStoreApi();
|
|
@@ -2057,7 +2200,7 @@ function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, targetHandleI
|
|
|
2057
2200
|
if (event.button !== 0) {
|
|
2058
2201
|
return;
|
|
2059
2202
|
}
|
|
2060
|
-
const { autoPanOnConnect, domNode, isValidConnection, connectionMode, connectionRadius, lib, onConnectStart, onConnectEnd, cancelConnection,
|
|
2203
|
+
const { autoPanOnConnect, domNode, isValidConnection, connectionMode, connectionRadius, lib, onConnectStart, onConnectEnd, cancelConnection, nodeLookup, rfId: flowId, panBy, updateConnection, } = store.getState();
|
|
2061
2204
|
const nodeId = isSourceHandle ? edge.target : edge.source;
|
|
2062
2205
|
const handleId = (isSourceHandle ? targetHandleId : sourceHandleId) || null;
|
|
2063
2206
|
const handleType = isSourceHandle ? 'target' : 'source';
|
|
@@ -2076,10 +2219,11 @@ function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, targetHandleI
|
|
|
2076
2219
|
domNode,
|
|
2077
2220
|
handleId,
|
|
2078
2221
|
nodeId,
|
|
2079
|
-
|
|
2222
|
+
nodeLookup,
|
|
2080
2223
|
isTarget,
|
|
2081
2224
|
edgeUpdaterType: handleType,
|
|
2082
2225
|
lib,
|
|
2226
|
+
flowId,
|
|
2083
2227
|
cancelConnection,
|
|
2084
2228
|
panBy,
|
|
2085
2229
|
isValidConnection,
|
|
@@ -2089,6 +2233,7 @@ function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, targetHandleI
|
|
|
2089
2233
|
onEdgeUpdateEnd: _onEdgeUpdateEnd,
|
|
2090
2234
|
updateConnection,
|
|
2091
2235
|
getTransform: () => store.getState().transform,
|
|
2236
|
+
getConnectionStartHandle: () => store.getState().connectionStartHandle,
|
|
2092
2237
|
});
|
|
2093
2238
|
};
|
|
2094
2239
|
const onEdgeUpdaterSourceMouseDown = (event) => handleEdgeUpdater(event, true);
|
|
@@ -2098,7 +2243,7 @@ function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, targetHandleI
|
|
|
2098
2243
|
return (jsxs(Fragment, { children: [(isUpdatable === 'source' || isUpdatable === true) && (jsx(EdgeAnchor, { position: sourcePosition, centerX: sourceX, centerY: sourceY, radius: edgeUpdaterRadius, onMouseDown: onEdgeUpdaterSourceMouseDown, onMouseEnter: onEdgeUpdaterMouseEnter, onMouseOut: onEdgeUpdaterMouseOut, type: "source" })), (isUpdatable === 'target' || isUpdatable === true) && (jsx(EdgeAnchor, { position: targetPosition, centerX: targetX, centerY: targetY, radius: edgeUpdaterRadius, onMouseDown: onEdgeUpdaterTargetMouseDown, onMouseEnter: onEdgeUpdaterMouseEnter, onMouseOut: onEdgeUpdaterMouseOut, type: "target" }))] }));
|
|
2099
2244
|
}
|
|
2100
2245
|
|
|
2101
|
-
function EdgeWrapper({ id, edgesFocusable, edgesUpdatable, elementsSelectable, onClick, onDoubleClick, onContextMenu, onMouseEnter, onMouseMove, onMouseLeave, edgeUpdaterRadius, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, rfId, edgeTypes, noPanClassName, onError, }) {
|
|
2246
|
+
function EdgeWrapper({ id, edgesFocusable, edgesUpdatable, elementsSelectable, onClick, onDoubleClick, onContextMenu, onMouseEnter, onMouseMove, onMouseLeave, edgeUpdaterRadius, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, rfId, edgeTypes, noPanClassName, onError, disableKeyboardA11y, }) {
|
|
2102
2247
|
let edge = useStore((s) => s.edgeLookup.get(id));
|
|
2103
2248
|
const defaultEdgeOptions = useStore((s) => s.defaultEdgeOptions);
|
|
2104
2249
|
edge = defaultEdgeOptions ? { ...defaultEdgeOptions, ...edge } : edge;
|
|
@@ -2147,9 +2292,9 @@ function EdgeWrapper({ id, edgesFocusable, edgesUpdatable, elementsSelectable, o
|
|
|
2147
2292
|
...(edgePosition || nullPosition),
|
|
2148
2293
|
};
|
|
2149
2294
|
}, [edge.source, edge.target, edge.sourceHandle, edge.targetHandle, edge.selected, edge.zIndex]), shallow);
|
|
2150
|
-
const markerStartUrl = useMemo(() => (edge.markerStart ? `url(#${getMarkerId(edge.markerStart, rfId)})` : undefined), [edge.markerStart, rfId]);
|
|
2151
|
-
const markerEndUrl = useMemo(() => (edge.markerEnd ? `url(#${getMarkerId(edge.markerEnd, rfId)})` : undefined), [edge.markerEnd, rfId]);
|
|
2152
|
-
if (edge.hidden ||
|
|
2295
|
+
const markerStartUrl = useMemo(() => (edge.markerStart ? `url('#${getMarkerId(edge.markerStart, rfId)}')` : undefined), [edge.markerStart, rfId]);
|
|
2296
|
+
const markerEndUrl = useMemo(() => (edge.markerEnd ? `url('#${getMarkerId(edge.markerEnd, rfId)}')` : undefined), [edge.markerEnd, rfId]);
|
|
2297
|
+
if (edge.hidden || sourceX === null || sourceY === null || targetX === null || targetY === null) {
|
|
2153
2298
|
return null;
|
|
2154
2299
|
}
|
|
2155
2300
|
const onEdgeClick = (event) => {
|
|
@@ -2194,7 +2339,7 @@ function EdgeWrapper({ id, edgesFocusable, edgesUpdatable, elementsSelectable, o
|
|
|
2194
2339
|
}
|
|
2195
2340
|
: undefined;
|
|
2196
2341
|
const onKeyDown = (event) => {
|
|
2197
|
-
if (elementSelectionKeys.includes(event.key) && isSelectable) {
|
|
2342
|
+
if (!disableKeyboardA11y && elementSelectionKeys.includes(event.key) && isSelectable) {
|
|
2198
2343
|
const { unselectNodesAndEdges, addSelectedEdges } = store.getState();
|
|
2199
2344
|
const unselect = event.key === 'Escape';
|
|
2200
2345
|
if (unselect) {
|
|
@@ -2216,11 +2361,10 @@ function EdgeWrapper({ id, edgesFocusable, edgesUpdatable, elementsSelectable, o
|
|
|
2216
2361
|
animated: edge.animated,
|
|
2217
2362
|
inactive: !isSelectable && !onClick,
|
|
2218
2363
|
updating: updateHover,
|
|
2364
|
+
selectable: isSelectable,
|
|
2219
2365
|
},
|
|
2220
|
-
]), onClick: onEdgeClick, onDoubleClick: onEdgeDoubleClick, onContextMenu: onEdgeContextMenu, onMouseEnter: onEdgeMouseEnter, onMouseMove: onEdgeMouseMove, onMouseLeave: onEdgeMouseLeave, onKeyDown: isFocusable ? onKeyDown : undefined, tabIndex: isFocusable ? 0 : undefined, role: isFocusable ? 'button' : 'img', "data-id": id, "data-testid": `rf__edge-${id}`, "aria-label": edge.ariaLabel === null ? undefined : edge.ariaLabel || `Edge from ${edge.source} to ${edge.target}`, "aria-describedby": isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : undefined, ref: edgeRef, children: [!updating && (jsx(EdgeComponent, { id: id, source: edge.source, target: edge.target, selected: edge.selected, animated: edge.animated, label: edge.label, labelStyle: edge.labelStyle, labelShowBg: edge.labelShowBg, labelBgStyle: edge.labelBgStyle, labelBgPadding: edge.labelBgPadding, labelBgBorderRadius: edge.labelBgBorderRadius, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, data: edge.data, style: edge.style, sourceHandleId: edge.sourceHandle, targetHandleId: edge.targetHandle, markerStart: markerStartUrl, markerEnd: markerEndUrl, pathOptions: 'pathOptions' in edge ? edge.pathOptions : undefined, interactionWidth: edge.interactionWidth })), isUpdatable && (jsx(EdgeUpdateAnchors, { edge: edge, isUpdatable: isUpdatable, edgeUpdaterRadius: edgeUpdaterRadius, onEdgeUpdate: onEdgeUpdate, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, setUpdateHover: setUpdateHover, setUpdating: setUpdating, sourceHandleId: edge.sourceHandle, targetHandleId: edge.targetHandle }))] }) }));
|
|
2366
|
+
]), onClick: onEdgeClick, onDoubleClick: onEdgeDoubleClick, onContextMenu: onEdgeContextMenu, onMouseEnter: onEdgeMouseEnter, onMouseMove: onEdgeMouseMove, onMouseLeave: onEdgeMouseLeave, onKeyDown: isFocusable ? onKeyDown : undefined, tabIndex: isFocusable ? 0 : undefined, role: isFocusable ? 'button' : 'img', "data-id": id, "data-testid": `rf__edge-${id}`, "aria-label": edge.ariaLabel === null ? undefined : edge.ariaLabel || `Edge from ${edge.source} to ${edge.target}`, "aria-describedby": isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : undefined, ref: edgeRef, children: [!updating && (jsx(EdgeComponent, { id: id, source: edge.source, target: edge.target, type: edge.type, selected: edge.selected, animated: edge.animated, selectable: isSelectable, deletable: edge.deletable ?? true, label: edge.label, labelStyle: edge.labelStyle, labelShowBg: edge.labelShowBg, labelBgStyle: edge.labelBgStyle, labelBgPadding: edge.labelBgPadding, labelBgBorderRadius: edge.labelBgBorderRadius, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, data: edge.data, style: edge.style, sourceHandleId: edge.sourceHandle, targetHandleId: edge.targetHandle, markerStart: markerStartUrl, markerEnd: markerEndUrl, pathOptions: 'pathOptions' in edge ? edge.pathOptions : undefined, interactionWidth: edge.interactionWidth })), isUpdatable && (jsx(EdgeUpdateAnchors, { edge: edge, isUpdatable: isUpdatable, edgeUpdaterRadius: edgeUpdaterRadius, onEdgeUpdate: onEdgeUpdate, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, setUpdateHover: setUpdateHover, setUpdating: setUpdating, sourceHandleId: edge.sourceHandle, targetHandleId: edge.targetHandle }))] }) }));
|
|
2221
2367
|
}
|
|
2222
|
-
EdgeWrapper.displayName = 'EdgeWrapper';
|
|
2223
|
-
var EdgeWrapper$1 = memo(EdgeWrapper);
|
|
2224
2368
|
|
|
2225
2369
|
const selector$c = (s) => ({
|
|
2226
2370
|
width: s.width,
|
|
@@ -2231,15 +2375,15 @@ const selector$c = (s) => ({
|
|
|
2231
2375
|
connectionMode: s.connectionMode,
|
|
2232
2376
|
onError: s.onError,
|
|
2233
2377
|
});
|
|
2234
|
-
|
|
2378
|
+
function EdgeRendererComponent({ defaultMarkerColor, onlyRenderVisibleElements, rfId, edgeTypes, noPanClassName, onEdgeUpdate, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeClick, edgeUpdaterRadius, onEdgeDoubleClick, onEdgeUpdateStart, onEdgeUpdateEnd, disableKeyboardA11y, }) {
|
|
2235
2379
|
const { edgesFocusable, edgesUpdatable, elementsSelectable, onError } = useStore(selector$c, shallow);
|
|
2236
2380
|
const edgeIds = useVisibleEdgeIds(onlyRenderVisibleElements);
|
|
2237
2381
|
return (jsxs("div", { className: "react-flow__edges", children: [jsx(MarkerDefinitions$1, { defaultColor: defaultMarkerColor, rfId: rfId }), edgeIds.map((id) => {
|
|
2238
|
-
return (jsx(EdgeWrapper
|
|
2239
|
-
})
|
|
2240
|
-
}
|
|
2241
|
-
|
|
2242
|
-
|
|
2382
|
+
return (jsx(EdgeWrapper, { id: id, edgesFocusable: edgesFocusable, edgesUpdatable: edgesUpdatable, elementsSelectable: elementsSelectable, noPanClassName: noPanClassName, onEdgeUpdate: onEdgeUpdate, onContextMenu: onEdgeContextMenu, onMouseEnter: onEdgeMouseEnter, onMouseMove: onEdgeMouseMove, onMouseLeave: onEdgeMouseLeave, onClick: onEdgeClick, edgeUpdaterRadius: edgeUpdaterRadius, onDoubleClick: onEdgeDoubleClick, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd, rfId: rfId, onError: onError, edgeTypes: edgeTypes, disableKeyboardA11y: disableKeyboardA11y }, id));
|
|
2383
|
+
})] }));
|
|
2384
|
+
}
|
|
2385
|
+
EdgeRendererComponent.displayName = 'EdgeRenderer';
|
|
2386
|
+
const EdgeRenderer = memo(EdgeRendererComponent);
|
|
2243
2387
|
|
|
2244
2388
|
const selector$b = (s) => `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`;
|
|
2245
2389
|
function Viewport({ children }) {
|
|
@@ -2296,7 +2440,7 @@ const ConnectionLine = ({ nodeId, handleType, style, type = ConnectionLineType.B
|
|
|
2296
2440
|
toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2],
|
|
2297
2441
|
connectionMode: s.connectionMode,
|
|
2298
2442
|
}), [nodeId]), shallow);
|
|
2299
|
-
const fromHandleBounds = fromNode?.
|
|
2443
|
+
const fromHandleBounds = fromNode?.internals.handleBounds;
|
|
2300
2444
|
let handleBounds = fromHandleBounds?.[handleType];
|
|
2301
2445
|
if (connectionMode === ConnectionMode.Loose) {
|
|
2302
2446
|
handleBounds = handleBounds ? handleBounds : fromHandleBounds?.[handleType === 'source' ? 'target' : 'source'];
|
|
@@ -2305,10 +2449,10 @@ const ConnectionLine = ({ nodeId, handleType, style, type = ConnectionLineType.B
|
|
|
2305
2449
|
return null;
|
|
2306
2450
|
}
|
|
2307
2451
|
const fromHandle = handleId ? handleBounds.find((d) => d.id === handleId) : handleBounds[0];
|
|
2308
|
-
const fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.
|
|
2309
|
-
const fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.
|
|
2310
|
-
const fromX =
|
|
2311
|
-
const fromY =
|
|
2452
|
+
const fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.measured.width ?? 0) / 2;
|
|
2453
|
+
const fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.measured.height ?? 0;
|
|
2454
|
+
const fromX = fromNode.internals.positionAbsolute.x + fromHandleX;
|
|
2455
|
+
const fromY = fromNode.internals.positionAbsolute.y + fromHandleY;
|
|
2312
2456
|
const fromPosition = fromHandle?.position;
|
|
2313
2457
|
const toPosition = fromPosition ? oppositePosition[fromPosition] : null;
|
|
2314
2458
|
if (!fromPosition || !toPosition) {
|
|
@@ -2368,66 +2512,68 @@ function ConnectionLineWrapper({ containerStyle, style, type, component }) {
|
|
|
2368
2512
|
const emptyTypes = {};
|
|
2369
2513
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2370
2514
|
function useNodeOrEdgeTypesWarning(nodeOrEdgeTypes = emptyTypes) {
|
|
2371
|
-
const
|
|
2515
|
+
const typesRef = useRef(nodeOrEdgeTypes);
|
|
2372
2516
|
const store = useStoreApi();
|
|
2373
2517
|
useEffect(() => {
|
|
2374
2518
|
if (process.env.NODE_ENV === 'development') {
|
|
2375
|
-
|
|
2376
|
-
|
|
2519
|
+
const usedKeys = new Set([...Object.keys(typesRef.current), ...Object.keys(nodeOrEdgeTypes)]);
|
|
2520
|
+
for (const key of usedKeys) {
|
|
2521
|
+
if (typesRef.current[key] !== nodeOrEdgeTypes[key]) {
|
|
2522
|
+
store.getState().onError?.('002', errorMessages['error002']());
|
|
2523
|
+
break;
|
|
2524
|
+
}
|
|
2377
2525
|
}
|
|
2378
|
-
|
|
2526
|
+
typesRef.current = nodeOrEdgeTypes;
|
|
2379
2527
|
}
|
|
2380
2528
|
}, [nodeOrEdgeTypes]);
|
|
2381
2529
|
}
|
|
2382
2530
|
|
|
2383
|
-
|
|
2531
|
+
function useStylesLoadedWarning() {
|
|
2532
|
+
const store = useStoreApi();
|
|
2533
|
+
const checked = useRef(false);
|
|
2534
|
+
useEffect(() => {
|
|
2535
|
+
if (process.env.NODE_ENV === 'development') {
|
|
2536
|
+
if (!checked.current) {
|
|
2537
|
+
const pane = document.querySelector('.react-flow__pane');
|
|
2538
|
+
if (pane && !(window.getComputedStyle(pane).zIndex === '1')) {
|
|
2539
|
+
store.getState().onError?.('013', errorMessages['error013']('react'));
|
|
2540
|
+
}
|
|
2541
|
+
checked.current = true;
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
}, []);
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
function GraphViewComponent({ nodeTypes, edgeTypes, onInit, onNodeClick, onEdgeClick, onNodeDoubleClick, onEdgeDoubleClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onSelectionContextMenu, onSelectionStart, onSelectionEnd, connectionLineType, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, selectionKeyCode, selectionOnDrag, selectionMode, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, deleteKeyCode, onlyRenderVisibleElements, elementsSelectable, defaultViewport, translateExtent, minZoom, maxZoom, preventScrolling, defaultMarkerColor, zoomOnScroll, zoomOnPinch, panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, onEdgeUpdate, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, edgeUpdaterRadius, onEdgeUpdateStart, onEdgeUpdateEnd, noDragClassName, noWheelClassName, noPanClassName, disableKeyboardA11y, nodeOrigin, nodeExtent, rfId, viewport, onViewportChange, }) {
|
|
2384
2548
|
useNodeOrEdgeTypesWarning(nodeTypes);
|
|
2385
2549
|
useNodeOrEdgeTypesWarning(edgeTypes);
|
|
2550
|
+
useStylesLoadedWarning();
|
|
2386
2551
|
useOnInitHandler(onInit);
|
|
2387
2552
|
useViewportSync(viewport);
|
|
2388
|
-
return (jsx(FlowRenderer
|
|
2389
|
-
};
|
|
2390
|
-
GraphView.displayName = 'GraphView';
|
|
2391
|
-
var GraphView$1 = memo(GraphView);
|
|
2392
|
-
|
|
2393
|
-
function handleControlledSelectionChange(changes, items) {
|
|
2394
|
-
return items.map((item) => {
|
|
2395
|
-
const change = changes.find((change) => change.id === item.id);
|
|
2396
|
-
if (change) {
|
|
2397
|
-
item.selected = change.selected;
|
|
2398
|
-
}
|
|
2399
|
-
return item;
|
|
2400
|
-
});
|
|
2401
|
-
}
|
|
2402
|
-
function updateNodesAndEdgesSelections({ changedNodes, changedEdges, get, set }) {
|
|
2403
|
-
const { nodes, edges, onNodesChange, onEdgesChange, hasDefaultNodes, hasDefaultEdges } = get();
|
|
2404
|
-
if (changedNodes?.length) {
|
|
2405
|
-
if (hasDefaultNodes) {
|
|
2406
|
-
set({ nodes: handleControlledSelectionChange(changedNodes, nodes) });
|
|
2407
|
-
}
|
|
2408
|
-
onNodesChange?.(changedNodes);
|
|
2409
|
-
}
|
|
2410
|
-
if (changedEdges?.length) {
|
|
2411
|
-
if (hasDefaultEdges) {
|
|
2412
|
-
set({ edges: handleControlledSelectionChange(changedEdges, edges) });
|
|
2413
|
-
}
|
|
2414
|
-
onEdgesChange?.(changedEdges);
|
|
2415
|
-
}
|
|
2553
|
+
return (jsx(FlowRenderer, { onPaneClick: onPaneClick, onPaneMouseEnter: onPaneMouseEnter, onPaneMouseMove: onPaneMouseMove, onPaneMouseLeave: onPaneMouseLeave, onPaneContextMenu: onPaneContextMenu, onPaneScroll: onPaneScroll, deleteKeyCode: deleteKeyCode, selectionKeyCode: selectionKeyCode, selectionOnDrag: selectionOnDrag, selectionMode: selectionMode, onSelectionStart: onSelectionStart, onSelectionEnd: onSelectionEnd, multiSelectionKeyCode: multiSelectionKeyCode, panActivationKeyCode: panActivationKeyCode, zoomActivationKeyCode: zoomActivationKeyCode, elementsSelectable: elementsSelectable, zoomOnScroll: zoomOnScroll, zoomOnPinch: zoomOnPinch, zoomOnDoubleClick: zoomOnDoubleClick, panOnScroll: panOnScroll, panOnScrollSpeed: panOnScrollSpeed, panOnScrollMode: panOnScrollMode, panOnDrag: panOnDrag, defaultViewport: defaultViewport, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, onSelectionContextMenu: onSelectionContextMenu, preventScrolling: preventScrolling, noDragClassName: noDragClassName, noWheelClassName: noWheelClassName, noPanClassName: noPanClassName, disableKeyboardA11y: disableKeyboardA11y, onViewportChange: onViewportChange, isControlledViewport: !!viewport, children: jsxs(Viewport, { children: [jsx(EdgeRenderer, { edgeTypes: edgeTypes, onEdgeClick: onEdgeClick, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeUpdate: onEdgeUpdate, onlyRenderVisibleElements: onlyRenderVisibleElements, onEdgeContextMenu: onEdgeContextMenu, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd, edgeUpdaterRadius: edgeUpdaterRadius, defaultMarkerColor: defaultMarkerColor, noPanClassName: noPanClassName, disableKeyboardA11y: disableKeyboardA11y, rfId: rfId }), jsx(ConnectionLineWrapper, { style: connectionLineStyle, type: connectionLineType, component: connectionLineComponent, containerStyle: connectionLineContainerStyle }), jsx("div", { className: "react-flow__edgelabel-renderer" }), jsx(NodeRenderer, { nodeTypes: nodeTypes, onNodeClick: onNodeClick, onNodeDoubleClick: onNodeDoubleClick, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave, onNodeContextMenu: onNodeContextMenu, onlyRenderVisibleElements: onlyRenderVisibleElements, noPanClassName: noPanClassName, noDragClassName: noDragClassName, disableKeyboardA11y: disableKeyboardA11y, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent, rfId: rfId }), jsx("div", { className: "react-flow__viewport-portal" })] }) }));
|
|
2416
2554
|
}
|
|
2555
|
+
GraphViewComponent.displayName = 'GraphView';
|
|
2556
|
+
const GraphView = memo(GraphViewComponent);
|
|
2417
2557
|
|
|
2418
|
-
const getInitialState = ({ nodes
|
|
2558
|
+
const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView, } = {}) => {
|
|
2419
2559
|
const nodeLookup = new Map();
|
|
2560
|
+
const parentLookup = new Map();
|
|
2420
2561
|
const connectionLookup = new Map();
|
|
2421
2562
|
const edgeLookup = new Map();
|
|
2422
|
-
|
|
2423
|
-
const
|
|
2563
|
+
const storeEdges = defaultEdges ?? edges ?? [];
|
|
2564
|
+
const storeNodes = defaultNodes ?? nodes ?? [];
|
|
2565
|
+
updateConnectionLookup(connectionLookup, edgeLookup, storeEdges);
|
|
2566
|
+
adoptUserNodes(storeNodes, nodeLookup, parentLookup, {
|
|
2424
2567
|
nodeOrigin: [0, 0],
|
|
2425
2568
|
elevateNodesOnSelect: false,
|
|
2426
2569
|
});
|
|
2427
2570
|
let transform = [0, 0, 1];
|
|
2428
2571
|
if (fitView && width && height) {
|
|
2429
|
-
|
|
2430
|
-
const bounds =
|
|
2572
|
+
// @todo users nodeOrigin should be used here
|
|
2573
|
+
const bounds = getInternalNodesBounds(nodeLookup, {
|
|
2574
|
+
nodeOrigin: [0, 0],
|
|
2575
|
+
filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight)),
|
|
2576
|
+
});
|
|
2431
2577
|
const { x, y, zoom } = getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
|
|
2432
2578
|
transform = [x, y, zoom];
|
|
2433
2579
|
}
|
|
@@ -2436,15 +2582,16 @@ const getInitialState = ({ nodes = [], edges = [], width, height, fitView, } = {
|
|
|
2436
2582
|
width: 0,
|
|
2437
2583
|
height: 0,
|
|
2438
2584
|
transform,
|
|
2439
|
-
nodes:
|
|
2585
|
+
nodes: storeNodes,
|
|
2440
2586
|
nodeLookup,
|
|
2441
|
-
|
|
2587
|
+
parentLookup,
|
|
2588
|
+
edges: storeEdges,
|
|
2442
2589
|
edgeLookup,
|
|
2443
2590
|
connectionLookup,
|
|
2444
2591
|
onNodesChange: null,
|
|
2445
2592
|
onEdgesChange: null,
|
|
2446
|
-
hasDefaultNodes:
|
|
2447
|
-
hasDefaultEdges:
|
|
2593
|
+
hasDefaultNodes: defaultNodes !== undefined,
|
|
2594
|
+
hasDefaultEdges: defaultEdges !== undefined,
|
|
2448
2595
|
panZoom: null,
|
|
2449
2596
|
minZoom: 0.5,
|
|
2450
2597
|
maxZoom: 2,
|
|
@@ -2484,78 +2631,60 @@ const getInitialState = ({ nodes = [], edges = [], width, height, fitView, } = {
|
|
|
2484
2631
|
autoPanOnConnect: true,
|
|
2485
2632
|
autoPanOnNodeDrag: true,
|
|
2486
2633
|
connectionRadius: 20,
|
|
2487
|
-
onError:
|
|
2634
|
+
onError: devWarn,
|
|
2488
2635
|
isValidConnection: undefined,
|
|
2489
2636
|
onSelectionChangeHandlers: [],
|
|
2490
2637
|
lib: 'react',
|
|
2638
|
+
debug: false,
|
|
2491
2639
|
};
|
|
2492
2640
|
};
|
|
2493
2641
|
|
|
2494
|
-
const
|
|
2495
|
-
...getInitialState({ nodes, edges, width, height, fitView: fitView$1 }),
|
|
2642
|
+
const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView: fitView$1, }) => createWithEqualityFn((set, get) => ({
|
|
2643
|
+
...getInitialState({ nodes, edges, width, height, fitView: fitView$1, defaultNodes, defaultEdges }),
|
|
2496
2644
|
setNodes: (nodes) => {
|
|
2497
|
-
const { nodeLookup, nodeOrigin, elevateNodesOnSelect } = get();
|
|
2645
|
+
const { nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect } = get();
|
|
2498
2646
|
// setNodes() is called exclusively in response to user actions:
|
|
2499
2647
|
// - either when the `<ReactFlow nodes>` prop is updated in the controlled ReactFlow setup,
|
|
2500
2648
|
// - or when the user calls something like `reactFlowInstance.setNodes()` in an uncontrolled ReactFlow setup.
|
|
2501
2649
|
//
|
|
2502
2650
|
// When this happens, we take the note objects passed by the user and extend them with fields
|
|
2503
2651
|
// relevant for internal React Flow operations.
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
set({ nodes: nodesWithInternalData });
|
|
2652
|
+
adoptUserNodes(nodes, nodeLookup, parentLookup, { nodeOrigin, elevateNodesOnSelect, checkEquality: true });
|
|
2653
|
+
set({ nodes });
|
|
2507
2654
|
},
|
|
2508
2655
|
setEdges: (edges) => {
|
|
2509
2656
|
const { connectionLookup, edgeLookup } = get();
|
|
2510
2657
|
updateConnectionLookup(connectionLookup, edgeLookup, edges);
|
|
2511
2658
|
set({ edges });
|
|
2512
2659
|
},
|
|
2513
|
-
// when the user works with an uncontrolled flow,
|
|
2514
|
-
// we set a flag `hasDefaultNodes` / `hasDefaultEdges`
|
|
2515
2660
|
setDefaultNodesAndEdges: (nodes, edges) => {
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
hasDefaultNodes
|
|
2520
|
-
hasDefaultEdges,
|
|
2521
|
-
};
|
|
2522
|
-
if (hasDefaultNodes) {
|
|
2523
|
-
const { nodeLookup, nodeOrigin, elevateNodesOnSelect } = get();
|
|
2524
|
-
nextState.nodes = adoptUserProvidedNodes(nodes, nodeLookup, {
|
|
2525
|
-
nodeOrigin,
|
|
2526
|
-
elevateNodesOnSelect,
|
|
2527
|
-
});
|
|
2661
|
+
if (nodes) {
|
|
2662
|
+
const { setNodes } = get();
|
|
2663
|
+
setNodes(nodes);
|
|
2664
|
+
set({ hasDefaultNodes: true });
|
|
2528
2665
|
}
|
|
2529
|
-
if (
|
|
2530
|
-
const {
|
|
2531
|
-
|
|
2532
|
-
|
|
2666
|
+
if (edges) {
|
|
2667
|
+
const { setEdges } = get();
|
|
2668
|
+
setEdges(edges);
|
|
2669
|
+
set({ hasDefaultEdges: true });
|
|
2533
2670
|
}
|
|
2534
|
-
set(nextState);
|
|
2535
2671
|
},
|
|
2536
2672
|
// Every node gets registerd at a ResizeObserver. Whenever a node
|
|
2537
2673
|
// changes its dimensions, this function is called to measure the
|
|
2538
2674
|
// new dimensions and update the nodes.
|
|
2539
|
-
|
|
2540
|
-
const {
|
|
2541
|
-
const changes =
|
|
2542
|
-
|
|
2543
|
-
changes.push({
|
|
2544
|
-
id: id,
|
|
2545
|
-
type: 'dimensions',
|
|
2546
|
-
dimensions,
|
|
2547
|
-
});
|
|
2548
|
-
});
|
|
2549
|
-
if (!updatedNodes) {
|
|
2675
|
+
updateNodeInternals: (updates) => {
|
|
2676
|
+
const { triggerNodeChanges, fitView, nodeLookup, parentLookup, fitViewOnInit, fitViewDone, fitViewOnInitOptions, domNode, nodeOrigin, debug, } = get();
|
|
2677
|
+
const { changes, updatedInternals } = updateNodeInternals(updates, nodeLookup, parentLookup, domNode, nodeOrigin);
|
|
2678
|
+
if (!updatedInternals) {
|
|
2550
2679
|
return;
|
|
2551
2680
|
}
|
|
2552
|
-
|
|
2681
|
+
updateAbsolutePositions(nodeLookup, { nodeOrigin });
|
|
2553
2682
|
// we call fitView once initially after all dimensions are set
|
|
2554
2683
|
let nextFitViewDone = fitViewDone;
|
|
2555
2684
|
if (!fitViewDone && fitViewOnInit) {
|
|
2556
|
-
nextFitViewDone = fitView(
|
|
2685
|
+
nextFitViewDone = fitView({
|
|
2557
2686
|
...fitViewOnInitOptions,
|
|
2558
|
-
nodes: fitViewOnInitOptions?.nodes
|
|
2687
|
+
nodes: fitViewOnInitOptions?.nodes,
|
|
2559
2688
|
});
|
|
2560
2689
|
}
|
|
2561
2690
|
// here we are cirmumventing the onNodesChange handler
|
|
@@ -2563,91 +2692,104 @@ const createRFStore = ({ nodes, edges, width, height, fitView: fitView$1, }) =>
|
|
|
2563
2692
|
// has not provided an onNodesChange handler.
|
|
2564
2693
|
// Nodes are only rendered if they have a width and height
|
|
2565
2694
|
// attribute which they get from this handler.
|
|
2566
|
-
set({
|
|
2695
|
+
set({ fitViewDone: nextFitViewDone });
|
|
2567
2696
|
if (changes?.length > 0) {
|
|
2568
|
-
|
|
2697
|
+
if (debug) {
|
|
2698
|
+
console.log('React Flow: trigger node changes', changes);
|
|
2699
|
+
}
|
|
2700
|
+
triggerNodeChanges?.(changes);
|
|
2569
2701
|
}
|
|
2570
2702
|
},
|
|
2571
|
-
updateNodePositions: (nodeDragItems,
|
|
2572
|
-
const
|
|
2703
|
+
updateNodePositions: (nodeDragItems, dragging = false) => {
|
|
2704
|
+
const parentExpandChildren = [];
|
|
2705
|
+
const changes = [];
|
|
2706
|
+
for (const [id, dragItem] of nodeDragItems) {
|
|
2707
|
+
// @todo add expandParent to drag item so that we can get rid of the look up here
|
|
2573
2708
|
const change = {
|
|
2574
|
-
id
|
|
2709
|
+
id,
|
|
2575
2710
|
type: 'position',
|
|
2711
|
+
position: dragItem.position,
|
|
2576
2712
|
dragging,
|
|
2577
2713
|
};
|
|
2578
|
-
if (
|
|
2579
|
-
|
|
2580
|
-
|
|
2714
|
+
if (dragItem?.expandParent && dragItem?.parentId && change.position) {
|
|
2715
|
+
parentExpandChildren.push({
|
|
2716
|
+
id,
|
|
2717
|
+
parentId: dragItem.parentId,
|
|
2718
|
+
rect: {
|
|
2719
|
+
...dragItem.internals.positionAbsolute,
|
|
2720
|
+
width: dragItem.measured.width,
|
|
2721
|
+
height: dragItem.measured.height,
|
|
2722
|
+
},
|
|
2723
|
+
});
|
|
2724
|
+
change.position.x = Math.max(0, change.position.x);
|
|
2725
|
+
change.position.y = Math.max(0, change.position.y);
|
|
2581
2726
|
}
|
|
2582
|
-
|
|
2583
|
-
}
|
|
2727
|
+
changes.push(change);
|
|
2728
|
+
}
|
|
2729
|
+
if (parentExpandChildren.length > 0) {
|
|
2730
|
+
const { nodeLookup, parentLookup } = get();
|
|
2731
|
+
const parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup);
|
|
2732
|
+
changes.push(...parentExpandChanges);
|
|
2733
|
+
}
|
|
2584
2734
|
get().triggerNodeChanges(changes);
|
|
2585
2735
|
},
|
|
2586
2736
|
triggerNodeChanges: (changes) => {
|
|
2587
|
-
const { onNodesChange,
|
|
2737
|
+
const { onNodesChange, setNodes, nodes, hasDefaultNodes, debug } = get();
|
|
2588
2738
|
if (changes?.length) {
|
|
2589
2739
|
if (hasDefaultNodes) {
|
|
2590
2740
|
const updatedNodes = applyNodeChanges(changes, nodes);
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
set({ nodes: nextNodes });
|
|
2741
|
+
setNodes(updatedNodes);
|
|
2742
|
+
}
|
|
2743
|
+
if (debug) {
|
|
2744
|
+
console.log('React Flow: trigger node changes', changes);
|
|
2596
2745
|
}
|
|
2597
2746
|
onNodesChange?.(changes);
|
|
2598
2747
|
}
|
|
2599
2748
|
},
|
|
2749
|
+
triggerEdgeChanges: (changes) => {
|
|
2750
|
+
const { onEdgesChange, setEdges, edges, hasDefaultEdges, debug } = get();
|
|
2751
|
+
if (changes?.length) {
|
|
2752
|
+
if (hasDefaultEdges) {
|
|
2753
|
+
const updatedEdges = applyEdgeChanges(changes, edges);
|
|
2754
|
+
setEdges(updatedEdges);
|
|
2755
|
+
}
|
|
2756
|
+
if (debug) {
|
|
2757
|
+
console.log('React Flow: trigger edge changes', changes);
|
|
2758
|
+
}
|
|
2759
|
+
onEdgesChange?.(changes);
|
|
2760
|
+
}
|
|
2761
|
+
},
|
|
2600
2762
|
addSelectedNodes: (selectedNodeIds) => {
|
|
2601
|
-
const { multiSelectionActive,
|
|
2602
|
-
let changedNodes;
|
|
2603
|
-
let changedEdges = null;
|
|
2763
|
+
const { multiSelectionActive, edgeLookup, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get();
|
|
2604
2764
|
if (multiSelectionActive) {
|
|
2605
|
-
|
|
2765
|
+
const nodeChanges = selectedNodeIds.map((nodeId) => createSelectionChange(nodeId, true));
|
|
2766
|
+
triggerNodeChanges(nodeChanges);
|
|
2767
|
+
return;
|
|
2606
2768
|
}
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
changedEdges = getSelectionChanges(edges);
|
|
2610
|
-
}
|
|
2611
|
-
updateNodesAndEdgesSelections({
|
|
2612
|
-
changedNodes,
|
|
2613
|
-
changedEdges,
|
|
2614
|
-
get,
|
|
2615
|
-
set,
|
|
2616
|
-
});
|
|
2769
|
+
triggerNodeChanges(getSelectionChanges(nodeLookup, new Set([...selectedNodeIds]), true));
|
|
2770
|
+
triggerEdgeChanges(getSelectionChanges(edgeLookup));
|
|
2617
2771
|
},
|
|
2618
2772
|
addSelectedEdges: (selectedEdgeIds) => {
|
|
2619
|
-
const { multiSelectionActive,
|
|
2620
|
-
let changedEdges;
|
|
2621
|
-
let changedNodes = null;
|
|
2773
|
+
const { multiSelectionActive, edgeLookup, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get();
|
|
2622
2774
|
if (multiSelectionActive) {
|
|
2623
|
-
changedEdges = selectedEdgeIds.map((edgeId) => createSelectionChange(edgeId, true));
|
|
2775
|
+
const changedEdges = selectedEdgeIds.map((edgeId) => createSelectionChange(edgeId, true));
|
|
2776
|
+
triggerEdgeChanges(changedEdges);
|
|
2777
|
+
return;
|
|
2624
2778
|
}
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
changedNodes = getSelectionChanges(nodes, new Set(), true);
|
|
2628
|
-
}
|
|
2629
|
-
updateNodesAndEdgesSelections({
|
|
2630
|
-
changedNodes,
|
|
2631
|
-
changedEdges,
|
|
2632
|
-
get,
|
|
2633
|
-
set,
|
|
2634
|
-
});
|
|
2779
|
+
triggerEdgeChanges(getSelectionChanges(edgeLookup, new Set([...selectedEdgeIds])));
|
|
2780
|
+
triggerNodeChanges(getSelectionChanges(nodeLookup, new Set(), true));
|
|
2635
2781
|
},
|
|
2636
2782
|
unselectNodesAndEdges: ({ nodes, edges } = {}) => {
|
|
2637
|
-
const { edges: storeEdges, nodes: storeNodes } = get();
|
|
2783
|
+
const { edges: storeEdges, nodes: storeNodes, triggerNodeChanges, triggerEdgeChanges } = get();
|
|
2638
2784
|
const nodesToUnselect = nodes ? nodes : storeNodes;
|
|
2639
2785
|
const edgesToUnselect = edges ? edges : storeEdges;
|
|
2640
|
-
const
|
|
2786
|
+
const nodeChanges = nodesToUnselect.map((n) => {
|
|
2641
2787
|
n.selected = false;
|
|
2642
2788
|
return createSelectionChange(n.id, false);
|
|
2643
2789
|
});
|
|
2644
|
-
const
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
changedEdges,
|
|
2648
|
-
get,
|
|
2649
|
-
set,
|
|
2650
|
-
});
|
|
2790
|
+
const edgeChanges = edgesToUnselect.map((edge) => createSelectionChange(edge.id, false));
|
|
2791
|
+
triggerNodeChanges(nodeChanges);
|
|
2792
|
+
triggerEdgeChanges(edgeChanges);
|
|
2651
2793
|
},
|
|
2652
2794
|
setMinZoom: (minZoom) => {
|
|
2653
2795
|
const { panZoom, maxZoom } = get();
|
|
@@ -2664,47 +2806,39 @@ const createRFStore = ({ nodes, edges, width, height, fitView: fitView$1, }) =>
|
|
|
2664
2806
|
set({ translateExtent });
|
|
2665
2807
|
},
|
|
2666
2808
|
resetSelectedElements: () => {
|
|
2667
|
-
const { edges, nodes } = get();
|
|
2668
|
-
const
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
.filter((e) => e.selected)
|
|
2673
|
-
.map((e) => createSelectionChange(e.id, false));
|
|
2674
|
-
updateNodesAndEdgesSelections({
|
|
2675
|
-
changedNodes: nodesToUnselect,
|
|
2676
|
-
changedEdges: edgesToUnselect,
|
|
2677
|
-
get,
|
|
2678
|
-
set,
|
|
2679
|
-
});
|
|
2809
|
+
const { edges, nodes, triggerNodeChanges, triggerEdgeChanges } = get();
|
|
2810
|
+
const nodeChanges = nodes.reduce((res, node) => (node.selected ? [...res, createSelectionChange(node.id, false)] : res), []);
|
|
2811
|
+
const edgeChanges = edges.reduce((res, edge) => (edge.selected ? [...res, createSelectionChange(edge.id, false)] : res), []);
|
|
2812
|
+
triggerNodeChanges(nodeChanges);
|
|
2813
|
+
triggerEdgeChanges(edgeChanges);
|
|
2680
2814
|
},
|
|
2681
2815
|
setNodeExtent: (nodeExtent) => {
|
|
2682
|
-
const {
|
|
2816
|
+
const { nodeLookup } = get();
|
|
2817
|
+
for (const [, node] of nodeLookup) {
|
|
2818
|
+
const positionAbsolute = clampPosition(node.position, nodeExtent);
|
|
2819
|
+
nodeLookup.set(node.id, {
|
|
2820
|
+
...node,
|
|
2821
|
+
internals: {
|
|
2822
|
+
...node.internals,
|
|
2823
|
+
positionAbsolute,
|
|
2824
|
+
},
|
|
2825
|
+
});
|
|
2826
|
+
}
|
|
2683
2827
|
set({
|
|
2684
2828
|
nodeExtent,
|
|
2685
|
-
nodes: nodes.map((node) => {
|
|
2686
|
-
const positionAbsolute = clampPosition(node.position, nodeExtent);
|
|
2687
|
-
return {
|
|
2688
|
-
...node,
|
|
2689
|
-
computed: {
|
|
2690
|
-
...node.computed,
|
|
2691
|
-
positionAbsolute,
|
|
2692
|
-
},
|
|
2693
|
-
};
|
|
2694
|
-
}),
|
|
2695
2829
|
});
|
|
2696
2830
|
},
|
|
2697
2831
|
panBy: (delta) => {
|
|
2698
2832
|
const { transform, width, height, panZoom, translateExtent } = get();
|
|
2699
2833
|
return panBy({ delta, panZoom, transform, translateExtent, width, height });
|
|
2700
2834
|
},
|
|
2701
|
-
fitView: (
|
|
2702
|
-
const { panZoom, width, height, minZoom, maxZoom, nodeOrigin } = get();
|
|
2835
|
+
fitView: (options) => {
|
|
2836
|
+
const { panZoom, width, height, minZoom, maxZoom, nodeOrigin, nodeLookup } = get();
|
|
2703
2837
|
if (!panZoom) {
|
|
2704
2838
|
return false;
|
|
2705
2839
|
}
|
|
2706
2840
|
return fitView({
|
|
2707
|
-
|
|
2841
|
+
nodeLookup,
|
|
2708
2842
|
width,
|
|
2709
2843
|
height,
|
|
2710
2844
|
panZoom,
|
|
@@ -2719,82 +2853,39 @@ const createRFStore = ({ nodes, edges, width, height, fitView: fitView$1, }) =>
|
|
|
2719
2853
|
connectionEndHandle: null,
|
|
2720
2854
|
}),
|
|
2721
2855
|
updateConnection: (params) => {
|
|
2722
|
-
const {
|
|
2856
|
+
const { connectionPosition } = get();
|
|
2723
2857
|
const currentConnection = {
|
|
2858
|
+
...params,
|
|
2724
2859
|
connectionPosition: params.connectionPosition ?? connectionPosition,
|
|
2725
|
-
connectionStatus: params.connectionStatus ?? connectionStatus,
|
|
2726
|
-
connectionStartHandle: params.connectionStartHandle ?? connectionStartHandle,
|
|
2727
|
-
connectionEndHandle: params.connectionEndHandle ?? connectionEndHandle,
|
|
2728
2860
|
};
|
|
2729
2861
|
set(currentConnection);
|
|
2730
2862
|
},
|
|
2731
|
-
reset: () => {
|
|
2732
|
-
// @todo: what should we do about this? Do we still need it?
|
|
2733
|
-
// if you are on a SPA with multiple flows, we want to make sure that the store gets resetted
|
|
2734
|
-
// when you switch pages. Does this reset solves this? Currently it always gets called. This
|
|
2735
|
-
// leads to an emtpy nodes array at the beginning.
|
|
2736
|
-
// set({ ...getInitialState() });
|
|
2737
|
-
},
|
|
2863
|
+
reset: () => set({ ...getInitialState() }),
|
|
2738
2864
|
}), Object.is);
|
|
2739
2865
|
|
|
2740
|
-
function ReactFlowProvider({
|
|
2741
|
-
const
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
}
|
|
2751
|
-
return jsx(Provider$1, { value: storeRef.current, children: children });
|
|
2866
|
+
function ReactFlowProvider({ initialNodes: nodes, initialEdges: edges, defaultNodes, defaultEdges, initialWidth: width, initialHeight: height, fitView, children, }) {
|
|
2867
|
+
const [store] = useState(() => createStore({
|
|
2868
|
+
nodes,
|
|
2869
|
+
edges,
|
|
2870
|
+
defaultNodes,
|
|
2871
|
+
defaultEdges,
|
|
2872
|
+
width,
|
|
2873
|
+
height,
|
|
2874
|
+
fitView,
|
|
2875
|
+
}));
|
|
2876
|
+
return (jsx(Provider$1, { value: store, children: jsx(BatchProvider, { children: children }) }));
|
|
2752
2877
|
}
|
|
2753
|
-
ReactFlowProvider.displayName = 'ReactFlowProvider';
|
|
2754
2878
|
|
|
2755
|
-
function Wrapper({ children, nodes, edges, width, height, fitView, }) {
|
|
2879
|
+
function Wrapper({ children, nodes, edges, defaultNodes, defaultEdges, width, height, fitView, }) {
|
|
2756
2880
|
const isWrapped = useContext(StoreContext);
|
|
2757
2881
|
if (isWrapped) {
|
|
2758
2882
|
// we need to wrap it with a fragment because it's not allowed for children to be a ReactNode
|
|
2759
2883
|
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051
|
|
2760
2884
|
return jsx(Fragment, { children: children });
|
|
2761
2885
|
}
|
|
2762
|
-
return (jsx(ReactFlowProvider, { initialNodes: nodes, initialEdges: edges, initialWidth: width, initialHeight: height, fitView: fitView, children: children }));
|
|
2763
|
-
}
|
|
2764
|
-
Wrapper.displayName = 'ReactFlowWrapper';
|
|
2765
|
-
|
|
2766
|
-
function getMediaQuery() {
|
|
2767
|
-
if (typeof window === 'undefined' || !window.matchMedia) {
|
|
2768
|
-
return null;
|
|
2769
|
-
}
|
|
2770
|
-
return window.matchMedia('(prefers-color-scheme: dark)');
|
|
2771
|
-
}
|
|
2772
|
-
/**
|
|
2773
|
-
* Hook for receiving the current color mode class 'dark' or 'light'.
|
|
2774
|
-
*
|
|
2775
|
-
* @internal
|
|
2776
|
-
* @param colorMode - The color mode to use ('dark', 'light' or 'system')
|
|
2777
|
-
*/
|
|
2778
|
-
function useColorModeClass(colorMode) {
|
|
2779
|
-
const [colorModeClass, setColorModeClass] = useState(colorMode === 'system' ? null : colorMode);
|
|
2780
|
-
useEffect(() => {
|
|
2781
|
-
if (colorMode !== 'system') {
|
|
2782
|
-
setColorModeClass(colorMode);
|
|
2783
|
-
return;
|
|
2784
|
-
}
|
|
2785
|
-
const mediaQuery = getMediaQuery();
|
|
2786
|
-
const updateColorModeClass = () => setColorModeClass(mediaQuery?.matches ? 'dark' : 'light');
|
|
2787
|
-
updateColorModeClass();
|
|
2788
|
-
mediaQuery?.addEventListener('change', updateColorModeClass);
|
|
2789
|
-
return () => {
|
|
2790
|
-
mediaQuery?.removeEventListener('change', updateColorModeClass);
|
|
2791
|
-
};
|
|
2792
|
-
}, [colorMode]);
|
|
2793
|
-
return colorModeClass !== null ? colorModeClass : getMediaQuery()?.matches ? 'dark' : 'light';
|
|
2886
|
+
return (jsx(ReactFlowProvider, { initialNodes: nodes, initialEdges: edges, defaultNodes: defaultNodes, defaultEdges: defaultEdges, initialWidth: width, initialHeight: height, fitView: fitView, children: children }));
|
|
2794
2887
|
}
|
|
2795
2888
|
|
|
2796
|
-
const initNodeOrigin = [0, 0];
|
|
2797
|
-
const initDefaultViewport = { x: 0, y: 0, zoom: 1 };
|
|
2798
2889
|
const wrapperStyle = {
|
|
2799
2890
|
width: '100%',
|
|
2800
2891
|
height: '100%',
|
|
@@ -2802,12 +2893,12 @@ const wrapperStyle = {
|
|
|
2802
2893
|
position: 'relative',
|
|
2803
2894
|
zIndex: 0,
|
|
2804
2895
|
};
|
|
2805
|
-
|
|
2896
|
+
function ReactFlow({ nodes, edges, defaultNodes, defaultEdges, className, nodeTypes, edgeTypes, onNodeClick, onEdgeClick, onInit, onMove, onMoveStart, onMoveEnd, onConnect, onConnectStart, onConnectEnd, onClickConnectStart, onClickConnectEnd, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onNodeDoubleClick, onNodeDragStart, onNodeDrag, onNodeDragStop, onNodesDelete, onEdgesDelete, onDelete, onSelectionChange, onSelectionDragStart, onSelectionDrag, onSelectionDragStop, onSelectionContextMenu, onSelectionStart, onSelectionEnd, onBeforeDelete, connectionMode, connectionLineType = ConnectionLineType.Bezier, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, deleteKeyCode = 'Backspace', selectionKeyCode = 'Shift', selectionOnDrag = false, selectionMode = SelectionMode.Full, panActivationKeyCode = 'Space', multiSelectionKeyCode = isMacOs() ? 'Meta' : 'Control', zoomActivationKeyCode = isMacOs() ? 'Meta' : 'Control', snapToGrid, snapGrid, onlyRenderVisibleElements = false, selectNodesOnDrag, nodesDraggable, nodesConnectable, nodesFocusable, nodeOrigin = defaultNodeOrigin, edgesFocusable, edgesUpdatable, elementsSelectable = true, defaultViewport: defaultViewport$1 = defaultViewport, minZoom = 0.5, maxZoom = 2, translateExtent = infiniteExtent, preventScrolling = true, nodeExtent, defaultMarkerColor = '#b1b1b7', zoomOnScroll = true, zoomOnPinch = true, panOnScroll = false, panOnScrollSpeed = 0.5, panOnScrollMode = PanOnScrollMode.Free, zoomOnDoubleClick = true, panOnDrag = true, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, children, onEdgeUpdate, onEdgeContextMenu, onEdgeDoubleClick, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdateStart, onEdgeUpdateEnd, edgeUpdaterRadius = 10, onNodesChange, onEdgesChange, noDragClassName = 'nodrag', noWheelClassName = 'nowheel', noPanClassName = 'nopan', fitView, fitViewOptions, connectOnClick, attributionPosition, proOptions, defaultEdgeOptions, elevateNodesOnSelect, elevateEdgesOnSelect, disableKeyboardA11y = false, autoPanOnConnect, autoPanOnNodeDrag, connectionRadius, isValidConnection, onError, style, id, nodeDragThreshold, viewport, onViewportChange, width, height, colorMode = 'light', debug, ...rest }, ref) {
|
|
2806
2897
|
const rfId = id || '1';
|
|
2807
2898
|
const colorModeClassName = useColorModeClass(colorMode);
|
|
2808
|
-
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
|
|
2809
|
-
}
|
|
2810
|
-
|
|
2899
|
+
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 })] }) }));
|
|
2900
|
+
}
|
|
2901
|
+
var index = fixedForwardRef(ReactFlow);
|
|
2811
2902
|
|
|
2812
2903
|
const selector$8 = (s) => s.domNode?.querySelector('.react-flow__edgelabel-renderer');
|
|
2813
2904
|
function EdgeLabelRenderer({ children }) {
|
|
@@ -2836,16 +2927,16 @@ function ViewportPortal({ children }) {
|
|
|
2836
2927
|
function useUpdateNodeInternals() {
|
|
2837
2928
|
const store = useStoreApi();
|
|
2838
2929
|
return useCallback((id) => {
|
|
2839
|
-
const { domNode,
|
|
2930
|
+
const { domNode, updateNodeInternals } = store.getState();
|
|
2840
2931
|
const updateIds = Array.isArray(id) ? id : [id];
|
|
2841
2932
|
const updates = new Map();
|
|
2842
2933
|
updateIds.forEach((updateId) => {
|
|
2843
2934
|
const nodeElement = domNode?.querySelector(`.react-flow__node[data-id="${updateId}"]`);
|
|
2844
2935
|
if (nodeElement) {
|
|
2845
|
-
updates.set(updateId, { id: updateId, nodeElement,
|
|
2936
|
+
updates.set(updateId, { id: updateId, nodeElement, force: true });
|
|
2846
2937
|
}
|
|
2847
2938
|
});
|
|
2848
|
-
requestAnimationFrame(() =>
|
|
2939
|
+
requestAnimationFrame(() => updateNodeInternals(updates));
|
|
2849
2940
|
}, []);
|
|
2850
2941
|
}
|
|
2851
2942
|
|
|
@@ -2939,7 +3030,7 @@ function useOnViewportChange({ onStart, onChange, onEnd }) {
|
|
|
2939
3030
|
* Hook for registering an onSelectionChange handler.
|
|
2940
3031
|
*
|
|
2941
3032
|
* @public
|
|
2942
|
-
* @
|
|
3033
|
+
* @param params.onChange - The handler to register
|
|
2943
3034
|
*/
|
|
2944
3035
|
function useOnSelectionChange({ onChange }) {
|
|
2945
3036
|
const store = useStoreApi();
|
|
@@ -2954,12 +3045,17 @@ function useOnSelectionChange({ onChange }) {
|
|
|
2954
3045
|
}
|
|
2955
3046
|
|
|
2956
3047
|
const selector$6 = (options) => (s) => {
|
|
2957
|
-
if (s.
|
|
3048
|
+
if (s.nodeLookup.size === 0) {
|
|
2958
3049
|
return false;
|
|
2959
3050
|
}
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
3051
|
+
for (const [, { hidden, internals }] of s.nodeLookup) {
|
|
3052
|
+
if (options.includeHiddenNodes || !hidden) {
|
|
3053
|
+
if (internals.handleBounds === undefined || !nodeHasDimensions(internals.userNode)) {
|
|
3054
|
+
return false;
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
return true;
|
|
2963
3059
|
};
|
|
2964
3060
|
const defaultOptions = {
|
|
2965
3061
|
includeHiddenNodes: false,
|
|
@@ -2977,7 +3073,7 @@ function useNodesInitialized(options = defaultOptions) {
|
|
|
2977
3073
|
}
|
|
2978
3074
|
|
|
2979
3075
|
/**
|
|
2980
|
-
*
|
|
3076
|
+
* Hook to check if a <Handle /> is connected to another <Handle /> and get the connections.
|
|
2981
3077
|
*
|
|
2982
3078
|
* @public
|
|
2983
3079
|
* @param param.type - handle type 'source' or 'target'
|
|
@@ -2985,12 +3081,12 @@ function useNodesInitialized(options = defaultOptions) {
|
|
|
2985
3081
|
* @param param.id - the handle id (this is only needed if the node has multiple handles of the same type)
|
|
2986
3082
|
* @param param.onConnect - gets called when a connection is established
|
|
2987
3083
|
* @param param.onDisconnect - gets called when a connection is removed
|
|
2988
|
-
* @returns an array with connections
|
|
3084
|
+
* @returns an array with handle connections
|
|
2989
3085
|
*/
|
|
2990
3086
|
function useHandleConnections({ type, id = null, nodeId, onConnect, onDisconnect, }) {
|
|
2991
3087
|
const _nodeId = useNodeId();
|
|
3088
|
+
const currentNodeId = nodeId ?? _nodeId;
|
|
2992
3089
|
const prevConnections = useRef(null);
|
|
2993
|
-
const currentNodeId = nodeId || _nodeId;
|
|
2994
3090
|
const connections = useStore((state) => state.connectionLookup.get(`${currentNodeId}-${type}-${id}`), areConnectionMapsEqual);
|
|
2995
3091
|
useEffect(() => {
|
|
2996
3092
|
// @todo dicuss if onConnect/onDisconnect should be called when the component mounts/unmounts
|
|
@@ -3007,18 +3103,21 @@ function useHandleConnections({ type, id = null, nodeId, onConnect, onDisconnect
|
|
|
3007
3103
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3008
3104
|
function useNodesData(nodeIds) {
|
|
3009
3105
|
const nodesData = useStore(useCallback((s) => {
|
|
3010
|
-
if (!Array.isArray(nodeIds)) {
|
|
3011
|
-
return s.nodeLookup.get(nodeIds)?.data || null;
|
|
3012
|
-
}
|
|
3013
3106
|
const data = [];
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3107
|
+
const isArrayOfIds = Array.isArray(nodeIds);
|
|
3108
|
+
const _nodeIds = isArrayOfIds ? nodeIds : [nodeIds];
|
|
3109
|
+
for (const nodeId of _nodeIds) {
|
|
3110
|
+
const node = s.nodeLookup.get(nodeId);
|
|
3111
|
+
if (node) {
|
|
3112
|
+
data.push({
|
|
3113
|
+
id: node.id,
|
|
3114
|
+
type: node.type,
|
|
3115
|
+
data: node.data,
|
|
3116
|
+
});
|
|
3018
3117
|
}
|
|
3019
3118
|
}
|
|
3020
|
-
return data;
|
|
3021
|
-
}, [nodeIds]),
|
|
3119
|
+
return isArrayOfIds ? data : data[0] ?? null;
|
|
3120
|
+
}, [nodeIds]), shallowNodeData);
|
|
3022
3121
|
return nodesData;
|
|
3023
3122
|
}
|
|
3024
3123
|
|
|
@@ -3032,19 +3131,24 @@ const selector$5 = (s) => ({
|
|
|
3032
3131
|
* Hook for accessing the ongoing connection.
|
|
3033
3132
|
*
|
|
3034
3133
|
* @public
|
|
3035
|
-
* @returns ongoing connection
|
|
3134
|
+
* @returns ongoing connection
|
|
3036
3135
|
*/
|
|
3037
3136
|
function useConnection() {
|
|
3038
3137
|
const ongoingConnection = useStore(selector$5, shallow);
|
|
3039
3138
|
return ongoingConnection;
|
|
3040
3139
|
}
|
|
3041
3140
|
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3141
|
+
/**
|
|
3142
|
+
* Hook for getting an internal node by id
|
|
3143
|
+
*
|
|
3144
|
+
* @public
|
|
3145
|
+
* @param id - id of the node
|
|
3146
|
+
* @returns array with visible node ids
|
|
3147
|
+
*/
|
|
3148
|
+
function useInternalNode(id) {
|
|
3149
|
+
const node = useStore(useCallback((s) => s.nodeLookup.get(id), [id]), shallow);
|
|
3150
|
+
return node;
|
|
3151
|
+
}
|
|
3048
3152
|
|
|
3049
3153
|
function LinePattern({ dimensions, lineWidth, variant, className }) {
|
|
3050
3154
|
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]) }));
|
|
@@ -3053,13 +3157,20 @@ function DotPattern({ radius, className }) {
|
|
|
3053
3157
|
return (jsx("circle", { cx: radius, cy: radius, r: radius, className: cc(['react-flow__background-pattern', 'dots', className]) }));
|
|
3054
3158
|
}
|
|
3055
3159
|
|
|
3160
|
+
var BackgroundVariant;
|
|
3161
|
+
(function (BackgroundVariant) {
|
|
3162
|
+
BackgroundVariant["Lines"] = "lines";
|
|
3163
|
+
BackgroundVariant["Dots"] = "dots";
|
|
3164
|
+
BackgroundVariant["Cross"] = "cross";
|
|
3165
|
+
})(BackgroundVariant || (BackgroundVariant = {}));
|
|
3166
|
+
|
|
3056
3167
|
const defaultSize = {
|
|
3057
3168
|
[BackgroundVariant.Dots]: 1,
|
|
3058
3169
|
[BackgroundVariant.Lines]: 1,
|
|
3059
3170
|
[BackgroundVariant.Cross]: 6,
|
|
3060
3171
|
};
|
|
3061
3172
|
const selector$4 = (s) => ({ transform: s.transform, patternId: `pattern-${s.rfId}` });
|
|
3062
|
-
function
|
|
3173
|
+
function BackgroundComponent({ id, variant = BackgroundVariant.Dots,
|
|
3063
3174
|
// only used for dots and cross
|
|
3064
3175
|
gap = 20,
|
|
3065
3176
|
// only used for lines and cross
|
|
@@ -3084,8 +3195,8 @@ size, lineWidth = 1, offset = 2, color, bgColor, style, className, patternClassN
|
|
|
3084
3195
|
'--xy-background-pattern-color-props': color,
|
|
3085
3196
|
}, ref: ref, "data-testid": "rf__background", children: [jsx("pattern", { id: _patternId, 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: isDots ? (jsx(DotPattern, { radius: scaledSize / offset, className: patternClassName })) : (jsx(LinePattern, { dimensions: patternDimensions, lineWidth: lineWidth, variant: variant, className: patternClassName })) }), jsx("rect", { x: "0", y: "0", width: "100%", height: "100%", fill: `url(#${_patternId})` })] }));
|
|
3086
3197
|
}
|
|
3087
|
-
|
|
3088
|
-
|
|
3198
|
+
BackgroundComponent.displayName = 'Background';
|
|
3199
|
+
const Background = memo(BackgroundComponent);
|
|
3089
3200
|
|
|
3090
3201
|
function PlusIcon() {
|
|
3091
3202
|
return (jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 32 32", children: jsx("path", { d: "M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z" }) }));
|
|
@@ -3107,15 +3218,16 @@ function UnlockIcon() {
|
|
|
3107
3218
|
return (jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 25 32", children: jsx("path", { d: "M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z" }) }));
|
|
3108
3219
|
}
|
|
3109
3220
|
|
|
3110
|
-
|
|
3111
|
-
|
|
3221
|
+
function ControlButton({ children, className, ...rest }) {
|
|
3222
|
+
return (jsx("button", { type: "button", className: cc(['react-flow__controls-button', className]), ...rest, children: children }));
|
|
3223
|
+
}
|
|
3112
3224
|
|
|
3113
3225
|
const selector$3 = (s) => ({
|
|
3114
3226
|
isInteractive: s.nodesDraggable || s.nodesConnectable || s.elementsSelectable,
|
|
3115
3227
|
minZoomReached: s.transform[2] <= s.minZoom,
|
|
3116
3228
|
maxZoomReached: s.transform[2] >= s.maxZoom,
|
|
3117
3229
|
});
|
|
3118
|
-
|
|
3230
|
+
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', }) {
|
|
3119
3231
|
const store = useStoreApi();
|
|
3120
3232
|
const { isInteractive, minZoomReached, maxZoomReached } = useStore(selector$3, shallow);
|
|
3121
3233
|
const { zoomIn, zoomOut, fitView } = useReactFlow();
|
|
@@ -3139,12 +3251,13 @@ const Controls = ({ style, showZoom = true, showFitView = true, showInteractive
|
|
|
3139
3251
|
});
|
|
3140
3252
|
onInteractiveChange?.(!isInteractive);
|
|
3141
3253
|
};
|
|
3142
|
-
|
|
3143
|
-
};
|
|
3144
|
-
|
|
3145
|
-
|
|
3254
|
+
const orientationClass = orientation === 'horizontal' ? 'horizontal' : 'vertical';
|
|
3255
|
+
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] }));
|
|
3256
|
+
}
|
|
3257
|
+
ControlsComponent.displayName = 'Controls';
|
|
3258
|
+
const Controls = memo(ControlsComponent);
|
|
3146
3259
|
|
|
3147
|
-
function
|
|
3260
|
+
function MiniMapNodeComponent({ id, x, y, width, height, style, color, strokeColor, strokeWidth, className, borderRadius, shapeRendering, selected, onClick, }) {
|
|
3148
3261
|
const { background, backgroundColor } = style || {};
|
|
3149
3262
|
const fill = (color || background || backgroundColor);
|
|
3150
3263
|
return (jsx("rect", { className: cc(['react-flow__minimap-node', { selected }, className]), x: x, y: y, rx: borderRadius, ry: borderRadius, width: width, height: height, style: {
|
|
@@ -3153,15 +3266,15 @@ function MiniMapNode({ id, x, y, width, height, style, color, strokeColor, strok
|
|
|
3153
3266
|
strokeWidth,
|
|
3154
3267
|
}, shapeRendering: shapeRendering, onClick: onClick ? (event) => onClick(event, id) : undefined }));
|
|
3155
3268
|
}
|
|
3156
|
-
|
|
3269
|
+
const MiniMapNode = memo(MiniMapNodeComponent);
|
|
3157
3270
|
|
|
3158
3271
|
const selector$2 = (s) => s.nodeOrigin;
|
|
3159
3272
|
const selectorNodeIds = (s) => s.nodes.map((node) => node.id);
|
|
3160
|
-
const getAttrFunction = (func) =>
|
|
3273
|
+
const getAttrFunction = (func) => func instanceof Function ? func : () => func;
|
|
3161
3274
|
function MiniMapNodes({ nodeStrokeColor, nodeColor, nodeClassName = '', nodeBorderRadius = 5, nodeStrokeWidth,
|
|
3162
3275
|
// We need to rename the prop to be `CapitalCase` so that JSX will render it as
|
|
3163
3276
|
// a component properly.
|
|
3164
|
-
nodeComponent: NodeComponent = MiniMapNode
|
|
3277
|
+
nodeComponent: NodeComponent = MiniMapNode, onClick, }) {
|
|
3165
3278
|
const nodeIds = useStore(selectorNodeIds, shallow);
|
|
3166
3279
|
const nodeOrigin = useStore(selector$2);
|
|
3167
3280
|
const nodeColorFunc = getAttrFunction(nodeColor);
|
|
@@ -3176,21 +3289,23 @@ nodeComponent: NodeComponent = MiniMapNode$1, onClick, }) {
|
|
|
3176
3289
|
// For more details, see a similar commit in `NodeRenderer/index.tsx`.
|
|
3177
3290
|
jsx(NodeComponentWrapper, { id: nodeId, nodeOrigin: nodeOrigin, nodeColorFunc: nodeColorFunc, nodeStrokeColorFunc: nodeStrokeColorFunc, nodeClassNameFunc: nodeClassNameFunc, nodeBorderRadius: nodeBorderRadius, nodeStrokeWidth: nodeStrokeWidth, NodeComponent: NodeComponent, onClick: onClick, shapeRendering: shapeRendering }, nodeId))) }));
|
|
3178
3291
|
}
|
|
3179
|
-
|
|
3292
|
+
function NodeComponentWrapperInner({ id, nodeOrigin, nodeColorFunc, nodeStrokeColorFunc, nodeClassNameFunc, nodeBorderRadius, nodeStrokeWidth, shapeRendering, NodeComponent, onClick, }) {
|
|
3180
3293
|
const { node, x, y } = useStore((s) => {
|
|
3181
3294
|
const node = s.nodeLookup.get(id);
|
|
3182
|
-
const { x, y } = getNodePositionWithOrigin(node,
|
|
3295
|
+
const { x, y } = getNodePositionWithOrigin(node, nodeOrigin).positionAbsolute;
|
|
3183
3296
|
return {
|
|
3184
3297
|
node,
|
|
3185
3298
|
x,
|
|
3186
3299
|
y,
|
|
3187
3300
|
};
|
|
3188
3301
|
}, shallow);
|
|
3189
|
-
if (!node || node.hidden || !(node
|
|
3302
|
+
if (!node || node.hidden || !nodeHasDimensions(node)) {
|
|
3190
3303
|
return null;
|
|
3191
3304
|
}
|
|
3192
|
-
|
|
3193
|
-
});
|
|
3305
|
+
const { width, height } = getNodeDimensions(node);
|
|
3306
|
+
return (jsx(NodeComponent, { x: x, y: y, width: width, height: height, style: node.style, selected: !!node.selected, className: nodeClassNameFunc(node), color: nodeColorFunc(node), borderRadius: nodeBorderRadius, strokeColor: nodeStrokeColorFunc(node), strokeWidth: nodeStrokeWidth, shapeRendering: shapeRendering, onClick: onClick, id: node.id }));
|
|
3307
|
+
}
|
|
3308
|
+
const NodeComponentWrapper = memo(NodeComponentWrapperInner);
|
|
3194
3309
|
var MiniMapNodes$1 = memo(MiniMapNodes);
|
|
3195
3310
|
|
|
3196
3311
|
const defaultWidth = 200;
|
|
@@ -3204,7 +3319,9 @@ const selector$1 = (s) => {
|
|
|
3204
3319
|
};
|
|
3205
3320
|
return {
|
|
3206
3321
|
viewBB,
|
|
3207
|
-
boundingRect: s.
|
|
3322
|
+
boundingRect: s.nodeLookup.size > 0
|
|
3323
|
+
? getBoundsOfRects(getInternalNodesBounds(s.nodeLookup, { nodeOrigin: s.nodeOrigin }), viewBB)
|
|
3324
|
+
: viewBB,
|
|
3208
3325
|
rfId: s.rfId,
|
|
3209
3326
|
nodeOrigin: s.nodeOrigin,
|
|
3210
3327
|
panZoom: s.panZoom,
|
|
@@ -3214,10 +3331,10 @@ const selector$1 = (s) => {
|
|
|
3214
3331
|
};
|
|
3215
3332
|
};
|
|
3216
3333
|
const ARIA_LABEL_KEY = 'react-flow__minimap-desc';
|
|
3217
|
-
function
|
|
3334
|
+
function MiniMapComponent({ style, className, nodeStrokeColor, nodeColor, nodeClassName = '', nodeBorderRadius = 5, nodeStrokeWidth,
|
|
3218
3335
|
// We need to rename the prop to be `CapitalCase` so that JSX will render it as
|
|
3219
3336
|
// a component properly.
|
|
3220
|
-
nodeComponent, maskColor, maskStrokeColor
|
|
3337
|
+
nodeComponent, bgColor, maskColor, maskStrokeColor, maskStrokeWidth, position = 'bottom-right', onClick, onNodeClick, pannable = false, zoomable = false, ariaLabel = 'React Flow mini map', inversePan, zoomStep = 10, offsetScale = 5, }) {
|
|
3221
3338
|
const store = useStoreApi();
|
|
3222
3339
|
const svg = useRef(null);
|
|
3223
3340
|
const { boundingRect, viewBB, rfId, panZoom, translateExtent, flowWidth, flowHeight } = useStore(selector$1, shallow);
|
|
@@ -3275,189 +3392,127 @@ nodeComponent, maskColor, maskStrokeColor = 'none', maskStrokeWidth = 1, positio
|
|
|
3275
3392
|
: undefined;
|
|
3276
3393
|
return (jsx(Panel, { position: position, style: {
|
|
3277
3394
|
...style,
|
|
3278
|
-
'--xy-minimap-
|
|
3395
|
+
'--xy-minimap-background-color-props': typeof bgColor === 'string' ? bgColor : undefined,
|
|
3396
|
+
'--xy-minimap-mask-background-color-props': typeof maskColor === 'string' ? maskColor : undefined,
|
|
3397
|
+
'--xy-minimap-mask-stroke-color-props': typeof maskStrokeColor === 'string' ? maskStrokeColor : undefined,
|
|
3398
|
+
'--xy-minimap-mask-stroke-width-props': typeof maskStrokeWidth === 'number' ? maskStrokeWidth * viewScale : undefined,
|
|
3279
3399
|
'--xy-minimap-node-background-color-props': typeof nodeColor === 'string' ? nodeColor : undefined,
|
|
3280
3400
|
'--xy-minimap-node-stroke-color-props': typeof nodeStrokeColor === 'string' ? nodeStrokeColor : undefined,
|
|
3281
3401
|
'--xy-minimap-node-stroke-width-props': typeof nodeStrokeWidth === 'string' ? nodeStrokeWidth : undefined,
|
|
3282
|
-
}, className: cc(['react-flow__minimap', className]), "data-testid": "rf__minimap", children: jsxs("svg", { width: elementWidth, height: elementHeight, viewBox: `${x} ${y} ${width} ${height}`, role: "img", "aria-labelledby": labelledBy, ref: svg, onClick: onSvgClick, children: [ariaLabel && jsx("title", { id: labelledBy, children: ariaLabel }), jsx(MiniMapNodes$1, { onClick: onSvgNodeClick, nodeColor: nodeColor, nodeStrokeColor: nodeStrokeColor, nodeBorderRadius: nodeBorderRadius, nodeClassName: nodeClassName, nodeStrokeWidth: nodeStrokeWidth, nodeComponent: nodeComponent }), jsx("path", { className: "react-flow__minimap-mask", d: `M${x - offset},${y - offset}h${width + offset * 2}v${height + offset * 2}h${-width - offset * 2}z
|
|
3283
|
-
M${viewBB.x},${viewBB.y}h${viewBB.width}v${viewBB.height}h${-viewBB.width}z`, fillRule: "evenodd",
|
|
3284
|
-
}
|
|
3285
|
-
MiniMap.displayName = 'MiniMap';
|
|
3286
|
-
var MiniMap$1 = memo(MiniMap);
|
|
3287
|
-
|
|
3288
|
-
var ResizeControlVariant;
|
|
3289
|
-
(function (ResizeControlVariant) {
|
|
3290
|
-
ResizeControlVariant["Line"] = "line";
|
|
3291
|
-
ResizeControlVariant["Handle"] = "handle";
|
|
3292
|
-
})(ResizeControlVariant || (ResizeControlVariant = {}));
|
|
3293
|
-
|
|
3294
|
-
// returns an array of two numbers (0, 1 or -1) representing the direction of the resize
|
|
3295
|
-
// 0 = no change, 1 = increase, -1 = decrease
|
|
3296
|
-
function getDirection({ width, prevWidth, height, prevHeight, invertX, invertY }) {
|
|
3297
|
-
const deltaWidth = width - prevWidth;
|
|
3298
|
-
const deltaHeight = height - prevHeight;
|
|
3299
|
-
const direction = [deltaWidth > 0 ? 1 : deltaWidth < 0 ? -1 : 0, deltaHeight > 0 ? 1 : deltaHeight < 0 ? -1 : 0];
|
|
3300
|
-
if (deltaWidth && invertX) {
|
|
3301
|
-
direction[0] = direction[0] * -1;
|
|
3302
|
-
}
|
|
3303
|
-
if (deltaHeight && invertY) {
|
|
3304
|
-
direction[1] = direction[1] * -1;
|
|
3305
|
-
}
|
|
3306
|
-
return direction;
|
|
3402
|
+
}, className: cc(['react-flow__minimap', className]), "data-testid": "rf__minimap", children: jsxs("svg", { width: elementWidth, height: elementHeight, viewBox: `${x} ${y} ${width} ${height}`, className: "react-flow__minimap-svg", role: "img", "aria-labelledby": labelledBy, ref: svg, onClick: onSvgClick, children: [ariaLabel && jsx("title", { id: labelledBy, children: ariaLabel }), jsx(MiniMapNodes$1, { onClick: onSvgNodeClick, nodeColor: nodeColor, nodeStrokeColor: nodeStrokeColor, nodeBorderRadius: nodeBorderRadius, nodeClassName: nodeClassName, nodeStrokeWidth: nodeStrokeWidth, nodeComponent: nodeComponent }), jsx("path", { className: "react-flow__minimap-mask", d: `M${x - offset},${y - offset}h${width + offset * 2}v${height + offset * 2}h${-width - offset * 2}z
|
|
3403
|
+
M${viewBB.x},${viewBB.y}h${viewBB.width}v${viewBB.height}h${-viewBB.width}z`, fillRule: "evenodd", pointerEvents: "none" })] }) }));
|
|
3307
3404
|
}
|
|
3405
|
+
MiniMapComponent.displayName = 'MiniMap';
|
|
3406
|
+
const MiniMap = memo(MiniMapComponent);
|
|
3308
3407
|
|
|
3309
|
-
const initPrevValues = { width: 0, height: 0, x: 0, y: 0 };
|
|
3310
|
-
const initStartValues = {
|
|
3311
|
-
...initPrevValues,
|
|
3312
|
-
pointerX: 0,
|
|
3313
|
-
pointerY: 0,
|
|
3314
|
-
aspectRatio: 1,
|
|
3315
|
-
};
|
|
3316
3408
|
function ResizeControl({ nodeId, position, variant = ResizeControlVariant.Handle, className, style = {}, children, color, minWidth = 10, minHeight = 10, maxWidth = Number.MAX_VALUE, maxHeight = Number.MAX_VALUE, keepAspectRatio = false, shouldResize, onResizeStart, onResize, onResizeEnd, }) {
|
|
3317
3409
|
const contextNodeId = useNodeId();
|
|
3318
3410
|
const id = typeof nodeId === 'string' ? nodeId : contextNodeId;
|
|
3319
3411
|
const store = useStoreApi();
|
|
3320
3412
|
const resizeControlRef = useRef(null);
|
|
3321
|
-
const startValues = useRef(initStartValues);
|
|
3322
|
-
const prevValues = useRef(initPrevValues);
|
|
3323
3413
|
const defaultPosition = variant === ResizeControlVariant.Line ? 'right' : 'bottom-right';
|
|
3324
3414
|
const controlPosition = position ?? defaultPosition;
|
|
3415
|
+
const resizer = useRef(null);
|
|
3325
3416
|
useEffect(() => {
|
|
3326
3417
|
if (!resizeControlRef.current || !id) {
|
|
3327
3418
|
return;
|
|
3328
3419
|
}
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
const nextAspectRatio = width / height;
|
|
3367
|
-
const isDiagonal = enableX && enableY;
|
|
3368
|
-
const isHorizontal = enableX && !enableY;
|
|
3369
|
-
const isVertical = enableY && !enableX;
|
|
3370
|
-
width = (nextAspectRatio <= aspectRatio && isDiagonal) || isVertical ? height * aspectRatio : width;
|
|
3371
|
-
height = (nextAspectRatio > aspectRatio && isDiagonal) || isHorizontal ? width / aspectRatio : height;
|
|
3372
|
-
if (width >= maxWidth) {
|
|
3373
|
-
width = maxWidth;
|
|
3374
|
-
height = maxWidth / aspectRatio;
|
|
3375
|
-
}
|
|
3376
|
-
else if (width <= minWidth) {
|
|
3377
|
-
width = minWidth;
|
|
3378
|
-
height = minWidth / aspectRatio;
|
|
3420
|
+
if (!resizer.current) {
|
|
3421
|
+
resizer.current = XYResizer({
|
|
3422
|
+
domNode: resizeControlRef.current,
|
|
3423
|
+
nodeId: id,
|
|
3424
|
+
getStoreItems: () => {
|
|
3425
|
+
const { nodeLookup, transform, snapGrid, snapToGrid, nodeOrigin } = store.getState();
|
|
3426
|
+
return {
|
|
3427
|
+
nodeLookup,
|
|
3428
|
+
transform,
|
|
3429
|
+
snapGrid,
|
|
3430
|
+
snapToGrid,
|
|
3431
|
+
nodeOrigin,
|
|
3432
|
+
};
|
|
3433
|
+
},
|
|
3434
|
+
onChange: (change, childChanges) => {
|
|
3435
|
+
const { triggerNodeChanges, nodeLookup, parentLookup, nodeOrigin } = store.getState();
|
|
3436
|
+
const changes = [];
|
|
3437
|
+
const nextPosition = { x: change.x, y: change.y };
|
|
3438
|
+
const node = nodeLookup.get(id);
|
|
3439
|
+
if (node && node.expandParent && node.parentId) {
|
|
3440
|
+
const child = {
|
|
3441
|
+
id: node.id,
|
|
3442
|
+
parentId: node.parentId,
|
|
3443
|
+
rect: {
|
|
3444
|
+
width: change.width ?? node.measured.width,
|
|
3445
|
+
height: change.height ?? node.measured.height,
|
|
3446
|
+
...evaluateAbsolutePosition({
|
|
3447
|
+
x: change.x ?? node.position.x,
|
|
3448
|
+
y: change.y ?? node.position.y,
|
|
3449
|
+
}, node.parentId, nodeLookup, node.origin ?? nodeOrigin),
|
|
3450
|
+
},
|
|
3451
|
+
};
|
|
3452
|
+
const parentExpandChanges = handleExpandParent([child], nodeLookup, parentLookup, nodeOrigin);
|
|
3453
|
+
changes.push(...parentExpandChanges);
|
|
3454
|
+
// when the parent was expanded by the child node, its position will be clamped at 0,0
|
|
3455
|
+
nextPosition.x = change.x ? Math.max(0, change.x) : undefined;
|
|
3456
|
+
nextPosition.y = change.y ? Math.max(0, change.y) : undefined;
|
|
3379
3457
|
}
|
|
3380
|
-
if (
|
|
3381
|
-
|
|
3382
|
-
|
|
3458
|
+
if (nextPosition.x !== undefined && nextPosition.y !== undefined) {
|
|
3459
|
+
const positionChange = {
|
|
3460
|
+
id,
|
|
3461
|
+
type: 'position',
|
|
3462
|
+
position: { ...nextPosition },
|
|
3463
|
+
};
|
|
3464
|
+
changes.push(positionChange);
|
|
3383
3465
|
}
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3466
|
+
if (change.width !== undefined && change.height !== undefined) {
|
|
3467
|
+
const dimensionChange = {
|
|
3468
|
+
id,
|
|
3469
|
+
type: 'dimensions',
|
|
3470
|
+
resizing: true,
|
|
3471
|
+
setAttributes: true,
|
|
3472
|
+
dimensions: {
|
|
3473
|
+
width: change.width,
|
|
3474
|
+
height: change.height,
|
|
3475
|
+
},
|
|
3476
|
+
};
|
|
3477
|
+
changes.push(dimensionChange);
|
|
3387
3478
|
}
|
|
3388
|
-
|
|
3389
|
-
const isWidthChange = width !== prevWidth;
|
|
3390
|
-
const isHeightChange = height !== prevHeight;
|
|
3391
|
-
if (invertX || invertY) {
|
|
3392
|
-
const x = invertX ? startNodeX - (width - startWidth) : startNodeX;
|
|
3393
|
-
const y = invertY ? startNodeY - (height - startHeight) : startNodeY;
|
|
3394
|
-
// only transform the node if the width or height changes
|
|
3395
|
-
const isXPosChange = x !== prevX && isWidthChange;
|
|
3396
|
-
const isYPosChange = y !== prevY && isHeightChange;
|
|
3397
|
-
if (isXPosChange || isYPosChange) {
|
|
3479
|
+
for (const childChange of childChanges) {
|
|
3398
3480
|
const positionChange = {
|
|
3399
|
-
|
|
3481
|
+
...childChange,
|
|
3400
3482
|
type: 'position',
|
|
3401
|
-
position: {
|
|
3402
|
-
x: isXPosChange ? x : prevX,
|
|
3403
|
-
y: isYPosChange ? y : prevY,
|
|
3404
|
-
},
|
|
3405
3483
|
};
|
|
3406
3484
|
changes.push(positionChange);
|
|
3407
|
-
prevValues.current.x = positionChange.position.x;
|
|
3408
|
-
prevValues.current.y = positionChange.position.y;
|
|
3409
3485
|
}
|
|
3410
|
-
|
|
3411
|
-
|
|
3486
|
+
triggerNodeChanges(changes);
|
|
3487
|
+
},
|
|
3488
|
+
onEnd: () => {
|
|
3412
3489
|
const dimensionChange = {
|
|
3413
3490
|
id: id,
|
|
3414
3491
|
type: 'dimensions',
|
|
3415
|
-
|
|
3416
|
-
resizing: true,
|
|
3417
|
-
dimensions: {
|
|
3418
|
-
width: width,
|
|
3419
|
-
height: height,
|
|
3420
|
-
},
|
|
3492
|
+
resizing: false,
|
|
3421
3493
|
};
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
if (callResize === false) {
|
|
3440
|
-
return;
|
|
3441
|
-
}
|
|
3442
|
-
onResize?.(event, nextValues);
|
|
3443
|
-
triggerNodeChanges(changes);
|
|
3444
|
-
}
|
|
3445
|
-
})
|
|
3446
|
-
.on('end', (event) => {
|
|
3447
|
-
const dimensionChange = {
|
|
3448
|
-
id: id,
|
|
3449
|
-
type: 'dimensions',
|
|
3450
|
-
resizing: false,
|
|
3451
|
-
};
|
|
3452
|
-
onResizeEnd?.(event, { ...prevValues.current });
|
|
3453
|
-
store.getState().triggerNodeChanges([dimensionChange]);
|
|
3494
|
+
store.getState().triggerNodeChanges([dimensionChange]);
|
|
3495
|
+
},
|
|
3496
|
+
});
|
|
3497
|
+
}
|
|
3498
|
+
resizer.current.update({
|
|
3499
|
+
controlPosition,
|
|
3500
|
+
boundaries: {
|
|
3501
|
+
minWidth,
|
|
3502
|
+
minHeight,
|
|
3503
|
+
maxWidth,
|
|
3504
|
+
maxHeight,
|
|
3505
|
+
},
|
|
3506
|
+
keepAspectRatio,
|
|
3507
|
+
onResizeStart,
|
|
3508
|
+
onResize,
|
|
3509
|
+
onResizeEnd,
|
|
3510
|
+
shouldResize,
|
|
3454
3511
|
});
|
|
3455
|
-
selection.call(dragHandler);
|
|
3456
3512
|
return () => {
|
|
3457
|
-
|
|
3513
|
+
resizer.current?.destroy();
|
|
3458
3514
|
};
|
|
3459
3515
|
}, [
|
|
3460
|
-
id,
|
|
3461
3516
|
controlPosition,
|
|
3462
3517
|
minWidth,
|
|
3463
3518
|
minHeight,
|
|
@@ -3467,21 +3522,20 @@ function ResizeControl({ nodeId, position, variant = ResizeControlVariant.Handle
|
|
|
3467
3522
|
onResizeStart,
|
|
3468
3523
|
onResize,
|
|
3469
3524
|
onResizeEnd,
|
|
3525
|
+
shouldResize,
|
|
3470
3526
|
]);
|
|
3471
3527
|
const positionClassNames = controlPosition.split('-');
|
|
3472
3528
|
const colorStyleProp = variant === ResizeControlVariant.Line ? 'borderColor' : 'backgroundColor';
|
|
3473
3529
|
const controlStyle = color ? { ...style, [colorStyleProp]: color } : style;
|
|
3474
3530
|
return (jsx("div", { className: cc(['react-flow__resize-control', 'nodrag', ...positionClassNames, variant, className]), ref: resizeControlRef, style: controlStyle, children: children }));
|
|
3475
3531
|
}
|
|
3476
|
-
|
|
3532
|
+
const NodeResizeControl = memo(ResizeControl);
|
|
3477
3533
|
|
|
3478
|
-
const handleControls = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
|
|
3479
|
-
const lineControls = ['top', 'right', 'bottom', 'left'];
|
|
3480
3534
|
function NodeResizer({ nodeId, isVisible = true, handleClassName, handleStyle, lineClassName, lineStyle, color, minWidth = 10, minHeight = 10, maxWidth = Number.MAX_VALUE, maxHeight = Number.MAX_VALUE, keepAspectRatio = false, shouldResize, onResizeStart, onResize, onResizeEnd, }) {
|
|
3481
3535
|
if (!isVisible) {
|
|
3482
3536
|
return null;
|
|
3483
3537
|
}
|
|
3484
|
-
return (jsxs(Fragment, { children: [
|
|
3538
|
+
return (jsxs(Fragment, { children: [XY_RESIZER_LINE_POSITIONS.map((position) => (jsx(NodeResizeControl, { className: lineClassName, style: lineStyle, nodeId: nodeId, position: position, variant: ResizeControlVariant.Line, color: color, minWidth: minWidth, minHeight: minHeight, maxWidth: maxWidth, maxHeight: maxHeight, onResizeStart: onResizeStart, keepAspectRatio: keepAspectRatio, shouldResize: shouldResize, onResize: onResize, onResizeEnd: onResizeEnd }, position))), XY_RESIZER_HANDLE_POSITIONS.map((position) => (jsx(NodeResizeControl, { className: handleClassName, style: handleStyle, nodeId: nodeId, position: position, color: color, minWidth: minWidth, minHeight: minHeight, maxWidth: maxWidth, maxHeight: maxHeight, onResizeStart: onResizeStart, keepAspectRatio: keepAspectRatio, shouldResize: shouldResize, onResize: onResize, onResizeEnd: onResizeEnd }, position)))] }));
|
|
3485
3539
|
}
|
|
3486
3540
|
|
|
3487
3541
|
const selector = (state) => state.domNode?.querySelector('.react-flow__renderer');
|
|
@@ -3493,12 +3547,12 @@ function NodeToolbarPortal({ children }) {
|
|
|
3493
3547
|
return createPortal(children, wrapperRef);
|
|
3494
3548
|
}
|
|
3495
3549
|
|
|
3496
|
-
const nodeEqualityFn = (a, b) => a?.
|
|
3497
|
-
a?.
|
|
3498
|
-
a?.
|
|
3499
|
-
a?.
|
|
3550
|
+
const nodeEqualityFn = (a, b) => a?.internals.positionAbsolute.x !== b?.internals.positionAbsolute.x ||
|
|
3551
|
+
a?.internals.positionAbsolute.y !== b?.internals.positionAbsolute.y ||
|
|
3552
|
+
a?.measured.width !== b?.measured.width ||
|
|
3553
|
+
a?.measured.height !== b?.measured.height ||
|
|
3500
3554
|
a?.selected !== b?.selected ||
|
|
3501
|
-
a?.
|
|
3555
|
+
a?.internals.z !== b?.internals.z;
|
|
3502
3556
|
const nodesEqualityFn = (a, b) => {
|
|
3503
3557
|
if (a.length !== b.length) {
|
|
3504
3558
|
return false;
|
|
@@ -3533,8 +3587,8 @@ function NodeToolbar({ nodeId, children, className, style, isVisible, position =
|
|
|
3533
3587
|
if (!isActive || !nodes.length) {
|
|
3534
3588
|
return null;
|
|
3535
3589
|
}
|
|
3536
|
-
const nodeRect = getNodesBounds(nodes, nodeOrigin);
|
|
3537
|
-
const zIndex = Math.max(...nodes.map((node) =>
|
|
3590
|
+
const nodeRect = getNodesBounds(nodes, { nodeOrigin });
|
|
3591
|
+
const zIndex = Math.max(...nodes.map((node) => node.internals.z + 1));
|
|
3538
3592
|
const wrapperStyle = {
|
|
3539
3593
|
position: 'absolute',
|
|
3540
3594
|
transform: getNodeToolbarTransform(nodeRect, viewport, position, offset, align),
|
|
@@ -3544,4 +3598,4 @@ function NodeToolbar({ nodeId, children, className, style, isVisible, position =
|
|
|
3544
3598
|
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 }) }));
|
|
3545
3599
|
}
|
|
3546
3600
|
|
|
3547
|
-
export { Background
|
|
3601
|
+
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 };
|