use ratatui::layout::Rect;
use ratatui::style::{Color, Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::Paragraph;
use ratatui::Frame;
use super::parse_fg_bg;
use crate::elements::Element;
pub fn render(frame: &mut Frame, area: Rect, element: &Element) {
let value = element
.props
.get("value")
.and_then(|v| v.as_str())
.unwrap_or("");
let placeholder = element
.props
.get("placeholder")
.and_then(|v| v.as_str())
.unwrap_or("");
let cursor = element
.props
.get("cursor")
.and_then(|v| v.as_u64())
.map(|v| v as usize)
.unwrap_or(value.len());
let prefix = element
.props
.get("prefix")
.and_then(|v| v.as_str())
.unwrap_or(" \u{258E} ");
let (fg, bg) = parse_fg_bg(element);
let prefix_style = Style::default().fg(Color::Gray);
let normal_style = Style::default().fg(fg).bg(bg);
let cursor_style = Style::default().add_modifier(Modifier::UNDERLINED);
if value.is_empty() && !placeholder.is_empty() {
let show_cursor = element
.props
.get("focused")
.and_then(|v| v.as_bool())
.unwrap_or(false);
let mut lines = vec![Line::from("")];
if show_cursor {
lines.push(Line::from(vec![
Span::styled(prefix.to_string(), prefix_style),
Span::styled(" ", cursor_style),
]));
} else {
lines.push(Line::from(vec![
Span::styled(prefix.to_string(), prefix_style),
Span::styled(
placeholder.to_string(),
Style::default().fg(Color::DarkGray),
),
]));
}
let paragraph = Paragraph::new(lines);
frame.render_widget(paragraph, area);
return;
}
let input_lines: Vec<&str> = if value.is_empty() {
vec![""]
} else {
value.split('\n').collect()
};
let mut lines: Vec<Line> = vec![Line::from("")]; let mut char_offset: usize = 0;
for input_line in &input_lines {
let chars: Vec<char> = input_line.chars().collect();
let line_char_len = chars.len();
let line_start = char_offset;
let line_end = char_offset + line_char_len;
let bar = Span::styled(prefix.to_string(), prefix_style);
if cursor >= line_start && cursor <= line_end {
let pos_in_line = cursor - line_start;
let before: String = chars[..pos_in_line].iter().collect();
if pos_in_line < line_char_len {
let cursor_char: String = chars[pos_in_line..pos_in_line + 1].iter().collect();
let rest: String = chars[pos_in_line + 1..].iter().collect();
lines.push(Line::from(vec![
bar,
Span::styled(before, normal_style),
Span::styled(cursor_char, cursor_style),
Span::styled(rest, normal_style),
]));
} else {
lines.push(Line::from(vec![
bar,
Span::styled(before, normal_style),
Span::styled("_".to_string(), Style::default().fg(Color::DarkGray)),
]));
}
} else {
lines.push(Line::from(vec![
bar,
Span::styled(input_line.to_string(), normal_style),
]));
}
char_offset = line_end + 1; }
let max_lines = area.height as usize;
if lines.len() > max_lines {
let skip = lines.len() - max_lines;
lines = lines.into_iter().skip(skip).collect();
}
let paragraph = Paragraph::new(lines);
frame.render_widget(paragraph, area);
}