@monolith-forensics/monolith-ui 1.4.0 → 1.4.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.
@@ -3,6 +3,9 @@ export type AlertProps = {
3
3
  children: React.ReactNode;
4
4
  variant?: AlertVariant;
5
5
  title?: string;
6
+ open?: boolean;
7
+ defaultOpen?: boolean;
8
+ showCloseButton?: boolean;
6
9
  onClose?: () => void;
7
10
  };
8
11
  export declare const Alert: React.FC<AlertProps>;
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { AlertCircleIcon, AlertTriangleIcon, CheckIcon, InfoIcon, } from "lucide-react";
2
+ import { AlertCircleIcon, AlertTriangleIcon, CheckIcon, InfoIcon, XIcon, } from "lucide-react";
3
3
  import styled from "styled-components";
4
+ import { useControlled } from "../Utilities";
4
5
  const Icons = {
5
6
  info: _jsx(InfoIcon, { size: 20 }),
6
7
  success: _jsx(CheckIcon, { size: 20 }),
@@ -9,14 +10,15 @@ const Icons = {
9
10
  default: _jsx(InfoIcon, { size: 20 }),
10
11
  };
11
12
  const StyledContainer = styled.div `
13
+ position: relative;
12
14
  display: flex;
13
15
  gap: 10px;
14
- padding: 15px;
16
+ padding: 15px 40px 15px 15px;
15
17
  border-radius: 4px;
16
18
 
17
- border: 1px solid ${({ theme, variant }) => theme.alert[variant].border};
18
- background-color: ${({ theme, variant }) => theme.alert[variant].background};
19
- color: ${({ theme, variant }) => theme.alert[variant].color};
19
+ border: 1px solid ${({ theme, $variant }) => theme.alert[$variant].border};
20
+ background-color: ${({ theme, $variant }) => theme.alert[$variant].background};
21
+ color: ${({ theme, $variant }) => theme.alert[$variant].color};
20
22
  `;
21
23
  const StyledTitle = styled.div `
22
24
  height: 25px;
@@ -26,7 +28,7 @@ const StyledTitle = styled.div `
26
28
  font-weight: bold;
27
29
  margin: 0px;
28
30
 
29
- color: ${({ theme, variant }) => { var _a; return (_a = theme.alert[variant]) === null || _a === void 0 ? void 0 : _a.color; }};
31
+ color: ${({ theme, $variant }) => { var _a; return (_a = theme.alert[$variant]) === null || _a === void 0 ? void 0 : _a.color; }};
30
32
  `;
31
33
  const StyledContent = styled.div `
32
34
  display: flex;
@@ -34,10 +36,11 @@ const StyledContent = styled.div `
34
36
  font-weight: 400;
35
37
  margin: 0px;
36
38
 
37
- color: ${({ theme, variant }) => theme.palette.text.primary};
39
+ color: ${({ theme }) => theme.palette.text.primary};
38
40
  `;
39
41
  const StyledContentContainer = styled.div `
40
42
  display: flex;
43
+ flex: 1;
41
44
  flex-direction: column;
42
45
  gap: 5px;
43
46
  `;
@@ -47,6 +50,44 @@ const StyledHeader = styled.div `
47
50
  height: 28px;
48
51
  align-items: center;
49
52
  `;
50
- export const Alert = ({ children, variant = "info", title, onClose, }) => {
51
- return (_jsxs(StyledContainer, { variant: variant, children: [_jsx(StyledHeader, { children: Icons[variant] }), _jsxs(StyledContentContainer, { children: [title && _jsx(StyledTitle, { variant: variant, children: title }), _jsx(StyledContent, { variant: variant, children: children })] })] }));
53
+ const StyledCloseButton = styled.button `
54
+ position: absolute;
55
+ top: 10px;
56
+ right: 10px;
57
+ border: none;
58
+ background: transparent;
59
+ display: inline-flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ padding: 0;
63
+ cursor: pointer;
64
+ color: ${({ theme, $variant }) => theme.alert[$variant].color};
65
+ `;
66
+ const StyledCloseIconWrapper = styled.div `
67
+ display: inline-flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ padding: 4px;
71
+ border-radius: 8px;
72
+ background-color: transparent;
73
+ transition:
74
+ background-color 0.15s ease,
75
+ opacity 0.15s ease;
76
+
77
+ ${StyledCloseButton}:hover & {
78
+ ${({ $variant, theme }) => $variant === "default"
79
+ ? `background-color: ${theme.palette.action.hover};`
80
+ : `background-color: ${theme.alert[$variant].background};`}
81
+ }
82
+ `;
83
+ export const Alert = ({ children, variant = "info", title, open, defaultOpen = true, showCloseButton = false, onClose, }) => {
84
+ const [isVisible, setIsVisible] = useControlled(open, defaultOpen);
85
+ if (!isVisible) {
86
+ return null;
87
+ }
88
+ const handleClose = () => {
89
+ setIsVisible(false);
90
+ onClose === null || onClose === void 0 ? void 0 : onClose();
91
+ };
92
+ return (_jsxs(StyledContainer, { "$variant": variant, children: [_jsx(StyledHeader, { children: Icons[variant] }), _jsxs(StyledContentContainer, { children: [title && _jsx(StyledTitle, { "$variant": variant, children: title }), _jsx(StyledContent, { "$variant": variant, children: children })] }), showCloseButton && (_jsx(StyledCloseButton, { type: "button", "$variant": variant, "aria-label": "Close alert", onClick: handleClose, children: _jsx(StyledCloseIconWrapper, { "$variant": variant, children: _jsx(XIcon, { size: 16 }) }) }))] }));
52
93
  };
@@ -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;
@@ -20,13 +20,13 @@ export type Operator = {
20
20
  label: string;
21
21
  value: string;
22
22
  };
23
- export type EditorType = "text" | "select" | "checkbox" | "radio" | "multiselect" | "date" | "time" | null;
23
+ export type InputType = "text" | "number" | "date" | "datetime" | "multiselect";
24
24
  export interface FilterDefinition {
25
25
  dataField: string;
26
26
  label: string;
27
27
  pluralLabel?: string;
28
28
  operators?: Operator[];
29
- inputType?: HTMLInputElement["type"];
29
+ inputType?: InputType;
30
30
  resolution?: "day" | "second" | "millisecond";
31
31
  isoString?: boolean;
32
32
  placeholder?: string;
@@ -34,7 +34,6 @@ export interface FilterDefinition {
34
34
  dropDownOptions?: {
35
35
  style?: React.CSSProperties;
36
36
  };
37
- editorType?: EditorType;
38
37
  query?: DropDownMenuProps["query"];
39
38
  }
40
39
  export interface Rule {
@@ -5,6 +5,6 @@ import useTable from "./useTable";
5
5
  const StaticRows = ({ targetElm, listElm }) => {
6
6
  var _a;
7
7
  const { data, loadingRowIds, keyField } = useTable();
8
- return (_jsx(TBody, { className: "mfui-tbody", children: _jsx(TableViewPort, { className: "mfui-tbody-viewport", ref: targetElm, children: _jsx(TableListElement, { className: "mfui-tbody-list", ref: listElm, children: (_a = data === null || data === void 0 ? void 0 : data.map) === null || _a === void 0 ? void 0 : _a.call(data, (row, index) => (_jsx(TableRow, { rowData: row, loading: !!keyField ? loadingRowIds === null || loadingRowIds === void 0 ? void 0 : loadingRowIds.includes(row[keyField]) : false }, index))) }) }) }));
8
+ return (_jsx(TBody, { className: "mfui-tbody", children: _jsx(TableViewPort, { className: "mfui-tbody-viewport", ref: targetElm, children: _jsx(TableListElement, { className: "mfui-tbody-list", ref: listElm, children: (_a = data === null || data === void 0 ? void 0 : data.map) === null || _a === void 0 ? void 0 : _a.call(data, (row) => (_jsx(TableRow, { rowData: row, loading: !!keyField ? loadingRowIds === null || loadingRowIds === void 0 ? void 0 : loadingRowIds.includes(row[keyField]) : false }, keyField ? row[keyField] : row.__key))) }) }) }));
9
9
  };
10
10
  export default StaticRows;
@@ -9,14 +9,14 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
14
14
  import { useOverlayScrollbars } from "overlayscrollbars-react";
15
15
  import { StyledTable } from "./TableComponents";
16
16
  import TableHeader from "./TableHeader";
17
17
  import TableProvider from "./TableProvider";
18
18
  import shortUUID from "short-uuid";
19
- import VirtualizedRows from "./VirtualIzedRows";
19
+ import VirtualizedRows from "./VirtualizedRows";
20
20
  import StaticRows from "./StaticRows";
21
21
  import TableMenu from "./TableMenu";
22
22
  import useTable from "./useTable";
@@ -37,7 +37,7 @@ const TableContent = ({ children, }) => {
37
37
  height: tableHeight || "100%",
38
38
  maxHeight: tableMaxHeight,
39
39
  minHeight: tableMinHeight,
40
- }, ref: tableElement, "data-compact": compactState, children: [_jsx(LoadingIndicator, { visible: loading }), _jsx(TableHeader, { headerRowElm: headerRowElm }), visibleColumnCount === 0 && _jsx(_Fragment, {}), virtualized === true ? (_jsx(VirtualizedRows, { tableDimensions: tableDimensions, targetElm: targetElm, listElm: listElm, rowHeight: rowHeight, headerRowHeight: headerRowHeight })) : (_jsx(StaticRows, { targetElm: targetElm, listElm: listElm }))] })] }));
40
+ }, ref: tableElement, "data-compact": compactState, children: [_jsx(LoadingIndicator, { visible: loading }), _jsx(TableHeader, { headerRowElm: headerRowElm }), visibleColumnCount === 0 && _jsx("div", { children: "No columns visible" }), virtualized === true ? (_jsx(VirtualizedRows, { tableDimensions: tableDimensions, targetElm: targetElm, listElm: listElm, rowHeight: rowHeight, headerRowHeight: headerRowHeight })) : (_jsx(StaticRows, { targetElm: targetElm, listElm: listElm }))] })] }));
41
41
  };
