1use crate::classes::ClassBuilder;
7use serde::{Deserialize, Serialize};
8use std::fmt;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub enum FlexDirection {
13 Row,
15 RowReverse,
17 Column,
19 ColumnReverse,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
25pub enum FlexWrap {
26 NoWrap,
28 Wrap,
30 WrapReverse,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
36pub enum JustifyContent {
37 Start,
39 End,
41 Center,
43 Between,
45 Around,
47 Evenly,
49}
50
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
53pub enum AlignItems {
54 Start,
56 End,
58 Center,
60 Baseline,
62 Stretch,
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
68pub enum AlignContent {
69 Start,
71 End,
73 Center,
75 Between,
77 Around,
79 Evenly,
81 Baseline,
83 Stretch,
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
89pub enum AlignSelf {
90 Auto,
92 Start,
94 End,
96 Center,
98 Stretch,
100 Baseline,
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
106pub enum FlexGrow {
107 Zero,
109 Grow,
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
115pub enum FlexShrink {
116 Zero,
118 Shrink,
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
124pub enum FlexBasis {
125 Auto,
127 Full,
129 Fit,
131 Max,
133 Min,
135 None,
137 Zero,
139}
140
141#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
143pub enum Order {
144 First,
146 Last,
148 None,
150 One,
152 Two,
154 Three,
156 Four,
158 Five,
160 Six,
162 Seven,
164 Eight,
166 Nine,
168 Ten,
170 Eleven,
172 Twelve,
174}
175
176impl FlexDirection {
177 pub fn to_class_name(&self) -> String {
178 match self {
179 FlexDirection::Row => "row".to_string(),
180 FlexDirection::RowReverse => "row-reverse".to_string(),
181 FlexDirection::Column => "col".to_string(),
182 FlexDirection::ColumnReverse => "col-reverse".to_string(),
183 }
184 }
185
186 pub fn to_css_value(&self) -> String {
187 match self {
188 FlexDirection::Row => "row".to_string(),
189 FlexDirection::RowReverse => "row-reverse".to_string(),
190 FlexDirection::Column => "column".to_string(),
191 FlexDirection::ColumnReverse => "column-reverse".to_string(),
192 }
193 }
194}
195
196impl FlexWrap {
197 pub fn to_class_name(&self) -> String {
198 match self {
199 FlexWrap::NoWrap => "nowrap".to_string(),
200 FlexWrap::Wrap => "wrap".to_string(),
201 FlexWrap::WrapReverse => "wrap-reverse".to_string(),
202 }
203 }
204
205 pub fn to_css_value(&self) -> String {
206 match self {
207 FlexWrap::NoWrap => "nowrap".to_string(),
208 FlexWrap::Wrap => "wrap".to_string(),
209 FlexWrap::WrapReverse => "wrap-reverse".to_string(),
210 }
211 }
212}
213
214impl JustifyContent {
215 pub fn to_class_name(&self) -> String {
216 match self {
217 JustifyContent::Start => "start".to_string(),
218 JustifyContent::End => "end".to_string(),
219 JustifyContent::Center => "center".to_string(),
220 JustifyContent::Between => "between".to_string(),
221 JustifyContent::Around => "around".to_string(),
222 JustifyContent::Evenly => "evenly".to_string(),
223 }
224 }
225
226 pub fn to_css_value(&self) -> String {
227 match self {
228 JustifyContent::Start => "flex-start".to_string(),
229 JustifyContent::End => "flex-end".to_string(),
230 JustifyContent::Center => "center".to_string(),
231 JustifyContent::Between => "space-between".to_string(),
232 JustifyContent::Around => "space-around".to_string(),
233 JustifyContent::Evenly => "space-evenly".to_string(),
234 }
235 }
236}
237
238impl AlignItems {
239 pub fn to_class_name(&self) -> String {
240 match self {
241 AlignItems::Start => "start".to_string(),
242 AlignItems::End => "end".to_string(),
243 AlignItems::Center => "center".to_string(),
244 AlignItems::Baseline => "baseline".to_string(),
245 AlignItems::Stretch => "stretch".to_string(),
246 }
247 }
248
249 pub fn to_css_value(&self) -> String {
250 match self {
251 AlignItems::Start => "flex-start".to_string(),
252 AlignItems::End => "flex-end".to_string(),
253 AlignItems::Center => "center".to_string(),
254 AlignItems::Baseline => "baseline".to_string(),
255 AlignItems::Stretch => "stretch".to_string(),
256 }
257 }
258}
259
260impl AlignContent {
261 pub fn to_class_name(&self) -> String {
262 match self {
263 AlignContent::Start => "start".to_string(),
264 AlignContent::End => "end".to_string(),
265 AlignContent::Center => "center".to_string(),
266 AlignContent::Between => "between".to_string(),
267 AlignContent::Around => "around".to_string(),
268 AlignContent::Evenly => "evenly".to_string(),
269 AlignContent::Baseline => "baseline".to_string(),
270 AlignContent::Stretch => "stretch".to_string(),
271 }
272 }
273
274 pub fn to_css_value(&self) -> String {
275 match self {
276 AlignContent::Start => "flex-start".to_string(),
277 AlignContent::End => "flex-end".to_string(),
278 AlignContent::Center => "center".to_string(),
279 AlignContent::Between => "space-between".to_string(),
280 AlignContent::Around => "space-around".to_string(),
281 AlignContent::Evenly => "space-evenly".to_string(),
282 AlignContent::Baseline => "baseline".to_string(),
283 AlignContent::Stretch => "stretch".to_string(),
284 }
285 }
286}
287
288impl AlignSelf {
289 pub fn to_class_name(&self) -> String {
290 match self {
291 AlignSelf::Auto => "auto".to_string(),
292 AlignSelf::Start => "start".to_string(),
293 AlignSelf::End => "end".to_string(),
294 AlignSelf::Center => "center".to_string(),
295 AlignSelf::Stretch => "stretch".to_string(),
296 AlignSelf::Baseline => "baseline".to_string(),
297 }
298 }
299
300 pub fn to_css_value(&self) -> String {
301 match self {
302 AlignSelf::Auto => "auto".to_string(),
303 AlignSelf::Start => "flex-start".to_string(),
304 AlignSelf::End => "flex-end".to_string(),
305 AlignSelf::Center => "center".to_string(),
306 AlignSelf::Stretch => "stretch".to_string(),
307 AlignSelf::Baseline => "baseline".to_string(),
308 }
309 }
310}
311
312impl FlexGrow {
313 pub fn to_class_name(&self) -> String {
314 match self {
315 FlexGrow::Zero => "0".to_string(),
316 FlexGrow::Grow => "grow".to_string(),
317 }
318 }
319
320 pub fn to_css_value(&self) -> String {
321 match self {
322 FlexGrow::Zero => "0".to_string(),
323 FlexGrow::Grow => "1".to_string(),
324 }
325 }
326}
327
328impl FlexShrink {
329 pub fn to_class_name(&self) -> String {
330 match self {
331 FlexShrink::Zero => "0".to_string(),
332 FlexShrink::Shrink => "shrink".to_string(),
333 }
334 }
335
336 pub fn to_css_value(&self) -> String {
337 match self {
338 FlexShrink::Zero => "0".to_string(),
339 FlexShrink::Shrink => "1".to_string(),
340 }
341 }
342}
343
344impl FlexBasis {
345 pub fn to_class_name(&self) -> String {
346 match self {
347 FlexBasis::Auto => "auto".to_string(),
348 FlexBasis::Full => "full".to_string(),
349 FlexBasis::Fit => "fit".to_string(),
350 FlexBasis::Max => "max".to_string(),
351 FlexBasis::Min => "min".to_string(),
352 FlexBasis::None => "none".to_string(),
353 FlexBasis::Zero => "0".to_string(),
354 }
355 }
356
357 pub fn to_css_value(&self) -> String {
358 match self {
359 FlexBasis::Auto => "auto".to_string(),
360 FlexBasis::Full => "100%".to_string(),
361 FlexBasis::Fit => "fit-content".to_string(),
362 FlexBasis::Max => "max-content".to_string(),
363 FlexBasis::Min => "min-content".to_string(),
364 FlexBasis::None => "none".to_string(),
365 FlexBasis::Zero => "0%".to_string(),
366 }
367 }
368}
369
370impl Order {
371 pub fn to_class_name(&self) -> String {
372 match self {
373 Order::First => "first".to_string(),
374 Order::Last => "last".to_string(),
375 Order::None => "none".to_string(),
376 Order::One => "1".to_string(),
377 Order::Two => "2".to_string(),
378 Order::Three => "3".to_string(),
379 Order::Four => "4".to_string(),
380 Order::Five => "5".to_string(),
381 Order::Six => "6".to_string(),
382 Order::Seven => "7".to_string(),
383 Order::Eight => "8".to_string(),
384 Order::Nine => "9".to_string(),
385 Order::Ten => "10".to_string(),
386 Order::Eleven => "11".to_string(),
387 Order::Twelve => "12".to_string(),
388 }
389 }
390
391 pub fn to_css_value(&self) -> String {
392 match self {
393 Order::First => "-9999".to_string(),
394 Order::Last => "9999".to_string(),
395 Order::None => "0".to_string(),
396 Order::One => "1".to_string(),
397 Order::Two => "2".to_string(),
398 Order::Three => "3".to_string(),
399 Order::Four => "4".to_string(),
400 Order::Five => "5".to_string(),
401 Order::Six => "6".to_string(),
402 Order::Seven => "7".to_string(),
403 Order::Eight => "8".to_string(),
404 Order::Nine => "9".to_string(),
405 Order::Ten => "10".to_string(),
406 Order::Eleven => "11".to_string(),
407 Order::Twelve => "12".to_string(),
408 }
409 }
410}
411
412impl fmt::Display for FlexDirection {
413 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
414 write!(f, "{}", self.to_class_name())
415 }
416}
417
418impl fmt::Display for FlexWrap {
419 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
420 write!(f, "{}", self.to_class_name())
421 }
422}
423
424impl fmt::Display for JustifyContent {
425 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
426 write!(f, "{}", self.to_class_name())
427 }
428}
429
430impl fmt::Display for AlignItems {
431 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
432 write!(f, "{}", self.to_class_name())
433 }
434}
435
436impl fmt::Display for AlignContent {
437 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
438 write!(f, "{}", self.to_class_name())
439 }
440}
441
442impl fmt::Display for AlignSelf {
443 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
444 write!(f, "{}", self.to_class_name())
445 }
446}
447
448impl fmt::Display for FlexGrow {
449 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
450 write!(f, "{}", self.to_class_name())
451 }
452}
453
454impl fmt::Display for FlexShrink {
455 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456 write!(f, "{}", self.to_class_name())
457 }
458}
459
460impl fmt::Display for FlexBasis {
461 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
462 write!(f, "{}", self.to_class_name())
463 }
464}
465
466impl fmt::Display for Order {
467 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
468 write!(f, "{}", self.to_class_name())
469 }
470}
471
472pub trait FlexDirectionUtilities {
474 fn flex_direction(self, direction: FlexDirection) -> Self;
475}
476
477impl FlexDirectionUtilities for ClassBuilder {
478 fn flex_direction(self, direction: FlexDirection) -> Self {
479 self.class(format!("flex-{}", direction.to_class_name()))
480 }
481}
482
483pub trait FlexWrapUtilities {
485 fn flex_wrap(self, wrap: FlexWrap) -> Self;
486}
487
488impl FlexWrapUtilities for ClassBuilder {
489 fn flex_wrap(self, wrap: FlexWrap) -> Self {
490 self.class(format!("flex-{}", wrap.to_class_name()))
491 }
492}
493
494pub trait JustifyContentUtilities {
496 fn justify_content(self, justify: JustifyContent) -> Self;
497}
498
499impl JustifyContentUtilities for ClassBuilder {
500 fn justify_content(self, justify: JustifyContent) -> Self {
501 self.class(format!("justify-{}", justify.to_class_name()))
502 }
503}
504
505pub trait AlignItemsUtilities {
507 fn align_items(self, align: AlignItems) -> Self;
508}
509
510impl AlignItemsUtilities for ClassBuilder {
511 fn align_items(self, align: AlignItems) -> Self {
512 self.class(format!("items-{}", align.to_class_name()))
513 }
514}
515
516pub trait AlignContentUtilities {
518 fn align_content(self, align: AlignContent) -> Self;
519}
520
521impl AlignContentUtilities for ClassBuilder {
522 fn align_content(self, align: AlignContent) -> Self {
523 self.class(format!("content-{}", align.to_class_name()))
524 }
525}
526
527pub trait AlignSelfUtilities {
529 fn align_self(self, align: AlignSelf) -> Self;
530}
531
532impl AlignSelfUtilities for ClassBuilder {
533 fn align_self(self, align: AlignSelf) -> Self {
534 self.class(format!("self-{}", align.to_class_name()))
535 }
536}
537
538pub trait FlexGrowUtilities {
540 fn flex_grow(self, grow: FlexGrow) -> Self;
541}
542
543impl FlexGrowUtilities for ClassBuilder {
544 fn flex_grow(self, grow: FlexGrow) -> Self {
545 self.class(format!("flex-grow-{}", grow.to_class_name()))
546 }
547}
548
549pub trait FlexShrinkUtilities {
551 fn flex_shrink(self, shrink: FlexShrink) -> Self;
552}
553
554impl FlexShrinkUtilities for ClassBuilder {
555 fn flex_shrink(self, shrink: FlexShrink) -> Self {
556 self.class(format!("flex-shrink-{}", shrink.to_class_name()))
557 }
558}
559
560pub trait FlexBasisUtilities {
562 fn flex_basis(self, basis: FlexBasis) -> Self;
563}
564
565impl FlexBasisUtilities for ClassBuilder {
566 fn flex_basis(self, basis: FlexBasis) -> Self {
567 self.class(format!("basis-{}", basis.to_class_name()))
568 }
569}
570
571pub trait OrderUtilities {
573 fn order(self, order: Order) -> Self;
574}
575
576impl OrderUtilities for ClassBuilder {
577 fn order(self, order: Order) -> Self {
578 self.class(format!("order-{}", order.to_class_name()))
579 }
580}
581
582#[cfg(test)]
583mod tests {
584 use super::*;
585
586 #[test]
587 fn test_flex_direction_utilities() {
588 let classes = ClassBuilder::new()
589 .flex_direction(FlexDirection::Row)
590 .flex_direction(FlexDirection::RowReverse)
591 .flex_direction(FlexDirection::Column)
592 .flex_direction(FlexDirection::ColumnReverse)
593 .build();
594
595 let css_classes = classes.to_css_classes();
596 assert!(css_classes.contains("flex-row"));
597 assert!(css_classes.contains("flex-row-reverse"));
598 assert!(css_classes.contains("flex-col"));
599 assert!(css_classes.contains("flex-col-reverse"));
600 }
601
602 #[test]
603 fn test_flex_wrap_utilities() {
604 let classes = ClassBuilder::new()
605 .flex_wrap(FlexWrap::NoWrap)
606 .flex_wrap(FlexWrap::Wrap)
607 .flex_wrap(FlexWrap::WrapReverse)
608 .build();
609
610 let css_classes = classes.to_css_classes();
611 assert!(css_classes.contains("flex-nowrap"));
612 assert!(css_classes.contains("flex-wrap"));
613 assert!(css_classes.contains("flex-wrap-reverse"));
614 }
615
616 #[test]
617 fn test_justify_content_utilities() {
618 let classes = ClassBuilder::new()
619 .justify_content(JustifyContent::Start)
620 .justify_content(JustifyContent::End)
621 .justify_content(JustifyContent::Center)
622 .justify_content(JustifyContent::Between)
623 .justify_content(JustifyContent::Around)
624 .justify_content(JustifyContent::Evenly)
625 .build();
626
627 let css_classes = classes.to_css_classes();
628 assert!(css_classes.contains("justify-start"));
629 assert!(css_classes.contains("justify-end"));
630 assert!(css_classes.contains("justify-center"));
631 assert!(css_classes.contains("justify-between"));
632 assert!(css_classes.contains("justify-around"));
633 assert!(css_classes.contains("justify-evenly"));
634 }
635
636 #[test]
637 fn test_align_items_utilities() {
638 let classes = ClassBuilder::new()
639 .align_items(AlignItems::Start)
640 .align_items(AlignItems::End)
641 .align_items(AlignItems::Center)
642 .align_items(AlignItems::Baseline)
643 .align_items(AlignItems::Stretch)
644 .build();
645
646 let css_classes = classes.to_css_classes();
647 assert!(css_classes.contains("items-start"));
648 assert!(css_classes.contains("items-end"));
649 assert!(css_classes.contains("items-center"));
650 assert!(css_classes.contains("items-baseline"));
651 assert!(css_classes.contains("items-stretch"));
652 }
653
654 #[test]
655 fn test_align_content_utilities() {
656 let classes = ClassBuilder::new()
657 .align_content(AlignContent::Start)
658 .align_content(AlignContent::End)
659 .align_content(AlignContent::Center)
660 .align_content(AlignContent::Between)
661 .align_content(AlignContent::Around)
662 .align_content(AlignContent::Evenly)
663 .align_content(AlignContent::Baseline)
664 .align_content(AlignContent::Stretch)
665 .build();
666
667 let css_classes = classes.to_css_classes();
668 assert!(css_classes.contains("content-start"));
669 assert!(css_classes.contains("content-end"));
670 assert!(css_classes.contains("content-center"));
671 assert!(css_classes.contains("content-between"));
672 assert!(css_classes.contains("content-around"));
673 assert!(css_classes.contains("content-evenly"));
674 assert!(css_classes.contains("content-baseline"));
675 assert!(css_classes.contains("content-stretch"));
676 }
677
678 #[test]
679 fn test_align_self_utilities() {
680 let classes = ClassBuilder::new()
681 .align_self(AlignSelf::Auto)
682 .align_self(AlignSelf::Start)
683 .align_self(AlignSelf::End)
684 .align_self(AlignSelf::Center)
685 .align_self(AlignSelf::Stretch)
686 .align_self(AlignSelf::Baseline)
687 .build();
688
689 let css_classes = classes.to_css_classes();
690 assert!(css_classes.contains("self-auto"));
691 assert!(css_classes.contains("self-start"));
692 assert!(css_classes.contains("self-end"));
693 assert!(css_classes.contains("self-center"));
694 assert!(css_classes.contains("self-stretch"));
695 assert!(css_classes.contains("self-baseline"));
696 }
697
698 #[test]
699 fn test_flex_grow_utilities() {
700 let classes = ClassBuilder::new()
701 .flex_grow(FlexGrow::Zero)
702 .flex_grow(FlexGrow::Grow)
703 .build();
704
705 let css_classes = classes.to_css_classes();
706 assert!(css_classes.contains("flex-grow-0"));
707 assert!(css_classes.contains("flex-grow-grow"));
708 }
709
710 #[test]
711 fn test_flex_shrink_utilities() {
712 let classes = ClassBuilder::new()
713 .flex_shrink(FlexShrink::Zero)
714 .flex_shrink(FlexShrink::Shrink)
715 .build();
716
717 let css_classes = classes.to_css_classes();
718 assert!(css_classes.contains("flex-shrink-0"));
719 assert!(css_classes.contains("flex-shrink-shrink"));
720 }
721
722 #[test]
723 fn test_flex_basis_utilities() {
724 let classes = ClassBuilder::new()
725 .flex_basis(FlexBasis::Auto)
726 .flex_basis(FlexBasis::Full)
727 .flex_basis(FlexBasis::Fit)
728 .flex_basis(FlexBasis::Max)
729 .flex_basis(FlexBasis::Min)
730 .flex_basis(FlexBasis::None)
731 .flex_basis(FlexBasis::Zero)
732 .build();
733
734 let css_classes = classes.to_css_classes();
735 assert!(css_classes.contains("basis-auto"));
736 assert!(css_classes.contains("basis-full"));
737 assert!(css_classes.contains("basis-fit"));
738 assert!(css_classes.contains("basis-max"));
739 assert!(css_classes.contains("basis-min"));
740 assert!(css_classes.contains("basis-none"));
741 assert!(css_classes.contains("basis-0"));
742 }
743
744 #[test]
745 fn test_order_utilities() {
746 let classes = ClassBuilder::new()
747 .order(Order::First)
748 .order(Order::Last)
749 .order(Order::None)
750 .order(Order::One)
751 .order(Order::Two)
752 .order(Order::Three)
753 .build();
754
755 let css_classes = classes.to_css_classes();
756 assert!(css_classes.contains("order-first"));
757 assert!(css_classes.contains("order-last"));
758 assert!(css_classes.contains("order-none"));
759 assert!(css_classes.contains("order-1"));
760 assert!(css_classes.contains("order-2"));
761 assert!(css_classes.contains("order-3"));
762 }
763
764 #[test]
765 fn test_complex_flexbox_combination() {
766 let classes = ClassBuilder::new()
767 .flex_direction(FlexDirection::Row)
768 .flex_wrap(FlexWrap::Wrap)
769 .justify_content(JustifyContent::Between)
770 .align_items(AlignItems::Center)
771 .align_content(AlignContent::Stretch)
772 .align_self(AlignSelf::Start)
773 .flex_grow(FlexGrow::Grow)
774 .flex_shrink(FlexShrink::Shrink)
775 .flex_basis(FlexBasis::Auto)
776 .order(Order::One)
777 .build();
778
779 let css_classes = classes.to_css_classes();
780 assert!(css_classes.contains("flex-row"));
781 assert!(css_classes.contains("flex-wrap"));
782 assert!(css_classes.contains("justify-between"));
783 assert!(css_classes.contains("items-center"));
784 assert!(css_classes.contains("content-stretch"));
785 assert!(css_classes.contains("self-start"));
786 assert!(css_classes.contains("flex-grow-grow"));
787 assert!(css_classes.contains("flex-shrink-shrink"));
788 assert!(css_classes.contains("basis-auto"));
789 assert!(css_classes.contains("order-1"));
790 }
791}