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

@jacoobia/contextify

v2.0.0

Published

A lightweight vanilla JavaScript context menu library with support for any icon library.

Readme

Contextify

A lightweight vanilla JavaScript context menu library with support for any icon library. This library was written for use in a personal project of mine as an AIO solution for the features of a context menu that I wanted that I could only find spread across multiple different context menu libraries. This is very early doors and I will continue to maintain this however slowly that may be as I build my personal projects and use cases change or the need for features arise.

Contextify in a file manager

Install

npm install @jacoobia/contextify
import Contextify from '@jacoobia/contextify';

Or without a bundler:

<script src="https://unpkg.com/@jacoobia/contextify/dist/contextify.global.js"></script>

| Build | File | Size | | --- | --- | --- | | ES module | dist/contextify.js | | | CommonJS | dist/contextify.cjs | | | Browser global | dist/contextify.global.js | 7.8 KB minified, 2.8 KB gzipped | | Types | dist/contextify.d.ts | |

No runtime dependencies.

Usage

//Construct our menu buttons 
const menuButtons = [
    { icon: 'fa-solid fa-camera', type: 'button', text: 'Screenshot', click: screenshot },
    { icon: 'fa-solid fa-times-circle', type: 'button', text: 'Cancel', click: (event) => { menu.hide(false); }}
];
//Create our new Contextify object with the buttons, theme, container
const menu = new Contextify(menuButtons, "dark", document.body);

Which creates the following menu (note, the example requires you to have a form of FontAwesome installed):

Example Menu

Options

new Contextify(buttons, theme, container?, alignment?, themePath?)

| Argument | Default | Description | | --- | --- | --- | | buttons | | Array of button definitions (see below). | | theme | | Theme name, e.g. "dark" loads contextify-dark.css. | | container | document.body | Element the menu is attached to and listens on. | | alignment | 'south-east' | Which way the menu opens from the cursor: 'north-west', 'north-east', 'south-west' or 'south-east'. | | themePath | 'themes/' | Folder the theme CSS is loaded from, e.g. "/node_modules/@jacoobia/contextify/themes/". |

Buttons

| Property | Description | | --- | --- | | text | Label shown on the button. | | type | 'button' (default) or 'separator'. | | icon | Icon class names ('bi bi-camera') or an Element such as an inline SVG. | | click | Called with { button, parent, handled, hotkey } when the button is clicked or its hotkey is pressed. | | hotkey | Keyboard shortcut that fires click, e.g. 'Ctrl + Shift + S'. Modifiers: Ctrl, Alt, Shift, Meta/Cmd. | | hotkeyLabel | Shortcut text shown on the button. Defaults to hotkey. A string without hotkey shows a shortcut your app already handles; false hides the label. | | requireMenuOpen | false by default, so hotkeys work any time. true only fires the hotkey while the menu is open. | | enabled | false greys the button out and disables its hotkey. | | colour / textcolour | Background / text colour as 'r:g:b:a', e.g. '255:0:0:1'. | | child | Array of buttons to show as a submenu. |

Methods

| Method | Description | | --- | --- | | show(x, y) | Opens the menu at viewport coordinates. | | hide(hideParent?) | Closes the menu and its submenus. | | assignTheme(theme, themePath?) | Swaps the theme stylesheet. | | enableButton(selector) / disableButton(selector) | Toggles the enabled / disabled class on a rendered button, e.g. '#Rename'. | | register() / deregister() | Adds / removes the menu's event listeners, including submenus. |

Hotkeys

  • Hotkeys fire while focus is inside the container, or at any time while the menu is open.
  • While typing in a text field, only hotkeys using Ctrl, Alt or Meta fire.
  • event.hotkey is the shortcut that fired click, or undefined for a mouse click.
  • When a hotkey fires while the menu is closed, event.button is null because no menu entry is rendered.
  • To hide every shortcut label: .context .hotkey { display: none; }
click: (event) => {
    if (event.hotkey === undefined) event.button.classList.add('used'); // mouse click, button is always set
}

Themes

All six themes

| Theme | Menu colour | Corners | Icons | Shortcuts | | --- | --- | --- | --- | --- | | dark | #292A2D | Square | Left | Shown | | light | #FFFFFF, bordered | Square | Left | Shown | | acid | #282E42, green accents | Square | Left | Shown | | min | #292A2D | Rounded | Right | Hidden | | simple | #1D2F43 | Rounded | Hidden | Hidden | | soft | #F3DCD4, bordered | Rounded | Right | Hidden |

Custom theme: copy a file from themes/ to contextify-{name}.css in your themePath folder and pass "{name}" as the theme.

Icons

Works with any icon library

{ icon: 'fa-solid fa-camera', text: 'Screenshot' }      // FontAwesome
{ icon: 'bi bi-camera', text: 'Screenshot' }            // Bootstrap Icons
{ icon: mySvgElement, text: 'Screenshot' }              // any Element, cloned into the menu

TypeScript

Types ship with the package:

import Contextify, { type ContextifyButton, type ContextifyClickEvent, type Alignment } from '@jacoobia/contextify';

Demos

| File | Shows | | --- | --- | | demo/showcase.html | A file manager with working actions and hotkeys. |

Build first (npm run build), then open it directly in a browser.

Light theme

Contributing

git clone https://github.com/jacoobia/Contextify.git
cd Contextify
npm install
npm run build
src/contextify.ts   the library (single file)
themes/             theme stylesheets
demo/               demo pages (open from disk after building)
media/              README images
dist/               build output (git-ignored)

License

MIT, see LICENSE.


Disclaimer: This has only been tested on desktop, MacOS and Windows 10. I have not tested this on any mobile devices.