mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
re export renderers in dioxus
This commit is contained in:
parent
b291a5c0b0
commit
af1749d7be
61 changed files with 860 additions and 100 deletions
32
Cargo.lock
generated
32
Cargo.lock
generated
|
@ -2347,13 +2347,19 @@ name = "dioxus"
|
|||
version = "0.4.3"
|
||||
dependencies = [
|
||||
"criterion 0.3.6",
|
||||
"dioxus-config-macro",
|
||||
"dioxus-core",
|
||||
"dioxus-core-macro",
|
||||
"dioxus-desktop",
|
||||
"dioxus-fullstack",
|
||||
"dioxus-hooks",
|
||||
"dioxus-hot-reload",
|
||||
"dioxus-html",
|
||||
"dioxus-liveview",
|
||||
"dioxus-router",
|
||||
"dioxus-rsx",
|
||||
"dioxus-signals",
|
||||
"dioxus-web",
|
||||
"env_logger",
|
||||
"futures-util",
|
||||
"rand 0.8.5",
|
||||
|
@ -2463,6 +2469,14 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-config-macro"
|
||||
version = "0.4.3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-core"
|
||||
version = "0.4.3"
|
||||
|
@ -2513,7 +2527,6 @@ dependencies = [
|
|||
"async-trait",
|
||||
"core-foundation",
|
||||
"crossbeam-channel",
|
||||
"dioxus",
|
||||
"dioxus-cli-config",
|
||||
"dioxus-core",
|
||||
"dioxus-core-macro",
|
||||
|
@ -2594,7 +2607,7 @@ dependencies = [
|
|||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"ciborium",
|
||||
"dioxus",
|
||||
"dioxus-core",
|
||||
"dioxus-desktop",
|
||||
"dioxus-hot-reload",
|
||||
"dioxus-router",
|
||||
|
@ -2703,13 +2716,25 @@ dependencies = [
|
|||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-lib"
|
||||
version = "0.4.3"
|
||||
dependencies = [
|
||||
"dioxus-config-macro",
|
||||
"dioxus-core",
|
||||
"dioxus-core-macro",
|
||||
"dioxus-hooks",
|
||||
"dioxus-html",
|
||||
"dioxus-rsx",
|
||||
"dioxus-signals",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dioxus-liveview"
|
||||
version = "0.4.3"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum 0.6.20",
|
||||
"dioxus",
|
||||
"dioxus-core",
|
||||
"dioxus-hot-reload",
|
||||
"dioxus-html",
|
||||
|
@ -2806,6 +2831,7 @@ dependencies = [
|
|||
"dioxus",
|
||||
"dioxus-cli-config",
|
||||
"dioxus-desktop",
|
||||
"dioxus-lib",
|
||||
"dioxus-liveview",
|
||||
"dioxus-router",
|
||||
"dioxus-router-macro",
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
resolver = "2"
|
||||
members = [
|
||||
"packages/dioxus",
|
||||
"packages/dioxus-lib",
|
||||
"packages/core",
|
||||
"packages/cli",
|
||||
"packages/cli-config",
|
||||
"packages/core-macro",
|
||||
"packages/config-macro",
|
||||
"packages/router-macro",
|
||||
"packages/extension",
|
||||
"packages/router",
|
||||
|
@ -57,8 +59,10 @@ version = "0.4.3"
|
|||
# dependencies that are shared across packages
|
||||
[workspace.dependencies]
|
||||
dioxus = { path = "packages/dioxus", version = "0.4.0" }
|
||||
dioxus-lib = { path = "packages/dioxus-lib", version = "0.4.0" }
|
||||
dioxus-core = { path = "packages/core", version = "0.4.2" }
|
||||
dioxus-core-macro = { path = "packages/core-macro", version = "0.4.0" }
|
||||
dioxus-core-macro = { path = "packages/core-macro", version = "0.4.0" }
|
||||
dioxus-config-macro = { path = "packages/config-macro", version = "0.4.0" }
|
||||
dioxus-router = { path = "packages/router", version = "0.4.1" }
|
||||
dioxus-router-macro = { path = "packages/router-macro", version = "0.4.1" }
|
||||
dioxus-html = { path = "packages/html", default-features = false, version = "0.4.0" }
|
||||
|
|
26
packages/config-macro/Cargo.toml
Normal file
26
packages/config-macro/Cargo.toml
Normal file
|
@ -0,0 +1,26 @@
|
|||
[package]
|
||||
name = "dioxus-config-macro"
|
||||
version = { workspace = true }
|
||||
authors = ["Jonathan Kelley"]
|
||||
edition = "2021"
|
||||
description = "Configuration macros for Dioxus"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/DioxusLabs/dioxus/"
|
||||
homepage = "https://dioxuslabs.com"
|
||||
keywords = ["dom", "ui", "gui", "react"]
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = { version = "1.0" }
|
||||
quote = "1.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
fullstack = []
|
||||
desktop = []
|
||||
web = []
|
||||
ssr = []
|
||||
liveview = []
|
||||
tui = []
|
39
packages/config-macro/README.md
Normal file
39
packages/config-macro/README.md
Normal file
|
@ -0,0 +1,39 @@
|
|||
# dioxus-config-macro
|
||||
|
||||
[![Crates.io][crates-badge]][crates-url]
|
||||
[![MIT licensed][mit-badge]][mit-url]
|
||||
[![Build Status][actions-badge]][actions-url]
|
||||
[![Discord chat][discord-badge]][discord-url]
|
||||
|
||||
[crates-badge]: https://img.shields.io/crates/v/dioxus-config-macro.svg
|
||||
[crates-url]: https://crates.io/crates/dioxus-config-macro
|
||||
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
||||
[mit-url]: https://github.com/dioxuslabs/dioxus/blob/master/LICENSE
|
||||
[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
|
||||
[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
|
||||
[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
|
||||
[discord-url]: https://discord.gg/XgGxMSkvUM
|
||||
|
||||
[Website](https://dioxuslabs.com) |
|
||||
[Guides](https://dioxuslabs.com/learn/0.4/) |
|
||||
[API Docs](https://docs.rs/dioxus-config-macro/latest/dioxus_core_macro) |
|
||||
[Chat](https://discord.gg/XgGxMSkvUM)
|
||||
|
||||
## Overview
|
||||
|
||||
`dioxus-config-macro` provides a handful of helpful macros to make it easier to work with optional sections of the launch builder.
|
||||
|
||||
## Contributing
|
||||
|
||||
- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
|
||||
- Join the discord and ask questions!
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the [MIT license].
|
||||
|
||||
[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in Dioxus by you shall be licensed as MIT without any additional
|
||||
terms or conditions.
|
112
packages/config-macro/src/lib.rs
Normal file
112
packages/config-macro/src/lib.rs
Normal file
|
@ -0,0 +1,112 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")]
|
||||
#![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn server(input: TokenStream) -> TokenStream {
|
||||
if cfg!(any(feature = "ssr", feature = "liveview")) {
|
||||
let input = TokenStream2::from(input);
|
||||
quote! {
|
||||
Some(#input)
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
None
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn client(input: TokenStream) -> TokenStream {
|
||||
if cfg!(any(feature = "desktop", feature = "web", feature = "tui")) {
|
||||
let input = TokenStream2::from(input);
|
||||
quote! {
|
||||
Some(#input)
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
None
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn desktop(input: TokenStream) -> TokenStream {
|
||||
if cfg!(feature = "desktop") {
|
||||
let input = TokenStream2::from(input);
|
||||
quote! {
|
||||
Some(#input)
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
None
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn fullstack(input: TokenStream) -> TokenStream {
|
||||
if cfg!(feature = "web") {
|
||||
let input = TokenStream2::from(input);
|
||||
quote! {
|
||||
Some(#input)
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
None
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn ssr(input: TokenStream) -> TokenStream {
|
||||
if cfg!(feature = "ssr") {
|
||||
let input = TokenStream2::from(input);
|
||||
quote! {
|
||||
Some(#input)
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
None
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn liveview(input: TokenStream) -> TokenStream {
|
||||
if cfg!(feature = "liveview") {
|
||||
let input = TokenStream2::from(input);
|
||||
quote! {
|
||||
Some(#input)
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
None
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn tui(input: TokenStream) -> TokenStream {
|
||||
if cfg!(feature = "tui") {
|
||||
let input = TokenStream2::from(input);
|
||||
quote! {
|
||||
Some(#input)
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
None
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
|
@ -185,7 +185,7 @@ impl Parse for ComponentBody {
|
|||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let item_fn: ItemFn = input.parse()?;
|
||||
|
||||
let element_type_path = "::dioxus::core::Element";
|
||||
let element_type_path = "dioxus_core::Element";
|
||||
|
||||
if item_fn.sig.output == ReturnType::Default {
|
||||
return Err(Error::new(
|
||||
|
|
|
@ -691,7 +691,7 @@ Finally, call `.build()` to create the instance of `{name}`.
|
|||
_phantom: (#( #phantom_generics ),*),
|
||||
}
|
||||
|
||||
impl #impl_generics ::dioxus::prelude::Properties for #name #ty_generics
|
||||
impl #impl_generics dioxus_core::prelude::Properties for #name #ty_generics
|
||||
#b_generics_where_extras_predicates
|
||||
{
|
||||
type Builder = #builder_name #generics_with_empty;
|
||||
|
@ -826,20 +826,20 @@ Finally, call `.build()` to create the instance of `{name}`.
|
|||
|
||||
Ok(quote! {
|
||||
#[allow(dead_code, non_camel_case_types, missing_docs)]
|
||||
impl #impl_generics ::dioxus::prelude::HasAttributes for #builder_name < #( #ty_generics ),* > #where_clause {
|
||||
impl #impl_generics dioxus_core::prelude::HasAttributes for #builder_name < #( #ty_generics ),* > #where_clause {
|
||||
fn push_attribute(
|
||||
mut self,
|
||||
name: &'static str,
|
||||
ns: Option<&'static str>,
|
||||
attr: impl ::dioxus::prelude::IntoAttributeValue,
|
||||
attr: impl dioxus_core::prelude::IntoAttributeValue,
|
||||
volatile: bool
|
||||
) -> Self {
|
||||
let ( #(#descructuring,)* ) = self.fields;
|
||||
self.#field_name.push(
|
||||
::dioxus::core::Attribute::new(
|
||||
dioxus_core::Attribute::new(
|
||||
name,
|
||||
{
|
||||
use ::dioxus::prelude::IntoAttributeValue;
|
||||
use dioxus_core::prelude::IntoAttributeValue;
|
||||
attr.into_value()
|
||||
},
|
||||
ns,
|
||||
|
|
|
@ -34,7 +34,7 @@ The `dioxus` crate exports the `rsx` macro which transforms a helpful, simpler s
|
|||
First, start with your app:
|
||||
|
||||
```rust
|
||||
# use dioxus::core::Mutations;
|
||||
# use dioxus::dioxus_core::Mutations;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
// First, declare a root component
|
||||
|
|
|
@ -73,10 +73,11 @@ pub(crate) mod innerlude {
|
|||
|
||||
pub use crate::innerlude::{
|
||||
fc_to_builder, generation, schedule_update, schedule_update_any, use_hook, vdom_is_rendering,
|
||||
AnyValue, Attribute, AttributeValue, CapturedError, Component, DynamicNode, Element, ElementId,
|
||||
Event, Fragment, HasAttributes, IntoDynNode, Mutation, Mutations, NoOpMutations, Properties,
|
||||
RenderReturn, ScopeId, ScopeState, Task, Template, TemplateAttribute, TemplateNode, VComponent,
|
||||
VNode, VNodeInner, VPlaceholder, VText, VirtualDom, WriteMutations,
|
||||
AnyValue, Attribute, AttributeValue, CapturedError, Component, ComponentFunction, DynamicNode,
|
||||
Element, ElementId, Event, Fragment, HasAttributes, IntoDynNode, Mutation, Mutations,
|
||||
NoOpMutations, Properties, RenderReturn, ScopeId, ScopeState, Task, Template,
|
||||
TemplateAttribute, TemplateNode, VComponent, VNode, VNodeInner, VPlaceholder, VText,
|
||||
VirtualDom, WriteMutations,
|
||||
};
|
||||
|
||||
/// The purpose of this module is to alleviate imports of many common types
|
||||
|
|
|
@ -113,8 +113,10 @@ where
|
|||
///
|
||||
/// > Note: If you get an error about the `ComponentFunction` trait not being implemented: make sure your props implements the `Properties` trait or if you would like to declare your props inline, make sure you use the #[component] macro on your function.
|
||||
pub trait ComponentFunction<P> {
|
||||
/// The props type for this component.
|
||||
type Props: 'static;
|
||||
|
||||
/// Run the component function with the given props.
|
||||
fn call(&self, props: Self::Props) -> Element;
|
||||
}
|
||||
|
||||
|
|
|
@ -147,6 +147,23 @@ impl ScopeContext {
|
|||
}
|
||||
}
|
||||
|
||||
/// Inject a Box<dyn Any> into the context of this scope
|
||||
pub(crate) fn provide_any_context(&self, mut value: Box<dyn Any>) {
|
||||
let mut contexts = self.shared_contexts.borrow_mut();
|
||||
|
||||
// If the context exists, swap it out for the new value
|
||||
for ctx in contexts.iter_mut() {
|
||||
// Swap the ptr directly
|
||||
if ctx.as_ref().type_id() == value.as_ref().type_id() {
|
||||
std::mem::swap(ctx, &mut value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Else, just push it
|
||||
contexts.push(value);
|
||||
}
|
||||
|
||||
/// Expose state to children further down the [`crate::VirtualDom`] Tree. Requires `Clone` on the context to allow getting values down the tree.
|
||||
///
|
||||
/// This is a "fundamental" operation and should only be called during initialization of a hook.
|
||||
|
|
|
@ -325,6 +325,14 @@ impl VirtualDom {
|
|||
self
|
||||
}
|
||||
|
||||
/// Build the virtualdom with a global context inserted into the base scope
|
||||
///
|
||||
/// This method is useful for when you want to provide a context in your app without knowing its type
|
||||
pub fn with_boxed_root_context(self, context: Box<dyn Any>) -> Self {
|
||||
self.base_scope().context().provide_any_context(context);
|
||||
self
|
||||
}
|
||||
|
||||
/// Manually mark a scope as requiring a re-render
|
||||
///
|
||||
/// Whenever the Runtime "works", it will re-render this scope
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//!
|
||||
//! This tests to ensure we clean it up
|
||||
|
||||
use dioxus::core::{ElementId, Mutation::*};
|
||||
use dioxus::dioxus_core::{ElementId, Mutation::*};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::core::{ElementId, Mutation::*};
|
||||
use dioxus::dioxus_core::{ElementId, Mutation::*};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::core::{ElementId, Mutation::*};
|
||||
use dioxus::dioxus_core::{ElementId, Mutation::*};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! This methods all use "rebuild_to_vec" which completely bypasses the scheduler.
|
||||
//! Hard rebuild_to_vecs don't consume any events from the event queue.
|
||||
|
||||
use dioxus::core::Mutation::*;
|
||||
use dioxus::dioxus_core::Mutation::*;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_core::ElementId;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// use dioxus::core::Mutation::*;
|
||||
// use dioxus::dioxus_core::Mutation::*;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Do we create fragments properly across complex boundaries?
|
||||
|
||||
use dioxus::core::Mutation::*;
|
||||
use dioxus::dioxus_core::Mutation::*;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_core::ElementId;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::core::Mutation::*;
|
||||
use dioxus::dioxus_core::Mutation::*;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_core::ElementId;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::core::Mutation::*;
|
||||
use dioxus::dioxus_core::Mutation::*;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_core::ElementId;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::core::{ElementId, Mutation::*};
|
||||
use dioxus::dioxus_core::{ElementId, Mutation::*};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
/// As we clean up old templates, the ID for the node should cycle
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::core::{ElementId, Mutation::*};
|
||||
use dioxus::dioxus_core::{ElementId, Mutation::*};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
/// When returning sets of components, we do a light diff of the contents to preserve some react-like functionality
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::core::Mutation::*;
|
||||
use dioxus::dioxus_core::Mutation::*;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_core::{ElementId, NoOpMutations};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//!
|
||||
//! It does not validated that component lifecycles work properly. This is done in another test file.
|
||||
|
||||
use dioxus::core::{ElementId, Mutation::*};
|
||||
use dioxus::dioxus_core::{ElementId, Mutation::*};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
/// Should result in moves, but not removals or additions
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::core::{ElementId, Mutation::*};
|
||||
use dioxus::dioxus_core::{ElementId, Mutation::*};
|
||||
use dioxus::prelude::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::core::{ElementId, Mutation};
|
||||
use dioxus::dioxus_core::{ElementId, Mutation};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn basic_syntax_is_a_template() -> Element {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
//! Tests for the lifecycle of components.
|
||||
use dioxus::core::{ElementId, Mutation::*};
|
||||
use dioxus::dioxus_core::{ElementId, Mutation::*};
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_html::SerializedHtmlEventConverter;
|
||||
use std::rc::Rc;
|
||||
|
|
|
@ -81,7 +81,6 @@ features = ["tokio_runtime", "hot-reload"]
|
|||
[dev-dependencies]
|
||||
dioxus-core-macro = { workspace = true }
|
||||
dioxus-hooks = { workspace = true }
|
||||
dioxus = { workspace = true }
|
||||
exitcode = "1.1.2"
|
||||
scraper = "0.16.0"
|
||||
|
||||
|
|
27
packages/dioxus-lib/Cargo.toml
Normal file
27
packages/dioxus-lib/Cargo.toml
Normal file
|
@ -0,0 +1,27 @@
|
|||
[package]
|
||||
name = "dioxus-lib"
|
||||
version = { workspace = true }
|
||||
authors = ["Jonathan Kelley", "Dioxus Labs", "ealmloff"]
|
||||
edition = "2021"
|
||||
description = "Portable, performant, and ergonomic framework for building cross-platform user interfaces in Rust"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/DioxusLabs/dioxus/"
|
||||
homepage = "https://dioxuslabs.com/learn/0.4/"
|
||||
keywords = ["dom", "ui", "gui", "react", "wasm"]
|
||||
rust-version = "1.65.0"
|
||||
|
||||
[dependencies]
|
||||
dioxus-core = { workspace = true }
|
||||
dioxus-html = { workspace = true, optional = true }
|
||||
dioxus-core-macro = { workspace = true, optional = true }
|
||||
dioxus-config-macro = { workspace = true, optional = true }
|
||||
dioxus-hooks = { workspace = true, optional = true }
|
||||
dioxus-rsx = { workspace = true, optional = true }
|
||||
dioxus-signals = { workspace = true, optional = true }
|
||||
|
||||
[features]
|
||||
default = ["macro", "html", "signals"]
|
||||
signals = ["dioxus-signals"]
|
||||
macro = ["dioxus-core-macro", "dioxus-rsx"]
|
||||
html = ["dioxus-html"]
|
||||
hooks = ["dioxus-hooks"]
|
341
packages/dioxus-lib/README.md
Normal file
341
packages/dioxus-lib/README.md
Normal file
|
@ -0,0 +1,341 @@
|
|||
<div style="text-align: center">
|
||||
<h1>🌗🚀 Dioxus</h1>
|
||||
<p>
|
||||
<strong>A concurrent, functional, virtual DOM for Rust</strong>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
# Resources
|
||||
|
||||
This overview provides a brief introduction to Dioxus. For a more in-depth guide, make sure to check out:
|
||||
|
||||
- [Getting Started](https://dioxuslabs.com/learn/0.4/getting_started)
|
||||
- [Book (0.4)](https://dioxuslabs.com/learn/0.4/)
|
||||
- [Examples](https://github.com/DioxusLabs/example-projects)
|
||||
|
||||
# Overview and Goals
|
||||
|
||||
Dioxus makes it easy to quickly build complex user interfaces with Rust. Any Dioxus app can run in the web browser,
|
||||
as a desktop app, as a mobile app, or anywhere else provided you build the right renderer.
|
||||
|
||||
Dioxus is heavily inspired by React, supporting many of the same concepts:
|
||||
|
||||
- Hooks for state
|
||||
- VirtualDom & diffing
|
||||
- Concurrency, fibers, and asynchronous rendering
|
||||
- JSX-like templating syntax
|
||||
|
||||
If you know React, then you know Dioxus.
|
||||
|
||||
Dioxus is _substantially_ more performant than many of the other Rust UI libraries (Yew/Percy) and is _significantly_ more performant
|
||||
than React—roughly competitive with InfernoJS.
|
||||
|
||||
Remember: Dioxus is a library for declaring interactive user interfaces—it is not a dedicated renderer. Most 1st party renderers for Dioxus currently only support web technologies.
|
||||
|
||||
## Brief Overview
|
||||
|
||||
All Dioxus apps are built by composing functions that take in a `Scope` which is generic over some `Properties` and return an `Element`.
|
||||
A `Scope` holds relevant state data for the currently rendered component.
|
||||
|
||||
To launch an app, we use the `launch` method for the specific renderer we want to use. In the launch function, we pass the app's `Component`.
|
||||
|
||||
```rust, ignore
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus_desktop::launch(App);
|
||||
}
|
||||
|
||||
// The #[component] attribute streamlines component creation.
|
||||
// It's not required, but highly recommended. For example, UpperCamelCase components will not generate a warning.
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
rsx!("hello world!"))
|
||||
}
|
||||
```
|
||||
|
||||
## Elements & your first component
|
||||
|
||||
To assemble UI trees with Dioxus, you need to use the `render` function on
|
||||
something called `LazyNodes`. To produce `LazyNodes`, you can use the `rsx!`
|
||||
macro or the NodeFactory API. For the most part, you want to use the `rsx!`
|
||||
macro.
|
||||
|
||||
Any element in `rsx!` can have attributes, listeners, and children. For
|
||||
consistency, we force all attributes and listeners to be listed _before_
|
||||
children.
|
||||
|
||||
```rust, ignore
|
||||
let value = "123";
|
||||
|
||||
rsx!(
|
||||
div {
|
||||
class: "my-class {value}", // <--- attribute
|
||||
onclick: move |_| log::info!("clicked!"), // <--- listener
|
||||
h1 { "hello world" }, // <--- child
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
The `rsx!` macro accepts attributes in "struct form" and will parse the rest
|
||||
of the body as child elements and rust expressions. Any rust expression that
|
||||
implements `IntoIterator<Item = impl IntoVNode>` will be parsed as a child.
|
||||
|
||||
```rust, ignore
|
||||
rsx!(
|
||||
div {
|
||||
(0..10).map(|_| rsx!(span { "hello world" }))
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
Used within components, the `rsx!` macro must be rendered into an `Element` with
|
||||
the `render` function on Scope.
|
||||
|
||||
If we want to omit the boilerplate of `cx.render`, we can simply pass in
|
||||
`cx` as the first argument of rsx. This is sometimes useful when we need to
|
||||
render nodes in match statements.
|
||||
|
||||
```rust, ignore
|
||||
#[component[
|
||||
fn Example() -> Element {
|
||||
|
||||
// both of these are equivalent
|
||||
rsx!("hello world"))
|
||||
|
||||
render!("hello world!")
|
||||
}
|
||||
```
|
||||
|
||||
Putting everything together, we can write a simple component that renders a list of
|
||||
elements:
|
||||
|
||||
```rust, ignore
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
let name = "dave";
|
||||
rsx!(
|
||||
h1 { "Hello, {name}!" }
|
||||
div {
|
||||
class: "my-class",
|
||||
id: "my-id",
|
||||
|
||||
(0..5).map(|i| rsx!(
|
||||
div { key: "{i}"
|
||||
"FizzBuzz: {i}"
|
||||
}
|
||||
))
|
||||
|
||||
}
|
||||
))
|
||||
}
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
We can compose these function components to build a complex app. Each new
|
||||
component we design must take some Properties. For components with no explicit
|
||||
properties, we can use the `()` type or simply omit the type altogether.
|
||||
|
||||
In Dioxus, all properties are memoized by default!
|
||||
|
||||
```rust, ignore
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
rsx!(
|
||||
Header {
|
||||
title: "My App",
|
||||
color: "red",
|
||||
}
|
||||
))
|
||||
}
|
||||
```
|
||||
|
||||
Our `Header` component takes a `title` and a `color` property, which we
|
||||
declare on an explicit `HeaderProps` struct.
|
||||
|
||||
```rust, ignore
|
||||
// The `Props` derive macro lets us add additional functionality to how props are interpreted.
|
||||
#[derive(Props, PartialEq)]
|
||||
struct HeaderProps {
|
||||
title: String,
|
||||
color: String,
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Header(cx: Scope<HeaderProps>) -> Element {
|
||||
rsx!(
|
||||
div {
|
||||
background_color: "{cx.props.color}"
|
||||
h1 { "{cx.props.title}" }
|
||||
}
|
||||
))
|
||||
}
|
||||
```
|
||||
|
||||
The `#[component]` macro also allows you to derive the props
|
||||
struct from function arguments:
|
||||
|
||||
```rust, ignore
|
||||
#[component]
|
||||
fn Header(title: String, color: String) -> Element {
|
||||
rsx!(
|
||||
div {
|
||||
background_color: "{color}"
|
||||
h1 { "{title}" }
|
||||
}
|
||||
))
|
||||
}
|
||||
```
|
||||
|
||||
Components may also borrow data from their parent component. We just need to
|
||||
attach some lifetimes to the props struct.
|
||||
|
||||
> Note: we don't need to derive `PartialEq` for borrowed props since they cannot be memoized.
|
||||
|
||||
```rust, ignore
|
||||
#[derive(Props)]
|
||||
struct HeaderProps<'a> {
|
||||
title: &'a str,
|
||||
color: &'a str,
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Header(props: HeaderProps -> Element {
|
||||
rsx!(
|
||||
div {
|
||||
background_color: "{cx.props.color}"
|
||||
h1 { "{cx.props.title}" }
|
||||
}
|
||||
))
|
||||
}
|
||||
```
|
||||
|
||||
Components that begin with an uppercase letter may be called with
|
||||
the traditional (for React) curly-brace syntax like so:
|
||||
|
||||
```rust, ignore
|
||||
rsx!(
|
||||
Header { title: "My App" }
|
||||
)
|
||||
```
|
||||
|
||||
Alternatively, if your components begin with a lowercase letter, you can use
|
||||
the function call syntax:
|
||||
|
||||
```rust, ignore
|
||||
rsx!(
|
||||
header( title: "My App" )
|
||||
)
|
||||
```
|
||||
|
||||
However, the convention is to use UpperCamelCase. The `#[component]` attribute will enforce this,
|
||||
but you can turn it off if you wish.
|
||||
|
||||
## Hooks
|
||||
|
||||
While components are reusable forms of UI elements, hooks are reusable forms
|
||||
of logic. Hooks provide us a way of retrieving state from the `Scope` and using
|
||||
it to render UI elements.
|
||||
|
||||
By convention, all hooks are functions that should start with `use_`. We can
|
||||
use hooks to define the state and modify it from within listeners.
|
||||
|
||||
```rust, ignore
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
let name = use_signal(|| "world");
|
||||
|
||||
render!("hello {name}!")
|
||||
}
|
||||
```
|
||||
|
||||
Hooks are sensitive to how they are used. To use hooks, you must abide by the
|
||||
["rules of hooks" (borrowed from React)](https://reactjs.org/docs/hooks-rules.html):
|
||||
|
||||
- Functions with "use\_" should not be called in callbacks
|
||||
- Functions with "use\_" should not be called out of order
|
||||
- Functions with "use\_" should not be called in loops or conditionals
|
||||
|
||||
In a sense, hooks let us add a field of state to our component without declaring
|
||||
an explicit state struct. However, this means we need to "load" the struct in the right
|
||||
order. If that order is wrong, then the hook will pick the wrong state and panic.
|
||||
|
||||
Most hooks you'll write are simply compositions of other hooks:
|
||||
|
||||
```rust, ignore
|
||||
fn use_username(d: Uuid) -> bool {
|
||||
let users = use_context::<Users>();
|
||||
users.get(&id).map(|user| user.logged_in).ok_or(false)
|
||||
}
|
||||
```
|
||||
|
||||
To create entirely new foundational hooks, we can use the `use_hook` method on `ScopeState`.
|
||||
|
||||
```rust, ignore
|
||||
fn use_mut_string() -> &mut String {
|
||||
cx.use_hook(|_| "Hello".to_string())
|
||||
}
|
||||
```
|
||||
|
||||
If you want to extend Dioxus with some new functionality, you'll probably want to implement a new hook from scratch.
|
||||
|
||||
## Putting it all together
|
||||
|
||||
Using components, templates, and hooks, we can build a simple app.
|
||||
|
||||
```rust, ignore
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus_desktop::launch(App);
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
let count = use_signal(|| 0);
|
||||
|
||||
rsx!(
|
||||
div { "Count: {count}" }
|
||||
button { onclick: move |_| count.set(count + 1), "Increment" }
|
||||
button { onclick: move |_| count.set(count - 1), "Decrement" }
|
||||
))
|
||||
}
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
This overview doesn't cover everything. Make sure to check out the tutorial and reference guide on the official
|
||||
website for more details.
|
||||
|
||||
Beyond this overview, Dioxus supports:
|
||||
|
||||
- Server-side rendering
|
||||
- Concurrent rendering (with async support)
|
||||
- Web/Desktop/Mobile support
|
||||
- Pre-rendering and rehydration
|
||||
- Fragments, Portals, and Suspense
|
||||
- Inline-styles
|
||||
- Custom event handlers
|
||||
- Custom elements
|
||||
- Basic fine-grained reactivity (IE SolidJS/Svelte)
|
||||
- and more!
|
||||
|
||||
Good luck!
|
||||
|
||||
## Inspiration, Resources, Alternatives, and Credits
|
||||
|
||||
Dioxus is inspired by:
|
||||
|
||||
- React: for its hooks, concurrency, suspense
|
||||
- Dodrio: for its research in bump allocation, double buffering, and diffing architecture
|
||||
|
||||
Alternatives to Dioxus include:
|
||||
|
||||
- Yew: supports function components and web, but no SSR, borrowed data, or bump allocation. Rather slow at times.
|
||||
- Percy: supports function components, web, ssr, but lacks state management
|
||||
- Sycamore: supports function components, web, ssr, but is closer to SolidJS than React
|
||||
- MoonZoom/Seed: opinionated frameworks based on the Elm model (message, update)—no hooks
|
||||
|
||||
We've put a lot of work into making Dioxus ergonomic and _familiar_.
|
||||
Our target audience is TypeScript developers looking to switch to Rust for the web—so we need to be comparable to React.
|
48
packages/dioxus-lib/src/lib.rs
Normal file
48
packages/dioxus-lib/src/lib.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")]
|
||||
#![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
|
||||
|
||||
#[cfg(feature = "hooks")]
|
||||
pub use dioxus_hooks as hooks;
|
||||
|
||||
#[cfg(feature = "signals")]
|
||||
pub use dioxus_signals as signals;
|
||||
|
||||
pub mod events {
|
||||
#[cfg(feature = "html")]
|
||||
pub use dioxus_html::prelude::*;
|
||||
}
|
||||
|
||||
#[cfg(feature = "html")]
|
||||
pub use dioxus_html as html;
|
||||
|
||||
#[cfg(feature = "macro")]
|
||||
pub use dioxus_rsx as rsx;
|
||||
|
||||
#[cfg(feature = "macro")]
|
||||
pub use dioxus_core_macro as core_macro;
|
||||
|
||||
pub mod prelude {
|
||||
#[cfg(feature = "hooks")]
|
||||
pub use crate::hooks::*;
|
||||
|
||||
#[cfg(feature = "signals")]
|
||||
pub use dioxus_signals::*;
|
||||
|
||||
pub use dioxus_core::prelude::*;
|
||||
|
||||
#[cfg(feature = "macro")]
|
||||
#[allow(deprecated)]
|
||||
pub use dioxus_core_macro::{component, format_args_f, inline_props, render, rsx, Props};
|
||||
|
||||
#[cfg(feature = "launch")]
|
||||
pub use dioxus_config_macro::*;
|
||||
|
||||
#[cfg(feature = "html")]
|
||||
pub use dioxus_html as dioxus_elements;
|
||||
|
||||
#[cfg(feature = "html")]
|
||||
pub use dioxus_elements::{prelude::*, GlobalAttributes, SvgAttributes};
|
||||
|
||||
pub use dioxus_core;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::core::RenderReturn;
|
||||
use dioxus::dioxus_core::RenderReturn;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_tui::DioxusElementToNodeId;
|
||||
use dioxus_tui::Query;
|
||||
|
|
|
@ -14,21 +14,38 @@ rust-version = "1.65.0"
|
|||
dioxus-core = { workspace = true }
|
||||
dioxus-html = { workspace = true, optional = true }
|
||||
dioxus-core-macro = { workspace = true, optional = true }
|
||||
dioxus-config-macro = { workspace = true, optional = true }
|
||||
dioxus-hooks = { workspace = true, optional = true }
|
||||
dioxus-rsx = { workspace = true, optional = true }
|
||||
dioxus-signals = { workspace = true, optional = true }
|
||||
dioxus-router = { workspace = true, optional = true }
|
||||
dioxus-web = { workspace = true, optional = true }
|
||||
dioxus-desktop = { workspace = true, optional = true }
|
||||
dioxus-fullstack = { workspace = true, optional = true }
|
||||
dioxus-liveview = { workspace = true, optional = true }
|
||||
# dioxus-tui = { workspace = true, optional = true }
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
dioxus-hot-reload = { workspace = true, optional = true }
|
||||
|
||||
[features]
|
||||
default = ["macro", "html", "hot-reload", "signals"]
|
||||
default = ["macro", "html", "hot-reload", "signals", "launch"]
|
||||
signals = ["dioxus-signals"]
|
||||
macro = ["dioxus-core-macro", "dioxus-rsx"]
|
||||
html = ["dioxus-html"]
|
||||
hooks = ["dioxus-hooks"]
|
||||
hot-reload = ["dioxus-hot-reload"]
|
||||
|
||||
launch = ["dioxus-config-macro"]
|
||||
router = ["dioxus-router"]
|
||||
|
||||
# Platforms
|
||||
fullstack = ["dioxus-fullstack"]
|
||||
desktop = ["dioxus-desktop", "dioxus-fullstack?/desktop"]
|
||||
web = ["dioxus-web", "dioxus-fullstack?/web"]
|
||||
ssr = ["dioxus-fullstack?/ssr"]
|
||||
liveview = ["dioxus-desktop"]
|
||||
# tui = ["dioxus-tui"]
|
||||
|
||||
[dev-dependencies]
|
||||
futures-util = { workspace = true }
|
||||
|
|
102
packages/dioxus/src/launch.rs
Normal file
102
packages/dioxus/src/launch.rs
Normal file
|
@ -0,0 +1,102 @@
|
|||
//! Launch helper macros for fullstack apps
|
||||
#![allow(unused)]
|
||||
use std::any::Any;
|
||||
|
||||
use crate::prelude::*;
|
||||
use dioxus_core::prelude::*;
|
||||
use dioxus_core::ComponentFunction;
|
||||
|
||||
pub trait ClonableAny: Any {
|
||||
fn clone_box(&self) -> Box<dyn ClonableAny>;
|
||||
}
|
||||
|
||||
impl<T: Any + Clone> ClonableAny for T {
|
||||
fn clone_box(&self) -> Box<dyn ClonableAny> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// The platform-independent part of the config needed to launch an application.
|
||||
pub struct CrossPlatformConfig<F: ComponentFunction<P>, P> {
|
||||
/// The root component function.
|
||||
pub component: F,
|
||||
/// The props for the root component.
|
||||
pub props: P,
|
||||
/// The contexts to provide to the root component.
|
||||
pub root_contexts: Vec<Box<dyn ClonableAny>>,
|
||||
}
|
||||
|
||||
pub trait PlatformBuilder<P> {
|
||||
type Config;
|
||||
|
||||
/// Launch the app.
|
||||
fn launch<F: ComponentFunction<P>>(config: CrossPlatformConfig<F, P>, config: Self::Config);
|
||||
}
|
||||
|
||||
impl<P> PlatformBuilder<P> for () {
|
||||
type Config = ();
|
||||
|
||||
fn launch<F: ComponentFunction<P>>(config: CrossPlatformConfig<F, P>, _: ()) {}
|
||||
}
|
||||
|
||||
/// A builder for a fullstack app.
|
||||
pub struct LaunchBuilder<F: ComponentFunction<P>, P> {
|
||||
cross_platform_config: CrossPlatformConfig<F, P>,
|
||||
}
|
||||
|
||||
impl<F: ComponentFunction<P>, P> LaunchBuilder<F, P> {
|
||||
/// Create a new builder for your application.
|
||||
pub fn new(component: F) -> Self
|
||||
where
|
||||
P: Default,
|
||||
{
|
||||
Self {
|
||||
cross_platform_config: CrossPlatformConfig {
|
||||
component,
|
||||
props: Default::default(),
|
||||
root_contexts: vec![],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Pass some props to your application.
|
||||
pub fn props(mut self, props: P) -> Self {
|
||||
self.cross_platform_config.props = props;
|
||||
self
|
||||
}
|
||||
|
||||
/// Inject state into the root component's context.
|
||||
pub fn context(mut self, state: impl ClonableAny + 'static) -> Self {
|
||||
self.cross_platform_config
|
||||
.root_contexts
|
||||
.push(Box::new(state));
|
||||
self
|
||||
}
|
||||
|
||||
/// Provide a platform-specific config to the builder.
|
||||
pub fn platform_config(
|
||||
self,
|
||||
config: Option<<CurrentPlatform as PlatformBuilder<P>>::Config>,
|
||||
) -> Self {
|
||||
self
|
||||
}
|
||||
|
||||
/// Launch the app.
|
||||
pub fn launch(self) {}
|
||||
}
|
||||
|
||||
#[cfg(feature = "router")]
|
||||
impl<R: Routable> LaunchBuilder<crate::router::FullstackRouterConfig<R>>
|
||||
where
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
R: Clone + serde::Serialize + serde::de::DeserializeOwned + Send + Sync + 'static,
|
||||
{
|
||||
/// Create a new launch builder for the given router.
|
||||
pub fn router() -> Self {
|
||||
let component = crate::router::RouteWithCfg::<R>;
|
||||
let props = crate::router::FullstackRouterConfig::default();
|
||||
Self::new_with_props(component, props)
|
||||
}
|
||||
}
|
||||
|
||||
type CurrentPlatform = ();
|
|
@ -2,7 +2,12 @@
|
|||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")]
|
||||
#![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
|
||||
|
||||
pub use dioxus_core as core;
|
||||
pub use dioxus_core;
|
||||
|
||||
#[cfg(feature = "launch")]
|
||||
mod launch;
|
||||
#[cfg(feature = "launch")]
|
||||
pub use launch::*;
|
||||
|
||||
#[cfg(feature = "hooks")]
|
||||
pub use dioxus_hooks as hooks;
|
||||
|
@ -37,6 +42,9 @@ pub mod prelude {
|
|||
#[allow(deprecated)]
|
||||
pub use dioxus_core_macro::{component, format_args_f, inline_props, render, rsx, Props};
|
||||
|
||||
#[cfg(feature = "launch")]
|
||||
pub use dioxus_config_macro::*;
|
||||
|
||||
#[cfg(feature = "html")]
|
||||
pub use dioxus_html as dioxus_elements;
|
||||
|
||||
|
@ -45,4 +53,6 @@ pub mod prelude {
|
|||
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "hot-reload"))]
|
||||
pub use dioxus_hot_reload::{self, hot_reload_init};
|
||||
|
||||
pub use dioxus_core;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,9 @@ tower-http = { version = "0.4.0", optional = true, features = ["fs", "compressio
|
|||
salvo = { version = "0.63.0", optional = true, features = ["serve-static", "websocket", "compression"] }
|
||||
http-body-util = { version = "0.1.0-rc.2", optional = true }
|
||||
|
||||
dioxus-core = { workspace = true }
|
||||
|
||||
# Dioxus + SSR
|
||||
dioxus = { workspace = true }
|
||||
dioxus-ssr = { workspace = true, optional = true }
|
||||
hyper = { version = "0.14.25", optional = true }
|
||||
http = { version = "0.2.9", optional = true }
|
||||
|
@ -67,7 +68,6 @@ dioxus-hot-reload = { workspace = true }
|
|||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
web-sys = { version = "0.3.61", features = ["Window", "Document", "Element", "HtmlDocument", "Storage", "console"] }
|
||||
|
||||
|
||||
[features]
|
||||
default = ["hot-reload"]
|
||||
router = ["dioxus-router"]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::prelude::*;
|
||||
use dioxus_core::prelude::*;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use std::any::Any;
|
||||
use std::cell::Cell;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Launch helper macros for fullstack apps
|
||||
#![allow(unused)]
|
||||
use crate::prelude::*;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_core::prelude::*;
|
||||
#[cfg(feature = "router")]
|
||||
use dioxus_router::prelude::*;
|
||||
|
||||
|
|
|
@ -11,9 +11,6 @@ where
|
|||
{
|
||||
use dioxus_router::prelude::RouterConfig;
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
let context = crate::prelude::server_context();
|
||||
|
||||
let cfg = props;
|
||||
render! {
|
||||
dioxus_router::prelude::Router::<R> {
|
||||
|
@ -23,8 +20,9 @@ where
|
|||
.history({
|
||||
#[cfg(feature = "ssr")]
|
||||
let history = dioxus_router::prelude::MemoryHistory::with_initial_path(
|
||||
context
|
||||
.request_parts().unwrap()
|
||||
crate::prelude::server_context()
|
||||
.request_parts()
|
||||
.unwrap()
|
||||
.uri
|
||||
.to_string()
|
||||
.parse()
|
||||
|
@ -44,7 +42,7 @@ where
|
|||
);
|
||||
history
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ rocket_ws = { version = "0.1.0", optional = true }
|
|||
[dev-dependencies]
|
||||
pretty_env_logger = { version = "0.5.0" }
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
dioxus = { workspace = true }
|
||||
warp = "0.3.3"
|
||||
axum = { version = "0.6.1", features = ["ws"] }
|
||||
salvo = { version = "0.63.0", features = ["affix", "websocket"] }
|
||||
|
|
|
@ -189,7 +189,7 @@ fn create_random_dynamic_node(, depth: usize) -> DynamicNode {
|
|||
node_paths: &[&[0]],
|
||||
attr_paths: &[],
|
||||
}),
|
||||
dioxus::core::exports::bumpalo::collections::Vec::new_in(cx.bump()).into(),
|
||||
dioxus::dioxus_core::exports::bumpalo::collections::Vec::new_in(cx.bump()).into(),
|
||||
cx.bump().alloc([cx.component(
|
||||
create_random_element,
|
||||
DepthProps { depth, root: false },
|
||||
|
@ -260,7 +260,7 @@ fn create_random_element(cx: Scope<DepthProps>) -> Element {
|
|||
None.into(),
|
||||
None,
|
||||
Cell::new(template),
|
||||
dioxus::core::exports::bumpalo::collections::Vec::new_in(cx.bump()).into(),
|
||||
dioxus::dioxus_core::exports::bumpalo::collections::Vec::new_in(cx.bump()).into(),
|
||||
{
|
||||
let dynamic_nodes: Vec<_> = dynamic_node_types
|
||||
.iter()
|
||||
|
|
|
@ -10,7 +10,7 @@ homepage = "https://dioxuslabs.com"
|
|||
keywords = ["dom", "ui", "gui", "react", "wasm"]
|
||||
|
||||
[dependencies]
|
||||
dioxus = { workspace = true }
|
||||
dioxus-lib = { workspace = true }
|
||||
dioxus-router-macro = { workspace = true }
|
||||
gloo = { version = "0.8.0", optional = true }
|
||||
tracing = { workspace = true }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[allow(deprecated)]
|
||||
use crate::hooks::use_router;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_lib::prelude::*;
|
||||
|
||||
/// The default component to render when an external navigation fails.
|
||||
#[allow(non_snake_case)]
|
||||
|
@ -14,11 +14,6 @@ pub fn FailureExternalNavigation() -> Element {
|
|||
"The application tried to programmatically navigate to an external page. This "
|
||||
"operation has failed. Click the link below to complete the navigation manually."
|
||||
}
|
||||
a {
|
||||
onclick: move |_| {
|
||||
router.clear_error()
|
||||
},
|
||||
"Click here to go back"
|
||||
}
|
||||
a { onclick: move |_| { router.clear_error() }, "Click here to go back" }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use dioxus::prelude::*;
|
||||
use dioxus_lib::prelude::*;
|
||||
|
||||
use tracing::error;
|
||||
|
||||
use crate::utils::use_router_internal::use_router_internal;
|
||||
|
@ -76,12 +77,7 @@ pub fn GoBackButton(
|
|||
let disabled = !router.can_go_back();
|
||||
|
||||
render! {
|
||||
button {
|
||||
disabled: "{disabled}",
|
||||
prevent_default: "onclick",
|
||||
onclick: move |_| router.go_back(),
|
||||
{children}
|
||||
}
|
||||
button { disabled: "{disabled}", prevent_default: "onclick", onclick: move |_| router.go_back(), {children} }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,11 +147,6 @@ pub fn GoForwardButton(
|
|||
let disabled = !router.can_go_forward();
|
||||
|
||||
render! {
|
||||
button {
|
||||
disabled: "{disabled}",
|
||||
prevent_default: "onclick",
|
||||
onclick: move |_| router.go_forward(),
|
||||
{children}
|
||||
}
|
||||
button { disabled: "{disabled}", prevent_default: "onclick", onclick: move |_| router.go_forward(), {children} }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ use std::any::Any;
|
|||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_lib::prelude::*;
|
||||
|
||||
use tracing::error;
|
||||
|
||||
use crate::navigation::NavigationTarget;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::prelude::{outlet::OutletContext, *};
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_lib::prelude::*;
|
||||
|
||||
/// An outlet for the current content.
|
||||
///
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use dioxus::prelude::*;
|
||||
use dioxus_lib::prelude::*;
|
||||
|
||||
use std::{cell::RefCell, str::FromStr};
|
||||
|
||||
use crate::{prelude::Outlet, routable::Routable, router_cfg::RouterConfig};
|
||||
|
@ -142,9 +143,7 @@ where
|
|||
// _marker: std::marker::PhantomData,
|
||||
// });
|
||||
|
||||
render! {
|
||||
Outlet::<R> {}
|
||||
}
|
||||
render! { Outlet::<R> {} }
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
|
@ -169,7 +168,5 @@ where
|
|||
_marker: std::marker::PhantomData,
|
||||
});
|
||||
|
||||
render! {
|
||||
Outlet::<R> {}
|
||||
}
|
||||
render! { Outlet::<R> {} }
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::prelude::{ExternalNavigationFailure, IntoRoutable, RouterContext};
|
|||
/// Panics if there is no router present.
|
||||
pub fn navigator() -> Navigator {
|
||||
Navigator(
|
||||
dioxus::core::prelude::consume_context::<RouterContext>()
|
||||
dioxus_lib::prelude::consume_context::<RouterContext>()
|
||||
.expect("A router must be present to use navigator"),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::prelude::*;
|
||||
use dioxus_lib::prelude::*;
|
||||
|
||||
use crate::{routable::Routable, utils::use_router_internal::use_router_internal};
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::{
|
|||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_lib::prelude::*;
|
||||
|
||||
use crate::{
|
||||
navigation::NavigationTarget,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::prelude::{consume_context, use_hook};
|
||||
use dioxus_lib::prelude::{consume_context, use_hook};
|
||||
|
||||
use crate::prelude::{Navigator, RouterContext};
|
||||
|
||||
|
|
|
@ -9,5 +9,5 @@ pub fn use_router() -> RouterContext {
|
|||
|
||||
/// Aquire the router without subscribing to updates.
|
||||
pub fn router() -> RouterContext {
|
||||
dioxus::core::prelude::consume_context().unwrap()
|
||||
dioxus_lib::prelude::consume_context().unwrap()
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ pub mod prelude {
|
|||
type Props;
|
||||
}
|
||||
|
||||
impl<P> HasProps for dioxus::prelude::Component<P> {
|
||||
impl<P> HasProps for dioxus_lib::prelude::Component<P> {
|
||||
type Props = P;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! # Routable
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_lib::prelude::*;
|
||||
|
||||
use std::iter::FlatMap;
|
||||
use std::slice::Iter;
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||
use crate::contexts::router::RoutingCallback;
|
||||
use crate::history::HistoryProvider;
|
||||
use crate::routable::Routable;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_lib::prelude::*;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use dioxus::prelude::ScopeId;
|
||||
use dioxus_lib::prelude::ScopeId;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ impl ToTokens for ElementAttrNamed {
|
|||
let value = quote! { #value };
|
||||
|
||||
quote! {
|
||||
::dioxus::core::Attribute::new(
|
||||
dioxus_core::Attribute::new(
|
||||
#attribute,
|
||||
#value,
|
||||
#ns,
|
||||
|
|
|
@ -101,7 +101,7 @@ impl ToTokens for Component {
|
|||
let fn_name = self.fn_name();
|
||||
|
||||
tokens.append_all(quote! {
|
||||
::dioxus::core::DynamicNode::Component(::dioxus::core::VComponent::new(
|
||||
dioxus_core::DynamicNode::Component(dioxus_core::VComponent::new(
|
||||
#name #prop_gen_args,
|
||||
#builder,
|
||||
#fn_name
|
||||
|
|
|
@ -280,7 +280,7 @@ impl ToTokens for Element {
|
|||
});
|
||||
|
||||
tokens.append_all(quote! {
|
||||
::dioxus::core::Element::new(
|
||||
dioxus_core::Element::new(
|
||||
#name,
|
||||
vec![ #(#listeners),* ],
|
||||
vec![ #(#attr),* ],
|
||||
|
|
|
@ -85,7 +85,7 @@ impl CallBody {
|
|||
};
|
||||
|
||||
quote! {
|
||||
::dioxus::core::LazyNodes::new( move | __cx: &::dioxus::core::ScopeState| -> ::dioxus::core::VNode {
|
||||
dioxus_core::LazyNodes::new( move | __cx: &dioxus_core::ScopeState| -> dioxus_core::VNode {
|
||||
#body
|
||||
})
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ impl ToTokens for CallBody {
|
|||
};
|
||||
|
||||
out_tokens.append_all(quote! {
|
||||
::dioxus::core::LazyNodes::new( move | __cx: &::dioxus::core::ScopeState| -> ::dioxus::core::VNode {
|
||||
dioxus_core::LazyNodes::new( move | __cx: &dioxus_core::ScopeState| -> dioxus_core::VNode {
|
||||
#body
|
||||
})
|
||||
})
|
||||
|
@ -246,14 +246,14 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
|
|||
let attr_paths = context.attr_paths.iter().map(|it| quote!(&[#(#it),*]));
|
||||
|
||||
out_tokens.append_all(quote! {
|
||||
static TEMPLATE: ::dioxus::core::Template = ::dioxus::core::Template {
|
||||
static TEMPLATE: dioxus_core::Template = dioxus_core::Template {
|
||||
name: #name,
|
||||
roots: &[ #roots ],
|
||||
node_paths: &[ #(#node_paths),* ],
|
||||
attr_paths: &[ #(#attr_paths),* ],
|
||||
};
|
||||
|
||||
::dioxus::core::VNode::new(
|
||||
dioxus_core::VNode::new(
|
||||
#key_tokens,
|
||||
TEMPLATE,
|
||||
Box::new([ #( #node_printer),* ]),
|
||||
|
@ -491,7 +491,7 @@ impl<'a> DynamicContext<'a> {
|
|||
}
|
||||
};
|
||||
quote! {
|
||||
::dioxus::core::TemplateAttribute::Static {
|
||||
dioxus_core::TemplateAttribute::Static {
|
||||
name: #name,
|
||||
namespace: #ns,
|
||||
value: #value,
|
||||
|
@ -515,7 +515,7 @@ impl<'a> DynamicContext<'a> {
|
|||
let ct = self.dynamic_attributes.len();
|
||||
self.dynamic_attributes.push(vec![attr]);
|
||||
self.attr_paths.push(self.current_path.clone());
|
||||
quote! { ::dioxus::core::TemplateAttribute::Dynamic { id: #ct }, }
|
||||
quote! { dioxus_core::TemplateAttribute::Dynamic { id: #ct }, }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -536,7 +536,7 @@ impl<'a> DynamicContext<'a> {
|
|||
let el_name = el_name.tag_name();
|
||||
|
||||
quote! {
|
||||
::dioxus::core::TemplateNode::Element {
|
||||
dioxus_core::TemplateNode::Element {
|
||||
tag: #el_name,
|
||||
namespace: #ns,
|
||||
attrs: &[ #attrs ],
|
||||
|
@ -547,7 +547,7 @@ impl<'a> DynamicContext<'a> {
|
|||
|
||||
BodyNode::Text(text) if text.is_static() => {
|
||||
let text = text.to_static().unwrap();
|
||||
quote! { ::dioxus::core::TemplateNode::Text{ text: #text } }
|
||||
quote! { dioxus_core::TemplateNode::Text{ text: #text } }
|
||||
}
|
||||
|
||||
BodyNode::RawExpr(_)
|
||||
|
@ -561,9 +561,9 @@ impl<'a> DynamicContext<'a> {
|
|||
|
||||
match root {
|
||||
BodyNode::Text(_) => {
|
||||
quote! { ::dioxus::core::TemplateNode::DynamicText { id: #ct } }
|
||||
quote! { dioxus_core::TemplateNode::DynamicText { id: #ct } }
|
||||
}
|
||||
_ => quote! { ::dioxus::core::TemplateNode::Dynamic { id: #ct } },
|
||||
_ => quote! { dioxus_core::TemplateNode::Dynamic { id: #ct } },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ impl ToTokens for BodyNode {
|
|||
BodyNode::Element(el) => el.to_tokens(tokens),
|
||||
BodyNode::Component(comp) => comp.to_tokens(tokens),
|
||||
BodyNode::Text(txt) => tokens.append_all(quote! {
|
||||
::dioxus::core::DynamicNode::Text(::dioxus::core::VText::new(#txt))
|
||||
dioxus_core::DynamicNode::Text(dioxus_core::VText::new(#txt))
|
||||
}),
|
||||
BodyNode::RawExpr(exp) => tokens.append_all(quote! {
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue