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
358
359
360
361
#![deny(missing_docs)]
#![forbid(unsafe_code)]
//! # About Leptos
//!
//! Leptos is a full-stack framework for building web applications in Rust. You can use it to build
//! - single-page apps (SPAs) rendered entirely in the browser, using client-side routing and loading
//!   or mutating data via async requests to the server
//! - multi-page apps (MPAs) rendered on the server, managing navigation, data, and mutations via
//!   web-standard `<a>` and `<form>` tags
//! - progressively-enhanced single-page apps that are rendered on the server and then hydrated on the client,
//!   enhancing your `<a>` and `<form>` navigations and mutations seamlessly when WASM is available.
//!
//! And you can do all three of these **using the same Leptos code.**
//!
//! Take a look at the [Leptos Book](https://leptos-rs.github.io/leptos/) for a walkthrough of the framework.
//! Join us on our [Discord Channel](https://discord.gg/v38Eef6sWG) to see what the community is building.
//! Explore our [Examples](https://github.com/leptos-rs/leptos/tree/main/examples) to see Leptos in action.
//!
//! # Learning by Example
//!
//! If you want to see what Leptos is capable of, check out
//! the [examples](https://github.com/leptos-rs/leptos/tree/main/examples):
//! - [`counter`](https://github.com/leptos-rs/leptos/tree/main/examples/counter) is the classic
//!   counter example, showing the basics of client-side rendering and reactive DOM updates
//! - [`counter_without_macros`](https://github.com/leptos-rs/leptos/tree/main/examples/counter_without_macros)
//!   adapts the counter example to use the builder pattern for the UI and avoids other macros, instead showing
//!   the code that Leptos generates.
//! - [`counters`](https://github.com/leptos-rs/leptos/tree/main/examples/counters) introduces parent-child
//!   communication via contexts, and the `<For/>` component for efficient keyed list updates.
//! - [`error_boundary`](https://github.com/leptos-rs/leptos/tree/main/examples/error_boundary) shows how to use
//!   `Result` types to handle errors.
//! - [`parent_child`](https://github.com/leptos-rs/leptos/tree/main/examples/parent_child) shows four different
//!   ways a parent component can communicate with a child, including passing a closure, context, and more
//! - [`fetch`](https://github.com/leptos-rs/leptos/tree/main/examples/fetch) introduces
//!   [Resource]s, which allow you to integrate arbitrary `async` code like an
//!   HTTP request within your reactive code.
//! - [`router`](https://github.com/leptos-rs/leptos/tree/main/examples/router) shows how to use Leptos’s nested router
//!   to enable client-side navigation and route-specific, reactive data loading.
//! - [`slots`](https://github.com/leptos-rs/leptos/tree/main/examples/slots) shows how to use slots on components.
//! - [`spread`](https://github.com/leptos-rs/leptos/tree/main/examples/spread) shows how the spread syntax can be used to spread data and/or event handlers onto elements.
//! - [`counter_isomorphic`](https://github.com/leptos-rs/leptos/tree/main/examples/counter_isomorphic) shows
//!   different methods of interaction with a stateful server, including server functions, server actions, forms,
//!   and server-sent events (SSE).
//! - [`todomvc`](https://github.com/leptos-rs/leptos/tree/main/examples/todomvc) shows the basics of building an
//!   isomorphic web app. Both the server and the client import the same app code from the `todomvc` example.
//!   The server renders the app directly to an HTML string, and the client hydrates that HTML to make it interactive.
//!   You might also want to
//!   see how we use [`create_effect`] to [serialize JSON to `localStorage`](https://github.com/leptos-rs/leptos/blob/16f084a71268ac325fbc4a5e50c260df185eadb6/examples/todomvc/src/lib.rs#L164)
//!   and [reactively call DOM methods](https://github.com/leptos-rs/leptos/blob/6d7c36655c9e7dcc3a3ad33d2b846a3f00e4ae74/examples/todomvc/src/lib.rs#L291)
//!   on [references to elements](https://github.com/leptos-rs/leptos/blob/6d7c36655c9e7dcc3a3ad33d2b846a3f00e4ae74/examples/todomvc/src/lib.rs#L254).
//! - [`hackernews`](https://github.com/leptos-rs/leptos/tree/main/examples/hackernews)
//!   and [`hackernews_axum`](https://github.com/leptos-rs/leptos/tree/main/examples/hackernews_axum)
//!   integrate calls to a real external REST API, routing, server-side rendering and hydration to create
//!   a fully-functional application that works as intended even before WASM has loaded and begun to run.
//! - [`todo_app_sqlite`](https://github.com/leptos-rs/leptos/tree/main/examples/todo_app_sqlite) and
//!   [`todo_app_sqlite_axum`](https://github.com/leptos-rs/leptos/tree/main/examples/todo_app_sqlite_axum)
//!   show how to build a full-stack app using server functions and database connections.
//! - [`tailwind`](https://github.com/leptos-rs/leptos/tree/main/examples/tailwind_csr) shows how to integrate
//!   TailwindCSS with `trunk` for CSR.
//!
//! Details on how to run each example can be found in its README.
//!
//! # Quick Links
//!
//! Here are links to the most important sections of the docs:
//! - **Reactivity**: the [`leptos_reactive`] overview, and more details in
//!   - signals: [`create_signal`], [`ReadSignal`], and [`WriteSignal`] (and [`create_rw_signal`] and [`RwSignal`])
//!   - computations: [`create_memo`] and [`Memo`]
//!   - `async` interop: [`create_resource`] and [`Resource`] for loading data using `async` functions,
//!     and [`create_action`] and [`Action`] to mutate data or imperatively call `async` functions.
//!   - reactions: [`create_effect`]
//! - **Templating/Views**: the [`view`] macro
//! - **Routing**: the [`leptos_router`](https://docs.rs/leptos_router/latest/leptos_router/) crate
//! - **Server Functions**: the [`server`](crate::leptos_server) macro, [`create_action`], and [`create_server_action`]
//!
//! # Feature Flags
//! - `nightly`: On `nightly` Rust, enables the function-call syntax for signal getters and setters.
//! - `csr` Client-side rendering: Generate DOM nodes in the browser
//! - `ssr` Server-side rendering: Generate an HTML string (typically on the server)
//! - `hydrate` Hydration: use this to add interactivity to an SSRed Leptos app
//! - `serde` (*Default*) In SSR/hydrate mode, uses [`serde`](https://docs.rs/serde/latest/serde/) to serialize resources and send them
//!   from the server to the client.
//! - `serde-lite` In SSR/hydrate mode, uses [`serde-lite`](https://docs.rs/serde-lite/latest/serde_lite/) to serialize resources and send them
//!   from the server to the client.
//! - `rkyv` In SSR/hydrate mode, uses [`rkyv`](https://docs.rs/rkyv/latest/rkyv/) to serialize resources and send them
//!   from the server to the client.
//! - `miniserde` In SSR/hydrate mode, uses [`miniserde`](https://docs.rs/miniserde/latest/miniserde/) to serialize resources and send them
//!   from the server to the client.
//! - `tracing` Adds additional support for [`tracing`](https://docs.rs/tracing/latest/tracing/) to components.
//! - `default-tls` Use default native TLS support. (Only applies when using server functions with a non-WASM client like a desktop app.)
//! - `rustls` Use `rustls`. (Only applies when using server functions with a non-WASM client like a desktop app.)
//! - `template_macro` Enables the [`template!`](leptos_macro::template) macro, which offers faster DOM node creation for some use cases in `csr`.
//!
//! **Important Note:** You must enable one of `csr`, `hydrate`, or `ssr` to tell Leptos
//! which mode your app is operating in. You should only enable one of these per build target,
//! i.e., you should not have both `hydrate` and `ssr` enabled for your server binary, only `ssr`.
//!
//! # A Simple Counter
//!
//! ```rust
//! use leptos::*;
//!
//! #[component]
//! pub fn SimpleCounter( initial_value: i32) -> impl IntoView {
//!     // create a reactive signal with the initial value
//!     let (value, set_value) = create_signal( initial_value);
//!
//!     // create event handlers for our buttons
//!     // note that `value` and `set_value` are `Copy`, so it's super easy to move them into closures
//!     let clear = move |_| set_value.set(0);
//!     let decrement = move |_| set_value.update(|value| *value -= 1);
//!     let increment = move |_| set_value.update(|value| *value += 1);
//!
//!     view! {
//!
//!         <div>
//!             <button on:click=clear>"Clear"</button>
//!             <button on:click=decrement>"-1"</button>
//!             <span>"Value: " {move || value.get().to_string()} "!"</span>
//!             <button on:click=increment>"+1"</button>
//!         </div>
//!     }
//! }
//! ```
//!
//! Leptos is easy to use with [Trunk](https://trunkrs.dev/) (or with a simple wasm-bindgen setup):
//! ```
//! # use leptos::*;
//! # if false { // can't run in doctests
//!
//! #[component]
//! fn SimpleCounter(initial_value: i32) -> impl IntoView {
//!     todo!()
//! }
//!
//! pub fn main() {
//!     mount_to_body(|| view! { <SimpleCounter initial_value=3 /> })
//! }
//! # }
//! ```

