Kaynağa Gözat

Merge pull request #1791 from ealmloff/breaking

Remove scope, use_state, use_ref, bump allocator and make everything 'static
Jonathan Kelley 1 yıl önce
ebeveyn
işleme
4f8868d43d
100 değiştirilmiş dosya ile 2202 ekleme ve 3785 silme
  1. 12 0
      .github/free_space.sh
  2. 61 46
      .github/workflows/main.yml
  3. 4 4
      .gitignore
  4. 427 879
      Cargo.lock
  5. 57 31
      Cargo.toml
  6. 7 4
      README.md
  7. 8 7
      examples/PWA-example/src/main.rs
  8. 0 413
      examples/all_css.rs
  9. 36 55
      examples/all_events.rs
  10. 25 14
      examples/assets/calculator.css
  11. 55 0
      examples/backgrounded_futures.rs
  12. 0 73
      examples/borrowed.rs
  13. 56 57
      examples/calculator.rs
  14. 22 56
      examples/calculator_mutable.rs
  15. 0 22
      examples/callback.rs
  16. 10 8
      examples/clock.rs
  17. 32 38
      examples/compose.rs
  18. 22 17
      examples/control_focus.rs
  19. 36 19
      examples/counter.rs
  20. 77 93
      examples/crm.rs
  21. 12 8
      examples/custom_assets.rs
  22. 18 18
      examples/custom_html.rs
  23. 8 12
      examples/disabled.rs
  24. 46 55
      examples/dog_app.rs
  25. 0 36
      examples/drops.rs
  26. 7 9
      examples/dynamic_asset.rs
  27. 8 11
      examples/error_handle.rs
  28. 7 11
      examples/eval.rs
  29. 0 57
      examples/fermi.rs
  30. 14 10
      examples/file_explorer.rs
  31. 31 39
      examples/file_upload.rs
  32. 11 13
      examples/filedragdrop.rs
  33. 37 43
      examples/flat_router.rs
  34. 4 4
      examples/form.rs
  35. 0 152
      examples/framework_benchmark.rs
  36. 8 8
      examples/generic_component.rs
  37. 20 0
      examples/global.rs
  38. 0 28
      examples/heavy_compute.rs
  39. 3 3
      examples/hello_world.rs
  40. 14 13
      examples/hydration.rs
  41. 0 43
      examples/inlineprops.rs
  42. 33 39
      examples/inputs.rs
  43. 19 20
      examples/link.rs
  44. 5 5
      examples/login_form.rs
  45. 44 0
      examples/memo_chain.rs
  46. 1 1
      examples/mobile_demo/Cargo.toml
  47. 12 8
      examples/mobile_demo/src/lib.rs
  48. 14 17
      examples/multiwindow.rs
  49. 4 4
      examples/nested_listeners.rs
  50. 4 6
      examples/openid_connect_demo/src/main.rs
  51. 0 1
      examples/openid_connect_demo/src/router.rs
  52. 15 17
      examples/openid_connect_demo/src/views/header.rs
  53. 2 2
      examples/openid_connect_demo/src/views/home.rs
  54. 5 5
      examples/openid_connect_demo/src/views/login.rs
  55. 2 2
      examples/openid_connect_demo/src/views/not_found.rs
  56. 15 15
      examples/optional_props.rs
  57. 8 8
      examples/overlay.rs
  58. 14 17
      examples/query_segments.rs
  59. 0 13
      examples/query_segments_demo/Cargo.toml
  60. 25 31
      examples/read_size.rs
  61. 5 9
      examples/readme.rs
  62. 8 18
      examples/reducer.rs
  63. 32 40
      examples/router.rs
  64. 0 58
      examples/rsx_compile_fail.rs
  65. 257 263
      examples/rsx_usage.rs
  66. 9 13
      examples/scroll_to_top.rs
  67. 0 73
      examples/shared_state.rs
  68. 6 9
      examples/shortcut.rs
  69. 7 16
      examples/shorthand.rs
  70. 48 15
      examples/signals.rs
  71. 0 82
      examples/simple_desktop.rs
  72. 5 5
      examples/simple_list.rs
  73. 27 11
      examples/simple_router.rs
  74. 16 16
      examples/spread.rs
  75. 5 6
      examples/ssr.rs
  76. 36 0
      examples/stale_memo.rs
  77. 6 7
      examples/streams.rs
  78. 26 33
      examples/suspense.rs
  79. 35 88
      examples/svg.rs
  80. 0 81
      examples/svg_basic.rs
  81. 2 3
      examples/tailwind/Cargo.toml
  82. 26 32
      examples/tailwind/src/main.rs
  83. 10 16
      examples/tasks.rs
  84. 5 7
      examples/textarea.rs
  85. 111 144
      examples/todomvc.rs
  86. 7 7
      examples/video_stream.rs
  87. 4 4
      examples/web_component.rs
  88. 35 40
      examples/window_event.rs
  89. 23 33
      examples/window_focus.rs
  90. 7 7
      examples/window_zoom.rs
  91. 5 7
      examples/xss_safety.rs
  92. 1 1
      packages/autofmt/tests/samples/immediate_expr.rsx
  93. 4 4
      packages/autofmt/tests/samples/long.rsx
  94. 3 3
      packages/autofmt/tests/samples/messy_indent.rsx
  95. 2 2
      packages/autofmt/tests/samples/reallylong.rsx
  96. 2 2
      packages/autofmt/tests/samples/trailing_expr.rsx
  97. 2 2
      packages/autofmt/tests/wrong/multi-4sp.rsx
  98. 3 3
      packages/autofmt/tests/wrong/multi-4sp.wrong.rsx
  99. 2 2
      packages/autofmt/tests/wrong/multi-tab.rsx
  100. 3 3
      packages/autofmt/tests/wrong/multi-tab.wrong.rsx

+ 12 - 0
.github/free_space.sh

@@ -0,0 +1,12 @@
+df -h
+sudo rm -rf ${GITHUB_WORKSPACE}/.git
+sudo rm -rf "$AGENT_TOOLSDIRECTORY"
+sudo rm -rf /usr/share/dotnet
+sudo apt-get remove -y '^ghc-8.*'
+sudo apt-get remove -y '^dotnet-.*'
+sudo apt-get remove -y '^llvm-.*'
+sudo apt-get remove -y 'php.*'
+sudo apt-get remove -y azure-cli google-cloud-sdk hhvm google-chrome-stable firefox powershell mono-devel
+sudo apt-get autoremove -y
+sudo apt-get clean
+df -h

+ 61 - 46
.github/workflows/main.yml

@@ -13,7 +13,6 @@ on:
       - lib.rs
       - lib.rs
       - Cargo.toml
       - Cargo.toml
       - Makefile.toml
       - Makefile.toml
-      - playwright-tests/**
 
 
   pull_request:
   pull_request:
     types: [opened, synchronize, reopened, ready_for_review]
     types: [opened, synchronize, reopened, ready_for_review]
@@ -70,12 +69,13 @@ jobs:
       - uses: davidB/rust-cargo-make@v1
       - uses: davidB/rust-cargo-make@v1
       - uses: browser-actions/setup-firefox@latest
       - uses: browser-actions/setup-firefox@latest
       - uses: jetli/wasm-pack-action@v0.4.0
       - uses: jetli/wasm-pack-action@v0.4.0
-      - run: sudo rm -rf /usr/share/dotnet
-      - run: sudo rm -rf "$AGENT_TOOLSDIRECTORY"
-      - run: |
-          df -h
-          sudo rm -rf ${GITHUB_WORKSPACE}/.git
-          df -h
+      - name: Free Disk Space (Ubuntu)
+        uses: jlumbroso/free-disk-space@v1.3.1
+        with: # speed things up a bit
+          large-packages: false
+          docker-images: false
+          swap-storage: false
+
       - run: cargo make tests
       - run: cargo make tests
 
 
   fmt:
   fmt:
@@ -112,42 +112,43 @@ jobs:
           save-if: ${{ github.ref == 'refs/heads/master' }}
           save-if: ${{ github.ref == 'refs/heads/master' }}
       - run: cargo clippy --workspace --examples --tests -- -D warnings
       - run: cargo clippy --workspace --examples --tests -- -D warnings
 
 
-  miri:
-    if: github.event.pull_request.draft == false
-    name: Miri
-    runs-on: ubuntu-latest
-    env:
-      CARGO_UNSTABLE_SPARSE_REGISTRY: 'true'
-      RUSTFLAGS: -Dwarnings
-      RUST_BACKTRACE: 1
-      MIRIFLAGS: -Zmiri-tag-gc=1
-      # Change to specific Rust release to pin
-      rust_stable: stable
-      rust_nightly: nightly-2023-11-16
-      rust_clippy: 1.70.0
+  # We removed most unsafe that we can, and using nightly doubles our cache size
+  # miri:
+  #   if: github.event.pull_request.draft == false
+  #   name: Miri
+  #   runs-on: ubuntu-latest
+  #   env:
+  #     CARGO_UNSTABLE_SPARSE_REGISTRY: 'true'
+  #     RUSTFLAGS: -Dwarnings
+  #     RUST_BACKTRACE: 1
+  #     MIRIFLAGS: -Zmiri-tag-gc=1
+  #     # Change to specific Rust release to pin
+  #     rust_stable: stable
+  #     rust_nightly: nightly-2023-11-16
+  #     rust_clippy: 1.70.0
 
 
-    steps:
-      - uses: actions/checkout@v4
-      - uses: ilammy/setup-nasm@v1
-      - name: Install Rust ${{ env.rust_nightly }}
-        uses: dtolnay/rust-toolchain@master
-        with:
-          toolchain: ${{ env.rust_nightly }}
-          components: miri
-      - uses: Swatinem/rust-cache@v2
-        with:
-          cache-all-crates: "true"
-          save-if: ${{ github.ref == 'refs/heads/master' }}
-      - name: miri
-        # Many of tests in tokio/tests and doctests use #[tokio::test] or
-        # #[tokio::main] that calls epoll_create1 that Miri does not support.
-        # run: cargo miri test --features full --lib --no-fail-fast
-        run: |
-          cargo miri test --package dioxus-core -- --exact --nocapture
-          cargo miri test --package dioxus-native-core --test miri_native  -- --exact --nocapture
-        env:
-          MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-strict-provenance -Zmiri-retag-fields
-          PROPTEST_CASES: 10
+  #   steps:
+  #     - uses: actions/checkout@v4
+  #     - uses: ilammy/setup-nasm@v1
+  #     - name: Install Rust ${{ env.rust_nightly }}
+  #       uses: dtolnay/rust-toolchain@master
+  #       with:
+  #         toolchain: ${{ env.rust_nightly }}
+  #         components: miri
+  #     - uses: Swatinem/rust-cache@v2
+  #       with:
+  #         cache-all-crates: "true"
+  #         save-if: ${{ github.ref == 'refs/heads/master' }}
+  #     - name: miri
+  #       # Many of tests in tokio/tests and doctests use #[tokio::test] or
+  #       # #[tokio::main] that calls epoll_create1 that Miri does not support.
+  #       # run: cargo miri test --features full --lib --no-fail-fast
+  #       run: |
+  #         cargo miri test --package dioxus-core -- --exact --nocapture
+  #         cargo miri test --package dioxus-native-core --test miri_native  -- --exact --nocapture
+  #       env:
+  #         MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-strict-provenance -Zmiri-retag-fields
+  #         PROPTEST_CASES: 10
 
 
   playwright:
   playwright:
     if: github.event.pull_request.draft == false
     if: github.event.pull_request.draft == false
@@ -160,6 +161,12 @@ jobs:
       - uses: actions/setup-node@v4
       - uses: actions/setup-node@v4
         with:
         with:
           node-version: 16
           node-version: 16
+      - name: Free Disk Space (Ubuntu)
+        uses: jlumbroso/free-disk-space@v1.3.1
+        with: # speed things up a bit
+          large-packages: false
+          docker-images: false
+          swap-storage: false
       - name: Install Rust
       - name: Install Rust
         uses: dtolnay/rust-toolchain@master
         uses: dtolnay/rust-toolchain@master
         with:
         with:
@@ -172,19 +179,19 @@ jobs:
 
 
       - name: Install dependencies
       - name: Install dependencies
         run: npm ci
         run: npm ci
-        working-directory: ./playwright-tests
+        working-directory: ./packages/playwright-tests
 
 
       - name: Install Playwright
       - name: Install Playwright
         run: npm install -D @playwright/test
         run: npm install -D @playwright/test
-        working-directory: ./playwright-tests
+        working-directory: ./packages/playwright-tests
 
 
       - name: Install Playwright Browsers
       - name: Install Playwright Browsers
         run: npx playwright install --with-deps
         run: npx playwright install --with-deps
-        working-directory: ./playwright-tests
+        working-directory: ./packages/playwright-tests
 
 
       - name: Run Playwright tests
       - name: Run Playwright tests
         run: npx playwright test
         run: npx playwright test
-        working-directory: ./playwright-tests
+        working-directory: ./packages/playwright-tests
 
 
       - uses: actions/upload-artifact@v4
       - uses: actions/upload-artifact@v4
         if: always()
         if: always()
@@ -250,6 +257,14 @@ jobs:
 
 
         uses: taiki-e/install-action@cross
         uses: taiki-e/install-action@cross
 
 
+      - name: Free Disk Space (Ubuntu)
+        if: ${{ matrix.platform.os == 'ubuntu-latest' }}
+        uses: jlumbroso/free-disk-space@v1.3.1
+        with: # speed things up a bit
+          large-packages: false
+          docker-images: false
+          swap-storage: false
+
       - uses: Swatinem/rust-cache@v2
       - uses: Swatinem/rust-cache@v2
         with:
         with:
           key: "${{ matrix.platform.target }}"
           key: "${{ matrix.platform.target }}"

+ 4 - 4
.gitignore

@@ -1,6 +1,6 @@
 /target
 /target
-/playwright-tests/web/dist
-/playwright-tests/fullstack/dist
+/packages/playwright-tests/web/dist
+/packages/playwright-tests/fullstack/dist
 /dist
 /dist
 .DS_Store
 .DS_Store
 /examples/assets/test_video.mp4
 /examples/assets/test_video.mp4
@@ -19,5 +19,5 @@ tarpaulin-report.html
 .idea/
 .idea/
 node_modules/
 node_modules/
 /test-results/
 /test-results/
-/playwright-report/
-/playwright/.cache/
+/packages/playwright-report/
+/packages/playwright/.cache/

+ 427 - 879
Cargo.lock

@@ -154,9 +154,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
 
 
 [[package]]
 [[package]]
 name = "anstream"
 name = "anstream"
-version = "0.6.5"
+version = "0.6.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
+checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
 dependencies = [
 dependencies = [
  "anstyle",
  "anstyle",
  "anstyle-parse",
  "anstyle-parse",
@@ -168,9 +168,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "anstyle"
 name = "anstyle"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
+checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220"
 
 
 [[package]]
 [[package]]
 name = "anstyle-parse"
 name = "anstyle-parse"
@@ -324,17 +324,6 @@ dependencies = [
  "futures-core",
  "futures-core",
 ]
 ]
 
 
-[[package]]
-name = "async-channel"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
-dependencies = [
- "concurrent-queue",
- "event-listener 2.5.3",
- "futures-core",
-]
-
 [[package]]
 [[package]]
 name = "async-channel"
 name = "async-channel"
 version = "2.1.1"
 version = "2.1.1"
@@ -364,9 +353,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "async-compression"
 name = "async-compression"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc2d0cfb2a7388d34f590e76686704c494ed7aaceed62ee1ba35cbf363abc2a5"
+checksum = "a116f46a969224200a0a97f29cfd4c50e7534e4b4826bd23ea2c3c533039c82c"
 dependencies = [
 dependencies = [
  "flate2",
  "flate2",
  "futures-core",
  "futures-core",
@@ -423,9 +412,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "async-io"
 name = "async-io"
-version = "2.2.2"
+version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6afaa937395a620e33dc6a742c593c01aced20aa376ffb0f628121198578ccc7"
+checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65"
 dependencies = [
 dependencies = [
  "async-lock 3.3.0",
  "async-lock 3.3.0",
  "cfg-if",
  "cfg-if",
@@ -433,8 +422,8 @@ dependencies = [
  "futures-io",
  "futures-io",
  "futures-lite 2.2.0",
  "futures-lite 2.2.0",
  "parking",
  "parking",
- "polling 3.3.1",
- "rustix 0.38.28",
+ "polling 3.3.2",
+ "rustix 0.38.31",
  "slab",
  "slab",
  "tracing",
  "tracing",
  "windows-sys 0.52.0",
  "windows-sys 0.52.0",
@@ -473,7 +462,7 @@ dependencies = [
  "cfg-if",
  "cfg-if",
  "event-listener 3.1.0",
  "event-listener 3.1.0",
  "futures-lite 1.13.0",
  "futures-lite 1.13.0",
- "rustix 0.38.28",
+ "rustix 0.38.31",
  "windows-sys 0.48.0",
  "windows-sys 0.48.0",
 ]
 ]
 
 
@@ -494,13 +483,13 @@ version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5"
 checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5"
 dependencies = [
 dependencies = [
- "async-io 2.2.2",
+ "async-io 2.3.1",
  "async-lock 2.8.0",
  "async-lock 2.8.0",
  "atomic-waker",
  "atomic-waker",
  "cfg-if",
  "cfg-if",
  "futures-core",
  "futures-core",
  "futures-io",
  "futures-io",
- "rustix 0.38.28",
+ "rustix 0.38.31",
  "signal-hook-registry",
  "signal-hook-registry",
  "slab",
  "slab",
  "windows-sys 0.48.0",
  "windows-sys 0.48.0",
@@ -792,9 +781,6 @@ version = "0.1.0"
 dependencies = [
 dependencies = [
  "axum 0.6.20",
  "axum 0.6.20",
  "dioxus",
  "dioxus",
- "dioxus-desktop",
- "dioxus-fullstack",
- "dioxus-router",
  "serde",
  "serde",
  "tokio",
  "tokio",
 ]
 ]
@@ -804,7 +790,6 @@ name = "axum-hello-world"
 version = "0.1.0"
 version = "0.1.0"
 dependencies = [
 dependencies = [
  "dioxus",
  "dioxus",
- "dioxus-fullstack",
  "reqwest",
  "reqwest",
  "serde",
  "serde",
  "simple_logger",
  "simple_logger",
@@ -831,9 +816,6 @@ version = "0.1.0"
 dependencies = [
 dependencies = [
  "axum 0.6.20",
  "axum 0.6.20",
  "dioxus",
  "dioxus",
- "dioxus-fullstack",
- "dioxus-router",
- "dioxus-web",
  "serde",
  "serde",
  "tokio",
  "tokio",
 ]
 ]
@@ -925,12 +907,6 @@ dependencies = [
  "rustc-demangle",
  "rustc-demangle",
 ]
 ]
 
 
-[[package]]
-name = "base16ct"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
-
 [[package]]
 [[package]]
 name = "base64"
 name = "base64"
 version = "0.9.3"
 version = "0.9.3"
@@ -1023,22 +999,13 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 
 [[package]]
 [[package]]
 name = "bitflags"
 name = "bitflags"
-version = "2.4.1"
+version = "2.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
 dependencies = [
 dependencies = [
  "serde",
  "serde",
 ]
 ]
 
 
-[[package]]
-name = "bitmaps"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
-dependencies = [
- "typenum",
-]
-
 [[package]]
 [[package]]
 name = "bitstream-io"
 name = "bitstream-io"
 version = "1.10.0"
 version = "1.10.0"
@@ -1084,7 +1051,7 @@ version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118"
 checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118"
 dependencies = [
 dependencies = [
- "async-channel 2.1.1",
+ "async-channel",
  "async-lock 3.3.0",
  "async-lock 3.3.0",
  "async-task",
  "async-task",
  "fastrand 2.0.1",
  "fastrand 2.0.1",
@@ -1096,9 +1063,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "borsh"
 name = "borsh"
-version = "1.3.0"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d4d6dafc1a3bb54687538972158f07b2c948bc57d5890df22c0739098b3028"
+checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667"
 dependencies = [
 dependencies = [
  "borsh-derive",
  "borsh-derive",
  "cfg_aliases",
  "cfg_aliases",
@@ -1106,12 +1073,12 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "borsh-derive"
 name = "borsh-derive"
-version = "1.3.0"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf4918709cc4dd777ad2b6303ed03cb37f3ca0ccede8c1b0d28ac6db8f4710e0"
+checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd"
 dependencies = [
 dependencies = [
  "once_cell",
  "once_cell",
- "proc-macro-crate 2.0.0",
+ "proc-macro-crate 3.1.0",
  "proc-macro2",
  "proc-macro2",
  "quote",
  "quote",
  "syn 2.0.48",
  "syn 2.0.48",
@@ -1155,7 +1122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
 checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
 dependencies = [
 dependencies = [
  "memchr",
  "memchr",
- "regex-automata 0.4.3",
+ "regex-automata 0.4.5",
  "serde",
  "serde",
 ]
 ]
 
 
@@ -1213,9 +1180,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "bytemuck"
 name = "bytemuck"
-version = "1.14.0"
+version = "1.14.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
+checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9"
 
 
 [[package]]
 [[package]]
 name = "byteorder"
 name = "byteorder"
@@ -1256,7 +1223,7 @@ version = "0.18.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2"
 checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "cairo-sys-rs",
  "cairo-sys-rs",
  "glib",
  "glib",
  "libc",
  "libc",
@@ -1292,7 +1259,7 @@ checksum = "92c1b6f44358912a9538fa3b6ac8d3aa3f585444f9dc32f12ed85d1545a9df9f"
 dependencies = [
 dependencies = [
  "anyhow",
  "anyhow",
  "auth-git2",
  "auth-git2",
- "clap 4.4.15",
+ "clap 4.4.18",
  "console",
  "console",
  "dialoguer",
  "dialoguer",
  "env_logger",
  "env_logger",
@@ -1302,7 +1269,7 @@ dependencies = [
  "heck 0.4.1",
  "heck 0.4.1",
  "home",
  "home",
  "ignore",
  "ignore",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "indicatif",
  "indicatif",
  "liquid",
  "liquid",
  "liquid-core",
  "liquid-core",
@@ -1320,7 +1287,7 @@ dependencies = [
  "serde",
  "serde",
  "tempfile",
  "tempfile",
  "thiserror",
  "thiserror",
- "toml 0.8.8",
+ "toml 0.8.9",
  "walkdir",
  "walkdir",
 ]
 ]
 
 
@@ -1407,7 +1374,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e3f9629bc6c4388ea699781dc988c2b99766d7679b151c81990b4fa1208fafd3"
 checksum = "e3f9629bc6c4388ea699781dc988c2b99766d7679b151c81990b4fa1208fafd3"
 dependencies = [
 dependencies = [
  "serde",
  "serde",
- "toml 0.8.8",
+ "toml 0.8.9",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -1417,7 +1384,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "802b755090e39835a4b0440fb0bbee0df7495a8b337f63db21e616f7821c7e8c"
 checksum = "802b755090e39835a4b0440fb0bbee0df7495a8b337f63db21e616f7821c7e8c"
 dependencies = [
 dependencies = [
  "serde",
  "serde",
- "toml 0.8.8",
+ "toml 0.8.9",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -1492,9 +1459,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
 
 
 [[package]]
 [[package]]
 name = "chrono"
 name = "chrono"
-version = "0.4.31"
+version = "0.4.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
+checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb"
 dependencies = [
 dependencies = [
  "android-tzdata",
  "android-tzdata",
  "iana-time-zone",
  "iana-time-zone",
@@ -1502,14 +1469,14 @@ dependencies = [
  "num-traits",
  "num-traits",
  "serde",
  "serde",
  "wasm-bindgen",
  "wasm-bindgen",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.0",
 ]
 ]
 
 
 [[package]]
 [[package]]
 name = "ciborium"
 name = "ciborium"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"
+checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
 dependencies = [
 dependencies = [
  "ciborium-io",
  "ciborium-io",
  "ciborium-ll",
  "ciborium-ll",
@@ -1518,18 +1485,18 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "ciborium-io"
 name = "ciborium-io"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
+checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
 
 
 [[package]]
 [[package]]
 name = "ciborium-ll"
 name = "ciborium-ll"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"
+checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
 dependencies = [
 dependencies = [
  "ciborium-io",
  "ciborium-io",
- "half 1.8.2",
+ "half 2.3.1",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -1555,9 +1522,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "clap"
 name = "clap"
-version = "4.4.15"
+version = "4.4.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c12ed66a79a555082f595f7eb980d08669de95009dd4b3d61168c573ebe38fc9"
+checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
 dependencies = [
 dependencies = [
  "clap_builder",
  "clap_builder",
  "clap_derive",
  "clap_derive",
@@ -1565,9 +1532,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "clap_builder"
 name = "clap_builder"
-version = "4.4.15"
+version = "4.4.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f4645eab3431e5a8403a96bea02506a8b35d28cd0f0330977dd5d22f9c84f43"
+checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
 dependencies = [
 dependencies = [
  "anstream",
  "anstream",
  "anstyle",
  "anstyle",
@@ -1593,12 +1560,6 @@ version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
 checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
 
 
-[[package]]
-name = "closure"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6173fd61b610d15a7566dd7b7620775627441c4ab9dac8906e17cb93a24b782"
-
 [[package]]
 [[package]]
 name = "cocoa"
 name = "cocoa"
 version = "0.25.0"
 version = "0.25.0"
@@ -1943,7 +1904,7 @@ dependencies = [
  "anes",
  "anes",
  "cast",
  "cast",
  "ciborium",
  "ciborium",
- "clap 4.4.15",
+ "clap 4.4.18",
  "criterion-plot 0.5.0",
  "criterion-plot 0.5.0",
  "futures",
  "futures",
  "is-terminal",
  "is-terminal",
@@ -2047,7 +2008,7 @@ version = "0.27.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
 checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "crossterm_winapi",
  "crossterm_winapi",
  "libc",
  "libc",
  "mio",
  "mio",
@@ -2082,18 +2043,6 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
 checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
 
 
-[[package]]
-name = "crypto-bigint"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
-dependencies = [
- "generic-array 0.14.7",
- "rand_core 0.6.4",
- "subtle",
- "zeroize",
-]
-
 [[package]]
 [[package]]
 name = "crypto-common"
 name = "crypto-common"
 version = "0.1.6"
 version = "0.1.6"
@@ -2122,23 +2071,6 @@ dependencies = [
  "syn 1.0.109",
  "syn 1.0.109",
 ]
 ]
 
 
-[[package]]
-name = "cssparser"
-version = "0.29.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa"
-dependencies = [
- "cssparser-macros",
- "dtoa-short",
- "itoa 1.0.10",
- "matches",
- "phf 0.10.1",
- "proc-macro2",
- "quote",
- "smallvec",
- "syn 1.0.109",
-]
-
 [[package]]
 [[package]]
 name = "cssparser"
 name = "cssparser"
 version = "0.33.0"
 version = "0.33.0"
@@ -2221,34 +2153,6 @@ dependencies = [
  "windows-sys 0.52.0",
  "windows-sys 0.52.0",
 ]
 ]
 
 
-[[package]]
-name = "curve25519-dalek"
-version = "4.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "curve25519-dalek-derive",
- "digest",
- "fiat-crypto",
- "platforms",
- "rustc_version",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "curve25519-dalek-derive"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.48",
-]
-
 [[package]]
 [[package]]
 name = "cvt"
 name = "cvt"
 version = "0.1.2"
 version = "0.1.2"
@@ -2260,9 +2164,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "darling"
 name = "darling"
-version = "0.20.3"
+version = "0.20.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
+checksum = "fc5d6b04b3fd0ba9926f945895de7d806260a2d7431ba82e7edaecb043c4c6b8"
 dependencies = [
 dependencies = [
  "darling_core",
  "darling_core",
  "darling_macro",
  "darling_macro",
@@ -2270,9 +2174,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "darling_core"
 name = "darling_core"
-version = "0.20.3"
+version = "0.20.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
+checksum = "04e48a959bcd5c761246f5d090ebc2fbf7b9cd527a492b07a67510c108f1e7e3"
 dependencies = [
 dependencies = [
  "fnv",
  "fnv",
  "ident_case",
  "ident_case",
@@ -2284,9 +2188,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "darling_macro"
 name = "darling_macro"
-version = "0.20.3"
+version = "0.20.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
+checksum = "1d1545d67a2149e1d93b7e5c7752dce5a7426eb5d1357ddcfd89336b94444f77"
 dependencies = [
 dependencies = [
  "darling_core",
  "darling_core",
  "quote",
  "quote",
@@ -2392,7 +2296,7 @@ version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a"
 checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "proc-macro2",
  "proc-macro2",
  "proc-macro2-diagnostics",
  "proc-macro2-diagnostics",
  "quote",
  "quote",
@@ -2435,15 +2339,25 @@ name = "dioxus"
 version = "0.4.3"
 version = "0.4.3"
 dependencies = [
 dependencies = [
  "criterion 0.3.6",
  "criterion 0.3.6",
+ "dioxus-config-macro",
  "dioxus-core",
  "dioxus-core",
  "dioxus-core-macro",
  "dioxus-core-macro",
+ "dioxus-desktop",
+ "dioxus-fullstack",
  "dioxus-hooks",
  "dioxus-hooks",
  "dioxus-hot-reload",
  "dioxus-hot-reload",
  "dioxus-html",
  "dioxus-html",
- "dioxus-rsx",
+ "dioxus-liveview",
+ "dioxus-mobile",
+ "dioxus-router",
+ "dioxus-signals",
+ "dioxus-ssr",
+ "dioxus-tui",
+ "dioxus-web",
  "env_logger",
  "env_logger",
  "futures-util",
  "futures-util",
  "rand 0.8.5",
  "rand 0.8.5",
+ "serde",
  "thiserror",
  "thiserror",
  "tokio",
  "tokio",
  "tracing",
  "tracing",
@@ -2486,7 +2400,7 @@ dependencies = [
  "cargo_metadata 0.18.1",
  "cargo_metadata 0.18.1",
  "cargo_toml 0.18.0",
  "cargo_toml 0.18.0",
  "chrono",
  "chrono",
- "clap 4.4.15",
+ "clap 4.4.18",
  "colored 2.1.0",
  "colored 2.1.0",
  "ctrlc",
  "ctrlc",
  "dioxus-autofmt",
  "dioxus-autofmt",
@@ -2524,8 +2438,8 @@ dependencies = [
  "tempfile",
  "tempfile",
  "thiserror",
  "thiserror",
  "tokio",
  "tokio",
- "toml 0.8.8",
- "toml_edit 0.21.0",
+ "toml 0.8.9",
+ "toml_edit 0.21.1",
  "tower",
  "tower",
  "tower-http 0.2.5",
  "tower-http 0.2.5",
  "walkdir",
  "walkdir",
@@ -2538,7 +2452,7 @@ name = "dioxus-cli-config"
 version = "0.4.1"
 version = "0.4.1"
 dependencies = [
 dependencies = [
  "cargo_toml 0.16.3",
  "cargo_toml 0.16.3",
- "clap 4.4.15",
+ "clap 4.4.18",
  "once_cell",
  "once_cell",
  "serde",
  "serde",
  "serde_json",
  "serde_json",
@@ -2548,13 +2462,19 @@ dependencies = [
  "tracing",
  "tracing",
 ]
 ]
 
 
+[[package]]
+name = "dioxus-config-macro"
+version = "0.4.3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
 [[package]]
 [[package]]
 name = "dioxus-core"
 name = "dioxus-core"
 version = "0.4.3"
 version = "0.4.3"
 dependencies = [
 dependencies = [
- "bumpalo",
  "dioxus",
  "dioxus",
- "dioxus-html",
  "dioxus-ssr",
  "dioxus-ssr",
  "futures-channel",
  "futures-channel",
  "futures-util",
  "futures-util",
@@ -2564,10 +2484,8 @@ dependencies = [
  "rustc-hash",
  "rustc-hash",
  "serde",
  "serde",
  "slab",
  "slab",
- "smallbox",
  "tokio",
  "tokio",
  "tracing",
  "tracing",
- "trybuild",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -2577,7 +2495,6 @@ dependencies = [
  "constcat",
  "constcat",
  "convert_case 0.6.0",
  "convert_case 0.6.0",
  "dioxus",
  "dioxus",
- "dioxus-core",
  "dioxus-rsx",
  "dioxus-rsx",
  "prettyplease",
  "prettyplease",
  "proc-macro2",
  "proc-macro2",
@@ -2603,7 +2520,6 @@ dependencies = [
  "dioxus",
  "dioxus",
  "dioxus-cli-config",
  "dioxus-cli-config",
  "dioxus-core",
  "dioxus-core",
- "dioxus-core-macro",
  "dioxus-hooks",
  "dioxus-hooks",
  "dioxus-hot-reload",
  "dioxus-hot-reload",
  "dioxus-html",
  "dioxus-html",
@@ -2612,15 +2528,14 @@ dependencies = [
  "exitcode",
  "exitcode",
  "futures-channel",
  "futures-channel",
  "futures-util",
  "futures-util",
+ "generational-box",
  "global-hotkey",
  "global-hotkey",
  "infer 0.11.0",
  "infer 0.11.0",
- "minify-js",
  "muda",
  "muda",
  "objc",
  "objc",
  "objc_id",
  "objc_id",
  "rfd",
  "rfd",
  "rustc-hash",
  "rustc-hash",
- "scraper",
  "serde",
  "serde",
  "serde_json",
  "serde_json",
  "slab",
  "slab",
@@ -2637,29 +2552,19 @@ dependencies = [
 name = "dioxus-examples"
 name = "dioxus-examples"
 version = "0.4.3"
 version = "0.4.3"
 dependencies = [
 dependencies = [
- "anyhow",
  "dioxus",
  "dioxus",
- "dioxus-desktop",
- "dioxus-router",
- "dioxus-signals",
  "dioxus-ssr",
  "dioxus-ssr",
- "env_logger",
- "fermi",
+ "form_urlencoded",
  "futures-util",
  "futures-util",
+ "getrandom 0.2.12",
  "http-range",
  "http-range",
- "im-rc",
- "log",
  "manganis",
  "manganis",
- "num-format",
  "rand 0.8.5",
  "rand 0.8.5",
  "reqwest",
  "reqwest",
  "separator",
  "separator",
  "serde",
  "serde",
  "serde_json",
  "serde_json",
- "simple_logger",
- "thiserror",
  "tokio",
  "tokio",
- "tracing-subscriber",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -2682,10 +2587,11 @@ dependencies = [
  "base64 0.21.7",
  "base64 0.21.7",
  "bytes",
  "bytes",
  "ciborium",
  "ciborium",
- "dioxus",
+ "dioxus-cli-config",
  "dioxus-desktop",
  "dioxus-desktop",
  "dioxus-hot-reload",
  "dioxus-hot-reload",
- "dioxus-router",
+ "dioxus-lib",
+ "dioxus-mobile",
  "dioxus-ssr",
  "dioxus-ssr",
  "dioxus-web",
  "dioxus-web",
  "dioxus_server_macro",
  "dioxus_server_macro",
@@ -2719,6 +2625,7 @@ dependencies = [
  "dioxus",
  "dioxus",
  "dioxus-core",
  "dioxus-core",
  "dioxus-debug-cell",
  "dioxus-debug-cell",
+ "dioxus-signals",
  "futures-channel",
  "futures-channel",
  "futures-util",
  "futures-util",
  "slab",
  "slab",
@@ -2748,13 +2655,14 @@ dependencies = [
 name = "dioxus-html"
 name = "dioxus-html"
 version = "0.4.3"
 version = "0.4.3"
 dependencies = [
 dependencies = [
- "async-channel 1.9.0",
  "async-trait",
  "async-trait",
  "dioxus-core",
  "dioxus-core",
  "dioxus-html-internal-macro",
  "dioxus-html-internal-macro",
  "dioxus-rsx",
  "dioxus-rsx",
  "enumset",
  "enumset",
  "euclid",
  "euclid",
+ "futures-channel",
+ "generational-box",
  "keyboard-types",
  "keyboard-types",
  "rfd",
  "rfd",
  "serde",
  "serde",
@@ -2781,6 +2689,8 @@ dependencies = [
 name = "dioxus-interpreter-js"
 name = "dioxus-interpreter-js"
 version = "0.4.3"
 version = "0.4.3"
 dependencies = [
 dependencies = [
+ "dioxus-core",
+ "dioxus-html",
  "js-sys",
  "js-sys",
  "serde",
  "serde",
  "sledgehammer_bindgen",
  "sledgehammer_bindgen",
@@ -2789,6 +2699,19 @@ dependencies = [
  "web-sys",
  "web-sys",
 ]
 ]
 
 
+[[package]]
+name = "dioxus-lib"
+version = "0.4.3"
+dependencies = [
+ "dioxus-config-macro",
+ "dioxus-core",
+ "dioxus-core-macro",
+ "dioxus-hooks",
+ "dioxus-html",
+ "dioxus-rsx",
+ "dioxus-signals",
+]
+
 [[package]]
 [[package]]
 name = "dioxus-liveview"
 name = "dioxus-liveview"
 version = "0.4.3"
 version = "0.4.3"
@@ -2796,12 +2719,14 @@ dependencies = [
  "async-trait",
  "async-trait",
  "axum 0.6.20",
  "axum 0.6.20",
  "dioxus",
  "dioxus",
+ "dioxus-cli-config",
  "dioxus-core",
  "dioxus-core",
  "dioxus-hot-reload",
  "dioxus-hot-reload",
  "dioxus-html",
  "dioxus-html",
  "dioxus-interpreter-js",
  "dioxus-interpreter-js",
  "futures-channel",
  "futures-channel",
  "futures-util",
  "futures-util",
+ "generational-box",
  "minify-js",
  "minify-js",
  "once_cell",
  "once_cell",
  "pretty_env_logger",
  "pretty_env_logger",
@@ -2821,16 +2746,6 @@ dependencies = [
  "warp",
  "warp",
 ]
 ]
 
 
-[[package]]
-name = "dioxus-logger"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d7cbab0b5519060fe9e14b3c21e3f2329b8386cd905618f78c7b929cd00cf54"
-dependencies = [
- "log",
- "web-sys",
-]
-
 [[package]]
 [[package]]
 name = "dioxus-mobile"
 name = "dioxus-mobile"
 version = "0.4.3"
 version = "0.4.3"
@@ -2876,13 +2791,8 @@ dependencies = [
 name = "dioxus-playwright-fullstack-test"
 name = "dioxus-playwright-fullstack-test"
 version = "0.1.0"
 version = "0.1.0"
 dependencies = [
 dependencies = [
- "axum 0.6.20",
  "dioxus",
  "dioxus",
- "dioxus-fullstack",
- "dioxus-web",
- "execute",
  "serde",
  "serde",
- "tokio",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -2900,9 +2810,9 @@ name = "dioxus-playwright-web-test"
 version = "0.0.1"
 version = "0.0.1"
 dependencies = [
 dependencies = [
  "dioxus",
  "dioxus",
- "dioxus-html",
- "dioxus-web",
  "serde_json",
  "serde_json",
+ "tracing",
+ "tracing-wasm",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -2925,14 +2835,14 @@ dependencies = [
  "criterion 0.5.1",
  "criterion 0.5.1",
  "dioxus",
  "dioxus",
  "dioxus-cli-config",
  "dioxus-cli-config",
- "dioxus-desktop",
+ "dioxus-fullstack",
+ "dioxus-lib",
  "dioxus-liveview",
  "dioxus-liveview",
  "dioxus-router",
  "dioxus-router",
  "dioxus-router-macro",
  "dioxus-router-macro",
  "dioxus-ssr",
  "dioxus-ssr",
- "dioxus-web",
  "gloo",
  "gloo",
- "gloo-utils 0.1.7",
+ "gloo-utils",
  "js-sys",
  "js-sys",
  "serde",
  "serde",
  "serde_json",
  "serde_json",
@@ -2942,7 +2852,6 @@ dependencies = [
  "urlencoding",
  "urlencoding",
  "wasm-bindgen",
  "wasm-bindgen",
  "wasm-bindgen-test",
  "wasm-bindgen-test",
- "wasm-logger",
  "web-sys",
  "web-sys",
 ]
 ]
 
 
@@ -2976,12 +2885,18 @@ version = "0.4.3"
 dependencies = [
 dependencies = [
  "dioxus",
  "dioxus",
  "dioxus-core",
  "dioxus-core",
- "dioxus-desktop",
+ "flume 0.11.0",
+ "futures-channel",
+ "futures-util",
  "generational-box",
  "generational-box",
+ "once_cell",
+ "parking_lot",
+ "rustc-hash",
  "serde",
  "serde",
  "simple_logger",
  "simple_logger",
  "tokio",
  "tokio",
  "tracing",
  "tracing",
+ "tracing-subscriber",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -2995,8 +2910,10 @@ dependencies = [
  "dioxus",
  "dioxus",
  "dioxus-core",
  "dioxus-core",
  "dioxus-html",
  "dioxus-html",
+ "dioxus-signals",
  "fern",
  "fern",
  "fs_extra",
  "fs_extra",
+ "generational-box",
  "http 0.2.11",
  "http 0.2.11",
  "lru 0.10.1",
  "lru 0.10.1",
  "rustc-hash",
  "rustc-hash",
@@ -3012,8 +2929,6 @@ name = "dioxus-tailwind"
 version = "0.0.0"
 version = "0.0.0"
 dependencies = [
 dependencies = [
  "dioxus",
  "dioxus",
- "dioxus-desktop",
- "dioxus-web",
  "manganis",
  "manganis",
 ]
 ]
 
 
@@ -3039,7 +2954,6 @@ dependencies = [
 name = "dioxus-web"
 name = "dioxus-web"
 version = "0.4.3"
 version = "0.4.3"
 dependencies = [
 dependencies = [
- "async-channel 1.9.0",
  "async-trait",
  "async-trait",
  "console_error_panic_hook",
  "console_error_panic_hook",
  "dioxus",
  "dioxus",
@@ -3050,6 +2964,7 @@ dependencies = [
  "dioxus-web",
  "dioxus-web",
  "futures-channel",
  "futures-channel",
  "futures-util",
  "futures-util",
+ "generational-box",
  "gloo-dialogs",
  "gloo-dialogs",
  "gloo-timers",
  "gloo-timers",
  "js-sys",
  "js-sys",
@@ -3062,7 +2977,6 @@ dependencies = [
  "wasm-bindgen",
  "wasm-bindgen",
  "wasm-bindgen-futures",
  "wasm-bindgen-futures",
  "wasm-bindgen-test",
  "wasm-bindgen-test",
- "wasm-logger",
  "web-sys",
  "web-sys",
 ]
 ]
 
 
@@ -3164,56 +3078,6 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
 checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
 
 
-[[package]]
-name = "dyn-clone"
-version = "1.0.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d"
-
-[[package]]
-name = "ecdsa"
-version = "0.16.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
-dependencies = [
- "der",
- "digest",
- "elliptic-curve",
- "rfc6979",
- "signature",
- "spki",
-]
-
-[[package]]
-name = "ed25519"
-version = "2.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
-dependencies = [
- "pkcs8",
- "signature",
-]
-
-[[package]]
-name = "ed25519-dalek"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
-dependencies = [
- "curve25519-dalek",
- "ed25519",
- "serde",
- "sha2",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "ego-tree"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591"
-
 [[package]]
 [[package]]
 name = "either"
 name = "either"
 version = "1.9.0"
 version = "1.9.0"
@@ -3223,27 +3087,6 @@ dependencies = [
  "serde",
  "serde",
 ]
 ]
 
 
-[[package]]
-name = "elliptic-curve"
-version = "0.13.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
-dependencies = [
- "base16ct",
- "crypto-bigint",
- "digest",
- "ff",
- "generic-array 0.14.7",
- "group",
- "hkdf",
- "pem-rfc7468",
- "pkcs8",
- "rand_core 0.6.4",
- "sec1",
- "subtle",
- "zeroize",
-]
-
 [[package]]
 [[package]]
 name = "encode_unicode"
 name = "encode_unicode"
 version = "0.3.6"
 version = "0.3.6"
@@ -3315,9 +3158,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "env_logger"
 name = "env_logger"
-version = "0.10.1"
+version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece"
+checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
 dependencies = [
 dependencies = [
  "humantime",
  "humantime",
  "is-terminal",
  "is-terminal",
@@ -3456,13 +3299,13 @@ checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193"
 
 
 [[package]]
 [[package]]
 name = "exr"
 name = "exr"
-version = "1.71.0"
+version = "1.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8"
+checksum = "279d3efcc55e19917fff7ab3ddd6c14afb6a90881a0078465196fe2f99d08c56"
 dependencies = [
 dependencies = [
  "bit_field",
  "bit_field",
- "flume",
- "half 2.2.1",
+ "flume 0.10.14",
+ "half 2.3.1",
  "lebe",
  "lebe",
  "miniz_oxide",
  "miniz_oxide",
  "rayon-core",
  "rayon-core",
@@ -3502,23 +3345,13 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
 
 
 [[package]]
 [[package]]
 name = "fdeflate"
 name = "fdeflate"
-version = "0.3.3"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "209098dd6dfc4445aa6111f0e98653ac323eaa4dfd212c9ca3931bf9955c31bd"
+checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645"
 dependencies = [
 dependencies = [
  "simd-adler32",
  "simd-adler32",
 ]
 ]
 
 
-[[package]]
-name = "fermi"
-version = "0.4.3"
-dependencies = [
- "closure",
- "dioxus-core",
- "im-rc",
- "tracing",
-]
-
 [[package]]
 [[package]]
 name = "fern"
 name = "fern"
 version = "0.6.2"
 version = "0.6.2"
@@ -3529,22 +3362,6 @@ dependencies = [
  "log",
  "log",
 ]
 ]
 
 
-[[package]]
-name = "ff"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
-dependencies = [
- "rand_core 0.6.4",
- "subtle",
-]
-
-[[package]]
-name = "fiat-crypto"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7"
-
 [[package]]
 [[package]]
 name = "field-offset"
 name = "field-offset"
 version = "0.3.6"
 version = "0.3.6"
@@ -3557,14 +3374,14 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "figment"
 name = "figment"
-version = "0.10.13"
+version = "0.10.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7629b8c7bcd214a072c2c88b263b5bb3ceb54c34365d8c41c1665461aeae0993"
+checksum = "2b6e5bc7bd59d60d0d45a6ccab6cf0f4ce28698fb4e81e750ddf229c9b824026"
 dependencies = [
 dependencies = [
  "atomic 0.6.0",
  "atomic 0.6.0",
  "pear",
  "pear",
  "serde",
  "serde",
- "toml 0.8.8",
+ "toml 0.8.9",
  "uncased",
  "uncased",
  "version_check",
  "version_check",
 ]
 ]
@@ -3603,6 +3420,19 @@ dependencies = [
  "miniz_oxide",
  "miniz_oxide",
 ]
 ]
 
 
+[[package]]
+name = "flume"
+version = "0.10.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "nanorand",
+ "pin-project",
+ "spin 0.9.8",
+]
+
 [[package]]
 [[package]]
 name = "flume"
 name = "flume"
 version = "0.11.0"
 version = "0.11.0"
@@ -3965,7 +3795,8 @@ dependencies = [
 name = "generational-box"
 name = "generational-box"
 version = "0.4.3"
 version = "0.4.3"
 dependencies = [
 dependencies = [
- "bumpalo",
+ "criterion 0.3.6",
+ "parking_lot",
  "rand 0.8.5",
  "rand 0.8.5",
 ]
 ]
 
 
@@ -3990,7 +3821,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
 dependencies = [
 dependencies = [
  "typenum",
  "typenum",
  "version_check",
  "version_check",
- "zeroize",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -4002,15 +3832,6 @@ dependencies = [
  "typenum",
  "typenum",
 ]
 ]
 
 
-[[package]]
-name = "getopts"
-version = "0.2.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
-dependencies = [
- "unicode-width",
-]
-
 [[package]]
 [[package]]
 name = "getrandom"
 name = "getrandom"
 version = "0.1.16"
 version = "0.1.16"
@@ -4110,7 +3931,7 @@ version = "0.18.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fbf97ba92db08df386e10c8ede66a2a0369bd277090afd8710e19e38de9ec0cd"
 checksum = "fbf97ba92db08df386e10c8ede66a2a0369bd277090afd8710e19e38de9ec0cd"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "libc",
  "libc",
  "libgit2-sys",
  "libgit2-sys",
  "log",
  "log",
@@ -4165,11 +3986,11 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "gix-config-value"
 name = "gix-config-value"
-version = "0.14.3"
+version = "0.14.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52e0be46f4cf1f8f9e88d0e3eb7b29718aff23889563249f379119bd1ab6910e"
+checksum = "5b8a1e7bfb37a46ed0b8468db37a6d8a0a61d56bdbe4603ae492cb322e5f3958"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "bstr 1.9.0",
  "bstr 1.9.0",
  "gix-path",
  "gix-path",
  "libc",
  "libc",
@@ -4217,7 +4038,7 @@ version = "0.14.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5db19298c5eeea2961e5b3bf190767a2d1f09b8802aeb5f258e42276350aff19"
 checksum = "5db19298c5eeea2961e5b3bf190767a2d1f09b8802aeb5f258e42276350aff19"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "bstr 1.9.0",
  "bstr 1.9.0",
  "gix-features",
  "gix-features",
  "gix-path",
  "gix-path",
@@ -4265,9 +4086,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "gix-path"
 name = "gix-path"
-version = "0.10.3"
+version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8dd0998ab245f33d40ca2267e58d542fe54185ebd1dc41923346cf28d179fb6"
+checksum = "97e9ad649bf5e109562d6acba657ca428661ec08e77eaf3a755d8fa55485be9c"
 dependencies = [
 dependencies = [
  "bstr 1.9.0",
  "bstr 1.9.0",
  "gix-trace",
  "gix-trace",
@@ -4299,14 +4120,14 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "gix-sec"
 name = "gix-sec"
-version = "0.10.3"
+version = "0.10.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78f6dce0c6683e2219e8169aac4b1c29e89540a8262fef7056b31d80d969408c"
+checksum = "f8d9bf462feaf05f2121cba7399dbc6c34d88a9cad58fc1e95027791d6a3c6d2"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "gix-path",
  "gix-path",
  "libc",
  "libc",
- "windows 0.52.0",
+ "windows-sys 0.52.0",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -4324,17 +4145,18 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "gix-trace"
 name = "gix-trace"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8e1127ede0475b58f4fe9c0aaa0d9bb0bad2af90bbd93ccd307c8632b863d89"
+checksum = "02b202d766a7fefc596e2cc6a89cda8ad8ad733aed82da635ac120691112a9b1"
 
 
 [[package]]
 [[package]]
 name = "gix-utils"
 name = "gix-utils"
-version = "0.1.8"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de6225e2de30b6e9bca2d9f1cc4731640fcef0fb3cabddceee366e7e85d3e94f"
+checksum = "56e839f3d0798b296411263da6bee780a176ef8008a5dfc31287f7eda9266ab8"
 dependencies = [
 dependencies = [
  "fastrand 2.0.1",
  "fastrand 2.0.1",
+ "unicode-normalization",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -4353,7 +4175,7 @@ version = "0.18.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5"
 checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "futures-channel",
  "futures-channel",
  "futures-core",
  "futures-core",
  "futures-executor",
  "futures-executor",
@@ -4402,9 +4224,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
 
 
 [[package]]
 [[package]]
 name = "global-hotkey"
 name = "global-hotkey"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d505f007b733fc3b3261ca0710e7e689411422ace5f5b2a63a14d8596159db23"
+checksum = "927a00fd7c31d82029f99ce2481a8de1ae974758017d6a55ebbe7f22edcd1617"
 dependencies = [
 dependencies = [
  "crossbeam-channel",
  "crossbeam-channel",
  "keyboard-types",
  "keyboard-types",
@@ -4423,7 +4245,7 @@ dependencies = [
  "aho-corasick 1.1.2",
  "aho-corasick 1.1.2",
  "bstr 1.9.0",
  "bstr 1.9.0",
  "log",
  "log",
- "regex-automata 0.4.3",
+ "regex-automata 0.4.5",
  "regex-syntax 0.8.2",
  "regex-syntax 0.8.2",
 ]
 ]
 
 
@@ -4440,9 +4262,9 @@ dependencies = [
  "gloo-history",
  "gloo-history",
  "gloo-net 0.3.1",
  "gloo-net 0.3.1",
  "gloo-render",
  "gloo-render",
- "gloo-storage 0.2.2",
+ "gloo-storage",
  "gloo-timers",
  "gloo-timers",
- "gloo-utils 0.1.7",
+ "gloo-utils",
  "gloo-worker",
  "gloo-worker",
 ]
 ]
 
 
@@ -4452,7 +4274,7 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f"
 checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f"
 dependencies = [
 dependencies = [
- "gloo-utils 0.1.7",
+ "gloo-utils",
  "js-sys",
  "js-sys",
  "serde",
  "serde",
  "wasm-bindgen",
  "wasm-bindgen",
@@ -4498,7 +4320,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "85725d90bf0ed47063b3930ef28e863658a7905989e9929a8708aab74a1d5e7f"
 checksum = "85725d90bf0ed47063b3930ef28e863658a7905989e9929a8708aab74a1d5e7f"
 dependencies = [
 dependencies = [
  "gloo-events",
  "gloo-events",
- "gloo-utils 0.1.7",
+ "gloo-utils",
  "serde",
  "serde",
  "serde-wasm-bindgen",
  "serde-wasm-bindgen",
  "serde_urlencoded",
  "serde_urlencoded",
@@ -4516,7 +4338,7 @@ dependencies = [
  "futures-channel",
  "futures-channel",
  "futures-core",
  "futures-core",
  "futures-sink",
  "futures-sink",
- "gloo-utils 0.1.7",
+ "gloo-utils",
  "js-sys",
  "js-sys",
  "pin-project",
  "pin-project",
  "serde",
  "serde",
@@ -4536,7 +4358,7 @@ dependencies = [
  "futures-channel",
  "futures-channel",
  "futures-core",
  "futures-core",
  "futures-sink",
  "futures-sink",
- "gloo-utils 0.1.7",
+ "gloo-utils",
  "http 0.2.11",
  "http 0.2.11",
  "js-sys",
  "js-sys",
  "pin-project",
  "pin-project",
@@ -4564,22 +4386,7 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480"
 checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480"
 dependencies = [
 dependencies = [
- "gloo-utils 0.1.7",
- "js-sys",
- "serde",
- "serde_json",
- "thiserror",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "gloo-storage"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a"
-dependencies = [
- "gloo-utils 0.2.0",
+ "gloo-utils",
  "js-sys",
  "js-sys",
  "serde",
  "serde",
  "serde_json",
  "serde_json",
@@ -4611,19 +4418,6 @@ dependencies = [
  "web-sys",
  "web-sys",
 ]
 ]
 
 
-[[package]]
-name = "gloo-utils"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa"
-dependencies = [
- "js-sys",
- "serde",
- "serde_json",
- "wasm-bindgen",
- "web-sys",
-]
-
 [[package]]
 [[package]]
 name = "gloo-worker"
 name = "gloo-worker"
 version = "0.2.1"
 version = "0.2.1"
@@ -4633,7 +4427,7 @@ dependencies = [
  "anymap2",
  "anymap2",
  "bincode",
  "bincode",
  "gloo-console",
  "gloo-console",
- "gloo-utils 0.1.7",
+ "gloo-utils",
  "js-sys",
  "js-sys",
  "serde",
  "serde",
  "wasm-bindgen",
  "wasm-bindgen",
@@ -4658,17 +4452,6 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "eec1c01eb1de97451ee0d60de7d81cf1e72aabefb021616027f3d1c3ec1c723c"
 checksum = "eec1c01eb1de97451ee0d60de7d81cf1e72aabefb021616027f3d1c3ec1c723c"
 
 
-[[package]]
-name = "group"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
-dependencies = [
- "ff",
- "rand_core 0.6.4",
- "subtle",
-]
-
 [[package]]
 [[package]]
 name = "gtk"
 name = "gtk"
 version = "0.18.1"
 version = "0.18.1"
@@ -4733,7 +4516,7 @@ dependencies = [
  "futures-sink",
  "futures-sink",
  "futures-util",
  "futures-util",
  "http 0.2.11",
  "http 0.2.11",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "slab",
  "slab",
  "tokio",
  "tokio",
  "tokio-util",
  "tokio-util",
@@ -4742,9 +4525,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "h2"
 name = "h2"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "991910e35c615d8cab86b5ab04be67e6ad24d2bf5f4f11fdbbed26da999bbeab"
+checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943"
 dependencies = [
 dependencies = [
  "bytes",
  "bytes",
  "fnv",
  "fnv",
@@ -4752,7 +4535,7 @@ dependencies = [
  "futures-sink",
  "futures-sink",
  "futures-util",
  "futures-util",
  "http 1.0.0",
  "http 1.0.0",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "slab",
  "slab",
  "tokio",
  "tokio",
  "tokio-util",
  "tokio-util",
@@ -4767,10 +4550,11 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
 
 
 [[package]]
 [[package]]
 name = "half"
 name = "half"
-version = "2.2.1"
+version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0"
+checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872"
 dependencies = [
 dependencies = [
+ "cfg-if",
  "crunchy",
  "crunchy",
 ]
 ]
 
 
@@ -4903,9 +4687,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "hermit-abi"
 name = "hermit-abi"
-version = "0.3.3"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
+checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f"
 
 
 [[package]]
 [[package]]
 name = "hex"
 name = "hex"
@@ -5099,7 +4883,7 @@ dependencies = [
  "bytes",
  "bytes",
  "futures-channel",
  "futures-channel",
  "futures-util",
  "futures-util",
- "h2 0.4.1",
+ "h2 0.4.2",
  "http 1.0.0",
  "http 1.0.0",
  "http-body 1.0.0",
  "http-body 1.0.0",
  "httparse",
  "httparse",
@@ -5154,12 +4938,11 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "hyper-util"
 name = "hyper-util"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67"
+checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
 dependencies = [
 dependencies = [
  "bytes",
  "bytes",
- "futures-channel",
  "futures-util",
  "futures-util",
  "http 1.0.0",
  "http 1.0.0",
  "http-body 1.0.0",
  "http-body 1.0.0",
@@ -5167,7 +4950,6 @@ dependencies = [
  "pin-project-lite",
  "pin-project-lite",
  "socket2 0.5.5",
  "socket2 0.5.5",
  "tokio",
  "tokio",
- "tracing",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -5235,32 +5017,17 @@ dependencies = [
  "globset",
  "globset",
  "log",
  "log",
  "memchr",
  "memchr",
- "regex-automata 0.4.3",
+ "regex-automata 0.4.5",
  "same-file",
  "same-file",
  "walkdir",
  "walkdir",
  "winapi-util",
  "winapi-util",
 ]
 ]
 
 
-[[package]]
-name = "im-rc"
-version = "15.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
-dependencies = [
- "bitmaps",
- "rand_core 0.6.4",
- "rand_xoshiro",
- "serde",
- "sized-chunks",
- "typenum",
- "version_check",
-]
-
 [[package]]
 [[package]]
 name = "image"
 name = "image"
-version = "0.24.7"
+version = "0.24.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711"
+checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23"
 dependencies = [
 dependencies = [
  "bytemuck",
  "bytemuck",
  "byteorder",
  "byteorder",
@@ -5268,7 +5035,6 @@ dependencies = [
  "exr",
  "exr",
  "gif",
  "gif",
  "jpeg-decoder",
  "jpeg-decoder",
- "num-rational",
  "num-traits",
  "num-traits",
  "png",
  "png",
  "qoi",
  "qoi",
@@ -5280,9 +5046,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "imagequant"
 name = "imagequant"
-version = "4.2.2"
+version = "4.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84d51957ac48371e8e2eaaeb4eba56150ff2109c1c8c200002afb7dd6e2d260f"
+checksum = "85a7f142d232ccbdc00cbef49d17f45639aeb07d9bfe28e17c21dea3efac64e5"
 dependencies = [
 dependencies = [
  "arrayvec",
  "arrayvec",
  "once_cell",
  "once_cell",
@@ -5293,9 +5059,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "imgref"
 name = "imgref"
-version = "1.10.0"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90d944e334f00f4449c9640b440a171f816be0152305c12ef90424fc35fd035c"
+checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126"
 
 
 [[package]]
 [[package]]
 name = "indexmap"
 name = "indexmap"
@@ -5310,9 +5076,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "indexmap"
 name = "indexmap"
-version = "2.1.0"
+version = "2.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
+checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520"
 dependencies = [
 dependencies = [
  "equivalent",
  "equivalent",
  "hashbrown 0.14.3",
  "hashbrown 0.14.3",
@@ -5449,9 +5215,9 @@ checksum = "ae52f28f45ac2bc96edb7714de995cffc174a395fb0abf5bff453587c980d7b9"
 
 
 [[package]]
 [[package]]
 name = "inventory"
 name = "inventory"
-version = "0.3.14"
+version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8573b2b1fb643a372c73b23f4da5f888677feef3305146d68a539250a9bccc7"
+checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767"
 
 
 [[package]]
 [[package]]
 name = "io-lifetimes"
 name = "io-lifetimes"
@@ -5459,7 +5225,7 @@ version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
 checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
 dependencies = [
 dependencies = [
- "hermit-abi 0.3.3",
+ "hermit-abi 0.3.4",
  "libc",
  "libc",
  "windows-sys 0.48.0",
  "windows-sys 0.48.0",
 ]
 ]
@@ -5515,8 +5281,8 @@ version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
 checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
 dependencies = [
 dependencies = [
- "hermit-abi 0.3.3",
- "rustix 0.38.28",
+ "hermit-abi 0.3.4",
+ "rustix 0.38.31",
  "windows-sys 0.52.0",
  "windows-sys 0.52.0",
 ]
 ]
 
 
@@ -5556,9 +5322,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "itertools"
 name = "itertools"
-version = "0.12.0"
+version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
 dependencies = [
 dependencies = [
  "either",
  "either",
 ]
 ]
@@ -5631,18 +5397,18 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "jpeg-decoder"
 name = "jpeg-decoder"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
+checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"
 dependencies = [
 dependencies = [
  "rayon",
  "rayon",
 ]
 ]
 
 
 [[package]]
 [[package]]
 name = "js-sys"
 name = "js-sys"
-version = "0.3.66"
+version = "0.3.67"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
+checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
 dependencies = [
 dependencies = [
  "wasm-bindgen",
  "wasm-bindgen",
 ]
 ]
@@ -5665,7 +5431,7 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a"
 checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "serde",
  "serde",
  "unicode-segmentation",
  "unicode-segmentation",
 ]
 ]
@@ -5722,7 +5488,7 @@ dependencies = [
  "html5ever",
  "html5ever",
  "indexmap 1.9.3",
  "indexmap 1.9.3",
  "matches",
  "matches",
- "selectors 0.22.0",
+ "selectors",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -5748,9 +5514,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
 
 
 [[package]]
 [[package]]
 name = "libc"
 name = "libc"
-version = "0.2.152"
+version = "0.2.153"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
 
 
 [[package]]
 [[package]]
 name = "libflate"
 name = "libflate"
@@ -5819,7 +5585,7 @@ version = "0.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
 checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "libc",
  "libc",
  "redox_syscall",
  "redox_syscall",
 ]
 ]
@@ -5880,9 +5646,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "libz-sys"
 name = "libz-sys"
-version = "1.1.14"
+version = "1.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "295c17e837573c8c821dbaeb3cceb3d745ad082f7572191409e69cbc1b3fd050"
+checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6"
 dependencies = [
 dependencies = [
  "cc",
  "cc",
  "libc",
  "libc",
@@ -5892,12 +5658,12 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "lightningcss"
 name = "lightningcss"
-version = "1.0.0-alpha.51"
+version = "1.0.0-alpha.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99d6ad516c08b24c246b339159dc2ee2144c012e8ebdf4db4bddefb8734b2b69"
+checksum = "771a62dedf5ec563bbfea9760f6c6a6bc546e67355eba0cd7d00c0dc34b11d90"
 dependencies = [
 dependencies = [
  "ahash 0.7.7",
  "ahash 0.7.7",
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "const-str",
  "const-str",
  "cssparser 0.33.0",
  "cssparser 0.33.0",
  "cssparser-color",
  "cssparser-color",
@@ -5943,9 +5709,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
 
 
 [[package]]
 [[package]]
 name = "linux-raw-sys"
 name = "linux-raw-sys"
-version = "0.4.12"
+version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
 
 
 [[package]]
 [[package]]
 name = "liquid"
 name = "liquid"
@@ -6046,9 +5812,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "loop9"
 name = "loop9"
-version = "0.1.4"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81a837f917de41d61ab531ba255d1913208d02325cab0d6a66a706e0dbaa699d"
+checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062"
 dependencies = [
 dependencies = [
  "imgref",
  "imgref",
 ]
 ]
@@ -6073,9 +5839,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "lru"
 name = "lru"
-version = "0.12.1"
+version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2994eeba8ed550fd9b47a0b38f0242bc3344e496483c6180b69139cc2fa5d1d7"
+checksum = "db2c024b41519440580066ba82aab04092b333e09066a5eb86c7c4890df31f22"
 dependencies = [
 dependencies = [
  "hashbrown 0.14.3",
  "hashbrown 0.14.3",
 ]
 ]
@@ -6435,9 +6201,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "muda"
 name = "muda"
-version = "0.11.3"
+version = "0.11.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "884427679a3ef726cd4a0ad6eec2ca618737ba11ebe8c9320dc305c09c78c8fc"
+checksum = "e406691fa7749604bbc7964bde28a300572d52621bb84540f6907c0f8fe08737"
 dependencies = [
 dependencies = [
  "cocoa",
  "cocoa",
  "crossbeam-channel",
  "crossbeam-channel",
@@ -6502,9 +6268,18 @@ dependencies = [
 name = "names"
 name = "names"
 version = "0.14.0"
 version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bddcd3bf5144b6392de80e04c347cd7fab2508f6df16a85fc496ecd5cec39bc"
+checksum = "7bddcd3bf5144b6392de80e04c347cd7fab2508f6df16a85fc496ecd5cec39bc"
+dependencies = [
+ "rand 0.8.5",
+]
+
+[[package]]
+name = "nanorand"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
 dependencies = [
 dependencies = [
- "rand 0.8.5",
+ "getrandom 0.2.12",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -6600,7 +6375,7 @@ version = "0.27.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
 checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "cfg-if",
  "cfg-if",
  "libc",
  "libc",
 ]
 ]
@@ -6693,6 +6468,12 @@ dependencies = [
  "zeroize",
  "zeroize",
 ]
 ]
 
 
+[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
 [[package]]
 [[package]]
 name = "num-derive"
 name = "num-derive"
 version = "0.3.3"
 version = "0.3.3"
@@ -6715,16 +6496,6 @@ dependencies = [
  "syn 2.0.48",
  "syn 2.0.48",
 ]
 ]
 
 
-[[package]]
-name = "num-format"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3"
-dependencies = [
- "arrayvec",
- "itoa 1.0.10",
-]
-
 [[package]]
 [[package]]
 name = "num-integer"
 name = "num-integer"
 version = "0.1.45"
 version = "0.1.45"
@@ -6774,7 +6545,7 @@ version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
 checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
 dependencies = [
 dependencies = [
- "hermit-abi 0.3.3",
+ "hermit-abi 0.3.4",
  "libc",
  "libc",
 ]
 ]
 
 
@@ -6814,26 +6585,6 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
 checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
 
 
-[[package]]
-name = "oauth2"
-version = "4.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f"
-dependencies = [
- "base64 0.13.1",
- "chrono",
- "getrandom 0.2.12",
- "http 0.2.11",
- "rand 0.8.5",
- "reqwest",
- "serde",
- "serde_json",
- "serde_path_to_error",
- "sha2",
- "thiserror",
- "url",
-]
-
 [[package]]
 [[package]]
 name = "objc"
 name = "objc"
 version = "0.2.7"
 version = "0.2.7"
@@ -6911,67 +6662,13 @@ dependencies = [
  "pathdiff",
  "pathdiff",
 ]
 ]
 
 
-[[package]]
-name = "openid_auth_demo"
-version = "0.1.0"
-dependencies = [
- "console_error_panic_hook",
- "dioxus",
- "dioxus-logger",
- "dioxus-router",
- "dioxus-web",
- "fermi",
- "form_urlencoded",
- "gloo-storage 0.3.0",
- "log",
- "openidconnect",
- "reqwest",
- "serde",
- "serde_json",
- "thiserror",
- "uuid",
- "web-sys",
-]
-
-[[package]]
-name = "openidconnect"
-version = "3.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62d6050f6a84b81f23c569f5607ad883293e57491036e318fafe6fc4895fadb1"
-dependencies = [
- "base64 0.13.1",
- "chrono",
- "dyn-clone",
- "ed25519-dalek",
- "hmac",
- "http 0.2.11",
- "itertools 0.10.5",
- "log",
- "oauth2",
- "p256",
- "p384",
- "rand 0.8.5",
- "rsa",
- "serde",
- "serde-value",
- "serde_derive",
- "serde_json",
- "serde_path_to_error",
- "serde_plain",
- "serde_with",
- "sha2",
- "subtle",
- "thiserror",
- "url",
-]
-
 [[package]]
 [[package]]
 name = "openssl"
 name = "openssl"
-version = "0.10.62"
+version = "0.10.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671"
+checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "cfg-if",
  "cfg-if",
  "foreign-types 0.3.2",
  "foreign-types 0.3.2",
  "libc",
  "libc",
@@ -6999,18 +6696,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
 
 
 [[package]]
 [[package]]
 name = "openssl-src"
 name = "openssl-src"
-version = "300.2.1+3.2.0"
+version = "300.2.2+3.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fe476c29791a5ca0d1273c697e96085bbabbbea2ef7afd5617e78a4b40332d3"
+checksum = "8bbfad0063610ac26ee79f7484739e2b07555a75c42453b89263830b5c8103bc"
 dependencies = [
 dependencies = [
  "cc",
  "cc",
 ]
 ]
 
 
 [[package]]
 [[package]]
 name = "openssl-sys"
 name = "openssl-sys"
-version = "0.9.98"
+version = "0.9.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7"
+checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae"
 dependencies = [
 dependencies = [
  "cc",
  "cc",
  "libc",
  "libc",
@@ -7075,30 +6772,6 @@ dependencies = [
  "supports-color",
  "supports-color",
 ]
 ]
 
 
-[[package]]
-name = "p256"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
-dependencies = [
- "ecdsa",
- "elliptic-curve",
- "primeorder",
- "sha2",
-]
-
-[[package]]
-name = "p384"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209"
-dependencies = [
- "ecdsa",
- "elliptic-curve",
- "primeorder",
- "sha2",
-]
-
 [[package]]
 [[package]]
 name = "pango"
 name = "pango"
 version = "0.18.3"
 version = "0.18.3"
@@ -7130,7 +6803,7 @@ version = "0.26.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "05d74befe2d076330d9a58bf9ca2da424568724ab278adf15fb5718253133887"
 checksum = "05d74befe2d076330d9a58bf9ca2da424568724ab278adf15fb5718253133887"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "cssparser 0.33.0",
  "cssparser 0.33.0",
  "fxhash",
  "fxhash",
  "log",
  "log",
@@ -7345,7 +7018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
 checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
 dependencies = [
 dependencies = [
  "fixedbitset",
  "fixedbitset",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -7365,9 +7038,7 @@ version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
 checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
 dependencies = [
 dependencies = [
- "phf_macros 0.10.0",
  "phf_shared 0.10.0",
  "phf_shared 0.10.0",
- "proc-macro-hack",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -7444,20 +7115,6 @@ dependencies = [
  "syn 1.0.109",
  "syn 1.0.109",
 ]
 ]
 
 
-[[package]]
-name = "phf_macros"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0"
-dependencies = [
- "phf_generator 0.10.0",
- "phf_shared 0.10.0",
- "proc-macro-hack",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
 [[package]]
 [[package]]
 name = "phf_macros"
 name = "phf_macros"
 version = "0.11.2"
 version = "0.11.2"
@@ -7500,18 +7157,18 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "pin-project"
 name = "pin-project"
-version = "1.1.3"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
+checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0"
 dependencies = [
 dependencies = [
  "pin-project-internal",
  "pin-project-internal",
 ]
 ]
 
 
 [[package]]
 [[package]]
 name = "pin-project-internal"
 name = "pin-project-internal"
-version = "1.1.3"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
+checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
 dependencies = [
 dependencies = [
  "proc-macro2",
  "proc-macro2",
  "quote",
  "quote",
@@ -7564,9 +7221,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "pkg-config"
 name = "pkg-config"
-version = "0.3.28"
+version = "0.3.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a"
+checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
 
 
 [[package]]
 [[package]]
 name = "plasmo"
 name = "plasmo"
@@ -7590,12 +7247,6 @@ dependencies = [
  "tokio",
  "tokio",
 ]
 ]
 
 
-[[package]]
-name = "platforms"
-version = "3.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c"
-
 [[package]]
 [[package]]
 name = "plist"
 name = "plist"
 version = "1.6.0"
 version = "1.6.0"
@@ -7603,7 +7254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef"
 checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef"
 dependencies = [
 dependencies = [
  "base64 0.21.7",
  "base64 0.21.7",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "line-wrap",
  "line-wrap",
  "quick-xml",
  "quick-xml",
  "serde",
  "serde",
@@ -7640,9 +7291,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "png"
 name = "png"
-version = "0.17.10"
+version = "0.17.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64"
+checksum = "1f6c3c3e617595665b8ea2ff95a86066be38fb121ff920a9c0eb282abcd1da5a"
 dependencies = [
 dependencies = [
  "bitflags 1.3.2",
  "bitflags 1.3.2",
  "crc32fast",
  "crc32fast",
@@ -7669,14 +7320,14 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "polling"
 name = "polling"
-version = "3.3.1"
+version = "3.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf63fa624ab313c11656b4cda960bfc46c410187ad493c41f6ba2d8c1e991c9e"
+checksum = "545c980a3880efd47b2e262f6a4bb6daad6555cf3367aa9c4e52895f69537a41"
 dependencies = [
 dependencies = [
  "cfg-if",
  "cfg-if",
  "concurrent-queue",
  "concurrent-queue",
  "pin-project-lite",
  "pin-project-lite",
- "rustix 0.38.28",
+ "rustix 0.38.31",
  "tracing",
  "tracing",
  "windows-sys 0.52.0",
  "windows-sys 0.52.0",
 ]
 ]
@@ -7757,15 +7408,6 @@ dependencies = [
  "syn 2.0.48",
  "syn 2.0.48",
 ]
 ]
 
 
-[[package]]
-name = "primeorder"
-version = "0.13.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
-dependencies = [
- "elliptic-curve",
-]
-
 [[package]]
 [[package]]
 name = "proc-macro-crate"
 name = "proc-macro-crate"
 version = "1.3.1"
 version = "1.3.1"
@@ -7782,7 +7424,16 @@ version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8"
 checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8"
 dependencies = [
 dependencies = [
- "toml_edit 0.20.2",
+ "toml_edit 0.20.7",
+]
+
+[[package]]
+name = "proc-macro-crate"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
+dependencies = [
+ "toml_edit 0.21.1",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -7817,9 +7468,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
 
 
 [[package]]
 [[package]]
 name = "proc-macro2"
 name = "proc-macro2"
-version = "1.0.76"
+version = "1.0.78"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
 dependencies = [
 dependencies = [
  "unicode-ident",
  "unicode-ident",
 ]
 ]
@@ -7845,18 +7496,18 @@ checksum = "794b5bf8e2d19b53dcdcec3e4bba628e20f5b6062503ba89281fa7037dd7bbcf"
 
 
 [[package]]
 [[package]]
 name = "profiling"
 name = "profiling"
-version = "1.0.13"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d135ede8821cf6376eb7a64148901e1690b788c11ae94dc297ae917dbc91dc0e"
+checksum = "0f0f7f43585c34e4fdd7497d746bc32e14458cf11c69341cc0587b1d825dde42"
 dependencies = [
 dependencies = [
  "profiling-procmacros",
  "profiling-procmacros",
 ]
 ]
 
 
 [[package]]
 [[package]]
 name = "profiling-procmacros"
 name = "profiling-procmacros"
-version = "1.0.13"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b322d7d65c1ab449be3c890fcbd0db6e1092d0dd05d79dba2dd28032cebeb05"
+checksum = "ce97fecd27bc49296e5e20518b5a1bb54a14f7d5fe6228bc9686ee2a74915cc8"
 dependencies = [
 dependencies = [
  "quote",
  "quote",
  "syn 2.0.48",
  "syn 2.0.48",
@@ -7891,16 +7542,6 @@ dependencies = [
  "bytemuck",
  "bytemuck",
 ]
 ]
 
 
-[[package]]
-name = "query_segments_demo"
-version = "0.1.0"
-dependencies = [
- "dioxus",
- "dioxus-router",
- "dioxus-web",
- "form_urlencoded",
-]
-
 [[package]]
 [[package]]
 name = "quick-error"
 name = "quick-error"
 version = "1.2.3"
 version = "1.2.3"
@@ -8034,27 +7675,18 @@ dependencies = [
  "rand_core 0.5.1",
  "rand_core 0.5.1",
 ]
 ]
 
 
-[[package]]
-name = "rand_xoshiro"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
-dependencies = [
- "rand_core 0.6.4",
-]
-
 [[package]]
 [[package]]
 name = "ratatui"
 name = "ratatui"
 version = "0.24.0"
 version = "0.24.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0ebc917cfb527a566c37ecb94c7e3fd098353516fb4eb6bea17015ade0182425"
 checksum = "0ebc917cfb527a566c37ecb94c7e3fd098353516fb4eb6bea17015ade0182425"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "cassowary",
  "cassowary",
  "crossterm 0.27.0",
  "crossterm 0.27.0",
  "indoc",
  "indoc",
  "itertools 0.11.0",
  "itertools 0.11.0",
- "lru 0.12.1",
+ "lru 0.12.2",
  "paste",
  "paste",
  "strum",
  "strum",
  "unicode-segmentation",
  "unicode-segmentation",
@@ -8114,7 +7746,7 @@ dependencies = [
  "cc",
  "cc",
  "cfg-if",
  "cfg-if",
  "interpolate_name",
  "interpolate_name",
- "itertools 0.12.0",
+ "itertools 0.12.1",
  "libc",
  "libc",
  "libfuzzer-sys 0.4.7",
  "libfuzzer-sys 0.4.7",
  "log",
  "log",
@@ -8165,9 +7797,9 @@ checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544"
 
 
 [[package]]
 [[package]]
 name = "rayon"
 name = "rayon"
-version = "1.8.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
+checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051"
 dependencies = [
 dependencies = [
  "either",
  "either",
  "rayon-core",
  "rayon-core",
@@ -8175,9 +7807,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "rayon-core"
 name = "rayon-core"
-version = "1.12.0"
+version = "1.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
 dependencies = [
 dependencies = [
  "crossbeam-deque",
  "crossbeam-deque",
  "crossbeam-utils",
  "crossbeam-utils",
@@ -8225,13 +7857,13 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "regex"
 name = "regex"
-version = "1.10.2"
+version = "1.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
+checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
 dependencies = [
 dependencies = [
  "aho-corasick 1.1.2",
  "aho-corasick 1.1.2",
  "memchr",
  "memchr",
- "regex-automata 0.4.3",
+ "regex-automata 0.4.5",
  "regex-syntax 0.8.2",
  "regex-syntax 0.8.2",
 ]
 ]
 
 
@@ -8246,9 +7878,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "regex-automata"
 name = "regex-automata"
-version = "0.4.3"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
+checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
 dependencies = [
 dependencies = [
  "aho-corasick 1.1.2",
  "aho-corasick 1.1.2",
  "memchr",
  "memchr",
@@ -8294,9 +7926,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "reqwest"
 name = "reqwest"
-version = "0.11.23"
+version = "0.11.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41"
+checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251"
 dependencies = [
 dependencies = [
  "base64 0.21.7",
  "base64 0.21.7",
  "bytes",
  "bytes",
@@ -8322,6 +7954,7 @@ dependencies = [
  "serde",
  "serde",
  "serde_json",
  "serde_json",
  "serde_urlencoded",
  "serde_urlencoded",
+ "sync_wrapper",
  "system-configuration",
  "system-configuration",
  "tokio",
  "tokio",
  "tokio-native-tls",
  "tokio-native-tls",
@@ -8348,16 +7981,6 @@ dependencies = [
  "quick-error 1.2.3",
  "quick-error 1.2.3",
 ]
 ]
 
 
-[[package]]
-name = "rfc6979"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
-dependencies = [
- "hmac",
- "subtle",
-]
-
 [[package]]
 [[package]]
 name = "rfd"
 name = "rfd"
 version = "0.12.1"
 version = "0.12.1"
@@ -8397,7 +8020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e3625f343d89990133d013e39c46e350915178cf94f1bec9f49b0cbef98a3e3c"
 checksum = "e3625f343d89990133d013e39c46e350915178cf94f1bec9f49b0cbef98a3e3c"
 dependencies = [
 dependencies = [
  "ahash 0.8.7",
  "ahash 0.8.7",
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "instant",
  "instant",
  "num-traits",
  "num-traits",
  "once_cell",
  "once_cell",
@@ -8495,7 +8118,7 @@ dependencies = [
  "either",
  "either",
  "figment",
  "figment",
  "futures",
  "futures",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "log",
  "log",
  "memchr",
  "memchr",
  "multer 2.1.0",
  "multer 2.1.0",
@@ -8526,7 +8149,7 @@ checksum = "a2238066abf75f21be6cd7dc1a09d5414a671f4246e384e49fe3f8a4936bd04c"
 dependencies = [
 dependencies = [
  "devise",
  "devise",
  "glob",
  "glob",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "proc-macro2",
  "proc-macro2",
  "quote",
  "quote",
  "rocket_http",
  "rocket_http",
@@ -8546,7 +8169,7 @@ dependencies = [
  "futures",
  "futures",
  "http 0.2.11",
  "http 0.2.11",
  "hyper 0.14.28",
  "hyper 0.14.28",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "log",
  "log",
  "memchr",
  "memchr",
  "pear",
  "pear",
@@ -8579,8 +8202,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
 checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
 dependencies = [
 dependencies = [
  "base64 0.21.7",
  "base64 0.21.7",
- "bitflags 2.4.1",
- "indexmap 2.1.0",
+ "bitflags 2.4.2",
+ "indexmap 2.2.2",
  "serde",
  "serde",
  "serde_derive",
  "serde_derive",
 ]
 ]
@@ -8656,9 +8279,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "rust_decimal"
 name = "rust_decimal"
-version = "1.33.1"
+version = "1.34.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06676aec5ccb8fc1da723cc8c0f9a46549f21ebb8753d3915c6c41db1e7f1dc4"
+checksum = "755392e1a2f77afd95580d3f0d0e94ac83eeeb7167552c9b5bca549e61a94d83"
 dependencies = [
 dependencies = [
  "arrayvec",
  "arrayvec",
  "borsh",
  "borsh",
@@ -8729,14 +8352,14 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "rustix"
 name = "rustix"
-version = "0.38.28"
+version = "0.38.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
+checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
 dependencies = [
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "errno",
  "errno",
  "libc",
  "libc",
- "linux-raw-sys 0.4.12",
+ "linux-raw-sys 0.4.13",
  "windows-sys 0.52.0",
  "windows-sys 0.52.0",
 ]
 ]
 
 
@@ -8835,7 +8458,7 @@ dependencies = [
  "bytes",
  "bytes",
  "flate2",
  "flate2",
  "futures-util",
  "futures-util",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "salvo_core",
  "salvo_core",
  "tokio",
  "tokio",
  "tokio-util",
  "tokio-util",
@@ -8900,7 +8523,7 @@ dependencies = [
  "http-body-util",
  "http-body-util",
  "hyper 1.1.0",
  "hyper 1.1.0",
  "hyper-util",
  "hyper-util",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "mime",
  "mime",
  "mime-infer",
  "mime-infer",
  "multer 3.0.0",
  "multer 3.0.0",
@@ -8998,23 +8621,6 @@ version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 
-[[package]]
-name = "scraper"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59e25654b5e9fd557a67dbaab5a5d36b8c448d0561beb4c041b6dbb902eddfa6"
-dependencies = [
- "ahash 0.8.7",
- "cssparser 0.29.6",
- "ego-tree",
- "getopts",
- "html5ever",
- "once_cell",
- "selectors 0.24.0",
- "smallvec",
- "tendril",
-]
-
 [[package]]
 [[package]]
 name = "sct"
 name = "sct"
 version = "0.7.1"
 version = "0.7.1"
@@ -9031,20 +8637,6 @@ version = "4.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
 checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
 
 
-[[package]]
-name = "sec1"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
-dependencies = [
- "base16ct",
- "der",
- "generic-array 0.14.7",
- "pkcs8",
- "subtle",
- "zeroize",
-]
-
 [[package]]
 [[package]]
 name = "security-framework"
 name = "security-framework"
 version = "2.9.2"
 version = "2.9.2"
@@ -9083,29 +8675,11 @@ dependencies = [
  "phf 0.8.0",
  "phf 0.8.0",
  "phf_codegen 0.8.0",
  "phf_codegen 0.8.0",
  "precomputed-hash",
  "precomputed-hash",
- "servo_arc 0.1.1",
+ "servo_arc",
  "smallvec",
  "smallvec",
  "thin-slice",
  "thin-slice",
 ]
 ]
 
 
-[[package]]
-name = "selectors"
-version = "0.24.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416"
-dependencies = [
- "bitflags 1.3.2",
- "cssparser 0.29.6",
- "derive_more",
- "fxhash",
- "log",
- "phf 0.8.0",
- "phf_codegen 0.8.0",
- "precomputed-hash",
- "servo_arc 0.2.0",
- "smallvec",
-]
-
 [[package]]
 [[package]]
 name = "semver"
 name = "semver"
 version = "1.0.21"
 version = "1.0.21"
@@ -9123,9 +8697,9 @@ checksum = "f97841a747eef040fcd2e7b3b9a220a7205926e60488e673d9e4926d27772ce5"
 
 
 [[package]]
 [[package]]
 name = "serde"
 name = "serde"
-version = "1.0.195"
+version = "1.0.196"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
+checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
 dependencies = [
 dependencies = [
  "serde_derive",
  "serde_derive",
 ]
 ]
@@ -9175,9 +8749,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "serde_derive"
 name = "serde_derive"
-version = "1.0.195"
+version = "1.0.196"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
+checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
 dependencies = [
 dependencies = [
  "proc-macro2",
  "proc-macro2",
  "quote",
  "quote",
@@ -9186,9 +8760,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "serde_json"
 name = "serde_json"
-version = "1.0.111"
+version = "1.0.113"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
+checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
 dependencies = [
 dependencies = [
  "itoa 1.0.10",
  "itoa 1.0.10",
  "ryu",
  "ryu",
@@ -9205,15 +8779,6 @@ dependencies = [
  "serde",
  "serde",
 ]
 ]
 
 
-[[package]]
-name = "serde_plain"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50"
-dependencies = [
- "serde",
-]
-
 [[package]]
 [[package]]
 name = "serde_qs"
 name = "serde_qs"
 version = "0.12.0"
 version = "0.12.0"
@@ -9269,15 +8834,15 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "serde_with"
 name = "serde_with"
-version = "3.4.0"
+version = "3.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
+checksum = "1b0ed1662c5a68664f45b76d18deb0e234aff37207086803165c961eb695e981"
 dependencies = [
 dependencies = [
  "base64 0.21.7",
  "base64 0.21.7",
  "chrono",
  "chrono",
  "hex",
  "hex",
  "indexmap 1.9.3",
  "indexmap 1.9.3",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "serde",
  "serde",
  "serde_json",
  "serde_json",
  "serde_with_macros",
  "serde_with_macros",
@@ -9286,9 +8851,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "serde_with_macros"
 name = "serde_with_macros"
-version = "3.4.0"
+version = "3.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788"
+checksum = "568577ff0ef47b879f736cd66740e022f3672788cdf002a05a4e609ea5a6fb15"
 dependencies = [
 dependencies = [
  "darling",
  "darling",
  "proc-macro2",
  "proc-macro2",
@@ -9298,9 +8863,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "server_fn"
 name = "server_fn"
-version = "0.5.4"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cfed18dfcc8d9004579c40482c3419c07f60ffb9c5b250542edca99f508b0ce9"
+checksum = "6c265de965fe48e09ad8899d0ab1ffebdfa1a9914e4de5ff107b07bd94cf7541"
 dependencies = [
 dependencies = [
  "ciborium",
  "ciborium",
  "const_format",
  "const_format",
@@ -9323,9 +8888,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "server_fn_macro"
 name = "server_fn_macro"
-version = "0.5.4"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b70ae8e22546ba85500391b36c08e3fba64871be8a26557a3663a8e08acb56f"
+checksum = "f77000541a62ceeec01eef3ee0f86c155c33dac5fae750ad04a40852c6d5469a"
 dependencies = [
 dependencies = [
  "const_format",
  "const_format",
  "proc-macro-error",
  "proc-macro-error",
@@ -9338,9 +8903,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "server_fn_macro_default"
 name = "server_fn_macro_default"
-version = "0.5.4"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7256ba61dfadb220598db418376e7bc2a34b96df36c4dc48f24ffe161810fc0b"
+checksum = "8a3353f22e2bcc451074d4feaa37317d9d17dff11d4311928384734ea17ab9ca"
 dependencies = [
 dependencies = [
  "server_fn_macro",
  "server_fn_macro",
  "syn 2.0.48",
  "syn 2.0.48",
@@ -9356,16 +8921,6 @@ dependencies = [
  "stable_deref_trait",
  "stable_deref_trait",
 ]
 ]
 
 
-[[package]]
-name = "servo_arc"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741"
-dependencies = [
- "nodrop",
- "stable_deref_trait",
-]
-
 [[package]]
 [[package]]
 name = "sha-1"
 name = "sha-1"
 version = "0.10.1"
 version = "0.10.1"
@@ -9531,16 +9086,6 @@ version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
 checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
 
 
-[[package]]
-name = "sized-chunks"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e"
-dependencies = [
- "bitmaps",
- "typenum",
-]
-
 [[package]]
 [[package]]
 name = "slab"
 name = "slab"
 version = "0.4.9"
 version = "0.4.9"
@@ -9580,17 +9125,11 @@ dependencies = [
  "version_check",
  "version_check",
 ]
 ]
 
 
-[[package]]
-name = "smallbox"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d92359f97e6b417da4328a970cf04a044db104fbd57f7d72cb7ff665bb8806af"
-
 [[package]]
 [[package]]
 name = "smallvec"
 name = "smallvec"
-version = "1.11.2"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
 
 
 [[package]]
 [[package]]
 name = "smartstring"
 name = "smartstring"
@@ -9689,7 +9228,7 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c"
 checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c"
 dependencies = [
 dependencies = [
- "itertools 0.12.0",
+ "itertools 0.12.1",
  "nom",
  "nom",
  "unicode_categories",
  "unicode_categories",
 ]
 ]
@@ -9732,7 +9271,7 @@ dependencies = [
  "futures-util",
  "futures-util",
  "hashlink",
  "hashlink",
  "hex",
  "hex",
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "ipnetwork",
  "ipnetwork",
  "log",
  "log",
  "mac_address",
  "mac_address",
@@ -9807,7 +9346,7 @@ dependencies = [
  "atoi",
  "atoi",
  "base64 0.21.7",
  "base64 0.21.7",
  "bigdecimal",
  "bigdecimal",
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "byteorder",
  "byteorder",
  "bytes",
  "bytes",
  "chrono",
  "chrono",
@@ -9855,7 +9394,7 @@ dependencies = [
  "base64 0.21.7",
  "base64 0.21.7",
  "bigdecimal",
  "bigdecimal",
  "bit-vec",
  "bit-vec",
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "byteorder",
  "byteorder",
  "chrono",
  "chrono",
  "crc",
  "crc",
@@ -9901,7 +9440,7 @@ checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490"
 dependencies = [
 dependencies = [
  "atoi",
  "atoi",
  "chrono",
  "chrono",
- "flume",
+ "flume 0.11.0",
  "futures-channel",
  "futures-channel",
  "futures-core",
  "futures-core",
  "futures-executor",
  "futures-executor",
@@ -9963,9 +9502,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 
 
 [[package]]
 [[package]]
 name = "str-buf"
 name = "str-buf"
-version = "3.0.2"
+version = "3.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e75b72ee54e2f93c3ea1354066162be893ee5e25773ab743de3e088cecbb4f31"
+checksum = "0ceb97b7225c713c2fd4db0153cb6b3cab244eb37900c3f634ed4d43310d8c34"
 
 
 [[package]]
 [[package]]
 name = "string_cache"
 name = "string_cache"
@@ -10128,7 +9667,7 @@ dependencies = [
  "cfg-expr 0.15.6",
  "cfg-expr 0.15.6",
  "heck 0.4.1",
  "heck 0.4.1",
  "pkg-config",
  "pkg-config",
- "toml 0.8.8",
+ "toml 0.8.9",
  "version-compare",
  "version-compare",
 ]
 ]
 
 
@@ -10146,9 +9685,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "tao"
 name = "tao"
-version = "0.24.0"
+version = "0.24.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c0dff18fed076d29cb5779e918ef4b8a5dbb756204e4a027794f0bce233d949"
+checksum = "75d4a64cfac8e487c61d778fe4ab8480f162451e8af7f247aafadcb3b2560852"
 dependencies = [
 dependencies = [
  "bitflags 1.3.2",
  "bitflags 1.3.2",
  "cc",
  "cc",
@@ -10308,7 +9847,7 @@ dependencies = [
  "cfg-if",
  "cfg-if",
  "fastrand 2.0.1",
  "fastrand 2.0.1",
  "redox_syscall",
  "redox_syscall",
- "rustix 0.38.28",
+ "rustix 0.38.31",
  "windows-sys 0.48.0",
  "windows-sys 0.48.0",
 ]
 ]
 
 
@@ -10389,9 +9928,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "tiff"
 name = "tiff"
-version = "0.9.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211"
+checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e"
 dependencies = [
 dependencies = [
  "flate2",
  "flate2",
  "jpeg-decoder",
  "jpeg-decoder",
@@ -10400,13 +9939,14 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "time"
 name = "time"
-version = "0.3.31"
+version = "0.3.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e"
+checksum = "fe80ced77cbfb4cb91a94bf72b378b4b6791a0d9b7f09d0be747d1bdff4e68bd"
 dependencies = [
 dependencies = [
  "deranged",
  "deranged",
  "itoa 1.0.10",
  "itoa 1.0.10",
  "libc",
  "libc",
+ "num-conv",
  "num_threads",
  "num_threads",
  "powerfmt",
  "powerfmt",
  "serde",
  "serde",
@@ -10422,10 +9962,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
 
 
 [[package]]
 [[package]]
 name = "time-macros"
 name = "time-macros"
-version = "0.2.16"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f"
+checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
 dependencies = [
 dependencies = [
+ "num-conv",
  "time-core",
  "time-core",
 ]
 ]
 
 
@@ -10471,9 +10012,9 @@ checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8"
 
 
 [[package]]
 [[package]]
 name = "tokio"
 name = "tokio"
-version = "1.35.1"
+version = "1.36.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
+checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
 dependencies = [
 dependencies = [
  "backtrace",
  "backtrace",
  "bytes",
  "bytes",
@@ -10617,15 +10158,15 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "toml"
 name = "toml"
-version = "0.8.8"
+version = "0.8.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35"
+checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325"
 dependencies = [
 dependencies = [
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "serde",
  "serde",
  "serde_spanned",
  "serde_spanned",
  "toml_datetime",
  "toml_datetime",
- "toml_edit 0.21.0",
+ "toml_edit 0.21.1",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -10643,7 +10184,7 @@ version = "0.19.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
 checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
 dependencies = [
 dependencies = [
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "serde",
  "serde",
  "serde_spanned",
  "serde_spanned",
  "toml_datetime",
  "toml_datetime",
@@ -10652,22 +10193,22 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "toml_edit"
 name = "toml_edit"
-version = "0.20.2"
+version = "0.20.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
+checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81"
 dependencies = [
 dependencies = [
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "toml_datetime",
  "toml_datetime",
  "winnow",
  "winnow",
 ]
 ]
 
 
 [[package]]
 [[package]]
 name = "toml_edit"
 name = "toml_edit"
-version = "0.21.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
+checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
 dependencies = [
 dependencies = [
- "indexmap 2.1.0",
+ "indexmap 2.2.2",
  "serde",
  "serde",
  "serde_spanned",
  "serde_spanned",
  "toml_datetime",
  "toml_datetime",
@@ -10744,9 +10285,9 @@ version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140"
 checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140"
 dependencies = [
 dependencies = [
- "async-compression 0.4.5",
+ "async-compression 0.4.6",
  "base64 0.21.7",
  "base64 0.21.7",
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "bytes",
  "bytes",
  "futures-core",
  "futures-core",
  "futures-util",
  "futures-util",
@@ -10923,9 +10464,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
 
 
 [[package]]
 [[package]]
 name = "trybuild"
 name = "trybuild"
-version = "1.0.88"
+version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76de4f783e610194f6c98bfd53f9fc52bb2e0d02c947621e8a0f4ecc799b2880"
+checksum = "9a9d3ba662913483d6722303f619e75ea10b7855b0f8e0d72799cf8621bb488f"
 dependencies = [
 dependencies = [
  "basic-toml",
  "basic-toml",
  "dissimilar",
  "dissimilar",
@@ -11023,18 +10564,20 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "ulid"
 name = "ulid"
-version = "1.1.0"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e37c4b6cbcc59a8dcd09a6429fbc7890286bcbb79215cea7b38a3c4c0921d93"
+checksum = "7e3c3b4dcec1e4729aab50688a1a0631483d79e65b194851425e7748287715a6"
 dependencies = [
 dependencies = [
+ "getrandom 0.2.12",
  "rand 0.8.5",
  "rand 0.8.5",
+ "web-time",
 ]
 ]
 
 
 [[package]]
 [[package]]
 name = "uncased"
 name = "uncased"
-version = "0.9.9"
+version = "0.9.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68"
+checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697"
 dependencies = [
 dependencies = [
  "serde",
  "serde",
  "version_check",
  "version_check",
@@ -11051,9 +10594,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "unicode-bidi"
 name = "unicode-bidi"
-version = "0.3.14"
+version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
 
 
 [[package]]
 [[package]]
 name = "unicode-bom"
 name = "unicode-bom"
@@ -11170,9 +10713,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 
 
 [[package]]
 [[package]]
 name = "uuid"
 name = "uuid"
-version = "1.6.1"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
+checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
 dependencies = [
 dependencies = [
  "getrandom 0.2.12",
  "getrandom 0.2.12",
  "serde",
  "serde",
@@ -11200,9 +10743,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
 
 
 [[package]]
 [[package]]
 name = "value-bag"
 name = "value-bag"
-version = "1.6.0"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cdbaf5e132e593e9fc1de6a15bbec912395b11fb9719e061cf64f804524c503"
+checksum = "126e423afe2dd9ac52142e7e9d5ce4135d7e13776c529d27fd6bc49f19e3280b"
 
 
 [[package]]
 [[package]]
 name = "vcpkg"
 name = "vcpkg"
@@ -11318,16 +10861,11 @@ name = "warp-hello-world"
 version = "0.1.0"
 version = "0.1.0"
 dependencies = [
 dependencies = [
  "dioxus",
  "dioxus",
- "dioxus-fullstack",
- "dioxus-web",
- "execute",
  "reqwest",
  "reqwest",
  "serde",
  "serde",
- "simple_logger",
  "tracing",
  "tracing",
  "tracing-subscriber",
  "tracing-subscriber",
  "tracing-wasm",
  "tracing-wasm",
- "warp",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -11344,9 +10882,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen"
 name = "wasm-bindgen"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
+checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
 dependencies = [
 dependencies = [
  "cfg-if",
  "cfg-if",
  "wasm-bindgen-macro",
  "wasm-bindgen-macro",
@@ -11354,9 +10892,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-backend"
 name = "wasm-bindgen-backend"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
+checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
 dependencies = [
 dependencies = [
  "bumpalo",
  "bumpalo",
  "log",
  "log",
@@ -11369,9 +10907,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-cli-support"
 name = "wasm-bindgen-cli-support"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf8226e223e2dfbe8f921b7f20b82d1b5d86a6b143e9d6286cca8edd16695583"
+checksum = "a875870b7b39024cbca8f61a0e1fc8edfe7ac02b484e5a9bcea64374050a850e"
 dependencies = [
 dependencies = [
  "anyhow",
  "anyhow",
  "base64 0.9.3",
  "base64 0.9.3",
@@ -11391,9 +10929,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-externref-xform"
 name = "wasm-bindgen-externref-xform"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8a719be856d8b0802c7195ca26ee6eb02cb9639a12b80be32db960ce9640cb8"
+checksum = "04c5d468dc79cfd824d181c386f34c2e7ea521ea5855ddd95af8f4cf3fa676f4"
 dependencies = [
 dependencies = [
  "anyhow",
  "anyhow",
  "walrus",
  "walrus",
@@ -11401,9 +10939,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-futures"
 name = "wasm-bindgen-futures"
-version = "0.4.39"
+version = "0.4.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12"
+checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461"
 dependencies = [
 dependencies = [
  "cfg-if",
  "cfg-if",
  "js-sys",
  "js-sys",
@@ -11413,9 +10951,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-macro"
 name = "wasm-bindgen-macro"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
+checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
 dependencies = [
 dependencies = [
  "quote",
  "quote",
  "wasm-bindgen-macro-support",
  "wasm-bindgen-macro-support",
@@ -11423,9 +10961,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-macro-support"
 name = "wasm-bindgen-macro-support"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
+checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
 dependencies = [
 dependencies = [
  "proc-macro2",
  "proc-macro2",
  "quote",
  "quote",
@@ -11436,9 +10974,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-multi-value-xform"
 name = "wasm-bindgen-multi-value-xform"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a12766255d4b9026700376cc81894eeb62903e4414cbc94675f6f9babd9cfb76"
+checksum = "65f10c037dad45759d53b598d4737acdced90a0945023c8c6cd8d67b4b3e4eaf"
 dependencies = [
 dependencies = [
  "anyhow",
  "anyhow",
  "walrus",
  "walrus",
@@ -11446,15 +10984,15 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-shared"
 name = "wasm-bindgen-shared"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
+checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-test"
 name = "wasm-bindgen-test"
-version = "0.3.39"
+version = "0.3.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cf9242c0d27999b831eae4767b2a146feb0b27d332d553e605864acd2afd403"
+checksum = "139bd73305d50e1c1c4333210c0db43d989395b64a237bd35c10ef3832a7f70c"
 dependencies = [
 dependencies = [
  "console_error_panic_hook",
  "console_error_panic_hook",
  "js-sys",
  "js-sys",
@@ -11466,9 +11004,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-test-macro"
 name = "wasm-bindgen-test-macro"
-version = "0.3.39"
+version = "0.3.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89"
+checksum = "70072aebfe5da66d2716002c729a14e4aec4da0e23cc2ea66323dac541c93928"
 dependencies = [
 dependencies = [
  "proc-macro2",
  "proc-macro2",
  "quote",
  "quote",
@@ -11477,9 +11015,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-threads-xform"
 name = "wasm-bindgen-threads-xform"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c2b14c5b9c2c7aa9dd1eb7161857de9783f40e98582e7f41f2d7c04ffdc155"
+checksum = "16ddf1a4beb1bceb2b73c2325581901ca2cd92af628f24389a678854dcd65b24"
 dependencies = [
 dependencies = [
  "anyhow",
  "anyhow",
  "walrus",
  "walrus",
@@ -11488,9 +11026,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-wasm-conventions"
 name = "wasm-bindgen-wasm-conventions"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaedf88769cb23c6fd2e3bfed65bcbff6c5d92c8336afbd80d2dfcc8eb5cf047"
+checksum = "93f13ed8ccdac31eadcfd4c9b2ec7bd43e77454b14acb1f43189f2875a9b0391"
 dependencies = [
 dependencies = [
  "anyhow",
  "anyhow",
  "walrus",
  "walrus",
@@ -11498,9 +11036,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-bindgen-wasm-interpreter"
 name = "wasm-bindgen-wasm-interpreter"
-version = "0.2.89"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8a79039df1e0822e6d66508ec86052993deac201e26060f62abcd85e1daf951"
+checksum = "c4282a271772a3063d4057c1144e118254f207fbbc1381b8d50b23c25585d893"
 dependencies = [
 dependencies = [
  "anyhow",
  "anyhow",
  "log",
  "log",
@@ -11530,9 +11068,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "wasm-streams"
 name = "wasm-streams"
-version = "0.3.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7"
+checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129"
 dependencies = [
 dependencies = [
  "futures-util",
  "futures-util",
  "js-sys",
  "js-sys",
@@ -11549,9 +11087,19 @@ checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b"
 
 
 [[package]]
 [[package]]
 name = "web-sys"
 name = "web-sys"
-version = "0.3.66"
+version = "0.3.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "web-time"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f"
+checksum = "2ee269d72cc29bf77a2c4bc689cc750fb39f5cbd493d2205bbb3f5c7779cf7b0"
 dependencies = [
 dependencies = [
  "js-sys",
  "js-sys",
  "wasm-bindgen",
  "wasm-bindgen",
@@ -11639,9 +11187,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "webpki-roots"
 name = "webpki-roots"
-version = "0.25.3"
+version = "0.25.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
+checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
 
 
 [[package]]
 [[package]]
 name = "webview2-com"
 name = "webview2-com"
@@ -11681,9 +11229,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "weezl"
 name = "weezl"
-version = "0.1.7"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
+checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
 
 
 [[package]]
 [[package]]
 name = "which"
 name = "which"
@@ -11694,7 +11242,7 @@ dependencies = [
  "either",
  "either",
  "home",
  "home",
  "once_cell",
  "once_cell",
- "rustix 0.38.28",
+ "rustix 0.38.31",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -12001,9 +11549,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
 
 
 [[package]]
 [[package]]
 name = "winnow"
 name = "winnow"
-version = "0.5.34"
+version = "0.5.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16"
+checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5"
 dependencies = [
 dependencies = [
  "memchr",
  "memchr",
 ]
 ]
@@ -12095,13 +11643,13 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "xattr"
 name = "xattr"
-version = "1.2.0"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "914566e6413e7fa959cc394fb30e563ba80f3541fbd40816d4c05a0fc3f2a0f1"
+checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
 dependencies = [
 dependencies = [
  "libc",
  "libc",
- "linux-raw-sys 0.4.12",
- "rustix 0.38.28",
+ "linux-raw-sys 0.4.13",
+ "rustix 0.38.31",
 ]
 ]
 
 
 [[package]]
 [[package]]

+ 57 - 31
Cargo.toml

@@ -2,10 +2,12 @@
 resolver = "2"
 resolver = "2"
 members = [
 members = [
     "packages/dioxus",
     "packages/dioxus",
+    "packages/dioxus-lib",
     "packages/core",
     "packages/core",
     "packages/cli",
     "packages/cli",
     "packages/cli-config",
     "packages/cli-config",
     "packages/core-macro",
     "packages/core-macro",
+    "packages/config-macro",
     "packages/router-macro",
     "packages/router-macro",
     "packages/extension",
     "packages/extension",
     "packages/router",
     "packages/router",
@@ -17,13 +19,12 @@ members = [
     "packages/desktop",
     "packages/desktop",
     "packages/mobile",
     "packages/mobile",
     "packages/interpreter",
     "packages/interpreter",
-    "packages/fermi",
     "packages/liveview",
     "packages/liveview",
     "packages/autofmt",
     "packages/autofmt",
     "packages/check",
     "packages/check",
     "packages/rsx",
     "packages/rsx",
     "packages/dioxus-tui",
     "packages/dioxus-tui",
-    "packages/rink",
+    "packages/plasmo",
     "packages/native-core",
     "packages/native-core",
     "packages/native-core-macro",
     "packages/native-core-macro",
     "packages/rsx-rosetta",
     "packages/rsx-rosetta",
@@ -42,14 +43,13 @@ members = [
     # Full project examples
     # Full project examples
     "examples/tailwind",
     "examples/tailwind",
     "examples/PWA-example",
     "examples/PWA-example",
-    "examples/query_segments_demo",
-    "examples/openid_connect_demo",
+    # "examples/openid_connect_demo",
     # Playwright tests
     # Playwright tests
-    "playwright-tests/liveview",
-    "playwright-tests/web",
-    "playwright-tests/fullstack",
+    "packages/playwright-tests/liveview",
+    "packages/playwright-tests/web",
+    "packages/playwright-tests/fullstack",
 ]
 ]
-exclude = ["examples/mobile_demo"]
+exclude = ["examples/mobile_demo", "examples/openid_connect_demo",]
 
 
 [workspace.package]
 [workspace.package]
 version = "0.4.3"
 version = "0.4.3"
@@ -57,25 +57,26 @@ version = "0.4.3"
 # dependencies that are shared across packages
 # dependencies that are shared across packages
 [workspace.dependencies]
 [workspace.dependencies]
 dioxus = { path = "packages/dioxus", version = "0.4.0" }
 dioxus = { path = "packages/dioxus", version = "0.4.0" }
+dioxus-lib = { path = "packages/dioxus-lib", version = "0.4.0" }
 dioxus-core = { path = "packages/core", version = "0.4.2" }
 dioxus-core = { path = "packages/core", version = "0.4.2" }
-dioxus-core-macro = { path = "packages/core-macro", version = "0.4.0"  }
+dioxus-core-macro = { path = "packages/core-macro", version = "0.4.0" }
+dioxus-config-macro = { path = "packages/config-macro", version = "0.4.0" }
 dioxus-router = { path = "packages/router", version = "0.4.1"  }
 dioxus-router = { path = "packages/router", version = "0.4.1"  }
 dioxus-router-macro = { path = "packages/router-macro", version = "0.4.1" }
 dioxus-router-macro = { path = "packages/router-macro", version = "0.4.1" }
-dioxus-html = { path = "packages/html", default-features = false, version = "0.4.0"  }
+dioxus-html = { path = "packages/html", version = "0.4.0"  }
 dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.4.0"  }
 dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.4.0"  }
 dioxus-hooks = { path = "packages/hooks", version = "0.4.0" }
 dioxus-hooks = { path = "packages/hooks", version = "0.4.0" }
-dioxus-web = { path = "packages/web", version = "0.4.0"  }
-dioxus-ssr = { path = "packages/ssr", version = "0.4.0"  }
-dioxus-desktop = { path = "packages/desktop", version = "0.4.0"  }
+dioxus-web = { path = "packages/web", version = "0.4.0" }
+dioxus-ssr = { path = "packages/ssr", version = "0.4.0", default-features = false }
+dioxus-desktop = { path = "packages/desktop", version = "0.4.0" }
 dioxus-mobile = { path = "packages/mobile", version = "0.4.0"  }
 dioxus-mobile = { path = "packages/mobile", version = "0.4.0"  }
 dioxus-interpreter-js = { path = "packages/interpreter", version = "0.4.0" }
 dioxus-interpreter-js = { path = "packages/interpreter", version = "0.4.0" }
-fermi = { path = "packages/fermi", version = "0.4.0"  }
 dioxus-liveview = { path = "packages/liveview", version = "0.4.0"  }
 dioxus-liveview = { path = "packages/liveview", version = "0.4.0"  }
 dioxus-autofmt = { path = "packages/autofmt", version = "0.4.0"  }
 dioxus-autofmt = { path = "packages/autofmt", version = "0.4.0"  }
 dioxus-check = { path = "packages/check", version = "0.4.0"  }
 dioxus-check = { path = "packages/check", version = "0.4.0"  }
 dioxus-rsx = { path = "packages/rsx", version = "0.4.0"  }
 dioxus-rsx = { path = "packages/rsx", version = "0.4.0"  }
 dioxus-tui = { path = "packages/dioxus-tui", version = "0.4.0"  }
 dioxus-tui = { path = "packages/dioxus-tui", version = "0.4.0"  }
-plasmo = { path = "packages/rink", version = "0.4.0" }
+plasmo = { path = "packages/plasmo", version = "0.4.0" }
 dioxus-native-core = { path = "packages/native-core", version = "0.4.0" }
 dioxus-native-core = { path = "packages/native-core", version = "0.4.0" }
 dioxus-native-core-macro = { path = "packages/native-core-macro", version = "0.4.0" }
 dioxus-native-core-macro = { path = "packages/native-core-macro", version = "0.4.0" }
 rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.4.0" }
 rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.4.0" }
@@ -120,28 +121,53 @@ keywords = ["dom", "ui", "gui", "react", "wasm"]
 rust-version = "1.60.0"
 rust-version = "1.60.0"
 publish = false
 publish = false
 
 
+[dependencies]
+manganis = { workspace = true, optional = true}
+reqwest = { version = "0.11.9", features = ["json"], optional = true}
+http-range = {version = "0.1.5", optional = true }
+
 [dev-dependencies]
 [dev-dependencies]
-dioxus = { workspace = true }
-dioxus-desktop = { workspace = true, features = ["transparent"] }
+dioxus = { workspace = true, features = ["router"]}
 dioxus-ssr = { workspace = true }
 dioxus-ssr = { workspace = true }
-dioxus-router = { workspace = true }
-dioxus-signals = { workspace = true }
-fermi = { workspace = true }
 futures-util = "0.3.21"
 futures-util = "0.3.21"
-log = "0.4.14"
-num-format = "0.4.0"
 separator = "0.4.1"
 separator = "0.4.1"
 serde = { version = "1.0.136", features = ["derive"] }
 serde = { version = "1.0.136", features = ["derive"] }
-im-rc = "15.0.0"
-anyhow = "1.0.53"
 serde_json = "1.0.79"
 serde_json = "1.0.79"
 rand = { version = "0.8.4", features = ["small_rng"] }
 rand = { version = "0.8.4", features = ["small_rng"] }
+form_urlencoded = "1.2.0"
+
+[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
+getrandom = { version = "0.2.12", features = ["js"] }
+
+[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
 tokio = { version = "1.16.1", features = ["full"] }
 tokio = { version = "1.16.1", features = ["full"] }
-reqwest = { version = "0.11.9", features = ["json"] }
-env_logger = "0.10.0"
-simple_logger = "4.0.0"
-thiserror = { workspace = true }
-manganis = { workspace = true }
-tracing-subscriber = "0.3.17"
-http-range = "0.1.5"
 
 
+# To make most examples faster to compile, we split out assets and http-related stuff
+# This trims off like 270 dependencies, leading to a significant speedup in compilation time
+[features]
+liveview = ["dioxus/liveview"]
+fullstack = ["dioxus/fullstack"]
+axum = ["dioxus/axum"]
+salvo = ["dioxus/salvo"]
+rocket = ["dioxus/rocket"]
+server = ["dioxus/axum"]
+default = ["dioxus/desktop"]
+web = ["dioxus/web"]
+collect-assets = ["manganis"]
+http = ["reqwest", "http-range"]
+
+[[example]]
+name = "login_form"
+required-features = ["http"]
+
+[[example]]
+name = "dog_app"
+required-features = ["http"]
+
+[[example]]
+name = "video_stream"
+required-features = ["http"]
+
+[[example]]
+name = "suspense"
+required-features = ["http"]

+ 7 - 4
README.md

@@ -52,17 +52,20 @@
 
 
 <br/>
 <br/>
 
 
+> [!WARNING]
+> Dioxus 0.5 (currently in master) contains massive breaking changes and is not compatible with Dioxus 0.4
+
 Dioxus is a portable, performant, and ergonomic framework for building cross-platform user interfaces in Rust.
 Dioxus is a portable, performant, and ergonomic framework for building cross-platform user interfaces in Rust.
 
 
 ```rust
 ```rust
-fn app(cx: Scope) -> Element {
-    let mut count = use_state(cx, || 0);
+fn app() -> Element {
+    let mut count = use_signal(|| 0);
 
 
-    cx.render(rsx! {
+    rsx! {
         h1 { "High-Five counter: {count}" }
         h1 { "High-Five counter: {count}" }
         button { onclick: move |_| count += 1, "Up high!" }
         button { onclick: move |_| count += 1, "Up high!" }
         button { onclick: move |_| count -= 1, "Down low!" }
         button { onclick: move |_| count -= 1, "Down low!" }
-    })
+    }
 }
 }
 ```
 ```
 
 

+ 8 - 7
examples/PWA-example/src/main.rs

@@ -5,16 +5,17 @@ fn main() {
     wasm_logger::init(wasm_logger::Config::default());
     wasm_logger::init(wasm_logger::Config::default());
     console_error_panic_hook::set_once();
     console_error_panic_hook::set_once();
 
 
-    dioxus_web::launch(app);
+    launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! (
-        div {
-            style: "text-align: center;",
+fn app() -> Element {
+    rsx! (
+        div { style: "text-align: center;",
             h1 { "🌗 Dioxus 🚀" }
             h1 { "🌗 Dioxus 🚀" }
             h3 { "Frontend that scales." }
             h3 { "Frontend that scales." }
-            p { "Dioxus is a portable, performant, and ergonomic framework for building cross-platform user interfaces in Rust." }
+            p {
+                "Dioxus is a portable, performant, and ergonomic framework for building cross-platform user interfaces in Rust."
+            }
         }
         }
-    ))
+    )
 }
 }

+ 0 - 413
examples/all_css.rs

@@ -1,413 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
-    dioxus_desktop::launch(app);
-}
-
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
-        div {
-            align_content: "a",
-            align_items: "a",
-            align_self: "a",
-            alignment_adjust: "a",
-            alignment_baseline: "a",
-            all: "a",
-            alt: "a",
-            animation: "a",
-            animation_delay: "a",
-            animation_direction: "a",
-            animation_duration: "a",
-            animation_fill_mode: "a",
-            animation_iteration_count: "a",
-            animation_name: "a",
-            animation_play_state: "a",
-            animation_timing_function: "a",
-            azimuth: "a",
-            backface_visibility: "a",
-            background: "a",
-            background_attachment: "a",
-            background_clip: "a",
-            background_color: "a",
-            background_image: "a",
-            background_origin: "a",
-            background_position: "a",
-            background_repeat: "a",
-            background_size: "a",
-            background_blend_mode: "a",
-            baseline_shift: "a",
-            bleed: "a",
-            bookmark_label: "a",
-            bookmark_level: "a",
-            bookmark_state: "a",
-            border: "a",
-            border_color: "a",
-            border_style: "a",
-            border_width: "a",
-            border_bottom: "a",
-            border_bottom_color: "a",
-            border_bottom_style: "a",
-            border_bottom_width: "a",
-            border_left: "a",
-            border_left_color: "a",
-            border_left_style: "a",
-            border_left_width: "a",
-            border_right: "a",
-            border_right_color: "a",
-            border_right_style: "a",
-            border_right_width: "a",
-            border_top: "a",
-            border_top_color: "a",
-            border_top_style: "a",
-            border_top_width: "a",
-            border_collapse: "a",
-            border_image: "a",
-            border_image_outset: "a",
-            border_image_repeat: "a",
-            border_image_slice: "a",
-            border_image_source: "a",
-            border_image_width: "a",
-            border_radius: "a",
-            border_bottom_left_radius: "a",
-            border_bottom_right_radius: "a",
-            border_top_left_radius: "a",
-            border_top_right_radius: "a",
-            border_spacing: "a",
-            bottom: "a",
-            box_decoration_break: "a",
-            box_shadow: "a",
-            box_sizing: "a",
-            box_snap: "a",
-            break_after: "a",
-            break_before: "a",
-            break_inside: "a",
-            buffered_rendering: "a",
-            caption_side: "a",
-            clear: "a",
-            clear_side: "a",
-            clip: "a",
-            clip_path: "a",
-            clip_rule: "a",
-            color: "a",
-            color_adjust: "a",
-            color_correction: "a",
-            color_interpolation: "a",
-            color_interpolation_filters: "a",
-            color_profile: "a",
-            color_rendering: "a",
-            column_fill: "a",
-            column_gap: "a",
-            column_rule: "a",
-            column_rule_color: "a",
-            column_rule_style: "a",
-            column_rule_width: "a",
-            column_span: "a",
-            columns: "a",
-            column_count: "a",
-            column_width: "a",
-            contain: "a",
-            content: "a",
-            counter_increment: "a",
-            counter_reset: "a",
-            counter_set: "a",
-            cue: "a",
-            cue_after: "a",
-            cue_before: "a",
-            cursor: "a",
-            direction: "a",
-            display: "a",
-            display_inside: "a",
-            display_outside: "a",
-            display_extras: "a",
-            display_box: "a",
-            dominant_baseline: "a",
-            elevation: "a",
-            empty_cells: "a",
-            enable_background: "a",
-            fill: "a",
-            fill_opacity: "a",
-            fill_rule: "a",
-            filter: "a",
-            float: "a",
-            float_defer_column: "a",
-            float_defer_page: "a",
-            float_offset: "a",
-            float_wrap: "a",
-            flow_into: "a",
-            flow_from: "a",
-            flex: "a",
-            flex_basis: "a",
-            flex_grow: "a",
-            flex_shrink: "a",
-            flex_flow: "a",
-            flex_direction: "a",
-            flex_wrap: "a",
-            flood_color: "a",
-            flood_opacity: "a",
-            font: "a",
-            font_family: "a",
-            font_size: "a",
-            font_stretch: "a",
-            font_style: "a",
-            font_weight: "a",
-            font_feature_settings: "a",
-            font_kerning: "a",
-            font_language_override: "a",
-            font_size_adjust: "a",
-            font_synthesis: "a",
-            font_variant: "a",
-            font_variant_alternates: "a",
-            font_variant_caps: "a",
-            font_variant_east_asian: "a",
-            font_variant_ligatures: "a",
-            font_variant_numeric: "a",
-            font_variant_position: "a",
-            footnote_policy: "a",
-            glyph_orientation_horizontal: "a",
-            glyph_orientation_vertical: "a",
-            grid: "a",
-            grid_auto_flow: "a",
-            grid_auto_columns: "a",
-            grid_auto_rows: "a",
-            grid_template: "a",
-            grid_template_areas: "a",
-            grid_template_columns: "a",
-            grid_template_rows: "a",
-            grid_area: "a",
-            grid_column: "a",
-            grid_column_start: "a",
-            grid_column_end: "a",
-            grid_row: "a",
-            grid_row_start: "a",
-            grid_row_end: "a",
-            hanging_punctuation: "a",
-            height: "a",
-            hyphenate_character: "a",
-            hyphenate_limit_chars: "a",
-            hyphenate_limit_last: "a",
-            hyphenate_limit_lines: "a",
-            hyphenate_limit_zone: "a",
-            hyphens: "a",
-            icon: "a",
-            image_orientation: "a",
-            image_resolution: "a",
-            image_rendering: "a",
-            ime: "a",
-            ime_align: "a",
-            ime_mode: "a",
-            ime_offset: "a",
-            ime_width: "a",
-            initial_letters: "a",
-            inline_box_align: "a",
-            isolation: "a",
-            justify_content: "a",
-            justify_items: "a",
-            justify_self: "a",
-            kerning: "a",
-            left: "a",
-            letter_spacing: "a",
-            lighting_color: "a",
-            line_box_contain: "a",
-            line_break: "a",
-            line_grid: "a",
-            line_height: "a",
-            line_slack: "a",
-            line_snap: "a",
-            list_style: "a",
-            list_style_image: "a",
-            list_style_position: "a",
-            list_style_type: "a",
-            margin: "a",
-            margin_bottom: "a",
-            margin_left: "a",
-            margin_right: "a",
-            margin_top: "a",
-            marker: "a",
-            marker_end: "a",
-            marker_mid: "a",
-            marker_pattern: "a",
-            marker_segment: "a",
-            marker_start: "a",
-            marker_knockout_left: "a",
-            marker_knockout_right: "a",
-            marker_side: "a",
-            marks: "a",
-            marquee_direction: "a",
-            marquee_play_count: "a",
-            marquee_speed: "a",
-            marquee_style: "a",
-            mask: "a",
-            mask_image: "a",
-            mask_repeat: "a",
-            mask_position: "a",
-            mask_clip: "a",
-            mask_origin: "a",
-            mask_size: "a",
-            mask_box: "a",
-            mask_box_outset: "a",
-            mask_box_repeat: "a",
-            mask_box_slice: "a",
-            mask_box_source: "a",
-            mask_box_width: "a",
-            mask_type: "a",
-            max_height: "a",
-            max_lines: "a",
-            max_width: "a",
-            min_height: "a",
-            min_width: "a",
-            mix_blend_mode: "a",
-            nav_down: "a",
-            nav_index: "a",
-            nav_left: "a",
-            nav_right: "a",
-            nav_up: "a",
-            object_fit: "a",
-            object_position: "a",
-            offset_after: "a",
-            offset_before: "a",
-            offset_end: "a",
-            offset_start: "a",
-            opacity: "a",
-            order: "a",
-            orphans: "a",
-            outline: "a",
-            outline_color: "a",
-            outline_style: "a",
-            outline_width: "a",
-            outline_offset: "a",
-            overflow: "a",
-            overflow_x: "a",
-            overflow_y: "a",
-            overflow_style: "a",
-            overflow_wrap: "a",
-            padding: "a",
-            padding_bottom: "a",
-            padding_left: "a",
-            padding_right: "a",
-            padding_top: "a",
-            page: "a",
-            page_break_after: "a",
-            page_break_before: "a",
-            page_break_inside: "a",
-            paint_order: "a",
-            pause: "a",
-            pause_after: "a",
-            pause_before: "a",
-            perspective: "a",
-            perspective_origin: "a",
-            pitch: "a",
-            pitch_range: "a",
-            play_during: "a",
-            pointer_events: "a",
-            position: "a",
-            quotes: "a",
-            region_fragment: "a",
-            resize: "a",
-            rest: "a",
-            rest_after: "a",
-            rest_before: "a",
-            richness: "a",
-            right: "a",
-            ruby_align: "a",
-            ruby_merge: "a",
-            ruby_position: "a",
-            scroll_behavior: "a",
-            scroll_snap_coordinate: "a",
-            scroll_snap_destination: "a",
-            scroll_snap_points_x: "a",
-            scroll_snap_points_y: "a",
-            scroll_snap_type: "a",
-            shape_image_threshold: "a",
-            shape_inside: "a",
-            shape_margin: "a",
-            shape_outside: "a",
-            shape_padding: "a",
-            shape_rendering: "a",
-            size: "a",
-            speak: "a",
-            speak_as: "a",
-            speak_header: "a",
-            speak_numeral: "a",
-            speak_punctuation: "a",
-            speech_rate: "a",
-            stop_color: "a",
-            stop_opacity: "a",
-            stress: "a",
-            string_set: "a",
-            stroke: "a",
-            stroke_dasharray: "a",
-            stroke_dashoffset: "a",
-            stroke_linecap: "a",
-            stroke_linejoin: "a",
-            stroke_miterlimit: "a",
-            stroke_opacity: "a",
-            stroke_width: "a",
-            tab_size: "a",
-            table_layout: "a",
-            text_align: "a",
-            text_align_all: "a",
-            text_align_last: "a",
-            text_anchor: "a",
-            text_combine_upright: "a",
-            text_decoration: "a",
-            text_decoration_color: "a",
-            text_decoration_line: "a",
-            text_decoration_style: "a",
-            text_decoration_skip: "a",
-            text_emphasis: "a",
-            text_emphasis_color: "a",
-            text_emphasis_style: "a",
-            text_emphasis_position: "a",
-            text_emphasis_skip: "a",
-            text_height: "a",
-            text_indent: "a",
-            text_justify: "a",
-            text_orientation: "a",
-            text_overflow: "a",
-            text_rendering: "a",
-            text_shadow: "a",
-            text_size_adjust: "a",
-            text_space_collapse: "a",
-            text_spacing: "a",
-            text_transform: "a",
-            text_underline_position: "a",
-            text_wrap: "a",
-            top: "a",
-            touch_action: "a",
-            transform: "a",
-            transform_box: "a",
-            transform_origin: "a",
-            transform_style: "a",
-            transition: "a",
-            transition_delay: "a",
-            transition_duration: "a",
-            transition_property: "a",
-            unicode_bidi: "a",
-            vector_effect: "a",
-            vertical_align: "a",
-            visibility: "a",
-            voice_balance: "a",
-            voice_duration: "a",
-            voice_family: "a",
-            voice_pitch: "a",
-            voice_range: "a",
-            voice_rate: "a",
-            voice_stress: "a",
-            voice_volumn: "a",
-            volume: "a",
-            white_space: "a",
-            widows: "a",
-            width: "a",
-            will_change: "a",
-            word_break: "a",
-            word_spacing: "a",
-            word_wrap: "a",
-            wrap_flow: "a",
-            wrap_through: "a",
-            writing_mode: "a",
-            z_index: "a",
-
-            "This example isn't quite useful yet"
-        }
-    })
-}

+ 36 - 55
examples/all_events.rs

@@ -1,78 +1,59 @@
-use dioxus::{events::*, html::MouseEvent, prelude::*};
+use dioxus::prelude::*;
+use std::{collections::VecDeque, fmt::Debug, rc::Rc};
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
-}
-
-#[derive(Debug)]
-enum Event {
-    MouseMove(MouseEvent),
-    MouseClick(MouseEvent),
-    MouseDoubleClick(MouseEvent),
-    MouseDown(MouseEvent),
-    MouseUp(MouseEvent),
-
-    Wheel(WheelEvent),
-
-    KeyDown(KeyboardEvent),
-    KeyUp(KeyboardEvent),
-    KeyPress(KeyboardEvent),
-
-    FocusIn(FocusEvent),
-    FocusOut(FocusEvent),
+    launch(app);
 }
 }
 
 
 const MAX_EVENTS: usize = 8;
 const MAX_EVENTS: usize = 8;
 
 
 const CONTAINER_STYLE: &str = r#"
 const CONTAINER_STYLE: &str = r#"
-        display: flex;
-        flex-direction: column;
-        align-items: center;
-    "#;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+"#;
 
 
 const RECT_STYLE: &str = r#"
 const RECT_STYLE: &str = r#"
-        background: deepskyblue;
-        height: 50vh;
-        width: 50vw;
-        color: white;
-        padding: 20px;
-        margin: 20px;
-        text-aligh: center;
-    "#;
-
-fn app(cx: Scope) -> Element {
-    let events = use_ref(cx, std::collections::VecDeque::new);
-
-    let log_event = move |event: Event| {
+    background: deepskyblue;
+    height: 50vh;
+    width: 50vw;
+    color: white;
+    padding: 20px;
+    margin: 20px;
+    text-aligh: center;
+"#;
+
+fn app() -> Element {
+    let mut events = use_signal(|| VecDeque::new() as VecDeque<Rc<dyn Debug>>);
+
+    let mut log_event = move |event: Rc<dyn Debug>| {
         let mut events = events.write();
         let mut events = events.write();
 
 
         if events.len() >= MAX_EVENTS {
         if events.len() >= MAX_EVENTS {
             events.pop_front();
             events.pop_front();
         }
         }
+
         events.push_back(event);
         events.push_back(event);
     };
     };
 
 
-    cx.render(rsx! (
+    rsx! {
         div { style: "{CONTAINER_STYLE}",
         div { style: "{CONTAINER_STYLE}",
-            div {
-                style: "{RECT_STYLE}",
-                // focusing is necessary to catch keyboard events
-                tabindex: "0",
-
-                onmousemove: move |event| log_event(Event::MouseMove(event)),
-                onclick: move |event| log_event(Event::MouseClick(event)),
-                ondoubleclick: move |event| log_event(Event::MouseDoubleClick(event)),
-                onmousedown: move |event| log_event(Event::MouseDown(event)),
-                onmouseup: move |event| log_event(Event::MouseUp(event)),
+            // focusing is necessary to catch keyboard events
+            div { style: "{RECT_STYLE}", tabindex: 0,
+                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()),
 
 
-                onwheel: move |event| log_event(Event::Wheel(event)),
+                onwheel: move |event| log_event(event.data()),
 
 
-                onkeydown: move |event| log_event(Event::KeyDown(event)),
-                onkeyup: move |event| log_event(Event::KeyUp(event)),
-                onkeypress: move |event| log_event(Event::KeyPress(event)),
+                onkeydown: move |event| log_event(event.data()),
+                onkeyup: move |event| log_event(event.data()),
+                onkeypress: move |event| log_event(event.data()),
 
 
-                onfocusin: move |event| log_event(Event::FocusIn(event)),
-                onfocusout: move |event| log_event(Event::FocusOut(event)),
+                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"
                 "Hover, click, type or scroll to see the info down below"
             }
             }
@@ -82,5 +63,5 @@ fn app(cx: Scope) -> Element {
                 }
                 }
             }
             }
         }
         }
-    ))
+    }
 }
 }

+ 25 - 14
examples/assets/calculator.css

@@ -1,13 +1,17 @@
 html {
 html {
   box-sizing: border-box;
   box-sizing: border-box;
 }
 }
-*, *:before, *:after {
+
+*,
+*:before,
+*:after {
   box-sizing: inherit;
   box-sizing: inherit;
 }
 }
 
 
 body {
 body {
   margin: 0;
   margin: 0;
   font: 100 14px 'Roboto';
   font: 100 14px 'Roboto';
+  font-family: Arial;
   overflow: hidden;
   overflow: hidden;
 }
 }
 
 
@@ -20,18 +24,18 @@ button {
   user-select: none;
   user-select: none;
   cursor: pointer;
   cursor: pointer;
   outline: none;
   outline: none;
-  
-  -webkit-tap-highlight-color: rgba(0,0,0,0);
+
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
 }
 }
 
 
 button:active {
 button:active {
-  box-shadow: inset 0px 0px 80px 0px rgba(0,0,0,0.25);
+  box-shadow: inset 0px 0px 80px 0px rgba(0, 0, 0, 0.25);
 }
 }
 
 
 #wrapper {
 #wrapper {
   /* height: 100vh; */
   /* height: 100vh; */
   height: max-content;
   height: max-content;
-  
+
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
   justify-content: center;
   justify-content: center;
@@ -47,7 +51,7 @@ button:active {
   width: 100%;
   width: 100%;
   height: 100%;
   height: 100%;
   background: black;
   background: black;
-  
+
   display: flex;
   display: flex;
   flex-direction: column;
   flex-direction: column;
 }
 }
@@ -61,14 +65,14 @@ button:active {
   background: #1c191c;
   background: #1c191c;
   line-height: 130px;
   line-height: 130px;
   /* font-size: 6em; */
   /* font-size: 6em; */
-    font-size: 16px;
-    font-size: 4vw;
+  font-size: 16px;
+  font-size: 4vw;
 
 
 
 
   max-height: 160px;
   max-height: 160px;
   padding: 0 30px;
   padding: 0 30px;
   /* height: 80px; */
   /* height: 80px; */
-  
+
   flex: 1;
   flex: 1;
 }
 }
 
 
@@ -85,7 +89,7 @@ button:active {
 
 
 .calculator-keypad {
 .calculator-keypad {
   height: 400px;
   height: 400px;
-  
+
   display: flex;
   display: flex;
 }
 }
 
 
@@ -99,7 +103,7 @@ button:active {
 
 
 .calculator .digit-keys {
 .calculator .digit-keys {
   background: #e0e0e7;
   background: #e0e0e7;
-  
+
   display: flex;
   display: flex;
   flex-direction: row;
   flex-direction: row;
   flex-wrap: wrap-reverse;
   flex-wrap: wrap-reverse;
@@ -109,28 +113,34 @@ button:active {
   width: 80px;
   width: 80px;
   height: 80px;
   height: 80px;
   border-top: 1px solid #777;
   border-top: 1px solid #777;
-  border-right: 1px solid #666;  
+  border-right: 1px solid #666;
   text-align: center;
   text-align: center;
   line-height: 80px;
   line-height: 80px;
 }
 }
+
 .calculator .function-keys .calculator-key {
 .calculator .function-keys .calculator-key {
   font-size: 2em;
   font-size: 2em;
 }
 }
+
 .calculator .function-keys .key-multiply {
 .calculator .function-keys .key-multiply {
   line-height: 50px;
   line-height: 50px;
 }
 }
+
 .calculator .digit-keys .calculator-key {
 .calculator .digit-keys .calculator-key {
   font-size: 2.25em;
   font-size: 2.25em;
 }
 }
+
 .calculator .digit-keys .key-0 {
 .calculator .digit-keys .key-0 {
   width: 160px;
   width: 160px;
   text-align: left;
   text-align: left;
   padding-left: 32px;
   padding-left: 32px;
 }
 }
+
 .calculator .digit-keys .key-dot {
 .calculator .digit-keys .key-dot {
   padding-top: 1em;
   padding-top: 1em;
   font-size: 0.75em;
   font-size: 0.75em;
 }
 }
+
 .calculator .operator-keys .calculator-key {
 .calculator .operator-keys .calculator-key {
   color: white;
   color: white;
   border-right: 0;
   border-right: 0;
@@ -138,8 +148,9 @@ button:active {
 }
 }
 
 
 .calculator .function-keys {
 .calculator .function-keys {
-  background: linear-gradient(to bottom, rgba(202,202,204,1) 0%, rgba(196,194,204,1) 100%);
+  background: linear-gradient(to bottom, rgba(202, 202, 204, 1) 0%, rgba(196, 194, 204, 1) 100%);
 }
 }
+
 .calculator .operator-keys {
 .calculator .operator-keys {
-  background:  linear-gradient(to bottom, rgba(252,156,23,1) 0%, rgba(247,126,27,1) 100%);
+  background: linear-gradient(to bottom, rgba(252, 156, 23, 1) 0%, rgba(247, 126, 27, 1) 100%);
 }
 }

+ 55 - 0
examples/backgrounded_futures.rs

@@ -0,0 +1,55 @@
+use dioxus::prelude::*;
+
+fn main() {
+    launch_desktop(app);
+}
+
+fn app() -> Element {
+    let mut show_child = use_signal(|| true);
+    let mut count = use_signal(|| 0);
+
+    let child = use_memo(move || {
+        rsx! {
+            Child {
+                count
+            }
+        }
+    });
+
+    rsx! {
+        button { onclick: move |_| show_child.toggle(), "Toggle child" }
+        button { onclick: move |_| count += 1, "Increment count" }
+        if show_child() {
+            {child.cloned()}
+        }
+    }
+}
+
+#[component]
+fn Child(count: Signal<i32>) -> Element {
+    let mut early_return = use_signal(|| false);
+
+    let early = rsx! {
+        button { onclick: move |_| early_return.toggle(), "Toggle {early_return} early return" }
+    };
+
+    if early_return() {
+        return early;
+    }
+
+    use_future(move || async move {
+        loop {
+            tokio::time::sleep(std::time::Duration::from_millis(100)).await;
+            println!("Child")
+        }
+    });
+
+    use_effect(move || {
+        println!("Child count: {}", count());
+    });
+
+    rsx! {
+        "hellO!"
+        {early}
+    }
+}

+ 0 - 73
examples/borrowed.rs

@@ -1,73 +0,0 @@
-#![allow(non_snake_case)]
-
-/*
-Dioxus manages borrow lifetimes for you. This means any child may borrow from its parent. However, it is not possible
-to hand out an &mut T to children - all props are consumed by &P, so you'd only get an &&mut T.
-
-How does it work?
-
-Dioxus will manually drop closures and props - things that borrow data before the component is ran again. This is done
-"bottom up" from the lowest child all the way to the initiating parent. As it traverses each listener and prop, the
-drop implementation is manually called, freeing any memory and ensuring that memory is not leaked.
-
-We cannot drop from the parent to the children - if the drop implementation modifies the data, downstream references
-might be broken since we take an &mut T and and &T to the data. Instead, we work bottom up, making sure to remove any
-potential references to the data before finally giving out an &mut T. This prevents us from mutably aliasing the data,
-and is proven to be safe with MIRI.
-*/
-
-use dioxus::prelude::*;
-
-fn main() {
-    dioxus_desktop::launch(app);
-}
-
-fn app(cx: Scope) -> Element {
-    let text = cx.use_hook(|| vec![String::from("abc=def")]);
-
-    let first = text.get_mut(0).unwrap();
-
-    cx.render(rsx! {
-        div {
-            Child1 { text: first }
-        }
-    })
-}
-
-#[derive(Props)]
-struct C1Props<'a> {
-    text: &'a mut String,
-}
-
-fn Child1<'a>(cx: Scope<'a, C1Props<'a>>) -> Element {
-    let (left, right) = cx.props.text.split_once('=').unwrap();
-
-    cx.render(rsx! {
-        div {
-            Child2 { text: left  }
-            Child2 { text: right  }
-        }
-    })
-}
-
-#[derive(Props)]
-struct C2Props<'a> {
-    text: &'a str,
-}
-
-fn Child2<'a>(cx: Scope<'a, C2Props<'a>>) -> Element {
-    cx.render(rsx! {
-        Child3 { text: cx.props.text }
-    })
-}
-
-#[derive(Props)]
-struct C3Props<'a> {
-    text: &'a str,
-}
-
-fn Child3<'a>(cx: Scope<'a, C3Props<'a>>) -> Element {
-    cx.render(rsx! {
-        div { "{cx.props.text}"}
-    })
-}

+ 56 - 57
examples/calculator.rs

@@ -6,65 +6,58 @@ This calculator version uses React-style state management. All state is held as
 use dioxus::events::*;
 use dioxus::events::*;
 use dioxus::html::input_data::keyboard_types::Key;
 use dioxus::html::input_data::keyboard_types::Key;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::{Config, LogicalSize, WindowBuilder};
 
 
 fn main() {
 fn main() {
-    let config = Config::new().with_window(
-        WindowBuilder::default()
-            .with_title("Calculator")
-            .with_inner_size(LogicalSize::new(300.0, 500.0)),
-    );
-
-    dioxus_desktop::launch_cfg(app, config);
+    LaunchBuilder::new()
+        .with_cfg(desktop!({
+            use dioxus::desktop::{Config, LogicalSize, WindowBuilder};
+            Config::new().with_window(
+                WindowBuilder::default()
+                    .with_title("Calculator")
+                    .with_inner_size(LogicalSize::new(300.0, 525.0)),
+            )
+        }))
+        .launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let val = use_state(cx, || String::from("0"));
+fn app() -> Element {
+    let mut val = use_signal(|| String::from("0"));
 
 
-    let input_digit = move |num: u8| {
-        if val.get() == "0" {
+    let mut input_digit = move |num: String| {
+        if val() == "0" {
             val.set(String::new());
             val.set(String::new());
         }
         }
-
-        val.make_mut().push_str(num.to_string().as_str());
+        val.write().push_str(num.as_str());
     };
     };
 
 
-    let input_operator = move |key: &str| val.make_mut().push_str(key);
+    let mut input_operator = move |key: &str| val.write().push_str(key);
 
 
     let handle_key_down_event = move |evt: KeyboardEvent| match evt.key() {
     let handle_key_down_event = move |evt: KeyboardEvent| match evt.key() {
         Key::Backspace => {
         Key::Backspace => {
-            if !val.len() != 0 {
-                val.make_mut().pop();
+            if !val().is_empty() {
+                val.write().pop();
             }
             }
         }
         }
         Key::Character(character) => match character.as_str() {
         Key::Character(character) => match character.as_str() {
-            "+" => input_operator("+"),
-            "-" => input_operator("-"),
-            "/" => input_operator("/"),
-            "*" => input_operator("*"),
-            "0" => input_digit(0),
-            "1" => input_digit(1),
-            "2" => input_digit(2),
-            "3" => input_digit(3),
-            "4" => input_digit(4),
-            "5" => input_digit(5),
-            "6" => input_digit(6),
-            "7" => input_digit(7),
-            "8" => input_digit(8),
-            "9" => input_digit(9),
+            "+" | "-" | "/" | "*" => input_operator(&character),
+            "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" => input_digit(character),
             _ => {}
             _ => {}
         },
         },
         _ => {}
         _ => {}
     };
     };
 
 
-    cx.render(rsx!(
+    rsx! {
         style { {include_str!("./assets/calculator.css")} }
         style { {include_str!("./assets/calculator.css")} }
         div { id: "wrapper",
         div { id: "wrapper",
             div { class: "app",
             div { class: "app",
-                div { class: "calculator",
-                    tabindex: "0",
-                    onkeydown: handle_key_down_event,
-                    div { class: "calculator-display", "{val}" }
+                div { class: "calculator", tabindex: "0", onkeydown: handle_key_down_event,
+                    div { class: "calculator-display",
+                        if val().is_empty() {
+                            "0"
+                        } else {
+                            "{val}"
+                        }
+                    }
                     div { class: "calculator-keypad",
                     div { class: "calculator-keypad",
                         div { class: "input-keys",
                         div { class: "input-keys",
                             div { class: "function-keys",
                             div { class: "function-keys",
@@ -72,55 +65,62 @@ fn app(cx: Scope) -> Element {
                                     class: "calculator-key key-clear",
                                     class: "calculator-key key-clear",
                                     onclick: move |_| {
                                     onclick: move |_| {
                                         val.set(String::new());
                                         val.set(String::new());
-                                        if !val.is_empty(){
+                                        if !val.cloned().is_empty() {
                                             val.set("0".into());
                                             val.set("0".into());
                                         }
                                         }
                                     },
                                     },
-                                    if val.is_empty() { "C" } else { "AC" }
+                                    if val.cloned().is_empty() { "C" } else { "AC" }
                                 }
                                 }
                                 button {
                                 button {
                                     class: "calculator-key key-sign",
                                     class: "calculator-key key-sign",
                                     onclick: move |_| {
                                     onclick: move |_| {
-                                        let temp = calc_val(val.as_str());
-                                        if temp > 0.0 {
-                                            val.set(format!("-{temp}"));
+                                        let new_val = calc_val(val.cloned().as_str());
+                                        if new_val > 0.0 {
+                                            val.set(format!("-{new_val}"));
                                         } else {
                                         } else {
-                                            val.set(format!("{}", temp.abs()));
+                                            val.set(format!("{}", new_val.abs()));
                                         }
                                         }
                                     },
                                     },
                                     "±"
                                     "±"
                                 }
                                 }
                                 button {
                                 button {
                                     class: "calculator-key key-percent",
                                     class: "calculator-key key-percent",
-                                    onclick: move |_| {
-                                        val.set(
-                                            format!("{}", calc_val(val.as_str()) / 100.0)
-                                        );
-                                    },
+                                    onclick: move |_| val.set(format!("{}", calc_val(val.cloned().as_str()) / 100.0)),
                                     "%"
                                     "%"
                                 }
                                 }
                             }
                             }
                             div { class: "digit-keys",
                             div { class: "digit-keys",
-                                button { class: "calculator-key key-0", onclick: move |_| input_digit(0), "0" }
-                                button { class: "calculator-key key-dot", onclick: move |_| val.make_mut().push('.'), "●" }
+                                button {
+                                    class: "calculator-key key-0",
+                                    onclick: move |_| input_digit(0.to_string()),
+                                    "0"
+                                }
+                                button {
+                                    class: "calculator-key key-dot",
+                                    onclick: move |_| val.write().push('.'),
+                                    "●"
+                                }
                                 for k in 1..10 {
                                 for k in 1..10 {
                                     button {
                                     button {
                                         class: "calculator-key {k}",
                                         class: "calculator-key {k}",
                                         name: "key-{k}",
                                         name: "key-{k}",
-                                        onclick: move |_| input_digit(k),
+                                        onclick: move |_| input_digit(k.to_string()),
                                         "{k}"
                                         "{k}"
                                     }
                                     }
                                 }
                                 }
                             }
                             }
                         }
                         }
                         div { class: "operator-keys",
                         div { class: "operator-keys",
-                            button { class: "calculator-key key-divide", onclick: move |_| input_operator("/"), "÷" }
-                            button { class: "calculator-key key-multiply", onclick: move |_| input_operator("*"), "×" }
-                            button { class: "calculator-key key-subtract", onclick: move |_| input_operator("-"), "−" }
-                            button { class: "calculator-key key-add", onclick: move |_| input_operator("+"), "+" }
+                            for (key, class) in [("/", "key-divide"), ("*", "key-multiply"), ("-", "key-subtract"), ("+", "key-add")] {
+                                button {
+                                    class: "calculator-key {class}",
+                                    onclick: move |_| input_operator(key),
+                                    "{key}"
+                                }
+                            }
                             button {
                             button {
                                 class: "calculator-key key-equals",
                                 class: "calculator-key key-equals",
-                                onclick: move |_| val.set(format!("{}", calc_val(val.as_str()))),
+                                onclick: move |_| val.set(format!("{}", calc_val(val.cloned().as_str()))),
                                 "="
                                 "="
                             }
                             }
                         }
                         }
@@ -128,8 +128,7 @@ fn app(cx: Scope) -> Element {
                 }
                 }
             }
             }
         }
         }
-
-    ))
+    }
 }
 }
 
 
 fn calc_val(val: &str) -> f64 {
 fn calc_val(val: &str) -> f64 {

+ 22 - 56
examples/pattern_model.rs → examples/calculator_mutable.rs

@@ -17,12 +17,12 @@
 //! the RefCell will panic and crash. You can use `try_get_mut` or `.modify` to avoid this problem, or just not hold two
 //! the RefCell will panic and crash. You can use `try_get_mut` or `.modify` to avoid this problem, or just not hold two
 //! RefMuts at the same time.
 //! RefMuts at the same time.
 
 
+use dioxus::desktop::tao::dpi::LogicalSize;
+use dioxus::desktop::{Config, WindowBuilder};
 use dioxus::events::*;
 use dioxus::events::*;
 use dioxus::html::input_data::keyboard_types::Key;
 use dioxus::html::input_data::keyboard_types::Key;
 use dioxus::html::MouseEvent;
 use dioxus::html::MouseEvent;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::tao::dpi::LogicalSize;
-use dioxus_desktop::{Config, WindowBuilder};
 
 
 fn main() {
 fn main() {
     let cfg = Config::new().with_window(
     let cfg = Config::new().with_window(
@@ -32,50 +32,34 @@ fn main() {
             .with_inner_size(LogicalSize::new(320.0, 530.0)),
             .with_inner_size(LogicalSize::new(320.0, 530.0)),
     );
     );
 
 
-    dioxus_desktop::launch_cfg(app, cfg);
+    LaunchBuilder::desktop().with_cfg(cfg).launch(app);
 }
 }
 
 
 const STYLE: &str = include_str!("./assets/calculator.css");
 const STYLE: &str = include_str!("./assets/calculator.css");
 
 
-fn app(cx: Scope) -> Element {
-    let state = use_ref(cx, Calculator::new);
+fn app() -> Element {
+    let mut state = use_signal(Calculator::new);
 
 
-    cx.render(rsx! {
+    rsx! {
         style { {STYLE} }
         style { {STYLE} }
         div { id: "wrapper",
         div { id: "wrapper",
             div { class: "app",
             div { class: "app",
-                div { class: "calculator", onkeypress: move |evt| state.write().handle_keydown(evt),
+                div {
+                    class: "calculator",
+                    onkeypress: move |evt| state.write().handle_keydown(evt),
                     div { class: "calculator-display", {state.read().formatted_display()} }
                     div { class: "calculator-display", {state.read().formatted_display()} }
                     div { class: "calculator-keypad",
                     div { class: "calculator-keypad",
                         div { class: "input-keys",
                         div { class: "input-keys",
                             div { class: "function-keys",
                             div { class: "function-keys",
-                                CalculatorKey {
-                                    name: "key-clear",
-                                    onclick: move |_| state.write().clear_display(),
+                                CalculatorKey { name: "key-clear", onclick: move |_| state.write().clear_display(),
                                     if state.read().display_value == "0" { "C" } else { "AC" }
                                     if state.read().display_value == "0" { "C" } else { "AC" }
                                 }
                                 }
-                                CalculatorKey {
-                                    name: "key-sign",
-                                    onclick: move |_| state.write().toggle_sign(),
-                                    "±"
-                                }
-                                CalculatorKey {
-                                    name: "key-percent",
-                                    onclick: move |_| state.write().toggle_percent(),
-                                    "%"
-                                }
+                                CalculatorKey { name: "key-sign", onclick: move |_| state.write().toggle_sign(), "±" }
+                                CalculatorKey { name: "key-percent", onclick: move |_| state.write().toggle_percent(), "%" }
                             }
                             }
                             div { class: "digit-keys",
                             div { class: "digit-keys",
-                                CalculatorKey {
-                                    name: "key-0",
-                                    onclick: move |_| state.write().input_digit(0),
-                                    "0"
-                                }
-                                CalculatorKey {
-                                    name: "key-dot",
-                                    onclick: move |_|  state.write().input_dot(),
-                                    "●"
-                                }
+                                CalculatorKey { name: "key-0", onclick: move |_| state.write().input_digit(0), "0" }
+                                CalculatorKey { name: "key-dot", onclick: move |_| state.write().input_dot(), "●" }
                                 for k in 1..10 {
                                 for k in 1..10 {
                                     CalculatorKey {
                                     CalculatorKey {
                                         key: "{k}",
                                         key: "{k}",
@@ -102,39 +86,21 @@ fn app(cx: Scope) -> Element {
                                 onclick: move |_| state.write().set_operator(Operator::Sub),
                                 onclick: move |_| state.write().set_operator(Operator::Sub),
                                 "−"
                                 "−"
                             }
                             }
-                            CalculatorKey {
-                                name: "key-add",
-                                onclick: move |_| state.write().set_operator(Operator::Add),
-                                "+"
-                            }
-                            CalculatorKey {
-                                name: "key-equals",
-                                onclick: move |_| state.write().perform_operation(),
-                                "="
-                            }
+                            CalculatorKey { name: "key-add", onclick: move |_| state.write().set_operator(Operator::Add), "+" }
+                            CalculatorKey { name: "key-equals", onclick: move |_| state.write().perform_operation(), "=" }
                         }
                         }
                     }
                     }
                 }
                 }
             }
             }
         }
         }
-    })
-}
-
-#[derive(Props)]
-struct CalculatorKeyProps<'a> {
-    name: &'a str,
-    onclick: EventHandler<'a, MouseEvent>,
-    children: Element<'a>,
+    }
 }
 }
 
 
-fn CalculatorKey<'a>(cx: Scope<'a, CalculatorKeyProps<'a>>) -> Element {
-    cx.render(rsx! {
-        button {
-            class: "calculator-key {cx.props.name}",
-            onclick: move |e| cx.props.onclick.call(e),
-            {&cx.props.children}
-        }
-    })
+#[component]
+fn CalculatorKey(name: String, onclick: EventHandler<MouseEvent>, children: Element) -> Element {
+    rsx! {
+        button { class: "calculator-key {name}", onclick: move |e| onclick.call(e), {&children} }
+    }
 }
 }
 
 
 struct Calculator {
 struct Calculator {

+ 0 - 22
examples/callback.rs

@@ -1,22 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
-    dioxus_desktop::launch(app);
-}
-
-fn app(cx: Scope) -> Element {
-    let login = use_callback!(cx, move |_| async move {
-        let res = reqwest::get("https://dog.ceo/api/breeds/list/all")
-            .await
-            .unwrap()
-            .text()
-            .await
-            .unwrap();
-
-        println!("{res:#?}, ");
-    });
-
-    cx.render(rsx! {
-        button { onclick: login, "Click me!" }
-    })
-}

+ 10 - 8
examples/clock.rs

@@ -1,22 +1,24 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_signals::use_signal;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let mut count = use_signal(cx, || 0);
+fn app() -> Element {
+    let mut count = use_signal(|| 0);
 
 
-    use_future!(cx, || async move {
+    use_future(move || async move {
         loop {
         loop {
             tokio::time::sleep(std::time::Duration::from_millis(10)).await;
             tokio::time::sleep(std::time::Duration::from_millis(10)).await;
             count += 1;
             count += 1;
-            println!("current: {count}");
         }
         }
     });
     });
 
 
-    cx.render(rsx! {
+    use_effect(move || {
+        println!("High-Five counter: {}", count());
+    });
+
+    rsx! {
         div { "High-Five counter: {count}" }
         div { "High-Five counter: {count}" }
-    })
+    }
 }
 }

+ 32 - 38
examples/compose.rs

@@ -1,68 +1,62 @@
 //! This example shows how to create a popup window and send data back to the parent window.
 //! This example shows how to create a popup window and send data back to the parent window.
 
 
+use std::rc::Rc;
+
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 use futures_util::StreamExt;
 use futures_util::StreamExt;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let emails_sent = use_ref(cx, Vec::new);
+fn app() -> Element {
+    let mut emails_sent = use_signal(|| Vec::new() as Vec<String>);
 
 
-    let tx = use_coroutine(cx, |mut rx: UnboundedReceiver<String>| {
-        to_owned![emails_sent];
-        async move {
-            while let Some(message) = rx.next().await {
-                emails_sent.write().push(message);
-            }
+    // Wait for responses to the compose channel, and then push them to the emails_sent signal.
+    let handle = use_coroutine(|mut rx: UnboundedReceiver<String>| async move {
+        while let Some(message) = rx.next().await {
+            emails_sent.write().push(message);
         }
         }
     });
     });
 
 
-    cx.render(rsx! {
-        div {
-            h1 { "This is your email" }
-
-            button {
-                onclick: move |_| {
-                    let dom = VirtualDom::new_with_props(compose, ComposeProps { app_tx: tx.clone() });
-                    dioxus_desktop::window().new_window(dom, Default::default());
-                },
-                "Click to compose a new email"
-            }
-
-            ul {
-                for message in emails_sent.read().iter() {
-                    li {
-                        h3 { "email" }
-                        span {"{message}"}
-                    }
+    let open_compose_window = move |_evt: MouseEvent| {
+        let tx = handle.tx();
+        dioxus::desktop::window().new_window(
+            VirtualDom::new_with_props(compose, Rc::new(move |s| tx.unbounded_send(s).unwrap())),
+            Default::default(),
+        );
+    };
+
+    rsx! {
+        h1 { "This is your email" }
+        button { onclick: open_compose_window, "Click to compose a new email" }
+        ul {
+            for message in emails_sent.read().iter() {
+                li {
+                    h3 { "email" }
+                    span { "{message}" }
                 }
                 }
             }
             }
         }
         }
-    })
-}
-
-struct ComposeProps {
-    app_tx: Coroutine<String>,
+    }
 }
 }
 
 
-fn compose(cx: Scope<ComposeProps>) -> Element {
-    let user_input = use_state(cx, String::new);
+fn compose(send: Rc<dyn Fn(String)>) -> Element {
+    let mut user_input = use_signal(String::new);
 
 
-    cx.render(rsx! {
+    rsx! {
         div {
         div {
             h1 { "Compose a new email" }
             h1 { "Compose a new email" }
 
 
             button {
             button {
                 onclick: move |_| {
                 onclick: move |_| {
-                    cx.props.app_tx.send(user_input.get().clone());
-                    dioxus_desktop::window().close();
+                    send(user_input.cloned());
+                    dioxus::desktop::window().close();
                 },
                 },
                 "Click to send"
                 "Click to send"
             }
             }
 
 
             input { oninput: move |e| user_input.set(e.value()), value: "{user_input}" }
             input { oninput: move |e| user_input.set(e.value()), value: "{user_input}" }
         }
         }
-    })
+    }
 }
 }

+ 22 - 17
examples/control_focus.rs

@@ -3,36 +3,41 @@ use std::rc::Rc;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let elements: &UseRef<Vec<Rc<MountedData>>> = use_ref(cx, Vec::new);
-    let running = use_state(cx, || true);
+fn app() -> Element {
+    let mut elements = use_signal(Vec::<Rc<MountedData>>::new);
+    let mut running = use_signal(|| true);
 
 
-    use_future!(cx, |(elements, running)| async move {
+    use_future(move || async move {
         let mut focused = 0;
         let mut focused = 0;
-        if *running.current() {
-            loop {
-                tokio::time::sleep(std::time::Duration::from_millis(10)).await;
-                if let Some(element) = elements.with(|f| f.get(focused).cloned()) {
-                    _ = element.set_focus(true).await;
-                } else {
-                    focused = 0;
-                }
-                focused += 1;
+
+        loop {
+            tokio::time::sleep(std::time::Duration::from_millis(10)).await;
+
+            if !running() {
+                continue;
             }
             }
+
+            if let Some(element) = elements.with(|f| f.get(focused).cloned()) {
+                _ = element.set_focus(true).await;
+            } else {
+                focused = 0;
+            }
+
+            focused += 1;
         }
         }
     });
     });
 
 
-    cx.render(rsx!(
+    rsx! {
         div {
         div {
             h1 { "Input Roulette" }
             h1 { "Input Roulette" }
             for i in 0..100 {
             for i in 0..100 {
                 input {
                 input {
                     value: "{i}",
                     value: "{i}",
                     onmounted: move |cx| {
                     onmounted: move |cx| {
-                        elements.write().push(cx.inner().clone());
+                        elements.write().push(cx.data());
                     },
                     },
                     oninput: move |_| {
                     oninput: move |_| {
                         running.set(false);
                         running.set(false);
@@ -40,5 +45,5 @@ fn app(cx: Scope) -> Element {
                 }
                 }
             }
             }
         }
         }
-    ))
+    }
 }
 }

+ 36 - 19
examples/counter.rs

@@ -4,33 +4,50 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let counters = use_state(cx, || vec![0, 0, 0]);
-    let sum: usize = counters.iter().copied().sum();
+fn app() -> Element {
+    let mut counters = use_signal(|| vec![0, 0, 0]);
+    let sum = use_memo(move || counters.read().iter().copied().sum::<i32>());
 
 
-    render! {
+    rsx! {
         div {
         div {
-            button { onclick: move |_| counters.make_mut().push(0), "Add counter" }
-            button { onclick: move |_| { counters.make_mut().pop(); }, "Remove counter" }
+            button { onclick: move |_| counters.write().push(0), "Add counter" }
+            button {
+                onclick: move |_| {
+                    counters.write().pop();
+                },
+                "Remove counter"
+            }
             p { "Total: {sum}" }
             p { "Total: {sum}" }
-            for (i, counter) in counters.iter().enumerate() {
-                li {
-                    button { onclick: move |_| counters.make_mut()[i] -= 1, "-1" }
-                    input {
-                        value: "{counter}",
-                        oninput: move |e| {
-                            if let Ok(value) = e.value().parse::<usize>() {
-                                counters.make_mut()[i] = value;
-                            }
-                        }
+            for i in 0..counters.len() {
+                Child { i, counters }
+            }
+        }
+    }
+}
+
+#[component]
+fn Child(counters: Signal<Vec<i32>>, i: usize) -> Element {
+    rsx! {
+        li {
+            button { onclick: move |_| counters.write()[i] -= 1, "-1" }
+            input {
+                value: "{counters.read()[i]}",
+                oninput: move |e| {
+                    if let Ok(value) = e.value().parse::<i32>() {
+                        counters.write()[i] = value;
                     }
                     }
-                    button { onclick: move |_| counters.make_mut()[i] += 1, "+1" }
-                    button { onclick: move |_| { counters.make_mut().remove(i); }, "x" }
                 }
                 }
             }
             }
+            button { onclick: move |_| counters.write()[i] += 1, "+1" }
+            button {
+                onclick: move |_| {
+                    counters.write().remove(i);
+                },
+                "x"
+            }
         }
         }
     }
     }
 }
 }

+ 77 - 93
examples/crm.rs

@@ -1,112 +1,100 @@
 //! Tiny CRM: A port of the Yew CRM example to Dioxus.
 //! Tiny CRM: A port of the Yew CRM example to Dioxus.
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_router::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(App);
+    LaunchBuilder::new()
+        .with_cfg(desktop!({
+            use dioxus::desktop::{LogicalSize, WindowBuilder};
+            dioxus::desktop::Config::default()
+                .with_window(WindowBuilder::new().with_inner_size(LogicalSize::new(800, 600)))
+        }))
+        .launch(|| {
+            rsx! {
+                link {
+                    rel: "stylesheet",
+                    href: "https://unpkg.com/purecss@2.0.6/build/pure-min.css",
+                    integrity: "sha384-Uu6IeWbM+gzNVXJcM9XV3SohHtmWE+3VGi496jvgX1jyvDTXfdK+rfZc8C1Aehk5",
+                    crossorigin: "anonymous"
+                }
+                style { {r#" .red { background-color: rgb(202, 60, 60) !important; } "#} }
+                h1 { "Dioxus CRM Example" }
+                Router::<Route> {}
+            }
+        });
 }
 }
 
 
-#[derive(Routable, Clone)]
-#[rustfmt::skip]
-enum Route {
-    #[route("/")]
-    ClientList {},
-    #[route("/new")]
-    ClientAdd {},
-    #[route("/settings")]
-    Settings {},
-}
+/// We only have one list of clients for the whole app, so we can use a global signal.
+static CLIENTS: GlobalSignal<Vec<Client>> = Signal::global(Vec::new);
 
 
-#[derive(Clone, Debug, Default)]
-pub struct Client {
-    pub first_name: String,
-    pub last_name: String,
-    pub description: String,
+struct Client {
+    first_name: String,
+    last_name: String,
+    description: String,
 }
 }
 
 
-type ClientContext = Vec<Client>;
-
-#[component]
-fn App(cx: Scope) -> Element {
-    use_shared_state_provider::<ClientContext>(cx, Default::default);
-
-    render! {
-        link {
-            rel: "stylesheet",
-            href: "https://unpkg.com/purecss@2.0.6/build/pure-min.css",
-            integrity: "sha384-Uu6IeWbM+gzNVXJcM9XV3SohHtmWE+3VGi496jvgX1jyvDTXfdK+rfZc8C1Aehk5",
-            crossorigin: "anonymous"
-        }
-
-        style {
-            "
-            .red {{
-                background-color: rgb(202, 60, 60) !important;
-            }}
-        "
-        }
+#[derive(Routable, Clone)]
+enum Route {
+    #[route("/")]
+    ClientList,
 
 
-        h1 { "Dioxus CRM Example" }
+    #[route("/new")]
+    ClientAdd,
 
 
-        Router::<Route> {}
-    }
+    #[route("/settings")]
+    Settings,
 }
 }
 
 
 #[component]
 #[component]
-fn ClientList(cx: Scope) -> Element {
-    let clients = use_shared_state::<ClientContext>(cx).unwrap();
-
-    cx.render(rsx! {
+fn ClientList() -> Element {
+    rsx! {
         h2 { "List of Clients" }
         h2 { "List of Clients" }
-
-        Link { to: Route::ClientAdd {}, class: "pure-button pure-button-primary", "Add Client" }
-        Link { to: Route::Settings {}, class: "pure-button", "Settings" }
-
-        for client in clients.read().iter() {
-            div {
-                class: "client",
-                style: "margin-bottom: 50px",
-
+        Link { to: Route::ClientAdd, class: "pure-button pure-button-primary", "Add Client" }
+        Link { to: Route::Settings, class: "pure-button", "Settings" }
+        for client in CLIENTS.read().iter() {
+            div { class: "client", style: "margin-bottom: 50px",
                 p { "Name: {client.first_name} {client.last_name}" }
                 p { "Name: {client.first_name} {client.last_name}" }
                 p { "Description: {client.description}" }
                 p { "Description: {client.description}" }
             }
             }
         }
         }
-    })
+    }
 }
 }
 
 
 #[component]
 #[component]
-fn ClientAdd(cx: Scope) -> Element {
-    let clients = use_shared_state::<ClientContext>(cx).unwrap();
-    let first_name = use_state(cx, String::new);
-    let last_name = use_state(cx, String::new);
-    let description = use_state(cx, String::new);
-
-    cx.render(rsx! {
+fn ClientAdd() -> Element {
+    let mut first_name = use_signal(String::new);
+    let mut last_name = use_signal(String::new);
+    let mut description = use_signal(String::new);
+
+    let submit_client = move |_: FormEvent| {
+        // Write the client
+        CLIENTS.write().push(Client {
+            first_name: first_name(),
+            last_name: last_name(),
+            description: description(),
+        });
+
+        // And then navigate back to the client list
+        dioxus::router::router().push(Route::ClientList);
+    };
+
+    rsx! {
         h2 { "Add new Client" }
         h2 { "Add new Client" }
-
-        form {
-            class: "pure-form pure-form-aligned",
-            onsubmit: move |_| {
-                let mut clients = clients.write();
-                clients
-                    .push(Client {
-                        first_name: first_name.to_string(),
-                        last_name: last_name.to_string(),
-                        description: description.to_string(),
-                    });
-                dioxus_router::router().push(Route::ClientList {});
-            },
-
+        form { class: "pure-form pure-form-aligned", onsubmit: submit_client,
             fieldset {
             fieldset {
                 div { class: "pure-control-group",
                 div { class: "pure-control-group",
-                    label { "for": "first_name", "First Name" }
+                    label { r#for: "first_name", "First Name" }
                     input {
                     input {
                         id: "first_name",
                         id: "first_name",
-                        "type": "text",
+                        r#type: "text",
                         placeholder: "First Name…",
                         placeholder: "First Name…",
                         required: "",
                         required: "",
                         value: "{first_name}",
                         value: "{first_name}",
-                        oninput: move |e| first_name.set(e.value())
+                        oninput: move |e| first_name.set(e.value()),
+
+                        // when the form mounts, focus the first name input
+                        onmounted: move |e| async move {
+                            _ = e.set_focus(true).await;
+                        },
                     }
                     }
                 }
                 }
 
 
@@ -114,7 +102,7 @@ fn ClientAdd(cx: Scope) -> Element {
                     label { "for": "last_name", "Last Name" }
                     label { "for": "last_name", "Last Name" }
                     input {
                     input {
                         id: "last_name",
                         id: "last_name",
-                        "type": "text",
+                        r#type: "text",
                         placeholder: "Last Name…",
                         placeholder: "Last Name…",
                         required: "",
                         required: "",
                         value: "{last_name}",
                         value: "{last_name}",
@@ -133,30 +121,26 @@ fn ClientAdd(cx: Scope) -> Element {
                 }
                 }
 
 
                 div { class: "pure-controls",
                 div { class: "pure-controls",
-                    button { "type": "submit", class: "pure-button pure-button-primary", "Save" }
-                    Link { to: Route::ClientList {}, class: "pure-button pure-button-primary red", "Cancel" }
+                    button { r#type: "submit", class: "pure-button pure-button-primary", "Save" }
+                    Link { to: Route::ClientList, class: "pure-button pure-button-primary red", "Cancel" }
                 }
                 }
             }
             }
         }
         }
-    })
+    }
 }
 }
 
 
 #[component]
 #[component]
-fn Settings(cx: Scope) -> Element {
-    let clients = use_shared_state::<ClientContext>(cx).unwrap();
-
-    cx.render(rsx! {
+fn Settings() -> Element {
+    rsx! {
         h2 { "Settings" }
         h2 { "Settings" }
-
         button {
         button {
             class: "pure-button pure-button-primary red",
             class: "pure-button pure-button-primary red",
             onclick: move |_| {
             onclick: move |_| {
-                let mut clients = clients.write();
-                clients.clear();
+                CLIENTS.write().clear();
+                dioxus::router::router().push(Route::ClientList);
             },
             },
             "Remove all Clients"
             "Remove all Clients"
         }
         }
-
-        Link { to: Route::ClientList {}, class: "pure-button", "Go back" }
-    })
+        Link { to: Route::ClientList, class: "pure-button", "Go back" }
+    }
 }
 }

+ 12 - 8
examples/custom_assets.rs

@@ -1,16 +1,20 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
+#[cfg(not(feature = "collect-assets"))]
+static ASSET_PATH: &str = "examples/assets/logo.png";
+
+#[cfg(feature = "collect-assets")]
+static ASSET_PATH: &str = manganis::mg!(image("examples/assets/logo.png").format(ImageType::Avif));
+
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
+fn app() -> Element {
+    rsx! {
         div {
         div {
-            p {
-                "This should show an image:"
-            }
-            img { src: manganis::mg!(image("examples/assets/logo.png").format(ImageType::Avif)).to_string() }
+            p { "This should show an image:" }
+            img { src: ASSET_PATH.to_string() }
         }
         }
-    })
+    }
 }
 }

+ 18 - 18
examples/custom_html.rs

@@ -1,19 +1,20 @@
 //! This example shows how to use a custom index.html and custom <HEAD> extensions
 //! This example shows how to use a custom index.html and custom <HEAD> extensions
 //! to add things like stylesheets, scripts, and third-party JS libraries.
 //! to add things like stylesheets, scripts, and third-party JS libraries.
 
 
+use dioxus::desktop::Config;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::Config;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch_cfg(
-        app,
-        Config::new().with_custom_head("<style>body { background-color: red; }</style>".into()),
-    );
+    LaunchBuilder::desktop()
+        .with_cfg(
+            Config::new().with_custom_head("<style>body { background-color: red; }</style>".into()),
+        )
+        .launch(app);
 
 
-    dioxus_desktop::launch_cfg(
-        app,
-        Config::new().with_custom_index(
-            r#"
+    LaunchBuilder::desktop()
+        .with_cfg(
+            Config::new().with_custom_index(
+                r#"
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html>
 <html>
   <head>
   <head>
@@ -26,15 +27,14 @@ fn main() {
   </body>
   </body>
 </html>
 </html>
         "#
         "#
-            .into(),
-        ),
-    );
+                .into(),
+            ),
+        )
+        .launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
-        div {
-            h1 {"hello world!"}
-        }
-    })
+fn app() -> Element {
+    rsx! {
+        div { h1 { "hello world!" } }
+    }
 }
 }

+ 8 - 12
examples/disabled.rs

@@ -1,25 +1,21 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let disabled = use_state(cx, || false);
+fn app() -> Element {
+    let mut disabled = use_signal(|| false);
 
 
-    cx.render(rsx! {
+    rsx! {
         div {
         div {
-            button {
-                onclick: move |_| disabled.set(!disabled),
+            button { onclick: move |_| disabled.toggle(),
                 "click to "
                 "click to "
-                if disabled == true { "enable" } else { "disable" }
+                if disabled() { "enable" } else { "disable" }
                 " the lower button"
                 " the lower button"
             }
             }
 
 
-            button {
-                disabled: "{disabled}",
-                "lower button"
-            }
+            button { disabled, "lower button" }
         }
         }
-    })
+    }
 }
 }

+ 46 - 55
examples/dog_app.rs

@@ -2,57 +2,49 @@ use dioxus::prelude::*;
 use std::collections::HashMap;
 use std::collections::HashMap;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(|cx| render!(AppRoot {}));
+    launch(app);
 }
 }
 
 
-#[derive(Debug, Clone, PartialEq, serde::Deserialize)]
-struct ListBreeds {
-    message: HashMap<String, Vec<String>>,
-}
-
-#[component]
-fn AppRoot(cx: Scope<'_>) -> Element {
-    let breed = use_state(cx, || "deerhound".to_string());
-
-    let breeds = use_future!(cx, || async move {
-        reqwest::get("https://dog.ceo/api/breeds/list/all")
+fn app() -> Element {
+    let mut breed = use_signal(|| "deerhound".to_string());
+    let breed_list = use_resource(move || async move {
+        let list = reqwest::get("https://dog.ceo/api/breeds/list/all")
             .await
             .await
             .unwrap()
             .unwrap()
             .json::<ListBreeds>()
             .json::<ListBreeds>()
-            .await
-    });
+            .await;
+
+        let Ok(breeds) = list else {
+            return rsx! { "error fetching breeds" };
+        };
 
 
-    match breeds.value()? {
-        Ok(breed_list) => cx.render(rsx! {
-            div { height: "500px",
-                h1 { "Select a dog breed!" }
-                div { display: "flex",
-                    ul { flex: "50%",
-                        for cur_breed in breed_list.message.keys().take(10) {
-                            li { key: "{cur_breed}",
-                                button {
-                                    onclick: move |_| breed.set(cur_breed.clone()),
-                                    "{cur_breed}"
-                                }
-                            }
-                        }
+        rsx! {
+            for cur_breed in breeds.message.keys().take(10).cloned() {
+                li { key: "{cur_breed}",
+                    button { onclick: move |_| breed.set(cur_breed.clone()),
+                        "{cur_breed}"
                     }
                     }
-                    div { flex: "50%", BreedPic { breed: breed.to_string() } }
                 }
                 }
             }
             }
-        }),
-        Err(_e) => cx.render(rsx! { div { "Error fetching breeds" } }),
-    }
-}
+        }
+    });
 
 
-#[derive(serde::Deserialize, Debug)]
-struct DogApi {
-    message: String,
+    let Some(breed_list) = breed_list() else {
+        return rsx! { "loading breeds..." };
+    };
+
+    rsx! {
+        h1 { "Select a dog breed!" }
+        div { height: "500px", display: "flex",
+            ul { flex: "50%", {breed_list} }
+            div { flex: "50%", BreedPic { breed } }
+        }
+    }
 }
 }
 
 
 #[component]
 #[component]
-fn BreedPic(cx: Scope, breed: String) -> Element {
-    let fut = use_future!(cx, |breed| async move {
+fn BreedPic(breed: Signal<String>) -> Element {
+    let mut fut = use_resource(move || async move {
         reqwest::get(format!("https://dog.ceo/api/breed/{breed}/images/random"))
         reqwest::get(format!("https://dog.ceo/api/breed/{breed}/images/random"))
             .await
             .await
             .unwrap()
             .unwrap()
@@ -60,23 +52,22 @@ fn BreedPic(cx: Scope, breed: String) -> Element {
             .await
             .await
     });
     });
 
 
-    match fut.value()? {
-        Ok(resp) => render! {
-            div {
-                button {
-                    onclick: move |_| {
-                        println!("clicked");
-                        fut.restart()
-                    },
-                    "Click to fetch another doggo"
-                }
-                img {
-                    src: "{resp.message}",
-                    max_width: "500px",
-                    max_height: "500px",
-                }
-            }
+    match fut.read().as_ref() {
+        Some(Ok(resp)) => rsx! {
+            button { onclick: move |_| fut.restart(), "Click to fetch another doggo" }
+            img { max_width: "500px", max_height: "500px", src: "{resp.message}" }
         },
         },
-        Err(_) => render! { div { "loading dogs failed" } },
+        Some(Err(_)) => rsx! { "loading image failed" },
+        None => rsx! { "loading image..." },
     }
     }
 }
 }
+
+#[derive(Debug, Clone, PartialEq, serde::Deserialize)]
+struct ListBreeds {
+    message: HashMap<String, Vec<String>>,
+}
+
+#[derive(serde::Deserialize, Debug)]
+struct DogApi {
+    message: String,
+}

+ 0 - 36
examples/drops.rs

@@ -1,36 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
-    dioxus_desktop::launch(app);
-}
-
-fn app(cx: Scope) -> Element {
-    let count = if cx.generation() % 2 == 0 { 10 } else { 0 };
-
-    println!("Generation: {}", cx.generation());
-
-    if cx.generation() < 10 {
-        cx.needs_update();
-    }
-
-    render! {
-        for _ in 0..count {
-            drop_child {}
-        }
-    }
-}
-
-fn drop_child(cx: Scope) -> Element {
-    cx.use_hook(|| Drops);
-    render! {
-        div{}
-    }
-}
-
-struct Drops;
-
-impl Drop for Drops {
-    fn drop(&mut self) {
-        println!("Dropped!");
-    }
-}

+ 7 - 9
examples/dynamic_asset.rs

@@ -1,23 +1,21 @@
+use dioxus::desktop::{use_asset_handler, wry::http::Response};
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::{use_asset_handler, wry::http::Response};
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    use_asset_handler(cx, "logos", |request, response| {
-        // Note that the "logos" prefix is stripped from the URI
-        //
-        // However, the asset is absolute to its "virtual folder" - meaning it starts with a leading slash
-        if request.uri().path() != "/logo.png" {
+fn app() -> Element {
+    use_asset_handler("logos", |request, response| {
+        // We get the original path - make sure you handle that!
+        if request.uri().path() != "/logos/logo.png" {
             return;
             return;
         }
         }
 
 
         response.respond(Response::new(include_bytes!("./assets/logo.png").to_vec()));
         response.respond(Response::new(include_bytes!("./assets/logo.png").to_vec()));
     });
     });
 
 
-    render! {
+    rsx! {
         div {
         div {
             img { src: "/logos/logo.png" }
             img { src: "/logos/logo.png" }
         }
         }

+ 8 - 11
examples/error_handle.rs

@@ -1,28 +1,25 @@
-use dioxus::{core::CapturedError, prelude::*};
+use dioxus::{dioxus_core::CapturedError, prelude::*};
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(App);
+    launch_desktop(app);
 }
 }
 
 
-#[component]
-fn App(cx: Scope) -> Element {
-    cx.render(rsx! {
+fn app() -> Element {
+    rsx! {
         ErrorBoundary {
         ErrorBoundary {
             handle_error: |error: CapturedError| rsx! {"Found error {error}"},
             handle_error: |error: CapturedError| rsx! {"Found error {error}"},
-            DemoC {
-                x: 1
-            }
+            DemoC { x: 1 }
         }
         }
-    })
+    }
 }
 }
 
 
 #[component]
 #[component]
-fn DemoC(cx: Scope, x: i32) -> Element {
+fn DemoC(x: i32) -> Element {
     let result = Err("Error");
     let result = Err("Error");
 
 
     result.throw()?;
     result.throw()?;
 
 
-    render! {
+    rsx! {
         h1 { "{x}" }
         h1 { "{x}" }
     }
     }
 }
 }

+ 7 - 11
examples/eval.rs

@@ -1,12 +1,12 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let future = use_future(cx, (), |_| async move {
-        let eval = eval(
+fn app() -> Element {
+    let future = use_resource(move || async move {
+        let mut eval = eval(
             r#"
             r#"
                 dioxus.send("Hi from JS!");
                 dioxus.send("Hi from JS!");
                 let msg = await dioxus.recv();
                 let msg = await dioxus.recv();
@@ -22,12 +22,8 @@ fn app(cx: Scope) -> Element {
         res
         res
     });
     });
 
 
-    match future.value() {
-        Some(v) => cx.render(rsx!(
-            p { "{v}" }
-        )),
-        _ => cx.render(rsx!(
-            p { "hello" }
-        )),
+    match future.value().as_ref() {
+        Some(v) => rsx!( p { "{v}" } ),
+        _ => rsx!( p { "waiting.." } ),
     }
     }
 }
 }

+ 0 - 57
examples/fermi.rs

@@ -1,57 +0,0 @@
-#![allow(non_snake_case)]
-
-use dioxus::prelude::*;
-use fermi::*;
-
-fn main() {
-    dioxus_desktop::launch(app)
-}
-
-static NAME: Atom<String> = Atom(|_| "world".to_string());
-
-fn app(cx: Scope) -> Element {
-    use_init_atom_root(cx);
-    let name = use_read(cx, &NAME);
-
-    cx.render(rsx! {
-        div { "hello {name}!" }
-        Child {}
-        ChildWithRef {}
-    })
-}
-
-fn Child(cx: Scope) -> Element {
-    let set_name = use_set(cx, &NAME);
-
-    cx.render(rsx! {
-        button {
-            onclick: move |_| set_name("dioxus".to_string()),
-            "reset name"
-        }
-    })
-}
-
-static NAMES: AtomRef<Vec<String>> = AtomRef(|_| vec!["world".to_string()]);
-
-fn ChildWithRef(cx: Scope) -> Element {
-    let names = use_atom_ref(cx, &NAMES);
-
-    cx.render(rsx! {
-        div {
-            ul {
-                for name in names.read().iter() {
-                    li { "hello: {name}" }
-                }
-            }
-            button {
-                onclick: move |_| {
-                    let names = names.clone();
-                    cx.spawn(async move {
-                        names.write().push("asd".to_string());
-                    })
-                },
-                "Add name"
-            }
-        }
-    })
-}

+ 14 - 10
examples/file_explorer.rs

@@ -8,30 +8,34 @@
 //! It also uses `use_ref` to maintain a model, rather than `use_state`. That way,
 //! It also uses `use_ref` to maintain a model, rather than `use_state`. That way,
 //! we dont need to clutter our code with `read` commands.
 //! we dont need to clutter our code with `read` commands.
 
 
+use dioxus::desktop::{Config, WindowBuilder};
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::{Config, WindowBuilder};
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch_cfg(
-        app,
-        Config::new().with_window(WindowBuilder::new().with_resizable(true)),
-    );
+    LaunchBuilder::desktop()
+        .with_cfg(Config::new().with_window(WindowBuilder::new().with_resizable(true)))
+        .launch(app)
 }
 }
 
 
+#[cfg(not(feature = "collect-assets"))]
+const _STYLE: &str = include_str!("../examples/assets/fileexplorer.css");
+
+#[cfg(feature = "collect-assets")]
 const _STYLE: &str = manganis::mg!(file("./examples/assets/fileexplorer.css"));
 const _STYLE: &str = manganis::mg!(file("./examples/assets/fileexplorer.css"));
 
 
-fn app(cx: Scope) -> Element {
-    let files = use_ref(cx, Files::new);
+fn app() -> Element {
+    let mut files = use_signal(Files::new);
 
 
-    cx.render(rsx! {
+    rsx! {
         div {
         div {
-            link { href:"https://fonts.googleapis.com/icon?family=Material+Icons", rel:"stylesheet", }
+            link { href:"https://fonts.googleapis.com/icon?family=Material+Icons", rel:"stylesheet" }
             header {
             header {
                 i { class: "material-icons icon-menu", "menu" }
                 i { class: "material-icons icon-menu", "menu" }
                 h1 { "Files: ", {files.read().current()} }
                 h1 { "Files: ", {files.read().current()} }
                 span { }
                 span { }
                 i { class: "material-icons", onclick: move |_| files.write().go_up(), "logout" }
                 i { class: "material-icons", onclick: move |_| files.write().go_up(), "logout" }
             }
             }
+            style { "{_STYLE}" }
             main {
             main {
                 {files.read().path_names.iter().enumerate().map(|(dir_id, path)| {
                 {files.read().path_names.iter().enumerate().map(|(dir_id, path)| {
                     let path_end = path.split('/').last().unwrap_or(path.as_str());
                     let path_end = path.split('/').last().unwrap_or(path.as_str());
@@ -60,7 +64,7 @@ fn app(cx: Scope) -> Element {
                 }
                 }
             }
             }
         }
         }
-    })
+    }
 }
 }
 
 
 struct Files {
 struct Files {

+ 31 - 39
examples/file_upload.rs

@@ -4,21 +4,38 @@ use dioxus::prelude::*;
 use tokio::time::sleep;
 use tokio::time::sleep;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(App);
+    launch(App);
 }
 }
 
 
-fn App(cx: Scope) -> Element {
-    let enable_directory_upload = use_state(cx, || false);
-    let files_uploaded: &UseRef<Vec<String>> = use_ref(cx, Vec::new);
+fn App() -> Element {
+    let mut enable_directory_upload = use_signal(|| false);
+    let mut files_uploaded = use_signal(|| Vec::new() as Vec<String>);
 
 
-    cx.render(rsx! {
+    let upload_files = move |evt: FormEvent| async move {
+        for file_name in evt.files().unwrap().files() {
+            // no files on form inputs?
+            sleep(std::time::Duration::from_secs(1)).await;
+            files_uploaded.write().push(file_name);
+        }
+    };
+
+    let handle_file_drop = move |evt: DragEvent| async move {
+        if let Some(file_engine) = &evt.files() {
+            let files = file_engine.files();
+            for file_name in &files {
+                if let Some(file) = file_engine.read_file_to_string(file_name).await {
+                    files_uploaded.write().push(file);
+                }
+            }
+        }
+    };
+
+    rsx! {
         label {
         label {
             input {
             input {
                 r#type: "checkbox",
                 r#type: "checkbox",
-                checked: "{enable_directory_upload}",
-                oninput: move |evt| {
-                    enable_directory_upload.set(evt.value().parse().unwrap());
-                },
+                checked: enable_directory_upload,
+                oninput: move |evt| enable_directory_upload.set(evt.checked()),
             },
             },
             "Enable directory upload"
             "Enable directory upload"
         }
         }
@@ -27,41 +44,16 @@ fn App(cx: Scope) -> Element {
             r#type: "file",
             r#type: "file",
             accept: ".txt,.rs",
             accept: ".txt,.rs",
             multiple: true,
             multiple: true,
-            directory: **enable_directory_upload,
-            onchange: |evt| {
-                to_owned![files_uploaded];
-                async move {
-                    if let Some(file_engine) = &evt.files() {
-                        let files = file_engine.files();
-                        for file_name in files {
-                            sleep(std::time::Duration::from_secs(1)).await;
-                            files_uploaded.write().push(file_name);
-                        }
-                    }
-                }
-            },
+            directory: enable_directory_upload,
+            onchange: upload_files,
         }
         }
         div {
         div {
             width: "100px",
             width: "100px",
             height: "100px",
             height: "100px",
             border: "1px solid black",
             border: "1px solid black",
             prevent_default: "ondrop dragover dragenter",
             prevent_default: "ondrop dragover dragenter",
-            ondrop: move |evt| {
-                to_owned![files_uploaded];
-                async move {
-                    if let Some(file_engine) = &evt.files() {
-                        let files = file_engine.files();
-                        for file_name in &files {
-                            if let Some(file) = file_engine.read_file_to_string(file_name).await{
-                                files_uploaded.write().push(file);
-                            }
-                        }
-                    }
-                }
-            },
-            ondragover: move |event: DragEvent| {
-                event.stop_propagation();
-            },
+            ondrop: handle_file_drop,
+            ondragover: move |event| event.stop_propagation(),
             "Drop files here"
             "Drop files here"
         }
         }
 
 
@@ -70,5 +62,5 @@ fn App(cx: Scope) -> Element {
                 li { "{file}" }
                 li { "{file}" }
             }
             }
         }
         }
-    })
+    }
 }
 }

+ 11 - 13
examples/filedragdrop.rs

@@ -1,19 +1,17 @@
+use dioxus::desktop::Config;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::Config;
 
 
 fn main() {
 fn main() {
-    let cfg = Config::new().with_file_drop_handler(|_w, e| {
-        println!("{e:?}");
-        true
-    });
-
-    dioxus_desktop::launch_with_props(app, (), cfg);
+    LaunchBuilder::desktop()
+        .with_cfg(Config::new().with_file_drop_handler(|_w, e| {
+            println!("{e:?}");
+            true
+        }))
+        .launch(app)
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx!(
-        div {
-            h1 { "drag a file here and check your console" }
-        }
-    ))
+fn app() -> Element {
+    rsx!(
+        div { h1 { "drag a file here and check your console" } }
+    )
 }
 }

+ 37 - 43
examples/flat_router.rs

@@ -1,24 +1,11 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::{tao::dpi::LogicalSize, Config, WindowBuilder};
-use dioxus_router::prelude::*;
 
 
 fn main() {
 fn main() {
-    env_logger::init();
-
-    let cfg = Config::new().with_window(
-        WindowBuilder::new()
-            .with_inner_size(LogicalSize::new(600, 1000))
-            .with_resizable(false),
-    );
-
-    dioxus_desktop::launch_cfg(App, cfg)
-}
-
-#[component]
-fn App(cx: Scope) -> Element {
-    render! {
-        Router::<Route> {}
-    }
+    launch(|| {
+        rsx! {
+            Router::<Route> {}
+        }
+    })
 }
 }
 
 
 #[derive(Routable, Clone)]
 #[derive(Routable, Clone)]
@@ -27,52 +14,59 @@ enum Route {
     #[layout(Footer)]
     #[layout(Footer)]
         #[route("/")]
         #[route("/")]
         Home {},
         Home {},
+
         #[route("/games")]
         #[route("/games")]
         Games {},
         Games {},
+
         #[route("/play")]
         #[route("/play")]
         Play {},
         Play {},
+
         #[route("/settings")]
         #[route("/settings")]
         Settings {},
         Settings {},
 }
 }
 
 
 #[component]
 #[component]
-fn Footer(cx: Scope) -> Element {
-    render! {
-        div {
-            Outlet::<Route> { }
-
-            p {
-                "----"
-            }
-
-            nav {
-                ul {
-                    li { Link { to: Route::Home {}, "Home" } }
-                    li { Link { to: Route::Games {}, "Games" } }
-                    li { Link { to: Route::Play {}, "Play" } }
-                    li { Link { to: Route::Settings {}, "Settings" } }
-                }
-            }
+fn Footer() -> Element {
+    rsx! {
+        Outlet::<Route> {}
+        p { "----" }
+        nav {
+            style { {STYLE} }
+            Link { to: Route::Home {}, class: "nav-btn", "Home" }
+            Link { to: Route::Games {}, class: "nav-btn", "Games" }
+            Link { to: Route::Play {}, class: "nav-btn", "Play" }
+            Link { to: Route::Settings {}, class: "nav-btn", "Settings" }
         }
         }
     }
     }
 }
 }
 
 
 #[component]
 #[component]
-fn Home(cx: Scope) -> Element {
-    render!("Home")
+fn Home() -> Element {
+    rsx!("Home")
 }
 }
 
 
 #[component]
 #[component]
-fn Games(cx: Scope) -> Element {
-    render!("Games")
+fn Games() -> Element {
+    rsx!("Games")
 }
 }
 
 
 #[component]
 #[component]
-fn Play(cx: Scope) -> Element {
-    render!("Play")
+fn Play() -> Element {
+    rsx!("Play")
 }
 }
 
 
 #[component]
 #[component]
-fn Settings(cx: Scope) -> Element {
-    render!("Settings")
+fn Settings() -> Element {
+    rsx!("Settings")
 }
 }
+
+const STYLE: &str = r#"
+    nav {
+        display: flex;
+        justify-content: space-around;
+    }
+    .nav-btn {
+        text-decoration: none;
+        color: black;
+    }
+"#;

+ 4 - 4
examples/form.rs

@@ -6,11 +6,11 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
+fn app() -> Element {
+    rsx! {
         div {
         div {
             h1 { "Form" }
             h1 { "Form" }
             form {
             form {
@@ -24,5 +24,5 @@ fn app(cx: Scope) -> Element {
                 button { r#type: "submit", value: "Submit", "Submit the form" }
                 button { r#type: "submit", value: "Submit", "Submit the form" }
             }
             }
         }
         }
-    })
+    }
 }
 }

+ 0 - 152
examples/framework_benchmark.rs

@@ -1,152 +0,0 @@
-#![allow(non_snake_case)]
-
-use dioxus::prelude::*;
-use rand::prelude::*;
-
-fn main() {
-    dioxus_desktop::launch(app);
-}
-
-#[derive(Clone, PartialEq)]
-struct Label {
-    key: usize,
-    labels: [&'static str; 3],
-}
-
-impl Label {
-    fn new_list(num: usize) -> Vec<Self> {
-        let mut rng = SmallRng::from_entropy();
-        let mut labels = Vec::with_capacity(num);
-        for x in 0..num {
-            labels.push(Label {
-                key: x,
-                labels: [
-                    ADJECTIVES.choose(&mut rng).unwrap(),
-                    COLOURS.choose(&mut rng).unwrap(),
-                    NOUNS.choose(&mut rng).unwrap(),
-                ],
-            });
-        }
-        labels
-    }
-}
-
-fn app(cx: Scope) -> Element {
-    let items = use_ref(cx, Vec::new);
-    let selected = use_state(cx, || None);
-
-    cx.render(rsx! {
-        div { class: "container",
-            div { class: "jumbotron",
-                div { class: "row",
-                    div { class: "col-md-6", h1 { "Dioxus" } }
-                    div { class: "col-md-6",
-                        div { class: "row",
-                            ActionButton { name: "Create 1,000 rows", id: "run",
-                                onclick: move |_| items.set(Label::new_list(1_000)),
-                            }
-                            ActionButton { name: "Create 10,000 rows", id: "runlots",
-                                onclick: move |_| items.set(Label::new_list(10_000)),
-                            }
-                            ActionButton { name: "Append 1,000 rows", id: "add",
-                                onclick: move |_| items.write().extend(Label::new_list(1_000)),
-                            }
-                            ActionButton { name: "Update every 10th row", id: "update",
-                                onclick: move |_| items.write().iter_mut().step_by(10).for_each(|item| item.labels[2] = "!!!"),
-                            }
-                            ActionButton { name: "Clear", id: "clear",
-                                onclick: move |_| items.write().clear(),
-                            }
-                            ActionButton { name: "Swap rows", id: "swaprows",
-                                onclick: move |_| items.write().swap(0, 998),
-                            }
-                        }
-                    }
-                }
-            }
-            table {
-                tbody {
-                    for (id, item) in items.read().iter().enumerate() {
-                        tr {
-                            class: if (*selected).map(|s| s == id).unwrap_or(false) { "danger" },
-                            td { class:"col-md-1" }
-                            td { class:"col-md-1", "{item.key}" }
-                            td { class:"col-md-1", onclick: move |_| selected.set(Some(id)),
-                                a { class: "lbl", "{item.labels[0]}{item.labels[1]}{item.labels[2]}" }
-                            }
-                            td { class: "col-md-1",
-                                a { class: "remove", onclick: move |_| { items.write().remove(id); },
-                                    span { class: "glyphicon glyphicon-remove remove", aria_hidden: "true" }
-                                }
-                            }
-                            td { class: "col-md-6" }
-                        }
-                    }
-
-                }
-             }
-            span { class: "preloadicon glyphicon glyphicon-remove", aria_hidden: "true" }
-        }
-    })
-}
-
-#[derive(Props)]
-struct ActionButtonProps<'a> {
-    name: &'a str,
-    id: &'a str,
-    onclick: EventHandler<'a>,
-}
-
-fn ActionButton<'a>(cx: Scope<'a, ActionButtonProps<'a>>) -> Element {
-    cx.render(rsx! {
-        div {
-            class: "col-sm-6 smallpad",
-            button {
-                class:"btn btn-primary btn-block",
-                r#type: "button",
-                id: "{cx.props.id}",
-                onclick: move |_| cx.props.onclick.call(()),
-
-                "{cx.props.name}"
-            }
-        }
-    })
-}
-
-static ADJECTIVES: &[&str] = &[
-    "pretty",
-    "large",
-    "big",
-    "small",
-    "tall",
-    "short",
-    "long",
-    "handsome",
-    "plain",
-    "quaint",
-    "clean",
-    "elegant",
-    "easy",
-    "angry",
-    "crazy",
-    "helpful",
-    "mushy",
-    "odd",
-    "unsightly",
-    "adorable",
-    "important",
-    "inexpensive",
-    "cheap",
-    "expensive",
-    "fancy",
-];
-
-static COLOURS: &[&str] = &[
-    "red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black",
-    "orange",
-];
-
-static NOUNS: &[&str] = &[
-    "table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger",
-    "pizza", "mouse", "keyboard",
-];

+ 8 - 8
examples/generic_component.rs

@@ -3,22 +3,22 @@ use std::fmt::Display;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    render! {
+fn app() -> Element {
+    rsx! {
         generic_child { data: 0 }
         generic_child { data: 0 }
     }
     }
 }
 }
 
 
-#[derive(PartialEq, Props)]
-struct GenericChildProps<T: Display + PartialEq> {
+#[derive(PartialEq, Props, Clone)]
+struct GenericChildProps<T: Display + PartialEq + Clone + 'static> {
     data: T,
     data: T,
 }
 }
 
 
-fn generic_child<T: Display + PartialEq>(cx: Scope<GenericChildProps<T>>) -> Element {
-    render! {
-        div { "{&cx.props.data}" }
+fn generic_child<T: Display + PartialEq + Clone>(props: GenericChildProps<T>) -> Element {
+    rsx! {
+        div { "{props.data}" }
     }
     }
 }
 }

+ 20 - 0
examples/global.rs

@@ -0,0 +1,20 @@
+//! Example: README.md showcase
+//!
+//! The example from the README.md.
+
+use dioxus::prelude::*;
+
+fn main() {
+    launch(app);
+}
+
+static COUNT: GlobalSignal<i32> = Signal::global(|| 0);
+static DOUBLED_COUNT: GlobalMemo<i32> = Signal::global_memo(|| COUNT() * 2);
+
+fn app() -> Element {
+    rsx! {
+        h1 { "{COUNT} x 2 = {DOUBLED_COUNT}" }
+        button { onclick: move |_| *COUNT.write() += 1, "Up high!" }
+        button { onclick: move |_| *COUNT.write() -= 1, "Down low!" }
+    }
+}

+ 0 - 28
examples/heavy_compute.rs

@@ -1,28 +0,0 @@
-//! This example shows that you can place heavy work on the main thread, and then
-//!
-//! You *should* be using `tokio::spawn_blocking` instead.
-//!
-//! Your app runs in an async runtime (Tokio), so you should avoid blocking
-//! the rendering of the VirtualDom.
-//!
-//!
-
-use dioxus::prelude::*;
-
-fn main() {
-    dioxus_desktop::launch(app);
-}
-
-fn app(cx: Scope) -> Element {
-    // This is discouraged
-    std::thread::sleep(std::time::Duration::from_millis(2_000));
-
-    // This is suggested
-    tokio::task::spawn_blocking(move || {
-        std::thread::sleep(std::time::Duration::from_millis(2_000));
-    });
-
-    cx.render(rsx! {
-        div { "Hello, world!" }
-    })
-}

+ 3 - 3
examples/hello_world.rs

@@ -1,11 +1,11 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    render! {
+fn app() -> Element {
+    rsx! {
         div { "Hello, world!" }
         div { "Hello, world!" }
     }
     }
 }
 }

+ 14 - 13
examples/hydration.rs

@@ -9,27 +9,28 @@
 //! In this example, we pre-render the page to HTML and then pass it into the desktop configuration. This serves as a
 //! In this example, we pre-render the page to HTML and then pass it into the desktop configuration. This serves as a
 //! proof-of-concept for the hydration feature, but you'll probably only want to use hydration for the web.
 //! proof-of-concept for the hydration feature, but you'll probably only want to use hydration for the web.
 
 
+use dioxus::desktop::Config;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::Config;
 
 
 fn main() {
 fn main() {
-    let mut vdom = VirtualDom::new(app);
-    let _ = vdom.rebuild();
-    let content = dioxus_ssr::pre_render(&vdom);
+    LaunchBuilder::desktop()
+        .with_cfg(Config::new().with_prerendered({
+            // We build the dom a first time, then pre-render it to HTML
+            let pre_rendered_dom = VirtualDom::prebuilt(app);
 
 
-    dioxus_desktop::launch_cfg(app, Config::new().with_prerendered(content));
+            // We then launch the app with the pre-rendered HTML
+            dioxus_ssr::pre_render(&pre_rendered_dom)
+        }))
+        .launch(app)
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let val = use_state(cx, || 0);
+fn app() -> Element {
+    let mut val = use_signal(|| 0);
 
 
-    cx.render(rsx! {
+    rsx! {
         div {
         div {
             h1 { "hello world. Count: {val}" }
             h1 { "hello world. Count: {val}" }
-            button {
-                onclick: move |_| *val.make_mut() += 1,
-                "click to increment"
-            }
+            button { onclick: move |_| val += 1, "click to increment" }
         }
         }
-    })
+    }
 }
 }

+ 0 - 43
examples/inlineprops.rs

@@ -1,43 +0,0 @@
-//! Run with `cargo-expand` to see what each one expands to.
-//! This file is named `inlineprops.rs`, because there used to be a `#[inline_props]` macro to
-//! do this. However, it's now deprecated (and will likely be removed in a future major version),
-//! so please use `#[component]` instead!
-use dioxus::prelude::*;
-
-#[component]
-fn Thing1<T>(cx: Scope, _a: T) -> Element {
-    cx.render(rsx! { "" })
-}
-
-#[component]
-fn Thing2(cx: Scope, _a: u32) -> Element<'a> {
-    cx.render(rsx! { "" })
-}
-
-#[component]
-fn Thing3<'a, T>(cx: Scope<'a>, _a: &'a T) -> Element<'a> {
-    cx.render(rsx! { "" })
-}
-
-#[component]
-fn Thing4<'a>(cx: Scope<'a>, _a: &'a u32) -> Element<'a> {
-    cx.render(rsx! { "" })
-}
-
-fn main() {
-    dioxus_desktop::launch(App);
-}
-
-#[component]
-fn App(cx: Scope) -> Element {
-    let state = use_state(cx, || 1);
-
-    cx.render(rsx! {
-        div {
-            Thing1 { _a: 1 },
-            Thing2 { _a: 1 },
-            Thing3 { _a: state },
-            Thing4 { _a: state },
-        }
-    })
-}

+ 33 - 39
examples/inputs.rs

@@ -5,7 +5,7 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
 const FIELDS: &[(&str, &str)] = &[
 const FIELDS: &[(&str, &str)] = &[
@@ -34,23 +34,21 @@ const FIELDS: &[(&str, &str)] = &[
     ("week", ""),  // degrades to text most of the time
     ("week", ""),  // degrades to text most of the time
 ];
 ];
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
+fn app() -> Element {
+    rsx! {
         div { margin_left: "30px",
         div { margin_left: "30px",
-            {select_example(cx)},
+            {select_example()},
             div {
             div {
                 // handling inputs on divs will catch all input events below
                 // handling inputs on divs will catch all input events below
                 // so the value of our input event will be either huey, dewey, louie, or true/false (because of the checkboxe)
                 // so the value of our input event will be either huey, dewey, louie, or true/false (because of the checkboxe)
                 // be mindful in grouping inputs together, as they will all be handled by the same event handler
                 // be mindful in grouping inputs together, as they will all be handled by the same event handler
-                oninput: move |evt| {
-                    println!("{evt:?}");
-                },
+                oninput: move |evt| println!("{evt:?}"),
                 div {
                 div {
                     input {
                     input {
                         id: "huey",
                         id: "huey",
                         r#type: "radio",
                         r#type: "radio",
                         value: "huey",
                         value: "huey",
-                        checked: "",
+                        checked: true,
                         name: "drone",
                         name: "drone",
                     }
                     }
                     label {
                     label {
@@ -65,10 +63,7 @@ fn app(cx: Scope) -> Element {
                         value: "dewey",
                         value: "dewey",
                         name: "drone",
                         name: "drone",
                     }
                     }
-                    label {
-                        r#for: "dewey",
-                        "Dewey"
-                    }
+                    label { r#for: "dewey", "Dewey" }
                 }
                 }
                 div {
                 div {
                     input {
                     input {
@@ -133,36 +128,35 @@ fn app(cx: Scope) -> Element {
                 }
                 }
             }
             }
         }
         }
-    })
+    }
 }
 }
 
 
-fn select_example(cx: Scope) -> Element {
-    cx.render(rsx! {
-    div {
-        select {
-            id: "selection",
-            name: "selection",
-            multiple: true,
-            oninput: move |evt| {
-                println!("{evt:?}");
-            },
-            option {
-                value : "Option 1",
-                label : "Option 1",
+fn select_example() -> Element {
+    rsx! {
+        div {
+            select {
+                id: "selection",
+                name: "selection",
+                multiple: true,
+                oninput: move |evt| println!("{evt:?}"),
+                option {
+                    value: "Option 1",
+                    label: "Option 1",
+                }
+                option {
+                    value: "Option 2",
+                    label: "Option 2",
+                    selected: true,
+                },
+                option {
+                    value: "Option 3",
+                    label: "Option 3",
+                }
             }
             }
-            option {
-                value : "Option 2",
-                label : "Option 2",
-                selected : true,
-            },
-            option {
-                value : "Option 3",
-                label : "Option 3",
+            label {
+                r#for: "selection",
+                "select element"
             }
             }
         }
         }
-        label {
-            r#for: "selection",
-            "select element"
-        }
-    }})
+    }
 }
 }

+ 19 - 20
examples/link.rs

@@ -1,30 +1,25 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_router::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(App);
+    launch_desktop(App);
 }
 }
 
 
 #[component]
 #[component]
-fn App(cx: Scope) -> Element {
-    cx.render(rsx! (
+fn App() -> Element {
+    rsx! (
         div {
         div {
-            p {
-                a { href: "http://dioxuslabs.com/", "Default link - links outside of your app" }
-            }
+            p { a { href: "http://dioxuslabs.com/", "Default link - links outside of your app" } }
             p {
             p {
                 a {
                 a {
                     href: "http://dioxuslabs.com/",
                     href: "http://dioxuslabs.com/",
                     prevent_default: "onclick",
                     prevent_default: "onclick",
                     onclick: |_| println!("Hello Dioxus"),
                     onclick: |_| println!("Hello Dioxus"),
-                    "Custom event link - links inside of your app",
+                    "Custom event link - links inside of your app"
                 }
                 }
             }
             }
         }
         }
-        div {
-            Router::<Route> {}
-        }
-    ))
+        div { Router::<Route> {} }
+    )
 }
 }
 
 
 #[derive(Routable, Clone)]
 #[derive(Routable, Clone)]
@@ -38,23 +33,27 @@ enum Route {
 }
 }
 
 
 #[component]
 #[component]
-fn Header(cx: Scope) -> Element {
-    render! {
+fn Header() -> Element {
+    rsx! {
         h1 { "Your app here" }
         h1 { "Your app here" }
         ul {
         ul {
-            li { Link { to: Route::Home {}, "home" } }
-            li { Link { to: Route::Settings {}, "settings" } }
+            li {
+                Link { to: Route::Home {}, "home" }
+            }
+            li {
+                Link { to: Route::Settings {}, "settings" }
+            }
         }
         }
         Outlet::<Route> {}
         Outlet::<Route> {}
     }
     }
 }
 }
 
 
 #[component]
 #[component]
-fn Home(cx: Scope) -> Element {
-    render!(h1 { "Home" })
+fn Home() -> Element {
+    rsx!( h1 { "Home" } )
 }
 }
 
 
 #[component]
 #[component]
-fn Settings(cx: Scope) -> Element {
-    render!(h1 { "Settings" })
+fn Settings() -> Element {
+    rsx!( h1 { "Settings" } )
 }
 }

+ 5 - 5
examples/login_form.rs

@@ -4,10 +4,10 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
+fn app() -> Element {
     let onsubmit = move |evt: FormEvent| async move {
     let onsubmit = move |evt: FormEvent| async move {
         let resp = reqwest::Client::new()
         let resp = reqwest::Client::new()
             .post("http://localhost:8080/login")
             .post("http://localhost:8080/login")
@@ -29,9 +29,9 @@ fn app(cx: Scope) -> Element {
         }
         }
     };
     };
 
 
-    cx.render(rsx! {
+    rsx! {
         h1 { "Login" }
         h1 { "Login" }
-        form { onsubmit: onsubmit,
+        form { onsubmit,
             input { r#type: "text", id: "username", name: "username" }
             input { r#type: "text", id: "username", name: "username" }
             label { "Username" }
             label { "Username" }
             br {}
             br {}
@@ -40,5 +40,5 @@ fn app(cx: Scope) -> Element {
             br {}
             br {}
             button { "Login" }
             button { "Login" }
         }
         }
-    })
+    }
 }
 }

+ 44 - 0
examples/memo_chain.rs

@@ -0,0 +1,44 @@
+use dioxus::prelude::*;
+
+fn main() {
+    launch_desktop(app);
+}
+
+fn app() -> Element {
+    let mut value = use_signal(|| 0);
+    let mut depth = use_signal(|| 0_usize);
+    let items = use_memo(move || (0..depth()).map(|f| f as _).collect::<Vec<isize>>());
+    let state = use_memo(move || value() + 1);
+
+    println!("rendering app");
+
+    rsx! {
+        button { onclick: move |_| value += 1, "Increment" }
+        button { onclick: move |_| depth += 1, "Add depth" }
+        button { onclick: move |_| depth -= 1, "Remove depth" }
+        Child { depth, items, state }
+    }
+}
+
+#[component]
+fn Child(
+    state: ReadOnlySignal<isize>,
+    items: ReadOnlySignal<Vec<isize>>,
+    depth: ReadOnlySignal<usize>,
+) -> Element {
+    if depth() == 0 {
+        return None;
+    }
+
+    // These memos don't get re-computed when early returns happen
+    let state = use_memo(move || state() + 1);
+    let item = use_memo(move || items()[depth()]);
+    let depth = use_memo(move || depth() - 1);
+
+    println!("rendering child: {}", depth());
+
+    rsx! {
+        h3 { "Depth({depth})-Item({item}): {state}"}
+        Child { depth, state, items }
+    }
+}

+ 1 - 1
examples/mobile_demo/Cargo.toml

@@ -2,7 +2,7 @@
 name = "mobile-demo"
 name = "mobile-demo"
 version = "0.1.0"
 version = "0.1.0"
 authors = ["Jonathan Kelley <jkelleyrtp@gmail.com>"]
 authors = ["Jonathan Kelley <jkelleyrtp@gmail.com>"]
-edition = "2018"
+edition = "2021"
 
 
 [lib]
 [lib]
 crate-type = ["staticlib", "cdylib", "rlib"]
 crate-type = ["staticlib", "cdylib", "rlib"]

+ 12 - 8
examples/mobile_demo/src/lib.rs

@@ -1,6 +1,6 @@
 use anyhow::Result;
 use anyhow::Result;
+use dioxus::desktop::Config;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::Config;
 #[cfg(target_os = "android")]
 #[cfg(target_os = "android")]
 use wry::android_binding;
 use wry::android_binding;
 
 
@@ -49,8 +49,7 @@ pub fn main() -> Result<()> {
 
 
     // Right now we're going through dioxus-desktop but we'd like to go through dioxus-mobile
     // Right now we're going through dioxus-desktop but we'd like to go through dioxus-mobile
     // That will seed the index.html with some fixes that prevent the page from scrolling/zooming etc
     // That will seed the index.html with some fixes that prevent the page from scrolling/zooming etc
-    dioxus_desktop::launch_cfg(
-        app,
+    LaunchBuilder::new().cfg(
         // Note that we have to disable the viewport goofiness of the browser.
         // Note that we have to disable the viewport goofiness of the browser.
         // Dioxus_mobile should do this for us
         // Dioxus_mobile should do this for us
         Config::default().with_custom_index(include_str!("index.html").to_string()),
         Config::default().with_custom_index(include_str!("index.html").to_string()),
@@ -59,17 +58,22 @@ pub fn main() -> Result<()> {
     Ok(())
     Ok(())
 }
 }
 
 
-fn app(cx: Scope) -> Element {
+fn app() -> Element {
     let items = cx.use_hook(|| vec![1, 2, 3]);
     let items = cx.use_hook(|| vec![1, 2, 3]);
 
 
     log::debug!("Hello from the app");
     log::debug!("Hello from the app");
 
 
-    render! {
+    rsx! {
         div {
         div {
-            h1 { "Hello, Mobile"}
-            div { margin_left: "auto", margin_right: "auto", width: "200px", padding: "10px", border: "1px solid black",
+            h1 { "Hello, Mobile" }
+            div {
+                margin_left: "auto",
+                margin_right: "auto",
+                width: "200px",
+                padding: "10px",
+                border: "1px solid black",
                 button {
                 button {
-                    onclick: move|_| {
+                    onclick: move |_| {
                         println!("Clicked!");
                         println!("Clicked!");
                         items.push(items.len());
                         items.push(items.len());
                         cx.needs_update_any(ScopeId::ROOT);
                         cx.needs_update_any(ScopeId::ROOT);

+ 14 - 17
examples/multiwindow.rs

@@ -1,25 +1,22 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
-        div {
-            button {
-                onclick: move |_| {
-                    let dom = VirtualDom::new(popup);
-                    dioxus_desktop::window().new_window(dom, Default::default());
-                },
-                "New Window"
-            }
-        }
-    })
+fn app() -> Element {
+    let onclick = move |_| {
+        let dom = VirtualDom::new(popup);
+        dioxus::desktop::window().new_window(dom, Default::default());
+    };
+
+    rsx! {
+        button { onclick, "New Window" }
+    }
 }
 }
 
 
-fn popup(cx: Scope) -> Element {
-    cx.render(rsx! {
-        div { "This is a popup!" }
-    })
+fn popup() -> Element {
+    rsx! {
+        div { "This is a popup window!" }
+    }
 }
 }

+ 4 - 4
examples/nested_listeners.rs

@@ -7,11 +7,11 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
+fn app() -> Element {
+    rsx! {
         div {
         div {
             onclick: move |_| println!("clicked! top"),
             onclick: move |_| println!("clicked! top"),
             "- div"
             "- div"
@@ -30,5 +30,5 @@ fn app(cx: Scope) -> Element {
                 "Does not handle clicks - only propagate"
                 "Does not handle clicks - only propagate"
             }
             }
         }
         }
-    })
+    }
 }
 }

+ 4 - 6
examples/openid_connect_demo/src/main.rs

@@ -14,8 +14,6 @@ pub(crate) mod views;
 use oidc::{AuthRequestState, AuthTokenState};
 use oidc::{AuthRequestState, AuthTokenState};
 use router::Route;
 use router::Route;
 
 
-use dioxus_router::prelude::*;
-
 use crate::{
 use crate::{
     constants::{DIOXUS_FRONT_AUTH_REQUEST, DIOXUS_FRONT_AUTH_TOKEN},
     constants::{DIOXUS_FRONT_AUTH_REQUEST, DIOXUS_FRONT_AUTH_TOKEN},
     oidc::ClientState,
     oidc::ClientState,
@@ -30,14 +28,14 @@ pub static DIOXUS_FRONT_ISSUER_URL: &str = env!("DIOXUS_FRONT_ISSUER_URL");
 pub static DIOXUS_FRONT_CLIENT_ID: &str = env!("DIOXUS_FRONT_CLIENT_ID");
 pub static DIOXUS_FRONT_CLIENT_ID: &str = env!("DIOXUS_FRONT_CLIENT_ID");
 pub static DIOXUS_FRONT_URL: &str = env!("DIOXUS_FRONT_URL");
 pub static DIOXUS_FRONT_URL: &str = env!("DIOXUS_FRONT_URL");
 
 
-fn App(cx: Scope) -> Element {
+fn App() -> Element {
     use_init_atom_root(cx);
     use_init_atom_root(cx);
 
 
     // Retrieve the value stored in the browser's storage
     // Retrieve the value stored in the browser's storage
     let stored_auth_token = LocalStorage::get(DIOXUS_FRONT_AUTH_TOKEN)
     let stored_auth_token = LocalStorage::get(DIOXUS_FRONT_AUTH_TOKEN)
         .ok()
         .ok()
         .unwrap_or(AuthTokenState::default());
         .unwrap_or(AuthTokenState::default());
-    let fermi_auth_token = use_atom_ref(cx, &FERMI_AUTH_TOKEN);
+    let fermi_auth_token = use_atom_ref(&FERMI_AUTH_TOKEN);
     if fermi_auth_token.read().is_none() {
     if fermi_auth_token.read().is_none() {
         *fermi_auth_token.write() = Some(stored_auth_token);
         *fermi_auth_token.write() = Some(stored_auth_token);
     }
     }
@@ -45,11 +43,11 @@ fn App(cx: Scope) -> Element {
     let stored_auth_request = LocalStorage::get(DIOXUS_FRONT_AUTH_REQUEST)
     let stored_auth_request = LocalStorage::get(DIOXUS_FRONT_AUTH_REQUEST)
         .ok()
         .ok()
         .unwrap_or(AuthRequestState::default());
         .unwrap_or(AuthRequestState::default());
-    let fermi_auth_request = use_atom_ref(cx, &FERMI_AUTH_REQUEST);
+    let fermi_auth_request = use_atom_ref(&FERMI_AUTH_REQUEST);
     if fermi_auth_request.read().is_none() {
     if fermi_auth_request.read().is_none() {
         *fermi_auth_request.write() = Some(stored_auth_request);
         *fermi_auth_request.write() = Some(stored_auth_request);
     }
     }
-    render! { Router::<Route> {} }
+    rsx! { Router::<Route> {} }
 }
 }
 
 
 fn main() {
 fn main() {

+ 0 - 1
examples/openid_connect_demo/src/router.rs

@@ -1,6 +1,5 @@
 use crate::views::{header::AuthHeader, home::Home, login::Login, not_found::NotFound};
 use crate::views::{header::AuthHeader, home::Home, login::Login, not_found::NotFound};
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_router::prelude::*;
 
 
 #[derive(Routable, Clone)]
 #[derive(Routable, Clone)]
 pub enum Route {
 pub enum Route {

+ 15 - 17
examples/openid_connect_demo/src/views/header.rs

@@ -9,15 +9,15 @@ use crate::{
     FERMI_AUTH_REQUEST, FERMI_AUTH_TOKEN, FERMI_CLIENT,
     FERMI_AUTH_REQUEST, FERMI_AUTH_TOKEN, FERMI_CLIENT,
 };
 };
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_router::prelude::{Link, Outlet};
+use dioxus::router::prelude::{Link, Outlet};
 use fermi::*;
 use fermi::*;
 use openidconnect::{url::Url, OAuth2TokenResponse, TokenResponse};
 use openidconnect::{url::Url, OAuth2TokenResponse, TokenResponse};
 
 
 #[component]
 #[component]
 pub fn LogOut(cx: Scope<ClientProps>) -> Element {
 pub fn LogOut(cx: Scope<ClientProps>) -> Element {
-    let fermi_auth_token = use_atom_ref(cx, &FERMI_AUTH_TOKEN);
+    let fermi_auth_token = use_atom_ref(&FERMI_AUTH_TOKEN);
     let fermi_auth_token_read = fermi_auth_token.read().clone();
     let fermi_auth_token_read = fermi_auth_token.read().clone();
-    let log_out_url_state = use_state(cx, || None::<Option<Result<Url, crate::errors::Error>>>);
+    let log_out_url_state = use_signal(|| None::<Option<Result<Url, crate::errors::Error>>>);
     cx.render(match fermi_auth_token_read {
     cx.render(match fermi_auth_token_read {
         Some(fermi_auth_token_read) => match fermi_auth_token_read.id_token.clone() {
         Some(fermi_auth_token_read) => match fermi_auth_token_read.id_token.clone() {
             Some(id_token) => match log_out_url_state.get() {
             Some(id_token) => match log_out_url_state.get() {
@@ -40,9 +40,7 @@ pub fn LogOut(cx: Scope<ClientProps>) -> Element {
                             }
                             }
                         }
                         }
                         Err(error) => {
                         Err(error) => {
-                            rsx! {
-                                div { "Failed to load disconnection url: {error:?}" }
-                            }
+                            rsx! { div { "Failed to load disconnection url: {error:?}" } }
                         }
                         }
                     },
                     },
                     None => {
                     None => {
@@ -61,7 +59,7 @@ pub fn LogOut(cx: Scope<ClientProps>) -> Element {
                         })
                         })
                     };
                     };
                     logout_url_task();
                     logout_url_task();
-                    rsx! { div{"Loading log out url... Please wait"}}
+                    rsx! { div { "Loading log out url... Please wait" } }
                 }
                 }
             },
             },
             None => {
             None => {
@@ -76,8 +74,8 @@ pub fn LogOut(cx: Scope<ClientProps>) -> Element {
 
 
 #[component]
 #[component]
 pub fn RefreshToken(cx: Scope<ClientProps>) -> Element {
 pub fn RefreshToken(cx: Scope<ClientProps>) -> Element {
-    let fermi_auth_token = use_atom_ref(cx, &FERMI_AUTH_TOKEN);
-    let fermi_auth_request = use_atom_ref(cx, &FERMI_AUTH_REQUEST);
+    let fermi_auth_token = use_atom_ref(&FERMI_AUTH_TOKEN);
+    let fermi_auth_request = use_atom_ref(&FERMI_AUTH_REQUEST);
     let fermi_auth_token_read = fermi_auth_token.read().clone();
     let fermi_auth_token_read = fermi_auth_token.read().clone();
     cx.render(match fermi_auth_token_read {
     cx.render(match fermi_auth_token_read {
         Some(fermi_auth_client_read) => match fermi_auth_client_read.refresh_token {
         Some(fermi_auth_client_read) => match fermi_auth_client_read.refresh_token {
@@ -128,9 +126,9 @@ pub fn RefreshToken(cx: Scope<ClientProps>) -> Element {
 }
 }
 
 
 #[component]
 #[component]
-pub fn LoadClient(cx: Scope) -> Element {
-    let init_client_future = use_future(cx, (), |_| async move { init_oidc_client().await });
-    let fermi_client: &UseAtomRef<ClientState> = use_atom_ref(cx, &FERMI_CLIENT);
+pub fn LoadClient() -> Element {
+    let init_client_future = use_future(move || async move { init_oidc_client().await });
+    let fermi_client: &UseAtomRef<ClientState> = use_atom_ref(&FERMI_CLIENT);
     cx.render(match init_client_future.value() {
     cx.render(match init_client_future.value() {
         Some(client_props) => match client_props {
         Some(client_props) => match client_props {
             Ok((client_id, client)) => {
             Ok((client_id, client)) => {
@@ -162,10 +160,10 @@ pub fn LoadClient(cx: Scope) -> Element {
 }
 }
 
 
 #[component]
 #[component]
-pub fn AuthHeader(cx: Scope) -> Element {
-    let auth_token = use_atom_ref(cx, &FERMI_AUTH_TOKEN);
-    let fermi_auth_request = use_atom_ref(cx, &FERMI_AUTH_REQUEST);
-    let fermi_client: &UseAtomRef<ClientState> = use_atom_ref(cx, &FERMI_CLIENT);
+pub fn AuthHeader() -> Element {
+    let auth_token = use_atom_ref(&FERMI_AUTH_TOKEN);
+    let fermi_auth_request = use_atom_ref(&FERMI_AUTH_REQUEST);
+    let fermi_client: &UseAtomRef<ClientState> = use_atom_ref(&FERMI_CLIENT);
     let client = fermi_client.read().oidc_client.clone();
     let client = fermi_client.read().oidc_client.clone();
     let auth_request_read = fermi_auth_request.read().clone();
     let auth_request_read = fermi_auth_request.read().clone();
     let auth_token_read = auth_token.read().clone();
     let auth_token_read = auth_token.read().clone();
@@ -197,7 +195,7 @@ pub fn AuthHeader(cx: Scope) -> Element {
                                         log::info!("Token expired");
                                         log::info!("Token expired");
                                         rsx! {
                                         rsx! {
                                             div {
                                             div {
-                                                RefreshToken {client_id: client_props.client_id, client: client_props.client}
+                                                RefreshToken { client_id: client_props.client_id, client: client_props.client }
                                                 Outlet::<Route> {}
                                                 Outlet::<Route> {}
                                             }
                                             }
                                         }
                                         }

+ 2 - 2
examples/openid_connect_demo/src/views/home.rs

@@ -1,5 +1,5 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
-pub fn Home(cx: Scope) -> Element {
-    render! { div { "Hello world" } }
+pub fn Home() -> Element {
+    rsx! { div { "Hello world" } }
 }
 }

+ 5 - 5
examples/openid_connect_demo/src/views/login.rs

@@ -5,16 +5,16 @@ use crate::{
     DIOXUS_FRONT_URL, FERMI_AUTH_REQUEST, FERMI_AUTH_TOKEN, FERMI_CLIENT,
     DIOXUS_FRONT_URL, FERMI_AUTH_REQUEST, FERMI_AUTH_TOKEN, FERMI_CLIENT,
 };
 };
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_router::prelude::{Link, NavigationTarget};
+use dioxus::router::prelude::{Link, NavigationTarget};
 use fermi::*;
 use fermi::*;
 use openidconnect::{OAuth2TokenResponse, TokenResponse};
 use openidconnect::{OAuth2TokenResponse, TokenResponse};
 
 
 #[component]
 #[component]
-pub fn Login(cx: Scope, query_string: String) -> Element {
-    let fermi_client = use_atom_ref(cx, &FERMI_CLIENT);
-    let fermi_auth_token = use_atom_ref(cx, &FERMI_AUTH_TOKEN);
+pub fn Login(query_string: String) -> Element {
+    let fermi_client = use_atom_ref(&FERMI_CLIENT);
+    let fermi_auth_token = use_atom_ref(&FERMI_AUTH_TOKEN);
     let home_url: NavigationTarget<Route> = DIOXUS_FRONT_URL.parse().unwrap();
     let home_url: NavigationTarget<Route> = DIOXUS_FRONT_URL.parse().unwrap();
-    let fermi_auth_request = use_atom_ref(cx, &FERMI_AUTH_REQUEST);
+    let fermi_auth_request = use_atom_ref(&FERMI_AUTH_REQUEST);
     let client = fermi_client.read().oidc_client.clone();
     let client = fermi_client.read().oidc_client.clone();
     let auth_token_read = fermi_auth_token.read().clone();
     let auth_token_read = fermi_auth_token.read().clone();
     cx.render(match (client, auth_token_read) {
     cx.render(match (client, auth_token_read) {

+ 2 - 2
examples/openid_connect_demo/src/views/not_found.rs

@@ -1,8 +1,8 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 #[component]
 #[component]
-pub fn NotFound(cx: Scope, route: Vec<String>) -> Element {
-    render! {
+pub fn NotFound(route: Vec<String>) -> Element {
+    rsx! {
         div{
         div{
             {route.join("")}
             {route.join("")}
         }
         }

+ 15 - 15
examples/optional_props.rs

@@ -7,11 +7,11 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
+fn app() -> Element {
+    rsx! {
         Button {
         Button {
             a: "asd".to_string(),
             a: "asd".to_string(),
             c: "asd".to_string(),
             c: "asd".to_string(),
@@ -30,12 +30,10 @@ fn app(cx: Scope) -> Element {
             c: "asd".to_string(),
             c: "asd".to_string(),
             d: Some("asd".to_string()),
             d: Some("asd".to_string()),
         }
         }
-    })
+    }
 }
 }
 
 
-type SthElse<T> = Option<T>;
-
-#[derive(Props, PartialEq)]
+#[derive(Props, PartialEq, Clone)]
 struct ButtonProps {
 struct ButtonProps {
     a: String,
     a: String,
 
 
@@ -51,14 +49,16 @@ struct ButtonProps {
     e: SthElse<String>,
     e: SthElse<String>,
 }
 }
 
 
-fn Button(cx: Scope<ButtonProps>) -> Element {
-    cx.render(rsx! {
+type SthElse<T> = Option<T>;
+
+fn Button(props: ButtonProps) -> Element {
+    rsx! {
         button {
         button {
-            "{cx.props.a} | "
-            "{cx.props.b:?} | "
-            "{cx.props.c:?} | "
-            "{cx.props.d:?} | "
-            "{cx.props.e:?}"
+            "{props.a} | "
+            "{props.b:?} | "
+            "{props.c:?} | "
+            "{props.d:?} | "
+            "{props.e:?}"
         }
         }
-    })
+    }
 }
 }

+ 8 - 8
examples/overlay.rs

@@ -1,12 +1,12 @@
+use dioxus::desktop::{tao::dpi::PhysicalPosition, LogicalSize, WindowBuilder};
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::{tao::dpi::PhysicalPosition, LogicalSize, WindowBuilder};
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch_cfg(app, make_config());
+    LaunchBuilder::desktop().with_cfg(make_config()).launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
+fn app() -> Element {
+    rsx! {
         div {
         div {
             width: "100%",
             width: "100%",
             height: "100%",
             height: "100%",
@@ -17,16 +17,16 @@ fn app(cx: Scope) -> Element {
                 width: "100%",
                 width: "100%",
                 height: "10px",
                 height: "10px",
                 background_color: "black",
                 background_color: "black",
-                onmousedown: move |_| dioxus_desktop::window().drag(),
+                onmousedown: move |_| dioxus::desktop::window().drag(),
             }
             }
 
 
             "This is an overlay!"
             "This is an overlay!"
         }
         }
-    })
+    }
 }
 }
 
 
-fn make_config() -> dioxus_desktop::Config {
-    dioxus_desktop::Config::default()
+fn make_config() -> dioxus::desktop::Config {
+    dioxus::desktop::Config::default()
         .with_window(make_window())
         .with_window(make_window())
         .with_custom_head(
         .with_custom_head(
             r#"
             r#"

+ 14 - 17
examples/query_segments_demo/src/main.rs → examples/query_segments.rs

@@ -1,16 +1,12 @@
-#![allow(unused)]
 //! Example: Url query segments usage
 //! Example: Url query segments usage
 //! ------------------------------------
 //! ------------------------------------
 //!
 //!
 //! This example shows how to access and use multiple query segments present in an url on the web.
 //! This example shows how to access and use multiple query segments present in an url on the web.
 //!
 //!
 //! Run `dx serve` and navigate to `http://localhost:8080/blog?name=John&surname=Doe`
 //! Run `dx serve` and navigate to `http://localhost:8080/blog?name=John&surname=Doe`
-use std::fmt::Display;
-
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_router::prelude::*;
+use std::fmt::Display;
 
 
-// ANCHOR: route
 #[derive(Routable, Clone)]
 #[derive(Routable, Clone)]
 #[rustfmt::skip]
 #[rustfmt::skip]
 enum Route {
 enum Route {
@@ -20,6 +16,7 @@ enum Route {
         // You must include query segments in child variants
         // You must include query segments in child variants
         query_params: ManualBlogQuerySegments,
         query_params: ManualBlogQuerySegments,
     },
     },
+
     // segments that follow the ?:field&:other_field syntax are query segments that follow the standard url query syntax
     // segments that follow the ?:field&:other_field syntax are query segments that follow the standard url query syntax
     #[route("/autoblog?:name&:surname")]
     #[route("/autoblog?:name&:surname")]
     AutomaticBlogPost {
     AutomaticBlogPost {
@@ -41,7 +38,7 @@ impl Display for ManualBlogQuerySegments {
     }
     }
 }
 }
 
 
-/// The query segment is anything that implements <https://docs.rs/dioxus-router/latest/dioxus_router/routable/trait.FromQuery.html>. You can implement that trait for a struct if you want to parse multiple query parameters.
+/// The query segment is anything that implements <https://docs.rs/dioxus-router/latest/dioxus::router/routable/trait.FromQuery.html>. You can implement that trait for a struct if you want to parse multiple query parameters.
 impl FromQuery for ManualBlogQuerySegments {
 impl FromQuery for ManualBlogQuerySegments {
     fn from_query(query: &str) -> Self {
     fn from_query(query: &str) -> Self {
         let mut name = None;
         let mut name = None;
@@ -63,26 +60,26 @@ impl FromQuery for ManualBlogQuerySegments {
 }
 }
 
 
 #[component]
 #[component]
-fn BlogPost(cx: Scope, query_params: ManualBlogQuerySegments) -> Element {
-    render! {
-        div{"This is your blogpost with a query segment:"}
-        div{ "{query_params:?}" }
+fn BlogPost(query_params: ManualBlogQuerySegments) -> Element {
+    rsx! {
+        div { "This is your blogpost with a query segment:" }
+        div { "{query_params:?}" }
     }
     }
 }
 }
 
 
 #[component]
 #[component]
-fn AutomaticBlogPost(cx: Scope, name: String, surname: String) -> Element {
-    render! {
-        div{"This is your blogpost with a query segment:"}
-        div{ "name={name}&surname={surname}" }
+fn AutomaticBlogPost(name: String, surname: String) -> Element {
+    rsx! {
+        div { "This is your blogpost with a query segment:" }
+        div { "name={name}&surname={surname}" }
     }
     }
 }
 }
 
 
 #[component]
 #[component]
-fn App(cx: Scope) -> Element {
-    render! { Router::<Route>{} }
+fn App() -> Element {
+    rsx! { Router::<Route> {} }
 }
 }
 
 
 fn main() {
 fn main() {
-    dioxus_web::launch(App);
+    launch(App);
 }
 }

+ 0 - 13
examples/query_segments_demo/Cargo.toml

@@ -1,13 +0,0 @@
-[package]
-name = "query_segments_demo"
-version = "0.1.0"
-edition = "2021"
-publish = false
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-dioxus = { path = "../../packages/dioxus", version = "*" }
-dioxus-router = { path = "../../packages/router", version = "*" }
-dioxus-web = { path = "../../packages/web", version = "*" }
-form_urlencoded = "1.2.0"

+ 25 - 31
examples/read_size.rs

@@ -4,10 +4,10 @@ use std::rc::Rc;
 use dioxus::{html::geometry::euclid::Rect, prelude::*};
 use dioxus::{html::geometry::euclid::Rect, prelude::*};
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch_cfg(
-        app,
-        dioxus_desktop::Config::default().with_custom_head(
-            r#"
+    LaunchBuilder::desktop()
+        .with_cfg(
+            dioxus::desktop::Config::default().with_custom_head(
+                r#"
 <style type="text/css">
 <style type="text/css">
     html, body {
     html, body {
         height: 100%;
         height: 100%;
@@ -20,41 +20,35 @@ fn main() {
     }
     }
 </style>
 </style>
 "#
 "#
-            .to_owned(),
-        ),
-    );
+                .to_owned(),
+            ),
+        )
+        .launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let div_element: &UseRef<Option<Rc<MountedData>>> = use_ref(cx, || None);
+fn app() -> Element {
+    let mut div_element = use_signal(|| None as Option<Rc<MountedData>>);
+    let mut dimensions = use_signal(Rect::zero);
 
 
-    let dimentions = use_ref(cx, Rect::zero);
+    let read_dims = move |_| async move {
+        let read = div_element.read();
+        let client_rect = read.as_ref().map(|el| el.get_client_rect());
+        if let Some(client_rect) = client_rect {
+            if let Ok(rect) = client_rect.await {
+                dimensions.set(rect);
+            }
+        }
+    };
 
 
-    cx.render(rsx!(
+    rsx!(
         div {
         div {
             width: "50%",
             width: "50%",
             height: "50%",
             height: "50%",
             background_color: "red",
             background_color: "red",
-            onmounted: move |cx| {
-                div_element.set(Some(cx.inner().clone()));
-            },
-            "This element is {dimentions.read():?}"
+            onmounted: move |cx| div_element.set(Some(cx.data())),
+            "This element is {dimensions():?}"
         }
         }
 
 
-        button {
-            onclick: move |_| {
-                to_owned![div_element, dimentions];
-                async move {
-                    let read = div_element.read();
-                    let client_rect = read.as_ref().map(|el| el.get_client_rect());
-                    if let Some(client_rect) = client_rect {
-                        if let Ok(rect) = client_rect.await {
-                            dimentions.set(rect);
-                        }
-                    }
-                }
-            },
-            "Read dimentions"
-        }
-    ))
+        button { onclick: read_dims, "Read dimensions" }
+    )
 }
 }

+ 5 - 9
examples/readme.rs

@@ -1,19 +1,15 @@
-//! Example: README.md showcase
-//!
-//! The example from the README.md.
-
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let mut count = use_state(cx, || 0);
+fn app() -> Element {
+    let mut count = use_signal(|| 0);
 
 
-    cx.render(rsx! {
+    rsx! {
         h1 { "High-Five counter: {count}" }
         h1 { "High-Five counter: {count}" }
         button { onclick: move |_| count += 1, "Up high!" }
         button { onclick: move |_| count += 1, "Up high!" }
         button { onclick: move |_| count -= 1, "Down low!" }
         button { onclick: move |_| count -= 1, "Down low!" }
-    })
+    }
 }
 }

+ 8 - 18
examples/pattern_reducer.rs → examples/reducer.rs

@@ -4,31 +4,24 @@
 //! This example shows how to encapsulate state in dioxus components with the reducer pattern.
 //! This example shows how to encapsulate state in dioxus components with the reducer pattern.
 //! This pattern is very useful when a single component can handle many types of input that can
 //! This pattern is very useful when a single component can handle many types of input that can
 //! be represented by an enum.
 //! be represented by an enum.
-//!
-//! Currently we don't have a reducer pattern hook. If you'd like to add it,
-//! feel free to make a PR.
 
 
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let state = use_state(cx, PlayerState::new);
+fn app() -> Element {
+    let mut state = use_signal(|| PlayerState { is_playing: false });
 
 
-    cx.render(rsx!(
+    rsx!(
         div {
         div {
             h1 {"Select an option"}
             h1 {"Select an option"}
-            h3 { "The radio is... ", {state.is_playing()}, "!" }
-            button { onclick: move |_| state.make_mut().reduce(PlayerAction::Pause),
-                "Pause"
-            }
-            button { onclick: move |_| state.make_mut().reduce(PlayerAction::Play),
-                "Play"
-            }
+            h3 { "The radio is... ", {state.read().is_playing()}, "!" }
+            button { onclick: move |_| state.write().reduce(PlayerAction::Pause), "Pause" }
+            button { onclick: move |_| state.write().reduce(PlayerAction::Play), "Play" }
         }
         }
-    ))
+    )
 }
 }
 
 
 enum PlayerAction {
 enum PlayerAction {
@@ -42,9 +35,6 @@ struct PlayerState {
 }
 }
 
 
 impl PlayerState {
 impl PlayerState {
-    fn new() -> Self {
-        Self { is_playing: false }
-    }
     fn reduce(&mut self, action: PlayerAction) {
     fn reduce(&mut self, action: PlayerAction) {
         match action {
         match action {
             PlayerAction::Pause => self.is_playing = false,
             PlayerAction::Pause => self.is_playing = false,

+ 32 - 40
examples/router.rs

@@ -1,15 +1,14 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_router::prelude::*;
 
 
 fn main() {
 fn main() {
-    #[cfg(target_arch = "wasm32")]
-    dioxus_web::launch(App);
-    #[cfg(not(target_arch = "wasm32"))]
-    dioxus_desktop::launch(App);
+    launch_desktop(|| {
+        rsx! {
+            Router::<Route> {}
+        }
+    });
 }
 }
 
 
-// ANCHOR: router
-#[derive(Routable, Clone)]
+#[derive(Routable, Clone, Debug, PartialEq)]
 #[rustfmt::skip]
 #[rustfmt::skip]
 enum Route {
 enum Route {
     #[layout(NavBar)]
     #[layout(NavBar)]
@@ -19,7 +18,7 @@ enum Route {
             #[layout(Blog)]
             #[layout(Blog)]
                 #[route("/")]
                 #[route("/")]
                 BlogList {},
                 BlogList {},
-                #[route("/blog/:name")]
+                #[route("/:name")]
                 BlogPost { name: String },
                 BlogPost { name: String },
             #[end_layout]
             #[end_layout]
         #[end_nest]
         #[end_nest]
@@ -33,22 +32,18 @@ enum Route {
         route: Vec<String>,
         route: Vec<String>,
     },
     },
 }
 }
-// ANCHOR_END: router
-
-#[component]
-fn App(cx: Scope) -> Element {
-    render! {
-        Router::<Route> {}
-    }
-}
 
 
 #[component]
 #[component]
-fn NavBar(cx: Scope) -> Element {
-    render! {
+fn NavBar() -> Element {
+    rsx! {
         nav {
         nav {
             ul {
             ul {
-                li { Link { to: Route::Home {}, "Home" } }
-                li { Link { to: Route::BlogList {}, "Blog" } }
+                li {
+                    Link { to: Route::Home {}, "Home" }
+                }
+                li {
+                    Link { to: Route::BlogList {}, "Blog" }
+                }
             }
             }
         }
         }
         Outlet::<Route> {}
         Outlet::<Route> {}
@@ -56,34 +51,36 @@ fn NavBar(cx: Scope) -> Element {
 }
 }
 
 
 #[component]
 #[component]
-fn Home(cx: Scope) -> Element {
-    render! {
-        h1 { "Welcome to the Dioxus Blog!" }
-    }
+fn Home() -> Element {
+    rsx! { h1 { "Welcome to the Dioxus Blog!" } }
 }
 }
 
 
 #[component]
 #[component]
-fn Blog(cx: Scope) -> Element {
-    render! {
+fn Blog() -> Element {
+    rsx! {
         h1 { "Blog" }
         h1 { "Blog" }
         Outlet::<Route> {}
         Outlet::<Route> {}
     }
     }
 }
 }
 
 
 #[component]
 #[component]
-fn BlogList(cx: Scope) -> Element {
-    render! {
+fn BlogList() -> Element {
+    rsx! {
         h2 { "Choose a post" }
         h2 { "Choose a post" }
         ul {
         ul {
             li {
             li {
                 Link {
                 Link {
-                    to: Route::BlogPost { name: "Blog post 1".into() },
+                    to: Route::BlogPost {
+                        name: "Blog post 1".into(),
+                    },
                     "Read the first blog post"
                     "Read the first blog post"
                 }
                 }
             }
             }
             li {
             li {
                 Link {
                 Link {
-                    to: Route::BlogPost { name: "Blog post 2".into() },
+                    to: Route::BlogPost {
+                        name: "Blog post 2".into(),
+                    },
                     "Read the second blog post"
                     "Read the second blog post"
                 }
                 }
             }
             }
@@ -92,20 +89,15 @@ fn BlogList(cx: Scope) -> Element {
 }
 }
 
 
 #[component]
 #[component]
-fn BlogPost(cx: Scope, name: String) -> Element {
-    render! {
-        h2 { "Blog Post: {name}"}
-    }
+fn BlogPost(name: String) -> Element {
+    rsx! { h2 { "Blog Post: {name}" } }
 }
 }
 
 
 #[component]
 #[component]
-fn PageNotFound(cx: Scope, route: Vec<String>) -> Element {
-    render! {
+fn PageNotFound(route: Vec<String>) -> Element {
+    rsx! {
         h1 { "Page not found" }
         h1 { "Page not found" }
         p { "We are terribly sorry, but the page you requested doesn't exist." }
         p { "We are terribly sorry, but the page you requested doesn't exist." }
-        pre {
-            color: "red",
-            "log:\nattemped to navigate to: {route:?}"
-        }
+        pre { color: "red", "log:\nattemped to navigate to: {route:?}" }
     }
     }
 }
 }

+ 0 - 58
examples/rsx_compile_fail.rs

@@ -1,58 +0,0 @@
-//! This example just flexes the ability to use arbitrary expressions within RSX.
-//! It also proves that lifetimes work properly, especially when used with use_ref
-
-use dioxus::prelude::*;
-
-fn main() {
-    let mut vdom = VirtualDom::new(example);
-    _ = vdom.rebuild();
-
-    let mut renderer = dioxus_ssr::Renderer::new();
-    renderer.pretty = true;
-    renderer.render(&vdom);
-}
-
-fn example(cx: Scope) -> Element {
-    let items = use_state(cx, || {
-        vec![Thing {
-            a: "asd".to_string(),
-            b: 10,
-        }]
-    });
-
-    let things = use_ref(cx, || {
-        vec![Thing {
-            a: "asd".to_string(),
-            b: 10,
-        }]
-    });
-    let things_list = things.read();
-
-    let mything = use_ref(cx, || Some(String::from("asd")));
-    let mything_read = mything.read();
-
-    cx.render(rsx!(
-        div {
-            div { id: "asd",
-                "your neighborhood spiderman"
-
-                for item in items.iter().cycle().take(5) {
-                    div { "{item.a}" }
-                }
-
-                for thing in things_list.iter() {
-                    div { "{thing.a}" "{thing.b}" }
-                }
-
-                if let Some(f) = mything_read.as_ref() {
-                    div { "{f}" }
-                }
-            }
-        }
-    ))
-}
-
-struct Thing {
-    a: String,
-    b: u32,
-}

+ 257 - 263
examples/rsx_usage.rs

@@ -39,269 +39,263 @@
 //! - Allow top-level fragments
 //! - Allow top-level fragments
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(App);
-}
-
-use core::{fmt, str::FromStr};
-use std::fmt::Display;
-
-use baller::Baller;
-use dioxus::prelude::*;
-
-#[component]
-fn App(cx: Scope) -> Element {
-    let formatting = "formatting!";
-    let formatting_tuple = ("a", "b");
-    let lazy_fmt = format_args!("lazily formatted text");
-    let asd = 123;
-    cx.render(rsx! {
-        div {
-            // Elements
-            div {}
-            h1 {"Some text"}
-            h1 {"Some text with {formatting}"}
-            h1 {"Formatting basic expressions {formatting_tuple.0} and {formatting_tuple.1}"}
-            h1 {"Formatting without interpolation " {formatting_tuple.0} "and" {formatting_tuple.1} }
-            h2 {
-                "Multiple"
-                "Text"
-                "Blocks"
-                "Use comments as separators in html"
-            }
-            div {
-                h1 {"multiple"}
-                h2 {"nested"}
-                h3 {"elements"}
-            }
-            div {
-                class: "my special div",
-                h1 {"Headers and attributes!"}
-            }
-            div {
-                // pass simple rust expressions in
-                class: lazy_fmt,
-                id: format_args!("attributes can be passed lazily with std::fmt::Arguments"),
-                class: "asd",
-                class: "{asd}",
-                // if statements can be used to conditionally render attributes
-                class: if formatting.contains("form") { "{asd}" },
-                div {
-                    class: {
-                        const WORD: &str = "expressions";
-                        format_args!("Arguments can be passed in through curly braces for complex {WORD}")
-                    }
-                }
-            }
-
-            // Expressions can be used in element position too:
-            {rsx!(p { "More templating!" })},
-
-            // Iterators
-            {(0..10).map(|i| rsx!(li { "{i}" }))},
-
-            // Iterators within expressions
-            {
-                let data = std::collections::HashMap::<&'static str, &'static str>::new();
-                // Iterators *should* have keys when you can provide them.
-                // Keys make your app run faster. Make sure your keys are stable, unique, and predictable.
-                // Using an "ID" associated with your data is a good idea.
-                data.into_iter().map(|(k, v)| rsx!(li { key: "{k}", "{v}" }))
-            }
-
-            // Matching
-            match true {
-                true => rsx!( h1 {"Top text"}),
-                false => rsx!( h1 {"Bottom text"})
-            }
-
-            // Conditional rendering
-            // Dioxus conditional rendering is based around None/Some. We have no special syntax for conditionals.
-            // You can convert a bool condition to rsx! with .then and .or
-            {true.then(|| rsx!(div {}))},
-
-            // Alternatively, you can use the "if" syntax - but both branches must be resolve to Element
-            if false {
-                h1 {"Top text"}
-            } else {
-                h1 {"Bottom text"}
-            }
-
-            // Using optionals for diverging branches
-            // Note that since this is wrapped in curlies, it's interpreted as an expression
-            {if true {
-                Some(rsx!(h1 {"Top text"}))
-            } else {
-                None
-            }}
-
-            // returning "None" without a diverging branch is a bit noisy... but rare in practice
-            {None as Option<()>},
-
-            // can also just use empty fragments
-            Fragment {}
-
-            // Fragments let you insert groups of nodes without a parent.
-            // This lets you make components that insert elements as siblings without a container.
-            div {"A"}
-            Fragment {
-                div {"B"}
-                div {"C"}
-                Fragment {
-                    "D"
-                    Fragment {
-                        "E"
-                        "F"
-                    }
-                }
-            }
-
-            // Components
-            // Can accept any paths
-            // Notice how you still get syntax highlighting and IDE support :)
-            Baller {}
-            baller::Baller {}
-            crate::baller::Baller {}
-
-            // Can take properties
-            Taller { a: "asd" }
-
-            // Can take optional properties
-            Taller { a: "asd" }
-
-            // Can pass in props directly as an expression
-            {
-                let props = TallerProps {a: "hello", children: None };
-                rsx!(Taller { ..props })
-            }
-
-            // Spreading can also be overridden manually
-            Taller {
-                ..TallerProps { a: "ballin!", children: None },
-                a: "not ballin!"
-            }
-
-            // Can take children too!
-            Taller { a: "asd", div {"hello world!"} }
-
-            // This component's props are defined *inline* with the `inline_props` macro
-            WithInline { text: "using functionc all syntax" }
-
-            // Components can be generic too
-            // This component takes i32 type to give you typed input
-            TypedInput::<i32> {}
-
-            // Type inference can be used too
-            TypedInput { initial: 10.0 }
-
-            // geneircs with the `inline_props` macro
-            Label { text: "hello geneirc world!" }
-            Label { text: 99.9 }
-
-            // Lowercase components work too, as long as they are access using a path
-            baller::lowercase_component {}
-
-            // For in-scope lowercase components, use the `self` keyword
-            self::lowercase_helper {}
-
-            // helper functions
-            // Anything that implements IntoVnode can be dropped directly into Rsx
-            {helper(cx, "hello world!")}
-
-            // Strings can be supplied directly
-            {String::from("Hello world!")}
-
-            // So can format_args
-            {format_args!("Hello {}!", "world")}
-
-            // Or we can shell out to a helper function
-            {format_dollars(10, 50)}
-        }
-    })
-}
-
-fn format_dollars(dollars: u32, cents: u32) -> String {
-    format!("${dollars}.{cents:02}")
-}
-
-fn helper<'a>(cx: &'a ScopeState, text: &'a str) -> Element<'a> {
-    cx.render(rsx! {
-        p { "{text}" }
-    })
-}
-
-// no_case_check disables PascalCase checking if you *really* want a snake_case component.
-// This will likely be deprecated/removed in a future update that will introduce a more polished linting system,
-// something like Clippy.
-#[component(no_case_check)]
-fn lowercase_helper(cx: Scope) -> Element {
-    cx.render(rsx! {
-        "asd"
-    })
-}
-
-mod baller {
-    use super::*;
-    #[derive(Props, PartialEq, Eq)]
-    pub struct BallerProps {}
-
-    #[component]
-    /// This component totally balls
-    pub fn Baller(_cx: Scope<BallerProps>) -> Element {
-        todo!()
-    }
-
-    // no_case_check disables PascalCase checking if you *really* want a snake_case component.
-    // This will likely be deprecated/removed in a future update that will introduce a more polished linting system,
-    // something like Clippy.
-    #[component(no_case_check)]
-    pub fn lowercase_component(cx: Scope) -> Element {
-        cx.render(rsx! { "look ma, no uppercase" })
-    }
-}
-
-#[derive(Props)]
-pub struct TallerProps<'a> {
-    /// Fields are documented and accessible in rsx!
-    a: &'static str,
-    children: Element<'a>,
-}
-
-/// Documention for this component is visible within the rsx macro
-#[component]
-pub fn Taller<'a>(cx: Scope<'a, TallerProps<'a>>) -> Element {
-    cx.render(rsx! {
-        {&cx.props.children}
-    })
-}
-
-#[derive(Props, PartialEq, Eq)]
-pub struct TypedInputProps<T> {
-    #[props(optional, default)]
-    initial: Option<T>,
-}
-
-#[allow(non_snake_case)]
-pub fn TypedInput<T>(_: Scope<TypedInputProps<T>>) -> Element
-where
-    T: FromStr + fmt::Display,
-    <T as FromStr>::Err: std::fmt::Display,
-{
     todo!()
     todo!()
+    //launch_desktop(App);
 }
 }
 
 
-#[component]
-fn WithInline<'a>(cx: Scope<'a>, text: &'a str) -> Element {
-    cx.render(rsx! {
-        p { "{text}" }
-    })
-}
-
-#[component]
-fn Label<T>(cx: Scope, text: T) -> Element
-where
-    T: Display,
-{
-    cx.render(rsx! {
-        p { "{text}" }
-    })
-}
+// use core::{fmt, str::FromStr};
+// use std::fmt::Display;
+
+// use baller::Baller;
+// use dioxus::prelude::*;
+
+// #[component]
+// fn App() -> Element {
+//     let formatting = "formatting!";
+//     let formatting_tuple = ("a", "b");
+//     let lazy_fmt = format_args!("lazily formatted text");
+//     let asd = 123;
+//     rsx! {
+//         div {
+//             // Elements
+//             div {}
+//             h1 {"Some text"}
+//             h1 {"Some text with {formatting}"}
+//             h1 {"Formatting basic expressions {formatting_tuple.0} and {formatting_tuple.1}"}
+//             h1 {"Formatting without interpolation " {formatting_tuple.0} "and" {formatting_tuple.1} }
+//             h2 {
+//                 "Multiple"
+//                 "Text"
+//                 "Blocks"
+//                 "Use comments as separators in html"
+//             }
+//             div {
+//                 h1 {"multiple"}
+//                 h2 {"nested"}
+//                 h3 {"elements"}
+//             }
+//             div {
+//                 class: "my special div",
+//                 h1 {"Headers and attributes!"}
+//             }
+//             div {
+//                 // pass simple rust expressions in
+//                 class: lazy_fmt,
+//                 id: format_args!("attributes can be passed lazily with std::fmt::Arguments"),
+//                 class: "asd",
+//                 class: "{asd}",
+//                 // if statements can be used to conditionally render attributes
+//                 class: if formatting.contains("form") { "{asd}" },
+//                 div {
+//                     class: {
+//                         const WORD: &str = "expressions";
+//                         format_args!("Arguments can be passed in through curly braces for complex {WORD}")
+//                     }
+//                 }
+//             }
+
+//             // Expressions can be used in element position too:
+//             {rsx!(p { "More templating!" })},
+
+//             // Iterators
+//             {(0..10).map(|i| rsx!(li { "{i}" }))},
+
+//             // Iterators within expressions
+//             {
+//                 let data = std::collections::HashMap::<&'static str, &'static str>::new();
+//                 // Iterators *should* have keys when you can provide them.
+//                 // Keys make your app run faster. Make sure your keys are stable, unique, and predictable.
+//                 // Using an "ID" associated with your data is a good idea.
+//                 data.into_iter().map(|(k, v)| rsx!(li { key: "{k}", "{v}" }))
+//             }
+
+//             // Matching
+//             match true {
+//                 true => rsx!( h1 {"Top text"}),
+//                 false => rsx!( h1 {"Bottom text"})
+//             }
+
+//             // Conditional rendering
+//             // Dioxus conditional rendering is based around None/Some. We have no special syntax for conditionals.
+//             // You can convert a bool condition to rsx! with .then and .or
+//             {true.then(|| rsx!(div {}))},
+
+//             // Alternatively, you can use the "if" syntax - but both branches must be resolve to Element
+//             if false {
+//                 h1 {"Top text"}
+//             } else {
+//                 h1 {"Bottom text"}
+//             }
+
+//             // Using optionals for diverging branches
+//             // Note that since this is wrapped in curlies, it's interpreted as an expression
+//             {if true {
+//                 Some(rsx!(h1 {"Top text"}))
+//             } else {
+//                 None
+//             }}
+
+//             // returning "None" without a diverging branch is a bit noisy... but rare in practice
+//             {None as Option<()>},
+
+//             // can also just use empty fragments
+//             Fragment {}
+
+//             // Fragments let you insert groups of nodes without a parent.
+//             // This lets you make components that insert elements as siblings without a container.
+//             div {"A"}
+//             Fragment {
+//                 div {"B"}
+//                 div {"C"}
+//                 Fragment {
+//                     "D"
+//                     Fragment {
+//                         "E"
+//                         "F"
+//                     }
+//                 }
+//             }
+
+//             // Components
+//             // Can accept any paths
+//             // Notice how you still get syntax highlighting and IDE support :)
+//             Baller {}
+//             baller::Baller {}
+//             crate::baller::Baller {}
+
+//             // Can take properties
+//             Taller { a: "asd" }
+
+//             // Can take optional properties
+//             Taller { a: "asd" }
+
+//             // Can pass in props directly as an expression
+//             {
+//                 let props = TallerProps {a: "hello", children: None };
+//                 rsx!(Taller { ..props })
+//             }
+
+//             // Spreading can also be overridden manually
+//             Taller {
+//                 ..TallerProps { a: "ballin!", children: None },
+//                 a: "not ballin!"
+//             }
+
+//             // Can take children too!
+//             Taller { a: "asd", div {"hello world!"} }
+
+//             // This component's props are defined *inline* with the `inline_props` macro
+//             WithInline { text: "using functionc all syntax" }
+
+//             // Components can be generic too
+//             // This component takes i32 type to give you typed input
+//             TypedInput::<i32> {}
+
+//             // Type inference can be used too
+//             TypedInput { initial: 10.0 }
+
+//             // geneircs with the `inline_props` macro
+//             Label { text: "hello geneirc world!" }
+//             Label { text: 99.9 }
+
+//             // Lowercase components work too, as long as they are access using a path
+//             baller::lowercase_component {}
+
+//             // For in-scope lowercase components, use the `self` keyword
+//             self::lowercase_helper {}
+
+//             // helper functions
+//             // Anything that implements IntoVnode can be dropped directly into Rsx
+//             {helper("hello world!")}
+
+//             // Strings can be supplied directly
+//             {String::from("Hello world!")}
+
+//             // So can format_args
+//             {format_args!("Hello {}!", "world")}
+
+//             // Or we can shell out to a helper function
+//             {format_dollars(10, 50)}
+//         }
+//     }
+// }
+
+// fn format_dollars(dollars: u32, cents: u32) -> String {
+//     format!("${dollars}.{cents:02}")
+// }
+
+// fn helper<'a>(cx: &'a ScopeState, text: &'a str) -> Element {
+//     rsx! {
+//         p { "{text}" }
+//     }
+// }
+
+// // no_case_check disables PascalCase checking if you *really* want a snake_case component.
+// // This will likely be deprecated/removed in a future update that will introduce a more polished linting system,
+// // something like Clippy.
+// #[component(no_case_check)]
+// fn lowercase_helper() -> Element {
+//     rsx! {
+//         "asd"
+//     }
+// }
+
+// mod baller {
+//     use super::*;
+
+//     #[component]
+//     /// This component totally balls
+//     pub fn Baller() -> Element {
+//         todo!()
+//     }
+
+//     // no_case_check disables PascalCase checking if you *really* want a snake_case component.
+//     // This will likely be deprecated/removed in a future update that will introduce a more polished linting system,
+//     // something like Clippy.
+//     #[component(no_case_check)]
+//     pub fn lowercase_component() -> Element {
+//         rsx! { "look ma, no uppercase" }
+//     }
+// }
+
+// /// Documention for this component is visible within the rsx macro
+// #[component]
+// pub fn Taller(
+//     /// Fields are documented and accessible in rsx!
+//     a: &'static str,
+//     children: Element,
+// ) -> Element {
+//     rsx! { {&children} }
+// }
+
+// #[derive(Props, PartialEq, Eq)]
+// pub struct TypedInputProps<T> {
+//     #[props(optional, default)]
+//     initial: Option<T>,
+// }
+
+// #[allow(non_snake_case)]
+// pub fn TypedInput<T>(_: Scope<TypedInputProps<T>>) -> Element
+// where
+//     T: FromStr + fmt::Display,
+//     <T as FromStr>::Err: std::fmt::Display,
+// {
+//     todo!()
+// }
+
+// #[component]
+// fn WithInline(cx: Scope<'a>, text: &'a str) -> Element {
+//     rsx! {
+//         p { "{text}" }
+//     }
+// }
+
+// #[component]
+// fn Label<T: Clone + PartialEq>(text: T) -> Element
+// where
+//     T: Display,
+// {
+//     rsx! {
+//         p { "{text}" }
+//     }
+// }

+ 9 - 13
examples/scroll_to_top.rs

@@ -1,18 +1,16 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let header_element = use_ref(cx, || None);
+fn app() -> Element {
+    let mut header_element = use_signal(|| None);
 
 
-    cx.render(rsx!(
+    rsx! {
         div {
         div {
             h1 {
             h1 {
-                onmounted: move |cx| {
-                    header_element.set(Some(cx.inner().clone()));
-                },
+                onmounted: move |cx| header_element.set(Some(cx.data())),
                 "Scroll to top example"
                 "Scroll to top example"
             }
             }
 
 
@@ -21,15 +19,13 @@ fn app(cx: Scope) -> Element {
             }
             }
 
 
             button {
             button {
-                onclick: move |_| {
-                    if let Some(header) = header_element.read().as_ref().cloned() {
-                        cx.spawn(async move {
-                            let _ = header.scroll_to(ScrollBehavior::Smooth).await;
-                        });
+                onclick: move |_| async move {
+                    if let Some(header) = header_element.cloned() {
+                        let _ = header.scroll_to(ScrollBehavior::Smooth).await;
                     }
                     }
                 },
                 },
                 "Scroll to top"
                 "Scroll to top"
             }
             }
         }
         }
-    ))
+    }
 }
 }

+ 0 - 73
examples/shared_state.rs

@@ -1,73 +0,0 @@
-use std::collections::HashMap;
-
-use dioxus::prelude::*;
-
-fn main() {
-    dioxus_desktop::launch(App);
-}
-
-#[derive(Default)]
-struct CoolData {
-    data: HashMap<usize, String>,
-}
-
-impl CoolData {
-    pub fn new(data: HashMap<usize, String>) -> Self {
-        Self { data }
-    }
-
-    pub fn view(&self, id: &usize) -> Option<&String> {
-        self.data.get(id)
-    }
-
-    pub fn set(&mut self, id: usize, data: String) {
-        self.data.insert(id, data);
-    }
-}
-
-#[component]
-#[rustfmt::skip]
-pub fn App(cx: Scope) -> Element {
-    use_shared_state_provider(cx, || CoolData::new(HashMap::from([
-        (0, "Hello, World!".to_string()),
-        (1, "Dioxus is amazing!".to_string())
-    ])));
-
-    render!(
-        DataEditor {
-            id: 0
-        }
-        DataEditor {
-            id: 1
-        }
-        DataView {
-            id: 0
-        }
-        DataView {
-            id: 1
-        }
-    )
-}
-
-#[component]
-fn DataEditor(cx: Scope, id: usize) -> Element {
-    let data = use_shared_state::<CoolData>(cx)?;
-
-    render! {
-        p {
-            {data.read().view(id)?}
-        }
-    }
-}
-
-#[component]
-fn DataView(cx: Scope, id: usize) -> Element {
-    let data = use_shared_state::<CoolData>(cx)?;
-
-    render! {
-        input {
-            oninput: move |e: FormEvent| data.write().set(*id, e.value()),
-            value: data.read().view(id)?
-        }
-    }
-}

+ 6 - 9
examples/shortcut.rs

@@ -1,17 +1,14 @@
+use dioxus::desktop::use_global_shortcut;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::use_global_shortcut;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let toggled = use_state(cx, || false);
+fn app() -> Element {
+    let mut toggled = use_signal(|| false);
 
 
-    use_global_shortcut(cx, "ctrl+s", {
-        to_owned![toggled];
-        move || toggled.modify(|t| !*t)
-    });
+    _ = use_global_shortcut("ctrl+s", move || toggled.toggle());
 
 
-    cx.render(rsx!("toggle: {toggled.get()}"))
+    rsx!("toggle: {toggled}")
 }
 }

+ 7 - 16
examples/shorthand.rs

@@ -1,10 +1,10 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
+fn app() -> Element {
     let a = 123;
     let a = 123;
     let b = 456;
     let b = 456;
     let c = 789;
     let c = 789;
@@ -14,10 +14,10 @@ fn app(cx: Scope) -> Element {
     // todo: i'd like it for children on elements to be inferred as the children of the element
     // todo: i'd like it for children on elements to be inferred as the children of the element
     // also should shorthands understand references/dereferences?
     // also should shorthands understand references/dereferences?
     // ie **a, *a, &a, &mut a, etc
     // ie **a, *a, &a, &mut a, etc
-    let children = render! { "Child" };
+    let children = rsx! { "Child" };
     let onclick = move |_| println!("Clicked!");
     let onclick = move |_| println!("Clicked!");
 
 
-    render! {
+    rsx! {
         div { class, id, {&children} }
         div { class, id, {&children} }
         Component { a, b, c, children, onclick }
         Component { a, b, c, children, onclick }
         Component { a, ..ComponentProps { a: 1, b: 2, c: 3, children: None, onclick: Default::default() } }
         Component { a, ..ComponentProps { a: 1, b: 2, c: 3, children: None, onclick: Default::default() } }
@@ -25,21 +25,12 @@ fn app(cx: Scope) -> Element {
 }
 }
 
 
 #[component]
 #[component]
-fn Component<'a>(
-    cx: Scope<'a>,
-    a: i32,
-    b: i32,
-    c: i32,
-    children: Element<'a>,
-    onclick: EventHandler<'a, ()>,
-) -> Element {
-    render! {
+fn Component(a: i32, b: i32, c: i32, children: Element, onclick: EventHandler) -> Element {
+    rsx! {
         div { "{a}" }
         div { "{a}" }
         div { "{b}" }
         div { "{b}" }
         div { "{c}" }
         div { "{c}" }
         div { {children} }
         div { {children} }
-        div {
-            onclick: move |_| onclick.call(()),
-        }
+        div { onclick: move |_| onclick.call(()) }
     }
     }
 }
 }

+ 48 - 15
examples/signals.rs

@@ -2,40 +2,60 @@ use dioxus::prelude::*;
 use std::time::Duration;
 use std::time::Duration;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let running = dioxus_signals::use_signal(cx, || true);
-    let mut count = dioxus_signals::use_signal(cx, || 0);
-    let saved_values = dioxus_signals::use_signal(cx, || vec![0.to_string()]);
+fn app() -> Element {
+    let mut running = use_signal(|| true);
+    let mut count = use_signal(|| 0);
+    let mut saved_values = use_signal(|| vec![0.to_string()]);
 
 
-    // Signals can be used in async functions without an explicit clone since they're 'static and Copy
-    // Signals are backed by a runtime that is designed to deeply integrate with Dioxus apps
-    use_future!(cx, || async move {
+    // use_memo will recompute the value of the signal whenever the captured signals change
+    let doubled_count = use_memo(move || count() * 2);
+
+    // use_effect will subscribe to any changes in the signal values it captures
+    // effects will always run after first mount and then whenever the signal values change
+    use_effect(move || println!("Count changed to {count}"));
+
+    // We can do early returns and conditional rendering which will pause all futures that haven't been polled
+    if count() > 30 {
+        return rsx! {
+            h1 { "Count is too high!" }
+            button { onclick: move |_| count.set(0), "Press to reset" }
+        };
+    }
+
+    // use_future will spawn an infinitely running future that can be started and stopped
+    use_future(move || async move {
         loop {
         loop {
-            if running.value() {
+            if running() {
                 count += 1;
                 count += 1;
             }
             }
             tokio::time::sleep(Duration::from_millis(400)).await;
             tokio::time::sleep(Duration::from_millis(400)).await;
         }
         }
     });
     });
 
 
-    cx.render(rsx! {
+    // use_resource will spawn a future that resolves to a value
+    let _slow_count = use_resource(move || async move {
+        tokio::time::sleep(Duration::from_millis(200)).await;
+        count() * 2
+    });
+
+    rsx! {
         h1 { "High-Five counter: {count}" }
         h1 { "High-Five counter: {count}" }
         button { onclick: move |_| count += 1, "Up high!" }
         button { onclick: move |_| count += 1, "Up high!" }
         button { onclick: move |_| count -= 1, "Down low!" }
         button { onclick: move |_| count -= 1, "Down low!" }
         button { onclick: move |_| running.toggle(), "Toggle counter" }
         button { onclick: move |_| running.toggle(), "Toggle counter" }
-        button { onclick: move |_| saved_values.push(count.value().to_string()), "Save this value" }
-        button { onclick: move |_| saved_values.write().clear(), "Clear saved values" }
+        button { onclick: move |_| saved_values.push(count.to_string()), "Save this value" }
+        button { onclick: move |_| saved_values.clear(), "Clear saved values" }
 
 
         // We can do boolean operations on the current signal value
         // We can do boolean operations on the current signal value
-        if count.value() > 5 {
+        if count() > 5 {
             h2 { "High five!" }
             h2 { "High five!" }
         }
         }
 
 
         // We can cleanly map signals with iterators
         // We can cleanly map signals with iterators
-        for value in saved_values.read().iter() {
+        for value in saved_values.iter() {
             h3 { "Saved value: {value}" }
             h3 { "Saved value: {value}" }
         }
         }
 
 
@@ -45,5 +65,18 @@ fn app(cx: Scope) -> Element {
         } else {
         } else {
             "No saved values"
             "No saved values"
         }
         }
-    })
+
+        // You can pass a value directly to any prop that accepts a signal
+        Child { count: doubled_count() }
+        Child { count: doubled_count }
+    }
+}
+
+#[component]
+fn Child(mut count: ReadOnlySignal<i32>) -> Element {
+    println!("rendering child with count {count}");
+
+    rsx! {
+        h1 { "{count}" }
+    }
 }
 }

+ 0 - 82
examples/simple_desktop.rs

@@ -1,82 +0,0 @@
-#![allow(non_snake_case)]
-
-use dioxus::prelude::*;
-use dioxus_router::prelude::*;
-
-fn main() {
-    simple_logger::SimpleLogger::new()
-        .with_level(log::LevelFilter::Debug)
-        .with_module_level("dioxus", log::LevelFilter::Trace)
-        .init()
-        .unwrap();
-    dioxus_desktop::launch(App);
-}
-
-#[component]
-fn App(cx: Scope) -> Element {
-    render! {
-        Router::<Route> {}
-    }
-}
-
-#[derive(Routable, Clone)]
-#[rustfmt::skip]
-enum Route {
-    #[layout(NavBar)]
-        #[route("/")]
-        Home {},
-        #[nest("/new")]
-            #[route("/")]
-            BlogList {},
-            #[route("/:post")]
-            BlogPost {
-                post: String,
-            },
-        #[end_nest]
-        #[route("/oranges")]
-        Oranges {},
-}
-
-#[component]
-fn NavBar(cx: Scope) -> Element {
-    render! {
-        h1 { "Your app here" }
-        ul {
-            li { Link { to: Route::Home {}, "home" } }
-            li { Link { to: Route::BlogList {}, "blog" } }
-            li { Link { to: Route::BlogPost { post: "tim".into() }, "tims' blog" } }
-            li { Link { to: Route::BlogPost { post: "bill".into() }, "bills' blog" } }
-            li { Link { to: Route::BlogPost { post: "james".into() }, "james amazing' blog" } }
-        }
-        Outlet::<Route> {}
-    }
-}
-
-#[component]
-fn Home(cx: Scope) -> Element {
-    log::debug!("rendering home {:?}", cx.scope_id());
-    render! { h1 { "Home" } }
-}
-
-#[component]
-fn BlogList(cx: Scope) -> Element {
-    log::debug!("rendering blog list {:?}", cx.scope_id());
-    render! { div { "Blog List" } }
-}
-
-#[component]
-fn BlogPost(cx: Scope, post: String) -> Element {
-    log::debug!("rendering blog post {}", post);
-
-    render! {
-        div {
-            h3 { "blog post: {post}"  }
-            Link { to: Route::BlogList {}, "back to blog list" }
-        }
-    }
-}
-
-#[component]
-fn Oranges(cx: Scope) -> Element {
-    render!("Oranges are not apples!")
-}

+ 5 - 5
examples/simple_list.rs

@@ -1,11 +1,11 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx!(
+fn app() -> Element {
+    rsx!(
         div {
         div {
             // Use Map directly to lazily pull elements
             // Use Map directly to lazily pull elements
             {(0..10).map(|f| rsx! { "{f}" })},
             {(0..10).map(|f| rsx! { "{f}" })},
@@ -22,7 +22,7 @@ fn app(cx: Scope) -> Element {
 
 
             // use a for loop where the body itself is RSX
             // use a for loop where the body itself is RSX
             for name in 0..10 {
             for name in 0..10 {
-                div {"{name}"}
+                div { "{name}" }
             }
             }
 
 
             // Or even use an unterminated conditional
             // Or even use an unterminated conditional
@@ -30,5 +30,5 @@ fn app(cx: Scope) -> Element {
                 "hello world!"
                 "hello world!"
             }
             }
         }
         }
-    ))
+    )
 }
 }

+ 27 - 11
examples/simple_router.rs

@@ -1,6 +1,6 @@
 #![allow(non_snake_case)]
 #![allow(non_snake_case)]
+
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_router::prelude::*;
 
 
 #[derive(Routable, Clone, PartialEq)]
 #[derive(Routable, Clone, PartialEq)]
 enum Route {
 enum Route {
@@ -13,30 +13,46 @@ enum Route {
 }
 }
 
 
 #[component]
 #[component]
-fn Homepage(cx: Scope) -> Element {
-    render! { h1 { "Welcome home" } }
+fn Homepage() -> Element {
+    rsx! { h1 { "Welcome home" } }
 }
 }
 
 
 #[component]
 #[component]
-fn Blog(cx: Scope, id: String) -> Element {
-    render! {
+fn Blog(id: String) -> Element {
+    rsx! {
         h1 { "How to make: " }
         h1 { "How to make: " }
         p { "{id}" }
         p { "{id}" }
     }
     }
 }
 }
 
 
 #[component]
 #[component]
-fn Nav(cx: Scope) -> Element {
-    render! {
+fn Nav() -> Element {
+    rsx! {
         nav {
         nav {
-            li { Link { to: Route::Homepage { }, "Go home" } }
-            li { Link { to: Route::Blog { id: "Brownies".to_string() }, "Learn Brownies" } }
-            li { Link { to: Route::Blog { id: "Cookies".to_string() }, "Learn Cookies"  } }
+            li {
+                Link { to: Route::Homepage {}, "Go home" }
+            }
+            li {
+                Link {
+                    to: Route::Blog {
+                        id: "Brownies".to_string(),
+                    },
+                    "Learn Brownies"
+                }
+            }
+            li {
+                Link {
+                    to: Route::Blog {
+                        id: "Cookies".to_string(),
+                    },
+                    "Learn Cookies"
+                }
+            }
         }
         }
         div { Outlet::<Route> {} }
         div { Outlet::<Route> {} }
     }
     }
 }
 }
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(|cx| render!(Router::<Route> {}));
+    launch_desktop(|| rsx! { Router::<Route> {} });
 }
 }

+ 16 - 16
examples/spread.rs

@@ -1,16 +1,15 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    let mut dom = VirtualDom::new(app);
-    let _ = dom.rebuild();
+    let dom = VirtualDom::prebuilt(app);
     let html = dioxus_ssr::render(&dom);
     let html = dioxus_ssr::render(&dom);
 
 
     println!("{}", html);
     println!("{}", html);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    render! {
-        Component {
+fn app() -> Element {
+    rsx! {
+        spreadable_component {
             width: "10px",
             width: "10px",
             extra_data: "hello{1}",
             extra_data: "hello{1}",
             extra_data2: "hello{2}",
             extra_data2: "hello{2}",
@@ -20,17 +19,18 @@ fn app(cx: Scope) -> Element {
     }
     }
 }
 }
 
 
-#[component]
-fn Component<'a>(cx: Scope<'a, Props<'a>>) -> Element<'a> {
-    render! {
-        audio { ..cx.props.attributes, "1: {cx.props.extra_data}\n2: {cx.props.extra_data2}" }
-    }
+#[derive(Props, PartialEq, Clone)]
+struct Props {
+    #[props(extends = GlobalAttributes)]
+    attributes: Vec<Attribute>,
+
+    extra_data: String,
+
+    extra_data2: String,
 }
 }
 
 
-#[derive(Props)]
-struct Props<'a> {
-    #[props(extends = GlobalAttributes)]
-    attributes: Vec<Attribute<'a>>,
-    extra_data: &'a str,
-    extra_data2: &'a str,
+fn spreadable_component(props: Props) -> Element {
+    rsx! {
+        audio { ..props.attributes, "1: {props.extra_data}\n2: {props.extra_data2}" }
+    }
 }
 }

+ 5 - 6
examples/ssr.rs

@@ -6,14 +6,13 @@ use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
     // We can render VirtualDoms
     // We can render VirtualDoms
-    let mut vdom = VirtualDom::new(app);
-    let _ = vdom.rebuild();
+    let vdom = VirtualDom::prebuilt(app);
     println!("{}", dioxus_ssr::render(&vdom));
     println!("{}", dioxus_ssr::render(&vdom));
 
 
     // Or we can render rsx! calls themselves
     // Or we can render rsx! calls themselves
     println!(
     println!(
         "{}",
         "{}",
-        dioxus_ssr::render_lazy(rsx! {
+        dioxus_ssr::render_element(rsx! {
             div {
             div {
                 h1 { "Hello, world!" }
                 h1 { "Hello, world!" }
             }
             }
@@ -30,11 +29,11 @@ fn main() {
     println!("{file}");
     println!("{file}");
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx!(
+fn app() -> Element {
+    rsx!(
         div {
         div {
             h1 { "Title" }
             h1 { "Title" }
             p { "Body" }
             p { "Body" }
         }
         }
-    ))
+    )
 }
 }

+ 36 - 0
examples/stale_memo.rs

@@ -0,0 +1,36 @@
+use dioxus::prelude::*;
+
+fn main() {
+    launch_desktop(app);
+}
+
+fn app() -> Element {
+    let mut state = use_signal(|| 0);
+    let mut depth = use_signal(|| 1_usize);
+
+    if depth() == 5 {
+        return rsx! {
+            div { "Max depth reached" }
+            button { onclick: move |_| depth -= 1, "Remove depth" }
+        };
+    }
+
+    let items = use_memo(move || (0..depth()).map(|f| f as _).collect::<Vec<isize>>());
+
+    rsx! {
+        button { onclick: move |_| state += 1, "Increment" }
+        button { onclick: move |_| depth += 1, "Add depth" }
+        button {
+            onclick: move |_| async move {
+                depth += 1;
+                tokio::time::sleep(std::time::Duration::from_millis(100)).await;
+                dbg!(items.read());
+                // if depth() is 5, this will be the old since the memo hasn't been re-computed
+                // use_memos are only re-computed when the signals they capture change
+                // *and* they are used in the current render
+                // If the use_memo isn't used, it can't be re-computed!
+            },
+            "Add depth with sleep"
+        }
+    }
+}

+ 6 - 7
examples/streams.rs

@@ -1,16 +1,15 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_signals::use_signal;
 use futures_util::{future, stream, Stream, StreamExt};
 use futures_util::{future, stream, Stream, StreamExt};
 use std::time::Duration;
 use std::time::Duration;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let count = use_signal(cx, || 10);
+fn app() -> Element {
+    let mut count = use_signal(|| 10);
 
 
-    use_future(cx, (), |_| async move {
+    use_future(move || async move {
         let mut stream = some_stream();
         let mut stream = some_stream();
 
 
         while let Some(second) = stream.next().await {
         while let Some(second) = stream.next().await {
@@ -18,9 +17,9 @@ fn app(cx: Scope) -> Element {
         }
         }
     });
     });
 
 
-    cx.render(rsx! {
+    rsx! {
         h1 { "High-Five counter: {count}" }
         h1 { "High-Five counter: {count}" }
-    })
+    }
 }
 }
 
 
 fn some_stream() -> std::pin::Pin<Box<dyn Stream<Item = i32>>> {
 fn some_stream() -> std::pin::Pin<Box<dyn Stream<Item = i32>>> {

+ 26 - 33
examples/suspense.rs

@@ -13,28 +13,25 @@
 //! We can achieve the majority of suspense functionality by composing "suspenseful"
 //! We can achieve the majority of suspense functionality by composing "suspenseful"
 //! primitives in our own custom components.
 //! primitives in our own custom components.
 
 
+use dioxus::desktop::{Config, LogicalSize, WindowBuilder};
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::{Config, LogicalSize, WindowBuilder};
 
 
 fn main() {
 fn main() {
-    let cfg = Config::new().with_window(
-        WindowBuilder::new()
-            .with_title("Doggo Fetcher")
-            .with_inner_size(LogicalSize::new(600.0, 800.0)),
-    );
-
-    dioxus_desktop::launch_cfg(app, cfg);
-}
-
-#[derive(serde::Deserialize)]
-struct DogApi {
-    message: String,
+    LaunchBuilder::desktop()
+        .with_cfg(
+            Config::new().with_window(
+                WindowBuilder::new()
+                    .with_title("Doggo Fetcher")
+                    .with_inner_size(LogicalSize::new(600.0, 800.0)),
+            ),
+        )
+        .launch(app)
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
+fn app() -> Element {
+    rsx! {
         div {
         div {
-            h1 {"Dogs are very important"}
+            h1 { "Dogs are very important" }
             p {
             p {
                 "The dog or domestic dog (Canis familiaris[4][5] or Canis lupus familiaris[5])"
                 "The dog or domestic dog (Canis familiaris[4][5] or Canis lupus familiaris[5])"
                 "is a domesticated descendant of the wolf which is characterized by an upturning tail."
                 "is a domesticated descendant of the wolf which is characterized by an upturning tail."
@@ -44,16 +41,21 @@ fn app(cx: Scope) -> Element {
             }
             }
 
 
             h3 { "Illustrious Dog Photo" }
             h3 { "Illustrious Dog Photo" }
-            Doggo { }
+            Doggo {}
         }
         }
-    })
+    }
 }
 }
 
 
 /// This component will re-render when the future has finished
 /// This component will re-render when the future has finished
 /// Suspense is achieved my moving the future into only the component that
 /// Suspense is achieved my moving the future into only the component that
 /// actually renders the data.
 /// actually renders the data.
-fn Doggo(cx: Scope) -> Element {
-    let fut = use_future(cx, (), |_| async move {
+fn Doggo() -> Element {
+    let mut fut = use_resource(move || async move {
+        #[derive(serde::Deserialize)]
+        struct DogApi {
+            message: String,
+        }
+
         reqwest::get("https://dog.ceo/api/breeds/image/random/")
         reqwest::get("https://dog.ceo/api/breeds/image/random/")
             .await
             .await
             .unwrap()
             .unwrap()
@@ -61,21 +63,12 @@ fn Doggo(cx: Scope) -> Element {
             .await
             .await
     });
     });
 
 
-    cx.render(match fut.value() {
+    match fut.read().as_ref() {
         Some(Ok(resp)) => rsx! {
         Some(Ok(resp)) => rsx! {
-            button {
-                onclick: move |_| fut.restart(),
-                "Click to fetch another doggo"
-            }
-            div {
-                img {
-                    max_width: "500px",
-                    max_height: "500px",
-                    src: "{resp.message}",
-                }
-            }
+            button { onclick: move |_| fut.restart(), "Click to fetch another doggo" }
+            div { img { max_width: "500px", max_height: "500px", src: "{resp.message}" } }
         },
         },
         Some(Err(_)) => rsx! { div { "loading dogs failed" } },
         Some(Err(_)) => rsx! { div { "loading dogs failed" } },
         None => rsx! { div { "loading dogs..." } },
         None => rsx! { div { "loading dogs..." } },
-    })
+    }
 }
 }

+ 35 - 88
examples/svg.rs

@@ -1,103 +1,50 @@
 // Thanks to @japsu and their project https://github.com/japsu/jatsi for the example!
 // Thanks to @japsu and their project https://github.com/japsu/jatsi for the example!
 
 
 use dioxus::prelude::*;
 use dioxus::prelude::*;
+use rand::{thread_rng, Rng};
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
-}
-
-fn app(cx: Scope) -> Element {
-    let val = use_state(cx, || 5);
-
-    cx.render(rsx! {
-        div {
-            user_select: "none",
-            webkit_user_select: "none",
-            margin_left: "10%",
-            margin_right: "10%",
-            h1 { "Click die to generate a new value" }
-            div {
-                cursor: "pointer",
-                height: "80%",
-                width: "80%",
-                Die {
-                    value: **val,
-                    keep: true,
-                    onclick: move |_| {
-                        use rand::Rng;
-                        let mut rng = rand::thread_rng();
-                        val.set(rng.gen_range(1..=6));
-                    }
-                }
+    launch(|| {
+        rsx! {
+            div { user_select: "none", webkit_user_select: "none", margin_left: "10%", margin_right: "10%",
+                h1 { "Click die to generate a new value" }
+                div { cursor: "pointer", height: "100%", width: "100%", Dice {} }
             }
             }
         }
         }
-    })
+    });
 }
 }
 
 
-#[derive(Props)]
-pub struct DieProps<'a> {
-    pub value: u64,
-    pub keep: bool,
-    pub onclick: EventHandler<'a, MouseEvent>,
-}
-
-const DOTS: [(i64, i64); 7] = [(-1, -1), (-1, -0), (-1, 1), (1, -1), (1, 0), (1, 1), (0, 0)];
-const DOTS_FOR_VALUE: [[bool; 7]; 6] = [
-    [false, false, false, false, false, false, true],
-    [false, false, true, true, false, false, false],
-    [false, false, true, true, false, false, true],
-    [true, false, true, true, false, true, false],
-    [true, false, true, true, false, true, true],
-    [true, true, true, true, true, true, false],
-];
-
-const OFFSET: i64 = 600;
-const DOT_RADIUS: &str = "200";
-const HELD_COLOR: &str = "#aaa";
-const UNHELD_COLOR: &str = "#ddd";
-
-// A six-sided die (D6) with dots.
-#[allow(non_snake_case)]
-pub fn Die<'a>(cx: Scope<'a, DieProps<'a>>) -> Element {
-    let &DieProps { value, keep, .. } = cx.props;
-
-    let active_dots = &DOTS_FOR_VALUE[(value - 1) as usize];
-    let fill = if keep { HELD_COLOR } else { UNHELD_COLOR };
-    let dots = DOTS
-        .iter()
-        .zip(active_dots.iter())
-        .filter(|(_, &active)| active)
-        .map(|((x, y), _)| {
-            let dcx = x * OFFSET;
-            let dcy = y * OFFSET;
-
-            rsx! {
+#[component]
+fn Dice() -> Element {
+    const Y: bool = true;
+    const N: bool = false;
+    const DOTS: [(i64, i64); 7] = [(-1, -1), (-1, -0), (-1, 1), (1, -1), (1, 0), (1, 1), (0, 0)];
+    const DOTS_FOR_VALUE: [[bool; 7]; 6] = [
+        [N, N, N, N, N, N, Y],
+        [N, N, Y, Y, N, N, N],
+        [N, N, Y, Y, N, N, Y],
+        [Y, N, Y, Y, N, Y, N],
+        [Y, N, Y, Y, N, Y, Y],
+        [Y, Y, Y, Y, Y, Y, N],
+    ];
+
+    let mut value = use_signal(|| 5);
+    let active_dots = use_memo(move || &DOTS_FOR_VALUE[(value() - 1) as usize]);
+
+    rsx! {
+        svg {
+            view_box: "-1000 -1000 2000 2000",
+            prevent_default: "onclick",
+            onclick: move |_| value.set(thread_rng().gen_range(1..=6)),
+            rect { x: -1000, y: -1000, width: 2000, height: 2000, rx: 200, fill: "#aaa" }
+            for ((x, y), _) in DOTS.iter().zip(active_dots.read().iter()).filter(|(_, &active)| active) {
                 circle {
                 circle {
-                    cx: "{dcx}",
-                    cy: "{dcy}",
-                    r: "{DOT_RADIUS}",
+                    cx: *x * 600,
+                    cy: *y * 600,
+                    r: 200,
                     fill: "#333"
                     fill: "#333"
                 }
                 }
             }
             }
-        });
-
-    cx.render(rsx! {
-      svg {
-        onclick: move |e| cx.props.onclick.call(e),
-        prevent_default: "onclick",
-        class: "die",
-        view_box: "-1000 -1000 2000 2000",
-
-        rect {
-          x: "-1000",
-          y: "-1000",
-          width: "2000",
-          height: "2000",
-          rx: "{DOT_RADIUS}",
-          fill: "{fill}",
         }
         }
-
-        {dots}
-      }
-    })
+    }
 }
 }

+ 0 - 81
examples/svg_basic.rs

@@ -1,81 +0,0 @@
-use dioxus::prelude::*;
-
-fn app(cx: Scope) -> Element {
-    cx.render(rsx!( svg {
-        width: "200",
-        height: "250",
-        xmlns: "http://www.w3.org/2000/svg",
-        version: "1.1",
-        rect {
-            x: "10",
-            y: "10",
-            width: "30",
-            height: "30",
-            stroke: "black",
-            fill: "transparent",
-            stroke_width: "5",
-        }
-        rect {
-            x: "60",
-            y: "10",
-            width: "30",
-            height: "30",
-            stroke: "black",
-            fill: "transparent",
-            stroke_width: "5",
-        }
-        circle {
-            cx: "25",
-            cy: "75",
-            r: "20",
-            stroke: "red",
-            fill: "transparent",
-            stroke_width: "5",
-        }
-        ellipse {
-            cx: "75",
-            cy: "75",
-            rx: "20",
-            ry: "5",
-            stroke: "red",
-            fill: "transparent",
-            stroke_width: "5",
-        }
-        line {
-            x1: "10",
-            x2: "50",
-            y1: "110",
-            y2: "150",
-            stroke: "orange",
-            stroke_width: "5",
-        }
-        polyline {
-            points: "60 110 65 120 70 115 75 130 80 125 85 140 90 135 95 150 100 145",
-            stroke: "orange",
-            fill: "transparent",
-            stroke_width: "5",
-        }
-        polygon {
-            points: "50 160 55 180 70 180 60 190 65 205 50 195 35 205 40 190 30 180 45 180",
-            stroke: "green",
-            fill: "transparent",
-            stroke_width: "5",
-        }
-        path {
-            d: "M20,230 Q40,205 50,230 T90,230",
-            fill: "none",
-            stroke: "blue",
-            stroke_width: "5",
-        }
-        path {
-            d: "M9.00001 9C9 62 103.5 124 103.5 178",
-            stroke: "#3CC4DC",
-            "stroke-linecap": "square",
-            "stroke-width": "square",
-        }
-    }))
-}
-
-fn main() {
-    dioxus_desktop::launch(app);
-}

+ 2 - 3
examples/tailwind/Cargo.toml

@@ -12,11 +12,10 @@ rust-version = "1.60.0"
 publish = false
 publish = false
 
 
 [dependencies]
 [dependencies]
-dioxus = { path = "../../packages/dioxus" }
 manganis = { workspace = true }
 manganis = { workspace = true }
 
 
 [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
 [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
-dioxus-desktop = { path = "../../packages/desktop" }
+dioxus = { path = "../../packages/dioxus", features = ["desktop"] }
 
 
 [target.'cfg(target_arch = "wasm32")'.dependencies]
 [target.'cfg(target_arch = "wasm32")'.dependencies]
-dioxus-web = { path = "../../packages/web" }
+dioxus = { path = "../../packages/dioxus", features = ["web"] }

+ 26 - 32
examples/tailwind/src/main.rs

@@ -5,33 +5,31 @@ use dioxus::prelude::*;
 const _STYLE: &str = manganis::mg!(file("./public/tailwind.css"));
 const _STYLE: &str = manganis::mg!(file("./public/tailwind.css"));
 
 
 fn main() {
 fn main() {
-    #[cfg(not(target_arch = "wasm32"))]
-    dioxus_desktop::launch(app);
-    #[cfg(target_arch = "wasm32")]
-    dioxus_web::launch(app);
+    launch(app);
 }
 }
 
 
-pub fn app(cx: Scope) -> Element {
+pub fn app() -> Element {
     let grey_background = true;
     let grey_background = true;
-    cx.render(rsx!(
+    rsx!(
         div {
         div {
             header {
             header {
                 class: "text-gray-400 body-font",
                 class: "text-gray-400 body-font",
                 // you can use optional attributes to optionally apply a tailwind class
                 // you can use optional attributes to optionally apply a tailwind class
-                class: if grey_background { "bg-gray-900" },
+                class: if grey_background {
+                    "bg-gray-900"
+                },
                 div { class: "container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center",
                 div { class: "container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center",
                     a { class: "flex title-font font-medium items-center text-white mb-4 md:mb-0",
                     a { class: "flex title-font font-medium items-center text-white mb-4 md:mb-0",
                         StacksIcon {}
                         StacksIcon {}
-                        span { class: "ml-3 text-xl", "Hello Dioxus!"}
+                        span { class: "ml-3 text-xl", "Hello Dioxus!" }
                     }
                     }
                     nav { class: "md:ml-auto flex flex-wrap items-center text-base justify-center",
                     nav { class: "md:ml-auto flex flex-wrap items-center text-base justify-center",
-                        a { class: "mr-5 hover:text-white", "First Link"}
-                        a { class: "mr-5 hover:text-white", "Second Link"}
-                        a { class: "mr-5 hover:text-white", "Third Link"}
-                        a { class: "mr-5 hover:text-white", "Fourth Link"}
+                        a { class: "mr-5 hover:text-white", "First Link" }
+                        a { class: "mr-5 hover:text-white", "Second Link" }
+                        a { class: "mr-5 hover:text-white", "Third Link" }
+                        a { class: "mr-5 hover:text-white", "Fourth Link" }
                     }
                     }
-                    button {
-                        class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
+                    button { class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
                         "Button"
                         "Button"
                         RightArrowIcon {}
                         RightArrowIcon {}
                     }
                     }
@@ -45,21 +43,17 @@ pub fn app(cx: Scope) -> Element {
                             br { class: "hidden lg:inline-block" }
                             br { class: "hidden lg:inline-block" }
                             "Dioxus Sneak Peek"
                             "Dioxus Sneak Peek"
                         }
                         }
-                        p {
-                            class: "mb-8 leading-relaxed",
+                        p { class: "mb-8 leading-relaxed",
 
 
                             "Dioxus is a new UI framework that makes it easy and simple to write cross-platform apps using web
                             "Dioxus is a new UI framework that makes it easy and simple to write cross-platform apps using web
                             technologies! It is functional, fast, and portable. Dioxus can run on the web, on the desktop, and
                             technologies! It is functional, fast, and portable. Dioxus can run on the web, on the desktop, and
                             on mobile and embedded platforms."
                             on mobile and embedded platforms."
-
                         }
                         }
                         div { class: "flex justify-center",
                         div { class: "flex justify-center",
-                            button {
-                                class: "inline-flex text-white bg-indigo-500 border-0 py-2 px-6 focus:outline-none hover:bg-indigo-600 rounded text-lg",
+                            button { class: "inline-flex text-white bg-indigo-500 border-0 py-2 px-6 focus:outline-none hover:bg-indigo-600 rounded text-lg",
                                 "Learn more"
                                 "Learn more"
                             }
                             }
-                            button {
-                                class: "ml-4 inline-flex text-gray-400 bg-gray-800 border-0 py-2 px-6 focus:outline-none hover:bg-gray-700 hover:text-white rounded text-lg",
+                            button { class: "ml-4 inline-flex text-gray-400 bg-gray-800 border-0 py-2 px-6 focus:outline-none hover:bg-gray-700 hover:text-white rounded text-lg",
                                 "Build an app"
                                 "Build an app"
                             }
                             }
                         }
                         }
@@ -68,18 +62,18 @@ pub fn app(cx: Scope) -> Element {
                         img {
                         img {
                             class: "object-cover object-center rounded",
                             class: "object-cover object-center rounded",
                             src: "https://i.imgur.com/oK6BLtw.png",
                             src: "https://i.imgur.com/oK6BLtw.png",
-                            referrerpolicy:"no-referrer",
-                            alt: "hero",
+                            referrerpolicy: "no-referrer",
+                            alt: "hero"
                         }
                         }
                     }
                     }
                 }
                 }
             }
             }
         }
         }
-    ))
+    )
 }
 }
 
 
-pub fn StacksIcon(cx: Scope) -> Element {
-    cx.render(rsx!(
+pub fn StacksIcon() -> Element {
+    rsx!(
         svg {
         svg {
             fill: "none",
             fill: "none",
             stroke: "currentColor",
             stroke: "currentColor",
@@ -88,13 +82,13 @@ pub fn StacksIcon(cx: Scope) -> Element {
             stroke_width: "2",
             stroke_width: "2",
             class: "w-10 h-10 text-white p-2 bg-indigo-500 rounded-full",
             class: "w-10 h-10 text-white p-2 bg-indigo-500 rounded-full",
             view_box: "0 0 24 24",
             view_box: "0 0 24 24",
-            path { d: "M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"}
+            path { d: "M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" }
         }
         }
-    ))
+    )
 }
 }
 
 
-pub fn RightArrowIcon(cx: Scope) -> Element {
-    cx.render(rsx!(
+pub fn RightArrowIcon() -> Element {
+    rsx!(
         svg {
         svg {
             fill: "none",
             fill: "none",
             stroke: "currentColor",
             stroke: "currentColor",
@@ -103,7 +97,7 @@ pub fn RightArrowIcon(cx: Scope) -> Element {
             stroke_width: "2",
             stroke_width: "2",
             class: "w-4 h-4 ml-1",
             class: "w-4 h-4 ml-1",
             view_box: "0 0 24 24",
             view_box: "0 0 24 24",
-            path { d: "M5 12h14M12 5l7 7-7 7"}
+            path { d: "M5 12h14M12 5l7 7-7 7" }
         }
         }
-    ))
+    )
 }
 }

+ 10 - 16
examples/tasks.rs

@@ -6,29 +6,23 @@ use dioxus::prelude::*;
 use std::time::Duration;
 use std::time::Duration;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let count = use_state(cx, || 0);
+fn app() -> Element {
+    let mut count = use_signal(|| 0);
 
 
-    use_future(cx, (), move |_| {
-        let mut count = count.clone();
-        async move {
-            loop {
-                tokio::time::sleep(Duration::from_millis(1000)).await;
-                count += 1;
-            }
+    use_future(move || async move {
+        loop {
+            tokio::time::sleep(Duration::from_millis(1000)).await;
+            count += 1;
         }
         }
     });
     });
 
 
-    cx.render(rsx! {
+    rsx! {
         div {
         div {
             h1 { "Current count: {count}" }
             h1 { "Current count: {count}" }
-            button {
-                onclick: move |_| count.set(0),
-                "Reset the count"
-            }
+            button { onclick: move |_| count.set(0), "Reset the count" }
         }
         }
-    })
+    }
 }
 }

+ 5 - 7
examples/textarea.rs

@@ -3,15 +3,13 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let model = use_state(cx, || String::from("asd"));
+fn app() -> Element {
+    let mut model = use_signal(|| String::from("asd"));
 
 
-    println!("{model}");
-
-    cx.render(rsx! {
+    rsx! {
         textarea {
         textarea {
             class: "border",
             class: "border",
             rows: "10",
             rows: "10",
@@ -19,5 +17,5 @@ fn app(cx: Scope) -> Element {
             value: "{model}",
             value: "{model}",
             oninput: move |e| model.set(e.value().clone()),
             oninput: move |e| model.set(e.value().clone()),
         }
         }
-    })
+    }
 }
 }

+ 111 - 144
examples/todomvc.rs

@@ -1,104 +1,108 @@
 #![allow(non_snake_case)]
 #![allow(non_snake_case)]
-
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 use dioxus_elements::input_data::keyboard_types::Key;
 use dioxus_elements::input_data::keyboard_types::Key;
+use std::collections::HashMap;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch(app);
 }
 }
 
 
 #[derive(PartialEq, Eq, Clone, Copy)]
 #[derive(PartialEq, Eq, Clone, Copy)]
-pub enum FilterState {
+enum FilterState {
     All,
     All,
     Active,
     Active,
     Completed,
     Completed,
 }
 }
 
 
-#[derive(Debug, PartialEq, Eq, Clone)]
-pub struct TodoItem {
-    pub id: u32,
-    pub checked: bool,
-    pub contents: String,
+#[derive(Debug, PartialEq, Eq)]
+struct TodoItem {
+    id: u32,
+    checked: bool,
+    contents: String,
 }
 }
 
 
-pub fn app(cx: Scope<()>) -> Element {
-    let todos = use_state(cx, im_rc::HashMap::<u32, TodoItem>::default);
-    let filter = use_state(cx, || FilterState::All);
+const STYLE: &str = include_str!("./assets/todomvc.css");
 
 
-    // Filter the todos based on the filter state
-    let mut filtered_todos = todos
-        .iter()
-        .filter(|(_, item)| match **filter {
-            FilterState::All => true,
-            FilterState::Active => !item.checked,
-            FilterState::Completed => item.checked,
-        })
-        .map(|f| *f.0)
-        .collect::<Vec<_>>();
-    filtered_todos.sort_unstable();
+fn app() -> Element {
+    let mut todos = use_signal(HashMap::<u32, TodoItem>::new);
+    let filter = use_signal(|| FilterState::All);
 
 
-    let active_todo_count = todos.values().filter(|item| !item.checked).count();
-    let active_todo_text = match active_todo_count {
-        1 => "item",
-        _ => "items",
-    };
+    let active_todo_count =
+        use_memo(move || todos.read().values().filter(|item| !item.checked).count());
+
+    let filtered_todos = use_memo(move || {
+        let mut filtered_todos = todos
+            .read()
+            .iter()
+            .filter(|(_, item)| match filter() {
+                FilterState::All => true,
+                FilterState::Active => !item.checked,
+                FilterState::Completed => item.checked,
+            })
+            .map(|f| *f.0)
+            .collect::<Vec<_>>();
 
 
-    let show_clear_completed = todos.values().any(|todo| todo.checked);
+        filtered_todos.sort_unstable();
+
+        filtered_todos
+    });
+
+    let toggle_all = move |_| {
+        let check = active_todo_count() != 0;
+        for (_, item) in todos.write().iter_mut() {
+            item.checked = check;
+        }
+    };
 
 
-    cx.render(rsx! {
+    rsx! {
         section { class: "todoapp",
         section { class: "todoapp",
-            style { {include_str!("./assets/todomvc.css")} }
-            TodoHeader { todos: todos }
+            style { {STYLE} }
+            TodoHeader { todos }
             section { class: "main",
             section { class: "main",
-                if !todos.is_empty() {
+                if !todos.read().is_empty() {
                     input {
                     input {
                         id: "toggle-all",
                         id: "toggle-all",
                         class: "toggle-all",
                         class: "toggle-all",
                         r#type: "checkbox",
                         r#type: "checkbox",
-                        onchange: move |_| {
-                            let check = active_todo_count != 0;
-                            for (_, item) in todos.make_mut().iter_mut() {
-                                item.checked = check;
-                            }
-                        },
-                        checked: if active_todo_count == 0 { "true" } else { "false" },
+                        onchange: toggle_all,
+                        checked: active_todo_count() == 0,
                     }
                     }
                     label { r#for: "toggle-all" }
                     label { r#for: "toggle-all" }
                 }
                 }
                 ul { class: "todo-list",
                 ul { class: "todo-list",
-                    for id in filtered_todos.iter() {
-                        TodoEntry {
-                            key: "{id}",
-                            id: *id,
-                            todos: todos,
-                        }
+                    for id in filtered_todos() {
+                        TodoEntry { key: "{id}", id, todos }
                     }
                     }
                 }
                 }
-                if !todos.is_empty() {
-                    ListFooter {
-                        active_todo_count: active_todo_count,
-                        active_todo_text: active_todo_text,
-                        show_clear_completed: show_clear_completed,
-                        todos: todos,
-                        filter: filter,
-                    }
+                if !todos.read().is_empty() {
+                    ListFooter { active_todo_count, todos, filter }
                 }
                 }
             }
             }
         }
         }
         PageFooter {}
         PageFooter {}
-    })
-}
-
-#[derive(Props)]
-pub struct TodoHeaderProps<'a> {
-    todos: &'a UseState<im_rc::HashMap<u32, TodoItem>>,
+    }
 }
 }
 
 
-pub fn TodoHeader<'a>(cx: Scope<'a, TodoHeaderProps<'a>>) -> Element {
-    let draft = use_state(cx, || "".to_string());
-    let todo_id = use_state(cx, || 0);
+#[component]
+fn TodoHeader(mut todos: Signal<HashMap<u32, TodoItem>>) -> Element {
+    let mut draft = use_signal(|| "".to_string());
+    let mut todo_id = use_signal(|| 0);
+
+    let onkeydown = move |evt: KeyboardEvent| {
+        if evt.key() == Key::Enter && !draft.read().is_empty() {
+            let id = todo_id();
+            let todo = TodoItem {
+                id,
+                checked: false,
+                contents: draft.to_string(),
+            };
+            todos.write().insert(id, todo);
+            todo_id += 1;
+            draft.set("".to_string());
+        }
+    };
 
 
-    cx.render(rsx! {
+    rsx! {
         header { class: "header",
         header { class: "header",
             h1 { "todos" }
             h1 { "todos" }
             input {
             input {
@@ -106,76 +110,46 @@ pub fn TodoHeader<'a>(cx: Scope<'a, TodoHeaderProps<'a>>) -> Element {
                 placeholder: "What needs to be done?",
                 placeholder: "What needs to be done?",
                 value: "{draft}",
                 value: "{draft}",
                 autofocus: "true",
                 autofocus: "true",
-                oninput: move |evt| {
-                    draft.set(evt.value().clone());
-                },
-                onkeydown: move |evt| {
-                    if evt.key() == Key::Enter && !draft.is_empty() {
-                        cx.props
-                            .todos
-                            .make_mut()
-                            .insert(
-                                **todo_id,
-                                TodoItem {
-                                    id: **todo_id,
-                                    checked: false,
-                                    contents: draft.to_string(),
-                                },
-                            );
-                        *todo_id.make_mut() += 1;
-                        draft.set("".to_string());
-                    }
-                }
+                oninput: move |evt| draft.set(evt.value().clone()),
+                onkeydown,
             }
             }
         }
         }
-    })
-}
-
-#[derive(Props)]
-pub struct TodoEntryProps<'a> {
-    todos: &'a UseState<im_rc::HashMap<u32, TodoItem>>,
-    id: u32,
+    }
 }
 }
 
 
-pub fn TodoEntry<'a>(cx: Scope<'a, TodoEntryProps<'a>>) -> Element {
-    let is_editing = use_state(cx, || false);
+#[component]
+fn TodoEntry(mut todos: Signal<HashMap<u32, TodoItem>>, id: u32) -> Element {
+    let mut is_editing = use_signal(|| false);
+    let checked = use_memo(move || todos.read().get(&id).unwrap().checked);
+    let contents = use_memo(move || todos.read().get(&id).unwrap().contents.clone());
 
 
-    let todos = cx.props.todos.get();
-    let todo = &todos[&cx.props.id];
-    let completed = if todo.checked { "completed" } else { "" };
-    let editing = if **is_editing { "editing" } else { "" };
-
-    cx.render(rsx!{
-        li { class: "{completed} {editing}",
+    rsx! {
+        li { class: if checked() { "completed" }, class: if is_editing() { "editing" },
             div { class: "view",
             div { class: "view",
                 input {
                 input {
                     class: "toggle",
                     class: "toggle",
                     r#type: "checkbox",
                     r#type: "checkbox",
-                    id: "cbg-{todo.id}",
-                    checked: "{todo.checked}",
-                    oninput: move |evt| {
-                        cx.props.todos.make_mut()[&cx.props.id].checked = evt.value().parse().unwrap();
-                    }
+                    id: "cbg-{id}",
+                    checked: "{checked}",
+                    oninput: move |evt| todos.write().get_mut(&id).unwrap().checked = evt.value().parse().unwrap(),
                 }
                 }
                 label {
                 label {
-                    r#for: "cbg-{todo.id}",
+                    r#for: "cbg-{id}",
                     ondoubleclick: move |_| is_editing.set(true),
                     ondoubleclick: move |_| is_editing.set(true),
                     prevent_default: "onclick",
                     prevent_default: "onclick",
-                    "{todo.contents}"
+                    "{contents}"
                 }
                 }
                 button {
                 button {
                     class: "destroy",
                     class: "destroy",
-                    onclick: move |_| {
-                        cx.props.todos.make_mut().remove(&todo.id);
-                    },
+                    onclick: move |_| { todos.write().remove(&id); },
                     prevent_default: "onclick"
                     prevent_default: "onclick"
                 }
                 }
             }
             }
-            if **is_editing {
+            if is_editing() {
                 input {
                 input {
                     class: "edit",
                     class: "edit",
-                    value: "{todo.contents}",
-                    oninput: move |evt| cx.props.todos.make_mut()[&cx.props.id].contents = evt.value(),
+                    value: "{contents}",
+                    oninput: move |evt| todos.write().get_mut(&id).unwrap().contents = evt.value(),
                     autofocus: "true",
                     autofocus: "true",
                     onfocusout: move |_| is_editing.set(false),
                     onfocusout: move |_| is_editing.set(false),
                     onkeydown: move |evt| {
                     onkeydown: move |evt| {
@@ -183,39 +157,32 @@ pub fn TodoEntry<'a>(cx: Scope<'a, TodoEntryProps<'a>>) -> Element {
                             Key::Enter | Key::Escape | Key::Tab => is_editing.set(false),
                             Key::Enter | Key::Escape | Key::Tab => is_editing.set(false),
                             _ => {}
                             _ => {}
                         }
                         }
-                    },
+                    }
                 }
                 }
             }
             }
         }
         }
-    })
+    }
 }
 }
 
 
-#[derive(Props)]
-pub struct ListFooterProps<'a> {
-    todos: &'a UseState<im_rc::HashMap<u32, TodoItem>>,
-    active_todo_count: usize,
-    active_todo_text: &'a str,
-    show_clear_completed: bool,
-    filter: &'a UseState<FilterState>,
-}
-
-pub fn ListFooter<'a>(cx: Scope<'a, ListFooterProps<'a>>) -> Element {
-    let active_todo_count = cx.props.active_todo_count;
-    let active_todo_text = cx.props.active_todo_text;
+#[component]
+fn ListFooter(
+    mut todos: Signal<HashMap<u32, TodoItem>>,
+    active_todo_count: ReadOnlySignal<usize>,
+    mut filter: Signal<FilterState>,
+) -> Element {
+    let show_clear_completed = use_memo(move || todos.read().values().any(|todo| todo.checked));
 
 
-    let selected = |state| {
-        if *cx.props.filter == state {
-            "selected"
-        } else {
-            "false"
-        }
-    };
-
-    cx.render(rsx! {
+    rsx! {
         footer { class: "footer",
         footer { class: "footer",
             span { class: "todo-count",
             span { class: "todo-count",
                 strong { "{active_todo_count} " }
                 strong { "{active_todo_count} " }
-                span { "{active_todo_text} left" }
+                span {
+                    match active_todo_count() {
+                        1 => "item",
+                        _ => "items",
+                    }
+                    " left"
+                }
             }
             }
             ul { class: "filters",
             ul { class: "filters",
                 for (state , state_text , url) in [
                 for (state , state_text , url) in [
@@ -226,27 +193,27 @@ pub fn ListFooter<'a>(cx: Scope<'a, ListFooterProps<'a>>) -> Element {
                     li {
                     li {
                         a {
                         a {
                             href: url,
                             href: url,
-                            class: selected(state),
-                            onclick: move |_| cx.props.filter.set(state),
+                            class: if filter() == state { "selected" },
+                            onclick: move |_| filter.set(state),
                             prevent_default: "onclick",
                             prevent_default: "onclick",
                             {state_text}
                             {state_text}
                         }
                         }
                     }
                     }
                 }
                 }
             }
             }
-            if cx.props.show_clear_completed {
+            if show_clear_completed() {
                 button {
                 button {
                     class: "clear-completed",
                     class: "clear-completed",
-                    onclick: move |_| cx.props.todos.make_mut().retain(|_, todo| !todo.checked),
+                    onclick: move |_| todos.write().retain(|_, todo| !todo.checked),
                     "Clear completed"
                     "Clear completed"
                 }
                 }
             }
             }
         }
         }
-    })
+    }
 }
 }
 
 
-pub fn PageFooter(cx: Scope) -> Element {
-    cx.render(rsx! {
+fn PageFooter() -> Element {
+    rsx! {
         footer { class: "info",
         footer { class: "info",
             p { "Double-click to edit a todo" }
             p { "Double-click to edit a todo" }
             p {
             p {
@@ -258,5 +225,5 @@ pub fn PageFooter(cx: Scope) -> Element {
                 a { href: "http://todomvc.com", "TodoMVC" }
                 a { href: "http://todomvc.com", "TodoMVC" }
             }
             }
         }
         }
-    })
+    }
 }
 }

+ 7 - 7
examples/video_stream.rs

@@ -1,7 +1,7 @@
+use dioxus::desktop::wry::http;
+use dioxus::desktop::wry::http::Response;
+use dioxus::desktop::{use_asset_handler, AssetRequest};
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::wry::http;
-use dioxus_desktop::wry::http::Response;
-use dioxus_desktop::{use_asset_handler, AssetRequest};
 use http::{header::*, response::Builder as ResponseBuilder, status::StatusCode};
 use http::{header::*, response::Builder as ResponseBuilder, status::StatusCode};
 use std::{io::SeekFrom, path::PathBuf};
 use std::{io::SeekFrom, path::PathBuf};
 use tokio::io::AsyncReadExt;
 use tokio::io::AsyncReadExt;
@@ -26,11 +26,11 @@ fn main() {
                 }
                 }
             });
             });
     }
     }
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    use_asset_handler(cx, "videos", move |request, responder| {
+fn app() -> Element {
+    use_asset_handler("videos", move |request, responder| {
         // Using dioxus::spawn works, but is slower than a dedicated thread
         // Using dioxus::spawn works, but is slower than a dedicated thread
         tokio::task::spawn(async move {
         tokio::task::spawn(async move {
             let video_file = PathBuf::from(VIDEO_PATH);
             let video_file = PathBuf::from(VIDEO_PATH);
@@ -43,7 +43,7 @@ fn app(cx: Scope) -> Element {
         });
         });
     });
     });
 
 
-    render! {
+    rsx! {
         div {
         div {
             video {
             video {
                 src: "/videos/test_video.mp4",
                 src: "/videos/test_video.mp4",

+ 4 - 4
examples/web_component.rs

@@ -1,13 +1,13 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
+fn app() -> Element {
+    rsx! {
         web-component {
         web-component {
             "my-prop": "5%",
             "my-prop": "5%",
         }
         }
-    })
+    }
 }
 }

+ 35 - 40
examples/window_event.rs

@@ -1,75 +1,70 @@
+use dioxus::desktop::{window, Config, WindowBuilder};
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::{Config, WindowBuilder};
 
 
 fn main() {
 fn main() {
-    let cfg = Config::new().with_window(
-        WindowBuilder::new()
-            .with_title("Borderless Window")
-            .with_decorations(false),
-    );
-
-    dioxus_desktop::launch_cfg(app, cfg);
+    LaunchBuilder::desktop()
+        .with_cfg(
+            Config::new().with_window(
+                WindowBuilder::new()
+                    .with_title("Borderless Window")
+                    .with_decorations(false),
+            ),
+        )
+        .launch(app)
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let window = dioxus_desktop::use_window(cx);
-
-    // if you want to make window fullscreen, you need close the resizable.
-    // window.set_fullscreen(true);
-    // window.set_resizable(false);
-
-    let fullscreen = use_state(cx, || false);
-    let always_on_top = use_state(cx, || false);
-    let decorations = use_state(cx, || false);
+fn app() -> Element {
+    let mut fullscreen = use_signal(|| false);
+    let mut always_on_top = use_signal(|| false);
+    let mut decorations = use_signal(|| false);
 
 
-    cx.render(rsx!(
-        link { href:"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css", rel:"stylesheet" }
+    rsx!(
+        link {
+            href: "https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css",
+            rel: "stylesheet"
+        }
         header {
         header {
             class: "text-gray-400 bg-gray-900 body-font",
             class: "text-gray-400 bg-gray-900 body-font",
-            onmousedown: move |_| window.drag(),
-            div {
-                class: "container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center",
+            onmousedown: move |_| window().drag(),
+            div { class: "container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center",
                 a { class: "flex title-font font-medium items-center text-white mb-4 md:mb-0",
                 a { class: "flex title-font font-medium items-center text-white mb-4 md:mb-0",
-                    span { class: "ml-3 text-xl", "Dioxus"}
+                    span { class: "ml-3 text-xl", "Dioxus" }
                 }
                 }
                 nav { class: "md:ml-auto flex flex-wrap items-center text-base justify-center" }
                 nav { class: "md:ml-auto flex flex-wrap items-center text-base justify-center" }
                 button {
                 button {
                     class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
                     class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
                     onmousedown: |evt| evt.stop_propagation(),
                     onmousedown: |evt| evt.stop_propagation(),
-                    onclick: move |_| window.set_minimized(true),
+                    onclick: move |_| window().set_minimized(true),
                     "Minimize"
                     "Minimize"
                 }
                 }
                 button {
                 button {
                     class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
                     class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
                     onmousedown: |evt| evt.stop_propagation(),
                     onmousedown: |evt| evt.stop_propagation(),
                     onclick: move |_| {
                     onclick: move |_| {
-
-                        window.set_fullscreen(!**fullscreen);
-                        window.set_resizable(**fullscreen);
-                        fullscreen.modify(|f| !*f);
+                        window().set_fullscreen(!fullscreen());
+                        window().set_resizable(fullscreen());
+                        fullscreen.toggle();
                     },
                     },
                     "Fullscreen"
                     "Fullscreen"
                 }
                 }
                 button {
                 button {
                     class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
                     class: "inline-flex items-center bg-gray-800 border-0 py-1 px-3 focus:outline-none hover:bg-gray-700 rounded text-base mt-4 md:mt-0",
                     onmousedown: |evt| evt.stop_propagation(),
                     onmousedown: |evt| evt.stop_propagation(),
-                    onclick: move |_| window.close(),
+                    onclick: move |_| window().close(),
                     "Close"
                     "Close"
                 }
                 }
             }
             }
         }
         }
         br {}
         br {}
-        div {
-            class: "container mx-auto",
-            div {
-                class: "grid grid-cols-5",
+        div { class: "container mx-auto",
+            div { class: "grid grid-cols-5",
                 div {
                 div {
                     button {
                     button {
                         class: "inline-flex items-center text-white bg-green-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
                         class: "inline-flex items-center text-white bg-green-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
                         onmousedown: |evt| evt.stop_propagation(),
                         onmousedown: |evt| evt.stop_propagation(),
                         onclick: move |_| {
                         onclick: move |_| {
-                            window.set_always_on_top(!always_on_top);
-                            always_on_top.set(!always_on_top);
+                            window().set_always_on_top(!always_on_top());
+                            always_on_top.toggle();
                         },
                         },
                         "Always On Top"
                         "Always On Top"
                     }
                     }
@@ -79,8 +74,8 @@ fn app(cx: Scope) -> Element {
                         class: "inline-flex items-center text-white bg-blue-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
                         class: "inline-flex items-center text-white bg-blue-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
                         onmousedown: |evt| evt.stop_propagation(),
                         onmousedown: |evt| evt.stop_propagation(),
                         onclick: move |_| {
                         onclick: move |_| {
-                            window.set_decorations(!decorations);
-                            decorations.set(!decorations);
+                            window().set_decorations(!decorations());
+                            decorations.toggle();
                         },
                         },
                         "Set Decorations"
                         "Set Decorations"
                     }
                     }
@@ -89,11 +84,11 @@ fn app(cx: Scope) -> Element {
                     button {
                     button {
                         class: "inline-flex items-center text-white bg-blue-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
                         class: "inline-flex items-center text-white bg-blue-500 border-0 py-1 px-3 hover:bg-green-700 rounded",
                         onmousedown: |evt| evt.stop_propagation(),
                         onmousedown: |evt| evt.stop_propagation(),
-                        onclick: move |_| window.set_title("Dioxus Application"),
+                        onclick: move |_| window().set_title("Dioxus Application"),
                         "Change Title"
                         "Change Title"
                     }
                     }
                 }
                 }
             }
             }
         }
         }
-    ))
+    )
 }
 }

+ 23 - 33
examples/window_focus.rs

@@ -1,45 +1,35 @@
+use dioxus::desktop::tao::event::Event as WryEvent;
+use dioxus::desktop::tao::event::WindowEvent;
+use dioxus::desktop::use_wry_event_handler;
+use dioxus::desktop::{Config, WindowCloseBehaviour};
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_desktop::tao::event::Event as WryEvent;
-use dioxus_desktop::tao::event::WindowEvent;
-use dioxus_desktop::use_wry_event_handler;
-use dioxus_desktop::{Config, WindowCloseBehaviour};
 
 
 fn main() {
 fn main() {
-    let cfg = Config::new().with_close_behaviour(WindowCloseBehaviour::CloseWindow);
-
-    dioxus_desktop::launch_cfg(app, cfg);
+    LaunchBuilder::desktop()
+        .with_cfg(Config::new().with_close_behaviour(WindowCloseBehaviour::CloseWindow))
+        .launch(app)
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let focused = use_state(cx, || false);
+fn app() -> Element {
+    let mut focused = use_signal(|| true);
 
 
-    use_wry_event_handler(cx, {
-        to_owned![focused];
-        move |event, _| {
-            if let WryEvent::WindowEvent {
-                event: WindowEvent::Focused(new_focused),
-                ..
-            } = event
-            {
-                focused.set(*new_focused);
-            }
+    use_wry_event_handler(move |event, _| {
+        if let WryEvent::WindowEvent {
+            event: WindowEvent::Focused(new_focused),
+            ..
+        } = event
+        {
+            focused.set(*new_focused)
         }
         }
     });
     });
 
 
-    cx.render(rsx! {
-        div{
-            width: "100%",
-            height: "100%",
-            display: "flex",
-            flex_direction: "column",
-            align_items: "center",
-            {
-                if *focused.get() {
-                    "This window is focused!"
-                } else {
-                    "This window is not focused!"
-                }
+    rsx! {
+        div { width: "100%", height: "100%", display: "flex", flex_direction: "column", align_items: "center",
+            if focused() {
+                "This window is focused!"
+            } else {
+                "This window is not focused!"
             }
             }
         }
         }
-    })
+    }
 }
 }

+ 7 - 7
examples/window_zoom.rs

@@ -1,22 +1,22 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let level = use_state(cx, || 1.0);
+fn app() -> Element {
+    let mut level = use_signal(|| 1.0);
 
 
-    cx.render(rsx! {
+    rsx! {
         input {
         input {
             r#type: "number",
             r#type: "number",
             value: "{level}",
             value: "{level}",
-            oninput: |e| {
+            oninput: move |e| {
                 if let Ok(new_zoom) = e.value().parse::<f64>() {
                 if let Ok(new_zoom) = e.value().parse::<f64>() {
                     level.set(new_zoom);
                     level.set(new_zoom);
-                    dioxus_desktop::window().webview.zoom(new_zoom);
+                    dioxus::desktop::window().webview.zoom(new_zoom);
                 }
                 }
             }
             }
         }
         }
-    })
+    }
 }
 }

+ 5 - 7
examples/xss_safety.rs

@@ -5,15 +5,13 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {
-    dioxus_desktop::launch(app);
+    launch_desktop(app);
 }
 }
 
 
-fn app(cx: Scope) -> Element {
-    let contents = use_state(cx, || {
-        String::from("<script>alert(\"hello world\")</script>")
-    });
+fn app() -> Element {
+    let mut contents = use_signal(|| String::from("<script>alert(\"hello world\")</script>"));
 
 
-    cx.render(rsx! {
+    rsx! {
         div {
         div {
             h1 {"Dioxus is XSS-Safe"}
             h1 {"Dioxus is XSS-Safe"}
             h3 { "{contents}" }
             h3 { "{contents}" }
@@ -23,5 +21,5 @@ fn app(cx: Scope) -> Element {
                 oninput: move |e| contents.set(e.value()),
                 oninput: move |e| contents.set(e.value()),
             }
             }
         }
         }
-    })
+    }
 }
 }

+ 1 - 1
packages/autofmt/tests/samples/immediate_expr.rsx

@@ -1,4 +1,4 @@
 fn it_works() {
 fn it_works() {
-    cx.render(rsx!({()}))
+    rsx!({()})
 }
 }
 
 

+ 4 - 4
packages/autofmt/tests/samples/long.rsx

@@ -5,8 +5,8 @@ pub fn Explainer<'a>(
     cx: Scope<'a>,
     cx: Scope<'a>,
     invert: bool,
     invert: bool,
     title: &'static str,
     title: &'static str,
-    content: Element<'a>,
-    flasher: Element<'a>,
+    content: Element,
+    flasher: Element,
 ) -> Element {
 ) -> Element {
     // pt-5 sm:pt-24 lg:pt-24
     // pt-5 sm:pt-24 lg:pt-24
 
 
@@ -32,10 +32,10 @@ pub fn Explainer<'a>(
         std::mem::swap(&mut left, &mut right);
         std::mem::swap(&mut left, &mut right);
     }
     }
 
 
-    cx.render(rsx! {
+    rsx! {
         div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light",
         div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light",
             {left},
             {left},
             {right}
             {right}
         }
         }
-    })
+    }
 }
 }

+ 3 - 3
packages/autofmt/tests/samples/messy_indent.rsx

@@ -1,4 +1,4 @@
-fn SaveClipboard(cx: Scope) -> Element {
+fn SaveClipboard() -> Element {
     rsx! {
     rsx! {
         div { class: "relative w-1/2 {align} max-w-md leading-8",
         div { class: "relative w-1/2 {align} max-w-md leading-8",
             h2 { class: "mb-6 text-3xl leading-tight md:text-4xl md:leading-tight lg:text-3xl lg:leading-tight font-heading font-mono font-bold",
             h2 { class: "mb-6 text-3xl leading-tight md:text-4xl md:leading-tight lg:text-3xl lg:leading-tight font-heading font-mono font-bold",
@@ -7,7 +7,7 @@ fn SaveClipboard(cx: Scope) -> Element {
         }
         }
     };
     };
 
 
-    cx.render(rsx! {
+    rsx! {
         div { "hello world", "hello world", "hello world" }
         div { "hello world", "hello world", "hello world" }
-    })
+    }
 }
 }

+ 2 - 2
packages/autofmt/tests/samples/reallylong.rsx

@@ -1,5 +1,5 @@
 pub static Icon3: Component<()> = |cx| {
 pub static Icon3: Component<()> = |cx| {
-    cx.render(rsx! {
+    rsx! {
         svg {
         svg {
             class: "w-6 h-6",
             class: "w-6 h-6",
             stroke_linecap: "round",
             stroke_linecap: "round",
@@ -11,5 +11,5 @@ pub static Icon3: Component<()> = |cx| {
             path { d: "M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2" }
             path { d: "M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2" }
             circle { cx: "12", cy: "7", r: "4" }
             circle { cx: "12", cy: "7", r: "4" }
         }
         }
-    })
+    }
 };
 };

+ 2 - 2
packages/autofmt/tests/samples/trailing_expr.rsx

@@ -1,7 +1,7 @@
 fn it_works() {
 fn it_works() {
-    cx.render(rsx! {
+    rsx! {
         div {
         div {
             span { "Description: ", {package.description.as_deref().unwrap_or("❌❌❌❌ missing")} }
             span { "Description: ", {package.description.as_deref().unwrap_or("❌❌❌❌ missing")} }
         }
         }
-    })
+    }
 }
 }

+ 2 - 2
packages/autofmt/tests/wrong/multi-4sp.rsx

@@ -1,3 +1,3 @@
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! { div { "hello world" } })
+fn app() -> Element {
+    rsx! { div { "hello world" } }
 }
 }

+ 3 - 3
packages/autofmt/tests/wrong/multi-4sp.wrong.rsx

@@ -1,5 +1,5 @@
-fn app(cx: Scope) -> Element {
-    cx.render(rsx! {
+fn app() -> Element {
+    rsx! {
         div {"hello world" }
         div {"hello world" }
-    })
+    }
 }
 }

+ 2 - 2
packages/autofmt/tests/wrong/multi-tab.rsx

@@ -1,3 +1,3 @@
-fn app(cx: Scope) -> Element {
-	cx.render(rsx! { div { "hello world" } })
+fn app() -> Element {
+	rsx! { div { "hello world" } }
 }
 }

+ 3 - 3
packages/autofmt/tests/wrong/multi-tab.wrong.rsx

@@ -1,5 +1,5 @@
-fn app(cx: Scope) -> Element {
-	cx.render(rsx! {
+fn app() -> Element {
+	rsx! {
 		div {"hello world" }
 		div {"hello world" }
-	})
+	}
 }
 }

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor