@@ -21,13 +21,16 @@ interface IProps {
2121 onChange : ( key : IOption [ 'value' ] ) => void ;
2222 onEdit ?: ( action : 'add' | 'remove' , key ?: IOption [ 'value' ] ) => void ;
2323 hideAdd ?: boolean ;
24- type ?: 'line'
24+ type ?: 'line' ;
25+ editableName ?: boolean ;
26+ editableNameOnBlur ?: ( option : IOption ) => void ;
2527}
2628
2729export default memo < IProps > ( function Tab ( props ) {
28- const { className, tabs, onChange, onEdit, activeTab, hideAdd, type } = props ;
30+ const { className, tabs, onChange, onEdit, activeTab, hideAdd, type, editableName , editableNameOnBlur } = props ;
2931 const [ internalTabs , setInternalTabs ] = useState < IOption [ ] > ( lodash . cloneDeep ( tabs || [ ] ) ) ;
3032 const [ internalActiveTab , setInternalActiveTab ] = useState < number | string | undefined > ( internalTabs [ 0 ] ?. value ) ;
33+ const [ editingTab , setEditingTab ] = useState < IOption [ 'value' ] | undefined > ( ) ;
3134
3235 useEffect ( ( ) => {
3336 setInternalActiveTab ( activeTab ) ;
@@ -52,31 +55,57 @@ export default memo<IProps>(function Tab(props) {
5255 onEdit ?.( 'add' )
5356 }
5457
58+ function onDoubleClick ( t : IOption ) {
59+ if ( editableName ) {
60+ setEditingTab ( t . value )
61+ }
62+ }
63+
64+
65+ function renderTabItem ( t : IOption , index : number ) {
66+ function inputOnChange ( value : string ) {
67+ internalTabs [ index ] . label = value
68+ setInternalTabs ( [ ...internalTabs ] )
69+ }
70+
71+ function onBlur ( ) {
72+ editableNameOnBlur ?.( t ) ;
73+ setEditingTab ( undefined ) ;
74+ }
75+
76+ return < div
77+ onDoubleClick = { ( ) => { onDoubleClick ( t ) } }
78+ key = { t . value }
79+ className = {
80+ classnames (
81+ { [ styles . tabItem ] : type !== 'line' } ,
82+ { [ styles . tabItemLine ] : type === 'line' } ,
83+ { [ styles . activeTabLine ] : t . value === internalActiveTab && type === 'line' } ,
84+ { [ styles . activeTab ] : t . value === internalActiveTab && type !== 'line' } ,
85+ )
86+ }
87+ >
88+ {
89+ t . value === editingTab ?
90+ < input onChange = { ( e ) => { inputOnChange ( e . target . value ) } } className = { styles . input } autoFocus onBlur = { onBlur } type = "text" />
91+ :
92+ < div className = { styles . text } key = { t . value } onClick = { changeTab . bind ( null , t ) } >
93+ { t . label }
94+ </ div >
95+ }
96+ < div className = { styles . icon } onClick = { deleteTab . bind ( null , t ) } >
97+ < Iconfont code = '' />
98+ </ div >
99+ </ div >
100+ }
101+
55102 return < div className = { classnames ( styles . tab , className ) } >
56103 {
57104 ! ! internalTabs ?. length &&
58105 < div className = { styles . tabList } >
59106 {
60107 internalTabs . map ( ( t , index ) => {
61- return < div
62- key = { t . value }
63- className = {
64- classnames (
65- { [ styles . tabItem ] : type !== 'line' } ,
66- { [ styles . tabItemLine ] : type === 'line' } ,
67- { [ styles . activeTabLine ] : t . value === internalActiveTab && type === 'line' } ,
68- { [ styles . activeTab ] : t . value === internalActiveTab && type !== 'line' } ,
69- )
70- }
71-
72- >
73- < div className = { styles . text } key = { t . value } onClick = { changeTab . bind ( null , t ) } >
74- { t . label }
75- </ div >
76- < div className = { styles . icon } onClick = { deleteTab . bind ( null , t ) } >
77- < Iconfont code = '' />
78- </ div >
79- </ div >
108+ return renderTabItem ( t , index )
80109 } )
81110 }
82111 </ div >
0 commit comments