mod additional_attributes;
pub use additional_attributes::*;
mod await_;
pub use await_::*;
pub use leptos_config::{self, get_configuration, LeptosOptions};
#[cfg(not(all(
    target_arch = "wasm32",
    any(feature = "csr", feature = "hydrate")
)))]
/// Utilities for server-side rendering HTML.
pub mod ssr {
    pub use leptos_dom::{ssr::*, ssr_in_order::*};
}
pub use leptos_dom::{
    self, create_node_ref, document, ev,
    helpers::{
        event_target, event_target_checked, event_target_value,
        request_animation_frame, request_animation_frame_with_handle,
        request_idle_callback, request_idle_callback_with_handle, set_interval,
        set_interval_with_handle, set_timeout, set_timeout_with_handle,
        window_event_listener, window_event_listener_untyped,
    },
    html,
    html::Binding,
    math, mount_to, mount_to_body, nonce, svg, window, Attribute, Class,
    CollectView, Errors, EventHandlerFn, Fragment, HtmlElement, IntoAttribute,
    IntoClass, IntoProperty, IntoStyle, IntoView, NodeRef, Property, View,
};
/// Utilities for simple isomorphic logging to the console or terminal.
pub mod logging {
    pub use leptos_dom::{debug_warn, error, log, warn};
}

