npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rozie-ui/rete-angular

v0.1.4

Published

Idiomatic Angular node-based flow/graph editor wrapping Rete.js v2 — one Rozie source compiled to Angular.

Readme

@rozie-ui/rete-angular

Idiomatic angular FlowCanvas — a cross-framework node-based flow / graph editor compiled from one Rozie source wrapping Rete.js v2. It follows the controlled-graph model: you bind ONE two-way graph object as the single source of truth and declare node TYPE templates with <NodeType> / <Port> children (render-by-type). The engine owns pan / zoom / drag / drag-to-connect, and the canvas writes layout (x/y on drag) and connections (on connect / disconnect) back through the model, so you never hand-reconcile. This package is generated; do not edit src/ by hand.

Install

npm i @rozie-ui/rete-angular

Peer dependencies: the Rete engine (rete + rete-area-plugin + rete-connection-plugin + rete-render-utils, all ^2) + @angular/core + @angular/common. Install them alongside this package.

Also installed: @rozie/runtime-angular — Rozie's small, tree-shaken runtime helper package (controllable state, keyboard navigation, event modifiers, and safe interpolation). It arrives as a regular dependency, so npm pulls it for you. Your bundler keeps only the helpers this component actually uses — typically a few hundred bytes to a few KB, minified and gzipped. What's in it and what it costs.

Rete ships no stylesheet — all node / socket / connection chrome is styled by this component, so there is no engine CSS to import.

Usage

import { Component } from '@angular/core';
import { FlowCanvas, NodeType, Port } from '@rozie-ui/rete-angular';

@Component({
  selector: 'app-demo',
  standalone: true,
  imports: [FlowCanvas, NodeType, Port],
  template: `
    <div style="height: 400px">
      <rozie-flow-canvas
        [(graph)]="graph"
        [(zoom)]="zoom"
        (connection-created)="onConnect($event)"
        (node-moved)="onMoved($event)"
      >
        <rozie-node-type type="source">
          <ng-template #body let-node="node">{{ node.data.label }}</ng-template>
          <rozie-port output="num" type="number" />
        </rozie-node-type>
        <rozie-node-type type="merge">
          <ng-template #body let-node="node">{{ node.data.label }}</ng-template>
          <rozie-port input="num" type="number" multiple />
        </rozie-node-type>
      </rozie-flow-canvas>
    </div>
  `,
})
export class DemoComponent {
  graph = {
    nodes: [
      { id: 'a', type: 'source', x: 0,   y: 0,  data: { label: 'Source' } },
      { id: 'b', type: 'merge',  x: 280, y: 60, data: { label: 'Merge' } },
    ],
    connections: [{ source: 'a', sourceOutput: 'num', target: 'b', targetInput: 'num' }],
  };
  zoom = 1;
  onConnect(c: any) { console.log('connected', c); }
  onMoved(e: any) { console.log('moved', e); }
}

Theming

Every visual value the canvas renders is a --rozie-flow-* CSS custom property with a built-in inline var(token, fallback) default — it looks right zero-config and re-skins by overriding a token at any ancestor scope. Overriding just --rozie-flow-accent recolors every selected/active affordance at once: the selected-node border + ring, socket hover, the selected-edge stroke, the active control button, the marquee box, and the minimap selection. Dark mode is a zero-import, OS-driven default — the component ships an @media (prefers-color-scheme: dark) block. Ready-made design-system bridges ship in the package:

import '@rozie-ui/rete-angular/themes/shadcn.css';    // or material.css, bootstrap.css, base.css

The full token vocabulary — plus the .dark / [data-theme="dark"] class strategy for apps that toggle theme by a root class — lives in @rozie-ui/rete-angular/themes/base.css.

Props

| Name | Type | Default | Two-way (model) | Required | | --- | --- | --- | :---: | :---: | | graph | Object | {…} | ✓ | | | validateTypes | Boolean | true | | | | zoom | Number | 1 | ✓ | | | pannable | Boolean | true | | | | zoomable | Boolean | true | | | | selectable | Boolean | true | | | | readonly | Boolean | false | | | | minZoom | Number | 0.1 | | | | maxZoom | Number | 4 | | | | snapGrid | Number | 0 | | | | accumulateOnCtrl | Boolean | true | | | | curvature | Number | 0.3 | | | | fitOnMount | Boolean | true | | | | controls | Boolean | true | | | | minimap | Boolean | false | | | | background | String | "dots" | | | | canConnect | Function | null | | | | history | Boolean | true | | | | mode | String | "pan" | ✓ | | | marquee | Boolean | false | | | | nodeToolbar | Boolean | false | | |

Events

| Event | Description | | --- | --- | | edge-click | | | edge-selected | | | selection-change | | | connect-end | | | node-action | | | connection-rejected | | | connection-created | | | connection-removed | | | node-picked | | | node-moved | | | translated | | | context-menu | |

Imperative handle

Beyond props, the component exposes imperative methods (declared once in the Rozie source via $expose). Grab a handle with the native ref mechanism and call them directly:

@Component({ /* ... */ })
export class DemoComponent {
  @ViewChild(FlowCanvas) flow!: FlowCanvas;  // or the viewChild() signal
  fit() { this.flow.zoomToFit(); }
  editor() { return this.flow.getEditor(); }
}

