116 lines
3.4 KiB
Rust
116 lines
3.4 KiB
Rust
use crate::ui::UIWidget;
|
|
use maud::{Markup, Render, html};
|
|
|
|
macro_rules! wrapper {
|
|
($constr:ident, $widgetname:ident, $class:literal) => {
|
|
#[allow(non_snake_case)]
|
|
pub fn $constr<I: UIWidget + 'static>(inherit: I) -> $widgetname {
|
|
$widgetname(None, Box::new(inherit))
|
|
}
|
|
|
|
pub struct $widgetname(Option<Box<dyn UIWidget>>, Box<dyn UIWidget>);
|
|
|
|
impl $widgetname {
|
|
fn wrapped_class(&self) -> Vec<String> {
|
|
self.1
|
|
.extended_class()
|
|
.into_iter()
|
|
.filter(|x| !x.is_empty())
|
|
.map(|x| {
|
|
let mut s = $class.to_string();
|
|
s.push_str(":");
|
|
s.push_str(&x);
|
|
s
|
|
})
|
|
.collect::<Vec<_>>()
|
|
}
|
|
|
|
pub fn on<T: UIWidget + 'static>(mut self, inner: T) -> Self {
|
|
self.0 = Some(Box::new(inner));
|
|
self
|
|
}
|
|
}
|
|
|
|
impl Render for $widgetname {
|
|
fn render(&self) -> Markup {
|
|
self.render_with_class("")
|
|
}
|
|
}
|
|
|
|
impl UIWidget for $widgetname {
|
|
fn can_inherit(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
fn base_class(&self) -> Vec<String> {
|
|
self.wrapped_class()
|
|
}
|
|
|
|
fn extended_class(&self) -> Vec<String> {
|
|
let mut ret = self.base_class();
|
|
if let Some(inner) = &self.0 {
|
|
ret.extend_from_slice(&inner.extended_class());
|
|
}
|
|
|
|
ret
|
|
}
|
|
|
|
fn render_with_class(&self, class: &str) -> Markup {
|
|
if self.0.as_ref().unwrap().can_inherit() {
|
|
self.0
|
|
.as_ref()
|
|
.unwrap()
|
|
.render_with_class(&format!("{} {class}", self.wrapped_class().join(" ")))
|
|
} else {
|
|
html! {
|
|
div class=(format!("{} {class}", self.wrapped_class().join(" "))) {
|
|
(self.0.as_ref().unwrap())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
wrapper!(Hover, HoverWrapper, "hover");
|
|
|
|
wrapper!(SmallScreen, SmallScreenWrapper, "sm");
|
|
wrapper!(MediumScreen, MediumScreenWrapper, "md");
|
|
wrapper!(LargeScreen, LargeScreenWrapper, "lg");
|
|
wrapper!(XLScreen, XLScreenWrapper, "xl");
|
|
wrapper!(_2XLScreen, _2XLScreenWrapper, "2xl");
|
|
|
|
// TODO : responsive media
|
|
|
|
// TODO : arbitrary values "min-[320px]:text-center max-[600px]:bg-sky-300"
|
|
|
|
#[allow(non_snake_case)]
|
|
pub mod Screen {
|
|
use crate::ui::UIWidget;
|
|
|
|
use super::{
|
|
_2XLScreen, _2XLScreenWrapper, LargeScreen, LargeScreenWrapper, MediumScreen,
|
|
MediumScreenWrapper, SmallScreen, SmallScreenWrapper, XLScreen, XLScreenWrapper,
|
|
};
|
|
|
|
pub fn small<I: UIWidget + 'static>(inherit: I) -> SmallScreenWrapper {
|
|
SmallScreen(inherit)
|
|
}
|
|
|
|
pub fn medium<I: UIWidget + 'static>(inherit: I) -> MediumScreenWrapper {
|
|
MediumScreen(inherit)
|
|
}
|
|
|
|
pub fn large<I: UIWidget + 'static>(inherit: I) -> LargeScreenWrapper {
|
|
LargeScreen(inherit)
|
|
}
|
|
|
|
pub fn xl<I: UIWidget + 'static>(inherit: I) -> XLScreenWrapper {
|
|
XLScreen(inherit)
|
|
}
|
|
|
|
pub fn _2xl<I: UIWidget + 'static>(inherit: I) -> _2XLScreenWrapper {
|
|
_2XLScreen(inherit)
|
|
}
|
|
}
|