import _extends from 'babel-runtime/helpers/extends'; import _defineProperty from 'babel-runtime/helpers/defineProperty'; import omit from 'omit.js'; import BaseMixin from '../../_util/BaseMixin'; import PropTypes from '../../_util/vue-types'; import raf from 'raf'; import KeyCode from './KeyCode'; import { getOptionProps } from '../../_util/props-util'; import { cloneElement } from '../../_util/vnode'; import Sentinel from './Sentinel'; function getDefaultActiveKey(props) { var activeKey = void 0; var children = props.children; children.forEach(function (child) { if (child && !activeKey && !child.disabled) { activeKey = child.key; } }); return activeKey; } function activeKeyIsValid(props, key) { var children = props.children; var keys = children.map(function (child) { return child && child.key; }); return keys.indexOf(key) >= 0; } export default { name: 'Tabs', mixins: [BaseMixin], model: { prop: 'activeKey', event: 'change' }, props: { destroyInactiveTabPane: PropTypes.bool, renderTabBar: PropTypes.func.isRequired, renderTabContent: PropTypes.func.isRequired, navWrapper: PropTypes.func.def(function (arg) { return arg; }), children: PropTypes.any.def([]), prefixCls: PropTypes.string.def('ant-tabs'), tabBarPosition: PropTypes.string.def('top'), activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), defaultActiveKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), __propsSymbol__: PropTypes.any }, data: function data() { var props = getOptionProps(this); var activeKey = void 0; if ('activeKey' in props) { activeKey = props.activeKey; } else if ('defaultActiveKey' in props) { activeKey = props.defaultActiveKey; } else { activeKey = getDefaultActiveKey(props); } return { _activeKey: activeKey }; }, provide: function provide() { return { sentinelContext: this }; }, watch: { __propsSymbol__: function __propsSymbol__() { var nextProps = getOptionProps(this); if ('activeKey' in nextProps) { this.setState({ _activeKey: nextProps.activeKey }); } else if (!activeKeyIsValid(nextProps, this.$data._activeKey)) { // https://github.com/ant-design/ant-design/issues/7093 this.setState({ _activeKey: getDefaultActiveKey(nextProps) }); } } }, beforeDestroy: function beforeDestroy() { this.destroy = true; raf.cancel(this.sentinelId); }, methods: { onTabClick: function onTabClick(activeKey, e) { if (this.tabBar.componentOptions && this.tabBar.componentOptions.listeners && this.tabBar.componentOptions.listeners.tabClick) { this.tabBar.componentOptions.listeners.tabClick(activeKey, e); } this.setActiveKey(activeKey); }, onNavKeyDown: function onNavKeyDown(e) { var eventKeyCode = e.keyCode; if (eventKeyCode === KeyCode.RIGHT || eventKeyCode === KeyCode.DOWN) { e.preventDefault(); var nextKey = this.getNextActiveKey(true); this.onTabClick(nextKey); } else if (eventKeyCode === KeyCode.LEFT || eventKeyCode === KeyCode.UP) { e.preventDefault(); var previousKey = this.getNextActiveKey(false); this.onTabClick(previousKey); } }, onScroll: function onScroll(_ref) { var target = _ref.target, currentTarget = _ref.currentTarget; if (target === currentTarget && target.scrollLeft > 0) { target.scrollLeft = 0; } }, // Sentinel for tab index setSentinelStart: function setSentinelStart(node) { this.sentinelStart = node; }, setSentinelEnd: function setSentinelEnd(node) { this.sentinelEnd = node; }, setPanelSentinelStart: function setPanelSentinelStart(node) { if (node !== this.panelSentinelStart) { this.updateSentinelContext(); } this.panelSentinelStart = node; }, setPanelSentinelEnd: function setPanelSentinelEnd(node) { if (node !== this.panelSentinelEnd) { this.updateSentinelContext(); } this.panelSentinelEnd = node; }, setActiveKey: function setActiveKey(activeKey) { if (this.$data._activeKey !== activeKey) { var props = getOptionProps(this); if (!('activeKey' in props)) { this.setState({ _activeKey: activeKey }); } this.__emit('change', activeKey); } }, getNextActiveKey: function getNextActiveKey(next) { var activeKey = this.$data._activeKey; var children = []; this.$props.children.forEach(function (c) { if (c && !c.disabled && c.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; }, updateSentinelContext: function updateSentinelContext() { var _this = this; if (this.destroy) return; raf.cancel(this.sentinelId); this.sentinelId = raf(function () { _this.$forceUpdate(); }); } }, render: function render() { var _cls; var h = arguments[0]; var props = this.$props; var prefixCls = props.prefixCls, navWrapper = props.navWrapper, tabBarPosition = props.tabBarPosition, renderTabContent = props.renderTabContent, renderTabBar = props.renderTabBar, destroyInactiveTabPane = props.destroyInactiveTabPane; var cls = (_cls = {}, _defineProperty(_cls, prefixCls, 1), _defineProperty(_cls, prefixCls + '-' + tabBarPosition, 1), _cls); this.tabBar = renderTabBar(); var tabBar = cloneElement(this.tabBar, { props: { prefixCls: prefixCls, navWrapper: navWrapper, tabBarPosition: tabBarPosition, panels: props.children, activeKey: this.$data._activeKey }, on: { keydown: this.onNavKeyDown, tabClick: this.onTabClick }, key: 'tabBar' }); var tabContent = cloneElement(renderTabContent(), { props: { prefixCls: prefixCls, tabBarPosition: tabBarPosition, activeKey: this.$data._activeKey, destroyInactiveTabPane: destroyInactiveTabPane }, on: { change: this.setActiveKey }, children: props.children, key: 'tabContent' }); var sentinelStart = h(Sentinel, { key: 'sentinelStart', attrs: { setRef: this.setSentinelStart, nextElement: this.panelSentinelStart } }); var sentinelEnd = h(Sentinel, { key: 'sentinelEnd', attrs: { setRef: this.setSentinelEnd, prevElement: this.panelSentinelEnd } }); var contents = []; if (tabBarPosition === 'bottom') { contents.push(sentinelStart, tabContent, sentinelEnd, tabBar); } else { contents.push(tabBar, sentinelStart, tabContent, sentinelEnd); } var listeners = _extends({}, omit(this.$listeners, ['change']), { scroll: this.onScroll }); return h( 'div', { on: listeners, 'class': cls }, [contents] ); } };