diff --git a/Cargo.lock b/Cargo.lock index 1dfb4263a4..40578aaf47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2093,6 +2093,7 @@ name = "dioxus" version = "0.5.2" dependencies = [ "criterion 0.3.6", + "dioxus", "dioxus-config-macro", "dioxus-core 0.5.2", "dioxus-core-macro", @@ -2262,12 +2263,14 @@ dependencies = [ "rand 0.8.5", "reqwest", "rustc-hash", + "rustversion", "serde", "slab", "tokio", "tracing", "tracing-fluent-assertions", "tracing-subscriber", + "web-sys", ] [[package]] @@ -2410,6 +2413,8 @@ dependencies = [ "futures-channel", "futures-util", "generational-box", + "reqwest", + "rustversion", "slab", "thiserror", "tokio", @@ -2439,15 +2444,18 @@ name = "dioxus-html" version = "0.5.2" dependencies = [ "async-trait", + "dioxus", "dioxus-core 0.5.2", "dioxus-html-internal-macro", "dioxus-rsx", + "dioxus-web", "enumset", "euclid", "futures-channel", "generational-box", "keyboard-types", "rfd", + "rustversion", "serde", "serde-value", "serde_json", @@ -2588,6 +2596,7 @@ dependencies = [ "gloo", "gloo-utils 0.1.7", "js-sys", + "rustversion", "serde", "serde_json", "tokio", @@ -2635,6 +2644,8 @@ dependencies = [ "generational-box", "once_cell", "parking_lot", + "rand 0.8.5", + "reqwest", "rustc-hash", "serde", "simple_logger", @@ -7760,9 +7771,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" diff --git a/packages/check/src/metadata.rs b/packages/check/src/metadata.rs index 19c3b7f7b8..11777e6f2d 100644 --- a/packages/check/src/metadata.rs +++ b/packages/check/src/metadata.rs @@ -1,11 +1,11 @@ #[derive(Debug, Clone, PartialEq, Eq)] /// Information about a hook call or function. pub struct HookInfo { - /// The name of the hook, e.g. `use_state`. + /// The name of the hook, e.g. `use_signal`. pub name: String, - /// The span of the hook, e.g. `use_signal(|| 0)`. + /// The span of the hook, e.g. `use_signal`. pub span: Span, - /// The span of the name, e.g. `use_state`. + /// The span of the name, e.g. `use_signal`. pub name_span: Span, } diff --git a/packages/core-macro/src/lib.rs b/packages/core-macro/src/lib.rs index 65bc461987..6b87a17d8b 100644 --- a/packages/core-macro/src/lib.rs +++ b/packages/core-macro/src/lib.rs @@ -31,6 +31,191 @@ pub fn derive_typed_builder(input: TokenStream) -> TokenStream { } /// The rsx! macro makes it easy for developers to write jsx-style markup in their components. +/// +/// ## Elements +/// +/// You can render elements with rsx! with the element name and then braces surrounding the attributes and children. +/// +/// ```rust, no_run +/// # use dioxus::prelude::*; +/// rsx! { +/// div { +/// div {} +/// } +/// }; +/// ``` +/// +///
+/// Web Components +/// +/// +/// Dioxus will automatically render any elements with `-` as a untyped web component: +/// +/// ```rust, no_run +/// # use dioxus::prelude::*; +/// rsx! { +/// div-component { +/// div {} +/// } +/// }; +/// ``` +/// +/// You can wrap your web component in a custom component to add type checking: +/// ```rust, no_run +/// # use dioxus::prelude::*; +/// #[component] +/// fn MyDivComponent(width: i64) -> Element { +/// rsx! { +/// div-component { +/// "width": width +/// } +/// } +/// } +/// ``` +/// +/// +///
+/// +/// ## Attributes +/// +/// You can add attributes to any element inside the braces. Attributes are key-value pairs separated by a colon. +/// +/// ```rust, no_run +/// # use dioxus::prelude::*; +/// let width = 100; +/// rsx! { +/// div { +/// // Set the class attribute to "my-class" +/// class: "my-class", +/// // attribute strings are automatically formatted with the format macro +/// width: "{width}px", +/// } +/// }; +/// ``` +/// +/// ### Optional Attributes +/// +/// You can include optional attributes with an unterminated if statement as the value of the attribute: +/// +/// ```rust, no_run +/// # use dioxus::prelude::*; +/// # let first_boolean = true; +/// # let second_boolean = false; +/// rsx! { +/// div { +/// // Set the class attribute to "my-class" if true +/// class: if first_boolean { +/// "my-class" +/// }, +/// // Set the class attribute to "my-other-class" if false +/// class: if second_boolean { +/// "my-other-class" +/// } +/// } +/// }; +/// ``` +/// +/// ### Raw Attributes +/// +/// Dioxus defaults to attributes that are type checked as html. If you want to include an attribute that is not included in the html spec, you can use the `raw` attribute surrounded by quotes: +/// +/// ```rust, no_run +/// # use dioxus::prelude::*; +/// rsx! { +/// div { +/// // Set the data-count attribute to "1" +/// "data-count": "1" +/// } +/// }; +/// ``` +/// +/// ## Text +/// +/// You can include text in your markup as a string literal: +/// +/// ```rust, no_run +/// # use dioxus::prelude::*; +/// let name = "World"; +/// rsx! { +/// div { +/// "Hello World" +/// // Just like attributes, you can included formatted segments inside your text +/// "Hello {name}" +/// } +/// }; +/// ``` +/// +/// ## Components +/// +/// You can render any [`macro@crate::component`]s you created inside your markup just like elements. Components must either start with a capital letter or contain a `_` character. +/// +/// ```rust, no_run +/// # use dioxus::prelude::*; +/// #[component] +/// fn HelloWorld() -> Element { +/// rsx! { "hello world!" } +/// } +/// +/// rsx! { +/// div { +/// HelloWorld {} +/// } +/// }; +/// ``` +/// +/// ## If statements +/// +/// You can use if statements to conditionally render children. The body of the for if statement is parsed as rsx markup: +/// +/// ```rust, no_run +/// # use dioxus::prelude::*; +/// let first_boolean = true; +/// let second_boolean = false; +/// rsx! { +/// if first_boolean { +/// div { +/// "first" +/// } +/// } +/// +/// if second_boolean { +/// "second" +/// } +/// }; +/// ``` +/// +/// ## For loops +/// +/// You can also use for loops to iterate over a collection of items. The body of the for loop is parsed as rsx markup: +/// +/// ```rust, no_run +/// # use dioxus::prelude::*; +/// let numbers = vec![1, 2, 3]; +/// rsx! { +/// for number in numbers { +/// div { +/// "{number}" +/// } +/// } +/// }; +/// ``` +/// +/// ## Raw Expressions +/// +/// You can include raw expressions inside your markup inside curly braces. Your expression must implement the [`IntoDynNode`](https://docs.rs/dioxus-core/latest/dioxus_core/trait.IntoDynNode.html) trait: +/// +/// ```rust, no_run +/// # use dioxus::prelude::*; +/// let name = "World"; +/// rsx! { +/// div { +/// // Text can be converted into a dynamic node in rsx +/// {name} +/// } +/// // Iterators can also be converted into dynamic nodes +/// {(0..10).map(|n| n * n).map(|number| rsx! { div { "{number}" } })} +/// }; +/// ``` #[proc_macro] pub fn rsx(tokens: TokenStream) -> TokenStream { match syn::parse::(tokens) { @@ -40,8 +225,6 @@ pub fn rsx(tokens: TokenStream) -> TokenStream { } /// The rsx! macro makes it easy for developers to write jsx-style markup in their components. -/// -/// The render macro automatically renders rsx - making it unhygienic. #[deprecated(note = "Use `rsx!` instead.")] #[proc_macro] pub fn render(tokens: TokenStream) -> TokenStream { @@ -71,7 +254,8 @@ pub fn render(tokens: TokenStream) -> TokenStream { /// /// # Examples /// * Without props: -/// ```rust,ignore +/// ```rust, no_run +/// # use dioxus::prelude::*; /// #[component] /// fn GreetBob() -> Element { /// rsx! { "hello, bob" } @@ -79,7 +263,8 @@ pub fn render(tokens: TokenStream) -> TokenStream { /// ``` /// /// * With props: -/// ```rust,ignore +/// ```rust, no_run +/// # use dioxus::prelude::*; /// #[component] /// fn GreetBob(bob: String) -> Element { /// rsx! { "hello, {bob}" } @@ -101,21 +286,25 @@ pub fn component(_args: TokenStream, input: TokenStream) -> TokenStream { /// you would be repeating a lot of the usual Rust boilerplate. /// /// # Example -/// ```rust,ignore +/// ```rust,no_run +/// # use dioxus::prelude::*; /// #[inline_props] -/// fn app(bob: String) -> Element { -/// rsx! { "hello, {bob}") } +/// fn GreetBob(bob: String) -> Element { +/// rsx! { "hello, {bob}" } /// } +/// ``` /// -/// // is equivalent to +/// is equivalent to /// -/// #[derive(PartialEq, Props)] +/// ```rust,no_run +/// # use dioxus::prelude::*; +/// #[derive(PartialEq, Props, Clone)] /// struct AppProps { /// bob: String, /// } /// -/// fn app(props: AppProps) -> Element { -/// rsx! { "hello, {bob}") } +/// fn GreetBob(props: AppProps) -> Element { +/// rsx! { "hello, {props.bob}" } /// } /// ``` #[proc_macro_attribute] diff --git a/packages/core-macro/src/props/mod.rs b/packages/core-macro/src/props/mod.rs index 948bec5d38..504e036330 100644 --- a/packages/core-macro/src/props/mod.rs +++ b/packages/core-macro/src/props/mod.rs @@ -3,8 +3,8 @@ //! However, it has been adopted to fit the Dioxus Props builder pattern. //! //! For Dioxus, we make a few changes: -//! - [x] Automatically implement Into