Skip to main content

tessera_shard/router/
home.rs

1use std::sync::Arc;
2
3use tessera_ui::{State, remember, tessera};
4
5use crate::router::{RouterController, RouterDestination, back::route_display};
6
7/// # shard_home
8///
9/// Provide a router controller and render shard UI rooted at the active
10/// destination.
11///
12/// ## Usage
13///
14/// Mount the root route for an app shell.
15/// On Android, system back pops one route and a predictive gesture previews
16/// the previous route. Android handles back at the root of the stack.
17///
18/// ## Parameters
19///
20/// - `root` — initial destination used when `controller` is omitted
21/// - `controller` — optional external router controller state
22///
23/// ## Examples
24///
25/// ```rust
26/// use tessera_shard::shard_home;
27///
28/// # #[derive(Clone)]
29/// # struct DemoDestination;
30/// # impl tessera_shard::router::RouterDestination for DemoDestination {
31/// #     fn exec_component(&self, _: tessera_ui::State<tessera_shard::RouterController>) {}
32/// #     fn exec_component_handle(&self) -> std::sync::Arc<dyn Fn(tessera_ui::State<tessera_shard::RouterController>) + Send + Sync> {
33/// #         std::sync::Arc::new(|_| {})
34/// #     }
35/// #     fn destination_id() -> &'static str { "demo" }
36/// # }
37/// # #[tessera_ui::tessera]
38/// # fn demo() {
39/// shard_home().root(DemoDestination);
40/// # }
41/// # tessera_ui::testing::layout_test(demo).run();
42/// ```
43#[tessera(tessera_ui)]
44pub fn shard_home(
45    #[prop(skip_setter)] root: Option<Arc<dyn RouterDestination>>,
46    controller: Option<State<RouterController>>,
47) {
48    let internal_controller = remember({
49        let root = root.clone();
50        move || match root.clone() {
51            Some(root) => RouterController::with_root_shared(root),
52            None => RouterController::new(),
53        }
54    });
55    let controller = controller.unwrap_or(internal_controller);
56
57    if root.is_none()
58        && controller == internal_controller
59        && controller.with(RouterController::is_empty)
60    {
61        panic!("shard_home requires `root` when `controller` is not provided");
62    }
63
64    route_display(controller);
65}
66
67impl ShardHomeBuilder {
68    pub fn root<T>(&self, root: T) -> Self
69    where
70        T: RouterDestination + 'static,
71    {
72        let value: Option<Arc<dyn RouterDestination>> = Some(Arc::new(root));
73        self.props
74            .configure("root", move |props| props.root = value);
75        Self { props: self.props }
76    }
77}