This project is an experimental port and refactor of litegraph.js (based on litegraph.ts) to TypeScript with ESM module support.
litegraph.ts is a TypeScript library designed to create graphs in the browser, akin to Unreal Blueprints. Users can easily program nodes, and the library includes an editor for constructing and testing graphs.
- Seamless integration with existing web applications
- Capability to run graphs independently of the editor
- Extensive documentation available
Note: The API and serialization format are not entirely compatible with vanilla litegraph.js and may change during development.
Note 2: This project's primary objective is to publish litegraph.ts to npm while carrying out ongoing renovations and refactoring.
- Renders on Canvas2D (zoom in/out and panning, easy to render complex interfaces, can be used inside a WebGLTexture)
- Easy to use editor (searchbox, keyboard shortcuts, multiple selection, context menu, ...)
- Optimized to support hundreds of nodes per graph (on editor but also on execution)
- Customizable theme (colors, shapes, background)
- Callbacks to personalize every action/drawing/event of nodes
- Subgraphs (nodes that contain graphs themselves)
- Live mode system (hides the graph but calls nodes to render whatever they want, useful to create UIs)
- Graphs can be executed in NodeJS
- Highly customizable nodes (color, shape, slots vertical or horizontal, widgets, custom rendering)
- Easy to integrate in any JS application (one single file, no dependencies)
- Typescript support
The above are the features of litegraph.js, which this library fully inherits. Below are the new features continuously updated in this library.
(A checkmark indicates implemented features)
- DOMWidget: Internally implemented widgets that support DOM, making it easy to create various UIs
- (Deprecated)
(削除) ReactWidget: Integrate support for using React components as widgets, allowing for more dynamic and complex UIs within nodes (削除ここまで) - Getter Setter Node: Implement getter and setter nodes that determine node connections in a hidden form
- Event Bus: LGraph / LGraphCanvas / LGraphNode support event subscription, making it easy to customize various features
- Progress: draw node progress / highlight
- Dom Anchors: You can freely insert DOM elements in any direction of the node's top, bottom, left, right, center, and middle to enhance UI functions, such as tooltip or error message
- Customize ContextMenu: Provide interfaces to customize all context menus in the graph
- Customize Dialog: Provide interfaces to customize all dialogs in the graph
- Graph Scheduler: Provide graph connection parsing based on graph theory, decompose component, and control different component(sub-graphs)
- Core Code
strictNullChecks: Type safe everywhere! - Input/Output widget: Provide widgets for easier handling of input and output within nodes.
- Control Flow: Introduce nodes that manage control flow like conditional branches and loops.
- UI testing
npm install @litegraph-ts/core @litegraph-ts/nodes-basic
import { LiteGraph, LGraph, LGraphCanvas } from "@litegraph-ts/core"; import { ConstantNumber, Watch } from "@litegraph-ts/nodes-basic"; // Include litegraph's CSS, required for the UI to function properly import "@litegraph-ts/core/css/litegraph.css"; // Grab canvas element from the index.html const root = document.getElementById("main") as HTMLDivElement; const canvas = root.querySelector<HTMLCanvasElement>(".graphCanvas"); // Setup graph (nodes/logic) and graph canvas (rendering/canvas/UI) const graph = new LGraph(); const graphCanvas = new LGraphCanvas(canvas, graph); graphCanvas.background_image = "imgs/grid.png"; (window as any).graph = graph; (window as any).graphCanvas = graphCanvas; // Refresh graph on every draw tick in a loop graph.onAfterExecute = () => { graphCanvas.draw(true); }; // Create a ConstantNumber, sends a constant number on its output var constNumber = LiteGraph.createNode(ConstantNumber); constNumber.pos = [200, 200]; constNumber.setValue(4.5); // Create a Watch, displays input value on its panel var watch = LiteGraph.createNode(Watch); watch.pos = [600, 300]; // Add components to the graph graph.add(constNumber); graph.add(watch); // Connect the first output of the number (output 0) to the first input of the watch (input 0) constNumber.connect(0, watch, 0); // Begin executing logic on the graph graph.start();
export class SumNode extends LGraphNode { static slotLayout: SlotLayout = { inputs: [ { type: "number", name: "num_a", }, { type: "number", name: "num_b", }, ], outputs: [ { type: "number", name: "sum", }, ], }; override onExecute(param: any, options: object): void { const input0 = this.getInputData(0) ?? 0; const input1 = this.getInputData(1) ?? 0; this.setOutputData(0, input0 + input1); } } LiteGraph.registerNodeType({ class: SumNode, title: "Sum Node", desc: "Add number A number b", type: "demo/sum", });
Or you can wrap an existing function:
function sum(a, b) { return a + b; } LiteGraph.wrapFunctionAsNode("demo/sum", sum, ["Number", "Number"], "Number");
class TextareaWidget extends DOMWidget { constructor( name: string, node: LGraphNode, { defaultValue, placeholder, }: { defaultValue?: string; placeholder?: string; } = {}, ) { const element = document.createElement("textarea"); element.style.resize = "none"; element.value = node.properties[name] ?? defaultValue ?? ""; if (placeholder) { element.placeholder = placeholder; } super({ element, name, node, options: { hideOnZoom: true, getValue: () => element.value, setValue: (x) => (element.value = x), }, }); element.addEventListener("input", () => { this.updateProperty(); }); } }