@statelyai/flow-react
v0.6.0
Published
Thin React adapter for @statelyai/flow with core and DOM re-exports.
Maintainers
Readme
@statelyai/flow-react
Thin React adapter for @statelyai/flow with core and DOM re-exports.
Philosophy
@statelyai/flow-react should be completely event-driven and composable. React should not hide a second flow model behind component internals; it should adapt the same FlowInstance that consumers can create, inspect, subscribe to, and trigger directly. It re-exports the lower layers so React consumers can install and import from one package.
The adapter abstracts over two lower layers:
@statelyai/flowowns the graph, viewport, selection, interaction state, semantic events, and derived engine queries.@statelyai/flow-domowns browser-only measurement and container attachment.
The React package owns React lifecycle, context, selector subscriptions, and a convenience renderer. It should be flexible enough for consumers to build their own stateful flow component from the instance alone.
Optimization is part of the architecture, not a later cleanup pass. Components should subscribe only to the data they actually render or use for derived work. For example, an edge layer should not subscribe to the entire store when it only needs edges, viewport, edge-path inputs, and selected edge ids.
The graph data structure is the source of truth for graph content, not for transient UI state. Core node and edge data should not grow flags like selected: true or dragging: true; selection, focus, dragging, hover, connection state, and similar interaction state live in the flow store and are derived into render props such as selected or dragging.
DOM measurement is one-directional by default. Nodes, ports, and edge labels report their inherent rendered size back to the engine, but default renderers should not apply measured width or height back onto the same DOM entities. Consumers can opt into controlled sizing for custom components, but the built-in DOM path should avoid measurement feedback loops.
Core API
| Export | Description |
| ------------------------------------- | -------------------------------------------------------------------------------- |
| createFlowInstance(options) | Creates the shared instance used by React and custom renderers |
| useFlow(options) | TipTap-style hook for creating a stable flow controller |
| useCreateFlowInstance(options) | React lifecycle hook for creating an instance and attaching listeners |
| useFlowSelector(selector, options?) | Subscribe to any part of the flow store from React |
| useFlowValue(selector, isEqual?) | Short selector hook for the nearest provider |
| useFlowContext() | Subscribe to the full flow store context |
| useFlowNode(id, selector?, isEqual?) | Subscribe to node data plus derived render fields |
| useFlowEdge(id, selector?, isEqual?) | Subscribe to edge data plus derived render fields |
| useFlowPort(id, selector?, isEqual?) | Subscribe to port data plus derived render fields |
| useFlowViewport() | Subscribe to viewport state |
| useFlowMeasurement(id) | Subscribe to measured bounds for an addressable |
| FlowInstanceProvider | Provides a FlowInstance through React context |
| useFlowInstance() | Reads the nearest FlowInstance |
| useOptionalFlowInstance() | Reads the nearest FlowInstance or returns null |
| StatelyFlow | Convenience component that renders nodes, edges, backgrounds, and overlays |
| FlowColorModeScope | Applies the current flow color mode as DOM data attributes and color-scheme |
| useFlowColorMode() | Reads the store color mode and resolves system to light or dark |
| useApplyFlowColorMode(element) | Applies flow color mode attributes to an existing DOM element from inside a flow |
@statelyai/flow-react/backgrounds exports Background, DotsBackground, LinesBackground, and CrossBackground helpers for viewport-aware canvas backgrounds. Backgrounds are plain React components, so consumers can also build custom ones with useFlowSelector((context) => context.viewport).
Color mode is store data, not engine behavior. @statelyai/flow-dom exports small helpers for resolving and applying light, dark, and system, while React exposes hooks/components that make those values easy to use with CSS variables.
Usage
import {
createEdge,
createGraph,
createNode,
StatelyFlow,
useFlow,
useFlowSelector,
} from "@statelyai/flow-react";
const graph = createGraph({
nodes: [
createNode({ id: "a", x: 0, y: 0, data: { label: "Start" } }),
createNode({ id: "b", x: 240, y: 120, data: { label: "Done" } }),
],
edges: [createEdge({ id: "a-b", sourceId: "a", targetId: "b" })],
});
function Flow() {
const flow = useFlow({
graph,
settings: {
store: { snapToGrid: true, snapGrid: [16, 16] },
},
listeners: [
{
selector: (context) => context.selection.size,
onChange: (selectionSize) => {
console.log("selection size", selectionSize);
},
},
],
});
return (
<StatelyFlow
flow={flow}
graph={graph}
renderNode={({ node, selected }) => (
<div data-selected={selected}>{node.data?.label ?? node.id}</div>
)}
/>
);
}Storybook
pnpm --filter @statelyai/flow-react storybook