@barefootjs/xyflow
v0.3.0
Published
Signal-based xyflow wrapper for BarefootJS
Downloads
806
Maintainers
Readme
@barefootjs/xyflow
Signal-based wrapper around @xyflow/system
for BarefootJS. Ships the utility layer
(store, signal hooks, types, geometry helpers, imperative
pointer-paced subsystems). The JSX-native renderer components
(Flow, Background, Controls, MiniMap, Handle, NodeWrapper,
SimpleEdge) live in the shadcn-style registry at
ui/components/ui/xyflow/ and ship
to consumers via:
bf add xyflow # via the BarefootJS CLI
npx shadcn@latest add https://ui.barefootjs.dev/r/xyflow.jsonThis split mirrors the chart pattern (@barefootjs/chart for utility,
ui/components/ui/chart/ for JSX components).
Usage
"use client"
import { Flow, Background, Controls, MiniMap } from "@/components/ui/xyflow"
import { useNodesState, useEdgesState } from "@barefootjs/xyflow"
const initialNodes = [
{ id: "1", position: { x: 100, y: 100 }, data: { label: "Input" } },
{ id: "2", position: { x: 350, y: 50 }, data: { label: "Transform" } },
{ id: "3", position: { x: 600, y: 125 }, data: { label: "Output" } },
]
const initialEdges = [
{ id: "e1-2", source: "1", target: "2" },
{ id: "e2-3", source: "2", target: "3" },
]
export function MyCanvas() {
const [nodes, setNodes] = useNodesState(initialNodes)
const [edges, setEdges] = useEdgesState(initialEdges)
return (
<div className="w-full h-[420px]">
<Flow nodes={nodes()} edges={edges()}>
<Background variant="dots" gap={20} />
<Controls />
<MiniMap pannable zoomable />
</Flow>
</div>
)
}Custom node bodies
The default <Flow> loop renders data.label ?? id inside each
<NodeWrapper>. To compose custom node bodies, mount your own
<NodeWrapper> instances as Flow children:
<Flow nodes={nodes()} edges={edges()}>
<Background />
{nodes().map((n) => (
<NodeWrapper key={n.id} nodeId={n.id}>
<div className="rounded-md border bg-card px-3 py-2">
{n.data.label}
<Handle type="target" position={Position.Left} nodeId={n.id} />
<Handle type="source" position={Position.Right} nodeId={n.id} />
</div>
</NodeWrapper>
))}
</Flow>What this package exports
| Surface | Item | Purpose |
|---|---|---|
| Store / state | createFlowStore, FlowContext | Reactive node / edge / viewport state |
| Hooks | useFlow, useViewport, useNodes, useEdges, useNodesInitialized, useStore, screenToFlowPosition | Read store from descendants |
| React Flow shim | useNodesState, useEdgesState, useReactFlow, addEdge, reconnectEdge | Drop-in helpers for migrators |
| Geometry | computeEdgePosition, getEdgePath | Path math shared with <SimpleEdge> |
| Subsystem attach | attachFlowSubsystems | <Flow>'s ref calls this — pan / zoom / keyboard / selection rectangle / pane click |
| Subsystem attach | attachConnectionHandler, attachReconnectionHandler | <Handle> and reconnect overlay refs |
| Imperative-only | setupKeyboardHandlers, setupNodeSelection, setupSelectionRectangle, initNodeResizer | Pointer-paced primitives that JSX gives no leverage to |
| Re-exports | getBezierPath, getSmoothStepPath, getStraightPath, getConnectedEdges, getOutgoers, getIncomers, getNodesBounds, getNodesInside, getEdgeToolbarTransform, Position, MarkerType, ConnectionMode | From @xyflow/system |
| Types | FlowProps, FlowStore, InternalFlowStore, NodeBase, EdgeBase, Viewport, NodeLookup, EdgeLookup, Connection, OnConnect, OnReconnect, IsValidConnection, HandleType, … | (see src/types.ts) |
Source layout
src/
├── index.ts re-exports the utility surface above
├── store.ts createFlowStore + signal wiring
├── hooks.ts useFlow / useViewport / useNodes / ...
├── context.ts FlowContext
├── types.ts FlowProps / FlowStore / InternalFlowStore / ...
├── constants.ts SVG_NS / INFINITE_EXTENT / ...
├── utils.ts misc helpers
├── edge-path.ts computeEdgePosition / getEdgePath
├── flow-subsystems.ts attachFlowSubsystems (panZoom + ResizeObserver + ...)
├── connection.ts attachConnectionHandler / attachReconnectionHandler
├── selection.ts setupKeyboardHandlers / setupSelectionRectangle / setupNodeSelection
├── node-resizer.ts initNodeResizer (pointer-paced resize handles)
├── compat.ts React Flow API shims
└── __tests__/ store / compat / jsx-smoke unit testsJSX-native components are deliberately not in this package — they
live in ui/components/ui/xyflow/index.tsx so consumers add the
source directly into their app, can edit it, and own their own copy
(shadcn pattern). This avoids the JSX-runtime resolution headaches
that come from publishing .tsx directly from a workspace package.
Related
@xyflow/system— upstream pan/zoom + edge-path math library this package wraps.
