1use crate::classes::ClassBuilder;
6use serde::{Deserialize, Serialize};
7use std::fmt;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11pub enum Display {
12 Block,
14 Inline,
16 InlineBlock,
18 Flex,
20 InlineFlex,
22 Grid,
24 InlineGrid,
26 Table,
28 InlineTable,
30 TableCaption,
32 TableCell,
34 TableColumn,
36 TableColumnGroup,
38 TableFooterGroup,
40 TableHeaderGroup,
42 TableRow,
44 TableRowGroup,
46 FlowRoot,
48 Contents,
50 ListItem,
52 Hidden,
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
58pub enum Position {
59 Static,
61 Fixed,
63 Absolute,
65 Relative,
67 Sticky,
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
73pub enum Overflow {
74 Auto,
76 Hidden,
78 Clip,
80 Visible,
82 Scroll,
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
88pub enum ZIndex {
89 Auto,
91 Zero,
93 Ten,
95 Twenty,
97 Thirty,
99 Forty,
101 Fifty,
103 OneHundred,
105 TwoHundred,
107 ThreeHundred,
109 FourHundred,
111 FiveHundred,
113 OneThousand,
115 Max,
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
121pub enum Float {
122 Right,
124 Left,
126 None,
128}
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
132pub enum Clear {
133 Left,
135 Right,
137 Both,
139 None,
141}
142
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
145pub enum Isolation {
146 Isolate,
148 Auto,
150}
151
152#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
154pub enum ObjectFit {
155 Contain,
157 Cover,
159 Fill,
161 None,
163 ScaleDown,
165}
166
167#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
169pub enum ObjectPosition {
170 Bottom,
172 Center,
174 Left,
176 LeftBottom,
178 LeftTop,
180 Right,
182 RightBottom,
184 RightTop,
186 Top,
188}
189
190#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
192pub enum OverscrollBehavior {
193 Auto,
195 Contain,
197 None,
199}
200
201#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
203pub enum Visibility {
204 Visible,
206 Hidden,
208 Collapse,
210}
211
212impl Display {
213 pub fn to_class_name(&self) -> String {
214 match self {
215 Display::Block => "block".to_string(),
216 Display::Inline => "inline".to_string(),
217 Display::InlineBlock => "inline-block".to_string(),
218 Display::Flex => "flex".to_string(),
219 Display::InlineFlex => "inline-flex".to_string(),
220 Display::Grid => "grid".to_string(),
221 Display::InlineGrid => "inline-grid".to_string(),
222 Display::Table => "table".to_string(),
223 Display::InlineTable => "inline-table".to_string(),
224 Display::TableCaption => "table-caption".to_string(),
225 Display::TableCell => "table-cell".to_string(),
226 Display::TableColumn => "table-column".to_string(),
227 Display::TableColumnGroup => "table-column-group".to_string(),
228 Display::TableFooterGroup => "table-footer-group".to_string(),
229 Display::TableHeaderGroup => "table-header-group".to_string(),
230 Display::TableRow => "table-row".to_string(),
231 Display::TableRowGroup => "table-row-group".to_string(),
232 Display::FlowRoot => "flow-root".to_string(),
233 Display::Contents => "contents".to_string(),
234 Display::ListItem => "list-item".to_string(),
235 Display::Hidden => "hidden".to_string(),
236 }
237 }
238
239 pub fn to_css_value(&self) -> String {
240 match self {
241 Display::Block => "block".to_string(),
242 Display::Inline => "inline".to_string(),
243 Display::InlineBlock => "inline-block".to_string(),
244 Display::Flex => "flex".to_string(),
245 Display::InlineFlex => "inline-flex".to_string(),
246 Display::Grid => "grid".to_string(),
247 Display::InlineGrid => "inline-grid".to_string(),
248 Display::Table => "table".to_string(),
249 Display::InlineTable => "inline-table".to_string(),
250 Display::TableCaption => "table-caption".to_string(),
251 Display::TableCell => "table-cell".to_string(),
252 Display::TableColumn => "table-column".to_string(),
253 Display::TableColumnGroup => "table-column-group".to_string(),
254 Display::TableFooterGroup => "table-footer-group".to_string(),
255 Display::TableHeaderGroup => "table-header-group".to_string(),
256 Display::TableRow => "table-row".to_string(),
257 Display::TableRowGroup => "table-row-group".to_string(),
258 Display::FlowRoot => "flow-root".to_string(),
259 Display::Contents => "contents".to_string(),
260 Display::ListItem => "list-item".to_string(),
261 Display::Hidden => "none".to_string(),
262 }
263 }
264}
265
266impl Position {
267 pub fn to_class_name(&self) -> String {
268 match self {
269 Position::Static => "static".to_string(),
270 Position::Fixed => "fixed".to_string(),
271 Position::Absolute => "absolute".to_string(),
272 Position::Relative => "relative".to_string(),
273 Position::Sticky => "sticky".to_string(),
274 }
275 }
276
277 pub fn to_css_value(&self) -> String {
278 match self {
279 Position::Static => "static".to_string(),
280 Position::Fixed => "fixed".to_string(),
281 Position::Absolute => "absolute".to_string(),
282 Position::Relative => "relative".to_string(),
283 Position::Sticky => "sticky".to_string(),
284 }
285 }
286}
287
288impl Overflow {
289 pub fn to_class_name(&self) -> String {
290 match self {
291 Overflow::Auto => "auto".to_string(),
292 Overflow::Hidden => "hidden".to_string(),
293 Overflow::Clip => "clip".to_string(),
294 Overflow::Visible => "visible".to_string(),
295 Overflow::Scroll => "scroll".to_string(),
296 }
297 }
298
299 pub fn to_css_value(&self) -> String {
300 match self {
301 Overflow::Auto => "auto".to_string(),
302 Overflow::Hidden => "hidden".to_string(),
303 Overflow::Clip => "clip".to_string(),
304 Overflow::Visible => "visible".to_string(),
305 Overflow::Scroll => "scroll".to_string(),
306 }
307 }
308}
309
310impl ZIndex {
311 pub fn to_class_name(&self) -> String {
312 match self {
313 ZIndex::Auto => "auto".to_string(),
314 ZIndex::Zero => "0".to_string(),
315 ZIndex::Ten => "10".to_string(),
316 ZIndex::Twenty => "20".to_string(),
317 ZIndex::Thirty => "30".to_string(),
318 ZIndex::Forty => "40".to_string(),
319 ZIndex::Fifty => "50".to_string(),
320 ZIndex::OneHundred => "100".to_string(),
321 ZIndex::TwoHundred => "200".to_string(),
322 ZIndex::ThreeHundred => "300".to_string(),
323 ZIndex::FourHundred => "400".to_string(),
324 ZIndex::FiveHundred => "500".to_string(),
325 ZIndex::OneThousand => "1000".to_string(),
326 ZIndex::Max => "9999".to_string(),
327 }
328 }
329
330 pub fn to_css_value(&self) -> String {
331 match self {
332 ZIndex::Auto => "auto".to_string(),
333 ZIndex::Zero => "0".to_string(),
334 ZIndex::Ten => "10".to_string(),
335 ZIndex::Twenty => "20".to_string(),
336 ZIndex::Thirty => "30".to_string(),
337 ZIndex::Forty => "40".to_string(),
338 ZIndex::Fifty => "50".to_string(),
339 ZIndex::OneHundred => "100".to_string(),
340 ZIndex::TwoHundred => "200".to_string(),
341 ZIndex::ThreeHundred => "300".to_string(),
342 ZIndex::FourHundred => "400".to_string(),
343 ZIndex::FiveHundred => "500".to_string(),
344 ZIndex::OneThousand => "1000".to_string(),
345 ZIndex::Max => "9999".to_string(),
346 }
347 }
348
349 pub fn all_values() -> Vec<ZIndex> {
351 vec![
352 ZIndex::Auto,
353 ZIndex::Zero,
354 ZIndex::Ten,
355 ZIndex::Twenty,
356 ZIndex::Thirty,
357 ZIndex::Forty,
358 ZIndex::Fifty,
359 ZIndex::OneHundred,
360 ZIndex::TwoHundred,
361 ZIndex::ThreeHundred,
362 ZIndex::FourHundred,
363 ZIndex::FiveHundred,
364 ZIndex::OneThousand,
365 ZIndex::Max,
366 ]
367 }
368
369 pub fn to_numeric_value(&self) -> Option<i32> {
371 match self {
372 ZIndex::Auto => None,
373 ZIndex::Zero => Some(0),
374 ZIndex::Ten => Some(10),
375 ZIndex::Twenty => Some(20),
376 ZIndex::Thirty => Some(30),
377 ZIndex::Forty => Some(40),
378 ZIndex::Fifty => Some(50),
379 ZIndex::OneHundred => Some(100),
380 ZIndex::TwoHundred => Some(200),
381 ZIndex::ThreeHundred => Some(300),
382 ZIndex::FourHundred => Some(400),
383 ZIndex::FiveHundred => Some(500),
384 ZIndex::OneThousand => Some(1000),
385 ZIndex::Max => Some(9999),
386 }
387 }
388}
389
390impl Float {
391 pub fn to_class_name(&self) -> String {
392 match self {
393 Float::Right => "right".to_string(),
394 Float::Left => "left".to_string(),
395 Float::None => "none".to_string(),
396 }
397 }
398
399 pub fn to_css_value(&self) -> String {
400 match self {
401 Float::Right => "right".to_string(),
402 Float::Left => "left".to_string(),
403 Float::None => "none".to_string(),
404 }
405 }
406}
407
408impl Clear {
409 pub fn to_class_name(&self) -> String {
410 match self {
411 Clear::Left => "left".to_string(),
412 Clear::Right => "right".to_string(),
413 Clear::Both => "both".to_string(),
414 Clear::None => "none".to_string(),
415 }
416 }
417
418 pub fn to_css_value(&self) -> String {
419 match self {
420 Clear::Left => "left".to_string(),
421 Clear::Right => "right".to_string(),
422 Clear::Both => "both".to_string(),
423 Clear::None => "none".to_string(),
424 }
425 }
426}
427
428impl Isolation {
429 pub fn to_class_name(&self) -> String {
430 match self {
431 Isolation::Isolate => "isolate".to_string(),
432 Isolation::Auto => "auto".to_string(),
433 }
434 }
435
436 pub fn to_css_value(&self) -> String {
437 match self {
438 Isolation::Isolate => "isolate".to_string(),
439 Isolation::Auto => "auto".to_string(),
440 }
441 }
442}
443
444impl ObjectFit {
445 pub fn to_class_name(&self) -> String {
446 match self {
447 ObjectFit::Contain => "contain".to_string(),
448 ObjectFit::Cover => "cover".to_string(),
449 ObjectFit::Fill => "fill".to_string(),
450 ObjectFit::None => "none".to_string(),
451 ObjectFit::ScaleDown => "scale-down".to_string(),
452 }
453 }
454
455 pub fn to_css_value(&self) -> String {
456 match self {
457 ObjectFit::Contain => "contain".to_string(),
458 ObjectFit::Cover => "cover".to_string(),
459 ObjectFit::Fill => "fill".to_string(),
460 ObjectFit::None => "none".to_string(),
461 ObjectFit::ScaleDown => "scale-down".to_string(),
462 }
463 }
464}
465
466impl ObjectPosition {
467 pub fn to_class_name(&self) -> String {
468 match self {
469 ObjectPosition::Bottom => "bottom".to_string(),
470 ObjectPosition::Center => "center".to_string(),
471 ObjectPosition::Left => "left".to_string(),
472 ObjectPosition::LeftBottom => "left-bottom".to_string(),
473 ObjectPosition::LeftTop => "left-top".to_string(),
474 ObjectPosition::Right => "right".to_string(),
475 ObjectPosition::RightBottom => "right-bottom".to_string(),
476 ObjectPosition::RightTop => "right-top".to_string(),
477 ObjectPosition::Top => "top".to_string(),
478 }
479 }
480
481 pub fn to_css_value(&self) -> String {
482 match self {
483 ObjectPosition::Bottom => "bottom".to_string(),
484 ObjectPosition::Center => "center".to_string(),
485 ObjectPosition::Left => "left".to_string(),
486 ObjectPosition::LeftBottom => "left bottom".to_string(),
487 ObjectPosition::LeftTop => "left top".to_string(),
488 ObjectPosition::Right => "right".to_string(),
489 ObjectPosition::RightBottom => "right bottom".to_string(),
490 ObjectPosition::RightTop => "right top".to_string(),
491 ObjectPosition::Top => "top".to_string(),
492 }
493 }
494}
495
496impl OverscrollBehavior {
497 pub fn to_class_name(&self) -> String {
498 match self {
499 OverscrollBehavior::Auto => "auto".to_string(),
500 OverscrollBehavior::Contain => "contain".to_string(),
501 OverscrollBehavior::None => "none".to_string(),
502 }
503 }
504
505 pub fn to_css_value(&self) -> String {
506 match self {
507 OverscrollBehavior::Auto => "auto".to_string(),
508 OverscrollBehavior::Contain => "contain".to_string(),
509 OverscrollBehavior::None => "none".to_string(),
510 }
511 }
512}
513
514impl Visibility {
515 pub fn to_class_name(&self) -> String {
516 match self {
517 Visibility::Visible => "visible".to_string(),
518 Visibility::Hidden => "invisible".to_string(),
519 Visibility::Collapse => "collapse".to_string(),
520 }
521 }
522
523 pub fn to_css_value(&self) -> String {
524 match self {
525 Visibility::Visible => "visible".to_string(),
526 Visibility::Hidden => "hidden".to_string(),
527 Visibility::Collapse => "collapse".to_string(),
528 }
529 }
530}
531
532impl fmt::Display for Display {
533 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
534 write!(f, "{}", self.to_class_name())
535 }
536}
537
538impl fmt::Display for Position {
539 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
540 write!(f, "{}", self.to_class_name())
541 }
542}
543
544impl fmt::Display for Overflow {
545 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546 write!(f, "{}", self.to_class_name())
547 }
548}
549
550impl fmt::Display for ZIndex {
551 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
552 write!(f, "{}", self.to_class_name())
553 }
554}
555
556pub trait DisplayUtilities {
558 fn display(self, display: Display) -> Self;
559}
560
561impl DisplayUtilities for ClassBuilder {
562 fn display(self, display: Display) -> Self {
563 self.class(display.to_class_name())
564 }
565}
566
567pub trait PositionUtilities {
569 fn position(self, position: Position) -> Self;
570}
571
572impl PositionUtilities for ClassBuilder {
573 fn position(self, position: Position) -> Self {
574 self.class(position.to_class_name())
575 }
576}
577
578pub trait OverflowUtilities {
580 fn overflow(self, overflow: Overflow) -> Self;
581 fn overflow_x(self, overflow: Overflow) -> Self;
582 fn overflow_y(self, overflow: Overflow) -> Self;
583}
584
585impl OverflowUtilities for ClassBuilder {
586 fn overflow(self, overflow: Overflow) -> Self {
587 self.class(format!("overflow-{}", overflow.to_class_name()))
588 }
589
590 fn overflow_x(self, overflow: Overflow) -> Self {
591 self.class(format!("overflow-x-{}", overflow.to_class_name()))
592 }
593
594 fn overflow_y(self, overflow: Overflow) -> Self {
595 self.class(format!("overflow-y-{}", overflow.to_class_name()))
596 }
597}
598
599pub trait ZIndexUtilities {
601 fn z_index(self, z_index: ZIndex) -> Self;
602}
603
604impl ZIndexUtilities for ClassBuilder {
605 fn z_index(self, z_index: ZIndex) -> Self {
606 self.class(format!("z-{}", z_index.to_class_name()))
607 }
608}
609
610pub trait FloatUtilities {
612 fn float(self, float: Float) -> Self;
613}
614
615impl FloatUtilities for ClassBuilder {
616 fn float(self, float: Float) -> Self {
617 self.class(format!("float-{}", float.to_class_name()))
618 }
619}
620
621pub trait ClearUtilities {
623 fn clear(self, clear: Clear) -> Self;
624}
625
626impl ClearUtilities for ClassBuilder {
627 fn clear(self, clear: Clear) -> Self {
628 self.class(format!("clear-{}", clear.to_class_name()))
629 }
630}
631
632pub trait IsolationUtilities {
634 fn isolation(self, isolation: Isolation) -> Self;
635}
636
637impl IsolationUtilities for ClassBuilder {
638 fn isolation(self, isolation: Isolation) -> Self {
639 self.class(format!("isolation-{}", isolation.to_class_name()))
640 }
641}
642
643pub trait ObjectFitUtilities {
645 fn object_fit(self, object_fit: ObjectFit) -> Self;
646}
647
648impl ObjectFitUtilities for ClassBuilder {
649 fn object_fit(self, object_fit: ObjectFit) -> Self {
650 self.class(format!("object-{}", object_fit.to_class_name()))
651 }
652}
653
654pub trait ObjectPositionUtilities {
656 fn object_position(self, object_position: ObjectPosition) -> Self;
657}
658
659impl ObjectPositionUtilities for ClassBuilder {
660 fn object_position(self, object_position: ObjectPosition) -> Self {
661 self.class(format!("object-{}", object_position.to_class_name()))
662 }
663}
664
665pub trait OverscrollBehaviorUtilities {
667 fn overscroll_behavior(self, behavior: OverscrollBehavior) -> Self;
668 fn overscroll_behavior_x(self, behavior: OverscrollBehavior) -> Self;
669 fn overscroll_behavior_y(self, behavior: OverscrollBehavior) -> Self;
670}
671
672impl OverscrollBehaviorUtilities for ClassBuilder {
673 fn overscroll_behavior(self, behavior: OverscrollBehavior) -> Self {
674 self.class(format!("overscroll-{}", behavior.to_class_name()))
675 }
676
677 fn overscroll_behavior_x(self, behavior: OverscrollBehavior) -> Self {
678 self.class(format!("overscroll-x-{}", behavior.to_class_name()))
679 }
680
681 fn overscroll_behavior_y(self, behavior: OverscrollBehavior) -> Self {
682 self.class(format!("overscroll-y-{}", behavior.to_class_name()))
683 }
684}
685
686pub trait VisibilityUtilities {
688 fn visibility(self, visibility: Visibility) -> Self;
689}
690
691impl VisibilityUtilities for ClassBuilder {
692 fn visibility(self, visibility: Visibility) -> Self {
693 self.class(visibility.to_class_name())
694 }
695}
696
697pub trait PositioningUtilities {
699 fn top(self, value: crate::utilities::spacing::SpacingValue) -> Self;
701
702 fn right(self, value: crate::utilities::spacing::SpacingValue) -> Self;
704
705 fn bottom(self, value: crate::utilities::spacing::SpacingValue) -> Self;
707
708 fn left(self, value: crate::utilities::spacing::SpacingValue) -> Self;
710
711 fn inset(self, value: crate::utilities::spacing::SpacingValue) -> Self;
713
714 fn inset_x(self, value: crate::utilities::spacing::SpacingValue) -> Self;
716
717 fn inset_y(self, value: crate::utilities::spacing::SpacingValue) -> Self;
719}
720
721impl PositioningUtilities for ClassBuilder {
722 fn top(self, value: crate::utilities::spacing::SpacingValue) -> Self {
723 self.class(format!("top-{}", value.to_class_name()))
724 }
725
726 fn right(self, value: crate::utilities::spacing::SpacingValue) -> Self {
727 self.class(format!("right-{}", value.to_class_name()))
728 }
729
730 fn bottom(self, value: crate::utilities::spacing::SpacingValue) -> Self {
731 self.class(format!("bottom-{}", value.to_class_name()))
732 }
733
734 fn left(self, value: crate::utilities::spacing::SpacingValue) -> Self {
735 self.class(format!("left-{}", value.to_class_name()))
736 }
737
738 fn inset(self, value: crate::utilities::spacing::SpacingValue) -> Self {
739 self.class(format!("inset-{}", value.to_class_name()))
740 }
741
742 fn inset_x(self, value: crate::utilities::spacing::SpacingValue) -> Self {
743 self.class(format!("inset-x-{}", value.to_class_name()))
744 }
745
746 fn inset_y(self, value: crate::utilities::spacing::SpacingValue) -> Self {
747 self.class(format!("inset-y-{}", value.to_class_name()))
748 }
749}
750
751impl ClassBuilder {
753 pub fn top_4(self) -> Self {
755 self.top(crate::utilities::spacing::SpacingValue::Integer(4))
756 }
757
758 pub fn right_2(self) -> Self {
760 self.right(crate::utilities::spacing::SpacingValue::Integer(2))
761 }
762
763 pub fn bottom_6(self) -> Self {
765 self.bottom(crate::utilities::spacing::SpacingValue::Integer(6))
766 }
767
768 pub fn left_8(self) -> Self {
770 self.left(crate::utilities::spacing::SpacingValue::Integer(8))
771 }
772
773 pub fn inset_0(self) -> Self {
775 self.inset(crate::utilities::spacing::SpacingValue::Zero)
776 }
777
778 pub fn inset_x_4(self) -> Self {
780 self.inset_x(crate::utilities::spacing::SpacingValue::Integer(4))
781 }
782
783 pub fn inset_y_2(self) -> Self {
785 self.inset_y(crate::utilities::spacing::SpacingValue::Integer(2))
786 }
787}
788
789#[cfg(test)]
790mod tests {
791 use super::*;
792
793 #[test]
794 fn test_display_utilities() {
795 let classes = ClassBuilder::new()
796 .display(Display::Block)
797 .display(Display::Flex)
798 .display(Display::Grid)
799 .display(Display::Hidden)
800 .build();
801
802 let css_classes = classes.to_css_classes();
803 assert!(css_classes.contains("block"));
804 assert!(css_classes.contains("flex"));
805 assert!(css_classes.contains("grid"));
806 assert!(css_classes.contains("hidden"));
807 }
808
809 #[test]
810 fn test_position_utilities() {
811 let classes = ClassBuilder::new()
812 .position(Position::Static)
813 .position(Position::Relative)
814 .position(Position::Absolute)
815 .position(Position::Fixed)
816 .position(Position::Sticky)
817 .build();
818
819 let css_classes = classes.to_css_classes();
820 assert!(css_classes.contains("static"));
821 assert!(css_classes.contains("relative"));
822 assert!(css_classes.contains("absolute"));
823 assert!(css_classes.contains("fixed"));
824 assert!(css_classes.contains("sticky"));
825 }
826
827 #[test]
828 fn test_overflow_utilities() {
829 let classes = ClassBuilder::new()
830 .overflow(Overflow::Auto)
831 .overflow(Overflow::Hidden)
832 .overflow(Overflow::Visible)
833 .overflow(Overflow::Scroll)
834 .overflow_x(Overflow::Hidden)
835 .overflow_y(Overflow::Scroll)
836 .build();
837
838 let css_classes = classes.to_css_classes();
839 assert!(css_classes.contains("overflow-auto"));
840 assert!(css_classes.contains("overflow-hidden"));
841 assert!(css_classes.contains("overflow-visible"));
842 assert!(css_classes.contains("overflow-scroll"));
843 assert!(css_classes.contains("overflow-x-hidden"));
844 assert!(css_classes.contains("overflow-y-scroll"));
845 }
846
847 #[test]
848 fn test_z_index_utilities() {
849 let classes = ClassBuilder::new()
850 .z_index(ZIndex::Auto)
851 .z_index(ZIndex::Zero)
852 .z_index(ZIndex::Ten)
853 .z_index(ZIndex::Fifty)
854 .z_index(ZIndex::OneHundred)
855 .z_index(ZIndex::FiveHundred)
856 .z_index(ZIndex::OneThousand)
857 .z_index(ZIndex::Max)
858 .build();
859
860 let css_classes = classes.to_css_classes();
861 assert!(css_classes.contains("z-auto"));
862 assert!(css_classes.contains("z-0"));
863 assert!(css_classes.contains("z-10"));
864 assert!(css_classes.contains("z-50"));
865 assert!(css_classes.contains("z-100"));
866 assert!(css_classes.contains("z-500"));
867 assert!(css_classes.contains("z-1000"));
868 assert!(css_classes.contains("z-9999"));
869 }
870
871 #[test]
872 fn test_extended_z_index_values() {
873 let all_z_values = ZIndex::all_values();
875 assert_eq!(all_z_values.len(), 14);
876 assert!(all_z_values.contains(&ZIndex::Auto));
877 assert!(all_z_values.contains(&ZIndex::OneHundred));
878 assert!(all_z_values.contains(&ZIndex::Max));
879
880 assert_eq!(ZIndex::Auto.to_numeric_value(), None);
882 assert_eq!(ZIndex::Zero.to_numeric_value(), Some(0));
883 assert_eq!(ZIndex::OneHundred.to_numeric_value(), Some(100));
884 assert_eq!(ZIndex::FiveHundred.to_numeric_value(), Some(500));
885 assert_eq!(ZIndex::OneThousand.to_numeric_value(), Some(1000));
886 assert_eq!(ZIndex::Max.to_numeric_value(), Some(9999));
887
888 assert_eq!(ZIndex::OneHundred.to_css_value(), "100");
890 assert_eq!(ZIndex::TwoHundred.to_css_value(), "200");
891 assert_eq!(ZIndex::Max.to_css_value(), "9999");
892 }
893
894 #[test]
895 fn test_float_utilities() {
896 let classes = ClassBuilder::new()
897 .float(Float::Left)
898 .float(Float::Right)
899 .float(Float::None)
900 .build();
901
902 let css_classes = classes.to_css_classes();
903 assert!(css_classes.contains("float-left"));
904 assert!(css_classes.contains("float-right"));
905 assert!(css_classes.contains("float-none"));
906 }
907
908 #[test]
909 fn test_clear_utilities() {
910 let classes = ClassBuilder::new()
911 .clear(Clear::Left)
912 .clear(Clear::Right)
913 .clear(Clear::Both)
914 .clear(Clear::None)
915 .build();
916
917 let css_classes = classes.to_css_classes();
918 assert!(css_classes.contains("clear-left"));
919 assert!(css_classes.contains("clear-right"));
920 assert!(css_classes.contains("clear-both"));
921 assert!(css_classes.contains("clear-none"));
922 }
923
924 #[test]
925 fn test_isolation_utilities() {
926 let classes = ClassBuilder::new()
927 .isolation(Isolation::Isolate)
928 .isolation(Isolation::Auto)
929 .build();
930
931 let css_classes = classes.to_css_classes();
932 assert!(css_classes.contains("isolation-isolate"));
933 assert!(css_classes.contains("isolation-auto"));
934 }
935
936 #[test]
937 fn test_object_fit_utilities() {
938 let classes = ClassBuilder::new()
939 .object_fit(ObjectFit::Contain)
940 .object_fit(ObjectFit::Cover)
941 .object_fit(ObjectFit::Fill)
942 .object_fit(ObjectFit::None)
943 .object_fit(ObjectFit::ScaleDown)
944 .build();
945
946 let css_classes = classes.to_css_classes();
947 assert!(css_classes.contains("object-contain"));
948 assert!(css_classes.contains("object-cover"));
949 assert!(css_classes.contains("object-fill"));
950 assert!(css_classes.contains("object-none"));
951 assert!(css_classes.contains("object-scale-down"));
952 }
953
954 #[test]
955 fn test_object_position_utilities() {
956 let classes = ClassBuilder::new()
957 .object_position(ObjectPosition::Center)
958 .object_position(ObjectPosition::Top)
959 .object_position(ObjectPosition::Bottom)
960 .object_position(ObjectPosition::Left)
961 .object_position(ObjectPosition::Right)
962 .build();
963
964 let css_classes = classes.to_css_classes();
965 assert!(css_classes.contains("object-center"));
966 assert!(css_classes.contains("object-top"));
967 assert!(css_classes.contains("object-bottom"));
968 assert!(css_classes.contains("object-left"));
969 assert!(css_classes.contains("object-right"));
970 }
971
972 #[test]
973 fn test_overscroll_behavior_utilities() {
974 let classes = ClassBuilder::new()
975 .overscroll_behavior(OverscrollBehavior::Auto)
976 .overscroll_behavior(OverscrollBehavior::Contain)
977 .overscroll_behavior(OverscrollBehavior::None)
978 .overscroll_behavior_x(OverscrollBehavior::Contain)
979 .overscroll_behavior_y(OverscrollBehavior::None)
980 .build();
981
982 let css_classes = classes.to_css_classes();
983 assert!(css_classes.contains("overscroll-auto"));
984 assert!(css_classes.contains("overscroll-contain"));
985 assert!(css_classes.contains("overscroll-none"));
986 assert!(css_classes.contains("overscroll-x-contain"));
987 assert!(css_classes.contains("overscroll-y-none"));
988 }
989
990 #[test]
991 fn test_visibility_utilities() {
992 let classes = ClassBuilder::new()
993 .visibility(Visibility::Visible)
994 .visibility(Visibility::Hidden)
995 .visibility(Visibility::Collapse)
996 .build();
997
998 let css_classes = classes.to_css_classes();
999 assert!(css_classes.contains("visible"));
1000 assert!(css_classes.contains("invisible"));
1001 assert!(css_classes.contains("collapse"));
1002 }
1003
1004 #[test]
1005 fn test_complex_layout_combination() {
1006 let classes = ClassBuilder::new()
1007 .display(Display::Flex)
1008 .position(Position::Relative)
1009 .overflow(Overflow::Hidden)
1010 .z_index(ZIndex::Ten)
1011 .float(Float::None)
1012 .clear(Clear::Both)
1013 .isolation(Isolation::Isolate)
1014 .object_fit(ObjectFit::Cover)
1015 .object_position(ObjectPosition::Center)
1016 .overscroll_behavior(OverscrollBehavior::Contain)
1017 .visibility(Visibility::Visible)
1018 .build();
1019
1020 let css_classes = classes.to_css_classes();
1021 assert!(css_classes.contains("flex"));
1022 assert!(css_classes.contains("relative"));
1023 assert!(css_classes.contains("overflow-hidden"));
1024 assert!(css_classes.contains("z-10"));
1025 assert!(css_classes.contains("float-none"));
1026 assert!(css_classes.contains("clear-both"));
1027 assert!(css_classes.contains("isolation-isolate"));
1028 assert!(css_classes.contains("object-cover"));
1029 assert!(css_classes.contains("object-center"));
1030 assert!(css_classes.contains("overscroll-contain"));
1031 assert!(css_classes.contains("visible"));
1032 }
1033
1034 #[test]
1036 fn test_positioning_utilities() {
1037 let classes = ClassBuilder::new()
1039 .top_4() .right_2() .bottom_6() .left_8() .inset_0() .inset_x_4() .inset_y_2() .build();
1047
1048 let css_classes = classes.to_css_classes();
1049 assert!(css_classes.contains("top-4"));
1050 assert!(css_classes.contains("right-2"));
1051 assert!(css_classes.contains("bottom-6"));
1052 assert!(css_classes.contains("left-8"));
1053 assert!(css_classes.contains("inset-0"));
1054 assert!(css_classes.contains("inset-x-4"));
1055 assert!(css_classes.contains("inset-y-2"));
1056 }
1057
1058 #[test]
1059 fn test_display_class_names() {
1060 assert_eq!(Display::Block.to_class_name(), "block");
1061 assert_eq!(Display::Inline.to_class_name(), "inline");
1062 assert_eq!(Display::InlineBlock.to_class_name(), "inline-block");
1063 assert_eq!(Display::Flex.to_class_name(), "flex");
1064 assert_eq!(Display::InlineFlex.to_class_name(), "inline-flex");
1065 assert_eq!(Display::Grid.to_class_name(), "grid");
1066 assert_eq!(Display::InlineGrid.to_class_name(), "inline-grid");
1067 assert_eq!(Display::Table.to_class_name(), "table");
1068 assert_eq!(Display::InlineTable.to_class_name(), "inline-table");
1069 assert_eq!(Display::TableCaption.to_class_name(), "table-caption");
1070 assert_eq!(Display::TableCell.to_class_name(), "table-cell");
1071 assert_eq!(Display::TableColumn.to_class_name(), "table-column");
1072 assert_eq!(Display::TableColumnGroup.to_class_name(), "table-column-group");
1073 assert_eq!(Display::TableFooterGroup.to_class_name(), "table-footer-group");
1074 assert_eq!(Display::TableHeaderGroup.to_class_name(), "table-header-group");
1075 assert_eq!(Display::TableRow.to_class_name(), "table-row");
1076 assert_eq!(Display::TableRowGroup.to_class_name(), "table-row-group");
1077 assert_eq!(Display::FlowRoot.to_class_name(), "flow-root");
1078 assert_eq!(Display::Contents.to_class_name(), "contents");
1079 assert_eq!(Display::ListItem.to_class_name(), "list-item");
1080 assert_eq!(Display::Hidden.to_class_name(), "hidden");
1081 }
1082
1083 #[test]
1084 fn test_display_css_values() {
1085 assert_eq!(Display::Block.to_css_value(), "block");
1086 assert_eq!(Display::Inline.to_css_value(), "inline");
1087 assert_eq!(Display::InlineBlock.to_css_value(), "inline-block");
1088 assert_eq!(Display::Flex.to_css_value(), "flex");
1089 assert_eq!(Display::InlineFlex.to_css_value(), "inline-flex");
1090 assert_eq!(Display::Grid.to_css_value(), "grid");
1091 assert_eq!(Display::InlineGrid.to_css_value(), "inline-grid");
1092 assert_eq!(Display::Table.to_css_value(), "table");
1093 assert_eq!(Display::InlineTable.to_css_value(), "inline-table");
1094 assert_eq!(Display::TableCaption.to_css_value(), "table-caption");
1095 assert_eq!(Display::TableCell.to_css_value(), "table-cell");
1096 assert_eq!(Display::TableColumn.to_css_value(), "table-column");
1097 assert_eq!(Display::TableColumnGroup.to_css_value(), "table-column-group");
1098 assert_eq!(Display::TableFooterGroup.to_css_value(), "table-footer-group");
1099 assert_eq!(Display::TableHeaderGroup.to_css_value(), "table-header-group");
1100 assert_eq!(Display::TableRow.to_css_value(), "table-row");
1101 assert_eq!(Display::TableRowGroup.to_css_value(), "table-row-group");
1102 assert_eq!(Display::FlowRoot.to_css_value(), "flow-root");
1103 assert_eq!(Display::Contents.to_css_value(), "contents");
1104 assert_eq!(Display::ListItem.to_css_value(), "list-item");
1105 assert_eq!(Display::Hidden.to_css_value(), "none");
1106 }
1107
1108 #[test]
1109 fn test_position_class_names() {
1110 assert_eq!(Position::Static.to_class_name(), "static");
1111 assert_eq!(Position::Fixed.to_class_name(), "fixed");
1112 assert_eq!(Position::Absolute.to_class_name(), "absolute");
1113 assert_eq!(Position::Relative.to_class_name(), "relative");
1114 assert_eq!(Position::Sticky.to_class_name(), "sticky");
1115 }
1116
1117 #[test]
1118 fn test_position_css_values() {
1119 assert_eq!(Position::Static.to_css_value(), "static");
1120 assert_eq!(Position::Fixed.to_css_value(), "fixed");
1121 assert_eq!(Position::Absolute.to_css_value(), "absolute");
1122 assert_eq!(Position::Relative.to_css_value(), "relative");
1123 assert_eq!(Position::Sticky.to_css_value(), "sticky");
1124 }
1125
1126 #[test]
1127 fn test_overflow_class_names() {
1128 assert_eq!(Overflow::Auto.to_class_name(), "auto");
1129 assert_eq!(Overflow::Hidden.to_class_name(), "hidden");
1130 assert_eq!(Overflow::Clip.to_class_name(), "clip");
1131 assert_eq!(Overflow::Visible.to_class_name(), "visible");
1132 assert_eq!(Overflow::Scroll.to_class_name(), "scroll");
1133 }
1134
1135 #[test]
1136 fn test_overflow_css_values() {
1137 assert_eq!(Overflow::Auto.to_css_value(), "auto");
1138 assert_eq!(Overflow::Hidden.to_css_value(), "hidden");
1139 assert_eq!(Overflow::Clip.to_css_value(), "clip");
1140 assert_eq!(Overflow::Visible.to_css_value(), "visible");
1141 assert_eq!(Overflow::Scroll.to_css_value(), "scroll");
1142 }
1143
1144 #[test]
1145 fn test_z_index_class_names() {
1146 assert_eq!(ZIndex::Auto.to_class_name(), "auto");
1147 assert_eq!(ZIndex::Zero.to_class_name(), "0");
1148 assert_eq!(ZIndex::Ten.to_class_name(), "10");
1149 assert_eq!(ZIndex::Twenty.to_class_name(), "20");
1150 assert_eq!(ZIndex::Thirty.to_class_name(), "30");
1151 assert_eq!(ZIndex::Forty.to_class_name(), "40");
1152 assert_eq!(ZIndex::Fifty.to_class_name(), "50");
1153 assert_eq!(ZIndex::OneHundred.to_class_name(), "100");
1154 assert_eq!(ZIndex::TwoHundred.to_class_name(), "200");
1155 assert_eq!(ZIndex::ThreeHundred.to_class_name(), "300");
1156 assert_eq!(ZIndex::FourHundred.to_class_name(), "400");
1157 assert_eq!(ZIndex::FiveHundred.to_class_name(), "500");
1158 assert_eq!(ZIndex::OneThousand.to_class_name(), "1000");
1159 assert_eq!(ZIndex::Max.to_class_name(), "9999");
1160 }
1161
1162 #[test]
1163 fn test_z_index_css_values() {
1164 assert_eq!(ZIndex::Auto.to_css_value(), "auto");
1165 assert_eq!(ZIndex::Zero.to_css_value(), "0");
1166 assert_eq!(ZIndex::Ten.to_css_value(), "10");
1167 assert_eq!(ZIndex::Twenty.to_css_value(), "20");
1168 assert_eq!(ZIndex::Thirty.to_css_value(), "30");
1169 assert_eq!(ZIndex::Forty.to_css_value(), "40");
1170 assert_eq!(ZIndex::Fifty.to_css_value(), "50");
1171 assert_eq!(ZIndex::OneHundred.to_css_value(), "100");
1172 assert_eq!(ZIndex::TwoHundred.to_css_value(), "200");
1173 assert_eq!(ZIndex::ThreeHundred.to_css_value(), "300");
1174 assert_eq!(ZIndex::FourHundred.to_css_value(), "400");
1175 assert_eq!(ZIndex::FiveHundred.to_css_value(), "500");
1176 assert_eq!(ZIndex::OneThousand.to_css_value(), "1000");
1177 assert_eq!(ZIndex::Max.to_css_value(), "9999");
1178 }
1179
1180 #[test]
1181 fn test_float_class_names() {
1182 assert_eq!(Float::Right.to_class_name(), "right");
1183 assert_eq!(Float::Left.to_class_name(), "left");
1184 assert_eq!(Float::None.to_class_name(), "none");
1185 }
1186
1187 #[test]
1188 fn test_float_css_values() {
1189 assert_eq!(Float::Right.to_css_value(), "right");
1190 assert_eq!(Float::Left.to_css_value(), "left");
1191 assert_eq!(Float::None.to_css_value(), "none");
1192 }
1193
1194 #[test]
1195 fn test_clear_class_names() {
1196 assert_eq!(Clear::Left.to_class_name(), "left");
1197 assert_eq!(Clear::Right.to_class_name(), "right");
1198 assert_eq!(Clear::Both.to_class_name(), "both");
1199 assert_eq!(Clear::None.to_class_name(), "none");
1200 }
1201
1202 #[test]
1203 fn test_clear_css_values() {
1204 assert_eq!(Clear::Left.to_css_value(), "left");
1205 assert_eq!(Clear::Right.to_css_value(), "right");
1206 assert_eq!(Clear::Both.to_css_value(), "both");
1207 assert_eq!(Clear::None.to_css_value(), "none");
1208 }
1209
1210 #[test]
1211 fn test_isolation_class_names() {
1212 assert_eq!(Isolation::Isolate.to_class_name(), "isolate");
1213 assert_eq!(Isolation::Auto.to_class_name(), "auto");
1214 }
1215
1216 #[test]
1217 fn test_isolation_css_values() {
1218 assert_eq!(Isolation::Isolate.to_css_value(), "isolate");
1219 assert_eq!(Isolation::Auto.to_css_value(), "auto");
1220 }
1221
1222 #[test]
1223 fn test_object_fit_class_names() {
1224 assert_eq!(ObjectFit::Contain.to_class_name(), "contain");
1225 assert_eq!(ObjectFit::Cover.to_class_name(), "cover");
1226 assert_eq!(ObjectFit::Fill.to_class_name(), "fill");
1227 assert_eq!(ObjectFit::None.to_class_name(), "none");
1228 assert_eq!(ObjectFit::ScaleDown.to_class_name(), "scale-down");
1229 }
1230
1231 #[test]
1232 fn test_object_fit_css_values() {
1233 assert_eq!(ObjectFit::Contain.to_css_value(), "contain");
1234 assert_eq!(ObjectFit::Cover.to_css_value(), "cover");
1235 assert_eq!(ObjectFit::Fill.to_css_value(), "fill");
1236 assert_eq!(ObjectFit::None.to_css_value(), "none");
1237 assert_eq!(ObjectFit::ScaleDown.to_css_value(), "scale-down");
1238 }
1239
1240 #[test]
1241 fn test_object_position_class_names() {
1242 assert_eq!(ObjectPosition::Bottom.to_class_name(), "bottom");
1243 assert_eq!(ObjectPosition::Center.to_class_name(), "center");
1244 assert_eq!(ObjectPosition::Left.to_class_name(), "left");
1245 assert_eq!(ObjectPosition::LeftBottom.to_class_name(), "left-bottom");
1246 assert_eq!(ObjectPosition::LeftTop.to_class_name(), "left-top");
1247 assert_eq!(ObjectPosition::Right.to_class_name(), "right");
1248 assert_eq!(ObjectPosition::RightBottom.to_class_name(), "right-bottom");
1249 assert_eq!(ObjectPosition::RightTop.to_class_name(), "right-top");
1250 assert_eq!(ObjectPosition::Top.to_class_name(), "top");
1251 }
1252
1253 #[test]
1254 fn test_object_position_css_values() {
1255 assert_eq!(ObjectPosition::Bottom.to_css_value(), "bottom");
1256 assert_eq!(ObjectPosition::Center.to_css_value(), "center");
1257 assert_eq!(ObjectPosition::Left.to_css_value(), "left");
1258 assert_eq!(ObjectPosition::LeftBottom.to_css_value(), "left bottom");
1259 assert_eq!(ObjectPosition::LeftTop.to_css_value(), "left top");
1260 assert_eq!(ObjectPosition::Right.to_css_value(), "right");
1261 assert_eq!(ObjectPosition::RightBottom.to_css_value(), "right bottom");
1262 assert_eq!(ObjectPosition::RightTop.to_css_value(), "right top");
1263 assert_eq!(ObjectPosition::Top.to_css_value(), "top");
1264 }
1265
1266 #[test]
1267 fn test_overscroll_behavior_class_names() {
1268 assert_eq!(OverscrollBehavior::Auto.to_class_name(), "auto");
1269 assert_eq!(OverscrollBehavior::Contain.to_class_name(), "contain");
1270 assert_eq!(OverscrollBehavior::None.to_class_name(), "none");
1271 }
1272
1273 #[test]
1274 fn test_overscroll_behavior_css_values() {
1275 assert_eq!(OverscrollBehavior::Auto.to_css_value(), "auto");
1276 assert_eq!(OverscrollBehavior::Contain.to_css_value(), "contain");
1277 assert_eq!(OverscrollBehavior::None.to_css_value(), "none");
1278 }
1279
1280 #[test]
1281 fn test_visibility_class_names() {
1282 assert_eq!(Visibility::Visible.to_class_name(), "visible");
1283 assert_eq!(Visibility::Hidden.to_class_name(), "invisible");
1284 assert_eq!(Visibility::Collapse.to_class_name(), "collapse");
1285 }
1286
1287 #[test]
1288 fn test_visibility_css_values() {
1289 assert_eq!(Visibility::Visible.to_css_value(), "visible");
1290 assert_eq!(Visibility::Hidden.to_css_value(), "hidden");
1291 assert_eq!(Visibility::Collapse.to_css_value(), "collapse");
1292 }
1293
1294 #[test]
1295 fn test_layout_serialization() {
1296 let display = Display::Flex;
1298 let serialized = serde_json::to_string(&display).unwrap();
1299 let deserialized: Display = serde_json::from_str(&serialized).unwrap();
1300 assert_eq!(display, deserialized);
1301
1302 let position = Position::Relative;
1304 let serialized = serde_json::to_string(&position).unwrap();
1305 let deserialized: Position = serde_json::from_str(&serialized).unwrap();
1306 assert_eq!(position, deserialized);
1307
1308 let z_index = ZIndex::Fifty;
1310 let serialized = serde_json::to_string(&z_index).unwrap();
1311 let deserialized: ZIndex = serde_json::from_str(&serialized).unwrap();
1312 assert_eq!(z_index, deserialized);
1313 }
1314
1315 #[test]
1316 fn test_layout_equality_and_hash() {
1317 assert_eq!(Display::Block, Display::Block);
1319 assert_ne!(Display::Block, Display::Flex);
1320
1321 assert_eq!(Position::Relative, Position::Relative);
1323 assert_ne!(Position::Relative, Position::Absolute);
1324
1325 assert_eq!(ZIndex::Ten, ZIndex::Ten);
1327 assert_ne!(ZIndex::Ten, ZIndex::Twenty);
1328
1329 use std::collections::HashMap;
1331 let mut map = HashMap::new();
1332 map.insert(Display::Flex, "flex");
1333 map.insert(Display::Grid, "grid");
1334 assert_eq!(map.get(&Display::Flex), Some(&"flex"));
1335 assert_eq!(map.get(&Display::Grid), Some(&"grid"));
1336 }
1337
1338 #[test]
1339 fn test_comprehensive_layout_utilities() {
1340 let classes = ClassBuilder::new()
1341 .display(Display::Flex)
1342 .position(Position::Relative)
1343 .overflow(Overflow::Hidden)
1344 .overflow_x(Overflow::Auto)
1345 .overflow_y(Overflow::Scroll)
1346 .z_index(ZIndex::Fifty)
1347 .float(Float::None)
1348 .clear(Clear::Both)
1349 .isolation(Isolation::Isolate)
1350 .object_fit(ObjectFit::Cover)
1351 .object_position(ObjectPosition::Center)
1352 .overscroll_behavior(OverscrollBehavior::Contain)
1353 .overscroll_behavior_x(OverscrollBehavior::Auto)
1354 .overscroll_behavior_y(OverscrollBehavior::None)
1355 .visibility(Visibility::Visible)
1356 .build();
1357
1358 let css_classes = classes.to_css_classes();
1359 assert!(css_classes.contains("flex"));
1360 assert!(css_classes.contains("relative"));
1361 assert!(css_classes.contains("overflow-hidden"));
1362 assert!(css_classes.contains("overflow-x-auto"));
1363 assert!(css_classes.contains("overflow-y-scroll"));
1364 assert!(css_classes.contains("z-50"));
1365 assert!(css_classes.contains("float-none"));
1366 assert!(css_classes.contains("clear-both"));
1367 assert!(css_classes.contains("isolation-isolate"));
1368 assert!(css_classes.contains("object-cover"));
1369 assert!(css_classes.contains("object-center"));
1370 assert!(css_classes.contains("overscroll-contain"));
1371 assert!(css_classes.contains("overscroll-x-auto"));
1372 assert!(css_classes.contains("overscroll-y-none"));
1373 assert!(css_classes.contains("visible"));
1374 }
1375}