use rdom_core::NodeId;
use super::ScrollAxis;
use super::geometry::{
is_horizontal_scroll_container, is_vertical_scroll_container, nearest_scroll_container,
scroll_metrics,
};
use crate::TuiDom;
use crate::runtime::smooth_scroll::{ScrollBehaviorOption, destination, perform_scroll};
pub const SCROLL_FOCUS_ATTR: &str = "data-rdom-scroll-focus";
pub(crate) fn scroll_focus_target(dom: &TuiDom) -> Option<NodeId> {
nearest_scroll_container(dom, dom.focused()?)
}
pub(crate) fn handle_scroll_key(dom: &mut TuiDom, key: crossterm::event::KeyEvent) -> bool {
use crossterm::event::{KeyCode, KeyModifiers};
let Some(focused) = dom.focused() else {
return false;
};
let Some(el) = nearest_scroll_container(dom, focused) else {
return false;
};
let vert = is_vertical_scroll_container(dom, el);
let horiz = is_horizontal_scroll_container(dom, el);
let (vh, _) = scroll_metrics(dom, el, ScrollAxis::Vertical);
let page = (vh as i32).max(1);
let (hscroll, vscroll) = destination(dom, el);
let (hscroll, vscroll) = (hscroll as i32, vscroll as i32);
let target = match key.code {
KeyCode::Down if vert => (hscroll, vscroll + 1),
KeyCode::Up if vert => (hscroll, vscroll - 1),
KeyCode::PageDown if vert => (hscroll, vscroll + page),
KeyCode::PageUp if vert => (hscroll, vscroll - page),
KeyCode::Char(' ') if vert => {
let dir = if key.modifiers.contains(KeyModifiers::SHIFT) {
-page
} else {
page
};
(hscroll, vscroll + dir)
}
KeyCode::Home if vert => (hscroll, 0),
KeyCode::End if vert => (hscroll, i32::MAX),
KeyCode::Right if horiz => (hscroll + 1, vscroll),
KeyCode::Left if horiz => (hscroll - 1, vscroll),
_ => return false,
};
perform_scroll(dom, el, target.0, target.1, ScrollBehaviorOption::Auto);
true
}