[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]
pagetop.workspace = true
serde.workspace = true
static-files.workspace = true
[build-dependencies]

View file

@ -11,22 +11,27 @@ pub mod grid;
#[rustfmt::skip]
#[derive(AutoDefault)]
pub enum BreakPoint {
#[default]
None, // < 576px (Dispositivos 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)
MD, // >= 768px (Dispositivos medianos: tabletas, 768px o más)
LG, // >= 992px (Dispositivos grandes: puestos de escritorio, 992px o más)
XL, // >= 1200px (Dispositivos muy grandes: puestos de escritorio grandes, 1200px o más)
XXL, // >= 1400px (Dispositivos extragrandes: puestos de escritorio más grandes, 1400px o más)
Fluid, // Siempre aplica el 100% del dispositivo
#[default] // DIMENSIONES - DISPOSITIVOS ---------------------------------------------------
None, // < 576px Muy pequeños: teléfonos en modo vertical, menos de 576px
SM, // >= 576px Pequeños: teléfonos en modo horizontal, 576px o más
MD, // >= 768px Medianos: tabletas, 768px o más
LG, // >= 992px Grandes: puestos de escritorio, 992px o más
XL, // >= 1200px Muy grandes: puestos de escritorio grandes, 1200px o más
XXL, // >= 1400px Extragrandes: puestos de escritorio más grandes, 1400px o más
// ------------------------------------------------------------------------------
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 {
/// 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 `false` si es None o Fluid.
/// Devuelve `false` si es None, Fluid o FluidMax.
pub fn is_breakpoint(&self) -> bool {
!matches!(self, BreakPoint::None | BreakPoint::Fluid)
!matches!(
self,
BreakPoint::None | BreakPoint::Fluid | BreakPoint::FluidMax(_)
)
}
}
@ -35,13 +40,14 @@ impl BreakPoint {
impl fmt::Display for BreakPoint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BreakPoint::None => write!(f, ""),
BreakPoint::SM => write!(f, "sm"),
BreakPoint::MD => write!(f, "md"),
BreakPoint::LG => write!(f, "lg"),
BreakPoint::XL => write!(f, "xl"),
BreakPoint::XXL => write!(f, "xxl"),
BreakPoint::Fluid => write!(f, "fluid"),
BreakPoint::None => write!(f, ""),
BreakPoint::SM => write!(f, "sm"),
BreakPoint::MD => write!(f, "md"),
BreakPoint::LG => write!(f, "lg"),
BreakPoint::XL => write!(f, "xl"),
BreakPoint::XXL => write!(f, "xxl"),
BreakPoint::Fluid => write!(f, "fluid"),
BreakPoint::FluidMax(_) => write!(f, "fluid"),
}
}
}

View file

@ -45,34 +45,39 @@ impl ComponentTrait for Container {
if output.is_empty() {
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() {
ContainerType::Default => PrepareMarkup::With(html! {
div id=[self.id()] class=[self.classes().get()] {
div id=[self.id()] class=[self.classes().get()] style=[style] {
(output)
}
}),
ContainerType::Main => PrepareMarkup::With(html! {
main id=[self.id()] class=[self.classes().get()] {
main id=[self.id()] class=[self.classes().get()] style=[style] {
(output)
}
}),
ContainerType::Header => PrepareMarkup::With(html! {
header id=[self.id()] class=[self.classes().get()] {
header id=[self.id()] class=[self.classes().get()] style=[style] {
(output)
}
}),
ContainerType::Footer => PrepareMarkup::With(html! {
footer id=[self.id()] class=[self.classes().get()] {
footer id=[self.id()] class=[self.classes().get()] style=[style] {
(output)
}
}),
ContainerType::Section => PrepareMarkup::With(html! {
section id=[self.id()] class=[self.classes().get()] {
section id=[self.id()] class=[self.classes().get()] style=[style] {
(output)
}
}),
ContainerType::Article => PrepareMarkup::With(html! {
article id=[self.id()] class=[self.classes().get()] {
article id=[self.id()] class=[self.classes().get()] style=[style] {
(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 *********************************************************************************************
pub mod config;
pub mod bs;
pub struct Bootsier;
@ -22,12 +24,12 @@ impl PackageTrait for Bootsier {
fn actions(&self) -> Vec<ActionBox> {
actions![
// action::theme::BeforePrepare::<Icon>::new(&Self, before_prepare_icon),
// action::theme::BeforePrepare::<Button>::new(&Self, before_prepare_button),
// action::theme::BeforePrepare::<Heading>::new(&Self, before_prepare_heading),
// action::theme::BeforePrepare::<Paragraph>::new(&Self, before_prepare_paragraph),
// action::theme::RenderComponent::<Error404>::new(&Self, render_error404),
]
//action::theme::BeforeRender::<Region>::new(&Self, before_render_region),
//action::theme::BeforePrepare::<Button>::new(&Self, before_prepare_button),
//action::theme::BeforePrepare::<Heading>::new(&Self, before_prepare_heading),
//action::theme::BeforePrepare::<Paragraph>::new(&Self, before_prepare_paragraph),
//action::theme::RenderComponent::<Error404>::new(&Self, render_error404),
]
}
fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
@ -40,18 +42,35 @@ impl ThemeTrait for Bootsier {
#[rustfmt::skip]
fn regions(&self) -> Vec<(&'static str, L10n)> {
vec![
("header", L10n::t("header", &LOCALES_BOOTSIER)),
("nav_branding", L10n::t("nav_branding", &LOCALES_BOOTSIER)),
("nav_main", L10n::t("nav_main", &LOCALES_BOOTSIER)),
("nav_additional", L10n::t("nav_additional", &LOCALES_BOOTSIER)),
("breadcrumb", L10n::t("breadcrumb", &LOCALES_BOOTSIER)),
("content", L10n::t("content", &LOCALES_BOOTSIER)),
("sidebar_first", L10n::t("sidebar_first", &LOCALES_BOOTSIER)),
("sidebar_second", L10n::t("sidebar_second", &LOCALES_BOOTSIER)),
("footer", L10n::t("footer", &LOCALES_BOOTSIER)),
("region-header", L10n::t("header", &LOCALES_BOOTSIER)),
("region-nav_branding", L10n::t("nav_branding", &LOCALES_BOOTSIER)),
("region-nav_main", L10n::t("nav_main", &LOCALES_BOOTSIER)),
("region-nav_additional", L10n::t("nav_additional", &LOCALES_BOOTSIER)),
("region-breadcrumb", L10n::t("breadcrumb", &LOCALES_BOOTSIER)),
("region-content", L10n::t("content", &LOCALES_BOOTSIER)),
("region-sidebar_first", L10n::t("sidebar_first", &LOCALES_BOOTSIER)),
("region-sidebar_second", L10n::t("sidebar_second", &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) {
page.alter_assets(AssetsOp::AddStyleSheet(
StyleSheet::from("/bootsier/bs/bootstrap.min.css")
@ -186,6 +205,7 @@ impl ThemeTrait for Bootsier {
})
*/
}
/*
#[rustfmt::skip]
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."
theme = "Bootsier"
[bootsier]
max_width = "1600px"
[log]
rolling = "Daily"