dioxus_bootstrap/
container.rs

1use dioxus::prelude::*;
2//use crate::FlexBoxClassSet;
3
4use super::size::*;
5
6#[derive(Clone, Copy, PartialEq)]
7pub enum ContainerType {
8    Container,
9    ContainerFluid,
10}
11
12#[derive(Clone, Props, PartialEq)]
13pub struct ContainerProps {
14    #[props(optional)]
15    id: String,
16    #[props(optional, default = ExtendedSize::Normal)]
17    size: ExtendedSize,
18    #[props(optional, default = ContainerType::Container)]
19    container_type: ContainerType,
20    #[props(optional, default = false)]
21    text_center: bool,
22    #[props(optional, default = None)]
23    max_width: Option<u16>,
24    #[props(optional, default = "".to_string())]
25    class: String,
26    children: Element,
27}
28
29#[component]
30pub fn Container(props: ContainerProps) -> Element {
31    let mut class_list = match props.container_type {
32        ContainerType::ContainerFluid => vec!["container-fluid".to_string()],
33        ContainerType::Container => {
34            let size_str: &str = props.size.into();
35            if size_str.is_empty() {
36                vec!["container".to_string()]
37            } else {
38                vec![format!("container-{}", size_str)]
39            }
40        }
41    };
42
43    if props.text_center {
44        class_list.push("text-center".to_string());
45    }
46    
47    if !props.class.is_empty() {
48        class_list.push(props.class.clone());
49    }
50
51    let class_list = class_list.join(" ");
52    let style = props.max_width.map(|w| format!("max-width: {}px;", w));
53    
54    rsx! {
55        div {
56            id: props.id,
57            class: class_list,
58            style: style.unwrap_or_default(),
59            {props.children}
60        }
61    }
62}
63
64#[derive(Clone, Copy, PartialEq)]
65pub enum AlignItems {
66    Start,
67    Center,
68    End,
69    Baseline,
70    Stretch,
71}
72
73impl Into<&'static str> for AlignItems {
74    fn into(self) -> &'static str {
75        match self {
76            AlignItems::Start => "align-items-start",
77            AlignItems::Center => "align-items-center",
78            AlignItems::End => "align-items-end",
79            AlignItems::Baseline => "align-items-baseline",
80            AlignItems::Stretch => "align-items-stretch",
81        }
82    }
83}
84
85#[derive(Clone, Copy, PartialEq)]
86pub enum JustifyContent {
87    Start,
88    Center,
89    End,
90    Around,
91    Between,
92    Evenly,
93}
94
95impl Into<&'static str> for JustifyContent {
96    fn into(self) -> &'static str {
97        match self {
98            JustifyContent::Start => "justify-content-start",
99            JustifyContent::Center => "justify-content-center",
100            JustifyContent::End => "justify-content-end",
101            JustifyContent::Around => "justify-content-around",
102            JustifyContent::Between => "justify-content-between",
103            JustifyContent::Evenly => "justify-content-evenly",
104        }
105    }
106}
107
108#[derive(Clone, Props, PartialEq)]
109pub struct RowProps {
110    #[props(optional)]
111    id: String,
112    #[props(optional, default = false)]
113    no_wrap: bool,
114    #[props(optional, default = None)]
115    align_items: Option<AlignItems>,
116    #[props(optional, default = None)]
117    justify_content: Option<JustifyContent>,
118    #[props(optional, default = None)]
119    gutter: Option<u8>,
120    #[props(optional, default = "".to_string())]
121    class: String,
122    children: Element,
123}
124
125//impl super::FlexBoxContainerProps for RowProps {
126//    fn prefix() -> &'static str {"row"}
127//}
128
129#[component]
130pub fn Row(props: RowProps) -> Element {
131    let mut class_list = vec!["row".to_string()];
132
133    if props.no_wrap {
134        class_list.push("flex-nowrap".to_string());
135    }
136    
137    if let Some(align) = props.align_items {
138        let align_str: &str = align.into();
139        class_list.push(align_str.to_string());
140    }
141    
142    if let Some(justify) = props.justify_content {
143        let justify_str: &str = justify.into();
144        class_list.push(justify_str.to_string());
145    }
146    
147    if let Some(g) = props.gutter {
148        class_list.push(format!("g-{}", g));
149    }
150    
151    if !props.class.is_empty() {
152        class_list.push(props.class.clone());
153    }
154
155    let class_list = class_list.join(" ");
156    rsx!{
157        div {
158            id: props.id,
159            class: class_list,
160            {props.children}
161        }
162    }
163}
164
165#[derive(Clone, Props, PartialEq)]
166pub struct ColProps {
167    #[props(optional)]
168    id: String,
169    /// Column width (1-12)
170    #[props(optional, default = None)]
171    span: Option<u8>,
172    /// Auto-sizing column
173    #[props(optional, default = false)]
174    auto: bool,
175    /// Breakpoint-specific spans
176    #[props(optional, default = None)]
177    xs: Option<u8>,
178    #[props(optional, default = None)]
179    sm: Option<u8>,
180    #[props(optional, default = None)]
181    md: Option<u8>,
182    #[props(optional, default = None)]
183    lg: Option<u8>,
184    #[props(optional, default = None)]
185    xl: Option<u8>,
186    #[props(optional, default = None)]
187    xxl: Option<u8>,
188    /// Offset columns
189    #[props(optional, default = None)]
190    offset: Option<u8>,
191    #[props(optional, default = None)]
192    offset_sm: Option<u8>,
193    #[props(optional, default = None)]
194    offset_md: Option<u8>,
195    #[props(optional, default = None)]
196    offset_lg: Option<u8>,
197    #[props(optional, default = None)]
198    offset_xl: Option<u8>,
199    #[props(optional, default = None)]
200    offset_xxl: Option<u8>,
201    /// Order
202    #[props(optional, default = None)]
203    order: Option<u8>,
204    #[props(optional, default = false)]
205    no_wrap: bool,
206    #[props(optional, default = "".to_string())]
207    class: String,
208    children: Element,
209}
210
211//impl super::FlexBoxContainerProps for ColProps {
212//    fn prefix() -> &'static str {"col"}
213//}
214
215#[component]
216pub fn Col(props: ColProps) -> Element {
217    let mut class_list = vec![];
218    
219    // Base column class
220    if props.auto {
221        class_list.push("col-auto".to_string());
222    } else if let Some(span) = props.span {
223        class_list.push(format!("col-{}", span));
224    } else {
225        class_list.push("col".to_string());
226    }
227    
228    // Responsive breakpoint classes
229    if let Some(xs) = props.xs {
230        class_list.push(format!("col-{}", xs));
231    }
232    if let Some(sm) = props.sm {
233        class_list.push(format!("col-sm-{}", sm));
234    }
235    if let Some(md) = props.md {
236        class_list.push(format!("col-md-{}", md));
237    }
238    if let Some(lg) = props.lg {
239        class_list.push(format!("col-lg-{}", lg));
240    }
241    if let Some(xl) = props.xl {
242        class_list.push(format!("col-xl-{}", xl));
243    }
244    if let Some(xxl) = props.xxl {
245        class_list.push(format!("col-xxl-{}", xxl));
246    }
247    
248    // Offset classes
249    if let Some(offset) = props.offset {
250        class_list.push(format!("offset-{}", offset));
251    }
252    if let Some(offset_sm) = props.offset_sm {
253        class_list.push(format!("offset-sm-{}", offset_sm));
254    }
255    if let Some(offset_md) = props.offset_md {
256        class_list.push(format!("offset-md-{}", offset_md));
257    }
258    if let Some(offset_lg) = props.offset_lg {
259        class_list.push(format!("offset-lg-{}", offset_lg));
260    }
261    if let Some(offset_xl) = props.offset_xl {
262        class_list.push(format!("offset-xl-{}", offset_xl));
263    }
264    if let Some(offset_xxl) = props.offset_xxl {
265        class_list.push(format!("offset-xxl-{}", offset_xxl));
266    }
267    
268    // Order
269    if let Some(order) = props.order {
270        class_list.push(format!("order-{}", order));
271    }
272
273    if props.no_wrap {
274        class_list.push("flex-nowrap".to_string());
275    }
276    
277    if !props.class.is_empty() {
278        class_list.push(props.class.clone());
279    }
280
281    let class_list = class_list.join(" ");
282    rsx!{
283        div { 
284            id: props.id,
285            class: class_list, 
286            {props.children} 
287        }
288    }
289}