Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

83 строки
3.2 KiB

  1. import contains from 'dom-helpers/contains';
  2. import listen from 'dom-helpers/listen';
  3. import { useCallback, useEffect, useRef } from 'react';
  4. import useEventCallback from '@restart/hooks/useEventCallback';
  5. import warning from 'warning';
  6. import ownerDocument from './utils/ownerDocument';
  7. var escapeKeyCode = 27;
  8. var noop = function noop() {};
  9. function isLeftClickEvent(event) {
  10. return event.button === 0;
  11. }
  12. function isModifiedEvent(event) {
  13. return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
  14. }
  15. /**
  16. * The `useRootClose` hook registers your callback on the document
  17. * when rendered. Powers the `<Overlay/>` component. This is used achieve modal
  18. * style behavior where your callback is triggered when the user tries to
  19. * interact with the rest of the document or hits the `esc` key.
  20. *
  21. * @param {Ref<HTMLElement>|HTMLElement} ref The element boundary
  22. * @param {function} onRootClose
  23. * @param {object} options
  24. * @param {boolean} options.disabled
  25. * @param {string} options.clickTrigger The DOM event name (click, mousedown, etc) to attach listeners on
  26. */
  27. function useRootClose(ref, onRootClose, _temp) {
  28. var _ref = _temp === void 0 ? {} : _temp,
  29. disabled = _ref.disabled,
  30. _ref$clickTrigger = _ref.clickTrigger,
  31. clickTrigger = _ref$clickTrigger === void 0 ? 'click' : _ref$clickTrigger;
  32. var preventMouseRootCloseRef = useRef(false);
  33. var onClose = onRootClose || noop;
  34. var handleMouseCapture = useCallback(function (e) {
  35. var currentTarget = ref && ('current' in ref ? ref.current : ref);
  36. warning(!!currentTarget, 'RootClose captured a close event but does not have a ref to compare it to. ' + 'useRootClose(), should be passed a ref that resolves to a DOM node');
  37. preventMouseRootCloseRef.current = !currentTarget || isModifiedEvent(e) || !isLeftClickEvent(e) || contains(currentTarget, e.target);
  38. }, [ref]);
  39. var handleMouse = useEventCallback(function (e) {
  40. if (!preventMouseRootCloseRef.current) {
  41. onClose(e);
  42. }
  43. });
  44. var handleKeyUp = useEventCallback(function (e) {
  45. if (e.keyCode === escapeKeyCode) {
  46. onClose(e);
  47. }
  48. });
  49. useEffect(function () {
  50. if (disabled || ref == null) return undefined;
  51. var doc = ownerDocument(ref.current); // Use capture for this listener so it fires before React's listener, to
  52. // avoid false positives in the contains() check below if the target DOM
  53. // element is removed in the React mouse callback.
  54. var removeMouseCaptureListener = listen(doc, clickTrigger, handleMouseCapture, true);
  55. var removeMouseListener = listen(doc, clickTrigger, handleMouse);
  56. var removeKeyupListener = listen(doc, 'keyup', handleKeyUp);
  57. var mobileSafariHackListeners = [];
  58. if ('ontouchstart' in doc.documentElement) {
  59. mobileSafariHackListeners = [].slice.call(doc.body.children).map(function (el) {
  60. return listen(el, 'mousemove', noop);
  61. });
  62. }
  63. return function () {
  64. removeMouseCaptureListener();
  65. removeMouseListener();
  66. removeKeyupListener();
  67. mobileSafariHackListeners.forEach(function (remove) {
  68. return remove();
  69. });
  70. };
  71. }, [ref, disabled, clickTrigger, handleMouseCapture, handleMouse, handleKeyUp]);
  72. }
  73. export default useRootClose;