A self-contained sub-program: owns its own state, update logic, and view.
Implements IModel so it can be run standalone via Program.Run or embedded inside a parent model.
Use IComponent<TResult> when the component needs to signal completion and return a typed result to its parent.
Pattern — define one sealed record per logical screen or reusable interactive widget, implement IComponent, and embed it as a typed field in the parent model:
{
public int Counter { get; init; }
{
if (Keys.Handle(msg) is { } action) msg = action;
return msg switch
{
NavUpMsg => (this with { Counter = Counter + 1 }, null),
_ => (this, null),
};
}
public IWidget
View() =>
new TextBlock($
"Count: {Counter}");
}
record AppModel(MyPage Page, ...) : IModel
{
public (IModel
Model,
ICmd? Cmd) Update(IMsg msg)
{
var (next, cmd) = Component.Delegate(Page, msg);
return (this with { Page = next }, cmd);
}
}
Factory for creating common command values.
Definition Cmd.cs:5
Declarative input binding map.
Definition KeyMap.cs:28
KeyMap On(ConsoleKey key, Func< IMsg > handler)
Bind a key (any modifiers) to a message factory.
Definition KeyMap.cs:35
A self-contained sub-program: owns its own state, update logic, and view.
Definition IComponent.cs:53
The root interface for all ConsoleForge application models.
Definition IModel.cs:10
IModel Model
Pure update function.
Definition IModel.cs:23
IWidget View()
Produce the root widget for the current model state.
ICmd? Init()
Called once at program start.
Marker interface for all messages flowing through the event loop.
Definition IMsg.cs:7
record QuitMsg
Signals the program loop to exit cleanly.
Definition Messages.cs:6
delegate Task< IMsg > ICmd()
A command: an async function that produces one message when complete.