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",
}
}
}