Browse Source

Merge pull request #691 from DioxusLabs/jk/overhaul-readmes

chore: clean up readmes
Jon Kelley 2 years ago
parent
commit
86fb58faf8

+ 0 - 494
notes/SOLVEDPROBLEMS.md

@@ -1,494 +0,0 @@
-# Solved problems while building Dioxus
-
-focuses:
-
-- ergonomics
-- render agnostic
-- remote coupling
-- memory efficient
-- concurrent
-- global context
-- scheduled updates
--
-
-## FC Macro for more elegant components
-
-Originally the syntax of the FC macro was meant to look like:
-
-```rust
-#[fc]
-fn example(cx: &Context<{ name: String }>) -> DomTree {
-    html! { <div> "Hello, {name}!" </div> }
-}
-```
-
-`Context` was originally meant to be more obviously parameterized around a struct definition. However, while this works with rustc, this does not work well with Rust Analyzer. Instead, the new form was chosen which works with Rust Analyzer and happens to be more ergonomic.
-
-```rust
-#[fc]
-fn example(cx: &Context, name: String) -> DomTree {
-    html! { <div> "Hello, {name}!" </div> }
-}
-```
-
-## Anonymous Components
-
-In Yew, the function_component macro turns a struct into a Trait `impl` with associated type `props`. Like so:
-
-```rust
-#[derive(Properties)]
-struct Props {
-    // some props
-}
-
-struct SomeComponent;
-impl FunctionProvider for SomeComponent {
-    type TProps = Props;
-
-    fn run(&mut self, props: &Props) -> Html {
-        // user's functional component goes here
-    }
-}
-
-pub type SomeComponent = FunctionComponent<function_name>;
-```
-
-By default, the underlying component is defined as a "functional" implementation of the `Component` trait with all the lifecycle methods. In Dioxus, we don't allow components as structs, and instead take a "hooks-only" approach. However, we still need cx. To get these without dealing with traits, we just assume functional components are modules. This lets the macros assume an FC is a module, and `FC::Props` is its props and `FC::component` is the component. Yew's method does a similar thing, but with associated types on traits.
-
-Perhaps one day we might use traits instead.
-
-The FC macro needs to work like this to generate a final module signature:
-
-```rust
-// "Example" can be used directly
-// The "associated types" are just children of the module
-// That way, files can just be components (yay, no naming craziness)
-mod Example {
-    // Associated metadata important for liveview
-    static NAME: &'static str = "Example";
-
-    struct Props {
-        name: String
-    }
-
-    fn component(cx: &Context<Props>) -> DomTree {
-        html! { <div> "Hello, {name}!" </div> }
-    }
-}
-
-// or, Example.rs
-
-static NAME: &'static str = "Example";
-
-struct Props {
-    name: String
-}
-
-fn component(cx: &Context<Props>) -> DomTree {
-    html! { <div> "Hello, {name}!" </div> }
-}
-```
-
-These definitions might be ugly, but the fc macro cleans it all up. The fc macro also allows some configuration
-
-```rust
-#[fc]
-fn example(cx: &Context, name: String) -> DomTree {
-    html! { <div> "Hello, {name}!" </div> }
-}
-
-// .. expands to
-
-mod Example {
-    use super::*;
-    static NAME: &'static str = "Example";
-    struct Props {
-        name: String
-    }
-    fn component(cx: &Context<Props>) -> DomTree {
-        html! { <div> "Hello, {name}!" </div> }
-    }
-}
-```
-
-## Live Components
-
-Live components are a very important part of the Dioxus ecosystem. However, the goal with live components was to constrain their implementation purely to APIs available through Context (concurrency, context, subscription).
-
-From a certain perspective, live components are simply server-side-rendered components that update when their props change. Here's more-or-less how live components work:
-
-```rust
-#[fc]
-static LiveFc: FC = |cx, refresh_handler: impl FnOnce| {
-    // Grab the "live context"
-    let live_context = cx.use_context::<LiveContext>();
-
-    // Ensure this component is registered as "live"
-    live_context.register_scope();
-
-    // send our props to the live context and get back a future
-    let vnodes = live_context.request_update(cx);
-
-    // Suspend the rendering of this component until the vnodes are finished arriving
-    // Render them once available
-    cx.suspend(async move {
-        let output = vnodes.await;
-
-        // inject any listener handles (ie button clicks, views, etc) to the parsed nodes
-        output[1].add_listener("onclick", refresh_handler);
-
-        // Return these nodes
-        // Nodes skip diffing and go straight to rendering
-        output
-    })
-}
-```
-
-Notice that LiveComponent receivers (the client-side interpretation of a LiveComponent) are simply suspended components waiting for updates from the LiveContext (the context that wraps the app to make it "live").
-
-## Allocation Strategy (ie incorporating Dodrio research)
-
----
-
-The `VNodeTree` type is a very special type that allows VNodes to be created using a pluggable allocator. The html! macro creates something that looks like:
-
-```rust
-pub static Example: Component = |cx| {
-    html! { <div> "blah" </div> }
-};
-
-// expands to...
-
-pub static Example: Component = |cx| {
-    // This function converts a Fn(allocator) -> DomTree closure to a VNode struct that will later be evaluated.
-    html_macro_to_vnodetree(move |allocator| {
-        let mut node0 = allocator.alloc(VElement::div);
-        let node1 = allocator.alloc_text("blah");
-        node0.children = [node1];
-        node0
-    })
-};
-```
-
-At runtime, the new closure is created that captures references to `cx`. Therefore, this closure can only be evaluated while `cx` is borrowed and in scope. However, this closure can only be evaluated with an `allocator`. Currently, the global and Bumpalo allocators are available, though in the future we will add support for creating a VDom with any allocator or arena system (IE Jemalloc, wee-alloc, etc). The intention here is to allow arena allocation of VNodes (no need to box nested VNodes). Between diffing phases, the arena will be overwritten as old nodes are replaced with new nodes. This saves allocation time and enables bump allocators.
-
-## Context and lifetimes
-
-We want components to be able to fearlessly "use_context" for use in state management solutions.
-
-However, we cannot provide these guarantees without compromising the references. If a context mutates, it cannot lend out references.
-
-Functionally, this can be solved with UnsafeCell and runtime dynamics. Essentially, if a context mutates, then any affected components would need to be updated, even if they themselves aren't updated. Otherwise, a reference would be pointing at data that could have potentially been moved.
-
-To do this safely is a pretty big challenge. We need to provide a method of sharing data that is safe, ergonomic, and that fits the abstraction model.
-
-Enter, the "ContextGuard".
-
-The "ContextGuard" is very similar to a Ref/RefMut from the RefCell implementation, but one that derefs into actual underlying value.
-
-However, derefs of the ContextGuard are a bit more sophisticated than the Ref model.
-
-For RefCell, when a Ref is taken, the RefCell is now "locked." This means you cannot take another `borrow_mut` instance while the Ref is still active. For our purposes, our modification phase is very limited, so we can make more assumptions about what is safe.
-
-1. We can pass out ContextGuards from any use of use_context. These don't actually lock the value until used.
-2. The ContextGuards only lock the data while the component is executing and when a callback is running.
-3. Modifications of the underlying context occur after a component is rendered and after the event has been run.
-
-With the knowledge that usage of ContextGuard can only be achieved in a component context and the above assumptions, we can design a guard that prevents any poor usage but also is ergonomic.
-
-As such, the design of the ContextGuard must:
-
-- be /copy/ for easy moves into closures
-- never point to invalid data (no dereferencing of raw pointers after movable data has been changed (IE a vec has been resized))
-- not allow references of underlying data to leak into closures
-
-To solve this, we can be clever with lifetimes to ensure that any data is protected, but context is still ergonomic.
-
-1. As such, deref context guard returns an element with a lifetime bound to the borrow of the guard.
-2. Because we cannot return locally borrowed data AND we consume context, this borrow cannot be moved into a closure.
-3. ContextGuard is _copy_ so the guard itself can be moved into closures
-4. ContextGuard derefs with its unique lifetime _inside_ closures
-5. Derefing a ContextGuard evaluates the underlying selector to ensure safe temporary access to underlying data
-
-```rust
-struct ExampleContext {
-    // unpinnable objects with dynamic sizing
-    items: Vec<String>
-}
-
-fn Example<'src>(cx: Scope<'src, ()>) -> DomTree<'src> {
-    let val: &'b ContextGuard<ExampleContext> = (&'b cx).use_context(|context: &'other ExampleContext| {
-        // always select the last element
-        context.items.last()
-    });
-
-    let handler1 = move |_| println!("Value is {}", val); // deref coercion performed here for printing
-    let handler2 = move |_| println!("Value is {}", val); // deref coercion performed here for printing
-
-    cx.render(html! {
-        <div>
-            <button onclick={handler1}> "Echo value with h1" </button>
-            <button onclick={handler2}> "Echo value with h2" </button>
-            <div>
-                <p> "Value is: {val}" </p>
-            </div>
-        </div>
-    })
-}
-```
-
-A few notes:
-
-- this does _not_ protect you from data races!!!
-- this does _not_ force rendering of components
-- this _does_ protect you from invalid + UB use of data
-- this approach leaves lots of room for fancy state management libraries
-- this approach is fairly quick, especially if borrows can be cached during usage phases
-
-## Concurrency
-
-For Dioxus, concurrency is built directly into the VirtualDOM lifecycle and event system. Suspended components prove "no changes" while diffing, and will cause a lifecycle update later. This is considered a "trigger" and will cause targeted diffs and re-renders. Renderers will need to await the Dioxus suspense queue if they want to process these updates. This will typically involve joining the suspense queue and event listeners together like:
-
-```rust
-// wait for an even either from the suspense queue or our own custom listener system
-let (left, right) = join!(vdom.suspense_queue, self.custom_event_listener);
-```
-
-LiveView is built on this model, and updates from the WebSocket connection to the host server are treated as external updates. This means any renderer can feed targeted EditLists (the underlying message of this event) directly into the VirtualDOM.
-
-## Execution Model
-
-<!-- todo -->
-
-## Diffing
-
-Diffing is an interesting story. Since we don't re-render the entire DOM, we need a way to patch up the DOM without visiting every component. To get this working, we need to think in cycles, queues, and stacks. Most of the original logic is pulled from Dodrio as Dioxus and Dodrio share much of the same DNA.
-
-When an event is triggered, we find the callback that installed the listener and run it. We then record all components affected by the running of the "subscription" primitive. In practice, many hooks will initiate a subscription, so it is likely that many components throughout the entire tree will need to be re-rendered. For each component, we attach its index and the type of update it needs.
-
-In practice, removals trump prop updates which trump subscription updates. Therefore, we only process updates where props are directly changed first, as this will likely flow into child components.
-
-Roughly, the flow looks like:
-
-- Process the initiating event
-- Mark components affected by the subscription API (the only way of causing forward updates)
-- Descend from the root into children, ignoring those not affected by the subscription API. (walking the tree until we hit the first affected component, or choosing the highest component)
-- Run this component and then immediately diff its output, marking any children that also need to be updated and putting them into the immediate queue
-- Mark this component as already-ran and remove it from the need_to_diff list, instead moving it into the "already diffed list"
-- Run the marked children until the immediate queue is empty
-
-```rust
-struct DiffMachine {
-    immediate_queue: Vec<Index>,
-    diffed: HashSet<Index>,
-    need_to_diff: HashSet<Index>
-    marked_for_removal: Vec<Index>
-}
-```
-
-On the actual diffing level, we're using the diffing algorithm pulled from Dodrio, but plan to move to a dedicated crate that implements Meyers/Patience for us. During the diffing phase, we track our current position using a "Traversal" which implements the "MoveTo". When "MoveTo" is combined with "Edit", it is possible for renderers to fully interpret a series of Moves and Edits together to update their internal node structures for rendering.
-
-## Patch Stream
-
-One of the most important parts of Dioxus is the ability to stream patches from server to client. However, this inherently has challenges where raw VNodes attach listeners to themselves, and are therefore not serializable.
-
-### How do properties work?
-
-How should properties passing work? Should we directly call the child? Should we box the props? Should we replace the pops inside the box?
-
-Here's (generally) my head is at:
-
-Components need to store their props on them if they want to be updated remotely. These props _can_ be updated after the fact.
-
-Perf concerns:
-unnecessary function runs - list-y components - hook calls? - making vnodes?
-
-Does any of this matter?
-Should we just run any component we see, immediately and imperatively? That will cause checks throughout the whole tree, no matter where the update occurred
-
-https://calendar.perfplanet.com/2013/diff/
-
-Here's how react does it:
-
-Any "dirty" node causes an entire subtree render. Calling "setState" at the very top will cascade all the way down. This is particularly bad for this component design:
-
-```rust
-static APP: Component = |cx| {
-    let title = use_context(Title);
-    cx.render(html!{
-        <div>
-            <h1> "{title}"</h1>
-            <HeavyList /> // VComponent::new(|| (FC, PropsForFc)) -> needs a context to immediately update the component's props imperatively? store the props in a box on bump? store the props on the child?
-            // if props didnt change, then let the refernece stay invalid?.... no, cant do that, bump gets reset
-            // immediately update props on the child component if it can be found? -> interesting, feels wrong, but faster, at the very least.
-            // can box on bump for the time being (fast enough), and then move it over? during the comparison phase? props only need to matter
-            // cant downcast (can with transmute, but yikes)
-            // how does chain borrowing work? a -> b -> c -> d
-            // if b gets marked as dirty, then c and d are invalidated (semantically, UB, but not *bad* UB, just data races)
-            // make props static? -> easy to move, gross to use
-            //
-            // treat like a context selector?
-            // use_props::<P>(2)
-            // child_props: Map<Scope, Box<dyn Props>>
-            // vs children: BTreeSet<Scope> -> to get nth
-        </div>
-    })
-};
-static HEAVY_LIST: Component = |cx| {
-    cx.render({
-        {0.100.map(i => <BigElement >)}
-    })
-};
-```
-
-An update to the use_context subscription will mark the node as dirty. The node then is forced to re-analyze HeavyList, even though HeavyList did not change. We should automatically implement this suppression knowing that props are immutable and can be partialeq.
-
-## FC Layout
-
-The FC layout was altered to make life easier for us inside the VirtualDom. The "view" function returns an unbounded VNode object. Calling the "view" function is unsafe under the hood, but prevents lifetimes from leaking out of the function call. Plus, it's easier to write. Because there are no lifetimes on the output (occur purely under the hood), we can escape needing to annotate them.
-
-```rust
-fn component(cx: Scope<Props>) -> DomTree {
-
-}
-```
-
-The VNode object purely represents a viewable "key". It also forces components to use the "view" function as there is no other way to generate the VNode object. Because the VNode is a required type of FC, we can guarantee the same usage and flow patterns for all components.
-
-## Events
-
-Events are finally in! To do events properly, we are abstracting over the event source with synthetic events. This forces 3rd party renderers to create the appropriate cross-platform event
-
-## Optional Props on Components
-
-A major goal here is ergonomics. Any field that is Option<T> should default to none.
-
-```rust
-
-rsx! {
-    Example { /* args go here */ a: 10, b: 20 }
-}
-
-
-```
-
-```rust
-#[derive(Properties)]
-struct Props {
-
-}
-
-static Component: Component<Props> = |cx| {
-
-}
-```
-
-or
-
-```rust
-#[fc]
-static Component: FC = |cx, name: &str| {
-
-}
-```
-
-## Noderefs
-
-How do we resolve noderefs in a world of patches? Patches _must_ be serializable, so if we do something like `Option<&RefCell<Slot>>`, then that must serialize as _something_ to indicate to a remote host that access to the node itself is desired. Our `Slot` type will need to be somewhat abstract.
-
-If we add a new patch type called "BindRef" we could do something like:
-
-```rust
-enum Patch {
-    //...
-    BindAsRef { raw_node: &RefCell<Option<Slot>> }
-}
-```
-
-```rust
-let node_ref = use_node_ref(cx);
-use_effect(cx, || {
-
-}, []);
-div { ref: node_ref,
-    "hello me"
-    h3 {"yo dom"}
-}
-```
-
-refs only work when you're native to the platform. it doesn't make sense to gain a ref when you're not native.
-
-## In-sync or separate?
-
-React makes refs - and protection against dom manipulation - work by modifying the real dom while diffing the virtual dom. This lets it bind real dom elements to the virtual dom elements. Dioxus currently does not do this, instead creating a list of changes for an interpreter to apply once diffing has completed.
-
-This behavior fit dodrio well as all dom manipulations would occur batched. The original intention for this approach was to make it faster to read out of Wasm and into JS. Dodrio is essentially performing the Wasm job that Wasm<->JS for strings does. In theory, this particular optimization is not necessary.
-
-https://github.com/fitzgen/dodrio/issues/77
-
-This issue/pr on the dodrio repository points to a future where elements are held on to by the virtualdom.
-
-Can we solve events, refs, and protection against 3rd party dom mutation all in one shot?
-
-I think we can....
-
-every node gets a globally unique ID
-
-abstract the real dom
-
-```rust
-
-struct VirtualDom<Dom: RealDom>
-
-trait RealDom {
-    type Node: RealNode;
-    fn get_node(&self, id: u32) -> &Self::Node;
-    fn get_node_mut(&mut self, id: u32) -> &mut Self::Node;
-    fn replace_node();
-    fn create_text_node();
-    fn create_element();
-    fn create_element_ns();
-}
-
-trait RealNode {
-    fn add_listener(&mut self, event: &str);
-    fn set_inner_text(&mut self, text: &str);
-    fn set_attr(&mut self, name, value);
-    fn set_class(&mut self);
-    fn remove_attr(&mut self);
-    // We can't have a generic type in trait objects, so instead we provide the inner as Any
-    fn raw_node_as_any_mut(&mut self) -> &mut dyn Any;
-}
-
-impl VirtualDom<Dom: RealDom> {
-    fn diff<Dom: RealDom>() {
-
-    }
-}
-enum VNode<'bump, 'realdom, RealDom> {
-    VElement {
-        real: &RealDom::Node
-    }
-    VText {
-        real: &RealDom::Node
-    }
-}
-
-
-fn main() {
-    let mut real_dom = websys::Document();
-    let virtual_dom = Dioxus::VirtualDom::new();
-
-    virtual_dom.rebuild(&mut real_dom);
-
-    loop {
-        let event = switch! {
-            real_dom.events.await => event,
-            virtual_dom.inner_events.await => event
-        };
-
-        virtual_dom.apply_event(&mut real_dom, event);
-    }
-}
-
-```

