312 lines
8.8 KiB
JavaScript
Executable File
312 lines
8.8 KiB
JavaScript
Executable File
import _extends from 'babel-runtime/helpers/extends';
|
|
import _defineProperty from 'babel-runtime/helpers/defineProperty';
|
|
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
|
|
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
|
|
import _createClass from 'babel-runtime/helpers/createClass';
|
|
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
|
|
import _inherits from 'babel-runtime/helpers/inherits';
|
|
import React from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import classnames from 'classnames';
|
|
import raf from 'raf';
|
|
import { polyfill } from 'react-lifecycles-compat';
|
|
import KeyCode from './KeyCode';
|
|
import TabPane from './TabPane';
|
|
import { getDataAttr } from './utils';
|
|
import Sentinel, { SentinelProvider } from './Sentinel';
|
|
|
|
function noop() {}
|
|
|
|
function getDefaultActiveKey(props) {
|
|
var activeKey = void 0;
|
|
React.Children.forEach(props.children, function (child) {
|
|
if (child && !activeKey && !child.props.disabled) {
|
|
activeKey = child.key;
|
|
}
|
|
});
|
|
return activeKey;
|
|
}
|
|
|
|
function activeKeyIsValid(props, key) {
|
|
var keys = React.Children.map(props.children, function (child) {
|
|
return child && child.key;
|
|
});
|
|
return keys.indexOf(key) >= 0;
|
|
}
|
|
|
|
var Tabs = function (_React$Component) {
|
|
_inherits(Tabs, _React$Component);
|
|
|
|
function Tabs(props) {
|
|
_classCallCheck(this, Tabs);
|
|
|
|
var _this = _possibleConstructorReturn(this, (Tabs.__proto__ || Object.getPrototypeOf(Tabs)).call(this, props));
|
|
|
|
_initialiseProps.call(_this);
|
|
|
|
var activeKey = void 0;
|
|
if ('activeKey' in props) {
|
|
activeKey = props.activeKey;
|
|
} else if ('defaultActiveKey' in props) {
|
|
activeKey = props.defaultActiveKey;
|
|
} else {
|
|
activeKey = getDefaultActiveKey(props);
|
|
}
|
|
|
|
_this.state = {
|
|
activeKey: activeKey
|
|
};
|
|
return _this;
|
|
}
|
|
|
|
_createClass(Tabs, [{
|
|
key: 'componentWillUnmount',
|
|
value: function componentWillUnmount() {
|
|
this.destroy = true;
|
|
raf.cancel(this.sentinelId);
|
|
}
|
|
|
|
// Sentinel for tab index
|
|
|
|
}, {
|
|
key: 'updateSentinelContext',
|
|
value: function updateSentinelContext() {
|
|
var _this2 = this;
|
|
|
|
if (this.destroy) return;
|
|
|
|
raf.cancel(this.sentinelId);
|
|
this.sentinelId = raf(function () {
|
|
if (_this2.destroy) return;
|
|
_this2.forceUpdate();
|
|
});
|
|
}
|
|
}, {
|
|
key: 'render',
|
|
value: function render() {
|
|
var _classnames;
|
|
|
|
var props = this.props;
|
|
|
|
var prefixCls = props.prefixCls,
|
|
navWrapper = props.navWrapper,
|
|
tabBarPosition = props.tabBarPosition,
|
|
className = props.className,
|
|
renderTabContent = props.renderTabContent,
|
|
renderTabBar = props.renderTabBar,
|
|
destroyInactiveTabPane = props.destroyInactiveTabPane,
|
|
direction = props.direction,
|
|
restProps = _objectWithoutProperties(props, ['prefixCls', 'navWrapper', 'tabBarPosition', 'className', 'renderTabContent', 'renderTabBar', 'destroyInactiveTabPane', 'direction']);
|
|
|
|
var cls = classnames((_classnames = {}, _defineProperty(_classnames, prefixCls, 1), _defineProperty(_classnames, prefixCls + '-' + tabBarPosition, 1), _defineProperty(_classnames, className, !!className), _defineProperty(_classnames, prefixCls + '-rtl', direction === 'rtl'), _classnames));
|
|
|
|
this.tabBar = renderTabBar();
|
|
|
|
var tabBar = React.cloneElement(this.tabBar, {
|
|
prefixCls: prefixCls,
|
|
navWrapper: navWrapper,
|
|
key: 'tabBar',
|
|
onKeyDown: this.onNavKeyDown,
|
|
tabBarPosition: tabBarPosition,
|
|
onTabClick: this.onTabClick,
|
|
panels: props.children,
|
|
activeKey: this.state.activeKey,
|
|
direction: this.props.direction
|
|
});
|
|
|
|
var tabContent = React.cloneElement(renderTabContent(), {
|
|
prefixCls: prefixCls,
|
|
tabBarPosition: tabBarPosition,
|
|
activeKey: this.state.activeKey,
|
|
destroyInactiveTabPane: destroyInactiveTabPane,
|
|
children: props.children,
|
|
onChange: this.setActiveKey,
|
|
key: 'tabContent',
|
|
direction: this.props.direction
|
|
});
|
|
|
|
var sentinelStart = React.createElement(Sentinel, {
|
|
key: 'sentinelStart',
|
|
setRef: this.setSentinelStart,
|
|
nextElement: this.panelSentinelStart
|
|
});
|
|
var sentinelEnd = React.createElement(Sentinel, {
|
|
key: 'sentinelEnd',
|
|
setRef: this.setSentinelEnd,
|
|
prevElement: this.panelSentinelEnd
|
|
});
|
|
|
|
var contents = [];
|
|
if (tabBarPosition === 'bottom') {
|
|
contents.push(sentinelStart, tabContent, sentinelEnd, tabBar);
|
|
} else {
|
|
contents.push(tabBar, sentinelStart, tabContent, sentinelEnd);
|
|
}
|
|
|
|
return React.createElement(
|
|
SentinelProvider,
|
|
{
|
|
value: {
|
|
sentinelStart: this.sentinelStart,
|
|
sentinelEnd: this.sentinelEnd,
|
|
setPanelSentinelStart: this.setPanelSentinelStart,
|
|
setPanelSentinelEnd: this.setPanelSentinelEnd
|
|
}
|
|
},
|
|
React.createElement(
|
|
'div',
|
|
_extends({
|
|
className: cls,
|
|
style: props.style
|
|
}, getDataAttr(restProps), {
|
|
onScroll: this.onScroll
|
|
}),
|
|
contents
|
|
)
|
|
);
|
|
}
|
|
}], [{
|
|
key: 'getDerivedStateFromProps',
|
|
value: function getDerivedStateFromProps(props, state) {
|
|
var newState = {};
|
|
if ('activeKey' in props) {
|
|
newState.activeKey = props.activeKey;
|
|
} else if (!activeKeyIsValid(props, state.activeKey)) {
|
|
newState.activeKey = getDefaultActiveKey(props);
|
|
}
|
|
if (Object.keys(newState).length > 0) {
|
|
return newState;
|
|
}
|
|
return null;
|
|
}
|
|
}]);
|
|
|
|
return Tabs;
|
|
}(React.Component);
|
|
|
|
var _initialiseProps = function _initialiseProps() {
|
|
var _this3 = this;
|
|
|
|
this.onTabClick = function (activeKey, e) {
|
|
if (_this3.tabBar.props.onTabClick) {
|
|
_this3.tabBar.props.onTabClick(activeKey, e);
|
|
}
|
|
_this3.setActiveKey(activeKey);
|
|
};
|
|
|
|
this.onNavKeyDown = function (e) {
|
|
var eventKeyCode = e.keyCode;
|
|
if (eventKeyCode === KeyCode.RIGHT || eventKeyCode === KeyCode.DOWN) {
|
|
e.preventDefault();
|
|
var nextKey = _this3.getNextActiveKey(true);
|
|
_this3.onTabClick(nextKey);
|
|
} else if (eventKeyCode === KeyCode.LEFT || eventKeyCode === KeyCode.UP) {
|
|
e.preventDefault();
|
|
var previousKey = _this3.getNextActiveKey(false);
|
|
_this3.onTabClick(previousKey);
|
|
}
|
|
};
|
|
|
|
this.onScroll = function (_ref) {
|
|
var target = _ref.target,
|
|
currentTarget = _ref.currentTarget;
|
|
|
|
if (target === currentTarget && target.scrollLeft > 0) {
|
|
target.scrollLeft = 0;
|
|
}
|
|
};
|
|
|
|
this.setSentinelStart = function (node) {
|
|
_this3.sentinelStart = node;
|
|
};
|
|
|
|
this.setSentinelEnd = function (node) {
|
|
_this3.sentinelEnd = node;
|
|
};
|
|
|
|
this.setPanelSentinelStart = function (node) {
|
|
if (node !== _this3.panelSentinelStart) {
|
|
_this3.updateSentinelContext();
|
|
}
|
|
_this3.panelSentinelStart = node;
|
|
};
|
|
|
|
this.setPanelSentinelEnd = function (node) {
|
|
if (node !== _this3.panelSentinelEnd) {
|
|
_this3.updateSentinelContext();
|
|
}
|
|
_this3.panelSentinelEnd = node;
|
|
};
|
|
|
|
this.setActiveKey = function (activeKey) {
|
|
if (_this3.state.activeKey !== activeKey) {
|
|
if (!('activeKey' in _this3.props)) {
|
|
_this3.setState({
|
|
activeKey: activeKey
|
|
});
|
|
}
|
|
_this3.props.onChange(activeKey);
|
|
}
|
|
};
|
|
|
|
this.getNextActiveKey = function (next) {
|
|
var activeKey = _this3.state.activeKey;
|
|
var children = [];
|
|
React.Children.forEach(_this3.props.children, function (c) {
|
|
if (c && !c.props.disabled) {
|
|
if (next) {
|
|
children.push(c);
|
|
} else {
|
|
children.unshift(c);
|
|
}
|
|
}
|
|
});
|
|
var length = children.length;
|
|
var ret = length && children[0].key;
|
|
children.forEach(function (child, i) {
|
|
if (child.key === activeKey) {
|
|
if (i === length - 1) {
|
|
ret = children[0].key;
|
|
} else {
|
|
ret = children[i + 1].key;
|
|
}
|
|
}
|
|
});
|
|
return ret;
|
|
};
|
|
};
|
|
|
|
Tabs.propTypes = {
|
|
destroyInactiveTabPane: PropTypes.bool,
|
|
renderTabBar: PropTypes.func.isRequired,
|
|
renderTabContent: PropTypes.func.isRequired,
|
|
navWrapper: PropTypes.func,
|
|
onChange: PropTypes.func,
|
|
children: PropTypes.node,
|
|
prefixCls: PropTypes.string,
|
|
className: PropTypes.string,
|
|
tabBarPosition: PropTypes.string,
|
|
style: PropTypes.object,
|
|
activeKey: PropTypes.string,
|
|
defaultActiveKey: PropTypes.string,
|
|
direction: PropTypes.string
|
|
};
|
|
|
|
Tabs.defaultProps = {
|
|
prefixCls: 'rc-tabs',
|
|
destroyInactiveTabPane: false,
|
|
onChange: noop,
|
|
navWrapper: function navWrapper(arg) {
|
|
return arg;
|
|
},
|
|
tabBarPosition: 'top',
|
|
children: null,
|
|
style: {},
|
|
direction: 'ltr'
|
|
};
|
|
|
|
Tabs.TabPane = TabPane;
|
|
|
|
polyfill(Tabs);
|
|
|
|
export default Tabs; |