13 KiB
13 KiB
Core API Reference
Renderer
createCliRenderer(config?)
Creates and initializes the CLI renderer.
import { createCliRenderer, type CliRendererConfig } from "@opentui/core"
const renderer = await createCliRenderer({
targetFPS: 60, // Target frames per second
exitOnCtrlC: true, // Exit process on Ctrl+C
consoleOptions: { // Debug console overlay
position: ConsolePosition.BOTTOM,
sizePercent: 30,
startInDebugMode: false,
},
onDestroy: () => {}, // Cleanup callback
})
CliRenderer Instance
renderer.root // Root renderable node
renderer.width // Terminal width in columns
renderer.height // Terminal height in rows
renderer.keyInput // Keyboard event emitter
renderer.console // Console overlay controller
renderer.start() // Start render loop
renderer.stop() // Stop render loop
renderer.destroy() // Cleanup and exit alternate screen
renderer.requestRender() // Request a re-render
Console Overlay
renderer.console.show() // Show console overlay
renderer.console.hide() // Hide console overlay
renderer.console.toggle() // Toggle visibility/focus
renderer.console.clear() // Clear console contents
Renderables
All renderables extend the base Renderable class and share common properties.
Common Properties
interface CommonProps {
id?: string // Unique identifier
// Positioning
position?: "relative" | "absolute"
left?: number | string
top?: number | string
right?: number | string
bottom?: number | string
// Dimensions
width?: number | string | "auto"
height?: number | string | "auto"
minWidth?: number
minHeight?: number
maxWidth?: number
maxHeight?: number
// Flexbox
flexDirection?: "row" | "column" | "row-reverse" | "column-reverse"
flexGrow?: number
flexShrink?: number
flexBasis?: number | string
flexWrap?: "nowrap" | "wrap" | "wrap-reverse"
justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly"
alignItems?: "flex-start" | "flex-end" | "center" | "stretch" | "baseline"
alignSelf?: "auto" | "flex-start" | "flex-end" | "center" | "stretch" | "baseline"
alignContent?: "flex-start" | "flex-end" | "center" | "stretch" | "space-between" | "space-around"
// Spacing
padding?: number
paddingTop?: number
paddingRight?: number
paddingBottom?: number
paddingLeft?: number
margin?: number
marginTop?: number
marginRight?: number
marginBottom?: number
marginLeft?: number
gap?: number
// Display
display?: "flex" | "none"
overflow?: "visible" | "hidden" | "scroll"
zIndex?: number
}
Renderable Methods
renderable.add(child) // Add child renderable
renderable.remove(child) // Remove child renderable
renderable.getRenderable(id) // Find child by ID
renderable.focus() // Focus this renderable
renderable.blur() // Remove focus
renderable.destroy() // Destroy and cleanup
renderable.on(event, handler) // Add event listener
renderable.off(event, handler) // Remove event listener
renderable.emit(event, ...args) // Emit event
TextRenderable
Display styled text content.
import { TextRenderable, TextAttributes, t, bold, fg, underline } from "@opentui/core"
const text = new TextRenderable(renderer, {
id: "text",
content: "Hello World",
fg: "#FFFFFF", // Foreground color
bg: "#000000", // Background color
attributes: TextAttributes.BOLD | TextAttributes.UNDERLINE,
selectable: true, // Allow text selection
})
// Styled text with template literals
const styled = new TextRenderable(renderer, {
content: t`${bold("Bold")} and ${fg("#FF0000")(underline("red underlined"))}`,
})
TextAttributes flags:
TextAttributes.BOLDTextAttributes.DIMTextAttributes.ITALICTextAttributes.UNDERLINETextAttributes.BLINKTextAttributes.INVERSETextAttributes.HIDDENTextAttributes.STRIKETHROUGH
BoxRenderable
Container with borders and layout.
import { BoxRenderable } from "@opentui/core"
const box = new BoxRenderable(renderer, {
id: "box",
width: 40,
height: 10,
backgroundColor: "#1a1a2e",
border: true,
borderStyle: "single" | "double" | "rounded" | "bold" | "none",
borderColor: "#FFFFFF",
title: "Panel Title",
titleAlignment: "left" | "center" | "right",
onMouseDown: (event) => {},
onMouseUp: (event) => {},
onMouseMove: (event) => {},
})
InputRenderable
Single-line text input.
import { InputRenderable, InputRenderableEvents } from "@opentui/core"
const input = new InputRenderable(renderer, {
id: "input",
width: 30,
placeholder: "Enter text...",
value: "", // Initial value
backgroundColor: "#1a1a1a",
textColor: "#FFFFFF",
cursorColor: "#00FF00",
focusedBackgroundColor: "#2a2a2a",
})
input.on(InputRenderableEvents.CHANGE, (value: string) => {
console.log("Value:", value)
})
input.focus() // Must be focused to receive input
SelectRenderable
List selection component.
import { SelectRenderable, SelectRenderableEvents } from "@opentui/core"
const select = new SelectRenderable(renderer, {
id: "select",
width: 30,
height: 10,
options: [
{ name: "Option 1", description: "First option", value: "1" },
{ name: "Option 2", description: "Second option", value: "2" },
],
selectedIndex: 0,
})
// Called when Enter is pressed - selection confirmed
select.on(SelectRenderableEvents.ITEM_SELECTED, (index, option) => {
console.log("Selected:", option.name)
performAction(option)
})
// Called when navigating with arrow keys
select.on(SelectRenderableEvents.SELECTION_CHANGED, (index, option) => {
console.log("Browsing:", option.name)
showPreview(option)
})
select.focus() // Navigate with up/down/j/k, select with enter
Event distinction:
ITEM_SELECTED- Enter key pressed, user confirms selectionSELECTION_CHANGED- Arrow keys, user navigating/browsing options
TabSelectRenderable
Horizontal tab selection.
import { TabSelectRenderable, TabSelectRenderableEvents } from "@opentui/core"
const tabs = new TabSelectRenderable(renderer, {
id: "tabs",
width: 60,
options: [
{ name: "Home", description: "Dashboard" },
{ name: "Settings", description: "Configuration" },
],
tabWidth: 20,
})
// Called when Enter is pressed - tab selected
tabs.on(TabSelectRenderableEvents.ITEM_SELECTED, (index, option) => {
console.log("Tab selected:", option.name)
switchToTab(index)
})
// Called when navigating with arrow keys
tabs.on(TabSelectRenderableEvents.SELECTION_CHANGED, (index, option) => {
console.log("Browsing tab:", option.name)
})
tabs.focus() // Navigate with left/right/[/], select with enter
Event distinction (same as SelectRenderable):
ITEM_SELECTED- Enter key pressed, user confirms tabSELECTION_CHANGED- Arrow keys, user navigating tabs
ScrollBoxRenderable
Scrollable container.
import { ScrollBoxRenderable } from "@opentui/core"
const scrollbox = new ScrollBoxRenderable(renderer, {
id: "scrollbox",
width: 40,
height: 20,
showScrollbar: true,
scrollbarOptions: {
showArrows: true,
trackOptions: {
foregroundColor: "#7aa2f7",
backgroundColor: "#414868",
},
},
})
// Add content that exceeds viewport
for (let i = 0; i < 100; i++) {
scrollbox.add(new TextRenderable(renderer, {
id: `line-${i}`,
content: `Line ${i}`,
}))
}
scrollbox.focus() // Scroll with arrow keys
ASCIIFontRenderable
ASCII art text.
import { ASCIIFontRenderable, RGBA } from "@opentui/core"
const title = new ASCIIFontRenderable(renderer, {
id: "title",
text: "OPENTUI",
font: "tiny" | "block" | "slick" | "shade",
color: RGBA.fromHex("#FFFFFF"),
})
FrameBufferRenderable
Low-level 2D rendering surface.
import { FrameBufferRenderable, RGBA } from "@opentui/core"
const canvas = new FrameBufferRenderable(renderer, {
id: "canvas",
width: 50,
height: 20,
})
// Direct pixel manipulation
canvas.frameBuffer.fillRect(10, 5, 20, 8, RGBA.fromHex("#FF0000"))
canvas.frameBuffer.drawText("Custom", 12, 7, RGBA.fromHex("#FFFFFF"))
canvas.frameBuffer.setCell(x, y, char, fg, bg)
Constructs (VNode API)
Declarative wrappers that create VNodes instead of direct instances.
import { Text, Box, Input, Select, instantiate, delegate } from "@opentui/core"
// Create VNode tree
const ui = Box(
{ border: true, padding: 1 },
Text({ content: "Hello" }),
Input({ placeholder: "Type here..." }),
)
// Instantiate onto renderer
renderer.root.add(ui)
// Delegate focus to nested element
const form = delegate(
{ focus: "email-input" },
Box(
{},
Text({ content: "Email:" }),
Input({ id: "email-input", placeholder: "you@example.com" }),
),
)
form.focus() // Focuses the input, not the box
Colors (RGBA)
The RGBA class is exported from @opentui/core but works across all frameworks (Core, React, Solid). Use it for programmatic color manipulation.
Creating Colors
import { RGBA, parseColor } from "@opentui/core"
// From hex string (most common)
RGBA.fromHex("#FF0000") // Full hex
RGBA.fromHex("#F00") // Short hex
// From integers (0-255 range)
RGBA.fromInts(255, 0, 0, 255) // r, g, b, a - fully opaque red
RGBA.fromInts(255, 0, 0, 128) // 50% transparent red
RGBA.fromInts(0, 0, 0, 0) // Fully transparent
// From normalized floats (0.0-1.0 range)
RGBA.fromValues(1.0, 0.0, 0.0, 1.0) // Fully opaque red
RGBA.fromValues(0.1, 0.1, 0.1, 0.7) // Dark gray, 70% opaque
RGBA.fromValues(0.0, 0.5, 1.0, 1.0) // Light blue
Common Color Patterns
// Theme colors
const primary = RGBA.fromHex("#7aa2f7") // Tokyo Night blue
const background = RGBA.fromHex("#1a1a2e")
const foreground = RGBA.fromHex("#c0caf5")
const error = RGBA.fromHex("#f7768e")
// Overlays and shadows
const modalOverlay = RGBA.fromValues(0.0, 0.0, 0.0, 0.5) // 50% black
const shadow = RGBA.fromInts(0, 0, 0, 77) // 30% black
// Borders
const activeBorder = RGBA.fromHex("#7aa2f7")
const inactiveBorder = RGBA.fromInts(65, 72, 104, 255)
parseColor Utility
// Accepts multiple formats
parseColor("#FF0000") // Hex string
parseColor("red") // CSS color name
parseColor("transparent") // Special values
parseColor(RGBA.fromHex("#F00")) // Pass-through RGBA objects
When to Use Each Method
| Method | Use When |
|---|---|
fromHex() |
Working with design specs, CSS colors, config files |
fromInts() |
You have 8-bit values (0-255), common in graphics |
fromValues() |
Doing color interpolation, animations, math |
parseColor() |
Accepting user input or config that could be any format |
Using RGBA in React/Solid
// Import from @opentui/core, use in any framework
import { RGBA } from "@opentui/core"
// React or Solid component
function ThemedBox() {
const bg = RGBA.fromHex("#1a1a2e")
const border = RGBA.fromInts(122, 162, 247, 255)
return (
<box backgroundColor={bg} borderColor={border} border>
<text fg={RGBA.fromHex("#c0caf5")}>Works everywhere!</text>
</box>
)
}
Color props in React/Solid accept both string formats ("#FF0000", "red") and RGBA objects.
Keyboard Input
import { type KeyEvent } from "@opentui/core"
renderer.keyInput.on("keypress", (key: KeyEvent) => {
console.log(key.name) // "a", "escape", "f1", etc.
console.log(key.sequence) // Raw escape sequence
console.log(key.ctrl) // Ctrl held
console.log(key.shift) // Shift held
console.log(key.meta) // Alt held
console.log(key.option) // Option held (macOS)
console.log(key.eventType) // "press" | "release" | "repeat"
})
renderer.keyInput.on("paste", (text: string) => {
console.log("Pasted:", text)
})
Animation Timeline
import { Timeline, engine } from "@opentui/core"
const timeline = new Timeline({
duration: 2000,
loop: false,
autoplay: true,
})
timeline.add(
{ width: 0 },
{
width: 50,
duration: 1000,
ease: "easeOutQuad",
onUpdate: (anim) => {
box.setWidth(anim.targets[0].width)
},
},
)
engine.attach(renderer)
engine.addTimeline(timeline)
Type Exports
import type {
CliRenderer,
CliRendererConfig,
RenderContext,
KeyEvent,
Renderable,
// ... and more
} from "@opentui/core"