1- import React from 'react' ;
2- import { Dropdown , DropdownProps , Form , Input } from 'antd' ;
1+ import React , { useState } from 'react' ;
2+ import { Dropdown , DropdownProps , Form , Input , Tabs } from 'antd' ;
33import { BlockHeader } from 'dt-react-component' ;
44import { IBlockHeaderProps } from 'dt-react-component/blockHeader' ;
55
66import { InputMode , ITreeNode , useTreeData } from '../useTreeData' ;
7- import { CatalogIcon , DragIcon , EllipsisIcon } from './icon' ;
7+ import { CatalogIcon , CloseIcon , DragIcon , EllipsisIcon , SearchIcon } from './icon' ;
88import CatalogueTree , { ICatalogueTree } from './tree' ;
99
10- export interface ICatalogue
10+ interface Tab {
11+ readonly key : string ;
12+ readonly title : React . ReactNode ;
13+ }
14+
15+ type readOnlyTab = readonly Tab [ ] ;
16+
17+ type TabKey < T extends readOnlyTab > = T [ number ] [ 'key' ] ;
18+
19+ interface NormalCatalogueProps
1120 extends Pick < IBlockHeaderProps , 'tooltip' | 'addonAfter' | 'addonBefore' | 'title' > ,
1221 ICatalogueTree {
1322 showSearch ?: boolean ;
@@ -19,23 +28,43 @@ export interface ICatalogue
1928 onSearch ?: ( value : string ) => void ;
2029 onSave ?: ( data : ITreeNode , value : string ) => Promise < string | void > ;
2130}
31+ interface TabsCatalogueProps < T extends readOnlyTab > extends NormalCatalogueProps {
32+ tabList ?: T ;
33+ activeTabKey ?: TabKey < T > ;
34+ defaultTabKey ?: TabKey < T > ;
35+ onTabChange ?: ( key : TabKey < T > ) => void ;
36+ }
37+
38+ export type CatalogueProps < T extends readOnlyTab = any > =
39+ | TabsCatalogueProps < T >
40+ | NormalCatalogueProps ;
41+
42+ function isTabMode < T extends readOnlyTab > (
43+ props : CatalogueProps < T >
44+ ) : props is TabsCatalogueProps < T > {
45+ return 'tabList' in props ;
46+ }
47+
48+ const Catalogue = < T extends readOnlyTab > ( props : CatalogueProps < T > ) => {
49+ const {
50+ title,
51+ addonBefore = < CatalogIcon style = { { fontSize : 20 } } /> ,
52+ tooltip = false ,
53+ showSearch = false ,
54+ placeholder = '搜索目录名称' ,
55+ addonAfter,
56+ edit = true ,
57+ treeData,
58+ draggable,
59+ overlay,
60+ onChange,
61+ onSearch,
62+ onSave,
63+ ...rest
64+ } = props ;
65+
66+ const [ tabSearch , setTabSearch ] = useState ( false ) ;
2267
23- const Catalogue = ( {
24- title,
25- addonBefore = < CatalogIcon style = { { fontSize : 20 } } /> ,
26- tooltip = false ,
27- showSearch = false ,
28- placeholder = '搜索目录名称' ,
29- addonAfter,
30- edit = true ,
31- treeData,
32- draggable,
33- overlay,
34- onChange,
35- onSearch,
36- onSave,
37- ...rest
38- } : ICatalogue ) => {
3968 const [ form ] = Form . useForm ( ) ;
4069
4170 const loopTree = ( data : ITreeNode [ ] ) : ITreeNode [ ] => {
@@ -64,25 +93,48 @@ const Catalogue = ({
6493 const renderHeader = ( ) => {
6594 if ( ! title ) return null ;
6695 return (
67- < BlockHeader
68- title = { title }
69- tooltip = { tooltip }
70- background = { false }
71- addonBefore = { addonBefore }
72- addonAfter = { addonAfter }
73- spaceBottom = { 12 }
74- />
96+ < div className = "dt-catalogue__header" >
97+ < BlockHeader
98+ title = { title }
99+ tooltip = { tooltip }
100+ background = { false }
101+ addonBefore = { addonBefore }
102+ addonAfter = { addonAfter }
103+ spaceBottom = { 12 }
104+ />
105+ </ div >
75106 ) ;
76107 } ;
77108
78109 const renderSearch = ( ) => {
79- if ( ! showSearch ) return null ;
110+ if ( ! showSearch || ( isTabMode ( props ) && ! tabSearch ) ) return null ;
80111 return (
81- < Input . Search
82- placeholder = { placeholder }
83- style = { { marginBottom : 12 } }
84- onSearch = { onSearch }
85- />
112+ < div className = "dt-catalogue__search" >
113+ < Input . Search placeholder = { placeholder } onSearch = { onSearch } />
114+ { isTabMode ( props ) && (
115+ < CloseIcon className = "close" style = { { } } onClick = { ( ) => setTabSearch ( false ) } />
116+ ) }
117+ </ div >
118+ ) ;
119+ } ;
120+
121+ const renderTab = ( ) => {
122+ if ( ! isTabMode ( props ) || tabSearch ) return null ;
123+ const { activeTabKey, tabList, onTabChange } = props ;
124+ return (
125+ < Tabs
126+ className = "dt-catalogue__tabs"
127+ size = "small"
128+ tabBarExtraContent = {
129+ < SearchIcon className = "search" onClick = { ( ) => setTabSearch ( true ) } />
130+ }
131+ activeKey = { activeTabKey }
132+ onChange = { onTabChange }
133+ >
134+ { tabList ?. map ( ( tab : { key : string ; title : React . ReactNode } ) => (
135+ < Tabs . TabPane tab = { tab . title } key = { tab . key } />
136+ ) ) }
137+ </ Tabs >
86138 ) ;
87139 } ;
88140
@@ -182,10 +234,9 @@ const Catalogue = ({
182234
183235 return (
184236 < div className = "dt-catalogue" >
185- < div className = "dt-catalogue__header" >
186- { renderHeader ( ) }
187- { renderSearch ( ) }
188- </ div >
237+ { renderHeader ( ) }
238+ { renderSearch ( ) }
239+ { renderTab ( ) }
189240 < CatalogueTree
190241 treeData = { loopTree ( treeData ) }
191242 draggable = { draggable ? { icon : false } : false }
0 commit comments