use maud::{Markup, Render, html}; use crate::ui::{ UIWidget, color::{Gradient, UIColor}, }; #[allow(non_snake_case)] pub fn Background(inner: T) -> BackgroundWidget { BackgroundWidget( Box::new(inner), None, None, None, None, None, None, None, None, None, None, ) } pub struct BackgroundWidget( // Inner Box, // Background Color Option>, // Background Attachment Option, Option, Option, Option, Option, // Background Image URL Option, // Gradient Option, Option, Option, ); impl BackgroundWidget { pub fn color(mut self, color: C) -> Self { self.1 = Some(Box::new(color)); self } pub fn image(mut self, url: &str) -> Self { self.7 = Some(url.to_string()); self } pub fn none(mut self) -> Self { self.8 = Some(BackgroundGradient::None); self } pub fn gradient(mut self, direction: BackgroundGradient, gradient: Gradient) -> Self { self.8 = Some(direction); self.9 = Some(gradient); self } pub fn position(mut self, position: BackgroundPosition) -> Self { self.10 = Some(position); self } pub fn scroll(mut self, attachment: BackgroundScrollAttachment) -> Self { self.2 = Some(attachment); self } pub fn clip(mut self, clip: BackgroundClip) -> Self { self.3 = Some(clip); self } pub fn origin(mut self, origin: BackgroundOrigin) -> Self { self.4 = Some(origin); self } pub fn repeat(mut self, repeat: BackgroundRepeat) -> Self { self.5 = Some(repeat); self } pub fn size(mut self, size: BackgroundSize) -> Self { self.6 = Some(size); self } } impl Render for BackgroundWidget { fn render(&self) -> Markup { self.render_with_class("") } } impl UIWidget for BackgroundWidget { fn can_inherit(&self) -> bool { true } fn base_class(&self) -> Vec { let mut ret = Vec::new(); if let Some(color) = &self.1 { ret.push(format!("bg-{}", color.color_class())); } if let Some(attachment) = &self.2 { ret.push(attachment.to_value().to_string()); } if let Some(clip) = &self.3 { ret.push(clip.to_value().to_string()); } if let Some(origin) = &self.4 { ret.push(origin.to_value().to_string()); } if let Some(repeat) = &self.5 { ret.push(repeat.to_value().to_string()); } if let Some(size) = &self.6 { ret.push(size.to_value().to_string()); } if let Some(image) = &self.7 { ret.push(format!("bg-[url('{image}')]")); } if let Some(gradient) = &self.8 { ret.push(gradient.to_value().to_string()); } if let Some(gradient) = &self.9 { ret.extend_from_slice(&gradient.color_class()); } if let Some(position) = &self.10 { ret.push(position.to_value().to_string()); } ret } fn extended_class(&self) -> Vec { let mut c = self.base_class(); c.extend_from_slice(&self.0.extended_class()); c } fn render_with_class(&self, class: &str) -> Markup { if self.0.as_ref().can_inherit() { self.0 .as_ref() .render_with_class(&format!("{} {class}", self.base_class().join(" "))) } else { html! { div class=(format!("{} {class}", self.base_class().join(" "))) { (self.0.as_ref()) } } } } } /// Controlling how a background image behaves when scrolling. pub enum BackgroundScrollAttachment { /// Fix the background image relative to the viewport. Fixed, /// Scroll the background image with the container and the viewport. Local, /// Scroll the background image with the viewport, but not with the container. Scroll, } impl BackgroundScrollAttachment { pub const fn to_value(&self) -> &str { match self { BackgroundScrollAttachment::Fixed => "bg-fixed", BackgroundScrollAttachment::Local => "bg-local", BackgroundScrollAttachment::Scroll => "bg-scroll", } } } pub enum BackgroundClip { Border, Padding, Content, Text, } impl BackgroundClip { pub const fn to_value(&self) -> &str { match self { BackgroundClip::Border => "bg-clip-border", BackgroundClip::Padding => "bg-clip-padding", BackgroundClip::Content => "bg-clip-content", BackgroundClip::Text => "bg-clip-text", } } } pub enum BackgroundOrigin { Border, Padding, Content, } impl BackgroundOrigin { pub const fn to_value(&self) -> &str { match self { BackgroundOrigin::Border => "bg-origin-border", BackgroundOrigin::Padding => "bg-origin-padding", BackgroundOrigin::Content => "bg-origin-content", } } } pub enum BackgroundRepeat { Repeat, NoRepeat, RepeatX, RepeatY, Round, Space, } impl BackgroundRepeat { pub const fn to_value(&self) -> &str { match self { BackgroundRepeat::Repeat => "bg-repeat", BackgroundRepeat::NoRepeat => "bg-no-repeat", BackgroundRepeat::RepeatX => "bg-repeat-x", BackgroundRepeat::RepeatY => "bg-repeat-y", BackgroundRepeat::Round => "bg-repeat-round", BackgroundRepeat::Space => "bg-repeat-space", } } } pub enum BackgroundSize { Auto, Cover, Contain, } impl BackgroundSize { pub const fn to_value(&self) -> &str { match self { BackgroundSize::Auto => "bg-auto", BackgroundSize::Cover => "bg-cover", BackgroundSize::Contain => "bg-contain", } } } pub enum BackgroundGradient { None, ToTop, ToTopRight, ToRight, ToBottomRight, ToBottom, ToBottomLeft, ToLeft, ToTopLeft, } impl BackgroundGradient { pub const fn to_value(&self) -> &str { match self { BackgroundGradient::None => "bg-none", BackgroundGradient::ToTop => "bg-gradient-to-t", BackgroundGradient::ToTopRight => "bg-gradient-to-tr", BackgroundGradient::ToRight => "bg-gradient-to-r", BackgroundGradient::ToBottomRight => "bg-gradient-to-br", BackgroundGradient::ToBottom => "bg-gradient-to-b", BackgroundGradient::ToBottomLeft => "bg-gradient-to-bl", BackgroundGradient::ToLeft => "bg-gradient-to-l", BackgroundGradient::ToTopLeft => "bg-gradient-to-tl", } } } pub enum BackgroundPosition { Bottom, Center, Left, LeftBottom, LeftTop, Right, RightBottom, RightTop, Top, } impl BackgroundPosition { pub const fn to_value(&self) -> &str { match self { BackgroundPosition::Bottom => "bg-bottom", BackgroundPosition::Center => "bg-center", BackgroundPosition::Left => "bg-left", BackgroundPosition::LeftBottom => "bg-left-bottom", BackgroundPosition::LeftTop => "bg-left-top", BackgroundPosition::Right => "bg-right", BackgroundPosition::RightBottom => "bg-right-bottom", BackgroundPosition::RightTop => "bg-right-top", BackgroundPosition::Top => "bg-top", } } }