# 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 Node Editor Instance
``` ### 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.