diff --git a/packages/router-macro/src/lib.rs b/packages/router-macro/src/lib.rs index 5a832f02b..e1dae23ad 100644 --- a/packages/router-macro/src/lib.rs +++ b/packages/router-macro/src/lib.rs @@ -32,8 +32,26 @@ pub fn routable(input: TokenStream) -> TokenStream { let parse_impl = route_enum.parse_impl(); let display_impl = route_enum.impl_display(); let routable_impl = route_enum.routable_impl(); + let name = &route_enum.name; + let vis = &route_enum.vis; quote! { + #vis fn Outlet(cx: dioxus::prelude::Scope) -> dioxus::prelude::Element { + dioxus_router::prelude::GenericOutlet::<#name>(cx) + } + + #vis fn Router(cx: dioxus::prelude::Scope>) -> dioxus::prelude::Element { + dioxus_router::prelude::GenericRouter(cx) + } + + #vis fn Link<'a>(cx: dioxus::prelude::Scope<'a, dioxus_router::prelude::GenericLinkProps<'a, #name>>) -> dioxus::prelude::Element<'a> { + dioxus_router::prelude::GenericLink(cx) + } + + #vis fn use_router(cx: &dioxus::prelude::ScopeState) -> &dioxus_router::prelude::GenericRouterContext { + dioxus_router::prelude::use_generic_router::(cx) + } + #route_enum #error_type @@ -48,6 +66,7 @@ pub fn routable(input: TokenStream) -> TokenStream { } struct RouteEnum { + vis: syn::Visibility, name: Ident, routes: Vec, nests: Vec, @@ -58,6 +77,7 @@ struct RouteEnum { impl RouteEnum { fn parse(data: syn::ItemEnum) -> syn::Result { let name = &data.ident; + let vis = &data.vis; let mut site_map = Vec::new(); let mut site_map_stack: Vec> = Vec::new(); @@ -201,6 +221,7 @@ impl RouteEnum { } let myself = Self { + vis: vis.clone(), name: name.clone(), routes, nests, diff --git a/packages/router/examples/simple_routes.rs b/packages/router/examples/simple_routes.rs index 4ab83cef0..0c9144cb0 100644 --- a/packages/router/examples/simple_routes.rs +++ b/packages/router/examples/simple_routes.rs @@ -15,7 +15,7 @@ fn main() { fn root(cx: Scope) -> Element { render! { - Router:: { + Router { config: RouterConfiguration { history: { #[cfg(not(target_arch = "wasm32"))] @@ -39,7 +39,7 @@ fn UserFrame(cx: Scope, user_id: usize) -> Element { div { background_color: "rgba(0,0,0,50%)", "children:" - Outlet:: {} + Outlet {} } } } @@ -50,12 +50,12 @@ fn Route1(cx: Scope, user_id: usize, dynamic: usize, extra: String) -> Element { pre { "Route1{{\n\tuser_id:{user_id},\n\tdynamic:{dynamic},\n\textra:{extra}\n}}" } - Link:: { + Link { target: Route::Route1 { user_id: *user_id, dynamic: *dynamic, extra: extra.clone() + "." }, "Route1 with extra+\".\"" } p { "Footer" } - Link:: { + Link { target: Route::Route3 { dynamic: String::new() }, "Home" } @@ -70,7 +70,7 @@ fn Route2(cx: Scope, user_id: usize) -> Element { } (0..*user_id).map(|i| rsx!{ p { "{i}" } }), p { "Footer" } - Link:: { + Link { target: Route::Route3 { dynamic: String::new() }, "Home" } @@ -97,7 +97,7 @@ fn Route3(cx: Scope, dynamic: String) -> Element { value: "{current_route.read()}" } "dynamic: {dynamic}" - Link:: { + Link { target: Route::Route2 { user_id: 8888 }, "hello world link" } @@ -107,7 +107,7 @@ fn Route3(cx: Scope, dynamic: String) -> Element { if let Ok(route) = parsed { if route != router_route { render! { - Link:: { + Link { target: route.clone(), "{route}" } diff --git a/packages/router/src/components/default_errors.rs b/packages/router/src/components/default_errors.rs index 979e448fc..dde582b42 100644 --- a/packages/router/src/components/default_errors.rs +++ b/packages/router/src/components/default_errors.rs @@ -1,4 +1,6 @@ -use crate::{components::Link, hooks::use_route, navigation::NavigationTarget, routable::Routable}; +use crate::{ + components::GenericLink, hooks::use_route, navigation::NavigationTarget, routable::Routable, +}; use dioxus::prelude::*; #[allow(non_snake_case)] @@ -35,7 +37,7 @@ pub fn FailureNamedNavigation(cx: Scope) -> Element { "We are sorry for the inconvenience. The link below may help to fix the problem, but " "there is no guarantee." } - Link:: { + GenericLink:: { target: NavigationTarget::External("https://google.com".into()), "Click here to try to fix the failure." } @@ -55,7 +57,7 @@ pub fn FailureRedirectionLimit(cx: Scope) -> Element { "We are sorry for the inconvenience. The link below may help to fix the problem, but " "there is no guarantee." } - Link:: { + GenericLink:: { target: NavigationTarget::External("https://google.com".into()), "Click here to try to fix the failure." } diff --git a/packages/router/src/components/link.rs b/packages/router/src/components/link.rs index fb570855d..0a639ca82 100644 --- a/packages/router/src/components/link.rs +++ b/packages/router/src/components/link.rs @@ -9,7 +9,7 @@ use crate::utils::use_router_internal::use_router_internal; /// The properties for a [`Link`]. #[derive(Props)] -pub struct LinkProps<'a, R: Routable> { +pub struct GenericLinkProps<'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. @@ -45,7 +45,7 @@ pub struct LinkProps<'a, R: Routable> { pub target: NavigationTarget, } -impl Debug for LinkProps<'_, R> { +impl Debug for GenericLinkProps<'_, R> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("LinkProps") .field("active_class", &self.active_class) @@ -125,8 +125,8 @@ impl Debug for LinkProps<'_, R> { /// # ); /// ``` #[allow(non_snake_case)] -pub fn Link<'a, R: Routable + Clone>(cx: Scope<'a, LinkProps<'a, R>>) -> Element { - let LinkProps { +pub fn GenericLink<'a, R: Routable + Clone>(cx: Scope<'a, GenericLinkProps<'a, R>>) -> Element { + let GenericLinkProps { active_class, children, class, diff --git a/packages/router/src/components/outlet.rs b/packages/router/src/components/outlet.rs index 73b10a694..61cf43c22 100644 --- a/packages/router/src/components/outlet.rs +++ b/packages/router/src/components/outlet.rs @@ -44,6 +44,6 @@ use dioxus::prelude::*; /// # let _ = vdom.rebuild(); /// # assert_eq!(dioxus_ssr::render(&vdom), "

App

Content

"); /// ``` -pub fn Outlet(cx: Scope) -> Element { +pub fn GenericOutlet(cx: Scope) -> Element { OutletContext::render::(cx) } diff --git a/packages/router/src/components/router.rs b/packages/router/src/components/router.rs index f6dceb8c3..ecbf7c9fb 100644 --- a/packages/router/src/components/router.rs +++ b/packages/router/src/components/router.rs @@ -3,7 +3,7 @@ use log::error; use std::{cell::RefCell, str::FromStr}; use crate::{ - prelude::{Outlet, RouterContext}, + prelude::{GenericOutlet, GenericRouterContext}, routable::Routable, router_cfg::RouterConfiguration, }; @@ -34,7 +34,7 @@ impl From> for RouterCfg { /// The props for [`Router`]. #[derive(Props)] -pub struct RouterProps +pub struct GenericRouterProps where ::Err: std::fmt::Display, { @@ -44,7 +44,7 @@ where config: RouterCfg, } -impl PartialEq for RouterProps +impl PartialEq for GenericRouterProps where ::Err: std::fmt::Display, { @@ -55,19 +55,19 @@ where } /// A component that renders the current route. -pub fn Router(cx: Scope>) -> Element +pub fn GenericRouter(cx: Scope>) -> Element where ::Err: std::fmt::Display, { use_context_provider(cx, || { #[allow(unreachable_code, unused_variables)] - if let Some(outer) = cx.consume_context::>() { + if let Some(outer) = cx.consume_context::>() { let msg = "Router components should not be nested within each other"; error!("{msg}, inner will be inactive and transparent"); #[cfg(debug_assertions)] panic!("{}", msg); } - let router = RouterContext::new( + let router = GenericRouterContext::new( cx.props.config.config.take().unwrap_or_default(), cx.schedule_update_any(), ); @@ -82,6 +82,6 @@ where }); render! { - Outlet:: {} + GenericOutlet:: {} } } diff --git a/packages/router/src/contexts/router.rs b/packages/router/src/contexts/router.rs index f40f88418..fa0692e9f 100644 --- a/packages/router/src/contexts/router.rs +++ b/packages/router/src/contexts/router.rs @@ -19,7 +19,7 @@ pub enum NavigationFailure { } /// A function the router will call after every routing update. -pub type RoutingCallback = Arc) -> Option>>; +pub type RoutingCallback = Arc) -> Option>>; struct MutableRouterState where @@ -43,7 +43,7 @@ where } /// A collection of router data that manages all routing functionality. -pub struct RouterContext +pub struct GenericRouterContext where R: Routable, { @@ -58,7 +58,7 @@ where failure_redirection_limit: fn(Scope) -> Element, } -impl Clone for RouterContext { +impl Clone for GenericRouterContext { fn clone(&self) -> Self { Self { state: self.state.clone(), @@ -72,7 +72,7 @@ impl Clone for RouterContext { } } -impl RouterContext +impl GenericRouterContext where R: Routable, { diff --git a/packages/router/src/hooks/use_router.rs b/packages/router/src/hooks/use_router.rs index 4e87054b2..d0dba00f4 100644 --- a/packages/router/src/hooks/use_router.rs +++ b/packages/router/src/hooks/use_router.rs @@ -1,11 +1,12 @@ use dioxus::prelude::ScopeState; use crate::{ - prelude::RouterContext, routable::Routable, utils::use_router_internal::use_router_internal, + prelude::GenericRouterContext, routable::Routable, + utils::use_router_internal::use_router_internal, }; /// A hook that provides access to information about the router -pub fn use_router(cx: &ScopeState) -> &RouterContext { +pub fn use_generic_router(cx: &ScopeState) -> &GenericRouterContext { use_router_internal(cx) .as_ref() .expect("use_route must have access to a router") diff --git a/packages/router/src/utils/use_router_internal.rs b/packages/router/src/utils/use_router_internal.rs index ab1a8e37c..ee84a452e 100644 --- a/packages/router/src/utils/use_router_internal.rs +++ b/packages/router/src/utils/use_router_internal.rs @@ -1,6 +1,6 @@ use dioxus::prelude::{ScopeId, ScopeState}; -use crate::{contexts::router::RouterContext, routable::Routable}; +use crate::{contexts::router::GenericRouterContext, routable::Routable}; /// A private hook to subscribe to the router. /// @@ -12,9 +12,11 @@ use crate::{contexts::router::RouterContext, routable::Routable}; /// - Otherwise [`Some`]. /// /// [`use_router`]: crate::hooks::use_router -pub(crate) fn use_router_internal(cx: &ScopeState) -> &Option> { +pub(crate) fn use_router_internal( + cx: &ScopeState, +) -> &Option> { let inner = cx.use_hook(|| { - let router = cx.consume_context::>()?; + let router = cx.consume_context::>()?; let id = cx.scope_id(); router.subscribe(id); @@ -25,7 +27,7 @@ pub(crate) fn use_router_internal(cx: &ScopeState) -> &Option { - router: RouterContext, + router: GenericRouterContext, id: ScopeId, }