Skip to main content

dioxus_tw_components/components/
formlist.rs

1use dioxus::prelude::*;
2
3pub struct FormListState {
4    max_size: usize,
5    current_size: usize,
6}
7
8impl FormListState {
9    fn new(current_size: usize) -> Self {
10        FormListState {
11            max_size: 1,
12            current_size,
13        }
14    }
15
16    fn get_max_size(&self) -> usize {
17        self.max_size
18    }
19
20    fn set_max_size(&mut self, max_size: usize) {
21        self.max_size = max_size;
22    }
23
24    fn get_current_size(&self) -> usize {
25        self.current_size
26    }
27
28    fn add_one(&mut self) {
29        if self.current_size < self.max_size {
30            self.current_size += 1;
31        }
32    }
33
34    fn remove_one(&mut self) {
35        if self.current_size > 1 {
36            self.current_size -= 1;
37        }
38    }
39}
40
41#[derive(Clone, PartialEq, Props)]
42pub struct FormListProps {
43    #[props(extends = div, extends = GlobalAttributes)]
44    attributes: Vec<Attribute>,
45
46    #[props(default = 1)]
47    max_size: usize,
48    #[props(default = 1)]
49    current_size: usize,
50
51    children: Element,
52}
53
54#[component]
55pub fn FormList(mut props: FormListProps) -> Element {
56    let default_classes = "formlist";
57    crate::setup_class_attribute(&mut props.attributes, default_classes);
58
59    let mut state = use_context_provider(|| Signal::new(FormListState::new(props.current_size)));
60
61    use_effect(move || {
62        state.write().set_max_size(props.max_size);
63    });
64
65    rsx! {
66        div { ..props.attributes, {props.children} }
67    }
68}
69
70#[derive(Clone, PartialEq, Props)]
71pub struct FormListItemProps {
72    #[props(extends = div, extends = GlobalAttributes)]
73    attributes: Vec<Attribute>,
74
75    children: Element,
76}
77
78#[component]
79pub fn FormListItem(mut props: FormListItemProps) -> Element {
80    let default_classes = "formlist-item";
81    crate::setup_class_attribute(&mut props.attributes, default_classes);
82
83    rsx! {
84        div { ..props.attributes, {props.children} }
85    }
86}
87
88#[derive(Clone, PartialEq, Props)]
89pub struct FormListLabelProps {
90    #[props(extends = label, extends = GlobalAttributes)]
91    attributes: Vec<Attribute>,
92
93    children: Element,
94}
95
96#[component]
97pub fn FormListLabel(mut props: FormListLabelProps) -> Element {
98    let default_classes = "formlist-label";
99    crate::setup_class_attribute(&mut props.attributes, default_classes);
100
101    rsx! {
102        label { ..props.attributes, {props.children} }
103    }
104}
105
106#[derive(Clone, PartialEq, Props)]
107pub struct FormListTriggerPlusProps {
108    #[props(extends = div, extends = GlobalAttributes)]
109    attributes: Vec<Attribute>,
110
111    children: Element,
112}
113
114#[component]
115pub fn FormListTriggerPlus(mut props: FormListTriggerPlusProps) -> Element {
116    let mut state = use_context::<Signal<FormListState>>();
117
118    let default_classes = "formlist-trigger-plus";
119    crate::setup_class_attribute(&mut props.attributes, default_classes);
120
121    rsx! {
122        div {
123            onclick: move |_| {
124                state.write().add_one();
125            },
126            ..props.attributes,
127            {props.children}
128        }
129    }
130}
131
132#[derive(Clone, PartialEq, Props)]
133pub struct FormListTriggerMinusProps {
134    #[props(extends = div, extends = GlobalAttributes)]
135    attributes: Vec<Attribute>,
136
137    children: Element,
138}
139
140#[component]
141pub fn FormListTriggerMinus(mut props: FormListTriggerMinusProps) -> Element {
142    let mut state = use_context::<Signal<FormListState>>();
143
144    let default_classes = "formlist-trigger-minus";
145    crate::setup_class_attribute(&mut props.attributes, default_classes);
146
147    rsx! {
148        div {
149            onclick: move |_| {
150                state.write().remove_one();
151            },
152            ..props.attributes,
153            {props.children}
154        }
155    }
156}
157
158#[derive(Clone, PartialEq, Props)]
159pub struct FormListContentProps {
160    #[props(extends = div, extends = GlobalAttributes)]
161    attributes: Vec<Attribute>,
162
163    #[props(default)]
164    list_fields: Vec<Element>,
165}
166
167#[component]
168pub fn FormListContent(mut props: FormListContentProps) -> Element {
169    let mut state = use_context::<Signal<FormListState>>();
170
171    let default_classes = "formlist-content";
172    crate::setup_class_attribute(&mut props.attributes, default_classes);
173
174    let max_size = props.list_fields.len();
175    use_effect(move || {
176        state.write().set_max_size(max_size);
177    });
178
179    let fields = props
180        .list_fields
181        .iter()
182        .take(state.read().get_current_size())
183        .map(|field| {
184            rsx! {
185                {field.clone()}
186            }
187        });
188
189    rsx! {
190        div { ..props.attributes,{fields} }
191    }
192}
193
194#[component]
195pub fn FormListMaxSize() -> Element {
196    let state = use_context::<Signal<FormListState>>();
197
198    rsx! { "{state.read().get_max_size()}" }
199}
200
201#[component]
202pub fn FormListCurrentSize() -> Element {
203    let state = use_context::<Signal<FormListState>>();
204
205    rsx! { "{state.read().get_current_size()}" }
206}