@@ -9,45 +9,63 @@ interface UseDetectMouseDownOutsideProps<Element extends HTMLElement> {
99 elementRef : React . RefObject < Element > ;
1010
1111 /**
12- * The callback to be invoked when a click
13- * has been detected outside
12+ * The callback to be invoked when a mouse down
13+ * has been detected outside the element
1414 */
1515 onMouseDown : ( ) => void ;
16+
17+ enabled ?: boolean ;
1618}
1719
1820/**
19- * Detects a click that has occurred outside of the specified element.
21+ * Detects a mouse down event that has occurred outside of the specified element.
22+ *
23+ * Note that the term "_outside_" refers to the DOM structure and not the
24+ * position that the element is displayed on screen. Any clicks on the specified
25+ * element of any of its children (or it's childrens childrens, recursively)
26+ * is considered _inside_. Everything else is considered _outside_
2027 */
2128function useDetectMouseDownOutside < Element extends HTMLElement > ( {
2229 elementRef,
2330 onMouseDown,
31+ enabled = true ,
2432} : UseDetectMouseDownOutsideProps < Element > ) {
2533 useEffect ( ( ) => {
26- function handler ( e : MouseEvent ) {
27- // TODO: Fix this - doesnt work for fixed/absolute positioned items.
28- // Instead of checking if it's inside/outside the rect,
29- // we'll probs have to recursively check all children to see
30- // if the child element is equal to the event target. If so,
31- // the click is within, otherwise it's outside.
32- const bounds = elementRef . current ?. getBoundingClientRect ( ) ;
33- if ( e . clientX < ( bounds ?. left ?? 0 ) ) {
34- return onMouseDown ( ) ;
34+ if ( ! enabled ) return ;
35+ function handler ( event : MouseEvent ) {
36+ if ( ! elementRef . current || elementRef . current === event . target ) {
37+ return ;
3538 }
36- if ( e . clientX > ( bounds ?. left ?? 0 ) + ( bounds ?. width ?? 0 ) ) {
37- return onMouseDown ( ) ;
39+
40+ console . log ( elementRef . current ) ;
41+
42+ let call = true ;
43+ function process ( children : HTMLCollection ) {
44+ for ( const child of children ) {
45+ if ( child === event . target ) {
46+ call = false ;
47+ return ;
48+ }
49+
50+ if ( child . children ) {
51+ process ( child . children ) ;
52+ }
53+ }
3854 }
39- if ( e . clientY < ( bounds ?. top ?? 0 ) ) {
40- return onMouseDown ( ) ;
55+
56+ if ( elementRef . current . children ) {
57+ process ( elementRef . current . children ) ;
4158 }
42- if ( e . clientY > ( bounds ?. top ?? 0 ) + ( bounds ?. height ?? 0 ) ) {
43- return onMouseDown ( ) ;
59+
60+ if ( call ) {
61+ onMouseDown ( ) ;
4462 }
4563 }
4664
4765 window . addEventListener ( "mousedown" , handler ) ;
4866
4967 return ( ) => window . removeEventListener ( "mousedown" , handler ) ;
50- } ) ;
68+ } , [ elementRef , enabled , onMouseDown ] ) ;
5169}
5270
5371export default useDetectMouseDownOutside ;
0 commit comments