tessera_ui/
router.rs

1//! Root routing entry utilities.
2//!
3//! This module re‑exports [`push`] and [`pop`] for manipulating the navigation stack
4//! and provides the [`router_root`] component which drives per‑frame execution of
5//! the current (top) destination.
6//!
7//! Core flow:
8//! * On the first frame, the supplied `root_dest` is pushed if the stack is empty.
9//! * On every frame, the top destination's `exec_component()` is invoked.
10//!
11//! The actual stack and destination logic live in `tessera_ui_shard::router`.
12//!
13//! # Typical Minimal Usage
14//!
15//! ```
16//! use tessera_ui::{tessera, shard, router::{router_root, Router}};
17//!
18//! #[shard]
19//! #[tessera]
20//! fn home_screen() { /* ... */ }
21//!
22//! // In your app's root layout:
23//! router_root(HomeScreenDestination {});
24//!
25//! ##[shard]
26//! ##[tessera]
27//! # fn settings_screen() { /* ... */ }
28//!
29//! // Somewhere inside an event (e.g. button click) to navigate:
30//! Router::with_mut(|router| {
31//!     router.push(SettingsScreenDestination {});
32//! });
33//!
34//! // To go back:
35//! Router::with_mut(|router| {
36//!     router.pop();
37//! });
38//! ```
39//!
40//! # Behavior
41//!
42//! * `router_root` is idempotent regarding the initial destination: it only pushes
43//!   `root_dest` when the stack is empty.
44//! * Subsequent frames never push automatically; they only execute the current top.
45//! * If the stack is externally cleared (not typical), `router_root` will push again.
46//!
47//! # Panics
48//!
49//! Panics if after internal logic the stack is still empty (indicates an unexpected
50//! mutation from user code while in the execution closure).
51//!
52//! # See Also
53//!
54//! * [`tessera_ui_shard::router::RouterDestination`]
55//! * `#[shard]` macro which generates `*Destination` structs.
56use tessera_ui_macros::tessera;
57
58pub use tessera_ui_shard::router::{Router, RouterDestination};
59
60/// Root component that drives the shard router stack each frame.
61///
62/// See module‑level docs for detailed usage patterns.
63///
64/// # Parameters
65/// * `root_dest` - The destination pushed only once when the stack is empty.
66///
67/// # Notes
68///
69/// Keep `router_root` exactly once at the point in your tree that should display
70/// the active routed component. Wrapping it multiple times would still execute
71/// only one top destination but wastes layout work.
72#[tessera(crate)]
73pub fn router_root(root_dest: impl RouterDestination + 'static) {
74    Router::try_init(root_dest);
75    Router::with_mut(|router| {
76        router
77            .last()
78            .expect("Router stack should not be empty")
79            .exec_component();
80    });
81}