lk-inside 0.3.1

A terminal user interface (TUI) application for interactive data analysis.
Documentation
//! A reusable UI component for handling text input in the TUI.

use ratatui::{
    layout::{Rect, Position}, // ADDED Position
    widgets::{Block, Borders, Paragraph},
    Frame, // Added Frame
};
use crossterm::event::KeyCode;
use crate::ui::theme; // ADDED

/// A customizable input field widget for text entry in the TUI.
///
/// This widget handles typing, backspace, delete, and cursor movement.
#[derive(Clone)]
pub struct InputWidget {
    /// The current string content of the input field.
    input_str: String,
    /// The current position of the cursor within the `input_str`.
    cursor_position: usize,
    /// The title for the input field.
    title: String, // ADDED
}

impl InputWidget {
    /// Creates a new `InputWidget` instance.
    pub fn new(title: String) -> Self { // Retained title in new signature
        InputWidget {
            input_str: String::new(),
            cursor_position: 0,
            title, // Initialized title
        }
    }

    /// Returns a clone of the current input string.
    pub fn get_input(&self) -> String {
        self.input_str.clone()
    }

    /// Sets the input string to a new value and places the cursor at the end.
    ///
    /// # Arguments
    ///
    /// * `s` - The new string to set as the input.
    pub fn set_input(&mut self, s: String) {
        self.input_str = s;
        self.cursor_position = self.input_str.len();
    }

    /// Clears the input string and resets the cursor position to the beginning.
    pub fn reset(&mut self) {
        self.input_str.clear();
        self.cursor_position = 0;
    }

    /// Handles a key press event, updating the input string and cursor position accordingly.
    ///
    /// # Arguments
    ///
    /// * `key` - The `KeyCode` of the pressed key.
    pub fn handle_key(&mut self, key: KeyCode) {
        match key {
            KeyCode::Char(c) => {
                self.input_str.insert(self.cursor_position, c);
                self.cursor_position += 1;
            }
            KeyCode::Backspace => {
                if self.cursor_position > 0 {
                    self.cursor_position -= 1;
                    self.input_str.remove(self.cursor_position);
                }
            }
            KeyCode::Delete => {
                if self.cursor_position < self.input_str.len() {
                    self.input_str.remove(self.cursor_position);
                }
            }
            KeyCode::Left => {
                self.cursor_position = self.cursor_position.saturating_sub(1);
            }
            KeyCode::Right => {
                self.cursor_position = (self.cursor_position + 1).min(self.input_str.len());
            }
            KeyCode::Home => {
                self.cursor_position = 0;
            }
            KeyCode::End => {
                self.cursor_position = self.input_str.len();
            }
            _ => {}
        }
    }

    // New render function
    pub fn render(&self, f: &mut Frame, area: Rect, is_focused: bool) {
        let border_style = if is_focused { theme::HIGHLIGHT_STYLE } else { theme::BORDER_STYLE };
        let input_block = Block::default()
            .borders(Borders::ALL)
            .title(self.title.clone()) // Use the title field
            .border_style(border_style);
        
        // Render the input field itself (text)
        let paragraph = Paragraph::new(self.input_str.as_str()).block(input_block);
        f.render_widget(paragraph, area);

        // Set cursor position if focused
        if is_focused {
            f.set_cursor_position( // REPLACED set_cursor
                Position::new(area.x + self.cursor_position as u16 + 1, area.y + 1) // CORRECTED
            );
        }
    }
}