@okta/odyssey-react-mui 1.14.3 → 1.14.4

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 (69) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/DataTable/DataTable.js +330 -0
  3. package/dist/DataTable/DataTable.js.map +1 -0
  4. package/dist/DataTable/DataTableRowActions.js +89 -0
  5. package/dist/DataTable/DataTableRowActions.js.map +1 -0
  6. package/dist/DataTable/DataTableSettings.js +72 -0
  7. package/dist/DataTable/DataTableSettings.js.map +1 -0
  8. package/dist/DataTable/constants.js +14 -0
  9. package/dist/DataTable/constants.js.map +1 -0
  10. package/dist/DataTable/index.js +14 -0
  11. package/dist/DataTable/index.js.map +1 -0
  12. package/dist/DataTable/reorderDataRowsLocally.js +26 -0
  13. package/dist/DataTable/reorderDataRowsLocally.js.map +1 -0
  14. package/dist/DataTable/useRowReordering.js +179 -0
  15. package/dist/DataTable/useRowReordering.js.map +1 -0
  16. package/dist/index.js +1 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/labs/DataFilters.js +42 -14
  19. package/dist/labs/DataFilters.js.map +1 -1
  20. package/dist/labs/DataTable.js +16 -11
  21. package/dist/labs/DataTable.js.map +1 -1
  22. package/dist/labs/index.js +0 -1
  23. package/dist/labs/index.js.map +1 -1
  24. package/dist/properties/ts/odyssey-react-mui.js +18 -1
  25. package/dist/properties/ts/odyssey-react-mui.js.map +1 -1
  26. package/dist/src/DataTable/DataTable.d.ts +133 -0
  27. package/dist/src/DataTable/DataTable.d.ts.map +1 -0
  28. package/dist/src/DataTable/DataTableRowActions.d.ts +30 -0
  29. package/dist/src/DataTable/DataTableRowActions.d.ts.map +1 -0
  30. package/dist/src/DataTable/DataTableSettings.d.ts +27 -0
  31. package/dist/src/DataTable/DataTableSettings.d.ts.map +1 -0
  32. package/dist/src/DataTable/constants.d.ts +13 -0
  33. package/dist/src/DataTable/constants.d.ts.map +1 -0
  34. package/dist/src/DataTable/index.d.ts +15 -0
  35. package/dist/src/DataTable/index.d.ts.map +1 -0
  36. package/dist/src/DataTable/reorderDataRowsLocally.d.ts +26 -0
  37. package/dist/src/DataTable/reorderDataRowsLocally.d.ts.map +1 -0
  38. package/dist/src/DataTable/useRowReordering.d.ts +56 -0
  39. package/dist/src/DataTable/useRowReordering.d.ts.map +1 -0
  40. package/dist/src/OdysseyTranslationProvider.d.ts +1 -1
  41. package/dist/src/OdysseyTranslationProvider.d.ts.map +1 -1
  42. package/dist/src/index.d.ts +1 -0
  43. package/dist/src/index.d.ts.map +1 -1
  44. package/dist/src/labs/DataFilters.d.ts.map +1 -1
  45. package/dist/src/labs/DataTable.d.ts +2 -2
  46. package/dist/src/labs/DataTable.d.ts.map +1 -1
  47. package/dist/src/labs/index.d.ts +0 -1
  48. package/dist/src/labs/index.d.ts.map +1 -1
  49. package/dist/src/properties/ts/odyssey-react-mui.d.ts +18 -1
  50. package/dist/src/properties/ts/odyssey-react-mui.d.ts.map +1 -1
  51. package/dist/src/theme/components.d.ts.map +1 -1
  52. package/dist/theme/components.js +37 -18
  53. package/dist/theme/components.js.map +1 -1
  54. package/dist/tsconfig.production.tsbuildinfo +1 -1
  55. package/package.json +3 -3
  56. package/src/DataTable/DataTable.tsx +538 -0
  57. package/src/DataTable/DataTableRowActions.tsx +124 -0
  58. package/src/DataTable/DataTableSettings.tsx +109 -0
  59. package/src/DataTable/constants.ts +13 -0
  60. package/src/DataTable/index.tsx +22 -0
  61. package/src/DataTable/reorderDataRowsLocally.tsx +48 -0
  62. package/src/DataTable/useRowReordering.tsx +233 -0
  63. package/src/index.ts +1 -0
  64. package/src/labs/DataFilters.tsx +60 -17
  65. package/src/labs/DataTable.tsx +24 -11
  66. package/src/labs/index.ts +0 -1
  67. package/src/properties/odyssey-react-mui.properties +19 -2
  68. package/src/properties/ts/odyssey-react-mui.ts +1 -1
  69. package/src/theme/components.tsx +43 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okta/odyssey-react-mui",
