233 lines
7.4 KiB
TypeScript
233 lines
7.4 KiB
TypeScript
import React, { useMemo, CSSProperties, HTMLAttributes, MouseEvent, WheelEvent } from 'react';
|
|
import cc from 'classcat';
|
|
|
|
import GraphView from '../GraphView';
|
|
import ElementUpdater from '../../components/ElementUpdater';
|
|
import DefaultNode from '../../components/Nodes/DefaultNode';
|
|
import InputNode from '../../components/Nodes/InputNode';
|
|
import OutputNode from '../../components/Nodes/OutputNode';
|
|
import { createNodeTypes } from '../NodeRenderer/utils';
|
|
import SelectionListener from '../../components/SelectionListener';
|
|
import { BezierEdge, StepEdge, SmoothStepEdge, StraightEdge } from '../../components/Edges';
|
|
import { createEdgeTypes } from '../EdgeRenderer/utils';
|
|
import Wrapper from './Wrapper';
|
|
import {
|
|
Elements,
|
|
NodeTypesType,
|
|
EdgeTypesType,
|
|
OnLoadFunc,
|
|
Node,
|
|
Edge,
|
|
Connection,
|
|
ConnectionLineType,
|
|
ConnectionLineComponent,
|
|
FlowTransform,
|
|
OnConnectStartFunc,
|
|
OnConnectStopFunc,
|
|
OnConnectEndFunc,
|
|
TranslateExtent,
|
|
KeyCode,
|
|
PanOnScrollMode,
|
|
} from '../../types';
|
|
|
|
import '../../style.css';
|
|
|
|
const defaultNodeTypes = {
|
|
input: InputNode,
|
|
default: DefaultNode,
|
|
output: OutputNode,
|
|
};
|
|
|
|
const defaultEdgeTypes = {
|
|
default: BezierEdge,
|
|
straight: StraightEdge,
|
|
step: StepEdge,
|
|
smoothstep: SmoothStepEdge,
|
|
};
|
|
|
|
export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onLoad'> {
|
|
elements: Elements;
|
|
onElementClick?: (event: MouseEvent, element: Node | Edge) => void;
|
|
onElementsRemove?: (elements: Elements) => void;
|
|
onNodeMouseEnter?: (event: MouseEvent, node: Node) => void;
|
|
onNodeMouseMove?: (event: MouseEvent, node: Node) => void;
|
|
onNodeMouseLeave?: (event: MouseEvent, node: Node) => void;
|
|
onNodeContextMenu?: (event: MouseEvent, node: Node) => void;
|
|
onNodeDragStart?: (event: MouseEvent, node: Node) => void;
|
|
onNodeDragStop?: (event: MouseEvent, node: Node) => void;
|
|
onConnect?: (connection: Edge | Connection) => void;
|
|
onConnectStart?: OnConnectStartFunc;
|
|
onConnectStop?: OnConnectStopFunc;
|
|
onConnectEnd?: OnConnectEndFunc;
|
|
onLoad?: OnLoadFunc;
|
|
onMove?: (flowTransform?: FlowTransform) => void;
|
|
onMoveStart?: (flowTransform?: FlowTransform) => void;
|
|
onMoveEnd?: (flowTransform?: FlowTransform) => void;
|
|
onSelectionChange?: (elements: Elements | null) => void;
|
|
onSelectionDragStart?: (event: MouseEvent, nodes: Node[]) => void;
|
|
onSelectionDrag?: (event: MouseEvent, nodes: Node[]) => void;
|
|
onSelectionDragStop?: (event: MouseEvent, nodes: Node[]) => void;
|
|
onSelectionContextMenu?: (event: MouseEvent, nodes: Node[]) => void;
|
|
onPaneScroll?: (event?: WheelEvent) => void;
|
|
onPaneClick?: (event: MouseEvent) => void;
|
|
onPaneContextMenu?: (event: MouseEvent) => void;
|
|
nodeTypes?: NodeTypesType;
|
|
edgeTypes?: EdgeTypesType;
|
|
connectionLineType?: ConnectionLineType;
|
|
connectionLineStyle?: CSSProperties;
|
|
connectionLineComponent?: ConnectionLineComponent;
|
|
deleteKeyCode?: KeyCode;
|
|
selectionKeyCode?: KeyCode;
|
|
multiSelectionKeyCode?: KeyCode;
|
|
snapToGrid?: boolean;
|
|
snapGrid?: [number, number];
|
|
onlyRenderVisibleElements?: boolean;
|
|
nodesDraggable?: boolean;
|
|
nodesConnectable?: boolean;
|
|
elementsSelectable?: boolean;
|
|
selectNodesOnDrag?: boolean;
|
|
paneMoveable?: boolean;
|
|
minZoom?: number;
|
|
maxZoom?: number;
|
|
defaultZoom?: number;
|
|
defaultPosition?: [number, number];
|
|
translateExtent?: TranslateExtent;
|
|
arrowHeadColor?: string;
|
|
markerEndId?: string;
|
|
zoomOnScroll?: boolean;
|
|
panOnScroll?: boolean;
|
|
panOnScrollSpeed?: number;
|
|
panOnScrollMode?: PanOnScrollMode;
|
|
zoomOnDoubleClick?: boolean;
|
|
}
|
|
|
|
const ReactFlow = ({
|
|
elements = [],
|
|
className,
|
|
nodeTypes = defaultNodeTypes,
|
|
edgeTypes = defaultEdgeTypes,
|
|
onElementClick,
|
|
onLoad,
|
|
onMove,
|
|
onMoveStart,
|
|
onMoveEnd,
|
|
onElementsRemove,
|
|
onConnect,
|
|
onConnectStart,
|
|
onConnectStop,
|
|
onConnectEnd,
|
|
onNodeMouseEnter,
|
|
onNodeMouseMove,
|
|
onNodeMouseLeave,
|
|
onNodeContextMenu,
|
|
onNodeDragStart,
|
|
onNodeDragStop,
|
|
onSelectionChange,
|
|
onSelectionDragStart,
|
|
onSelectionDrag,
|
|
onSelectionDragStop,
|
|
onSelectionContextMenu,
|
|
connectionLineType = ConnectionLineType.Bezier,
|
|
connectionLineStyle,
|
|
connectionLineComponent,
|
|
deleteKeyCode = 'Backspace',
|
|
selectionKeyCode = 'Shift',
|
|
multiSelectionKeyCode = 'Meta',
|
|
snapToGrid = false,
|
|
snapGrid = [15, 15],
|
|
onlyRenderVisibleElements = true,
|
|
selectNodesOnDrag = true,
|
|
nodesDraggable,
|
|
nodesConnectable,
|
|
elementsSelectable,
|
|
minZoom,
|
|
maxZoom,
|
|
defaultZoom = 1,
|
|
defaultPosition = [0, 0],
|
|
translateExtent,
|
|
arrowHeadColor = '#b1b1b7',
|
|
markerEndId,
|
|
zoomOnScroll = true,
|
|
panOnScroll = false,
|
|
panOnScrollSpeed = 0.5,
|
|
panOnScrollMode = PanOnScrollMode.Free,
|
|
zoomOnDoubleClick = true,
|
|
paneMoveable = true,
|
|
onPaneClick,
|
|
onPaneScroll,
|
|
onPaneContextMenu,
|
|
children,
|
|
...rest
|
|
}: ReactFlowProps) => {
|
|
const nodeTypesParsed = useMemo(() => createNodeTypes(nodeTypes), []);
|
|
const edgeTypesParsed = useMemo(() => createEdgeTypes(edgeTypes), []);
|
|
const reactFlowClasses = cc(['react-flow', className]);
|
|
|
|
return (
|
|
<div {...rest} className={reactFlowClasses}>
|
|
<Wrapper>
|
|
<GraphView
|
|
onLoad={onLoad}
|
|
onMove={onMove}
|
|
onMoveStart={onMoveStart}
|
|
onMoveEnd={onMoveEnd}
|
|
onElementClick={onElementClick}
|
|
onNodeMouseEnter={onNodeMouseEnter}
|
|
onNodeMouseMove={onNodeMouseMove}
|
|
onNodeMouseLeave={onNodeMouseLeave}
|
|
onNodeContextMenu={onNodeContextMenu}
|
|
onNodeDragStart={onNodeDragStart}
|
|
onNodeDragStop={onNodeDragStop}
|
|
nodeTypes={nodeTypesParsed}
|
|
edgeTypes={edgeTypesParsed}
|
|
connectionLineType={connectionLineType}
|
|
connectionLineStyle={connectionLineStyle}
|
|
connectionLineComponent={connectionLineComponent}
|
|
selectionKeyCode={selectionKeyCode}
|
|
onElementsRemove={onElementsRemove}
|
|
deleteKeyCode={deleteKeyCode}
|
|
multiSelectionKeyCode={multiSelectionKeyCode}
|
|
onConnect={onConnect}
|
|
onConnectStart={onConnectStart}
|
|
onConnectStop={onConnectStop}
|
|
onConnectEnd={onConnectEnd}
|
|
snapToGrid={snapToGrid}
|
|
snapGrid={snapGrid}
|
|
onlyRenderVisibleElements={onlyRenderVisibleElements}
|
|
nodesDraggable={nodesDraggable}
|
|
nodesConnectable={nodesConnectable}
|
|
elementsSelectable={elementsSelectable}
|
|
selectNodesOnDrag={selectNodesOnDrag}
|
|
minZoom={minZoom}
|
|
maxZoom={maxZoom}
|
|
defaultZoom={defaultZoom}
|
|
defaultPosition={defaultPosition}
|
|
translateExtent={translateExtent}
|
|
arrowHeadColor={arrowHeadColor}
|
|
markerEndId={markerEndId}
|
|
zoomOnScroll={zoomOnScroll}
|
|
zoomOnDoubleClick={zoomOnDoubleClick}
|
|
panOnScroll={panOnScroll}
|
|
panOnScrollSpeed={panOnScrollSpeed}
|
|
panOnScrollMode={panOnScrollMode}
|
|
paneMoveable={paneMoveable}
|
|
onPaneClick={onPaneClick}
|
|
onPaneScroll={onPaneScroll}
|
|
onPaneContextMenu={onPaneContextMenu}
|
|
onSelectionDragStart={onSelectionDragStart}
|
|
onSelectionDrag={onSelectionDrag}
|
|
onSelectionDragStop={onSelectionDragStop}
|
|
onSelectionContextMenu={onSelectionContextMenu}
|
|
/>
|
|
<ElementUpdater elements={elements} />
|
|
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
|
|
{children}
|
|
</Wrapper>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
ReactFlow.displayName = 'ReactFlow';
|
|
|
|
export default ReactFlow;
|