1use crate::prelude::{
4 AsClasses, ChildrenProperties, ExtendClasses, Raw, SpaceItems, Spacer, WithBreakpoints,
5};
6use std::{fmt::Debug, rc::Rc};
7use yew::{
8 html::ChildrenRenderer,
9 prelude::*,
10 virtual_dom::{VChild, VComp},
11};
12
13#[derive(Copy, Clone, Debug, PartialEq)]
14pub enum FlexModifier {
15 Grow,
17 Shrink,
19 Flex1,
21 Flex2,
23 Flex3,
25 Flex4,
27 FullWidth,
29 Column,
31 Row,
37 Justify(Justify),
38 Align(Alignment),
39}
40
41#[derive(Copy, Clone, Debug, PartialEq)]
42pub enum Justify {
43 Start,
44 End,
45 SpaceBetween,
46}
47
48#[derive(Copy, Clone, Debug, PartialEq)]
49pub enum Alignment {
50 Right,
51 Left,
52 Start,
53 Center,
54 End,
55 Baseline,
56 Stretch,
57}
58
59impl AsClasses for FlexModifier {
60 fn extend_classes(&self, classes: &mut Classes) {
61 match self {
62 FlexModifier::Grow => classes.push("pf-m-grow"),
63 FlexModifier::Shrink => classes.push("pf-m-shrink"),
64 FlexModifier::Flex1 => classes.push("pf-m-flex-1"),
65 FlexModifier::Flex2 => classes.push("pf-m-flex-2"),
66 FlexModifier::Flex3 => classes.push("pf-m-flex-3"),
67 FlexModifier::Flex4 => classes.push("pf-m-flex-4"),
68 FlexModifier::FullWidth => classes.push("pf-m-full-width"),
69 FlexModifier::Column => classes.push("pf-m-column"),
70 FlexModifier::Row => classes.push("pf-m-row"),
71 FlexModifier::Justify(layout) => match layout {
72 Justify::Start => classes.push("pf-m-justify-content-flex-start"),
73 Justify::End => classes.push("pf-m-justify-content-flex-end"),
74 Justify::SpaceBetween => classes.push("pf-m-justify-content-space-between"),
75 },
76 FlexModifier::Align(alignment) => match alignment {
77 Alignment::Right => classes.push("pf-m-align-right"),
78 Alignment::Left => classes.push("pf-m-align-left"),
79 Alignment::Start => classes.push("pf-m-align-self-flex-start"),
80 Alignment::Center => classes.push("pf-m-align-self-center"),
81 Alignment::End => classes.push("pf-m-align-self-flex-end"),
82 Alignment::Baseline => classes.push("pf-m-align-self-baseline"),
83 Alignment::Stretch => classes.push("pf-m-align-self-stretch"),
84 },
85 }
86 }
87}
88
89#[derive(Clone, PartialEq)]
90pub enum FlexChild {
91 Flex(Rc<<Flex as BaseComponent>::Properties>),
92 FlexItem(Rc<<FlexItem as BaseComponent>::Properties>),
93 Raw(Rc<<Raw as BaseComponent>::Properties>),
94}
95
96impl From<FlexProperties> for FlexChild {
97 fn from(props: FlexProperties) -> Self {
98 FlexChild::Flex(Rc::new(props))
99 }
100}
101
102impl From<FlexItemProperties> for FlexChild {
103 fn from(props: FlexItemProperties) -> Self {
104 FlexChild::FlexItem(Rc::new(props))
105 }
106}
107
108impl From<ChildrenProperties> for FlexChild {
109 fn from(props: ChildrenProperties) -> Self {
110 FlexChild::Raw(Rc::new(props))
111 }
112}
113
114#[derive(PartialEq, Clone)]
115pub struct FlexChildVariant {
116 props: FlexChild,
117}
118
119impl<CHILD> From<VChild<CHILD>> for FlexChildVariant
120where
121 CHILD: BaseComponent,
122 CHILD::Properties: Into<FlexChild> + Clone,
123{
124 fn from(vchild: VChild<CHILD>) -> Self {
125 Self {
126 props: (*vchild.props).clone().into(),
127 }
128 }
129}
130
131impl From<FlexChildVariant> for Html {
132 fn from(value: FlexChildVariant) -> Self {
133 match value.props {
134 FlexChild::Flex(props) => VComp::new::<Flex>(props, None).into(),
135 FlexChild::FlexItem(props) => VComp::new::<FlexItem>(props, None).into(),
136 FlexChild::Raw(props) => VComp::new::<Raw>(props, None).into(),
137 }
138 }
139}
140
141pub trait ToFlexItems {
142 fn into_flex_items(self) -> Vec<VChild<FlexItem>>;
143}
144
145impl ToFlexItems for Vec<Html> {
146 fn into_flex_items(self) -> Vec<VChild<FlexItem>> {
147 self.into_iter()
148 .map(|html| html_nested! {<FlexItem> { html }</FlexItem>})
149 .collect()
150 }
151}
152
153#[derive(Clone, PartialEq, Properties)]
154pub struct FlexProperties {
155 #[prop_or_default]
156 pub children: ChildrenRenderer<FlexChildVariant>,
157 #[prop_or_default]
158 pub modifiers: WithBreakpoints<FlexModifier>,
159 #[prop_or_default]
161 pub spacer: WithBreakpoints<Spacer>,
162 #[prop_or_default]
164 pub space_items: WithBreakpoints<SpaceItems>,
165}
166
167#[function_component(Flex)]
181pub fn flex(props: &FlexProperties) -> Html {
182 let mut classes = Classes::from("pf-v5-l-flex");
183
184 classes.extend_from(&props.modifiers);
185 classes.extend_from(&props.space_items);
186 classes.extend_from(&props.spacer);
187
188 html! (
189 <div class={classes}>
190 { for props.children.iter() }
191 </div>
192 )
193}
194
195#[derive(Clone, PartialEq, Properties)]
198pub struct FlexItemProperties {
199 #[prop_or_default]
200 pub children: Html,
201 #[prop_or_default]
202 pub modifiers: WithBreakpoints<FlexModifier>,
203 #[prop_or_default]
204 pub spacer: WithBreakpoints<Spacer>,
205}
206
207#[function_component(FlexItem)]
213pub fn flex_item(props: &FlexItemProperties) -> Html {
214 let mut classes = Classes::from("pf-v5-l-flex__item");
215
216 classes.extend_from(&props.modifiers);
217 classes.extend_from(&props.spacer);
218
219 html! (
220 <div class={classes}>
221 { props.children.clone() }
222 </div>
223 )
224}