UNPKG

@matthewgapp/solidjs-flow

Version:

React Flow - A highly customizable React library for building node-based editors and interactive flow charts.

515 lines (511 loc) 19.9 kB
// import type { CSSProperties, HTMLAttributes, MouseEvent as ReactMouseEvent, WheelEvent } from 'react'; import type { ConnectionMode, ConnectionLineType, OnConnect, OnConnectStart, OnConnectEnd, CoordinateExtent, KeyCode, PanOnScrollMode, ProOptions, PanelPosition, OnMove, OnMoveStart, OnMoveEnd, Viewport, NodeOrigin, HandleType, SelectionMode, OnError, ColorMode, SnapGrid, } from '@xyflow/system'; import type { OnSelectionChangeFunc, NodeTypes, EdgeTypes, Node, Edge, ConnectionLineComponent, OnEdgeUpdateFunc, OnInit, DefaultEdgeOptions, FitViewOptions, OnNodesDelete, OnEdgesDelete, OnDelete, OnNodesChange, OnEdgesChange, NodeMouseHandler, SelectionDragHandler, EdgeMouseHandler, OnNodeDrag, OnBeforeDelete, IsValidConnection, SolidEvent, } from '.'; import { JSX } from 'solid-js' /** * ReactFlow component props. * @public */ export interface ReactFlowProps<NodeType extends Node = Node, EdgeType extends Edge = Edge> extends Omit<JSX.HTMLAttributes<HTMLDivElement>, 'onError'> { /** An array of nodes to render in a controlled flow. * @example * const nodes = [ * { * id: 'node-1', * type: 'input', * data: { label: 'Node 1' }, * position: { x: 250, y: 50 } * } * ]; */ nodes?: NodeType[]; /** An array of edges to render in a controlled flow. * @example * const edges = [ * { * id: 'edge-1-2', * source: 'node-1', * target: 'node-2', * } * ]; */ edges?: EdgeType[]; /** The initial nodes to render in an uncontrolled flow. */ defaultNodes?: NodeType[]; /** The initial edges to render in an uncontrolled flow. */ defaultEdges?: EdgeType[]; /** Defaults to be applied to all new edges that are added to the flow. * * Properties on a new edge will override these defaults if they exist. * @example * const defaultEdgeOptions = { * type: 'customEdgeType', * animated: true, * interactionWidth: 10, * data: { label: 'custom label' }, * hidden: false, * deletable: true, * selected: false, * focusable: true, * markerStart: EdgeMarker.ArrowClosed, * markerEnd: EdgeMarker.ArrowClosed, * zIndex: 12, * ariaLabel: 'custom aria label' * } */ defaultEdgeOptions?: DefaultEdgeOptions; /** This event handler is called when a user clicks on a node */ onNodeClick?: NodeMouseHandler<NodeType>; /** This event handler is called when a user double clicks on a node */ onNodeDoubleClick?: NodeMouseHandler<NodeType>; /** This event handler is called when mouse of a user enters a node */ onNodeMouseEnter?: NodeMouseHandler<NodeType>; /** This event handler is called when mouse of a user moves over a node */ onNodeMouseMove?: NodeMouseHandler<NodeType>; /** This event handler is called when mouse of a user leaves a node */ onNodeMouseLeave?: NodeMouseHandler<NodeType>; /** This event handler is called when a user right clicks on a node */ onNodeContextMenu?: NodeMouseHandler<NodeType>; /** This event handler is called when a user starts to drag a node */ onNodeDragStart?: OnNodeDrag<NodeType>; /** This event handler is called when a user drags a node */ onNodeDrag?: OnNodeDrag<NodeType>; /** This event handler is called when a user stops dragging a node */ onNodeDragStop?: OnNodeDrag<NodeType>; /** This event handler is called when a user clicks on an edge */ onEdgeClick?: (event: MouseEvent, edge: EdgeType) => void; /** This event handler is called when a user right clicks on an edge */ onEdgeContextMenu?: EdgeMouseHandler<EdgeType>; /** This event handler is called when mouse of a user enters an edge */ onEdgeMouseEnter?: EdgeMouseHandler<EdgeType>; /** This event handler is called when mouse of a user moves over an edge */ onEdgeMouseMove?: EdgeMouseHandler<EdgeType>; /** This event handler is called when mouse of a user leaves an edge */ onEdgeMouseLeave?: EdgeMouseHandler<EdgeType>; /** This event handler is called when a user double clicks on an edge */ onEdgeDoubleClick?: EdgeMouseHandler<EdgeType>; onEdgeUpdateStart?: (event: MouseEvent, edge: EdgeType, handleType: HandleType) => void; onEdgeUpdateEnd?: (event: MouseEvent | TouchEvent, edge: EdgeType, handleType: HandleType) => void; onEdgeUpdate?: OnEdgeUpdateFunc<EdgeType>; /** This event handler is called when a Node is updated * @example // Use NodesState hook to create edges and get onNodesChange handler * import ReactFlow, { useNodesState } from '@xyflow/react'; * const [edges, setNodes, onNodesChange] = useNodesState(initialNodes); * * return (<ReactFlow onNodeChange={onNodeChange} {...rest} />) * @example // Use helper function to update edge * import ReactFlow, { applyNodeChanges } from '@xyflow/react'; * * const onNodeChange = useCallback( * (changes) => setNode((eds) => applyNodeChanges(changes, eds)), * [], * ); * * return (<ReactFlow onNodeChange={onNodeChange} {...rest} />) */ onNodesChange?: OnNodesChange<NodeType>; /** This event handler is called when a Edge is updated * @example // Use EdgesState hook to create edges and get onEdgesChange handler * import ReactFlow, { useEdgesState } from '@xyflow/react'; * const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); * * return (<ReactFlow onEdgesChange={onEdgesChange} {...rest} />) * @example // Use helper function to update edge * import ReactFlow, { applyEdgeChanges } from '@xyflow/react'; * * const onEdgesChange = useCallback( * (changes) => setEdges((eds) => applyEdgeChanges(changes, eds)), * [], * ); * * return (<ReactFlow onEdgesChange={onEdgesChange} {...rest} />) */ onEdgesChange?: OnEdgesChange<EdgeType>; /** This event handler gets called when a Node is deleted */ onNodesDelete?: OnNodesDelete<NodeType>; /** This event handler gets called when a Edge is deleted */ onEdgesDelete?: OnEdgesDelete<EdgeType>; /** This event handler gets called when a Node or Edge is deleted */ onDelete?: OnDelete<NodeType, EdgeType>; /** This event handler gets called when a user starts to drag a selection box */ onSelectionDragStart?: SelectionDragHandler<NodeType>; /** This event handler gets called when a user drags a selection box */ onSelectionDrag?: SelectionDragHandler<NodeType>; /** This event handler gets called when a user stops dragging a selection box */ onSelectionDragStop?: SelectionDragHandler<NodeType>; onSelectionStart?: (event: MouseEvent) => void; onSelectionEnd?: (event: MouseEvent) => void; onSelectionContextMenu?: <T,>(event: SolidEvent<T, MouseEvent>, nodes: NodeType[]) => void; /** When a connection line is completed and two nodes are connected by the user, this event fires with the new connection. * * You can use the addEdge utility to convert the connection to a complete edge. * @example // Use helper function to update edges onConnect * import ReactFlow, { addEdge } from '@xyflow/react'; * * const onConnect = useCallback( * (params) => setEdges((eds) => addEdge(params, eds)), * [], * ); * * return (<ReactFlow onConnect={onConnect} {...rest} />) */ onConnect?: OnConnect; /** This event handler gets called when a user starts to drag a connection line */ onConnectStart?: OnConnectStart; /** This event handler gets called when a user stops dragging a connection line */ onConnectEnd?: OnConnectEnd; onClickConnectStart?: OnConnectStart; onClickConnectEnd?: OnConnectEnd; /** This event handler gets called when a flow has finished initializing */ onInit?: OnInit<NodeType, EdgeType>; /** This event handler is called while the user is either panning or zooming the viewport. */ onMove?: OnMove; /** This event handler gets called when a user starts to pan or zoom the viewport */ onMoveStart?: OnMoveStart; /** This event handler gets called when a user stops panning or zooming the viewport */ onMoveEnd?: OnMoveEnd; /** This event handler gets called when a user changes group of selected elements in the flow */ onSelectionChange?: OnSelectionChangeFunc; /** This event handler gets called when user scroll inside the pane */ onPaneScroll?: (event?: WheelEvent) => void; /** This event handler gets called when user clicks inside the pane */ onPaneClick?: (event: MouseEvent) => void; /** This event handler gets called when user right clicks inside the pane */ onPaneContextMenu?: (event: MouseEvent | MouseEvent) => void; /** This event handler gets called when mouse enters the pane */ onPaneMouseEnter?: (event: MouseEvent) => void; /** This event handler gets called when mouse moves over the pane */ onPaneMouseMove?: (event: MouseEvent) => void; /** This event handler gets called when mouse leaves the pane */ onPaneMouseLeave?: (event: MouseEvent) => void; /** This handler gets called before the user deletes nodes or edges and provides a way to abort the deletion by returning false. */ onBeforeDelete?: OnBeforeDelete<NodeType, EdgeType>; /** Custom node types to be available in a flow. * * React Flow matches a node's type to a component in the nodeTypes object. * @example * import CustomNode from './CustomNode'; * * const nodeTypes = { nameOfNodeType: CustomNode }; */ nodeTypes?: NodeTypes; /** Custom edge types to be available in a flow. * * React Flow matches an edge's type to a component in the edgeTypes object. * @example * import CustomEdge from './CustomEdge'; * * const edgeTypes = { nameOfEdgeType: CustomEdge }; */ edgeTypes?: EdgeTypes; /** The type of edge path to use for connection lines. * * Although created edges can be of any type, React Flow needs to know what type of path to render for the connection line before the edge is created! */ connectionLineType?: ConnectionLineType; /** Styles to be applied to the connection line */ connectionLineStyle?: JSX.CSSProperties; /** React Component to be used as a connection line */ connectionLineComponent?: ConnectionLineComponent; /** Styles to be applied to the container of the connection line */ connectionLineContainerStyle?: JSX.CSSProperties; /** 'strict' connection mode will only allow you to connect source handles to target handles. * * 'loose' connection mode will allow you to connect handles of any type to one another. * @default 'strict' */ connectionMode?: ConnectionMode; /** Pressing down this key deletes all selected nodes & edges. * @default 'Backspace' */ deleteKeyCode?: KeyCode | null; /** If a key is set, you can pan the viewport while that key is held down even if panOnScroll is set to false. * * By setting this prop to null you can disable this functionality. * @default 'Space' */ selectionKeyCode?: KeyCode | null; /** Select multiple elements with a selection box, without pressing down selectionKey */ selectionOnDrag?: boolean; /** When set to "partial", when the user creates a selection box by click and dragging nodes that are only partially in the box are still selected. * @default 'full' */ selectionMode?: SelectionMode; /** If a key is set, you can pan the viewport while that key is held down even if panOnScroll is set to false. * * By setting this prop to null you can disable this functionality. * @default 'Space' */ panActivationKeyCode?: KeyCode | null; /** Pressing down this key you can select multiple elements by clicking. * @default 'Meta' for macOS, "Ctrl" for other systems */ multiSelectionKeyCode?: KeyCode | null; /** If a key is set, you can zoom the viewport while that key is held down even if panOnScroll is set to false. * * By setting this prop to null you can disable this functionality. * @default 'Meta' for macOS, "Ctrl" for other systems * */ zoomActivationKeyCode?: KeyCode | null; /** Set this prop to make the flow snap to the grid */ snapToGrid?: boolean; /** Grid all nodes will snap to * @example [20, 20] */ snapGrid?: SnapGrid; /** You can enable this optimisation to instruct Svelte Flow to only render nodes and edges that would be visible in the viewport. * * This might improve performance when you have a large number of nodes and edges but also adds an overhead. * @default false */ onlyRenderVisibleElements?: boolean | undefined; /** Controls if all nodes should be draggable * @default true */ nodesDraggable?: boolean; /** Controls if all nodes should be connectable to each other * @default true */ nodesConnectable?: boolean; /** Controls if all nodes should be focusable * @default true */ nodesFocusable?: boolean; /** Defines nodes relative position to its coordinates * @example * [0, 0] // default, top left * [0.5, 0.5] // center * [1, 1] // bottom right */ nodeOrigin?: NodeOrigin; /** Controls if all edges should be focusable * @default true */ edgesFocusable?: boolean; /** Controls if all edges should be updateable * @default true */ edgesUpdatable?: boolean; /** Controls if all elements should (nodes & edges) be selectable * @default true */ elementsSelectable?: boolean; /** If true, nodes get selected on drag * @default true */ selectNodesOnDrag?: boolean; /** Enableing this prop allows users to pan the viewport by clicking and dragging. * * You can also set this prop to an array of numbers to limit which mouse buttons can activate panning. * @example [0, 2] // allows panning with the left and right mouse buttons * [0, 1, 2, 3, 4] // allows panning with all mouse buttons */ panOnDrag?: boolean | number[]; /** Minimum zoom level * @default 0.5 */ minZoom?: number; /** Maximum zoom level * @default 2 */ maxZoom?: number; /** Controlled viewport to be used instead of internal one */ viewport?: Viewport; /** Sets the initial position and zoom of the viewport. * * If a default viewport is provided but fitView is enabled, the default viewport will be ignored. * @example * const initialViewport = { * zoom: 0.5, * position: { x: 0, y: 0 } * }; */ defaultViewport?: Viewport; /** * Gets called when the viewport changes. */ onViewportChange?: (viewport: Viewport) => void; /** By default the viewport extends infinitely. You can use this prop to set a boundary. * * The first pair of coordinates is the top left boundary and the second pair is the bottom right. * @example [[-1000, -10000], [1000, 1000]] */ translateExtent?: CoordinateExtent; /** Disabling this prop will allow the user to scroll the page even when their pointer is over the flow. * @default true */ preventScrolling?: boolean; /** By default nodes can be placed on an infinite flow. You can use this prop to set a boundary. * * The first pair of coordinates is the top left boundary and the second pair is the bottom right. * @example [[-1000, -10000], [1000, 1000]] */ nodeExtent?: CoordinateExtent; /** Color of edge markers * @example "#b1b1b7" */ defaultMarkerColor?: string; /** Controls if the viewport should zoom by scrolling inside the container */ zoomOnScroll?: boolean; /** Controls if the viewport should zoom by pinching on a touch screen */ zoomOnPinch?: boolean; /** Controls if the viewport should pan by scrolling inside the container * * Can be limited to a specific direction with panOnScrollMode */ panOnScroll?: boolean; /** Controls how fast viewport should be panned on scroll. * * Use togther with panOnScroll prop. */ panOnScrollSpeed?: number; /** This prop is used to limit the direction of panning when panOnScroll is enabled. * * The "free" option allows panning in any direction. * @default "free" * @example "horizontal" | "vertical" */ panOnScrollMode?: PanOnScrollMode; /** Controls if the viewport should zoom by double clicking somewhere on the flow */ zoomOnDoubleClick?: boolean; edgeUpdaterRadius?: number; noDragClassName?: string | undefined; noWheelClassName?: string; noPanClassName?: string; /** If set, initial viewport will show all nodes & edges */ fitView?: boolean; /** Options to be used in combination with fitView * @example * const fitViewOptions = { * padding: 0.1, * includeHiddenNodes: false, * minZoom: 0.1, * maxZoom: 1, * duration: 200, * nodes: [{id: 'node-1'}, {id: 'node-2'}], // nodes to fit * }; */ fitViewOptions?: FitViewOptions; /**The connectOnClick option lets you click or tap on a source handle to start a connection * and then click on a target handle to complete the connection. * * If you set this option to false, users will need to drag the connection line to the target * handle to create a connection. */ connectOnClick?: boolean; /** Set position of the attribution * @default 'bottom-right' * @example 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right' */ attributionPosition?: PanelPosition; /** By default, we render a small attribution in the corner of your flows that links back to the project. * * Anyone is free to remove this attribution whether they're a Pro subscriber or not * but we ask that you take a quick look at our {@link https://reactflow.dev/learn/troubleshooting/remove-attribution | removing attribution guide} * before doing so. */ proOptions?: ProOptions; /** Enabling this option will raise the z-index of nodes when they are selected. * @default true */ elevateNodesOnSelect?: boolean; /** Enabling this option will raise the z-index of edges when they are selected. * @default true */ elevateEdgesOnSelect?: boolean; /** * Can be set true if built-in keyboard controls should be disabled. * @default false */ disableKeyboardA11y?: boolean; /** You can enable this prop to automatically pan the viewport while dragging a node. * @default true */ autoPanOnNodeDrag?: boolean; /** You can enable this prop to automatically pan the viewport while dragging a node. * @default true */ autoPanOnConnect?: boolean; /** You can enable this prop to automatically pan the viewport while making a new connection. * @default true */ connectionRadius?: number; /** Ocassionally something may happen that causes Svelte Flow to throw an error. * * Instead of exploding your application, we log a message to the console and then call this event handler. * You might use it for additional logging or to show a message to the user. */ onError?: OnError; /** This callback can be used to validate a new connection * * If you return false, the edge will not be added to your flow. * If you have custom connection logic its preferred to use this callback over the isValidConnection prop on the handle component for performance reasons. * @default (connection: Connection) => true */ isValidConnection?: IsValidConnection; /** With a threshold greater than zero you can control the distinction between node drag and click events. * * If threshold equals 1, you need to drag the node 1 pixel before a drag event is fired. * @default 1 */ nodeDragThreshold?: number; /** Sets a fixed width for the flow */ width?: number; /** Sets a fixed height for the flow */ height?: number; /** Controls color scheme used for styling the flow * @default 'system' * @example 'system' | 'light' | 'dark' */ colorMode?: ColorMode; /** If set true, some debug information will be logged to the console like which events are fired. * * @default undefined */ debug?: boolean; }