+ 30 - 69
packages/autofmt/README.md

@@ -1,88 +1,49 @@
-# This crate autofmts blocks of rsx!
+# dioxus-autofmt
 
-This crate formats rsx! by parsing call bodies and pretty-printing them back out.
 
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
 
+[crates-badge]: https://img.shields.io/crates/v/dioxus-autofmt.svg
+[crates-url]: https://crates.io/crates/dioxus-autofmt
 
-# Todo:
-Sorted roughly in order of what's possible
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
 
-- [x] Oneline rsx! calls - blocker because this wrecks formatting
-- [ ] Nested RSX calls (important) - unnecessary but desirable
-- [ ] RSX edits overstepping each other
-- [ ] Collapse components and elements under syntax -
-- [ ] Don't eat comments in exprs
-- [ ] Format regular exprs
-- [ ] Fix prettyplease around chaining
-- [ ] Don't eat comments in prettyplease
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
 
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
 
-# Technique
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-autofmt/latest/dioxus-autofmt) |
+[Chat](https://discord.gg/XgGxMSkvUM)
 
 
-div {
-    div {}
-    div {}
-}
+## Overview
 
+`dioxus-autofmt` provides a pretty printer for the `rsx` syntax tree.
 
-div
 
-possible line break
-div
-div
+This is done manually with a via set of formatting rules. The output is not guaranteed to be stable between minor versions of the crate as we might tweak the output.
 
+`dioxus-autofmt` provides an API to perform precision edits as well as just spit out a block of formatted RSX from any RSX syntax tree. This is used by the `rsx-rosetta` crate which can accept various input languages and output valid RSX.
 
 
-string of possible items within a nesting
-div {
-    attr_pair
-    expr
-    text
-    comment
-}
-a nesting is either a component or an element
+## Contributing
 
-idea:
-collect all items into a queue
-q
-```rust
-section {
-    div {
-        h1 { p { "asdasd" } }
-        h1 { p { "asdasd" } }
-    }
-}
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
 
-section {}
-```
+## License
+This project is licensed under the [MIT license].
 
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
 
-// space
-// space
-// space
-
-
-3 - section
-3 - section div
-3 - section div h1
-3 - section div h1 p
-3 - section div h1 p text
-3 - section
-3 - section div
-3 - section div h1
-3 - section div h1 p
-3 - section div h1 p text
-
-block
-
-- when we hit the end of a trail, we can make a decision what needs to be hard breaked
-- most nestings cannot be merged into a single one, so at some point we need to write the line break
-- this is the scan section. we scan forward until it's obvious where to place a hard break
-- when a line is finished, we can print it out by unloading our queued items
-- never double nested
-
-
-Terms
-- break is a whitespace than can flex, dependent on the situation
-- ‹⁠›
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.

+ 47 - 6
packages/core-macro/README.md

@@ -1,7 +1,48 @@
-# core-macro
+# dioxus-core-macro
 
-This crate implements these macros:
-- `format_args_f`: for f-string interpolation inside of text blocks
-- `Props`: derive macro for typed-builder with props configurations
-- 
-- 
+
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
+
+[crates-badge]: https://img.shields.io/crates/v/dioxus-core-macro.svg
+[crates-url]: https://crates.io/crates/dioxus-core-macro
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-core-macro/latest/dioxus-core-macro) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+
+## Overview
+
+`dioxus-core-macro` provides a handful of helpful macros used by the `dioxus` crate. These include:
+
+- The `rsx!` macro that underpins templates and node creation
+- The `inline_props` that transforms function arguments into an auto-derived struct
+- The `format_args_f` macro which allows f-string formatting with support for expressions
+
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.

+ 0 - 14
packages/desktop/ARCHITECTURE.md

@@ -1,14 +0,0 @@
-# dioxus webview arch
-
-
-dioxus webview represents a usecase of dioxus to stream edits from one dom to another. In this particular case, we stream edits from a native process into the webview's runtime. WebView is really portable, so we can leverage the UI of iOS, Android, and all desktop platforms while also maintaining direct access to platform-specific APIs. It's the best of both worlds!
-
-
-For this to work properly, we need to ship a universal client that receives Dioxus edits from a remote process. To make our lives (as developers) a bit easier, the client code is currently implemented in JS (subject to change!).
-
-The provider (the thing that talks to the client on the other side of the network) is still written in Rust, and is supplied through the dioxus-webview crate. The client is much more "dumb" than the provider - the provider must handle NodeID generation, flushing changes, priorities, managing events, and more.
-
-
-## update; wry!
-
-Wry is an effort by the Tauri team to make fully native 

+ 55 - 3
packages/desktop/README.md

@@ -1,5 +1,57 @@
-# Dioxus-Desktop
+# Dioxus Desktop (webview)
 
-Because the host VirtualDOM is running in its own native process, native applications can unlock their full potential. Dioxus-Desktop is designed to be a 100% rust alternative to ElectronJS without the memory overhead or bloat of ElectronJS apps.
 
