Kadajett/blECSd: A modern typescript rewrite of blessed, with dozens of modern features, a strict functional architecture, and bitECS as a backend for a fully composable API. Not just for games either! ;)


CI
npm version

dvdBounce

A high-performance terminal UI library built on TypeScript and bitECS.

blECSd provides a complete toolkit for building terminal applications: dashboards, file managers, system monitors, CLI tools, and games. It combines the performance of an Entity Component System with production-ready widgets and form controls.

  • 18 Widgets: Box, Panel, Tabs, List, Table, Tree, VirtualizedList, and more
  • Form Controls: TextInput, Checkbox, RadioButton, Slider, Select, ProgressBar
  • 32 Components: Position, Renderable, Focusable, Interactive, Animation, Collision, etc.
  • 12 Systems: Layout, Input, Render, Animation, Collision, Camera, Drag, Focus, etc.
  • Physics-based Animations: Velocity, acceleration, friction for smooth transitions
  • Virtualized Rendering: Efficiently render 1000s of items
  • State Machines: Built-in FSM support for complex UI state
import {
  createWorld,
  addEntity,
  setPosition,
  setDimensions,
  setBorder,
  setContent,
  createPanel,
  createList,
  createTextInput,
  createEventBus
} from 'blecsd';

// Create a world and entities
const world = createWorld();

// Create a panel with a title
const panel = createPanel(world, {
  x: 2,
  y: 1,
  width: 40,
  height: 10,
  title: 'My Application',
  border: { type: 'rounded' }
});

// Create an interactive list
const list = createList(world, {
  x: 4,
  y: 3,
  width: 36,
  height: 6,
  items: [
    { label: 'Option 1', value: 'opt1' },
    { label: 'Option 2', value: 'opt2' },
    { label: 'Option 3', value: 'opt3' }
  ]
});

// Type-safe events
interface AppEvents {
  'item:selected': { value: string };
}
const events = createEventBusAppEvents>();
events.on('item:selected', (e) => console.log(`Selected: ${e.value}`));

Widget Description
Box Base container with borders, padding, content
Panel Box with title bar, collapsible, close button
Tabs Tabbed container with keyboard navigation
Text Text display with alignment, wrapping
List Selectable list with keyboard/mouse support
Table Data table with headers, columns, sorting
Tree Hierarchical tree view with expand/collapse
VirtualizedList Efficient list for large datasets
ListTable Table-style list display
Listbar Horizontal navigation bar
Line Horizontal/vertical separator
Loading Loading indicator with spinner
ScrollableBox Container with scroll support
ScrollableText Scrollable text area
HoverText Tooltip/hover text display
Layout Flex/grid layout container

Control Description
TextInput Single/multi-line text entry with cursor, selection
Checkbox Boolean toggle with customizable characters
RadioButton Single selection from group
Slider Range value selection, horizontal/vertical
Select Dropdown selection menu
ProgressBar Progress indicator, horizontal/vertical
Form Form field management, validation, submit

blECSd provides ECS components that work with any bitECS world:

Component Purpose
Position X/Y coordinates, z-index, absolute positioning
Renderable Colors, visibility, dirty tracking
Dimensions Width, height, min/max constraints, percentages
Hierarchy Parent-child relationships, traversal
Focusable Keyboard focus, tab order
Interactive Click, hover, drag states
Scrollable Scroll position, content size, scrollbars
Border Box borders (single, double, rounded, bold, ascii)
Content Text content, alignment, wrapping, tag parsing
Padding Inner spacing
Label Text labels with positioning
Animation Frame-based sprite animations
Velocity Movement with speed, friction, max speed
Collision AABB/circle collision detection, layers, triggers
Camera Viewport, target following, bounds
StateMachine Finite state machine with events, transitions
Sprite Sprite sheets, frames
Shadow Drop shadows with opacity, blending
VirtualViewport Virtualized content rendering

See API Reference for the complete list.

System Purpose
inputSystem Process keyboard/mouse input
focusSystem Manage focus, tab navigation
layoutSystem Calculate positions, dimensions
renderSystem Render entities to screen buffer
virtualizedRenderSystem Efficient rendering for large datasets
animationSystem Update sprite animations
movementSystem Apply velocity to position
collisionSystem Detect and resolve collisions
cameraSystem Update camera following target
dragSystem Handle drag and drop
stateMachineSystem Process state machine transitions
outputSystem Write buffer to terminal

blECSd is a library, not a framework:

  1. Components work standalone: Import them into any bitECS world
  2. No required update loop: All systems are callable functions
  3. Mix and match: Use our input parsing with your rendering, or vice versa
  4. You own the world: Functions take world as a parameter; we never hold global state
// Your world, your control
import { createWorld, addEntity, setPosition, setRenderable, layoutSystem, renderSystem } from 'blecsd';

const world = createWorld();
const eid = addEntity(world);

// Use components without our update loop
setPosition(world, eid, 10, 5);

// Call systems when you want
layoutSystem(world);
renderSystem(world);

PackedStore: Cache-Friendly Storage

blECSd includes a PackedStore primitive for systems that iterate over entities in hot paths (rendering, animation, collision). It provides O(1) add/remove/get with dense, cache-friendly iteration.

PackedStore uses four parallel arrays to keep live data contiguous:

data[]        Dense values, packed into [0, size) with no gaps
dataIndex[]   Maps handle.index -> position in data[]
id[]          Maps data position -> handle.index (inverse of dataIndex)
generations[] Generation counter per slot for stale handle detection

Removals use swap-and-pop: the last element fills the gap, so data[] is always contiguous. This means iterating data[0..size] hits sequential memory with no pointer chasing, which is 2-5x faster than Map.forEach for iteration-heavy workloads.

For most code, use createComponentStore() instead of PackedStore directly. It provides a Map-like API (get, set, has, delete, forEach) with two backing modes:

import { createComponentStore } from 'blecsd';

// Iterable mode: backed by PackedStore, dense iteration via forEach/data()
// Use for stores iterated in hot paths (widget rendering, layout, animation)
const renderData = createComponentStoreRenderInfo>({ iterable: true });

// Non-iterable mode (default): backed by a plain Map
// Use for point lookups like callback registries or config
const callbacks = createComponentStore() => void>({ iterable: false });

Mode Backing Iteration Best for
iterable: true PackedStore Dense, cache-friendly Hot paths (render, animate, layout)
iterable: false Map Standard Map iteration Callbacks, config, point lookups

  • Dashboards: System monitors, log viewers, status displays
  • File Managers: Tree views, virtualized lists, panels
  • CLI Tools: Forms, menus, progress indicators
  • Dev Tools: Debug panels, profilers, inspectors
  • Games: Roguelikes, text adventures, puzzle games

Feature blECSd Ink blessed Textual
Architecture ECS + PackedStore (data-oriented) React (component) Class-based Widget classes
Language TypeScript TypeScript/JSX JavaScript Python
Widgets 18 built-in Few built-in Many built-in Many built-in
Animation Physics-based Manual Manual CSS-like
Virtualization Built-in Manual Manual Built-in
Game support First-class Limited Limited Limited

Choose blECSd if you want data-oriented design, physics-based animations, or game development support. Choose Ink for React-style development. Choose Textual for Python projects.

pnpm install
pnpm test
pnpm lint
pnpm build

MIT



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *