ymc/
select.rs

1#![allow(unused_variables)]
2#![allow(dead_code)]
3
4#[doc(inline)]
5pub use super::list::{ActionDetail, ListIndex, SelectedDetail};
6
7use super::text_inputs::{
8    // validity_state::ValidityStateJS, 
9    NativeValidityState, ValidityState, ValidityTransform,
10};
11use super::utils::WeakComponentLink;
12use super::{event_into_details, to_option, to_option_string};
13use gloo::events::EventListener;
14use wasm_bindgen::prelude::*;
15use web_sys::Node;
16use yew::prelude::*;
17
18/// The `select` component
19///
20/// [Documentation](https://github.com/material-components/material-components-web-components/tree/master/packages/select)
21pub struct Select {
22    props: Props,
23    node_ref: NodeRef,
24    // validity_transform_closure:
25    //     Option<Closure<dyn Fn(String, NativeValidityState) -> ValidityStateJS>>,
26    opened_listener: Option<EventListener>,
27    closed_listener: Option<EventListener>,
28    action_listener: Option<EventListener>,
29    selected_listener: Option<EventListener>,
30}
31
32/// Props for [`Select`]
33///
34/// Documentation:
35///
36/// - [Properties](https://github.com/material-components/material-components-web-components/tree/master/packages/select#propertiesattributes)
37/// - [Events](https://github.com/material-components/material-components-web-components/tree/master/packages/select#events)
38#[derive(Clone, PartialEq, Properties)]
39pub struct Props {
40    #[prop_or_default]
41    pub value: String,
42    #[prop_or_default]
43    pub label: String,
44    #[prop_or_default]
45    pub natural_menu_width: bool,
46    #[prop_or_default]
47    pub icon: String,
48    #[prop_or_default]
49    pub disabled: bool,
50    #[prop_or_default]
51    pub outlined: bool,
52    #[prop_or_default]
53    pub helper: String,
54    #[prop_or_default]
55    pub required: bool,
56    #[prop_or_default]
57    pub validation_message: String,
58    #[prop_or_default]
59    pub items: String,
60    #[prop_or(- 1)]
61    pub index: i64,
62    // #[prop_or_default]
63    // pub validity_transform: Option<ValidityTransform>,
64    #[prop_or_default]
65    pub validate_on_initial_render: bool,
66    #[prop_or_default]
67    pub children: Children,
68    /// [`WeakComponentLink`] for `List` which provides the following methods
69    /// - ```select(&self)```
70    ///
71    /// See [`WeakComponentLink`] documentation for more information
72    #[prop_or_default]
73    pub select_link: WeakComponentLink<Select>,
74    /// Binds to `opened` event on `select-surface`
75    ///
76    /// See events docs to learn more.
77    #[prop_or_default]
78    pub onopened: Callback<()>,
79    /// Binds to `closed` event on `select-surface`
80    ///
81    /// See events docs to learn more.
82    #[prop_or_default]
83    pub onclosed: Callback<()>,
84    /// Binds to `action` event on `list`
85    ///
86    /// See events docs to learn more.
87    #[prop_or_default]
88    pub onaction: Callback<ActionDetail>,
89    /// Binds to `selected` event on `list`
90    ///
91    /// See events docs to learn more.
92    #[prop_or_default]
93    pub onselected: Callback<SelectedDetail>,
94}
95
96impl Component for Select {
97    type Message = ();
98    type Properties = Props;
99
100    fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
101        // props.select_link.borrow_mut().replace(link);
102        // Select::ensure_loaded();
103        Self {
104            props,
105            node_ref: NodeRef::default(),
106            // validity_transform_closure: None,
107            opened_listener: None,
108            closed_listener: None,
109            action_listener: None,
110            selected_listener: None,
111        }
112    }
113
114    fn update(&mut self, _msg: Self::Message) -> ShouldRender {
115        false
116    }
117
118    fn change(&mut self, props: Self::Properties) -> bool {
119        if self.props != props {
120            self.props = props;
121            true
122        } else {
123            false
124        }
125    }
126
127    fn view(&self) -> Html {
128        //         value?=to_option_string(&self.props.value)
129        //         label?=to_option_string(&self.props.label)
130        //         naturalMenuWidth?=to_option(self.props.natural_menu_width)
131        //         icon?=to_option_string(&self.props.icon)
132        //         disabled=self.props.disabled
133        //         outlined?=to_option(self.props.outlined)
134        //         helper?=to_option_string(&self.props.helper)
135        //         required=self.props.required
136        //         validationMessage?=to_option_string(&self.props.validation_message)
137        //         items?=to_option_string(&self.props.items)
138        //         index=self.props.index
139        //         validateOnInitialRender?=to_option(self.props.validate_on_initial_render)
140        //         ref=self.node_ref.clone()
141
142        //       { self.props.children.clone() }
143
144        html!{
145            <div class="mdc-select mdc-select--filled demo-width-class">
146                <div class="mdc-select__anchor"
147                    role="button"
148                    aria-haspopup="listbox"
149                    aria-expanded="false"
150                    aria-labelledby="demo-label demo-selected-text">
151                    <span class="mdc-select__ripple"></span>
152                    <span id="demo-label" class="mdc-floating-label"> { "Pick a Food Group" }</span>
153                    <span class="mdc-select__selected-text-container">
154                    <span id="demo-selected-text" class="mdc-select__selected-text">{ "Vegetables" }</span>
155                    </span>
156                    <span class="mdc-select__dropdown-icon">
157                        <svg
158                            class="mdc-select__dropdown-icon-graphic"
159                            viewBox="7 10 10 5" focusable="false">
160                            <polygon
161                                class="mdc-select__dropdown-icon-inactive"
162                                stroke="none"
163                                fill-rule="evenodd"
164                                points="7 10 12 15 17 10">
165                            </polygon>
166                            <polygon
167                                class="mdc-select__dropdown-icon-active"
168                                stroke="none"
169                                fill-rule="evenodd"
170                                points="7 15 12 10 17 15">
171                            </polygon>
172                        </svg>
173                    </span>
174                    <span class="mdc-line-ripple"></span>
175                </div>
176
177                <div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
178                    <ul class="mdc-list" role="listbox" aria-label="Food picker listbox">
179                    <li class="mdc-list-item mdc-list-item--selected" aria-selected="true" data-value="" role="option">
180                        <span class="mdc-list-item__ripple"></span>
181                    </li>
182                    <li class="mdc-list-item" aria-selected="false" data-value="grains" role="option">
183                        <span class="mdc-list-item__ripple"></span>
184                        <span class="mdc-list-item__text">
185                        { "Bread, Cereal, Rice, and Pasta" }
186                        </span>
187                    </li>
188                    <li class="mdc-list-item mdc-list-item--disabled" aria-selected="false" data-value="vegetables" aria-disabled="true" role="option">
189                        <span class="mdc-list-item__ripple"></span>
190                        <span class="mdc-list-item__text">
191                        { "Vegetables" }
192                        </span>
193                    </li>
194                    <li class="mdc-list-item" aria-selected="false" data-value="fruit" role="option">
195                        <span class="mdc-list-item__ripple"></span>
196                        <span class="mdc-list-item__text">
197                        { "Fruit" }
198                        </span>
199                    </li>
200                    </ul>
201                </div>
202            </div>
203        }
204    }
205
206    //noinspection DuplicatedCode
207    fn rendered(&mut self, first_render: bool) {
208        // if first_render {
209        //     let element = self.node_ref.cast::<Select>().unwrap();
210        //     if let Some(transform) = self.props.validity_transform.clone() {
211        //         self.validity_transform_closure = Some(Closure::wrap(Box::new(
212        //             move |s: String, v: NativeValidityState| -> ValidityStateJS {
213        //                 transform.0(s, v).into()
214        //             },
215        //         )
216        //             as Box<dyn Fn(String, NativeValidityState) -> ValidityStateJS>));
217        //         element.set_validity_transform(&self.validity_transform_closure.as_ref().unwrap());
218        //     }
219
220        //     let onopened = self.props.onopened.clone();
221        //     self.opened_listener = Some(EventListener::new(&element, "opened", move |_| {
222        //         onopened.emit(())
223        //     }));
224
225        //     let onclosed = self.props.onclosed.clone();
226        //     self.closed_listener = Some(EventListener::new(&element, "closed", move |_| {
227        //         onclosed.emit(())
228        //     }));
229
230        //     let on_action = self.props.onaction.clone();
231        //     self.action_listener = Some(EventListener::new(&element, "action", move |event| {
232        //         on_action.emit(ActionDetail::from(event_into_details(event)))
233        //     }));
234
235        //     let on_selected = self.props.onselected.clone();
236        //     self.selected_listener = Some(EventListener::new(&element, "selected", move |event| {
237        //         on_selected.emit(SelectedDetail::from(event_into_details(event)))
238        //     }));
239        // }
240    }
241}
242
243impl WeakComponentLink<Select> {
244    pub fn select(&self, val: usize) {
245        // let c = (*self.borrow().as_ref().unwrap().get_component().unwrap())
246        //     .node_ref
247        //     .clone();
248        // let select_element = c.cast::<Select>().unwrap();
249        // select_element.select(val);
250    }
251}
252
253impl Select {
254    /// Returns [`ValidityTransform`] to be passed to `validity_transform` prop
255    pub fn validity_transform<F: Fn(String, NativeValidityState) -> ValidityState + 'static>(
256        func: F,
257    ) -> ValidityTransform {
258        ValidityTransform::new(func)
259    }
260}