Skip to content

Commit

Permalink
fix: #718 dragend don't fire on virtualization (#719)
Browse files Browse the repository at this point in the history
* fix: #718 dragend don't fire on virtualization

* update pr.yml

* checkout v3

* clean up

---------

Co-authored-by: 章勇 <zhangyong@zhangyong.com>
Co-authored-by: Kevin Van Cott <kevinvandy656@gmail.com>
  • Loading branch information
3 people committed Oct 12, 2023
1 parent b5075de commit ec3a896
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 33 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }}

- name: Setup PNPM
uses: pnpm/action-setup@v2
with:
version: 8.5.1
version: 8.8.0

- name: Install Dependencies
run: pnpm i
Expand Down
24 changes: 20 additions & 4 deletions packages/material-react-table/src/body/MRT_TableBody.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { memo, useMemo } from 'react';
import { memo, useCallback, useMemo } from 'react';
import {
type Range,
type VirtualItem,
type Virtualizer,
useVirtualizer,
} from '@tanstack/react-virtual';
import TableBody from '@mui/material/TableBody';
import Typography from '@mui/material/Typography';
import { MRT_TableBodyRow, Memo_MRT_TableBodyRow } from './MRT_TableBodyRow';
import { getCanRankRows, parseFromValuesOrFunc } from '../column.utils';
import {
extraIndexRangeExtractor,
getCanRankRows,
parseFromValuesOrFunc,
} from '../column.utils';
import { rankGlobalFuzzy } from '../sortingFns';
import { type MRT_Row, type MRT_TableInstance } from '../types';

