ymc/text_inputs/
textfield.rs

1#![allow(unused_variables)]
2#![allow(dead_code)]
3
4use super::set_on_input_handler;
5use crate::text_inputs::{
6    // validity_state::ValidityStateJS, 
7    TextFieldType, ValidityState, ValidityTransform,
8};
9use crate::{to_option, to_option_string};
10use gloo::events::EventListener;
11use wasm_bindgen::prelude::*;
12use wasm_bindgen::JsCast;
13use web_sys::Node;
14use web_sys::ValidityState as NativeValidityState;
15use yew::prelude::*;
16
17
18/// The `textfield` component
19///
20/// [Documentation](https://github.com/material-components/material-components-web-components/tree/master/packages/textfield)
21pub struct TextField {
22    props: TextFieldProps,
23    node_ref: NodeRef,
24    // validity_transform_closure:
25    //     Option<Closure<dyn Fn(String, NativeValidityState) -> ValidityStateJS>>,
26    input_listener: Option<EventListener>,
27}
28
29/// Props for [`TextField`]
30///
31/// Documentation:
32///
33/// - [Properties](https://github.com/material-components/material-components-web-components/tree/master/packages/textfield#propertiesattributes)
34#[derive(Properties, Clone)]
35pub struct TextFieldProps {
36    #[prop_or_default]
37    pub open: bool,
38    #[prop_or_default]
39    pub value: String,
40    #[prop_or(TextFieldType::Text)]
41    pub field_type: TextFieldType,
42    #[prop_or_default]
43    pub label: String,
44    #[prop_or_default]
45    pub placeholder: String,
46    #[prop_or_default]
47    pub prefix: String,
48    #[prop_or_default]
49    pub suffix: String,
50    #[prop_or_default]
51    pub icon: String,
52    #[prop_or_default]
53    pub icon_trailing: String,
54    #[prop_or_default]
55    pub disabled: bool,
56    #[prop_or_default]
57    pub char_counter: bool,
58    #[prop_or_default]
59    pub outlined: bool,
60    #[prop_or_default]
61    pub helper: String,
62    #[prop_or_default]
63    pub helper_persistent: bool,
64    #[prop_or_default]
65    pub required: bool,
66    #[prop_or_default]
67    pub max_length: String,
68    #[prop_or_default]
69    pub validation_message: String,
70    #[prop_or_default]
71    pub pattern: String,
72    /// Type: `number | string` so I'll leave it as a string
73    #[prop_or_default]
74    pub min: String,
75    /// Type: `number | string`  so I'll leave it as a string
76    #[prop_or_default]
77    pub max: String,
78    // What you doing...
79    #[prop_or_default]
80    pub size: Option<i64>,
81    // ...step size
82    #[prop_or_default]
83    pub step: Option<i64>,
84    #[prop_or_default]
85    pub auto_validate: bool,
86    // #[prop_or_default]
87    // pub validity_transform: Option<ValidityTransform>,
88    #[prop_or_default]
89    pub validate_on_initial_render: bool,
90    #[prop_or_default]
91    pub oninput: Callback<InputData>,
92    #[prop_or_default]
93    pub name: String,
94}
95
96impl Component for TextField {
97    type Message = ();
98    type Properties = TextFieldProps;
99
100    fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
101        // TextField::ensure_loaded();
102        Self {
103            props,
104            node_ref: NodeRef::default(),
105            // validity_transform_closure: None,
106            input_listener: None,
107        }
108    }
109
110    fn update(&mut self, _msg: Self::Message) -> ShouldRender {
111        false
112    }
113
114    fn change(&mut self, props: Self::Properties) -> bool {
115        self.props = props;
116        true
117    }
118
119    fn view(&self) -> Html {
120        //         open=self.props.open
121        //         label?=to_option_string(&self.props.label)
122        //         placeholder?=to_option_string(&self.props.placeholder)
123        //         prefix?=to_option_string(&self.props.prefix)
124        //         suffix?=to_option_string(&self.props.suffix)
125        //         icon?=to_option_string(&self.props.icon)
126        //         iconTrailing?=to_option_string(&self.props.icon_trailing)
127        //         disabled=self.props.disabled
128        //         charCounter?=to_option(self.props.char_counter)
129        //         outlined?=to_option(self.props.outlined)
130        //         helper?=to_option_string(&self.props.helper)
131        //         helperPersistent?=to_option(self.props.helper_persistent)
132        //         required=self.props.required
133        //         maxLength?=to_option_string(&self.props.max_length)
134        //         validationMessage?=to_option_string(&self.props.validation_message)
135        //         pattern?=to_option_string(&self.props.pattern)
136        //         min?=to_option_string(&self.props.min)
137        //         max?=to_option_string(&self.props.max)
138        //         size?=self.props.size //.map_or("null".to_string(), |v| v.to_string())
139        //         step?=self.props.step //.map_or("null".to_string(), |v| v.to_string())
140        //         autoValidate?=to_option(self.props.auto_validate)
141        //         validateOnInitialRender?=to_option(self.props.validate_on_initial_render)
142        //         name?=to_option_string(&self.props.name)
143        //         ref=self.node_ref.clone()
144
145        html! {
146            <label class="mdc-text-field mdc-text-field--filled">
147                <span class="mdc-text-field__ripple"></span>
148                <span class="mdc-floating-label" id="my-label-id">{ "Hint text" }</span>
149                <input class="mdc-text-field__input" type="text" aria-labelledby="my-label-id"/>
150                <span class="mdc-line-ripple"></span>
151            </label>
152        }
153    }
154
155    fn rendered(&mut self, first_render: bool) {
156        // if first_render {
157        //     self.input_listener = Some(set_on_input_handler(
158        //         &self.node_ref,
159        //         self.props.oninput.clone(),
160        //         |(input_event, detail)| {
161        //             InputData {
162        //                 value: detail
163        //                     .unchecked_into::<TextFieldInputEvent>()
164        //                     .target()
165        //                     .value(),
166        //                 event: input_event,
167        //             }
168        //         },
169        //     ));
170
171        //     let element = self.node_ref.cast::<TextField>().unwrap();
172        //     element.set_type(&JsValue::from(&self.props.field_type.to_string()));
173        //     element.set_value(&JsValue::from(&self.props.value));
174
175        //     let this = self.node_ref.cast::<TextField>().unwrap();
176        //     if let Some(transform) = self.props.validity_transform.clone() {
177        //         self.validity_transform_closure = Some(Closure::wrap(Box::new(
178        //             move |s: String, v: NativeValidityState| -> ValidityStateJS {
179        //                 transform.0(s, v).into()
180        //             },
181        //         )
182        //             as Box<dyn Fn(String, NativeValidityState) -> ValidityStateJS>));
183        //         this.set_validity_transform(&self.validity_transform_closure.as_ref().unwrap());
184        //     }
185        // }
186    }
187}
188
189impl TextField {
190    pub fn validity_transform<F: Fn(String, NativeValidityState) -> ValidityState + 'static>(
191        func: F,
192    ) -> ValidityTransform {
193        ValidityTransform::new(func)
194    }
195}
196