use crate::router::context::use_router;
use silex_core::traits::RxGet;
use silex_dom::attribute::{AttributeBuilder, GlobalAttributes};
use silex_dom::element::TypedElement;
use silex_dom::prelude::{GlobalEventAttributes, View};
use silex_html::A as TagA;
use silex_html::a;
#[derive(Clone)]
pub struct Link {
href: String,
inner: TypedElement<TagA>,
}
use crate::router::ToRoute;
#[allow(non_snake_case)]
pub fn Link<T: ToRoute, V: View + 'static>(to: T, child: V) -> Link {
let href = to.to_route();
let element = a(child).attr("href", &href);
Link {
href,
inner: element,
}
}
impl Link {
pub fn class(self, name: impl silex_dom::attribute::IntoStorable) -> Self {
Self {
inner: self.inner.class(name),
..self
}
}
pub fn style(self, css: impl silex_dom::attribute::IntoStorable) -> Self {
Self {
inner: self.inner.style(css),
..self
}
}
pub fn active_class(self, name: impl Into<String>) -> Self {
if let Some(router) = use_router() {
let path_signal = router.path;
let href = self.href.clone();
let class_name = name.into();
let is_active = silex_core::rx! {
let current_path = path_signal.get();
if href == "/" {
current_path == "/"
} else if current_path == href {
true
} else if current_path.starts_with(&href) {
if href.ends_with('/') {
true
} else {
current_path.chars().nth(href.len()) == Some('/')
}
} else {
false
}
};
Self {
inner: self.inner.class((class_name, is_active)),
..self
}
} else {
self
}
}
}
impl View for Link {
fn mount(self, parent: &web_sys::Node, attrs: Vec<silex_dom::attribute::PendingAttribute>) {
let href = self.href.clone();
let router_ctx = use_router();
if let Some(ctx) = &router_ctx
&& !ctx.base_path.is_empty()
&& ctx.base_path != "/"
&& href.starts_with('/')
{
let base = ctx.base_path.trim_end_matches('/');
let full_href = format!("{}{}", base, href);
let _ = self.inner.dom_element.set_attribute("href", &full_href);
}
let element = self.inner.on_click(move |e: web_sys::MouseEvent| {
e.prevent_default();
if let Some(ctx) = &router_ctx {
ctx.navigator.push(href.as_str());
} else {
if let Some(ctx) = use_router() {
ctx.navigator.push(href.as_str());
} else {
let window = web_sys::window().unwrap();
let _ = window.location().set_href(&href);
}
}
});
element.mount(parent, attrs);
}
fn mount_ref(
&self,
parent: &web_sys::Node,
attrs: Vec<silex_dom::attribute::PendingAttribute>,
) {
self.clone().mount(parent, attrs);
}
}