diff --git a/src/core/component.rs b/src/core/component.rs index 3691472..e5858cb 100644 --- a/src/core/component.rs +++ b/src/core/component.rs @@ -8,5 +8,5 @@ pub use children::Children; pub use children::{Child, ChildOp}; pub use children::{Typed, TypedOp}; -mod slot; -pub use slot::TypedSlot; +mod optional; +pub use optional::TypedOpt; diff --git a/src/core/component/optional.rs b/src/core/component/optional.rs new file mode 100644 index 0000000..c13b833 --- /dev/null +++ b/src/core/component/optional.rs @@ -0,0 +1,59 @@ +use crate::core::component::{Component, Typed}; +use crate::html::{html, Context, Markup}; +use crate::{builder_fn, AutoDefault}; + +/// Contenedor **opcional** para un componente [`Typed`]. +/// +/// Un `TypedOpt` actúa como un contenedor para incluir o no un subcomponente tipado. Internamente +/// encapsula `Option>`, pero ofrece una API más sencilla para construir estructuras +/// jerárquicas o contenidas de componentes. +/// +/// # Ejemplo +/// +/// ```rust +/// use pagetop::prelude::*; +/// +/// let icon = Icon::default(); +/// let icon = TypedOpt::new(icon); +/// assert!(icon.get().is_some()); +/// ``` +#[derive(AutoDefault)] +pub struct TypedOpt(Option>); + +impl TypedOpt { + /// Crea un nuevo [`TypedOpt`]. + /// + /// El componente se envuelve automáticamente en un [`Typed`] y se almacena. + pub fn new(component: C) -> Self { + TypedOpt(Some(Typed::with(component))) + } + + // TypedOpt BUILDER **************************************************************************** + + /// Establece un componente nuevo, o lo vacía. + /// + /// Si se proporciona `Some(component)`, se guarda como [`Typed`]; y si es `None`, se limpia. + #[builder_fn] + pub fn with_component(mut self, component: Option) -> Self { + self.0 = component.map(Typed::with); + self + } + + // TypedOpt GETTERS **************************************************************************** + + /// Devuelve un clon (incrementa el contador `Arc`) de [`Typed`], si existe. + pub fn get(&self) -> Option> { + self.0.clone() + } + + // TypedOpt 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! {} + } + } +} diff --git a/src/core/component/slot.rs b/src/core/component/slot.rs deleted file mode 100644 index 19ed72a..0000000 --- a/src/core/component/slot.rs +++ /dev/null @@ -1,64 +0,0 @@ -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>`, 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(Option>); - -impl Default for TypedSlot { - fn default() -> Self { - TypedSlot(None) - } -} - -impl TypedSlot { - /// 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) -> Self { - self.0 = component.map(Typed::with); - self - } - - // TypedSlot GETTERS ********************************************************************* - - /// Devuelve un clon (incrementa el contador `Arc`) de [`Typed`], si existe. - pub fn get(&self) -> Option> { - 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! {} - } - } -} diff --git a/src/html.rs b/src/html.rs index 4858bbf..89d19d4 100644 --- a/src/html.rs +++ b/src/html.rs @@ -50,14 +50,14 @@ pub type OptionClasses = AttrClasses; use crate::{core, AutoDefault}; -/// **Obsoleto desde la versión 0.4.0**: usar [`TypedSlot`](crate::core::component::TypedSlot) en su +/// **Obsoleto desde la versión 0.4.0**: usar [`TypedOpt`](crate::core::component::TypedOpt) en su /// lugar. #[deprecated( since = "0.4.0", - note = "Use `pagetop::core::component::TypedSlot` instead" + note = "Use `pagetop::core::component::TypedOpt` instead" )] #[allow(type_alias_bounds)] -pub type OptionComponent = core::component::TypedSlot; +pub type OptionComponent = core::component::TypedOpt; /// Prepara contenido HTML para su conversión a [`Markup`]. ///