use crossterm::event::{KeyModifiers, MouseButton, MouseEvent, MouseEventKind};
use rdom_core::ListenerOptions;
use crate::tui_event::TuiDispatchExt;
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);
let _ = ctx.dom.dispatch_tui_event(focused, &mut click);
})
.expect("root button keydown listener install");
}
pub(super) fn is_button_like(dom: &TuiDom, id: rdom_core::NodeId) -> bool {
let node = dom.node(id);
match node.tag_name() {
Some("button") => true,
Some("input") => matches!(
node.get_attribute("type"),
Some("submit") | Some("reset") | Some("button")
),
_ => false,
}
}
#[cfg(test)]
mod tests;