Files
xyflow/packages/core/src/container/ReactFlow/index.tsx

315 lines
10 KiB
TypeScript

import { forwardRef } from 'react';
import type { CSSProperties } from 'react';
import cc from 'classcat';
import {
ConnectionLineType,
ConnectionMode,
PanOnScrollMode,
SelectionMode,
type EdgeTypes,
type EdgeTypesWrapped,
type NodeOrigin,
type NodeTypes,
type NodeTypesWrapped,
type ReactFlowProps,
type ReactFlowRefType,
type Viewport,
} from '@reactflow/system';
import Attribution from '../../components/Attribution';
import { BezierEdge, SmoothStepEdge, StepEdge, StraightEdge, SimpleBezierEdge } from '../../components/Edges';
import DefaultNode from '../../components/Nodes/DefaultNode';
import InputNode from '../../components/Nodes/InputNode';
import OutputNode from '../../components/Nodes/OutputNode';
import GroupNode from '../../components/Nodes/GroupNode';
import SelectionListener from '../../components/SelectionListener';
import StoreUpdater from '../../components/StoreUpdater';
import A11yDescriptions from '../../components/A11yDescriptions';
import { createEdgeTypes } from '../EdgeRenderer/utils';
import { createNodeTypes } from '../NodeRenderer/utils';
import GraphView from '../GraphView';
import Wrapper from './Wrapper';
import { infiniteExtent } from '../../store/initialState';
import { useNodeOrEdgeTypes } from './utils';
const defaultNodeTypes: NodeTypes = {
input: InputNode,
default: DefaultNode,
output: OutputNode,
group: GroupNode,
};
const defaultEdgeTypes: EdgeTypes = {
default: BezierEdge,
straight: StraightEdge,
step: StepEdge,
smoothstep: SmoothStepEdge,
simplebezier: SimpleBezierEdge,
};
const initNodeOrigin: NodeOrigin = [0, 0];
const initSnapGrid: [number, number] = [15, 15];
const initDefaultViewport: Viewport = { x: 0, y: 0, zoom: 1 };
const wrapperStyle: CSSProperties = {
width: '100%',
height: '100%',
overflow: 'hidden',
position: 'relative',
zIndex: 0,
};
const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
(
{
nodes,
edges,
defaultNodes,
defaultEdges,
className,
nodeTypes = defaultNodeTypes,
edgeTypes = defaultEdgeTypes,
onNodeClick,
onEdgeClick,
onInit,
onMove,
onMoveStart,
onMoveEnd,
onConnect,
onConnectStart,
onConnectEnd,
onClickConnectStart,
onClickConnectEnd,
onNodeMouseEnter,
onNodeMouseMove,
onNodeMouseLeave,
onNodeContextMenu,
onNodeDoubleClick,
onNodeDragStart,
onNodeDrag,
onNodeDragStop,
onNodesDelete,
onEdgesDelete,
onSelectionChange,
onSelectionDragStart,
onSelectionDrag,
onSelectionDragStop,
onSelectionContextMenu,
onSelectionStart,
onSelectionEnd,
connectionMode = ConnectionMode.Strict,
connectionLineType = ConnectionLineType.Bezier,
connectionLineStyle,
connectionLineComponent,
connectionLineContainerStyle,
deleteKeyCode = 'Backspace',
selectionKeyCode = 'Shift',
selectionOnDrag = false,
selectionMode = SelectionMode.Full,
panActivationKeyCode = 'Space',
multiSelectionKeyCode = 'Meta',
zoomActivationKeyCode = 'Meta',
snapToGrid = false,
snapGrid = initSnapGrid,
onlyRenderVisibleElements = false,
selectNodesOnDrag = true,
nodesDraggable,
nodesConnectable,
nodesFocusable,
nodeOrigin = initNodeOrigin,
edgesFocusable,
elementsSelectable,
defaultViewport = initDefaultViewport,
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 = false,
fitViewOptions,
connectOnClick = true,
attributionPosition,
proOptions,
defaultEdgeOptions,
elevateNodesOnSelect = true,
elevateEdgesOnSelect = false,
disableKeyboardA11y = false,
autoPanOnConnect = true,
autoPanOnNodeDrag = true,
connectionRadius = 20,
onError,
style,
id,
...rest
},
ref
) => {
const nodeTypesWrapped = useNodeOrEdgeTypes(nodeTypes, createNodeTypes) as NodeTypesWrapped;
const edgeTypesWrapped = useNodeOrEdgeTypes(edgeTypes, createEdgeTypes) as EdgeTypesWrapped;
const rfId = id || '1';
return (
<div
{...rest}
style={{ ...style, ...wrapperStyle }}
ref={ref}
className={cc(['react-flow', className])}
data-testid="rf__wrapper"
id={id}
>
<Wrapper>
<GraphView
onInit={onInit}
onMove={onMove}
onMoveStart={onMoveStart}
onMoveEnd={onMoveEnd}
onNodeClick={onNodeClick}
onEdgeClick={onEdgeClick}
onNodeMouseEnter={onNodeMouseEnter}
onNodeMouseMove={onNodeMouseMove}
onNodeMouseLeave={onNodeMouseLeave}
onNodeContextMenu={onNodeContextMenu}
onNodeDoubleClick={onNodeDoubleClick}
nodeTypes={nodeTypesWrapped}
edgeTypes={edgeTypesWrapped}
connectionLineType={connectionLineType}
connectionLineStyle={connectionLineStyle}
connectionLineComponent={connectionLineComponent}
connectionLineContainerStyle={connectionLineContainerStyle}
selectionKeyCode={selectionKeyCode}
selectionOnDrag={selectionOnDrag}
selectionMode={selectionMode}
deleteKeyCode={deleteKeyCode}
multiSelectionKeyCode={multiSelectionKeyCode}
panActivationKeyCode={panActivationKeyCode}
zoomActivationKeyCode={zoomActivationKeyCode}
onlyRenderVisibleElements={onlyRenderVisibleElements}
selectNodesOnDrag={selectNodesOnDrag}
defaultViewport={defaultViewport}
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}
elevateEdgesOnSelect={elevateEdgesOnSelect}
rfId={rfId}
disableKeyboardA11y={disableKeyboardA11y}
nodeOrigin={nodeOrigin}
nodeExtent={nodeExtent}
/>
<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}
elementsSelectable={elementsSelectable}
elevateNodesOnSelect={elevateNodesOnSelect}
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}
onNodeDragStart={onNodeDragStart}
onNodeDrag={onNodeDrag}
onNodeDragStop={onNodeDragStop}
onSelectionDrag={onSelectionDrag}
onSelectionDragStart={onSelectionDragStart}
onSelectionDragStop={onSelectionDragStop}
noPanClassName={noPanClassName}
nodeOrigin={nodeOrigin}
rfId={rfId}
autoPanOnConnect={autoPanOnConnect}
autoPanOnNodeDrag={autoPanOnNodeDrag}
onError={onError}
connectionRadius={connectionRadius}
/>
<SelectionListener onSelectionChange={onSelectionChange} />
{children}
<Attribution proOptions={proOptions} position={attributionPosition} />
<A11yDescriptions rfId={rfId} disableKeyboardA11y={disableKeyboardA11y} />
</Wrapper>
</div>
);
}
);
ReactFlow.displayName = 'ReactFlow';
export default ReactFlow;