├── .devcontainer ├── Dockerfile ├── README.md └── devcontainer.json ├── .docker ├── Dockerfile_base_test_image ├── Dockerfile_code_coverage ├── Dockerfile_pre_test ├── Dockerfile_test ├── README.md └── run_local_tests.sh ├── .github ├── CODEOWNERS ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_requst.md ├── actions │ └── free-disk-space │ │ └── action.yml ├── dependabot.yml ├── install.ps1 ├── install.sh └── workflows │ ├── main.yml │ ├── merge.yml │ ├── promote.yml │ ├── publish.yml │ ├── setup-dev-drive.ps1 │ └── typos.yml ├── .gitignore ├── .mailmap ├── .vscode ├── .gitignore ├── settings.json └── spellright.dict ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── _typos.toml ├── codecov.yml ├── example-projects ├── ecommerce-site │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ ├── demo.png │ ├── public │ │ ├── loading.css │ │ └── tailwind.css │ ├── src │ │ ├── api.rs │ │ ├── components │ │ │ ├── cart.rs │ │ │ ├── error.rs │ │ │ ├── home.rs │ │ │ ├── loading.rs │ │ │ ├── nav.rs │ │ │ ├── product_item.rs │ │ │ └── product_page.rs │ │ └── main.rs │ └── tailwind.css ├── file-explorer │ ├── .gitignore │ ├── Cargo.toml │ ├── Dioxus.toml │ ├── README.md │ ├── assets │ │ ├── fileexplorer.css │ │ └── image.png │ └── src │ │ └── main.rs ├── fullstack-hackernews │ ├── .gitignore │ ├── Cargo.toml │ ├── assets │ │ └── hackernews.css │ └── src │ │ └── main.rs └── wifi-scanner │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ ├── demo_small.png │ └── src │ └── main.rs ├── examples ├── README.md ├── all_events.rs ├── assets │ ├── calculator.css │ ├── clock.css │ ├── context_api.css │ ├── counter.css │ ├── crm.css │ ├── custom_assets.css │ ├── events.css │ ├── file_upload.css │ ├── flat_router.css │ ├── links.css │ ├── logo.png │ ├── overlay.css │ ├── radio.css │ ├── read_size.css │ ├── roulette.css │ ├── router.css │ ├── todomvc.css │ └── visible.css ├── backgrounded_futures.rs ├── calculator.rs ├── calculator_mutable.rs ├── clock.rs ├── context_api.rs ├── control_focus.rs ├── counters.rs ├── crm.rs ├── custom_assets.rs ├── custom_html.rs ├── custom_menu.rs ├── disabled.rs ├── dog_app.rs ├── dynamic_asset.rs ├── errors.rs ├── eval.rs ├── file_upload.rs ├── flat_router.rs ├── form.rs ├── fullstack-auth │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ ├── auth.rs │ │ └── main.rs ├── fullstack-desktop │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── fullstack-hello-world │ ├── .gitignore │ ├── Cargo.toml │ ├── assets │ │ └── hello.css │ └── src │ │ └── main.rs ├── fullstack-router │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── fullstack-streaming │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── fullstack-websockets │ ├── .gitignore │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── future.rs ├── generic_component.rs ├── global.rs ├── hash_fragment_state.rs ├── hello_world.rs ├── hydration.rs ├── image_generator_openai.rs ├── link.rs ├── logging.rs ├── login_form.rs ├── memo_chain.rs ├── meta.rs ├── multiwindow.rs ├── nested_listeners.rs ├── optional_props.rs ├── overlay.rs ├── popup.rs ├── pwa │ ├── Cargo.toml │ ├── Dioxus.toml │ ├── LICENSE │ ├── README.md │ ├── index.html │ ├── public │ │ ├── favicon.ico │ │ ├── logo_192.png │ │ ├── logo_512.png │ │ ├── manifest.json │ │ └── sw.js │ └── src │ │ └── main.rs ├── query_segment_search.rs ├── read_size.rs ├── readme.rs ├── reducer.rs ├── resize.rs ├── router.rs ├── router_resource.rs ├── router_restore_scroll.rs ├── rsx_usage.rs ├── scroll_to_offset.rs ├── scroll_to_top.rs ├── shortcut.rs ├── shorthand.rs ├── signals.rs ├── simple_list.rs ├── simple_router.rs ├── spread.rs ├── ssr.rs ├── streams.rs ├── suspense.rs ├── svg.rs ├── tailwind │ ├── .gitignore │ ├── Cargo.toml │ ├── Dioxus.toml │ ├── README.md │ ├── public │ │ └── tailwind.css │ ├── src │ │ └── main.rs │ └── tailwind.css ├── title.rs ├── todomvc.rs ├── video_stream.rs ├── visible.rs ├── weather_app.rs ├── web_component.rs ├── wgpu_child_window.rs ├── window_event.rs ├── window_focus.rs ├── window_zoom.rs └── xss_safety.rs ├── flake.lock ├── flake.nix ├── lychee.toml ├── notes ├── CONTRIBUTING.md ├── FAQ.md ├── RELEASING.md ├── android_and_ios2.avif ├── autofmt.gif ├── bundle.gif ├── dioxus-community.avif ├── dioxus_splash_8.avif ├── docs.avif ├── flat-splash.avif ├── header-dark-updated.svg ├── header-dark.svg ├── header-light-updated.svg ├── header-light.svg ├── header.svg ├── hotreload.gif ├── image-splash.avif ├── releases │ └── 0.7.0-alpha.0.md ├── splash-header-darkmode.svg └── splash-header.svg ├── packages ├── asset-resolver │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── autofmt │ ├── .vscode │ │ └── settings.json │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ ├── buffer.rs │ │ ├── collect_macros.rs │ │ ├── indent.rs │ │ ├── lib.rs │ │ ├── prettier_please.rs │ │ └── writer.rs │ └── tests │ │ ├── error_handling.rs │ │ ├── partials │ │ ├── no_parse.rsx │ │ ├── okay.rsx │ │ └── wrong.rsx │ │ ├── samples.rs │ │ ├── samples │ │ ├── asset.rsx │ │ ├── attributes.rsx │ │ ├── basic_expr.rsx │ │ ├── collapse.rsx │ │ ├── collapse_expr.rsx │ │ ├── comments.rsx │ │ ├── commentshard.rsx │ │ ├── complex.rsx │ │ ├── docsite.rsx │ │ ├── emoji.rsx │ │ ├── fat_exprs.rsx │ │ ├── ifchain_forloop.rsx │ │ ├── immediate_expr.rsx │ │ ├── key.rsx │ │ ├── letsome.rsx │ │ ├── long.rsx │ │ ├── long_exprs.rsx │ │ ├── manual_props.rsx │ │ ├── many_exprs.rsx │ │ ├── messy_indent.rsx │ │ ├── misplaced.rsx │ │ ├── multirsx.rsx │ │ ├── nested.rsx │ │ ├── oneline.rsx │ │ ├── prop_rsx.rsx │ │ ├── raw_strings.rsx │ │ ├── reallylong.rsx │ │ ├── shorthand.rsx │ │ ├── simple.rsx │ │ ├── skip.rsx │ │ ├── spaces.rsx │ │ ├── staged.rsx │ │ ├── t2.rsx │ │ ├── tiny.rsx │ │ ├── tinynoopt.rsx │ │ └── trailing_expr.rsx │ │ ├── srcless.rs │ │ ├── srcless │ │ ├── asset.rsx │ │ └── basic_expr.rsx │ │ ├── wrong.rs │ │ └── wrong │ │ ├── comments-4sp.rsx │ │ ├── comments-4sp.wrong.rsx │ │ ├── comments-tab.rsx │ │ ├── comments-tab.wrong.rsx │ │ ├── multi-4sp.rsx │ │ ├── multi-4sp.wrong.rsx │ │ ├── multi-tab.rsx │ │ ├── multi-tab.wrong.rsx │ │ ├── multiexpr-4sp.rsx │ │ ├── multiexpr-4sp.wrong.rsx │ │ ├── multiexpr-many.rsx │ │ ├── multiexpr-many.wrong.rsx │ │ ├── multiexpr-tab.rsx │ │ ├── multiexpr-tab.wrong.rsx │ │ ├── oneline-expand.rsx │ │ ├── oneline-expand.wrong.rsx │ │ ├── shortened.rsx │ │ ├── shortened.wrong.rsx │ │ ├── simple-combo-expr.rsx │ │ ├── simple-combo-expr.wrong.rsx │ │ ├── skipfail.rsx │ │ ├── skipfail.wrong.rsx │ │ ├── syntax_error.rsx │ │ └── syntax_error.wrong.rsx ├── check │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── check.rs │ │ ├── issues.rs │ │ ├── lib.rs │ │ └── metadata.rs ├── cli-config │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── lib.rs ├── cli-opt │ ├── Cargo.toml │ ├── build.rs │ └── src │ │ ├── build_info.rs │ │ ├── css.rs │ │ ├── file.rs │ │ ├── folder.rs │ │ ├── hash.rs │ │ ├── image │ │ ├── jpg.rs │ │ ├── mod.rs │ │ └── png.rs │ │ ├── js.rs │ │ ├── json.rs │ │ └── lib.rs ├── cli │ ├── .gitignore │ ├── Cargo.toml │ ├── Dioxus.toml │ ├── README.md │ ├── assets │ │ ├── android │ │ │ ├── MainActivity.kt.hbs │ │ │ └── gen │ │ │ │ ├── .gitignore │ │ │ │ ├── app │ │ │ │ ├── build.gradle.kts.hbs │ │ │ │ ├── proguard-rules.pro │ │ │ │ └── src │ │ │ │ │ └── main │ │ │ │ │ ├── AndroidManifest.xml.hbs │ │ │ │ │ ├── assets │ │ │ │ │ └── .gitignore │ │ │ │ │ ├── kotlin │ │ │ │ │ └── .gitignore │ │ │ │ │ └── res │ │ │ │ │ ├── drawable-v24 │ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ │ ├── drawable │ │ │ │ │ └── ic_launcher_background.xml │ │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ │ └── ic_launcher.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.webp │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.webp │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.webp │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.webp │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.webp │ │ │ │ │ └── values │ │ │ │ │ ├── colors.xml │ │ │ │ │ ├── strings.xml.hbs │ │ │ │ │ └── styles.xml │ │ │ │ ├── build.gradle.kts │ │ │ │ ├── gradle.properties │ │ │ │ ├── gradle │ │ │ │ └── wrapper │ │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ │ └── gradle-wrapper.properties │ │ │ │ ├── gradlew │ │ │ │ ├── gradlew.bat │ │ │ │ └── settings.gradle │ │ ├── dioxus.toml │ │ ├── ios │ │ │ └── ios.plist.hbs │ │ ├── macos │ │ │ └── mac.plist.hbs │ │ └── web │ │ │ ├── dev.index.html │ │ │ ├── dev.loading.html │ │ │ └── prod.index.html │ ├── build.rs │ └── src │ │ ├── build │ │ ├── assets.rs │ │ ├── builder.rs │ │ ├── context.rs │ │ ├── mod.rs │ │ ├── patch.rs │ │ ├── request.rs │ │ └── tools.rs │ │ ├── bundle_utils.rs │ │ ├── cli │ │ ├── autoformat.rs │ │ ├── build.rs │ │ ├── build_assets.rs │ │ ├── bundle.rs │ │ ├── check.rs │ │ ├── clean.rs │ │ ├── config.rs │ │ ├── create.rs │ │ ├── init.rs │ │ ├── link.rs │ │ ├── mod.rs │ │ ├── run.rs │ │ ├── serve.rs │ │ ├── target.rs │ │ ├── translate.rs │ │ ├── update.rs │ │ └── verbosity.rs │ │ ├── config │ │ ├── app.rs │ │ ├── bundle.rs │ │ ├── dioxus_config.rs │ │ ├── mod.rs │ │ ├── serve.rs │ │ └── web.rs │ │ ├── devcfg.rs │ │ ├── dx_build_info.rs │ │ ├── error.rs │ │ ├── fastfs.rs │ │ ├── logging.rs │ │ ├── main.rs │ │ ├── platform.rs │ │ ├── rustcwrapper.rs │ │ ├── serve │ │ ├── ansi_buffer.rs │ │ ├── mod.rs │ │ ├── output.rs │ │ ├── proxy.rs │ │ ├── proxy_ws.rs │ │ ├── runner.rs │ │ ├── server.rs │ │ └── update.rs │ │ ├── settings.rs │ │ ├── tailwind.rs │ │ ├── wasm_bindgen.rs │ │ ├── wasm_opt.rs │ │ └── workspace.rs ├── config-macro │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── lib.rs ├── config-macros │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── lib.rs ├── const-serialize-macro │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── const-serialize │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ ├── const_buffers.rs │ │ ├── const_vec.rs │ │ └── lib.rs │ └── tests │ │ ├── enum.rs │ │ ├── eq.rs │ │ ├── lists.rs │ │ ├── primitive.rs │ │ ├── str.rs │ │ ├── structs.rs │ │ └── tuples.rs ├── core-macro │ ├── .vscode │ │ └── settings.json │ ├── Cargo.toml │ ├── README.md │ ├── docs │ │ ├── component.md │ │ ├── props.md │ │ └── rsx.md │ ├── src │ │ ├── component.rs │ │ ├── lib.rs │ │ ├── props │ │ │ └── mod.rs │ │ └── utils.rs │ └── tests │ │ ├── event_handler.rs │ │ ├── generics.rs │ │ ├── rsx.rs │ │ ├── rsx │ │ ├── trailing-comma-0.rs │ │ └── trailing-comma-0.stderr │ │ └── values_memoize_in_place.rs ├── core-types │ ├── Cargo.toml │ └── src │ │ ├── attributes.rs │ │ ├── bubbles.rs │ │ ├── bundled.rs │ │ ├── event.rs │ │ ├── formatter.rs │ │ ├── hr_context.rs │ │ └── lib.rs ├── core │ ├── .vscode │ │ ├── settings.json │ │ └── spellright.dict │ ├── Cargo.toml │ ├── README.md │ ├── docs │ │ ├── common_spawn_errors.md │ │ └── reactivity.md │ ├── src │ │ ├── any_props.rs │ │ ├── arena.rs │ │ ├── diff │ │ │ ├── component.rs │ │ │ ├── iterator.rs │ │ │ ├── mod.rs │ │ │ └── node.rs │ │ ├── effect.rs │ │ ├── error_boundary.rs │ │ ├── events.rs │ │ ├── fragment.rs │ │ ├── generational_box.rs │ │ ├── global_context.rs │ │ ├── hotreload_utils.rs │ │ ├── launch.rs │ │ ├── lib.rs │ │ ├── mutations.rs │ │ ├── nodes.rs │ │ ├── properties.rs │ │ ├── reactive_context.rs │ │ ├── render_error.rs │ │ ├── root_wrapper.rs │ │ ├── runtime.rs │ │ ├── scheduler.rs │ │ ├── scope_arena.rs │ │ ├── scope_context.rs │ │ ├── scopes.rs │ │ ├── suspense │ │ │ ├── component.rs │ │ │ └── mod.rs │ │ ├── tasks.rs │ │ └── virtual_dom.rs │ └── tests │ │ ├── .rustfmt.toml │ │ ├── README.md │ │ ├── attr_cleanup.rs │ │ ├── attributes_pass.rs │ │ ├── boolattrs.rs │ │ ├── bubble_error.rs │ │ ├── children_drop_futures.rs │ │ ├── conditional_formatted_attributes.rs │ │ ├── context_api.rs │ │ ├── create_dom.rs │ │ ├── create_fragments.rs │ │ ├── create_lists.rs │ │ ├── create_passthru.rs │ │ ├── cycle.rs │ │ ├── diff_component.rs │ │ ├── diff_dynamic_node.rs │ │ ├── diff_element.rs │ │ ├── diff_keyed_list.rs │ │ ├── diff_unkeyed_list.rs │ │ ├── error_boundary.rs │ │ ├── event_propagation.rs │ │ ├── fuzzing.rs │ │ ├── hotreloading.rs │ │ ├── kitchen_sink.rs │ │ ├── lifecycle.rs │ │ ├── many_roots.rs │ │ ├── memory_leak.rs │ │ ├── miri_full_app.rs │ │ ├── miri_simple.rs │ │ ├── miri_stress.rs │ │ ├── safety.rs │ │ ├── suspense.rs │ │ ├── task.rs │ │ └── tracing.rs ├── depinfo │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── dx.d │ │ └── lib.rs ├── desktop │ ├── .vscode │ │ └── settings.json │ ├── Cargo.toml │ ├── README.md │ ├── architecure │ │ └── Desktop Event Architecture.png │ ├── build.rs │ ├── headless_tests │ │ ├── eval.rs │ │ ├── events.rs │ │ ├── rendering.rs │ │ └── utils.rs │ ├── src │ │ ├── android_sync_lock.rs │ │ ├── app.rs │ │ ├── assets.rs │ │ ├── assets │ │ │ ├── default_icon.bin │ │ │ ├── default_icon.png │ │ │ ├── dev.index.html │ │ │ └── prod.index.html │ │ ├── config.rs │ │ ├── desktop_context.rs │ │ ├── document.rs │ │ ├── edits.rs │ │ ├── element.rs │ │ ├── event_handlers.rs │ │ ├── events.rs │ │ ├── file_upload.rs │ │ ├── hooks.rs │ │ ├── ipc.rs │ │ ├── js │ │ │ ├── hash.txt │ │ │ └── native_eval.js │ │ ├── launch.rs │ │ ├── lib.rs │ │ ├── menubar.rs │ │ ├── mobile_shortcut.rs │ │ ├── protocol.rs │ │ ├── query.rs │ │ ├── readme.md │ │ ├── shortcut.rs │ │ ├── trayicon.rs │ │ ├── ts │ │ │ └── native_eval.ts │ │ ├── waker.rs │ │ └── webview.rs │ └── tsconfig.json ├── devtools-types │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── devtools │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── dioxus-lib │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── lib.rs ├── dioxus │ ├── Cargo.toml │ ├── README.md │ ├── benches │ │ └── jsframework.rs │ └── src │ │ ├── launch.rs │ │ └── lib.rs ├── document │ ├── Cargo.toml │ ├── assets │ │ ├── script.js │ │ └── style.css │ ├── build.rs │ ├── docs │ │ ├── eval.md │ │ └── head.md │ ├── src │ │ ├── document.rs │ │ ├── elements │ │ │ ├── link.rs │ │ │ ├── meta.rs │ │ │ ├── mod.rs │ │ │ ├── script.rs │ │ │ ├── style.rs │ │ │ ├── stylesheet.rs │ │ │ └── title.rs │ │ ├── error.rs │ │ ├── eval.rs │ │ ├── js │ │ │ ├── hash.txt │ │ │ └── head.js │ │ ├── lib.rs │ │ └── ts │ │ │ ├── .gitignore │ │ │ ├── eval.ts │ │ │ └── head.ts │ └── tsconfig.json ├── dx-wire-format │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── extension │ ├── .eslintrc.js │ ├── .gitignore │ ├── .vscode │ │ ├── launch.json │ │ └── tasks.json │ ├── Cargo.toml │ ├── DEV.md │ ├── LICENSE.txt │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── pkg │ │ └── package.json │ ├── src │ │ ├── lib.rs │ │ └── main.ts │ ├── static │ │ └── icon.png │ ├── tsconfig.json │ └── webpack.config.js ├── fullstack-hooks │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── hooks │ │ ├── mod.rs │ │ ├── server_cached.rs │ │ └── server_future.rs │ │ ├── lib.rs │ │ └── streaming.rs ├── fullstack-protocol │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── lib.rs ├── fullstack │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ ├── docs │ │ └── request_origin.md │ └── src │ │ ├── lib.rs │ │ └── web.rs ├── generational-box │ ├── Cargo.toml │ ├── README.md │ ├── benches │ │ └── lock.rs │ ├── src │ │ ├── entry.rs │ │ ├── error.rs │ │ ├── lib.rs │ │ ├── references.rs │ │ ├── sync.rs │ │ └── unsync.rs │ └── tests │ │ ├── basic.rs │ │ ├── errors.rs │ │ ├── reference_counting.rs │ │ ├── reused.rs │ │ └── sync.rs ├── history │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── memory.rs ├── hooks │ ├── Cargo.toml │ ├── README.md │ ├── docs │ │ ├── derived_state.md │ │ ├── moving_state_around.md │ │ ├── rules_of_hooks.md │ │ ├── side_effects.md │ │ └── use_resource.md │ ├── src │ │ ├── lib.rs │ │ ├── use_after_suspense_resolved.rs │ │ ├── use_callback.rs │ │ ├── use_collection.rs │ │ ├── use_context.rs │ │ ├── use_coroutine.rs │ │ ├── use_effect.rs │ │ ├── use_future.rs │ │ ├── use_hook_did_run.rs │ │ ├── use_memo.rs │ │ ├── use_on_destroy.rs │ │ ├── use_reactive.rs │ │ ├── use_resource.rs │ │ ├── use_root_context.rs │ │ ├── use_set_compare.rs │ │ ├── use_signal.rs │ │ └── use_sorted.rs │ └── tests │ │ ├── effect.rs │ │ └── memo.rs ├── html-internal-macro │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ ├── 01-simple.rs │ │ └── progress.rs ├── html │ ├── Cargo.toml │ ├── README.md │ ├── docs │ │ ├── common_event_handler_errors.md │ │ └── event_handlers.md │ ├── src │ │ ├── attribute_groups.rs │ │ ├── elements.rs │ │ ├── events │ │ │ ├── animation.rs │ │ │ ├── clipboard.rs │ │ │ ├── composition.rs │ │ │ ├── drag.rs │ │ │ ├── focus.rs │ │ │ ├── form.rs │ │ │ ├── image.rs │ │ │ ├── keyboard.rs │ │ │ ├── media.rs │ │ │ ├── mod.rs │ │ │ ├── mounted.rs │ │ │ ├── mouse.rs │ │ │ ├── pointer.rs │ │ │ ├── resize.rs │ │ │ ├── scroll.rs │ │ │ ├── selection.rs │ │ │ ├── toggle.rs │ │ │ ├── touch.rs │ │ │ ├── transition.rs │ │ │ ├── visible.rs │ │ │ └── wheel.rs │ │ ├── file_data.rs │ │ ├── geometry.rs │ │ ├── input_data.rs │ │ ├── lib.rs │ │ ├── point_interaction.rs │ │ ├── render_template.rs │ │ └── transit.rs │ └── tsconfig.json ├── interpreter │ ├── .gitignore │ ├── Cargo.toml │ ├── NOTES.md │ ├── README.md │ ├── build.rs │ ├── src │ │ ├── js │ │ │ ├── common.js │ │ │ ├── core.js │ │ │ ├── hash.txt │ │ │ ├── hydrate.js │ │ │ ├── initialize_streaming.js │ │ │ ├── native.js │ │ │ └── patch_console.js │ │ ├── lib.rs │ │ ├── ts │ │ │ ├── .gitignore │ │ │ ├── common.ts │ │ │ ├── core.ts │ │ │ ├── form.ts │ │ │ ├── hydrate.ts │ │ │ ├── hydrate_types.ts │ │ │ ├── initialize_streaming.ts │ │ │ ├── native.ts │ │ │ ├── patch_console.ts │ │ │ ├── serialize.ts │ │ │ └── set_attribute.ts │ │ ├── unified_bindings.rs │ │ └── write_native_mutations.rs │ ├── tests │ │ ├── e2e.rs │ │ └── serialize.rs │ └── tsconfig.json ├── isrg │ ├── Cargo.toml │ └── src │ │ ├── config.rs │ │ ├── freshness.rs │ │ ├── fs_cache.rs │ │ ├── lib.rs │ │ └── memory_cache.rs ├── lazy-js-bundle │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── liveview │ ├── Cargo.toml │ ├── README.md │ ├── examples │ │ ├── axum.rs │ │ └── axum_stress.rs │ └── src │ │ ├── adapters │ │ ├── axum_adapter.rs │ │ └── mod.rs │ │ ├── config.rs │ │ ├── document.rs │ │ ├── element.rs │ │ ├── events.rs │ │ ├── history.rs │ │ ├── index.html │ │ ├── launch.rs │ │ ├── lib.rs │ │ ├── main.js │ │ ├── pool.rs │ │ └── query.rs ├── logger │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── lib.rs ├── manganis │ ├── manganis-core │ │ ├── Cargo.toml │ │ ├── assets │ │ │ ├── image.png │ │ │ ├── script.js │ │ │ └── style.css │ │ └── src │ │ │ ├── asset.rs │ │ │ ├── css.rs │ │ │ ├── folder.rs │ │ │ ├── images.rs │ │ │ ├── js.rs │ │ │ ├── lib.rs │ │ │ └── options.rs │ ├── manganis-macro │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── assets │ │ │ ├── asset.txt │ │ │ ├── image.png │ │ │ ├── manganis_macro.dat │ │ │ ├── script.js │ │ │ └── style.css │ │ └── src │ │ │ ├── asset.rs │ │ │ ├── css_module.rs │ │ │ ├── lib.rs │ │ │ └── linker.rs │ └── manganis │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── assets │ │ ├── image.png │ │ ├── script.js │ │ └── style.css │ │ └── src │ │ ├── lib.rs │ │ └── macro_helpers.rs ├── mobile │ ├── .cargo │ │ └── config.toml │ ├── .vscode │ │ └── settings.json │ ├── Cargo.toml │ ├── Makefile.toml │ ├── README.md │ └── src │ │ └── lib.rs ├── native │ ├── Cargo.toml │ └── src │ │ ├── assets.rs │ │ ├── contexts.rs │ │ ├── dioxus_application.rs │ │ ├── dioxus_document.rs │ │ ├── events.rs │ │ ├── lib.rs │ │ └── mutation_writer.rs ├── playwright-tests │ ├── .gitignore │ ├── barebones-template │ │ ├── .gitignore │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── Dioxus.toml │ │ ├── README.md │ │ ├── assets │ │ │ ├── favicon.ico │ │ │ ├── header.svg │ │ │ └── main.css │ │ └── src │ │ │ └── main.rs │ ├── cli-optimization.spec.js │ ├── cli-optimization │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── build.rs │ │ ├── images │ │ │ └── toasts.png │ │ └── src │ │ │ └── main.rs │ ├── default-features-disabled.spec.js │ ├── default-features-disabled │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ ├── fullstack-mounted.spec.js │ ├── fullstack-mounted │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ ├── fullstack-routing.spec.js │ ├── fullstack-routing │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ ├── fullstack.spec.js │ ├── fullstack │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ ├── liveview.spec.js │ ├── liveview │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ ├── nested-suspense-no-js.spec.js │ ├── nested-suspense-ssg.spec.js │ ├── nested-suspense.spec.js │ ├── nested-suspense │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── assets │ │ │ └── style.css │ │ └── src │ │ │ ├── lib.rs │ │ │ ├── main.rs │ │ │ └── ssg.rs │ ├── package-lock.json │ ├── package.json │ ├── playwright.config.js │ ├── suspense-carousel.spec.js │ ├── suspense-carousel │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ ├── wasm-split-harness │ │ ├── .cargo │ │ │ └── config.toml │ │ ├── Cargo.toml │ │ ├── data │ │ │ ├── .gitignore │ │ │ └── index.html │ │ ├── docsite.sh │ │ ├── run.sh │ │ └── src │ │ │ ├── main.rs │ │ │ └── stars.js │ ├── wasm-split.spec.js │ ├── web-routing.spec.js │ ├── web-routing │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ ├── web.spec.js │ └── web │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ └── main.rs ├── router-macro │ ├── Cargo.toml │ └── src │ │ ├── hash.rs │ │ ├── layout.rs │ │ ├── lib.rs │ │ ├── nest.rs │ │ ├── query.rs │ │ ├── redirect.rs │ │ ├── route.rs │ │ ├── route_tree.rs │ │ └── segment.rs ├── router │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ ├── components │ │ │ ├── child_router.rs │ │ │ ├── default_errors.rs │ │ │ ├── history_buttons.rs │ │ │ ├── history_provider.rs │ │ │ ├── link.rs │ │ │ ├── outlet.rs │ │ │ └── router.rs │ │ ├── contexts │ │ │ ├── navigator.rs │ │ │ ├── outlet.rs │ │ │ └── router.rs │ │ ├── hooks │ │ │ ├── use_navigator.rs │ │ │ ├── use_route.rs │ │ │ └── use_router.rs │ │ ├── lib.rs │ │ ├── navigation.rs │ │ ├── routable.rs │ │ ├── router_cfg.rs │ │ └── utils │ │ │ └── use_router_internal.rs │ └── tests │ │ ├── parent.rs │ │ ├── parsing.rs │ │ ├── site_map.rs │ │ └── via_ssr │ │ ├── link.rs │ │ ├── main.rs │ │ ├── navigation.rs │ │ ├── outlet.rs │ │ ├── redirect.rs │ │ └── without_index.rs ├── rsx-hotreload │ ├── Cargo.toml │ ├── src │ │ ├── collect.rs │ │ ├── diff.rs │ │ ├── extensions.rs │ │ ├── last_build_state.rs │ │ └── lib.rs │ └── tests │ │ ├── hotreload_pattern.rs │ │ ├── hotreloads.rs │ │ └── valid │ │ ├── combo.new.rsx │ │ ├── combo.old.rsx │ │ ├── expr.new.rsx │ │ ├── expr.old.rsx │ │ ├── for_.new.rsx │ │ ├── for_.old.rsx │ │ ├── if_.new.rsx │ │ ├── if_.old.rsx │ │ ├── let_.new.rsx │ │ ├── let_.old.rsx │ │ ├── nested.new.rsx │ │ └── nested.old.rsx ├── rsx-rosetta │ ├── Cargo.toml │ ├── README.md │ ├── examples │ │ └── html.rs │ ├── src │ │ └── lib.rs │ └── tests │ │ ├── escape.rs │ │ ├── h-tags.rs │ │ ├── raw.rs │ │ ├── simple.rs │ │ ├── svgs.rs │ │ └── web-component.rs ├── rsx │ ├── .vscode │ │ └── settings.json │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ ├── assign_dyn_ids.rs │ │ ├── attribute.rs │ │ ├── component.rs │ │ ├── diagnostics.rs │ │ ├── element.rs │ │ ├── expr_node.rs │ │ ├── forloop.rs │ │ ├── ifchain.rs │ │ ├── ifmt.rs │ │ ├── lib.rs │ │ ├── literal.rs │ │ ├── location.rs │ │ ├── node.rs │ │ ├── partial_closure.rs │ │ ├── raw_expr.rs │ │ ├── rsx_block.rs │ │ ├── rsx_call.rs │ │ ├── template_body.rs │ │ ├── text_node.rs │ │ └── util.rs │ └── tests │ │ └── parsing.rs ├── server-macro │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── server │ ├── Cargo.toml │ ├── docs │ │ └── request_origin.md │ └── src │ │ ├── config.rs │ │ ├── context.rs │ │ ├── document.rs │ │ ├── launch.rs │ │ ├── lib.rs │ │ ├── render.rs │ │ ├── server.rs │ │ └── streaming.rs ├── signals │ ├── Cargo.toml │ ├── README.md │ ├── docs │ │ ├── hoist │ │ │ ├── error.rs │ │ │ └── fixed_list.rs │ │ ├── memo.md │ │ └── signals.md │ ├── examples │ │ ├── context.rs │ │ ├── dependencies.rs │ │ ├── map_signal.rs │ │ ├── read_only_degrade.rs │ │ ├── selector.rs │ │ ├── send.rs │ │ └── split_subscriptions.rs │ ├── src │ │ ├── copy_value.rs │ │ ├── global │ │ │ ├── memo.rs │ │ │ ├── mod.rs │ │ │ └── signal.rs │ │ ├── impls.rs │ │ ├── lib.rs │ │ ├── map.rs │ │ ├── memo.rs │ │ ├── props.rs │ │ ├── read.rs │ │ ├── read_only_signal.rs │ │ ├── set_compare.rs │ │ ├── signal.rs │ │ ├── warnings.rs │ │ └── write.rs │ └── tests │ │ ├── create.rs │ │ ├── memo.rs │ │ └── subscribe.rs ├── ssr │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ ├── cache.rs │ │ ├── config.rs │ │ ├── lib.rs │ │ ├── renderer.rs │ │ └── template.rs │ └── tests │ │ ├── bool_attr.rs │ │ ├── escape.rs │ │ ├── forward_spreads.rs │ │ ├── hydration.rs │ │ ├── inner_html.rs │ │ ├── simple.rs │ │ ├── spread.rs │ │ └── styles.rs ├── subsecond │ ├── README.md │ ├── subsecond-tests │ │ ├── cross-tls-crate-dylib │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ │ └── lib.rs │ │ ├── cross-tls-crate │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ │ └── lib.rs │ │ └── cross-tls-test │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ └── src │ │ │ └── main.rs │ ├── subsecond-types │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ └── subsecond │ │ ├── Cargo.toml │ │ └── src │ │ └── lib.rs ├── wasm-split │ ├── README.md │ ├── wasm-split-cli │ │ ├── Cargo.toml │ │ ├── data │ │ │ └── .gitignore │ │ └── src │ │ │ ├── __wasm_split.js │ │ │ ├── lib.rs │ │ │ └── main.rs │ ├── wasm-split-macro │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── wasm-split │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ └── wasm-used │ │ ├── Cargo.toml │ │ └── src │ │ └── lib.rs └── web │ ├── .gitignore │ ├── .vscode │ └── settings.json │ ├── Cargo.toml │ ├── README.md │ ├── build.rs │ └── src │ ├── cfg.rs │ ├── devtools.rs │ ├── document.rs │ ├── dom.rs │ ├── events │ ├── animation.rs │ ├── clipboard.rs │ ├── composition.rs │ ├── drag.rs │ ├── file.rs │ ├── focus.rs │ ├── form.rs │ ├── keyboard.rs │ ├── load.rs │ ├── media.rs │ ├── mod.rs │ ├── mounted.rs │ ├── mouse.rs │ ├── pointer.rs │ ├── resize.rs │ ├── scroll.rs │ ├── selection.rs │ ├── toggle.rs │ ├── touch.rs │ ├── transition.rs │ ├── visible.rs │ └── wheel.rs │ ├── file_engine.rs │ ├── history │ ├── mod.rs │ └── scroll.rs │ ├── hydration │ ├── hydrate.rs │ └── mod.rs │ ├── js │ ├── eval.js │ └── hash.txt │ ├── launch.rs │ ├── lib.rs │ ├── mutations.rs │ └── ts │ └── eval.ts └── translations ├── fa-ir └── README.md ├── ja-jp └── README.md ├── ko-kr └── README.md ├── pt-br └── README.md ├── tr-tr └── README.md └── zh-cn └── README.md /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG VARIANT="nightly-bookworm-slim" 2 | FROM rustlang/rust:${VARIANT} 3 | 4 | ENV DEBIAN_FRONTEND=noninteractive 5 | 6 | # Install required system libraries and NPM 7 | # Reference: https://dioxuslabs.com/learn/0.6/contributing/#before-you-contribute 8 | RUN apt-get update -qq \ 9 | && apt-get install -y -qq \ 10 | libgdk3.0-cil \ 11 | libatk1.0-dev \ 12 | libcairo2-dev \ 13 | libpango1.0-dev \ 14 | libgdk-pixbuf2.0-dev \ 15 | libsoup-3.0-dev \ 16 | libjavascriptcoregtk-4.1-dev \ 17 | libwebkit2gtk-4.1-dev \ 18 | npm \ 19 | && rm -rf /var/lib/apt/lists/* 20 | 21 | # Set a shared folder for pre-installed browsers 22 | ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright 23 | 24 | # Temporarily install Playwright globally to install the browsers and their dependencies 25 | RUN npm install -g @playwright/test && \ 26 | npx playwright install --with-deps && \ 27 | npm uninstall -g @playwright/test 28 | -------------------------------------------------------------------------------- /.docker/Dockerfile_base_test_image: -------------------------------------------------------------------------------- 1 | FROM rust:1.58-buster 2 | 3 | RUN apt update 4 | RUN apt install -y \ 5 | libglib2.0-dev \ 6 | libgtk-3-dev \ 7 | libsoup2.4-dev \ 8 | libappindicator3-dev \ 9 | libwebkit2gtk-4.0-dev \ 10 | firefox-esr \ 11 | # for Tarpaulin code coverage 12 | liblzma-dev binutils-dev libcurl4-openssl-dev libdw-dev libelf-dev 13 | 14 | CMD ["exit"] 15 | -------------------------------------------------------------------------------- /.docker/Dockerfile_code_coverage: -------------------------------------------------------------------------------- 1 | FROM dioxus-test-image 2 | 3 | WORKDIR /run_test 4 | RUN cargo install cargo-tarpaulin 5 | RUN cargo cache -a 6 | 7 | ENTRYPOINT [ "bash" ] 8 | -------------------------------------------------------------------------------- /.docker/Dockerfile_pre_test: -------------------------------------------------------------------------------- 1 | FROM dioxus-base-test-image 2 | 3 | RUN cargo install cargo-binstall 4 | RUN cargo install cargo-make 5 | RUN cargo install wasm-pack 6 | RUN cargo install cargo-cache && cargo cache -a 7 | 8 | CMD ["exit"] 9 | -------------------------------------------------------------------------------- /.docker/Dockerfile_test: -------------------------------------------------------------------------------- 1 | FROM dioxus-pre-test 2 | 3 | RUN mkdir run_test 4 | COPY tmp /run_test 5 | WORKDIR /run_test 6 | RUN cargo test --workspace --tests 7 | RUN cargo cache -a 8 | 9 | CMD ["exit"] 10 | -------------------------------------------------------------------------------- /.docker/README.md: -------------------------------------------------------------------------------- 1 | # Why this? 2 | 3 | This part is used to test whole package before pushing it 4 | 5 | # How to use it? 6 | 7 | Just run in the folder: 8 | `bash run_local_tests.sh`. If nothing fails, then you can push your code to the repo. 9 | or run: 10 | `bash run_local_tests.sh --with-full-docker-cleanup` 11 | for cleaning up images as well 12 | 13 | # How is it composed of? 14 | 15 | 1. `Dockerfile_pre_test` will build the base image for the tests to be run into 16 | 2. `Dockerfile_test` will run the actual tests based on 1. 17 | 3. `run_local_tests.sh` to wrap this up 18 | 19 | # Warning 20 | 21 | The task requires some amount of CPU work and disk space (5GB per tests). Some clean up is included in the script. 22 | 23 | # Requirements 24 | 25 | * [docker](https://docs.docker.com/engine/install/) 26 | * bash 27 | * rsync -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # borrowed from tauri - only allow core maintainers to approve PRs 2 | 3 | * @DioxusLabs/core 4 | 5 | .github @DioxusLabs/core 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: DioxusLabs # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | open_collective: dioxus-labs # Replace with a single Open Collective username 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_requst.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: If you have any interesting advice, you can tell us. 4 | labels: enhancement 5 | --- 6 | 7 | ## Feature Request 8 | 9 | 13 | 14 | ## Implement Suggestion 15 | 16 | 20 | -------------------------------------------------------------------------------- /.github/actions/free-disk-space/action.yml: -------------------------------------------------------------------------------- 1 | name: Free Disk Space 2 | description: Free up disk space on the runner 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Free Disk Space (Ubuntu) 7 | if: runner.os == 'Linux' 8 | shell: bash 9 | run: | 10 | echo "Freeing up disk space..." 11 | sudo rm -rf /opt/ghc 12 | sudo rm -rf /usr/share/dotnet 13 | sudo rm -rf /usr/local/lib/android 14 | sudo rm -rf /usr/share/swift 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | # Maintain dependencies for GitHub Actions 5 | - package-ecosystem: "github-actions" 6 | directory: "/" 7 | schedule: 8 | interval: "weekly" 9 | -------------------------------------------------------------------------------- /.github/workflows/setup-dev-drive.ps1: -------------------------------------------------------------------------------- 1 | # This creates a 20GB dev drive, and exports all required environment 2 | # variables so that rustup, uv and others all use the dev drive as much 3 | # as possible. 4 | $Volume = New-VHD -Path C:/uv_dev_drive.vhdx -SizeBytes 20GB | 5 | Mount-VHD -Passthru | 6 | Initialize-Disk -Passthru | 7 | New-Partition -AssignDriveLetter -UseMaximumSize | 8 | Format-Volume -FileSystem ReFS -Confirm:$false -Force 9 | 10 | Write-Output $Volume 11 | 12 | $Drive = "$($Volume.DriveLetter):" 13 | $Tmp = "$($Drive)/uv-tmp" 14 | 15 | # Create the directory ahead of time in an attempt to avoid race-conditions 16 | New-Item $Tmp -ItemType Directory 17 | 18 | Write-Output ` 19 | "DEV_DRIVE=$($Drive)" ` 20 | "TMP=$($Tmp)" ` 21 | "TEMP=$($Tmp)" ` 22 | "RUSTUP_HOME=$($Drive)/.rustup" ` 23 | "CARGO_HOME=$($Drive)/.cargo" ` 24 | "UV_WORKSPACE=$($Drive)/uv" ` 25 | "PATH=$($Drive)/.cargo/bin;$env:PATH" ` 26 | >> $env:GITHUB_ENV -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .dioxus 2 | /target 3 | /packages/playwright-tests/web/dist 4 | /packages/playwright-tests/fullstack/dist 5 | /packages/playwright-tests/test-results 6 | /dist 7 | .DS_Store 8 | /examples/assets/test_video.mp4 9 | static 10 | 11 | # new recommendation to keep the lockfile in for CI and reproducible builds 12 | # Cargo.lock 13 | 14 | .vscode/* 15 | !.vscode/settings.json 16 | !.vscode/tasks.json 17 | !.vscode/launch.json 18 | !.vscode/extensions.json 19 | tarpaulin-report.html 20 | 21 | # Jetbrain 22 | .idea/ 23 | node_modules/ 24 | /test-results/ 25 | /packages/playwright-report/ 26 | /packages/playwright/.cache/ 27 | 28 | 29 | # ignore the output of tmps 30 | tmp/ 31 | bundle/ 32 | 33 | # in debugging we frequently dump wasm to wat with `wasm-tools print` 34 | *.wat 35 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Jonathan Kelley 2 | -------------------------------------------------------------------------------- /.vscode/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/.vscode/.gitignore -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "[toml]": { 4 | "editor.formatOnSave": false 5 | }, 6 | "[handlebars]": { 7 | "editor.formatOnSave": false 8 | }, 9 | "[javascript]": { 10 | "editor.formatOnSave": false 11 | }, 12 | "dioxus.formatOnSave": "disabled", 13 | // "rust-analyzer.check.workspace": true, 14 | // "rust-analyzer.check.workspace": false, 15 | // "rust-analyzer.check.features": "all", 16 | // "rust-analyzer.cargo.buildScripts.rebuildOnSave": false, 17 | // "rust-analyzer.check.workspace": false, 18 | // "rust-analyzer.check.allTargets": true, 19 | "rust-analyzer.cargo.features": "all", 20 | "rust-analyzer.check.features": "all", 21 | "rust-analyzer.cargo.extraArgs": [ 22 | "--tests" 23 | ], 24 | } 25 | -------------------------------------------------------------------------------- /_typos.toml: -------------------------------------------------------------------------------- 1 | [default.extend-words] 2 | # https://ratatui.rs/ 3 | ratatui = "ratatui" 4 | # lits is short for literals 5 | lits = "lits" 6 | # https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seeked_event 7 | seeked = "seeked" 8 | # https://developer.apple.com/forums/thread/108953 9 | # udid = unique device identifier 10 | udid = "udid" 11 | # Part of Blitz's API 12 | unparented = "unparented" 13 | 14 | [files] 15 | extend-exclude = ["translations/*", "CHANGELOG.md", "*.js"] 16 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | fail_ci_if_error: false 3 | -------------------------------------------------------------------------------- /example-projects/ecommerce-site/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /example-projects/ecommerce-site/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ecommerce-site" 3 | version = "0.1.1" 4 | edition = "2018" 5 | publish = false 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | dioxus = { workspace = true, features = ["fullstack", "router"] } 10 | reqwest = { workspace = true, features = ["json"] } 11 | serde = { workspace = true } 12 | 13 | [target.'cfg(target_family = "wasm")'.dependencies] 14 | chrono = { workspace = true, features = ["serde", "wasmbind"] } 15 | 16 | [target.'cfg(not(target_family = "wasm"))'.dependencies] 17 | chrono = { workspace = true, features = ["serde"] } 18 | 19 | [features] 20 | web = ["dioxus/web"] 21 | server = ["dioxus/server"] 22 | -------------------------------------------------------------------------------- /example-projects/ecommerce-site/README.md: -------------------------------------------------------------------------------- 1 | # Dioxus Example: An e-commerce site using the FakeStoreAPI 2 | 3 | This example app is a fullstack web application leveraging the [FakeStoreAPI](https://fakestoreapi.com) and [Tailwind CSS](https://tailwindcss.com/). 4 | 5 | ![Demo Image](demo.png) 6 | 7 | # Development 8 | 9 | 1. Run the following commands to serve the application: 10 | 11 | ```bash 12 | dx serve 13 | ``` 14 | 15 | Note that in Dioxus 0.7, the Tailwind watcher is initialized automatically if a `tailwind.css` file is find in your app's root. 16 | 17 | # Status 18 | 19 | This is a work in progress. The following features are currently implemented: 20 | 21 | - [x] A homepage with a list of products dynamically fetched from the FakeStoreAPI (rendered using SSR) 22 | - [x] A product detail page with details about a product (rendered using LiveView) 23 | - [ ] A cart page 24 | - [ ] A checkout page 25 | - [ ] A login page 26 | -------------------------------------------------------------------------------- /example-projects/ecommerce-site/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/example-projects/ecommerce-site/demo.png -------------------------------------------------------------------------------- /example-projects/ecommerce-site/public/loading.css: -------------------------------------------------------------------------------- 1 | @keyframes spin { 2 | 0% { 3 | transform: rotate(0deg); 4 | } 5 | 6 | 100% { 7 | transform: rotate(360deg); 8 | } 9 | } 10 | .spinner { 11 | width: 10px; 12 | height: 10px; 13 | border: 4px solid #f3f3f3; 14 | border-top: 4px solid #3498db; 15 | border-radius: 50%; 16 | animation: spin 2s linear infinite; 17 | } -------------------------------------------------------------------------------- /example-projects/ecommerce-site/src/components/cart.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /example-projects/ecommerce-site/src/components/error.rs: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | #[component] 4 | pub fn error_page() -> Element { 5 | rsx! { 6 | section { class: "py-20", 7 | div { class: "container mx-auto px-4", 8 | div { class: "flex flex-wrap -mx-4 mb-24 text-center", 9 | "An internal error has occurred" 10 | } 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example-projects/ecommerce-site/src/components/home.rs: -------------------------------------------------------------------------------- 1 | // The homepage is statically rendered, so we don't need to a persistent websocket connection. 2 | 3 | use crate::{ 4 | api::{fetch_products, Sort}, 5 | components::nav, 6 | components::product_item::product_item, 7 | }; 8 | use dioxus::prelude::*; 9 | 10 | pub(crate) fn Home() -> Element { 11 | let products = use_server_future(|| fetch_products(10, Sort::Ascending))?; 12 | let products = products().unwrap()?; 13 | 14 | rsx! { 15 | nav::nav {} 16 | section { class: "p-10", 17 | for product in products { 18 | product_item { 19 | product 20 | } 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example-projects/ecommerce-site/src/components/loading.rs: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | #[component] 4 | pub(crate) fn ChildrenOrLoading(children: Element) -> Element { 5 | rsx! { 6 | document::Link { 7 | rel: "stylesheet", 8 | href: asset!("/public/loading.css") 9 | } 10 | SuspenseBoundary { 11 | fallback: |context: SuspenseContext| { 12 | rsx! { 13 | if let Some(placeholder) = context.suspense_placeholder() { 14 | {placeholder} 15 | } else { 16 | LoadingIndicator {} 17 | } 18 | } 19 | }, 20 | {children} 21 | } 22 | } 23 | } 24 | 25 | #[component] 26 | fn LoadingIndicator() -> Element { 27 | rsx! { 28 | div { 29 | class: "spinner", 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example-projects/ecommerce-site/tailwind.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | @source "./src/**/*.{rs,html,css}"; 3 | -------------------------------------------------------------------------------- /example-projects/file-explorer/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /dist/ 5 | /static/ 6 | /.dioxus/ 7 | 8 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 9 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 10 | Cargo.lock 11 | 12 | # These are backup files generated by rustfmt 13 | **/*.rs.bk 14 | -------------------------------------------------------------------------------- /example-projects/file-explorer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "file-explorer" 3 | edition = "2021" 4 | version = "0.1.0" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["desktop"] } 11 | open = { workspace = true } 12 | -------------------------------------------------------------------------------- /example-projects/file-explorer/Dioxus.toml: -------------------------------------------------------------------------------- 1 | [application] 2 | 3 | # App (Project) Name 4 | name = "file-explorer" 5 | 6 | # Dioxus App Default Platform 7 | # desktop, web 8 | default_platform = "desktop" 9 | 10 | # `build` & `serve` dist path 11 | out_dir = "dist" 12 | 13 | # assets file folder 14 | asset_dir = "assets" 15 | 16 | [web.app] 17 | 18 | # HTML title tag content 19 | title = "file-explorer" 20 | 21 | [web.watcher] 22 | 23 | # when watcher trigger, regenerate the `index.html` 24 | reload_html = true 25 | 26 | # which files or dirs will be watcher monitoring 27 | watch_path = ["src", "assets"] 28 | 29 | # include `assets` in web platform 30 | [web.resource] 31 | 32 | # CSS style file 33 | 34 | style = [] 35 | 36 | # Javascript code file 37 | script = [] 38 | 39 | [web.resource.dev] 40 | 41 | # Javascript code file 42 | # serve: [dev-server] only 43 | script = [] 44 | -------------------------------------------------------------------------------- /example-projects/file-explorer/README.md: -------------------------------------------------------------------------------- 1 | # File-explorer with Rust and Dioxus 2 | 3 | This example shows how a Dioxus App can directly leverage system calls and libraries to bridge native functionality with the WebView renderer. 4 | 5 | ![example](./assets/image.png) 6 | 7 | 8 | ## To run this example: 9 | 10 | ``` 11 | dx serve 12 | ``` 13 | 14 | -------------------------------------------------------------------------------- /example-projects/file-explorer/assets/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/example-projects/file-explorer/assets/image.png -------------------------------------------------------------------------------- /example-projects/fullstack-hackernews/.gitignore: -------------------------------------------------------------------------------- 1 | /static 2 | /dist -------------------------------------------------------------------------------- /example-projects/fullstack-hackernews/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fullstack-hackernews-example" 3 | version = "0.1.0" 4 | authors = ["Evan Almloff "] 5 | edition = "2021" 6 | publish = false 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | dioxus = { workspace = true, features = ["fullstack", "router"] } 12 | chrono = { workspace = true, features = ["serde"] } 13 | reqwest = { workspace= true, features = ["json"] } 14 | serde = { workspace = true, features = ["derive"] } 15 | 16 | [features] 17 | default = [] 18 | server = ["dioxus/server"] 19 | web = ["dioxus/web"] 20 | -------------------------------------------------------------------------------- /example-projects/fullstack-hackernews/assets/hackernews.css: -------------------------------------------------------------------------------- 1 | @keyframes spin { 2 | 0% { 3 | transform: rotate(0deg); 4 | } 5 | 6 | 100% { 7 | transform: rotate(360deg); 8 | } 9 | } 10 | .spinner { 11 | width: 10px; 12 | height: 10px; 13 | border: 4px solid #f3f3f3; 14 | border-top: 4px solid #3498db; 15 | border-radius: 50%; 16 | animation: spin 2s linear infinite; 17 | } -------------------------------------------------------------------------------- /example-projects/wifi-scanner/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /example-projects/wifi-scanner/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wifi-scanner" 3 | version = "0.1.1" 4 | edition = "2018" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | tokio = { workspace = true, features = ["full"] } 11 | dioxus = { workspace = true, features = ["desktop"] } 12 | futures-channel = { workspace = true } 13 | futures = { workspace = true } 14 | wifiscanner = "0.5.1" 15 | -------------------------------------------------------------------------------- /example-projects/wifi-scanner/README.md: -------------------------------------------------------------------------------- 1 | # WiFi scanner app 2 | 3 | This desktop app showcases the use of background threads. 4 | 5 | ![Demo of app](./demo_small.png) 6 | -------------------------------------------------------------------------------- /example-projects/wifi-scanner/demo_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/example-projects/wifi-scanner/demo_small.png -------------------------------------------------------------------------------- /examples/assets/clock.css: -------------------------------------------------------------------------------- 1 | html body { 2 | margin: 0; 3 | padding: 0; 4 | height: 100vh; 5 | font-family: 'Courier New', Courier, monospace; 6 | } 7 | 8 | #app { 9 | display: flex; 10 | justify-content: center; 11 | align-items: center; 12 | flex-direction: column; 13 | height: 100vh; 14 | background-color: plum; 15 | font-size: 6em; 16 | color: aliceblue; 17 | } 18 | 19 | #title { 20 | font-size: 0.5em; 21 | color: black; 22 | margin-bottom: 0.5em; 23 | } 24 | -------------------------------------------------------------------------------- /examples/assets/context_api.css: -------------------------------------------------------------------------------- 1 | .main-container { 2 | font-family: system-ui, sans-serif; 3 | max-width: 600px; 4 | margin: 2rem auto; 5 | padding: 2rem; 6 | } 7 | 8 | .light-theme { 9 | background: #ffffff; 10 | color: #1a1a1a; 11 | border: 1px solid #e0e0e0; 12 | } 13 | 14 | .dark-theme { 15 | background: #1a1a1a; 16 | color: #ffffff; 17 | border: 1px solid #333; 18 | } 19 | 20 | .controls { 21 | display: flex; 22 | gap: 1rem; 23 | margin: 2rem 0; 24 | } 25 | 26 | .btn { 27 | padding: 0.5rem 1rem; 28 | border: none; 29 | border-radius: 4px; 30 | cursor: pointer; 31 | transition: opacity 0.2s; 32 | } 33 | 34 | .btn:disabled { 35 | opacity: 0.7; 36 | cursor: not-allowed; 37 | } 38 | 39 | .display { 40 | padding: 2rem; 41 | border-radius: 8px; 42 | margin-top: 2rem; 43 | } 44 | -------------------------------------------------------------------------------- /examples/assets/counter.css: -------------------------------------------------------------------------------- 1 | html body { 2 | font-family: Arial, sans-serif; 3 | margin: 20px; 4 | padding: 0; 5 | display: flex; 6 | justify-content: center; 7 | font-size: 2rem; 8 | height: 100vh; 9 | background-color: #f0f0f0; 10 | } 11 | 12 | #controls { 13 | display: flex; 14 | justify-content: center; 15 | align-items: center; 16 | margin-top: 20px; 17 | } 18 | 19 | button { 20 | padding: 5px 10px; 21 | margin: 0 5px; 22 | } 23 | 24 | input { 25 | width: 50px; 26 | } 27 | -------------------------------------------------------------------------------- /examples/assets/crm.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #f4f4f4; 3 | font-family: 'Open Sans', sans-serif; 4 | font-size: 14px; 5 | line-height: 1.42857143; 6 | color: #333; 7 | margin: 20px; 8 | padding: 20px; 9 | display: flex; 10 | flex-direction: column; 11 | align-items: center; 12 | } 13 | 14 | .red { 15 | background-color: rgb(202, 60, 60) !important; 16 | } 17 | -------------------------------------------------------------------------------- /examples/assets/custom_assets.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #f0f0f0; 3 | font-family: Arial, sans-serif; 4 | margin: 0; 5 | padding: 0; 6 | display: flex; 7 | justify-content: center; 8 | align-items: center; 9 | text-align: center; 10 | height: 100vh; 11 | width: 100vw; 12 | } 13 | -------------------------------------------------------------------------------- /examples/assets/events.css: -------------------------------------------------------------------------------- 1 | #container { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | } 6 | 7 | #receiver { 8 | background: deepskyblue; 9 | height: 30vh; 10 | width: 80vw; 11 | color: white; 12 | padding: 20px; 13 | margin: 20px; 14 | text-align: center; 15 | } 16 | 17 | #log { 18 | background: lightgray; 19 | padding: 20px; 20 | margin: 20px; 21 | overflow-y: scroll; 22 | align-items: start; 23 | text-align: left; 24 | } 25 | -------------------------------------------------------------------------------- /examples/assets/file_upload.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, sans-serif; 3 | margin: 10px; 4 | padding: 10px; 5 | background-color: #f4f4f4; 6 | justify-content: center; 7 | align-items: center; 8 | min-height: 100vh; 9 | } 10 | 11 | #drop-zone { 12 | border: 2px dashed #ccc; 13 | border-radius: 3px; 14 | padding: 20px; 15 | text-align: center; 16 | cursor: pointer; 17 | margin: 20px; 18 | background-color: rgba(225, 124, 225, 0); 19 | } 20 | -------------------------------------------------------------------------------- /examples/assets/flat_router.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, sans-serif; 3 | margin: 20px; 4 | padding: 20px; 5 | background-color: #f4f4f4; 6 | height: 100vh; 7 | } 8 | 9 | nav { 10 | display: flex; 11 | justify-content: space-around; 12 | } 13 | 14 | .nav-btn { 15 | text-decoration: none; 16 | color: black; 17 | } 18 | 19 | a { 20 | padding: 10px; 21 | border: none; 22 | border-radius: 5px; 23 | cursor: pointer; 24 | } 25 | 26 | /* button hover effect */ 27 | a:hover { 28 | background-color: #dd6a6a; 29 | } 30 | 31 | #content { 32 | border: 2px dashed #ccc; 33 | padding-top: 20px; 34 | display: flex; 35 | justify-content: center; 36 | align-items: center; 37 | height: 100%; 38 | flex-direction: column; 39 | gap: 20px; 40 | } 41 | -------------------------------------------------------------------------------- /examples/assets/links.css: -------------------------------------------------------------------------------- 1 | #external-links { 2 | display: flex; 3 | flex-direction: column; 4 | } 5 | 6 | #nav { 7 | display: flex; 8 | justify-content: space-between; 9 | align-items: center; 10 | padding: 1rem; 11 | background-color: #f4f4f4; 12 | } 13 | -------------------------------------------------------------------------------- /examples/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/examples/assets/logo.png -------------------------------------------------------------------------------- /examples/assets/overlay.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100px; 3 | margin: 0; 4 | overscroll-behavior-y: none; 5 | overscroll-behavior-x: none; 6 | overflow: hidden; 7 | } 8 | #main, #bodywrap { 9 | height: 100%; 10 | margin: 0; 11 | overscroll-behavior-x: none; 12 | overscroll-behavior-y: none; 13 | } -------------------------------------------------------------------------------- /examples/assets/radio.css: -------------------------------------------------------------------------------- 1 | body { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | justify-content: center; 6 | text-align: center; 7 | } 8 | 9 | button { 10 | margin: 10px; 11 | padding: 10px; 12 | border: none; 13 | border-radius: 5px; 14 | background-color: #f0f0f0; 15 | cursor: pointer; 16 | } 17 | 18 | #pause { 19 | background-color: #ff0000; 20 | } 21 | 22 | #play { 23 | background-color: #00ff00; 24 | } 25 | 26 | 27 | .bounce { 28 | animation: boomBox 0.5s infinite; 29 | } 30 | 31 | @keyframes boomBox { 32 | 0% { 33 | transform: scale(1.0); 34 | } 35 | 36 | 50% { 37 | transform: scale(2); 38 | } 39 | 40 | 100% { 41 | transform: scale(1.0); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/assets/read_size.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | width: 100%; 4 | margin: 0; 5 | } 6 | #main { 7 | height: 100%; 8 | width: 100%; 9 | } -------------------------------------------------------------------------------- /examples/assets/roulette.css: -------------------------------------------------------------------------------- 1 | #main { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: center; 5 | align-items: center; 6 | } 7 | 8 | #roulette-grid { 9 | margin: 10px; 10 | display: grid; 11 | grid-template-columns: repeat(9, 1fr); 12 | grid-gap: 10px; 13 | margin: 0 auto; 14 | padding: 20px; 15 | } 16 | 17 | #roulette-grid>input { 18 | color: white; 19 | font-size: 20px; 20 | width: 50px; 21 | } 22 | 23 | #roulette-grid>input:nth-child(odd) { 24 | background-color: red; 25 | } 26 | 27 | #roulette-grid>input:nth-child(even) { 28 | background-color: black; 29 | } 30 | -------------------------------------------------------------------------------- /examples/assets/router.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | display: flex; 3 | justify-content: flex-start; 4 | gap: 1rem; 5 | align-items: center; 6 | } 7 | 8 | #blog-list { 9 | display: flex; 10 | flex-direction: column; 11 | align-items: start; 12 | gap: 1rem; 13 | } 14 | -------------------------------------------------------------------------------- /examples/assets/visible.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | .container { 6 | height: 500px; 7 | width: 500px; 8 | margin: 100px auto; 9 | } 10 | 11 | p { 12 | line-height: 30px; 13 | 14 | } 15 | 16 | .animated-text { 17 | font-size: 30px; 18 | text-align: center; 19 | opacity: 0; 20 | transform: translateY(100px); 21 | transition: opacity 1s ease, transform 1s ease; 22 | } 23 | 24 | .animated-text.visible { 25 | opacity: 1; 26 | transform: translateX(0); 27 | } 28 | -------------------------------------------------------------------------------- /examples/custom_assets.rs: -------------------------------------------------------------------------------- 1 | //! A simple example on how to use assets loading from the filesystem. 2 | //! 3 | //! Dioxus provides the asset!() macro which is a convenient way to load assets from the filesystem. 4 | //! This ensures the asset makes it into the bundle through dependencies and is accessible in environments 5 | //! like web and android where assets are lazily loaded using platform-specific APIs. 6 | 7 | use dioxus::prelude::*; 8 | 9 | static ASSET_PATH: Asset = asset!("/examples/assets/logo.png"); 10 | 11 | fn main() { 12 | dioxus::launch(app); 13 | } 14 | 15 | fn app() -> Element { 16 | rsx! { 17 | div { 18 | h1 { "This should show an image:" } 19 | img { src: ASSET_PATH } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/custom_html.rs: -------------------------------------------------------------------------------- 1 | //! This example shows how to use a custom index.html and custom extensions 2 | //! to add things like stylesheets, scripts, and third-party JS libraries. 3 | 4 | use dioxus::prelude::*; 5 | 6 | fn main() { 7 | dioxus::LaunchBuilder::new() 8 | .with_cfg( 9 | dioxus::desktop::Config::new().with_custom_index( 10 | r#" 11 | 12 | 13 | 14 | Dioxus app 15 | 16 | 17 | 18 | 19 |

