@@ -27,9 +27,6 @@ export default class TailoredSelect extends LitElement {
2727
2828 connectedCallback ( ) {
2929 super . connectedCallback ( )
30-
31- // Ensure focusable
32- // this.tabIndex = 0
3330 }
3431
3532 firstUpdated ( changedProperties ) {
@@ -38,19 +35,19 @@ export default class TailoredSelect extends LitElement {
3835 // On load, everything starts in available. We need to move selected over.
3936 this . availableOptions . forEach ( ( option ) => {
4037 option . addEventListener ( 'click' , ( ) => this . toggleOption ( option ) )
41- option . addEventListener ( 'mouseover' , ( ) => this . handleOptionFocus ( option ) )
38+ option . addEventListener ( 'mouseover' , ( ) => this . handleOptionActive ( option ) )
4239 this . assignOptionSlot ( option )
4340 } )
4441
45- this . resetOptionFocus ( )
42+ this . resetActiveOption ( )
4643 this . updateFormValue ( )
4744 }
4845
4946 // Input Behavior
5047
5148 handleInputBlur ( ) {
5249 this . hasFocus = false
53- this . resetOptionFocus ( )
50+ this . resetActiveOption ( )
5451 // this.emit('ts-blur')
5552 }
5653
@@ -66,16 +63,21 @@ export default class TailoredSelect extends LitElement {
6663 handleInputKeyDown ( event ) {
6764 switch ( event . key ) {
6865 case 'ArrowDown' :
69- this . focusNextOption ( )
66+ this . activateNextOption ( )
7067 break
7168 case 'ArrowUp' :
72- this . focusPreviousOption ( )
69+ this . activatePreviousOption ( )
7370 break
7471 case 'Enter' :
75- this . toggleOption ( this . focusedOption )
72+ if ( this . availableOptions . length > 0 ) {
73+ this . toggleOption ( this . activeOption )
74+ }
7675 break
7776 case 'Backspace' :
7877 this . deleteSelection ( )
78+ if ( ! this . activeOption ) {
79+ this . resetActiveOption ( )
80+ }
7981 break
8082 }
8183 }
@@ -85,13 +87,17 @@ export default class TailoredSelect extends LitElement {
8587 if ( ! value ) {
8688 // Make all options visible
8789 this . availableOptions . forEach ( ( opt ) => ( opt . hidden = false ) )
90+ this . resetActiveOption ( )
8891 return
8992 }
9093
9194 const matcher = new RegExp ( value , 'i' )
9295 this . availableOptions . forEach ( ( opt ) => {
9396 opt . hidden = ! Boolean ( opt . value . match ( matcher ) )
9497 } )
98+
99+ this . resetActiveOption ( )
100+ this . updateNoResultsMessage ( )
95101 }
96102
97103 deleteSelection ( ) {
@@ -121,7 +127,7 @@ export default class TailoredSelect extends LitElement {
121127
122128 // Option Behavior
123129
124- handleOptionFocus ( option ) {
130+ handleOptionActive ( option ) {
125131 if ( option . selected ) {
126132 return
127133 }
@@ -150,42 +156,52 @@ export default class TailoredSelect extends LitElement {
150156 return this . shadowRoot . querySelector ( 'div[role="listbox"]' )
151157 }
152158
153- focusNextOption ( option = this . focusedOption ) {
159+ activateNextOption ( option = this . activeOption ) {
154160 const index = this . availableOptions . indexOf ( option )
155- if ( index == this . availableOptions . length - 1 ) return
161+ if ( index == this . availableOptions . length - 1 ) return false
156162
157163 const nextOption = this . availableOptions [ index + 1 ]
158164 this . setActiveOption ( nextOption )
165+ return true
159166 }
160167
161- focusPreviousOption ( ) {
162- const index = this . availableOptions . indexOf ( this . focusedOption )
163- if ( index == 0 ) return
168+ activatePreviousOption ( ) {
169+ const index = this . availableOptions . indexOf ( this . activeOption )
170+ if ( index == 0 ) return false
164171
165172 const nextOption = this . availableOptions [ index - 1 ]
166173 this . setActiveOption ( nextOption )
174+ return true
175+ }
176+
177+ ensureActiveOption ( option ) {
178+ if ( this . activateNextOption ( option ) ) return
179+ if ( this . activatePreviousOption ( option ) ) return
180+
181+ this . clearActiveOption ( )
167182 }
168183
169184 setActiveOption ( option ) {
170- this . clearOptionFocus ( )
185+ this . clearActiveOption ( )
171186 this . setHeight ( option )
172- option . classList . add ( 'focused ' )
187+ option . classList . add ( 'active ' )
173188 }
174189
175- resetOptionFocus ( ) {
176- this . clearOptionFocus ( )
190+ resetActiveOption ( ) {
191+ this . clearActiveOption ( )
177192
178- const firstOption = this . availableOptions [ 0 ]
179- if ( firstOption ) {
180- this . setActiveOption ( firstOption )
193+ const firstSelectableOption = this . availableOptions . filter ( ( option ) => ! option . hidden ) [ 0 ]
194+ if ( firstSelectableOption ) {
195+ this . setActiveOption ( firstSelectableOption )
181196 }
182197 }
183198
184- clearOptionFocus ( ) {
185- this . removeFocus ( this . focusedOption )
199+ clearActiveOption ( ) {
200+ this . removeActiveOption ( this . activeOption )
186201 }
187- removeFocus ( option ) {
188- option ?. classList . remove ( 'focused' )
202+
203+ removeActiveOption ( option ) {
204+ option ?. classList . remove ( 'active' )
189205 }
190206
191207 setHeight ( option ) {
@@ -201,8 +217,8 @@ export default class TailoredSelect extends LitElement {
201217 }
202218 }
203219
204- get focusedOption ( ) {
205- return this . availableOptions . find ( ( opt ) => opt . classList . contains ( 'focused ' ) )
220+ get activeOption ( ) {
221+ return this . availableOptions . find ( ( opt ) => opt . classList . contains ( 'active ' ) )
206222 }
207223
208224 // handleChange(event) {
@@ -236,7 +252,10 @@ export default class TailoredSelect extends LitElement {
236252 }
237253
238254 toggleOption ( option ) {
239- if ( ! option . selected ) this . focusNextOption ( option )
255+ if ( ! option . selected ) {
256+ // Only performed when toggling on
257+ this . ensureActiveOption ( option )
258+ }
240259
241260 option . selected = ! option . selected
242261 this . assignOptionSlot ( option )
@@ -260,7 +279,7 @@ export default class TailoredSelect extends LitElement {
260279 }
261280
262281 updateNoResultsMessage ( ) {
263- const noResults = this . availableOptions . every ( ( opt ) => opt . hidden )
282+ const noResults = this . availableOptions . every ( ( option ) => option . hidden )
264283 this . noResultsMessage . classList . toggle ( 'active' , noResults )
265284 }
266285
@@ -474,7 +493,7 @@ export default class TailoredSelect extends LitElement {
474493 cursor : pointer;
475494 }
476495
477- ::slotted (option.focused ) {
496+ ::slotted (option.active ) {
478497 background-color : var (--option-background-color-hover );
479498 color : var (--option-text-color-hover );
480499 }
0 commit comments