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

@liy/mote-agentic-component-catalog

v0.2.12

Published

Shared component catalog, JSON renderer, and Mote query integration for agent-authored interfaces.

Readme

@liy/mote-agentic-component-catalog

Shared component catalog for agent-authored interfaces. The package includes component schemas and authoring guides, the React registry and JSON renderer, chart interactions, styles, and optional Mote registered-query helpers. Supply a catalog spec and prepared datasets to ComponentRenderer; rendering does not require a query provider or an app bootstrap.

Generated apps can additionally use the query helpers to fetch registered queries pinned to an app bundle. Build those apps as static SPAs with Vite base: "./". Mote timelines use the same renderer with agent-supplied datasets; the MCP host owns submission and the timeline owns persistence and revisions.

The ./catalog entry exports catalog schemas and parseInlineWidgetContent without importing CSS or React rendering. Mote's MCP host uses it to validate widget submissions. Every component has one public contract and responsive behavior in generated apps and timeline widgets. ComponentRenderer receives spec, prepared datasets, and locale; data acquisition stays with the caller. Local state and event bindings use the same json-render runtime in both hosts. ComponentRenderer contains one ComponentProvider for datasets, locale, and chart handles, plus json-render's state/action provider. The timeline mounts it directly; envelope validation happens when reading timeline records. Query hooks remain outside this rendering stack.

Generated apps import ./styles.css, which is complete: the Mote design-system tokens, base styles and font faces followed by the catalog's component rules. ./components.css holds only the component rules, for hosts that already load the design-system stylesheet, such as the Mote timeline.

Agent discovery

component-catalog list
component-catalog describe Table
component-catalog describe Button

The package ships this standalone executable and one generated catalog.json. Commands return JSON with the package version and manifest path. describe includes props, semantic requirements, a validated example, available local actions and paths to detailed authoring and widget submission guides. There are no host or device flags. --help documents usage; unknown components and invalid arguments exit nonzero.

The sandbox runtime bundles the executable and assets unchanged and exposes the command on agents' PATH. Outside the sandbox, run npm exec -- component-catalog from a project with this package installed. Discovery makes no network calls. Match the app dependency to the reported catalog release.

src/components.ts owns schemas, descriptions, events, guides, and examples. src/component-rules.ts pairs semantic checks with descriptions. The build validates examples through the same contract used by ComponentRenderer and widget submission, then generates the manifest. Do not edit generated JSON. Widget title, summary, identity, and transport limits remain submission metadata; they do not change component props or interactions.

Data tables

Use the catalog's Table to browse prepared records. Tables share the renderer's datasets and locale with charts; rows stay outside the authored spec.

const tableSpec: Spec = {
  root: "records",
  elements: {
    records: {
      type: "Table", visible: true, children: [],
      props: {
        dataset: "usage", title: "Product use", pageSize: 10, showPageSize: true,
        columns: [
          { field: "product", mobile: "primary" },
          { field: "kg", mobile: "primary" },
          { field: "month", mobile: "secondary" },
        ],
      },
    },
  },
};
// Reuse the prepared usage dataset from the chart example below.
<ComponentRenderer spec={tableSpec} datasets={{ usage }} locale="en" />;

Omit columns to display all declared fields. Columns inherit the dataset's labels, types, units, and category labelField; authored labels may override metadata. Set sortable: false when ordering a field is not meaningful. Local pagination defaults to 10 rows and accepts authored sizes from 1 to 100. Set showPageSize: true to expose a lightweight labeled number input; it is hidden by default. Operators can enter a positive integer, apply with Enter or blur, and cancel with Escape. Sorting covers the supplied dataset and returns to its first page. Numeric values keep numeric ordering, nulls appear as missing, and ISO date values sort chronologically while displaying as supplied.

Narrow containers keep primary fields visible and move secondary fields into expandable row details. Without explicit primary fields, the first two columns are primary. Mobile operators can sort by any sortable column. All controls support keyboard input, 44px touch targets on mobile, English/Chinese copy, and Mote themes. Compact headers, alternating row backgrounds without divider lines, and quiet chevron pagination keep the emphasis on the data.

For React composition, wrap Table in ComponentProvider with the same datasets and locale. ComponentProvider also supports standalone charts. Table accepts the same props as the catalog's Table.

