ratatui-kit 0.7.0

A framework for building interactive terminal user interfaces with ratatui
Documentation
use crate::{
    AnyElement, Hooks, UsePreviousSize,
    prelude::{Fragment, Positioned, Text},
};
use ratatui::{style::Style, text::Span};
use ratatui_kit_macros::{Props, component, element};

#[derive(Debug, Clone, Props, Default)]
pub struct InputProps {
    pub input: tui_input::Input,
    pub cursor_style: Style,
    pub placeholder: String,
    pub placeholder_style: Style,
    pub style: Style,
    pub hide_cursor: bool,
}

#[component]
pub fn Input(props: &InputProps, mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
    let size = hooks.use_previous_size();
    let input = &props.input;
    let input_width = size.width.saturating_sub(1) as usize;
    let scroll = if props.hide_cursor || input_width == 0 {
        0
    } else {
        input.visual_scroll(input_width)
    };
    let text = if input.value().is_empty() {
        props.placeholder.clone()
    } else {
        input.value().to_string()
    };

    let x = input.visual_cursor().max(scroll) - scroll;

    let position = (size.x + x as u16, size.y);

    element!(Fragment {
        Text(
            text:text,
            style: if input.value().is_empty() {
                props.placeholder_style
            }else{
                props.style
            },
            scroll:(0, scroll as u16),
        )
        if !props.hide_cursor {
            Positioned(
                x: position.0.min(size.x + size.width.saturating_sub(1)),
                y: position.1.min(size.y + size.height),
                width: 1u16,
                height: 1u16,
            ){
                widget(Span::from(" ").style(props.cursor_style))
            }
        }
    })
}