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

lit-graph

v0.1.0

Published

A Lit module for declarative, type-safe reactive port wiring between components

Readme

lit-graph

lit-graph is a minimal TypeScript library for declaratively wiring reactive inputs and outputs between Lit components or plain objects. It uses @inport, @outport, and @node decorators to mark reactive fields, and provides a central LitGraph class for managing runtime connections.

It is built on top of @lit-labs/signals for reactivity.

Why Use lit-graph?

When building applications with Lit, there's often a trade-off between creating highly reusable components and creating components which interact across the DOM. Manually managing event listeners, callbacks, and shared state can erode component encapsulation and introduce a maze of boilerplate that’s hard to maintain.

lit-graph addresses this by letting each component declare its own public-facing ports—inputs with @inport and outputs with @outport—and then connecting those ports anywhere in the DOM with a single, declarative call:

litgraph.edge('sourceId.portName', 'targetId.portName');

This promotes encapsulation and reuse while simplifying inter-component communication with minimal overhead.

📦 Installation

npm install lit-graph lit @lit-labs/signals

🚀 Quick Start

1. Define Nodes

import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { outport, inport, node } from 'lit-graph';

@customElement('my-button')
@node
export class MyButton extends LitElement {
  @outport() clicked = false;

  render() {
    return html`<button 
      @mousedown=${() => this.clicked.send(true)} 
      @mouseup=${() => this.clicked.send(false)}>
        Click me
    </button>`;
  }
}

@customElement('my-indicator')
@node
export class MyIndicator extends LitElement {
  @inport() flash = false;

  nodeExecutor(flash) {
    this.log.info('indicator flashing!')
  }

  render() {
    return html`<div style="background: ${this.flash ? 'yellow' : 'gray'}">
      Indicator
    </div>`;
  }
}

2. Connect Ports

import { litgraph } from 'lit-graph';

litgraph.edge('btn.clicked', 'ind.flash');

3. HTML Structure

<my-button id="btn"></my-button>
<my-indicator id="ind"></my-indicator>

⚙️ Core Concepts

@inport()

Defines an input property that can be connected to any number of outputs. Values assigned to this property will come from connected @outports.

@outport()

Defines an output port with a .send(value) method. When called, it pushes the value to all connected @inports.

@node

Marks a class (element or headless) as a node with ports. Nodes also support the optional nodeExecutor() method for reactive transforms.

nodeExecutor()

This function will execute any time an inport is updated. Defining this function inside an element decorated with @node will add custom reactive behavior to the element. This is also true for "headless" nodes, nodes which are not elements.

🔌 createContext

const graph = createContext();
graph.node('nodeId', NodeClass);
graph.edge('source.out', 'target._in');
  • .node(id, Ctor) – Instantiates and registers a headless node. Not necessary for elements.
  • .edge(src, dst) – Connects an Outport to an Inport
  • .setLogLevel(level) – Adjusts log verbosity

The default, global instance is exported as litgraph. This instance is used to connect elements across the DOM.


🧪 Headless Nodes

Headless nodes are plain JavaScript classes (not custom elements) that are registered directly with a LitGraph instance using .node(id, Ctor).

They support full reactive behavior: their @inport values are tracked, and whenever any input changes, the node is notified via nodeExecutor(...inports,...outports) method. Arguments appear in order they were declared in the node.

@node
class Adder {
  @inport() a = 0;
  @inport() b = 0;
  @outport() result;

  async exec(a, b, result) {
    result.send(a + b);
  }
}

🧱 Contexts

import { createContext } from 'lit-graph';

const graph = createContext(element);
graph.edge('localNode.out', 'localTarget.in');

Creates a scoped LitGraph instance that searches for nodes under a DOM subtree.


🧾 API Reference

function inport(name?: string): PropertyDecorator
function outport(name?: string): PropertyDecorator
function node<T>(Ctor: T): T
function createContext(root: Element): LitGraph

class LitGraph {
  node(id: string, Ctor: new () => any): any
  edge(from: string | Outport, to: string | Signal.State | string): void
  setLogLevel(level: string): void
}

License

lit-graph is released under the MIT License. This license permits free use, modification, distribution, and private use of lit-graph, but with limited liability and warranty as detailed in the license terms.