♻️ (bootsier): Reorganiza en capas token/class/bs

Sustituye `attrs/` y `classes/` por tres capas diferenciadas:
- `token/`: primitivas CSS (BreakPoint, Color, ScaleSize, etc.).
- `class/`: tipos compuestos (Border, Background, Margin, etc.).
- `bs/*/props.rs`: props tipadas para cada componente de Bootstrap.

El patrón de construcción es `suffix()` -> `push_to()` -> `to_class()`.
`push_to()` es `pub` en `class/` y `bs/*/props.rs` para que los temas
derivados puedan acceder a los mismos mecanismos de construcción.
This commit is contained in:
Manuel Cillero 2026-06-29 20:32:20 +02:00
parent 64db114eb0
commit f37db56ec5
47 changed files with 1307 additions and 1201 deletions

View file

@ -1,40 +0,0 @@
//! Definiciones para crear campos de texto de una línea.
use pagetop::prelude::*;
pub use pagetop::base::component::form::input::{Field, Kind, Mode};
/// Extensión de Bootsier para [`form::input::Field`].
///
/// Proporciona soporte para **etiquetas flotantes** (*floating label*). La etiqueta flotante se
/// superpone al control mientras está vacío y permanece flotante cuando tiene contenido o está
/// enfocado.
///
/// ```rust,no_run
/// # use pagetop::locale::L10n;
/// use pagetop_bootsier::theme::*;
///
/// let nombre = form::input::Field::text()
/// .with_name("name")
/// .with_label(L10n::n("Name"))
/// .with_placeholder(L10n::n("Enter your name"))
/// .with_floating_label(true);
/// ```
pub trait InputBootsier {
/// Establece si la etiqueta se muestra flotante sobre el campo.
///
/// Cuando está activo, la etiqueta se superpone al campo y asciende al enfocarlo o cuando tiene
/// contenido. Requiere que el campo tenga un atributo `placeholder` definido; si no se
/// especifica, se fuerza `placeholder=""` antes del renderizado.
fn with_floating_label(self, floating: bool) -> Self;
}
impl InputBootsier for Field {
fn with_floating_label(self, floating: bool) -> Self {
if floating {
self.with_prop(PropsOp::add_classes("form-floating"))
} else {
self.with_prop(PropsOp::remove_classes("form-floating"))
}
}
}