update + text
This commit is contained in:
parent
340f014365
commit
bf72429ac5
6 changed files with 703 additions and 19 deletions
|
@ -12,6 +12,10 @@ pub mod ui;
|
||||||
|
|
||||||
// Postgres
|
// Postgres
|
||||||
|
|
||||||
|
// TODO : IDEA
|
||||||
|
// more efficient table join using WHERE ANY instead of multiple SELECTs
|
||||||
|
// map_tables(Vec<T>, Fn(&T) -> U) -> Vec<U>
|
||||||
|
|
||||||
pub static PG: OnceCell<sqlx::PgPool> = OnceCell::const_new();
|
pub static PG: OnceCell<sqlx::PgPool> = OnceCell::const_new();
|
||||||
|
|
||||||
/// A macro to retrieve or initialize the `PostgreSQL` connection pool.
|
/// A macro to retrieve or initialize the `PostgreSQL` connection pool.
|
||||||
|
|
|
@ -39,7 +39,12 @@ pub mod prelude {
|
||||||
pub use super::primitives::shadow::Shadow;
|
pub use super::primitives::shadow::Shadow;
|
||||||
pub use super::primitives::sized::Sized;
|
pub use super::primitives::sized::Sized;
|
||||||
pub use super::primitives::space::{ScreenValue, SpaceBetween};
|
pub use super::primitives::space::{ScreenValue, SpaceBetween};
|
||||||
pub use super::primitives::text::{Paragraph, Span, Text};
|
pub use super::primitives::text::{
|
||||||
|
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::visibility::Visibility;
|
pub use super::primitives::visibility::Visibility;
|
||||||
pub use super::primitives::width::{MaxWidth, MinWidth, Width};
|
pub use super::primitives::width::{MaxWidth, MinWidth, Width};
|
||||||
pub use super::primitives::zindex::ZIndex;
|
pub use super::primitives::zindex::ZIndex;
|
||||||
|
|
|
@ -67,6 +67,7 @@ impl DivWidget {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo : Fix weird types
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn push_for_each<
|
pub fn push_for_each<
|
||||||
T: UIWidget + 'static,
|
T: UIWidget + 'static,
|
||||||
|
|
|
@ -1,24 +1,36 @@
|
||||||
use crate::ui::UIWidget;
|
use crate::ui::UIWidget;
|
||||||
use maud::{Markup, Render, html};
|
use maud::{Markup, Render, html};
|
||||||
|
|
||||||
use super::space::ScreenValue;
|
use super::{
|
||||||
|
flex::Either,
|
||||||
|
space::{Fraction, ScreenValue},
|
||||||
|
};
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn Height<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> HeightWidget {
|
pub fn Height<T: UIWidget + 'static>(
|
||||||
|
size: Either<ScreenValue, Fraction>,
|
||||||
|
inner: T,
|
||||||
|
) -> HeightWidget {
|
||||||
HeightWidget(Box::new(inner), size, 0)
|
HeightWidget(Box::new(inner), size, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn MinHeight<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> HeightWidget {
|
pub fn MinHeight<T: UIWidget + 'static>(
|
||||||
|
size: Either<ScreenValue, Fraction>,
|
||||||
|
inner: T,
|
||||||
|
) -> HeightWidget {
|
||||||
HeightWidget(Box::new(inner), size, 1)
|
HeightWidget(Box::new(inner), size, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn MaxHeight<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> HeightWidget {
|
pub fn MaxHeight<T: UIWidget + 'static>(
|
||||||
|
size: Either<ScreenValue, Fraction>,
|
||||||
|
inner: T,
|
||||||
|
) -> HeightWidget {
|
||||||
HeightWidget(Box::new(inner), size, 2)
|
HeightWidget(Box::new(inner), size, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HeightWidget(Box<dyn UIWidget>, ScreenValue, u8);
|
pub struct HeightWidget(Box<dyn UIWidget>, Either<ScreenValue, Fraction>, u8);
|
||||||
|
|
||||||
impl Render for HeightWidget {
|
impl Render for HeightWidget {
|
||||||
fn render(&self) -> Markup {
|
fn render(&self) -> Markup {
|
||||||
|
@ -34,15 +46,27 @@ impl UIWidget for HeightWidget {
|
||||||
fn base_class(&self) -> Vec<String> {
|
fn base_class(&self) -> Vec<String> {
|
||||||
match self.2 {
|
match self.2 {
|
||||||
1 => {
|
1 => {
|
||||||
return vec![format!("min-h-{}", self.1.to_value())];
|
return vec![format!(
|
||||||
|
"min-h-{}",
|
||||||
|
self.1
|
||||||
|
.map(|x| x.to_value().to_string(), |x| x.to_value().to_string())
|
||||||
|
)];
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
return vec![format!("max-h-{}", self.1.to_value())];
|
return vec![format!(
|
||||||
|
"max-h-{}",
|
||||||
|
self.1
|
||||||
|
.map(|x| x.to_value().to_string(), |x| x.to_value().to_string())
|
||||||
|
)];
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
vec![format!("h-{}", self.1.to_value())]
|
vec![format!(
|
||||||
|
"h-{}",
|
||||||
|
self.1
|
||||||
|
.map(|x| x.to_value().to_string(), |x| x.to_value().to_string())
|
||||||
|
)]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extended_class(&self) -> Vec<String> {
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::ui::{UIWidget, color::UIColor};
|
use crate::ui::{UIWidget, color::UIColor};
|
||||||
use maud::{Markup, Render, html};
|
use maud::{Markup, Render, html};
|
||||||
|
|
||||||
|
use super::{Nothing, space::ScreenValue};
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
/// Text UI Widget
|
/// Text UI Widget
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -13,6 +15,21 @@ pub fn Text(txt: &str) -> TextWidget {
|
||||||
color: String::new(),
|
color: String::new(),
|
||||||
style: Vec::new(),
|
style: Vec::new(),
|
||||||
size: String::new(),
|
size: String::new(),
|
||||||
|
line_height: None,
|
||||||
|
overflow: None,
|
||||||
|
wrap: None,
|
||||||
|
indent: None,
|
||||||
|
transform: None,
|
||||||
|
decoration: None,
|
||||||
|
whitespace: None,
|
||||||
|
wordbreak: None,
|
||||||
|
hyphens: None,
|
||||||
|
spacing: None,
|
||||||
|
clamp: None,
|
||||||
|
pseudo: None,
|
||||||
|
align: None,
|
||||||
|
vert_align: None,
|
||||||
|
list_style: None,
|
||||||
span: false,
|
span: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +45,21 @@ pub fn Paragraph<T: UIWidget + 'static>(inner: T) -> TextWidget {
|
||||||
txt: String::new(),
|
txt: String::new(),
|
||||||
style: Vec::new(),
|
style: Vec::new(),
|
||||||
size: String::new(),
|
size: String::new(),
|
||||||
|
indent: None,
|
||||||
|
overflow: None,
|
||||||
|
decoration: None,
|
||||||
|
whitespace: None,
|
||||||
|
wordbreak: None,
|
||||||
|
hyphens: None,
|
||||||
|
wrap: None,
|
||||||
|
spacing: None,
|
||||||
|
transform: None,
|
||||||
|
pseudo: None,
|
||||||
|
vert_align: None,
|
||||||
|
line_height: None,
|
||||||
|
list_style: None,
|
||||||
|
clamp: None,
|
||||||
|
align: None,
|
||||||
span: false,
|
span: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +75,22 @@ pub fn Span(txt: &str) -> TextWidget {
|
||||||
font: String::new(),
|
font: String::new(),
|
||||||
style: Vec::new(),
|
style: Vec::new(),
|
||||||
color: String::new(),
|
color: String::new(),
|
||||||
|
list_style: None,
|
||||||
size: String::new(),
|
size: String::new(),
|
||||||
|
indent: None,
|
||||||
|
overflow: None,
|
||||||
|
whitespace: None,
|
||||||
|
wordbreak: None,
|
||||||
|
hyphens: None,
|
||||||
|
decoration: None,
|
||||||
|
transform: None,
|
||||||
|
wrap: None,
|
||||||
|
vert_align: None,
|
||||||
|
spacing: None,
|
||||||
|
line_height: None,
|
||||||
|
clamp: None,
|
||||||
|
align: None,
|
||||||
|
pseudo: None,
|
||||||
span: true,
|
span: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,11 +102,44 @@ pub struct TextWidget {
|
||||||
style: Vec<String>,
|
style: Vec<String>,
|
||||||
font: String,
|
font: String,
|
||||||
color: String,
|
color: String,
|
||||||
|
list_style: Option<ListStyle>,
|
||||||
|
line_height: Option<LineHeight>,
|
||||||
|
decoration: Option<DecorationWidget>,
|
||||||
|
transform: Option<TextTransform>,
|
||||||
|
vert_align: Option<VerticalTextAlignment>,
|
||||||
|
overflow: Option<TextOverflow>,
|
||||||
|
indent: Option<ScreenValue>,
|
||||||
|
wrap: Option<TextWrap>,
|
||||||
|
whitespace: Option<TextWhitespace>,
|
||||||
|
wordbreak: Option<TextWordBreak>,
|
||||||
|
hyphens: Option<TextHyphens>,
|
||||||
size: String,
|
size: String,
|
||||||
span: bool,
|
span: bool,
|
||||||
|
spacing: Option<LetterSpacing>,
|
||||||
|
pseudo: Option<TextContent>,
|
||||||
|
align: Option<TextAlignment>,
|
||||||
|
clamp: Option<LineClamp>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextWidget {
|
impl TextWidget {
|
||||||
|
#[must_use]
|
||||||
|
pub fn whitespace(mut self, whitespace: TextWhitespace) -> Self {
|
||||||
|
self.whitespace = Some(whitespace);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn wordbreak(mut self, wordbreak: TextWordBreak) -> Self {
|
||||||
|
self.wordbreak = Some(wordbreak);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn hyphen(mut self, hyphen: TextHyphens) -> Self {
|
||||||
|
self.hyphens = Some(hyphen);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
// Weight
|
// Weight
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -137,12 +217,78 @@ impl TextWidget {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn wrap(mut self, wrap: TextWrap) -> Self {
|
||||||
|
self.wrap = Some(wrap);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn indentation(mut self, indent: ScreenValue) -> Self {
|
||||||
|
self.indent = Some(indent);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn align(mut self, alignment: TextAlignment) -> Self {
|
||||||
|
self.align = Some(alignment);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn align_vertical(mut self, alignment: VerticalTextAlignment) -> Self {
|
||||||
|
self.vert_align = Some(alignment);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn transform(mut self, transform: TextTransform) -> Self {
|
||||||
|
self.transform = Some(transform);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn number_style(mut self, s: NumberStyle) -> Self {
|
pub fn number_style(mut self, s: NumberStyle) -> Self {
|
||||||
self.style.push(s.to_value().to_string());
|
self.style.push(s.to_value().to_string());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn overflow(mut self, overflow: TextOverflow) -> Self {
|
||||||
|
self.overflow = Some(overflow);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn max_lines(mut self, l: LineClamp) -> Self {
|
||||||
|
self.clamp = Some(l);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn decoration(mut self, decoration: DecorationWidget) -> Self {
|
||||||
|
self.decoration = Some(decoration);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn list_style(mut self, style: ListStyle) -> Self {
|
||||||
|
self.list_style = Some(style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn content(mut self, content: TextContent) -> Self {
|
||||||
|
self.pseudo = Some(content);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn line_height(mut self, height: LineHeight) -> Self {
|
||||||
|
self.line_height = Some(height);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
// Sizes
|
// Sizes
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -291,12 +437,48 @@ impl UIWidget for TextWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_class(&self) -> Vec<String> {
|
fn base_class(&self) -> Vec<String> {
|
||||||
vec![
|
let mut ret = vec![
|
||||||
self.color.clone(),
|
self.color.clone(),
|
||||||
self.font.clone(),
|
self.font.clone(),
|
||||||
self.size.clone(),
|
self.size.clone(),
|
||||||
self.family.clone(),
|
self.family.clone(),
|
||||||
]
|
];
|
||||||
|
|
||||||
|
macro_rules! add_option {
|
||||||
|
($opt:ident, $ret:ident) => {
|
||||||
|
if let Some($opt) = &self.$opt {
|
||||||
|
$ret.push($opt.to_value().to_string());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
add_option!(spacing, ret);
|
||||||
|
|
||||||
|
if let Some(indent) = &self.indent {
|
||||||
|
ret.push(format!("indent-{}", indent.to_value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
add_option!(clamp, ret);
|
||||||
|
add_option!(align, ret);
|
||||||
|
add_option!(vert_align, ret);
|
||||||
|
add_option!(list_style, ret);
|
||||||
|
add_option!(pseudo, ret);
|
||||||
|
add_option!(line_height, ret);
|
||||||
|
|
||||||
|
if let Some(decoration) = &self.decoration {
|
||||||
|
ret.extend_from_slice(&decoration.base_class());
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.extend_from_slice(&self.style);
|
||||||
|
|
||||||
|
add_option!(transform, ret);
|
||||||
|
add_option!(overflow, ret);
|
||||||
|
add_option!(wrap, ret);
|
||||||
|
add_option!(whitespace, ret);
|
||||||
|
add_option!(wordbreak, ret);
|
||||||
|
add_option!(hyphens, ret);
|
||||||
|
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extended_class(&self) -> Vec<String> {
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
@ -357,3 +539,450 @@ impl NumberStyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum LetterSpacing {
|
||||||
|
Tighter,
|
||||||
|
Tight,
|
||||||
|
Normal,
|
||||||
|
Wide,
|
||||||
|
Wider,
|
||||||
|
Widest,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LetterSpacing {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
LetterSpacing::Tighter => "tracking-tighter",
|
||||||
|
LetterSpacing::Tight => "tracking-tight",
|
||||||
|
LetterSpacing::Normal => "tracking-normal",
|
||||||
|
LetterSpacing::Wide => "tracking-wide",
|
||||||
|
LetterSpacing::Wider => "tracking-wider",
|
||||||
|
LetterSpacing::Widest => "tracking-widest",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum LineClamp {
|
||||||
|
None,
|
||||||
|
_1,
|
||||||
|
_2,
|
||||||
|
_3,
|
||||||
|
_4,
|
||||||
|
_5,
|
||||||
|
_6,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LineClamp {
|
||||||
|
pub fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
LineClamp::None => "line-clamp-none",
|
||||||
|
LineClamp::_1 => "line-clamp-1",
|
||||||
|
LineClamp::_2 => "line-clamp-2",
|
||||||
|
LineClamp::_3 => "line-clamp-3",
|
||||||
|
LineClamp::_4 => "line-clamp-4",
|
||||||
|
LineClamp::_5 => "line-clamp-5",
|
||||||
|
LineClamp::_6 => "line-clamp-6",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TextAlignment {
|
||||||
|
Left,
|
||||||
|
Center,
|
||||||
|
Right,
|
||||||
|
Justify,
|
||||||
|
Start,
|
||||||
|
End,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextAlignment {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
TextAlignment::Left => "text-left",
|
||||||
|
TextAlignment::Center => "text-center",
|
||||||
|
TextAlignment::Right => "text-right",
|
||||||
|
TextAlignment::Justify => "text-justify",
|
||||||
|
TextAlignment::Start => "text-start",
|
||||||
|
TextAlignment::End => "text-end",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ListStyle {
|
||||||
|
Url(String),
|
||||||
|
None,
|
||||||
|
Disc,
|
||||||
|
Decimal,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListStyle {
|
||||||
|
pub fn to_value(&self) -> String {
|
||||||
|
match self {
|
||||||
|
ListStyle::Url(url) => format!("list-image-[url({url})]"),
|
||||||
|
ListStyle::None => "list-none".to_string(),
|
||||||
|
ListStyle::Disc => "list-disc".to_string(),
|
||||||
|
ListStyle::Decimal => "list-decimal".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TextContent {
|
||||||
|
None,
|
||||||
|
Before(String),
|
||||||
|
After(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextContent {
|
||||||
|
pub fn to_value(&self) -> String {
|
||||||
|
match self {
|
||||||
|
TextContent::None => "content-none".to_string(),
|
||||||
|
TextContent::Before(c) => format!("before:content-['{c}']"),
|
||||||
|
TextContent::After(c) => format!("after:content-['{c}']"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum LineHeight {
|
||||||
|
_3,
|
||||||
|
_4,
|
||||||
|
_5,
|
||||||
|
_6,
|
||||||
|
_7,
|
||||||
|
_8,
|
||||||
|
_9,
|
||||||
|
_10,
|
||||||
|
None,
|
||||||
|
Tight,
|
||||||
|
Snug,
|
||||||
|
Normal,
|
||||||
|
Relaxed,
|
||||||
|
Loose,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LineHeight {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
LineHeight::_3 => "leading-3",
|
||||||
|
LineHeight::_4 => "leading-4",
|
||||||
|
LineHeight::_5 => "leading-5",
|
||||||
|
LineHeight::_6 => "leading-6",
|
||||||
|
LineHeight::_7 => "leading-7",
|
||||||
|
LineHeight::_8 => "leading-8",
|
||||||
|
LineHeight::_9 => "leading-9",
|
||||||
|
LineHeight::_10 => "leading-10",
|
||||||
|
LineHeight::None => "leading-none",
|
||||||
|
LineHeight::Tight => "leading-tight",
|
||||||
|
LineHeight::Snug => "leading-snug",
|
||||||
|
LineHeight::Normal => "leading-normal",
|
||||||
|
LineHeight::Relaxed => "leading-relaxed",
|
||||||
|
LineHeight::Loose => "leading-loose",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decoration
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn TextDecoration<T: UIWidget + 'static>(kind: DecorationKind) -> DecorationWidget {
|
||||||
|
DecorationWidget {
|
||||||
|
kind: kind.to_value().to_string(),
|
||||||
|
color: None,
|
||||||
|
style: None,
|
||||||
|
underline_offset: None,
|
||||||
|
thickness: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DecorationWidget {
|
||||||
|
kind: String,
|
||||||
|
color: Option<String>,
|
||||||
|
style: Option<DecorationStyle>,
|
||||||
|
thickness: Option<DecorationThickness>,
|
||||||
|
underline_offset: Option<UnderlineOffset>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DecorationWidget {
|
||||||
|
#[must_use]
|
||||||
|
pub fn thickness(mut self, thickness: DecorationThickness) -> Self {
|
||||||
|
self.thickness = Some(thickness);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn style(mut self, style: DecorationStyle) -> Self {
|
||||||
|
self.style = Some(style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn color<C: UIColor>(mut self, color: C) -> Self {
|
||||||
|
self.color = Some(format!("decoration-{}", color.color_class()));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn underline_offset(mut self, offset: UnderlineOffset) -> Self {
|
||||||
|
self.underline_offset = Some(offset);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DecorationKind {
|
||||||
|
Underline,
|
||||||
|
Overline,
|
||||||
|
LineThrough,
|
||||||
|
NoUnderline,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DecorationKind {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
DecorationKind::Underline => "underline",
|
||||||
|
DecorationKind::Overline => "overline",
|
||||||
|
DecorationKind::LineThrough => "line-through",
|
||||||
|
DecorationKind::NoUnderline => "no-underline",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DecorationThickness {
|
||||||
|
Auto,
|
||||||
|
FromFont,
|
||||||
|
_0,
|
||||||
|
_1,
|
||||||
|
_2,
|
||||||
|
_4,
|
||||||
|
_8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DecorationThickness {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
DecorationThickness::Auto => "decoration-auto",
|
||||||
|
DecorationThickness::FromFont => "decoration-from-font",
|
||||||
|
DecorationThickness::_0 => "decoration-0",
|
||||||
|
DecorationThickness::_1 => "decoration-1",
|
||||||
|
DecorationThickness::_2 => "decoration-2",
|
||||||
|
DecorationThickness::_4 => "decoration-4",
|
||||||
|
DecorationThickness::_8 => "decoration-8",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DecorationStyle {
|
||||||
|
Solid,
|
||||||
|
Double,
|
||||||
|
Dotted,
|
||||||
|
Dashed,
|
||||||
|
Wavy,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DecorationStyle {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
DecorationStyle::Solid => "decoration-solid",
|
||||||
|
DecorationStyle::Double => "decoration-double",
|
||||||
|
DecorationStyle::Dotted => "decoration-dotted",
|
||||||
|
DecorationStyle::Dashed => "decoration-dashed",
|
||||||
|
DecorationStyle::Wavy => "decoration-wavy",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Render for DecorationWidget {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for DecorationWidget {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
let mut ret = vec![self.kind.clone()];
|
||||||
|
|
||||||
|
if let Some(color) = &self.color {
|
||||||
|
ret.push(color.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(style) = &self.style {
|
||||||
|
ret.push(style.to_value().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(thickness) = &self.thickness {
|
||||||
|
ret.push(thickness.to_value().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(offset) = &self.underline_offset {
|
||||||
|
ret.push(offset.to_value().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
self.base_class()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_class(&self, _: &str) -> Markup {
|
||||||
|
Nothing()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum UnderlineOffset {
|
||||||
|
Auto,
|
||||||
|
_0,
|
||||||
|
_1,
|
||||||
|
_2,
|
||||||
|
_4,
|
||||||
|
_8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnderlineOffset {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Self::Auto => "underline-offset-auto",
|
||||||
|
Self::_0 => "underline-offset-0",
|
||||||
|
Self::_1 => "underline-offset-1",
|
||||||
|
Self::_2 => "underline-offset-2",
|
||||||
|
Self::_4 => "underline-offset-4",
|
||||||
|
Self::_8 => "underline-offset-8",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum VerticalTextAlignment {
|
||||||
|
Baseline,
|
||||||
|
Top,
|
||||||
|
Middle,
|
||||||
|
Bottom,
|
||||||
|
TextTop,
|
||||||
|
TextBottom,
|
||||||
|
Sub,
|
||||||
|
Super,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VerticalTextAlignment {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
VerticalTextAlignment::Baseline => "align-baseline",
|
||||||
|
VerticalTextAlignment::Top => "align-top",
|
||||||
|
VerticalTextAlignment::Middle => "align-middle",
|
||||||
|
VerticalTextAlignment::Bottom => "align-bottom",
|
||||||
|
VerticalTextAlignment::TextTop => "align-text-top",
|
||||||
|
VerticalTextAlignment::TextBottom => "align-text-bottom",
|
||||||
|
VerticalTextAlignment::Sub => "align-sub",
|
||||||
|
VerticalTextAlignment::Super => "align-super",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TextTransform {
|
||||||
|
Uppecase,
|
||||||
|
Lowercase,
|
||||||
|
Capitalize,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextTransform {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
TextTransform::Uppecase => "uppercase",
|
||||||
|
TextTransform::Lowercase => "lowercase",
|
||||||
|
TextTransform::Capitalize => "capitalize",
|
||||||
|
TextTransform::None => "normal-case",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TextOverflow {
|
||||||
|
Truncate,
|
||||||
|
Ellipsis,
|
||||||
|
Clip,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextOverflow {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
TextOverflow::Truncate => "truncate",
|
||||||
|
TextOverflow::Ellipsis => "text-ellipsis",
|
||||||
|
TextOverflow::Clip => "text-clip",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TextWrap {
|
||||||
|
Wrap,
|
||||||
|
NoWrap,
|
||||||
|
Balance,
|
||||||
|
Pretty,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextWrap {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
TextWrap::Wrap => "text-wrap",
|
||||||
|
TextWrap::NoWrap => "text-nowrap",
|
||||||
|
TextWrap::Balance => "text-balance",
|
||||||
|
TextWrap::Pretty => "text-pretty",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TextWhitespace {
|
||||||
|
Normal,
|
||||||
|
NoWrap,
|
||||||
|
Pre,
|
||||||
|
PreLine,
|
||||||
|
PreWrap,
|
||||||
|
BreakSpaces,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextWhitespace {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
TextWhitespace::Normal => "whitespace-normal",
|
||||||
|
TextWhitespace::NoWrap => "whitespace-nowrap",
|
||||||
|
TextWhitespace::Pre => "whitespace-pre",
|
||||||
|
TextWhitespace::PreLine => "whitespace-pre-line",
|
||||||
|
TextWhitespace::PreWrap => "whitespace-pre-wrap",
|
||||||
|
TextWhitespace::BreakSpaces => "whitespace-break-spaces",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TextWordBreak {
|
||||||
|
Normal,
|
||||||
|
Words,
|
||||||
|
All,
|
||||||
|
Keep,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextWordBreak {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
TextWordBreak::Normal => "break-normal",
|
||||||
|
TextWordBreak::Words => "break-words",
|
||||||
|
TextWordBreak::All => "break-all",
|
||||||
|
TextWordBreak::Keep => "break-keep",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TextHyphens {
|
||||||
|
None,
|
||||||
|
Manual,
|
||||||
|
Auto,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextHyphens {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
TextHyphens::None => "hyphens-none",
|
||||||
|
TextHyphens::Manual => "hyphens-manual",
|
||||||
|
TextHyphens::Auto => "hyphens-auto",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,24 +1,33 @@
|
||||||
use crate::ui::UIWidget;
|
use crate::ui::UIWidget;
|
||||||
use maud::{Markup, Render, html};
|
use maud::{Markup, Render, html};
|
||||||
|
|
||||||
use super::space::ScreenValue;
|
use super::{
|
||||||
|
flex::Either,
|
||||||
|
space::{Fraction, ScreenValue},
|
||||||
|
};
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn Width<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> WidthWidget {
|
pub fn Width<T: UIWidget + 'static>(size: Either<ScreenValue, Fraction>, inner: T) -> WidthWidget {
|
||||||
WidthWidget(Box::new(inner), size, 0)
|
WidthWidget(Box::new(inner), size, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn MinWidth<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> WidthWidget {
|
pub fn MinWidth<T: UIWidget + 'static>(
|
||||||
|
size: Either<ScreenValue, Fraction>,
|
||||||
|
inner: T,
|
||||||
|
) -> WidthWidget {
|
||||||
WidthWidget(Box::new(inner), size, 1)
|
WidthWidget(Box::new(inner), size, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn MaxWidth<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> WidthWidget {
|
pub fn MaxWidth<T: UIWidget + 'static>(
|
||||||
|
size: Either<ScreenValue, Fraction>,
|
||||||
|
inner: T,
|
||||||
|
) -> WidthWidget {
|
||||||
WidthWidget(Box::new(inner), size, 2)
|
WidthWidget(Box::new(inner), size, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WidthWidget(Box<dyn UIWidget>, ScreenValue, u8);
|
pub struct WidthWidget(Box<dyn UIWidget>, Either<ScreenValue, Fraction>, u8);
|
||||||
|
|
||||||
impl Render for WidthWidget {
|
impl Render for WidthWidget {
|
||||||
fn render(&self) -> Markup {
|
fn render(&self) -> Markup {
|
||||||
|
@ -34,15 +43,27 @@ impl UIWidget for WidthWidget {
|
||||||
fn base_class(&self) -> Vec<String> {
|
fn base_class(&self) -> Vec<String> {
|
||||||
match self.2 {
|
match self.2 {
|
||||||
1 => {
|
1 => {
|
||||||
return vec![format!("min-w-{}", self.1.to_value())];
|
return vec![format!(
|
||||||
|
"min-w-{}",
|
||||||
|
self.1
|
||||||
|
.map(|x| x.to_value().to_string(), |x| x.to_value().to_string())
|
||||||
|
)];
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
return vec![format!("max-w-{}", self.1.to_value())];
|
return vec![format!(
|
||||||
|
"max-w-{}",
|
||||||
|
self.1
|
||||||
|
.map(|x| x.to_value().to_string(), |x| x.to_value().to_string())
|
||||||
|
)];
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
vec![format!("w-{}", self.1.to_value())]
|
vec![format!(
|
||||||
|
"w-{}",
|
||||||
|
self.1
|
||||||
|
.map(|x| x.to_value().to_string(), |x| x.to_value().to_string())
|
||||||
|
)]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extended_class(&self) -> Vec<String> {
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
|
Loading…
Add table
Reference in a new issue