Selaa lähdekoodia

fix native core, plasmo and dioxus-tui

Evan Almloff 1 vuosi sitten
vanhempi
commit
439e39bab4
37 muutettua tiedostoa jossa 588 lisäystä ja 266 poistoa
  1. 257 1
      Cargo.lock
  2. 8 8
      Cargo.toml
  3. 88 29
      packages/dioxus-tui/src/element.rs
  4. 37 51
      packages/dioxus-tui/src/lib.rs
  5. 0 2
      packages/html/src/events/keyboard.rs
  6. 174 152
      packages/native-core/src/dioxus.rs
  7. 9 8
      packages/native-core/src/node.rs
  8. 0 0
      packages/plasmo/.gitignore
  9. 0 0
      packages/plasmo/.vscode/spellright.dict
  10. 0 0
      packages/plasmo/Cargo.toml
  11. 13 13
      packages/plasmo/README.md
  12. 0 0
      packages/plasmo/examples/counter_button.rs
  13. 0 0
      packages/plasmo/examples/example.png
  14. 0 0
      packages/plasmo/examples/grid.rs
  15. 0 0
      packages/plasmo/examples/widgets.rs
  16. 0 0
      packages/plasmo/src/config.rs
  17. 0 0
      packages/plasmo/src/focus.rs
  18. 0 0
      packages/plasmo/src/hooks.rs
  19. 0 0
      packages/plasmo/src/layout.rs
  20. 0 0
      packages/plasmo/src/lib.rs
  21. 0 0
      packages/plasmo/src/prevent_default.rs
  22. 0 0
      packages/plasmo/src/query.rs
  23. 0 0
      packages/plasmo/src/render.rs
  24. 1 1
      packages/plasmo/src/style.rs
  25. 0 0
      packages/plasmo/src/style_attributes.rs
  26. 0 0
      packages/plasmo/src/widget.rs
  27. 0 0
      packages/plasmo/src/widgets/button.rs
  28. 0 0
      packages/plasmo/src/widgets/checkbox.rs
  29. 0 0
      packages/plasmo/src/widgets/input.rs
  30. 0 0
      packages/plasmo/src/widgets/mod.rs
  31. 0 0
      packages/plasmo/src/widgets/number.rs
  32. 0 0
      packages/plasmo/src/widgets/password.rs
  33. 0 0
      packages/plasmo/src/widgets/slider.rs
  34. 0 0
      packages/plasmo/src/widgets/text_like.rs
  35. 0 0
      packages/plasmo/src/widgets/textbox.rs
  36. 0 0
      packages/plasmo/test.html
  37. 1 1
      translations/pt-br/README.md

+ 257 - 1
Cargo.lock

@@ -203,6 +203,12 @@ version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344"
 
+[[package]]
+name = "anymap"
+version = "1.0.0-beta.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f1f8f5a6f3d50d89e3797d7593a50f96bb2aaa20ca0cc7be1fb673232c91d72"
+
 [[package]]
 name = "anymap2"
 version = "0.13.0"
@@ -1354,6 +1360,12 @@ dependencies = [
  "toml 0.8.2",
 ]
 
+[[package]]
+name = "cassowary"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
+
 [[package]]
 name = "cast"
 version = "0.3.0"
@@ -1947,6 +1959,47 @@ version = "0.8.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
 
+[[package]]
+name = "crossterm"
+version = "0.26.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13"
+dependencies = [
+ "bitflags 1.3.2",
+ "crossterm_winapi",
+ "libc",
+ "mio",
+ "parking_lot",
+ "signal-hook",
+ "signal-hook-mio",
+ "winapi",
+]
+
+[[package]]
+name = "crossterm"
+version = "0.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
+dependencies = [
+ "bitflags 2.4.2",
+ "crossterm_winapi",
+ "libc",
+ "mio",
+ "parking_lot",
+ "signal-hook",
+ "signal-hook-mio",
+ "winapi",
+]
+
+[[package]]
+name = "crossterm_winapi"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
+dependencies = [
+ "winapi",
+]
+
 [[package]]
 name = "cruet"
 version = "0.14.0"
