Commit 6e83459 1 parent 3fb7de9 commit 6e83459 Copy full SHA for 6e83459
File tree 5 files changed +91
-0
lines changed
5 files changed +91
-0
lines changed Original file line number Diff line number Diff line change @@ -69,3 +69,4 @@ export * from './utils/useFileInput/useFileInput';
69
69
export { useActionHandlers } from './utils/useActionHandlers' ;
70
70
export { useUniqId } from './utils/useUniqId' ;
71
71
export { getLayersCount } from './utils/LayerManager' ;
72
+ export * from './utils/useOutsideClick' ;
Original file line number Diff line number Diff line change
1
+ /* eslint-disable jsx-a11y/click-events-have-key-events */
2
+ import React from 'react' ;
3
+
4
+ import { useOutsideClick } from '../useOutsideClick' ;
5
+
6
+ export const Demo = ( ) => {
7
+ const observerRef = React . useRef ( null ) ;
8
+ const [ status , setStatus ] = React . useState < 1 | 0 > ( 0 ) ;
9
+
10
+ const handleOutsideClick = ( ) => {
11
+ setStatus ( 0 ) ;
12
+ } ;
13
+
14
+ const handleClick = ( ) => {
15
+ setStatus ( 1 ) ;
16
+ } ;
17
+
18
+ useOutsideClick ( {
19
+ ref : observerRef ,
20
+ handler : handleOutsideClick ,
21
+ } ) ;
22
+
23
+ return (
24
+ < div >
25
+ < h1 > { status } </ h1 >
26
+ < div ref = { observerRef } onClick = { handleClick } >
27
+ { 'Target' }
28
+ </ div >
29
+ < div > { 'Outside' } </ div >
30
+ </ div >
31
+ ) ;
32
+ } ;
Original file line number Diff line number Diff line change
1
+ import React from 'react' ;
2
+
3
+ import { render , screen } from '@testing-library/react' ;
4
+ import userEvent from '@testing-library/user-event' ;
5
+
6
+ import { Demo } from './Demo' ;
7
+
8
+ test ( 'Check useOutsideClick correct work' , async ( ) => {
9
+ render ( < Demo /> ) ;
10
+
11
+ expect ( screen . getByRole ( 'heading' ) ) . toHaveTextContent ( '0' ) ;
12
+
13
+ await userEvent . click ( screen . getByText ( 'Target' ) ) ;
14
+
15
+ expect ( screen . getByRole ( 'heading' ) ) . toHaveTextContent ( '1' ) ;
16
+
17
+ await userEvent . click ( screen . getByText ( 'Outside' ) ) ;
18
+
19
+ expect ( screen . getByRole ( 'heading' ) ) . toHaveTextContent ( '0' ) ;
20
+ } ) ;
Original file line number Diff line number Diff line change
1
+ export { useOutsideClick } from './useOutsideClick' ;
2
+ export type { UseOutsideClickProps } from './useOutsideClick' ;
Original file line number Diff line number Diff line change
1
+ import React from 'react' ;
2
+
3
+ export interface UseOutsideClickProps < T > {
4
+ ref : React . RefObject < T > ;
5
+ handler ?: ( ) => void ;
6
+ }
7
+
8
+ type UseOutsideClickType = < K extends HTMLElement > ( props : UseOutsideClickProps < K > ) => void ;
9
+
10
+ /**
11
+ * Hook for observing clicks outside a given target
12
+ *
13
+ * @param ref - purpose of observation
14
+ * @param handler - callback when a click is triggered outside the observation target
15
+ *
16
+ * @return - nothing
17
+ */
18
+ export const useOutsideClick : UseOutsideClickType = ( { ref, handler} ) => {
19
+ React . useEffect ( ( ) => {
20
+ const callback = ( e : MouseEvent | TouchEvent ) => {
21
+ const elem = ref ?. current ;
22
+
23
+ if ( elem && ! elem . contains ( e . target as Node ) && handler ) {
24
+ handler ( ) ;
25
+ }
26
+ } ;
27
+
28
+ window . addEventListener ( 'mouseup' , callback , { capture : true } ) ;
29
+ window . addEventListener ( 'touchend' , callback , { capture : true } ) ;
30
+
31
+ return ( ) => {
32
+ window . removeEventListener ( 'mouseup' , callback , { capture : true } ) ;
33
+ window . removeEventListener ( 'touchend' , callback , { capture : true } ) ;
34
+ } ;
35
+ } , [ handler , ref ] ) ;
36
+ } ;
You can’t perform that action at this time.
0 commit comments