mui-universal-table 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.
@@ -0,0 +1,1134 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import Paper$1 from '@mui/material/Paper';
4
+ import { Collapse, Box, Typography, LinearProgress, IconButton, Tooltip, Button, Paper, InputBase, Stack, Divider, Toolbar, TableHead, TableRow, TableCell, Checkbox, TableSortLabel, Badge, TableBody, Skeleton, TableContainer, Table, TablePagination } from '@mui/material';
5
+ import { alpha } from '@mui/material/styles';
6
+ import { Task, Clear, Search, RemoveCircle, AddCircle } from '@mui/icons-material';
7
+ import RefreshIcon from '@mui/icons-material/Refresh';
8
+
9
+ function _arrayLikeToArray(r, a) {
10
+ (null == a || a > r.length) && (a = r.length);
11
+ for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
12
+ return n;
13
+ }
14
+ function _arrayWithHoles(r) {
15
+ if (Array.isArray(r)) return r;
16
+ }
17
+ function _arrayWithoutHoles(r) {
18
+ if (Array.isArray(r)) return _arrayLikeToArray(r);
19
+ }
20
+ function _defineProperty(e, r, t) {
21
+ return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
22
+ value: t,
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true
26
+ }) : e[r] = t, e;
27
+ }
28
+ function _extends() {
29
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
30
+ for (var e = 1; e < arguments.length; e++) {
31
+ var t = arguments[e];
32
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
33
+ }
34
+ return n;
35
+ }, _extends.apply(null, arguments);
36
+ }
37
+ function _iterableToArray(r) {
38
+ if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
39
+ }
40
+ function _iterableToArrayLimit(r, l) {
41
+ var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
42
+ if (null != t) {
43
+ var e,
44
+ n,
45
+ i,
46
+ u,
47
+ a = [],
48
+ f = true,
49
+ o = false;
50
+ try {
51
+ if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
52
+ } catch (r) {
53
+ o = true, n = r;
54
+ } finally {
55
+ try {
56
+ if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
57
+ } finally {
58
+ if (o) throw n;
59
+ }
60
+ }
61
+ return a;
62
+ }
63
+ }
64
+ function _nonIterableRest() {
65
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
66
+ }
67
+ function _nonIterableSpread() {
68
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
69
+ }
70
+ function ownKeys(e, r) {
71
+ var t = Object.keys(e);
72
+ if (Object.getOwnPropertySymbols) {
73
+ var o = Object.getOwnPropertySymbols(e);
74
+ r && (o = o.filter(function (r) {
75
+ return Object.getOwnPropertyDescriptor(e, r).enumerable;
76
+ })), t.push.apply(t, o);
77
+ }
78
+ return t;
79
+ }
80
+ function _objectSpread2(e) {
81
+ for (var r = 1; r < arguments.length; r++) {
82
+ var t = null != arguments[r] ? arguments[r] : {};
83
+ r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
84
+ _defineProperty(e, r, t[r]);
85
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
86
+ Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
87
+ });
88
+ }
89
+ return e;
90
+ }
91
+ function _slicedToArray(r, e) {
92
+ return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
93
+ }
94
+ function _toConsumableArray(r) {
95
+ return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
96
+ }
97
+ function _toPrimitive(t, r) {
98
+ if ("object" != typeof t || !t) return t;
99
+ var e = t[Symbol.toPrimitive];
100
+ if (void 0 !== e) {
101
+ var i = e.call(t, r);
102
+ if ("object" != typeof i) return i;
103
+ throw new TypeError("@@toPrimitive must return a primitive value.");
104
+ }
105
+ return ("string" === r ? String : Number)(t);
106
+ }
107
+ function _toPropertyKey(t) {
108
+ var i = _toPrimitive(t, "string");
109
+ return "symbol" == typeof i ? i : i + "";
110
+ }
111
+ function _unsupportedIterableToArray(r, a) {
112
+ if (r) {
113
+ if ("string" == typeof r) return _arrayLikeToArray(r, a);
114
+ var t = {}.toString.call(r).slice(8, -1);
115
+ return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
116
+ }
117
+ }
118
+
119
+ var LazyLoadingIndicator = function LazyLoadingIndicator(_ref) {
120
+ var show = _ref.show,
121
+ currentPage = _ref.currentPage,
122
+ totalPages = _ref.totalPages;
123
+ return /*#__PURE__*/React.createElement(Collapse, {
124
+ "in": show,
125
+ timeout: "auto",
126
+ unmountOnExit: true
127
+ }, /*#__PURE__*/React.createElement(Box, {
128
+ sx: {
129
+ width: "100%",
130
+ p: 2
131
+ }
132
+ }, /*#__PURE__*/React.createElement(Typography, {
133
+ variant: "body2",
134
+ color: "text.secondary",
135
+ sx: {
136
+ mb: 1
137
+ }
138
+ }, "Loading page ", currentPage, " of ", totalPages, "..."), /*#__PURE__*/React.createElement(LinearProgress, {
139
+ variant: "determinate",
140
+ value: currentPage / totalPages * 100
141
+ })));
142
+ };
143
+ LazyLoadingIndicator.propTypes = {
144
+ show: PropTypes.bool.isRequired,
145
+ currentPage: PropTypes.number,
146
+ totalPages: PropTypes.number
147
+ };
148
+
149
+ /**
150
+ * Standard visually-hidden style: content is accessible to screen readers
151
+ * but invisible on screen. Defined locally to avoid importing from
152
+ * @mui/utils which is not a declared peer dependency.
153
+ */
154
+ var visuallyHidden = {
155
+ border: 0,
156
+ clip: "rect(0 0 0 0)",
157
+ height: "1px",
158
+ margin: -1,
159
+ overflow: "hidden",
160
+ padding: 0,
161
+ position: "absolute",
162
+ whiteSpace: "nowrap",
163
+ width: "1px"
164
+ };
165
+ function getSelectableRowId(row, index, selectID) {
166
+ return selectID ? row[selectID] : index;
167
+ }
168
+ function getSearchableColumnIds(headers) {
169
+ return headers.filter(function (column) {
170
+ return column.searchable;
171
+ }).map(function (column) {
172
+ return column.id;
173
+ });
174
+ }
175
+ function filterRows(data, searchTerm, filterOptions) {
176
+ if (!searchTerm) {
177
+ return data;
178
+ }
179
+ var term = searchTerm.toLocaleLowerCase();
180
+ return data.filter(function (row) {
181
+ return filterOptions.some(function (filterOption) {
182
+ return String(row[filterOption]).toLocaleLowerCase().includes(term);
183
+ });
184
+ });
185
+ }
186
+ function getPageOptions(rowCount) {
187
+ if (rowCount <= 5) return [5];
188
+ if (rowCount <= 10) return [5, rowCount];
189
+ if (rowCount <= 25) return [5, 10, rowCount];
190
+ if (rowCount < 50) return [5, 10, 25, rowCount];
191
+ if (rowCount < 100) return [5, 10, 25, 50, rowCount];
192
+ return [5, 10, 25, 50, 100, rowCount];
193
+ }
194
+ function splitHeaders(headers) {
195
+ return headers.reduce(function (groups, header) {
196
+ if (header.subRow) {
197
+ groups.subTables.push(header);
198
+ } else {
199
+ groups.columns.push(header);
200
+ }
201
+ return groups;
202
+ }, {
203
+ subTables: [],
204
+ columns: []
205
+ });
206
+ }
207
+ function descendingComparator(a, b, orderBy) {
208
+ if (b[orderBy] < a[orderBy]) {
209
+ return -1;
210
+ }
211
+ if (b[orderBy] > a[orderBy]) {
212
+ return 1;
213
+ }
214
+ return 0;
215
+ }
216
+ function getComparator(order, orderBy) {
217
+ return order === "desc" ? function (a, b) {
218
+ return descendingComparator(a, b, orderBy);
219
+ } : function (a, b) {
220
+ return -descendingComparator(a, b, orderBy);
221
+ };
222
+ }
223
+
224
+ /**
225
+ * Format a cell value for display. Handles dates safely:
226
+ * returns the raw value for non-date headers, and a formatted
227
+ * date string for date headers (guards against invalid dates).
228
+ *
229
+ * Uses `new Date(raw)` directly rather than `Date.parse(raw)` to
230
+ * handle epoch-millisecond numbers, Date objects, and string
231
+ * formats that Date.parse may reject.
232
+ */
233
+ function formatCellValue(header, rowValues) {
234
+ var raw = rowValues[header.id];
235
+ if (!header.date) {
236
+ return raw;
237
+ }
238
+
239
+ // null and undefined produce a valid epoch-0 Date, not Invalid Date
240
+ if (raw === null || raw === undefined) {
241
+ return raw;
242
+ }
243
+ var d = new Date(raw);
244
+ if (Number.isNaN(d.getTime())) {
245
+ return raw;
246
+ }
247
+ return d.toDateString() + " " + d.toLocaleTimeString("en-US", {
248
+ hour: "numeric",
249
+ minute: "2-digit",
250
+ hour12: true
251
+ });
252
+ }
253
+ function stableSort(array, comparator, headers) {
254
+ var dateColumns = new Set(headers.filter(function (object) {
255
+ return object.date;
256
+ }).map(function (value) {
257
+ return value.id;
258
+ }));
259
+
260
+ // Build stable entries — compare pre-computed sort keys so we never
261
+ // mutate the original data or its shallow copies.
262
+ // Each entry is [originalRow, sortKey, index] so that the comparator
263
+ // works on numeric-converted date values while the original rows are
264
+ // returned unchanged (preserving the data seen by header.component).
265
+ var stabilizedThis = array.map(function (el, index) {
266
+ var sortKey = _objectSpread2({}, el);
267
+ for (var property in sortKey) {
268
+ if (dateColumns.has(property)) {
269
+ var parsed = Number(new Date(sortKey[property]));
270
+ // Preserve the original value for invalid dates so formatCellValue
271
+ // can display the fallback instead of passing NaN to React children.
272
+ if (!Number.isNaN(parsed)) {
273
+ sortKey[property] = parsed;
274
+ }
275
+ }
276
+ }
277
+ return [el, sortKey, index];
278
+ });
279
+ stabilizedThis.sort(function (a, b) {
280
+ var order = comparator(a[1], b[1]);
281
+ if (order !== 0) return order;
282
+ return a[2] - b[2];
283
+ });
284
+ return stabilizedThis.map(function (el) {
285
+ return el[0];
286
+ });
287
+ }
288
+
289
+ function useSearchableRows(data, headers) {
290
+ var _React$useState = React.useState(""),
291
+ _React$useState2 = _slicedToArray(_React$useState, 2),
292
+ searchTerm = _React$useState2[0],
293
+ setSearchTerm = _React$useState2[1];
294
+ var filterOptions = React.useMemo(function () {
295
+ return getSearchableColumnIds(headers);
296
+ }, [headers]);
297
+ var rows = React.useMemo(function () {
298
+ return filterRows(data, searchTerm, filterOptions);
299
+ }, [data, filterOptions, searchTerm]);
300
+ return {
301
+ rows: rows,
302
+ searchTerm: searchTerm,
303
+ setSearchTerm: setSearchTerm
304
+ };
305
+ }
306
+
307
+ function useSelectableRows(_ref) {
308
+ var rows = _ref.rows,
309
+ selectRows = _ref.selectRows,
310
+ selectID = _ref.selectID;
311
+ var _React$useState = React.useState([]),
312
+ _React$useState2 = _slicedToArray(_React$useState, 2),
313
+ selected = _React$useState2[0],
314
+ setSelected = _React$useState2[1];
315
+ var clearSelection = React.useCallback(function () {
316
+ setSelected([]);
317
+ }, []);
318
+ var handleSelectAllClick = React.useCallback(function (event) {
319
+ if (!event.target.checked) {
320
+ setSelected([]);
321
+ return;
322
+ }
323
+ var newSelected = rows.map(function (row, index) {
324
+ return getSelectableRowId(row, index, selectID);
325
+ });
326
+ setSelected(newSelected);
327
+ }, [rows, selectID]);
328
+ var handleClick = React.useCallback(function (event, id) {
329
+ if (!selectRows) {
330
+ return;
331
+ }
332
+ setSelected(function (previous) {
333
+ return previous.includes(id) ? previous.filter(function (selectedId) {
334
+ return selectedId !== id;
335
+ }) : [].concat(_toConsumableArray(previous), [id]);
336
+ });
337
+ }, [selectRows]);
338
+ return {
339
+ selected: selected,
340
+ clearSelection: clearSelection,
341
+ handleSelectAllClick: handleSelectAllClick,
342
+ handleClick: handleClick
343
+ };
344
+ }
345
+
346
+ function TableSelectionBanner(_ref) {
347
+ var selected = _ref.selected,
348
+ onSelection = _ref.onSelection,
349
+ selectIcon = _ref.selectIcon;
350
+ return /*#__PURE__*/React.createElement(Collapse, {
351
+ "in": selected.length > 0,
352
+ unmountOnExit: true
353
+ }, /*#__PURE__*/React.createElement(Box, {
354
+ sx: {
355
+ p: 2,
356
+ display: "flex",
357
+ justifyContent: "space-between",
358
+ bgcolor: function bgcolor(theme) {
359
+ return alpha(theme.palette.primary.main, theme.palette.action.activatedOpacity);
360
+ },
361
+ borderRadius: 1,
362
+ borderBottomLeftRadius: 0,
363
+ borderBottomRightRadius: 0
364
+ }
365
+ }, /*#__PURE__*/React.createElement(Typography, {
366
+ variant: "h6",
367
+ id: "tableTitle",
368
+ component: "div"
369
+ }, selected.length, " selected"), /*#__PURE__*/React.createElement(IconButton, {
370
+ onClick: function onClick() {
371
+ return onSelection(selected);
372
+ }
373
+ }, selectIcon || /*#__PURE__*/React.createElement(Task, null))));
374
+ }
375
+ TableSelectionBanner.propTypes = {
376
+ selected: PropTypes.array.isRequired,
377
+ onSelection: PropTypes.func,
378
+ selectIcon: PropTypes.element
379
+ };
380
+
381
+ function TableTitle(_ref) {
382
+ var name = _ref.name,
383
+ subTable = _ref.subTable;
384
+ return /*#__PURE__*/React.createElement(Typography, {
385
+ variant: subTable ? "h6" : "h5",
386
+ color: subTable ? "secondary" : "primary",
387
+ sx: {
388
+ p: 2
389
+ }
390
+ }, name);
391
+ }
392
+ TableTitle.propTypes = {
393
+ name: PropTypes.string,
394
+ subTable: PropTypes.bool
395
+ };
396
+
397
+ function ReloadBtn(_ref) {
398
+ var setLoading = _ref.setLoading,
399
+ loading = _ref.loading,
400
+ onReload = _ref.onReload;
401
+ var canReload = typeof onReload === "function" || typeof setLoading === "function";
402
+ if (!canReload) {
403
+ return null;
404
+ }
405
+ var handleClick = function handleClick() {
406
+ if (typeof onReload === "function") {
407
+ onReload();
408
+ } else if (typeof setLoading === "function") {
409
+ setLoading(true);
410
+ }
411
+ };
412
+ return /*#__PURE__*/React.createElement(Tooltip, {
413
+ title: "Reload"
414
+ }, /*#__PURE__*/React.createElement(Button, {
415
+ variant: "contained",
416
+ color: "primary",
417
+ onClick: handleClick,
418
+ disabled: loading
419
+ }, /*#__PURE__*/React.createElement(RefreshIcon, null)));
420
+ }
421
+ ReloadBtn.propTypes = {
422
+ setLoading: PropTypes.func,
423
+ loading: PropTypes.bool,
424
+ /** Preferred callback — fires when the user clicks reload. */
425
+ onReload: PropTypes.func
426
+ };
427
+
428
+ function FancySearch(_ref) {
429
+ var value = _ref.value,
430
+ onSubmit = _ref.onSubmit;
431
+ var _React$useState = React.useState(value),
432
+ _React$useState2 = _slicedToArray(_React$useState, 2),
433
+ search = _React$useState2[0],
434
+ setSearch = _React$useState2[1];
435
+ var _React$useState3 = React.useState(Boolean(search)),
436
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
437
+ hover = _React$useState4[0],
438
+ setHover = _React$useState4[1];
439
+ var expanded = hover || Boolean(search);
440
+ var handleSubmit = function handleSubmit(e) {
441
+ e.preventDefault();
442
+ onSubmit(search);
443
+ };
444
+ var handleEndHover = function handleEndHover() {
445
+ setHover(false);
446
+ };
447
+
448
+ // Sync internal state when the parent clears/changes the search term.
449
+ // A ref tracks whether this sync came from the user typing or from a parent
450
+ // update, so the debounce only fires for genuine user input.
451
+ var isUserType = React.useRef(false);
452
+ React.useEffect(function () {
453
+ if (isUserType.current) {
454
+ // User is typing — debounce as normal
455
+ isUserType.current = false;
456
+ var timer = setTimeout(function () {
457
+ onSubmit(search);
458
+ }, 700);
459
+ return function () {
460
+ return clearTimeout(timer);
461
+ };
462
+ }
463
+ // External value change (parent reset, clear from clearSelection, etc.)
464
+ // — sync state and do NOT fire a stale debounce.
465
+ setSearch(value);
466
+ return undefined;
467
+ }, [search, value, onSubmit]);
468
+ return /*#__PURE__*/React.createElement("form", {
469
+ onSubmit: handleSubmit
470
+ }, /*#__PURE__*/React.createElement(Paper, {
471
+ elevation: 0,
472
+ sx: {
473
+ borderRadius: expanded ? "24px" : "50px",
474
+ display: "flex",
475
+ alignItems: "center",
476
+ transition: "all 0.5s ease-in-out",
477
+ p: expanded ? 1 : 0.5,
478
+ width: "fit-content",
479
+ border: function border(theme) {
480
+ return "1px solid ".concat(theme.palette.divider);
481
+ },
482
+ mb: 1
483
+ },
484
+ onMouseEnter: function onMouseEnter() {
485
+ return setHover(true);
486
+ },
487
+ onMouseLeave: handleEndHover,
488
+ onKeyDown: function onKeyDown(e) {
489
+ return e.key === "Enter" && handleSubmit(e);
490
+ }
491
+ }, /*#__PURE__*/React.createElement(InputBase, {
492
+ placeholder: "Search",
493
+ value: search,
494
+ onChange: function onChange(e) {
495
+ isUserType.current = true;
496
+ setSearch(e.target.value);
497
+ },
498
+ sx: _objectSpread2({
499
+ ml: 1,
500
+ width: expanded ? "100%" : 0,
501
+ transition: "width 0.5s ease-in-out"
502
+ }, expanded ? {} : {
503
+ margin: 0
504
+ }),
505
+ onBlur: handleEndHover
506
+ }), /*#__PURE__*/React.createElement(Collapse, {
507
+ "in": Boolean(search),
508
+ orientation: "horizontal",
509
+ unmountOnExit: true
510
+ }, /*#__PURE__*/React.createElement(Stack, {
511
+ direction: "row",
512
+ alignItems: "center",
513
+ spacing: 0,
514
+ sx: {
515
+ mr: 3
516
+ }
517
+ }, /*#__PURE__*/React.createElement(IconButton, {
518
+ onClick: function onClick() {
519
+ isUserType.current = false;
520
+ setSearch("");
521
+ // Immediately clear instead of waiting for the debounce
522
+ onSubmit("");
523
+ }
524
+ }, /*#__PURE__*/React.createElement(Clear, null)), /*#__PURE__*/React.createElement(Divider, {
525
+ orientation: "vertical",
526
+ flexItem: true
527
+ }))), /*#__PURE__*/React.createElement(IconButton, {
528
+ onClick: handleSubmit,
529
+ type: "submit"
530
+ }, /*#__PURE__*/React.createElement(Search, null))));
531
+ }
532
+ FancySearch.propTypes = {
533
+ value: PropTypes.string,
534
+ onSubmit: PropTypes.func.isRequired
535
+ };
536
+
537
+ function SearchArea(props) {
538
+ var current = props.current,
539
+ setFinalVal = props.setFinalVal,
540
+ searchName = props.searchName,
541
+ persistSearch = props.persistSearch;
542
+ var searchVal = React.useMemo(function () {
543
+ if (current !== undefined && current !== null) return current;
544
+ if (persistSearch && searchName) {
545
+ var _sessionStorage$getIt;
546
+ return (_sessionStorage$getIt = sessionStorage.getItem("searchVal:".concat(searchName))) !== null && _sessionStorage$getIt !== void 0 ? _sessionStorage$getIt : "";
547
+ }
548
+ return "";
549
+ }, [current, persistSearch, searchName]);
550
+ return /*#__PURE__*/React.createElement("div", {
551
+ key: "SearchArea"
552
+ }, /*#__PURE__*/React.createElement(FancySearch, {
553
+ value: searchVal,
554
+ onSubmit: setFinalVal
555
+ }));
556
+ }
557
+ SearchArea.propTypes = {
558
+ current: PropTypes.string,
559
+ setFinalVal: PropTypes.func.isRequired,
560
+ searchName: PropTypes.string,
561
+ /** Persist search term to sessionStorage (requires searchName). Default: false */
562
+ persistSearch: PropTypes.bool
563
+ };
564
+
565
+ function TableToolbarContent(_ref) {
566
+ var setLoading = _ref.setLoading,
567
+ onReload = _ref.onReload,
568
+ reloadBtnLoading = _ref.reloadBtnLoading,
569
+ searchTerm = _ref.searchTerm,
570
+ onSearchChange = _ref.onSearchChange,
571
+ name = _ref.name,
572
+ persistSearch = _ref.persistSearch;
573
+ return /*#__PURE__*/React.createElement(Toolbar, {
574
+ sx: {
575
+ pl: {
576
+ sm: 2
577
+ },
578
+ pr: {
579
+ xs: 1,
580
+ sm: 1
581
+ },
582
+ pt: 2
583
+ }
584
+ }, /*#__PURE__*/React.createElement(Stack, {
585
+ spacing: 2,
586
+ direction: {
587
+ xs: "column",
588
+ md: "row"
589
+ },
590
+ sx: {
591
+ width: "100%",
592
+ alignItems: {
593
+ xs: "flex-start",
594
+ md: "center"
595
+ }
596
+ }
597
+ }, /*#__PURE__*/React.createElement(Box, {
598
+ sx: {
599
+ flex: "1 1 100%"
600
+ },
601
+ id: "tableTitle"
602
+ }, /*#__PURE__*/React.createElement(ReloadBtn, {
603
+ setLoading: setLoading,
604
+ onReload: onReload,
605
+ loading: reloadBtnLoading
606
+ })), /*#__PURE__*/React.createElement(SearchArea, {
607
+ current: searchTerm,
608
+ setFinalVal: onSearchChange,
609
+ searchName: name,
610
+ persistSearch: persistSearch
611
+ })));
612
+ }
613
+ TableToolbarContent.propTypes = {
614
+ setLoading: PropTypes.func,
615
+ onReload: PropTypes.func,
616
+ reloadBtnLoading: PropTypes.bool,
617
+ searchTerm: PropTypes.string,
618
+ onSearchChange: PropTypes.func.isRequired,
619
+ name: PropTypes.string,
620
+ persistSearch: PropTypes.bool
621
+ };
622
+
623
+ function useEnhancedTableState(_ref) {
624
+ var rows = _ref.rows,
625
+ subTable = _ref.subTable,
626
+ resetFlag = _ref.resetFlag;
627
+ var _React$useState = React.useState("asc"),
628
+ _React$useState2 = _slicedToArray(_React$useState, 2),
629
+ order = _React$useState2[0],
630
+ setOrder = _React$useState2[1];
631
+ var _React$useState3 = React.useState(""),
632
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
633
+ orderBy = _React$useState4[0],
634
+ setOrderBy = _React$useState4[1];
635
+ var _React$useState5 = React.useState(function () {
636
+ return {
637
+ page: 0,
638
+ rowsPerPage: subTable ? rows.length : 5,
639
+ resetFlag: resetFlag
640
+ };
641
+ }),
642
+ _React$useState6 = _slicedToArray(_React$useState5, 2),
643
+ pagination = _React$useState6[0],
644
+ setPagination = _React$useState6[1];
645
+ React.useEffect(function () {
646
+ // eslint-disable-next-line react-hooks/set-state-in-effect
647
+ setPagination(function (previous) {
648
+ if (previous.resetFlag === resetFlag) {
649
+ return previous;
650
+ }
651
+ return _objectSpread2(_objectSpread2({}, previous), {}, {
652
+ page: 0,
653
+ resetFlag: resetFlag
654
+ });
655
+ });
656
+ }, [resetFlag]);
657
+ var page = pagination.page;
658
+ var rowsPerPage = subTable ? rows.length : pagination.rowsPerPage;
659
+ var handleRequestSort = React.useCallback(function (event, property) {
660
+ var isAsc = orderBy === property && order === "asc";
661
+ setOrder(isAsc ? "desc" : "asc");
662
+ setOrderBy(property);
663
+ }, [order, orderBy]);
664
+ var handleChangePage = React.useCallback(function (event, newPage) {
665
+ setPagination(function (previous) {
666
+ return _objectSpread2(_objectSpread2({}, previous), {}, {
667
+ page: newPage
668
+ });
669
+ });
670
+ }, []);
671
+ var handleChangeRowsPerPage = React.useCallback(function (event) {
672
+ setPagination(function (previous) {
673
+ return _objectSpread2(_objectSpread2({}, previous), {}, {
674
+ page: 0,
675
+ rowsPerPage: Number.parseInt(event.target.value, 10)
676
+ });
677
+ });
678
+ }, []);
679
+ return {
680
+ order: order,
681
+ orderBy: orderBy,
682
+ page: page,
683
+ rowsPerPage: rowsPerPage,
684
+ handleRequestSort: handleRequestSort,
685
+ handleChangePage: handleChangePage,
686
+ handleChangeRowsPerPage: handleChangeRowsPerPage
687
+ };
688
+ }
689
+
690
+ function EnhancedTableHead(props) {
691
+ var order = props.order,
692
+ orderBy = props.orderBy,
693
+ onRequestSort = props.onRequestSort,
694
+ selectRows = props.selectRows,
695
+ numSelected = props.numSelected,
696
+ rowCount = props.rowCount,
697
+ onSelectAllClick = props.onSelectAllClick;
698
+ var createSortHandler = function createSortHandler(property) {
699
+ return function (event) {
700
+ onRequestSort(event, property);
701
+ };
702
+ };
703
+ return /*#__PURE__*/React.createElement(TableHead, null, /*#__PURE__*/React.createElement(TableRow, null, selectRows && /*#__PURE__*/React.createElement(TableCell, {
704
+ padding: "checkbox"
705
+ }, /*#__PURE__*/React.createElement(Checkbox, {
706
+ color: "primary",
707
+ indeterminate: numSelected > 0 && numSelected < rowCount,
708
+ checked: rowCount > 0 && numSelected === rowCount,
709
+ onChange: onSelectAllClick
710
+ })), props.headings.map(function (headCell) {
711
+ return /*#__PURE__*/React.createElement(TableCell, {
712
+ key: headCell.id,
713
+ align: headCell.numeric ? "right" : "left",
714
+ padding: "normal",
715
+ sortDirection: orderBy === headCell.id ? order : false
716
+ }, /*#__PURE__*/React.createElement(TableSortLabel, {
717
+ active: orderBy === headCell.id,
718
+ direction: orderBy === headCell.id ? order : "asc",
719
+ onClick: createSortHandler(headCell.id)
720
+ }, headCell.label, orderBy === headCell.id ? /*#__PURE__*/React.createElement(Box, {
721
+ component: "span",
722
+ sx: visuallyHidden
723
+ }, order === "desc" ? "sorted descending" : "sorted ascending") : undefined));
724
+ })));
725
+ }
726
+ EnhancedTableHead.propTypes = {
727
+ onRequestSort: PropTypes.func.isRequired,
728
+ order: PropTypes.oneOf(["asc", "desc"]).isRequired,
729
+ orderBy: PropTypes.string.isRequired,
730
+ headings: PropTypes.array.isRequired,
731
+ selectRows: PropTypes.bool,
732
+ numSelected: PropTypes.number,
733
+ rowCount: PropTypes.number,
734
+ onSelectAllClick: PropTypes.func
735
+ };
736
+
737
+ /**
738
+ * Lazily import UniversalTable to statically break the circular dependency:
739
+ * UniversalTable → EnhancedTable → DataRow → SubTableRow → UniversalTable
740
+ * React.lazy resolves the import at render time, so the module graph stays acyclic.
741
+ */
742
+ var UniversalTable$2 = /*#__PURE__*/React.lazy(function () {
743
+ return Promise.resolve().then(function () { return UniversalTable$1; });
744
+ });
745
+
746
+ // ---------------------------------------------------------------------------
747
+ // SubRowToggleCell
748
+ // ---------------------------------------------------------------------------
749
+
750
+ function SubRowToggleCell(_ref) {
751
+ var header = _ref.header,
752
+ isOpen = _ref.isOpen,
753
+ onToggle = _ref.onToggle,
754
+ rowValues = _ref.rowValues,
755
+ hideBadge = _ref.hideBadge;
756
+ return /*#__PURE__*/React.createElement(TableCell, null, /*#__PURE__*/React.createElement(Tooltip, {
757
+ title: isOpen ? "Hide ".concat(header.id) : "Show ".concat(header.id)
758
+ }, /*#__PURE__*/React.createElement(Box, null, /*#__PURE__*/React.createElement(IconButton, {
759
+ onClick: function onClick(event) {
760
+ event.stopPropagation();
761
+ onToggle();
762
+ },
763
+ disabled: rowValues[header.id].length === 0,
764
+ color: header.iconColor || "secondary"
765
+ }, /*#__PURE__*/React.createElement(Badge, {
766
+ badgeContent: rowValues[header.id].length,
767
+ invisible: hideBadge,
768
+ anchorOrigin: {
769
+ vertical: "bottom",
770
+ horizontal: "right"
771
+ },
772
+ sx: {
773
+ "& .MuiBadge-badge": {
774
+ color: function color(theme) {
775
+ return theme.palette.text.primary;
776
+ }
777
+ }
778
+ }
779
+ }, isOpen ? (header === null || header === void 0 ? void 0 : header.closeIcon) || /*#__PURE__*/React.createElement(RemoveCircle, null) : (header === null || header === void 0 ? void 0 : header.openIcon) || /*#__PURE__*/React.createElement(AddCircle, null))))));
780
+ }
781
+ SubRowToggleCell.propTypes = {
782
+ header: PropTypes.object.isRequired,
783
+ isOpen: PropTypes.bool.isRequired,
784
+ onToggle: PropTypes.func.isRequired,
785
+ rowValues: PropTypes.object.isRequired,
786
+ hideBadge: PropTypes.bool
787
+ };
788
+
789
+ // ---------------------------------------------------------------------------
790
+ // SubTableRow
791
+ // ---------------------------------------------------------------------------
792
+
793
+ function SubTableRow(_ref2) {
794
+ var table = _ref2.table,
795
+ isOpen = _ref2.isOpen,
796
+ rowValues = _ref2.rowValues,
797
+ colSpan = _ref2.colSpan;
798
+ return /*#__PURE__*/React.createElement(TableRow, null, /*#__PURE__*/React.createElement(TableCell, {
799
+ colSpan: colSpan,
800
+ style: {
801
+ paddingBottom: 0,
802
+ paddingTop: 0
803
+ }
804
+ }, /*#__PURE__*/React.createElement(Collapse, {
805
+ "in": isOpen,
806
+ timeout: "auto",
807
+ unmountOnExit: true
808
+ }, /*#__PURE__*/React.createElement(React.Suspense, {
809
+ fallback: null
810
+ }, /*#__PURE__*/React.createElement(UniversalTable$2, {
811
+ loading: table.loading,
812
+ setLoading: table.setLoading,
813
+ onReload: table.onReload,
814
+ data: rowValues[table.id],
815
+ headers: table.headers,
816
+ name: table.subTitle,
817
+ subTable: true
818
+ })))));
819
+ }
820
+ SubTableRow.propTypes = {
821
+ table: PropTypes.object.isRequired,
822
+ isOpen: PropTypes.bool.isRequired,
823
+ rowValues: PropTypes.object.isRequired,
824
+ colSpan: PropTypes.number.isRequired
825
+ };
826
+
827
+ function renderDataCells(headers, rowValues) {
828
+ return headers.map(function (header, index) {
829
+ return /*#__PURE__*/React.createElement(TableCell, _extends({
830
+ key: header.id || index
831
+ }, header.cellProps), header.component ? header.component(rowValues) : formatCellValue(header, rowValues));
832
+ });
833
+ }
834
+ var DataRow = /*#__PURE__*/React.memo(function DataRow(props) {
835
+ var rowValues = props.rowValues,
836
+ headers = props.headers,
837
+ selectRows = props.selectRows,
838
+ isSelected = props.isSelected,
839
+ handleClick = props.handleClick;
840
+ var _React$useMemo = React.useMemo(function () {
841
+ return splitHeaders(headers);
842
+ }, [headers]),
843
+ subTables = _React$useMemo.subTables,
844
+ columns = _React$useMemo.columns;
845
+ var hideBadge = props.hideBadge || false;
846
+ var isItemSelected = isSelected(props.rowID);
847
+ var _React$useState = React.useState(Array.from({
848
+ length: subTables.length
849
+ }).fill(false)),
850
+ _React$useState2 = _slicedToArray(_React$useState, 2),
851
+ reveal = _React$useState2[0],
852
+ setReveal = _React$useState2[1];
853
+ var toggleSubRow = React.useCallback(function (index) {
854
+ setReveal(function (previous) {
855
+ var next = _toConsumableArray(previous);
856
+ next[index] = !next[index];
857
+ return next;
858
+ });
859
+ }, []);
860
+ var handleRowKeyDown = React.useCallback(function (event) {
861
+ if (selectRows && (event.key === " " || event.key === "Enter")) {
862
+ event.preventDefault();
863
+ handleClick(event, props.rowID);
864
+ }
865
+ }, [selectRows, handleClick, props.rowID]);
866
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TableRow, {
867
+ tabIndex: selectRows ? 0 : -1,
868
+ hover: selectRows,
869
+ role: selectRows ? "checkbox" : "row",
870
+ selected: isItemSelected,
871
+ "aria-checked": isItemSelected,
872
+ onKeyDown: handleRowKeyDown
873
+ }, selectRows && /*#__PURE__*/React.createElement(TableCell, {
874
+ padding: "checkbox"
875
+ }, /*#__PURE__*/React.createElement(Checkbox, {
876
+ color: "primary",
877
+ checked: isItemSelected,
878
+ onClick: function onClick(event) {
879
+ return handleClick(event, props.rowID);
880
+ }
881
+ })), subTables.map(function (header, index) {
882
+ return /*#__PURE__*/React.createElement(SubRowToggleCell, {
883
+ key: header.id || index,
884
+ header: header,
885
+ isOpen: reveal[index],
886
+ onToggle: function onToggle() {
887
+ return toggleSubRow(index);
888
+ },
889
+ rowValues: rowValues,
890
+ hideBadge: hideBadge
891
+ });
892
+ }), renderDataCells(columns, rowValues)), subTables.map(function (table, index) {
893
+ return /*#__PURE__*/React.createElement(SubTableRow, {
894
+ key: table.id || index,
895
+ table: table,
896
+ isOpen: reveal[index],
897
+ rowValues: rowValues,
898
+ colSpan: props.headers.length + 1
899
+ });
900
+ }));
901
+ });
902
+ DataRow.propTypes = {
903
+ rowValues: PropTypes.object.isRequired,
904
+ headers: PropTypes.array.isRequired,
905
+ selectRows: PropTypes.bool,
906
+ isSelected: PropTypes.func.isRequired,
907
+ handleClick: PropTypes.func,
908
+ hideBadge: PropTypes.bool,
909
+ rowID: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
910
+ };
911
+
912
+ var TableLoader = function TableLoader() {
913
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TableHead, null), /*#__PURE__*/React.createElement(TableBody, null, Array.from({
914
+ length: 5
915
+ }).map(function (_, index) {
916
+ return /*#__PURE__*/React.createElement(TableRow, {
917
+ key: index
918
+ }, Array.from({
919
+ length: 4
920
+ }).map(function (_, cellIndex) {
921
+ return /*#__PURE__*/React.createElement(TableCell, {
922
+ key: cellIndex
923
+ }, /*#__PURE__*/React.createElement(Skeleton, {
924
+ height: 30
925
+ }));
926
+ }));
927
+ })));
928
+ };
929
+
930
+ function EnhancedTable(props) {
931
+ var headers = props.headers,
932
+ rows = props.rows,
933
+ subTable = props.subTable,
934
+ selected = props.selected,
935
+ selectID = props.selectID;
936
+ var _useEnhancedTableStat = useEnhancedTableState({
937
+ rows: rows,
938
+ subTable: subTable,
939
+ resetFlag: props.resetFlag
940
+ }),
941
+ order = _useEnhancedTableStat.order,
942
+ orderBy = _useEnhancedTableStat.orderBy,
943
+ page = _useEnhancedTableStat.page,
944
+ rowsPerPage = _useEnhancedTableStat.rowsPerPage,
945
+ handleRequestSort = _useEnhancedTableStat.handleRequestSort,
946
+ handleChangePage = _useEnhancedTableStat.handleChangePage,
947
+ handleChangeRowsPerPage = _useEnhancedTableStat.handleChangeRowsPerPage;
948
+ var emptyRows = Math.max(0, rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage));
949
+ var isSelected = React.useCallback(function (id) {
950
+ return selected.includes(id);
951
+ }, [selected]);
952
+ var visibleRows = React.useMemo(function () {
953
+ return stableSort(rows, getComparator(order, orderBy), headers).slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
954
+ }, [headers, order, orderBy, page, rows, rowsPerPage]);
955
+ return /*#__PURE__*/React.createElement(TableContainer, null, /*#__PURE__*/React.createElement(Table, {
956
+ sx: {
957
+ minWidth: 750
958
+ },
959
+ size: "small" ,
960
+ "aria-label": props.name || "data table"
961
+ }, props.loading ? /*#__PURE__*/React.createElement(TableLoader, null) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EnhancedTableHead, {
962
+ order: order,
963
+ orderBy: orderBy,
964
+ onRequestSort: handleRequestSort,
965
+ headings: headers,
966
+ selectRows: props.selectRows,
967
+ numSelected: selected.length,
968
+ rowCount: rows.length,
969
+ onSelectAllClick: props.handleSelectAllClick
970
+ }), /*#__PURE__*/React.createElement(TableBody, null, visibleRows.map(function (row, index) {
971
+ var rowKey = selectID ? row[selectID] : "row-".concat(page * rowsPerPage + index);
972
+ var rowID = getSelectableRowId(row, index, selectID);
973
+ return /*#__PURE__*/React.createElement(DataRow, {
974
+ key: rowKey,
975
+ rowID: rowID,
976
+ headers: headers,
977
+ rowValues: row,
978
+ hideBadge: props.hideBadge,
979
+ selectRows: props.selectRows,
980
+ handleClick: props.handleClick,
981
+ isSelected: isSelected
982
+ });
983
+ }), !subTable && emptyRows > 0 && /*#__PURE__*/React.createElement(TableRow, {
984
+ style: {
985
+ height: (33 ) * emptyRows
986
+ }
987
+ }, /*#__PURE__*/React.createElement(TableCell, {
988
+ colSpan: headers.length
989
+ }))))), subTable ? /*#__PURE__*/React.createElement(Box, {
990
+ sx: {
991
+ mb: 3
992
+ }
993
+ }) : /*#__PURE__*/React.createElement(TablePagination, {
994
+ rowsPerPageOptions: props.pageSizeOptions || getPageOptions(rows.length),
995
+ component: "div",
996
+ count: rows.length,
997
+ rowsPerPage: rowsPerPage,
998
+ page: page,
999
+ onPageChange: handleChangePage,
1000
+ onRowsPerPageChange: handleChangeRowsPerPage,
1001
+ sx: {
1002
+ overflow: "visible"
1003
+ },
1004
+ showFirstButton: true,
1005
+ showLastButton: true
1006
+ }));
1007
+ }
1008
+ EnhancedTable.propTypes = {
1009
+ headers: PropTypes.array.isRequired,
1010
+ rows: PropTypes.array.isRequired,
1011
+ subTable: PropTypes.bool,
1012
+ hideBadge: PropTypes.bool,
1013
+ loading: PropTypes.bool,
1014
+ selectRows: PropTypes.bool,
1015
+ handleSelectAllClick: PropTypes.func,
1016
+ handleClick: PropTypes.func,
1017
+ selected: PropTypes.array,
1018
+ selectID: PropTypes.string,
1019
+ resetFlag: PropTypes.string,
1020
+ pageSizeOptions: PropTypes.arrayOf(PropTypes.number),
1021
+ name: PropTypes.string
1022
+ };
1023
+
1024
+ function UniversalTable(_ref) {
1025
+ var loading = _ref.loading,
1026
+ setLoading = _ref.setLoading,
1027
+ onReload = _ref.onReload,
1028
+ _ref$lazyloading = _ref.lazyloading,
1029
+ lazyloading = _ref$lazyloading === void 0 ? false : _ref$lazyloading,
1030
+ currentPage = _ref.currentPage,
1031
+ totalPages = _ref.totalPages,
1032
+ data = _ref.data,
1033
+ headers = _ref.headers,
1034
+ name = _ref.name,
1035
+ reloadBtnLoading = _ref.reloadBtnLoading,
1036
+ _ref$subTable = _ref.subTable,
1037
+ subTable = _ref$subTable === void 0 ? false : _ref$subTable,
1038
+ _ref$hideBadge = _ref.hideBadge,
1039
+ hideBadge = _ref$hideBadge === void 0 ? false : _ref$hideBadge,
1040
+ _ref$selectRows = _ref.selectRows,
1041
+ selectRows = _ref$selectRows === void 0 ? false : _ref$selectRows,
1042
+ selectID = _ref.selectID,
1043
+ selectIcon = _ref.selectIcon,
1044
+ onSelection = _ref.onSelection,
1045
+ pageSizeOptions = _ref.pageSizeOptions,
1046
+ persistSearch = _ref.persistSearch;
1047
+ var head = headers || [];
1048
+ var _useSearchableRows = useSearchableRows(data, head),
1049
+ rows = _useSearchableRows.rows,
1050
+ searchTerm = _useSearchableRows.searchTerm,
1051
+ setSearchTerm = _useSearchableRows.setSearchTerm;
1052
+ var _useSelectableRows = useSelectableRows({
1053
+ rows: rows,
1054
+ selectRows: selectRows,
1055
+ selectID: selectID
1056
+ }),
1057
+ selected = _useSelectableRows.selected,
1058
+ clearSelection = _useSelectableRows.clearSelection,
1059
+ handleSelectAllClick = _useSelectableRows.handleSelectAllClick,
1060
+ handleClick = _useSelectableRows.handleClick;
1061
+ var handleSearchChange = React.useCallback(function (value) {
1062
+ clearSelection();
1063
+ setSearchTerm(value);
1064
+ }, [clearSelection, setSearchTerm]);
1065
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(LazyLoadingIndicator, {
1066
+ show: lazyloading,
1067
+ currentPage: currentPage,
1068
+ totalPages: totalPages
1069
+ }), /*#__PURE__*/React.createElement(Paper$1, {
1070
+ sx: _objectSpread2({}, subTable && {
1071
+ boxShadow: "none"
1072
+ })
1073
+ }, /*#__PURE__*/React.createElement(TableSelectionBanner, {
1074
+ selected: selected,
1075
+ onSelection: onSelection,
1076
+ selectIcon: selectIcon
1077
+ }), /*#__PURE__*/React.createElement(TableTitle, {
1078
+ name: name,
1079
+ subTable: subTable
1080
+ }), !subTable && /*#__PURE__*/React.createElement(TableToolbarContent, {
1081
+ setLoading: setLoading,
1082
+ onReload: onReload,
1083
+ reloadBtnLoading: reloadBtnLoading,
1084
+ searchTerm: searchTerm,
1085
+ onSearchChange: handleSearchChange,
1086
+ name: name,
1087
+ persistSearch: persistSearch
1088
+ }), /*#__PURE__*/React.createElement(EnhancedTable, {
1089
+ headers: head,
1090
+ rows: rows,
1091
+ resetFlag: searchTerm,
1092
+ subTable: subTable,
1093
+ hideBadge: hideBadge,
1094
+ loading: loading,
1095
+ selectRows: selectRows,
1096
+ handleSelectAllClick: handleSelectAllClick,
1097
+ handleClick: handleClick,
1098
+ selected: selected,
1099
+ selectID: selectID,
1100
+ pageSizeOptions: pageSizeOptions,
1101
+ name: name
1102
+ })));
1103
+ }
1104
+ UniversalTable.propTypes = {
1105
+ loading: PropTypes.bool,
1106
+ setLoading: PropTypes.func,
1107
+ /** Preferred callback — fires when the user clicks reload. */
1108
+ onReload: PropTypes.func,
1109
+ lazyloading: PropTypes.bool,
1110
+ currentPage: PropTypes.number,
1111
+ totalPages: PropTypes.number,
1112
+ data: PropTypes.array.isRequired,
1113
+ headers: PropTypes.array.isRequired,
1114
+ name: PropTypes.string,
1115
+ reloadBtnLoading: PropTypes.bool,
1116
+ subTable: PropTypes.bool,
1117
+ hideBadge: PropTypes.bool,
1118
+ selectRows: PropTypes.bool,
1119
+ selectID: PropTypes.string,
1120
+ selectIcon: PropTypes.element,
1121
+ onSelection: PropTypes.func,
1122
+ /** Override default page size options (e.g. [10, 25, 50]). Default auto-computed. */
1123
+ pageSizeOptions: PropTypes.arrayOf(PropTypes.number),
1124
+ /** Persist search term to sessionStorage (requires name prop). Default: false */
1125
+ persistSearch: PropTypes.bool
1126
+ };
1127
+
1128
+ var UniversalTable$1 = /*#__PURE__*/Object.freeze({
1129
+ __proto__: null,
1130
+ default: UniversalTable
1131
+ });
1132
+
1133
+ export { UniversalTable, UniversalTable as default };
1134
+ //# sourceMappingURL=index.esm.js.map