diff --git a/extensions/pagetop-bootsier/src/theme/attrs.rs b/extensions/pagetop-bootsier/src/theme/attrs.rs deleted file mode 100644 index 3b3be43a..00000000 --- a/extensions/pagetop-bootsier/src/theme/attrs.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Colección de elementos auxiliares de Bootstrap para Bootsier. - -mod breakpoint; -pub use breakpoint::BreakPoint; - -mod color; -pub use color::{Color, Opacity}; -pub use color::{ColorBg, ColorText}; - -mod layout; -pub use layout::{ScaleSize, Side}; - -mod border; -pub use border::BorderColor; - -mod rounded; -pub use rounded::RoundedRadius; diff --git a/extensions/pagetop-bootsier/src/theme/attrs/border.rs b/extensions/pagetop-bootsier/src/theme/attrs/border.rs deleted file mode 100644 index f83bb13a..00000000 --- a/extensions/pagetop-bootsier/src/theme/attrs/border.rs +++ /dev/null @@ -1,86 +0,0 @@ -use pagetop::prelude::*; - -use crate::theme::attrs::Color; - -/// Esquema de color para los bordes ([`classes::Border`](crate::theme::classes::Border)). -#[derive(AutoDefault, Clone, Copy, Debug, PartialEq)] -pub enum BorderColor { - /// No define ninguna clase. - #[default] - Default, - /// Genera la clase `border-{color}`. - Theme(Color), - /// Genera la clase `border-{color}-subtle` (un tono suavizado del color). - Subtle(Color), - /// Color negro. - Black, - /// Color blanco. - White, -} - -impl BorderColor { - const BORDER: &str = "border"; - const BORDER_PREFIX: &str = "border-"; - - /// Devuelve el sufijo de la clase `border-*`, o `None` si no define ninguna clase. - #[rustfmt::skip] - #[inline] - const fn suffix(self) -> Option<&'static str> { - match self { - Self::Default => None, - Self::Theme(_) => Some(""), - Self::Subtle(_) => Some("-subtle"), - Self::Black => Some("-black"), - Self::White => Some("-white"), - } - } - - /// 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,no_run - /// # use pagetop_bootsier::theme::*; - /// 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(), ""); - /// ``` - 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() - } -} diff --git a/extensions/pagetop-bootsier/src/theme/attrs/breakpoint.rs b/extensions/pagetop-bootsier/src/theme/attrs/breakpoint.rs deleted file mode 100644 index 5ee64ad5..00000000 --- a/extensions/pagetop-bootsier/src/theme/attrs/breakpoint.rs +++ /dev/null @@ -1,114 +0,0 @@ -use pagetop::prelude::*; - -/// Define los puntos de ruptura (*breakpoints*) para aplicar diseño *responsive*. -#[derive(AutoDefault, Clone, Copy, Debug, PartialEq)] -pub enum BreakPoint { - /// **Menos de 576px**. Dispositivos muy pequeños: teléfonos en modo vertical. - #[default] - None, - /// **576px o más** - Dispositivos pequeños: teléfonos en modo horizontal. - SM, - /// **768px o más** - Dispositivos medianos: tabletas. - MD, - /// **992px o más** - Dispositivos grandes: puestos de escritorio. - LG, - /// **1200px o más** - Dispositivos muy grandes: puestos de escritorio grandes. - XL, - /// **1400px o más** - Dispositivos extragrandes: puestos de escritorio más grandes. - XXL, -} - -impl BreakPoint { - /// Devuelve la identificación del punto de ruptura. - #[rustfmt::skip] - #[inline] - pub(crate) const fn as_str(self) -> &'static str { - match self { - Self::None => "", - Self::SM => "sm", - Self::MD => "md", - Self::LG => "lg", - Self::XL => "xl", - Self::XXL => "xxl", - } - } - - /// Añade el punto de ruptura con un prefijo y un sufijo (opcional) separados por un guion `-` a - /// la cadena de clases. - /// - /// - Para `None` - `prefix` o `prefix-suffix` (si `suffix` no está vacío). - /// - Para `SM..XXL` - `prefix-{breakpoint}` o `prefix-{breakpoint}-{suffix}`. - #[inline] - pub(crate) fn push_class(self, classes: &mut String, prefix: &str, suffix: &str) { - if prefix.is_empty() { - return; - } - if !classes.is_empty() { - classes.push(' '); - } - match self { - Self::None => classes.push_str(prefix), - _ => { - classes.push_str(prefix); - classes.push('-'); - classes.push_str(self.as_str()); - } - } - if !suffix.is_empty() { - classes.push('-'); - classes.push_str(suffix); - } - } - - /// Devuelve la clase para el punto de ruptura, con un prefijo y un sufijo opcional, separados - /// por un guion `-`. - /// - /// - Para `None` - `prefix` o `prefix-suffix` (si `suffix` no está vacío). - /// - Para `SM..XXL` - `prefix-{breakpoint}` o `prefix-{breakpoint}-{suffix}`. - /// - Si `prefix` está vacío devuelve `""`. - /// - /// # Ejemplos - /// - /// ```rust,no_run - /// # use pagetop_bootsier::theme::*; - /// let bp = BreakPoint::MD; - /// assert_eq!(bp.class_with("col", ""), "col-md"); - /// assert_eq!(bp.class_with("col", "6"), "col-md-6"); - /// - /// let bp = BreakPoint::None; - /// assert_eq!(bp.class_with("offcanvas", ""), "offcanvas"); - /// assert_eq!(bp.class_with("col", "12"), "col-12"); - /// - /// let bp = BreakPoint::LG; - /// assert_eq!(bp.class_with("", "3"), ""); - /// ``` - #[doc(hidden)] - pub fn class_with(self, prefix: &str, suffix: &str) -> String { - if prefix.is_empty() { - return String::new(); - } - - let bp = self.as_str(); - let has_bp = !bp.is_empty(); - let has_suffix = !suffix.is_empty(); - - let mut len = prefix.len(); - if has_bp { - len += 1 + bp.len(); - } - if has_suffix { - len += 1 + suffix.len(); - } - let mut class = String::with_capacity(len); - class.push_str(prefix); - if has_bp { - class.push('-'); - class.push_str(bp); - } - if has_suffix { - class.push('-'); - class.push_str(suffix); - } - class - } -} diff --git a/extensions/pagetop-bootsier/src/theme/attrs/rounded.rs b/extensions/pagetop-bootsier/src/theme/attrs/rounded.rs deleted file mode 100644 index 0f9536a8..00000000 --- a/extensions/pagetop-bootsier/src/theme/attrs/rounded.rs +++ /dev/null @@ -1,117 +0,0 @@ -use pagetop::prelude::*; - -/// Radio para el redondeo de esquinas ([`classes::Rounded`](crate::theme::classes::Rounded)). -#[derive(AutoDefault, Clone, Copy, Debug, PartialEq)] -pub enum RoundedRadius { - /// No define ninguna clase. - #[default] - None, - /// Genera `rounded` (radio por defecto del tema). - Default, - /// Genera `rounded-0` (sin redondeo). - Zero, - /// Genera `rounded-1`. - Scale1, - /// Genera `rounded-2`. - Scale2, - /// Genera `rounded-3`. - Scale3, - /// Genera `rounded-4`. - Scale4, - /// Genera `rounded-5`. - Scale5, - /// Genera `rounded-circle`. - Circle, - /// Genera `rounded-pill`. - Pill, -} - -impl RoundedRadius { - const ROUNDED: &str = "rounded"; - - /// Devuelve el sufijo para `*rounded-*`, o `None` si no define ninguna clase, o `""` para el - /// redondeo por defecto. - #[rustfmt::skip] - #[inline] - const fn suffix(self) -> Option<&'static str> { - match self { - Self::None => None, - Self::Default => Some(""), - Self::Zero => Some("-0"), - Self::Scale1 => Some("-1"), - Self::Scale2 => Some("-2"), - Self::Scale3 => Some("-3"), - Self::Scale4 => Some("-4"), - Self::Scale5 => Some("-5"), - Self::Circle => Some("-circle"), - Self::Pill => Some("-pill"), - } - } - - /// Añade el redondeo de esquinas a la cadena de clases usando el prefijo dado (`rounded-top`, - /// `rounded-bottom-start`, o vacío para `rounded-*`). - #[inline] - pub(crate) fn push_class(self, classes: &mut String, prefix: &str) { - if let Some(suffix) = self.suffix() { - if !classes.is_empty() { - classes.push(' '); - } - if prefix.is_empty() { - classes.push_str(Self::ROUNDED); - } else { - classes.push_str(prefix); - } - classes.push_str(suffix); - } - } - - /// Devuelve la clase para el redondeo de esquinas con el prefijo dado (`rounded-top`, - /// `rounded-bottom-start`, o vacío para `rounded-*`). - /// - /// # Ejemplos - /// - /// ```rust,no_run - /// # use pagetop_bootsier::theme::*; - /// assert_eq!(RoundedRadius::Scale2.class_with(""), "rounded-2"); - /// assert_eq!(RoundedRadius::Zero.class_with("rounded-top"), "rounded-top-0"); - /// assert_eq!(RoundedRadius::Scale3.class_with("rounded-top-end"), "rounded-top-end-3"); - /// assert_eq!(RoundedRadius::Circle.class_with(""), "rounded-circle"); - /// assert_eq!(RoundedRadius::None.class_with("rounded-bottom-start"), ""); - /// ``` - #[doc(hidden)] - pub fn class_with(self, prefix: &str) -> String { - if let Some(suffix) = self.suffix() { - let base_len = if prefix.is_empty() { - Self::ROUNDED.len() - } else { - prefix.len() - }; - let mut class = String::with_capacity(base_len + suffix.len()); - if prefix.is_empty() { - class.push_str(Self::ROUNDED); - } else { - class.push_str(prefix); - } - class.push_str(suffix); - return class; - } - String::new() - } - - /// Devuelve la clase `rounded-*` para el redondeo de esquinas. - /// - /// # Ejemplos - /// - /// ```rust,no_run - /// # use pagetop_bootsier::theme::*; - /// assert_eq!(RoundedRadius::Default.to_class(), "rounded"); - /// assert_eq!(RoundedRadius::Zero.to_class(), "rounded-0"); - /// assert_eq!(RoundedRadius::Scale3.to_class(), "rounded-3"); - /// assert_eq!(RoundedRadius::Circle.to_class(), "rounded-circle"); - /// assert_eq!(RoundedRadius::None.to_class(), ""); - /// ``` - #[inline] - pub fn to_class(self) -> String { - self.class_with("") - } -} diff --git a/extensions/pagetop-bootsier/src/theme/bs.rs b/extensions/pagetop-bootsier/src/theme/bs.rs new file mode 100644 index 00000000..c5dd6e08 --- /dev/null +++ b/extensions/pagetop-bootsier/src/theme/bs.rs @@ -0,0 +1,53 @@ +//! Tipos y componentes disponibles. +//! +//! A continuación, el apartado **Modules** incluye las definiciones necesarias para los componentes +//! que se muestran en el apartado **Structs**, mientras que en **Enums** se listan los elementos +//! auxiliares del tema utilizados en clases y componentes. + +mod attrs; +pub use attrs::*; + +mod classes; +pub use classes::*; + +// Button. +mod button; +pub use button::{Button, ButtonAction}; + +// Container. +pub mod container; +#[doc(inline)] +pub use container::Container; + +// Dropdown. +pub mod dropdown; +#[doc(inline)] +pub use dropdown::Dropdown; + +// Form. +pub mod form; +#[doc(inline)] +pub use form::Form; + +// Image. +pub mod image; +#[doc(inline)] +pub use image::Image; + +// Nav. +pub mod nav; +#[doc(inline)] +pub use nav::Nav; + +// Navbar. +pub mod navbar; +#[doc(inline)] +pub use navbar::Navbar; + +// Offcanvas. +pub mod offcanvas; +#[doc(inline)] +pub use offcanvas::Offcanvas; + +// Sidebar (componentes de navegación de AdminLTE). +pub mod sidebar; diff --git a/extensions/pagetop-bootsier/src/theme/button.rs b/extensions/pagetop-bootsier/src/theme/bs/button.rs similarity index 100% rename from extensions/pagetop-bootsier/src/theme/button.rs rename to extensions/pagetop-bootsier/src/theme/bs/button.rs diff --git a/extensions/pagetop-bootsier/src/theme/container.rs b/extensions/pagetop-bootsier/src/theme/bs/container.rs similarity index 71% rename from extensions/pagetop-bootsier/src/theme/container.rs rename to extensions/pagetop-bootsier/src/theme/bs/container.rs index 707fdc4f..41a35d60 100644 --- a/extensions/pagetop-bootsier/src/theme/container.rs +++ b/extensions/pagetop-bootsier/src/theme/bs/container.rs @@ -1,9 +1,9 @@ //! Definiciones para crear contenedores de componentes ([`Container`]). //! //! Cada contenedor envuelve contenido usando la etiqueta semántica indicada por -//! [`container::Kind`](crate::theme::container::Kind). +//! [`container::Kind`](crate::theme::bs::container::Kind). //! -//! Con [`container::Width`](crate::theme::container::Width) se puede definir el ancho y el +//! Con [`container::Width`](crate::theme::bs::container::Width) se puede definir el ancho y el //! comportamiento *responsive* del contenedor. También permite aplicar utilidades de estilo para el //! fondo, texto, borde o esquinas redondeadas. diff --git a/extensions/pagetop-bootsier/src/theme/container/component.rs b/extensions/pagetop-bootsier/src/theme/bs/container/component.rs similarity index 74% rename from extensions/pagetop-bootsier/src/theme/container/component.rs rename to extensions/pagetop-bootsier/src/theme/bs/container/component.rs index 07a835a7..a398a05b 100644 --- a/extensions/pagetop-bootsier/src/theme/container/component.rs +++ b/extensions/pagetop-bootsier/src/theme/bs/container/component.rs @@ -2,10 +2,11 @@ use pagetop::prelude::*; use crate::theme::*; -/// Componente para crear un **contenedor de componentes** ([`container`]). +/// Componente para crear un **contenedor de componentes** +/// ([`container`](crate::theme::bs::container)). /// /// Envuelve un conjunto de componentes en un contenedor establecido que se crea aplicando uno de -/// los tipos definidos en [`container::Kind`]. +/// los tipos definidos en [`container::Kind`](crate::theme::bs::container::Kind). /// /// Si no contiene elementos, el componente **no se renderiza**. /// @@ -14,18 +15,18 @@ use crate::theme::*; /// ```rust,no_run /// use pagetop_bootsier::theme::*; /// -/// let main = Container::main() +/// let main = bs::Container::main() /// .with_id("main-page") -/// .with_width(container::Width::From(BreakPoint::LG)); +/// .with_width(bs::container::Width::From(token::BreakPoint::LG)); /// ``` #[derive(AutoDefault, Clone, Debug, Getters)] pub struct Container { /// Devuelve identificador, clases CSS y atributos HTML del componente. props: Props, /// Devuelve el tipo semántico del contenedor. - container_kind: container::Kind, + container_kind: bs::container::Kind, /// Devuelve el comportamiento para el ancho del contenedor. - container_width: container::Width, + container_width: bs::container::Width, /// Devuelve la lista de componentes (`children`) del contenedor. children: Children, } @@ -49,38 +50,38 @@ impl Component for Container { return Ok(html! {}); } let style = match self.container_width() { - container::Width::FluidMax(w) if w.is_measurable() => { + bs::container::Width::FluidMax(w) if w.is_measurable() => { Some(util::join!("max-width: ", w.to_string(), ";")) } _ => None, }; Ok(match self.container_kind() { - container::Kind::Default => html! { + bs::container::Kind::Default => html! { div (self.props()) style=[style] { (output) } }, - container::Kind::Main => html! { + bs::container::Kind::Main => html! { main (self.props()) style=[style] { (output) } }, - container::Kind::Header => html! { + bs::container::Kind::Header => html! { header (self.props()) style=[style] { (output) } }, - container::Kind::Footer => html! { + bs::container::Kind::Footer => html! { footer (self.props()) style=[style] { (output) } }, - container::Kind::Section => html! { + bs::container::Kind::Section => html! { section (self.props()) style=[style] { (output) } }, - container::Kind::Article => html! { + bs::container::Kind::Article => html! { article (self.props()) style=[style] { (output) } @@ -93,7 +94,7 @@ impl Container { /// Crea un contenedor de tipo `Main` (`
`). pub fn main() -> Self { Self { - container_kind: container::Kind::Main, + container_kind: bs::container::Kind::Main, ..Default::default() } } @@ -101,7 +102,7 @@ impl Container { /// Crea un contenedor de tipo `Header` (`
`). pub fn header() -> Self { Self { - container_kind: container::Kind::Header, + container_kind: bs::container::Kind::Header, ..Default::default() } } @@ -109,7 +110,7 @@ impl Container { /// Crea un contenedor de tipo `Footer` (`