Skip to content

Commit

Permalink
release v2.0.0-alpha.4 - new pagination ui
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinVandy committed Oct 7, 2023
1 parent 2402fdb commit 577a739
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 102 deletions.
Expand Up @@ -151,7 +151,14 @@ const Example = () => {
enableRowActions: true,
enableRowSelection: true,
initialState: { showColumnFilters: true, showGlobalFilter: true },
paginationDisplayMode: 'pages',
positionToolbarAlertBanner: 'bottom',
muiTablePaginationProps: {
color: 'secondary',
rowsPerPageOptions: [10, 20, 30],
shape: 'rounded',
variant: 'outlined'
},
renderDetailPanel: ({ row }) => (
<Box
sx={{
Expand Down
2 changes: 1 addition & 1 deletion packages/material-react-table/package.json
@@ -1,5 +1,5 @@
{
"version": "2.0.0-alpha.3",
"version": "2.0.0-alpha.4",
"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
12 changes: 12 additions & 0 deletions packages/material-react-table/src/icons.ts
@@ -1,6 +1,8 @@
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
import ArrowRightIcon from '@mui/icons-material/ArrowRight';
import CancelIcon from '@mui/icons-material/Cancel';
import ChevronLefIcon from '@mui/icons-material/ChevronLeft';
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
import ClearAllIcon from '@mui/icons-material/ClearAll';
import CloseIcon from '@mui/icons-material/Close';
import DensityLargeIcon from '@mui/icons-material/DensityLarge';
Expand All @@ -13,9 +15,11 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import FilterAltIcon from '@mui/icons-material/FilterAlt';
import FilterListIcon from '@mui/icons-material/FilterList';
import FilterListOffIcon from '@mui/icons-material/FilterListOff';
import FirstPageIcon from '@mui/icons-material/FirstPage';
import FullscreenIcon from '@mui/icons-material/Fullscreen';
import FullscreenExitIcon from '@mui/icons-material/FullscreenExit';
import KeyboardDoubleArrowDownIcon from '@mui/icons-material/KeyboardDoubleArrowDown';
import LastPageIcon from '@mui/icons-material/LastPage';
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
import MoreVertIcon from '@mui/icons-material/MoreVert';
import PushPinIcon from '@mui/icons-material/PushPin';
Expand All @@ -31,6 +35,8 @@ export interface MRT_Icons {
ArrowDownwardIcon: any;
ArrowRightIcon: any;
CancelIcon: any;
ChevronLefIcon: any;
ChevronRightIcon: any;
ClearAllIcon: any;
CloseIcon: any;
DensityLargeIcon: any;
Expand All @@ -43,9 +49,11 @@ export interface MRT_Icons {
FilterAltIcon: any;
FilterListIcon: any;
FilterListOffIcon: any;
FirstPageIcon?: any;
FullscreenExitIcon: any;
FullscreenIcon: any;
KeyboardDoubleArrowDownIcon: any;
LastPageIcon?: any;
MoreHorizIcon: any;
MoreVertIcon: any;
PushPinIcon: any;
Expand All @@ -62,6 +70,8 @@ export const MRT_Default_Icons: MRT_Icons = {
ArrowDownwardIcon,
ArrowRightIcon,
CancelIcon,
ChevronLefIcon,
ChevronRightIcon,
ClearAllIcon,
CloseIcon,
DensityLargeIcon,
Expand All @@ -74,9 +84,11 @@ export const MRT_Default_Icons: MRT_Icons = {
FilterAltIcon,
FilterListIcon,
FilterListOffIcon,
FirstPageIcon,
FullscreenExitIcon,
FullscreenIcon,
KeyboardDoubleArrowDownIcon,
LastPageIcon,
MoreHorizIcon,
MoreVertIcon,
PushPinIcon,
Expand Down
191 changes: 124 additions & 67 deletions packages/material-react-table/src/toolbar/MRT_TablePagination.tsx
@@ -1,14 +1,22 @@
import { type ChangeEvent } from 'react';
import TablePagination from '@mui/material/TablePagination';
import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import Pagination, { type PaginationProps } from '@mui/material/Pagination';
import PaginationItem from '@mui/material/PaginationItem';
import Select from '@mui/material/Select';
import Typography from '@mui/material/Typography';
import { parseFromValuesOrFunc } from '../column.utils';
import { type MRT_TableInstance } from '../types';

interface Props<TData extends Record<string, any>> {
const defaultPageSizeOptions = [5, 10, 15, 20, 25, 30, 50, 100];

interface Props<TData extends Record<string, any> = {}> {
position?: 'bottom' | 'top';
table: MRT_TableInstance<TData>;
}

export const MRT_TablePagination = <TData extends Record<string, any>>({
export const MRT_TablePagination = <TData extends Record<string, any> = {}>({
position = 'bottom',
table,
}: Props<TData>) => {
Expand All @@ -17,8 +25,10 @@ export const MRT_TablePagination = <TData extends Record<string, any>>({
getState,
options: {
enableToolbarInternalActions,
icons: { ChevronLefIcon, ChevronRightIcon, FirstPageIcon, LastPageIcon },
localization,
muiTablePaginationProps,
paginationDisplayMode,
rowCount,
},
setPageIndex,
Expand All @@ -29,80 +39,127 @@ export const MRT_TablePagination = <TData extends Record<string, any>>({
showGlobalFilter,
} = getState();

const totalRowCount = rowCount ?? getPrePaginationRowModel().rows.length;
const showFirstLastPageButtons = totalRowCount / pageSize > 2;

const tablePaginationProps = parseFromValuesOrFunc(muiTablePaginationProps, {
const paginationProps = parseFromValuesOrFunc(muiTablePaginationProps, {
table,
});

const handleChangeRowsPerPage = (event: ChangeEvent<HTMLInputElement>) => {
setPageSize(+event.target.value);
};
const totalRowCount = rowCount ?? getPrePaginationRowModel().rows.length;
const numberOfPages = Math.ceil(totalRowCount / pageSize);
const showFirstLastPageButtons = numberOfPages > 2;
const showFirstButton =
showFirstLastPageButtons && paginationProps?.showFirstButton !== false;
const showLastButton =
showFirstLastPageButtons && paginationProps?.showLastButton !== false;
const firstRowIndex = pageIndex * pageSize;
const lastRowIndex = Math.min(pageIndex * pageSize + pageSize, totalRowCount);

return (
<TablePagination
component="div"
count={totalRowCount}
getItemAriaLabel={(type) =>
type === 'first'
? localization.goToFirstPage
: type === 'last'
? localization.goToLastPage
: type === 'next'
? localization.goToNextPage
: localization.goToPreviousPage
}
labelDisplayedRows={({ count, from, to }) =>
`${from}-${to} ${localization.of} ${count}`
}
labelRowsPerPage={localization.rowsPerPage}
onPageChange={(_: any, newPage: number) => setPageIndex(newPage)}
onRowsPerPageChange={handleChangeRowsPerPage}
page={Math.max(
Math.min(pageIndex, Math.ceil(totalRowCount / pageSize) - 1),
0,
)}
rowsPerPage={pageSize}
rowsPerPageOptions={[5, 10, 15, 20, 25, 30, 50, 100]}
showFirstButton={showFirstLastPageButtons}
showLastButton={showFirstLastPageButtons}
{...tablePaginationProps}
SelectProps={{
MenuProps: { MenuListProps: { disablePadding: true }, sx: { m: 0 } },
sx: { m: '0 1rem 0 1ch' },
...tablePaginationProps?.SelectProps,
}}
sx={(theme) => ({
'& . MuiTablePagination-select': {
m: '0 1px',
},
'& .MuiTablePagination-actions': {
m: '0 1px',
},
'& .MuiTablePagination-displayedRows': {
m: '0 1px',
},
'& .MuiTablePagination-selectLabel': {
m: '0 -1px',
},
'& .MuiTablePagination-toolbar': {
alignItems: 'center',
display: 'flex',
},
'&. MuiInputBase-root': {
m: '0 1px',
},
<Box
sx={{
alignItems: 'center',
display: 'flex',
gap: '8px',
justifyContent: 'space-between',
mt:
position === 'top' &&
enableToolbarInternalActions &&
!showGlobalFilter
? '3.5rem'
? '3rem'
: undefined,
position: 'relative',
px: '4px',
py: '12px',
zIndex: 2,
...(parseFromValuesOrFunc(tablePaginationProps?.sx, theme) as any),
})}
/>
}}
>
{paginationProps?.showRowsPerPage !== false && (
<Box sx={{ alignItems: 'center', display: 'flex', gap: '8px' }}>
<InputLabel htmlFor="mrt-rows-per-page" sx={{ mb: 0 }}>
{localization.rowsPerPage}
</InputLabel>
<Select
id="mrt-rows-per-page"
label={localization.rowsPerPage}
onChange={(event) => setPageSize(+event.target.value)}
sx={{ '&::before': { border: 'none' }, mb: 0 }}
value={pageSize}
variant="standard"
>
{defaultPageSizeOptions.map((value) => (
<MenuItem key={value} sx={{ m: 0 }} value={value}>
{value}
</MenuItem>
))}
</Select>
</Box>
)}
{paginationDisplayMode === 'pages' ? (
<Pagination
count={numberOfPages}
onChange={(_e, newPageIndex) => setPageIndex(newPageIndex - 1)}
page={pageIndex + 1}
renderItem={(item) => (
<PaginationItem
slots={{
first: FirstPageIcon,
last: LastPageIcon,
next: ChevronRightIcon,
previous: ChevronLefIcon,
}}
{...item}
/>
)}
showFirstButton={showFirstButton}
showLastButton={showLastButton}
{...(paginationProps as PaginationProps)}
/>
) : paginationDisplayMode === 'default' ? (
<>
<Typography mb="0" mx="8px" variant="body2">{`${
lastRowIndex === 0 ? 0 : (firstRowIndex + 1).toLocaleString()
}-${lastRowIndex.toLocaleString()} ${
localization.of
} ${totalRowCount.toLocaleString()}`}</Typography>
<Box gap="xs">
{showFirstButton && (
<IconButton
aria-label={localization.goToFirstPage}
disabled={pageIndex <= 0}
onClick={() => setPageIndex(0)}
size="small"
>
<FirstPageIcon />
</IconButton>
)}
<IconButton
aria-label={localization.goToPreviousPage}
disabled={pageIndex <= 0}
onClick={() => setPageIndex(pageIndex - 1)}
size="small"
>
<ChevronLefIcon />
</IconButton>
<IconButton
aria-label={localization.goToNextPage}
disabled={lastRowIndex >= totalRowCount}
onClick={() => setPageIndex(pageIndex + 1)}
size="small"
>
<ChevronRightIcon />
</IconButton>
{showLastButton && (
<IconButton
aria-label={localization.goToLastPage}
disabled={lastRowIndex >= totalRowCount}
onClick={() => setPageIndex(numberOfPages - 1)}
size="small"
>
<LastPageIcon />
</IconButton>
)}
</Box>
</>
) : null}
</Box>
);
};
20 changes: 14 additions & 6 deletions packages/material-react-table/src/types.ts
Expand Up @@ -38,14 +38,15 @@ import {
type Virtualizer,
type VirtualizerOptions,
} from '@tanstack/react-virtual';
import { type AutocompleteProps } from '@mui/material';
import { type AlertProps } from '@mui/material/Alert';
import { type AutocompleteProps } from '@mui/material/Autocomplete';
import { type ButtonProps } from '@mui/material/Button';
import { type CheckboxProps } from '@mui/material/Checkbox';
import { type ChipProps } from '@mui/material/Chip';
import { type DialogProps } from '@mui/material/Dialog';
import { type IconButtonProps } from '@mui/material/IconButton';
import { type LinearProgressProps } from '@mui/material/LinearProgress';
import { type PaginationProps } from '@mui/material/Pagination';
import { type PaperProps } from '@mui/material/Paper';
import { type RadioProps } from '@mui/material/Radio';
import { type SkeletonProps } from '@mui/material/Skeleton';
Expand All @@ -56,7 +57,6 @@ import { type TableCellProps } from '@mui/material/TableCell';
import { type TableContainerProps } from '@mui/material/TableContainer';
import { type TableFooterProps } from '@mui/material/TableFooter';
import { type TableHeadProps } from '@mui/material/TableHead';
import { type TablePaginationProps } from '@mui/material/TablePagination';
import { type TableRowProps } from '@mui/material/TableRow';
import { type TextFieldProps } from '@mui/material/TextField';
import { type ToolbarProps } from '@mui/material/Toolbar';
Expand Down Expand Up @@ -917,10 +917,18 @@ export type MRT_TableOptions<TData extends Record<string, any>> = Omit<
}) => TableRowProps)
| TableRowProps;
muiTablePaginationProps?:
| ((props: {
table: MRT_TableInstance<TData>;
}) => Partial<Omit<TablePaginationProps, 'rowsPerPage'>>)
| Partial<Omit<TablePaginationProps, 'rowsPerPage'>>;
| ((props: { table: MRT_TableInstance<TData> }) => Partial<
PaginationProps & {
rowsPerPageOptions?: number[];
showRowsPerPage?: boolean;
}
>)
| Partial<
PaginationProps & {
rowsPerPageOptions?: number[];
showRowsPerPage?: boolean;
}
>;
muiTablePaperProps?:
| ((props: { table: MRT_TableInstance<TData> }) => PaperProps)
| PaperProps;
Expand Down

0 comments on commit 577a739

Please sign in to comment.