01 React Flow — The Reference Implementation
Architecture
React Flow is built on a Zustand store at its core. The <ReactFlow> component wraps a <ReactFlowProvider> which initializes this store. All state — nodes, edges, viewport, selection, connection-in-progress — lives in one centralized store. Components subscribe to slices via useStore(selector).
Rendering pipeline: DOM-based nodes (each node is a positioned <div>), SVG-based edges (rendered in an <svg> layer beneath the node layer). Nodes are real DOM elements, enabling rich HTML content, form inputs, and full accessibility.
Data Model
| Type | Key Fields | Field Count |
|---|---|---|
Node<T> |
id, position, data, type, measured, parentId, handles, draggable, selectable, connectable, deletable, dragHandle, extent, expandParent, origin, zIndex, resizing, focusable, ariaRole |
25+ |
Edge<T> |
id, source, target, sourceHandle, targetHandle, type, data, label, animated, markerStart, markerEnd, reconnectable, interactionWidth, selectable, deletable |
18+ |
Handle |
id, type, position, isConnectable, isConnectableStart, isConnectableEnd, isValidConnection |
7+ |
Connection |
source, target, sourceHandle, targetHandle |
4 |
Viewport |
x, y, zoom |
3 |
Built-in Types
Node Types
default · input · output · group
Edge Types
default (bezier) · straight · step · smoothstep · simplebezier
Feature Surface
Props on <ReactFlow>
Hooks exposed
Event callbacks
Sub-components
Interaction Features
- Node dragging with configurable threshold, drag handles, auto-pan
- Edge connection by drag (handle-to-handle) and click-to-connect mode
- Edge reconnection (drag existing edge to new target)
- Multi-selection (shift+click, rubber-band selection box)
- Selection box drag, keyboard delete
- Snap-to-grid, node extent constraints (including
"parent") - Auto-pan on drag near canvas edges
- Pan via drag, scroll, or space+drag
- Zoom via scroll, pinch, double-click, or ctrl+scroll
- Full keyboard navigation (tab through nodes/edges)
Components
<ReactFlow>,<ReactFlowProvider><Handle>with connection validation<Background>(dots, lines, cross)<Controls>,<MiniMap>,<Panel><ViewportPortal>,<NodeResizer>,<NodeToolbar><BaseEdge>,<EdgeLabelRenderer>
Hooks
| Hook | Purpose |
|---|---|
useReactFlow() | Imperative API: get/set/add nodes & edges, fitView, zoom, viewport, screenToFlowPosition, deleteElements, getIntersectingNodes |
useNodes() / useEdges() | Reactive accessors |
useNodesState() / useEdgesState() | State + setter + onChange bundles |
useViewport() | Current viewport |
useOnViewportChange() | Viewport start/change/end callbacks |
useConnection() | In-progress connection data |
useHandleConnections() | Edges connected to a specific handle |
useNodeId() | Current node context |
useNodesData() | Subscribe to specific node data |
useNodesInitialized() | Measurement readiness signal |
useOnSelectionChange() | Selection events |
useStore() / useStoreApi() | Direct Zustand access |
useKeyPress() | Keyboard state |
useUpdateNodeInternals() | Force re-measure |
Event System (~40 callbacks)
| Category | Events |
|---|---|
| Node | click, doubleClick, dragStart, drag, dragStop, mouseEnter, mouseMove, mouseLeave, contextMenu, delete |
| Edge | click, doubleClick, mouseEnter, mouseMove, mouseLeave, contextMenu, reconnect, reconnectStart, reconnectEnd, delete |
| Connection | connect, connectStart, connectEnd, clickConnectStart, clickConnectEnd, isValidConnection |
| Pane | click, contextMenu, scroll, mouseMove, mouseEnter, mouseLeave |
| Selection | change, dragStart, drag, dragStop, start, end, contextMenu |
| Viewport | move, moveStart, moveEnd |
| Lifecycle | init, error, delete, beforeDelete |
02 Compose Flow — Current State
Package: dev.shibasis.composeflow
KMP Targets: commonMain, Android, iOS/macOS (Darwin), JVM Desktop, JS/Web
Rendering Pipeline
Compose graphicsLayer transform for viewport (translate + scale), DOM-positioned nodes via Box + offset, Canvas-drawn edges via DrawScope. This is a good architectural match to react-flow’s DOM-nodes + SVG-edges pattern.
What’s Implemented
Data Model
| Type | Fields | File |
|---|---|---|
Node | id, position, data, type, width, height, measured, handles, sourcePosition, targetPosition, parentId, showDefaultHandles, selected, dragging, hidden, zIndex | model/Model.kt |
Edge | id, source, target, sourceHandle, targetHandle, type, data, label, selected, hidden, animated, markerEnd, zIndex | model/Model.kt |
Handle | id, type, position, offset, inset | model/Model.kt |
Connection | source, target, sourceHandle, targetHandle | model/Model.kt |
Viewport | x, y, zoom | model/Model.kt |
Change System
NodeChangesealed interface:NodeAddChange,NodeRemoveChange,NodeReplaceChange,NodeSelectionChange,NodePositionChange,NodeDimensionChangeEdgeChangesealed interface:EdgeAddChange,EdgeRemoveChange,EdgeReplaceChange,EdgeSelectionChangeapplyNodeChanges(),applyEdgeChanges(),addEdge()helpers
State Management
NodesState—nodes,replaceNodes(),updateNodes(),onNodesChange(), destructuring operatorsEdgesState—edges,replaceEdges(),updateEdges(),onEdgesChange(), destructuring operatorsReactFlowState—viewport,canvasSize,selectedNodeIds/EdgeIds,setViewport(),panBy(),screenToFlowPosition(),centerOn(),focusNode(),zoomTo(),zoomBy(),fitView()ReactFlowProvider,useReactFlowState(),useViewport()
Main Composable — ReactFlow()
~25 parameters: nodes, edges, state, nodeTypes, onNodesChange, onConnect, onNodeClick, fitView, fitViewOptions, showBackground, backgroundVariant, showControls, showMiniMap, minZoom, maxZoom, defaultNodeWidth/Height, nodeRenderStyle, edgeRenderStyle, edgePathStyle, handleRenderStyle, onPaneClick, overlay, viewportOverlay
Components
FlowBackground— Dots, Lines, Cross patternsFlowControls— zoom in/out/fit with percentage displayMiniMap— overview with node/edge renderingPanelwithPanelPositionFlowNodeBox— node container with drag, click, measurementHandlecomposable — circular handles with source/target stylingDefaultNode— label + type display
Interactions
- Wheel/trackpad zoom with ctrl/meta modifier detection
- Pan via scroll (no modifier) and pointer drag
- Multi-touch pinch-to-zoom with centroid tracking
- Right-click detection (no pan on right-click)
- Node dragging with viewport.zoom compensation and drag threshold
- macOS trackpad magnification via Apple EAWT reflection (Desktop)
- Platform bridge abstraction for desktop-specific gestures
Edge Rendering
- Bezier paths with smart tangent distance and collinear bias
- Orthogonal (step) paths
- Arrow markers (open + closed)
- Per-edge render styles (color, width, alpha)
JS/Web Interop
- Karakum-generated TypeScript externals for
@xyflow/react - Bidirectional conversion between common models and react-flow JS objects
- Full external declarations for all react-flow components
- Hook wrappers:
useNodesState,useEdgesState,useReactFlow,useViewport,useOnViewportChange,useOnSelectionChange,useStore
Theme System
Complete dark-theme color token palette (FlowTokens.kt) and comprehensive sizing constants for every element (FlowSizing.kt).
Tests & Tracking
FlowChangesTest— addEdge deduplication, applyNodeChanges, applyEdgeChangesparity/features.jsonwith structured parity matrix and GradlereportParitytask
03 Reaktor Flow — The Bridge Layer
Package: dev.shibasis.reaktor.flow
Dependencies: compose-flow + reaktor-graph
reaktor-flow is a specialized adapter that transforms reaktor-graph Graph objects into compose-flow visual representations. It has four sub-systems.
3a. Adapter Layer
| File | Responsibility |
|---|---|
ReaktorFlowBuilder.kt | Traverses a Graph, creates GraphNodeLayout records with position/size, converts to compose-flow Node/Edge lists |
ReaktorFlowAssembly.kt | Resolves edges from graph semantics: attachment, navigation, data, and containment edges |
ReaktorFlowMeasurement.kt | Text-based width/height measurement (character counting × charWidthPx) |
ReaktorFlowPorts.kt | Maps graph node types to ReaktorNodeKind, assigns port colors |
ReaktorFlowLabels.kt | Derives display labels, handles UUID detection |
ReaktorFlowLayoutPolicy.kt | Graph root route detection |
3b. Layout Engine
BlueprintReaktorGraphLayoutStrategy implements a sophisticated lane-based layout:
- Services in left column(s)
- Routes in middle column(s) with attached screens to the right
- Standalone screens below
- Containers at bottom with nested child graphs
- Adaptive column counts based on node count thresholds
- Region boxes around graph boundaries with recursive layout for nested graphs
3c. Editor / Render Layer
| File | Responsibility |
|---|---|
ReaktorGraphEditor.kt | Top-level editor with keyboard shortcuts (Cmd+/− zoom), focus management |
ReaktorGraphCanvas.kt | Orchestration boundary — creates ReactFlowState, delegates to scene |
ReaktorGraphScene.kt | Wires everything: nodes/edges state, configures ReactFlow() with graph-specific types, styles, overlays |
ReaktorGraphSceneState.kt | Syncs graph changes, handles initial framing with delay, preserves dragged positions across rebuilds |
ReaktorGraphViewport.kt | Graph-specific fit-view with readable zoom bias, right-inset compensation |
ReaktorGraphOverlays.kt | Chrome composition: toolbar, legend, minimap, region overlays |
Render Components
ReaktorGraphNodeCard— Rich node cards with kind-colored title bar, port rows with dots/labels, root badge, hidden port countersReaktorGraphToolbar— Zoom controls, graph label, node/edge countsReaktorGraphLegend— Filterable node-kind legend with highlight supportReaktorGraphMiniMap— Custom minimap with viewport indicator and kind-colored nodesReaktorGraphRegions— Dashed-border region boxes with label chips
3d. Type System
| Type | Values / Fields |
|---|---|
ReaktorNodeKind | Screen (green), Route (blue), Container (purple), Service (orange), Node (gray) — each with title/body/border colors |
ReaktorEdgeKind | Attachment, Navigation, Data, Containment — each with accent color |
ReaktorGraphNodeData | nodeId, title, subtitle, graphLabel, isRootNode, port lists & counts, kind |
ReaktorGraphEdgeData | kind, label |
ReaktorGraphRegion | label, id, position, dimensions, color, depth |
ReaktorFlowGraph | Complete snapshot: nodes, edges, regions, lookup maps (graphNodes, flowIdsByNode, graphIdsByNode, graphs), style |
3e. Style System
ReaktorGraphStyle is a comprehensive tuning object with nested configs:
Canvas
Background, chrome, text colors, fonts
Layout
Column/row gaps, compact gaps, group gaps
Node
Min width, title sizing, badge sizing, padding
Port
Row height, font sizing, handle offsets, preview rows
Region
Content padding, child gaps, frame insets, label styling
Chrome
Overlay padding, panel radius, minimap sizing
Viewport
Zoom bounds, readable zoom bias, startup delay
WidthPolicy
Per-node-type width multipliers
~100 tunable parameters in total.
04 Parity Snapshot
Estimated feature parity with react-flow
Parameters on ReactFlow() composable
Hooks / composable state accessors
Missing react-flow props & callbacks
05 Detailed Gap Analysis
| Category | Feature | Status |
|---|---|---|
| Node Features | Core node model (id, position, data, type, handles, zIndex) | Done |
Custom node types via nodeTypes | Done | |
| Node dragging with zoom compensation | Done | |
| Node click handler | Done | |
| Node measurement & dimension reporting | Done | |
draggable per-node flag | Missing | |
selectable / connectable / deletable per-node | Missing | |
extent / "parent" constraint | Missing | |
expandParent | Missing | |
origin (node anchor point) | Missing | |
Built-in input / output / group types | Missing | |
| Node resizing | Missing | |
| Keyboard navigation / accessibility | Missing | |
| All remaining node events (doubleClick, drag start/stop, mouse enter/move/leave, contextMenu) | Missing | |
| Edge Features | Bezier edge rendering | Done |
| Orthogonal (step) edge rendering | Done | |
| Arrow markers (open + closed) | Done | |
| Per-edge render styles | Done | |
straight / smoothstep / simplebezier edge types | Missing | |
markerStart | Missing | |
| Edge click / hover / selection interaction | Missing | |
| Edge reconnection | Missing | |
interactionWidth | Missing | |
| Rich label content (not just String) | Missing | |
| Connection | onConnect callback | Partial |
| Drag-to-connect (handle-to-handle) | Missing | |
| Connection line rendering during drag | Missing | |
isValidConnection callback | Missing | |
| Click-to-connect mode | Missing | |
connectionRadius / connectionMode | Missing | |
| Selection | Single node/edge selection tracking | Done |
| Multi-select (shift+click) | Missing | |
| Rubber-band selection box | Missing | |
onSelectionChange | Missing | |
| Selection drag | Missing | |
| Deletion | Keyboard delete | Missing |
onDelete / onBeforeDelete | Missing | |
Configurable deleteKeyCode | Missing | |
| Viewport | Pan (drag, scroll, wheel) | Done |
| Zoom (wheel, ctrl+scroll, pinch) | Done | |
| Fit view | Done | |
| Programmatic zoom/pan/center | Done | |
| Snap-to-grid | Missing | |
translateExtent (viewport bounds) | Missing | |
| Controlled viewport mode | Missing | |
Viewport culling (onlyRenderVisibleElements) | Missing | |
| Zoom on double-click | Missing | |
| Auto-pan on drag near edge | Missing | |
| Components | Background (dots, lines, cross) | Done |
| Controls | Done | |
| MiniMap | Done | |
| Panel | Done | |
NodeResizer / NodeToolbar | Missing | |
BaseEdge / EdgeLabelRenderer | Missing | |
| Hooks / API | State management (NodesState, EdgesState, ReactFlowState) | Done |
screenToFlowPosition | Done | |
flowToScreenPosition | Missing | |
Imperative methods (addNodes, deleteElements, getIntersectingNodes) | Missing | |
useConnection, useHandleConnections, useNodeId, useKeyPress | Missing | |
| Platform | Desktop platform bridge (macOS trackpad, AWT scroll anchor) | Done |
| JS/Web react-flow interop bridge | Partial |
06 Architecture Diagram
07 Roadmap to Parity
Phase 1 — Core Interactions (Month 1–2)
- Drag-to-connect — The defining flow-editor interaction. Connection line rendering during drag, handle hit-testing,
isValidConnection,onConnect/onConnectStart/onConnectEnd. - Edge interaction — Click, hover, selection on edges. Options: hit-test on Canvas paths, invisible wider interaction overlay, or Modifier-based rendering.
- Multi-selection — Shift+click to toggle, rubber-band selection box,
onSelectionChange. - Keyboard delete — Delete/Backspace to remove selected nodes/edges.
onDelete/onBeforeDelete. - More edge types —
straight,step,smoothstep. Path generation functions are straightforward.
Phase 2 — Node Constraints & Polish (Month 2–3)
- Per-node flags —
draggable,selectable,connectable,deletableon individual nodes/edges. - Node extent / parent constraints —
extent: "parent",expandParent. Critical for sub-flows. - Edge reconnection — Drag existing edge endpoint to new handle.
- Snap-to-grid — Grid alignment during drag.
- Auto-pan — Pan viewport when dragging near canvas edges.
Phase 3 — Advanced Features (Month 3–4)
- Node resizer — Drag handles on node corners/edges to resize.
- Controlled viewport —
viewport/onViewportChangepair for external control. - Viewport culling — Only render visible nodes/edges for large graphs.
- Full imperative API — Match
useReactFlow()method surface. - Keyboard navigation — Tab through nodes/edges, Enter to select.
Phase 4 — Full Parity (Month 4–5)
NodeToolbar,EdgeLabelRenderer,BaseEdgecomponents- Connection modes (strict/loose), click-to-connect
- Z-index modes (basic/group)
- Color mode (light/dark switching)
- All remaining event callbacks (~25 missing)
08 Architectural Strengths Already in Place
Clean Separation
model (common) → runtime (common) → compose rendering (common) → platform bridges (per-target)
Immutable Data
@Immutable annotations on all models. Change-based state updates, not direct mutation.
JS Interop
Karakum-generated externals bridge to real react-flow on web. Bidirectional model conversion.
Platform Bridge
Abstraction for desktop-specific gestures. macOS trackpad already integrated via EAWT reflection.
Parity Tracking
parity/features.json with structured matrix and Gradle reportParity task built in.
Comprehensive Theming
Token-based color palette and ~60 sizing constants. Mirrors Fluent/React design-token patterns.
What reaktor-flow Needs Next
| Need | Description |
|---|---|
| Bidirectional editing | Currently read-only visualization. Needs to support node creation/deletion, edge creation, and propagate changes back to reaktor-graph. |
| Web parity via JS target | jsMain in compose-flow has react-flow interop, but reaktor-flow doesn’t have JS-specific code yet. Needed for Manna’s web app. |
| Graph mutation API | ReaktorFlowGraph is a snapshot. Need a mutable controller that can addNode(), removeNode(), addEdge(), removeEdge() and sync back to Graph. |
| Layout algorithm pluggability | Only BlueprintReaktorGraphLayoutStrategy exists. Need force-directed, hierarchical (dagre-like), and manual layout options. |
| Serialization | Save/restore graph layouts and viewport state. |