--- name: svelte-flow description: Build node-based editors, interactive diagrams, and flow visualizations using Svelte Flow. Use when creating workflow editors, data flow diagrams, organizational charts, mindmaps, process visualizations, DAG editors, or any interactive node-graph UI. Supports custom nodes/edges, layouts (dagre, hierarchical), animations, and advanced features like proximity connect, floating edges, and contextual zoom. keywords: [svelte-flow, visualization, nodes, graph-editor, diagrams, interactive-ui] --- # Svelte Flow Expert guide for building node-based UIs with Svelte Flow (@xyflow/svelte). ## Installation ```bash npm install @xyflow/svelte ``` ## Core Setup ```svelte ``` ## Key Concepts ### Nodes Each node requires: - `id`: Unique identifier - `position`: `{ x: number, y: number }` - `data`: Object with custom properties (typically includes `label`) - Optional: `type`, `style`, `hidden`, `width`, `height`, `sourcePosition`, `targetPosition` ```typescript const node = { id: '1', type: 'custom', position: { x: 100, y: 100 }, data: { label: 'My Node', color: '#ff0000' }, style: 'background: #f0f0f0', width: 150, height: 100 }; ``` ### Edges Each edge requires: - `id`: Unique identifier - `source`: Source node ID - `target`: Target node ID - Optional: `type`, `label`, `animated`, `markerEnd`, `markerStart`, `style`, `hidden` ```typescript const edge = { id: 'e1-2', source: '1', target: '2', type: 'smoothstep', label: 'connects to', animated: true, markerEnd: { type: MarkerType.ArrowClosed } }; ``` ### Built-in Types **Edge Types:** - `default`: Straight line - `smoothstep`: Smooth 90-degree turns - `step`: Hard 90-degree turns - `straight`: Alias for default - `bezier`: Curved bezier line **Node Types:** - `default`: Basic rectangle node - `input`: Node with only source handles - `output`: Node with only target handles ## Custom Nodes ```svelte
{data.label}
``` Register custom nodes: ```svelte ``` ## Custom Edges ```svelte {#if label}
{label}
{/if} ``` Path helpers available: - `getStraightPath()` - `getBezierPath()` - `getSmoothStepPath()` Register custom edges: ```svelte ``` ## Updating State **Critical:** Nodes and edges are immutable. Create new objects to trigger updates. ```svelte ``` ## Event Handling Common event handlers: ```svelte console.log('node clicked', event.targetNode)} onnodedrag={(event) => console.log('node dragging', event.targetNode)} onnodedragstop={(event) => console.log('drag ended', event.targetNode)} onedgeclick={(event) => console.log('edge clicked', event.edge)} onconnect={(params) => { edges = [...edges, { id: `e${params.source}-${params.target}`, ...params }]; }} /> ``` Available events: - `onnodeclick`, `onnodedoubleclick` - `onnodedrag`, `onnodedragstart`, `onnodedragstop` - `onedgeclick`, `onedgedoubleclick` - `onconnect`, `onconnectstart`, `onconnectend` - `onbeforedelete` (async, can prevent deletion) - `oninit`, `onmove`, `onmovestart`, `onmoveend` ## Layout Algorithms ### Dagre (Hierarchical) ```typescript import dagre from '@dagrejs/dagre'; import { Position } from '@xyflow/svelte'; function getLayoutedElements(nodes: Node[], edges: Edge[], direction = 'TB') { const dagreGraph = new dagre.graphlib.Graph(); dagreGraph.setDefaultEdgeLabel(() => ({})); const isHorizontal = direction === 'LR'; dagreGraph.setGraph({ rankdir: direction }); const nodeWidth = 172; const nodeHeight = 36; nodes.forEach((node) => { dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight }); }); edges.forEach((edge) => { dagreGraph.setEdge(edge.source, edge.target); }); dagre.layout(dagreGraph); const layoutedNodes = nodes.map((node) => { const nodeWithPosition = dagreGraph.node(node.id); return { ...node, targetPosition: isHorizontal ? Position.Left : Position.Top, sourcePosition: isHorizontal ? Position.Right : Position.Bottom, position: { x: nodeWithPosition.x - nodeWidth / 2, y: nodeWithPosition.y - nodeHeight / 2, }, }; }); return { nodes: layoutedNodes, edges }; } ``` ## Advanced Features ### Floating Edges Edges that dynamically connect to the closest point on node boundaries: ```svelte ``` Register with `ConnectionMode.Loose`: ```svelte ``` ### Proximity Connect Auto-connect nodes when dragged close together: ```svelte ``` ### Edge Reconnection Allow users to drag edge endpoints to different nodes: ```svelte {#if !reconnecting} {/if} {#if selected} {/if} ``` ### Delete Node and Reconnect Edges ```svelte ``` ## Components ### Controls ```svelte ``` ### MiniMap ```svelte ``` ### Background ```svelte ``` Variants: `Dots`, `Lines`, `Cross` ### Panel (Custom Controls) ```svelte ``` Positions: `top-left`, `top-center`, `top-right`, `bottom-left`, `bottom-center`, `bottom-right` ## Utility Functions ```typescript import { getConnectedEdges, getIncomers, getOutgoers, addEdge, applyEdgeChanges, applyNodeChanges } from '@xyflow/svelte'; // Get edges connected to nodes const connectedEdges = getConnectedEdges(nodes, edges); // Get nodes that connect TO a node const incomers = getIncomers(targetNode, nodes, edges); // Get nodes that a node connects TO const outgoers = getOutgoers(sourceNode, nodes, edges); // Add edge with validation edges = addEdge(connection, edges); ``` ## Store Management (Alternative) For centralized state: ```javascript // store.svelte.js let nodes = $state.raw([...]); let edges = $state.raw([...]); export const getNodes = () => nodes; export const getEdges = () => edges; export const setNodes = (newNodes) => nodes = newNodes; export const setEdges = (newEdges) => edges = newEdges; ``` ```svelte ``` ## Export to Image ```svelte ``` ## Performance Tips - Use `$state.raw` for nodes and edges (prevents deep reactivity) - For large graphs (1000+ nodes), set `elevateNodesOnSelect={false}` and `elevateEdgesOnSelect={false}` - Use `minZoom` and `maxZoom` to limit zoom levels - Consider virtualization for extremely large graphs ## Common Props ```svelte ```