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}
104
105/// Float values
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
107pub enum Float {
108    /// Float right
109    Right,
110    /// Float left
111    Left,
112    /// Float none
113    None,
114}
115
116/// Clear values
117#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
118pub enum Clear {
119    /// Clear left
120    Left,
121    /// Clear right
122    Right,
123    /// Clear both
124    Both,
125    /// Clear none
126    None,
127}
128
129/// Isolation values
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
131pub enum Isolation {
132    /// Isolate
133    Isolate,
134    /// Isolate auto
135    Auto,
136}
137
138/// Object fit values
139#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
140pub enum ObjectFit {
141    /// Contain object fit
142    Contain,
143    /// Cover object fit
144    Cover,
145    /// Fill object fit
146    Fill,
147    /// None object fit
148    None,
149    /// Scale-down object fit
150    ScaleDown,
151}
152
153/// Object position values
154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
155pub enum ObjectPosition {
156    /// Bottom object position
157    Bottom,
158    /// Center object position
159    Center,
160    /// Left object position
161    Left,
162    /// Left bottom object position
163    LeftBottom,
164    /// Left top object position
165    LeftTop,
166    /// Right object position
167    Right,
168    /// Right bottom object position
169    RightBottom,
170    /// Right top object position
171    RightTop,
172    /// Top object position
173    Top,
174}
175
176/// Overscroll behavior values
177#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
178pub enum OverscrollBehavior {
179    /// Auto overscroll behavior
180    Auto,
181    /// Contain overscroll behavior
182    Contain,
183    /// None overscroll behavior
184    None,
185}
186
187/// Visibility values
188#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
189pub enum Visibility {
190    /// Visible
191    Visible,
192    /// Hidden
193    Hidden,
194    /// Collapse
195    Collapse,
196}
197
198impl Display {
199    pub fn to_class_name(&self) -> String {
200        match self {
201            Display::Block => "block".to_string(),
202            Display::Inline => "inline".to_string(),
203            Display::InlineBlock => "inline-block".to_string(),
204            Display::Flex => "flex".to_string(),
205            Display::InlineFlex => "inline-flex".to_string(),
206            Display::Grid => "grid".to_string(),
207            Display::InlineGrid => "inline-grid".to_string(),
208            Display::Table => "table".to_string(),
209            Display::InlineTable => "inline-table".to_string(),
210            Display::TableCaption => "table-caption".to_string(),
211            Display::TableCell => "table-cell".to_string(),
212            Display::TableColumn => "table-column".to_string(),
213            Display::TableColumnGroup => "table-column-group".to_string(),
214            Display::TableFooterGroup => "table-footer-group".to_string(),
215            Display::TableHeaderGroup => "table-header-group".to_string(),
216            Display::TableRow => "table-row".to_string(),
217            Display::TableRowGroup => "table-row-group".to_string(),
218            Display::FlowRoot => "flow-root".to_string(),
219            Display::Contents => "contents".to_string(),
220            Display::ListItem => "list-item".to_string(),
221            Display::Hidden => "hidden".to_string(),
222        }
223    }
224    
225    pub fn to_css_value(&self) -> String {
226        match self {
227            Display::Block => "block".to_string(),
228            Display::Inline => "inline".to_string(),
229            Display::InlineBlock => "inline-block".to_string(),
230            Display::Flex => "flex".to_string(),
231            Display::InlineFlex => "inline-flex".to_string(),
232            Display::Grid => "grid".to_string(),
233            Display::InlineGrid => "inline-grid".to_string(),
234            Display::Table => "table".to_string(),
235            Display::InlineTable => "inline-table".to_string(),
236            Display::TableCaption => "table-caption".to_string(),
237            Display::TableCell => "table-cell".to_string(),
238            Display::TableColumn => "table-column".to_string(),
239            Display::TableColumnGroup => "table-column-group".to_string(),
240            Display::TableFooterGroup => "table-footer-group".to_string(),
241            Display::TableHeaderGroup => "table-header-group".to_string(),
242            Display::TableRow => "table-row".to_string(),
243            Display::TableRowGroup => "table-row-group".to_string(),
244            Display::FlowRoot => "flow-root".to_string(),
245            Display::Contents => "contents".to_string(),
246            Display::ListItem => "list-item".to_string(),
247            Display::Hidden => "none".to_string(),
248        }
249    }
250}
251
252impl Position {
253    pub fn to_class_name(&self) -> String {
254        match self {
255            Position::Static => "static".to_string(),
256            Position::Fixed => "fixed".to_string(),
257            Position::Absolute => "absolute".to_string(),
258            Position::Relative => "relative".to_string(),
259            Position::Sticky => "sticky".to_string(),
260        }
261    }
262    
263    pub fn to_css_value(&self) -> String {
264        match self {
265            Position::Static => "static".to_string(),
266            Position::Fixed => "fixed".to_string(),
267            Position::Absolute => "absolute".to_string(),
268            Position::Relative => "relative".to_string(),
269            Position::Sticky => "sticky".to_string(),
270        }
271    }
272}
273
274impl Overflow {
275    pub fn to_class_name(&self) -> String {
276        match self {
277            Overflow::Auto => "auto".to_string(),
278            Overflow::Hidden => "hidden".to_string(),
279            Overflow::Clip => "clip".to_string(),
280            Overflow::Visible => "visible".to_string(),
281            Overflow::Scroll => "scroll".to_string(),
282        }
283    }
284    
285    pub fn to_css_value(&self) -> String {
286        match self {
287            Overflow::Auto => "auto".to_string(),
288            Overflow::Hidden => "hidden".to_string(),
289            Overflow::Clip => "clip".to_string(),
290            Overflow::Visible => "visible".to_string(),
291            Overflow::Scroll => "scroll".to_string(),
292        }
293    }
294}
295
296impl ZIndex {
297    pub fn to_class_name(&self) -> String {
298        match self {
299            ZIndex::Auto => "auto".to_string(),
300            ZIndex::Zero => "0".to_string(),
301            ZIndex::Ten => "10".to_string(),
302            ZIndex::Twenty => "20".to_string(),
303            ZIndex::Thirty => "30".to_string(),
304            ZIndex::Forty => "40".to_string(),
305            ZIndex::Fifty => "50".to_string(),
306        }
307    }
308    
309    pub fn to_css_value(&self) -> String {
310        match self {
311            ZIndex::Auto => "auto".to_string(),
312            ZIndex::Zero => "0".to_string(),
313            ZIndex::Ten => "10".to_string(),
314            ZIndex::Twenty => "20".to_string(),
315            ZIndex::Thirty => "30".to_string(),
316            ZIndex::Forty => "40".to_string(),
317            ZIndex::Fifty => "50".to_string(),
318        }
319    }
320}
321
322impl Float {
323    pub fn to_class_name(&self) -> String {
324        match self {
325            Float::Right => "right".to_string(),
326            Float::Left => "left".to_string(),
327            Float::None => "none".to_string(),
328        }
329    }
330    
331    pub fn to_css_value(&self) -> String {
332        match self {
333            Float::Right => "right".to_string(),
334            Float::Left => "left".to_string(),
335            Float::None => "none".to_string(),
336        }
337    }
338}
339
340impl Clear {
341    pub fn to_class_name(&self) -> String {
342        match self {
343            Clear::Left => "left".to_string(),
344            Clear::Right => "right".to_string(),
345            Clear::Both => "both".to_string(),
346            Clear::None => "none".to_string(),
347        }
348    }
349    
350    pub fn to_css_value(&self) -> String {
351        match self {
352            Clear::Left => "left".to_string(),
353            Clear::Right => "right".to_string(),
354            Clear::Both => "both".to_string(),
355            Clear::None => "none".to_string(),
356        }
357    }
358}
359
360impl Isolation {
361    pub fn to_class_name(&self) -> String {
362        match self {
363            Isolation::Isolate => "isolate".to_string(),
364            Isolation::Auto => "auto".to_string(),
365        }
366    }
367    
368    pub fn to_css_value(&self) -> String {
369        match self {
370            Isolation::Isolate => "isolate".to_string(),
371            Isolation::Auto => "auto".to_string(),
372        }
373    }
374}
375
376impl ObjectFit {
377    pub fn to_class_name(&self) -> String {
378        match self {
379            ObjectFit::Contain => "contain".to_string(),
380            ObjectFit::Cover => "cover".to_string(),
381            ObjectFit::Fill => "fill".to_string(),
382            ObjectFit::None => "none".to_string(),
383            ObjectFit::ScaleDown => "scale-down".to_string(),
384        }
385    }
386    
387    pub fn to_css_value(&self) -> String {
388        match self {
389            ObjectFit::Contain => "contain".to_string(),
390            ObjectFit::Cover => "cover".to_string(),
391            ObjectFit::Fill => "fill".to_string(),
392            ObjectFit::None => "none".to_string(),
393            ObjectFit::ScaleDown => "scale-down".to_string(),
394        }
395    }
396}
397
398impl ObjectPosition {
399    pub fn to_class_name(&self) -> String {
400        match self {
401            ObjectPosition::Bottom => "bottom".to_string(),
402            ObjectPosition::Center => "center".to_string(),
403            ObjectPosition::Left => "left".to_string(),
404            ObjectPosition::LeftBottom => "left-bottom".to_string(),
405            ObjectPosition::LeftTop => "left-top".to_string(),
406            ObjectPosition::Right => "right".to_string(),
407            ObjectPosition::RightBottom => "right-bottom".to_string(),
408            ObjectPosition::RightTop => "right-top".to_string(),
409            ObjectPosition::Top => "top".to_string(),
410        }
411    }
412    
413    pub fn to_css_value(&self) -> String {
414        match self {
415            ObjectPosition::Bottom => "bottom".to_string(),
416            ObjectPosition::Center => "center".to_string(),
417            ObjectPosition::Left => "left".to_string(),
418            ObjectPosition::LeftBottom => "left bottom".to_string(),
419            ObjectPosition::LeftTop => "left top".to_string(),
420            ObjectPosition::Right => "right".to_string(),
421            ObjectPosition::RightBottom => "right bottom".to_string(),
422            ObjectPosition::RightTop => "right top".to_string(),
423            ObjectPosition::Top => "top".to_string(),
424        }
425    }
426}
427
428impl OverscrollBehavior {
429    pub fn to_class_name(&self) -> String {
430        match self {
431            OverscrollBehavior::Auto => "auto".to_string(),
432            OverscrollBehavior::Contain => "contain".to_string(),
433            OverscrollBehavior::None => "none".to_string(),
434        }
435    }
436    
437    pub fn to_css_value(&self) -> String {
438        match self {
439            OverscrollBehavior::Auto => "auto".to_string(),
440            OverscrollBehavior::Contain => "contain".to_string(),
441            OverscrollBehavior::None => "none".to_string(),
442        }
443    }
444}
445
446impl Visibility {
447    pub fn to_class_name(&self) -> String {
448        match self {
449            Visibility::Visible => "visible".to_string(),
450            Visibility::Hidden => "invisible".to_string(),
451            Visibility::Collapse => "collapse".to_string(),
452        }
453    }
454    
455    pub fn to_css_value(&self) -> String {
456        match self {
457            Visibility::Visible => "visible".to_string(),
458            Visibility::Hidden => "hidden".to_string(),
459            Visibility::Collapse => "collapse".to_string(),
460        }
461    }
462}
463
464impl fmt::Display for Display {
465    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
466        write!(f, "{}", self.to_class_name())
467    }
468}
469
470impl fmt::Display for Position {
471    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
472        write!(f, "{}", self.to_class_name())
473    }
474}
475
476impl fmt::Display for Overflow {
477    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
478        write!(f, "{}", self.to_class_name())
479    }
480}
481
482impl fmt::Display for ZIndex {
483    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
484        write!(f, "{}", self.to_class_name())
485    }
486}
487
488/// Trait for adding display utilities to a class builder
489pub trait DisplayUtilities {
490    fn display(self, display: Display) -> Self;
491}
492
493impl DisplayUtilities for ClassBuilder {
494    fn display(self, display: Display) -> Self {
495        self.class(display.to_class_name())
496    }
497}
498
499/// Trait for adding position utilities to a class builder
500pub trait PositionUtilities {
501    fn position(self, position: Position) -> Self;
502}
503
504impl PositionUtilities for ClassBuilder {
505    fn position(self, position: Position) -> Self {
506        self.class(position.to_class_name())
507    }
508}
509
510/// Trait for adding overflow utilities to a class builder
511pub trait OverflowUtilities {
512    fn overflow(self, overflow: Overflow) -> Self;
513    fn overflow_x(self, overflow: Overflow) -> Self;
514    fn overflow_y(self, overflow: Overflow) -> Self;
515}
516
517impl OverflowUtilities for ClassBuilder {
518    fn overflow(self, overflow: Overflow) -> Self {
519        self.class(format!("overflow-{}", overflow.to_class_name()))
520    }
521    
522    fn overflow_x(self, overflow: Overflow) -> Self {
523        self.class(format!("overflow-x-{}", overflow.to_class_name()))
524    }
525    
526    fn overflow_y(self, overflow: Overflow) -> Self {
527        self.class(format!("overflow-y-{}", overflow.to_class_name()))
528    }
529}
530
531/// Trait for adding z-index utilities to a class builder
532pub trait ZIndexUtilities {
533    fn z_index(self, z_index: ZIndex) -> Self;
534}
535
536impl ZIndexUtilities for ClassBuilder {
537    fn z_index(self, z_index: ZIndex) -> Self {
538        self.class(format!("z-{}", z_index.to_class_name()))
539    }
540}
541
542/// Trait for adding float utilities to a class builder
543pub trait FloatUtilities {
544    fn float(self, float: Float) -> Self;
545}
546
547impl FloatUtilities for ClassBuilder {
548    fn float(self, float: Float) -> Self {
549        self.class(format!("float-{}", float.to_class_name()))
550    }
551}
552
553/// Trait for adding clear utilities to a class builder
554pub trait ClearUtilities {
555    fn clear(self, clear: Clear) -> Self;
556}
557
558impl ClearUtilities for ClassBuilder {
559    fn clear(self, clear: Clear) -> Self {
560        self.class(format!("clear-{}", clear.to_class_name()))
561    }
562}
563
564/// Trait for adding isolation utilities to a class builder
565pub trait IsolationUtilities {
566    fn isolation(self, isolation: Isolation) -> Self;
567}
568
569impl IsolationUtilities for ClassBuilder {
570    fn isolation(self, isolation: Isolation) -> Self {
571        self.class(format!("isolation-{}", isolation.to_class_name()))
572    }
573}
574
575/// Trait for adding object fit utilities to a class builder
576pub trait ObjectFitUtilities {
577    fn object_fit(self, object_fit: ObjectFit) -> Self;
578}
579
580impl ObjectFitUtilities for ClassBuilder {
581    fn object_fit(self, object_fit: ObjectFit) -> Self {
582        self.class(format!("object-{}", object_fit.to_class_name()))
583    }
584}
585
586/// Trait for adding object position utilities to a class builder
587pub trait ObjectPositionUtilities {
588    fn object_position(self, object_position: ObjectPosition) -> Self;
589}
590
591impl ObjectPositionUtilities for ClassBuilder {
592    fn object_position(self, object_position: ObjectPosition) -> Self {
593        self.class(format!("object-{}", object_position.to_class_name()))
594    }
595}
596
597/// Trait for adding overscroll behavior utilities to a class builder
598pub trait OverscrollBehaviorUtilities {
599    fn overscroll_behavior(self, behavior: OverscrollBehavior) -> Self;
600    fn overscroll_behavior_x(self, behavior: OverscrollBehavior) -> Self;
601    fn overscroll_behavior_y(self, behavior: OverscrollBehavior) -> Self;
602}
603
604impl OverscrollBehaviorUtilities for ClassBuilder {
605    fn overscroll_behavior(self, behavior: OverscrollBehavior) -> Self {
606        self.class(format!("overscroll-{}", behavior.to_class_name()))
607    }
608    
609    fn overscroll_behavior_x(self, behavior: OverscrollBehavior) -> Self {
610        self.class(format!("overscroll-x-{}", behavior.to_class_name()))
611    }
612    
613    fn overscroll_behavior_y(self, behavior: OverscrollBehavior) -> Self {
614        self.class(format!("overscroll-y-{}", behavior.to_class_name()))
615    }
616}
617
618/// Trait for adding visibility utilities to a class builder
619pub trait VisibilityUtilities {
620    fn visibility(self, visibility: Visibility) -> Self;
621}
622
623impl VisibilityUtilities for ClassBuilder {
624    fn visibility(self, visibility: Visibility) -> Self {
625        self.class(visibility.to_class_name())
626    }
627}
628
629/// Trait for adding positioning utilities to a class builder
630pub trait PositioningUtilities {
631    /// Add top positioning
632    fn top(self, value: crate::utilities::spacing::SpacingValue) -> Self;
633    
634    /// Add right positioning
635    fn right(self, value: crate::utilities::spacing::SpacingValue) -> Self;
636    
637    /// Add bottom positioning
638    fn bottom(self, value: crate::utilities::spacing::SpacingValue) -> Self;
639    
640    /// Add left positioning
641    fn left(self, value: crate::utilities::spacing::SpacingValue) -> Self;
642    
643    /// Add inset positioning (all sides)
644    fn inset(self, value: crate::utilities::spacing::SpacingValue) -> Self;
645    
646    /// Add horizontal inset positioning
647    fn inset_x(self, value: crate::utilities::spacing::SpacingValue) -> Self;
648    
649    /// Add vertical inset positioning
650    fn inset_y(self, value: crate::utilities::spacing::SpacingValue) -> Self;
651}
652
653impl PositioningUtilities for ClassBuilder {
654    fn top(self, value: crate::utilities::spacing::SpacingValue) -> Self {
655        self.class(format!("top-{}", value.to_class_name()))
656    }
657    
658    fn right(self, value: crate::utilities::spacing::SpacingValue) -> Self {
659        self.class(format!("right-{}", value.to_class_name()))
660    }
661    
662    fn bottom(self, value: crate::utilities::spacing::SpacingValue) -> Self {
663        self.class(format!("bottom-{}", value.to_class_name()))
664    }
665    
666    fn left(self, value: crate::utilities::spacing::SpacingValue) -> Self {
667        self.class(format!("left-{}", value.to_class_name()))
668    }
669    
670    fn inset(self, value: crate::utilities::spacing::SpacingValue) -> Self {
671        self.class(format!("inset-{}", value.to_class_name()))
672    }
673    
674    fn inset_x(self, value: crate::utilities::spacing::SpacingValue) -> Self {
675        self.class(format!("inset-x-{}", value.to_class_name()))
676    }
677    
678    fn inset_y(self, value: crate::utilities::spacing::SpacingValue) -> Self {
679        self.class(format!("inset-y-{}", value.to_class_name()))
680    }
681}
682
683/// Convenience methods for positioning utilities
684impl ClassBuilder {
685    /// Add top positioning with value 4
686    pub fn top_4(self) -> Self {
687        self.top(crate::utilities::spacing::SpacingValue::Integer(4))
688    }
689    
690    /// Add right positioning with value 2
691    pub fn right_2(self) -> Self {
692        self.right(crate::utilities::spacing::SpacingValue::Integer(2))
693    }
694    
695    /// Add bottom positioning with value 6
696    pub fn bottom_6(self) -> Self {
697        self.bottom(crate::utilities::spacing::SpacingValue::Integer(6))
698    }
699    
700    /// Add left positioning with value 8
701    pub fn left_8(self) -> Self {
702        self.left(crate::utilities::spacing::SpacingValue::Integer(8))
703    }
704    
705    /// Add inset positioning with value 0
706    pub fn inset_0(self) -> Self {
707        self.inset(crate::utilities::spacing::SpacingValue::Zero)
708    }
709    
710    /// Add horizontal inset positioning with value 4
711    pub fn inset_x_4(self) -> Self {
712        self.inset_x(crate::utilities::spacing::SpacingValue::Integer(4))
713    }
714    
715    /// Add vertical inset positioning with value 2
716    pub fn inset_y_2(self) -> Self {
717        self.inset_y(crate::utilities::spacing::SpacingValue::Integer(2))
718    }
719}
720
721#[cfg(test)]
722mod tests {
723    use super::*;
724    
725    #[test]
726    fn test_display_utilities() {
727        let classes = ClassBuilder::new()
728            .display(Display::Block)
729            .display(Display::Flex)
730            .display(Display::Grid)
731            .display(Display::Hidden)
732            .build();
733        
734        let css_classes = classes.to_css_classes();
735        assert!(css_classes.contains("block"));
736        assert!(css_classes.contains("flex"));
737        assert!(css_classes.contains("grid"));
738        assert!(css_classes.contains("hidden"));
739    }
740    
741    #[test]
742    fn test_position_utilities() {
743        let classes = ClassBuilder::new()
744            .position(Position::Static)
745            .position(Position::Relative)
746            .position(Position::Absolute)
747            .position(Position::Fixed)
748            .position(Position::Sticky)
749            .build();
750        
751        let css_classes = classes.to_css_classes();
752        assert!(css_classes.contains("static"));
753        assert!(css_classes.contains("relative"));
754        assert!(css_classes.contains("absolute"));
755        assert!(css_classes.contains("fixed"));
756        assert!(css_classes.contains("sticky"));
757    }
758    
759    #[test]
760    fn test_overflow_utilities() {
761        let classes = ClassBuilder::new()
762            .overflow(Overflow::Auto)
763            .overflow(Overflow::Hidden)
764            .overflow(Overflow::Visible)
765            .overflow(Overflow::Scroll)
766            .overflow_x(Overflow::Hidden)
767            .overflow_y(Overflow::Scroll)
768            .build();
769        
770        let css_classes = classes.to_css_classes();
771        assert!(css_classes.contains("overflow-auto"));
772        assert!(css_classes.contains("overflow-hidden"));
773        assert!(css_classes.contains("overflow-visible"));
774        assert!(css_classes.contains("overflow-scroll"));
775        assert!(css_classes.contains("overflow-x-hidden"));
776        assert!(css_classes.contains("overflow-y-scroll"));
777    }
778    
779    #[test]
780    fn test_z_index_utilities() {
781        let classes = ClassBuilder::new()
782            .z_index(ZIndex::Auto)
783            .z_index(ZIndex::Zero)
784            .z_index(ZIndex::Ten)
785            .z_index(ZIndex::Fifty)
786            .build();
787        
788        let css_classes = classes.to_css_classes();
789        assert!(css_classes.contains("z-auto"));
790        assert!(css_classes.contains("z-0"));
791        assert!(css_classes.contains("z-10"));
792        assert!(css_classes.contains("z-50"));
793    }
794    
795    #[test]
796    fn test_float_utilities() {
797        let classes = ClassBuilder::new()
798            .float(Float::Left)
799            .float(Float::Right)
800            .float(Float::None)
801            .build();
802        
803        let css_classes = classes.to_css_classes();
804        assert!(css_classes.contains("float-left"));
805        assert!(css_classes.contains("float-right"));
806        assert!(css_classes.contains("float-none"));
807    }
808    
809    #[test]
810    fn test_clear_utilities() {
811        let classes = ClassBuilder::new()
812            .clear(Clear::Left)
813            .clear(Clear::Right)
814            .clear(Clear::Both)
815            .clear(Clear::None)
816            .build();
817        
818        let css_classes = classes.to_css_classes();
819        assert!(css_classes.contains("clear-left"));
820        assert!(css_classes.contains("clear-right"));
821        assert!(css_classes.contains("clear-both"));
822        assert!(css_classes.contains("clear-none"));
823    }
824    
825    #[test]
826    fn test_isolation_utilities() {
827        let classes = ClassBuilder::new()
828            .isolation(Isolation::Isolate)
829            .isolation(Isolation::Auto)
830            .build();
831        
832        let css_classes = classes.to_css_classes();
833        assert!(css_classes.contains("isolation-isolate"));
834        assert!(css_classes.contains("isolation-auto"));
835    }
836    
837    #[test]
838    fn test_object_fit_utilities() {
839        let classes = ClassBuilder::new()
840            .object_fit(ObjectFit::Contain)
841            .object_fit(ObjectFit::Cover)
842            .object_fit(ObjectFit::Fill)
843            .object_fit(ObjectFit::None)
844            .object_fit(ObjectFit::ScaleDown)
845            .build();
846        
847        let css_classes = classes.to_css_classes();
848        assert!(css_classes.contains("object-contain"));
849        assert!(css_classes.contains("object-cover"));
850        assert!(css_classes.contains("object-fill"));
851        assert!(css_classes.contains("object-none"));
852        assert!(css_classes.contains("object-scale-down"));
853    }
854    
855    #[test]
856    fn test_object_position_utilities() {
857        let classes = ClassBuilder::new()
858            .object_position(ObjectPosition::Center)
859            .object_position(ObjectPosition::Top)
860            .object_position(ObjectPosition::Bottom)
861            .object_position(ObjectPosition::Left)
862            .object_position(ObjectPosition::Right)
863            .build();
864        
865        let css_classes = classes.to_css_classes();
866        assert!(css_classes.contains("object-center"));
867        assert!(css_classes.contains("object-top"));
868        assert!(css_classes.contains("object-bottom"));
869        assert!(css_classes.contains("object-left"));
870        assert!(css_classes.contains("object-right"));
871    }
872    
873    #[test]
874    fn test_overscroll_behavior_utilities() {
875        let classes = ClassBuilder::new()
876            .overscroll_behavior(OverscrollBehavior::Auto)
877            .overscroll_behavior(OverscrollBehavior::Contain)
878            .overscroll_behavior(OverscrollBehavior::None)
879            .overscroll_behavior_x(OverscrollBehavior::Contain)
880            .overscroll_behavior_y(OverscrollBehavior::None)
881            .build();
882        
883        let css_classes = classes.to_css_classes();
884        assert!(css_classes.contains("overscroll-auto"));
885        assert!(css_classes.contains("overscroll-contain"));
886        assert!(css_classes.contains("overscroll-none"));
887        assert!(css_classes.contains("overscroll-x-contain"));
888        assert!(css_classes.contains("overscroll-y-none"));
889    }
890    
891    #[test]
892    fn test_visibility_utilities() {
893        let classes = ClassBuilder::new()
894            .visibility(Visibility::Visible)
895            .visibility(Visibility::Hidden)
896            .visibility(Visibility::Collapse)
897            .build();
898        
899        let css_classes = classes.to_css_classes();
900        assert!(css_classes.contains("visible"));
901        assert!(css_classes.contains("invisible"));
902        assert!(css_classes.contains("collapse"));
903    }
904    
905    #[test]
906    fn test_complex_layout_combination() {
907        let classes = ClassBuilder::new()
908            .display(Display::Flex)
909            .position(Position::Relative)
910            .overflow(Overflow::Hidden)
911            .z_index(ZIndex::Ten)
912            .float(Float::None)
913            .clear(Clear::Both)
914            .isolation(Isolation::Isolate)
915            .object_fit(ObjectFit::Cover)
916            .object_position(ObjectPosition::Center)
917            .overscroll_behavior(OverscrollBehavior::Contain)
918            .visibility(Visibility::Visible)
919            .build();
920        
921        let css_classes = classes.to_css_classes();
922        assert!(css_classes.contains("flex"));
923        assert!(css_classes.contains("relative"));
924        assert!(css_classes.contains("overflow-hidden"));
925        assert!(css_classes.contains("z-10"));
926        assert!(css_classes.contains("float-none"));
927        assert!(css_classes.contains("clear-both"));
928        assert!(css_classes.contains("isolation-isolate"));
929        assert!(css_classes.contains("object-cover"));
930        assert!(css_classes.contains("object-center"));
931        assert!(css_classes.contains("overscroll-contain"));
932        assert!(css_classes.contains("visible"));
933    }
934
935    /// Test that positioning utilities (top/right/bottom/left) are implemented
936    #[test]
937    fn test_positioning_utilities() {
938        // This test will fail until we implement positioning utilities
939        let classes = ClassBuilder::new()
940            .top_4()  // top-4
941            .right_2()  // right-2
942            .bottom_6()  // bottom-6
943            .left_8()  // left-8
944            .inset_0()  // inset-0
945            .inset_x_4()  // inset-x-4
946            .inset_y_2()  // inset-y-2
947            .build();
948        
949        let css_classes = classes.to_css_classes();
950        assert!(css_classes.contains("top-4"));
951        assert!(css_classes.contains("right-2"));
952        assert!(css_classes.contains("bottom-6"));
953        assert!(css_classes.contains("left-8"));
954        assert!(css_classes.contains("inset-0"));
955        assert!(css_classes.contains("inset-x-4"));
956        assert!(css_classes.contains("inset-y-2"));
957    }
958}