-By bridging the native process, desktop apps can access full multithreading power, peripheral support, hardware access, and native filesystem controls without the hassle of web technologies. Our goal with this desktop crate is to make it easy to ship both a web and native application, and quickly see large performance boosts without having to re-write the whole stack. As the dioxus ecosystem grows, we hope to see 3rd parties providing wrappers for storage, offline mode, etc that supports both web and native technologies.
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
+
+[crates-badge]: https://img.shields.io/crates/v/dioxus-desktop.svg
+[crates-url]: https://crates.io/crates/dioxus-desktop
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-desktop/latest/dioxus-desktop) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+
+## Overview
+
+`dioxus-desktop` provides a webview-based desktop renderer for the Dioxus VirtualDom.
+
+This requires that webview is installed on the target system. WebView is installed by default on macOS and iOS devices, but might not come preinstalled on Windows or Linux devices. To fix these issues, follow the [instructions in the guide](guide-url).
+
+[guide-url]: https://dioxuslabs.com/guide/setup.html#platform-specific-dependencies
+
+
+
+## Features
+
+- Simple, one-line launch for desktop apps
+- Dioxus virtualdom running on a native thread
+- Full HTML/CSS support via `wry` and `tao`
+- Exposed `window` and `Proxy` types from tao for direct window manipulation
+- Helpful hooks for
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.

+ 47 - 11
packages/hooks/README.md

@@ -1,22 +1,58 @@
-# Common hooks for Dioxus
+# Dioxus Hooks
 
-This crate includes some basic useful hooks for dioxus:
+
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
+
+[crates-badge]: https://img.shields.io/crates/v/dioxus-hooks.svg
+[crates-url]: https://crates.io/crates/dioxus-hooks
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-hooks/latest/dioxus-hooks) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+
+## Overview
+
+`dioxus-hooks` includes some basic useful hooks for dioxus:
 
 - use_state
 - use_ref
 - use_future
 - use_coroutine
+- use_callback
+
+Unlike React, none of these hooks are foundational since they all build off the primitive `cx.use_hook`.
+
+This crate also provides a few helpful macros to get around some Rust lifetime management issues in async.
+
+- `to_owned![]`
+- `use_future!()`
+- `use_callback!()`
+
 
-## use_state
+## Contributing
 
-The primary mechanism of stored state.
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
 
-You can always use it "normally" with the `split` method:
+## License
+This project is licensed under the [MIT license].
 
-```rust
-// Rusty-smart-pointer usage:
-let value = use_state(cx, || 10);
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
 
-// "Classic" usage:
-let (value, set_value) = use_state(cx, || 0).split();
-```
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.

+ 42 - 31
packages/html/README.md

@@ -1,4 +1,30 @@
-# Html (and SVG) Namespace for Dioxus
+# `dioxus-html`: Html (and SVG) Namespace for Dioxus
+
+
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
+
+[crates-badge]: https://img.shields.io/crates/v/dioxus-html.svg
+[crates-url]: https://crates.io/crates/dioxus-html
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-html/latest/dioxus-html) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+
+## Overview
 
 The Dioxus `rsx!` and `html!` macros can accept any compile-time correct namespace on top of NodeFactory. This crate provides the HTML (and SVG) namespaces which get imported in the Dioxus prelude.
 
@@ -73,35 +99,20 @@ mod dioxus_elements {
 }
 ```
 
-## Limitations:
--
 
-## How to work around it:
-If an attribute in Dioxus is invalid (defined incorrectly) - first, make an issue - but then, you can work around it. The raw builder API is actually somewhat ergonomic to work with, and the NodeFactory type exposes a bunch of methods to make any type of tree - even invalid ones! So obviously, be careful, but there's basically anything you can do.
 
-```rust
-cx.render(rsx!{
-    div {
-        h1 {}
-        // Oh no! I need a super custom element
-        {LazyNodes::new(move |f| {
-            f.raw_element(
-                // tag name
-                "custom_element",
-
-                // attributes
-                &[f.attr("billy", format_args!("goat"))],
-
-                // listeners
-                &[f.listener(onclick(move |_| {}))],
-
-                // children
-                &[cx.render(rsx!(div {} ))],
-
-                // key
-                None
-            )
-        })}
-    }
-})
-```
+
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.

+ 1 - 1
packages/html/src/events/drag.rs

@@ -9,7 +9,7 @@ pub type DragEvent = Event<DragData>;
 /// (such as another DOM element). Applications are free to interpret a drag and drop interaction in an
 /// application-specific way.
 #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone, PartialEq, Eq)]
 pub struct DragData {
     /// Inherit mouse data
     pub mouse: MouseData,

+ 1 - 1
packages/html/src/events/mouse.rs

@@ -10,7 +10,7 @@ pub type MouseEvent = Event<MouseData>;
 
 /// A synthetic event that wraps a web-style [`MouseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)
 #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
-#[derive(Clone, Default, PartialEq)]
+#[derive(Clone, Default, PartialEq, Eq)]
 /// Data associated with a mouse event
 ///
 /// Do not use the deprecated fields; they may change or become private in the future.

+ 43 - 4
packages/interpreter/README.md

@@ -1,7 +1,46 @@
-# JS Interpreter
+# `dioxus-interpreter-js`
 
-After diffing old and new trees, the Dioxus VirtualDom produces patches that are used to modify the existing Dom. We can send these patches anywhere - including targets without WASM support.
 
-In renderers with support for JavaScript, we use the interpreter from this repository - written in TypeScript - to patch the Dom. This lets us circumvent any overhead on the Rust <-> Dom boundary and keep consistency in our interpreter implementation in web/webview targets.
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
 
-For now - both Dioxus Web and Dioxus Desktop (webview) use the same interpreter code with tweaks.
+[crates-badge]: https://img.shields.io/crates/v/dioxus-interpreter-js.svg
+[crates-url]: https://crates.io/crates/dioxus-interpreter-js
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-interpreter-js/latest/dioxus-interpreter-js) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+
+## Overview
+
+`dioxus-interpreter-js` provides the high-performance JavaScript glue that interprets the stream of edits produced by the Dioxus VirtualDom and converts them into mutations on the actual web DOM.
+
+This crate features bindings for the web and sledgehammer for increased performance.
+
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.

+ 0 - 944
packages/interpreter/src/interpreter.old.js

@@ -1,944 +0,0 @@
-export function main() {
-  let root = window.document.getElementById("main");
-  if (root != null) {
-    window.interpreter = new Interpreter(root);
-    window.ipc.postMessage(serializeIpcMessage("initialize"));
-  }
-}
-
-class ListenerMap {
-  constructor(root) {
-    // bubbling events can listen at the root element
-    this.global = {};
-    // non bubbling events listen at the element the listener was created at
-    this.local = {};
-    this.root = root;
-  }
-
-  create(event_name, element, handler, bubbles) {
-    if (bubbles) {
-      if (this.global[event_name] === undefined) {
-        this.global[event_name] = {};
-        this.global[event_name].active = 1;
-        this.global[event_name].callback = handler;
-        this.root.addEventListener(event_name, handler);
-      } else {
-        this.global[event_name].active++;
-      }
-    }
-    else {
-      const id = element.getAttribute("data-dioxus-id");
-      if (!this.local[id]) {
-        this.local[id] = {};
-      }
-      this.local[id][event_name] = handler;
-      element.addEventListener(event_name, handler);
-    }
-  }
-
-  remove(element, event_name, bubbles) {
-    if (bubbles) {
-      this.global[event_name].active--;
-      if (this.global[event_name].active === 0) {
-        this.root.removeEventListener(event_name, this.global[event_name].callback);
-        delete this.global[event_name];
-      }
-    }
-    else {
-      const id = element.getAttribute("data-dioxus-id");
-      delete this.local[id][event_name];
-      if (this.local[id].length === 0) {
-        delete this.local[id];
-      }
-      element.removeEventListener(event_name, handler);
-    }
-  }
-}
-
-export class Interpreter {
-  constructor(root) {
-    this.root = root;
-    this.lastNode = root;
-    this.listeners = new ListenerMap(root);
-    this.handlers = {};
-    this.nodes = [root];
-    this.parents = [];
-  }
-  checkAppendParent() {
-    if (this.parents.length > 0) {
-      const lastParent = this.parents[this.parents.length - 1];
-      lastParent[1]--;
-      if (lastParent[1] === 0) {
-        this.parents.pop();
-      }
-      lastParent[0].appendChild(this.lastNode);
-    }
-  }
-  AppendChildren(root, children) {
-    let node;
-    if (root == null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[root];
-    }
-    for (let i = 0; i < children.length; i++) {
-      node.appendChild(this.nodes[children[i]]);
-    }
-  }
-  ReplaceWith(root, nodes) {
-    let node;
-    if (root == null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[root];
-    }
-    let els = [];
-    for (let i = 0; i < nodes.length; i++) {
-      els.push(this.nodes[nodes[i]])
-    }
-    node.replaceWith(...els);
-  }
-  InsertAfter(root, nodes) {
-    let node;
-    if (root == null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[root];
-    }
-    let els = [];
-    for (let i = 0; i < nodes.length; i++) {
-      els.push(this.nodes[nodes[i]])
-    }
-    node.after(...els);
-  }
-  InsertBefore(root, nodes) {
-    let node;
-    if (root == null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[root];
-    }
-    let els = [];
-    for (let i = 0; i < nodes.length; i++) {
-      els.push(this.nodes[nodes[i]])
-    }
-    node.before(...els);
-  }
-  Remove(root) {
-    let node;
-    if (root == null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[root];
-    }
-    if (node !== undefined) {
-      node.remove();
-    }
-  }
-  CreateTextNode(text, root) {
-    this.lastNode = document.createTextNode(text);
-    this.checkAppendParent();
-    if (root != null) {
-      this.nodes[root] = this.lastNode;
-    }
-  }
-  CreateElement(tag, root, children) {
-    this.lastNode = document.createElement(tag);
-    this.checkAppendParent();
-    if (root != null) {
-      this.nodes[root] = this.lastNode;
-    }
-    if (children > 0) {
-      this.parents.push([this.lastNode, children]);
-    }
-  }
-  CreateElementNs(tag, root, ns, children) {
-    this.lastNode = document.createElementNS(ns, tag);
-    this.checkAppendParent();
-    if (root != null) {
-      this.nodes[root] = this.lastNode;
-    }
-    if (children > 0) {
-      this.parents.push([this.lastNode, children]);
-    }
-  }
-  CreatePlaceholder(root) {
-    this.lastNode = document.createElement("pre");
-    this.lastNode.hidden = true;
-    this.checkAppendParent();
-    if (root != null) {
-      this.nodes[root] = this.lastNode;
-    }
-  }
-  NewEventListener(event_name, root, handler, bubbles) {
-    let node;
-    if (root == null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[root];
-    }
-    node.setAttribute("data-dioxus-id", `${root}`);
-    this.listeners.create(event_name, node, handler, bubbles);
-  }
-  RemoveEventListener(root, event_name, bubbles) {
-    let node;
-    if (root == null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[root];
-    }
-    node.removeAttribute(`data-dioxus-id`);
-    this.listeners.remove(node, event_name, bubbles);
-  }
-  SetText(root, text) {
-    let node;
-    if (root == null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[root];
-    }
-    node.data = text;
-  }
-  SetAttribute(root, field, value, ns) {
-    const name = field;
-    let node;
-    if (root == null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[root];
-    }
-    if (ns === "style") {
-      // @ts-ignore
-      node.style[name] = value;
-    } else if (ns != null || ns != undefined) {
-      node.setAttributeNS(ns, name, value);
-    } else {
-      switch (name) {
-        case "value":
-          if (value !== node.value) {
-            node.value = value;
-          }
-          break;
-        case "checked":
-          node.checked = value === "true";
-          break;
-        case "selected":
-          node.selected = value === "true";
-          break;
-        case "dangerous_inner_html":
-          node.innerHTML = value;
-          break;
-        default:
-          // https://github.com/facebook/react/blob/8b88ac2592c5f555f315f9440cbb665dd1e7457a/packages/react-dom/src/shared/DOMProperty.js#L352-L364
-          if (value === "false" && bool_attrs.hasOwnProperty(name)) {
-            node.removeAttribute(name);
-          } else {
-            node.setAttribute(name, value);
-          }
-      }
-    }
-  }
-  RemoveAttribute(root, field, ns) {
-    const name = field;
-    let node;
-    if (root == null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[root];
-    }
-    if (ns == "style") {
-      node.style.removeProperty(name);
-    } else if (ns !== null || ns !== undefined) {
-      node.removeAttributeNS(ns, name);
-    } else if (name === "value") {
-      node.value = "";
-    } else if (name === "checked") {
-      node.checked = false;
-    } else if (name === "selected") {
-      node.selected = false;
-    } else if (name === "dangerous_inner_html") {
-      node.innerHTML = "";
-    } else {
-      node.removeAttribute(name);
-    }
-  }
-  CloneNode(old, new_id) {
-    let node;
-    if (old === null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[old];
-    }
-    this.nodes[new_id] = node.cloneNode(true);
-  }
-  CloneNodeChildren(old, new_ids) {
-    let node;
-    if (old === null) {
-      node = this.lastNode;
-    } else {
-      node = this.nodes[old];
-    }
-    const old_node = node.cloneNode(true);
-    let i = 0;
-    for (let node = old_node.firstChild; i < new_ids.length; node = node.nextSibling) {
-      this.nodes[new_ids[i++]] = node;
-    }
-  }
-  FirstChild() {
-    this.lastNode = this.lastNode.firstChild;
-  }
-  NextSibling() {
-    this.lastNode = this.lastNode.nextSibling;
-  }
-  ParentNode() {
-    this.lastNode = this.lastNode.parentNode;
-  }
-  StoreWithId(id) {
-    this.nodes[id] = this.lastNode;
-  }
-  SetLastNode(root) {
-    this.lastNode = this.nodes[root];
-  }
-  handleEdits(edits) {
-    for (let edit of edits) {
-      this.handleEdit(edit);
-    }
-  }
-  handleEdit(edit) {
-    switch (edit.type) {
-      case "PushRoot":
-        this.PushRoot(edit.root);
-        break;
-      case "AppendChildren":
-        this.AppendChildren(edit.root, edit.children);
-        break;
-      case "ReplaceWith":
-        this.ReplaceWith(edit.root, edit.nodes);
-        break;
-      case "InsertAfter":
-        this.InsertAfter(edit.root, edit.nodes);
-        break;
-      case "InsertBefore":
-        this.InsertBefore(edit.root, edit.nodes);
-        break;
-      case "Remove":
-        this.Remove(edit.root);
-        break;
-      case "CreateTextNode":
-        this.CreateTextNode(edit.text, edit.root);
-        break;
-      case "CreateElement":
-        this.CreateElement(edit.tag, edit.root, edit.children);
-        break;
-      case "CreateElementNs":
-        this.CreateElementNs(edit.tag, edit.root, edit.ns, edit.children);
-        break;
-      case "CreatePlaceholder":
-        this.CreatePlaceholder(edit.root);
-        break;
-      case "RemoveEventListener":
-        this.RemoveEventListener(edit.root, edit.event_name);
-        break;
-      case "NewEventListener":
-        // this handler is only provided on desktop implementations since this
-        // method is not used by the web implementation
-        let handler = (event) => {
-          let target = event.target;
-          if (target != null) {
-            let realId = target.getAttribute(`data-dioxus-id`);
-            let shouldPreventDefault = target.getAttribute(
-              `dioxus-prevent-default`
-            );
-
-            if (event.type === "click") {
-              // todo call prevent default if it's the right type of event
-              if (shouldPreventDefault !== `onclick`) {
-                if (target.tagName === "A") {
-                  event.preventDefault();
-                  const href = target.getAttribute("href");
-                  if (href !== "" && href !== null && href !== undefined) {
-                    window.ipc.postMessage(
-                      serializeIpcMessage("browser_open", { href })
-                    );
-                  }
-                }
-              }
-
-              // also prevent buttons from submitting
-              if (target.tagName === "BUTTON" && event.type == "submit") {
-                event.preventDefault();
-              }
-            }
-            // walk the tree to find the real element
-            while (realId == null) {
-              // we've reached the root we don't want to send an event
-              if (target.parentElement === null) {
-                return;
-              }
-
-              target = target.parentElement;
-              realId = target.getAttribute(`data-dioxus-id`);
-            }
-
-            shouldPreventDefault = target.getAttribute(
-              `dioxus-prevent-default`
-            );
-
-            let contents = serialize_event(event);
-
-            if (shouldPreventDefault === `on${event.type}`) {
-              event.preventDefault();
-            }
-
-            if (event.type === "submit") {
-              event.preventDefault();
-            }
-
-            if (
-              target.tagName === "FORM" &&
-              (event.type === "submit" || event.type === "input")
-            ) {
-              for (let x = 0; x < target.elements.length; x++) {
-                let element = target.elements[x];
-                let name = element.getAttribute("name");
-                if (name != null) {
-                  if (element.getAttribute("type") === "checkbox") {
-                    // @ts-ignore
-                    contents.values[name] = element.checked ? "true" : "false";
-                  } else if (element.getAttribute("type") === "radio") {
-                    if (element.checked) {
-                      contents.values[name] = element.value;
-                    }
-                  } else {
-                    // @ts-ignore
-                    contents.values[name] =
-                      element.value ?? element.textContent;
-                  }
-                }
-              }
-            }
-
-            if (realId === null) {
-              return;
-            }
-            realId = parseInt(realId);
-            window.ipc.postMessage(
-              serializeIpcMessage("user_event", {
-                event: edit.event_name,
-                mounted_dom_id: realId,
-                contents: contents,
-              })
-            );
-          }
-        };
-        this.NewEventListener(edit.event_name, edit.root, handler, event_bubbles(edit.event_name));
-
-        break;
-      case "SetText":
-        this.SetText(edit.root, edit.text);
-        break;
-      case "SetAttribute":
-        this.SetAttribute(edit.root, edit.field, edit.value, edit.ns);
-        break;
-      case "RemoveAttribute":
-        this.RemoveAttribute(edit.root, edit.name, edit.ns);
-        break;
-      case "CloneNode":
-        this.CloneNode(edit.id, edit.new_id);
-        break;
-      case "CloneNodeChildren":
-        this.CloneNodeChildren(edit.id, edit.new_ids);
-        break;
-      case "FirstChild":
-        this.FirstChild();
-        break;
-      case "NextSibling":
-        this.NextSibling();
-        break;
-      case "ParentNode":
-        this.ParentNode();
-        break;
-      case "StoreWithId":
-        this.StoreWithId(BigInt(edit.id));
-        break;
-      case "SetLastNode":
-        this.SetLastNode(BigInt(edit.id));
-        break;
-    }
-  }
-}
-
-export function serialize_event(event) {
-  switch (event.type) {
-    case "copy":
-    case "cut":
-    case "past": {
-      return {};
-    }
-    case "compositionend":
-    case "compositionstart":
-    case "compositionupdate": {
-      let { data } = event;
-      return {
-        data,
-      };
-    }
-    case "keydown":
-    case "keypress":
-    case "keyup": {
-      let {
-        charCode,
-        key,
-        altKey,
-        ctrlKey,
-        metaKey,
-        keyCode,
-        shiftKey,
-        location,
-        repeat,
-        which,
-        code,
-      } = event;
-      return {
-        char_code: charCode,
-        key: key,
-        alt_key: altKey,
-        ctrl_key: ctrlKey,
-        meta_key: metaKey,
-        key_code: keyCode,
-        shift_key: shiftKey,
-        location: location,
-        repeat: repeat,
-        which: which,
-        code,
-      };
-    }
-    case "focus":
-    case "blur": {
-      return {};
-    }
-    case "change": {
-      let target = event.target;
-      let value;
-      if (target.type === "checkbox" || target.type === "radio") {
-        value = target.checked ? "true" : "false";
-      } else {
-        value = target.value ?? target.textContent;
-      }
-      return {
-        value: value,
-        values: {},
-      };
-    }
-    case "input":
-    case "invalid":
-    case "reset":
-    case "submit": {
-      let target = event.target;
-      let value = target.value ?? target.textContent;
-
-      if (target.type === "checkbox") {
-        value = target.checked ? "true" : "false";
-      }
-
-      return {
-        value: value,
-        values: {},
-      };
-    }
-    case "click":
-    case "contextmenu":
-    case "doubleclick":
-    case "dblclick":
-    case "drag":
-    case "dragend":
-    case "dragenter":
-    case "dragexit":
-    case "dragleave":
-    case "dragover":
-    case "dragstart":
-    case "drop":
-    case "mousedown":
-    case "mouseenter":
-    case "mouseleave":
-    case "mousemove":
-    case "mouseout":
-    case "mouseover":
-    case "mouseup": {
-      const {
-        altKey,
-        button,
-        buttons,
-        clientX,
-        clientY,
-        ctrlKey,
-        metaKey,
-        offsetX,
-        offsetY,
-        pageX,
-        pageY,
-        screenX,
-        screenY,
-        shiftKey,
-      } = event;
-      return {
-        alt_key: altKey,
-        button: button,
-        buttons: buttons,
-        client_x: clientX,
-        client_y: clientY,
-        ctrl_key: ctrlKey,
-        meta_key: metaKey,
-        offset_x: offsetX,
-        offset_y: offsetY,
-        page_x: pageX,
-        page_y: pageY,
-        screen_x: screenX,
-        screen_y: screenY,
-        shift_key: shiftKey,
-      };
-    }
-    case "pointerdown":
-    case "pointermove":
-    case "pointerup":
-    case "pointercancel":
-    case "gotpointercapture":
-    case "lostpointercapture":
-    case "pointerenter":
-    case "pointerleave":
-    case "pointerover":
-    case "pointerout": {
-      const {
-        altKey,
-        button,
-        buttons,
-        clientX,
-        clientY,
-        ctrlKey,
-        metaKey,
-        pageX,
-        pageY,
-        screenX,
-        screenY,
-        shiftKey,
-        pointerId,
-        width,
-        height,
-        pressure,
-        tangentialPressure,
-        tiltX,
-        tiltY,
-        twist,
-        pointerType,
-        isPrimary,
-      } = event;
-      return {
-        alt_key: altKey,
-        button: button,
-        buttons: buttons,
-        client_x: clientX,
-        client_y: clientY,
-        ctrl_key: ctrlKey,
-        meta_key: metaKey,
-        page_x: pageX,
-        page_y: pageY,
-        screen_x: screenX,
-        screen_y: screenY,
-        shift_key: shiftKey,
-        pointer_id: pointerId,
-        width: width,
-        height: height,
-        pressure: pressure,
-        tangential_pressure: tangentialPressure,
-        tilt_x: tiltX,
-        tilt_y: tiltY,
-        twist: twist,
-        pointer_type: pointerType,
-        is_primary: isPrimary,
-      };
-    }
-    case "select": {
-      return {};
-    }
-    case "touchcancel":
-    case "touchend":
-    case "touchmove":
-    case "touchstart": {
-      const { altKey, ctrlKey, metaKey, shiftKey } = event;
-      return {
-        // changed_touches: event.changedTouches,
-        // target_touches: event.targetTouches,
-        // touches: event.touches,
-        alt_key: altKey,
-        ctrl_key: ctrlKey,
-        meta_key: metaKey,
-        shift_key: shiftKey,
-      };
-    }
-    case "scroll": {
-      return {};
-    }
-    case "wheel": {
-      const { deltaX, deltaY, deltaZ, deltaMode } = event;
-      return {
-        delta_x: deltaX,
-        delta_y: deltaY,
-        delta_z: deltaZ,
-        delta_mode: deltaMode,
-      };
-    }
-    case "animationstart":
-    case "animationend":
-    case "animationiteration": {
-      const { animationName, elapsedTime, pseudoElement } = event;
-      return {
-        animation_name: animationName,
-        elapsed_time: elapsedTime,
-        pseudo_element: pseudoElement,
-      };
-    }
-    case "transitionend": {
-      const { propertyName, elapsedTime, pseudoElement } = event;
-      return {
-        property_name: propertyName,
-        elapsed_time: elapsedTime,
-        pseudo_element: pseudoElement,
-      };
-    }
-    case "abort":
-    case "canplay":
-    case "canplaythrough":
-    case "durationchange":
-    case "emptied":
-    case "encrypted":
-    case "ended":
-    case "error":
-    case "loadeddata":
-    case "loadedmetadata":
-    case "loadstart":
-    case "pause":
-    case "play":
-    case "playing":
-    case "progress":
-    case "ratechange":
-    case "seeked":
-    case "seeking":
-    case "stalled":
-    case "suspend":
-    case "timeupdate":
-    case "volumechange":
-    case "waiting": {
-      return {};
-    }
-    case "toggle": {
-      return {};
-    }
-    default: {
-      return {};
-    }
-  }
-}
-function serializeIpcMessage(method, params = {}) {
-  return JSON.stringify({ method, params });
-}
-const bool_attrs = {
-  allowfullscreen: true,
-  allowpaymentrequest: true,
-  async: true,
-  autofocus: true,
-  autoplay: true,
-  checked: true,
-  controls: true,
-  default: true,
-  defer: true,
-  disabled: true,
-  formnovalidate: true,
-  hidden: true,
-  ismap: true,
-  itemscope: true,
-  loop: true,
-  multiple: true,
-  muted: true,
-  nomodule: true,
-  novalidate: true,
-  open: true,
-  playsinline: true,
-  readonly: true,
-  required: true,
-  reversed: true,
-  selected: true,
-  truespeed: true,
-};
-
-function is_element_node(node) {
-  return node.nodeType == 1;
-}
-
-function event_bubbles(event) {
-  switch (event) {
-    case "copy":
-      return true;
-    case "cut":
-      return true;
-    case "paste":
-      return true;
-    case "compositionend":
-      return true;
-    case "compositionstart":
-      return true;
-    case "compositionupdate":
-      return true;
-    case "keydown":
-      return true;
-    case "keypress":
-      return true;
-    case "keyup":
-      return true;
-    case "focus":
-      return false;
-    case "focusout":
-      return true;
-    case "focusin":
-      return true;
-    case "blur":
-      return false;
-    case "change":
-      return true;
-    case "input":
-      return true;
-    case "invalid":
-      return true;
-    case "reset":
-      return true;
-    case "submit":
-      return true;
-    case "click":
-      return true;
-    case "contextmenu":
-      return true;
-    case "doubleclick":
-      return true;
-    case "dblclick":
-      return true;
-    case "drag":
-      return true;
-    case "dragend":
-      return true;
-    case "dragenter":
-      return false;
-    case "dragexit":
-      return false;
-    case "dragleave":
-      return true;
-    case "dragover":
-      return true;
-    case "dragstart":
-      return true;
-    case "drop":
-      return true;
-    case "mousedown":
-      return true;
-    case "mouseenter":
-      return false;
-    case "mouseleave":
-      return false;
-    case "mousemove":
-      return true;
-    case "mouseout":
-      return true;
-    case "scroll":
-      return false;
-    case "mouseover":
-      return true;
-    case "mouseup":
-      return true;
-    case "pointerdown":
-      return true;
-    case "pointermove":
-      return true;
-    case "pointerup":
-      return true;
-    case "pointercancel":
-      return true;
-    case "gotpointercapture":
-      return true;
-    case "lostpointercapture":
-      return true;
-    case "pointerenter":
-      return false;
-    case "pointerleave":
-      return false;
-    case "pointerover":
-      return true;
-    case "pointerout":
-      return true;
-    case "select":
-      return true;
-    case "touchcancel":
-      return true;
-    case "touchend":
-      return true;
-    case "touchmove":
-      return true;
-    case "touchstart":
-      return true;
-    case "wheel":
-      return true;
-    case "abort":
-      return false;
-    case "canplay":
-      return false;
-    case "canplaythrough":
-      return false;
-    case "durationchange":
-      return false;
-    case "emptied":
-      return false;
-    case "encrypted":
-      return true;
-    case "ended":
-      return false;
-    case "error":
-      return false;
-    case "loadeddata":
-      return false;
-    case "loadedmetadata":
-      return false;
-    case "loadstart":
-      return false;
-    case "pause":
-      return false;
-    case "play":
-      return false;
-    case "playing":
-      return false;
-    case "progress":
-      return false;
-    case "ratechange":
-      return false;
-    case "seeked":
-      return false;
-    case "seeking":
-      return false;
-    case "stalled":
-      return false;
-    case "suspend":
-      return false;
-    case "timeupdate":
-      return false;
-    case "volumechange":
-      return false;
-    case "waiting":
-      return false;
-    case "animationstart":
-      return true;
-    case "animationend":
-      return true;
-    case "animationiteration":
-      return true;
-    case "transitionend":
-      return true;
-    case "toggle":
-      return true;
-  }
-}

