♻️ Major code restructuring
This commit is contained in:
parent
a96e203bb3
commit
fa66d628a0
221 changed files with 228 additions and 315 deletions
3
src/base/action.rs
Normal file
3
src/base/action.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
pub mod component;
|
||||
|
||||
pub mod page;
|
||||
9
src/base/action/component.rs
Normal file
9
src/base/action/component.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
pub type FnActionComponent<C> = fn(component: &mut C, cx: &mut Context);
|
||||
|
||||
mod before_prepare_component;
|
||||
pub use before_prepare_component::*;
|
||||
|
||||
mod after_prepare_component;
|
||||
pub use after_prepare_component::*;
|
||||
55
src/base/action/component/after_prepare_component.rs
Normal file
55
src/base/action/component/after_prepare_component.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
use super::FnActionComponent;
|
||||
|
||||
#[derive(BaseHandle)]
|
||||
pub struct AfterPrepareComponent<C: ComponentTrait> {
|
||||
f: FnActionComponent<C>,
|
||||
referer_handle: Option<Handle>,
|
||||
referer_id: OptionId,
|
||||
weight: Weight,
|
||||
}
|
||||
|
||||
impl<C: ComponentTrait> ActionTrait for AfterPrepareComponent<C> {
|
||||
fn referer_handle(&self) -> Option<Handle> {
|
||||
self.referer_handle
|
||||
}
|
||||
|
||||
fn referer_id(&self) -> Option<String> {
|
||||
self.referer_id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ComponentTrait> AfterPrepareComponent<C> {
|
||||
pub fn new(f: FnActionComponent<C>) -> Self {
|
||||
AfterPrepareComponent {
|
||||
f,
|
||||
referer_handle: Some(C::static_handle()),
|
||||
referer_id: OptionId::default(),
|
||||
weight: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn filter_by_referer_id(mut self, id: impl Into<String>) -> Self {
|
||||
self.referer_id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_weight(mut self, value: Weight) -> Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch(component: &mut C, cx: &mut Context, referer_id: Option<String>) {
|
||||
dispatch_actions(
|
||||
(Self::static_handle(), Some(component.handle()), referer_id),
|
||||
|action| (action_ref::<AfterPrepareComponent<C>>(&**action).f)(component, cx),
|
||||
);
|
||||
}
|
||||
}
|
||||
55
src/base/action/component/before_prepare_component.rs
Normal file
55
src/base/action/component/before_prepare_component.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
use super::FnActionComponent;
|
||||
|
||||
#[derive(BaseHandle)]
|
||||
pub struct BeforePrepareComponent<C: ComponentTrait> {
|
||||
f: FnActionComponent<C>,
|
||||
referer_handle: Option<Handle>,
|
||||
referer_id: OptionId,
|
||||
weight: Weight,
|
||||
}
|
||||
|
||||
impl<C: ComponentTrait> ActionTrait for BeforePrepareComponent<C> {
|
||||
fn referer_handle(&self) -> Option<Handle> {
|
||||
self.referer_handle
|
||||
}
|
||||
|
||||
fn referer_id(&self) -> Option<String> {
|
||||
self.referer_id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ComponentTrait> BeforePrepareComponent<C> {
|
||||
pub fn new(f: FnActionComponent<C>) -> Self {
|
||||
BeforePrepareComponent {
|
||||
f,
|
||||
referer_handle: Some(C::static_handle()),
|
||||
referer_id: OptionId::default(),
|
||||
weight: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn filter_by_referer_id(mut self, id: impl Into<String>) -> Self {
|
||||
self.referer_id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_weight(mut self, value: Weight) -> Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch(component: &mut C, cx: &mut Context, referer_id: Option<String>) {
|
||||
dispatch_actions(
|
||||
(Self::static_handle(), Some(component.handle()), referer_id),
|
||||
|action| (action_ref::<BeforePrepareComponent<C>>(&**action).f)(component, cx),
|
||||
);
|
||||
}
|
||||
}
|
||||
9
src/base/action/page.rs
Normal file
9
src/base/action/page.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
pub type FnActionPage = fn(page: &mut Page);
|
||||
|
||||
mod before_prepare_body;
|
||||
pub use before_prepare_body::*;
|
||||
|
||||
mod after_prepare_body;
|
||||
pub use after_prepare_body::*;
|
||||
34
src/base/action/page/after_prepare_body.rs
Normal file
34
src/base/action/page/after_prepare_body.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
use super::FnActionPage;
|
||||
|
||||
#[derive(BaseHandle)]
|
||||
pub struct AfterPrepareBody {
|
||||
f: FnActionPage,
|
||||
weight: Weight,
|
||||
}
|
||||
|
||||
impl ActionTrait for AfterPrepareBody {
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
}
|
||||
|
||||
impl AfterPrepareBody {
|
||||
pub fn new(f: FnActionPage) -> Self {
|
||||
AfterPrepareBody { f, weight: 0 }
|
||||
}
|
||||
|
||||
pub fn with_weight(mut self, value: Weight) -> Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch(page: &mut Page) {
|
||||
dispatch_actions((Self::static_handle(), None, None), |action| {
|
||||
(action_ref::<AfterPrepareBody>(&**action).f)(page)
|
||||
});
|
||||
}
|
||||
}
|
||||
34
src/base/action/page/before_prepare_body.rs
Normal file
34
src/base/action/page/before_prepare_body.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
use super::FnActionPage;
|
||||
|
||||
#[derive(BaseHandle)]
|
||||
pub struct BeforePrepareBody {
|
||||
f: FnActionPage,
|
||||
weight: Weight,
|
||||
}
|
||||
|
||||
impl ActionTrait for BeforePrepareBody {
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
}
|
||||
|
||||
impl BeforePrepareBody {
|
||||
pub fn new(f: FnActionPage) -> Self {
|
||||
BeforePrepareBody { f, weight: 0 }
|
||||
}
|
||||
|
||||
pub fn with_weight(mut self, value: Weight) -> Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch(page: &mut Page) {
|
||||
dispatch_actions((Self::static_handle(), None, None), |action| {
|
||||
(action_ref::<BeforePrepareBody>(&**action).f)(page)
|
||||
});
|
||||
}
|
||||
}
|
||||
202
src/base/component.rs
Normal file
202
src/base/component.rs
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
use crate::core::component::{Context, ContextOp};
|
||||
use crate::html::{JavaScript, StyleSheet};
|
||||
use crate::{SmartDefault, Weight};
|
||||
|
||||
// Context parameters.
|
||||
pub const PARAM_BASE_WEIGHT: &str = "base.weight";
|
||||
pub const PARAM_BASE_INCLUDE_ICONS: &str = "base.include.icon";
|
||||
pub const PARAM_BASE_INCLUDE_FLEX_ASSETS: &str = "base.include.flex";
|
||||
pub const PARAM_BASE_INCLUDE_MENU_ASSETS: &str = "base.include.menu";
|
||||
|
||||
pub(crate) fn add_base_assets(cx: &mut Context) {
|
||||
let weight = cx.get_param::<Weight>(PARAM_BASE_WEIGHT).unwrap_or(-90);
|
||||
|
||||
cx.alter(ContextOp::AddStyleSheet(
|
||||
StyleSheet::at("/base/css/root.css")
|
||||
.with_version("0.0.1")
|
||||
.with_weight(weight),
|
||||
));
|
||||
if let Some(true) = cx.get_param::<bool>(PARAM_BASE_INCLUDE_ICONS) {
|
||||
cx.alter(ContextOp::AddStyleSheet(
|
||||
StyleSheet::at("/base/css/icons.min.css")
|
||||
.with_version("1.11.1")
|
||||
.with_weight(weight),
|
||||
));
|
||||
}
|
||||
if let Some(true) = cx.get_param::<bool>(PARAM_BASE_INCLUDE_FLEX_ASSETS) {
|
||||
cx.alter(ContextOp::AddStyleSheet(
|
||||
StyleSheet::at("/base/css/flex.css")
|
||||
.with_version("0.0.1")
|
||||
.with_weight(weight),
|
||||
));
|
||||
}
|
||||
if let Some(true) = cx.get_param::<bool>(PARAM_BASE_INCLUDE_MENU_ASSETS) {
|
||||
cx.alter(ContextOp::AddStyleSheet(
|
||||
StyleSheet::at("/base/css/menu.css")
|
||||
.with_version("0.0.1")
|
||||
.with_weight(weight),
|
||||
))
|
||||
.alter(ContextOp::AddJavaScript(
|
||||
JavaScript::at("/base/js/menu.js")
|
||||
.with_version("0.0.1")
|
||||
.with_weight(weight),
|
||||
));
|
||||
}
|
||||
cx.alter(ContextOp::AddStyleSheet(
|
||||
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),
|
||||
));
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
pub enum BreakPoint {
|
||||
#[default]
|
||||
None, /* Does not apply. Rest initially assume 1 pixel = 0.0625em */
|
||||
SM, /* PageTop default applies to <= 568px - @media screen and (max-width: 35.5em) */
|
||||
MD, /* PageTop default applies to <= 768px - @media screen and (max-width: 48em) */
|
||||
LG, /* PageTop default applies to <= 992px - @media screen and (max-width: 62em) */
|
||||
XL, /* PageTop default applies to <= 1280px - @media screen and (max-width: 80em) */
|
||||
X2L, /* PageTop default applies to <= 1440px - @media screen and (max-width: 90em) */
|
||||
X3L, /* PageTop default applies to <= 1920px - @media screen and (max-width: 120em) */
|
||||
X2K, /* PageTop default applies to <= 2560px - @media screen and (max-width: 160em) */
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for BreakPoint {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
BreakPoint::None => "pt-bp__none",
|
||||
BreakPoint::SM => "pt-bp__sm",
|
||||
BreakPoint::MD => "pt-bp__md",
|
||||
BreakPoint::LG => "pt-bp__lg",
|
||||
BreakPoint::XL => "pt-bp__xl",
|
||||
BreakPoint::X2L => "pt-bp__x2l",
|
||||
BreakPoint::X3L => "pt-bp__x3l",
|
||||
BreakPoint::X2K => "pt-bp__x2k",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ButtonStyle {
|
||||
#[default]
|
||||
Default,
|
||||
Info,
|
||||
Success,
|
||||
Warning,
|
||||
Danger,
|
||||
Light,
|
||||
Dark,
|
||||
Link,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for ButtonStyle {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
ButtonStyle::Default => "pt-button__default",
|
||||
ButtonStyle::Info => "pt-button__info",
|
||||
ButtonStyle::Success => "pt-button__success",
|
||||
ButtonStyle::Warning => "pt-button__warning",
|
||||
ButtonStyle::Danger => "pt-button__danger",
|
||||
ButtonStyle::Light => "pt-button__light",
|
||||
ButtonStyle::Dark => "pt-button__dark",
|
||||
ButtonStyle::Link => "pt-button__link",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum FontSize {
|
||||
ExtraLarge,
|
||||
XxLarge,
|
||||
XLarge,
|
||||
Large,
|
||||
Medium,
|
||||
#[default]
|
||||
Normal,
|
||||
Small,
|
||||
XSmall,
|
||||
XxSmall,
|
||||
ExtraSmall,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for FontSize {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
FontSize::ExtraLarge => "pt-fs__x3l",
|
||||
FontSize::XxLarge => "pt-fs__x2l",
|
||||
FontSize::XLarge => "pt-fs__xl",
|
||||
FontSize::Large => "pt-fs__l",
|
||||
FontSize::Medium => "pt-fs__m",
|
||||
FontSize::Normal => "",
|
||||
FontSize::Small => "pt-fs__s",
|
||||
FontSize::XSmall => "pt-fs__xs",
|
||||
FontSize::XxSmall => "pt-fs__x2s",
|
||||
FontSize::ExtraSmall => "pt-fs__x3s",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
mod html;
|
||||
pub use html::Html;
|
||||
|
||||
mod translate;
|
||||
pub use translate::Translate;
|
||||
|
||||
mod wrapper;
|
||||
pub use wrapper::{Wrapper, WrapperType};
|
||||
|
||||
pub mod flex;
|
||||
|
||||
mod icon;
|
||||
pub use icon::Icon;
|
||||
|
||||
mod heading;
|
||||
pub use heading::{Heading, HeadingSize, HeadingType};
|
||||
|
||||
mod paragraph;
|
||||
pub use paragraph::Paragraph;
|
||||
|
||||
mod button;
|
||||
pub use button::{Button, ButtonTarget};
|
||||
|
||||
mod image;
|
||||
pub use image::{Image, ImageSize};
|
||||
|
||||
mod block;
|
||||
pub use block::Block;
|
||||
|
||||
mod branding;
|
||||
pub use branding::Branding;
|
||||
|
||||
mod powered_by;
|
||||
pub use powered_by::{PoweredBy, PoweredByLogo};
|
||||
|
||||
mod error403;
|
||||
pub use error403::Error403;
|
||||
|
||||
mod error404;
|
||||
pub use error404::Error404;
|
||||
|
||||
pub mod menu;
|
||||
pub use menu::Menu;
|
||||
|
||||
pub mod form;
|
||||
pub use form::{Form, FormMethod};
|
||||
101
src/base/component/block.rs
Normal file
101
src/base/component/block.rs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Block {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
classes : OptionClasses,
|
||||
title : OptionTranslated,
|
||||
stuff : AnyComponents,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Block {
|
||||
fn new() -> Self {
|
||||
Block::default()
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
||||
self.prepend_classes("pt-block");
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
let block_body = self.components().render(cx);
|
||||
if !block_body.is_empty() {
|
||||
let id = cx.required_id::<Block>(self.id());
|
||||
return PrepareMarkup::With(html! {
|
||||
div id=(id) class=[self.classes().get()] {
|
||||
@if let Some(title) = self.title().using(cx.langid()) {
|
||||
h2 class="pt-block__title" { (title) }
|
||||
}
|
||||
div class="pt-block__body" { (block_body) }
|
||||
}
|
||||
});
|
||||
}
|
||||
PrepareMarkup::None
|
||||
}
|
||||
}
|
||||
|
||||
impl Block {
|
||||
// Block BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_title(&mut self, title: L10n) -> &mut Self {
|
||||
self.title.alter_value(title);
|
||||
self
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn add_component(mut self, component: impl ComponentTrait) -> Self {
|
||||
self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(component)));
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_components(&mut self, op: ArcAnyOp) -> &mut Self {
|
||||
self.stuff.alter_value(op);
|
||||
self
|
||||
}
|
||||
|
||||
// Block GETTERS.
|
||||
|
||||
pub fn title(&self) -> &OptionTranslated {
|
||||
&self.title
|
||||
}
|
||||
|
||||
pub fn components(&self) -> &AnyComponents {
|
||||
&self.stuff
|
||||
}
|
||||
}
|
||||
124
src/base/component/branding.rs
Normal file
124
src/base/component/branding.rs
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, SmartDefault)]
|
||||
pub struct Branding {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
#[default(_code = "config::SETTINGS.app.name.to_owned()")]
|
||||
app_name : String,
|
||||
slogan : OptionTranslated,
|
||||
logo : OptionComponent<Image>,
|
||||
#[default(_code = "|_| \"/\"")]
|
||||
frontpage : FnContextualPath,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Branding {
|
||||
fn new() -> Self {
|
||||
Branding::default()
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
let logo = self.logo().render(cx);
|
||||
let title = L10n::l("site_home").using(cx.langid());
|
||||
PrepareMarkup::With(html! {
|
||||
div id=[self.id()] class="pt-branding" {
|
||||
div class="pt-branding__wrapper" {
|
||||
@if !logo.is_empty() {
|
||||
div class="pt-branding__logo" { (logo) }
|
||||
}
|
||||
div class="pt-branding__text" {
|
||||
div class="pt-branding__name" {
|
||||
a href=(self.frontpage()(cx)) title=[title] rel="home" {
|
||||
(self.app_name())
|
||||
}
|
||||
}
|
||||
@if let Some(slogan) = self.slogan().using(cx.langid()) {
|
||||
div class="pt-branding__slogan" {
|
||||
(slogan)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Branding {
|
||||
// Branding BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_app_name(&mut self, app_name: impl Into<String>) -> &mut Self {
|
||||
self.app_name = app_name.into();
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_slogan(&mut self, slogan: L10n) -> &mut Self {
|
||||
self.slogan.alter_value(slogan);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_logo(&mut self, logo: Option<Image>) -> &mut Self {
|
||||
self.logo.alter_value(logo);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_frontpage(&mut self, frontpage: FnContextualPath) -> &mut Self {
|
||||
self.frontpage = frontpage;
|
||||
self
|
||||
}
|
||||
|
||||
// Branding GETTERS.
|
||||
|
||||
pub fn app_name(&self) -> &String {
|
||||
&self.app_name
|
||||
}
|
||||
|
||||
pub fn slogan(&self) -> &OptionTranslated {
|
||||
&self.slogan
|
||||
}
|
||||
|
||||
pub fn logo(&self) -> &OptionComponent<Image> {
|
||||
&self.logo
|
||||
}
|
||||
|
||||
pub fn frontpage(&self) -> &FnContextualPath {
|
||||
&self.frontpage
|
||||
}
|
||||
}
|
||||
171
src/base/component/button.rs
Normal file
171
src/base/component/button.rs
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ButtonTarget {
|
||||
#[default]
|
||||
Default,
|
||||
Blank,
|
||||
Parent,
|
||||
Top,
|
||||
Context(String),
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Button {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
classes : OptionClasses,
|
||||
style : ButtonStyle,
|
||||
font_size : FontSize,
|
||||
left_icon : OptionComponent<Icon>,
|
||||
right_icon : OptionComponent<Icon>,
|
||||
href : OptionString,
|
||||
html : OptionTranslated,
|
||||
target : ButtonTarget,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Button {
|
||||
fn new() -> Self {
|
||||
Button::default()
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
||||
self.prepend_classes([self.style().to_string(), self.font_size().to_string()].join(" "));
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
let target = match &self.target() {
|
||||
ButtonTarget::Blank => Some("_blank"),
|
||||
ButtonTarget::Parent => Some("_parent"),
|
||||
ButtonTarget::Top => Some("_top"),
|
||||
ButtonTarget::Context(name) => Some(name.as_str()),
|
||||
_ => None,
|
||||
};
|
||||
PrepareMarkup::With(html! {
|
||||
a
|
||||
id=[self.id()]
|
||||
class=[self.classes().get()]
|
||||
href=[self.href().get()]
|
||||
target=[target]
|
||||
{
|
||||
(self.left_icon().render(cx))
|
||||
" " span { (self.html().escaped(cx.langid())) } " "
|
||||
(self.right_icon().render(cx))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Button {
|
||||
pub fn anchor(href: impl Into<String>, html: L10n) -> Self {
|
||||
Button::default().with_href(href).with_html(html)
|
||||
}
|
||||
|
||||
// Button BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_style(&mut self, style: ButtonStyle) -> &mut Self {
|
||||
self.style = style;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_font_size(&mut self, font_size: FontSize) -> &mut Self {
|
||||
self.font_size = font_size;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_left_icon(&mut self, icon: Option<Icon>) -> &mut Self {
|
||||
self.left_icon.alter_value(icon);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_right_icon(&mut self, icon: Option<Icon>) -> &mut Self {
|
||||
self.right_icon.alter_value(icon);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_href(&mut self, href: impl Into<String>) -> &mut Self {
|
||||
self.href.alter_value(href);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_html(&mut self, html: L10n) -> &mut Self {
|
||||
self.html.alter_value(html);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_target(&mut self, target: ButtonTarget) -> &mut Self {
|
||||
self.target = target;
|
||||
self
|
||||
}
|
||||
|
||||
// Button GETTERS.
|
||||
|
||||
pub fn style(&self) -> &ButtonStyle {
|
||||
&self.style
|
||||
}
|
||||
|
||||
pub fn font_size(&self) -> &FontSize {
|
||||
&self.font_size
|
||||
}
|
||||
|
||||
pub fn left_icon(&self) -> &OptionComponent<Icon> {
|
||||
&self.left_icon
|
||||
}
|
||||
|
||||
pub fn right_icon(&self) -> &OptionComponent<Icon> {
|
||||
&self.right_icon
|
||||
}
|
||||
|
||||
pub fn href(&self) -> &OptionString {
|
||||
&self.href
|
||||
}
|
||||
|
||||
pub fn html(&self) -> &OptionTranslated {
|
||||
&self.html
|
||||
}
|
||||
|
||||
pub fn target(&self) -> &ButtonTarget {
|
||||
&self.target
|
||||
}
|
||||
}
|
||||
20
src/base/component/error403.rs
Normal file
20
src/base/component/error403.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
use crate::core::component::{ComponentTrait, Context};
|
||||
use crate::html::{html, PrepareMarkup};
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(BaseHandle)]
|
||||
pub struct Error403;
|
||||
|
||||
impl ComponentTrait for Error403 {
|
||||
fn new() -> Self {
|
||||
Error403
|
||||
}
|
||||
|
||||
fn prepare_component(&self, _cx: &mut Context) -> PrepareMarkup {
|
||||
PrepareMarkup::With(html! {
|
||||
div {
|
||||
h1 { ("FORBIDDEN ACCESS") }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
20
src/base/component/error404.rs
Normal file
20
src/base/component/error404.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
use crate::core::component::{ComponentTrait, Context};
|
||||
use crate::html::{html, PrepareMarkup};
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(BaseHandle)]
|
||||
pub struct Error404;
|
||||
|
||||
impl ComponentTrait for Error404 {
|
||||
fn new() -> Self {
|
||||
Error404
|
||||
}
|
||||
|
||||
fn prepare_component(&self, _cx: &mut Context) -> PrepareMarkup {
|
||||
PrepareMarkup::With(html! {
|
||||
div {
|
||||
h1 { ("RESOURCE NOT FOUND") }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
322
src/base/component/flex.rs
Normal file
322
src/base/component/flex.rs
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
mod container;
|
||||
pub use container::Container;
|
||||
mod item;
|
||||
pub use item::Item;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum Direction {
|
||||
#[default]
|
||||
Default,
|
||||
Row(BreakPoint),
|
||||
RowReverse(BreakPoint),
|
||||
Column(BreakPoint),
|
||||
ColumnReverse(BreakPoint),
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for Direction {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Direction::Default => concat_string!(
|
||||
"pt-flex__container pt-flex__row ", BreakPoint::default().to_string()
|
||||
),
|
||||
Direction::Row(breakpoint) => concat_string!(
|
||||
"pt-flex__container pt-flex__row ", breakpoint.to_string()
|
||||
),
|
||||
Direction::RowReverse(breakpoint) => concat_string!(
|
||||
"pt-flex__container pt-flex__row pt-flex__reverse ", breakpoint.to_string()
|
||||
),
|
||||
Direction::Column(breakpoint) => concat_string!(
|
||||
"pt-flex__container pt-flex__col ", breakpoint.to_string()
|
||||
),
|
||||
Direction::ColumnReverse(breakpoint) => concat_string!(
|
||||
"pt-flex__container pt-flex__col pt-flex__reverse ", breakpoint.to_string()
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum WrapAlign {
|
||||
#[default]
|
||||
Default,
|
||||
NoWrap,
|
||||
Wrap(ContentAlign),
|
||||
WrapReverse(ContentAlign),
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for WrapAlign {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
WrapAlign::Default => "".to_owned(),
|
||||
WrapAlign::NoWrap => "flex-nowrap".to_owned(),
|
||||
WrapAlign::Wrap(a) => concat_string!("pt-flex__wrap ", a.to_string()),
|
||||
WrapAlign::WrapReverse(a) => concat_string!("pt-flex__wrap-reverse ", a.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ContentAlign {
|
||||
#[default]
|
||||
Default,
|
||||
Start,
|
||||
End,
|
||||
Center,
|
||||
Stretch,
|
||||
SpaceBetween,
|
||||
SpaceAround,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for ContentAlign {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
ContentAlign::Default => "",
|
||||
ContentAlign::Start => "pt-flex__align-start",
|
||||
ContentAlign::End => "pt-flex__align-end",
|
||||
ContentAlign::Center => "pt-flex__align-center",
|
||||
ContentAlign::Stretch => "pt-flex__align-stretch",
|
||||
ContentAlign::SpaceBetween => "pt-flex__align-space-between",
|
||||
ContentAlign::SpaceAround => "pt-flex__align-space-around",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ContentJustify {
|
||||
#[default]
|
||||
Default,
|
||||
Start,
|
||||
End,
|
||||
Center,
|
||||
SpaceBetween,
|
||||
SpaceAround,
|
||||
SpaceEvenly,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for ContentJustify {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
ContentJustify::Default => "",
|
||||
ContentJustify::Start => "pt-flex__justify-start",
|
||||
ContentJustify::End => "pt-flex__justify-end",
|
||||
ContentJustify::Center => "pt-flex__justify-center",
|
||||
ContentJustify::SpaceBetween => "pt-flex__justify-space-between",
|
||||
ContentJustify::SpaceAround => "pt-flex__justify-space-around",
|
||||
ContentJustify::SpaceEvenly => "pt-flex__justify-space-evenly",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ItemAlign {
|
||||
#[default]
|
||||
Default,
|
||||
Top,
|
||||
Bottom,
|
||||
Middle,
|
||||
Stretch,
|
||||
Baseline,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for ItemAlign {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
ItemAlign::Default => "",
|
||||
ItemAlign::Top => "pt-flex__item-top",
|
||||
ItemAlign::Bottom => "pt-flex__item-bottom",
|
||||
ItemAlign::Middle => "pt-flex__item-middle",
|
||||
ItemAlign::Stretch => "pt-flex__item-stretch",
|
||||
ItemAlign::Baseline => "pt-flex__item-baseline",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum Gap {
|
||||
#[default]
|
||||
Default,
|
||||
Row(unit::Value),
|
||||
Column(unit::Value),
|
||||
Distinct(unit::Value, unit::Value),
|
||||
Both(unit::Value),
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for Gap {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Gap::Default => "".to_owned(),
|
||||
Gap::Row(r) => concat_string!("row-gap: ", r.to_string(), ";"),
|
||||
Gap::Column(c) => concat_string!("column-gap: ", c.to_string(), ";"),
|
||||
Gap::Distinct(r, c) => concat_string!("gap: ", r.to_string(), " ", c.to_string(), ";"),
|
||||
Gap::Both(v) => concat_string!("gap: ", v.to_string(), ";"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ItemGrow {
|
||||
#[default]
|
||||
Default,
|
||||
Is1,
|
||||
Is2,
|
||||
Is3,
|
||||
Is4,
|
||||
Is5,
|
||||
Is6,
|
||||
Is7,
|
||||
Is8,
|
||||
Is9,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for ItemGrow {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
ItemGrow::Default => "",
|
||||
ItemGrow::Is1 => "pt-flex__grow-1",
|
||||
ItemGrow::Is2 => "pt-flex__grow-2",
|
||||
ItemGrow::Is3 => "pt-flex__grow-3",
|
||||
ItemGrow::Is4 => "pt-flex__grow-4",
|
||||
ItemGrow::Is5 => "pt-flex__grow-5",
|
||||
ItemGrow::Is6 => "pt-flex__grow-6",
|
||||
ItemGrow::Is7 => "pt-flex__grow-7",
|
||||
ItemGrow::Is8 => "pt-flex__grow-8",
|
||||
ItemGrow::Is9 => "pt-flex__grow-9",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ItemShrink {
|
||||
#[default]
|
||||
Default,
|
||||
Is1,
|
||||
Is2,
|
||||
Is3,
|
||||
Is4,
|
||||
Is5,
|
||||
Is6,
|
||||
Is7,
|
||||
Is8,
|
||||
Is9,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for ItemShrink {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
ItemShrink::Default => "",
|
||||
ItemShrink::Is1 => "pt-flex__shrink-1",
|
||||
ItemShrink::Is2 => "pt-flex__shrink-2",
|
||||
ItemShrink::Is3 => "pt-flex__shrink-3",
|
||||
ItemShrink::Is4 => "pt-flex__shrink-4",
|
||||
ItemShrink::Is5 => "pt-flex__shrink-5",
|
||||
ItemShrink::Is6 => "pt-flex__shrink-6",
|
||||
ItemShrink::Is7 => "pt-flex__shrink-7",
|
||||
ItemShrink::Is8 => "pt-flex__shrink-8",
|
||||
ItemShrink::Is9 => "pt-flex__shrink-9",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ItemSize {
|
||||
#[default]
|
||||
Default,
|
||||
Percent10,
|
||||
Percent20,
|
||||
Percent25,
|
||||
Percent33,
|
||||
Percent40,
|
||||
Percent50,
|
||||
Percent60,
|
||||
Percent66,
|
||||
Percent75,
|
||||
Percent80,
|
||||
Percent90,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for ItemSize {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
ItemSize::Default => "",
|
||||
ItemSize::Percent10 => "pt-flex__width-10",
|
||||
ItemSize::Percent20 => "pt-flex__width-20",
|
||||
ItemSize::Percent25 => "pt-flex__width-25",
|
||||
ItemSize::Percent33 => "pt-flex__width-33",
|
||||
ItemSize::Percent40 => "pt-flex__width-40",
|
||||
ItemSize::Percent50 => "pt-flex__width-50",
|
||||
ItemSize::Percent60 => "pt-flex__width-60",
|
||||
ItemSize::Percent66 => "pt-flex__width-66",
|
||||
ItemSize::Percent75 => "pt-flex__width-75",
|
||||
ItemSize::Percent80 => "pt-flex__width-80",
|
||||
ItemSize::Percent90 => "pt-flex__width-90",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ItemOffset {
|
||||
#[default]
|
||||
Default,
|
||||
Offset10,
|
||||
Offset20,
|
||||
Offset25,
|
||||
Offset33,
|
||||
Offset40,
|
||||
Offset50,
|
||||
Offset60,
|
||||
Offset66,
|
||||
Offset75,
|
||||
Offset80,
|
||||
Offset90,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for ItemOffset {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
ItemOffset::Default => "",
|
||||
ItemOffset::Offset10 => "pt-flex__offset-10",
|
||||
ItemOffset::Offset20 => "pt-flex__offset-20",
|
||||
ItemOffset::Offset25 => "pt-flex__offset-25",
|
||||
ItemOffset::Offset33 => "pt-flex__offset-33",
|
||||
ItemOffset::Offset40 => "pt-flex__offset-40",
|
||||
ItemOffset::Offset50 => "pt-flex__offset-50",
|
||||
ItemOffset::Offset60 => "pt-flex__offset-60",
|
||||
ItemOffset::Offset66 => "pt-flex__offset-66",
|
||||
ItemOffset::Offset75 => "pt-flex__offset-75",
|
||||
ItemOffset::Offset80 => "pt-flex__offset-80",
|
||||
ItemOffset::Offset90 => "pt-flex__offset-90",
|
||||
})
|
||||
}
|
||||
}
|
||||
152
src/base/component/flex/container.rs
Normal file
152
src/base/component/flex/container.rs
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Container {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
classes : OptionClasses,
|
||||
items : TypedComponents<flex::Item>,
|
||||
direction : flex::Direction,
|
||||
wrap_align : flex::WrapAlign,
|
||||
content_justify: flex::ContentJustify,
|
||||
items_align : flex::ItemAlign,
|
||||
gap : flex::Gap,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Container {
|
||||
fn new() -> Self {
|
||||
Container::default()
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn setup_before_prepare(&mut self, cx: &mut Context) {
|
||||
self.prepend_classes(
|
||||
[
|
||||
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()),
|
||||
};
|
||||
|
||||
PrepareMarkup::With(html! {
|
||||
div id=[self.id()] class=[self.classes().get()] style=[gap] {
|
||||
(self.items().render(cx))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Container {
|
||||
// Container BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn add_item(mut self, item: flex::Item) -> Self {
|
||||
self.items.alter_value(ArcTypedOp::Add(ArcTypedComponent::new(item)));
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_items(&mut self, op: ArcTypedOp<flex::Item>) -> &mut Self {
|
||||
self.items.alter_value(op);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_direction(&mut self, direction: flex::Direction) -> &mut Self {
|
||||
self.direction = direction;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_wrap_align(&mut self, wrap: flex::WrapAlign) -> &mut Self {
|
||||
self.wrap_align = wrap;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_content_justify(&mut self, justify: flex::ContentJustify) -> &mut Self {
|
||||
self.content_justify = justify;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_items_align(&mut self, align: flex::ItemAlign) -> &mut Self {
|
||||
self.items_align = align;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_gap(&mut self, gap: flex::Gap) -> &mut Self {
|
||||
self.gap = gap;
|
||||
self
|
||||
}
|
||||
|
||||
// Container GETTERS.
|
||||
|
||||
pub fn items(&self) -> &TypedComponents<flex::Item> {
|
||||
&self.items
|
||||
}
|
||||
|
||||
pub fn direction(&self) -> &flex::Direction {
|
||||
&self.direction
|
||||
}
|
||||
|
||||
pub fn wrap_align(&self) -> &flex::WrapAlign {
|
||||
&self.wrap_align
|
||||
}
|
||||
|
||||
pub fn content_justify(&self) -> &flex::ContentJustify {
|
||||
&self.content_justify
|
||||
}
|
||||
|
||||
pub fn items_align(&self) -> &flex::ItemAlign {
|
||||
&self.items_align
|
||||
}
|
||||
|
||||
pub fn gap(&self) -> &flex::Gap {
|
||||
&self.gap
|
||||
}
|
||||
}
|
||||
166
src/base/component/flex/item.rs
Normal file
166
src/base/component/flex/item.rs
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Item {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
classes : OptionClasses,
|
||||
inner_classes: OptionClasses,
|
||||
item_grow : flex::ItemGrow,
|
||||
item_shrink : flex::ItemShrink,
|
||||
item_size : flex::ItemSize,
|
||||
item_offset : flex::ItemOffset,
|
||||
item_align : flex::ItemAlign,
|
||||
stuff : AnyComponents,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Item {
|
||||
fn new() -> Self {
|
||||
Item::default()
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
||||
self.prepend_classes(
|
||||
[
|
||||
"pt-flex__item".to_owned(),
|
||||
self.grow().to_string(),
|
||||
self.shrink().to_string(),
|
||||
self.size().to_string(),
|
||||
self.offset().to_string(),
|
||||
self.align().to_string(),
|
||||
]
|
||||
.join(" "),
|
||||
);
|
||||
self.inner_classes
|
||||
.alter_value(ClassesOp::Prepend, "pt-flex__item-inner");
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
let order = match self.weight() {
|
||||
0 => None,
|
||||
_ => Some(concat_string!("order: ", self.weight().to_string(), ";")),
|
||||
};
|
||||
PrepareMarkup::With(html! {
|
||||
div id=[self.id()] class=[self.classes().get()] style=[order] {
|
||||
div class=[self.inner_classes().get()] {
|
||||
(self.components().render(cx))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Item {
|
||||
// Item BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_inner_classes(&mut self, op: ClassesOp, classes: impl Into<String>) -> &mut Self {
|
||||
self.inner_classes.alter_value(op, classes);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_grow(&mut self, grow: flex::ItemGrow) -> &mut Self {
|
||||
self.item_grow = grow;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_shrink(&mut self, shrink: flex::ItemShrink) -> &mut Self {
|
||||
self.item_shrink = shrink;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_size(&mut self, size: flex::ItemSize) -> &mut Self {
|
||||
self.item_size = size;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_offset(&mut self, offset: flex::ItemOffset) -> &mut Self {
|
||||
self.item_offset = offset;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_align(&mut self, align: flex::ItemAlign) -> &mut Self {
|
||||
self.item_align = align;
|
||||
self
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn add_component(mut self, component: impl ComponentTrait) -> Self {
|
||||
self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(component)));
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_components(&mut self, op: ArcAnyOp) -> &mut Self {
|
||||
self.stuff.alter_value(op);
|
||||
self
|
||||
}
|
||||
|
||||
// Item GETTERS.
|
||||
|
||||
pub fn inner_classes(&self) -> &OptionClasses {
|
||||
&self.inner_classes
|
||||
}
|
||||
|
||||
pub fn grow(&self) -> &flex::ItemGrow {
|
||||
&self.item_grow
|
||||
}
|
||||
|
||||
pub fn shrink(&self) -> &flex::ItemShrink {
|
||||
&self.item_shrink
|
||||
}
|
||||
|
||||
pub fn size(&self) -> &flex::ItemSize {
|
||||
&self.item_size
|
||||
}
|
||||
|
||||
pub fn offset(&self) -> &flex::ItemOffset {
|
||||
&self.item_offset
|
||||
}
|
||||
|
||||
pub fn align(&self) -> &flex::ItemAlign {
|
||||
&self.item_align
|
||||
}
|
||||
|
||||
pub fn components(&self) -> &AnyComponents {
|
||||
&self.stuff
|
||||
}
|
||||
}
|
||||
14
src/base/component/form.rs
Normal file
14
src/base/component/form.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
mod form_main;
|
||||
pub use form_main::{Form, FormMethod};
|
||||
|
||||
mod input;
|
||||
pub use input::{Input, InputType};
|
||||
|
||||
mod hidden;
|
||||
pub use hidden::Hidden;
|
||||
|
||||
mod date;
|
||||
pub use date::Date;
|
||||
|
||||
mod action_button;
|
||||
pub use action_button::{ActionButton, ActionButtonType};
|
||||
199
src/base/component/form/action_button.rs
Normal file
199
src/base/component/form/action_button.rs
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ActionButtonType {
|
||||
#[default]
|
||||
Submit,
|
||||
Reset,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for ActionButtonType {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
ActionButtonType::Submit => "submit",
|
||||
ActionButtonType::Reset => "reset",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct ActionButton {
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
classes : OptionClasses,
|
||||
button_type: ActionButtonType,
|
||||
style : ButtonStyle,
|
||||
font_size : FontSize,
|
||||
left_icon : OptionComponent<Icon>,
|
||||
right_icon : OptionComponent<Icon>,
|
||||
name : OptionString,
|
||||
value : OptionTranslated,
|
||||
autofocus : OptionString,
|
||||
disabled : OptionString,
|
||||
}
|
||||
|
||||
impl ComponentTrait for ActionButton {
|
||||
fn new() -> Self {
|
||||
ActionButton::submit()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
||||
self.prepend_classes([self.style().to_string(), self.font_size().to_string()].join(" "));
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
let id = self.name().get().map(|name| concat_string!("edit-", name));
|
||||
PrepareMarkup::With(html! {
|
||||
button
|
||||
type=(self.button_type().to_string())
|
||||
id=[id]
|
||||
class=[self.classes().get()]
|
||||
name=[self.name().get()]
|
||||
value=[self.value().using(cx.langid())]
|
||||
autofocus=[self.autofocus().get()]
|
||||
disabled=[self.disabled().get()]
|
||||
{
|
||||
(self.left_icon().render(cx))
|
||||
" " (self.value().escaped(cx.langid())) " "
|
||||
(self.right_icon().render(cx))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ActionButton {
|
||||
pub fn submit() -> Self {
|
||||
ActionButton {
|
||||
button_type: ActionButtonType::Submit,
|
||||
style: ButtonStyle::Default,
|
||||
value: OptionTranslated::new(L10n::l("button_submit")),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset() -> Self {
|
||||
ActionButton {
|
||||
button_type: ActionButtonType::Reset,
|
||||
style: ButtonStyle::Info,
|
||||
value: OptionTranslated::new(L10n::l("button_reset")),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
// Button BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_style(&mut self, style: ButtonStyle) -> &mut Self {
|
||||
self.style = style;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_font_size(&mut self, font_size: FontSize) -> &mut Self {
|
||||
self.font_size = font_size;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_left_icon(&mut self, icon: Option<Icon>) -> &mut Self {
|
||||
self.left_icon.alter_value(icon);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_right_icon(&mut self, icon: Option<Icon>) -> &mut Self {
|
||||
self.right_icon.alter_value(icon);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_name(&mut self, name: &str) -> &mut Self {
|
||||
self.name.alter_value(name);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_value(&mut self, value: L10n) -> &mut Self {
|
||||
self.value.alter_value(value);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
|
||||
self.autofocus.alter_value(match toggle {
|
||||
true => "autofocus",
|
||||
false => "",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
|
||||
self.disabled.alter_value(match toggle {
|
||||
true => "disabled",
|
||||
false => "",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
// Button GETTERS.
|
||||
|
||||
pub fn button_type(&self) -> &ActionButtonType {
|
||||
&self.button_type
|
||||
}
|
||||
|
||||
pub fn style(&self) -> &ButtonStyle {
|
||||
&self.style
|
||||
}
|
||||
|
||||
pub fn font_size(&self) -> &FontSize {
|
||||
&self.font_size
|
||||
}
|
||||
|
||||
pub fn left_icon(&self) -> &OptionComponent<Icon> {
|
||||
&self.left_icon
|
||||
}
|
||||
|
||||
pub fn right_icon(&self) -> &OptionComponent<Icon> {
|
||||
&self.right_icon
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &OptionString {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn value(&self) -> &OptionTranslated {
|
||||
&self.value
|
||||
}
|
||||
|
||||
pub fn autofocus(&self) -> &OptionString {
|
||||
&self.autofocus
|
||||
}
|
||||
|
||||
pub fn disabled(&self) -> &OptionString {
|
||||
&self.disabled
|
||||
}
|
||||
}
|
||||
200
src/base/component/form/date.rs
Normal file
200
src/base/component/form/date.rs
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Date {
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
classes : OptionClasses,
|
||||
name : OptionString,
|
||||
value : OptionString,
|
||||
label : OptionString,
|
||||
placeholder : OptionString,
|
||||
autofocus : OptionString,
|
||||
autocomplete: OptionString,
|
||||
disabled : OptionString,
|
||||
readonly : OptionString,
|
||||
required : OptionString,
|
||||
help_text : OptionString,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Date {
|
||||
fn new() -> Self {
|
||||
Date::default().with_classes(ClassesOp::Add, "form-item form-type-date")
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, _cx: &mut Context) -> PrepareMarkup {
|
||||
let id = self.name().get().map(|name| concat_string!("edit-", name));
|
||||
PrepareMarkup::With(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) }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Date {
|
||||
// Date BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_name(&mut self, name: &str) -> &mut Self {
|
||||
self.name.alter_value(name);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_value(&mut self, value: &str) -> &mut Self {
|
||||
self.value.alter_value(value);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_label(&mut self, label: &str) -> &mut Self {
|
||||
self.label.alter_value(label);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_placeholder(&mut self, placeholder: &str) -> &mut Self {
|
||||
self.placeholder.alter_value(placeholder);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
|
||||
self.autofocus.alter_value(match toggle {
|
||||
true => "autofocus",
|
||||
false => "",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_autocomplete(&mut self, toggle: bool) -> &mut Self {
|
||||
self.autocomplete.alter_value(match toggle {
|
||||
true => "",
|
||||
false => "off",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
|
||||
self.disabled.alter_value(match toggle {
|
||||
true => "disabled",
|
||||
false => "",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_readonly(&mut self, toggle: bool) -> &mut Self {
|
||||
self.readonly.alter_value(match toggle {
|
||||
true => "readonly",
|
||||
false => "",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_required(&mut self, toggle: bool) -> &mut Self {
|
||||
self.required.alter_value(match toggle {
|
||||
true => "required",
|
||||
false => "",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_help_text(&mut self, help_text: &str) -> &mut Self {
|
||||
self.help_text.alter_value(help_text);
|
||||
self
|
||||
}
|
||||
|
||||
// Date GETTERS.
|
||||
|
||||
pub fn name(&self) -> &OptionString {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn value(&self) -> &OptionString {
|
||||
&self.value
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &OptionString {
|
||||
&self.label
|
||||
}
|
||||
|
||||
pub fn placeholder(&self) -> &OptionString {
|
||||
&self.placeholder
|
||||
}
|
||||
|
||||
pub fn autofocus(&self) -> &OptionString {
|
||||
&self.autofocus
|
||||
}
|
||||
|
||||
pub fn autocomplete(&self) -> &OptionString {
|
||||
&self.autocomplete
|
||||
}
|
||||
|
||||
pub fn disabled(&self) -> &OptionString {
|
||||
&self.disabled
|
||||
}
|
||||
|
||||
pub fn readonly(&self) -> &OptionString {
|
||||
&self.readonly
|
||||
}
|
||||
|
||||
pub fn required(&self) -> &OptionString {
|
||||
&self.required
|
||||
}
|
||||
|
||||
pub fn help_text(&self) -> &OptionString {
|
||||
&self.help_text
|
||||
}
|
||||
}
|
||||
130
src/base/component/form/form_main.rs
Normal file
130
src/base/component/form/form_main.rs
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum FormMethod {
|
||||
#[default]
|
||||
Post,
|
||||
Get,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Form {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
classes : OptionClasses,
|
||||
action : OptionString,
|
||||
charset : OptionString,
|
||||
method : FormMethod,
|
||||
stuff : AnyComponents,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Form {
|
||||
fn new() -> Self {
|
||||
Form::default()
|
||||
.with_classes(ClassesOp::Add, "form")
|
||||
.with_charset("UTF-8")
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
let method = match self.method() {
|
||||
FormMethod::Post => Some("post".to_owned()),
|
||||
FormMethod::Get => None,
|
||||
};
|
||||
PrepareMarkup::With(html! {
|
||||
form
|
||||
id=[self.id()]
|
||||
class=[self.classes().get()]
|
||||
action=[self.action().get()]
|
||||
method=[method]
|
||||
accept-charset=[self.charset().get()]
|
||||
{
|
||||
div { (self.elements().render(cx)) }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Form {
|
||||
// Form BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_action(&mut self, action: &str) -> &mut Self {
|
||||
self.action.alter_value(action);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_charset(&mut self, charset: &str) -> &mut Self {
|
||||
self.charset.alter_value(charset);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_method(&mut self, method: FormMethod) -> &mut Self {
|
||||
self.method = method;
|
||||
self
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn with_element(mut self, element: impl ComponentTrait) -> Self {
|
||||
self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(element)));
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_elements(&mut self, op: ArcAnyOp) -> &mut Self {
|
||||
self.stuff.alter_value(op);
|
||||
self
|
||||
}
|
||||
|
||||
// Form GETTERS.
|
||||
|
||||
pub fn action(&self) -> &OptionString {
|
||||
&self.action
|
||||
}
|
||||
|
||||
pub fn charset(&self) -> &OptionString {
|
||||
&self.charset
|
||||
}
|
||||
|
||||
pub fn method(&self) -> &FormMethod {
|
||||
&self.method
|
||||
}
|
||||
|
||||
pub fn elements(&self) -> &AnyComponents {
|
||||
&self.stuff
|
||||
}
|
||||
}
|
||||
63
src/base/component/form/hidden.rs
Normal file
63
src/base/component/form/hidden.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, SmartDefault)]
|
||||
pub struct Hidden {
|
||||
weight: Weight,
|
||||
name : OptionName,
|
||||
value : OptionString,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Hidden {
|
||||
fn new() -> Self {
|
||||
Hidden::default()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn prepare_component(&self, _cx: &mut Context) -> PrepareMarkup {
|
||||
let id = self.name().get().map(|name| concat_string!("value-", name));
|
||||
PrepareMarkup::With(html! {
|
||||
input type="hidden" id=[id] name=[self.name().get()] value=[self.value().get()] {}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Hidden {
|
||||
pub fn set(name: &str, value: &str) -> Self {
|
||||
Hidden::default().with_name(name).with_value(value)
|
||||
}
|
||||
|
||||
// Hidden BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_name(&mut self, name: &str) -> &mut Self {
|
||||
self.name.alter_value(name);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_value(&mut self, value: &str) -> &mut Self {
|
||||
self.value.alter_value(value);
|
||||
self
|
||||
}
|
||||
|
||||
// Hidden GETTERS.
|
||||
|
||||
pub fn name(&self) -> &OptionName {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn value(&self) -> &OptionString {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
317
src/base/component/form/input.rs
Normal file
317
src/base/component/form/input.rs
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum InputType {
|
||||
#[default]
|
||||
Textfield,
|
||||
Password,
|
||||
Search,
|
||||
Email,
|
||||
Telephone,
|
||||
Url,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Input {
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
classes : OptionClasses,
|
||||
input_type : InputType,
|
||||
name : OptionName,
|
||||
value : OptionString,
|
||||
label : OptionTranslated,
|
||||
size : Option<u16>,
|
||||
minlength : Option<u16>,
|
||||
maxlength : Option<u16>,
|
||||
placeholder : OptionString,
|
||||
autofocus : OptionString,
|
||||
autocomplete: OptionString,
|
||||
disabled : OptionString,
|
||||
readonly : OptionString,
|
||||
required : OptionString,
|
||||
help_text : OptionTranslated,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Input {
|
||||
fn new() -> Self {
|
||||
Input::default()
|
||||
.with_classes(ClassesOp::Add, "form-item form-type-textfield")
|
||||
.with_size(Some(60))
|
||||
.with_maxlength(Some(128))
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
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));
|
||||
PrepareMarkup::With(html! {
|
||||
div class=[self.classes().get()] {
|
||||
@if let Some(label) = self.label().using(cx.langid()) {
|
||||
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(description) = self.help_text().using(cx.langid()) {
|
||||
div class="form-text" { (description) }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Input {
|
||||
pub fn textfield() -> Self {
|
||||
Input::default()
|
||||
}
|
||||
|
||||
pub fn password() -> Self {
|
||||
let mut input = Input::default().with_classes(
|
||||
ClassesOp::Replace("form-type-textfield".to_owned()),
|
||||
"form-type-password",
|
||||
);
|
||||
input.input_type = InputType::Password;
|
||||
input
|
||||
}
|
||||
|
||||
pub fn search() -> Self {
|
||||
let mut input = Input::default().with_classes(
|
||||
ClassesOp::Replace("form-type-textfield".to_owned()),
|
||||
"form-type-search",
|
||||
);
|
||||
input.input_type = InputType::Search;
|
||||
input
|
||||
}
|
||||
|
||||
pub fn email() -> Self {
|
||||
let mut input = Input::default().with_classes(
|
||||
ClassesOp::Replace("form-type-textfield".to_owned()),
|
||||
"form-type-email",
|
||||
);
|
||||
input.input_type = InputType::Email;
|
||||
input
|
||||
}
|
||||
|
||||
pub fn telephone() -> Self {
|
||||
let mut input = Input::default().with_classes(
|
||||
ClassesOp::Replace("form-type-textfield".to_owned()),
|
||||
"form-type-telephone",
|
||||
);
|
||||
input.input_type = InputType::Telephone;
|
||||
input
|
||||
}
|
||||
|
||||
pub fn url() -> Self {
|
||||
let mut input = Input::default().with_classes(
|
||||
ClassesOp::Replace("form-type-textfield".to_owned()),
|
||||
"form-type-url",
|
||||
);
|
||||
input.input_type = InputType::Url;
|
||||
input
|
||||
}
|
||||
|
||||
// Input BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_name(&mut self, name: &str) -> &mut Self {
|
||||
if let Some(previous) = self.name.get() {
|
||||
self.remove_classes(concat_string!("form-item-", previous));
|
||||
}
|
||||
self.add_classes(concat_string!("form-item-", name));
|
||||
self.name.alter_value(name);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_value(&mut self, value: &str) -> &mut Self {
|
||||
self.value.alter_value(value);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_label(&mut self, label: L10n) -> &mut Self {
|
||||
self.label.alter_value(label);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_size(&mut self, size: Option<u16>) -> &mut Self {
|
||||
self.size = size;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_minlength(&mut self, minlength: Option<u16>) -> &mut Self {
|
||||
self.minlength = minlength;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_maxlength(&mut self, maxlength: Option<u16>) -> &mut Self {
|
||||
self.maxlength = maxlength;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_placeholder(&mut self, placeholder: &str) -> &mut Self {
|
||||
self.placeholder.alter_value(placeholder);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_autofocus(&mut self, toggle: bool) -> &mut Self {
|
||||
self.autofocus.alter_value(match toggle {
|
||||
true => "autofocus",
|
||||
false => "",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_autocomplete(&mut self, toggle: bool) -> &mut Self {
|
||||
self.autocomplete.alter_value(match toggle {
|
||||
true => "",
|
||||
false => "off",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_disabled(&mut self, toggle: bool) -> &mut Self {
|
||||
self.disabled.alter_value(match toggle {
|
||||
true => "disabled",
|
||||
false => "",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_readonly(&mut self, toggle: bool) -> &mut Self {
|
||||
self.readonly.alter_value(match toggle {
|
||||
true => "readonly",
|
||||
false => "",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_required(&mut self, toggle: bool) -> &mut Self {
|
||||
self.required.alter_value(match toggle {
|
||||
true => "required",
|
||||
false => "",
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_help_text(&mut self, help_text: L10n) -> &mut Self {
|
||||
self.help_text.alter_value(help_text);
|
||||
self
|
||||
}
|
||||
|
||||
// Input GETTERS.
|
||||
|
||||
pub fn input_type(&self) -> &InputType {
|
||||
&self.input_type
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &OptionName {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn value(&self) -> &OptionString {
|
||||
&self.value
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &OptionTranslated {
|
||||
&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) -> &OptionString {
|
||||
&self.placeholder
|
||||
}
|
||||
|
||||
pub fn autofocus(&self) -> &OptionString {
|
||||
&self.autofocus
|
||||
}
|
||||
|
||||
pub fn autocomplete(&self) -> &OptionString {
|
||||
&self.autocomplete
|
||||
}
|
||||
|
||||
pub fn disabled(&self) -> &OptionString {
|
||||
&self.disabled
|
||||
}
|
||||
|
||||
pub fn readonly(&self) -> &OptionString {
|
||||
&self.readonly
|
||||
}
|
||||
|
||||
pub fn required(&self) -> &OptionString {
|
||||
&self.required
|
||||
}
|
||||
|
||||
pub fn help_text(&self) -> &OptionTranslated {
|
||||
&self.help_text
|
||||
}
|
||||
}
|
||||
178
src/base/component/heading.rs
Normal file
178
src/base/component/heading.rs
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum HeadingType {
|
||||
#[default]
|
||||
H1,
|
||||
H2,
|
||||
H3,
|
||||
H4,
|
||||
H5,
|
||||
H6,
|
||||
}
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum HeadingSize {
|
||||
ExtraLarge,
|
||||
XxLarge,
|
||||
XLarge,
|
||||
Large,
|
||||
Medium,
|
||||
#[default]
|
||||
Normal,
|
||||
Subtitle,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl ToString for HeadingSize {
|
||||
fn to_string(&self) -> String {
|
||||
String::from(match self {
|
||||
HeadingSize::ExtraLarge => "pt-heading__title-x3l",
|
||||
HeadingSize::XxLarge => "pt-heading__title-x2l",
|
||||
HeadingSize::XLarge => "pt-heading__title-xl",
|
||||
HeadingSize::Large => "pt-heading__title-l",
|
||||
HeadingSize::Medium => "pt-heading__title-m",
|
||||
HeadingSize::Normal => "",
|
||||
HeadingSize::Subtitle => "pt-heading__subtitle",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Heading {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
classes : OptionClasses,
|
||||
heading_type: HeadingType,
|
||||
size : HeadingSize,
|
||||
text : OptionTranslated,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Heading {
|
||||
fn new() -> Self {
|
||||
Heading::default()
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
||||
self.add_classes(self.size().to_string());
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
let id = self.id();
|
||||
let classes = self.classes().get();
|
||||
let text = self.text().escaped(cx.langid());
|
||||
PrepareMarkup::With(html! { @match &self.heading_type() {
|
||||
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) },
|
||||
}})
|
||||
}
|
||||
}
|
||||
|
||||
impl Heading {
|
||||
pub fn h1(text: L10n) -> Self {
|
||||
Heading::default()
|
||||
.with_heading_type(HeadingType::H1)
|
||||
.with_text(text)
|
||||
}
|
||||
|
||||
pub fn h2(text: L10n) -> Self {
|
||||
Heading::default()
|
||||
.with_heading_type(HeadingType::H2)
|
||||
.with_text(text)
|
||||
}
|
||||
|
||||
pub fn h3(text: L10n) -> Self {
|
||||
Heading::default()
|
||||
.with_heading_type(HeadingType::H3)
|
||||
.with_text(text)
|
||||
}
|
||||
|
||||
pub fn h4(text: L10n) -> Self {
|
||||
Heading::default()
|
||||
.with_heading_type(HeadingType::H4)
|
||||
.with_text(text)
|
||||
}
|
||||
|
||||
pub fn h5(text: L10n) -> Self {
|
||||
Heading::default()
|
||||
.with_heading_type(HeadingType::H5)
|
||||
.with_text(text)
|
||||
}
|
||||
|
||||
pub fn h6(text: L10n) -> Self {
|
||||
Heading::default()
|
||||
.with_heading_type(HeadingType::H6)
|
||||
.with_text(text)
|
||||
}
|
||||
|
||||
// Heading BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_heading_type(&mut self, heading_type: HeadingType) -> &mut Self {
|
||||
self.heading_type = heading_type;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_size(&mut self, size: HeadingSize) -> &mut Self {
|
||||
self.size = size;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_text(&mut self, text: L10n) -> &mut Self {
|
||||
self.text.alter_value(text);
|
||||
self
|
||||
}
|
||||
|
||||
// Paragraph GETTERS.
|
||||
|
||||
pub fn heading_type(&self) -> &HeadingType {
|
||||
&self.heading_type
|
||||
}
|
||||
|
||||
pub fn size(&self) -> &HeadingSize {
|
||||
&self.size
|
||||
}
|
||||
|
||||
pub fn text(&self) -> &OptionTranslated {
|
||||
&self.text
|
||||
}
|
||||
}
|
||||
35
src/base/component/html.rs
Normal file
35
src/base/component/html.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(BaseHandle, SmartDefault)]
|
||||
pub struct Html(Markup);
|
||||
|
||||
impl ComponentTrait for Html {
|
||||
fn new() -> Self {
|
||||
Html::default()
|
||||
}
|
||||
|
||||
fn prepare_component(&self, _cx: &mut Context) -> PrepareMarkup {
|
||||
PrepareMarkup::With(html! { (self.html()) })
|
||||
}
|
||||
}
|
||||
|
||||
impl Html {
|
||||
pub fn with(html: Markup) -> Self {
|
||||
Html(html)
|
||||
}
|
||||
|
||||
// Html BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_html(&mut self, html: Markup) -> &mut Self {
|
||||
self.0 = html;
|
||||
self
|
||||
}
|
||||
|
||||
// Html GETTERS.
|
||||
|
||||
pub fn html(&self) -> &Markup {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
85
src/base/component/icon.rs
Normal file
85
src/base/component/icon.rs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Icon {
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
classes : OptionClasses,
|
||||
icon_name : OptionString,
|
||||
font_size : FontSize,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Icon {
|
||||
fn new() -> Self {
|
||||
Icon::default()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn setup_before_prepare(&mut self, cx: &mut Context) {
|
||||
if let Some(icon_name) = self.icon_name().get() {
|
||||
self.prepend_classes(
|
||||
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()] {} }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Icon {
|
||||
pub fn with(icon_name: impl Into<String>) -> Self {
|
||||
Icon::default().with_icon_name(icon_name)
|
||||
}
|
||||
|
||||
// Icon BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_icon_name(&mut self, name: impl Into<String>) -> &mut Self {
|
||||
self.icon_name.alter_value(name);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_font_size(&mut self, font_size: FontSize) -> &mut Self {
|
||||
self.font_size = font_size;
|
||||
self
|
||||
}
|
||||
|
||||
// Icon GETTERS.
|
||||
|
||||
pub fn icon_name(&self) -> &OptionString {
|
||||
&self.icon_name
|
||||
}
|
||||
|
||||
pub fn font_size(&self) -> &FontSize {
|
||||
&self.font_size
|
||||
}
|
||||
}
|
||||
125
src/base/component/image.rs
Normal file
125
src/base/component/image.rs
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
const IMG_FLUID: &str = "pt-img__fluid";
|
||||
const IMG_FIXED: &str = "pt-img__fixed";
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ImageSize {
|
||||
#[default]
|
||||
Auto,
|
||||
Size(u16, u16),
|
||||
Width(u16),
|
||||
Height(u16),
|
||||
Both(u16),
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Image {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
classes : OptionClasses,
|
||||
source : OptionString,
|
||||
size : ImageSize,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Image {
|
||||
fn new() -> Self {
|
||||
Image::default().with_classes(ClassesOp::Add, IMG_FLUID)
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, _cx: &mut Context) -> PrepareMarkup {
|
||||
let (width, height) = match self.size() {
|
||||
ImageSize::Auto => (None, None),
|
||||
ImageSize::Size(width, height) => (Some(width), Some(height)),
|
||||
ImageSize::Width(width) => (Some(width), None),
|
||||
ImageSize::Height(height) => (None, Some(height)),
|
||||
ImageSize::Both(value) => (Some(value), Some(value)),
|
||||
};
|
||||
PrepareMarkup::With(html! {
|
||||
img
|
||||
src=[self.source().get()]
|
||||
id=[self.id()]
|
||||
class=[self.classes().get()]
|
||||
width=[width]
|
||||
height=[height] {}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Image {
|
||||
pub fn with(source: &str) -> Self {
|
||||
Image::default()
|
||||
.with_source(source)
|
||||
.with_classes(ClassesOp::Add, IMG_FLUID)
|
||||
}
|
||||
|
||||
pub fn fixed(source: &str) -> Self {
|
||||
Image::default()
|
||||
.with_source(source)
|
||||
.with_classes(ClassesOp::Add, IMG_FIXED)
|
||||
}
|
||||
|
||||
pub fn pagetop() -> Self {
|
||||
Image::default()
|
||||
.with_source("/base/pagetop-logo.svg")
|
||||
.with_classes(ClassesOp::Add, IMG_FIXED)
|
||||
.with_size(ImageSize::Size(64, 64))
|
||||
}
|
||||
|
||||
// Image BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_source(&mut self, source: &str) -> &mut Self {
|
||||
self.source.alter_value(source);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_size(&mut self, size: ImageSize) -> &mut Self {
|
||||
self.size = size;
|
||||
self
|
||||
}
|
||||
|
||||
// Image GETTERS.
|
||||
|
||||
pub fn source(&self) -> &OptionString {
|
||||
&self.source
|
||||
}
|
||||
|
||||
pub fn size(&self) -> &ImageSize {
|
||||
&self.size
|
||||
}
|
||||
}
|
||||
17
src/base/component/menu.rs
Normal file
17
src/base/component/menu.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
mod menu_main;
|
||||
pub use menu_main::Menu;
|
||||
|
||||
mod item;
|
||||
pub use item::{Item, ItemType};
|
||||
|
||||
mod submenu;
|
||||
pub use submenu::Submenu;
|
||||
|
||||
mod megamenu;
|
||||
pub use megamenu::Megamenu;
|
||||
|
||||
mod group;
|
||||
pub use group::Group;
|
||||
|
||||
mod element;
|
||||
pub use element::{Element, ElementType};
|
||||
87
src/base/component/menu/element.rs
Normal file
87
src/base/component/menu/element.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
use super::Submenu;
|
||||
|
||||
type Content = ArcTypedComponent<Html>;
|
||||
type SubmenuItems = ArcTypedComponent<Submenu>;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ElementType {
|
||||
#[default]
|
||||
Void,
|
||||
Html(Content),
|
||||
Submenu(SubmenuItems),
|
||||
}
|
||||
|
||||
// Element.
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, SmartDefault)]
|
||||
pub struct Element {
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
element_type: ElementType,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Element {
|
||||
fn new() -> Self {
|
||||
Element::default()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
match self.element_type() {
|
||||
ElementType::Void => PrepareMarkup::None,
|
||||
ElementType::Html(content) => PrepareMarkup::With(html! {
|
||||
(content.render(cx))
|
||||
}),
|
||||
ElementType::Submenu(submenu) => PrepareMarkup::With(html! {
|
||||
(submenu.render(cx))
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Element {
|
||||
pub fn html(content: Html) -> Self {
|
||||
Element {
|
||||
element_type: ElementType::Html(Content::new(content)),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn submenu(submenu: Submenu) -> Self {
|
||||
Element {
|
||||
element_type: ElementType::Submenu(SubmenuItems::new(submenu)),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
// Element BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
// Element GETTERS.
|
||||
|
||||
pub fn element_type(&self) -> &ElementType {
|
||||
&self.element_type
|
||||
}
|
||||
}
|
||||
79
src/base/component/menu/group.rs
Normal file
79
src/base/component/menu/group.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
use super::Element;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, SmartDefault)]
|
||||
pub struct Group {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
elements : TypedComponents<Element>,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Group {
|
||||
fn new() -> Self {
|
||||
Group::default()
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
PrepareMarkup::With(html! {
|
||||
div id=[self.id()] class="menu-group" {
|
||||
(self.elements().render(cx))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Group {
|
||||
// Group BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn add_element(mut self, element: Element) -> Self {
|
||||
self.elements.alter_value(ArcTypedOp::Add(ArcTypedComponent::new(element)));
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_elements(&mut self, op: ArcTypedOp<Element>) -> &mut Self {
|
||||
self.elements.alter_value(op);
|
||||
self
|
||||
}
|
||||
|
||||
// Group GETTERS.
|
||||
|
||||
pub fn elements(&self) -> &TypedComponents<Element> {
|
||||
&self.elements
|
||||
}
|
||||
}
|
||||
207
src/base/component/menu/item.rs
Normal file
207
src/base/component/menu/item.rs
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
use super::{Megamenu, Submenu};
|
||||
|
||||
type Label = L10n;
|
||||
type Content = ArcTypedComponent<Html>;
|
||||
type SubmenuItems = ArcTypedComponent<Submenu>;
|
||||
type MegamenuGroups = ArcTypedComponent<Megamenu>;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum ItemType {
|
||||
#[default]
|
||||
Void,
|
||||
Label(Label),
|
||||
Link(Label, FnContextualPath),
|
||||
LinkBlank(Label, FnContextualPath),
|
||||
Html(Content),
|
||||
Submenu(Label, SubmenuItems),
|
||||
Megamenu(Label, MegamenuGroups),
|
||||
}
|
||||
|
||||
// Item.
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, SmartDefault)]
|
||||
pub struct Item {
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
item_type : ItemType,
|
||||
description: OptionTranslated,
|
||||
left_icon : OptionComponent<Icon>,
|
||||
right_icon : OptionComponent<Icon>,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Item {
|
||||
fn new() -> Self {
|
||||
Item::default()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
let description = self.description.using(cx.langid());
|
||||
|
||||
let left_icon = self.left_icon().render(cx);
|
||||
let right_icon = self.right_icon().render(cx);
|
||||
|
||||
match self.item_type() {
|
||||
ItemType::Void => PrepareMarkup::None,
|
||||
ItemType::Label(label) => PrepareMarkup::With(html! {
|
||||
li class="pt-menu__label" {
|
||||
span title=[description] {
|
||||
(left_icon)
|
||||
(label.escaped(cx.langid()))
|
||||
(right_icon)
|
||||
}
|
||||
}
|
||||
}),
|
||||
ItemType::Link(label, path) => PrepareMarkup::With(html! {
|
||||
li class="pt-menu__link" {
|
||||
a href=(path(cx)) title=[description] {
|
||||
(left_icon)
|
||||
(label.escaped(cx.langid()))
|
||||
(right_icon)
|
||||
}
|
||||
}
|
||||
}),
|
||||
ItemType::LinkBlank(label, path) => PrepareMarkup::With(html! {
|
||||
li class="pt-menu__link" {
|
||||
a href=(path(cx)) title=[description] target="_blank" {
|
||||
(left_icon)
|
||||
(label.escaped(cx.langid()))
|
||||
(right_icon)
|
||||
}
|
||||
}
|
||||
}),
|
||||
ItemType::Html(content) => PrepareMarkup::With(html! {
|
||||
li class="pt-menu__html" {
|
||||
(content.render(cx))
|
||||
}
|
||||
}),
|
||||
ItemType::Submenu(label, submenu) => PrepareMarkup::With(html! {
|
||||
li class="pt-menu__children" {
|
||||
a href="#" title=[description] {
|
||||
(left_icon)
|
||||
(label.escaped(cx.langid())) i class="pt-menu__icon bi-chevron-down" {}
|
||||
}
|
||||
div class="pt-menu__subs" {
|
||||
(submenu.render(cx))
|
||||
}
|
||||
}
|
||||
}),
|
||||
ItemType::Megamenu(label, megamenu) => PrepareMarkup::With(html! {
|
||||
li class="pt-menu__children" {
|
||||
a href="#" title=[description] {
|
||||
(left_icon)
|
||||
(label.escaped(cx.langid())) i class="pt-menu__icon bi-chevron-down" {}
|
||||
}
|
||||
div class="pt-menu__subs pt-menu__mega" {
|
||||
(megamenu.render(cx))
|
||||
}
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Item {
|
||||
pub fn label(label: L10n) -> Self {
|
||||
Item {
|
||||
item_type: ItemType::Label(label),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn link(label: L10n, path: FnContextualPath) -> Self {
|
||||
Item {
|
||||
item_type: ItemType::Link(label, path),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn link_blank(label: L10n, path: FnContextualPath) -> Self {
|
||||
Item {
|
||||
item_type: ItemType::LinkBlank(label, path),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn html(content: Html) -> Self {
|
||||
Item {
|
||||
item_type: ItemType::Html(Content::new(content)),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn submenu(label: L10n, submenu: Submenu) -> Self {
|
||||
Item {
|
||||
item_type: ItemType::Submenu(label, SubmenuItems::new(submenu)),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn megamenu(label: L10n, megamenu: Megamenu) -> Self {
|
||||
Item {
|
||||
item_type: ItemType::Megamenu(label, MegamenuGroups::new(megamenu)),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
// Item BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_description(&mut self, text: L10n) -> &mut Self {
|
||||
self.description.alter_value(text);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_left_icon(&mut self, icon: Option<Icon>) -> &mut Self {
|
||||
self.left_icon.alter_value(icon);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_right_icon(&mut self, icon: Option<Icon>) -> &mut Self {
|
||||
self.right_icon.alter_value(icon);
|
||||
self
|
||||
}
|
||||
|
||||
// Item GETTERS.
|
||||
|
||||
pub fn item_type(&self) -> &ItemType {
|
||||
&self.item_type
|
||||
}
|
||||
|
||||
pub fn description(&self) -> &OptionTranslated {
|
||||
&self.description
|
||||
}
|
||||
|
||||
pub fn left_icon(&self) -> &OptionComponent<Icon> {
|
||||
&self.left_icon
|
||||
}
|
||||
|
||||
pub fn right_icon(&self) -> &OptionComponent<Icon> {
|
||||
&self.right_icon
|
||||
}
|
||||
}
|
||||
79
src/base/component/menu/megamenu.rs
Normal file
79
src/base/component/menu/megamenu.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
use super::Group;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, SmartDefault)]
|
||||
pub struct Megamenu {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
groups : TypedComponents<Group>,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Megamenu {
|
||||
fn new() -> Self {
|
||||
Megamenu::default()
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
PrepareMarkup::With(html! {
|
||||
div id=[self.id()] class="pt-menu__groups" {
|
||||
(self.groups().render(cx))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Megamenu {
|
||||
// Megamenu BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn add_group(mut self, group: Group) -> Self {
|
||||
self.groups.alter_value(ArcTypedOp::Add(ArcTypedComponent::new(group)));
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_groups(&mut self, op: ArcTypedOp<Group>) -> &mut Self {
|
||||
self.groups.alter_value(op);
|
||||
self
|
||||
}
|
||||
|
||||
// Megamenu GETTERS.
|
||||
|
||||
pub fn groups(&self) -> &TypedComponents<Group> {
|
||||
&self.groups
|
||||
}
|
||||
}
|
||||
107
src/base/component/menu/menu_main.rs
Normal file
107
src/base/component/menu/menu_main.rs
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
use super::Item;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, SmartDefault)]
|
||||
pub struct Menu {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
items : TypedComponents<Item>,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Menu {
|
||||
fn new() -> Self {
|
||||
Menu::default()
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
cx.set_param::<bool>(PARAM_BASE_INCLUDE_MENU_ASSETS, true);
|
||||
cx.set_param::<bool>(PARAM_BASE_INCLUDE_ICONS, true);
|
||||
|
||||
PrepareMarkup::With(html! {
|
||||
div id=[self.id()] class="pt-menu__container" {
|
||||
div class="pt-menu__wrapper" {
|
||||
div class="pt-menu__main" {
|
||||
div class="pt-menu__overlay" {}
|
||||
nav class="pt-menu__nav" {
|
||||
div class="pt-menu__header" {
|
||||
button type="button" class="pt-menu__arrow" {
|
||||
i class="bi-chevron-left" {}
|
||||
}
|
||||
div class="pt-menu__title" {}
|
||||
button type="button" class="pt-menu__close" {
|
||||
i class="bi-x" {}
|
||||
}
|
||||
}
|
||||
ul class="pt-menu__section" {
|
||||
(self.items().render(cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
button
|
||||
type="button"
|
||||
class="pt-menu__trigger"
|
||||
title=[L10n::l("menu_toggle").using(cx.langid())]
|
||||
{
|
||||
span {} span {} span {}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Menu {
|
||||
// Menu BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn add_item(mut self, item: Item) -> Self {
|
||||
self.items.alter_value(ArcTypedOp::Add(ArcTypedComponent::new(item)));
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_items(&mut self, op: ArcTypedOp<Item>) -> &mut Self {
|
||||
self.items.alter_value(op);
|
||||
self
|
||||
}
|
||||
|
||||
// Menu GETTERS.
|
||||
|
||||
pub fn items(&self) -> &TypedComponents<Item> {
|
||||
&self.items
|
||||
}
|
||||
}
|
||||
95
src/base/component/menu/submenu.rs
Normal file
95
src/base/component/menu/submenu.rs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
use super::Item;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, SmartDefault)]
|
||||
pub struct Submenu {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
title : OptionTranslated,
|
||||
items : TypedComponents<Item>,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Submenu {
|
||||
fn new() -> Self {
|
||||
Submenu::default()
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
PrepareMarkup::With(html! {
|
||||
div id=[self.id()] class="pt-menu__items" {
|
||||
@if let Some(title) = self.title().using(cx.langid()) {
|
||||
h4 class="pt-menu__title" { (title) }
|
||||
}
|
||||
ul {
|
||||
(self.items().render(cx))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Submenu {
|
||||
// Submenu BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_title(&mut self, title: L10n) -> &mut Self {
|
||||
self.title.alter_value(title);
|
||||
self
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn add_item(mut self, item: Item) -> Self {
|
||||
self.items.alter_value(ArcTypedOp::Add(ArcTypedComponent::new(item)));
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_items(&mut self, op: ArcTypedOp<Item>) -> &mut Self {
|
||||
self.items.alter_value(op);
|
||||
self
|
||||
}
|
||||
|
||||
// Submenu GETTERS.
|
||||
|
||||
pub fn title(&self) -> &OptionTranslated {
|
||||
&self.title
|
||||
}
|
||||
|
||||
pub fn items(&self) -> &TypedComponents<Item> {
|
||||
&self.items
|
||||
}
|
||||
}
|
||||
110
src/base/component/paragraph.rs
Normal file
110
src/base/component/paragraph.rs
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Paragraph {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
classes : OptionClasses,
|
||||
font_size : FontSize,
|
||||
stuff : AnyComponents,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Paragraph {
|
||||
fn new() -> Self {
|
||||
Paragraph::default()
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn setup_before_prepare(&mut self, _cx: &mut Context) {
|
||||
self.prepend_classes(self.font_size().to_string());
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
PrepareMarkup::With(html! {
|
||||
p
|
||||
id=[self.id()]
|
||||
class=[self.classes().get()]
|
||||
{
|
||||
(self.components().render(cx))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Paragraph {
|
||||
pub fn with(component: impl ComponentTrait) -> Self {
|
||||
Paragraph::default().add_component(component)
|
||||
}
|
||||
|
||||
pub fn translated(l10n: L10n) -> Self {
|
||||
Paragraph::default().add_translated(l10n)
|
||||
}
|
||||
|
||||
// Paragraph BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_font_size(&mut self, font_size: FontSize) -> &mut Self {
|
||||
self.font_size = font_size;
|
||||
self
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn add_component(mut self, component: impl ComponentTrait) -> Self {
|
||||
self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(component)));
|
||||
self
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn add_translated(mut self, l10n: L10n) -> Self {
|
||||
self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(Translate::with(l10n))));
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_components(&mut self, op: ArcAnyOp) -> &mut Self {
|
||||
self.stuff.alter_value(op);
|
||||
self
|
||||
}
|
||||
|
||||
// Paragraph GETTERS.
|
||||
|
||||
pub fn font_size(&self) -> &FontSize {
|
||||
&self.font_size
|
||||
}
|
||||
|
||||
pub fn components(&self) -> &AnyComponents {
|
||||
&self.stuff
|
||||
}
|
||||
}
|
||||
133
src/base/component/powered_by.rs
Normal file
133
src/base/component/powered_by.rs
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(Default, Eq, PartialEq)]
|
||||
pub enum PoweredByLogo {
|
||||
#[default]
|
||||
None,
|
||||
Color,
|
||||
LineDark,
|
||||
LineLight,
|
||||
LineRGB(u8, u8, u8),
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, SmartDefault)]
|
||||
pub struct PoweredBy {
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
copyright : Option<String>,
|
||||
logo : PoweredByLogo,
|
||||
}
|
||||
|
||||
impl ComponentTrait for PoweredBy {
|
||||
fn new() -> Self {
|
||||
let year = Utc::now().format("%Y").to_string();
|
||||
let c = concat_string!(year, " © ", config::SETTINGS.app.name);
|
||||
PoweredBy {
|
||||
copyright: Some(c),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
Some("pt-poweredby".to_owned())
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
let poweredby_pagetop = L10n::l("poweredby_pagetop")
|
||||
.with_arg(
|
||||
"pagetop_link",
|
||||
"<a href=\"https://crates.io/crates/pagetop\">PageTop</a>",
|
||||
)
|
||||
.escaped(cx.langid());
|
||||
|
||||
let pagetop_logo = match self.logo() {
|
||||
PoweredByLogo::None => html! {},
|
||||
PoweredByLogo::Color => self.logo_color(cx),
|
||||
PoweredByLogo::LineDark => self.logo_line(10, 11, 9, cx),
|
||||
PoweredByLogo::LineLight => self.logo_line(255, 255, 255, cx),
|
||||
PoweredByLogo::LineRGB(r, g, b) => self.logo_line(*r, *g, *b, cx),
|
||||
};
|
||||
|
||||
PrepareMarkup::With(html! {
|
||||
div id=[self.id()] {
|
||||
@if let Some(c) = self.copyright() {
|
||||
span class="pt-poweredby__copyright" { (c) "." } " "
|
||||
}
|
||||
span class="pt-poweredby__pagetop" { (poweredby_pagetop) " " (pagetop_logo) }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl PoweredBy {
|
||||
// PoweredBy BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_copyright(&mut self, copyright: Option<impl Into<String>>) -> &mut Self {
|
||||
self.copyright = copyright.map(|c| c.into());
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_logo(&mut self, logo: PoweredByLogo) -> &mut Self {
|
||||
self.logo = logo;
|
||||
self
|
||||
}
|
||||
|
||||
// PoweredBy GETTERS.
|
||||
|
||||
pub fn copyright(&self) -> &Option<String> {
|
||||
&self.copyright
|
||||
}
|
||||
|
||||
pub fn logo(&self) -> &PoweredByLogo {
|
||||
&self.logo
|
||||
}
|
||||
|
||||
// PoweredBy PRIVATE.
|
||||
|
||||
fn logo_color(&self, cx: &mut Context) -> Markup {
|
||||
let logo_txt = &L10n::l("pagetop_logo").using(cx.langid());
|
||||
html! {
|
||||
span class="pt-poweredby__logo" aria-label=[logo_txt] {
|
||||
img src="/base/pagetop-logo.svg" alt=[logo_txt] {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn logo_line(&self, r: u8, g: u8, b: u8, cx: &mut Context) -> Markup {
|
||||
let logo_txt = L10n::l("pagetop_logo").using(cx.langid());
|
||||
let logo_rgb = format!("rgb({},{},{})", r, g, b);
|
||||
html! {
|
||||
span class="pt-poweredby__logo" aria-label=[logo_txt] {
|
||||
svg viewBox="0 0 1614 1614" xmlns="http://www.w3.org/2000/svg" role="img" {
|
||||
path fill=(logo_rgb) d="M 1573,357 L 1415,357 C 1400,357 1388,369 1388,383 L 1388,410 1335,410 1335,357 C 1335,167 1181,13 992,13 L 621,13 C 432,13 278,167 278,357 L 278,410 225,410 225,383 C 225,369 213,357 198,357 L 40,357 C 25,357 13,369 13,383 L 13,648 C 13,662 25,674 40,674 L 198,674 C 213,674 225,662 225,648 L 225,621 278,621 278,1256 C 278,1446 432,1600 621,1600 L 992,1600 C 1181,1600 1335,1446 1335,1256 L 1335,621 1388,621 1388,648 C 1388,662 1400,674 1415,674 L 1573,674 C 1588,674 1600,662 1600,648 L 1600,383 C 1600,369 1588,357 1573,357 L 1573,357 1573,357 Z M 66,410 L 172,410 172,621 66,621 66,410 66,410 Z M 1282,357 L 1282,488 C 1247,485 1213,477 1181,464 L 1196,437 C 1203,425 1199,409 1186,401 1174,394 1158,398 1150,411 L 1133,440 C 1105,423 1079,401 1056,376 L 1075,361 C 1087,352 1089,335 1079,324 1070,313 1054,311 1042,320 L 1023,335 C 1000,301 981,263 967,221 L 1011,196 C 1023,189 1028,172 1021,160 1013,147 997,143 984,150 L 953,168 C 945,136 941,102 940,66 L 992,66 C 1152,66 1282,197 1282,357 L 1282,357 1282,357 Z M 621,66 L 674,66 674,225 648,225 C 633,225 621,237 621,251 621,266 633,278 648,278 L 674,278 674,357 648,357 C 633,357 621,369 621,383 621,398 633,410 648,410 L 674,410 674,489 648,489 C 633,489 621,501 621,516 621,530 633,542 648,542 L 664,542 C 651,582 626,623 600,662 583,653 563,648 542,648 469,648 410,707 410,780 410,787 411,794 412,801 388,805 361,806 331,806 L 331,357 C 331,197 461,66 621,66 L 621,66 621,66 Z M 621,780 C 621,824 586,859 542,859 498,859 463,824 463,780 463,736 498,701 542,701 586,701 621,736 621,780 L 621,780 621,780 Z M 225,463 L 278,463 278,569 225,569 225,463 225,463 Z M 992,1547 L 621,1547 C 461,1547 331,1416 331,1256 L 331,859 C 367,859 400,858 431,851 454,888 495,912 542,912 615,912 674,853 674,780 674,747 662,718 642,695 675,645 706,594 720,542 L 780,542 C 795,542 807,530 807,516 807,501 795,489 780,489 L 727,489 727,410 780,410 C 795,410 807,398 807,383 807,369 795,357 780,357 L 727,357 727,278 780,278 C 795,278 807,266 807,251 807,237 795,225 780,225 L 727,225 727,66 887,66 C 889,111 895,155 905,196 L 869,217 C 856,224 852,240 859,253 864,261 873,266 882,266 887,266 891,265 895,263 L 921,248 C 937,291 958,331 983,367 L 938,403 C 926,412 925,429 934,440 939,447 947,450 954,450 960,450 966,448 971,444 L 1016,408 C 1043,438 1074,465 1108,485 L 1084,527 C 1076,539 1081,555 1093,563 1098,565 1102,566 1107,566 1116,566 1125,561 1129,553 L 1155,509 C 1194,527 1237,538 1282,541 L 1282,1256 C 1282,1416 1152,1547 992,1547 L 992,1547 992,1547 Z M 1335,463 L 1388,463 1388,569 1335,569 1335,463 1335,463 Z M 1441,410 L 1547,410 1547,621 1441,621 1441,410 1441,410 Z" {}
|
||||
path fill=(logo_rgb) d="M 1150,1018 L 463,1018 C 448,1018 436,1030 436,1044 L 436,1177 C 436,1348 545,1468 701,1468 L 912,1468 C 1068,1468 1177,1348 1177,1177 L 1177,1044 C 1177,1030 1165,1018 1150,1018 L 1150,1018 1150,1018 Z M 912,1071 L 1018,1071 1018,1124 912,1124 912,1071 912,1071 Z M 489,1071 L 542,1071 542,1124 489,1124 489,1071 489,1071 Z M 701,1415 L 700,1415 C 701,1385 704,1352 718,1343 731,1335 759,1341 795,1359 802,1363 811,1363 818,1359 854,1341 882,1335 895,1343 909,1352 912,1385 913,1415 L 912,1415 701,1415 701,1415 701,1415 Z M 1124,1177 C 1124,1296 1061,1384 966,1408 964,1365 958,1320 922,1298 894,1281 856,1283 807,1306 757,1283 719,1281 691,1298 655,1320 649,1365 647,1408 552,1384 489,1296 489,1177 L 569,1177 C 583,1177 595,1165 595,1150 L 595,1071 859,1071 859,1150 C 859,1165 871,1177 886,1177 L 1044,1177 C 1059,1177 1071,1165 1071,1150 L 1071,1071 1124,1071 1124,1177 1124,1177 1124,1177 Z" {}
|
||||
path fill=(logo_rgb) d="M 1071,648 C 998,648 939,707 939,780 939,853 998,912 1071,912 1144,912 1203,853 1203,780 1203,707 1144,648 1071,648 L 1071,648 1071,648 Z M 1071,859 C 1027,859 992,824 992,780 992,736 1027,701 1071,701 1115,701 1150,736 1150,780 1150,824 1115,859 1071,859 L 1071,859 1071,859 Z" {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/base/component/translate.rs
Normal file
35
src/base/component/translate.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(BaseHandle, SmartDefault)]
|
||||
pub struct Translate(L10n);
|
||||
|
||||
impl ComponentTrait for Translate {
|
||||
fn new() -> Self {
|
||||
Translate::default()
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
PrepareMarkup::With(self.l10n().escaped(cx.langid()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Translate {
|
||||
pub fn with(l10n: L10n) -> Self {
|
||||
Translate(l10n)
|
||||
}
|
||||
|
||||
// Translate BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_l10n(&mut self, l10n: L10n) -> &mut Self {
|
||||
self.0 = l10n;
|
||||
self
|
||||
}
|
||||
|
||||
// Translate GETTERS.
|
||||
|
||||
pub fn l10n(&self) -> &L10n {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
168
src/base/component/wrapper.rs
Normal file
168
src/base/component/wrapper.rs
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
pub enum WrapperType {
|
||||
#[default]
|
||||
Container,
|
||||
Header,
|
||||
Footer,
|
||||
Main,
|
||||
Section,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(BaseHandle, ComponentClasses, SmartDefault)]
|
||||
pub struct Wrapper {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
classes : OptionClasses,
|
||||
inner_classes: OptionClasses,
|
||||
wrapper_type : WrapperType,
|
||||
stuff : AnyComponents,
|
||||
}
|
||||
|
||||
impl ComponentTrait for Wrapper {
|
||||
fn new() -> Self {
|
||||
Wrapper::default()
|
||||
.with_classes(ClassesOp::Add, "container")
|
||||
.with_inner_classes(ClassesOp::Add, "container")
|
||||
}
|
||||
|
||||
fn id(&self) -> Option<String> {
|
||||
self.id.get()
|
||||
}
|
||||
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
|
||||
fn is_renderable(&self, cx: &Context) -> bool {
|
||||
(self.renderable.check)(cx)
|
||||
}
|
||||
|
||||
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
|
||||
match self.wrapper_type() {
|
||||
WrapperType::Header => PrepareMarkup::With(html! {
|
||||
header id=[self.id()] class=[self.classes().get()] {
|
||||
div class=[self.inner_classes().get()] {
|
||||
(self.components().render(cx))
|
||||
}
|
||||
}
|
||||
}),
|
||||
WrapperType::Footer => PrepareMarkup::With(html! {
|
||||
footer id=[self.id()] class=[self.classes().get()] {
|
||||
div class=[self.inner_classes().get()] {
|
||||
(self.components().render(cx))
|
||||
}
|
||||
}
|
||||
}),
|
||||
WrapperType::Main => PrepareMarkup::With(html! {
|
||||
main id=[self.id()] class=[self.classes().get()] {
|
||||
div class=[self.inner_classes().get()] {
|
||||
(self.components().render(cx))
|
||||
}
|
||||
}
|
||||
}),
|
||||
WrapperType::Section => PrepareMarkup::With(html! {
|
||||
section id=[self.id()] class=[self.classes().get()] {
|
||||
div class=[self.inner_classes().get()] {
|
||||
(self.components().render(cx))
|
||||
}
|
||||
}
|
||||
}),
|
||||
_ => PrepareMarkup::With(html! {
|
||||
div id=[self.id()] class=[self.classes().get()] {
|
||||
(self.components().render(cx))
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Wrapper {
|
||||
pub fn header() -> Self {
|
||||
let mut c = Wrapper::default()
|
||||
.with_classes(ClassesOp::Add, "header")
|
||||
.with_inner_classes(ClassesOp::Add, "container");
|
||||
c.wrapper_type = WrapperType::Header;
|
||||
c
|
||||
}
|
||||
|
||||
pub fn footer() -> Self {
|
||||
let mut c = Wrapper::default()
|
||||
.with_classes(ClassesOp::Add, "footer")
|
||||
.with_inner_classes(ClassesOp::Add, "container");
|
||||
c.wrapper_type = WrapperType::Footer;
|
||||
c
|
||||
}
|
||||
|
||||
pub fn main() -> Self {
|
||||
let mut c = Wrapper::default()
|
||||
.with_classes(ClassesOp::Add, "main")
|
||||
.with_inner_classes(ClassesOp::Add, "container");
|
||||
c.wrapper_type = WrapperType::Main;
|
||||
c
|
||||
}
|
||||
|
||||
pub fn section() -> Self {
|
||||
let mut c = Wrapper::default()
|
||||
.with_classes(ClassesOp::Add, "section")
|
||||
.with_inner_classes(ClassesOp::Add, "container");
|
||||
c.wrapper_type = WrapperType::Section;
|
||||
c
|
||||
}
|
||||
|
||||
// Wrapper BUILDER.
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_id(&mut self, id: impl Into<String>) -> &mut Self {
|
||||
self.id.alter_value(id);
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_weight(&mut self, value: Weight) -> &mut Self {
|
||||
self.weight = value;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_renderable(&mut self, check: FnIsRenderable) -> &mut Self {
|
||||
self.renderable.check = check;
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_inner_classes(&mut self, op: ClassesOp, classes: impl Into<String>) -> &mut Self {
|
||||
self.inner_classes.alter_value(op, classes);
|
||||
self
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub fn add_component(mut self, component: impl ComponentTrait) -> Self {
|
||||
self.stuff.alter_value(ArcAnyOp::Add(ArcAnyComponent::new(component)));
|
||||
self
|
||||
}
|
||||
|
||||
#[fn_with]
|
||||
pub fn alter_components(&mut self, op: ArcAnyOp) -> &mut Self {
|
||||
self.stuff.alter_value(op);
|
||||
self
|
||||
}
|
||||
|
||||
// Wrapper GETTERS.
|
||||
|
||||
pub fn inner_classes(&self) -> &OptionClasses {
|
||||
&self.inner_classes
|
||||
}
|
||||
|
||||
pub fn wrapper_type(&self) -> &WrapperType {
|
||||
&self.wrapper_type
|
||||
}
|
||||
|
||||
pub fn components(&self) -> &AnyComponents {
|
||||
&self.stuff
|
||||
}
|
||||
}
|
||||
8
src/base/theme.rs
Normal file
8
src/base/theme.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
mod basic;
|
||||
pub use basic::Basic;
|
||||
|
||||
mod chassis;
|
||||
pub use chassis::Chassis;
|
||||
|
||||
mod inception;
|
||||
pub use inception::Inception;
|
||||
32
src/base/theme/basic.rs
Normal file
32
src/base/theme/basic.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(BaseHandle)]
|
||||
pub struct Basic;
|
||||
|
||||
impl PackageTrait for Basic {
|
||||
fn name(&self) -> L10n {
|
||||
L10n::n("Basic")
|
||||
}
|
||||
|
||||
fn theme(&self) -> Option<ThemeRef> {
|
||||
Some(&Basic)
|
||||
}
|
||||
}
|
||||
|
||||
impl ThemeTrait for Basic {
|
||||
fn after_prepare_body(&self, page: &mut Page) {
|
||||
page.alter_favicon(Some(Favicon::new().with_icon("/base/favicon.ico")))
|
||||
.alter_context(ContextOp::AddStyleSheet(
|
||||
StyleSheet::at("/base/css/normalize.min.css")
|
||||
.with_version("8.0.1")
|
||||
.with_weight(-90),
|
||||
))
|
||||
.alter_context(ContextOp::AddBaseAssets)
|
||||
.alter_context(ContextOp::AddStyleSheet(
|
||||
StyleSheet::at("/base/css/basic.css")
|
||||
.with_version("0.0.1")
|
||||
.with_weight(-90),
|
||||
));
|
||||
}
|
||||
}
|
||||
32
src/base/theme/chassis.rs
Normal file
32
src/base/theme/chassis.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(BaseHandle)]
|
||||
pub struct Chassis;
|
||||
|
||||
impl PackageTrait for Chassis {
|
||||
fn name(&self) -> L10n {
|
||||
L10n::n("Chassis")
|
||||
}
|
||||
|
||||
fn theme(&self) -> Option<ThemeRef> {
|
||||
Some(&Chassis)
|
||||
}
|
||||
}
|
||||
|
||||
impl ThemeTrait for Chassis {
|
||||
fn after_prepare_body(&self, page: &mut Page) {
|
||||
page.alter_favicon(Some(Favicon::new().with_icon("/base/favicon.ico")))
|
||||
.alter_context(ContextOp::AddStyleSheet(
|
||||
StyleSheet::at("/base/css/normalize.min.css")
|
||||
.with_version("8.0.1")
|
||||
.with_weight(-90),
|
||||
))
|
||||
.alter_context(ContextOp::AddBaseAssets)
|
||||
.alter_context(ContextOp::AddStyleSheet(
|
||||
StyleSheet::at("/base/css/chassis.css")
|
||||
.with_version("0.0.1")
|
||||
.with_weight(-90),
|
||||
));
|
||||
}
|
||||
}
|
||||
32
src/base/theme/inception.rs
Normal file
32
src/base/theme/inception.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use crate::prelude::*;
|
||||
use crate::BaseHandle;
|
||||
|
||||
#[derive(BaseHandle)]
|
||||
pub struct Inception;
|
||||
|
||||
impl PackageTrait for Inception {
|
||||
fn name(&self) -> L10n {
|
||||
L10n::n("Inception")
|
||||
}
|
||||
|
||||
fn theme(&self) -> Option<ThemeRef> {
|
||||
Some(&Inception)
|
||||
}
|
||||
}
|
||||
|
||||
impl ThemeTrait for Inception {
|
||||
fn after_prepare_body(&self, page: &mut Page) {
|
||||
page.alter_favicon(Some(Favicon::new().with_icon("/base/favicon.ico")))
|
||||
.alter_context(ContextOp::AddStyleSheet(
|
||||
StyleSheet::at("/base/css/normalize.min.css")
|
||||
.with_version("8.0.1")
|
||||
.with_weight(-90),
|
||||
))
|
||||
.alter_context(ContextOp::AddBaseAssets)
|
||||
.alter_context(ContextOp::AddStyleSheet(
|
||||
StyleSheet::at("/base/css/inception.css")
|
||||
.with_version("0.0.1")
|
||||
.with_weight(-90),
|
||||
));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue