Kaynağa Gözat

docs: move around examples

Jonathan Kelley 4 yıl önce
ebeveyn
işleme
70cd46d
45 değiştirilmiş dosya ile 3743 ekleme ve 2292 silme
  1. 1 0
      .vscode/spellright.dict
  2. 13 12
      Cargo.toml
  3. 5 4
      README.md
  4. 4 13
      examples/app.rs
  5. 0 94
      examples/example_app.rs
  6. 0 39
      examples/external_updates.rs
  7. 0 0
      examples/listener.rs
  8. 0 65
      examples/live.rs
  9. 0 42
      examples/router.rs
  10. 60 0
      examples/rsx_usage.rs
  11. 0 45
      examples/website.rs
  12. 3 3
      examples/webview.rs
  13. 2 2
      notes/CHANGELOG.md
  14. 5 5
      notes/Parity.md
  15. 36 39
      packages/atoms/README.md
  16. 10 0
      packages/atoms/examples/structured_app.rs
  17. 58 0
      packages/atoms/notes/async.md
  18. 7 10
      packages/core/examples/alternative.rs
  19. 34 49
      packages/core/examples/borrowed.rs
  20. 0 29
      packages/core/examples/component_child.rs
  21. 0 72
      packages/core/examples/fc.rs
  22. 0 59
      packages/core/examples/macro_testing.rs
  23. 0 44
      packages/core/examples/nested.rs
  24. 0 16
      packages/core/examples/props.rs
  25. 0 47
      packages/core/examples/rsx_usage.rs
  26. 0 18
      packages/core/examples/showcase.rs
  27. 0 41
      packages/core/examples/step.rs
  28. 0 8
      packages/core/examples/template.rs
  29. 0 16
      packages/core/examples/text.rs
  30. 0 28
      packages/core/examples/textstream.rs
  31. 152 171
      packages/core/src/events.rs
  32. 0 68
      packages/hooks/src/hooks/mod.rs
  33. 0 469
      packages/hooks/src/hooks/use_context.rs
  34. 0 320
      packages/hooks/src/hooks/use_effect.rs
  35. 0 203
      packages/hooks/src/hooks/use_reducer.rs
  36. 0 98
      packages/hooks/src/hooks/use_ref.rs
  37. 0 142
      packages/hooks/src/hooks/use_state.rs
  38. 11 0
      packages/html-namespace/Cargo.toml
  39. 22 0
      packages/html-namespace/README.md
  40. 2598 0
      packages/html-namespace/examples/attrlist.html
  41. 42 0
      packages/html-namespace/examples/namespace.rs
  42. 627 0
      packages/html-namespace/src/lib.rs
  43. 21 0
      packages/web/examples/events.rs
  44. 22 19
      packages/web/src/interpreter.rs
  45. 10 2
      src/lib.rs

+ 1 - 0
.vscode/spellright.dict

@@ -49,3 +49,4 @@ lodash
 crates.io
 utilties
 js
+Dyon

+ 13 - 12
Cargo.toml

@@ -10,7 +10,7 @@ description = "Core functionality for Dioxus - a concurrent renderer-agnostic Vi
 [dependencies]
 dioxus-core = { path="./packages/core", version="0.1.0" }
 dioxus-core-macro = { path="./packages/core-macro", version="0.1.0" }
-dioxus-hooks = { path="./packages/hooks", version="0.0.0" }
+# dioxus-hooks = { path="./packages/hooks", version="0.0.0" }
 
 
 [features]
@@ -30,20 +30,20 @@ split-debuginfo = "unpacked"
 
 [dev-dependencies]
 # For the tide ssr examples
-async-std = { version="1.9.0", features=["attributes"] }
-tide = { version="0.16.0" }
+# async-std = { version="1.9.0", features=["attributes"] }
+# tide = { version="0.16.0" }
 
 # For the livewview example
-tide-websockets = "0.4.0"
-serde_millis = "0.1"
-serde_json = "1"
-serde = { version="1", features=['derive'] }
+# tide-websockets = "0.4.0"
+# serde_millis = "0.1"
+# serde_json = "1"
+# serde = { version="1", features=['derive'] }
 
 # For the doc generator
-pulldown-cmark = { version="0.8.0", default-features=false }
+# pulldown-cmark = { version="0.8.0", default-features=false }
 
-dioxus-webview = { path="./packages/webview", version="0.0.0" }
-dioxus-hooks = { path="./packages/hooks", version="0.0.0" }
+# dioxus-webview = { path="./packages/webview", version="0.0.0" }
+# dioxus-hooks = { path="./packages/hooks", version="0.0.0" }
 rand = "0.8.4"
 
 
@@ -51,10 +51,11 @@ rand = "0.8.4"
 members = [
     "packages/core-macro",
     "packages/core",
-    "packages/web",
+    "packages/html-namespace",
+    # "packages/web",
+    # "packages/atoms",
     # "packages/ssr",
     # "packages/docsite",
-    # "packages/atoms",
     # "packages/router",
     # "packages/inputs",
 ]

+ 5 - 4
README.md

@@ -8,10 +8,10 @@
 Dioxus is a portable, performant, and ergonomic framework for building cross-platform user experiences in Rust.
 
 ```rust
-fn Example(ctx: Context<()>) -> VNode {
-    let (selection, set_selection) = use_state(&ctx, || "..?");
+fn Example(cx: Context<()>) -> VNode {
+    let (selection, set_selection) = use_state(&cx, || "..?");
 
-    ctx.render(rsx! {
+    cx.render(rsx! {
         h1 { "Hello, {selection}" }
         button { "?", onclick: move |_| set_selection("world!")}
         button { "?", onclick: move |_| set_selection("Dioxus 🎉")}
@@ -19,7 +19,7 @@ fn Example(ctx: Context<()>) -> VNode {
 };
 ```
 
-Dioxus can be used to deliver webapps, desktop apps, static pages, liveview apps, Android apps, iOS Apps, and more. At its core, Dioxus is entirely renderer agnostic and has great documentation for creating new renderers for any platform.
+Dioxus can be used to deliver webapps, desktop apps, static pages, liveview apps, eventually mobile apps (WIP), and more. At its core, Dioxus is entirely renderer agnostic and has great documentation for creating new renderers for any platform.
 
 If you know React, then you already know Dioxus.
 
@@ -29,6 +29,7 @@ If you know React, then you already know Dioxus.
 - Minimal boilerplate
 - Familiar design and semantics
 - Simple build, test, and deploy
+- Compile-time correct templating
 - Support for html! and rsx! templating
 - SSR, WASM, desktop, and mobile support
 - Powerful and simple integrated state management

+ 4 - 13
packages/core/examples/app.rs → examples/app.rs

@@ -1,14 +1,14 @@
+#![allow(unused)]
 /*
 This example shows how to encapsulate sate in dioxus components with the reducer pattern.
 This pattern is very useful when a single component can handle many types of input that can
 be represented by an enum. This particular pattern is very powerful in rust where ADTs can simplify
 much of the traditional reducer boilerplate.
 */
-#![allow(unused)]
-use std::future::Future;
 
