diff --git a/Cargo.lock b/Cargo.lock
index f59bd8cfd..a5b0aab05 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -203,12 +203,6 @@ 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"
@@ -1309,12 +1303,6 @@ dependencies = [
"toml 0.8.10",
]
-[[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"
@@ -1890,47 +1878,6 @@ 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 = "crunchy"
version = "0.2.2"
@@ -2201,7 +2148,7 @@ version = "0.5.0-alpha.0"
dependencies = [
"criterion 0.3.6",
"dioxus-config-macro",
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"dioxus-core-macro",
"dioxus-desktop",
"dioxus-fullstack",
@@ -2213,7 +2160,6 @@ dependencies = [
"dioxus-router",
"dioxus-signals",
"dioxus-ssr",
- "dioxus-tui",
"dioxus-web",
"env_logger",
"futures-util",
@@ -2268,7 +2214,7 @@ dependencies = [
"dioxus-autofmt",
"dioxus-check",
"dioxus-cli-config",
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"dioxus-hot-reload",
"dioxus-html",
"dioxus-rsx",
@@ -2357,6 +2303,20 @@ dependencies = [
"tracing-subscriber",
]
+[[package]]
+name = "dioxus-core"
+version = "0.5.0-alpha.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f39bef0484998f724622964f04468ddfde7fd550f5f0f1aef9394306e9caba44"
+dependencies = [
+ "futures-channel",
+ "futures-util",
+ "longest-increasing-subsequence",
+ "rustc-hash",
+ "slab",
+ "tracing",
+]
+
[[package]]
name = "dioxus-core-macro"
version = "0.5.0-alpha.0"
@@ -2387,7 +2347,7 @@ dependencies = [
"core-foundation",
"dioxus",
"dioxus-cli-config",
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"dioxus-hooks",
"dioxus-hot-reload",
"dioxus-html",
@@ -2449,7 +2409,7 @@ dependencies = [
name = "dioxus-fullstack"
version = "0.5.0-alpha.0"
dependencies = [
- "anymap 0.12.1",
+ "anymap",
"async-trait",
"axum",
"base64",
@@ -2488,7 +2448,7 @@ name = "dioxus-hooks"
version = "0.5.0-alpha.0"
dependencies = [
"dioxus",
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"dioxus-debug-cell",
"dioxus-signals",
"futures-channel",
@@ -2506,7 +2466,7 @@ name = "dioxus-hot-reload"
version = "0.5.0-alpha.0"
dependencies = [
"chrono",
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"dioxus-html",
"dioxus-rsx",
"execute",
@@ -2523,7 +2483,7 @@ name = "dioxus-html"
version = "0.5.0-alpha.0"
dependencies = [
"async-trait",
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"dioxus-html-internal-macro",
"dioxus-rsx",
"enumset",
@@ -2556,7 +2516,7 @@ dependencies = [
name = "dioxus-interpreter-js"
version = "0.5.0-alpha.0"
dependencies = [
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"dioxus-html",
"js-sys",
"md5",
@@ -2572,7 +2532,7 @@ name = "dioxus-lib"
version = "0.5.0-alpha.0"
dependencies = [
"dioxus-config-macro",
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"dioxus-core-macro",
"dioxus-hooks",
"dioxus-html",
@@ -2587,7 +2547,7 @@ dependencies = [
"axum",
"dioxus",
"dioxus-cli-config",
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"dioxus-hot-reload",
"dioxus-html",
"dioxus-interpreter-js",
@@ -2614,40 +2574,6 @@ dependencies = [
"dioxus-desktop",
]
-[[package]]
-name = "dioxus-native-core"
-version = "0.5.0-alpha.0"
-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.5.0-alpha.0"
-dependencies = [
- "anymap 0.12.1",
- "dioxus",
- "dioxus-native-core",
- "quote",
- "rustc-hash",
- "smallvec",
- "syn 2.0.51",
-]
-
[[package]]
name = "dioxus-playwright-fullstack-test"
version = "0.1.0"
@@ -2730,7 +2656,7 @@ dependencies = [
name = "dioxus-rsx"
version = "0.5.0-alpha.0"
dependencies = [
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"internment",
"krates",
"proc-macro2",
@@ -2745,7 +2671,7 @@ name = "dioxus-signals"
version = "0.5.0-alpha.0"
dependencies = [
"dioxus",
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"futures-channel",
"futures-util",
"generational-box",
@@ -2769,7 +2695,7 @@ dependencies = [
"async-trait",
"chrono",
"dioxus",
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"dioxus-html",
"dioxus-signals",
"fern",
@@ -2793,24 +2719,6 @@ dependencies = [
"manganis",
]
-[[package]]
-name = "dioxus-tui"
-version = "0.5.0-alpha.0"
-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.5.0-alpha.0"
@@ -2818,7 +2726,7 @@ dependencies = [
"async-trait",
"console_error_panic_hook",
"dioxus",
- "dioxus-core",
+ "dioxus-core 0.5.0-alpha.0",
"dioxus-html",
"dioxus-interpreter-js",
"dioxus-ssr",
@@ -4293,12 +4201,6 @@ 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"
@@ -5152,15 +5054,6 @@ 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.1"
@@ -5701,10 +5594,11 @@ dependencies = [
[[package]]
name = "manganis"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c10916db4ed51967d92545eb5629ce1e1cc05c74da2cd2aab6ab6c57c2e838b6"
+checksum = "a42db80aa639f70d6bf1d2ef93612d2ffbb33f6ea17d473b91bfeb3f67bc24bc"
dependencies = [
+ "dioxus-core 0.5.0-alpha.0 (registry+https://github.com/rust-lang/crates.io-index)",
"manganis-macro",
]
@@ -5737,9 +5631,9 @@ dependencies = [
[[package]]
name = "manganis-common"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82ee0f9002a9f5d7e3b662e55562996c60401bae16da23f3790c52e0823216ea"
+checksum = "176dfb4bb5592b0d130176add9893af527ab565fc1bcf58ece88acd6276688d1"
dependencies = [
"anyhow",
"base64",
@@ -5753,9 +5647,9 @@ dependencies = [
[[package]]
name = "manganis-macro"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da50cc6074480dc6c255a09c9d48dd4a379e6162feb5d308ec33d5ba9da4e579"
+checksum = "ab2c2e11190c2f3d6133cffda5c955b463a7e90b7ba866e71e7dfa65fa97ddfc"
dependencies = [
"manganis-common",
"proc-macro2",
@@ -6917,28 +6811,6 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
-[[package]]
-name = "plasmo"
-version = "0.5.0-alpha.0"
-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"
@@ -7354,24 +7226,6 @@ 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",
- "paste",
- "strum",
- "unicode-segmentation",
- "unicode-width",
-]
-
[[package]]
name = "rav1e"
version = "0.6.6"
@@ -8362,50 +8216,6 @@ 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"
@@ -8511,15 +8321,6 @@ 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.1"
@@ -8920,28 +8721,6 @@ 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.51",
-]
-
[[package]]
name = "subprocess"
version = "0.2.9"
@@ -9042,18 +8821,6 @@ 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"
diff --git a/Cargo.toml b/Cargo.toml
index 71f4875c9..9df562b8e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,10 +23,6 @@ members = [
"packages/autofmt",
"packages/check",
"packages/rsx",
- "packages/dioxus-tui",
- "packages/plasmo",
- "packages/native-core",
- "packages/native-core-macro",
"packages/rsx-rosetta",
"packages/generational-box",
"packages/signals",
@@ -74,10 +70,6 @@ dioxus-liveview = { path = "packages/liveview", version = "0.5.0-alpha.0" }
dioxus-autofmt = { path = "packages/autofmt", version = "0.5.0-alpha.0" }
dioxus-check = { path = "packages/check", version = "0.5.0-alpha.0" }
dioxus-rsx = { path = "packages/rsx", version = "0.5.0-alpha.0" }
-dioxus-tui = { path = "packages/dioxus-tui", version = "0.5.0-alpha.0" }
-plasmo = { path = "packages/plasmo", version = "0.5.0-alpha.0" }
-dioxus-native-core = { path = "packages/native-core", version = "0.5.0-alpha.0" }
-dioxus-native-core-macro = { path = "packages/native-core-macro", version = "0.5.0-alpha.0" }
rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.5.0-alpha.0" }
dioxus-signals = { path = "packages/signals", version = "0.5.0-alpha.0" }
dioxus-cli-config = { path = "packages/cli-config", version = "0.5.0-alpha.0" }
diff --git a/packages/config-macro/Cargo.toml b/packages/config-macro/Cargo.toml
index f7bba9255..57eec5756 100644
--- a/packages/config-macro/Cargo.toml
+++ b/packages/config-macro/Cargo.toml
@@ -24,4 +24,3 @@ mobile = []
web = []
ssr = []
liveview = []
-tui = []
diff --git a/packages/config-macro/src/lib.rs b/packages/config-macro/src/lib.rs
index 0f318208f..13a38dcf8 100644
--- a/packages/config-macro/src/lib.rs
+++ b/packages/config-macro/src/lib.rs
@@ -23,7 +23,7 @@ pub fn server_only(input: TokenStream) -> TokenStream {
#[proc_macro]
pub fn client(input: TokenStream) -> TokenStream {
- if cfg!(any(feature = "desktop", feature = "web", feature = "tui")) {
+ if cfg!(any(feature = "desktop", feature = "web")) {
let input = TokenStream2::from(input);
quote! {
#input
@@ -110,18 +110,3 @@ pub fn liveview(input: TokenStream) -> TokenStream {
}
.into()
}
-
-#[proc_macro]
-pub fn tui(input: TokenStream) -> TokenStream {
- if cfg!(feature = "tui") {
- let input = TokenStream2::from(input);
- quote! {
- #input
- }
- } else {
- quote! {
- || {}
- }
- }
- .into()
-}
diff --git a/packages/dioxus-tui/.gitignore b/packages/dioxus-tui/.gitignore
deleted file mode 100644
index 96ef6c0b9..000000000
--- a/packages/dioxus-tui/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/target
-Cargo.lock
diff --git a/packages/dioxus-tui/.vscode/spellright.dict b/packages/dioxus-tui/.vscode/spellright.dict
deleted file mode 100644
index c30e473fc..000000000
--- a/packages/dioxus-tui/.vscode/spellright.dict
+++ /dev/null
@@ -1,2 +0,0 @@
-esque
-Tui
diff --git a/packages/dioxus-tui/Cargo.toml b/packages/dioxus-tui/Cargo.toml
deleted file mode 100644
index 47ff3f536..000000000
--- a/packages/dioxus-tui/Cargo.toml
+++ /dev/null
@@ -1,36 +0,0 @@
-[package]
-name = "dioxus-tui"
-version = { workspace = true }
-authors = ["Jonathan Kelley, Evan Almloff"]
-edition = "2021"
-description = "TUI-based renderer for Dioxus"
-repository = "https://github.com/DioxusLabs/dioxus/"
-homepage = "https://dioxuslabs.com/learn/0.4/getting_started/tui"
-keywords = ["dom", "ui", "gui", "react", "terminal"]
-license = "MIT OR Apache-2.0"
-
-[dependencies]
-dioxus-core = { workspace = true, features = ["serialize"] }
-dioxus-html = { workspace = true }
-dioxus-native-core = { workspace = true, features = ["dioxus"] }
-dioxus-native-core-macro = { workspace = true }
-dioxus-hot-reload = { workspace = true, optional = true }
-plasmo = { workspace = true }
-
-crossterm = "0.26.0"
-tokio = { workspace = true, features = ["full"] }
-futures = "0.3.19"
-taffy = "0.3.12"
-
-[dev-dependencies]
-dioxus = { workspace = true }
-tokio = { version = "1" }
-criterion = "0.3.5"
-
-[[bench]]
-name = "update"
-harness = false
-
-[features]
-default = ["hot-reload"]
-hot-reload = ["dioxus-hot-reload"]
diff --git a/packages/dioxus-tui/README.md b/packages/dioxus-tui/README.md
deleted file mode 100644
index 19bac2219..000000000
--- a/packages/dioxus-tui/README.md
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
Dioxus TUI
-
- Beautiful terminal user interfaces in Rust with Dioxus .
-
-
-
-
-
-
-
-Leverage React-like patterns, CSS, HTML, and Rust to build beautiful, portable, terminal user interfaces with Dioxus.
-
-```rust
-fn app() -> Element {
- rsx!{
- div {
- width: "100%",
- height: "10px",
- background_color: "red",
- justify_content: "center",
- align_items: "center",
- "Hello world!"
- }
- })
-}
-```
-
-
-
-## Background
-
-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.
-
-Dioxus TUI is essentially a port of [Ink](https://github.com/vadimdemedes/ink) but for [`Rust`](https://www.rust-lang.org/) and [`Dioxus`](https://dioxuslabs.com/). Dioxus TUI doesn't depend on Node.js or any other JavaScript runtime, so your binaries are portable and beautiful.
-
-## Limitations
-
-- **Subset of Html**
- Terminals can only render a subset of HTML. We support as much as we can.
-- **Particular frontend design**
- Terminals and browsers are and look different. Therefore, the same design might not be the best to cover both renderers.
-
-## Status
-
-**WARNING: Dioxus TUI is currently under construction!**
-
-Rendering a VirtualDom works fine, but the ecosystem of hooks is not yet ready. Additionally, some bugs in the flexbox implementation might be quirky at times.
-
-## Features
-
-Dioxus TUI features:
-
-- [x] Flexbox-based layout system
-- [ ] CSS selectors
-- [x] inline CSS support
-- [x] Built-in focusing system
-
-* [x] Widgets1
-* [ ] Support for events, hooks, and callbacks2
-* [ ] Html tags3
-
-1 Currently only a subset of the input element is implemented as a component (not an element). The `Input` component supports sliders, text, numbers, passwords, buttons, and checkboxes.
-2 Basic keyboard, mouse, and focus events are implemented.
-3 Currently, most HTML tags don't translate into any meaning inside of Dioxus TUI. So an `input` _element_ won't mean anything nor does it have any additional functionality.
diff --git a/packages/dioxus-tui/benches/update.rs b/packages/dioxus-tui/benches/update.rs
deleted file mode 100644
index 0f0479400..000000000
--- a/packages/dioxus-tui/benches/update.rs
+++ /dev/null
@@ -1,155 +0,0 @@
-use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
-use dioxus::prelude::*;
-use dioxus_tui::{Config, TuiContext};
-
-criterion_group!(mbenches, tui_update);
-criterion_main!(mbenches);
-
-/// This benchmarks the cache performance of the TUI for small edits by changing one box at a time.
-fn tui_update(c: &mut Criterion) {
- {
- let mut group = c.benchmark_group("Update boxes");
-
- for size in 1..=20usize {
- let parameter_string = format!("{}", (size).pow(2));
- group.bench_with_input(
- BenchmarkId::new("size", parameter_string),
- &size,
- |b, size| {
- b.iter(|| {
- dioxus_tui::launch_cfg_with_props(
- app,
- GridProps {
- size: *size,
- update_count: 1,
- },
- Config::default().with_headless(),
- )
- })
- },
- );
- }
- }
-
- {
- let mut group = c.benchmark_group("Update many boxes");
-
- for update_count in 1..=20usize {
- let update_count = update_count * 20;
- let parameter_string = update_count.to_string();
- group.bench_with_input(
- BenchmarkId::new("update count", parameter_string),
- &update_count,
- |b, update_count| {
- b.iter(|| {
- dioxus_tui::launch_cfg_with_props(
- app,
- GridProps {
- size: 20,
- update_count: *update_count,
- },
- Config::default().with_headless(),
- )
- })
- },
- );
- }
- }
-}
-
-#[derive(Props, PartialEq, Clone)]
-struct BoxProps {
- x: usize,
- y: usize,
- hue: f32,
- alpha: f32,
-}
-#[allow(non_snake_case)]
-fn Box(props: BoxProps) -> Element {
- let count = use_signal(|| 0);
-
- let x = props.x * 2;
- let y = props.y * 2;
- let hue = props.hue;
- let display_hue = props.hue as u32 / 10;
- let count = count();
- let alpha = props.alpha + (count % 100) as f32;
-
- rsx! {
- div {
- left: "{x}%",
- top: "{y}%",
- width: "100%",
- height: "100%",
- background_color: "hsl({hue}, 100%, 50%, {alpha}%)",
- align_items: "center",
- p{"{display_hue:03}"}
- }
- }
-}
-
-#[derive(Props, PartialEq, Clone)]
-struct GridProps {
- size: usize,
- update_count: usize,
-}
-#[allow(non_snake_case)]
-fn Grid(props: GridProps) -> Element {
- let size = props.size;
- let mut count = use_signal(|| 0);
- let mut counts = use_signal(|| vec![0; size * size]);
-
- let ctx: TuiContext = consume_context();
- if count() + props.update_count >= (size * size) {
- ctx.quit();
- } else {
- for _ in 0..props.update_count {
- counts.with_mut(|c| {
- let i = count();
- c[i] += 1;
- c[i] %= 360;
- });
- count.with_mut(|i| {
- *i += 1;
- *i %= size * size;
- });
- }
- }
-
- rsx! {
- div{
- width: "100%",
- height: "100%",
- flex_direction: "column",
- for x in 0..size {
- div {
- width: "100%",
- height: "100%",
- flex_direction: "row",
- for y in 0..size {
- Box {
- key: "{x}-{y}",
- x: x,
- y: y,
- alpha: 100.0,
- hue: y as f32*100.0/size as f32 + counts.read()[x*size + y] as f32,
- }
- }
- }
- }
- }
- }
-}
-
-fn app(props: GridProps) -> Element {
- rsx! {
- div{
- width: "100%",
- height: "100%",
- Grid{
- size: props.size,
- update_count: props.update_count,
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/all_terminal_events.rs b/packages/dioxus-tui/examples/all_terminal_events.rs
deleted file mode 100644
index 45aec8837..000000000
--- a/packages/dioxus-tui/examples/all_terminal_events.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-use dioxus::prelude::*;
-use std::{fmt::Debug, rc::Rc};
-
-fn main() {
- dioxus_tui::launch(app);
-}
-
-const MAX_EVENTS: usize = 8;
-
-fn app() -> Element {
- let mut events = use_signal(|| Vec::new() as Vec>);
-
- let mut log_event = move |event: Rc| events.write().push(event);
-
- rsx! {
- div { width: "100%", height: "100%", flex_direction: "column",
- div {
- width: "80%",
- height: "50%",
- border_width: "1px",
- justify_content: "center",
- align_items: "center",
- background_color: "hsl(248, 53%, 58%)",
-
- // Mosue
- onmousemove: move |event| log_event(event.data()),
- onclick: move |event| log_event(event.data()),
- ondoubleclick: move |event| log_event(event.data()),
- onmousedown: move |event| log_event(event.data()),
- onmouseup: move |event| log_event(event.data()),
-
- // Scroll
- onwheel: move |event| log_event(event.data()),
-
- // Keyboard
- onkeydown: move |event| log_event(event.data()),
- onkeyup: move |event| log_event(event.data()),
- onkeypress: move |event| log_event(event.data()),
-
- // Focus
- onfocusin: move |event| log_event(event.data()),
- onfocusout: move |event| log_event(event.data()),
-
- "Hover, click, type or scroll to see the info down below"
- }
- div { width: "80%", height: "50%", flex_direction: "column",
- // A trailing iterator of the last MAX_EVENTS events
- // The index actually is a fine key here, since events are append-only and therefore stable
- for (index, event) in events.read().iter().enumerate().rev().take(MAX_EVENTS).rev() {
- p { key: "{index}",
- {
- // TUI panics if text overflows (https://github.com/DioxusLabs/dioxus/issues/371)
- // temporary hack: just trim the strings (and make sure viewport is big enough)
- // todo: remove
- let mut trimmed = format!("{event:?}");
- trimmed.truncate(200);
- trimmed
- }
- }
- }
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/border.rs b/packages/dioxus-tui/examples/border.rs
deleted file mode 100644
index b38edd061..000000000
--- a/packages/dioxus-tui/examples/border.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
- dioxus_tui::launch(app);
-}
-
-fn app() -> Element {
- let mut radius = use_signal(|| 0);
-
- rsx! {
- div {
- width: "100%",
- height: "100%",
- justify_content: "center",
- align_items: "center",
- background_color: "hsl(248, 53%, 58%)",
- onwheel: move |w| radius.with_mut(|r| *r = (*r + w.delta().strip_units().y as i8).abs()),
-
- border_style: "solid none solid double",
- border_width: "thick",
- border_radius: "{radius}px",
- border_color: "#0000FF #FF00FF #FF0000 #00FF00",
-
- "{radius}"
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/buttons.rs b/packages/dioxus-tui/examples/buttons.rs
deleted file mode 100644
index 5173103af..000000000
--- a/packages/dioxus-tui/examples/buttons.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-use dioxus::prelude::*;
-use dioxus_html::input_data::keyboard_types::Code;
-
-fn main() {
- dioxus_tui::launch(app);
-}
-
-#[component]
-fn Button(color_offset: u32, layer: u16) -> Element {
- let mut toggle = use_signal(|| false);
- let mut hovered = use_signal(|| false);
-
- let hue = color_offset % 255;
- let saturation = if toggle() { 50 } else { 25 } + if hovered() { 50 } else { 25 };
- let brightness = saturation / 2;
- let color = format!("hsl({hue}, {saturation}, {brightness})");
-
- rsx! {
- div{
- width: "100%",
- height: "100%",
- background_color: "{color}",
- tabindex: "{layer}",
- onkeydown: move |e| {
- if let Code::Space = e.code() {
- toggle.toggle();
- }
- },
- onclick: move |_| toggle.toggle(),
- onmouseenter: move |_| hovered.set(true),
- onmouseleave: move |_| hovered.set(false),
- justify_content: "center",
- align_items: "center",
- display: "flex",
- flex_direction: "column",
- p { "tabindex: {layer}" }
- }
- }
-}
-
-fn app() -> Element {
- rsx! {
- div {
- display: "flex",
- flex_direction: "column",
- width: "100%",
- height: "100%",
- for y in 1..8 {
- div {
- display: "flex",
- flex_direction: "row",
- width: "100%",
- height: "100%",
- for x in 1..8 {
- if (x + y) % 2 == 0 {
- div {
- width: "100%",
- height: "100%",
- background_color: "rgb(100, 100, 100)",
- }
- } else {
- Button {
- color_offset: x * y,
- layer: ((x + y) % 3) as u16,
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/color_test.rs b/packages/dioxus-tui/examples/color_test.rs
deleted file mode 100644
index 72fa5b44a..000000000
--- a/packages/dioxus-tui/examples/color_test.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
- dioxus_tui::launch_cfg(
- app,
- dioxus_tui::Config::default().with_rendering_mode(dioxus_tui::RenderingMode::Ansi),
- );
-}
-
-fn app() -> Element {
- let steps = 50;
- rsx! {
- div{
- width: "100%",
- height: "100%",
- flex_direction: "column",
- for x in 0..=steps {
- div { width: "100%", height: "100%", flex_direction: "row",
- for y in 0..=steps {
- {
- let hue = x as f32*360.0/steps as f32;
- let alpha = y as f32*100.0/steps as f32;
- rsx! {
- div {
- left: "{x}px",
- top: "{y}px",
- width: "10%",
- height: "100%",
- background_color: "hsl({hue}, 100%, 50%, {alpha}%)",
- }
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/example.png b/packages/dioxus-tui/examples/example.png
deleted file mode 100644
index ba45e6e99..000000000
Binary files a/packages/dioxus-tui/examples/example.png and /dev/null differ
diff --git a/packages/dioxus-tui/examples/flex.rs b/packages/dioxus-tui/examples/flex.rs
deleted file mode 100644
index bbe6df055..000000000
--- a/packages/dioxus-tui/examples/flex.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
- dioxus_tui::launch(app);
-}
-
-fn app() -> Element {
- rsx! {
- div {
- width: "100%",
- height: "100%",
- flex_direction: "column",
- // justify_content: "center",
- // align_items: "center",
- // flex_direction: "row",
- // background_color: "red",
-
- p {
- background_color: "black",
- flex_direction: "column",
- justify_content: "center",
- align_items: "center",
- // height: "10%",
- "hi"
- "hi"
- "hi"
- }
-
- li {
- background_color: "red",
- flex_direction: "column",
- justify_content: "center",
- align_items: "center",
- // height: "10%",
- "bib"
- "bib"
- "bib"
- "bib"
- "bib"
- "bib"
- "bib"
- "bib"
- }
- li {
- background_color: "blue",
- flex_direction: "column",
- justify_content: "center",
- align_items: "center",
- // height: "10%",
- "zib"
- "zib"
- "zib"
- "zib"
- "zib"
- "zib"
- "zib"
- "zib"
- "zib"
- "zib"
- "zib"
- "zib"
- "zib"
- }
- p {
- background_color: "yellow",
- "asd"
- }
- p {
- background_color: "green",
- "asd"
- }
- p {
- background_color: "white",
- "asd"
- }
- p {
- background_color: "cyan",
- "asd"
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/hover.rs b/packages/dioxus-tui/examples/hover.rs
deleted file mode 100644
index 30740e0d7..000000000
--- a/packages/dioxus-tui/examples/hover.rs
+++ /dev/null
@@ -1,125 +0,0 @@
-use dioxus::{events::MouseData, prelude::*};
-use dioxus_core::Event;
-use std::convert::TryInto;
-use std::fmt::Write;
-use std::rc::Rc;
-
-fn main() {
- dioxus_tui::launch(app);
-}
-
-fn app() -> Element {
- fn to_str(c: &[i32; 3]) -> String {
- let mut result = String::new();
- result += "#";
- for c in c.iter() {
- write!(result, "{c:02X?}").unwrap();
- }
- result
- }
-
- fn get_brightness(m: Rc) -> i32 {
- let b: i32 = m.held_buttons().len().try_into().unwrap();
- 127 * b
- }
-
- let mut q1_color = use_signal(|| [200; 3]);
- let mut q2_color = use_signal(|| [200; 3]);
- let mut q3_color = use_signal(|| [200; 3]);
- let mut q4_color = use_signal(|| [200; 3]);
-
- let mut page_coordinates = use_signal(|| "".to_string());
- let mut element_coordinates = use_signal(|| "".to_string());
- let mut buttons = use_signal(|| "".to_string());
- let mut modifiers = use_signal(|| "".to_string());
-
- let update_data = move |event: Event| {
- page_coordinates.set(format!("{:?}", event.page_coordinates()));
- element_coordinates.set(format!("{:?}", event.element_coordinates()));
-
- // Note: client coordinates are also available, but they would be the same as the page coordinates in this example, because there is no scrolling.
- // There are also screen coordinates, but they are currently the same as client coordinates due to technical limitations
- buttons.set(format!("{:?}", event.held_buttons()));
- modifiers.set(format!("{:?}", event.modifiers()));
- };
-
- rsx! {
- div {
- width: "100%",
- height: "100%",
- flex_direction: "column",
- div {
- width: "100%",
- height: "50%",
- flex_direction: "row",
- div {
- border_width: "1px",
- width: "50%",
- height: "100%",
- justify_content: "center",
- align_items: "center",
- background_color: to_str(&q1_color()),
- onmouseenter: move |m| q1_color.set([get_brightness(m.data()), 0, 0]),
- onmousedown: move |m| q1_color.set([get_brightness(m.data()), 0, 0]),
- onmouseup: move |m| q1_color.set([get_brightness(m.data()), 0, 0]),
- onwheel: move |w| q1_color.set([q1_color()[0] + (10.0 * w.delta().strip_units().y) as i32, 0, 0]),
- onmouseleave: move |_| q1_color.set([200; 3]),
- onmousemove: update_data,
- "click me"
- }
- div {
- width: "50%",
- height: "100%",
- justify_content: "center",
- align_items: "center",
- background_color: to_str(&q2_color()),
- onmouseenter: move |m| q2_color.set([get_brightness(m.data()); 3]),
- onmousedown: move |m| q2_color.set([get_brightness(m.data()); 3]),
- onmouseup: move |m| q2_color.set([get_brightness(m.data()); 3]),
- onwheel: move |w| q2_color.set([q2_color()[0] + (10.0 * w.delta().strip_units().y) as i32; 3]),
- onmouseleave: move |_| q2_color.set([200; 3]),
- onmousemove: update_data,
- "click me"
- }
- }
-
- div {
- width: "100%",
- height: "50%",
- flex_direction: "row",
- div {
- width: "50%",
- height: "100%",
- justify_content: "center",
- align_items: "center",
- background_color: to_str(&q3_color()),
- onmouseenter: move |m| q3_color.set([0, get_brightness(m.data()), 0]),
- onmousedown: move |m| q3_color.set([0, get_brightness(m.data()), 0]),
- onmouseup: move |m| q3_color.set([0, get_brightness(m.data()), 0]),
- onwheel: move |w| q3_color.set([0, q3_color()[1] + (10.0 * w.delta().strip_units().y) as i32, 0]),
- onmouseleave: move |_| q3_color.set([200; 3]),
- onmousemove: update_data,
- "click me"
- }
- div {
- width: "50%",
- height: "100%",
- justify_content: "center",
- align_items: "center",
- background_color: to_str(&q4_color()),
- onmouseenter: move |m| q4_color.set([0, 0, get_brightness(m.data())]),
- onmousedown: move |m| q4_color.set([0, 0, get_brightness(m.data())]),
- onmouseup: move |m| q4_color.set([0, 0, get_brightness(m.data())]),
- onwheel: move |w| q4_color.set([0, 0, q4_color()[2] + (10.0 * w.delta().strip_units().y) as i32]),
- onmouseleave: move |_| q4_color.set([200; 3]),
- onmousemove: update_data,
- "click me"
- }
- }
- div { "Page coordinates: {page_coordinates}" }
- div { "Element coordinates: {element_coordinates}" }
- div { "Buttons: {buttons}" }
- div { "Modifiers: {modifiers}" }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/list.rs b/packages/dioxus-tui/examples/list.rs
deleted file mode 100644
index 156e83550..000000000
--- a/packages/dioxus-tui/examples/list.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
- dioxus_tui::launch(app);
-}
-
-fn app() -> Element {
- rsx! {
- div {
- width: "100%",
- height: "100%",
- flex_direction: "column",
- border_width: "1px",
-
- h1 { height: "2px", color: "green",
- "that's awesome!"
- }
-
- ul {
- flex_direction: "column",
- padding_left: "3px",
- for i in 0..10 {
- "> hello {i}"
- }
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/many_small_edit_stress.rs b/packages/dioxus-tui/examples/many_small_edit_stress.rs
deleted file mode 100644
index 1093e353f..000000000
--- a/packages/dioxus-tui/examples/many_small_edit_stress.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-use dioxus::prelude::*;
-use dioxus_tui::{Config, TuiContext};
-
-/// This benchmarks the cache performance of the TUI for small edits by changing one box at a time.
-fn main() {
- for size in 1..=20usize {
- for _ in 0..10 {
- let dom = VirtualDom::new(app).with_root_context(size);
- dioxus_tui::launch_vdom_cfg(dom, Config::default().with_headless())
- }
- }
-}
-
-fn app() -> Element {
- let size = use_context::();
- rsx! {
- div { width: "100%", height: "100%", Grid { size } }
- }
-}
-
-#[component]
-fn Box(x: usize, y: usize, hue: f32, alpha: f32) -> Element {
- let count = use_signal(|| 0);
-
- let x = x * 2;
- let y = y * 2;
- let hue = hue;
- let display_hue = hue as u32 / 10;
-
- let alpha = alpha + (count() % 100) as f32;
-
- rsx! {
- div {
- left: "{x}%",
- top: "{y}%",
- width: "100%",
- height: "100%",
- background_color: "hsl({hue}, 100%, 50%, {alpha}%)",
- align_items: "center",
- p{"{display_hue:03}"}
- }
- }
-}
-
-#[component]
-fn Grid(size: usize) -> Element {
- let size = size;
- let mut count = use_signal(|| 0);
- let mut counts = use_signal(|| vec![0; size * size]);
-
- let ctx: TuiContext = consume_context();
-
- if count() + 1 >= (size * size) {
- ctx.quit();
- } else {
- counts.with_mut(|c| {
- let i = count();
- c[i] += 1;
- c[i] %= 360;
- });
- count.with_mut(|i| {
- *i += 1;
- *i %= size * size;
- });
- }
-
- rsx! {
- div{
- width: "100%",
- height: "100%",
- flex_direction: "column",
- for x in 0..size {
- div{
- width: "100%",
- height: "100%",
- flex_direction: "row",
- for y in 0..size {
- {
- let alpha = y as f32*100.0/size as f32 + counts.read()[x*size + y] as f32;
- let key = format!("{}-{}", x, y);
- rsx! {
- Box {
- x: x,
- y: y,
- alpha: 100.0,
- hue: alpha,
- key: "{key}",
- }
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/margin.rs b/packages/dioxus-tui/examples/margin.rs
deleted file mode 100644
index 20ce9a8e1..000000000
--- a/packages/dioxus-tui/examples/margin.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
- dioxus_tui::launch(app);
-}
-
-fn app() -> Element {
- rsx! {
- div {
- width: "100%",
- height: "100%",
- flex_direction: "column",
- background_color: "black",
- margin_right: "10px",
-
- div {
- width: "70%",
- height: "70%",
- background_color: "green",
- margin_left: "4px",
-
- div {
- width: "100%",
- height: "100%",
-
- margin_top: "2px",
- margin_bottom: "2px",
- margin_left: "2px",
- margin_right: "2px",
- flex_shrink: "0",
-
- background_color: "red",
- justify_content: "center",
- align_items: "center",
- flex_direction: "column",
-
- padding_top: "2px",
- padding_bottom: "2px",
- padding_left: "4px",
- padding_right: "4px",
-
- "[A]"
- "[A]"
- "[A]"
- "[A]"
- }
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/quadrants.rs b/packages/dioxus-tui/examples/quadrants.rs
deleted file mode 100644
index fd410b554..000000000
--- a/packages/dioxus-tui/examples/quadrants.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-#![allow(non_snake_case)]
-
-use dioxus::prelude::*;
-
-fn main() {
- dioxus_tui::launch_cfg(app, Default::default());
-}
-
-#[component]
-fn Quadrant(color: String, text: String) -> Element {
- rsx! {
- div {
- border_width: "1px",
- width: "50%",
- height: "100%",
- justify_content: "center",
- align_items: "center",
- background_color: "{color}",
- "{text}"
- }
- }
-}
-
-fn app() -> Element {
- rsx! {
- div {
- width: "100%",
- height: "100%",
- flex_direction: "column",
- div {
- width: "100%",
- height: "50%",
- flex_direction: "row",
- Quadrant {
- color: "red".to_string(),
- text: "[A]".to_string()
- },
- Quadrant {
- color: "black".to_string(),
- text: "[B]".to_string()
- }
- }
- div {
- width: "100%",
- height: "50%",
- flex_direction: "row",
- Quadrant {
- color: "green".to_string(),
- text: "[C]".to_string()
- },
- Quadrant {
- color: "blue".to_string(),
- text: "[D]".to_string()
- }
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/readme_hello_world.rs b/packages/dioxus-tui/examples/readme_hello_world.rs
deleted file mode 100644
index c17869596..000000000
--- a/packages/dioxus-tui/examples/readme_hello_world.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
- dioxus_tui::launch(app);
-}
-
-fn app() -> Element {
- rsx! {
- div {
- width: "100%",
- height: "10px",
- background_color: "red",
- justify_content: "center",
- align_items: "center",
-
- "Hello world!"
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/task.rs b/packages/dioxus-tui/examples/task.rs
deleted file mode 100644
index 01e7831a0..000000000
--- a/packages/dioxus-tui/examples/task.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
- dioxus_tui::launch(app);
-}
-
-fn app() -> Element {
- let mut count = use_signal(|| 0);
-
- use_future(move || async move {
- loop {
- count += 1;
- tokio::time::sleep(std::time::Duration::from_millis(1000)).await;
- schedule_update();
- }
- });
-
- rsx! {
- div { width: "100%",
- div { width: "50%", height: "5px", background_color: "blue", justify_content: "center", align_items: "center",
- "Hello {count}!"
- }
- div { width: "50%", height: "10px", background_color: "red", justify_content: "center", align_items: "center",
- "Hello {count}!"
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/text.rs b/packages/dioxus-tui/examples/text.rs
deleted file mode 100644
index 7e3a59d4d..000000000
--- a/packages/dioxus-tui/examples/text.rs
+++ /dev/null
@@ -1,113 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
- dioxus_tui::launch(app);
-}
-
-fn app() -> Element {
- let mut alpha = use_signal(|| 100);
-
- rsx! {
- div {
- width: "100%",
- height: "100%",
- flex_direction: "column",
- onwheel: move |evt| alpha.set((alpha() + evt.delta().strip_units().y as i64).clamp(0, 100)),
-
- p {
- background_color: "black",
- flex_direction: "column",
- justify_content: "center",
- align_items: "center",
- color: "green",
- "hi"
- "hi"
- "hi"
- }
-
- li {
- background_color: "red",
- flex_direction: "column",
- justify_content: "center",
- align_items: "center",
- "bib"
- "bib"
- "bib"
- "bib"
- "bib"
- "bib"
- "bib"
- "bib"
- }
- li {
- background_color: "blue",
- flex_direction: "column",
- justify_content: "center",
- align_items: "center",
- "zib"
- "zib"
- "zib"
- "zib"
- "zib"
- "zib"
- }
- p {
- background_color: "yellow",
- "asd"
- }
- p {
- background_color: "green",
- "asd"
- }
- p {
- background_color: "white",
- "asd"
- }
- p {
- background_color: "cyan",
- "asd"
- }
- div {
- font_weight: "bold",
- color: "#666666",
- p {
- "bold"
- }
- p {
- font_weight: "normal",
- " normal"
- }
- }
- p {
- font_style: "italic",
- color: "red",
- "italic"
- }
- p {
- text_decoration: "underline",
- color: "rgba(255, 255, 255)",
- "underline"
- }
- p {
- text_decoration: "line-through",
- color: "hsla(10, 100%, 70%)",
- "line-through"
- }
- div{
- position: "absolute",
- top: "1px",
- background_color: "rgba(255, 0, 0, 50%)",
- width: "100%",
- p {
- color: "rgba(255, 255, 255, {alpha}%)",
- background_color: "rgba(100, 100, 100, {alpha}%)",
- "rgba(255, 255, 255, {alpha}%)"
- }
- p {
- color: "rgba(255, 255, 255, 100%)",
- "rgba(255, 255, 255, 100%)"
- }
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/examples/widgets.rs b/packages/dioxus-tui/examples/widgets.rs
deleted file mode 100644
index 355f773b2..000000000
--- a/packages/dioxus-tui/examples/widgets.rs
+++ /dev/null
@@ -1,90 +0,0 @@
-use dioxus::prelude::*;
-use dioxus_tui::Config;
-
-fn main() {
- dioxus_tui::launch_cfg(app, Config::new());
-}
-
-fn app() -> Element {
- let mut bg_green = use_signal(|| false);
- let color = if bg_green() { "green" } else { "red" };
-
- rsx! {
- div {
- width: "100%",
- background_color: "{color}",
- flex_direction: "column",
- align_items: "center",
- justify_content: "center",
- input {
- oninput: move |data| if data.value() == "good" {
- bg_green.set(true);
- } else{
- bg_green.set(false);
- },
- r#type: "checkbox",
- value: "good",
- width: "50%",
- height: "10%",
- checked: "true",
- }
- input {
- oninput: move |data| if &data.value() == "hello world"{
- bg_green.set(true);
- } else {
- bg_green.set(false);
- },
- width: "50%",
- height: "10%",
- maxlength: "11",
- }
- input {
- oninput: move |data| {
- if (data.value().parse::().unwrap() - 40.0).abs() < 5.0 {
- bg_green.set(true);
- } else{
- bg_green.set(false);
- }
- },
- r#type: "range",
- width: "50%",
- height: "10%",
- min: "20",
- max: "80",
- }
- input {
- oninput: move |data| {
- if data.value() == "10"{
- bg_green.set(true);
- } else {
- bg_green.set(false);
- }
- },
- r#type: "number",
- width: "50%",
- height: "10%",
- maxlength: "4",
- }
- input {
- oninput: move |data| {
- if data.value() == "hello world"{
- bg_green.set(true);
- } else{
- bg_green.set(false);
- }
- },
- r#type: "password",
- width: "50%",
- height: "10%",
- maxlength: "11",
- }
- input {
- oninput: move |_| { bg_green.set(true) },
- r#type: "button",
- value: "green",
- width: "50%",
- height: "10%",
- }
- }
- }
-}
diff --git a/packages/dioxus-tui/src/element.rs b/packages/dioxus-tui/src/element.rs
deleted file mode 100644
index bb6e36722..000000000
--- a/packages/dioxus-tui/src/element.rs
+++ /dev/null
@@ -1,158 +0,0 @@
-use std::{
- any::Any,
- fmt::{Display, Formatter},
-};
-
-use dioxus_core::{ElementId, WriteMutations};
-use dioxus_html::{
- geometry::euclid::{Point2D, Rect, Size2D},
- MountedData, MountedError, RenderedElementBacking,
-};
-
-use dioxus_native_core::{dioxus::DioxusNativeCoreMutationWriter, NodeId};
-use plasmo::query::{ElementRef, Query};
-
-pub(crate) struct DioxusTUIMutationWriter<'a> {
- pub(crate) query: Query,
- pub(crate) events: &'a mut Vec<(ElementId, &'static str, Box, 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)
- }
- }
-
- 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)
- }
-}
-
-#[derive(Clone)]
-pub(crate) struct TuiElement {
- query: Query,
- id: NodeId,
-}
-
-impl TuiElement {
- pub(crate) fn element(&self) -> ElementRef {
- self.query.get(self.id)
- }
-}
-
-impl RenderedElementBacking for TuiElement {
- fn get_client_rect(
- &self,
- ) -> std::pin::Pin<
- Box<
- dyn futures::Future<
- Output = dioxus_html::MountedResult>,
- >,
- >,
- > {
- let layout = self.element().layout();
- Box::pin(async move {
- match layout {
- Some(layout) => {
- let x = layout.location.x as f64;
- let y = layout.location.y as f64;
- let width = layout.size.width as f64;
- let height = layout.size.height as f64;
- Ok(Rect::new(Point2D::new(x, y), Size2D::new(width, height)))
- }
- None => Err(MountedError::OperationFailed(Box::new(TuiElementNotFound))),
- }
- })
- }
-
- fn as_any(&self) -> &dyn std::any::Any {
- self
- }
-}
-
-#[derive(Debug)]
-struct TuiElementNotFound;
-
-impl Display for TuiElementNotFound {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- write!(f, "TUI element not found")
- }
-}
-
-impl std::error::Error for TuiElementNotFound {}
diff --git a/packages/dioxus-tui/src/events.rs b/packages/dioxus-tui/src/events.rs
deleted file mode 100644
index 3e7b6fd2a..000000000
--- a/packages/dioxus-tui/src/events.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-use core::panic;
-
-use dioxus_html::*;
-
-use crate::element::TuiElement;
-
-fn downcast(event: &PlatformEventData) -> plasmo::EventData {
- event
- .downcast::()
- .expect("event should be of type EventData")
- .clone()
-}
-
-pub(crate) struct SerializedHtmlEventConverter;
-
-impl HtmlEventConverter for SerializedHtmlEventConverter {
- fn convert_animation_data(&self, _: &PlatformEventData) -> AnimationData {
- panic!("animation events not supported")
- }
-
- fn convert_clipboard_data(&self, _: &PlatformEventData) -> ClipboardData {
- panic!("clipboard events not supported")
- }
-
- fn convert_composition_data(&self, _: &PlatformEventData) -> CompositionData {
- panic!("composition events not supported")
- }
-
- fn convert_drag_data(&self, _: &PlatformEventData) -> DragData {
- panic!("drag events not supported")
- }
-
- fn convert_focus_data(&self, event: &PlatformEventData) -> FocusData {
- if let plasmo::EventData::Focus(event) = downcast(event) {
- FocusData::new(event)
- } else {
- panic!("event should be of type Focus")
- }
- }
-
- fn convert_form_data(&self, event: &PlatformEventData) -> FormData {
- if let plasmo::EventData::Form(event) = downcast(event) {
- FormData::new(event)
- } else {
- panic!("event should be of type Form")
- }
- }
-
- fn convert_image_data(&self, _: &PlatformEventData) -> ImageData {
- panic!("image events not supported")
- }
-
- fn convert_keyboard_data(&self, event: &PlatformEventData) -> KeyboardData {
- if let plasmo::EventData::Keyboard(event) = downcast(event) {
- KeyboardData::new(event)
- } else {
- panic!("event should be of type Keyboard")
- }
- }
-
- fn convert_media_data(&self, _: &PlatformEventData) -> MediaData {
- panic!("media events not supported")
- }
-
- fn convert_mounted_data(&self, event: &PlatformEventData) -> MountedData {
- event.downcast::().cloned().unwrap().into()
- }
-
- fn convert_mouse_data(&self, event: &PlatformEventData) -> MouseData {
- if let plasmo::EventData::Mouse(event) = downcast(event) {
- MouseData::new(event)
- } else {
- panic!("event should be of type Mouse")
- }
- }
-
- fn convert_pointer_data(&self, _: &PlatformEventData) -> PointerData {
- panic!("pointer events not supported")
- }
-
- fn convert_scroll_data(&self, _: &PlatformEventData) -> ScrollData {
- panic!("scroll events not supported")
- }
-
- fn convert_selection_data(&self, _: &PlatformEventData) -> SelectionData {
- panic!("selection events not supported")
- }
-
- fn convert_toggle_data(&self, _: &PlatformEventData) -> ToggleData {
- panic!("toggle events not supported")
- }
-
- fn convert_touch_data(&self, _: &PlatformEventData) -> TouchData {
- panic!("touch events not supported")
- }
-
- fn convert_transition_data(&self, _: &PlatformEventData) -> TransitionData {
- panic!("transition events not supported")
- }
-
- fn convert_wheel_data(&self, event: &PlatformEventData) -> WheelData {
- if let plasmo::EventData::Wheel(event) = downcast(event) {
- WheelData::new(event)
- } else {
- panic!("event should be of type Wheel")
- }
- }
-}
diff --git a/packages/dioxus-tui/src/lib.rs b/packages/dioxus-tui/src/lib.rs
deleted file mode 100644
index 294c0300b..000000000
--- a/packages/dioxus-tui/src/lib.rs
+++ /dev/null
@@ -1,208 +0,0 @@
-#![doc = include_str!("../README.md")]
-#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")]
-#![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
-
-mod element;
-mod events;
-
-use std::{
- any::Any,
- ops::Deref,
- rc::Rc,
- sync::{Arc, RwLock},
-};
-
-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::DioxusTUIMutationWriter;
-pub use plasmo::{query::Query, Config, RenderingMode, Size, TuiContext};
-use plasmo::{render, Driver};
-
-pub mod launch {
- use super::*;
-
- pub type Config = super::Config;
- /// Launches the WebView and runs the event loop, with configuration and root props.
- pub fn launch(
- root: fn() -> Element,
- contexts: Vec Box>>,
- platform_config: Config,
- ) {
- let mut virtual_dom = VirtualDom::new(root);
-
- for context in contexts {
- virtual_dom.insert_any_root_context(context());
- }
-
- launch_vdom_cfg(virtual_dom, platform_config)
- }
-}
-
-pub fn launch(app: fn() -> Element) {
- launch_cfg(app, Config::default())
-}
-
-pub fn launch_cfg(app: fn() -> Element, cfg: Config) {
- launch_vdom_cfg(VirtualDom::new(app), cfg)
-}
-
-pub fn launch_cfg_with_props(app: fn(P) -> Element, props: P, cfg: Config) {
- launch_vdom_cfg(VirtualDom::new_with_props(app, props), cfg)
-}
-
-pub fn launch_vdom_cfg(vdom: VirtualDom, cfg: Config) {
- dioxus_html::set_event_converter(Box::new(events::SerializedHtmlEventConverter));
-
- render(cfg, |rdom, taffy, event_tx| {
- let dioxus_state = {
- let mut rdom = rdom.write().unwrap();
- DioxusState::create(&mut rdom)
- };
- let dioxus_state = Rc::new(RwLock::new(dioxus_state));
- let vdom = vdom
- .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 queued_events = Vec::new();
-
- let mut myself = DioxusRenderer {
- vdom,
- dioxus_state,
- queued_events,
- #[cfg(all(feature = "hot-reload", debug_assertions))]
- hot_reload_rx: {
- let (hot_reload_tx, hot_reload_rx) =
- tokio::sync::mpsc::unbounded_channel::();
- dioxus_hot_reload::connect(move |msg| {
- let _ = hot_reload_tx.send(msg);
- });
- 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();
-}
-
-struct DioxusRenderer {
- vdom: VirtualDom,
- dioxus_state: Rc>,
- // Events that are queued up to be sent to the vdom next time the vdom is polled
- queued_events: Vec<(ElementId, &'static str, Box, bool)>,
- #[cfg(all(feature = "hot-reload", debug_assertions))]
- hot_reload_rx: tokio::sync::mpsc::UnboundedReceiver,
-}
-
-impl Driver for DioxusRenderer {
- fn update(&mut self, rdom: &Arc>) {
- 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
- self.vdom.render_immediate(&mut writer);
- }
-
- fn handle_event(
- &mut self,
- rdom: &Arc>,
- id: NodeId,
- event: &str,
- value: Rc,
- bubbles: bool,
- ) {
- let id = { rdom.read().unwrap().get(id).unwrap().mounted_id() };
- if let Some(id) = id {
- let inner_value = value.deref().clone();
- let boxed_event = Box::new(inner_value);
- let platform_event = PlatformEventData::new(boxed_event);
- self.vdom
- .handle_event(event, Rc::new(platform_event), id, bubbles);
- }
- }
-
- fn poll_async(&mut self) -> std::pin::Pin + '_>> {
- // Add any queued events
- for (id, event, value, bubbles) in self.queued_events.drain(..) {
- let platform_event = PlatformEventData::new(value);
- self.vdom
- .handle_event(event, Rc::new(platform_event), id, bubbles);
- }
-
- #[cfg(all(feature = "hot-reload", debug_assertions))]
- return Box::pin(async {
- let hot_reload_wait = self.hot_reload_rx.recv();
- let mut hot_reload_msg = None;
- let wait_for_work = self.vdom.wait_for_work();
- tokio::select! {
- Some(msg) = hot_reload_wait => {
- #[cfg(all(feature = "hot-reload", debug_assertions))]
- {
- hot_reload_msg = Some(msg);
- }
- #[cfg(not(all(feature = "hot-reload", debug_assertions)))]
- let () = msg;
- }
- _ = wait_for_work => {}
- }
- // if we have a new template, replace the old one
- if let Some(msg) = hot_reload_msg {
- match msg {
- dioxus_hot_reload::HotReloadMsg::UpdateTemplate(template) => {
- self.vdom.replace_template(template);
- }
- dioxus_hot_reload::HotReloadMsg::Shutdown => {
- std::process::exit(0);
- }
- }
- }
- });
-
- #[cfg(not(all(feature = "hot-reload", debug_assertions)))]
- Box::pin(self.vdom.wait_for_work())
- }
-}
-
-#[derive(Clone)]
-pub struct DioxusElementToNodeId {
- mapping: Rc>,
-}
-
-impl DioxusElementToNodeId {
- pub fn get_node_id(&self, element_id: ElementId) -> Option {
- self.mapping
- .read()
- .unwrap()
- .try_element_to_node_id(element_id)
- }
-}
diff --git a/packages/dioxus-tui/test.html b/packages/dioxus-tui/test.html
deleted file mode 100644
index 5298c723e..000000000
--- a/packages/dioxus-tui/test.html
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
- Test
-
-
-
-
-
-
-
-
Hello World
-
This is a test
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/packages/dioxus-tui/tests/events.rs b/packages/dioxus-tui/tests/events.rs
deleted file mode 100644
index f49b64d97..000000000
--- a/packages/dioxus-tui/tests/events.rs
+++ /dev/null
@@ -1,381 +0,0 @@
-use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent};
-use dioxus::prelude::*;
-use dioxus_html::input_data::keyboard_types::Code;
-use dioxus_tui::TuiContext;
-use std::future::Future;
-use std::pin::Pin;
-use std::task::{Context, Poll};
-
-/// The tui renderer will look for any event that has occured or any future that has resolved in a loop.
-/// It will resolve at most one event per loop.
-/// This future will resolve after a certain number of polls. If the number of polls is greater than the number of events triggered, and the event has not been recieved there is an issue with the event system.
-struct PollN(usize);
-impl PollN {
- fn new(n: usize) -> Self {
- PollN(n)
- }
-}
-impl Future for PollN {
- type Output = ();
-
- fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll {
- if self.0 == 0 {
- Poll::Ready(())
- } else {
- self.0 -= 1;
- Poll::Pending
- }
- }
-}
-
-#[test]
-fn key_down() {
- dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
-
- fn app() -> Element {
- let render_count = use_signal(|| 0);
- let mut render_count_handle = render_count;
- let tui_ctx: TuiContext = consume_context();
-
- spawn(async move {
- PollN::new(3).await;
- render_count_handle.with_mut(|x| *x + 1);
- });
- if render_count() > 2 {
- panic!("Event was not received");
- }
- // focus the element
- tui_ctx.inject_event(Event::Key(KeyEvent {
- code: KeyCode::Tab,
- modifiers: KeyModifiers::NONE,
- kind: crossterm::event::KeyEventKind::Press,
- state: crossterm::event::KeyEventState::NONE,
- }));
- tui_ctx.inject_event(Event::Key(KeyEvent {
- code: KeyCode::Char('a'),
- modifiers: KeyModifiers::NONE,
- kind: crossterm::event::KeyEventKind::Press,
- state: crossterm::event::KeyEventState::NONE,
- }));
- rsx! {
- div {
- width: "100%",
- height: "100%",
- onkeydown: move |evt| {
- assert_eq!(evt.data.code(), Code::KeyA);
- tui_ctx.quit();
- }
- }
- }
- }
-}
-
-#[test]
-fn mouse_down() {
- dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
-
- fn app() -> Element {
- let render_count = use_signal(|| 0);
- let tui_ctx: TuiContext = consume_context();
- let mut render_count_handle = render_count;
- spawn(async move {
- PollN::new(2).await;
- render_count_handle.with_mut(|x| *x + 1);
- });
- if render_count() > 2 {
- panic!("Event was not received");
- }
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 0,
- row: 0,
- kind: crossterm::event::MouseEventKind::Down(MouseButton::Left),
- modifiers: KeyModifiers::NONE,
- }));
- rsx! {
- div {
- width: "100%",
- height: "100%",
- onmousedown: move |evt| {
- assert!(
- evt.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Primary)
- );
- tui_ctx.quit();
- }
- }
- }
- }
-}
-
-#[test]
-fn mouse_up() {
- dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
-
- fn app() -> Element {
- let render_count = use_signal(|| 0);
- let tui_ctx: TuiContext = consume_context();
- let mut render_count_handle = render_count;
- spawn(async move {
- PollN::new(3).await;
- render_count_handle.with_mut(|x| *x + 1);
- });
- if render_count() > 2 {
- panic!("Event was not received");
- }
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 0,
- row: 0,
- kind: crossterm::event::MouseEventKind::Down(MouseButton::Left),
- modifiers: KeyModifiers::NONE,
- }));
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 0,
- row: 0,
- kind: crossterm::event::MouseEventKind::Up(MouseButton::Left),
- modifiers: KeyModifiers::NONE,
- }));
- rsx! {
- div {
- width: "100%",
- height: "100%",
- onmouseup: move |_| {
- tui_ctx.quit();
- }
- }
- }
- }
-}
-
-#[test]
-fn mouse_enter() {
- dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
-
- fn app() -> Element {
- let render_count = use_signal(|| 0);
- let mut render_count_handle = render_count;
- let tui_ctx: TuiContext = consume_context();
- spawn(async move {
- PollN::new(3).await;
- render_count_handle.with_mut(|x| *x + 1);
- });
- if render_count() > 2 {
- panic!("Event was not received");
- }
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 100,
- row: 100,
- kind: crossterm::event::MouseEventKind::Moved,
- modifiers: KeyModifiers::NONE,
- }));
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 0,
- row: 0,
- kind: crossterm::event::MouseEventKind::Moved,
- modifiers: KeyModifiers::NONE,
- }));
- rsx! {
- div {
- width: "50%",
- height: "50%",
- onmouseenter: move |_| {
- tui_ctx.quit();
- }
- }
- }
- }
-}
-
-#[test]
-fn mouse_exit() {
- dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
-
- fn app() -> Element {
- let render_count = use_signal(|| 0);
- let tui_ctx: TuiContext = consume_context();
- let mut render_count_handle = render_count;
- spawn(async move {
- PollN::new(3).await;
- render_count_handle.with_mut(|x| *x + 1);
- });
- if render_count() > 2 {
- panic!("Event was not received");
- }
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 0,
- row: 0,
- kind: crossterm::event::MouseEventKind::Moved,
- modifiers: KeyModifiers::NONE,
- }));
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 100,
- row: 100,
- kind: crossterm::event::MouseEventKind::Moved,
- modifiers: KeyModifiers::NONE,
- }));
- rsx! {
- div {
- width: "50%",
- height: "50%",
- onmouseenter: move |_| {
- tui_ctx.quit();
- }
- }
- }
- }
-}
-
-#[test]
-fn mouse_move() {
- dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
-
- fn app() -> Element {
- let render_count = use_signal(|| 0);
- let tui_ctx: TuiContext = consume_context();
- let mut render_count_handle = render_count;
- spawn(async move {
- PollN::new(3).await;
- render_count_handle.with_mut(|x| *x + 1);
- });
- if render_count() > 2 {
- panic!("Event was not received");
- }
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 40,
- row: 40,
- kind: crossterm::event::MouseEventKind::Moved,
- modifiers: KeyModifiers::NONE,
- }));
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 60,
- row: 60,
- kind: crossterm::event::MouseEventKind::Moved,
- modifiers: KeyModifiers::NONE,
- }));
- rsx! {
- div {
- width: "100%",
- height: "100%",
- onmousemove: move |_| {
- tui_ctx.quit();
- }
- }
- }
- }
-}
-
-#[test]
-fn wheel() {
- dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
-
- fn app() -> Element {
- let render_count = use_signal(|| 0);
- let tui_ctx: TuiContext = consume_context();
- let mut render_count_handle = render_count;
- spawn(async move {
- PollN::new(3).await;
- render_count_handle.with_mut(|x| *x + 1);
- });
- if render_count() > 2 {
- panic!("Event was not received");
- }
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 50,
- row: 50,
- kind: crossterm::event::MouseEventKind::Moved,
- modifiers: KeyModifiers::NONE,
- }));
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 50,
- row: 50,
- kind: crossterm::event::MouseEventKind::ScrollDown,
- modifiers: KeyModifiers::NONE,
- }));
- rsx! {
- div {
- width: "100%",
- height: "100%",
- onwheel: move |evt| {
- assert!(evt.data.delta().strip_units().y > 0.0);
- tui_ctx.quit();
- }
- }
- }
- }
-}
-
-#[test]
-fn click() {
- dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
-
- fn app() -> Element {
- let render_count = use_signal(|| 0);
- let tui_ctx: TuiContext = consume_context();
- let mut render_count_handle = render_count;
- spawn(async move {
- PollN::new(3).await;
- render_count_handle.with_mut(|x| *x + 1);
- });
- if render_count() > 2 {
- panic!("Event was not received");
- }
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 50,
- row: 50,
- kind: crossterm::event::MouseEventKind::Down(MouseButton::Left),
- modifiers: KeyModifiers::NONE,
- }));
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 50,
- row: 50,
- kind: crossterm::event::MouseEventKind::Up(MouseButton::Left),
- modifiers: KeyModifiers::NONE,
- }));
- rsx! {
- div {
- width: "100%",
- height: "100%",
- onclick: move |_| {
- tui_ctx.quit();
- }
- }
- }
- }
-}
-
-#[test]
-fn context_menu() {
- dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless());
-
- fn app() -> Element {
- let render_count = use_signal(|| 0);
- let tui_ctx: TuiContext = consume_context();
- let mut render_count_handle = render_count;
- spawn(async move {
- PollN::new(3).await;
- render_count_handle.with_mut(|x| *x + 1);
- });
- if render_count() > 2 {
- panic!("Event was not received");
- }
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 50,
- row: 50,
- kind: crossterm::event::MouseEventKind::Down(MouseButton::Right),
- modifiers: KeyModifiers::NONE,
- }));
- tui_ctx.inject_event(Event::Mouse(MouseEvent {
- column: 50,
- row: 50,
- kind: crossterm::event::MouseEventKind::Up(MouseButton::Right),
- modifiers: KeyModifiers::NONE,
- }));
- rsx! {
- div {
- width: "100%",
- height: "100%",
- oncontextmenu: move |_| {
- tui_ctx.quit();
- }
- }
- }
- }
-}
diff --git a/packages/dioxus/Cargo.toml b/packages/dioxus/Cargo.toml
index fbaed9660..67029a37b 100644
--- a/packages/dioxus/Cargo.toml
+++ b/packages/dioxus/Cargo.toml
@@ -24,7 +24,6 @@ dioxus-desktop = { workspace = true, optional = true }
dioxus-fullstack = { workspace = true, optional = true }
dioxus-liveview = { workspace = true, optional = true }
dioxus-ssr ={ workspace = true, optional = true }
-dioxus-tui = { workspace = true, optional = true }
serde = { version = "1.0.136", optional = true }
@@ -50,7 +49,6 @@ web = ["dioxus-web", "dioxus-fullstack?/web", "dioxus-config-macro/web", "dioxus
ssr = ["dioxus-ssr", "dioxus-router?/ssr", "dioxus-config-macro/ssr"]
liveview = ["dioxus-liveview", "dioxus-config-macro/liveview", "dioxus-router?/liveview"]
axum = ["dioxus-fullstack?/axum", "dioxus-fullstack?/server", "ssr", "dioxus-liveview?/axum"]
-tui = ["dioxus-tui", "dioxus-config-macro/tui"]
# This feature just disables the no-renderer-enabled warning
third-party-renderer = []
diff --git a/packages/dioxus/build.rs b/packages/dioxus/build.rs
index 15315eeb9..d5d3e7374 100644
--- a/packages/dioxus/build.rs
+++ b/packages/dioxus/build.rs
@@ -7,7 +7,7 @@ fn main() {
let liveview_renderers = ["liveview", "axum"];
let fullstack_renderers = ["axum"];
- let client_renderers = ["desktop", "mobile", "web", "tui"];
+ let client_renderers = ["desktop", "mobile", "web"];
let client_renderer_selected = client_renderers
.iter()
.any(|renderer| feature_enabled(renderer));
diff --git a/packages/dioxus/src/launch.rs b/packages/dioxus/src/launch.rs
index e58e3ecb5..4030f093f 100644
--- a/packages/dioxus/src/launch.rs
+++ b/packages/dioxus/src/launch.rs
@@ -80,17 +80,6 @@ impl LaunchBuilder {
}
}
- #[cfg(feature = "tui")]
- #[cfg_attr(docsrs, doc(cfg(feature = "tui")))]
- /// Launch your tui application
- pub fn tui() -> LaunchBuilder {
- LaunchBuilder {
- launch_fn: dioxus_tui::launch::launch,
- contexts: Vec::new(),
- platform_config: None,
- }
- }
-
/// Provide a custom launch function for your application.
///
/// Useful for third party renderers to tap into the launch builder API without having to reimplement it.
@@ -184,24 +173,11 @@ mod current_platform {
))]
pub use dioxus_liveview::launch::*;
- #[cfg(all(
- feature = "tui",
- not(any(
- feature = "liveview",
- feature = "web",
- feature = "desktop",
- feature = "mobile",
- feature = "fullstack"
- ))
- ))]
- pub use dioxus_tui::launch::*;
-
#[cfg(not(any(
feature = "liveview",
feature = "desktop",
feature = "mobile",
feature = "web",
- feature = "tui",
feature = "fullstack"
)))]
pub type Config = ();
@@ -211,7 +187,6 @@ mod current_platform {
feature = "desktop",
feature = "mobile",
feature = "web",
- feature = "tui",
feature = "fullstack"
)))]
pub fn launch(
@@ -251,10 +226,3 @@ pub fn launch_desktop(app: fn() -> Element) {
pub fn launch_fullstack(app: fn() -> Element) {
LaunchBuilder::fullstack().launch(app)
}
-
-#[cfg(feature = "tui")]
-#[cfg_attr(docsrs, doc(cfg(feature = "tui")))]
-/// Launch your tui application without any additional configuration. See [`LaunchBuilder`] for more options.
-pub fn launch_tui(app: fn() -> Element) {
- LaunchBuilder::tui().launch(app)
-}
diff --git a/packages/dioxus/src/lib.rs b/packages/dioxus/src/lib.rs
index bd2e8f70b..b7afd3be0 100644
--- a/packages/dioxus/src/lib.rs
+++ b/packages/dioxus/src/lib.rs
@@ -106,10 +106,6 @@ pub use dioxus_desktop as mobile;
#[cfg_attr(docsrs, doc(cfg(feature = "liveview")))]
pub use dioxus_liveview as liveview;
-#[cfg(feature = "tui")]
-#[cfg_attr(docsrs, doc(cfg(feature = "tui")))]
-pub use dioxus_tui as tui;
-
#[cfg(feature = "ssr")]
#[cfg_attr(docsrs, doc(cfg(feature = "ssr")))]
pub use dioxus_ssr as ssr;
diff --git a/packages/native-core-macro/.gitignore b/packages/native-core-macro/.gitignore
deleted file mode 100644
index 96ef6c0b9..000000000
--- a/packages/native-core-macro/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/target
-Cargo.lock
diff --git a/packages/native-core-macro/Cargo.toml b/packages/native-core-macro/Cargo.toml
deleted file mode 100644
index 92d739117..000000000
--- a/packages/native-core-macro/Cargo.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-[package]
-name = "dioxus-native-core-macro"
-version = { workspace = true }
-edition = "2021"
-description = "Build natively rendered apps with Dioxus"
-license = "MIT OR Apache-2.0"
-repository = "https://github.com/DioxusLabs/dioxus/"
-homepage = "https://dioxuslabs.com"
-keywords = ["dom", "ui", "gui", "react"]
-authors = ["Jonathan Kelley", "Evan Almloff"]
-
-[lib]
-proc-macro = true
-
-[dependencies]
-syn = { version = "2.0", features = ["extra-traits", "full"] }
-quote = "1.0"
-
-[dev-dependencies]
-smallvec = "1.6"
-rustc-hash = { workspace = true }
-anymap = "0.12.1"
-dioxus = { workspace = true }
-dioxus-native-core = { workspace = true }
diff --git a/packages/native-core-macro/README.md b/packages/native-core-macro/README.md
deleted file mode 100644
index 4cf19cece..000000000
--- a/packages/native-core-macro/README.md
+++ /dev/null
@@ -1,39 +0,0 @@
-# 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/learn/0.4/) |
-[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 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.
diff --git a/packages/native-core-macro/src/lib.rs b/packages/native-core-macro/src/lib.rs
deleted file mode 100644
index fdaa12cf5..000000000
--- a/packages/native-core-macro/src/lib.rs
+++ /dev/null
@@ -1,390 +0,0 @@
-#![doc = include_str!("../README.md")]
-#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")]
-#![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
-
-extern crate proc_macro;
-
-use std::collections::HashSet;
-
-use proc_macro::TokenStream;
-use quote::{format_ident, quote};
-use syn::{parse_macro_input, ItemImpl, Type, TypePath, TypeTuple};
-
-/// A helper attribute for deriving `State` for a struct.
-#[proc_macro_attribute]
-pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream {
- let impl_block: syn::ItemImpl = parse_macro_input!(input as syn::ItemImpl);
-
- let has_create_fn = impl_block
- .items
- .iter()
- .any(|item| matches!(item, syn::ImplItem::Fn(method) if method.sig.ident == "create"));
-
- let parent_dependencies = impl_block
- .items
- .iter()
- .find_map(|item| {
- if let syn::ImplItem::Type(syn::ImplItemType { ident, ty, .. }) = item {
- (ident == "ParentDependencies").then_some(ty)
- } else {
- None
- }
- })
- .expect("ParentDependencies must be defined");
- let child_dependencies = impl_block
- .items
- .iter()
- .find_map(|item| {
- if let syn::ImplItem::Type(syn::ImplItemType { ident, ty, .. }) = item {
- (ident == "ChildDependencies").then_some(ty)
- } else {
- None
- }
- })
- .expect("ChildDependencies must be defined");
- let node_dependencies = impl_block
- .items
- .iter()
- .find_map(|item| {
- if let syn::ImplItem::Type(syn::ImplItemType { ident, ty, .. }) = item {
- (ident == "NodeDependencies").then_some(ty)
- } else {
- None
- }
- })
- .expect("NodeDependencies must be defined");
-
- let this_type = &impl_block.self_ty;
- let this_type = extract_type_path(this_type)
- .unwrap_or_else(|| panic!("Self must be a type path, found {}", quote!(#this_type)));
-
- let mut combined_dependencies = HashSet::new();
-
- let self_path: TypePath = syn::parse_quote!(Self);
-
- let parent_dependencies = match extract_tuple(parent_dependencies) {
- Some(tuple) => {
- let mut parent_dependencies = Vec::new();
- for type_ in &tuple.elems {
- let mut type_ = extract_type_path(type_).unwrap_or_else(|| {
- panic!(
- "ParentDependencies must be a tuple of type paths, found {}",
- quote!(#type_)
- )
- });
- if type_ == self_path {
- type_ = this_type.clone();
- }
- combined_dependencies.insert(type_.clone());
- parent_dependencies.push(type_);
- }
- parent_dependencies
- }
- _ => panic!(
- "ParentDependencies must be a tuple, found {}",
- quote!(#parent_dependencies)
- ),
- };
- let child_dependencies = match extract_tuple(child_dependencies) {
- Some(tuple) => {
- let mut child_dependencies = Vec::new();
- for type_ in &tuple.elems {
- let mut type_ = extract_type_path(type_).unwrap_or_else(|| {
- panic!(
- "ChildDependencies must be a tuple of type paths, found {}",
- quote!(#type_)
- )
- });
- if type_ == self_path {
- type_ = this_type.clone();
- }
- combined_dependencies.insert(type_.clone());
- child_dependencies.push(type_);
- }
- child_dependencies
- }
- _ => panic!(
- "ChildDependencies must be a tuple, found {}",
- quote!(#child_dependencies)
- ),
- };
- let node_dependencies = match extract_tuple(node_dependencies) {
- Some(tuple) => {
- let mut node_dependencies = Vec::new();
- for type_ in &tuple.elems {
- let mut type_ = extract_type_path(type_).unwrap_or_else(|| {
- panic!(
- "NodeDependencies must be a tuple of type paths, found {}",
- quote!(#type_)
- )
- });
- if type_ == self_path {
- type_ = this_type.clone();
- }
- combined_dependencies.insert(type_.clone());
- node_dependencies.push(type_);
- }
- node_dependencies
- }
- _ => panic!(
- "NodeDependencies must be a tuple, found {}",
- quote!(#node_dependencies)
- ),
- };
- combined_dependencies.insert(this_type.clone());
-
- let combined_dependencies: Vec<_> = combined_dependencies.into_iter().collect();
- let parent_dependancies_idxes: Vec<_> = parent_dependencies
- .iter()
- .filter_map(|ident| combined_dependencies.iter().position(|i| i == ident))
- .collect();
- let child_dependencies_idxes: Vec<_> = child_dependencies
- .iter()
- .filter_map(|ident| combined_dependencies.iter().position(|i| i == ident))
- .collect();
- let node_dependencies_idxes: Vec<_> = node_dependencies
- .iter()
- .filter_map(|ident| combined_dependencies.iter().position(|i| i == ident))
- .collect();
- let this_type_idx = combined_dependencies
- .iter()
- .enumerate()
- .find_map(|(i, ident)| (this_type == *ident).then_some(i))
- .unwrap();
- let this_view = format_ident!("__data{}", this_type_idx);
-
- let combined_dependencies_quote = combined_dependencies.iter().map(|ident| {
- if ident == &this_type {
- quote! {shipyard::ViewMut<#ident>}
- } else {
- quote! {shipyard::View<#ident>}
- }
- });
- let combined_dependencies_quote = quote!((#(#combined_dependencies_quote,)*));
-
- let ItemImpl {
- attrs,
- defaultness,
- unsafety,
- impl_token,
- generics,
- trait_,
- self_ty,
- items,
- ..
- } = impl_block;
- let for_ = trait_.as_ref().map(|t| t.2);
- let trait_ = trait_.map(|t| t.1);
-
- let split_views: Vec<_> = (0..combined_dependencies.len())
- .map(|i| {
- let ident = format_ident!("__data{}", i);
- if i == this_type_idx {
- quote! {mut #ident}
- } else {
- quote! {#ident}
- }
- })
- .collect();
-
- let node_view = node_dependencies_idxes
- .iter()
- .map(|i| format_ident!("__data{}", i))
- .collect::>();
- let get_node_view = {
- if node_dependencies.is_empty() {
- quote! {
- let raw_node = ();
- }
- } else {
- let temps = (0..node_dependencies.len())
- .map(|i| format_ident!("__temp{}", i))
- .collect::>();
- quote! {
- let raw_node: (#(*const #node_dependencies,)*) = {
- let (#(#temps,)*) = (#(node_view,)*).get(id).unwrap_or_else(|err| panic!("Failed to get node view {:?}", err));
- (#(#temps as *const _,)*)
- };
- }
- }
- };
- let deref_node_view = {
- if node_dependencies.is_empty() {
- quote! {
- let node = raw_node;
- }
- } else {
- let indexes = (0..node_dependencies.len()).map(syn::Index::from);
- quote! {
- let node = unsafe { (#(dioxus_native_core::prelude::DependancyView::new(&*raw_node.#indexes),)*) };
- }
- }
- };
-
- let parent_view = parent_dependancies_idxes
- .iter()
- .map(|i| format_ident!("__data{}", i))
- .collect::>();
- let get_parent_view = {
- if parent_dependencies.is_empty() {
- quote! {
- let raw_parent = tree.parent_id_advanced(id, Self::TRAVERSE_SHADOW_DOM).map(|_| ());
- }
- } else {
- let temps = (0..parent_dependencies.len())
- .map(|i| format_ident!("__temp{}", i))
- .collect::>();
- quote! {
- let raw_parent = tree.parent_id_advanced(id, Self::TRAVERSE_SHADOW_DOM).and_then(|parent_id| {
- let raw_parent: Option<(#(*const #parent_dependencies,)*)> = (#(parent_view,)*).get(parent_id).ok().map(|c| {
- let (#(#temps,)*) = c;
- (#(#temps as *const _,)*)
- });
- raw_parent
- });
- }
- }
- };
- let deref_parent_view = {
- if parent_dependencies.is_empty() {
- quote! {
- let parent = raw_parent;
- }
- } else {
- let indexes = (0..parent_dependencies.len()).map(syn::Index::from);
- quote! {
- let parent = unsafe { raw_parent.map(|raw_parent| (#(dioxus_native_core::prelude::DependancyView::new(&*raw_parent.#indexes),)*)) };
- }
- }
- };
-
- let child_view = child_dependencies_idxes
- .iter()
- .map(|i| format_ident!("__data{}", i))
- .collect::>();
- let get_child_view = {
- if child_dependencies.is_empty() {
- quote! {
- let raw_children: Vec<_> = tree.children_ids_advanced(id, Self::TRAVERSE_SHADOW_DOM).into_iter().map(|_| ()).collect();
- }
- } else {
- let temps = (0..child_dependencies.len())
- .map(|i| format_ident!("__temp{}", i))
- .collect::>();
- quote! {
- let raw_children: Vec<_> = tree.children_ids_advanced(id, Self::TRAVERSE_SHADOW_DOM).into_iter().filter_map(|id| {
- let raw_children: Option<(#(*const #child_dependencies,)*)> = (#(child_view,)*).get(id).ok().map(|c| {
- let (#(#temps,)*) = c;
- (#(#temps as *const _,)*)
- });
- raw_children
- }).collect();
- }
- }
- };
- let deref_child_view = {
- if child_dependencies.is_empty() {
- quote! {
- let children = raw_children;
- }
- } else {
- let indexes = (0..child_dependencies.len()).map(syn::Index::from);
- quote! {
- let children = unsafe { raw_children.iter().map(|raw_children| (#(dioxus_native_core::prelude::DependancyView::new(&*raw_children.#indexes),)*)).collect::>() };
- }
- }
- };
-
- let trait_generics = trait_
- .as_ref()
- .unwrap()
- .segments
- .last()
- .unwrap()
- .arguments
- .clone();
-
- // if a create function is defined, we don't generate one
- // otherwise we generate a default one that uses the update function and the default constructor
- let create_fn = (!has_create_fn).then(|| {
- quote! {
- fn create<'a>(
- node_view: dioxus_native_core::prelude::NodeView # trait_generics,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &dioxus_native_core::prelude::SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
- }
- });
-
- quote!(
- #(#attrs)*
- #defaultness #unsafety #impl_token #generics #trait_ #for_ #self_ty {
- #create_fn
-
- #(#items)*
-
- fn workload_system(type_id: std::any::TypeId, dependants: std::sync::Arc, pass_direction: dioxus_native_core::prelude::PassDirection) -> dioxus_native_core::exports::shipyard::WorkloadSystem {
- use dioxus_native_core::exports::shipyard::{IntoWorkloadSystem, Get, AddComponent};
- use dioxus_native_core::tree::TreeRef;
- use dioxus_native_core::prelude::{NodeType, NodeView};
-
- let node_mask = Self::NODE_MASK.build();
-
- (move |data: #combined_dependencies_quote, run_view: dioxus_native_core::prelude::RunPassView #trait_generics| {
- let (#(#split_views,)*) = data;
- let tree = run_view.tree.clone();
- let node_types = run_view.node_type.clone();
- dioxus_native_core::prelude::run_pass(type_id, dependants.clone(), pass_direction, run_view, |id, context| {
- let node_data: &NodeType<_> = node_types.get(id).unwrap_or_else(|err| panic!("Failed to get node type {:?}", err));
- // get all of the states from the tree view
- // Safety: No node has itself as a parent or child.
- let raw_myself: Option<*mut Self> = (&mut #this_view).get(id).ok().map(|c| c as *mut _);
- #get_node_view
- #get_parent_view
- #get_child_view
-
- let myself: Option<&mut Self> = unsafe { raw_myself.map(|val| &mut *val) };
- #deref_node_view
- #deref_parent_view
- #deref_child_view
-
- let view = NodeView::new(id, node_data, &node_mask);
- if let Some(myself) = myself {
- myself
- .update(view, node, parent, children, context)
- }
- else {
- (&mut #this_view).add_component_unchecked(
- id,
- Self::create(view, node, parent, children, context));
- true
- }
- })
- }).into_workload_system().unwrap()
- }
- }
- )
- .into()
-}
-
-fn extract_tuple(ty: &Type) -> Option {
- match ty {
- Type::Tuple(tuple) => Some(tuple.clone()),
- Type::Group(group) => extract_tuple(&group.elem),
- _ => None,
- }
-}
-
-fn extract_type_path(ty: &Type) -> Option {
- match ty {
- Type::Path(path) => Some(path.clone()),
- Type::Group(group) => extract_type_path(&group.elem),
- _ => None,
- }
-}
diff --git a/packages/native-core/.gitignore b/packages/native-core/.gitignore
deleted file mode 100644
index 96ef6c0b9..000000000
--- a/packages/native-core/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/target
-Cargo.lock
diff --git a/packages/native-core/Cargo.toml b/packages/native-core/Cargo.toml
deleted file mode 100644
index db75fcfd8..000000000
--- a/packages/native-core/Cargo.toml
+++ /dev/null
@@ -1,39 +0,0 @@
-[package]
-name = "dioxus-native-core"
-version = { workspace = true }
-edition = "2021"
-license = "MIT OR Apache-2.0"
-repository = "https://github.com/DioxusLabs/dioxus/"
-homepage = "https://dioxuslabs.com"
-description = "Build natively rendered apps with Dioxus"
-keywords = ["dom", "ui", "gui", "react"]
-authors = ["Jonathan Kelley", "Evan Almloff"]
-
-[dependencies]
-dioxus-core = { workspace = true, optional = true }
-
-keyboard-types = "0.7"
-smallvec = "1.6"
-rustc-hash = { workspace = true }
-anymap = "1.0.0-beta.2"
-parking_lot = { version = "0.12.1", features = ["send_guard"] }
-dashmap = "5.4.0"
-
-# for parsing attributes
-taffy = { version = "0.3.12", optional = true }
-lightningcss = { version = "1.0.0-alpha.39", optional = true }
-
-shipyard = { version = "0.6.2", features = ["proc", "std"], default-features = false }
-
-[dev-dependencies]
-rand = "0.8.5"
-dioxus = { workspace = true }
-tokio = { workspace = true, features = ["full"] }
-dioxus-native-core = { workspace = true, features = ["dioxus"] }
-dioxus-native-core-macro = { workspace = true }
-
-[features]
-default = []
-layout-attributes = ["dep:taffy", "dep:lightningcss"]
-dioxus = ["dioxus-core"]
-parallel = ["shipyard/parallel"]
diff --git a/packages/native-core/README.md b/packages/native-core/README.md
deleted file mode 100644
index c467d37de..000000000
--- a/packages/native-core/README.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# 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 several 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 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.
diff --git a/packages/native-core/_tests/called_minimally_on_build.rs b/packages/native-core/_tests/called_minimally_on_build.rs
deleted file mode 100644
index af0ca7a7c..000000000
--- a/packages/native-core/_tests/called_minimally_on_build.rs
+++ /dev/null
@@ -1,237 +0,0 @@
-use dioxus::prelude::*;
-use dioxus_native_core::prelude::*;
-use dioxus_native_core_macro::partial_derive_state;
-use shipyard::Component;
-
-macro_rules! dep {
- ( child( $name:ty, $dep:ty ) ) => {
- #[partial_derive_state]
- impl State for $name {
- type ParentDependencies = ();
- type ChildDependencies = $dep;
- type NodeDependencies = ();
-
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::ALL;
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- _: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- self.0 += 1;
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
- }
- };
-
- ( parent( $name:ty, $dep:ty ) ) => {
- #[partial_derive_state]
- impl State for $name {
- type ParentDependencies = $dep;
- type ChildDependencies = ();
- type NodeDependencies = ();
-
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::ALL;
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- _: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- self.0 += 1;
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
- }
- };
-
- ( node( $name:ty, $dep:ty ) ) => {
- #[partial_derive_state]
- impl State for $name {
- type ParentDependencies = $dep;
- type ChildDependencies = ();
- type NodeDependencies = ();
-
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::ALL;
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- _: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- self.0 += 1;
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
- }
- };
-}
-
-macro_rules! test_state{
- ( state: ( $( $state:ty ),* ) ) => {
- #[test]
- fn state_reduce_initally_called_minimally() {
- #[allow(non_snake_case)]
- fn Base() -> Element {
- rsx!{
- div {
- div{
- div{
- p{}
- }
- p{
- "hello"
- }
- div{
- h1{}
- }
- p{
- "world"
- }
- }
- }
- }
- }
-
- let mut vdom = VirtualDom::new(Base);
-
- let mutations = vdom.rebuild();
-
- let mut dom: RealDom = RealDom::new([$( <$state>::to_type_erased() ),*]);
- let mut dioxus_state = DioxusState::create(&mut dom);
-
- dioxus_state.apply_mutations(&mut dom, mutations);
- dom.update_state(SendAnyMap::new());
-
- dom.traverse_depth_first_advanced(false, |n| {
- $(
- assert_eq!(n.get::<$state>().unwrap().0, 1);
- )*
- });
- }
- }
-}
-
-mod node_depends_on_child_and_parent {
- use super::*;
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Node(i32);
- dep!(node(Node, (Child, Parent)));
-
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Child(i32);
- dep!(child(Child, (Child,)));
-
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Parent(i32);
- dep!(parent(Parent, (Parent,)));
-
- test_state!(state: (Child, Node, Parent));
-}
-
-mod child_depends_on_node_that_depends_on_parent {
- use super::*;
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Node(i32);
- dep!(node(Node, (Parent,)));
-
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Child(i32);
- dep!(child(Child, (Node,)));
-
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Parent(i32);
- dep!(parent(Parent, (Parent,)));
-
- test_state!(state: (Child, Node, Parent));
-}
-
-mod parent_depends_on_node_that_depends_on_child {
- use super::*;
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Node(i32);
- dep!(node(Node, (Child,)));
-
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Child(i32);
- dep!(child(Child, (Child,)));
-
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Parent(i32);
- dep!(parent(Parent, (Node,)));
-
- test_state!(state: (Child, Node, Parent));
-}
-
-mod node_depends_on_other_node_state {
- use super::*;
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Node1(i32);
- dep!(node(Node1, (Node2,)));
-
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Node2(i32);
- dep!(node(Node2, ()));
-
- test_state!(state: (Node1, Node2));
-}
-
-mod node_child_and_parent_state_depends_on_self {
- use super::*;
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Node(i32);
- dep!(node(Node, ()));
-
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Child(i32);
- dep!(child(Child, (Child,)));
-
- #[derive(Debug, Clone, Default, PartialEq, Component)]
- struct Parent(i32);
- dep!(parent(Parent, (Parent,)));
-
- test_state!(state: (Child, Node, Parent));
-}
diff --git a/packages/native-core/_tests/custom_element.rs b/packages/native-core/_tests/custom_element.rs
deleted file mode 100644
index 1aaab3953..000000000
--- a/packages/native-core/_tests/custom_element.rs
+++ /dev/null
@@ -1,389 +0,0 @@
-use dioxus::prelude::*;
-use dioxus_native_core::{custom_element::CustomElement, prelude::*};
-use dioxus_native_core_macro::partial_derive_state;
-use shipyard::Component;
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Component)]
-pub struct ColorState {
- color: usize,
-}
-
-#[partial_derive_state]
-impl State for ColorState {
- type ParentDependencies = (Self,);
- type ChildDependencies = ();
- type NodeDependencies = ();
-
- // The color state should not be effected by the shadow dom
- const TRAVERSE_SHADOW_DOM: bool = false;
-
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new()
- .with_attrs(AttributeMaskBuilder::Some(&["color"]))
- .with_element();
-
- fn update<'a>(
- &mut self,
- view: NodeView,
- _: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- if let Some(size) = view
- .attributes()
- .into_iter()
- .flatten()
- .find(|attr| attr.attribute.name == "color")
- {
- self.color = size
- .value
- .as_float()
- .or_else(|| size.value.as_int().map(|i| i as f64))
- .or_else(|| size.value.as_text().and_then(|i| i.parse().ok()))
- .unwrap_or(0.0) as usize;
- } else if let Some((parent,)) = parent {
- *self = *parent;
- }
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Component)]
-pub struct LayoutState {
- size: usize,
-}
-
-#[partial_derive_state]
-impl State for LayoutState {
- type ParentDependencies = (Self,);
- type ChildDependencies = ();
- type NodeDependencies = ();
-
- // The layout state should be effected by the shadow dom
- const TRAVERSE_SHADOW_DOM: bool = true;
-
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new()
- .with_attrs(AttributeMaskBuilder::Some(&["size"]))
- .with_element();
-
- fn update<'a>(
- &mut self,
- view: NodeView,
- _: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- if let Some(size) = view
- .attributes()
- .into_iter()
- .flatten()
- .find(|attr| attr.attribute.name == "size")
- {
- self.size = size
- .value
- .as_float()
- .or_else(|| size.value.as_int().map(|i| i as f64))
- .or_else(|| size.value.as_text().and_then(|i| i.parse().ok()))
- .unwrap_or(0.0) as usize;
- } else if let Some((parent,)) = parent {
- if parent.size > 0 {
- self.size = parent.size - 1;
- }
- }
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
-}
-
-mod dioxus_elements {
- macro_rules! builder_constructors {
- (
- $(
- $(#[$attr:meta])*
- $name:ident {
- $(
- $(#[$attr_method:meta])*
- $fil:ident: $vil:ident,
- )*
- };
- )*
- ) => {
- $(
- #[allow(non_camel_case_types)]
- $(#[$attr])*
- pub struct $name;
-
- #[allow(non_upper_case_globals, unused)]
- impl $name {
- pub const TAG_NAME: &'static str = stringify!($name);
- pub const NAME_SPACE: Option<&'static str> = None;
-
- $(
- pub const $fil: (&'static str, Option<&'static str>, bool) = (stringify!($fil), None, false);
- )*
- }
-
- impl GlobalAttributes for $name {}
- )*
- }
- }
-
- pub trait GlobalAttributes {}
-
- pub trait SvgAttributes {}
-
- builder_constructors! {
- customelementslot {
- size: attr,
- color: attr,
- };
- customelementnoslot {
- size: attr,
- color: attr,
- };
- testing132 {
- color: attr,
- };
- }
-}
-
-struct CustomElementWithSlot {
- root: NodeId,
- slot: NodeId,
-}
-
-impl CustomElement for CustomElementWithSlot {
- const NAME: &'static str = "customelementslot";
-
- fn create(mut node: NodeMut<()>) -> Self {
- let dom = node.real_dom_mut();
- let child = dom.create_node(ElementNode {
- tag: "div".into(),
- namespace: None,
- attributes: Default::default(),
- listeners: Default::default(),
- });
- let slot_id = child.id();
- let mut root = dom.create_node(ElementNode {
- tag: "div".into(),
- namespace: None,
- attributes: Default::default(),
- listeners: Default::default(),
- });
- root.add_child(slot_id);
-
- Self {
- root: root.id(),
- slot: slot_id,
- }
- }
-
- fn slot(&self) -> Option {
- Some(self.slot)
- }
-
- fn roots(&self) -> Vec {
- vec![self.root]
- }
-
- fn attributes_changed(
- &mut self,
- node: NodeMut<()>,
- attributes: &dioxus_native_core::node_ref::AttributeMask,
- ) {
- println!("attributes_changed");
- println!("{:?}", attributes);
- println!("{:?}: {:#?}", node.id(), &*node.node_type());
- }
-}
-
-struct CustomElementWithNoSlot {
- root: NodeId,
-}
-
-impl CustomElement for CustomElementWithNoSlot {
- const NAME: &'static str = "customelementnoslot";
-
- fn create(mut node: NodeMut<()>) -> Self {
- let dom = node.real_dom_mut();
- let root = dom.create_node(ElementNode {
- tag: "div".into(),
- namespace: None,
- attributes: Default::default(),
- listeners: Default::default(),
- });
- Self { root: root.id() }
- }
-
- fn roots(&self) -> Vec {
- vec![self.root]
- }
-
- fn attributes_changed(
- &mut self,
- node: NodeMut<()>,
- attributes: &dioxus_native_core::node_ref::AttributeMask,
- ) {
- println!("attributes_changed");
- println!("{:?}", attributes);
- println!("{:?}: {:#?}", node.id(), &*node.node_type());
- }
-}
-
-#[test]
-fn custom_elements_work() {
- fn app() -> Element {
- let count = use_signal(|| 0);
-
- use_future(|count| async move {
- count.with_mut(|count| *count += 1);
- });
-
- rsx! {
- customelementslot {
- size: "{count}",
- color: "1",
- customelementslot {
- testing132 {}
- }
- }
- }
- }
-
- let rt = tokio::runtime::Builder::new_current_thread()
- .enable_time()
- .build()
- .unwrap();
-
- rt.block_on(async {
- let mut rdom = RealDom::new([LayoutState::to_type_erased(), ColorState::to_type_erased()]);
- rdom.register_custom_element::();
- let mut dioxus_state = DioxusState::create(&mut rdom);
- let mut dom = VirtualDom::new(app);
-
- let mutations = dom.rebuild();
- dioxus_state.apply_mutations(&mut rdom, mutations);
-
- let ctx = SendAnyMap::new();
- rdom.update_state(ctx);
-
- for i in 0..10usize {
- dom.wait_for_work().await;
-
- let mutations = dom.render_immediate();
- dioxus_state.apply_mutations(&mut rdom, mutations);
-
- let ctx = SendAnyMap::new();
- rdom.update_state(ctx);
-
- // render...
- rdom.traverse_depth_first_advanced(true, |node| {
- let node_type = &*node.node_type();
- let height = node.height() as usize;
- let indent = " ".repeat(height);
- let color = *node.get::().unwrap();
- let size = *node.get::().unwrap();
- let id = node.id();
- println!("{indent}{id:?} {color:?} {size:?} {node_type:?}");
- if let NodeType::Element(el) = node_type {
- match el.tag.as_str() {
- // the color should bubble up from customelementslot
- "testing132" | "customelementslot" => {
- assert_eq!(color.color, 1);
- }
- // the color of the light dom should not effect the color of the shadow dom, so the color of divs in the shadow dom should be 0
- "div" => {
- assert_eq!(color.color, 0);
- }
- _ => {}
- }
- if el.tag != "Root" {
- assert_eq!(size.size, (i + 2).saturating_sub(height));
- }
- }
- });
- }
- });
-}
-
-#[test]
-#[should_panic]
-fn slotless_custom_element_cant_have_children() {
- fn app() -> Element {
- rsx! {
- customelementnoslot {
- testing132 {}
- }
- }
- }
-
- let rt = tokio::runtime::Builder::new_current_thread()
- .enable_time()
- .build()
- .unwrap();
-
- rt.block_on(async {
- let mut rdom = RealDom::new([LayoutState::to_type_erased(), ColorState::to_type_erased()]);
- rdom.register_custom_element::();
- let mut dioxus_state = DioxusState::create(&mut rdom);
- let mut dom = VirtualDom::new(app);
-
- let mutations = dom.rebuild();
- dioxus_state.apply_mutations(&mut rdom, mutations);
-
- let ctx = SendAnyMap::new();
- rdom.update_state(ctx);
- });
-}
-
-#[test]
-fn slotless_custom_element() {
- fn app() -> Element {
- rsx! {
- customelementnoslot {
- }
- }
- }
-
- let rt = tokio::runtime::Builder::new_current_thread()
- .enable_time()
- .build()
- .unwrap();
-
- rt.block_on(async {
- let mut rdom = RealDom::new([LayoutState::to_type_erased(), ColorState::to_type_erased()]);
- rdom.register_custom_element::();
- let mut dioxus_state = DioxusState::create(&mut rdom);
- let mut dom = VirtualDom::new(app);
-
- let mutations = dom.rebuild();
- dioxus_state.apply_mutations(&mut rdom, mutations);
-
- let ctx = SendAnyMap::new();
- rdom.update_state(ctx);
- });
-}
diff --git a/packages/native-core/_tests/fuzzing.rs b/packages/native-core/_tests/fuzzing.rs
deleted file mode 100644
index cd8e97be8..000000000
--- a/packages/native-core/_tests/fuzzing.rs
+++ /dev/null
@@ -1,386 +0,0 @@
-use std::cell::Cell;
-
-use dioxus::prelude::Props;
-use dioxus_core::*;
-use dioxus_native_core::prelude::*;
-use dioxus_native_core_macro::partial_derive_state;
-use shipyard::Component;
-
-fn random_ns() -> Option<&'static str> {
- let namespace = rand::random::() % 2;
- match namespace {
- 0 => None,
- 1 => Some(Box::leak(
- format!("ns{}", rand::random::()).into_boxed_str(),
- )),
- _ => unreachable!(),
- }
-}
-
-fn create_random_attribute(attr_idx: &mut usize) -> TemplateAttribute<'static> {
- match rand::random::() % 2 {
- 0 => TemplateAttribute::Static {
- name: Box::leak(format!("attr{}", rand::random::()).into_boxed_str()),
- value: Box::leak(format!("value{}", rand::random::()).into_boxed_str()),
- namespace: random_ns(),
- },
- 1 => TemplateAttribute::Dynamic {
- id: {
- let old_idx = *attr_idx;
- *attr_idx += 1;
- old_idx
- },
- },
- _ => unreachable!(),
- }
-}
-
-fn create_random_template_node(
- dynamic_node_types: &mut Vec,
- template_idx: &mut usize,
- attr_idx: &mut usize,
- depth: usize,
-) -> TemplateNode {
- match rand::random::() % 4 {
- 0 => {
- let attrs = {
- let attrs: Vec<_> = (0..(rand::random::() % 10))
- .map(|_| create_random_attribute(attr_idx))
- .collect();
- Box::leak(attrs.into_boxed_slice())
- };
- TemplateNode::Element {
- tag: Box::leak(format!("tag{}", rand::random::()).into_boxed_str()),
- namespace: random_ns(),
- attrs,
- children: {
- if depth > 4 {
- &[]
- } else {
- let children: Vec<_> = (0..(rand::random::() % 3))
- .map(|_| {
- create_random_template_node(
- dynamic_node_types,
- template_idx,
- attr_idx,
- depth + 1,
- )
- })
- .collect();
- Box::leak(children.into_boxed_slice())
- }
- },
- }
- }
- 1 => TemplateNode::Text {
- text: Box::leak(format!("{}", rand::random::()).into_boxed_str()),
- },
- 2 => TemplateNode::DynamicText {
- id: {
- let old_idx = *template_idx;
- *template_idx += 1;
- dynamic_node_types.push(DynamicNodeType::Text);
- old_idx
- },
- },
- 3 => TemplateNode::Dynamic {
- id: {
- let old_idx = *template_idx;
- *template_idx += 1;
- dynamic_node_types.push(DynamicNodeType::Other);
- old_idx
- },
- },
- _ => unreachable!(),
- }
-}
-
-fn generate_paths(
- node: &TemplateNode,
- current_path: &[u8],
- node_paths: &mut Vec>,
- attr_paths: &mut Vec>,
-) {
- match node {
- TemplateNode::Element {
- children, attrs, ..
- } => {
- for attr in *attrs {
- match attr {
- TemplateAttribute::Static { .. } => {}
- TemplateAttribute::Dynamic { .. } => {
- attr_paths.push(current_path.to_vec());
- }
- }
- }
- for (i, child) in children.iter().enumerate() {
- let mut current_path = current_path.to_vec();
- current_path.push(i as u8);
- generate_paths(child, ¤t_path, node_paths, attr_paths);
- }
- }
- TemplateNode::Text { .. } => {}
- TemplateNode::DynamicText { .. } => {
- node_paths.push(current_path.to_vec());
- }
- TemplateNode::Dynamic { .. } => {
- node_paths.push(current_path.to_vec());
- }
- }
-}
-
-enum DynamicNodeType {
- Text,
- Other,
-}
-
-fn create_random_template(name: &'static str) -> (Template, Vec) {
- let mut dynamic_node_type = Vec::new();
- let mut template_idx = 0;
- let mut attr_idx = 0;
- let roots = (0..(1 + rand::random::() % 5))
- .map(|_| {
- create_random_template_node(&mut dynamic_node_type, &mut template_idx, &mut attr_idx, 0)
- })
- .collect::>();
- assert!(!roots.is_empty());
- let roots = Box::leak(roots.into_boxed_slice());
- let mut node_paths = Vec::new();
- let mut attr_paths = Vec::new();
- for (i, root) in roots.iter().enumerate() {
- generate_paths(root, &[i as u8], &mut node_paths, &mut attr_paths);
- }
- let node_paths = Box::leak(
- node_paths
- .into_iter()
- .map(|v| &*Box::leak(v.into_boxed_slice()))
- .collect::>()
- .into_boxed_slice(),
- );
- let attr_paths = Box::leak(
- attr_paths
- .into_iter()
- .map(|v| &*Box::leak(v.into_boxed_slice()))
- .collect::>()
- .into_boxed_slice(),
- );
- (
- Template {
- name,
- roots,
- node_paths,
- attr_paths,
- },
- dynamic_node_type,
- )
-}
-
-fn create_random_dynamic_node(depth: usize) -> DynamicNode {
- let range = if depth > 3 { 1 } else { 3 };
- match rand::random::() % range {
- 0 => DynamicNode::Placeholder(Default::default()),
- 1 => cx.make_node((0..(rand::random::() % 5)).map(|_| {
- cx.vnode(
- None.into(),
- Default::default(),
- Cell::new(Template {
- name: concat!(file!(), ":", line!(), ":", column!(), ":0"),
- roots: &[TemplateNode::Dynamic { id: 0 }],
- node_paths: &[&[0]],
- attr_paths: &[],
- }),
- dioxus::dioxus_core::exports::bumpalo::collections::Vec::new_in(cx.bump()).into(),
- cx.bump().alloc([cx.component(
- create_random_element,
- DepthProps { depth, root: false },
- "create_random_element",
- )]),
- &[],
- )
- })),
- 2 => cx.component(
- create_random_element,
- DepthProps { depth, root: false },
- "create_random_element",
- ),
- _ => unreachable!(),
- }
-}
-
-fn create_random_dynamic_attr() -> Attribute {
- let value = match rand::random::() % 6 {
- 0 => AttributeValue::Text(Box::leak(
- format!("{}", rand::random::()).into_boxed_str(),
- )),
- 1 => AttributeValue::Float(rand::random()),
- 2 => AttributeValue::Int(rand::random()),
- 3 => AttributeValue::Bool(rand::random()),
- 4 => cx.any_value(rand::random::()),
- 5 => AttributeValue::None,
- _ => unreachable!(),
- };
-
- Attribute::new(
- Box::leak(format!("attr{}", rand::random::()).into_boxed_str()),
- value,
- random_ns(),
- rand::random(),
- )
-}
-
-static mut TEMPLATE_COUNT: usize = 0;
-
-#[derive(PartialEq, Props, Component)]
-struct DepthProps {
- depth: usize,
- root: bool,
-}
-
-fn create_random_element(cx: Scope) -> Element {
- cx.needs_update();
- let range = if cx.props.root { 2 } else { 3 };
- let node = match rand::random::() % range {
- 0 | 1 => {
- let (template, dynamic_node_types) = create_random_template(Box::leak(
- format!(
- "{}{}",
- concat!(file!(), ":", line!(), ":", column!(), ":"),
- {
- unsafe {
- let old = TEMPLATE_COUNT;
- TEMPLATE_COUNT += 1;
- old
- }
- }
- )
- .into_boxed_str(),
- ));
- println!("{template:#?}");
- let node = cx.vnode(
- None.into(),
- None,
- Cell::new(template),
- dioxus::dioxus_core::exports::bumpalo::collections::Vec::new_in(cx.bump()).into(),
- {
- let dynamic_nodes: Vec<_> = dynamic_node_types
- .iter()
- .map(|ty| match ty {
- DynamicNodeType::Text => DynamicNode::Text(VText::new(Box::leak(
- format!("{}", rand::random::()).into_boxed_str(),
- ))),
- DynamicNodeType::Other => {
- create_random_dynamic_node(cx.props.depth + 1)
- }
- })
- .collect();
- cx.bump().alloc(dynamic_nodes)
- },
- cx.bump()
- .alloc(
- (0..template.attr_paths.len())
- .map(|_| create_random_dynamic_attr(cx).into())
- .collect::>(),
- )
- .as_slice(),
- );
- Some(node)
- }
- _ => None,
- };
- println!("{node:#?}");
- node
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Default, Component)]
-pub struct BlablaState {
- count: usize,
-}
-
-#[partial_derive_state]
-impl State for BlablaState {
- type ParentDependencies = (Self,);
- type ChildDependencies = ();
- type NodeDependencies = ();
-
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new()
- .with_attrs(AttributeMaskBuilder::Some(&["blabla"]))
- .with_element();
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- if let Some((parent,)) = parent {
- if parent.count != 0 {
- self.count += 1;
- }
- }
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
-}
-
-// test for panics when creating random nodes and templates
-#[test]
-fn create() {
- for _ in 0..100 {
- let mut vdom = VirtualDom::new_with_props(
- create_random_element,
- DepthProps {
- depth: 0,
- root: true,
- },
- );
- let mutations = vdom.rebuild();
- let mut rdom: RealDom = RealDom::new([BlablaState::to_type_erased()]);
- let mut dioxus_state = DioxusState::create(&mut rdom);
- dioxus_state.apply_mutations(&mut rdom, mutations);
-
- let ctx = SendAnyMap::new();
- rdom.update_state(ctx);
- }
-}
-
-// test for panics when diffing random nodes
-// This test will change the template every render which is not very realistic, but it helps stress the system
-#[test]
-fn diff() {
- for _ in 0..10 {
- let mut vdom = VirtualDom::new_with_props(
- create_random_element,
- DepthProps {
- depth: 0,
- root: true,
- },
- );
- let mutations = vdom.rebuild();
- let mut rdom: RealDom = RealDom::new([BlablaState::to_type_erased()]);
- let mut dioxus_state = DioxusState::create(&mut rdom);
- dioxus_state.apply_mutations(&mut rdom, mutations);
-
- let ctx = SendAnyMap::new();
- rdom.update_state(ctx);
- for _ in 0..10 {
- let mutations = vdom.render_immediate();
- dioxus_state.apply_mutations(&mut rdom, mutations);
-
- let ctx = SendAnyMap::new();
- rdom.update_state(ctx);
- }
- }
-}
diff --git a/packages/native-core/_tests/miri_native.rs b/packages/native-core/_tests/miri_native.rs
deleted file mode 100644
index 5a8abd44c..000000000
--- a/packages/native-core/_tests/miri_native.rs
+++ /dev/null
@@ -1,154 +0,0 @@
-use dioxus::prelude::*;
-use dioxus_native_core::prelude::*;
-use dioxus_native_core_macro::partial_derive_state;
-use shipyard::Component;
-use tokio::time::sleep;
-
-#[derive(Debug, Clone, PartialEq, Eq, Default, Component)]
-pub struct BlablaState {
- count: usize,
-}
-
-#[partial_derive_state]
-impl State for BlablaState {
- type ParentDependencies = (Self,);
- type ChildDependencies = ();
- type NodeDependencies = ();
-
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new()
- .with_attrs(AttributeMaskBuilder::Some(&["blabla"]))
- .with_element();
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- if let Some((parent,)) = parent {
- if parent.count != 0 {
- self.count += 1;
- }
- }
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
-}
-
-mod dioxus_elements {
- macro_rules! builder_constructors {
- (
- $(
- $(#[$attr:meta])*
- $name:ident {
- $(
- $(#[$attr_method:meta])*
- $fil:ident: $vil:ident,
- )*
- };
- )*
- ) => {
- $(
- #[allow(non_camel_case_types)]
- $(#[$attr])*
- pub struct $name;
-
- impl $name {
- pub const TAG_NAME: &'static str = stringify!($name);
- pub const NAME_SPACE: Option<&'static str> = None;
-
- $(
- pub const $fil: (&'static str, Option<&'static str>, bool) = (stringify!($fil), None, false);
- )*
- }
-
- impl GlobalAttributes for $name {}
- )*
- }
- }
-
- pub trait GlobalAttributes {}
-
- pub trait SvgAttributes {}
-
- builder_constructors! {
- blabla {
-
- };
- }
-}
-
-#[test]
-fn native_core_is_okay() {
- use std::sync::{Arc, Mutex};
- use std::time::Duration;
-
- fn app() -> Element {
- let colors = use_signal(|| vec!["green", "blue", "red"]);
- let padding = use_signal(|| 10);
-
- use_effect(colors, |colors| async move {
- sleep(Duration::from_millis(1000)).await;
- colors.with_mut(|colors| colors.reverse());
- });
-
- use_effect(padding, |padding| async move {
- sleep(Duration::from_millis(10)).await;
- padding.with_mut(|padding| {
- if *padding < 65 {
- *padding += 1;
- } else {
- *padding = 5;
- }
- });
- });
-
- let _big = colors[0];
- let _mid = colors[1];
- let _small = colors[2];
-
- rsx! {
- blabla {}
- }
- }
-
- let rt = tokio::runtime::Builder::new_current_thread()
- .enable_time()
- .build()
- .unwrap();
-
- rt.block_on(async {
- let rdom = Arc::new(Mutex::new(RealDom::new([BlablaState::to_type_erased()])));
- let mut dioxus_state = DioxusState::create(&mut rdom.lock().unwrap());
- let mut dom = VirtualDom::new(app);
-
- let mutations = dom.rebuild();
- dioxus_state.apply_mutations(&mut rdom.lock().unwrap(), mutations);
-
- let ctx = SendAnyMap::new();
- rdom.lock().unwrap().update_state(ctx);
-
- for _ in 0..10 {
- dom.wait_for_work().await;
-
- let mutations = dom.render_immediate();
- dioxus_state.apply_mutations(&mut rdom.lock().unwrap(), mutations);
-
- let ctx = SendAnyMap::new();
- rdom.lock().unwrap().update_state(ctx);
- }
- });
-}
diff --git a/packages/native-core/_tests/passes.rs b/packages/native-core/_tests/passes.rs
deleted file mode 100644
index 368333fb5..000000000
--- a/packages/native-core/_tests/passes.rs
+++ /dev/null
@@ -1,440 +0,0 @@
-use dioxus_native_core::node::NodeType;
-use dioxus_native_core::prelude::*;
-use dioxus_native_core_macro::partial_derive_state;
-use rustc_hash::{FxHashMap, FxHashSet};
-use shipyard::Component;
-
-fn create_blank_element() -> NodeType {
- NodeType::Element(ElementNode {
- tag: "div".to_owned(),
- namespace: None,
- attributes: FxHashMap::default(),
- listeners: FxHashSet::default(),
- })
-}
-
-#[test]
-fn node_pass() {
- #[derive(Debug, Default, Clone, PartialEq, Component)]
- struct Number(i32);
-
- #[partial_derive_state]
- impl State for Number {
- type ChildDependencies = ();
- type NodeDependencies = ();
- type ParentDependencies = ();
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new();
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- _: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- self.0 += 1;
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
- }
-
- let mut tree: RealDom = RealDom::new([Number::to_type_erased()]);
- tree.update_state(SendAnyMap::new());
-
- assert_eq!(
- tree.get(tree.root_id()).unwrap().get().as_deref(),
- Some(&Number(1))
- );
-
- // mark the node as dirty
- tree.get_mut(tree.root_id()).unwrap().get_mut::();
-
- tree.update_state(SendAnyMap::new());
- assert_eq!(
- tree.get(tree.root_id()).unwrap().get().as_deref(),
- Some(&Number(2))
- );
-}
-
-#[test]
-fn dependant_node_pass() {
- #[derive(Debug, Default, Clone, PartialEq, Component)]
- struct AddNumber(i32);
-
- #[partial_derive_state]
- impl State for AddNumber {
- type ChildDependencies = ();
- type NodeDependencies = (SubtractNumber,);
- type ParentDependencies = ();
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new();
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- _: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- self.0 += 1;
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
- }
-
- #[derive(Debug, Default, Clone, PartialEq, Component)]
- struct SubtractNumber(i32);
-
- #[partial_derive_state]
- impl State for SubtractNumber {
- type ChildDependencies = ();
- type NodeDependencies = ();
- type ParentDependencies = ();
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new();
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- _: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- self.0 -= 1;
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
- }
-
- let mut tree: RealDom = RealDom::new([
- AddNumber::to_type_erased(),
- SubtractNumber::to_type_erased(),
- ]);
- tree.update_state(SendAnyMap::new());
-
- let root = tree.get(tree.root_id()).unwrap();
- assert_eq!(root.get().as_deref(), Some(&AddNumber(1)));
- assert_eq!(root.get().as_deref(), Some(&SubtractNumber(-1)));
-
- // mark the subtract state as dirty, it should update the add state
- tree.get_mut(tree.root_id())
- .unwrap()
- .get_mut::();
-
- tree.update_state(SendAnyMap::new());
- let root = tree.get(tree.root_id()).unwrap();
- assert_eq!(root.get().as_deref(), Some(&AddNumber(2)));
- assert_eq!(root.get().as_deref(), Some(&SubtractNumber(-2)));
-
- // mark the add state as dirty, it should ~not~ update the subtract state
- tree.get_mut(tree.root_id()).unwrap().get_mut::();
-
- tree.update_state(SendAnyMap::new());
- let root = tree.get(tree.root_id()).unwrap();
- assert_eq!(root.get().as_deref(), Some(&AddNumber(3)));
- assert_eq!(root.get().as_deref(), Some(&SubtractNumber(-2)));
-}
-
-#[test]
-fn independant_node_pass() {
- #[derive(Debug, Default, Clone, PartialEq, Component)]
- struct AddNumber(i32);
-
- #[partial_derive_state]
- impl State for AddNumber {
- type ChildDependencies = ();
- type NodeDependencies = ();
- type ParentDependencies = ();
-
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new();
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- _: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- self.0 += 1;
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
- }
-
- #[derive(Debug, Default, Clone, PartialEq, Component)]
- struct SubtractNumber(i32);
-
- #[partial_derive_state]
- impl State for SubtractNumber {
- type ChildDependencies = ();
- type NodeDependencies = ();
- type ParentDependencies = ();
-
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new();
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- _: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- self.0 -= 1;
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
- }
-
- let mut tree: RealDom = RealDom::new([
- AddNumber::to_type_erased(),
- SubtractNumber::to_type_erased(),
- ]);
- tree.update_state(SendAnyMap::new());
-
- let root = tree.get(tree.root_id()).unwrap();
- assert_eq!(root.get().as_deref(), Some(&AddNumber(1)));
- assert_eq!(root.get().as_deref(), Some(&SubtractNumber(-1)));
-
- // mark the subtract state as dirty, it should ~not~ update the add state
- tree.get_mut(tree.root_id())
- .unwrap()
- .get_mut::();
-
- tree.update_state(SendAnyMap::new());
-
- let root = tree.get(tree.root_id()).unwrap();
- assert_eq!(root.get().as_deref(), Some(&AddNumber(1)));
- assert_eq!(root.get().as_deref(), Some(&SubtractNumber(-2)));
-
- // mark the add state as dirty, it should ~not~ update the subtract state
- tree.get_mut(tree.root_id()).unwrap().get_mut::();
-
- tree.update_state(SendAnyMap::new());
-
- let root = tree.get(tree.root_id()).unwrap();
- assert_eq!(root.get().as_deref(), Some(&AddNumber(2)));
- assert_eq!(root.get().as_deref(), Some(&SubtractNumber(-2)));
-}
-
-#[test]
-fn down_pass() {
- #[derive(Debug, Clone, PartialEq, Component)]
- struct AddNumber(i32);
-
- impl Default for AddNumber {
- fn default() -> Self {
- Self(1)
- }
- }
-
- #[partial_derive_state]
- impl State for AddNumber {
- type ChildDependencies = ();
- type NodeDependencies = ();
- type ParentDependencies = (AddNumber,);
-
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new();
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- _: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- if let Some((parent,)) = parent {
- self.0 += parent.0;
- }
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self::default();
- myself.update(node_view, node, parent, children, context);
- myself
- }
- }
-
- let mut tree: RealDom = RealDom::new([AddNumber::to_type_erased()]);
- let grandchild1 = tree.create_node(create_blank_element());
- let grandchild1 = grandchild1.id();
- let mut child1 = tree.create_node(create_blank_element());
- child1.add_child(grandchild1);
- let child1 = child1.id();
- let grandchild2 = tree.create_node(create_blank_element());
- let grandchild2 = grandchild2.id();
- let mut child2 = tree.create_node(create_blank_element());
- child2.add_child(grandchild2);
- let child2 = child2.id();
- let mut parent = tree.get_mut(tree.root_id()).unwrap();
- parent.add_child(child1);
- parent.add_child(child2);
-
- tree.update_state(SendAnyMap::new());
-
- let root = tree.get(tree.root_id()).unwrap();
- dbg!(root.id());
- assert_eq!(root.get().as_deref(), Some(&AddNumber(1)));
-
- let child1 = tree.get(child1).unwrap();
- dbg!(child1.id());
- assert_eq!(child1.get().as_deref(), Some(&AddNumber(2)));
-
- let grandchild1 = tree.get(grandchild1).unwrap();
- assert_eq!(grandchild1.get().as_deref(), Some(&AddNumber(3)));
-
- let child2 = tree.get(child2).unwrap();
- assert_eq!(child2.get().as_deref(), Some(&AddNumber(2)));
-
- let grandchild2 = tree.get(grandchild2).unwrap();
- assert_eq!(grandchild2.get().as_deref(), Some(&AddNumber(3)));
-}
-
-#[test]
-fn up_pass() {
- // Tree before:
- // 1=\
- // 1=\
- // 1
- // 1=\
- // 1
- // Tree after:
- // 4=\
- // 2=\
- // 1
- // 2=\
- // 1
-
- #[derive(Debug, Clone, PartialEq, Component)]
- struct AddNumber(i32);
-
- #[partial_derive_state]
- impl State for AddNumber {
- type ChildDependencies = (AddNumber,);
- type NodeDependencies = ();
- type ParentDependencies = ();
-
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new();
-
- fn update<'a>(
- &mut self,
- _: NodeView,
- _: ::ElementBorrowed<'a>,
- _: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- self.0 += children.iter().map(|(i,)| i.0).sum::();
- true
- }
-
- fn create<'a>(
- node_view: NodeView<()>,
- node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> Self {
- let mut myself = Self(1);
- myself.update(node_view, node, parent, children, context);
- myself
- }
- }
-
- let mut tree: RealDom = RealDom::new([AddNumber::to_type_erased()]);
- let grandchild1 = tree.create_node(create_blank_element());
- let grandchild1 = grandchild1.id();
- let mut child1 = tree.create_node(create_blank_element());
- child1.add_child(grandchild1);
- let child1 = child1.id();
- let grandchild2 = tree.create_node(create_blank_element());
- let grandchild2 = grandchild2.id();
- let mut child2 = tree.create_node(create_blank_element());
- child2.add_child(grandchild2);
- let child2 = child2.id();
- let mut parent = tree.get_mut(tree.root_id()).unwrap();
- parent.add_child(child1);
- parent.add_child(child2);
-
- tree.update_state(SendAnyMap::new());
-
- let root = tree.get(tree.root_id()).unwrap();
- assert_eq!(root.get().as_deref(), Some(&AddNumber(5)));
-
- let child1 = tree.get(child1).unwrap();
- assert_eq!(child1.get().as_deref(), Some(&AddNumber(2)));
-
- let grandchild1 = tree.get(grandchild1).unwrap();
- assert_eq!(grandchild1.get().as_deref(), Some(&AddNumber(1)));
-
- let child2 = tree.get(child2).unwrap();
- assert_eq!(child2.get().as_deref(), Some(&AddNumber(2)));
-
- let grandchild2 = tree.get(grandchild2).unwrap();
- assert_eq!(grandchild2.get().as_deref(), Some(&AddNumber(1)));
-}
diff --git a/packages/native-core/examples/custom_attr.rs b/packages/native-core/examples/custom_attr.rs
deleted file mode 100644
index e7bbb36ea..000000000
--- a/packages/native-core/examples/custom_attr.rs
+++ /dev/null
@@ -1,231 +0,0 @@
-use dioxus_native_core::exports::shipyard::Component;
-use dioxus_native_core::node_ref::*;
-use dioxus_native_core::prelude::*;
-use dioxus_native_core::real_dom::NodeTypeMut;
-use dioxus_native_core_macro::partial_derive_state;
-
-struct FontSize(f64);
-
-// All states need to derive Component
-#[derive(Default, Debug, Copy, Clone, Component)]
-struct Size(f64, f64);
-
-#[derive(Default, Debug, Copy, Clone, Component)]
-struct X;
-
-impl FromAnyValue for X {
- fn from_any_value(_: &dyn std::any::Any) -> Self {
- X
- }
-}
-
-/// Derive some of the boilerplate for the State implementation
-#[partial_derive_state]
-impl State for Size {
- type ParentDependencies = ();
-
- // The size of the current node depends on the size of its children
- type ChildDependencies = (Self,);
-
- type NodeDependencies = ();
-
- // Size only cares about the width, height, and text parts of the current node
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new()
- // Get access to the width and height attributes
- .with_attrs(AttributeMaskBuilder::Some(&["width", "height"]))
- // Get access to the text of the node
- .with_text();
-
- fn update<'a>(
- &mut self,
- node_view: NodeView,
- _node: ::ElementBorrowed<'a>,
- _parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> bool {
- let font_size = context.get::().unwrap().0;
- let mut width;
- let mut height;
- if let Some(text) = node_view.text() {
- // if the node has text, use the text to size our object
- width = text.len() as f64 * font_size;
- height = font_size;
- } else {
- // otherwise, the size is the maximum size of the children
- width = children
- .iter()
- .map(|(item,)| item.0)
- .reduce(|accum, item| if accum >= item { accum } else { item })
- .unwrap_or(0.0);
-
- height = children
- .iter()
- .map(|(item,)| item.1)
- .reduce(|accum, item| if accum >= item { accum } else { item })
- .unwrap_or(0.0);
- }
- // if the node contains a width or height attribute it overrides the other size
- for a in node_view.attributes().into_iter().flatten() {
- match &*a.attribute.name {
- "width" => width = a.value.as_float().unwrap(),
- "height" => height = a.value.as_float().unwrap(),
- // because Size only depends on the width and height, no other attributes will be passed to the member
- _ => panic!(),
- }
- }
- // to determine what other parts of the dom need to be updated we return a boolean that marks if this member changed
- let changed = (width != self.0) || (height != self.1);
- *self = Self(width, height);
- changed
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Default, Component)]
-struct TextColor {
- r: u8,
- g: u8,
- b: u8,
-}
-
-#[partial_derive_state]
-impl State for TextColor {
- // TextColor depends on the TextColor part of the parent
- type ParentDependencies = (Self,);
-
- type ChildDependencies = ();
-
- type NodeDependencies = ();
-
- // TextColor only cares about the color attribute of the current node
- const NODE_MASK: NodeMaskBuilder<'static> =
- // Get access to the color attribute
- NodeMaskBuilder::new().with_attrs(AttributeMaskBuilder::Some(&["color"]));
-
- fn update<'a>(
- &mut self,
- node_view: NodeView,
- _node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- _children: Vec<::ElementBorrowed<'a>>,
- _context: &SendAnyMap,
- ) -> bool {
- // TextColor only depends on the color tag, so getting the first tag is equivilent to looking through all tags
- let new = match node_view
- .attributes()
- .and_then(|mut attrs| attrs.next())
- .and_then(|attr| attr.value.as_text())
- {
- // if there is a color tag, translate it
- Some("red") => TextColor { r: 255, g: 0, b: 0 },
- Some("green") => TextColor { r: 0, g: 255, b: 0 },
- Some("blue") => TextColor { r: 0, g: 0, b: 255 },
- Some(color) => panic!("unknown color {color}"),
- // otherwise check if the node has a parent and inherit that color
- None => match parent {
- Some((parent,)) => *parent,
- None => Self::default(),
- },
- };
- // check if the member has changed
- let changed = new != *self;
- *self = new;
- changed
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Default, Component)]
-struct Border(bool);
-
-#[partial_derive_state]
-impl State for Border {
- // TextColor depends on the TextColor part of the parent
- type ParentDependencies = (Self,);
-
- type ChildDependencies = ();
-
- type NodeDependencies = ();
-
- // Border does not depended on any other member in the current node
- const NODE_MASK: NodeMaskBuilder<'static> =
- // Get access to the border attribute
- NodeMaskBuilder::new().with_attrs(AttributeMaskBuilder::Some(&["border"]));
-
- fn update<'a>(
- &mut self,
- node_view: NodeView,
- _node: ::ElementBorrowed<'a>,
- _parent: Option<::ElementBorrowed<'a>>,
- _children: Vec<::ElementBorrowed<'a>>,
- _context: &SendAnyMap,
- ) -> bool {
- // check if the node contians a border attribute
- let new = Self(
- node_view
- .attributes()
- .and_then(|mut attrs| attrs.next().map(|a| a.attribute.name == "border"))
- .is_some(),
- );
- // check if the member has changed
- let changed = new != *self;
- *self = new;
- changed
- }
-}
-
-fn main() -> Result<(), Box> {
- let mut rdom: RealDom = RealDom::new([
- Border::to_type_erased(),
- TextColor::to_type_erased(),
- Size::to_type_erased(),
- ]);
-
- let mut count = 0;
-
- // intial render
- let text_id = rdom.create_node(format!("Count: {count}")).id();
- let mut root = rdom.get_mut(rdom.root_id()).unwrap();
- // set the color to red
- if let NodeTypeMut::Element(mut element) = root.node_type_mut() {
- element.set_attribute(("color", "style"), "red".to_string());
- }
- root.add_child(text_id);
-
- let mut ctx = SendAnyMap::new();
- // set the font size to 3.3
- ctx.insert(FontSize(3.3));
- // update the State for nodes in the real_dom tree
- let _to_rerender = rdom.update_state(ctx);
-
- // we need to run the vdom in a async runtime
- tokio::runtime::Builder::new_current_thread()
- .enable_all()
- .build()?
- .block_on(async {
- loop {
- // update the count
- count += 1;
- let mut text = rdom.get_mut(text_id).unwrap();
- if let NodeTypeMut::Text(mut text) = text.node_type_mut() {
- *text = format!("Count: {count}");
- }
-
- let mut ctx = SendAnyMap::new();
- ctx.insert(FontSize(3.3));
- let _to_rerender = rdom.update_state(ctx);
-
- // render...
- rdom.traverse_depth_first_advanced(true, |node| {
- let indent = " ".repeat(node.height() as usize);
- let color = *node.get::().unwrap();
- let size = *node.get::().unwrap();
- let border = *node.get::().unwrap();
- let id = node.id();
- println!("{indent}{id:?} {color:?} {size:?} {border:?}");
- });
-
- // wait 1 second
- tokio::time::sleep(std::time::Duration::from_secs(1)).await;
- }
- })
-}
diff --git a/packages/native-core/examples/font_size.rs b/packages/native-core/examples/font_size.rs
deleted file mode 100644
index 40261baa2..000000000
--- a/packages/native-core/examples/font_size.rs
+++ /dev/null
@@ -1,175 +0,0 @@
-use dioxus_native_core::exports::shipyard::Component;
-use dioxus_native_core::node_ref::*;
-use dioxus_native_core::prelude::*;
-use dioxus_native_core::real_dom::NodeTypeMut;
-use dioxus_native_core_macro::partial_derive_state;
-
-// All states need to derive Component
-#[derive(Default, Debug, Copy, Clone, Component)]
-struct Size(f64, f64);
-
-/// Derive some of the boilerplate for the State implementation
-#[partial_derive_state]
-impl State for Size {
- type ParentDependencies = ();
-
- // The size of the current node depends on the size of its children
- type ChildDependencies = (Self,);
-
- type NodeDependencies = (FontSize,);
-
- // Size only cares about the width, height, and text parts of the current node
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new()
- // Get access to the width and height attributes
- .with_attrs(AttributeMaskBuilder::Some(&["width", "height"]))
- // Get access to the text of the node
- .with_text();
-
- fn update<'a>(
- &mut self,
- node_view: NodeView<()>,
- (font_size,): ::ElementBorrowed<'a>,
- _parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- _: &SendAnyMap,
- ) -> bool {
- let font_size = font_size.size;
- let mut width;
- let mut height;
- if let Some(text) = node_view.text() {
- // if the node has text, use the text to size our object
- width = text.len() as f64 * font_size;
- height = font_size;
- } else {
- // otherwise, the size is the maximum size of the children
- width = children
- .iter()
- .map(|(item,)| item.0)
- .reduce(|accum, item| if accum >= item { accum } else { item })
- .unwrap_or(0.0);
-
- height = children
- .iter()
- .map(|(item,)| item.1)
- .reduce(|accum, item| if accum >= item { accum } else { item })
- .unwrap_or(0.0);
- }
- // if the node contains a width or height attribute it overrides the other size
- for a in node_view.attributes().into_iter().flatten() {
- match &*a.attribute.name {
- "width" => width = a.value.as_float().unwrap(),
- "height" => height = a.value.as_float().unwrap(),
- // because Size only depends on the width and height, no other attributes will be passed to the member
- _ => panic!(),
- }
- }
- // to determine what other parts of the dom need to be updated we return a boolean that marks if this member changed
- let changed = (width != self.0) || (height != self.1);
- *self = Self(width, height);
- changed
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Component)]
-struct FontSize {
- size: f64,
-}
-
-impl Default for FontSize {
- fn default() -> Self {
- Self { size: 16.0 }
- }
-}
-
-#[partial_derive_state]
-impl State for FontSize {
- // TextColor depends on the TextColor part of the parent
- type ParentDependencies = (Self,);
-
- type ChildDependencies = ();
-
- type NodeDependencies = ();
-
- // TextColor only cares about the color attribute of the current node
- const NODE_MASK: NodeMaskBuilder<'static> =
- // Get access to the color attribute
- NodeMaskBuilder::new().with_attrs(AttributeMaskBuilder::Some(&["font-size"]));
-
- fn update<'a>(
- &mut self,
- node_view: NodeView<()>,
- _node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- _children: Vec<::ElementBorrowed<'a>>,
- _context: &SendAnyMap,
- ) -> bool {
- let mut new = None;
- for attr in node_view.attributes().into_iter().flatten() {
- if attr.attribute.name == "font-size" {
- new = Some(FontSize {
- size: attr.value.as_float().unwrap(),
- });
- }
- }
- let new = new.unwrap_or(parent.map(|(p,)| *p).unwrap_or_default());
- // check if the member has changed
- let changed = new != *self;
- *self = new;
- changed
- }
-}
-
-fn main() -> Result<(), Box> {
- let mut rdom: RealDom = RealDom::new([FontSize::to_type_erased(), Size::to_type_erased()]);
-
- let mut count = 0;
-
- // intial render
- let text_id = rdom.create_node(format!("Count: {count}")).id();
- let mut root = rdom.get_mut(rdom.root_id()).unwrap();
- // set the color to red
- if let NodeTypeMut::Element(mut element) = root.node_type_mut() {
- element.set_attribute(("color", "style"), "red".to_string());
- element.set_attribute(("font-size", "style"), 1.);
- }
- root.add_child(text_id);
-
- let ctx = SendAnyMap::new();
- // update the State for nodes in the real_dom tree
- let _to_rerender = rdom.update_state(ctx);
-
- // we need to run the vdom in a async runtime
- tokio::runtime::Builder::new_current_thread()
- .enable_all()
- .build()?
- .block_on(async {
- loop {
- // update the count and font size
- count += 1;
- let mut text = rdom.get_mut(text_id).unwrap();
- if let NodeTypeMut::Text(mut text) = text.node_type_mut() {
- *text = format!("Count: {count}");
- }
- if let NodeTypeMut::Element(mut element) =
- rdom.get_mut(rdom.root_id()).unwrap().node_type_mut()
- {
- element.set_attribute(("font-size", "style"), count as f64);
- }
-
- let ctx = SendAnyMap::new();
- let _to_rerender = rdom.update_state(ctx);
-
- // render...
- rdom.traverse_depth_first_advanced(true, |node| {
- let indent = " ".repeat(node.height() as usize);
- let font_size = *node.get::().unwrap();
- let size = *node.get::().unwrap();
- let id = node.id();
- println!("{indent}{id:?} {font_size:?} {size:?}");
- });
-
- // wait 1 second
- tokio::time::sleep(std::time::Duration::from_secs(1)).await;
- }
- })
-}
diff --git a/packages/native-core/examples/simple.rs b/packages/native-core/examples/simple.rs
deleted file mode 100644
index 276d06d08..000000000
--- a/packages/native-core/examples/simple.rs
+++ /dev/null
@@ -1,222 +0,0 @@
-use dioxus_native_core::exports::shipyard::Component;
-use dioxus_native_core::node_ref::*;
-use dioxus_native_core::prelude::*;
-use dioxus_native_core::real_dom::NodeTypeMut;
-use dioxus_native_core_macro::partial_derive_state;
-
-struct FontSize(f64);
-
-// All states need to derive Component
-#[derive(Default, Debug, Copy, Clone, Component)]
-struct Size(f64, f64);
-
-/// Derive some of the boilerplate for the State implementation
-#[partial_derive_state]
-impl State for Size {
- type ParentDependencies = ();
-
- // The size of the current node depends on the size of its children
- type ChildDependencies = (Self,);
-
- type NodeDependencies = ();
-
- // Size only cares about the width, height, and text parts of the current node
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new()
- // Get access to the width and height attributes
- .with_attrs(AttributeMaskBuilder::Some(&["width", "height"]))
- // Get access to the text of the node
- .with_text();
-
- fn update<'a>(
- &mut self,
- node_view: NodeView<()>,
- _node: ::ElementBorrowed<'a>,
- _parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> bool {
- let font_size = context.get::().unwrap().0;
- let mut width;
- let mut height;
- if let Some(text) = node_view.text() {
- // if the node has text, use the text to size our object
- width = text.len() as f64 * font_size;
- height = font_size;
- } else {
- // otherwise, the size is the maximum size of the children
- width = children
- .iter()
- .map(|(item,)| item.0)
- .reduce(|accum, item| if accum >= item { accum } else { item })
- .unwrap_or(0.0);
-
- height = children
- .iter()
- .map(|(item,)| item.1)
- .reduce(|accum, item| if accum >= item { accum } else { item })
- .unwrap_or(0.0);
- }
- // if the node contains a width or height attribute it overrides the other size
- for a in node_view.attributes().into_iter().flatten() {
- match &*a.attribute.name {
- "width" => width = a.value.as_float().unwrap(),
- "height" => height = a.value.as_float().unwrap(),
- // because Size only depends on the width and height, no other attributes will be passed to the member
- _ => panic!(),
- }
- }
- // to determine what other parts of the dom need to be updated we return a boolean that marks if this member changed
- let changed = (width != self.0) || (height != self.1);
- *self = Self(width, height);
- changed
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Default, Component)]
-struct TextColor {
- r: u8,
- g: u8,
- b: u8,
-}
-
-#[partial_derive_state]
-impl State for TextColor {
- // TextColor depends on the TextColor part of the parent
- type ParentDependencies = (Self,);
-
- type ChildDependencies = ();
-
- type NodeDependencies = ();
-
- // TextColor only cares about the color attribute of the current node
- const NODE_MASK: NodeMaskBuilder<'static> =
- // Get access to the color attribute
- NodeMaskBuilder::new().with_attrs(AttributeMaskBuilder::Some(&["color"]));
-
- fn update<'a>(
- &mut self,
- node_view: NodeView<()>,
- _node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- _children: Vec<::ElementBorrowed<'a>>,
- _context: &SendAnyMap,
- ) -> bool {
- // TextColor only depends on the color tag, so getting the first tag is equivilent to looking through all tags
- let new = match node_view
- .attributes()
- .and_then(|mut attrs| attrs.next())
- .and_then(|attr| attr.value.as_text())
- {
- // if there is a color tag, translate it
- Some("red") => TextColor { r: 255, g: 0, b: 0 },
- Some("green") => TextColor { r: 0, g: 255, b: 0 },
- Some("blue") => TextColor { r: 0, g: 0, b: 255 },
- Some(color) => panic!("unknown color {color}"),
- // otherwise check if the node has a parent and inherit that color
- None => match parent {
- Some((parent,)) => *parent,
- None => Self::default(),
- },
- };
- // check if the member has changed
- let changed = new != *self;
- *self = new;
- changed
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Default, Component)]
-struct Border(bool);
-
-#[partial_derive_state]
-impl State for Border {
- // TextColor depends on the TextColor part of the parent
- type ParentDependencies = (Self,);
-
- type ChildDependencies = ();
-
- type NodeDependencies = ();
-
- // Border does not depended on any other member in the current node
- const NODE_MASK: NodeMaskBuilder<'static> =
- // Get access to the border attribute
- NodeMaskBuilder::new().with_attrs(AttributeMaskBuilder::Some(&["border"]));
-
- fn update<'a>(
- &mut self,
- node_view: NodeView<()>,
- _node: ::ElementBorrowed<'a>,
- _parent: Option<::ElementBorrowed<'a>>,
- _children: Vec<::ElementBorrowed<'a>>,
- _context: &SendAnyMap,
- ) -> bool {
- // check if the node contians a border attribute
- let new = Self(
- node_view
- .attributes()
- .and_then(|mut attrs| attrs.next().map(|a| a.attribute.name == "border"))
- .is_some(),
- );
- // check if the member has changed
- let changed = new != *self;
- *self = new;
- changed
- }
-}
-
-fn main() -> Result<(), Box> {
- let mut rdom: RealDom = RealDom::new([
- Border::to_type_erased(),
- TextColor::to_type_erased(),
- Size::to_type_erased(),
- ]);
-
- let mut count = 0;
-
- // intial render
- let text_id = rdom.create_node(format!("Count: {count}")).id();
- let mut root = rdom.get_mut(rdom.root_id()).unwrap();
- // set the color to red
- if let NodeTypeMut::Element(mut element) = root.node_type_mut() {
- element.set_attribute(("color", "style"), "red".to_string());
- }
- root.add_child(text_id);
-
- let mut ctx = SendAnyMap::new();
- // set the font size to 3.3
- ctx.insert(FontSize(3.3));
- // update the State for nodes in the real_dom tree
- let _to_rerender = rdom.update_state(ctx);
-
- // we need to run the vdom in a async runtime
- tokio::runtime::Builder::new_current_thread()
- .enable_all()
- .build()?
- .block_on(async {
- loop {
- // update the count
- count += 1;
- let mut text = rdom.get_mut(text_id).unwrap();
- if let NodeTypeMut::Text(mut text) = text.node_type_mut() {
- *text = format!("Count: {count}");
- }
-
- let mut ctx = SendAnyMap::new();
- ctx.insert(FontSize(3.3));
- let _to_rerender = rdom.update_state(ctx);
-
- // render...
- rdom.traverse_depth_first_advanced(true, |node| {
- let indent = " ".repeat(node.height() as usize);
- let color = *node.get::().unwrap();
- let size = *node.get::().unwrap();
- let border = *node.get::().unwrap();
- let id = node.id();
- println!("{indent}{id:?} {color:?} {size:?} {border:?}");
- });
-
- // wait 1 second
- tokio::time::sleep(std::time::Duration::from_secs(1)).await;
- }
- })
-}
diff --git a/packages/native-core/examples/simple_dioxus.rs b/packages/native-core/examples/simple_dioxus.rs
deleted file mode 100644
index afb9fe487..000000000
--- a/packages/native-core/examples/simple_dioxus.rs
+++ /dev/null
@@ -1,245 +0,0 @@
-#![allow(non_snake_case)]
-use dioxus::prelude::*;
-use dioxus_native_core::exports::shipyard::Component;
-use dioxus_native_core::node_ref::*;
-use dioxus_native_core::prelude::*;
-use dioxus_native_core_macro::partial_derive_state;
-
-struct FontSize(f64);
-
-// All states need to derive Component
-#[derive(Default, Debug, Copy, Clone, Component)]
-struct Size(f64, f64);
-
-/// Derive some of the boilerplate for the State implementation
-#[partial_derive_state]
-impl State for Size {
- type ParentDependencies = ();
-
- // The size of the current node depends on the size of its children
- type ChildDependencies = (Self,);
-
- type NodeDependencies = ();
-
- // Size only cares about the width, height, and text parts of the current node
- const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new()
- // Get access to the width and height attributes
- .with_attrs(AttributeMaskBuilder::Some(&["width", "height"]))
- // Get access to the text of the node
- .with_text();
-
- fn update<'a>(
- &mut self,
- node_view: NodeView<()>,
- _node: ::ElementBorrowed<'a>,
- _parent: Option<::ElementBorrowed<'a>>,
- children: Vec<::ElementBorrowed<'a>>,
- context: &SendAnyMap,
- ) -> bool {
- let font_size = context.get::().unwrap().0;
- let mut width;
- let mut height;
- if let Some(text) = node_view.text() {
- // if the node has text, use the text to size our object
- width = text.len() as f64 * font_size;
- height = font_size;
- } else {
- // otherwise, the size is the maximum size of the children
- width = children
- .iter()
- .map(|(item,)| item.0)
- .reduce(|accum, item| if accum >= item { accum } else { item })
- .unwrap_or(0.0);
-
- height = children
- .iter()
- .map(|(item,)| item.1)
- .reduce(|accum, item| if accum >= item { accum } else { item })
- .unwrap_or(0.0);
- }
- // if the node contains a width or height attribute it overrides the other size
- for a in node_view.attributes().into_iter().flatten() {
- match &*a.attribute.name {
- "width" => width = a.value.as_float().unwrap(),
- "height" => height = a.value.as_float().unwrap(),
- // because Size only depends on the width and height, no other attributes will be passed to the member
- _ => panic!(),
- }
- }
- // to determine what other parts of the dom need to be updated we return a boolean that marks if this member changed
- let changed = (width != self.0) || (height != self.1);
- *self = Self(width, height);
- changed
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Default, Component)]
-struct TextColor {
- r: u8,
- g: u8,
- b: u8,
-}
-
-#[partial_derive_state]
-impl State for TextColor {
- // TextColor depends on the TextColor part of the parent
- type ParentDependencies = (Self,);
-
- type ChildDependencies = ();
-
- type NodeDependencies = ();
-
- // TextColor only cares about the color attribute of the current node
- const NODE_MASK: NodeMaskBuilder<'static> =
- // Get access to the color attribute
- NodeMaskBuilder::new().with_attrs(AttributeMaskBuilder::Some(&["color"]));
-
- fn update<'a>(
- &mut self,
- node_view: NodeView<()>,
- _node: ::ElementBorrowed<'a>,
- parent: Option<::ElementBorrowed<'a>>,
- _children: Vec<::ElementBorrowed<'a>>,
- _context: &SendAnyMap,
- ) -> bool {
- // TextColor only depends on the color tag, so getting the first tag is equivilent to looking through all tags
- let new = match node_view
- .attributes()
- .and_then(|mut attrs| attrs.next())
- .and_then(|attr| attr.value.as_text())
- {
- // if there is a color tag, translate it
- Some("red") => TextColor { r: 255, g: 0, b: 0 },
- Some("green") => TextColor { r: 0, g: 255, b: 0 },
- Some("blue") => TextColor { r: 0, g: 0, b: 255 },
- Some(color) => panic!("unknown color {color}"),
- // otherwise check if the node has a parent and inherit that color
- None => match parent {
- Some((parent,)) => *parent,
- None => Self::default(),
- },
- };
- // check if the member has changed
- let changed = new != *self;
- *self = new;
- changed
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Default, Component)]
-struct Border(bool);
-
-#[partial_derive_state]
-impl State for Border {
- // TextColor depends on the TextColor part of the parent
- type ParentDependencies = (Self,);
-
- type ChildDependencies = ();
-
- type NodeDependencies = ();
-
- // Border does not depended on any other member in the current node
- const NODE_MASK: NodeMaskBuilder<'static> =
- // Get access to the border attribute
- NodeMaskBuilder::new().with_attrs(AttributeMaskBuilder::Some(&["border"]));
-
- fn update<'a>(
- &mut self,
- node_view: NodeView<()>,
- _node: ::ElementBorrowed<'a>,
- _parent: Option<::ElementBorrowed<'a>>,
- _children: Vec<::ElementBorrowed<'a>>,
- _context: &SendAnyMap,
- ) -> bool {
- // check if the node contians a border attribute
- let new = Self(
- node_view
- .attributes()
- .and_then(|mut attrs| attrs.next().map(|a| a.attribute.name == "border"))
- .is_some(),
- );
- // check if the member has changed
- let changed = new != *self;
- *self = new;
- changed
- }
-}
-
-fn main() -> Result<(), Box> {
- fn app() -> Element {
- let mut count = use_signal(|| 0);
-
- use_future(move || async move {
- loop {
- tokio::time::sleep(std::time::Duration::from_secs(1)).await;
- count += 1;
- }
- });
-
- rsx! {
- div { color: "red",
- "{count}",
- Comp {}
- }
- }
- }
-
- fn Comp() -> Element {
- rsx! {
- div { border: "", "hello world" }
- }
- }
-
- // create the vdom, the real_dom, and the binding layer between them
- let mut vdom = VirtualDom::new(app);
- let mut rdom: RealDom = RealDom::new([
- Border::to_type_erased(),
- TextColor::to_type_erased(),
- Size::to_type_erased(),
- ]);
- let mut dioxus_intigration_state = DioxusState::create(&mut rdom);
-
- // update the structure of the real_dom tree
- let mut writer = dioxus_intigration_state.create_mutation_writer(&mut rdom);
- vdom.rebuild(&mut writer);
-
- let mut ctx = SendAnyMap::new();
- // set the font size to 3.3
- ctx.insert(FontSize(3.3));
- // update the State for nodes in the real_dom tree
- let _to_rerender = rdom.update_state(ctx);
-
- // we need to run the vdom in a async runtime
- tokio::runtime::Builder::new_current_thread()
- .enable_all()
- .build()?
- .block_on(async {
- loop {
- // wait for the vdom to update
- vdom.wait_for_work().await;
-
- // get the mutations from the vdom
- // update the structure of the real_dom tree
- let mut writer = dioxus_intigration_state.create_mutation_writer(&mut rdom);
- vdom.rebuild(&mut writer);
-
- // update the state of the real_dom tree
- let mut ctx = SendAnyMap::new();
- // set the font size to 3.3
- ctx.insert(FontSize(3.3));
- let _to_rerender = rdom.update_state(ctx);
-
- // render...
- rdom.traverse_depth_first_advanced(true, |node| {
- let indent = " ".repeat(node.height() as usize);
- let color = *node.get::().unwrap();
- let size = *node.get::().unwrap();
- let border = *node.get::().unwrap();
- let id = node.id();
- let node = node.node_type();
- let node_type = &*node;
- println!("{indent}{id:?} {color:?} {size:?} {border:?} {node_type:?}");
- });
- }
- })
-}
diff --git a/packages/native-core/src/custom_element.rs b/packages/native-core/src/custom_element.rs
deleted file mode 100644
index 3675089f6..000000000
--- a/packages/native-core/src/custom_element.rs
+++ /dev/null
@@ -1,180 +0,0 @@
-//! A custom element is a controlled element that renders to a shadow DOM. This allows you to create elements that act like widgets without relying on a specific framework.
-//!
-//! Each custom element is registered with a element name and namespace with [`RealDom::register_custom_element`] or [`RealDom::register_custom_element_with_factory`]. Once registered, they will be created automatically when the element is added to the DOM.
-
-// Used in doc links
-#[allow(unused)]
-use crate::real_dom::RealDom;
-
-use std::sync::{Arc, RwLock};
-
-use rustc_hash::FxHashMap;
-use shipyard::Component;
-
-use crate::{
- node::{FromAnyValue, NodeType},
- node_ref::AttributeMask,
- prelude::{NodeImmutable, NodeMut},
- tree::TreeMut,
- NodeId,
-};
-
-pub(crate) struct CustomElementRegistry {
- builders: FxHashMap<(&'static str, Option<&'static str>), CustomElementBuilder>,
-}
-
-impl Default for CustomElementRegistry {
- fn default() -> Self {
- Self {
- builders: FxHashMap::default(),
- }
- }
-}
-
-impl CustomElementRegistry {
- pub fn register(&mut self)
- where
- F: CustomElementFactory,
- U: CustomElementUpdater,
- {
- self.builders.insert(
- (F::NAME, F::NAMESPACE),
- CustomElementBuilder {
- create: |node| Box::new(F::create(node)),
- },
- );
- }
-
- pub fn add_shadow_dom(&self, mut node: NodeMut) {
- let element_tag = if let NodeType::Element(el) = &*node.node_type() {
- Some((el.tag.clone(), el.namespace.clone()))
- } else {
- None
- };
- if let Some((tag, ns)) = element_tag {
- if let Some(builder) = self.builders.get(&(tag.as_str(), ns.as_deref())) {
- let boxed_custom_element = { (builder.create)(node.reborrow()) };
-
- let shadow_roots = boxed_custom_element.roots();
-
- let light_id = node.id();
- node.real_dom_mut().tree_mut().create_subtree(
- light_id,
- shadow_roots,
- boxed_custom_element.slot(),
- );
-
- let boxed_custom_element = CustomElementManager {
- inner: Arc::new(RwLock::new(boxed_custom_element)),
- };
-
- node.insert(boxed_custom_element);
- }
- }
- }
-}
-
-struct CustomElementBuilder {
- create: fn(NodeMut) -> Box>,
-}
-
-/// A controlled element that renders to a shadow DOM.
-///
-/// Register with [`RealDom::register_custom_element`]
-///
-/// This is a simplified custom element trait for elements that can create themselves. For more granular control, implement [`CustomElementFactory`] and [`CustomElementUpdater`] instead.
-pub trait CustomElement: Send + Sync + 'static {
- /// The tag of the element
- const NAME: &'static str;
-
- /// The namespace of the element
- const NAMESPACE: Option<&'static str> = None;
-
- /// Create a new element *without mounting* it.
- /// The node passed in is the light DOM node. The element should not modify the light DOM node, but it can get the [`NodeMut::real_dom_mut`] from the node to create new nodes.
- fn create(light_root: NodeMut) -> Self;
-
- /// The root node of the custom element. These roots must be not change once the element is created.
- fn roots(&self) -> Vec;
-
- /// The slot to render children of the element into. The slot must be not change once the element is created.
- fn slot(&self) -> Option {
- None
- }
-
- /// Update the custom element's shadow tree with the new attributes.
- /// Called when the attributes of the custom element are changed.
- fn attributes_changed(&mut self, light_node: NodeMut, attributes: &AttributeMask);
-}
-
-/// A factory for creating custom elements
-///
-/// Register with [`RealDom::register_custom_element_with_factory`]
-pub trait CustomElementFactory, V: FromAnyValue + Send + Sync = ()>:
- Send + Sync + 'static
-{
- /// The tag of the element
- const NAME: &'static str;
-
- /// The namespace of the element
- const NAMESPACE: Option<&'static str> = None;
-
- /// Create a new element *without mounting* it.
- /// The node passed in is the light DOM node. The element should not modify the light DOM node, but it can get the [`NodeMut::real_dom_mut`] from the node to create new nodes.
- fn create(dom: NodeMut) -> W;
-}
-
-impl, V: FromAnyValue + Send + Sync> CustomElementFactory for W {
- const NAME: &'static str = W::NAME;
-
- const NAMESPACE: Option<&'static str> = W::NAMESPACE;
-
- fn create(node: NodeMut) -> Self {
- Self::create(node)
- }
-}
-
-/// A trait for updating custom elements
-pub trait CustomElementUpdater: Send + Sync + 'static {
- /// Update the custom element's shadow tree with the new attributes.
- /// Called when the attributes of the custom element are changed.
- fn attributes_changed(&mut self, light_root: NodeMut, attributes: &AttributeMask);
-
- /// The root node of the custom element. These roots must be not change once the element is created.
- fn roots(&self) -> Vec;
-
- /// The slot to render children of the element into. The slot must be not change once the element is created.
- fn slot(&self) -> Option {
- None
- }
-}
-
-impl, V: FromAnyValue + Send + Sync> CustomElementUpdater for W {
- fn attributes_changed(&mut self, light_root: NodeMut, attributes: &AttributeMask) {
- self.attributes_changed(light_root, attributes);
- }
-
- fn roots(&self) -> Vec {
- self.roots()
- }
-
- fn slot(&self) -> Option