Terminosaurus

repository·main·Indexed 42 days ago

https://github.com/arcanis/terminosaurus

A 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.

Tokens
8.2K
Snippets
30
Records
50
Agent score
50%

What's inside Terminosaurus

  1. Overview of Terminosaurus

    main
    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.
  2. What is Terminosaurus?

    main
    Terminosaurus 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.
  3. Understand the TermElement widget concept

    main

    The TermElement widget 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 TermElement and implement the renderContent method to define what appears inside the box.

    In React environments, TermElement is exposed via the <term:div/> component and is typically used to define the high-level application layout.

  4. Compare Terminosaurus with Ink and Blessed

    main

    Terminosaurus 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.
  5. Use the TermEditor widget for syntax-highlighted input

    main
    The TermEditor widget is an enhanced version of the TermInput widget. It provides syntax highlighting capabilities by leveraging vscode-textmate. It is designed for scenarios where users need to input code or structured text that requires visual feedback through highlighting.
  6. How Terminosaurus elements and styles work together

    main

    Terminosaurus uses a tree-based model where elements like TermElement and TermText are appended to one another (e.g., element.appendTo(parent)).

    Layout is managed via CSS-like properties. You can use StyleValues.FlexDirection to control layout flow (e.g., Row or Column) and properties like flexGrow, flexShrink, marginLeft, and marginRight to 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,
      });
    });
  7. Understand the TermScreen class

    main

    The TermScreen class serves as the primary render target for a Terminosaurus application. It functions similarly to the window object in a web browser, acting as the environment where your application lives.

    Crucially, a TermScreen is not a node within the element tree; it is the container/target that exists outside the tree itself.

  8. Use the Terminosaurus React renderer

    main

    Terminosaurus provides a React renderer that allows you to build terminal UIs using familiar JSX syntax. By importing render from terminosaurus/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 like onClick using 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/>);
  9. Start a Terminosaurus application with run()

    main

    To start a terminal application, use the run function imported from terminosaurus. 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. The run function provides a screen object in its callback, which contains the rootNode used for appending elements.

    import {run} from 'terminosaurus';
    
    run(screen => {
      // Your application logic goes here
    });
  10. Handle events in React components

    main

    You can attach event handlers to Terminosaurus React components by using the on prefix 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/>
    );
  11. Use the framework-agnostic Terminosaurus API

    main

    You can use the core Terminosaurus API directly to build interfaces. This involves using run to initialize the terminal environment and interacting with elements like TermText and TermElement. You can manually append elements to the screen.rootNode and attach event listeners using addEventListener on 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();
    });