Flitter
Diagram
Node and edge editors with React Flow's interactions, drawn by Flitter on SVG or Canvas.
- Layouts
- 5
- Edge paths
- 5
- Renderers
- 2
- Drag a node
- Wheel or pinch to zoom
- Shift+drag to select
- Drag from a handle to connect
- Drag an edge end to reconnect
- Backspace deletes
Nodes in, editor out
Describe nodes and edges as plain objects, the same shape React Flow uses. FlowDiagram returns a widget with panning, zooming, selection, connecting, controls and a minimap already wired.
The editor keeps its own state. Change callbacks tell you what happened, and a FlowController lets you change it from outside.
import Widget from "@flitterjs/react";
import type { FlowEdge, FlowNode } from "flitter-ui/diagram";
import { FlowDiagram } from "@/components/diagram/flow-diagram";
const nodes: FlowNode[] = [
{ id: "1", type: "input", position: { x: 0, y: 0 }, data: { label: "Input" } },
{ id: "2", position: { x: 0, y: 120 }, data: { label: "Default" } },
{ id: "3", type: "output", position: { x: 0, y: 240 }, data: { label: "Output" } },
];
const edges: FlowEdge[] = [
{ id: "e1-2", source: "1", target: "2", animated: true },
{ id: "e2-3", source: "2", target: "3", markerEnd: "arrowclosed" },
];
// Create the widget once. A new instance remounts the editor.
const diagram = FlowDiagram({ nodes, edges, fitView: true });
export default function App() {
return <Widget widget={diagram} width="100%" height="480px" renderer="canvas" />;
}React Flow's interactions
Drag to pan, wheel to zoom, Shift+drag to box-select, drag between handles to connect, drag an edge end to reconnect it. Defaults match React Flow.
Mouse and touch
On touch screens a tap selects, one finger drags nodes or pans, and two fingers pinch to zoom around their midpoint.
Resizer and toolbar
Selected nodes can show resize controls and a toolbar that stays at screen size, like React Flow's NodeResizer and NodeToolbar.
Rebuilds only what changed
Each node and edge widget listens to its own signal. Dragging a node rebuilds that node and its edges; panning and zooming rebuild none.
SVG or Canvas
The editor is a Flitter widget tree, so either renderer draws it. Nodes, edges, the background and the minimap all follow.
Pluggable layouts
Layered, tree, force, grid and circular ship built in, and children are laid out inside their group. dagre or ELK plug in as one async function.
One graph, five layouts
Every node below starts at the origin. The layout runs once the nodes are measured, then fits the view. Switch the algorithm to see the same graph placed differently.
Bring your own nodes
A node type is a builder that returns any Flitter widget, plus the handles it exposes. Handles are declared, not measured, so edges know where to attach before anything is painted.
FlowDiagram({
nodes,
edges,
nodeTypes: {
// Any Flitter widget, plus the handles it exposes
task: {
build: ({ node, selected }) =>
Container({
width: 180,
padding: EdgeInsets.all(12),
decoration: new BoxDecoration({
color: selected ? "#fff7e6" : "#ffffff",
border: Border.all({ color: "#f59e0b" }),
borderRadius: BorderRadius.circular(8),
}),
child: Text(String(node.data.label)),
}),
handles: [
{ type: "target", position: "left" },
{ type: "source", position: "right" },
],
},
},
layout: { algorithm: layeredLayout, options: { direction: "LR" } },
});