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 crate::primitives::dialog::types::{
    Dialog, DialogActionsLayout, DialogBodyRenderer, DialogFooter, DialogKeymap, DialogModalMode,
    DialogPadding, DialogShadow, DialogType, DialogWrap,
};
use crossterm::event::KeyCode;
use ratatui::layout::Alignment;
use ratatui::style::{Color, Modifier, Style};

impl<'a> Dialog<'a> {
    pub fn new(title: &'a str, message: &'a str) -> Self {
        Self {
            title,
            message,
            dialog_type: DialogType::Info,
            buttons: Vec::new(),
            selected_button: 0,
            width_percent: 0.6,
            height_percent: 0.4,
            footer: DialogFooter::Hidden,
            footer_style: Style::default().fg(Color::DarkGray),
            footer_alignment: Alignment::Center,
            title_inside: false,
            backdrop_style: None,
            shadow: DialogShadow::None,
            modal_mode: DialogModalMode::Blocking,
            border_color: None,
            style: Style::default(),
            button_selected_style: Style::default()
                .fg(Color::Black)
                .bg(Color::Cyan)
                .add_modifier(Modifier::BOLD),
            button_style: Style::default(),
            actions_layout: DialogActionsLayout::Horizontal,
            actions_alignment: Alignment::Center,
            message_alignment: Alignment::Center,
            content_padding: DialogPadding::default(),
            wrap: DialogWrap::WordTrim,
            body_renderer: None,
            keymap: DialogKeymap::default(),
            wrap_button_navigation: false,
            button_areas: Vec::new(),
            theme_info_color: None,
            theme_success_color: None,
            theme_warning_color: None,
            theme_error_color: None,
            theme_confirm_color: None,
        }
    }

    pub fn info(title: &'a str, message: &'a str) -> Self {
        Self::new(title, message).dialog_type(DialogType::Info)
    }

    pub fn warning(title: &'a str, message: &'a str) -> Self {
        Self::new(title, message).dialog_type(DialogType::Warning)
    }

    pub fn error(title: &'a str, message: &'a str) -> Self {
        Self::new(title, message).dialog_type(DialogType::Error)
    }

    pub fn success(title: &'a str, message: &'a str) -> Self {
        Self::new(title, message).dialog_type(DialogType::Success)
    }

    pub fn confirm(title: &'a str, message: &'a str) -> Self {
        Self::new(title, message)
            .dialog_type(DialogType::Confirm)
            .buttons(vec!["Yes", "No"])
    }

    pub fn dialog_type(mut self, dialog_type: DialogType) -> Self {
        self.dialog_type = dialog_type;
        self
    }

    pub fn buttons(mut self, buttons: Vec<&'a str>) -> Self {
        self.buttons = buttons;
        self
    }

    pub fn style(mut self, style: Style) -> Self {
        self.style = style;
        self
    }

    pub fn border_color(mut self, border_color: Color) -> Self {
        self.border_color = Some(border_color);
        self
    }

    pub fn width_percent(mut self, width_percent: f32) -> Self {
        self.width_percent = width_percent;
        self
    }

    pub fn height_percent(mut self, height_percent: f32) -> Self {
        self.height_percent = height_percent;
        self
    }

    pub fn footer(mut self, footer: &'a str) -> Self {
        self.footer = DialogFooter::Text(footer);
        self
    }

    pub fn hide_footer(mut self) -> Self {
        self.footer = DialogFooter::Hidden;
        self
    }

    pub fn footer_alignment(mut self, alignment: Alignment) -> Self {
        self.footer_alignment = alignment;
        self
    }

    pub fn footer_style(mut self, footer_style: Style) -> Self {
        self.footer_style = footer_style;
        self
    }

    pub fn title_inside(mut self, title_inside: bool) -> Self {
        self.title_inside = title_inside;
        self
    }

    pub fn overlay(mut self, overlay: bool) -> Self {
        self.backdrop_style = if overlay {
            Some(Style::default().bg(Color::Rgb(0, 0, 0)))
        } else {
            None
        };
        self
    }

    pub fn overlay_style(mut self, overlay_style: Style) -> Self {
        self.backdrop_style = Some(overlay_style);
        self
    }

    pub fn backdrop_style(mut self, backdrop_style: Style) -> Self {
        self.backdrop_style = Some(backdrop_style);
        self
    }

    pub fn no_backdrop(mut self) -> Self {
        self.backdrop_style = None;
        self
    }

    pub fn shadow(mut self, shadow: DialogShadow) -> Self {
        self.shadow = shadow;
        self
    }

    pub fn modal_mode(mut self, modal_mode: DialogModalMode) -> Self {
        self.modal_mode = modal_mode;
        self
    }

    pub fn button_selected_style(mut self, button_selected_style: Style) -> Self {
        self.button_selected_style = button_selected_style;
        self
    }

    pub fn button_style(mut self, button_style: Style) -> Self {
        self.button_style = button_style;
        self
    }

    pub fn actions_layout(mut self, layout: DialogActionsLayout) -> Self {
        self.actions_layout = layout;
        self
    }

    pub fn actions_alignment(mut self, alignment: Alignment) -> Self {
        self.actions_alignment = alignment;
        self
    }

    pub fn message_alignment(mut self, alignment: Alignment) -> Self {
        self.message_alignment = alignment;
        self
    }

    pub fn content_padding(mut self, horizontal: u16, vertical: u16) -> Self {
        self.content_padding = DialogPadding {
            horizontal,
            vertical,
        };
        self
    }

    pub fn wrap_mode(mut self, wrap: DialogWrap) -> Self {
        self.wrap = wrap;
        self
    }

    pub fn body_renderer(mut self, body_renderer: Box<dyn DialogBodyRenderer + 'a>) -> Self {
        self.body_renderer = Some(body_renderer);
        self
    }

    pub fn keymap(mut self, keymap: DialogKeymap) -> Self {
        self.keymap = keymap;
        self
    }

    pub fn wrap_button_navigation(mut self, wrap: bool) -> Self {
        self.wrap_button_navigation = wrap;
        self
    }

    pub fn default_selection(mut self, index: usize) -> Self {
        if !self.buttons.is_empty() {
            self.selected_button = index.min(self.buttons.len() - 1);
        }
        self
    }

    pub fn next_keys(mut self, keys: Vec<KeyCode>) -> Self {
        self.keymap.next = keys;
        self
    }

    pub fn previous_keys(mut self, keys: Vec<KeyCode>) -> Self {
        self.keymap.previous = keys;
        self
    }

    pub fn confirm_keys(mut self, keys: Vec<KeyCode>) -> Self {
        self.keymap.confirm = keys;
        self
    }

    pub fn cancel_keys(mut self, keys: Vec<KeyCode>) -> Self {
        self.keymap.cancel = keys;
        self
    }

    #[cfg(feature = "theme")]
    pub fn with_theme(mut self, theme: &ratkit_theme::AppTheme) -> Self {
        self.theme_info_color = Some(theme.info);
        self.theme_success_color = Some(theme.success);
        self.theme_warning_color = Some(theme.warning);
        self.theme_error_color = Some(theme.error);
        self.theme_confirm_color = Some(theme.primary);

        self.style = Style::default().bg(theme.background_panel).fg(theme.text);

        self.button_selected_style = Style::default()
            .fg(theme.selected_text)
            .bg(theme.primary)
            .add_modifier(Modifier::BOLD);
        self.button_style = Style::default().fg(theme.text);

        self
    }
}