+ 54 - 2
packages/liveview/README.md

@@ -1,3 +1,55 @@
-# Dioxus LiveView
+# Dioxus Liveview
 
-Server rendered apps with minimal latency
+
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
+
+[crates-badge]: https://img.shields.io/crates/v/dioxus-liveview.svg
+[crates-url]: https://crates.io/crates/dioxus-liveview
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-liveview/latest/dioxus-liveview) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+
+## Overview
+
+`dioxus-liveview` provides adapters for running the Dioxus VirtualDom over a websocket connection.
+
+The current backend frameworks supported include:
+
+- Axum
+- Warp
+- Salvo
+
+Dioxus-LiveView exports a number of primitives to wire up an app into an existing backend framework.
+
+- A threadpool for spawning the `!Send` VirtualDom and interacting with it from the websocket
+- An adapter for transforming various socket types into the `LiveViewSocket` type
+- The glue to load the interpreter into your app
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.

+ 43 - 4
packages/mobile/README.md

@@ -1,11 +1,34 @@
-# Getting started: mobile
+# Dioxus Mobile
 
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
 
-Dioxus is unique in that it actually supports mobile. However, support is very young and you might need to dip down into some of the primitives until better supported is ready.
+[crates-badge]: https://img.shields.io/crates/v/dioxus-mobile.svg
+[crates-url]: https://crates.io/crates/dioxus-mobile
 
