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

@ai-matrx/kit

v0.16.2

Published

The always-include AI Matrx kit: the little primitives every Matrx app speaks — autosave that never loses a keystroke, stale-response guards, clipboard with graceful fallbacks — one per subpath, tree-shaken to what you use.

Readme

@ai-matrx/kit

The always-include AI Matrx kit: the little primitives every Matrx application speaks, one capability per subpath, tree-shaken to what you use. React is the only required peer; only three subpaths carry runtime dependencies, each because the dependency IS the capability: /json-format (json5 — tolerant parsing is the feature), /idb-store (idb — the typed IndexedDB wrapper is the engine), and /qr (jsqr, loaded lazily only when the browser has no native BarcodeDetector).

The confirm DIALOG is not here — the opener is. Since 0.9.0 the body (ConfirmDialog, ConfirmDialogHost) lives in @ai-matrx/design-system, which owns the AlertDialog, the shipped motion layer and the overlay scrim token. Mount <ConfirmDialogHost /> from there once at your app root, then call confirm() from @ai-matrx/kit/confirm-opener anywhere. Since 0.10.0 that opener is a thin specialisation of @ai-matrx/kit/opener — the same engine any app can use for its own imperative dialogs. One surface, one owner: kit re-exports none of the dialog.

npm install @ai-matrx/kit

| Subpath | Export | What it does | |---|---|---| | @ai-matrx/kit/autosave | useAutosave | Debounced autosave with in-flight coalescing, a UI status (idle/unsaved/saving/saved/error), loud non-throwing failures that re-queue the payload, and flush-on-unmount so no keystroke is ever lost. | | @ai-matrx/kit/latest-request | useLatestRequest | Makes a superseded async response impossible to apply: claim an attempt, then check the predicate before every state write after an await. Kills the out-of-order-response bug (the wrong record under a confident label) at the only moment that matters — apply time. Render-stable by construction. | | @ai-matrx/kit/clipboard | useClipboard | Copy/paste text, links, and images with the browser quirks solved: canvas→PNG re-encode for image copy, Safari clipboard.read feature detection, param-stripping link copy. Notifier injected — wrap your own toast. | | @ai-matrx/kit/content-transfer | snapshot, preparation, serializers, createBrowserTransport | Immutable projected content snapshots, explicit omission evidence, JSON/table formats, and rich clipboard/download outcomes. Browser APIs are used only when delivery is requested. |

Surface handles omit own object properties whose captured value is undefined, recursively, so host optional fields retain absent-value semantics. normalizeTransferJson(value) stays strict by default; a caller must explicitly pass { omitUndefinedObjectProperties: true } to request the same object-only omission. Array undefined entries or sparse slots still fail at their JSON pointer.

| @ai-matrx/kit/search-scoring | filterAndSortBySearch, computeSearchScore, matchesSearch, idMatchesQuery | Relevance-weighted search ranking — title above description, exact above prefix above includes, pasted-UUID matching — instead of the naive .includes() filter. | | @ai-matrx/kit/concurrency | runWithConcurrency | Bounded worker pool over an array with per-item failure isolation and a cooperative shouldStart() cancel hook. | | @ai-matrx/kit/text-case | formatText, createFormatter | Acronym-aware normalization of messy DB/API strings into title/sentence case with word-replacement overrides. | | @ai-matrx/kit/drafts | useDurableDraft + the local-drafts store | User-authored text that survives anything: write-through localStorage drafts, restore on mount, key-change adoption, cleared only after content durably landed. | | @ai-matrx/kit/opener | createOpener, Opener, OpenerHostController, OpenerAbortError | THE opener pattern, once. Build an imperative await open(request) for any global dialog: pure TS, zero React, so hundreds of call sites (thunks, utils, sync handlers) import it at near-zero cost while the heavy body stays behind a lazy host. You get the whole contract for free — one host at a time, requests queued in call order before the host hydrates, never a silent default answer, a console scream naming the component to mount when a request waits with no host, opt-in dedupe so a double-clicked action cannot stack two dialogs, and opt-in AbortSignal cancellation. State lives on a globalThis Symbol.for(slot), so host and caller find each other across packages AND across ESM/CJS module graphs. | | @ai-matrx/kit/credential-generator | generateCredentialSecret, CREDENTIAL_GENERATION_TECHNICAL_LIMITS | A pure local Web Crypto password/passphrase generator. Hosts supply validated feature limits within the published technical work ceilings; the generator never stores, logs, fetches, or falls back from secure entropy. | | @ai-matrx/kit/opener-react | useOpenerHost | The mount side of an opener: registers the component as THE host, drains queued requests one at a time, and hands back { request, open, settle }. React only — no markup, no CSS — so the dialog body stays entirely yours. | | @ai-matrx/kit/confirm-opener | confirm, ConfirmOptions | The window.confirm replacement's imperative half — pure TS, zero React, zero radix, no "use client", so a Redux thunk, a util or a sync handler can import it at near-zero bundle cost. await confirm({ title, description, variant: "destructive" }) resolves true/false; pre-mount calls queue and concurrent calls present one at a time; with no host mounted it stays pending forever rather than inventing a silent default. Needs <ConfirmDialogHost /> from @ai-matrx/design-system mounted once — the two share one registry through a globalThis slot. | | @ai-matrx/kit/toast | createMatrxToast | The captured sonner wrapper as a factory: pass your sonner toast in, get a drop-in toast back whose .error/.warning also feed your injected error-capture sink, plus toastErrorAlreadyCaptured for notices whose failure was already captured upstream. No sonner import — and sonner is not declared as a dependency or peer at all. | | @ai-matrx/kit/invalidation | registerInvalidationCallback, fireInvalidation | Zero-import, name-keyed callback registry that breaks import edges into heavy chunk clusters: the heavy cluster registers at its own module init, the ubiquitous module fires by name. Unregistered names are a deliberate no-op; a throwing callback screams and never breaks the caller. Keep your key constants in ONE host module. | | @ai-matrx/kit/delimiter-guard | guardMarkdownDelimiters (+ guardMathDelimiters, guardRunawayLinks, reportDelimiterViolations) | Keeps one stray streamed delimiter from swallowing a whole section: a $$ that would turn prose into a red KaTeX error span, or an unclosed [ that would turn a section into one giant link, gets invisibly neutralized while real math and links keep rendering. Pure; report violations loudly via the optional injected capture sink. | | @ai-matrx/kit/json-format | detectJson, formatJsonText, stringifyJson | "Is this text JSON, and what shape should it be in?" Detection survives code fences, surrounding prose, and tolerant (JSON5) input — looksLikeJson gates offering, ok gates running. The writer does minify / width-aware compact (inline + pack) / pretty, key sorting, fence add/strip/preserve. Never throws, never mangles text it did not parse. | | @ai-matrx/kit/idle-scheduler | useIdleTask, useIdleReady, useIdleGate, useIdleRegister + registerIdleTask, onFlushComplete, whenPageIdle | Priority-aware deferred execution: work waits for document load → paint → true browser idle (scheduler.postTask / requestIdleCallback / MessageChannel fallback, hidden tabs still flush), then runs 1-first…5-last. Zero re-renders to register; one re-render for the ready signal. | | @ai-matrx/kit/url-state | useUrlState + codecs, useMirroredUrlState, useUrlSearchParams, commitUrlParams | The URL as the source of truth for view state: refresh, copied links, and Back/Forward reproduce the same view. Codecs (string/enum/boolean/positive-integer/JSON) omit defaults so pristine URLs stay clean; discrete decisions push, high-frequency text replaces; every write notifies every other URL-backed control on the page. | | @ai-matrx/kit/idb-store | DBStoreManager, PublicStoreManager, FeatureStore, getIdbStoreSingleton | Typed, versioned IndexedDB stores over idb: subclass, declare your object stores/indexes in setupStores, and every operation resolves { data, error } — never throws, before or after init. Hold each store's one instance with getIdbStoreSingleton(key, create) (a globalThis slot, so the ESM and CJS graphs share it). | | @ai-matrx/kit/color-util | findNearestTailwindColor, getColorFromTailwind, formatTailwindColor, format* normalizers, createColorNormalizer, tailwindColors | The bidirectional Tailwind-token color mapping with zero dependencies: token → hex lookups (including fuzzy input like "skyblue598"), and hex/rgb() → nearest token by perceptual CIEDE2000 distance (bit-identical to the colord lab plugin; a colord instance also plugs straight into the structural { delta(hex) } seam). Plus the pure paste-anything input normalizers and the injected-validity normalizeColorInput waterfall. | | @ai-matrx/kit/react-tree | treeContainsComponent | Safe React children-tree scan for optional a11y children (is a DialogDescription anywhere under these children?): walks elements, arrays, fragments, iterables, and portals by hand, and SKIPS a non-renderable child with a loud dev scream instead of crashing at the probe like React.Children.toArray would. | | @ai-matrx/kit/qr | decodeQrFromImageFile, decodeQrFromElement, decodeQrFromImageData, hasNativeQrDetector | THE QR decoder, in memory and never uploaded: a pasted screenshot, a dropped file, or a live <video>/<canvas> frame in; the encoded text (or null) out. Native BarcodeDetector first; the pure-JS jsqr fallback is lazily imported only in browsers that lack it. | | @ai-matrx/kit/format | formatDurationMs / Seconds / Minutes, formatRelativeTime, formatAbsoluteDate, parseTimestamp, durationMsBetween, formatFileSize, getInitials, avatarPaletteIndex | THE one home for the tiny display formatters nothing else owns, with the display decision made ONCE per voice. Durations speak clock (9:04), compact (5.2s, 1m 30s), coarse (45 min, 3d 4h) or long (45 minutes, 3 days — the voice that goes inside a sentence), and round: "down" makes any of them safe for a countdown. Relative stamps speak short, long or locale-aware intl, all three in BOTH directions — "2d ago" and "in 2d" — with a sub-minute future magnitude reading "just now" because that much is clock skew, and suffix: false for a dense column whose header already says "Age" or "Due" (it drops " ago" and "in " alike). The unit is always in the name — there is deliberately no formatDuration. It also owns the HONEST NUMBER contract: formatUsd, formatCount, formatPercentFromFraction, safeRatio and sumKnown refuse to invent a value — unknown reads as UNKNOWN_DISPLAY ("—"), a measured 0 still reads as 0, and sumKnown hands back how many values it could NOT measure beside the total, so ?? 0 is never the easy path into an aggregate. |

