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

@knkcs/mediahub-ui

v0.7.0

Published

Reusable mediahub asset-management UI surfaces (AssetPicker, AssetLibrary) for host apps

Readme

@knkcs/mediahub-ui

Mediahub's reusable UI, published as a versioned npm package so that every host renders the same media surfaces instead of re-implementing them.

Two hosts consume it today: knkCMS core, which embeds it as a build-time dependency, and mediahub's own standalone app, which consumes it through the workspace.

Screens, not routes

A screen takes typed paths and emits callbacks; the host owns routing and draws the page frame. No screen builds a URL, and no host builds UI a screen already owns.

That contract is the point of the package. When a host re-implements a surface instead of composing it, the two copies diverge and bugs are fixed in one of them — see knkCS/mediahub#138, which consolidated the asset-type screens after four such bugs, and mediahub ADR 0008, which removed a host-built browse switcher for the same reason.

What it exports

| Surface | What it is | |---|---| | AssetLibrary | The media browser: folder tree, filters, upload, and the context rail carrying Tags and Collections | | AssetDetail | One asset, its versions and its metadata | | AssetPicker, CollectionPicker | Embeddable pickers for a host's own forms | | AssetTypeIndex, AssetTypeCreate, AssetTypeDetail | Asset-type administration, including the AI-processes tab | | CollectionIndex | The Collections the user can see, marking the Restricted ones. Listing is not gated by authority — per ADR 0001 seeing a Collection and managing it are separate privileges. Each row offers a way into that Collection's contents, pointing at the host's links.collectionHref — a host that registers none renders no such control at all | | CollectionCreate | Create a Collection from a name, slug and description. Static only — a smart Collection's rules are stored and never evaluated, so no type selector and no rules editor appear (#173) | | CollectionDetail | One Collection's identity — name, description, delete — and its access control: the Restricted toggle (with the leak-guard refusal naming what it would expose) and the roster, offered only where the can-manage probe says the reader is an authority (ADR 0001: owner-on-the-Collection or admin-on-its-workspace, and grantees never see the roster). Also the way into the Collection's contents, via the host's links.collectionHref, offered to everyone who can see the Collection and absent where the host registers no such route — looking is neither management nor Curation. Not Curation: adding and removing assets happens in the library, where the assets are | | MediahubProvider | The provider a host mounts once, holding the clients and query client | | Clients | createConnectMediahubClients adapts per-service Connect clients into the domain clients the screens' hooks read, and owns the mapping — a host supplies transport only | | Hooks and stores | The queries and mutations behind the screens, for a host composing its own view | | filtersFromSearchParams, searchParamsFromFilters | How a filter set is written into a URL, so a link means the same thing in every host (ADR 0009). Not a route: a host passes the parameters it holds and decides whether to sync at all |

Everything lands at the package root (.). A second entry point, ./testing, ships a stub client and fixtures so a host can test its own composition without a server.

The URL encoding is the one export whose names are a contract rather than a type: folderId, tags, collectionId, search, statusSlug, behavior are spelled in every link anyone has shared, and renaming one would compile. ADR 0009 accepts that cost deliberately; the names are pinned by test so a rename fails the suite.

Narrowing composes

Folder, Collection and Tag narrow the library together — one folder, many collections, many tags. They are not alternative modes, and a UI that makes them mutually exclusive cannot express a question the data model permits. AssetLibrary accounts for what is applied with a row of dismissible filter chips. See ADR 0008 and the Narrowing entry in CONTEXT.md.

Layout comes from anker

Screens use anker's templates and primitives — IndexPageTemplate, DetailPageTemplate, SubNavLayout, ContextRail — and report their frame through anker's host contract. anker's own guidance is explicit: if a template does not fit, file an issue rather than hand-rolling a layout.

Peers

Every non-trivial dependency is a peer the host supplies once, so a host and the package can never load two copies of React, the query client or anker. The Rollup external list is derived from peerDependencies, so declaring a peer is the whole change.

Releases

Versioned with release-please from conventional commits, and published to npm by CI. A commit whose subject loses its feat:/fix: prefix — which a squash merge can do — produces no release at all, silently (knkCS/mediahub#185).