feat: add drag and drop column rearrangement for table viz (#19381)

This commit is contained in:
stevetracvc
2022-05-24 20:10:57 -06:00
committed by GitHub
parent ce547f4098
commit 7e9b85f76c
8 changed files with 93 additions and 6 deletions

View File

@@ -29,6 +29,7 @@ import {
usePagination,
useSortBy,
useGlobalFilter,
useColumnOrder,
PluginHook,
TableOptions,
FilterType,
@@ -64,6 +65,7 @@ export interface DataTableProps<D extends object> extends TableOptions<D> {
sticky?: boolean;
rowCount: number;
wrapperRef?: MutableRefObject<HTMLDivElement>;
onColumnOrderChange: () => void;
}
export interface RenderHTMLCellProps extends HTMLProps<HTMLTableCellElement> {
@@ -95,12 +97,14 @@ export default typedMemo(function DataTable<D extends object>({
hooks,
serverPagination,
wrapperRef: userWrapperRef,
onColumnOrderChange,
...moreUseTableOptions
}: DataTableProps<D>): JSX.Element {
const tableHooks: PluginHook<D>[] = [
useGlobalFilter,
useSortBy,
usePagination,
useColumnOrder,
doSticky ? useSticky : [],
hooks || [],
].flat();
@@ -172,6 +176,8 @@ export default typedMemo(function DataTable<D extends object>({
setGlobalFilter,
setPageSize: setPageSize_,
wrapStickyTable,
setColumnOrder,
allColumns,
state: { pageIndex, pageSize, globalFilter: filterValue, sticky = {} },
} = useTable<D>(
{
@@ -211,6 +217,33 @@ export default typedMemo(function DataTable<D extends object>({
const shouldRenderFooter = columns.some(x => !!x.Footer);
let columnBeingDragged = -1;
const onDragStart = (e: React.DragEvent) => {
const el = e.target as HTMLTableCellElement;
columnBeingDragged = allColumns.findIndex(
col => col.id === el.dataset.columnName,
);
e.dataTransfer.setData('text/plain', `${columnBeingDragged}`);
};
const onDrop = (e: React.DragEvent) => {
const el = e.target as HTMLTableCellElement;
const newPosition = allColumns.findIndex(
col => col.id === el.dataset.columnName,
);
if (newPosition !== -1) {
const currentCols = allColumns.map(c => c.id);
const colToBeMoved = currentCols.splice(columnBeingDragged, 1);
currentCols.splice(newPosition, 0, colToBeMoved[0]);
setColumnOrder(currentCols);
// toggle value in TableChart to trigger column width recalc
onColumnOrderChange();
}
e.preventDefault();
};
const renderTable = () => (
<table {...getTableProps({ className: tableClassName })}>
<thead>
@@ -223,6 +256,8 @@ export default typedMemo(function DataTable<D extends object>({
column.render('Header', {
key: column.id,
...column.getSortByToggleProps(),
onDragStart,
onDrop,
}),
)}
</tr>

View File

@@ -350,6 +350,7 @@ function useInstance<D extends object>(instance: TableInstance<D>) {
data,
page,
rows,
allColumns,
getTableSize = () => undefined,
} = instance;
@@ -370,7 +371,7 @@ function useInstance<D extends object>(instance: TableInstance<D>) {
useMountedMemo(getTableSize, [getTableSize]) || sticky;
// only change of data should trigger re-render
// eslint-disable-next-line react-hooks/exhaustive-deps
const table = useMemo(renderer, [page, rows]);
const table = useMemo(renderer, [page, rows, allColumns]);
useLayoutEffect(() => {
if (!width || !height) {

View File

@@ -36,6 +36,8 @@ import {
UseSortByState,
UseTableHooks,
UseSortByHooks,
UseColumnOrderState,
UseColumnOrderInstanceProps,
Renderer,
HeaderProps,
TableFooterProps,
@@ -64,6 +66,7 @@ declare module 'react-table' {
UseRowSelectInstanceProps<D>,
UseRowStateInstanceProps<D>,
UseSortByInstanceProps<D>,
UseColumnOrderInstanceProps<D>,
UseStickyInstanceProps {}
export interface TableState<D extends object>
@@ -73,6 +76,7 @@ declare module 'react-table' {
UsePaginationState<D>,
UseRowSelectState<D>,
UseSortByState<D>,
UseColumnOrderState<D>,
UseStickyState {}
// Typing from @types/react-table is incomplete
@@ -82,12 +86,19 @@ declare module 'react-table' {
onClick?: React.MouseEventHandler;
}
interface TableRearrangeColumnsProps {
onDragStart: (e: React.DragEvent) => void;
onDrop: (e: React.DragEvent) => void;
}
export interface ColumnInterface<D extends object>
extends UseGlobalFiltersColumnOptions<D>,
UseSortByColumnOptions<D> {
// must define as a new property because it's not possible to override
// the existing `Header` renderer option
Header?: Renderer<TableSortByToggleProps & HeaderProps<D>>;
Header?: Renderer<
TableSortByToggleProps & HeaderProps<D> & TableRearrangeColumnsProps
>;
Footer?: Renderer<TableFooterProps<D>>;
}