Implementa temas hijo y macro render_component!

Añade `Theme::parent()` para declarar jerarquías de herencia entre
temas. Sustituye la acción `PrepareRender<C>` por el método
`Theme::prepare_component()` y la macro `render_component!`.
This commit is contained in:
Manuel Cillero 2026-03-22 08:58:15 +01:00
parent af309930f7
commit 4cbe84b4c0
14 changed files with 161 additions and 139 deletions

View file

@ -5,6 +5,3 @@ pub use before_render_component::*;
mod after_render_component;
pub use after_render_component::*;
mod prepare_render;
pub use prepare_render::*;

View file

@ -1,65 +0,0 @@
use crate::prelude::*;
/// Tipo de función para alterar el renderizado de un componente.
///
/// Permite a un [tema](crate::base::action::theme) sobreescribir el renderizado predeterminado de
/// los componentes.
///
/// Recibe una referencia al componente `component` y una referencia mutable al contexto `cx`.
pub type FnPrepareRender<C> = fn(component: &C, cx: &mut Context) -> Result<Markup, ComponentError>;
/// Ejecuta [`FnPrepareRender`] para preparar el renderizado de un componente.
///
/// Permite a un tema hacer una implementación nueva del renderizado de un componente.
pub struct PrepareRender<C: Component> {
f: FnPrepareRender<C>,
theme_type_id: Option<UniqueId>,
referer_type_id: Option<UniqueId>,
}
/// Filtro para despachar [`FnPrepareRender`] que modifica el renderizado de un componente `C`.
impl<C: Component> ActionDispatcher for PrepareRender<C> {
/// Devuelve el identificador de tipo ([`UniqueId`]) del tema.
fn theme_type_id(&self) -> Option<UniqueId> {
self.theme_type_id
}
/// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`.
fn referer_type_id(&self) -> Option<UniqueId> {
self.referer_type_id
}
}
impl<C: Component> PrepareRender<C> {
/// Permite [registrar](Extension::actions) una nueva acción [`FnPrepareRender`] para un tema
/// dado.
pub fn new(theme: ThemeRef, f: FnPrepareRender<C>) -> Self {
PrepareRender {
f,
theme_type_id: Some(theme.type_id()),
referer_type_id: Some(UniqueId::of::<C>()),
}
}
/// Despacha las acciones. Se detiene en cuanto una renderiza o produce un error.
#[inline]
pub(crate) fn dispatch(component: &C, cx: &mut Context) -> Result<Markup, ComponentError> {
let mut render_result: Result<Markup, ComponentError> = Ok(html! {});
dispatch_actions_until(
&ActionKey::new(
UniqueId::of::<Self>(),
Some(cx.theme().type_id()),
Some(UniqueId::of::<C>()),
None,
),
|action: &Self| match &render_result {
Ok(markup) if markup.is_empty() => {
render_result = (action.f)(component, cx);
std::ops::ControlFlow::Continue(())
}
_ => std::ops::ControlFlow::Break(()),
},
);
render_result
}
}