[bootsier] Añade opción para configurar ancho

This commit is contained in:
Manuel Cillero 2025-01-04 08:44:45 +01:00
parent 70f46c8a3d
commit 7039ca6b68
6 changed files with 116 additions and 38 deletions

View file

@ -17,6 +17,7 @@ license = { workspace = true }
[dependencies] [dependencies]
pagetop.workspace = true pagetop.workspace = true
serde.workspace = true
static-files.workspace = true static-files.workspace = true
[build-dependencies] [build-dependencies]

View file

@ -11,22 +11,27 @@ pub mod grid;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(AutoDefault)] #[derive(AutoDefault)]
pub enum BreakPoint { pub enum BreakPoint {
#[default] #[default] // DIMENSIONES - DISPOSITIVOS ---------------------------------------------------
None, // < 576px (Dispositivos muy pequeños: teléfonos en modo vertical, menos de 576px) None, // < 576px Muy pequeños: teléfonos en modo vertical, menos de 576px
SM, // >= 576px (Dispositivos pequeños: teléfonos en modo horizontal, 576px o más) SM, // >= 576px Pequeños: teléfonos en modo horizontal, 576px o más
MD, // >= 768px (Dispositivos medianos: tabletas, 768px o más) MD, // >= 768px Medianos: tabletas, 768px o más
LG, // >= 992px (Dispositivos grandes: puestos de escritorio, 992px o más) LG, // >= 992px Grandes: puestos de escritorio, 992px o más
XL, // >= 1200px (Dispositivos muy grandes: puestos de escritorio grandes, 1200px o más) XL, // >= 1200px Muy grandes: puestos de escritorio grandes, 1200px o más
XXL, // >= 1400px (Dispositivos extragrandes: puestos de escritorio más grandes, 1400px o más) XXL, // >= 1400px Extragrandes: puestos de escritorio más grandes, 1400px o más
Fluid, // Siempre aplica el 100% del dispositivo // ------------------------------------------------------------------------------
Fluid, // Para Container, aplica el 100% del dispositivo siempre
FluidMax(unit::Value) // Para Container, aplica el 100% del dispositivo hasta un ancho máximo
} }
impl BreakPoint { impl BreakPoint {
/// Indica si se trata de un punto de interrupción de Bootstrap. /// Indica si se trata de un punto de interrupción de Bootstrap.
/// Devuelve `true` si el valor es SM, MD, LG, XL o XXL. /// Devuelve `true` si el valor es SM, MD, LG, XL o XXL.
/// Devuelve `false` si es None o Fluid. /// Devuelve `false` si es None, Fluid o FluidMax.
pub fn is_breakpoint(&self) -> bool { pub fn is_breakpoint(&self) -> bool {
!matches!(self, BreakPoint::None | BreakPoint::Fluid) !matches!(
self,
BreakPoint::None | BreakPoint::Fluid | BreakPoint::FluidMax(_)
)
} }
} }
@ -42,6 +47,7 @@ impl fmt::Display for BreakPoint {
BreakPoint::XL => write!(f, "xl"), BreakPoint::XL => write!(f, "xl"),
BreakPoint::XXL => write!(f, "xxl"), BreakPoint::XXL => write!(f, "xxl"),
BreakPoint::Fluid => write!(f, "fluid"), BreakPoint::Fluid => write!(f, "fluid"),
BreakPoint::FluidMax(_) => write!(f, "fluid"),
} }
} }
} }

View file

