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(inherit: I) -> $widgetname { $widgetname(None, Box::new(inherit)) } pub struct $widgetname(Option>, Box); impl $widgetname { fn wrapped_class(&self) -> Vec { 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::>() } pub fn on(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 { self.wrapped_class() } fn extended_class(&self) -> Vec { 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(inherit: I) -> SmallScreenWrapper { SmallScreen(inherit) } pub fn medium(inherit: I) -> MediumScreenWrapper { MediumScreen(inherit) } pub fn large(inherit: I) -> LargeScreenWrapper { LargeScreen(inherit) } pub fn xl(inherit: I) -> XLScreenWrapper { XLScreen(inherit) } pub fn _2xl(inherit: I) -> _2XLScreenWrapper { _2XLScreen(inherit) } }