PHP code example of codenzia / filament-diagrammer
1. Go to this page and download the library: Download codenzia/filament-diagrammer library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
codenzia / filament-diagrammer example snippets
declare(strict_types=1);
namespace App\Filament\Pages;
use Codenzia\FilamentDiagrammer\Components\DiagramCanvas;
use Codenzia\FilamentDiagrammer\Components\DiagramConnection;
use Codenzia\FilamentDiagrammer\Components\DiagramNode;
use Codenzia\FilamentDiagrammer\Enums\ConnectionEndpoint;
use Codenzia\FilamentDiagrammer\Enums\ConnectorType;
use Codenzia\FilamentDiagrammer\Pages\Diagram;
class MyDiagram extends Diagram
{
protected static ?string $title = 'My Diagram';
protected function getDiagramCanvas(): DiagramCanvas
{
return DiagramCanvas::make()
->grid(enabled: true, size: 20, type: 'dots')
->zoom(enabled: true, min: 0.1, max: 3.0, step: 0.05)
->snapToGrid()
->defaultConnector(ConnectorType::BEZIER)
->nodes($this->getNodes())
->connections($this->getConnections());
}
protected function getNodes(): array
{
return [
DiagramNode::make('start')
->label('Start')
->type('Process')
->position(100, 100)
->color('#22c55e')
->sourceEndpoints([ConnectionEndpoint::BOTTOM]),
DiagramNode::make('end')
->label('End')
->type('Process')
->position(400, 300)
->color('#3b82f6')
->targetEndpoints([ConnectionEndpoint::TOP]),
];
}
protected function getConnections(): array
{
return [
DiagramConnection::make('start', 'end')
->label('Flow')
->connector(ConnectorType::BEZIER)
->animated(),
];
}
}
declare(strict_types=1);
namespace App\Diagram\NodeTypes;
use Codenzia\FilamentDiagrammer\Enums\NodeShape;
use Codenzia\FilamentDiagrammer\NodeTypes\BaseNodeType;
use Filament\Forms\Components\TagsInput;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
class GoalNode extends BaseNodeType
{
public static function label(): string
{
return 'Goal';
}
public static function icon(): ?string
{
return 'heroicon-o-flag';
}
public static function defaultColor(): ?string
{
return '#22c55e';
}
public static function defaultShape(): NodeShape
{
return NodeShape::RECTANGLE;
}
// Filament schema components for the body section
public static function bodySchema(): array
{
return [
TextEntry::make('description')
->hiddenLabel()
->size('xs')
->color('gray'),
];
}
// Filament form components for the edit slide-over
public static function editFormSchema(): array
{
return [
TextInput::make('label')->label('Title')->
use App\Diagram\NodeTypes\GoalNode;
DiagramNode::make('goal-1')
->label('Customer Experience')
->type(GoalNode::class) // Schemas resolved from class
->position(100, 200)
->data([
'description' => 'Improve NPS score by 20 points',
'tags' => ['Customer', 'CX'],
'progress' => 60.0,
]);
use App\Models\Kpi;
use App\Diagram\NodeTypes\KpiNode;
protected function getNodes(): array
{
return Kpi::all()->map(fn (Kpi $kpi) =>
DiagramNode::make("kpi-{$kpi->id}")
->label($kpi->title)
->type(KpiNode::class)
->record($kpi) // Components resolve from model attributes
)->toArray();
}
public static function bodySchema(): array
{
return [
TextEntry::make('description'), // Reads $kpi->description
TagEntry::make('tags'), // Reads $kpi->tags (relationship or cast)
];
}
use Codenzia\FilamentDiagrammer\Components\DiagramCanvas;
use Codenzia\FilamentDiagrammer\Components\DiagramConnection;
use Codenzia\FilamentDiagrammer\Components\DiagramNode;
use Codenzia\FilamentDiagrammer\Enums\ConnectionEndpoint;
use Codenzia\FilamentDiagrammer\Enums\ConnectorType;
use Codenzia\FilamentDiagrammer\Enums\HeaderStyle;
use Filament\Forms\Components\TagsInput;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
protected function getDiagramCanvas(): DiagramCanvas
{
return DiagramCanvas::make()
->snapToGrid()
->defaultConnector(ConnectorType::STRAIGHT)
->nodes($this->getClassNodes())
->connections($this->getClassConnections());
}
protected function getClassNodes(): array
{
// Pre-compute display HTML to avoid Filament TextEntry array-state limitations
$fmtProps = fn (array $props): string => collect($props)
->map(fn ($p) => '<div class="font-mono py-0.5 text-gray-700 dark:text-gray-300">'.e($p).'</div>')
->join('');
$fmtMethods = fn (array $methods): string => collect($methods)
->map(fn ($m) => '<div class="font-mono py-0.5 text-violet-600 dark:text-violet-400">'.e($m).'</div>')
->join('');
$makeNode = fn (string $id, string $label, array $properties, array $methods, float $x, float $y) =>
DiagramNode::make($id)
->label($label)
->type('Class')
->color('#3b82f6')
->icon('heroicon-o-code-bracket')
->headerStyle(HeaderStyle::MAC)
->position($x, $y)
->size(260)
->sourceEndpoints([ConnectionEndpoint::RIGHT, ConnectionEndpoint::BOTTOM])
->targetEndpoints([ConnectionEndpoint::LEFT, ConnectionEndpoint::TOP])
->bodySchema([
TextEntry::make('properties_html')->hiddenLabel()->html()->size('xs'),
])
->footerSchema([
TextEntry::make('methods_html')->hiddenLabel()->html()->size('xs'),
])
->editFormSchema([
TextInput::make('label')->label('Class Name')->
DiagramCanvas::make()
// ─── Layout ───────────────────────────────────────────────
->height('70vh')
->background('#f8fafc') // Light mode background (null = auto)
->canvasDarkBackground('#1a1b1e') // Dark mode background (null = auto)
// ─── Grid ─────────────────────────────────────────────────
->grid(enabled: true, size: 20, color: null, type: 'dots')
->gridDarkColor('#2a2b2e') // Grid color for dark mode
->snapToGrid(true)
// ─── Zoom & Pan ──────────────────────────────────────────
->zoom(enabled: true, min: 0.1, max: 3.0, step: 0.05, default: 1.0)
->panEnabled(true)
// ─── Toolbar ─────────────────────────────────────────────
->toolbar(enabled: true, position: 'top')
->undoRedo(true) // Undo/redo buttons (Ctrl+Z / Ctrl+Y)
->save(true) // Save button (Ctrl+S) with dirty indicator
->export(true) // Export dropdown (PNG/PDF with theme choice)
->zoomControls(true)
->zoomControlsPosition(ZoomControlsPosition::BOTTOM_RIGHT) // TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, FLOAT, DOCKED
->fitView(true)
->fitViewPadding(60) // Padding around nodes when fitting
// ─── Interactivity ───────────────────────────────────────
->readOnly(false)
->keyboardShortcuts(true)
->multiSelect(true)
->interactionModeToggle(true) // Show pan/select mode toggle in toolbar
->defaultInteractionMode('pan') // 'pan' or 'select' — default left-click drag behavior
->dragToConnect() // Enable drag port-to-port connections
->newConnectionDefaults([...]) // Default props for new connections
->autoOpenConnectionEditor() // Open editor after new connection
->defaultConnector(ConnectorType::BEZIER)
// ─── Context Menu ────────────────────────────────────────
->contextMenu(true) // Right-click context menu
->contextMenuItems([ // Custom menu items
ContextMenuItem::make('export-node')
->label('Export as JSON')
->icon('heroicon-o-arrow-down-tray')
->group('node')
->wireMethod('exportNodeAsJson'),
])
// ─── Alignment Guides ────────────────────────────────────
->alignmentGuides(true) // Snap-to-alignment guides during drag
->alignmentThreshold(5) // Snap distance in pixels
// ─── Minimap ─────────────────────────────────────────────
->minimap(true) // Show minimap overview
->minimapPosition('bottom-right') // bottom-right, bottom-left, top-right, top-left
// ─── Connection Styling ──────────────────────────────────
->connectionColor('#9ca3af') // Light mode stroke
->connectionDarkColor('#6b7280') // Dark mode stroke
->connectionHoverColor('#f59e0b') // Hover highlight
->connectionHoverWidth(3) // Stroke width on hover
->connectionArrowSize(10) // Arrow head size
->connectionArrowFoldback(0.8) // 0.0 = flat, 1.0 = sharp point
// ─── Endpoints ───────────────────────────────────────────
->endpointType('Dot') // 'Dot', 'Rectangle', or 'Blank'
->endpointRadius(2)
// ─── Selection ───────────────────────────────────────────
->selectionColor('#f59e0b') // Border/glow color for selected nodes
// ─── Node Defaults ───────────────────────────────────────
->nodeDefaultWidth(240)
->nodeDefaultHeight(200) // null = auto (content-driven)
->contentSizing('auto') // 'auto', 'fit', or 'clip'
// ─── Auto Layout ─────────────────────────────────────────
->autoLayoutHGap(60) // Horizontal gap between node edges (px)
->autoLayoutVGap(60) // Vertical gap between levels (px)
// ─── Data ────────────────────────────────────────────────
->nodes([...])
->connections([...])
// ─── Actions (Filament Actions) ──────────────────────────
->headerActions([...])
->toolbarActions([...])
->footerActions([...])
// ─── Lifecycle Callbacks ─────────────────────────────────
->onNodeCreate(fn ($nodeId) => ...)
->onNodeDelete(fn ($nodeId) => ...)
->onNodeMove(fn ($nodeId, $x, $y) => ...)
->onConnectionCreate(fn ($sourceId, $targetId) => ...)
->onConnectionDelete(fn ($sourceId, $targetId) => ...)
->onSave(fn ($nodes, $connections) => ...);
DiagramNode::make('node-1')
// ─── Basic ───────────────────────────────────────────────
->label('My Node')
->type(GoalNode::class) // NodeType class or plain string
->position(100, 200) // Optional — auto-layout if omitted
->size(width: 240, height: null) // Height auto-sizes by default
->autoFit() // Width adapts to content
->shape(NodeShape::RECTANGLE)
->color('#3b82f6') // Accent color (header tint)
->borderColor('#e5e7eb')
->icon('heroicon-o-bolt')
// ─── Header Styling ──────────────────────────────────────
->headerBackgroundColor('#1e40af') // Custom header background
->headerStyle(HeaderStyle::MAC) // none, windows, mac, custom
->footerBackgroundColor('#f1f5f9') // Custom footer background
// ─── Behavior ────────────────────────────────────────────
->draggable(true) // Can user drag this node?
->selectable(true) // Can user click to select?
->deletable(true) // Show X button & allow Delete key?
->connectable(true) // Show connection endpoints?
->resizable(false) // Allow resize handles?
// ─── Connection Endpoints ────────────────────────────────
->sourceEndpoints([ConnectionEndpoint::BOTTOM, ConnectionEndpoint::RIGHT])
->targetEndpoints([ConnectionEndpoint::TOP, ConnectionEndpoint::LEFT])
// ─── Sections (Filament Schemas) ─────────────────────────
->headerSchema([...]) // Or resolved from NodeType
->bodySchema([...])
->footerSchema([...])
->leftSidebarSchema([...])
->rightSidebarSchema([...])
->editFormSchema([...]) // Edit slide-over form (inline, no NodeType needed)
// ─── Section Actions ─────────────────────────────────────
->headerActions([...])
->footerActions([...])
// ─── Data (backing state for schemas) ────────────────────
->record($eloquentModel) // Bind an Eloquent model directly
->data([ // Or provide data manually (overrides record)
'description' => 'Some description',
'tags' => ['Tag1', 'Tag2'],
'progress' => 75.0,
])
// ─── Callbacks ───────────────────────────────────────────
->onClick(fn ($nodeId) => ...)
->onDoubleClick(fn ($nodeId) => ...)
// ─── Extra HTML Attributes ───────────────────────────────
->extraAttributes(['data-priority' => 'high']);
// These nodes will be auto-positioned
DiagramNode::make('a')->label('A')->type(GoalNode::class),
DiagramNode::make('b')->label('B')->type(GoalNode::class),
DiagramNode::make('c')->label('C')->type(GoalNode::class),
use Codenzia\FilamentDiagrammer\Contracts\NodeType;
use Codenzia\FilamentDiagrammer\Enums\NodeShape;
interface NodeType
{
public static function label(): string;
public static function description(): ?string; // Shown in palette help tooltip
public static function icon(): ?string;
public static function defaultColor(): ?string;
public static function defaultShape(): NodeShape;
public static function defaultWidth(): ?float;
public static function headerSchema(): array;
public static function bodySchema(): array;
public static function footerSchema(): array;
public static function leftSidebarSchema(): array;
public static function rightSidebarSchema(): array;
public static function editFormSchema(): array;
}
use Codenzia\FilamentDiagrammer\Concerns\HasDiagram;
class MyPage extends Page implements HasActions, HasForms
{
use HasDiagram;
use InteractsWithActions;
use InteractsWithForms;
// Required: define the canvas configuration
protected function getDiagramCanvas(): DiagramCanvas { ... }
// Required for an editable diagram: the plugin fails closed, so without
// this override every diagram mutation is rejected with a 403
protected function canEditDiagram(): bool
{
return auth()->user()?->can('update', $this->record) ?? false;
}
// Optional: customize the node edit form (opens in slide-over)
// Note: if a node has a NodeType with editFormSchema(), that is used instead
protected function getNodeFormSchema(): array
{
return [
TextInput::make('title')->el
}
}
DiagramCanvas::make()
->background('#ffffff') // Light mode
->canvasDarkBackground('#0f172a') // Dark mode
->gridColor('#e5e7eb') // Light grid
->gridDarkColor('#1e3a5f'); // Dark grid
DiagramCanvas::make()
->undoRedo(true); // Enabled by default
DiagramCanvas::make()
->save(true) // Enabled by default
->onSave(fn (array $nodes, array $connections) => /* persist to DB */);
// Eloquent model with a JSON column
->onSave(fn ($nodes, $connections) => $this->diagram->update([
'state' => ['nodes' => $nodes, 'connections' => $connections],
]))
// Simple JSON file (suitable for prototypes / demos)
->onSave(fn ($nodes, $connections) => file_put_contents(
storage_path('app/diagram.json'),
json_encode(compact('nodes', 'connections'))
))
DiagramCanvas::make()
->export(true); // Enabled by default
use Codenzia\FilamentDiagrammer\Enums\ZoomControlsPosition;
DiagramCanvas::make()
->zoomControlsPosition(ZoomControlsPosition::BOTTOM_RIGHT); // Default
DiagramCanvas::make()
->contextMenu(true) // Enabled by default
use Codenzia\FilamentDiagrammer\Components\ContextMenuItem;
DiagramCanvas::make()
->contextMenuItems([
ContextMenuItem::make('export-json')
->label('Export as JSON')
->icon('heroicon-o-arrow-down-tray')
->group('node') // 'node', 'connection', or 'canvas'
->wireMethod('exportNodeAsJson') // Livewire method to call
->shortcut('Ctrl+E')
->sort(50),
ContextMenuItem::make('highlight')
->label('Highlight Node')
->group('node')
->wireMethod('highlightNode'),
]);
DiagramCanvas::make()
->multiSelect(true)
DiagramCanvas::make()
->interactionModeToggle(true) // Show the toggle (default: true)
->defaultInteractionMode('pan') // 'pan' or 'select' (default: 'pan')
DiagramCanvas::make()
->alignmentGuides(true) // Disabled by default
->alignmentThreshold(5) // Snap distance in pixels (default: 5)
$canvas = DiagramCanvas::make()
->beforeConnectionCreate(function (string $sourceId, string $targetId, ?string $sourcePort): bool {
// Return false to reject the connection
if ($sourceId === $targetId) {
return false;
}
return true;
});
class TriggerNodeType extends BaseNodeType
{
// Only accept connections from these node types
public static function allowedInputTypes(): array
{
return []; // empty = accept any (default)
}
// Only allow connections to these node types
public static function allowedOutputTypes(): array
{
return [ConditionNodeType::class, ActionNodeType::class];
}
// Limit the number of incoming connections
public static function maxInputConnections(): ?int
{
return 0; // trigger nodes have no inputs
}
// Limit the number of outgoing connections
public static function maxOutputConnections(): ?int
{
return null; // null = unlimited
}
}
js
// Export as PNG with current theme
exportAs('png', 'current');
// Export as PDF in light mode
exportAs('pdf', 'light');
// Export as PNG in dark mode
exportAs('png', 'dark');
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.