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

@omni-ir/react

v0.15.0

Published

Omni-IR for React: the Trusted Catalog components and a streaming renderer with McpMutation governance

Readme

@omni-ir/react

React rendering for Omni-IR, an open protocol for generative UI. OmniRenderer draws a streaming Omni-IR document with the Trusted Catalog, a fixed set of components that own all styling. The model never writes HTML, CSS or code.

  • Components appear as their lines arrive, with placeholders for parts that haven't arrived yet.
  • A component that fails shows a fallback; the rest of the screen keeps working.
  • Buttons that trigger backend actions stay disabled until an McpMutation approves them, and their params are checked against your tool registry before your handler runs.

Install

npm install @omni-ir/react @omni-ir/core react

Requires React 19. ES modules only.

Usage

import { createParser } from "@omni-ir/core";
import { OmniRenderer, createMutationHandler, generate } from "@omni-ir/react";
import "@omni-ir/react/omni.css";
import { z } from "zod";

const tools = {
  "payments.confirm": z.strictObject({ amount: z.number().positive() }),
};

const parser = createParser({ tools });

export function Screen() {
  return <OmniRenderer store={parser.store} tools={tools} onMutation={(call) => console.log(call.tool, call.params)} />;
}

// Feed the parser from any stream: an LLM, a file, or an Omni-IR server.
parser.write('root = Card([title, pay])\ntitle = Heading("Confirm payment")\n');
parser.write('pay = Button("Pay $42.50", action="pay")\n');
parser.write('payM = McpMutation(pay, tool="payments.confirm", params={amount: 42.50})\n');
parser.end();

With an Omni-IR server

If your server implements POST /api/generate (server-sent events) and POST /api/mutate, as the reference server does, two helpers connect them:

const outcome = await generate("a payment confirmation for $42.50", { parser });
const onMutation = createMutationHandler(); // posts governed actions to /api/mutate

Images

Streams name pictures from your app's asset registry; they can never supply a URL. Pass the same registry to the parser (which rejects unknown names) and the renderer (which supplies the picture):

const assets = { "cabin-pines": { src: "/img/cabin.jpg", width: 640, height: 400 } };
const parser = createParser({ tools, assets });
// <OmniRenderer store={parser.store} tools={tools} assets={assets} onMutation={…} />

Fields and confirmations

Fields can declare required, format, minLength and maxLength; the renderer checks the fields an action reads before it runs, and shows its own message under each one that fails. For actions that need the person's say-so, give a sentence per tool:

<OmniRenderer store={parser.store} tools={tools} confirm={{ "payments.confirm": "Pay {amount}?" }} onMutation={…} />

The action runs only after the person confirms in the renderer's dialog. Nothing in a stream can skip or change it.

App components

Components your app adds to the catalog (defineComponents in @omni-ir/core), drawn by your own views. Pass the same components to the parser:

<OmniRenderer components={{ ProductCard, QuantityPicker }} resolvePicture={(name) => productPicture(name)} … />

Each view gets checked props with $state read, its children, pictures by name and, for a field, its value and message. missingViews(components, views) lists any without a view.

Your own catalog

catalog replaces the built-in components with your own (trusted) ones. It must provide every component type; start from DEFAULT_CATALOG:

import { DEFAULT_CATALOG, type Catalog } from "@omni-ir/react";
const catalog: Catalog = { ...DEFAULT_CATALOG, Button: MyButton };

Specification

The format and the renderer requirements are defined in SPEC.md.

License

Apache-2.0