From 191d6e537dc614c5bdf398499feb77f9e4307d51 Mon Sep 17 00:00:00 2001 From: Ali Date: Fri, 2 Jun 2023 15:05:57 +0800 Subject: [PATCH] feat(tabs): add tabs components API add new API fix #2203 --- .gitignore | 3 +- DEVELOP_GUIDE.md | 6 +--- src/_util/useDragSorter.tsx | 19 ++++++++++- src/tabs/Tabs.tsx | 2 ++ src/tabs/__tests__/tabs.test.tsx | 14 ++++++-- src/tabs/_example/drag-sort.jsx | 56 ++++++++++++++++++++------------ src/tabs/tabs.en-US.md | 2 ++ src/tabs/tabs.md | 2 ++ src/tabs/type.ts | 8 +++++ 9 files changed, 83 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 3255934767..18dea7abec 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ robotMsg.json .nyc_output cypress-coverage instrumented -cy-report \ No newline at end of file +cy-report +.history \ No newline at end of file diff --git a/DEVELOP_GUIDE.md b/DEVELOP_GUIDE.md index 90d5774316..2383da097a 100644 --- a/DEVELOP_GUIDE.md +++ b/DEVELOP_GUIDE.md @@ -208,11 +208,7 @@ npm run init # 运行全部单元测试用例(包括所有example的ssr测试) npm run test -# 运行全部单元测试用例 -npm run test:unit -# 运行指定组件单元测试用例,xxx表示组件目录名称, 多个组件用空格分开 -# eg: npm run test:unit button affix -npm run test:unit xxx +# 目前项目测试框架以采用 vitest, 如想单个测试,请下载对应的 vitest vscode插件,进行可视化操作 # 运行全部e2e测试用例 npm run test:e2e diff --git a/src/_util/useDragSorter.tsx b/src/_util/useDragSorter.tsx index 4a3103dc0b..5548a0ae72 100644 --- a/src/_util/useDragSorter.tsx +++ b/src/_util/useDragSorter.tsx @@ -3,6 +3,8 @@ import { useCallback, useRef, useState } from 'react'; interface DragSortProps { sortOnDraggable: boolean; onDragSort?: (context: DragSortContext) => void; + onCustomDragEnd?: (context: DragSortContext) => void; + onCustomDragStart?: (context: DragSortContext) => void; onDragOverCheck?: { x?: boolean; targetClassNameRegExp?: RegExp; @@ -31,7 +33,7 @@ export interface DragSortContext { } function useDragSorter(props: DragSortProps): DragSortInnerProps { - const { sortOnDraggable, onDragSort, onDragOverCheck } = props; + const { sortOnDraggable, onDragSort, onCustomDragEnd, onCustomDragStart, onDragOverCheck } = props; const [draggingIndex, setDraggingIndex] = useState(-1); const [dragStartData, setDragStartData] = useState(null); const [isDropped, setIsDropped] = useState(null); @@ -70,6 +72,7 @@ function useDragSorter(props: DragSortProps): DragSortInnerProps { target: record, targetIndex: index, }); + setDraggingIndex(index); }, [ @@ -97,6 +100,13 @@ function useDragSorter(props: DragSortProps): DragSortInnerProps { nodeWidth: width, mouseX: e.clientX || 0, }); + + onCustomDragStart?.({ + currentIndex: index, + current: record, + target: dragStartData, + targetIndex: draggingIndex, + }); } } @@ -110,6 +120,13 @@ function useDragSorter(props: DragSortProps): DragSortInnerProps { setIsDropped(false); setDraggingIndex(-1); setDragStartData(null); + + onCustomDragEnd?.({ + currentIndex: -1, + current: null, + target: dragStartData, + targetIndex: draggingIndex, + }); } function getDragProps(index, record: T) { if (sortOnDraggable) { diff --git a/src/tabs/Tabs.tsx b/src/tabs/Tabs.tsx index 46fff8daf4..437952b3d2 100644 --- a/src/tabs/Tabs.tsx +++ b/src/tabs/Tabs.tsx @@ -29,6 +29,8 @@ const Tabs = forwardRefWithStatics( x: true, targetClassNameRegExp: new RegExp(targetClassNameRegExpStr), }, + onCustomDragStart: props?.onDragStart, + onCustomDragEnd: props?.onDragEnd, }); const memoChildren = useMemo(() => { diff --git a/src/tabs/__tests__/tabs.test.tsx b/src/tabs/__tests__/tabs.test.tsx index 0804841533..1b8ae0171f 100644 --- a/src/tabs/__tests__/tabs.test.tsx +++ b/src/tabs/__tests__/tabs.test.tsx @@ -310,9 +310,16 @@ describe('Tabs 组件测试', () => { tagBox.removeChild(reactTag); }); + const onDragStart = vi.fn(() => { + console.log('888---999'); + }); + const onDragEnd = vi.fn(() => { + console.log('888---999'); + }); + const { container } = render(
- +
vueContent
@@ -336,7 +343,10 @@ describe('Tabs 组件测试', () => { targetIndex: 0, }, }); - expect(onDragSort).toHaveBeenCalled(1); + expect(onDragSort).toHaveBeenCalled(); + expect(onDragStart).toHaveBeenCalled(); + waitFor(() => expect(onDragEnd).toHaveBeenCalled()); + expect(onDragSort.mock.calls[0][0].target.value).toEqual('vue'); expect(container.querySelectorAll('.t-tabs__nav-item-text-wrapper').item(0).firstChild.nodeValue).toEqual('react'); }); diff --git a/src/tabs/_example/drag-sort.jsx b/src/tabs/_example/drag-sort.jsx index faf5d3d7f5..d39013f872 100644 --- a/src/tabs/_example/drag-sort.jsx +++ b/src/tabs/_example/drag-sort.jsx @@ -11,23 +11,37 @@ const defaultList = [ ]; export default function DragSortExample() { - const [tabList1, setTabList1] = useState([...defaultList]); const [tabList2, setTabList2] = useState([...defaultList]); - const onDragSort1 = useCallback(debounce(({ currentIndex, targetIndex }) => { - const temp = tabList1[currentIndex]; - tabList1[currentIndex] = tabList1[targetIndex]; - tabList1[targetIndex] = temp; - setTabList1([...tabList1]); - }, 500), [tabList1]); + const onDragSort1 = useCallback( + debounce((contents) => { + console.log('%c [ onDragSort1 ]-19', 'font-size:13px; background:#671c39; color:#ab607d;', contents); + const temp = tabList1[contents.currentIndex]; + tabList1[contents.currentIndex] = tabList1[contents.targetIndex]; + tabList1[contents.targetIndex] = temp; + setTabList1([...tabList1]); + }, 500), + [tabList1], + ); + + const onDragSort2 = useCallback( + debounce(({ currentIndex, targetIndex }) => { + const temp = tabList2[currentIndex]; + tabList2[currentIndex] = tabList2[targetIndex]; + tabList2[targetIndex] = temp; + setTabList2([...tabList2]); + }, 500), + [tabList2], + ); + + const onDragStart = useCallback((dragStartContents) => { + console.log('%c [ onDragStart ]-39', 'font-size:13px; background:#1b7980; color:#5fbdc4;', dragStartContents); + }, []); - const onDragSort2 = useCallback(debounce(({ currentIndex, targetIndex }) => { - const temp = tabList2[currentIndex]; - tabList2[currentIndex] = tabList2[targetIndex]; - tabList2[targetIndex] = temp; - setTabList2([...tabList2]); - }, 500), [tabList2]); + const onDragEnd = useCallback((dragEndContents) => { + console.log('%c [ onDragEnd ]-43', 'font-size:13px; background:#933e71; color:#d782b5;', dragEndContents); + }, []); return ( @@ -36,21 +50,23 @@ export default function DragSortExample() { list={tabList1} dragSort onDragSort={onDragSort1} + onDragStart={onDragStart} + onDragEnd={onDragEnd} /> - { - tabList2.map(({ label, value, panel }) => - - {panel} - - ) - } + {tabList2.map(({ label, value, panel }) => ( + + {panel} + + ))} ); diff --git a/src/tabs/tabs.en-US.md b/src/tabs/tabs.en-US.md index db4658c9a0..a020b2572e 100644 --- a/src/tabs/tabs.en-US.md +++ b/src/tabs/tabs.en-US.md @@ -21,6 +21,8 @@ defaultValue | String / Number | - | uncontrolled property。Typescript:`TabVa onAdd | Function | | Typescript:`(context: { e: MouseEvent }) => void`
| N onChange | Function | | Typescript:`(value: TabValue) => void`
| N onDragSort | Function | | Typescript:`(context: TabsDragSortContext) => void`
trigger on drag sort。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/tabs/type.ts)。
`interface TabsDragSortContext { currentIndex: number; current: TabValue; targetIndex: number; target: TabValue }`
| N +onDragStart | Function | | Typescript:`(context: TabsDragSortContext) => void`
trigger when drag sort starts。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/tabs/type.ts)。
`interface TabsDragSortContext { currentIndex: number; current: TabValue; targetIndex: number; target: TabValue }`
| N +onDragEnd | Function | | Typescript:`(context: TabsDragSortContext) => void`
trigger when drag sort ends。[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/tabs/type.ts)。
`interface TabsDragSortContext { currentIndex: number; current: TabValue; targetIndex: number; target: TabValue }`
| N onRemove | Function | | Typescript:`(options: { value: TabValue; index: number; e: MouseEvent }) => void`
| N ### TabPanel Props diff --git a/src/tabs/tabs.md b/src/tabs/tabs.md index 1469fec67d..d4d6e60540 100644 --- a/src/tabs/tabs.md +++ b/src/tabs/tabs.md @@ -20,6 +20,8 @@ defaultValue | String / Number | - | 激活的选项卡值。非受控属性。T onAdd | Function | | TS 类型:`(context: { e: MouseEvent }) => void`
添加选项卡时触发 | N onChange | Function | | TS 类型:`(value: TabValue) => void`
激活的选项卡发生变化时触发 | N onDragSort | Function | | TS 类型:`(context: TabsDragSortContext) => void`
拖拽排序时触发。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/tabs/type.ts)。
`interface TabsDragSortContext { currentIndex: number; current: TabValue; targetIndex: number; target: TabValue }`
| N +onDragStart | Function | | TS 类型:`(context: TabsDragSortContext) => void`
拖拽排序开始时触发。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/tabs/type.ts)。
`interface TabsDragSortContext { currentIndex: number; current: TabValue; targetIndex: number; target: TabValue }`
| N +onDragEnd | Function | | TS 类型:`(context: TabsDragSortContext) => void`
拖拽排序结束时触发。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/tabs/type.ts)。
`interface TabsDragSortContext { currentIndex: number; current: TabValue; targetIndex: number; target: TabValue }`
| N onRemove | Function | | TS 类型:`(options: { value: TabValue; index: number; e: MouseEvent }) => void`
删除选项卡时触发 | N ### TabPanel Props diff --git a/src/tabs/type.ts b/src/tabs/type.ts index 5c28eeab52..d815b64606 100644 --- a/src/tabs/type.ts +++ b/src/tabs/type.ts @@ -62,6 +62,14 @@ export interface TdTabsProps { * 拖拽排序时触发 */ onDragSort?: (context: TabsDragSortContext) => void; + /** + * 拖拽排序开始时出发 + */ + onDragStart?: (context: TabsDragSortContext) => void; + /** + * 拖拽排序结束时出发 + */ + onDragEnd?: (context: TabsDragSortContext) => void; /** * 删除选项卡时触发 */