credential-generator bundles the EFF Large Wordlist (7,776 entries; SHA-256 addd35536511597a02fa0a9ff1e5284677b8883b83e986e43f15a3db996b903e). EFF's copyright policy makes its original material available under CC-BY 4.0.

More subpaths are on the roadmap: copy-for-ai.

Host wiring: /url-state

No wiring is required. The module writes through the History API (history.pushState/replaceState) and dispatches its own sync event — this is exactly how it runs inside the Next.js App Router host it was extracted from; do NOT pass the Next.js router. Inject a router only when your host's router must observe or perform the URL writes (react-router, a memory router in tests, a native shell):

import { setUrlStateRouter } from "@ai-matrx/kit/url-state";

setUrlStateRouter({
  push: (url) => myRouter.navigate(url),               // full relative URL: pathname?query#hash
  replace: (url) => myRouter.navigate(url, { replace: true }),
  // Optional: where the current URL is read from (default: window.location)
  getLocation: () => ({ pathname, search, hash }),
});

Call it once at app boot (setUrlStateRouter(null) removes it). With no router injected, behavior is byte-identical to the Matrx frontend original.

Design

  • One package, many subpaths — you always include the kit; you only bundle what you import.
  • Injected hosts (the clipboard notifier), opinionated behavior (the autosave status contract, the apply-time guard). The opinions are the product.
  • ESM + CommonJS conditions with matching declarations, proven from the packed tarball. The "use client" boundary is stamped per chunk: React-touching subpaths carry it, pure ones (search-scoring, concurrency, text-case, invalidation, delimiter-guard, json-format, idb-store, color-util, react-tree, qr, credential-generator) ship unstamped and RSC-safe.

MIT © AI Matrx