Skip to content

Commit

Permalink
release v2.11.2 - row pinning fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinVandy committed Feb 9, 2024
1 parent 3d33091 commit 3ecdff5
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 158 deletions.
6 changes: 6 additions & 0 deletions apps/material-react-table-docs/pages/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ import Head from 'next/head';

## MRT V2 Changelog

### Version 2.11.3 - 2024-02-08

- Fixed bugs with batch row selection and row pinning together
- Fixed duplicate pinned rows when global filter is present for non-sticky row pinning modes
- Fixed selected row count in toolbar alert banner with sub row selection

### Version 2.11.1 - 2024-02-05

- Fixed bug where new batch row selection feature did not account for `manualPagination`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ const table = useMaterialReactTable({
//clicking anywhere on the row will select it
muiTableBodyRowProps: ({ row, staticRowIndex, table }) => ({
onClick: (event) =>
getMRT_RowSelectionHandler()({ event, row, staticRowIndex, table }), //import this helper function from material-react-table
getMRT_RowSelectionHandler({ row, staticRowIndex, table })(event), //import this helper function from material-react-table
sx: { cursor: 'pointer' },
}),
});
Expand Down
202 changes: 101 additions & 101 deletions apps/material-react-table-docs/public/sitemap-0.xml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/material-react-table/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.11.1",
"version": "2.11.2",
"license": "MIT",
"name": "material-react-table",
"description": "A fully featured Material UI V5 implementation of TanStack React Table V8, written from the ground up in TypeScript.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const MRT_TableBody = <TData extends MRT_RowData>({
.map((r) => r.id);
}, [rowPinning, getRowModel().rows]);

const rows = useMRT_Rows(table, pinnedRowIds);
const rows = useMRT_Rows(table);

