@framedev/tui
v0.2.2
Published
Bubbletea-inspired TUI framework for TypeScript/Node.js
Downloads
375
Readme
@framedev/tui
A minimal TUI (Terminal User Interface) framework for TypeScript/Node.js, inspired by Charm's Bubbletea.
Features
- 🎯 Elm Architecture - Predictable state management with Model/Update/View pattern
- ⚡ TypeScript-first - Full type safety
- 🪶 Lightweight - Only 3 dependencies (ansi-escapes, string-width, strip-ansi)
- 🎨 Flexible rendering - Inline or full-screen (alt buffer) modes
- ⌨️ Keyboard input - Arrow keys, special keys, Ctrl combinations
- 🔄 Command system - Built-in async command handling
Installation
pnpm add @framedev/tuiQuick Start
import { Program, type Init, type Update, type View, quit } from '@framedev/tui';
// 1. Define your model (application state)
interface Model {
count: number;
}
// 2. Define your messages (events)
type Msg =
| { type: 'key'; key: string }
| { type: 'quit' };
// 3. Initialize your model
const init: Init<Model, Msg> = () => {
return [{ count: 0 }];
};
// 4. Handle updates
const update: Update<Model, Msg> = (model, msg) => {
switch (msg.type) {
case 'key':
if (msg.key === 'q') return [model, quit()];
if (msg.key === '+') return [{ count: model.count + 1 }];
if (msg.key === '-') return [{ count: model.count - 1 }];
return [model];
default:
return [model];
}
};
// 5. Render your view
const view: View<Model> = (model) => {
return `
Counter: ${model.count}
Press + to increment, - to decrement, q to quit
`.trim();
};
// 6. Run your program
const program = new Program(init, update, view);
program.run();Core Concepts
The Elm Architecture
The framework follows The Elm Architecture pattern with three core concepts:
- Model - Your application state
- Update - How state changes in response to messages
- View - How to display the current state
Commands
Commands allow you to perform async operations:
import { tick, batch } from '@framedev/tui';
const update: Update<Model, Msg> = (model, msg) => {
// Run a command after 1 second
return [model, tick(1000, { type: 'timer' })];
// Run multiple commands
return [model, batch(
fetchDataCmd(),
tick(1000, { type: 'timer' })
)];
};Input Handling
Keyboard input is automatically converted to messages:
- Regular keys:
{ type: 'key', key: 'a' } - Special keys:
enter,backspace,tab,escape - Arrow keys:
up,down,left,right - Ctrl combinations:
{ type: 'key', key: 'c', ctrl: true }
Program Options
const program = new Program(init, update, view, {
altScreen: true, // Use full-screen mode
mouseAllMotion: false, // Enable mouse tracking (future)
});API Reference
Program<Model, Msg>
Main program class that runs the event loop.
Constructor:
new Program(init, update, view, options?)Methods:
run()- Start the programsend(msg)- Send a message to the programquit()- Quit the program
Built-in Commands
quit()- Quit the programtick(delayMs, msg)- Send a message after a delaybatch(...cmds)- Run multiple commands in parallelsequence(...cmds)- Run commands one after anothernone()- No-op command
License
MIT
