♻️ (html): Cambia tipos Option... por Attr...

Renombra los tipos para atributos HTML `Id`, `Name`, `Value` (`String`),
`L10n` (`Translate`) y `Classes`. Y mueve `OptionComponent` al *core* de
componentes como `TypedSlot`.
This commit is contained in:
Manuel Cillero 2025-08-23 18:52:45 +02:00
parent e08c412a36
commit 5ef85154b5
17 changed files with 367 additions and 311 deletions

View file

@ -0,0 +1,64 @@
use crate::builder_fn;
use crate::core::component::{Component, Typed};
use crate::html::{html, Context, Markup};
/// Contenedor para un componente [`Typed`] opcional.
///
/// Un `TypedSlot` actúa como un contenedor dentro de otro componente para incluir o no un
/// subcomponente. Internamente encapsula `Option<Typed<C>>`, pero proporciona una API más sencilla
/// para construir estructuras jerárquicas.
///
/// # Ejemplo
///
/// ```rust,ignore
/// use pagetop::prelude::*;
///
/// let comp = MyComponent::new();
/// let opt = TypedSlot::new(comp);
/// assert!(opt.get().is_some());
/// ```
pub struct TypedSlot<C: Component>(Option<Typed<C>>);
impl<C: Component> Default for TypedSlot<C> {
fn default() -> Self {
TypedSlot(None)
}
}
impl<C: Component> TypedSlot<C> {
/// Crea un nuevo [`TypedSlot`].
///
/// El componente se envuelve automáticamente en un [`Typed`] y se almacena.
pub fn new(component: C) -> Self {
TypedSlot(Some(Typed::with(component)))
}
// TypedSlot BUILDER *********************************************************************
/// Establece un componente nuevo, o lo vacía.
///
/// Si se proporciona `Some(component)`, se guarda en [`Typed`]; y si es `None`, se limpia.
#[builder_fn]
pub fn with_value(mut self, component: Option<C>) -> Self {
self.0 = component.map(Typed::with);
self
}
// TypedSlot GETTERS *********************************************************************
/// Devuelve un clon (incrementa el contador `Arc`) de [`Typed<C>`], si existe.
pub fn get(&self) -> Option<Typed<C>> {
self.0.clone()
}
// TypedSlot RENDER ************************************************************************
/// Renderiza el componente, si existe.
pub fn render(&self, cx: &mut Context) -> Markup {
if let Some(component) = &self.0 {
component.render(cx)
} else {
html! {}
}
}
}