class

Phosphor::MockWidget

Inherits Reference < Object

Abstract base for reusable, app-agnostic UI primitives.

A MockWidget owns its internal render state (WidgetState) and responds to generic Cmd values via handle_cmd. It knows nothing about the application's Msg enum, AppState, or theme — those concerns live in the Widget wrapper.

This layer is extractable as a published shard: ListMock, SpinnerMock, and similar primitives have no dependency on any specific application.

Subclasses must define:

  • A Props record carrying only already-resolved Style values.
  • property props : Props typed to the subclass's own Props record.
  • render_content(frame, buf) writing cells via buf.set_string.
  • handle_cmd(cmd) mutating state and returning a CmdResult.

Constructors

new(state : WidgetState = WidgetState.new)

Initialises the widget with an optional state.

state defaults to a freshly-zeroed WidgetState; pass a subclass instance to restore cursor or scroll position across mounts.

Source

Instance methods

animation_interval

How often this widget needs a TickEvent to animate — a spinner's frame advance, an indeterminate progress bar's moving block, a notification's self-dismiss countdown. nil (the default) means it never animates on its own.

View#animation_interval takes the minimum non-nil value across every mounted widget; App#run's main loop uses that to decide how long it can block on event_ch.receive before it needs to wake up and synthesize a tick itself — see App#run's doc comment. This replaces manually mounting a TickPort in Screen#on_mount for widgets that declare their own interval here.

Override to return a value from the subclass's own Props (e.g. props.animation_interval, if that Props record declares one).

Source
handle_cmd(cmd : Cmd) : CmdResult

Responds to cmd, mutating state if appropriate.

Returns CmdResult::Rerender when the widget's visual state changed and a repaint is needed, CmdResult::Bubble to forward an unhandled command to the parent, or CmdResult::None when no repaint is required.

Source
hit_test(x : Int32, y : Int32) : Bool

Returns true if (x, y) falls within the bounds of the Frame this widget was last rendered into. Always false before the first render call. Used by View#dispatch to route mouse events to the widget under the cursor.

Source
preferred_height(width : Int32) : Int32 | Nil

This widget's preferred row count when rendered at the given width, or nil (the default) if it has no natural height — e.g. a widget that always fills whatever frame it's given, rather than wrapping a fixed amount of content.

View#preferred_height sums this across every mounted widget so Terminal#auto_resize can size an Inline session's block to fit its content — see App.run(mode: RenderMode::Inline, height: Terminal::AUTO_HEIGHT). width matters because some widgets wrap (ParagraphMock) or truncate content depending on how much horizontal space they get.

Source
render(frame : Frame, buf : Buffer) : Void

Writes this widget's cells into buf within the bounds of frame.

Records frame for hit_test, then delegates to render_content, which subclasses implement. Not overridden by subclasses.

Source
render_content(frame : Frame, buf : Buffer) : Void

Writes this widget's cells into buf within the bounds of frame.

Implementations must stay inside frame.x..frame.x + frame.width - 1 and frame.y..frame.y + frame.height - 1. All output goes through buf.set_string using Style values from props — never hardcoded ANSI escape sequences.

Source
state
Source
state=(state : WidgetState)
Source

Nested types