Commit graph

306 commits

Author SHA1 Message Date
70744a51a5 ✨ (auth): Añade idioma y tema preferidos al usuario
- CurrentUser pasa de enum a struct con `id` opcional (anónimo = None) y
  preferencias de idioma, zona horaria y tema validadas en `with_*()`.
- `RequestLocale` tiene en cuenta el idioma preferido del usuario, y
  Context usa su tema si lo tiene (`default_theme()` en otro caso).
- Nuevos componentes `form::SelectLanguage`, `form::SelectTheme` y
  `form::SelectTimezone`, con `Timezone::supported_by_region()` para
  listar y validar las zonas IANA ofrecidas.
2026-10-04 23:09:07 +02:00
c848b97450 🎨 (basic): Organiza estilos de Basic e Intro
Divide `basic.css` en parciales SCSS bajo `assets/scss/basic/`, integra
`normalize.css` en `basic.min.css` y compila `intro.scss` por separado a
`intro.min.css`.
2026-10-03 11:15:10 +02:00
56a2471090 💄 (button): Aplica estilo deshabilitado a enlaces
Un `<a>` deshabilitado no tiene un equivalente a `:disabled` sobre el
que aplicar estilos. Button añade ahora la clase `disabled`.
2026-10-02 23:33:22 +02:00
c06efbd0d1 🎨 Ajustes menores de separadores de sección 2026-10-02 22:59:26 +02:00
04502ef81e ✨ (user): Añade zona horaria propia del usuario
Sustituye el campo de texto libre por un selector de zonas horarias IANA
canónicas agrupadas por región, con la opción de usar la del sitio (que
muestra la zona efectiva).
2026-10-02 22:31:58 +02:00
90e4f85bd4 ✨ (datetime): Añade zona horaria y formato de fechas
Añade formatos `DateFormat`, `TimeFormat`, `RelativeFormat` y
`DatePrecision`, con estilos traducidos vía Fluent (orden día/mes/año,
nombre del mes, plurales). La zona horaria efectiva se resuelve por
petición, la propia del usuario autenticado si la tiene, si no la
configurada para la aplicación (`app.timezone`), o UTC en su defecto- y
se expone en `Contextual` junto a format_date(), format_time(),
format_datetime(), format_iso_datetime(), format_relative(),
format_since() y format_until().
2026-10-01 21:53:57 +02:00
3df73f0551 ✨ (locale): Añade Lc::with_number() para plurales
`with_arg()` sólo interpola texto, y el selector de plural de Fluent
(`{ $n -> [one] ... *[other] ... }`) sólo aplica las reglas de plural
cuando el argumento es un FluentValue::Number.
2026-09-29 07:08:48 +02:00
dbdaeb6151 ✨ (user): Ordena alfabéticamente grupos de permisos
Añade `Lc::collation_key()` en PageTop para obtener una clave de
ordenación no sensible a mayúsculas y acentos, con `ñ` como letra propia
entre `n` y `o` en español.
2026-09-27 13:12:57 +02:00
165cb49880 ✨ (base): Añade with_menu_end() para menú al final 2026-09-26 14:21:39 +02:00
3f3634fdab ♻️ Atributos class e id explícitos en html!
Se usa `class="..."` e `id="..."` en lugar de `div.a #x`. El HTML
generado es idéntico.
2026-09-26 07:05:59 +02:00
58d1fef4f1 ⚡️ (core): Registro de acciones inmutable 2026-09-26 00:56:30 +02:00
5b2ddeb6cc ⚡️ (pagetop): Mejora uso de Props, Grid y HttpRequest 2026-09-24 22:29:27 +02:00
c47724bb68 ✨ (base): Implementa Navbar con funcionalidad base
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.
2026-09-21 16:27:44 +02:00
f8f023b513 ✨ (pagetop): Añade PageTopSvg::Tile y ajusta Image 2026-09-21 13:51:18 +02:00
16eec316c4 ♻️ (base): Reorganiza el componente Intro 2026-09-20 23:53:18 +02:00
c6cd4fcd7d ✨ (base): Añade with_width() a Container 2026-09-19 03:14:21 +02:00
9143f1eb26 ✨ (pagetop): Añade with_expand() a Navbar
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()`.
2026-09-19 01:52:55 +02:00
307ca6f62c ✨ (pagetop): Añade Grid y extrae Flex de Container 2026-09-18 16:49:09 +02:00
dfff12881f 🚧 (pagetop): Comparte align entre Flex y Grid
Extrae `Align`/`AlignContent`/`ItemAlign`/`Gap` de Flexbox a un nuevo
módulo neutral `html::align` (`Items`/`Content`/`ItemSelf`/`Gap`) para
que tambien lo use CSS Grid.
2026-09-13 23:08:39 +02:00
3c3ffc91e6 ♻️ (pagetop): with_prop() acepta impl Into<PropsOp>
`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.
2026-09-13 01:38:33 +02:00
50e4b42fe4 ✨ (pagetop): Añade Margin y Padding nativos
- 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.
2026-09-13 00:48:11 +02:00
64113aff09 ♻️ (pagetop): Sustituye StyleSheet::inline
- `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()`.
2026-09-12 20:44:17 +02:00
0b8f3f3000 ✨ (pagetop): Añade puntos de corte a Flex/FlexItem
- `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.
2026-09-12 11:13:19 +02:00
8577ca8a59 ♻️ (pagetop): Props::unpack() exige &mut Context 2026-09-08 07:28:50 +02:00
ee1b48ff3f ♻️ (pagetop): Divide props.rs en varios módulos 2026-09-06 20:36:12 +02:00
28f1eee391 ♻️ (pagetop): Separa handle_component() en 2 métodos
`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()`.
2026-09-06 13:07:01 +02:00
1e2d171805 ♻️ (pagetop): setup() recibe &mut Context
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.
2026-09-06 09:04:44 +02:00
f2a7507317 ✨ (theme): Añade Breakpoint y ResponsiveStyles
- Nuevo `Breakpoint` (`Xs`/`Sm`/`Md`/`Lg`/`Xl`/`Xxl`) y
  `Theme::breakpoint_min_width()`, que traduce cada variante al ancho
  mínimo CSS del tema activo (mismo patrón que `Theme::intent_color()`).
- `ResponsiveStyles` acumula declaraciones `property: value` agrupadas
  por punto de corte (opcional: `None` para reglas siempre activas, sin
  depender del tema) y por clase o clases. Aplica first-write-wins para
  clases utilitarias repetidas por muchos componentes. `render()` las
  agrupa en bloques `@media (min-width: ...)` mobile-first, sin saltos
  de línea.
2026-09-06 01:46:06 +02:00
b163b7726e ♻️ (util): Simplifica normalize_ascii*
`normalize_ascii_or_empty()` pasa a llamarse `normalize_ascii()` (la
variante indulgente, la más usada); la antigua `normalize_ascii()` pasa
a `normalize_ascii_non_blank()`.
2026-09-05 21:19:15 +02:00
ab1d4f0efb ♻️ (pagetop): Incorpora Context al render de Props 2026-09-05 00:19:39 +02:00
17e16652e4 ✨ (pagetop): Añade Flex/FlexItem para usar Flexbox
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.
2026-09-04 01:04:53 +02:00
4e4fdf7b10 📝 Resalta términos en docs de Block y Breadcrumb 2026-08-29 19:52:45 +02:00
1be3d88888 ♻️ Migra #[builder_fn] a #[builder_impl]
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).
2026-08-29 19:25:58 +02:00
c34dc02357 ✨ (macros): Añade #[builder_impl]
Aplica `#[builder_fn]` a todos los métodos `with_...()` de un bloque
`impl` o de una definición de trait de una vez, sin anotarlos uno a uno.
2026-08-29 19:19:58 +02:00
35ae5bb6a8 ✨ (base): Añade componentes Nav y Navbar
Dropdown incorpora tamaño y estilo de botón configurables
(`button::Size`/`Style`), reutilizados también por Navbar. El tema Basic
sirve `basic.min.css` y añade el JS de inicialización de Navbar.
2026-08-28 18:24:43 +02:00
da959183f6 ✨ (button): Añade Button::anchor() para navegación
- Renderiza un `<a href>` real con el aspecto de un botón, distinto del
  estilo puramente visual `button::Style::Link`.
