1
0
Эх сурвалжийг харах

wip: fix issues with lifetimes

this commit fixes some lifetime issues regarding having to "move" data into the IntoVNode closure.
Jonathan Kelley 4 жил өмнө
parent
commit
a38a81e
39 өөрчлөгдсөн 567 нэмэгдсэн , 256 устгасан
  1. 9 9
      README.md
  2. 20 5
      examples/readme.rs
  3. 162 17
      packages/core-macro/src/lib.rs
  4. 1 1
      packages/core-macro/src/rsx/element.rs
  5. 1 1
      packages/core-macro/src/rsx/mod.rs
  6. 20 18
      packages/core/examples/alternative.rs
  7. 19 6
      packages/core/src/component.rs
  8. 6 6
      packages/core/src/debug_renderer.rs
  9. 195 66
      packages/core/src/events.rs
  10. 1 2
      packages/core/src/lib.rs
  11. 50 85
      packages/core/src/nodebuilder.rs
  12. 19 22
      packages/core/src/virtual_dom.rs
  13. 13 1
      packages/html-namespace/src/lib.rs
  14. 1 0
      packages/web/Cargo.toml
  15. 1 0
      packages/web/examples/basic.rs
  16. 3 2
      packages/web/examples/calculator.rs
  17. 1 0
      packages/web/examples/children.rs
  18. 1 0
      packages/web/examples/context.rs
  19. 3 2
      packages/web/examples/deep.rs
  20. 3 1
      packages/web/examples/demoday.rs
  21. 1 0
      packages/web/examples/derive.rs
  22. 1 0
      packages/web/examples/fragment.rs
  23. 9 4
      packages/web/examples/framework_benchmark.rs
  24. 1 0
      packages/web/examples/hello.rs
  25. 1 0
      packages/web/examples/helloworld.rs
  26. 2 0
      packages/web/examples/infer.rs
  27. 4 2
      packages/web/examples/input.rs
  28. 1 0
      packages/web/examples/jackjillrsx.rs
  29. 2 0
      packages/web/examples/landingpage.rs
  30. 2 2
      packages/web/examples/landingpage2.rs
  31. 2 1
      packages/web/examples/list.rs
  32. 1 0
      packages/web/examples/listy.rs
  33. 1 0
      packages/web/examples/many.rs
  34. 1 0
      packages/web/examples/model.rs
  35. 3 1
      packages/web/examples/rsxt.rs
  36. 2 1
      packages/web/examples/todomvc-nodeps.rs
  37. 1 0
      packages/web/examples/todomvc/main.rs
  38. 2 1
      packages/web/examples/todomvc_simple.rs
  39. 1 0
      src/lib.rs

+ 9 - 9
README.md

@@ -107,29 +107,29 @@ Dioxus is heavily inspired by React, but we want your transition to feel like an
 | Feature                 | Dioxus | React | Notes for Dioxus                                      |
 | ----------------------- | ------ | ----- | ----------------------------------------------------- |
 | Conditional Rendering   | ✅      | ✅     | if/then to hide/show component                        |
-| Map, Iterator           | ✅      | ✅     | map/filter/reduce rsx!                                |
+| Map, Iterator           | ✅      | ✅     | map/filter/reduce to produce rsx!                     |
 | Keyed Components        | ✅      | ✅     | advanced diffing with keys                            |
 | Web                     | ✅      | ✅     | renderer for web browser                              |
 | Desktop (webview)       | ✅      | ✅     | renderer for desktop                                  |
-| Context                 | ✅      | ✅     | share state through the tree                          |
+| Shared State (Context)  | ✅      | ✅     | share state through the tree                          |
 | Hook                    | ✅      | ✅     | memory cells in components                            |
 | SSR                     | ✅      | ✅     | render directly to string                             |
 | Component Children      | ✅      | ✅     | cx.children() as a list of nodes                      |
-| Null components         | ✅      | ✅     | allow returning no components                         |
-| No-div components       | ✅      | ✅     | components that render components                     |
-| Fragments               | ✅      | ✅     | rsx! can return multiple elements without a root      |
+| Headless components     | ✅      | ✅     | components that don't return real elements            |
+| Fragments               | ✅      | ✅     | multiple elements without a real root                 |
 | Manual Props            | ✅      | ✅     | Manually pass in props with spread syntax             |
 | Controlled Inputs       | ✅      | ✅     | stateful wrappers around inputs                       |
-| CSS/Inline Styles       | ✅      | ✅     | syntax for inline styles/attribute groups[2]          |
-| NodeRef                 | 🛠      | ✅     | gain direct access to nodes [1]                       |
-| 1st class global state  | 🛠      | ✅     | redux/recoil/mobx on top of context                   |
+| CSS/Inline Styles       | ✅      | ✅     | syntax for inline styles/attribute groups             |
+| Custom elements         | ✅      | ✅     | Define new element primitives                         |
+| Compile-time correct    | ✅      | ✅     | Throw errors on invalid template layouts              |
+| 1st class global state  | ✅      | ❓     | redux/recoil/mobx on top of context                   |
 | Suspense                | 🛠      | ✅     | schedule future render from future/promise            |
 | Cooperative Scheduling  | 🛠      | ✅     | Prioritize important events over non-important events |
 | Fine-grained reactivity | 🛠      | ❓     | Skip diffing for fine-grain updates                   |
 | Runs natively           | ✅      | ❓     | runs as a portable binary w/o a runtime (Node)        |
+| NodeRef                 | 🛠      | ✅     | gain direct access to nodes [1]                       |
 
 - [1] Currently blocked until we figure out a cross-platform way of exposing an imperative Node API.
-- [2] Would like to solve this in a more general way. Something like attribute groups that's not styling-specific.
 
 ### Phase 2: Advanced Toolkits
 

+ 20 - 5
examples/readme.rs

@@ -2,8 +2,7 @@
 //!
 //! The example from the README.md
 