Expand Down Expand Up @@ -60,6 +65,7 @@ export const MRT_TableBody = <TData extends Record<string, any>>({
const {
columnFilters,
density,
draggingRow,
expanded,
globalFilter,
isFullScreen,
Expand Down Expand Up @@ -152,6 +158,12 @@ export const MRT_TableBody = <TData extends Record<string, any>>({
? (element) => element?.getBoundingClientRect().height
: undefined,
overscan: 4,
rangeExtractor: useCallback(
(range: Range) => {
return extraIndexRangeExtractor(range, draggingRow?.index ?? 0);
},
[draggingRow],
),
...rowVirtualizerProps,
})
: undefined;
Expand Down Expand Up @@ -213,12 +225,16 @@ export const MRT_TableBody = <TData extends Record<string, any>>({
{tableBodyProps?.children ??
(!rows.length ? (
<tr
style={{ display: layoutMode?.startsWith('grid') ? 'grid' : undefined }}
style={{
display: layoutMode?.startsWith('grid') ? 'grid' : undefined,
}}
>
<td
colSpan={table.getVisibleLeafColumns().length}
style={{
display: layoutMode?.startsWith('grid') ? 'grid' : 'table-cell',
display: layoutMode?.startsWith('grid')
? 'grid'
: 'table-cell',
}}
>
{renderEmptyRowsFallback?.({ table }) ?? (
Expand Down
19 changes: 19 additions & 0 deletions packages/material-react-table/src/column.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
type Renderable,
type Row,
} from '@tanstack/react-table';
import { type Range, defaultRangeExtractor } from '@tanstack/react-virtual';
import { type TableCellProps } from '@mui/material/TableCell';
import { alpha, lighten } from '@mui/material/styles';
import { type Theme } from '@mui/material/styles';
Expand Down Expand Up @@ -423,3 +424,21 @@ export const createRow = <TData extends Record<string, any>>(
-1,
0,
) as MRT_Row<TData>;

export const extraIndexRangeExtractor = (
range: Range,
draggingIndex: number,
) => {
const newIndexs = defaultRangeExtractor(range);
if (
draggingIndex >= 0 &&
draggingIndex < Math.max(range.startIndex - range.overscan, 0)
) {
newIndexs.unshift(draggingIndex);
}
if (draggingIndex >= 0 && draggingIndex > range.endIndex + range.overscan) {
newIndexs.push(draggingIndex);
}
return newIndexs;
};

30 changes: 20 additions & 10 deletions packages/material-react-table/src/table/MRT_Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import { useCallback, useMemo } from 'react';
import {
type Range,
type Virtualizer,
defaultRangeExtractor,
useVirtualizer,
} from '@tanstack/react-virtual';
import Table from '@mui/material/Table';
import { MRT_TableBody, Memo_MRT_TableBody } from '../body/MRT_TableBody';
import { parseCSSVarId, parseFromValuesOrFunc } from '../column.utils';
import { extraIndexRangeExtractor, parseCSSVarId, parseFromValuesOrFunc } from '../column.utils';
import { MRT_TableFooter } from '../footer/MRT_TableFooter';
import { MRT_TableHead } from '../head/MRT_TableHead';
import { type MRT_TableInstance } from '../types';
Expand Down Expand Up @@ -43,6 +42,7 @@ export const MRT_Table = <TData extends Record<string, any>>({
columnSizing,
columnSizingInfo,
columnVisibility,
draggingColumn,
isFullScreen,
} = getState();

Expand Down Expand Up @@ -93,6 +93,10 @@ export const MRT_Table = <TData extends Record<string, any>>({
[columnPinning, enableColumnVirtualization, enableColumnPinning],
);

const draggingColumnIndex = table
.getVisibleLeafColumns()
.findIndex((c) => c.id === draggingColumn?.id);

const columnVirtualizer:
| Virtualizer<HTMLDivElement, HTMLTableCellElement>
| undefined = enableColumnVirtualization
Expand All @@ -103,14 +107,20 @@ export const MRT_Table = <TData extends Record<string, any>>({
horizontal: true,
overscan: 3,
rangeExtractor: useCallback(
(range: Range) => [
...new Set([
...leftPinnedIndexes,
...defaultRangeExtractor(range),
...rightPinnedIndexes,
]),
],
[leftPinnedIndexes, rightPinnedIndexes],
(range: Range) => {
const newIndexs = extraIndexRangeExtractor(
range,
draggingColumnIndex,
);
return [
...new Set([
...leftPinnedIndexes,
...newIndexs,
...rightPinnedIndexes,
]),
];
},
[leftPinnedIndexes, rightPinnedIndexes, draggingColumnIndex],
),
...columnVirtualizerProps,
})
Expand Down
16 changes: 6 additions & 10 deletions packages/material-react-table/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,8 @@ export type MRT_TableInstance<TData extends Record<string, any>> = Omit<
setEditingCell: Dispatch<SetStateAction<MRT_Cell<TData> | null>>;
setEditingRow: Dispatch<SetStateAction<MRT_Row<TData> | null>>;
setGlobalFilterFn: Dispatch<SetStateAction<MRT_FilterOption>>;
setHoveredColumn: Dispatch<
SetStateAction<{ id: string } | MRT_Column<TData> | null>
>;
setHoveredRow: Dispatch<
SetStateAction<{ id: string } | MRT_Row<TData> | null>
>;
setHoveredColumn: Dispatch<SetStateAction<Partial<MRT_Column<TData>> | null>>;
setHoveredRow: Dispatch<SetStateAction<Partial<MRT_Row<TData>> | null>>;
setIsFullScreen: Dispatch<SetStateAction<boolean>>;
setShowAlertBanner: Dispatch<SetStateAction<boolean>>;
setShowColumnFilters: Dispatch<SetStateAction<boolean>>;
Expand All @@ -288,8 +284,8 @@ export type MRT_TableState<TData extends Record<string, any>> = TableState & {
editingCell: MRT_Cell<TData> | null;
editingRow: MRT_Row<TData> | null;
globalFilterFn: MRT_FilterOption;
hoveredColumn: { id: string } | MRT_Column<TData> | null;
hoveredRow: { id: string } | MRT_Row<TData> | null;
hoveredColumn: Partial<MRT_Column<TData>> | null;
hoveredRow: Partial<MRT_Row<TData>> | null;
isFullScreen: boolean;
isLoading: boolean;
isSaving: boolean;
Expand Down Expand Up @@ -972,8 +968,8 @@ export type MRT_TableOptions<TData extends Record<string, any>> = Omit<
values: Record<LiteralUnion<string & DeepKeys<TData>>, any>;
}) => Promise<void> | void;
onGlobalFilterFnChange?: OnChangeFn<MRT_FilterOption>;
onHoveredColumnChange?: OnChangeFn<{ id: string } | MRT_Column<TData> | null>;
onHoveredRowChange?: OnChangeFn<{ id: string } | MRT_Row<TData> | null>;
onHoveredColumnChange?: OnChangeFn<Partial<MRT_Row<TData>> | null>;
onHoveredRowChange?: OnChangeFn<Partial<MRT_Row<TData>> | null>;
onIsFullScreenChange?: OnChangeFn<boolean>;
onShowAlertBannerChange?: OnChangeFn<boolean>;
onShowColumnFiltersChange?: OnChangeFn<boolean>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,15 @@ export const ColumnOrderingStateManaged = () => {
/>
);
};

export const ColumnOrderingEnabledWithColumnVirtualization = () => (
<MaterialReactTable
columnVirtualizerOptions={{
overscan: 0
}}
columns={columns}
data={data}
enableColumnOrdering
enableColumnVirtualization
/>
);
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ type Person = {
email: string;
firstName: string;
lastName: string;
num: number;
state: string;
};

const columns: MRT_ColumnDef<Person>[] = [
{
accessorKey: 'num',
header: '#',
},
{
accessorKey: 'firstName',
header: 'First Name',
Expand All @@ -49,12 +54,13 @@ const columns: MRT_ColumnDef<Person>[] = [
},
];

const initData = [...Array(100)].map(() => ({
const initData = [...Array(100)].map((_, i) => ({
address: faker.location.streetAddress(),
city: faker.location.city(),
email: faker.internet.email(),
firstName: faker.person.firstName(),
lastName: faker.person.lastName(),
num: i,
state: faker.location.state(),
}));

Expand Down Expand Up @@ -88,7 +94,9 @@ export const RowOrderingEnabled = () => {
export const RowOrderingWithSelect = () => {
const [data, setData] = useState(() => initData);
const [draggingRow, setDraggingRow] = useState<MRT_Row<Person> | null>(null);
const [hoveredRow, setHoveredRow] = useState<MRT_Row<Person> | null>(null);
const [hoveredRow, setHoveredRow] = useState<Partial<MRT_Row<Person>> | null>(
null,
);

return (
<MaterialReactTable
Expand All @@ -103,7 +111,7 @@ export const RowOrderingWithSelect = () => {
onDragEnd: () => {
if (hoveredRow && draggingRow) {
data.splice(
hoveredRow.index,
hoveredRow?.index ?? 0,
0,
data.splice(draggingRow.index, 1)[0],
);
Expand All @@ -124,7 +132,9 @@ export const RowOrderingWithSelect = () => {
export const RowOrderingWithPinning = () => {
const [data, setData] = useState(() => initData);
const [draggingRow, setDraggingRow] = useState<MRT_Row<Person> | null>(null);
const [hoveredRow, setHoveredRow] = useState<MRT_Row<Person> | null>(null);
const [hoveredRow, setHoveredRow] = useState<Partial<MRT_Row<Person>> | null>(
null,
);

return (
<MaterialReactTable
Expand All @@ -138,7 +148,7 @@ export const RowOrderingWithPinning = () => {
onDragEnd: () => {
if (hoveredRow && draggingRow) {
data.splice(
hoveredRow.index,
hoveredRow?.index ?? 0,
0,
data.splice(draggingRow.index, 1)[0],
);
Expand All @@ -159,7 +169,9 @@ export const RowOrderingWithPinning = () => {
export const RowAndColumnOrdering = () => {
const [data, setData] = useState(() => initData);
const [draggingRow, setDraggingRow] = useState<MRT_Row<Person> | null>(null);
const [hoveredRow, setHoveredRow] = useState<MRT_Row<Person> | null>(null);
const [hoveredRow, setHoveredRow] = useState<Partial<MRT_Row<Person>> | null>(
null,
);

return (
<MaterialReactTable
Expand All @@ -174,7 +186,7 @@ export const RowAndColumnOrdering = () => {
onDragEnd: () => {
if (hoveredRow && draggingRow) {
data.splice(
hoveredRow.index,
hoveredRow.index ?? 0,
0,
data.splice(draggingRow.index, 1)[0],
);
Expand All @@ -191,3 +203,32 @@ export const RowAndColumnOrdering = () => {
/>
);
};

export const RowOrderingWithRowVirtualization = () => {
const [data, setData] = useState(() => initData);

return (
<MaterialReactTable
autoResetPageIndex={false}
columns={columns}
data={data}
enablePagination={false}
enableRowOrdering
enableRowVirtualization
enableSorting={false}
muiRowDragHandleProps={({ table }) => ({
onDragEnd: () => {
const { draggingRow, hoveredRow } = table.getState();
if (hoveredRow && draggingRow) {
data.splice(
(hoveredRow as MRT_Row<Person>).index,
0,
data.splice(draggingRow.index, 1)[0],
);
setData([...data]);
}
},
})}
/>
);
};

0 comments on commit ec3a896

Please sign in to comment.