4
4
Slot ,
5
5
useContext ,
6
6
useSignal ,
7
- useVisibleTask$ ,
8
7
} from '@builder.io/qwik' ;
9
8
import SelectContextId from './select-context-id' ;
10
9
@@ -17,120 +16,116 @@ export const SelectListBox = component$((props: SelectListBoxProps) => {
17
16
const fullStrgSearchFailedSignal = useSignal ( false ) ;
18
17
const context = useContext ( SelectContextId ) ;
19
18
20
- useVisibleTask$ ( function setKeyHandler ( { cleanup } ) {
21
- function keyHandler ( e : KeyboardEvent ) {
22
- const availableOptions = context . optionsStore . filter (
23
- ( option ) => ! ( option ?. getAttribute ( 'aria-disabled' ) === 'true' ) ,
24
- ) ;
25
- const target = e . target as HTMLElement ;
26
- const currentIndex = availableOptions . indexOf ( target ) ;
19
+ return (
20
+ < ul
21
+ ref = { context . listboxRef }
22
+ role = "listbox"
23
+ tabIndex = { 0 }
24
+ hidden = { ! context . isListboxHiddenSig . value }
25
+ style = { `
26
+ display: ${ context . isOpenSig . value ? 'block' : 'none' } ;
27
+ position: absolute;
28
+ z-index: 1;
29
+ ${ props . style }
30
+ ` }
31
+ class = { props . class }
32
+ onKeyDown$ = { ( e ) => {
33
+ console . log ( e . key ) ;
34
+ console . log ( 'do i run on server???' ) ;
27
35
28
- if (
29
- e . key === 'ArrowDown' ||
30
- e . key === 'ArrowUp' ||
31
- e . key === 'Home' ||
32
- e . key === 'End' ||
33
- e . key === ' '
34
- ) {
35
- e . preventDefault ( ) ;
36
- }
36
+ const availableOptions = context . optionsStore . filter (
37
+ ( option ) => ! ( option ?. getAttribute ( 'aria-disabled' ) === 'true' ) ,
38
+ ) ;
39
+ const target = e . target as HTMLElement ;
40
+ const currentIndex = availableOptions . indexOf ( target ) ;
37
41
38
- if ( e . key === 'ArrowDown' ) {
39
- if ( currentIndex === availableOptions . length - 1 ) {
40
- availableOptions [ 0 ] ?. focus ( ) ;
41
- } else {
42
- availableOptions [ currentIndex + 1 ] ?. focus ( ) ;
42
+ if (
43
+ e . key === 'ArrowDown' ||
44
+ e . key === 'ArrowUp' ||
45
+ e . key === 'Home' ||
46
+ e . key === 'End' ||
47
+ e . key === ' '
48
+ ) {
49
+ e . preventDefault ( ) ;
43
50
}
44
- }
45
51
46
- if ( e . key === 'ArrowUp' ) {
47
- if ( currentIndex <= 0 ) {
48
- availableOptions [ availableOptions . length - 1 ] ?. focus ( ) ;
49
- } else {
50
- availableOptions [ currentIndex - 1 ] ?. focus ( ) ;
52
+ if ( e . key === 'ArrowDown' ) {
53
+ if ( currentIndex === availableOptions . length - 1 ) {
54
+ availableOptions [ 0 ] ?. focus ( ) ;
55
+ } else {
56
+ availableOptions [ currentIndex + 1 ] ?. focus ( ) ;
57
+ }
58
+ }
59
+
60
+ if ( e . key === 'ArrowUp' ) {
61
+ if ( currentIndex <= 0 ) {
62
+ availableOptions [ availableOptions . length - 1 ] ?. focus ( ) ;
63
+ } else {
64
+ availableOptions [ currentIndex - 1 ] ?. focus ( ) ;
65
+ }
51
66
}
52
- }
53
67
54
- clearTimeout ( prevTimeoutSignal . value ) ;
68
+ clearTimeout ( prevTimeoutSignal . value ) ;
55
69
56
- prevTimeoutSignal . value = setTimeout ( ( ) => {
57
- inputStrgSignal . value = '' ;
58
- } , 500 ) ;
70
+ prevTimeoutSignal . value = setTimeout ( ( ) => {
71
+ inputStrgSignal . value = '' ;
72
+ } , 500 ) ;
59
73
60
- const searchFirstCharOnly =
61
- inputStrgSignal . value . length < 1 || fullStrgSearchFailedSignal . value ;
62
- if ( searchFirstCharOnly ) {
63
- const charOptions : Readonly < string [ ] > = availableOptions . map ( ( e ) => {
64
- return e . textContent ! . slice ( 0 , 1 ) . toLowerCase ( ) ;
65
- } ) ;
66
- const currentChar = e . key . toLowerCase ( ) ;
67
- if ( ! fullStrgSearchFailedSignal . value ) {
68
- inputStrgSignal . value += currentChar ;
69
- }
70
- const charIndex = charOptions . indexOf ( currentChar ) ;
71
- if ( charIndex !== - 1 ) {
72
- if ( indexDiffSignal . value === undefined ) {
73
- availableOptions [ charIndex ] . focus ( ) ;
74
- indexDiffSignal . value = charIndex + 1 ;
75
- } else {
76
- const isRepeat = charOptions [ indexDiffSignal . value - 1 ] === currentChar ;
77
- if ( isRepeat ) {
78
- const nextChars = charOptions . slice ( indexDiffSignal . value ) ;
79
- const repeatIndex = nextChars . indexOf ( currentChar ) ;
80
- if ( repeatIndex !== - 1 ) {
81
- const nextIndex = repeatIndex + indexDiffSignal . value ;
82
- availableOptions [ nextIndex ] . focus ( ) ;
83
- indexDiffSignal . value = nextIndex + 1 ;
74
+ const searchFirstCharOnly =
75
+ inputStrgSignal . value . length < 1 || fullStrgSearchFailedSignal . value ;
76
+ if ( searchFirstCharOnly ) {
77
+ const charOptions : Readonly < string [ ] > = availableOptions . map ( ( e ) => {
78
+ return e . textContent ! . slice ( 0 , 1 ) . toLowerCase ( ) ;
79
+ } ) ;
80
+ const currentChar = e . key . toLowerCase ( ) ;
81
+ if ( ! fullStrgSearchFailedSignal . value ) {
82
+ inputStrgSignal . value += currentChar ;
83
+ }
84
+ const charIndex = charOptions . indexOf ( currentChar ) ;
85
+ if ( charIndex !== - 1 ) {
86
+ if ( indexDiffSignal . value === undefined ) {
87
+ availableOptions [ charIndex ] . focus ( ) ;
88
+ indexDiffSignal . value = charIndex + 1 ;
89
+ } else {
90
+ const isRepeat = charOptions [ indexDiffSignal . value - 1 ] === currentChar ;
91
+ if ( isRepeat ) {
92
+ const nextChars = charOptions . slice ( indexDiffSignal . value ) ;
93
+ const repeatIndex = nextChars . indexOf ( currentChar ) ;
94
+ if ( repeatIndex !== - 1 ) {
95
+ const nextIndex = repeatIndex + indexDiffSignal . value ;
96
+ availableOptions [ nextIndex ] . focus ( ) ;
97
+ indexDiffSignal . value = nextIndex + 1 ;
98
+ } else {
99
+ availableOptions [ charIndex ] . focus ( ) ;
100
+ indexDiffSignal . value = charIndex + 1 ;
101
+ }
84
102
} else {
85
103
availableOptions [ charIndex ] . focus ( ) ;
104
+ // bc char has changed, user is typing a new strg
105
+ fullStrgSearchFailedSignal . value = false ;
86
106
indexDiffSignal . value = charIndex + 1 ;
87
107
}
88
- } else {
89
- availableOptions [ charIndex ] . focus ( ) ;
90
- // bc char has changed, user is typing a new strg
91
- fullStrgSearchFailedSignal . value = false ;
92
- indexDiffSignal . value = charIndex + 1 ;
93
108
}
94
109
}
95
- }
96
- } else {
97
- const strgOptions : Readonly < string [ ] > = availableOptions . map ( ( e ) => {
98
- return e . textContent ! . toLowerCase ( ) ;
99
- } ) ;
100
- const searchStrg = inputStrgSignal . value + e . key . toLowerCase ( ) ;
101
- const firstPossibleOptIndex = strgOptions . findIndex ( ( e ) => {
102
- const size = searchStrg . length ;
103
- return e . substring ( 0 , size ) === searchStrg ;
104
- } ) ;
105
- if ( firstPossibleOptIndex !== - 1 ) {
106
- availableOptions [ firstPossibleOptIndex ] . focus ( ) ;
107
- inputStrgSignal . value = searchStrg ;
108
- indexDiffSignal . value = firstPossibleOptIndex + 1 ;
109
110
} else {
110
- clearTimeout ( prevTimeoutSignal . value ) ;
111
- fullStrgSearchFailedSignal . value = true ;
111
+ const strgOptions : Readonly < string [ ] > = availableOptions . map ( ( e ) => {
112
+ return e . textContent ! . toLowerCase ( ) ;
113
+ } ) ;
114
+ const searchStrg = inputStrgSignal . value + e . key . toLowerCase ( ) ;
115
+ const firstPossibleOptIndex = strgOptions . findIndex ( ( e ) => {
116
+ const size = searchStrg . length ;
117
+ return e . substring ( 0 , size ) === searchStrg ;
118
+ } ) ;
119
+ if ( firstPossibleOptIndex !== - 1 ) {
120
+ availableOptions [ firstPossibleOptIndex ] . focus ( ) ;
121
+ inputStrgSignal . value = searchStrg ;
122
+ indexDiffSignal . value = firstPossibleOptIndex + 1 ;
123
+ } else {
124
+ clearTimeout ( prevTimeoutSignal . value ) ;
125
+ fullStrgSearchFailedSignal . value = true ;
126
+ }
112
127
}
113
- }
114
- }
115
- context . listboxRef . value ?. addEventListener ( 'keydown' , keyHandler ) ;
116
- cleanup ( ( ) => {
117
- context . listboxRef . value ?. removeEventListener ( 'keydown' , keyHandler ) ;
118
- } ) ;
119
- } ) ;
120
-
121
- return (
122
- < ul
123
- ref = { context . listboxRef }
124
- role = "listbox"
125
- tabIndex = { 0 }
126
- hidden = { ! context . isListboxHiddenSig . value }
127
- style = { `
128
- display: ${ context . isOpenSig . value ? 'block' : 'none' } ;
129
- position: absolute;
130
- z-index: 1;
131
- ${ props . style }
132
- ` }
133
- class = { props . class }
128
+ } }
134
129
>
135
130
< Slot />
136
131
</ ul >
0 commit comments