@@ -2,47 +2,37 @@ import Menu, { MenuItem } from '../../../menu';
22import Dropdown from '../../../vc-dropdown' ;
33import type { Tab , TabsLocale , EditableConfig } from '../interface' ;
44import AddButton from './AddButton' ;
5- import type { Key , VueNode } from '../../../_util/type' ;
5+ import type { Key } from '../../../_util/type' ;
66import KeyCode from '../../../_util/KeyCode' ;
7- import type { CSSProperties , PropType } from 'vue' ;
7+ import type { CSSProperties , ExtractPropTypes , PropType } from 'vue' ;
88import classNames from '../../../_util/classNames' ;
99import { defineComponent , watch , computed , onMounted } from 'vue' ;
1010import PropTypes from '../../../_util/vue-types' ;
1111import useState from '../../../_util/hooks/useState' ;
1212import { EllipsisOutlined } from '@ant-design/icons-vue' ;
1313
14- export interface OperationNodeProps {
15- prefixCls : string ;
16- id : string ;
17- tabs : Tab [ ] ;
18- rtl : boolean ;
19- tabBarGutter ?: number ;
20- activeKey : Key ;
21- mobile : boolean ;
22- moreIcon ?: VueNode ;
23- moreTransitionName ?: string ;
24- editable ?: EditableConfig ;
25- locale ?: TabsLocale ;
26- onTabClick : ( key : Key , e : MouseEvent | KeyboardEvent ) => void ;
27- }
14+ const operationNodeProps = {
15+ prefixCls : { type : String } ,
16+ id : { type : String } ,
17+ tabs : { type : Object as PropType < Tab [ ] > } ,
18+ rtl : { type : Boolean } ,
19+ tabBarGutter : { type : Number } ,
20+ activeKey : { type : [ String , Number ] } ,
21+ mobile : { type : Boolean } ,
22+ moreIcon : PropTypes . any ,
23+ moreTransitionName : { type : String } ,
24+ editable : { type : Object as PropType < EditableConfig > } ,
25+ locale : { type : Object as PropType < TabsLocale > , default : undefined as TabsLocale } ,
26+ removeAriaLabel : String ,
27+ onTabClick : { type : Function as PropType < ( key : Key , e : MouseEvent | KeyboardEvent ) => void > } ,
28+ } ;
29+
30+ export type OperationNodeProps = Partial < ExtractPropTypes < typeof operationNodeProps > > ;
2831
2932export default defineComponent ( {
3033 name : 'OperationNode' ,
3134 inheritAttrs : false ,
32- props : {
33- prefixCls : { type : String } ,
34- id : { type : String } ,
35- tabs : { type : Object as PropType < Tab [ ] > } ,
36- rtl : { type : Boolean } ,
37- tabBarGutter : { type : Number } ,
38- activeKey : { type : [ String , Number ] } ,
39- mobile : { type : Boolean } ,
40- moreIcon : PropTypes . any ,
41- moreTransitionName : { type : String } ,
42- editable : { type : Object as PropType < EditableConfig > } ,
43- locale : { type : Object as PropType < TabsLocale > , default : undefined as TabsLocale } ,
44- onTabClick : { type : Function as PropType < ( key : Key , e : MouseEvent | KeyboardEvent ) => void > } ,
45- } ,
35+ props : operationNodeProps ,
4636 emits : [ 'tabClick' ] ,
4737 slots : [ 'moreIcon' ] ,
4838 setup ( props , { attrs, slots } ) {
@@ -99,6 +89,15 @@ export default defineComponent({
9989 selectedKey . value !== null ? `${ popupId . value } -${ selectedKey . value } ` : null ,
10090 ) ;
10191
92+ const onRemoveTab = ( event : MouseEvent | KeyboardEvent , key : Key ) => {
93+ event . preventDefault ( ) ;
94+ event . stopPropagation ( ) ;
95+ props . editable . onEdit ( 'remove' , {
96+ key,
97+ event,
98+ } ) ;
99+ } ;
100+
102101 onMounted ( ( ) => {
103102 watch (
104103 selectedKey ,
@@ -174,17 +173,34 @@ export default defineComponent({
174173 dropdownAriaLabel !== undefined ? dropdownAriaLabel : 'expanded dropdown'
175174 }
176175 >
177- { tabs . map ( tab => (
178- < MenuItem
179- key = { tab . key }
180- id = { `${ popupId . value } -${ tab . key } ` }
181- role = "option"
182- aria-controls = { id && `${ id } -panel-${ tab . key } ` }
183- disabled = { tab . disabled }
184- >
185- { typeof tab . tab === 'function' ? tab . tab ( ) : tab . tab }
186- </ MenuItem >
187- ) ) }
176+ { tabs . map ( tab => {
177+ const removable = editable && tab . closable !== false && ! tab . disabled ;
178+ return (
179+ < MenuItem
180+ key = { tab . key }
181+ id = { `${ popupId . value } -${ tab . key } ` }
182+ role = "option"
183+ aria-controls = { id && `${ id } -panel-${ tab . key } ` }
184+ disabled = { tab . disabled }
185+ >
186+ < span > { typeof tab . tab === 'function' ? tab . tab ( ) : tab . tab } </ span >
187+ { removable && (
188+ < button
189+ type = "button"
190+ aria-label = { props . removeAriaLabel || 'remove' }
191+ tabindex = { 0 }
192+ class = { `${ dropdownPrefix } -menu-item-remove` }
193+ onClick = { e => {
194+ e . stopPropagation ( ) ;
195+ onRemoveTab ( e , tab . key ) ;
196+ } }
197+ >
198+ { tab . closeIcon ?.( ) || editable . removeIcon ?.( ) || '×' }
199+ </ button >
200+ ) }
201+ </ MenuItem >
202+ ) ;
203+ } ) }
188204 </ Menu >
189205 ) ,
190206 default : ( ) => (
0 commit comments