use crossterm::event::{Event, KeyCode, KeyEventKind};
use ratatui::{
layout::{Direction, Flex},
style::Stylize,
text::Line,
};
use ratatui_kit::prelude::*;
use crate::theme::AppChromeTheme;
#[derive(Props, Default)]
pub struct SettingItemProps {
pub is_editing: bool,
pub top_title: String,
pub bottom_title: String,
pub children: Vec<AnyElement<'static>>,
}
#[component]
pub fn SettingItem(props: &mut SettingItemProps, hooks: Hooks) -> impl Into<AnyElement<'static>> {
let theme = hooks.use_component_theme::<AppChromeTheme>();
let mut top_title = Line::from(props.top_title.clone());
let mut bottom_title = Line::from(props.bottom_title.clone());
if props.is_editing {
top_title = top_title.not_dim();
bottom_title = bottom_title.not_dim();
}
let border_style = if props.is_editing {
theme.border.patch(theme.highlight)
} else {
theme.border
};
element!(Border(
top_title: top_title,
border_style: border_style,
bottom_title: bottom_title,
style: if props.is_editing {
theme.border.not_dim()
} else {
theme.border
}
) {
{ std::mem::take(&mut props.children) }
})
}
#[derive(Props, Default)]
pub struct AdjustableSettingItemProps {
pub is_editing: bool,
pub label: String,
pub value: String,
pub on_decrease: Handler<'static, ()>,
pub on_increase: Handler<'static, ()>,
}
#[component]
pub fn AdjustableSettingItem(
props: &mut AdjustableSettingItemProps,
mut hooks: Hooks,
) -> impl Into<AnyElement<'static>> {
let theme = hooks.use_component_theme::<AppChromeTheme>();
let is_editing = props.is_editing;
let mut on_decrease = props.on_decrease.take();
let mut on_increase = props.on_increase.take();
hooks.use_event_handler(EventScope::Current, EventPriority::Normal, move |event| {
let Event::Key(key) = event else {
return EventResult::Ignored;
};
if key.kind != KeyEventKind::Press {
return EventResult::Ignored;
}
if !is_editing {
return EventResult::Ignored;
}
match key.code {
KeyCode::Left | KeyCode::Char('h') => {
on_decrease(());
EventResult::Consumed
}
KeyCode::Right | KeyCode::Char('l') => {
on_increase(());
EventResult::Consumed
}
_ => EventResult::Ignored,
}
});
element!(SettingItem(is_editing: is_editing) {
View(flex_direction: Direction::Horizontal, justify_content: Flex::SpaceBetween) {
widget(Line::from(props.label.clone()).style(theme.text))
widget(Line::from(props.value.clone()).style(theme.text))
}
})
}