mirror of
https://github.com/henrywhitaker3/Speedtest-Tracker.git
synced 2025-12-26 07:13:35 +01:00
537 lines
16 KiB
JavaScript
Vendored
537 lines
16 KiB
JavaScript
Vendored
"use strict";
|
|
|
|
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 _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
|
|
|
|
var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));
|
|
|
|
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 = _interopRequireDefault(require("react"));
|
|
|
|
var _reactDom = _interopRequireDefault(require("react-dom"));
|
|
|
|
var _ModalManager = _interopRequireDefault(require("./ModalManager"));
|
|
|
|
var _ownerDocument = _interopRequireDefault(require("./utils/ownerDocument"));
|
|
|
|
var _useWaitForDOMRef = _interopRequireDefault(require("./utils/useWaitForDOMRef"));
|
|
|
|
/* eslint-disable react/prop-types */
|
|
function omitProps(props, propTypes) {
|
|
var keys = Object.keys(props);
|
|
var newProps = {};
|
|
keys.forEach(function (prop) {
|
|
if (!Object.prototype.hasOwnProperty.call(propTypes, prop)) {
|
|
newProps[prop] = props[prop];
|
|
}
|
|
});
|
|
return newProps;
|
|
}
|
|
|
|
var manager;
|
|
/**
|
|
* Love them or hate them, `<Modal />` provides a solid foundation for creating dialogs, lightboxes, or whatever else.
|
|
* The Modal component renders its `children` node in front of a backdrop component.
|
|
*
|
|
* The Modal offers a few helpful features over using just a `<Portal/>` component and some styles:
|
|
*
|
|
* - Manages dialog stacking when one-at-a-time just isn't enough.
|
|
* - Creates a backdrop, for disabling interaction below the modal.
|
|
* - It properly manages focus; moving to the modal content, and keeping it there until the modal is closed.
|
|
* - It disables scrolling of the page content while open.
|
|
* - Adds the appropriate ARIA roles are automatically.
|
|
* - Easily pluggable animations via a `<Transition/>` component.
|
|
*
|
|
* Note that, in the same way the backdrop element prevents users from clicking or interacting
|
|
* with the page content underneath the Modal, Screen readers also need to be signaled to not to
|
|
* interact with page content while the Modal is open. To do this, we use a common technique of applying
|
|
* the `aria-hidden='true'` attribute to the non-Modal elements in the Modal `container`. This means that for
|
|
* a Modal to be truly modal, it should have a `container` that is _outside_ your app's
|
|
* React hierarchy (such as the default: document.body).
|
|
*/
|
|
|
|
var Modal = /*#__PURE__*/function (_React$Component) {
|
|
(0, _inheritsLoose2["default"])(Modal, _React$Component);
|
|
|
|
function Modal() {
|
|
var _this;
|
|
|
|
for (var _len = arguments.length, _args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
_args[_key] = arguments[_key];
|
|
}
|
|
|
|
_this = _React$Component.call.apply(_React$Component, [this].concat(_args)) || this;
|
|
_this.state = {
|
|
exited: !_this.props.show
|
|
};
|
|
|
|
_this.onShow = function () {
|
|
var _this$props = _this.props,
|
|
container = _this$props.container,
|
|
containerClassName = _this$props.containerClassName,
|
|
onShow = _this$props.onShow;
|
|
|
|
_this.getModalManager().add((0, _assertThisInitialized2["default"])(_this), container, containerClassName);
|
|
|
|
_this.removeKeydownListener = (0, _listen["default"])(document, 'keydown', _this.handleDocumentKeyDown);
|
|
_this.removeFocusListener = (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(_this.enforceFocus);
|
|
}, true);
|
|
|
|
if (onShow) {
|
|
onShow();
|
|
} // autofocus after onShow, to not trigger a focus event for previous
|
|
// modals before this one is shown.
|
|
|
|
|
|
_this.autoFocus();
|
|
};
|
|
|
|
_this.onHide = function () {
|
|
_this.getModalManager().remove((0, _assertThisInitialized2["default"])(_this));
|
|
|
|
_this.removeKeydownListener();
|
|
|
|
_this.removeFocusListener();
|
|
|
|
if (_this.props.restoreFocus) {
|
|
_this.restoreLastFocus();
|
|
}
|
|
};
|
|
|
|
_this.setDialogRef = function (ref) {
|
|
_this.dialog = ref;
|
|
};
|
|
|
|
_this.setBackdropRef = function (ref) {
|
|
_this.backdrop = ref && _reactDom["default"].findDOMNode(ref);
|
|
};
|
|
|
|
_this.handleHidden = function () {
|
|
_this.setState({
|
|
exited: true
|
|
});
|
|
|
|
_this.onHide();
|
|
|
|
if (_this.props.onExited) {
|
|
var _this$props2;
|
|
|
|
(_this$props2 = _this.props).onExited.apply(_this$props2, arguments);
|
|
}
|
|
};
|
|
|
|
_this.handleBackdropClick = function (e) {
|
|
if (e.target !== e.currentTarget) {
|
|
return;
|
|
}
|
|
|
|
if (_this.props.onBackdropClick) {
|
|
_this.props.onBackdropClick(e);
|
|
}
|
|
|
|
if (_this.props.backdrop === true) {
|
|
_this.props.onHide();
|
|
}
|
|
};
|
|
|
|
_this.handleDocumentKeyDown = function (e) {
|
|
if (_this.props.keyboard && e.keyCode === 27 && _this.isTopModal()) {
|
|
if (_this.props.onEscapeKeyDown) {
|
|
_this.props.onEscapeKeyDown(e);
|
|
}
|
|
|
|
_this.props.onHide();
|
|
}
|
|
};
|
|
|
|
_this.enforceFocus = function () {
|
|
if (!_this.props.enforceFocus || !_this._isMounted || !_this.isTopModal()) {
|
|
return;
|
|
}
|
|
|
|
var currentActiveElement = (0, _activeElement["default"])((0, _ownerDocument["default"])((0, _assertThisInitialized2["default"])(_this)));
|
|
|
|
if (_this.dialog && !(0, _contains["default"])(_this.dialog, currentActiveElement)) {
|
|
_this.dialog.focus();
|
|
}
|
|
};
|
|
|
|
_this.renderBackdrop = function () {
|
|
var _this$props3 = _this.props,
|
|
renderBackdrop = _this$props3.renderBackdrop,
|
|
Transition = _this$props3.backdropTransition;
|
|
var backdrop = renderBackdrop({
|
|
ref: _this.setBackdropRef,
|
|
onClick: _this.handleBackdropClick
|
|
});
|
|
|
|
if (Transition) {
|
|
backdrop = _react["default"].createElement(Transition, {
|
|
appear: true,
|
|
"in": _this.props.show
|
|
}, backdrop);
|
|
}
|
|
|
|
return backdrop;
|
|
};
|
|
|
|
return _this;
|
|
}
|
|
|
|
Modal.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps) {
|
|
if (nextProps.show) {
|
|
return {
|
|
exited: false
|
|
};
|
|
}
|
|
|
|
if (!nextProps.transition) {
|
|
// Otherwise let handleHidden take care of marking exited.
|
|
return {
|
|
exited: true
|
|
};
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
var _proto = Modal.prototype;
|
|
|
|
_proto.componentDidMount = function componentDidMount() {
|
|
this._isMounted = true;
|
|
|
|
if (this.props.show) {
|
|
this.onShow();
|
|
}
|
|
};
|
|
|
|
_proto.componentDidUpdate = function componentDidUpdate(prevProps) {
|
|
var transition = this.props.transition;
|
|
|
|
if (prevProps.show && !this.props.show && !transition) {
|
|
// Otherwise handleHidden will call this.
|
|
this.onHide();
|
|
} else if (!prevProps.show && this.props.show) {
|
|
this.onShow();
|
|
}
|
|
};
|
|
|
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
|
var _this$props4 = this.props,
|
|
show = _this$props4.show,
|
|
transition = _this$props4.transition;
|
|
this._isMounted = false;
|
|
|
|
if (show || transition && !this.state.exited) {
|
|
this.onHide();
|
|
}
|
|
};
|
|
|
|
_proto.getSnapshotBeforeUpdate = function getSnapshotBeforeUpdate(prevProps) {
|
|
if (_canUseDOM["default"] && !prevProps.show && this.props.show) {
|
|
this.lastFocus = (0, _activeElement["default"])();
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
_proto.getModalManager = function getModalManager() {
|
|
if (this.props.manager) {
|
|
return this.props.manager;
|
|
}
|
|
|
|
if (!manager) {
|
|
manager = new _ModalManager["default"]();
|
|
}
|
|
|
|
return manager;
|
|
};
|
|
|
|
_proto.restoreLastFocus = function restoreLastFocus() {
|
|
// Support: <=IE11 doesn't support `focus()` on svg elements (RB: #917)
|
|
if (this.lastFocus && this.lastFocus.focus) {
|
|
this.lastFocus.focus(this.props.restoreFocusOptions);
|
|
this.lastFocus = null;
|
|
}
|
|
};
|
|
|
|
_proto.autoFocus = function autoFocus() {
|
|
if (!this.props.autoFocus) return;
|
|
var currentActiveElement = (0, _activeElement["default"])((0, _ownerDocument["default"])(this));
|
|
|
|
if (this.dialog && !(0, _contains["default"])(this.dialog, currentActiveElement)) {
|
|
this.lastFocus = currentActiveElement;
|
|
this.dialog.focus();
|
|
}
|
|
};
|
|
|
|
_proto.isTopModal = function isTopModal() {
|
|
return this.getModalManager().isTopModal(this);
|
|
};
|
|
|
|
_proto.render = function render() {
|
|
var _this$props5 = this.props,
|
|
show = _this$props5.show,
|
|
container = _this$props5.container,
|
|
children = _this$props5.children,
|
|
renderDialog = _this$props5.renderDialog,
|
|
_this$props5$role = _this$props5.role,
|
|
role = _this$props5$role === void 0 ? 'dialog' : _this$props5$role,
|
|
Transition = _this$props5.transition,
|
|
backdrop = _this$props5.backdrop,
|
|
className = _this$props5.className,
|
|
style = _this$props5.style,
|
|
onExit = _this$props5.onExit,
|
|
onExiting = _this$props5.onExiting,
|
|
onEnter = _this$props5.onEnter,
|
|
onEntering = _this$props5.onEntering,
|
|
onEntered = _this$props5.onEntered,
|
|
props = (0, _objectWithoutPropertiesLoose2["default"])(_this$props5, ["show", "container", "children", "renderDialog", "role", "transition", "backdrop", "className", "style", "onExit", "onExiting", "onEnter", "onEntering", "onEntered"]);
|
|
|
|
if (!(show || Transition && !this.state.exited)) {
|
|
return null;
|
|
}
|
|
|
|
var dialogProps = (0, _extends2["default"])({
|
|
role: role,
|
|
ref: this.setDialogRef,
|
|
// apparently only works on the dialog role element
|
|
'aria-modal': role === 'dialog' ? true : undefined
|
|
}, omitProps(props, Modal.propTypes), {
|
|
style: style,
|
|
className: className,
|
|
tabIndex: '-1'
|
|
});
|
|
var dialog = renderDialog ? renderDialog(dialogProps) : _react["default"].createElement("div", dialogProps, _react["default"].cloneElement(children, {
|
|
role: 'document'
|
|
}));
|
|
|
|
if (Transition) {
|
|
dialog = _react["default"].createElement(Transition, {
|
|
appear: true,
|
|
unmountOnExit: true,
|
|
"in": show,
|
|
onExit: onExit,
|
|
onExiting: onExiting,
|
|
onExited: this.handleHidden,
|
|
onEnter: onEnter,
|
|
onEntering: onEntering,
|
|
onEntered: onEntered
|
|
}, dialog);
|
|
}
|
|
|
|
return _reactDom["default"].createPortal(_react["default"].createElement(_react["default"].Fragment, null, backdrop && this.renderBackdrop(), dialog), container);
|
|
};
|
|
|
|
return Modal;
|
|
}(_react["default"].Component); // dumb HOC for the sake react-docgen
|
|
|
|
|
|
Modal.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
|
|
* 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.
|
|
*/
|
|
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"].object
|
|
};
|
|
Modal.defaultProps = {
|
|
show: false,
|
|
role: 'dialog',
|
|
backdrop: true,
|
|
keyboard: true,
|
|
autoFocus: true,
|
|
enforceFocus: true,
|
|
restoreFocus: true,
|
|
onHide: function onHide() {},
|
|
renderBackdrop: function renderBackdrop(props) {
|
|
return _react["default"].createElement("div", props);
|
|
}
|
|
};
|
|
|
|
function forwardRef(Component) {
|
|
// eslint-disable-next-line react/display-name
|
|
var ModalWithContainer = _react["default"].forwardRef(function (props, ref) {
|
|
var resolved = (0, _useWaitForDOMRef["default"])(props.container);
|
|
return resolved ? _react["default"].createElement(Component, (0, _extends2["default"])({}, props, {
|
|
ref: ref,
|
|
container: resolved
|
|
})) : null;
|
|
});
|
|
|
|
ModalWithContainer.Manager = _ModalManager["default"];
|
|
ModalWithContainer._Inner = Component;
|
|
return ModalWithContainer;
|
|
}
|
|
|
|
var ModalWithContainer = forwardRef(Modal);
|
|
ModalWithContainer.Manager = _ModalManager["default"];
|
|
var _default = ModalWithContainer;
|
|
exports["default"] = _default;
|
|
module.exports = exports.default; |