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

@jolly-pixel/ui

v3.2.0

Published

Common and System's UI for JollyPixel's editors

Readme

📌 About

Browser-based Lit components for JollyPixel editor interfaces: controlled fields, actions, icons, theming and collaboration-aware field state.

💡 Features

  • Form controls: text, number, slider, range, checkbox, select, flags, color and button groups
  • Containers and chrome: panes, folders, tabs, docks, floating panes, dialogs, toolbars and rails
  • Actions and layout: buttons, separators and property rows
  • Controlled fields: shared values, events, drafts, validation, mixed values and defaults
  • Collaboration state: peer presence, field locking and peer colors
  • Feedback: determinate and indeterminate progress plus the runtime loading screen
  • Theming: light/dark themes, density presets and semantic custom-property tokens
  • Icons: built-in glyphs and an open registry for custom icons

💃 Getting Started

This package is available in the Node Package Repository and can be easily installed with npm or yarn.

$ npm i @jolly-pixel/ui
# or
$ yarn add @jolly-pixel/ui

[!IMPORTANT] lit is a peer dependency. Use one compatible copy in the application.

👀 Usage Example

Import the package to register its custom elements. Apply themeStyles to a shadow-root scope host, then bind field values and change events:

import { LitElement, html, css } from "lit";
import { customElement } from "lit/decorators.js";
import { themeStyles } from "@jolly-pixel/ui";

@customElement("settings-pane")
export class SettingsPane extends LitElement {
  static override styles = [themeStyles, css`:host { display: block; }`];

  #opacity = 1;

  override render() {
    return html`
      <jolly-text
        label="Name"
        .value=${"Player"}
      ></jolly-text>

      <jolly-number
        label="Opacity"
        .step=${0.01}
        .min=${0}
        .max=${1}
        .value=${this.#opacity}
        .default=${1}
        @jolly-change=${this.#setOpacity}
      ></jolly-number>

      <jolly-button variant="accent" @click=${this.#resetOpacity}>
        Reset opacity
      </jolly-button>
    `;
  }

  #setOpacity = (event: CustomEvent<{ value: number }>) => {
    this.#opacity = event.detail.value;
    this.requestUpdate();
  };

  #resetOpacity = () => {
    this.#opacity = 1;
    this.requestUpdate();
  };
}

jolly-text, jolly-number and jolly-button are components provided by this package. Fields are controlled: they render the supplied value and emit changes, so the handler writes the new value back into the component's state.

Set density on the scope host when needed:

<settings-pane density="compact"></settings-pane>

📚 API

The installation and first component example above are the starting point. These guides cover cross-component behavior:

The API reference follows the implementation folders. Each registered custom element has one page with its usage, properties, events, methods, slots, and styling surface where applicable.

🖼️ Examples Gallery

Every component has a gallery entry, which is also its only end to end fixture.

pnpm run dev

The gallery exercises the shared field states. Deep-link a control with or without the surrounding shell:

/?example=controls/number
/?example=controls/number&chrome=off

Adding an example:

  • Put the module in examples/scripts/examples/<group>/, and give it the id <group>/<name>. The folder, the id prefix, and the navigation group are the same word, and groups.ts maps it to a label. An id outside that list fails to compile.
  • Register it in that folder's index.ts, which is the only order the navigation and the manifest sweep read. manifest.ts itself never changes.
  • Return a teardown from render only for state living outside host: timers, subscriptions, listeners on window or document, and panes mounting themselves on document.body. The gallery clears host on its own.
  • Keep DOM access inside render. The manifest sweep imports every example in Node, where HTMLElement does not exist at module scope.
  • Give a component one page, and declare its variants as options rather than as sibling pages. The shell renders one checkbox per option, remounts the example on a toggle, and keeps the state in the URL (/?example=containers/tabs&closable=1), so a variant stays deep-linkable and survives a reload. End to end tests pass them through openExample(page, id, { options }).

Contributors Guide

Read the contributing guide before making changes.

Run the package checks with:

pnpm run test
pnpm run test:e2e
pnpm run lint

Unit tests use node:test; end-to-end tests use Playwright against the gallery.

End-to-end tests follow the production ownership model under test/e2e/:

  • controls/, containers/, and field/ hold component and field contracts.
  • gallery/ verifies the gallery harness and manifest.
  • scenarios/ holds multi-component workflows that do not belong to one source module.
  • support/ owns navigation, event capture, dock and computed-style helpers. Pointer and locator helpers come from @jolly-pixel/e2e. Do not duplicate these helpers in a spec.

Keep a test with the component that owns the observed contract. Put only deliberately cross-component user workflows in scenarios/.

[!IMPORTANT] Keep unit-test assertions in plain modules. Component decorators are not erasable syntax and cannot be imported directly by node --test with type stripping.

[!CAUTION] Include tests for new features and bug fixes.

License

MIT

This package embeds Roboto Mono (weight 400, latin subset), licensed under the Apache License 2.0. See NOTICE for the full attribution. The face is registered against the document on first import of themeStyles; call ensureFontFace() yourself if you declare theme tokens by hand. Without it, --jolly-font-family falls back to the system mono stack.