WIP: Añade componente para la gestión de menús #8
5 changed files with 258 additions and 189 deletions
|
|
@ -12,8 +12,9 @@ pub mod dropdown;
|
||||||
pub use dropdown::Dropdown;
|
pub use dropdown::Dropdown;
|
||||||
|
|
||||||
// Image.
|
// Image.
|
||||||
mod image;
|
pub mod image;
|
||||||
pub use image::{Image, ImageSize};
|
#[doc(inline)]
|
||||||
|
pub use image::Image;
|
||||||
|
|
||||||
// Navbar.
|
// Navbar.
|
||||||
pub mod navbar;
|
pub mod navbar;
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,7 @@ impl Container {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Establece esquinas redondeadas para el contenedor.
|
/// Establece esquinas redondeadas para el contenedor ([`Rounded`]).
|
||||||
#[builder_fn]
|
#[builder_fn]
|
||||||
pub fn with_rounded(mut self, rounded: Rounded) -> Self {
|
pub fn with_rounded(mut self, rounded: Rounded) -> Self {
|
||||||
self.rounded = rounded;
|
self.rounded = rounded;
|
||||||
|
|
@ -282,12 +282,12 @@ impl Container {
|
||||||
&self.text_color
|
&self.text_color
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Devuelve el borde del contenedor.
|
/// Devuelve el borde configurado del contenedor.
|
||||||
pub fn border(&self) -> &Border {
|
pub fn border(&self) -> &Border {
|
||||||
&self.border
|
&self.border
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Devuelve las esquinas redondeadas del contenedor.
|
/// Devuelve las esquinas redondeadas configuradas para el contenedor.
|
||||||
pub fn rounded(&self) -> &Rounded {
|
pub fn rounded(&self) -> &Rounded {
|
||||||
&self.rounded
|
&self.rounded
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,186 +1,7 @@
|
||||||
use pagetop::prelude::*;
|
//! Definiciones para renderizar imágenes ([`Image`]).
|
||||||
|
|
||||||
use crate::prelude::*;
|
mod props;
|
||||||
|
pub use props::{Size, Source};
|
||||||
|
|
||||||
#[derive(AutoDefault)]
|
mod component;
|
||||||
pub enum ImageSource {
|
pub use component::Image;
|
||||||
#[default]
|
|
||||||
//Logo(PageTopLogo),
|
|
||||||
Responsive(String),
|
|
||||||
Thumbnail(String),
|
|
||||||
Static(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub enum ImageSize {
|
|
||||||
#[default]
|
|
||||||
Auto,
|
|
||||||
Dimensions(UnitValue, UnitValue),
|
|
||||||
Width(UnitValue),
|
|
||||||
Height(UnitValue),
|
|
||||||
Both(UnitValue),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
#[derive(AutoDefault)]
|
|
||||||
pub struct Image {
|
|
||||||
id : AttrId,
|
|
||||||
classes: AttrClasses,
|
|
||||||
source : ImageSource,
|
|
||||||
alt : AttrL10n,
|
|
||||||
size : ImageSize,
|
|
||||||
border : Border,
|
|
||||||
rounded: Rounded,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Component for Image {
|
|
||||||
fn new() -> Self {
|
|
||||||
Image::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id(&self) -> Option<String> {
|
|
||||||
self.id.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
|
||||||
self.alter_classes(
|
|
||||||
ClassesOp::Prepend,
|
|
||||||
[
|
|
||||||
String::from(match self.source() {
|
|
||||||
//ImageSource::Logo(_) => "img-fluid",
|
|
||||||
ImageSource::Responsive(_) => "img-fluid",
|
|
||||||
ImageSource::Thumbnail(_) => "img-thumbnail",
|
|
||||||
_ => "",
|
|
||||||
}),
|
|
||||||
self.border().to_string(),
|
|
||||||
self.rounded().to_string(),
|
|
||||||
]
|
|
||||||
.join(" "),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
|
||||||
let dimensions = match self.size() {
|
|
||||||
ImageSize::Auto => None,
|
|
||||||
ImageSize::Dimensions(w, h) => {
|
|
||||||
let w = w.to_string();
|
|
||||||
let h = h.to_string();
|
|
||||||
Some(join!("width: ", w, "; height: ", h, ";"))
|
|
||||||
}
|
|
||||||
ImageSize::Width(w) => {
|
|
||||||
let w = w.to_string();
|
|
||||||
Some(join!("width: ", w, ";"))
|
|
||||||
}
|
|
||||||
ImageSize::Height(h) => {
|
|
||||||
let h = h.to_string();
|
|
||||||
Some(join!("height: ", h, ";"))
|
|
||||||
}
|
|
||||||
ImageSize::Both(v) => {
|
|
||||||
let v = v.to_string();
|
|
||||||
Some(join!("width: ", v, "; height: ", v, ";"))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let source = match self.source() {
|
|
||||||
/*
|
|
||||||
ImageSource::Logo(logo) => {
|
|
||||||
return PrepareMarkup::With(html! {
|
|
||||||
span
|
|
||||||
id=[self.id()]
|
|
||||||
class=[self.classes().get()]
|
|
||||||
style=[dimensions]
|
|
||||||
{
|
|
||||||
(logo.render(cx))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
ImageSource::Responsive(source) => Some(source),
|
|
||||||
ImageSource::Thumbnail(source) => Some(source),
|
|
||||||
ImageSource::Static(source) => Some(source),
|
|
||||||
};
|
|
||||||
PrepareMarkup::With(html! {
|
|
||||||
img
|
|
||||||
src=[source]
|
|
||||||
alt=[self.alternative().lookup(cx)]
|
|
||||||
id=[self.id()]
|
|
||||||
class=[self.classes().get()]
|
|
||||||
style=[dimensions] {}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Image {
|
|
||||||
pub fn with(source: ImageSource) -> Self {
|
|
||||||
Image::default().with_source(source)
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< Image BUILDER >**************************************************************************
|
|
||||||
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_id(mut self, id: impl AsRef<str>) -> Self {
|
|
||||||
self.id.alter_value(id);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef<str>) -> Self {
|
|
||||||
self.classes.alter_value(op, classes);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_source(mut self, source: ImageSource) -> Self {
|
|
||||||
self.source = source;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_alternative(mut self, alt: L10n) -> Self {
|
|
||||||
self.alt.alter_value(alt);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_size(mut self, size: ImageSize) -> Self {
|
|
||||||
self.size = size;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_border(mut self, border: Border) -> Self {
|
|
||||||
self.border = border;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[builder_fn]
|
|
||||||
pub fn with_rounded(mut self, rounded: Rounded) -> Self {
|
|
||||||
self.rounded = rounded;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
// **< Image GETTERS >**************************************************************************
|
|
||||||
|
|
||||||
pub fn classes(&self) -> &AttrClasses {
|
|
||||||
&self.classes
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn source(&self) -> &ImageSource {
|
|
||||||
&self.source
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn alternative(&self) -> &AttrL10n {
|
|
||||||
&self.alt
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size(&self) -> &ImageSize {
|
|
||||||
&self.size
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn border(&self) -> &Border {
|
|
||||||
&self.border
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rounded(&self) -> &Rounded {
|
|
||||||
&self.rounded
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
194
extensions/pagetop-bootsier/src/theme/image/component.rs
Normal file
194
extensions/pagetop-bootsier/src/theme/image/component.rs
Normal file
|
|
@ -0,0 +1,194 @@
|
||||||
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// Componente para renderizar una **imagen**.
|
||||||
|
///
|
||||||
|
/// - Ajusta su disposición según el origen definido en [`image::Source`].
|
||||||
|
/// - Permite configurar **dimensiones** ([`with_size()`](Self::with_size)), **borde**
|
||||||
|
/// ([`with_border()`](Self::with_border)) y **redondeo de esquinas**
|
||||||
|
/// ([`with_rounded()`](Self::with_rounded)).
|
||||||
|
/// - Resuelve el texto alternativo `alt` con **localización** mediante [`L10n`].
|
||||||
|
#[rustfmt::skip]
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub struct Image {
|
||||||
|
id : AttrId,
|
||||||
|
classes: AttrClasses,
|
||||||
|
size : image::Size,
|
||||||
|
source : image::Source,
|
||||||
|
alt : AttrL10n,
|
||||||
|
border : Border,
|
||||||
|
rounded: Rounded,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Image {
|
||||||
|
fn new() -> Self {
|
||||||
|
Image::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<String> {
|
||||||
|
self.id.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
||||||
|
self.alter_classes(
|
||||||
|
ClassesOp::Prepend,
|
||||||
|
[
|
||||||
|
String::from(match self.source() {
|
||||||
|
image::Source::Logo(_) => "img-fluid",
|
||||||
|
image::Source::Responsive(_) => "img-fluid",
|
||||||
|
image::Source::Thumbnail(_) => "img-thumbnail",
|
||||||
|
image::Source::Plain(_) => "",
|
||||||
|
}),
|
||||||
|
self.border().to_string(),
|
||||||
|
self.rounded().to_string(),
|
||||||
|
]
|
||||||
|
.join(" "),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||||
|
let dimensions = match self.size() {
|
||||||
|
image::Size::Auto => None,
|
||||||
|
image::Size::Dimensions(w, h) => {
|
||||||
|
let w = w.to_string();
|
||||||
|
let h = h.to_string();
|
||||||
|
Some(join!("width: ", w, "; height: ", h, ";"))
|
||||||
|
}
|
||||||
|
image::Size::Width(w) => {
|
||||||
|
let w = w.to_string();
|
||||||
|
Some(join!("width: ", w, ";"))
|
||||||
|
}
|
||||||
|
image::Size::Height(h) => {
|
||||||
|
let h = h.to_string();
|
||||||
|
Some(join!("height: ", h, ";"))
|
||||||
|
}
|
||||||
|
image::Size::Both(v) => {
|
||||||
|
let v = v.to_string();
|
||||||
|
Some(join!("width: ", v, "; height: ", v, ";"))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let alt_text = self.alternative().lookup(cx).unwrap_or_default();
|
||||||
|
let is_decorative = alt_text.is_empty();
|
||||||
|
let source = match self.source() {
|
||||||
|
image::Source::Logo(logo) => {
|
||||||
|
return PrepareMarkup::With(html! {
|
||||||
|
span
|
||||||
|
id=[self.id()]
|
||||||
|
class=[self.classes().get()]
|
||||||
|
style=[dimensions]
|
||||||
|
role=[(!is_decorative).then_some("img")]
|
||||||
|
aria-label=[(!is_decorative).then_some(alt_text)]
|
||||||
|
aria-hidden=[is_decorative.then_some("true")]
|
||||||
|
{
|
||||||
|
(logo.render(cx))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
image::Source::Responsive(source) => Some(source),
|
||||||
|
image::Source::Thumbnail(source) => Some(source),
|
||||||
|
image::Source::Plain(source) => Some(source),
|
||||||
|
};
|
||||||
|
PrepareMarkup::With(html! {
|
||||||
|
img
|
||||||
|
src=[source]
|
||||||
|
alt=(alt_text)
|
||||||
|
id=[self.id()]
|
||||||
|
class=[self.classes().get()]
|
||||||
|
style=[dimensions] {}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Image {
|
||||||
|
/// Crea rápidamente una imagen especificando su origen.
|
||||||
|
pub fn with(source: image::Source) -> Self {
|
||||||
|
Image::default().with_source(source)
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Image BUILDER >**************************************************************************
|
||||||
|
|
||||||
|
/// Establece el identificador único (`id`) de la imagen.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_id(mut self, id: impl AsRef<str>) -> Self {
|
||||||
|
self.id.alter_value(id);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modifica la lista de clases CSS aplicadas a la imagen.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_classes(mut self, op: ClassesOp, classes: impl AsRef<str>) -> Self {
|
||||||
|
self.classes.alter_value(op, classes);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Define las dimensiones de la imagen (auto, ancho/alto, ambos).
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_size(mut self, size: image::Size) -> Self {
|
||||||
|
self.size = size;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el origen de la imagen, influyendo en su disposición en el contenido.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_source(mut self, source: image::Source) -> Self {
|
||||||
|
self.source = source;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Define el texto alternativo localizado ([`L10n`]) para la imagen.
|
||||||
|
///
|
||||||
|
/// Se recomienda siempre aportar un texto alternativo salvo que la imagen sea puramente
|
||||||
|
/// decorativa.
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_alternative(mut self, alt: L10n) -> Self {
|
||||||
|
self.alt.alter_value(alt);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece el borde de la imagen ([`Border`]).
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_border(mut self, border: Border) -> Self {
|
||||||
|
self.border = border;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Establece esquinas redondeadas para la imagen ([`Rounded`]).
|
||||||
|
#[builder_fn]
|
||||||
|
pub fn with_rounded(mut self, rounded: Rounded) -> Self {
|
||||||
|
self.rounded = rounded;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Image GETTERS >**************************************************************************
|
||||||
|
|
||||||
|
/// Devuelve las clases CSS asociadas a la imagen.
|
||||||
|
pub fn classes(&self) -> &AttrClasses {
|
||||||
|
&self.classes
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Devuelve las dimensiones de la imagen.
|
||||||
|
pub fn size(&self) -> &image::Size {
|
||||||
|
&self.size
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Devuelve el origen de la imagen.
|
||||||
|
pub fn source(&self) -> &image::Source {
|
||||||
|
&self.source
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Devuelve el texto alternativo localizado.
|
||||||
|
pub fn alternative(&self) -> &AttrL10n {
|
||||||
|
&self.alt
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Devuelve el borde configurado de la imagen.
|
||||||
|
pub fn border(&self) -> &Border {
|
||||||
|
&self.border
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Devuelve las esquinas redondeadas configuradas para la imagen.
|
||||||
|
pub fn rounded(&self) -> &Rounded {
|
||||||
|
&self.rounded
|
||||||
|
}
|
||||||
|
}
|
||||||
53
extensions/pagetop-bootsier/src/theme/image/props.rs
Normal file
53
extensions/pagetop-bootsier/src/theme/image/props.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
use pagetop::prelude::*;
|
||||||
|
|
||||||
|
// **< Size >***************************************************************************************
|
||||||
|
|
||||||
|
/// Define las **dimensiones** de una imagen ([`Image`](crate::theme::Image)).
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub enum Size {
|
||||||
|
/// Ajuste automático por defecto.
|
||||||
|
///
|
||||||
|
/// La imagen usa su tamaño natural o se ajusta al contenedor donde se publica.
|
||||||
|
#[default]
|
||||||
|
Auto,
|
||||||
|
/// Establece explícitamente el **ancho y alto** de la imagen.
|
||||||
|
///
|
||||||
|
/// Útil cuando se desea fijar ambas dimensiones de forma exacta. Ten en cuenta que la imagen
|
||||||
|
/// puede distorsionarse si no se mantiene la proporción original.
|
||||||
|
Dimensions(UnitValue, UnitValue),
|
||||||
|
/// Establece sólo el **ancho** de la imagen.
|
||||||
|
///
|
||||||
|
/// La altura se ajusta proporcionalmente de manera automática.
|
||||||
|
Width(UnitValue),
|
||||||
|
/// Establece sólo la **altura** de la imagen.
|
||||||
|
///
|
||||||
|
/// El ancho se ajusta proporcionalmente de manera automática.
|
||||||
|
Height(UnitValue),
|
||||||
|
/// Establece **el mismo valor** para el ancho y el alto de la imagen.
|
||||||
|
///
|
||||||
|
/// Práctico para forzar rápidamente un área cuadrada. Ten en cuenta que la imagen puede
|
||||||
|
/// distorsionarse si la original no es cuadrada.
|
||||||
|
Both(UnitValue),
|
||||||
|
}
|
||||||
|
|
||||||
|
// **< Source >*************************************************************************************
|
||||||
|
|
||||||
|
/// Especifica la **fuente** para publicar una imagen ([`Image`](crate::theme::Image)).
|
||||||
|
#[derive(AutoDefault)]
|
||||||
|
pub enum Source {
|
||||||
|
/// Imagen con el logotipo de PageTop.
|
||||||
|
#[default]
|
||||||
|
Logo(PageTopSvg),
|
||||||
|
/// Imagen que se adapta automáticamente a su contenedor.
|
||||||
|
///
|
||||||
|
/// El `String` asociado es la URL (o ruta) de la imagen.
|
||||||
|
Responsive(String),
|
||||||
|
/// Imagen que aplica el estilo **miniatura** de Bootstrap.
|
||||||
|
///
|
||||||
|
/// El `String` asociado es la URL (o ruta) de la imagen.
|
||||||
|
Thumbnail(String),
|
||||||
|
/// Imagen sin clases específicas de Bootstrap, útil para controlar con CSS propio.
|
||||||
|
///
|
||||||
|
/// El `String` asociado es la URL (o ruta) de la imagen.
|
||||||
|
Plain(String),
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue