ratkit 0.2.16

A comprehensive collection of reusable TUI components for ratatui including resizable splits, tree views, markdown rendering, toast notifications, dialogs, and terminal embedding
Documentation
use crossterm::event::KeyCode;
use ratatui::buffer::Buffer;
use ratatui::layout::{Alignment, Rect};
use ratatui::style::{Color, Style};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DialogType {
    Info,
    Success,
    Warning,
    Error,
    Confirm,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DialogActionsLayout {
    Horizontal,
    Vertical,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DialogWrap {
    WordTrim,
    WordNoTrim,
    NoWrap,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DialogModalMode {
    Blocking,
    Passthrough,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DialogShadow {
    None,
    Soft,
    Medium,
    Strong,
    Custom {
        offset_x: u16,
        offset_y: u16,
        style: Style,
    },
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DialogPadding {
    pub horizontal: u16,
    pub vertical: u16,
}

impl Default for DialogPadding {
    fn default() -> Self {
        Self {
            horizontal: 1,
            vertical: 0,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DialogFooter<'a> {
    Hidden,
    Text(&'a str),
}

#[derive(Debug, Clone)]
pub struct DialogKeymap {
    pub next: Vec<KeyCode>,
    pub previous: Vec<KeyCode>,
    pub confirm: Vec<KeyCode>,
    pub cancel: Vec<KeyCode>,
    pub close: Vec<KeyCode>,
}

impl Default for DialogKeymap {
    fn default() -> Self {
        Self {
            next: vec![
                KeyCode::Tab,
                KeyCode::Right,
                KeyCode::Down,
                KeyCode::Char('j'),
                KeyCode::Char('l'),
            ],
            previous: vec![
                KeyCode::BackTab,
                KeyCode::Left,
                KeyCode::Up,
                KeyCode::Char('k'),
                KeyCode::Char('h'),
            ],
            confirm: vec![KeyCode::Enter, KeyCode::Char(' ')],
            cancel: vec![KeyCode::Esc],
            close: vec![KeyCode::Char('q')],
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DialogAction {
    Select(usize),
    Confirm(usize),
    Cancel,
    Close,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DialogEventResult {
    pub consumed: bool,
    pub action: Option<DialogAction>,
}

impl DialogEventResult {
    pub fn ignored() -> Self {
        Self {
            consumed: false,
            action: None,
        }
    }

    pub fn consumed(action: Option<DialogAction>) -> Self {
        Self {
            consumed: true,
            action,
        }
    }
}

pub trait DialogBodyRenderer {
    fn render_body(&mut self, area: Rect, buf: &mut Buffer);
}

pub struct Dialog<'a> {
    pub title: &'a str,
    pub message: &'a str,
    pub dialog_type: DialogType,
    pub buttons: Vec<&'a str>,
    pub selected_button: usize,
    pub width_percent: f32,
    pub height_percent: f32,
    pub footer: DialogFooter<'a>,
    pub footer_style: Style,
    pub footer_alignment: Alignment,
    pub title_inside: bool,
    pub backdrop_style: Option<Style>,
    pub shadow: DialogShadow,
    pub modal_mode: DialogModalMode,
    pub border_color: Option<Color>,
    pub style: Style,
    pub button_selected_style: Style,
    pub button_style: Style,
    pub actions_layout: DialogActionsLayout,
    pub actions_alignment: Alignment,
    pub message_alignment: Alignment,
    pub content_padding: DialogPadding,
    pub wrap: DialogWrap,
    pub body_renderer: Option<Box<dyn DialogBodyRenderer + 'a>>,
    pub keymap: DialogKeymap,
    pub wrap_button_navigation: bool,
    pub button_areas: Vec<Rect>,
    pub theme_info_color: Option<Color>,
    pub theme_success_color: Option<Color>,
    pub theme_warning_color: Option<Color>,
    pub theme_error_color: Option<Color>,
    pub theme_confirm_color: Option<Color>,
}

pub struct DialogState {
    pub selected_button: usize,
}

impl DialogState {
    pub fn new() -> Self {
        Self { selected_button: 0 }
    }
}

impl Default for DialogState {
    fn default() -> Self {
        Self::new()
    }
}