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

@meldkit/react-ui

v0.1.2

Published

Ready-made collaboration UI for @meldkit/react: presence avatars, connection status, remote carets, live pointer cursors

Readme

@meldkit/react-ui

Ready-made collaboration UI for @meldkit/react: presence avatars, a connection indicator, and remote carets.

Entirely optional. The SDK has no idea this package exists, and everything here is a few dozen lines you could write yourself — the point is that you shouldn't have to write them twice.

npm install @meldkit/react-ui
import {
  Avatars,
  ConnectionStatus,
  CaretOverlay,
  useIdentity,
} from '@meldkit/react-ui';
import '@meldkit/react-ui/styles.css';

Components

<Avatars /> — who's in the room, as a row of circles with each person's initials. Reads presence from the provider, so it takes no props in the common case. Pass me / others to render a list you've already filtered or sorted.

The row is bounded in both directions. Past stackAfter (3) the circles overlap instead of pushing the layout sideways; past max (5) the remainder collapses into a +N whose tooltip names them. A room of thirty people is a real thing, and a presence bar that tries to draw thirty of anything has stopped being a presence bar.

Your own circle leads the row and carries an accent ring, so it never ends up inside the overflow count. A green dot marks anyone whose cursor or pointer says they're active right now.

<ConnectionStatus /> — connection state, and errors. It reports both, because the two disagree in the case that matters: with the wrong room key the socket is perfectly healthy and the document is empty, so a plain status dot would say "connected" next to a blank screen.

<CaretOverlay text={text}>{yourTextarea}</CaretOverlay> — remote carets over a text input. A textarea can't contain elements, so this wraps yours in a mirror layer holding the same text with the same font and padding, its own text transparent, sitting on top. The browser works out where character N lands — no measurement code, correct through wrapping and resizing.

It draws carets and nothing else. The value, the edits and the CRDT stay yours; pair it with useSharedText from @meldkit/react.

<InlineCarets text={…} others={…} /> — the same carets in text you render yourself: a list row, a heading, a cell.

<Cursors space={{ width, height }} /> — everyone else's pointer, drawn over a shared surface. Reads pointer from presence and places it as a percentage of its container, so the same position lands in the same place in windows of different sizes. Its wrapper has to be positioned, and has to have the same aspect ratio as space.

Motion is the part that takes care. Each cursor moves by transform rather than left/top, because offsets are a layout change and animating them re-lays-out and repaints whatever is underneath on every frame. And each glides for as long as that person's own last gap between updates took, rather than a fixed duration — too short and a cursor sprints to each position then sits still until the next one, which is what reads as jitter; too long and it lags behind the person driving it.

Pass status to put a word next to someone's name — "drawing", "typing" — from whatever field of your presence answers that.

useIdentity() — a throwaway display name and colour for apps that don't have accounts yet. Only for display; the userId in your access token is who you are to MeldKit, and it comes from your server.

Presence shape

The components read three fields:

type CollaboratorPresence = {
  name: string;
  color: string;
  cursor?: number | null; // character offset, not a pixel position
};

A floor, not a ceiling — carry whatever else you need alongside them. The to-do example adds an editing field naming the row someone is in, which is how the same caret component serves one list row there and a whole document in the text editor example.

Offsets rather than coordinates is the load-bearing decision: a pixel position means nothing in a window of a different width, an offset means the same thing everywhere.

Styling

Import @meldkit/react-ui/styles.css once, near your entry point. Then, in order of how much you want to change:

  1. Retheme with the custom properties (--mk-accent, --mk-line, --mk-doc-font, …) — set them on :root, or on any ancestor to scope it.
  2. Restyle with your own rules against the mk- class names, or skip the stylesheet entirely and style the markup yourself.

One caveat, and it's the only part of the CSS that isn't cosmetic: the mirror layer and the text input must agree on every property that affects where a character lands, or carets drift further off with every line. Both read the same --mk-doc-* variables from one rule so they can't diverge. Retheme those rather than setting font or padding on the textarea directly.