const rowVirtualizer = useMRT_RowVirtualizer(table, rows);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type ChangeEvent, type MouseEvent } from 'react';
import { type MouseEvent } from 'react';
import Checkbox, { type CheckboxProps } from '@mui/material/Checkbox';
import Radio, { type RadioProps } from '@mui/material/Radio';
import Tooltip from '@mui/material/Tooltip';
Expand All @@ -11,6 +11,7 @@ import {
import {
getIsRowSelected,
getMRT_RowSelectionHandler,
getMRT_SelectAllHandler,
} from '../../utils/row.utils';
import { getCommonTooltipProps } from '../../utils/style.utils';
import { parseFromValuesOrFunc } from '../../utils/utils';
Expand All @@ -32,22 +33,16 @@ export const MRT_SelectCheckbox = <TData extends MRT_RowData>({
getState,
options: {
enableMultiRowSelection,
enableRowPinning,
localization,
muiSelectAllCheckboxProps,
muiSelectCheckboxProps,
rowPinningDisplayMode,
selectAllMode,
},
refs: { lastSelectedRowId },
} = table;
const { density, isLoading } = getState();

const selectAll = !row;

const isStickySelection =
enableRowPinning && rowPinningDisplayMode?.includes('select');

const allRowsSelected = selectAll
? selectAllMode === 'page'
? table.getIsAllPageRowsSelected()
Expand All @@ -68,17 +63,15 @@ export const MRT_SelectCheckbox = <TData extends MRT_RowData>({
...rest,
};

const onSelectionChange = getMRT_RowSelectionHandler();
const onSelectionChange = row
? getMRT_RowSelectionHandler({
row,
staticRowIndex,
table,
})
: undefined;

const onSelectAllChange = (event: ChangeEvent<HTMLInputElement>) => {
selectAllMode === 'all'
? table.getToggleAllRowsSelectedHandler()(event)
: table.getToggleAllPageRowsSelectedHandler()(event);
if (isStickySelection) {
table.setRowPinning({ bottom: [], top: [] });
}
lastSelectedRowId.current = null;
};
const onSelectAllChange = getMRT_SelectAllHandler({ table });

const commonProps = {
'aria-label': selectAll
Expand All @@ -94,9 +87,7 @@ export const MRT_SelectCheckbox = <TData extends MRT_RowData>({
},
onChange: (event) => {
event.stopPropagation();
row
? onSelectionChange({ event, row, staticRowIndex, table })
: onSelectAllChange(event);
row ? onSelectionChange!(event) : onSelectAllChange(event);
},
size: (density === 'compact' ? 'small' : 'medium') as 'medium' | 'small',
...checkboxProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Chip from '@mui/material/Chip';
import Collapse from '@mui/material/Collapse';
import Stack from '@mui/material/Stack';
import { type MRT_RowData, type MRT_TableInstance } from '../../types';
import { getMRT_SelectAllHandler } from '../../utils/row.utils';
import { parseFromValuesOrFunc } from '../../utils/utils';
import { MRT_SelectCheckbox } from '../inputs/MRT_SelectCheckbox';

Expand Down Expand Up @@ -36,7 +37,7 @@ export const MRT_ToolbarAlertBanner = <TData extends MRT_RowData>({
renderToolbarAlertBannerContent,
rowCount,
},
refs: { lastSelectedRowId, tablePaperRef },
refs: { tablePaperRef },
} = table;
const { density, grouping, rowSelection, showAlertBanner } = getState();

Expand All @@ -51,7 +52,7 @@ export const MRT_ToolbarAlertBanner = <TData extends MRT_RowData>({
table,
});

const totalRowCount = rowCount ?? getPrePaginationRowModel().rows.length;
const totalRowCount = rowCount ?? getPrePaginationRowModel().flatRows.length;

const selectedRowCount = useMemo(
() =>
Expand All @@ -67,10 +68,7 @@ export const MRT_ToolbarAlertBanner = <TData extends MRT_RowData>({
?.replace('{selectedCount}', selectedRowCount.toLocaleString())
?.replace('{rowCount}', totalRowCount.toString())}
<Button
onClick={() => {
table.toggleAllRowsSelected(false);
lastSelectedRowId.current = null;
}}
onClick={(event) => getMRT_SelectAllHandler({ table })(event, false)}
size="small"
sx={{ p: '2px' }}
>
Expand Down
3 changes: 1 addition & 2 deletions packages/material-react-table/src/hooks/useMRT_Rows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { getMRT_Rows } from '../utils/row.utils';

export const useMRT_Rows = <TData extends MRT_RowData>(
table: MRT_TableInstance<TData>,
pinnedRowIds: string[] = [],
): MRT_Row<TData>[] => {
const {
getRowModel,
Expand All @@ -25,7 +24,7 @@ export const useMRT_Rows = <TData extends MRT_RowData>(
} = getState();

const rows = useMemo(
() => getMRT_Rows(table, pinnedRowIds),
() => getMRT_Rows(table),
[
creatingRow,
data,
Expand Down
80 changes: 56 additions & 24 deletions packages/material-react-table/src/utils/row.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import { parseFromValuesOrFunc } from './utils';

export const getMRT_Rows = <TData extends MRT_RowData>(
table: MRT_TableInstance<TData>,
pinnedRowIds: string[] = [],
all?: boolean,
): MRT_Row<TData>[] => {
const {
getBottomRows,
getCenterRows,
getPrePaginationRowModel,
getRowModel,
Expand Down Expand Up @@ -41,21 +39,31 @@ export const getMRT_Rows = <TData extends MRT_RowData>(
: getRowModel().rows
: getCenterRows();
} else {
// fuzzy ranking adjustments
rows = getPrePaginationRowModel().rows.sort((a, b) =>
rankGlobalFuzzy(a, b),
);
if (enablePagination && !manualPagination && !all) {
const start = pagination.pageIndex * pagination.pageSize;
rows = rows.slice(start, start + pagination.pageSize);
}
if (enableRowPinning && !rowPinningDisplayMode?.includes('sticky')) {
// "re-center-ize" the rows (no top or bottom pinned rows unless sticky)
rows = rows.filter((row) => !row.getIsPinned());
}
}
// row pinning adjustments
if (enableRowPinning && rowPinningDisplayMode?.includes('sticky')) {
const centerPinnedRowIds = rows
.filter((row) => row.getIsPinned())
.map((r) => r.id);

rows = [
...getTopRows().filter((row) => !pinnedRowIds.includes(row.id)),
...getTopRows().filter((row) => !centerPinnedRowIds.includes(row.id)),
...rows,
...getBottomRows().filter((row) => !pinnedRowIds.includes(row.id)),
];
}
// blank inserted creating row adjustments
if (
positionCreatingRow !== undefined &&
creatingRow &&
Expand Down Expand Up @@ -135,18 +143,19 @@ export const getIsRowSelected = <TData extends MRT_RowData>({
};

export const getMRT_RowSelectionHandler =
() =>
<TData extends MRT_RowData>({
event,
row,
staticRowIndex = 0,
table,
}: {
event: ChangeEvent<HTMLInputElement> | MouseEvent<HTMLTableRowElement>;
row: MRT_Row<TData>;
staticRowIndex?: number;
table: MRT_TableInstance<TData>;
}) => {
}) =>
(
event: ChangeEvent<HTMLInputElement> | MouseEvent<HTMLTableRowElement>,
value?: boolean,
) => {
const {
getState,
options: {
Expand All @@ -164,13 +173,12 @@ export const getMRT_RowSelectionHandler =

const paginationOffset = manualPagination ? 0 : pageSize * pageIndex;

const isCurrentRowChecked = getIsRowSelected({ row, table });

const isStickySelection =
enableRowPinning && rowPinningDisplayMode?.includes('select');
const wasCurrentRowChecked = getIsRowSelected({ row, table });

// toggle selection of this row
row.getToggleSelectedHandler()(event);
row.toggleSelected(value ?? !wasCurrentRowChecked);

const changedRowIds = new Set<string>([row.id]);

// if shift key is pressed, select all rows between last selected and this one
if (
Expand All @@ -179,7 +187,7 @@ export const getMRT_RowSelectionHandler =
(event as any).nativeEvent.shiftKey &&
lastSelectedRowId.current !== null
) {
const rows = getMRT_Rows(table, undefined, true);
const rows = getMRT_Rows(table, true);

const lastIndex = rows.findIndex(
(r) => r.id === lastSelectedRowId.current,
Expand All @@ -199,9 +207,10 @@ export const getMRT_RowSelectionHandler =

// toggle selection of all rows between last selected and this one
// but only if the last selected row is not the same as the current one
if (isCurrentRowChecked !== isLastIndexChecked) {
if (wasCurrentRowChecked !== isLastIndexChecked) {
for (let i = start; i <= end; i++) {
rows[i].toggleSelected(!isCurrentRowChecked);
rows[i].toggleSelected(!wasCurrentRowChecked);
changedRowIds.add(rows[i].id);
}
}
}
Expand All @@ -215,13 +224,36 @@ export const getMRT_RowSelectionHandler =
row.subRows?.forEach((r) => r.toggleSelected(false));
}

if (isStickySelection) {
row.pin(
!row.getIsPinned() && isCurrentRowChecked
? rowPinningDisplayMode?.includes('bottom')
? 'bottom'
: 'top'
: false,
);
if (enableRowPinning && rowPinningDisplayMode?.includes('select')) {
changedRowIds.forEach((rowId) => {
const rowToTogglePin = table.getRow(rowId);
rowToTogglePin.pin(
!wasCurrentRowChecked //was not previously pinned or selected
? rowPinningDisplayMode?.includes('bottom')
? 'bottom'
: 'top'
: false,
);
});
}
};

export const getMRT_SelectAllHandler =
<TData extends MRT_RowData>({ table }: { table: MRT_TableInstance<TData> }) =>
(
event: ChangeEvent<HTMLInputElement> | MouseEvent<HTMLButtonElement>,
value?: boolean,
) => {
const {
options: { enableRowPinning, rowPinningDisplayMode, selectAllMode },
refs: { lastSelectedRowId },
} = table;

selectAllMode === 'all'
? table.toggleAllRowsSelected(value ?? (event as any).target.checked)
: table.toggleAllPageRowsSelected(value ?? (event as any).target.checked);
if (enableRowPinning && rowPinningDisplayMode?.includes('select')) {
table.setRowPinning({ bottom: [], top: [] });
}
lastSelectedRowId.current = null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,6 @@ export const GroupingColumnsSetState = () => {
columns={columns}
data={data}
enableGrouping
state={{ columnOrder: columns.map((c) => c.accessorKey as string) }}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export const RowPinningTopMode = () => (
data={data}
enablePagination={false}
enableRowPinning
keepPinnedRows={false}
muiTableContainerProps={{
sx: {
maxHeight: '600px',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export const SelectionEnabledWithRowClick = () => (
enableRowSelection
muiTableBodyRowProps={({ row, staticRowIndex, table }) => ({
onClick: (event) =>
getMRT_RowSelectionHandler()({ event, row, staticRowIndex, table }),
getMRT_RowSelectionHandler({ row, staticRowIndex, table })(event),
style: {
cursor: 'pointer',
userSelect: 'none',
Expand Down

0 comments on commit 3ecdff5

Please sign in to comment.