♻️ [bootsier] Refactoriza la gestión de clases

- Mejora la legibilidad del código.
- Simplifica las alteraciones de clases en los componentes `Container`,
  `Dropdown`, `Image`, `Nav`, `Navbar` y `Offcanvas` usando métodos
  dedicados para generar clases en función de sus propiedades.
- Mejora los enums añadiendo métodos que devuelven sus clases
  asociadas, reduciendo código repetitivo.
- Elimina el trait `JoinClasses` y su implementación, integrando la
  lógica de unión de clases directamente en los componentes.
This commit is contained in:
Manuel Cillero 2025-11-15 13:16:15 +01:00
parent 39033ef641
commit 623ef7e2c7
33 changed files with 1607 additions and 647 deletions

View file

@ -35,22 +35,12 @@ impl Component for Navbar {
}
fn setup_before_prepare(&mut self, _cx: &mut Context) {
self.alter_classes(
ClassesOp::Prepend,
[
"navbar".to_string(),
self.expand().try_class("navbar-expand").unwrap_or_default(),
match self.position() {
navbar::Position::Static => "",
navbar::Position::FixedTop => "fixed-top",
navbar::Position::FixedBottom => "fixed-bottom",
navbar::Position::StickyTop => "sticky-top",
navbar::Position::StickyBottom => "sticky-bottom",
}
.to_string(),
]
.join_classes(),
);
self.alter_classes(ClassesOp::Prepend, {
let mut classes = "navbar".to_string();
self.expand().push_class(&mut classes, "navbar-expand", "");
self.position().push_class(&mut classes);
classes
});
}
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {

View file

@ -38,6 +38,14 @@ impl Component for Item {
}
}
fn setup_before_prepare(&mut self, _cx: &mut Context) {
if let Self::Nav(nav) = self {
if let Some(mut nav) = nav.borrow_mut() {
nav.alter_classes(ClassesOp::Prepend, "navbar-nav");
}
}
}
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
match self {
Self::Void => PrepareMarkup::None,
@ -48,29 +56,8 @@ impl Component for Item {
if items.is_empty() {
return PrepareMarkup::None;
}
let classes = AttrClasses::new(
[
"navbar-nav",
match nav.nav_kind() {
nav::Kind::Default => "",
nav::Kind::Tabs => "nav-tabs",
nav::Kind::Pills => "nav-pills",
nav::Kind::Underline => "nav-underline",
},
match nav.nav_layout() {
nav::Layout::Default => "",
nav::Layout::Start => "justify-content-start",
nav::Layout::Center => "justify-content-center",
nav::Layout::End => "justify-content-end",
nav::Layout::Vertical => "flex-column",
nav::Layout::Fill => "nav-fill",
nav::Layout::Justified => "nav-justified",
},
]
.join_classes(),
);
PrepareMarkup::With(html! {
ul id=[nav.id()] class=[classes.get()] {
ul id=[nav.id()] class=[nav.classes().get()] {
(items)
}
})

View file

@ -42,7 +42,7 @@ pub enum Layout {
// **< Position >***********************************************************************************
/// Posición global de una barra de navegación [`Navbar`] en el documento.
#[derive(AutoDefault)]
#[derive(AutoDefault, Clone, Copy, Debug, PartialEq)]
pub enum Position {
/// Barra normal, fluye con el documento.
#[default]
@ -62,3 +62,37 @@ pub enum Position {
/// La barra de navegación se fija en la parte inferior al hacer *scroll*.
StickyBottom,
}
impl Position {
// Devuelve la clase base asociada a la posición de la barra de navegación.
#[inline]
const fn as_str(self) -> &'static str {
match self {
Self::Static => "",
Self::FixedTop => "fixed-top",
Self::FixedBottom => "fixed-bottom",
Self::StickyTop => "sticky-top",
Self::StickyBottom => "sticky-bottom",
}
}
// Añade la clase asociada a la posición de la barra de navegación a la cadena de clases.
#[inline]
pub(crate) fn push_class(self, classes: &mut String) {
let class = self.as_str();
if class.is_empty() {
return;
}
if !classes.is_empty() {
classes.push(' ');
}
classes.push_str(class);
}
/* Devuelve la clase asociada a la posición de la barra de navegación, o cadena vacía si no
// aplica (reservado).
#[inline]
pub(crate) fn to_class(self) -> String {
self.as_str().to_string()
} */
}