🚧 General components review

This commit is contained in:
Manuel Cillero 2023-11-13 17:23:58 +01:00
parent 905b4b1cba
commit 3d2e750577
25 changed files with 1557 additions and 304 deletions

View file

@ -19,8 +19,8 @@ impl ModuleTrait for Admin {
fn actions(&self) -> Vec<Action> {
actions![
action::page::BeforePrepareBody::with(before_prepare_body),
action::component::BeforePrepareComponent::<Menu>::with(before_prepare_menu)
action::page::BeforePrepareBody::new(before_prepare_body),
action::component::BeforePrepareComponent::<Menu>::new(before_prepare_menu)
.filter_by_referer_id("admin-menu-test"),
]
}

View file

@ -124,16 +124,16 @@ impl ThemeTrait for Bootsier {
}
_ => {}
};
match a.anchor_type() {
match a.button_type() {
ButtonType::Link => {
a.alter_classes(
ClassesOp::Replace(a.anchor_type().to_string()),
ClassesOp::Replace(a.button_type().to_string()),
"btn btn-link",
);
}
ButtonType::Primary => {
a.alter_classes(
ClassesOp::Replace(a.anchor_type().to_string()),
ClassesOp::Replace(a.button_type().to_string()),
"btn btn-primary",
);
}

View file

@ -3,5 +3,11 @@
/* Heading component */
.pt-heading__subtitle {
margin-top: calc(-1 * var(--pt-gap-0-5));
margin-top: calc(-1 * var(--pt-gap-0-35));
}
/* Button component */
.btn-link {
text-decoration: none;
}

View file

@ -24,7 +24,10 @@ impl ThemeTrait for Bulmix {
.with_version("0.9.4")
.with_weight(-99),
))
.alter_context(ContextOp::AddBaseAssets);
.alter_context(ContextOp::AddBaseAssets)
.alter_context(ContextOp::AddStyleSheet(
StyleSheet::at("/bulmix/css/styles.css").with_version("0.0.1"),
));
}
fn before_prepare_component(&self, component: &mut dyn ComponentTrait, _cx: &mut Context) {
@ -50,8 +53,8 @@ impl ThemeTrait for Bulmix {
_ => {}
};
}
COMPONENT_BASE_ANCHOR => {
let a = component_as_mut::<Anchor>(component);
COMPONENT_BASE_BUTTON => {
let a = component_as_mut::<Button>(component);
match a.font_size() {
FontSize::ExtraLarge => {
a.alter_classes(ClassesOp::Replace(a.font_size().to_string()), "is-size-1");
@ -70,12 +73,20 @@ impl ThemeTrait for Bulmix {
}
_ => {}
};
if let AnchorType::Button = a.anchor_type() {
a.alter_classes(
ClassesOp::Replace(a.anchor_type().to_string()),
"button is-primary",
);
};
match a.button_type() {
ButtonType::Link => {
a.alter_classes(
ClassesOp::Replace(a.button_type().to_string()),
"button is-text",
);
}
ButtonType::Primary => {
a.alter_classes(
ClassesOp::Replace(a.button_type().to_string()),
"button is-primary",
);
}
}
}
COMPONENT_BASE_HEADING => {
let h = component_as_mut::<Heading>(component);
@ -112,19 +123,18 @@ impl ThemeTrait for Bulmix {
}
}
fn render_component(&self, component: &dyn ComponentTrait, cx: &mut Context) -> Option<Markup> {
fn render_component(
&self,
component: &dyn ComponentTrait,
_cx: &mut Context,
) -> Option<Markup> {
match component.handle() {
COMPONENT_BASE_ICON => {
let icon = component_as_ref::<Icon>(component);
if icon.icon_name().is_empty() {
return None;
};
cx.set_param::<bool>(PARAM_BASE_INCLUDE_ICONS, true);
Some(html! {
span class="icon" {
i class=[icon.classes().get()] {}
}
})
match icon.icon_name().get() {
None => None,
_ => Some(html! { span class="icon" { i class=[icon.classes().get()] {} } }),
}
}
_ => None,
}

View file

@ -0,0 +1,11 @@
html {
scroll-behavior: smooth;
}
/* OVERRIDE COMPONENT STYLES */
/* Button component */
.is-link {
text-decoration: none;
}

View file

@ -70,20 +70,20 @@ fn hello_world() -> Wrapper {
),
))
.add_component(
Anchor::button(
Button::primary(
"https://github.com/manuelcillero/pagetop",
L10n::t("hello_code", &LOCALES_HOMEDEMO),
)
.with_target(AnchorTarget::Blank)
.with_target(ButtonTarget::Blank)
.with_left_icon(Icon::with("git"))
.with_classes(ClassesOp::Add, "code-link")
.with_font_size(FontSize::Large),
.with_font_size(FontSize::Medium),
)
.add_component(
Anchor::link("#welcome", L10n::t("hello_welcome", &LOCALES_HOMEDEMO))
Button::link("#welcome", L10n::t("hello_welcome", &LOCALES_HOMEDEMO))
.with_left_icon(Icon::with("arrow-down-circle-fill"))
.with_classes(ClassesOp::Add, "welcome-link")
.with_font_size(FontSize::Large),
.with_font_size(FontSize::Medium),
),
)
.add_item(

View file

@ -18,7 +18,7 @@ body.default-homepage [class$="-col-text"] {
body.default-homepage [class$="-col-image"] {
padding: 1rem 5%;
}
/*
#hello-world a {
margin: .25rem;
}
@ -36,7 +36,7 @@ body.default-homepage [class$="-col-image"] {
#hello-world .hello-col-image {
padding-top: 3em;
}
*/
#welcome > div.container {
padding: 2rem 1rem;
border-radius: 28px;

View file

@ -23,7 +23,7 @@ impl ModuleTrait for Node {
}
fn actions(&self) -> Vec<Action> {
actions![action::page::BeforePrepareBody::with(before_prepare_body).with_weight(-1)]
actions![action::page::BeforePrepareBody::new(before_prepare_body).with_weight(-1)]
}
fn migrations(&self) -> Vec<MigrationItem> {

View file

@ -46,6 +46,11 @@ pub(crate) fn add_base_assets(cx: &mut Context) {
StyleSheet::at("/base/css/looks.css")
.with_version("0.0.1")
.with_weight(weight),
))
.alter(ContextOp::AddStyleSheet(
StyleSheet::at("/base/css/buttons.css")
.with_version("0.0.1")
.with_weight(weight),
));
}
@ -135,8 +140,8 @@ mod heading;
pub use heading::{Heading, HeadingDisplay, HeadingType, COMPONENT_BASE_HEADING};
mod paragraph;
pub use paragraph::{Paragraph, COMPONENT_BASE_PARAGRAPH};
mod anchor;
pub use anchor::{Anchor, AnchorTarget, AnchorType, COMPONENT_BASE_ANCHOR};
mod button;
pub use button::{Button, ButtonTarget, ButtonType, COMPONENT_BASE_BUTTON};
mod image;
pub use image::{Image, ImageSize, COMPONENT_BASE_IMAGE};
mod block;

View file

@ -3,20 +3,19 @@ use crate::prelude::*;
#[rustfmt::skip]
#[derive(Default)]
pub struct Block {
id : OptionId,
weight : Weight,
renderable: Renderable,
id : OptionId,
classes : OptionClasses,
title : OptionTranslated,
stuff : ArcComponents,
template : String,
stuff : AnyComponents,
}
impl_handle!(COMPONENT_BASE_BLOCK for Block);
impl ComponentTrait for Block {
fn new() -> Self {
Block::default().with_classes(ClassesOp::Add, "block")
Block::default()
}
fn id(&self) -> Option<String> {
@ -31,7 +30,14 @@ impl ComponentTrait for Block {
(self.renderable.check)(cx)
}
fn setup_before_prepare(&mut self, _cx: &mut Context) {
self.classes.alter_value(ClassesOp::AddFirst, "block");
}
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
if self.components().is_empty() {
return PrepareMarkup::None;
}
let id = cx.required_id::<Block>(self.id());
PrepareMarkup::With(html! {
div id=(id) class=[self.classes().get()] {
@ -79,20 +85,15 @@ impl Block {
self
}
#[rustfmt::skip]
pub fn add_component(mut self, component: impl ComponentTrait) -> Self {
self.stuff.alter(ArcOp::Add(ArcComponent::with(component)));
self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(component)));
self
}
#[fn_builder]
pub fn alter_components(&mut self, op: ArcOp) -> &mut Self {
self.stuff.alter(op);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
pub fn alter_components(&mut self, op: ArcAnyOp) -> &mut Self {
self.stuff.alter_value(op);
self
}
@ -106,11 +107,7 @@ impl Block {
&self.title
}
pub fn components(&self) -> &ArcComponents {
pub fn components(&self) -> &AnyComponents {
&self.stuff
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,14 +1,13 @@
use crate::prelude::*;
type SiteLogo = TypedComponent<Image>;
#[rustfmt::skip]
pub struct Branding {
id : OptionId,
weight : Weight,
renderable: Renderable,
app_name : String,
slogan : OptionTranslated,
logo : SiteLogo,
logo : ArcTypedComponent<Image>,
frontpage : FnContextualPath,
}
@ -16,11 +15,12 @@ pub struct Branding {
impl Default for Branding {
fn default() -> Self {
Branding {
id : OptionId::default(),
weight : Weight::default(),
renderable: Renderable::default(),
app_name : config::SETTINGS.app.name.to_owned(),
slogan : OptionTranslated::default(),
logo : SiteLogo::default(),
logo : ArcTypedComponent::<Image>::default(),
frontpage : |_| "/",
}
}
@ -34,7 +34,7 @@ impl ComponentTrait for Branding {
}
fn id(&self) -> Option<String> {
Some("pt-branding".to_owned())
self.id.get()
}
fn weight(&self) -> Weight {
@ -48,7 +48,7 @@ impl ComponentTrait for Branding {
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
let title = L10n::l("site_home").using(cx.langid());
PrepareMarkup::With(html! {
div id=[self.id()] {
div id=[self.id()] class="pt-branding" {
div class="pt-branding__wrapper" {
div class="pt-branding__logo" {
(self.logo().render(cx))
@ -74,6 +74,12 @@ impl ComponentTrait for Branding {
impl Branding {
// Branding BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value;
@ -120,7 +126,7 @@ impl Branding {
&self.slogan
}
pub fn logo(&self) -> &SiteLogo {
pub fn logo(&self) -> &ArcTypedComponent<Image> {
&self.logo
}

View file

@ -1,27 +1,24 @@
use crate::prelude::*;
new_handle!(COMPONENT_BASE_ANCHOR);
#[derive(Default)]
pub enum AnchorType {
pub enum ButtonType {
#[default]
Link,
Button,
Location,
Primary,
}
#[rustfmt::skip]
impl ToString for AnchorType {
impl ToString for ButtonType {
fn to_string(&self) -> String {
match self {
AnchorType::Button => "btn btn-primary".to_string(),
_ => "".to_string(),
}
String::from(match self {
ButtonType::Link => "pt-button__link",
ButtonType::Primary => "pt-button__primary",
})
}
}
#[derive(Default)]
pub enum AnchorTarget {
pub enum ButtonTarget {
#[default]
Default,
Blank,
@ -30,31 +27,29 @@ pub enum AnchorTarget {
Context(String),
}
type AnchorIcon = TypedComponent<Icon>;
type ButtonIcon = ArcTypedComponent<Icon>;
#[rustfmt::skip]
#[derive(Default)]
pub struct Anchor {
pub struct Button {
id : OptionId,
weight : Weight,
renderable : Renderable,
id : OptionId,
classes : OptionClasses,
button_type: ButtonType,
font_size : FontSize,
anchor_type: AnchorType,
href : OptionString,
html : OptionTranslated,
left_icon : AnchorIcon,
right_icon : AnchorIcon,
target : AnchorTarget,
left_icon : ButtonIcon,
right_icon : ButtonIcon,
target : ButtonTarget,
}
impl ComponentTrait for Anchor {
fn new() -> Self {
Anchor::default()
}
impl_handle!(COMPONENT_BASE_BUTTON for Button);
fn handle(&self) -> Handle {
COMPONENT_BASE_ANCHOR
impl ComponentTrait for Button {
fn new() -> Self {
Button::default()
}
fn id(&self) -> Option<String> {
@ -69,13 +64,20 @@ impl ComponentTrait for Anchor {
(self.renderable.check)(cx)
}
fn setup_before_prepare(&mut self, _cx: &mut Context) {
self.classes.alter_value(
ClassesOp::AddFirst,
[self.button_type.to_string(), self.font_size.to_string()].join(" "),
);
}
#[rustfmt::skip]
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
let target = match &self.target() {
AnchorTarget::Blank => Some("_blank"),
AnchorTarget::Parent => Some("_parent"),
AnchorTarget::Top => Some("_top"),
AnchorTarget::Context(name) => Some(name.as_str()),
ButtonTarget::Blank => Some("_blank"),
ButtonTarget::Parent => Some("_parent"),
ButtonTarget::Top => Some("_top"),
ButtonTarget::Context(name) => Some(name.as_str()),
_ => None,
};
PrepareMarkup::With(html! {
@ -85,31 +87,36 @@ impl ComponentTrait for Anchor {
href=[self.href().get()]
target=[target]
{
(self.left_icon().prepare(cx))
" " span { (self.html().escaped(cx.langid())) } " "
(self.right_icon().prepare(cx))
(self.left_icon().render(cx))
" " span { (self.html().escaped(cx.langid()).unwrap_or_default()) } " "
(self.right_icon().render(cx))
}
})
}
}
impl Anchor {
impl Button {
pub fn link(href: impl Into<String>, html: L10n) -> Self {
Anchor::new().with_href(href).with_html(html)
}
pub fn button(href: impl Into<String>, html: L10n) -> Self {
Anchor::new()
.with_type(AnchorType::Button)
Button::default()
.with_type(ButtonType::Link)
.with_href(href)
.with_html(html)
}
pub fn location(id: impl Into<String>) -> Self {
Anchor::new().with_type(AnchorType::Location).with_id(id)
pub fn primary(href: impl Into<String>, html: L10n) -> Self {
Button::default()
.with_type(ButtonType::Primary)
.with_href(href)
.with_html(html)
}
// Anchor BUILDER.
// Button BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
@ -123,12 +130,6 @@ impl Anchor {
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: impl Into<String>) -> &mut Self {
self.classes.alter_value(op, classes);
@ -136,22 +137,14 @@ impl Anchor {
}
#[fn_builder]
pub fn alter_font_size(&mut self, font_size: FontSize) -> &mut Self {
self.classes.alter_value(
ClassesOp::Replace(self.font_size.to_string()),
font_size.to_string(),
);
self.font_size = font_size;
pub fn alter_type(&mut self, button_type: ButtonType) -> &mut Self {
self.button_type = button_type;
self
}
#[fn_builder]
pub fn alter_type(&mut self, anchor_type: AnchorType) -> &mut Self {
self.classes.alter_value(
ClassesOp::Replace(self.anchor_type.to_string()),
anchor_type.to_string(),
);
self.anchor_type = anchor_type;
pub fn alter_font_size(&mut self, font_size: FontSize) -> &mut Self {
self.font_size = font_size;
self
}
@ -180,23 +173,23 @@ impl Anchor {
}
#[fn_builder]
pub fn alter_target(&mut self, target: AnchorTarget) -> &mut Self {
pub fn alter_target(&mut self, target: ButtonTarget) -> &mut Self {
self.target = target;
self
}
// Anchor GETTERS.
// Button GETTERS.
pub fn classes(&self) -> &OptionClasses {
&self.classes
}
pub fn font_size(&self) -> &FontSize {
&self.font_size
pub fn button_type(&self) -> &ButtonType {
&self.button_type
}
pub fn anchor_type(&self) -> &AnchorType {
&self.anchor_type
pub fn font_size(&self) -> &FontSize {
&self.font_size
}
pub fn href(&self) -> &OptionString {
@ -207,15 +200,15 @@ impl Anchor {
&self.html
}
pub fn left_icon(&self) -> &AnchorIcon {
pub fn left_icon(&self) -> &ButtonIcon {
&self.left_icon
}
pub fn right_icon(&self) -> &AnchorIcon {
pub fn right_icon(&self) -> &ButtonIcon {
&self.right_icon
}
pub fn target(&self) -> &AnchorTarget {
pub fn target(&self) -> &ButtonTarget {
&self.target
}
}

View file

@ -3,9 +3,9 @@ use crate::prelude::*;
#[rustfmt::skip]
#[derive(Default)]
pub struct Container {
id : OptionId,
weight : Weight,
renderable : Renderable,
id : OptionId,
classes : OptionClasses,
items : TypedComponents<flex::Item>,
direction : flex::Direction,
@ -19,7 +19,7 @@ impl_handle!(COMPONENT_BASE_FLEX_CONTAINER for Container);
impl ComponentTrait for Container {
fn new() -> Self {
Container::default().with_classes(ClassesOp::Add, flex::Direction::Default.to_string())
Container::default()
}
fn id(&self) -> Option<String> {
@ -34,9 +34,22 @@ impl ComponentTrait for Container {
(self.renderable.check)(cx)
}
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
cx.set_param::<bool>(PARAM_BASE_INCLUDE_FLEX_ASSETS, true);
fn setup_before_prepare(&mut self, cx: &mut Context) {
self.classes.alter_value(
ClassesOp::AddFirst,
[
self.direction.to_string(),
self.wrap_align.to_string(),
self.content_justify.to_string(),
self.items_align.to_string(),
]
.join(" "),
);
cx.set_param::<bool>(PARAM_BASE_INCLUDE_FLEX_ASSETS, true);
}
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
let gap = match self.gap() {
flex::Gap::Default => None,
_ => Some(self.gap().to_string()),
@ -53,6 +66,12 @@ impl ComponentTrait for Container {
impl Container {
// Container BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value;
@ -65,65 +84,44 @@ impl Container {
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: impl Into<String>) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[rustfmt::skip]
pub fn add_item(mut self, item: flex::Item) -> Self {
self.items.alter(TypedOp::Add(TypedComponent::with(item)));
self.items.alter_value(ArcTypedOp::Add(ArcTypedComponent::new(item)));
self
}
#[fn_builder]
pub fn alter_items(&mut self, op: TypedOp<flex::Item>) -> &mut Self {
self.items.alter(op);
pub fn alter_items(&mut self, op: ArcTypedOp<flex::Item>) -> &mut Self {
self.items.alter_value(op);
self
}
#[fn_builder]
pub fn alter_direction(&mut self, direction: flex::Direction) -> &mut Self {
self.classes.alter_value(
ClassesOp::Replace(self.direction.to_string()),
direction.to_string(),
);
self.direction = direction;
self
}
#[fn_builder]
pub fn alter_wrap_align(&mut self, wrap: flex::WrapAlign) -> &mut Self {
self.classes.alter_value(
ClassesOp::Replace(self.wrap_align.to_string()),
wrap.to_string(),
);
self.wrap_align = wrap;
self
}
#[fn_builder]
pub fn alter_content_justify(&mut self, justify: flex::ContentJustify) -> &mut Self {
self.classes.alter_value(
ClassesOp::Replace(self.content_justify.to_string()),
justify.to_string(),
);
self.content_justify = justify;
self
}
#[fn_builder]
pub fn alter_items_align(&mut self, align: flex::ItemAlign) -> &mut Self {
self.classes.alter_value(
ClassesOp::Replace(self.items_align.to_string()),
align.to_string(),
);
self.items_align = align;
self
}

View file

@ -3,9 +3,9 @@ use crate::prelude::*;
#[rustfmt::skip]
#[derive(Default)]
pub struct Item {
id : OptionId,
weight : Weight,
renderable : Renderable,
id : OptionId,
item_classes : OptionClasses,
inner_classes: OptionClasses,
item_grow : flex::ItemGrow,
@ -13,7 +13,7 @@ pub struct Item {
item_size : flex::ItemSize,
item_offset : flex::ItemOffset,
item_align : flex::ItemAlign,
stuff : ArcComponents,
stuff : AnyComponents,
}
impl_handle!(COMPONENT_BASE_FLEX_ITEM for Item);
@ -21,8 +21,6 @@ impl_handle!(COMPONENT_BASE_FLEX_ITEM for Item);
impl ComponentTrait for Item {
fn new() -> Self {
Item::default()
.with_item_classes(ClassesOp::Add, "pt-flex__item")
.with_inner_classes(ClassesOp::Add, "pt-flex__item-inner")
}
fn id(&self) -> Option<String> {
@ -37,6 +35,23 @@ impl ComponentTrait for Item {
(self.renderable.check)(cx)
}
fn setup_before_prepare(&mut self, _cx: &mut Context) {
self.item_classes.alter_value(
ClassesOp::AddFirst,
[
"pt-flex__item".to_owned(),
self.item_grow.to_string(),
self.item_shrink.to_string(),
self.item_size.to_string(),
self.item_offset.to_string(),
self.item_align.to_string(),
]
.join(" "),
);
self.inner_classes
.alter_value(ClassesOp::AddFirst, "pt-flex__item-inner");
}
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
let order = match self.weight() {
0 => None,
@ -55,6 +70,12 @@ impl ComponentTrait for Item {
impl Item {
// Item BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value;
@ -67,12 +88,6 @@ impl Item {
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_item_classes(&mut self, op: ClassesOp, classes: impl Into<String>) -> &mut Self {
self.item_classes.alter_value(op, classes);
@ -87,62 +102,43 @@ impl Item {
#[fn_builder]
pub fn alter_grow(&mut self, grow: flex::ItemGrow) -> &mut Self {
self.item_classes.alter_value(
ClassesOp::Replace(self.item_grow.to_string()),
grow.to_string(),
);
self.item_grow = grow;
self
}
#[fn_builder]
pub fn alter_shrink(&mut self, shrink: flex::ItemShrink) -> &mut Self {
self.item_classes.alter_value(
ClassesOp::Replace(self.item_shrink.to_string()),
shrink.to_string(),
);
self.item_shrink = shrink;
self
}
#[fn_builder]
pub fn alter_size(&mut self, size: flex::ItemSize) -> &mut Self {
self.item_classes.alter_value(
ClassesOp::Replace(self.item_size.to_string()),
size.to_string(),
);
self.item_size = size;
self
}
#[fn_builder]
pub fn alter_offset(&mut self, offset: flex::ItemOffset) -> &mut Self {
self.item_classes.alter_value(
ClassesOp::Replace(self.item_offset.to_string()),
offset.to_string(),
);
self.item_offset = offset;
self
}
#[fn_builder]
pub fn alter_align(&mut self, align: flex::ItemAlign) -> &mut Self {
self.item_classes.alter_value(
ClassesOp::Replace(self.item_align.to_string()),
align.to_string(),
);
self.item_align = align;
self
}
#[rustfmt::skip]
pub fn add_component(mut self, component: impl ComponentTrait) -> Self {
self.stuff.alter(ArcOp::Add(ArcComponent::with(component)));
self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(component)));
self
}
#[fn_builder]
pub fn alter_components(&mut self, op: ArcOp) -> &mut Self {
self.stuff.alter(op);
pub fn alter_components(&mut self, op: ArcAnyOp) -> &mut Self {
self.stuff.alter_value(op);
self
}
@ -176,7 +172,7 @@ impl Item {
&self.item_align
}
pub fn components(&self) -> &ArcComponents {
pub fn components(&self) -> &AnyComponents {
&self.stuff
}
}

View file

@ -37,7 +37,7 @@ impl_handle!(COMPONENT_BASE_BUTTON for Button);
impl ComponentTrait for Button {
fn new() -> Self {
Button::default().with_classes(ClassesOp::Add, "btn btn-primary form-button")
Button::default()
}
fn weight(&self) -> Weight {
@ -48,16 +48,18 @@ impl ComponentTrait for Button {
(self.renderable.check)(cx)
}
fn setup_before_prepare(&mut self, _cx: &mut Context) {
self.classes.alter_value(
ClassesOp::AddFirst,
concat_string!("btn btn-primary form-", self.button_type.to_string()),
);
}
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
let button_type = match self.button_type() {
ButtonType::Button => "button",
ButtonType::Submit => "submit",
ButtonType::Reset => "reset",
};
let id = self.name().get().map(|name| concat_string!("edit-", name));
PrepareMarkup::With(html! {
button
type=(button_type)
type=(self.button_type().to_string())
id=[id]
class=[self.classes().get()]
name=[self.name().get()]
@ -65,7 +67,7 @@ impl ComponentTrait for Button {
autofocus=[self.autofocus().get()]
disabled=[self.disabled().get()]
{
(self.value().escaped(cx.langid()))
(self.value().escaped(cx.langid()).unwrap_or_default())
}
})
}
@ -77,17 +79,13 @@ impl Button {
}
pub fn submit(value: L10n) -> Self {
let mut button = Button::default()
.with_classes(ClassesOp::Replace("form-button".to_owned()), "form-submit")
.with_value(value);
let mut button = Button::default().with_value(value);
button.button_type = ButtonType::Submit;
button
}
pub fn reset(value: L10n) -> Self {
let mut button = Button::default()
.with_classes(ClassesOp::Replace("form-button".to_owned()), "form-reset")
.with_value(value);
let mut button = Button::default().with_value(value);
button.button_type = ButtonType::Reset;
button
}

View file

@ -41,9 +41,9 @@ impl ToString for HeadingDisplay {
#[rustfmt::skip]
#[derive(Default)]
pub struct Heading {
id : OptionId,
weight : Weight,
renderable : Renderable,
id : OptionId,
classes : OptionClasses,
heading_type: HeadingType,
text : OptionTranslated,
@ -72,13 +72,14 @@ impl ComponentTrait for Heading {
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
let id = self.id();
let classes = self.classes().get();
let text = self.text().escaped(cx.langid()).unwrap_or_default();
PrepareMarkup::With(html! { @match &self.heading_type() {
HeadingType::H1 => h1 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H2 => h2 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H3 => h3 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H4 => h4 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H5 => h5 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H6 => h6 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H1 => h1 id=[id] class=[classes] { (text) },
HeadingType::H2 => h2 id=[id] class=[classes] { (text) },
HeadingType::H3 => h3 id=[id] class=[classes] { (text) },
HeadingType::H4 => h4 id=[id] class=[classes] { (text) },
HeadingType::H5 => h5 id=[id] class=[classes] { (text) },
HeadingType::H6 => h6 id=[id] class=[classes] { (text) },
}})
}
}
@ -122,6 +123,12 @@ impl Heading {
// Heading BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value;
@ -134,12 +141,6 @@ impl Heading {
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: impl Into<String>) -> &mut Self {
self.classes.alter_value(op, classes);

View file

@ -6,8 +6,8 @@ pub struct Icon {
weight : Weight,
renderable: Renderable,
classes : OptionClasses,
icon_name : OptionString,
font_size : FontSize,
icon_name : String,
}
impl_handle!(COMPONENT_BASE_ICON for Icon);
@ -25,17 +25,26 @@ impl ComponentTrait for Icon {
(self.renderable.check)(cx)
}
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
if self.icon_name().is_empty() {
return PrepareMarkup::None;
fn setup_before_prepare(&mut self, cx: &mut Context) {
if let Some(icon_name) = self.icon_name.get() {
self.classes.alter_value(
ClassesOp::AddFirst,
concat_string!("bi-", icon_name, " ", self.font_size.to_string()),
);
cx.set_param::<bool>(PARAM_BASE_INCLUDE_ICONS, true);
}
}
fn prepare_component(&self, _cx: &mut Context) -> PrepareMarkup {
match self.icon_name().get() {
None => PrepareMarkup::None,
_ => PrepareMarkup::With(html! { i class=[self.classes().get()] {} }),
}
cx.set_param::<bool>(PARAM_BASE_INCLUDE_ICONS, true);
PrepareMarkup::With(html! { i class=[self.classes().get()] {} })
}
}
impl Icon {
pub fn with(icon_name: &str) -> Self {
pub fn with(icon_name: impl Into<String>) -> Self {
Icon::default().with_icon_name(icon_name)
}
@ -60,22 +69,14 @@ impl Icon {
}
#[fn_builder]
pub fn alter_font_size(&mut self, font_size: FontSize) -> &mut Self {
self.classes.alter_value(
ClassesOp::Replace(self.font_size.to_string()),
font_size.to_string(),
);
self.font_size = font_size;
pub fn alter_icon_name(&mut self, name: impl Into<String>) -> &mut Self {
self.icon_name.alter_value(name);
self
}
#[fn_builder]
pub fn alter_icon_name(&mut self, name: &str) -> &mut Self {
self.classes.alter_value(
ClassesOp::Replace(concat_string!("bi-", self.icon_name)),
concat_string!("bi-", name),
);
self.icon_name = name.to_owned();
pub fn alter_font_size(&mut self, font_size: FontSize) -> &mut Self {
self.font_size = font_size;
self
}
@ -85,11 +86,11 @@ impl Icon {
&self.classes
}
pub fn icon_name(&self) -> &OptionString {
&self.icon_name
}
pub fn font_size(&self) -> &FontSize {
&self.font_size
}
pub fn icon_name(&self) -> &str {
self.icon_name.as_str()
}
}

View file

@ -16,9 +16,9 @@ pub enum ImageSize {
#[rustfmt::skip]
#[derive(Default)]
pub struct Image {
id : OptionId,
weight : Weight,
renderable: Renderable,
id : OptionId,
classes : OptionClasses,
source : OptionString,
size : ImageSize,
@ -84,6 +84,12 @@ impl Image {
// Image BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value;
@ -96,12 +102,6 @@ impl Image {
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: impl Into<String>) -> &mut Self {
self.classes.alter_value(op, classes);

View file

@ -3,12 +3,12 @@ use crate::prelude::*;
#[rustfmt::skip]
#[derive(Default)]
pub struct Paragraph {
id : OptionId,
weight : Weight,
renderable: Renderable,
id : OptionId,
classes : OptionClasses,
font_size : FontSize,
stuff : ArcComponents,
stuff : AnyComponents,
}
impl_handle!(COMPONENT_BASE_PARAGRAPH for Paragraph);
@ -30,6 +30,11 @@ impl ComponentTrait for Paragraph {
(self.renderable.check)(cx)
}
fn setup_before_prepare(&mut self, _cx: &mut Context) {
self.classes
.alter_value(ClassesOp::AddFirst, self.font_size.to_string());
}
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
PrepareMarkup::With(html! {
p
@ -53,6 +58,12 @@ impl Paragraph {
// Paragraph BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value;
@ -65,12 +76,6 @@ impl Paragraph {
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: impl Into<String>) -> &mut Self {
self.classes.alter_value(op, classes);
@ -79,28 +84,25 @@ impl Paragraph {
#[fn_builder]
pub fn alter_font_size(&mut self, font_size: FontSize) -> &mut Self {
self.classes.alter_value(
ClassesOp::Replace(self.font_size.to_string()),
font_size.to_string(),
);
self.font_size = font_size;
self
}
#[rustfmt::skip]
pub fn add_component(mut self, component: impl ComponentTrait) -> Self {
self.stuff.alter(ArcOp::Add(ArcComponent::with(component)));
self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(component)));
self
}
#[rustfmt::skip]
pub fn add_translated(mut self, l10n: L10n) -> Self {
self.stuff
.alter(ArcOp::Add(ArcComponent::with(Translate::with(l10n))));
self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(Translate::with(l10n))));
self
}
#[fn_builder]
pub fn alter_components(&mut self, op: ArcOp) -> &mut Self {
self.stuff.alter(op);
pub fn alter_components(&mut self, op: ArcAnyOp) -> &mut Self {
self.stuff.alter_value(op);
self
}
@ -114,7 +116,7 @@ impl Paragraph {
&self.font_size
}
pub fn components(&self) -> &ArcComponents {
pub fn components(&self) -> &AnyComponents {
&self.stuff
}
}

View file

@ -13,13 +13,13 @@ pub enum WrapperType {
#[rustfmt::skip]
#[derive(Default)]
pub struct Wrapper {
id : OptionId,
weight : Weight,
renderable : Renderable,
id : OptionId,
classes : OptionClasses,
inner_classes: OptionClasses,
wrapper_type : WrapperType,
stuff : ArcComponents,
stuff : AnyComponents,
template : String,
}
@ -118,6 +118,12 @@ impl Wrapper {
// Wrapper BUILDER.
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
self.weight = value;
@ -130,12 +136,6 @@ impl Wrapper {
self
}
#[fn_builder]
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
self.id.alter_value(id);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: impl Into<String>) -> &mut Self {
self.classes.alter_value(op, classes);
@ -148,14 +148,15 @@ impl Wrapper {
self
}
#[rustfmt::skip]
pub fn add_component(mut self, component: impl ComponentTrait) -> Self {
self.stuff.alter(ArcOp::Add(ArcComponent::with(component)));
self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(component)));
self
}
#[fn_builder]
pub fn alter_components(&mut self, op: ArcOp) -> &mut Self {
self.stuff.alter(op);
pub fn alter_components(&mut self, op: ArcAnyOp) -> &mut Self {
self.stuff.alter_value(op);
self
}
@ -179,7 +180,7 @@ impl Wrapper {
&self.wrapper_type
}
pub fn components(&self) -> &ArcComponents {
pub fn components(&self) -> &AnyComponents {
&self.stuff
}

View file

@ -39,6 +39,9 @@ pub trait ComponentTrait: ComponentBase + HasHandle + Send + Sync {
true
}
#[allow(unused_variables)]
fn setup_before_prepare(&mut self, cx: &mut Context) {}
#[allow(unused_variables)]
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
PrepareMarkup::None
@ -48,6 +51,9 @@ pub trait ComponentTrait: ComponentBase + HasHandle + Send + Sync {
impl<C: ComponentTrait> ComponentBase for C {
fn render(&mut self, cx: &mut Context) -> Markup {
if self.is_renderable(cx) {
// Comprueba el componente antes de prepararlo.
self.setup_before_prepare(cx);
// Acciones del tema antes de preparar el componente.
cx.theme().before_prepare_component(self, cx);

File diff suppressed because it is too large Load diff

View file

@ -18,7 +18,7 @@ body {
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: var(--pt-gap-0-9);
margin-bottom: var(--pt-gap-0-35);
font-weight: var(--pt-fw--bold);
line-height: var(--pt-lh--header);
}
@ -58,7 +58,18 @@ h6 {
p {
margin-top: 0;
margin-bottom: var(--pt-gap-0-9);
margin-bottom: var(--pt-gap-0-75);
}
a {
color: var(--pt-color--primary);
transition: color .15s ease-in-out;
}
a:hover {
color: var(--pt-color--primary-dark);
}
a:active {
color: var(--pt-color--primary-light);
}
/* LAYOUT */

View file

@ -96,7 +96,7 @@
font-size: calc(var(--pt-fs--x3l) * 1.2);
}
.pt-heading__subtitle {
margin-top: calc(-1 * var(--pt-gap-0-75));
margin-top: calc(-1 * var(--pt-gap-0-5));
}
/* LG - Applies <= 992px */
@media screen and (max-width: 62em) {

View file

@ -15,10 +15,12 @@
--pt-fs--xs: 0.75rem;
--pt-fs--x2s: 0.5625rem;
--pt-fs--x3s: 0.375rem;
/* Font weight */
--pt-fw--light: 300;
--pt-fw--base: 400;
--pt-fw--bold: 500;
/* Line height */
--pt-lh--base: 1.5;
--pt-lh--header: 1.2;
@ -33,7 +35,7 @@
--line-height-s: 1.125rem;
--max-bg-color: 98.125rem;
*/
--pt-gap: 1.125rem;
--pt-gap: 1.125em;
/*
--content-left: 5.625rem;
--site-header-height-wide: var(--pt-gap10);
@ -82,10 +84,11 @@
}
*/
:root {
--pt-gap-0-15: calc(0.15 * var(--pt-gap));
--pt-gap-0-25: calc(0.25 * var(--pt-gap));
--pt-gap-0-35: calc(0.35 * var(--pt-gap));
--pt-gap-0-5: calc(0.5 * var(--pt-gap));
--pt-gap-0-75: calc(0.75 * var(--pt-gap));
--pt-gap-0-9: calc(0.9 * var(--pt-gap));
--pt-gap-1-5: calc(1.5 * var(--pt-gap));
--pt-gap-2: calc(2 * var(--pt-gap));
--pt-gap-2-5: calc(2.5 * var(--pt-gap));
@ -100,27 +103,24 @@
--pt-gap-11: calc(11 * var(--pt-gap));
--pt-gap-12: calc(12 * var(--pt-gap));
--pt-color--primary-hue: 202;
--pt-color--primary-saturation: 79%;
--pt-color--primary-lightness: 50;
--pt-color--primary-30: hsl(var(--pt-color--primary-hue),var(--pt-color--primary-saturation),calc(1% * (var(--pt-color--primary-lightness) - (0.36 * var(--pt-color--primary-lightness)))));
--pt-color--primary-40: hsl(var(--pt-color--primary-hue),var(--pt-color--primary-saturation),calc(1% * (var(--pt-color--primary-lightness) - (0.24 * var(--pt-color--primary-lightness)))));
--pt-color--primary-50: hsl(var(--pt-color--primary-hue),var(--pt-color--primary-saturation),calc(1% * var(--pt-color--primary-lightness)));
--pt-color--primary-60: hsl(var(--pt-color--primary-hue),var(--pt-color--primary-saturation),calc(1% * (var(--pt-color--primary-lightness) + (0.24 * (100 - var(--pt-color--primary-lightness))))));
--pt-color--primary-80: hsl(var(--pt-color--primary-hue),var(--pt-color--primary-saturation),calc(1% * (var(--pt-color--primary-lightness) + (0.85 * (100 - var(--pt-color--primary-lightness))))));
--pt-color--primary-hue: 216;
--pt-color--primary-sat: 98%;
--pt-color--primary-light: hsl(var(--pt-color--primary-hue), var(--pt-color--primary-sat), 60%);
--pt-color--primary-dark: hsl(var(--pt-color--primary-hue), var(--pt-color--primary-sat), 40%);
--pt-color--primary: hsl(var(--pt-color--primary-hue), var(--pt-color--primary-sat), 50%);
--pt-color--gray-hue: 201;
--pt-color--gray-saturation: 15%;
--pt-color--gray-5: hsl(var(--pt-color--gray-hue),var(--pt-color--gray-saturation),5%);
--pt-color--gray-10: hsl(var(--pt-color--gray-hue),var(--pt-color--gray-saturation),11%);
--pt-color--gray-20: hsl(var(--pt-color--gray-hue),var(--pt-color--gray-saturation),20%);
--pt-color--gray-45: hsl(var(--pt-color--gray-hue),var(--pt-color--gray-saturation),44%);
--pt-color--gray-60: hsl(var(--pt-color--gray-hue),var(--pt-color--gray-saturation),57%);
--pt-color--gray-65: hsl(var(--pt-color--gray-hue),var(--pt-color--gray-saturation),63%);
--pt-color--gray-70: hsl(var(--pt-color--gray-hue),var(--pt-color--gray-saturation),72%);
--pt-color--gray-90: hsl(var(--pt-color--gray-hue),var(--pt-color--gray-saturation),88%);
--pt-color--gray-95: hsl(var(--pt-color--gray-hue),var(--pt-color--gray-saturation),93%);
--pt-color--gray-100: hsl(var(--pt-color--gray-hue),var(--pt-color--gray-saturation),97%);
--pt-color--gray-sat: 15%;
--pt-color--gray-5: hsl(var(--pt-color--gray-hue), var(--pt-color--gray-sat), 5%);
--pt-color--gray-10: hsl(var(--pt-color--gray-hue), var(--pt-color--gray-sat) ,11%);
--pt-color--gray-20: hsl(var(--pt-color--gray-hue), var(--pt-color--gray-sat),20%);
--pt-color--gray-45: hsl(var(--pt-color--gray-hue), var(--pt-color--gray-sat), 44%);
--pt-color--gray-60: hsl(var(--pt-color--gray-hue), var(--pt-color--gray-sat), 57%);
--pt-color--gray-65: hsl(var(--pt-color--gray-hue), var(--pt-color--gray-sat), 63%);
--pt-color--gray-70: hsl(var(--pt-color--gray-hue), var(--pt-color--gray-sat), 72%);
--pt-color--gray-90: hsl(var(--pt-color--gray-hue), var(--pt-color--gray-sat), 88%);
--pt-color--gray-95: hsl(var(--pt-color--gray-hue), var(--pt-color--gray-sat), 93%);
--pt-color--gray-100: hsl(var(--pt-color--gray-hue), var(--pt-color--gray-sat), 97%);
--pt-color--white: #fff;
--pt-color--bg: #fafafa;
@ -143,9 +143,9 @@
--header-height-wide-when-fixed: calc(6 * var(--pt-gap));
--mobile-nav-width: 31.25rem;
*/
--pt-border-radius: 0.1875rem;
--pt-border-radius: 0.375rem;
/* Menu component */
--pt-menu--color-bg: var(--pt-color--gray-100);
--pt-menu--color-highlight: #e91e63;
--pt-menu--color-border: rgba(0, 0, 0, 0.1);