# API Reference
A map of the public surface, with the signatures you'll actually call. Full
generated docs live on [docs.rs](https://docs.rs/tui-pages). Signatures here are
abbreviated (bounds elided) for readability.
## Prelude
```rust
use tui_pages::prelude::*;
```
Pulls in the runtime types, the focus types, `modes::*`, `parse_binding`, and —
importantly — the traits `TuiActionHandler`, `FocusController`, and
`PageProvider`. With the `dialog` feature it also brings in `DialogData`,
`DialogResult`, `DialogTheme`, `render_dialog`, and the `dialog::*` helpers.
## Building the app
```rust
TuiPages::builder(initial_view: V) -> TuiPagesBuilder<...>
impl TuiPagesBuilder {
// pages + handler (both required)
fn page_fn(self, f: PageFn<V, S, O>) -> Self; // page provider as a fn
fn pages(self, provider: P) -> Self; // or a custom PageProvider
fn handler(self, h: Handler) -> Self;
// bindings & commands
fn bind(self, mode: impl Into<ModeId>, binding: &str, action: A) -> Self;
fn keymap(self, mode: impl Into<ModeId>, f: impl FnOnce(&mut KeyMap<A>)) -> Self;
fn command(self, name: impl Into<String>, aliases, action: A) -> Self;
// tuning (all optional)
fn fallback_view(self, view: V) -> Self; // view to fall back to on close
fn focus_wrap(self, wrap: FocusWrap) -> Self; // Clamp (default) or Wrap
fn input_timeout_ms(self, ms: u64) -> Self; // chord-sequence timeout
fn command_timeout_ms(self, ms: u64) -> Self;
fn build(self) -> TuiPages<...>;
}
```
`PageFn<V, S, O>` is `fn(&V, &S, Option<&FocusTarget<O>>) -> PageSpec<O>`.
## The runtime: `TuiPages`
Public fields (you **read** these to render; you don't drive them):
```rust
pub input: InputPipeline<A>
pub commands: CommandResolver<A> // resolve typed commands
pub focus: FocusManager<O, M> // focus.current(), focus.has_overlay(), ...
pub buffer: BufferState<V> // buffer.panes(), buffer.is_split(), ...
```
Methods you call:
```rust
fn handle_key(&mut self, key: KeyEvent, state: &mut S)
-> Result<TuiPagesOutput<A>, TuiPagesError<E>>;
fn submit_command(&mut self, input: &str, state: &mut S)
-> Result<TuiPagesOutput<A>, TuiPagesError<E>>;
fn refresh_page(&mut self, state: &S); // re-read the current page spec
fn current_view(&self) -> &V; // active buffer's view
fn apply_effect(&mut self, effect: TuiEffect<V, O, M>, state: &S) -> bool;
```
```rust
pub struct TuiPagesOutput<A> {
pub status: TuiPagesStatus<A>,
pub quit_requested: bool,
}
pub enum TuiPagesStatus<A> {
ActionHandled, TextHandled,
Waiting(Vec<InputHint<A>>), Cancelled,
CommandIncomplete(Vec<CommandHint>), CommandUnknown, CommandEmpty,
}
```
## Your handler
```rust
pub trait TuiActionHandler<V, A, S, O = (), M = ()> {
type Error;
fn handle_action(&mut self, action: A, ctx: ActionContext<V, O>, state: &mut S)
-> Result<ActionOutcome<V, O, M>, Self::Error>;
// default returns ActionOutcome::none(); override for text-input pages
fn handle_text(&mut self, chord: KeyChord, ctx: ActionContext<V, O>, state: &mut S)
-> Result<ActionOutcome<V, O, M>, Self::Error>;
}
pub struct ActionContext<V, O = ()> {
pub current_view: V,
pub focus: Option<FocusTarget<O>>,
pub has_overlay: bool,
}
```
## Effects & outcomes
```rust
pub enum TuiEffect<V, O = (), M = ()> {
None, Focus(FocusIntent<O, M>), Navigate(V),
NextBuffer, PreviousBuffer, CloseBuffer,
SplitPane(PaneSplit), ClosePane, NextPane, PreviousPane,
RefreshPage, Quit,
}
impl ActionOutcome<V, O, M> {
fn none() -> Self;
fn effect(e: TuiEffect<V, O, M>) -> Self;
fn effects(iter: impl IntoIterator<Item = TuiEffect<V, O, M>>) -> Self;
}
```
## Pages & focus
```rust
pub struct PageSpec<O = ()> { /* see Core Concepts */ }
impl PageSpec<O> {
fn new() -> Self;
fn focus(self, builder: PageFocusBuilder<O>) -> Self; // prefer this
fn focus_targets(self, targets: Vec<FocusTarget<O>>) -> Self;
fn modes(self, modes: impl IntoIterator<Item = ModeId>) -> Self;
fn accepts_text_input(self, yes: bool) -> Self;
}
impl PageFocusBuilder<O> {
fn new() -> Self;
fn button(self, index: usize) -> Self;
fn buttons(self, indices: &[usize]) -> Self;
fn section(self, id: usize) -> Self;
fn section_with_items(self, id: usize, item_count: usize) -> Self;
fn canvas_field(self, index: usize) -> Self;
fn canvas_fields(self, count: usize) -> Self;
fn internal_canvas_field(self, index: usize) -> Self;
fn target(self, t: FocusTarget<O>) -> Self;
fn build(self) -> Vec<FocusTarget<O>>;
}
pub enum FocusTarget<O = ()> {
Button(usize), Section(usize), SectionItem { section: usize, item: usize },
CanvasField(usize), InternalCanvasField(usize),
Overlay(O), ModalItem(usize), Custom(String),
}
pub enum FocusIntent<O = (), M = ()> {
Next, Prev, Activate, LeaveSection,
Set(FocusTarget<O>), Open(FocusTarget<O>), Close(FocusTarget<O>),
Toggle(FocusTarget<O>), ClearOverlay,
EnterSection { item_count: usize },
ExitCanvasForward, ExitCanvasBackward,
ShowModal { data: M, count: usize }, UpdateModal { data: M, count: usize },
RegisterPage(Vec<FocusTarget<O>>),
RegisterPageAndEnterSection { targets: Vec<FocusTarget<O>>, section: usize, item_count: usize, item: usize },
}
pub enum FocusWrap { Clamp, Wrap }
```
`FocusManager` — read-only from your side:
```rust
fn current(&self) -> Option<FocusTarget<O>>;
fn is_focused(&self, target: &FocusTarget<O>) -> bool;
fn has_overlay(&self) -> bool;
fn focus_wrap(&self) -> FocusWrap;
fn clear_overlay(&mut self); // used when closing an app-owned palette
```
## Input
```rust
fn parse_binding(s: &str) -> Vec<KeyChord>; // lenient, drops bad tokens
fn parse_key(s: &str) -> Option<KeyChord>;
fn try_parse_binding(s: &str) -> Result<Vec<KeyChord>, ParseKeyError>; // strict
fn try_parse_key(s: &str) -> Result<KeyChord, ParseKeyError>;
impl KeyChord {
fn from_event(event: &KeyEvent) -> Self;
fn display_string(&self) -> String;
pub code: KeyCode,
pub modifiers: KeyModifiers,
}
```
There is no `FromStr`/`parse()` on `KeyChord` — use the functions above.
## Commands
```rust
pub enum CommandResponse<A> { Execute(A), Incomplete(Vec<CommandHint>), Unknown, Empty }
pub struct CommandHint { pub alias: String, pub action_name: String }
impl CommandResolver<A> { // available as tui.commands
fn process(&self, input: &str) -> CommandResponse<A>;
fn get_feedback(&self, input: &str) -> Option<String>;
}
```
## Navigation
```rust
pub enum PaneSplit { Horizontal, Vertical }
impl BufferState<V> { // available as tui.buffer (read-only use)
fn get_active_view(&self) -> Option<&V>;
fn is_split(&self) -> bool;
fn split_direction(&self) -> Option<PaneSplit>;
fn panes(&self) -> &[PaneSession<V>];
fn active_pane_index(&self) -> usize;
}
```
You drive buffers and panes through `TuiEffect`, not through these mutators.
## Dialog (feature `dialog`)
```rust
pub struct DialogData<D = ()> {
pub title: String, pub message: String,
pub buttons: Vec<String>, pub purpose: Option<D>, pub is_loading: bool,
}
impl DialogData<D> {
fn new(title, message, buttons, purpose: D) -> Self;
fn loading(title, message) -> Self;
fn show_intent<O>(self) -> FocusIntent<O, DialogData<D>>;
}
pub enum DialogResult<D> { Selected { purpose: Option<D>, index: usize }, Dismissed }
pub enum DialogKey<D> { Ignored, Consumed, Resolved(DialogResult<D>) }
// helpers
fn dialog::handle_key<O, D>(focus: &mut FocusManager<O, DialogData<D>>, key: KeyEvent) -> DialogKey<D>;
fn dialog::current_dialog<O, D>(focus: &FocusManager<O, DialogData<D>>) -> Option<&DialogData<D>>;
fn dialog::active_button<O, D>(focus: &FocusManager<O, DialogData<D>>) -> Option<usize>;
fn render_dialog<D>(f: &mut Frame, area: Rect, data: &DialogData<D>, active_button: usize, theme: &DialogTheme);
```
## Terminal
```rust
fn tui_pages::terminal::enter() -> io::Result<TerminalGuard>;
```
Enables raw mode + the alternate screen and returns a guard that restores the
terminal when it drops — including on a panic.