Advertisement
Guest User

Untitled

a guest
Jul 21st, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.15 KB | None | 0 0
  1. import React from "react";
  2.  
  3. export default function useClickOutside(onClickOutside, exempt = []) {
  4. const container = React.useRef(null);
  5. const mouseDownTargetIsOutside = React.useRef(false);
  6.  
  7. React.useEffect(() => {
  8. /* if the click event doesnt start outside of the element then we want to ignore it */
  9. /* imagine if someone clicked while swiping the cursor, if it started inside, then they probably */
  10. /* wouldn't expect mouseup to fire like it was outside */
  11. function onMouseDown(event) {
  12. /* If the target is inside, then don't fire click outside handler */
  13. if (container.current && container.current.contains(event.target)) {
  14. mouseDownTargetIsOutside.current = false;
  15. return;
  16. }
  17.  
  18. mouseDownTargetIsOutside.current = true;
  19. }
  20.  
  21. function onMouseUp(event) {
  22. /* If both targets weren't outside then we can bail early */
  23. const mouseUpTargetIsOutside =
  24. !container.current || !container.current.contains(event.target);
  25. if (!mouseDownTargetIsOutside.current || !mouseUpTargetIsOutside) {
  26. return;
  27. }
  28.  
  29. /* exempt is an array of strings (css selectors) or html elements */
  30. /* Here we figure out if the target matches either, or is nested inside an exempt element */
  31. const targetIsExempt = exempt.some(selectorOrElement => {
  32. if (typeof selectorOrElement === "string") {
  33. return Boolean(event.target.closest(selectorOrElement));
  34. } else if (
  35. selectorOrElement instanceof HTMLElement ||
  36. selectorOrElement.current instanceof HTMLElement
  37. ) {
  38. const element = selectorOrElement.current || selectorOrElement;
  39. return event.target === element || element.contains(event.target);
  40. }
  41.  
  42. return false;
  43. });
  44.  
  45. if (targetIsExempt) {
  46. return;
  47. }
  48.  
  49. onClickOutside(event, container);
  50. }
  51.  
  52. window.addEventListener("mousedown", onMouseDown, true);
  53. window.addEventListener("mouseup", onMouseUp, true);
  54.  
  55. return () => {
  56. window.removeEventListener("mousedown", onMouseDown, true);
  57. window.removeEventListener("mouseup", onMouseUp, true);
  58. };
  59. });
  60.  
  61. return container;
  62. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement