♻️ [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:
parent
75eec8bebc
commit
bb34ba5887
17 changed files with 367 additions and 311 deletions
|
@ -7,3 +7,6 @@ mod children;
|
|||
pub use children::Children;
|
||||
pub use children::{Child, ChildOp};
|
||||
pub use children::{Typed, TypedOp};
|
||||
|
||||
mod slot;
|
||||
pub use slot::TypedSlot;
|
||||
|
|
|
@ -9,13 +9,13 @@ use std::vec::IntoIter;
|
|||
|
||||
/// Representa un componente encapsulado de forma segura y compartida.
|
||||
///
|
||||
/// Esta estructura permite manipular y renderizar cualquier tipo que implemente [`Component`],
|
||||
/// garantizando acceso concurrente a través de [`Arc<RwLock<_>>`].
|
||||
/// Esta estructura permite manipular y renderizar un componente que implemente [`Component`], y
|
||||
/// habilita acceso concurrente mediante [`Arc<RwLock<_>>`].
|
||||
#[derive(Clone)]
|
||||
pub struct Child(Arc<RwLock<dyn Component>>);
|
||||
|
||||
impl Child {
|
||||
/// Crea un nuevo [`Child`] a partir de un componente.
|
||||
/// Crea un nuevo `Child` a partir de un componente.
|
||||
pub fn with(component: impl Component) -> Self {
|
||||
Child(Arc::new(RwLock::new(component)))
|
||||
}
|
||||
|
@ -46,7 +46,8 @@ impl Child {
|
|||
|
||||
/// Variante tipada de [`Child`] para evitar conversiones durante el uso.
|
||||
///
|
||||
/// Facilita el acceso a componentes del mismo tipo sin necesidad de hacer `downcast`.
|
||||
/// Esta estructura permite manipular y renderizar un componente concreto que implemente
|
||||
/// [`Component`], y habilita acceso concurrente mediante [`Arc<RwLock<_>>`].
|
||||
pub struct Typed<C: Component>(Arc<RwLock<C>>);
|
||||
|
||||
impl<C: Component> Clone for Typed<C> {
|
||||
|
@ -56,7 +57,7 @@ impl<C: Component> Clone for Typed<C> {
|
|||
}
|
||||
|
||||
impl<C: Component> Typed<C> {
|
||||
/// Crea un nuevo [`Typed`] a partir de un componente.
|
||||
/// Crea un nuevo `Typed` a partir de un componente.
|
||||
pub fn with(component: C) -> Self {
|
||||
Typed(Arc::new(RwLock::new(component)))
|
||||
}
|
||||
|
@ -284,7 +285,7 @@ impl IntoIterator for Children {
|
|||
///
|
||||
/// # Ejemplo de uso:
|
||||
///
|
||||
/// ```rust#ignore
|
||||
/// ```rust,ignore
|
||||
/// let children = Children::new().with(child1).with(child2);
|
||||
/// for child in children {
|
||||
/// println!("{:?}", child.id());
|
||||
|
@ -303,7 +304,7 @@ impl<'a> IntoIterator for &'a Children {
|
|||
///
|
||||
/// # Ejemplo de uso:
|
||||
///
|
||||
/// ```rust#ignore
|
||||
/// ```rust,ignore
|
||||
/// let children = Children::new().with(child1).with(child2);
|
||||
/// for child in &children {
|
||||
/// println!("{:?}", child.id());
|
||||
|
@ -322,7 +323,7 @@ impl<'a> IntoIterator for &'a mut Children {
|
|||
///
|
||||
/// # Ejemplo de uso:
|
||||
///
|
||||
/// ```rust#ignore
|
||||
/// ```rust,ignore
|
||||
/// let mut children = Children::new().with(child1).with(child2);
|
||||
/// for child in &mut children {
|
||||
/// child.render(&mut context);
|
||||
|
|
64
src/core/component/slot.rs
Normal file
64
src/core/component/slot.rs
Normal 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! {}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue