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))
}