Module: panel - uhop/console-toolkit GitHub Wiki

The panel.js module provides a Panel class, which is a 2D array of cells corresponding to characters (one position) on the screen. Each cell can be empty (null), or an object with symbol and state properties. See Concepts.

The Panel class works closely with the Box class and strings. All three can be easily converted between each other.

panel.js

import Panel from 'console-toolkit/panel.js';

This module defines the Panel class.

Class Panel

import Panel from 'console-toolkit/panel.js';
import Box from 'console-toolkit/box.js';
import style from 'console-toolkit/style.js';

const panel = new Panel(7, 5),
  box = Box.make('one\ntwo\nthree', {align: 'center'}),
  errorStyle = style.bold.bright.yellow.bg.red;

panel.put(1, 1, box).fillState({state: errorStyle});
for (const line of panel.toStrings()) console.log(line);

This is the most elaborate text container out of three. It provides the following members:

Name Return Description
constructor(width, height) Panel Creates a new Panel object with empty cells.
width number The width of the panel.
height number The height of the panel.
box array The 2D array of cells.
toStrings({emptySymbol = ' ', emptyState = RESET_STATE}) strings Returns the panel as an array of strings. Empty cells are filled with emptySymbol and emptyState.
toBox({emptySymbol = ' ', emptyState = RESET_STATE}) Box Returns the panel as a Box object. Empty cells are filled with emptySymbol and emptyState.
extract(x, y, width, height) Panel Extracts a sub-panel from the panel.
clone() Panel Returns a copy of the panel.
toPanel() Panel An alias for clone().
copyFrom(x, y, width, height, panel, x1 = 0, y1 = 0) this Copies the contents of the panel from the specified rectangle to panel at x1 and y1.
put(x, y, box, {emptySymbol = '\x07'} = {}) this Puts box at x and y treating emptySymbol as an empty cell.

The methods that work on the cell level:

Name Return Description
applyFn(x, y, width, height, fn, options) this Applies fn to every cell in the given rectangle in the panel.
applyFn(fn) this Applies fn to every cell in the panel.
fill(x, y, width, height, symbol, state = {}, options) this Fills the given rectangle in the panel with symbol and state properties.
fill(symbol, state = {}) this Fills the panel with symbol and state properties.
fillState(x, y, width, height, {emptySymbol = ' ', state = ''}) this Fills the given rectangle in the panel with the state property using emptySymbol for empty cells.
fillState({emptySymbol = ' ', state = ''}) this Fills the panel with the state property using emptySymbol for empty cells.
fillNonEmptyState(x, y, width, height, {state = ''}) this Fills the given rectangle of non-empty cells in the panel with the state property.
fillNonEmptyState({state = ''}) this Fills the non-empty cells in the panel with the state property.
combineStateBefore(x, y, width, height, {state = {}, emptySymbol = ' ', emptyState = RESET_STATE}) this Combines the state of the cells in the given rectangle with the state property. Empty cells are assumed to have emptySymbol and emptyState.
combineStateBefore({state = {}, emptySymbol = ' ', emptyState = RESET_STATE}) this Combines the state of the cells in the panel with the state property. Empty cells are assumed to have emptySymbol and emptyState.
combineStateAfter(x, y, width, height, {state = {}, emptySymbol = ' ', emptyState = RESET_STATE}) this Combines the state of the cells in the given rectangle with the state property. Empty cells are assumed to have emptySymbol and emptyState.
combineStateAfter({state = {}, emptySymbol = ' ', emptyState = RESET_STATE}) this Combines the state of the cells in the panel with the state property. Empty cells are assumed to have emptySymbol and emptyState.
combineState(...args) this An alias for combineStateAfter().
clear(x, y, width, height, options) this Clears the given rectangle in the panel making cells empty.
clear() this Clears the panel making cells empty.

The padding methods:

Name Return Description
padLeft(n) this Pads the left side of the panel with n empty cells.
padRight(n) this Pads the right side of the panel with n empty cells.
padLeftRight(n, m) this Pads the left and right side of the panel with n and m empty cells.
padTop(n) this Pads the top side of the panel with n empty rows.
padBottom(n) this Pads the bottom side of the panel with n empty rows.
padTopBottom(n, m) this Pads the top and bottom side of the panel with n and m empty rows.
pad(t, r, b, l) this Pads the panel with t, r, b, and l empty rows/cells.

