Flow
A visual flowchart and workflow editor based on Alpine Flow. Build flow diagrams, DAGs, and node-based UIs with zoom, pan, and drag-and-drop.
Basic Usage
A simple flow with nodes and edges:
Drag to pan, scroll to zoom, use the toolbar at bottom-left.
<neura::flow :nodes="$nodes" :edges="$edges" height="400px" />
Workflow Example
A workflow with multiple nodes and branches (validate, reject, approve):
$nodes = [
['id' => 'w1', 'type' => 'step', 'data' => ['label' => 'Submit', 'description' => 'Form sent']],
['id' => 'w2', 'type' => 'step', 'data' => ['label' => 'Review', 'description' => 'Check data']],
['id' => 'w3', 'type' => 'step', 'data' => ['label' => 'Approved', 'description' => 'Validation OK']],
['id' => 'w4', 'type' => 'step', 'data' => ['label' => 'Rejected', 'description' => 'Needs correction']],
['id' => 'w5', 'type' => 'step', 'data' => ['label' => 'Complete', 'description' => 'Done']],
];
$edges = [
['source' => 'w1', 'target' => 'w2'],
['source' => 'w2', 'target' => 'w3'],
['source' => 'w2', 'target' => 'w4'],
['source' => 'w3', 'target' => 'w5'],
['source' => 'w4', 'target' => 'w1'],
];
<neura::flow :nodes="$nodes" :edges="$edges" height="450px" />
Empty Flow
An empty editor with toolbar to add nodes via the UI:
<neura::flow :nodes="[]" :edges="[]" height="350px" />
Custom Node Types
Define your own node types via the
nodeDefinitions slot and the x-node directive:
<neura::flow :nodes="$nodes" :edges="$edges">
<x-slot:nodeDefinitions>
<div
x-node="{ type: 'customNode', deletable: true, allowBranching: true }"
x-data="{ props: { title: '', status: 'pending' } }"
>
<div x-ignore>
<div class="rounded-lg bg-primary-100 dark:bg-primary-900/30 px-4 py-2 border border-primary-200 dark:border-primary-800">
<span class="font-medium" x-text="props.title"></span>
<span class="text-xs ml-2" x-text="props.status"></span>
</div>
</div>
</div>
</x-slot:nodeDefinitions>
</neura::flow>
$nodes = [
['id' => '1', 'type' => 'customNode', 'data' => ['title' => 'My node', 'status' => 'active']],
];
Zoom and Pan Options
Customize editor behavior:
<neura::flow
:nodes="$nodes"
:edges="$edges"
height="500px"
:minZoom="0.25"
:maxZoom="3"
:panOnScroll="true"
:panOnDrag="true"
:zoomOnWheelScroll="false"
:zoomOnPinch="true"
:autoCenter="true"
toolbarClasses="bottom left"
backgroundClasses="dots"
/>
Data Structure
// Node
[
'id' => 'unique-id', // Required: unique identifier
'type' => 'step', // Required: node type (must match a registered x-node)
'data' => [ // Required: persisted data (synced with node props)
'label' => 'Title',
'description' => '...',
// ... custom properties
],
]
// Edge (connection between two nodes)
[
'source' => 'source-node-id',
'target' => 'target-node-id',
]
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| nodes | array | [] | Initial nodes |
| edges | array | [] | Connections (source, target) |
| height | string | 500px | Container height |
| minZoom | number | 0.5 | Minimum zoom level |
| maxZoom | number | 2 | Maximum zoom level |
| panOnScroll | boolean | true | Pan on scroll |
| panOnDrag | boolean | true | Pan on drag |
| zoomOnWheelScroll | boolean | false | Zoom with wheel (otherwise pan) |
| zoomOnPinch | boolean | true | Zoom on pinch (mobile) |
| autoCenter | boolean | true | Center the graph in view on load |
| toolbarClasses | string | bottom left | Toolbar position |
| backgroundClasses | string | dots | Background style (dots, grid, etc.) |
Alpine Flow Events
Alpine Flow dispatches global events you can listen to:
| Event | Payload | Description |
|---|---|---|
| @flow-init.window | { data: true } | Editor initialized |
| @flow-new-node-rendered.window | { data: 'node-id' } | New node rendered |
| @flow-nodes-deleted.window | { data: [id1, id2] } | Nodes deleted |
<div @flow-init.window="console.log('Flow ready')">
<neura::flow :nodes="$nodes" :edges="$edges" />
</div>
flowEditor API
To access the editor and its methods (addNode, deleteNode, toObject, etc.), capture a reference via
x-init:
<div x-data="{ editor: null }">
<div
x-init="editor = $el._x_dataStack?.[0]"
x-data="flowEditor({ nodes: [], edges: [] })"
style="height: 500px"
></div>
<button @click="editor.addNode({ id: 'new-1', type: 'step', data: {} })">
Add node
</button>
<button @click="console.log(editor.toObject())">
Export (nodes, edges, viewport)
</button>
</div>
Resources
Flow is built on @copyfactory/alpine-flow. See the repo for the full API and advanced examples.
The component requires
@copyfactory/alpine-flow. Alpine.js is provided by Livewire. Install dependencies with:
php artisan neura-kit:install-deps