ant-design/components/tabs/demo/custom-tab-bar-node.tsx
Wuxh 76241f5d0b
chore(tabs): update demo (#39731)
* 做重复了

* Revert "做重复了"

This reverts commit 79c59e79ea66c6592df9dca0e41e10399044ec7a.

* site(theme): demo block supports no inner margin configuration

ref: https://d.umijs.org/guide/write-demo#%E4%B8%8D%E9%9C%80%E8%A6%81%E5%86%85%E8%BE%B9%E8%B7%9D

* docs(tabs): update demo styles

* chore: update style

* test: update snapshot

* Revert "site(theme): demo block supports no inner margin configuration"

This reverts commit ee2ff25796.

* chore: update

* Revert "chore: update"

This reverts commit bbe449cb3f.

* Revert "Revert "site(theme): demo block supports no inner margin configuration""

This reverts commit 5eac19e7f2.

* chore: convert to debug demo

* chore: use emotion

* test: update snapshot
2022-12-23 12:12:24 +08:00

126 lines
3.0 KiB
TypeScript

import React, { useRef, useState } from 'react';
import type { TabsProps } from 'antd';
import { Tabs } from 'antd';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
const type = 'DraggableTabNode';
interface DraggableTabPaneProps extends React.HTMLAttributes<HTMLDivElement> {
index: React.Key;
moveNode: (dragIndex: React.Key, hoverIndex: React.Key) => void;
}
const DraggableTabNode = ({ index, children, moveNode }: DraggableTabPaneProps) => {
const ref = useRef<HTMLDivElement>(null);
const [{ isOver }, drop] = useDrop({
accept: type,
collect: (monitor) => {
const { index: dragIndex } = monitor.getItem() || {};
if (dragIndex === index) {
return {};
}
return {
isOver: monitor.isOver(),
};
},
drop: (item: { index: React.Key }) => {
moveNode(item.index, index);
},
});
const [, drag] = useDrag({
type,
item: { index },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
});
drop(drag(ref));
// Style
const style: React.CSSProperties = { marginRight: 24 };
if (isOver) {
style.transition = 'all 0.3s';
}
return (
<div ref={ref} style={style}>
{children}
</div>
);
};
const DraggableTabs: React.FC<TabsProps> = (props) => {
const { items = [] } = props;
const [order, setOrder] = useState<React.Key[]>([]);
const moveTabNode = (dragKey: React.Key, hoverKey: React.Key) => {
const newOrder = order.slice();
items.forEach((item) => {
if (item.key && newOrder.indexOf(item.key) === -1) {
newOrder.push(item.key);
}
});
const dragIndex = newOrder.indexOf(dragKey);
const hoverIndex = newOrder.indexOf(hoverKey);
newOrder.splice(dragIndex, 1);
newOrder.splice(hoverIndex, 0, dragKey);
setOrder(newOrder);
};
const renderTabBar: TabsProps['renderTabBar'] = (tabBarProps, DefaultTabBar) => (
<DefaultTabBar {...tabBarProps}>
{(node) => (
<DraggableTabNode key={node.key} index={node.key!} moveNode={moveTabNode}>
{node}
</DraggableTabNode>
)}
</DefaultTabBar>
);
const orderItems = [...items].sort((a, b) => {
const orderA = order.indexOf(a.key!);
const orderB = order.indexOf(b.key!);
if (orderA !== -1 && orderB !== -1) {
return orderA - orderB;
}
if (orderA !== -1) {
return -1;
}
if (orderB !== -1) {
return 1;
}
const ia = items.indexOf(a);
const ib = items.indexOf(b);
return ia - ib;
});
return (
<DndProvider backend={HTML5Backend}>
<Tabs renderTabBar={renderTabBar} {...props} items={orderItems} />
</DndProvider>
);
};
const App: React.FC = () => (
<DraggableTabs
items={new Array(3).fill(null).map((_, i) => {
const id = String(i + 1);
return {
label: `tab ${id}`,
key: id,
children: `Content of Tab Pane ${id}`,
};
})}
/>
);
export default App;