@monolith-forensics/monolith-ui 1.3.115-dev.0 → 1.3.116-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -58,6 +58,7 @@ const StyledContent = styled.div `
58
58
  const StyledInnerContent = styled.div `
59
59
  display: flex;
60
60
  flex-direction: column;
61
+ flex: 1 1 auto;
61
62
 
62
63
  overflow-y: auto;
63
64
  padding: 25px;
@@ -81,7 +81,7 @@ const TableMenu = () => {
81
81
  inputRef.current.value = "";
82
82
  }
83
83
  }, [searchState]);
84
- return (_jsxs(StyledContainer, { children: [_jsxs(FlexedRow, { className: "justify-sb", children: [_jsxs(FlexedRow, { children: [(addButtonOptions === null || addButtonOptions === void 0 ? void 0 : addButtonOptions.enabled) === true &&
84
+ return (_jsxs(StyledContainer, { className: "mfui-table-menu", children: [_jsxs(FlexedRow, { className: "justify-sb", children: [_jsxs(FlexedRow, { children: [(addButtonOptions === null || addButtonOptions === void 0 ? void 0 : addButtonOptions.enabled) === true &&
85
85
  ((addButtonOptions === null || addButtonOptions === void 0 ? void 0 : addButtonOptions.type) === "button" ||
86
86
  (addButtonOptions === null || addButtonOptions === void 0 ? void 0 : addButtonOptions.type) === undefined) && (_jsx(Button, Object.assign({ color: "primary", variant: "contained", size: "xxs", onClick: () => { var _a; return (_a = addButtonOptions === null || addButtonOptions === void 0 ? void 0 : addButtonOptions.onClick) === null || _a === void 0 ? void 0 : _a.call(addButtonOptions); } }, addButtonOptions === null || addButtonOptions === void 0 ? void 0 : addButtonOptions.buttonOptions, { children: ((_b = tableMenuOptions === null || tableMenuOptions === void 0 ? void 0 : tableMenuOptions.addButtonOptions) === null || _b === void 0 ? void 0 : _b.label) || "+ Add Record" }))), (addButtonOptions === null || addButtonOptions === void 0 ? void 0 : addButtonOptions.enabled) === true &&
87
87
  (addButtonOptions === null || addButtonOptions === void 0 ? void 0 : addButtonOptions.type) === "menu" && (_jsx(DropDownMenu, Object.assign({ data: [], variant: "contained", arrow: true, size: "xxs", buttonProps: {
@@ -17,9 +17,27 @@ import TableDefaults from "./TableDefaults";
17
17
  import shortUUID from "short-uuid";
18
18
  import { SelectionStatus } from "./enums";
19
19
  import moment from "moment";
20
+ import { useControlled } from "../Utilities";
21
+ const calculateSelectionTotal = (selectionState, totalRecords, dataLength = 0) => {
22
+ if (!selectionState) {
23
+ return 0;
24
+ }
25
+ switch (selectionState.selectionStatus) {
26
+ case SelectionStatus.All:
27
+ return totalRecords || dataLength;
28
+ case SelectionStatus.SomeIncluded:
29
+ return selectionState.selectedRowKeys.length;
30
+ case SelectionStatus.SomeExcluded:
31
+ return totalRecords
32
+ ? totalRecords - selectionState.excludedRowKeys.length
33
+ : dataLength - selectionState.excludedRowKeys.length;
34
+ default:
35
+ return 0;
36
+ }
37
+ };
20
38
  export const TableContext = createContext(null);
21
39
  const TableProvider = (_a) => {
22
- var { children, columns, tableInstanceRef, stateStorage, height, maxHeight, minHeight, focusedRowId } = _a, props = __rest(_a, ["children", "columns", "tableInstanceRef", "stateStorage", "height", "maxHeight", "minHeight", "focusedRowId"]);
40
+ var { children, columns, data, keyField, tableInstanceRef, stateStorage, tableMenuOptions, manualSorting, manualFiltering, manualSearch, height, maxHeight, minHeight, focusedRowId, enableColumnResize, enableSorting, compact, totalRecords, onColumnStateChange, onColumnReorder, onColumnHeaderClick, onSort, onRowUpdated, tableElement, headerRowElm, tableDimensions, targetElm, listElm, defaultSelectionState, selectionState, onSelectionChange, defaultFilterState, filterState, onFilterChange } = _a, props = __rest(_a, ["children", "columns", "data", "keyField", "tableInstanceRef", "stateStorage", "tableMenuOptions", "manualSorting", "manualFiltering", "manualSearch", "height", "maxHeight", "minHeight", "focusedRowId", "enableColumnResize", "enableSorting", "compact", "totalRecords", "onColumnStateChange", "onColumnReorder", "onColumnHeaderClick", "onSort", "onRowUpdated", "tableElement", "headerRowElm", "tableDimensions", "targetElm", "listElm", "defaultSelectionState", "selectionState", "onSelectionChange", "defaultFilterState", "filterState", "onFilterChange"]);
23
41
  const _columns = useMemo(() => columns
24
42
  .map((child, index) => {
25
43
  if (child.dataField === "__key") {
@@ -34,36 +52,47 @@ const TableProvider = (_a) => {
34
52
  ? child.width < TableDefaults.td.minWidth
35
53
  ? child.width
36
54
  : TableDefaults.td.minWidth
37
- : TableDefaults.td.minWidth, columnId: shortUUID.generate(), enableResize: resolveColumnResize(child, props.enableColumnResize) });
55
+ : TableDefaults.td.minWidth, columnId: shortUUID.generate(), enableResize: resolveColumnResize(child, enableColumnResize) });
38
56
  })
39
- .sort((a, b) => a.orderValue - b.orderValue), [columns, props.enableColumnResize]);
57
+ .sort((a, b) => a.orderValue - b.orderValue), [columns, enableColumnResize]);
40
58
  const savedTableState = useMemo(() => {
41
59
  return (stateStorage === null || stateStorage === void 0 ? void 0 : stateStorage.enabled)
42
60
  ? StateStorage.getTableState(stateStorage.key)
43
61
  : undefined;
44
62
  }, [stateStorage === null || stateStorage === void 0 ? void 0 : stateStorage.key]);
45
63
  const { columnState: savedColumnState, selectionState: savedSelectionState, sortState: savedSortState, searchState: savedSearchState, filterState: savedFilterState, } = savedTableState || {};
46
- const [compactState, setCompactState] = useState(props.compact || false);
64
+ const [compactState, setCompactState] = useState(compact || false);
47
65
  const [columnState, setColumnState] = useState(syncColumnState(_columns, savedColumnState));
48
66
  const [search, setSearch] = useState(savedSearchState || "");
49
- const [filterState, setFilterState] = useState(savedFilterState);
67
+ const [_filterState, _setFilterState] = useControlled(filterState, defaultFilterState ||
68
+ savedFilterState || {
69
+ combinator: "and",
70
+ rules: [],
71
+ });
50
72
  const [sortState, setSortState] = useState(savedSortState);
51
- const [selectionStatus, setSelectionStatus] = useState((savedSelectionState === null || savedSelectionState === void 0 ? void 0 : savedSelectionState.selectionStatus) || SelectionStatus.None);
52
- const [excludedRowKeys, setExcludedRowKeys] = useState((savedSelectionState === null || savedSelectionState === void 0 ? void 0 : savedSelectionState.excludedRowKeys) || []);
53
- const [selectedRowKeys, setSelectedRowKeys] = useState((savedSelectionState === null || savedSelectionState === void 0 ? void 0 : savedSelectionState.selectedRowKeys) || []);
54
- const calculateSelectionTotal = (selectionState, totalRecords, dataLength = 0) => {
55
- switch (selectionState.selectionStatus) {
56
- case SelectionStatus.All:
57
- return totalRecords || dataLength;
58
- case SelectionStatus.SomeIncluded:
59
- return selectionState.selectedRowKeys.length;
60
- case SelectionStatus.SomeExcluded:
61
- return totalRecords
62
- ? totalRecords - selectionState.excludedRowKeys.length
63
- : dataLength - selectionState.excludedRowKeys.length;
64
- default:
65
- return 0;
66
- }
73
+ const [_selectionState, _setSelectionState] = useControlled(selectionState, defaultSelectionState || {
74
+ selectedRowKeys: (savedSelectionState === null || savedSelectionState === void 0 ? void 0 : savedSelectionState.selectedRowKeys) || [],
75
+ excludedRowKeys: (savedSelectionState === null || savedSelectionState === void 0 ? void 0 : savedSelectionState.excludedRowKeys) || [],
76
+ selectionStatus: (savedSelectionState === null || savedSelectionState === void 0 ? void 0 : savedSelectionState.selectionStatus) || SelectionStatus.None,
77
+ totalSelected: calculateSelectionTotal(savedSelectionState, totalRecords, data.length),
78
+ });
79
+ const selectionStatus = _selectionState.selectionStatus;
80
+ const excludedRowKeys = _selectionState.excludedRowKeys;
81
+ const selectedRowKeys = _selectionState.selectedRowKeys;
82
+ const setSelectionStatus = (selectionStatus) => {
83
+ _setSelectionState((prev) => {
84
+ return Object.assign(Object.assign({}, prev), { selectionStatus });
85
+ });
86
+ };
87
+ const setExcludedRowKeys = (excludedRowKeys) => {
88
+ _setSelectionState((prev) => {
89
+ return Object.assign(Object.assign({}, prev), { excludedRowKeys });
90
+ });
91
+ };
92
+ const setSelectedRowKeys = (selectedRowKeys) => {
93
+ _setSelectionState((prev) => {
94
+ return Object.assign(Object.assign({}, prev), { selectedRowKeys });
95
+ });
67
96
  };
68
97
  const getCalculatedSelectionTotal = () => {
69
98
  return calculateSelectionTotal({
@@ -71,15 +100,14 @@ const TableProvider = (_a) => {
71
100
  excludedRowKeys,
72
101
  selectionStatus,
73
102
  totalSelected: 0,
74
- }, props === null || props === void 0 ? void 0 : props.totalRecords, props.data.length);
103
+ }, totalRecords, data.length);
75
104
  };
76
105
  const getColumnState = (dataField) => {
77
106
  return columnState.find((col) => col.dataField === dataField);
78
107
  };
79
108
  const updateColumnState = (columnState) => {
80
- var _a;
81
109
  setColumnState(columnState);
82
- (_a = props.onColumnStateChange) === null || _a === void 0 ? void 0 : _a.call(props, columnState);
110
+ onColumnStateChange === null || onColumnStateChange === void 0 ? void 0 : onColumnStateChange(columnState);
83
111
  if (stateStorage === null || stateStorage === void 0 ? void 0 : stateStorage.enabled) {
84
112
  if ((stateStorage === null || stateStorage === void 0 ? void 0 : stateStorage.type) === "localStorage") {
85
113
  StateStorage.setColumnState(stateStorage.key, columnState);
@@ -87,7 +115,7 @@ const TableProvider = (_a) => {
87
115
  }
88
116
  };
89
117
  const handleColumnReorder = (dragColumn, dropColumn) => {
90
- var _a, _b, _c;
118
+ var _a, _b;
91
119
  if (!dragColumn || !dropColumn)
92
120
  return;
93
121
  const dropColumnOrder = (_a = columnState.find((col) => col.dataField === dropColumn.dataField)) === null || _a === void 0 ? void 0 : _a.orderValue;
@@ -110,14 +138,13 @@ const TableProvider = (_a) => {
110
138
  })
111
139
  .sort((a, b) => a.orderValue - b.orderValue);
112
140
  updateColumnState(newColumnState);
113
- (_c = props.onColumnReorder) === null || _c === void 0 ? void 0 : _c.call(props, {
141
+ onColumnReorder === null || onColumnReorder === void 0 ? void 0 : onColumnReorder({
114
142
  columnState: newColumnState,
115
143
  column: dragColumn,
116
144
  });
117
145
  };
118
146
  const handleColumnHeaderClick = (column) => {
119
- var _a, _b;
120
- if (props.enableSorting === true || column.enableSorting === true) {
147
+ if (enableSorting === true || column.enableSorting === true) {
121
148
  let newSortState = {
122
149
  dataField: column.dataField,
123
150
  dir: "asc",
@@ -132,16 +159,17 @@ const TableProvider = (_a) => {
132
159
  }
133
160
  }
134
161
  }
135
- (_a = props.onColumnHeaderClick) === null || _a === void 0 ? void 0 : _a.call(props, { column, sort: newSortState });
162
+ onColumnHeaderClick === null || onColumnHeaderClick === void 0 ? void 0 : onColumnHeaderClick({ column, sort: newSortState });
136
163
  updateSortState(newSortState);
137
164
  }
138
165
  else {
139
- (_b = props.onColumnHeaderClick) === null || _b === void 0 ? void 0 : _b.call(props, { column, sort: undefined });
166
+ onColumnHeaderClick === null || onColumnHeaderClick === void 0 ? void 0 : onColumnHeaderClick({ column, sort: undefined });
140
167
  updateSortState(undefined);
141
168
  }
142
169
  };
143
170
  const handleFilterChange = (query) => {
144
- setFilterState(query);
171
+ _setFilterState(query);
172
+ onFilterChange === null || onFilterChange === void 0 ? void 0 : onFilterChange(query);
145
173
  if (stateStorage === null || stateStorage === void 0 ? void 0 : stateStorage.enabled) {
146
174
  if ((stateStorage === null || stateStorage === void 0 ? void 0 : stateStorage.type) === "localStorage") {
147
175
  StateStorage.setFilterState(stateStorage.key, query);
@@ -149,9 +177,9 @@ const TableProvider = (_a) => {
149
177
  }
150
178
  };
151
179
  const updateSearchState = (searchState) => {
152
- var _a, _b, _c;
180
+ var _a, _b;
153
181
  setSearch(searchState);
154
- (_c = (_b = (_a = props.tableMenuOptions) === null || _a === void 0 ? void 0 : _a.searchOptions) === null || _b === void 0 ? void 0 : _b.onSearch) === null || _c === void 0 ? void 0 : _c.call(_b, searchState);
182
+ (_b = (_a = tableMenuOptions === null || tableMenuOptions === void 0 ? void 0 : tableMenuOptions.searchOptions) === null || _a === void 0 ? void 0 : _a.onSearch) === null || _b === void 0 ? void 0 : _b.call(_a, searchState);
155
183
  if (stateStorage === null || stateStorage === void 0 ? void 0 : stateStorage.enabled) {
156
184
  if ((stateStorage === null || stateStorage === void 0 ? void 0 : stateStorage.type) === "localStorage") {
157
185
  StateStorage.setSearchState(stateStorage.key, searchState);
@@ -165,10 +193,10 @@ const TableProvider = (_a) => {
165
193
  updateSearchState("");
166
194
  };
167
195
  const updateSortState = (sortState) => {
168
- var _a, _b;
196
+ var _a;
169
197
  setSortState(sortState);
170
- (_a = props.onSort) === null || _a === void 0 ? void 0 : _a.call(props, {
171
- column: (_b = columnState.find((col) => col.dataField === (sortState === null || sortState === void 0 ? void 0 : sortState.dataField))) !== null && _b !== void 0 ? _b : {},
198
+ onSort === null || onSort === void 0 ? void 0 : onSort({
199
+ column: (_a = columnState.find((col) => col.dataField === (sortState === null || sortState === void 0 ? void 0 : sortState.dataField))) !== null && _a !== void 0 ? _a : {},
172
200
  sort: sortState,
173
201
  });
174
202
  if (stateStorage === null || stateStorage === void 0 ? void 0 : stateStorage.enabled) {
@@ -179,7 +207,7 @@ const TableProvider = (_a) => {
179
207
  };
180
208
  const sortData = (sortState) => {
181
209
  // sort data
182
- return props.data.sort((a, b) => {
210
+ return data.sort((a, b) => {
183
211
  if (sortState) {
184
212
  if (sortState.dir === "asc") {
185
213
  if (a[sortState.dataField] < b[sortState.dataField]) {
@@ -212,7 +240,7 @@ const TableProvider = (_a) => {
212
240
  };
213
241
  const searchData = (searchText) => {
214
242
  const columnKeys = columnState.map((col) => col.dataField);
215
- return props.data.filter((row) => {
243
+ return data.filter((row) => {
216
244
  return columnKeys.some((key) => {
217
245
  if (typeof row[key] === "string") {
218
246
  return row[key].toLowerCase().includes(searchText.toLowerCase());
@@ -320,15 +348,15 @@ const TableProvider = (_a) => {
320
348
  }
321
349
  };
322
350
  const filterData = (filter) => {
323
- if (!props.data)
351
+ if (!data)
324
352
  return [];
325
353
  const { combinator, rules } = filter;
326
354
  if (!combinator || !rules)
327
- return props.data;
355
+ return data;
328
356
  if (combinator === "or") {
329
- return props.data.filter((row) => rules.some((rule) => rowMatchesRule(row, rule)));
357
+ return data.filter((row) => rules.some((rule) => rowMatchesRule(row, rule)));
330
358
  }
331
- return props.data.filter((row) => rules.every((rule) => rowMatchesRule(row, rule)));
359
+ return data.filter((row) => rules.every((rule) => rowMatchesRule(row, rule)));
332
360
  };
333
361
  const toggleColumnVisibility = (dataField) => {
334
362
  const newColumnState = columnState.map((col) => {
@@ -353,39 +381,50 @@ const TableProvider = (_a) => {
353
381
  }
354
382
  }
355
383
  };
384
+ const getRowKey = (row) => {
385
+ const key = !!keyField ? row[keyField] : row.__key;
386
+ return String(key);
387
+ };
356
388
  const selectRow = (row) => {
357
- var _a;
358
- const key = !!props.keyField ? row[props.keyField] : row.__key;
359
- const keyField = !!props.keyField ? props.keyField : "__key";
389
+ const key = getRowKey(row);
360
390
  const newSelectionState = {
361
391
  selectedRowKeys,
362
392
  excludedRowKeys,
363
393
  selectionStatus,
364
394
  totalSelected: 0,
365
395
  };
366
- if (props.data.length === selectedRowKeys.length + 1) {
367
- newSelectionState.selectionStatus = SelectionStatus.All;
396
+ if (selectionStatus === SelectionStatus.All ||
397
+ selectionStatus === SelectionStatus.SomeExcluded) {
398
+ const nextExcluded = excludedRowKeys.filter((k) => k !== key);
399
+ newSelectionState.excludedRowKeys = nextExcluded;
400
+ newSelectionState.selectedRowKeys = [];
401
+ newSelectionState.selectionStatus =
402
+ nextExcluded.length === 0
403
+ ? SelectionStatus.All
404
+ : SelectionStatus.SomeExcluded;
368
405
  }
369
406
  else {
370
- newSelectionState.selectionStatus = SelectionStatus.SomeIncluded;
407
+ const nextSelected = selectedRowKeys.includes(key)
408
+ ? selectedRowKeys
409
+ : [...selectedRowKeys, key];
410
+ newSelectionState.selectedRowKeys = nextSelected;
411
+ newSelectionState.excludedRowKeys = excludedRowKeys.filter((k) => k !== key);
412
+ newSelectionState.selectionStatus =
413
+ nextSelected.length === 0
414
+ ? SelectionStatus.None
415
+ : nextSelected.length === data.length
416
+ ? SelectionStatus.All
417
+ : SelectionStatus.SomeIncluded;
371
418
  }
372
- newSelectionState.selectedRowKeys = [
373
- ...newSelectionState.selectedRowKeys,
374
- key,
375
- ];
376
- newSelectionState.excludedRowKeys =
377
- newSelectionState.excludedRowKeys.filter((k) => k !== key);
378
- newSelectionState.totalSelected = calculateSelectionTotal(newSelectionState, props === null || props === void 0 ? void 0 : props.totalRecords, props.data.length);
419
+ newSelectionState.totalSelected = calculateSelectionTotal(newSelectionState, totalRecords, data.length);
379
420
  setSelectionStatus(newSelectionState.selectionStatus);
380
421
  setSelectedRowKeys(newSelectionState.selectedRowKeys);
381
422
  setExcludedRowKeys(newSelectionState.excludedRowKeys);
382
423
  saveSelectionState(newSelectionState);
383
- (_a = props.onSelectionChange) === null || _a === void 0 ? void 0 : _a.call(props, newSelectionState);
424
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(newSelectionState);
384
425
  };
385
426
  const deselectRow = (row) => {
386
- var _a;
387
- const key = !!props.keyField ? row[props.keyField] : row.__key;
388
- const keyField = !!props.keyField ? props.keyField : "__key";
427
+ const key = getRowKey(row);
389
428
  const newSelectionState = {
390
429
  selectedRowKeys,
391
430
  excludedRowKeys,
@@ -394,27 +433,34 @@ const TableProvider = (_a) => {
394
433
  };
395
434
  if (selectionStatus === SelectionStatus.All ||
396
435
  selectionStatus === SelectionStatus.SomeExcluded) {
397
- newSelectionState.selectionStatus = SelectionStatus.SomeExcluded;
398
- newSelectionState.excludedRowKeys = [
399
- ...newSelectionState.excludedRowKeys,
400
- key,
401
- ];
436
+ const nextExcluded = excludedRowKeys.includes(key)
437
+ ? excludedRowKeys
438
+ : [...excludedRowKeys, key];
439
+ const totalSelectableRows = totalRecords || data.length;
440
+ newSelectionState.selectedRowKeys = [];
441
+ newSelectionState.excludedRowKeys = nextExcluded;
442
+ newSelectionState.selectionStatus =
443
+ nextExcluded.length >= totalSelectableRows
444
+ ? SelectionStatus.None
445
+ : SelectionStatus.SomeExcluded;
402
446
  }
403
- if (selectedRowKeys.length === 1) {
404
- newSelectionState.selectionStatus = SelectionStatus.None;
447
+ else {
448
+ const nextSelected = selectedRowKeys.filter((k) => k !== key);
449
+ newSelectionState.selectedRowKeys = nextSelected;
450
+ newSelectionState.selectionStatus =
451
+ nextSelected.length === 0
452
+ ? SelectionStatus.None
453
+ : SelectionStatus.SomeIncluded;
405
454
  }
406
- newSelectionState.selectedRowKeys =
407
- newSelectionState.selectedRowKeys.filter((k) => k !== key);
408
- newSelectionState.totalSelected = calculateSelectionTotal(newSelectionState, props === null || props === void 0 ? void 0 : props.totalRecords, props.data.length);
455
+ newSelectionState.totalSelected = calculateSelectionTotal(newSelectionState, totalRecords, data.length);
409
456
  setSelectionStatus(newSelectionState.selectionStatus);
410
457
  setSelectedRowKeys(newSelectionState.selectedRowKeys);
411
458
  setExcludedRowKeys(newSelectionState.excludedRowKeys);
412
459
  saveSelectionState(newSelectionState);
413
- (_a = props.onSelectionChange) === null || _a === void 0 ? void 0 : _a.call(props, newSelectionState);
460
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(newSelectionState);
414
461
  };
415
462
  const selectAllRows = () => {
416
- var _a, _b;
417
- const keys = ((_a = props.data) === null || _a === void 0 ? void 0 : _a.map((row) => !!props.keyField ? row[props.keyField] : row.__key)) || [];
463
+ const keys = (data === null || data === void 0 ? void 0 : data.map((row) => getRowKey(row))) || [];
418
464
  const newSelectionState = {
419
465
  selectedRowKeys,
420
466
  excludedRowKeys,
@@ -424,15 +470,14 @@ const TableProvider = (_a) => {
424
470
  newSelectionState.selectedRowKeys = keys;
425
471
  newSelectionState.excludedRowKeys = [];
426
472
  newSelectionState.selectionStatus = SelectionStatus.All;
427
- newSelectionState.totalSelected = calculateSelectionTotal(newSelectionState, props === null || props === void 0 ? void 0 : props.totalRecords, props.data.length);
473
+ newSelectionState.totalSelected = calculateSelectionTotal(newSelectionState, totalRecords, data.length);
428
474
  setSelectionStatus(newSelectionState.selectionStatus);
429
475
  setSelectedRowKeys(newSelectionState.selectedRowKeys);
430
476
  setExcludedRowKeys(newSelectionState.excludedRowKeys);
431
477
  saveSelectionState(newSelectionState);
432
- (_b = props.onSelectionChange) === null || _b === void 0 ? void 0 : _b.call(props, newSelectionState);
478
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(newSelectionState);
433
479
  };
434
480
  const clearSelections = () => {
435
- var _a;
436
481
  const newSelectionState = {
437
482
  selectedRowKeys,
438
483
  excludedRowKeys,
@@ -442,16 +487,16 @@ const TableProvider = (_a) => {
442
487
  newSelectionState.selectedRowKeys = [];
443
488
  newSelectionState.excludedRowKeys = [];
444
489
  newSelectionState.selectionStatus = SelectionStatus.None;
445
- newSelectionState.totalSelected = calculateSelectionTotal(newSelectionState, props === null || props === void 0 ? void 0 : props.totalRecords, props.data.length);
490
+ newSelectionState.totalSelected = calculateSelectionTotal(newSelectionState, totalRecords, data.length);
446
491
  setSelectionStatus(newSelectionState.selectionStatus);
447
492
  setSelectedRowKeys(newSelectionState.selectedRowKeys);
448
493
  setExcludedRowKeys(newSelectionState.excludedRowKeys);
449
- (_a = props.onSelectionChange) === null || _a === void 0 ? void 0 : _a.call(props, newSelectionState);
494
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(newSelectionState);
450
495
  saveSelectionState(newSelectionState);
451
496
  };
452
497
  const getSelectedRows = () => {
453
- return props.data.filter((row) => {
454
- const key = !!props.keyField ? row[props.keyField] : row.__key;
498
+ return data.filter((row) => {
499
+ const key = getRowKey(row);
455
500
  return selectedRowKeys.includes(key);
456
501
  });
457
502
  };
@@ -459,7 +504,7 @@ const TableProvider = (_a) => {
459
504
  return selectedRowKeys;
460
505
  };
461
506
  const isRowSelected = (row) => {
462
- const key = !!props.keyField ? row[props.keyField] : row.__key;
507
+ const key = getRowKey(row);
463
508
  switch (selectionStatus) {
464
509
  case SelectionStatus.All:
465
510
  return true;
@@ -474,7 +519,7 @@ const TableProvider = (_a) => {
474
519
  }
475
520
  };
476
521
  const isRowFocused = (row) => {
477
- const key = !!props.keyField ? row[props.keyField] : row.__key;
522
+ const key = getRowKey(row);
478
523
  return focusedRowId === key;
479
524
  };
480
525
  if (tableInstanceRef) {
@@ -504,33 +549,30 @@ const TableProvider = (_a) => {
504
549
  },
505
550
  sortState,
506
551
  searchState: search,
507
- filterState,
552
+ _filterState,
508
553
  };
509
554
  },
510
555
  };
511
556
  }
512
557
  const _data = useMemo(() => {
513
- let processedData = props.data; // create a new array to avoid mutating the original data
514
- if (props.manualSorting !== true) {
558
+ let processedData = data; // create a new array to avoid mutating the original data
559
+ if (manualSorting !== true) {
515
560
  processedData = sortData(sortState);
516
561
  }
517
- if (props.manualFiltering !== true && filterState) {
518
- processedData = filterData(filterState);
562
+ if (manualFiltering !== true && _filterState) {
563
+ processedData = filterData(_filterState);
519
564
  }
520
- if (props.manualSearch !== true && search) {
565
+ if (manualSearch !== true && search) {
521
566
  processedData = searchData(search);
522
567
  }
523
568
  return processedData;
524
- }, [props.data, columnState, search, sortState, filterState]);
525
- return (_jsx(TableContext.Provider, { value: Object.assign(Object.assign({ columnState,
569
+ }, [data, columnState, search, sortState, _filterState]);
570
+ return (_jsx(TableContext.Provider, { value: Object.assign({ columnState,
526
571
  setColumnState,
527
- sortState, searchState: search, handleColumnReorder,
528
- handleColumnHeaderClick, selectionState: {
529
- selectedRowKeys,
530
- excludedRowKeys,
531
- selectionStatus,
532
- totalSelected: getCalculatedSelectionTotal(),
533
- }, selectRow,
572
+ sortState, searchState: search, totalRecords,
573
+ keyField,
574
+ handleColumnReorder,
575
+ handleColumnHeaderClick, selectionState: _selectionState, selectRow,
534
576
  deselectRow,
535
577
  isRowSelected,
536
578
  isRowFocused,
@@ -541,10 +583,15 @@ const TableProvider = (_a) => {
541
583
  toggleColumnVisibility,
542
584
  runSearch,
543
585
  clearSearch,
544
- handleFilterChange,
545
- filterState,
546
- compactState,
586
+ handleFilterChange, filterState: _filterState, compactState,
547
587
  toggleCompact,
548
- getCalculatedSelectionTotal, tableHeight: height, tableMaxHeight: maxHeight, tableMinHeight: minHeight }, props), { onRowUpdated: (props === null || props === void 0 ? void 0 : props.onRowUpdated) || (() => { }), data: _data }), children: children }));
588
+ getCalculatedSelectionTotal,
589
+ focusedRowId,
590
+ manualSorting,
591
+ manualSearch,
592
+ stateStorage, tableHeight: height, tableMaxHeight: maxHeight, tableMinHeight: minHeight, compact, tableElement: tableElement, headerRowElm: headerRowElm, tableDimensions: tableDimensions, targetElm: targetElm, listElm: listElm, enableColumnResize,
593
+ onSelectionChange,
594
+ onColumnStateChange,
595
+ onColumnReorder, onRowUpdated: onRowUpdated || (() => { }), tableMenuOptions, data: _data }, props), children: children }));
549
596
  };
550
597
  export default TableProvider;
@@ -189,7 +189,6 @@ export interface TableProviderProps {
189
189
  enableSorting?: boolean;
190
190
  tableMenuOptions?: TableMenuOptions;
191
191
  focusedRowId?: string | number;
192
- onSelectionChange?: onSelectionChangeFn;
193
192
  onActionButtonClick?: (rowData: any) => void;
194
193
  onColumnResize?: (e: OnColumnChangeProps) => void;
195
194
  onColumnReorder?: (e: OnColumnChangeProps) => void;
@@ -206,6 +205,13 @@ export interface TableProviderProps {
206
205
  rowData: any;
207
206
  updatedData: any;
208
207
  }) => void;
208
+ /** Controlled States */
209
+ defaultSelectionState?: SelectionState;
210
+ selectionState?: SelectionState;
211
+ onSelectionChange?: onSelectionChangeFn;
212
+ defaultFilterState?: Query;
213
+ filterState?: Query;
214
+ onFilterChange?: (e: Query) => void;
209
215
  }
210
216
  export interface TableRowProps {
211
217
  rowData: {
@@ -305,7 +311,6 @@ export interface TableProps {
305
311
  rowData: any;
306
312
  updatedData: any;
307
313
  }) => void;
308
- onSelectionChange?: onSelectionChangeFn;
309
314
  onActionButtonClick?: (rowData: any) => void;
310
315
  onColumnResize?: (e: OnColumnChangeProps) => void;
311
316
  onColumnReorder?: (e: OnColumnChangeProps) => void;
@@ -321,7 +326,13 @@ export interface TableProps {
321
326
  onScroll?: (e: React.UIEvent<HTMLElement>) => void;
322
327
  onScrollToTop?: (e: React.UIEvent<HTMLElement>) => void;
323
328
  onScrollToBottom?: (e: React.UIEvent<HTMLElement>) => void;
324
- onFilterChange?: (e: any) => void;
329
+ /** Controlled States */
330
+ defaultSelectionState?: SelectionState;
331
+ selectionState?: SelectionState;
332
+ onSelectionChange?: onSelectionChangeFn;
333
+ defaultFilterState?: Query;
334
+ filterState?: Query;
335
+ onFilterChange?: (e: Query) => void;
325
336
  }
326
337
  export type TableInstance = {
327
338
  columnState: ColumnState[];
@@ -1 +1,5 @@
1
1
  export * from "./getPdfTextContent";
2
+ export * from "./useControlled";
3
+ export * from "./calculateFileHash";
4
+ export * from "./readFileAsBuffer";
5
+ export * from "./parseTimestamp";
@@ -1 +1,5 @@
1
1
  export * from "./getPdfTextContent";
2
+ export * from "./useControlled";
3
+ export * from "./calculateFileHash";
4
+ export * from "./readFileAsBuffer";
5
+ export * from "./parseTimestamp";
@@ -1,6 +1,15 @@
1
1
  import moment from "moment";
2
+ // Converts a timestamp + format string into UI-friendly `Segment[]`.
3
+ // Each segment describes either:
4
+ // - a date/time token (year, month, hour, etc.) with a formatted value, or
5
+ // - a literal separator from the format string ("/", ":", "-", " ", etc.).
6
+ //
7
+ // When `timestamp` is empty, segment values fall back to placeholders so the
8
+ // DateInput can still render an editable structure.
2
9
  export default function parseTimestamp(timestamp, format, utc = false) {
3
- // Define patterns to identify datetime components and their placeholders
10
+ // Supported format tokens and how each token maps to a segment type.
11
+ // `momentType` is used by consumers that need to know which unit the
12
+ // segment represents in Moment's terminology.
4
13
  const patterns = [
5
14
  { pattern: "YYYY", placeholder: "YYYY", type: "year", momentType: "year" },
6
15
  { pattern: "MM", placeholder: "MM", type: "month", momentType: "month" },
@@ -28,11 +37,13 @@ export default function parseTimestamp(timestamp, format, utc = false) {
28
37
  momentType: "timezone",
29
38
  },
30
39
  ];
31
- // Helper function to split format into datetime components and separators
40
+ // Break the format into ordered parts while keeping separators.
41
+ // Example: "MM/DD/YYYY HH:mm" => ["MM", "/", "DD", "/", "YYYY", " ", "HH", ":", "mm"]
32
42
  function splitFormat(format) {
33
43
  return format.split(/(YYYY|MM|DD|HH|h|mm|ss|SSS|Z)/).filter((s) => s);
34
44
  }
35
- // Helper function to match segments to their placeholders and types
45
+ // Convert each format part into a known token descriptor.
46
+ // Unknown parts are treated as literal separators.
36
47
  function matchSegment(segment) {
37
48
  const pattern = patterns.find((p) => p.pattern === segment);
38
49
  return pattern
@@ -46,6 +57,9 @@ export default function parseTimestamp(timestamp, format, utc = false) {
46
57
  index: -1,
47
58
  };
48
59
  }
60
+ // Build the final Segment[] in format order.
61
+ // For date/time tokens, format the timestamp using local or UTC mode.
62
+ // For separators (or empty timestamp), use the placeholder as the value.
49
63
  const segments = splitFormat(format).map((segment, i) => {
50
64
  const { pattern, placeholder, type, momentType } = matchSegment(segment);
51
65
  const value = timestamp
@@ -0,0 +1 @@
1
+ export declare function useControlled<T>(controlledValue: T | undefined, defaultValue: T): [T, React.Dispatch<React.SetStateAction<T>>];
@@ -0,0 +1,12 @@
1
+ import { useCallback, useState } from "react";
2
+ export function useControlled(controlledValue, defaultValue) {
3
+ const [internalValue, setInternalValue] = useState(defaultValue);
4
+ const isControlled = controlledValue !== undefined;
5
+ const value = isControlled ? controlledValue : internalValue;
6
+ const setValue = useCallback((next) => {
7
+ if (!isControlled) {
8
+ setInternalValue(next);
9
+ }
10
+ }, [isControlled]);
11
+ return [value, setValue];
12
+ }
package/dist/index.d.ts CHANGED
@@ -43,3 +43,4 @@ export * from "./Tabs";
43
43
  export * from "./Divider";
44
44
  export * from "./SegmentedControl";
45
45
  export * from "./Popover";
46
+ export * from "./Utilities";
package/dist/index.js CHANGED
@@ -35,3 +35,4 @@ export * from "./Tabs";
35
35
  export * from "./Divider";
36
36
  export * from "./SegmentedControl";
37
37
  export * from "./Popover";
38
+ export * from "./Utilities";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monolith-forensics/monolith-ui",
3
- "version": "1.3.115-dev.0",
3
+ "version": "1.3.116-dev.0",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Matt Danner (Monolith Forensics LLC)",