react-block-ui
Version:
Block UI for react
367 lines (317 loc) • 11.1 kB
JavaScript
import React, { Component } from 'react';
function Loader() {
return React.createElement(
"div",
{ className: "loading-indicator" },
React.createElement(
"span",
{ className: "loading-bullet" },
"\u2022"
),
' ',
React.createElement(
"span",
{ className: "loading-bullet" },
"\u2022"
),
' ',
React.createElement(
"span",
{ className: "loading-bullet" },
"\u2022"
)
);
}
// https://gist.github.com/Alex1990/046a6553dc83e22dd6f4
/**
* Get the current active element safely.
* Ref: https://github.com/jquery/jquery-ui/blob/2b84531ae9331f60e4d739fabca6d78abde89ae1/ui/safe-active-element.js
*/
function safeActiveElement(doc) {
doc = doc || document;
var activeElement = void 0;
try {
activeElement = document.activeElement;
if (!activeElement || !activeElement.nodeName) {
activeElement = doc.body;
}
} catch (error) {
activeElement = doc.body;
}
return activeElement;
}
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var objectWithoutProperties = function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var defaultProps = {
tag: 'div',
renderChildren: true,
loader: Loader
};
var BlockUi$1 = function (_Component) {
inherits(BlockUi, _Component);
function BlockUi(props) {
classCallCheck(this, BlockUi);
var _this = possibleConstructorReturn(this, (BlockUi.__proto__ || Object.getPrototypeOf(BlockUi)).call(this, props));
_this.tabbedUpTop = _this.tabbedUpTop.bind(_this);
_this.tabbedDownTop = _this.tabbedDownTop.bind(_this);
_this.tabbedUpBottom = _this.tabbedUpBottom.bind(_this);
_this.tabbedDownBottom = _this.tabbedDownBottom.bind(_this);
_this.setHelper = _this.setRef.bind(_this, 'helper');
_this.setBlocker = _this.setRef.bind(_this, 'blocker');
_this.setTopFocus = _this.setRef.bind(_this, 'topFocus');
_this.setContainer = _this.setRef.bind(_this, 'container');
_this.setMessageContainer = _this.setRef.bind(_this, 'messageContainer');
_this.handleScroll = _this.handleScroll.bind(_this);
_this.state = { top: '50%' };
return _this;
}
createClass(BlockUi, [{
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var _this2 = this;
if (nextProps.blocking !== this.props.blocking) {
if (nextProps.blocking) {
// blocking started
if (this.helper && this.helper.parentNode && this.helper.parentNode.contains && this.helper.parentNode.contains(safeActiveElement())) {
this.focused = safeActiveElement();
// https://www.tjvantoll.com/2013/08/30/bugs-with-document-activeelement-in-internet-explorer/#blurring-the-body-switches-windows-in-ie9-and-ie10
if (this.focused && this.focused !== document.body) {
(window.setImmediate || setTimeout)(function () {
return _this2.focused && typeof _this2.focused.blur === 'function' && _this2.focused.blur();
});
}
}
} else {
this.detachListeners();
var ae = safeActiveElement();
if (this.focused && (!ae || ae === document.body || ae === this.topFocus)) {
if (typeof this.focused.focus === 'function') {
this.focused.focus();
}
this.focused = null;
}
}
}
if (nextProps.keepInView && (nextProps.keepInView !== this.props.keepInView || nextProps.blocking && nextProps.blocking !== this.props.blocking)) {
this.attachListeners();
this.keepInView(nextProps);
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.detachListeners();
}
}, {
key: 'setRef',
value: function setRef(name, ref) {
this[name] = ref;
if (ref && name === 'container') {
this.keepInView();
}
}
}, {
key: 'attachListeners',
value: function attachListeners() {
window.addEventListener('scroll', this.handleScroll);
}
}, {
key: 'detachListeners',
value: function detachListeners() {
window.removeEventListener('scroll', this.handleScroll);
}
}, {
key: 'blockingTab',
value: function blockingTab(e) {
var withShift = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
// eslint-disable-next-line eqeqeq
return this.props.blocking && (e.key === 'Tab' || e.keyCode === 9) && e.shiftKey == withShift;
}
}, {
key: 'tabbedUpTop',
value: function tabbedUpTop(e) {
if (this.blockingTab(e)) {
this.blocker.focus();
}
}
}, {
key: 'tabbedDownTop',
value: function tabbedDownTop(e) {
if (this.blockingTab(e)) {
e.preventDefault();
this.blocker.focus();
}
}
}, {
key: 'tabbedUpBottom',
value: function tabbedUpBottom(e) {
if (this.blockingTab(e, true)) {
this.topFocus.focus();
}
}
}, {
key: 'tabbedDownBottom',
value: function tabbedDownBottom(e) {
if (this.blockingTab(e, true)) {
e.preventDefault();
this.topFocus.focus();
}
}
}, {
key: 'keepInView',
value: function keepInView() {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;
if (props.blocking && props.keepInView && this.container) {
var containerBounds = this.container.getBoundingClientRect();
var windowHeight = window.innerHeight;
if (containerBounds.top > windowHeight || containerBounds.bottom < 0) return;
if (containerBounds.top >= 0 && containerBounds.bottom <= windowHeight) {
if (this.state.top !== '50%') {
this.setState({ top: '50%' });
}
return;
}
var messageBoundsHeight = this.messageContainer ? this.messageContainer.getBoundingClientRect().height : 0;
var top = Math.max(Math.min(windowHeight, containerBounds.bottom) - Math.max(containerBounds.top, 0), messageBoundsHeight) / 2;
if (containerBounds.top < 0) {
top = Math.min(top - containerBounds.top, containerBounds.height - messageBoundsHeight / 2);
}
if (this.state.top !== top) {
this.setState({ top: top });
}
}
}
}, {
key: 'handleScroll',
value: function handleScroll() {
this.keepInView();
}
}, {
key: 'render',
value: function render() {
var _props = this.props,
Tag = _props.tag,
blocking = _props.blocking,
className = _props.className,
children = _props.children,
message = _props.message,
Loader$$1 = _props.loader,
renderChildren = _props.renderChildren,
keepInView = _props.keepInView,
_props$ariaLabel = _props.ariaLabel,
ariaLabel = _props$ariaLabel === undefined ? 'loading' : _props$ariaLabel,
attributes = objectWithoutProperties(_props, ['tag', 'blocking', 'className', 'children', 'message', 'loader', 'renderChildren', 'keepInView', 'ariaLabel']);
var classes = blocking ? 'block-ui ' + className : className;
var renderChilds = !blocking || renderChildren;
return React.createElement(
Tag,
_extends({}, attributes, { className: classes, 'aria-busy': blocking }),
blocking && React.createElement(
'div',
{ tabIndex: '0', onKeyUp: this.tabbedUpTop, onKeyDown: this.tabbedDownTop, ref: this.setTopFocus },
React.createElement(
'div',
{ className: 'sr-only' },
message || ariaLabel
)
),
renderChilds && children,
blocking && React.createElement(
'div',
{ className: 'block-ui-container',
tabIndex: '0',
ref: this.setBlocker,
onKeyUp: this.tabbedUpBottom,
onKeyDown: this.tabbedDownBottom
},
React.createElement('div', { className: 'block-ui-overlay', ref: this.setContainer }),
React.createElement(
'div',
{ className: 'block-ui-message-container',
ref: this.setMessageContainer,
style: { top: keepInView ? this.state.top : undefined }
},
React.createElement(
'div',
{ className: 'block-ui-message' },
message || React.createElement(
'span',
{ className: 'sr-only' },
ariaLabel
),
React.createElement(
'div',
{ 'aria-hidden': true },
React.isValidElement(Loader$$1) ? Loader$$1 : React.createElement(Loader$$1, null)
)
)
)
),
React.createElement('span', { ref: this.setHelper })
);
}
}]);
return BlockUi;
}(Component);
BlockUi$1.defaultProps = defaultProps;
export default BlockUi$1;
//# sourceMappingURL=reactblockui.es.js.map