/// Types to make it easier to handle errors in your application.
pub mod error {
    pub use server_fn::error::{Error, Result};
}
#[cfg(all(target_arch = "wasm32", feature = "template_macro"))]
pub use leptos_macro::template;
#[cfg(not(all(target_arch = "wasm32", feature = "template_macro")))]
pub use leptos_macro::view as template;
pub use leptos_macro::{component, island, slice, slot, view, Params};
cfg_if::cfg_if!(
    if #[cfg(feature="spin")] {
        pub use leptos_spin_macro::server;
    } else {
        pub use leptos_macro::server;
    }
);
pub use leptos_reactive::*;
pub use leptos_server::{
    self, create_action, create_multi_action, create_server_action,
    create_server_multi_action, Action, MultiAction, ServerFnError,
    ServerFnErrorErr,
};
pub use server_fn::{self, ServerFn as _};
mod error_boundary;
pub use error_boundary::*;
mod animated_show;
mod for_loop;
mod provider;
mod show;
pub use animated_show::*;
pub use for_loop::*;
pub use provider::*;
#[cfg(feature = "experimental-islands")]
pub use serde;
#[cfg(feature = "experimental-islands")]
pub use serde_json;
pub use show::*;
pub use suspense_component::*;
mod suspense_component;
mod transition;

