ant-design-vue/components/tabs/tabs.tsx
tangjinzhou 9e0df41a55
refactor: Anchor、Alert、Avatar、Badge、BackTop、Col、Form、Layout、Menu、Space、Spin、Switch、Row、Result、Rate (#4171)
* chore: remove  resize-observer-polyfill

* refactor: align

* refactor(v3/avatar): refactor using composition api  (#4052)

* refactor(avatar): refactor using composition api

* refactor: update props define

* fix: avatar src scale not update

* refactor: resizeObserver

* refactor: divider

* refactor: localeProvider

* refactor(v3/back-top): use composition api (#4060)

* refactor: backtop

* refactor: empty

* refactor: transButton

* feat(v3/avatar): add avatar group (#4062)

* feat(avatar): add avatar group

* refactor: update

* refactor: update

Co-authored-by: tangjinzhou <415800467@qq.com>

* refactor: avatar

* refactor: avatar

* style: rename useProvide

* refactor:  menu (#4110)

* fix: menu

* refactor: menu

* refactor: remove rc-menu

* fix: menu rtl error

* style: lint

* refactor(Anchor): use composition api (#4054)

* refactor: anchor

* refactor: anchor

* refactor: anchor

* feat: update

* fix: icon class lose

* refactor(v3/badge): use composition api (#4076)

* refactor: badge

* fix: badge inheritAttrs

* refactor: grid

* refactor: layout

* fix: menu not close

* refactor: space

* refactor: result

* refactor: affix

* refactor: comment

* refactor: form

* feat: spin add rtl

* feat: export spin type

* refactor: pageHeader

* refactor: page-header

* refactor: skeleton

* refactor: typography

* refactor(v3/rate): use composition api

* fix: add useRef hook

* refactor: form

* fix: menu not update

* refactor: form

* refactor: form

* fix: slide animate not work

* fix: menu mode error

* fix: menu icon

* refactor: rate

* perf: remove rate

* feat: add vc-overflow

* refactor: menu

* fix: remove flex check (#4165)

* fix: dist locale file lose #3684

* release 2.2.0-beta.1

* dcos: update changelog

* chore: update type

* docs: update changelog

Co-authored-by: John <John60676@qq.com>
Co-authored-by: 言肆 <18x@loacg.com>
Co-authored-by: zkwolf <chenhao5866@gmail.com>
2021-06-07 17:35:03 +08:00

181 lines
6.0 KiB
Vue
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 { defineComponent, inject, PropType } from 'vue';
import { tuple } from '../_util/type';
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
import PlusOutlined from '@ant-design/icons-vue/PlusOutlined';
import VcTabs, { TabPane } from '../vc-tabs/src';
import TabContent from '../vc-tabs/src/TabContent';
import PropTypes, { withUndefined } from '../_util/vue-types';
import {
getComponent,
getOptionProps,
filterEmpty,
getPropsData,
getSlot,
} from '../_util/props-util';
import { cloneElement } from '../_util/vnode';
import isValid from '../_util/isValid';
import { defaultConfigProvider } from '../config-provider';
import TabBar from './TabBar';
export default defineComponent({
TabPane,
name: 'ATabs',
inheritAttrs: false,
props: {
prefixCls: PropTypes.string,
activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
defaultActiveKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
hideAdd: PropTypes.looseBool.def(false),
centered: PropTypes.looseBool.def(false),
tabBarStyle: PropTypes.object,
tabBarExtraContent: PropTypes.any,
destroyInactiveTabPane: PropTypes.looseBool.def(false),
type: PropTypes.oneOf(tuple('line', 'card', 'editable-card')),
tabPosition: PropTypes.oneOf(['top', 'right', 'bottom', 'left']).def('top'),
size: PropTypes.oneOf(['default', 'small', 'large']),
animated: withUndefined(PropTypes.oneOfType([PropTypes.looseBool, PropTypes.object])),
tabBarGutter: PropTypes.number,
renderTabBar: PropTypes.func,
onChange: {
type: Function as PropType<(activeKey: string) => void>,
},
onTabClick: PropTypes.func,
onPrevClick: {
type: Function as PropType<(e: MouseEvent) => void>,
},
onNextClick: {
type: Function as PropType<(e: MouseEvent) => void>,
},
onEdit: {
type: Function as PropType<
(targetKey: string | MouseEvent, action: 'add' | 'remove') => void
>,
},
},
emits: ['update:activeKey', 'edit', 'change'],
setup() {
return {
configProvider: inject('configProvider', defaultConfigProvider),
};
},
methods: {
removeTab(targetKey: string, e: MouseEvent) {
e.stopPropagation();
if (isValid(targetKey)) {
this.$emit('edit', targetKey, 'remove');
}
},
handleChange(activeKey: string) {
this.$emit('update:activeKey', activeKey);
this.$emit('change', activeKey);
},
createNewTab(targetKey: MouseEvent) {
this.$emit('edit', targetKey, 'add');
},
},
render() {
const props = getOptionProps(this);
const {
prefixCls: customizePrefixCls,
size,
type = 'line',
tabPosition,
animated = true,
hideAdd,
renderTabBar,
} = props;
const { class: className, ...restProps } = this.$attrs;
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('tabs', customizePrefixCls);
const children = filterEmpty(getSlot(this));
let tabBarExtraContent = getComponent(this, 'tabBarExtraContent');
let tabPaneAnimated = typeof animated === 'object' ? animated.tabPane : animated;
// card tabs should not have animation
if (type !== 'line') {
tabPaneAnimated = 'animated' in props ? tabPaneAnimated : false;
}
const cls = {
[className as string]: className,
[`${prefixCls}-vertical`]: tabPosition === 'left' || tabPosition === 'right',
[`${prefixCls}-${size}`]: !!size,
[`${prefixCls}-card`]: type.indexOf('card') >= 0,
[`${prefixCls}-${type}`]: true,
[`${prefixCls}-no-animation`]: !tabPaneAnimated,
};
// only card type tabs can be added and closed
let childrenWithClose = [];
if (type === 'editable-card') {
childrenWithClose = [];
children.forEach((child, index) => {
const props = getPropsData(child) as any;
let closable = props.closable;
closable = typeof closable === 'undefined' ? true : closable;
const closeIcon = closable ? (
<CloseOutlined
class={`${prefixCls}-close-x`}
onClick={e => this.removeTab(child.key, e)}
/>
) : null;
childrenWithClose.push(
cloneElement(child, {
tab: (
<div class={closable ? undefined : `${prefixCls}-tab-unclosable`}>
{getComponent(child, 'tab')}
{closeIcon}
</div>
),
key: child.key || index,
}),
);
});
// Add new tab handler
if (!hideAdd) {
tabBarExtraContent = (
<span>
<PlusOutlined class={`${prefixCls}-new-tab`} onClick={this.createNewTab} />
{tabBarExtraContent}
</span>
);
}
}
tabBarExtraContent = tabBarExtraContent ? (
<div class={`${prefixCls}-extra-content`}>{tabBarExtraContent}</div>
) : null;
const renderTabBarSlot = renderTabBar || this.$slots.renderTabBar;
const tabBarProps = {
...props,
prefixCls,
tabBarExtraContent,
renderTabBar: renderTabBarSlot,
...restProps,
children,
};
const contentCls = {
[`${prefixCls}-${tabPosition}-content`]: true,
[`${prefixCls}-card-content`]: type.indexOf('card') >= 0,
};
const tabsProps = {
...props,
prefixCls,
tabBarPosition: tabPosition,
// https://github.com/vueComponent/ant-design-vue/issues/2030
// 如仅传递 tabBarProps 会导致,第二次执行 renderTabBar 时,丢失 on 属性,
// 添加key之后会在babel jsx 插件中做一次merge最终TabBar接收的是一个新的对象而不是 tabBarProps
renderTabBar: () => <TabBar key="tabBar" {...tabBarProps} />,
renderTabContent: () => (
<TabContent class={contentCls} animated={tabPaneAnimated} animatedWithMargin />
),
children: childrenWithClose.length > 0 ? childrenWithClose : children,
...restProps,
onChange: this.handleChange,
class: cls,
};
return <VcTabs {...tabsProps} />;
},
});