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

inputism

v0.0.4

Published

Turn images into checkbox mosaics

Readme

Inputism

Inputism turns images into checkbox mosaics. The preferred way to display that model is the <inputism-image> web component.

The library keeps these concerns separate:

  1. An input source provides RGBA pixels.
  2. The core creates an InputismImage from those pixels.
  3. A renderer displays the model.

This means an application can use a URL, a data URL, a file decoder, or any other source that produces RGBA data without changing the image model.

Install

npm install inputism

View inputism on npm

Quick start

Load the web-component entry once. It registers <inputism-image> and includes the default styles:

<script type="module" src="https://esm.sh/inputism/element"></script>

<inputism-image
  src="/cat.jpg"
  density="36"
  mark="indeterminate"
  label="A cat"
></inputism-image>

The component accepts these attributes:

| Attribute | Values | Purpose | | --- | --- | --- | | src | URL, data URL, or blob URL | Image source to decode | | density | Positive integer | Number of columns | | mark | checked, indeterminate, or background | Cell appearance | | max-rows | Positive integer | Upper limit for generated rows | | crossorigin | CORS mode | Request mode for remote images | | label | Text | Accessible name for the internal image | | loading | lazy | Wait until the element approaches the viewport |

To reserve space before a source image loads, provide its dimensions. The component uses them as a fallback aspect ratio; surrounding CSS can still set its own aspect-ratio or width.

<inputism-image
  src="/cat.jpg"
  width="640"
  height="480"
></inputism-image>

label is a component-specific attribute. The component applies role="img" to its internal grid and uses label as that role's aria-label, similar to the relationship between <img> and alt. The attribute is not applied to the host element. If it is omitted, the internal image has no accessible name.

Changing src, density, or max-rows loads the source again. Changing mark updates the rendered cells. Without loading="lazy", sources load as soon as the component connects. Lazy sources use IntersectionObserver and load when they are near the viewport.

Supplying encoded image data

src also accepts a base64 data URL. This is useful when the application already has an encoded image:

const element = document.querySelector("inputism-image");
element?.setAttribute("src", encodedImageDataUrl);

Remote URLs must allow anonymous CORS access. If the server is configured for credentialed requests, use crossorigin="use-credentials".

Supplying RGBA data

When the application already has pixels, create the shared model directly and assign it to the component's image property:

import { createInputismImage } from "inputism/core";
import type { InputismElement } from "inputism/element";

const image = createInputismImage(
  {
    width: pixelsWidth,
    height: pixelsHeight,
    data: rgbaPixels,
  },
  {
    density: 36,
    mark: "indeterminate",
  },
);

const element = document.querySelector<InputismElement>("inputism-image");
if (element) {
  element.image = image;
}

RgbaImage.data is row-major RGBA data: four values per source pixel in red, green, blue, alpha order. The core downsamples those pixels into the requested layout.

Handling load and errors

After a src image has loaded, been converted, and rendered, the component emits a bubbling inputism-load event. InputismElement includes the custom event type, so the converted InputismImage model is available as the typed event.detail:

import "inputism/element";
import type { InputismElement } from "inputism/element";

const element = document.querySelector<InputismElement>("inputism-image");
const output = document.querySelector<HTMLElement>("[data-load-status]");

element?.addEventListener("inputism-load", (event) => {
  const image = event.detail;
  if (output) {
    output.textContent = `Loaded ${image.columns} × ${image.rows} cells.`;
  }
});

If a src cannot be loaded, the component does not render an error message. It instead emits a bubbling inputism-error event; the original error is available as event.detail:

import "inputism/element";
import type { InputismElement } from "inputism/element";

const element = document.querySelector<InputismElement>("inputism-image");

element?.addEventListener("inputism-error", (event) => {
  const error = event.detail;
  console.error("Inputism could not load the image", error);
});

Core model

Use inputism/core when layout creation and pixel sampling need to be controlled separately:

import {
  createInputismColors,
  createInputismLayout,
} from "inputism/core";

const layout = createInputismLayout(width, height, {
  density: 36,
  mark: "indeterminate",
});
const colors = createInputismColors(rgbaImage, layout);

The layout describes the cell coordinate system:

{
  columns: 36,
  rows: 24,
  mark: "indeterminate",
}

InputismColors stores one RGB triplet per cell in a flat Uint8ClampedArray. Its length is columns * rows * 3.

The one-step helper returns both parts as an InputismImage:

import { createInputismImage } from "inputism/core";

const image = createInputismImage(rgbaImage, {
  density: 36,
  mark: "checked",
});

Source adapters

Use inputism/source to keep image acquisition separate from pixel transformation:

import {
  createInputismImageFromSource,
  type ImageDataSource,
} from "inputism/source";

const source: ImageDataSource = async () => ({
  width: pixelsWidth,
  height: pixelsHeight,
  data: rgbaPixels,
});

const image = await createInputismImageFromSource(source, {
  density: 36,
  mark: "checked",
});

For browser image URLs, data URLs, and blob URLs, use the included adapter:

import { createInputismImageFromUrl } from "inputism/source";

const image = await createInputismImageFromUrl("/cat.jpg", {
  density: 36,
});

HTML renderer

inputism/html is the lower-level renderer used by the web component. It creates the grid structure, applies cell colors, and returns the styles needed to display that structure:

import { createInputismHtml } from "inputism/html";

const view = createInputismHtml(container, layout);
view.setColors(colors);
view.setColors(nextColors);

Set inlineStyles: true when the exported HTML should carry its visual rules directly on the grid and inputs:

createInputismHtml(container, layout, { inlineStyles: true });

With the default options, use view.styles to build a stylesheet for the generated classes. The web component uses this same style object inside its shadow root.

For a complete model, use the one-step helper:

import { renderInputismHtml } from "inputism/html";

renderInputismHtml(container, image, {
  mark: "checked",
  inlineStyles: true,
});

Web-component exports

The inputism/element entry registers the element when imported:

import { defineInputismElement } from "inputism/element";

defineInputismElement();

It also exports InputismElement for applications that need the element class directly.