Skip to main content

a3s_tui/
model.rs

1//! Core model traits for TEA (The Elm Architecture).
2//!
3//! Two traits are provided:
4//! - [`Model`]: String-based rendering (simple, low-level)
5//! - [`ElementModel`]: Element tree rendering (recommended, Flexbox layout)
6
7use crate::cmd::Cmd;
8use crate::element::Element;
9
10/// A TEA model with string-based rendering.
11///
12/// Implement this trait for simple applications that render directly to a string.
13/// For most use cases, prefer [`ElementModel`] which provides Flexbox layout.
14pub trait Model: Send + 'static {
15    type Msg: Send + 'static;
16
17    /// Called once when the program starts. Return a command to perform initialization.
18    fn init(&mut self) -> Option<Cmd<Self::Msg>> {
19        None
20    }
21
22    /// Handle a message and update state. Return an optional command.
23    fn update(&mut self, msg: Self::Msg) -> Option<Cmd<Self::Msg>>;
24
25    /// Render the current state to a string.
26    fn view(&self) -> String;
27
28    /// Where to place the real terminal cursor as `(column, row)`, or `None` to
29    /// keep it hidden. Returning a position shows a normal blinking cursor at the
30    /// text insertion point — the correct behaviour for input fields (including
31    /// wide CJK glyphs), instead of a faked reverse-video block.
32    fn cursor(&self) -> Option<(u16, u16)> {
33        None
34    }
35}
36
37/// A TEA model with Element tree rendering and Flexbox layout.
38///
39/// This is the recommended trait for building terminal UIs. The `view()` method
40/// returns an [`Element`] tree that is laid out using Flexbox and rendered
41/// incrementally.
42pub trait ElementModel: Send + 'static {
43    type Msg: Send + 'static;
44
45    /// Called once when the program starts. Return a command to perform initialization.
46    fn init(&mut self) -> Option<Cmd<Self::Msg>> {
47        None
48    }
49
50    /// Handle a message and update state. Return an optional command.
51    fn update(&mut self, msg: Self::Msg) -> Option<Cmd<Self::Msg>>;
52
53    /// Build the UI element tree from current state.
54    fn view(&self) -> Element<Self::Msg>;
55}