95 lines
3.1 KiB
Rust
95 lines
3.1 KiB
Rust
use pagetop::prelude::*;
|
|
|
|
use crate::prelude::*;
|
|
|
|
/// Elementos que puede contener una barra de navegación [`Navbar`](crate::theme::Navbar).
|
|
///
|
|
/// Cada variante determina qué se renderiza y cómo. Estos elementos se colocan **dentro del
|
|
/// contenido** de la barra (la parte colapsable, el *offcanvas* o el bloque simple), por lo que son
|
|
/// independientes de la marca o del botón que ya pueda definir el propio [`navbar::Layout`].
|
|
#[derive(AutoDefault, Clone, Debug)]
|
|
pub enum Item {
|
|
/// Sin contenido, no produce salida.
|
|
#[default]
|
|
Void,
|
|
/// Marca de identidad mostrada dentro del contenido de la barra de navegación.
|
|
///
|
|
/// Útil cuando el [`navbar::Layout`] no incluye marca, y se quiere incluir dentro del área
|
|
/// colapsable/*offcanvas*. Si el *layout* ya muestra una marca, esta variante no la sustituye,
|
|
/// sólo añade otra dentro del bloque de contenidos.
|
|
Brand(Embed<navbar::Brand>),
|
|
/// Representa un menú de navegación [`Nav`](crate::theme::Nav).
|
|
Nav(Embed<Nav>),
|
|
/// Representa un *texto localizado* libre.
|
|
Text(L10n),
|
|
}
|
|
|
|
impl Component for Item {
|
|
fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
fn id(&self) -> Option<String> {
|
|
match self {
|
|
Self::Void => None,
|
|
Self::Brand(brand) => brand.id(),
|
|
Self::Nav(nav) => nav.id(),
|
|
Self::Text(_) => None,
|
|
}
|
|
}
|
|
|
|
fn setup(&mut self, _cx: &Context) {
|
|
if let Self::Nav(nav) = self {
|
|
if let Some(mut nav) = nav.get() {
|
|
nav.alter_classes(ClassesOp::Prepend, "navbar-nav");
|
|
}
|
|
}
|
|
}
|
|
|
|
fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
|
Ok(match self {
|
|
Self::Void => html! {},
|
|
Self::Brand(brand) => html! { (brand.render(cx)) },
|
|
Self::Nav(nav) => {
|
|
if let Some(nav) = nav.get() {
|
|
let items = nav.items().render(cx);
|
|
if items.is_empty() {
|
|
return Ok(html! {});
|
|
}
|
|
html! {
|
|
ul id=[nav.id()] class=[nav.classes().get()] {
|
|
(items)
|
|
}
|
|
}
|
|
} else {
|
|
html! {}
|
|
}
|
|
}
|
|
Self::Text(text) => html! {
|
|
span class="navbar-text" {
|
|
(text.using(cx))
|
|
}
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Item {
|
|
/// Crea un elemento de tipo [`navbar::Brand`] para añadir en el contenido de [`Navbar`].
|
|
///
|
|
/// Pensado para barras colapsables u offcanvas donde se quiere que la marca aparezca en la zona
|
|
/// desplegable.
|
|
pub fn brand(brand: navbar::Brand) -> Self {
|
|
Self::Brand(Embed::with(brand))
|
|
}
|
|
|
|
/// Crea un elemento de tipo [`Nav`] para añadir al contenido de [`Navbar`].
|
|
pub fn nav(item: Nav) -> Self {
|
|
Self::Nav(Embed::with(item))
|
|
}
|
|
|
|
/// Crea un elemento con un *texto localizado*, mostrado sin interacción.
|
|
pub fn text(item: L10n) -> Self {
|
|
Self::Text(item)
|
|
}
|
|
}
|