mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 14:54:16 +00:00
stash
This commit is contained in:
parent
9cdd8cac15
commit
db4c1cb4b3
8 changed files with 223 additions and 186 deletions
|
@ -7,7 +7,7 @@ version.workspace = true
|
|||
any_spawner = { workspace = true }
|
||||
either_of = { workspace = true }
|
||||
reactive_graph = { workspace = true }
|
||||
tachys = { workspace = true }
|
||||
tachys = { workspace = true, features = ["reactive_graph"] }
|
||||
url = "2"
|
||||
js-sys = { version = "0.3" }
|
||||
wasm-bindgen = { version = "0.2" }
|
||||
|
|
52
routing/src/matching/choose_view.rs
Normal file
52
routing/src/matching/choose_view.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use crate::RouteData;
|
||||
use either_of::*;
|
||||
use tachys::{renderer::Renderer, view::Render};
|
||||
|
||||
pub trait ChooseView<R>
|
||||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type Output: Render<R>;
|
||||
|
||||
fn choose(self, route_data: RouteData<R>) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<F, View, R> ChooseView<R> for F
|
||||
where
|
||||
F: Fn(RouteData<R>) -> View,
|
||||
View: Render<R>,
|
||||
R: Renderer,
|
||||
{
|
||||
type Output = View;
|
||||
|
||||
fn choose(self, route_data: RouteData<R>) -> Self::Output {
|
||||
self(route_data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> ChooseView<R> for ()
|
||||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type Output = ();
|
||||
|
||||
fn choose(self, _route_data: RouteData<R>) -> Self::Output {}
|
||||
}
|
||||
|
||||
impl<A, B, Rndr> ChooseView<Rndr> for Either<A, B>
|
||||
where
|
||||
A: ChooseView<Rndr>,
|
||||
B: ChooseView<Rndr>,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type Output = Either<A::Output, B::Output>;
|
||||
|
||||
fn choose(self, route_data: RouteData<Rndr>) -> Self::Output {
|
||||
match self {
|
||||
Either::Left(f) => Either::Left(f.choose(route_data)),
|
||||
Either::Right(f) => Either::Right(f.choose(route_data)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add other Either implementations
|
|
@ -84,7 +84,6 @@ impl PossibleRouteMatch for WildcardSegment {
|
|||
mod tests {
|
||||
use super::PossibleRouteMatch;
|
||||
use crate::{ParamSegment, StaticSegment, WildcardSegment};
|
||||
use alloc::vec::Vec;
|
||||
|
||||
#[test]
|
||||
fn single_param_match() {
|
||||
|
|
|
@ -76,7 +76,6 @@ impl PossibleRouteMatch for StaticSegment {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{PossibleRouteMatch, StaticSegment};
|
||||
use alloc::vec::Vec;
|
||||
|
||||
#[test]
|
||||
fn single_static_match() {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
mod choose_view;
|
||||
mod path_segment;
|
||||
pub use choose_view::*;
|
||||
pub use path_segment::*;
|
||||
mod horizontal;
|
||||
mod nested;
|
||||
|
@ -40,12 +42,15 @@ impl<Children, Rndr> Routes<Children, Rndr> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, Children, Rndr> Routes<Children, Rndr>
|
||||
impl<Children, Rndr> Routes<Children, Rndr>
|
||||
where
|
||||
Rndr: Renderer + 'static,
|
||||
Children: MatchNestedRoutes<'a, Rndr>,
|
||||
Children: MatchNestedRoutes<Rndr>,
|
||||
{
|
||||
pub fn match_route(&'a self, path: &'a str) -> Option<Children::Match> {
|
||||
pub fn match_route<'a>(
|
||||
&'a self,
|
||||
path: &'a str,
|
||||
) -> Option<Children::Match<'a>> {
|
||||
let path = match &self.base {
|
||||
None => path,
|
||||
Some(base) => {
|
||||
|
@ -72,10 +77,10 @@ where
|
|||
}
|
||||
|
||||
pub fn generate_routes(
|
||||
&'a self,
|
||||
&self,
|
||||
) -> (
|
||||
Option<&str>,
|
||||
impl IntoIterator<Item = Vec<PathSegment>> + 'a,
|
||||
impl IntoIterator<Item = Vec<PathSegment>> + '_,
|
||||
) {
|
||||
(self.base.as_deref(), self.children.generate_routes())
|
||||
}
|
||||
|
@ -98,22 +103,27 @@ where
|
|||
|
||||
fn to_params(&self) -> Self::Params;
|
||||
|
||||
fn into_child(self) -> Option<Self::Child>;
|
||||
|
||||
fn to_view(&self) -> impl Fn() -> View;
|
||||
fn into_view_and_child(
|
||||
self,
|
||||
) -> (
|
||||
impl ChooseView<R, Output = Self::View> + 'a,
|
||||
Option<Self::Child>,
|
||||
);
|
||||
}
|
||||
|
||||
pub trait MatchNestedRoutes<'a, R>
|
||||
pub trait MatchNestedRoutes<R>
|
||||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type Data;
|
||||
type Match: MatchInterface<'a, R>;
|
||||
type Match<'a>: MatchInterface<'a, R>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn match_nested(
|
||||
fn match_nested<'a>(
|
||||
&'a self,
|
||||
path: &'a str,
|
||||
) -> (Option<(RouteMatchId, Self::Match)>, &'a str);
|
||||
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &str);
|
||||
|
||||
fn generate_routes(
|
||||
&self,
|
||||
|
@ -124,14 +134,17 @@ where
|
|||
mod tests {
|
||||
use super::{NestedRoute, ParamSegment, Routes};
|
||||
use crate::{MatchInterface, PathSegment, StaticSegment, WildcardSegment};
|
||||
use std::marker::PhantomData;
|
||||
use tachys::renderer::dom::Dom;
|
||||
|
||||
#[test]
|
||||
pub fn matches_single_root_route() {
|
||||
let routes = Routes::new(NestedRoute {
|
||||
let routes = Routes::<_, Dom>::new(NestedRoute {
|
||||
segments: StaticSegment("/"),
|
||||
children: (),
|
||||
data: (),
|
||||
view: || (),
|
||||
view: |_| (),
|
||||
rndr: PhantomData,
|
||||
});
|
||||
let matched = routes.match_route("/");
|
||||
assert!(matched.is_some());
|
||||
|
@ -151,10 +164,12 @@ mod tests {
|
|||
segments: (StaticSegment("author"), StaticSegment("contact")),
|
||||
children: (),
|
||||
data: (),
|
||||
view: "Contact Me",
|
||||
view: |_| "Contact Me",
|
||||
rndr: PhantomData,
|
||||
},
|
||||
data: (),
|
||||
view: "Home",
|
||||
view: |_| "Home",
|
||||
rndr: PhantomData,
|
||||
});
|
||||
|
||||
// route generation
|
||||
|
@ -188,9 +203,11 @@ mod tests {
|
|||
children: (),
|
||||
data: (),
|
||||
view: "Contact Me",
|
||||
rndr: PhantomData,
|
||||
},
|
||||
data: (),
|
||||
view: "Home",
|
||||
rndr: PhantomData,
|
||||
});
|
||||
let matched = routes.match_route("/");
|
||||
assert!(matched.is_none());
|
||||
|
@ -207,16 +224,19 @@ mod tests {
|
|||
children: (),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
NestedRoute {
|
||||
segments: StaticSegment("about"),
|
||||
children: (),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
NestedRoute {
|
||||
segments: StaticSegment("/blog"),
|
||||
|
@ -226,16 +246,19 @@ mod tests {
|
|||
children: (),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
NestedRoute {
|
||||
segments: (StaticSegment("post"), ParamSegment("id")),
|
||||
children: (),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
));
|
||||
|
||||
|
@ -289,16 +312,19 @@ mod tests {
|
|||
children: (),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
NestedRoute {
|
||||
segments: StaticSegment("about"),
|
||||
children: (),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
NestedRoute {
|
||||
segments: StaticSegment("/blog"),
|
||||
|
@ -308,12 +334,14 @@ mod tests {
|
|||
children: (),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
NestedRoute {
|
||||
segments: StaticSegment("category"),
|
||||
children: (),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
NestedRoute {
|
||||
segments: (
|
||||
|
@ -323,10 +351,12 @@ mod tests {
|
|||
children: (),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
NestedRoute {
|
||||
segments: (
|
||||
|
@ -336,6 +366,7 @@ mod tests {
|
|||
children: (),
|
||||
data: (),
|
||||
view: || (),
|
||||
rndr: PhantomData,
|
||||
},
|
||||
),
|
||||
"/portfolio",
|
||||
|
|
|
@ -2,21 +2,24 @@ use super::{
|
|||
MatchInterface, MatchNestedRoutes, PartialPathMatch, PathSegment,
|
||||
PossibleRouteMatch, RouteMatchId,
|
||||
};
|
||||
use crate::{ChooseView, RouteData};
|
||||
use core::{fmt, iter};
|
||||
use tachys::renderer::Renderer;
|
||||
use std::marker::PhantomData;
|
||||
use tachys::{renderer::Renderer, view::Render};
|
||||
|
||||
mod tuples;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct NestedRoute<Segments, Children, Data, View> {
|
||||
pub struct NestedRoute<Segments, Children, Data, ViewFn, R> {
|
||||
pub segments: Segments,
|
||||
pub children: Children,
|
||||
pub data: Data,
|
||||
pub view: View,
|
||||
pub view: ViewFn,
|
||||
pub rndr: PhantomData<R>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct NestedMatch<'a, ParamsIter, Child, ViewFn, View> {
|
||||
pub struct NestedMatch<'a, ParamsIter, Child, ViewFn> {
|
||||
id: RouteMatchId,
|
||||
/// The portion of the full path matched only by this nested route.
|
||||
matched: &'a str,
|
||||
|
@ -24,12 +27,11 @@ pub struct NestedMatch<'a, ParamsIter, Child, ViewFn, View> {
|
|||
params: ParamsIter,
|
||||
/// The nested route.
|
||||
child: Child,
|
||||
view_fn: ViewFn,
|
||||
view: View
|
||||
view_fn: &'a ViewFn,
|
||||
}
|
||||
|
||||
impl<'a, ParamsIter, Child, View> fmt::Debug
|
||||
for NestedMatch<'a, ParamsIter, Child, View>
|
||||
impl<'a, ParamsIter, Child, ViewFn> fmt::Debug
|
||||
for NestedMatch<'a, ParamsIter, Child, ViewFn>
|
||||
where
|
||||
ParamsIter: fmt::Debug,
|
||||
Child: fmt::Debug,
|
||||
|
@ -43,16 +45,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, ParamsIter, Child, ViewFn, View, Rndr> MatchInterface<'a, Rndr>
|
||||
for NestedMatch<'a, ParamsIter, Child, ViewFn, View>
|
||||
impl<'a, ParamsIter, Child, ViewFn, Rndr> MatchInterface<'a, Rndr>
|
||||
for NestedMatch<'a, ParamsIter, Child, ViewFn>
|
||||
where
|
||||
Rndr: Renderer + 'static,
|
||||
ParamsIter: IntoIterator<Item = (&'a str, &'a str)> + Clone,
|
||||
Child: MatchInterface<'a, Rndr>,
|
||||
ViewFn: Fn(RouteData<Rndr>),
|
||||
ViewFn::Output: Render<Rndr>,
|
||||
{
|
||||
type Params = ParamsIter;
|
||||
type Child = Child;
|
||||
type View = View;
|
||||
type View = ViewFn::Output;
|
||||
|
||||
fn as_id(&self) -> RouteMatchId {
|
||||
self.id
|
||||
|
@ -66,43 +70,43 @@ where
|
|||
self.params.clone()
|
||||
}
|
||||
|
||||
fn into_child(self) -> Option<Self::Child> {
|
||||
Some(self.child)
|
||||
}
|
||||
|
||||
fn to_view(&self) -> Self::ViewFn {
|
||||
self.view
|
||||
fn into_view_and_child(
|
||||
self,
|
||||
) -> (
|
||||
impl ChooseView<Rndr, Output = Self::View> + 'a,
|
||||
Option<Self::Child>,
|
||||
) {
|
||||
(self.view_fn, Some(self.child))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, ParamsIter, Child, View> NestedMatch<'a, ParamsIter, Child, View> {
|
||||
impl<'a, ParamsIter, Child, ViewFn> NestedMatch<'a, ParamsIter, Child, ViewFn> {
|
||||
pub fn matched(&self) -> &'a str {
|
||||
self.matched
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Segments, Children, Data, View, Rndr> MatchNestedRoutes<'a, Rndr>
|
||||
for NestedRoute<Segments, Children, Data, View>
|
||||
impl<Segments, Children, Data, ViewFn, Rndr> MatchNestedRoutes<Rndr>
|
||||
for NestedRoute<Segments, Children, Data, ViewFn, Rndr>
|
||||
where
|
||||
Rndr: Renderer + 'static,
|
||||
Segments: PossibleRouteMatch,
|
||||
Children: MatchNestedRoutes<'a, Rndr>,
|
||||
<Segments::ParamsIter<'a> as IntoIterator>::IntoIter: Clone,
|
||||
<<Children::Match as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter:
|
||||
Children: MatchNestedRoutes<Rndr>,
|
||||
for<'a> <Segments::ParamsIter<'a> as IntoIterator>::IntoIter: Clone,
|
||||
for <'a> <<Children::Match<'a> as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter:
|
||||
Clone,
|
||||
Children: 'a,
|
||||
View: 'a,
|
||||
ViewFn: Fn(RouteData<Rndr>),
|
||||
{
|
||||
type Data = Data;
|
||||
type Match = NestedMatch<'a, iter::Chain<
|
||||
type Match<'a> = NestedMatch<'a, iter::Chain<
|
||||
<Segments::ParamsIter<'a> as IntoIterator>::IntoIter,
|
||||
<<Children::Match as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter,
|
||||
>, Children::Match, View>;
|
||||
<<Children::Match<'a> as MatchInterface<'a, Rndr>>::Params as IntoIterator>::IntoIter,
|
||||
>, Children::Match<'a>, ViewFn> where <Children as MatchNestedRoutes<Rndr>>::Match<'a>: 'a, ViewFn: 'a, Children: 'a, Segments: 'a, Data: 'a;
|
||||
|
||||
fn match_nested(
|
||||
fn match_nested<'a>(
|
||||
&'a self,
|
||||
path: &'a str,
|
||||
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
|
||||
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
|
||||
self.segments
|
||||
.test(path)
|
||||
.and_then(
|
||||
|
@ -125,7 +129,7 @@ where
|
|||
matched,
|
||||
params: params.chain(inner.to_params()),
|
||||
child: inner,
|
||||
view: &self.view,
|
||||
view_fn: &self.view,
|
||||
},
|
||||
)),
|
||||
remaining,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::{MatchInterface, MatchNestedRoutes, PathSegment, RouteMatchId};
|
||||
use crate::ChooseView;
|
||||
use core::iter;
|
||||
use either_of::*;
|
||||
use tachys::renderer::Renderer;
|
||||
|
@ -23,24 +24,27 @@ where
|
|||
iter::empty()
|
||||
}
|
||||
|
||||
fn into_child(self) -> Option<Self::Child> {
|
||||
None
|
||||
fn into_view_and_child(
|
||||
self,
|
||||
) -> (
|
||||
impl ChooseView<Rndr, Output = Self::View> + 'a,
|
||||
Option<Self::Child>,
|
||||
) {
|
||||
((), None)
|
||||
}
|
||||
|
||||
fn to_view(&self) -> Self::View {}
|
||||
}
|
||||
|
||||
impl<'a, Rndr> MatchNestedRoutes<'a, Rndr> for ()
|
||||
impl<Rndr> MatchNestedRoutes<Rndr> for ()
|
||||
where
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type Data = ();
|
||||
type Match = ();
|
||||
type Match<'a> = ();
|
||||
|
||||
fn match_nested(
|
||||
fn match_nested<'a>(
|
||||
&self,
|
||||
path: &'a str,
|
||||
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
|
||||
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
|
||||
(Some((RouteMatchId(0), ())), path)
|
||||
}
|
||||
|
||||
|
@ -72,27 +76,28 @@ where
|
|||
self.0.to_params()
|
||||
}
|
||||
|
||||
fn into_child(self) -> Option<Self::Child> {
|
||||
self.0.into_child()
|
||||
}
|
||||
|
||||
fn to_view(&self) -> Self::View {
|
||||
self.0.to_view()
|
||||
fn into_view_and_child(
|
||||
self,
|
||||
) -> (
|
||||
impl ChooseView<Rndr, Output = Self::View> + 'a,
|
||||
Option<Self::Child>,
|
||||
) {
|
||||
self.0.into_view_and_child()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A, Rndr> MatchNestedRoutes<'a, Rndr> for (A,)
|
||||
impl<A, Rndr> MatchNestedRoutes<Rndr> for (A,)
|
||||
where
|
||||
A: MatchNestedRoutes<'a, Rndr>,
|
||||
A: MatchNestedRoutes<Rndr>,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type Data = A::Data;
|
||||
type Match = A::Match;
|
||||
type Match<'a> = A::Match<'a> where A: 'a;
|
||||
|
||||
fn match_nested(
|
||||
fn match_nested<'a>(
|
||||
&'a self,
|
||||
path: &'a str,
|
||||
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
|
||||
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
|
||||
self.0.match_nested(path)
|
||||
}
|
||||
|
||||
|
@ -105,7 +110,7 @@ where
|
|||
|
||||
impl<'a, A, B, Rndr> MatchInterface<'a, Rndr> for Either<A, B>
|
||||
where
|
||||
Rndr: Renderer + 'a,
|
||||
Rndr: Renderer,
|
||||
A: MatchInterface<'a, Rndr>,
|
||||
B: MatchInterface<'a, Rndr>,
|
||||
{
|
||||
|
@ -137,34 +142,38 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn into_child(self) -> Option<Self::Child> {
|
||||
Some(match self {
|
||||
Either::Left(i) => Either::Left(i.into_child()?),
|
||||
Either::Right(i) => Either::Right(i.into_child()?),
|
||||
})
|
||||
}
|
||||
|
||||
fn to_view(&self) -> Self::View {
|
||||
fn into_view_and_child(
|
||||
self,
|
||||
) -> (
|
||||
impl ChooseView<Rndr, Output = Self::View> + 'a,
|
||||
Option<Self::Child>,
|
||||
) {
|
||||
match self {
|
||||
Either::Left(i) => Either::Left(i.to_view()),
|
||||
Either::Right(i) => Either::Right(i.to_view()),
|
||||
Either::Left(i) => {
|
||||
let (view, child) = i.into_view_and_child();
|
||||
(Either::Left(view), child.map(Either::Left))
|
||||
}
|
||||
Either::Right(i) => {
|
||||
let (view, child) = i.into_view_and_child();
|
||||
(Either::Right(view), child.map(Either::Right))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A, B, Rndr> MatchNestedRoutes<'a, Rndr> for (A, B)
|
||||
impl<A, B, Rndr> MatchNestedRoutes<Rndr> for (A, B)
|
||||
where
|
||||
A: MatchNestedRoutes<'a, Rndr>,
|
||||
B: MatchNestedRoutes<'a, Rndr>,
|
||||
A: MatchNestedRoutes<Rndr>,
|
||||
B: MatchNestedRoutes<Rndr>,
|
||||
Rndr: Renderer + 'static,
|
||||
{
|
||||
type Data = (A::Data, B::Data);
|
||||
type Match = Either<A::Match, B::Match>;
|
||||
type Match<'a> = Either<A::Match<'a>, B::Match<'a>> where A: 'a, B: 'a;
|
||||
|
||||
fn match_nested(
|
||||
fn match_nested<'a>(
|
||||
&'a self,
|
||||
path: &'a str,
|
||||
) -> (Option<(RouteMatchId, Self::Match)>, &'a str) {
|
||||
) -> (Option<(RouteMatchId, Self::Match<'a>)>, &'a str) {
|
||||
#[allow(non_snake_case)]
|
||||
let (A, B) = &self;
|
||||
if let (Some((id, matched)), remaining) = A.match_nested(path) {
|
||||
|
@ -209,7 +218,6 @@ macro_rules! tuples {
|
|||
Rndr: Renderer + 'static,
|
||||
$($ty: MatchInterface<'a, Rndr>),*,
|
||||
$($ty::Child: 'a),*,
|
||||
$($ty::View: 'a),*,
|
||||
{
|
||||
type Params = $either<$(
|
||||
<$ty::Params as IntoIterator>::IntoIter,
|
||||
|
@ -241,7 +249,7 @@ macro_rules! tuples {
|
|||
})
|
||||
}
|
||||
|
||||
fn to_view(&self) -> Self::View {
|
||||
fn to_view(&self) -> impl ChooseView<Rndr, Output = Self::View> {
|
||||
match self {
|
||||
$($either::$ty(i) => $either::$ty(i.to_view()),)*
|
||||
}
|
||||
|
@ -282,7 +290,7 @@ macro_rules! tuples {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
tuples!(EitherOf3 => A = 0, B = 1, C = 2);
|
||||
tuples!(EitherOf4 => A = 0, B = 1, C = 2, D = 3);
|
||||
tuples!(EitherOf5 => A = 0, B = 1, C = 2, D = 3, E = 4);
|
||||
|
@ -297,3 +305,4 @@ tuples!(EitherOf13 => A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, I
|
|||
tuples!(EitherOf14 => A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, I = 8, J = 9, K = 10, L = 11, M = 12, N = 13);
|
||||
tuples!(EitherOf15 => A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, I = 8, J = 9, K = 10, L = 11, M = 12, N = 13, O = 14);
|
||||
tuples!(EitherOf16 => A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, I = 8, J = 9, K = 10, L = 11, M = 12, N = 13, O = 14, P = 15);
|
||||
*/
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
MatchInterface, MatchNestedRoutes, PossibleRouteMatch, RouteMatchId,
|
||||
Routes,
|
||||
},
|
||||
Params,
|
||||
ChooseView, Params,
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
use either_of::*;
|
||||
|
@ -84,89 +84,28 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait ChooseView<R>
|
||||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type Output;
|
||||
|
||||
fn choose(self, route_data: RouteData<R>) -> Self::Output;
|
||||
}
|
||||
|
||||
pub struct RouteData<'a, R>
|
||||
pub struct RouteData<R>
|
||||
where
|
||||
R: Renderer,
|
||||
{
|
||||
pub params: ArcMemo<Params>,
|
||||
pub outlet: Box<dyn FnOnce() -> AnyView<R> + 'a>,
|
||||
pub outlet: Box<dyn FnOnce() -> AnyView<R>>,
|
||||
}
|
||||
|
||||
impl<F, View, R> ChooseView<R> for F
|
||||
where
|
||||
F: Fn(RouteData<R>) -> View,
|
||||
R: Renderer,
|
||||
{
|
||||
type Output = View;
|
||||
|
||||
fn choose(self, route_data: RouteData<R>) -> Self::Output {
|
||||
self(route_data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> ChooseView<R> for ()
|
||||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type Output = ();
|
||||
|
||||
fn choose(self, _route_data: RouteData<R>) -> Self::Output {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, FnA, B, FnB, Rndr> ChooseView<Rndr> for Either<FnA, FnB>
|
||||
where
|
||||
FnA: Fn(RouteData<Rndr>) -> A,
|
||||
FnB: Fn(RouteData<Rndr>) -> B,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type Output = Either<A, B>;
|
||||
|
||||
fn choose(self, route_data: RouteData<Rndr>) -> Self::Output {
|
||||
match self {
|
||||
Either::Left(f) => Either::Left(f(route_data)),
|
||||
Either::Right(f) => Either::Right(f(route_data)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Rndr, Loc, FallbackFn, Fallback, Children, View> Render<Rndr>
|
||||
impl<Rndr, Loc, FallbackFn, Fallback, Children> Render<Rndr>
|
||||
for Router<Rndr, Loc, Children, FallbackFn>
|
||||
where
|
||||
Loc: Location,
|
||||
FallbackFn: Fn() -> Fallback + 'static,
|
||||
Fallback: Render<Rndr>,
|
||||
for<'a> Children: MatchNestedRoutes<'a, Rndr> + 'static,
|
||||
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
|
||||
'a,
|
||||
R,
|
||||
>>::View: ChooseView<Rndr, Output = View>,
|
||||
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
|
||||
'a,
|
||||
R,
|
||||
>>::Child: std::fmt::Debug,
|
||||
View: Render<Rndr> + IntoAny<Rndr> + 'static,
|
||||
View::State: 'static,
|
||||
Children: MatchNestedRoutes<Rndr> + 'static,
|
||||
/*View: Render<Rndr> + IntoAny<Rndr> + 'static,
|
||||
View::State: 'static,*/
|
||||
Fallback::State: 'static,
|
||||
Rndr: Renderer + 'static,
|
||||
{
|
||||
type State = RenderEffect<
|
||||
EitherState<
|
||||
NestedRouteState<View::State>,
|
||||
<Fallback as Render<Rndr>>::State,
|
||||
Rndr,
|
||||
>,
|
||||
>;
|
||||
type State =
|
||||
RenderEffect<EitherState<(), <Fallback as Render<Rndr>>::State, Rndr>>;
|
||||
type FallibleState = ();
|
||||
|
||||
fn build(self) -> Self::State {
|
||||
|
@ -191,29 +130,33 @@ where
|
|||
if let Some(new_match) = new_match {
|
||||
match &mut prev.state {
|
||||
Either::Left(prev) => {
|
||||
nested_rebuild(&outer_owner, prev, new_match);
|
||||
//nested_rebuild(&outer_owner, prev, new_match);
|
||||
}
|
||||
Either::Right(_) => {
|
||||
Either::<_, Fallback>::Left(NestedRouteView::new(
|
||||
/*Either::<_, Fallback>::Left(NestedRouteView::new(
|
||||
&outer_owner,
|
||||
new_match,
|
||||
))
|
||||
.rebuild(&mut prev);
|
||||
.rebuild(&mut prev);*/
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Either::<NestedRouteView<View, Rndr>, _>::Right((self
|
||||
/*Either::<NestedRouteView<View, Rndr>, _>::Right((self
|
||||
.fallback)(
|
||||
))
|
||||
.rebuild(&mut prev);
|
||||
.rebuild(&mut prev);*/
|
||||
}
|
||||
prev
|
||||
} else {
|
||||
match new_match {
|
||||
Some(matched) => Either::Left(NestedRouteView::new(
|
||||
Some(matched) =>
|
||||
/*Either::Left(NestedRouteView::new(
|
||||
&outer_owner,
|
||||
matched,
|
||||
)),
|
||||
))*/
|
||||
{
|
||||
Either::Left(())
|
||||
}
|
||||
_ => Either::Right((self.fallback)()),
|
||||
}
|
||||
.build()
|
||||
|
@ -235,14 +178,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn nested_rebuild<'a, NewMatch, R>(
|
||||
/*fn nested_rebuild<NewMatch, R>(
|
||||
outer_owner: &Owner,
|
||||
current: &mut NestedRouteState<
|
||||
<<NewMatch::View as ChooseView<R>>::Output as Render<R>>::State,
|
||||
>,
|
||||
new: NewMatch,
|
||||
) where
|
||||
NewMatch: MatchInterface<'a, R> + 'a,
|
||||
NewMatch: MatchInterface<R>,
|
||||
NewMatch::View: ChooseView<R>,
|
||||
<NewMatch::View as ChooseView<R>>::Output: Render<R> + IntoAny<R> + 'static,
|
||||
NewMatch::Child: std::fmt::Debug,
|
||||
|
@ -270,7 +213,7 @@ fn nested_rebuild<'a, NewMatch, R>(
|
|||
|
||||
// update params, in case they're different
|
||||
// TODO
|
||||
}
|
||||
}*/
|
||||
|
||||
pub struct NestedRouteView<View, R>
|
||||
where
|
||||
|
@ -288,11 +231,12 @@ impl<View, R> NestedRouteView<View, R>
|
|||
where
|
||||
R: Renderer + 'static,
|
||||
{
|
||||
pub fn new<'a, Matcher>(outer_owner: &Owner, route_match: Matcher) -> Self
|
||||
pub fn new<Matcher>(outer_owner: &Owner, route_match: Matcher) -> Self
|
||||
where
|
||||
Matcher: MatchInterface<'a, R>,
|
||||
Matcher::View: ChooseView<R, Output = View>,
|
||||
Matcher::Child: std::fmt::Debug,
|
||||
Matcher: for<'a> MatchInterface<'a, R, View = View> + 'static,
|
||||
for<'a> <Matcher as MatchInterface<'a, R>>::View:
|
||||
ChooseView<R, Output = View>,
|
||||
for<'a> <Matcher as MatchInterface<'a, R>>::Child: std::fmt::Debug,
|
||||
View: IntoAny<R> + 'static,
|
||||
{
|
||||
let params = ArcRwSignal::new(
|
||||
|
@ -304,14 +248,13 @@ where
|
|||
);
|
||||
let matched = ArcRwSignal::new(route_match.as_matched().to_string());
|
||||
let id = route_match.as_id();
|
||||
let view = route_match.to_view();
|
||||
let (view, child) = route_match.into_view_and_child();
|
||||
let route_data = RouteData {
|
||||
params: {
|
||||
let params = params.clone();
|
||||
ArcMemo::new(move |_| params.get())
|
||||
},
|
||||
outlet: Box::new({
|
||||
let child = route_match.into_child();
|
||||
move || {
|
||||
child
|
||||
.map(|child| {
|
||||
|
@ -323,7 +266,6 @@ where
|
|||
}),
|
||||
outlet: Box::new(|| ().into_any())
|
||||
};*/
|
||||
let view = child.to_view();
|
||||
format!("{child:?}")
|
||||
})
|
||||
.into_any()
|
||||
|
@ -413,11 +355,11 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
trait RouteView<'a, R>: MatchInterface<'a, R>
|
||||
trait RouteView<R>: for<'a> MatchInterface<'a, R>
|
||||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type RouteViewChild: RouteView<'a, R>;
|
||||
type RouteViewChild: RouteView<R>;
|
||||
type RouteView: Render<R>;
|
||||
|
||||
fn into_child(self) -> Option<Self::RouteViewChild>;
|
||||
|
@ -429,14 +371,14 @@ where
|
|||
Loc: Location,
|
||||
FallbackFn: Fn() -> Fallback + 'static,
|
||||
Fallback: RenderHtml<Rndr>,
|
||||
for<'a> Children: MatchNestedRoutes<'a, Rndr> + 'static,
|
||||
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
|
||||
Children: MatchNestedRoutes<Rndr> + 'static,
|
||||
for<'a> <<Children as MatchNestedRoutes<Rndr>>::Match<'a> as MatchInterface<
|
||||
'a,
|
||||
R,
|
||||
Rndr,
|
||||
>>::View: ChooseView<Rndr, Output = View>,
|
||||
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
|
||||
for<'a> <<Children as MatchNestedRoutes<Rndr>>::Match<'a> as MatchInterface<
|
||||
'a,
|
||||
R,
|
||||
Rndr,
|
||||
>>::Child: std::fmt::Debug,
|
||||
View: Render<Rndr> + IntoAny<Rndr> + 'static,
|
||||
View::State: 'static,
|
||||
|
@ -465,10 +407,10 @@ where
|
|||
Loc: Location,
|
||||
FallbackFn: Fn() -> Fallback,
|
||||
Fallback: Render<Rndr>,
|
||||
for<'a> Children: MatchNestedRoutes<'a, Rndr>,
|
||||
for<'a> <<Children as MatchNestedRoutes<'a, Rndr>>::Match as MatchInterface<
|
||||
Children: MatchNestedRoutes<Rndr>,
|
||||
for<'a> <<Children as MatchNestedRoutes<Rndr>>::Match<'a> as MatchInterface<
|
||||
'a,
|
||||
R,
|
||||
Rndr,
|
||||
>>::View: ChooseView<Rndr, Output = View>,
|
||||
Rndr: Renderer,
|
||||
Router<Rndr, Loc, Children, FallbackFn>: RenderHtml<Rndr>,
|
||||
|
@ -503,6 +445,7 @@ macro_rules! tuples {
|
|||
where
|
||||
Rndr: Renderer,
|
||||
$([<Fn $ty>]: Fn(RouteData<Rndr>) -> $ty,)*
|
||||
$($ty: Render<Rndr>,)*
|
||||
{
|
||||
type Output = $either<$($ty,)*>;
|
||||
|
||||
|
|
Loading…
Reference in a new issue