325 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import _extends from 'babel-runtime/helpers/extends';
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';
var _class, _temp;
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { KEYCODE, obj } from '../util';
import TabNav from './tabs/nav';
import TabContent from './tabs/content';
import { toArray } from './tabs/utils';
var noop = function noop() {};
/** Tab */
var Tab = (_temp = _class = function (_Component) {
_inherits(Tab, _Component);
function Tab(props, context) {
_classCallCheck(this, Tab);
var _this = _possibleConstructorReturn(this, _Component.call(this, props, context));
_this.handleTriggerEvent = function (eventType, key) {
var _this$props = _this.props,
triggerType = _this$props.triggerType,
onClick = _this$props.onClick,
onChange = _this$props.onChange;
if (triggerType === eventType) {
onClick(key);
_this.setActiveKey(key);
if (_this.state.activeKey !== key) {
onChange(key);
}
}
};
_this.onNavKeyDown = function (e) {
var keyCode = e.keyCode;
if (keyCode >= KEYCODE.LEFT && keyCode <= KEYCODE.DOWN) {
e.preventDefault();
}
var newKey = void 0;
if (keyCode === KEYCODE.RIGHT || keyCode === KEYCODE.DOWN) {
newKey = _this.getNextActiveKey(true);
_this.handleTriggerEvent(_this.props.triggerType, newKey);
} else if (keyCode === KEYCODE.LEFT || keyCode === KEYCODE.UP) {
newKey = _this.getNextActiveKey(false);
_this.handleTriggerEvent(_this.props.triggerType, newKey);
}
};
_this.state = {
activeKey: _this.getDefaultActiveKey(props)
};
return _this;
}
Tab.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
if (nextProps.activeKey !== undefined && this.state.activeKey !== '' + nextProps.activeKey) {
this.setState({
activeKey: '' + nextProps.activeKey
});
}
};
Tab.prototype.getDefaultActiveKey = function getDefaultActiveKey(props) {
var activeKey = props.activeKey === undefined ? props.defaultActiveKey : props.activeKey;
if (activeKey === undefined) {
React.Children.forEach(props.children, function (child, index) {
if (activeKey !== undefined) return;
if (React.isValidElement(child)) {
if (!child.props.disabled) {
activeKey = child.key || index;
}
}
});
}
return '' + activeKey;
};
Tab.prototype.getNextActiveKey = function getNextActiveKey(isNext) {
var _this2 = this;
var children = [];
React.Children.forEach(this.props.children, function (child) {
if (React.isValidElement(child)) {
if (!child.props.disabled) {
if (isNext) {
children.push(child);
} else {
children.unshift(child);
}
}
}
});
var length = children.length;
var key = length && children[0].key;
children.forEach(function (child, i) {
if (child.key === _this2.state.activeKey) {
if (i === length - 1) {
key = children[0].key;
} else {
key = children[i + 1].key;
}
}
});
return key;
};
Tab.prototype.setActiveKey = function setActiveKey(key) {
var activeKey = this.state.activeKey;
// 如果 key 没变,或者受控状态下,则跳过
if (key === activeKey || 'activeKey' in this.props) {
return;
}
this.setState({
activeKey: key
});
};
Tab.prototype.render = function render() {
var _classnames;
var _props = this.props,
prefix = _props.prefix,
animation = _props.animation,
shape = _props.shape,
size = _props.size,
extra = _props.extra,
excessMode = _props.excessMode,
tabPosition = _props.tabPosition,
tabRender = _props.tabRender,
triggerType = _props.triggerType,
lazyLoad = _props.lazyLoad,
unmountInactiveTabs = _props.unmountInactiveTabs,
popupProps = _props.popupProps,
navStyle = _props.navStyle,
navClassName = _props.navClassName,
contentStyle = _props.contentStyle,
contentClassName = _props.contentClassName,
className = _props.className,
onClose = _props.onClose,
children = _props.children,
rtl = _props.rtl,
device = _props.device,
others = _objectWithoutProperties(_props, ['prefix', 'animation', 'shape', 'size', 'extra', 'excessMode', 'tabPosition', 'tabRender', 'triggerType', 'lazyLoad', 'unmountInactiveTabs', 'popupProps', 'navStyle', 'navClassName', 'contentStyle', 'contentClassName', 'className', 'onClose', 'children', 'rtl', 'device']);
var activeKey = this.state.activeKey;
var tabs = toArray(children);
var isTouchable = ['phone', 'tablet'].indexOf(device) !== -1;
var newPosition = tabPosition;
if (rtl && ['left', 'right'].indexOf(tabPosition) >= 0) {
newPosition = tabPosition === 'left' ? 'right' : 'left';
}
var classNames = classnames((_classnames = {}, _classnames[prefix + 'tabs'] = true, _classnames[prefix + 'tabs-' + shape] = shape, _classnames[prefix + 'tabs-vertical'] = shape === 'wrapped' && ['left', 'right'].indexOf(tabPosition) >= 0, _classnames[prefix + 'tabs-scrollable'] = isTouchable, _classnames[prefix + 'tabs-' + newPosition] = shape === 'wrapped', _classnames['' + (prefix + size)] = size, _classnames), className);
var navProps = {
prefix: prefix,
rtl: rtl,
animation: animation,
activeKey: activeKey,
excessMode: isTouchable ? 'slide' : excessMode,
extra: extra,
tabs: tabs,
tabPosition: tabPosition,
tabRender: tabRender,
triggerType: triggerType,
popupProps: popupProps,
onClose: onClose,
onTriggerEvent: this.handleTriggerEvent,
onKeyDown: this.onNavKeyDown,
style: navStyle,
className: navClassName
};
var contentProps = {
prefix: prefix,
activeKey: activeKey,
lazyLoad: lazyLoad,
unmountInactiveTabs: unmountInactiveTabs,
style: contentStyle,
className: contentClassName
};
var tabChildren = [React.createElement(TabNav, _extends({ key: 'tab-nav' }, navProps)), React.createElement(
TabContent,
_extends({ key: 'tab-content' }, contentProps),
tabs
)];
if (tabPosition === 'bottom') {
tabChildren.reverse();
}
return React.createElement(
'div',
_extends({
dir: rtl ? 'rtl' : undefined,
className: classNames
}, obj.pickOthers(Tab.propTypes, others)),
tabChildren
);
};
return Tab;
}(Component), _class.propTypes = {
prefix: PropTypes.string,
rtl: PropTypes.bool,
device: PropTypes.oneOf(['tablet', 'desktop', 'phone']),
/**
* 被激活的选项卡的 key, 赋值则tab为受控组件, 用户无法切换
*/
activeKey: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
/**
* 初始化时被激活的选项卡的 key
*/
defaultActiveKey: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
/**
* 外观形态
*/
shape: PropTypes.oneOf(['pure', 'wrapped', 'text', 'capsule']),
/**
* 是否开启动效
*/
animation: PropTypes.bool,
/**
* 选项卡过多时的滑动模式
*/
excessMode: PropTypes.oneOf(['slide', 'dropdown']),
/**
* 导航选项卡的位置只适用于包裹型wrapped选项卡
*/
tabPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
/**
* 尺寸
*/
size: PropTypes.oneOf(['small', 'medium']),
/**
* 激活选项卡的触发方式
*/
triggerType: PropTypes.oneOf(['hover', 'click']),
/**
* 是否延迟加载 TabPane 的内容, 默认开启, 即不提前渲染
*/
lazyLoad: PropTypes.bool,
/**
* 是否自动卸载未处于激活状态的选项卡
*/
unmountInactiveTabs: PropTypes.bool,
/**
* 导航条的自定义样式
*/
navStyle: PropTypes.object,
/**
* 导航条的自定义样式类
*/
navClassName: PropTypes.string,
/**
* 内容区容器的自定义样式
*/
contentStyle: PropTypes.object,
/**
* 内容区容器的自定义样式类
*/
contentClassName: PropTypes.string,
/**
* 导航栏附加内容
*/
extra: PropTypes.node,
/**
* 点击单个选项卡时触发的回调
*/
onClick: PropTypes.func,
/**
* 选项卡发生切换时的事件回调
* @param {String|Number} key 改变后的 key
*/
onChange: PropTypes.func,
/**
* 选项卡被关闭时的事件回调
* @param {String|Number} key 关闭的选项卡的 key
*/
onClose: PropTypes.func,
/**
* 自定义选项卡模板渲染函数
* @param {String} key 当前 Tab.Item 的 key 值
* @param {Object} props 传给 Tab.Item 的所有属性键值对
* @return {ReactNode} 返回自定义组件
*/
tabRender: PropTypes.func,
/**
* 弹层属性透传, 只有当 excessMode 为 dropdown 时生效
*/
popupProps: PropTypes.object,
children: PropTypes.any,
className: PropTypes.string
}, _class.defaultProps = {
prefix: 'next-',
shape: 'pure',
size: 'medium',
animation: true,
tabPosition: 'top',
excessMode: 'slide',
triggerType: 'click',
lazyLoad: true,
unmountInactiveTabs: false,
onClick: noop,
onChange: noop,
onClose: noop
}, _temp);
Tab.displayName = 'Tab';
export { Tab as default };