♻️ (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 748bd81bf1
commit 2e39af0856
33 changed files with 1607 additions and 647 deletions

View file

@ -2,12 +2,8 @@ use pagetop::prelude::*;
use crate::theme::aux::Color;
use std::fmt;
// **< BorderColor >********************************************************************************
/// Colores `border-*` para los bordes ([`classes::Border`](crate::theme::classes::Border)).
#[derive(AutoDefault)]
#[derive(AutoDefault, Clone, Copy, Debug, PartialEq)]
pub enum BorderColor {
/// No define ninguna clase.
#[default]
@ -22,60 +18,70 @@ pub enum BorderColor {
White,
}
#[rustfmt::skip]
impl fmt::Display for BorderColor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Default => Ok(()),
Self::Theme(c) => write!(f, "border-{c}"),
Self::Subtle(c) => write!(f, "border-{c}-subtle"),
Self::Black => f.write_str("border-black"),
Self::White => f.write_str("border-white"),
}
}
}
impl BorderColor {
const BORDER: &str = "border";
const BORDER_PREFIX: &str = "border-";
// **< BorderSize >*********************************************************************************
/// Tamaño para el ancho de los bordes ([`classes::Border`](crate::theme::classes::Border)).
///
/// Mapea a `border`, `border-0` y `border-{1..5}`:
///
/// - `None` no añade ninguna clase.
/// - `Default` genera `border` (borde por defecto del tema).
/// - `Zero` genera `border-0` (sin borde).
/// - `Scale{1..5}` genera `border-{1..5}` (ancho creciente).
#[derive(AutoDefault)]
pub enum BorderSize {
#[default]
None,
Default,
Zero,
Scale1,
Scale2,
Scale3,
Scale4,
Scale5,
}
impl BorderSize {
// Devuelve el sufijo de la clase `border-*`, o `None` si no define ninguna clase.
#[rustfmt::skip]
pub(crate) fn to_class(&self, prefix: impl AsRef<str>) -> String {
#[inline]
const fn suffix(self) -> Option<&'static str> {
match self {
Self::None => String::new(),
Self::Default => String::from(prefix.as_ref()),
Self::Zero => join!(prefix, "-0"),
Self::Scale1 => join!(prefix, "-1"),
Self::Scale2 => join!(prefix, "-2"),
Self::Scale3 => join!(prefix, "-3"),
Self::Scale4 => join!(prefix, "-4"),
Self::Scale5 => join!(prefix, "-5"),
Self::Default => None,
Self::Theme(_) => Some(""),
Self::Subtle(_) => Some("-subtle"),
Self::Black => Some("-black"),
Self::White => Some("-white"),
}
}
}
impl fmt::Display for BorderSize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_class("border"))
// Añade la clase `border-*` a la cadena de clases.
#[inline]
pub(crate) fn push_class(self, classes: &mut String) {
if let Some(suffix) = self.suffix() {
if !classes.is_empty() {
classes.push(' ');
}
match self {
Self::Theme(c) | Self::Subtle(c) => {
classes.push_str(Self::BORDER_PREFIX);
classes.push_str(c.as_str());
}
_ => classes.push_str(Self::BORDER),
}
classes.push_str(suffix);
}
}
/// Devuelve la clase `border-*` correspondiente al color de borde.
///
/// # Ejemplos
///
/// ```rust
/// # use pagetop_bootsier::prelude::*;
/// assert_eq!(BorderColor::Theme(Color::Primary).to_class(), "border-primary");
/// assert_eq!(BorderColor::Subtle(Color::Warning).to_class(), "border-warning-subtle");
/// assert_eq!(BorderColor::Black.to_class(), "border-black");
/// assert_eq!(BorderColor::Default.to_class(), "");
/// ```
#[inline]
pub fn to_class(self) -> String {
if let Some(suffix) = self.suffix() {
let base_len = match self {
Self::Theme(c) | Self::Subtle(c) => Self::BORDER_PREFIX.len() + c.as_str().len(),
_ => Self::BORDER.len(),
};
let mut class = String::with_capacity(base_len + suffix.len());
match self {
Self::Theme(c) | Self::Subtle(c) => {
class.push_str(Self::BORDER_PREFIX);
class.push_str(c.as_str());
}
_ => class.push_str(Self::BORDER),
}
class.push_str(suffix);
return class;
}
String::new()
}
}