Skip to content

Commit 5f37731

Browse files
committed
refactor: refactor tabs
1 parent 2768fef commit 5f37731

File tree

13 files changed

+304
-197
lines changed

13 files changed

+304
-197
lines changed

src/components/tabs/Tab.tsx

+8-18
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,20 @@ import {
88
useDrop,
99
} from 'react-dnd';
1010

11-
import { prefixClaName, classNames } from 'mo/common/className';
12-
export interface TabSwicherProps {
13-
children: any;
14-
className?: string;
15-
}
11+
import { classNames, getBEMElement, getBEMModifier, prefixClaName } from 'mo/common/className';
1612

17-
export function TabSwicher({ children, className }: TabSwicherProps) {
18-
return (
19-
<div className={classNames(prefixClaName('tab-switcher'), className)}>
20-
{children}
21-
</div>
22-
);
23-
}
13+
export const tabClassName = prefixClaName('tab')
14+
export const tabItemClassName = getBEMElement(tabClassName, 'item')
2415

2516
export const Tab = (props) => {
26-
const { id, index, children, onMoveTab, onTabChange } = props;
17+
const { index, propsKey, activeTab, children, onMoveTab, onTabChange } = props;
2718
const ref = useRef<HTMLDivElement>(null);
2819

2920
const [, drag] = useDrag({
3021
collect: (monitor: DragSourceMonitor) => ({
3122
isDragging: monitor.isDragging(),
3223
}),
33-
item: { type: 'DND_NODE', id, index },
24+
item: { type: 'DND_NODE', propsKey, index },
3425
});
3526

3627
const [, drop] = useDrop({
@@ -40,10 +31,9 @@ export const Tab = (props) => {
4031
monitor: DropTargetMonitor
4132
) {
4233
if (!ref.current) return;
43-
let hoverIndex;
4434
const component = ref.current;
4535
const dragIndex = monitor.getItem().index;
46-
hoverIndex = index;
36+
let hoverIndex = index;
4737
// Don't replace items with themselves
4838
if (dragIndex === hoverIndex) {
4939
return;
@@ -71,11 +61,11 @@ export const Tab = (props) => {
7161
});
7262

7363
drag(drop(ref));
74-
7564
return (
7665
<div
7766
ref={ref}
78-
onClick={(event: React.MouseEvent) => onTabChange(props.index)}
67+
className={classNames(tabItemClassName, { [getBEMModifier(tabItemClassName, 'active')]: activeTab === propsKey })}
68+
onClick={(event: React.MouseEvent) => onTabChange(event, propsKey)}
7969
>
8070
{children}
8171
</div>

src/components/tabs/index.tsx

+81-40
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,45 @@
11
import * as React from 'react';
2-
import { useCallback } from 'react';
3-
import update from 'immutability-helper';
2+
import { useCallback, useState } from 'react';
43
import { DndProvider } from 'react-dnd';
54
import HTML5Backend from 'react-dnd-html5-backend';
5+
import update from 'immutability-helper';
66

7-
import { Scrollable } from 'mo/components/scrollable';
8-
import { TabSwicher, Tab } from './Tab';
7+
import { prefixClaName, getBEMElement, getBEMModifier, classNames } from 'mo/common/className';
8+
import { Icon } from 'mo/components/icon';
9+
10+
import { Tab, tabItemClassName } from './Tab';
911
import TabButton from './tabButton';
10-
import './style.scss';
1112

13+
import './style.scss';
1214
export interface ITab {
13-
id?: number | string;
15+
key?: string;
1416
name?: string;
15-
activeTab?: number;
1617
modified?: boolean;
17-
renderPane?: () => React.ReactNode;
1818
value?: string;
19-
mode?: string | undefined;
19+
language?: string | undefined;
20+
tip?: string | React.ReactNode;
21+
label?: React.ReactNode;
22+
renderPanel?: React.ReactNode;
2023
}
2124
export interface ITabsProps {
25+
closable?: boolean;
2226
data: ITab[];
23-
closeTab?: (item: ITab) => void;
27+
activeTab?: string;
28+
type?: 'line' | 'editable-card';
29+
onCloseTab?: (item?: ITab) => void ;
2430
onMoveTab?: (tabs: ITab[]) => void;
25-
onSelectTab?: (index: number) => void;
26-
onTabChange: (index: number) => void;
31+
onSelectTab?: (event: React.MouseEvent, key?: string) => void;
32+
onTabChange: (index: string) => void;
2733
}
2834

29-
const DraggleTabs = (props: ITabsProps) => {
30-
const { data, onSelectTab } = props;
35+
export const tabsClassName = prefixClaName('tabs')
36+
export const tabsHeader = getBEMElement(tabsClassName, 'header')
37+
export const tabsContent = getBEMElement(tabsClassName, 'content')
38+
export const tabsContentItem = getBEMElement(tabsContent, 'item')
3139

40+
const Tabs = (props: ITabsProps) => {
41+
const { closable, data, activeTab: newActiveTab, type = 'line', onCloseTab, onSelectTab } = props;
42+
const [activeTab, setActiveTab] = useState<string | number | void>(newActiveTab)
3243
const onMoveTab = useCallback(
3344
(dragIndex, hoverIndex) => {
3445
const dragTab = data[dragIndex];
@@ -44,37 +55,67 @@ const DraggleTabs = (props: ITabsProps) => {
4455
[data]
4556
);
4657

47-
const onTabClick = (key) => {
48-
console.log(`onTabClick ${key}`);
49-
onSelectTab?.(key);
58+
const onTabClick = (event: React.MouseEvent, key?: string) => {
59+
setActiveTab(key)
60+
onSelectTab?.(event, key);
61+
};
62+
63+
const onTabClose = (item: ITab) => {
64+
let activekey = (data.filter(tab => item.key === tab.key))?.[0]?.key
65+
setActiveTab(activekey)
66+
onCloseTab?.(item)
5067
};
5168

52-
const onTabClose = (item: ITab) => {};
69+
const renderTabBar = (tab) => (
70+
<TabButton
71+
key={tab.key}
72+
name={tab.name}
73+
modified={tab.modified}
74+
active={activeTab === tab.key}
75+
onClose={() => onCloseTab?.(tab)}
76+
className={'tab-button'}
77+
/>)
5378
return (
5479
<DndProvider backend={HTML5Backend}>
55-
<Scrollable className={'normal-items'}>
56-
<TabSwicher className="tab-switcher">
57-
{data?.map((item: ITab, index: number) => (
58-
<Tab
59-
onMoveTab={onMoveTab}
60-
onTabChange={onTabClick}
61-
index={index}
62-
id={item.id}
63-
>
64-
<TabButton
65-
key={item.id}
66-
name={item.name}
67-
modified={item.modified}
68-
active={item.activeTab === index}
69-
onClose={() => onTabClose(item)}
70-
className={'tab-button'}
71-
/>
72-
</Tab>
73-
))}
74-
</TabSwicher>
75-
</Scrollable>
80+
<div className={classNames(tabsClassName, getBEMModifier(tabsClassName, `${type}`))}>
81+
<div className={tabsHeader}>
82+
{data?.map((tab: ITab, index: number) => {
83+
return (
84+
<Tab
85+
onMoveTab={onMoveTab}
86+
onTabChange={onTabClick}
87+
index={index}
88+
propsKey={tab.key}
89+
key={tab.key}
90+
activeTab={activeTab}
91+
title={tab.tip}
92+
>
93+
{type === 'editable-card' ? renderTabBar?.(tab) : tab.label}
94+
{closable && (
95+
<div className={getBEMModifier(tabItemClassName, 'close')} onClick={(e) => {
96+
e.stopPropagation()
97+
onTabClose(tab)
98+
}}>
99+
<Icon type="close" />
100+
</div>
101+
)}
102+
</Tab>
103+
)
104+
})}
105+
</div>
106+
<div className={tabsContent}>{
107+
data?.map((tab: ITab) => {
108+
return (
109+
<div className={classNames(tabsContentItem, { [getBEMModifier(tabsContentItem, 'active')]: activeTab === tab.key })}>
110+
{tab.renderPanel}
111+
</div>
112+
)
113+
})
114+
}
115+
</div>
116+
</div>
76117
</DndProvider>
77118
);
78119
};
79120

80-
export default DraggleTabs;
121+
export default Tabs;

0 commit comments

Comments
 (0)