84 lines
2.3 KiB
Rust
84 lines
2.3 KiB
Rust
use crate::theme::{input, ui};
|
|
use ratatui::layout::{Constraint, Layout, Rect};
|
|
use ratatui::style::{Color, Style};
|
|
use ratatui::text::{Line, Span};
|
|
use ratatui::widgets::Paragraph;
|
|
use ratatui::Frame;
|
|
|
|
use super::ModalFrame;
|
|
|
|
pub struct TextInputModal<'a> {
|
|
title: &'a str,
|
|
input: &'a str,
|
|
hint: Option<&'a str>,
|
|
border_color: Color,
|
|
width: u16,
|
|
}
|
|
|
|
impl<'a> TextInputModal<'a> {
|
|
pub fn new(title: &'a str, input: &'a str) -> Self {
|
|
Self {
|
|
title,
|
|
input,
|
|
hint: None,
|
|
border_color: ui::TEXT_PRIMARY,
|
|
width: 50,
|
|
}
|
|
}
|
|
|
|
pub fn hint(mut self, h: &'a str) -> Self {
|
|
self.hint = Some(h);
|
|
self
|
|
}
|
|
|
|
pub fn border_color(mut self, c: Color) -> Self {
|
|
self.border_color = c;
|
|
self
|
|
}
|
|
|
|
pub fn width(mut self, w: u16) -> Self {
|
|
self.width = w;
|
|
self
|
|
}
|
|
|
|
pub fn render_centered(self, frame: &mut Frame, term: Rect) {
|
|
let height = if self.hint.is_some() { 6 } else { 5 };
|
|
|
|
let inner = ModalFrame::new(self.title)
|
|
.width(self.width)
|
|
.height(height)
|
|
.border_color(self.border_color)
|
|
.render_centered(frame, term);
|
|
|
|
if self.hint.is_some() {
|
|
let rows =
|
|
Layout::vertical([Constraint::Length(1), Constraint::Length(1)]).split(inner);
|
|
|
|
frame.render_widget(
|
|
Paragraph::new(Line::from(vec![
|
|
Span::raw("> "),
|
|
Span::styled(self.input, Style::new().fg(input::TEXT)),
|
|
Span::styled("█", Style::new().fg(input::CURSOR)),
|
|
])),
|
|
rows[0],
|
|
);
|
|
|
|
if let Some(hint) = self.hint {
|
|
frame.render_widget(
|
|
Paragraph::new(Span::styled(hint, Style::new().fg(input::HINT))),
|
|
rows[1],
|
|
);
|
|
}
|
|
} else {
|
|
frame.render_widget(
|
|
Paragraph::new(Line::from(vec![
|
|
Span::raw("> "),
|
|
Span::styled(self.input, Style::new().fg(input::TEXT)),
|
|
Span::styled("█", Style::new().fg(input::CURSOR)),
|
|
])),
|
|
inner,
|
|
);
|
|
}
|
|
}
|
|
}
|