Skip to content

Commit

Permalink
feat: add second version of Tab component
Browse files Browse the repository at this point in the history
  • Loading branch information
mumiao committed Nov 25, 2020
1 parent 52cbfe3 commit 6aabcf6
Show file tree
Hide file tree
Showing 19 changed files with 372 additions and 161 deletions.
5 changes: 3 additions & 2 deletions .stylelintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"rules": {
"indentation": 4,
"scss/dollar-variable-pattern": null,
"max-nesting-depth": 4
"max-nesting-depth": 4,
"no-missing-end-of-source-newline": null
}
}
}
4 changes: 3 additions & 1 deletion commitlint.config.js
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
module.exports = { extends: ['@commitlint/config-conventional'] };
module.exports = {
extends: ['@commitlint/config-conventional']
};
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"react-split-pane": "^0.1.92",
"reflect-metadata": "^0.1.13",
"tsyringe": "^4.3.0",
"vscode-codicons": "^0.0.10"
"vscode-codicons": "^0.0.10",
"vscode-icons-js": "^11.0.0"
},
"devDependencies": {
"@commitlint/cli": "^11.0.0",
Expand Down
31 changes: 31 additions & 0 deletions src/components/fileIcon/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import './style.scss';
import * as React from 'react';
import {
getIconForFile,
getIconForFolder,
getIconForOpenFolder,
} from 'vscode-icons-js';
import { prefixClaName, classNames } from 'mo/common/className';

const ICON_BASE_PATH = '/assets/fileIcons/';

export interface Props {
fileName: string;
type?: 'folder' | 'folderOpen' | 'file';
className?: string;
}

export default function FileIcon({ fileName, type, className }: Props) {
const iconPath: string | undefined =
type === 'file'
? getIconForFile(fileName)
: type === 'folder'
? getIconForFolder(fileName)
: getIconForOpenFolder(fileName);
return (
<i
className={classNames(prefixClaName('file-icon'), className)}
style={{ backgroundImage: `url(${ICON_BASE_PATH + iconPath})` }}
/>
);
}
11 changes: 11 additions & 0 deletions src/components/fileIcon/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@import 'mo/style/common';
$fileIcon: 'file-icon';

#{prefix($fileIcon)} {
background-position: center center;
background-size: contain;
display: inline-block;
height: 16px;
vertical-align: middle;
width: 16px;
}
38 changes: 25 additions & 13 deletions src/components/tabs/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@ import {
useDrop,
} from 'react-dnd';

interface ITabProps {
active?: string;
content?: React.ReactNode;
index?: number;
id?: number | string;
name?: any;
moveTab: (dragIndex?: number, hoverIndex?: number | string) => void;
import { prefixClaName, classNames } from 'mo/common/className';
export interface TabSwicherProps {
children: any;
className?: string;
}

const WrapTabNode: React.FC<ITabProps> = (props) => {
const { id, index, moveTab, children } = props;
export function TabSwicher({ children, className }: TabSwicherProps) {
return (
<div className={classNames(prefixClaName('tab-switcher'), className)}>
{children}
</div>
);
}

export const Tab = (props) => {
const { id, index, children, onMoveTab, onTabChange } = props;
const ref = useRef<HTMLDivElement>(null);

const [, drag] = useDrag({
Expand All @@ -34,7 +39,6 @@ const WrapTabNode: React.FC<ITabProps> = (props) => {
item: { type: string; index: number },
monitor: DropTargetMonitor
) {
debugger;
if (!ref.current) return;
let hoverIndex;
const component = ref.current;
Expand All @@ -61,13 +65,21 @@ const WrapTabNode: React.FC<ITabProps> = (props) => {
if (dragIndex > hoverIndex && hoverClientX > hoverMiddleX) {
return;
}
moveTab(dragIndex, hoverIndex);
onMoveTab(dragIndex, hoverIndex);
monitor.getItem().index = hoverIndex;
},
});

drag(drop(ref));

return <div ref={ref}>{children}</div>;
return (
<div
ref={ref}
onClick={(event: React.MouseEvent) => onTabChange(props.index)}
>
{children}
</div>
);
};

export default WrapTabNode;
export default Tab;
97 changes: 41 additions & 56 deletions src/components/tabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,33 @@ import update from 'immutability-helper';
import { DndProvider } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

import Tabs, { TabPane } from 'rc-tabs';

import WrapTabNode from './Tab';
import { prefixClaName } from 'mo/common/className';
import { Scrollable } from 'mo/components/scrollable';
import { TabSwicher, Tab } from './tab';
import TabButton from './tabButton';
import './style.scss';

export interface ITab {
active?: string;
id?: number;
name?: string;
mode?: string;
data?: [];
value?: string;
renderPane?: () => React.ReactNode;
id?: number | string;
name?: string; // fileName
activeTab?: number; // activeTab
modified?: boolean; // modify file
}
interface ITabsProps {
export interface ITabsProps {
data: ITab[];
closeTab?: (index: number) => void;
changeTab?: (tabs: ITab[]) => void;
closeTab?: (item: ITab) => void;
onMoveTab?: (tabs: ITab[]) => void;
selectTab?: (index: number) => void;
children?: React.ReactNode;
// onMoveTab: (dragIndex?: number, hoverIndex?: number | string) => void;
onTabChange: (index: number) => void;
}

const DraggleTabs: React.FC<ITabsProps> = (props: ITabsProps) => {
const { data, changeTab, selectTab } = props;
const DraggleTabs = (props: ITabsProps) => {
const { data, onMoveTab, selectTab } = props;

const moveTab = useCallback(
const onMoveTab = useCallback(
(dragIndex, hoverIndex) => {
const dragTab = data[dragIndex];
changeTab?.(
onMoveTab?.(
update(data, {
$splice: [
[dragIndex, 1],
Expand All @@ -47,46 +44,34 @@ const DraggleTabs: React.FC<ITabsProps> = (props: ITabsProps) => {

const onTabClick = (key) => {
console.log(`onTabClick ${key}`);
if (selectTab) selectTab(key);
};

const renderTabBar = (props, DefaultTabBar) => {
return (
<DefaultTabBar {...props}>
{(node) => {
return (
<WrapTabNode
key={node.key}
index={node.key}
moveTab={moveTab}
>
{node}
</WrapTabNode>
);
}}
</DefaultTabBar>
);
selectTab?.(key);
};

const onTabClose = (item: ITab) => {};
return (
<div className={prefixClaName('tabs-container')}>
<DndProvider backend={HTML5Backend}>
<Tabs
renderTabBar={renderTabBar}
onChange={onTabClick}
editable={{
showAdd: false,
onEdit: () => {
console.log(1);
},
}}
>
{data?.map(({ active, id, name }: ITab, index) => {
return <TabPane tab={`${name}`} key={index} />;
})}
</Tabs>
</DndProvider>
</div>
<DndProvider backend={HTML5Backend}>
<Scrollable>
<TabSwicher className="tab-switcher">
{data?.map((item: ITab, index: number) => (
<Tab
onMoveTab={onMoveTab}
onTabChange={onTabClick}
index={index}
id={item.id}
>
<TabButton
key={item.id}
name={item.name}
modified={item.modified}
active={item.activeTab === index}
onClose={() => onTabClose(item)}
className={'tab-button'}
/>
</Tab>
))}
</TabSwicher>
</Scrollable>
</DndProvider>
);
};

Expand Down
Loading

0 comments on commit 6aabcf6

Please sign in to comment.