tabiew 0.14.2

A lightweight TUI application to view and query tabular data files, such as CSV, TSV, and parquet.
use ratatui::{
    layout::{Constraint, Flex, Layout},
    widgets::{Clear, Widget},
};

use crate::{
    misc::color_ext::ColorExt,
    tui::{
        component::Component,
        widgets::{
            block::Block,
            input::{Input, InputType},
        },
    },
};

#[derive(Debug)]
pub struct TextPicker {
    input: Input,
    title: String,
    darken_bg: bool,
}

impl TextPicker {
    pub fn with_max_len(self, max_len: usize) -> Self {
        Self {
            input: self.input.with_max_len(max_len),
            ..self
        }
    }

    pub fn with_value(self, value: String) -> Self {
        Self {
            input: self.input.with_value(value),
            ..self
        }
    }

    pub fn with_input_type(self, input_type: InputType) -> Self {
        Self {
            input: self.input.with_input_type(input_type),
            ..self
        }
    }

    pub fn with_title(self, title: impl Into<String>) -> Self {
        Self {
            title: title.into(),
            ..self
        }
    }

    pub fn with_hint(self, hint: impl Into<String>) -> Self {
        Self {
            input: self.input.with_hint(hint.into()),
            ..self
        }
    }

    pub fn no_darken_bg(self) -> Self {
        Self {
            darken_bg: false,
            ..self
        }
    }

    pub fn input(&self) -> &Input {
        &self.input
    }

    pub fn input_mut(&mut self) -> &mut Input {
        &mut self.input
    }

    pub fn value(&self) -> &str {
        self.input.value()
    }
}

impl Default for TextPicker {
    fn default() -> Self {
        Self {
            input: Default::default(),
            title: Default::default(),
            darken_bg: true,
        }
    }
}

impl Component for TextPicker {
    fn render(
        &mut self,
        _: ratatui::prelude::Rect,
        buf: &mut ratatui::prelude::Buffer,
        focus_state: crate::tui::component::FocusState,
    ) {
        if self.darken_bg {
            for cell in buf.content.iter_mut() {
                cell.bg = cell.bg.darken();
                cell.fg = cell.fg.darken();
            }
        }

        let [area] = Layout::horizontal([Constraint::Length(80)])
            .flex(Flex::Center)
            .areas(buf.area);
        let [_, area] =
            Layout::vertical([Constraint::Length(3), Constraint::Length(3)]).areas(area);
        Widget::render(Clear, area, buf);

        let area = {
            let block = Block::default().title(self.title.as_str());
            let inner = block.inner(area);
            block.render(area, buf);
            inner
        };

        self.input.render(area, buf, focus_state);
    }

    fn handle(&mut self, event: crossterm::event::KeyEvent) -> bool {
        self.input.handle(event)
    }
}