diff --git a/crates/components/src/tabs.rs b/crates/components/src/tabs.rs index b056dcd62..c961a4918 100644 --- a/crates/components/src/tabs.rs +++ b/crates/components/src/tabs.rs @@ -34,7 +34,7 @@ pub enum TabStatus { Hovering, } -/// Clickable Tab. Usually used in combination with [`Tabsbar`], [`Link`] and [`ActivableRoute`]. +/// Clickable Tab. Usually used in combination with [`Tabsbar`], [`crate::Link`] and [`crate::ActivableRoute`]. /// /// # Styling /// Inherits the [`TabTheme`](freya_hooks::TabTheme) theme. @@ -164,7 +164,7 @@ pub fn Tab( } /// Clickable BottomTab. Same thing as Tab but designed to be placed in the bottom of your app, -/// usually used in combination with [`Tabsbar`], [`Link`] and [`ActivableRoute`]. +/// usually used in combination with [`Tabsbar`], [`crate::Link`] and [`crate::ActivableRoute`]. /// /// # Styling /// Inherits the [`BottomTabTheme`](freya_hooks::BottomTabTheme) theme. diff --git a/crates/core/src/elements/utils.rs b/crates/core/src/elements/utils.rs index 9d3d8e446..f14565c76 100644 --- a/crates/core/src/elements/utils.rs +++ b/crates/core/src/elements/utils.rs @@ -109,7 +109,7 @@ pub trait ElementUtils { /// Check if this element requires any kind of special caching. /// Mainly used for text-like elements with shadows. - /// See [crate::compositor::CompositorCache]. + /// See [crate::render::CompositorCache]. /// Default to `false`. #[inline] fn element_needs_cached_area(&self, _node_ref: &DioxusNode) -> bool { diff --git a/crates/freya/Cargo.toml b/crates/freya/Cargo.toml index 8797c7eda..4b6d19bb2 100644 --- a/crates/freya/Cargo.toml +++ b/crates/freya/Cargo.toml @@ -12,7 +12,7 @@ keywords = ["gui", "ui", "desktop", "skia", "dioxus"] categories = ["gui", "asynchronous"] [package.metadata.docs.rs] -features = ["freya-engine/mocked-engine"] +features = ["freya-engine/mocked-engine", "docs"] no-default-features = true [features] @@ -27,6 +27,7 @@ default = ["skia"] performance-overlay = [] fade-cached-incremental-areas = ["freya-core/fade-cached-incremental-areas"] disable-zoom-shortcuts = ["freya-renderer/disable-zoom-shortcuts"] +docs = ["dep:freya-testing"] [dependencies] freya-devtools = { workspace = true, optional = true } @@ -39,6 +40,7 @@ freya-core = { workspace = true } freya-components = { workspace = true } freya-engine = { workspace = true } torin = { workspace = true } +freya-testing = { workspace = true, optional = true } dioxus = { workspace = true } dioxus-core-macro = { workspace = true } diff --git a/crates/freya/src/_docs/accessibility.rs b/crates/freya/src/_docs/accessibility.rs index b0402d015..92f490831 100644 --- a/crates/freya/src/_docs/accessibility.rs +++ b/crates/freya/src/_docs/accessibility.rs @@ -1,13 +1,13 @@ //! # Accessibility -//! +//! //! TODO -//! +//! //! ### `use_focus` hook -//! -//! ```rs +//! +//! ```rust //! fn app() -> Element { //! let mut my_focus = use_focus(); -//! +//! //! rsx!( //! rect { //! width: "100%", @@ -20,4 +20,4 @@ //! } //! ) //! } -//! ``` \ No newline at end of file +//! ``` diff --git a/crates/freya/src/_docs/dioxus_fundamentals.rs b/crates/freya/src/_docs/dioxus_fundamentals.rs index ac6768ae3..8ea9fa943 100644 --- a/crates/freya/src/_docs/dioxus_fundamentals.rs +++ b/crates/freya/src/_docs/dioxus_fundamentals.rs @@ -1,15 +1,15 @@ -//! -//! # Dioxus Fundamentals -//! -//! As you should know by now, Freya runs on 🧬 [Dioxus](https://dioxuslabs.com), a renderer-agnostic UI library for Rust. -//! -//! - [UI](self::_docs::ui) -//! - [Components](self::_docs::components_and_props) -//! - [Hooks](self::_docs::hooks) -//! - [State Management](self::_docs::state_management) -//! - [Signals](self::_docs::state_management::signals) -//! - [Global Signals](self::_docs::state_management::global_signals) -//! - [Lifecycle](self::_docs::state_management::lifecycle) -//! - [Context](self::_docs::state_management::context) -//! - [Memoization](self::_docs::state_management::memoization) -//! +//! +//! # Dioxus Fundamentals +//! +//! As you should know by now, Freya runs on 🧬 [Dioxus](https://dioxuslabs.com), a renderer-agnostic UI library for Rust. +//! +//! - [UI](crate::_docs::ui) +//! - [Components](crate::_docs::components_and_props) +//! - [Hooks](crate::_docs::hooks) +//! - [State Management](crate::_docs::state_management) +//! - [Signals](crate::_docs::state_management::signals) +//! - [Global Signals](crate::_docs::state_management::global_signals) +//! - [Lifecycle](crate::_docs::state_management::lifecycle) +//! - [Context](crate::_docs::state_management::context) +//! - [Memoization](crate::_docs::state_management::memoization) +//! - [Async Tasks](crate::_docs::async_tasks) diff --git a/crates/freya/src/_docs/elements.rs b/crates/freya/src/_docs/elements.rs index cea40a461..59e98228e 100644 --- a/crates/freya/src/_docs/elements.rs +++ b/crates/freya/src/_docs/elements.rs @@ -1,17 +1,17 @@ //! # Elements -//! -//! This is an overview of the elements supported in Freya. -//! -//! > For more info check the [API Reference](https://docs.rs/freya/latest/freya/elements/index.html#structs). -//! +//! +//! This is an overview of the elements supported in Freya. +//! +//! > For more info check the [API Reference](freya_elements::elements#structs). +//! //! ### `rect` -//! -//! [`rect`](https://docs.rs/freya/latest/freya/elements/struct.rect.html) is a generic element that acts as a container for other elements. -//! +//! +//! [`rect`](freya_elements::elements::rect) is a generic element that acts as a container for other elements. +//! //! You can specify things like **width**, **padding** or even in what **direction** the inner elements are stacked. -//! +//! //! Example: -//! +//! //! ```rust //! fn app() -> Element { //! rsx!( @@ -22,13 +22,13 @@ //! ) //! } //! ``` -//! +//! //! ### `label` -//! -//! [`label`](https://docs.rs/freya/latest/freya/elements/struct.label.html) simply let's you display some text. -//! +//! +//! [`label`](freya_elements::elements::label) simply let's you display some text. +//! //! Example: -//! +//! //! ```rust //! fn app() -> Element { //! rsx!( @@ -38,15 +38,15 @@ //! ) //! } //! ``` -//! +//! //! ### `paragraph` -//! -//! [`paragraph`](https://docs.rs/freya/latest/freya/elements/struct.paragraph.html) element let's you build texts with different styles. -//! +//! +//! [`paragraph`](freya_elements::elements::paragraph) element let's you build texts with different styles. +//! //! This used used with the `text` element. -//! +//! //! Example: -//! +//! //! ```rust //! fn app() -> Element { //! rsx!( @@ -63,45 +63,41 @@ //! ) //! } //! ``` -//! +//! //! ### `image` -//! -//! [`image`](https://docs.rs/freya/latest/freya/elements/struct.image.html) element let's you show an image. -//! +//! +//! [`image`](freya_elements::elements::image) element let's you show an image. +//! //! Example: -//! +//! //! ```rust //! static RUST_LOGO: &[u8] = include_bytes!("./rust_logo.png"); -//! +//! //! fn app() -> Element { //! let image_data = static_bytes(RUST_LOGO); -//! rsx!( -//! image { -//! image_data: image_data, -//! width: "100%", -//! height: "100%", -//! } -//! ) +//! rsx!(image { +//! image_data: image_data, +//! width: "100%", +//! height: "100%", +//! }) //! } //! ``` -//! +//! //! ### `svg` -//! -//! [`svg`](https://docs.rs/freya/latest/freya/elements/struct.svg.html) element let's you display an SVG. -//! +//! +//! [`svg`](freya_elements::elements::svg) element let's you display an SVG. +//! //! Example: -//! +//! //! ```rust //! static FERRIS: &[u8] = static_bytes!("./ferris.svg"); -//! +//! //! fn app() -> Element { //! let ferris = static_bytes(FERRIS); -//! rsx!( -//! svg { -//! svg_data: ferris, -//! width: "100%", -//! height: "100%", -//! } -//! ) +//! rsx!(svg { +//! svg_data: ferris, +//! width: "100%", +//! height: "100%", +//! }) //! } -//! ``` \ No newline at end of file +//! ``` diff --git a/crates/freya/src/_docs/hooks.rs b/crates/freya/src/_docs/hooks.rs index 82131c3a5..17e7cd75a 100644 --- a/crates/freya/src/_docs/hooks.rs +++ b/crates/freya/src/_docs/hooks.rs @@ -1,102 +1,102 @@ -//! # Hooks -//! -//! Hooks are special functions to be used inside of Components that lets you handle different things like the state or lifecycle of your component. They are usually prefixed with `use`, e.g `use_signal`, `use_effect`, `use_memo`, etc. -//! -//! # Rules of Hooks -//! -//! Even though hooks appear to be normal functions they are in fact special so you cannot just call them however you want. -//! -//! ## 1. They cannot be called conditionally -//! -//! You cannot do the following because hooks need to maintain their order. So, if one component is calling 3 different hooks in one render, and then in another render if just calls 2, it would be breaking this rule. -//! -//! ❌: -//! ```rust -//! #[component] -//! fn MyComponent(value: bool) -> Element { -//! let is_enabled = if value { -//! // This should be moved out of the conditional -//! use_signal(|| value) -//! } else { -//! true -//! }; -//! -//! rsx!(...) -//! } -//! ``` -//! -//! ✅: -//! ```rust -//! #[component] -//! fn MyComponent(initial_value: bool) -> Element { -//! let is_enabled = use_signal(|| initial_value) -//! -//! rsx!(...) -//! } -//! ``` -//! -//! ## 2. They can only be called inside of Component functions -//! -//! You cannot call them inside of event handlers, futures, etc. -//! -//! ❌: -//! ```rust -//! #[component] -//! fn MyComponent() -> Element { -//! let onclick = |_| { -//! let state = use_signal(|| false); -//! }; -//! -//! rsx!( -//! label { -//! onclick, -//! "Hello, World!" -//! } -//! ) -//! } -//! ``` -//! -//! ✅: -//! ```rust -//! #[component] -//! fn MyComponent() -> Element { -//! let mut state = use_signal(|| false); -//! -//! let onclick = move |_| { -//! state.set(true); -//! }; -//! -//! rsx!( -//! label { -//! onclick, -//! "Hello, World!" -//! } -//! ) -//! } -//! ``` -//! -//! ## 3. They cannot be called in loops -//! -//! Hooks cannot be called in loops as the numbers of iterations might change between renders. -//! -//! ❌: -//! ```rust -//! #[component] -//! fn MyComponent() -> Element { -//! for i in 0..5 { -//! let state = use_signal(|| i); -//! } -//! -//! rsx!(...) -//! } -//! ``` -//! -//! ✅: -//! ```rust -//! #[component] -//! fn MyComponent() -> Element { -//! let state = use_signal(|| (0..5).iter().collect::>()); -//! -//! rsx!(...) -//! } -//! ``` \ No newline at end of file +//! # Hooks +//! +//! Hooks are special functions to be used inside of Components that lets you handle different things like the state or lifecycle of your component. They are usually prefixed with `use`, e.g `use_signal`, `use_effect`, `use_memo`, etc. +//! +//! # Rules of Hooks +//! +//! Even though hooks appear to be normal functions they are in fact special so you cannot just call them however you want. +//! +//! ## 1. They cannot be called conditionally +//! +//! You cannot do the following because hooks need to maintain their order. So, if one component is calling 3 different hooks in one render, and then in another render if just calls 2, it would be breaking this rule. +//! +//! ❌: +//! ```rust +//! #[component] +//! fn MyComponent(value: bool) -> Element { +//! let is_enabled = if value { +//! // This should be moved out of the conditional +//! use_signal(|| value) +//! } else { +//! true +//! }; +//! +//! rsx!(...) +//! } +//! ``` +//! +//! ✅: +//! ```rust +//! #[component] +//! fn MyComponent(initial_value: bool) -> Element { +//! let is_enabled = use_signal(|| initial_value) +//! +//! rsx!(...) +//! } +//! ``` +//! +//! ## 2. They can only be called inside of Component functions +//! +//! You cannot call them inside of event handlers, futures, etc. +//! +//! ❌: +//! ```rust +//! #[component] +//! fn MyComponent() -> Element { +//! let onclick = |_| { +//! let state = use_signal(|| false); +//! }; +//! +//! rsx!( +//! label { +//! onclick, +//! "Hello, World!" +//! } +//! ) +//! } +//! ``` +//! +//! ✅: +//! ```rust +//! #[component] +//! fn MyComponent() -> Element { +//! let mut state = use_signal(|| false); +//! +//! let onclick = move |_| { +//! state.set(true); +//! }; +//! +//! rsx!( +//! label { +//! onclick, +//! "Hello, World!" +//! } +//! ) +//! } +//! ``` +//! +//! ## 3. They cannot be called in loops +//! +//! Hooks cannot be called in loops as the numbers of iterations might change between renders. +//! +//! ❌: +//! ```rust +//! #[component] +//! fn MyComponent() -> Element { +//! for i in 0..5 { +//! let state = use_signal(|| i); +//! } +//! +//! rsx!(...) +//! } +//! ``` +//! +//! ✅: +//! ```rust +//! #[component] +//! fn MyComponent() -> Element { +//! let state = use_signal(|| (0..5).iter().collect::>()); +//! +//! rsx!(...) +//! } +//! ``` diff --git a/crates/freya/src/_docs/introduction.rs b/crates/freya/src/_docs/introduction.rs index bda11152d..516dcb71d 100644 --- a/crates/freya/src/_docs/introduction.rs +++ b/crates/freya/src/_docs/introduction.rs @@ -1,39 +1,39 @@ -//! # Introduction -//! -//! **Freya** is a Rust 🦀 library to make GUI applications that are **cross-platform**, which means they will run the same way in Windows, macOS and Linux. -//! -//! It uses a model where you compose the app by splitting the UI in different components that return pieces of UI or call other components, this is because -//! Freya runs on 🧬 [Dioxus](https://dioxuslabs.com), a renderer-agnostic UI library inspired by ReactJS. -//! -//! Even though you might have seen that Dioxus renders to HTML, that it uses WASM, or that it uses CSS. this does not apply to Freya. In fact, Freya only uses some of the core -//! crates of Dioxus, which means that you will be writing Dioxus components and using some of its APIs but, the elements, attributes, styling, layout, events, and more things -//! will be provided by Freya. -//! -//! Freya uses 🎨 [Skia](https://skia.org/) as rendering engine because its a very battle tested library and has great support for a lot of features. -//! -//! #### Example -//! -//! ```rust -//! fn main() { -//! // **Start** your app by specifying the root component and some config parameters -//! launch_with_props(app, "Counter", (400.0, 350.0)); -//! } -//! -//! fn app() -> Element { -//! // Define a **state** -//! let mut count = use_signal(|| 0); -//! -//! // Declare the **UI** -//! rsx!( -//! rect { -//! height: "100%", -//! width: "100%", -//! background: "rgb(35, 35, 35)", -//! color: "white", -//! padding: "12", -//! onclick: move |_| count += 1, // **Update** the state -//! label { "Click to increase -> {count}" } // Display the **state** -//! } -//! ) -//! } -//! ``` \ No newline at end of file +//! # Introduction +//! +//! **Freya** is a Rust 🦀 library to make GUI applications that are **cross-platform**, which means they will run the same way in Windows, macOS and Linux. +//! +//! It uses a model where you compose the app by splitting the UI in different components that return pieces of UI or call other components, this is because +//! Freya runs on 🧬 [Dioxus](https://dioxuslabs.com), a renderer-agnostic UI library inspired by ReactJS. +//! +//! Even though you might have seen that Dioxus renders to HTML, that it uses WASM, or that it uses CSS. this does not apply to Freya. In fact, Freya only uses some of the core +//! crates of Dioxus, which means that you will be writing Dioxus components and using some of its APIs but, the elements, attributes, styling, layout, events, and more things +//! will be provided by Freya. +//! +//! Freya uses 🎨 [Skia](https://skia.org/) as rendering engine because its a very battle tested library and has great support for a lot of features. +//! +//! #### Example +//! +//! ```rust +//! fn main() { +//! // **Start** your app by specifying the root component and some config parameters +//! launch_with_props(app, "Counter", (400.0, 350.0)); +//! } +//! +//! fn app() -> Element { +//! // Define a **state** +//! let mut count = use_signal(|| 0); +//! +//! // Declare the **UI** +//! rsx!( +//! rect { +//! height: "100%", +//! width: "100%", +//! background: "rgb(35, 35, 35)", +//! color: "white", +//! padding: "12", +//! onclick: move |_| count += 1, // **Update** the state +//! label { "Click to increase -> {count}" } // Display the **state** +//! } +//! ) +//! } +//! ``` diff --git a/crates/freya/src/_docs/mod.rs b/crates/freya/src/_docs/mod.rs index 7b39f5cd1..4a0da78e8 100644 --- a/crates/freya/src/_docs/mod.rs +++ b/crates/freya/src/_docs/mod.rs @@ -1,16 +1,16 @@ +pub mod accessibility; pub mod async_tasks; pub mod components_and_props; -pub mod hooks; +pub mod development_setup; pub mod devtools; +pub mod dioxus_fundamentals; +pub mod elements; +pub mod hooks; pub mod i18n; +pub mod introduction; pub mod performance; pub mod router; -pub mod development_setup; pub mod state_management; pub mod theming; -pub mod ui; -pub mod introduction; -pub mod dioxus_fundamentals; pub mod third_party_state; -pub mod elements; -pub mod accessibility; \ No newline at end of file +pub mod ui; diff --git a/crates/freya/src/_docs/state_management.rs b/crates/freya/src/_docs/state_management.rs index 4af18c6dc..136422a86 100644 --- a/crates/freya/src/_docs/state_management.rs +++ b/crates/freya/src/_docs/state_management.rs @@ -4,13 +4,14 @@ //! //! See the different features: //! -//! - [Signals](self::signals) -//! - [Global Signals](self:::global_signals) -//! - [Lifecycle](self:::lifecycle) -//! - [Context](self:::context) -//! - [Memoization](self:::memoization) +//! - [Signals](crate::_docs::state_management::signals) +//! - [Global Signals](crate::_docs::state_management::global_signals) +//! - [Lifecycle](crate::_docs::state_management::lifecycle) +//! - [Context](crate::_docs::state_management::context) +//! - [Memoization](crate::_docs::state_management::memoization) pub mod context; pub mod global_signals; +pub mod lifecycle; pub mod memoization; pub mod signals; diff --git a/crates/freya/src/_docs/lifecycle.rs b/crates/freya/src/_docs/state_management/lifecycle.rs similarity index 87% rename from crates/freya/src/_docs/lifecycle.rs rename to crates/freya/src/_docs/state_management/lifecycle.rs index 732bce955..fb708e0c5 100644 --- a/crates/freya/src/_docs/lifecycle.rs +++ b/crates/freya/src/_docs/state_management/lifecycle.rs @@ -1,74 +1,74 @@ -//! # Lifecycle -//! -//! Dioxus components can use hooks to manage certain lifecycle situations. -//! -//! ## Component creation -//! You can run certain logic when the component is created for the first time by using the `use_hook` hook. -//! -//! ```rust -//! fn app() -> Element { -//! -//! use_hook(|| { -//! println!("Component running for the first time!"); -//! }); -//! -//! rsx!(...) -//! } -//! ``` -//! -//! ## Component destroyment -//! -//! Run some logic when the component is being destroyed. -//! -//! ```rust -//! fn app() -> Element { -//! -//! use_drop(|| { -//! println!("Component is being dropped."); -//! }); -//! -//! rsx!(...) -//! } -//! ``` -//! -//! ## Side effects -//! -//! Run some logic when a signal is changed. -//! -//! ```rust -//! fn app() -> Element { -//! let mut signal = use_signal(|| 1); -//! -//! use_effect(move || { -//! // Because we are reading this signal -//! // now the effect is subscribed to any change -//! let value = signal(); -//! println!("Value of signal is {value}"); -//! }); -//! -//! rsx!(...) -//! } -//! ``` -//! -//! ## Side effects with dependencies -//! -//! Run some logic when a signal is changed. -//! -//! ```rust -//! fn app() -> Element { -//! let mut signal = use_signal(|| 1); -//! let mut other_signal = use_signal(|| 1); -//! -//! // Manually specify non-signal values that we might want to react to -//! use_effect(use_reactive(&signal, |value| { -//! println!("Value of signal is {value}"); -//! })); -//! -//! // When you need multiple values you can pass a tuple -//! use_effect(use_reactive(&(signal, other_signal), |(value, other_signal)| { -//! println!("Value of signals are {value} and {other_signal}"); -//! })); -//! -//! rsx!(...) -//! } -//! ``` \ No newline at end of file +//! # Lifecycle +//! +//! Dioxus components can use hooks to manage certain lifecycle situations. +//! +//! ## Component creation +//! You can run certain logic when the component is created for the first time by using the `use_hook` hook. +//! +//! ```rust +//! fn app() -> Element { +//! +//! use_hook(|| { +//! println!("Component running for the first time!"); +//! }); +//! +//! rsx!(...) +//! } +//! ``` +//! +//! ## Component destroyment +//! +//! Run some logic when the component is being destroyed. +//! +//! ```rust +//! fn app() -> Element { +//! +//! use_drop(|| { +//! println!("Component is being dropped."); +//! }); +//! +//! rsx!(...) +//! } +//! ``` +//! +//! ## Side effects +//! +//! Run some logic when a signal is changed. +//! +//! ```rust +//! fn app() -> Element { +//! let mut signal = use_signal(|| 1); +//! +//! use_effect(move || { +//! // Because we are reading this signal +//! // now the effect is subscribed to any change +//! let value = signal(); +//! println!("Value of signal is {value}"); +//! }); +//! +//! rsx!(...) +//! } +//! ``` +//! +//! ## Side effects with dependencies +//! +//! Run some logic when a signal is changed. +//! +//! ```rust +//! fn app() -> Element { +//! let mut signal = use_signal(|| 1); +//! let mut other_signal = use_signal(|| 1); +//! +//! // Manually specify non-signal values that we might want to react to +//! use_effect(use_reactive(&signal, |value| { +//! println!("Value of signal is {value}"); +//! })); +//! +//! // When you need multiple values you can pass a tuple +//! use_effect(use_reactive(&(signal, other_signal), |(value, other_signal)| { +//! println!("Value of signals are {value} and {other_signal}"); +//! })); +//! +//! rsx!(...) +//! } +//! ``` diff --git a/crates/freya/src/lib.rs b/crates/freya/src/lib.rs index dc118f6d7..121d794b1 100644 --- a/crates/freya/src/lib.rs +++ b/crates/freya/src/lib.rs @@ -4,9 +4,9 @@ )] //! # Freya //! -//! **Freya** is a declarative, cross-platform GUI Rust library, powered by 🧬 [Dioxus](https://dioxuslabs.com) and 🎨 [Skia](https://skia.org/). -//! -//! **It does not use any web tech**, check the [Differences with Dioxus](https://book.freyaui.dev/differences_with_dioxus.html). +//! **Freya** is a declarative, cross-platform GUI Rust library, powered by 🧬 [Dioxus](https://dioxuslabs.com) and 🎨 [Skia](https://skia.org/). +//! +//! **It does not use any web tech**, check the [Differences with Dioxus](https://book.freyaui.dev/differences_with_dioxus.html). //! //! ### Basics //! - [Introduction](self::_docs::introduction) @@ -21,7 +21,7 @@ //! - [Context](self::_docs::state_management::context) //! - [Memoization](self::_docs::state_management::memoization) //! - [Async Tasks](self::_docs::async_tasks) -//! +//! //! ### Learn //! - [Development Setup](self::_docs::development_setup) //! - [Elements Overview](self::_docs::elements) @@ -43,7 +43,7 @@ //! - [Elements and attributes](freya_elements::elements#structs) //! - [Events](freya_elements::elements#functions) //! - [Built-in Components](freya_components) -//! - [Built-in Hooks](freya_hoo +//! - [Built-in Hooks](freya_hooks) //! //! ## Features flags //!