diff --git a/packages/tui/src/focus.rs b/packages/tui/src/focus.rs index 623bc255c..c3fffd119 100644 --- a/packages/tui/src/focus.rs +++ b/packages/tui/src/focus.rs @@ -1,4 +1,4 @@ -use crate::Dom; +use crate::{node::PreventDefault, Dom}; use dioxus_core::ElementId; use dioxus_native_core::utils::{ElementProduced, PersistantElementIter}; @@ -59,7 +59,6 @@ impl Default for FocusLevel { #[derive(Clone, PartialEq, Debug, Default)] pub(crate) struct Focus { - pub pass_focus: bool, pub level: FocusLevel, } @@ -71,9 +70,6 @@ impl NodeDepState for Focus { fn reduce(&mut self, node: NodeView<'_>, _sibling: &Self::DepState, _: &Self::Ctx) -> bool { let new = Focus { - pass_focus: !node - .attributes() - .any(|a| a.name == "dioxus-prevent-default" && a.value.trim() == "keydown"), level: if let Some(a) = node.attributes().find(|a| a.name == "tabindex") { if let Ok(index) = a.value.parse::() { match index.cmp(&0) { @@ -106,7 +102,7 @@ impl NodeDepState for Focus { } const FOCUS_EVENTS: &[&str] = &sorted_str_slice!(["keydown", "keypress", "keyup"]); -const FOCUS_ATTRIBUTES: &[&str] = &sorted_str_slice!(["dioxus-prevent-default", "tabindex"]); +const FOCUS_ATTRIBUTES: &[&str] = &sorted_str_slice!(["tabindex"]); #[derive(Default)] pub(crate) struct FocusState { @@ -120,7 +116,7 @@ impl FocusState { /// Returns true if the focus has changed. pub fn progress(&mut self, rdom: &mut Dom, forward: bool) -> bool { if let Some(last) = self.last_focused_id { - if !rdom[last].state.focus.pass_focus { + if rdom[last].state.prevent_default == PreventDefault::KeyDown { return false; } } diff --git a/packages/tui/src/lib.rs b/packages/tui/src/lib.rs index f8ee2ec80..b310b1186 100644 --- a/packages/tui/src/lib.rs +++ b/packages/tui/src/lib.rs @@ -8,26 +8,22 @@ use crossterm::{ use dioxus_core::exports::futures_channel::mpsc::unbounded; use dioxus_core::*; use dioxus_native_core::real_dom::RealDom; -use dioxus_native_core::state::*; -use dioxus_native_core_macro::State; -use focus::Focus; use focus::FocusState; use futures::{ channel::mpsc::{UnboundedReceiver, UnboundedSender}, pin_mut, StreamExt, }; -use layout::StretchLayout; use std::cell::RefCell; use std::rc::Rc; use std::{io, time::Duration}; use stretch2::{prelude::Size, Stretch}; -use style_attributes::StyleModifier; use tui::{backend::CrosstermBackend, layout::Rect, Terminal}; mod config; mod focus; mod hooks; mod layout; +mod node; mod render; mod style; mod style_attributes; @@ -35,21 +31,7 @@ mod widget; pub use config::*; pub use hooks::*; - -type Dom = RealDom; -type Node = dioxus_native_core::real_dom::Node; - -#[derive(Debug, Clone, State, Default)] -struct NodeState { - #[child_dep_state(layout, RefCell)] - layout: StretchLayout, - // depends on attributes, the C component of it's parent and a u8 context - #[parent_dep_state(style)] - style: StyleModifier, - #[node_dep_state()] - focus: Focus, - focused: bool, -} +pub(crate) use node::*; #[derive(Clone)] pub struct TuiContext { diff --git a/packages/tui/src/node.rs b/packages/tui/src/node.rs new file mode 100644 index 000000000..d16c9cc19 --- /dev/null +++ b/packages/tui/src/node.rs @@ -0,0 +1,91 @@ +use crate::focus::Focus; +use crate::layout::StretchLayout; +use crate::style_attributes::StyleModifier; +use dioxus_native_core::{real_dom::RealDom, state::*}; +use dioxus_native_core_macro::State; + +pub(crate) type Dom = RealDom; +pub(crate) type Node = dioxus_native_core::real_dom::Node; + +#[derive(Debug, Clone, State, Default)] +pub(crate) struct NodeState { + #[child_dep_state(layout, RefCell)] + pub layout: StretchLayout, + // depends on attributes, the C component of it's parent and a u8 context + #[parent_dep_state(style)] + pub style: StyleModifier, + #[node_dep_state()] + pub prevent_default: PreventDefault, + #[node_dep_state()] + pub focus: Focus, + pub focused: bool, +} + +#[derive(PartialEq, Debug, Clone)] +pub(crate) enum PreventDefault { + Focus, + KeyPress, + KeyRelease, + KeyDown, + KeyUp, + MouseDown, + Click, + MouseEnter, + MouseLeave, + MouseOut, + Unknown, + MouseOver, + ContextMenu, + Wheel, + MouseUp, +} + +impl Default for PreventDefault { + fn default() -> Self { + PreventDefault::Unknown + } +} + +impl NodeDepState for PreventDefault { + type Ctx = (); + + type DepState = (); + + const NODE_MASK: dioxus_native_core::node_ref::NodeMask = + dioxus_native_core::node_ref::NodeMask::NONE; + + fn reduce( + &mut self, + node: dioxus_native_core::node_ref::NodeView, + _sibling: &Self::DepState, + _ctx: &Self::Ctx, + ) -> bool { + let new = match node + .attributes() + .find(|a| a.name == "dioxus-prevent-default") + .map(|a| a.value) + { + Some("focus") => PreventDefault::Focus, + Some("keypress") => PreventDefault::KeyPress, + Some("keyrelease") => PreventDefault::KeyRelease, + Some("keydown") => PreventDefault::KeyDown, + Some("keyup") => PreventDefault::KeyUp, + Some("click") => PreventDefault::Click, + Some("mousedown") => PreventDefault::MouseDown, + Some("mouseup") => PreventDefault::MouseUp, + Some("mouseenter") => PreventDefault::MouseEnter, + Some("mouseover") => PreventDefault::MouseOver, + Some("mouseleave") => PreventDefault::MouseLeave, + Some("mouseout") => PreventDefault::MouseOut, + Some("wheel") => PreventDefault::Wheel, + Some("contextmenu") => PreventDefault::ContextMenu, + _ => return false, + }; + if new == *self { + false + } else { + *self = new; + true + } + } +}