use ratatui::layout::Rect;
use ratatui::widgets::{Block, Borders};
use ratatui::Frame;
use ratatui_sci_fi::widgets::{TextInput, TextInputState};
use super::theme;
#[derive(Debug, Clone)]
pub struct InputField {
pub value: String,
pub mask: bool,
}
impl InputField {
pub fn new(mask: bool) -> Self {
Self {
value: String::new(),
mask,
}
}
pub fn push_char(&mut self, c: char) {
self.value.push(c);
}
pub fn backspace(&mut self) {
self.value.pop();
}
pub fn clear(&mut self) {
self.value.clear();
}
pub fn rendered(&self) -> String {
if self.mask {
"•".repeat(self.value.chars().count())
} else {
self.value.clone()
}
}
}
pub fn render_input(frame: &mut Frame, area: Rect, field: &InputField, label: &str, tick: u64) {
let block = Block::default()
.borders(Borders::ALL)
.border_style(theme::border())
.title(label)
.title_style(theme::title_style());
let inner = block.inner(area);
frame.render_widget(block, area);
let mut state = TextInputState {
value: field.value.clone(),
cursor: field.value.chars().count(),
blink_tick: tick,
};
let mut input = TextInput::new().theme(ratatui_sci_fi::Theme::Cyberpunk);
if field.mask {
input = input.password(true);
}
frame.render_stateful_widget(input, inner, &mut state);
}
#[cfg(test)]
mod tests {
use super::InputField;
#[test]
fn push_and_backspace() {
let mut f = InputField::new(false);
for c in "abc".chars() {
f.push_char(c);
}
assert_eq!(f.value, "abc");
f.backspace();
assert_eq!(f.value, "ab");
}
#[test]
fn mask_renders_bullets() {
let mut f = InputField::new(true);
for c in "secret".chars() {
f.push_char(c);
}
assert_eq!(f.rendered(), "•".repeat(6));
f.clear();
assert_eq!(f.rendered(), "");
}
}