fusor/lib.rs
1//! Reactive Rust for HTML script blocks, compiled by Cargo without a Rust DSL.
2//!
3//! ```
4//! use fusor::{signal, derived, effect, batch};
5//! let count = signal(0);
6//! let doubled = derived({ let count = count.clone(); move || count.get() * 2 });
7//! let subscription = effect(move || println!("{}", doubled.get()));
8//! batch(|| { count.set(2); count.set(3); });
9//! // Prints 0, then 6. Dropping the subscription stops it.
10//! drop(subscription);
11//! ```
12
13#[doc(hidden)]
14pub mod authoring;
15pub mod bind;
16mod cleanup;
17pub mod coherence;
18mod owner;
19mod reactive;
20#[doc(hidden)]
21pub mod render;
22pub use cleanup::{Cleanup, CleanupEffect, effect_with_cleanup};
23pub use owner::{ContextError, ContextKey, Owner, OwnerHandle, Registration};
24/// Source-version snapshots for supported renderer and async-read integration.
25#[doc(hidden)]
26pub use reactive::versions;
27
28/// Versioned contract shared by the HTML compiler and the DOM runtime.
29/// This is an implementation interface, not application authoring syntax.
30#[doc(hidden)]
31pub mod template;
32pub use reactive::{
33 Derived, Effect, Memo, Signal, batch, derived, effect, memo, memo_with_eq, signal, untrack,
34};
35
36/// The explicit input contract for compiler-resolved component tags.
37///
38/// `Inputs` is a named-field struct (or a unit struct for empty tags). The
39/// compiler builds it with an ordinary struct literal: rustc checks every field,
40/// its visibility, and its type. Input expressions and this constructor run once
41/// per mounted identity, untracked. Pass signals or memos for live shared inputs.
42/// Construction is separate from rendering: browser mounts require `Component`.
43/// `owner` is the new child's prepared owner. The caller owns preparation,
44/// activation, rollback, and conversion of construction errors. This trait does
45/// not itself defer ordinary effects or activate the owner.
46///
47/// Simple concrete components can use `#[derive(fusor::FromInputs)]`:
48/// mark every field `#[input]` (required from the parent) or
49/// `#[local(init = expression)]` (initialized once per instance). The derive
50/// generates a `TypeNameInputs` struct with the component's visibility and
51/// public input fields, plus this trait implementation. Original field
52/// visibility is unchanged. Unit and all-local components get unit Inputs.
53///
54/// Local expressions execute in declaration order in the generated constructor;
55/// `Self` refers to the component. They have no implicit `inputs`/`owner` names
56/// and cannot access other instance fields. Implement this trait manually for
57/// input-dependent initialization, owner-aware setup, or generic components.
58/// The derive creates neither a `new` method nor a template association.
59/// Use `#[from_inputs(crate = ::alias)]` when renaming the runtime dependency.
60/// Enable the `derive` feature to use the derive without any browser dependencies;
61/// `dom` also enables it. The derived error type is `std::convert::Infallible`.
62///
63/// # Migrating manual implementations
64///
65/// Existing browser implementations add `type Error = fusor::dom::JsValue;` and
66/// keep their return signature. `fusor::dom::FromInputs` is this same trait.
67/// Portable implementations choose their own error type. Browser mounting uses
68/// `fusor::dom::IntoMountError`: it preserves `JsValue` and supports `Infallible`,
69/// `String`, and `&str`. Implement it for custom browser errors; there is no
70/// blanket `Display` conversion.
71pub trait FromInputs: Sized {
72 type Inputs;
73 type Error;
74 fn from_inputs(inputs: Self::Inputs, owner: OwnerHandle) -> Result<Self, Self::Error>;
75}
76
77#[cfg(feature = "dom")]
78pub mod dom;
79
80#[cfg(feature = "derive")]
81pub use fusor_macros::FromInputs;
82
83#[cfg(feature = "javascript")]
84pub mod js;
85#[cfg(feature = "javascript")]
86pub use fusor_macros::JsInputs;
87#[cfg(feature = "javascript")]
88pub use js::JsInputs;
89
90/// The small set of types needed by a reactive application.
91pub mod prelude {
92 pub use crate::FromInputs;
93 #[cfg(feature = "javascript")]
94 pub use crate::JsInputs;
95 #[cfg(feature = "dom")]
96 pub use crate::dom::{Component, Content, Scope, TemplateComponent, document, element};
97 pub use crate::{Cleanup, CleanupEffect, effect_with_cleanup};
98 pub use crate::{ContextError, ContextKey, Owner, OwnerHandle};
99 pub use crate::{
100 Derived, Effect, Memo, Signal, batch, derived, effect, memo, memo_with_eq, signal, untrack,
101 };
102}