mirror of
https://github.com/DioxusLabs/dioxus
synced 2025-02-17 06:08:26 +00:00
chore: get event test working
This commit is contained in:
parent
565df11f7b
commit
0027cdd938
5 changed files with 263 additions and 214 deletions
|
@ -6,17 +6,23 @@ pub struct ElementId(pub usize);
|
||||||
|
|
||||||
pub struct ElementRef {
|
pub struct ElementRef {
|
||||||
// the pathway of the real element inside the template
|
// the pathway of the real element inside the template
|
||||||
pub path: &'static [u8],
|
pub path: ElementPath,
|
||||||
|
|
||||||
// The actual template
|
// The actual template
|
||||||
pub template: *mut VNode<'static>,
|
pub template: *mut VNode<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum ElementPath {
|
||||||
|
Deep(&'static [u8]),
|
||||||
|
Root(usize),
|
||||||
|
}
|
||||||
|
|
||||||
impl ElementRef {
|
impl ElementRef {
|
||||||
pub fn null() -> Self {
|
pub fn null() -> Self {
|
||||||
Self {
|
Self {
|
||||||
template: std::ptr::null_mut(),
|
template: std::ptr::null_mut(),
|
||||||
path: &[],
|
path: ElementPath::Root(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +34,21 @@ impl<'b> VirtualDom {
|
||||||
|
|
||||||
entry.insert(ElementRef {
|
entry.insert(ElementRef {
|
||||||
template: template as *const _ as *mut _,
|
template: template as *const _ as *mut _,
|
||||||
path,
|
path: ElementPath::Deep(path),
|
||||||
|
});
|
||||||
|
|
||||||
|
println!("Claiming {}", id);
|
||||||
|
|
||||||
|
ElementId(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_root(&mut self, template: &VNode, path: usize) -> ElementId {
|
||||||
|
let entry = self.elements.vacant_entry();
|
||||||
|
let id = entry.key();
|
||||||
|
|
||||||
|
entry.insert(ElementRef {
|
||||||
|
template: template as *const _ as *mut _,
|
||||||
|
path: ElementPath::Root(path),
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("Claiming {}", id);
|
println!("Claiming {}", id);
|
||||||
|
@ -76,3 +96,30 @@ impl<'b> VirtualDom {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl ElementPath {
|
||||||
|
pub(crate) fn is_ascendant(&self, big: &&[u8]) -> bool {
|
||||||
|
match *self {
|
||||||
|
ElementPath::Deep(small) => small.len() <= big.len() && small == &big[..small.len()],
|
||||||
|
ElementPath::Root(r) => big.len() == 1 && big[0] == r as u8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn path_ascendant() {
|
||||||
|
// assert!(&ElementPath::Deep(&[]).is_ascendant(&&[0_u8]));
|
||||||
|
// assert!(&ElementPath::Deep(&[1, 2]), &[1, 2, 3]);
|
||||||
|
// assert!(!is_path_ascendant(
|
||||||
|
// &ElementPath::Deep(&[1, 2, 3, 4]),
|
||||||
|
// &[1, 2, 3]
|
||||||
|
// ));
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<&[u8]> for ElementPath {
|
||||||
|
fn eq(&self, other: &&[u8]) -> bool {
|
||||||
|
match *self {
|
||||||
|
ElementPath::Deep(deep) => deep.eq(*other),
|
||||||
|
ElementPath::Root(r) => other.len() == 1 && other[0] == r as u8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -63,7 +63,8 @@ impl<'b: 'static> VirtualDom {
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateNode::Element { .. } | TemplateNode::Text(_) => {
|
TemplateNode::Element { .. } | TemplateNode::Text(_) => {
|
||||||
let this_id = self.next_element(template, &[]);
|
let this_id = self.next_root(template, root_idx);
|
||||||
|
|
||||||
template.root_ids[root_idx].set(this_id);
|
template.root_ids[root_idx].set(this_id);
|
||||||
self.mutations.push(LoadTemplate {
|
self.mutations.push(LoadTemplate {
|
||||||
name: template.template.id,
|
name: template.template.id,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
any_props::VProps,
|
any_props::VProps,
|
||||||
arena::{ElementId, ElementRef},
|
arena::{ElementId, ElementRef},
|
||||||
factory::RenderReturn,
|
factory::RenderReturn,
|
||||||
innerlude::{DirtyScope, Mutations, Scheduler, SchedulerMsg},
|
innerlude::{DirtyScope, ElementPath, Mutations, Scheduler, SchedulerMsg},
|
||||||
mutations::Mutation,
|
mutations::Mutation,
|
||||||
nodes::{Template, TemplateId},
|
nodes::{Template, TemplateId},
|
||||||
scheduler::{SuspenseBoundary, SuspenseId},
|
scheduler::{SuspenseBoundary, SuspenseId},
|
||||||
|
@ -368,15 +368,11 @@ impl VirtualDom {
|
||||||
let target_path = el_ref.path;
|
let target_path = el_ref.path;
|
||||||
|
|
||||||
for (idx, attr) in template.dynamic_attrs.iter().enumerate() {
|
for (idx, attr) in template.dynamic_attrs.iter().enumerate() {
|
||||||
fn is_path_ascendant(small: &[u8], big: &[u8]) -> bool {
|
|
||||||
small.len() >= big.len() && small == &big[..small.len()]
|
|
||||||
}
|
|
||||||
|
|
||||||
let this_path = template.template.attr_paths[idx];
|
let this_path = template.template.attr_paths[idx];
|
||||||
|
|
||||||
// listeners are required to be prefixed with "on", but they come back to the virtualdom with that missing
|
// listeners are required to be prefixed with "on", but they come back to the virtualdom with that missing
|
||||||
// we should fix this so that we look for "onclick" instead of "click"
|
// we should fix this so that we look for "onclick" instead of "click"
|
||||||
if &attr.name[2..] == name && is_path_ascendant(&target_path, &this_path) {
|
if &attr.name[2..] == name && target_path.is_ascendant(&this_path) {
|
||||||
listeners.push(&attr.value);
|
listeners.push(&attr.value);
|
||||||
|
|
||||||
// Break if the event doesn't bubble anyways
|
// Break if the event doesn't bubble anyways
|
||||||
|
@ -387,7 +383,7 @@ impl VirtualDom {
|
||||||
// Break if this is the exact target element.
|
// Break if this is the exact target element.
|
||||||
// This means we won't call two listeners with the same name on the same element. This should be
|
// This means we won't call two listeners with the same name on the same element. This should be
|
||||||
// documented, or be rejected from the rsx! macro outright
|
// documented, or be rejected from the rsx! macro outright
|
||||||
if this_path == target_path {
|
if target_path == this_path {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
//! Tests for the lifecycle of components.
|
//! Tests for the lifecycle of components.
|
||||||
use dioxus::core::{ElementId, Mutation::*};
|
use dioxus::core::{ElementId, Mutation::*};
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
type Shared<T> = Arc<Mutex<T>>;
|
type Shared<T> = Arc<Mutex<T>>;
|
||||||
|
@ -14,21 +15,26 @@ fn manual_diffing() {
|
||||||
value: Shared<&'static str>,
|
value: Shared<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static App: Component<AppProps> = |cx| {
|
fn app(cx: Scope<AppProps>) -> Element {
|
||||||
let val = cx.props.value.lock().unwrap();
|
let val = cx.props.value.lock().unwrap();
|
||||||
cx.render(rsx_without_templates! { div { "{val}" } })
|
cx.render(rsx! { div { "{val}" } })
|
||||||
};
|
};
|
||||||
|
|
||||||
let value = Arc::new(Mutex::new("Hello"));
|
let value = Arc::new(Mutex::new("Hello"));
|
||||||
let mut dom = VirtualDom::new_with_props(App, AppProps { value: value.clone() });
|
let mut dom = VirtualDom::new_with_props(app, AppProps { value: value.clone() });
|
||||||
|
|
||||||
let _ = dom.rebuild();
|
let _ = dom.rebuild();
|
||||||
|
|
||||||
*value.lock().unwrap() = "goodbye";
|
*value.lock().unwrap() = "goodbye";
|
||||||
|
|
||||||
let edits = dom.rebuild();
|
assert_eq!(
|
||||||
|
dom.rebuild().santize().edits,
|
||||||
println!("edits: {:?}", edits);
|
[
|
||||||
|
LoadTemplate { name: "template", index: 0, id: ElementId(3) },
|
||||||
|
HydrateText { path: &[0], value: "goodbye", id: ElementId(4) },
|
||||||
|
AppendChildren { m: 1 }
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -36,229 +42,228 @@ fn events_generate() {
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let count = cx.use_hook(|| 0);
|
let count = cx.use_hook(|| 0);
|
||||||
|
|
||||||
let inner = match *count {
|
match *count {
|
||||||
0 => {
|
0 => cx.render(rsx! {
|
||||||
rsx_without_templates! {
|
|
||||||
div {
|
div {
|
||||||
onclick: move |_| *count += 1,
|
onclick: move |_| {
|
||||||
div {
|
*count += 1
|
||||||
"nested"
|
},
|
||||||
}
|
div { "nested" }
|
||||||
"Click me!"
|
"Click me!"
|
||||||
}
|
}
|
||||||
|
}),
|
||||||
|
_ => cx.render(rsx!(())),
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
cx.render(inner)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut dom = VirtualDom::new(app);
|
let mut dom = VirtualDom::new(app);
|
||||||
let mut channel = dom.get_scheduler_channel();
|
_ = dom.rebuild();
|
||||||
assert!(dom.has_work());
|
|
||||||
|
dom.handle_event(
|
||||||
|
"click",
|
||||||
|
Rc::new(MouseData::default()),
|
||||||
|
ElementId(1),
|
||||||
|
true,
|
||||||
|
EventPriority::Immediate,
|
||||||
|
);
|
||||||
|
|
||||||
|
dom.mark_dirty_scope(ScopeId(0));
|
||||||
|
let edits = dom.render_immediate();
|
||||||
|
|
||||||
let edits = dom.rebuild();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
edits.edits,
|
edits.edits,
|
||||||
[
|
[
|
||||||
CreateElement { root: Some(1), tag: "div", children: 0 },
|
CreatePlaceholder { id: ElementId(2) },
|
||||||
NewEventListener { event_name: "click", scope: ScopeId(0), root: Some(1) },
|
ReplaceWith { id: ElementId(1), m: 1 }
|
||||||
CreateElement { root: Some(2), tag: "div", children: 0 },
|
|
||||||
CreateTextNode { root: Some(3), text: "nested" },
|
|
||||||
AppendChildren { root: Some(2), children: vec![3] },
|
|
||||||
CreateTextNode { root: Some(4), text: "Click me!" },
|
|
||||||
AppendChildren { root: Some(1), children: vec![2, 4] },
|
|
||||||
AppendChildren { root: Some(0), children: vec![1] }
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn components_generate() {
|
// fn components_generate() {
|
||||||
fn app(cx: Scope) -> Element {
|
// fn app(cx: Scope) -> Element {
|
||||||
let render_phase = cx.use_hook(|| 0);
|
// let render_phase = cx.use_hook(|| 0);
|
||||||
*render_phase += 1;
|
// *render_phase += 1;
|
||||||
|
|
||||||
cx.render(match *render_phase {
|
// cx.render(match *render_phase {
|
||||||
1 => rsx_without_templates!("Text0"),
|
// 1 => rsx_without_templates!("Text0"),
|
||||||
2 => rsx_without_templates!(div {}),
|
// 2 => rsx_without_templates!(div {}),
|
||||||
3 => rsx_without_templates!("Text2"),
|
// 3 => rsx_without_templates!("Text2"),
|
||||||
4 => rsx_without_templates!(Child {}),
|
// 4 => rsx_without_templates!(Child {}),
|
||||||
5 => rsx_without_templates!({ None as Option<()> }),
|
// 5 => rsx_without_templates!({ None as Option<()> }),
|
||||||
6 => rsx_without_templates!("text 3"),
|
// 6 => rsx_without_templates!("text 3"),
|
||||||
7 => rsx_without_templates!({ (0..2).map(|f| rsx_without_templates!("text {f}")) }),
|
// 7 => rsx_without_templates!({ (0..2).map(|f| rsx_without_templates!("text {f}")) }),
|
||||||
8 => rsx_without_templates!(Child {}),
|
// 8 => rsx_without_templates!(Child {}),
|
||||||
_ => todo!(),
|
// _ => todo!(),
|
||||||
})
|
// })
|
||||||
};
|
// };
|
||||||
|
|
||||||
fn Child(cx: Scope) -> Element {
|
// fn Child(cx: Scope) -> Element {
|
||||||
println!("Running child");
|
// println!("Running child");
|
||||||
cx.render(rsx_without_templates! {
|
// cx.render(rsx_without_templates! {
|
||||||
h1 {}
|
// h1 {}
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
let mut dom = VirtualDom::new(app);
|
// let mut dom = VirtualDom::new(app);
|
||||||
let edits = dom.rebuild();
|
// let edits = dom.rebuild();
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
edits.edits,
|
// edits.edits,
|
||||||
[
|
// [
|
||||||
CreateTextNode { root: Some(1), text: "Text0" },
|
// CreateTextNode { root: Some(1), text: "Text0" },
|
||||||
AppendChildren { root: Some(0), children: vec![1] }
|
// AppendChildren { root: Some(0), children: vec![1] }
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
|
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
dom.hard_diff(ScopeId(0)).edits,
|
// dom.hard_diff(ScopeId(0)).edits,
|
||||||
[
|
// [
|
||||||
CreateElement { root: Some(2), tag: "div", children: 0 },
|
// CreateElement { root: Some(2), tag: "div", children: 0 },
|
||||||
ReplaceWith { root: Some(1), nodes: vec![2] }
|
// ReplaceWith { root: Some(1), nodes: vec![2] }
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
|
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
dom.hard_diff(ScopeId(0)).edits,
|
// dom.hard_diff(ScopeId(0)).edits,
|
||||||
[
|
// [
|
||||||
CreateTextNode { root: Some(1), text: "Text2" },
|
// CreateTextNode { root: Some(1), text: "Text2" },
|
||||||
ReplaceWith { root: Some(2), nodes: vec![1] }
|
// ReplaceWith { root: Some(2), nodes: vec![1] }
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
|
|
||||||
// child {}
|
// // child {}
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
dom.hard_diff(ScopeId(0)).edits,
|
// dom.hard_diff(ScopeId(0)).edits,
|
||||||
[
|
// [
|
||||||
CreateElement { root: Some(2), tag: "h1", children: 0 },
|
// CreateElement { root: Some(2), tag: "h1", children: 0 },
|
||||||
ReplaceWith { root: Some(1), nodes: vec![2] }
|
// ReplaceWith { root: Some(1), nodes: vec![2] }
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
|
|
||||||
// placeholder
|
// // placeholder
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
dom.hard_diff(ScopeId(0)).edits,
|
// dom.hard_diff(ScopeId(0)).edits,
|
||||||
[
|
// [
|
||||||
CreatePlaceholder { root: Some(1) },
|
// CreatePlaceholder { root: Some(1) },
|
||||||
ReplaceWith { root: Some(2), nodes: vec![1] }
|
// ReplaceWith { root: Some(2), nodes: vec![1] }
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
|
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
dom.hard_diff(ScopeId(0)).edits,
|
// dom.hard_diff(ScopeId(0)).edits,
|
||||||
[
|
// [
|
||||||
CreateTextNode { root: Some(2), text: "text 3" },
|
// CreateTextNode { root: Some(2), text: "text 3" },
|
||||||
ReplaceWith { root: Some(1), nodes: vec![2] }
|
// ReplaceWith { root: Some(1), nodes: vec![2] }
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
|
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
dom.hard_diff(ScopeId(0)).edits,
|
// dom.hard_diff(ScopeId(0)).edits,
|
||||||
[
|
// [
|
||||||
CreateTextNode { text: "text 0", root: Some(1) },
|
// CreateTextNode { text: "text 0", root: Some(1) },
|
||||||
CreateTextNode { text: "text 1", root: Some(3) },
|
// CreateTextNode { text: "text 1", root: Some(3) },
|
||||||
ReplaceWith { root: Some(2), nodes: vec![1, 3] },
|
// ReplaceWith { root: Some(2), nodes: vec![1, 3] },
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
|
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
dom.hard_diff(ScopeId(0)).edits,
|
// dom.hard_diff(ScopeId(0)).edits,
|
||||||
[
|
// [
|
||||||
CreateElement { tag: "h1", root: Some(2), children: 0 },
|
// CreateElement { tag: "h1", root: Some(2), children: 0 },
|
||||||
ReplaceWith { root: Some(1), nodes: vec![2] },
|
// ReplaceWith { root: Some(1), nodes: vec![2] },
|
||||||
Remove { root: Some(3) },
|
// Remove { root: Some(3) },
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn component_swap() {
|
// fn component_swap() {
|
||||||
fn app(cx: Scope) -> Element {
|
// fn app(cx: Scope) -> Element {
|
||||||
let render_phase = cx.use_hook(|| 0);
|
// let render_phase = cx.use_hook(|| 0);
|
||||||
*render_phase += 1;
|
// *render_phase += 1;
|
||||||
|
|
||||||
cx.render(match *render_phase {
|
// cx.render(match *render_phase {
|
||||||
0 => rsx_without_templates!(
|
// 0 => rsx_without_templates!(
|
||||||
div {
|
// div {
|
||||||
NavBar {}
|
// NavBar {}
|
||||||
Dashboard {}
|
// Dashboard {}
|
||||||
}
|
// }
|
||||||
),
|
// ),
|
||||||
1 => rsx_without_templates!(
|
// 1 => rsx_without_templates!(
|
||||||
div {
|
// div {
|
||||||
NavBar {}
|
// NavBar {}
|
||||||
Results {}
|
// Results {}
|
||||||
}
|
// }
|
||||||
),
|
// ),
|
||||||
2 => rsx_without_templates!(
|
// 2 => rsx_without_templates!(
|
||||||
div {
|
// div {
|
||||||
NavBar {}
|
// NavBar {}
|
||||||
Dashboard {}
|
// Dashboard {}
|
||||||
}
|
// }
|
||||||
),
|
// ),
|
||||||
3 => rsx_without_templates!(
|
// 3 => rsx_without_templates!(
|
||||||
div {
|
// div {
|
||||||
NavBar {}
|
// NavBar {}
|
||||||
Results {}
|
// Results {}
|
||||||
}
|
// }
|
||||||
),
|
// ),
|
||||||
4 => rsx_without_templates!(
|
// 4 => rsx_without_templates!(
|
||||||
div {
|
// div {
|
||||||
NavBar {}
|
// NavBar {}
|
||||||
Dashboard {}
|
// Dashboard {}
|
||||||
}
|
// }
|
||||||
),
|
// ),
|
||||||
_ => rsx_without_templates!("blah"),
|
// _ => rsx_without_templates!("blah"),
|
||||||
})
|
// })
|
||||||
};
|
// };
|
||||||
|
|
||||||
static NavBar: Component = |cx| {
|
// static NavBar: Component = |cx| {
|
||||||
println!("running navbar");
|
// println!("running navbar");
|
||||||
cx.render(rsx_without_templates! {
|
// cx.render(rsx_without_templates! {
|
||||||
h1 {
|
// h1 {
|
||||||
"NavBar"
|
// "NavBar"
|
||||||
{(0..3).map(|f| rsx_without_templates!(NavLink {}))}
|
// {(0..3).map(|f| rsx_without_templates!(NavLink {}))}
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
};
|
// };
|
||||||
|
|
||||||
static NavLink: Component = |cx| {
|
// static NavLink: Component = |cx| {
|
||||||
println!("running navlink");
|
// println!("running navlink");
|
||||||
cx.render(rsx_without_templates! {
|
// cx.render(rsx_without_templates! {
|
||||||
h1 {
|
// h1 {
|
||||||
"NavLink"
|
// "NavLink"
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
};
|
// };
|
||||||
|
|
||||||
static Dashboard: Component = |cx| {
|
// static Dashboard: Component = |cx| {
|
||||||
println!("running dashboard");
|
// println!("running dashboard");
|
||||||
cx.render(rsx_without_templates! {
|
// cx.render(rsx_without_templates! {
|
||||||
div {
|
// div {
|
||||||
"dashboard"
|
// "dashboard"
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
};
|
// };
|
||||||
|
|
||||||
static Results: Component = |cx| {
|
// static Results: Component = |cx| {
|
||||||
println!("running results");
|
// println!("running results");
|
||||||
cx.render(rsx_without_templates! {
|
// cx.render(rsx_without_templates! {
|
||||||
div {
|
// div {
|
||||||
"results"
|
// "results"
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
};
|
// };
|
||||||
|
|
||||||
let mut dom = VirtualDom::new(app);
|
// let mut dom = VirtualDom::new(app);
|
||||||
let edits = dom.rebuild();
|
// let edits = dom.rebuild();
|
||||||
dbg!(&edits);
|
// dbg!(&edits);
|
||||||
|
|
||||||
let edits = dom.work_with_deadline(|| false);
|
// let edits = dom.work_with_deadline(|| false);
|
||||||
dbg!(&edits);
|
// dbg!(&edits);
|
||||||
let edits = dom.work_with_deadline(|| false);
|
// let edits = dom.work_with_deadline(|| false);
|
||||||
dbg!(&edits);
|
// dbg!(&edits);
|
||||||
let edits = dom.work_with_deadline(|| false);
|
// let edits = dom.work_with_deadline(|| false);
|
||||||
dbg!(&edits);
|
// dbg!(&edits);
|
||||||
let edits = dom.work_with_deadline(|| false);
|
// let edits = dom.work_with_deadline(|| false);
|
||||||
dbg!(&edits);
|
// dbg!(&edits);
|
||||||
}
|
// }
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub type MouseEvent = UiEvent<MouseData>;
|
||||||
|
|
||||||
/// A synthetic event that wraps a web-style [`MouseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)
|
/// A synthetic event that wraps a web-style [`MouseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Default)]
|
||||||
/// Data associated with a mouse event
|
/// Data associated with a mouse event
|
||||||
///
|
///
|
||||||
/// Do not use the deprecated fields; they may change or become private in the future.
|
/// Do not use the deprecated fields; they may change or become private in the future.
|
||||||
|
|
Loading…
Add table
Reference in a new issue