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

@miadi/attention-ui

v0.3.0

Published

The React host of @miadi/attention-core for reviewing and answering Chronicle ATTENTION items. Core owns the vocabulary, behaviour and visual specification; this package owns React state and events. No component owns a URL, token, filesystem root, or medi

Readme

@miadi/attention-ui

The React host of @miadi/attention-core. Core owns the item vocabulary, the panel's behaviour and its visual specification; this package owns React state and events, plus a ReactNode slot where a host renders its own navigation. It owns no transport.

A page without React renders the same panel from core (renderAttentionPanelHtml, mountAttentionPanel); a parity test here holds the two markups identical. @miadi/attention-ui/styles.css is core's stylesheet, shipped under this package's path so existing imports keep working.

Lifecycle changes the panel’s posture. Open items remain prominent. In a mixed store, answered decisions move under History. When everything is answered, the panel becomes one quiet Attention complete row; View Decisions makes the full record available on demand without displacing the host’s main content.

import { AttentionPanel } from "@miadi/attention-ui";
import "@miadi/attention-ui/styles.css";

<AttentionPanel
  items={items}
  onAnswer={async (item, answer) => {
    await client.answer({ episode: item.episode, id: item.id, answer });
    return { tone: "ok", message: "Answer recorded." };
  }}
/>;

A public or otherwise non-writing host can use the same context and history surface without presenting a form:

<AttentionPanel items={items} interaction="read-only" />

interaction is a host-granted capability, not a network inference. The host decides whether it is "answer" or "read-only"; the package never inspects a hostname, token, filesystem root, or medicine-wheel address.

The host supplies items and onAnswer; therefore a Next route, MCP-backed desktop UI, Forgewright view, or another agent-authored interface can reuse the same component without inheriting Miadi URLs, tokens, filesystem roots, or medicine-wheel configuration.

The stylesheet adds responsive row/action layout, visible keyboard focus, touch-sized controls, and long-identifier containment. Presentation remains host-driven through theme, labels, className, and the stable attention-* selectors. In an episode-local room, omit the optional episode field from display items so the room identity is not repeated; global inboxes can keep it.

A global inbox — every row from a different episode — passes renderEpisodeRef to link each row to its room. The row's summary is a disclosure button, so the node is rendered beside it rather than inside it, and it replaces the plain slug:

<AttentionPanel
  items={openAcrossEveryEpisode}
  renderEpisodeRef={(item) => (
    <Link href={`/chronicle/${item.episode}`}>{item.episode} →</Link>
  )}
  onAnswer={answer}
/>

The package still learns no URL: the host returns whatever navigation it owns.

A link into a room can name the question it is about. initialOpenId opens that item on the first render — server-side included, and under History when it is already answered — so the reader is not handed the list a second time:

<AttentionPanel items={items} initialOpenId={idFromTheQueryString} />

Each row carries data-attention-id, so a host that wants to scroll or focus can find it without the package owning a ref.

The panel preserves drafts while another item is reviewed, exposes each disclosure through aria-controls, announces inline validation and async results, identifies the durable attention ID, and leaves transport/error semantics to the host callback.

Contract and first host: jgwill/Miadi#631. Quiet history and the public witness boundary: jgwill/Miadi#635.