External HTML

20 |
21 | 22 | 23 | "# 24 | .into(), 25 | ), 26 | ) 27 | .launch(app); 28 | } 29 | 30 | fn app() -> Element { 31 | rsx! { 32 | h1 { "Custom HTML!" } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/disabled.rs: -------------------------------------------------------------------------------- 1 | //! A simple demonstration of how to set attributes on buttons to disable them. 2 | //! 3 | //! This example also showcases the shorthand syntax for attributes, and how signals themselves implement IntoAttribute 4 | 5 | use dioxus::prelude::*; 6 | 7 | fn main() { 8 | dioxus::launch(app); 9 | } 10 | 11 | fn app() -> Element { 12 | let mut disabled = use_signal(|| false); 13 | 14 | rsx! { 15 | div { style: "text-align: center; margin: 20px; display: flex; flex-direction: column; align-items: center;", 16 | button { onclick: move |_| disabled.toggle(), 17 | "click to " 18 | if disabled() { "enable" } else { "disable" } 19 | " the lower button" 20 | } 21 | button { disabled, "lower button" } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/fullstack-auth/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | target 3 | static 4 | .dioxus -------------------------------------------------------------------------------- /examples/fullstack-desktop/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | target 3 | static 4 | .dioxus -------------------------------------------------------------------------------- /examples/fullstack-desktop/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fullstack-desktop-example" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | dioxus = { workspace = true, features = ["launch", "fullstack"] } 9 | serde = { workspace = true } 10 | 11 | [features] 12 | default = [] 13 | server = ["dioxus/server"] 14 | desktop = ["dioxus/desktop"] 15 | -------------------------------------------------------------------------------- /examples/fullstack-hello-world/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | target 3 | static 4 | .dioxus -------------------------------------------------------------------------------- /examples/fullstack-hello-world/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fullstack-hello-world-example" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["fullstack"]} 11 | serde = { workspace = true } 12 | reqwest = { workspace = true } 13 | 14 | [features] 15 | default = [] 16 | server = ["dioxus/server"] 17 | web = ["dioxus/web"] 18 | -------------------------------------------------------------------------------- /examples/fullstack-hello-world/assets/hello.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: rgb(108, 104, 104); 3 | } 4 | -------------------------------------------------------------------------------- /examples/fullstack-router/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | target 3 | static 4 | .dioxus -------------------------------------------------------------------------------- /examples/fullstack-router/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fullstack-router-example" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["fullstack", "router"] } 11 | axum = { workspace = true, optional = true } 12 | tokio = { workspace = true, features = ["full"], optional = true } 13 | serde = { workspace = true, features = ["derive"] } 14 | 15 | [features] 16 | default = [] 17 | server = ["axum", "dioxus/server"] 18 | web = ["dioxus/web"] 19 | 20 | -------------------------------------------------------------------------------- /examples/fullstack-streaming/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | target 3 | static 4 | .dioxus -------------------------------------------------------------------------------- /examples/fullstack-streaming/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fullstack-streaming-example" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["fullstack"] } 11 | serde = { workspace = true } 12 | futures = { workspace = true } 13 | tokio = { workspace = true, optional = true } 14 | futures-util.workspace = true 15 | 16 | [features] 17 | default = [] 18 | server = ["dioxus/server", "dep:tokio"] 19 | web = ["dioxus/web"] 20 | -------------------------------------------------------------------------------- /examples/fullstack-websockets/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | target 3 | static 4 | .dioxus -------------------------------------------------------------------------------- /examples/fullstack-websockets/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fullstack-websocket-example" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["fullstack"] } 11 | futures.workspace = true 12 | tokio = { workspace = true, features = ["full"], optional = true } 13 | 14 | [features] 15 | server = ["dioxus/server", "dep:tokio"] 16 | web = ["dioxus/web"] 17 | -------------------------------------------------------------------------------- /examples/generic_component.rs: -------------------------------------------------------------------------------- 1 | //! This example demonstrates how to create a generic component in Dioxus. 2 | //! 3 | //! Generic components can be useful when you want to create a component that renders differently depending on the type 4 | //! of data it receives. In this particular example, we're just using a type that implements `Display` and `PartialEq`, 5 | 6 | use dioxus::prelude::*; 7 | use std::fmt::Display; 8 | 9 | fn main() { 10 | dioxus::launch(app); 11 | } 12 | 13 | fn app() -> Element { 14 | rsx! { 15 | generic_child { data: 0 } 16 | } 17 | } 18 | 19 | #[derive(PartialEq, Props, Clone)] 20 | struct GenericChildProps { 21 | data: T, 22 | } 23 | 24 | fn generic_child(props: GenericChildProps) -> Element { 25 | rsx! { 26 | div { "{props.data}" } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/hello_world.rs: -------------------------------------------------------------------------------- 1 | //! The simplest example of a Dioxus app. 2 | //! 3 | //! In this example we: 4 | //! - import a number of important items from the prelude (launch, Element, rsx, div, etc.) 5 | //! - define a main function that calls the launch function with our app function 6 | //! - define an app function that returns a div element with the text "Hello, world!" 7 | //! 8 | //! The `launch` function is the entry point for all Dioxus apps. It takes a function that returns an Element. This function 9 | //! calls "launch" on the currently-configured renderer you have. So if the `web` feature is enabled, it will launch a web 10 | //! app, and if the `desktop` feature is enabled, it will launch a desktop app. 11 | 12 | use dioxus::prelude::*; 13 | 14 | fn main() { 15 | dioxus::launch(app); 16 | } 17 | 18 | fn app() -> Element { 19 | rsx! { 20 | div { "Hello, world!" } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/pwa/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-pwa-example" 3 | version = "0.1.0" 4 | authors = ["Antonio Curavalea "] 5 | edition = "2021" 6 | publish = false 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | dioxus = { workspace = true, features = ["web"] } 12 | -------------------------------------------------------------------------------- /examples/pwa/Dioxus.toml: -------------------------------------------------------------------------------- 1 | [application] 2 | 3 | # App (Project) Name 4 | name = "dioxus-pwa-example" 5 | 6 | # Dioxus App Default Platform 7 | # desktop, web, mobile, ssr 8 | default_platform = "web" 9 | 10 | # `build` & `serve` dist path 11 | out_dir = "dist" 12 | 13 | # resource (public) file folder 14 | asset_dir = "public" 15 | 16 | [web.app] 17 | 18 | # HTML title tag content 19 | title = "dioxus | ⛺" 20 | 21 | [web.watcher] 22 | 23 | # when watcher trigger, regenerate the `index.html` 24 | reload_html = true 25 | 26 | # which files or dirs will be watcher monitoring 27 | watch_path = ["src", "public"] 28 | -------------------------------------------------------------------------------- /examples/pwa/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {app_title} 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/pwa/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/examples/pwa/public/favicon.ico -------------------------------------------------------------------------------- /examples/pwa/public/logo_192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/examples/pwa/public/logo_192.png -------------------------------------------------------------------------------- /examples/pwa/public/logo_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/examples/pwa/public/logo_512.png -------------------------------------------------------------------------------- /examples/pwa/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Dioxus", 3 | "icons": [ 4 | { 5 | "src": "logo_192.png", 6 | "type": "image/png", 7 | "sizes": "192x192" 8 | }, 9 | { 10 | "src": "logo_512.png", 11 | "type": "image/png", 12 | "sizes": "512x512", 13 | "purpose": "any" 14 | }, 15 | { 16 | "src": "logo_512.png", 17 | "type": "image/png", 18 | "sizes": "any", 19 | "purpose": "any" 20 | } 21 | ], 22 | "start_url": "/", 23 | "id": "/", 24 | "display": "standalone", 25 | "display_override": ["window-control-overlay", "standalone"], 26 | "scope": "/", 27 | "theme_color": "#000000", 28 | "background_color": "#ffffff", 29 | "short_name": "Dioxus", 30 | "description": "Dioxus is a portable, performant, and ergonomic framework for building cross-platform user interfaces in Rust.", 31 | "dir": "ltr", 32 | "lang": "en", 33 | "orientation": "portrait" 34 | } 35 | -------------------------------------------------------------------------------- /examples/pwa/src/main.rs: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | fn main() { 4 | dioxus::launch(app); 5 | } 6 | 7 | fn app() -> Element { 8 | rsx! ( 9 | div { style: "text-align: center;", 10 | h1 { "🌗 Dioxus 🚀" } 11 | h3 { "Frontend that scales." } 12 | p { "Build web, desktop, and mobile apps with Dioxus" } 13 | } 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /examples/readme.rs: -------------------------------------------------------------------------------- 1 | //! The example from the readme! 2 | //! 3 | //! This example demonstrates how to create a simple counter app with dioxus. The `Signal` type wraps inner values, 4 | //! making them `Copy`, allowing them to be freely used in closures and async functions. `Signal` also provides 5 | //! helper methods like AddAssign, SubAssign, toggle, etc, to make it easy to update the value without running 6 | //! into lock issues. 7 | 8 | use dioxus::prelude::*; 9 | 10 | fn main() { 11 | dioxus::launch(app); 12 | } 13 | 14 | fn app() -> Element { 15 | let mut count = use_signal(|| 0); 16 | 17 | rsx! { 18 | h1 { "High-Five counter: {count}" } 19 | button { onclick: move |_| count += 1, "Up high!" } 20 | button { onclick: move |_| count -= 1, "Down low!" } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/resize.rs: -------------------------------------------------------------------------------- 1 | //! Run a callback 2 | //! 3 | //! Whenever an Element is finally mounted to the Dom, its data is available to be read. 4 | //! These fields can typically only be read asynchronously, since various renderers need to release the main thread to 5 | //! perform layout and painting. 6 | 7 | use dioxus::prelude::*; 8 | use dioxus_elements::geometry::euclid::Size2D; 9 | 10 | fn main() { 11 | dioxus::launch(app); 12 | } 13 | 14 | fn app() -> Element { 15 | let mut dimensions = use_signal(Size2D::zero); 16 | 17 | rsx!( 18 | document::Link { 19 | rel: "stylesheet", 20 | href: asset!("/examples/assets/read_size.css"), 21 | } 22 | div { 23 | width: "50%", 24 | height: "50%", 25 | background_color: "red", 26 | onresize: move |evt| dimensions.set(evt.data().get_content_box_size().unwrap()), 27 | "This element is {dimensions():?}" 28 | } 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /examples/shortcut.rs: -------------------------------------------------------------------------------- 1 | //! Add global shortcuts to your app while a component is active 2 | //! 3 | //! This demo shows how to add a global shortcut to your app that toggles a signal. You could use this to implement 4 | //! a raycast-type app, or to add a global shortcut to your app that toggles a component on and off. 5 | //! 6 | //! These are *global* shortcuts, so they will work even if your app is not in focus. 7 | 8 | use dioxus::desktop::{use_global_shortcut, HotKeyState}; 9 | use dioxus::prelude::*; 10 | 11 | fn main() { 12 | dioxus::LaunchBuilder::desktop().launch(app); 13 | } 14 | 15 | fn app() -> Element { 16 | let mut toggled = use_signal(|| false); 17 | 18 | _ = use_global_shortcut("ctrl+s", move |state| { 19 | if state == HotKeyState::Pressed { 20 | toggled.toggle(); 21 | } 22 | }); 23 | 24 | rsx!("toggle: {toggled}") 25 | } 26 | -------------------------------------------------------------------------------- /examples/tailwind/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /examples/tailwind/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-tailwind" 3 | version = "0.0.0" 4 | authors = [] 5 | edition = "2021" 6 | description = "A tailwindcss example using Dioxus" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | homepage = "https://dioxuslabs.com" 10 | documentation = "https://dioxuslabs.com" 11 | publish = false 12 | 13 | [dependencies] 14 | manganis = { workspace = true } 15 | dioxus = { workspace = true } 16 | 17 | [features] 18 | default = ["desktop"] 19 | web = ["dioxus/web"] 20 | desktop = ["dioxus/desktop"] 21 | -------------------------------------------------------------------------------- /examples/tailwind/Dioxus.toml: -------------------------------------------------------------------------------- 1 | [application] 2 | 3 | # App (Project) Name 4 | name = "Tailwind CSS + Dioxus" 5 | 6 | # Dioxus App Default Platform 7 | # desktop, web, mobile, ssr 8 | default_platform = "web" 9 | 10 | # `build` & `serve` dist path 11 | out_dir = "dist" 12 | 13 | # resource (public) file folder 14 | asset_dir = "public" 15 | 16 | [web.app] 17 | 18 | # HTML title tag content 19 | title = "dioxus | ⛺" 20 | 21 | [web.watcher] 22 | 23 | # when watcher trigger, regenerate the `index.html` 24 | reload_html = true 25 | 26 | # which files or dirs will be watcher monitoring 27 | watch_path = ["src", "public"] 28 | -------------------------------------------------------------------------------- /examples/tailwind/README.md: -------------------------------------------------------------------------------- 1 | Example: Basic Tailwind usage 2 | 3 | This example shows how an app might be styled with TailwindCSS. 4 | 5 | ## Running 6 | 7 | Our [Tailwind](https://dioxuslabs.com/learn/0.6/cookbook/tailwind) guide explains how to setup and run Dioxus-Tailwind projects. 8 | 9 | Note that in Dioxus 0.7, the Tailwind watcher is initialized automatically if a `tailwind.css` file is find in your app's root. 10 | -------------------------------------------------------------------------------- /examples/tailwind/tailwind.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | @source "./src/**/*.{rs,html,css}"; 3 | -------------------------------------------------------------------------------- /examples/title.rs: -------------------------------------------------------------------------------- 1 | //! This example shows how to set the title of the page or window with the Title component 2 | 3 | use dioxus::prelude::*; 4 | 5 | fn main() { 6 | dioxus::launch(app); 7 | } 8 | 9 | fn app() -> Element { 10 | let mut count = use_signal(|| 0); 11 | 12 | rsx! { 13 | div { 14 | // You can set the title of the page with the Title component 15 | // In web applications, this sets the title in the head. On desktop, it sets the window title 16 | document::Title { "My Application (Count {count})" } 17 | button { onclick: move |_| count += 1, "Up high!" } 18 | button { onclick: move |_| count -= 1, "Down low!" } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/window_zoom.rs: -------------------------------------------------------------------------------- 1 | //! Adjust the zoom of a desktop app 2 | //! 3 | //! This example shows how to adjust the zoom of a desktop app using the webview.zoom method. 4 | 5 | use dioxus::prelude::*; 6 | 7 | fn main() { 8 | dioxus::LaunchBuilder::desktop().launch(app); 9 | } 10 | 11 | fn app() -> Element { 12 | let mut level = use_signal(|| 1.0); 13 | 14 | rsx! { 15 | h1 { "Zoom level: {level}" } 16 | p { "Change the zoom level of the webview by typing a number in the input below." } 17 | input { 18 | r#type: "number", 19 | value: "{level}", 20 | oninput: move |e| { 21 | if let Ok(new_zoom) = e.value().parse::() { 22 | level.set(new_zoom); 23 | _ = dioxus::desktop::window().webview.zoom(new_zoom); 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/xss_safety.rs: -------------------------------------------------------------------------------- 1 | //! XSS Safety 2 | //! 3 | //! This example proves that Dioxus is safe from XSS attacks. 4 | 5 | use dioxus::prelude::*; 6 | 7 | fn main() { 8 | dioxus::launch(app); 9 | } 10 | 11 | fn app() -> Element { 12 | let mut contents = use_signal(|| String::from("")); 13 | 14 | rsx! { 15 | div { 16 | h1 {"Dioxus is XSS-Safe"} 17 | h3 { "{contents}" } 18 | input { 19 | value: "{contents}", 20 | r#type: "text", 21 | oninput: move |e| contents.set(e.value()), 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lychee.toml: -------------------------------------------------------------------------------- 1 | # This is the configuration file for lychee, a link validator. 2 | exclude = ['file:///', 'https://github.com/DioxusLabs/dioxus/commit'] 3 | exclude_path = ['target'] 4 | no_progress = false 5 | cache = true 6 | max_cache_age = "10d" 7 | accept = ["200..=204", "429"] 8 | -------------------------------------------------------------------------------- /notes/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | On Linux, install the following packages: 4 | 5 | ```bash 6 | sudo apt install libgdk3.0-cil libatk1.0-dev libcairo2-dev libpango1.0-dev libgdk-pixbuf2.0-dev libsoup-3.0-dev libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev 7 | ``` 8 | 9 | Then run: 10 | 11 | ```bash 12 | cargo test --workspace --tests 13 | ``` 14 | -------------------------------------------------------------------------------- /notes/android_and_ios2.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/notes/android_and_ios2.avif -------------------------------------------------------------------------------- /notes/autofmt.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/notes/autofmt.gif -------------------------------------------------------------------------------- /notes/bundle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/notes/bundle.gif -------------------------------------------------------------------------------- /notes/dioxus-community.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/notes/dioxus-community.avif -------------------------------------------------------------------------------- /notes/dioxus_splash_8.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/notes/dioxus_splash_8.avif -------------------------------------------------------------------------------- /notes/docs.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/notes/docs.avif -------------------------------------------------------------------------------- /notes/flat-splash.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/notes/flat-splash.avif -------------------------------------------------------------------------------- /notes/hotreload.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/notes/hotreload.gif -------------------------------------------------------------------------------- /notes/image-splash.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/notes/image-splash.avif -------------------------------------------------------------------------------- /packages/asset-resolver/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-asset-resolver" 3 | edition = "2021" 4 | version.workspace = true 5 | authors = ["Jonathan Kelley", "Dioxus Labs"] 6 | description = "Cross-platform asset resolver for manganis and dioxus" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | homepage = "https://dioxuslabs.com" 10 | keywords = ["web", "desktop", "mobile", "gui", "wasm"] 11 | rust-version = "1.79.0" 12 | 13 | [dependencies] 14 | http = { workspace = true } 15 | percent-encoding = { workspace = true } 16 | infer = { workspace = true } 17 | thiserror = { workspace = true } 18 | dioxus-cli-config = { workspace = true } 19 | 20 | [target.'cfg(target_os = "android")'.dependencies] 21 | jni = "0.21.1" 22 | ndk = { version = "0.9.0" } 23 | ndk-sys = { version = "0.6.0" } 24 | ndk-context = { version = "0.1.1" } 25 | -------------------------------------------------------------------------------- /packages/autofmt/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // dont let our extension kick on the rsx files - we're fixing it! 3 | "dioxus.formatOnSave": "disabled", 4 | // enable this when modifying tab-based indentation 5 | // When inside .rsx files, dont automatically use spaces 6 | // "files.autoSave": "off" 7 | } 8 | -------------------------------------------------------------------------------- /packages/autofmt/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-autofmt" 3 | version = { workspace = true } 4 | edition = "2021" 5 | authors = ["Jonathan Kelley"] 6 | description = "Autofomatter for Dioxus RSX" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | homepage = "https://dioxuslabs.com" 10 | keywords = ["web", "desktop", "mobile", "gui", "wasm"] 11 | 12 | [dependencies] 13 | dioxus-rsx = { workspace = true } 14 | proc-macro2 = { workspace = true, features = ["span-locations"] } 15 | quote = { workspace = true } 16 | syn = { workspace = true, features = [ 17 | "full", 18 | "extra-traits", 19 | "visit", 20 | "visit-mut", 21 | ] } 22 | serde = { workspace = true, features = ["derive"] } 23 | prettyplease = { workspace = true } 24 | 25 | [dev-dependencies] 26 | pretty_assertions = { workspace = true } 27 | 28 | [package.metadata.docs.rs] 29 | cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"] 30 | -------------------------------------------------------------------------------- /packages/autofmt/tests/error_handling.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn no_parse() { 3 | let src = include_str!("./partials/no_parse.rsx"); 4 | assert!(syn::parse_file(src).is_err()); 5 | } 6 | 7 | #[test] 8 | fn parses_but_fmt_fails() { 9 | let src = include_str!("./partials/wrong.rsx"); 10 | let file = syn::parse_file(src).unwrap(); 11 | let formatted = dioxus_autofmt::try_fmt_file(src, &file, Default::default()); 12 | assert!(&formatted.is_err()); 13 | } 14 | 15 | #[test] 16 | fn parses_and_is_okay() { 17 | let src = include_str!("./partials/okay.rsx"); 18 | let file = syn::parse_file(src).unwrap(); 19 | let formatted = dioxus_autofmt::try_fmt_file(src, &file, Default::default()).unwrap(); 20 | assert_ne!(formatted.len(), 0); 21 | } 22 | -------------------------------------------------------------------------------- /packages/autofmt/tests/partials/no_parse.rsx: -------------------------------------------------------------------------------- 1 | #[component] 2 | fn SidebarSection() -> Element { 3 | rsx! { 4 | div { 5 | { .doesnt_work) } 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/autofmt/tests/partials/okay.rsx: -------------------------------------------------------------------------------- 1 | #[component] 2 | fn SidebarSection() -> Element { 3 | rsx! { 4 | div { 5 | onclick: move |_| { 6 | works() 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/autofmt/tests/partials/wrong.rsx: -------------------------------------------------------------------------------- 1 | #[component] 2 | fn SidebarSection() -> Element { 3 | rsx! { 4 | div { 5 | onclick: move |_| { 6 | .doesnt_work() 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/asset.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | div { "hi" } 3 | img { 4 | // note: the line breaking here is weird but it's because of prettyplease, not dioxus-autofmt 5 | // we might want to fix this in the future 6 | src: asset!( 7 | "/assets/logo.png".image().size(512, 512).format(ImageType::Jpg).url_encoded() 8 | .image().size(512, 512).format(ImageType::Jpg).url_encoded() 9 | ), 10 | alt: "logo", 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/basic_expr.rsx: -------------------------------------------------------------------------------- 1 | fn itworks() { 2 | rsx! { 3 | div { 4 | "hi" 5 | {children} 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/collapse.rsx: -------------------------------------------------------------------------------- 1 | // nesting pushes out 2 | rsx! { 3 | Fragment { 4 | Fragment { 5 | Fragment { 6 | Fragment { 7 | Fragment { 8 | div { "Finally have a real node!" } 9 | } 10 | } 11 | } 12 | } 13 | } 14 | } 15 | 16 | // we don't make extra spaces 17 | rsx! { 18 | Component { blah: rsx! {} } 19 | } 20 | 21 | rsx! {} 22 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/collapse_expr.rsx: -------------------------------------------------------------------------------- 1 | fn itworks() { 2 | rsx! { 3 | "{name}" 4 | "{name}" 5 | "{name}" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/commentshard.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | // Comments 3 | div { 4 | // Comments 5 | class: "asdasd", 6 | 7 | // Comments 8 | "hello world" 9 | 10 | // Comments 11 | {expr1} 12 | 13 | // Comments 14 | {expr2} 15 | 16 | // Comments 17 | // Comments 18 | // Comments 19 | // Comments 20 | // Comments 21 | {expr3} 22 | 23 | div { 24 | // todo some work in here 25 | } 26 | 27 | div { 28 | // todo some work in here 29 | // todo some work in here 30 | // 31 | // todo some work in here 32 | } 33 | 34 | div { 35 | // todo some work in here 36 | class: "hello world", 37 | 38 | // todo some work in here 39 | class: "hello world", 40 | } 41 | 42 | div { 43 | div {} 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/emoji.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | div { class: "asdasdasd asdasdasd asdasdasd asdasdasd asdasdasd asdasdasd asdasdasd asdasdasd asdasdasd", 3 | section { "🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/ifchain_forloop.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | // Does this work? 3 | for i in b { 4 | // Hey it works? 5 | div {} 6 | } 7 | 8 | // Some ifchain 9 | if a > 10 { 10 | // 11 | div {} 12 | } else if a > 20 { 13 | h1 {} 14 | } else if a > 20 { 15 | h1 {} 16 | } else if a > 20 { 17 | h1 {} 18 | } else if a > 20 { 19 | h1 {} 20 | } else if a > 20 { 21 | h1 {} 22 | } else if a > 20 { 23 | h1 {} 24 | } else { 25 | h3 {} 26 | } 27 | 28 | div { 29 | class: "asdasd", 30 | class: if expr { "asdasd" } else { "asdasd" }, 31 | class: if expr { "asdasd" }, 32 | class: if expr { "asdasd" } else if expr { "asdasd" } else { "asdasd" }, 33 | 34 | // comments? 35 | class: if expr { "asdasd" } else if expr { "asdasd" } else { "asdasd" }, // comments!!? 36 | // comments? 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/immediate_expr.rsx: -------------------------------------------------------------------------------- 1 | fn it_works() { 2 | rsx! { 3 | {()} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/key.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | li { key: "{link}", 3 | Link { class: "py-1 px-2 {hover} {hover_bg}", to: "{link}", "{name}" } 4 | } 5 | 6 | li { key: "{link}", asd: "asd", 7 | Link { class: "py-1 px-2 {hover} {hover_bg}", to: "{link}", "{name}" } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/letsome.rsx: -------------------------------------------------------------------------------- 1 | #[component] 2 | fn SidebarSection() -> Element { 3 | rsx! { 4 | if let Some(url) = &link.location { 5 | "hi {url}" 6 | } 7 | 8 | if val.is_empty() { 9 | "No content" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/long_exprs.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | div { 3 | div { 4 | div { 5 | div { 6 | section { class: "body-font overflow-hidden dark:bg-ideblack", 7 | div { class: "container px-6 mx-auto", 8 | div { class: "-my-8 divide-y-2 divide-gray-100", 9 | {POSTS.iter().enumerate().map(|(id, post)| rsx! { 10 | BlogPostItem { post, id } 11 | })} 12 | } 13 | } 14 | } 15 | } 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/manual_props.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | div { 3 | Component { 4 | adsasd: "asd", 5 | onclick: move |_| { 6 | let a = a; 7 | }, 8 | div { "thing" } 9 | } 10 | Component { 11 | asdasd: "asdasd", 12 | asdasd: "asdasdasdasdasdasdasdasdasdasd", 13 | ..Props { a: 10, b: 20 }, 14 | } 15 | Component { 16 | asdasd: "asdasd", 17 | ..Props { 18 | a: 10, 19 | b: 20, 20 | c: { 21 | fn main() {} 22 | }, 23 | }, 24 | "content" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/messy_indent.rsx: -------------------------------------------------------------------------------- 1 | fn SaveClipboard() -> Element { 2 | rsx! { 3 | div { class: "relative w-1/2 {align} max-w-md leading-8", 4 | 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", 5 | "{title}" 6 | } 7 | } 8 | }; 9 | 10 | rsx! { 11 | div { 12 | "hello world" 13 | "hello world" 14 | "hello world" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/multirsx.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | 3 | // hi 4 | div {} 5 | 6 | // hi 7 | div { 8 | "abcd" 9 | "ball" 10 | "s" 11 | } 12 | 13 | // 14 | // 15 | // 16 | div { 17 | "abcd" 18 | "ball" 19 | "s" 20 | } 21 | 22 | // 23 | // 24 | // 25 | div { 26 | "abcd" 27 | "ball" 28 | "s" 29 | 30 | // 31 | "asdasd" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/oneline.rsx: -------------------------------------------------------------------------------- 1 | rsx! { "hello world" } 2 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/raw_strings.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | // Raw text strings 3 | button { 4 | r#"Click me"# 5 | r##"Click me"## 6 | r######"Click me"###### 7 | r#"dynamic {1}"# 8 | } 9 | 10 | // Raw attribute strings 11 | div { 12 | width: r#"10px"#, 13 | height: r##"{10}px"##, 14 | "raw-attr": r###"raw-attr"###, 15 | "raw-attr2": r###"{100}"###, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/reallylong.rsx: -------------------------------------------------------------------------------- 1 | pub static Icon3: Component<()> = |cx| { 2 | rsx! { 3 | svg { 4 | class: "w-6 h-6", 5 | stroke_linecap: "round", 6 | fill: "none", 7 | stroke_linejoin: "round", 8 | stroke_width: "2", 9 | stroke: "currentColor", 10 | view_box: "0 0 24 24", 11 | path { d: "M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2" } 12 | circle { cx: "12", cy: "7", r: "4" } 13 | } 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/skip.rsx: -------------------------------------------------------------------------------- 1 | /// dont format this component 2 | #[rustfmt::skip] 3 | #[component] 4 | fn SidebarSection() -> Element { 5 | rsx! { 6 | div { 7 | "hi" div {} div {} 8 | } 9 | } 10 | } 11 | 12 | /// dont format this component 13 | #[component] 14 | fn SidebarSection() -> Element { 15 | // format this 16 | rsx! { 17 | div { "hi" } 18 | } 19 | 20 | // and this 21 | rsx! { 22 | div { 23 | "hi" 24 | div {} 25 | div {} 26 | } 27 | } 28 | 29 | // but not this 30 | #[rustfmt::skip] 31 | rsx! { 32 | div { 33 | "hi" div {} div {} 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/spaces.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | if let Some(Some(record)) = &*records.read_unchecked() { 3 | { 4 | let (label, value): (Vec, Vec) = record 5 | .iter() 6 | .rev() 7 | .map(|d| (d.model.clone().expect("work"), d.row_total)) 8 | .collect(); 9 | rsx! { 10 | BarChart { id: "bar-plot".to_string(), x: value, y: label } 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/staged.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | div {} 3 | 4 | div { "hi" } 5 | 6 | div { class: "hello", "hi" } 7 | 8 | div { class: "hello", glass: "123", "hi" } 9 | 10 | div { {some_expr} } 11 | div { 12 | {POSTS.iter().enumerate().map(|(id, post)| rsx! { 13 | BlogPostItem { post, id } 14 | })} 15 | } 16 | 17 | div { class: "123123123123123123123123123123123123", 18 | { 19 | some_really_long_expr_some_really_long_expr_some_really_long_expr_some_really_long_expr_ 20 | } 21 | } 22 | 23 | div { class: "-my-8 divide-y-2 divide-gray-100", 24 | {POSTS.iter().enumerate().map(|(id, post)| rsx! { 25 | BlogPostItem { post, id } 26 | })} 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/t2.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | div {} 3 | div { 4 | // div { 5 | } 6 | } 7 | 8 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/tiny.rsx: -------------------------------------------------------------------------------- 1 | fn ItWorks() { 2 | rsx! { 3 | div { 4 | div { 5 | div {} 6 | div {} 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/tinynoopt.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | div { 3 | div {} 4 | div {} 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/autofmt/tests/samples/trailing_expr.rsx: -------------------------------------------------------------------------------- 1 | fn it_works() { 2 | rsx! { 3 | div { 4 | span { 5 | "Description: " 6 | {package.description.as_deref().unwrap_or("❌❌❌❌ missing")} 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/autofmt/tests/srcless/asset.rsx: -------------------------------------------------------------------------------- 1 | parse_quote! { 2 | img { src: asset!("/assets/logos/123.png") } 3 | img { src: asset!("/assets/logos/456.png") } 4 | img { src: asset!("/assets/logos/789.png") } 5 | } 6 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/comments-4sp.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | div { 3 | // Comments 4 | class: "asdasd", 5 | "hello world" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/comments-4sp.wrong.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | div { 3 | // Comments 4 | class: "asdasd", "hello world" } 5 | } 6 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/comments-tab.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | div { 3 | // Comments 4 | class: "asdasd", 5 | "hello world" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/comments-tab.wrong.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | div { 3 | // Comments 4 | class: "asdasd", "hello world" } 5 | } 6 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/multi-4sp.rsx: -------------------------------------------------------------------------------- 1 | fn app() -> Element { 2 | rsx! { 3 | div { "hello world" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/multi-4sp.wrong.rsx: -------------------------------------------------------------------------------- 1 | fn app() -> Element { 2 | rsx! { div {"hello world" } } 3 | } 4 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/multi-tab.rsx: -------------------------------------------------------------------------------- 1 | fn app() -> Element { 2 | rsx! { 3 | div { "hello world" } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/multi-tab.wrong.rsx: -------------------------------------------------------------------------------- 1 | fn app() -> Element { 2 | rsx! { div {"hello world" } } 3 | } 4 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/multiexpr-4sp.rsx: -------------------------------------------------------------------------------- 1 | fn ItWorks() { 2 | rsx! { 3 | div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", 4 | {left} 5 | {right} 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/multiexpr-4sp.wrong.rsx: -------------------------------------------------------------------------------- 1 | fn ItWorks() { 2 | rsx! { 3 | div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", {left}, {right} } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/multiexpr-tab.rsx: -------------------------------------------------------------------------------- 1 | fn ItWorks() { 2 | rsx! { 3 | div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", 4 | {left} 5 | {right} 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/multiexpr-tab.wrong.rsx: -------------------------------------------------------------------------------- 1 | fn ItWorks() { 2 | rsx! { 3 | div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", {left}, {right} } 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/oneline-expand.rsx: -------------------------------------------------------------------------------- 1 | fn main() { 2 | rsx! { 3 | button { 4 | id: "start_stop", 5 | onclick: move |_| { 6 | timer 7 | .with_mut(|t| { 8 | t.started_at = if t.started_at.is_none() { 9 | Some(Instant::now()) 10 | } else { 11 | None 12 | }; 13 | }) 14 | }, 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/oneline-expand.wrong.rsx: -------------------------------------------------------------------------------- 1 | fn main() { 2 | rsx! { 3 | button { 4 | id: "start_stop", 5 | onclick: move |_| timer.with_mut(|t| t.started_at = if t.started_at.is_none() { Some(Instant::now()) } else { None } ) 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/shortened.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | Chapter { chapter } 3 | 4 | div { class } 5 | } 6 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/shortened.wrong.rsx: -------------------------------------------------------------------------------- 1 | rsx! { 2 | Chapter { chapter: chapter } 3 | 4 | div { class: class } 5 | } 6 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/skipfail.rsx: -------------------------------------------------------------------------------- 1 | /// dont format this component 2 | #[rustfmt::skip] 3 | #[component] 4 | fn SidebarSection() -> Element { 5 | rsx! { 6 | div { 7 | "hi" div {} div {} 8 | } 9 | } 10 | } 11 | 12 | /// dont format this component 13 | #[component] 14 | fn SidebarSection() -> Element { 15 | // format this 16 | rsx! { 17 | div { "hi" } 18 | } 19 | 20 | // and this 21 | rsx! { 22 | div { 23 | "hi" 24 | div {} 25 | div {} 26 | } 27 | } 28 | 29 | // but not this 30 | #[rustfmt::skip] 31 | rsx! { 32 | div { 33 | "hi" div {} div {} 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/skipfail.wrong.rsx: -------------------------------------------------------------------------------- 1 | /// dont format this component 2 | #[rustfmt::skip] 3 | #[component] 4 | fn SidebarSection() -> Element { 5 | rsx! { 6 | div { 7 | "hi" div {} div {} 8 | } 9 | } 10 | } 11 | 12 | /// dont format this component 13 | #[component] 14 | fn SidebarSection() -> Element { 15 | // format this 16 | rsx! { 17 | div { "hi" } 18 | } 19 | 20 | // and this 21 | rsx! { 22 | div { "hi" div {} div {} } 23 | } 24 | 25 | // but not this 26 | #[rustfmt::skip] 27 | rsx! { 28 | div { 29 | "hi" div {} div {} 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/syntax_error.rsx: -------------------------------------------------------------------------------- 1 | fn app() -> Element { 2 | rsx! { 3 | let x="hello world"; 4 | div { "hello world" } 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/autofmt/tests/wrong/syntax_error.wrong.rsx: -------------------------------------------------------------------------------- 1 | fn app() -> Element { 2 | rsx! { 3 | let x="hello world"; 4 | div { "hello world" } 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/check/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-check" 3 | version = { workspace = true } 4 | edition = "2021" 5 | authors = ["Dioxus Labs"] 6 | description = "Checks Dioxus RSX files for issues" 7 | license = "MIT/Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | homepage = "https://dioxuslabs.com" 10 | keywords = ["web", "desktop", "mobile", "gui", "wasm"] 11 | 12 | [dependencies] 13 | proc-macro2 = { workspace = true, features = ["span-locations"] } 14 | quote = {workspace = true } 15 | syn = { workspace = true, features = ["full", "extra-traits", "visit"] } 16 | owo-colors = { workspace = true, features = ["supports-colors"] } 17 | 18 | [dev-dependencies] 19 | indoc = "2.0.6" 20 | pretty_assertions = { workspace = true } 21 | -------------------------------------------------------------------------------- /packages/check/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")] 3 | #![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")] 4 | 5 | mod check; 6 | mod issues; 7 | mod metadata; 8 | 9 | pub use check::check_file; 10 | pub use issues::{Issue, IssueReport}; 11 | -------------------------------------------------------------------------------- /packages/cli-config/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | .DS_Store 4 | .idea/ 5 | -------------------------------------------------------------------------------- /packages/cli-config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-cli-config" 3 | edition = "2021" 4 | version.workspace = true 5 | authors = ["Jonathan Kelley", "Evan Almloff"] 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/DioxusLabs/dioxus/" 8 | homepage = "https://dioxuslabs.com" 9 | description = "CLI Configuration for dioxus-cli" 10 | keywords = ["web", "desktop", "mobile", "gui", "wasm"] 11 | 12 | [dependencies] 13 | wasm-bindgen = { workspace = true, optional = true } 14 | 15 | [features] 16 | web = ["dep:wasm-bindgen"] 17 | -------------------------------------------------------------------------------- /packages/cli-config/README.md: -------------------------------------------------------------------------------- 1 | # dioxus-cli-config 2 | 3 | A crate that provides key/value names and types for configuring Dioxus applications at runtime. 4 | 5 | This crate exists for us to very cleanly define the exact fields we want to pass down to Dioxus applications at runtime but without exposing the entire config object. 6 | 7 | This leads to faster compile times, smaller binaries, and a clearer distinction between the config and the application. 8 | -------------------------------------------------------------------------------- /packages/cli-opt/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | built::write_built_file().expect("Failed to acquire build-time information"); 3 | } 4 | -------------------------------------------------------------------------------- /packages/cli-opt/src/build_info.rs: -------------------------------------------------------------------------------- 1 | // The file has been placed there by the build script. 2 | include!(concat!(env!("OUT_DIR"), "/built.rs")); 3 | 4 | pub(crate) fn version() -> String { 5 | format!( 6 | "{} ({})", 7 | PKG_VERSION, 8 | GIT_COMMIT_HASH_SHORT.unwrap_or("was built without git repository") 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /packages/cli-opt/src/image/jpg.rs: -------------------------------------------------------------------------------- 1 | use image::{DynamicImage, EncodableLayout}; 2 | use std::{ 3 | io::{BufWriter, Write}, 4 | path::Path, 5 | }; 6 | 7 | pub(crate) fn compress_jpg(image: DynamicImage, output_location: &Path) -> anyhow::Result<()> { 8 | let mut comp = mozjpeg::Compress::new(mozjpeg::ColorSpace::JCS_EXT_RGBX); 9 | let width = image.width() as usize; 10 | let height = image.height() as usize; 11 | 12 | comp.set_size(width, height); 13 | let mut comp = comp.start_compress(Vec::new())?; // any io::Write will work 14 | 15 | comp.write_scanlines(image.to_rgba8().as_bytes())?; 16 | 17 | let jpeg_bytes = comp.finish()?; 18 | 19 | let file = std::fs::File::create(output_location)?; 20 | let w = &mut BufWriter::new(file); 21 | w.write_all(&jpeg_bytes)?; 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /packages/cli/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | .DS_Store 4 | .idea/ 5 | -------------------------------------------------------------------------------- /packages/cli/Dioxus.toml: -------------------------------------------------------------------------------- 1 | [application] 2 | 3 | # App name 4 | name = "project_name" 5 | 6 | # `build` & `serve` output path 7 | out_dir = "dist" 8 | 9 | # The static resource path 10 | asset_dir = "public" 11 | 12 | [web.app] 13 | 14 | # HTML title tag content 15 | title = "project_name" 16 | 17 | [web.watcher] 18 | 19 | # When watcher is triggered, regenerate the `index.html` 20 | reload_html = true 21 | 22 | # Which files or dirs will be monitored 23 | watch_path = ["src", "public"] 24 | 25 | [[web.proxy]] 26 | backend = "http://localhost:8000/api/" 27 | -------------------------------------------------------------------------------- /packages/cli/assets/android/MainActivity.kt.hbs: -------------------------------------------------------------------------------- 1 | package dev.dioxus.main; 2 | 3 | // need to re-export buildconfig down from the parent 4 | import {{application_id}}.BuildConfig; 5 | typealias BuildConfig = BuildConfig; 6 | 7 | 8 | class MainActivity : WryActivity() 9 | -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /.idea/caches 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | /.idea/navEditor.xml 8 | /.idea/assetWizardSettings.xml 9 | .DS_Store 10 | build 11 | /captures 12 | .externalNativeBuild 13 | jniLibs 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/src/main/assets/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/cli/assets/android/gen/app/src/main/assets/.gitignore -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/src/main/kotlin/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/cli/assets/android/gen/app/src/main/kotlin/.gitignore -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/cli/assets/android/gen/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/cli/assets/android/gen/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/cli/assets/android/gen/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/cli/assets/android/gen/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/cli/assets/android/gen/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/src/main/res/values/strings.xml.hbs: -------------------------------------------------------------------------------- 1 | 2 | {{app_name}} 3 | 4 | -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/build.gradle.kts: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | dependencies { 7 | classpath("com.android.tools.build:gradle:8.7.0") 8 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20") 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | } 18 | 19 | tasks.register("clean").configure { 20 | delete("build") 21 | } 22 | 23 | -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/cli/assets/android/gen/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue May 10 19:22:52 CST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /packages/cli/assets/android/gen/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | -------------------------------------------------------------------------------- /packages/cli/assets/web/prod.index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {app_title} 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/cli/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | built::write_built_file().expect("Failed to acquire build-time information"); 3 | } 4 | -------------------------------------------------------------------------------- /packages/cli/src/cli/clean.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::Result; 3 | 4 | /// Clean build artifacts. 5 | /// 6 | /// Simply runs `cargo clean` 7 | #[derive(Clone, Debug, Parser)] 8 | pub(crate) struct Clean {} 9 | 10 | impl Clean { 11 | /// todo(jon): we should add a config option that just wipes target/dx and target/dioxus-client instead of doing a full clean 12 | pub(crate) async fn clean(self) -> Result { 13 | let output = tokio::process::Command::new("cargo") 14 | .arg("clean") 15 | .output() 16 | .await?; 17 | 18 | if !output.status.success() { 19 | return Err(anyhow::anyhow!("Cargo clean failed.").into()); 20 | } 21 | 22 | Ok(StructuredOutput::Success) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/cli/src/cli/verbosity.rs: -------------------------------------------------------------------------------- 1 | use clap::Parser; 2 | 3 | #[derive(Parser, Clone, Copy, Debug)] 4 | pub struct Verbosity { 5 | /// Use verbose output [default: false] 6 | #[clap(long, global = true)] 7 | pub(crate) verbose: bool, 8 | 9 | /// Use trace output [default: false] 10 | #[clap(long, global = true)] 11 | pub(crate) trace: bool, 12 | 13 | /// Output logs in JSON format 14 | #[clap(long, global = true)] 15 | pub(crate) json_output: bool, 16 | } 17 | -------------------------------------------------------------------------------- /packages/cli/src/config/mod.rs: -------------------------------------------------------------------------------- 1 | mod app; 2 | mod bundle; 3 | mod dioxus_config; 4 | mod serve; 5 | mod web; 6 | 7 | pub(crate) use app::*; 8 | pub(crate) use bundle::*; 9 | pub(crate) use dioxus_config::*; 10 | pub(crate) use serve::*; 11 | pub(crate) use web::*; 12 | -------------------------------------------------------------------------------- /packages/cli/src/config/serve.rs: -------------------------------------------------------------------------------- 1 | use clap::Parser; 2 | 3 | /// The arguments for the address the server will run on 4 | #[derive(Clone, Debug, Default, Parser)] 5 | pub(crate) struct AddressArguments { 6 | /// The port the server will run on 7 | #[clap(long)] 8 | pub(crate) port: Option, 9 | 10 | /// The address the server will run on 11 | #[clap(long)] 12 | pub(crate) addr: Option, 13 | } 14 | -------------------------------------------------------------------------------- /packages/cli/src/devcfg.rs: -------------------------------------------------------------------------------- 1 | //! Configuration of the CLI at runtime to enable certain experimental features. 2 | 3 | /// Should we force the entropy to be used on the main exe? 4 | /// 5 | /// This is used to verify that binaries are copied with different names such that they don't collide 6 | /// and should generally be only enabled on certain platforms that require it. 7 | pub(crate) fn should_force_entropy() -> bool { 8 | std::env::var("DIOXUS_FORCE_ENTRY").is_ok() 9 | } 10 | 11 | /// Should the CLI not download any additional tools? 12 | pub(crate) fn no_downloads() -> bool { 13 | std::env::var("NO_DOWNLOADS").is_ok() 14 | } 15 | 16 | /// Should we test the installs? 17 | #[allow(dead_code)] // -> used in tests only 18 | pub(crate) fn test_installs() -> bool { 19 | std::env::var("TEST_INSTALLS").is_ok() 20 | } 21 | -------------------------------------------------------------------------------- /packages/cli/src/dx_build_info.rs: -------------------------------------------------------------------------------- 1 | // The file has been placed there by the build script. 2 | include!(concat!(env!("OUT_DIR"), "/built.rs")); 3 | -------------------------------------------------------------------------------- /packages/config-macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-config-macro" 3 | version = { workspace = true } 4 | authors = ["Jonathan Kelley"] 5 | edition = "2021" 6 | description = "Configuration macros for Dioxus" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | homepage = "https://dioxuslabs.com" 10 | keywords = ["web", "desktop", "mobile", "gui", "wasm"] 11 | 12 | [lib] 13 | proc-macro = true 14 | 15 | [dependencies] 16 | proc-macro2 = { version = "1.0" } 17 | quote = { workspace = true } 18 | 19 | [features] 20 | default = [] 21 | fullstack = [] 22 | desktop = [] 23 | mobile = [] 24 | web = [] 25 | ssr = [] 26 | liveview = [] 27 | 28 | [package.metadata.docs.rs] 29 | cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"] 30 | -------------------------------------------------------------------------------- /packages/config-macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-config-macros" 3 | edition = "2021" 4 | version.workspace = true 5 | authors = ["Dioxus Labs"] 6 | description = "Macros used internally by codegen" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | homepage = "https://dioxuslabs.com" 10 | keywords = ["web", "desktop", "mobile", "gui", "wasm"] 11 | rust-version = "1.79.0" 12 | 13 | [dependencies] 14 | 15 | [features] 16 | default = [] 17 | wasm-split = [] 18 | -------------------------------------------------------------------------------- /packages/config-macros/README.md: -------------------------------------------------------------------------------- 1 | # Dioxus Config Macros 2 | 3 | These macros are used internally by codegen and are not intended for general use. 4 | 5 | Dioxus will export its feature flags into this crate, allowing downstream codegen to use them under the "dioxus" namespace. 6 | 7 | ## License 8 | 9 | This project is licensed under the [MIT license]. 10 | 11 | [mit license]: https://github.com/dioxuslabs/dioxus/blob/main/LICENSE-MIT 12 | 13 | Unless you explicitly state otherwise, any contribution intentionally submitted 14 | for inclusion in Dioxus by you shall be licensed as MIT without any additional 15 | terms or conditions. 16 | -------------------------------------------------------------------------------- /packages/const-serialize-macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "const-serialize-macro" 3 | version = { workspace = true } 4 | authors = ["Evan Almloff"] 5 | edition = "2021" 6 | description = "A macro to derive const serialize" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/dioxuslabs/dioxus" 9 | homepage = "https://dioxuslabs.com/learn/0.5/getting_started" 10 | keywords = ["const", "serialize"] 11 | 12 | [dependencies] 13 | syn = { workspace = true } 14 | quote = { workspace = true } 15 | proc-macro2 = { workspace = true } 16 | 17 | [lib] 18 | proc-macro = true 19 | -------------------------------------------------------------------------------- /packages/const-serialize/.gitignore: -------------------------------------------------------------------------------- 1 | target -------------------------------------------------------------------------------- /packages/const-serialize/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "const-serialize" 3 | version = { workspace = true } 4 | authors = ["Evan Almloff"] 5 | edition = "2021" 6 | description = "A serialization framework that works in const contexts" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/dioxuslabs/dioxus" 9 | homepage = "https://dioxuslabs.com/learn/0.5/getting_started" 10 | keywords = ["const", "serialize"] 11 | 12 | [dependencies] 13 | const-serialize-macro = { workspace = true } 14 | serde = { workspace = true, features = ["derive"], optional = true } 15 | 16 | [dev-dependencies] 17 | const-serialize = { path = "." } 18 | rand = { workspace = true } 19 | 20 | [features] 21 | test-big-endian = [] 22 | serde = ["dep:serde"] 23 | -------------------------------------------------------------------------------- /packages/const-serialize/tests/tuples.rs: -------------------------------------------------------------------------------- 1 | use const_serialize::{deserialize_const, serialize_const, ConstVec}; 2 | 3 | #[test] 4 | fn test_serialize_const_layout_tuple() { 5 | let mut buf = ConstVec::new(); 6 | buf = serialize_const(&(1234u32, 5678u16), buf); 7 | let buf = buf.read(); 8 | assert_eq!( 9 | deserialize_const!((u32, u16), buf).unwrap().1, 10 | (1234u32, 5678u16) 11 | ); 12 | 13 | let mut buf = ConstVec::new(); 14 | buf = serialize_const(&(1234f64, 5678u16, 90u8), buf); 15 | let buf = buf.read(); 16 | assert_eq!( 17 | deserialize_const!((f64, u16, u8), buf).unwrap().1, 18 | (1234f64, 5678u16, 90u8) 19 | ); 20 | 21 | let mut buf = ConstVec::new(); 22 | buf = serialize_const(&(1234u32, 5678u16, 90u8, 1000000f64), buf); 23 | let buf = buf.read(); 24 | assert_eq!( 25 | deserialize_const!((u32, u16, u8, f64), buf).unwrap().1, 26 | (1234u32, 5678u16, 90u8, 1000000f64) 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /packages/core-macro/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.check.workspace": false, 3 | // "rust-analyzer.check.command": "check alsjdlaskdjljkasd", 4 | "rust-analyzer.check.allTargets": false, 5 | "rust-analyzer.cargo.buildScripts.enable": true, 6 | "rust-analyzer.cargo.buildScripts.overrideCommand": [ 7 | "cargo", 8 | "check", 9 | "--quiet", 10 | // "--package", 11 | // "dioxus-core-macro", 12 | "--message-format", 13 | "json", 14 | "--all-targets" 15 | ], 16 | "rust-analyzer.cargo.buildScripts.rebuildOnSave": false, 17 | "rust-analyzer.cargo.buildScripts.invocationLocation": "root", 18 | "rust-analyzer.cargo.buildScripts.invocationStrategy": "once", 19 | // "rust-analyzer.check.command": "check --package dioxus-core-macro" 20 | } 21 | -------------------------------------------------------------------------------- /packages/core-macro/tests/rsx/trailing-comma-0.rs: -------------------------------------------------------------------------------- 1 | // Given an `rsx!` invocation with a missing trailing comma, 2 | // ensure the stderr output has an informative span. 3 | 4 | use dioxus::prelude::*; 5 | 6 | fn main() { 7 | rsx! { 8 | p { 9 | class: "foo bar" 10 | "Hello world" 11 | } 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /packages/core-macro/tests/rsx/trailing-comma-0.stderr: -------------------------------------------------------------------------------- 1 | error: Attributes must be separated by commas 2 | = help: Did you forget a comma? 3 | --> tests/rsx/trailing-comma-0.rs:9:13 4 | | 5 | 9 | class: "foo bar" 6 | | ^^^^^ 7 | -------------------------------------------------------------------------------- /packages/core-types/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-core-types" 3 | edition = "2021" 4 | version.workspace = true 5 | authors = ["Jonathan Kelley", "Evan Almloff"] 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/DioxusLabs/dioxus/" 8 | homepage = "https://dioxuslabs.com" 9 | description = "CLI Configuration for dioxus-cli" 10 | keywords = ["dom", "ui", "gui", "react", ] 11 | 12 | 13 | [dependencies] 14 | -------------------------------------------------------------------------------- /packages/core-types/src/attributes.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/core-types/src/attributes.rs -------------------------------------------------------------------------------- /packages/core-types/src/bundled.rs: -------------------------------------------------------------------------------- 1 | use std::sync::LazyLock; 2 | 3 | pub fn is_bundled_app() -> bool { 4 | static BUNDLED: LazyLock = LazyLock::new(|| { 5 | // If the env var is set, we're bundled 6 | if std::env::var("DIOXUS_CLI_ENABLED").is_ok() { 7 | return true; 8 | } 9 | 10 | // If the cargo manifest dir is set, we're not bundled. 11 | // Generally this is only set with `cargo run` 12 | if let Ok(path) = std::env::var("CARGO_MANIFEST_DIR") { 13 | if !path.is_empty() { 14 | return false; 15 | } 16 | } 17 | 18 | true 19 | }); 20 | 21 | *BUNDLED 22 | } 23 | -------------------------------------------------------------------------------- /packages/core-types/src/formatter.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::Cow; 2 | 3 | /// Take this type and format it into a Cow<'static, str> 4 | /// 5 | /// This trait exists so libraries like manganis can implement this type for asssets without depending 6 | /// on dioxus-core, which can be heavy in proc macros and build scripts. 7 | /// 8 | /// We don't want a blanket impl for T: Display because that might conflict for the other integral data 9 | /// types of AttributeValue 10 | /// 11 | /// Todo: we might be able to specialize without this just with Display. 12 | pub trait DioxusFormattable { 13 | fn format(&self) -> Cow<'static, str>; 14 | } 15 | -------------------------------------------------------------------------------- /packages/core-types/src/hr_context.rs: -------------------------------------------------------------------------------- 1 | pub trait HotReloadingContext { 2 | fn map_attribute( 3 | element_name_rust: &str, 4 | attribute_name_rust: &str, 5 | ) -> Option<(&'static str, Option<&'static str>)>; 6 | fn map_element(element_name_rust: &str) -> Option<(&'static str, Option<&'static str>)>; 7 | } 8 | 9 | pub struct Empty; 10 | 11 | impl HotReloadingContext for Empty { 12 | fn map_attribute(_: &str, _: &str) -> Option<(&'static str, Option<&'static str>)> { 13 | None 14 | } 15 | 16 | fn map_element(_: &str) -> Option<(&'static str, Option<&'static str>)> { 17 | None 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/core-types/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod bubbles; 2 | pub mod bundled; 3 | pub mod formatter; 4 | pub mod hr_context; 5 | 6 | pub use bubbles::*; 7 | pub use bundled::*; 8 | pub use formatter::*; 9 | pub use hr_context::*; 10 | -------------------------------------------------------------------------------- /packages/core/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.checkOnSave.allTargets": false 3 | } 4 | -------------------------------------------------------------------------------- /packages/core/.vscode/spellright.dict: -------------------------------------------------------------------------------- 1 | Dodrio 2 | VDoms 3 | dom 4 | virtualdom 5 | ns 6 | nohasher 7 | Preact 8 | vnodes 9 | -------------------------------------------------------------------------------- /packages/core/src/launch.rs: -------------------------------------------------------------------------------- 1 | //! This module contains utilities renderers use to integrate with the launch function. 2 | 3 | /// A marker trait for platform configs. We use this marker to 4 | /// make sure that the user doesn't accidentally pass in a config 5 | /// builder instead of the config 6 | pub trait LaunchConfig: 'static {} 7 | 8 | impl LaunchConfig for () {} 9 | -------------------------------------------------------------------------------- /packages/core/tests/.rustfmt.toml: -------------------------------------------------------------------------------- 1 | struct_variant_width = 100 2 | struct_lit_width = 80 3 | -------------------------------------------------------------------------------- /packages/core/tests/attributes_pass.rs: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | /// Make sure that rsx! is parsing templates and their attributes properly 4 | #[test] 5 | fn attributes_pass_properly() { 6 | let h = rsx! { 7 | circle { 8 | cx: 50, 9 | cy: 50, 10 | r: 40, 11 | stroke: "green", 12 | fill: "yellow" 13 | } 14 | }; 15 | 16 | let o = h.unwrap(); 17 | 18 | let template = &o.template; 19 | 20 | assert_eq!(template.attr_paths.len(), 3); 21 | 22 | let _circle = template.roots[0]; 23 | let TemplateNode::Element { attrs, tag, namespace, children } = _circle else { 24 | panic!("Expected an element"); 25 | }; 26 | 27 | assert_eq!(tag, "circle"); 28 | assert_eq!(namespace, Some("http://www.w3.org/2000/svg")); 29 | assert_eq!(children.len(), 0); 30 | assert_eq!(attrs.len(), 5); 31 | } 32 | -------------------------------------------------------------------------------- /packages/core/tests/boolattrs.rs: -------------------------------------------------------------------------------- 1 | use dioxus::dioxus_core::{ElementId, Mutation::*}; 2 | use dioxus::prelude::*; 3 | 4 | #[test] 5 | fn bool_test() { 6 | let mut app = VirtualDom::new(|| rsx!(div { hidden: false })); 7 | 8 | assert_eq!( 9 | app.rebuild_to_vec().edits, 10 | [ 11 | LoadTemplate { index: 0, id: ElementId(1) }, 12 | SetAttribute { 13 | name: "hidden", 14 | value: dioxus_core::AttributeValue::Bool(false), 15 | id: ElementId(1,), 16 | ns: None 17 | }, 18 | AppendChildren { m: 1, id: ElementId(0) }, 19 | ] 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /packages/core/tests/bubble_error.rs: -------------------------------------------------------------------------------- 1 | //! we should properly bubble up errors from components 2 | 3 | use dioxus::prelude::*; 4 | 5 | fn app() -> Element { 6 | let raw = match generation() % 2 { 7 | 0 => "123.123", 8 | 1 => "123.123.123", 9 | _ => unreachable!(), 10 | }; 11 | 12 | let value = raw.parse::().unwrap_or(123.123); 13 | 14 | rsx! { div { "hello {value}" } } 15 | } 16 | 17 | #[test] 18 | fn bubbles_error() { 19 | let mut dom = VirtualDom::new(app); 20 | 21 | { 22 | let _edits = dom.rebuild_to_vec(); 23 | } 24 | 25 | dom.mark_dirty(ScopeId::APP); 26 | 27 | _ = dom.render_immediate_to_vec(); 28 | } 29 | -------------------------------------------------------------------------------- /packages/core/tests/hotreloading.rs: -------------------------------------------------------------------------------- 1 | //! It should be possible to swap out templates at runtime, enabling hotreloading 2 | -------------------------------------------------------------------------------- /packages/core/tests/safety.rs: -------------------------------------------------------------------------------- 1 | //! Tests related to safety of the library. 2 | 3 | use dioxus::prelude::*; 4 | 5 | /// Ensure no issues with not calling rebuild_to_vec 6 | #[test] 7 | fn root_node_isnt_null() { 8 | let dom = VirtualDom::new(|| rsx!("Hello world!")); 9 | 10 | let scope = dom.base_scope(); 11 | 12 | // We haven't built the tree, so trying to get out the root node should fail 13 | assert!(scope.try_root_node().is_none()); 14 | 15 | dom.in_runtime(|| { 16 | // The height should be 0 17 | assert_eq!(ScopeId::ROOT.height(), 0); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /packages/depinfo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "depinfo" 3 | version.workspace = true 4 | edition = "2021" 5 | authors = ["Jonathan Kelley"] 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/DioxusLabs/dioxus/" 8 | homepage = "https://dioxuslabs.com" 9 | description = "Depinfo parser for Rust" 10 | keywords = ["rustc", "cargo", "dep-info" ] 11 | 12 | [dependencies] 13 | thiserror = { workspace = true } 14 | 15 | -------------------------------------------------------------------------------- /packages/depinfo/README.md: -------------------------------------------------------------------------------- 1 | # Rustc Dep-Info Parser 2 | 3 | This crate parses the output of rustc's `.d` dep-info file. It is used by the hot-reloading engine and other libraries to provide higher quality dependency analysis for the user's project. 4 | 5 | ## License 6 | 7 | This project is licensed under either the [MIT license] or the [Apache-2 License]. 8 | 9 | [apache-2 license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-APACHE 10 | [mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT 11 | 12 | Unless you explicitly state otherwise, any contribution intentionally submitted 13 | for inclusion in Dioxus by you, shall be licensed as MIT or Apache-2, without any additional 14 | terms or conditions. 15 | -------------------------------------------------------------------------------- /packages/desktop/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // "rust-analyzer.cargo.target": "aarch64-linux-android" 3 | } 4 | -------------------------------------------------------------------------------- /packages/desktop/architecure/Desktop Event Architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/desktop/architecure/Desktop Event Architecture.png -------------------------------------------------------------------------------- /packages/desktop/src/android_sync_lock.rs: -------------------------------------------------------------------------------- 1 | /// This is a hack to get around the fact that wry is currently not thread safe on android 2 | /// 3 | /// We want to acquire this mutex before doing anything with the virtualdom directly 4 | pub fn android_runtime_lock() -> std::sync::MutexGuard<'static, ()> { 5 | use std::sync::{Mutex, OnceLock}; 6 | 7 | static RUNTIME_LOCK: OnceLock> = OnceLock::new(); 8 | 9 | RUNTIME_LOCK.get_or_init(|| Mutex::new(())).lock().unwrap() 10 | } 11 | -------------------------------------------------------------------------------- /packages/desktop/src/assets/default_icon.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/desktop/src/assets/default_icon.bin -------------------------------------------------------------------------------- /packages/desktop/src/assets/default_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/desktop/src/assets/default_icon.png -------------------------------------------------------------------------------- /packages/desktop/src/assets/prod.index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dioxus app 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/desktop/src/js/hash.txt: -------------------------------------------------------------------------------- 1 | [16018260687765471498] -------------------------------------------------------------------------------- /packages/desktop/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "CommonJS", 4 | "lib": [ 5 | "ES2015", 6 | "DOM", 7 | "dom", 8 | "dom.iterable", 9 | "ESNext" 10 | ], 11 | "noImplicitAny": true, 12 | "removeComments": true, 13 | "preserveConstEnums": true, 14 | }, 15 | "exclude": [ 16 | "**/*.spec.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/devtools-types/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-devtools-types" 3 | edition = "2021" 4 | version.workspace = true 5 | authors = ["Jonathan Kelley", "Evan Almloff"] 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/DioxusLabs/dioxus/" 8 | homepage = "https://dioxuslabs.com" 9 | description = "CLI Configuration for dioxus-cli" 10 | keywords = ["dom", "ui", "gui", "react", ] 11 | 12 | [dependencies] 13 | serde = { workspace = true, features = ["derive"] } 14 | dioxus-core = { workspace = true, features = ["serialize"] } 15 | subsecond-types = { workspace = true } 16 | -------------------------------------------------------------------------------- /packages/document/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-document" 3 | edition = "2021" 4 | version.workspace = true 5 | authors = ["Jonathan Kelley", "Evan Almloff"] 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/DioxusLabs/dioxus/" 8 | homepage = "https://dioxuslabs.com" 9 | description = "CLI Configuration for dioxus-cli" 10 | keywords = ["dom", "ui", "gui", "react"] 11 | 12 | [dependencies] 13 | dioxus-core = { workspace = true } 14 | dioxus-core-types = { workspace = true } 15 | dioxus-core-macro = { workspace = true } 16 | dioxus-html = { workspace = true } 17 | tracing = { workspace = true } 18 | serde = { workspace = true } 19 | serde_json = { workspace = true } 20 | futures-channel = { workspace = true } 21 | futures-util = { workspace = true } 22 | generational-box = { workspace = true } 23 | 24 | [build-dependencies] 25 | lazy-js-bundle = { workspace = true } 26 | 27 | [dev-dependencies] 28 | dioxus = { workspace = true } 29 | -------------------------------------------------------------------------------- /packages/document/assets/script.js: -------------------------------------------------------------------------------- 1 | // this script is included as an asset!() for a test 2 | -------------------------------------------------------------------------------- /packages/document/assets/style.css: -------------------------------------------------------------------------------- 1 | /* this stylesheet is included as an asset!() for a test */ 2 | -------------------------------------------------------------------------------- /packages/document/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // If any TS files change, re-run the build script 3 | lazy_js_bundle::LazyTypeScriptBindings::new() 4 | .with_watching("./src/ts") 5 | .with_binding("./src/ts/head.ts", "./src/js/head.js") 6 | .run(); 7 | } 8 | -------------------------------------------------------------------------------- /packages/document/src/js/hash.txt: -------------------------------------------------------------------------------- 1 | [5568016277461366671, 8375185156499858125] -------------------------------------------------------------------------------- /packages/document/src/js/head.js: -------------------------------------------------------------------------------- 1 | var createElementInHead=function(tag,attributes,children){const element=document.createElement(tag);for(let[key,value]of attributes)element.setAttribute(key,value);if(children)element.appendChild(document.createTextNode(children));document.head.appendChild(element)};window.createElementInHead=createElementInHead; 2 | -------------------------------------------------------------------------------- /packages/document/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | mod document; 4 | mod elements; 5 | mod error; 6 | mod eval; 7 | 8 | pub use document::*; 9 | pub use elements::*; 10 | pub use error::*; 11 | pub use eval::*; 12 | 13 | /// Get the document provider for the current platform or a no-op provider if the platform doesn't document functionality. 14 | pub fn document() -> Rc { 15 | match dioxus_core::prelude::try_consume_context::>() { 16 | Some(document) => document, 17 | None => { 18 | tracing::error!( 19 | "Unable to find a document in the renderer. Using the default no-op document." 20 | ); 21 | Rc::new(NoOpDocument) 22 | } 23 | } 24 | } 25 | 26 | /// Evaluate some javascript in the current document 27 | #[doc = include_str!("../docs/eval.md")] 28 | #[doc(alias = "javascript")] 29 | pub fn eval(script: &str) -> Eval { 30 | document().eval(script.to_string()) 31 | } 32 | -------------------------------------------------------------------------------- /packages/document/src/ts/.gitignore: -------------------------------------------------------------------------------- 1 | # please dont accidentally run tsc and commit your js in this dir. 2 | *.js 3 | 4 | -------------------------------------------------------------------------------- /packages/document/src/ts/head.ts: -------------------------------------------------------------------------------- 1 | // Helper functions for working with the document head 2 | 3 | function createElementInHead( 4 | tag: string, 5 | attributes: [string, string][], 6 | children: string | null 7 | ): void { 8 | const element = document.createElement(tag); 9 | for (const [key, value] of attributes) { 10 | element.setAttribute(key, value); 11 | } 12 | if (children) { 13 | element.appendChild(document.createTextNode(children)); 14 | } 15 | document.head.appendChild(element); 16 | } 17 | 18 | // @ts-ignore 19 | window.createElementInHead = createElementInHead; 20 | -------------------------------------------------------------------------------- /packages/document/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "CommonJS", 4 | "lib": [ 5 | "ES2015", 6 | "DOM", 7 | "dom", 8 | "dom.iterable", 9 | "ESNext" 10 | ], 11 | "noImplicitAny": true, 12 | "removeComments": true, 13 | "preserveConstEnums": true, 14 | }, 15 | "exclude": [ 16 | "**/*.spec.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/dx-wire-format/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-dx-wire-format" 3 | edition = "2021" 4 | version.workspace = true 5 | publish = true 6 | authors = ["Jonathan Kelley"] 7 | description = "Wire format for the Dioxus CLI" 8 | license = "MIT OR Apache-2.0" 9 | repository = "https://github.com/DioxusLabs/dioxus/" 10 | homepage = "https://dioxuslabs.com/learn/0.6/" 11 | keywords = ["dom", "ui", "gui", "react", "wasm"] 12 | rust-version = "1.79.0" 13 | 14 | [dependencies] 15 | serde = { workspace = true, features = ["derive"] } 16 | serde_json = { workspace = true } 17 | cargo_metadata = { workspace = true } 18 | -------------------------------------------------------------------------------- /packages/extension/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /**@type {import('eslint').Linter.Config} */ 2 | // eslint-disable-next-line no-undef 3 | module.exports = { 4 | root: true, 5 | parser: '@typescript-eslint/parser', 6 | plugins: [ 7 | '@typescript-eslint', 8 | ], 9 | extends: [ 10 | 'eslint:recommended', 11 | 'plugin:@typescript-eslint/recommended', 12 | ], 13 | rules: { 14 | 'semi': [2, "always"], 15 | '@typescript-eslint/no-unused-vars': 0, 16 | '@typescript-eslint/no-explicit-any': 0, 17 | '@typescript-eslint/explicit-module-boundary-types': 0, 18 | '@typescript-eslint/no-non-null-assertion': 0, 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /packages/extension/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | Thumbs.db 4 | */node_modules/ 5 | node_modules/ 6 | */out/ 7 | out/ 8 | */.vs/ 9 | .vs/ 10 | tsconfig.lsif.json 11 | *.lsif 12 | *.db 13 | *.vsix 14 | pkg/ 15 | -------------------------------------------------------------------------------- /packages/extension/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/extension/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-ext" 3 | version = { workspace = true } 4 | edition = "2021" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | wasm-bindgen = { workspace = true } 11 | dioxus-autofmt = { workspace = true } 12 | dioxus-rsx-rosetta = { workspace = true } 13 | html_parser = { workspace = true } 14 | syn = { workspace = true } 15 | 16 | [lib] 17 | crate-type = ["cdylib", "rlib"] 18 | -------------------------------------------------------------------------------- /packages/extension/DEV.md: -------------------------------------------------------------------------------- 1 | 2 | ## packaging 3 | 4 | ``` 5 | $ cd myExtension 6 | $ vsce package 7 | # myExtension.vsix generated 8 | $ vsce publish 9 | # .myExtension published to VS Code Marketplace 10 | ``` 11 | -------------------------------------------------------------------------------- /packages/extension/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dioxus-ext", 3 | "version": "0.1.0", 4 | "files": [ 5 | "dioxus_ext_bg.wasm", 6 | "dioxus_ext.js", 7 | "dioxus_ext.d.ts", 8 | "dioxus_ext_bg.js", 9 | "dioxus_ext_bg.d.ts", 10 | "dioxus_ext_bg.wasm.d.ts" 11 | ], 12 | "main": "dioxus_ext.js", 13 | "types": "dioxus_ext.d.ts" 14 | } 15 | -------------------------------------------------------------------------------- /packages/extension/static/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/extension/static/icon.png -------------------------------------------------------------------------------- /packages/extension/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2021", 5 | "lib": [ 6 | "ES2021" 7 | ], 8 | "outDir": "out", 9 | "sourceMap": true, 10 | "strict": true, 11 | "rootDir": "src" 12 | }, 13 | "exclude": [ 14 | "node_modules", 15 | ".vscode-test", 16 | "out" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/fullstack-hooks/src/hooks/mod.rs: -------------------------------------------------------------------------------- 1 | mod server_cached; 2 | pub use server_cached::*; 3 | mod server_future; 4 | pub use server_future::*; 5 | -------------------------------------------------------------------------------- /packages/fullstack-hooks/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(missing_docs)] 2 | #![doc = include_str!("../README.md")] 3 | 4 | mod hooks; 5 | pub use hooks::*; 6 | mod streaming; 7 | pub use streaming::*; 8 | -------------------------------------------------------------------------------- /packages/fullstack-protocol/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-fullstack-protocol" 3 | edition = "2021" 4 | version.workspace = true 5 | authors = ["Jonathan Kelley", "Evan Almloff"] 6 | description = "Fullstack protocol for Dioxus: Build fullstack web, desktop, and mobile apps with a single codebase." 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | homepage = "https://dioxuslabs.com" 10 | keywords = ["web", "desktop", "mobile", "gui", "server"] 11 | resolver = "2" 12 | 13 | [dependencies] 14 | ciborium = { workspace = true } 15 | dioxus-core = { workspace = true } 16 | base64 = { workspace = true } 17 | serde = { workspace = true } 18 | tracing = { workspace = true } 19 | 20 | [features] 21 | web = [] 22 | -------------------------------------------------------------------------------- /packages/fullstack-protocol/README.md: -------------------------------------------------------------------------------- 1 | # Fullstack Protocol 2 | 3 | Dioxus-fullstack-protocol is the internal protocol the dioxus web and server renderers use to communicate with each other in dioxus fullstack. It is used to send futures and values from the server to the client during fullstack rendering. 4 | -------------------------------------------------------------------------------- /packages/fullstack/.gitignore: -------------------------------------------------------------------------------- 1 | target -------------------------------------------------------------------------------- /packages/fullstack/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")] 3 | #![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")] 4 | #![deny(missing_docs)] 5 | #![cfg_attr(docsrs, feature(doc_cfg))] 6 | 7 | #[cfg(all(feature = "web", feature = "document"))] 8 | mod web; 9 | 10 | #[cfg(all(feature = "web", feature = "document"))] 11 | pub use web::FullstackWebDocument; 12 | 13 | #[cfg(feature = "server")] 14 | pub use dioxus_server::*; 15 | 16 | /// A prelude of commonly used items in dioxus-fullstack. 17 | pub mod prelude { 18 | pub use dioxus_fullstack_hooks::*; 19 | 20 | pub use dioxus_server_macro::*; 21 | pub use server_fn::{self, ServerFn as _, ServerFnError}; 22 | 23 | #[cfg(feature = "server")] 24 | pub use dioxus_server::prelude::*; 25 | } 26 | -------------------------------------------------------------------------------- /packages/generational-box/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "generational-box" 3 | authors = ["Evan Almloff"] 4 | version = { workspace = true } 5 | edition = "2021" 6 | description = "A box backed by a generational runtime" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | keywords = ["generational", "box", "memory", "allocator"] 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | parking_lot = { workspace = true } 14 | tracing = { workspace = true } 15 | 16 | [dev-dependencies] 17 | rand = { workspace = true } 18 | criterion = { workspace = true } 19 | 20 | [features] 21 | debug_borrows = [] 22 | debug_ownership = [] 23 | 24 | [[bench]] 25 | name = "lock" 26 | harness = false 27 | 28 | [package.metadata.docs.rs] 29 | cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"] 30 | -------------------------------------------------------------------------------- /packages/generational-box/tests/reused.rs: -------------------------------------------------------------------------------- 1 | //! This test needs to be in its own file such that it doesn't share 2 | //! an address space with the other tests. 3 | //! 4 | //! That will cause random failures on CI. 5 | 6 | use generational_box::{Storage, SyncStorage, UnsyncStorage}; 7 | 8 | #[test] 9 | fn reused() { 10 | fn reused_test>() { 11 | let first_ptr; 12 | { 13 | let owner = S::owner(); 14 | first_ptr = owner.insert(1).raw_ptr(); 15 | drop(owner); 16 | } 17 | { 18 | let owner = S::owner(); 19 | let second_ptr = owner.insert(1234).raw_ptr(); 20 | assert_eq!(first_ptr, second_ptr); 21 | drop(owner); 22 | } 23 | } 24 | 25 | reused_test::(); 26 | reused_test::(); 27 | } 28 | -------------------------------------------------------------------------------- /packages/history/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-history" 3 | edition = "2021" 4 | version = { workspace = true } 5 | authors = ["Jonathan Kelley"] 6 | description = "History provider for dioxus" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | homepage = "https://dioxuslabs.com" 10 | keywords = ["dom", "ui", "gui", "react"] 11 | 12 | 13 | [dependencies] 14 | dioxus-core = { workspace = true } 15 | tracing = { workspace = true } 16 | 17 | [dev-dependencies] 18 | dioxus = { workspace = true, features = ["router"] } 19 | -------------------------------------------------------------------------------- /packages/hooks/src/use_after_suspense_resolved.rs: -------------------------------------------------------------------------------- 1 | use dioxus_core::{prelude::suspense_context, use_hook}; 2 | 3 | /// Run a closure after the suspense boundary this is under is resolved. The 4 | /// closure will be run immediately if the suspense boundary is already resolved 5 | /// or the scope is not under a suspense boundary. 6 | pub fn use_after_suspense_resolved(suspense_resolved: impl FnOnce() + 'static) { 7 | use_hook(|| { 8 | // If this is under a suspense boundary, we need to check if it is resolved 9 | match suspense_context() { 10 | Some(context) => { 11 | // If it is suspended, run the closure after the suspense is resolved 12 | context.after_suspense_resolved(suspense_resolved) 13 | } 14 | None => { 15 | // Otherwise, just run the resolved closure immediately 16 | suspense_resolved(); 17 | } 18 | } 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /packages/hooks/src/use_hook_did_run.rs: -------------------------------------------------------------------------------- 1 | use dioxus_core::prelude::*; 2 | use dioxus_signals::{CopyValue, Writable}; 3 | 4 | /// A hook that uses before/after lifecycle hooks to determine if the hook was run 5 | #[doc = include_str!("../docs/rules_of_hooks.md")] 6 | #[doc = include_str!("../docs/moving_state_around.md")] 7 | pub fn use_hook_did_run(mut handler: impl FnMut(bool) + 'static) { 8 | let mut did_run_ = use_hook(|| CopyValue::new(false)); 9 | 10 | // Before render always set the value to false 11 | use_before_render(move || did_run_.set(false)); 12 | 13 | // Only when this hook is hit do we want to set the value to true 14 | did_run_.set(true); 15 | 16 | // After render, we can check if the hook was run 17 | use_after_render(move || handler(did_run_())); 18 | } 19 | -------------------------------------------------------------------------------- /packages/hooks/src/use_memo.rs: -------------------------------------------------------------------------------- 1 | use crate::use_callback; 2 | use dioxus_core::prelude::*; 3 | use dioxus_signals::Memo; 4 | 5 | #[doc = include_str!("../docs/derived_state.md")] 6 | #[doc = include_str!("../docs/rules_of_hooks.md")] 7 | #[doc = include_str!("../docs/moving_state_around.md")] 8 | #[track_caller] 9 | pub fn use_memo(mut f: impl FnMut() -> R + 'static) -> Memo { 10 | let callback = use_callback(move |_| f()); 11 | let caller = std::panic::Location::caller(); 12 | #[allow(clippy::redundant_closure)] 13 | use_hook(|| Memo::new_with_location(move || callback(()), caller)) 14 | } 15 | -------------------------------------------------------------------------------- /packages/hooks/src/use_on_destroy.rs: -------------------------------------------------------------------------------- 1 | use dioxus_core::prelude::use_drop; 2 | 3 | #[deprecated(note = "Use `use_drop` instead, which has the same functionality.")] 4 | pub fn use_on_unmount(destroy: D) { 5 | use_drop(destroy); 6 | } 7 | -------------------------------------------------------------------------------- /packages/html-internal-macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-html-internal-macro" 3 | version = { workspace = true } 4 | edition = "2021" 5 | repository = "https://github.com/DioxusLabs/dioxus/" 6 | homepage = "https://dioxuslabs.com" 7 | keywords = ["dom", "ui", "gui", "react", "liveview"] 8 | license = "MIT OR Apache-2.0" 9 | description = "HTML function macros for Dioxus" 10 | 11 | 12 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 13 | 14 | [dependencies] 15 | proc-macro2 = { workspace = true } 16 | syn = { workspace = true, features = ["full"] } 17 | quote = { workspace = true } 18 | convert_case = { workspace = true } 19 | 20 | [lib] 21 | proc-macro = true 22 | 23 | [[test]] 24 | name = "tests" 25 | path = "tests/progress.rs" 26 | 27 | [dev-dependencies] 28 | trybuild = { workspace = true, features = ["diff"] } 29 | -------------------------------------------------------------------------------- /packages/html-internal-macro/tests/01-simple.rs: -------------------------------------------------------------------------------- 1 | fn main() {} 2 | -------------------------------------------------------------------------------- /packages/html-internal-macro/tests/progress.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn tests() { 3 | let t = trybuild::TestCases::new(); 4 | t.pass("tests/01-simple.rs"); 5 | } 6 | -------------------------------------------------------------------------------- /packages/html/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "CommonJS", 4 | "lib": [ 5 | "ES2015", 6 | "DOM", 7 | "dom", 8 | "dom.iterable", 9 | "ESNext" 10 | ], 11 | "noImplicitAny": true, 12 | "removeComments": true, 13 | "preserveConstEnums": true, 14 | }, 15 | "exclude": [ 16 | "**/*.spec.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/interpreter/.gitignore: -------------------------------------------------------------------------------- 1 | gen2/ 2 | -------------------------------------------------------------------------------- /packages/interpreter/NOTES.md: -------------------------------------------------------------------------------- 1 | # Notes on the web implementation 2 | 3 | Here's some useful resources if you ever need to splunk into the intricacies of how events are handled in HTML: 4 | 5 | 6 | - Not all event handlers are sync: https://w3c.github.io/uievents/#sync-async 7 | - Some attributes are truthy: https://github.com/facebook/react/blob/8b88ac2592c5f555f315f9440cbb665dd1e7457a/packages/react-dom/src/shared/DOMProperty.js#L352-L364 8 | -------------------------------------------------------------------------------- /packages/interpreter/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // If any TS files change, re-run the build script 3 | lazy_js_bundle::LazyTypeScriptBindings::new() 4 | .with_watching("./src/ts") 5 | .with_binding("./src/ts/common.ts", "./src/js/common.js") 6 | .with_binding("./src/ts/native.ts", "./src/js/native.js") 7 | .with_binding("./src/ts/core.ts", "./src/js/core.js") 8 | .with_binding("./src/ts/hydrate.ts", "./src/js/hydrate.js") 9 | .with_binding("./src/ts/patch_console.ts", "./src/js/patch_console.js") 10 | .with_binding( 11 | "./src/ts/initialize_streaming.ts", 12 | "./src/js/initialize_streaming.js", 13 | ) 14 | .run(); 15 | } 16 | -------------------------------------------------------------------------------- /packages/interpreter/src/js/hash.txt: -------------------------------------------------------------------------------- 1 | [6449103750905854967, 17669692872757955279, 13069001215487072322, 11420464406527728232, 3770103091118609057, 5444526391971481782, 15100726369461302769, 5052021921702764563, 10988859153374944111, 18245313843715340442] -------------------------------------------------------------------------------- /packages/interpreter/src/js/hydrate.js: -------------------------------------------------------------------------------- 1 | function register_rehydrate_chunk_for_streaming(callback){return register_rehydrate_chunk_for_streaming_debug(callback)}function register_rehydrate_chunk_for_streaming_debug(callback){window.hydration_callback=callback;for(let i=0;i{const decoded=atob(data),bytes=Uint8Array.from(decoded,(c)=>c.charCodeAt(0));if(window.hydration_callback)window.hydration_callback(id,bytes,debug_types,debug_locations);else window.hydrate_queue.push([id,bytes,debug_types,debug_locations])}; 2 | -------------------------------------------------------------------------------- /packages/interpreter/src/js/patch_console.js: -------------------------------------------------------------------------------- 1 | function monkeyPatchConsole(ws){const console=window.console,log=console.log,info=console.info,warn=console.warn,error=console.error,debug=console.debug;console.log=function(...args){if(ws.readyState===WebSocket.OPEN)ws.send(JSON.stringify({Log:{level:"log",messages:args}}));log.apply(console,args)},console.info=function(...args){if(ws.readyState===WebSocket.OPEN)ws.send(JSON.stringify({Log:{level:"info",messages:args}}));info.apply(console,args)},console.warn=function(...args){if(ws.readyState===WebSocket.OPEN)ws.send(JSON.stringify({Log:{level:"warn",messages:args}}));warn.apply(console,args)},console.error=function(...args){if(ws.readyState===WebSocket.OPEN)ws.send(JSON.stringify({Log:{level:"error",messages:args}}));error.apply(console,args)},console.debug=function(...args){if(ws.readyState===WebSocket.OPEN)ws.send(JSON.stringify({Log:{level:"debug",messages:args}}));debug.apply(console,args)}}export{monkeyPatchConsole}; 2 | -------------------------------------------------------------------------------- /packages/interpreter/src/ts/.gitignore: -------------------------------------------------------------------------------- 1 | # please dont accidentally run tsc and commit your js in this dir. 2 | *.js 3 | 4 | -------------------------------------------------------------------------------- /packages/interpreter/src/ts/common.ts: -------------------------------------------------------------------------------- 1 | export { setAttributeInner } from "./set_attribute"; 2 | export { retrieveFormValues } from "./form"; 3 | -------------------------------------------------------------------------------- /packages/interpreter/src/ts/hydrate.ts: -------------------------------------------------------------------------------- 1 | import "./hydrate_types"; 2 | import { HydrationCallback } from "./hydrate_types"; 3 | 4 | export function register_rehydrate_chunk_for_streaming(callback: HydrationCallback): void { 5 | return register_rehydrate_chunk_for_streaming_debug(callback); 6 | } 7 | 8 | export function register_rehydrate_chunk_for_streaming_debug( 9 | callback: HydrationCallback 10 | ): void { 11 | window.hydration_callback = callback; 12 | for (let i = 0; i < window.hydrate_queue.length; i++) { 13 | const [id, data, debug_types, debug_locations] = window.hydrate_queue[i]; 14 | window.hydration_callback(id, data, debug_types, debug_locations); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/interpreter/src/ts/hydrate_types.ts: -------------------------------------------------------------------------------- 1 | export { }; 2 | 3 | export type HydrationCallback = ( 4 | id: number[], 5 | data: Uint8Array, 6 | debug_types: string[] | null, 7 | debug_locations: string[] | null 8 | ) => void; 9 | 10 | declare global { 11 | interface Window { 12 | hydrate_queue: [number[], Uint8Array, string[] | null, string[] | null][]; 13 | hydration_callback: 14 | | null 15 | | HydrationCallback; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/interpreter/src/ts/initialize_streaming.ts: -------------------------------------------------------------------------------- 1 | import "./hydrate_types"; 2 | 3 | // Chunks may load before the wasm has loaded and the callback to hydrate the dom is registered. We queue up hydration ids and data until the wasm is ready 4 | window.hydrate_queue = []; 5 | 6 | // @ts-ignore 7 | window.dx_hydrate = ( 8 | id: number[], 9 | data: string, 10 | debug_types: string[] | null, 11 | debug_locations: string[] | null 12 | ) => { 13 | // First convert the base64 encoded string to a Uint8Array 14 | const decoded = atob(data); 15 | const bytes = Uint8Array.from(decoded, (c) => c.charCodeAt(0)); 16 | if (window.hydration_callback) { 17 | window.hydration_callback(id, bytes, debug_types, debug_locations); 18 | } else { 19 | window.hydrate_queue.push([id, bytes, debug_types, debug_locations]); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /packages/interpreter/tests/e2e.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that the interpreter loads, has no errors, and writes mutations 2 | -------------------------------------------------------------------------------- /packages/interpreter/tests/serialize.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that events are serialized and deserialized correctly. 2 | -------------------------------------------------------------------------------- /packages/interpreter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "CommonJS", 4 | "lib": [ 5 | "ES2015", 6 | "DOM", 7 | "dom", 8 | "dom.iterable", 9 | "ESNext" 10 | ], 11 | "noImplicitAny": true, 12 | "removeComments": true, 13 | "preserveConstEnums": true, 14 | "typeRoots": [".src/ts/types"] 15 | }, 16 | "exclude": [ 17 | "**/*.spec.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/isrg/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-isrg" 3 | edition = "2021" 4 | version.workspace = true 5 | authors = ["Jonathan Kelley", "Evan Almloff"] 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/DioxusLabs/dioxus/" 8 | homepage = "https://dioxuslabs.com" 9 | description = "CLI Configuration for dioxus-cli" 10 | keywords = ["dom", "ui", "gui", "react"] 11 | 12 | [dependencies] 13 | chrono = { workspace = true } 14 | http = { workspace = true } 15 | thiserror = { workspace = true } 16 | rustc-hash = { workspace = true } 17 | lru = { workspace = true } 18 | tracing = { workspace = true } 19 | walkdir = { workspace = true } 20 | -------------------------------------------------------------------------------- /packages/lazy-js-bundle/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lazy-js-bundle" 3 | version = { workspace = true } 4 | edition = "2021" 5 | authors = ["Jonathan Kelley"] 6 | description = "A codegen library to bundle TypeScript into JavaScript without requiring a bundler to be installed" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | homepage = "https://dioxuslabs.com" 10 | documentation = "https://docs.rs/dioxus" 11 | keywords = ["ts", "codegen", "typescript", "javascript", "wasm"] 12 | -------------------------------------------------------------------------------- /packages/liveview/examples/axum.rs: -------------------------------------------------------------------------------- 1 | use axum::Router; 2 | use dioxus::prelude::*; 3 | use dioxus_liveview::LiveviewRouter; 4 | 5 | fn app() -> Element { 6 | let mut num = use_signal(|| 0); 7 | 8 | rsx! { 9 | div { 10 | "hello axum! {num}" 11 | button { onclick: move |_| num += 1, "Increment" } 12 | } 13 | } 14 | } 15 | 16 | #[tokio::main] 17 | async fn main() { 18 | dioxus::logger::initialize_default(); 19 | 20 | let addr: std::net::SocketAddr = ([127, 0, 0, 1], 3030).into(); 21 | 22 | let app = Router::new().with_app("/", app); 23 | 24 | println!("Listening on http://{addr}"); 25 | 26 | let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); 27 | axum::serve(listener, app.into_make_service()) 28 | .await 29 | .unwrap(); 30 | } 31 | -------------------------------------------------------------------------------- /packages/liveview/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dioxus app 5 | 6 | 7 | 8 |
9 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /packages/manganis/manganis-core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "manganis-core" 3 | edition = "2021" 4 | version = { workspace = true } 5 | authors = ["Jonathan Kelley"] 6 | description = "core for manganis" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | homepage = "https://dioxuslabs.com" 10 | keywords = ["dom", "ui", "gui", "assets"] 11 | 12 | 13 | # be careful with dependencies you add here - these need to get compiled for the proc macro and therefore 14 | # prevent the main code from compiling! 15 | [dependencies] 16 | serde = { workspace = true, features = ["derive"] } 17 | const-serialize = { workspace = true, features = ["serde"] } 18 | dioxus-core-types = { workspace = true, optional = true } 19 | dioxus-cli-config = { workspace = true, optional = true } 20 | 21 | [dev-dependencies] 22 | manganis = { workspace = true } 23 | dioxus = { workspace = true } 24 | 25 | [features] 26 | dioxus = ["dep:dioxus-core-types", "dep:dioxus-cli-config"] 27 | -------------------------------------------------------------------------------- /packages/manganis/manganis-core/assets/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/manganis/manganis-core/assets/image.png -------------------------------------------------------------------------------- /packages/manganis/manganis-core/assets/script.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/manganis/manganis-core/assets/script.js -------------------------------------------------------------------------------- /packages/manganis/manganis-core/assets/style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/manganis/manganis-core/assets/style.css -------------------------------------------------------------------------------- /packages/manganis/manganis-core/src/folder.rs: -------------------------------------------------------------------------------- 1 | use const_serialize::SerializeConst; 2 | 3 | use crate::AssetOptions; 4 | 5 | /// The builder for a folder asset. 6 | #[derive( 7 | Debug, 8 | Eq, 9 | PartialEq, 10 | PartialOrd, 11 | Clone, 12 | Copy, 13 | Hash, 14 | SerializeConst, 15 | serde::Serialize, 16 | serde::Deserialize, 17 | )] 18 | pub struct FolderAssetOptions {} 19 | 20 | impl Default for FolderAssetOptions { 21 | fn default() -> Self { 22 | Self::new() 23 | } 24 | } 25 | 26 | impl FolderAssetOptions { 27 | /// Create a new folder asset using the builder 28 | pub const fn new() -> Self { 29 | Self {} 30 | } 31 | 32 | /// Convert the options into options for a generic asset 33 | pub const fn into_asset_options(self) -> AssetOptions { 34 | AssetOptions::Folder(self) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/manganis/manganis-core/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod folder; 2 | pub use folder::*; 3 | 4 | mod images; 5 | pub use images::*; 6 | 7 | mod options; 8 | pub use options::*; 9 | 10 | mod css; 11 | pub use css::*; 12 | 13 | mod js; 14 | pub use js::*; 15 | 16 | mod asset; 17 | pub use asset::*; 18 | -------------------------------------------------------------------------------- /packages/manganis/manganis-macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "manganis-macro" 3 | version.workspace = true 4 | edition = "2021" 5 | authors = ["Evan Almloff"] 6 | description = "Ergonomic, automatic, cross crate asset collection and optimization" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/manganis/" 9 | homepage = "https://dioxuslabs.com" 10 | keywords = ["assets"] 11 | 12 | [lib] 13 | proc-macro = true 14 | 15 | # be careful with dependencies you add here - these need to get compiled for the proc macro and therefore 16 | # prevent the main code from compiling! 17 | [dependencies] 18 | proc-macro2 = { workspace = true } 19 | quote = { workspace = true } 20 | syn = { workspace = true, features = ["full", "extra-traits"] } 21 | manganis-core = { workspace = true } 22 | dunce = { workspace = true } 23 | macro-string = { workspace = true } 24 | 25 | [features] 26 | default = [] 27 | 28 | [dev-dependencies] 29 | manganis = { workspace = true } 30 | -------------------------------------------------------------------------------- /packages/manganis/manganis-macro/README.md: -------------------------------------------------------------------------------- 1 | # Manganis Macro 2 | 3 | This crate contains the macro used to interact with the Manganis asset system. 4 | -------------------------------------------------------------------------------- /packages/manganis/manganis-macro/assets/asset.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/manganis/manganis-macro/assets/asset.txt -------------------------------------------------------------------------------- /packages/manganis/manganis-macro/assets/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/manganis/manganis-macro/assets/image.png -------------------------------------------------------------------------------- /packages/manganis/manganis-macro/assets/manganis_macro.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/manganis/manganis-macro/assets/manganis_macro.dat -------------------------------------------------------------------------------- /packages/manganis/manganis-macro/assets/script.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/manganis/manganis-macro/assets/script.js -------------------------------------------------------------------------------- /packages/manganis/manganis-macro/assets/style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/manganis/manganis-macro/assets/style.css -------------------------------------------------------------------------------- /packages/manganis/manganis/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | # Manganese is a rusting catalyst. Manganis makes it faster to collect rust assets (and has almost no google search results) 3 | name = "manganis" 4 | version.workspace = true 5 | authors = ["Evan Almloff"] 6 | edition = "2021" 7 | description = "Ergonomic, automatic, cross crate asset collection and optimization" 8 | license = "MIT OR Apache-2.0" 9 | repository = "https://github.com/DioxusLabs/manganis/" 10 | homepage = "https://dioxuslabs.com" 11 | keywords = ["assets"] 12 | 13 | [lib] 14 | 15 | [dependencies] 16 | const-serialize = { workspace = true } 17 | manganis-core = { workspace = true } 18 | manganis-macro = { workspace = true } 19 | 20 | [features] 21 | default = [] 22 | dioxus = ["manganis-core/dioxus"] 23 | -------------------------------------------------------------------------------- /packages/manganis/manganis/assets/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/manganis/manganis/assets/image.png -------------------------------------------------------------------------------- /packages/manganis/manganis/assets/script.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/manganis/manganis/assets/script.js -------------------------------------------------------------------------------- /packages/manganis/manganis/assets/style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/manganis/manganis/assets/style.css -------------------------------------------------------------------------------- /packages/manganis/manganis/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![deny(missing_docs)] 3 | 4 | #[doc(hidden)] 5 | pub mod macro_helpers; 6 | pub use manganis_macro::{asset, css_module}; 7 | 8 | pub use manganis_core::{ 9 | Asset, AssetOptions, BundledAsset, CssAssetOptions, CssModuleAssetOptions, FolderAssetOptions, 10 | ImageAssetOptions, ImageFormat, ImageSize, JsAssetOptions, 11 | }; 12 | -------------------------------------------------------------------------------- /packages/mobile/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = [ 3 | "aarch64-apple-ios", 4 | "aarch64-linux-android" 5 | ] 6 | -------------------------------------------------------------------------------- /packages/mobile/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.inlayHints.enable": true, 3 | "rust-analyzer.checkOnSave.allTargets": true, 4 | } 5 | -------------------------------------------------------------------------------- /packages/mobile/Makefile.toml: -------------------------------------------------------------------------------- 1 | [tasks.test] 2 | command = "cargo" 3 | args = [ 4 | "test", 5 | "--no-run", 6 | ] 7 | 8 | -------------------------------------------------------------------------------- /packages/playwright-tests/.gitignore: -------------------------------------------------------------------------------- 1 | playwright-report 2 | /web/dist/ 3 | -------------------------------------------------------------------------------- /packages/playwright-tests/barebones-template/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target 4 | .DS_Store 5 | 6 | # These are backup files generated by rustfmt 7 | **/*.rs.bk 8 | -------------------------------------------------------------------------------- /packages/playwright-tests/barebones-template/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "barebones-template-test" 3 | version = "0.1.0" 4 | authors = ["Jonathan Kelley "] 5 | edition = "2021" 6 | publish = false 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | dioxus = { workspace = true, features = [] } 12 | 13 | [features] 14 | default = ["web"] 15 | web = ["dioxus/web"] 16 | desktop = ["dioxus/desktop"] 17 | mobile = ["dioxus/mobile"] 18 | -------------------------------------------------------------------------------- /packages/playwright-tests/barebones-template/Dioxus.toml: -------------------------------------------------------------------------------- 1 | [application] 2 | 3 | [web.app] 4 | 5 | # HTML title tag content 6 | title = "myapp" 7 | 8 | # include `assets` in web platform 9 | [web.resource] 10 | 11 | # Additional CSS style files 12 | style = [] 13 | 14 | # Additional JavaScript files 15 | script = [] 16 | 17 | [web.resource.dev] 18 | 19 | # Javascript code file 20 | # serve: [dev-server] only 21 | script = [] 22 | -------------------------------------------------------------------------------- /packages/playwright-tests/barebones-template/README.md: -------------------------------------------------------------------------------- 1 | # Development 2 | 3 | Your new bare-bones project includes minimal organization with a single `main.rs` file and a few assets. 4 | 5 | ``` 6 | project/ 7 | ├─ assets/ # Any assets that are used by the app should be placed here 8 | ├─ src/ 9 | │ ├─ main.rs # main.rs is the entry point to your application and currently contains all components for the app 10 | ├─ Cargo.toml # The Cargo.toml file defines the dependencies and feature flags for your project 11 | ``` 12 | 13 | ### Serving Your App 14 | 15 | Run the following command in the root of your project to start developing with the default platform: 16 | 17 | ```bash 18 | dx serve 19 | ``` 20 | 21 | To run for a different platform, use the `--platform platform` flag. E.g. 22 | ```bash 23 | dx serve --platform desktop 24 | ``` 25 | 26 | -------------------------------------------------------------------------------- /packages/playwright-tests/barebones-template/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/playwright-tests/barebones-template/assets/favicon.ico -------------------------------------------------------------------------------- /packages/playwright-tests/barebones-template/assets/main.css: -------------------------------------------------------------------------------- 1 | /* App-wide styling */ 2 | body { 3 | background-color: #0f1116; 4 | color: #ffffff; 5 | font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 6 | margin: 20px; 7 | } 8 | 9 | #hero { 10 | margin: 0; 11 | display: flex; 12 | flex-direction: column; 13 | justify-content: center; 14 | align-items: center; 15 | } 16 | 17 | #links { 18 | width: 400px; 19 | text-align: left; 20 | font-size: x-large; 21 | color: white; 22 | display: flex; 23 | flex-direction: column; 24 | } 25 | 26 | #links a { 27 | color: white; 28 | text-decoration: none; 29 | margin-top: 20px; 30 | margin: 10px 0px; 31 | border: white 1px solid; 32 | border-radius: 5px; 33 | padding: 10px; 34 | } 35 | 36 | #links a:hover { 37 | background-color: #1f1f1f; 38 | cursor: pointer; 39 | } 40 | 41 | #header { 42 | max-width: 1200px; 43 | } 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /packages/playwright-tests/cli-optimization/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | target 3 | monaco-editor-0.52.2 -------------------------------------------------------------------------------- /packages/playwright-tests/cli-optimization/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-cli-optimization-test" 3 | version = "0.0.1" 4 | edition = "2021" 5 | description = "Playwright test for Dioxus CLI optimization" 6 | license = "MIT OR Apache-2.0" 7 | publish = false 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["web"] } 11 | 12 | [build-dependencies] 13 | reqwest = { workspace = true, features = ["blocking"] } 14 | flate2 = "1.1.0" 15 | tar = "0.4.44" 16 | -------------------------------------------------------------------------------- /packages/playwright-tests/cli-optimization/build.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | fn main() { 4 | // If the monaco editor folder doesn't exist, download it 5 | let monaco_path = PathBuf::from("monaco-editor-0.52.2"); 6 | if monaco_path.exists() { 7 | return; 8 | } 9 | 10 | let url = "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz"; 11 | let bytes = reqwest::blocking::get(url).unwrap().bytes().unwrap(); 12 | let mut archive = tar::Archive::new(flate2::read::GzDecoder::new(bytes.as_ref())); 13 | archive.unpack(&monaco_path).unwrap(); 14 | } 15 | -------------------------------------------------------------------------------- /packages/playwright-tests/cli-optimization/images/toasts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/playwright-tests/cli-optimization/images/toasts.png -------------------------------------------------------------------------------- /packages/playwright-tests/default-features-disabled.spec.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const { test, expect } = require("@playwright/test"); 3 | 4 | test("loads with correct features", async ({ page }) => { 5 | await page.goto("http://localhost:8002"); 6 | 7 | // Expect the page to contain the pending text. 8 | const main = page.locator("#main"); 9 | await expect(main).toContainText('server features: ["server"]'); 10 | await expect(main).toContainText('client features: ["web"]'); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/playwright-tests/default-features-disabled/.gitignore: -------------------------------------------------------------------------------- 1 | .dioxus 2 | dist 3 | target -------------------------------------------------------------------------------- /packages/playwright-tests/default-features-disabled/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-playwright-default-features-disabled-test" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["fullstack"] } 11 | 12 | [features] 13 | # Web is a default feature, but it shouldn't actually be enabled in server builds 14 | default = ["web"] 15 | server = ["dioxus/server"] 16 | web = ["dioxus/web"] 17 | -------------------------------------------------------------------------------- /packages/playwright-tests/fullstack-mounted.spec.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const { test, expect } = require("@playwright/test"); 3 | 4 | test("hydration", async ({ page }) => { 5 | await page.goto("http://localhost:7777"); 6 | 7 | // Expect the page to contain the pending text. 8 | const main = page.locator("#main"); 9 | await expect(main).toContainText("The mounted event was triggered."); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/playwright-tests/fullstack-mounted/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-playwright-fullstack-mounted-test" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["fullstack"] } 11 | serde = "1.0.218" 12 | tokio = { workspace = true, features = ["full"], optional = true } 13 | 14 | [features] 15 | default = [] 16 | server = ["dioxus/server", "dep:tokio"] 17 | web = ["dioxus/web"] 18 | -------------------------------------------------------------------------------- /packages/playwright-tests/fullstack-mounted/src/main.rs: -------------------------------------------------------------------------------- 1 | // Regression test for https://github.com/DioxusLabs/dioxus/pull/3480 2 | 3 | use dioxus::prelude::*; 4 | 5 | fn main() { 6 | dioxus::launch(App); 7 | } 8 | 9 | #[component] 10 | fn App() -> Element { 11 | let mut mounted = use_signal(|| false); 12 | 13 | rsx! { 14 | div { 15 | onmounted: move |_| { 16 | mounted.set(true); 17 | }, 18 | if mounted() { 19 | "The mounted event was triggered." 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/playwright-tests/fullstack-routing/.gitignore: -------------------------------------------------------------------------------- 1 | .dioxus 2 | dist 3 | target -------------------------------------------------------------------------------- /packages/playwright-tests/fullstack-routing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-playwright-fullstack-routing-test" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["fullstack", "router"] } 11 | serde = "1.0.159" 12 | tokio = { workspace = true, features = ["full"], optional = true } 13 | 14 | [features] 15 | default = [] 16 | server = ["dioxus/server", "dep:tokio"] 17 | web = ["dioxus/web"] 18 | -------------------------------------------------------------------------------- /packages/playwright-tests/fullstack/.gitignore: -------------------------------------------------------------------------------- 1 | .dioxus 2 | dist 3 | target -------------------------------------------------------------------------------- /packages/playwright-tests/fullstack/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-playwright-fullstack-test" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["fullstack"] } 11 | futures.workspace = true 12 | serde = "1.0.218" 13 | tokio = { workspace = true, features = ["full"], optional = true } 14 | 15 | [features] 16 | default = [] 17 | server = ["dioxus/server", "dep:tokio"] 18 | web = ["dioxus/web"] 19 | -------------------------------------------------------------------------------- /packages/playwright-tests/liveview/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-playwright-liveview-test" 3 | version = "0.0.1" 4 | edition = "2021" 5 | description = "Playwright test for Dioxus Liveview" 6 | license = "MIT OR Apache-2.0" 7 | publish = false 8 | 9 | [dependencies] 10 | dioxus = { workspace = true } 11 | dioxus-liveview = { workspace = true, features = ["axum"] } 12 | tokio = { workspace = true, features = ["full"] } 13 | axum = { workspace = true, default-features = true, features = ["ws"] } 14 | -------------------------------------------------------------------------------- /packages/playwright-tests/nested-suspense/.gitignore: -------------------------------------------------------------------------------- 1 | .dioxus 2 | dist 3 | target -------------------------------------------------------------------------------- /packages/playwright-tests/nested-suspense/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nested-suspense" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["fullstack"] } 11 | serde = "1.0.218" 12 | tokio = { workspace = true, features = ["full"], optional = true } 13 | 14 | [features] 15 | default = [] 16 | server = ["dioxus/server", "tokio"] 17 | web = ["dioxus/web"] 18 | 19 | # We need a separate bin for the SSG build to avoid conflicting server caches 20 | [[bin]] 21 | name = "nested-suspense-ssg" 22 | path = "src/ssg.rs" 23 | 24 | [[bin]] 25 | name = "nested-suspense" 26 | path = "src/main.rs" 27 | -------------------------------------------------------------------------------- /packages/playwright-tests/nested-suspense/assets/style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/dioxus/544d8cc4da0fe6de5dff411e2ee665128458ae47/packages/playwright-tests/nested-suspense/assets/style.css -------------------------------------------------------------------------------- /packages/playwright-tests/nested-suspense/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case)] 2 | use dioxus::prelude::*; 3 | use nested_suspense::app; 4 | 5 | fn main() { 6 | LaunchBuilder::new() 7 | .with_cfg(server_only! { 8 | ServeConfig::builder() 9 | .enable_out_of_order_streaming() 10 | }) 11 | .launch(app); 12 | } 13 | -------------------------------------------------------------------------------- /packages/playwright-tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dioxus", 3 | "version": "1.0.0", 4 | "description": "

