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

@marccawood/lit-menu

v0.2.0

Published

Anchored dropdown menu as a themeable Lit web component, with a promise API.

Readme

@marccawood/lit-menu

An anchored dropdown menu as a Lit web component. One call, one promise, one chosen id.

A native popover, so the browser draws it in the top layer: an overflow: hidden ancestor never clips it, no z-index has to be won, and an outside click dismisses it. Flips above its anchor when it would run past the bottom of the viewport. Escape closes it and marks the key press defaultPrevented, so an app that also closes something on Escape can tell the key was already used.

Depends only on lit. Needs the Popover API (Chrome 114, Safari 17, Firefox 125).

Live example →cd example && npm install && npm run dev

Sibling packages: @marccawood/lit-dialogs for modals, @marccawood/lit-toast for notifications.

Install

npm install @marccawood/lit-menu lit

Use

There is no element to place in a template. The menu mounts itself on first use:

import { AnchoredMenu } from '@marccawood/lit-menu';

button.addEventListener('click', async (e) => {
  const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
  const picked = await AnchoredMenu.open(rect, [
    { id: 'open', label: 'Open', icon: 'open_in_new' },
    { id: 'rename', label: 'Rename', icon: 'edit' },
    { id: 'delete', label: 'Delete', icon: 'delete', danger: true },
  ]);
  if (picked === 'delete') await remove();
});

open resolves to the chosen id, or null if the user clicked outside or pressed Escape. The anchor is a viewport-space DOMRect — usually getBoundingClientRect() of whatever the user clicked.

| Item field | Meaning | | ---------- | ------------------------------------------------------------- | | id | What open resolves to | | label | The visible text | | icon | Optional Material Icons ligature name, shown before the label | | danger | Optional; renders the label in the danger color |

defineAnchoredMenu(tag) is exported but optional. Call it before the first open() only if the default anchored-menu tag clashes with something.

Theme

Set these on any ancestor. Every one falls back to the value shown.

| Token | Fallback | | ------------------- | ----------------------- | | --menu-surface | #fff | | --menu-text | #111 | | --menu-border | #e5e7eb | | --menu-hover | #f3f4f6 | | --menu-danger | #b91c1c | | --menu-icon | #6b7280 | | --menu-radius | 0.4rem | | --menu-font | system-ui, sans-serif | | --menu-min-width | 190px | | --menu-max-height | min(60vh, 420px) | | --menu-z | 150000 |

--menu-z no longer decides anything — a popover sits in the top layer, above every stacking context. It is still applied, so setting it changes nothing either way.

Icons

Item icons are Material Icons ligature names. Load the font once globally:

import 'material-icons/iconfont/material-icons.css';

Without it an item shows its glyph name as text. Items with no icon need no font at all.

materialIconStyles is exported for your own shadow-DOM components — class rules in the document stylesheet do not reach inside a shadow root, so each component needs a copy.

API

| Export | What it is | | -------------------- | --------------------------------------------------------------------- | | AnchoredMenu.open | (anchor: DOMRect, items) => Promise<string \| null>. Self-mounting. | | AnchoredMenu | The element class, if you want to mount it yourself. | | defineAnchoredMenu | Guarded customElements.define, default tag anchored-menu. | | AnchoredMenuItem | The item type. | | placeMenu | The pure placement rule. Exported because it is tested, and reusable. | | materialIconStyles | Material Icons class rules for your own shadow roots. |

Develop

npm install
npm run typecheck
npm test
npm run build

Publishing runs from a version tag. Push v0.1.0 and the publish workflow checks the tag against package.json, runs the tests, and publishes to npm.

Origin

Extracted from easyDBAccess, where it serves the table footer menus and the per-column value pickers.

License

MIT © Marc Cawood