WIP: Añade componente para la gestión de menús #8
23 changed files with 1041 additions and 994 deletions
|
|
@ -98,7 +98,6 @@ pub mod theme;
|
||||||
/// *Prelude* del tema.
|
/// *Prelude* del tema.
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::config::*;
|
pub use crate::config::*;
|
||||||
pub use crate::theme::aux::*;
|
|
||||||
pub use crate::theme::*;
|
pub use crate::theme::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,18 @@
|
||||||
//! Definiciones y componentes del tema.
|
//! Definiciones y componentes del tema.
|
||||||
|
//!
|
||||||
|
//! En esta página, 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.
|
||||||
|
|
||||||
pub mod aux;
|
mod aux;
|
||||||
|
pub use aux::*;
|
||||||
|
|
||||||
|
pub mod classes;
|
||||||
|
|
||||||
// Container.
|
// Container.
|
||||||
mod container;
|
pub mod container;
|
||||||
pub use container::{Container, ContainerType, ContainerWidth};
|
#[doc(inline)]
|
||||||
|
pub use container::Container;
|
||||||
|
|
||||||
// Dropdown.
|
// Dropdown.
|
||||||
pub mod dropdown;
|
pub mod dropdown;
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,13 @@ pub use breakpoint::BreakPoint;
|
||||||
|
|
||||||
mod color;
|
mod color;
|
||||||
pub use color::{Color, Opacity};
|
pub use color::{Color, Opacity};
|
||||||
pub use color::{ColorBg, ColorBorder, ColorButton, ColorText};
|
pub use color::{ColorBg, ColorText};
|
||||||
pub use color::{StyleBg, StyleBorder, StyleText};
|
|
||||||
|
|
||||||
mod border;
|
mod border;
|
||||||
pub use border::{Border, BorderSize};
|
pub use border::{BorderColor, BorderSize};
|
||||||
|
|
||||||
mod rounded;
|
mod rounded;
|
||||||
pub use rounded::{Rounded, RoundedRadius};
|
pub use rounded::RoundedRadius;
|
||||||
|
|
||||||
mod size;
|
mod button;
|
||||||
pub use size::ButtonSize;
|
pub use button::{ButtonColor, ButtonSize};
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,47 @@
|
||||||
use pagetop::prelude::*;
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::theme::aux::Color;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
// **< BorderColor >********************************************************************************
|
||||||
|
|
||||||
|
/// Colores `border-*` para los bordes ([`classes::Border`](crate::theme::classes::Border)).
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub enum BorderColor {
|
||||||
|
/// No define ninguna clase.
|
||||||
|
#[default]
|
||||||
|
Default,
|
||||||
|
/// Genera internamente clases `border-{color}`.
|
||||||
|
Theme(Color),
|
||||||
|
/// Genera internamente clases `border-{color}-subtle` (un tono suavizado del color).
|
||||||
|
Subtle(Color),
|
||||||
|
/// Color negro.
|
||||||
|
Black,
|
||||||
|
/// Color blanco.
|
||||||
|
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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// **< BorderSize >*********************************************************************************
|
// **< BorderSize >*********************************************************************************
|
||||||
|
|
||||||
/// Tamaño para el ancho de los bordes ([`Border`]).
|
/// Tamaño para el ancho de los bordes ([`classes::Border`](crate::theme::classes::Border)).
|
||||||
///
|
///
|
||||||
/// Mapea a `border`, `border-0` y `border-{1..5}`:
|
/// Mapea a `border`, `border-0` y `border-{1..5}`:
|
||||||
///
|
///
|
||||||
/// - `None` no añade clase (devuelve `""`).
|
/// - `None` no añade ninguna clase.
|
||||||
/// - `Default` genera `border` (borde por defecto del tema).
|
/// - `Default` genera `border` (borde por defecto del tema).
|
||||||
/// - `Zero` genera `border-0` (sin borde).
|
/// - `Zero` genera `border-0` (sin borde).
|
||||||
/// - `Scale{1..5}` genera `border-{1..5}` (ancho creciente).
|
/// - `Scale{1..5}` genera `border-{1..5}` (ancho creciente).
|
||||||
|
|
@ -29,7 +60,7 @@ pub enum BorderSize {
|
||||||
|
|
||||||
impl BorderSize {
|
impl BorderSize {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
fn to_class(&self, prefix: impl AsRef<str>) -> String {
|
pub(crate) fn to_class(&self, prefix: impl AsRef<str>) -> String {
|
||||||
match self {
|
match self {
|
||||||
Self::None => String::new(),
|
Self::None => String::new(),
|
||||||
Self::Default => String::from(prefix.as_ref()),
|
Self::Default => String::from(prefix.as_ref()),
|
||||||
|
|
@ -48,146 +79,3 @@ impl fmt::Display for BorderSize {
|
||||||
write!(f, "{}", self.to_class("border"))
|
write!(f, "{}", self.to_class("border"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// **< Border >*************************************************************************************
|
|
||||||
|
|
||||||
/// Agrupa propiedades para crear **bordes**.
|
|
||||||
///
|
|
||||||
/// Permite:
|
|
||||||
///
|
|
||||||
/// - Definir un tamaño **global** para todo el borde (`size`).
|
|
||||||
/// - Ajustar el tamaño de cada **lado lógico** (`top`, `end`, `bottom`, `start`, **en este orden**,
|
|
||||||
/// respetando LTR/RTL).
|
|
||||||
/// - Aplicar un **color** al borde (`ColorBorder`).
|
|
||||||
/// - Aplicar un nivel de **opacidad** (`BorderOpacity`).
|
|
||||||
///
|
|
||||||
/// # Comportamiento aditivo / sustractivo
|
|
||||||
///
|
|
||||||
/// - **Aditivo**: basta con crear un borde sin tamaño con `Border::new()` para ir añadiendo cada
|
|
||||||
/// lado lógico con el tamaño deseado usando `BorderSize::Scale{1..5}`.
|
|
||||||
///
|
|
||||||
/// - **Sustractivo**: se crea un borde con tamaño predefinido, p. ej. utilizando
|
|
||||||
/// `Border::with(BorderSize::Scale2)` y eliminar los lados deseados con `BorderSize::Zero`.
|
|
||||||
///
|
|
||||||
/// - **Anchos diferentes por lado**: usando `BorderSize::Scale{1..5}` en cada lado deseado.
|
|
||||||
///
|
|
||||||
/// # Ejemplos
|
|
||||||
///
|
|
||||||
/// **Borde global:**
|
|
||||||
/// ```rust
|
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
|
||||||
/// let b = Border::with(BorderSize::Scale2);
|
|
||||||
/// assert_eq!(b.to_string(), "border-2");
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// **Aditivo (solo borde superior):**
|
|
||||||
/// ```rust
|
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
|
||||||
/// let b = Border::new().with_top(BorderSize::Scale1);
|
|
||||||
/// assert_eq!(b.to_string(), "border-top-1");
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// **Sustractivo (borde global menos el superior):**
|
|
||||||
/// ```rust
|
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
|
||||||
/// let b = Border::with(BorderSize::Default).with_top(BorderSize::Zero);
|
|
||||||
/// assert_eq!(b.to_string(), "border border-top-0");
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// **Ancho por lado (lado lógico inicial a 2 y final a 4):**
|
|
||||||
/// ```rust
|
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
|
||||||
/// let b = Border::new().with_start(BorderSize::Scale2).with_end(BorderSize::Scale4);
|
|
||||||
/// assert_eq!(b.to_string(), "border-end-4 border-start-2");
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// **Combinado (ejemplo completo):**
|
|
||||||
/// ```rust
|
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
|
||||||
/// let b = Border::with(BorderSize::Default) // Borde global por defecto.
|
|
||||||
/// .with_top(BorderSize::Zero) // Quita borde superior.
|
|
||||||
/// .with_end(BorderSize::Scale3) // Ancho 3 para el lado lógico final.
|
|
||||||
/// .with_style(StyleBorder::Both(ColorBorder::Theme(Color::Primary), Opacity::Half));
|
|
||||||
///
|
|
||||||
/// assert_eq!(b.to_string(), "border border-top-0 border-end-3 border-primary border-opacity-50");
|
|
||||||
/// ```
|
|
||||||
#[rustfmt::skip]
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub struct Border {
|
|
||||||
size : BorderSize,
|
|
||||||
top : BorderSize,
|
|
||||||
end : BorderSize,
|
|
||||||
bottom: BorderSize,
|
|
||||||
start : BorderSize,
|
|
||||||
style : StyleBorder,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Border {
|
|
||||||
/// Prepara un borde **sin tamaño global** de partida.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Crea un borde **con tamaño global** (`size`).
|
|
||||||
pub fn with(size: BorderSize) -> Self {
|
|
||||||
Self::default().with_size(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< Border BUILDER >*************************************************************************
|
|
||||||
|
|
||||||
/// Establece el tamaño global del borde (`border*`).
|
|
||||||
pub fn with_size(mut self, size: BorderSize) -> Self {
|
|
||||||
self.size = size;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el tamaño del borde superior (`border-top-*`).
|
|
||||||
pub fn with_top(mut self, size: BorderSize) -> Self {
|
|
||||||
self.top = size;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el tamaño del borde en el lado lógico final (`border-end-*`). Respeta LTR/RTL.
|
|
||||||
pub fn with_end(mut self, size: BorderSize) -> Self {
|
|
||||||
self.end = size;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el tamaño del borde inferior (`border-bottom-*`).
|
|
||||||
pub fn with_bottom(mut self, size: BorderSize) -> Self {
|
|
||||||
self.bottom = size;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el tamaño del borde en el lado lógico inicial (`border-start-*`). Respeta LTR/RTL.
|
|
||||||
pub fn with_start(mut self, size: BorderSize) -> Self {
|
|
||||||
self.start = size;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el estilo de color/opacidad del borde.
|
|
||||||
pub fn with_style(mut self, style: StyleBorder) -> Self {
|
|
||||||
self.style = style;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Border {
|
|
||||||
/// Concatena cada definición en el orden: *global*, `top`, `end`, `bottom`, `start` y
|
|
||||||
/// *color*/*opacidad*; respetando LTR/RTL y omitiendo las definiciones vacías.
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}",
|
|
||||||
join_opt!([
|
|
||||||
self.size.to_string(),
|
|
||||||
self.top.to_class("border-top"),
|
|
||||||
self.end.to_class("border-end"),
|
|
||||||
self.bottom.to_class("border-bottom"),
|
|
||||||
self.start.to_class("border-start"),
|
|
||||||
self.style.to_string(),
|
|
||||||
]; " ")
|
|
||||||
.unwrap_or_default()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,25 +3,6 @@ use pagetop::prelude::*;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/// Define los puntos de ruptura (*breakpoints*) para aplicar diseño *responsive*.
|
/// Define los puntos de ruptura (*breakpoints*) para aplicar diseño *responsive*.
|
||||||
///
|
|
||||||
/// - `"sm"`, `"md"`, `"lg"`, `"xl"` o `"xxl"` para los puntos de ruptura `SM`, `MD`, `LG`, `XL` o
|
|
||||||
/// `XXL`, respectivamente.
|
|
||||||
/// - `""` (cadena vacía) para `None`.
|
|
||||||
///
|
|
||||||
/// # Ejemplos
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
|
||||||
/// assert_eq!(BreakPoint::MD.to_string(), "md");
|
|
||||||
/// assert_eq!(BreakPoint::None.to_string(), "");
|
|
||||||
///
|
|
||||||
/// // Forma correcta para clases con prefijo:
|
|
||||||
/// assert_eq!(BreakPoint::MD.to_class("col"), "col-md");
|
|
||||||
/// assert_eq!(BreakPoint::None.to_class("offcanvas"), "offcanvas");
|
|
||||||
///
|
|
||||||
/// assert_eq!(BreakPoint::XXL.try_class("col"), Some("col-xxl".to_string()));
|
|
||||||
/// assert_eq!(BreakPoint::None.try_class("offcanvas"), None);
|
|
||||||
/// ```
|
|
||||||
#[derive(AutoDefault)]
|
#[derive(AutoDefault)]
|
||||||
pub enum BreakPoint {
|
pub enum BreakPoint {
|
||||||
/// **Menos de 576px**. Dispositivos muy pequeños: teléfonos en modo vertical.
|
/// **Menos de 576px**. Dispositivos muy pequeños: teléfonos en modo vertical.
|
||||||
|
|
@ -40,46 +21,43 @@ pub enum BreakPoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BreakPoint {
|
impl BreakPoint {
|
||||||
/// Comprueba si es un punto de ruptura efectivo.
|
#[rustfmt::skip]
|
||||||
///
|
|
||||||
/// Devuelve `true` si el valor es `SM`, `MD`, `LG`, `XL` o `XXL`; y `false` en otro caso.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_breakpoint(&self) -> bool {
|
const fn suffix(&self) -> Option<&'static str> {
|
||||||
!matches!(self, Self::None)
|
match self {
|
||||||
|
Self::None => None,
|
||||||
|
Self::SM => Some("sm"),
|
||||||
|
Self::MD => Some("md"),
|
||||||
|
Self::LG => Some("lg"),
|
||||||
|
Self::XL => Some("xl"),
|
||||||
|
Self::XXL => Some("xxl"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Genera un nombre de clase CSS basado en el punto de ruptura.
|
/// Genera un nombre de clase CSS basado en el punto de ruptura.
|
||||||
///
|
///
|
||||||
/// Si es un punto de ruptura efectivo (ver [`is_breakpoint()`](Self::is_breakpoint), concatena
|
/// Si es un punto de ruptura efectivo concatena el prefijo, un guion (`-`) y el sufijo
|
||||||
/// el prefijo, un guion (`-`) y el sufijo asociado. En otro caso devuelve únicamente el
|
/// asociado. Para `None` devuelve sólo el prefijo.
|
||||||
/// prefijo.
|
|
||||||
///
|
///
|
||||||
/// # Ejemplo
|
/// # Ejemplo
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
/// let breakpoint = BreakPoint::MD;
|
/// let breakpoint = BreakPoint::MD;
|
||||||
/// let class = breakpoint.to_class("col");
|
/// assert_eq!(breakpoint.to_class("col"), "col-md");
|
||||||
/// assert_eq!(class, "col-md".to_string());
|
|
||||||
///
|
///
|
||||||
/// let breakpoint = BreakPoint::None;
|
/// let breakpoint = BreakPoint::None;
|
||||||
/// let class = breakpoint.to_class("offcanvas");
|
/// assert_eq!(breakpoint.to_class("offcanvas"), "offcanvas");
|
||||||
/// assert_eq!(class, "offcanvas".to_string());
|
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_class(&self, prefix: impl AsRef<str>) -> String {
|
pub fn to_class(&self, prefix: impl AsRef<str>) -> String {
|
||||||
if self.is_breakpoint() {
|
join_pair!(prefix, "-", self.suffix().unwrap_or_default())
|
||||||
join!(prefix, "-", self.to_string())
|
|
||||||
} else {
|
|
||||||
String::from(prefix.as_ref())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Intenta generar un nombre de clase CSS basado en el punto de ruptura.
|
/// Intenta generar un nombre de clase CSS basado en el punto de ruptura.
|
||||||
///
|
///
|
||||||
/// Si es un punto de ruptura efectivo (ver [`is_breakpoint()`](Self::is_breakpoint), devuelve
|
/// Si es un punto de ruptura efectivo devuelve `Some(String)` concatenando el prefijo, un guion
|
||||||
/// `Some(String)` concatenando el prefijo, un guion (`-`) y el sufijo asociado. En otro caso
|
/// (`-`) y el sufijo asociado. En otro caso devuelve `None`.
|
||||||
/// devuelve `None`.
|
|
||||||
///
|
///
|
||||||
/// # Ejemplo
|
/// # Ejemplo
|
||||||
///
|
///
|
||||||
|
|
@ -95,24 +73,19 @@ impl BreakPoint {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_class(&self, prefix: impl AsRef<str>) -> Option<String> {
|
pub fn try_class(&self, prefix: impl AsRef<str>) -> Option<String> {
|
||||||
if self.is_breakpoint() {
|
self.suffix().map(|suffix| join_pair!(prefix, "-", suffix))
|
||||||
Some(join!(prefix, "-", self.to_string()))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl fmt::Display for BreakPoint {
|
impl fmt::Display for BreakPoint {
|
||||||
|
/// Implementa [`Display`](std::fmt::Display) para asociar `"sm"`, `"md"`, `"lg"`, `"xl"` o
|
||||||
|
/// `"xxl"` a los puntos de ruptura `BreakPoint::SM`, `MD`, `LG`, `XL` o `XXL`, respectivamente.
|
||||||
|
/// Y `""` (cadena vacía) a `BreakPoint::None`.
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
if let Some(suffix) = self.suffix() {
|
||||||
Self::None => Ok(()),
|
f.write_str(suffix)
|
||||||
Self::SM => f.write_str("sm"),
|
} else {
|
||||||
Self::MD => f.write_str("md"),
|
Ok(())
|
||||||
Self::LG => f.write_str("lg"),
|
|
||||||
Self::XL => f.write_str("xl"),
|
|
||||||
Self::XXL => f.write_str("xxl"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
58
extensions/pagetop-bootsier/src/theme/aux/button.rs
Normal file
58
extensions/pagetop-bootsier/src/theme/aux/button.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
use crate::theme::aux::Color;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
// **< ButtonColor >********************************************************************************
|
||||||
|
|
||||||
|
/// Variantes de color `btn-*` para botones.
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub enum ButtonColor {
|
||||||
|
/// No define ninguna clase.
|
||||||
|
#[default]
|
||||||
|
Default,
|
||||||
|
/// Genera internamente clases `btn-{color}` (botón relleno).
|
||||||
|
Background(Color),
|
||||||
|
/// Genera `btn-outline-{color}` (fondo transparente y contorno con borde).
|
||||||
|
Outline(Color),
|
||||||
|
/// Aplica estilo de los enlaces (`btn-link`), sin caja ni fondo, heredando el color de texto.
|
||||||
|
Link,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
impl fmt::Display for ButtonColor {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Default => Ok(()),
|
||||||
|
Self::Background(c) => write!(f, "btn-{c}"),
|
||||||
|
Self::Outline(c) => write!(f, "btn-outline-{c}"),
|
||||||
|
Self::Link => f.write_str("btn-link"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< ButtonSize >*********************************************************************************
|
||||||
|
|
||||||
|
/// Tamaño visual de un botón.
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub enum ButtonSize {
|
||||||
|
/// Tamaño por defecto del tema (no añade clase).
|
||||||
|
#[default]
|
||||||
|
Default,
|
||||||
|
/// Botón compacto.
|
||||||
|
Small,
|
||||||
|
/// Botón destacado/grande.
|
||||||
|
Large,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
impl fmt::Display for ButtonSize {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Default => Ok(()),
|
||||||
|
Self::Small => f.write_str("btn-sm"),
|
||||||
|
Self::Large => f.write_str("btn-lg"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,8 +7,10 @@ use std::fmt;
|
||||||
/// Paleta de colores temáticos.
|
/// Paleta de colores temáticos.
|
||||||
///
|
///
|
||||||
/// Equivalen a los nombres estándar definidos por Bootstrap (`primary`, `secondary`, `success`,
|
/// Equivalen a los nombres estándar definidos por Bootstrap (`primary`, `secondary`, `success`,
|
||||||
/// etc.). Este tipo enumerado sirve de base para componer clases de color para el fondo
|
/// etc.). Este tipo enumerado sirve de base para componer las clases de color para fondo
|
||||||
/// ([`ColorBg`]), bordes ([`ColorBorder`]) y texto ([`ColorText`]).
|
/// ([`classes::Background`](crate::theme::classes::Background)), bordes
|
||||||
|
/// ([`classes::Border`](crate::theme::classes::Border)) y texto
|
||||||
|
/// ([`classes::Text`](crate::theme::classes::Text)).
|
||||||
#[derive(AutoDefault)]
|
#[derive(AutoDefault)]
|
||||||
pub enum Color {
|
pub enum Color {
|
||||||
#[default]
|
#[default]
|
||||||
|
|
@ -38,12 +40,69 @@ impl fmt::Display for Color {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// **< Opacity >************************************************************************************
|
||||||
|
|
||||||
|
/// Niveles de opacidad (`opacity-*`).
|
||||||
|
///
|
||||||
|
/// Se usa normalmente para graduar la transparencia del color de fondo `bg-opacity-*`
|
||||||
|
/// ([`classes::Background`](crate::theme::classes::Background)), de los bordes `border-opacity-*`
|
||||||
|
/// ([`classes::Border`](crate::theme::classes::Border)) o del texto `text-opacity-*`
|
||||||
|
/// ([`classes::Text`](crate::theme::classes::Text)).
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub enum Opacity {
|
||||||
|
/// No define ninguna clase.
|
||||||
|
#[default]
|
||||||
|
Default,
|
||||||
|
/// Permite generar clases `*-opacity-100` (100% de opacidad).
|
||||||
|
Opaque,
|
||||||
|
/// Permite generar clases `*-opacity-75` (75%).
|
||||||
|
SemiOpaque,
|
||||||
|
/// Permite generar clases `*-opacity-50` (50%).
|
||||||
|
Half,
|
||||||
|
/// Permite generar clases `*-opacity-25` (25%).
|
||||||
|
SemiTransparent,
|
||||||
|
/// Permite generar clases `*-opacity-10` (10%).
|
||||||
|
AlmostTransparent,
|
||||||
|
/// Permite generar clases `*-opacity-0` (0%, totalmente transparente).
|
||||||
|
Transparent,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Opacity {
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[inline]
|
||||||
|
const fn suffix(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Default => "",
|
||||||
|
Self::Opaque => "opacity-100",
|
||||||
|
Self::SemiOpaque => "opacity-75",
|
||||||
|
Self::Half => "opacity-50",
|
||||||
|
Self::SemiTransparent => "opacity-25",
|
||||||
|
Self::AlmostTransparent => "opacity-10",
|
||||||
|
Self::Transparent => "opacity-0",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn to_class(&self, prefix: impl AsRef<str>) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Default => String::new(),
|
||||||
|
_ => join_pair!(prefix, "-", self.suffix()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Opacity {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(self.suffix())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// **< ColorBg >************************************************************************************
|
// **< ColorBg >************************************************************************************
|
||||||
|
|
||||||
/// Colores `bg-*` para el fondo.
|
/// Colores `bg-*` para el fondo.
|
||||||
#[derive(AutoDefault)]
|
#[derive(AutoDefault)]
|
||||||
pub enum ColorBg {
|
pub enum ColorBg {
|
||||||
/// No define ninguna clase (devuelve `""` para facilitar la composición de clases).
|
/// No define ninguna clase.
|
||||||
#[default]
|
#[default]
|
||||||
Default,
|
Default,
|
||||||
/// Fondo predefinido del tema (`bg-body`).
|
/// Fondo predefinido del tema (`bg-body`).
|
||||||
|
|
@ -81,71 +140,12 @@ impl fmt::Display for ColorBg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// **< ColorBorder >********************************************************************************
|
|
||||||
|
|
||||||
/// Colores `border-*` para los bordes ([`Border`](crate::theme::aux::Border)).
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub enum ColorBorder {
|
|
||||||
/// No define ninguna clase (devuelve `""` para facilitar la composición de clases).
|
|
||||||
#[default]
|
|
||||||
Default,
|
|
||||||
/// Genera internamente clases `border-{color}`.
|
|
||||||
Theme(Color),
|
|
||||||
/// Genera internamente clases `border-{color}-subtle` (un tono suavizado del color).
|
|
||||||
Subtle(Color),
|
|
||||||
/// Color negro.
|
|
||||||
Black,
|
|
||||||
/// Color blanco.
|
|
||||||
White,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl fmt::Display for ColorBorder {
|
|
||||||
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"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< ColorButton >********************************************************************************
|
|
||||||
|
|
||||||
/// Variantes de color `btn-*` para botones.
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub enum ColorButton {
|
|
||||||
/// No define ninguna clase (devuelve `""` para facilitar la composición de clases).
|
|
||||||
#[default]
|
|
||||||
Default,
|
|
||||||
/// Genera internamente clases `btn-{color}` (botón relleno).
|
|
||||||
Background(Color),
|
|
||||||
/// Genera `btn-outline-{color}` (fondo transparente y contorno con borde).
|
|
||||||
Outline(Color),
|
|
||||||
/// Aplica estilo de los enlaces (`btn-link`), sin caja ni fondo, heredando el color de texto.
|
|
||||||
Link,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl fmt::Display for ColorButton {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Default => Ok(()),
|
|
||||||
Self::Background(c) => write!(f, "btn-{c}"),
|
|
||||||
Self::Outline(c) => write!(f, "btn-outline-{c}"),
|
|
||||||
Self::Link => f.write_str("btn-link"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< ColorText >**********************************************************************************
|
// **< ColorText >**********************************************************************************
|
||||||
|
|
||||||
/// Colores `text-*` para el texto.
|
/// Colores `text-*` para el texto.
|
||||||
#[derive(AutoDefault)]
|
#[derive(AutoDefault)]
|
||||||
pub enum ColorText {
|
pub enum ColorText {
|
||||||
/// No define ninguna clase (devuelve `""` para facilitar la composición de clases).
|
/// No define ninguna clase.
|
||||||
#[default]
|
#[default]
|
||||||
Default,
|
Default,
|
||||||
/// Color predefinido del tema (`text-body`).
|
/// Color predefinido del tema (`text-body`).
|
||||||
|
|
@ -182,135 +182,3 @@ impl fmt::Display for ColorText {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// **< Opacity >************************************************************************************
|
|
||||||
|
|
||||||
/// Niveles de opacidad (`opacity-*`).
|
|
||||||
///
|
|
||||||
/// Se usa normalmente para graduar la transparencia del color de fondo `bg-opacity-*`
|
|
||||||
/// ([`StyleBg`]), de los bordes `border-opacity-*` ([`StyleBorder`]) o del texto `text-opacity-*`
|
|
||||||
/// ([`StyleText`]).
|
|
||||||
#[rustfmt::skip]
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub enum Opacity {
|
|
||||||
/// Genera internamente clases `opacity-100` (100% de opacidad).
|
|
||||||
#[default]
|
|
||||||
Opaque,
|
|
||||||
/// Genera internamente clases `opacity-75` (75%).
|
|
||||||
SemiOpaque,
|
|
||||||
/// Genera internamente clases `opacity-50` (50%).
|
|
||||||
Half,
|
|
||||||
/// Genera internamente clases `opacity-25` (25%).
|
|
||||||
SemiTransparent,
|
|
||||||
/// Genera internamente clases `opacity-10` (10%).
|
|
||||||
AlmostTransparent,
|
|
||||||
/// Genera internamente clases `opacity-0` (0%, totalmente transparente).
|
|
||||||
Transparent,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl fmt::Display for Opacity {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Opaque => f.write_str("opacity-100"),
|
|
||||||
Self::SemiOpaque => f.write_str("opacity-75"),
|
|
||||||
Self::Half => f.write_str("opacity-50"),
|
|
||||||
Self::SemiTransparent => f.write_str("opacity-25"),
|
|
||||||
Self::AlmostTransparent => f.write_str("opacity-10"),
|
|
||||||
Self::Transparent => f.write_str("opacity-0"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< StyleBg >***********************************************************************************
|
|
||||||
|
|
||||||
/// Estilos de color/opacidad para el fondo.
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub enum StyleBg {
|
|
||||||
/// No define ninguna clase (devuelve `""` para facilitar la composición de clases).
|
|
||||||
#[default]
|
|
||||||
Default,
|
|
||||||
/// Genera internamente clases `bg-*`.
|
|
||||||
Color(ColorBg),
|
|
||||||
/// Genera internamente clases `bg-opacity-*`.
|
|
||||||
Opacity(Opacity),
|
|
||||||
/// Genera internamente clases `bg-* bg-opacity-*`.
|
|
||||||
Both(ColorBg, Opacity),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl fmt::Display for StyleBg {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Default => Ok(()),
|
|
||||||
Self::Color(c) => write!(f, "{c}"),
|
|
||||||
Self::Opacity(o) => write!(f, "bg-{o}"),
|
|
||||||
Self::Both(c, o) => write!(f, "{c} bg-{o}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< StyleBorder >*******************************************************************************
|
|
||||||
|
|
||||||
/// Estilos de color/opacidad para los bordes ([`Border`](crate::theme::aux::Border)).
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub enum StyleBorder {
|
|
||||||
/// No define ninguna clase (devuelve `""` para facilitar la composición de clases).
|
|
||||||
#[default]
|
|
||||||
Default,
|
|
||||||
/// Genera internamente clases `border-*`.
|
|
||||||
Color(ColorBorder),
|
|
||||||
/// Genera internamente clases `border-opacity-*`.
|
|
||||||
Opacity(Opacity),
|
|
||||||
/// Genera internamente clases `border-* border-opacity-*`.
|
|
||||||
Both(ColorBorder, Opacity),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl fmt::Display for StyleBorder {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Default => Ok(()),
|
|
||||||
Self::Color(c) => write!(f, "{c}"),
|
|
||||||
Self::Opacity(o) => write!(f, "border-{o}"),
|
|
||||||
Self::Both(c, o) => write!(f, "{c} border-{o}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< StyleText >*********************************************************************************
|
|
||||||
|
|
||||||
/// Estilos de color/opacidad para texto y fondo del texto.
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub enum StyleText {
|
|
||||||
/// No define ninguna clase (devuelve `""` para facilitar la composición de clases).
|
|
||||||
#[default]
|
|
||||||
Default,
|
|
||||||
/// Genera internamente clases `text-*`.
|
|
||||||
Color(ColorText),
|
|
||||||
/// Genera internamente clases `text-opacity-*`.
|
|
||||||
Opacity(Opacity),
|
|
||||||
/// Genera internamente clases `text-* text-opacity-*`.
|
|
||||||
Both(ColorText, Opacity),
|
|
||||||
/// Genera internamente clases `text-bg-*` (para el color de fondo del texto).
|
|
||||||
Bg(Color),
|
|
||||||
/// Genera internamente clases `text-bg-* text-*`.
|
|
||||||
BgAndColor(Color, ColorText),
|
|
||||||
/// Genera internamente clases `text-bg-* text-* text-opacity-*`.
|
|
||||||
All(Color, ColorText, Opacity),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl fmt::Display for StyleText {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Default => Ok(()),
|
|
||||||
Self::Color(c) => write!(f, "{c}"),
|
|
||||||
Self::Opacity(o) => write!(f, "text-{o}"),
|
|
||||||
Self::Both(c, o) => write!(f, "{c} text-{o}"),
|
|
||||||
Self::Bg(bg) => write!(f, "text-bg-{bg}"),
|
|
||||||
Self::BgAndColor(bg, c) => write!(f, "text-bg-{bg} {c}"),
|
|
||||||
Self::All(bg, c, o) => write!(f, "text-bg-{bg} {c} text-{o}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,11 @@ use pagetop::prelude::*;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
// **< RoundedRadius >******************************************************************************
|
/// Radio para el redondeo de esquinas ([`classes::Rounded`](crate::theme::classes::Rounded)).
|
||||||
|
|
||||||
/// Radio para el redondeo de esquinas ([`Rounded`]).
|
|
||||||
///
|
///
|
||||||
/// Mapea a `rounded`, `rounded-0`, `rounded-{1..5}`, `rounded-circle` y `rounded-pill`.
|
/// Mapea a `rounded`, `rounded-0`, `rounded-{1..5}`, `rounded-circle` y `rounded-pill`.
|
||||||
///
|
///
|
||||||
/// - `None` no añade clase (devuelve `""`).
|
/// - `None` no añade ninguna clase.
|
||||||
/// - `Default` genera `rounded` (radio por defecto del tema).
|
/// - `Default` genera `rounded` (radio por defecto del tema).
|
||||||
/// - `Zero` genera `rounded-0` (sin redondeo).
|
/// - `Zero` genera `rounded-0` (sin redondeo).
|
||||||
/// - `Scale{1..5}` genera `rounded-{1..5}` (radio creciente).
|
/// - `Scale{1..5}` genera `rounded-{1..5}` (radio creciente).
|
||||||
|
|
@ -31,18 +29,18 @@ pub enum RoundedRadius {
|
||||||
|
|
||||||
impl RoundedRadius {
|
impl RoundedRadius {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
fn to_class(&self, base: impl AsRef<str>) -> String {
|
pub(crate) fn to_class(&self, prefix: impl AsRef<str>) -> String {
|
||||||
match self {
|
match self {
|
||||||
RoundedRadius::None => String::new(),
|
RoundedRadius::None => String::new(),
|
||||||
RoundedRadius::Default => String::from(base.as_ref()),
|
RoundedRadius::Default => String::from(prefix.as_ref()),
|
||||||
RoundedRadius::Zero => join!(base, "-0"),
|
RoundedRadius::Zero => join!(prefix, "-0"),
|
||||||
RoundedRadius::Scale1 => join!(base, "-1"),
|
RoundedRadius::Scale1 => join!(prefix, "-1"),
|
||||||
RoundedRadius::Scale2 => join!(base, "-2"),
|
RoundedRadius::Scale2 => join!(prefix, "-2"),
|
||||||
RoundedRadius::Scale3 => join!(base, "-3"),
|
RoundedRadius::Scale3 => join!(prefix, "-3"),
|
||||||
RoundedRadius::Scale4 => join!(base, "-4"),
|
RoundedRadius::Scale4 => join!(prefix, "-4"),
|
||||||
RoundedRadius::Scale5 => join!(base, "-5"),
|
RoundedRadius::Scale5 => join!(prefix, "-5"),
|
||||||
RoundedRadius::Circle => join!(base, "-circle"),
|
RoundedRadius::Circle => join!(prefix, "-circle"),
|
||||||
RoundedRadius::Pill => join!(base, "-pill"),
|
RoundedRadius::Pill => join!(prefix, "-pill"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -52,163 +50,3 @@ impl fmt::Display for RoundedRadius {
|
||||||
write!(f, "{}", self.to_class("rounded"))
|
write!(f, "{}", self.to_class("rounded"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// **< Rounded >************************************************************************************
|
|
||||||
|
|
||||||
/// Agrupa propiedades para crear **esquinas redondeadas**.
|
|
||||||
///
|
|
||||||
/// Permite:
|
|
||||||
///
|
|
||||||
/// - Definir un radio **global para todas las esquinas** (`radius`).
|
|
||||||
/// - Ajustar el radio asociado a las **esquinas de cada lado lógico** (`top`, `end`, `bottom`,
|
|
||||||
/// `start`, **en este orden**, respetando LTR/RTL).
|
|
||||||
/// - Ajustar el radio de las **esquinas concretas** (`top-start`, `top-end`, `bottom-start`,
|
|
||||||
/// `bottom-end`, **en este orden**, respetando LTR/RTL).
|
|
||||||
///
|
|
||||||
/// # Ejemplos
|
|
||||||
///
|
|
||||||
/// **Radio global:**
|
|
||||||
/// ```rust
|
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
|
||||||
/// let r = Rounded::with(RoundedRadius::Default);
|
|
||||||
/// assert_eq!(r.to_string(), "rounded");
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// **Sin redondeo:**
|
|
||||||
/// ```rust
|
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
|
||||||
/// let r = Rounded::new();
|
|
||||||
/// assert_eq!(r.to_string(), "");
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// **Radio en las esquinas de un lado lógico:**
|
|
||||||
/// ```rust
|
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
|
||||||
/// let r = Rounded::new().with_end(RoundedRadius::Scale2);
|
|
||||||
/// assert_eq!(r.to_string(), "rounded-end-2");
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// **Radio en una esquina concreta:**
|
|
||||||
/// ```rust
|
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
|
||||||
/// let r = Rounded::new().with_top_start(RoundedRadius::Scale3);
|
|
||||||
/// assert_eq!(r.to_string(), "rounded-top-start-3");
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// **Combinado (ejemplo completo):**
|
|
||||||
/// ```rust
|
|
||||||
/// # use pagetop_bootsier::prelude::*;
|
|
||||||
/// let r = Rounded::new()
|
|
||||||
/// .with_top(RoundedRadius::Default) // Añade redondeo arriba.
|
|
||||||
/// .with_bottom_start(RoundedRadius::Scale4) // Añade una esquina redondeada concreta.
|
|
||||||
/// .with_bottom_end(RoundedRadius::Circle); // Añade redondeo extremo en otra esquina.
|
|
||||||
///
|
|
||||||
/// assert_eq!(r.to_string(), "rounded-top rounded-bottom-start-4 rounded-bottom-end-circle");
|
|
||||||
/// ```
|
|
||||||
#[rustfmt::skip]
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub struct Rounded {
|
|
||||||
radius : RoundedRadius,
|
|
||||||
top : RoundedRadius,
|
|
||||||
end : RoundedRadius,
|
|
||||||
bottom : RoundedRadius,
|
|
||||||
start : RoundedRadius,
|
|
||||||
top_start : RoundedRadius,
|
|
||||||
top_end : RoundedRadius,
|
|
||||||
bottom_start: RoundedRadius,
|
|
||||||
bottom_end : RoundedRadius,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Rounded {
|
|
||||||
/// Prepara las esquinas **sin redondeo global** de partida.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Crea las esquinas **con redondeo global** (`radius`).
|
|
||||||
pub fn with(radius: RoundedRadius) -> Self {
|
|
||||||
Self::default().with_radius(radius)
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< Rounded BUILDER >************************************************************************
|
|
||||||
|
|
||||||
/// Establece el radio global de las esquinas (`rounded*`).
|
|
||||||
pub fn with_radius(mut self, radius: RoundedRadius) -> Self {
|
|
||||||
self.radius = radius;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el radio en las esquinas del lado superior (`rounded-top-*`).
|
|
||||||
pub fn with_top(mut self, radius: RoundedRadius) -> Self {
|
|
||||||
self.top = radius;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el radio en las esquinas del lado lógico final (`rounded-end-*`). Respeta LTR/RTL.
|
|
||||||
pub fn with_end(mut self, radius: RoundedRadius) -> Self {
|
|
||||||
self.end = radius;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el radio en las esquinas del lado inferior (`rounded-bottom-*`).
|
|
||||||
pub fn with_bottom(mut self, radius: RoundedRadius) -> Self {
|
|
||||||
self.bottom = radius;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el radio en las esquinas del lado lógico inicial (`rounded-start-*`). Respeta
|
|
||||||
/// LTR/RTL.
|
|
||||||
pub fn with_start(mut self, radius: RoundedRadius) -> Self {
|
|
||||||
self.start = radius;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el radio en la esquina superior-inicial (`rounded-top-start-*`). Respeta LTR/RTL.
|
|
||||||
pub fn with_top_start(mut self, radius: RoundedRadius) -> Self {
|
|
||||||
self.top_start = radius;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el radio en la esquina superior-final (`rounded-top-end-*`). Respeta LTR/RTL.
|
|
||||||
pub fn with_top_end(mut self, radius: RoundedRadius) -> Self {
|
|
||||||
self.top_end = radius;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el radio en la esquina inferior-inicial (`rounded-bottom-start-*`). Respeta
|
|
||||||
/// LTR/RTL.
|
|
||||||
pub fn with_bottom_start(mut self, radius: RoundedRadius) -> Self {
|
|
||||||
self.bottom_start = radius;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el radio en la esquina inferior-final (`rounded-bottom-end-*`). Respeta LTR/RTL.
|
|
||||||
pub fn with_bottom_end(mut self, radius: RoundedRadius) -> Self {
|
|
||||||
self.bottom_end = radius;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Rounded {
|
|
||||||
/// Concatena cada definición en el orden: *global*, `top`, `end`, `bottom`, `start`,
|
|
||||||
/// `top-start`, `top-end`, `bottom-start` y `bottom-end`; respetando LTR/RTL y omitiendo las
|
|
||||||
/// definiciones vacías.
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}",
|
|
||||||
join_opt!([
|
|
||||||
self.radius.to_string(),
|
|
||||||
self.top.to_class("rounded-top"),
|
|
||||||
self.end.to_class("rounded-end"),
|
|
||||||
self.bottom.to_class("rounded-bottom"),
|
|
||||||
self.start.to_class("rounded-start"),
|
|
||||||
self.top_start.to_class("rounded-top-start"),
|
|
||||||
self.top_end.to_class("rounded-top-end"),
|
|
||||||
self.bottom_start.to_class("rounded-bottom-start"),
|
|
||||||
self.bottom_end.to_class("rounded-bottom-end"),
|
|
||||||
]; " ")
|
|
||||||
.unwrap_or_default()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
use pagetop::prelude::*;
|
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
// **< ButtonSize >*********************************************************************************
|
|
||||||
|
|
||||||
/// Tamaño visual de un botón.
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub enum ButtonSize {
|
|
||||||
/// Tamaño por defecto del tema (no añade clase).
|
|
||||||
#[default]
|
|
||||||
Default,
|
|
||||||
/// Botón compacto.
|
|
||||||
Small,
|
|
||||||
/// Botón destacado/grande.
|
|
||||||
Large,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl fmt::Display for ButtonSize {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Default => Ok(()),
|
|
||||||
Self::Small => f.write_str("btn-sm"),
|
|
||||||
Self::Large => f.write_str("btn-lg"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
10
extensions/pagetop-bootsier/src/theme/classes.rs
Normal file
10
extensions/pagetop-bootsier/src/theme/classes.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
//! Conjunto de clases para aplicar en componentes del tema.
|
||||||
|
|
||||||
|
mod color;
|
||||||
|
pub use color::{Background, Text};
|
||||||
|
|
||||||
|
mod border;
|
||||||
|
pub use border::Border;
|
||||||
|
|
||||||
|
mod rounded;
|
||||||
|
pub use rounded::Rounded;
|
||||||
155
extensions/pagetop-bootsier/src/theme/classes/border.rs
Normal file
155
extensions/pagetop-bootsier/src/theme/classes/border.rs
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
use crate::theme::aux::{BorderColor, BorderSize, Opacity};
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// Clases para crear **bordes**.
|
||||||
|
///
|
||||||
|
/// Permite:
|
||||||
|
///
|
||||||
|
/// - Definir un tamaño **global** para todo el borde (`size`).
|
||||||
|
/// - Ajustar el tamaño de cada **lado lógico** (`top`, `end`, `bottom`, `start`, **en este orden**,
|
||||||
|
/// respetando LTR/RTL).
|
||||||
|
/// - Aplicar un **color** al borde (`BorderColor`).
|
||||||
|
/// - Aplicar un nivel de **opacidad** (`Opacity`).
|
||||||
|
///
|
||||||
|
/// # Comportamiento aditivo / sustractivo
|
||||||
|
///
|
||||||
|
/// - **Aditivo**: basta con crear un borde sin tamaño con `classes::Border::new()` para ir
|
||||||
|
/// añadiendo cada lado lógico con el tamaño deseado usando `BorderSize::Scale{1..5}`.
|
||||||
|
///
|
||||||
|
/// - **Sustractivo**: se crea un borde con tamaño predefinido, p. ej. utilizando
|
||||||
|
/// `classes::Border::with(BorderSize::Scale2)` y eliminar los lados deseados con `BorderSize::Zero`.
|
||||||
|
///
|
||||||
|
/// - **Anchos diferentes por lado**: usando `BorderSize::Scale{1..5}` en cada lado deseado.
|
||||||
|
///
|
||||||
|
/// # Ejemplos
|
||||||
|
///
|
||||||
|
/// **Borde global:**
|
||||||
|
/// ```rust
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let b = classes::Border::with(BorderSize::Scale2);
|
||||||
|
/// assert_eq!(b.to_string(), "border-2");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// **Aditivo (solo borde superior):**
|
||||||
|
/// ```rust
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let b = classes::Border::new().with_top(BorderSize::Scale1);
|
||||||
|
/// assert_eq!(b.to_string(), "border-top-1");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// **Sustractivo (borde global menos el superior):**
|
||||||
|
/// ```rust
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let b = classes::Border::with(BorderSize::Default).with_top(BorderSize::Zero);
|
||||||
|
/// assert_eq!(b.to_string(), "border border-top-0");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// **Ancho por lado (lado lógico inicial a 2 y final a 4):**
|
||||||
|
/// ```rust
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let b = classes::Border::new().with_start(BorderSize::Scale2).with_end(BorderSize::Scale4);
|
||||||
|
/// assert_eq!(b.to_string(), "border-end-4 border-start-2");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// **Combinado (ejemplo completo):**
|
||||||
|
/// ```rust
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let b = classes::Border::with(BorderSize::Default) // Borde global por defecto.
|
||||||
|
/// .with_top(BorderSize::Zero) // Quita borde superior.
|
||||||
|
/// .with_end(BorderSize::Scale3) // Ancho 3 para el lado lógico final.
|
||||||
|
/// .with_color(BorderColor::Theme(Color::Primary))
|
||||||
|
/// .with_opacity(Opacity::Half);
|
||||||
|
///
|
||||||
|
/// assert_eq!(b.to_string(), "border border-top-0 border-end-3 border-primary border-opacity-50");
|
||||||
|
/// ```
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub struct Border {
|
||||||
|
size : BorderSize,
|
||||||
|
top : BorderSize,
|
||||||
|
end : BorderSize,
|
||||||
|
bottom : BorderSize,
|
||||||
|
start : BorderSize,
|
||||||
|
color : BorderColor,
|
||||||
|
opacity: Opacity,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Border {
|
||||||
|
/// Prepara un borde **sin tamaño global** de partida.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crea un borde **con tamaño global** (`size`).
|
||||||
|
pub fn with(size: BorderSize) -> Self {
|
||||||
|
Self::default().with_size(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Border BUILDER >*************************************************************************
|
||||||
|
|
||||||
|
/// Establece el tamaño global del borde (`border*`).
|
||||||
|
pub fn with_size(mut self, size: BorderSize) -> Self {
|
||||||
|
self.size = size;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el tamaño del borde superior (`border-top-*`).
|
||||||
|
pub fn with_top(mut self, size: BorderSize) -> Self {
|
||||||
|
self.top = size;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el tamaño del borde en el lado lógico final (`border-end-*`). Respeta LTR/RTL.
|
||||||
|
pub fn with_end(mut self, size: BorderSize) -> Self {
|
||||||
|
self.end = size;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el tamaño del borde inferior (`border-bottom-*`).
|
||||||
|
pub fn with_bottom(mut self, size: BorderSize) -> Self {
|
||||||
|
self.bottom = size;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el tamaño del borde en el lado lógico inicial (`border-start-*`). Respeta LTR/RTL.
|
||||||
|
pub fn with_start(mut self, size: BorderSize) -> Self {
|
||||||
|
self.start = size;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el color del borde.
|
||||||
|
pub fn with_color(mut self, color: BorderColor) -> Self {
|
||||||
|
self.color = color;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece la opacidad del borde.
|
||||||
|
pub fn with_opacity(mut self, opacity: Opacity) -> Self {
|
||||||
|
self.opacity = opacity;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Border {
|
||||||
|
/// Concatena, en este orden, las clases para *global*, `top`, `end`, `bottom`, `start`, *color*
|
||||||
|
/// y *opacidad*; respetando LTR/RTL y omitiendo las definiciones vacías.
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
[
|
||||||
|
self.size.to_string(),
|
||||||
|
self.top.to_class("border-top"),
|
||||||
|
self.end.to_class("border-end"),
|
||||||
|
self.bottom.to_class("border-bottom"),
|
||||||
|
self.start.to_class("border-start"),
|
||||||
|
self.color.to_string(),
|
||||||
|
self.opacity.to_class("border"),
|
||||||
|
]
|
||||||
|
.join_classes()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
207
extensions/pagetop-bootsier/src/theme/classes/color.rs
Normal file
207
extensions/pagetop-bootsier/src/theme/classes/color.rs
Normal file
|
|
@ -0,0 +1,207 @@
|
||||||
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
use crate::theme::aux::{ColorBg, ColorText, Opacity};
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
// **< Bg >*****************************************************************************************
|
||||||
|
|
||||||
|
/// Clases para establecer **color/opacidad del fondo**.
|
||||||
|
///
|
||||||
|
/// # Ejemplos
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// // Sin clases.
|
||||||
|
/// let s = classes::Background::new();
|
||||||
|
/// assert_eq!(s.to_string(), "");
|
||||||
|
///
|
||||||
|
/// // Sólo color de fondo.
|
||||||
|
/// let s = classes::Background::with(ColorBg::Theme(Color::Primary));
|
||||||
|
/// assert_eq!(s.to_string(), "bg-primary");
|
||||||
|
///
|
||||||
|
/// // Color más opacidad.
|
||||||
|
/// let s = classes::Background::with(ColorBg::BodySecondary).with_opacity(Opacity::Half);
|
||||||
|
/// assert_eq!(s.to_string(), "bg-body-secondary bg-opacity-50");
|
||||||
|
///
|
||||||
|
/// // Usando `From<ColorBg>`.
|
||||||
|
/// let s: classes::Background = ColorBg::Black.into();
|
||||||
|
/// assert_eq!(s.to_string(), "bg-black");
|
||||||
|
///
|
||||||
|
/// // Usando `From<(ColorBg, Opacity)>`.
|
||||||
|
/// let s: classes::Background = (ColorBg::White, Opacity::SemiTransparent).into();
|
||||||
|
/// assert_eq!(s.to_string(), "bg-white bg-opacity-25");
|
||||||
|
/// ```
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub struct Background {
|
||||||
|
color : ColorBg,
|
||||||
|
opacity: Opacity,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Background {
|
||||||
|
/// Prepara un nuevo estilo para aplicar al fondo.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crea un estilo fijando el color de fondo (`bg-*`).
|
||||||
|
pub fn with(color: ColorBg) -> Self {
|
||||||
|
Self::default().with_color(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Bg BUILDER >*****************************************************************************
|
||||||
|
|
||||||
|
/// Establece el color de fondo (`bg-*`).
|
||||||
|
pub fn with_color(mut self, color: ColorBg) -> Self {
|
||||||
|
self.color = color;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece la opacidad del fondo (`bg-opacity-*`).
|
||||||
|
pub fn with_opacity(mut self, opacity: Opacity) -> Self {
|
||||||
|
self.opacity = opacity;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Background {
|
||||||
|
/// Concatena, en este orden, color del fondo (`bg-*`) y opacidad (`bg-opacity-*`), omitiendo
|
||||||
|
/// las definiciones vacías.
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let classes = [self.color.to_string(), self.opacity.to_class("bg")].join_classes();
|
||||||
|
write!(f, "{classes}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(ColorBg, Opacity)> for Background {
|
||||||
|
/// Atajo para crear un [`classes::Background`](crate::theme::classes::Background) a partir del color de fondo y
|
||||||
|
/// la opacidad.
|
||||||
|
///
|
||||||
|
/// # Ejemplo
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let s: classes::Background = (ColorBg::White, Opacity::SemiTransparent).into();
|
||||||
|
/// assert_eq!(s.to_string(), "bg-white bg-opacity-25");
|
||||||
|
/// ```
|
||||||
|
fn from((color, opacity): (ColorBg, Opacity)) -> Self {
|
||||||
|
Background::with(color).with_opacity(opacity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ColorBg> for Background {
|
||||||
|
/// Atajo para crear un [`classes::Background`](crate::theme::classes::Background) a partir del color de fondo.
|
||||||
|
///
|
||||||
|
/// # Ejemplo
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let s: classes::Background = ColorBg::Black.into();
|
||||||
|
/// assert_eq!(s.to_string(), "bg-black");
|
||||||
|
/// ```
|
||||||
|
fn from(color: ColorBg) -> Self {
|
||||||
|
Background::with(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Text >***************************************************************************************
|
||||||
|
|
||||||
|
/// Clases para establecer **color/opacidad del texto**.
|
||||||
|
///
|
||||||
|
/// # Ejemplos
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// // Sin clases.
|
||||||
|
/// let s = classes::Text::new();
|
||||||
|
/// assert_eq!(s.to_string(), "");
|
||||||
|
///
|
||||||
|
/// // Sólo color del texto.
|
||||||
|
/// let s = classes::Text::with(ColorText::Theme(Color::Primary));
|
||||||
|
/// assert_eq!(s.to_string(), "text-primary");
|
||||||
|
///
|
||||||
|
/// // Color del texto y opacidad.
|
||||||
|
/// let s = classes::Text::new().with_color(ColorText::White).with_opacity(Opacity::SemiTransparent);
|
||||||
|
/// assert_eq!(s.to_string(), "text-white text-opacity-25");
|
||||||
|
///
|
||||||
|
/// // Usando `From<ColorText>`.
|
||||||
|
/// let s: classes::Text = ColorText::Black.into();
|
||||||
|
/// assert_eq!(s.to_string(), "text-black");
|
||||||
|
///
|
||||||
|
/// // Usando `From<(ColorText, Opacity)>`.
|
||||||
|
/// let s: classes::Text = (ColorText::Theme(Color::Danger), Opacity::Opaque).into();
|
||||||
|
/// assert_eq!(s.to_string(), "text-danger text-opacity-100");
|
||||||
|
/// ```
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub struct Text {
|
||||||
|
color : ColorText,
|
||||||
|
opacity: Opacity,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Text {
|
||||||
|
/// Prepara un nuevo estilo para aplicar al texto.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crea un estilo fijando el color del texto (`text-*`).
|
||||||
|
pub fn with(color: ColorText) -> Self {
|
||||||
|
Self::default().with_color(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Text BUILDER >***************************************************************************
|
||||||
|
|
||||||
|
/// Establece el color del texto (`text-*`).
|
||||||
|
pub fn with_color(mut self, color: ColorText) -> Self {
|
||||||
|
self.color = color;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece la opacidad del texto (`text-opacity-*`).
|
||||||
|
pub fn with_opacity(mut self, opacity: Opacity) -> Self {
|
||||||
|
self.opacity = opacity;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Text {
|
||||||
|
/// Concatena, en este orden, `text-*` y `text-opacity-*`, omitiendo las definiciones vacías.
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let classes = [self.color.to_string(), self.opacity.to_class("text")].join_classes();
|
||||||
|
write!(f, "{classes}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(ColorText, Opacity)> for Text {
|
||||||
|
/// Atajo para crear un [`classes::Text`](crate::theme::classes::Text) a partir del color del
|
||||||
|
/// texto y su opacidad.
|
||||||
|
///
|
||||||
|
/// # Ejemplo
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let s: classes::Text = (ColorText::Theme(Color::Danger), Opacity::Opaque).into();
|
||||||
|
/// assert_eq!(s.to_string(), "text-danger text-opacity-100");
|
||||||
|
/// ```
|
||||||
|
fn from((color, opacity): (ColorText, Opacity)) -> Self {
|
||||||
|
Text::with(color).with_opacity(opacity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ColorText> for Text {
|
||||||
|
/// Atajo para crear un [`classes::Text`](crate::theme::classes::Text) a partir del color del
|
||||||
|
/// texto.
|
||||||
|
///
|
||||||
|
/// # Ejemplo
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let s: classes::Text = ColorText::Black.into();
|
||||||
|
/// assert_eq!(s.to_string(), "text-black");
|
||||||
|
/// ```
|
||||||
|
fn from(color: ColorText) -> Self {
|
||||||
|
Text::with(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
163
extensions/pagetop-bootsier/src/theme/classes/rounded.rs
Normal file
163
extensions/pagetop-bootsier/src/theme/classes/rounded.rs
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
use crate::theme::aux::RoundedRadius;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// Clases para definir **esquinas redondeadas**.
|
||||||
|
///
|
||||||
|
/// Permite:
|
||||||
|
///
|
||||||
|
/// - Definir un radio **global para todas las esquinas** (`radius`).
|
||||||
|
/// - Ajustar el radio asociado a las **esquinas de cada lado lógico** (`top`, `end`, `bottom`,
|
||||||
|
/// `start`, **en este orden**, respetando LTR/RTL).
|
||||||
|
/// - Ajustar el radio de las **esquinas concretas** (`top-start`, `top-end`, `bottom-start`,
|
||||||
|
/// `bottom-end`, **en este orden**, respetando LTR/RTL).
|
||||||
|
///
|
||||||
|
/// # Ejemplos
|
||||||
|
///
|
||||||
|
/// **Radio global:**
|
||||||
|
/// ```rust
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let r = classes::Rounded::with(RoundedRadius::Default);
|
||||||
|
/// assert_eq!(r.to_string(), "rounded");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// **Sin redondeo:**
|
||||||
|
/// ```rust
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let r = classes::Rounded::new();
|
||||||
|
/// assert_eq!(r.to_string(), "");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// **Radio en las esquinas de un lado lógico:**
|
||||||
|
/// ```rust
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let r = classes::Rounded::new().with_end(RoundedRadius::Scale2);
|
||||||
|
/// assert_eq!(r.to_string(), "rounded-end-2");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// **Radio en una esquina concreta:**
|
||||||
|
/// ```rust
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let r = classes::Rounded::new().with_top_start(RoundedRadius::Scale3);
|
||||||
|
/// assert_eq!(r.to_string(), "rounded-top-start-3");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// **Combinado (ejemplo completo):**
|
||||||
|
/// ```rust
|
||||||
|
/// # use pagetop_bootsier::prelude::*;
|
||||||
|
/// let r = classes::Rounded::new()
|
||||||
|
/// .with_top(RoundedRadius::Default) // Añade redondeo arriba.
|
||||||
|
/// .with_bottom_start(RoundedRadius::Scale4) // Añade una esquina redondeada concreta.
|
||||||
|
/// .with_bottom_end(RoundedRadius::Circle); // Añade redondeo extremo en otra esquina.
|
||||||
|
///
|
||||||
|
/// assert_eq!(r.to_string(), "rounded-top rounded-bottom-start-4 rounded-bottom-end-circle");
|
||||||
|
/// ```
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub struct Rounded {
|
||||||
|
radius : RoundedRadius,
|
||||||
|
top : RoundedRadius,
|
||||||
|
end : RoundedRadius,
|
||||||
|
bottom : RoundedRadius,
|
||||||
|
start : RoundedRadius,
|
||||||
|
top_start : RoundedRadius,
|
||||||
|
top_end : RoundedRadius,
|
||||||
|
bottom_start: RoundedRadius,
|
||||||
|
bottom_end : RoundedRadius,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rounded {
|
||||||
|
/// Prepara las esquinas **sin redondeo global** de partida.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crea las esquinas **con redondeo global** (`radius`).
|
||||||
|
pub fn with(radius: RoundedRadius) -> Self {
|
||||||
|
Self::default().with_radius(radius)
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Rounded BUILDER >************************************************************************
|
||||||
|
|
||||||
|
/// Establece el radio global de las esquinas (`rounded*`).
|
||||||
|
pub fn with_radius(mut self, radius: RoundedRadius) -> Self {
|
||||||
|
self.radius = radius;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el radio en las esquinas del lado superior (`rounded-top-*`).
|
||||||
|
pub fn with_top(mut self, radius: RoundedRadius) -> Self {
|
||||||
|
self.top = radius;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el radio en las esquinas del lado lógico final (`rounded-end-*`). Respeta LTR/RTL.
|
||||||
|
pub fn with_end(mut self, radius: RoundedRadius) -> Self {
|
||||||
|
self.end = radius;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el radio en las esquinas del lado inferior (`rounded-bottom-*`).
|
||||||
|
pub fn with_bottom(mut self, radius: RoundedRadius) -> Self {
|
||||||
|
self.bottom = radius;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el radio en las esquinas del lado lógico inicial (`rounded-start-*`). Respeta
|
||||||
|
/// LTR/RTL.
|
||||||
|
pub fn with_start(mut self, radius: RoundedRadius) -> Self {
|
||||||
|
self.start = radius;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el radio en la esquina superior-inicial (`rounded-top-start-*`). Respeta LTR/RTL.
|
||||||
|
pub fn with_top_start(mut self, radius: RoundedRadius) -> Self {
|
||||||
|
self.top_start = radius;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el radio en la esquina superior-final (`rounded-top-end-*`). Respeta LTR/RTL.
|
||||||
|
pub fn with_top_end(mut self, radius: RoundedRadius) -> Self {
|
||||||
|
self.top_end = radius;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el radio en la esquina inferior-inicial (`rounded-bottom-start-*`). Respeta
|
||||||
|
/// LTR/RTL.
|
||||||
|
pub fn with_bottom_start(mut self, radius: RoundedRadius) -> Self {
|
||||||
|
self.bottom_start = radius;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el radio en la esquina inferior-final (`rounded-bottom-end-*`). Respeta LTR/RTL.
|
||||||
|
pub fn with_bottom_end(mut self, radius: RoundedRadius) -> Self {
|
||||||
|
self.bottom_end = radius;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Rounded {
|
||||||
|
/// Concatena, en este orden, las clases para *global*, `top`, `end`, `bottom`, `start`,
|
||||||
|
/// `top-start`, `top-end`, `bottom-start` y `bottom-end`; respetando LTR/RTL y omitiendo las
|
||||||
|
/// definiciones vacías.
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
[
|
||||||
|
self.radius.to_string(),
|
||||||
|
self.top.to_class("rounded-top"),
|
||||||
|
self.end.to_class("rounded-end"),
|
||||||
|
self.bottom.to_class("rounded-bottom"),
|
||||||
|
self.start.to_class("rounded-start"),
|
||||||
|
self.top_start.to_class("rounded-top-start"),
|
||||||
|
self.top_end.to_class("rounded-top-end"),
|
||||||
|
self.bottom_start.to_class("rounded-bottom-start"),
|
||||||
|
self.bottom_end.to_class("rounded-bottom-end"),
|
||||||
|
]
|
||||||
|
.join_classes()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,299 +1,24 @@
|
||||||
use pagetop::prelude::*;
|
//! Definiciones para crear contenedores de componentes ([`Container`]).
|
||||||
|
//!
|
||||||
|
//! Cada contenedor envuelve contenido usando la etiqueta semántica indicada por
|
||||||
|
//! [`container::Kind`](crate::theme::container::Kind).
|
||||||
|
//!
|
||||||
|
//! Con [`container::Width`](crate::theme::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.
|
||||||
|
//!
|
||||||
|
//! # Ejemplo
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! # use pagetop::prelude::*;
|
||||||
|
//! # use pagetop_bootsier::prelude::*;
|
||||||
|
//! let main = Container::main()
|
||||||
|
//! .with_id("main-page")
|
||||||
|
//! .with_width(container::Width::From(BreakPoint::LG));
|
||||||
|
//! ```
|
||||||
|
|
||||||
use crate::prelude::*;
|
mod props;
|
||||||
|
pub use props::{Kind, Width};
|
||||||
|
|
||||||
// **< ContainerType >******************************************************************************
|
mod component;
|
||||||
|
pub use component::Container;
|
||||||
/// Tipo de contenedor ([`Container`]).
|
|
||||||
///
|
|
||||||
/// Permite aplicar la etiqueta HTML apropiada (`<main>`, `<header>`, etc.) manteniendo una API
|
|
||||||
/// común a todos los contenedores.
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub enum ContainerType {
|
|
||||||
/// Contenedor genérico (`<div>`).
|
|
||||||
#[default]
|
|
||||||
Default,
|
|
||||||
/// Contenido principal de la página (`<main>`).
|
|
||||||
Main,
|
|
||||||
/// Encabezado de la página o de sección (`<header>`).
|
|
||||||
Header,
|
|
||||||
/// Pie de la página o de sección (`<footer>`).
|
|
||||||
Footer,
|
|
||||||
/// Sección de contenido (`<section>`).
|
|
||||||
Section,
|
|
||||||
/// Artículo de contenido (`<article>`).
|
|
||||||
Article,
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< ContainerWidth >*****************************************************************************
|
|
||||||
|
|
||||||
/// Define el comportamiento para ajustar el ancho de un contenedor ([`Container`]).
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub enum ContainerWidth {
|
|
||||||
/// Comportamiento por defecto, aplica los anchos máximos predefinidos para cada punto de
|
|
||||||
/// ruptura. Por debajo del menor punto de ruptura ocupa el 100% del ancho disponible.
|
|
||||||
#[default]
|
|
||||||
Default,
|
|
||||||
/// Aplica los anchos máximos predefinidos a partir del punto de ruptura indicado. Por debajo de
|
|
||||||
/// ese punto de ruptura ocupa el 100% del ancho disponible.
|
|
||||||
From(BreakPoint),
|
|
||||||
/// Ocupa el 100% del ancho disponible siempre.
|
|
||||||
Fluid,
|
|
||||||
/// Ocupa el 100% del ancho disponible hasta un ancho máximo explícito.
|
|
||||||
FluidMax(UnitValue),
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< Container >**********************************************************************************
|
|
||||||
|
|
||||||
/// Componente para crear un **contenedor de componentes**.
|
|
||||||
///
|
|
||||||
/// Envuelve el contenido con la etiqueta HTML indicada por [`ContainerType`]. Sólo se renderiza si
|
|
||||||
/// existen componentes hijos (*children*).
|
|
||||||
#[rustfmt::skip]
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub struct Container {
|
|
||||||
id : AttrId,
|
|
||||||
classes : AttrClasses,
|
|
||||||
container_type : ContainerType,
|
|
||||||
container_width: ContainerWidth,
|
|
||||||
style_bg : StyleBg,
|
|
||||||
style_text : StyleText,
|
|
||||||
border : Border,
|
|
||||||
rounded : Rounded,
|
|
||||||
children : Children,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Component for Container {
|
|
||||||
fn new() -> Self {
|
|
||||||
Container::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id(&self) -> Option<String> {
|
|
||||||
self.id.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
|
||||||
self.alter_classes(
|
|
||||||
ClassesOp::Prepend,
|
|
||||||
[
|
|
||||||
join_pair!(
|
|
||||||
"container",
|
|
||||||
"-",
|
|
||||||
match self.width() {
|
|
||||||
ContainerWidth::Default => String::new(),
|
|
||||||
ContainerWidth::From(bp) => bp.to_string(),
|
|
||||||
ContainerWidth::Fluid => "fluid".to_string(),
|
|
||||||
ContainerWidth::FluidMax(_) => "fluid".to_string(),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
self.style_bg().to_string(),
|
|
||||||
self.style_text().to_string(),
|
|
||||||
self.border().to_string(),
|
|
||||||
self.rounded().to_string(),
|
|
||||||
]
|
|
||||||
.join(" "),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
|
||||||
let output = self.children().render(cx);
|
|
||||||
if output.is_empty() {
|
|
||||||
return PrepareMarkup::None;
|
|
||||||
}
|
|
||||||
let style = match self.width() {
|
|
||||||
ContainerWidth::FluidMax(w) if w.is_measurable() => {
|
|
||||||
Some(join!("max-width: ", w.to_string(), ";"))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
match self.container_type() {
|
|
||||||
ContainerType::Default => PrepareMarkup::With(html! {
|
|
||||||
div id=[self.id()] class=[self.classes().get()] style=[style] {
|
|
||||||
(output)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
ContainerType::Main => PrepareMarkup::With(html! {
|
|
||||||
main id=[self.id()] class=[self.classes().get()] style=[style] {
|
|
||||||
(output)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
ContainerType::Header => PrepareMarkup::With(html! {
|
|
||||||
header id=[self.id()] class=[self.classes().get()] style=[style] {
|
|
||||||
(output)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
ContainerType::Footer => PrepareMarkup::With(html! {
|
|
||||||
footer id=[self.id()] class=[self.classes().get()] style=[style] {
|
|
||||||
(output)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
ContainerType::Section => PrepareMarkup::With(html! {
|
|
||||||
section id=[self.id()] class=[self.classes().get()] style=[style] {
|
|
||||||
(output)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
ContainerType::Article => PrepareMarkup::With(html! {
|
|
||||||
article id=[self.id()] class=[self.classes().get()] style=[style] {
|
|
||||||
(output)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Container {
|
|
||||||
/// Crea un contenedor de tipo `Main` (`<main>`).
|
|
||||||
pub fn main() -> Self {
|
|
||||||
Container {
|
|
||||||
container_type: ContainerType::Main,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Crea un contenedor de tipo `Header` (`<header>`).
|
|
||||||
pub fn header() -> Self {
|
|
||||||
Container {
|
|
||||||
container_type: ContainerType::Header,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Crea un contenedor de tipo `Footer` (`<footer>`).
|
|
||||||
pub fn footer() -> Self {
|
|
||||||
Container {
|
|
||||||
container_type: ContainerType::Footer,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Crea un contenedor de tipo `Section` (`<section>`).
|
|
||||||
pub fn section() -> Self {
|
|
||||||
Container {
|
|
||||||
container_type: ContainerType::Section,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Crea un contenedor de tipo `Article` (`<article>`).
|
|
||||||
pub fn article() -> Self {
|
|
||||||
Container {
|
|
||||||
container_type: ContainerType::Article,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< Container BUILDER >**********************************************************************
|
|
||||||
|
|
||||||
/// Establece el identificador único (`id`) del contenedor.
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_id(mut self, id: impl AsRef<str>) -> Self {
|
|
||||||
self.id.alter_value(id);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Modifica la lista de clases CSS aplicadas al contenedor.
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef<str>) -> Self {
|
|
||||||
self.classes.alter_value(op, classes);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el comportamiento del ancho para el contenedor.
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_width(mut self, width: ContainerWidth) -> Self {
|
|
||||||
self.container_width = width;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el estilo del fondo ([`StyleBg`]).
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_style_bg(mut self, style: StyleBg) -> Self {
|
|
||||||
self.style_bg = style;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el estilo del texto ([`StyleText`]).
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_style_text(mut self, style: StyleText) -> Self {
|
|
||||||
self.style_text = style;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Atajo para definir los estilos de fondo y texto a la vez.
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_styles(mut self, style_bg: StyleBg, style_text: StyleText) -> Self {
|
|
||||||
self.style_bg = style_bg;
|
|
||||||
self.style_text = style_text;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el borde del contenedor ([`Border`]).
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_border(mut self, border: Border) -> Self {
|
|
||||||
self.border = border;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece esquinas redondeadas para el contenedor ([`Rounded`]).
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_rounded(mut self, rounded: Rounded) -> Self {
|
|
||||||
self.rounded = rounded;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Añade un nuevo componente hijo al contenedor.
|
|
||||||
#[inline]
|
|
||||||
pub fn add_child(mut self, component: impl Component) -> Self {
|
|
||||||
self.children.add(Child::with(component));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Modifica la lista de componentes (`children`) aplicando una operación [`ChildOp`].
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_child(mut self, op: ChildOp) -> Self {
|
|
||||||
self.children.alter_child(op);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< Container GETTERS >**********************************************************************
|
|
||||||
|
|
||||||
/// Devuelve las clases CSS asociadas al contenedor.
|
|
||||||
pub fn classes(&self) -> &AttrClasses {
|
|
||||||
&self.classes
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Devuelve el tipo semántico del contenedor.
|
|
||||||
pub fn container_type(&self) -> &ContainerType {
|
|
||||||
&self.container_type
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Devuelve el comportamiento para el ancho del contenedor.
|
|
||||||
pub fn width(&self) -> &ContainerWidth {
|
|
||||||
&self.container_width
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Devuelve el estilo del fondo del contenedor.
|
|
||||||
pub fn style_bg(&self) -> &StyleBg {
|
|
||||||
&self.style_bg
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Devuelve el estilo del texto del contenedor.
|
|
||||||
pub fn style_text(&self) -> &StyleText {
|
|
||||||
&self.style_text
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Devuelve el borde configurado del contenedor.
|
|
||||||
pub fn border(&self) -> &Border {
|
|
||||||
&self.border
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Devuelve las esquinas redondeadas configuradas para el contenedor.
|
|
||||||
pub fn rounded(&self) -> &Rounded {
|
|
||||||
&self.rounded
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Devuelve la lista de componentes (`children`) del contenedor.
|
|
||||||
pub fn children(&self) -> &Children {
|
|
||||||
&self.children
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
197
extensions/pagetop-bootsier/src/theme/container/component.rs
Normal file
197
extensions/pagetop-bootsier/src/theme/container/component.rs
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// Componente para crear un **contenedor de componentes**.
|
||||||
|
///
|
||||||
|
/// Envuelve un contenido con la etiqueta HTML indicada por [`container::Kind`]. Sólo se renderiza
|
||||||
|
/// si existen componentes hijos (*children*).
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub struct Container {
|
||||||
|
id : AttrId,
|
||||||
|
classes : AttrClasses,
|
||||||
|
container_kind : container::Kind,
|
||||||
|
container_width: container::Width,
|
||||||
|
children : Children,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Container {
|
||||||
|
fn new() -> Self {
|
||||||
|
Container::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<String> {
|
||||||
|
self.id.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
||||||
|
self.alter_classes(
|
||||||
|
ClassesOp::Prepend,
|
||||||
|
[join_pair!(
|
||||||
|
"container",
|
||||||
|
"-",
|
||||||
|
match self.width() {
|
||||||
|
container::Width::Default => String::new(),
|
||||||
|
container::Width::From(bp) => bp.to_string(),
|
||||||
|
container::Width::Fluid => "fluid".to_string(),
|
||||||
|
container::Width::FluidMax(_) => "fluid".to_string(),
|
||||||
|
}
|
||||||
|
)]
|
||||||
|
.join_classes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||||
|
let output = self.children().render(cx);
|
||||||
|
if output.is_empty() {
|
||||||
|
return PrepareMarkup::None;
|
||||||
|
}
|
||||||
|
let style = match self.width() {
|
||||||
|
container::Width::FluidMax(w) if w.is_measurable() => {
|
||||||
|
Some(join!("max-width: ", w.to_string(), ";"))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
match self.container_kind() {
|
||||||
|
container::Kind::Default => PrepareMarkup::With(html! {
|
||||||
|
div id=[self.id()] class=[self.classes().get()] style=[style] {
|
||||||
|
(output)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
container::Kind::Main => PrepareMarkup::With(html! {
|
||||||
|
main id=[self.id()] class=[self.classes().get()] style=[style] {
|
||||||
|
(output)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
container::Kind::Header => PrepareMarkup::With(html! {
|
||||||
|
header id=[self.id()] class=[self.classes().get()] style=[style] {
|
||||||
|
(output)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
container::Kind::Footer => PrepareMarkup::With(html! {
|
||||||
|
footer id=[self.id()] class=[self.classes().get()] style=[style] {
|
||||||
|
(output)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
container::Kind::Section => PrepareMarkup::With(html! {
|
||||||
|
section id=[self.id()] class=[self.classes().get()] style=[style] {
|
||||||
|
(output)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
container::Kind::Article => PrepareMarkup::With(html! {
|
||||||
|
article id=[self.id()] class=[self.classes().get()] style=[style] {
|
||||||
|
(output)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Container {
|
||||||
|
/// Crea un contenedor de tipo `Main` (`<main>`).
|
||||||
|
pub fn main() -> Self {
|
||||||
|
Container {
|
||||||
|
container_kind: container::Kind::Main,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crea un contenedor de tipo `Header` (`<header>`).
|
||||||
|
pub fn header() -> Self {
|
||||||
|
Container {
|
||||||
|
container_kind: container::Kind::Header,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crea un contenedor de tipo `Footer` (`<footer>`).
|
||||||
|
pub fn footer() -> Self {
|
||||||
|
Container {
|
||||||
|
container_kind: container::Kind::Footer,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crea un contenedor de tipo `Section` (`<section>`).
|
||||||
|
pub fn section() -> Self {
|
||||||
|
Container {
|
||||||
|
container_kind: container::Kind::Section,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Crea un contenedor de tipo `Article` (`<article>`).
|
||||||
|
pub fn article() -> Self {
|
||||||
|
Container {
|
||||||
|
container_kind: container::Kind::Article,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Container BUILDER >**********************************************************************
|
||||||
|
|
||||||
|
/// Establece el identificador único (`id`) del contenedor.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_id(mut self, id: impl AsRef<str>) -> Self {
|
||||||
|
self.id.alter_value(id);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modifica la lista de clases CSS aplicadas al contenedor.
|
||||||
|
///
|
||||||
|
/// También acepta clases predefinidas para:
|
||||||
|
///
|
||||||
|
/// - Modificar el color de fondo ([`classes::Background`]).
|
||||||
|
/// - Definir la apariencia del texto ([`classes::Text`]).
|
||||||
|
/// - Establecer bordes ([`classes::Border`]).
|
||||||
|
/// - Redondear las esquinas ([`classes::Rounded`]).
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef<str>) -> Self {
|
||||||
|
self.classes.alter_value(op, classes);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el comportamiento del ancho para el contenedor.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_width(mut self, width: container::Width) -> Self {
|
||||||
|
self.container_width = width;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Añade un nuevo componente hijo al contenedor.
|
||||||
|
#[inline]
|
||||||
|
pub fn add_child(mut self, component: impl Component) -> Self {
|
||||||
|
self.children.add(Child::with(component));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modifica la lista de componentes (`children`) aplicando una operación [`ChildOp`].
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_child(mut self, op: ChildOp) -> Self {
|
||||||
|
self.children.alter_child(op);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Container GETTERS >**********************************************************************
|
||||||
|
|
||||||
|
/// Devuelve las clases CSS asociadas al contenedor.
|
||||||
|
pub fn classes(&self) -> &AttrClasses {
|
||||||
|
&self.classes
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Devuelve el tipo semántico del contenedor.
|
||||||
|
pub fn container_kind(&self) -> &container::Kind {
|
||||||
|
&self.container_kind
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Devuelve el comportamiento para el ancho del contenedor.
|
||||||
|
pub fn width(&self) -> &container::Width {
|
||||||
|
&self.container_width
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Devuelve la lista de componentes (`children`) del contenedor.
|
||||||
|
pub fn children(&self) -> &Children {
|
||||||
|
&self.children
|
||||||
|
}
|
||||||
|
}
|
||||||
44
extensions/pagetop-bootsier/src/theme/container/props.rs
Normal file
44
extensions/pagetop-bootsier/src/theme/container/props.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
// **< Kind >***************************************************************************************
|
||||||
|
|
||||||
|
/// Tipo de contenedor ([`Container`]).
|
||||||
|
///
|
||||||
|
/// Permite aplicar la etiqueta HTML apropiada (`<main>`, `<header>`, etc.) manteniendo una API
|
||||||
|
/// común a todos los contenedores.
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub enum Kind {
|
||||||
|
/// Contenedor genérico (`<div>`).
|
||||||
|
#[default]
|
||||||
|
Default,
|
||||||
|
/// Contenido principal de la página (`<main>`).
|
||||||
|
Main,
|
||||||
|
/// Encabezado de la página o de sección (`<header>`).
|
||||||
|
Header,
|
||||||
|
/// Pie de la página o de sección (`<footer>`).
|
||||||
|
Footer,
|
||||||
|
/// Sección de contenido (`<section>`).
|
||||||
|
Section,
|
||||||
|
/// Artículo de contenido (`<article>`).
|
||||||
|
Article,
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Width >**************************************************************************************
|
||||||
|
|
||||||
|
/// Define el comportamiento para ajustar el ancho de un contenedor ([`Container`]).
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub enum Width {
|
||||||
|
/// Comportamiento por defecto, aplica los anchos máximos predefinidos para cada punto de
|
||||||
|
/// ruptura. Por debajo del menor punto de ruptura ocupa el 100% del ancho disponible.
|
||||||
|
#[default]
|
||||||
|
Default,
|
||||||
|
/// Aplica los anchos máximos predefinidos a partir del punto de ruptura indicado. Por debajo de
|
||||||
|
/// ese punto de ruptura ocupa el 100% del ancho disponible.
|
||||||
|
From(BreakPoint),
|
||||||
|
/// Ocupa el 100% del ancho disponible siempre.
|
||||||
|
Fluid,
|
||||||
|
/// Ocupa el 100% del ancho disponible hasta un ancho máximo explícito.
|
||||||
|
FluidMax(UnitValue),
|
||||||
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
//! # use pagetop_bootsier::prelude::*;
|
//! # use pagetop_bootsier::prelude::*;
|
||||||
//! let dd = Dropdown::new()
|
//! let dd = Dropdown::new()
|
||||||
//! .with_title(L10n::n("Menu"))
|
//! .with_title(L10n::n("Menu"))
|
||||||
//! .with_button_color(ColorButton::Background(Color::Secondary))
|
//! .with_button_color(ButtonColor::Background(Color::Secondary))
|
||||||
//! .with_auto_close(dropdown::AutoClose::ClickableInside)
|
//! .with_auto_close(dropdown::AutoClose::ClickableInside)
|
||||||
//! .with_direction(dropdown::Direction::Dropend)
|
//! .with_direction(dropdown::Direction::Dropend)
|
||||||
//! .add_item(dropdown::Item::link(L10n::n("Home"), |_| "/"))
|
//! .add_item(dropdown::Item::link(L10n::n("Home"), |_| "/"))
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ pub struct Dropdown {
|
||||||
classes : AttrClasses,
|
classes : AttrClasses,
|
||||||
title : L10n,
|
title : L10n,
|
||||||
button_size : ButtonSize,
|
button_size : ButtonSize,
|
||||||
button_color : ColorButton,
|
button_color : ButtonColor,
|
||||||
button_split : bool,
|
button_split : bool,
|
||||||
button_grouped: bool,
|
button_grouped: bool,
|
||||||
auto_close : dropdown::AutoClose,
|
auto_close : dropdown::AutoClose,
|
||||||
|
|
@ -59,7 +59,7 @@ impl Component for Dropdown {
|
||||||
dropdown::Direction::Dropend => "dropend",
|
dropdown::Direction::Dropend => "dropend",
|
||||||
dropdown::Direction::Dropstart => "dropstart",
|
dropdown::Direction::Dropstart => "dropstart",
|
||||||
}
|
}
|
||||||
].join(" "));
|
].join_classes());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||||
|
|
@ -79,7 +79,7 @@ impl Component for Dropdown {
|
||||||
"btn",
|
"btn",
|
||||||
&self.button_size().to_string(),
|
&self.button_size().to_string(),
|
||||||
&self.button_color().to_string(),
|
&self.button_color().to_string(),
|
||||||
].join(" "));
|
].join_classes());
|
||||||
@let (offset, reference) = match self.menu_position() {
|
@let (offset, reference) = match self.menu_position() {
|
||||||
dropdown::MenuPosition::Default => (None, None),
|
dropdown::MenuPosition::Default => (None, None),
|
||||||
dropdown::MenuPosition::Offset(x, y) => (Some(format!("{x},{y}")), None),
|
dropdown::MenuPosition::Offset(x, y) => (Some(format!("{x},{y}")), None),
|
||||||
|
|
@ -212,7 +212,7 @@ impl Dropdown {
|
||||||
|
|
||||||
/// Define el color/estilo del botón.
|
/// Define el color/estilo del botón.
|
||||||
#[builder_fn]
|
#[builder_fn]
|
||||||
pub fn with_button_color(mut self, color: ColorButton) -> Self {
|
pub fn with_button_color(mut self, color: ButtonColor) -> Self {
|
||||||
self.button_color = color;
|
self.button_color = color;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
@ -291,7 +291,7 @@ impl Dropdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Devuelve el color/estilo configurado del botón.
|
/// Devuelve el color/estilo configurado del botón.
|
||||||
pub fn button_color(&self) -> &ColorButton {
|
pub fn button_color(&self) -> &ButtonColor {
|
||||||
&self.button_color
|
&self.button_color
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ use crate::prelude::*;
|
||||||
///
|
///
|
||||||
/// - Ajusta su disposición según el origen definido en [`image::Source`].
|
/// - Ajusta su disposición según el origen definido en [`image::Source`].
|
||||||
/// - Permite configurar **dimensiones** ([`with_size()`](Self::with_size)), **borde**
|
/// - Permite configurar **dimensiones** ([`with_size()`](Self::with_size)), **borde**
|
||||||
/// ([`with_border()`](Self::with_border)) y **redondeo de esquinas**
|
/// ([`classes::Border`](crate::theme::classes::Border)) y **redondeo de esquinas**
|
||||||
/// ([`with_rounded()`](Self::with_rounded)).
|
/// ([`classes::Rounded`](crate::theme::classes::Rounded)).
|
||||||
/// - Resuelve el texto alternativo `alt` con **localización** mediante [`L10n`].
|
/// - Resuelve el texto alternativo `alt` con **localización** mediante [`L10n`].
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[derive(AutoDefault)]
|
#[derive(AutoDefault)]
|
||||||
|
|
@ -17,8 +17,6 @@ pub struct Image {
|
||||||
size : image::Size,
|
size : image::Size,
|
||||||
source : image::Source,
|
source : image::Source,
|
||||||
alt : AttrL10n,
|
alt : AttrL10n,
|
||||||
border : Border,
|
|
||||||
rounded: Rounded,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for Image {
|
impl Component for Image {
|
||||||
|
|
@ -33,17 +31,12 @@ impl Component for Image {
|
||||||
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
||||||
self.alter_classes(
|
self.alter_classes(
|
||||||
ClassesOp::Prepend,
|
ClassesOp::Prepend,
|
||||||
[
|
match self.source() {
|
||||||
String::from(match self.source() {
|
image::Source::Logo(_) => "img-fluid",
|
||||||
image::Source::Logo(_) => "img-fluid",
|
image::Source::Responsive(_) => "img-fluid",
|
||||||
image::Source::Responsive(_) => "img-fluid",
|
image::Source::Thumbnail(_) => "img-thumbnail",
|
||||||
image::Source::Thumbnail(_) => "img-thumbnail",
|
image::Source::Plain(_) => "",
|
||||||
image::Source::Plain(_) => "",
|
},
|
||||||
}),
|
|
||||||
self.border().to_string(),
|
|
||||||
self.rounded().to_string(),
|
|
||||||
]
|
|
||||||
.join(" "),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,6 +109,11 @@ impl Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Modifica la lista de clases CSS aplicadas a la imagen.
|
/// Modifica la lista de clases CSS aplicadas a la imagen.
|
||||||
|
///
|
||||||
|
/// También acepta clases predefinidas para:
|
||||||
|
///
|
||||||
|
/// - Establecer bordes ([`classes::Border`]).
|
||||||
|
/// - Redondear las esquinas ([`classes::Rounded`]).
|
||||||
#[builder_fn]
|
#[builder_fn]
|
||||||
pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef<str>) -> Self {
|
pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef<str>) -> Self {
|
||||||
self.classes.alter_value(op, classes);
|
self.classes.alter_value(op, classes);
|
||||||
|
|
@ -146,20 +144,6 @@ impl Image {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Establece el borde de la imagen ([`Border`]).
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_border(mut self, border: Border) -> Self {
|
|
||||||
self.border = border;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece esquinas redondeadas para la imagen ([`Rounded`]).
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_rounded(mut self, rounded: Rounded) -> Self {
|
|
||||||
self.rounded = rounded;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< Image GETTERS >**************************************************************************
|
// **< Image GETTERS >**************************************************************************
|
||||||
|
|
||||||
/// Devuelve las clases CSS asociadas a la imagen.
|
/// Devuelve las clases CSS asociadas a la imagen.
|
||||||
|
|
@ -181,14 +165,4 @@ impl Image {
|
||||||
pub fn alternative(&self) -> &AttrL10n {
|
pub fn alternative(&self) -> &AttrL10n {
|
||||||
&self.alt
|
&self.alt
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Devuelve el borde configurado de la imagen.
|
|
||||||
pub fn border(&self) -> &Border {
|
|
||||||
&self.border
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Devuelve las esquinas redondeadas configuradas para la imagen.
|
|
||||||
pub fn rounded(&self) -> &Rounded {
|
|
||||||
&self.rounded
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ impl Component for Nav {
|
||||||
nav::Layout::Justified => "nav-justified",
|
nav::Layout::Justified => "nav-justified",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
.join(" "),
|
.join_classes(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,12 @@ const TOGGLE_OFFCANVAS: &str = "offcanvas";
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[derive(AutoDefault)]
|
#[derive(AutoDefault)]
|
||||||
pub struct Navbar {
|
pub struct Navbar {
|
||||||
id : AttrId,
|
id : AttrId,
|
||||||
classes : AttrClasses,
|
classes : AttrClasses,
|
||||||
expand : BreakPoint,
|
expand : BreakPoint,
|
||||||
layout : navbar::Layout,
|
layout : navbar::Layout,
|
||||||
position : navbar::Position,
|
position : navbar::Position,
|
||||||
style_bg : StyleBg,
|
items : Children,
|
||||||
style_text: StyleText,
|
|
||||||
items : Children,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for Navbar {
|
impl Component for Navbar {
|
||||||
|
|
@ -50,10 +48,8 @@ impl Component for Navbar {
|
||||||
navbar::Position::StickyBottom => "sticky-bottom",
|
navbar::Position::StickyBottom => "sticky-bottom",
|
||||||
}
|
}
|
||||||
.to_string(),
|
.to_string(),
|
||||||
self.style_bg().to_string(),
|
|
||||||
self.style_text().to_string(),
|
|
||||||
]
|
]
|
||||||
.join(" "),
|
.join_classes(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,6 +228,11 @@ impl Navbar {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Modifica la lista de clases CSS aplicadas a la barra de navegación.
|
/// Modifica la lista de clases CSS aplicadas a la barra de navegación.
|
||||||
|
///
|
||||||
|
/// También acepta clases predefinidas para:
|
||||||
|
///
|
||||||
|
/// - Modificar el color de fondo ([`classes::Background`]).
|
||||||
|
/// - Definir la apariencia del texto ([`classes::Text`]).
|
||||||
#[builder_fn]
|
#[builder_fn]
|
||||||
pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef<str>) -> Self {
|
pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef<str>) -> Self {
|
||||||
self.classes.alter_value(op, classes);
|
self.classes.alter_value(op, classes);
|
||||||
|
|
@ -259,28 +260,6 @@ impl Navbar {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Establece el estilo del fondo ([`StyleBg`]).
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_style_bg(mut self, style: StyleBg) -> Self {
|
|
||||||
self.style_bg = style;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el estilo del texto ([`StyleText`]).
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_style_text(mut self, style: StyleText) -> Self {
|
|
||||||
self.style_text = style;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Atajo para definir los estilos de fondo y texto a la vez.
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_styles(mut self, style_bg: StyleBg, style_text: StyleText) -> Self {
|
|
||||||
self.style_bg = style_bg;
|
|
||||||
self.style_text = style_text;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Añade un nuevo contenido hijo.
|
/// Añade un nuevo contenido hijo.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn add_item(mut self, item: navbar::Item) -> Self {
|
pub fn add_item(mut self, item: navbar::Item) -> Self {
|
||||||
|
|
@ -317,16 +296,6 @@ impl Navbar {
|
||||||
&self.position
|
&self.position
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Devuelve el estilo del fondo del contenedor.
|
|
||||||
pub fn style_bg(&self) -> &StyleBg {
|
|
||||||
&self.style_bg
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Devuelve el estilo del texto del contenedor.
|
|
||||||
pub fn style_text(&self) -> &StyleText {
|
|
||||||
&self.style_text
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Devuelve la lista de contenidos (`children`).
|
/// Devuelve la lista de contenidos (`children`).
|
||||||
pub fn items(&self) -> &Children {
|
pub fn items(&self) -> &Children {
|
||||||
&self.items
|
&self.items
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ impl Component for Item {
|
||||||
nav::Layout::Justified => "nav-justified",
|
nav::Layout::Justified => "nav-justified",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
.join(" "),
|
.join_classes(),
|
||||||
);
|
);
|
||||||
PrepareMarkup::With(html! {
|
PrepareMarkup::With(html! {
|
||||||
ul id=[nav.id()] class=[classes.get()] {
|
ul id=[nav.id()] class=[classes.get()] {
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ impl Component for Offcanvas {
|
||||||
offcanvas::Visibility::Show => "show",
|
offcanvas::Visibility::Show => "show",
|
||||||
}.to_string(),
|
}.to_string(),
|
||||||
]
|
]
|
||||||
.join(" "),
|
.join_classes(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue