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
#![deny(missing_docs)]
#![cfg_attr(not(feature = "stable"), feature(fn_traits))]
#![cfg_attr(not(feature = "stable"), feature(unboxed_closures))]
#![cfg_attr(not(feature = "stable"), feature(type_name_of_val))]

//! The reactive system for the [Leptos](https://docs.rs/leptos/latest/leptos/) Web framework.
//!
//! ## Fine-Grained Reactivity
//!
//! Leptos is built on a fine-grained reactive system, which means that individual reactive values
//! (“signals,” sometimes known as observables) trigger the code that reacts to them (“effects,”
//! sometimes known as observers) to re-run. These two halves of the reactive system are inter-dependent.
//! Without effects, signals can change within the reactive system but never be observed in a way
//! that interacts with the outside world. Without signals, effects run once but never again, as
//! there’s no observable value to subscribe to.
//!
//! Here are the most commonly-used functions and types you'll need to build a reactive system:
//!
//! ### Signals
//! 1. *Signals:* [create_signal](crate::create_signal), which returns a ([ReadSignal](crate::ReadSignal),
//!    [WriteSignal](crate::WriteSignal)) tuple, or [create_rw_signal](crate::create_rw_signal), which returns
//!    a signal [RwSignal](crate::RwSignal) without this read-write segregation.
//! 2. *Derived Signals:* any function that relies on another signal.
//! 3. *Memos:* [create_memo](crate::create_memo), which returns a [Memo](crate::Memo).
//! 4. *Resources:* [create_resource], which converts an `async` [std::future::Future] into a
//!    synchronous [Resource](crate::Resource) signal.
//!
//! ### Effects
//! 1. Use [create_effect](crate::create_effect) when you need to synchronize the reactive system
//!    with something outside it (for example: logging to the console, writing to a file or local storage)
//! 2. The Leptos DOM renderer wraps any [Fn] in your template with [create_effect](crate::create_effect), so
//!    components you write do *not* need explicit effects to synchronize with the DOM.
//!
//! ### Example
//! ```
//! use leptos_reactive::*;
//!
//! // creates a new reactive Scope
//! // this is omitted from most of the examples in the docs
//! // you usually won't need to call it yourself
//! create_scope(create_runtime(), |cx| {
//!     // a signal: returns a (getter, setter) pair
//!     let (count, set_count) = create_signal(cx, 0);
//!
//!     // calling the getter gets the value
//!     assert_eq!(count(), 0);
//!     // calling the setter sets the value
//!     set_count(1);
//!     // or we can mutate it in place with update()
//!     set_count.update(|n| *n += 1);
//!
//!     // a derived signal: a plain closure that relies on the signal
//!     // the closure will run whenever we *access* double_count()
//!     let double_count = move || count() * 2;
//!     assert_eq!(double_count(), 4);
//!
//!     // a memo: subscribes to the signal
//!     // the closure will run only when count changes
//!     let memoized_triple_count = create_memo(cx, move |_| count() * 3);
//!     assert_eq!(memoized_triple_count(), 6);
//!
//!     // this effect will run whenever count() changes
//!     create_effect(cx, move |_| {
//!         println!("Count = {}", count());
//!     });
//! });
//! ```

#[cfg_attr(debug_assertions, macro_use)]
extern crate tracing;

#[macro_use]
mod signal;
mod context;
mod effect;
mod hydration;
mod memo;
mod node;
mod resource;
mod runtime;
mod scope;
mod selector;
mod serialization;
mod signal_wrappers_read;
mod signal_wrappers_write;
mod slice;
mod spawn;
mod spawn_microtask;
mod stored_value;
pub mod suspense;

pub use context::*;
pub use effect::*;
pub use memo::*;
pub use resource::*;
use runtime::*;
pub use runtime::{create_runtime, RuntimeId};
pub use scope::*;
pub use selector::*;
pub use serialization::*;
pub use signal::{prelude as signal_prelude, *};
pub use signal_wrappers_read::*;
pub use signal_wrappers_write::*;
pub use slice::*;
pub use spawn::*;
pub use spawn_microtask::*;
pub use stored_value::*;
pub use suspense::SuspenseContext;

mod macros {
    macro_rules! debug_warn {
        ($($x:tt)*) => {
            {
                #[cfg(debug_assertions)]
                {
                    ($crate::console_warn(&format_args!($($x)*).to_string()))
                }
                #[cfg(not(debug_assertions))]
                {
                    ($($x)*)
                }
            }
        }
    }

    pub(crate) use debug_warn;
}

pub(crate) fn console_warn(s: &str) {
    #[cfg(not(any(feature = "csr", feature = "hydrate")))]
    eprintln!("{s}");
    #[cfg(any(feature = "csr", feature = "hydrate"))]
    web_sys::console::warn_1(&wasm_bindgen::JsValue::from_str(s));
}