- Renombra `ButtonKind`/`ButtonStyle` a `Kind`/`Style`.
- Añade `button::Size` (`button-sm`/`button-lg`).
2026-08-28 11:38:57 +02:00
434d31c5eb 📝 (doc): Sustituye "..." por "etc." 2026-08-28 11:16:58 +02:00
56a6691c87 🚧 (theme): Renombra variantes de Intent
Renombra `Intent::Secondary`/`Danger` a `Neutral`/`Severe` y actualiza
Badge y su CSS por defecto (basic.css) al nuevo vocabulario.

Introduce el punto de extensión `Theme::intent_color()`, que traduce una
`Intent` al nombre de color de la paleta propia de cada tema, con
`Intent::color(cx)` como atajo de uso desde los componentes.
2026-08-28 01:10:45 +02:00
af53cd4b52 ♻️ (dropdown): Integra Dropdown con accessible-menu
Renombra `dropdown.init.js` a `basic.dropdown.init.js` y añade cierre
cruzado entre menús abiertos y cierre al clicar fuera. Corrige el icono
de apertura/cierre y el estado cerrado por defecto de dropdown-menu.
Migra `with_item` de `ChildOp` a `TypedOp<dropdown::Item>`.
2026-08-26 23:58:33 +02:00
76c5cb9b76 ✨ (base): Añade componente Dialog
Sustituye `PropsOp::Translate` por `Rename` para que los temas traduzcan
atributos `data-dialog-*` al vocabulario propio (p. ej. `data-bs-*` en
Bootsier).
2026-08-26 21:56:10 +02:00
3c67d9d04c ✨ (props): Añade la operación PropsOp::translate
Permite a un tema traducir el vocabulario de atributos de un componente
al suyo propio (p. ej. `data-dialog-*` -> `data-bs-*`) sin conocer su
valor, respetando el que ya tuviera el destino si existía.
2026-08-26 06:55:37 +02:00
99a4837e11 ✨ (button): Añade componentes Button y ButtonSet 2026-08-24 20:18:29 +02:00
c8654a5742 ✨ (core): Añade TypedOp<C> para restringir Children
Mismo repertorio de operaciones que `ChildOp`, pero cada variante exige
un componente de tipo `C`, evitando que un componente ajeno a ese tipo
acabe en una lista pensada para un único tipo de elemento.
2026-08-24 20:00:12 +02:00
d8f82ea1d2 ♻️ (response): Renombra Waypoint::as_str a as_deref 2026-08-23 13:39:38 +02:00
e24b9ab9de ♻️ (pagetop): Logotipo embebido y Badge en Intent
- `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.
2026-08-22 09:44:28 +02:00
4ba66f5995 🚧 (base): Añade BadgeKind para el tipo de Badge 2026-08-21 11:18:16 +02:00
997017bb75 🎨 (core): Retoques de estilo menores 2026-08-21 08:23:39 +02:00
b50d186fb1 ✨ (theme): Añade IntoColor para colores opcionales
Permite que métodos como `with_color(color: impl IntoColor)` acepten un
color directo o uno opcional (`Some(...)`/`None`) sin la ambigüedad que
produce un `Into<Option<C>>` genérico.
2026-08-21 08:18:28 +02:00
bb6855e41f ✨ (theme): Añade ColorName y CoreColors
Nuevo trait `ColorName` para que cada tema aporte su propia paleta de
colores; `CoreColors` es la paleta por defecto.

Aprovecha para refactorizar `core/theme.rs` en submódulos por concepto.
2026-08-20 21:54:12 +02:00
fe2b2c176f ♻️ (bootsier): Mueve Brand al core de PageTop 2026-08-17 05:53:55 +02:00