-Currently, only iOS is supported through us, however you *can* add android support by following the same instructions below, but using the `android` guide in `cargo-mobile`.
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-mobile/latest/dioxus-mobile) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+
+## Overview
+
+`dioxus-mobile` is a re-export of `dioxus-desktop` with some minor tweaks and documentation changes. As this crate evolves, it will provide some more unique features to mobile, but for now, it's very similar to the desktop crate.
+
+Dioxus Mobile supports both iOS and Android. However, Android support is still quite experimental and requires a lot of configuration. A good area to contribute here would be to improve the CLI tool to include bundling and mobile configuration.
 
-Also, Dioxus Desktop and Dioxus Mobile share the same codebase, and dioxus-mobile currently just re-exports dioxus-desktop.
 
 ## Getting Set up
 
@@ -76,3 +99,19 @@ To configure the webview, menubar, and other important desktop-specific features
 ## Future Steps
 
 Make sure to read the [Dioxus Guide](https://dioxuslabs.com/guide) if you already haven't!
+
+
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.

+ 43 - 0
packages/native-core-macro/README.md

@@ -0,0 +1,43 @@
+# Dioxus Native Core Macro
+
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
+
+[crates-badge]: https://img.shields.io/crates/v/dioxus-native-core-macro.svg
+[crates-url]: https://crates.io/crates/dioxus-native-core-macro
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-native-core-macro/latest/dioxus-native-core-macro) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+
+## Overview
+
+`dioxus-native-core-macro` provides a handful of macros used by native-core for native renderers like TUI, Blitz, and Freya to derive their own state.
+
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.

+ 45 - 1
packages/native-core/README.md

