♻️ (bootsier): Mueve Brand al core de PageTop
This commit is contained in:
parent
bf4c635e59
commit
fe2b2c176f
5 changed files with 134 additions and 81 deletions
|
|
@ -143,6 +143,8 @@ impl Theme for Bootsier {
|
||||||
cx: &mut Context,
|
cx: &mut Context,
|
||||||
) -> Option<Result<Markup, ComponentError>> {
|
) -> Option<Result<Markup, ComponentError>> {
|
||||||
setup_component!(component, {
|
setup_component!(component, {
|
||||||
|
Badge => |c| theme::bs::badge::setup(c),
|
||||||
|
Brand => |c| theme::bs::brand::setup(c),
|
||||||
Button => |c| theme::bs::button::setup(c),
|
Button => |c| theme::bs::button::setup(c),
|
||||||
Container => |c| theme::bs::container::setup(c),
|
Container => |c| theme::bs::container::setup(c),
|
||||||
Image => |c| theme::bs::image::setup(c),
|
Image => |c| theme::bs::image::setup(c),
|
||||||
|
|
|
||||||
9
extensions/pagetop-bootsier/src/theme/bs/brand.rs
Normal file
9
extensions/pagetop-bootsier/src/theme/bs/brand.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
pub use pagetop::base::component::Brand;
|
||||||
|
|
||||||
|
// **< Brand SETUP >********************************************************************************
|
||||||
|
|
||||||
|
pub(crate) fn setup(brand: &mut Brand) {
|
||||||
|
brand.alter_prop(PropsOp::replace_classes("brand", "navbar-brand"));
|
||||||
|
}
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
use pagetop::prelude::*;
|
|
||||||
|
|
||||||
use crate::theme::*;
|
|
||||||
|
|
||||||
/// Marca de identidad para mostrar en una barra de navegación [`Navbar`](crate::theme::bs::Navbar).
|
|
||||||
///
|
|
||||||
/// Representa la identidad del sitio con una imagen, título y eslogan:
|
|
||||||
///
|
|
||||||
/// - Si hay URL ([`with_route()`](Self::with_route)), el bloque completo actúa como enlace. Por
|
|
||||||
/// defecto enlaza a la raíz del sitio (`/`).
|
|
||||||
/// - Si no hay imagen ([`with_image()`](Self::with_image)) ni título
|
|
||||||
/// ([`with_title()`](Self::with_title)), la marca de identidad no se renderiza.
|
|
||||||
/// - El eslogan ([`with_slogan()`](Self::with_slogan)) es opcional; por defecto no tiene contenido.
|
|
||||||
#[derive(AutoDefault, Clone, Debug, Getters)]
|
|
||||||
pub struct Brand {
|
|
||||||
/// Devuelve la imagen de marca (si la hay).
|
|
||||||
image: Embed<bs::Image>,
|
|
||||||
/// Devuelve el título de la identidad de marca.
|
|
||||||
#[default(_code = "Lc::n(&global::SETTINGS.app.name)")]
|
|
||||||
title: Lc,
|
|
||||||
/// Devuelve el eslogan de la marca.
|
|
||||||
slogan: Lc,
|
|
||||||
/// Devuelve la ruta asociada a la marca (si existe).
|
|
||||||
#[default(_code = "Some(\"/\".into())")]
|
|
||||||
route: Option<Route>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl Component for Brand {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
|
||||||
let image = self.image().render(cx).await;
|
|
||||||
let title = self.title().using(cx);
|
|
||||||
if title.is_empty() && image.is_empty() {
|
|
||||||
return Ok(html! {});
|
|
||||||
}
|
|
||||||
let slogan = self.slogan().using(cx);
|
|
||||||
Ok(html! {
|
|
||||||
@if let Some(route) = self.route() {
|
|
||||||
a class="navbar-brand" href=(route.resolve(cx)) { (image) (title) (slogan) }
|
|
||||||
} @else {
|
|
||||||
span class="navbar-brand" { (image) (title) (slogan) }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Brand {
|
|
||||||
// **< Brand BUILDER >**************************************************************************
|
|
||||||
|
|
||||||
/// Asigna o quita la imagen de marca. Si se pasa `None`, no se mostrará.
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_image(mut self, image: Option<bs::Image>) -> Self {
|
|
||||||
self.image.alter_component(image);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Establece el título de la identidad de marca.
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_title(mut self, title: Lc) -> Self {
|
|
||||||
self.title = title;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Define el eslogan de la marca.
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_slogan(mut self, slogan: Lc) -> Self {
|
|
||||||
self.slogan = slogan;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Define la ruta de destino. Si es `None`, la marca no será un enlace.
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_route(mut self, route: Option<Route>) -> Self {
|
|
||||||
self.route = route;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,6 +5,9 @@ pub mod layout;
|
||||||
mod badge;
|
mod badge;
|
||||||
pub use badge::Badge;
|
pub use badge::Badge;
|
||||||
|
|
||||||
|
mod brand;
|
||||||
|
pub use brand::Brand;
|
||||||
|
|
||||||
pub mod breadcrumb;
|
pub mod breadcrumb;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use breadcrumb::Breadcrumb;
|
pub use breadcrumb::Breadcrumb;
|
||||||
|
|
|
||||||
120
src/base/component/brand.rs
Normal file
120
src/base/component/brand.rs
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// Componente para mostrar la **identidad de marca** de un sitio o aplicación.
|
||||||
|
///
|
||||||
|
/// Combina una imagen, un título y un eslogan opcional, típicamente en la cabecera de la página o
|
||||||
|
/// dentro de una barra de navegación proporcionada por un tema.
|
||||||
|
///
|
||||||
|
/// - Si hay ruta ([`with_route()`]), el bloque completo actúa como enlace. Por defecto enlaza a la
|
||||||
|
/// raíz del sitio (`/`).
|
||||||
|
/// - Si no hay imagen ([`with_image()`]) ni título ([`with_title()`]), la marca de identidad no se
|
||||||
|
/// renderiza.
|
||||||
|
/// - El eslogan ([`with_slogan()`]) es opcional; por defecto no tiene contenido.
|
||||||
|
///
|
||||||
|
/// # Ejemplo
|
||||||
|
///
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// use pagetop::prelude::*;
|
||||||
|
///
|
||||||
|
/// let brand = Brand::new()
|
||||||
|
/// .with_image(Some(Image::with(image::Source::logo(PageTopSvg::Color))))
|
||||||
|
/// .with_title(Lc::n("PageTop"))
|
||||||
|
/// .with_route(Route::from("/"));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`with_route()`]: Self::with_route
|
||||||
|
/// [`with_image()`]: Self::with_image
|
||||||
|
/// [`with_title()`]: Self::with_title
|
||||||
|
/// [`with_slogan()`]: Self::with_slogan
|
||||||
|
#[derive(AutoDefault, Clone, Debug, Getters)]
|
||||||
|
pub struct Brand {
|
||||||
|
/// Devuelve identificador, clases CSS, atributos HTML y valores extra del componente.
|
||||||
|
props: Props,
|
||||||
|
/// Devuelve la imagen de marca (si la hay).
|
||||||
|
image: Embed<Image>,
|
||||||
|
/// Devuelve el título de la identidad de marca.
|
||||||
|
#[default(_code = "Lc::n(&global::SETTINGS.app.name)")]
|
||||||
|
title: Lc,
|
||||||
|
/// Devuelve el eslogan de la marca.
|
||||||
|
slogan: Lc,
|
||||||
|
/// Devuelve la ruta asociada a la marca (si existe).
|
||||||
|
#[default(_code = "Some(\"/\".into())")]
|
||||||
|
route: Option<Route>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Component for Brand {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<String> {
|
||||||
|
self.props.get_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(&mut self, _cx: &Context) {
|
||||||
|
self.alter_prop(PropsOp::prepend_classes("brand"));
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
|
||||||
|
let image = self.image().render(cx).await;
|
||||||
|
let title = self.title().using(cx);
|
||||||
|
if image.is_empty() && title.is_empty() {
|
||||||
|
return Ok(html! {});
|
||||||
|
}
|
||||||
|
let slogan = self.slogan().using(cx);
|
||||||
|
Ok(html! {
|
||||||
|
@if let Some(route) = self.route() {
|
||||||
|
a (self.props()) href=(route.resolve(cx)) { (image) (title) (slogan) }
|
||||||
|
} @else {
|
||||||
|
span (self.props()) { (image) (title) (slogan) }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Brand {
|
||||||
|
// **< Brand BUILDER >**************************************************************************
|
||||||
|
|
||||||
|
/// Establece el identificador único del componente; igual a `with_prop(PropsOp::set_id(id))`.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_id(mut self, id: impl Into<CowStr>) -> Self {
|
||||||
|
self.props.alter_id(id);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modifica identificador, clases CSS, atributos HTML o valores extra del componente.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_prop(mut self, op: PropsOp) -> Self {
|
||||||
|
self.props.alter_prop(op);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asigna o quita la imagen de marca. Si se pasa `None`, no se mostrará.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_image(mut self, image: impl Into<Option<Image>>) -> Self {
|
||||||
|
self.image.alter_component(image);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el título de la identidad de marca.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_title(mut self, title: Lc) -> Self {
|
||||||
|
self.title = title;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Define el eslogan de la marca.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_slogan(mut self, slogan: Lc) -> Self {
|
||||||
|
self.slogan = slogan;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Define la ruta de destino. Si es `None`, la marca no será un enlace.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_route(mut self, route: impl Into<Option<Route>>) -> Self {
|
||||||
|
self.route = route.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue