freya_components/
animated_router.rs1use std::marker::PhantomData;
2
3use freya_core::prelude::*;
4use freya_router::prelude::{
5 Routable,
6 use_route,
7};
8
9#[derive(Clone)]
10pub enum AnimatedRouterContext<R: Routable + PartialEq> {
11 FromTo(R, R),
13 In(R),
15}
16
17impl<R: Routable + PartialEq> AnimatedRouterContext<R> {
18 pub fn target_route(&self) -> &R {
20 match self {
21 Self::FromTo(_, to) => to,
22 Self::In(to) => to,
23 }
24 }
25
26 pub fn set_target_route(&mut self, to: R) {
28 match self {
29 Self::FromTo(old_from, old_to) => {
30 *old_from = old_to.clone();
31 *old_to = to
32 }
33 Self::In(old_to) => *self = Self::FromTo(old_to.clone(), to),
34 }
35 }
36
37 pub fn settle(&mut self) {
39 if let Self::FromTo(_, to) = self {
40 *self = Self::In(to.clone())
41 }
42 }
43}
44
45#[derive(Clone, PartialEq)]
46pub struct AnimatedRouter<R> {
47 content: Element,
48 _phantom: PhantomData<R>,
49}
50
51impl<R> AnimatedRouter<R> {
52 pub fn new(children: impl Into<Element>) -> Self {
53 Self {
54 content: children.into(),
55 _phantom: PhantomData::<R>,
56 }
57 }
58}
59
60impl<R: Routable + 'static + PartialEq> Render for AnimatedRouter<R> {
64 fn render(&self) -> impl IntoElement {
65 let route = use_route::<R>();
66 let mut prev_route = use_state(|| AnimatedRouterContext::In(route.clone()));
67 use_provide_context(move || prev_route);
68
69 if prev_route.peek().target_route() != &route {
70 prev_route.write().set_target_route(route);
71 }
72
73 self.content.clone()
74 }
75}
76
77pub fn use_animated_router<Route: Routable + PartialEq>() -> State<AnimatedRouterContext<Route>> {
79 use_consume()
80}