tui_dispatch_core/
component.rs

1//! Component trait for pure UI elements
2
3use ratatui::{layout::Rect, Frame};
4
5use crate::event::{EventKind, EventType};
6use crate::Action;
7
8/// A pure UI component that renders based on props and emits actions
9///
10/// Components follow these rules:
11/// 1. Props contain ALL read-only data needed for rendering
12/// 2. `handle_event` returns actions, never mutates external state
13/// 3. `render` is a pure function of props (plus internal UI state like scroll position)
14///
15/// Internal UI state (scroll position, selection highlight) can be stored in `&mut self`,
16/// but data mutations must go through actions.
17///
18/// # Focus and Context
19///
20/// Components receive `EventKind` (the raw event) rather than the full `Event` with context.
21/// Focus information and other context should be passed through `Props`. This keeps components
22/// decoupled from the specific ComponentId type used by the application.
23pub trait Component {
24    /// Data required to render the component (read-only)
25    type Props<'a>;
26
27    /// Event types this component wants to receive
28    ///
29    /// Return the event types this component should be subscribed to.
30    /// Global events are always delivered regardless of this.
31    fn subscriptions(&self) -> Vec<EventType> {
32        vec![]
33    }
34
35    /// Handle an event and return actions to dispatch
36    ///
37    /// Components receive the raw `EventKind` (key press, mouse event, etc.).
38    /// Focus state and other context should be passed through `Props`.
39    fn handle_event(&mut self, event: &EventKind, props: Self::Props<'_>) -> Vec<impl Action>;
40
41    /// Render the component to the frame
42    fn render(&mut self, frame: &mut Frame, area: Rect, props: Self::Props<'_>);
43
44    /// Get the last rendered area (for hit-testing and focus management)
45    fn area(&self) -> Option<Rect> {
46        None
47    }
48}