diff --git a/packages/native-core/src/dioxus.rs b/packages/native-core/src/dioxus.rs index 5760d9d2e..f7426f1d6 100644 --- a/packages/native-core/src/dioxus.rs +++ b/packages/native-core/src/dioxus.rs @@ -31,7 +31,11 @@ impl DioxusState { } pub fn element_to_node_id(&self, element_id: ElementId) -> NodeId { - self.node_id_mapping.get(element_id.0).unwrap().unwrap() + self.try_element_to_node_id(element_id).unwrap() + } + + pub fn try_element_to_node_id(&self, element_id: ElementId) -> Option { + self.node_id_mapping.get(element_id.0).copied().flatten() } fn set_element_id(&mut self, mut node: NodeMut, element_id: ElementId) { diff --git a/packages/tui/src/dioxus.rs b/packages/tui/src/dioxus.rs index 32b5d4941..8c58d35bf 100644 --- a/packages/tui/src/dioxus.rs +++ b/packages/tui/src/dioxus.rs @@ -1,10 +1,10 @@ -use std::{ops::Deref, rc::Rc}; +use std::{ops::Deref, rc::Rc, sync::RwLock}; -use dioxus_core::{Component, VirtualDom}; +use dioxus_core::{Component, ElementId, VirtualDom}; use dioxus_html::EventData; use dioxus_native_core::{ dioxus::{DioxusState, NodeImmutableDioxusExt}, - Renderer, + NodeId, Renderer, }; use crate::{query::Query, render, Config, TuiContext}; @@ -29,6 +29,10 @@ pub fn launch_cfg_with_props(app: Component, props: Props let mut rdom = rdom.write().unwrap(); let mut dioxus_state = DioxusState::create(&mut rdom); dioxus_state.apply_mutations(&mut rdom, muts); + let dioxus_state = Rc::new(RwLock::new(dioxus_state)); + vdom = vdom.with_root_context(DioxusElementToNodeId { + mapping: dioxus_state.clone(), + }); DioxusRenderer { vdom, dioxus_state, @@ -48,7 +52,7 @@ pub fn launch_cfg_with_props(app: Component, props: Props struct DioxusRenderer { vdom: VirtualDom, - dioxus_state: DioxusState, + dioxus_state: Rc>, #[cfg(all(feature = "hot-reload", debug_assertions))] hot_reload_rx: tokio::sync::mpsc::UnboundedReceiver, } @@ -57,7 +61,10 @@ impl Renderer> for DioxusRenderer { fn render(&mut self, mut root: dioxus_native_core::NodeMut<()>) { let rdom = root.real_dom_mut(); let muts = self.vdom.render_immediate(); - self.dioxus_state.apply_mutations(rdom, muts); + self.dioxus_state + .write() + .unwrap() + .apply_mutations(rdom, muts); } fn handle_event( @@ -107,3 +114,17 @@ impl Renderer> for DioxusRenderer { Box::pin(self.vdom.wait_for_work()) } } + +#[derive(Clone)] +pub struct DioxusElementToNodeId { + mapping: Rc>, +} + +impl DioxusElementToNodeId { + pub fn get_node_id(&self, element_id: ElementId) -> Option { + self.mapping + .read() + .unwrap() + .try_element_to_node_id(element_id) + } +} diff --git a/packages/tui/src/focus.rs b/packages/tui/src/focus.rs index 8379444d8..37d27b0e5 100644 --- a/packages/tui/src/focus.rs +++ b/packages/tui/src/focus.rs @@ -271,12 +271,11 @@ impl FocusState { pub(crate) fn set_focus(&mut self, rdom: &mut RealDom, id: NodeId) { if let Some(old) = self.last_focused_id.replace(id) { - let focused = rdom.get_state_mut_raw::(old).unwrap(); - *focused = Focused(false); + let mut node = rdom.get_mut(old).unwrap(); + node.insert(Focused(false)); } - let focused = rdom.get_state_mut_raw::(id).unwrap(); - *focused = Focused(true); - let node = rdom.get(id).unwrap(); + let mut node = rdom.get_mut(id).unwrap(); + node.insert(Focused(true)); self.focus_level = node.get::().unwrap().level; // reset the position to the currently focused element while self.focus_iter.next(rdom).id() != id {} diff --git a/packages/tui/src/lib.rs b/packages/tui/src/lib.rs index 9f316ed58..49b4d3555 100644 --- a/packages/tui/src/lib.rs +++ b/packages/tui/src/lib.rs @@ -24,7 +24,7 @@ use tokio::select; use tui::{backend::CrosstermBackend, layout::Rect, Terminal}; mod config; -#[cfg(feature = "dioxus")] +#[cfg(feature = "dioxus-bindings")] pub mod dioxus; mod focus; mod hooks; @@ -36,12 +36,16 @@ mod render; mod style; mod style_attributes; mod widget; -// mod widgets; +#[cfg(feature = "dioxus-bindings")] +mod widgets; -#[cfg(feature = "dioxus")] +#[cfg(feature = "dioxus-bindings")] pub use crate::dioxus::*; pub use config::*; pub use hooks::*; +pub use query::Query; +#[cfg(feature = "dioxus-bindings")] +pub use widgets::*; // the layout space has a multiplier of 10 to minimize rounding errors pub(crate) fn screen_to_layout_space(screen: u16) -> f32 { diff --git a/packages/tui/src/prelude/mod.rs b/packages/tui/src/prelude/mod.rs index 2d5b029a0..f7bbb3696 100644 --- a/packages/tui/src/prelude/mod.rs +++ b/packages/tui/src/prelude/mod.rs @@ -1 +1,2 @@ -// pub use crate::widgets::*; +#[cfg(feature = "dioxus-bindings")] +pub use crate::widgets::*; diff --git a/packages/tui/src/widgets/mod.rs b/packages/tui/src/widgets/mod.rs index cbf3d6d50..18e3b12b4 100644 --- a/packages/tui/src/widgets/mod.rs +++ b/packages/tui/src/widgets/mod.rs @@ -6,12 +6,16 @@ mod password; mod slider; mod textbox; -use dioxus_core::{ElementId, RenderReturn, Scope}; +use dioxus_core::{RenderReturn, Scope}; +use dioxus_native_core::NodeId; pub use input::*; -pub(crate) fn get_root_id(cx: Scope) -> Option { +use crate::DioxusElementToNodeId; + +pub(crate) fn get_root_id(cx: Scope) -> Option { if let RenderReturn::Ready(sync) = cx.root_node() { - sync.root_ids.get(0) + let mapping: DioxusElementToNodeId = cx.consume_context()?; + mapping.get_node_id(sync.root_ids.get(0)?) } else { None } diff --git a/packages/tui/src/widgets/number.rs b/packages/tui/src/widgets/number.rs index 48e198ebd..3e9d80d2d 100644 --- a/packages/tui/src/widgets/number.rs +++ b/packages/tui/src/widgets/number.rs @@ -113,7 +113,7 @@ pub(crate) fn NumbericInput<'a>(cx: Scope<'a, NumbericInputProps>) -> Element<'a }; if is_text{ let mut text = text_ref.write(); - cursor.write().handle_input(&k, &mut *text, max_len); + cursor.write().handle_input(&k.code(), &k.key(), &k.modifiers(), &mut *text, max_len); update(text.clone()); let node = tui_query.get(get_root_id(cx).unwrap()); diff --git a/packages/tui/src/widgets/password.rs b/packages/tui/src/widgets/password.rs index 714a5ad93..5e74e8b09 100644 --- a/packages/tui/src/widgets/password.rs +++ b/packages/tui/src/widgets/password.rs @@ -88,7 +88,9 @@ pub(crate) fn Password<'a>(cx: Scope<'a, PasswordProps>) -> Element<'a> { return; } let mut text = text_ref.write(); - cursor.write().handle_input(&k, &mut *text, max_len); + cursor + .write() + .handle_input(&k.code(), &k.key(), &k.modifiers(), &mut *text, max_len); if let Some(input_handler) = &cx.props.raw_oninput { input_handler.call(FormData { value: text.clone(), diff --git a/packages/tui/src/widgets/textbox.rs b/packages/tui/src/widgets/textbox.rs index ad48f0800..6c378cd72 100644 --- a/packages/tui/src/widgets/textbox.rs +++ b/packages/tui/src/widgets/textbox.rs @@ -90,7 +90,7 @@ pub(crate) fn TextBox<'a>(cx: Scope<'a, TextBoxProps>) -> Element<'a> { return; } let mut text = text_ref.write(); - cursor.write().handle_input(&k, &mut *text, max_len); + cursor.write().handle_input(&k.code(), &k.key(), &k.modifiers(), &mut *text, max_len); if let Some(input_handler) = &cx.props.raw_oninput{ input_handler.call(FormData{ value: text.clone(),