@@ -2503,7 +2556,7 @@ dependencies = [
 name = "dioxus-fullstack"
 version = "0.4.3"
 dependencies = [
- "anymap",
+ "anymap 0.12.1",
  "async-trait",
  "axum 0.6.20",
  "base64 0.21.7",
@@ -2668,6 +2721,40 @@ dependencies = [
  "dioxus-desktop",
 ]
 
+[[package]]
+name = "dioxus-native-core"
+version = "0.4.3"
+dependencies = [
+ "anymap 1.0.0-beta.2",
+ "dashmap",
+ "dioxus",
+ "dioxus-core",
+ "dioxus-native-core",
+ "dioxus-native-core-macro",
+ "keyboard-types",
+ "lightningcss",
+ "parking_lot",
+ "rand 0.8.5",
+ "rustc-hash",
+ "shipyard",
+ "smallvec",
+ "taffy",
+ "tokio",
+]
+
+[[package]]
+name = "dioxus-native-core-macro"
+version = "0.4.3"
+dependencies = [
+ "anymap 0.12.1",
+ "dioxus",
+ "dioxus-native-core",
+ "quote",
+ "rustc-hash",
+ "smallvec",
+ "syn 2.0.48",
+]
+
 [[package]]
 name = "dioxus-playwright-fullstack-test"
 version = "0.1.0"
@@ -2817,6 +2904,24 @@ dependencies = [
  "manganis",
 ]
 
+[[package]]
+name = "dioxus-tui"
+version = "0.4.3"
+dependencies = [
+ "criterion 0.3.6",
+ "crossterm 0.26.1",
+ "dioxus",
+ "dioxus-core",
+ "dioxus-hot-reload",
+ "dioxus-html",
+ "dioxus-native-core",
+ "dioxus-native-core-macro",
+ "futures",
+ "plasmo",
+ "taffy",
+ "tokio",
+]
+
 [[package]]
 name = "dioxus-web"
 version = "0.4.3"
@@ -4316,6 +4421,12 @@ dependencies = [
  "system-deps",
 ]
 
+[[package]]
+name = "grid"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eec1c01eb1de97451ee0d60de7d81cf1e72aabefb021616027f3d1c3ec1c723c"
+
 [[package]]
 name = "gtk"
 version = "0.18.1"
@@ -5175,6 +5286,15 @@ dependencies = [
  "either",
 ]
 
+[[package]]
+name = "itertools"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
+dependencies = [
+ "either",
+]
+
 [[package]]
 name = "itertools"
 version = "0.12.0"
@@ -5692,6 +5812,15 @@ dependencies = [
  "hashbrown 0.13.2",
 ]
 
+[[package]]
+name = "lru"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2994eeba8ed550fd9b47a0b38f0242bc3344e496483c6180b69139cc2fa5d1d7"
+dependencies = [
+ "hashbrown 0.14.3",
+]
+
 [[package]]
 name = "lru-cache"
 version = "0.1.2"
@@ -7033,6 +7162,28 @@ version = "0.3.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
 
+[[package]]
+name = "plasmo"
+version = "0.4.3"
+dependencies = [
+ "anyhow",
+ "anymap 1.0.0-beta.2",
+ "criterion 0.3.6",
+ "crossterm 0.26.1",
+ "dioxus-html",
+ "dioxus-native-core",
+ "dioxus-native-core-macro",
+ "futures",
+ "futures-channel",
+ "once_cell",
+ "ratatui",
+ "rustc-hash",
+ "shipyard",
+ "smallvec",
+ "taffy",
+ "tokio",
+]
+
 [[package]]
 name = "plist"
 version = "1.6.0"
@@ -7463,6 +7614,24 @@ dependencies = [
  "rand_core 0.5.1",
 ]
 
+[[package]]
+name = "ratatui"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ebc917cfb527a566c37ecb94c7e3fd098353516fb4eb6bea17015ade0182425"
+dependencies = [
+ "bitflags 2.4.2",
+ "cassowary",
+ "crossterm 0.27.0",
+ "indoc",
+ "itertools 0.11.0",
+ "lru 0.12.1",
+ "paste",
+ "strum",
+ "unicode-segmentation",
+ "unicode-width",
+]
+
 [[package]]
 name = "rav1e"
 version = "0.6.6"
@@ -8744,6 +8913,50 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
 
+[[package]]
+name = "shipyard"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3511ae730f2e1c3d62a9025e2f9b2acbf130968057f1b3caab6d74a54a5e0e56"
+dependencies = [
+ "hashbrown 0.12.3",
+ "lock_api",
+ "rayon",
+ "shipyard_proc",
+]
+
+[[package]]
+name = "shipyard_proc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3eb847f4b9582e468198b5cfb5731b65cc67fe5e535acc9cbf3c11703d15f08c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "signal-hook"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
+dependencies = [
+ "libc",
+ "signal-hook-registry",
+]
+
+[[package]]
+name = "signal-hook-mio"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
+dependencies = [
+ "libc",
+ "mio",
+ "signal-hook",
+]
+
 [[package]]
 name = "signal-hook-registry"
 version = "1.4.1"
@@ -8841,6 +9054,15 @@ dependencies = [
  "rustc-hash",
 ]
 
+[[package]]
+name = "slotmap"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"
+dependencies = [
+ "version_check",
+]
+
 [[package]]
 name = "smallvec"
 version = "1.13.0"
@@ -9265,6 +9487,28 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
+[[package]]
+name = "strum"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.25.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
+dependencies = [
+ "heck 0.4.1",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.48",
+]
+
 [[package]]
 name = "subprocess"
 version = "0.2.9"
@@ -9365,6 +9609,18 @@ dependencies = [
  "version-compare",
 ]
 
+[[package]]
+name = "taffy"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c2287b6d7f721ada4cddf61ade5e760b2c6207df041cac9bfaa192897362fd3"
+dependencies = [
+ "arrayvec",
+ "grid",
+ "num-traits",
+ "slotmap",
+]
+
 [[package]]
 name = "tao"
 version = "0.24.1"

+ 8 - 8
Cargo.toml

@@ -24,10 +24,10 @@ members = [
     "packages/autofmt",
     "packages/check",
     "packages/rsx",
-    # "packages/dioxus-tui",
-    # "packages/rink",
-    # "packages/native-core",
-    # "packages/native-core-macro",
+    "packages/dioxus-tui",
+    "packages/plasmo",
+    "packages/native-core",
+    "packages/native-core-macro",
     "packages/rsx-rosetta",
     "packages/generational-box",
     "packages/signals",
@@ -78,10 +78,10 @@ dioxus-liveview = { path = "packages/liveview", version = "0.4.0"  }
 dioxus-autofmt = { path = "packages/autofmt", version = "0.4.0"  }
 dioxus-check = { path = "packages/check", version = "0.4.0"  }
 dioxus-rsx = { path = "packages/rsx", version = "0.4.0"  }
-# dioxus-tui = { path = "packages/dioxus-tui", version = "0.4.0"  }
-# plasmo = { path = "packages/rink", version = "0.4.0" }
-# dioxus-native-core = { path = "packages/native-core", version = "0.4.0" }
-# dioxus-native-core-macro = { path = "packages/native-core-macro", version = "0.4.0" }
+dioxus-tui = { path = "packages/dioxus-tui", version = "0.4.0"  }
+plasmo = { path = "packages/plasmo", version = "0.4.0" }
+dioxus-native-core = { path = "packages/native-core", version = "0.4.0" }
+dioxus-native-core-macro = { path = "packages/native-core-macro", version = "0.4.0" }
 rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.4.0" }
 dioxus-signals = { path = "packages/signals" }
 dioxus-cli-config = { path = "packages/cli-config", version = "0.4.1" }

+ 88 - 29
packages/dioxus-tui/src/element.rs

@@ -3,45 +3,104 @@ use std::{
     fmt::{Display, Formatter},
 };
 
-use dioxus_core::{ElementId, Mutations, VirtualDom};
+use dioxus_core::{ElementId, WriteMutations};
 use dioxus_html::{
     geometry::euclid::{Point2D, Rect, Size2D},
     MountedData, MountedError, RenderedElementBacking,
 };
 
-use dioxus_native_core::NodeId;
+use dioxus_native_core::{dioxus::DioxusNativeCoreMutationWriter, NodeId};
 use plasmo::query::{ElementRef, Query};
 
-pub(crate) fn find_mount_events(mutations: &Mutations) -> Vec<ElementId> {
-    let mut mount_events = Vec::new();
-    for mutation in &mutations.edits {
-        if let dioxus_core::Mutation::NewEventListener {
-            name: "mounted",
-            id,
-        } = mutation
-        {
-            mount_events.push(*id);
+pub(crate) struct DioxusTUIMutationWriter<'a> {
+    pub(crate) query: Query,
+    pub(crate) events: &'a mut Vec<(ElementId, &'static str, Box<dyn Any>, bool)>,
+    pub(crate) native_core_writer: DioxusNativeCoreMutationWriter<'a>,
+}
+
+impl WriteMutations for DioxusTUIMutationWriter<'_> {
+    fn register_template(&mut self, template: dioxus_core::prelude::Template) {
+        self.native_core_writer.register_template(template)
+    }
+
+    fn append_children(&mut self, id: ElementId, m: usize) {
+        self.native_core_writer.append_children(id, m)
+    }
+
+    fn assign_node_id(&mut self, path: &'static [u8], id: ElementId) {
+        self.native_core_writer.assign_node_id(path, id)
+    }
+
+    fn create_placeholder(&mut self, id: ElementId) {
+        self.native_core_writer.create_placeholder(id)
+    }
+
+    fn create_text_node(&mut self, value: &str, id: ElementId) {
+        self.native_core_writer.create_text_node(value, id)
+    }
+
+    fn hydrate_text_node(&mut self, path: &'static [u8], value: &str, id: ElementId) {
+        self.native_core_writer.hydrate_text_node(path, value, id)
+    }
+
+    fn load_template(&mut self, name: &'static str, index: usize, id: ElementId) {
+        self.native_core_writer.load_template(name, index, id)
+    }
+
+    fn replace_node_with(&mut self, id: ElementId, m: usize) {
+        self.native_core_writer.replace_node_with(id, m)
+    }
+
+    fn replace_placeholder_with_nodes(&mut self, path: &'static [u8], m: usize) {
+        self.native_core_writer
+            .replace_placeholder_with_nodes(path, m)
+    }
+
+    fn insert_nodes_after(&mut self, id: ElementId, m: usize) {
+        self.native_core_writer.insert_nodes_after(id, m)
+    }
+
+    fn insert_nodes_before(&mut self, id: ElementId, m: usize) {
+        self.native_core_writer.insert_nodes_before(id, m)
+    }
+
+    fn set_attribute(
+        &mut self,
+        name: &'static str,
+        ns: Option<&'static str>,
+        value: &dioxus_core::AttributeValue,
+        id: ElementId,
+    ) {
+        self.native_core_writer.set_attribute(name, ns, value, id)
+    }
+
+    fn set_node_text(&mut self, value: &str, id: ElementId) {
+        self.native_core_writer.set_node_text(value, id)
+    }
+
+    fn create_event_listener(&mut self, name: &'static str, id: ElementId) {
+        if name == "mounted" {
+            let element = TuiElement {
+                query: self.query.clone(),
+                id: self.native_core_writer.state.element_to_node_id(id),
+            };
+            self.events
+                .push((id, "mounted", Box::new(MountedData::new(element)), false));
+        } else {
+            self.native_core_writer.create_event_listener(name, id)
         }
     }
-    mount_events
-}
 
-// We need to queue the mounted events to give rink time to rendere and resolve the layout of elements after they are created
-pub(crate) fn create_mounted_events(
-    vdom: &VirtualDom,
-    events: &mut Vec<(ElementId, &'static str, Box<dyn Any>, bool)>,
-    mount_events: impl Iterator<Item = (ElementId, NodeId)>,
-) {
-    let query: Query = vdom
-        .base_scope()
-        .consume_context()
-        .expect("Query should be in context");
-    for (id, node_id) in mount_events {
-        let element = TuiElement {
-            query: query.clone(),
-            id: node_id,
-        };
-        events.push((id, "mounted", Box::new(MountedData::new(element)), false));
+    fn remove_event_listener(&mut self, name: &'static str, id: ElementId) {
+        self.native_core_writer.remove_event_listener(name, id)
+    }
+
+    fn remove_node(&mut self, id: ElementId) {
+        self.native_core_writer.remove_node(id)
+    }
+
+    fn push_root(&mut self, id: ElementId) {
+        self.native_core_writer.push_root(id)
     }
 }
 

+ 37 - 51
packages/dioxus-tui/src/lib.rs

@@ -12,24 +12,20 @@ use std::{
     sync::{Arc, RwLock},
 };
 
-use dioxus_core::{Component, ElementId, VirtualDom};
+use dioxus_core::{Element, ElementId, ScopeId, VirtualDom};
 use dioxus_html::PlatformEventData;
 use dioxus_native_core::dioxus::{DioxusState, NodeImmutableDioxusExt};
 use dioxus_native_core::prelude::*;
 
-use element::{create_mounted_events, find_mount_events};
+use element::DioxusTUIMutationWriter;
 pub use plasmo::{query::Query, Config, RenderingMode, Size, TuiContext};
 use plasmo::{render, Driver};
 
-pub fn launch(app: Component<()>) {
+pub fn launch(app: fn() -> Element) {
     launch_cfg(app, Config::default())
 }
 
-pub fn launch_cfg(app: Component<()>, cfg: Config) {
-    launch_cfg_with_props(app, (), cfg);
-}
-
-pub fn launch_cfg_with_props<Props: 'static>(app: Component<Props>, props: Props, cfg: Config) {
+pub fn launch_cfg(app: fn() -> Element, cfg: Config) {
     dioxus_html::set_event_converter(Box::new(events::SerializedHtmlEventConverter));
 
     render(cfg, |rdom, taffy, event_tx| {
@@ -38,36 +34,16 @@ pub fn launch_cfg_with_props<Props: 'static>(app: Component<Props>, props: Props
             DioxusState::create(&mut rdom)
         };
         let dioxus_state = Rc::new(RwLock::new(dioxus_state));
-        let mut vdom = VirtualDom::new_with_props(app, props)
+        let mut vdom = VirtualDom::new(app)
             .with_root_context(TuiContext::new(event_tx))
             .with_root_context(Query::new(rdom.clone(), taffy.clone()))
             .with_root_context(DioxusElementToNodeId {
                 mapping: dioxus_state.clone(),
             });
-        let muts = vdom.rebuild();
-
-        let mut queued_events = Vec::new();
 
-        {
-            let mut rdom = rdom.write().unwrap();
-            let mut dioxus_state = dioxus_state.write().unwrap();
+        let queued_events = Vec::new();
 
-            // Find any mount events
-            let mounted = find_mount_events(&muts);
-
-            dioxus_state.apply_mutations(&mut rdom, muts);
-
-            // Send the mount events
-            create_mounted_events(
-                &vdom,
-                &mut queued_events,
-                mounted
-                    .iter()
-                    .map(|id| (*dbg!(id), dioxus_state.element_to_node_id(*id))),
-            );
-        }
-
-        DioxusRenderer {
+        let mut myself = DioxusRenderer {
             vdom,
             dioxus_state,
             queued_events,
@@ -80,7 +56,25 @@ pub fn launch_cfg_with_props<Props: 'static>(app: Component<Props>, props: Props
                 });
                 hot_reload_rx
             },
+        };
+
+        {
+            let mut rdom = rdom.write().unwrap();
+            let mut dioxus_state = myself.dioxus_state.write().unwrap();
+
+            let mut writer = DioxusTUIMutationWriter {
+                query: myself
+                    .vdom
+                    .in_runtime(|| ScopeId::ROOT.consume_context().unwrap()),
+                events: &mut myself.queued_events,
+                native_core_writer: dioxus_state.create_mutation_writer(&mut rdom),
+            };
+
+            // Find any mount events
+            myself.vdom.rebuild(&mut writer);
         }
+
+        myself
     })
     .unwrap();
 }
@@ -96,27 +90,19 @@ struct DioxusRenderer {
 
 impl Driver for DioxusRenderer {
     fn update(&mut self, rdom: &Arc<RwLock<RealDom>>) {
-        let muts = self.vdom.render_immediate();
-        {
-            let mut rdom = rdom.write().unwrap();
+        let mut rdom = rdom.write().unwrap();
+        let mut dioxus_state = self.dioxus_state.write().unwrap();
+
+        let mut writer = DioxusTUIMutationWriter {
+            query: self
+                .vdom
+                .in_runtime(|| ScopeId::ROOT.consume_context().unwrap()),
+            events: &mut self.queued_events,
+            native_core_writer: dioxus_state.create_mutation_writer(&mut rdom),
+        };
 
-            {
-                // Find any mount events
-                let mounted = find_mount_events(&muts);
-
-                let mut dioxus_state = self.dioxus_state.write().unwrap();
-                dioxus_state.apply_mutations(&mut rdom, muts);
-
-                // Send the mount events
-                create_mounted_events(
-                    &self.vdom,
-                    &mut self.queued_events,
-                    mounted
-                        .iter()
-                        .map(|id| (*id, dioxus_state.element_to_node_id(*id))),
-                );
-            }
-        }
+        // Find any mount events
+        self.vdom.render_immediate(&mut writer);
     }
 
     fn handle_event(

+ 0 - 2
packages/html/src/events/keyboard.rs

@@ -246,8 +246,6 @@ impl<'de> serde::Deserialize<'de> for KeyCode {
     where
         D: serde::Deserializer<'de>,
     {
-        use std::convert::TryInto;
-
         // We could be deserializing a unicode character, so we need to use u64 even if the output only takes u8
         let value = u64::deserialize(deserializer)?;
 

+ 174 - 152
packages/native-core/src/dioxus.rs

@@ -1,7 +1,7 @@
 //! Integration between Dioxus and the RealDom
 
 use crate::tree::TreeMut;
-use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode};
+use dioxus_core::{AttributeValue, ElementId, TemplateNode, WriteMutations};
 use rustc_hash::{FxHashMap, FxHashSet};
 use shipyard::Component;
 
@@ -48,6 +48,14 @@ impl DioxusState {
         self.node_id_mapping.get(element_id.0).copied().flatten()
     }
 
+    /// Create a mutation writer for the RealDom
+    pub fn create_mutation_writer<'a, V: FromAnyValue + Send + Sync>(
+        &'a mut self,
+        rdom: &'a mut RealDom<V>,
+    ) -> DioxusNativeCoreMutationWriter<'a, V> {
+        DioxusNativeCoreMutationWriter { rdom, state: self }
+    }
+
     fn set_element_id<V: FromAnyValue + Send + Sync>(
         &mut self,
         mut node: NodeMut<V>,
@@ -74,165 +82,179 @@ impl DioxusState {
         }
         current.id()
     }
+}
+
+/// A writer for mutations that can be used with the RealDom.
+pub struct DioxusNativeCoreMutationWriter<'a, V: FromAnyValue + Send + Sync = ()> {
+    pub rdom: &'a mut RealDom<V>,
+    pub state: &'a mut DioxusState,
+}
+
+impl<V: FromAnyValue + Send + Sync> WriteMutations for DioxusNativeCoreMutationWriter<'_, V> {
+    fn register_template(&mut self, template: dioxus_core::prelude::Template) {
+        let mut template_root_ids = Vec::new();
+        for root in template.roots {
+            let id = create_template_node(self.rdom, root);
+            template_root_ids.push(id);
+        }
+        self.state
+            .templates
+            .insert(template.name.to_string(), template_root_ids);
+    }
+
+    fn append_children(&mut self, id: ElementId, m: usize) {
+        let children = self.state.stack.split_off(self.state.stack.len() - m);
+        let parent = self.state.element_to_node_id(id);
+        for child in children {
+            self.rdom.get_mut(parent).unwrap().add_child(child);
+        }
+    }
+
+    fn assign_node_id(&mut self, path: &'static [u8], id: ElementId) {
+        let node_id = self.state.load_child(self.rdom, path);
+        self.state
+            .set_element_id(self.rdom.get_mut(node_id).unwrap(), id);
+    }
+
+    fn create_placeholder(&mut self, id: ElementId) {
+        let node = NodeType::Placeholder;
+        let node = self.rdom.create_node(node);
+        let node_id = node.id();
+        self.state.set_element_id(node, id);
+        self.state.stack.push(node_id);
+    }
+
+    fn create_text_node(&mut self, value: &str, id: ElementId) {
+        let node_data = NodeType::Text(TextNode {
+            listeners: FxHashSet::default(),
+            text: value.to_string(),
+        });
+        let node = self.rdom.create_node(node_data);
+        let node_id = node.id();
+        self.state.set_element_id(node, id);
+        self.state.stack.push(node_id);
+    }
+
+    fn hydrate_text_node(&mut self, path: &'static [u8], value: &str, id: ElementId) {
+        let node_id = self.state.load_child(self.rdom, path);
+        let node = self.rdom.get_mut(node_id).unwrap();
+        self.state.set_element_id(node, id);
+        let mut node = self.rdom.get_mut(node_id).unwrap();
+        let node_type_mut = node.node_type_mut();
+        if let NodeTypeMut::Text(mut text) = node_type_mut {
+            *text.text_mut() = value.to_string();
+        } else {
+            drop(node_type_mut);
+            node.set_type(NodeType::Text(TextNode {
+                text: value.to_string(),
+                listeners: FxHashSet::default(),
+            }));
+        }
+    }
+
+    fn load_template(&mut self, name: &'static str, index: usize, id: ElementId) {
+        let template_id = self.state.templates[name][index];
+        let clone_id = self.rdom.get_mut(template_id).unwrap().clone_node();
+        let clone = self.rdom.get_mut(clone_id).unwrap();
+        self.state.set_element_id(clone, id);
+        self.state.stack.push(clone_id);
+    }
+
+    fn replace_node_with(&mut self, id: ElementId, m: usize) {
+        let new_nodes = self.state.stack.split_off(self.state.stack.len() - m);
+        let old_node_id = self.state.element_to_node_id(id);
+        for new in new_nodes {
+            let mut node = self.rdom.get_mut(new).unwrap();
+            node.insert_before(old_node_id);
+        }
+        self.rdom.get_mut(old_node_id).unwrap().remove();
+    }
+
+    fn replace_placeholder_with_nodes(&mut self, path: &'static [u8], m: usize) {
+        let new_nodes = self.state.stack.split_off(self.state.stack.len() - m);
+        let old_node_id = self.state.load_child(self.rdom, path);
+        for new in new_nodes {
+            let mut node = self.rdom.get_mut(new).unwrap();
+            node.insert_before(old_node_id);
+        }
+        self.rdom.get_mut(old_node_id).unwrap().remove();
+    }
+
+    fn insert_nodes_after(&mut self, id: ElementId, m: usize) {
+        let new_nodes = self.state.stack.split_off(self.state.stack.len() - m);
+        let old_node_id = self.state.element_to_node_id(id);
+        for new in new_nodes.into_iter().rev() {
+            let mut node = self.rdom.get_mut(new).unwrap();
+            node.insert_after(old_node_id);
+        }
+    }
+
+    fn insert_nodes_before(&mut self, id: ElementId, m: usize) {
+        let new_nodes = self.state.stack.split_off(self.state.stack.len() - m);
+        let old_node_id = self.state.element_to_node_id(id);
+        for new in new_nodes {
+            self.rdom.tree_mut().insert_before(old_node_id, new);
+        }
+    }
 
-    /// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state.
-    pub fn apply_mutations<V: FromAnyValue + Send + Sync>(
+    fn set_attribute(
         &mut self,
-        rdom: &mut RealDom<V>,
-        mutations: Mutations,
+        name: &'static str,
+        ns: Option<&'static str>,
+        value: &AttributeValue,
+        id: ElementId,
     ) {
-        for template in mutations.templates {
-            let mut template_root_ids = Vec::new();
-            for root in template.roots {
-                let id = create_template_node(rdom, root);
-                template_root_ids.push(id);
+        let node_id = self.state.element_to_node_id(id);
+        let mut node = self.rdom.get_mut(node_id).unwrap();
+        let mut node_type_mut = node.node_type_mut();
+        if let NodeTypeMut::Element(element) = &mut node_type_mut {
+            if let AttributeValue::None = &value {
+                element.remove_attribute(&OwnedAttributeDiscription {
+                    name: name.to_string(),
+                    namespace: ns.map(|s| s.to_string()),
+                });
+            } else {
+                element.set_attribute(
+                    OwnedAttributeDiscription {
+                        name: name.to_string(),
+                        namespace: ns.map(|s| s.to_string()),
+                    },
+                    OwnedAttributeValue::from(value),
+                );
             }
-            self.templates
-                .insert(template.name.to_string(), template_root_ids);
         }
+    }
 
-        for e in mutations.edits {
-            use dioxus_core::Mutation::*;
-            match e {
-                AppendChildren { id, m } => {
-                    let children = self.stack.split_off(self.stack.len() - m);
-                    let parent = self.element_to_node_id(id);
-                    for child in children {
-                        rdom.get_mut(parent).unwrap().add_child(child);
-                    }
-                }
-                AssignId { path, id } => {
-                    let node_id = self.load_child(rdom, path);
-                    self.set_element_id(rdom.get_mut(node_id).unwrap(), id);
-                }
-                CreatePlaceholder { id } => {
-                    let node = NodeType::Placeholder;
-                    let node = rdom.create_node(node);
-                    let node_id = node.id();
-                    self.set_element_id(node, id);
-                    self.stack.push(node_id);
-                }
-                CreateTextNode { value, id } => {
-                    let node_data = NodeType::Text(TextNode {
-                        listeners: FxHashSet::default(),
-                        text: value.to_string(),
-                    });
-                    let node = rdom.create_node(node_data);
-                    let node_id = node.id();
-                    self.set_element_id(node, id);
-                    self.stack.push(node_id);
-                }
-                HydrateText { path, value, id } => {
-                    let node_id = self.load_child(rdom, path);
-                    let node = rdom.get_mut(node_id).unwrap();
-                    self.set_element_id(node, id);
-                    let mut node = rdom.get_mut(node_id).unwrap();
-                    let node_type_mut = node.node_type_mut();
-                    if let NodeTypeMut::Text(mut text) = node_type_mut {
-                        *text.text_mut() = value.to_string();
-                    } else {
-                        drop(node_type_mut);
-                        node.set_type(NodeType::Text(TextNode {
-                            text: value.to_string(),
-                            listeners: FxHashSet::default(),
-                        }));
-                    }
-                }
-                LoadTemplate { name, index, id } => {
-                    let template_id = self.templates[name][index];
-                    let clone_id = rdom.get_mut(template_id).unwrap().clone_node();
-                    let clone = rdom.get_mut(clone_id).unwrap();
-                    self.set_element_id(clone, id);
-                    self.stack.push(clone_id);
-                }
-                ReplaceWith { id, m } => {
-                    let new_nodes = self.stack.split_off(self.stack.len() - m);
-                    let old_node_id = self.element_to_node_id(id);
-                    for new in new_nodes {
-                        let mut node = rdom.get_mut(new).unwrap();
-                        node.insert_before(old_node_id);
-                    }
-                    rdom.get_mut(old_node_id).unwrap().remove();
-                }
-                ReplacePlaceholder { path, m } => {
-                    let new_nodes = self.stack.split_off(self.stack.len() - m);
-                    let old_node_id = self.load_child(rdom, path);
-                    for new in new_nodes {
-                        let mut node = rdom.get_mut(new).unwrap();
-                        node.insert_before(old_node_id);
-                    }
-                    rdom.get_mut(old_node_id).unwrap().remove();
-                }
-                InsertAfter { id, m } => {
-                    let new_nodes = self.stack.split_off(self.stack.len() - m);
-                    let old_node_id = self.element_to_node_id(id);
-                    for new in new_nodes.into_iter().rev() {
-                        let mut node = rdom.get_mut(new).unwrap();
-                        node.insert_after(old_node_id);
-                    }
-                }
-                InsertBefore { id, m } => {
-                    let new_nodes = self.stack.split_off(self.stack.len() - m);
-                    let old_node_id = self.element_to_node_id(id);
-                    for new in new_nodes {
-                        rdom.tree_mut().insert_before(old_node_id, new);
-                    }
-                }
-                SetAttribute {
-                    name,
-                    value,
-                    id,
-                    ns,
-                } => {
-                    let node_id = self.element_to_node_id(id);
-                    let mut node = rdom.get_mut(node_id).unwrap();
-                    let mut node_type_mut = node.node_type_mut();
-                    if let NodeTypeMut::Element(element) = &mut node_type_mut {
-                        if let BorrowedAttributeValue::None = &value {
-                            element.remove_attribute(&OwnedAttributeDiscription {
-                                name: name.to_string(),
-                                namespace: ns.map(|s| s.to_string()),
-                            });
-                        } else {
-                            element.set_attribute(
-                                OwnedAttributeDiscription {
-                                    name: name.to_string(),
-                                    namespace: ns.map(|s| s.to_string()),
-                                },
-                                OwnedAttributeValue::from(value),
-                            );
-                        }
-                    }
-                }
-                SetText { value, id } => {
-                    let node_id = self.element_to_node_id(id);
-                    let mut node = rdom.get_mut(node_id).unwrap();
-                    let node_type_mut = node.node_type_mut();
-                    if let NodeTypeMut::Text(mut text) = node_type_mut {
-                        *text.text_mut() = value.to_string();
-                    }
-                }
-                NewEventListener { name, id } => {
-                    let node_id = self.element_to_node_id(id);
-                    let mut node = rdom.get_mut(node_id).unwrap();
-                    node.add_event_listener(name);
-                }
-                RemoveEventListener { id, name } => {
-                    let node_id = self.element_to_node_id(id);
-                    let mut node = rdom.get_mut(node_id).unwrap();
-                    node.remove_event_listener(name);
-                }
-                Remove { id } => {
-                    let node_id = self.element_to_node_id(id);
-                    rdom.get_mut(node_id).unwrap().remove();
-                }
-                PushRoot { id } => {
-                    let node_id = self.element_to_node_id(id);
-                    self.stack.push(node_id);
-                }
-            }
+    fn set_node_text(&mut self, value: &str, id: ElementId) {
+        let node_id = self.state.element_to_node_id(id);
+        let mut node = self.rdom.get_mut(node_id).unwrap();
+        let node_type_mut = node.node_type_mut();
+        if let NodeTypeMut::Text(mut text) = node_type_mut {
+            *text.text_mut() = value.to_string();
         }
     }
+
+    fn create_event_listener(&mut self, name: &'static str, id: ElementId) {
+        let node_id = self.state.element_to_node_id(id);
+        let mut node = self.rdom.get_mut(node_id).unwrap();
+        node.add_event_listener(name);
+    }
+
+    fn remove_event_listener(&mut self, name: &'static str, id: ElementId) {
+        let node_id = self.state.element_to_node_id(id);
+        let mut node = self.rdom.get_mut(node_id).unwrap();
+        node.remove_event_listener(name);
+    }
+
+    fn remove_node(&mut self, id: ElementId) {
+        let node_id = self.state.element_to_node_id(id);
+        self.rdom.get_mut(node_id).unwrap().remove();
+    }
+
+    fn push_root(&mut self, id: ElementId) {
+        let node_id = self.state.element_to_node_id(id);
+        self.state.stack.push(node_id);
+    }
 }
 
 fn create_template_node<V: FromAnyValue + Send + Sync>(

+ 9 - 8
packages/native-core/src/node.rs

@@ -201,15 +201,16 @@ impl<V: FromAnyValue> Display for OwnedAttributeValue<V> {
 }
 
 #[cfg(feature = "dioxus")]
-impl<V: FromAnyValue> From<dioxus_core::BorrowedAttributeValue<'_>> for OwnedAttributeValue<V> {
-    fn from(value: dioxus_core::BorrowedAttributeValue<'_>) -> Self {
+impl<V: FromAnyValue> From<&dioxus_core::AttributeValue> for OwnedAttributeValue<V> {
+    fn from(value: &dioxus_core::AttributeValue) -> Self {
         match value {
-            dioxus_core::BorrowedAttributeValue::Text(text) => Self::Text(text.to_string()),
-            dioxus_core::BorrowedAttributeValue::Float(float) => Self::Float(float),
-            dioxus_core::BorrowedAttributeValue::Int(int) => Self::Int(int),
-            dioxus_core::BorrowedAttributeValue::Bool(bool) => Self::Bool(bool),
-            dioxus_core::BorrowedAttributeValue::Any(any) => Self::Custom(V::from_any_value(any.as_any())),
-            dioxus_core::BorrowedAttributeValue::None => panic!("None attribute values result in removing the attribute, not converting it to a None value.")
+            dioxus_core::AttributeValue::Text(text) => Self::Text(text.clone()),
+            dioxus_core::AttributeValue::Float(float) => Self::Float(*float),
+            dioxus_core::AttributeValue::Int(int) => Self::Int(*int),
+            dioxus_core::AttributeValue::Bool(bool) => Self::Bool(*bool),
+            dioxus_core::AttributeValue::Any(any) => Self::Custom(V::from_any_value(any.as_any())),
+            dioxus_core::AttributeValue::None => panic!("None attribute values result in removing the attribute, not converting it to a None value."),
+            _ => panic!("Unsupported attribute value type"),
         }
     }
 }

+ 0 - 0
packages/rink/.gitignore → packages/plasmo/.gitignore


+ 0 - 0
packages/rink/.vscode/spellright.dict → packages/plasmo/.vscode/spellright.dict


+ 0 - 0
packages/rink/Cargo.toml → packages/plasmo/Cargo.toml


+ 13 - 13
packages/rink/README.md → packages/plasmo/README.md

@@ -1,5 +1,5 @@
 <div align="center">
-  <h1>Rink</h1>
+  <h1>Plasmo</h1>
   <p>
     <strong>A beautiful terminal user interfaces library in Rust.</strong>
   </p>
@@ -7,23 +7,23 @@
 
 <div align="center">
   <!-- Crates version -->
-  <a href="https://crates.io/crates/rink">
-    <img src="https://img.shields.io/crates/v/rink.svg?style=flat-square"
+  <a href="https://crates.io/crates/plasmo">
+    <img src="https://img.shields.io/crates/v/plasmo.svg?style=flat-square"
     alt="Crates.io version" />
   </a>
   <!-- Downloads -->
-  <a href="https://crates.io/crates/rink">
-    <img src="https://img.shields.io/crates/d/rink.svg?style=flat-square"
+  <a href="https://crates.io/crates/plasmo">
+    <img src="https://img.shields.io/crates/d/plasmo.svg?style=flat-square"
       alt="Download" />
   </a>
   <!-- docs -->
-  <a href="https://docs.rs/rink">
+  <a href="https://docs.rs/plasmo">
     <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/rink/actions">
-    <img src="https://github.com/dioxuslabs/rink/actions/workflows/main.yml/badge.svg"
+  <a href="https://github.com/jkelleyrtp/plasmo/actions">
+    <img src="https://github.com/dioxuslabs/plasmo/actions/workflows/main.yml/badge.svg"
       alt="CI status" />
   </a>
   <!-- Discord -->
@@ -34,7 +34,7 @@
 
 <br/>
 
-Leverage CSS, HTML, and Rust to build beautiful, portable, terminal user interfaces. Rink is the cross-framework library that powers [`Dioxus-TUI`](https://github.com/DioxusLabs/dioxus/tree/master/packages/dioxus-tui)
+Leverage CSS, HTML, and Rust to build beautiful, portable, terminal user interfaces. Plasmo is the cross-framework library that powers [`Dioxus-TUI`](https://github.com/DioxusLabs/dioxus/tree/master/packages/dioxus-tui)
 
 ![demo app](examples/example.png)
 
@@ -42,7 +42,7 @@ Leverage CSS, HTML, and Rust to build beautiful, portable, terminal user interfa
 
 You can use Html-like semantics with inline styles, tree hierarchy, components, and more in your [`text-based user interface (TUI)`](https://en.wikipedia.org/wiki/Text-based_user_interface) application.
 
-Rink is essentially a port of [Ink](https://github.com/vadimdemedes/ink) but for [`Rust`](https://www.rust-lang.org/). Rink doesn't depend on Node.js or any other JavaScript runtime, so your binaries are portable and beautiful.
+Plasmo is essentially a port of [Ink](https://github.com/vadimdemedes/ink) but for [`Rust`](https://www.rust-lang.org/). Plasmo doesn't depend on Node.js or any other JavaScript runtime, so your binaries are portable and beautiful.
 
 ## Limitations
 
@@ -53,13 +53,13 @@ Rink is essentially a port of [Ink](https://github.com/vadimdemedes/ink) but for
 
 ## Status
 
-**WARNING: Rink is currently under construction!**
+**WARNING: Plasmo is currently under construction!**
 
 Rendering a Dom works fine, but the ecosystem of widgets is not ready yet. Additionally, some bugs in the flexbox implementation might be quirky at times.
 
 ## Features
 
-Rink features:
+Plasmo features:
 
 - [x] Flexbox-based layout system
 - [ ] CSS selectors
@@ -71,4 +71,4 @@ Rink features:
 * [ ] Html tags<sup>2</sup>
 
 <sup>1</sup> Basic keyboard, mouse, and focus events are implemented.
-<sup>2</sup> Currently, most HTML tags don't translate into any meaning inside of Rink. So an `input` _element_ won't mean anything nor does it have any additional functionality.
+<sup>2</sup> Currently, most HTML tags don't translate into any meaning inside of Plasmo. So an `input` _element_ won't mean anything nor does it have any additional functionality.

+ 0 - 0
packages/rink/examples/counter_button.rs → packages/plasmo/examples/counter_button.rs


+ 0 - 0
packages/rink/examples/example.png → packages/plasmo/examples/example.png


+ 0 - 0
packages/rink/examples/grid.rs → packages/plasmo/examples/grid.rs


+ 0 - 0
packages/rink/examples/widgets.rs → packages/plasmo/examples/widgets.rs


+ 0 - 0
packages/rink/src/config.rs → packages/plasmo/src/config.rs


+ 0 - 0
packages/rink/src/focus.rs → packages/plasmo/src/focus.rs


+ 0 - 0
packages/rink/src/hooks.rs → packages/plasmo/src/hooks.rs


+ 0 - 0
packages/rink/src/layout.rs → packages/plasmo/src/layout.rs


+ 0 - 0
packages/rink/src/lib.rs → packages/plasmo/src/lib.rs


+ 0 - 0
packages/rink/src/prevent_default.rs → packages/plasmo/src/prevent_default.rs


+ 0 - 0
packages/rink/src/query.rs → packages/plasmo/src/query.rs


+ 0 - 0
packages/rink/src/render.rs → packages/plasmo/src/render.rs


+ 1 - 1
packages/rink/src/style.rs → packages/plasmo/src/style.rs

@@ -329,7 +329,7 @@ fn to_rgb(c: Color) -> [u8; 3] {
                 let l = (idx - 232) / 24;
                 [l; 3]
             }
-            // rink will never generate these colors, but they might be on the screen from another program
+            // plasmo will never generate these colors, but they might be on the screen from another program
             _ => [0, 0, 0],
         },
         Color::Reset => [0, 0, 0],

+ 0 - 0
packages/rink/src/style_attributes.rs → packages/plasmo/src/style_attributes.rs


+ 0 - 0
packages/rink/src/widget.rs → packages/plasmo/src/widget.rs


+ 0 - 0
packages/rink/src/widgets/button.rs → packages/plasmo/src/widgets/button.rs


+ 0 - 0
packages/rink/src/widgets/checkbox.rs → packages/plasmo/src/widgets/checkbox.rs


+ 0 - 0
packages/rink/src/widgets/input.rs → packages/plasmo/src/widgets/input.rs


+ 0 - 0
packages/rink/src/widgets/mod.rs → packages/plasmo/src/widgets/mod.rs


+ 0 - 0
packages/rink/src/widgets/number.rs → packages/plasmo/src/widgets/number.rs


+ 0 - 0
packages/rink/src/widgets/password.rs → packages/plasmo/src/widgets/password.rs


+ 0 - 0
packages/rink/src/widgets/slider.rs → packages/plasmo/src/widgets/slider.rs


+ 0 - 0
packages/rink/src/widgets/text_like.rs → packages/plasmo/src/widgets/text_like.rs


+ 0 - 0
packages/rink/src/widgets/textbox.rs → packages/plasmo/src/widgets/textbox.rs


+ 0 - 0
packages/rink/test.html → packages/plasmo/test.html


+ 1 - 1
translations/pt-br/README.md

@@ -167,7 +167,7 @@ Para mais informações sobre quais funções estão atualmente disponíveis e p
 
 Quer adentrar e ajudar a construir o futuro do frontend em Rust? Há um vasto número de lugares em que você pode contribuir e fazer uma grande diferença:
 
-- [TUI renderer](https://github.com/dioxusLabs/rink)
+- [TUI renderer](https://github.com/dioxusLabs/plasmo)
 - [Ferramentas CLI](https://github.com/dioxusLabs/cli)
 - [Documentação e Exemplos de Projeto](https://github.com/dioxusLabs/docsite)
 - LiveView e Servidor Web