//! Cocotte provides a convenient way to build Ratatui terminal applications by composing independent sub-apps.
//!
//! Define:
//! - an `Event` type to represent application inputs such as keys, ticks, or setup events
//! - a `State` type to hold shared application data
//! - several [`SubApp`]s for input handling and rendering. Each subapp handles the `Event`s and renders
//!
//! Then use the [`define_sub_apps`] macro to combine them all into a single app. The macro provides the `make_app` function that creates your app for you.
//!
//! # Example
//!
//! ```no_run
//! use cocotte::eyre::Result;
//! use cocotte::ratatui::layout::{Constraint, Rect};
//! use cocotte::ratatui::widgets::{Block, Borders};
//! use cocotte::ratatui::Frame;
//! use cocotte::{define_sub_apps, SubApp};
//! use crossterm::event::{self, Event, KeyCode, KeyEvent};
//!
//! #[derive(Clone, Debug)]
//! enum AppEvent {
//!     Tick,
//!     Key(KeyEvent),
//! }
//!
//! #[derive(Default)]
//! struct State {
//!     should_quit: bool,
//! }
//!
//! struct Pane;
//!
//! impl Pane {
//!     fn new() -> Self {
//!         Self
//!     }
//! }
//!
//! impl SubApp<AppEvent, State> for Pane {
//!     fn handle_input(&mut self, event: &mut AppEvent, state: &mut State) {
//!         if let AppEvent::Key(KeyEvent {
//!             code: KeyCode::Char('q') | KeyCode::Esc,
//!             ..
//!         }) = event
//!         {
//!             state.should_quit = true;
//!         }
//!     }
//!
//!     fn render(&self, frame: &mut Frame, area: Rect, _state: &mut State) {
//!         let block = Block::default().borders(Borders::ALL).title("Pane");
//!         frame.render_widget(block, area);
//!     }
//!
//!     fn constraints(&self) -> Constraint {
//!         Constraint::Fill(1)
//!     }
//! }
//!
//! define_sub_apps! {
//!     event = AppEvent;
//!     state = State;
//!     Pane(Pane) => Pane::new(),
//! }
//!
//! fn main() -> Result<()> {
//!     let mut app = make_app()?;
//!     let mut state = State::default();
//!     let mut setup = AppEvent::Tick;
//!     app.handle_input(&mut setup, &mut state);
//!
//!     while !state.should_quit {
//!         app.draw(&mut state)?;
//!
//!         if let Event::Key(key) = event::read()? {
//!             let mut event = AppEvent::Key(key);
//!             app.handle_input(&mut event, &mut state);
//!         }
//!     }
//!
//!     Ok(())
//! }
//! ```

pub mod app;
pub mod sub_app;

pub use app::App;
pub use eyre;
pub use ratatui;
pub use sub_app::SubApp;
