You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

98 lines
3.7 KiB

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