import React, { useState, useRef, useEffect, useCallback, createRef, RefObject } from 'react'; import { ReactSortable } from 'react-sortablejs'; import classames from 'classnames'; import { LeftOutlined, RightOutlined } from '@easyv/react-icons'; export interface DataSourceType { id: string; name: string; rank: number; } export interface SortableTabsProp { dataSource: DataSourceType[]; selectKey?: string; onTabChange?: (key: string) => void; onDragChange?: (dragKey: string, rank: number, changeDataSource: DataSourceType[]) => void; } export default function SortableTabs({ dataSource, selectKey, onTabChange, onDragChange, }: SortableTabsProp) { const scrollRef = useRef(null); const [listRef, setListRef] = useState[]>([]); const [innerDataSource, setInnerDataSource] = useState([]); const [, setAddScrollLen] = useState(0); const handleScroll = useCallback( (addScrollLen: number = 0) => { if (!scrollRef.current) return; const selectindex = dataSource.findIndex((i) => i.id === selectKey); if (selectindex > -1) { const itemRef = listRef[selectindex]; if (!itemRef?.current) return; const scrollRefRect = scrollRef.current.getBoundingClientRect(); const itemRefRect = itemRef.current.getBoundingClientRect(); scrollRef.current.scrollTo({ left: itemRef.current.offsetLeft - scrollRef.current.offsetLeft - (scrollRefRect.width - itemRefRect.width) / 2 + addScrollLen, behavior: 'smooth', }); } else { scrollRef.current.scrollTo({ left: 0, behavior: 'smooth', }); } }, [dataSource, listRef, selectKey], ); useEffect(() => { setAddScrollLen(0); handleScroll(0); }, [handleScroll]); useEffect(() => { setInnerDataSource(JSON.parse(JSON.stringify(dataSource))); setListRef(dataSource.map(() => createRef())); }, [dataSource]); useEffect(() => { for (let index = 0; index < innerDataSource.length; index++) { const item = innerDataSource[index]; const { id: key } = item; if (key !== dataSource[index]?.id) { const oldIndex = dataSource.findIndex(({ id }) => id === key); const oldPrev = dataSource[oldIndex - 1]; const newPrev = innerDataSource[index - 1]; const oldNext = dataSource[oldIndex + 1]; const newNext = innerDataSource[index + 1]; if (oldPrev?.id !== newPrev?.id && oldNext?.id !== newNext?.id) { let newOrder; if (newPrev === undefined) { newOrder = dataSource[0].rank - 1; } else if (newNext === undefined) { newOrder = dataSource[dataSource.length - 1].rank + 1; } else { newOrder = dataSource[dataSource.length - 1].rank + 1; } onDragChange?.(key, newOrder, innerDataSource); return; } } } }, [innerDataSource, dataSource, onDragChange]); return (
setAddScrollLen((state) => { handleScroll(state - 100); return state - 100; }) }>
{innerDataSource.map((item, index) => (
onTabChange?.(item.id)}> {item.name}
))}
setAddScrollLen((state) => { handleScroll(state + 100); return state + 100; }) }>
); }