Table pagination covers only the rows supplied by the host. It does not fetch additional query pages or recover truncated results. Retain GenAppQueryStatus and refine a query if its result is truncated. Server fetching stays outside the JSON catalog; the design system's React DataTable separately supports controlled serverPagination for hosts that own a paginated endpoint.

Editable charts

Supply prepared datasets once, outside the render spec. Use stable field keys for mappings and labels for people. Each chart owns a stable id, a dataset reference, recommended defaults, and the controls its author chooses to expose. Field mapping borrows from Vega-Lite; this is a small Mote contract, with no Vega-Lite grammar compatibility requirement. ECharts is a bundled, private renderer.

import { useRef } from "react";
import {
  ComponentRenderer, type ChartDataset, type ChartsHandle, type Spec,
} from "@liy/mote-agentic-component-catalog";
import "@liy/mote-agentic-component-catalog/styles.css";

const usage: ChartDataset = {
  grain: "One month and product", timezone: "Asia/Shanghai",
  fields: {
    month: { type: "date", label: "Month", grain: "month" },
    product: { type: "category", label: "Product" },
    kg: { type: "number", label: "Product mass", unit: "kg",
      aggregates: ["sum"], additive: true },
  },
  rows: [
    { month: "2026-01-01", product: "A", kg: 4 },
    { month: "2026-01-01", product: "B", kg: 6 },
    { month: "2026-02-01", product: "A", kg: null },
  ],
};
const spec: Spec = {
  root: "usage",
  elements: {
    usage: {
      type: "Chart", visible: true, children: [],
      props: {
        id: "pesticide-use", dataset: "usage", title: "Product use over time",
        defaults: { x: "month", y: "kg", series: "product", aggregate: "sum" },
        controls: [
          { key: "type", options: ["line", "bar", "area", "pie", "donut"] },
          { key: "x" }, { key: "y" }, { key: "interval" },
          { key: "stack" }, { key: "horizontal" }, { key: "sort" },
        ],
      },
    },
  },
};
export function App() {
  const charts = useRef<ChartsHandle>(null);
  return <ComponentRenderer ref={charts} spec={spec}
    datasets={{ usage }} locale="en" />;
}

For React composition, ComponentProvider and Chart expose the same behavior. Use the same props and provider datasets; chart IDs must be unique within a provider. data-chart-id, field keys, and control keys identify the same elements in source, the rendered UI, and the host handle.

Token-efficient edits

After mounting, a host can call the renderer ref:

charts.current.list(); // ["pesticide-use"]
const chart = charts.current.get("pesticide-use");
chart?.inspect(); // effective spec, field metadata, row grain, and rows COUNT
chart?.update({ type: "bar", stack: "sum" }); // { ok: true }
chart?.update({ y: "product" }); // { ok: false, issue: "number" }; view retained
chart?.undo();
chart?.reset();

Inspect only the selected chart when context is needed. Follow-up edits contain only changed top-level settings; axis objects replace as a unit. Null clears series, aggregate, interval, or a pinned axis bound; hidden: [] shows all series. Legend keys are JSON.stringify(categoryValue), preserving primitive types; labels are never identities. Routine controls, legend selections, tooltips, undo, and reset execute locally with no model or query calls.

An agent editing application source changes the target chart's defaults or controls, without rewriting its rows or component code. On source/default refresh, changed authored keys win and unrelated valid user choices survive. Data refresh retains compatible settings and clears stale undo history.

The imperative ref is an explicit host integration surface, not a global or an MCP endpoint. A host must connect its agent transport to that handle if live agent edits are desired. This runtime does not install a cross-frame messaging bridge. Settings and up to 30 undo entries last for the mounted session; a host can persist inspect().spec and provide it on a later mount.

