react-gosuslugi
Version:
react-gosuslugi collection of common React UI components
368 lines (300 loc) • 13.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
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 _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 _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _classnames = require('classnames');
var _classnames2 = _interopRequireDefault(_classnames);
var _uuid = require('./helpers/uuid');
var _uuid2 = _interopRequireDefault(_uuid);
var _propTypes3 = require('./helpers/propTypes');
var _count = require('./helpers/count');
var _childrenDeepMap = require('./helpers/childrenDeepMap');
var _elementTypes = require('./helpers/elementTypes');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectWithoutProperties(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; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(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; }
function _inherits(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; }
{} /* eslint-disable */
// Determine if a node from event.target is a Tab element
function isTabNode(node) {
return 'getAttribute' in node && node.getAttribute('role') === 'tab';
}
// Determine if a tab node is disabled
function isTabDisabled(node) {
return node.getAttribute('aria-disabled') === 'true';
}
var canUseActiveElement = void 0;
try {
canUseActiveElement = !!(typeof window !== 'undefined' && window.document && window.document.activeElement);
} catch (e) {
// Work around for IE bug when accessing document.activeElement in an iframe
// Refer to the following resources:
// http://stackoverflow.com/a/10982960/369687
// https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12733599
canUseActiveElement = false;
}
var UncontrolledTabs = function (_PureComponent) {
_inherits(UncontrolledTabs, _PureComponent);
function UncontrolledTabs() {
var _ref;
var _temp, _this, _ret;
_classCallCheck(this, UncontrolledTabs);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = UncontrolledTabs.__proto__ || Object.getPrototypeOf(UncontrolledTabs)).call.apply(_ref, [this].concat(args))), _this), _this.tabNodes = [], _this.handleKeyDown = function (e) {
if (_this.isTabFromContainer(e.target)) {
var index = _this.props.selectedIndex;
var preventDefault = false;
var useSelectedIndex = false;
if (e.keyCode === 32 || e.keyCode === 13) {
preventDefault = true;
useSelectedIndex = false;
_this.handleClick(e);
}
if (e.keyCode === 37 || e.keyCode === 38) {
// Select next tab to the left
index = _this.getPrevTab(index);
preventDefault = true;
useSelectedIndex = true;
} else if (e.keyCode === 39 || e.keyCode === 40) {
// Select next tab to the right
index = _this.getNextTab(index);
preventDefault = true;
useSelectedIndex = true;
}
// This prevents scrollbars from moving around
if (preventDefault) {
e.preventDefault();
}
// Only use the selected index in the state if we're not using the tabbed index
if (useSelectedIndex) {
_this.setSelected(index, e);
}
}
}, _this.handleClick = function (e) {
var node = e.target;
// eslint-disable-next-line no-cond-assign
do {
if (_this.isTabFromContainer(node)) {
if (isTabDisabled(node)) {
return;
}
var index = [].slice.call(node.parentNode.children).filter(isTabNode).indexOf(node);
_this.setSelected(index, e);
return;
}
} while ((node = node.parentNode) !== null);
}, _temp), _possibleConstructorReturn(_this, _ret);
}
_createClass(UncontrolledTabs, [{
key: 'setSelected',
value: function setSelected(index, event) {
// Check index boundary
if (index < 0 || index >= this.getTabsCount()) return;
// Call change event handler
this.props.onSelect(index, this.props.selectedIndex, event);
}
}, {
key: 'getNextTab',
value: function getNextTab(index) {
var count = this.getTabsCount();
// Look for non-disabled tab from index to the last tab on the right
for (var i = index + 1; i < count; i++) {
if (!isTabDisabled(this.getTab(i))) {
return i;
}
}
// If no tab found, continue searching from first on left to index
for (var _i = 0; _i < index; _i++) {
if (!isTabDisabled(this.getTab(_i))) {
return _i;
}
}
// No tabs are disabled, return index
return index;
}
}, {
key: 'getPrevTab',
value: function getPrevTab(index) {
var i = index;
// Look for non-disabled tab from index to first tab on the left
while (i--) {
if (!isTabDisabled(this.getTab(i))) {
return i;
}
}
// If no tab found, continue searching from last tab on right to index
i = this.getTabsCount();
while (i-- > index) {
if (!isTabDisabled(this.getTab(i))) {
return i;
}
}
// No tabs are disabled, return index
return index;
}
}, {
key: 'getTabsCount',
value: function getTabsCount() {
return (0, _count.getTabsCount)(this.props.children);
}
}, {
key: 'getPanelsCount',
value: function getPanelsCount() {
return (0, _count.getPanelsCount)(this.props.children);
}
}, {
key: 'getTab',
value: function getTab(index) {
return this.tabNodes['tabs-' + index];
}
}, {
key: 'getChildren',
value: function getChildren() {
var _this2 = this;
var index = 0;
var _props = this.props,
children = _props.children,
disabledTabClassName = _props.disabledTabClassName,
focus = _props.focus,
forceRenderTabPanel = _props.forceRenderTabPanel,
selectedIndex = _props.selectedIndex,
selectedTabClassName = _props.selectedTabClassName,
selectedTabPanelClassName = _props.selectedTabPanelClassName;
this.tabIds = this.tabIds || [];
this.panelIds = this.panelIds || [];
var diff = this.tabIds.length - this.getTabsCount();
// Add ids if new tabs have been added
// Don't bother removing ids, just keep them in case they are added again
// This is more efficient, and keeps the uuid counter under control
while (diff++ < 0) {
this.tabIds.push((0, _uuid2.default)());
this.panelIds.push((0, _uuid2.default)());
}
// Map children to dynamically setup refs
return (0, _childrenDeepMap.deepMap)(children, function (child) {
var result = child;
// Clone TabList and Tab components to have refs
if ((0, _elementTypes.isTabList)(child)) {
var listIndex = 0;
// Figure out if the current focus in the DOM is set on a Tab
// If it is we should keep the focus on the next selected tab
var wasTabFocused = false;
if (canUseActiveElement) {
wasTabFocused = _react2.default.Children.toArray(child.props.children).filter(_elementTypes.isTab).some(function (tab, i) {
return document.activeElement === _this2.getTab(i);
});
}
result = (0, _react.cloneElement)(child, {
children: (0, _childrenDeepMap.deepMap)(child.props.children, function (tab) {
var key = 'tabs-' + listIndex;
var selected = selectedIndex === listIndex;
var props = {
tabRef: function tabRef(node) {
_this2.tabNodes[key] = node;
},
id: _this2.tabIds[listIndex],
panelId: _this2.panelIds[listIndex],
selected: selected,
focus: selected && (focus || wasTabFocused)
};
if (selectedTabClassName) props.selectedClassName = selectedTabClassName;
if (disabledTabClassName) props.disabledClassName = disabledTabClassName;
listIndex++;
return (0, _react.cloneElement)(tab, props);
})
});
} else if ((0, _elementTypes.isTabPanel)(child)) {
var props = {
id: _this2.panelIds[index],
tabId: _this2.tabIds[index],
selected: selectedIndex === index
};
if (forceRenderTabPanel) props.forceRender = forceRenderTabPanel;
if (selectedTabPanelClassName) props.selectedClassName = selectedTabPanelClassName;
index++;
result = (0, _react.cloneElement)(child, props);
}
return result;
});
}
}, {
key: 'isTabFromContainer',
/**
* Determine if a node from event.target is a Tab element for the current Tabs container.
* If the clicked element is not a Tab, it returns false.
* If it finds another Tabs container between the Tab and `this`, it returns false.
*/
value: function isTabFromContainer(node) {
// return immediately if the clicked element is not a Tab.
if (!isTabNode(node)) {
return false;
}
// Check if the first occurrence of a Tabs container is `this` one.
var nodeAncestor = node.parentElement;
do {
if (nodeAncestor === this.node) return true;else if (nodeAncestor.getAttribute('data-tabs')) break;
nodeAncestor = nodeAncestor.parentElement;
} while (nodeAncestor);
return false;
}
}, {
key: 'render',
value: function render() {
var _this3 = this;
// Delete all known props, so they don't get added to DOM
var _props2 = this.props,
children = _props2.children,
className = _props2.className,
disabledTabClassName = _props2.disabledTabClassName,
domRef = _props2.domRef,
focus = _props2.focus,
forceRenderTabPanel = _props2.forceRenderTabPanel,
onSelect = _props2.onSelect,
selectedIndex = _props2.selectedIndex,
selectedTabClassName = _props2.selectedTabClassName,
selectedTabPanelClassName = _props2.selectedTabPanelClassName,
attributes = _objectWithoutProperties(_props2, ['children', 'className', 'disabledTabClassName', 'domRef', 'focus', 'forceRenderTabPanel', 'onSelect', 'selectedIndex', 'selectedTabClassName', 'selectedTabPanelClassName']);
return _react2.default.createElement(
'div',
_extends({}, attributes, {
className: (0, _classnames2.default)(className),
onClick: this.handleClick,
onKeyDown: this.handleKeyDown,
ref: function ref(node) {
_this3.node = node;
if (domRef) domRef(node);
},
'data-tabs': true
}),
this.getChildren()
);
}
}]);
return UncontrolledTabs;
}(_react.PureComponent);
UncontrolledTabs.defaultProps = {
className: 'react-tabs',
focus: false
};
UncontrolledTabs.propTypes = {
children: _propTypes3.childrenPropType,
className: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.array, _propTypes2.default.object]),
disabledTabClassName: _propTypes2.default.string,
domRef: _propTypes2.default.func,
focus: _propTypes2.default.bool,
forceRenderTabPanel: _propTypes2.default.bool,
onSelect: _propTypes2.default.func.isRequired,
selectedIndex: _propTypes2.default.number.isRequired,
selectedTabClassName: _propTypes2.default.string,
selectedTabPanelClassName: _propTypes2.default.string
};
exports.default = UncontrolledTabs;