Terminosaurus
repository·main·Indexed 42 days ago
https://github.com/arcanis/terminosaurusA DOM-like UI library for TypeScript to build complex graphical terminal interfaces. It features a framework-agnostic core API and a dedicated React renderer, supporting Flexbox layout, CSS-like properties, event listeners, and text wrapping. Version 3.0.0-rc.11.
What's inside Terminosaurus
- Terminosaurus is a DOM-like UI library for TypeScript designed to build graphical terminal interfaces. It abstracts away complex positioning and state updates, providing a way to manage terminal UIs using concepts similar to the web DOM. It features a framework-agnostic core API, a dedicated React renderer, advanced layout positioning, event handlers, text wrapping, and CSS-like properties.
What is Terminosaurus?
mainTerminosaurus is an open-source terminal GUI library designed to simplify the creation of terminal applications. It features a framework-agnostic core API and provides a powerful React renderer for building complex terminal interfaces using a component-based approach.Understand the TermElement widget concept
mainThe
TermElementwidget is the foundational building block for all other widgets in Terminosaurus. It manages the rectangular geometry of a widget, including positioning, bounding box computation, and border rendering.To create a custom widget, you inherit from
TermElementand implement therenderContentmethod to define what appears inside the box.In React environments,
TermElementis exposed via the<term:div/>component and is typically used to define the high-level application layout.Use the TermInput widget
mainTheTermInputwidget is an extension of theTermTextwidget. It provides the same text rendering capabilities but adds support for focus management and keyboard events, making it suitable for interactive text entry.Compare Terminosaurus with Ink and Blessed
mainTerminosaurus distinguishes itself from other terminal UI libraries through its framework-agnostic core, comprehensive support for Flexbox layout, relative/absolute positioning, focus management, scrolling, text alignment, text wrapping, and extensive CSS property support.
Key comparisons:
- Ink: Supports React and Flexbox, but lacks relative/absolute positioning, scrolling, text alignment/wrapping, and full CSS property support.
- Blessed: Lacks framework-agnostic API, Flexbox, positioning, focus management, scrolling, and text alignment/wrapping. React support is limited via unmaintained third-party adapters.
Use the TermEditor widget for syntax-highlighted input
mainTheTermEditorwidget is an enhanced version of theTermInputwidget. It provides syntax highlighting capabilities by leveragingvscode-textmate. It is designed for scenarios where users need to input code or structured text that requires visual feedback through highlighting.How Terminosaurus elements and styles work together
mainTerminosaurus uses a tree-based model where elements like
TermElementandTermTextare appended to one another (e.g.,element.appendTo(parent)).Layout is managed via CSS-like properties. You can use
StyleValues.FlexDirectionto control layout flow (e.g.,RoworColumn) and properties likeflexGrow,flexShrink,marginLeft, andmarginRightto position elements within containers. This allows for complex, responsive terminal UIs where child elements react to the size and state of their parents.import { StyleValues, TermElement, TermText, color, length, run, } from 'terminosaurus'; run(screen => { const container = new TermElement(); container.appendTo(screen.rootNode); // ... setup elements ... container.style.reset({ flexDirection: StyleValues.FlexDirection.Row, }); const barContainer = new TermElement(); barContainer.appendTo(container); barContainer.style.reset({ marginLeft: length(2), marginRight: length(2), flexGrow: 1, flexShrink: 1, }); });Understand the TermScreen class
mainThe
TermScreenclass serves as the primary render target for a Terminosaurus application. It functions similarly to thewindowobject in a web browser, acting as the environment where your application lives.Crucially, a
TermScreenis not a node within the element tree; it is the container/target that exists outside the tree itself.Use the Terminosaurus React renderer
mainTerminosaurus provides a React renderer that allows you to build terminal UIs using familiar JSX syntax. By importing
renderfromterminosaurus/react, you can mount a React component tree to the terminal. You can use custom elements (e.g.,<term:div>) within your components to represent terminal UI elements and handle events likeonClickusing standard React patterns.import { useState } from 'react' import { render, } from 'terminosaurus/react'; function App() { const [counter, setCounter] = useState(0); const increaseCounter = () => { setCounter(counter + 1); }; return ( <term:div onClick={increaseCounter}> Counter: {counter} </term:div> ); } render({}, <App/>);Start a Terminosaurus application with run()
mainTo start a terminal application, use the
runfunction imported fromterminosaurus. This is the preferred way to initialize your app because it automatically handles the asynchronous loading of required WASM modules and waits for the application to complete before returning. Therunfunction provides ascreenobject in its callback, which contains therootNodeused for appending elements.import {run} from 'terminosaurus'; run(screen => { // Your application logic goes here });Handle events in React components
mainYou can attach event handlers to Terminosaurus React components by using the
onprefix followed by the event name (e.g.,onClick). This allows you to integrate standard React state management with terminal interactions.import {useState} from 'react'; import {render} from 'terminosaurus/react'; function Counter() { const [count, setCount] = useState(0); return ( <term:div onClick={() => setCount(count + 1)}> Clicked {count} times </term:div> ); } render( <Counter/> );Use the framework-agnostic Terminosaurus API
mainYou can use the core Terminosaurus API directly to build interfaces. This involves using
runto initialize the terminal environment and interacting with elements likeTermTextandTermElement. You can manually append elements to thescreen.rootNodeand attach event listeners usingaddEventListeneron element event properties (e.g.,onClick).import { TermElement, TermText, run, } from 'terminosaurus'; run({}, async screen => { const text = new TermText(); text.appendTo(screen.rootNode); let counter = 0; const increaseCounter = () => { counter += 1; text.setText(`Counter: ${counter}`); }; text.onClick.addEventListener(() => { increaseCounter(); }); increaseCounter(); });