1use dioxus::prelude::*;
2use 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#[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 #[props(optional, default = None)]
171 span: Option<u8>,
172 #[props(optional, default = false)]
174 auto: bool,
175 #[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 #[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 #[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#[component]
216pub fn Col(props: ColProps) -> Element {
217 let mut class_list = vec![];
218
219 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 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 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 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}