update
This commit is contained in:
parent
f3a85de02e
commit
86f61ff3f6
15 changed files with 918 additions and 41 deletions
|
@ -15,12 +15,16 @@ pub async fn index_page(ctx: RequestContext) -> StringResponse {
|
||||||
h1 { "Hello World!" };
|
h1 { "Hello World!" };
|
||||||
|
|
||||||
(Hover(
|
(Hover(
|
||||||
Padding(Text("").color(&Gray::_400)).x(ScreenValue::_10),
|
Cursor::NorthEastResize.on(
|
||||||
Link("/test", Text("Hello")).hx_get("/test").hx_get("/test").hx_trigger(
|
Padding(Text("").color(&Gray::_400)).x(ScreenValue::_10)
|
||||||
Event::on_load().delay("2s")
|
|
||||||
.and(Event::on_revealed())
|
|
||||||
)
|
)
|
||||||
))
|
).on(
|
||||||
|
Link("/test", Text("Hello")).hx_get("/test").hx_get("/test").hx_trigger(
|
||||||
|
Event::on_load().delay("2s")
|
||||||
|
.and(Event::on_revealed())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
(content)
|
(content)
|
||||||
|
|
||||||
|
|
11
src/htmx.rs
11
src/htmx.rs
|
@ -1,8 +1,11 @@
|
||||||
|
use crate::request::assets::DataResponse;
|
||||||
use rocket::get;
|
use rocket::get;
|
||||||
|
|
||||||
use crate::request::{StringResponse, respond_script};
|
|
||||||
|
|
||||||
#[get("/assets/htmx.min.js")]
|
#[get("/assets/htmx.min.js")]
|
||||||
pub fn htmx_script_route() -> StringResponse {
|
pub fn htmx_script_route() -> DataResponse {
|
||||||
respond_script(include_str!("htmx.min.js").to_string())
|
DataResponse::new(
|
||||||
|
include_str!("htmx.min.js").as_bytes().to_vec(),
|
||||||
|
"application/javascript".to_string(),
|
||||||
|
Some(60 * 60 * 24 * 3),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,18 @@ pub mod components;
|
||||||
// Preludes
|
// Preludes
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use super::color::*;
|
pub use super::color::*;
|
||||||
pub use super::primitives::Nothing;
|
|
||||||
pub use super::primitives::Context;
|
pub use super::primitives::Context;
|
||||||
|
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;
|
||||||
pub use super::primitives::aspect::Aspect;
|
pub use super::primitives::aspect::Aspect;
|
||||||
pub use super::primitives::background::Background;
|
pub use super::primitives::background::Background;
|
||||||
pub use super::primitives::container::Container;
|
pub use super::primitives::container::Container;
|
||||||
|
pub use super::primitives::cursor::Cursor;
|
||||||
pub use super::primitives::div::Div;
|
pub use super::primitives::div::Div;
|
||||||
pub use super::primitives::flex::{Flex, Justify};
|
pub use super::primitives::flex::{Flex, Justify};
|
||||||
pub use super::primitives::header::Header;
|
pub use super::primitives::header::Header;
|
||||||
pub use super::primitives::height::Height;
|
pub use super::primitives::height::HeightWidget;
|
||||||
pub use super::primitives::image::Image;
|
pub use super::primitives::image::Image;
|
||||||
pub use super::primitives::link::Link;
|
pub use super::primitives::link::Link;
|
||||||
pub use super::primitives::margin::Margin;
|
pub use super::primitives::margin::Margin;
|
||||||
|
@ -36,7 +37,9 @@ pub mod prelude {
|
||||||
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::{Paragraph, Span, Text};
|
||||||
|
pub use super::primitives::visibility::Visibility;
|
||||||
pub use super::primitives::width::Width;
|
pub use super::primitives::width::Width;
|
||||||
|
pub use super::primitives::zindex::ZIndex;
|
||||||
pub use super::wrapper::Hover;
|
pub use super::wrapper::Hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
124
src/ui/primitives/cursor.rs
Normal file
124
src/ui/primitives/cursor.rs
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
use crate::ui::UIWidget;
|
||||||
|
use maud::{Markup, Render, html};
|
||||||
|
|
||||||
|
pub enum Cursor {
|
||||||
|
Auto,
|
||||||
|
Default,
|
||||||
|
Pointer,
|
||||||
|
Wait,
|
||||||
|
Text,
|
||||||
|
Move,
|
||||||
|
Help,
|
||||||
|
NotAllowed,
|
||||||
|
None,
|
||||||
|
ContextMenu,
|
||||||
|
Progress,
|
||||||
|
Cell,
|
||||||
|
Crosshair,
|
||||||
|
VerticalText,
|
||||||
|
Alias,
|
||||||
|
Copy,
|
||||||
|
NoDrop,
|
||||||
|
Grab,
|
||||||
|
Grabbing,
|
||||||
|
AllScroll,
|
||||||
|
ColResize,
|
||||||
|
RowResize,
|
||||||
|
NorthResize,
|
||||||
|
EastResize,
|
||||||
|
SouthResize,
|
||||||
|
WestResize,
|
||||||
|
NorthEastResize,
|
||||||
|
NorthWestResize,
|
||||||
|
SouthEastResize,
|
||||||
|
SouthWestResize,
|
||||||
|
EastWestResize,
|
||||||
|
NorthSouthResize,
|
||||||
|
NorthEastSouthWestResize,
|
||||||
|
NorthWestSouthEastResize,
|
||||||
|
ZoomIn,
|
||||||
|
ZoomOut,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cursor {
|
||||||
|
pub fn on<T: UIWidget + 'static>(self, inner: T) -> CursorWidget {
|
||||||
|
CursorWidget(self, Box::new(inner))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CursorWidget(Cursor, Box<dyn UIWidget>);
|
||||||
|
|
||||||
|
impl Render for CursorWidget {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for CursorWidget {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
let class = match self.0 {
|
||||||
|
Cursor::Auto => "cursor-auto",
|
||||||
|
Cursor::Default => "cursor-default",
|
||||||
|
Cursor::Pointer => "cursor-pointer",
|
||||||
|
Cursor::Wait => "cursor-wait",
|
||||||
|
Cursor::Text => "cursor-text",
|
||||||
|
Cursor::Move => "cursor-move",
|
||||||
|
Cursor::Help => "cursor-help",
|
||||||
|
Cursor::NotAllowed => "cursor-not-allowed",
|
||||||
|
Cursor::None => "cursor-none",
|
||||||
|
Cursor::ContextMenu => "cursor-context-menu",
|
||||||
|
Cursor::Progress => "cursor-progress",
|
||||||
|
Cursor::Cell => "cursor-cell",
|
||||||
|
Cursor::Crosshair => "cursor-crosshair",
|
||||||
|
Cursor::VerticalText => "cursor-vertical-text",
|
||||||
|
Cursor::Alias => "cursor-alias",
|
||||||
|
Cursor::Copy => "cursor-copy",
|
||||||
|
Cursor::NoDrop => "cursor-no-drop",
|
||||||
|
Cursor::Grab => "cursor-grab",
|
||||||
|
Cursor::Grabbing => "cursor-grabbing",
|
||||||
|
Cursor::AllScroll => "cursor-all-scroll",
|
||||||
|
Cursor::ColResize => "cursor-col-resize",
|
||||||
|
Cursor::RowResize => "cursor-row-resize",
|
||||||
|
Cursor::NorthResize => "cursor-n-resize",
|
||||||
|
Cursor::EastResize => "cursor-e-resize",
|
||||||
|
Cursor::SouthResize => "cursor-s-resize",
|
||||||
|
Cursor::WestResize => "cursor-w-resize",
|
||||||
|
Cursor::NorthEastResize => "cursor-ne-resize",
|
||||||
|
Cursor::NorthWestResize => "cursor-nw-resize",
|
||||||
|
Cursor::SouthEastResize => "cursor-se-resize",
|
||||||
|
Cursor::SouthWestResize => "cursor-sw-resize",
|
||||||
|
Cursor::EastWestResize => "cursor-ew-resize",
|
||||||
|
Cursor::NorthSouthResize => "cursor-ns-resize",
|
||||||
|
Cursor::NorthEastSouthWestResize => "cursor-nesw-resize",
|
||||||
|
Cursor::NorthWestSouthEastResize => "cursor-nwse-resize",
|
||||||
|
Cursor::ZoomIn => "cursor-zoom-in",
|
||||||
|
Cursor::ZoomOut => "cursor-zoom-out",
|
||||||
|
};
|
||||||
|
|
||||||
|
vec![class.to_string()]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
let mut c = self.base_class();
|
||||||
|
c.extend_from_slice(&self.1.extended_class());
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_class(&self, class: &str) -> Markup {
|
||||||
|
let inner = &self.1;
|
||||||
|
|
||||||
|
if inner.can_inherit() {
|
||||||
|
inner.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
div class=(format!("{} {class}", self.base_class().join(" "))) {
|
||||||
|
(inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,22 @@
|
||||||
use crate::ui::UIWidget;
|
use crate::ui::UIWidget;
|
||||||
use maud::{Markup, Render, html};
|
use maud::{Markup, Render, html};
|
||||||
|
|
||||||
|
use super::space::{Fraction, ScreenValue};
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn Flex<T: UIWidget + 'static>(inner: T) -> FlexWidget {
|
pub fn Flex<T: UIWidget + 'static>(inner: T) -> FlexWidget {
|
||||||
FlexWidget(Box::new(inner), vec![], false)
|
FlexWidget(Box::new(inner), vec![], false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Justify {
|
pub enum Justify {
|
||||||
|
Normal,
|
||||||
|
Start,
|
||||||
|
End,
|
||||||
Center,
|
Center,
|
||||||
Between,
|
Between,
|
||||||
|
Around,
|
||||||
|
Evenly,
|
||||||
|
Stretch,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FlexWidget(Box<dyn UIWidget>, Vec<String>, bool);
|
pub struct FlexWidget(Box<dyn UIWidget>, Vec<String>, bool);
|
||||||
|
@ -33,11 +41,29 @@ impl FlexWidget {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn direction(mut self, direction: Direction) -> Self {
|
||||||
|
self.1.push(format!("flex-{}", direction.to_value()));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn wrap(mut self, wrap: Wrap) -> Self {
|
||||||
|
self.1.push(format!("flex-{}", wrap.to_value()));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn justify(mut self, value: Justify) -> Self {
|
pub fn justify(mut self, value: Justify) -> Self {
|
||||||
let class = match value {
|
let class = match value {
|
||||||
Justify::Center => "justify-center".to_owned(),
|
Justify::Center => "justify-center".to_string(),
|
||||||
Justify::Between => "justify-between".to_owned(),
|
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.1.push(class);
|
||||||
|
@ -51,10 +77,56 @@ impl FlexWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn gap(mut self, amount: u32) -> Self {
|
pub fn gap(mut self, amount: ScreenValue) -> Self {
|
||||||
self.1.push(format!("gap-{amount}"));
|
self.1.push(format!("gap-{}", amount.to_value()));
|
||||||
self
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Direction {
|
||||||
|
Row,
|
||||||
|
RowReverse,
|
||||||
|
Column,
|
||||||
|
ColumnReverse,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Direction {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Direction::Row => "row",
|
||||||
|
Direction::RowReverse => "row-reverse",
|
||||||
|
Direction::Column => "col",
|
||||||
|
Direction::ColumnReverse => "col-reverse",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Wrap {
|
||||||
|
Wrap,
|
||||||
|
Reverse,
|
||||||
|
NoWrap,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Wrap {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Wrap::Wrap => "wrap",
|
||||||
|
Wrap::Reverse => "wrap-reverse",
|
||||||
|
Wrap::NoWrap => "nowrap",
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UIWidget for FlexWidget {
|
impl UIWidget for FlexWidget {
|
||||||
|
@ -88,3 +160,242 @@ impl UIWidget for FlexWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum Either<R, L> {
|
||||||
|
Right(R),
|
||||||
|
Left(L),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, L> Either<R, L> {
|
||||||
|
pub fn map<X, Y, U>(self, lf: X, rf: Y) -> U
|
||||||
|
where
|
||||||
|
X: FnOnce(L) -> U,
|
||||||
|
Y: FnOnce(R) -> U,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Either::Right(r) => rf(r),
|
||||||
|
Either::Left(l) => lf(l),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ScreenValue> for Either<ScreenValue, Fraction> {
|
||||||
|
fn from(value: ScreenValue) -> Self {
|
||||||
|
Self::Right(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Fraction> for Either<ScreenValue, Fraction> {
|
||||||
|
fn from(value: Fraction) -> Self {
|
||||||
|
Self::Left(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn FlexBasis<T: UIWidget + 'static>(
|
||||||
|
inner: T,
|
||||||
|
value: Either<ScreenValue, Fraction>,
|
||||||
|
) -> FlexBasisWidget {
|
||||||
|
FlexBasisWidget(Box::new(inner), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FlexBasisWidget(Box<dyn UIWidget>, Either<ScreenValue, Fraction>);
|
||||||
|
|
||||||
|
impl Render for FlexBasisWidget {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for FlexBasisWidget {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
vec![format!(
|
||||||
|
"basis-{}",
|
||||||
|
self.1
|
||||||
|
.clone()
|
||||||
|
.map(|x| x.to_value().to_string(), |x| x.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, _: &str) -> Markup {
|
||||||
|
if self.0.as_ref().can_inherit() {
|
||||||
|
self.0
|
||||||
|
.as_ref()
|
||||||
|
.render_with_class(&format!("{}", self.base_class().join(" ")))
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
div class=(format!("{}", self.base_class().join(" "))) {
|
||||||
|
(self.0.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn FlexGrow<T: UIWidget + 'static>(strategy: Strategy, inner: T) -> FlexGrowWidget {
|
||||||
|
FlexGrowWidget(strategy, Box::new(inner))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FlexGrowWidget(Strategy, Box<dyn UIWidget>);
|
||||||
|
|
||||||
|
impl Render for FlexGrowWidget {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for FlexGrowWidget {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
vec![self.0.to_value().to_string()]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
let mut c = self.base_class();
|
||||||
|
c.extend_from_slice(&self.1.extended_class());
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_class(&self, _: &str) -> Markup {
|
||||||
|
if self.1.as_ref().can_inherit() {
|
||||||
|
self.1
|
||||||
|
.as_ref()
|
||||||
|
.render_with_class(&format!("{}", self.base_class().join(" ")))
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
div class=(format!("{}", self.base_class().join(" "))) {
|
||||||
|
(self.1.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Strategy {
|
||||||
|
/// Allow a flex item to shrink but not grow, taking into account its initial size.
|
||||||
|
Initial,
|
||||||
|
/// Allow a flex item to grow and shrink as needed, ignoring its initial size.
|
||||||
|
Expand,
|
||||||
|
/// Allow a flex item to grow and shrink, taking into account its initial size.
|
||||||
|
Auto,
|
||||||
|
/// Prevent a flex item from growing or shrinking.
|
||||||
|
None,
|
||||||
|
/// Allow a flex item to grow to fill any available space.
|
||||||
|
Grow,
|
||||||
|
/// Prevent a flex item from growing.
|
||||||
|
NoGrow,
|
||||||
|
/// Allow a flex item to shrink if needed.
|
||||||
|
Shrink,
|
||||||
|
/// Prevent a flex item from shrinking.
|
||||||
|
NoShrink,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Strategy {
|
||||||
|
pub fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Self::Initial => "flex-initial",
|
||||||
|
Self::Expand => "flex-1",
|
||||||
|
Self::Auto => "flex-auto",
|
||||||
|
Self::None => "flex-none",
|
||||||
|
Self::Grow => "grow",
|
||||||
|
Self::NoGrow => "grow-0",
|
||||||
|
Self::Shrink => "shrink",
|
||||||
|
Self::NoShrink => "shrink-0",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Order {
|
||||||
|
_1,
|
||||||
|
_2,
|
||||||
|
_3,
|
||||||
|
_4,
|
||||||
|
_5,
|
||||||
|
_6,
|
||||||
|
_7,
|
||||||
|
_8,
|
||||||
|
_9,
|
||||||
|
_10,
|
||||||
|
_11,
|
||||||
|
_12,
|
||||||
|
First,
|
||||||
|
Last,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Order {
|
||||||
|
pub fn on<T: UIWidget + 'static>(self, inner: T) -> OrderWidget {
|
||||||
|
OrderWidget(self, Box::new(inner))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OrderWidget(Order, Box<dyn UIWidget>);
|
||||||
|
|
||||||
|
impl Render for OrderWidget {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for OrderWidget {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
let class = match self.0 {
|
||||||
|
Order::_1 => "order-1",
|
||||||
|
Order::_2 => "order-2",
|
||||||
|
Order::_3 => "order-3",
|
||||||
|
Order::_4 => "order-4",
|
||||||
|
Order::_5 => "order-5",
|
||||||
|
Order::_6 => "order-6",
|
||||||
|
Order::_7 => "order-7",
|
||||||
|
Order::_8 => "order-8",
|
||||||
|
Order::_9 => "order-9",
|
||||||
|
Order::_10 => "order-10",
|
||||||
|
Order::_11 => "order-11",
|
||||||
|
Order::_12 => "order-12",
|
||||||
|
Order::First => "order-first",
|
||||||
|
Order::Last => "order-last",
|
||||||
|
Order::None => "order-none",
|
||||||
|
};
|
||||||
|
|
||||||
|
vec![class.to_string()]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
let mut c = self.base_class();
|
||||||
|
c.extend_from_slice(&self.1.extended_class());
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_with_class(&self, class: &str) -> Markup {
|
||||||
|
let inner = &self.1;
|
||||||
|
|
||||||
|
if inner.can_inherit() {
|
||||||
|
inner.render_with_class(&format!("{} {class}", self.base_class().join(" ")))
|
||||||
|
} else {
|
||||||
|
html! {
|
||||||
|
div class=(format!("{} {class}", self.base_class().join(" "))) {
|
||||||
|
(inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,24 +4,44 @@ use maud::{Markup, Render, html};
|
||||||
use super::space::ScreenValue;
|
use super::space::ScreenValue;
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn Width<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> Height {
|
pub fn Height<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> HeightWidget {
|
||||||
Height(Box::new(inner), size)
|
HeightWidget(Box::new(inner), size, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Height(Box<dyn UIWidget>, ScreenValue);
|
#[allow(non_snake_case)]
|
||||||
|
pub fn MinHeight<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> HeightWidget {
|
||||||
|
HeightWidget(Box::new(inner), size, 1)
|
||||||
|
}
|
||||||
|
|
||||||
impl Render for Height {
|
#[allow(non_snake_case)]
|
||||||
|
pub fn MaxHeight<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> HeightWidget {
|
||||||
|
HeightWidget(Box::new(inner), size, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HeightWidget(Box<dyn UIWidget>, ScreenValue, u8);
|
||||||
|
|
||||||
|
impl Render for HeightWidget {
|
||||||
fn render(&self) -> Markup {
|
fn render(&self) -> Markup {
|
||||||
self.render_with_class("")
|
self.render_with_class("")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UIWidget for Height {
|
impl UIWidget for HeightWidget {
|
||||||
fn can_inherit(&self) -> bool {
|
fn can_inherit(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_class(&self) -> Vec<String> {
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
match self.2 {
|
||||||
|
1 => {
|
||||||
|
return vec![format!("min-h-{}", self.1.to_value())];
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
return vec![format!("max-h-{}", self.1.to_value())];
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
vec![format!("h-{}", self.1.to_value())]
|
vec![format!("h-{}", self.1.to_value())]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ impl LinkWidget {
|
||||||
/// Enable HTMX link capabilities
|
/// Enable HTMX link capabilities
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn use_htmx(self) -> Self {
|
pub fn use_htmx(self) -> Self {
|
||||||
|
// todo : investigate htmx attrs
|
||||||
let url = self.1.clone();
|
let url = self.1.clone();
|
||||||
self.hx_get(&url)
|
self.hx_get(&url)
|
||||||
.hx_target(Selector::Query("#main_content".to_string()))
|
.hx_target(Selector::Query("#main_content".to_string()))
|
||||||
|
|
|
@ -5,6 +5,7 @@ use super::UIWidget;
|
||||||
pub mod aspect;
|
pub mod aspect;
|
||||||
pub mod background;
|
pub mod background;
|
||||||
pub mod container;
|
pub mod container;
|
||||||
|
pub mod cursor;
|
||||||
pub mod div;
|
pub mod div;
|
||||||
pub mod flex;
|
pub mod flex;
|
||||||
pub mod header;
|
pub mod header;
|
||||||
|
@ -19,7 +20,9 @@ pub mod shadow;
|
||||||
pub mod sized;
|
pub mod sized;
|
||||||
pub mod space;
|
pub mod space;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
|
pub mod visibility;
|
||||||
pub mod width;
|
pub mod width;
|
||||||
|
pub mod zindex;
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -30,7 +33,7 @@ pub fn Nothing() -> PreEscaped<String> {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
/// Create a new inheritance context
|
/// Create a new inheritance context
|
||||||
///
|
///
|
||||||
/// This acts as a hard barrier for inheritance.
|
/// This acts as a hard barrier for inheritance.
|
||||||
/// This allows you to embed Widgets without them interacting with the rest of the tree.
|
/// This allows you to embed Widgets without them interacting with the rest of the tree.
|
||||||
pub fn Context<T: UIWidget>(inner: T) -> PreEscaped<String> {
|
pub fn Context<T: UIWidget>(inner: T) -> PreEscaped<String> {
|
||||||
|
|
|
@ -31,10 +31,6 @@ impl Shadow {
|
||||||
pub fn _2xl<T: UIWidget + 'static>(inner: T) -> Self {
|
pub fn _2xl<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
Self(Box::new(inner), "2xl".to_owned())
|
Self(Box::new(inner), "2xl".to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner<T: UIWidget + 'static>(inner: T) -> Self {
|
|
||||||
Self(Box::new(inner), "inner".to_owned())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for Shadow {
|
impl Render for Shadow {
|
||||||
|
@ -76,3 +72,75 @@ impl UIWidget for Shadow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct DropShadow(Box<dyn UIWidget>, String);
|
||||||
|
|
||||||
|
impl DropShadow {
|
||||||
|
pub fn small<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), "sm".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn regular<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), String::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn medium<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), "md".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn large<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), "lg".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn none<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), "none".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn xl<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), "xl".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _2xl<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), "2xl".to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Render for DropShadow {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for DropShadow {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
if self.1.is_empty() {
|
||||||
|
vec!["drop-shadow".to_string()]
|
||||||
|
} else {
|
||||||
|
vec![format!("drop-shadow-{}", self.1)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@ impl UIWidget for SpaceBetweenWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum ScreenValue {
|
pub enum ScreenValue {
|
||||||
_0,
|
_0,
|
||||||
_0p5,
|
_0p5,
|
||||||
|
@ -165,6 +166,7 @@ impl ScreenValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Fraction {
|
pub enum Fraction {
|
||||||
_1on2,
|
_1on2,
|
||||||
_1on3,
|
_1on3,
|
||||||
|
|
|
@ -8,8 +8,10 @@ pub fn Text(txt: &str) -> TextWidget {
|
||||||
TextWidget {
|
TextWidget {
|
||||||
inner: None,
|
inner: None,
|
||||||
txt: txt.to_string(),
|
txt: txt.to_string(),
|
||||||
|
family: String::new(),
|
||||||
font: String::new(),
|
font: String::new(),
|
||||||
color: String::new(),
|
color: String::new(),
|
||||||
|
style: Vec::new(),
|
||||||
size: String::new(),
|
size: String::new(),
|
||||||
span: false,
|
span: false,
|
||||||
}
|
}
|
||||||
|
@ -21,8 +23,10 @@ pub fn Paragraph<T: UIWidget + 'static>(inner: T) -> TextWidget {
|
||||||
TextWidget {
|
TextWidget {
|
||||||
inner: Some(Box::new(inner)),
|
inner: Some(Box::new(inner)),
|
||||||
font: String::new(),
|
font: String::new(),
|
||||||
|
family: String::new(),
|
||||||
color: String::new(),
|
color: String::new(),
|
||||||
txt: String::new(),
|
txt: String::new(),
|
||||||
|
style: Vec::new(),
|
||||||
size: String::new(),
|
size: String::new(),
|
||||||
span: false,
|
span: false,
|
||||||
}
|
}
|
||||||
|
@ -35,7 +39,9 @@ pub fn Span(txt: &str) -> TextWidget {
|
||||||
TextWidget {
|
TextWidget {
|
||||||
inner: None,
|
inner: None,
|
||||||
txt: txt.to_string(),
|
txt: txt.to_string(),
|
||||||
|
family: String::new(),
|
||||||
font: String::new(),
|
font: String::new(),
|
||||||
|
style: Vec::new(),
|
||||||
color: String::new(),
|
color: String::new(),
|
||||||
size: String::new(),
|
size: String::new(),
|
||||||
span: true,
|
span: true,
|
||||||
|
@ -45,6 +51,8 @@ pub fn Span(txt: &str) -> TextWidget {
|
||||||
pub struct TextWidget {
|
pub struct TextWidget {
|
||||||
inner: Option<Box<dyn UIWidget>>,
|
inner: Option<Box<dyn UIWidget>>,
|
||||||
txt: String,
|
txt: String,
|
||||||
|
family: String,
|
||||||
|
style: Vec<String>,
|
||||||
font: String,
|
font: String,
|
||||||
color: String,
|
color: String,
|
||||||
size: String,
|
size: String,
|
||||||
|
@ -52,6 +60,41 @@ pub struct TextWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextWidget {
|
impl TextWidget {
|
||||||
|
// Weight
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn thin(mut self) -> Self {
|
||||||
|
self.font = "font-thin".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn extralight(mut self) -> Self {
|
||||||
|
self.font = "font-extralight".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn light(mut self) -> Self {
|
||||||
|
self.font = "font-light".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn normal(mut self) -> Self {
|
||||||
|
self.font = "font-normal".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Turn `Text` medium.
|
||||||
|
///
|
||||||
|
/// Adds the class `font-medium`
|
||||||
|
#[must_use]
|
||||||
|
pub fn medium(mut self) -> Self {
|
||||||
|
self.font = "font-medium".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Turn `Text` semibold.
|
/// Turn `Text` semibold.
|
||||||
///
|
///
|
||||||
/// Adds the class `font-semibold`
|
/// Adds the class `font-semibold`
|
||||||
|
@ -70,12 +113,83 @@ impl TextWidget {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turn `Text` medium.
|
|
||||||
///
|
|
||||||
/// Adds the class `font-medium`
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn medium(mut self) -> Self {
|
pub fn extrabold(mut self) -> Self {
|
||||||
self.font = "font-medium".to_string();
|
self.font = "font-extrabold".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn weight_black(mut self) -> Self {
|
||||||
|
self.font = "font-black".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
// Styles
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn italic(mut self, apply: bool) -> Self {
|
||||||
|
if apply {
|
||||||
|
self.style.push("italic".to_string());
|
||||||
|
} else {
|
||||||
|
self.style.push("not-italic".to_string())
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn number_style(mut self, s: NumberStyle) -> Self {
|
||||||
|
self.style.push(s.to_value().to_string());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sizes
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn _9xl(mut self) -> Self {
|
||||||
|
self.size = "text-9xl".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn _8xl(mut self) -> Self {
|
||||||
|
self.size = "text-8xl".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn _7xl(mut self) -> Self {
|
||||||
|
self.size = "text-7xl".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn _6xl(mut self) -> Self {
|
||||||
|
self.size = "text-6xl".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn _5xl(mut self) -> Self {
|
||||||
|
self.size = "text-5xl".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn _4xl(mut self) -> Self {
|
||||||
|
self.size = "text-4xl".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn large(mut self) -> Self {
|
||||||
|
self.size = "text-lg".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn base_size(mut self) -> Self {
|
||||||
|
self.size = "text-base".to_string();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +229,17 @@ impl TextWidget {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Turn `Text` size to x small.
|
||||||
|
///
|
||||||
|
/// Adds the class `text-xs`
|
||||||
|
#[must_use]
|
||||||
|
pub fn xs(mut self) -> Self {
|
||||||
|
self.size = "text-xs".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text Color
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn color<T: UIColor>(mut self, color: &T) -> Self {
|
pub fn color<T: UIColor>(mut self, color: &T) -> Self {
|
||||||
self.color = format!("text-{}", color.color_class());
|
self.color = format!("text-{}", color.color_class());
|
||||||
|
@ -132,6 +257,26 @@ impl TextWidget {
|
||||||
self.color = "text-white".to_string();
|
self.color = "text-white".to_string();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Font Family
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn sans(mut self) -> Self {
|
||||||
|
self.family = "font-sans".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn serif(mut self) -> Self {
|
||||||
|
self.family = "font-serif".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn mono(mut self) -> Self {
|
||||||
|
self.family = "font-mono".to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for TextWidget {
|
impl Render for TextWidget {
|
||||||
|
@ -146,7 +291,12 @@ impl UIWidget for TextWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_class(&self) -> Vec<String> {
|
fn base_class(&self) -> Vec<String> {
|
||||||
vec![self.color.clone(), self.font.clone(), self.size.clone()]
|
vec![
|
||||||
|
self.color.clone(),
|
||||||
|
self.font.clone(),
|
||||||
|
self.size.clone(),
|
||||||
|
self.family.clone(),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extended_class(&self) -> Vec<String> {
|
fn extended_class(&self) -> Vec<String> {
|
||||||
|
@ -179,3 +329,31 @@ impl UIWidget for TextWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum NumberStyle {
|
||||||
|
Normal,
|
||||||
|
Ordinal,
|
||||||
|
SlashedZero,
|
||||||
|
OldStyle,
|
||||||
|
Lining,
|
||||||
|
Proportional,
|
||||||
|
Tabular,
|
||||||
|
DiagonalFractions,
|
||||||
|
StackedFractions,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NumberStyle {
|
||||||
|
pub const fn to_value(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
NumberStyle::Normal => "normal-nums",
|
||||||
|
NumberStyle::Ordinal => "ordinal",
|
||||||
|
NumberStyle::SlashedZero => "slashed-zero",
|
||||||
|
NumberStyle::OldStyle => "oldstyle-nums",
|
||||||
|
NumberStyle::Lining => "lining-nums",
|
||||||
|
NumberStyle::Proportional => "proportional-nums",
|
||||||
|
NumberStyle::Tabular => "tabular-nums",
|
||||||
|
NumberStyle::DiagonalFractions => "diagonal-fractions",
|
||||||
|
NumberStyle::StackedFractions => "stacked-fractions",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
54
src/ui/primitives/visibility.rs
Normal file
54
src/ui/primitives/visibility.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
use crate::ui::UIWidget;
|
||||||
|
use maud::{Markup, Render, html};
|
||||||
|
|
||||||
|
pub struct Visibility(Box<dyn UIWidget>, String);
|
||||||
|
|
||||||
|
impl Visibility {
|
||||||
|
pub fn visible<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), "visible".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hidden<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), "invisible".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn collapsed<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), "collapse".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Render for Visibility {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for Visibility {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
vec![self.1.clone()]
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,10 +5,20 @@ use super::space::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: ScreenValue, inner: T) -> WidthWidget {
|
||||||
WidthWidget(Box::new(inner), size)
|
WidthWidget(Box::new(inner), size, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WidthWidget(Box<dyn UIWidget>, ScreenValue);
|
#[allow(non_snake_case)]
|
||||||
|
pub fn MinWidth<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> WidthWidget {
|
||||||
|
WidthWidget(Box::new(inner), size, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn MaxWidth<T: UIWidget + 'static>(size: ScreenValue, inner: T) -> WidthWidget {
|
||||||
|
WidthWidget(Box::new(inner), size, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WidthWidget(Box<dyn UIWidget>, ScreenValue, u8);
|
||||||
|
|
||||||
impl Render for WidthWidget {
|
impl Render for WidthWidget {
|
||||||
fn render(&self) -> Markup {
|
fn render(&self) -> Markup {
|
||||||
|
@ -22,6 +32,16 @@ impl UIWidget for WidthWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_class(&self) -> Vec<String> {
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
match self.2 {
|
||||||
|
1 => {
|
||||||
|
return vec![format!("min-w-{}", self.1.to_value())];
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
return vec![format!("max-w-{}", self.1.to_value())];
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
vec![format!("w-{}", self.1.to_value())]
|
vec![format!("w-{}", self.1.to_value())]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
82
src/ui/primitives/zindex.rs
Normal file
82
src/ui/primitives/zindex.rs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
use maud::{Markup, Render, html};
|
||||||
|
|
||||||
|
use crate::ui::UIWidget;
|
||||||
|
|
||||||
|
pub struct ZIndex(Box<dyn UIWidget>, u8);
|
||||||
|
|
||||||
|
impl Render for ZIndex {
|
||||||
|
fn render(&self) -> Markup {
|
||||||
|
self.render_with_class("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ZIndex {
|
||||||
|
pub fn auto<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zero<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn one<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn two<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn three<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn four<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn five<T: UIWidget + 'static>(inner: T) -> Self {
|
||||||
|
Self(Box::new(inner), 6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UIWidget for ZIndex {
|
||||||
|
fn can_inherit(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_class(&self) -> Vec<String> {
|
||||||
|
let class = match self.1 {
|
||||||
|
0 => "z-auto",
|
||||||
|
1 => "z-0",
|
||||||
|
2 => "z-10",
|
||||||
|
3 => "z-20",
|
||||||
|
4 => "z-30",
|
||||||
|
5 => "z-40",
|
||||||
|
6 => "z-50",
|
||||||
|
_ => "z-auto",
|
||||||
|
};
|
||||||
|
|
||||||
|
vec![class.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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,11 +3,11 @@ use maud::{Markup, Render, html};
|
||||||
use crate::ui::UIWidget;
|
use crate::ui::UIWidget;
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn Hover<T: UIWidget + 'static, I: UIWidget + 'static>(inherit: I, inner: T) -> HoverWrapper {
|
pub fn Hover<I: UIWidget + 'static>(inherit: I) -> HoverWrapper {
|
||||||
HoverWrapper(Box::new(inner), Box::new(inherit))
|
HoverWrapper(None, Box::new(inherit))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HoverWrapper(Box<dyn UIWidget>, Box<dyn UIWidget>);
|
pub struct HoverWrapper(Option<Box<dyn UIWidget>>, Box<dyn UIWidget>);
|
||||||
|
|
||||||
impl HoverWrapper {
|
impl HoverWrapper {
|
||||||
fn hovered_class(&self) -> Vec<String> {
|
fn hovered_class(&self) -> Vec<String> {
|
||||||
|
@ -18,6 +18,11 @@ impl HoverWrapper {
|
||||||
.map(|x| format!("hover:{x}"))
|
.map(|x| format!("hover:{x}"))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on<T: UIWidget + 'static>(mut self, inner: T) -> Self {
|
||||||
|
self.0 = Some(Box::new(inner));
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for HoverWrapper {
|
impl Render for HoverWrapper {
|
||||||
|
@ -36,20 +41,19 @@ impl UIWidget for HoverWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extended_class(&self) -> Vec<String> {
|
fn extended_class(&self) -> Vec<String> {
|
||||||
let mut ret = self.base_class();
|
self.base_class()
|
||||||
ret.extend_from_slice(&self.0.extended_class());
|
|
||||||
ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_with_class(&self, class: &str) -> Markup {
|
fn render_with_class(&self, class: &str) -> Markup {
|
||||||
if self.0.as_ref().can_inherit() {
|
if self.0.as_ref().unwrap().can_inherit() {
|
||||||
self.0
|
self.0
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
.render_with_class(&format!("{} {class}", self.hovered_class().join(" ")))
|
.render_with_class(&format!("{} {class}", self.hovered_class().join(" ")))
|
||||||
} else {
|
} else {
|
||||||
html! {
|
html! {
|
||||||
div class=(format!("{} {class}", self.hovered_class().join(" "))) {
|
div class=(format!("{} {class}", self.hovered_class().join(" "))) {
|
||||||
(self.0.as_ref())
|
(self.0.as_ref().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue