Skip to content

TkxFlowChart

import { TkxFlowChart, type FlowChartData } from 'tekivex-ui';

TkxFlowChart is a controlled, headless 2D graph editor: a pannable / zoomable canvas with draggable nodes, cubic-Bezier edges, click-to-select, keyboard navigation, inline rename, a right-click context menu, and a property inspector. Use it for flow diagrams, pipeline builders, state machines, or any node-and-edge surface where you own the data and the component only emits changes.

You must hold data in state and apply every onChange payload back — the component never mutates anything implicitly.

import { useState } from 'react';
import { TkxFlowChart, type FlowChartData } from 'tekivex-ui';
function Demo() {
const [graph, setGraph] = useState<FlowChartData>({
nodes: [
{ id: 'a', x: 40, y: 60, label: 'Start', color: '#00f5d4' },
{ id: 'b', x: 320, y: 60, label: 'Process' },
],
edges: [{ id: 'a-b', from: 'a', to: 'b' }],
});
return (
<TkxFlowChart
data={graph}
onChange={setGraph}
onSelect={(id) => console.log('selected', id)}
/>
);
}
PropTypeDefaultDescription
dataFlowChartDatarequiredControlled { nodes, edges } graph state.
onChange(next: FlowChartData) => voidrequiredFired on every mutation (drag, edge add, rename, delete, inspector edits). You must persist it.
selectedIdstring | nullControlled selected node id. Omit to let the component own selection internally.
onSelect(id: string | null) => voidFired on selection change.
initialViewportViewport{ x: 0, y: 0, scale: 1 }Initial pan/zoom. Uncontrolled after mount.
draggablebooleantrueAllow node drag.
pannablebooleantrueAllow canvas pan (drag empty space).
zoomablebooleantrueAllow wheel + pinch zoom.
minZoomnumber0.25Min zoom factor.
maxZoomnumber3Max zoom factor.
heightnumber480Canvas height in px. Width is always 100% of the parent.
showGridbooleantrueRender the background dot grid.
showControlsbooleantrueShow the zoom-in / fit / zoom-out / inspector toolbar.
renderNode(node: FlowNode, isSelected: boolean) => ReactNodeCustom node body renderer. Disables inline double-click rename (see gotchas).
classNamestring
styleCSSPropertiesMerged onto the container.
interface FlowNode {
id: string;
x: number; // top-left corner in graph-space
y: number;
width?: number; // default 160
height?: number; // default 60
label: string;
color?: string; // accent for border + ports + edges
data?: unknown; // free-form payload echoed back to you
}
interface FlowEdge {
id: string;
from: string; // source node id
to: string; // target node id
label?: string; // drawn at the edge midpoint
color?: string; // defaults to the source node's color
}
interface FlowChartData {
nodes: FlowNode[];
edges: FlowEdge[];
}
interface Viewport { x: number; y: number; scale: number }

Coordinates are graph-space (not screen pixels). The viewport translate + scale maps them to the screen. Edges always route from the right port of the source to the left port of the target (left-to-right reading flow).

  • Fully controlled data. data + onChange are required. Nothing moves, connects, or deletes unless you write the new state back. Dropping the onChange result on the floor makes the editor appear frozen.
  • Selection can be controlled or uncontrolled. Pass selectedId to control it; omit it and the component tracks selection internally while still firing onSelect.
  • Creating edges: drag from a node’s right-hand + port onto another node. A live dashed draft line tracks the cursor; dropping on a valid target node appends a new edge. Duplicate from→to edges are silently ignored. Edge endpoints are not draggable and edges cannot be re-routed — delete and redraw.
  • Inline rename: double-click a node to edit its label (Enter commits, Esc cancels). This only works with the default renderer — passing renderNode suppresses it because your custom body owns the double-click.
  • Keyboard model (focus the canvas first):
    • Tab / Shift+Tab — cycle node selection (Tab with nothing selected selects the first node).
    • Arrow keys — nudge the selected node by 1px; Shift + arrow = 10px.
    • Delete / Backspace — if an edge is selected, removes just that edge; otherwise removes the selected node and all connected edges.
  • Edge selection takes Delete priority. Click an edge to select it (node selection is cleared) so Delete targets the edge, not a node.
  • Context menu: right-click a node for Rename / Duplicate / Bring-to-front / Delete. All actions go through onChange.
  • Zoom anchoring: wheel and pinch zoom keep the point under the cursor/pinch-center fixed. The fit button () frames all nodes.
  • touchAction is set to none when pan or zoom is enabled, so the component owns touch gestures inside its bounds.