Data and control rules

  • Fields use number, date, or category. labelField associates stable category IDs with another field's display names. key optionally declares a row identity, needed for scatter points with identical coordinates.
  • Supply at most 2,000 prepared rows. Normalize SQL decimal strings explicitly, preserve nulls, and keep measures with different units separate. Unknown categories remain visible; rows missing a numeric/time position are counted as unplottable. Null measures appear as missing in the data table.
  • aggregate is explicit and must appear in the measure's aggregates list. Available operations are sum, mean, min, and max. A mean is over the supplied non-null rows, not a weighted average of source observations; do not permit it on pre-averaged data. A sum with some unknown inputs shows the known subtotal and reports unknown input rows in its tooltip.
  • interval combines date values into day/week/month/quarter/year buckets, using the declared timezone for timestamps. Weeks start Monday. The date field's grain prevents invented finer detail; weekly totals cannot be redistributed into calendar months or years. ISO timestamps require offsets.
  • Agents can set xAxis/yAxis presentation: min, max, step (numeric tick spacing), ticks (a density hint), and scale. These settings stay in the chart spec and have no control sections. Date positions preserve actual elapsed time. Changing tick density does not aggregate data.
  • Stacked bar/area and pie/donut require explicitly additive, disjoint data. Pie and percentage stacks require nonnegative values. Legend filtering hides marks while retaining the full percentage denominator; hidden pie slices reserve their space. sort by value orders categorical groups by their combined plotted value. Time and numeric axes retain natural order.
  • The standard control layout exposes Style, X axis mapping, Y axis mapping, X axis grouping (calendar interval), Compare series (100% stack, Stack, Side by side), Orientation, and Order. Inapplicable controls are hidden. Each declared control can override its label and restrict its options. Metadata supplies field choices; invalid combinations are disabled. Style switches retain compatible settings; pie/donut moves the current grouping field into the category mapping. Undo restores the prior view.
  • Charts support hover, tap to pin/dismiss, arrow-key inspection, and a data table. Tooltips follow the mouse and anchor to selected marks, flipping at screen edges. Tap empty space or press Escape to dismiss a pinned value. Legend filtering uses the shared MultiSelect with colored chips and a searchable checklist. Controls wrap and stretch to fill each row; the legend picker spans the available width. Dropdowns, including Vertical/Horizontal bar orientation, use the shared Select. English and Chinese copy, theme tokens, responsive controls, and whitespace grouping are shared with Mote.

Business transformations (SQL planning, joins, allocation, conversion, weighted rates, and server aggregation) stay upstream. These bounded visual rollups are not a general transformation pipeline. The old parallel labels/series chart API is removed; migrate authored charts to named fields and a dataset reference when adopting this runtime version.

Registered queries

Keep mote.queries.json at the repository root, outside dist:

{
  "queries": [{
    "key": "farms",
    "sql": "SELECT farm_code, farm_name FROM analytics.farms ORDER BY farm_code",
    "parameters": [],
    "maxRows": 200
  }]
}

The host validates SQL, parameters and actual database output columns when it registers the build. Browser code references keys only; never import the SQL manifest into the frontend. An app without queries still declares { "queries": [] }.

import {
  GenAppQueryProvider, GenAppQueryStatus, useGenAppQuery,
} from "@liy/mote-agentic-component-catalog";
import "@liy/mote-agentic-component-catalog/styles.css";

function FarmPanel() {
  const query = useGenAppQuery("farms");
  return <>
    <GenAppQueryStatus query={query} />
    {query.status === "ready" ? <p>{query.result.rowCount} rows returned</p> : null}
  </>;
}

export function App() {
  return <GenAppQueryProvider><FarmPanel /></GenAppQueryProvider>;
}

Keep the shared status beside your catalog view. It distinguishes loading, denial, empty results, truncation and dataset Farm coverage. Session expiry offers Reopen in Mote; unavailable public versions offer the current app. Query results are { columns, rows, effectiveScope, truncated, ... }; column names/types come from the registered contract. Adapt ready rows into a prepared dataset and pass it to the renderer separately from the app's spec.

The serving Worker supplies mote-app-bootstrap with the pinned bundle and explicit viewing mode. The client posts parameters to /query/<key> and limits itself to four active requests and 32 waiting requests. It does not cache results. Abort signals cancel work and queued requests. GenAppQueryClient is available for non-hook consumers; the provider accepts an explicit bootstrap for controlled local fixtures.

Use orchestrator workspace check <ticket-id> before integration. Integration registers an immutable bundle and advances preview; publication separately requires administrator selection and review of public datasets and Farms.