🎨 Incluye componentes base originales de PageTop

This commit is contained in:
Manuel Cillero 2023-05-14 18:11:51 +02:00
parent fc579fc29d
commit ee46003c15
29 changed files with 4276 additions and 11 deletions

View file

@ -7,13 +7,16 @@ authors = [
"Manuel Cillero <manuel@cillero.es>"
]
description = """\
Theme for PageTop with a minimal set of styles to view the basic composition of pages and \
components.\
Module for PageTop with a minimal set of components for page composition.\
"""
homepage = "https://pagetop.cillero.es"
repository = "https://github.com/manuelcillero/pagetop"
license = "Apache-2.0 OR MIT"
[dependencies]
pagetop = { path = "../pagetop", version = "0.0" }
pagetop = { version = "0.0", path = "../pagetop" }
static-files = "0.2.3"
maud = "0.25.0"
[build-dependencies]
pagetop-build = { version = "0.0", path = "../pagetop-build" }

View file

@ -1,5 +1,4 @@
Tema de prueba para **PageTop** con un conjunto mínimo de estilos para ver la composición básica de
páginas y componentes.
Proporciona un conjunto básico de componentes para la composición de páginas en **PageTop**.
[PageTop](https://github.com/manuelcillero/pagetop/tree/main/pagetop), es un entorno de desarrollo
basado en algunos de los *crates* más estables y populares del ecosistema Rust para proporcionar

3
pagetop-minimal/build.rs Normal file
View file

@ -0,0 +1,3 @@
fn main() -> std::io::Result<()> {
pagetop_build::bundle_resources("./static", "minimal", None)
}

View file

@ -0,0 +1,22 @@
mod container;
pub use container::{Container, ContainerType, COMPONENT_CONTAINER};
pub mod grid;
mod html;
pub use html::{Html, COMPONENT_HTML};
mod icon;
pub use icon::{Icon, COMPONENT_ICON};
mod heading;
pub use heading::{Heading, HeadingDisplay, HeadingType, COMPONENT_HEADING};
mod paragraph;
pub use paragraph::{Paragraph, ParagraphDisplay, COMPONENT_PARAGRAPH};
mod anchor;
pub use anchor::{Anchor, AnchorIcon, AnchorTarget, AnchorType, COMPONENT_ANCHOR};
mod block;
pub use block::{Block, COMPONENT_BLOCK};
mod image;
pub use image::{Image, COMPONENT_IMAGE};
pub mod form_element;
pub use form_element::{Form, FormMethod, COMPONENT_FORM};

View file

@ -0,0 +1,222 @@
use pagetop::prelude::*;
use crate::component::Icon;
pub_handle!(COMPONENT_ANCHOR);
#[derive(Default)]
pub enum AnchorType {
#[default]
Link,
Button,
Location,
}
#[derive(Default)]
pub enum AnchorTarget {
#[default]
Default,
Blank,
Parent,
Top,
Context(String),
}
pub type AnchorIcon = ComponentsBundle;
#[rustfmt::skip]
#[derive(Default)]
pub struct Anchor {
weight : isize,
renderable : Renderable,
id : IdentifierValue,
classes : Classes,
anchor_type: AnchorType,
href : AttributeValue,
html : HtmlMarkup,
left_icon : AnchorIcon,
right_icon : AnchorIcon,
target : AnchorTarget,
template : String,
}
impl ComponentTrait for Anchor {
fn new() -> Self {
Anchor::default()
}
fn handle(&self) -> Handle {
COMPONENT_ANCHOR
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
#[rustfmt::skip]
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
let target = match &self.target() {
AnchorTarget::Blank => Some("_blank"),
AnchorTarget::Parent => Some("_parent"),
AnchorTarget::Top => Some("_top"),
AnchorTarget::Context(name) => Some(name.as_str()),
_ => None,
};
html! {
a
id=[self.id().get()]
class=[self.classes().get()]
href=[self.href().get()]
target=[target]
{
(self.left_icon().render(rcx))
span { (*self.html()) }
(self.right_icon().render(rcx))
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Anchor {
pub fn link(href: &str, html: Markup) -> Self {
Anchor::new().with_href(href).with_html(html)
}
pub fn button(href: &str, html: Markup) -> Self {
Anchor::new()
.with_type(AnchorType::Button)
.with_href(href)
.with_html(html)
}
pub fn location(id: &str) -> Self {
Anchor::new().with_type(AnchorType::Location).with_id(id)
}
// Anchor BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &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
}
#[fn_builder]
pub fn alter_type(&mut self, anchor_type: AnchorType) -> &mut Self {
self.anchor_type = anchor_type;
self.classes.alter_value(
ClassesOp::SetDefault,
match self.anchor_type {
AnchorType::Button => "btn btn-primary",
_ => "",
},
);
self
}
#[fn_builder]
pub fn alter_href(&mut self, href: &str) -> &mut Self {
self.href.alter_value(href);
self
}
#[fn_builder]
pub fn alter_html(&mut self, html: Markup) -> &mut Self {
self.html.markup = html;
self
}
#[fn_builder]
pub fn alter_left_icon(&mut self, icon: Icon) -> &mut Self {
self.left_icon.clear();
self.left_icon.add(icon);
self
}
#[fn_builder]
pub fn alter_right_icon(&mut self, icon: Icon) -> &mut Self {
self.right_icon.clear();
self.right_icon.add(icon);
self
}
#[fn_builder]
pub fn alter_target(&mut self, target: AnchorTarget) -> &mut Self {
self.target = target;
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Anchor GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn anchor_type(&self) -> &AnchorType {
&self.anchor_type
}
pub fn href(&self) -> &AttributeValue {
&self.href
}
pub fn html(&self) -> &Markup {
&self.html.markup
}
pub fn left_icon(&self) -> &AnchorIcon {
&self.left_icon
}
pub fn right_icon(&self) -> &AnchorIcon {
&self.right_icon
}
pub fn target(&self) -> &AnchorTarget {
&self.target
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,129 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_BLOCK);
hook_before_render_component!(HOOK_BEFORE_RENDER_BLOCK, Block);
#[rustfmt::skip]
#[derive(Default)]
pub struct Block {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
title : AttributeValue,
components: ComponentsBundle,
template : String,
}
impl ComponentTrait for Block {
fn new() -> Self {
Block::default().with_classes(ClassesOp::SetDefault, "block")
}
fn handle(&self) -> Handle {
COMPONENT_BLOCK
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
before_render_inline(self, rcx);
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
let id = rcx.required_id::<Block>(self.id());
html! {
div id=(id) class=[self.classes().get()] {
@if let Some(title) = self.title().get() {
h2 class="block-title" { (title) }
}
div class="block-body" {
(self.components().render(rcx))
}
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Block {
// Block BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &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
}
#[fn_builder]
pub fn alter_title(&mut self, title: &str) -> &mut Self {
self.title.alter_value(title);
self
}
#[fn_builder]
pub fn alter_component(&mut self, component: impl ComponentTrait) -> &mut Self {
self.components.add(component);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Block GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn title(&self) -> &AttributeValue {
&self.title
}
pub fn components(&self) -> &ComponentsBundle {
&self.components
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,194 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_CONTAINER);
hook_before_render_component!(HOOK_BEFORE_RENDER_CONTAINER, Container);
#[derive(Default)]
pub enum ContainerType {
#[default]
Wrapper,
Header,
Footer,
Main,
Section,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Container {
weight : isize,
renderable : Renderable,
id : IdentifierValue,
classes : Classes,
inner_classes : Classes,
container_type: ContainerType,
components : ComponentsBundle,
template : String,
}
impl ComponentTrait for Container {
fn new() -> Self {
Container::default()
.with_classes(ClassesOp::SetDefault, "container")
.with_inner_classes(ClassesOp::SetDefault, "container")
}
fn handle(&self) -> Handle {
COMPONENT_CONTAINER
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
before_render_inline(self, rcx);
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
match self.container_type() {
ContainerType::Header => html! {
header id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(rcx))
}
}
},
ContainerType::Footer => html! {
footer id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(rcx))
}
}
},
ContainerType::Main => html! {
main id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(rcx))
}
}
},
ContainerType::Section => html! {
section id=[self.id().get()] class=[self.classes().get()] {
div class=[self.inner_classes().get()] {
(self.components().render(rcx))
}
}
},
_ => html! {
div id=[self.id().get()] class=[self.classes().get()] {
(self.components().render(rcx))
}
},
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Container {
pub fn header() -> Self {
let mut c = Container::new().with_classes(ClassesOp::SetDefault, "header");
c.container_type = ContainerType::Header;
c
}
pub fn footer() -> Self {
let mut c = Container::new().with_classes(ClassesOp::SetDefault, "footer");
c.container_type = ContainerType::Footer;
c
}
pub fn main() -> Self {
let mut c = Container::new().with_classes(ClassesOp::SetDefault, "main");
c.container_type = ContainerType::Main;
c
}
pub fn section() -> Self {
let mut c = Container::new().with_classes(ClassesOp::SetDefault, "section");
c.container_type = ContainerType::Section;
c
}
// Container BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &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
}
#[fn_builder]
pub fn alter_inner_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.inner_classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_component(&mut self, component: impl ComponentTrait) -> &mut Self {
self.components.add(component);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Container GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn inner_classes(&self) -> &Classes {
&self.inner_classes
}
pub fn container_type(&self) -> &ContainerType {
&self.container_type
}
pub fn components(&self) -> &ComponentsBundle {
&self.components
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,11 @@
mod form;
pub use form::{Form, FormMethod, COMPONENT_FORM};
mod input;
pub use input::{Input, InputType, COMPONENT_INPUT};
mod hidden;
pub use hidden::{Hidden, COMPONENT_HIDDEN};
mod date;
pub use date::{Date, COMPONENT_DATE};
mod button;
pub use button::{Button, ButtonType, COMPONENT_BUTTON};

View file

@ -0,0 +1,183 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_BUTTON);
#[derive(Default)]
pub enum ButtonType {
#[default]
Button,
Submit,
Reset,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Button {
weight : isize,
renderable : Renderable,
classes : Classes,
button_type: ButtonType,
name : AttributeValue,
value : AttributeValue,
autofocus : AttributeValue,
disabled : AttributeValue,
template : String,
}
impl ComponentTrait for Button {
fn new() -> Self {
Button::default()
.with_classes(ClassesOp::SetDefault, "btn btn-primary")
.with_classes(ClassesOp::AddFirst, "form-button")
}
fn handle(&self) -> Handle {
COMPONENT_BUTTON
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
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));
html! {
button
type=(button_type)
id=[id]
class=[self.classes().get()]
name=[self.name().get()]
value=[self.value().get()]
autofocus=[self.autofocus().get()]
disabled=[self.disabled().get()]
{
@if let Some(value) = self.value().get() { (value) }
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Button {
pub fn with(value: &str) -> Self {
Button::new().with_value(value)
}
pub fn submit(value: &str) -> Self {
let mut button = Button::new()
.with_classes(ClassesOp::Replace("form-button"), "form-submit")
.with_value(value);
button.button_type = ButtonType::Submit;
button
}
pub fn reset(value: &str) -> Self {
let mut button = Button::new()
.with_classes(ClassesOp::Replace("form-button"), "form-reset")
.with_value(value);
button.button_type = ButtonType::Reset;
button
}
// Button BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.alter_value(name);
self
}
#[fn_builder]
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.alter_value(value);
self
}
#[fn_builder]
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
self.autofocus.alter_value(match toggle {
true => "autofocus",
false => "",
});
self
}
#[fn_builder]
pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
self.disabled.alter_value(match toggle {
true => "disabled",
false => "",
});
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Button GETTERS.
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn button_type(&self) -> &ButtonType {
&self.button_type
}
pub fn name(&self) -> &AttributeValue {
&self.name
}
pub fn value(&self) -> &AttributeValue {
&self.value
}
pub fn autofocus(&self) -> &AttributeValue {
&self.autofocus
}
pub fn disabled(&self) -> &AttributeValue {
&self.disabled
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,236 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_DATE);
#[rustfmt::skip]
#[derive(Default)]
pub struct Date {
weight : isize,
renderable : Renderable,
classes : Classes,
name : AttributeValue,
value : AttributeValue,
label : AttributeValue,
placeholder : AttributeValue,
autofocus : AttributeValue,
autocomplete: AttributeValue,
disabled : AttributeValue,
readonly : AttributeValue,
required : AttributeValue,
help_text : AttributeValue,
template : String,
}
impl ComponentTrait for Date {
fn new() -> Self {
Date::default()
.with_classes(ClassesOp::SetDefault, "form-item")
.with_classes(ClassesOp::AddFirst, "form-type-date")
}
fn handle(&self) -> Handle {
COMPONENT_DATE
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
let id = self.name().get().map(|name| concat_string!("edit-", name));
html! {
div class=[self.classes().get()] {
@if let Some(label) = self.label().get() {
label class="form-label" for=[&id] {
(label) " "
@if self.required().get().is_some() {
span
class="form-required"
title="Este campo es obligatorio." { "*" } " ";
}
}
}
input
type="date"
id=[id]
class="form-control"
name=[self.name().get()]
value=[self.value().get()]
placeholder=[self.placeholder().get()]
autofocus=[self.autofocus().get()]
autocomplete=[self.autocomplete().get()]
readonly=[self.readonly().get()]
required=[self.required().get()]
disabled=[self.disabled().get()];
@if let Some(help_text) = self.help_text().get() {
div class="form-text" { (help_text) }
}
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Date {
// Date BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.alter_value(name);
self
}
#[fn_builder]
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.alter_value(value);
self
}
#[fn_builder]
pub fn alter_label(&mut self, label: &str) -> &mut Self {
self.label.alter_value(label);
self
}
#[fn_builder]
pub fn alter_placeholder(&mut self, placeholder: &str) -> &mut Self {
self.placeholder.alter_value(placeholder);
self
}
#[fn_builder]
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
self.autofocus.alter_value(match toggle {
true => "autofocus",
false => "",
});
self
}
#[fn_builder]
pub fn alter_autocomplete(&mut self, toggle: bool) -> &mut Self {
self.autocomplete.alter_value(match toggle {
true => "",
false => "off",
});
self
}
#[fn_builder]
pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
self.disabled.alter_value(match toggle {
true => "disabled",
false => "",
});
self
}
#[fn_builder]
pub fn alter_readonly(&mut self, toggle: bool) -> &mut Self {
self.readonly.alter_value(match toggle {
true => "readonly",
false => "",
});
self
}
#[fn_builder]
pub fn alter_required(&mut self, toggle: bool) -> &mut Self {
self.required.alter_value(match toggle {
true => "required",
false => "",
});
self
}
#[fn_builder]
pub fn alter_help_text(&mut self, help_text: &str) -> &mut Self {
self.help_text.alter_value(help_text);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Date GETTERS.
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn name(&self) -> &AttributeValue {
&self.name
}
pub fn value(&self) -> &AttributeValue {
&self.value
}
pub fn label(&self) -> &AttributeValue {
&self.label
}
pub fn placeholder(&self) -> &AttributeValue {
&self.placeholder
}
pub fn autofocus(&self) -> &AttributeValue {
&self.autofocus
}
pub fn autocomplete(&self) -> &AttributeValue {
&self.autocomplete
}
pub fn disabled(&self) -> &AttributeValue {
&self.disabled
}
pub fn readonly(&self) -> &AttributeValue {
&self.readonly
}
pub fn required(&self) -> &AttributeValue {
&self.required
}
pub fn help_text(&self) -> &AttributeValue {
&self.help_text
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,164 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_FORM);
hook_before_render_component!(HOOK_BEFORE_RENDER_FORM, Form);
#[derive(Default)]
pub enum FormMethod {
#[default]
Post,
Get,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Form {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
action : AttributeValue,
charset : AttributeValue,
method : FormMethod,
elements : ComponentsBundle,
template : String,
}
impl ComponentTrait for Form {
fn new() -> Self {
Form::default()
.with_classes(ClassesOp::SetDefault, "form")
.with_charset("UTF-8")
}
fn handle(&self) -> Handle {
COMPONENT_FORM
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
before_render_inline(self, rcx);
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
let method = match self.method() {
FormMethod::Post => Some("post".to_owned()),
FormMethod::Get => None,
};
html! {
form
id=[self.id().get()]
class=[self.classes().get()]
action=[self.action().get()]
method=[method]
accept-charset=[self.charset().get()]
{
div { (self.elements().render(rcx)) }
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Form {
// Form BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &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
}
#[fn_builder]
pub fn alter_action(&mut self, action: &str) -> &mut Self {
self.action.alter_value(action);
self
}
#[fn_builder]
pub fn alter_charset(&mut self, charset: &str) -> &mut Self {
self.charset.alter_value(charset);
self
}
#[fn_builder]
pub fn alter_method(&mut self, method: FormMethod) -> &mut Self {
self.method = method;
self
}
#[fn_builder]
pub fn alter_element(&mut self, element: impl ComponentTrait) -> &mut Self {
self.elements.add(element);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Form GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn action(&self) -> &AttributeValue {
&self.action
}
pub fn charset(&self) -> &AttributeValue {
&self.charset
}
pub fn method(&self) -> &FormMethod {
&self.method
}
pub fn elements(&self) -> &ComponentsBundle {
&self.elements
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,76 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_HIDDEN);
#[rustfmt::skip]
#[derive(Default)]
pub struct Hidden {
weight: isize,
name : NameValue,
value : AttributeValue,
}
impl ComponentTrait for Hidden {
fn new() -> Self {
Hidden::default()
}
fn handle(&self) -> Handle {
COMPONENT_HIDDEN
}
fn weight(&self) -> isize {
self.weight
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
let id = self.name().get().map(|name| concat_string!("value-", name));
html! {
input type="hidden" id=[id] name=[self.name().get()] value=[self.value().get()];
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Hidden {
pub fn set(name: &str, value: &str) -> Self {
Hidden::new().with_name(name).with_value(value)
}
// Hidden BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.alter_value(name);
self
}
#[fn_builder]
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.alter_value(value);
self
}
// Hidden GETTERS.
pub fn name(&self) -> &NameValue {
&self.name
}
pub fn value(&self) -> &AttributeValue {
&self.value
}
}

View file

@ -0,0 +1,357 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_INPUT);
#[derive(Default)]
pub enum InputType {
#[default]
Textfield,
Password,
Search,
Email,
Telephone,
Url,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Input {
weight : isize,
renderable : Renderable,
classes : Classes,
input_type : InputType,
name : NameValue,
value : AttributeValue,
label : AttributeValue,
size : Option<u16>,
minlength : Option<u16>,
maxlength : Option<u16>,
placeholder : AttributeValue,
autofocus : AttributeValue,
autocomplete: AttributeValue,
disabled : AttributeValue,
readonly : AttributeValue,
required : AttributeValue,
help_text : AttributeValue,
template : String,
}
impl ComponentTrait for Input {
fn new() -> Self {
Input::default()
.with_classes(ClassesOp::SetDefault, "form-item")
.with_classes(ClassesOp::AddFirst, "form-type-textfield")
.with_size(Some(60))
.with_maxlength(Some(128))
}
fn handle(&self) -> Handle {
COMPONENT_INPUT
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
#[rustfmt::skip]
fn default_render(&self, _: &mut RenderContext) -> Markup {
let type_input = match self.input_type() {
InputType::Textfield => "text",
InputType::Password => "password",
InputType::Search => "search",
InputType::Email => "email",
InputType::Telephone => "tel",
InputType::Url => "url",
};
let id = self.name().get().map(|name| concat_string!("edit-", name));
html! {
div class=[self.classes().get()] {
@if let Some(label) = self.label().get() {
label class="form-label" for=[&id] {
(label) " "
@if self.required().get().is_some() {
span
class="form-required"
title="Este campo es obligatorio." { "*" } " ";
}
}
}
input
type=(type_input)
id=[id]
class="form-control"
name=[self.name().get()]
value=[self.value().get()]
size=[self.size()]
minlength=[self.minlength()]
maxlength=[self.maxlength()]
placeholder=[self.placeholder().get()]
autofocus=[self.autofocus().get()]
autocomplete=[self.autocomplete().get()]
readonly=[self.readonly().get()]
required=[self.required().get()]
disabled=[self.disabled().get()];
@if let Some(help_text) = self.help_text().get() {
div class="form-text" { (help_text) }
}
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Input {
pub fn textfield() -> Self {
Input::new()
}
#[rustfmt::skip]
pub fn password() -> Self {
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-password",
);
input.input_type = InputType::Password;
input
}
#[rustfmt::skip]
pub fn search() -> Self {
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-search",
);
input.input_type = InputType::Search;
input
}
#[rustfmt::skip]
pub fn email() -> Self {
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-email"
);
input.input_type = InputType::Email;
input
}
#[rustfmt::skip]
pub fn telephone() -> Self {
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-telephone",
);
input.input_type = InputType::Telephone;
input
}
#[rustfmt::skip]
pub fn url() -> Self {
let mut input = Input::new().with_classes(
ClassesOp::Replace("form-type-textfield"),
"form-type-url"
);
input.input_type = InputType::Url;
input
}
// Input BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
#[fn_builder]
pub fn alter_name(&mut self, name: &str) -> &mut Self {
self.name.alter_value(name);
self.alter_classes(
ClassesOp::SetDefault,
concat_string!("form-item form-item-", name).as_str(),
);
self
}
#[fn_builder]
pub fn alter_value(&mut self, value: &str) -> &mut Self {
self.value.alter_value(value);
self
}
#[fn_builder]
pub fn alter_label(&mut self, label: &str) -> &mut Self {
self.label.alter_value(label);
self
}
#[fn_builder]
pub fn alter_size(&mut self, size: Option<u16>) -> &mut Self {
self.size = size;
self
}
#[fn_builder]
pub fn alter_minlength(&mut self, minlength: Option<u16>) -> &mut Self {
self.minlength = minlength;
self
}
#[fn_builder]
pub fn alter_maxlength(&mut self, maxlength: Option<u16>) -> &mut Self {
self.maxlength = maxlength;
self
}
#[fn_builder]
pub fn alter_placeholder(&mut self, placeholder: &str) -> &mut Self {
self.placeholder.alter_value(placeholder);
self
}
#[fn_builder]
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
self.autofocus.alter_value(match toggle {
true => "autofocus",
false => "",
});
self
}
#[fn_builder]
pub fn alter_autocomplete(&mut self, toggle: bool) -> &mut Self {
self.autocomplete.alter_value(match toggle {
true => "",
false => "off",
});
self
}
#[fn_builder]
pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
self.disabled.alter_value(match toggle {
true => "disabled",
false => "",
});
self
}
#[fn_builder]
pub fn alter_readonly(&mut self, toggle: bool) -> &mut Self {
self.readonly.alter_value(match toggle {
true => "readonly",
false => "",
});
self
}
#[fn_builder]
pub fn alter_required(&mut self, toggle: bool) -> &mut Self {
self.required.alter_value(match toggle {
true => "required",
false => "",
});
self
}
#[fn_builder]
pub fn alter_help_text(&mut self, help_text: &str) -> &mut Self {
self.help_text.alter_value(help_text);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Input GETTERS.
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn input_type(&self) -> &InputType {
&self.input_type
}
pub fn name(&self) -> &NameValue {
&self.name
}
pub fn value(&self) -> &AttributeValue {
&self.value
}
pub fn label(&self) -> &AttributeValue {
&self.label
}
pub fn size(&self) -> Option<u16> {
self.size
}
pub fn minlength(&self) -> Option<u16> {
self.minlength
}
pub fn maxlength(&self) -> Option<u16> {
self.maxlength
}
pub fn placeholder(&self) -> &AttributeValue {
&self.placeholder
}
pub fn autofocus(&self) -> &AttributeValue {
&self.autofocus
}
pub fn autocomplete(&self) -> &AttributeValue {
&self.autocomplete
}
pub fn disabled(&self) -> &AttributeValue {
&self.disabled
}
pub fn readonly(&self) -> &AttributeValue {
&self.readonly
}
pub fn required(&self) -> &AttributeValue {
&self.required
}
pub fn help_text(&self) -> &AttributeValue {
&self.help_text
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,4 @@
mod row;
pub use row::{Row, COMPONENT_ROW};
mod column;
pub use column::{Column, ColumnSize, COMPONENT_COLUMN};

View file

@ -0,0 +1,171 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_COLUMN);
hook_before_render_component!(HOOK_BEFORE_RENDER_COLUMN, Column);
const SIZE__DEFAULT: &str = "col-md";
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 ColumnSize {
#[default]
Default,
Is1of12,
Is2of12,
Is3of12,
Is4of12,
Is5of12,
Is6of12,
Is7of12,
Is8of12,
Is9of12,
Is10of12,
Is11of12,
IsFull,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Column {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
size : ColumnSize,
components: ComponentsBundle,
template : String,
}
impl ComponentTrait for Column {
fn new() -> Self {
Column::default().with_classes(ClassesOp::SetDefault, SIZE__DEFAULT)
}
fn handle(&self) -> Handle {
COMPONENT_COLUMN
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
before_render_inline(self, rcx);
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
html! {
div id=[self.id().get()] class=[self.classes().get()] {
(self.components().render(rcx))
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Column {
// Column BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &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: ColumnSize) -> &mut Self {
match size {
ColumnSize::Default => self.alter_classes(ClassesOp::SetDefault, SIZE__DEFAULT),
ColumnSize::Is1of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__1_OF_12),
ColumnSize::Is2of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__2_OF_12),
ColumnSize::Is3of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__3_OF_12),
ColumnSize::Is4of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__4_OF_12),
ColumnSize::Is5of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__5_OF_12),
ColumnSize::Is6of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__6_OF_12),
ColumnSize::Is7of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__7_OF_12),
ColumnSize::Is8of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__8_OF_12),
ColumnSize::Is9of12 => self.alter_classes(ClassesOp::SetDefault, SIZE__9_OF_12),
ColumnSize::Is10of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_10_OF_12),
ColumnSize::Is11of12 => self.alter_classes(ClassesOp::SetDefault, SIZE_11_OF_12),
ColumnSize::IsFull => self.alter_classes(ClassesOp::SetDefault, SIZE_12_OF_12),
};
self.size = size;
self
}
#[fn_builder]
pub fn alter_component(&mut self, component: impl ComponentTrait) -> &mut Self {
self.components.add(component);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Column GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn size(&self) -> &ColumnSize {
&self.size
}
pub fn components(&self) -> &ComponentsBundle {
&self.components
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,114 @@
use pagetop::prelude::*;
use crate::component::grid;
pub_handle!(COMPONENT_ROW);
hook_before_render_component!(HOOK_BEFORE_RENDER_ROW, Row);
#[rustfmt::skip]
#[derive(Default)]
pub struct Row {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
columns : ComponentsBundle,
template : String,
}
impl ComponentTrait for Row {
fn new() -> Self {
Row::default().with_classes(ClassesOp::SetDefault, "row")
}
fn handle(&self) -> Handle {
COMPONENT_ROW
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
before_render_inline(self, rcx);
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
html! {
div id=[self.id().get()] class=[self.classes().get()] {
(self.columns().render(rcx))
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Row {
// Row BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &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
}
#[fn_builder]
pub fn alter_column(&mut self, column: grid::Column) -> &mut Self {
self.columns.add(column);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Row GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn columns(&self) -> &ComponentsBundle {
&self.columns
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,205 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_HEADING);
#[derive(Default)]
pub enum HeadingType {
#[default]
H1,
H2,
H3,
H4,
H5,
H6,
}
#[derive(Default)]
pub enum HeadingDisplay {
#[default]
Normal,
XxLarge,
Large,
Medium,
Small,
XxSmall,
Subtitle,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Heading {
weight : isize,
renderable : Renderable,
id : IdentifierValue,
classes : Classes,
heading_type: HeadingType,
html : HtmlMarkup,
display : HeadingDisplay,
template : String,
}
impl ComponentTrait for Heading {
fn new() -> Self {
Heading::default()
}
fn handle(&self) -> Handle {
COMPONENT_HEADING
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
let id = self.id().get();
let classes = self.classes().get();
html! { @match &self.heading_type() {
HeadingType::H1 => h1 id=[id] class=[classes] { (*self.html()) },
HeadingType::H2 => h2 id=[id] class=[classes] { (*self.html()) },
HeadingType::H3 => h3 id=[id] class=[classes] { (*self.html()) },
HeadingType::H4 => h4 id=[id] class=[classes] { (*self.html()) },
HeadingType::H5 => h5 id=[id] class=[classes] { (*self.html()) },
HeadingType::H6 => h6 id=[id] class=[classes] { (*self.html()) },
}}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Heading {
pub fn h1(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H1)
.with_html(html)
}
pub fn h2(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H2)
.with_html(html)
}
pub fn h3(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H3)
.with_html(html)
}
pub fn h4(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H4)
.with_html(html)
}
pub fn h5(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H5)
.with_html(html)
}
pub fn h6(html: Markup) -> Self {
Heading::new()
.with_heading_type(HeadingType::H6)
.with_html(html)
}
// Heading BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &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
}
#[fn_builder]
pub fn alter_heading_type(&mut self, heading_type: HeadingType) -> &mut Self {
self.heading_type = heading_type;
self
}
#[fn_builder]
pub fn alter_html(&mut self, html: Markup) -> &mut Self {
self.html.markup = html;
self
}
#[rustfmt::skip]
#[fn_builder]
pub fn alter_display(&mut self, display: HeadingDisplay) -> &mut Self {
self.display = display;
self.classes.alter_value(
ClassesOp::SetDefault,
match &self.display() {
HeadingDisplay::XxLarge => "display-2",
HeadingDisplay::Large => "display-3",
HeadingDisplay::Medium => "display-4",
HeadingDisplay::Small => "display-5",
HeadingDisplay::XxSmall => "display-6",
HeadingDisplay::Normal => "",
HeadingDisplay::Subtitle => "",
},
);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Paragraph GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn heading_type(&self) -> &HeadingType {
&self.heading_type
}
pub fn html(&self) -> &Markup {
&self.html.markup
}
pub fn display(&self) -> &HeadingDisplay {
&self.display
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,84 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_HTML);
#[rustfmt::skip]
#[derive(Default)]
pub struct Html {
weight : isize,
renderable: Renderable,
html : HtmlMarkup,
template : String,
}
impl ComponentTrait for Html {
fn new() -> Self {
Html::default()
}
fn handle(&self) -> Handle {
COMPONENT_HTML
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
html! { (*self.html()) }
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Html {
pub fn with(html: Markup) -> Self {
Html::new().with_html(html)
}
// Html BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_html(&mut self, html: Markup) -> &mut Self {
self.html.markup = html;
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Html GETTERS.
pub fn html(&self) -> &Markup {
&self.html.markup
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,94 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_ICON);
#[rustfmt::skip]
#[derive(Default)]
pub struct Icon {
weight : isize,
renderable: Renderable,
icon_name : String,
classes : Classes,
}
impl ComponentTrait for Icon {
fn new() -> Self {
Icon::default().with_classes(ClassesOp::SetDefault, "bi-question-circle-fill")
}
fn handle(&self) -> Handle {
COMPONENT_ICON
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn before_render(&mut self, rcx: &mut RenderContext) {
rcx.alter(ContextOp::AddStyleSheet(
StyleSheet::located("/minimal/icons/bootstrap-icons.css").with_version("1.8.2"),
));
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
html! { i class=[self.classes().get()] {}; }
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Icon {
pub fn with(icon_name: &str) -> Self {
Icon::new().with_icon_name(icon_name)
}
// Icon BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &mut Self {
self.renderable.check = check;
self
}
#[fn_builder]
pub fn alter_icon_name(&mut self, name: &str) -> &mut Self {
self.icon_name = name.to_owned();
self.alter_classes(
ClassesOp::SetDefault,
concat_string!("bi-", self.icon_name).as_str(),
);
self
}
#[fn_builder]
pub fn alter_classes(&mut self, op: ClassesOp, classes: &str) -> &mut Self {
self.classes.alter_value(op, classes);
self
}
// Icon GETTERS.
pub fn icon_name(&self) -> &str {
self.icon_name.as_str()
}
pub fn classes(&self) -> &Classes {
&self.classes
}
}

View file

@ -0,0 +1,111 @@
use pagetop::prelude::*;
pub_handle!(COMPONENT_IMAGE);
#[rustfmt::skip]
#[derive(Default)]
pub struct Image {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
source : AttributeValue,
template : String,
}
impl ComponentTrait for Image {
fn new() -> Self {
Image::default().with_classes(ClassesOp::SetDefault, "img-fluid")
}
fn handle(&self) -> Handle {
COMPONENT_IMAGE
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, _: &mut RenderContext) -> Markup {
html! {
img
src=[self.source().get()]
id=[self.id().get()]
class=[self.classes().get()];
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Image {
pub fn with(source: &str) -> Self {
Image::new().with_source(source)
}
// Image BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &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
}
#[fn_builder]
pub fn alter_source(&mut self, source: &str) -> &mut Self {
self.source.alter_value(source);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Image GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn source(&self) -> &AttributeValue {
&self.source
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -0,0 +1,149 @@
use pagetop::prelude::*;
use crate::component::Html;
pub_handle!(COMPONENT_PARAGRAPH);
#[derive(Default)]
pub enum ParagraphDisplay {
#[default]
Normal,
XxLarge,
Large,
Medium,
Small,
XxSmall,
}
#[rustfmt::skip]
#[derive(Default)]
pub struct Paragraph {
weight : isize,
renderable: Renderable,
id : IdentifierValue,
classes : Classes,
components: ComponentsBundle,
display : ParagraphDisplay,
template : String,
}
impl ComponentTrait for Paragraph {
fn new() -> Self {
Paragraph::default()
}
fn handle(&self) -> Handle {
COMPONENT_PARAGRAPH
}
fn weight(&self) -> isize {
self.weight
}
fn is_renderable(&self, rcx: &RenderContext) -> bool {
(self.renderable.check)(rcx)
}
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
html! {
p
id=[self.id().get()]
class=[self.classes().get()]
{
(self.components().render(rcx))
}
}
}
fn as_ref_any(&self) -> &dyn AnyComponent {
self
}
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
self
}
}
impl Paragraph {
pub fn with(html: Markup) -> Self {
Paragraph::new().with_component(Html::with(html))
}
// Paragraph BUILDER.
#[fn_builder]
pub fn alter_weight(&mut self, weight: isize) -> &mut Self {
self.weight = weight;
self
}
#[fn_builder]
pub fn alter_renderable(&mut self, check: IsRenderable) -> &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
}
#[fn_builder]
pub fn alter_component(&mut self, component: impl ComponentTrait) -> &mut Self {
self.components.add(component);
self
}
#[rustfmt::skip]
#[fn_builder]
pub fn alter_display(&mut self, display: ParagraphDisplay) -> &mut Self {
self.display = display;
self.classes.alter_value(
ClassesOp::SetDefault,
match &self.display() {
ParagraphDisplay::XxLarge => "fs-2",
ParagraphDisplay::Large => "fs-3",
ParagraphDisplay::Medium => "fs-4",
ParagraphDisplay::Small => "fs-5",
ParagraphDisplay::XxSmall => "fs-6",
ParagraphDisplay::Normal => "",
},
);
self
}
#[fn_builder]
pub fn alter_template(&mut self, template: &str) -> &mut Self {
self.template = template.to_owned();
self
}
// Paragraph GETTERS.
pub fn id(&self) -> &IdentifierValue {
&self.id
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn components(&self) -> &ComponentsBundle {
&self.components
}
pub fn display(&self) -> &ParagraphDisplay {
&self.display
}
pub fn template(&self) -> &str {
self.template.as_str()
}
}

View file

@ -1,17 +1,20 @@
use pagetop::prelude::*;
pub_handle!(THEME_MINIMAL);
pub mod component;
pub mod module;
pub_handle!(MODULE_MINIMAL);
include!(concat!(env!("OUT_DIR"), "/minimal.rs"));
pub struct Minimal;
impl ModuleTrait for Minimal {
fn handle(&self) -> Handle {
THEME_MINIMAL
MODULE_MINIMAL
}
fn theme(&self) -> Option<ThemeStaticRef> {
Some(&Minimal)
fn configure_service(&self, cfg: &mut server::web::ServiceConfig) {
serve_static_files!(cfg, "/minimal", bundle_minimal);
}
}
impl ThemeTrait for Minimal {}

View file

@ -0,0 +1 @@
pub mod menu;

View file

@ -0,0 +1,21 @@
use pagetop::prelude::*;
pub_handle!(MODULE_MENU);
pub_locale!("src/module/menu/locales");
pub struct Menu;
impl ModuleTrait for Menu {
fn handle(&self) -> Handle {
MODULE_MENU
}
fn name(&self) -> String {
l("module_name")
}
fn description(&self) -> Option<String> {
Some(l("module_description"))
}
}

View file

@ -0,0 +1,2 @@
module_name = Menu
module_description = ...

View file

@ -0,0 +1,2 @@
module_name = Menú
module_description = ...

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.