1
+ // src/features/docs/doc-tree/hooks/useDropdownKeyboardNav.ts
2
+ import { DropdownMenuOption } from '@gouvfr-lasuite/ui-kit' ;
1
3
import { RefObject , useEffect } from 'react' ;
2
4
3
- import { DropdownMenuOption } from '../DropdownMenu ' ;
5
+ import { useKeyboardActivation } from './useKeyboardActivation ' ;
4
6
5
7
type UseDropdownKeyboardNavProps = {
6
8
isOpen : boolean ;
@@ -19,64 +21,65 @@ export const useDropdownKeyboardNav = ({
19
21
setFocusedIndex,
20
22
onOpenChange,
21
23
} : UseDropdownKeyboardNavProps ) => {
24
+ useKeyboardActivation ( [ 'Enter' , ' ' ] , isOpen , ( ) => {
25
+ if ( focusedIndex === - 1 ) {
26
+ return ;
27
+ }
28
+
29
+ const enabledIndices = options
30
+ . map ( ( opt , i ) => ( opt . show !== false && ! opt . disabled ? i : - 1 ) )
31
+ . filter ( ( i ) => i !== - 1 ) ;
32
+
33
+ const selectedOpt = options [ enabledIndices [ focusedIndex ] ] ;
34
+ if ( selectedOpt ?. callback ) {
35
+ onOpenChange ( false ) ;
36
+ void selectedOpt . callback ( ) ;
37
+ }
38
+ } ) ;
39
+
22
40
useEffect ( ( ) => {
23
41
const handleKeyDown = ( event : KeyboardEvent ) => {
24
42
if ( ! isOpen ) {
25
43
return ;
26
44
}
27
45
28
46
const enabledIndices = options
29
- . map ( ( option , index ) =>
30
- option . show !== false && ! option . disabled ? index : - 1 ,
31
- )
32
- . filter ( ( index ) => index !== - 1 ) ;
47
+ . map ( ( opt , i ) => ( opt . show !== false && ! opt . disabled ? i : - 1 ) )
48
+ . filter ( ( i ) => i !== - 1 ) ;
33
49
34
50
switch ( event . key ) {
35
- case 'ArrowDown' :
51
+ case 'ArrowDown' : {
36
52
event . preventDefault ( ) ;
37
53
const nextIndex =
38
54
focusedIndex < enabledIndices . length - 1 ? focusedIndex + 1 : 0 ;
39
- const nextEnabledIndex = enabledIndices [ nextIndex ] ;
55
+ const nextEnabled = enabledIndices [ nextIndex ] ;
40
56
setFocusedIndex ( nextIndex ) ;
41
- menuItemRefs . current [ nextEnabledIndex ] ?. focus ( ) ;
57
+ menuItemRefs . current [ nextEnabled ] ?. focus ( ) ;
42
58
break ;
59
+ }
43
60
44
- case 'ArrowUp' :
61
+ case 'ArrowUp' : {
45
62
event . preventDefault ( ) ;
46
63
const prevIndex =
47
64
focusedIndex > 0 ? focusedIndex - 1 : enabledIndices . length - 1 ;
48
- const prevEnabledIndex = enabledIndices [ prevIndex ] ;
65
+ const prevEnabled = enabledIndices [ prevIndex ] ;
49
66
setFocusedIndex ( prevIndex ) ;
50
- menuItemRefs . current [ prevEnabledIndex ] ?. focus ( ) ;
67
+ menuItemRefs . current [ prevEnabled ] ?. focus ( ) ;
51
68
break ;
69
+ }
52
70
53
- case 'Enter' :
54
- case ' ' :
55
- event . preventDefault ( ) ;
56
- if ( focusedIndex >= 0 && focusedIndex < enabledIndices . length ) {
57
- const selectedOptionIndex = enabledIndices [ focusedIndex ] ;
58
- const selectedOption = options [ selectedOptionIndex ] ;
59
- if ( selectedOption && selectedOption . callback ) {
60
- onOpenChange ( false ) ;
61
- void selectedOption . callback ( ) ;
62
- }
63
- }
64
- break ;
65
-
66
- case 'Escape' :
71
+ case 'Escape' : {
67
72
event . preventDefault ( ) ;
68
73
onOpenChange ( false ) ;
69
74
break ;
75
+ }
70
76
}
71
77
} ;
72
78
73
79
if ( isOpen ) {
74
80
document . addEventListener ( 'keydown' , handleKeyDown ) ;
75
81
}
76
-
77
- return ( ) => {
78
- document . removeEventListener ( 'keydown' , handleKeyDown ) ;
79
- } ;
82
+ return ( ) => document . removeEventListener ( 'keydown' , handleKeyDown ) ;
80
83
} , [
81
84
isOpen ,
82
85
focusedIndex ,
0 commit comments