1
- import React , { useEffect , useRef , FunctionComponent } from 'react' ;
1
+ import React , {
2
+ useRef ,
3
+ useEffect ,
4
+ MutableRefObject ,
5
+ FunctionComponent
6
+ } from 'react' ;
2
7
3
8
type MouseEvents = 'click' | 'mousedown' | 'mouseup' ;
4
9
type TouchEvents = 'touchstart' | 'touchend' ;
10
+ type Events = MouseEvent | TouchEvent ;
5
11
6
12
interface Props extends React . HTMLAttributes < HTMLElement > {
7
- onClickAway : ( event : MouseEvent | TouchEvent ) => void ;
13
+ onClickAway : ( event : Events ) => void ;
8
14
mouseEvent ?: MouseEvents ;
9
15
touchEvent ?: TouchEvents ;
10
16
as ?: React . ElementType ;
@@ -17,11 +23,19 @@ const ClickAwayListener: FunctionComponent<Props> = ({
17
23
touchEvent = 'touchend' ,
18
24
...props
19
25
} ) => {
20
- let node = useRef < HTMLElement > ( null ) ;
26
+ const node = useRef < HTMLElement > ( null ) ;
27
+ const bubbledEvent : MutableRefObject < Events | null > = useRef ( null ) ;
28
+
29
+ const handleBubbledEvents = ( event : Events | null ) => {
30
+ bubbledEvent . current = event ;
31
+ } ;
21
32
22
33
useEffect ( ( ) => {
23
- const handleEvents = ( event : MouseEvent | TouchEvent ) : void => {
24
- if ( node . current && node . current . contains ( event . target as Node ) ) {
34
+ const handleEvents = ( event : Events ) : void => {
35
+ if (
36
+ ( node . current && node . current . contains ( event . target as Node ) ) ||
37
+ ( bubbledEvent . current && bubbledEvent . current . target === event . target )
38
+ ) {
25
39
return ;
26
40
}
27
41
@@ -37,7 +51,12 @@ const ClickAwayListener: FunctionComponent<Props> = ({
37
51
} ;
38
52
} , [ mouseEvent , onClickAway , touchEvent ] ) ;
39
53
40
- return React . createElement ( as , { ref : node , ...props } ) ;
54
+ return React . createElement ( as , {
55
+ ref : node ,
56
+ onClick : handleBubbledEvents ,
57
+ onTouchEnd : handleBubbledEvents ,
58
+ ...props
59
+ } ) ;
41
60
} ;
42
61
43
62
export default ClickAwayListener ;
0 commit comments