This commit is contained in:
JMARyA 2025-01-21 00:52:29 +01:00
parent b752d77815
commit 95ceaa8231
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
6 changed files with 340 additions and 9 deletions

View file

@ -12,7 +12,7 @@ pub trait ColorCircle {
fn next(&self) -> Self; fn next(&self) -> Self;
} }
// todo : specific colors rgb // todo : specific colors rgb -[#50d71e]
macro_rules! color_map { macro_rules! color_map {
($name:ident, $id:literal) => { ($name:ident, $id:literal) => {

View file

@ -17,6 +17,7 @@ pub mod components;
pub mod prelude { pub mod prelude {
pub use super::color::*; pub use super::color::*;
pub use super::primitives::Context; pub use super::primitives::Context;
pub use super::primitives::NoBrowserAppearance;
pub use super::primitives::Nothing; pub use super::primitives::Nothing;
pub use super::primitives::Side; pub use super::primitives::Side;
pub use super::primitives::Size; pub use super::primitives::Size;
@ -27,7 +28,7 @@ pub mod prelude {
Border, BorderSide, BorderSize, BorderStyle, Outline, OutlineStyle, Ring, Border, BorderSide, BorderSize, BorderStyle, Outline, OutlineStyle, Ring,
}; };
pub use super::primitives::container::Container; pub use super::primitives::container::Container;
pub use super::primitives::cursor::Cursor; pub use super::primitives::cursor::{Action, Cursor, TouchAction};
pub use super::primitives::div::Div; pub use super::primitives::div::Div;
pub use super::primitives::filter::{ pub use super::primitives::filter::{
Blur, Brightness, Contrast, Grayscale, HueRotate, Invert, Saturate, Sepia, Blur, Brightness, Contrast, Grayscale, HueRotate, Invert, Saturate, Sepia,
@ -41,7 +42,7 @@ pub mod prelude {
pub use super::primitives::link::Link; pub use super::primitives::link::Link;
pub use super::primitives::margin::Margin; pub use super::primitives::margin::Margin;
pub use super::primitives::padding::Padding; pub use super::primitives::padding::Padding;
pub use super::primitives::position::{Position, PositionKind}; pub use super::primitives::position::{Position, PositionKind, Resize, Resizeable};
pub use super::primitives::rounded::Rounded; pub use super::primitives::rounded::Rounded;
pub use super::primitives::script; pub use super::primitives::script;
pub use super::primitives::shadow::Shadow; pub use super::primitives::shadow::Shadow;
@ -49,10 +50,11 @@ pub mod prelude {
pub use super::primitives::space::{ScreenValue, SpaceBetween}; pub use super::primitives::space::{ScreenValue, SpaceBetween};
pub use super::primitives::svg::SVG; pub use super::primitives::svg::SVG;
pub use super::primitives::text::{ pub use super::primitives::text::{
Code, DecorationKind, DecorationStyle, DecorationThickness, LetterSpacing, LineClamp, AccentColor, Code, DecorationKind, DecorationStyle, DecorationThickness, LetterSpacing,
LineHeight, ListStyle, NumberStyle, Paragraph, Span, Text, TextAlignment, TextContent, LineClamp, LineHeight, ListStyle, NumberStyle, Paragraph, Span, Text, TextAlignment,
TextDecoration, TextHyphens, TextOverflow, TextTransform, TextWhitespace, TextWordBreak, TextContent, TextCursorColor, TextDecoration, TextHyphens, TextOverflow, TextSelection,
TextWrap, UnderlineOffset, VerticalTextAlignment, TextTransform, TextWhitespace, TextWordBreak, TextWrap, UnderlineOffset,
VerticalTextAlignment,
}; };
pub use super::primitives::transform::{ pub use super::primitives::transform::{
RenderTransformCPU, RenderTransformGPU, Rotate, Scale, Skew, Transform, TransformOrigin, RenderTransformCPU, RenderTransformGPU, Rotate, Scale, Skew, Transform, TransformOrigin,

View file

@ -122,3 +122,76 @@ impl UIWidget for CursorWidget {
} }
} }
} }
#[allow(non_snake_case)]
pub fn TouchAction<T: UIWidget + 'static>(action: Action, inner: T) -> TouchActionWidget {
TouchActionWidget(Box::new(inner), action)
}
pub struct TouchActionWidget(Box<dyn UIWidget>, 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<String> {
vec![self.1.to_value().to_string()]
}
fn extended_class(&self) -> Vec<String> {
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",
}
}
}

View file

@ -1,5 +1,5 @@
use super::UIWidget; use super::UIWidget;
use maud::{PreEscaped, html}; use maud::{Markup, PreEscaped, Render, html};
pub mod animation; pub mod animation;
pub mod aspect; pub mod aspect;
@ -135,3 +135,46 @@ impl Side {
} }
} }
} }
#[allow(non_snake_case)]
pub fn NoBrowserAppearance<T: UIWidget + 'static>(inner: T) -> NoBrowserAppearanceWidget {
NoBrowserAppearanceWidget(Box::new(inner))
}
pub struct NoBrowserAppearanceWidget(Box<dyn UIWidget>);
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<String> {
vec!["appearance-none".to_string()]
}
fn extended_class(&self) -> Vec<String> {
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())
}
}
}
}
}

View file

@ -2,6 +2,8 @@ use maud::{Markup, Render, html};
use crate::ui::UIWidget; use crate::ui::UIWidget;
use super::Side;
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn Position<T: UIWidget + 'static>(kind: PositionKind, inner: T) -> Positioned { pub fn Position<T: UIWidget + 'static>(kind: PositionKind, inner: T) -> Positioned {
Positioned { Positioned {
@ -208,3 +210,132 @@ impl PositionKind {
} }
} }
} }
#[allow(non_snake_case)]
pub fn ObjectPosition<T: UIWidget + 'static>(side: Side, inner: T) -> ObjectPositioned {
ObjectPositioned {
inner: Box::new(inner),
side,
}
}
pub struct ObjectPositioned {
inner: Box<dyn UIWidget>,
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<String> {
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<String> {
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<T: UIWidget + 'static>(mode: Resize, inner: T) -> ResizeableWidget {
ResizeableWidget(Box::new(inner), mode)
}
pub struct ResizeableWidget(Box<dyn UIWidget>, 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<String> {
vec![self.1.to_value().to_string()]
}
fn extended_class(&self) -> Vec<String> {
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())
}
}
}
}
}

View file

@ -1,5 +1,5 @@
use crate::ui::{UIWidget, color::UIColor}; use crate::ui::{UIWidget, color::UIColor};
use maud::{Markup, PreEscaped, Render}; use maud::{Markup, PreEscaped, Render, html};
use super::{Nothing, space::ScreenValue}; use super::{Nothing, space::ScreenValue};
@ -31,6 +31,7 @@ pub fn Text(txt: &str) -> TextWidget {
align: None, align: None,
vert_align: None, vert_align: None,
list_style: None, list_style: None,
select: None,
kind: TextKind::Paragraph, kind: TextKind::Paragraph,
} }
} }
@ -68,6 +69,7 @@ pub fn Paragraph<T: UIWidget + 'static>(inner: T) -> TextWidget {
list_style: None, list_style: None,
clamp: None, clamp: None,
align: None, align: None,
select: None,
kind: TextKind::Paragraph, kind: TextKind::Paragraph,
} }
} }
@ -100,6 +102,7 @@ pub fn Span(txt: &str) -> TextWidget {
clamp: None, clamp: None,
align: None, align: None,
pseudo: None, pseudo: None,
select: None,
kind: TextKind::Span, kind: TextKind::Span,
} }
} }
@ -132,6 +135,7 @@ pub fn Code(txt: &str) -> TextWidget {
clamp: None, clamp: None,
align: None, align: None,
pseudo: None, pseudo: None,
select: None,
kind: TextKind::Pre, kind: TextKind::Pre,
} }
} }
@ -160,10 +164,17 @@ pub struct TextWidget {
pseudo: Option<TextContent>, pseudo: Option<TextContent>,
align: Option<TextAlignment>, align: Option<TextAlignment>,
clamp: Option<LineClamp>, clamp: Option<LineClamp>,
select: Option<TextSelection>,
title: Option<String>, title: Option<String>,
} }
impl TextWidget { impl TextWidget {
#[must_use]
pub fn select(mut self, select: TextSelection) -> Self {
self.select = Some(select);
self
}
#[must_use] #[must_use]
pub fn whitespace(mut self, whitespace: TextWhitespace) -> Self { pub fn whitespace(mut self, whitespace: TextWhitespace) -> Self {
self.whitespace = Some(whitespace); self.whitespace = Some(whitespace);
@ -527,6 +538,7 @@ impl UIWidget for TextWidget {
add_option!(list_style, ret); add_option!(list_style, ret);
add_option!(pseudo, ret); add_option!(pseudo, ret);
add_option!(line_height, ret); add_option!(line_height, ret);
add_option!(select, ret);
if let Some(decoration) = &self.decoration { if let Some(decoration) = &self.decoration {
ret.extend_from_slice(&decoration.base_class()); ret.extend_from_slice(&decoration.base_class());
@ -1061,3 +1073,73 @@ 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<T: UIWidget + 'static, C: UIColor + 'static>(color: C, inner: T) -> $widget {
$widget(Box::new(inner), Box::new(color))
}
pub struct $widget(Box<dyn UIWidget>, Box<dyn UIColor>);
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<String> {
let mut class = $class.to_string();
class.push_str(&format!("-{}", self.1.color_class()));
vec![class]
}
fn extended_class(&self) -> Vec<String> {
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");