based/src/ui/wrapper/mod.rs
2025-01-17 16:28:56 +01:00

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)
}
}