3
- "version": "1.14.3",
3
+ "version": "1.14.4",
4
4
  "description": "React MUI components for Odyssey, Okta's design system",
5
5
  "author": "Okta, Inc.",
6
6
  "license": "Apache-2.0",
@@ -51,7 +51,7 @@
51
51
  "@mui/system": "^5.15.9",
52
52
  "@mui/utils": "^5.15.9",
53
53
  "@mui/x-date-pickers": "^5.0.15",
54
- "@okta/odyssey-design-tokens": "^1.14.3",
54
+ "@okta/odyssey-design-tokens": "^1.14.4",
55
55
  "date-fns": "^2.30.0",
56
56
  "i18next": "^23.8.2",
57
57
  "material-react-table": "^2.11.3",
@@ -63,5 +63,5 @@
63
63
  "react": ">=17 <19",
64
64
  "react-dom": ">=17 <19"
65
65
  },
66
- "gitHead": "8ffc832fce91c68f4b6396e06051859a8c2dd0a1"
66
+ "gitHead": "12404ee89fca66a0d95fc5af2c0252727558d78d"
67
67
  }
@@ -0,0 +1,538 @@
1
+ /*!
2
+ * Copyright (c) 2023-present, Okta, Inc. and/or its affiliates. All rights reserved.
3
+ * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
4
+ *
5
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
6
+ * Unless required by applicable law or agreed to in writing, software
7
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
+ *
10
+ * See the License for the specific language governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
14
+ import {
15
+ MRT_Cell,
16
+ MRT_DensityState,
17
+ MRT_Row,
18
+ MRT_RowData,
19
+ MRT_SortingState,
20
+ MRT_TableOptions,
21
+ MRT_Virtualizer,
22
+ MRT_VisibilityState,
23
+ MaterialReactTable,
24
+ useMaterialReactTable,
25
+ } from "material-react-table";
26
+ import {
27
+ ArrowDownIcon,
28
+ ArrowUnsortedIcon,
29
+ DragIndicatorIcon,
30
+ } from "../icons.generated";
31
+ import { densityValues } from "./constants";
32
+ import {
33
+ DataTablePagination,
34
+ paginationTypeValues,
35
+ } from "../labs/DataTablePagination";
36
+ import { DataFilter, DataFilters } from "../labs/DataFilters";
37
+ import {
38
+ DataTableRowActions,
39
+ DataTableRowActionsProps,
40
+ } from "./DataTableRowActions";
41
+ import { useRowReordering } from "./useRowReordering";
42
+ import { DataTableSettings } from "./DataTableSettings";
43
+ import { Box } from "../Box";
44
+ import { DataTableRowSelectionState } from ".";
45
+
46
+ export type DataTableProps = {
47
+ /**
48
+ * The columns that make up the table
49
+ */
50
+ columns: MRT_TableOptions<MRT_RowData>["columns"];
51
+ /**
52
+ * The total number of rows in the table. Optional, because it's sometimes impossible
53
+ * to calculate. Used in table pagination to know when to disable the "next"/"more" button.
54
+ */
55
+ totalRows?: number;
56
+ /**
57
+ * The function to get the ID of a row
58
+ */
59
+ getRowId?: MRT_TableOptions<MRT_RowData>["getRowId"];
60
+ /**
61
+ * The initial density of the table. This is available even if the table density
62
+ * isn't changeable.
63
+ */
64
+ initialDensity?: (typeof densityValues)[number];
65
+ /**
66
+ * If true, the end user will be able to change the table density.
67
+ */
68
+ hasChangeableDensity?: boolean;
69
+ /**
70
+ * If true, the end user can resize individual columns.
71
+ */
72
+ hasColumnResizing?: boolean;
73
+ /**
74
+ * If true, the end user will be able to show/hide columns.
75
+ */
76
+ hasColumnVisibility?: boolean;
77
+ /**
78
+ * If true, the end user will be able to filter columns.
79
+ */
80
+ hasFilters?: boolean;
81
+ /**
82
+ * If true, the table will include pagination controls.
83
+ */
84
+ hasPagination?: boolean;
85
+ /**
86
+ * If true, the table will include checkboxes on each row, enabling
87
+ * the user to select some or all rows.
88
+ */
89
+ hasRowSelection?: boolean;
90
+ /**
91
+ * If true, the global table search controls will be shown.
92
+ */
93
+ hasSearch?: boolean;
94
+ /**
95
+ * If true, the end user can sort columns (ascending, descending, or neither)
96
+ */
97
+ hasSorting?: boolean;
98
+ /**
99
+ * If true, the end user can reorder rows via a drag-and-drop interface
100
+ */
101
+ hasRowReordering?: boolean;
102
+ /**
103
+ * If true, the search field will include a Search button, rather than
104
+ * firing on input change.
105
+ */
106
+ hasSearchSubmitButton?: boolean;
107
+ /**
108
+ * The debounce time, in milliseconds, for the search input firing
109
+ * `onChangeSearch` when changed. If `hasSearchSubmitButton` is true,
110
+ * this doesn't do anything.
111
+ */
112
+ searchDelayTime?: number;
113
+ /**
114
+ * Callback that fires when a row (or rows) is selected or unselected.
115
+ */
116
+ onChangeRowSelection?: (rowSelection: DataTableRowSelectionState) => void;
117
+ /**
118
+ * Callback that fires whenever the table needs to fetch new data, due to changes in
119
+ * page, results per page, search input, filters, or sorting
120
+ */
121
+ getData: ({
122
+ page,
123
+ resultsPerPage,
124
+ search,
125
+ filters,
126
+ sort,
127
+ }: {
128
+ page?: number;
129
+ resultsPerPage?: number;
130
+ search?: string;
131
+ filters?: DataFilter[];
132
+ sort?: MRT_SortingState;
133
+ }) =>
134
+ | MRT_TableOptions<MRT_RowData>["data"]
135
+ | Promise<MRT_TableOptions<MRT_RowData>["data"]>;
136
+ /**
137
+ * Callback that fires when the user reorders rows within the table. Can be used
138
+ * to propogate order change to the backend.
139
+ */
140
+ onReorderRows?: ({
141
+ rowId,
142
+ newRowIndex,
143
+ }: {
144
+ rowId: string;
145
+ newRowIndex: number;
146
+ }) => void;
147
+ /**
148
+ * The current page number.
149
+ */
150
+ currentPage?: number;
151
+ /**
152
+ * The number of results per page.
153
+ */
154
+ resultsPerPage?: number;
155
+ /**
156
+ * The type of pagination controls shown. Defaults to next/prev buttons, but can be
157
+ * set to a simple "Load more" button by setting to "loadMore".
158
+ */
159
+ paginationType?: (typeof paginationTypeValues)[number];
160
+ /**
161
+ * Action buttons to display in each row
162
+ */
163
+ rowActionButtons?: DataTableRowActionsProps["rowActionButtons"];
164
+ /**
165
+ * Menu items to include in the optional actions menu on each row.
166
+ */
167
+ rowActionMenuItems?: DataTableRowActionsProps["rowActionMenuItems"];
168
+ };
169
+
170
+ const displayColumnDefOptions = {
171
+ "mrt-row-actions": {
172
+ header: "",
173
+ grow: true,
174
+ muiTableBodyCellProps: {
175
+ align: "right",
176
+ sx: {
177
+ overflow: "visible",
178
+ width: "unset",
179
+ },
180
+ className: "ods-actions-cell",
181
+ },
182
+ muiTableHeadCellProps: {
183
+ align: "right",
184
+ sx: {
185
+ width: "unset",
186
+ },
187
+ className: "ods-actions-cell",
188
+ },
189
+ },
190
+ "mrt-row-drag": {
191
+ header: "",
192
+ muiTableBodyCellProps: {
193
+ sx: {
194
+ minWidth: 0,
195
+ width: "auto",
196
+ },
197
+ className: "ods-drag-handle",
198
+ },
199
+ muiTableHeadCellProps: {
200
+ sx: {
201
+ minWidth: 0,
202
+ width: "auto",
203
+ },
204
+ children: (
205
+ // Add a spacer to simulate the width of the drag handle in the column.
206
+ // Without this, the head cells are offset from their body cell counterparts
207
+ <Box sx={{ marginInline: "-0.1rem" }}>
208
+ <DragIndicatorIcon sx={{ marginInline: 1, opacity: 0 }} />
209
+ </Box>
210
+ ),
211
+ },
212
+ },
213
+ "mrt-row-select": {
214
+ muiTableHeadCellProps: {
215
+ padding: "checkbox",
216
+ },
217
+ muiTableBodyCellProps: {
218
+ padding: "checkbox",
219
+ },
220
+ },
221
+ };
222
+
223
+ const DataTable = ({
224
+ columns,
225
+ getRowId: getRowIdProp,
226
+ currentPage = 1,
227
+ initialDensity = densityValues[0],
228
+ resultsPerPage = 20,
229
+ getData,
230
+ onReorderRows,
231
+ totalRows,
232
+ hasSearchSubmitButton,
233
+ searchDelayTime,
234
+ paginationType = "paged",
235
+ onChangeRowSelection,
236
+ rowActionButtons,
237
+ rowActionMenuItems,
238
+ hasChangeableDensity,
239
+ hasColumnResizing,
240
+ hasColumnVisibility,
241
+ hasFilters,
242
+ hasPagination,
243
+ hasRowReordering,
244
+ hasRowSelection,
245
+ hasSearch,
246
+ hasSorting,
247
+ }: DataTableProps) => {
248
+ const [data, setData] = useState<MRT_RowData[]>([]);
249
+ const [pagination, setPagination] = useState({
250
+ pageIndex: currentPage,
251
+ pageSize: resultsPerPage,
252
+ });
253
+ const [draggingRow, setDraggingRow] = useState<MRT_Row<MRT_RowData> | null>();
254
+
255
+ // Table states
256
+ const [columnSorting, setColumnSorting] = useState<MRT_SortingState>([]);
257
+ const [columnVisibility, setColumnVisibility] =
258
+ useState<MRT_VisibilityState>();
259
+ const [rowDensity, setRowDensity] =
260
+ useState<MRT_DensityState>(initialDensity);
261
+ const [search, setSearch] = useState<string>("");
262
+ const [filters, setFilters] = useState<DataFilter[]>();
263
+
264
+ const {
265
+ dragHandleStyles,
266
+ dragHandleText,
267
+ draggableTableBodyRowClassName,
268
+ handleDragHandleKeyDown,
269
+ handleDragHandleOnDragCapture,
270
+ handleDragHandleOnDragEnd,
271
+ resetDraggingAndHoveredRow,
272
+ updateRowOrder,
273
+ } = useRowReordering({
274
+ totalRows,
275
+ onReorderRows,
276
+ data,
277
+ setData,
278
+ draggingRow,
279
+ setDraggingRow,
280
+ resultsPerPage: pagination.pageSize,
281
+ page: pagination.pageIndex,
282
+ });
283
+
284
+ const getRowId = getRowIdProp ? getRowIdProp : (row: MRT_RowData) => row.id;
285
+
286
+ const rowDensityCellClassName = useMemo(() => {
287
+ return rowDensity === "spacious"
288
+ ? "MuiTableCell-spacious"
289
+ : rowDensity === "compact"
290
+ ? "MuiTableCell-compact"
291
+ : "MuiTableCell-default";
292
+ }, [rowDensity]);
293
+
294
+ const renderRowActions = useCallback(
295
+ ({ row }: { row: MRT_Row<MRT_RowData> }) => {
296
+ const currentIndex =
297
+ row.index + (pagination.pageIndex - 1) * pagination.pageSize;
298
+ return (
299
+ <DataTableRowActions
300
+ row={row}
301
+ rowIndex={currentIndex}
302
+ rowActionButtons={rowActionButtons}
303
+ rowActionMenuItems={rowActionMenuItems}
304
+ totalRows={totalRows}
305
+ updateRowOrder={
306
+ hasRowReordering && onReorderRows ? updateRowOrder : undefined
307
+ }
308
+ />
309
+ );
310
+ },
311
+ [
312
+ pagination,
313
+ rowActionButtons,
314
+ rowActionMenuItems,
315
+ hasRowReordering,
316
+ onReorderRows,
317
+ totalRows,
318
+ updateRowOrder,
319
+ ],
320
+ );
321
+
322
+ const dataTableFilters = useMemo(
323
+ () =>
324
+ columns
325
+ .filter((column) => column.enableColumnFilter !== false)
326
+ .map((column) => {
327
+ return {
328
+ id: column.accessorKey as string,
329
+ label: column.header,
330
+ variant: column.filterVariant ?? "text",
331
+ options: column.filterSelectOptions,
332
+ } as DataFilter;
333
+ }),
334
+ [columns],
335
+ );
336
+
337
+ const defaultCell = useCallback(
338
+ ({ cell }: { cell: MRT_Cell<MRT_RowData> }) => {
339
+ const value = cell.getValue<string>();
340
+ return (
341
+ <Box
342
+ sx={{
343
+ whiteSpace: "nowrap",
344
+ textOverflow: "ellipsis",
345
+ overflow: "hidden",
346
+ }}
347
+ >
348
+ {value}
349
+ </Box>
350
+ );
351
+ },
352
+ [],
353
+ );
354
+
355
+ const dataTable = useMaterialReactTable({
356
+ columns: columns,
357
+ data: data,
358
+ getRowId: getRowId,
359
+ state: {
360
+ density: rowDensity,
361
+ sorting: columnSorting,
362
+ globalFilter: search,
363
+ columnVisibility,
364
+ },
365
+ icons: {
366
+ ArrowDownwardIcon: ArrowDownIcon,
367
+ DragHandleIcon: DragIndicatorIcon,
368
+ SyncAltIcon: ArrowUnsortedIcon,
369
+ },
370
+
371
+ // Base table settings
372
+ enableColumnActions: false,
373
+ enableColumnResizing: hasColumnResizing,
374
+ enableDensityToggle: false,
375
+ enableFilters: false,
376
+ enableFullScreenToggle: false,
377
+ enableGlobalFilter: false,
378
+ enableHiding: false,
379
+ enablePagination: false,
380
+ layoutMode: "grid-no-grow",
381
+ manualFiltering: true,
382
+ manualSorting: true,
383
+ muiTablePaperProps: {
384
+ elevation: 0,
385
+ sx: {
386
+ overflow: "visible",
387
+ },
388
+ },
389
+ selectAllMode: "all",
390
+ displayColumnDefOptions:
391
+ displayColumnDefOptions as MRT_TableOptions<MRT_RowData>["displayColumnDefOptions"],
392
+ muiTableBodyCellProps: () => ({
393
+ className: rowDensityCellClassName,
394
+ }),
395
+ defaultColumn: {
396
+ Cell: defaultCell,
397
+ },
398
+
399
+ // Reordering
400
+ enableRowOrdering: hasRowReordering && Boolean(onReorderRows),
401
+ enableRowDragging: hasRowReordering && Boolean(onReorderRows),
402
+ muiTableBodyRowProps: ({ table, row }) => ({
403
+ className: draggableTableBodyRowClassName({
404
+ currentRowId: row.id,
405
+ draggingRowId: draggingRow?.id,
406
+ hoveredRowId: table.getState().hoveredRow?.id,
407
+ }),
408
+ }),
409
+ muiRowDragHandleProps: ({ table, row }) => ({
410
+ onKeyDown: (event) => handleDragHandleKeyDown({ table, row, event }),
411
+ onBlur: () => resetDraggingAndHoveredRow(table),
412
+ onDragEnd: () => handleDragHandleOnDragEnd(table),
413
+ onDragCapture: () => handleDragHandleOnDragCapture(table),
414
+ sx: dragHandleStyles,
415
+ ...dragHandleText,
416
+ }),
417
+
418
+ // Row actions
419
+ enableRowActions:
420
+ (hasRowReordering === true && onReorderRows) ||
421
+ rowActionButtons ||
422
+ rowActionMenuItems
423
+ ? true
424
+ : false,
425
+ positionActionsColumn:
426
+ "last" as MRT_TableOptions<MRT_RowData>["positionActionsColumn"],
427
+ renderRowActions: ({ row }) => renderRowActions({ row }),
428
+
429
+ // Row selection
430
+ enableRowSelection: hasRowSelection,
431
+
432
+ // Sorting
433
+ enableSorting: hasSorting,
434
+ onSortingChange: setColumnSorting,
435
+ muiTableHeadCellProps: ({ column: currentColumn }) => ({
436
+ className: columnSorting.find(
437
+ (sortedColumn) => sortedColumn.id === currentColumn.id,
438
+ )
439
+ ? "isSorted"
440
+ : "isUnsorted",
441
+ }),
442
+
443
+ // Virtualization
444
+ enableRowVirtualization:
445
+ paginationType === "loadMore" || pagination.pageSize > 50,
446
+ rowVirtualizerInstanceRef:
447
+ useRef<MRT_Virtualizer<HTMLDivElement, HTMLTableRowElement>>(null),
448
+ rowVirtualizerOptions: {
449
+ overscan: 4,
450
+ },
451
+
452
+ // Filters
453
+ renderTopToolbar: () => (
454
+ <Box sx={{ marginBottom: 5 }}>
455
+ <DataFilters
456
+ onChangeSearch={hasSearch ? setSearch : undefined}
457
+ onChangeFilters={hasFilters ? setFilters : undefined}
458
+ hasSearchSubmitButton={hasSearchSubmitButton}
459
+ searchDelayTime={searchDelayTime}
460
+ filters={hasFilters ? dataTableFilters : undefined}
461
+ additionalActions={
462
+ <DataTableSettings
463
+ hasChangeableDensity={hasChangeableDensity}
464
+ rowDensity={rowDensity}
465
+ setRowDensity={setRowDensity}
466
+ hasColumnVisibility={hasColumnVisibility}
467
+ columns={columns}
468
+ columnVisibility={columnVisibility}
469
+ setColumnVisibility={setColumnVisibility}
470
+ />
471
+ }
472
+ />
473
+ </Box>
474
+ ),
475
+
476
+ // Pagination
477
+ renderBottomToolbar: hasPagination
478
+ ? () => (
479
+ <DataTablePagination
480
+ paginationType={paginationType}
481
+ currentNumberOfResults={data.length}
482
+ currentPage={pagination.pageIndex}
483
+ isPreviousButtonDisabled={pagination.pageIndex <= 1}
484
+ isNextButtonDisabled={false} // TODO: Add logic for disabling next/load more button
485
+ onClickPrevious={() =>
486
+ setPagination({
487
+ pageIndex: pagination.pageIndex - 1,
488
+ pageSize: pagination.pageSize,
489
+ })
490
+ }
491
+ onClickNext={() => {
492
+ if (paginationType === "loadMore") {
493
+ setPagination({
494
+ pageSize: pagination.pageSize,
495
+ pageIndex: pagination.pageSize + resultsPerPage,
496
+ });
497
+ } else {
498
+ setPagination({
499
+ pageSize: pagination.pageSize,
500
+ pageIndex: pagination.pageIndex + 1,
501
+ });
502
+ }
503
+ }}
504
+ />
505
+ )
506
+ : undefined,
507
+ });
508
+
509
+ // Effects
510
+ useEffect(() => {
511
+ onChangeRowSelection?.(dataTable.getState().rowSelection);
512
+ }, [dataTable.getState().rowSelection, dataTable, onChangeRowSelection]);
513
+
514
+ useEffect(() => {
515
+ (async () => {
516
+ try {
517
+ const incomingData = await getData?.({
518
+ page: pagination.pageIndex,
519
+ resultsPerPage: pagination.pageSize,
520
+ search,
521
+ filters,
522
+ sort: columnSorting,
523
+ });
524
+ setData(incomingData);
525
+ } catch (error) {
526
+ } finally {
527
+ }
528
+ })();
529
+ }, [pagination, columnSorting, search, filters, getData]);
530
+
531
+ // Render the table
532
+ return <MaterialReactTable table={dataTable} />;
533
+ };
534
+
535
+ const MemoizedDataTable = memo(DataTable);
536
+ MemoizedDataTable.displayName = "DataTable";
537
+
538
+ export { MemoizedDataTable as DataTable };
@@ -0,0 +1,124 @@
1
+ /*!
2
+ * Copyright (c) 2023-present, Okta, Inc. and/or its affiliates. All rights reserved.
3
+ * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
4
+ *
5
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
6
+ * Unless required by applicable law or agreed to in writing, software
7
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
+ *
10
+ * See the License for the specific language governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { MRT_Row, MRT_RowData } from "material-react-table";
14
+ import { Fragment, ReactElement, memo } from "react";
15
+ import { Button } from "../Button";
16
+ import { MenuItem } from "../MenuItem";
17
+ import { Box as MuiBox } from "@mui/material";
18
+ import { MenuButton, MenuButtonProps } from "../MenuButton";
19
+ import {
20
+ ArrowBottomIcon,
21
+ ArrowDownIcon,
22
+ ArrowTopIcon,
23
+ ArrowUpIcon,
24
+ MoreIcon,
25
+ } from "../icons.generated";
26
+ import { DataTableProps } from "./DataTable";
27
+ import { Trans, useTranslation } from "react-i18next";
28
+
29
+ export type DataTableRowActionsProps = {
30
+ row: MRT_Row<MRT_RowData>;
31
+ rowIndex: number;
32
+ rowActionButtons?: (
33
+ row: MRT_RowData,
34
+ ) => ReactElement<typeof Button | typeof Fragment>;
35
+ rowActionMenuItems?: (row: MRT_RowData) => MenuButtonProps["children"];
36
+ totalRows?: DataTableProps["totalRows"];
37
+ updateRowOrder?: ({
38
+ rowId,
39
+ newRowIndex,
40
+ }: {
41
+ rowId: string;
42
+ newRowIndex: number;
43
+ }) => void;
44
+ };
45
+
46
+ const DataTableRowActions = ({
47
+ row,
48
+ rowIndex,
49
+ rowActionButtons,
50
+ rowActionMenuItems,
51
+ totalRows,
52
+ updateRowOrder,
53
+ }: DataTableRowActionsProps) => {
54
+ const { t } = useTranslation();
55
+ return (
56
+ <MuiBox display="flex">
57
+ {rowActionButtons?.(row)}
58
+ {(rowActionMenuItems || updateRowOrder) && (
59
+ <MenuButton
60
+ endIcon={<MoreIcon />}
61
+ size="small"
62
+ buttonVariant="floating"
63
+ ariaLabel={t("table.moreactions.arialabel")}
64
+ menuAlignment="right"
65
+ >
66
+ {rowActionMenuItems && <>{rowActionMenuItems(row)}</>}
67
+ {rowActionMenuItems && updateRowOrder && <hr />}
68
+ {updateRowOrder && (
69
+ <>
70
+ <MenuItem
71
+ isDisabled={rowIndex <= 0}
72
+ onClick={() =>
73
+ updateRowOrder({ rowId: row.id, newRowIndex: 0 })
74
+ }
75
+ >
76
+ <ArrowTopIcon /> <Trans i18nKey="table.reorder.tofront" />
77
+ </MenuItem>
78
+ <MenuItem
79
+ isDisabled={rowIndex <= 0}
80
+ onClick={() =>
81
+ updateRowOrder({
82
+ rowId: row.id,
83
+ newRowIndex: rowIndex <= 0 ? 0 : rowIndex - 1,
84
+ })
85
+ }
86
+ >
87
+ <ArrowUpIcon /> <Trans i18nKey="table.reorder.forward" />
88
+ </MenuItem>
89
+ <MenuItem
90
+ isDisabled={totalRows ? rowIndex >= totalRows - 1 : false}
91
+ onClick={() =>
92
+ updateRowOrder({
93
+ rowId: row.id,
94
+ newRowIndex: rowIndex + 1,
95
+ })
96
+ }
97
+ >
98
+ <ArrowDownIcon /> <Trans i18nKey="table.reorder.backward" />
99
+ </MenuItem>
100
+ <>
101
+ {totalRows && (
102
+ <MenuItem
103
+ isDisabled={rowIndex >= totalRows - 1}
104
+ onClick={() =>
105
+ updateRowOrder({
106
+ rowId: row.id,
107
+ newRowIndex: totalRows,
108
+ })
109
+ }
110
+ >
111
+ <ArrowBottomIcon /> <Trans i18nKey="table.reorder.toback" />
112
+ </MenuItem>
113
+ )}
114
+ </>
115
+ </>
116
+ )}
117
+ </MenuButton>
118
+ )}
119
+ </MuiBox>
120
+ );
121
+ };
122
+
123
+ const MemoizedDataTableRowActions = memo(DataTableRowActions);
124
+ export { MemoizedDataTableRowActions as DataTableRowActions };