freya_router/contexts/
outlet.rs

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
use dioxus_lib::prelude::*;

use crate::{
    routable::Routable,
    utils::use_router_internal::use_router_internal,
};

/// A context that manages nested routing levels for outlet components.
///
/// The outlet context keeps track of the current nesting level of routes and helps
/// manage the hierarchical structure of nested routes in the application.
///
/// # Type Parameters
///
/// * `R` - The routable type that implements the routing logic
#[derive(Clone, Default)]
pub struct OutletContext<R> {
    current_level: usize,
    _marker: std::marker::PhantomData<R>,
}

impl<R> OutletContext<R> {
    /// Creates a new outlet context starting at level 0
    pub fn new() -> Self {
        Self {
            current_level: 0,
            _marker: std::marker::PhantomData,
        }
    }

    /// Creates a new outlet context for the next nesting level
    pub fn next(&self) -> Self {
        Self {
            current_level: self.current_level + 1,
            _marker: std::marker::PhantomData,
        }
    }

    /// Returns the current nesting level of this outlet
    pub fn level(&self) -> usize {
        self.current_level
    }

    pub(crate) fn render() -> Element
    where
        R: Routable + Clone,
    {
        let router = use_router_internal().expect("Outlet must be inside of a router");
        let outlet: OutletContext<R> = use_outlet_context();
        let current_level = outlet.level();
        provide_context(outlet.next());
        router.current::<R>().render(current_level)
    }
}

/// Returns the current outlet context from the component hierarchy.
///
/// This hook retrieves the outlet context from the current component scope. If no context is found,
/// it creates a new context with a default level of 0.
///
/// # Type Parameters
///
/// * `R` - The routable type that implements the routing logic
///
/// # Returns
///
/// Returns an [`OutletContext<R>`] containing the current nesting level information.
///
/// # Examples
///
/// ```rust, no_run
/// # use dioxus_lib::prelude::*;
/// # use freya_router::prelude::{use_outlet_context,Routable};
/// # #[derive(Routable,Clone,PartialEq)]
/// # enum MyRouter {
/// #   #[route("/")]
/// #   MyView
/// # }
/// # #[component]
/// # fn MyView() -> Element {
/// #   rsx!( rect {} )
/// # }
/// let outlet_ctx = use_outlet_context::<MyRouter>();
/// println!("Current nesting level: {}", outlet_ctx.level());
/// ```
pub fn use_outlet_context<R: Clone + 'static>() -> OutletContext<R> {
    use_hook(|| try_consume_context().unwrap_or_else(OutletContext::new))
}