TermUI.Component.Helpers (TermUI v0.2.0)
View SourceCommon helper functions and macros for TermUI components.
This module is automatically imported when you use TermUI.Component.
It provides convenience functions for building render trees and
working with props and styles.
Render Tree Builders
text/1,text/2- Create text nodesbox/1,box/2- Create box containersstack/2,stack/3- Create stacked layouts
Props Helpers
props!/2- Validate and extract required props
Style Helpers
merge_styles/2- Merge multiple stylescompute_size/2- Calculate content dimensions
Summary
Functions
Creates a box container.
Delegates to RenderNode.cells/2 for creating cell-based render nodes.
Computes the size of a render node.
Computes the display size of text content.
Creates an empty node.
Checks if a value fits within a rect.
Merges multiple styles in order, with later styles overriding earlier ones.
Creates a positioned cell for use with RenderNode.cells/2.
Validates and extracts props with type checking and defaults.
Creates a stack layout.
Creates a styled wrapper around a node.
Creates a text node.
Truncates text to fit within a given width.
Functions
@spec box( [TermUI.Component.RenderNode.t()], keyword() ) :: TermUI.Component.RenderNode.t()
Creates a box container.
Examples
box([text("Content")])
box([text("Styled")], style: Style.new() |> Style.bg(:blue))
@spec cells( [TermUI.Component.RenderNode.positioned_cell()], keyword() ) :: TermUI.Component.RenderNode.t()
Delegates to RenderNode.cells/2 for creating cell-based render nodes.
Examples
cells = [positioned_cell(0, 0, "H"), positioned_cell(1, 0, "i")]
cells(cells)
@spec compute_node_size(TermUI.Component.RenderNode.t()) :: {non_neg_integer() | :auto, non_neg_integer() | :auto}
Computes the size of a render node.
For text nodes, returns the text dimensions.
For containers, returns explicit size or :auto.
Examples
compute_node_size(text("Hello"))
# {5, 1}
compute_node_size(box([], width: 20, height: 10))
# {20, 10}
@spec compute_size(String.t()) :: {non_neg_integer(), non_neg_integer()}
Computes the display size of text content.
Returns {width, height} where width is the maximum line length
and height is the number of lines.
Examples
compute_size("Hello")
# {5, 1}
compute_size("Line 1\nLine 2")
# {6, 2}
@spec empty() :: TermUI.Component.RenderNode.t()
Creates an empty node.
Examples
empty()
@spec fits_in_rect?( {non_neg_integer(), non_neg_integer()}, TermUI.Component.rect() ) :: boolean()
Checks if a value fits within a rect.
Examples
fits_in_rect?({10, 5}, %{x: 0, y: 0, width: 20, height: 10})
# true
fits_in_rect?({30, 5}, %{x: 0, y: 0, width: 20, height: 10})
# false
@spec merge_styles([TermUI.Renderer.Style.t() | nil]) :: TermUI.Renderer.Style.t()
Merges multiple styles in order, with later styles overriding earlier ones.
Follows CSS cascade rules - later values take precedence, attributes combine.
Examples
base = Style.new() |> Style.fg(:white)
override = Style.new() |> Style.fg(:red) |> Style.bold()
merge_styles([base, override])
# Result: fg: :red, attrs: [:bold]
@spec positioned_cell( non_neg_integer(), non_neg_integer(), String.t(), TermUI.Renderer.Style.t() | nil ) :: TermUI.Component.RenderNode.positioned_cell()
Creates a positioned cell for use with RenderNode.cells/2.
Examples
cell = positioned_cell(0, 0, "A", Style.new() |> Style.fg(:red))
# %{x: 0, y: 0, cell: %Cell{char: "A", fg: :red}}
Validates and extracts props with type checking and defaults.
Raises ArgumentError if required props are missing or types don't match.
Spec Format
Each prop spec is a tuple: {name, type, opts}
Types: :string, :integer, :boolean, :atom, :any, :style
Options:
:required- Prop must be present (default: false):default- Default value if not provided
Examples
props!(props, [
{:text, :string, required: true},
{:count, :integer, default: 0},
{:enabled, :boolean, default: true}
])
# Returns %{text: "...", count: 0, enabled: true}
@spec stack( TermUI.Component.RenderNode.direction(), [TermUI.Component.RenderNode.t()], keyword() ) :: TermUI.Component.RenderNode.t()
Creates a stack layout.
Examples
stack(:vertical, [text("Top"), text("Bottom")])
stack(:horizontal, [text("Left"), text("Right")])
@spec styled(TermUI.Component.RenderNode.t(), TermUI.Renderer.Style.t()) :: TermUI.Component.RenderNode.t()
Creates a styled wrapper around a node.
Examples
styled(text("Hello"), Style.new() |> Style.fg(:red))
@spec text(String.t(), TermUI.Renderer.Style.t() | nil) :: TermUI.Component.RenderNode.t()
Creates a text node.
Examples
text("Hello, World!")
text("Styled", Style.new() |> Style.fg(:red))
@spec truncate_text(String.t(), non_neg_integer()) :: String.t()
Truncates text to fit within a given width.
Examples
truncate_text("Hello, World!", 5)
# "Hello"
truncate_text("Hi", 10)
# "Hi"