@lminii/material-react-table-mcp 4.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.
Files changed (284) 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.js +215 -0
  5. package/data/examples/advanced.tsx +309 -0
  6. package/data/examples/aggregation-and-grouping.js +116 -0
  7. package/data/examples/aggregation-and-grouping.tsx +153 -0
  8. package/data/examples/aggregation-multi.js +89 -0
  9. package/data/examples/aggregation-multi.tsx +105 -0
  10. package/data/examples/alternate-column-filtering.js +38 -0
  11. package/data/examples/alternate-column-filtering.tsx +49 -0
  12. package/data/examples/alternate-detail-panel.js +65 -0
  13. package/data/examples/alternate-detail-panel.tsx +81 -0
  14. package/data/examples/alternate-pagination.js +17 -0
  15. package/data/examples/alternate-pagination.tsx +23 -0
  16. package/data/examples/basic.js +86 -0
  17. package/data/examples/basic.tsx +109 -0
  18. package/data/examples/chart-detail-panel.js +69 -0
  19. package/data/examples/chart-detail-panel.tsx +89 -0
  20. package/data/examples/column-actions-space.js +34 -0
  21. package/data/examples/column-actions-space.tsx +44 -0
  22. package/data/examples/column-alignment.js +58 -0
  23. package/data/examples/column-alignment.tsx +70 -0
  24. package/data/examples/custom-column-actions.js +74 -0
  25. package/data/examples/custom-column-actions.tsx +109 -0
  26. package/data/examples/custom-column-filtering-ui.js +59 -0
  27. package/data/examples/custom-column-filtering-ui.tsx +89 -0
  28. package/data/examples/custom-headless.js +85 -0
  29. package/data/examples/custom-headless.tsx +125 -0
  30. package/data/examples/custom-top-toolbar.js +60 -0
  31. package/data/examples/custom-top-toolbar.tsx +88 -0
  32. package/data/examples/customize-display-columns.js +72 -0
  33. package/data/examples/customize-display-columns.tsx +85 -0
  34. package/data/examples/customize-filter-components.js +78 -0
  35. package/data/examples/customize-filter-components.tsx +101 -0
  36. package/data/examples/customize-filter-modes.js +59 -0
  37. package/data/examples/customize-filter-modes.tsx +73 -0
  38. package/data/examples/customize-filter-variants.js +98 -0
  39. package/data/examples/customize-filter-variants.tsx +116 -0
  40. package/data/examples/customize-global-filter-component.js +37 -0
  41. package/data/examples/customize-global-filter-component.tsx +52 -0
  42. package/data/examples/customize-remove-column-grouping.js +75 -0
  43. package/data/examples/customize-remove-column-grouping.tsx +94 -0
  44. package/data/examples/customize-row-selection.js +43 -0
  45. package/data/examples/customize-row-selection.tsx +54 -0
  46. package/data/examples/customize-table-styles.js +81 -0
  47. package/data/examples/customize-table-styles.tsx +100 -0
  48. package/data/examples/disable-column-actions.js +26 -0
  49. package/data/examples/disable-column-actions.tsx +37 -0
  50. package/data/examples/disable-column-hiding.js +74 -0
  51. package/data/examples/disable-column-hiding.tsx +90 -0
  52. package/data/examples/disable-density-toggle.js +37 -0
  53. package/data/examples/disable-density-toggle.tsx +49 -0
  54. package/data/examples/dynamic-columns.js +124 -0
  55. package/data/examples/dynamic-columns.tsx +189 -0
  56. package/data/examples/editing-crud-cell.js +288 -0
  57. package/data/examples/editing-crud-cell.tsx +377 -0
  58. package/data/examples/editing-crud-modal.js +275 -0
  59. package/data/examples/editing-crud-modal.tsx +370 -0
  60. package/data/examples/editing-crud-row.js +255 -0
  61. package/data/examples/editing-crud-row.tsx +333 -0
  62. package/data/examples/editing-crud-table.js +280 -0
  63. package/data/examples/editing-crud-table.tsx +369 -0
  64. package/data/examples/editing-crud-tree.js +328 -0
  65. package/data/examples/editing-crud-tree.tsx +416 -0
  66. package/data/examples/enable-cell-actions.js +52 -0
  67. package/data/examples/enable-cell-actions.tsx +76 -0
  68. package/data/examples/enable-click-to-copy.js +33 -0
  69. package/data/examples/enable-click-to-copy.tsx +39 -0
  70. package/data/examples/enable-column-grouping.js +69 -0
  71. package/data/examples/enable-column-grouping.tsx +120 -0
  72. package/data/examples/enable-column-ordering.js +37 -0
  73. package/data/examples/enable-column-ordering.tsx +48 -0
  74. package/data/examples/enable-column-pinning.js +58 -0
  75. package/data/examples/enable-column-pinning.tsx +69 -0
  76. package/data/examples/enable-column-resizing.js +45 -0
  77. package/data/examples/enable-column-resizing.tsx +56 -0
  78. package/data/examples/enable-column-virtualization.js +19 -0
  79. package/data/examples/enable-column-virtualization.tsx +27 -0
  80. package/data/examples/enable-detail-panel-conditionally.js +61 -0
  81. package/data/examples/enable-detail-panel-conditionally.tsx +78 -0
  82. package/data/examples/enable-detail-panel-virtualized.js +64 -0
  83. package/data/examples/enable-detail-panel-virtualized.tsx +80 -0
  84. package/data/examples/enable-expanding-tree.js +87 -0
  85. package/data/examples/enable-expanding-tree.tsx +110 -0
  86. package/data/examples/enable-filter-facet-values.js +52 -0
  87. package/data/examples/enable-filter-facet-values.tsx +65 -0
  88. package/data/examples/enable-row-dragging.js +102 -0
  89. package/data/examples/enable-row-dragging.tsx +137 -0
  90. package/data/examples/enable-row-numbers-original.js +37 -0
  91. package/data/examples/enable-row-numbers-original.tsx +48 -0
  92. package/data/examples/enable-row-numbers-static.js +37 -0
  93. package/data/examples/enable-row-numbers-static.tsx +48 -0
  94. package/data/examples/enable-row-ordering.js +40 -0
  95. package/data/examples/enable-row-ordering.tsx +57 -0
  96. package/data/examples/enable-row-pinning-select.js +64 -0
  97. package/data/examples/enable-row-pinning-select.tsx +76 -0
  98. package/data/examples/enable-row-pinning-static.js +39 -0
  99. package/data/examples/enable-row-pinning-static.tsx +50 -0
  100. package/data/examples/enable-row-pinning-sticky.js +57 -0
  101. package/data/examples/enable-row-pinning-sticky.tsx +69 -0
  102. package/data/examples/enable-row-selection.js +71 -0
  103. package/data/examples/enable-row-selection.tsx +96 -0
  104. package/data/examples/enable-row-virtualization.js +85 -0
  105. package/data/examples/enable-row-virtualization.tsx +101 -0
  106. package/data/examples/enable-sticky-header.js +47 -0
  107. package/data/examples/enable-sticky-header.tsx +59 -0
  108. package/data/examples/expanding-tree-expanded.js +98 -0
  109. package/data/examples/expanding-tree-expanded.tsx +121 -0
  110. package/data/examples/expanding-tree-flat-parse.js +102 -0
  111. package/data/examples/expanding-tree-flat-parse.tsx +125 -0
  112. package/data/examples/expanding-tree-root-expanded.js +120 -0
  113. package/data/examples/expanding-tree-root-expanded.tsx +151 -0
  114. package/data/examples/export-to-csv.js +84 -0
  115. package/data/examples/export-to-csv.tsx +114 -0
  116. package/data/examples/export-to-pdf.js +76 -0
  117. package/data/examples/export-to-pdf.tsx +104 -0
  118. package/data/examples/external-toolbar.js +82 -0
  119. package/data/examples/external-toolbar.tsx +108 -0
  120. package/data/examples/font-awesome-icons.js +62 -0
  121. package/data/examples/font-awesome-icons.tsx +106 -0
  122. package/data/examples/infinite-scrolling.js +137 -0
  123. package/data/examples/infinite-scrolling.tsx +208 -0
  124. package/data/examples/lazy-detail-panel.js +164 -0
  125. package/data/examples/lazy-detail-panel.tsx +262 -0
  126. package/data/examples/lazy-sub-rows.js +118 -0
  127. package/data/examples/lazy-sub-rows.tsx +190 -0
  128. package/data/examples/linear-progress.js +48 -0
  129. package/data/examples/linear-progress.tsx +66 -0
  130. package/data/examples/loading.js +34 -0
  131. package/data/examples/loading.tsx +50 -0
  132. package/data/examples/localization-i18n-ar.js +40 -0
  133. package/data/examples/localization-i18n-ar.tsx +65 -0
  134. package/data/examples/localization-i18n-az.js +38 -0
  135. package/data/examples/localization-i18n-az.tsx +60 -0
  136. package/data/examples/localization-i18n-bg.js +38 -0
  137. package/data/examples/localization-i18n-bg.tsx +60 -0
  138. package/data/examples/localization-i18n-cs.js +38 -0
  139. package/data/examples/localization-i18n-cs.tsx +60 -0
  140. package/data/examples/localization-i18n-da.js +38 -0
  141. package/data/examples/localization-i18n-da.tsx +60 -0
  142. package/data/examples/localization-i18n-de.js +38 -0
  143. package/data/examples/localization-i18n-de.tsx +60 -0
  144. package/data/examples/localization-i18n-el.js +38 -0
  145. package/data/examples/localization-i18n-el.tsx +60 -0
  146. package/data/examples/localization-i18n-en.js +38 -0
  147. package/data/examples/localization-i18n-en.tsx +60 -0
  148. package/data/examples/localization-i18n-es.js +38 -0
  149. package/data/examples/localization-i18n-es.tsx +60 -0
  150. package/data/examples/localization-i18n-et.js +38 -0
  151. package/data/examples/localization-i18n-et.tsx +60 -0
  152. package/data/examples/localization-i18n-fa.js +40 -0
  153. package/data/examples/localization-i18n-fa.tsx +66 -0
  154. package/data/examples/localization-i18n-fi.js +38 -0
  155. package/data/examples/localization-i18n-fi.tsx +60 -0
  156. package/data/examples/localization-i18n-fr.js +38 -0
  157. package/data/examples/localization-i18n-fr.tsx +60 -0
  158. package/data/examples/localization-i18n-he.js +40 -0
  159. package/data/examples/localization-i18n-he.tsx +66 -0
  160. package/data/examples/localization-i18n-hr.js +38 -0
  161. package/data/examples/localization-i18n-hr.tsx +60 -0
  162. package/data/examples/localization-i18n-hu.js +38 -0
  163. package/data/examples/localization-i18n-hu.tsx +60 -0
  164. package/data/examples/localization-i18n-hy.js +40 -0
  165. package/data/examples/localization-i18n-hy.tsx +65 -0
  166. package/data/examples/localization-i18n-id.js +38 -0
  167. package/data/examples/localization-i18n-id.tsx +60 -0
  168. package/data/examples/localization-i18n-it.js +38 -0
  169. package/data/examples/localization-i18n-it.tsx +60 -0
  170. package/data/examples/localization-i18n-ja.js +38 -0
  171. package/data/examples/localization-i18n-ja.tsx +60 -0
  172. package/data/examples/localization-i18n-ko.js +38 -0
  173. package/data/examples/localization-i18n-ko.tsx +60 -0
  174. package/data/examples/localization-i18n-nl.js +38 -0
  175. package/data/examples/localization-i18n-nl.tsx +60 -0
  176. package/data/examples/localization-i18n-no.js +38 -0
  177. package/data/examples/localization-i18n-no.tsx +60 -0
  178. package/data/examples/localization-i18n-np.js +38 -0
  179. package/data/examples/localization-i18n-np.tsx +60 -0
  180. package/data/examples/localization-i18n-pl.js +38 -0
  181. package/data/examples/localization-i18n-pl.tsx +60 -0
  182. package/data/examples/localization-i18n-pt-BR.js +38 -0
  183. package/data/examples/localization-i18n-pt-BR.tsx +60 -0
  184. package/data/examples/localization-i18n-pt.js +38 -0
  185. package/data/examples/localization-i18n-pt.tsx +60 -0
  186. package/data/examples/localization-i18n-ro.js +38 -0
  187. package/data/examples/localization-i18n-ro.tsx +60 -0
  188. package/data/examples/localization-i18n-ru.js +38 -0
  189. package/data/examples/localization-i18n-ru.tsx +60 -0
  190. package/data/examples/localization-i18n-sk.js +38 -0
  191. package/data/examples/localization-i18n-sk.tsx +60 -0
  192. package/data/examples/localization-i18n-sr-Cyrl-RS.js +38 -0
  193. package/data/examples/localization-i18n-sr-Cyrl-RS.tsx +60 -0
  194. package/data/examples/localization-i18n-sr-Latn-RS.js +38 -0
  195. package/data/examples/localization-i18n-sr-Latn-RS.tsx +60 -0
  196. package/data/examples/localization-i18n-sv.js +38 -0
  197. package/data/examples/localization-i18n-sv.tsx +60 -0
  198. package/data/examples/localization-i18n-tr.js +38 -0
  199. package/data/examples/localization-i18n-tr.tsx +60 -0
  200. package/data/examples/localization-i18n-uk.js +38 -0
  201. package/data/examples/localization-i18n-uk.tsx +60 -0
  202. package/data/examples/localization-i18n-vi.js +38 -0
  203. package/data/examples/localization-i18n-vi.tsx +60 -0
  204. package/data/examples/localization-i18n-zh-hans.js +38 -0
  205. package/data/examples/localization-i18n-zh-hans.tsx +60 -0
  206. package/data/examples/localization-i18n-zh-hant.js +38 -0
  207. package/data/examples/localization-i18n-zh-hant.tsx +60 -0
  208. package/data/examples/manual-selection.js +81 -0
  209. package/data/examples/manual-selection.tsx +105 -0
  210. package/data/examples/minimal.js +66 -0
  211. package/data/examples/minimal.tsx +78 -0
  212. package/data/examples/mui-theme.js +109 -0
  213. package/data/examples/mui-theme.tsx +136 -0
  214. package/data/examples/multi-sorting.js +48 -0
  215. package/data/examples/multi-sorting.tsx +58 -0
  216. package/data/examples/persistent-state.js +126 -0
  217. package/data/examples/persistent-state.tsx +184 -0
  218. package/data/examples/react-query.js +122 -0
  219. package/data/examples/react-query.tsx +182 -0
  220. package/data/examples/remote.js +113 -0
  221. package/data/examples/remote.tsx +150 -0
  222. package/data/examples/row-actions-buttons.js +54 -0
  223. package/data/examples/row-actions-buttons.tsx +89 -0
  224. package/data/examples/row-actions-menu-items.js +36 -0
  225. package/data/examples/row-actions-menu-items.tsx +64 -0
  226. package/data/examples/single-row-selection.js +74 -0
  227. package/data/examples/single-row-selection.tsx +98 -0
  228. package/data/examples/virtualized.js +122 -0
  229. package/data/examples/virtualized.tsx +138 -0
  230. package/data/guides/accessibility.md +119 -0
  231. package/data/guides/aggregation.md +210 -0
  232. package/data/guides/async-loading.md +132 -0
  233. package/data/guides/best-practices.md +363 -0
  234. package/data/guides/cell-actions.md +139 -0
  235. package/data/guides/click-to-copy.md +67 -0
  236. package/data/guides/column-actions.md +69 -0
  237. package/data/guides/column-filtering.md +366 -0
  238. package/data/guides/column-grouping.md +192 -0
  239. package/data/guides/column-hiding.md +133 -0
  240. package/data/guides/column-ordering-dnd.md +99 -0
  241. package/data/guides/column-pinning.md +72 -0
  242. package/data/guides/column-resizing.md +157 -0
  243. package/data/guides/column-size.md +162 -0
  244. package/data/guides/customize-components.md +395 -0
  245. package/data/guides/customize-icons.md +35 -0
  246. package/data/guides/data-columns.md +292 -0
  247. package/data/guides/density-toggle.md +46 -0
  248. package/data/guides/detail-panel.md +195 -0
  249. package/data/guides/display-columns.md +135 -0
  250. package/data/guides/editing.md +367 -0
  251. package/data/guides/expanding-sub-rows.md +194 -0
  252. package/data/guides/full-screen-toggle.md +63 -0
  253. package/data/guides/global-filtering.md +237 -0
  254. package/data/guides/localization.md +57 -0
  255. package/data/guides/memoization.md +157 -0
  256. package/data/guides/pagination.md +171 -0
  257. package/data/guides/row-actions.md +116 -0
  258. package/data/guides/row-numbers.md +24 -0
  259. package/data/guides/row-ordering-dnd.md +51 -0
  260. package/data/guides/row-pinning.md +96 -0
  261. package/data/guides/row-selection.md +237 -0
  262. package/data/guides/sorting.md +190 -0
  263. package/data/guides/state-management.md +165 -0
  264. package/data/guides/sticky-header.md +41 -0
  265. package/data/guides/table-event-listeners.md +103 -0
  266. package/data/guides/toolbar-customization.md +251 -0
  267. package/data/guides/virtualization.md +183 -0
  268. package/data/index.json +1930 -0
  269. package/data/reference/mrt-components.md +183 -0
  270. package/data/reference/mrt-hooks.md +125 -0
  271. package/data/skills/README.md +81 -0
  272. package/data/skills/composable-components/SKILL.md +189 -0
  273. package/data/skills/customization/SKILL.md +190 -0
  274. package/data/skills/drag-and-drop-ordering/SKILL.md +227 -0
  275. package/data/skills/editing/SKILL.md +243 -0
  276. package/data/skills/filtering/SKILL.md +213 -0
  277. package/data/skills/getting-started/SKILL.md +213 -0
  278. package/data/skills/localization/SKILL.md +182 -0
  279. package/data/skills/migrate-v3-to-v4/SKILL.md +161 -0
  280. package/data/skills/state-and-server-data/SKILL.md +200 -0
  281. package/data/skills/virtualization/SKILL.md +203 -0
  282. package/dist/data.js +159 -0
  283. package/dist/index.js +244 -0
  284. package/package.json +50 -0
