@mini_7/material-react-table-mcp 4.0.0

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.
Files changed (170) hide show
  1. package/README.md +68 -0
  2. package/data/MIGRATION.md +136 -0
  3. package/data/api.json +5379 -0
  4. package/data/examples/advanced.tsx +309 -0
  5. package/data/examples/aggregation-and-grouping.tsx +153 -0
  6. package/data/examples/aggregation-multi.tsx +105 -0
  7. package/data/examples/alternate-column-filtering.tsx +49 -0
  8. package/data/examples/alternate-detail-panel.tsx +81 -0
  9. package/data/examples/alternate-pagination.tsx +23 -0
  10. package/data/examples/basic.tsx +109 -0
  11. package/data/examples/chart-detail-panel.tsx +89 -0
  12. package/data/examples/column-actions-space.tsx +44 -0
  13. package/data/examples/column-alignment.tsx +70 -0
  14. package/data/examples/custom-column-actions.tsx +109 -0
  15. package/data/examples/custom-column-filtering-ui.tsx +89 -0
  16. package/data/examples/custom-headless.tsx +125 -0
  17. package/data/examples/custom-top-toolbar.tsx +88 -0
  18. package/data/examples/customize-display-columns.tsx +85 -0
  19. package/data/examples/customize-filter-components.tsx +101 -0
  20. package/data/examples/customize-filter-modes.tsx +73 -0
  21. package/data/examples/customize-filter-variants.tsx +116 -0
  22. package/data/examples/customize-global-filter-component.tsx +52 -0
  23. package/data/examples/customize-remove-column-grouping.tsx +94 -0
  24. package/data/examples/customize-row-selection.tsx +54 -0
  25. package/data/examples/customize-table-styles.tsx +100 -0
  26. package/data/examples/disable-column-actions.tsx +37 -0
  27. package/data/examples/disable-column-hiding.tsx +90 -0
  28. package/data/examples/disable-density-toggle.tsx +49 -0
  29. package/data/examples/dynamic-columns.tsx +189 -0
  30. package/data/examples/editing-crud-cell.tsx +377 -0
  31. package/data/examples/editing-crud-modal.tsx +370 -0
  32. package/data/examples/editing-crud-row.tsx +333 -0
  33. package/data/examples/editing-crud-table.tsx +369 -0
  34. package/data/examples/editing-crud-tree.tsx +416 -0
  35. package/data/examples/enable-cell-actions.tsx +76 -0
  36. package/data/examples/enable-click-to-copy.tsx +39 -0
  37. package/data/examples/enable-column-grouping.tsx +120 -0
  38. package/data/examples/enable-column-ordering.tsx +48 -0
  39. package/data/examples/enable-column-pinning.tsx +69 -0
  40. package/data/examples/enable-column-resizing.tsx +56 -0
  41. package/data/examples/enable-column-virtualization.tsx +27 -0
  42. package/data/examples/enable-detail-panel-conditionally.tsx +78 -0
  43. package/data/examples/enable-detail-panel-virtualized.tsx +80 -0
  44. package/data/examples/enable-expanding-tree.tsx +110 -0
  45. package/data/examples/enable-filter-facet-values.tsx +65 -0
  46. package/data/examples/enable-row-dragging.tsx +137 -0
  47. package/data/examples/enable-row-numbers-original.tsx +48 -0
  48. package/data/examples/enable-row-numbers-static.tsx +48 -0
  49. package/data/examples/enable-row-ordering.tsx +57 -0
  50. package/data/examples/enable-row-pinning-select.tsx +76 -0
  51. package/data/examples/enable-row-pinning-static.tsx +50 -0
  52. package/data/examples/enable-row-pinning-sticky.tsx +69 -0
  53. package/data/examples/enable-row-selection.tsx +96 -0
  54. package/data/examples/enable-row-virtualization.tsx +101 -0
  55. package/data/examples/enable-sticky-header.tsx +59 -0
  56. package/data/examples/expanding-tree-expanded.tsx +121 -0
  57. package/data/examples/expanding-tree-flat-parse.tsx +125 -0
  58. package/data/examples/expanding-tree-root-expanded.tsx +151 -0
  59. package/data/examples/export-to-csv.tsx +114 -0
  60. package/data/examples/export-to-pdf.tsx +104 -0
  61. package/data/examples/external-toolbar.tsx +108 -0
  62. package/data/examples/font-awesome-icons.tsx +106 -0
  63. package/data/examples/infinite-scrolling.tsx +208 -0
  64. package/data/examples/lazy-detail-panel.tsx +262 -0
  65. package/data/examples/lazy-sub-rows.tsx +190 -0
  66. package/data/examples/linear-progress.tsx +66 -0
  67. package/data/examples/loading.tsx +50 -0
  68. package/data/examples/localization-i18n-ar.tsx +65 -0
  69. package/data/examples/localization-i18n-az.tsx +60 -0
  70. package/data/examples/localization-i18n-bg.tsx +60 -0
  71. package/data/examples/localization-i18n-cs.tsx +60 -0
  72. package/data/examples/localization-i18n-da.tsx +60 -0
  73. package/data/examples/localization-i18n-de.tsx +60 -0
  74. package/data/examples/localization-i18n-el.tsx +60 -0
  75. package/data/examples/localization-i18n-en.tsx +60 -0
  76. package/data/examples/localization-i18n-es.tsx +60 -0
  77. package/data/examples/localization-i18n-et.tsx +60 -0
  78. package/data/examples/localization-i18n-fa.tsx +66 -0
  79. package/data/examples/localization-i18n-fi.tsx +60 -0
  80. package/data/examples/localization-i18n-fr.tsx +60 -0
  81. package/data/examples/localization-i18n-he.tsx +66 -0
  82. package/data/examples/localization-i18n-hr.tsx +60 -0
  83. package/data/examples/localization-i18n-hu.tsx +60 -0
  84. package/data/examples/localization-i18n-hy.tsx +65 -0
  85. package/data/examples/localization-i18n-id.tsx +60 -0
  86. package/data/examples/localization-i18n-it.tsx +60 -0
  87. package/data/examples/localization-i18n-ja.tsx +60 -0
  88. package/data/examples/localization-i18n-ko.tsx +60 -0
  89. package/data/examples/localization-i18n-nl.tsx +60 -0
  90. package/data/examples/localization-i18n-no.tsx +60 -0
  91. package/data/examples/localization-i18n-np.tsx +60 -0
  92. package/data/examples/localization-i18n-pl.tsx +60 -0
  93. package/data/examples/localization-i18n-pt-BR.tsx +60 -0
  94. package/data/examples/localization-i18n-pt.tsx +60 -0
  95. package/data/examples/localization-i18n-ro.tsx +60 -0
  96. package/data/examples/localization-i18n-ru.tsx +60 -0
  97. package/data/examples/localization-i18n-sk.tsx +60 -0
  98. package/data/examples/localization-i18n-sr-Cyrl-RS.tsx +60 -0
  99. package/data/examples/localization-i18n-sr-Latn-RS.tsx +60 -0
  100. package/data/examples/localization-i18n-sv.tsx +60 -0
  101. package/data/examples/localization-i18n-tr.tsx +60 -0
  102. package/data/examples/localization-i18n-uk.tsx +60 -0
  103. package/data/examples/localization-i18n-vi.tsx +60 -0
  104. package/data/examples/localization-i18n-zh-hans.tsx +60 -0
  105. package/data/examples/localization-i18n-zh-hant.tsx +60 -0
  106. package/data/examples/manual-selection.tsx +105 -0
  107. package/data/examples/minimal.tsx +78 -0
  108. package/data/examples/mui-theme.tsx +136 -0
  109. package/data/examples/multi-sorting.tsx +58 -0
  110. package/data/examples/persistent-state.tsx +184 -0
  111. package/data/examples/react-query.tsx +182 -0
  112. package/data/examples/remote.tsx +150 -0
  113. package/data/examples/row-actions-buttons.tsx +89 -0
  114. package/data/examples/row-actions-menu-items.tsx +64 -0
  115. package/data/examples/single-row-selection.tsx +98 -0
  116. package/data/examples/virtualized.tsx +138 -0
  117. package/data/guides/accessibility.md +119 -0
  118. package/data/guides/aggregation.md +210 -0
  119. package/data/guides/async-loading.md +132 -0
  120. package/data/guides/best-practices.md +363 -0
  121. package/data/guides/cell-actions.md +139 -0
  122. package/data/guides/click-to-copy.md +67 -0
  123. package/data/guides/column-actions.md +69 -0
  124. package/data/guides/column-filtering.md +366 -0
  125. package/data/guides/column-grouping.md +192 -0
  126. package/data/guides/column-hiding.md +133 -0
  127. package/data/guides/column-ordering-dnd.md +99 -0
  128. package/data/guides/column-pinning.md +72 -0
  129. package/data/guides/column-resizing.md +157 -0
  130. package/data/guides/column-size.md +162 -0
  131. package/data/guides/customize-components.md +395 -0
  132. package/data/guides/customize-icons.md +35 -0
  133. package/data/guides/data-columns.md +292 -0
  134. package/data/guides/density-toggle.md +46 -0
  135. package/data/guides/detail-panel.md +195 -0
  136. package/data/guides/display-columns.md +135 -0
  137. package/data/guides/editing.md +367 -0
  138. package/data/guides/expanding-sub-rows.md +194 -0
  139. package/data/guides/full-screen-toggle.md +63 -0
  140. package/data/guides/global-filtering.md +237 -0
  141. package/data/guides/localization.md +57 -0
  142. package/data/guides/memoization.md +157 -0
  143. package/data/guides/pagination.md +171 -0
  144. package/data/guides/row-actions.md +116 -0
  145. package/data/guides/row-numbers.md +24 -0
  146. package/data/guides/row-ordering-dnd.md +51 -0
  147. package/data/guides/row-pinning.md +96 -0
  148. package/data/guides/row-selection.md +237 -0
  149. package/data/guides/sorting.md +190 -0
  150. package/data/guides/state-management.md +165 -0
  151. package/data/guides/sticky-header.md +41 -0
  152. package/data/guides/table-event-listeners.md +103 -0
  153. package/data/guides/toolbar-customization.md +251 -0
  154. package/data/guides/virtualization.md +183 -0
  155. package/data/index.json +1930 -0
  156. package/data/reference/mrt-components.md +183 -0
  157. package/data/reference/mrt-hooks.md +125 -0
  158. package/data/skills/composable-components/SKILL.md +189 -0
  159. package/data/skills/customization/SKILL.md +190 -0
  160. package/data/skills/drag-and-drop-ordering/SKILL.md +227 -0
  161. package/data/skills/editing/SKILL.md +243 -0
  162. package/data/skills/filtering/SKILL.md +213 -0
  163. package/data/skills/getting-started/SKILL.md +213 -0
  164. package/data/skills/localization/SKILL.md +182 -0
  165. package/data/skills/migrate-v3-to-v4/SKILL.md +161 -0
  166. package/data/skills/state-and-server-data/SKILL.md +200 -0
  167. package/data/skills/virtualization/SKILL.md +203 -0
  168. package/dist/data.js +137 -0
  169. package/dist/index.js +232 -0
  170. package/package.json +50 -0
