mui-datatables-updated 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,25 +6,47 @@ import TableCell from '@mui/material/TableCell';
6
6
  import TableContainer from '@mui/material/TableContainer';
7
7
  import TablePagination from '@mui/material/TablePagination';
8
8
  import TableRow from '@mui/material/TableRow';
9
- import React, { useCallback } from 'react';
10
- import { EnhancedTableHead, HeadCell } from './TableHead';
9
+ import React, { useCallback, useRef } from 'react';
10
+ import { useReactToPrint } from "react-to-print";
11
+ import { EnhancedTableHead } from './TableHead';
11
12
  import { CustomSelectedToolbarProps, EnhancedTableToolbar } from './Toolbar';
12
13
  import { getComparator, Order } from './utils';
14
+ import { LabelDisplayedRowsArgs } from '@mui/material/TablePagination';
13
15
 
14
- export interface CustomCell<T> {
15
- id: keyof T;
16
- render: (row: T, key: keyof T) => React.ReactNode;
16
+ export interface Column {
17
+ name: string;
18
+ label?: string;
19
+ options?: {
20
+ customBodyRender?: (value: any) => React.ReactNode;
21
+ filter?: boolean;
22
+ sort?: boolean;
23
+ }
24
+ }
25
+
26
+ export interface Options {
27
+ translations?: {
28
+ filterTooltip?: string;
29
+ searchTooltip?: string;
30
+ downloadTooltip?: string;
31
+ printTooltip?: string;
32
+ filtersTitle?: string;
33
+ resetButtonText?: string;
34
+ rowsPerPageText?: string;
35
+ searchPlaceholder?: string;
36
+ selectedTextRenderer?: (selected: number) => string;
37
+ labelDisplayedRows?: ({ from, to, count }: LabelDisplayedRowsArgs) => string;
38
+ }
17
39
  }
18
40
 
19
41
  export interface EnhancedTableProps<T extends object> extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
20
42
  title: string;
21
43
  data: T[];
22
- headCells?: HeadCell<T>[];
23
44
  deactivateSelect?: boolean;
24
45
  defaultOrderBy?: string;
25
46
  defaultOrder?: Order;
26
47
  excludedColumns?: (keyof T)[];
27
- customCells?: CustomCell<T>[];
48
+ columns?: Column[];
49
+ options?: Options;
28
50
  CustomToolbar?: React.FC;
29
51
  CustomSelectedToolbar?: React.FC<CustomSelectedToolbarProps<T>>;
30
52
  }
@@ -37,7 +59,6 @@ interface EnhancedTableState<T> {
37
59
  rowsPerPage: number;
38
60
  searchQuery: string;
39
61
  filterFunc: (row: T) => boolean;
40
- filteredData: T[];
41
62
  currentData: T[];
42
63
  visibleRows: T[];
43
64
  emptyRows: number;
@@ -46,16 +67,18 @@ interface EnhancedTableState<T> {
46
67
  export const MUITable = <T extends object>({
47
68
  title,
48
69
  data,
49
- headCells: passedHeadCells,
50
70
  deactivateSelect,
51
71
  defaultOrderBy,
52
72
  defaultOrder,
53
73
  excludedColumns,
54
- customCells,
74
+ columns: passedColumns,
55
75
  CustomToolbar,
56
76
  CustomSelectedToolbar,
77
+ options,
57
78
  ...rest
58
79
  }: EnhancedTableProps<T>) => {
80
+ const tableRef = useRef<HTMLDivElement>(null);
81
+ const reactToPrintFn = useReactToPrint({ contentRef: tableRef });
59
82
 
60
83
  const getDefaultOrderByKey = React.useCallback((): keyof T => {
61
84
  if (data.length === 0) return "id" as keyof T;
@@ -83,25 +106,23 @@ export const MUITable = <T extends object>({
83
106
  rowsPerPage: 5,
84
107
  searchQuery: "",
85
108
  filterFunc: () => true,
86
- filteredData: data,
87
109
  currentData: data,
88
110
  visibleRows: data,
89
111
  emptyRows: 0,
90
112
  };
91
113
  });
92
114
 
93
- const generateHeadCells = React.useCallback((): HeadCell<T>[] => {
115
+ const generateColumns = React.useCallback((): Column[] => {
94
116
  if (data.length === 0) return [];
95
117
  return Object.keys(data[0] as object)
96
118
  .filter((key) => !(excludedColumns || []).includes(key as keyof T))
97
119
  .map((key) => ({
98
- id: key as keyof T,
120
+ name: key,
99
121
  label: key.charAt(0).toUpperCase() + key.slice(1),
100
- numeric: typeof data[0][key as keyof T] === 'number',
101
122
  }));
102
123
  }, [data, excludedColumns]);
103
124
 
104
- const headCells = passedHeadCells || generateHeadCells();
125
+ const columns = passedColumns || generateColumns();
105
126
 
106
127
  const handleSearch = (query: string) => {
107
128
  setState((prevState) => ({ ...prevState, searchQuery: query.toLowerCase() }));
@@ -112,46 +133,49 @@ export const MUITable = <T extends object>({
112
133
  setState((prevState) => ({ ...prevState, orderBy: orderByKey }));
113
134
  }, [data, getDefaultOrderByKey]);
114
135
 
115
- // Filter data based on applied filters
116
- React.useEffect(() => {
117
- const newFilteredData = data.filter(state.filterFunc);
118
-
119
- setState((prevState) => ({
120
- ...prevState,
121
- filteredData: newFilteredData,
122
- currentData: newFilteredData,
123
- }));
124
- }, [data, state.filterFunc]);
125
-
126
- // Search data based on search query
136
+ // Data sorting, filtering, and pagination
127
137
  React.useEffect(() => {
128
- const searchResults = state.filteredData.filter((row) =>
129
- Object.values(row as Record<string, unknown>).some((value) =>
130
- typeof value === 'string' && value.toLowerCase().includes(state.searchQuery)
138
+ // Apply filters, search query, and sort data
139
+ const sortedData = [...data]
140
+ .filter(state.filterFunc)
141
+ .filter((row) =>
142
+ Object.values(row as Record<string, unknown>).some((value) =>
143
+ typeof value === "string" &&
144
+ value.toLowerCase().includes(state.searchQuery)
145
+ )
131
146
  )
132
- );
133
- setState((prevState) => ({ ...prevState, currentData: searchResults }));
134
- }, [state.filteredData, state.searchQuery]);
147
+ .sort(getComparator<T, keyof T>(state.order, state.orderBy));
135
148
 
136
- // Sort and paginate data to display TablePagination and visible rows respectively
137
- React.useEffect(() => {
138
- const sortedData = [...state.currentData].sort(
139
- getComparator<T, keyof T>(state.order, state.orderBy)
140
- );
149
+ // Paginate the processed data
150
+ const startIndex = state.page * state.rowsPerPage;
141
151
  const paginatedData = sortedData.slice(
142
- state.page * state.rowsPerPage,
143
- state.page * state.rowsPerPage + state.rowsPerPage
152
+ startIndex,
153
+ startIndex + state.rowsPerPage
144
154
  );
155
+
145
156
  const calculatedEmptyRows = Math.max(
146
157
  0,
147
- (1 + state.page) * state.rowsPerPage - state.currentData.length
158
+ (1 + state.page) * state.rowsPerPage - sortedData.length
148
159
  );
160
+
149
161
  setState((prevState) => ({
150
162
  ...prevState,
151
163
  visibleRows: paginatedData,
152
164
  emptyRows: calculatedEmptyRows,
165
+ selected: prevState.selected.filter((selectedRow) =>
166
+ data.includes(selectedRow)
167
+ ),
153
168
  }));
154
- }, [state.currentData, state.order, state.orderBy, state.page, state.rowsPerPage]);
169
+ }, [
170
+ state.filterFunc,
171
+ state.order,
172
+ state.orderBy,
173
+ state.page,
174
+ state.rowsPerPage,
175
+ state.searchQuery,
176
+ data,
177
+ ]);
178
+
155
179
 
156
180
  // Remove selected rows deleted from the data to prevent stale selected state
157
181
  React.useEffect(() => {
@@ -217,7 +241,7 @@ export const MUITable = <T extends object>({
217
241
  }, []);
218
242
 
219
243
  return (
220
- <div {...rest}>
244
+ <div {...rest} ref={tableRef}>
221
245
  <Paper sx={{ width: '100%', mb: 2 }}>
222
246
  <EnhancedTableToolbar
223
247
  title={title}
@@ -225,10 +249,12 @@ export const MUITable = <T extends object>({
225
249
  selected={state.selected}
226
250
  onFilterChange={handleFilterChange}
227
251
  onSearch={handleSearch}
228
- headCells={headCells}
252
+ printFn={reactToPrintFn}
253
+ columns={columns}
229
254
  CustomToolbar={CustomToolbar}
230
255
  CustomSelectedToolbar={CustomSelectedToolbar}
231
256
  data={data}
257
+ options={options}
232
258
  />
233
259
  <TableContainer>
234
260
  <Table
@@ -237,7 +263,7 @@ export const MUITable = <T extends object>({
237
263
  size="small"
238
264
  >
239
265
  <EnhancedTableHead
240
- headCells={headCells}
266
+ columns={columns}
241
267
  numSelected={state.selected.length}
242
268
  order={state.order}
243
269
  orderBy={state.orderBy}
@@ -248,7 +274,6 @@ export const MUITable = <T extends object>({
248
274
  />
249
275
  <TableBody>
250
276
  {state.visibleRows.map((row, index) => {
251
- const selectionKey = state.orderBy;
252
277
  const isItemSelected = state.selected.some((selectedRow) => selectedRow === row);
253
278
  const labelId = `enhanced-table-checkbox-${index}`;
254
279
 
@@ -259,7 +284,7 @@ export const MUITable = <T extends object>({
259
284
  role="checkbox"
260
285
  aria-checked={isItemSelected}
261
286
  tabIndex={-1}
262
- key={String(row[selectionKey])}
287
+ key={index}
263
288
  selected={isItemSelected}
264
289
  sx={{ cursor: 'pointer' }}
265
290
  >
@@ -274,20 +299,17 @@ export const MUITable = <T extends object>({
274
299
  />
275
300
  </TableCell>
276
301
  )}
277
- {headCells.map((headCell, cellIndex) => (
302
+ {columns.map((column, cellIndex) => (
278
303
  <TableCell
279
- key={String(headCell.id)}
304
+ key={String(column.name)}
280
305
  component={cellIndex === 0 ? "th" : undefined}
281
306
  id={cellIndex === 0 ? labelId : undefined}
282
307
  scope={cellIndex === 0 ? "row" : undefined}
283
308
  padding="normal"
284
309
  >
285
- {customCells &&
286
- customCells.some((renderer) => renderer.id === headCell.id)
287
- ? customCells
288
- .find((renderer) => renderer.id === headCell.id)
289
- ?.render(row, headCell.id)
290
- : String(row[headCell.id])}
310
+ {column.options?.customBodyRender
311
+ ? column.options.customBodyRender((row as Record<string, any>)[column.name])
312
+ : String((row as Record<string, any>)[column.name])}
291
313
  </TableCell>
292
314
  ))}
293
315
  </TableRow>
@@ -299,7 +321,7 @@ export const MUITable = <T extends object>({
299
321
  height: 33 * state.emptyRows,
300
322
  }}
301
323
  >
302
- <TableCell colSpan={headCells.length + 1} />
324
+ <TableCell colSpan={columns.length + 1} />
303
325
  </TableRow>
304
326
  )}
305
327
  </TableBody>
@@ -313,6 +335,8 @@ export const MUITable = <T extends object>({
313
335
  page={state.page}
314
336
  onPageChange={handleChangePage}
315
337
  onRowsPerPageChange={handleChangeRowsPerPage}
338
+ labelRowsPerPage={options?.translations?.rowsPerPageText || "Rows per page"}
339
+ labelDisplayedRows={options?.translations?.labelDisplayedRows || (({ from, to, count }) => `${from}-${to} of ${count}`)}
316
340
  />
317
341
  </Paper>
318
342
  </div>
@@ -5,14 +5,9 @@ import TableHead from '@mui/material/TableHead';
5
5
  import TableRow from '@mui/material/TableRow';
6
6
  import TableSortLabel from '@mui/material/TableSortLabel';
7
7
  import { visuallyHidden } from '@mui/utils';
8
+ import { Column } from './MUITable';
8
9
  import { Order } from './utils';
9
10
 
10
- export interface HeadCell<T> {
11
- id: keyof T;
12
- label: string;
13
- numeric: boolean;
14
- }
15
-
16
11
  interface EnhancedTableProps<T> {
17
12
  numSelected: number;
18
13
  onRequestSort: (event: React.MouseEvent<unknown>, property: keyof T) => void;
@@ -20,7 +15,7 @@ interface EnhancedTableProps<T> {
20
15
  order: Order;
21
16
  orderBy: keyof T;
22
17
  rowCount: number;
23
- headCells: HeadCell<T>[];
18
+ columns: Column[];
24
19
  deactivateSelectAll?: boolean;
25
20
  }
26
21
 
@@ -31,7 +26,7 @@ export function EnhancedTableHead<T>({
31
26
  numSelected,
32
27
  rowCount,
33
28
  onRequestSort,
34
- headCells,
29
+ columns,
35
30
  deactivateSelectAll,
36
31
  }: EnhancedTableProps<T>) {
37
32
  const createSortHandler =
@@ -55,25 +50,29 @@ export function EnhancedTableHead<T>({
55
50
  />
56
51
  </TableCell>
57
52
  }
58
- {headCells.map((headCell) => (
53
+ {columns.map((column) => (
59
54
  <TableCell
60
- key={String(headCell.id)}
55
+ key={String(column.name)}
61
56
  padding='normal'
62
- sortDirection={orderBy === headCell.id ? order : false}
57
+ sortDirection={orderBy === column.name ? order : false}
63
58
  >
64
- <TableSortLabel
65
- active={orderBy === headCell.id}
66
- direction={orderBy === headCell.id ? order : 'asc'}
67
- onClick={createSortHandler(headCell.id)}
68
- sx={{ fontWeight: 'bold' }}
69
- >
70
- {headCell.label}
71
- {orderBy === headCell.id ? (
72
- <Box component="span" sx={visuallyHidden}>
73
- {order === 'desc' ? 'sorted descending' : 'sorted ascending'}
74
- </Box>
75
- ) : null}
76
- </TableSortLabel>
59
+ {column.options?.sort !== false ? (
60
+ <TableSortLabel
61
+ active={orderBy === column.name}
62
+ direction={orderBy === column.name ? order : 'asc'}
63
+ onClick={createSortHandler(column.name as keyof T)}
64
+ sx={{ fontWeight: 'bold' }}
65
+ >
66
+ {column.label}
67
+ {orderBy === column.name ? (
68
+ <Box component="span" sx={visuallyHidden}>
69
+ {order === 'desc' ? 'sorted descending' : 'sorted ascending'}
70
+ </Box>
71
+ ) : null}
72
+ </TableSortLabel>
73
+ ) : (
74
+ <span style={{ fontWeight: 700 }}>{column.label}</span>
75
+ )}
77
76
  </TableCell>
78
77
  ))}
79
78
  </TableRow>
@@ -1,10 +1,11 @@
1
+ import { Close, CloudDownload, Print } from "@mui/icons-material";
1
2
  import FilterListIcon from "@mui/icons-material/FilterList";
2
3
  import SearchIcon from "@mui/icons-material/Search";
3
- import { Box, Button, Checkbox, IconButton, InputBase, Popover, Slider, Stack, Toolbar, Tooltip, Typography } from "@mui/material";
4
+ import { Box, Button, Checkbox, IconButton, Popover, Slider, Stack, TextField, Toolbar, Tooltip, Typography } from "@mui/material";
4
5
  import { alpha } from "@mui/material/styles";
5
6
  import React, { useEffect, useState } from "react";
6
- import { Close } from "@mui/icons-material";
7
- import { HeadCell } from "./TableHead";
7
+ import { Column, Options } from "./MUITable";
8
+ import { UseReactToPrintFn } from "react-to-print";
8
9
 
9
10
  interface Filter {
10
11
  key: string;
@@ -30,24 +31,53 @@ interface EnhancedTableToolbarProps<T> {
30
31
  selected: readonly T[];
31
32
  onFilterChange: (filterFunc: (row: T) => boolean) => void;
32
33
  onSearch: (query: string) => void;
33
- headCells: HeadCell<T>[];
34
+ printFn: UseReactToPrintFn;
35
+ columns: Column[];
34
36
  CustomToolbar?: React.FC;
35
37
  CustomSelectedToolbar?: React.FC<CustomSelectedToolbarProps<T>>;
36
38
  data?: T[];
39
+ options?: Options;
37
40
  }
38
41
 
39
42
  export function EnhancedTableToolbar<T>(props: EnhancedTableToolbarProps<T>) {
40
- const { title, numSelected, selected, onFilterChange, onSearch, headCells, CustomToolbar, CustomSelectedToolbar, data } = props;
43
+ const { title, numSelected, selected, onFilterChange, onSearch, printFn, columns, CustomToolbar, CustomSelectedToolbar, data, options } = props;
41
44
 
42
45
  const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
43
46
  const [filters, setFilters] = useState<Filter[]>([]);
44
47
  const [filterConfig, setFilterConfig] = useState<FilterConfig[]>([]);
45
48
  // rest value to force re-render of filters
46
49
  const [resetCounter, setResetCounter] = useState(0);
50
+ const [openSearch, setOpenSearch] = useState(false);
51
+
52
+ function downloadCSV(data: Record<string, any>[], filename: string = "data.csv"): void {
53
+ // Base case
54
+ if (data.length === 0) {
55
+ console.warn("No data to export.");
56
+ return;
57
+ }
58
+
59
+ // Create CSV content
60
+ const headers = Object.keys(data[0] as Record<string, any>);
61
+ const csvRows = data.map(obj =>
62
+ headers.map(field => JSON.stringify(obj[field] ?? "")).join(",")
63
+ );
64
+ const csvContent = [headers.join(","), ...csvRows].join("\n");
65
+
66
+ // Create Blob and download
67
+ const blob = new Blob([csvContent], { type: "text/csv" });
68
+ const link = document.createElement("a");
69
+ link.href = URL.createObjectURL(blob);
70
+ link.download = filename;
71
+ document.body.appendChild(link);
72
+ link.click();
73
+ document.body.removeChild(link);
74
+ URL.revokeObjectURL(link.href);
75
+ }
47
76
 
48
77
  useEffect(() => {
49
78
  if (data && data.length > 0) {
50
- const inferredConfig = Object.keys(data[0] as object).map((key: string) => {
79
+ const inferredConfig = columns.map((column) => {
80
+ const key = column.name;
51
81
  const values = data.map((row) => (row as Record<string, any>)[key]);
52
82
  const isNumber = values.every((val) => typeof val === "number");
53
83
  const inferredType = isNumber ? "number" : typeof values[0] === "boolean" ? "boolean" : "string";
@@ -60,7 +90,7 @@ export function EnhancedTableToolbar<T>(props: EnhancedTableToolbarProps<T>) {
60
90
  });
61
91
  setFilterConfig(inferredConfig);
62
92
  }
63
- }, [data]);
93
+ }, [data, columns]);
64
94
 
65
95
  useEffect(() => {
66
96
  const newFilterFunc = (row: T) => {
@@ -91,6 +121,10 @@ export function EnhancedTableToolbar<T>(props: EnhancedTableToolbarProps<T>) {
91
121
  setAnchorEl(null);
92
122
  };
93
123
 
124
+ const handleSearchChange = () => {
125
+ setOpenSearch((prev) => !prev);
126
+ };
127
+
94
128
  const open = Boolean(anchorEl);
95
129
 
96
130
  const getFilter = (key: string): Filter | undefined =>
@@ -137,11 +171,8 @@ export function EnhancedTableToolbar<T>(props: EnhancedTableToolbarProps<T>) {
137
171
  return (
138
172
  <Toolbar
139
173
  sx={[
140
- { pl: { sm: 2 }, pr: { sm: 1 } },
141
- numSelected > 0 && {
142
- bgcolor: (theme) =>
143
- alpha(theme.palette.primary.main, theme.palette.action.activatedOpacity),
144
- },
174
+ { px: { sm: 2 }, borderBottom: 1, borderColor: "divider" },
175
+ numSelected > 0 && { bgcolor: (theme) => alpha(theme.palette.primary.main, theme.palette.action.activatedOpacity) },
145
176
  ]}
146
177
  >
147
178
  {numSelected > 0 ? (
@@ -152,7 +183,9 @@ export function EnhancedTableToolbar<T>(props: EnhancedTableToolbarProps<T>) {
152
183
  variant="subtitle1"
153
184
  component="div"
154
185
  >
155
- {numSelected} selected
186
+ {options?.translations?.selectedTextRenderer
187
+ ? options.translations.selectedTextRenderer(numSelected)
188
+ : `${numSelected} selected`}
156
189
  </Typography>
157
190
  {CustomSelectedToolbar && (
158
191
  <CustomSelectedToolbar data={data} selected={selected} />
@@ -165,39 +198,58 @@ export function EnhancedTableToolbar<T>(props: EnhancedTableToolbarProps<T>) {
165
198
  width="100%"
166
199
  alignItems="center"
167
200
  >
168
- <Typography
169
- sx={{ flex: "1 1 100%", alignContent: "center", paddingLeft: 1 }}
170
- variant="h6"
171
- id="tableTitle"
172
- component="div"
173
- >
174
- {title}
175
- </Typography>
176
- <Box
177
- sx={{
178
- flexGrow: 1,
179
- display: "flex",
180
- alignItems: "center",
181
- border: 1,
182
- borderColor: "lightgray",
183
- borderRadius: 1,
184
- }}
185
- >
186
- <InputBase
187
- placeholder="Search…"
188
- onChange={(e) => onSearch(e.target.value)}
189
- sx={{ marginLeft: 2, flex: 1, width: 180 }}
190
- />
191
- <IconButton>
201
+ {openSearch ? (
202
+ <Stack direction="row" alignItems="center">
192
203
  <SearchIcon />
193
- </IconButton>
194
- </Box>
195
- <Tooltip title="Filter list">
196
- <IconButton onClick={handleOpen}>
197
- <FilterListIcon />
198
- </IconButton>
199
- </Tooltip>
200
- {CustomToolbar && <CustomToolbar />}
204
+ <TextField
205
+ placeholder={options?.translations?.searchPlaceholder || "Search..."}
206
+ onChange={(e) => onSearch(e.target.value)}
207
+ variant="standard"
208
+ autoFocus
209
+ fullWidth
210
+ sx={{ marginLeft: 1 }}
211
+ />
212
+ <IconButton
213
+ onClick={handleSearchChange}
214
+ sx={{ '&:hover': { color: 'error.main' } }}
215
+ >
216
+ <Close />
217
+ </IconButton>
218
+ </Stack>
219
+ ) : (
220
+
221
+ <Typography
222
+ sx={{ flex: "1 1 100%", alignContent: "center", paddingLeft: 1 }}
223
+ variant="h6"
224
+ id="tableTitle"
225
+ component="div"
226
+ >
227
+ {title}
228
+ </Typography>
229
+ )}
230
+ <Stack direction="row" spacing={0.5}>
231
+ <Tooltip title={options?.translations?.searchTooltip || "Search"}>
232
+ <IconButton onClick={handleSearchChange}>
233
+ <SearchIcon />
234
+ </IconButton>
235
+ </Tooltip>
236
+ <Tooltip title={options?.translations?.downloadTooltip || "Download CSV"}>
237
+ <IconButton onClick={() => downloadCSV(data as Record<string, any>[], "data.csv")}>
238
+ <CloudDownload />
239
+ </IconButton>
240
+ </Tooltip>
241
+ <Tooltip title={options?.translations?.printTooltip || "Print"}>
242
+ <IconButton onClick={() => printFn()}>
243
+ <Print />
244
+ </IconButton>
245
+ </Tooltip>
246
+ <Tooltip title={options?.translations?.filterTooltip || "Filter list"}>
247
+ <IconButton onClick={handleOpen}>
248
+ <FilterListIcon />
249
+ </IconButton>
250
+ </Tooltip>
251
+ {CustomToolbar && <CustomToolbar />}
252
+ </Stack>
201
253
  </Stack>
202
254
  )}
203
255
  <Popover
@@ -218,19 +270,19 @@ export function EnhancedTableToolbar<T>(props: EnhancedTableToolbarProps<T>) {
218
270
  >
219
271
  <Stack direction="row" justifyContent="space-between">
220
272
  <Typography variant="h6" sx={{ marginBottom: 2 }}>
221
- Filters
273
+ {options?.translations?.filtersTitle || "Filters"}
222
274
  </Typography>
223
275
  <Button variant="contained" size="small" sx={{ height: "fit-content" }} onClick={resetFilters}>
224
- Reset
276
+ {options?.translations?.resetButtonText || "Reset"}
225
277
  </Button>
226
278
  </Stack>
227
- <Stack key={resetCounter} spacing={2}>
279
+ <Stack key={resetCounter}>
228
280
  {filterConfig.map(({ key, type, min, max }) => {
229
281
  const currentFilter = getFilter(key);
230
282
  return (
231
283
  <Box key={key}>
232
284
  <Typography variant="subtitle1">
233
- {headCells.find((cell) => cell.id === key)?.label}
285
+ {columns.find((cell) => cell.name === key)?.label}
234
286
  </Typography>
235
287
  {type === "number" && min !== undefined && max !== undefined && (
236
288
  <Slider
@@ -249,15 +301,14 @@ export function EnhancedTableToolbar<T>(props: EnhancedTableToolbarProps<T>) {
249
301
  />
250
302
  )}
251
303
  {type === "string" && (
252
- <InputBase
253
- placeholder="Search..."
304
+ <TextField
305
+ placeholder={options?.translations?.searchPlaceholder || "Search..."}
306
+ size="small"
254
307
  value={(currentFilter?.value as string) || ""}
255
308
  onChange={(e) => handleFilterChange(key, e.target.value)}
256
309
  sx={{
257
- padding: 1,
258
- border: 1,
259
- borderColor: "lightgray",
260
- borderRadius: 1,
310
+ marginBottom: 1,
311
+ paddingY: 0.5,
261
312
  width: "100%",
262
313
  }}
263
314
  />
package/src/index.ts CHANGED
@@ -1 +1,3 @@
1
- export { MUITable } from './components/MUITable';
1
+ export { MUITable as default } from './components/MUITable';
2
+ export type { Column } from './components/MUITable';
3
+ export type { CustomSelectedToolbarProps } from './components/Toolbar';