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

@glowbox/lcd

v1.12.0

Published

Character LCD module component — the HD44780-class 16×2: a reflective display whose ink takes real time to move (LC response smear), with the contrast pot, passive-matrix crosstalk streaks, the uninitialised row of boot boxes, CGRAM custom glyphs and a bl

Downloads

227

Readme

@glowbox/lcd

A character LCD module (HD44780-class — the 16×2) as a canvas component: the glowbox family's first reflective display. Dark ink on a lit pane, native to a light page the way every emissive sibling is native to a dark one. Zero dependencies.

The reason it exists is the liquid crystal, not the character grid (a div grid and an LCD webfont render the layout for free):

  • A dot is a shutter, and shutters are slow. Every dot chases its target over real tens of milliseconds — rise faster than fall, so moving text drags a trailing ghost. Cutting the power doesn't blank the glass; the ink drains out at crystal speed.
  • The contrast pot is a knob, not a colour. Too low sinks the ink into the ghost lattice; overdriving past ~0.85 raises the undriven dots and grows passive-matrix crosstalk — faint streaks down heavily driven columns, exactly what twisting the trimmer too far does.
  • Boot is the uninitialised controller: power-up shows the top row as solid blocks for a moment — the most recognisable 16×2 symptom there is.
  • CGRAM: 8 custom glyph slots (setGlyph), addressed from text by code points 0–7, 5×8 like the hardware — the bar-chart/animation party trick.
  • age runs the family wear arc at column-driver granularity: dimming, then a flickering column, then a dead blank stripe of bare lattice.
yarn add @glowbox/lcd
import { createLcdModule } from '@glowbox/lcd';

const lcd = createLcdModule(canvas, { cols: 16, rows: 2, text: 'HELLO\nWORLD' });
lcd?.setLine(1, 'READY>');
lcd?.setCursor(6, 1);
lcd?.setOptions({ cursor: 'block' });

Options

| option | default | notes | | ------------ | --------------- | ---------------------------------------------------------------------------------------------- | | cols | 16 | character columns | | rows | 2 | character rows | | text | '' | '\n' splits rows, or one string per row; truncated/padded to the grid | | panel | 'green' | 'green' (STN, readable unlit) · 'blue' (negative — needs its backlight) · 'white' (FSTN) | | backlight | true | true/false or a 0..1 level; on the blue glass it IS the image | | contrast | 0.8 | the trimmer 0..1; past ~0.85 the lattice darkens and crosstalk streaks grow | | response | 0.4 | liquid-crystal speed 0..1 (≈100 ms rise); 0 snaps, 1 is cold glass | | ghost | true | the resting dot lattice | | cursor | 'none' | 'line' (steady underline) · 'block' (blinking); position via setCursor | | age | 0 | wear 0..1: dim → flickering column → dead column | | glyphs | — | extension face over the vendored ASCII font (see below); null resets | | on | true | power; off drains the ink, then the pane sits unlit | | boot | true | the uninitialised boot row (skipped under reduced motion) | | bezel | dark plastic | Color; a frame hugging the glass (canvas past it is transparent); null = none, glass fills | | bezelWidth | 3 | frame thickness in dot pitches (max 16); 0 matches bezel: null | | theme | 'dark' | 'light' / 'auto' bundle the colour defaults (see Themes) | | pixelRatio | 2 | cap on devicePixelRatio | | label | 'lcd display' | accessible name (aria-label); the shown text is appended; '' hides |

Colours are the family Color ([r,g,b] 0..1 or any CSS string). Every option is live-updatable via setOptions(patch).

Handle

setText(text) / setLine(row, text) / setGlyph(slot, rows) / setCursor(col, row) / power(on) drive the module; cellAt(clientX, clientY) and cellRect(x, y) expose the layout maths (viewport coordinates — the family hit-test pair); setOptions, resize, snapshot() (PNG data URL) and dispose() are the family contract. The canvas gets role="img" and an aria-label that reads what the module says.

Custom glyphs (CGRAM)

// A bar-chart glyph in slot 0: 8 rows of 5-bit masks, bit 4 = leftmost dot.
lcd.setGlyph(0, [0, 0, 0, 0b11111, 0b11111, 0b11111, 0b11111, 0]);
lcd.setText('LEVEL ' + '\u0000'.repeat(5)); // text addresses CGRAM by code point

Extension faces (glyphs)

The vendored face covers printable ASCII (repertoire5x7() lists it). Teach the module more by injecting a glyph table — character → 5×7 ASCII art ('#' = ink, 7 rows of 5), the face's own authoring format:

import { createLcdModule, LATIN_5X7 } from '@glowbox/lcd';
createLcdModule(canvas, { glyphs: LATIN_5X7 }); // Å Ä Ö å ä ö Ø ø Æ æ Ü ü ß É é Ñ ñ Ç ç °

LATIN_5X7 is the Western-European/Nordic table — the A02 ROM's territory (the ubiquitous A00 ROM had katakana here and no accents at all; that's what CGRAM was for). It ships in the package but tree-shakes away unless imported. CGRAM code points 0–7 always win over injected glyphs; patch glyphs: null to hand back the plain face. Author your own table in the same art format (compile5x7 gives the raw masks if you need them).

No sound

An LED-backlit module is silent — like the vfd, this core ships no sound module. (The EL-inverter whine of older glass is a niche for the day someone misses it.)

Themes

theme bundles the colour defaults: 'dark' (the default — near-black plastic), 'light' (pale grey plastic), or 'auto' to follow the page's prefers-color-scheme.

The glass is hardware, not a mood: a reflective pane already belongs on a light page, so panel stays your choice and the theme only moves the plastic around it. A bezel you set yourself is yours for good.

Wrappers: @glowbox/svelte · @glowbox/react · @glowbox/vue. Live demo: https://eetu.github.io/glowbox/.