`render_sections()` devuelve `Option<Container>`, con `None` si no queda
ninguna sección visible con páginas accesibles. `dashboard()` y
`section_page()` responden con `AccessDenied` en ese caso, sin crear un
permiso nuevo.
Retira AdminLTE 4 de Bootsier: CSS/JS, `bs::sidebar`, `BootsierRegions`
y el shell propio de `CoreTemplates::Admin`. Sólo quedaba un sidebar de
5 secciones ya alcanzables desde el dashboard, las páginas de sección y
el breadcrumb de `AdminFrame`.
Añade `Navbar::with_position()` y `navbar::Position` al núcleo, con las
clases de Basic para barras fijas y pegajosas, y `navbar::Item::form()`
para mostrar un formulario dentro de la barra.
Las barras sin botón de despliegue (`Simple` y `SimpleBrandLeft`) ya no
colapsan: el punto de corte no les afecta y su menú se mantiene en
línea, con salto de línea si no cabe. En Bootsier usan `navbar-expand` y
`SimpleBrandLeft` agrupa los contenidos junto a la marca.
Navbar guarda el punto de corte a partir del cual deja de colapsar
(`Breakpoint::Md` por defecto) y añade la clase `navbar-expand-{nombre}`
o `navbar-expand` si no tiene ancho mínimo. El nombre lo resuelve el
tema activo con `Theme::breakpoint_entry()`.
`FlexItem`, `Margin` y `Padding` se pasan directamente gracias a `From`
hacia `PropsOp`, sin `PropsOp::flex_item()`/`margin()`/`padding()` ni
`.into()` explícito. Revisadas todas las llamadas en el código para
simplificarlas.
- Nuevo módulo `html::spacing` con `Margin`/`Padding`: igual que
`FlexItem`, se resuelven generando clases CSS dinámicamente y se
aplican con `PropsOp::margin()`/`PropsOp::padding()` sobre cualquier
componente.
- Elimina `Margin`/`Padding` de `pagetop-bootsier`.
- Añade el ejemplo `intro-spacing` con los patrones de uso típicos.
- `StyleSheet::inline` se resuelve ahora con `ResponsiveStyles`.
- `StyleSheet` se simplifica a sólo hojas de estilo externas.
- `ResponsiveStyles` añade `add_styles()` para declarar varias
propiedades en una sola llamada.
- `AssetsOp` gana un constructor por variante y conversiones
"From<Favicon/Preload/StyleSheet/JavaScript>" para pasarlos
directamente a `with_assets()`.
- `Breakpoint` gana variante `Xxxl` y métodos `name()`/`min_width()`/
`resolved()`, para consultarse contra el tema activo.
- `Theme::breakpoint_entry()` sustituye a `breakpoint_min_width()`:
devuelve un `BreakpointEntry` con nombre y ancho mínimo.
- Nuevo `Responsive<T>`, valor en cascada mobile-first por punto de
corte.
- Ejemplo `examples/intro-responsive.rs` con los patrones de uso.
`Theme::handle_component()` se divide en `setup_component()` (síncrono,
muta por tipo con la macro homónima) y `render_component()` (async,
decide el renderizado con su propia macro). Aplica mismo criterio que ya
separa `Component::setup()` de `prepare()`.
Antes sólo mutaba el propio componente; ahora también puede aplicar
ajustes síncronos sobre el Context, visibles para las extensiones que
intercepten BeforeRender. La frontera con prepare() pasa a ser de
sincronía, no de qué puede mutar cada uno.
Container y Navbar lo adoptan vía `with_flex()`/`PropsOp::flex_item()`.
Y se elimina `ButtonSet` porque su funcionalidad queda cubierta por este
mecanismo más general. Incluye el ejemplo `examples/intro-flex.rs` con
los patrones de uso.
Sustituye las ~400 anotaciones `#[builder_fn]` método a método por un
único `#[builder_impl]` por `impl`/`trait`, en 74 ficheros de pagetop y
sus extensiones (admin, bootsier, menu, user).
Identidad de usuario, sesiones en base de datos, roles y permisos (RBAC)
con "authenticated" implícito, contraseñas con Argon2id, tokens de
un solo uso para verificación de email y restablecimiento de contraseña,
y la UI de administración completa (usuarios, roles, permisos) sobre
pagetop-admin.
Incluye datos de demostración opcionales tras la feature `demo-data`.
Gestión centralizada y persistente de menús: entidades y migraciones
SeaORM, sistema de acciones para declarar menús/ítems por código, caché
in-process del árbol y los componentes `MenuBlock`/`MenuBreadcrumb`.
Panel de administración extensible: registro de secciones/páginas/
tareas/acciones vía acciones `Declare*`, formularios de configuración
automáticos (ConfigForm + SettingsSchema) y persistencia en la tabla
`settings`.
- Añade Dialog como modal de Bootstrap, con el JS de soporte para
`htmx:confirm` y el saneado de su posición fija.
- Adapta Nav, Navbar y Dropdown al reuso de los tipos movidos al core, y
traduce BootsierColors/Intent en Button y Badge, con soporte para
Light/Dark vía with_color().
- Reexporta en el tema los componentes de PageTop que faltaban: Block,
Breadcrumb, Messages, Pager, Table y form::Number.
- `PageTopSvg::markup_with()` fusiona `Props` y controla la etiqueta
accesible directamente en el `<svg>`.
- `Image` ya no duplica accesibilidad para el logotipo y corrige el
`alt` vacío en el resto de fuentes (Responsive/Thumbnail/Plain).
- Sustituye `BadgeKind` y el `ColorName`/`IntoColor` de `core/theme`
por un `Intent` compartido.
`Attr<T>` no aportaba nada sobre `Option<T>` directo: `Getters` ya trata
los campos `Option<T>` como caso especial (`Option<&T>`, o `Option<T>`
con `#[getters(copy)]`) y `#[builder_fn]` funciona igual sobre ellos.
`Image`, `Size` y `Source` pasan a `pagetop::base::component` como
componente genérico reutilizable por cualquier tema. Bootsier
sustituye las clases semánticas por las de Bootstrap (`img-fluid`,
`img-thumbnail`) interceptando `setup()`.
`L10n::using()` insertaba el texto de `L10n::n()` sin escapar,
tratándolo igual que una traducción de confianza (`l()`/`t()`); ahora se
escapa como cualquier otro valor interpolado con `html!`.
Además, `using()` no debe usarse en valores de atributo. Su marcado de
confianza para `l()`/`t()` podría romper el delimitador si la traducción
contuviera una comilla. Se sustituye por `lookup()`
Añade nuevas variantes `Kind::StrictText` y `StrictPassword`
(`Field::strict_text()` y `strict_password()`) para forzar en el campo
`autocomplete=off`, desactivar spellcheck y autocorrect, aplicar
`readonly+onfocus`, y enmascarar las contraseñas vía CSS en vez de
`type="password"`. Replicado en pagetop-bootsier.
- Añade `#[builder_fn]` a `with_width()`/`with_floating_label()`.
- `Rounded::new()` pasa a aplicar el radio por defecto
(`Rounded::default()` queda sin redondeo).
- `Form::action` usa `Route` en lugar de `AttrValue`, y `check::Item`
expone `value` en vez de `name` para generar casillas con `name`
compartido valores distintos.
Centraliza la paginación genérica junto con `Paginated::map_items()`
para enriquecer los elementos de una página con datos de otra tabla sin
perder la metadata de paginación.
Nuevo método `oob()` para incluir fragmentos adicionales marcados con
`hx-swap-oob` en el cuerpo de la respuesta, sin necesidad de construir
el envoltorio a mano ni depender del `hx-target` de la petición.
De paso, `set_header()` usa ya las constantes de `hx::response` en vez
de literales repetidos, y se revisan comentarios.
- Nuevo `SortDir` en `pagetop::html` para representar direcciones de
orden (asc/desc) y calcular la siguiente al pulsar una cabecera.
- `hx_table::sort_link()` construye el enlace de ordenación con los
cuatro atributos `hx-*` fijos, reutilizable en cualquier tabla.
- `HtmxResponse` usa `RoutePath` en `location`/`push_url`/`replace_url`/
`redirect` para preservar "lang"; `location_json()` se separa de
`location()` para el caso de configuración JSON personalizada.
- Añade el módulo `prelude` y una batería de tests para hx, hx_table,
request, response y extension.