Intigrate macro with router hooks and components

This commit is contained in:
Evan Almloff committed 2023-05-22 16:42:32 -05:00
1 parent ef6551a6cd
commit e4b8fbfafe
37 files changed
+1442 -3009

No files matched your search

+20 -26
View File
@@ -1,14 +1,15 @@
use std::fmt::Debug;
use dioxus::prelude::*;
use dioxus_router_core::{navigation::NavigationTarget, RouterMessage};
use log::error;
use crate::navigation::NavigationTarget;
use crate::routable::Routable;
use crate::utils::use_router_internal::use_router_internal;
/// The properties for a [`Link`].
#[derive(Props)]
pub struct LinkProps<'a> {
pub struct LinkProps<'a, R: Routable> {
/// A class to apply to the generate HTML anchor tag if the `target` route is active.
pub active_class: Option<&'a str>,
/// The children to render within the generated HTML anchor tag.
@@ -18,11 +19,6 @@ pub struct LinkProps<'a> {
/// If `active_class` is [`Some`] and the `target` route is active, `active_class` will be
/// appended at the end of `class`.
pub class: Option<&'a str>,
/// Require the __exact__ `target` to be active, for the [`Link`] to be active.
///
/// See [`RouterState::is_at`](dioxus_router_core::RouterState::is_at) for more details.
#[props(default)]
pub exact: bool,
/// The id attribute for the generated HTML anchor tag.
pub id: Option<&'a str>,
/// When [`true`], the `target` route will be opened in a new tab.
@@ -46,22 +42,21 @@ pub struct LinkProps<'a> {
pub rel: Option<&'a str>,
/// The navigation target. Roughly equivalent to the href attribute of an HTML anchor tag.
#[props(into)]
pub target: NavigationTarget,
pub target: NavigationTarget<R>,
}
impl Debug for LinkProps<'_> {
impl<R: Routable> Debug for LinkProps<'_, R> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LinkProps")
.field("active_class", &self.active_class)
.field("children", &self.children)
.field("class", &self.class)
.field("exact", &self.exact)
.field("id", &self.id)
.field("new_tab", &self.new_tab)
.field("onclick", &self.onclick.as_ref().map(|_| "onclick is set"))
.field("onclick_only", &self.onclick_only)
.field("rel", &self.rel)
.field("target", &self.target)
.field("target", &self.target.to_string())
.finish()
}
}
@@ -130,12 +125,11 @@ impl Debug for LinkProps<'_> {
/// # );
/// ```
#[allow(non_snake_case)]
pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
pub fn Link<'a, R: Routable + Clone>(cx: Scope<'a, LinkProps<'a, R>>) -> Element {
let LinkProps {
active_class,
children,
class,
exact,
id,
new_tab,
onclick,
@@ -145,7 +139,7 @@ pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
} = cx.props;
// hook up to router
let router = match use_router_internal(cx) {
let router = match use_router_internal::<R>(cx) {
Some(r) => r,
#[allow(unreachable_code)]
None => {
@@ -156,19 +150,19 @@ pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
return None;
}
};
let state = loop {
if let Some(state) = router.state.try_read() {
break state;
}
};
let sender = router.sender.clone();
let href = state.href(target);
let current_route = router.current();
let href = current_route.to_string();
let ac = active_class
.and_then(|active_class| {
state
.is_at(target, *exact)
.then(|| format!(" {active_class}"))
.and_then(|active_class| match target {
NavigationTarget::Internal(target) => {
if href == target.to_string() {
Some(format!(" {active_class}"))
} else {
None
}
}
_ => None,
})
.unwrap_or_default();
@@ -186,7 +180,7 @@ pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
let do_default = onclick.is_none() || !onclick_only;
let action = move |event| {
if do_default && is_router_nav {
let _ = sender.unbounded_send(RouterMessage::Push(target.clone()));
router.push(target.clone());
}
if let Some(handler) = onclick {