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
//! Standalone, flexible fine-grained reactivity
//!
//! This crate brings the benefits of fine-grained reactivity to contexts beyond traditional
//! web UI. Signals are lightweight metadata (4 bytes) - your values stay in your structs.
//!
//! # Quick Start
//!
//! ```ignore
//! use reaktiv::{Signal, Effect, Computed, Transaction, flush_effects};
//!
//! struct Component {
//! value: f64,
//! signal: Signal, // Just 4 bytes of metadata
//! }
//!
//! impl Component {
//! fn set(&mut self, v: f64) {
//! self.value = v;
//! self.signal.emit(); // Notify subscribers
//! }
//!
//! fn get(&self) -> f64 {
//! self.signal.track_dependency(); // Auto-track in effects
//! self.value
//! }
//! }
//!
//! // Effects auto-track dependencies and run immediately
//! let effect = Effect::new(|| {
//! let value = component.get(); // Tracks dependency automatically
//! println!("Value: {}", value);
//! });
//!
//! // Batch changes with transactions - effects run once at the end
//! Transaction::run(|| {
//! component.set(1.0);
//! component.set(2.0);
//! }); // Effect runs once with final value
//!
//! flush_effects();
//! ```
//!
//! # Core Types
//!
//! - [`Signal`] - Lightweight reactive marker (4 bytes). Call [`emit()`](Signal::emit) when value changes.
//! - [`Effect`] - Auto-runs when tracked signals change. Runs immediately on creation.
//! - [`Computed<T>`] - Cached derived value. Only recomputes when dependencies change.
//! - [`Transaction`] - Batch multiple changes into one effect run.
//!
//! # Working with Signals
//!
//! ```ignore
//! let signal = Signal::new();
//!
//! // Inside an effect, track this signal as a dependency
//! signal.track_dependency();
//!
//! // Notify all subscribers when value changes
//! signal.emit();
//!
//! // Skip UI-only subscribers (useful for preventing update loops)
//! signal.emit_from_ui();
//! ```
//!
//! # Creating Effects
//!
//! ```ignore
//! // Effect runs immediately and tracks dependencies automatically
//! let effect = Effect::new(|| {
//! signal.track_dependency();
//! println!("Signal changed!");
//! });
//!
//! // Skippable effects can be deferred under load
//! let skippable = Effect::new_skippable(|| {
//! // Non-critical UI updates
//! });
//! ```
//!
//! # Computed Values
//!
//! ```ignore
//! // Runs immediately and caches the result
//! let doubled = Computed::new(|| {
//! input_signal.track_dependency();
//! input_value * 2
//! });
//!
//! // Defers computation until first access
//! let lazy = Computed::lazy(|| expensive_computation());
//!
//! let value = doubled.get(); // Returns cached value
//! ```
//!
//! # Batching Updates
//!
//! ```ignore
//! // Effects run once at the end instead of 3 times
//! Transaction::run(|| {
//! signal_a.emit();
//! signal_b.emit();
//! signal_c.emit();
//! }); // All pending effects run here
//!
//! // Suppress UI-triggered effects during internal updates
//! Transaction::no_ui_updates(|| {
//! internal_recalculation();
//! });
//! ```
//!
//! # Processing Effects
//!
//! ```ignore
//! flush_effects(); // Process all pending effects synchronously
//! is_processing_scheduled(); // Check if effects are waiting to run
//! untracked(|| { ... }); // Read signals without tracking dependencies
//!
//! // For async/event loop integration
//! spawn_effect_loop(); // Start async effect processing
//! ```
// Internal modules
pub
// Core types
pub use Computed;
pub use Effect;
pub use Signal;
pub use Transaction;
// Key functions
pub use ;
// Executor integration (for custom event loops)
pub use ;