use crate::router::context::use_router;
use silex_core::traits::Get;
use silex_dom::View;
use silex_dom::attribute::{AttributeBuilder, GlobalAttributes};
use silex_dom::element::TypedElement;
use silex_html::A as TagA;
use silex_html::a;
pub struct Link {
href: String,
inner: TypedElement<TagA>,
}
use crate::router::ToRoute;
#[allow(non_snake_case)]
pub fn Link<T: ToRoute, V: View>(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: &str) -> Self {
Self {
inner: self.inner.class(name),
..self
}
}
pub fn style(self, css: &str) -> Self {
Self {
inner: self.inner.style(css),
..self
}
}
pub fn active_class(self, name: &str) -> Self {
if let Some(router) = use_router() {
let path_signal = router.path;
let href = self.href.clone();
let class_name = name.to_string();
let is_active = move || {
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) {
let href = self.href.clone();
let router_ctx = use_router();
if let Some(ctx) = &router_ctx {
if !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);
}
}