use yew::prelude::*;
use super::Container;
use crate::util::Dimension;
use crate::icons::BI;
pub struct NavDropdownItem { }
#[derive(Properties, Clone, PartialEq)]
pub struct NavDropdownItemProps {
#[prop_or_default]
pub text: AttrValue,
#[prop_or_default]
pub url: Option<AttrValue>,
#[prop_or_default]
pub onclick: Callback<MouseEvent>,
#[prop_or_default]
pub icon: Option<&'static BI>,
}
impl Component for NavDropdownItem {
type Message = ();
type Properties = NavDropdownItemProps;
fn create(_ctx: &Context<Self>) -> Self {
Self {}
}
fn view(&self, ctx: &Context<Self>) -> Html {
let props = ctx.props();
html! {
<li>
<a
class="dropdown-item"
href={props.url.clone()}
onclick={props.onclick.clone()}
>
if let Some(icon) = props.icon {
{icon}{" "} }
{props.text.clone()}
</a>
</li>
}
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct NavDropdown { }
#[derive(Properties, Clone, PartialEq)]
pub struct NavDropdownProps {
#[prop_or_default]
pub children: Children,
#[prop_or_default]
pub id: AttrValue,
#[prop_or_default]
pub expanded: bool,
#[prop_or_default]
pub text: AttrValue,
#[prop_or_default]
pub active: bool,
#[prop_or_default]
pub icon: Option<&'static BI>,
}
impl Component for NavDropdown {
type Message = ();
type Properties = NavDropdownProps;
fn create(_ctx: &Context<Self>) -> Self {
Self { }
}
fn view(&self, ctx: &Context<Self>) -> Html {
let props = ctx.props();
let expanded = String::from(match props.expanded {
true => "true",
false => "false"
});
let mut dropdown_toggle_classes = Classes::new();
dropdown_toggle_classes.push(String::from("nav-link"));
dropdown_toggle_classes.push(String::from("dropdown-toggle"));
if props.active {
dropdown_toggle_classes.push(String::from("active"));
}
html! {
<li class="nav-item dropdown">
<a class={dropdown_toggle_classes} href="#" id={props.id.clone()} role="button" data-bs-toggle="dropdown" aria-expanded={expanded}>
if let Some(icon) = props.icon {
{icon}{" "}
}
{props.text.clone()}
</a>
<ul class="dropdown-menu" aria-labelledby={props.id.clone()}>
{ for props.children.iter() }
</ul>
</li>
}
}
}
pub struct NavItem { }
#[derive(Properties, Clone, PartialEq)]
pub struct NavItemProperties {
#[prop_or_default]
pub url: Option<AttrValue>,
#[prop_or_default]
pub active: bool,
#[prop_or_default]
pub disabled: bool,
#[prop_or_default]
pub text: AttrValue,
#[prop_or_default]
pub id: AttrValue,
#[prop_or_default]
pub children: Children,
#[prop_or_default]
pub onclick: Callback<MouseEvent>,
#[prop_or_default]
pub icon: Option<&'static BI>,
}
impl Component for NavItem {
type Message = ();
type Properties = NavItemProperties;
fn create(_ctx: &Context<Self>) -> Self {
Self {}
}
fn view(&self, ctx: &Context<Self>) -> Html {
let props = ctx.props();
match &props.children.is_empty() {
true => {
let mut classes = Classes::new();
classes.push(String::from("nav-link"));
if props.active {
classes.push(String::from("active"));
}
if props.disabled {
classes.push(String::from("disabled"));
}
match props.disabled {
true => {
html! {
<li class="nav-item">
<a
class={classes}
tabindex="-1"
aria-disabled="true"
href={props.url.clone()}
onclick={props.onclick.clone()}
>
if let Some(icon) = props.icon {
{icon}{" "}
}
{props.text.clone()}
</a>
</li>
}
},
false => {
html! {
<li class="nav-item">
<a
class={classes}
href={props.url.clone()}
onclick={props.onclick.clone()}
>
if let Some(icon) = props.icon {
{icon}{" "}
}
{props.text.clone()}
</a>
</li>
}
}
}
},
false => {
html! {
<NavDropdown text={props.text.clone()} id={props.id.clone()} active={props.active}>
{ for props.children.iter() }
</NavDropdown>
}
}
}
}
}
#[derive(Clone, PartialEq, Eq)]
pub enum BrandType {
BrandSimple {
text: AttrValue, url: Option<AttrValue> },
BrandIcon { icon: BI, text: AttrValue, url: Option<AttrValue> },
BrandImage {
image_url: AttrValue,
alt: AttrValue,
dimension: Option<Dimension>
},
BrandCombined {
text: AttrValue,
url: Option<AttrValue>,
image_url: AttrValue,
alt: AttrValue,
dimension: Option<Dimension>
}
}
pub struct NavBar { }
#[derive(Properties, Clone, PartialEq)]
pub struct NavBarProps {
#[prop_or_default]
pub children: Children,
#[prop_or_default]
pub class: AttrValue,
#[prop_or_default]
pub nav_id: AttrValue,
#[prop_or_default]
pub expanded: bool,
#[prop_or_default]
pub brand: Option<BrandType>,
#[prop_or_default]
pub brand_callback: Callback<MouseEvent>
}
impl Component for NavBar {
type Message = ();
type Properties = NavBarProps;
fn create(_ctx: &Context<Self>) -> Self {
Self {}
}
fn view(&self, ctx: &Context<Self>) -> Html {
let props = ctx.props();
let expanded = String::from(match &props.expanded {
true => {
"true"
},
false => {
"false"
}
});
let mut classes = Classes::new();
classes.push("navbar");
classes.push(props.class.to_string());
let brand = match &props.brand {
None => html!{},
Some(b) => {
match b {
BrandType::BrandSimple{text, url} => {
let url = match url {
Some(u) => u.clone(),
None => AttrValue::from("#")
};
html!{
<a class="navbar-brand" href={url} onclick={props.brand_callback.clone()}>
{text.clone()}
</a>
}
},
BrandType::BrandIcon { text, icon, url } => {
let url = match url {
Some(u) => u.clone(),
None => AttrValue::from("#")
};
html! {
<a class="navbar-brand" href={url} onclick={props.brand_callback.clone()}>
{icon}
{text.clone()}
</a>
}
}
BrandType::BrandImage { image_url, alt, dimension } => {
match dimension {
None => {
html! {
<a class="navbar-brand" href={"#"} onclick={props.brand_callback.clone()}>
<img src={image_url.clone()} alt={alt.clone()} class="d-inline-block align-text-top" />
</a>
}
}
Some(Dimension{width, height}) => {
html! {
<a class="navbar-brand" href={"#"} onclick={props.brand_callback.clone()}>
<img src={image_url.clone()} alt={alt.clone()} width={width.clone()} height={height.clone()} class="d-inline-block align-text-top" />
</a>
}
}
}
}
BrandType::BrandCombined { text, url, image_url, alt, dimension } => {
let url = match url {
Some(u) => u.clone(),
None => AttrValue::from("#")
};
match dimension {
None => {
html! {
<a class="navbar-brand" href={url} onclick={props.brand_callback.clone()}>
<img src={image_url.clone()} alt={alt.clone()} class="d-inline-block align-text-top" />
{text.clone()}
</a>
}
},
Some(Dimension{width, height}) => {
html! {
<a class="navbar-brand" href={url} onclick={props.brand_callback.clone()}>
<img src={image_url.clone()} alt={alt.clone()} width={width.clone()} height={height.clone()} class="d-inline-block align-text-top" />
{text.clone()}
</a>
}
}
}
}
}
}
};
html! {
<nav class={classes}>
<Container fluid=true>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target={format!("#{}", props.nav_id.clone())} aria-controls={props.nav_id.clone()} aria-expanded={expanded} aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
{brand}
<div class="collapse navbar-collapse" id={props.nav_id.clone()}>
<ul class="navbar-nav">
{ for props.children.clone() }
</ul>
</div>
</Container>
</nav>
}
}
}