multiverse/widgets/
popup_input.rs

1use crossterm::event::KeyEvent;
2use ratatui::{
3    buffer::Buffer,
4    layout::{Constraint, Flex, Layout, Rect},
5    style::{Stylize, palette::tailwind},
6    widgets::{Block, Borders, Clear, Widget},
7};
8use tui_textarea::TextArea;
9
10#[derive(Default, Clone)]
11pub(crate) struct PopupInput {
12    /// The text area that will keep track of what the user has input.
13    textarea: TextArea<'static>,
14
15    /// Title of popup
16    title: String,
17
18    /// Placeholder text of popup
19    placeholder_text: String,
20
21    /// Width constraint text of popup
22    width_constraint: Constraint,
23
24    /// Height constraint of popup
25    height_constraint: Constraint,
26}
27
28impl PopupInput {
29    /// Create a new empty [`PopupInput`] widget.
30    pub fn new<T: Into<String>>(title: T, placeholder_text: T) -> Self {
31        let mut ret = Self {
32            textarea: TextArea::default(),
33            title: title.into(),
34            placeholder_text: placeholder_text.into(),
35            width_constraint: Constraint::Percentage(40),
36            height_constraint: Constraint::Length(3),
37        };
38
39        // Set the placeholder text.
40        ret.textarea.set_placeholder_text(ret.placeholder_text.clone());
41
42        // Let's first create a block to set the background color.
43        let input_block =
44            Block::new().borders(Borders::ALL).bg(tailwind::BLUE.c400).title(ret.title.clone());
45
46        // Now we set the block and we render the textarea.
47        ret.textarea.set_block(input_block);
48
49        ret
50    }
51
52    /// Width constraint text of popup
53    pub fn width_constraint(&mut self, value: Constraint) -> Self {
54        self.width_constraint = value;
55        self.clone()
56    }
57
58    /// Height constraint of popup
59    pub fn height_constraint(&mut self, value: Constraint) -> Self {
60        self.height_constraint = value;
61        self.clone()
62    }
63
64    /// Receive a key press event and handle it.
65    pub fn handle_key_press(&mut self, key: KeyEvent) {
66        self.textarea.input(key);
67    }
68
69    /// Get the currently input text.
70    pub fn get_input(&self) -> String {
71        self.textarea.lines().join("\n")
72    }
73}
74
75impl Widget for &mut PopupInput {
76    fn render(self, area: Rect, buf: &mut Buffer) {
77        let vertical = Layout::vertical([self.height_constraint]).flex(Flex::Center);
78        let horizontal = Layout::horizontal([self.width_constraint]).flex(Flex::Center);
79        let [area] = vertical.areas(area);
80        let [area] = horizontal.areas(area);
81        Clear.render(area, buf);
82
83        self.textarea.render(area, buf);
84    }
85}