@@ -1 +1,45 @@
-# Dioxus Native-Core: An lazy approach to GUI state and trees
+# Dioxus Native Core
+
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
+
+[crates-badge]: https://img.shields.io/crates/v/dioxus-native-core.svg
+[crates-url]: https://crates.io/crates/dioxus-native-core
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-native-core/latest/dioxus-native-core) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+
+## Overview
+
+`dioxus-native-core` provides a number of helpful utilities for lazily resolving computed values of the Dioxus VirtualDom to be used in conjunction with a native rendering engine.
+
+The main "value-add" of this crate over implementing your own native tree is that this tree is incrementally recomputed using the Dioxus VirtualDom's edit stream. Only parts of the tree that rely on each other will be redrawn - all else will be ignored.
+
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.

+ 42 - 57
packages/router/README.md

@@ -1,55 +1,31 @@
-<div align="center">
-  <h1>Dioxus Router</h1>
-</div>
-
-
-<div align="center">
-  <!-- Crates version -->
-  <a href="https://crates.io/crates/dioxus">
-    <img src="https://img.shields.io/crates/v/dioxus.svg?style=flat-square"
-    alt="Crates.io version" />
-  </a>
-  <!-- Downloads -->
-  <a href="https://crates.io/crates/dioxus">
-    <img src="https://img.shields.io/crates/d/dioxus.svg?style=flat-square"
-      alt="Download" />
-  </a>
-  <!-- docs -->
-  <a href="https://docs.rs/dioxus">
-    <img src="https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square"
-      alt="docs.rs docs" />
-  </a>
-  <!-- CI -->
-  <a href="https://github.com/jkelleyrtp/dioxus/actions">
-    <img src="https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg"
-      alt="CI status" />
-  </a>
-
-  <!--Awesome -->
-  <a href="https://github.com/dioxuslabs/awesome-dioxus">
-    <img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome Page" />
-  </a>
-  <!-- Discord -->
-  <a href="https://discord.gg/XgGxMSkvUM">
-    <img src="https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square" alt="Discord Link" />
-  </a>
-</div>
-
-
-
-<div align="center">
-  <h3>
-    <a href="https://dioxuslabs.com"> Website </a>
-    <span> | </span>
-    <a href="https://github.com/DioxusLabs/example-projects"> Examples </a>
-    <span> | </span>
-    <a href="https://dioxuslabs.com/router"> Guide (Latest) </a>
-    <span> | </span>
-    <a href="https://dioxuslabs.com/nightly/router"> Guide (Master) </a>
-  </h3>
-</div>
-
-Dioxus Router is a first-party Router for all your Dioxus Apps. It provides a React-Router style interface that works anywhere: across the browser, SSR, and natively.
+# Dioxus Native Core
+
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
+
+[crates-badge]: https://img.shields.io/crates/v/dioxus-router.svg
+[crates-url]: https://crates.io/crates/dioxus-router
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-router/latest/dioxus-router) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+
+## Overview
+
+Dioxus Router is a first-party Router for all your Dioxus Apps. It provides a React-Router style interface using somewhat loose typing rules.
 
 ```rust, ignore
 fn app() {
@@ -63,10 +39,19 @@ fn app() {
 }
 ```
 
+You need to enable the right features for the platform you're targeting since these are not determined automatically!
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
 
-## Resources
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.
 
-- See the mdbook
-- See the one-page brief
-- See the guide on the doc site
-- The crates.io API

+ 42 - 2
packages/rsx-rosetta/README.md

@@ -1,5 +1,30 @@
-# Rosetta for RSX
----
+
+
+# `rsx-rosetta`
+
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
+
+[crates-badge]: https://img.shields.io/crates/v/rsx-rosetta.svg
+[crates-url]: https://crates.io/crates/rsx-rosetta
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/rsx-rosetta/latest/rsx-rosetta) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+## Overview
 
 Dioxus sports its own templating language inspired by C#/Kotlin/RTMP, etc. It's pretty straightforward.
 
@@ -17,3 +42,18 @@ This library provids a central AST that can accept a number of inputs:
 - Jinja (todo)
 
 From there, you can convert directly to a string or into some other AST.
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.
+

+ 1 - 1
packages/rsx-rosetta/src/lib.rs

@@ -81,7 +81,7 @@ pub fn rsx_node_from_html(node: &Node) -> Option<BodyNode> {
     }
 }
 
-/// Pull out all the svgs from the body and replace them with components
+/// Pull out all the svgs from the body and replace them with components of the same name
 pub fn collect_svgs(children: &mut [BodyNode], out: &mut Vec<BodyNode>) {
     for child in children {
         match child {

+ 43 - 1
packages/rsx/README.md

@@ -1 +1,43 @@
-# The actual RSX language implemented using syn parsers.
+# Dioxus-RSX
+
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
+
+[crates-badge]: https://img.shields.io/crates/v/dioxus-rsx.svg
+[crates-url]: https://crates.io/crates/dioxus-rsx
+
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/dioxus-rsx/latest/dioxus-rsx) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+
+## Overview
+
+This crate provides the actual DSL that Dioxus uses in the `rsx!` macro. This crate is separate from the macro crate to enable tooling like autoformat, translation, and AST manipulation (extract to component).
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.
+

+ 1 - 28
packages/ssr/README.md

@@ -51,33 +51,6 @@ let _ = dom.rebuild();
 let content = dioxus_ssr::render_vdom(&dom);
 ```
 
-## Configuring output
-It's possible to configure the output of the generated HTML.
-
-```rust, ignore
-let content = dioxus_ssr::render_vdom(&dom, |config| config.pretty(true).prerender(true));
-```
-
-## Usage as a writer
-
-We provide the basic `SsrFormatter` object that implements `Display`, so you can integrate SSR into an existing string, or write directly to a file.
-
-```rust, ignore
-use std::fmt::{Error, Write};
-
-let mut buf = String::new();
-
-let dom = VirtualDom::new(app);
-let _ = dom.rebuild();
-
-let args = dioxus_ssr::formatter(dom, |config| config);
-buf.write_fmt!(format_args!("{}", args));
-```
-
-## Configuration
-
-
-
 
 
 
@@ -95,7 +68,7 @@ To enable pre-rendering, simply configure the `SsrConfig` with pre-rendering ena
 ```rust, ignore
 let dom = VirtualDom::new(App);
 
-let text = dioxus_ssr::render_vdom(App, |cfg| cfg.pre_render(true));
+let text = dioxus_ssr::render_vdom(App, Config { pre_render: true, ..Default::default() });
 ```
 
 ## Usage in server-side rendering

+ 42 - 7
packages/web/README.md

@@ -1,11 +1,46 @@
-# Dioxus-Web
+# Dioxus-web
 
-Build interactive user experiences directly in the web browser!
+[![Crates.io][crates-badge]][crates-url]
+[![MIT licensed][mit-badge]][mit-url]
+[![Build Status][actions-badge]][actions-url]
+[![Discord chat][discord-badge]][discord-url]
 
-Dioxus-web provides a `WebsysRenderer` for the Dioxus Virtual Dom that handles events, progresses components, and updates the actual DOM using web-sys methods.
+[crates-badge]: https://img.shields.io/crates/v/rsx-rosetta.svg
+[crates-url]: https://crates.io/crates/rsx-rosetta
 
+[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
+[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
+
+[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
+[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
+
+[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
+[discord-url]: https://discord.gg/XgGxMSkvUM
+
+[Website](https://dioxuslabs.com) |
+[Guides](https://dioxuslabs.com/guide/) |
+[API Docs](https://docs.rs/rsx-rosetta/latest/rsx-rosetta) |
+[Chat](https://discord.gg/XgGxMSkvUM)
+
+## Overview
+
+Run Dioxus in the browser using WebAssembly.
+
+- Relies on sledgehammer and websys to modify the dom
+- Supports instant hotreloading via the Dioxus CLI
+- Around 60k gzipped
+
+## Contributing
+
+- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
+- Join the discord and ask questions!
+
+## License
+This project is licensed under the [MIT license].
+
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Dioxus by you, shall be licensed as MIT, without any additional
+terms or conditions.
 
-## Web-specific Optimizations
-- Uses string interning of all common node types
-- Optimistically interns short strings
-- Builds trees completely before mounting them