Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: #718 dragend don't fire on virtualization #719

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another scanning of all rows potentially on every render, even if no dragging is occurring or the dragging features are not enabled


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]);
}
},
})}
/>
);
};
Loading