", 5 | "main": "index.js", 6 | "directories": { 7 | "doc": "docs", 8 | "example": "examples" 9 | }, 10 | "scripts": {}, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "@playwright/test": "^1.52.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/playwright-tests/suspense-carousel/.gitignore: -------------------------------------------------------------------------------- 1 | .dioxus 2 | dist 3 | target -------------------------------------------------------------------------------- /packages/playwright-tests/suspense-carousel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "suspense-carousel" 3 | edition = "2021" 4 | version.workspace = true 5 | publish = false 6 | 7 | [dependencies] 8 | dioxus = { workspace = true, features = ["fullstack"] } 9 | async-std = "1.13.0" 10 | serde = "1.0.218" 11 | 12 | [features] 13 | default = [] 14 | server = ["dioxus/server"] 15 | web = ["dioxus/web"] 16 | -------------------------------------------------------------------------------- /packages/playwright-tests/wasm-split-harness/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | # It's recommended to set the flag on a per-target basis: 2 | [target.wasm32-unknown-unknown] 3 | rustflags = ['--cfg', 'getrandom_backend="wasm_js"'] 4 | -------------------------------------------------------------------------------- /packages/playwright-tests/wasm-split-harness/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasm-split-harness" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | authors = ["Jonathan Kelley"] 7 | 8 | [dependencies] 9 | dioxus = { workspace = true, features = ["web", "router", "wasm-split"] } 10 | dioxus-router = { workspace = true, features = ["wasm-split"] } 11 | anyhow = { workspace = true } 12 | async-compression = { workspace = true, features = ["futures-io", "gzip", "brotli"] } 13 | futures = { workspace = true } 14 | js-sys = { workspace = true } 15 | wasm-bindgen = { workspace = true } 16 | wasm-bindgen-futures = { workspace = true } 17 | web-sys = { workspace = true, features = ["Document", "Window", "HtmlElement", "Text", "DomRectReadOnly", "console"] } 18 | getrandom = { workspace = true, features = ["js"] } 19 | reqwest = { workspace = true, features = ["json"] } 20 | -------------------------------------------------------------------------------- /packages/playwright-tests/wasm-split-harness/data/.gitignore: -------------------------------------------------------------------------------- 1 | harness/ 2 | -------------------------------------------------------------------------------- /packages/playwright-tests/wasm-split-harness/data/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello wasm-bindgen 5 | 6 | 7 |
8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /packages/playwright-tests/wasm-split-harness/docsite.sh: -------------------------------------------------------------------------------- 1 | cargo build --bin wasm-split-cli 2 | CLI=./target/debug/wasm-split-cli 3 | 4 | rm -rf docsite/chunks 5 | 6 | # Run the wasm-split-cli on the with_body.wasm file 7 | ${CLI} split docsite/input.wasm docsite/bindgen/main_bg.wasm docsite/chunks 8 | 9 | # copy the contents of the wasm_bindgen folder to the docsite folder 10 | mv docsite/chunks/main.wasm docsite/chunks/main_bg.wasm # rename the main wasm file 11 | cp -r docsite/bindgen/snippets docsite/chunks/snippets 12 | cp docsite/bindgen/main.js docsite/chunks/main.js 13 | 14 | python3 -m http.server 8080 --directory docsite 15 | -------------------------------------------------------------------------------- /packages/playwright-tests/wasm-split-harness/src/stars.js: -------------------------------------------------------------------------------- 1 | // Handle caching of github stars 2 | // This file is part of the fuzz test to prove we can handle linked js files 3 | 4 | // Two days 5 | const STAR_EXPIRE_TIME = 172800000; 6 | 7 | export function get_stars(name) { 8 | let item = localStorage.getItem(name); 9 | let data = JSON.parse(item); 10 | 11 | if (!data) { 12 | return null; 13 | } 14 | 15 | if (data.expires <= Date.now()) { 16 | localStorage.removeItem(name); 17 | return null; 18 | } 19 | 20 | return data.stars; 21 | } 22 | 23 | export function set_stars(name, value) { 24 | let expires = Date.now() + STAR_EXPIRE_TIME; 25 | let data = { stars: value, expires }; 26 | 27 | let converted = JSON.stringify(data); 28 | localStorage.setItem(name, converted); 29 | } 30 | -------------------------------------------------------------------------------- /packages/playwright-tests/web-routing/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | target 3 | -------------------------------------------------------------------------------- /packages/playwright-tests/web-routing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-playwright-web-routing-test" 3 | version = "0.0.1" 4 | edition = "2021" 5 | description = "Playwright test for Dioxus Web Routing" 6 | license = "MIT OR Apache-2.0" 7 | publish = false 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["web", "router"]} 11 | -------------------------------------------------------------------------------- /packages/playwright-tests/web/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | target 3 | -------------------------------------------------------------------------------- /packages/playwright-tests/web/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-playwright-web-test" 3 | version = "0.0.1" 4 | edition = "2021" 5 | description = "Playwright test for Dioxus Web" 6 | license = "MIT OR Apache-2.0" 7 | publish = false 8 | 9 | [dependencies] 10 | dioxus = { workspace = true, features = ["web"]} 11 | serde_json = { workspace = true } 12 | tracing = { workspace = true } 13 | tracing-wasm = { workspace = true } 14 | wasm-bindgen = { workspace = true } 15 | web-sys = { workspace = true, features = ["Element", "Window"] } 16 | -------------------------------------------------------------------------------- /packages/router/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | static -------------------------------------------------------------------------------- /packages/router/src/components/default_errors.rs: -------------------------------------------------------------------------------- 1 | #[allow(deprecated)] 2 | use crate::hooks::use_router; 3 | use dioxus_lib::prelude::*; 4 | 5 | /// The default component to render when an external navigation fails. 6 | #[allow(non_snake_case)] 7 | pub fn FailureExternalNavigation() -> Element { 8 | #[allow(deprecated)] 9 | let router = use_router(); 10 | 11 | rsx! { 12 | h1 { "External Navigation Failure!" } 13 | p { 14 | "The application tried to programmatically navigate to an external page. This " 15 | "operation has failed. Click the link below to complete the navigation manually." 16 | } 17 | a { onclick: move |_| { router.clear_error() }, "Click here to go back" } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/router/src/components/history_provider.rs: -------------------------------------------------------------------------------- 1 | use dioxus_history::{provide_history_context, History}; 2 | use dioxus_lib::prelude::*; 3 | 4 | use std::rc::Rc; 5 | 6 | /// A component that provides a [`History`] for all child [`Router`] components. Renderers generally provide a default history automatically. 7 | #[component] 8 | #[allow(missing_docs)] 9 | pub fn HistoryProvider( 10 | /// The history to provide to child components. 11 | history: Callback<(), Rc>, 12 | /// The children to render within the history provider. 13 | children: Element, 14 | ) -> Element { 15 | use_hook(|| { 16 | provide_history_context(history(())); 17 | }); 18 | 19 | children 20 | } 21 | -------------------------------------------------------------------------------- /packages/router/src/hooks/use_router.rs: -------------------------------------------------------------------------------- 1 | use crate::{prelude::RouterContext, utils::use_router_internal::use_router_internal}; 2 | 3 | #[deprecated = "prefer the `router()` function or `use_route` functions"] 4 | #[must_use] 5 | /// A hook that provides access to information about the router. 6 | pub fn use_router() -> RouterContext { 7 | use_router_internal().expect("use_route must have access to a router") 8 | } 9 | 10 | /// Acquire the router without subscribing to updates. 11 | #[doc(alias = "url")] 12 | pub fn router() -> RouterContext { 13 | dioxus_lib::prelude::consume_context() 14 | } 15 | 16 | /// Try to acquire the router without subscribing to updates. 17 | #[doc(alias = "url")] 18 | pub fn try_router() -> Option { 19 | dioxus_lib::prelude::try_consume_context() 20 | } 21 | -------------------------------------------------------------------------------- /packages/router/src/utils/use_router_internal.rs: -------------------------------------------------------------------------------- 1 | use dioxus_lib::prelude::*; 2 | 3 | use crate::prelude::*; 4 | 5 | /// A private hook to subscribe to the router. 6 | /// 7 | /// Used to reduce redundancy within other components/hooks. Safe to call multiple times for a 8 | /// single component, but not recommended. Multiple subscriptions will be discarded. 9 | /// 10 | /// # Return values 11 | /// - [`None`], when the current component isn't a descendant of a [`Router`] component. 12 | /// - Otherwise [`Some`]. 13 | pub(crate) fn use_router_internal() -> Option { 14 | use_hook(try_consume_context) 15 | } 16 | -------------------------------------------------------------------------------- /packages/router/tests/via_ssr/main.rs: -------------------------------------------------------------------------------- 1 | mod link; 2 | mod navigation; 3 | mod outlet; 4 | mod redirect; 5 | mod without_index; 6 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-rsx-hotreload" 3 | edition = "2021" 4 | version.workspace = true 5 | authors = ["Jonathan Kelley", "Evan Almloff"] 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/DioxusLabs/dioxus/" 8 | homepage = "https://dioxuslabs.com" 9 | description = "CLI Configuration for dioxus-cli" 10 | keywords = ["dom", "ui", "gui", "react"] 11 | 12 | [dependencies] 13 | dioxus-rsx = { workspace = true } 14 | internment = { workspace = true } 15 | proc-macro2 = { workspace = true, features = ["span-locations"] } 16 | proc-macro2-diagnostics = { workspace = true } 17 | quote = { workspace = true } 18 | syn = { workspace = true, features = ["full", "extra-traits", "visit", "visit-mut"] } 19 | tracing = { workspace = true } 20 | dioxus-core = { workspace = true } 21 | dioxus-core-types = { workspace = true } 22 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod collect; 2 | pub use collect::*; 3 | 4 | mod diff; 5 | pub use diff::*; 6 | 7 | mod last_build_state; 8 | 9 | mod extensions; 10 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/tests/valid/expr.new.rsx: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | pub fn CoolChild() -> Element { 4 | let head_ = rsx! { 5 | div { 6 | div { "asasddasdasd" } 7 | div { "asasdd1asaassdd23asasddasd" } 8 | div { "aasdsdsaasdsddasd" } 9 | } 10 | }; 11 | 12 | rsx! { 13 | div { 14 | {head_} 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/tests/valid/expr.old.rsx: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | pub fn CoolChild() -> Element { 4 | let head_ = rsx! { 5 | div { 6 | div { "asasddasdasd" } 7 | div { "asasdd1asaassdd23asasddasd" } 8 | // div { "aasdsdsaasdsddasd" } 9 | } 10 | }; 11 | 12 | rsx! { 13 | div { 14 | {head_} 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/tests/valid/for_.new.rsx: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | pub fn CoolChild() -> Element { 4 | rsx! { 5 | for items in vec![1, 2, 3] { 6 | div { "asasddasdasd" } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/tests/valid/for_.old.rsx: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | pub fn CoolChild() -> Element { 4 | rsx! { 5 | for items in vec![1, 2, 3] { 6 | div { "123" } 7 | div { "asasddasdasd" } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/tests/valid/if_.new.rsx: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | pub fn CoolChild() -> Element { 4 | rsx! { 5 | if cond() { 6 | div { "123" } 7 | div { "asasddasdasd" } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/tests/valid/if_.old.rsx: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | pub fn CoolChild() -> Element { 4 | rsx! { 5 | if cond() { 6 | div { "asasddasdasd" } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/tests/valid/let_.new.rsx: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | pub fn CoolChild() -> Element { 4 | let head_ = rsx! { 5 | div { 6 | div { "asasddasdasd" } 7 | div { "asasdd1asaassdd23asasddasd" } 8 | } 9 | }; 10 | 11 | head_ 12 | } 13 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/tests/valid/let_.old.rsx: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | pub fn CoolChild() -> Element { 4 | let head_ = rsx! { 5 | div { 6 | div { "asasddasdasd" } 7 | div { "asasdd1asaassdd23asasddasdasd" } 8 | } 9 | }; 10 | 11 | head_ 12 | } 13 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/tests/valid/nested.new.rsx: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | pub fn CoolChild() -> Element { 4 | rsx! { 5 | ForLoop { 6 | div { "123" } 7 | div { "asasddasdasd" } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/rsx-hotreload/tests/valid/nested.old.rsx: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | pub fn CoolChild() -> Element { 4 | rsx! { 5 | ForLoop { 6 | div { "asasddasdasd" } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/rsx-rosetta/examples/html.rs: -------------------------------------------------------------------------------- 1 | use html_parser::Dom; 2 | 3 | fn main() { 4 | let html = r#" 5 |
6 |
hello world!
7 |
hello world!
8 |
hello world!
9 |
hello world!
10 |
hello world!
11 |
hello world!
12 | hello world! 13 |
14 | "# 15 | .trim(); 16 | 17 | let dom = Dom::parse(html).unwrap(); 18 | 19 | let body = dioxus_rsx_rosetta::rsx_from_html(&dom); 20 | 21 | let out = dioxus_autofmt::write_block_out(&body).unwrap(); 22 | 23 | println!("{out}"); 24 | } 25 | -------------------------------------------------------------------------------- /packages/rsx-rosetta/tests/escape.rs: -------------------------------------------------------------------------------- 1 | use html_parser::Dom; 2 | 3 | // Regression test for https://github.com/DioxusLabs/dioxus/issues/3037 4 | // We need to escape html entities as we translate html because rsx doesn't support them 5 | #[test] 6 | fn escaped_text() { 7 | let html = r#"
<div>⌛⌛⌛⌛
"#.trim(); 8 | 9 | let dom = Dom::parse(html).unwrap(); 10 | 11 | let body = dioxus_rsx_rosetta::rsx_from_html(&dom); 12 | 13 | let out = dioxus_autofmt::write_block_out(&body).unwrap(); 14 | 15 | let expected = r#" 16 | div { "
⌛⌛⌛⌛" }"#; 17 | pretty_assertions::assert_eq!(&out, &expected); 18 | } 19 | -------------------------------------------------------------------------------- /packages/rsx-rosetta/tests/h-tags.rs: -------------------------------------------------------------------------------- 1 | use html_parser::Dom; 2 | 3 | #[test] 4 | fn h_tags_translate() { 5 | let html = r#" 6 |
7 |

hello world!

8 |

hello world!

9 |

hello world!

10 |

hello world!

11 |
hello world!
12 |
hello world!
13 |
14 | "# 15 | .trim(); 16 | 17 | let dom = Dom::parse(html).unwrap(); 18 | 19 | let body = dioxus_rsx_rosetta::rsx_from_html(&dom); 20 | 21 | let out = dioxus_autofmt::write_block_out(&body).unwrap(); 22 | 23 | let expected = r#" 24 | div { 25 | h1 { "hello world!" } 26 | h2 { "hello world!" } 27 | h3 { "hello world!" } 28 | h4 { "hello world!" } 29 | h5 { "hello world!" } 30 | h6 { "hello world!" } 31 | }"#; 32 | pretty_assertions::assert_eq!(&out, &expected); 33 | } 34 | -------------------------------------------------------------------------------- /packages/rsx-rosetta/tests/raw.rs: -------------------------------------------------------------------------------- 1 | use html_parser::Dom; 2 | 3 | #[test] 4 | fn raw_attribute() { 5 | let html = r#" 6 |
7 |
hello world!
8 |
9 | "# 10 | .trim(); 11 | 12 | let dom = Dom::parse(html).unwrap(); 13 | 14 | let body = dioxus_rsx_rosetta::rsx_from_html(&dom); 15 | 16 | let out = dioxus_autofmt::write_block_out(&body).unwrap(); 17 | 18 | let expected = r#" 19 | div { 20 | div { "unrecognizedattribute": "asd", "hello world!" } 21 | }"#; 22 | pretty_assertions::assert_eq!(&out, &expected); 23 | } 24 | -------------------------------------------------------------------------------- /packages/rsx-rosetta/tests/web-component.rs: -------------------------------------------------------------------------------- 1 | use html_parser::Dom; 2 | 3 | #[test] 4 | fn web_components_translate() { 5 | let html = r#" 6 |
7 | 8 |
9 | "# 10 | .trim(); 11 | 12 | let dom = Dom::parse(html).unwrap(); 13 | 14 | let body = dioxus_rsx_rosetta::rsx_from_html(&dom); 15 | 16 | let out = dioxus_autofmt::write_block_out(&body).unwrap(); 17 | 18 | let expected = r#" 19 | div { 20 | my-component {} 21 | }"#; 22 | pretty_assertions::assert_eq!(&out, &expected); 23 | } 24 | -------------------------------------------------------------------------------- /packages/rsx/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.check.workspace": false, 3 | "rust-analyzer.cargo.features": "all" 4 | } 5 | -------------------------------------------------------------------------------- /packages/rsx/src/util.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | 3 | use proc_macro2::TokenStream as TokenStream2; 4 | use std::{fmt::Debug, hash::Hash}; 5 | use syn::{ 6 | ext::IdentExt, 7 | parse::{Parse, ParseBuffer}, 8 | Ident, 9 | }; 10 | 11 | /// Parse a raw ident and return a new ident with the r# prefix added 12 | pub fn parse_raw_ident(parse_buffer: &ParseBuffer) -> syn::Result { 13 | // First try to parse as a normal ident 14 | if let Ok(ident) = Ident::parse(parse_buffer) { 15 | return Ok(ident); 16 | } 17 | // If that fails, try to parse as a raw ident 18 | let ident = Ident::parse_any(parse_buffer)?; 19 | Ok(Ident::new_raw(&ident.to_string(), ident.span())) 20 | } 21 | -------------------------------------------------------------------------------- /packages/signals/docs/hoist/fixed_list.rs: -------------------------------------------------------------------------------- 1 | #[component] 2 | fn Counters() -> Element { 3 | let mut counts = use_signal(Vec::new); 4 | 5 | rsx! { 6 | button { onclick: move |_| counts.write().push(0), "Add child" } 7 | button { 8 | onclick: move |_| { 9 | counts.write().pop(); 10 | }, 11 | "Remove child" 12 | } 13 | "{counts:?}" 14 | // Instead of passing up a signal, we can just write to the signal that lives in the parent 15 | for index in 0..counts.len() { 16 | Counter { 17 | index, 18 | counts 19 | } 20 | } 21 | } 22 | } 23 | 24 | #[component] 25 | fn Counter(index: usize, mut counts: Signal>) -> Element { 26 | rsx! { 27 | button { 28 | onclick: move |_| counts.write()[index] += 1, 29 | "{counts.read()[index]}" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/signals/examples/context.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case)] 2 | 3 | use dioxus::prelude::*; 4 | 5 | fn main() { 6 | dioxus::launch(app) 7 | } 8 | 9 | // Because signal is never read in this component, this component will not rerun when the signal changes 10 | fn app() -> Element { 11 | use_context_provider(|| Signal::new(0)); 12 | rsx! { Child {} } 13 | } 14 | 15 | // This component does read from the signal, so when the signal changes it will rerun 16 | #[component] 17 | fn Child() -> Element { 18 | let signal: Signal = use_context(); 19 | rsx! { "{signal}" } 20 | } 21 | -------------------------------------------------------------------------------- /packages/signals/examples/read_only_degrade.rs: -------------------------------------------------------------------------------- 1 | //! Signals can degrade into a ReadOnlySignal variant automatically 2 | //! This is done thanks to a conversion by the #[component] macro 3 | 4 | use dioxus::prelude::*; 5 | 6 | fn main() { 7 | dioxus::launch(app); 8 | } 9 | 10 | fn app() -> Element { 11 | let mut count = use_signal(|| 0); 12 | 13 | rsx! { 14 | h1 { "High-Five counter: {count}" } 15 | button { onclick: move |_| count += 1, "Up high!" } 16 | button { onclick: move |_| count -= 1, "Down low!" } 17 | Child { 18 | count, 19 | "hiiii" 20 | } 21 | } 22 | } 23 | 24 | #[component] 25 | fn Child(count: ReadOnlySignal, children: Element) -> Element { 26 | rsx! { 27 | div { "Count: {count}" } 28 | {children} 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/signals/examples/selector.rs: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | fn main() { 4 | dioxus::launch(app) 5 | } 6 | 7 | fn app() -> Element { 8 | let mut signal = use_signal(|| 0); 9 | let doubled = use_memo(move || signal * 2); 10 | 11 | rsx! { 12 | button { 13 | onclick: move |_| signal += 1, 14 | "Increase" 15 | } 16 | Child { signal: doubled } 17 | } 18 | } 19 | 20 | #[component] 21 | fn Child(signal: ReadOnlySignal) -> Element { 22 | rsx! { "{signal}" } 23 | } 24 | -------------------------------------------------------------------------------- /packages/signals/examples/send.rs: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | fn main() { 4 | dioxus::launch(app); 5 | } 6 | 7 | fn app() -> Element { 8 | let mut signal = use_signal_sync(|| 0); 9 | 10 | use_hook(|| { 11 | std::thread::spawn(move || loop { 12 | std::thread::sleep(std::time::Duration::from_secs(1)); 13 | signal += 1; 14 | }); 15 | }); 16 | 17 | rsx! { 18 | button { onclick: move |_| signal += 1, "Increase" } 19 | "{signal}" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/signals/src/global/memo.rs: -------------------------------------------------------------------------------- 1 | use super::{Global, InitializeFromFunction}; 2 | use crate::read::Readable; 3 | use crate::read_impls; 4 | use crate::Memo; 5 | 6 | impl InitializeFromFunction for Memo { 7 | fn initialize_from_function(f: fn() -> T) -> Self { 8 | Memo::new(f) 9 | } 10 | } 11 | 12 | /// A memo that can be accessed from anywhere in the application and created in a static 13 | pub type GlobalMemo = Global, T>; 14 | 15 | impl GlobalMemo { 16 | /// Get the generational id of the signal. 17 | pub fn id(&self) -> generational_box::GenerationalBoxId { 18 | self.resolve().id() 19 | } 20 | 21 | /// Resolve the global memo. This will try to get the existing value from the current virtual dom, and if it doesn't exist, it will create a new one. 22 | pub fn memo(&self) -> Memo { 23 | self.resolve() 24 | } 25 | } 26 | 27 | read_impls!(GlobalMemo where T: PartialEq); 28 | -------------------------------------------------------------------------------- /packages/signals/src/global/signal.rs: -------------------------------------------------------------------------------- 1 | use super::{Global, InitializeFromFunction}; 2 | use crate::read::Readable; 3 | use crate::read_impls; 4 | use crate::Signal; 5 | 6 | impl InitializeFromFunction for Signal { 7 | fn initialize_from_function(f: fn() -> T) -> Self { 8 | Signal::new(f()) 9 | } 10 | } 11 | 12 | /// A signal that can be accessed from anywhere in the application and created in a static 13 | pub type GlobalSignal = Global, T>; 14 | 15 | impl GlobalSignal { 16 | /// Get the generational id of the signal. 17 | pub fn id(&self) -> generational_box::GenerationalBoxId { 18 | self.resolve().id() 19 | } 20 | 21 | /// Resolve the global signal. This will try to get the existing value from the current virtual dom, and if it doesn't exist, it will create a new one. 22 | pub fn signal(&self) -> Signal { 23 | self.resolve() 24 | } 25 | } 26 | 27 | read_impls!(GlobalSignal); 28 | -------------------------------------------------------------------------------- /packages/signals/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")] 3 | #![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")] 4 | #![warn(missing_docs)] 5 | #![allow(clippy::type_complexity)] 6 | 7 | mod copy_value; 8 | pub use copy_value::*; 9 | 10 | pub(crate) mod signal; 11 | pub use signal::*; 12 | 13 | mod read_only_signal; 14 | pub use read_only_signal::*; 15 | 16 | mod map; 17 | pub use map::*; 18 | 19 | mod set_compare; 20 | pub use set_compare::*; 21 | 22 | mod memo; 23 | pub use memo::*; 24 | 25 | mod global; 26 | pub use global::*; 27 | 28 | mod impls; 29 | 30 | pub use generational_box::{ 31 | AnyStorage, BorrowError, BorrowMutError, Owner, Storage, SyncStorage, UnsyncStorage, 32 | }; 33 | 34 | mod read; 35 | pub use read::*; 36 | 37 | mod write; 38 | pub use write::*; 39 | 40 | mod props; 41 | pub use props::*; 42 | 43 | pub mod warnings; 44 | -------------------------------------------------------------------------------- /packages/signals/src/props.rs: -------------------------------------------------------------------------------- 1 | use crate::{ReadOnlySignal, Signal}; 2 | use dioxus_core::prelude::*; 3 | 4 | #[doc(hidden)] 5 | pub struct SignalFromMarker(std::marker::PhantomData); 6 | 7 | impl SuperFrom> for ReadOnlySignal 8 | where 9 | O: SuperFrom, 10 | { 11 | fn super_from(input: T) -> Self { 12 | ReadOnlySignal::new(Signal::new(O::super_from(input))) 13 | } 14 | } 15 | 16 | #[test] 17 | #[allow(unused)] 18 | fn into_signal_compiles() { 19 | fn takes_signal_string(_: impl SuperInto, M>) {} 20 | 21 | fn takes_option_signal_string(_: impl SuperInto>, M>) {} 22 | 23 | fn don_t_run() { 24 | takes_signal_string("hello world"); 25 | takes_signal_string(Signal::new(String::from("hello world"))); 26 | takes_option_signal_string("hello world"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/ssr/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dioxus-ssr" 3 | version = { workspace = true } 4 | authors = ["Jonathan Kelley"] 5 | edition = "2021" 6 | description = "Dioxus render-to-string" 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | keywords = ["dom", "ui", "gui", "react", "ssr"] 10 | 11 | [dependencies] 12 | dioxus-core = { workspace = true, features = ["serialize"] } 13 | dioxus-core-types = { workspace = true } 14 | askama_escape = { workspace = true } 15 | rustc-hash = { workspace = true } 16 | 17 | [dev-dependencies] 18 | dioxus = { workspace = true } 19 | 20 | [package.metadata.docs.rs] 21 | cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"] 22 | -------------------------------------------------------------------------------- /packages/ssr/src/config.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/ssr/src/template.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/ssr/tests/bool_attr.rs: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | #[test] 4 | fn static_boolean_attributes() { 5 | fn app() -> Element { 6 | rsx! { 7 | div { hidden: "false" } 8 | div { hidden: "true" } 9 | } 10 | } 11 | 12 | let mut dom = VirtualDom::new(app); 13 | dom.rebuild(&mut dioxus_core::NoOpMutations); 14 | 15 | assert_eq!( 16 | dioxus_ssr::render(&dom), 17 | r#"
"# 18 | ); 19 | } 20 | 21 | #[test] 22 | fn dynamic_boolean_attributes() { 23 | fn app() -> Element { 24 | rsx! { 25 | div { hidden: false } 26 | div { hidden: true } 27 | } 28 | } 29 | 30 | let mut dom = VirtualDom::new(app); 31 | dom.rebuild(&mut dioxus_core::NoOpMutations); 32 | 33 | assert_eq!( 34 | dioxus_ssr::render(&dom), 35 | r#"
"# 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /packages/ssr/tests/inner_html.rs: -------------------------------------------------------------------------------- 1 | use dioxus::prelude::*; 2 | 3 | #[test] 4 | fn static_inner_html() { 5 | fn app() -> Element { 6 | rsx! { div { dangerous_inner_html: "
1234
" } } 7 | } 8 | 9 | let mut dom = VirtualDom::new(app); 10 | dom.rebuild(&mut dioxus_core::NoOpMutations); 11 | 12 | assert_eq!(dioxus_ssr::render(&dom), r#"
1234
"#); 13 | } 14 | 15 | #[test] 16 | fn dynamic_inner_html() { 17 | fn app() -> Element { 18 | let inner_html = "
1234
"; 19 | rsx! { div { dangerous_inner_html: "{inner_html}" } } 20 | } 21 | 22 | let mut dom = VirtualDom::new(app); 23 | dom.rebuild(&mut dioxus_core::NoOpMutations); 24 | 25 | assert_eq!(dioxus_ssr::render(&dom), r#"
1234
"#); 26 | } 27 | -------------------------------------------------------------------------------- /packages/subsecond/subsecond-tests/cross-tls-crate-dylib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cross-tls-crate-dylib" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [lib] 8 | # when testing, use a dylib 9 | # crate-type = ["dylib"] 10 | 11 | [dependencies] 12 | -------------------------------------------------------------------------------- /packages/subsecond/subsecond-tests/cross-tls-crate-dylib/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use std::cell::Cell; 2 | use std::{cell::RefCell, thread::LocalKey}; 3 | 4 | #[derive(Debug)] 5 | pub struct StoredItem { 6 | pub name: String, 7 | pub value: f32, 8 | pub items: Vec, 9 | } 10 | 11 | thread_local! { 12 | pub static BAZ: RefCell> = const { RefCell::new(None) }; 13 | } 14 | 15 | pub fn get_baz() -> &'static LocalKey>> { 16 | if BAZ.with(|f| f.borrow().is_none()) { 17 | BAZ.set(Some(StoredItem { 18 | name: "BAR".to_string(), 19 | value: 0.0, 20 | items: vec!["item1".to_string(), "item2".to_string()], 21 | })); 22 | } 23 | 24 | &BAZ 25 | } 26 | -------------------------------------------------------------------------------- /packages/subsecond/subsecond-tests/cross-tls-crate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cross-tls-crate" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /packages/subsecond/subsecond-tests/cross-tls-crate/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use std::cell::Cell; 2 | use std::{cell::RefCell, thread::LocalKey}; 3 | 4 | #[derive(Debug)] 5 | pub struct StoredItem { 6 | pub name: String, 7 | pub value: f32, 8 | pub items: Vec, 9 | } 10 | 11 | thread_local! { 12 | pub static BAR: RefCell> = const { RefCell::new(None) }; 13 | } 14 | 15 | pub fn get_bar() -> &'static LocalKey>> { 16 | if BAR.with(|f| f.borrow().is_none()) { 17 | BAR.set(Some(StoredItem { 18 | name: "BAR".to_string(), 19 | value: 0.0, 20 | items: vec!["item1".to_string(), "item2".to_string()], 21 | })); 22 | } 23 | 24 | &BAR 25 | } 26 | -------------------------------------------------------------------------------- /packages/subsecond/subsecond-tests/cross-tls-test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "subsecond-tls-harness" 3 | version = "0.1.0" 4 | edition = "2021" 5 | publish = false 6 | 7 | [dependencies] 8 | dioxus-devtools = { workspace = true } 9 | cross-tls-crate = { path = "../cross-tls-crate" } 10 | cross-tls-crate-dylib = { path = "../cross-tls-crate-dylib" } 11 | -------------------------------------------------------------------------------- /packages/subsecond/subsecond-tests/cross-tls-test/README.md: -------------------------------------------------------------------------------- 1 | harness for testing cross-crate TLS imports. 2 | 3 | TLS is the hardest to get right with binary patchinig since we need to rewrite initializers. 4 | 5 | this crate relies on two crates - one as a dylib and the other as an rlib 6 | 7 | the dylib should make it into our bundle and the rlib should just be linked. 8 | 9 | both shouldn't cause access errors or segfaults during hotpatch. 10 | 11 | ```sh 12 | cargo run --package dioxus-cli -- serve --hotpatch 13 | ``` 14 | -------------------------------------------------------------------------------- /packages/subsecond/subsecond-types/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "subsecond-types" 3 | version.workspace = true 4 | edition = "2021" 5 | authors = ["Jonathan Kelley"] 6 | description = "Types crate for the Subsecond hotpatch engine." 7 | license = "MIT OR Apache-2.0" 8 | repository = "https://github.com/DioxusLabs/dioxus/" 9 | keywords = ["hotpatch", "engine", "subsecond", "dioxus"] 10 | 11 | 12 | [dependencies] 13 | serde = { workspace = true, features = ["derive"] } 14 | -------------------------------------------------------------------------------- /packages/wasm-split/README.md: -------------------------------------------------------------------------------- 1 | # This folder contains the wasm-split sub-workspace 2 | 3 | wasm-split is a tool that allows you to split a wasm binary into multiple chunks that are lazily loaded on demand. 4 | 5 | This workspace is comprised of: 6 | - the harness on which we test against 7 | - the wasm-split user-facing crate 8 | - the wasm-split-macro crate which is used to generate the wasm-split loader 9 | - the wasm-split-cli crate which is imported by the dioxus-cli and used when building the wasm modules 10 | - the wasm-used crate which provides a custom walrus `Used` struct that makes it easier to debug why a emit_wasm might be failing 11 | -------------------------------------------------------------------------------- /packages/wasm-split/wasm-split-cli/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasm-split-cli" 3 | edition = "2021" 4 | version = { workspace = true } 5 | authors = ["Jonathan Kelley"] 6 | description = "CLI-support for wasm-split - a tool for splitting up large WASM binaries into smaller chunks" 7 | repository = "https://github.com/DioxusLabs/dioxus/" 8 | license = "MIT OR Apache-2.0" 9 | keywords = ["wasm", "cli", "split", "dioxus"] 10 | rust-version = "1.81.0" 11 | 12 | 13 | [dependencies] 14 | anyhow = { workspace = true } 15 | itertools = { workspace = true } 16 | walrus = { workspace = true, features = ["parallel"]} 17 | wasmparser = { workspace = true } 18 | id-arena = { workspace = true } 19 | rayon = { workspace = true } 20 | tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] } 21 | tracing = { workspace = true } 22 | clap = { workspace = true, features = ["derive"] } 23 | wasm-used = { workspace = true} 24 | -------------------------------------------------------------------------------- /packages/wasm-split/wasm-split-cli/data/.gitignore: -------------------------------------------------------------------------------- 1 | # this folder contains the wasm output for the test harnessa, so ignore it 2 | 3 | *.wasm 4 | bindgen/ 5 | -------------------------------------------------------------------------------- /packages/wasm-split/wasm-split-macro/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasm-split-macro" 3 | edition = "2021" 4 | version = { workspace = true } 5 | authors = ["Jonathan Kelley"] 6 | description = "macro crate for wasm-split - a tool for splitting up large WASM binaries into smaller chunks" 7 | repository = "https://github.com/DioxusLabs/dioxus/" 8 | license = "MIT OR Apache-2.0" 9 | keywords = ["wasm", "cli", "split", "dioxus"] 10 | rust-version = "1.81.0" 11 | 12 | 13 | [dependencies] 14 | syn = { workspace = true, features = ["full"] } 15 | base16 = { workspace = true } 16 | digest = { workspace = true } 17 | quote = { workspace = true } 18 | sha2 = { workspace = true } 19 | proc-macro2 = { workspace = true } 20 | 21 | [lib] 22 | proc-macro = true 23 | -------------------------------------------------------------------------------- /packages/wasm-split/wasm-split/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasm-splitter" 3 | version = { workspace = true } 4 | edition = "2021" 5 | authors = ["Jonathan Kelley"] 6 | description = "A tool for splitting up large WASM binaries into smaller chunks" 7 | repository = "https://github.com/DioxusLabs/dioxus/" 8 | license = "MIT OR Apache-2.0" 9 | keywords = ["wasm", "cli", "split", "dioxus"] 10 | rust-version = "1.81.0" 11 | 12 | 13 | [dependencies] 14 | async-once-cell = { workspace = true, features = ["std"] } 15 | wasm-split-macro = { workspace = true } 16 | -------------------------------------------------------------------------------- /packages/wasm-split/wasm-used/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasm-used" 3 | edition = "2021" 4 | version.workspace = true 5 | authors = ["Jonathan Kelley"] 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/DioxusLabs/dioxus/" 8 | homepage = "https://dioxuslabs.com" 9 | description = "wasm-used implementation for Rust" 10 | keywords = ["wasm", "wasm-used", "wasm-split", "dioxus" ] 11 | 12 | [dependencies] 13 | walrus = { workspace = true, features = ["parallel"] } 14 | id-arena = { workspace = true } 15 | tracing = { workspace = true } 16 | -------------------------------------------------------------------------------- /packages/web/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | -------------------------------------------------------------------------------- /packages/web/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.cargo.target": "wasm32-unknown-unknown", 3 | } 4 | -------------------------------------------------------------------------------- /packages/web/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // If any TS files change, re-run the build script 3 | lazy_js_bundle::LazyTypeScriptBindings::new() 4 | .with_watching("./src/ts") 5 | .with_binding("./src/ts/eval.ts", "./src/js/eval.js") 6 | .run(); 7 | } 8 | -------------------------------------------------------------------------------- /packages/web/src/events/animation.rs: -------------------------------------------------------------------------------- 1 | use dioxus_html::HasAnimationData; 2 | use web_sys::AnimationEvent; 3 | 4 | use super::{Synthetic, WebEventExt}; 5 | 6 | impl HasAnimationData for Synthetic { 7 | fn animation_name(&self) -> String { 8 | self.event.animation_name() 9 | } 10 | 11 | fn pseudo_element(&self) -> String { 12 | self.event.pseudo_element() 13 | } 14 | 15 | fn elapsed_time(&self) -> f32 { 16 | self.event.elapsed_time() 17 | } 18 | 19 | fn as_any(&self) -> &dyn std::any::Any { 20 | &self.event 21 | } 22 | } 23 | 24 | impl WebEventExt for dioxus_html::AnimationData { 25 | type WebEvent = web_sys::AnimationEvent; 26 | 27 | #[inline(always)] 28 | fn try_as_web_event(&self) -> Option { 29 | self.downcast::().cloned() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/web/src/events/clipboard.rs: -------------------------------------------------------------------------------- 1 | use dioxus_html::HasClipboardData; 2 | use web_sys::Event; 3 | 4 | use super::{Synthetic, WebEventExt}; 5 | 6 | impl From<&Event> for Synthetic { 7 | fn from(e: &Event) -> Self { 8 | Synthetic::new(e.clone()) 9 | } 10 | } 11 | 12 | impl HasClipboardData for Synthetic { 13 | fn as_any(&self) -> &dyn std::any::Any { 14 | &self.event 15 | } 16 | } 17 | 18 | impl WebEventExt for dioxus_html::ClipboardData { 19 | type WebEvent = web_sys::Event; 20 | 21 | #[inline(always)] 22 | fn try_as_web_event(&self) -> Option { 23 | self.downcast::().cloned() 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/web/src/events/composition.rs: -------------------------------------------------------------------------------- 1 | use dioxus_html::HasCompositionData; 2 | use web_sys::CompositionEvent; 3 | 4 | use super::{Synthetic, WebEventExt}; 5 | 6 | impl HasCompositionData for Synthetic { 7 | fn data(&self) -> std::string::String { 8 | self.event.data().unwrap_or_default() 9 | } 10 | 11 | fn as_any(&self) -> &dyn std::any::Any { 12 | &self.event 13 | } 14 | } 15 | 16 | impl WebEventExt for dioxus_html::CompositionData { 17 | type WebEvent = web_sys::CompositionEvent; 18 | 19 | #[inline(always)] 20 | fn try_as_web_event(&self) -> Option { 21 | self.downcast::().cloned() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/web/src/events/focus.rs: -------------------------------------------------------------------------------- 1 | use dioxus_html::HasFocusData; 2 | 3 | use super::{Synthetic, WebEventExt}; 4 | 5 | impl HasFocusData for Synthetic { 6 | fn as_any(&self) -> &dyn std::any::Any { 7 | &self.event 8 | } 9 | } 10 | 11 | impl WebEventExt for dioxus_html::FocusData { 12 | type WebEvent = web_sys::FocusEvent; 13 | 14 | #[inline(always)] 15 | fn try_as_web_event(&self) -> Option { 16 | self.downcast::().cloned() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/web/src/events/load.rs: -------------------------------------------------------------------------------- 1 | use std::any::Any; 2 | 3 | use dioxus_html::HasImageData; 4 | use web_sys::Event; 5 | 6 | use super::WebEventExt; 7 | 8 | #[derive(Clone)] 9 | pub(crate) struct WebImageEvent { 10 | raw: Event, 11 | error: bool, 12 | } 13 | 14 | impl WebImageEvent { 15 | pub fn new(raw: Event, error: bool) -> Self { 16 | Self { raw, error } 17 | } 18 | } 19 | 20 | impl HasImageData for WebImageEvent { 21 | fn load_error(&self) -> bool { 22 | self.error 23 | } 24 | 25 | fn as_any(&self) -> &dyn Any { 26 | &self.raw 27 | } 28 | } 29 | 30 | impl WebEventExt for dioxus_html::ImageData { 31 | type WebEvent = Event; 32 | 33 | #[inline(always)] 34 | fn try_as_web_event(&self) -> Option { 35 | self.downcast::().map(|e| e.raw.clone()) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/web/src/events/media.rs: -------------------------------------------------------------------------------- 1 | use super::{Synthetic, WebEventExt}; 2 | use dioxus_html::HasMediaData; 3 | 4 | impl HasMediaData for Synthetic { 5 | fn as_any(&self) -> &dyn std::any::Any { 6 | &self.event 7 | } 8 | } 9 | 10 | impl WebEventExt for dioxus_html::MediaData { 11 | type WebEvent = web_sys::Event; 12 | 13 | #[inline(always)] 14 | fn try_as_web_event(&self) -> Option { 15 | self.downcast::().cloned() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/web/src/events/selection.rs: -------------------------------------------------------------------------------- 1 | use super::{Synthetic, WebEventExt}; 2 | use dioxus_html::HasSelectionData; 3 | 4 | impl HasSelectionData for Synthetic { 5 | fn as_any(&self) -> &dyn std::any::Any { 6 | &self.event 7 | } 8 | } 9 | 10 | impl WebEventExt for dioxus_html::SelectionData { 11 | type WebEvent = web_sys::Event; 12 | 13 | #[inline(always)] 14 | fn try_as_web_event(&self) -> Option { 15 | self.downcast::().cloned() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/web/src/events/toggle.rs: -------------------------------------------------------------------------------- 1 | use super::{Synthetic, WebEventExt}; 2 | use dioxus_html::HasToggleData; 3 | 4 | impl HasToggleData for Synthetic { 5 | fn as_any(&self) -> &dyn std::any::Any { 6 | &self.event 7 | } 8 | } 9 | 10 | impl WebEventExt for dioxus_html::ToggleData { 11 | type WebEvent = web_sys::Event; 12 | 13 | #[inline(always)] 14 | fn try_as_web_event(&self) -> Option { 15 | self.downcast::().cloned() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/web/src/events/transition.rs: -------------------------------------------------------------------------------- 1 | use dioxus_html::HasTransitionData; 2 | use web_sys::TransitionEvent; 3 | 4 | use super::Synthetic; 5 | 6 | impl HasTransitionData for Synthetic { 7 | fn elapsed_time(&self) -> f32 { 8 | self.event.elapsed_time() 9 | } 10 | 11 | fn property_name(&self) -> String { 12 | self.event.property_name() 13 | } 14 | 15 | fn pseudo_element(&self) -> String { 16 | self.event.pseudo_element() 17 | } 18 | 19 | fn as_any(&self) -> &dyn std::any::Any { 20 | &self.event 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/web/src/js/hash.txt: -------------------------------------------------------------------------------- 1 | [460758788096589933] --------------------------------------------------------------------------------