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

malevich-tui-components

v0.21.1

Published

A headless, renderer-agnostic TUI component library: layout and interaction algorithms only. Color, text measurement, key semantics, and terminal compositing are all host-supplied ports; components run unmodified against any host matching the Component/Fo

Readme

Malevich

A headless, renderer-agnostic TUI component library — layout and interaction algorithms only. Color, text measurement, key semantics, and terminal compositing are all host-supplied ports, not something Malevich owns or hardcodes; it depends only on the Component/Focusable interface shape, not on any specific TUI framework's package, so a component runs unmodified on any host whose types match that shape, e.g. @earendil-works/pi-tui or @dpopsuev/alef-tui.

Install

bun add malevich-tui-components

Usage

import { Table } from "malevich-tui-components";

const table = new Table({
  columns: [{ header: "Engine", key: "engine" }, { header: "Credits", key: "credits" }],
  rows: [{ engine: "tavily", credits: "2" }],
});

// Mount it however your host TUI framework mounts a Component --
// e.g. inside Pi's ctx.ui.custom().
console.log(table.render(80).join("\n"));

Pass a host's own visibleWidth/truncateToWidth (both pi-tui and alef-tui export these) via the measure option for correct Unicode/ANSI handling; components default to plain-ASCII measurement otherwise.

Components

| Component | Description | |---|---| | Table | Tabular data with auto-sized or fixed column widths, alignment, and a header separator. | | ProgressBar | A single-line label filled/empty-bar pct% meter. | | Dialog | A bordered title+body+action-hints dialog, dispatching to the matching action on its key. framed: false omits its own top/bottom rule for nesting inside a host's own already-drawn border (e.g. an Envelope). | | Toast | A single auto-dismissing message (or wrapped Component). | | NotificationQueue | A capped, auto-expiring queue of leveled (info/success/warning/error) notifications. | | ScrollView | Wraps a child in a fixed-height, vertically scrollable viewport with an optional scrollbar. | | SplitPane | Two children side by side, separated by a border, split by a ratio. | | Collapsible | A toggleable header that shows/hides a wrapped child. | | CollapsibleText | A collapsible block for long text, showing the first N lines behind a toggle. | | TreeView | A labeled tree with box-drawing connectors; nodes may embed a child Component and/or nested children. | | Menu | A bordered, keyboard-navigable action list with per-item shortcut keys. | | MultiSelectList | A bounded checkbox list with a focus-following row viewport, optional action rows, shortcuts, and separate state-model access for direct tests. | | Badge | A single-line label: count indicator, abbreviating large counts (1.5k, 2.0M). | | SeparatorLine | A full-width rule with optional embedded left/right labels. | | Envelope | A bordered, collapsible box with the title embedded in the top border. | | Card | A bordered entity surface with caller-supplied title/content/footer lines and explicit selected/unselected frame and body styles. | | BorderedSelectPanel | Wraps a host-provided list Component (e.g. the host's own SelectList) in a border+title+help-text scaffold -- formalizes a pattern found hand-rolled in five separate real codebases. Owns no selection logic itself. framed: false omits its own top/bottom rule for nesting inside a host's own already-drawn border (e.g. an Envelope). | | MaskedInput | A single-line input rendering only mask glyphs, with bracketed-paste handling. Generalized from Enigma's own. | | Form | An N-field Tab/Shift+Tab-navigable form with required-field validation, keyed to a Record result. Composes with the host's own text inputs and Malevich's MaskedInput. | | HistoryChart | A cumulative, stacked-by-series ASCII bar chart with a Y-axis scale, an optional budget threshold line, X-axis time labels, and a legend. | | Text | Plain "render a string, styled and fit to width" primitive -- truncates or word-wraps to the render width. | | Board | A multi-column card board (Kanban-style): items grouped into columns, keyboard-navigable selection (arrow keys move between cards, skipping empty columns), caller-supplied card rendering. | | TabMenu | A horizontal tab bar that can descend into child levels -- Enter on a branch node walks down into its children, Escape walks back up (or cancels at the root). A leaf node resolves onSelect with its value; a mnemonic character jumps to and activates a node in one step. | | TabbedContainer | A persistent tab bar (every tab's label always visible) over one swappable child Component -- the composable primitive for hosting several sibling features (Packages/Find/Config/Settings, say) in one long-lived overlay instead of each closing and opening its own. Left/Right or Tab/Shift-Tab cycle; a mnemonic character jumps directly, defaulting to a tab's own first letter or set explicitly when two labels would collide on it. Every other key delegates straight to the active tab's own content. | | Spinner | A tiny indeterminate-progress ticker for a single in-flight async call with no discrete step count -- renders no chrome of its own, a host embeds glyph() inline (a table cell, a status line, a dialog). |

Utilities

| Export | Description | |---|---| | GlyphSet / unicodeGlyphs / asciiGlyphs | Injectable rule/tree-connector characters, accepted via glyphs on Table, Dialog, BorderedSelectPanel, SeparatorLine, and TreeView -- swap in asciiGlyphs for terminals/fonts that render box-drawing poorly. Every component defaults to unicodeGlyphs. | | deriveTableColumns | Given unknown[], derives Table-ready columns/rows when every item is a plain object: unions the keys, stringifies non-string values. Returns undefined for non-tabular input. | | firstDistinctStyle | Given a baseline-styled string and candidate-styled strings (in preference order), returns the first candidate that's visually distinct from the baseline, else a fallback -- the fix for a theme that maps two semantic color tokens to the same underlying color, making a more specific token look identical to plain text. | | renderFramedPanel | The rule+title+content+rule scaffold shared by Dialog, Menu, and BorderedSelectPanel -- assembly only, callers pass already-styled/measured lines. | | KeyMatcher / legacyKeyMatcher | Injectable named-key recognition (matchesKey(data, keyId)), accepted via matchesKey on Board, TabMenu, TabbedContainer, Form, MaskedInput, Menu, ScrollView, and Dialog -- pass a host's real matcher (Kitty-protocol-aware) instead of the small legacy-sequences-only default. | | findMnemonicConflicts / assertNoMnemonicConflicts | Tree-style accelerator-key conflict detection -- given a MnemonicContext tree describing which key bindings are reachable together (a root's own plus whichever single child is active), reports any key bound to more than one distinct action along a path. Meant to run as a standing test assertion against a real application's own keybinding tree. |

License

MIT. The Table component and the Component/Focusable interfaces are adapted from Mario Zechner's pi-tui/alef-tui (also MIT) — see LICENSE.

Development

bun install
bun test
bun x tsc --noEmit
bun run build