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}