use crossterm::event::{KeyModifiers, MouseButton, MouseEvent, MouseEventKind};
use rdom_core::ListenerOptions;
use crate::{TuiDom, TuiEvent};
pub fn install(dom: &mut TuiDom) {
let root = dom.root();
dom.add_event_listener(root, "keydown", ListenerOptions::default(), move |ctx| {
if ctx.event.default_prevented() {
return;
}
let Some(focused) = ctx.dom.focused() else {
return;
};
if !is_button_like(ctx.dom, focused) {
return;
}
let Some(key) = ctx.event.detail.as_keyboard() else {
return;
};
if key.modifiers.ctrl || key.modifiers.alt || key.modifiers.meta {
return;
}
let triggers = matches!(key.key.as_str(), "Enter" | " ");
if !triggers {
return;
}
let fake_mouse = MouseEvent {
kind: MouseEventKind::Up(MouseButton::Left),
column: 0,
row: 0,
modifiers: KeyModifiers::empty(),
};
let mut click = TuiEvent::click(fake_mouse);
click.event = click.event.clone().with_synthetic(true);
crate::tui_event::dispatch_to_live(ctx.dom, focused, &mut click);
ctx.event.prevent_default();
})
.expect("root button keydown listener install");
}
pub(super) fn is_button_like(dom: &TuiDom, id: rdom_core::NodeId) -> bool {
use rdom_core::InputTypeState as T;
dom.node(id).tag_name() == Some("button")
|| matches!(
dom.input_type_state(id),
Some(T::Submit | T::Image | T::Reset | T::Button)
)
}
#[cfg(test)]
mod tests;