-use dioxus::{events::on::MouseEvent, prelude::*};
-use dioxus_html_namespace::{button, div, h1};
+use dioxus::prelude::*;
 
 fn main() {
     dioxus::web::launch(Example)
@@ -12,11 +11,27 @@ fn main() {
 fn Example(cx: Context<()>) -> VNode {
     let name = use_state(&cx, || "..?");
 
-    let handler = move |e: MouseEvent| e.cl;
-
     cx.render(rsx! {
         h1 { "Hello, {name}" }
-        button { "?", onclick: move |event| name.set("world!")}
+        button { "?", onclick: move |_| name.set("world!")}
         button { "?", onclick: move |_| name.set("Dioxus 🎉")}
     })
 }
+
+static Example2: FC<()> = |cx| {
+    let (g, set_g) = use_state_classic(&cx, || 0);
+    let v = (0..10).map(|f| {
+        dioxus::prelude::LazyNodes::new(move |__cx: &NodeFactory| {
+            __cx.element(dioxus_elements::li)
+                .listeners([dioxus::events::on::onclick(__cx, move |_| set_g(10))])
+                .finish()
+        })
+    });
+    cx.render(dioxus::prelude::LazyNodes::new(
+        move |__cx: &NodeFactory| {
+            __cx.element(dioxus_elements::div)
+                .children([__cx.fragment_from_iter(v)])
+                .finish()
+        },
+    ))
+};

+ 162 - 17
packages/core-macro/src/lib.rs

@@ -20,23 +20,6 @@ pub fn html(s: TokenStream) -> TokenStream {
     }
 }
 
-/// The html! macro makes it easy for developers to write jsx-style markup in their components.
-/// ```
-/// rsx! {
-///     div {
-///         class: "some special class"
-///         h1 { "Children too" }
-///     }
-/// }
-/// ```
-#[proc_macro]
-pub fn rsx(s: TokenStream) -> TokenStream {
-    match syn::parse::<rsx::RsxRender>(s) {
-        Err(e) => e.to_compile_error().into(),
-        Ok(s) => s.to_token_stream().into(),
-    }
-}
-
 /// The html! macro makes it easy for developers to write jsx-style markup in their components.
 /// We aim to keep functional parity with html templates.
 #[proc_macro]
@@ -97,3 +80,165 @@ pub fn derive_typed_builder(input: proc_macro::TokenStream) -> proc_macro::Token
         Err(error) => error.to_compile_error().into(),
     }
 }
+
+/// The html! macro makes it easy for developers to write jsx-style markup in their components.
+///
+/// ## Complete Reference Guide:
+/// ```
+/// const Example: FC<()> = |cx| {
+///     let formatting = "formatting!";
+///     let formatting_tuple = ("a", "b");
+///     let lazy_fmt = format_args!("lazily formatted text");
+///     cx.render(rsx! {
+///         div {
+///             // Elements
+///             div {}
+///             h1 {"Some text"}
+///             h1 {"Some text with {formatting}"}
+///             h1 {"Formatting basic expressions {formatting_tuple.0} and {formatting_tuple.1}"}
+///             h2 {
+///                 "Multiple"
+///                 "Text"
+///                 "Blocks"
+///                 "Use comments as separators in html"
+///             }
+///             div {
+///                 h1 {"multiple"}
+///                 h2 {"nested"}
+///                 h3 {"elements"}
+///             }
+///             div {
+///                 class: "my special div"
+///                 h1 {"Headers and attributes!"}
+///             }
+///             div {
+///                 // pass simple rust expressions in
+///                 class: lazy_fmt,
+///                 id: format_args!("attributes can be passed lazily with std::fmt::Arguments"),
+///                 div {
+///                     class: {
+///                         const WORD: &str = "expressions";
+///                         format_args!("Arguments can be passed in through curly braces for complex {}", WORD)
+///                     }
+///                 }
+///             }
+///
+///             // Expressions can be used in element position too:
+///             {rsx!(p { "More templating!" })}
+///             {html!(<p>"Even HTML templating!!"</p>)}
+///
+///             // Iterators
+///             {(0..10).map(|i| rsx!(li { "{i}" }))}
+///             {{
+///                 let data = std::collections::HashMap::<&'static str, &'static str>::new();
+///                 // Iterators *should* have keys when you can provide them.
+///                 // Keys make your app run faster. Make sure your keys are stable, unique, and predictable.
+///                 // Using an "ID" associated with your data is a good idea.
+///                 data.into_iter().map(|(k, v)| rsx!(li { key: "{k}" "{v}" }))
+///             }}
+///            
+///             // Matching
+///             // Matching will throw a Rust error about "no two closures are the same type"
+///             // To fix this, call "render" method or use the "in" syntax to produce VNodes.
+///             // There's nothing we can do about it, sorry :/ (unless you want *really* unhygenic macros)
+///             {match true {
+///                 true => rsx!(in cx, h1 {"Top text"}),
+///                 false => cx.render(rsx!( h1 {"Bottom text"}))
+///             }}
+///
+///             // Conditional rendering
+///             // Dioxus conditional rendering is based around None/Some. We have no special syntax for conditionals.
+///             // You can convert a bool condition to rsx! with .then and .or
+///             {true.then(|| rsx!(div {}))}
+///
+///             // True conditions need to be rendered (same reasons as matching)
+///             {if true {
+///                 rsx!(in cx, h1 {"Top text"})
+///             } else {
+///                 rsx!(in cx, h1 {"Bottom text"})
+///             }}
+///
+///             // returning "None" is a bit noisy... but rare in practice
+///             {None as Option<()>}
+///
+///             // Use the Dioxus type-alias for less noise
+///             {NONE_ELEMENT}
+///
+///             // can also just use empty fragments
+///             Fragment {}
+///
+///             // Fragments let you insert groups of nodes without a parent.
+///             // This lets you make components that insert elements as siblings without a container.
+///             div {"A"}
+///             Fragment {
+///                 div {"B"}
+///                 div {"C"}
+///                 Fragment {
+///                     "D"
+///                     Fragment {
+///                         "heavily nested fragments is an antipattern"
+///                         "they cause Dioxus to do unnecessary work"
+///                         "don't use them carelessly if you can help it"
+///                     }
+///                 }
+///             }
+///
+///             // Components
+///             // Can accept any paths
+///             // Notice how you still get syntax highlighting and IDE support :)
+///             Baller {}
+///             baller::Baller { }
+///             crate::baller::Baller {}
+///
+///             // Can take properties
+///             Taller { a: "asd" }
+///
+///             // Can take optional properties
+///             Taller { a: "asd" }
+///
+///             // Can pass in props directly as an expression
+///             {{
+///                 let props = TallerProps {a: "hello"};
+///                 rsx!(Taller { ..props })
+///             }}
+///
+///             // Spreading can also be overridden manually
+///             Taller {
+///                 ..TallerProps { a: "ballin!" }
+///                 a: "not ballin!"
+///             }
+///
+///             // Can take children too!
+///             Taller { a: "asd", div {"hello world!"} }
+///         }
+///     })
+/// };
+///
+/// mod baller {
+///     use super::*;
+///     pub struct BallerProps {}
+///
+///     /// This component totally balls
+///     pub fn Baller(cx: Context<()>) -> VNode {
+///         todo!()
+///     }
+/// }
+///
+/// #[derive(Debug, PartialEq, Props)]
+/// pub struct TallerProps {
+///     a: &'static str,
+/// }
+///
+/// /// This component is taller than most :)
+/// pub fn Taller(cx: Context<TallerProps>) -> VNode {
+///     let b = true;
+///     todo!()
+/// }
+/// ```
+#[proc_macro]
+pub fn rsx(s: TokenStream) -> TokenStream {
+    match syn::parse::<rsx::RsxRender>(s) {
+        Err(e) => e.to_compile_error().into(),
+        Ok(s) => s.to_token_stream().into(),
+    }
+}