#[cfg(any(debug_assertions, feature = "ssr"))]
#[doc(hidden)]
pub use tracing;
pub use transition::*;
#[doc(hidden)]
pub use typed_builder;
#[doc(hidden)]
pub use typed_builder::Optional;
#[doc(hidden)]
pub use typed_builder_macro;
#[doc(hidden)]
#[cfg(any(
    feature = "csr",
    feature = "hydrate",
    feature = "template_macro"
))]
pub use wasm_bindgen; // used in islands
#[doc(hidden)]
#[cfg(any(
    feature = "csr",
    feature = "hydrate",
    feature = "template_macro"
))]
pub use web_sys; // used in islands

mod children;
mod portal;
mod view_fn;
pub use children::*;
pub use portal::*;
pub use view_fn::*;

extern crate self as leptos;

/// A type for taking anything that implements [`IntoAttribute`].
///
/// ```rust
/// use leptos::*;
///
/// #[component]
/// pub fn MyHeading(
///     text: String,
///     #[prop(optional, into)] class: Option<AttributeValue>,
/// ) -> impl IntoView {
///     view! {
///       <h1 class=class>{text}</h1>
///     }
/// }
/// ```
pub type AttributeValue = Box<dyn IntoAttribute>;

#[doc(hidden)]
pub trait Component<P> {}

#[doc(hidden)]
pub trait Props {
    type Builder;
    fn builder() -> Self::Builder;
}

#[doc(hidden)]
pub trait DynAttrs {
    fn dyn_attrs(self, _args: Vec<(&'static str, Attribute)>) -> Self
    where
        Self: Sized,
    {
        self
    }
}

impl DynAttrs for () {}

#[doc(hidden)]
pub trait PropsOrNoPropsBuilder {
    type Builder;
    fn builder_or_not() -> Self::Builder;
}

#[doc(hidden)]
#[derive(Copy, Clone, Debug, Default)]
pub struct EmptyPropsBuilder {}

impl EmptyPropsBuilder {
    pub fn build(self) {}
}

impl<P: Props> PropsOrNoPropsBuilder for P {
    type Builder = <P as Props>::Builder;
    fn builder_or_not() -> Self::Builder {
        Self::builder()
    }
}

impl PropsOrNoPropsBuilder for EmptyPropsBuilder {
    type Builder = EmptyPropsBuilder;
    fn builder_or_not() -> Self::Builder {
        EmptyPropsBuilder {}
    }
}

impl<F, R> Component<EmptyPropsBuilder> for F where F: FnOnce() -> R {}

impl<P, F, R> Component<P> for F
where
    F: FnOnce(P) -> R,
    P: Props,
{
}

#[doc(hidden)]
pub fn component_props_builder<P: PropsOrNoPropsBuilder>(
    _f: &impl Component<P>,
) -> <P as PropsOrNoPropsBuilder>::Builder {
    <P as PropsOrNoPropsBuilder>::builder_or_not()
}

#[doc(hidden)]
pub fn component_view<P>(f: impl ComponentConstructor<P>, props: P) -> View {
    f.construct(props)
}

#[doc(hidden)]
pub trait ComponentConstructor<P> {
    fn construct(self, props: P) -> View;
}

impl<Func, V> ComponentConstructor<()> for Func
where
    Func: FnOnce() -> V,
    V: IntoView,
{
    fn construct(self, (): ()) -> View {
        (self)().into_view()
    }
}

impl<Func, V, P> ComponentConstructor<P> for Func
where
    Func: FnOnce(P) -> V,
    V: IntoView,
    P: PropsOrNoPropsBuilder,
{
    fn construct(self, props: P) -> View {
        (self)(props).into_view()
    }
}