-use dioxus::hooks::use_reducer;
-use dioxus_ssr::prelude::*;
+fn main() {}
+use dioxus::prelude::*;
+use std::future::Future;
 
 enum Actions {
     Pause,
@@ -88,8 +88,6 @@ enum KindaState {
 static EnumReducer: FC<()> = |ctx| {
     let (state, reduce) = use_reducer(&ctx, || KindaState::Ready, |cur, new| *cur = new);
 
-    let contents = helper(&ctx);
-
     let status = match state {
         KindaState::Ready => "Ready",
         KindaState::Complete => "Complete",
@@ -99,7 +97,6 @@ static EnumReducer: FC<()> = |ctx| {
     ctx.render(rsx! {
         div {
             h1 {"{status}"}
-            {contents}
             button {
                 "Set Ready"
                 onclick: move |_| reduce(KindaState::Ready)
@@ -126,12 +123,6 @@ static EnumReducer: FC<()> = |ctx| {
     })
 };
 
-fn helper(ctx: &Context) -> VNode {
-    ctx.render(rsx! {
-        div {}
-    })
-}
-
 /// Demonstrate how the DebugRenderer can be used to unit test components without needing a browser
 /// These tests can run locally.
 /// They use the "compare" method of the debug renderer to do partial tree compares for succint

+ 0 - 94
examples/example_app.rs

@@ -1,94 +0,0 @@
-//! Example App
-//! --------------
-//!
-//! This example shows how to use the cross-platform abilities of dioxus to generate everything a dioxus app might need.
-//! All of your apps will look like this.
-//!
-//! cargo run --features dioxus/static
-
-use std::u32;
-
-use dioxus::prelude::Context;
-
-// #[allow(unused_lifetimes)]
-#[derive(Debug, PartialEq, Hash)]
-struct Pool<'a> {
-    a: u32,
-    b: &'a str,
-}
-
-struct UserData {}
-type Query<In, Out> = fn(&Pool, In) -> Result<Out, ()>;
-// type Query<In, Out> = fn(&Pool, In) -> Out;
-
-static GET_USER: Query<String, Vec<UserData>> = |pool, name| {
-    //
-    let b = Ok(())?;
-    let b = Ok(())?;
-    let b = Ok(())?;
-    let b = Ok(())?;
-    let b = Ok(())?;
-    let b = Ok(())?;
-    todo!()
-};
-
-static SET_USER: Query<String, Vec<UserData>> = |pool, name| {
-    //
-    todo!()
-};
-
-fn main() {
-    //     // returns a future
-    //     let user_data = use_db(&ctx, GET_USER, || "Bill");
-
-    //     use_try_suspense(&ctx, async move {
-    //         match user_data.await? {
-    //             Ok() => {}
-    //             Err(err) => {}
-    //         }
-    //     })
-    // }
-
-    // fn use_try_suspense(ctx: &Context<()>) {
-    //     let c: Result<(), ()> = {
-    //         // let b = Ok(());
-    //         // b?
-    //     };
-}
-
-mod launches {
-    #[cfg(feature = "wasm")]
-    fn launch() {
-        // launch the wasm_rednerer
-    }
-
-    #[cfg(feature = "static")]
-    fn launch() {
-        // render the tree to text
-    }
-
-    // #[cfg(features = "server")]
-    // fn launch() {
-    //     // launch the app
-    // }
-
-    // #[cfg(features = "liveview")]
-    // fn launch() {
-    //     // launch the app
-    // }
-
-    // #[cfg(features = "desktop")]
-    // fn launch() {
-    //     // launch the app
-    // }
-
-    // #[cfg(features = "android")]
-    // fn launch() {
-    //     // launch a simulator in dev mode
-    // }
-
-    // #[cfg(features = "ios")]
-    // fn launch() {
-    //     // launch a simulator in dev mode
-    // }
-}

+ 0 - 39
examples/external_updates.rs

@@ -1,39 +0,0 @@
-//! Example: External Updates
-//! -------------------------
-//!
-//! Cause updates to the VirtualDOM state from outside the component lifecycle.
-//! The root props could be changed or the use_receiver hook could be used.
-//!
-//!
-
-fn main() {
-    let (recv, sender) = channel();
-
-    async_std::task::spawn({
-        for location in ["a", "b", "c", "d"] {
-            sender.send(location);
-        }
-    });
-
-    let app = diouxs_webview::launch_with_props(App, RootProps { recv }).await;
-}
-
-struct RootProps {
-    navigator: Receiver<&'static str>,
-}
-
-fn App(ctx: Context, props: &RootProps) -> VNode {
-    let router = use_router(&ctx, |router| {});
-
-    let navigator = use_history(&ctx);
-
-    use_receiver(&ctx, || ctx.recv.clone(), |to| navigator.navigate(to));
-
-    ctx.render(rsx! {
-        div {
-            a { href: "/dogs/"}
-            a { href: "/cats/"}
-            {content}
-        }
-    })
-}

+ 0 - 0
packages/core/examples/listener.rs → examples/listener.rs


+ 0 - 65
examples/live.rs

@@ -1,65 +0,0 @@
-use dioxus::prelude::*;
-use tide::{with_state, Request};
-use tide_websockets::{WebSocket, WebSocketConnection};
-
-fn main() {
-    let mut g = Context { props: &() };
-    LiveComponent(&mut g);
-}
-
-#[cfg(not(target_arch = "wasm32"))]
-async fn server() -> tide::Result<()> {
-    // Build the API
-    let mut app = tide::with_state(());
-    app.at("/app").get(WebSocket::new(live_handler));
-
-    // Launch the server
-    app.listen("127.0.0.1:8080").await?;
-
-    Ok(())
-}
-
-async fn live_handler(req: Request<()>, stream: WebSocketConnection) -> tide::Result<()> {
-    Ok(())
-}
-
-static LiveComponent: FC<()> = |ctx| {
-    use_live_component(
-        ctx,
-        #[cfg(target_arch = "wasm32")]
-        || {
-            // Always wait on the context's live component API
-            // suspend the component until this promise arrives, or fall back
-            let g = &LiveComponent;
-            html! {
-                <div>
-                   {"Hello world!"}
-                </div>
-            }
-        },
-        #[cfg(not(target_arch = "wasm32"))]
-        || {
-            // actually use the code originally specified in the component
-            // this gives use the function pointer. We don't necessarily get to hash the same pointer between two binaries
-            // Some key will need to be made, likely based on the function parameter
-            let g = &LiveComponent;
-            html! {
-                <div>
-                    {"Hello world!"}
-                </div>
-            }
-        },
-    )
-};
-
-/// This hooks connects with the LiveContext at the top of the app.
-fn use_live_component<T>(ctx: &mut Context<T>, b: fn() -> VNode) -> VNode {
-    todo!()
-}
-
-/// LiveContext is a special, limited form of the context api that disallows the "Context API"
-/// Its purpose is to shield the original Context where calls to use_context will fail. Instead of panicing and confusing
-/// users, we simply disallow usage of "use_context" and "childen". In effect, only serialiable props can be allowed.
-///
-/// In the future, we might try to lift these restrictions (esp children since they are virtual) but are limited via the web connection
-struct LiveContext {}

+ 0 - 42
examples/router.rs

@@ -1,42 +0,0 @@
-//! Dioxus Router
-//! -------------
-//!
-//! This exmaple showcases the Dioxus Router hook. This hook makes it possible to using the browser's navigation API to
-//! display different content based on the Page's URL. The hook provides a configuration object that calls various
-//! specified callbacks whenever the page URL changes. Using this hook should feel like building a "URL directory", similar
-//! to how Tide handles paths.
-
-use dioxus::prelude::*;
-
-fn main() {
-    diouxs_webview::launch(App).run().await
-}
-
-fn App(ctx: Context<()>) -> VNode {
-    let router = use_router(&ctx, |router| {
-        //
-        router.get("/dogs/:dogId/").render(|ctx, request| {
-            rsx! {
-                div {
-
-                }
-            }
-        });
-
-        router.get("/cats/:catId/").render(|ctx, request| {
-            rsx! {
-                div {
-
-                }
-            }
-        });
-    });
-
-    ctx.render(rsx! {
-        div {
-            a { href: "/dogs/"}
-            a { href: "/cats/"}
-            {router.render()}
-        }
-    })
-}

+ 60 - 0
examples/rsx_usage.rs

@@ -0,0 +1,60 @@
+fn main() {}
+
+mod components {
+    use baller::Baller;
+    use dioxus::prelude::*;
+
+    fn example() {
+        let g = rsx! {
+            div {
+                crate::components::baller::Baller {}
+                baller::Baller {
+                }
+                Taller {
+                    a: "asd"
+                }
+                baller::Baller {}
+                baller::Baller {}
+                Baller {
+                    // todo: manual props
+                    // {...BallerProps {}}
+                }
+                div {
+                    a: "asd",
+                    a: "asd",
+                    a: "asd",
+                    a: "asd",
+                    div {
+                        "asdas",
+                        "asdas",
+                        "asdas",
+                        "asdas",
+                        div {},
+                        div {
+                            class: "asdasd"
+                        },
+                    }
+                }
+            }
+        };
+    }
+
+    mod baller {
+        use super::*;
+        pub struct BallerProps {}
+
+        pub fn Baller(ctx: Context<()>) -> VNode {
+            todo!()
+        }
+    }
+
+    #[derive(Debug, PartialEq, Props)]
+    pub struct TallerProps {
+        a: &'static str,
+    }
+
+    pub fn Taller(ctx: Context<TallerProps>) -> VNode {
+        let b = true;
+        todo!()
+    }
+}

+ 0 - 45
examples/website.rs

@@ -1,45 +0,0 @@
-//! DioxusLabs Webiste
-//! ------------------
-//!
-//! This is the example powering the DioxusLabs website :)
-//! It's always good to dogfood your code, right?
-
-use dioxus::prelude::*;
-
-fn main() {}
-
-mod state {
-    pub struct AppState {
-        cur_page: Route,
-    }
-
-    pub enum Route {
-        Homepage,
-        Docs,
-    }
-}
-
-static APP: FC<()> = |ctx| {
-    ctx.render(html! {
-        <div>
-
-        <div>
-    })
-};
-
-/// Draw the navbar on top of the screen
-static Navbar: FC<state::Route> = |ctx| {
-    ctx.render(html! {
-        <div>
-
-        <div>
-    })
-};
-
-static Homepage: FC<()> = |ctx| {
-    ctx.render(html! {
-        <div>
-
-        <div>
-    })
-};

+ 3 - 3
examples/webview.rs

@@ -9,8 +9,8 @@
 
 use dioxus::prelude::*;
 
-async fn main() {
-    dioxus_webview::launch(|ctx| {
+fn main() {
+    dioxus::webview::launch(|ctx| {
         let (count, set_count) = use_state(&ctx, || 0);
 
         ctx.render(rsx! {
@@ -23,5 +23,5 @@ async fn main() {
                 }
             }
         })
-    }).await;
+    });
 }

+ 2 - 2
notes/CHANGELOG.md

@@ -113,8 +113,8 @@ Welcome to the first iteration of the Dioxus Virtual DOM! This release brings su
   - [ ] Re-exported through the `dioxus` crate (not core)
 - [ ] Hooks
   - [ ] Re-exported through the `dioxus` crate (not essential to core virtualdom)
-- [ ] fragments
-- [ ] pass-thru components
+- [x] fragments
+- [x] pass-thru components
 
 ## Less-essential todos
 

+ 5 - 5
notes/Parity.md

@@ -13,20 +13,20 @@ Sorted by priority
 | Context                | ✅     | ✅    | share state through the tree                     |
 | Hook                   | ✅     | ✅    | memory cells in components                       |
 | SSR                    | ✅     | ✅    | render directly to string                        |
-| Runs natively          | ✅     | 👀    | runs as a sharable binary                        |
-| Component Children     | ✅     | ✅    | ctx.children() as a list of nodes                |
+| Runs natively          | ✅     | 👀    | runs as a portable binary w/ extra tooling       |
+| 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 |
 | NodeRef                | 👀     | ✅    | gain direct access to nodes                      |
-| Controlled Inputs      | 👀     | ✅    | stateful wrappers around inputs                  |
+| Controlled Inputs      |      | ✅    | stateful wrappers around inputs                  |
 | CSS/Inline Styles      | 🛠      | ✅    | syntax for inline/conditional styles             |
 | 1st class global state | 🛠      | ✅    | redux/recoil/mobx on top of context              |
 | ----- Phase 2 -----    | -----  | ----- | -----                                            |
 | 1st class router       | 👀     | ✅    | Hook built on top of history                     |
 | Assets                 | 👀     | ✅    | include css/svg/img url statically               |
 | Integrated classnames  | 🛠      | 👀    | built-in `classnames`                            |
-| Suspense               | 👀     | 👀    | schedule future render from future               |
+| Suspense               | 👀     | 👀    | schedule future render from future/promise       |
 | Transition             | 👀     | 👀    | High-level control over suspense                 |
 | Animation              | 👀     | ✅    | Spring-style animations                          |
 | Mobile                 | 👀     | ✅    | Render with cacao                                |
@@ -34,7 +34,7 @@ Sorted by priority
 | 3D Renderer            | 👀     | ✅    | react-three-fiber                                |
 | ----- Phase 3 -----    | -----  | ----- | -----                                            |
 | Portal                 | 👀     | ✅    | cast elements through tree                       |
-| Error/Panic boundary   | 👀     | ✅    | catch panics and display BSOD                    |
+| Error/Panic boundary   | 👀     | ✅    | catch panics and display custom BSOD             |
 | Code-splitting         | 👀     | ✅    | Make bundle smaller/lazy                         |
 | LiveView               | 👀     | 👀    | Example for SSR + WASM apps                      |
 

+ 36 - 39
packages/atoms/README.md

@@ -1,42 +1,42 @@
 <div align="center">
-  <h1>⚛ Atoms</h1>
+  <h1>⚛ Dirac</h1>
   <p>
     <strong>Global state for Dioxus</strong>
   </p>
 </div>
 
-Atoms is a global state management toolkit for Dioxus, built on the concept of composable atoms of state:
+Dirac is a global state management toolkit for Dioxus, built on the concept of composable atoms of state:
 
 ```rust
 const COUNT: Atom<u32> = |_| 0;
 
 const Incr: FC<()> = |cx| {
-    let (count, set_count) = Atoms::use_read_write(&cx, &COUNT);
-    cx.render(rsx!( button { onclick: move |_| set_count(count + 1), "+" } ))
+    let (count, set_count) = dirac::use_read_write(&cx, &COUNT);
+    rsx!(in cx, button { onclick: move |_| set_count(count + 1), "+" } )
 }
 
 const Decr: FC<()> = |cx| {
-    let (count, set_count) = Atoms::use_read_write(&cx, &COUNT);
-    cx.render(rsx!( button { onclick: move |_| set_count(count - 1), "-" } ))
+    let (count, set_count) = dirac::use_read_write(&cx, &COUNT);
+    rsx!(in cx, button { onclick: move |_| set_count(count - 1), "-" } )
 }
 
 const App: FC<()> = |cx| {
-    let count = Atoms::use_read(&cx, &COUNT);
+    let count = dirac::use_read(&cx, &COUNT);
     cx.render(rsx!{
-        div {
-            "Count is {count}"
-            Incr {}
-            Decr {}
-        }
+        "Count is {count}"
+        Incr {}
+        Decr {}
     })
 }
 ```
 
-Atoms.rs provides a global state management API for Dioxus apps built on the concept of "atomic state." Instead of grouping state together into a single bundle ALA Redux, Atom provides individual building blocks of state called Atoms. These atoms can be set/get anywhere in the app and combined to craft complex state. Atom should be easier to learn and more efficient than Redux.
+Dirac provides a global state management API for Dioxus apps built on the concept of "atomic state." Instead of grouping state together into a single bundle like Redux, Dyon provides individual building blocks of state called atoms. These atoms can be set/get anywhere in the app and combined to craft complex state. Dyon should be easier to learn, more efficient than Redux, and allow you to build complex Dioxus apps with relative ease.
 
-Atoms.rs is officially supported by the Dioxus team. By doing so, we are "planting our flag in the sand" for atomic state management instead of bundled (Redux-style) state management. Atomic state management fits well with the internals of Dioxus and idiomatic Rust, meaning Atoms.rs state management will be faster, more efficient, and less sensitive to data races than Redux-style apps.
+## Support
 
-Internally, Dioxus uses batching to speed up linear-style operations. Atoms.rs integrates with this batching optimization, making app-wide state changes extremely fast. This way, Atoms.rs can be pushed significantly harder than Redux without the need to enable/disable debug flags to prevent performance slowdowns.
+Dyon is officially supported by the Dioxus team. By doing so, we are "planting our flag in the sand" for atomic state management instead of bundled (Redux-style) state management. Atomic state management fits well with the internals of Dioxus and idiomatic Rust, meaning Dirac state management will be faster, more efficient, and less sensitive to data races than Redux-style apps.
+
+Internally, Dioxus uses batching to speed up linear-style operations. Dirac integrates with this batching optimization, making app-wide state changes extremely fast. This way, Dirac can be pushed significantly harder than Redux without the need to enable/disable debug flags to prevent performance slowdowns.
 
 # Guide
 
@@ -45,19 +45,19 @@ Internally, Dioxus uses batching to speed up linear-style operations. Atoms.rs i
 A simple atom of state is defined globally as a const:
 
 ```rust
-const Light: Atom<&str> = |_| "Green";
+const LightColor: Atom<&str> = |_| "Green";
 ```
 
-This atom of state is initialized with a value of `"Green"`. The atom that is returned does not actually contain any values. Instead, the atom's key - which is automatically generated in this instance - is used in the context of a Atom App.
+This atom of state is initialized with a value of `"Green"`. The atom that is returned does not actually contain any values. Instead, the atom's key - which is automatically generated in this instance - is used in the context of a Dioxus App.
 
 This is then later used in components like so:
 
 ```rust
 fn App(ctx: Context<()>) -> VNode {
     // The Atom root must be initialized at the top of the application before any use_Atom hooks
-    Atoms::init_root(&ctx, |_| {});
+    dirac::intialize_root(&ctx, |_| {});
 
-    let color = Atoms::use_read(&ctx, Light);
+    let color = dirac::use_read(&ctx, &LightColor);
 
     ctx.render(rsx!( h1 {"Color of light: {color}"} ))
 }
@@ -67,15 +67,13 @@ Atoms are considered "Writable" objects since any consumer may also set the Atom
 
 ```rust
 fn App(ctx: Context<()>) -> VNode {
-    let color = Atoms::use_read(&ctx, Light);
-    let set_color = Atoms::use_write(&ctx, Light);
+    let color = dirac::use_read(&ctx, &LightColor);
+    let set_color = dirac::use_write(&ctx, &LightColor);
     ctx.render(rsx!(
-        div {
-            h1 { "Color: {color}" }
-            button { onclick: move |_| set_color("red"), "red" }
-            button { onclick: move |_| set_color("yellow"), "yellow" }
-            button { onclick: move |_| set_color("green"), "green" }
-        }
+        h1 { "Color: {color}" }
+        button { onclick: move |_| set_color("red"), "red" }
+        button { onclick: move |_| set_color("yellow"), "yellow" }
+        button { onclick: move |_| set_color("green"), "green" }
     ))
 }
 ```
@@ -84,12 +82,10 @@ fn App(ctx: Context<()>) -> VNode {
 
 ```rust
 fn App(ctx: Context<()>) -> VNode {
-    let (color, set_color) = Atoms::use_read_write(ctx, Light);
+    let (color, set_color) = dirac::use_read_write(&ctx, &Light);
     ctx.render(rsx!(
-        div {
-            h1 { "Color: {color}" }
-            button { onclick: move |_| set_color("red"), "red" }
-        }
+        h1 { "Color: {color}" }
+        button { onclick: move |_| set_color("red"), "red" }
     ))
 }
 ```
@@ -98,7 +94,7 @@ fn App(ctx: Context<()>) -> VNode {
 
 Selectors are a concept popular in the JS world as a way of narrowing down a selection of state outside the VDOM lifecycle. Selectors have two functions: 1 summarize/narrow down some complex state and 2) memoize calculations.
 
-Selectors are only `readable` - they cannot be set. This differs from AtomJS where selectors _are_ `writable`. Selectors, as you might've guessed, "select" some data from atoms and other selectors.
+Selectors are only `readable` - they cannot be set. This differs from RecoilJS where selectors _are_ `writable`. Selectors, as you might've guessed, "select" some data from atoms and other selectors.
 
 Selectors provide a `SelectorApi` which essentially exposes a read-only `AtomApi`. They have the `get` method which allows any readable valued to be obtained for the purpose of generating a new value. A `Selector` may only return `'static` data, however `SelectorBorrowed` may return borrowed data.
 
@@ -121,9 +117,12 @@ const ThreeChars: SelectorBorrowed<str> = |api| api.get(&Light).chars().take(3).
 Unfortunately, Rust tries to coerce `T` (the type in the Selector generics) to the `'static` lifetime because we defined it as a static. `SelectorBorrowed` defines a type for a function that returns `&T` and provides the right lifetime for `T`. If you don't like having to use a dedicated `Borrowed` type, regular functions work too:
 
 ```rust
+// An atom
 fn Light(api: &mut AtomBuilder) -> &'static str {
     "Green"
 }
+
+// A selector
 fn ThreeChars(api: &mut SelectorApi) -> &'static str {
     api.get(&Light).chars().take(3).unwrap()
 }
@@ -134,7 +133,7 @@ Returning borrowed data is generally frowned upon, but may be useful when used w
 - If a selected value equals its previous selection (via PartialEq), the old value must be kept around to avoid evaluating subscribed components.
 - It's unlikely that a change in a dependency's data will not change the selector's output.
 
-In general, borrowed selectors introduce a slight memory overhead as they need to retain previous state to safely memoize downstream subscribers. The amount of state kept around scales with the amount of `gets` in a selector - though as the number of dependencies increase, the less likely the selector actually stays memoized. Atom tries to optimize this behavior the best it can to balance component evaluations with memory overhead.
+In general, borrowed selectors introduce a slight memory overhead as they need to retain previous state to safely memoize downstream subscribers. The amount of state kept around scales with the amount of `gets` in a selector - though as the number of dependencies increase, the less likely the selector actually stays memoized. Dirac tries to optimize this behavior the best it can to balance component evaluations with memory overhead.
 
 ## Families
 
@@ -156,12 +155,10 @@ Whenever you `select` on a `Family`, the ID of the entry is tracked. Other subsc
 
 ```rust
 fn App(ctx: Context<()>) -> VNode {
-    let (rating, set_rating) = Atoms::use_read_write(ctx, CloudRatings.select("AWS"));
+    let (rating, set_rating) = dirac::use_read_write(ctx, CloudRatings.select("AWS"));
     ctx.render(rsx!(
-        div {
-            h1 { "AWS rating: {rating}" }
-            button { onclick: move |_| set_rating((rating + 1) % 5), "incr" }
-        }
+        h1 { "AWS rating: {rating}" }
+        button { onclick: move |_| set_rating((rating + 1) % 5), "incr" }
     ))
 }
 ```

+ 10 - 0
packages/atoms/examples/structured_app.rs

@@ -0,0 +1,10 @@
+fn main() {}
+
+use dioxus_core::prelude::*;
+
+static App: FC<()> = |ctx| {
+    //
+    use_initialize_app()
+};
+
+fn use_initialize_app(cx: &impl Scoped) {}

+ 58 - 0
packages/atoms/notes/async.md

@@ -0,0 +1,58 @@
+# Asynchronous state management
+
+Async is pervasive in web frontends. The web heavily relies on external resources like http, requests, storage, etc.
+
+## How does Redux do it?
+
+Thunks
+
+- call a synchronous dispatch function
+- queues an asynchronous "thunk"
+- thunks may not modify state, may only call reducers
+
+## How does Recoil do it?
+
+useRecoilCallback
+
+- call an async function
+- get/set any atom with the Recoil API
+- synchronously set values
+
+async atoms
+
+- atom's "get" returns a promise that resolves to the atom's value
+- if a request fails
+
+## How should we do it?
+
+```rust
+const USER_ID: Atom<String> = |atom| String::from("ThisIsDummyData");
+const TITLE: Selector<Result<String>> = |atom| {
+    atom.async_get(|api| async {
+        let user_id = api.get(ID);
+        let resp: Result<UserData> = surf::get(format!("https://myapi.com/users/{}", user_id))
+            .recv_json()
+            .await;
+    });
+}
+
+#[derive(Deref)]
+struct UserManager(RecoilApi);
+impl UserManager {
+    fn load_user_data() {
+
+    }
+}
+
+async fn Example(cx: Context<()>) -> Result<VNode> {
+    let title = use_read(cx, TITLE)?;
+}
+```
+
+```rust
+fn use_initialize_app() {
+    // initialize theme systems
+    // initialize websocket connection
+    // create task queue
+}
+```

+ 7 - 10
packages/core/examples/alternative.rs

@@ -5,13 +5,8 @@ use dioxus_core::prelude::*;
 static Example: FC<()> = |ctx| {
     ctx.render(dioxus_core::prelude::LazyNodes::new(move |ctx| {
         let bump = ctx.bump();
-        dioxus::builder::ElementBuilder::new(ctx, "h1")
-            .children([{
-                use bumpalo::core_alloc::fmt::Write;
-                let mut s = bumpalo::collections::String::new_in(bump);
-                write!(s, "hello");
-                dioxus::builder::text2(s)
-            }])
+        dioxus_core::builder::ElementBuilder::new(ctx, "h1")
+            .children([dioxus_core::builder::text3(bump, format_args!("hello"))])
             .finish()
     }))
 };
@@ -22,9 +17,11 @@ struct Props {
 static Example2: FC<Props> = |ctx| {
     ctx.render(dioxus_core::prelude::LazyNodes::new(move |__ctx| {
         let bump = __ctx.bump();
-        dioxus::builder::ElementBuilder::new(__ctx, "h1")
-            .children([{ dioxus::builder::text3(bump, format_args!("{}", ctx.text)) }])
-            // .children([{ dioxus::builder::text3(bump, format_args!("hello")) }])
+        dioxus_core::builder::ElementBuilder::new(__ctx, "h1")
+            .children([dioxus_core::builder::text3(
+                bump,
+                format_args!("{}", ctx.props.text),
+            )])
             .finish()
     }))
 };

+ 34 - 49
packages/core/examples/borrowed.rs

@@ -4,14 +4,12 @@
 //! It's slightly more advanced than just cloning, but well worth the investment.
 //!
 //! If you use the FC macro, we handle the lifetimes automatically, making it easy to write efficient & performant components.
-
 fn main() {}
 
-use std::{borrow::Borrow, ops::Deref, rc::Rc};
-
 use dioxus_core::prelude::*;
+use std::rc::Rc;
 
-struct Props {
+struct AppProps {
     items: Vec<Rc<ListItem>>,
 }
 
@@ -21,67 +19,54 @@ struct ListItem {
     age: u32,
 }
 
-fn app(ctx: Context<Props>) -> VNode {
+fn app(ctx: Context<AppProps>) -> VNode {
     let (val, set_val) = use_state(&ctx, || 0);
 
-    ctx.render(dioxus::prelude::LazyNodes::new(move |c| {
-        let mut root = builder::ElementBuilder::new(c, "div");
-        for child in &ctx.items {
-            // notice that the child directly borrows from our vec
-            // this makes lists very fast (simply views reusing lifetimes)
-            // <ChildItem item=child hanldler=setter />
-            root = root.child(builder::virtual_child(
-                c,
-                ChildItem,
-                // create the props with nothing but the fc<T>
-                fc_to_builder(ChildItem)
-                    .item(child.clone())
-                    .item_handler(Callback(set_val.clone()))
-                    .build(),
-                None,
-                &[],
-            ));
-        }
-        root.finish()
+    ctx.render(LazyNodes::new(move |_nodectx| {
+        builder::ElementBuilder::new(_nodectx, "div")
+            .iter_child({
+                ctx.items.iter().map(|child| {
+                    builder::virtual_child(
+                        _nodectx,
+                        ChildItem,
+                        ChildProps {
+                            item: child.clone(),
+                            item_handler: set_val.clone(),
+                        },
+                        None,
+                        &[],
+                    )
+                })
+            })
+            .iter_child([builder::ElementBuilder::new(_nodectx, "div")
+                .iter_child([builder::text3(_nodectx.bump(), format_args!("{}", val))])
+                .finish()])
+            .finish()
     }))
 }
 
 // props should derive a partialeq implementation automatically, but implement ptr compare for & fields
-#[derive(Props, PartialEq)]
 struct ChildProps {
     // Pass down complex structs
     item: Rc<ListItem>,
 
     // Even pass down handlers!
-    item_handler: Callback<i32>,
+    item_handler: Rc<dyn Fn(i32)>,
 }
 
-fn ChildItem<'a>(ctx: Context<ChildProps>) -> VNode {
-    ctx.render(rsx! {
-        div {
-            // onclick: move |evt| (ctx.item_handler)(10)
-            h1 { "abcd123 {ctx.item.name}" }
-            h2 { "abcd123" }
-            div {
-                "abcd123"
-                h2 { }
-                p { }
-            }
-        }
-    })
+fn ChildItem<'a>(cx: Context<'a, ChildProps>) -> VNode {
+    cx.render(LazyNodes::new(move |__cx| todo!()))
 }
 
-#[derive(Clone)]
-struct Callback<I, O = ()>(Rc<dyn Fn(I) -> O>);
-impl<I, O> Deref for Callback<I, O> {
-    type Target = Rc<dyn Fn(I) -> O>;
-
-    fn deref(&self) -> &Self::Target {
-        &self.0
+impl PartialEq for ChildProps {
+    fn eq(&self, other: &Self) -> bool {
+        false
     }
 }
-impl<I, O> PartialEq for Callback<I, O> {
-    fn eq(&self, other: &Self) -> bool {
-        Rc::ptr_eq(&self.0, &other.0)
+unsafe impl Properties for ChildProps {
+    type Builder = ();
+    const CAN_BE_MEMOIZED: bool = false;
+    fn builder() -> Self::Builder {
+        ()
     }
 }

+ 0 - 29
packages/core/examples/component_child.rs

@@ -1,29 +0,0 @@
-use std::{ops::Deref, rc::Rc};
-
-use dioxus::virtual_dom::Scope;
-use dioxus_core::prelude::*;
-
-type RcStr = Rc<str>;
-
-fn main() {
-    let r: RcStr = "asdasd".into();
-    let r: RcStr = String::from("asdasd").into();
-
-    let g = rsx! {
-        div {
-            Example {}
-        }
-    };
-}
-
-static Example: FC<()> = |ctx| {
-    let nodes = ctx.children();
-
-    //
-    rsx! { in ctx,
-        div {
-            h1 {"these are children nodes: "}
-            {nodes}
-        }
-    }
-};

+ 0 - 72
packages/core/examples/fc.rs

@@ -1,72 +0,0 @@
-use dioxus_core::component::fc_to_builder;
-use dioxus_core::prelude::*;
-
-static BLAH: FC<()> = |ctx| {
-    let g = "asd".to_string();
-    ctx.render(rsx! {
-        div {
-            SomeComponent {
-                some_field: g
-            }
-        }
-    })
-};
-
-#[derive(PartialEq, Props)]
-pub struct ExampleProps {
-    some_field: String,
-}
-
-static SomeComponent: FC<ExampleProps> = |ctx| {
-    let blah = rsx! {
-        div {}
-    };
-
-    let data = match 1 {
-        1 => ctx.render(rsx! (
-            div {
-                h1 {}
-                h3 {}
-            }
-        )),
-        1 => ctx.render(rsx!( div { "abc" } )),
-        2 => ctx.render(rsx!( div { "abc" } )),
-        3 => ctx.render(rsx!( div { "abc" } )),
-        _ => todo!(),
-    };
-
-    let data = match 1 {
-        1 => ctx.render(rsx! (
-            div {
-                h1 {}
-                h3 {}
-            }
-        )),
-        1 => ctx.render(rsx!(
-            div { "abc" }
-        )),
-        2 => ctx.render(rsx!(
-            div { "abc" }
-        )),
-        3 => ctx.render(rsx!(
-            div { "abc" }
-        )),
-        _ => todo!(),
-    };
-
-    let i = (0..10).map(|v| {
-        rsx! {
-            div {
-                "{v}"
-            }
-        }
-    });
-
-    ctx.render(rsx! {
-        div {
-            ""
-         }
-    })
-};
-
-fn main() {}

+ 0 - 59
packages/core/examples/macro_testing.rs

@@ -1,59 +0,0 @@
-use baller::Baller;
-use dioxus_core::prelude::*;
-
-fn main() {
-    let g = rsx! {
-        div {
-            crate::baller::Baller {}
-            baller::Baller {
-            }
-            Taller {
-                a: "asd"
-            }
-            baller::Baller {}
-            baller::Baller {}
-            Baller {
-                // todo: manual props
-                // {...BallerProps {}}
-            }
-            div {
-                a: "asd",
-                a: "asd",
-                a: "asd",
-                a: "asd",
-                div {
-                    "asdas",
-                    "asdas",
-                    "asdas",
-                    "asdas",
-                    div {},
-                    div {
-                        // classes: {[ ("baller", true), ("maller", false) ]}
-                        // class: "asdasd"
-                        // class: "{customname}",
-                        // class: {[("baller", true), ("hover", false)]}
-                    },
-                }
-            }
-        }
-    };
-}
-
-mod baller {
-    use super::*;
-    pub struct BallerProps {}
-
-    pub fn Baller(ctx: Context<()>) -> VNode {
-        todo!()
-    }
-}
-
-#[derive(Debug, PartialEq, Props)]
-pub struct TallerProps {
-    a: &'static str,
-}
-
-pub fn Taller(ctx: Context<TallerProps>) -> VNode {
-    let b = true;
-    todo!()
-}

+ 0 - 44
packages/core/examples/nested.rs

@@ -1,44 +0,0 @@
-#![allow(unused)]
-//! Example of components in
-
-use std::{borrow::Borrow, marker::PhantomData};
-
-use dioxus_core::prelude::*;
-
-fn main() {}
-
-static Header: FC<()> = |ctx| {
-    let inner = use_ref(&ctx, || 0);
-
-    let handler1 = move || println!("Value is {}", inner.borrow());
-
-    ctx.render(dioxus::prelude::LazyNodes::new(|nodectx| {
-        builder::ElementBuilder::new(nodectx, "div")
-            .child(VNode::Component(nodectx.bump().alloc(VComponent::new(
-                nodectx,
-                Bottom,
-                (),
-                None,
-                &[],
-            ))))
-            .finish()
-    }))
-};
-
-static Bottom: FC<()> = |ctx| {
-    ctx.render(html! {
-        <div>
-            <h1> "bruh 1" </h1>
-            <h1> "bruh 2" </h1>
-        </div>
-    })
-};
-
-fn Top(ctx: Context<()>) -> VNode {
-    ctx.render(html! {
-        <div>
-            <h1> "bruh 1" </h1>
-            <h1> "bruh 2" </h1>
-        </div>
-    })
-}

+ 0 - 16
packages/core/examples/props.rs

@@ -1,16 +0,0 @@
-use dioxus_core::prelude::*;
-
-#[derive(Debug, PartialEq, Props)]
-struct SomeProps {
-    a: i32,
-
-    // automatically do the default (none) and automatically Into<T>
-    #[builder(default, setter(strip_option))]
-    b: Option<i32>,
-}
-
-fn main() {
-    let g: SomeProps = SomeProps::builder().a(10).b(10).build();
-
-    let _r = g.b.unwrap_or_else(|| 10);
-}

+ 0 - 47
packages/core/examples/rsx_usage.rs

@@ -1,47 +0,0 @@
-use dioxus_core::prelude::*;
-
-fn main() {}
-
-trait SProps {}
-
-trait Comp {
-    type Props;
-}
-
-impl<T> Comp for FC<T> {
-    type Props = T;
-}
-
-fn test() {
-    // let g: FC<ButtonProps> = CustomButton;
-}
-
-trait Render: Sized {
-    fn render(ctx: Context<Self>) -> VNode;
-}
-// include as much as you might accept
-struct Button {
-    onhover: Option<Box<dyn Fn()>>,
-}
-
-impl Render for Button {
-    fn render(ctx: Context<Self>) -> VNode {
-        let _onfocus = move |_evt: ()| log::debug!("Focused");
-
-        // todo!()
-        ctx.render(rsx! {
-            button {
-                // ..ctx.attrs,
-                class: "abc123",
-                // style: { a: 2, b: 3, c: 4 },
-                onclick: move |_evt| {
-                    // log::info("hello world");
-                },
-                // Custom1 { a: 123 }
-                // Custom2 { a: 456, "abc", h1 {"1"}, h2 {"2"} }
-                // Custom3 { a: "sometext goes here" }
-                // Custom4 { onclick: |evt| log::info("click") }
-            }
-        })
-    }
-}

+ 0 - 18
packages/core/examples/showcase.rs

@@ -1,18 +0,0 @@
-//! The book of patterns
-//! -----
-//!
-//! This "book" shows a bunch of useful patterns, ergonomic highlights, and quirks for common usecases when building components.
-//!
-//! Here's what's in the book:
-//! - [ ] Use the builder pattern directly instead of the macro
-//! - [ ] Using statics instead of functions for components without type hassle.
-//! - [ ] Use the FC macro on statics and fns for inling props
-//! - [ ] Using borrowed data from parent to child
-//!
-//! Running this example will generate a beautiful webpage. This webpage is used on the diouxs website.
-
-fn main() {}
-
-mod static_usage {}
-mod fc_macro {}
-mod borrowed_data {}

+ 0 - 41
packages/core/examples/step.rs

@@ -1,41 +0,0 @@
-use dioxus_core::debug_renderer::DebugRenderer;
-use dioxus_core::{component::Properties, prelude::*};
-
-fn main() -> Result<(), ()> {
-    let p1 = SomeProps { name: "bob".into() };
-
-    let _vdom = DebugRenderer::new_with_props(Example, p1);
-
-    Ok(())
-}
-
-#[derive(Debug, PartialEq, Props)]
-struct SomeProps {
-    name: String,
-}
-
-static Example: FC<SomeProps> = |ctx| {
-    ctx.render(html! {
-        <div>
-            <h1> "hello world!" </h1>
-        </div>
-    })
-};
-
-// #[test]
-#[derive(PartialEq, Clone)]
-struct MyStruct {
-    a: String,
-}
-
-fn check_before_to_owned() {
-    let new_str = MyStruct {
-        a: "asd".to_string(),
-    };
-
-    let out = town(&new_str);
-}
-
-fn town<T: ToOwned + PartialEq>(t: &T) -> T::Owned {
-    t.to_owned()
-}

+ 0 - 8
packages/core/examples/template.rs

@@ -1,8 +0,0 @@
-use dioxus_core::prelude::*;
-use dioxus_core_macro::rsx_template;
-
-fn main() {
-    let g = html!("<div> </div>");
-    let g = html!("<div> </div>");
-    // let g = rsx!("div { div { } } ");
-}

+ 0 - 16
packages/core/examples/text.rs

@@ -1,16 +0,0 @@
-use dioxus_core::prelude::*;
-use dioxus_core_macro::format_args_f;
-
-fn main() {
-    let num = 123;
-    let b = Bump::new();
-
-    let g = rsx! {
-        div {
-            "abc {num}"
-            div {
-                "asd"
-            }
-        }
-    };
-}

+ 0 - 28
packages/core/examples/textstream.rs

@@ -1,28 +0,0 @@
-use dioxus::virtual_dom::VirtualDom;
-use dioxus_core::prelude::*;
-fn main() {
-    let mut dom = VirtualDom::new(App);
-    let edits = dom.rebuild().unwrap();
-    dbg!(edits);
-}
-
-static App: FC<()> = |ctx| {
-    //
-    ctx.render(rsx! {
-        div {
-            "abc"
-            "123"
-        }
-    })
-};
-
-static Fragment: FC<()> = |ctx| {
-    //
-
-    let children = ctx.children();
-    ctx.render(LazyNodes::new(move |c: &NodeCtx| {
-        //
-        let frag = c.bump().alloc(VFragment::new(None, children));
-        VNode::Fragment(frag)
-    }))
-};

+ 152 - 171
packages/core/src/events.rs

@@ -4,6 +4,8 @@
 //! 3rd party renderers are responsible for converting their native events into these virtual event types. Events might
 //! be heavy or need to interact through FFI, so the events themselves are designed to be lazy.
 
+use std::rc::Rc;
+
 use crate::innerlude::ScopeIdx;
 
 #[derive(Debug)]
@@ -26,24 +28,21 @@ impl EventTrigger {
 #[derive(Debug)]
 pub enum VirtualEvent {
     // Real events
-    ClipboardEvent(on::ClipboardEvent),
-    CompositionEvent(on::CompositionEvent),
-    KeyboardEvent(on::KeyboardEvent),
-    FocusEvent(on::FocusEvent),
-    FormEvent(on::FormEvent),
-    GenericEvent(on::GenericEvent),
-    SelectionEvent(on::SelectionEvent),
-    TouchEvent(on::TouchEvent),
-    UIEvent(on::UIEvent),
-    WheelEvent(on::WheelEvent),
-    MediaEvent(on::MediaEvent),
-    AnimationEvent(on::AnimationEvent),
-    TransitionEvent(on::TransitionEvent),
-    ToggleEvent(on::ToggleEvent),
-
-    // TODO these events are particularly heavy, so we box them
-    MouseEvent(on::MouseEvent),
-    PointerEvent(on::PointerEvent),
+    ClipboardEvent(Rc<dyn on::ClipboardEvent>),
+    CompositionEvent(Rc<dyn on::CompositionEvent>),
+    KeyboardEvent(Rc<dyn on::KeyboardEvent>),
+    FocusEvent(Rc<dyn on::FocusEvent>),
+    FormEvent(Rc<dyn on::FormEvent>),
+    SelectionEvent(Rc<dyn on::SelectionEvent>),
+    TouchEvent(Rc<dyn on::TouchEvent>),
+    UIEvent(Rc<dyn on::UIEvent>),
+    WheelEvent(Rc<dyn on::WheelEvent>),
+    MediaEvent(Rc<dyn on::MediaEvent>),
+    AnimationEvent(Rc<dyn on::AnimationEvent>),
+    TransitionEvent(Rc<dyn on::TransitionEvent>),
+    ToggleEvent(Rc<dyn on::ToggleEvent>),
+    MouseEvent(Rc<dyn on::MouseEvent>),
+    PointerEvent(Rc<dyn on::PointerEvent>),
 
     // ImageEvent(event_data::ImageEvent),
     OtherEvent,
@@ -51,7 +50,7 @@ pub enum VirtualEvent {
 
 pub mod on {
     #![allow(unused)]
-    use std::{ops::Deref, rc::Rc};
+    use std::{fmt::Debug, ops::Deref, rc::Rc};
 
     use crate::{
         builder::ElementBuilder,
@@ -64,10 +63,13 @@ pub mod on {
     macro_rules! event_directory {
         ( $( $eventdata:ident: [ $( $name:ident )* ]; )* ) => {
             $(
+
+
+
                 $(
                     pub fn $name<'a>(
                         c: &'_ NodeCtx<'a>,
-                        callback: impl Fn($eventdata) + 'a,
+                        callback: impl Fn(Rc<dyn $eventdata>) + 'a,
                     ) -> Listener<'a> {
                         let bump = &c.bump();
                         Listener {
@@ -91,7 +93,6 @@ pub mod on {
         KeyboardEvent: [keydown keypress keyup];
         FocusEvent: [focus blur];
         FormEvent: [change input invalid reset submit];
-        GenericEvent: [];
         MouseEvent: [
             click contextmenu doubleclick drag dragend dragenter dragexit
             dragleave dragover dragstart drop mousedown mouseenter mouseleave
@@ -116,45 +117,46 @@ pub mod on {
         ToggleEvent: [toggle];
     }
 
-    pub struct GetModifierKey(pub Box<dyn Fn(usize) -> bool>);
-    impl std::fmt::Debug for GetModifierKey {
-        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-            Ok(()) // just skip for now
-        }
+    trait GenericEvent {
+        /// Returns whether or not a specific event is a bubbling event
+        fn bubbles(&self) -> bool;
+        /// Sets or returns whether the event should propagate up the hierarchy or not
+        fn cancelBubble(&self) -> ();
+        /// Returns whether or not an event can have its default action prevented
+        fn cancelable(&self) -> bool;
+        /// Returns whether the event is composed or not
+        fn composed(&self) -> bool;
+        /// Returns the event's path
+        fn composedPath(&self) -> ();
+        /// Returns the element whose event listeners triggered the event
+        fn currentTarget(&self) -> ();
+        /// Returns whether or not the preventDefault method was called for the event
+        fn defaultPrevented(&self) -> ();
+        /// Returns which phase of the event flow is currently being evaluated
+        fn eventPhase(&self) -> ();
+        /// Returns whether or not an event is trusted
+        fn isTrusted(&self) -> ();
+        /// Cancels the event if it is cancelable, meaning that the default action that belongs to the event will
+        fn preventDefault(&self) -> ();
+        /// Prevents other listeners of the same event from being called
+        fn stopImmediatePropagation(&self) -> ();
+        /// Prevents further propagation of an event during event flow
+        fn stopPropagation(&self) -> ();
+        /// Returns the element that triggered the event
+        fn target(&self) -> ();
+        /// Returns the time (in milliseconds relative to the epoch) at which the event was created
+        fn timeStamp(&self) -> usize;
     }
 
-    // DOMDataTransfer clipboardData
-    #[derive(Debug)]
-    pub struct ClipboardEvent {}
-
-    #[derive(Debug)]
-    pub struct CompositionEvent {
-        data: String,
+    pub trait ClipboardEvent: Debug {
+        // DOMDataTransfer clipboardData
     }
 
-    #[derive(Debug)]
-    pub struct KeyboardEvent {
-        char_code: usize,
-        ctrl_key: bool,
-        key: String,
-        key_code: usize,
-        locale: String,
-        location: usize,
-        meta_key: bool,
-        repeat: bool,
-        shift_key: bool,
-        which: usize,
-        get_modifier_state: GetModifierKey,
-    }
-    pub struct KeyboardEvent2(pub Rc<dyn KeyboardEventT>);
-    impl std::ops::Deref for KeyboardEvent2 {
-        type Target = dyn KeyboardEventT;
-        fn deref(&self) -> &Self::Target {
-            self.0.as_ref()
-        }
+    pub trait CompositionEvent: Debug {
+        fn data(&self) -> String;
     }
 
-    pub trait KeyboardEventT {
+    pub trait KeyboardEvent: Debug {
         fn char_code(&self) -> usize;
         fn ctrl_key(&self) -> bool;
         fn key(&self) -> String;
@@ -165,146 +167,125 @@ pub mod on {
         fn repeat(&self) -> bool;
         fn shift_key(&self) -> bool;
         fn which(&self) -> usize;
-        fn get_modifier_state(&self) -> GetModifierKey;
+        fn get_modifier_state(&self, key_code: usize) -> bool;
     }
 
-    #[derive(Debug)]
-    pub struct FocusEvent {/* DOMEventTarget relatedTarget */}
-
-    #[derive(Debug)]
-    pub struct FormEvent {
-        pub value: String,
+    pub trait FocusEvent: Debug {
+        /* DOMEventTarget relatedTarget */
     }
 
-    #[derive(Debug)]
-    pub struct GenericEvent {/* Error Load */}
-
-    #[derive(Debug)]
-    pub struct MouseEvent(pub Box<RawMouseEvent>);
-
-    #[derive(Debug)]
-    pub struct RawMouseEvent {
-        pub alt_key: bool,
-        pub button: i32,
-        pub buttons: i32,
-        pub client_x: i32,
-        pub client_y: i32,
-        pub ctrl_key: bool,
-        pub meta_key: bool,
-        pub page_x: i32,
-        pub page_y: i32,
-        pub screen_x: i32,
-        pub screen_y: i32,
-        pub shift_key: bool,
-        pub get_modifier_state: GetModifierKey,
-        // relatedTarget: DOMEventTarget,
-    }
-    impl Deref for MouseEvent {
-        type Target = RawMouseEvent;
-        fn deref(&self) -> &Self::Target {
-            self.0.as_ref()
-        }
+    pub trait FormEvent: Debug {
+        fn value(&self) -> String;
     }
 
-    #[derive(Debug)]
-    pub struct PointerEvent(Box<RawPointerEvent>);
-    impl Deref for PointerEvent {
-        type Target = RawPointerEvent;
-        fn deref(&self) -> &Self::Target {
-            self.0.as_ref()
-        }
+    pub trait MouseEvent: Debug {
+        fn alt_key(&self) -> bool;
+        fn button(&self) -> i32;
+        fn buttons(&self) -> i32;
+        fn client_x(&self) -> i32;
+        fn client_y(&self) -> i32;
+        fn ctrl_key(&self) -> bool;
+        fn meta_key(&self) -> bool;
+        fn page_x(&self) -> i32;
+        fn page_y(&self) -> i32;
+        fn screen_x(&self) -> i32;
+        fn screen_y(&self) -> i32;
+        fn shift_key(&self) -> bool;
+        fn get_modifier_state(&self, key_code: usize) -> bool;
     }
 
-    #[derive(Debug)]
-    pub struct RawPointerEvent {
+    pub trait PointerEvent: Debug {
         // Mouse only
-        alt_key: bool,
-        button: usize,
-        buttons: usize,
-        client_x: i32,
-        client_y: i32,
-        ctrl_key: bool,
-        meta_key: bool,
-        page_x: i32,
-        page_y: i32,
-        screen_x: i32,
-        screen_y: i32,
-        shift_key: bool,
-        get_modifier_state: GetModifierKey,
-
-        // Pointer-specific
-        pointer_id: usize,
-        width: usize,
-        height: usize,
-        pressure: usize,
-        tangential_pressure: usize,
-        tilt_x: i32,
-        tilt_y: i32,
-        twist: i32,
-        pointer_type: String,
-        is_primary: bool,
+        fn alt_key(&self) -> bool;
+        fn button(&self) -> usize;
+        fn buttons(&self) -> usize;
+        fn client_x(&self) -> i32;
+        fn client_y(&self) -> i32;
+        fn ctrl_key(&self) -> bool;
+        fn meta_key(&self) -> bool;
+        fn page_x(&self) -> i32;
+        fn page_y(&self) -> i32;
+        fn screen_x(&self) -> i32;
+        fn screen_y(&self) -> i32;
+        fn shift_key(&self) -> bool;
+        fn get_modifier_state(&self, key_code: usize) -> bool;
+        fn pointer_id(&self) -> usize;
+        fn width(&self) -> usize;
+        fn height(&self) -> usize;
+        fn pressure(&self) -> usize;
+        fn tangential_pressure(&self) -> usize;
+        fn tilt_x(&self) -> i32;
+        fn tilt_y(&self) -> i32;
+        fn twist(&self) -> i32;
+        fn pointer_type(&self) -> String;
+        fn is_primary(&self) -> bool;
     }
 
-    #[derive(Debug)]
-    pub struct SelectionEvent {}
-
-    #[derive(Debug)]
-    pub struct TouchEvent {
-        alt_key: bool,
-        ctrl_key: bool,
-        meta_key: bool,
-        shift_key: bool,
-        get_modifier_state: GetModifierKey,
-        //
+    pub trait SelectionEvent: Debug {}
+
+    pub trait TouchEvent: Debug {
+        fn alt_key(&self) -> bool;
+        fn ctrl_key(&self) -> bool;
+        fn meta_key(&self) -> bool;
+        fn shift_key(&self) -> bool;
+        fn get_modifier_state(&self, key_code: usize) -> bool;
         // changedTouches: DOMTouchList,
-        // todo
         // targetTouches: DOMTouchList,
         // touches: DOMTouchList,
-        //  getModifierState(key): boolean
     }
 
-    #[derive(Debug)]
-    pub struct UIEvent {
+    pub trait UIEvent: Debug {
         // DOMAbstractView view
-        detail: i32,
+        fn detail(&self) -> i32;
+    }
+
+    pub trait WheelEvent: Debug {
+        fn delta_mode(&self) -> i32;
+        fn delta_x(&self) -> i32;
+        fn delta_y(&self) -> i32;
+        fn delta_z(&self) -> i32;
     }
 
-    #[derive(Debug)]
-    pub struct WheelEvent {
-        delta_mode: i32,
-        delta_x: i32,
-        delta_y: i32,
-        delta_z: i32,
+    pub trait MediaEvent: Debug {}
+
+    pub trait ImageEvent: Debug {
+        //     load error
     }
 
-    #[derive(Debug)]
-    pub struct MediaEvent {}
-
-    // todo!
-    // imageevent clashes with media event
-    // might need to derive this e manually
-    //
-    // #[derive(Debug)]
-    // pub struct ImageEvent {}
-    // event_builder! {
-    //     ImageEvent;
-    //     load error
-    // }
-
-    #[derive(Debug)]
-    pub struct AnimationEvent {
-        animation_name: String,
-        pseudo_element: String,
-        elapsed_time: f32,
+    pub trait AnimationEvent: Debug {
+        fn animation_name(&self) -> String;
+        fn pseudo_element(&self) -> String;
+        fn elapsed_time(&self) -> f32;
     }
 
-    #[derive(Debug)]
-    pub struct TransitionEvent {
-        property_name: String,
-        pseudo_element: String,
-        elapsed_time: f32,
+    pub trait TransitionEvent: Debug {
+        fn property_name(&self) -> String;
+        fn pseudo_element(&self) -> String;
+        fn elapsed_time(&self) -> f32;
     }
 
-    #[derive(Debug)]
-    pub struct ToggleEvent {}
+    pub trait ToggleEvent: Debug {}
+}
+
+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();
+                }
+            }
+        };
+    }
 }

+ 0 - 68
packages/hooks/src/hooks/mod.rs

@@ -1,68 +0,0 @@
-mod use_context;
-mod use_effect;
-mod use_reducer;
-mod use_ref;
-mod use_state;
-
-pub use use_context::*;
-pub use use_effect::*;
-pub use use_reducer::*;
-pub use use_ref::*;
-pub use use_state::*;
-
-use crate::{HookUpdater, CURRENT_HOOK};
-use std::cell::RefCell;
-use std::ops::DerefMut;
-use std::rc::Rc;
-
-pub fn use_hook<InternalHook: 'static, Output, Tear: FnOnce(&mut InternalHook) -> () + 'static>(
-    initializer: impl FnOnce() -> InternalHook,
-    runner: impl FnOnce(&mut InternalHook, HookUpdater) -> Output,
-    tear_down: Tear,
-) -> Output {
-    // Extract current hook
-    let updater = CURRENT_HOOK.with(|hook_state_holder| {
-        let mut hook_state_holder = hook_state_holder
-            .try_borrow_mut()
-            .expect("Nested hooks not supported");
-
-        let mut hook_state = hook_state_holder
-            .as_mut()
-            .expect("No current hook. Hooks can only be called inside function components");
-
-        // Determine which hook position we're at and increment for the next hook
-        let hook_pos = hook_state.counter;
-        hook_state.counter += 1;
-
-        // Initialize hook if this is the first call
-        if hook_pos >= hook_state.hooks.len() {
-            let initial_state = Rc::new(RefCell::new(initializer()));
-            hook_state.hooks.push(initial_state.clone());
-            hook_state.destroy_listeners.push(Box::new(move || {
-                let mut is = initial_state.borrow_mut();
-                let ihook = is.deref_mut();
-                tear_down(ihook);
-            }));
-        }
-
-        let hook = hook_state
-            .hooks
-            .get(hook_pos)
-            .expect("Not the same number of hooks. Hooks must not be called conditionally")
-            .clone();
-
-        HookUpdater {
-            hook,
-            process_message: hook_state.process_message.clone(),
-        }
-    });
-
-    // Execute the actual hook closure we were given. Let it mutate the hook state and let
-    // it create a callback that takes the mutable hook state.
-    let mut hook = updater.hook.borrow_mut();
-    let hook: &mut InternalHook = hook
-        .downcast_mut()
-        .expect("Incompatible hook type. Hooks must always be called in the same order");
-
-    runner(hook, updater.clone())
-}

+ 0 - 469
packages/hooks/src/hooks/use_context.rs

@@ -1,469 +0,0 @@
-// Naming this file use_context could be confusing. Not least to the IDE.
-use crate::{get_current_scope, use_hook};
-use std::any::TypeId;
-use std::cell::RefCell;
-use std::rc::{Rc, Weak};
-use std::{iter, mem};
-use yew::html;
-use yew::html::{AnyScope, Scope};
-use yew::{Children, Component, ComponentLink, Html, Properties};
-
-type ConsumerCallback<T> = Box<dyn Fn(Rc<T>)>;
-type UseContextOutput<T> = Option<Rc<T>>;
-
-struct UseContext<T2: Clone + PartialEq + 'static> {
-    provider_scope: Option<Scope<ContextProvider<T2>>>,
-    current_context: Option<Rc<T2>>,
-    callback: Option<Rc<ConsumerCallback<T2>>>,
-}
-
-pub fn use_context<T: Clone + PartialEq + 'static>() -> UseContextOutput<T> {
-    let scope = get_current_scope()
-        .expect("No current Scope. `use_context` can only be called inside function components");
-
-    use_hook(
-        // Initializer
-        move || {
-            let provider_scope = find_context_provider_scope::<T>(&scope);
-            let current_context =
-                with_provider_component(&provider_scope, |comp| Rc::clone(&comp.context));
-
-            UseContext {
-                provider_scope,
-                current_context,
-                callback: None,
-            }
-        },
-        // Runner
-        |hook, updater| {
-            // setup a listener for the context provider to update us
-            let listener = move |ctx: Rc<T>| {
-                updater.callback(move |state: &mut UseContext<T>| {
-                    state.current_context = Some(ctx);
-                    true
-                });
-            };
-            hook.callback = Some(Rc::new(Box::new(listener)));
-
-            // Subscribe to the context provider with our callback
-            let weak_cb = Rc::downgrade(hook.callback.as_ref().unwrap());
-            with_provider_component(&hook.provider_scope, |comp| {
-                comp.subscribe_consumer(weak_cb)
-            });
-
-            // Return the current state
-            hook.current_context.clone()
-        },
-        // Cleanup
-        |hook| {
-            if let Some(cb) = hook.callback.take() {
-                drop(cb);
-            }
-        },
-    )
-}
-
-#[derive(Clone, PartialEq, Properties)]
-pub struct ContextProviderProps<T: Clone + PartialEq> {
-    pub context: T,
-    pub children: Children,
-}
-
-pub struct ContextProvider<T: Clone + PartialEq + 'static> {
-    context: Rc<T>,
-    children: Children,
-    consumers: RefCell<Vec<Weak<ConsumerCallback<T>>>>,
-}
-
-impl<T: Clone + PartialEq> ContextProvider<T> {
-    /// Add the callback to the subscriber list to be called whenever the context changes.
-    /// The consumer is unsubscribed as soon as the callback is dropped.
-    fn subscribe_consumer(&self, mut callback: Weak<ConsumerCallback<T>>) {
-        // consumers re-subscribe on every render. Try to keep the subscriber list small by reusing dead slots.
-        let mut consumers = self.consumers.borrow_mut();
-        for cb in consumers.iter_mut() {
-            if cb.strong_count() == 0 {
-                mem::swap(cb, &mut callback);
-                return;
-            }
-        }
-
-        // no slot to reuse, this is a new consumer
-        consumers.push(callback);
-    }
-
-    /// Notify all subscribed consumers and remove dropped consumers from the list.
-    fn notify_consumers(&mut self) {
-        let context = &self.context;
-        self.consumers.borrow_mut().retain(|cb| {
-            if let Some(cb) = cb.upgrade() {
-                cb(Rc::clone(context));
-                true
-            } else {
-                false
-            }
-        });
-    }
-}
-
-impl<T: Clone + PartialEq + 'static> Component for ContextProvider<T> {
-    type Message = ();
-    type Properties = ContextProviderProps<T>;
-
-    fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
-        Self {
-            children: ctx.children,
-            context: Rc::new(ctx.context),
-            consumers: RefCell::new(Vec::new()),
-        }
-    }
-
-    fn update(&mut self, _msg: Self::Message) -> bool {
-        true
-    }
-
-    fn change(&mut self, props: Self::Properties) -> bool {
-        let should_render = if self.children == ctx.children {
-            false
-        } else {
-            self.children = ctx.children;
-            true
-        };
-
-        let new_context = Rc::new(ctx.context);
-        if self.context != new_context {
-            self.context = new_context;
-            self.notify_consumers();
-        }
-
-        should_render
-    }
-
-    fn view(&self) -> Html {
-        html! { <>{ self.children.clone() }</> }
-    }
-}
-
-fn find_context_provider_scope<T: Clone + PartialEq + 'static>(
-    scope: &AnyScope,
-) -> Option<Scope<ContextProvider<T>>> {
-    let expected_type_id = TypeId::of::<ContextProvider<T>>();
-    iter::successors(Some(scope), |scope| scope.get_parent())
-        .filter(|scope| scope.get_type_id() == &expected_type_id)
-        .cloned()
-        .map(AnyScope::downcast::<ContextProvider<T>>)
-        .next()
-}
-
-fn with_provider_component<T, F, R>(
-    provider_scope: &Option<Scope<ContextProvider<T>>>,
-    f: F,
-) -> Option<R>
-where
-    T: Clone + PartialEq,
-    F: FnOnce(&ContextProvider<T>) -> R,
-{
-    provider_scope
-        .as_ref()
-        .and_then(|scope| scope.get_component().map(|comp| f(&*comp)))
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::hooks::{use_effect, use_ref, use_state};
-    use crate::util::*;
-    use crate::{FunctionComponent, FunctionProvider};
-    use wasm_bindgen_test::*;
-    use yew::prelude::*;
-
-    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
-
-    #[wasm_bindgen_test]
-    fn use_context_scoping_works() {
-        #[derive(Clone, Debug, PartialEq)]
-        struct ExampleContext(String);
-        struct UseContextFunctionOuter {}
-        struct UseContextFunctionInner {}
-        struct ExpectNoContextFunction {}
-        type UseContextComponent = FunctionComponent<UseContextFunctionOuter>;
-        type UseContextComponentInner = FunctionComponent<UseContextFunctionInner>;
-        type ExpectNoContextComponent = FunctionComponent<ExpectNoContextFunction>;
-        impl FunctionProvider for ExpectNoContextFunction {
-            type TProps = ();
-
-            fn run(_props: &Self::TProps) -> Html {
-                if use_context::<ExampleContext>().is_some() {
-                    yew::services::ConsoleService::log(&format!(
-                        "Context should be None here, but was {:?}!",
-                        use_context::<ExampleContext>().unwrap()
-                    ));
-                };
-                return html! {
-                    <div></div>
-                };
-            }
-        }
-        impl FunctionProvider for UseContextFunctionOuter {
-            type TProps = ();
-
-            fn run(_props: &Self::TProps) -> Html {
-                type ExampleContextProvider = ContextProvider<ExampleContext>;
-                return html! {
-                    <div>
-                        <ExampleContextProvider context=ExampleContext("wrong1".into())>
-                            <div>{"ignored"}</div>
-                        </ExampleContextProvider>
-                        <ExampleContextProvider context=ExampleContext("wrong2".into())>
-                            <ExampleContextProvider context=ExampleContext("correct".into())>
-                                <ExampleContextProvider context=ExampleContext("wrong1".into())>
-                                    <div>{"ignored"}</div>
-                                </ExampleContextProvider>
-                                <UseContextComponentInner />
-                            </ExampleContextProvider>
-                        </ExampleContextProvider>
-                        <ExampleContextProvider context=ExampleContext("wrong3".into())>
-                            <div>{"ignored"}</div>
-                        </ExampleContextProvider>
-                        <ExpectNoContextComponent />
-                    </div>
-                };
-            }
-        }
-        impl FunctionProvider for UseContextFunctionInner {
-            type TProps = ();
-
-            fn run(_props: &Self::TProps) -> Html {
-                let context = use_context::<ExampleContext>();
-                return html! {
-                    <div id="result">{ &context.unwrap().0 }</div>
-                };
-            }
-        }
-
-        let app: App<UseContextComponent> = yew::App::new();
-        app.mount(yew::utils::document().get_element_by_id("output").unwrap());
-        let result: String = obtain_result_by_id("result");
-        assert_eq!("correct", result);
-    }
-
-    #[wasm_bindgen_test]
-    fn use_context_works_with_multiple_types() {
-        #[derive(Clone, Debug, PartialEq)]
-        struct ContextA(u32);
-        #[derive(Clone, Debug, PartialEq)]
-        struct ContextB(u32);
-
-        struct Test1Function;
-        impl FunctionProvider for Test1Function {
-            type TProps = ();
-
-            fn run(_props: &Self::TProps) -> Html {
-                assert_eq!(use_context::<ContextA>(), Some(Rc::new(ContextA(2))));
-                assert_eq!(use_context::<ContextB>(), Some(Rc::new(ContextB(1))));
-
-                return html! {};
-            }
-        }
-        type Test1 = FunctionComponent<Test1Function>;
-
-        struct Test2Function;
-        impl FunctionProvider for Test2Function {
-            type TProps = ();
-
-            fn run(_props: &Self::TProps) -> Html {
-                assert_eq!(use_context::<ContextA>(), Some(Rc::new(ContextA(0))));
-                assert_eq!(use_context::<ContextB>(), Some(Rc::new(ContextB(1))));
-
-                return html! {};
-            }
-        }
-        type Test2 = FunctionComponent<Test2Function>;
-
-        struct Test3Function;
-        impl FunctionProvider for Test3Function {
-            type TProps = ();
-
-            fn run(_props: &Self::TProps) -> Html {
-                assert_eq!(use_context::<ContextA>(), Some(Rc::new(ContextA(0))));
-                assert_eq!(use_context::<ContextB>(), None);
-
-                return html! {};
-            }
-        }
-        type Test3 = FunctionComponent<Test3Function>;
-
-        struct Test4Function;
-        impl FunctionProvider for Test4Function {
-            type TProps = ();
-
-            fn run(_props: &Self::TProps) -> Html {
-                assert_eq!(use_context::<ContextA>(), None);
-                assert_eq!(use_context::<ContextB>(), None);
-
-                return html! {};
-            }
-        }
-        type Test4 = FunctionComponent<Test4Function>;
-
-        struct TestFunction;
-        impl FunctionProvider for TestFunction {
-            type TProps = ();
-
-            fn run(_props: &Self::TProps) -> Html {
-                type ContextAProvider = ContextProvider<ContextA>;
-                type ContextBProvider = ContextProvider<ContextB>;
-
-                return html! {
-                    <div>
-                        <ContextAProvider context=ContextA(0)>
-                            <ContextBProvider context=ContextB(1)>
-                                <ContextAProvider context=ContextA(2)>
-                                    <Test1/>
-                                </ContextAProvider>
-                                <Test2/>
-                            </ContextBProvider>
-                            <Test3/>
-                        </ContextAProvider>
-                        <Test4 />
-                    </div>
-                };
-            }
-        }
-        type TestComponent = FunctionComponent<TestFunction>;
-
-        let app: App<TestComponent> = yew::App::new();
-        app.mount(yew::utils::document().get_element_by_id("output").unwrap());
-    }
-
-    #[wasm_bindgen_test]
-    fn use_context_update_works() {
-        #[derive(Clone, Debug, PartialEq)]
-        struct MyContext(String);
-
-        #[derive(Clone, Debug, PartialEq, Properties)]
-        struct RenderCounterProps {
-            id: String,
-            children: Children,
-        }
-
-        struct RenderCounterFunction;
-        impl FunctionProvider for RenderCounterFunction {
-            type TProps = RenderCounterProps;
-
-            fn run(props: &Self::TProps) -> Html {
-                let counter = use_ref(|| 0);
-                *counter.borrow_mut() += 1;
-                log::info!("Render counter {:?}", counter);
-                return html! {
-                    <>
-                        <div id=ctx.id.clone()>
-                            { format!("total: {}", counter.borrow()) }
-                        </div>
-                        { ctx.children.clone() }
-                    </>
-                };
-            }
-        }
-        type RenderCounter = FunctionComponent<RenderCounterFunction>;
-
-        #[derive(Clone, Debug, PartialEq, Properties)]
-        struct ContextOutletProps {
-            id: String,
-            #[prop_or_default]
-            magic: usize,
-        }
-        struct ContextOutletFunction;
-        impl FunctionProvider for ContextOutletFunction {
-            type TProps = ContextOutletProps;
-
-            fn run(props: &Self::TProps) -> Html {
-                let counter = use_ref(|| 0);
-                *counter.borrow_mut() += 1;
-
-                let ctx = use_context::<Rc<MyContext>>().expect("context not passed down");
-                log::info!("============");
-                log::info!("ctx is {:#?}", ctx);
-                log::info!("magic is {:#?}", ctx.magic);
-                log::info!("outlet counter is {:#?}", ctx);
-                log::info!("============");
-
-                return html! {
-                    <>
-                        <div>{ format!("magic: {}\n", ctx.magic) }</div>
-                        <div id=ctx.id.clone()>
-                            { format!("current: {}, total: {}", ctx.0, counter.borrow()) }
-                        </div>
-                    </>
-                };
-            }
-        }
-        type ContextOutlet = FunctionComponent<ContextOutletFunction>;
-
-        struct TestFunction;
-        impl FunctionProvider for TestFunction {
-            type TProps = ();
-
-            fn run(_props: &Self::TProps) -> Html {
-                type MyContextProvider = ContextProvider<Rc<MyContext>>;
-
-                let (ctx, set_ctx) = use_state(|| MyContext("hello".into()));
-                let rendered = use_ref(|| 0);
-
-                // this is used to force an update specific to test-2
-                let (magic_rc, set_magic) = use_state(|| 0);
-                let magic: usize = *magic_rc;
-
-                use_effect(move || {
-                    let count = *rendered.borrow();
-                    match count {
-                        0 => {
-                            set_ctx(MyContext("world".into()));
-                            *rendered.borrow_mut() += 1;
-                        }
-                        1 => {
-                            // force test-2 to re-render.
-                            set_magic(1);
-                            *rendered.borrow_mut() += 1;
-                        }
-                        2 => {
-                            set_ctx(MyContext("hello world!".into()));
-                            *rendered.borrow_mut() += 1;
-                        }
-                        _ => (),
-                    };
-                    || {}
-                });
-
-                return html! {
-                    <MyContextProvider context=ctx>
-                        <RenderCounter id="test-0">
-                            <ContextOutlet id="test-1"/>
-                            <ContextOutlet id="test-2" magic=magic/>
-                        </RenderCounter>
-                    </MyContextProvider>
-                };
-            }
-        }
-        type TestComponent = FunctionComponent<TestFunction>;
-
-        wasm_logger::init(wasm_logger::Config::default());
-        let app: App<TestComponent> = yew::App::new();
-        app.mount(yew::utils::document().get_element_by_id("output").unwrap());
-
-        // 1 initial render + 3 update steps
-        assert_eq!(obtain_result_by_id("test-0"), "total: 4");
-
-        // 1 initial + 2 context update
-        assert_eq!(
-            obtain_result_by_id("test-1"),
-            "current: hello world!, total: 3"
-        );
-
-        // 1 initial + 1 context update + 1 magic update + 1 context update
-        assert_eq!(
-            obtain_result_by_id("test-2"),
-            "current: hello world!, total: 4"
-        );
-    }
-}

+ 0 - 320
packages/hooks/src/hooks/use_effect.rs

@@ -1,320 +0,0 @@
-use crate::use_hook;
-use std::{borrow::Borrow, rc::Rc};
-
-struct UseEffect<Destructor> {
-    destructor: Option<Box<Destructor>>,
-}
-
-/// This hook is used for hooking into the component's lifecycle.
-///
-/// # Example
-/// ```rust
-/// # use yew_functional::{function_component, use_effect, use_state};
-/// # use yew::prelude::*;
-/// # use std::rc::Rc;
-/// #
-/// #[function_component(UseEffect)]
-/// fn effect() -> Html {
-///     let (counter, set_counter) = use_state(|| 0);
-///
-///     let counter_one = counter.clone();
-///     use_effect(move || {
-///         // Make a call to DOM API after component is rendered
-///         yew::utils::document().set_title(&format!("You clicked {} times", counter_one));
-///
-///         // Perform the cleanup
-///         || yew::utils::document().set_title(&format!("You clicked 0 times"))
-///     });
-///
-///     let onclick = {
-///         let counter = Rc::clone(&counter);
-///         Callback::from(move |_| set_counter(*counter + 1))
-///     };
-///
-///     html! {
-///         <button onclick=onclick>{ format!("Increment to {}", counter) }</button>
-///     }
-/// }
-/// ```
-pub fn use_effect<Destructor>(callback: impl FnOnce() -> Destructor + 'static)
-where
-    Destructor: FnOnce() + 'static,
-{
-    let callback = Box::new(callback);
-    use_hook(
-        move || {
-            let effect: UseEffect<Destructor> = UseEffect { destructor: None };
-            effect
-        },
-        |_, updater| {
-            // Run on every render
-            updater.post_render(move |state: &mut UseEffect<Destructor>| {
-                if let Some(de) = state.destructor.take() {
-                    de();
-                }
-                let new_destructor = callback();
-                state.destructor.replace(Box::new(new_destructor));
-                false
-            });
-        },
-        |hook| {
-            if let Some(destructor) = hook.destructor.take() {
-                destructor()
-            }
-        },
-    )
-}
-
-struct UseEffectDeps<Destructor, Dependents> {
-    destructor: Option<Box<Destructor>>,
-    deps: Rc<Dependents>,
-}
-
-/// This hook is similar to [`use_effect`] but it accepts dependencies.
-///
-/// Whenever the dependencies are changed, the effect callback is called again.
-/// To detect changes, dependencies must implement `PartialEq`.
-/// Note that the destructor also runs when dependencies change.
-pub fn use_effect_with_deps<Callback, Destructor, Dependents>(callback: Callback, deps: Dependents)
-where
-    Callback: FnOnce(&Dependents) -> Destructor + 'static,
-    Destructor: FnOnce() + 'static,
-    Dependents: PartialEq + 'static,
-{
-    let deps = Rc::new(deps);
-    let deps_c = deps.clone();
-
-    use_hook(
-        move || {
-            let destructor: Option<Box<Destructor>> = None;
-            UseEffectDeps {
-                destructor,
-                deps: deps_c,
-            }
-        },
-        move |_, updater| {
-            updater.post_render(move |state: &mut UseEffectDeps<Destructor, Dependents>| {
-                if state.deps != deps {
-                    if let Some(de) = state.destructor.take() {
-                        de();
-                    }
-                    let new_destructor = callback(deps.borrow());
-                    state.deps = deps;
-                    state.destructor.replace(Box::new(new_destructor));
-                } else if state.destructor.is_none() {
-                    state
-                        .destructor
-                        .replace(Box::new(callback(state.deps.borrow())));
-                }
-                false
-            });
-        },
-        |hook| {
-            if let Some(destructor) = hook.destructor.take() {
-                destructor()
-            }
-        },
-    );
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::hooks::{use_effect_with_deps, use_ref, use_state};
-    use crate::util::*;
-    use crate::{FunctionComponent, FunctionProvider};
-    use std::ops::Deref;
-    use std::ops::DerefMut;
-    use std::rc::Rc;
-    use wasm_bindgen_test::*;
-    use yew::prelude::*;
-    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
-
-    #[wasm_bindgen_test]
-    fn use_effect_works_many_times() {
-        struct UseEffectFunction {}
-        impl FunctionProvider for UseEffectFunction {
-            type TProps = ();
-
-            fn run(_: &Self::TProps) -> Html {
-                let (counter, set_counter) = use_state(|| 0);
-                let counter_clone = counter.clone();
-
-                use_effect_with_deps(
-                    move |_| {
-                        if *counter_clone < 4 {
-                            set_counter(*counter_clone + 1);
-                        }
-                        || {}
-                    },
-                    *counter,
-                );
-
-                return html! {
-                    <div>
-                        {"The test result is"}
-                        <div id="result">{counter}</div>
-                        {"\n"}
-                    </div>
-                };
-            }
-        }
-
-        type UseEffectComponent = FunctionComponent<UseEffectFunction>;
-        let app: App<UseEffectComponent> = yew::App::new();
-        app.mount(yew::utils::document().get_element_by_id("output").unwrap());
-        let result = obtain_result();
-        assert_eq!(result.as_str(), "4");
-    }
-
-    #[wasm_bindgen_test]
-    fn use_effect_works_once() {
-        struct UseEffectFunction {}
-        impl FunctionProvider for UseEffectFunction {
-            type TProps = ();
-
-            fn run(_: &Self::TProps) -> Html {
-                let (counter, set_counter) = use_state(|| 0);
-                let counter_clone = counter.clone();
-
-                use_effect_with_deps(
-                    move |_| {
-                        set_counter(*counter_clone + 1);
-                        || panic!("Destructor should not have been called")
-                    },
-                    (),
-                );
-
-                return html! {
-                    <div>
-                        {"The test result is"}
-                        <div id="result">{counter}</div>
-                        {"\n"}
-                    </div>
-                };
-            }
-        }
-        type UseEffectComponent = FunctionComponent<UseEffectFunction>;
-        let app: App<UseEffectComponent> = yew::App::new();
-        app.mount(yew::utils::document().get_element_by_id("output").unwrap());
-        let result = obtain_result();
-        assert_eq!(result.as_str(), "1");
-    }
-
-    #[wasm_bindgen_test]
-    fn use_effect_refires_on_dependency_change() {
-        struct UseEffectFunction {}
-        impl FunctionProvider for UseEffectFunction {
-            type TProps = ();
-
-            fn run(_: &Self::TProps) -> Html {
-                let number_ref = use_ref(|| 0);
-                let number_ref_c = number_ref.clone();
-                let number_ref2 = use_ref(|| 0);
-                let number_ref2_c = number_ref2.clone();
-                let arg = *number_ref.borrow_mut().deref_mut();
-                let (_, set_counter) = use_state(|| 0);
-                use_effect_with_deps(
-                    move |dep| {
-                        let mut ref_mut = number_ref_c.borrow_mut();
-                        let inner_ref_mut = ref_mut.deref_mut();
-                        if *inner_ref_mut < 1 {
-                            *inner_ref_mut += 1;
-                            assert_eq!(dep, &0);
-                        } else {
-                            assert_eq!(dep, &1);
-                        }
-                        set_counter(10); // we just need to make sure it does not panic
-                        move || {
-                            set_counter(11);
-                            *number_ref2_c.borrow_mut().deref_mut() += 1;
-                        }
-                    },
-                    arg,
-                );
-                return html! {
-                    <div>
-                        {"The test result is"}
-                        <div id="result">{*number_ref.borrow_mut().deref_mut()}{*number_ref2.borrow_mut().deref_mut()}</div>
-                        {"\n"}
-                    </div>
-                };
-            }
-        }
-        type UseEffectComponent = FunctionComponent<UseEffectFunction>;
-        let app: App<UseEffectComponent> = yew::App::new();
-        app.mount(yew::utils::document().get_element_by_id("output").unwrap());
-        let result: String = obtain_result();
-
-        assert_eq!(result.as_str(), "11");
-    }
-
-    #[wasm_bindgen_test]
-    fn use_effect_destroys_on_component_drop() {
-        struct UseEffectFunction {}
-        struct UseEffectWrapper {}
-        #[derive(Properties, Clone)]
-        struct WrapperProps {
-            destroy_called: Rc<dyn Fn()>,
-        }
-        impl PartialEq for WrapperProps {
-            fn eq(&self, _other: &Self) -> bool {
-                false
-            }
-        }
-        #[derive(Properties, Clone)]
-        struct FunctionProps {
-            effect_called: Rc<dyn Fn()>,
-            destroy_called: Rc<dyn Fn()>,
-        }
-        impl PartialEq for FunctionProps {
-            fn eq(&self, _other: &Self) -> bool {
-                false
-            }
-        }
-        type UseEffectComponent = FunctionComponent<UseEffectFunction>;
-        type UseEffectWrapperComponent = FunctionComponent<UseEffectWrapper>;
-        impl FunctionProvider for UseEffectFunction {
-            type TProps = FunctionProps;
-
-            fn run(props: &Self::TProps) -> Html {
-                let effect_called = ctx.effect_called.clone();
-                let destroy_called = ctx.destroy_called.clone();
-                use_effect_with_deps(
-                    move |_| {
-                        effect_called();
-                        move || destroy_called()
-                    },
-                    (),
-                );
-                return html! {};
-            }
-        }
-        impl FunctionProvider for UseEffectWrapper {
-            type TProps = WrapperProps;
-
-            fn run(props: &Self::TProps) -> Html {
-                let (show, set_show) = use_state(|| true);
-                if *show {
-                    let effect_called: Rc<dyn Fn()> = Rc::new(move || set_show(false));
-                    return html! {
-                        <UseEffectComponent destroy_called=ctx.destroy_called.clone() effect_called=effect_called />
-                    };
-                } else {
-                    return html! {
-                        <div>{"EMPTY"}</div>
-                    };
-                }
-            }
-        }
-        let app: App<UseEffectWrapperComponent> = yew::App::new();
-        let destroy_counter = Rc::new(std::cell::RefCell::new(0));
-        let destroy_counter_c = destroy_counter.clone();
-        app.mount_with_props(
-            yew::utils::document().get_element_by_id("output").unwrap(),
-            WrapperProps {
-                destroy_called: Rc::new(move || *destroy_counter_c.borrow_mut().deref_mut() += 1),
-            },
-        );
-        assert_eq!(1, *destroy_counter.borrow().deref());
-    }
-}

+ 0 - 203
packages/hooks/src/hooks/use_reducer.rs

@@ -1,203 +0,0 @@
-use crate::use_hook;
-use std::rc::Rc;
-
-struct UseReducer<State> {
-    current_state: Rc<State>,
-}
-
-/// This hook is an alternative to [`use_state`]. It is used to handle component's state and is used
-/// when complex actions needs to be performed on said state.
-///
-/// For lazy initialization, consider using [`use_reducer_with_init`] instead.
-///
-/// # Example
-/// ```rust
-/// # use yew_functional::{function_component, use_reducer};
-/// # use yew::prelude::*;
-/// # use std::rc::Rc;
-/// # use std::ops::DerefMut;
-/// #
-/// #[function_component(UseReducer)]
-/// fn reducer() -> Html {
-///     /// reducer's Action
-///     enum Action {
-///         Double,
-///         Square,
-///     }
-///
-///     /// reducer's State
-///     struct CounterState {
-///         counter: i32,
-///     }
-///
-///     let (
-///         counter, // the state
-///         // function to update the state
-///         // as the same suggests, it dispatches the values to the reducer function
-///         dispatch
-///     ) = use_reducer(
-///         // the reducer function
-///         |prev: Rc<CounterState>, action: Action| CounterState {
-///             counter: match action {
-///                 Action::Double => prev.counter * 2,
-///                 Action::Square => prev.counter * prev.counter,
-///             }
-///         },
-///         // initial state
-///         CounterState { counter: 1 },
-///     );
-///
-///    let double_onclick = {
-///         let dispatch = Rc::clone(&dispatch);
-///         Callback::from(move |_| dispatch(Action::Double))
-///     };
-///     let square_onclick = Callback::from(move |_| dispatch(Action::Square));
-///
-///     html! {
-///         <>
-///             <div id="result">{ counter.counter }</div>
-///
-///             <button onclick=double_onclick>{ "Double" }</button>
-///             <button onclick=square_onclick>{ "Square" }</button>
-///         </>
-///     }
-/// }
-/// ```
-pub fn use_reducer<Action: 'static, Reducer, State: 'static>(
-    reducer: Reducer,
-    initial_state: State,
-) -> (Rc<State>, Rc<dyn Fn(Action)>)
-where
-    Reducer: Fn(Rc<State>, Action) -> State + 'static,
-{
-    use_reducer_with_init(reducer, initial_state, |a| a)
-}
-
-/// [`use_reducer`] but with init argument.
-///
-/// This is useful for lazy initialization where it is beneficial not to perform expensive
-/// computation up-front
-///
-/// # Example
-/// ```rust
-/// # use yew_functional::{function_component, use_reducer_with_init};
-/// # use yew::prelude::*;
-/// # use std::rc::Rc;
-/// #
-/// #[function_component(UseReducerWithInit)]
-/// fn reducer_with_init() -> Html {
-///     struct CounterState {
-///         counter: i32,
-///     }
-///     let (counter, dispatch) = use_reducer_with_init(
-///         |prev: Rc<CounterState>, action: i32| CounterState {
-///             counter: prev.counter + action,
-///         },
-///         0,
-///         |initial: i32| CounterState {
-///             counter: initial + 10,
-///         },
-///     );
-///
-///     html! {
-///         <>
-///             <div id="result">{counter.counter}</div>
-///
-///             <button onclick=Callback::from(move |_| dispatch(10))>{"Increment by 10"}</button>
-///         </>
-///     }
-/// }
-/// ```
-pub fn use_reducer_with_init<
-    Reducer,
-    Action: 'static,
-    State: 'static,
-    InitialState: 'static,
-    InitFn: 'static,
->(
-    reducer: Reducer,
-    initial_state: InitialState,
-    init: InitFn,
-) -> (Rc<State>, Rc<dyn Fn(Action)>)
-where
-    Reducer: Fn(Rc<State>, Action) -> State + 'static,
-    InitFn: Fn(InitialState) -> State,
-{
-    let init = Box::new(init);
-    let reducer = Rc::new(reducer);
-    use_hook(
-        move || UseReducer {
-            current_state: Rc::new(init(initial_state)),
-        },
-        |s, updater| {
-            let setter: Rc<dyn Fn(Action)> = Rc::new(move |action: Action| {
-                let reducer = reducer.clone();
-                // We call the callback, consumer the updater
-                // Required to put the type annotations on Self so the method knows how to downcast
-                updater.callback(move |state: &mut UseReducer<State>| {
-                    let new_state = reducer(state.current_state.clone(), action);
-                    state.current_state = Rc::new(new_state);
-                    true
-                });
-            });
-
-            let current = s.current_state.clone();
-            (current, setter)
-        },
-        |_| {},
-    )
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-    use crate::hooks::use_effect_with_deps;
-    use crate::util::*;
-    use crate::{FunctionComponent, FunctionProvider};
-    use wasm_bindgen_test::*;
-    use yew::prelude::*;
-    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
-
-    #[wasm_bindgen_test]
-    fn use_reducer_works() {
-        struct UseReducerFunction {}
-        impl FunctionProvider for UseReducerFunction {
-            type TProps = ();
-            fn run(_: &Self::TProps) -> Html {
-                struct CounterState {
-                    counter: i32,
-                }
-                let (counter, dispatch) = use_reducer_with_init(
-                    |prev: std::rc::Rc<CounterState>, action: i32| CounterState {
-                        counter: prev.counter + action,
-                    },
-                    0,
-                    |initial: i32| CounterState {
-                        counter: initial + 10,
-                    },
-                );
-
-                use_effect_with_deps(
-                    move |_| {
-                        dispatch(1);
-                        || {}
-                    },
-                    (),
-                );
-                return html! {
-                    <div>
-                        {"The test result is"}
-                        <div id="result">{counter.counter}</div>
-                        {"\n"}
-                    </div>
-                };
-            }
-        }
-        type UseReducerComponent = FunctionComponent<UseReducerFunction>;
-        let app: App<UseReducerComponent> = yew::App::new();
-        app.mount(yew::utils::document().get_element_by_id("output").unwrap());
-        let result = obtain_result();
-
-        assert_eq!(result.as_str(), "11");
-    }
-}

+ 0 - 98
packages/hooks/src/hooks/use_ref.rs

@@ -1,98 +0,0 @@
-use crate::use_hook;
-use std::{cell::RefCell, rc::Rc};
-
-/// This hook is used for obtaining a mutable reference to a stateful value.
-/// Its state persists across renders.
-///
-/// It is important to note that you do not get notified of state changes.
-/// If you need the component to be re-rendered on state change, consider using [`use_state`].
-///
-/// # Example
-/// ```rust
-/// # use yew_functional::{function_component, use_state, use_ref};
-/// # use yew::prelude::*;
-/// # use std::rc::Rc;
-/// # use std::cell::RefCell;
-/// # use std::ops::{Deref, DerefMut};
-/// #
-/// #[function_component(UseRef)]
-/// fn ref_hook() -> Html {
-///     let (message, set_message) = use_state(|| "".to_string());
-///     let message_count = use_ref(|| 0);
-///
-///     let onclick = Callback::from(move |e| {
-///         let window = yew::utils::window();
-///
-///         if *message_count.borrow_mut() > 3 {
-///             window.alert_with_message("Message limit reached");
-///         } else {
-///             *message_count.borrow_mut() += 1;
-///             window.alert_with_message("Message sent");
-///         }
-///     });
-///
-///     let onchange = Callback::from(move |e| {
-///         if let ChangeData::Value(value) = e {
-///             set_message(value)
-///         }
-///     });
-///
-///     html! {
-///         <div>
-///             <input onchange=onchange value=message />
-///             <button onclick=onclick>{ "Send" }</button>
-///         </div>
-///     }
-/// }
-/// ```
-pub fn use_ref<T: 'static>(initial_value: impl FnOnce() -> T + 'static) -> Rc<RefCell<T>> {
-    use_hook(
-        || Rc::new(RefCell::new(initial_value())),
-        |state| state.clone(),
-        |_| {},
-    )
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::{
-        hooks::use_state,
-        util::*,
-        {FunctionComponent, FunctionProvider},
-    };
-    use std::ops::DerefMut;
-    use wasm_bindgen_test::*;
-    use yew::prelude::*;
-    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
-
-    #[wasm_bindgen_test]
-    fn use_ref_works() {
-        struct UseRefFunction {}
-        impl FunctionProvider for UseRefFunction {
-            type TProps = ();
-
-            fn run(_: &Self::TProps) -> Html {
-                let ref_example = use_ref(|| 0);
-                *ref_example.borrow_mut().deref_mut() += 1;
-                let (counter, set_counter) = use_state(|| 0);
-                if *counter < 5 {
-                    set_counter(*counter + 1)
-                }
-                return html! {
-                    <div>
-                        {"The test output is: "}
-                        <div id="result">{*ref_example.borrow_mut().deref_mut() > 4}</div>
-                        {"\n"}
-                    </div>
-                };
-            }
-        }
-        type UseRefComponent = FunctionComponent<UseRefFunction>;
-        let app: App<UseRefComponent> = yew::App::new();
-        app.mount(yew::utils::document().get_element_by_id("output").unwrap());
-
-        let result = obtain_result();
-        assert_eq!(result.as_str(), "true");
-    }
-}

+ 0 - 142
packages/hooks/src/hooks/use_state.rs

@@ -1,142 +0,0 @@
-use crate::use_hook;
-use std::rc::Rc;
-
-struct UseState<T2> {
-    current: Rc<T2>,
-}
-
-/// This hook is used to mange state in a function component.
-///
-/// # Example
-/// ```rust
-/// # use yew_functional::{function_component, use_state, use_ref};
-/// # use yew::prelude::*;
-/// # use std::rc::Rc;
-/// #
-/// #[function_component(UseState)]
-/// fn state() -> Html {
-///     let (
-///         counter, // the returned state
-///         set_counter // setter to update the state
-///     ) = use_state(|| 0);
-///     let onclick = {
-///         let counter = Rc::clone(&counter);
-///         Callback::from(move |_| set_counter(*counter + 1))
-///     };
-///
-///     html! {
-///         <div>
-///             <button onclick=onclick>{ "Increment value" }</button>
-///             <p>
-///                 <b>{ "Current value: " }</b>
-///                 { counter }
-///             </p>
-///         </div>
-///     }
-/// }
-/// ```
-pub fn use_state<T: 'static, F: FnOnce() -> T + 'static>(
-    initial_state_fn: F,
-) -> (Rc<T>, Rc<dyn Fn(T)>) {
-    use_hook(
-        // Initializer
-        move || UseState {
-            current: Rc::new(initial_state_fn()),
-        },
-        // Runner
-        move |hook, updater| {
-            let setter: Rc<(dyn Fn(T))> = Rc::new(move |new_val: T| {
-                updater.callback(move |st: &mut UseState<T>| {
-                    st.current = Rc::new(new_val);
-                    true
-                })
-            });
-
-            let current = hook.current.clone();
-            (current, setter)
-        },
-        // Teardown
-        |_| {},
-    )
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::hooks::use_effect_with_deps;
-    use crate::util::*;
-    use crate::{FunctionComponent, FunctionProvider};
-    use wasm_bindgen_test::*;
-    use yew::prelude::*;
-    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
-
-    #[wasm_bindgen_test]
-    fn use_state_works() {
-        struct UseStateFunction {}
-        impl FunctionProvider for UseStateFunction {
-            type TProps = ();
-
-            fn run(_: &Self::TProps) -> Html {
-                let (counter, set_counter) = use_state(|| 0);
-                if *counter < 5 {
-                    set_counter(*counter + 1)
-                }
-                return html! {
-                    <div>
-                        {"Test Output: "}
-                        <div id="result">{*counter}</div>
-                        {"\n"}
-                    </div>
-                };
-            }
-        }
-        type UseComponent = FunctionComponent<UseStateFunction>;
-        let app: App<UseComponent> = yew::App::new();
-        app.mount(yew::utils::document().get_element_by_id("output").unwrap());
-        let result = obtain_result();
-        assert_eq!(result.as_str(), "5");
-    }
-
-    #[wasm_bindgen_test]
-    fn multiple_use_state_setters() {
-        struct UseStateFunction {}
-        impl FunctionProvider for UseStateFunction {
-            type TProps = ();
-
-            fn run(_: &Self::TProps) -> Html {
-                let (counter, set_counter_in_use_effect) = use_state(|| 0);
-                let counter = *counter;
-                // clone without manually wrapping with Rc
-                let set_counter_in_another_scope = set_counter_in_use_effect.clone();
-                use_effect_with_deps(
-                    move |_| {
-                        // 1st location
-                        set_counter_in_use_effect(counter + 1);
-                        || {}
-                    },
-                    (),
-                );
-                let another_scope = move || {
-                    if counter < 11 {
-                        // 2nd location
-                        set_counter_in_another_scope(counter + 10)
-                    }
-                };
-                another_scope();
-                return html! {
-                    <div>
-                        {"Test Output: "}
-                        // expected output
-                        <div id="result">{counter}</div>
-                        {"\n"}
-                    </div>
-                };
-            }
-        }
-        type UseComponent = FunctionComponent<UseStateFunction>;
-        let app: App<UseComponent> = yew::App::new();
-        app.mount(yew::utils::document().get_element_by_id("output").unwrap());
-        let result = obtain_result();
-        assert_eq!(result.as_str(), "11");
-    }
-}

+ 11 - 0
packages/html-namespace/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "dioxus-html-namespace"
+version = "0.0.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+
+[dev-dependencies]
+scraper = "0.12.0"

+ 22 - 0
packages/html-namespace/README.md

@@ -0,0 +1,22 @@
+# Html (and SVG) Namespace for Dioxus
+
+The Dioxus `rsx!` and `html!` macros can accept any compile-time correct namespace on top of NodeBuilder. This crate provides the HTML (and SVG) namespaces which get imported in the Dioxus prelude.
+
+However, this abstraction enables you to add any namespace of elements, provided they're in scope when rsx! is called. For an example, a UI that is designed for Augmented Reality might use different primitives than HTML:
+
+```rust
+use ar_namespace::*;
+
+rsx! {
+    magic_div {
+        magic_header {}
+        magic_paragraph {
+            on_magic_click: move |event| {
+                //
+            }
+        }
+    }
+}
+```
+
+This is currently a not-very-explored part of Dioxus. However, the namespacing system does make it possible to provide syntax highlighting, documentation, "go to definition" and compile-time correctness, so it's worth having it abstracted.

+ 2598 - 0
packages/html-namespace/examples/attrlist.html

@@ -0,0 +1,2598 @@
+<tbody>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Attributes/accept">accept</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/form"><code>&lt;form&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"
+        ><code>&lt;input&gt;</code></a
+      >
+    </td>
+    <td>List of types the server accepts, typically a file type.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/form#attr-accept-charset"
+          >accept-charset</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/form"><code>&lt;form&gt;</code></a>
+    </td>
+    <td>List of supported charsets.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/accesskey"
+          >accesskey</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>Keyboard shortcut to activate or add focus to the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/action"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >action</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/form"><code>&lt;form&gt;</code></a>
+    </td>
+    <td>
+      The URI of a program that processes the information submitted via the
+      form.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/align"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >align</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/applet"
+        ><code>&lt;applet&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/caption"
+        ><code>&lt;caption&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/col"><code>&lt;col&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/colgroup"
+        ><code>&lt;colgroup&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/hr"><code>&lt;hr&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/table"><code>&lt;table&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/tbody"><code>&lt;tbody&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/td"><code>&lt;td&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/tfoot"
+        ><code>&lt;tfoot&gt;</code></a
+      >
+      , <a href="/en-US/docs/Web/HTML/Element/th"><code>&lt;th&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/thead"><code>&lt;thead&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/tr"><code>&lt;tr&gt;</code></a>
+    </td>
+    <td>Specifies the horizontal alignment of the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/iframe#attr-allow"
+          >allow</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >
+    </td>
+    <td>Specifies a feature-policy for the iframe.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/alt"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >alt</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/applet"
+        ><code>&lt;applet&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/area"><code>&lt;area&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"
+        ><code>&lt;input&gt;</code></a
+      >
+    </td>
+    <td>Alternative text in case an image can't be displayed.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/script#attr-async"
+          >async</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/script"
+        ><code>&lt;script&gt;</code></a
+      >
+    </td>
+    <td>Executes the script asynchronously.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/autocapitalize"
+          >autocapitalize</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>
+      Sets whether input is automatically capitalized when entered by user
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Attributes/autocomplete"
+          >autocomplete</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/form"><code>&lt;form&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/select"
+        ><code>&lt;select&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>
+      Indicates whether controls in this form can by default have their values
+      automatically completed by the browser.
+    </td>
+  </tr>
+  <tr>
+    <td id="attr-autofocus">
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/autofocus"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >autofocus</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/button"
+        ><code>&lt;button&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/keygen"
+        ><code>&lt;keygen&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/select"
+        ><code>&lt;select&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>The element should be automatically focused after the page loaded.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/autoplay"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >autoplay</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/audio"><code>&lt;audio&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/video"
+        ><code>&lt;video&gt;</code></a
+      >
+    </td>
+    <td>The audio or video should play as soon as possible.</td>
+  </tr>
+  <tr>
+    <td><code>background</code></td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/body"><code>&lt;body&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/table"><code>&lt;table&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/td"><code>&lt;td&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/th"><code>&lt;th&gt;</code></a>
+    </td>
+    <td>
+      Specifies the URL of an image file.
+      <div class="note notecard">
+        <strong>Note:</strong> Although browsers and email clients may still
+        support this attribute, it is obsolete. Use CSS
+        <a href="/en-US/docs/Web/CSS/background-image"
+          ><code>background-image</code></a
+        >
+        instead.
+      </div>
+    </td>
+  </tr>
+  <tr>
+    <td><code>bgcolor</code></td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/body"><code>&lt;body&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/col"><code>&lt;col&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/colgroup"
+        ><code>&lt;colgroup&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/marquee"
+        ><code>&lt;marquee&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/table"><code>&lt;table&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/tbody"><code>&lt;tbody&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/tfoot"><code>&lt;tfoot&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/td"><code>&lt;td&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/th"><code>&lt;th&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/tr"><code>&lt;tr&gt;</code></a>
+    </td>
+    <td>
+      <p>Background color of the element.</p>
+
+      <div class="note notecard">
+        <p>
+          <strong>Note:</strong> This is a legacy attribute. Please use the CSS
+          <a href="/en-US/docs/Web/CSS/background-color"
+            ><code>background-color</code></a
+          >
+          property instead.
+        </p>
+      </div>
+    </td>
+  </tr>
+  <tr>
+    <td><code>border</code></td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/object"
+        ><code>&lt;object&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/table"
+        ><code>&lt;table&gt;</code></a
+      >
+    </td>
+    <td>
+      <p>The border width.</p>
+
+      <div class="note notecard">
+        <p>
+          <strong>Note:</strong> This is a legacy attribute. Please use the CSS
+          <a href="/en-US/docs/Web/CSS/border"><code>border</code></a> property
+          instead.
+        </p>
+      </div>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/buffered"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >buffered</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/audio"><code>&lt;audio&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/video"
+        ><code>&lt;video&gt;</code></a
+      >
+    </td>
+    <td>Contains the time range of already buffered media.</td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Attributes/capture">capture</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"
+        ><code>&lt;input&gt;</code></a
+      >
+    </td>
+    <td>
+      From the
+      <a
+        href="https://w3c.github.io/html-media-capture/#the-capture-attribute"
+        hreflang="en"
+        lang="en"
+        class="external"
+        rel=" noopener"
+        >HTML Media Capture<br /><small lang="en-US"
+          >The definition of 'media capture' in that specification.</small
+        ></a
+      >spec, specifies a new file can be captured.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/keygen#attr-challenge"
+          >challenge</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/keygen"
+        ><code>&lt;keygen&gt;</code></a
+      >
+    </td>
+    <td>A challenge string that is submitted along with the public key.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/charset"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >charset</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/meta"><code>&lt;meta&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/script"
+        ><code>&lt;script&gt;</code></a
+      >
+    </td>
+    <td>Declares the character encoding of the page or script.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/checked"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >checked</a
+        ></code
+      >
+    </td>
+    <td>
+      <a
+        href="/en-US/docs/Web/HTML/Element/command"
+        class="page-not-created"
+        title="This is a link to an unwritten page"
+        ><code>&lt;command&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"
+        ><code>&lt;input&gt;</code></a
+      >
+    </td>
+    <td>Indicates whether the element should be checked on page load.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/cite"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >cite</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/blockquote"
+        ><code>&lt;blockquote&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/del"><code>&lt;del&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/ins"><code>&lt;ins&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/q"><code>&lt;q&gt;</code></a>
+    </td>
+    <td>Contains a URI which points to the source of the quote or change.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/class">class</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>Often used with CSS to style elements with common properties.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/applet#attr-code">code</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/applet"
+        ><code>&lt;applet&gt;</code></a
+      >
+    </td>
+    <td>
+      Specifies the URL of the applet's class file to be loaded and executed.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/applet#attr-codebase"
+          >codebase</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/applet"
+        ><code>&lt;applet&gt;</code></a
+      >
+    </td>
+    <td>
+      This attribute gives the absolute or relative URL of the directory where
+      applets' .class files referenced by the code attribute are stored.
+    </td>
+  </tr>
+  <tr>
+    <td><code>color</code></td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/basefont"
+        ><code>&lt;basefont&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/font"><code>&lt;font&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/hr"><code>&lt;hr&gt;</code></a>
+    </td>
+    <td>
+      <p>
+        This attribute sets the text color using either a named color or a color
+        specified in the hexadecimal #RRGGBB format.
+      </p>
+
+      <div class="note notecard">
+        <p>
+          <strong>Note:</strong> This is a legacy attribute. Please use the CSS
+          <a href="/en-US/docs/Web/CSS/color"><code>color</code></a> property
+          instead.
+        </p>
+      </div>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/textarea#attr-cols"
+          >cols</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>Defines the number of columns in a textarea.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/colspan"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >colspan</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/td"><code>&lt;td&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/th"><code>&lt;th&gt;</code></a>
+    </td>
+    <td>
+      The colspan attribute defines the number of columns a cell should span.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/meta#attr-content"
+          >content</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/meta"><code>&lt;meta&gt;</code></a>
+    </td>
+    <td>
+      A value associated with <code>http-equiv</code> or
+      <code>name</code> depending on the context.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/contenteditable"
+          >contenteditable</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>Indicates whether the element's content is editable.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/contextmenu"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >contextmenu</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>
+      Defines the ID of a
+      <a href="/en-US/docs/Web/HTML/Element/menu"><code>&lt;menu&gt;</code></a>
+      element which will serve as the element's context menu.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/controls"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >controls</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/audio"><code>&lt;audio&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/video"
+        ><code>&lt;video&gt;</code></a
+      >
+    </td>
+    <td>
+      Indicates whether the browser should show playback controls to the user.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/area#attr-coords"
+          >coords</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/area"><code>&lt;area&gt;</code></a>
+    </td>
+    <td>A set of values specifying the coordinates of the hot-spot region.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Attributes/crossorigin"
+          >crossorigin</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/audio"><code>&lt;audio&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/link"><code>&lt;link&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/script"
+        ><code>&lt;script&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/video"
+        ><code>&lt;video&gt;</code></a
+      >
+    </td>
+    <td>How the element handles cross-origin requests</td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/API/HTMLIFrameElement/csp">csp</a></code>
+      <svg class="icon icon-experimental" tabindex="0">
+        <use xlink:href="/assets/badges.svg#icon-experimental"></use>
+      </svg>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >
+    </td>
+    <td>
+      Specifies the Content Security Policy that an embedded document must agree
+      to enforce upon itself.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/object#attr-data">data</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/object"
+        ><code>&lt;object&gt;</code></a
+      >
+    </td>
+    <td>Specifies the URL of the resource.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/data-*"
+          >data-*</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>Lets you attach custom attributes to an HTML element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/datetime"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >datetime</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/del"><code>&lt;del&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/ins"><code>&lt;ins&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/time"><code>&lt;time&gt;</code></a>
+    </td>
+    <td>Indicates the date and time associated with the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/img#attr-decoding"
+          >decoding</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a>
+    </td>
+    <td>Indicates the preferred method to decode the image.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/track#attr-default"
+          >default</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/track"
+        ><code>&lt;track&gt;</code></a
+      >
+    </td>
+    <td>
+      Indicates that the track should be enabled unless the user's preferences
+      indicate something different.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/script#attr-defer"
+          >defer</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/script"
+        ><code>&lt;script&gt;</code></a
+      >
+    </td>
+    <td>
+      Indicates that the script should be executed after the page has been
+      parsed.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Global_attributes/dir">dir</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>
+      Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl
+      (Right-To-Left)
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/dirname"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >dirname</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Attributes/disabled">disabled</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/button"
+        ><code>&lt;button&gt;</code></a
+      >,
+      <a
+        href="/en-US/docs/Web/HTML/Element/command"
+        class="page-not-created"
+        title="This is a link to an unwritten page"
+        ><code>&lt;command&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/fieldset"
+        ><code>&lt;fieldset&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/keygen"
+        ><code>&lt;keygen&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/optgroup"
+        ><code>&lt;optgroup&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/option"
+        ><code>&lt;option&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/select"
+        ><code>&lt;select&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>Indicates whether the user can interact with the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/download"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >download</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/a"><code>&lt;a&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/area"><code>&lt;area&gt;</code></a>
+    </td>
+    <td>
+      Indicates that the hyperlink is to be used for downloading a resource.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/draggable"
+          >draggable</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>Defines whether the element can be dragged.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/form#attr-enctype"
+          >enctype</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/form"><code>&lt;form&gt;</code></a>
+    </td>
+    <td>
+      Defines the content type of the form data when the <code>method</code> is
+      POST.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/enterkeyhint"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >enterkeyhint</a
+        ></code
+      >
+      <svg class="icon icon-experimental" tabindex="0">
+        <use xlink:href="/assets/badges.svg#icon-experimental"></use>
+      </svg>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Global_attributes/contenteditable"
+        ><code>contenteditable</code></a
+      >
+    </td>
+    <td>
+      The
+      <a
+        href="https://html.spec.whatwg.org/dev/interaction.html#input-modalities:-the-enterkeyhint-attribute"
+        class="external"
+        rel=" noopener"
+        ><code>enterkeyhint</code></a
+      >
+      specifies what action label (or icon) to present for the enter key on
+      virtual keyboards. The attribute can be used with form controls (such as
+      the value of <code>textarea</code> elements), or in elements in an editing
+      host (e.g., using <code>contenteditable</code> attribute).
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Attributes/for">for</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/label"><code>&lt;label&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/output"
+        ><code>&lt;output&gt;</code></a
+      >
+    </td>
+    <td>Describes elements which belongs to this one.</td>
+  </tr>
+  <tr>
+    <td id="attr-form">
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/form"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >form</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/button"
+        ><code>&lt;button&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/fieldset"
+        ><code>&lt;fieldset&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/keygen"
+        ><code>&lt;keygen&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/label"><code>&lt;label&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/meter"><code>&lt;meter&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/object"
+        ><code>&lt;object&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/output"
+        ><code>&lt;output&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/progress"
+        ><code>&lt;progress&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/select"
+        ><code>&lt;select&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>Indicates the form that is the owner of the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/formaction"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >formaction</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/button"
+        ><code>&lt;button&gt;</code></a
+      >
+    </td>
+    <td>
+      Indicates the action of the element, overriding the action defined in the
+      <a href="/en-US/docs/Web/HTML/Element/form"><code>&lt;form&gt;</code></a
+      >.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/formenctype"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >formenctype</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/button"
+        ><code>&lt;button&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"
+        ><code>&lt;input&gt;</code></a
+      >
+    </td>
+    <td>
+      If the button/input is a submit button (<code>type="submit"</code>), this
+      attribute sets the encoding type to use during form submission. If this
+      attribute is specified, it overrides the <code>enctype</code> attribute of
+      the button's <a href="/en-US/docs/Web/HTML/Element/form">form</a> owner.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/formmethod"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >formmethod</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/button"
+        ><code>&lt;button&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"
+        ><code>&lt;input&gt;</code></a
+      >
+    </td>
+    <td>
+      If the button/input is a submit button (<code>type="submit"</code>), this
+      attribute sets the submission method to use during form submission
+      (<code>GET</code>, <code>POST</code>, etc.). If this attribute is
+      specified, it overrides the <code>method</code> attribute of the button's
+      <a href="/en-US/docs/Web/HTML/Element/form">form</a> owner.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/formnovalidate"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >formnovalidate</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/button"
+        ><code>&lt;button&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"
+        ><code>&lt;input&gt;</code></a
+      >
+    </td>
+    <td>
+      If the button/input is a submit button (<code>type="submit"</code>), this
+      boolean attribute specifies that the form is not to be validated when it
+      is submitted. If this attribute is specified, it overrides the
+      <code>novalidate</code> attribute of the button's
+      <a href="/en-US/docs/Web/HTML/Element/form">form</a> owner.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/formtarget"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >formtarget</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/button"
+        ><code>&lt;button&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"
+        ><code>&lt;input&gt;</code></a
+      >
+    </td>
+    <td>
+      If the button/input is a submit button (<code>type="submit"</code>), this
+      attribute specifies the browsing context (for example, tab, window, or
+      inline frame) in which to display the response that is received after
+      submitting the form. If this attribute is specified, it overrides the
+      <code>target</code> attribute of the button's
+      <a href="/en-US/docs/Web/HTML/Element/form">form</a> owner.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/headers"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >headers</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/td"><code>&lt;td&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/th"><code>&lt;th&gt;</code></a>
+    </td>
+    <td>
+      IDs of the <code>&lt;th&gt;</code> elements which applies to this element.
+    </td>
+  </tr>
+  <tr>
+    <td><code>height</code></td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/canvas"
+        ><code>&lt;canvas&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/embed"><code>&lt;embed&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/object"
+        ><code>&lt;object&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/video"
+        ><code>&lt;video&gt;</code></a
+      >
+    </td>
+    <td>
+      <p>
+        Specifies the height of elements listed here. For all other elements,
+        use the CSS
+        <a href="/en-US/docs/Web/CSS/height"><code>height</code></a> property.
+      </p>
+
+      <div class="note notecard">
+        <p>
+          <strong>Note:</strong> In some instances, such as
+          <a href="/en-US/docs/Web/HTML/Element/div"><code>&lt;div&gt;</code></a
+          >, this is a legacy attribute, in which case the CSS
+          <a href="/en-US/docs/Web/CSS/height"><code>height</code></a> property
+          should be used instead.
+        </p>
+      </div>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/hidden"
+          >hidden</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>
+      Prevents rendering of given element, while keeping child elements, e.g.
+      script elements, active.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/meter#attr-high">high</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/meter"
+        ><code>&lt;meter&gt;</code></a
+      >
+    </td>
+    <td>Indicates the lower bound of the upper range.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/href"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >href</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/a"><code>&lt;a&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/area"><code>&lt;area&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/base"><code>&lt;base&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/link"><code>&lt;link&gt;</code></a>
+    </td>
+    <td>The URL of a linked resource.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/hreflang"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >hreflang</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/a"><code>&lt;a&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/area"><code>&lt;area&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/link"><code>&lt;link&gt;</code></a>
+    </td>
+    <td>Specifies the language of the linked resource.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/meta#attr-http-equiv"
+          >http-equiv</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/meta"><code>&lt;meta&gt;</code></a>
+    </td>
+    <td>Defines a pragma directive.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Element/command#attr-icon"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >icon</a
+        ></code
+      >
+    </td>
+    <td>
+      <a
+        href="/en-US/docs/Web/HTML/Element/command"
+        class="page-not-created"
+        title="This is a link to an unwritten page"
+        ><code>&lt;command&gt;</code></a
+      >
+    </td>
+    <td>Specifies a picture which represents the command.</td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Global_attributes/id">id</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>
+      Often used with CSS to style a specific element. The value of this
+      attribute must be unique.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/importance"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >importance</a
+        ></code
+      >
+      <svg class="icon icon-experimental" tabindex="0">
+        <use xlink:href="/assets/badges.svg#icon-experimental"></use>
+      </svg>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/link"><code>&lt;link&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/script"
+        ><code>&lt;script&gt;</code></a
+      >
+    </td>
+    <td>Indicates the relative fetch priority for the resource.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/Security/Subresource_Integrity"
+          >integrity</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/link"><code>&lt;link&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/script"
+        ><code>&lt;script&gt;</code></a
+      >
+    </td>
+    <td>
+      <p>
+        Specifies a
+        <a href="/en-US/docs/Web/Security/Subresource_Integrity"
+          >Subresource Integrity</a
+        >
+        value that allows browsers to verify what they fetch.
+      </p>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/img#attr-intrinsicsize"
+        ><code>intrinsicsize</code></a
+      >
+      <svg class="icon icon-deprecated" tabindex="0">
+        <use xlink:href="/assets/badges.svg#icon-deprecated"></use>
+      </svg>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a>
+    </td>
+    <td>
+      This attribute tells the browser to ignore the actual intrinsic size of
+      the image and pretend it’s the size specified in the attribute.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes/inputmode"
+        ><code>inputmode</code></a
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Global_attributes/contenteditable"
+        ><code>contenteditable</code></a
+      >
+    </td>
+    <td>
+      Provides a hint as to the type of data that might be entered by the user
+      while editing the element or its contents. The attribute can be used with
+      form controls (such as the value of <code>textarea</code> elements), or in
+      elements in an editing host (e.g., using
+      <code>contenteditable</code> attribute).
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/img#attr-ismap">ismap</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a>
+    </td>
+    <td>Indicates that the image is part of a server-side image map.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/itemprop"
+          >itemprop</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/keygen#attr-keytype"
+          >keytype</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/keygen"
+        ><code>&lt;keygen&gt;</code></a
+      >
+    </td>
+    <td>Specifies the type of key generated.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/track#attr-kind">kind</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/track"
+        ><code>&lt;track&gt;</code></a
+      >
+    </td>
+    <td>Specifies the kind of text track.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/label"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >label</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/optgroup"
+        ><code>&lt;optgroup&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/option"
+        ><code>&lt;option&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/track"
+        ><code>&lt;track&gt;</code></a
+      >
+    </td>
+    <td>Specifies a user-readable title of the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/lang">lang</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>Defines the language used in the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/script#attr-language"
+          >language</a
+        ></code
+      >
+      <svg class="icon icon-deprecated" tabindex="0">
+        <use xlink:href="/assets/badges.svg#icon-deprecated"></use>
+      </svg>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/script"
+        ><code>&lt;script&gt;</code></a
+      >
+    </td>
+    <td>Defines the script language used in the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code>loading</code>
+      <svg class="icon icon-experimental" tabindex="0">
+        <use xlink:href="/assets/badges.svg#icon-experimental"></use>
+      </svg>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >
+    </td>
+    <td>
+      Indicates if the element should be loaded lazily
+      (<code>loading="lazy"</code>) or loaded immediately
+      (<code>loading="eager"</code>).
+      <div class="note notecard">
+        <strong>WIP:</strong>
+        <a
+          href="https://github.com/whatwg/html/pull/3752"
+          class="external"
+          rel=" noopener"
+          >WHATWG PR #3752</a
+        >
+      </div>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/input#attr-list">list</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"
+        ><code>&lt;input&gt;</code></a
+      >
+    </td>
+    <td>Identifies a list of pre-defined options to suggest to the user.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/loop"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >loop</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/audio"><code>&lt;audio&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/bgsound"
+        ><code>&lt;bgsound&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/marquee"
+        ><code>&lt;marquee&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/video"
+        ><code>&lt;video&gt;</code></a
+      >
+    </td>
+    <td>
+      Indicates whether the media should start playing from the start when it's
+      finished.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Element/meter#attr-low">low</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/meter"
+        ><code>&lt;meter&gt;</code></a
+      >
+    </td>
+    <td>Indicates the upper bound of the lower range.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/html#attr-manifest"
+          >manifest</a
+        ></code
+      >
+      <svg class="icon icon-deprecated" tabindex="0">
+        <use xlink:href="/assets/badges.svg#icon-deprecated"></use>
+      </svg>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/html"><code>&lt;html&gt;</code></a>
+    </td>
+    <td>
+      Specifies the URL of the document's cache manifest.
+      <div class="note notecard">
+        <strong>Note:</strong> This attribute is obsolete, use
+        <a href="/en-US/docs/Web/Manifest"
+          ><code>&lt;link rel="manifest"&gt;</code></a
+        >
+        instead.
+      </div>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Attributes/max">max</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/meter"><code>&lt;meter&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/progress"
+        ><code>&lt;progress&gt;</code></a
+      >
+    </td>
+    <td>Indicates the maximum value allowed.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Attributes/maxlength">maxlength</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>Defines the maximum number of characters allowed in the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Attributes/minlength">minlength</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>Defines the minimum number of characters allowed in the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/media"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >media</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/a"><code>&lt;a&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/area"><code>&lt;area&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/link"><code>&lt;link&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/source"
+        ><code>&lt;source&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/style"
+        ><code>&lt;style&gt;</code></a
+      >
+    </td>
+    <td>
+      Specifies a hint of the media for which the linked resource was designed.
+    </td>
+  </tr>
+  <tr>
+    <td><a href="/en-US/docs/Web/HTML/Element/form#attr-method">method</a></td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/form"><code>&lt;form&gt;</code></a>
+    </td>
+    <td>
+      Defines which <a href="/en-US/docs/Web/HTTP">HTTP</a> method to use when
+      submitting the form. Can be <code>GET</code> (default) or
+      <code>POST</code>.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Attributes/min">min</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/meter"
+        ><code>&lt;meter&gt;</code></a
+      >
+    </td>
+    <td>Indicates the minimum value allowed.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Attributes/multiple">multiple</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/select"
+        ><code>&lt;select&gt;</code></a
+      >
+    </td>
+    <td>
+      Indicates whether multiple values can be entered in an input of the type
+      <code>email</code> or <code>file</code>.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/muted"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >muted</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/audio"><code>&lt;audio&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/video"
+        ><code>&lt;video&gt;</code></a
+      >
+    </td>
+    <td>
+      Indicates whether the audio will be initially silenced on page load.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/name"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >name</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/button"
+        ><code>&lt;button&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/form"><code>&lt;form&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/fieldset"
+        ><code>&lt;fieldset&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/keygen"
+        ><code>&lt;keygen&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/object"
+        ><code>&lt;object&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/output"
+        ><code>&lt;output&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/select"
+        ><code>&lt;select&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/map"><code>&lt;map&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/meta"><code>&lt;meta&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/param"
+        ><code>&lt;param&gt;</code></a
+      >
+    </td>
+    <td>
+      Name of the element. For example used by the server to identify the fields
+      in form submits.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/form#attr-novalidate"
+          >novalidate</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/form"><code>&lt;form&gt;</code></a>
+    </td>
+    <td>
+      This attribute indicates that the form shouldn't be validated when
+      submitted.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/details#attr-open">open</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/details"
+        ><code>&lt;details&gt;</code></a
+      >
+    </td>
+    <td>Indicates whether the details will be shown on page load.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/meter#attr-optimum"
+          >optimum</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/meter"
+        ><code>&lt;meter&gt;</code></a
+      >
+    </td>
+    <td>Indicates the optimal numeric value.</td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Attributes/pattern">pattern</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"
+        ><code>&lt;input&gt;</code></a
+      >
+    </td>
+    <td>
+      Defines a regular expression which the element's value will be validated
+      against.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Element/a#attr-ping">ping</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/a"><code>&lt;a&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/area"><code>&lt;area&gt;</code></a>
+    </td>
+    <td>
+      The <code>ping</code> attribute specifies a space-separated list of URLs
+      to be notified if a user follows the hyperlink.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/placeholder"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >placeholder</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>Provides a hint to the user of what can be entered in the field.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/video#attr-poster"
+          >poster</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/video"
+        ><code>&lt;video&gt;</code></a
+      >
+    </td>
+    <td>
+      A URL indicating a poster frame to show until the user plays or seeks.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/preload"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >preload</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/audio"><code>&lt;audio&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/video"
+        ><code>&lt;video&gt;</code></a
+      >
+    </td>
+    <td>
+      Indicates whether the whole resource, parts of it or nothing should be
+      preloaded.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Element/command#attr-radiogroup"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >radiogroup</a
+        ></code
+      >
+    </td>
+    <td>
+      <a
+        href="/en-US/docs/Web/HTML/Element/command"
+        class="page-not-created"
+        title="This is a link to an unwritten page"
+        ><code>&lt;command&gt;</code></a
+      >
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Attributes/readonly">readonly</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>Indicates whether the element can be edited.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/referralpolicy"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >referrerpolicy</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/a"><code>&lt;a&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/area"><code>&lt;area&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/link"><code>&lt;link&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/script"
+        ><code>&lt;script&gt;</code></a
+      >
+    </td>
+    <td>Specifies which referrer is sent when fetching the resource.</td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Attributes/rel">rel</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/a"><code>&lt;a&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/area"><code>&lt;area&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/link"><code>&lt;link&gt;</code></a>
+    </td>
+    <td>Specifies the relationship of the target object to the link object.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Attributes/required">required</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/select"
+        ><code>&lt;select&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>Indicates whether this element is required to fill out or not.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/ol#attr-reversed"
+          >reversed</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/ol"><code>&lt;ol&gt;</code></a>
+    </td>
+    <td>
+      Indicates whether the list should be displayed in a descending order
+      instead of a ascending.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/textarea#attr-rows"
+          >rows</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>Defines the number of rows in a text area.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/rowspan"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >rowspan</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/td"><code>&lt;td&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/th"><code>&lt;th&gt;</code></a>
+    </td>
+    <td>Defines the number of rows a table cell should span over.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/iframe#attr-sandbox"
+          >sandbox</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >
+    </td>
+    <td>
+      Stops a document loaded in an iframe from using certain features (such as
+      submitting forms or opening new windows).
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/th#attr-scope">scope</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/th"><code>&lt;th&gt;</code></a>
+    </td>
+    <td>
+      Defines the cells that the header test (defined in the
+      <code>th</code> element) relates to.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/style#attr-scoped"
+          >scoped</a
+        ></code
+      >
+      <svg class="icon icon-nonstandard" tabindex="0">
+        <use xlink:href="/assets/badges.svg#icon-nonstandard"></use>
+      </svg>
+      <svg class="icon icon-deprecated" tabindex="0">
+        <use xlink:href="/assets/badges.svg#icon-deprecated"></use>
+      </svg>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/style"
+        ><code>&lt;style&gt;</code></a
+      >
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/option#attr-selected"
+          >selected</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/option"
+        ><code>&lt;option&gt;</code></a
+      >
+    </td>
+    <td>Defines a value which will be selected on page load.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/shape"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >shape</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/a"><code>&lt;a&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/area"><code>&lt;area&gt;</code></a>
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Attributes/size">size</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/select"
+        ><code>&lt;select&gt;</code></a
+      >
+    </td>
+    <td>
+      Defines the width of the element (in pixels). If the element's
+      <code>type</code> attribute is <code>text</code> or
+      <code>password</code> then it's the number of characters.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/sizes"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >sizes</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/link"><code>&lt;link&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/source"
+        ><code>&lt;source&gt;</code></a
+      >
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/slot">slot</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>Assigns a slot in a shadow DOM shadow tree to an element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/span"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >span</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/col"><code>&lt;col&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/colgroup"
+        ><code>&lt;colgroup&gt;</code></a
+      >
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/spellcheck"
+          >spellcheck</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>Indicates whether spell checking is allowed for the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/src"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >src</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/audio"><code>&lt;audio&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/embed"><code>&lt;embed&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/script"
+        ><code>&lt;script&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/source"
+        ><code>&lt;source&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/track"><code>&lt;track&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/video"
+        ><code>&lt;video&gt;</code></a
+      >
+    </td>
+    <td>The URL of the embeddable content.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/iframe#attr-srcdoc"
+          >srcdoc</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/track#attr-srclang"
+          >srclang</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/track"
+        ><code>&lt;track&gt;</code></a
+      >
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/srcset"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >srcset</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/source"
+        ><code>&lt;source&gt;</code></a
+      >
+    </td>
+    <td>One or more responsive image candidates.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/ol#attr-start">start</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/ol"><code>&lt;ol&gt;</code></a>
+    </td>
+    <td>Defines the first number if other than 1.</td>
+  </tr>
+  <tr>
+    <td>
+      <code><a href="/en-US/docs/Web/HTML/Attributes/step">step</a></code>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/input"
+        ><code>&lt;input&gt;</code></a
+      >
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/style">style</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>Defines CSS styles which will override styles previously set.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/table#attr-summary"
+          >summary</a
+        ></code
+      >
+      <svg class="icon icon-deprecated" tabindex="0">
+        <use xlink:href="/assets/badges.svg#icon-deprecated"></use>
+      </svg>
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/table"
+        ><code>&lt;table&gt;</code></a
+      >
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/tabindex"
+          >tabindex</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>
+      Overrides the browser's default tab order and follows the one specified
+      instead.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/target"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >target</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/a"><code>&lt;a&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/area"><code>&lt;area&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/base"><code>&lt;base&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/form"><code>&lt;form&gt;</code></a>
+    </td>
+    <td>
+      Specifies where to open the linked document (in the case of an
+      <code>&lt;a&gt;</code> element) or where to display the response received
+      (in the case of a <code>&lt;form&gt;</code> element)
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/title">title</a></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>Text to be displayed in a tooltip when hovering over the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Global_attributes/translate"
+          >translate</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Global_attributes">Global attribute</a>
+    </td>
+    <td>
+      Specify whether an element’s attribute values and the values of its
+      <code
+        ><a
+          href="https://dom.spec.whatwg.org/#text"
+          id="ref-for-text①⑦"
+          class="external"
+          rel=" noopener"
+          >Text</a
+        ></code
+      >
+      node children are to be translated when the page is localized, or whether
+      to leave them unchanged.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/type"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >type</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/button"
+        ><code>&lt;button&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a
+        href="/en-US/docs/Web/HTML/Element/command"
+        class="page-not-created"
+        title="This is a link to an unwritten page"
+        ><code>&lt;command&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/embed"><code>&lt;embed&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/object"
+        ><code>&lt;object&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/script"
+        ><code>&lt;script&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/source"
+        ><code>&lt;source&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/style"><code>&lt;style&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/menu"><code>&lt;menu&gt;</code></a>
+    </td>
+    <td>Defines the type of the element.</td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/usemap"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >usemap</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/object"
+        ><code>&lt;object&gt;</code></a
+      >
+    </td>
+    <td></td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/value"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >value</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/button"
+        ><code>&lt;button&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/data"><code>&lt;data&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/li"><code>&lt;li&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/meter"><code>&lt;meter&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/option"
+        ><code>&lt;option&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/progress"
+        ><code>&lt;progress&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/param"
+        ><code>&lt;param&gt;</code></a
+      >
+    </td>
+    <td>
+      Defines a default value which will be displayed in the element on page
+      load.
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a
+          href="/en-US/docs/Web/HTML/Attributes/width"
+          class="page-not-created"
+          title="This is a link to an unwritten page"
+          >width</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/canvas"
+        ><code>&lt;canvas&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/embed"><code>&lt;embed&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/iframe"
+        ><code>&lt;iframe&gt;</code></a
+      >, <a href="/en-US/docs/Web/HTML/Element/img"><code>&lt;img&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/input"><code>&lt;input&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/object"
+        ><code>&lt;object&gt;</code></a
+      >,
+      <a href="/en-US/docs/Web/HTML/Element/video"
+        ><code>&lt;video&gt;</code></a
+      >
+    </td>
+    <td>
+      <p>For the elements listed here, this establishes the element's width.</p>
+
+      <div class="note notecard">
+        <p>
+          <strong>Note:</strong> For all other instances, such as
+          <a href="/en-US/docs/Web/HTML/Element/div"><code>&lt;div&gt;</code></a
+          >, this is a legacy attribute, in which case the CSS
+          <a href="/en-US/docs/Web/CSS/width"><code>width</code></a> property
+          should be used instead.
+        </p>
+      </div>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <code
+        ><a href="/en-US/docs/Web/HTML/Element/textarea#attr-wrap"
+          >wrap</a
+        ></code
+      >
+    </td>
+    <td>
+      <a href="/en-US/docs/Web/HTML/Element/textarea"
+        ><code>&lt;textarea&gt;</code></a
+      >
+    </td>
+    <td>Indicates whether the text should be wrapped.</td>
+  </tr>
+</tbody>

+ 42 - 0
packages/html-namespace/examples/namespace.rs

@@ -0,0 +1,42 @@
+use scraper::{Html, Selector};
+
+struct AttrClass {
+    attr_name: String,
+    attr_doc_link: String,
+    target_elements: Vec<String>,
+    docs: String,
+}
+
+const contents: &str = "";
+// let contents = include_str!("./attrlist.html");
+fn main() {
+    let mut items: Vec<AttrClass> = Vec::new();
+
+    let fragment = Html::parse_fragment(contents);
+
+    let ul_selector = Selector::parse("tbody").unwrap();
+    let li_selector = Selector::parse("tr").unwrap();
+
+    let ul = fragment.select(&ul_selector).next().unwrap();
+    for element in ul.select(&li_selector) {
+        let mut childs = element.children().into_iter();
+
+        let attr_field_node = childs.next().unwrap();
+        let elements_node = childs.next().unwrap();
+        let description_node = childs.next().unwrap();
+
+        // let attr_name = { todo!() };
+        // let attr_doc_link = { todo!() };
+        // let target_elements = { todo!() };
+
+        // let docs = description_node.text();
+
+        // todo!()
+        // items.push(AttrClass {
+        //     attr_name,
+        //     attr_doc_link,
+        //     target_elements,
+        //     docs,
+        // })
+    }
+}

+ 627 - 0
packages/html-namespace/src/lib.rs

@@ -0,0 +1,627 @@
+trait DioxusElement {
+    const TAG_NAME: &'static str;
+    const NAME_SPACE: Option<&'static str>;
+}
+
+struct myinput {}
+
+struct NodeBuilder {}
+impl NodeBuilder {
+    // fn add_attr()
+}
+
+macro_rules! builder_constructors {
+    ( $(
+        $(#[$attr:meta])*
+        $name:ident;
+        // {
+            // attrs: [
+            //     $(
+            //         $(#[$attr2:meta])*
+            //         $attr3:ident
+            //         ,
+            //     )*
+            // ];
+        // }
+    )* ) => {
+        $(
+            #[allow(non_camel_case_types)]
+            $(#[$attr])*
+            pub struct $name<'a> {
+                // the we wrap the builder, shielding what can be added
+                builder: &'a NodeBuilder
+            }
+            impl<'a> DioxusElement for $name<'a> {
+                const TAG_NAME: &'static str = stringify!($name);
+                const NAME_SPACE: Option<&'static str> = None;
+            }
+        )*
+    };
+
+    ( $(
+        $(#[$attr:meta])*
+        $name:ident <> $namespace:tt;
+    )* ) => {};
+}
+
+// Organized in the same order as
+// https://developer.mozilla.org/en-US/docs/Web/HTML/Element
+//
+// Does not include obsolete elements.
+builder_constructors! {
+    // Document metadata
+
+    /// Build a
+    /// [`<base>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
+    /// element.
+    ///
+    /// A base element is your mom!
+    base;
+
+    /// Build a
+    /// [`<head>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)
+    /// element.
+    head;
+    /// Build a
+    /// [`<link>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
+    /// element.
+    link;
+    /// Build a
+    /// [`<meta>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta)
+    /// element.
+    meta;
+    /// Build a
+    /// [`<style>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style)
+    /// element.
+    style;
+    /// Build a
+    /// [`<title>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title)
+    /// element.
+    title;
+
+    // Sectioning root
+
+    /// Build a
+    /// [`<body>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body)
+    /// element.
+    body;
+
+    // Content sectioning
+
+    /// Build a
+    /// [`<address>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address)
+    /// element.
+    address;
+    /// Build a
+    /// [`<article>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article)
+    /// element.
+    article;
+    /// Build a
+    /// [`<aside>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside)
+    /// element.
+    aside;
+    /// Build a
+    /// [`<footer>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer)
+    /// element.
+    footer;
+    /// Build a
+    /// [`<header>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header)
+    /// element.
+    header;
+
+    /// Build a
+    /// [`<h1>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1)
+    /// element.
+    h1;
+
+    /// Build a
+    /// [`<h2>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h2)
+    /// element.
+    h2;
+    /// Build a
+    /// [`<h3>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h3)
+    /// element.
+    h3;
+    /// Build a
+    /// [`<h4>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4)
+    /// element.
+    h4;
+    /// Build a
+    /// [`<h5>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5)
+    /// element.
+    h5;
+    /// Build a
+    /// [`<h6>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6)
+    /// element.
+    h6;
+    /// Build a
+    /// [`<hgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup)
+    /// element.
+    hgroup;
+    /// Build a
+    /// [`<main>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main)
+    /// element.
+    main;
+    /// Build a
+    /// [`<nav>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)
+    /// element.
+    nav;
+    /// Build a
+    /// [`<section>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section)
+    /// element.
+    section;
+
+    // Text content
+
+    /// Build a
+    /// [`<blockquote>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote)
+    /// element.
+    blockquote;
+    /// Build a
+    /// [`<dd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd)
+    /// element.
+    dd;
+    /// Build a
+    /// [`<div>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div)
+    /// element.
+    div;
+    /// Build a
+    /// [`<dl>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl)
+    /// element.
+    dl;
+    /// Build a
+    /// [`<dt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt)
+    /// element.
+    dt;
+    /// Build a
+    /// [`<figcaption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption)
+    /// element.
+    figcaption;
+    /// Build a
+    /// [`<figure>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure)
+    /// element.
+    figure;
+    /// Build a
+    /// [`<hr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr)
+    /// element.
+    hr;
+    /// Build a
+    /// [`<li>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li)
+    /// element.
+    li;
+    /// Build a
+    /// [`<ol>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol)
+    /// element.
+    ol;
+    /// Build a
+    /// [`<p>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p)
+    /// element.
+    p;
+    /// Build a
+    /// [`<pre>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre)
+    /// element.
+    pre;
+    /// Build a
+    /// [`<ul>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul)
+    /// element.
+    ul;
+
+    // Inline text semantics
+
+    /// Build a
+    /// [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
+    /// element.
+    a;
+    /// Build a
+    /// [`<abbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr)
+    /// element.
+    abbr;
+    /// Build a
+    /// [`<b>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b)
+    /// element.
+    b;
+    /// Build a
+    /// [`<bdi>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi)
+    /// element.
+    bdi;
+    /// Build a
+    /// [`<bdo>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo)
+    /// element.
+    bdo;
+    /// Build a
+    /// [`<br>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br)
+    /// element.
+    br;
+    /// Build a
+    /// [`<cite>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite)
+    /// element.
+    cite;
+    /// Build a
+    /// [`<code>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code)
+    /// element.
+    code;
+    /// Build a
+    /// [`<data>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data)
+    /// element.
+    data;
+    /// Build a
+    /// [`<dfn>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dfn)
+    /// element.
+    dfn;
+    /// Build a
+    /// [`<em>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em)
+    /// element.
+    em;
+    /// Build a
+    /// [`<i>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i)
+    /// element.
+    i;
+    /// Build a
+    /// [`<kbd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd)
+    /// element.
+    kbd;
+    /// Build a
+    /// [`<mark>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark)
+    /// element.
+    mark;
+    /// Build a
+    /// [`<q>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q)
+    /// element.
+    q;
+    /// Build a
+    /// [`<rb>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rb)
+    /// element.
+    rb;
+    /// Build a
+    /// [`<rp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rp)
+    /// element.
+    rp;
+    /// Build a
+    /// [`<rt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt)
+    /// element.
+    rt;
+    /// Build a
+    /// [`<rtc>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rtc)
+    /// element.
+    rtc;
+    /// Build a
+    /// [`<ruby>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby)
+    /// element.
+    ruby;
+    /// Build a
+    /// [`<s>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s)
+    /// element.
+    s;
+    /// Build a
+    /// [`<samp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp)
+    /// element.
+    samp;
+    /// Build a
+    /// [`<small>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small)
+    /// element.
+    small;
+    /// Build a
+    /// [`<span>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span)
+    /// element.
+    span;
+    /// Build a
+    /// [`<strong>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong)
+    /// element.
+    strong;
+    /// Build a
+    /// [`<sub>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub)
+    /// element.
+    sub;
+    /// Build a
+    /// [`<sup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup)
+    /// element.
+    sup;
+    /// Build a
+    /// [`<time>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time)
+    /// element.
+    time;
+    /// Build a
+    /// [`<u>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u)
+    /// element.
+    u;
+    /// Build a
+    /// [`<var>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var)
+    /// element.
+    var;
+    /// Build a
+    /// [`<wbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr)
+    /// element.
+    wbr;
+
+    // Image and multimedia
+
+    /// Build a
+    /// [`<area>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area)
+    /// element.
+    area;
+    /// Build a
+    /// [`<audio>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio)
+    /// element.
+    audio;
+    /// Build a
+    /// [`<img>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img)
+    /// element.
+    img;
+    /// Build a
+    /// [`<map>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map)
+    /// element.
+    map;
+    /// Build a
+    /// [`<track>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track)
+    /// element.
+    track;
+    /// Build a
+    /// [`<video>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video)
+    /// element.
+    video;
+
+    // Embedded content
+
+    /// Build a
+    /// [`<embed>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed)
+    /// element.
+    embed;
+    /// Build a
+    /// [`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)
+    /// element.
+    iframe;
+    /// Build a
+    /// [`<object>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object)
+    /// element.
+    object;
+    /// Build a
+    /// [`<param>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/param)
+    /// element.
+    param;
+    /// Build a
+    /// [`<picture>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture)
+    /// element.
+    picture;
+    /// Build a
+    /// [`<source>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source)
+    /// element.
+    source;
+
+    // Scripting
+
+    /// Build a
+    /// [`<canvas>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas)
+    /// element.
+    canvas;
+    /// Build a
+    /// [`<noscript>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript)
+    /// element.
+    noscript;
+    /// Build a
+    /// [`<script>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)
+    /// element.
+    script;
+
+    // Demarcating edits
+
+    /// Build a
+    /// [`<del>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del)
+    /// element.
+    del;
+    /// Build a
+    /// [`<ins>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins)
+    /// element.
+    ins;
+
+    // Table content
+
+    /// Build a
+    /// [`<caption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption)
+    /// element.
+    caption;
+    /// Build a
+    /// [`<col>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col)
+    /// element.
+    col;
+    /// Build a
+    /// [`<colgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup)
+    /// element.
+    colgroup;
+    /// Build a
+    /// [`<table>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table)
+    /// element.
+    table;
+    /// Build a
+    /// [`<tbody>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody)
+    /// element.
+    tbody;
+    /// Build a
+    /// [`<td>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td)
+    /// element.
+    td;
+    /// Build a
+    /// [`<tfoot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot)
+    /// element.
+    tfoot;
+    /// Build a
+    /// [`<th>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th)
+    /// element.
+    th;
+    /// Build a
+    /// [`<thead>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead)
+    /// element.
+    thead;
+    /// Build a
+    /// [`<tr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr)
+    /// element.
+    tr;
+
+    // Forms
+
+    /// Build a
+    /// [`<button>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)
+    /// element.
+    button;
+    /// Build a
+    /// [`<datalist>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist)
+    /// element.
+    datalist;
+    /// Build a
+    /// [`<fieldset>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset)
+    /// element.
+    fieldset;
+    /// Build a
+    /// [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)
+    /// element.
+    form;
+    /// Build a
+    /// [`<input>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)
+    /// element.
+    input;
+    /// Build a
+    /// [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label)
+    /// element.
+    label;
+    /// Build a
+    /// [`<legend>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend)
+    /// element.
+    legend;
+    /// Build a
+    /// [`<meter>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter)
+    /// element.
+    meter;
+    /// Build a
+    /// [`<optgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup)
+    /// element.
+    optgroup;
+    /// Build a
+    /// [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
+    /// element.
+    option;
+    /// Build a
+    /// [`<output>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output)
+    /// element.
+    output;
+    /// Build a
+    /// [`<progress>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress)
+    /// element.
+    progress;
+    /// Build a
+    /// [`<select>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select)
+    /// element.
+    select;
+    /// Build a
+    /// [`<textarea>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea)
+    /// element.
+    textarea;
+
+    // Interactive elements
+
+    /// Build a
+    /// [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)
+    /// element.
+    details;
+    /// Build a
+    /// [`<dialog>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog)
+    /// element.
+    dialog;
+    /// Build a
+    /// [`<menu>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu)
+    /// element.
+    menu;
+    /// Build a
+    /// [`<menuitem>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menuitem)
+    /// element.
+    menuitem;
+    /// Build a
+    /// [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary)
+    /// element.
+    summary;
+
+    // Web components
+
+    /// Build a
+    /// [`<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.
+    template;
+}
+
+builder_constructors! {
+    // SVG components
+
+    /// Build a
+    /// [`<svg>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg)
+    /// element.
+    svg <> "http://www.w3.org/2000/svg" ;
+    /// Build a
+    /// [`<path>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path)
+    /// element.
+    path <> "http://www.w3.org/2000/svg";
+    /// Build a
+    /// [`<circle>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle)
+    /// element.
+    circle <>  "http://www.w3.org/2000/svg";
+    /// Build a
+    /// [`<ellipse>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/ellipse)
+    /// element.
+    ellipse <> "http://www.w3.org/2000/svg";
+    /// Build a
+    /// [`<line>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line)
+    /// element.
+    line <> "http://www.w3.org/2000/svg";
+    /// Build a
+    /// [`<polygon>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon)
+    /// element.
+    polygon <> "http://www.w3.org/2000/svg";
+    /// Build a
+    /// [`<polyline>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polyline)
+    /// element.
+    polyline <> "http://www.w3.org/2000/svg";
+    /// Build a
+    /// [`<rect>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect)
+    /// element.
+    rect <> "http://www.w3.org/2000/svg";
+    /// Build a
+    /// [`<image>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image)
+    /// element.
+    image <> "http://www.w3.org/2000/svg";
+}
+
+macro_rules! impl_attrs {
+    ( $(
+        $(#[$attr:meta])*
+        $name:ident: [$($f:ident)*];
+    )* ) => {};
+}
+
+impl_attrs! {
+    /// Indicates whether the user can interact with the element
+    disabled: [button command fieldset input keygen optgroup option select textarea];
+
+}
+
+mod tests {
+    use super::*;
+    fn r#type() {}
+
+    struct MyThing {}
+    impl MyThing {
+        /// eat my socks
+        fn r#type(&self) -> &Self {
+            self
+        }
+        fn nothing(&self) -> &Self {
+            self
+        }
+    }
+    fn test() {
+        let t = MyThing {};
+        t.r#type().r#nothing();
+
+        // let g = div::TAG_NAME;
+    }
+}

+ 21 - 0
packages/web/examples/events.rs

@@ -0,0 +1,21 @@
+use dioxus_core as dioxus;
+use dioxus_core::events::on::*;
+use dioxus_core::prelude::*;
+
+fn main() {}
+
+fn autocomplete() {
+    let handler = move |evt| {
+        let r = evt.alt_key();
+        if evt.alt_key() {}
+    };
+
+    let g = rsx! {
+        button {
+            button {
+                onclick: {handler}
+            }
+        }
+
+    };
+}

+ 22 - 19
packages/web/src/interpreter.rs

@@ -602,31 +602,34 @@ fn virtual_event_from_websys_event(event: &web_sys::Event) -> VirtualEvent {
 
             // todo - this needs to be a "controlled" event
             // these events won't carry the right data with them
-            VirtualEvent::FormEvent(FormEvent { value })
+            todo!()
+            // VirtualEvent::FormEvent(FormEvent { value })
         }
 
         "click" | "contextmenu" | "doubleclick" | "drag" | "dragend" | "dragenter" | "dragexit"
         | "dragleave" | "dragover" | "dragstart" | "drop" | "mousedown" | "mouseenter"
         | "mouseleave" | "mousemove" | "mouseout" | "mouseover" | "mouseup" => {
             let evt: web_sys::MouseEvent = event.clone().dyn_into().unwrap();
-            VirtualEvent::MouseEvent(MouseEvent(Box::new(RawMouseEvent {
-                alt_key: evt.alt_key(),
-                button: evt.button() as i32,
-                buttons: evt.buttons() as i32,
-                client_x: evt.client_x(),
-                client_y: evt.client_y(),
-                ctrl_key: evt.ctrl_key(),
-                meta_key: evt.meta_key(),
-                page_x: evt.page_x(),
-                page_y: evt.page_y(),
-                screen_x: evt.screen_x(),
-                screen_y: evt.screen_y(),
-                shift_key: evt.shift_key(),
-                get_modifier_state: GetModifierKey(Box::new(|f| {
-                    // evt.get_modifier_state(f)
-                    todo!("This is not yet implemented properly, sorry :(");
-                })),
-            })))
+            // MouseEvent(Box::new(RawMouseEvent {
+            //                 alt_key: evt.alt_key(),
+            //                 button: evt.button() as i32,
+            //                 buttons: evt.buttons() as i32,
+            //                 client_x: evt.client_x(),
+            //                 client_y: evt.client_y(),
+            //                 ctrl_key: evt.ctrl_key(),
+            //                 meta_key: evt.meta_key(),
+            //                 page_x: evt.page_x(),
+            //                 page_y: evt.page_y(),
+            //                 screen_x: evt.screen_x(),
+            //                 screen_y: evt.screen_y(),
+            //                 shift_key: evt.shift_key(),
+            //                 get_modifier_state: GetModifierKey(Box::new(|f| {
+            //                     // evt.get_modifier_state(f)
+            //                     todo!("This is not yet implemented properly, sorry :(");
+            //                 })),
+            //             }))
+            todo!()
+            // VirtualEvent::MouseEvent()
         }
 
         "pointerdown" | "pointermove" | "pointerup" | "pointercancel" | "gotpointercapture"

+ 10 - 2
src/lib.rs

@@ -182,6 +182,12 @@ pub mod prelude {
     pub use dioxus_core::prelude::*;
     pub use dioxus_core_macro::fc;
 }
+pub mod builder {
+    // pub use dioxus_core::builder::*;
+}
+pub mod events {
+    // pub use dioxus_core::events::*;
+}
 // Just a heads-up, the core functionality of dioxus rests in Dioxus-Core. This crate just wraps a bunch of utilities
 // together and exports their namespaces to something predicatble.
 #[cfg(feature = "core")]
@@ -220,7 +226,9 @@ pub mod testing {
 #[cfg(feature = "atoms")]
 pub mod atoms {}
 
-#[cfg(feature = "desktop")]
-pub mod desktop {
+// #[cfg(feature = "desktop")]
+pub mod webview {
     //! A webview based renderer for building desktop applications with Dioxus
+    use dioxus_core::prelude::FC;
+    pub fn launch<P>(f: FC<P>) {}
 }