+ 1 - 1
packages/core-macro/src/rsx/element.rs

@@ -25,7 +25,7 @@ impl ToTokens for Element {
         // let name = &self.name.to_string();
 
         tokens.append_all(quote! {
-            __cx.element(#name)
+            __cx.element(dioxus_elements::#name)
         });
 
         // Add attributes

+ 1 - 1
packages/core-macro/src/rsx/mod.rs

@@ -80,7 +80,7 @@ impl ToTokens for RsxRender {
             quote! {#inner}
         } else {
             let childs = &self.roots;
-            quote! { __cx.fragment_from_iter(&[ #(#childs),* ]) }
+            quote! { __cx.fragment_from_iter([ #(#childs),* ]) }
         };
 
         match &self.custom_context {

+ 20 - 18
packages/core/examples/alternative.rs

@@ -1,27 +1,29 @@
 fn main() {}
 
+use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
+mod dioxus_elements {
+    use super::*;
+    pub struct div;
+    impl DioxusElement for div {
+        const TAG_NAME: &'static str = "str";
+        const NAME_SPACE: Option<&'static str> = None;
+    }
+}
 
 static Example: FC<()> = |cx| {
-    cx.render(dioxus_core::prelude::LazyNodes::new(move |cx| {
+    let list = (0..10).map(|f| {
+        //
+        LazyNodes::new(move |f: NodeFactory| todo!())
+    });
+    cx.render(LazyNodes::new(move |cx| {
         let bump = cx.bump();
-        dioxus_core::builder::ElementBuilder::new(cx, "h1")
-            .children([dioxus_core::builder::text3(bump, format_args!("hello"))])
-            .finish()
-    }))
-};
-
-struct Props {
-    text: String,
-}
-static Example2: FC<Props> = |cx| {
-    cx.render(dioxus_core::prelude::LazyNodes::new(move |__cx| {
-        let bump = __cx.bump();
-        dioxus_core::builder::ElementBuilder::new(__cx, "h1")
-            .children([dioxus_core::builder::text3(
-                bump,
-                format_args!("{}", cx.props.text),
-            )])
+        dioxus_core::builder::ElementBuilder::new(&cx, "h1")
+            .children([
+                cx.text(format_args!("hello")),
+                cx.text(format_args!("hello")),
+                cx.fragment_from_iter(list),
+            ])
             .finish()
     }))
 };

+ 19 - 6
packages/core/src/component.rs

@@ -49,10 +49,23 @@ pub fn fc_to_builder<T: Properties>(_: FC<T>) -> T::Builder {
 ///
 /// Fragments are incredibly useful when necessary, but *do* add cost in the diffing phase.
 /// Try to avoid nesting fragments if you can. Infinitely nested Fragments *will* cause diffing to crash.
-#[allow(non_upper_case_globals)]
-pub const Fragment: FC<()> = |cx| {
-    use crate::prelude::*;
-    cx.render(LazyNodes::new(move |c| {
-        crate::nodebuilder::vfragment(c, None, cx.children())
+use crate::prelude::*;
+pub fn Fragment<'a>(cx: Context<'a, ()>) -> VNode<'a> {
+    let childs: &'a [VNode<'a>] = cx.children();
+    cx.render(LazyNodes::new({
+        move |f| {
+            //
+            f.fragment_from_iter(childs)
+        }
     }))
-};
+}
+// #[allow(non_upper_case_globals)]
+// pub const Fragment: FC<()> = |cx| {
+//     use crate::prelude::*;
+//     let childs = cx.children();
+//     cx.render(LazyNodes::new(move |c| {
+//         c.fragment_from_iter(childs)
+//         // c.text(format_args!(""))
+//         // crate::nodebuilder::vfragment(c, None, cx.children())
+//     }))
+// };

+ 6 - 6
packages/core/src/debug_renderer.rs

@@ -49,18 +49,18 @@ impl DebugRenderer {
     // If you have a list or "nth" child, you do need to list those children, but you don't need to
     // fill in their children/attrs/etc
     // Does not handle children or lifecycles and will always fail the test if they show up in the rhs
-    pub fn compare<'a, F>(&self, other: LazyNodes<'a, F>) -> Result<()>
+    pub fn compare<F>(&self, other: LazyNodes<F>) -> Result<()>
     where
-        F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
+        F: for<'b, 'c> FnOnce(&'b NodeFactory<'c>) -> VNode<'c>,
     {
         Ok(())
     }
 
     // Do a full compare - everything must match
     // Ignores listeners and children components
-    pub fn compare_full<'a, F>(&self, other: LazyNodes<'a, F>) -> Result<()>
+    pub fn compare_full<F>(&self, other: LazyNodes<F>) -> Result<()>
     where
-        F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
+        F: for<'b, 'c> FnOnce(&'b NodeFactory<'c>) -> VNode<'c>,
     {
         Ok(())
     }
@@ -69,9 +69,9 @@ impl DebugRenderer {
         Ok(())
     }
 
-    pub fn render_nodes<'a, F>(&self, other: LazyNodes<'a, F>) -> Result<()>
+    pub fn render_nodes<F>(&self, other: LazyNodes<F>) -> Result<()>
     where
-        F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
+        F: for<'b, 'c> FnOnce(&'b NodeFactory<'c>) -> VNode<'c>,
     {
         Ok(())
     }

+ 195 - 66
packages/core/src/events.rs

@@ -124,14 +124,12 @@ pub mod on {
 
     macro_rules! event_directory {
         ( $(
-            $(
-                #[$attr:meta]
-            )*
+            $( #[$attr:meta] )*
             $eventdata:ident($wrapper:ident): [
                 $(
-                    #[$method_attr:meta]
+                    $( #[$method_attr:meta] )*
+                    $name:ident
                 )*
-                $( $name:ident )*
             ];
         )* ) => {
             $(
@@ -149,8 +147,8 @@ pub mod on {
                     }
                 }
 
-                $(#[$method_attr])*
                 $(
+                    $(#[$method_attr])*
                     pub fn $name<'a>(
                         c: &'_ NodeFactory<'a>,
                         callback: impl Fn($wrapper) + 'a,
@@ -181,35 +179,51 @@ pub mod on {
     //
     //
     event_directory! {
-
-
-
-
         ClipboardEventInner(ClipboardEvent): [
             /// Called when "copy"
             oncopy
+            /// oncut
             oncut
+            /// onpaste
             onpaste
         ];
+
         CompositionEventInner(CompositionEvent): [
+            /// oncompositionend
             oncompositionend
+            /// oncompositionstart
             oncompositionstart
+            /// oncompositionupdate
             oncompositionupdate
         ];
+
         KeyboardEventInner(KeyboardEvent): [
+            /// onkeydown
             onkeydown
+            /// onkeypress
             onkeypress
+            /// onkeyup
             onkeyup
         ];
+
         FocusEventInner(FocusEvent): [
+            /// onfocus
             onfocus
+            /// onblur
             onblur
         ];
+
+
         FormEventInner(FormEvent): [
+            /// onchange
             onchange
+            /// oninput
             oninput
+            /// oninvalid
             oninvalid
+            /// onreset
             onreset
+            /// onsubmit
             onsubmit
         ];
 
@@ -237,63 +251,202 @@ pub mod on {
         /// ```
         ///
         /// ## Event Handlers
-        /// - click
-        /// - contextmenu
-        /// - doubleclick
-        /// - drag
-        /// - dragend
-        /// - dragenter
-        /// - dragexit
-        /// - dragleave
-        /// - dragover
-        /// - dragstart
-        /// - drop
-        /// - mousedown
-        /// - mouseenter
-        /// - mouseleave
-        /// - mousemove
-        /// - mouseout
-        /// - mouseover
-        /// - mouseup
+        /// - [`onclick`]
+        /// - [`oncontextmenu`]
+        /// - [`ondoubleclick`]
+        /// - [`ondrag`]
+        /// - [`ondragend`]
+        /// - [`ondragenter`]
+        /// - [`ondragexit`]
+        /// - [`ondragleave`]
+        /// - [`ondragover`]
+        /// - [`ondragstart`]
+        /// - [`ondrop`]
+        /// - [`onmousedown`]
+        /// - [`onmouseenter`]
+        /// - [`onmouseleave`]
+        /// - [`onmousemove`]
+        /// - [`onmouseout`]
+        /// - [`onmouseover`]
+        /// - [`onmouseup`]
         MouseEventInner(MouseEvent): [
-            /// Onclick!
+            /// Execute a callback when a button is clicked.
+            ///
+            /// ## Description
+            ///
+            /// An element receives a click event when a pointing device button (such as a mouse's primary mouse button)
+            /// is both pressed and released while the pointer is located inside the element.
+            ///
+            /// - Bubbles: Yes
+            /// - Cancelable: Yes
+            /// - Interface: [`MouseEvent`]
+            ///
+            /// If the button is pressed on one element and the pointer is moved outside the element before the button
+            /// is released, the event is fired on the most specific ancestor element that contained both elements.
+            /// `click` fires after both the `mousedown` and `mouseup` events have fired, in that order.
+            ///
+            /// ## Example
+            /// ```
+            /// rsx!( button { "click me", onclick: move |_| log::info!("Clicked!`") } )
+            /// ```
+            ///
+            /// ## Reference
+            /// - https://www.w3schools.com/tags/ev_onclick.asp
+            /// - https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event
+            ///
             onclick
+            /// oncontextmenu
             oncontextmenu
+            /// ondoubleclick
             ondoubleclick
+            /// ondrag
             ondrag
+            /// ondragend
             ondragend
+            /// ondragenter
             ondragenter
+            /// ondragexit
             ondragexit
+            /// ondragleave
             ondragleave
+            /// ondragover
             ondragover
+            /// ondragstart
             ondragstart
+            /// ondrop
             ondrop
+            /// onmousedown
             onmousedown
+            /// onmouseenter
             onmouseenter
+            /// onmouseleave
             onmouseleave
+            /// onmousemove
             onmousemove
+            /// onmouseout
             onmouseout
+            /// onmouseover
             onmouseover
+            /// onmouseup
             onmouseup
         ];
 
         PointerEventInner(PointerEvent): [
-            pointerdown pointermove pointerup pointercancel gotpointercapture
-            lostpointercapture pointerenter pointerleave pointerover pointerout
+            /// pointerdown
+            onpointerdown
+            /// pointermove
+            onpointermove
+            /// pointerup
+            onpointerup
+            /// pointercancel
+            onpointercancel
+            /// gotpointercapture
+            ongotpointercapture
+            /// lostpointercapture
+            onlostpointercapture
+            /// pointerenter
+            onpointerenter
+            /// pointerleave
+            onpointerleave
+            /// pointerover
+            onpointerover
+            /// pointerout
+            onpointerout
+        ];
+
+        SelectionEventInner(SelectionEvent): [
+            /// onselect
+            onselect
+        ];
+
+        TouchEventInner(TouchEvent): [
+            /// ontouchcancel
+            ontouchcancel
+            /// ontouchend
+            ontouchend
+            /// ontouchmove
+            ontouchmove
+            /// ontouchstart
+            ontouchstart
+        ];
+
+        UIEventInner(UIEvent): [
+            ///
+            scroll
+        ];
+
+        WheelEventInner(WheelEvent): [
+            ///
+            wheel
         ];
-        SelectionEventInner(SelectionEvent): [select];
-        TouchEventInner(TouchEvent): [touchcancel touchend touchmove touchstart];
-        UIEventInner(UIEvent): [scroll];
-        WheelEventInner(WheelEvent): [wheel];
+
         MediaEventInner(MediaEvent): [
-            abort canplay canplaythrough durationchange emptied encrypted
-            ended error loadeddata loadedmetadata loadstart pause play
-            playing progress ratechange seeked seeking stalled suspend
-            timeupdate volumechange waiting
+            ///abort
+            onabort
+            ///canplay
+            oncanplay
+            ///canplaythrough
+            oncanplaythrough
+            ///durationchange
+            ondurationchange
+            ///emptied
+            onemptied
+            ///encrypted
+            onencrypted
+            ///ended
+            onended
+            ///error
+            onerror
+            ///loadeddata
+            onloadeddata
+            ///loadedmetadata
+            onloadedmetadata
+            ///loadstart
+            onloadstart
+            ///pause
+            onpause
+            ///play
+            onplay
+            ///playing
+            onplaying
+            ///progress
+            onprogress
+            ///ratechange
+            onratechange
+            ///seeked
+            onseeked
+            ///seeking
+            onseeking
+            ///stalled
+            onstalled
+            ///suspend
+            onsuspend
+            ///timeupdate
+            ontimeupdate
+            ///volumechange
+            onvolumechange
+            ///waiting
+            onwaiting
+        ];
+
+        AnimationEventInner(AnimationEvent): [
+            /// onanimationstart
+            onanimationstart
+            /// onanimationend
+            onanimationend
+            /// onanimationiteration
+            onanimationiteration
+        ];
+
+        TransitionEventInner(TransitionEvent): [
+            ///
+            ontransitionend
+        ];
+
+        ToggleEventInner(ToggleEvent): [
+            ///
+            ontoggle
         ];
-        AnimationEventInner(AnimationEvent): [animationstart animationend animationiteration];
-        TransitionEventInner(TransitionEvent): [transitionend];
-        ToggleEventInner(ToggleEvent): [toggle];
     }
 
     pub trait GenericEventInner {
@@ -404,7 +557,6 @@ pub mod on {
         fn alt_key(&self) -> bool;
         fn button(&self) -> i16;
         fn buttons(&self) -> u16;
-
         /// Get the X coordinate of the mouse relative to the window
         fn client_x(&self) -> i32;
         fn client_y(&self) -> i32;
@@ -709,26 +861,3 @@ pub mod on {
         }
     }
 }
-
-// mod tests {
-
-//     use std::rc::Rc;
-
-//     use crate as dioxus;
-//     use crate::events::on::MouseEvent;
-//     use crate::prelude::*;
-
-//     fn autocomplete() {
-//         // let v = move |evt| {
-//         //     let r = evt.alt_key();
-//         // };
-
-//         let g = rsx! {
-//             button {
-//                 onclick: move |evt| {
-//                     let r = evt.alt_key();
-//                 }
-//             }
-//         };
-//     }
-// }

+ 1 - 2
packages/core/src/lib.rs

@@ -16,7 +16,7 @@ pub mod component;
 pub mod styles;
 pub mod util; // Logic for extending FC
 
-pub mod debug_renderer;
+// pub mod debug_renderer;
 pub mod diff;
 
 pub mod error; // Error type we expose to the renderers
@@ -62,7 +62,6 @@ pub mod prelude {
 
     pub use crate::nodebuilder::LazyNodes;
 
-    pub use crate::nodebuilder::ChildrenList;
     pub use crate::nodebuilder::{DioxusElement, NodeFactory};
     // pub use nodes::iterables::IterableNodes;
     /// This type alias is an internal way of abstracting over the static functions that represent components.

+ 50 - 85
packages/core/src/nodebuilder.rs

@@ -6,6 +6,7 @@ use std::{
     cell::{Cell, RefCell},
     fmt::Arguments,
     intrinsics::transmute,
+    marker::PhantomData,
     u128,
 };
 
@@ -511,8 +512,9 @@ where
     pub fn iter_child(mut self, nodes: impl IntoIterator<Item = impl IntoVNode<'a>>) -> Self {
         let len_before = self.children.len();
         for item in nodes {
-            let child = item.into_vnode(&self.cx);
-            self.children.push(child);
+            todo!()
+            // let child = item.into_vnode(&self.cx);
+            // self.children.push(child);
         }
         if cfg!(debug_assertions) {
             if self.children.len() > len_before + 1 {
@@ -541,52 +543,53 @@ impl<'a> IntoIterator for VNode<'a> {
     }
 }
 impl<'a> IntoVNode<'a> for VNode<'a> {
-    fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
+    fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
         self
     }
 }
 
 impl<'a> IntoVNode<'a> for &VNode<'a> {
-    fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
+    fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a>
+// where
+    //     'a: 'c,
+    {
+        todo!()
         // cloning is cheap since vnodes are just references into bump arenas
-        self.clone()
+        // self.clone()
     }
 }
 
 pub trait IntoVNode<'a> {
-    fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a>;
+    fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a>;
 }
 
-pub trait VNodeBuilder<'a, G>: IntoIterator<Item = G>
-where
-    G: IntoVNode<'a>,
-{
-}
+// pub trait VNodeBuilder<'a, G>: IntoIterator<Item = G>
+// where
+//     G: IntoVNode<'a>,
+// {
+// }
 
-impl<'a, F> VNodeBuilder<'a, LazyNodes<'a, F>> for LazyNodes<'a, F> where
-    F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a
-{
-}
+// impl<'a, F> VNodeBuilder<'a, LazyNodes<F>> for LazyNodes<F> where F: FnOnce(NodeFactory) -> VNode {}
 
 // Wrap the the node-builder closure in a concrete type.
 // ---
 // This is a bit of a hack to implement the IntoVNode trait for closure types.
 pub struct LazyNodes<'a, G>
 where
-    G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
+    G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
 {
     inner: G,
-    _p: std::marker::PhantomData<&'a ()>,
+    _p: PhantomData<&'a ()>,
 }
 
 impl<'a, G> LazyNodes<'a, G>
 where
-    G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
+    G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
 {
     pub fn new(f: G) -> Self {
         Self {
             inner: f,
-            _p: std::default::Default::default(),
+            _p: PhantomData {},
         }
     }
 }
@@ -598,9 +601,9 @@ where
 //  rsx! { {nodes } }
 impl<'a, G> IntoVNode<'a> for LazyNodes<'a, G>
 where
-    G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
+    G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
 {
-    fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
+    fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
         (self.inner)(cx)
     }
 }
@@ -608,7 +611,7 @@ where
 // Required because anything that enters brackets in the rsx! macro needs to implement IntoIterator
 impl<'a, G> IntoIterator for LazyNodes<'a, G>
 where
-    G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
+    G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
 {
     type Item = Self;
     type IntoIter = std::iter::Once<Self::Item>;
@@ -617,23 +620,23 @@ where
     }
 }
 
-impl<'a> IntoVNode<'a> for () {
-    fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
-        todo!();
-        VNode::Suspended {
-            real: Cell::new(RealDomNode::empty()),
-        }
-    }
-}
-
-impl<'a> IntoVNode<'a> for Option<()> {
-    fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
-        todo!();
-        VNode::Suspended {
-            real: Cell::new(RealDomNode::empty()),
-        }
-    }
-}
+// impl IntoVNode<'_> for () {
+//     fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> {
+//         todo!();
+//         VNode::Suspended {
+//             real: Cell::new(RealDomNode::empty()),
+//         }
+//     }
+// }
+
+// impl IntoVNode<'_> for Option<()> {
+//     fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> {
+//         todo!();
+//         VNode::Suspended {
+//             real: Cell::new(RealDomNode::empty()),
+//         }
+//     }
+// }
 
 /// Construct a text VNode.
 ///
@@ -702,7 +705,7 @@ pub fn attr<'a>(name: &'static str, value: &'a str) -> Attribute<'a> {
 }
 
 pub fn virtual_child<'a, T: Properties + 'a>(
-    cx: &NodeFactory<'a>,
+    cx: NodeFactory<'a>,
     f: FC<T>,
     props: T,
     key: Option<&'a str>, // key: NodeKey<'a>,
@@ -713,54 +716,28 @@ pub fn virtual_child<'a, T: Properties + 'a>(
     // todo!()
     VNode::Component(
         cx.bump()
-            .alloc(crate::nodes::VComponent::new(cx, f, props, key, children)),
+            .alloc(crate::nodes::VComponent::new(&cx, f, props, key, children)),
         // cx.bump()
         //     .alloc(crate::nodes::VComponent::new(f, props, key)),
     )
 }
 
 pub fn vfragment<'a>(
-    cx: &NodeFactory<'a>,
+    cx: NodeFactory<'a>,
     key: Option<&'a str>, // key: NodeKey<'a>,
     children: &'a [VNode<'a>],
 ) -> VNode<'a> {
     VNode::Fragment(cx.bump().alloc(VFragment::new(key, children)))
 }
 
-pub struct ChildrenList<'a, 'b> {
-    cx: &'b NodeFactory<'a>,
-    children: bumpalo::collections::Vec<'a, VNode<'a>>,
-}
-
-impl<'a, 'b> ChildrenList<'a, 'b> {
-    pub fn new(cx: &'b NodeFactory<'a>) -> Self {
-        Self {
-            cx,
-            children: bumpalo::collections::Vec::new_in(cx.bump()),
-        }
-    }
-
-    pub fn add_child(mut self, nodes: impl IntoIterator<Item = impl IntoVNode<'a>>) -> Self {
-        for item in nodes {
-            let child = item.into_vnode(&self.cx);
-            self.children.push(child);
-        }
-        self
-    }
-
-    pub fn finish(self) -> &'a [VNode<'a>] {
-        self.children.into_bump_slice()
-    }
-}
-
 /// This struct provides an ergonomic API to quickly build VNodes.
 ///
 /// NodeFactory is used to build VNodes in the component's memory space.
 /// This struct adds metadata to the final VNode about listeners, attributes, and children
-#[derive(Clone)]
+#[derive(Copy, Clone)]
 pub struct NodeFactory<'a> {
     pub scope_ref: &'a Scope,
-    pub listener_id: Cell<usize>,
+    pub listener_id: &'a Cell<usize>,
 }
 
 impl<'a> NodeFactory<'a> {
@@ -791,7 +768,7 @@ impl<'a> NodeFactory<'a> {
     pub fn attr(
         &self,
         name: &'static str,
-        val: Arguments<'a>,
+        val: Arguments,
         namespace: Option<&'static str>,
     ) -> Attribute<'a> {
         let value = raw_text(self.bump(), val);
@@ -802,18 +779,6 @@ impl<'a> NodeFactory<'a> {
         }
     }
 
-    pub fn child_list(&self) -> ChildrenList {
-        ChildrenList::new(&self)
-    }
-
-    pub fn fragment_builder<'b>(
-        &'b self,
-        key: Option<&'a str>,
-        builder: impl FnOnce(ChildrenList<'a, 'b>) -> &'a [VNode<'a>],
-    ) -> VNode<'a> {
-        self.fragment(builder(ChildrenList::new(&self)), key)
-    }
-
     pub fn fragment(&self, children: &'a [VNode<'a>], key: Option<&'a str>) -> VNode<'a> {
         VNode::Fragment(self.bump().alloc(VFragment {
             children,
@@ -822,12 +787,12 @@ impl<'a> NodeFactory<'a> {
     }
 
     pub fn fragment_from_iter(
-        &self,
+        self,
         node_iter: impl IntoIterator<Item = impl IntoVNode<'a>>,
     ) -> VNode<'a> {
         let mut nodes = bumpalo::collections::Vec::new_in(self.bump());
         for node in node_iter.into_iter() {
-            nodes.push(node.into_vnode(&self));
+            nodes.push(node.into_vnode(self));
         }
         VNode::Fragment(
             self.bump()

+ 19 - 22
packages/core/src/virtual_dom.rs

@@ -393,6 +393,8 @@ pub struct Scope {
     // could also use ourborous
     hooks: RefCell<Vec<Hook>>,
 
+    pub(crate) listener_idx: Cell<usize>,
+
     // Unsafety:
     // - is self-refenrential and therefore needs to point into the bump
     // Stores references into the listeners attached to the vnodes
@@ -463,6 +465,7 @@ impl Scope {
             height,
             event_channel,
             arena_link,
+            listener_idx: Default::default(),
             frames: ActiveFrame::new(),
             hooks: Default::default(),
             shared_contexts: Default::default(),
@@ -506,13 +509,9 @@ impl Scope {
 
         // Remove all the outdated listeners
         self.listeners.borrow_mut().clear();
-        // self.listeners
-        //     .try_borrow_mut()
-        //     .ok()
-        //     .ok_or(Error::FatalInternal("Borrowing listener failed"))?
-        //     .drain(..);
 
         self.hookidx.set(0);
+        self.listener_idx.set(0);
 
         let caller = self
             .caller
@@ -522,12 +521,8 @@ impl Scope {
         // Cast the caller ptr from static to one with our own reference
         let c2: &OpaqueComponent = caller.as_ref();
         let c3: &OpaqueComponent = unsafe { std::mem::transmute(c2) };
-        // let c2: &OpaqueComponent<'static> = caller.as_ref();
-        // let c3: &OpaqueComponent<'sel> = unsafe { std::mem::transmute(c2) };
-
-        let unsafe_head = unsafe { self.own_vnodes(c3) };
 
-        self.frames.cur_frame_mut().head_node = unsafe_head;
+        self.frames.cur_frame_mut().head_node = unsafe { self.own_vnodes(c3) };
 
         Ok(())
     }
@@ -685,13 +680,15 @@ pub trait Scoped<'src>: Sized {
     ///     cx.render(lazy_tree)
     /// }
     ///```
-    fn render<'a, F: for<'b> FnOnce(&'b NodeFactory<'src>) -> VNode<'src> + 'src + 'a>(
+    fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
         self,
         lazy_nodes: LazyNodes<'src, F>,
     ) -> VNode<'src> {
-        lazy_nodes.into_vnode(&NodeFactory {
-            scope_ref: self.get_scope(),
-            listener_id: 0.into(),
+        let scope_ref = self.get_scope();
+        let listener_id = &scope_ref.listener_idx;
+        lazy_nodes.into_vnode(NodeFactory {
+            scope_ref,
+            listener_id,
         })
     }
 
@@ -890,14 +887,14 @@ Any function prefixed with "use" should not be called conditionally.
 #[derive(Clone)]
 pub struct SuspendedContext {}
 
-impl SuspendedContext {
-    pub fn render<'a, 'src, F: for<'b> FnOnce(&'b NodeFactory<'src>) -> VNode<'src> + 'src + 'a>(
-        self,
-        lazy_nodes: LazyNodes<'src, F>,
-    ) -> VNode<'src> {
-        todo!()
-    }
-}
+// impl SuspendedContext {
+//     pub fn render<'a, F: for<'b, 'src> FnOnce(&'b NodeFactory<'src>) -> VNode<'src>>(
+//         &self,
+//         lazy_nodes: LazyNodes<F>,
+//     ) -> VNode {
+//         todo!()
+//     }
+// }
 
 // ==================================================================================
 //                Supporting structs for the above abstractions

+ 13 - 1
packages/html-namespace/src/lib.rs

@@ -26,7 +26,18 @@ macro_rules! builder_constructors {
     ( $(
         $(#[$attr:meta])*
         $name:ident <> $namespace:tt;
-    )* ) => {};
+    )* ) => {
+        $(
+            #[allow(non_camel_case_types)]
+            $(#[$attr])*
+            pub struct $name;
+
+            impl DioxusElement for $name {
+                const TAG_NAME: &'static str = stringify!($name);
+                const NAME_SPACE: Option<&'static str> = Some(stringify!($namespace));
+            }
+        )*
+    };
 }
 
 // Organized in the same order as
@@ -554,6 +565,7 @@ builder_constructors! {
     /// [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot)
     /// element.
     slot;
+
     /// Build a
     /// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
     /// element.

+ 1 - 0
packages/web/Cargo.toml

@@ -9,6 +9,7 @@ license = "MIT/Apache-2.0"
 
 [dependencies]
 dioxus-core = { path="../core", version="0.1.2" }
+dioxus-html-namespace = { path="../html-namespace" }
 js-sys = "0.3"
 wasm-bindgen = { version="0.2.71", features=["enable-interning"] }
 lazy_static = "1.4.0"

+ 1 - 0
packages/web/examples/basic.rs

@@ -3,6 +3,7 @@
 use dioxus::events::on::MouseEvent;
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::*;
 
 fn main() {

+ 3 - 2
packages/web/examples/calculator.rs

@@ -9,6 +9,7 @@
 use dioxus::events::on::*;
 use dioxus::prelude::*;
 use dioxus_core as dioxus;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 const STYLE: &str = include_str!("../../../examples/assets/calculator.css");
@@ -159,7 +160,7 @@ struct CalculatorKeyProps<'a> {
     onclick: &'a dyn Fn(MouseEvent),
 }
 
-fn CalculatorKey<'a>(cx: Context<'a, CalculatorKeyProps>) -> VNode<'a> {
+fn CalculatorKey<'a, 'r>(cx: Context<'a, CalculatorKeyProps<'r>>) -> VNode<'a> {
     cx.render(rsx! {
         button {
             class: "calculator-key {cx.name}"
@@ -181,7 +182,7 @@ fn CalculatorDisplay<'a>(cx: Context<'a, CalculatorDisplayProps>) -> VNode<'a> {
     // TODO: make it autoscaling with css
     cx.render(rsx! {
         div { class: "calculator-display"
-            div { class: "auto-scaling-text", "{display_value}" }
+            div { class: "auto-scaling-text", "{formatted}" }
         }
     })
 }

+ 1 - 0
packages/web/examples/children.rs

@@ -1,6 +1,7 @@
 //! Basic example that renders a simple VNode to the browser.
 
 use dioxus_core::prelude::*;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::*;
 
 fn main() {

+ 1 - 0
packages/web/examples/context.rs

@@ -14,6 +14,7 @@
 use dioxus_core::prelude::*;
 use dioxus_core as dioxus;
 use dioxus_web::WebsysRenderer;
+use dioxus_html_namespace as dioxus_elements;
 
 fn main() {
     wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));

+ 3 - 2
packages/web/examples/deep.rs

@@ -1,13 +1,14 @@
 use std::rc::Rc;
 
+use dioxus::prelude::*;
 use dioxus_core as dioxus;
-use dioxus_web::{dioxus::prelude::*, WebsysRenderer};
+use dioxus_html_namespace as dioxus_elements;
 
 fn main() {
     wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
     console_error_panic_hook::set_once();
 
-    wasm_bindgen_futures::spawn_local(WebsysRenderer::start(CustomA))
+    wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(CustomA))
 }
 
 fn CustomA(cx: Context<()>) -> VNode {

+ 3 - 1
packages/web/examples/demoday.rs

@@ -1,4 +1,6 @@
 use dioxus_core as dioxus;
+use dioxus_html_namespace as dioxus_elements;
+use dioxus_html_namespace::*;
 use dioxus_web::{dioxus::prelude::*, WebsysRenderer};
 
 fn main() {
@@ -9,7 +11,7 @@ fn main() {
 
 fn App(cx: Context<()>) -> VNode {
     cx.render(rsx! {
-        main { class: "dark:bg-gray-800 bg-white relative h-screen"
+        div { class: "dark:bg-gray-800 bg-white relative h-screen"
             NavBar {}
             {(0..10).map(|f| rsx!(Landing { key: "{f}" }))}
         }

+ 1 - 0
packages/web/examples/derive.rs

@@ -1,5 +1,6 @@
 use dioxus::{events::on::MouseEvent, prelude::*};
 use dioxus_core as dioxus;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 fn main() {

+ 1 - 0
packages/web/examples/fragment.rs

@@ -1,6 +1,7 @@
 //! Basic example that renders a simple VNode to the browser.
 
 use dioxus_core::prelude::*;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::*;
 
 fn main() {

+ 9 - 4
packages/web/examples/framework_benchmark.rs

@@ -12,6 +12,9 @@ use dioxus::events::on::MouseEvent;
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
 use dioxus_web::WebsysRenderer;
+use dioxus_html_namespace as dioxus_elements;
+
+
 
 fn main() {
     wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
@@ -21,7 +24,8 @@ fn main() {
 }
 
 // We use a special immutable hashmap to make hashmap operations efficient
-type RowList = im_rc::HashMap<usize, Rc<str>, nohash_hasher::BuildNoHashHasher<usize>>;
+type RowList = im_rc::HashMap<usize, Rc<str>, FxBuildHasher>;
+// type RowList = im_rc::HashMap<usize, Rc<str>, nohash_hasher::BuildNoHashHasher<usize>>;
 
 static App: FC<()> = |cx| {
     let (items, set_items) = use_state_classic(&cx, || RowList::default());
@@ -90,15 +94,15 @@ static App: FC<()> = |cx| {
 };
 
 #[derive(Props)]
-struct ActionButtonProps<F: Fn(Rc<dyn MouseEvent>)> {
+struct ActionButtonProps<F: Fn(MouseEvent)> {
     name: &'static str,
     id: &'static str,
     action: F,
 }
-fn ActionButton<F: Fn(Rc<dyn MouseEvent>)>(cx: Context<ActionButtonProps<F>>) -> VNode {
+fn ActionButton<F: Fn(MouseEvent)>(cx: Context<ActionButtonProps<F>>) -> VNode {
     cx.render(rsx! {
         div { class: "col-sm-6 smallpad"
-            button {class:"btn btn-primary btn-block", type: "button", id: "{cx.id}",  onclick: {&cx.action},
+            button {class:"btn btn-primary btn-block", r#type: "button", id: "{cx.id}",  onclick: {&cx.action},
                 "{cx.name}"
             }
         }
@@ -128,6 +132,7 @@ fn Row<'a>(cx: Context<'a, RowProps>) -> VNode {
     })
 }
 
+use fxhash::{FxBuildHasher, FxHasher32};
 use rand::prelude::*;
 fn create_new_row_label(rng: &mut SmallRng) -> Rc<str> {
     let mut label = String::new();

+ 1 - 0
packages/web/examples/hello.rs

@@ -1,5 +1,6 @@
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 fn main() {

+ 1 - 0
packages/web/examples/helloworld.rs

@@ -1,4 +1,5 @@
 use dioxus_core as dioxus;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::prelude::*;
 
 fn main() {

+ 2 - 0
packages/web/examples/infer.rs

@@ -1,6 +1,8 @@
 use dioxus_core as dioxus;
 use dioxus_core::{events::on::MouseEvent, prelude::*};
 use dioxus_web::WebsysRenderer;
+use dioxus_html_namespace as dioxus_elements;
+
 
 fn main() {
     // Setup logging

+ 4 - 2
packages/web/examples/input.rs

@@ -1,6 +1,8 @@
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
 use dioxus_web::WebsysRenderer;
+use dioxus_html_namespace as dioxus_elements;
+
 
 fn main() {
     // wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
@@ -24,7 +26,7 @@ static App: FC<()> = |cx| {
                         placeholder: "Username"
                         class: "shadow appearance-none rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                         id: "username" 
-                        type: "text"
+                        r#type: "text"
                         value: "{val}"
                         oninput: move |evet| set_val(evet.value())
                     }
@@ -56,7 +58,7 @@ static UserInput: FC<()> = |cx| {
             input { class: "shadow appearance-none rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                 placeholder: "Username"
                 id: "username"
-                type: "text"
+                r#type: "text"
                 oninput: move |evet| set_val(evet.value())
             }
             p { "Val is: {val}" }

+ 1 - 0
packages/web/examples/jackjillrsx.rs

@@ -1,5 +1,6 @@
 use dioxus::prelude::*;
 use dioxus_core as dioxus;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 fn main() {

+ 2 - 0
packages/web/examples/landingpage.rs

@@ -3,7 +3,9 @@
 use std::rc::Rc;
 
 use dioxus_core::prelude::*;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::*;
+
 fn main() {
     // Setup logging
     // wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));

+ 2 - 2
packages/web/examples/landingpage2.rs

@@ -1,9 +1,9 @@
 //! Basic example that renders a simple VNode to the browser.
 
-use std::{future::Future, pin::Pin, rc::Rc};
-
 use dioxus_core::prelude::*;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::*;
+
 fn main() {
     // Setup logging and panic handling
     wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));

+ 2 - 1
packages/web/examples/list.rs

@@ -1,5 +1,6 @@
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 use std::collections::BTreeMap;
 
@@ -72,7 +73,7 @@ static App: FC<()> = |cx| {
                                 "{todo.contents}"
                                 input {
                                     class: "toggle"
-                                    type: "checkbox"
+                                    r#type: "checkbox"
                                     "{todo.checked}"
                                 }
                             }

+ 1 - 0
packages/web/examples/listy.rs

@@ -1,5 +1,6 @@
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 fn main() {

+ 1 - 0
packages/web/examples/many.rs

@@ -1,5 +1,6 @@
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 fn main() {

+ 1 - 0
packages/web/examples/model.rs

@@ -18,6 +18,7 @@
 use dioxus::events::on::*;
 use dioxus::prelude::*;
 use dioxus_core as dioxus;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 const STYLE: &str = include_str!("../../../examples/assets/calculator.css");

+ 3 - 1
packages/web/examples/rsxt.rs

@@ -4,6 +4,8 @@ use std::rc::Rc;
 use dioxus::{events::on::MouseEvent, prelude::*};
 use dioxus_core as dioxus;
 use dioxus_web::WebsysRenderer;
+use dioxus_html_namespace as dioxus_elements;
+
 
 fn main() {
     wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));
@@ -50,7 +52,7 @@ static Example: FC<ExampleProps> = |cx| {
 };
 
 #[derive(Props)]
-struct ButtonProps<'src, F: Fn(Rc<dyn MouseEvent>)> {
+struct ButtonProps<'src, F: Fn(MouseEvent)> {
     name: &'src str,
     handler: F,
 }

+ 2 - 1
packages/web/examples/todomvc-nodeps.rs

@@ -2,6 +2,7 @@ use std::{collections::HashMap, rc::Rc};
 
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 static APP_STYLE: &'static str = include_str!("./todomvc/style.css");
@@ -112,7 +113,7 @@ pub fn TodoEntry(cx: Context<TodoEntryProps>) -> VNode {
             "{todo.id}"
             input {
                 class: "toggle"
-                type: "checkbox"
+                r#type: "checkbox"
                 "{todo.checked}"
             }
            {is_editing.then(|| rsx!{

+ 1 - 0
packages/web/examples/todomvc/main.rs

@@ -1,4 +1,5 @@
 use dioxus_core as dioxus;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::{prelude::*, WebsysRenderer};
 
 // mod filtertoggles;

+ 2 - 1
packages/web/examples/todomvc_simple.rs

@@ -2,6 +2,7 @@ use std::{collections::HashMap, rc::Rc};
 
 use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
+use dioxus_html_namespace as dioxus_elements;
 use dioxus_web::WebsysRenderer;
 
 static APP_STYLE: &'static str = include_str!("./todomvc/style.css");
@@ -115,7 +116,7 @@ pub fn TodoEntry(cx: Context<TodoEntryProps>) -> VNode {
             "{todo.id}"
             input {
                 class: "toggle"
-                type: "checkbox"
+                r#type: "checkbox"
                 "{todo.checked}"
             }
            {is_editing.then(|| rsx!{

+ 1 - 0
src/lib.rs

@@ -169,6 +169,7 @@ pub mod prelude {
     //! A glob import that includes helper types like FC, rsx!, html!, and required traits
     pub use dioxus_core::prelude::*;
     pub use dioxus_core_macro::fc;
+    pub use dioxus_html_namespace as dioxus_elements;
 }
 // pub mod builder {
 //     // pub use dioxus_core::builder::*;