| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- import classNames from 'classnames';
- import {
- Dispatch,
- MutableRefObject,
- ReactNode,
- SetStateAction,
- forwardRef,
- useEffect,
- useState,
- } from 'react';
- import BodyTr from './BodyTr';
- import {Empty} from 'antd';
- import {HeaderGroup, Row, RowModel} from '@tanstack/react-table';
- import {
- DndContext,
- DragEndEvent,
- DragOverlay,
- DragStartEvent,
- PointerSensor,
- closestCenter,
- useSensor,
- } from '@dnd-kit/core';
- import {
- SortableContext,
- arrayMove,
- verticalListSortingStrategy,
- } from '@dnd-kit/sortable';
- import {debounce} from 'lodash-es';
- type Props = {
- scrollProgess: 'start' | 'end' | 'process',
- getCenterTotalSize: () => number,
- getRowModel: () => RowModel<Record<string, any>>,
- highlightValue?: unknown,
- hightlightKey?: any,
- getHeaderGroups: () => HeaderGroup<Record<string, any>>[],
- enableDnd?: boolean,
- rawKey?: any,
- data: any[],
- setData: Dispatch<SetStateAction<any[]>>,
- isSecondLevel?: boolean,
- renderSubComponent?: (row: Row<Record<string, any>>) => ReactNode,
- };
- type ActiveState = {
- row: Row<Record<string, any>>,
- } | null;
- export default forwardRef<HTMLDivElement, Props>(function TableBody(
- {
- scrollProgess,
- getCenterTotalSize,
- getRowModel,
- highlightValue,
- hightlightKey,
- getHeaderGroups,
- data,
- enableDnd,
- rawKey,
- setData,
- isSecondLevel,
- renderSubComponent,
- },
- ref,
- ) {
- const sensor = useSensor(PointerSensor, {
- activationConstraint: {distance: 10},
- });
- const [active, setActive] = useState<ActiveState>(null);
- function onDragStart(event: DragStartEvent) {
- setActive(event.active.data.current as ActiveState);
- }
- function onDragEnd({over, active}: DragEndEvent) {
- setActive(null);
- if (!over)
- return;
- const {id: activeId} = active,
- {id: overId} = over;
- if (activeId === overId)
- return;
- setData(function(prev) {
- const fromIdx = prev.findIndex(val => val[rawKey ?? 'id'] === activeId),
- toIdx = prev.findIndex(val => val[rawKey ?? 'id'] === overId);
- return arrayMove(prev, fromIdx, toIdx);
- });
- }
- const [tableWidth, setTableWidth] = useState(0);
- useEffect(function() {
- if (!enableDnd) return;
- const dom = (ref as MutableRefObject<HTMLDivElement>).current;
- const obsever = new ResizeObserver(debounce(
- function([entrie]) {
- setTableWidth(entrie.contentRect.width);
- },
- 300,
- {leading: false, trailing: true},
- ));
- obsever.observe(dom);
- return () => obsever.disconnect();
- }, [enableDnd, ref]);
- return (
- <DndContext
- sensors={[sensor]}
- collisionDetection={closestCenter}
- onDragStart={onDragStart}
- onDragEnd={onDragEnd}
- >
- <SortableContext
- items={data.map(val => val[rawKey ?? 'id'])}
- strategy={verticalListSortingStrategy}
- >
- <div className="ld-table-body-wrapper" ref={ref}>
- <table
- className={classNames('ld-table', {
- 'ld-table-enabled-right-fixed-shadow': scrollProgess !== 'end',
- 'ld-table-enabled-left-fixed-shadow': scrollProgess !== 'start',
- })}
- style={{width: getCenterTotalSize()}}
- >
- <tbody className="ld-table-body">
- {getRowModel().rows.length > 0 ? (
- getRowModel().rows.map(function(row) {
- return (
- <BodyTr
- key={row.id}
- highlight={row.original[hightlightKey as string ?? 'id'] === highlightValue}
- enableDnd={enableDnd}
- row={row}
- renderSubComponent={renderSubComponent}
- />
- );
- })
- ) : (
- <tr>
- <td
- colSpan={getHeaderGroups()[0].headers.length}
- style={{padding: 0}}
- >
- <Empty
- image={Empty.PRESENTED_IMAGE_SIMPLE}
- style={{
- width: '400px',
- position: 'sticky',
- left: '50%',
- transform: 'translateX(-50%)',
- overflow: 'hidden',
- margin: 0,
- padding: '50px 10px',
- }}
- />
- </td>
- </tr>
- )}
- </tbody>
- </table>
- </div>
- <DragOverlay>
- {active && (
- <div
- className={classNames({
- 'ld-table-preview-transform': isSecondLevel,
- })}
- style={{width: tableWidth, overflow: 'hidden'}}
- >
- <table
- className={classNames('ld-table', {
- 'ld-table-enabled-right-fixed-shadow': scrollProgess !== 'end',
- 'ld-table-enabled-left-fixed-shadow': scrollProgess !== 'start',
- })}
- style={{width: getCenterTotalSize()}}
- >
- <tbody>
- <BodyTr {...active} preview />
- </tbody>
- </table>
- </div>
- )}
- </DragOverlay>
- </SortableContext>
- </DndContext>
- );
- });
|