SAI Nodes

๐Ÿš€ A Fully Customizable Node-Based Editor for Flutter

SAI Nodes is a lightweight, scalable, and highly customizable Flutter package for building interactive, node-based user interfaces.

Whether you're building tools for developers, designers, or end-users, SAI Nodes provides the building blocks for:

๐Ÿ’ก Use Cases

  • ๐ŸŽฎ Visual Scripting Editors โ€“ Game logic, automation flows, or state machines.

  • ๐Ÿ›  Workflow & Process Designers โ€“ Business rules, decision trees, and automation paths.

  • ๐ŸŽจ Shader & Material Graphs โ€“ Build custom shaders visually.

  • ๐Ÿ“Š Dataflow Tools โ€“ ETL pipelines, AI workflows, or processing graphs.

  • ๐Ÿค– ML Architecture Visualizers โ€“ Visualize and configure neural networks.

  • ๐Ÿ”Š Modular Audio Systems โ€“ Synthesizers, effect chains, or sequencing tools.

  • ๐Ÿง  Graph-Based UIs โ€“ Mind maps, dependency trees, and hierarchical structures.


๐ŸŒŸ Features

  • โœ… Customizable UI โ€“ Fully override widgets, ports, fields, and layout logic.

  • ๐Ÿ’พ Pluggable Storage โ€“ Save/load projects through JSON with full control over serialization.

  • โšก Optimized Performance โ€“ Hardware-accelerated rendering, efficient hit testing, and rebuild minimization.

  • ๐Ÿ”— Flexible Graph System โ€“ Directional edges, typed ports, data links, control links, and more.

  • ๐Ÿงฉ Compound Editing Operations โ€“ Insert a node into an existing flow as one undoable operation and organize nodes in movable, resizable frames.

  • ๐Ÿ“ Scalable Architecture โ€“ Suitable for lightweight diagrams and complex editors.

  • ๐ŸŒ Localization Support โ€“ Easily adapt node-based UIs to multiple languages.

  • ๐ŸŽจ Lightweight & Elegant โ€“ Minimal dependencies, styling hooks, and a compact public API.

  • ๐Ÿ›ก๏ธ Reliable Controller โ€“ Safe project resets, invalid endpoint handling, stale-selection cleanup, and duplicate-link protection.


๐Ÿ›  Roadmap

The package is being developed as a reusable foundation for workflow, shader, and dataflow editors. Here's what's next:

โš™๏ธ Performance Enhancements

  • Static Branch Precomputation โ€“ Improve runtime by detecting and collapsing static branches in execution graphs.

๐Ÿ“š Documentation Improvements

  • Expanded API documentation and usage examples.

  • Guides for building workflow, shader, audio, and dataflow tools.

๐ŸŽ› General-Purpose Flexibility

  • ๐Ÿค– Node Configuration State Machine โ€“ Dynamically add or remove ports and fields on nodes at runtime, allowing node structure to adapt to current links and input data.

  • โ™ป๏ธ Reusable Graph Macros โ€“ Define, save, and reuse templates made up of multiple nodes.

  • ๐ŸŽฉ Enhanced Editor Mode โ€“ Add advanced, opt-in editing tools and productivity shortcuts.


๐Ÿ“ธ Preview

SAI Nodes node editor preview


๐Ÿ“š Quickstart Guide

For a fast start, follow the installation and usage examples below. More complete examples will be added as the editor API grows.


๐Ÿ“ฆ Installation

To add SAI Nodes to your Flutter project, include it in your pubspec.yaml:

dependencies:
  sai_nodes: ^0.3.0

Then, run:

flutter pub get

๐Ÿ› ๏ธ Usage

Import the package in your Dart file:

import 'package:sai_nodes/sai_nodes.dart';

Create a controller and add the editor to your widget tree:

final controller = NodeEditorController();

NodeEditorWidget(
  controller: controller,
  expandToParent: true,
  overlay: () => const <OverlayData>[],
);

The package declares its grid shader as a package resource. The consuming application does not need to redeclare it:

flutter:
  uses-material-design: true

For custom graphs, register NodePrototype instances with typed data or control ports and provide field, header, port, node, or context-menu builders as needed.

Generic editor extensions

NodeEditorWidget.nodeEditorMenuBuilder enables the built-in searchable and collapsible canvas menu:

NodeEditorWidget(
  controller: controller,
  overlay: () => const <OverlayData>[],
  nodeEditorMenuBuilder: (context, position) => [
    const NodeEditorMenuAction(label: 'Create node'),
    const NodeEditorMenuDivider(),
    NodeEditorMenuSection(
      label: 'View',
      entries: [
        NodeEditorMenuAction(
          label: 'Reset zoom',
          onSelected: controller.resetViewport,
        ),
      ],
    ),
  ],
);

Use nodeMenuBuilder for the same menu surface on individual nodes. Both builders return NodeEditorMenuEntry values, including actions, dividers, and nested sections. With the menu focused, Up/Down moves between enabled actions and Enter activates the highlighted action.

Set NodeEditorConfig.enableNodeResize to show the built-in resize handle, or use NodeResizeBuilder for an application-specific handle. Node instance titles and fixed sizes are available as NodeDataModel.customTitle and NodeDataModel.customSize, and are included in node JSON. Link endpoints are available as link.endpoints.sourceNodeId, link.endpoints.sourcePortId, link.endpoints.targetNodeId, and link.endpoints.targetPortId. Optional link labels are available as link.label and can be changed with NodeEditorController.setLinkLabel.

The controller also exposes reusable editor primitives for application hosts:

  • navigateSelection moves to the nearest node in a direction.
  • contentRevision changes only for persisted graph mutations.
  • screenToWorld, worldToScreen, and visibleWorldBounds share the editor's viewport math.
  • applyLayout applies several node positions as one undoable operation.
  • spliceNodeIntoLink inserts a detached node between compatible flow endpoints as one undoable operation.
  • createFrame, moveFrame, resizeFrame, and frame membership methods provide generic editor-owned grouping primitives.
  • clipboardPayloadEncoder and clipboardPayloadDecoder allow a host to carry JSON-compatible metadata alongside the package-owned node payload.

๐Ÿงฉ Examples & Demo

Explore the repository for the package source, tests, and current integration examples:


๐Ÿ•น๏ธ Current Input Support

Legend:

  • โœ… Supported
  • โŒ Unsupported
  • โš ๏ธ Partial
  • ๐Ÿงช Untested
๐Ÿ–ฅ๏ธ Desktop and ๐Ÿ’ป laptop Windows Linux macOS
native/mouse โœ… โœ… โœ…
native/trackpad โœ… โš ๏ธ โœ…
web/mouse โœ… โœ… โœ…
web/trackpad โš ๏ธ โš ๏ธ โš ๏ธ
๐Ÿ“ฑ Mobile Android iOS
native โœ… ๐Ÿงช
web โœ… ๐Ÿงช

๐Ÿ“œ License

SAI Nodes is open-source and released under the MIT License. Contributions are welcome!


๐Ÿ™Œ Contributing

We'd love your help in making SAI Nodes even better! You can contribute by:

  • ๐Ÿ’ก Suggesting new features

  • ๐Ÿ› Reporting bugs

  • ๐Ÿ”ง Submitting pull requests

  • ๐Ÿ‘ Sharing what you've built

Feel free to file an issue or contribute directly on GitHub.


๐Ÿš€ Let's Build Together!

Enjoy using SAI Nodes and create amazing node-based UIs for your Flutter apps! ๐ŸŒŸ

Libraries

sai_nodes