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