diff --git a/Cargo.toml b/Cargo.toml index 8f3a33d96..5955451f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,10 +15,10 @@ members = [ "packages/liveview", "packages/autofmt", "packages/rsx", - "docs/guide", "packages/tui", "packages/native-core", "packages/native-core-macro", + "docs/guide", ] # This is a "virtual package" diff --git a/packages/native-core/src/utils/cursor.rs b/packages/native-core/src/utils/cursor.rs index 86bcb71b1..c042d4cbf 100644 --- a/packages/native-core/src/utils/cursor.rs +++ b/packages/native-core/src/utils/cursor.rs @@ -200,7 +200,7 @@ impl Cursor { } change -= 1; } - c.move_col(change as i32, text); + c.move_col(change, text); }, data.modifiers().contains(Modifiers::SHIFT), ); diff --git a/packages/tui/src/widgets/number.rs b/packages/tui/src/widgets/number.rs index 05cb2d678..2df1f512b 100644 --- a/packages/tui/src/widgets/number.rs +++ b/packages/tui/src/widgets/number.rs @@ -99,7 +99,7 @@ pub(crate) fn NumbericInput<'a>(cx: Scope<'a, NumbericInputProps>) -> Element<'a update(text.clone()); }; - render! { + cx.render(rsx! { div{ width: "{width}", height: "{height}", @@ -120,7 +120,7 @@ pub(crate) fn NumbericInput<'a>(cx: Scope<'a, NumbericInputProps>) -> Element<'a let Point{ x, y } = node.pos().unwrap(); let Pos { col, row } = cursor.read().start; - let (x, y) = (col as u16 + x as u16 + if border == "none" {0} else {1}, row as u16 + y as u16 + if border == "none" {0} else {1}); + let (x, y) = (col as u16 + x as u16 + u16::from(border != "none"), row as u16 + y as u16 + u16::from(border != "none")); if let Ok(pos) = crossterm::cursor::position() { if pos != (x, y){ execute!(stdout(), MoveTo(x, y)).unwrap(); @@ -172,7 +172,7 @@ pub(crate) fn NumbericInput<'a>(cx: Scope<'a, NumbericInputProps>) -> Element<'a let Point{ x, y } = node.pos().unwrap(); let Pos { col, row } = cursor.read().start; - let (x, y) = (col as u16 + x as u16 + if border == "none" {0} else {1}, row as u16 + y as u16 + if border == "none" {0} else {1}); + let (x, y) = (col as u16 + x as u16 + u16::from(border != "none"), row as u16 + y as u16 + u16::from(border != "none")); if let Ok(pos) = crossterm::cursor::position() { if pos != (x, y){ execute!(stdout(), MoveTo(x, y)).unwrap(); @@ -205,5 +205,5 @@ pub(crate) fn NumbericInput<'a>(cx: Scope<'a, NumbericInputProps>) -> Element<'a "{text_after_second_cursor}" } - } + }) } diff --git a/packages/tui/src/widgets/password.rs b/packages/tui/src/widgets/password.rs index 7f8455d71..f82d0a346 100644 --- a/packages/tui/src/widgets/password.rs +++ b/packages/tui/src/widgets/password.rs @@ -83,40 +83,44 @@ pub(crate) fn Password<'a>(cx: Scope<'a, PasswordProps>) -> Element<'a> { "solid" }; - render! { - div{ + let onkeydown = move |k: KeyboardEvent| { + if k.key() == Key::Enter { + return; + } + let mut text = text_ref.write(); + cursor.write().handle_input(&k, &mut text, max_len); + if let Some(input_handler) = &cx.props.raw_oninput { + input_handler.call(FormData { + value: text.clone(), + values: HashMap::new(), + files: None, + }); + } + + let node = tui_query.get(get_root_id(cx).unwrap()); + let Point { x, y } = node.pos().unwrap(); + + let Pos { col, row } = cursor.read().start; + let (x, y) = ( + col as u16 + x as u16 + u16::from(border != "none"), + row as u16 + y as u16 + u16::from(border != "none"), + ); + if let Ok(pos) = crossterm::cursor::position() { + if pos != (x, y) { + execute!(stdout(), MoveTo(x, y)).unwrap(); + } + } else { + execute!(stdout(), MoveTo(x, y)).unwrap(); + } + }; + + cx.render(rsx! { + div { width: "{width}", height: "{height}", border_style: "{border}", - onkeydown: move |k| { - if k.key()== Key::Enter { - return; - } - let mut text = text_ref.write(); - cursor.write().handle_input(&k, &mut text, max_len); - if let Some(input_handler) = &cx.props.raw_oninput{ - input_handler.call(FormData{ - value: text.clone(), - values: HashMap::new(), - files: None - }); - } - - let node = tui_query.get(get_root_id(cx).unwrap()); - let Point{ x, y } = node.pos().unwrap(); - - let Pos { col, row } = cursor.read().start; - let (x, y) = (col as u16 + x as u16 + if border == "none" {0} else {1}, row as u16 + y as u16 + if border == "none" {0} else {1}); - if let Ok(pos) = crossterm::cursor::position() { - if pos != (x, y){ - execute!(stdout(), MoveTo(x, y)).unwrap(); - } - } - else{ - execute!(stdout(), MoveTo(x, y)).unwrap(); - } - }, + onkeydown: onkeydown, onmousemove: move |evt| { if *dragging.get() { @@ -133,6 +137,7 @@ pub(crate) fn Password<'a>(cx: Scope<'a, PasswordProps>) -> Element<'a> { } } }, + onmousedown: move |evt| { let offset = evt.data.element_coordinates(); let mut new = Pos::new(offset.x as usize, offset.y as usize); @@ -149,7 +154,7 @@ pub(crate) fn Password<'a>(cx: Scope<'a, PasswordProps>) -> Element<'a> { let Point{ x, y } = node.pos().unwrap(); let Pos { col, row } = cursor.read().start; - let (x, y) = (col as u16 + x as u16 + if border == "none" {0} else {1}, row as u16 + y as u16 + if border == "none" {0} else {1}); + let (x, y) = (col as u16 + x as u16 + u16::from(border != "none"), row as u16 + y as u16 + u16::from(border != "none")); if let Ok(pos) = crossterm::cursor::position() { if pos != (x, y){ execute!(stdout(), MoveTo(x, y)).unwrap(); @@ -182,5 +187,5 @@ pub(crate) fn Password<'a>(cx: Scope<'a, PasswordProps>) -> Element<'a> { "{text_after_second_cursor}" } - } + }) } diff --git a/packages/tui/src/widgets/slider.rs b/packages/tui/src/widgets/slider.rs index 43f0ac77e..0d5dbca13 100644 --- a/packages/tui/src/widgets/slider.rs +++ b/packages/tui/src/widgets/slider.rs @@ -42,13 +42,12 @@ pub(crate) fn Slider<'a>(cx: Scope<'a, SliderProps>) -> Element<'a> { .and_then(|v| v.parse().ok()) .unwrap_or(size / 10.0); - let current_value = if let Some(value) = value { - value - } else { - *value_state.get() + let current_value = match value { + Some(value) => value, + None => *value_state.get(), } - .max(min) - .min(max); + .clamp(min, max); + let fst_width = 100.0 * (current_value - min) / size; let snd_width = 100.0 * (max - current_value) / size; assert!(fst_width + snd_width > 99.0 && fst_width + snd_width < 101.0); @@ -63,7 +62,7 @@ pub(crate) fn Slider<'a>(cx: Scope<'a, SliderProps>) -> Element<'a> { } }; - render! { + cx.render(rsx! { div{ width: "{width}", height: "{height}", @@ -72,11 +71,11 @@ pub(crate) fn Slider<'a>(cx: Scope<'a, SliderProps>) -> Element<'a> { onkeydown: move |event| { match event.key() { Key::ArrowLeft => { - value_state.set((current_value - step).max(min).min(max)); + value_state.set((current_value - step).clamp(min, max)); update(value_state.current().to_string()); } Key::ArrowRight => { - value_state.set((current_value + step).max(min).min(max)); + value_state.set((current_value + step).clamp(min, max)); update(value_state.current().to_string()); } _ => () @@ -104,5 +103,5 @@ pub(crate) fn Slider<'a>(cx: Scope<'a, SliderProps>) -> Element<'a> { background_color: "rgba(10,10,10,0.5)", } } - } + }) } diff --git a/packages/tui/src/widgets/textbox.rs b/packages/tui/src/widgets/textbox.rs index 8628fca29..4a58725bc 100644 --- a/packages/tui/src/widgets/textbox.rs +++ b/packages/tui/src/widgets/textbox.rs @@ -79,7 +79,7 @@ pub(crate) fn TextBox<'a>(cx: Scope<'a, TextBoxProps>) -> Element<'a> { "solid" }; - render! { + cx.render(rsx! { div{ width: "{width}", height: "{height}", @@ -103,7 +103,7 @@ pub(crate) fn TextBox<'a>(cx: Scope<'a, TextBoxProps>) -> Element<'a> { let Point{ x, y } = node.pos().unwrap(); let Pos { col, row } = cursor.read().start; - let (x, y) = (col as u16 + x as u16 + if border == "none" {0} else {1}, row as u16 + y as u16 + if border == "none" {0} else {1}); + let (x, y) = (col as u16 + x as u16 + u16::from(border != "none"), row as u16 + y as u16 + u16::from(border != "none")); if let Ok(pos) = crossterm::cursor::position() { if pos != (x, y){ execute!(stdout(), MoveTo(x, y)).unwrap(); @@ -145,7 +145,7 @@ pub(crate) fn TextBox<'a>(cx: Scope<'a, TextBoxProps>) -> Element<'a> { let Point{ x, y } = node.pos().unwrap(); let Pos { col, row } = cursor.read().start; - let (x, y) = (col as u16 + x as u16 + if border == "none" {0} else {1}, row as u16 + y as u16 + if border == "none" {0} else {1}); + let (x, y) = (col as u16 + x as u16 + u16::from(border != "none"), row as u16 + y as u16 + u16::from(border != "none")); if let Ok(pos) = crossterm::cursor::position() { if pos != (x, y){ execute!(stdout(), MoveTo(x, y)).unwrap(); @@ -178,5 +178,5 @@ pub(crate) fn TextBox<'a>(cx: Scope<'a, TextBoxProps>) -> Element<'a> { "{text_after_second_cursor}" } - } + }) } diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index 7fa3d202d..fdae04a9a 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -339,8 +339,6 @@ fn read_input_to_data(target: Element) -> Rc { } fn walk_event_for_id(event: &web_sys::Event) -> Option<(ElementId, web_sys::Element)> { - use wasm_bindgen::JsCast; - let mut target = event .target() .expect("missing target") diff --git a/packages/web/src/lib.rs b/packages/web/src/lib.rs index 3f700740f..bfc6f6d63 100644 --- a/packages/web/src/lib.rs +++ b/packages/web/src/lib.rs @@ -54,19 +54,21 @@ // - Do DOM work in the next requestAnimationFrame callback pub use crate::cfg::Config; -use crate::dom::virtual_event_from_websys_event; pub use crate::util::{use_eval, EvalResult}; -use dioxus_core::{Element, ElementId, Scope, VirtualDom}; +use dioxus_core::{Element, Scope, VirtualDom}; use futures_util::{pin_mut, FutureExt, StreamExt}; mod cache; mod cfg; mod dom; mod hot_reload; -// mod rehydrate; -mod ric_raf; mod util; +// Currently disabled since it actually slows down immediate rendering +// todo: only schedule non-immediate renders through ric/raf +// mod ric_raf; +// mod rehydrate; + /// Launch the VirtualDOM given a root component and a configuration. /// /// This function expects the root component to not have root props. To launch the root component with root props, use @@ -195,8 +197,6 @@ pub async fn run_with_props(root: fn(Scope) -> Element, root_prop // the mutations come back with nothing - we need to actually mount them websys_dom.mount(); - let _work_loop = ric_raf::RafLoop::new(); - loop { log::debug!("waiting for work");