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

@tern-tui/core

v0.2.0

Published

tern core — TypeScript bindings for the tern TUI engine

Downloads

296

Readme

@tern/core

TypeScript bindings for the tern TUI engine. This package wraps the tern-node napi addon (the Rust core) behind a small declarative API: a renderer owns the terminal (raw mode + alternate screen), scene nodes are built with factory functions, and an event loop pulls input back from the Rust side.

Purpose

@tern/core is the single JS surface over the engine. It is renderer-agnostic: @tern/react and @tern/solid both drive the same node/factory API, so a scene built with the core factories renders identically under either reconciler. All engine logic stays in Rust (constitution) — the JS side only describes the scene and reads events.

API surface

Renderer

  • createRenderer({ exitOnCtrlC }) — construct a Renderer (enters raw mode
    • alternate screen). exitOnCtrlC: true tears the terminal down on Ctrl+C instead of surfacing it as an event.
  • Rendererroot (the scene root Node), render() (paint the scene), pollEvents(timeoutMs) (pull native events, feeding the handlers), onKey / onResize / onFocus / onMouse / onPaste (each returns an unsubscribe), hit_test(col, row) (z-ordered node ids covering a cell), destroy(), destroyed.

Scene nodes

  • NodeaddChild / insertBefore / remove (tree ops), setProps (replace props + style), appendSpan(text, style) (streaming feed), contentSize() (laid-out content size), children / props / type / attached.
  • Element factories (pure data until attached): Text(props), Box(props, ...children), StreamingText(props).

Roadmap element factories (compositions over the primitives; no new napi node kinds)

  • Input (+ editKey) — framed box with a caret-painted text leaf.
  • Spinner (+ tick, DEFAULT_SPINNER_FRAMES) — determinate bar or indeterminate frame glyph.
  • StatusBar — single-row left/center/right segment strip.
  • Panels (+ collapsePanel / expandPanel / togglePanel / focusPanel, and the drag-resize helpers startPanelDrag / dragPanels / endPanelDrag, PANEL_DRAG_MIN_SIZE) — collapsible header/body stack with a 1-cell drag gutter.
  • DiffView (+ DIFF_ADD_FG / DIFF_DEL_FG) — unified or side-by-side diff rows: gutter, +/-/ markers, per-kind colors, mode="side" two-column layout, inline_highlight intra-line highlighting, wrap passthrough, scroll_x / scroll_y panning.
  • Select (+ selectKey, visibleOptions, SELECT_FILTER_PLACEHOLDER) — filterable option list, multi checkmarks, floating overlay.
  • ScrollView (+ scrollTo / scrollBy / scrollTop, SCROLLBAR_THUMB_CHAR / SCROLLBAR_TRACK_CHAR) — clip/scroll region with an optional track + thumb scrollbar.

Streaming auto-scrollsetStreamAutoScroll, isStreamFollowing, syncStreamTail (pin scroll_y to the stream tail after each append), followTail (re-attach after a manual scroll), scrollToBottom (a one-shot jump to the tail that dismisses the affordance — STREAM_AFFORDANCE_CHAR, stamped when a manual scroll above the tail detaches the follow — without re-attaching).

ThemeTheme / ThemeOverrides types, defaultTheme, mergeTheme(base, overrides), resolveTheme(theme, props) (stamps plain fg/bg/border_style from role/component hints).

FocusFocusManager (class), focusManager (default instance), useFocus(id, node, onKey, manager?, onPaste?), routePaste (paste counterpart of routeKey).

TypesNodeProps, NodeType, KeyEvent, KeyHandler, ResizeHandler, FocusHandler, MouseHandler, Span, Renderer, TernEventJs, ContentSize, MouseEventJs, NodeHandle, TuiRendererOptions, TuiRenderer (napi types re-exported from tern-node's index.d.ts).

Example

import { createRenderer, Box, Text } from "@tern/core";

const renderer = createRenderer({ exitOnCtrlC: true });
renderer.root.addChild(
  Box({ border_style: "rounded", padding: 1 }, Text({ text: "Hello" })),
);
renderer.render();

let quit = false;
renderer.onKey((event) => {
  if (event.name === "char" && event.char === "q") quit = true;
});
while (!quit && !renderer.destroyed) {
  renderer.pollEvents(50);
}
renderer.destroy();

Runtime

Deno-first: the native addon is loaded via node:module createRequire (./addon.ts), which Deno 2.x supports for Node-API addons with --allow-ffi (+ read access to the .node file). Node.js works unchanged. Check with deno check src/index.ts, test with deno test src.

Documentation

See docs/guide.md for the getting-started guide, docs/components.md for the component overview, and README.md for quick-starts using the @tern/react / @tern/solid renderers.