yew_bs/components/
grid.rs

1use yew::prelude::*;
2use crate::components::common::Breakpoint;
3#[derive(Properties, PartialEq)]
4pub struct GridProps {
5    #[prop_or_default]
6    pub children: Children,
7    #[prop_or_default]
8    pub fluid: bool,
9    #[prop_or_default]
10    pub breakpoint: Option<Breakpoint>,
11    #[prop_or_default]
12    pub gutter: Option<u8>,
13    #[prop_or_default]
14    pub gutter_x: Option<u8>,
15    #[prop_or_default]
16    pub gutter_y: Option<u8>,
17    #[prop_or_default]
18    pub container_class: Option<AttrValue>,
19    #[prop_or_default]
20    pub row_class: Option<AttrValue>,
21    #[prop_or_default]
22    pub node_ref: NodeRef,
23}
24#[function_component(Grid)]
25pub fn grid(props: &GridProps) -> Html {
26    let mut container_classes = Classes::new();
27    if props.fluid {
28        container_classes.push("container-fluid");
29    } else if let Some(breakpoint) = props.breakpoint {
30        container_classes.push(format!("container-{}", breakpoint.as_str()));
31    } else {
32        container_classes.push("container");
33    }
34    if let Some(class) = &props.container_class {
35        container_classes.push(class.to_string());
36    }
37    let mut row_classes = Classes::new();
38    row_classes.push("row");
39    if let Some(gutter) = props.gutter {
40        row_classes.push(format!("g-{}", gutter));
41    } else {
42        if let Some(gutter_x) = props.gutter_x {
43            row_classes.push(format!("gx-{}", gutter_x));
44        }
45        if let Some(gutter_y) = props.gutter_y {
46            row_classes.push(format!("gy-{}", gutter_y));
47        }
48    }
49    if let Some(class) = &props.row_class {
50        row_classes.push(class.to_string());
51    }
52    html! {
53        < div class = { container_classes } ref = { props.node_ref.clone() } > < div
54        class = { row_classes } > { for props.children.iter() } </ div > </ div >
55    }
56}
57#[derive(Properties, PartialEq)]
58pub struct GridItemProps {
59    #[prop_or_default]
60    pub children: Children,
61    #[prop_or_default]
62    pub size: Option<GridSize>,
63    #[prop_or_default]
64    pub xs: Option<GridSize>,
65    #[prop_or_default]
66    pub sm: Option<GridSize>,
67    #[prop_or_default]
68    pub md: Option<GridSize>,
69    #[prop_or_default]
70    pub lg: Option<GridSize>,
71    #[prop_or_default]
72    pub xl: Option<GridSize>,
73    #[prop_or_default]
74    pub xxl: Option<GridSize>,
75    #[prop_or_default]
76    pub offset: Option<u8>,
77    #[prop_or_default]
78    pub order: Option<GridOrder>,
79    #[prop_or_default]
80    pub class: Option<AttrValue>,
81    #[prop_or_default]
82    pub node_ref: NodeRef,
83}
84#[derive(Clone, Copy, PartialEq, Debug)]
85pub enum GridSize {
86    Auto,
87    Fixed(u8),
88}
89#[derive(Clone, Copy, PartialEq, Debug)]
90pub enum GridOrder {
91    First,
92    Last,
93    Number(u8),
94}
95impl GridOrder {
96    pub fn as_str(&self) -> String {
97        match self {
98            GridOrder::First => "first".to_string(),
99            GridOrder::Last => "last".to_string(),
100            GridOrder::Number(n) => n.to_string(),
101        }
102    }
103}
104#[function_component(GridItem)]
105pub fn grid_item(props: &GridItemProps) -> Html {
106    let mut classes = Classes::new();
107    let has_breakpoint_sizes = props.xs.is_some() || props.sm.is_some()
108        || props.md.is_some() || props.lg.is_some() || props.xl.is_some()
109        || props.xxl.is_some();
110    if !has_breakpoint_sizes {
111        match props.size {
112            Some(GridSize::Auto) => classes.push("col-auto"),
113            Some(GridSize::Fixed(size)) => classes.push(format!("col-{}", size)),
114            None => classes.push("col"),
115        }
116    } else {
117        if let Some(size) = props.xs {
118            match size {
119                GridSize::Auto => classes.push("col-auto"),
120                GridSize::Fixed(s) => classes.push(format!("col-{}", s)),
121            }
122        }
123        if let Some(size) = props.sm {
124            match size {
125                GridSize::Auto => classes.push("col-sm-auto"),
126                GridSize::Fixed(s) => classes.push(format!("col-sm-{}", s)),
127            }
128        }
129        if let Some(size) = props.md {
130            match size {
131                GridSize::Auto => classes.push("col-md-auto"),
132                GridSize::Fixed(s) => classes.push(format!("col-md-{}", s)),
133            }
134        }
135        if let Some(size) = props.lg {
136            match size {
137                GridSize::Auto => classes.push("col-lg-auto"),
138                GridSize::Fixed(s) => classes.push(format!("col-lg-{}", s)),
139            }
140        }
141        if let Some(size) = props.xl {
142            match size {
143                GridSize::Auto => classes.push("col-xl-auto"),
144                GridSize::Fixed(s) => classes.push(format!("col-xl-{}", s)),
145            }
146        }
147        if let Some(size) = props.xxl {
148            match size {
149                GridSize::Auto => classes.push("col-xxl-auto"),
150                GridSize::Fixed(s) => classes.push(format!("col-xxl-{}", s)),
151            }
152        }
153    }
154    if let Some(offset) = props.offset {
155        classes.push(format!("offset-{}", offset));
156    }
157    if let Some(order) = &props.order {
158        classes.push(format!("order-{}", order.as_str()));
159    }
160    if let Some(class) = &props.class {
161        classes.push(class.to_string());
162    }
163    html! {
164        < div class = { classes } ref = { props.node_ref.clone() } > { for props.children
165        .iter() } </ div >
166    }
167}