freya_components/
activable_route.rs1use freya_core::prelude::*;
2use freya_router::{
3 hooks::use_route,
4 prelude::Routable,
5};
6
7use crate::activable_route_context::ActivableRouteContext;
8
9#[derive(PartialEq, Clone)]
10pub struct ActivableRoute<T> {
11 child: Element,
12 route: T,
13 exact: bool,
14 routes: Vec<T>,
15}
16
17impl<T> ActivableRoute<T> {
18 pub fn new(route: T, child: impl Into<Element>) -> Self {
19 Self {
20 child: child.into(),
21 route,
22 exact: false,
23 routes: vec![],
24 }
25 }
26
27 pub fn exact(mut self, exact: bool) -> Self {
28 self.exact = exact;
29 self
30 }
31
32 pub fn routes(mut self, routes: Vec<T>) -> Self {
33 self.routes = routes;
34 self
35 }
36}
37
38impl<T: PartialEq + Clone + 'static + Routable> Render for ActivableRoute<T> {
39 fn render(&self) -> impl IntoElement {
40 let current_route = use_route::<T>();
41
42 let is_descendent_route_active = current_route.is_child_of(&self.route);
43 let is_descendent_routes_active = self
44 .routes
45 .iter()
46 .any(|route| current_route.is_child_of(route));
47 let is_descendent_active =
48 !self.exact && (is_descendent_route_active || is_descendent_routes_active);
49
50 let is_exact_active = current_route == self.route || self.routes.contains(¤t_route);
51
52 let is_active = is_descendent_active || is_exact_active;
53
54 let mut ctx = use_provide_context::<ActivableRouteContext>(|| {
55 ActivableRouteContext(State::create(is_active))
56 });
57
58 if *ctx.0.peek() != is_active {
59 *ctx.0.write() = is_active;
60 }
61
62 self.child.clone()
63 }
64}