[pagetop] Añade gestión de rutas con parámetros

This commit is contained in:
Manuel Cillero 2025-12-12 00:14:55 +01:00
parent f1cbd3bd66
commit 35013b36df
8 changed files with 197 additions and 56 deletions

View file

@ -17,11 +17,12 @@ pub enum ItemKind {
Void,
/// Etiqueta sin comportamiento interactivo.
Label(L10n),
/// Elemento de navegación. Opcionalmente puede abrirse en una nueva ventana y estar
/// inicialmente deshabilitado.
/// Elemento de navegación basado en una [`RoutePath`] dinámica devuelta por
/// [`FnPathByContext`]. Opcionalmente, puede abrirse en una nueva ventana y estar inicialmente
/// deshabilitado.
Link {
label: L10n,
path: FnPathByContext,
route: FnPathByContext,
blank: bool,
disabled: bool,
},
@ -71,10 +72,10 @@ impl ItemKind {
/// Representa un **elemento individual** de un menú [`Nav`](crate::theme::Nav).
///
/// Cada instancia de [`nav::Item`](crate::theme::nav::Item) se traduce en un componente visible que
/// puede comportarse como texto, enlace, botón o menú desplegable según su [`ItemKind`].
/// puede comportarse como texto, enlace, contenido HTML o menú desplegable, según su [`ItemKind`].
///
/// Permite definir identificador, clases de estilo adicionales o tipo de interacción asociada,
/// manteniendo una interfaz común para renderizar todos los elementos del menú.
/// Permite definir el identificador, las clases de estilo adicionales y el tipo de interacción
/// asociada, manteniendo una interfaz común para renderizar todos los elementos del menú.
#[derive(AutoDefault, Getters)]
pub struct Item {
#[getters(skip)]
@ -112,13 +113,13 @@ impl Component for Item {
ItemKind::Link {
label,
path,
route,
blank,
disabled,
} => {
let path = path(cx);
let route_link = route(cx);
let current_path = cx.request().map(|request| request.path());
let is_current = !*disabled && (current_path == Some(&path));
let is_current = !*disabled && (current_path == Some(route_link.path()));
let mut classes = "nav-link".to_string();
if is_current {
@ -128,7 +129,7 @@ impl Component for Item {
classes.push_str(" disabled");
}
let href = (!*disabled).then_some(path);
let href = (!*disabled).then_some(route_link);
let target = (!*disabled && *blank).then_some("_blank");
let rel = (!*disabled && *blank).then_some("noopener noreferrer");
@ -202,11 +203,15 @@ impl Item {
}
/// Crea un enlace para la navegación.
pub fn link(label: L10n, path: FnPathByContext) -> Self {
///
/// La ruta se obtiene invocando [`FnPathByContext`], que devuelve dinámicamente una
/// [`RoutePath`] en función del [`Context`]. El enlace se marca como `active` si la ruta actual
/// del *request* coincide con la ruta de destino (devuelta por `RoutePath::path`).
pub fn link(label: L10n, route: FnPathByContext) -> Self {
Item {
item_kind: ItemKind::Link {
label,
path,
route,
blank: false,
disabled: false,
},
@ -215,11 +220,11 @@ impl Item {
}
/// Crea un enlace deshabilitado que no permite la interacción.
pub fn link_disabled(label: L10n, path: FnPathByContext) -> Self {
pub fn link_disabled(label: L10n, route: FnPathByContext) -> Self {
Item {
item_kind: ItemKind::Link {
label,
path,
route,
blank: false,
disabled: true,
},
@ -228,11 +233,11 @@ impl Item {
}
/// Crea un enlace que se abre en una nueva ventana o pestaña.
pub fn link_blank(label: L10n, path: FnPathByContext) -> Self {
pub fn link_blank(label: L10n, route: FnPathByContext) -> Self {
Item {
item_kind: ItemKind::Link {
label,
path,
route,
blank: true,
disabled: false,
},
@ -241,11 +246,11 @@ impl Item {
}
/// Crea un enlace inicialmente deshabilitado que se abriría en una nueva ventana.
pub fn link_blank_disabled(label: L10n, path: FnPathByContext) -> Self {
pub fn link_blank_disabled(label: L10n, route: FnPathByContext) -> Self {
Item {
item_kind: ItemKind::Link {
label,
path,
route,
blank: true,
disabled: true,
},
@ -266,9 +271,9 @@ impl Item {
/// Crea un elemento de navegación que contiene un menú desplegable [`Dropdown`].
///
/// Sólo se tienen en cuenta **el título** (si no existe le asigna uno por defecto) y **la lista
/// de elementos** del [`Dropdown`]; el resto de propiedades del componente no afectarán a su
/// representación en [`Nav`].
/// Sólo se tienen en cuenta **el título** (si no existe, se asigna uno por defecto) y **la
/// lista de elementos** del [`Dropdown`]; el resto de propiedades del componente no afectarán
/// a su representación en [`Nav`].
pub fn dropdown(menu: Dropdown) -> Self {
Item {
item_kind: ItemKind::Dropdown(Typed::with(menu)),