From 063ae2aae87cbb5815c66a1ee80db205c9880b8e Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sun, 13 Aug 2023 10:53:12 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A7=20[minimal]=20New=20flex=20layout?= =?UTF-8?q?=20components?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop-minimal/src/component.rs | 3 +- pagetop-minimal/src/component/flex.rs | 4 + .../src/component/flex/container.rs | 114 ++++++++++++ pagetop-minimal/src/component/flex/item.rs | 176 ++++++++++++++++++ pagetop-minimal/static/css/minimal.css | 34 +++- 5 files changed, 328 insertions(+), 3 deletions(-) create mode 100644 pagetop-minimal/src/component/flex.rs create mode 100644 pagetop-minimal/src/component/flex/container.rs create mode 100644 pagetop-minimal/src/component/flex/item.rs diff --git a/pagetop-minimal/src/component.rs b/pagetop-minimal/src/component.rs index 3cbae79f..1f86bde5 100644 --- a/pagetop-minimal/src/component.rs +++ b/pagetop-minimal/src/component.rs @@ -1,6 +1,7 @@ mod container; pub use container::{Container, ContainerType, COMPONENT_CONTAINER}; +pub mod flex; pub mod grid; mod icon; @@ -12,7 +13,7 @@ pub use paragraph::{Paragraph, ParagraphDisplay, COMPONENT_PARAGRAPH}; mod anchor; pub use anchor::{Anchor, AnchorTarget, AnchorType, COMPONENT_ANCHOR}; mod image; -pub use image::{Image, COMPONENT_IMAGE}; +pub use image::{Image, ImageSize, COMPONENT_IMAGE}; mod block; pub use block::{Block, COMPONENT_BLOCK}; mod site_branding; diff --git a/pagetop-minimal/src/component/flex.rs b/pagetop-minimal/src/component/flex.rs new file mode 100644 index 00000000..1025c13f --- /dev/null +++ b/pagetop-minimal/src/component/flex.rs @@ -0,0 +1,4 @@ +mod container; +pub use container::{Container, COMPONENT_FLEX_CONTAINER}; +mod item; +pub use item::{Item, COMPONENT_FLEX_ITEM}; diff --git a/pagetop-minimal/src/component/flex/container.rs b/pagetop-minimal/src/component/flex/container.rs new file mode 100644 index 00000000..8858c286 --- /dev/null +++ b/pagetop-minimal/src/component/flex/container.rs @@ -0,0 +1,114 @@ +use pagetop::prelude::*; + +use crate::component::flex; + +new_handle!(COMPONENT_FLEX_CONTAINER); + +actions_for_component!(Container); + +#[rustfmt::skip] +#[derive(Default)] +pub struct Container { + weight : Weight, + renderable: Renderable, + id : IdentifierValue, + classes : Classes, + items : PackComponents, + template : String, +} + +impl ComponentTrait for Container { + fn new() -> Self { + Container::default().with_classes(ClassesOp::SetDefault, "flex") + } + + fn handle(&self) -> Handle { + COMPONENT_FLEX_CONTAINER + } + + fn id(&self) -> Option { + self.id.get() + } + + fn weight(&self) -> Weight { + self.weight + } + + fn is_renderable(&self, cx: &Context) -> bool { + (self.renderable.check)(cx) + } + + fn before_prepare_component(&mut self, cx: &mut Context) { + run_actions_before_prepare_container(self, cx); + } + + fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { + PrepareMarkup::With(html! { + div id=[self.id()] class=[self.classes().get()] { + (self.items().prepare(cx)) + } + }) + } + + fn after_prepare_component(&mut self, cx: &mut Context) { + run_actions_after_prepare_container(self, cx); + } +} + +impl Container { + // Container BUILDER. + + #[fn_builder] + pub fn alter_weight(&mut self, value: Weight) -> &mut Self { + self.weight = value; + self + } + + #[fn_builder] + pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self { + self.renderable.check = check; + self + } + + #[fn_builder] + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.alter_value(id); + self + } + + #[fn_builder] + pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self { + self.classes.alter_value(op, classes); + self + } + + pub fn with_item(mut self, item: flex::Item) -> Self { + self.items.alter(PackOp::Add, ComponentArc::new(item)); + self + } + + pub fn alter_items(&mut self, op: PackOp, item: flex::Item) -> &mut Self { + self.items.alter(op, ComponentArc::new(item)); + self + } + + #[fn_builder] + pub fn alter_template(&mut self, template: &str) -> &mut Self { + self.template = template.to_owned(); + self + } + + // Container GETTERS. + + pub fn classes(&self) -> &Classes { + &self.classes + } + + pub fn items(&self) -> &PackComponents { + &self.items + } + + pub fn template(&self) -> &str { + self.template.as_str() + } +} diff --git a/pagetop-minimal/src/component/flex/item.rs b/pagetop-minimal/src/component/flex/item.rs new file mode 100644 index 00000000..7dae7b6f --- /dev/null +++ b/pagetop-minimal/src/component/flex/item.rs @@ -0,0 +1,176 @@ +use pagetop::prelude::*; + +new_handle!(COMPONENT_FLEX_ITEM); + +actions_for_component!(Item); + +const SIZE_DEFAULT: &str = "col"; +const SIZE_1_OF_12: &str = "col-md-1"; +const SIZE_2_OF_12: &str = "col-md-2"; +const SIZE_3_OF_12: &str = "col-md-3"; +const SIZE_4_OF_12: &str = "col-md-4"; +const SIZE_5_OF_12: &str = "col-md-5"; +const SIZE_6_OF_12: &str = "col-md-6"; +const SIZE_7_OF_12: &str = "col-md-7"; +const SIZE_8_OF_12: &str = "col-md-8"; +const SIZE_9_OF_12: &str = "col-md-9"; +const SIZE_10_OF_12: &str = "col-md-10"; +const SIZE_11_OF_12: &str = "col-md-11"; +const SIZE_12_OF_12: &str = "col-md-12"; + +#[derive(Default)] +pub enum ItemSize { + #[default] + Default, + Is1of12, + Is2of12, + Is3of12, + Is4of12, + Is5of12, + Is6of12, + Is7of12, + Is8of12, + Is9of12, + Is10of12, + Is11of12, + IsFull, +} + +#[rustfmt::skip] +#[derive(Default)] +pub struct Item { + weight : Weight, + renderable: Renderable, + id : IdentifierValue, + classes : Classes, + size : ItemSize, + stuff : PackComponents, + template : String, +} + +impl ComponentTrait for Item { + fn new() -> Self { + Item::default().with_classes(ClassesOp::SetDefault, SIZE_DEFAULT) + } + + fn handle(&self) -> Handle { + COMPONENT_FLEX_ITEM + } + + fn id(&self) -> Option { + self.id.get() + } + + fn weight(&self) -> Weight { + self.weight + } + + fn is_renderable(&self, cx: &Context) -> bool { + (self.renderable.check)(cx) + } + + fn before_prepare_component(&mut self, cx: &mut Context) { + run_actions_before_prepare_item(self, cx); + } + + fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { + PrepareMarkup::With(html! { + div id=[self.id()] class=[self.classes().get()] { + (self.components().prepare(cx)) + } + }) + } + + fn after_prepare_component(&mut self, cx: &mut Context) { + run_actions_after_prepare_item(self, cx); + } +} + +impl Item { + // Item BUILDER. + + #[fn_builder] + pub fn alter_weight(&mut self, value: Weight) -> &mut Self { + self.weight = value; + self + } + + #[fn_builder] + pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self { + self.renderable.check = check; + self + } + + #[fn_builder] + pub fn alter_id(&mut self, id: &str) -> &mut Self { + self.id.alter_value(id); + self + } + + #[fn_builder] + pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self { + self.classes.alter_value(op, classes); + self + } + + #[rustfmt::skip] + #[fn_builder] + pub fn alter_size(&mut self, size: ItemSize) -> &mut Self { + match size { + ItemSize::Default => self.alter_classes(ClassesOp::SetDefault, SIZE_DEFAULT), + ItemSize::Is1of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_1_OF_12), + ItemSize::Is2of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_2_OF_12), + ItemSize::Is3of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_3_OF_12), + ItemSize::Is4of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_4_OF_12), + ItemSize::Is5of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_5_OF_12), + ItemSize::Is6of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_6_OF_12), + ItemSize::Is7of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_7_OF_12), + ItemSize::Is8of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_8_OF_12), + ItemSize::Is9of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_9_OF_12), + ItemSize::Is10of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_10_OF_12), + ItemSize::Is11of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_11_OF_12), + ItemSize::IsFull => self.alter_classes(ClassesOp::SetDefault, SIZE_12_OF_12), + }; + self.size = size; + self + } + + pub fn with_component(mut self, component: impl ComponentTrait) -> Self { + self.stuff.alter(PackOp::Add, ComponentArc::new(component)); + self + } + + pub fn with_component_arc(mut self, arc: ComponentArc) -> Self { + self.stuff.alter(PackOp::Add, arc); + self + } + + pub fn alter_components(&mut self, op: PackOp, component: impl ComponentTrait) -> &mut Self { + self.stuff.alter(op, ComponentArc::new(component)); + self + } + + #[fn_builder] + pub fn alter_template(&mut self, template: &str) -> &mut Self { + self.template = template.to_owned(); + self + } + + // Item GETTERS. + + pub fn classes(&self) -> &Classes { + &self.classes + } + + pub fn size(&self) -> &ItemSize { + &self.size + } + + pub fn components(&self) -> &PackComponents { + &self.stuff + } + + pub fn template(&self) -> &str { + self.template.as_str() + } +} diff --git a/pagetop-minimal/static/css/minimal.css b/pagetop-minimal/static/css/minimal.css index 9c6df304..eda8142e 100644 --- a/pagetop-minimal/static/css/minimal.css +++ b/pagetop-minimal/static/css/minimal.css @@ -1,4 +1,34 @@ -/* SiteBranding component */ +/* Flex components */ +.flex { + display: flex; + flex-direction: column; +} +@media (min-width: 768px) { + .flex { + flex-direction: row; + } +} +/* Grid components */ +.row .row { + margin: 0 -1.5em; +} +.col { + padding: 0 1.5em; +} +.row:after { + content: ""; + clear: both; + display: table; +} +@media only screen { + .col { + float: left; + width: 100%; + box-sizing: border-box; + } +} + +/* SiteBranding component */ /* #site-branding { float: left; } @@ -32,7 +62,7 @@ display: block; } } - +*/ /* PoweredBy component */ #powered-by { text-align: center;