The removing/inserting and resizing methods:

Name Return Description
removeColumns(x, n) this Removes n columns starting at x.
removeRows(y, n) this Removes n rows starting at y.
insertColumns(x, n) this Inserts n empty columns starting at x.
insertRows(y, n) this Inserts n empty rows starting at y.
resizeH(newWidth, align = 'right') this Resizes the panel horizontally.
resizeV(newHeight, align = 'bottom') this Resizes the panel vertically.
resize(newWidth, newHeight, horizontal = 'right', vertical = 'bottom') this Resizes the panel.

The stacking methods:

Name Return Description
addBottom(panel, {align = 'left'}) this Adds panel to the bottom of the panel.
addRight(panel, {align = 'top'}) this Adds panel to the right of the panel.

The geometric transformation methods:

Name Return Description
transpose() Panel Transposes the panel. It rotates it around the main axis.
rotateRight() Panel Rotates the panel 90 degrees to the right.
rotateLeft() Panel Rotates the panel 90 degrees to the left.
flipH() this Flips the panel horizontally.
flipV() this Flips the panel vertically.

Notes on APIs and semantics

An empty cell is represented by null. They are used when a Panel object is created, when it is padded, when it is cleared, and when rows or columns are inserted. When a panel is converted to a Box or strings, the API takes a symbol and a state, which are used when rendering empty cells. Usually the symbol is space ( ) and the state is RESET_STATE.

Non-empty cells are represented by {symbol, state} objects. symbol should be a string that renders as a single character on the scree. It cannot include ASCI escape sequences, but can be an arbitrary Unicode character. state is an object similar to RESET_STATE. See state for a description of the properties.

constructor() creates a new Panel object with the given width and height filled with empty cells.

put(x, y, box, emptySymbol = '\x07') inserts a text box at the given location. Strings can have SGR sequences, which will be correctly interpreted. emptySymbol defines a character that will be interpreted as an empty cell. By default it is BELL (ASCII 7).

applyFn(x, y, width, height, fn, options) applies fn to every cell in the given rectangle in the panel. It serves as the foundation for all other cell level methods. fn(x, y, cell) takes the position of the cell and the cell object. It returns the new cell object or undefined. The new cell object will replace the old cell. options is an object, which is passed to size() of strings/split.js used to calculate a width of the returned character. Other applyFn()-based methods can take the same options as an argument. See how the methods are defined above.

combineStateAfter() and combineStateBefore() combine the state of the cells in the given rectangle with the state. Empty cells are assumed to have emptySymbol and emptyState. The application of states is not symmetric:

import {Colors, Commands, getColor} from 'console-toolkit/ansi/colors.js';
import {combineStates} from 'console-toolkit/ansi/sgr-state.js';

const state1 = {bold: null, foreground: getColor(Colors.RED)};
const state2 = {bold: Commands.BOLD, background: getColor(Colors.GREEN)};

const before = combineStates(state1, state2);
// {bold: Commands.BOLD, foreground: getColor(Colors.RED), background: getColor(Colors.GREEN)}

const after = combineStates(state2, state1);
// {bold: null, background: getColor(Colors.GREEN), foreground: getColor(Colors.RED)}

So if we want to define some generic properties they should be applied "before". If we want to override the generic properties they should be applied "after".

addRight() and addBottom() stack the panel argument on the current panel. If panels are of different sizes, the extra space of the smaller panel is padded with empty cells.

transpose() rotates the panel around the main axis. If the original panel was 3 by 4, the transposed panel will be 4 by 3:

import Panel from 'console-toolkit/panel.js';

const panel = new Panel(3, 4);
// ...
const transposed = panel.transpose();

panel.width === transposed.height;
panel.height === transposed.width;

t.deepEqual(panel.box[0][0], transposed.box[0][0]);
t.deepEqual(panel.box[3][2], transposed.box[2][3]);

t.deepEqual(panel.box[0][2], transposed.box[2][0]);
t.deepEqual(panel.box[3][0], transposed.box[0][3]);

rotateRight() and rotateLeft() rotate the panel 90 degrees to the right and left, respectively. Just like transpose(), they produce a new panel of H by W size.

Function toPanel()

The toPanel() method is an alias for Panel.make().

Exports

The Panel class is exported by name and as the default export. toPanel() is exported by name.