tailwind_rs_core/utilities/
flexbox.rs

1//! Flexbox utilities for tailwind-rs
2//!
3//! This module provides utilities for flexbox layout including flex direction,
4//! flex wrap, justify content, align items, align content, and flex properties.
5
6use crate::classes::ClassBuilder;
7use serde::{Deserialize, Serialize};
8use std::fmt;
9
10/// Flex direction values
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub enum FlexDirection {
13    /// Row direction
14    Row,
15    /// Row reverse direction
16    RowReverse,
17    /// Column direction
18    Column,
19    /// Column reverse direction
20    ColumnReverse,
21}
22
23/// Flex wrap values
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
25pub enum FlexWrap {
26    /// No wrap
27    NoWrap,
28    /// Wrap
29    Wrap,
30    /// Wrap reverse
31    WrapReverse,
32}
33
34/// Justify content values
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
36pub enum JustifyContent {
37    /// Start justify
38    Start,
39    /// End justify
40    End,
41    /// Center justify
42    Center,
43    /// Between justify
44    Between,
45    /// Around justify
46    Around,
47    /// Evenly justify
48    Evenly,
49}
50
51/// Align items values
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
53pub enum AlignItems {
54    /// Start align
55    Start,
56    /// End align
57    End,
58    /// Center align
59    Center,
60    /// Baseline align
61    Baseline,
62    /// Baseline last align
63    BaselineLast,
64    /// Stretch align
65    Stretch,
66}
67
68/// Align content values
69#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
70pub enum AlignContent {
71    /// Start align content
72    Start,
73    /// End align content
74    End,
75    /// Center align content
76    Center,
77    /// Between align content
78    Between,
79    /// Around align content
80    Around,
81    /// Evenly align content
82    Evenly,
83    /// Baseline align content
84    Baseline,
85    /// Stretch align content
86    Stretch,
87}
88
89/// Align self values
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
91pub enum AlignSelf {
92    /// Auto align self
93    Auto,
94    /// Start align self
95    Start,
96    /// End align self
97    End,
98    /// Center align self
99    Center,
100    /// Stretch align self
101    Stretch,
102    /// Baseline align self
103    Baseline,
104    /// Baseline last align self
105    BaselineLast,
106}
107
108/// Flex grow values
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
110pub enum FlexGrow {
111    /// No grow
112    Zero,
113    /// Grow
114    Grow,
115}
116
117/// Flex shrink values
118#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
119pub enum FlexShrink {
120    /// No shrink
121    Zero,
122    /// Shrink
123    Shrink,
124}
125
126/// Flex basis values
127#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
128pub enum FlexBasis {
129    /// Auto basis
130    Auto,
131    /// Full basis
132    Full,
133    /// Fit basis
134    Fit,
135    /// Max basis
136    Max,
137    /// Min basis
138    Min,
139    /// None basis
140    None,
141    /// Zero basis
142    Zero,
143}
144
145/// Flex values
146#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
147pub enum Flex {
148    /// Flex 1
149    One,
150    /// Flex auto
151    Auto,
152    /// Flex initial
153    Initial,
154    /// Flex none
155    None,
156}
157
158/// Order values
159#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
160pub enum Order {
161    /// First order
162    First,
163    /// Last order
164    Last,
165    /// None order
166    None,
167    /// Order 1
168    One,
169    /// Order 2
170    Two,
171    /// Order 3
172    Three,
173    /// Order 4
174    Four,
175    /// Order 5
176    Five,
177    /// Order 6
178    Six,
179    /// Order 7
180    Seven,
181    /// Order 8
182    Eight,
183    /// Order 9
184    Nine,
185    /// Order 10
186    Ten,
187    /// Order 11
188    Eleven,
189    /// Order 12
190    Twelve,
191}
192
193impl FlexDirection {
194    pub fn to_class_name(&self) -> String {
195        match self {
196            FlexDirection::Row => "row".to_string(),
197            FlexDirection::RowReverse => "row-reverse".to_string(),
198            FlexDirection::Column => "col".to_string(),
199            FlexDirection::ColumnReverse => "col-reverse".to_string(),
200        }
201    }
202    
203    pub fn to_css_value(&self) -> String {
204        match self {
205            FlexDirection::Row => "row".to_string(),
206            FlexDirection::RowReverse => "row-reverse".to_string(),
207            FlexDirection::Column => "column".to_string(),
208            FlexDirection::ColumnReverse => "column-reverse".to_string(),
209        }
210    }
211}
212
213impl FlexWrap {
214    pub fn to_class_name(&self) -> String {
215        match self {
216            FlexWrap::NoWrap => "nowrap".to_string(),
217            FlexWrap::Wrap => "wrap".to_string(),
218            FlexWrap::WrapReverse => "wrap-reverse".to_string(),
219        }
220    }
221    
222    pub fn to_css_value(&self) -> String {
223        match self {
224            FlexWrap::NoWrap => "nowrap".to_string(),
225            FlexWrap::Wrap => "wrap".to_string(),
226            FlexWrap::WrapReverse => "wrap-reverse".to_string(),
227        }
228    }
229}
230
231impl JustifyContent {
232    pub fn to_class_name(&self) -> String {
233        match self {
234            JustifyContent::Start => "start".to_string(),
235            JustifyContent::End => "end".to_string(),
236            JustifyContent::Center => "center".to_string(),
237            JustifyContent::Between => "between".to_string(),
238            JustifyContent::Around => "around".to_string(),
239            JustifyContent::Evenly => "evenly".to_string(),
240        }
241    }
242    
243    pub fn to_css_value(&self) -> String {
244        match self {
245            JustifyContent::Start => "flex-start".to_string(),
246            JustifyContent::End => "flex-end".to_string(),
247            JustifyContent::Center => "center".to_string(),
248            JustifyContent::Between => "space-between".to_string(),
249            JustifyContent::Around => "space-around".to_string(),
250            JustifyContent::Evenly => "space-evenly".to_string(),
251        }
252    }
253}
254
255impl AlignItems {
256    pub fn to_class_name(&self) -> String {
257        match self {
258            AlignItems::Start => "start".to_string(),
259            AlignItems::End => "end".to_string(),
260            AlignItems::Center => "center".to_string(),
261            AlignItems::Baseline => "baseline".to_string(),
262            AlignItems::BaselineLast => "baseline-last".to_string(),
263            AlignItems::Stretch => "stretch".to_string(),
264        }
265    }
266    
267    pub fn to_css_value(&self) -> String {
268        match self {
269            AlignItems::Start => "flex-start".to_string(),
270            AlignItems::End => "flex-end".to_string(),
271            AlignItems::Center => "center".to_string(),
272            AlignItems::Baseline => "baseline".to_string(),
273            AlignItems::BaselineLast => "last baseline".to_string(),
274            AlignItems::Stretch => "stretch".to_string(),
275        }
276    }
277}
278
279impl AlignContent {
280    pub fn to_class_name(&self) -> String {
281        match self {
282            AlignContent::Start => "start".to_string(),
283            AlignContent::End => "end".to_string(),
284            AlignContent::Center => "center".to_string(),
285            AlignContent::Between => "between".to_string(),
286            AlignContent::Around => "around".to_string(),
287            AlignContent::Evenly => "evenly".to_string(),
288            AlignContent::Baseline => "baseline".to_string(),
289            AlignContent::Stretch => "stretch".to_string(),
290        }
291    }
292    
293    pub fn to_css_value(&self) -> String {
294        match self {
295            AlignContent::Start => "flex-start".to_string(),
296            AlignContent::End => "flex-end".to_string(),
297            AlignContent::Center => "center".to_string(),
298            AlignContent::Between => "space-between".to_string(),
299            AlignContent::Around => "space-around".to_string(),
300            AlignContent::Evenly => "space-evenly".to_string(),
301            AlignContent::Baseline => "baseline".to_string(),
302            AlignContent::Stretch => "stretch".to_string(),
303        }
304    }
305}
306
307impl AlignSelf {
308    pub fn to_class_name(&self) -> String {
309        match self {
310            AlignSelf::Auto => "auto".to_string(),
311            AlignSelf::Start => "start".to_string(),
312            AlignSelf::End => "end".to_string(),
313            AlignSelf::Center => "center".to_string(),
314            AlignSelf::Stretch => "stretch".to_string(),
315            AlignSelf::Baseline => "baseline".to_string(),
316            AlignSelf::BaselineLast => "baseline-last".to_string(),
317        }
318    }
319    
320    pub fn to_css_value(&self) -> String {
321        match self {
322            AlignSelf::Auto => "auto".to_string(),
323            AlignSelf::Start => "flex-start".to_string(),
324            AlignSelf::End => "flex-end".to_string(),
325            AlignSelf::Center => "center".to_string(),
326            AlignSelf::Stretch => "stretch".to_string(),
327            AlignSelf::Baseline => "baseline".to_string(),
328            AlignSelf::BaselineLast => "last baseline".to_string(),
329        }
330    }
331}
332
333impl FlexGrow {
334    pub fn to_class_name(&self) -> String {
335        match self {
336            FlexGrow::Zero => "0".to_string(),
337            FlexGrow::Grow => "grow".to_string(),
338        }
339    }
340    
341    pub fn to_css_value(&self) -> String {
342        match self {
343            FlexGrow::Zero => "0".to_string(),
344            FlexGrow::Grow => "1".to_string(),
345        }
346    }
347}
348
349impl FlexShrink {
350    pub fn to_class_name(&self) -> String {
351        match self {
352            FlexShrink::Zero => "0".to_string(),
353            FlexShrink::Shrink => "shrink".to_string(),
354        }
355    }
356    
357    pub fn to_css_value(&self) -> String {
358        match self {
359            FlexShrink::Zero => "0".to_string(),
360            FlexShrink::Shrink => "1".to_string(),
361        }
362    }
363}
364
365impl FlexBasis {
366    pub fn to_class_name(&self) -> String {
367        match self {
368            FlexBasis::Auto => "auto".to_string(),
369            FlexBasis::Full => "full".to_string(),
370            FlexBasis::Fit => "fit".to_string(),
371            FlexBasis::Max => "max".to_string(),
372            FlexBasis::Min => "min".to_string(),
373            FlexBasis::None => "none".to_string(),
374            FlexBasis::Zero => "0".to_string(),
375        }
376    }
377    
378    pub fn to_css_value(&self) -> String {
379        match self {
380            FlexBasis::Auto => "auto".to_string(),
381            FlexBasis::Full => "100%".to_string(),
382            FlexBasis::Fit => "fit-content".to_string(),
383            FlexBasis::Max => "max-content".to_string(),
384            FlexBasis::Min => "min-content".to_string(),
385            FlexBasis::None => "none".to_string(),
386            FlexBasis::Zero => "0%".to_string(),
387        }
388    }
389}
390
391impl Flex {
392    pub fn to_class_name(&self) -> String {
393        match self {
394            Flex::One => "1".to_string(),
395            Flex::Auto => "auto".to_string(),
396            Flex::Initial => "initial".to_string(),
397            Flex::None => "none".to_string(),
398        }
399    }
400    
401    pub fn to_css_value(&self) -> String {
402        match self {
403            Flex::One => "1 1 0%".to_string(),
404            Flex::Auto => "1 1 auto".to_string(),
405            Flex::Initial => "0 1 auto".to_string(),
406            Flex::None => "none".to_string(),
407        }
408    }
409}
410
411impl Order {
412    pub fn to_class_name(&self) -> String {
413        match self {
414            Order::First => "first".to_string(),
415            Order::Last => "last".to_string(),
416            Order::None => "none".to_string(),
417            Order::One => "1".to_string(),
418            Order::Two => "2".to_string(),
419            Order::Three => "3".to_string(),
420            Order::Four => "4".to_string(),
421            Order::Five => "5".to_string(),
422            Order::Six => "6".to_string(),
423            Order::Seven => "7".to_string(),
424            Order::Eight => "8".to_string(),
425            Order::Nine => "9".to_string(),
426            Order::Ten => "10".to_string(),
427            Order::Eleven => "11".to_string(),
428            Order::Twelve => "12".to_string(),
429        }
430    }
431    
432    pub fn to_css_value(&self) -> String {
433        match self {
434            Order::First => "-9999".to_string(),
435            Order::Last => "9999".to_string(),
436            Order::None => "0".to_string(),
437            Order::One => "1".to_string(),
438            Order::Two => "2".to_string(),
439            Order::Three => "3".to_string(),
440            Order::Four => "4".to_string(),
441            Order::Five => "5".to_string(),
442            Order::Six => "6".to_string(),
443            Order::Seven => "7".to_string(),
444            Order::Eight => "8".to_string(),
445            Order::Nine => "9".to_string(),
446            Order::Ten => "10".to_string(),
447            Order::Eleven => "11".to_string(),
448            Order::Twelve => "12".to_string(),
449        }
450    }
451}
452
453impl fmt::Display for FlexDirection {
454    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
455        write!(f, "{}", self.to_class_name())
456    }
457}
458
459impl fmt::Display for FlexWrap {
460    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
461        write!(f, "{}", self.to_class_name())
462    }
463}
464
465impl fmt::Display for JustifyContent {
466    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
467        write!(f, "{}", self.to_class_name())
468    }
469}
470
471impl fmt::Display for AlignItems {
472    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
473        write!(f, "{}", self.to_class_name())
474    }
475}
476
477impl fmt::Display for AlignContent {
478    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
479        write!(f, "{}", self.to_class_name())
480    }
481}
482
483impl fmt::Display for AlignSelf {
484    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
485        write!(f, "{}", self.to_class_name())
486    }
487}
488
489impl fmt::Display for FlexGrow {
490    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
491        write!(f, "{}", self.to_class_name())
492    }
493}
494
495impl fmt::Display for FlexShrink {
496    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
497        write!(f, "{}", self.to_class_name())
498    }
499}
500
501impl fmt::Display for FlexBasis {
502    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503        write!(f, "{}", self.to_class_name())
504    }
505}
506
507impl fmt::Display for Flex {
508    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509        write!(f, "{}", self.to_class_name())
510    }
511}
512
513impl fmt::Display for Order {
514    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
515        write!(f, "{}", self.to_class_name())
516    }
517}
518
519/// Trait for adding flex direction utilities to a class builder
520pub trait FlexDirectionUtilities {
521    fn flex_direction(self, direction: FlexDirection) -> Self;
522}
523
524impl FlexDirectionUtilities for ClassBuilder {
525    fn flex_direction(self, direction: FlexDirection) -> Self {
526        self.class(format!("flex-{}", direction.to_class_name()))
527    }
528}
529
530/// Trait for adding flex wrap utilities to a class builder
531pub trait FlexWrapUtilities {
532    fn flex_wrap(self, wrap: FlexWrap) -> Self;
533}
534
535impl FlexWrapUtilities for ClassBuilder {
536    fn flex_wrap(self, wrap: FlexWrap) -> Self {
537        self.class(format!("flex-{}", wrap.to_class_name()))
538    }
539}
540
541/// Trait for adding justify content utilities to a class builder
542pub trait JustifyContentUtilities {
543    fn justify_content(self, justify: JustifyContent) -> Self;
544}
545
546impl JustifyContentUtilities for ClassBuilder {
547    fn justify_content(self, justify: JustifyContent) -> Self {
548        self.class(format!("justify-{}", justify.to_class_name()))
549    }
550}
551
552/// Trait for adding align items utilities to a class builder
553pub trait AlignItemsUtilities {
554    fn align_items(self, align: AlignItems) -> Self;
555}
556
557impl AlignItemsUtilities for ClassBuilder {
558    fn align_items(self, align: AlignItems) -> Self {
559        self.class(format!("items-{}", align.to_class_name()))
560    }
561}
562
563/// Trait for adding align content utilities to a class builder
564pub trait AlignContentUtilities {
565    fn align_content(self, align: AlignContent) -> Self;
566}
567
568impl AlignContentUtilities for ClassBuilder {
569    fn align_content(self, align: AlignContent) -> Self {
570        self.class(format!("content-{}", align.to_class_name()))
571    }
572}
573
574/// Trait for adding align self utilities to a class builder
575pub trait AlignSelfUtilities {
576    fn align_self(self, align: AlignSelf) -> Self;
577}
578
579impl AlignSelfUtilities for ClassBuilder {
580    fn align_self(self, align: AlignSelf) -> Self {
581        self.class(format!("self-{}", align.to_class_name()))
582    }
583}
584
585/// Trait for adding flex grow utilities to a class builder
586pub trait FlexGrowUtilities {
587    fn flex_grow(self, grow: FlexGrow) -> Self;
588}
589
590impl FlexGrowUtilities for ClassBuilder {
591    fn flex_grow(self, grow: FlexGrow) -> Self {
592        self.class(format!("flex-grow-{}", grow.to_class_name()))
593    }
594}
595
596/// Trait for adding flex shrink utilities to a class builder
597pub trait FlexShrinkUtilities {
598    fn flex_shrink(self, shrink: FlexShrink) -> Self;
599}
600
601impl FlexShrinkUtilities for ClassBuilder {
602    fn flex_shrink(self, shrink: FlexShrink) -> Self {
603        self.class(format!("flex-shrink-{}", shrink.to_class_name()))
604    }
605}
606
607/// Trait for adding flex basis utilities to a class builder
608pub trait FlexBasisUtilities {
609    fn flex_basis(self, basis: FlexBasis) -> Self;
610}
611
612impl FlexBasisUtilities for ClassBuilder {
613    fn flex_basis(self, basis: FlexBasis) -> Self {
614        self.class(format!("basis-{}", basis.to_class_name()))
615    }
616}
617
618/// Trait for adding flex utilities to a class builder
619pub trait FlexUtilities {
620    fn flex(self, flex: Flex) -> Self;
621}
622
623impl FlexUtilities for ClassBuilder {
624    fn flex(self, flex: Flex) -> Self {
625        self.class(format!("flex-{}", flex.to_class_name()))
626    }
627}
628
629/// Trait for adding order utilities to a class builder
630pub trait OrderUtilities {
631    fn order(self, order: Order) -> Self;
632}
633
634impl OrderUtilities for ClassBuilder {
635    fn order(self, order: Order) -> Self {
636        self.class(format!("order-{}", order.to_class_name()))
637    }
638}
639
640#[cfg(test)]
641mod tests {
642    use super::*;
643    
644    #[test]
645    fn test_flex_direction_utilities() {
646        let classes = ClassBuilder::new()
647            .flex_direction(FlexDirection::Row)
648            .flex_direction(FlexDirection::RowReverse)
649            .flex_direction(FlexDirection::Column)
650            .flex_direction(FlexDirection::ColumnReverse)
651            .build();
652        
653        let css_classes = classes.to_css_classes();
654        assert!(css_classes.contains("flex-row"));
655        assert!(css_classes.contains("flex-row-reverse"));
656        assert!(css_classes.contains("flex-col"));
657        assert!(css_classes.contains("flex-col-reverse"));
658    }
659    
660    #[test]
661    fn test_flex_wrap_utilities() {
662        let classes = ClassBuilder::new()
663            .flex_wrap(FlexWrap::NoWrap)
664            .flex_wrap(FlexWrap::Wrap)
665            .flex_wrap(FlexWrap::WrapReverse)
666            .build();
667        
668        let css_classes = classes.to_css_classes();
669        assert!(css_classes.contains("flex-nowrap"));
670        assert!(css_classes.contains("flex-wrap"));
671        assert!(css_classes.contains("flex-wrap-reverse"));
672    }
673    
674    #[test]
675    fn test_justify_content_utilities() {
676        let classes = ClassBuilder::new()
677            .justify_content(JustifyContent::Start)
678            .justify_content(JustifyContent::End)
679            .justify_content(JustifyContent::Center)
680            .justify_content(JustifyContent::Between)
681            .justify_content(JustifyContent::Around)
682            .justify_content(JustifyContent::Evenly)
683            .build();
684        
685        let css_classes = classes.to_css_classes();
686        assert!(css_classes.contains("justify-start"));
687        assert!(css_classes.contains("justify-end"));
688        assert!(css_classes.contains("justify-center"));
689        assert!(css_classes.contains("justify-between"));
690        assert!(css_classes.contains("justify-around"));
691        assert!(css_classes.contains("justify-evenly"));
692    }
693    
694    #[test]
695    fn test_align_items_utilities() {
696        let classes = ClassBuilder::new()
697            .align_items(AlignItems::Start)
698            .align_items(AlignItems::End)
699            .align_items(AlignItems::Center)
700            .align_items(AlignItems::Baseline)
701            .align_items(AlignItems::Stretch)
702            .build();
703        
704        let css_classes = classes.to_css_classes();
705        assert!(css_classes.contains("items-start"));
706        assert!(css_classes.contains("items-end"));
707        assert!(css_classes.contains("items-center"));
708        assert!(css_classes.contains("items-baseline"));
709        assert!(css_classes.contains("items-stretch"));
710    }
711    
712    #[test]
713    fn test_align_content_utilities() {
714        let classes = ClassBuilder::new()
715            .align_content(AlignContent::Start)
716            .align_content(AlignContent::End)
717            .align_content(AlignContent::Center)
718            .align_content(AlignContent::Between)
719            .align_content(AlignContent::Around)
720            .align_content(AlignContent::Evenly)
721            .align_content(AlignContent::Baseline)
722            .align_content(AlignContent::Stretch)
723            .build();
724        
725        let css_classes = classes.to_css_classes();
726        assert!(css_classes.contains("content-start"));
727        assert!(css_classes.contains("content-end"));
728        assert!(css_classes.contains("content-center"));
729        assert!(css_classes.contains("content-between"));
730        assert!(css_classes.contains("content-around"));
731        assert!(css_classes.contains("content-evenly"));
732        assert!(css_classes.contains("content-baseline"));
733        assert!(css_classes.contains("content-stretch"));
734    }
735    
736    #[test]
737    fn test_align_self_utilities() {
738        let classes = ClassBuilder::new()
739            .align_self(AlignSelf::Auto)
740            .align_self(AlignSelf::Start)
741            .align_self(AlignSelf::End)
742            .align_self(AlignSelf::Center)
743            .align_self(AlignSelf::Stretch)
744            .align_self(AlignSelf::Baseline)
745            .build();
746        
747        let css_classes = classes.to_css_classes();
748        assert!(css_classes.contains("self-auto"));
749        assert!(css_classes.contains("self-start"));
750        assert!(css_classes.contains("self-end"));
751        assert!(css_classes.contains("self-center"));
752        assert!(css_classes.contains("self-stretch"));
753        assert!(css_classes.contains("self-baseline"));
754    }
755    
756    #[test]
757    fn test_flex_grow_utilities() {
758        let classes = ClassBuilder::new()
759            .flex_grow(FlexGrow::Zero)
760            .flex_grow(FlexGrow::Grow)
761            .build();
762        
763        let css_classes = classes.to_css_classes();
764        assert!(css_classes.contains("flex-grow-0"));
765        assert!(css_classes.contains("flex-grow-grow"));
766    }
767    
768    #[test]
769    fn test_flex_shrink_utilities() {
770        let classes = ClassBuilder::new()
771            .flex_shrink(FlexShrink::Zero)
772            .flex_shrink(FlexShrink::Shrink)
773            .build();
774        
775        let css_classes = classes.to_css_classes();
776        assert!(css_classes.contains("flex-shrink-0"));
777        assert!(css_classes.contains("flex-shrink-shrink"));
778    }
779    
780    #[test]
781    fn test_flex_basis_utilities() {
782        let classes = ClassBuilder::new()
783            .flex_basis(FlexBasis::Auto)
784            .flex_basis(FlexBasis::Full)
785            .flex_basis(FlexBasis::Fit)
786            .flex_basis(FlexBasis::Max)
787            .flex_basis(FlexBasis::Min)
788            .flex_basis(FlexBasis::None)
789            .flex_basis(FlexBasis::Zero)
790            .build();
791        
792        let css_classes = classes.to_css_classes();
793        assert!(css_classes.contains("basis-auto"));
794        assert!(css_classes.contains("basis-full"));
795        assert!(css_classes.contains("basis-fit"));
796        assert!(css_classes.contains("basis-max"));
797        assert!(css_classes.contains("basis-min"));
798        assert!(css_classes.contains("basis-none"));
799        assert!(css_classes.contains("basis-0"));
800    }
801    
802    #[test]
803    fn test_order_utilities() {
804        let classes = ClassBuilder::new()
805            .order(Order::First)
806            .order(Order::Last)
807            .order(Order::None)
808            .order(Order::One)
809            .order(Order::Two)
810            .order(Order::Three)
811            .build();
812        
813        let css_classes = classes.to_css_classes();
814        assert!(css_classes.contains("order-first"));
815        assert!(css_classes.contains("order-last"));
816        assert!(css_classes.contains("order-none"));
817        assert!(css_classes.contains("order-1"));
818        assert!(css_classes.contains("order-2"));
819        assert!(css_classes.contains("order-3"));
820    }
821    
822    #[test]
823    fn test_complex_flexbox_combination() {
824        let classes = ClassBuilder::new()
825            .flex_direction(FlexDirection::Row)
826            .flex_wrap(FlexWrap::Wrap)
827            .justify_content(JustifyContent::Between)
828            .align_items(AlignItems::Center)
829            .align_content(AlignContent::Stretch)
830            .align_self(AlignSelf::Start)
831            .flex_grow(FlexGrow::Grow)
832            .flex_shrink(FlexShrink::Shrink)
833            .flex_basis(FlexBasis::Auto)
834            .order(Order::One)
835            .build();
836        
837        let css_classes = classes.to_css_classes();
838        assert!(css_classes.contains("flex-row"));
839        assert!(css_classes.contains("flex-wrap"));
840        assert!(css_classes.contains("justify-between"));
841        assert!(css_classes.contains("items-center"));
842        assert!(css_classes.contains("content-stretch"));
843        assert!(css_classes.contains("self-start"));
844        assert!(css_classes.contains("flex-grow-grow"));
845        assert!(css_classes.contains("flex-shrink-shrink"));
846        assert!(css_classes.contains("basis-auto"));
847        assert!(css_classes.contains("order-1"));
848    }
849    
850    /// Test that all Week 5 flexbox utilities are implemented
851    #[test]
852    fn test_week5_flexbox_utilities() {
853        // Test all Week 5 flexbox utilities
854        let classes = ClassBuilder::new()
855            // Flex Direction & Wrap
856            .flex_direction(FlexDirection::Row)
857            .flex_direction(FlexDirection::RowReverse)
858            .flex_direction(FlexDirection::Column)
859            .flex_direction(FlexDirection::ColumnReverse)
860            .flex_wrap(FlexWrap::Wrap)
861            .flex_wrap(FlexWrap::WrapReverse)
862            .flex_wrap(FlexWrap::NoWrap)
863            .flex(Flex::One)
864            .flex(Flex::Auto)
865            .flex(Flex::Initial)
866            .flex(Flex::None)
867            // Flex Alignment
868            .justify_content(JustifyContent::Start)
869            .justify_content(JustifyContent::End)
870            .justify_content(JustifyContent::Center)
871            .justify_content(JustifyContent::Between)
872            .justify_content(JustifyContent::Around)
873            .justify_content(JustifyContent::Evenly)
874            .align_items(AlignItems::Start)
875            .align_items(AlignItems::End)
876            .align_items(AlignItems::Center)
877            .align_items(AlignItems::Baseline)
878            .align_items(AlignItems::Stretch)
879            .align_self(AlignSelf::Auto)
880            .align_self(AlignSelf::Start)
881            .align_self(AlignSelf::End)
882            .align_self(AlignSelf::Center)
883            .align_self(AlignSelf::Stretch)
884            .align_self(AlignSelf::Baseline)
885            .build();
886        
887        let css_classes = classes.to_css_classes();
888        
889        // Flex Direction & Wrap
890        assert!(css_classes.contains("flex-row"));
891        assert!(css_classes.contains("flex-row-reverse"));
892        assert!(css_classes.contains("flex-col"));
893        assert!(css_classes.contains("flex-col-reverse"));
894        assert!(css_classes.contains("flex-wrap"));
895        assert!(css_classes.contains("flex-wrap-reverse"));
896        assert!(css_classes.contains("flex-nowrap"));
897        assert!(css_classes.contains("flex-1"));
898        assert!(css_classes.contains("flex-auto"));
899        assert!(css_classes.contains("flex-initial"));
900        assert!(css_classes.contains("flex-none"));
901        
902        // Flex Alignment
903        assert!(css_classes.contains("justify-start"));
904        assert!(css_classes.contains("justify-end"));
905        assert!(css_classes.contains("justify-center"));
906        assert!(css_classes.contains("justify-between"));
907        assert!(css_classes.contains("justify-around"));
908        assert!(css_classes.contains("justify-evenly"));
909        assert!(css_classes.contains("items-start"));
910        assert!(css_classes.contains("items-end"));
911        assert!(css_classes.contains("items-center"));
912        assert!(css_classes.contains("items-baseline"));
913        assert!(css_classes.contains("items-stretch"));
914        assert!(css_classes.contains("self-auto"));
915        assert!(css_classes.contains("self-start"));
916        assert!(css_classes.contains("self-end"));
917        assert!(css_classes.contains("self-center"));
918        assert!(css_classes.contains("self-stretch"));
919        assert!(css_classes.contains("self-baseline"));
920    }
921
922    #[test]
923    fn test_flex_direction_class_names() {
924        assert_eq!(FlexDirection::Row.to_class_name(), "row");
925        assert_eq!(FlexDirection::RowReverse.to_class_name(), "row-reverse");
926        assert_eq!(FlexDirection::Column.to_class_name(), "col");
927        assert_eq!(FlexDirection::ColumnReverse.to_class_name(), "col-reverse");
928    }
929
930    #[test]
931    fn test_flex_direction_css_values() {
932        assert_eq!(FlexDirection::Row.to_css_value(), "row");
933        assert_eq!(FlexDirection::RowReverse.to_css_value(), "row-reverse");
934        assert_eq!(FlexDirection::Column.to_css_value(), "column");
935        assert_eq!(FlexDirection::ColumnReverse.to_css_value(), "column-reverse");
936    }
937
938    #[test]
939    fn test_flex_wrap_class_names() {
940        assert_eq!(FlexWrap::NoWrap.to_class_name(), "nowrap");
941        assert_eq!(FlexWrap::Wrap.to_class_name(), "wrap");
942        assert_eq!(FlexWrap::WrapReverse.to_class_name(), "wrap-reverse");
943    }
944
945    #[test]
946    fn test_flex_wrap_css_values() {
947        assert_eq!(FlexWrap::NoWrap.to_css_value(), "nowrap");
948        assert_eq!(FlexWrap::Wrap.to_css_value(), "wrap");
949        assert_eq!(FlexWrap::WrapReverse.to_css_value(), "wrap-reverse");
950    }
951
952    #[test]
953    fn test_justify_content_class_names() {
954        assert_eq!(JustifyContent::Start.to_class_name(), "start");
955        assert_eq!(JustifyContent::End.to_class_name(), "end");
956        assert_eq!(JustifyContent::Center.to_class_name(), "center");
957        assert_eq!(JustifyContent::Between.to_class_name(), "between");
958        assert_eq!(JustifyContent::Around.to_class_name(), "around");
959        assert_eq!(JustifyContent::Evenly.to_class_name(), "evenly");
960    }
961
962    #[test]
963    fn test_justify_content_css_values() {
964        assert_eq!(JustifyContent::Start.to_css_value(), "flex-start");
965        assert_eq!(JustifyContent::End.to_css_value(), "flex-end");
966        assert_eq!(JustifyContent::Center.to_css_value(), "center");
967        assert_eq!(JustifyContent::Between.to_css_value(), "space-between");
968        assert_eq!(JustifyContent::Around.to_css_value(), "space-around");
969        assert_eq!(JustifyContent::Evenly.to_css_value(), "space-evenly");
970    }
971
972    #[test]
973    fn test_align_items_class_names() {
974        assert_eq!(AlignItems::Start.to_class_name(), "start");
975        assert_eq!(AlignItems::End.to_class_name(), "end");
976        assert_eq!(AlignItems::Center.to_class_name(), "center");
977        assert_eq!(AlignItems::Baseline.to_class_name(), "baseline");
978        assert_eq!(AlignItems::Stretch.to_class_name(), "stretch");
979    }
980
981    #[test]
982    fn test_align_items_css_values() {
983        assert_eq!(AlignItems::Start.to_css_value(), "flex-start");
984        assert_eq!(AlignItems::End.to_css_value(), "flex-end");
985        assert_eq!(AlignItems::Center.to_css_value(), "center");
986        assert_eq!(AlignItems::Baseline.to_css_value(), "baseline");
987        assert_eq!(AlignItems::Stretch.to_css_value(), "stretch");
988    }
989
990    #[test]
991    fn test_align_content_class_names() {
992        assert_eq!(AlignContent::Start.to_class_name(), "start");
993        assert_eq!(AlignContent::End.to_class_name(), "end");
994        assert_eq!(AlignContent::Center.to_class_name(), "center");
995        assert_eq!(AlignContent::Between.to_class_name(), "between");
996        assert_eq!(AlignContent::Around.to_class_name(), "around");
997        assert_eq!(AlignContent::Evenly.to_class_name(), "evenly");
998        assert_eq!(AlignContent::Baseline.to_class_name(), "baseline");
999        assert_eq!(AlignContent::Stretch.to_class_name(), "stretch");
1000    }
1001
1002    #[test]
1003    fn test_align_content_css_values() {
1004        assert_eq!(AlignContent::Start.to_css_value(), "flex-start");
1005        assert_eq!(AlignContent::End.to_css_value(), "flex-end");
1006        assert_eq!(AlignContent::Center.to_css_value(), "center");
1007        assert_eq!(AlignContent::Between.to_css_value(), "space-between");
1008        assert_eq!(AlignContent::Around.to_css_value(), "space-around");
1009        assert_eq!(AlignContent::Evenly.to_css_value(), "space-evenly");
1010        assert_eq!(AlignContent::Baseline.to_css_value(), "baseline");
1011        assert_eq!(AlignContent::Stretch.to_css_value(), "stretch");
1012    }
1013
1014    #[test]
1015    fn test_align_self_class_names() {
1016        assert_eq!(AlignSelf::Auto.to_class_name(), "auto");
1017        assert_eq!(AlignSelf::Start.to_class_name(), "start");
1018        assert_eq!(AlignSelf::End.to_class_name(), "end");
1019        assert_eq!(AlignSelf::Center.to_class_name(), "center");
1020        assert_eq!(AlignSelf::Stretch.to_class_name(), "stretch");
1021        assert_eq!(AlignSelf::Baseline.to_class_name(), "baseline");
1022    }
1023
1024    #[test]
1025    fn test_align_self_css_values() {
1026        assert_eq!(AlignSelf::Auto.to_css_value(), "auto");
1027        assert_eq!(AlignSelf::Start.to_css_value(), "flex-start");
1028        assert_eq!(AlignSelf::End.to_css_value(), "flex-end");
1029        assert_eq!(AlignSelf::Center.to_css_value(), "center");
1030        assert_eq!(AlignSelf::Stretch.to_css_value(), "stretch");
1031        assert_eq!(AlignSelf::Baseline.to_css_value(), "baseline");
1032    }
1033
1034    #[test]
1035    fn test_flex_grow_class_names() {
1036        assert_eq!(FlexGrow::Zero.to_class_name(), "0");
1037        assert_eq!(FlexGrow::Grow.to_class_name(), "grow");
1038    }
1039
1040    #[test]
1041    fn test_flex_grow_css_values() {
1042        assert_eq!(FlexGrow::Zero.to_css_value(), "0");
1043        assert_eq!(FlexGrow::Grow.to_css_value(), "1");
1044    }
1045
1046    #[test]
1047    fn test_flex_shrink_class_names() {
1048        assert_eq!(FlexShrink::Zero.to_class_name(), "0");
1049        assert_eq!(FlexShrink::Shrink.to_class_name(), "shrink");
1050    }
1051
1052    #[test]
1053    fn test_flex_shrink_css_values() {
1054        assert_eq!(FlexShrink::Zero.to_css_value(), "0");
1055        assert_eq!(FlexShrink::Shrink.to_css_value(), "1");
1056    }
1057
1058    #[test]
1059    fn test_flex_basis_class_names() {
1060        assert_eq!(FlexBasis::Auto.to_class_name(), "auto");
1061        assert_eq!(FlexBasis::Full.to_class_name(), "full");
1062        assert_eq!(FlexBasis::Fit.to_class_name(), "fit");
1063        assert_eq!(FlexBasis::Max.to_class_name(), "max");
1064        assert_eq!(FlexBasis::Min.to_class_name(), "min");
1065        assert_eq!(FlexBasis::None.to_class_name(), "none");
1066        assert_eq!(FlexBasis::Zero.to_class_name(), "0");
1067    }
1068
1069    #[test]
1070    fn test_flex_basis_css_values() {
1071        assert_eq!(FlexBasis::Auto.to_css_value(), "auto");
1072        assert_eq!(FlexBasis::Full.to_css_value(), "100%");
1073        assert_eq!(FlexBasis::Fit.to_css_value(), "fit-content");
1074        assert_eq!(FlexBasis::Max.to_css_value(), "max-content");
1075        assert_eq!(FlexBasis::Min.to_css_value(), "min-content");
1076        assert_eq!(FlexBasis::None.to_css_value(), "none");
1077        assert_eq!(FlexBasis::Zero.to_css_value(), "0%");
1078    }
1079
1080    #[test]
1081    fn test_flex_class_names() {
1082        assert_eq!(Flex::One.to_class_name(), "1");
1083        assert_eq!(Flex::Auto.to_class_name(), "auto");
1084        assert_eq!(Flex::Initial.to_class_name(), "initial");
1085        assert_eq!(Flex::None.to_class_name(), "none");
1086    }
1087
1088    #[test]
1089    fn test_flex_css_values() {
1090        assert_eq!(Flex::One.to_css_value(), "1 1 0%");
1091        assert_eq!(Flex::Auto.to_css_value(), "1 1 auto");
1092        assert_eq!(Flex::Initial.to_css_value(), "0 1 auto");
1093        assert_eq!(Flex::None.to_css_value(), "none");
1094    }
1095
1096    #[test]
1097    fn test_order_class_names() {
1098        assert_eq!(Order::First.to_class_name(), "first");
1099        assert_eq!(Order::Last.to_class_name(), "last");
1100        assert_eq!(Order::None.to_class_name(), "none");
1101        assert_eq!(Order::One.to_class_name(), "1");
1102        assert_eq!(Order::Two.to_class_name(), "2");
1103        assert_eq!(Order::Three.to_class_name(), "3");
1104        assert_eq!(Order::Four.to_class_name(), "4");
1105        assert_eq!(Order::Five.to_class_name(), "5");
1106        assert_eq!(Order::Six.to_class_name(), "6");
1107        assert_eq!(Order::Seven.to_class_name(), "7");
1108        assert_eq!(Order::Eight.to_class_name(), "8");
1109        assert_eq!(Order::Nine.to_class_name(), "9");
1110        assert_eq!(Order::Ten.to_class_name(), "10");
1111        assert_eq!(Order::Eleven.to_class_name(), "11");
1112        assert_eq!(Order::Twelve.to_class_name(), "12");
1113    }
1114
1115    #[test]
1116    fn test_order_css_values() {
1117        assert_eq!(Order::First.to_css_value(), "-9999");
1118        assert_eq!(Order::Last.to_css_value(), "9999");
1119        assert_eq!(Order::None.to_css_value(), "0");
1120        assert_eq!(Order::One.to_css_value(), "1");
1121        assert_eq!(Order::Two.to_css_value(), "2");
1122        assert_eq!(Order::Three.to_css_value(), "3");
1123        assert_eq!(Order::Four.to_css_value(), "4");
1124        assert_eq!(Order::Five.to_css_value(), "5");
1125        assert_eq!(Order::Six.to_css_value(), "6");
1126        assert_eq!(Order::Seven.to_css_value(), "7");
1127        assert_eq!(Order::Eight.to_css_value(), "8");
1128        assert_eq!(Order::Nine.to_css_value(), "9");
1129        assert_eq!(Order::Ten.to_css_value(), "10");
1130        assert_eq!(Order::Eleven.to_css_value(), "11");
1131        assert_eq!(Order::Twelve.to_css_value(), "12");
1132    }
1133
1134    #[test]
1135    fn test_flexbox_serialization() {
1136        // Test FlexDirection serialization
1137        let direction = FlexDirection::Row;
1138        let serialized = serde_json::to_string(&direction).unwrap();
1139        let deserialized: FlexDirection = serde_json::from_str(&serialized).unwrap();
1140        assert_eq!(direction, deserialized);
1141
1142        // Test JustifyContent serialization
1143        let justify = JustifyContent::Center;
1144        let serialized = serde_json::to_string(&justify).unwrap();
1145        let deserialized: JustifyContent = serde_json::from_str(&serialized).unwrap();
1146        assert_eq!(justify, deserialized);
1147
1148        // Test Order serialization
1149        let order = Order::First;
1150        let serialized = serde_json::to_string(&order).unwrap();
1151        let deserialized: Order = serde_json::from_str(&serialized).unwrap();
1152        assert_eq!(order, deserialized);
1153    }
1154
1155    #[test]
1156    fn test_flexbox_equality_and_hash() {
1157        // Test FlexDirection equality
1158        assert_eq!(FlexDirection::Row, FlexDirection::Row);
1159        assert_ne!(FlexDirection::Row, FlexDirection::Column);
1160
1161        // Test JustifyContent equality
1162        assert_eq!(JustifyContent::Center, JustifyContent::Center);
1163        assert_ne!(JustifyContent::Center, JustifyContent::Start);
1164
1165        // Test Order equality
1166        assert_eq!(Order::First, Order::First);
1167        assert_ne!(Order::First, Order::Last);
1168
1169        // Test hash consistency
1170        use std::collections::HashMap;
1171        let mut map = HashMap::new();
1172        map.insert(FlexDirection::Row, "row");
1173        map.insert(FlexDirection::Column, "column");
1174        assert_eq!(map.get(&FlexDirection::Row), Some(&"row"));
1175        assert_eq!(map.get(&FlexDirection::Column), Some(&"column"));
1176    }
1177
1178    #[test]
1179    fn test_comprehensive_flexbox_utilities() {
1180        let classes = ClassBuilder::new()
1181            .flex_direction(FlexDirection::Row)
1182            .flex_wrap(FlexWrap::Wrap)
1183            .justify_content(JustifyContent::Between)
1184            .align_items(AlignItems::Center)
1185            .align_content(AlignContent::Stretch)
1186            .align_self(AlignSelf::Start)
1187            .flex_grow(FlexGrow::Grow)
1188            .flex_shrink(FlexShrink::Shrink)
1189            .flex_basis(FlexBasis::Auto)
1190            .flex(Flex::One)
1191            .order(Order::First)
1192            .build();
1193
1194        let css_classes = classes.to_css_classes();
1195        assert!(css_classes.contains("flex-row"));
1196        assert!(css_classes.contains("flex-wrap"));
1197        assert!(css_classes.contains("justify-between"));
1198        assert!(css_classes.contains("items-center"));
1199        assert!(css_classes.contains("content-stretch"));
1200        assert!(css_classes.contains("self-start"));
1201        assert!(css_classes.contains("flex-grow-grow"));
1202        assert!(css_classes.contains("flex-shrink-shrink"));
1203        assert!(css_classes.contains("basis-auto"));
1204        assert!(css_classes.contains("flex-1"));
1205        assert!(css_classes.contains("order-first"));
1206    }
1207}