leptos/
lib.rs

1#![deny(missing_docs)]
2
3//! # About Leptos
4//!
5//! Leptos is a full-stack framework for building web applications in Rust. You can use it to build
6//! - single-page apps (SPAs) rendered entirely in the browser, using client-side routing and loading
7//!   or mutating data via async requests to the server.
8//! - multi-page apps (MPAs) rendered on the server, managing navigation, data, and mutations via
9//!   web-standard `<a>` and `<form>` tags.
10//! - progressively-enhanced single-page apps that are rendered on the server and then hydrated on the client,
11//!   enhancing your `<a>` and `<form>` navigations and mutations seamlessly when WASM is available.
12//!
13//! And you can do all three of these **using the same Leptos code**.
14//!
15//! Take a look at the [Leptos Book](https://leptos-rs.github.io/leptos/) for a walkthrough of the framework.
16//! Join us on our [Discord Channel](https://discord.gg/v38Eef6sWG) to see what the community is building.
17//! Explore our [Examples](https://github.com/leptos-rs/leptos/tree/main/examples) to see Leptos in action.
18//!
19//! # Learning by Example
20//!
21//! If you want to see what Leptos is capable of, check out
22//! the [examples](https://github.com/leptos-rs/leptos/tree/main/examples):
23//!
24//! - **[`counter`]** is the classic counter example, showing the basics of client-side rendering and reactive DOM updates.
25//! - **[`counter_without_macros`]** adapts the counter example to use the builder pattern for the UI and avoids other macros,
26//!   instead showing the code that Leptos generates.
27//! - **[`counters`]** introduces parent-child communication via contexts, and the [`<For/>`](leptos::prelude::For) component
28//!   for efficient keyed list updates.
29//! - **[`error_boundary`]** shows how to use [`Result`] types to handle errors.
30//! - **[`parent_child`]** shows four different ways a parent component can communicate with a child, including passing a closure,
31//!   context, and more.
32//! - **[`fetch`]** introduces [`Resource`](leptos::prelude::Resource)s, which allow you to integrate arbitrary `async` code like an
33//!   HTTP request within your reactive code.
34//! - **[`router`]** shows how to use Leptos’s nested router to enable client-side navigation and route-specific, reactive data loading.
35//! - **[`slots`]** shows how to use slots on components.
36//! - **[`spread`]** shows how the spread syntax can be used to spread data and/or event handlers onto elements.
37//! - **[`counter_isomorphic`]** shows different methods of interaction with a stateful server, including server functions,
38//!   server actions, forms, and server-sent events (SSE).
39//! - **[`todomvc`]** shows the basics of building an isomorphic web app. Both the server and the client import the same app code.
40//!   The server renders the app directly to an HTML string, and the client hydrates that HTML to make it interactive.
41//!   You might also want to see how we use [`Effect::new`](leptos::prelude::Effect) to
42//!   [serialize JSON to `localStorage`](https://github.com/leptos-rs/leptos/blob/20af4928b2fffe017408d3f4e7330db22cf68277/examples/todomvc/src/lib.rs#L191-L209)
43//!   and [reactively call DOM methods](https://github.com/leptos-rs/leptos/blob/16f084a71268ac325fbc4a5e50c260df185eadb6/examples/todomvc/src/lib.rs#L292-L296)
44//!   on [references to elements](https://github.com/leptos-rs/leptos/blob/20af4928b2fffe017408d3f4e7330db22cf68277/examples/todomvc/src/lib.rs#L228).
45//! - **[`hackernews`]** and **[`hackernews_axum`]** integrate calls to a real external REST API, routing, server-side rendering and
46//!   hydration to create a fully-functional application that works as intended even before WASM has loaded and begun to run.
47//! - **[`todo_app_sqlite`]** and **[`todo_app_sqlite_axum`]** show how to build a full-stack app using server functions and
48//!   database connections.
49//! - **[`tailwind`]** shows how to integrate TailwindCSS with `trunk` for CSR.
50//!
51//! [`counter`]: https://github.com/leptos-rs/leptos/tree/main/examples/counter
52//! [`counter_without_macros`]: https://github.com/leptos-rs/leptos/tree/main/examples/counter_without_macros
53//! [`counters`]: https://github.com/leptos-rs/leptos/tree/main/examples/counters
54//! [`error_boundary`]: https://github.com/leptos-rs/leptos/tree/main/examples/error_boundary
55//! [`parent_child`]: https://github.com/leptos-rs/leptos/tree/main/examples/parent_child
56//! [`fetch`]: https://github.com/leptos-rs/leptos/tree/main/examples/fetch
57//! [`router`]: https://github.com/leptos-rs/leptos/tree/main/examples/router
58//! [`slots`]: https://github.com/leptos-rs/leptos/tree/main/examples/slots
59//! [`spread`]: https://github.com/leptos-rs/leptos/tree/main/examples/spread
60//! [`counter_isomorphic`]: https://github.com/leptos-rs/leptos/tree/main/examples/counter_isomorphic
61//! [`todomvc`]: https://github.com/leptos-rs/leptos/tree/main/examples/todomvc
62//! [`hackernews`]: https://github.com/leptos-rs/leptos/tree/main/examples/hackernews
63//! [`hackernews_axum`]: https://github.com/leptos-rs/leptos/tree/main/examples/hackernews_axum
64//! [`todo_app_sqlite`]: https://github.com/leptos-rs/leptos/tree/main/examples/todo_app_sqlite
65//! [`todo_app_sqlite_axum`]: https://github.com/leptos-rs/leptos/tree/main/examples/todo_app_sqlite_axum
66//! [`tailwind`]: https://github.com/leptos-rs/leptos/tree/main/examples/tailwind_csr
67//!
68//! Details on how to run each example can be found in its README.
69//!
70//! # Quick Links
71//!
72//! Here are links to the most important sections of the docs:
73//! - **Reactivity**: the [`reactive_graph`] overview, and more details in
74//!   + signals: [`signal`](leptos::prelude::signal), [`ReadSignal`](leptos::prelude::ReadSignal),
75//!     [`WriteSignal`](leptos::prelude::WriteSignal) and [`RwSignal`](leptos::prelude::RwSignal).
76//!   + computations: [`Memo`](leptos::prelude::Memo).
77//!   + `async` interop: [`Resource`](leptos::prelude::Resource) for loading data using `async` functions
78//!     and [`Action`](leptos::prelude::Action) to mutate data or imperatively call `async` functions.
79//!   + reactions: [`Effect`](leptos::prelude::Effect) and [`RenderEffect`](leptos::prelude::RenderEffect).
80//! - **Templating/Views**: the [`view`] macro and [`IntoView`] trait.
81//! - **Routing**: the [`leptos_router`](https://docs.rs/leptos_router/latest/leptos_router/) crate
82//! - **Server Functions**: the [`server`](macro@leptos::prelude::server) macro and [`ServerAction`](leptos::prelude::ServerAction).
83//!
84//! # Feature Flags
85//!
86//! - **`nightly`**: On `nightly` Rust, enables the function-call syntax for signal getters and setters.
87//!   Also enables some experimental optimizations that improve the handling of static strings and
88//!   the performance of the `template! {}` macro.
89//! - **`csr`** Client-side rendering: Generate DOM nodes in the browser.
90//! - **`ssr`** Server-side rendering: Generate an HTML string (typically on the server).
91//! - **`islands`** Activates “islands mode,” in which components are not made interactive on the
92//!   client unless they use the `#[island]` macro.
93//! - **`hydrate`** Hydration: use this to add interactivity to an SSRed Leptos app.
94//! - **`nonce`** Adds support for nonces to be added as part of a Content Security Policy.
95//! - **`rkyv`** In SSR/hydrate mode, enables using [`rkyv`](https://docs.rs/rkyv/latest/rkyv/) to serialize resources.
96//! - **`tracing`** Adds support for [`tracing`](https://docs.rs/tracing/latest/tracing/).
97//! - **`trace-component-props`** Adds `tracing` support for component props.
98//! - **`delegation`** Uses event delegation rather than the browser’s native event handling
99//!   system. (This improves the performance of creating large numbers of elements simultaneously,
100//!   in exchange for occasional edge cases in which events behave differently from native browser
101//!   events.)
102//! - **`rustls`** Use `rustls` for server functions.
103//!
104//! **Important Note:** You must enable one of `csr`, `hydrate`, or `ssr` to tell Leptos
105//! which mode your app is operating in. You should only enable one of these per build target,
106//! i.e., you should not have both `hydrate` and `ssr` enabled for your server binary, only `ssr`.
107//!
108//! # A Simple Counter
109//!
110//! ```rust
111//! use leptos::prelude::*;
112//!
113//! #[component]
114//! pub fn SimpleCounter(initial_value: i32) -> impl IntoView {
115//!     // create a reactive signal with the initial value
116//!     let (value, set_value) = signal(initial_value);
117//!
118//!     // create event handlers for our buttons
119//!     // note that `value` and `set_value` are `Copy`, so it's super easy to move them into closures
120//!     let clear = move |_| set_value.set(0);
121//!     let decrement = move |_| *set_value.write() -= 1;
122//!     let increment = move |_| *set_value.write() += 1;
123//!
124//!     view! {
125//!         <div>
126//!             <button on:click=clear>"Clear"</button>
127//!             <button on:click=decrement>"-1"</button>
128//!             <span>"Value: " {value} "!"</span>
129//!             <button on:click=increment>"+1"</button>
130//!         </div>
131//!     }
132//! }
133//! ```
134//!
135//! Leptos is easy to use with [Trunk](https://trunkrs.dev/) (or with a simple wasm-bindgen setup):
136//!
137//! ```rust
138//! use leptos::{mount::mount_to_body, prelude::*};
139//!
140//! #[component]
141//! fn SimpleCounter(initial_value: i32) -> impl IntoView {
142//!     // ...
143//!     # _ = initial_value;
144//! }
145//!
146//! pub fn main() {
147//! # if false { // can't run in doctest
148//!     mount_to_body(|| view! { <SimpleCounter initial_value=3 /> })
149//! # }
150//! }
151//! ```
152
153#![cfg_attr(all(feature = "nightly", rustc_nightly), feature(fn_traits))]
154#![cfg_attr(all(feature = "nightly", rustc_nightly), feature(unboxed_closures))]
155
156extern crate self as leptos;
157
158/// Exports all the core types of the library.
159pub mod prelude {
160    // Traits
161    // These should always be exported from the prelude
162    pub use reactive_graph::prelude::*;
163    pub use tachys::prelude::*;
164
165    // Structs
166    // In the future, maybe we should remove this blanket export
167    // However, it is definitely useful relative to looking up every struct etc.
168    mod export_types {
169        #[cfg(feature = "nonce")]
170        pub use crate::nonce::*;
171        pub use crate::{
172            callback::*, children::*, component::*, control_flow::*, error::*,
173            form::*, hydration::*, into_view::*, mount::*, suspense::*,
174            text_prop::*,
175        };
176        pub use leptos_config::*;
177        pub use leptos_dom::helpers::*;
178        pub use leptos_macro::*;
179        pub use leptos_server::*;
180        pub use oco_ref::*;
181        pub use reactive_graph::{
182            actions::*,
183            computed::*,
184            effect::*,
185            graph::untrack,
186            owner::*,
187            signal::*,
188            wrappers::{read::*, write::*},
189        };
190        pub use server_fn::{
191            self,
192            error::{FromServerFnError, ServerFnError, ServerFnErrorErr},
193        };
194        pub use tachys::{
195            reactive_graph::{bind::BindAttribute, node_ref::*, Suspend},
196            view::{fragment::Fragment, template::ViewTemplate},
197        };
198    }
199    pub use export_types::*;
200}
201
202/// Components used for working with HTML forms, like `<ActionForm>`.
203pub mod form;
204
205/// A standard way to wrap functions and closures to pass them to components.
206pub mod callback;
207
208/// Types that can be passed as the `children` prop of a component.
209pub mod children;
210
211/// Wrapper for intercepting component attributes.
212pub mod attribute_interceptor;
213
214#[doc(hidden)]
215/// Traits used to implement component constructors.
216pub mod component;
217mod error_boundary;
218
219/// Tools for handling errors.
220pub mod error {
221    pub use crate::error_boundary::*;
222    pub use throw_error::*;
223}
224
225/// Control-flow components like `<Show>`, `<For>`, and `<Await>`.
226pub mod control_flow {
227    pub use crate::{
228        animated_show::*, await_::*, for_loop::*, show::*, show_let::*,
229    };
230}
231mod animated_show;
232mod await_;
233mod for_loop;
234mod show;
235mod show_let;
236
237/// A component that allows rendering a component somewhere else.
238pub mod portal;
239
240/// Components to enable server-side rendering and client-side hydration.
241pub mod hydration;
242
243/// Utilities for exporting nonces to be used for a Content Security Policy.
244#[cfg(feature = "nonce")]
245pub mod nonce;
246
247/// Components to load asynchronous data.
248pub mod suspense {
249    pub use crate::{suspense_component::*, transition::*};
250}
251
252#[macro_use]
253mod suspense_component;
254
255/// Types for reactive string properties for components.
256pub mod text_prop;
257mod transition;
258pub use leptos_macro::*;
259#[doc(inline)]
260pub use server_fn;
261#[doc(hidden)]
262pub use typed_builder;
263#[doc(hidden)]
264pub use typed_builder_macro;
265mod into_view;
266pub use into_view::IntoView;
267#[doc(inline)]
268pub use leptos_dom;
269mod provider;
270#[doc(inline)]
271pub use tachys;
272/// Tools to mount an application to the DOM, or to hydrate it from server-rendered HTML.
273pub mod mount;
274#[doc(inline)]
275pub use leptos_config as config;
276#[doc(inline)]
277pub use oco_ref as oco;
278mod from_form_data;
279#[doc(inline)]
280pub use either_of as either;
281#[doc(inline)]
282pub use reactive_graph as reactive;
283
284/// Provide and access data along the reactive graph, sharing data without directly passing arguments.
285pub mod context {
286    pub use crate::provider::*;
287    pub use reactive_graph::owner::{provide_context, use_context};
288}
289
290#[doc(inline)]
291pub use leptos_server as server;
292/// HTML attribute types.
293#[doc(inline)]
294pub use tachys::html::attribute as attr;
295/// HTML element types.
296#[doc(inline)]
297pub use tachys::html::element as html;
298/// HTML event types.
299#[doc(no_inline)]
300pub use tachys::html::event as ev;
301/// MathML element types.
302#[doc(inline)]
303pub use tachys::mathml as math;
304/// SVG element types.
305#[doc(inline)]
306pub use tachys::svg;
307
308#[cfg(feature = "subsecond")]
309/// Utilities for using binary hot-patching with [`subsecond`].
310pub mod subsecond;
311
312/// Utilities for simple isomorphic logging to the console or terminal.
313pub mod logging {
314    pub use leptos_dom::{
315        debug_error, debug_log, debug_warn, error, log, warn,
316    };
317}
318
319/// Utilities for working with asynchronous tasks.
320pub mod task {
321    use any_spawner::Executor;
322    use reactive_graph::computed::ScopedFuture;
323    use std::future::Future;
324
325    /// Spawns a thread-safe [`Future`].
326    ///
327    /// This will be run with the current reactive owner and observer using a [`ScopedFuture`].
328    #[track_caller]
329    #[inline(always)]
330    pub fn spawn(fut: impl Future<Output = ()> + Send + 'static) {
331        let fut = ScopedFuture::new(fut);
332
333        #[cfg(not(target_family = "wasm"))]
334        Executor::spawn(fut);
335
336        #[cfg(target_family = "wasm")]
337        Executor::spawn_local(fut);
338    }
339
340    /// Spawns a [`Future`] that cannot be sent across threads.
341    #[track_caller]
342    #[inline(always)]
343    pub fn spawn_local(fut: impl Future<Output = ()> + 'static) {
344        Executor::spawn_local(fut)
345    }
346
347    /// Waits until the next "tick" of the current async executor.
348    pub async fn tick() {
349        Executor::tick().await
350    }
351
352    pub use reactive_graph::{
353        spawn_local_scoped, spawn_local_scoped_with_cancellation,
354    };
355}
356
357// these reexports are used in islands
358#[cfg(feature = "islands")]
359#[doc(hidden)]
360pub use serde;
361#[doc(hidden)]
362pub use serde_json;
363#[cfg(feature = "tracing")]
364#[doc(hidden)]
365pub use tracing;
366#[doc(hidden)]
367pub use wasm_bindgen;
368#[doc(hidden)]
369pub use wasm_split_helpers as wasm_split;
370#[doc(hidden)]
371pub use web_sys;
372
373#[doc(hidden)]
374pub mod __reexports {
375    pub use send_wrapper;
376    pub use wasm_bindgen_futures;
377}
378
379#[doc(hidden)]
380#[derive(Clone, Debug, Default)]
381pub struct PrefetchLazyFn(
382    pub  reactive_graph::owner::ArcStoredValue<
383        std::collections::HashSet<&'static str>,
384    >,
385);
386
387#[doc(hidden)]
388pub fn prefetch_lazy_fn_on_server(id: &'static str) {
389    use crate::context::use_context;
390    use reactive_graph::traits::WriteValue;
391
392    if let Some(prefetches) = use_context::<PrefetchLazyFn>() {
393        prefetches.0.write_value().insert(id);
394    }
395}
396
397#[doc(hidden)]
398#[derive(Clone, Debug, Default)]
399pub struct WasmSplitManifest(
400    pub  reactive_graph::owner::ArcStoredValue<(
401        String,                                         // the pkg root
402        std::collections::HashMap<String, Vec<String>>, // preloads
403        String, // the name of the __wasm_split.js file
404    )>,
405);