-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
424 additions
and
296 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
use std::{ | ||
fmt::{self, Debug}, | ||
rc::Rc, | ||
}; | ||
|
||
use yew::{Component, ComponentLink, Html, Properties}; | ||
|
||
use crate::{router::RouterListener, Routable, Router}; | ||
|
||
/// Wraps `Rc` around `Fn` so it can be passed as a prop. | ||
pub struct RenderFn<T: Routable>(Rc<dyn Fn(&Router<T>) -> Html>); | ||
|
||
impl<T: Routable> RenderFn<T> { | ||
/// Creates a new [`RenderFn`] | ||
/// | ||
/// It is recommended that you use [`Router::render`] instead | ||
pub fn new(value: impl Fn(&Router<T>) -> Html + 'static) -> Self { | ||
Self(Rc::new(value)) | ||
} | ||
} | ||
|
||
impl<T: Routable> Debug for RenderFn<T> { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
f.debug_tuple("RenderFn").finish() | ||
} | ||
} | ||
|
||
impl<T: Routable> Clone for RenderFn<T> { | ||
fn clone(&self) -> Self { | ||
Self(Rc::clone(&self.0)) | ||
} | ||
} | ||
|
||
impl<T: Routable> PartialEq for RenderFn<T> { | ||
fn eq(&self, other: &Self) -> bool { | ||
// https://github.com/rust-lang/rust-clippy/issues/6524 | ||
#[allow(clippy::vtable_address_comparisons)] | ||
Rc::ptr_eq(&self.0, &other.0) | ||
} | ||
} | ||
|
||
/// Props for [`RouterConsumer`] | ||
#[derive(Clone, PartialEq, Properties)] | ||
pub struct RouterConsumerProps<T: Routable> { | ||
/// Callback which returns [`Html`] to be rendered for the current route. | ||
pub render: RenderFn<T>, | ||
} | ||
|
||
/// The context provider component. | ||
/// | ||
/// Every child (direct or indirect) of this component may access the context value. | ||
/// In order to consume contexts, [`ComponentLink::context`][Scope::context] method is used, | ||
/// In function components the `use_context` hook is used. | ||
#[derive(Debug)] | ||
pub struct RouterConsumer<T: Routable> { | ||
render: RenderFn<T>, | ||
router: Router<T>, | ||
_listener: RouterListener<T>, | ||
} | ||
|
||
impl<T: Routable> Component for RouterConsumer<T> { | ||
type Message = (); | ||
type Properties = RouterConsumerProps<T>; | ||
|
||
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self { | ||
let router = Router::new(link.clone()); | ||
let _listener = router.register(link.callback(|_| ())); | ||
Self { | ||
render: props.render, | ||
router, | ||
_listener, | ||
} | ||
} | ||
|
||
fn update(&mut self, _msg: Self::Message) -> bool { | ||
true | ||
} | ||
|
||
fn change(&mut self, props: Self::Properties) -> bool { | ||
if self.render != props.render { | ||
self.render = props.render; | ||
true | ||
} else { | ||
false | ||
} | ||
} | ||
|
||
fn view(&self) -> Html { | ||
(&self.render.0)(&self.router) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,9 @@ | |
mod link; | ||
pub use link::*; | ||
|
||
mod mount; | ||
pub use mount::*; | ||
|
||
mod consumer; | ||
pub use consumer::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
use std::rc::Rc; | ||
|
||
use yew::{html, Callback, Children, Component, ComponentLink, ContextProvider, Html, Properties}; | ||
|
||
use crate::{context::RoutingContext, Routable, RouterAction}; | ||
|
||
/// Props for [`ContextProvider`] | ||
#[derive(Debug, Clone, PartialEq, Properties)] | ||
pub struct MountProps<T: Routable> { | ||
/// Context value to be passed down | ||
pub route: Rc<T>, | ||
pub onroute: Callback<RouterAction<T>>, | ||
/// Children | ||
pub children: Children, | ||
} | ||
|
||
/// The context provider component. | ||
/// | ||
/// Every child (direct or indirect) of this component may access the context value. | ||
/// In order to consume contexts, [`ComponentLink::context`][Scope::context] method is used, | ||
/// In function components the `use_context` hook is used. | ||
#[derive(Debug)] | ||
pub struct Mount<T: Routable> { | ||
context: RoutingContext<T>, | ||
children: Children, | ||
} | ||
|
||
impl<T: Routable> Component for Mount<T> { | ||
type Message = (); | ||
type Properties = MountProps<T>; | ||
|
||
fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self { | ||
Self { | ||
children: props.children, | ||
context: RoutingContext { | ||
route: props.route, | ||
onroute: props.onroute, | ||
}, | ||
} | ||
} | ||
|
||
fn update(&mut self, _msg: Self::Message) -> bool { | ||
false | ||
} | ||
|
||
fn change(&mut self, props: Self::Properties) -> bool { | ||
self.children = props.children; | ||
self.context = RoutingContext { | ||
route: props.route, | ||
onroute: props.onroute, | ||
}; | ||
true | ||
} | ||
|
||
fn view(&self) -> Html { | ||
let context = self.context.clone(); | ||
html! { | ||
<ContextProvider<RoutingContext<T>> context=context> | ||
{ self.children.clone() } | ||
</ContextProvider<RoutingContext<T>>> | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.