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