Files
xyflow/src/container/ReactFlow/index.tsx
T

225 lines
7.0 KiB
TypeScript

import React, { useMemo, CSSProperties, HTMLAttributes, MouseEvent, WheelEvent } from 'react';
import cc from 'classcat';
const nodeEnv: string = __ENV__ as string;
if (nodeEnv !== 'production') {
const whyDidYouRender = require('@welldone-software/why-did-you-render');
whyDidYouRender(React);
}
import GraphView from '../GraphView';
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,
} 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?: number;
selectionKeyCode?: number;
snapToGrid?: boolean;
snapGrid?: [number, number];
onlyRenderVisibleNodes?: 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;
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 = 8,
selectionKeyCode = 16,
snapToGrid = false,
snapGrid = [15, 15],
onlyRenderVisibleNodes = true,
selectNodesOnDrag = true,
nodesDraggable,
nodesConnectable,
elementsSelectable,
minZoom,
maxZoom,
defaultZoom = 1,
defaultPosition = [0, 0],
translateExtent,
arrowHeadColor = '#b1b1b7',
markerEndId,
zoomOnScroll = true,
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}
elements={elements}
onConnect={onConnect}
onConnectStart={onConnectStart}
onConnectStop={onConnectStop}
onConnectEnd={onConnectEnd}
snapToGrid={snapToGrid}
snapGrid={snapGrid}
onlyRenderVisibleNodes={onlyRenderVisibleNodes}
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}
paneMoveable={paneMoveable}
onPaneClick={onPaneClick}
onPaneScroll={onPaneScroll}
onPaneContextMenu={onPaneContextMenu}
onSelectionDragStart={onSelectionDragStart}
onSelectionDrag={onSelectionDrag}
onSelectionDragStop={onSelectionDragStop}
onSelectionContextMenu={onSelectionContextMenu}
/>
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
{children}
</Wrapper>
</div>
);
};
ReactFlow.displayName = 'ReactFlow';
export default ReactFlow;