mirror of
https://github.com/idanoo/GoScrobble.git
synced 2024-11-26 10:25:14 +00:00
456 lines
15 KiB
JavaScript
456 lines
15 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
|
||
|
|
||
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
|
||
|
exports.__esModule = true;
|
||
|
exports["default"] = void 0;
|
||
|
|
||
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
||
|
|
||
|
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
|
||
|
|
||
|
var _activeElement = _interopRequireDefault(require("dom-helpers/activeElement"));
|
||
|
|
||
|
var _contains = _interopRequireDefault(require("dom-helpers/contains"));
|
||
|
|
||
|
var _canUseDOM = _interopRequireDefault(require("dom-helpers/canUseDOM"));
|
||
|
|
||
|
var _listen = _interopRequireDefault(require("dom-helpers/listen"));
|
||
|
|
||
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
||
|
|
||
|
var _react = _interopRequireWildcard(require("react"));
|
||
|
|
||
|
var _reactDom = _interopRequireDefault(require("react-dom"));
|
||
|
|
||
|
var _useMounted = _interopRequireDefault(require("@restart/hooks/useMounted"));
|
||
|
|
||
|
var _useWillUnmount = _interopRequireDefault(require("@restart/hooks/useWillUnmount"));
|
||
|
|
||
|
var _usePrevious = _interopRequireDefault(require("@restart/hooks/usePrevious"));
|
||
|
|
||
|
var _useEventCallback = _interopRequireDefault(require("@restart/hooks/useEventCallback"));
|
||
|
|
||
|
var _ModalManager = _interopRequireDefault(require("./ModalManager"));
|
||
|
|
||
|
var _useWaitForDOMRef = _interopRequireDefault(require("./useWaitForDOMRef"));
|
||
|
|
||
|
/* eslint-disable @typescript-eslint/no-use-before-define, react/prop-types */
|
||
|
var manager;
|
||
|
|
||
|
function getManager() {
|
||
|
if (!manager) manager = new _ModalManager["default"]();
|
||
|
return manager;
|
||
|
}
|
||
|
|
||
|
function useModalManager(provided) {
|
||
|
var modalManager = provided || getManager();
|
||
|
var modal = (0, _react.useRef)({
|
||
|
dialog: null,
|
||
|
backdrop: null
|
||
|
});
|
||
|
return Object.assign(modal.current, {
|
||
|
add: function add(container, className) {
|
||
|
return modalManager.add(modal.current, container, className);
|
||
|
},
|
||
|
remove: function remove() {
|
||
|
return modalManager.remove(modal.current);
|
||
|
},
|
||
|
isTopModal: function isTopModal() {
|
||
|
return modalManager.isTopModal(modal.current);
|
||
|
},
|
||
|
setDialogRef: (0, _react.useCallback)(function (ref) {
|
||
|
modal.current.dialog = ref;
|
||
|
}, []),
|
||
|
setBackdropRef: (0, _react.useCallback)(function (ref) {
|
||
|
modal.current.backdrop = ref;
|
||
|
}, [])
|
||
|
});
|
||
|
}
|
||
|
|
||
|
var Modal = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
|
||
|
var _ref$show = _ref.show,
|
||
|
show = _ref$show === void 0 ? false : _ref$show,
|
||
|
_ref$role = _ref.role,
|
||
|
role = _ref$role === void 0 ? 'dialog' : _ref$role,
|
||
|
className = _ref.className,
|
||
|
style = _ref.style,
|
||
|
children = _ref.children,
|
||
|
_ref$backdrop = _ref.backdrop,
|
||
|
backdrop = _ref$backdrop === void 0 ? true : _ref$backdrop,
|
||
|
_ref$keyboard = _ref.keyboard,
|
||
|
keyboard = _ref$keyboard === void 0 ? true : _ref$keyboard,
|
||
|
onBackdropClick = _ref.onBackdropClick,
|
||
|
onEscapeKeyDown = _ref.onEscapeKeyDown,
|
||
|
transition = _ref.transition,
|
||
|
backdropTransition = _ref.backdropTransition,
|
||
|
_ref$autoFocus = _ref.autoFocus,
|
||
|
autoFocus = _ref$autoFocus === void 0 ? true : _ref$autoFocus,
|
||
|
_ref$enforceFocus = _ref.enforceFocus,
|
||
|
enforceFocus = _ref$enforceFocus === void 0 ? true : _ref$enforceFocus,
|
||
|
_ref$restoreFocus = _ref.restoreFocus,
|
||
|
restoreFocus = _ref$restoreFocus === void 0 ? true : _ref$restoreFocus,
|
||
|
restoreFocusOptions = _ref.restoreFocusOptions,
|
||
|
renderDialog = _ref.renderDialog,
|
||
|
_ref$renderBackdrop = _ref.renderBackdrop,
|
||
|
renderBackdrop = _ref$renderBackdrop === void 0 ? function (props) {
|
||
|
return /*#__PURE__*/_react["default"].createElement("div", props);
|
||
|
} : _ref$renderBackdrop,
|
||
|
providedManager = _ref.manager,
|
||
|
containerRef = _ref.container,
|
||
|
containerClassName = _ref.containerClassName,
|
||
|
onShow = _ref.onShow,
|
||
|
_ref$onHide = _ref.onHide,
|
||
|
onHide = _ref$onHide === void 0 ? function () {} : _ref$onHide,
|
||
|
onExit = _ref.onExit,
|
||
|
onExited = _ref.onExited,
|
||
|
onExiting = _ref.onExiting,
|
||
|
onEnter = _ref.onEnter,
|
||
|
onEntering = _ref.onEntering,
|
||
|
onEntered = _ref.onEntered,
|
||
|
rest = (0, _objectWithoutPropertiesLoose2["default"])(_ref, ["show", "role", "className", "style", "children", "backdrop", "keyboard", "onBackdropClick", "onEscapeKeyDown", "transition", "backdropTransition", "autoFocus", "enforceFocus", "restoreFocus", "restoreFocusOptions", "renderDialog", "renderBackdrop", "manager", "container", "containerClassName", "onShow", "onHide", "onExit", "onExited", "onExiting", "onEnter", "onEntering", "onEntered"]);
|
||
|
var container = (0, _useWaitForDOMRef["default"])(containerRef);
|
||
|
var modal = useModalManager(providedManager);
|
||
|
var isMounted = (0, _useMounted["default"])();
|
||
|
var prevShow = (0, _usePrevious["default"])(show);
|
||
|
|
||
|
var _useState = (0, _react.useState)(!show),
|
||
|
exited = _useState[0],
|
||
|
setExited = _useState[1];
|
||
|
|
||
|
var lastFocusRef = (0, _react.useRef)(null);
|
||
|
(0, _react.useImperativeHandle)(ref, function () {
|
||
|
return modal;
|
||
|
}, [modal]);
|
||
|
|
||
|
if (_canUseDOM["default"] && !prevShow && show) {
|
||
|
lastFocusRef.current = (0, _activeElement["default"])();
|
||
|
}
|
||
|
|
||
|
if (!transition && !show && !exited) {
|
||
|
setExited(true);
|
||
|
} else if (show && exited) {
|
||
|
setExited(false);
|
||
|
}
|
||
|
|
||
|
var handleShow = (0, _useEventCallback["default"])(function () {
|
||
|
modal.add(container, containerClassName);
|
||
|
removeKeydownListenerRef.current = (0, _listen["default"])(document, 'keydown', handleDocumentKeyDown);
|
||
|
removeFocusListenerRef.current = (0, _listen["default"])(document, 'focus', // the timeout is necessary b/c this will run before the new modal is mounted
|
||
|
// and so steals focus from it
|
||
|
function () {
|
||
|
return setTimeout(handleEnforceFocus);
|
||
|
}, true);
|
||
|
|
||
|
if (onShow) {
|
||
|
onShow();
|
||
|
} // autofocus after onShow to not trigger a focus event for previous
|
||
|
// modals before this one is shown.
|
||
|
|
||
|
|
||
|
if (autoFocus) {
|
||
|
var currentActiveElement = (0, _activeElement["default"])(document);
|
||
|
|
||
|
if (modal.dialog && currentActiveElement && !(0, _contains["default"])(modal.dialog, currentActiveElement)) {
|
||
|
lastFocusRef.current = currentActiveElement;
|
||
|
modal.dialog.focus();
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
var handleHide = (0, _useEventCallback["default"])(function () {
|
||
|
modal.remove();
|
||
|
removeKeydownListenerRef.current == null ? void 0 : removeKeydownListenerRef.current();
|
||
|
removeFocusListenerRef.current == null ? void 0 : removeFocusListenerRef.current();
|
||
|
|
||
|
if (restoreFocus) {
|
||
|
var _lastFocusRef$current;
|
||
|
|
||
|
// Support: <=IE11 doesn't support `focus()` on svg elements (RB: #917)
|
||
|
(_lastFocusRef$current = lastFocusRef.current) == null ? void 0 : _lastFocusRef$current.focus == null ? void 0 : _lastFocusRef$current.focus(restoreFocusOptions);
|
||
|
lastFocusRef.current = null;
|
||
|
}
|
||
|
}); // TODO: try and combine these effects: https://github.com/react-bootstrap/react-overlays/pull/794#discussion_r409954120
|
||
|
// Show logic when:
|
||
|
// - show is `true` _and_ `container` has resolved
|
||
|
|
||
|
(0, _react.useEffect)(function () {
|
||
|
if (!show || !container) return;
|
||
|
handleShow();
|
||
|
}, [show, container,
|
||
|
/* should never change: */
|
||
|
handleShow]); // Hide cleanup logic when:
|
||
|
// - `exited` switches to true
|
||
|
// - component unmounts;
|
||
|
|
||
|
(0, _react.useEffect)(function () {
|
||
|
if (!exited) return;
|
||
|
handleHide();
|
||
|
}, [exited, handleHide]);
|
||
|
(0, _useWillUnmount["default"])(function () {
|
||
|
handleHide();
|
||
|
}); // --------------------------------
|
||
|
|
||
|
var handleEnforceFocus = (0, _useEventCallback["default"])(function () {
|
||
|
if (!enforceFocus || !isMounted() || !modal.isTopModal()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var currentActiveElement = (0, _activeElement["default"])();
|
||
|
|
||
|
if (modal.dialog && currentActiveElement && !(0, _contains["default"])(modal.dialog, currentActiveElement)) {
|
||
|
modal.dialog.focus();
|
||
|
}
|
||
|
});
|
||
|
var handleBackdropClick = (0, _useEventCallback["default"])(function (e) {
|
||
|
if (e.target !== e.currentTarget) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
onBackdropClick == null ? void 0 : onBackdropClick(e);
|
||
|
|
||
|
if (backdrop === true) {
|
||
|
onHide();
|
||
|
}
|
||
|
});
|
||
|
var handleDocumentKeyDown = (0, _useEventCallback["default"])(function (e) {
|
||
|
if (keyboard && e.keyCode === 27 && modal.isTopModal()) {
|
||
|
onEscapeKeyDown == null ? void 0 : onEscapeKeyDown(e);
|
||
|
|
||
|
if (!e.defaultPrevented) {
|
||
|
onHide();
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
var removeFocusListenerRef = (0, _react.useRef)();
|
||
|
var removeKeydownListenerRef = (0, _react.useRef)();
|
||
|
|
||
|
var handleHidden = function handleHidden() {
|
||
|
setExited(true);
|
||
|
|
||
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
||
|
args[_key] = arguments[_key];
|
||
|
}
|
||
|
|
||
|
onExited == null ? void 0 : onExited.apply(void 0, args);
|
||
|
};
|
||
|
|
||
|
var Transition = transition;
|
||
|
|
||
|
if (!container || !(show || Transition && !exited)) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
var dialogProps = (0, _extends2["default"])({
|
||
|
role: role,
|
||
|
ref: modal.setDialogRef,
|
||
|
// apparently only works on the dialog role element
|
||
|
'aria-modal': role === 'dialog' ? true : undefined
|
||
|
}, rest, {
|
||
|
style: style,
|
||
|
className: className,
|
||
|
tabIndex: -1
|
||
|
});
|
||
|
var dialog = renderDialog ? renderDialog(dialogProps) : /*#__PURE__*/_react["default"].createElement("div", dialogProps, /*#__PURE__*/_react["default"].cloneElement(children, {
|
||
|
role: 'document'
|
||
|
}));
|
||
|
|
||
|
if (Transition) {
|
||
|
dialog = /*#__PURE__*/_react["default"].createElement(Transition, {
|
||
|
appear: true,
|
||
|
unmountOnExit: true,
|
||
|
"in": !!show,
|
||
|
onExit: onExit,
|
||
|
onExiting: onExiting,
|
||
|
onExited: handleHidden,
|
||
|
onEnter: onEnter,
|
||
|
onEntering: onEntering,
|
||
|
onEntered: onEntered
|
||
|
}, dialog);
|
||
|
}
|
||
|
|
||
|
var backdropElement = null;
|
||
|
|
||
|
if (backdrop) {
|
||
|
var BackdropTransition = backdropTransition;
|
||
|
backdropElement = renderBackdrop({
|
||
|
ref: modal.setBackdropRef,
|
||
|
onClick: handleBackdropClick
|
||
|
});
|
||
|
|
||
|
if (BackdropTransition) {
|
||
|
backdropElement = /*#__PURE__*/_react["default"].createElement(BackdropTransition, {
|
||
|
appear: true,
|
||
|
"in": !!show
|
||
|
}, backdropElement);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_reactDom["default"].createPortal( /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, backdropElement, dialog), container));
|
||
|
});
|
||
|
var propTypes = {
|
||
|
/**
|
||
|
* Set the visibility of the Modal
|
||
|
*/
|
||
|
show: _propTypes["default"].bool,
|
||
|
|
||
|
/**
|
||
|
* A DOM element, a `ref` to an element, or function that returns either. The Modal is appended to it's `container` element.
|
||
|
*
|
||
|
* For the sake of assistive technologies, the container should usually be the document body, so that the rest of the
|
||
|
* page content can be placed behind a virtual backdrop as well as a visual one.
|
||
|
*/
|
||
|
container: _propTypes["default"].any,
|
||
|
|
||
|
/**
|
||
|
* A callback fired when the Modal is opening.
|
||
|
*/
|
||
|
onShow: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* A callback fired when either the backdrop is clicked, or the escape key is pressed.
|
||
|
*
|
||
|
* The `onHide` callback only signals intent from the Modal,
|
||
|
* you must actually set the `show` prop to `false` for the Modal to close.
|
||
|
*/
|
||
|
onHide: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* Include a backdrop component.
|
||
|
*/
|
||
|
backdrop: _propTypes["default"].oneOfType([_propTypes["default"].bool, _propTypes["default"].oneOf(['static'])]),
|
||
|
|
||
|
/**
|
||
|
* A function that returns the dialog component. Useful for custom
|
||
|
* rendering. **Note:** the component should make sure to apply the provided ref.
|
||
|
*
|
||
|
* ```js static
|
||
|
* renderDialog={props => <MyDialog {...props} />}
|
||
|
* ```
|
||
|
*/
|
||
|
renderDialog: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* A function that returns a backdrop component. Useful for custom
|
||
|
* backdrop rendering.
|
||
|
*
|
||
|
* ```js
|
||
|
* renderBackdrop={props => <MyBackdrop {...props} />}
|
||
|
* ```
|
||
|
*/
|
||
|
renderBackdrop: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* A callback fired when the escape key, if specified in `keyboard`, is pressed.
|
||
|
*
|
||
|
* If preventDefault() is called on the keyboard event, closing the modal will be cancelled.
|
||
|
*/
|
||
|
onEscapeKeyDown: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* A callback fired when the backdrop, if specified, is clicked.
|
||
|
*/
|
||
|
onBackdropClick: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* A css class or set of classes applied to the modal container when the modal is open,
|
||
|
* and removed when it is closed.
|
||
|
*/
|
||
|
containerClassName: _propTypes["default"].string,
|
||
|
|
||
|
/**
|
||
|
* Close the modal when escape key is pressed
|
||
|
*/
|
||
|
keyboard: _propTypes["default"].bool,
|
||
|
|
||
|
/**
|
||
|
* A `react-transition-group@2.0.0` `<Transition/>` component used
|
||
|
* to control animations for the dialog component.
|
||
|
*/
|
||
|
transition: _propTypes["default"].elementType,
|
||
|
|
||
|
/**
|
||
|
* A `react-transition-group@2.0.0` `<Transition/>` component used
|
||
|
* to control animations for the backdrop components.
|
||
|
*/
|
||
|
backdropTransition: _propTypes["default"].elementType,
|
||
|
|
||
|
/**
|
||
|
* When `true` The modal will automatically shift focus to itself when it opens, and
|
||
|
* replace it to the last focused element when it closes. This also
|
||
|
* works correctly with any Modal children that have the `autoFocus` prop.
|
||
|
*
|
||
|
* Generally this should never be set to `false` as it makes the Modal less
|
||
|
* accessible to assistive technologies, like screen readers.
|
||
|
*/
|
||
|
autoFocus: _propTypes["default"].bool,
|
||
|
|
||
|
/**
|
||
|
* When `true` The modal will prevent focus from leaving the Modal while open.
|
||
|
*
|
||
|
* Generally this should never be set to `false` as it makes the Modal less
|
||
|
* accessible to assistive technologies, like screen readers.
|
||
|
*/
|
||
|
enforceFocus: _propTypes["default"].bool,
|
||
|
|
||
|
/**
|
||
|
* When `true` The modal will restore focus to previously focused element once
|
||
|
* modal is hidden
|
||
|
*/
|
||
|
restoreFocus: _propTypes["default"].bool,
|
||
|
|
||
|
/**
|
||
|
* Options passed to focus function when `restoreFocus` is set to `true`
|
||
|
*
|
||
|
* @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#Parameters
|
||
|
*/
|
||
|
restoreFocusOptions: _propTypes["default"].shape({
|
||
|
preventScroll: _propTypes["default"].bool
|
||
|
}),
|
||
|
|
||
|
/**
|
||
|
* Callback fired before the Modal transitions in
|
||
|
*/
|
||
|
onEnter: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* Callback fired as the Modal begins to transition in
|
||
|
*/
|
||
|
onEntering: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* Callback fired after the Modal finishes transitioning in
|
||
|
*/
|
||
|
onEntered: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* Callback fired right before the Modal transitions out
|
||
|
*/
|
||
|
onExit: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* Callback fired as the Modal begins to transition out
|
||
|
*/
|
||
|
onExiting: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* Callback fired after the Modal finishes transitioning out
|
||
|
*/
|
||
|
onExited: _propTypes["default"].func,
|
||
|
|
||
|
/**
|
||
|
* A ModalManager instance used to track and manage the state of open
|
||
|
* Modals. Useful when customizing how modals interact within a container
|
||
|
*/
|
||
|
manager: _propTypes["default"].instanceOf(_ModalManager["default"])
|
||
|
};
|
||
|
Modal.displayName = 'Modal';
|
||
|
Modal.propTypes = propTypes;
|
||
|
|
||
|
var _default = Object.assign(Modal, {
|
||
|
Manager: _ModalManager["default"]
|
||
|
});
|
||
|
|
||
|
exports["default"] = _default;
|
||
|
module.exports = exports.default;
|