@@ -57,13 +57,12 @@ pub fn AutoComplete(
57
57
css_vars
58
58
} ) ;
59
59
60
- let select_option_index = create_rw_signal :: < usize > ( 0 ) ;
60
+ let select_option_index = create_rw_signal :: < Option < usize > > ( None ) ;
61
61
let menu_ref = create_node_ref :: < html:: Div > ( ) ;
62
62
let is_show_menu = create_rw_signal ( false ) ;
63
63
let auto_complete_ref = create_node_ref :: < html:: Div > ( ) ;
64
64
let options = StoredMaybeSignal :: from ( options) ;
65
65
let open_menu = move || {
66
- select_option_index. set ( 0 ) ;
67
66
is_show_menu. set ( true ) ;
68
67
} ;
69
68
let allow_value = move |_| {
@@ -82,39 +81,53 @@ pub fn AutoComplete(
82
81
if let Some ( on_select) = on_select {
83
82
on_select. call ( option_value) ;
84
83
}
84
+ select_option_index. set ( None ) ;
85
85
is_show_menu. set ( false ) ;
86
86
} ;
87
87
88
+ // we unset selection index whenever options get changed
89
+ // otherwise e.g. selection could move from one item to
90
+ // another staying on the same index
91
+ create_effect ( move |_ | {
92
+ options. get ( ) ;
93
+ select_option_index. update ( |index| * index = None ) ;
94
+ } ) ;
95
+
88
96
let on_keydown = move |event : ev:: KeyboardEvent | {
89
97
if !is_show_menu. get_untracked ( ) {
90
98
return ;
91
99
}
92
100
let key = event. key ( ) ;
93
101
if key == * "ArrowDown" {
94
102
select_option_index. update ( |index| {
95
- if * index == options. with_untracked ( |options| options. len ( ) ) - 1 {
96
- * index = 0
103
+ if * index == Some ( options. with_untracked ( |options| options. len ( ) ) - 1 ) {
104
+ * index = None
97
105
} else {
98
- * index += 1
106
+ * index = Some ( index . map_or ( 0 , |index| index + 1 ) )
99
107
}
100
108
} ) ;
101
109
} else if key == * "ArrowUp" {
102
110
select_option_index. update ( |index| {
103
- if * index == 0 {
104
- * index = options. with_untracked ( |options| options. len ( ) ) - 1 ;
111
+ if * index == Some ( 0 ) {
112
+ * index = None // options.with_untracked(|options| options.len()) - 1;
105
113
} else {
106
- * index -= 1
114
+ * index = index . map ( |index| index - 1 )
107
115
}
108
116
} ) ;
109
117
} else if key == * "Enter" {
110
118
event. prevent_default ( ) ;
111
119
let option_value = options. with_untracked ( |options| {
112
120
let index = select_option_index. get_untracked ( ) ;
113
- if options. len ( ) > index {
114
- let option = & options[ index] ;
115
- Some ( option. value . clone ( ) )
116
- } else {
117
- None
121
+ match index {
122
+ None => {
123
+ let value = value. get_untracked ( ) ;
124
+ ( !value. is_empty ( ) ) . then_some ( value)
125
+ }
126
+ Some ( index) if options. len ( ) > index => {
127
+ let option = & options[ index] ;
128
+ Some ( option. value . clone ( ) )
129
+ }
130
+ _ => None
118
131
}
119
132
} ) ;
120
133
if let Some ( option_value) = option_value {
@@ -189,13 +202,13 @@ pub fn AutoComplete(
189
202
select_value( option_value. clone( ) ) ;
190
203
} ;
191
204
let on_mouseenter = move |_| {
192
- select_option_index. set( index) ;
205
+ select_option_index. set( Some ( index) ) ;
193
206
} ;
194
207
let on_mousedown = move |ev: ev:: MouseEvent | {
195
208
ev. prevent_default( ) ;
196
209
} ;
197
210
create_effect( move |_| {
198
- if index == select_option_index. get( ) {
211
+ if Some ( index) == select_option_index. get( ) {
199
212
if !is_show_menu. get( ) {
200
213
return ;
201
214
}
@@ -218,7 +231,7 @@ pub fn AutoComplete(
218
231
class="thaw-auto-complete__menu-item"
219
232
class=(
220
233
"thaw-auto-complete__menu-item--selected" ,
221
- move || index == select_option_index. get( ) ,
234
+ move || Some ( index) == select_option_index. get( ) ,
222
235
)
223
236
224
237
on: click=on_click
0 commit comments