192 lines
7.1 KiB
Markdown
192 lines
7.1 KiB
Markdown
# NodeEditor.js API Documentation
|
|
|
|
`NodeEditor.js` is a lightweight, framework-agnostic, zero-dependency node editor library written in pure ES6 JavaScript. It leverages standard DOM elements for high-performance node manipulation and an SVG overlay plane for drawing scalable Bezier connections.
|
|
|
|
---
|
|
|
|
## 🚀 Quick Start
|
|
|
|
### 1. HTML Setup
|
|
Create a dedicated target container for the editor. Ensure the container has explicit dimensional bounds (`width` and `height`).
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Node Editor Instance</title>
|
|
<style>
|
|
body { margin: 0; background: #111; }
|
|
#editor-container {
|
|
width: 100vw;
|
|
height: 100vh;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div id="editor-container"></div>
|
|
|
|
<script type="module" src="./app.js"></script>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
### 2. JavaScript Initialization (`app.js`)
|
|
Import the `NodeEditor` module, hook it to your DOM node, and instantiate your first pipeline.
|
|
|
|
```javascript
|
|
import { NodeEditor } from './NodeEditor.js';
|
|
|
|
// 1. Initialize the UI Engine
|
|
const container = document.getElementById('editor-container');
|
|
const editor = new NodeEditor(container);
|
|
|
|
// 2. Extract the State Manager
|
|
const graph = editor.getGraphManager();
|
|
|
|
// 3. Spawning Nodes
|
|
const nodeA = graph.addNode({
|
|
type: 'source_node',
|
|
title: 'Data Stream',
|
|
x: 100,
|
|
y: 150,
|
|
inputs: [],
|
|
outputs: [{ id: 'out_raw', name: 'Raw Buffer' }]
|
|
});
|
|
|
|
const nodeB = graph.addNode({
|
|
type: 'processing_node',
|
|
title: 'Transform Matrix',
|
|
x: 450,
|
|
y: 250,
|
|
inputs: [{ id: 'in_data', name: 'Payload' }],
|
|
outputs: [{ id: 'out_success', name: 'Success' }]
|
|
});
|
|
|
|
// 4. Create a programmatically driven wire connection
|
|
graph.connect(nodeA.id, 'out_raw', nodeB.id, 'in_data');
|
|
```
|
|
|
|
---
|
|
|
|
## 🛠️ Architecture Overview
|
|
|
|
The library enforces a strict separation of concerns via an asynchronous, decoupled state cycle:
|
|
|
|
```
|
|
[User Action / UI Pointer Interaction]
|
|
│
|
|
▼
|
|
[GraphManager State Engine] ◄─── (Single Source of Truth)
|
|
│
|
|
▼ (Dispatches Event Hub Actions)
|
|
[NodeEditor Render Architecture]
|
|
│
|
|
┌──────────┴──────────┐
|
|
▼ ▼
|
|
[DOM Element Nodes] [SVG Vector Overlay Patches]
|
|
```
|
|
|
|
|
|
---
|
|
|
|
## 📚 API Reference
|
|
|
|
### `NodeEditor` (UI Controller)
|
|
|
|
The wrapper orchestration manager that structures layout elements, listens to user viewport transforms, and monitors state bindings.
|
|
|
|
* **`new NodeEditor(containerElement)`**
|
|
Instantiates a fresh node pipeline map inside a target DOM container.
|
|
* **`editor.getGraphManager()`**
|
|
Returns the underlying data `GraphManager` engine operating behind the target instance.
|
|
* **`editor.updateAllConnections()`**
|
|
Forces an absolute layout recalculation of all connection nodes in view. Useful if you change node positions outside the lifecycle API or resize your external container dynamically.
|
|
|
|
---
|
|
|
|
### `GraphManager` (State Controller)
|
|
|
|
The isolated data engine that processes, updates, validates, and serializes graph states.
|
|
|
|
#### Node Management APIs
|
|
* **`addNode(config)`**
|
|
Registers a new data node. Returns the instantiated `NodeSchema` object.
|
|
* `config.title`: (String) Header title text.
|
|
* `config.x` / `config.y`: (Numbers) Absolute starting canvas positioning.
|
|
* `config.inputs` / `config.outputs`: Array of port objects (`{ id: 'unique_port_id', name: 'Display Name' }`).
|
|
* `config.id`: *(Optional)* Provide a deterministic string ID; otherwise, an internal generic system identifier will be automatically assigned.
|
|
* **`deleteNode(nodeId)`**
|
|
Destroys the node element matching the identifier and automatically sweeps/prunes any associated broken dependency lines.
|
|
* **`updateNodePosition(nodeId, x, y)`**
|
|
Mutates raw positioning values inside the memory reference model and triggers view updating layers.
|
|
|
|
#### Connection Management APIs
|
|
* **`connect(fromNodeId, fromSocketId, toNodeId, toSocketId)`**
|
|
Wires an active logical curve bridge between an output port and an input port. Returns `ConnectionSchema` object or `null` if the connection is illegal (e.g. self-looping or double mapping onto an input).
|
|
* **`disconnect(connectionId)`**
|
|
Severs a trace path across nodes using its direct line identifier.
|
|
|
|
#### Serialization & Hydration
|
|
* **`getState()`**
|
|
Returns a deep, JSON-serializable clone of the entire active workspace graph network topology.
|
|
* **`loadState(graphState)`**
|
|
Clears all active rendered interface objects and loads a freshly mapped `GraphState` configuration layer.
|
|
|
|
```javascript
|
|
// Saving state to local storage
|
|
const currentSnapshot = graph.getState();
|
|
localStorage.setItem('my_graph', JSON.stringify(currentSnapshot));
|
|
|
|
// Restoring state later
|
|
const cachedSnapshot = JSON.parse(localStorage.getItem('my_graph'));
|
|
if (cachedSnapshot) {
|
|
graph.loadState(cachedSnapshot);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🎛️ Handling Graph Events
|
|
|
|
The `GraphManager` implements a lightweight publisher/subscriber layout. You can listen to lifecycle changes across your pipeline engine to trigger custom code:
|
|
|
|
```javascript
|
|
// Capture changes to map properties to external reactive modules
|
|
graph.on('stateChanged', (latestState) => {
|
|
console.log("Global modifications registered:", latestState);
|
|
});
|
|
|
|
// Trace isolated edge terminations
|
|
graph.on('connectionRemoved', (connId) => {
|
|
console.warn(`Connection item vanished from runtime: ${connId}`);
|
|
});
|
|
|
|
// Trace node structural changes
|
|
graph.on('nodeAdded', (node) => {
|
|
console.log(`New node generated: ${node.title}`);
|
|
});
|
|
```
|
|
|
|
### Available Event Signatures
|
|
|
|
| Event Key | Callback Arguments | Description |
|
|
| :--- | :--- | :--- |
|
|
| `'nodeAdded'` | `(nodeSchema)` | Dispatched when a node object joins the topology. |
|
|
| `'nodeRemoved'` | `(nodeId)` | Dispatched when a node is removed from the canvas. |
|
|
| `'nodeMoved'` | `(nodeSchema)` | Dispatched repeatedly when a node object moves coordinates. |
|
|
| `'connectionAdded'`| `(connectionSchema)` | Dispatched when two nodes are connected. |
|
|
| `'connectionRemoved'`| `(connectionId)` | Dispatched when an edge bridge is broken or deleted. |
|
|
| `'stateChanged'` | `(graphState)` | Global catch-all event executed immediately after any graph mutation. |
|
|
|
|
---
|
|
|
|
## ⌨️ User Interface Interactions
|
|
|
|
* **Pan Canvas:** Click and drag anywhere on the empty background or the SVG connection space.
|
|
* **Zoom Viewport:** Scroll your mouse wheel or trackpad up and down. The transformation framework calculates and pins vector values centered **directly on your mouse cursor location**.
|
|
* **Drag Nodes:** Click and hold the node header bar container element. Movement velocities match your active zoom ratio precisely.
|
|
* **Draw Wires:** Click a target circular socket connector on an output node and drag your mouse. Drop the temporary dashed wire onto a target input node socket to complete a bridge connection.
|
|
* **Destroy Wires:** Click directly on an active solid colored connection bridge path vector line to delete it from the running memory structure.
|
|
* **Destroy Nodes:** Click the small `✕` button positioned inside the upper-right corner of the node header frame. |