@effect-tui/core
v2.0.1
Published
Terminal UI library built with Effect
Downloads
999
Maintainers
Readme
@effect-tui/core
Low-level terminal UI primitives built with Effect.
Installation
bun add @effect-tui/core effectFeatures
- CellBuffer - Frame storage with glyph, style, and width-aware cells
- Palette - Style deduplication for ANSI output
- Colors - Color helpers (indexed, RGB, hex, grayscale)
- Keys - Raw TTY key decoding
- Spring animations - Analytical spring physics
Core Concepts
CellBuffer
A 2D grid of cells, each storing a codepoint, style ID, and width. Handles wide characters (CJK, emoji) correctly.
const buffer = new CellBuffer(80, 24)
buffer.put(0, 0, "Hello", styleId) // Put string
buffer.drawCP(5, 0, 0x1F600, styleId) // Draw codepoint (emoji)
buffer.fillRect(0, 1, 10, 3, 32, styleId) // Fill rectanglePalette
Maps style objects to numeric IDs and generates ANSI escape sequences:
const palette = new Palette()
const style = palette.id({ fg: Colors.green, bg: Colors.black })
const ansi = palette.sgr(style) // "\x1b[32;40m"Colors
Colors.red // Named color (indexed)
Colors.rgb(255,0,0) // RGB
Colors.hex("#ff0000") // Hex
Colors.gray(12) // Grayscale (0-23)
Colors.idx(196) // 256-color indexBasic Usage
import { CellBuffer, Surface, Colors } from "@effect-tui/core"
// Create a buffer
const buffer = new CellBuffer(80, 24)
buffer.put(0, 0, "Hello", { fg: Colors.green })
// Render to terminal
const surface = new Surface(process.stdout)
surface.render(buffer)Animation
MotionValue
Observable values with spring physics (matches framer-motion):
import { motionValue } from "@effect-tui/core"
// Create motion value
const mv = motionValue(0)
// Subscribe to changes
mv.onChange((value) => console.log(value))
// Animate to target with spring physics
mv.animate(100, { duration: 0.35, bounce: 0.2 })
// Read current value
const value = mv.get()Parameters:
duration- Time to reach ~99% of target (seconds)bounce- Overshoot amount (0 = no bounce, 0.5 = bouncy)
Step
Frame-based discrete animation (used by ShinyText):
import { Step } from "@effect-tui/core"
// Create stepper cycling through 10 frames at 80ms/frame
let stepper = Step.init(10, 80)
// Tick with current timestamp
stepper = Step.tick(stepper, Date.now())
console.log(stepper.index) // Current frame indexRelated
- @effect-tui/react - React renderer for terminal UIs
License
MIT
