mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
ported A
This commit is contained in:
parent
5405dcd09d
commit
0a8b516182
1 changed files with 48 additions and 60 deletions
|
@ -39,44 +39,36 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Properties that can be passed to the [A] component, which is an HTML
|
||||
/// [`a`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
|
||||
/// progressively enhanced to use client-side routing.
|
||||
#[derive(TypedBuilder)]
|
||||
pub struct AProps<H>
|
||||
where
|
||||
H: ToHref + 'static,
|
||||
{
|
||||
/// Used to calculate the link's `href` attribute. Will be resolved relative
|
||||
/// to the current route.
|
||||
pub href: H,
|
||||
/// If `true`, the link is marked active when the location matches exactly;
|
||||
/// if false, link is marked active if the current route starts with it.
|
||||
#[builder(default)]
|
||||
pub exact: bool,
|
||||
/// An object of any type that will be pushed to router state
|
||||
#[builder(default, setter(strip_option))]
|
||||
pub state: Option<State>,
|
||||
/// If `true`, the link will not add to the browser's history (so, pressing `Back`
|
||||
/// will skip this page.)
|
||||
#[builder(default)]
|
||||
pub replace: bool,
|
||||
/// Sets the `class` attribute on the underlying `<a>` tag, making it easier to style.
|
||||
#[builder(default, setter(strip_option, into))]
|
||||
pub class: Option<MaybeSignal<String>>,
|
||||
/// The nodes or elements to be shown inside the link.
|
||||
pub children: Box<dyn Fn(Scope) -> Fragment>
|
||||
}
|
||||
|
||||
/// An HTML [`a`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
|
||||
/// progressively enhanced to use client-side routing.
|
||||
#[allow(non_snake_case)]
|
||||
pub fn A<H>(cx: Scope, props: AProps<H>) -> impl IntoView
|
||||
#[component]
|
||||
pub fn A<H>(
|
||||
cx: Scope,
|
||||
/// Used to calculate the link's `href` attribute. Will be resolved relative
|
||||
/// to the current route.
|
||||
href: H,
|
||||
/// If `true`, the link is marked active when the location matches exactly;
|
||||
/// if false, link is marked active if the current route starts with it.
|
||||
#[prop(optional)]
|
||||
exact: bool,
|
||||
/// An object of any type that will be pushed to router state
|
||||
#[prop(optional)]
|
||||
state: Option<State>,
|
||||
/// If `true`, the link will not add to the browser's history (so, pressing `Back`
|
||||
/// will skip this page.)
|
||||
#[prop(optional)]
|
||||
replace: bool,
|
||||
/// Sets the `class` attribute on the underlying `<a>` tag, making it easier to style.
|
||||
#[prop(optional, into)]
|
||||
class: Option<MaybeSignal<String>>,
|
||||
/// The nodes or elements to be shown inside the link.
|
||||
children: Box<dyn Fn(Scope) -> Fragment>,
|
||||
) -> impl IntoView
|
||||
where
|
||||
H: ToHref + 'static,
|
||||
{
|
||||
let location = use_location(cx);
|
||||
let href = use_resolved_path(cx, move || props.href.to_href()());
|
||||
let href = use_resolved_path(cx, move || href.to_href()());
|
||||
let is_active = create_memo(cx, move |_| match href.get() {
|
||||
None => false,
|
||||
|
||||
|
@ -87,7 +79,7 @@ where
|
|||
.unwrap_or_default()
|
||||
.to_lowercase();
|
||||
let loc = location.pathname.get().to_lowercase();
|
||||
if props.exact {
|
||||
if exact {
|
||||
loc == path
|
||||
} else {
|
||||
loc.starts_with(&path)
|
||||
|
@ -95,33 +87,29 @@ where
|
|||
}
|
||||
});
|
||||
|
||||
let class = props.class;
|
||||
|
||||
Component::new("A", move |cx| {
|
||||
cfg_if! {
|
||||
if #[cfg(any(feature = "csr", feature = "hydrate"))] {
|
||||
view! { cx,
|
||||
<a
|
||||
href=move || href.get().unwrap_or_default()
|
||||
prop:state={props.state.map(|s| s.to_js_value())}
|
||||
prop:replace={props.replace}
|
||||
aria-current=move || if is_active.get() { Some("page") } else { None }
|
||||
class=move || class.as_ref().map(|class| class.get())
|
||||
>
|
||||
{move || (props.children)(cx)}
|
||||
</a>
|
||||
}
|
||||
} else {
|
||||
view! { cx,
|
||||
<a
|
||||
href=move || href().unwrap_or_default()
|
||||
aria-current=move || if is_active() { Some("page") } else { None }
|
||||
class=move || class.as_ref().map(|class| class.get())
|
||||
>
|
||||
{move || (props.children)(cx)}
|
||||
</a>
|
||||
}
|
||||
cfg_if! {
|
||||
if #[cfg(any(feature = "csr", feature = "hydrate"))] {
|
||||
view! { cx,
|
||||
<a
|
||||
href=move || href.get().unwrap_or_default()
|
||||
prop:state={state.map(|s| s.to_js_value())}
|
||||
prop:replace={replace}
|
||||
aria-current=move || if is_active.get() { Some("page") } else { None }
|
||||
class=move || class.as_ref().map(|class| class.get())
|
||||
>
|
||||
{children(cx)}
|
||||
</a>
|
||||
}
|
||||
} else {
|
||||
view! { cx,
|
||||
<a
|
||||
href=move || href().unwrap_or_default()
|
||||
aria-current=move || if is_active() { Some("page") } else { None }
|
||||
class=move || class.as_ref().map(|class| class.get())
|
||||
>
|
||||
{move || (props.children)(cx)}
|
||||
</a>
|
||||
}
|
||||
}
|
||||
}).into_view(cx)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue