@@ -42,7 +42,12 @@ import {
42
42
DEFAULT_VALID_MESSAGE ,
43
43
DEFAULT_VALID_MESSAGE_ID_SUFFIX
44
44
} from '../../shared/constants' ;
45
- import { ChangeEvent , ClickEvent } from '../../shared/model' ;
45
+ import {
46
+ ClickEvent ,
47
+ GeneralEvent ,
48
+ InputEvent ,
49
+ InteractionEvent
50
+ } from '../../shared/model' ;
46
51
import DBCustomSelectList from '../custom-select-list/custom-select-list.lite' ;
47
52
import DBCustomSelectListItem from '../custom-select-list-item/custom-select-list-item.lite' ;
48
53
import DBCustomSelectDropdown from '../custom-select-dropdown/custom-select-dropdown.lite' ;
@@ -157,12 +162,15 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
157
162
state . _validity = props . validation ?? 'no-validation' ;
158
163
}
159
164
} ,
160
- handleDropdownToggle : ( event : any ) => {
165
+ handleDropdownToggle : ( event : GeneralEvent < HTMLDetailsElement > ) => {
161
166
if ( props . onDropdownToggle ) {
162
167
event . stopPropagation ( ) ;
163
168
props . onDropdownToggle ( event ) ;
164
169
}
165
- if ( event . target . open ) {
170
+ if (
171
+ event . target instanceof HTMLDetailsElement &&
172
+ event . target . open
173
+ ) {
166
174
state . _documentClickListenerCallbackId =
167
175
new DocumentClickListener ( ) . addCallback ( ( event ) =>
168
176
state . handleDocumentClose ( event )
@@ -175,7 +183,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
175
183
176
184
state . handleAutoPlacement ( ) ;
177
185
state . _observer ?. observe ( detailsRef ) ;
178
- if ( ! event . target . dataset . test ) {
186
+ if ( ! event . target . dataset [ ' test' ] ) {
179
187
// We need this workaround for snapshot testing
180
188
state . handleOpenByKeyboardFocus ( ) ;
181
189
}
@@ -239,8 +247,14 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
239
247
} `;
240
248
}
241
249
} ,
242
- handleTagRemove : ( option : CustomSelectOptionType , event : any ) => {
243
- event . stopPropagation ( ) ;
250
+ handleTagRemove : (
251
+ option : CustomSelectOptionType ,
252
+ event ?: ClickEvent < HTMLButtonElement > | void
253
+ ) => {
254
+ if ( event ) {
255
+ event . stopPropagation ( ) ;
256
+ }
257
+
244
258
state . handleSelect ( option . value ) ;
245
259
state . handleSummaryFocus ( ) ;
246
260
} ,
@@ -328,7 +342,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
328
342
( event . key === 'ArrowUp' ||
329
343
event . key === 'ArrowLeft' )
330
344
) {
331
- state . handleClose ( 'close' ) ;
345
+ state . handleClose ( undefined , true ) ;
332
346
state . handleSummaryFocus ( ) ;
333
347
} else {
334
348
// 3. Otherwise, we need to move to the first checkbox
@@ -357,7 +371,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
357
371
handleKeyboardPress : ( event : any ) => {
358
372
event . stopPropagation ( ) ;
359
373
if ( event . key === 'Escape' && detailsRef ?. open ) {
360
- state . handleClose ( 'close' ) ;
374
+ state . handleClose ( undefined , true ) ;
361
375
state . handleSummaryFocus ( ) ;
362
376
} else if (
363
377
event . key === 'ArrowDown' ||
@@ -368,17 +382,23 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
368
382
state . handleArrowDownUp ( event ) ;
369
383
}
370
384
} ,
371
- handleClose : ( event : any ) => {
385
+ handleClose : (
386
+ event ?: InteractionEvent < HTMLDetailsElement > | void ,
387
+ forceClose ?: boolean
388
+ ) => {
372
389
if ( detailsRef ) {
373
- if ( event === 'close' ) {
390
+ if ( forceClose ) {
374
391
detailsRef . open = false ;
375
392
state . handleSummaryFocus ( ) ;
376
- } else if ( detailsRef . open && event ?. relatedTarget ) {
377
- const relatedTarget = event . relatedTarget as HTMLElement ;
378
- if ( ! detailsRef . contains ( relatedTarget ) ) {
379
- // We need to use delay here because the combination of `contains`
380
- // and changing the DOM element causes a race condition inside browser
381
- delay ( ( ) => ( detailsRef . open = false ) , 1 ) ;
393
+ } else if ( detailsRef . open && event ) {
394
+ if ( event . relatedTarget ) {
395
+ const relatedTarget =
396
+ event . relatedTarget as HTMLElement ;
397
+ if ( ! detailsRef . contains ( relatedTarget ) ) {
398
+ // We need to use delay here because the combination of `contains`
399
+ // and changing the DOM element causes a race condition inside browser
400
+ delay ( ( ) => ( detailsRef . open = false ) , 1 ) ;
401
+ }
382
402
}
383
403
}
384
404
}
@@ -444,7 +464,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
444
464
}
445
465
} else {
446
466
state . handleOptionSelected ( [ value ] ) ;
447
- state . handleClose ( 'close' ) ;
467
+ state . handleClose ( undefined , true ) ;
448
468
}
449
469
}
450
470
} ,
@@ -515,12 +535,19 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
515
535
}
516
536
} ,
517
537
// Don't trigger onOptionSelected event
518
- handleSearch : ( event : any ) => {
538
+ handleSearch : (
539
+ valueOrEvent ?: InputEvent < HTMLInputElement > | string | void
540
+ ) => {
541
+ if ( valueOrEvent === undefined ) {
542
+ return ;
543
+ }
544
+
519
545
let filterText ;
520
546
521
- if ( typeof event === 'string' ) {
522
- filterText = event ;
547
+ if ( typeof valueOrEvent === 'string' ) {
548
+ filterText = valueOrEvent ;
523
549
} else {
550
+ const event = valueOrEvent as InputEvent < HTMLInputElement > ;
524
551
event . stopPropagation ( ) ;
525
552
526
553
if ( props . onSearch ) {
@@ -596,8 +623,10 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
596
623
597
624
onUpdate ( ( ) => {
598
625
if ( detailsRef ) {
599
- detailsRef . addEventListener ( 'focusout' , ( event : any ) =>
600
- state . handleClose ( event )
626
+ detailsRef . addEventListener (
627
+ 'focusout' ,
628
+ ( event : InteractionEvent < HTMLDetailsElement > ) =>
629
+ state . handleClose ( event )
601
630
) ;
602
631
}
603
632
} , [ detailsRef ] ) ;
@@ -833,7 +862,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
833
862
ref = { detailsRef }
834
863
open = { props . open }
835
864
/* @ts -expect-error details as an event named onToggle */
836
- onToggle = { ( event : any ) => state . handleDropdownToggle ( event ) }
865
+ onToggle = { ( event ) => state . handleDropdownToggle ( event ) }
837
866
onKeyDown = { ( event ) => state . handleKeyboardPress ( event ) } >
838
867
{ props . children }
839
868
< Show when = { props . options } >
@@ -872,7 +901,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
872
901
index
873
902
) }
874
903
onRemove = { (
875
- event : ClickEvent < HTMLButtonElement >
904
+ event ? : ClickEvent < HTMLButtonElement > | void
876
905
) =>
877
906
state . handleTagRemove (
878
907
option ,
@@ -909,7 +938,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
909
938
: undefined
910
939
}
911
940
onInput = { (
912
- event : ChangeEvent < HTMLInputElement >
941
+ event : InputEvent < HTMLInputElement >
913
942
) => state . handleSearch ( event ) }
914
943
/>
915
944
</ div >
@@ -1028,7 +1057,9 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
1028
1057
size = "small"
1029
1058
name = { state . _id }
1030
1059
form = { state . _id }
1031
- onClick = { ( ) => state . handleClose ( 'close' ) } >
1060
+ onClick = { ( ) =>
1061
+ state . handleClose ( undefined , true )
1062
+ } >
1032
1063
{ props . mobileCloseButtonText ??
1033
1064
DEFAULT_CLOSE_BUTTON }
1034
1065
</ DBButton >
0 commit comments