1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
//! <div align="center">
//!   <h1>🌗🚀 Dioxus</h1>
//!   <p>
//!     <strong>A concurrent, functional, virtual DOM for Rust</strong>
//!   </p>
//! </div>
//!
//! # Resources
//!
//! This overview is provides a brief introduction to Dioxus. For a more in-depth guide, make sure to check out:
//! - [Getting Started](https://dioxuslabs.com/getting-started)
//! - [Book](https://dioxuslabs.com/book)
//! - [Reference](https://dioxuslabs.com/reference)
//! - [Community Examples](https://github.com/DioxusLabs/community-examples)
//!
//! # 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 competitve 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 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);
//! }
//!
//! fn app(cx: Scope) -> Element {
//!     cx.render(rsx!("hello world!"))
//! }
//! ```
//!
//! ## Elements & your first component
//!
//! To assemble UI trees with Diouxs, 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 then 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
//! fn example(cx: Scope) -> Element {
//!
//!     // both of these are equivalent
//!     cx.render(rsx!("hello world"))
//!
//!     rsx!(cx, "hello world!")
//! }
//! ```
//!
//! Putting everything together, we can write a simple component that a list of
//! elements:
//!
//! ```rust, ignore
//! fn app(cx: Scope) -> Element {
//!     let name = "dave";
//!     cx.render(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
//! fn App(cx: Scope) -> Element {
//!     cx.render(rsx!(
//!         Header {
//!             title: "My App",
//!             color: "red",
//!         }
//!     ))
//! }
//! ```
//!
//! Our `Header` component takes in a `title` and a `color` property, which we
//! delcare 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,
//! }
//!
//! fn Header(cx: Scope<HeaderProps>) -> Element {
//!     cx.render(rsx!(
//!         div {
//!             background_color: "{cx.props.color}"
//!             h1 { "{cx.props.title}" }
//!         }
//!     ))
//! }
//! ```
//!
//! Components may use the `inline_props` macro to completely inline the props
//! definition into the function arguments.
//!
//! ```rust, ignore
//! #[inline_props]
//! fn Header(cx: Scope, title: String, color: String) -> Element {
//!     cx.render(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,
//! }
//!
//! fn Header<'a>(cx: Scope<'a, HeaderProps<'a>>) -> Element {
//!     cx.render(rsx!(
//!         div {
//!             background_color: "{cx.props.color}"
//!             h1 { "{cx.props.title}" }
//!         }
//!     ))
//! }
//! ```
//!
//! Components that beging with an uppercase letter may be called through
//! traditional 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" )
//! )
//! ```
//!
//! ## Hooks
//!
//! While components are reusable forms of UI elements, hooks are reusable forms
//! of logic. Hooks provide us a way of retrieving state from `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 state and modify it from within listeners.
//!
//! ```rust, ignore
//! fn app(cx: Scope) -> Element {
//!     let name = use_state(&cx, || "world");
//!
//!     rsx!(cx, "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 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 composition of other hooks:
//!
//! ```rust, ignore
//! fn use_username(cx: &ScopeState, id: Uuid) -> bool {
//!     let users = use_context::<Users>(cx);
//!     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(cx: &ScopeState) -> &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);
//! }
//!
//! fn App(cx: Scope) -> Element {
//!     let mut count = use_state(&cx, || 0);
//!
//!     cx.render(rsx!(
//!         div { "Count: {count}" }
//!         button { onclick: move |_| count += 1, "Increment" }
//!         button { onclick: move |_| 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 in state management
//! - Sycamore: supports function components, web, ssr, but closer to SolidJS than React
//! - MoonZoom/Seed: opionated in the Elm model (message, update) - no hooks
//!
//! We've put a lot of work into making Dioxus ergonomic and *familiar*.
//! Our target audience is TypeSrcipt developers looking to switch to Rust for the web - so we need to be comparabale to React.

pub use dioxus_core as core;

#[cfg(feature = "hooks")]
pub use dioxus_hooks as hooks;

#[cfg(feature = "router")]
pub use dioxus_router as router;

#[cfg(feature = "ssr")]
pub use dioxus_ssr as ssr;

#[cfg(feature = "web")]
pub use dioxus_web as web;

#[cfg(feature = "desktop")]
pub use dioxus_desktop as desktop;

// #[cfg(feature = "mobile")]
// pub use dioxus_mobile as mobile;

pub mod events {
    #[cfg(feature = "html")]
    pub use dioxus_html::{on::*, KeyCode};
}

pub mod prelude {
    pub use dioxus_core::prelude::*;
    pub use dioxus_core_macro::{format_args_f, inline_props, rsx, Props, Routable};
    pub use dioxus_elements::{GlobalAttributes, SvgAttributes};
    pub use dioxus_hooks::*;
    pub use dioxus_html as dioxus_elements;
}