mirror of
https://github.com/idanoo/GoScrobble.git
synced 2024-11-23 00:45:16 +00:00
105 lines
3.8 KiB
JavaScript
105 lines
3.8 KiB
JavaScript
|
import contains from 'dom-helpers/contains';
|
||
|
import listen from 'dom-helpers/listen';
|
||
|
import { useCallback, useEffect, useRef } from 'react';
|
||
|
import useEventCallback from '@restart/hooks/useEventCallback';
|
||
|
import warning from 'warning';
|
||
|
import ownerDocument from './ownerDocument';
|
||
|
var escapeKeyCode = 27;
|
||
|
|
||
|
var noop = function noop() {};
|
||
|
|
||
|
function isLeftClickEvent(event) {
|
||
|
return event.button === 0;
|
||
|
}
|
||
|
|
||
|
function isModifiedEvent(event) {
|
||
|
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
|
||
|
}
|
||
|
|
||
|
var getRefTarget = function getRefTarget(ref) {
|
||
|
return ref && ('current' in ref ? ref.current : ref);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The `useRootClose` hook registers your callback on the document
|
||
|
* when rendered. Powers the `<Overlay/>` component. This is used achieve modal
|
||
|
* style behavior where your callback is triggered when the user tries to
|
||
|
* interact with the rest of the document or hits the `esc` key.
|
||
|
*
|
||
|
* @param {Ref<HTMLElement>| HTMLElement} ref The element boundary
|
||
|
* @param {function} onRootClose
|
||
|
* @param {object=} options
|
||
|
* @param {boolean=} options.disabled
|
||
|
* @param {string=} options.clickTrigger The DOM event name (click, mousedown, etc) to attach listeners on
|
||
|
*/
|
||
|
function useRootClose(ref, onRootClose, _temp) {
|
||
|
var _ref = _temp === void 0 ? {} : _temp,
|
||
|
disabled = _ref.disabled,
|
||
|
_ref$clickTrigger = _ref.clickTrigger,
|
||
|
clickTrigger = _ref$clickTrigger === void 0 ? 'click' : _ref$clickTrigger;
|
||
|
|
||
|
var preventMouseRootCloseRef = useRef(false);
|
||
|
var onClose = onRootClose || noop;
|
||
|
var handleMouseCapture = useCallback(function (e) {
|
||
|
var currentTarget = getRefTarget(ref);
|
||
|
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');
|
||
|
preventMouseRootCloseRef.current = !currentTarget || isModifiedEvent(e) || !isLeftClickEvent(e) || !!contains(currentTarget, e.target);
|
||
|
}, [ref]);
|
||
|
var handleMouse = useEventCallback(function (e) {
|
||
|
if (!preventMouseRootCloseRef.current) {
|
||
|
onClose(e);
|
||
|
}
|
||
|
});
|
||
|
var handleKeyUp = useEventCallback(function (e) {
|
||
|
if (e.keyCode === escapeKeyCode) {
|
||
|
onClose(e);
|
||
|
}
|
||
|
});
|
||
|
useEffect(function () {
|
||
|
if (disabled || ref == null) return undefined; // Store the current event to avoid triggering handlers immediately
|
||
|
// https://github.com/facebook/react/issues/20074
|
||
|
|
||
|
var currentEvent = window.event;
|
||
|
var doc = ownerDocument(getRefTarget(ref)); // Use capture for this listener so it fires before React's listener, to
|
||
|
// avoid false positives in the contains() check below if the target DOM
|
||
|
// element is removed in the React mouse callback.
|
||
|
|
||
|
var removeMouseCaptureListener = listen(doc, clickTrigger, handleMouseCapture, true);
|
||
|
var removeMouseListener = listen(doc, clickTrigger, function (e) {
|
||
|
// skip if this event is the same as the one running when we added the handlers
|
||
|
if (e === currentEvent) {
|
||
|
currentEvent = undefined;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
handleMouse(e);
|
||
|
});
|
||
|
var removeKeyupListener = listen(doc, 'keyup', function (e) {
|
||
|
// skip if this event is the same as the one running when we added the handlers
|
||
|
if (e === currentEvent) {
|
||
|
currentEvent = undefined;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
handleKeyUp(e);
|
||
|
});
|
||
|
var mobileSafariHackListeners = [];
|
||
|
|
||
|
if ('ontouchstart' in doc.documentElement) {
|
||
|
mobileSafariHackListeners = [].slice.call(doc.body.children).map(function (el) {
|
||
|
return listen(el, 'mousemove', noop);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return function () {
|
||
|
removeMouseCaptureListener();
|
||
|
removeMouseListener();
|
||
|
removeKeyupListener();
|
||
|
mobileSafariHackListeners.forEach(function (remove) {
|
||
|
return remove();
|
||
|
});
|
||
|
};
|
||
|
}, [ref, disabled, clickTrigger, handleMouseCapture, handleMouse, handleKeyUp]);
|
||
|
}
|
||
|
|
||
|
export default useRootClose;
|