@@ -4,7 +4,7 @@ use yew::prelude::*;
4
4
/// Props for a custom input component.
5
5
#[ derive( Properties , PartialEq ) ]
6
6
pub struct Props {
7
- /// The type of the input, e.g., "text", "email", " password", etc.
7
+ /// The type of the input, e.g., "text", "password", etc.
8
8
pub input_type : Option < String > ,
9
9
10
10
/// The label to be displayed for the input field.
@@ -13,9 +13,6 @@ pub struct Props {
13
13
/// The name of the input field, used for form submission and accessibility.
14
14
pub name : String ,
15
15
16
- /// The icon class to be used for displaying an icon alongside the input.
17
- pub icon : String ,
18
-
19
16
/// Indicates whether the input is required or not.
20
17
pub required : bool ,
21
18
@@ -52,6 +49,12 @@ pub struct Props {
52
49
/// A callback function to validate the input value. It takes a `String` as input and returns a `bool`.
53
50
pub validate_function : Callback < String , bool > ,
54
51
52
+ /// The icon when the password is visible.
53
+ pub eye_active : Option < String > ,
54
+
55
+ /// The icon when the password is not visible.
56
+ pub eye_disabled : Option < String > ,
57
+
55
58
// Additional props for accessibility and SEO:
56
59
/// The ID attribute of the input element.
57
60
pub input_id : Option < String > ,
@@ -117,7 +120,6 @@ pub struct Props {
117
120
/// input_ref={input_email_ref}
118
121
/// input_placeholder={"Email".to_string()}
119
122
/// icon_class={"fas fa-user".to_string()}
120
- /// icon={"fas fa-user".to_string()}
121
123
/// error_message={"Enter a valid email address".to_string()}
122
124
/// form_input_class={"".to_string()}
123
125
/// form_input_field_class={"form-one-field".to_string()}
@@ -134,13 +136,30 @@ pub struct Props {
134
136
/// ```
135
137
#[ function_component( CustomInput ) ]
136
138
pub fn custom_input ( props : & Props ) -> Html {
139
+
140
+ let eye_active_handle = use_state ( || false ) ;
141
+ let eye_active = ( * eye_active_handle) . clone ( ) ;
142
+
143
+ let password_type_handle = use_state ( || "password" ) ;
144
+ let password_type = ( * password_type_handle) . clone ( ) ;
145
+
137
146
let input_valid = * props. input_valid_handle ;
138
147
139
148
let aria_invalid = props
140
149
. aria_invalid
141
150
. clone ( )
142
151
. unwrap_or_else ( || "true" . to_string ( ) ) ;
143
152
153
+ let eye_icon_active = props
154
+ . eye_active
155
+ . clone ( )
156
+ . unwrap_or_else ( || "fa fa-eye" . to_string ( ) ) ;
157
+
158
+ let eye_icon_disabled = props
159
+ . eye_disabled
160
+ . clone ( )
161
+ . unwrap_or_else ( || "fa fa-eye-slash" . to_string ( ) ) ;
162
+
144
163
let aria_required = props
145
164
. aria_required
146
165
. clone ( )
@@ -166,14 +185,22 @@ pub fn custom_input(props: &Props) -> Html {
166
185
} )
167
186
} ;
168
187
169
- html ! {
170
- <div class={ props. form_input_class. clone( ) } >
171
- <label class={ props. form_input_label_class. clone( ) } for ={ props. input_id. clone( ) } >
172
- { & props. label}
173
- </label>
174
- <div class={ props. form_input_field_class. clone( ) } >
188
+ let on_toggle_password = {
189
+ Callback :: from ( move |_| {
190
+ if eye_active {
191
+ password_type_handle. set ( "password" . into ( ) )
192
+ } else {
193
+ password_type_handle. set ( "text" . into ( ) )
194
+ }
195
+ eye_active_handle. set ( !eye_active) ;
196
+ } )
197
+ } ;
198
+
199
+ let input_tag = match ( * input_type) . into ( ) {
200
+ "password" => html ! {
201
+ <>
175
202
<input
176
- type ={ input_type }
203
+ type ={ password_type }
177
204
class={ props. form_input_input_class. clone( ) }
178
205
id={ props. input_id. clone( ) }
179
206
name={ props. name. clone( ) }
@@ -186,6 +213,53 @@ pub fn custom_input(props: &Props) -> Html {
186
213
oninput={ onchange}
187
214
required={ props. required}
188
215
/>
216
+ <span
217
+ class={ format!( "toggle-button {}" , if eye_active { eye_icon_active } else { eye_icon_disabled } ) }
218
+ onclick={ on_toggle_password}
219
+ ></span>
220
+ </>
221
+ } ,
222
+ "textarea" => html ! {
223
+ <textarea
224
+ class={ props. form_input_input_class. clone( ) }
225
+ id={ props. input_id. clone( ) }
226
+ name={ props. name. clone( ) }
227
+ ref={ props. input_ref. clone( ) }
228
+ placeholder={ props. input_placeholder. clone( ) }
229
+ aria-label={ props. aria_label. clone( ) }
230
+ aria-required={ aria_required}
231
+ aria-invalid={ aria_invalid}
232
+ aria-describedby={ props. aria_describedby. clone( ) }
233
+ oninput={ onchange}
234
+ required={ props. required}
235
+ >
236
+ </textarea>
237
+ } ,
238
+ _ => html ! {
239
+ <input
240
+ type ={ input_type}
241
+ class={ props. form_input_input_class. clone( ) }
242
+ id={ props. input_id. clone( ) }
243
+ name={ props. name. clone( ) }
244
+ ref={ props. input_ref. clone( ) }
245
+ placeholder={ props. input_placeholder. clone( ) }
246
+ aria-label={ props. aria_label. clone( ) }
247
+ aria-required={ aria_required}
248
+ aria-invalid={ aria_invalid}
249
+ aria-describedby={ props. aria_describedby. clone( ) }
250
+ oninput={ onchange}
251
+ required={ props. required}
252
+ />
253
+ }
254
+ } ;
255
+
256
+ html ! {
257
+ <div class={ props. form_input_class. clone( ) } >
258
+ <label class={ props. form_input_label_class. clone( ) } for ={ props. input_id. clone( ) } >
259
+ { & props. label}
260
+ </label>
261
+ <div class={ props. form_input_field_class. clone( ) } >
262
+ { input_tag }
189
263
<span class={ props. icon_class. clone( ) } ></span>
190
264
</div>
191
265
if !input_valid {
0 commit comments