| Method | Description | | --- | --- | | getEditor | Return the underlying Rete NodeEditor instance for direct graph-model access (the engine escape hatch). | | getArea | Return the underlying Rete AreaPlugin instance (viewport transform, node views, pan/zoom). | | addNode | Imperatively add a node — addNode(spec) where spec is { id, type, x, y, data? }. The node's sockets come from its TYPE's <Port> schema (never a per-node port array) and its label from data.label. Returns the id. NOT reaped by the graph reconcile. | | removeNode | Imperatively remove a node and its connections by id — removeNode(id). Returns whether it existed. The engine-only escape hatch — NOT written back to the bound graph model (use deleteNode for the controlled-graph delete). | | deleteNode | Remove a node and its incident connections from the CONTROLLED graph — deleteNode(id) writes a fresh graph object back through the two-way model (the blessed cascading delete; the $watch(graph) reconcile reaps the live engine node/edges). Returns whether a node was removed. Contrast removeNode, the engine-only imperative escape hatch. | | duplicateNode | Clone a node in the CONTROLLED graph — duplicateNode(id) copies the node spec at a small offset with a FRESH unique id (never a colliding one), deep-cloning its data so the copy is independent of the source, and writes one fresh graph object back through the two-way model. Connections are NOT cloned — a duplicate is an isolated node (the React-Flow default). One history entry per duplicate. Returns the new id, or null for an unknown id. The same routine the NodeToolbar's Duplicate button and Ctrl/Cmd+D drive. | | addConnection | Imperatively add a connection — addConnection({ id?, source, sourceOutput?, target, targetInput? }). Returns the id. NOT reaped by the graph reconcile. | | removeConnection | Imperatively remove a connection by id — removeConnection(id). | | clear | Remove every node and connection from the graph. | | zoomToFit | Pan and zoom the viewport to fit all nodes (Rete AreaExtensions.zoomAt). | | zoomTo | Set the zoom level — zoomTo(k). Echoes the new level back into the two-way zoom model. | | setCenter | Center the viewport on graph coordinates — setCenter(x, y, { zoom? }). Optionally sets the zoom. Echoes the level into the zoom model and fires translated. Powers the pannable built-in MiniMap. | | setViewport | Set the raw viewport transform — setViewport({ x, y, k }) (any field omitted keeps its current value). Echoes k into the zoom model and fires translated. | | screenToFlowPosition | Project a screen/client coordinate to graph coordinates — screenToFlowPosition(clientX, clientY){ x, y } (or null before mount). The palette drag-drop primitive: on a canvas @drop, call it with the event client coords and push a fresh node into the bound graph at the result. The consumer owns the drag/drop; the canvas owns the projection. | | getNodes | Return a serialized snapshot of all nodes as [{ id, label, x, y }] (live positions from the area). | | getConnections | Return a serialized snapshot of all connections as [{ id, source, sourceOutput, target, targetInput }]. | | getTransform | Return the current viewport transform { x, y, k } (pan offset + zoom), or null before mount. | | autoArrange | Relayout the graph into a non-overlapping layered arrangement — await autoArrange(opts?) runs the elkjs-backed auto-layout, then reads the arranged node positions back through the two-way graph model (echo-guarded, one undoable gesture). Verb-only — never auto-triggered. opts.options forwards elk layout options (direction / spacing). No-op before mount. The engine (rete-auto-arrange-plugin + its 1.5 MB elkjs payload) is loaded by a dynamic import on the FIRST call and reused after — so it stays out of your bundle entirely unless you arrange, and the first call pays a chunk fetch. If the optional peer is not installed, the returned promise rejects rather than silently doing nothing. | | undo | Undo the most recent graph edit (drag / connect / disconnect / delete) — undo() restores the previous snapshot through the two-way graph model (echo-guarded). Graph-only (nodes + connections), NOT the viewport. One gesture = one step. No-op when there is nothing to undo. Also bound to Ctrl/Cmd+Z. Opt out with :history="false". | | redo | Redo the edit most recently undone — redo() re-applies the snapshot through the graph model (echo-guarded). A fresh edit after an undo discards the redo branch. No-op when there is nothing to redo. Also bound to Ctrl/Cmd+Shift+Z and Ctrl/Cmd+Y. | | canUndo | Return whether there is an edit to undo — canUndo() → boolean. | | canRedo | Return whether there is an edit to redo — canRedo() → boolean. | | getSelectedNodes | Return the currently-selected nodes as [{ id, label, x, y }] (the getNodes() shape, filtered to the live selection). Empty when nothing is selected. Complements the push-only selection-change event with an on-demand read. | | selectNode | Programmatically select a node by id — selectNode(id, accumulate?) (accumulate=true adds to the selection; falsy replaces it). Drives selection from a sidebar/search. No-op when selection is disabled (readonly / !selectable). NOT named bare select (inherited HTMLElement method → Lit shadow). | | clearSelection | Clear the current node selection (and any selected edge) — clearSelection(). | | selectAll | Select every node — selectAll(). Also bound to Ctrl/Cmd+A from a focused canvas (the marquee only covers a dragged region). No-op when selection is disabled. | | centerOnNode | Pan (and optionally zoom via opts.zoom) to center the viewport on a node by id — await centerOnNode(id, opts?). Measures the node to find its center in graph coords. No-op before mount or for an unknown id. |

Slots

| Slot | Params | | --- | --- | | node | node, selected, emit | | toolbar | node, emit | | (default) | |