2
2
import React , { useState , useRef , createRef , useEffect , useMemo } from 'react' ;
3
3
4
4
// Create interface for button properties
5
- interface ButtonProps
5
+ interface ButtonProps < ButtonElement extends HTMLElement >
6
6
extends Pick <
7
- React . DetailedHTMLProps < React . ButtonHTMLAttributes < HTMLButtonElement > , HTMLButtonElement > ,
7
+ React . DetailedHTMLProps < React . ButtonHTMLAttributes < ButtonElement > , ButtonElement > ,
8
8
'onKeyDown' | 'onClick' | 'tabIndex' | 'role' | 'aria-haspopup' | 'aria-expanded'
9
9
> {
10
- ref : React . RefObject < HTMLButtonElement > ;
10
+ ref : React . RefObject < ButtonElement > ;
11
11
}
12
12
13
13
// A custom Hook that abstracts away the listeners/controls for dropdown menus
14
14
export interface DropdownMenuOptions {
15
15
disableFocusFirstItemOnClick ?: boolean ;
16
16
}
17
17
18
- interface DropdownMenuResponse {
19
- readonly buttonProps : ButtonProps ;
18
+ interface DropdownMenuResponse < ButtonElement extends HTMLElement > {
19
+ readonly buttonProps : ButtonProps < ButtonElement > ;
20
20
readonly itemProps : {
21
21
onKeyDown : ( e : React . KeyboardEvent < HTMLAnchorElement > ) => void ;
22
22
tabIndex : number ;
@@ -28,15 +28,18 @@ interface DropdownMenuResponse {
28
28
readonly moveFocus : ( itemIndex : number ) => void ;
29
29
}
30
30
31
- export default function useDropdownMenu ( itemCount : number , options ?: DropdownMenuOptions ) : DropdownMenuResponse {
31
+ export default function useDropdownMenu < ButtonElement extends HTMLElement = HTMLButtonElement > (
32
+ itemCount : number ,
33
+ options ?: DropdownMenuOptions
34
+ ) : DropdownMenuResponse < ButtonElement > {
32
35
// Use state
33
36
const [ isOpen , setIsOpen ] = useState < boolean > ( false ) ;
34
37
const currentFocusIndex = useRef < number | null > ( null ) ;
35
38
const firstRun = useRef ( true ) ;
36
39
const clickedOpen = useRef ( false ) ;
37
40
38
41
// Create refs
39
- const buttonRef = useRef < HTMLButtonElement > ( null ) ;
42
+ const buttonRef = useRef < ButtonElement > ( null ) ;
40
43
const itemRefs = useMemo < React . RefObject < HTMLAnchorElement > [ ] > (
41
44
( ) => Array . from ( { length : itemCount } , ( ) => createRef < HTMLAnchorElement > ( ) ) ,
42
45
[ itemCount ]
@@ -216,7 +219,7 @@ export default function useDropdownMenu(itemCount: number, options?: DropdownMen
216
219
} ;
217
220
218
221
// Define spreadable props for button and items
219
- const buttonProps : ButtonProps = {
222
+ const buttonProps : ButtonProps < ButtonElement > = {
220
223
onKeyDown : buttonListener ,
221
224
onClick : buttonListener ,
222
225
tabIndex : 0 ,
0 commit comments