@ -45,34 +45,39 @@ impl ComponentTrait for Container {
if output.is_empty() { if output.is_empty() {
return PrepareMarkup::None; return PrepareMarkup::None;
} }
let style = if let BreakPoint::FluidMax(max_width) = self.breakpoint() {
Some(join_string!("max-width: ", max_width.to_string(), ";"))
} else {
None
};
match self.container_type() { match self.container_type() {
ContainerType::Default => PrepareMarkup::With(html! { ContainerType::Default => PrepareMarkup::With(html! {
div id=[self.id()] class=[self.classes().get()] { div id=[self.id()] class=[self.classes().get()] style=[style] {
(output) (output)
} }
}), }),
ContainerType::Main => PrepareMarkup::With(html! { ContainerType::Main => PrepareMarkup::With(html! {
main id=[self.id()] class=[self.classes().get()] { main id=[self.id()] class=[self.classes().get()] style=[style] {
(output) (output)
} }
}), }),
ContainerType::Header => PrepareMarkup::With(html! { ContainerType::Header => PrepareMarkup::With(html! {
header id=[self.id()] class=[self.classes().get()] { header id=[self.id()] class=[self.classes().get()] style=[style] {
(output) (output)
} }
}), }),
ContainerType::Footer => PrepareMarkup::With(html! { ContainerType::Footer => PrepareMarkup::With(html! {
footer id=[self.id()] class=[self.classes().get()] { footer id=[self.id()] class=[self.classes().get()] style=[style] {
(output) (output)
} }
}), }),
ContainerType::Section => PrepareMarkup::With(html! { ContainerType::Section => PrepareMarkup::With(html! {
section id=[self.id()] class=[self.classes().get()] { section id=[self.id()] class=[self.classes().get()] style=[style] {
(output) (output)
} }
}), }),
ContainerType::Article => PrepareMarkup::With(html! { ContainerType::Article => PrepareMarkup::With(html! {
article id=[self.id()] class=[self.classes().get()] { article id=[self.id()] class=[self.classes().get()] style=[style] {
(output) (output)
} }
}), }),

View file

@ -0,0 +1,43 @@
//! Opciones de configuración.
//!
//! Ejemplo:
//!
//! ```toml
//! [bootsier]
//! max_width = "90rem"
//! ```
//!
//! Uso:
//!
//! ```rust#ignore
//! use pagetop_bootsier::config;
//!
//! assert_eq!(config::SETTINGS.bootsier.max_width, unit::Value::Rem(90));
//! ```
//!
//! Consulta [`pagetop::config`] para aprender cómo `PageTop` lee los archivos de opciones y aplica
//! los valores de configuración.
use pagetop::prelude::*;
use serde::Deserialize;
include_config!(SETTINGS: Settings => [
// [bootsier]
"bootsier.max_width" => "1440px",
]);
#[derive(Debug, Deserialize)]
/// Opciones de configuración para la sección [`[bootsier]`](Bootsier) (ver [`SETTINGS`]).
pub struct Settings {
pub bootsier: Bootsier,
}
#[derive(Debug, Deserialize)]
/// Sección `[bootsier]` de la configuración.
///
/// Ver [`Settings`].
pub struct Bootsier {
/// Ancho máximo predeterminado para la página, por ejemplo "100%" o "90rem".
/// Valor por defecto: *"1440px"*
pub max_width: unit::Value,
}

View file

@ -11,6 +11,8 @@ const BOOTSTRAP_VERSION: &str = "5.3.3"; // Versión de la librería Bootstrap.
// API ********************************************************************************************* // API *********************************************************************************************
pub mod config;
pub mod bs; pub mod bs;
pub struct Bootsier; pub struct Bootsier;
@ -22,7 +24,7 @@ impl PackageTrait for Bootsier {
fn actions(&self) -> Vec<ActionBox> { fn actions(&self) -> Vec<ActionBox> {
actions![ actions![
// action::theme::BeforePrepare::<Icon>::new(&Self, before_prepare_icon), //action::theme::BeforeRender::<Region>::new(&Self, before_render_region),
//action::theme::BeforePrepare::<Button>::new(&Self, before_prepare_button), //action::theme::BeforePrepare::<Button>::new(&Self, before_prepare_button),
//action::theme::BeforePrepare::<Heading>::new(&Self, before_prepare_heading), //action::theme::BeforePrepare::<Heading>::new(&Self, before_prepare_heading),
//action::theme::BeforePrepare::<Paragraph>::new(&Self, before_prepare_paragraph), //action::theme::BeforePrepare::<Paragraph>::new(&Self, before_prepare_paragraph),
@ -40,18 +42,35 @@ impl ThemeTrait for Bootsier {
#[rustfmt::skip] #[rustfmt::skip]
fn regions(&self) -> Vec<(&'static str, L10n)> { fn regions(&self) -> Vec<(&'static str, L10n)> {
vec![ vec![
("header", L10n::t("header", &LOCALES_BOOTSIER)), ("region-header", L10n::t("header", &LOCALES_BOOTSIER)),
("nav_branding", L10n::t("nav_branding", &LOCALES_BOOTSIER)), ("region-nav_branding", L10n::t("nav_branding", &LOCALES_BOOTSIER)),
("nav_main", L10n::t("nav_main", &LOCALES_BOOTSIER)), ("region-nav_main", L10n::t("nav_main", &LOCALES_BOOTSIER)),
("nav_additional", L10n::t("nav_additional", &LOCALES_BOOTSIER)), ("region-nav_additional", L10n::t("nav_additional", &LOCALES_BOOTSIER)),
("breadcrumb", L10n::t("breadcrumb", &LOCALES_BOOTSIER)), ("region-breadcrumb", L10n::t("breadcrumb", &LOCALES_BOOTSIER)),
("content", L10n::t("content", &LOCALES_BOOTSIER)), ("region-content", L10n::t("content", &LOCALES_BOOTSIER)),
("sidebar_first", L10n::t("sidebar_first", &LOCALES_BOOTSIER)), ("region-sidebar_first", L10n::t("sidebar_first", &LOCALES_BOOTSIER)),
("sidebar_second", L10n::t("sidebar_second", &LOCALES_BOOTSIER)), ("region-sidebar_second", L10n::t("sidebar_second", &LOCALES_BOOTSIER)),
("footer", L10n::t("footer", &LOCALES_BOOTSIER)), ("region-footer", L10n::t("footer", &LOCALES_BOOTSIER)),
] ]
} }
fn render_page_body(&self, page: &mut Page) -> Markup {
html! {
body id=[page.body_id().get()] class=[page.body_classes().get()] {
//@if let Some(skip) = L10n::l("skip_to_content").using(page.context().langid()) {
// div class="skip__to_content" {
// a href=(concat_string!("#", skip_to_id)) { (skip) }
// }
//}
(bs::Container::new()
.with_id("container-wrapper")
.with_breakpoint(bs::BreakPoint::FluidMax(config::SETTINGS.bootsier.max_width))
.add_child(Region::of("region-content"))
.render(page.context()))
}
}
}
fn after_render_page_body(&self, page: &mut Page) { fn after_render_page_body(&self, page: &mut Page) {
page.alter_assets(AssetsOp::AddStyleSheet( page.alter_assets(AssetsOp::AddStyleSheet(
StyleSheet::from("/bootsier/bs/bootstrap.min.css") StyleSheet::from("/bootsier/bs/bootstrap.min.css")
@ -186,6 +205,7 @@ impl ThemeTrait for Bootsier {
}) })
*/ */
} }
/* /*
#[rustfmt::skip] #[rustfmt::skip]
fn with_font(font_size: &FontSize) -> String { fn with_font(font_size: &FontSize) -> String {

View file

@ -3,5 +3,8 @@ name = "PageTop"
description = "An opinionated web framework to build modular Server-Side Rendering web solutions." description = "An opinionated web framework to build modular Server-Side Rendering web solutions."
theme = "Bootsier" theme = "Bootsier"
[bootsier]
max_width = "1600px"
[log] [log]
rolling = "Daily" rolling = "Daily"