tailwind_rs_core/utilities/
layout.rs

1//! Layout utilities for tailwind-rs
2//!
3//! This module provides utilities for display, position, overflow, z-index, and other layout properties.
4
5use crate::classes::ClassBuilder;
6use serde::{Deserialize, Serialize};
7use std::fmt;
8
9/// Display values
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11pub enum Display {
12    /// Block display
13    Block,
14    /// Inline display
15    Inline,
16    /// Inline-block display
17    InlineBlock,
18    /// Flex display
19    Flex,
20    /// Inline-flex display
21    InlineFlex,
22    /// Grid display
23    Grid,
24    /// Inline-grid display
25    InlineGrid,
26    /// Table display
27    Table,
28    /// Inline-table display
29    InlineTable,
30    /// Table-caption display
31    TableCaption,
32    /// Table-cell display
33    TableCell,
34    /// Table-column display
35    TableColumn,
36    /// Table-column-group display
37    TableColumnGroup,
38    /// Table-footer-group display
39    TableFooterGroup,
40    /// Table-header-group display
41    TableHeaderGroup,
42    /// Table-row display
43    TableRow,
44    /// Table-row-group display
45    TableRowGroup,
46    /// Flow-root display
47    FlowRoot,
48    /// Contents display
49    Contents,
50    /// List-item display
51    ListItem,
52    /// Hidden display
53    Hidden,
54}
55
56/// Position values
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
58pub enum Position {
59    /// Static position
60    Static,
61    /// Fixed position
62    Fixed,
63    /// Absolute position
64    Absolute,
65    /// Relative position
66    Relative,
67    /// Sticky position
68    Sticky,
69}
70
71/// Overflow values
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
73pub enum Overflow {
74    /// Auto overflow
75    Auto,
76    /// Hidden overflow
77    Hidden,
78    /// Clip overflow
79    Clip,
80    /// Visible overflow
81    Visible,
82    /// Scroll overflow
83    Scroll,
84}
85
86/// Z-index values
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
88pub enum ZIndex {
89    /// Auto z-index
90    Auto,
91    /// Z-index 0
92    Zero,
93    /// Z-index 10
94    Ten,
95    /// Z-index 20
96    Twenty,
97    /// Z-index 30
98    Thirty,
99    /// Z-index 40
100    Forty,
101    /// Z-index 50
102    Fifty,
103    /// Z-index 100
104    OneHundred,
105    /// Z-index 200
106    TwoHundred,
107    /// Z-index 300
108    ThreeHundred,
109    /// Z-index 400
110    FourHundred,
111    /// Z-index 500
112    FiveHundred,
113    /// Z-index 1000
114    OneThousand,
115    /// Z-index 9999
116    Max,
117}
118
119/// Float values
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
121pub enum Float {
122    /// Float right
123    Right,
124    /// Float left
125    Left,
126    /// Float none
127    None,
128}
129
130/// Clear values
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
132pub enum Clear {
133    /// Clear left
134    Left,
135    /// Clear right
136    Right,
137    /// Clear both
138    Both,
139    /// Clear none
140    None,
141}
142
143/// Isolation values
144#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
145pub enum Isolation {
146    /// Isolate
147    Isolate,
148    /// Isolate auto
149    Auto,
150}
151
152/// Object fit values
153#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
154pub enum ObjectFit {
155    /// Contain object fit
156    Contain,
157    /// Cover object fit
158    Cover,
159    /// Fill object fit
160    Fill,
161    /// None object fit
162    None,
163    /// Scale-down object fit
164    ScaleDown,
165}
166
167/// Object position values
168#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
169pub enum ObjectPosition {
170    /// Bottom object position
171    Bottom,
172    /// Center object position
173    Center,
174    /// Left object position
175    Left,
176    /// Left bottom object position
177    LeftBottom,
178    /// Left top object position
179    LeftTop,
180    /// Right object position
181    Right,
182    /// Right bottom object position
183    RightBottom,
184    /// Right top object position
185    RightTop,
186    /// Top object position
187    Top,
188}
189
190/// Overscroll behavior values
191#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
192pub enum OverscrollBehavior {
193    /// Auto overscroll behavior
194    Auto,
195    /// Contain overscroll behavior
196    Contain,
197    /// None overscroll behavior
198    None,
199}
200
201/// Visibility values
202#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
203pub enum Visibility {
204    /// Visible
205    Visible,
206    /// Hidden
207    Hidden,
208    /// Collapse
209    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    /// Get all available z-index values
350    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    /// Get the numeric value of the z-index
370    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
556/// Trait for adding display utilities to a class builder
557pub 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
567/// Trait for adding position utilities to a class builder
568pub 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
578/// Trait for adding overflow utilities to a class builder
579pub 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
599/// Trait for adding z-index utilities to a class builder
600pub 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
610/// Trait for adding float utilities to a class builder
611pub 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
621/// Trait for adding clear utilities to a class builder
622pub 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
632/// Trait for adding isolation utilities to a class builder
633pub 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
643/// Trait for adding object fit utilities to a class builder
644pub 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
654/// Trait for adding object position utilities to a class builder
655pub 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
665/// Trait for adding overscroll behavior utilities to a class builder
666pub 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
686/// Trait for adding visibility utilities to a class builder
687pub 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
697/// Trait for adding positioning utilities to a class builder
698pub trait PositioningUtilities {
699    /// Add top positioning
700    fn top(self, value: crate::utilities::spacing::SpacingValue) -> Self;
701    
702    /// Add right positioning
703    fn right(self, value: crate::utilities::spacing::SpacingValue) -> Self;
704    
705    /// Add bottom positioning
706    fn bottom(self, value: crate::utilities::spacing::SpacingValue) -> Self;
707    
708    /// Add left positioning
709    fn left(self, value: crate::utilities::spacing::SpacingValue) -> Self;
710    
711    /// Add inset positioning (all sides)
712    fn inset(self, value: crate::utilities::spacing::SpacingValue) -> Self;
713    
714    /// Add horizontal inset positioning
715    fn inset_x(self, value: crate::utilities::spacing::SpacingValue) -> Self;
716    
717    /// Add vertical inset positioning
718    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
751/// Convenience methods for positioning utilities
752impl ClassBuilder {
753    /// Add top positioning with value 4
754    pub fn top_4(self) -> Self {
755        self.top(crate::utilities::spacing::SpacingValue::Integer(4))
756    }
757    
758    /// Add right positioning with value 2
759    pub fn right_2(self) -> Self {
760        self.right(crate::utilities::spacing::SpacingValue::Integer(2))
761    }
762    
763    /// Add bottom positioning with value 6
764    pub fn bottom_6(self) -> Self {
765        self.bottom(crate::utilities::spacing::SpacingValue::Integer(6))
766    }
767    
768    /// Add left positioning with value 8
769    pub fn left_8(self) -> Self {
770        self.left(crate::utilities::spacing::SpacingValue::Integer(8))
771    }
772    
773    /// Add inset positioning with value 0
774    pub fn inset_0(self) -> Self {
775        self.inset(crate::utilities::spacing::SpacingValue::Zero)
776    }
777    
778    /// Add horizontal inset positioning with value 4
779    pub fn inset_x_4(self) -> Self {
780        self.inset_x(crate::utilities::spacing::SpacingValue::Integer(4))
781    }
782    
783    /// Add vertical inset positioning with value 2
784    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        // Test all z-index values are available
874        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        // Test numeric values
881        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        // Test CSS values
889        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 that positioning utilities (top/right/bottom/left) are implemented
1035    #[test]
1036    fn test_positioning_utilities() {
1037        // This test will fail until we implement positioning utilities
1038        let classes = ClassBuilder::new()
1039            .top_4()  // top-4
1040            .right_2()  // right-2
1041            .bottom_6()  // bottom-6
1042            .left_8()  // left-8
1043            .inset_0()  // inset-0
1044            .inset_x_4()  // inset-x-4
1045            .inset_y_2()  // inset-y-2
1046            .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        // Test Display serialization
1297        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        // Test Position serialization
1303        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        // Test ZIndex serialization
1309        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        // Test Display equality
1318        assert_eq!(Display::Block, Display::Block);
1319        assert_ne!(Display::Block, Display::Flex);
1320
1321        // Test Position equality
1322        assert_eq!(Position::Relative, Position::Relative);
1323        assert_ne!(Position::Relative, Position::Absolute);
1324
1325        // Test ZIndex equality
1326        assert_eq!(ZIndex::Ten, ZIndex::Ten);
1327        assert_ne!(ZIndex::Ten, ZIndex::Twenty);
1328
1329        // Test hash consistency
1330        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}