diff --git a/examples/ui.rs b/examples/ui.rs index e2f92d3..b2256f7 100644 --- a/examples/ui.rs +++ b/examples/ui.rs @@ -15,8 +15,8 @@ pub async fn index_page(ctx: RequestContext) -> StringResponse { h1 { "Hello World!" }; ( - Screen::medium(Hover(Background(Nothing()).color(Red::_700))).on( - Background(Text("HELLO!")).color(Blue::_700) + Screen::medium(Hover(Background(Red::_700, Nothing()))).on( + Background(Blue::_700, Text("HELLO!")) ) ) diff --git a/src/lib.rs b/src/lib.rs index 809b519..1985369 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -#![feature(const_vec_string_slice)] - use tokio::sync::OnceCell; pub mod auth; diff --git a/src/ui/color.rs b/src/ui/color.rs index e7baa05..c42e898 100644 --- a/src/ui/color.rs +++ b/src/ui/color.rs @@ -12,7 +12,7 @@ pub trait ColorCircle { fn next(&self) -> Self; } -// todo : specific colors rgb -[#50d71e] +// todo : specific colors rgb macro_rules! color_map { ($name:ident, $id:literal) => { @@ -133,81 +133,3 @@ impl UIColor for Colors { } } } - -// TODO : Gradient - -pub struct Gradient { - start: Box, - middle: Option>, - end: Option>, - pos_start: Option, - pos_middle: Option, - pos_end: Option, -} - -impl Gradient { - pub fn from(start: C) -> Self { - Self { - start: Box::new(start), - middle: None, - end: None, - pos_end: None, - pos_middle: None, - pos_start: None, - } - } - - pub fn via(mut self, middle: C) -> Self { - self.middle = Some(Box::new(middle)); - self - } - - pub fn to(mut self, end: C) -> Self { - self.end = Some(Box::new(end)); - self - } - - pub fn step_start(mut self, percentage: u8) -> Self { - assert!(percentage <= 100, "Percentage should be under 100%"); - self.pos_start = Some(percentage); - self - } - - pub fn step_middle(mut self, percentage: u8) -> Self { - assert!(percentage <= 100, "Percentage should be under 100%"); - self.pos_middle = Some(percentage); - self - } - - pub fn step_end(mut self, percentage: u8) -> Self { - assert!(percentage <= 100, "Percentage should be under 100%"); - self.pos_end = Some(percentage); - self - } - - pub fn color_class(&self) -> Vec { - let mut classes = vec![format!("from-{}", self.start.color_class())]; - - if let Some(via) = &self.middle { - classes.push(format!("via-{}", via.color_class())); - } - - if let Some(end) = &self.end { - classes.push(format!("to-{}", end.color_class())); - } - - if let Some(step) = &self.pos_start { - classes.push(format!("from-{step}%")); - } - - if let Some(step) = &self.pos_middle { - classes.push(format!("via-{step}%")); - } - - if let Some(step) = &self.pos_end { - classes.push(format!("to-{step}%")); - } - - classes - } -} diff --git a/src/ui/components/appbar.rs b/src/ui/components/appbar.rs index 8145568..50fbbb8 100644 --- a/src/ui/components/appbar.rs +++ b/src/ui/components/appbar.rs @@ -38,8 +38,9 @@ impl UIWidget for AppBarWidget { } fn render_with_class(&self, _: &str) -> Markup { - Padding(Shadow::medium( - Background(Header( + Padding(Shadow::medium(Background( + Gray::_800, + Header( Padding( Flex( Div() @@ -69,9 +70,8 @@ impl UIWidget for AppBarWidget { .items_center(), ) .x(ScreenValue::_6), - )) - .color(Gray::_800), - )) + ), + ))) .y(ScreenValue::_2) .render() } diff --git a/src/ui/components/shell.rs b/src/ui/components/shell.rs index 2bc0396..bdcca62 100644 --- a/src/ui/components/shell.rs +++ b/src/ui/components/shell.rs @@ -1,7 +1,5 @@ use maud::{PreEscaped, html}; -// TODO : refactor shell - /// Represents the HTML structure of a page shell, including the head, body class, and body content. /// /// This structure is used to construct the overall HTML structure of a page, making it easier to generate consistent HTML pages dynamically. diff --git a/src/ui/mod.rs b/src/ui/mod.rs index ab1717d..602b811 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,5 +1,6 @@ use components::Shell; -use maud::{Markup, PreEscaped, Render, html}; +use maud::{Markup, PreEscaped, Render}; +use prelude::Text; // UI @@ -16,26 +17,15 @@ pub mod components; pub mod prelude { pub use super::color::*; pub use super::primitives::Context; - pub use super::primitives::NoBrowserAppearance; pub use super::primitives::Nothing; pub use super::primitives::Side; pub use super::primitives::Size; pub use super::primitives::animation::{Animated, Animation, Delay, Duration, Scope, Timing}; pub use super::primitives::aspect::Aspect; pub use super::primitives::background::Background; - pub use super::primitives::border::{ - Border, BorderSide, BorderSize, BorderStyle, Outline, OutlineStyle, Ring, - }; pub use super::primitives::container::Container; - pub use super::primitives::cursor::{Action, Cursor, TouchAction}; - pub use super::primitives::display::{ - BoxDecorationBreak, BoxSizing, BreakAfter, BreakBefore, BreakInside, BreakInsideValue, - BreakValue, Clear, Display, Float, ObjectFit, Overflow, - }; + pub use super::primitives::cursor::Cursor; pub use super::primitives::div::Div; - pub use super::primitives::filter::{ - Blur, Brightness, Contrast, Grayscale, HueRotate, Invert, Saturate, Sepia, - }; pub use super::primitives::flex::{ Direction, Flex, FlexBasis, FlexGrow, Justify, Order, Strategy, Wrap, }; @@ -45,20 +35,16 @@ pub mod prelude { pub use super::primitives::link::Link; pub use super::primitives::margin::Margin; pub use super::primitives::padding::Padding; - pub use super::primitives::position::{Position, PositionKind, Resize, Resizeable}; pub use super::primitives::rounded::Rounded; pub use super::primitives::script; - pub use super::primitives::scroll::{Overscroll, Scroll, SnapAlign, SnapType}; pub use super::primitives::shadow::Shadow; pub use super::primitives::sized::Sized; pub use super::primitives::space::{ScreenValue, SpaceBetween}; - pub use super::primitives::svg::SVG; pub use super::primitives::text::{ - AccentColor, Code, DecorationKind, DecorationStyle, DecorationThickness, LetterSpacing, - LineClamp, LineHeight, ListStyle, NumberStyle, Paragraph, Span, Text, TextAlignment, - TextContent, TextCursorColor, TextDecoration, TextHyphens, TextOverflow, TextSelection, - TextTransform, TextWhitespace, TextWordBreak, TextWrap, UnderlineOffset, - VerticalTextAlignment, + Code, DecorationKind, DecorationStyle, DecorationThickness, LetterSpacing, LineClamp, + LineHeight, ListStyle, NumberStyle, Paragraph, Span, Text, TextAlignment, TextContent, + TextDecoration, TextHyphens, TextOverflow, TextTransform, TextWhitespace, TextWordBreak, + TextWrap, UnderlineOffset, VerticalTextAlignment, }; pub use super::primitives::transform::{ RenderTransformCPU, RenderTransformGPU, Rotate, Scale, Skew, Transform, TransformOrigin, @@ -153,37 +139,37 @@ impl UIWidget for PreEscaped { impl UIWidget for String { fn can_inherit(&self) -> bool { - false + Text(&self).can_inherit() } fn base_class(&self) -> Vec { - Vec::new() + Text(&self).base_class() } fn extended_class(&self) -> Vec { - Vec::new() + Text(&self).extended_class() } - fn render_with_class(&self, _: &str) -> Markup { - html!((self)) + fn render_with_class(&self, class: &str) -> Markup { + Text(&self).render_with_class(class) } } impl UIWidget for &str { fn can_inherit(&self) -> bool { - false + Text(&self).can_inherit() } fn base_class(&self) -> Vec { - Vec::new() + Text(&self).base_class() } fn extended_class(&self) -> Vec { - Vec::new() + Text(&self).extended_class() } - fn render_with_class(&self, _: &str) -> Markup { - html!((self)) + fn render_with_class(&self, class: &str) -> Markup { + Text(&self).render_with_class(class) } } diff --git a/src/ui/primitives/background.rs b/src/ui/primitives/background.rs index dbd000f..e07503e 100644 --- a/src/ui/primitives/background.rs +++ b/src/ui/primitives/background.rs @@ -1,98 +1,16 @@ use maud::{Markup, Render, html}; -use crate::ui::{ - UIWidget, - color::{Gradient, UIColor}, -}; +use crate::ui::{UIWidget, color::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 fn Background( + color: C, + inner: T, +) -> BackgroundWidget { + BackgroundWidget(Box::new(inner), Box::new(color)) } -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 - } -} +pub struct BackgroundWidget(Box, Box); impl Render for BackgroundWidget { fn render(&self) -> Markup { @@ -106,49 +24,7 @@ impl UIWidget for BackgroundWidget { } 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 + vec![format!("bg-{}", self.1.color_class())] } fn extended_class(&self) -> Vec { @@ -171,151 +47,3 @@ impl UIWidget for BackgroundWidget { } } } - -/// 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", - } - } -} diff --git a/src/ui/primitives/border.rs b/src/ui/primitives/border.rs deleted file mode 100644 index c7e14c3..0000000 --- a/src/ui/primitives/border.rs +++ /dev/null @@ -1,397 +0,0 @@ -use maud::{Markup, Render, html}; - -use crate::ui::{UIWidget, color::UIColor}; - -pub enum BorderSize { - _0, - _2, - _4, - _8, -} - -impl BorderSize { - pub const fn to_value(&self) -> &str { - match self { - BorderSize::_0 => "0", - BorderSize::_2 => "2", - BorderSize::_4 => "4", - BorderSize::_8 => "8", - } - } -} - -pub enum BorderSide { - X, - Y, - Start, - End, - Top, - Right, - Bottom, - Left, -} - -impl BorderSide { - pub const fn to_value(&self) -> &str { - match self { - BorderSide::X => "x", - BorderSide::Y => "y", - BorderSide::Start => "s", - BorderSide::End => "e", - BorderSide::Top => "t", - BorderSide::Right => "r", - BorderSide::Bottom => "b", - BorderSide::Left => "l", - } - } -} - -pub enum BorderStyle { - Solid, - Dashed, - Dotted, - Double, - Hidden, - None, -} - -impl BorderStyle { - pub const fn to_value(&self) -> &str { - match self { - BorderStyle::Solid => "border-solid", - BorderStyle::Dashed => "border-dashed", - BorderStyle::Dotted => "border-dotted", - BorderStyle::Double => "border-double", - BorderStyle::Hidden => "border-hidden", - BorderStyle::None => "border-none", - } - } -} - -#[allow(non_snake_case)] -pub fn Border(inner: T) -> BorderWidget { - BorderWidget(Box::new(inner), None, None, None, None) -} - -pub struct BorderWidget( - Box, - Option, - Option, - Option>, - Option, -); - -impl BorderWidget { - #[must_use] - pub fn size(mut self, size: BorderSize) -> Self { - self.1 = Some(size); - self - } - - #[must_use] - pub const fn side(mut self, side: BorderSide) -> Self { - self.2 = Some(side); - self - } - - #[must_use] - pub const fn style(mut self, style: BorderStyle) -> Self { - self.4 = Some(style); - self - } - - #[must_use] - pub fn color(mut self, color: C) -> Self { - self.3 = Some(Box::new(color)); - self - } - - fn border_class(&self) -> String { - if let Some(side) = &self.2 { - if let Some(size) = &self.1 { - return format!("border-{}-{}", side.to_value(), size.to_value()); - } - } else if let Some(size) = &self.1 { - return format!("border-{}", size.to_value()); - } - - "border".to_owned() - } -} - -impl Render for BorderWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for BorderWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let mut ret = vec![self.border_class()]; - - if let Some(color) = &self.3 { - ret.push(format!("border-{}", color.color_class())); - } - - if let Some(style) = &self.4 { - ret.push(style.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()) - } - } - } - } -} - -pub enum OutlineStyle { - Solid, - Dashed, - Dotted, - Double, - None, -} - -impl OutlineStyle { - pub const fn to_value(&self) -> &str { - match self { - OutlineStyle::Solid => "outline", - OutlineStyle::Dashed => "outline-dashed", - OutlineStyle::Dotted => "outline-dotted", - OutlineStyle::Double => "outline-double", - OutlineStyle::None => "outline-none", - } - } -} - -#[allow(non_snake_case)] -pub fn Outline(width: u32, inner: T) -> OutlineWidget { - OutlineWidget(Box::new(inner), width, None, None, 0) -} - -pub struct OutlineWidget( - Box, - u32, - Option>, - Option, - u32, -); - -impl OutlineWidget { - #[must_use] - pub const fn offset(mut self, offset: u32) -> Self { - self.4 = offset; - self - } - - #[must_use] - pub const fn style(mut self, style: OutlineStyle) -> Self { - self.3 = Some(style); - self - } - - #[must_use] - pub fn color(mut self, color: C) -> Self { - self.2 = Some(Box::new(color)); - self - } -} - -impl Render for OutlineWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for OutlineWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let class = match self.1 { - 0 => "outline-0", - 1 => "outline-1", - 2 => "outline-2", - 4 => "outline-4", - 8 => "outline-8", - _ => &format!("outline-[{}px]", self.1), - }; - - let mut ret = vec![class.to_string()]; - - if let Some(color) = &self.2 { - ret.push(format!("outline-{}", color.color_class())); - } - - if let Some(style) = &self.3 { - ret.push(style.to_value().to_string()); - } - - ret.push(match self.4 { - 0 => "outline-offset-0".to_string(), - 1 => "outline-offset-1".to_string(), - 2 => "outline-offset-2".to_string(), - 4 => "outline-offset-4".to_string(), - 8 => "outline-offset-8".to_string(), - _ => format!("outline-offset-[{}px]", self.4), - }); - - 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()) - } - } - } - } -} - -#[allow(non_snake_case)] -pub fn Ring(width: u32, inner: T) -> RingWidget { - RingWidget(Box::new(inner), width, None, false, 0, None) -} - -pub struct RingWidget( - // Inner - Box, - // Size - u32, - // Color - Option>, - // Inset - bool, - // Offset Width - u32, - // Offset Color - Option>, -); - -impl RingWidget { - #[must_use] - pub const fn inset(mut self) -> Self { - self.3 = true; - self - } - - #[must_use] - pub const fn offset_width(mut self, offset: u32) -> Self { - self.4 = offset; - self - } - - #[must_use] - pub fn offset_color(mut self, color: C) -> Self { - self.5 = Some(Box::new(color)); - self - } - - #[must_use] - pub fn color(mut self, color: C) -> Self { - self.2 = Some(Box::new(color)); - self - } -} - -impl Render for RingWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for RingWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let class = match self.1 { - 0 => "ring-0", - 1 => "ring-1", - 2 => "ring-2", - 4 => "ring-4", - 8 => "ring-8", - _ => &format!("ring-[{}px]", self.1), - }; - - let mut ret = vec![class.to_string()]; - - if let Some(color) = &self.2 { - ret.push(format!("ring-{}", color.color_class())); - } - - if self.3 { - ret.push("ring-inset".to_string()); - } - - ret.push(match self.4 { - 0 => "ring-offset-0".to_string(), - 1 => "ring-offset-1".to_string(), - 2 => "ring-offset-2".to_string(), - 4 => "ring-offset-4".to_string(), - 8 => "ring-offset-8".to_string(), - _ => format!("ring-offset-[{}px]", self.4), - }); - - if let Some(color) = &self.5 { - ret.push(format!("ring-offset-{}", color.color_class())); - } - - 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()) - } - } - } - } -} diff --git a/src/ui/primitives/cursor.rs b/src/ui/primitives/cursor.rs index d6d5141..1ab521e 100644 --- a/src/ui/primitives/cursor.rs +++ b/src/ui/primitives/cursor.rs @@ -122,76 +122,3 @@ impl UIWidget for CursorWidget { } } } - -#[allow(non_snake_case)] -pub fn TouchAction(action: Action, inner: T) -> TouchActionWidget { - TouchActionWidget(Box::new(inner), action) -} - -pub struct TouchActionWidget(Box, Action); - -impl Render for TouchActionWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for TouchActionWidget { - fn can_inherit(&self) -> bool { - false - } - - fn base_class(&self) -> Vec { - vec![self.1.to_value().to_string()] - } - - 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()) - } - } - } - } -} - -pub enum Action { - Auto, - None, - PanX, - PanLeft, - PanRight, - PanY, - PanUp, - PanDown, - PinchZoom, - Manipulation, -} - -impl Action { - pub const fn to_value(&self) -> &str { - match self { - Action::Auto => "touch-auto", - Action::None => "touch-none", - Action::PanX => "touch-pan-x", - Action::PanLeft => "touch-pan-left", - Action::PanRight => "touch-pan-right", - Action::PanY => "touch-pan-y", - Action::PanUp => "touch-pan-up", - Action::PanDown => "touch-pan-down", - Action::PinchZoom => "touch-pinch-zoom", - Action::Manipulation => "touch-manipulation", - } - } -} diff --git a/src/ui/primitives/display.rs b/src/ui/primitives/display.rs deleted file mode 100644 index 287bd59..0000000 --- a/src/ui/primitives/display.rs +++ /dev/null @@ -1,314 +0,0 @@ -use crate::ui::UIWidget; -use maud::{Markup, Render, html}; - -macro_rules! string_class_widget { - ($name:ident) => { - pub struct $name(Box, String); - - impl Render for $name { - fn render(&self) -> Markup { - self.render_with_class("") - } - } - - impl UIWidget for $name { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - vec![self.1.clone()] - } - - 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()) - } - } - } - } - } - }; -} - -macro_rules! constructor { - ($name:ident, $class:literal) => { - #[allow(non_snake_case)] - pub fn $name(inner: T) -> Self { - Self(Box::new(inner), $class.to_string()) - } - }; -} - -pub enum BreakValue { - Auto, - Avoid, - All, - AvoidPage, - Page, - Left, - Right, - Column, -} - -impl BreakValue { - pub const fn to_value(&self) -> &str { - match self { - BreakValue::Auto => "auto", - BreakValue::Avoid => "avoid", - BreakValue::All => "all", - BreakValue::AvoidPage => "break-page", - BreakValue::Page => "page", - BreakValue::Left => "left", - BreakValue::Right => "right", - BreakValue::Column => "column", - } - } -} - -#[allow(non_snake_case)] -pub fn BreakAfter(value: BreakValue, inner: T) -> BreakWidget { - BreakWidget(Box::new(inner), false, value) -} - -#[allow(non_snake_case)] -pub fn BreakBefore(value: BreakValue, inner: T) -> BreakWidget { - BreakWidget(Box::new(inner), true, value) -} - -pub struct BreakWidget(Box, bool, BreakValue); - -impl Render for BreakWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for BreakWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - if self.1 { - vec![format!("break-before-{}", self.2.to_value())] - } else { - vec![format!("break-after-{}", self.2.to_value())] - } - } - - 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()) - } - } - } - } -} - -pub enum BreakInsideValue { - Auto, - Avoid, - AvoidPage, - AvoidColumn, -} - -impl BreakInsideValue { - pub const fn to_value(&self) -> &str { - match self { - BreakInsideValue::Auto => "break-inside-auto", - BreakInsideValue::Avoid => "break-inside-avoid", - BreakInsideValue::AvoidPage => "break-inside-avoid-page", - BreakInsideValue::AvoidColumn => "break-inside-avoid-column", - } - } -} - -#[allow(non_snake_case)] -pub fn BreakInside(value: BreakValue, inner: T) -> BreakWidget { - BreakWidget(Box::new(inner), true, value) -} - -pub struct BreakInsideWidget(Box, BreakValue); - -impl Render for BreakInsideWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for BreakInsideWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - vec![self.1.to_value().to_string()] - } - - 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()) - } - } - } - } -} - -string_class_widget!(BoxDecorationBreak); - -impl BoxDecorationBreak { - constructor!(Clone, "box-decoration-clone"); - constructor!(Slice, "box-decoration-slice"); -} - -string_class_widget!(BoxSizing); - -impl BoxSizing { - constructor!(Border, "box-border"); - constructor!(Content, "box-content"); -} - -string_class_widget!(Display); - -impl Display { - constructor!(Block, "block"); - constructor!(InlineBlock, "inline-block"); - constructor!(Inline, "inline"); - constructor!(Flex, "flex"); - constructor!(InlineFlex, "inline-flex"); - constructor!(Table, "table"); - constructor!(InlineTable, "inline-table"); - constructor!(TableCaption, "table-caption"); - constructor!(TableCell, "table-cell"); - constructor!(TableColumn, "table-column"); - constructor!(TableColumnGroup, "table-column-group"); - constructor!(TableFooterGroup, "table-footer-group"); - constructor!(TableHeaderGroup, "table-header-group"); - constructor!(TableRowGroup, "table-row-group"); - constructor!(TableRow, "table-row"); - constructor!(FlowRoot, "flow-root"); - constructor!(Grid, "grid"); - constructor!(InlineGrid, "inline-grid"); - constructor!(Contents, "contents"); - constructor!(ListItem, "list-item"); - constructor!(Hidden, "hidden"); -} - -string_class_widget!(Float); - -impl Float { - constructor!(Start, "float-start"); - constructor!(End, "float-end"); - constructor!(Left, "float-left"); - constructor!(Right, "float-right"); - constructor!(None, "float-none"); -} - -string_class_widget!(Clear); - -impl Clear { - constructor!(Start, "clear-start"); - constructor!(End, "clear-end"); - constructor!(Left, "clear-left"); - constructor!(Right, "clear-right"); - constructor!(Both, "clear-both"); - constructor!(None, "clear-none"); -} - -string_class_widget!(ObjectFit); - -impl ObjectFit { - constructor!(Contain, "object-contain"); - constructor!(Cover, "object-cover"); - constructor!(Fill, "object-fill"); - constructor!(None, "object-none"); - constructor!(ScaleDown, "object-scale-down"); -} - -string_class_widget!(Overflow); - -impl Overflow { - constructor!(Auto, "overflow-auto"); - constructor!(Hidden, "overflow-hidden"); - constructor!(Clip, "overflow-clip"); - constructor!(Visible, "overflow-visible"); - constructor!(Scroll, "overflow-scroll"); - constructor!(XAuto, "overflow-x-auto"); - constructor!(YAuto, "overflow-y-auto"); - constructor!(XHidden, "overflow-x-hidden"); - constructor!(YHidden, "overflow-y-hidden"); - constructor!(XClip, "overflow-x-clip"); - constructor!(YClip, "overflow-y-clip"); - constructor!(XVisible, "overflow-x-visible"); - constructor!(YVisible, "overflow-y-visible"); - constructor!(XScroll, "overflow-x-scroll"); - constructor!(YScroll, "overflow-y-scroll"); -} - -string_class_widget!(JustifySelf); - -impl JustifySelf { - constructor!(Auto, "justify-self-auto"); - constructor!(Start, "justify-self-start"); - constructor!(End, "justify-self-end"); - constructor!(Center, "justify-self-center"); - constructor!(Stretch, "justify-self-stretch"); -} - -string_class_widget!(PlaceSelf); - -impl PlaceSelf { - constructor!(Auto, "place-self-auto"); - constructor!(Start, "place-self-start"); - constructor!(End, "place-self-end"); - constructor!(Center, "place-self-center"); - constructor!(Stretch, "place-self-stretch"); -} - -string_class_widget!(AlignSelf); - -impl AlignSelf { - constructor!(Auto, "self-auto"); - constructor!(Start, "self-start"); - constructor!(End, "self-end"); - constructor!(Center, "self-center"); - constructor!(Stretch, "self-stretch"); - constructor!(Baseline, "self-baseline"); -} diff --git a/src/ui/primitives/filter.rs b/src/ui/primitives/filter.rs deleted file mode 100644 index 3218387..0000000 --- a/src/ui/primitives/filter.rs +++ /dev/null @@ -1,479 +0,0 @@ -use crate::ui::UIWidget; -use maud::{Markup, Render, html}; - -use super::Size; - -#[allow(non_snake_case)] -pub fn Blur(amount: Size, inner: T) -> BlurWidget { - BlurWidget(Box::new(inner), amount, false) -} - -pub struct BlurWidget(Box, Size, bool); - -impl BlurWidget { - pub fn backdrop(mut self) -> Self { - self.2 = true; - self - } -} - -impl Render for BlurWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for BlurWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let class = match &self.1 { - Size::Custom(s) => &format!(" blur-[{s}]"), - Size::None => "blur-none", - Size::Small => "blur-sm", - Size::Regular => "blur", - Size::Medium => "blur-md", - Size::Large => "blur-lg", - Size::XL => "blur-xl", - Size::_2XL => "blur-2xl", - Size::_3XL => "blur-3xl", - Size::Full => "blur-3xl", - }; - - if self.2 { - return vec![format!("backdrop-{class}")]; - } - - vec![class.to_string()] - } - - 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()) - } - } - } - } -} - -macro_rules! build_value_widget { - ($constr:ident, $widget:ident, $class:literal) => { - #[allow(non_snake_case)] - pub fn $constr(value: f64, inner: T) -> $widget { - $widget(Box::new(inner), value, false) - } - - pub struct $widget(Box, f64, bool); - - impl $widget { - pub fn backdrop(mut self) -> Self { - self.2 = true; - self - } - } - - impl Render for $widget { - fn render(&self) -> Markup { - self.render_with_class("") - } - } - - impl UIWidget for $widget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let mut ret = $class.to_string(); - ret.push_str(&format!("-[{:.2}]", self.1)); - - if self.2 { - return vec![format!("backdrop-{ret}")]; - } - - vec![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()) - } - } - } - } - } - }; -} - -build_value_widget!(Brightness, BrightnessWidget, "brightness"); -build_value_widget!(Contrast, ConstrastWidget, "contrast"); -build_value_widget!(Saturate, SaturationWidget, "saturate"); - -macro_rules! build_on_off_widget { - ($constr:ident, $widget:ident, $class:literal) => { - #[allow(non_snake_case)] - pub fn $constr(inner: T) -> $widget { - $widget(Box::new(inner), true, false) - } - - pub struct $widget(Box, bool, bool); - - impl $widget { - pub fn none(mut self) -> Self { - self.1 = false; - self - } - - pub fn backdrop(mut self) -> Self { - self.2 = true; - self - } - } - - impl Render for $widget { - fn render(&self) -> Markup { - self.render_with_class("") - } - } - - impl UIWidget for $widget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let class = if self.1 { - $class.to_string() - } else { - concat!($class, "-0").to_string() - }; - - if self.2 { - return vec![format!("backdrop-{class}")]; - } - - vec![class] - } - - 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()) - } - } - } - } - } - }; -} - -build_on_off_widget!(Grayscale, GrayscaleWidget, "grayscale"); -build_on_off_widget!(Invert, InvertWidget, "invert"); -build_on_off_widget!(Sepia, SepiaWidget, "sepia"); - -#[allow(non_snake_case)] -pub fn HueRotate(deg: u32, inner: T) -> HueRotateWidget { - HueRotateWidget(Box::new(inner), deg, false) -} - -pub struct HueRotateWidget(Box, u32, bool); - -impl HueRotateWidget { - pub fn backdrop(mut self) -> Self { - self.2 = true; - self - } -} - -impl Render for HueRotateWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for HueRotateWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let class = format!("hue-rotate-[{:.2}deg]", self.1); - - if self.2 { - return vec![format!("backdrop-{class}")]; - } - - vec![class] - } - - 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()) - } - } - } - } -} - -#[allow(non_snake_case)] -pub fn Opacity(value: f64, inner: T) -> OpacityWidget { - OpacityWidget(Box::new(inner), value, false) -} - -pub struct OpacityWidget(Box, f64, bool); - -impl OpacityWidget { - pub fn backdrop(mut self) -> Self { - self.2 = true; - self - } -} - -impl Render for OpacityWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for OpacityWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let class = match self.1 { - 0.0 => "opacity-0", - 0.05 => "opacity-5", - 0.1 => "opacity-10", - 0.15 => "opacity-15", - 0.2 => "opacity-20", - 0.25 => "opacity-25", - 0.3 => "opacity-30", - 0.35 => "opacity-35", - 0.4 => "opacity-40", - 0.45 => "opacity-45", - 0.5 => "opacity-50", - 0.55 => "opacity-55", - 0.6 => "opacity-60", - 0.65 => "opacity-65", - 0.7 => "opacity-70", - 0.75 => "opacity-75", - 0.8 => "opacity-80", - 0.85 => "opacity-85", - 0.9 => "opacity-90", - 0.95 => "opacity-95", - 1.0 => "opacity-100", - _ => &format!("opacity-[{:.2}]", self.1), - }; - - if self.2 { - return vec![format!("backdrop-{class}")]; - } - - vec![class.to_string()] - } - - 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()) - } - } - } - } -} - -pub enum BlendMode { - Normal, - Multiply, - Screen, - Overlay, - Darken, - Lighten, - ColorDodge, - ColorBurn, - HardLight, - SoftLight, - Difference, - Exclusion, - Hue, - Saturation, - Color, - Luminosity, - PlusDarker, - PlusLighter, -} - -impl BlendMode { - pub const fn to_value(&self) -> &str { - match self { - BlendMode::Normal => "normal", - BlendMode::Multiply => "multiply", - BlendMode::Screen => "screen", - BlendMode::Overlay => "overlay", - BlendMode::Darken => "darken", - BlendMode::Lighten => "lighten", - BlendMode::ColorDodge => "color-dodge", - BlendMode::ColorBurn => "color-burn", - BlendMode::HardLight => "hard-light", - BlendMode::SoftLight => "soft-light", - BlendMode::Difference => "difference", - BlendMode::Exclusion => "exclusion", - BlendMode::Hue => "hue", - BlendMode::Saturation => "saturation", - BlendMode::Color => "color", - BlendMode::Luminosity => "luminosity", - BlendMode::PlusDarker => "plus-darker", - BlendMode::PlusLighter => "plus-lighter", - } - } -} - -#[allow(non_snake_case)] -pub fn MixBlendMode(mode: BlendMode, inner: T) -> MixBlendModeWidget { - MixBlendModeWidget(Box::new(inner), mode) -} - -pub struct MixBlendModeWidget(Box, BlendMode); - -impl Render for MixBlendModeWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for MixBlendModeWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - vec![format!("mix-blend-{}", self.1.to_value())] - } - - 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()) - } - } - } - } -} - -#[allow(non_snake_case)] -pub fn BackgroundBlendMode( - mode: BlendMode, - inner: T, -) -> BackgroundBlendModeWidget { - BackgroundBlendModeWidget(Box::new(inner), mode) -} - -pub struct BackgroundBlendModeWidget(Box, BlendMode); - -impl Render for BackgroundBlendModeWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for BackgroundBlendModeWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - vec![format!("bg-blend-{}", self.1.to_value())] - } - - 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()) - } - } - } - } -} diff --git a/src/ui/primitives/flex.rs b/src/ui/primitives/flex.rs index 35b231e..b662362 100644 --- a/src/ui/primitives/flex.rs +++ b/src/ui/primitives/flex.rs @@ -1,11 +1,11 @@ -use crate::ui::{UIWidget, color::UIColor}; +use crate::ui::UIWidget; use maud::{Markup, Render, html}; use super::space::{Fraction, ScreenValue}; #[allow(non_snake_case)] pub fn Flex(inner: T) -> FlexWidget { - FlexWidget(Box::new(inner), vec![], false, None) + FlexWidget(Box::new(inner), vec![], false) } pub enum Justify { @@ -19,7 +19,7 @@ pub enum Justify { Stretch, } -pub struct FlexWidget(Box, Vec, bool, Option); +pub struct FlexWidget(Box, Vec, bool); impl Render for FlexWidget { fn render(&self) -> Markup { @@ -41,65 +41,9 @@ impl FlexWidget { self } - #[must_use] - pub fn divide_style(mut self, style: DivideStyle) -> Self { - self.1.push(style.to_value().to_string()); - self - } - - #[must_use] - pub fn divide_color(mut self, color: C) -> Self { - self.1.push(format!("divide-{}", color.color_class())); - self - } - - #[must_use] - pub fn divide_x(mut self, width: DivideWidth) -> Self { - let reversed = self - .3 - .as_ref() - .map(|x| match x { - Direction::Row => false, - Direction::RowReverse => true, - Direction::Column => false, - Direction::ColumnReverse => true, - }) - .unwrap_or_default(); - - self.1.push(format!("divide-x-{}", width.to_value())); - - if reversed { - self.1.push("divide-x-reverse".to_string()); - } - - self - } - - #[must_use] - pub fn divide_y(mut self, width: DivideWidth) -> Self { - let reversed = self - .3 - .as_ref() - .map(|x| match x { - Direction::Row => false, - Direction::RowReverse => true, - Direction::Column => false, - Direction::ColumnReverse => true, - }) - .unwrap_or_default(); - - self.1.push(format!("divide-y-{}", width.to_value())); - - if reversed { - self.1.push("divide-y-reverse".to_string()); - } - - self - } - #[must_use] pub fn direction(mut self, direction: Direction) -> Self { - self.3 = Some(direction); + self.1.push(format!("flex-{}", direction.to_value())); self } @@ -109,24 +53,6 @@ impl FlexWidget { self } - #[must_use] - pub fn justify_items(mut self, justify: JustifyItems) -> Self { - self.1.push(justify.to_value().to_string()); - self - } - - #[must_use] - pub fn align_content(mut self, align: AlignContent) -> Self { - self.1.push(align.to_value().to_string()); - self - } - - #[must_use] - pub fn align_items(mut self, align: AlignItems) -> Self { - self.1.push(align.to_value().to_string()); - self - } - #[must_use] pub fn justify(mut self, value: Justify) -> Self { let class = match value { @@ -169,26 +95,6 @@ impl FlexWidget { } } -pub enum DivideWidth { - Custom(u64), - _0, - _2, - _4, - _8, -} - -impl DivideWidth { - pub fn to_value(&self) -> String { - match self { - DivideWidth::Custom(s) => format!("[{s}px]"), - DivideWidth::_0 => "0".to_string(), - DivideWidth::_2 => "2".to_string(), - DivideWidth::_4 => "4".to_string(), - DivideWidth::_8 => "8".to_string(), - } - } -} - pub enum Direction { Row, RowReverse, @@ -230,11 +136,6 @@ impl UIWidget for FlexWidget { fn base_class(&self) -> Vec { let mut res = vec!["flex".to_string()]; - - if let Some(direction) = &self.3 { - res.push(format!("flex-{}", direction.to_value())); - } - res.extend_from_slice(&self.1); res } @@ -498,89 +399,3 @@ impl UIWidget for OrderWidget { } } } - -pub enum DivideStyle { - Solid, - Dashed, - Dotted, - Double, - None, -} - -impl DivideStyle { - pub const fn to_value(&self) -> &str { - match self { - DivideStyle::Solid => "divide-solid", - DivideStyle::Dashed => "divide-dashed", - DivideStyle::Dotted => "divide-dotted", - DivideStyle::Double => "divide-double", - DivideStyle::None => "divide-none", - } - } -} - -pub enum JustifyItems { - Start, - End, - Center, - Stretch, -} - -impl JustifyItems { - pub const fn to_value(&self) -> &str { - match self { - JustifyItems::Start => "justify-items-start", - JustifyItems::End => "justify-items-end", - JustifyItems::Center => "justify-items-center", - JustifyItems::Stretch => "justify-items-stretch", - } - } -} - -pub enum AlignContent { - Normal, - Center, - Start, - End, - Between, - Around, - Evenly, - Baseline, - Stretch, -} - -impl AlignContent { - pub const fn to_value(&self) -> &str { - match self { - AlignContent::Normal => "content-normal", - AlignContent::Center => "content-center", - AlignContent::Start => "content-start", - AlignContent::End => "content-end", - AlignContent::Between => "content-between", - AlignContent::Around => "content-around", - AlignContent::Evenly => "content-evenly", - AlignContent::Baseline => "content-baseline", - AlignContent::Stretch => "content-stretch", - } - } -} - -pub enum AlignItems { - Start, - End, - Center, - Baseline, - Stretch, -} - -impl AlignItems { - pub const fn to_value(&self) -> &str { - match self { - AlignItems::Start => "items-start", - AlignItems::End => "items-end", - AlignItems::Center => "items-center", - AlignItems::Baseline => "items-baseline", - AlignItems::Stretch => "items-stretch", - } - } -} diff --git a/src/ui/primitives/grid.rs b/src/ui/primitives/grid.rs deleted file mode 100644 index cd1e345..0000000 --- a/src/ui/primitives/grid.rs +++ /dev/null @@ -1,461 +0,0 @@ -use crate::ui::{UIWidget, color::UIColor}; -use maud::{Markup, Render, html}; - -use super::{ - flex::{AlignContent, AlignItems, DivideStyle, DivideWidth, Justify, JustifyItems}, - space::ScreenValue, -}; - -#[allow(non_snake_case)] -pub fn Grid(inner: T) -> GridWidget { - GridWidget(Box::new(inner), vec![], false) -} - -pub struct GridWidget(Box, Vec, bool); - -impl Render for GridWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -pub enum GridAmount { - _1, - _2, - _3, - _4, - _5, - _6, - _7, - _8, - _9, - _10, - _11, - _12, - None, - Subgrid, -} - -impl GridAmount { - pub const fn to_value(&self) -> &str { - match self { - GridAmount::_1 => "1", - GridAmount::_2 => "2", - GridAmount::_3 => "3", - GridAmount::_4 => "4", - GridAmount::_5 => "5", - GridAmount::_6 => "6", - GridAmount::_7 => "7", - GridAmount::_8 => "8", - GridAmount::_9 => "9", - GridAmount::_10 => "10", - GridAmount::_11 => "11", - GridAmount::_12 => "12", - GridAmount::None => "none", - GridAmount::Subgrid => "subgrid", - } - } -} - -impl GridWidget { - #[must_use] - pub fn columns(mut self, amount: GridAmount) -> Self { - self.1.push(format!("grid-cols-{}", amount.to_value())); - self - } - - #[must_use] - pub fn rows(mut self, amount: GridAmount) -> Self { - self.1.push(format!("grid-rows-{}", amount.to_value())); - self - } - - #[must_use] - pub fn auto_flow(mut self, flow: GridAutoFlow) -> Self { - self.1.push(flow.to_value().to_string()); - self - } - - #[must_use] - pub fn auto_columns(mut self, size: GridAutoSize) -> Self { - self.1.push(format!("auto-cols-{}", size.to_value())); - self - } - - #[must_use] - pub fn auto_rows(mut self, size: GridAutoSize) -> Self { - self.1.push(format!("auto-rows-{}", size.to_value())); - self - } - - #[must_use] - pub fn full_center(mut self) -> Self { - self.1.push("items-center".to_owned()); - self.1.push("justify-center".to_owned()); - self - } - - #[must_use] - pub const fn group(mut self) -> Self { - self.2 = true; - self - } - - #[must_use] - pub fn divide_style(mut self, style: DivideStyle) -> Self { - self.1.push(style.to_value().to_string()); - self - } - - #[must_use] - pub fn divide_color(mut self, color: C) -> Self { - self.1.push(format!("divide-{}", color.color_class())); - self - } - - #[must_use] - pub fn divide_x(mut self, width: DivideWidth) -> Self { - self.1.push(format!("divide-x-{}", width.to_value())); - self - } - - #[must_use] - pub fn divide_y(mut self, width: DivideWidth) -> Self { - self.1.push(format!("divide-y-{}", width.to_value())); - self - } - - #[must_use] - pub fn justify_items(mut self, justify: JustifyItems) -> Self { - self.1.push(justify.to_value().to_string()); - self - } - - #[must_use] - pub fn align_content(mut self, align: AlignContent) -> Self { - self.1.push(align.to_value().to_string()); - self - } - - #[must_use] - pub fn align_items(mut self, align: AlignItems) -> Self { - self.1.push(align.to_value().to_string()); - self - } - - #[must_use] - pub fn justify(mut self, value: Justify) -> Self { - let class = match value { - Justify::Center => "justify-center".to_string(), - Justify::Between => "justify-between".to_string(), - Justify::Normal => "justify-normal".to_string(), - Justify::Start => "justify-start".to_string(), - Justify::End => "justify-end".to_string(), - Justify::Around => "justify-around".to_string(), - Justify::Evenly => "justify-evenly".to_string(), - Justify::Stretch => "justify-stretch".to_string(), - }; - - self.1.push(class); - self - } - - #[must_use] - pub fn items_center(mut self) -> Self { - self.1.push("items-center".to_owned()); - self - } - - #[must_use] - pub fn gap(mut self, amount: ScreenValue) -> Self { - self.1.push(format!("gap-{}", amount.to_value())); - self - } - - #[must_use] - pub fn gap_x(mut self, amount: ScreenValue) -> Self { - self.1.push(format!("gap-x-{}", amount.to_value())); - self - } - - #[must_use] - pub fn gap_y(mut self, amount: ScreenValue) -> Self { - self.1.push(format!("gap-y-{}", amount.to_value())); - self - } -} - -impl UIWidget for GridWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let mut res = vec!["grid".to_string()]; - res.extend_from_slice(&self.1); - res - } - - 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.2 { - 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()) - } - } - } - } -} - -pub enum GridAutoFlow { - Row, - Column, - Dense, - RowDense, - ColumnDense, -} - -impl GridAutoFlow { - pub const fn to_value(&self) -> &str { - match self { - GridAutoFlow::Row => "grid-flow-row", - GridAutoFlow::Column => "grid-flow-col", - GridAutoFlow::Dense => "grid-flow-dense", - GridAutoFlow::RowDense => "grid-flow-row-dense", - GridAutoFlow::ColumnDense => "grid-flow-col-dense", - } - } -} - -pub enum GridAutoSize { - Auto, - Min, - Max, - Fr, -} - -impl GridAutoSize { - pub const fn to_value(&self) -> &str { - match self { - GridAutoSize::Auto => "auto", - GridAutoSize::Min => "min", - GridAutoSize::Max => "max", - GridAutoSize::Fr => "fr", - } - } -} - -#[allow(non_snake_case)] -pub fn GridElementColumn(inner: T) -> GridElement { - GridElement(Box::new(inner), Vec::new(), "col".to_string()) -} - -#[allow(non_snake_case)] -pub fn GridElementRow(inner: T) -> GridElement { - GridElement(Box::new(inner), Vec::new(), "row".to_string()) -} - -pub struct GridElement(Box, Vec, String); - -impl GridElement { - pub fn auto(mut self) -> Self { - self.1.push(format!("{}-auto", self.2)); - self - } - - pub fn span(mut self, value: GridElementValue) -> Self { - self.1.push(format!("{}-span-{}", self.2, match value { - GridElementValue::_1 => "1", - GridElementValue::_2 => "2", - GridElementValue::_3 => "3", - GridElementValue::_4 => "4", - GridElementValue::_5 => "5", - GridElementValue::_6 => "6", - GridElementValue::_7 => "7", - GridElementValue::_8 => "8", - GridElementValue::_9 => "9", - GridElementValue::_10 => "10", - GridElementValue::_11 => "11", - GridElementValue::_12 => "12", - GridElementValue::Auto => "full", - })); - self - } - - pub fn start(mut self, value: GridElementValue) -> Self { - self.1 - .push(format!("{}-start-{}", self.2, value.to_value())); - self - } - - pub fn end(mut self, value: GridElementValue) -> Self { - self.1.push(format!("{}-end-{}", self.2, value.to_value())); - self - } -} - -impl Render for GridElement { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for GridElement { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let mut res = vec!["grid".to_string()]; - res.extend_from_slice(&self.1); - res - } - - 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()) - } - } - } - } -} - -pub enum GridElementValue { - _1, - _2, - _3, - _4, - _5, - _6, - _7, - _8, - _9, - _10, - _11, - _12, - Auto, -} - -impl GridElementValue { - pub const fn to_value(&self) -> &str { - match self { - GridElementValue::_1 => "1", - GridElementValue::_2 => "2", - GridElementValue::_3 => "3", - GridElementValue::_4 => "4", - GridElementValue::_5 => "5", - GridElementValue::_6 => "6", - GridElementValue::_7 => "7", - GridElementValue::_8 => "8", - GridElementValue::_9 => "9", - GridElementValue::_10 => "10", - GridElementValue::_11 => "11", - GridElementValue::_12 => "12", - GridElementValue::Auto => "auto", - } - } -} - -macro_rules! string_class_widget { - ($name:ident) => { - pub struct $name(Box, String); - - impl Render for $name { - fn render(&self) -> Markup { - self.render_with_class("") - } - } - - impl UIWidget for $name { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - vec![self.1.clone()] - } - - 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()) - } - } - } - } - } - }; -} - -macro_rules! constructor { - ($name:ident, $class:literal) => { - #[allow(non_snake_case)] - pub fn $name(inner: T) -> Self { - Self(Box::new(inner), $class.to_string()) - } - }; -} - -string_class_widget!(Columns); - -impl Columns { - constructor!(_1, "columns-1"); - constructor!(_2, "columns-2"); - constructor!(_3, "columns-3"); - constructor!(_4, "columns-4"); - constructor!(_5, "columns-5"); - constructor!(_6, "columns-6"); - constructor!(_7, "columns-7"); - constructor!(_8, "columns-8"); - constructor!(_9, "columns-9"); - constructor!(_10, "columns-10"); - constructor!(_11, "columns-11"); - constructor!(_12, "columns-12"); - constructor!(Auto, "columns-auto"); - constructor!(_3XS, "columns-3xs"); - constructor!(_2XS, "columns-2xs"); - constructor!(XS, "columns-xs"); - constructor!(Small, "columns-sm"); - constructor!(Medium, "columns-md"); - constructor!(Large, "columns-lg"); - constructor!(XL, "columns-xl"); - constructor!(_2XL, "columns-2xl"); - constructor!(_3XL, "columns-3xl"); - constructor!(_4XL, "columns-4xl"); - constructor!(_5XL, "columns-5xl"); - constructor!(_6XL, "columns-6xl"); - constructor!(_7XL, "columns-7xl"); -} diff --git a/src/ui/primitives/list.rs b/src/ui/primitives/list.rs deleted file mode 100644 index 630a766..0000000 --- a/src/ui/primitives/list.rs +++ /dev/null @@ -1,103 +0,0 @@ -use crate::ui::UIWidget; -use maud::{Markup, Render, html}; - -#[allow(non_snake_case)] -#[must_use] -pub fn OrderedList() -> ListWidget { - ListWidget(Vec::new(), true) -} - -#[allow(non_snake_case)] -#[must_use] -pub fn UnorderedList() -> ListWidget { - ListWidget(Vec::new(), false) -} - -pub struct ListWidget(Vec>, bool); - -impl ListWidget { - #[must_use] - pub fn push(mut self, element: T) -> Self { - self.0.push(Box::new(element)); - self - } - - #[must_use] - pub fn push_some T>( - mut self, - option: Option, - then: U, - ) -> Self { - if let Some(val) = option { - self.0.push(Box::new(then(val))); - } - self - } - - #[must_use] - pub fn push_if T>( - mut self, - condition: bool, - then: U, - ) -> Self { - if condition { - self.0.push(Box::new(then())); - } - self - } - - #[must_use] - pub fn push_for_each(mut self, items: &[X], mut action: F) -> Self - where - T: UIWidget + 'static, - F: FnMut(&X) -> T, - { - for item in items { - self.0.push(Box::new(action(item))); - } - - self - } -} - -impl Render for ListWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for ListWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - vec![] - } - - fn extended_class(&self) -> Vec { - vec![] - } - - fn render_with_class(&self, class: &str) -> Markup { - let inner = html! { - @for e in &self.0 { - li { (e.as_ref()) }; - } - }; - - if self.1 { - html! { - ol class=(class) { - (inner); - } - } - } else { - html! { - ul class=(class) { - (inner); - } - } - } - } -} diff --git a/src/ui/primitives/mod.rs b/src/ui/primitives/mod.rs index d2d21f5..0e1c096 100644 --- a/src/ui/primitives/mod.rs +++ b/src/ui/primitives/mod.rs @@ -1,33 +1,25 @@ +use maud::{PreEscaped, html}; + use super::UIWidget; -use maud::{Markup, PreEscaped, Render, html}; pub mod animation; pub mod aspect; pub mod background; -pub mod border; pub mod container; pub mod cursor; -pub mod display; pub mod div; -pub mod filter; pub mod flex; -pub mod grid; pub mod header; pub mod height; pub mod image; pub mod input; pub mod link; -pub mod list; pub mod margin; pub mod padding; -pub mod position; pub mod rounded; -pub mod scroll; pub mod shadow; pub mod sized; pub mod space; -pub mod svg; -pub mod table; pub mod text; pub mod transform; pub mod visibility; @@ -70,7 +62,6 @@ pub fn script(script: &str) -> PreEscaped { } pub enum Size { - Custom(String), None, Small, Regular, @@ -86,7 +77,6 @@ impl Size { #[must_use] pub const fn to_value(&self) -> &str { match self { - Self::Custom(str) => str.as_str(), Self::None => "none", Self::Small => "sm", Self::Regular => "", @@ -140,46 +130,3 @@ impl Side { } } } - -#[allow(non_snake_case)] -pub fn NoBrowserAppearance(inner: T) -> NoBrowserAppearanceWidget { - NoBrowserAppearanceWidget(Box::new(inner)) -} - -pub struct NoBrowserAppearanceWidget(Box); - -impl Render for NoBrowserAppearanceWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for NoBrowserAppearanceWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - vec!["appearance-none".to_string()] - } - - 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!("appearance-none {class}")) - } else { - html! { - div class=(format!("appearance-none {class}")) { - (self.0.as_ref()) - } - } - } - } -} diff --git a/src/ui/primitives/position.rs b/src/ui/primitives/position.rs deleted file mode 100644 index 2019981..0000000 --- a/src/ui/primitives/position.rs +++ /dev/null @@ -1,341 +0,0 @@ -use maud::{Markup, Render, html}; - -use crate::ui::UIWidget; - -use super::Side; - -#[allow(non_snake_case)] -pub fn Position(kind: PositionKind, inner: T) -> Positioned { - Positioned { - inner: Box::new(inner), - kind, - inset: None, - inset_x: None, - inset_y: None, - start: None, - end: None, - top: None, - right: None, - bottom: None, - left: None, - } -} - -pub struct Positioned { - inner: Box, - kind: PositionKind, - inset: Option, - inset_x: Option, - inset_y: Option, - start: Option, - end: Option, - top: Option, - right: Option, - bottom: Option, - left: Option, -} - -impl Positioned { - pub fn inset(mut self, value: i64) -> Self { - self.inset = Some(value); - self - } - pub fn inset_x(mut self, value: i64) -> Self { - self.inset_x = Some(value); - self - } - - pub fn inset_y(mut self, value: i64) -> Self { - self.inset_y = Some(value); - self - } - - pub fn start(mut self, value: i64) -> Self { - self.start = Some(value); - self - } - - pub fn end(mut self, value: i64) -> Self { - self.end = Some(value); - self - } - - pub fn top(mut self, value: i64) -> Self { - self.top = Some(value); - self - } - - pub fn right(mut self, value: i64) -> Self { - self.right = Some(value); - self - } - - pub fn bottom(mut self, value: i64) -> Self { - self.bottom = Some(value); - self - } - - pub fn left(mut self, value: i64) -> Self { - self.left = Some(value); - self - } -} - -impl Render for Positioned { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for Positioned { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let mut ret = vec![self.kind.to_value().to_string()]; - - if let Some(inset) = &self.inset { - if inset.is_negative() { - ret.push(format!("-inset-[{inset}px]")); - } else { - ret.push(format!("inset-[{inset}px]")); - } - } - - if let Some(inset) = &self.inset_x { - if inset.is_negative() { - ret.push(format!("-inset-x-[{inset}px]")); - } else { - ret.push(format!("inset-x-[{inset}px]")); - } - } - - if let Some(inset) = &self.inset_y { - if inset.is_negative() { - ret.push(format!("-inset-y-[{inset}px]")); - } else { - ret.push(format!("inset-y-[{inset}px]")); - } - } - - if let Some(start) = &self.start { - if start.is_negative() { - ret.push(format!("-start-[{start}px]")); - } else { - ret.push(format!("start-[{start}px]")); - } - } - - if let Some(end) = &self.end { - if end.is_negative() { - ret.push(format!("-end-[{end}px]")); - } else { - ret.push(format!("end-[{end}px]")); - } - } - - if let Some(value) = &self.top { - if value.is_negative() { - ret.push(format!("-top-[{value}px]")); - } else { - ret.push(format!("top-[{value}px]")); - } - } - - if let Some(value) = &self.right { - if value.is_negative() { - ret.push(format!("-right-[{value}px]")); - } else { - ret.push(format!("right-[{value}px]")); - } - } - - if let Some(value) = &self.bottom { - if value.is_negative() { - ret.push(format!("-bottom-[{value}px]")); - } else { - ret.push(format!("bottom-[{value}px]")); - } - } - - if let Some(value) = &self.left { - if value.is_negative() { - ret.push(format!("-left-[{value}px]")); - } else { - ret.push(format!("left-[{value}px]")); - } - } - - ret - } - - fn extended_class(&self) -> Vec { - let mut c = self.base_class(); - c.extend_from_slice(&self.inner.extended_class()); - c - } - - fn render_with_class(&self, class: &str) -> Markup { - if self.inner.as_ref().can_inherit() { - self.inner - .as_ref() - .render_with_class(&format!("{} {class}", self.base_class().join(" "))) - } else { - html! { - div class=(format!("{} {class}", self.base_class().join(" "))) { - (self.inner.as_ref()) - } - } - } - } -} - -pub enum PositionKind { - Static, - Fixed, - Absolute, - Relative, - Sticky, -} - -impl PositionKind { - pub const fn to_value(&self) -> &str { - match self { - PositionKind::Static => "static", - PositionKind::Fixed => "fixed", - PositionKind::Absolute => "absolute", - PositionKind::Relative => "relative", - PositionKind::Sticky => "sticky", - } - } -} - -#[allow(non_snake_case)] -pub fn ObjectPosition(side: Side, inner: T) -> ObjectPositioned { - ObjectPositioned { - inner: Box::new(inner), - side, - } -} - -pub struct ObjectPositioned { - inner: Box, - side: Side, -} - -impl Render for ObjectPositioned { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for ObjectPositioned { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - vec![ - match self.side { - Side::Start => "object-top", - Side::End => "object-bottom", - Side::Top => "object-top", - Side::Right => "object-right", - Side::Bottom => "object-bottom", - Side::Left => "object-left", - Side::StartStart => "object-left-top", - Side::StartEnd => "object-right-top", - Side::EndEnd => "object-right-bottom", - Side::EndStart => "object-left-bottom", - Side::TopLeft => "object-left-top", - Side::TopRight => "object-right-top", - Side::BottomRight => "object-right-bottom", - Side::BottomLeft => "object-left-bottom", - Side::Center => "object-center", - } - .to_string(), - ] - } - - fn extended_class(&self) -> Vec { - let mut c = self.base_class(); - c.extend_from_slice(&self.inner.extended_class()); - c - } - - fn render_with_class(&self, class: &str) -> Markup { - if self.inner.as_ref().can_inherit() { - self.inner - .as_ref() - .render_with_class(&format!("{} {class}", self.base_class().join(" "))) - } else { - html! { - div class=(format!("{} {class}", self.base_class().join(" "))) { - (self.inner.as_ref()) - } - } - } - } -} - -pub enum Resize { - None, - Y, - X, - Both, -} - -impl Resize { - pub const fn to_value(&self) -> &str { - match self { - Resize::None => "resize-none", - Resize::Y => "resize-y", - Resize::X => "resize-x", - Resize::Both => "resize", - } - } -} - -#[allow(non_snake_case)] -pub fn Resizeable(mode: Resize, inner: T) -> ResizeableWidget { - ResizeableWidget(Box::new(inner), mode) -} - -pub struct ResizeableWidget(Box, Resize); - -impl Render for ResizeableWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for ResizeableWidget { - fn can_inherit(&self) -> bool { - false - } - - fn base_class(&self) -> Vec { - vec![self.1.to_value().to_string()] - } - - 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()) - } - } - } - } -} diff --git a/src/ui/primitives/rounded.rs b/src/ui/primitives/rounded.rs index d448fe3..f716814 100644 --- a/src/ui/primitives/rounded.rs +++ b/src/ui/primitives/rounded.rs @@ -12,7 +12,7 @@ pub struct RoundedWidget(Box, Option, Option); impl RoundedWidget { #[must_use] - pub fn size(mut self, size: Size) -> Self { + pub const fn size(mut self, size: Size) -> Self { self.1 = Some(size); self } diff --git a/src/ui/primitives/scroll.rs b/src/ui/primitives/scroll.rs deleted file mode 100644 index 720ffe2..0000000 --- a/src/ui/primitives/scroll.rs +++ /dev/null @@ -1,234 +0,0 @@ -use super::{margin::Margin, padding::PaddingWidget}; -use crate::ui::UIWidget; -use maud::{Markup, Render, html}; - -#[allow(non_snake_case)] -pub fn Scroll(inner: T) -> ScrollWidget { - ScrollWidget(Box::new(inner), true, None, None, None, None, false) -} - -pub struct ScrollWidget( - Box, - bool, - Option, - Option, - Option, - Option, - bool, -); - -impl ScrollWidget { - pub fn smooth(mut self, value: bool) -> Self { - self.1 = value; - self - } - - pub fn scroll_margin(mut self, margin: Margin) -> Self { - self.2 = Some(margin); - self - } - - pub fn scroll_padding(mut self, padding: PaddingWidget) -> Self { - self.3 = Some(padding); - self - } - - pub fn overscroll(mut self, behaviour: Overscroll) -> Self { - self.4 = Some(behaviour); - self - } - - pub fn snap(mut self, kind: SnapType) -> Self { - self.5 = Some(kind); - self - } - - pub fn skip_snap(mut self) -> Self { - self.6 = true; - self - } -} - -impl Render for ScrollWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for ScrollWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - let mut ret = Vec::new(); - - if self.1 { - ret.push("scroll-smooth".to_string()); - } - - if let Some(margin) = &self.2 { - let classes = margin - .base_class() - .into_iter() - .map(|x| format!("scroll-{x}")) - .collect::>(); - ret.extend_from_slice(&classes); - } - - if let Some(padding) = &self.3 { - let classes = padding - .base_class() - .into_iter() - .map(|x| format!("scroll-{x}")) - .collect::>(); - ret.extend_from_slice(&classes); - } - - if let Some(overscroll) = &self.4 { - ret.push(overscroll.to_value().to_string()); - } - - if let Some(snap) = &self.5 { - ret.push(snap.to_value().to_string()); - } - - if self.6 { - ret.push("snap-normal".to_string()); - } else { - ret.push("snap-always".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()) - } - } - } - } -} - -pub enum Overscroll { - Auto, - Contain, - None, - YAuto, - YContain, - YNone, - XAuto, - XContain, - XNone, -} - -impl Overscroll { - pub const fn to_value(&self) -> &str { - match self { - Overscroll::Auto => "overscroll-auto", - Overscroll::Contain => "overscroll-contain", - Overscroll::None => "overscroll-none", - Overscroll::YAuto => "overscroll-y-auto", - Overscroll::YContain => "overscroll-y-contain", - Overscroll::YNone => "overscroll-y-none", - Overscroll::XAuto => "overscroll-x-auto", - Overscroll::XContain => "overscroll-x-contain", - Overscroll::XNone => "overscroll-x-none", - } - } -} - -pub enum SnapType { - None, - X, - Y, - Both, - Mandatory, - Proximity, -} - -impl SnapType { - pub const fn to_value(&self) -> &str { - match self { - SnapType::None => "snap-none", - SnapType::X => "snap-x", - SnapType::Y => "snap-y", - SnapType::Both => "snap-both", - SnapType::Mandatory => "snap-mandatory", - SnapType::Proximity => "snap-proximity", - } - } -} - -pub struct SnapAlign(Box, String); - -impl SnapAlign { - #[allow(non_snake_case)] - pub fn Start(inner: T) -> Self { - Self(Box::new(inner), "snap-start".to_string()) - } - - #[allow(non_snake_case)] - pub fn End(inner: T) -> Self { - Self(Box::new(inner), "snap-end".to_string()) - } - - #[allow(non_snake_case)] - pub fn Center(inner: T) -> Self { - Self(Box::new(inner), "snap-center".to_string()) - } - - #[allow(non_snake_case)] - pub fn None(inner: T) -> Self { - Self(Box::new(inner), "snap-align-none".to_string()) - } -} - -impl Render for SnapAlign { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for SnapAlign { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - vec![self.1.clone()] - } - - 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()) - } - } - } - } -} diff --git a/src/ui/primitives/shadow.rs b/src/ui/primitives/shadow.rs index 5e3cc64..92f2323 100644 --- a/src/ui/primitives/shadow.rs +++ b/src/ui/primitives/shadow.rs @@ -1,46 +1,35 @@ -use crate::ui::{UIWidget, color::UIColor}; +use crate::ui::UIWidget; use maud::{Markup, Render, html}; -pub struct Shadow(Box, String, Option>); +pub struct Shadow(Box, String); impl Shadow { + pub fn medium(inner: T) -> Self { + Self(Box::new(inner), "md".to_owned()) + } + pub fn small(inner: T) -> Self { - Self(Box::new(inner), "sm".to_owned(), None) + Self(Box::new(inner), "sm".to_owned()) } pub fn regular(inner: T) -> Self { - Self(Box::new(inner), String::new(), None) - } - - pub fn medium(inner: T) -> Self { - Self(Box::new(inner), "md".to_owned(), None) + Self(Box::new(inner), String::new()) } pub fn large(inner: T) -> Self { - Self(Box::new(inner), "lg".to_owned(), None) - } - - pub fn xl(inner: T) -> Self { - Self(Box::new(inner), "xl".to_owned(), None) - } - - pub fn _2xl(inner: T) -> Self { - Self(Box::new(inner), "2xl".to_owned(), None) - } - - pub fn inner(inner: T) -> Self { - Self(Box::new(inner), "inner".to_owned(), None) + Self(Box::new(inner), "lg".to_owned()) } pub fn none(inner: T) -> Self { - Self(Box::new(inner), "none".to_owned(), None) + Self(Box::new(inner), "none".to_owned()) } -} -impl Shadow { - pub fn color(mut self, color: C) -> Self { - self.2 = Some(Box::new(color)); - self + pub fn xl(inner: T) -> Self { + Self(Box::new(inner), "xl".to_owned()) + } + + pub fn _2xl(inner: T) -> Self { + Self(Box::new(inner), "2xl".to_owned()) } } @@ -56,17 +45,11 @@ impl UIWidget for Shadow { } fn base_class(&self) -> Vec { - let mut ret = if self.1.is_empty() { + if self.1.is_empty() { vec!["shadow".to_string()] } else { vec![format!("shadow-{}", self.1)] - }; - - if let Some(color) = &self.2 { - ret.push(format!("shadow-{}", color.color_class())); } - - ret } fn extended_class(&self) -> Vec { diff --git a/src/ui/primitives/svg.rs b/src/ui/primitives/svg.rs deleted file mode 100644 index 79de1cf..0000000 --- a/src/ui/primitives/svg.rs +++ /dev/null @@ -1,76 +0,0 @@ -use maud::{Markup, Render, html}; - -use crate::ui::{UIWidget, color::UIColor}; - -#[allow(non_snake_case)] -pub fn SVG(inner: T) -> SVGWidget { - SVGWidget(Box::new(inner), None, None, None) -} - -pub struct SVGWidget( - Box, - Option>, - Option>, - Option, -); - -impl SVGWidget { - pub fn fill(mut self, color: C) -> Self { - self.1 = Some(Box::new(color)); - self - } - - pub fn stroke(mut self, color: C) -> Self { - self.2 = Some(Box::new(color)); - self - } - - pub fn stroke_width(mut self, width: u32) -> Self { - self.3 = Some(width); - self - } -} - -impl Render for SVGWidget { - fn render(&self) -> Markup { - self.render_with_class("") - } -} - -impl UIWidget for SVGWidget { - fn can_inherit(&self) -> bool { - false - } - - fn base_class(&self) -> Vec { - let mut ret = vec![]; - - if let Some(fill) = &self.1 { - ret.push(format!("fill-{}", fill.color_class())); - } - - if let Some(stroke) = &self.2 { - ret.push(format!("stroke-{}", stroke.color_class())); - } - - if let Some(stroke_width) = &self.3 { - ret.push(format!("stroke-[{stroke_width}px]")); - } - - 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, _: &str) -> Markup { - html! { - svg class=(self.base_class().join(" ")) { - (self.0.as_ref()) - } - } - } -} diff --git a/src/ui/primitives/table.rs b/src/ui/primitives/table.rs deleted file mode 100644 index 60bf8a6..0000000 --- a/src/ui/primitives/table.rs +++ /dev/null @@ -1,204 +0,0 @@ -use maud::{Markup, Render, html}; - -use crate::ui::UIWidget; - -use super::{div::Div, space::ScreenValue}; - -#[allow(non_snake_case)] -pub fn Table(inner: Vec>) -> TableWidget { - let inner = Div().vanish().push_for_each(&inner, |row| { - TableRow( - Div() - .vanish() - .push_for_each(&row, |col| TableData(col.clone())), - ) - }); - - TableWidget(Box::new(inner), Vec::new(), None, None) -} - -pub struct TableWidget( - Box, - Vec, - Option>, - Option, -); - -impl TableWidget { - pub fn header(mut self, header: T) -> Self { - self.2 = Some(Box::new(header)); - self - } - - pub fn caption(mut self, caption: Caption) -> Self { - self.3 = Some(caption); - self - } - - pub fn border_collapse(mut self) -> Self { - self.1.push("border-collapse".to_string()); - self - } - - pub fn border_seperate(mut self) -> Self { - self.1.push("border-separate".to_string()); - self - } - - pub fn border_spacing(mut self, spacing: ScreenValue) -> Self { - self.1 - .push(format!("border-spacing-{}", spacing.to_value())); - self - } - - pub fn border_spacing_x(mut self, spacing: ScreenValue) -> Self { - self.1 - .push(format!("border-spacing-x-{}", spacing.to_value())); - self - } - - pub fn border_spacing_y(mut self, spacing: ScreenValue) -> Self { - self.1 - .push(format!("border-spacing-y-{}", spacing.to_value())); - self - } - - pub fn layout_fixed(mut self) -> Self { - self.1.push("table-fixed".to_string()); - self - } - - pub fn layout_auto(mut self) -> Self { - self.1.push("table-auto".to_string()); - self - } -} - -impl Render for TableWidget { - fn render(&self) -> maud::Markup { - self.render_with_class("") - } -} - -impl UIWidget for TableWidget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - self.1.clone() - } - - fn extended_class(&self) -> Vec { - self.base_class() - } - - fn render_with_class(&self, class: &str) -> maud::Markup { - html! { - table class=(format!("{} {class}", self.base_class().join(" "))) { - @if let Some(caption) = &self.3 { - (caption) - } - - @if let Some(header) = &self.2 { - thead { - (header) - }; - }; - - (self.0.as_ref()) - }; - } - } -} - -pub struct Caption(Box, bool); - -impl Caption { - #[allow(non_snake_case)] - pub fn Top(inner: T) -> Self { - Self(Box::new(inner), true) - } - - #[allow(non_snake_case)] - pub fn Bottom(inner: T) -> Self { - Self(Box::new(inner), false) - } -} - -impl Render for Caption { - fn render(&self) -> maud::Markup { - self.render_with_class("") - } -} - -impl UIWidget for Caption { - fn can_inherit(&self) -> bool { - false - } - - fn base_class(&self) -> Vec { - if self.1 { - vec!["caption-top".to_string()] - } else { - vec!["caption-bottom".to_string()] - } - } - - fn extended_class(&self) -> Vec { - self.base_class() - } - - fn render_with_class(&self, _: &str) -> maud::Markup { - html! { - caption class=(self.base_class().join(" ")) { - (self.0.as_ref()) - }; - } - } -} - -macro_rules! element_widget { - ($name:ident, $widget:ident, $element:ident) => { - #[allow(non_snake_case)] - pub fn $name(inner: T) -> $widget { - $widget(Box::new(inner)) - } - - pub struct $widget(Box); - - impl Render for $widget { - fn render(&self) -> Markup { - self.render_with_class("") - } - } - - impl UIWidget for $widget { - fn can_inherit(&self) -> bool { - true - } - - fn base_class(&self) -> Vec { - Vec::new() - } - - 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 { - html! { - $element class=(class) { - (self.0.as_ref()) - } - } - } - } - }; -} - -element_widget!(TableRow, TableRowWidget, tr); -element_widget!(TableHead, TableHeadWidget, th); -element_widget!(TableData, TableDataWidget, td); diff --git a/src/ui/primitives/text.rs b/src/ui/primitives/text.rs index 43befe7..5230a1f 100644 --- a/src/ui/primitives/text.rs +++ b/src/ui/primitives/text.rs @@ -1,5 +1,5 @@ use crate::ui::{UIWidget, color::UIColor}; -use maud::{Markup, PreEscaped, Render, html}; +use maud::{Markup, PreEscaped, Render}; use super::{Nothing, space::ScreenValue}; @@ -31,7 +31,6 @@ pub fn Text(txt: &str) -> TextWidget { align: None, vert_align: None, list_style: None, - select: None, kind: TextKind::Paragraph, } } @@ -69,7 +68,6 @@ pub fn Paragraph(inner: T) -> TextWidget { list_style: None, clamp: None, align: None, - select: None, kind: TextKind::Paragraph, } } @@ -102,7 +100,6 @@ pub fn Span(txt: &str) -> TextWidget { clamp: None, align: None, pseudo: None, - select: None, kind: TextKind::Span, } } @@ -135,7 +132,6 @@ pub fn Code(txt: &str) -> TextWidget { clamp: None, align: None, pseudo: None, - select: None, kind: TextKind::Pre, } } @@ -164,17 +160,10 @@ pub struct TextWidget { pseudo: Option, align: Option, clamp: Option, - select: Option, title: Option, } impl TextWidget { - #[must_use] - pub fn select(mut self, select: TextSelection) -> Self { - self.select = Some(select); - self - } - #[must_use] pub fn whitespace(mut self, whitespace: TextWhitespace) -> Self { self.whitespace = Some(whitespace); @@ -538,7 +527,6 @@ impl UIWidget for TextWidget { add_option!(list_style, ret); add_option!(pseudo, ret); add_option!(line_height, ret); - add_option!(select, ret); if let Some(decoration) = &self.decoration { ret.extend_from_slice(&decoration.base_class()); @@ -1073,73 +1061,3 @@ impl TextHyphens { } } } - -pub enum TextSelection { - None, - Text, - All, - Auto, -} - -impl TextSelection { - pub const fn to_value(&self) -> &str { - match self { - TextSelection::None => "select-none", - TextSelection::Text => "select-text", - TextSelection::All => "select-all", - TextSelection::Auto => "select-auto ", - } - } -} - -macro_rules! color_widget { - ($constr:ident, $widget:ident, $class:literal) => { - #[allow(non_snake_case)] - pub fn $constr(color: C, inner: T) -> $widget { - $widget(Box::new(inner), Box::new(color)) - } - - pub struct $widget(Box, Box); - - impl Render for $widget { - fn render(&self) -> Markup { - self.render_with_class("") - } - } - - impl UIWidget for $widget { - fn can_inherit(&self) -> bool { - false - } - - fn base_class(&self) -> Vec { - let mut class = $class.to_string(); - class.push_str(&format!("-{}", self.1.color_class())); - vec![class] - } - - 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()) - } - } - } - } - } - }; -} - -color_widget!(TextCursorColor, CaretColorWidget, "caret"); -color_widget!(AccentColor, AccentColorWidget, "accent"); diff --git a/src/ui/wrapper/mod.rs b/src/ui/wrapper/mod.rs index 06654a3..4fac146 100644 --- a/src/ui/wrapper/mod.rs +++ b/src/ui/wrapper/mod.rs @@ -74,29 +74,6 @@ macro_rules! wrapper { } wrapper!(Hover, HoverWrapper, "hover"); -wrapper!(DarkMode, DarkModeWrapper, "dark"); -wrapper!(Active, ActiveWrapper, "active"); -wrapper!(Focus, FocusWrapper, "focus"); -wrapper!(First, FirstWrapper, "first"); -wrapper!(Odd, OddWrapper, "odd"); -wrapper!(Even, EvenWrapper, "even"); - -wrapper!(Required, RequiredWrapper, "required"); -wrapper!(Invalid, InvalidWrapper, "invalid"); -wrapper!(Disabled, DisabledWrapper, "disabled"); -wrapper!(Placeholder, PlaceholderWrapper, "placeholder"); -wrapper!(FileButton, FileButtonWrapper, "file"); -wrapper!(Marker, MarkerWrapper, "marker"); -wrapper!(Selection, SelectionWrapper, "selection"); -wrapper!(FirstLine, FirstLineWrapper, "first-line"); -wrapper!(FirstLetter, FirstLetterWrapper, "first-letter"); - -wrapper!(Portrait, PortraitWrapper, "portrait"); -wrapper!(Landscape, LandscapeWrapper, "landscape"); -wrapper!(Print, PrintWrapper, "print"); -wrapper!(LeftToRight, LeftToRightWrapper, "ltr"); -wrapper!(RightToLeft, RightToLeftWrapper, "rtl"); -wrapper!(Opened, OpenWrapper, "open"); wrapper!(SmallScreen, SmallScreenWrapper, "sm"); wrapper!(MediumScreen, MediumScreenWrapper, "md");