Mirror of https://github.com/roostorg/coop github.com/roostorg/coop
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 54 lines 2.1 kB view raw
1import { useEffect, useRef } from 'react'; 2 3/** 4 * This hook can be used to capture clicks outside of a component. 5 * For example, use this in a dropdown component to capture clicks 6 * outside of the dropdown to close it. 7 * @param onClick - the callback that gets called when a user clicks 8 * outside the component in which this hook is used. 9 * 10 * Implementation details: https://www.robinwieruch.de/react-hook-detect-click-outside-component/ 11 */ 12export function useOutsideClick(onClick: (_: MouseEvent) => void) { 13 const ref = useRef() as React.MutableRefObject<HTMLInputElement>; 14 15 useEffect(() => { 16 const handleClick = (event: MouseEvent) => { 17 /** 18 * Some ant design components have subcomponents that aren't 19 * actually child components. They set separately in the component 20 * tree and are positioned absolutely, not relatively. These components 21 * are treated as part of the rest of the DOM, i.e. 'outside' the 22 * component referenced by the ref param. 23 * One example: the dropdown menu component in ant design's <Select /> 24 * component is not a child of the <Select /> component. So clicking an 25 * item in the dropdown would normally trigger the onClick() function 26 * here, as if it were outside the dropdown component altogether, 27 * and we don't want that. So we have a few hardcoded ant design component 28 * class names that we exempt from ever being considered 'outside' a 29 * component that would use this hook. 30 */ 31 const prohibitedClassNames = [ 32 'ant-select-item-option-content', 33 'ant-picker-cell-inner', 34 ]; 35 36 if ( 37 ref.current && 38 event.target instanceof HTMLElement && 39 !ref.current.contains(event.target) && 40 !prohibitedClassNames.includes(event.target.className) 41 ) { 42 onClick(event); 43 } 44 }; 45 46 document.addEventListener('click', handleClick, true); 47 48 return () => { 49 document.removeEventListener('click', handleClick, true); 50 }; 51 }, [ref, onClick]); 52 53 return ref; 54}