@@ -0,0 +1,136 @@
1
+ import { useMemo } from 'react';
2
+ import { MaterialReactTable, type MRT_ColumnDef } from 'material-react-table';
3
+ import { createTheme, ThemeProvider, useTheme } from '@mui/material';
4
+
5
+ type Person = {
6
+ firstName: string;
7
+ lastName: string;
8
+ address: string;
9
+ city: string;
10
+ state: string;
11
+ };
12
+
13
+ //column definitions...
14
+ const columns: MRT_ColumnDef<Person>[] = [
15
+ {
16
+ accessorKey: 'firstName',
17
+ header: 'First Name',
18
+ },
19
+ {
20
+ accessorKey: 'lastName',
21
+ header: 'Last Name',
22
+ },
23
+ {
24
+ accessorKey: 'address',
25
+ header: 'Address',
26
+ },
27
+ {
28
+ accessorKey: 'city',
29
+ header: 'City',
30
+ },
31
+ {
32
+ accessorKey: 'state',
33
+ header: 'State',
34
+ },
35
+ ];
36
+ //end
37
+
38
+ //data definitions...
39
+ const data = [
40
+ {
41
+ firstName: 'Dylan',
42
+ lastName: 'Murray',
43
+ address: '261 Erdman Ford',
44
+ city: 'East Daphne',
45
+ state: 'Kentucky',
46
+ },
47
+ {
48
+ firstName: 'Raquel',
49
+ lastName: 'Kohler',
50
+ address: '769 Dominic Grove',
51
+ city: 'Columbus',
52
+ state: 'Ohio',
53
+ },
54
+ {
55
+ firstName: 'Ervin',
56
+ lastName: 'Reinger',
57
+ address: '566 Brakus Inlet',
58
+ city: 'South Linda',
59
+ state: 'West Virginia',
60
+ },
61
+ {
62
+ firstName: 'Brittany',
63
+ lastName: 'McCullough',
64
+ address: '722 Emie Stream',
65
+ city: 'Lincoln',
66
+ state: 'Nebraska',
67
+ },
68
+ {
69
+ firstName: 'Branson',
70
+ lastName: 'Frami',
71
+ address: '32188 Larkin Turnpike',
72
+ city: 'Charleston',
73
+ state: 'South Carolina',
74
+ },
75
+ ];
76
+ //end
77
+
78
+ const Example = () => {
79
+ const globalTheme = useTheme(); //(optional) if you already have a theme defined in your app root, you can import here
80
+
81
+ const tableTheme = useMemo(
82
+ () =>
83
+ createTheme({
84
+ palette: {
85
+ mode: globalTheme.palette.mode, //let's use the same dark/light mode as the global theme
86
+ primary: globalTheme.palette.secondary, //swap in the secondary color as the primary for the table
87
+ info: {
88
+ main: 'rgb(255,122,0)', //add in a custom color for the toolbar alert background stuff
89
+ },
90
+ background: {
91
+ default:
92
+ globalTheme.palette.mode === 'light'
93
+ ? 'rgb(254,255,244)' //random light yellow color for the background in light mode
94
+ : '#000', //pure black table in dark mode for fun
95
+ },
96
+ },
97
+ typography: {
98
+ button: {
99
+ textTransform: 'none', //customize typography styles for all buttons in table by default
100
+ fontSize: '1.2rem',
101
+ },
102
+ },
103
+ components: {
104
+ MuiTooltip: {
105
+ styleOverrides: {
106
+ tooltip: {
107
+ fontSize: '1.1rem', //override to make tooltip font size larger
108
+ },
109
+ },
110
+ },
111
+ MuiSwitch: {
112
+ styleOverrides: {
113
+ thumb: {
114
+ color: 'pink', //change the color of the switch thumb in the columns show/hide menu to pink
115
+ },
116
+ },
117
+ },
118
+ },
119
+ }),
120
+ [globalTheme],
121
+ );
122
+
123
+ return (
124
+ <ThemeProvider theme={tableTheme}>
125
+ <MaterialReactTable
126
+ columns={columns}
127
+ data={data}
128
+ enableRowSelection
129
+ enableColumnOrdering
130
+ enableColumnPinning
131
+ />
132
+ </ThemeProvider>
133
+ );
134
+ };
135
+
136
+ export default Example;
@@ -0,0 +1,58 @@
1
+ import {
2
+ MaterialReactTable,
3
+ useMaterialReactTable,
4
+ type MRT_ColumnDef,
5
+ } from 'material-react-table';
6
+ import { data, type Person } from './makeData';
7
+ import { Button } from '@mui/material';
8
+
9
+ const columns: MRT_ColumnDef<Person>[] = [
10
+ {
11
+ accessorKey: 'firstName',
12
+ header: 'First Name',
13
+ sortDescFirst: false, //sort first name in ascending order by default on first sort click (default for non-numeric columns)
14
+ },
15
+ //column definitions...
16
+ {
17
+ accessorKey: 'lastName',
18
+ header: 'Last Name',
19
+ },
20
+ {
21
+ accessorKey: 'city',
22
+ header: 'City',
23
+ },
24
+ {
25
+ accessorKey: 'state',
26
+ header: 'State',
27
+ },
28
+ //end
29
+ {
30
+ accessorKey: 'salary',
31
+ header: 'Salary',
32
+ sortDescFirst: true, //sort salary in descending order by default on first sort click (default for numeric columns)
33
+ },
34
+ ];
35
+
36
+ const Example = () => {
37
+ const table = useMaterialReactTable({
38
+ columns,
39
+ data,
40
+ isMultiSortEvent: () => true, //now no need to hold `shift` key to multi-sort
41
+ maxMultiSortColCount: 3, //prevent more than 3 columns from being sorted at once
42
+ initialState: {
43
+ sorting: [
44
+ { id: 'state', desc: false }, //sort by state in ascending order by default
45
+ { id: 'city', desc: true }, //then sort by city in descending order by default
46
+ ],
47
+ },
48
+ renderTopToolbarCustomActions: ({ table }) => (
49
+ <Button onClick={() => table.resetSorting(true)}>
50
+ Clear All Sorting
51
+ </Button>
52
+ ),
53
+ });
54
+
55
+ return <MaterialReactTable table={table} />;
56
+ };
57
+
58
+ export default Example;
@@ -0,0 +1,184 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+ import { Button } from '@mui/material';
3
+ import {
4
+ MaterialReactTable,
5
+ type MRT_ColumnDef,
6
+ type MRT_ColumnFiltersState,
7
+ type MRT_DensityState,
8
+ type MRT_SortingState,
9
+ type MRT_VisibilityState,
10
+ } from 'material-react-table';
11
+ import { data, type Person } from './makeData';
12
+
13
+ //column definitions...
14
+ const columns: MRT_ColumnDef<Person>[] = [
15
+ {
16
+ accessorKey: 'firstName',
17
+ header: 'First Name',
18
+ },
19
+ {
20
+ accessorKey: 'lastName',
21
+ header: 'Last Name',
22
+ },
23
+ {
24
+ accessorKey: 'city',
25
+ header: 'City',
26
+ },
27
+ {
28
+ accessorKey: 'state',
29
+ header: 'State',
30
+ },
31
+ {
32
+ accessorKey: 'salary',
33
+ header: 'Salary',
34
+ },
35
+ ];
36
+ //end
37
+
38
+ const Example = () => {
39
+ const isFirstRender = useRef(true);
40
+
41
+ const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>(
42
+ [],
43
+ );
44
+ const [columnVisibility, setColumnVisibility] = useState<MRT_VisibilityState>(
45
+ {},
46
+ );
47
+ const [density, setDensity] = useState<MRT_DensityState>('comfortable');
48
+ const [globalFilter, setGlobalFilter] = useState<string | undefined>(
49
+ undefined,
50
+ );
51
+ const [showGlobalFilter, setShowGlobalFilter] = useState(false);
52
+ const [showColumnFilters, setShowColumnFilters] = useState(false);
53
+ const [sorting, setSorting] = useState<MRT_SortingState>([]);
54
+
55
+ //load state from local storage
56
+ useEffect(() => {
57
+ const columnFilters = sessionStorage.getItem('mrt_columnFilters_table_1');
58
+ const columnVisibility = sessionStorage.getItem(
59
+ 'mrt_columnVisibility_table_1',
60
+ );
61
+ const density = sessionStorage.getItem('mrt_density_table_1');
62
+ const globalFilter = sessionStorage.getItem('mrt_globalFilter_table_1');
63
+ const showGlobalFilter = sessionStorage.getItem(
64
+ 'mrt_showGlobalFilter_table_1',
65
+ );
66
+ const showColumnFilters = sessionStorage.getItem(
67
+ 'mrt_showColumnFilters_table_1',
68
+ );
69
+ const sorting = sessionStorage.getItem('mrt_sorting_table_1');
70
+
71
+ if (columnFilters) {
72
+ setColumnFilters(JSON.parse(columnFilters));
73
+ }
74
+ if (columnVisibility) {
75
+ setColumnVisibility(JSON.parse(columnVisibility));
76
+ }
77
+ if (density) {
78
+ setDensity(JSON.parse(density));
79
+ }
80
+ if (globalFilter) {
81
+ setGlobalFilter(JSON.parse(globalFilter) || undefined);
82
+ }
83
+ if (showGlobalFilter) {
84
+ setShowGlobalFilter(JSON.parse(showGlobalFilter));
85
+ }
86
+ if (showColumnFilters) {
87
+ setShowColumnFilters(JSON.parse(showColumnFilters));
88
+ }
89
+ if (sorting) {
90
+ setSorting(JSON.parse(sorting));
91
+ }
92
+ isFirstRender.current = false;
93
+ }, []);
94
+
95
+ //save states to local storage
96
+ useEffect(() => {
97
+ if (isFirstRender.current) return;
98
+ sessionStorage.setItem(
99
+ 'mrt_columnFilters_table_1',
100
+ JSON.stringify(columnFilters),
101
+ );
102
+ }, [columnFilters]);
103
+
104
+ useEffect(() => {
105
+ if (isFirstRender.current) return;
106
+ sessionStorage.setItem(
107
+ 'mrt_columnVisibility_table_1',
108
+ JSON.stringify(columnVisibility),
109
+ );
110
+ }, [columnVisibility]);
111
+
112
+ useEffect(() => {
113
+ if (isFirstRender.current) return;
114
+ sessionStorage.setItem('mrt_density_table_1', JSON.stringify(density));
115
+ }, [density]);
116
+
117
+ useEffect(() => {
118
+ if (isFirstRender.current) return;
119
+ sessionStorage.setItem(
120
+ 'mrt_globalFilter_table_1',
121
+ JSON.stringify(globalFilter ?? ''),
122
+ );
123
+ }, [globalFilter]);
124
+
125
+ useEffect(() => {
126
+ if (isFirstRender.current) return;
127
+ sessionStorage.setItem(
128
+ 'mrt_showGlobalFilter_table_1',
129
+ JSON.stringify(showGlobalFilter),
130
+ );
131
+ }, [showGlobalFilter]);
132
+
133
+ useEffect(() => {
134
+ if (isFirstRender.current) return;
135
+ sessionStorage.setItem(
136
+ 'mrt_showColumnFilters_table_1',
137
+ JSON.stringify(showColumnFilters),
138
+ );
139
+ }, [showColumnFilters]);
140
+
141
+ useEffect(() => {
142
+ if (isFirstRender.current) return;
143
+ sessionStorage.setItem('mrt_sorting_table_1', JSON.stringify(sorting));
144
+ }, [sorting]);
145
+
146
+ const resetState = () => {
147
+ sessionStorage.removeItem('mrt_columnFilters_table_1');
148
+ sessionStorage.removeItem('mrt_columnVisibility_table_1');
149
+ sessionStorage.removeItem('mrt_density_table_1');
150
+ sessionStorage.removeItem('mrt_globalFilter_table_1');
151
+ sessionStorage.removeItem('mrt_showGlobalFilter_table_1');
152
+ sessionStorage.removeItem('mrt_showColumnFilters_table_1');
153
+ sessionStorage.removeItem('mrt_sorting_table_1');
154
+ window.location.reload();
155
+ };
156
+
157
+ return (
158
+ <MaterialReactTable
159
+ columns={columns}
160
+ data={data}
161
+ onColumnFiltersChange={setColumnFilters}
162
+ onColumnVisibilityChange={setColumnVisibility}
163
+ onDensityChange={setDensity}
164
+ onGlobalFilterChange={setGlobalFilter}
165
+ onShowColumnFiltersChange={setShowColumnFilters}
166
+ onShowGlobalFilterChange={setShowGlobalFilter}
167
+ onSortingChange={setSorting}
168
+ state={{
169
+ columnFilters,
170
+ columnVisibility,
171
+ density,
172
+ globalFilter,
173
+ showColumnFilters,
174
+ showGlobalFilter,
175
+ sorting,
176
+ }}
177
+ renderTopToolbarCustomActions={() => (
178
+ <Button onClick={resetState}>Reset State</Button>
179
+ )}
180
+ />
181
+ );
182
+ };
183
+
184
+ export default Example;
@@ -0,0 +1,182 @@
1
+ import { lazy, Suspense, useMemo, useState } from 'react';
2
+ import {
3
+ MaterialReactTable,
4
+ useMaterialReactTable,
5
+ type MRT_ColumnDef,
6
+ type MRT_ColumnFiltersState,
7
+ type MRT_PaginationState,
8
+ type MRT_SortingState,
9
+ } from 'material-react-table';
10
+ import { IconButton, Tooltip } from '@mui/material';
11
+ import RefreshIcon from '@mui/icons-material/Refresh';
12
+ import {
13
+ QueryClient,
14
+ QueryClientProvider,
15
+ keepPreviousData,
16
+ useQuery,
17
+ } from '@tanstack/react-query'; //note: this is TanStack React Query V5
18
+
19
+ //Your API response shape will probably be different. Knowing a total row count is important though.
20
+ type UserApiResponse = {
21
+ data: Array<User>;
22
+ meta: {
23
+ totalRowCount: number;
24
+ };
25
+ };
26
+
27
+ type User = {
28
+ firstName: string;
29
+ lastName: string;
30
+ address: string;
31
+ state: string;
32
+ phoneNumber: string;
33
+ lastLogin: Date;
34
+ };
35
+
36
+ const Example = () => {
37
+ //manage our own state for stuff we want to pass to the API
38
+ const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>(
39
+ [],
40
+ );
41
+ const [globalFilter, setGlobalFilter] = useState('');
42
+ const [sorting, setSorting] = useState<MRT_SortingState>([]);
43
+ const [pagination, setPagination] = useState<MRT_PaginationState>({
44
+ pageIndex: 0,
45
+ pageSize: 10,
46
+ });
47
+
48
+ //consider storing this code in a custom hook (i.e useFetchUsers)
49
+ const {
50
+ data: { data = [], meta } = {}, //your data and api response will probably be different
51
+ isError,
52
+ isRefetching,
53
+ isLoading,
54
+ refetch,
55
+ } = useQuery<UserApiResponse>({
56
+ queryKey: [
57
+ 'users-list',
58
+ {
59
+ columnFilters, //refetch when columnFilters changes
60
+ globalFilter, //refetch when globalFilter changes
61
+ pagination, //refetch when pagination changes
62
+ sorting, //refetch when sorting changes
63
+ },
64
+ ],
65
+ queryFn: async () => {
66
+ const fetchURL = new URL('/api/data', location.origin);
67
+
68
+ //read our state and pass it to the API as query params
69
+ fetchURL.searchParams.set(
70
+ 'start',
71
+ `${pagination.pageIndex * pagination.pageSize}`,
72
+ );
73
+ fetchURL.searchParams.set('size', `${pagination.pageSize}`);
74
+ fetchURL.searchParams.set('filters', JSON.stringify(columnFilters ?? []));
75
+ fetchURL.searchParams.set('globalFilter', globalFilter ?? '');
76
+ fetchURL.searchParams.set('sorting', JSON.stringify(sorting ?? []));
77
+
78
+ //use whatever fetch library you want, fetch, axios, etc
79
+ const response = await fetch(fetchURL.href);
80
+ const json = (await response.json()) as UserApiResponse;
81
+ return json;
82
+ },
83
+ placeholderData: keepPreviousData, //don't go to 0 rows when refetching or paginating to next page
84
+ });
85
+
86
+ const columns = useMemo<MRT_ColumnDef<User>[]>(
87
+ //column definitions...
88
+ () => [
89
+ {
90
+ accessorKey: 'firstName',
91
+ header: 'First Name',
92
+ },
93
+ {
94
+ accessorKey: 'lastName',
95
+ header: 'Last Name',
96
+ },
97
+ {
98
+ accessorKey: 'address',
99
+ header: 'Address',
100
+ },
101
+ {
102
+ accessorKey: 'state',
103
+ header: 'State',
104
+ },
105
+ {
106
+ accessorKey: 'phoneNumber',
107
+ header: 'Phone Number',
108
+ },
109
+ {
110
+ accessorFn: (row) => new Date(row.lastLogin),
111
+ id: 'lastLogin',
112
+ header: 'Last Login',
113
+ Cell: ({ cell }) => new Date(cell.getValue<Date>()).toLocaleString(),
114
+ filterFn: 'greaterThan',
115
+ filterVariant: 'date',
116
+ enableGlobalFilter: false,
117
+ },
118
+ ],
119
+ [],
120
+ //end
121
+ );
122
+
123
+ const table = useMaterialReactTable({
124
+ columns,
125
+ data,
126
+ initialState: { showColumnFilters: true },
127
+ manualFiltering: true, //turn off built-in client-side filtering
128
+ manualPagination: true, //turn off built-in client-side pagination
129
+ manualSorting: true, //turn off built-in client-side sorting
130
+ muiToolbarAlertBannerProps: isError
131
+ ? {
132
+ color: 'error',
133
+ children: 'Error loading data',
134
+ }
135
+ : undefined,
136
+ onColumnFiltersChange: setColumnFilters,
137
+ onGlobalFilterChange: setGlobalFilter,
138
+ onPaginationChange: setPagination,
139
+ onSortingChange: setSorting,
140
+ renderTopToolbarCustomActions: () => (
141
+ <Tooltip arrow title="Refresh Data">
142
+ <IconButton onClick={() => refetch()}>
143
+ <RefreshIcon />
144
+ </IconButton>
145
+ </Tooltip>
146
+ ),
147
+ rowCount: meta?.totalRowCount ?? 0,
148
+ state: {
149
+ columnFilters,
150
+ globalFilter,
151
+ isLoading,
152
+ pagination,
153
+ showAlertBanner: isError,
154
+ showProgressBars: isRefetching,
155
+ sorting,
156
+ },
157
+ });
158
+
159
+ return <MaterialReactTable table={table} />;
160
+ };
161
+
162
+ //react query setup in App.tsx
163
+ const ReactQueryDevtoolsProduction = lazy(() =>
164
+ import('@tanstack/react-query-devtools/build/modern/production.js').then(
165
+ (d) => ({
166
+ default: d.ReactQueryDevtools,
167
+ }),
168
+ ),
169
+ );
170
+
171
+ const queryClient = new QueryClient();
172
+
173
+ export default function App() {
174
+ return (
175
+ <QueryClientProvider client={queryClient}>
176
+ <Example />
177
+ <Suspense fallback={null}>
178
+ <ReactQueryDevtoolsProduction />
179
+ </Suspense>
180
+ </QueryClientProvider>
181
+ );
182
+ }
@@ -0,0 +1,150 @@
1
+ import { useEffect, useMemo, useState } from 'react';
2
+ import {
3
+ MaterialReactTable,
4
+ useMaterialReactTable,
5
+ type MRT_ColumnDef,
6
+ type MRT_ColumnFiltersState,
7
+ type MRT_PaginationState,
8
+ type MRT_SortingState,
9
+ } from 'material-react-table';
10
+
11
+ type UserApiResponse = {
12
+ data: Array<User>;
13
+ meta: {
14
+ totalRowCount: number;
15
+ };
16
+ };
17
+
18
+ type User = {
19
+ firstName: string;
20
+ lastName: string;
21
+ address: string;
22
+ state: string;
23
+ phoneNumber: string;
24
+ };
25
+
26
+ const Example = () => {
27
+ //data and fetching state
28
+ const [data, setData] = useState<User[]>([]);
29
+ const [isError, setIsError] = useState(false);
30
+ const [isLoading, setIsLoading] = useState(false);
31
+ const [isRefetching, setIsRefetching] = useState(false);
32
+ const [rowCount, setRowCount] = useState(0);
33
+
34
+ //table state
35
+ const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>(
36
+ [],
37
+ );
38
+ const [globalFilter, setGlobalFilter] = useState('');
39
+ const [sorting, setSorting] = useState<MRT_SortingState>([]);
40
+ const [pagination, setPagination] = useState<MRT_PaginationState>({
41
+ pageIndex: 0,
42
+ pageSize: 10,
43
+ });
44
+
45
+ //if you want to avoid useEffect, look at the React Query example instead
46
+ useEffect(() => {
47
+ const fetchData = async () => {
48
+ if (!data.length) {
49
+ setIsLoading(true);
50
+ } else {
51
+ setIsRefetching(true);
52
+ }
53
+
54
+ const url = new URL('/api/data', location.origin);
55
+ url.searchParams.set(
56
+ 'start',
57
+ `${pagination.pageIndex * pagination.pageSize}`,
58
+ );
59
+ url.searchParams.set('size', `${pagination.pageSize}`);
60
+ url.searchParams.set('filters', JSON.stringify(columnFilters ?? []));
61
+ url.searchParams.set('globalFilter', globalFilter ?? '');
62
+ url.searchParams.set('sorting', JSON.stringify(sorting ?? []));
63
+
64
+ try {
65
+ const response = await fetch(url.href);
66
+ const json = (await response.json()) as UserApiResponse;
67
+ setData(json.data);
68
+ setRowCount(json.meta.totalRowCount);
69
+ } catch (error) {
70
+ setIsError(true);
71
+ console.error(error);
72
+ return;
73
+ }
74
+ setIsError(false);
75
+ setIsLoading(false);
76
+ setIsRefetching(false);
77
+ };
78
+ fetchData();
79
+ // eslint-disable-next-line react-hooks/exhaustive-deps
80
+ }, [
81
+ columnFilters, //re-fetch when column filters change
82
+ globalFilter, //re-fetch when global filter changes
83
+ pagination.pageIndex, //re-fetch when page index changes
84
+ pagination.pageSize, //re-fetch when page size changes
85
+ sorting, //re-fetch when sorting changes
86
+ ]);
87
+
88
+ const columns = useMemo<MRT_ColumnDef<User>[]>(
89
+ () => [
90
+ {
91
+ accessorKey: 'firstName',
92
+ header: 'First Name',
93
+ },
94
+ //column definitions...
95
+ {
96
+ accessorKey: 'lastName',
97
+ header: 'Last Name',
98
+ },
99
+ {
100
+ accessorKey: 'address',
101
+ header: 'Address',
102
+ },
103
+ {
104
+ accessorKey: 'state',
105
+ header: 'State',
106
+ },
107
+ {
108
+ accessorKey: 'phoneNumber',
109
+ header: 'Phone Number',
110
+ },
111
+ //end
112
+ ],
113
+ [],
114
+ );
115
+
116
+ const table = useMaterialReactTable({
117
+ columns,
118
+ data,
119
+ enableRowSelection: true,
120
+ getRowId: (row) => row.phoneNumber,
121
+ initialState: { showColumnFilters: true },
122
+ manualFiltering: true,
123
+ manualPagination: true,
124
+ manualSorting: true,
125
+ muiToolbarAlertBannerProps: isError
126
+ ? {
127
+ color: 'error',
128
+ children: 'Error loading data',
129
+ }
130
+ : undefined,
131
+ onColumnFiltersChange: setColumnFilters,
132
+ onGlobalFilterChange: setGlobalFilter,
133
+ onPaginationChange: setPagination,
134
+ onSortingChange: setSorting,
135
+ rowCount,
136
+ state: {
137
+ columnFilters,
138
+ globalFilter,
139
+ isLoading,
140
+ pagination,
141
+ showAlertBanner: isError,
142
+ showProgressBars: isRefetching,
143
+ sorting,
144
+ },
145
+ });
146
+
147
+ return <MaterialReactTable table={table} />;
148
+ };
149
+
150
+ export default Example;