42
42
  export const Table = (_a) => {
43
43
  var { data, columnProps, children } = _a, props = __rest(_a, ["data", "columnProps", "children"]) // pass through props straight to table context
@@ -109,6 +109,22 @@ export const Table = (_a) => {
109
109
  resizeObserver.unobserve(element);
110
110
  };
111
111
  }, []);
112
- const __data = useMemo(() => data === null || data === void 0 ? void 0 : data.map((d, i) => (Object.assign(Object.assign({}, d), { __key: shortUUID.generate(), __index: i }))), [data]);
112
+ // Persistent cache mapping each row object to a stable UUID.
113
+ // Uses a WeakMap so entries are automatically garbage collected
114
+ // when their corresponding row objects are no longer referenced.
115
+ const uuidCache = useRef(new WeakMap());
116
+ // Augment each row with a stable __key (UUID) and __index.
117
+ // The WeakMap ensures that the same row object always receives
118
+ // the same UUID across re-renders, preventing unnecessary DOM
119
+ // reconciliation. useMemo preserves referential stability of
120
+ // the output array when the data reference hasn't changed.
121
+ const __data = useMemo(() => data === null || data === void 0 ? void 0 : data.map((d, i) => {
122
+ let key = uuidCache.current.get(d);
123
+ if (!key) {
124
+ key = shortUUID.uuid();
125
+ uuidCache.current.set(d, key);
126
+ }
127
+ return Object.assign(Object.assign({}, d), { __key: key, __index: i });
128
+ }), [data]);
113
129
  return (_jsx(TableProvider, Object.assign({ columns: columnProps, data: __data, tableElement: tableElement, headerRowElm: headerRowElm, tableDimensions: tableDimensions, targetElm: targetElm, listElm: listElm }, props, { children: _jsx(TableContent, { children: children }) })));
114
130
  };
@@ -29,7 +29,7 @@ const FlexedRow = styled.div `
29
29
  }
30
30
  `;
31
31
  const TableMenu = () => {
32
- var _a, _b, _c, _d;
32
+ var _a, _b, _c, _d, _e;
33
33
  const { data, columnState, searchState, toggleColumnVisibility, tableMenuOptions, runSearch, enableSelection, compactState, toggleCompact, totalRecords, getCalculatedSelectionTotal, filterState, handleFilterChange, clearSearch, } = useTable();
34
34
  const inputRef = useRef(null);
35
35
  if ((tableMenuOptions === null || tableMenuOptions === void 0 ? void 0 : tableMenuOptions.enabled) !== true)
@@ -38,7 +38,7 @@ const TableMenu = () => {
38
38
  const queryFilter = useQueryFilter({
39
39
  defaultFilter: filterState,
40
40
  filterDefinitions: (filterOptions === null || filterOptions === void 0 ? void 0 : filterOptions.filterDefinitions) || [],
41
- showCombinator: true,
41
+ showCombinator: (_a = filterOptions === null || filterOptions === void 0 ? void 0 : filterOptions.showCombinator) !== null && _a !== void 0 ? _a : true,
42
42
  onFilterChange: (q) => {
43
43
  var _a;
44
44
  handleFilterChange(q);
@@ -81,13 +81,13 @@ 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
- (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: ((_a = tableMenuOptions === null || tableMenuOptions === void 0 ? void 0 : tableMenuOptions.addButtonOptions) === null || _a === void 0 ? void 0 : _a.label) || "+ Add Record" }))), (addButtonOptions === null || addButtonOptions === void 0 ? void 0 : addButtonOptions.enabled) === true &&
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: {
88
88
  color: "primary",
89
89
  size: "xxs",
90
- } }, addButtonOptions === null || addButtonOptions === void 0 ? void 0 : addButtonOptions.menuOptions, { children: ((_b = tableMenuOptions === null || tableMenuOptions === void 0 ? void 0 : tableMenuOptions.addButtonOptions) === null || _b === void 0 ? void 0 : _b.label) || "Options" }))), (filterOptions === null || filterOptions === void 0 ? void 0 : filterOptions.enabled) === true && (_jsx(DropDownMenu, { variant: "outlined", size: "xs", data: ((_c = filterOptions === null || filterOptions === void 0 ? void 0 : filterOptions.filterDefinitions) === null || _c === void 0 ? void 0 : _c.map((filter) => ({
90
+ } }, addButtonOptions === null || addButtonOptions === void 0 ? void 0 : addButtonOptions.menuOptions, { children: ((_c = tableMenuOptions === null || tableMenuOptions === void 0 ? void 0 : tableMenuOptions.addButtonOptions) === null || _c === void 0 ? void 0 : _c.label) || "Options" }))), (filterOptions === null || filterOptions === void 0 ? void 0 : filterOptions.enabled) === true && (_jsx(DropDownMenu, { variant: "outlined", size: "xs", data: ((_d = filterOptions === null || filterOptions === void 0 ? void 0 : filterOptions.filterDefinitions) === null || _d === void 0 ? void 0 : _d.map((filter) => ({
91
91
  label: filter.label,
92
92
  value: filter.dataField,
93
93
  data: filter,
@@ -131,6 +131,6 @@ const TableMenu = () => {
131
131
  style: { padding: "0px 4px", height: 24 },
132
132
  }, dropDownProps: {
133
133
  style: { width: 175, maxWidth: 400 },
134
- }, children: _jsx(Columns3Icon, { size: 14 }) })), (searchOptions === null || searchOptions === void 0 ? void 0 : searchOptions.enabled) === true && (_jsx(TextInput, { ref: inputRef, size: "xs", placeholder: ((_d = tableMenuOptions === null || tableMenuOptions === void 0 ? void 0 : tableMenuOptions.searchOptions) === null || _d === void 0 ? void 0 : _d.placeholder) || "Search", defaultValue: searchState, onChange: handleSearch }))] })] }), _jsx(QueryFilter, { queryFilter: queryFilter })] }));
134
+ }, children: _jsx(Columns3Icon, { size: 14 }) })), (searchOptions === null || searchOptions === void 0 ? void 0 : searchOptions.enabled) === true && (_jsx(TextInput, { ref: inputRef, size: "xs", placeholder: ((_e = tableMenuOptions === null || tableMenuOptions === void 0 ? void 0 : tableMenuOptions.searchOptions) === null || _e === void 0 ? void 0 : _e.placeholder) || "Search", defaultValue: searchState, onChange: handleSearch }))] })] }), _jsx(QueryFilter, { queryFilter: queryFilter })] }));
135
135
  };
136
136
  export default TableMenu;