@@ -0,0 +1,215 @@
1
+ import { useMemo } from 'react';
2
+ //MRT Imports
3
+ import { MaterialReactTable, useMaterialReactTable, MRT_GlobalFilterTextField, MRT_ToggleFiltersButton, } from 'material-react-table';
4
+ //Material UI Imports
5
+ import { Box, Button, ListItemIcon, MenuItem, Typography, lighten, } from '@mui/material';
6
+ //Icons Imports
7
+ import { AccountCircle, Send } from '@mui/icons-material';
8
+ //Mock Data
9
+ import { data } from './makeData';
10
+ const Example = () => {
11
+ const columns = useMemo(() => [
12
+ {
13
+ id: 'employee', //id used to define `group` column
14
+ header: 'Employee',
15
+ columns: [
16
+ {
17
+ accessorFn: (row) => `${row.firstName} ${row.lastName}`, //accessorFn used to join multiple data into a single cell
18
+ id: 'name', //id is still required when using accessorFn instead of accessorKey
19
+ header: 'Name',
20
+ size: 250,
21
+ Cell: ({ renderedCellValue, row }) => (<Box sx={{
22
+ display: 'flex',
23
+ alignItems: 'center',
24
+ gap: '1rem',
25
+ }}>
26
+ <img alt="avatar" height={30} src={row.original.avatar} loading="lazy" style={{ borderRadius: '50%' }}/>
27
+ {/* using renderedCellValue instead of cell.getValue() preserves filter match highlighting */}
28
+ <span>{renderedCellValue}</span>
29
+ </Box>),
30
+ },
31
+ {
32
+ accessorKey: 'email', //accessorKey used to define `data` column. `id` gets set to accessorKey automatically
33
+ enableClickToCopy: true,
34
+ filterVariant: 'autocomplete',
35
+ header: 'Email',
36
+ size: 300,
37
+ },
38
+ ],
39
+ },
40
+ {
41
+ id: 'id',
42
+ header: 'Job Info',
43
+ columns: [
44
+ {
45
+ accessorKey: 'salary',
46
+ // filterVariant: 'range', //if not using filter modes feature, use this instead of filterFn
47
+ filterFn: 'between',
48
+ header: 'Salary',
49
+ size: 200,
50
+ //custom conditional format and styling
51
+ Cell: ({ cell }) => (<Box component="span" sx={(theme) => ({
52
+ backgroundColor: cell.getValue() < 50000
53
+ ? theme.palette.error.dark
54
+ : cell.getValue() >= 50000 &&
55
+ cell.getValue() < 75000
56
+ ? theme.palette.warning.dark
57
+ : theme.palette.success.dark,
58
+ borderRadius: '0.25rem',
59
+ color: '#fff',
60
+ maxWidth: '9ch',
61
+ p: '0.25rem',
62
+ })}>
63
+ {cell.getValue()?.toLocaleString?.('en-US', {
64
+ style: 'currency',
65
+ currency: 'USD',
66
+ minimumFractionDigits: 0,
67
+ maximumFractionDigits: 0,
68
+ })}
69
+ </Box>),
70
+ },
71
+ {
72
+ accessorKey: 'jobTitle', //hey a simple column for once
73
+ header: 'Job Title',
74
+ size: 350,
75
+ },
76
+ {
77
+ accessorFn: (row) => new Date(row.startDate), //convert to Date for sorting and filtering
78
+ id: 'startDate',
79
+ header: 'Start Date',
80
+ filterVariant: 'date',
81
+ filterFn: 'lessThan',
82
+ sortFn: 'datetime',
83
+ Cell: ({ cell }) => cell.getValue()?.toLocaleDateString(), //render Date as a string
84
+ Header: ({ column }) => <em>{column.columnDef.header}</em>, //custom header markup
85
+ muiFilterTextFieldProps: {
86
+ sx: {
87
+ minWidth: '250px',
88
+ },
89
+ },
90
+ },
91
+ ],
92
+ },
93
+ ], []);
94
+ const table = useMaterialReactTable({
95
+ columns,
96
+ data, //data must be memoized or stable (useState, useMemo, defined outside of this component, etc.)
97
+ enableColumnFilterModes: true,
98
+ enableColumnOrdering: true,
99
+ enableGrouping: true,
100
+ enableColumnPinning: true,
101
+ enableFacetedValues: true,
102
+ enableRowActions: true,
103
+ enableRowSelection: true,
104
+ initialState: {
105
+ showColumnFilters: true,
106
+ showGlobalFilter: true,
107
+ columnPinning: {
108
+ end: ['mrt-row-actions'],
109
+ start: ['mrt-row-expand', 'mrt-row-select'],
110
+ },
111
+ },
112
+ paginationDisplayMode: 'pages',
113
+ positionToolbarAlertBanner: 'bottom',
114
+ muiSearchTextFieldProps: {
115
+ size: 'small',
116
+ variant: 'outlined',
117
+ },
118
+ muiPaginationProps: {
119
+ color: 'secondary',
120
+ rowsPerPageOptions: [10, 20, 30],
121
+ shape: 'rounded',
122
+ variant: 'outlined',
123
+ },
124
+ renderDetailPanel: ({ row }) => (<Box sx={{
125
+ alignItems: 'center',
126
+ display: 'flex',
127
+ justifyContent: 'space-around',
128
+ left: '30px',
129
+ maxWidth: '1000px',
130
+ position: 'sticky',
131
+ width: '100%',
132
+ }}>
133
+ <img alt="avatar" height={200} src={row.original.avatar} loading="lazy" style={{ borderRadius: '50%' }}/>
134
+ <Box sx={{ textAlign: 'center' }}>
135
+ <Typography variant="h4">Signature Catch Phrase:</Typography>
136
+ <Typography variant="h1">
137
+ &quot;{row.original.signatureCatchPhrase}&quot;
138
+ </Typography>
139
+ </Box>
140
+ </Box>),
141
+ renderRowActionMenuItems: ({ closeMenu }) => [
142
+ <MenuItem key={0} onClick={() => {
143
+ // View profile logic...
144
+ closeMenu();
145
+ }} sx={{ m: 0 }}>
146
+ <ListItemIcon>
147
+ <AccountCircle />
148
+ </ListItemIcon>
149
+ View Profile
150
+ </MenuItem>,
151
+ <MenuItem key={1} onClick={() => {
152
+ // Send email logic...
153
+ closeMenu();
154
+ }} sx={{ m: 0 }}>
155
+ <ListItemIcon>
156
+ <Send />
157
+ </ListItemIcon>
158
+ Send Email
159
+ </MenuItem>,
160
+ ],
161
+ renderTopToolbar: ({ table }) => {
162
+ const handleDeactivate = () => {
163
+ table.getSelectedRowModel().flatRows.map((row) => {
164
+ alert('deactivating ' + row.getValue('name'));
165
+ });
166
+ };
167
+ const handleActivate = () => {
168
+ table.getSelectedRowModel().flatRows.map((row) => {
169
+ alert('activating ' + row.getValue('name'));
170
+ });
171
+ };
172
+ const handleContact = () => {
173
+ table.getSelectedRowModel().flatRows.map((row) => {
174
+ alert('contact ' + row.getValue('name'));
175
+ });
176
+ };
177
+ return (<Box sx={(theme) => ({
178
+ backgroundColor: lighten(theme.palette.background.default, 0.05),
179
+ display: 'flex',
180
+ gap: '0.5rem',
181
+ p: '8px',
182
+ justifyContent: 'space-between',
183
+ })}>
184
+ <Box sx={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
185
+ {/* import MRT sub-components */}
186
+ <MRT_GlobalFilterTextField table={table}/>
187
+ <MRT_ToggleFiltersButton table={table}/>
188
+ </Box>
189
+ <Box>
190
+ <Box sx={{ display: 'flex', gap: '0.5rem' }}>
191
+ <Button color="error" disabled={!table.getIsSomeRowsSelected()} onClick={handleDeactivate} variant="contained">
192
+ Deactivate
193
+ </Button>
194
+ <Button color="success" disabled={!table.getIsSomeRowsSelected()} onClick={handleActivate} variant="contained">
195
+ Activate
196
+ </Button>
197
+ <Button color="info" disabled={!table.getIsSomeRowsSelected()} onClick={handleContact} variant="contained">
198
+ Contact
199
+ </Button>
200
+ </Box>
201
+ </Box>
202
+ </Box>);
203
+ },
204
+ });
205
+ return <MaterialReactTable table={table}/>;
206
+ };
207
+ //Date Picker Imports - these should just be in your Context Provider
208
+ import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
209
+ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
210
+ const ExampleWithLocalizationProvider = () => (
211
+ //App.tsx or AppProviders file
212
+ <LocalizationProvider dateAdapter={AdapterDayjs}>
213
+ <Example />
214
+ </LocalizationProvider>);
215
+ export default ExampleWithLocalizationProvider;
@@ -0,0 +1,309 @@
1
+ import { useMemo } from 'react';
2
+
3
+ //MRT Imports
4
+ import {
5
+ MaterialReactTable,
6
+ useMaterialReactTable,
7
+ type MRT_ColumnDef,
8
+ MRT_GlobalFilterTextField,
9
+ MRT_ToggleFiltersButton,
10
+ } from 'material-react-table';
11
+
12
+ //Material UI Imports
13
+ import {
14
+ Box,
15
+ Button,
16
+ ListItemIcon,
17
+ MenuItem,
18
+ Typography,
19
+ lighten,
20
+ } from '@mui/material';
21
+
22
+ //Icons Imports
23
+ import { AccountCircle, Send } from '@mui/icons-material';
24
+
25
+ //Mock Data
26
+ import { data } from './makeData';
27
+
28
+ export type Employee = {
29
+ firstName: string;
30
+ lastName: string;
31
+ email: string;
32
+ jobTitle: string;
33
+ salary: number;
34
+ startDate: string;
35
+ signatureCatchPhrase: string;
36
+ avatar: string;
37
+ };
38
+
39
+ const Example = () => {
40
+ const columns = useMemo<MRT_ColumnDef<Employee>[]>(
41
+ () => [
42
+ {
43
+ id: 'employee', //id used to define `group` column
44
+ header: 'Employee',
45
+ columns: [
46
+ {
47
+ accessorFn: (row) => `${row.firstName} ${row.lastName}`, //accessorFn used to join multiple data into a single cell
48
+ id: 'name', //id is still required when using accessorFn instead of accessorKey
49
+ header: 'Name',
50
+ size: 250,
51
+ Cell: ({ renderedCellValue, row }) => (
52
+ <Box
53
+ sx={{
54
+ display: 'flex',
55
+ alignItems: 'center',
56
+ gap: '1rem',
57
+ }}
58
+ >
59
+ <img
60
+ alt="avatar"
61
+ height={30}
62
+ src={row.original.avatar}
63
+ loading="lazy"
64
+ style={{ borderRadius: '50%' }}
65
+ />
66
+ {/* using renderedCellValue instead of cell.getValue() preserves filter match highlighting */}
67
+ <span>{renderedCellValue}</span>
68
+ </Box>
69
+ ),
70
+ },
71
+ {
72
+ accessorKey: 'email', //accessorKey used to define `data` column. `id` gets set to accessorKey automatically
73
+ enableClickToCopy: true,
74
+ filterVariant: 'autocomplete',
75
+ header: 'Email',
76
+ size: 300,
77
+ },
78
+ ],
79
+ },
80
+ {
81
+ id: 'id',
82
+ header: 'Job Info',
83
+ columns: [
84
+ {
85
+ accessorKey: 'salary',
86
+ // filterVariant: 'range', //if not using filter modes feature, use this instead of filterFn
87
+ filterFn: 'between',
88
+ header: 'Salary',
89
+ size: 200,
90
+ //custom conditional format and styling
91
+ Cell: ({ cell }) => (
92
+ <Box
93
+ component="span"
94
+ sx={(theme) => ({
95
+ backgroundColor:
96
+ cell.getValue<number>() < 50_000
97
+ ? theme.palette.error.dark
98
+ : cell.getValue<number>() >= 50_000 &&
99
+ cell.getValue<number>() < 75_000
100
+ ? theme.palette.warning.dark
101
+ : theme.palette.success.dark,
102
+ borderRadius: '0.25rem',
103
+ color: '#fff',
104
+ maxWidth: '9ch',
105
+ p: '0.25rem',
106
+ })}
107
+ >
108
+ {cell.getValue<number>()?.toLocaleString?.('en-US', {
109
+ style: 'currency',
110
+ currency: 'USD',
111
+ minimumFractionDigits: 0,
112
+ maximumFractionDigits: 0,
113
+ })}
114
+ </Box>
115
+ ),
116
+ },
117
+ {
118
+ accessorKey: 'jobTitle', //hey a simple column for once
119
+ header: 'Job Title',
120
+ size: 350,
121
+ },
122
+ {
123
+ accessorFn: (row) => new Date(row.startDate), //convert to Date for sorting and filtering
124
+ id: 'startDate',
125
+ header: 'Start Date',
126
+ filterVariant: 'date',
127
+ filterFn: 'lessThan',
128
+ sortFn: 'datetime',
129
+ Cell: ({ cell }) => cell.getValue<Date>()?.toLocaleDateString(), //render Date as a string
130
+ Header: ({ column }) => <em>{column.columnDef.header}</em>, //custom header markup
131
+ muiFilterTextFieldProps: {
132
+ sx: {
133
+ minWidth: '250px',
134
+ },
135
+ },
136
+ },
137
+ ],
138
+ },
139
+ ],
140
+ [],
141
+ );
142
+
143
+ const table = useMaterialReactTable({
144
+ columns,
145
+ data, //data must be memoized or stable (useState, useMemo, defined outside of this component, etc.)
146
+ enableColumnFilterModes: true,
147
+ enableColumnOrdering: true,
148
+ enableGrouping: true,
149
+ enableColumnPinning: true,
150
+ enableFacetedValues: true,
151
+ enableRowActions: true,
152
+ enableRowSelection: true,
153
+ initialState: {
154
+ showColumnFilters: true,
155
+ showGlobalFilter: true,
156
+ columnPinning: {
157
+ end: ['mrt-row-actions'],
158
+ start: ['mrt-row-expand', 'mrt-row-select'],
159
+ },
160
+ },
161
+ paginationDisplayMode: 'pages',
162
+ positionToolbarAlertBanner: 'bottom',
163
+ muiSearchTextFieldProps: {
164
+ size: 'small',
165
+ variant: 'outlined',
166
+ },
167
+ muiPaginationProps: {
168
+ color: 'secondary',
169
+ rowsPerPageOptions: [10, 20, 30],
170
+ shape: 'rounded',
171
+ variant: 'outlined',
172
+ },
173
+ renderDetailPanel: ({ row }) => (
174
+ <Box
175
+ sx={{
176
+ alignItems: 'center',
177
+ display: 'flex',
178
+ justifyContent: 'space-around',
179
+ left: '30px',
180
+ maxWidth: '1000px',
181
+ position: 'sticky',
182
+ width: '100%',
183
+ }}
184
+ >
185
+ <img
186
+ alt="avatar"
187
+ height={200}
188
+ src={row.original.avatar}
189
+ loading="lazy"
190
+ style={{ borderRadius: '50%' }}
191
+ />
192
+ <Box sx={{ textAlign: 'center' }}>
193
+ <Typography variant="h4">Signature Catch Phrase:</Typography>
194
+ <Typography variant="h1">
195
+ &quot;{row.original.signatureCatchPhrase}&quot;
196
+ </Typography>
197
+ </Box>
198
+ </Box>
199
+ ),
200
+ renderRowActionMenuItems: ({ closeMenu }) => [
201
+ <MenuItem
202
+ key={0}
203
+ onClick={() => {
204
+ // View profile logic...
205
+ closeMenu();
206
+ }}
207
+ sx={{ m: 0 }}
208
+ >
209
+ <ListItemIcon>
210
+ <AccountCircle />
211
+ </ListItemIcon>
212
+ View Profile
213
+ </MenuItem>,
214
+ <MenuItem
215
+ key={1}
216
+ onClick={() => {
217
+ // Send email logic...
218
+ closeMenu();
219
+ }}
220
+ sx={{ m: 0 }}
221
+ >
222
+ <ListItemIcon>
223
+ <Send />
224
+ </ListItemIcon>
225
+ Send Email
226
+ </MenuItem>,
227
+ ],
228
+ renderTopToolbar: ({ table }) => {
229
+ const handleDeactivate = () => {
230
+ table.getSelectedRowModel().flatRows.map((row) => {
231
+ alert('deactivating ' + row.getValue('name'));
232
+ });
233
+ };
234
+
235
+ const handleActivate = () => {
236
+ table.getSelectedRowModel().flatRows.map((row) => {
237
+ alert('activating ' + row.getValue('name'));
238
+ });
239
+ };
240
+
241
+ const handleContact = () => {
242
+ table.getSelectedRowModel().flatRows.map((row) => {
243
+ alert('contact ' + row.getValue('name'));
244
+ });
245
+ };
246
+
247
+ return (
248
+ <Box
249
+ sx={(theme) => ({
250
+ backgroundColor: lighten(theme.palette.background.default, 0.05),
251
+ display: 'flex',
252
+ gap: '0.5rem',
253
+ p: '8px',
254
+ justifyContent: 'space-between',
255
+ })}
256
+ >
257
+ <Box sx={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
258
+ {/* import MRT sub-components */}
259
+ <MRT_GlobalFilterTextField table={table} />
260
+ <MRT_ToggleFiltersButton table={table} />
261
+ </Box>
262
+ <Box>
263
+ <Box sx={{ display: 'flex', gap: '0.5rem' }}>
264
+ <Button
265
+ color="error"
266
+ disabled={!table.getIsSomeRowsSelected()}
267
+ onClick={handleDeactivate}
268
+ variant="contained"
269
+ >
270
+ Deactivate
271
+ </Button>
272
+ <Button
273
+ color="success"
274
+ disabled={!table.getIsSomeRowsSelected()}
275
+ onClick={handleActivate}
276
+ variant="contained"
277
+ >
278
+ Activate
279
+ </Button>
280
+ <Button
281
+ color="info"
282
+ disabled={!table.getIsSomeRowsSelected()}
283
+ onClick={handleContact}
284
+ variant="contained"
285
+ >
286
+ Contact
287
+ </Button>
288
+ </Box>
289
+ </Box>
290
+ </Box>
291
+ );
292
+ },
293
+ });
294
+
295
+ return <MaterialReactTable table={table} />;
296
+ };
297
+
298
+ //Date Picker Imports - these should just be in your Context Provider
299
+ import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
300
+ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
301
+
302
+ const ExampleWithLocalizationProvider = () => (
303
+ //App.tsx or AppProviders file
304
+ <LocalizationProvider dateAdapter={AdapterDayjs}>
305
+ <Example />
306
+ </LocalizationProvider>
307
+ );
308
+
309
+ export default ExampleWithLocalizationProvider;
@@ -0,0 +1,116 @@
1
+ import { useMemo } from 'react';
2
+ import { Box, Stack } from '@mui/material';
3
+ import { MaterialReactTable, useMaterialReactTable, } from 'material-react-table';
4
+ import { data } from './makeData';
5
+ const Example = () => {
6
+ const averageSalary = useMemo(() => data.reduce((acc, curr) => acc + curr.salary, 0) / data.length, []);
7
+ const maxAge = useMemo(() => data.reduce((acc, curr) => Math.max(acc, curr.age), 0), []);
8
+ const columns = useMemo(() => [
9
+ {
10
+ header: 'First Name',
11
+ accessorKey: 'firstName',
12
+ enableGrouping: false, //do not let this column be grouped
13
+ },
14
+ {
15
+ header: 'Last Name',
16
+ accessorKey: 'lastName',
17
+ },
18
+ {
19
+ header: 'Age',
20
+ accessorKey: 'age',
21
+ aggregationFn: 'max', //show the max age in the group (lots of pre-built aggregationFns to choose from)
22
+ //required to render an aggregated cell
23
+ AggregatedCell: ({ cell, table }) => (<>
24
+ Oldest by{' '}
25
+ {table.getColumn(cell.row.groupingColumnId ?? '').columnDef.header}:{' '}
26
+ <Box sx={{ color: 'info.main', display: 'inline', fontWeight: 'bold' }}>
27
+ {cell.getValue()}
28
+ </Box>
29
+ </>),
30
+ Footer: () => (<Stack>
31
+ Max Age:
32
+ <Box sx={{
33
+ color: 'warning.main',
34
+ }}>
35
+ {Math.round(maxAge)}
36
+ </Box>
37
+ </Stack>),
38
+ },
39
+ {
40
+ header: 'Gender',
41
+ accessorKey: 'gender',
42
+ //optionally, customize the cell render when this column is grouped. Make the text blue and pluralize the word
43
+ GroupedCell: ({ cell, row }) => (<Box sx={{ color: 'primary.main' }}>
44
+ <strong>{cell.getValue()}s </strong> ({row.subRows?.length})
45
+ </Box>),
46
+ },
47
+ {
48
+ header: 'State',
49
+ accessorKey: 'state',
50
+ },
51
+ {
52
+ header: 'Salary',
53
+ accessorKey: 'salary',
54
+ aggregationFn: 'mean',
55
+ //required to render an aggregated cell, show the average salary in the group
56
+ AggregatedCell: ({ cell, table }) => (<>
57
+ Average by{' '}
58
+ {table.getColumn(cell.row.groupingColumnId ?? '').columnDef.header}:{' '}
59
+ <Box sx={{ color: 'success.main', fontWeight: 'bold' }}>
60
+ {cell.getValue()?.toLocaleString?.('en-US', {
61
+ style: 'currency',
62
+ currency: 'USD',
63
+ minimumFractionDigits: 0,
64
+ maximumFractionDigits: 0,
65
+ })}
66
+ </Box>
67
+ </>),
68
+ //customize normal cell render on normal non-aggregated rows
69
+ Cell: ({ cell }) => (<>
70
+ {cell.getValue()?.toLocaleString?.('en-US', {
71
+ style: 'currency',
72
+ currency: 'USD',
73
+ minimumFractionDigits: 0,
74
+ maximumFractionDigits: 0,
75
+ })}
76
+ </>),
77
+ Footer: () => (<Stack>
78
+ Average Salary:
79
+ <Box sx={{
80
+ color: 'warning.main',
81
+ }}>
82
+ {averageSalary?.toLocaleString?.('en-US', {
83
+ style: 'currency',
84
+ currency: 'USD',
85
+ minimumFractionDigits: 0,
86
+ maximumFractionDigits: 0,
87
+ })}
88
+ </Box>
89
+ </Stack>),
90
+ },
91
+ ], [averageSalary, maxAge]);
92
+ const table = useMaterialReactTable({
93
+ columns,
94
+ data,
95
+ displayColumnDefOptions: {
96
+ 'mrt-row-expand': {
97
+ enableResizing: true,
98
+ },
99
+ },
100
+ enableColumnResizing: true,
101
+ enableGrouping: true,
102
+ enableStickyHeader: true,
103
+ enableStickyFooter: true,
104
+ initialState: {
105
+ density: 'compact',
106
+ expanded: true, //expand all groups by default
107
+ grouping: ['state'], //an array of columns to group by by default (can be multiple)
108
+ pagination: { pageIndex: 0, pageSize: 20 },
109
+ sorting: [{ id: 'state', desc: false }], //sort by state by default
110
+ },
111
+ muiToolbarAlertBannerChipProps: { color: 'primary' },
112
+ muiTableContainerProps: { sx: { maxHeight: 700 } },
113
+ });
114
+ return <MaterialReactTable table={table}/>;
115
+ };
116
+ export default Example;