@monolith-forensics/monolith-ui 1.3.91 → 1.3.94

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.
@@ -7,7 +7,7 @@ interface InfoComponentProps {
7
7
  label?: string | ReactNode;
8
8
  }
9
9
  export declare const InfoComponent: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<InfoComponentProps, never>> & string & Omit<({ className, children, description, label }: InfoComponentProps) => string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined, keyof import("react").Component<any, {}, any>>;
10
- interface FieldLabelProps {
10
+ export interface FieldLabelProps {
11
11
  className?: string;
12
12
  children?: ReactNode;
13
13
  error?: string;
@@ -15,6 +15,7 @@ interface FieldLabelProps {
15
15
  size?: Size;
16
16
  asterisk?: boolean;
17
17
  style?: React.CSSProperties;
18
+ actionComponent?: ReactNode;
18
19
  }
19
- declare const FieldLabel: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<FieldLabelProps, never>> & string & Omit<({ className, children, error, description, size, style, }: FieldLabelProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
20
+ declare const FieldLabel: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<FieldLabelProps, never>> & string & Omit<({ className, children, error, description, size, style, actionComponent, }: FieldLabelProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
20
21
  export default FieldLabel;
@@ -24,22 +24,38 @@ export const InfoComponent = styled(({ className, children, description, label }
24
24
  margin-bottom: 5px;
25
25
  }
26
26
  `;
27
- const FieldLabel = styled(({ className, children, error, description, size = "sm", style, }) => {
28
- return (_jsxs("div", { className: className + " FieldLabel", style: style, children: [_jsx(InfoComponent, { description: description, label: children, children: _jsx("div", { className: "label", children: children }) }), error && (_jsx("div", { className: "error", title: error, children: error || "Invalid Value" }))] }));
27
+ const FieldLabel = styled(({ className, children, error, description, size = "sm", style, actionComponent, }) => {
28
+ return (_jsxs("div", { className: className + " FieldLabel", style: style, children: [_jsxs("div", { className: "label-content", children: [_jsx(InfoComponent, { description: description, label: children, children: _jsx("div", { className: "label", children: children }) }), error && (_jsx("div", { className: "error", title: error, children: error || "Invalid Value" }))] }), actionComponent && (_jsx("div", { className: "action-section", children: actionComponent }))] }));
29
29
  }) `
30
30
  user-select: none;
31
- font-family: apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
32
- "Helvetica Neue", Arial, sans-serif;
31
+ font-family:
32
+ apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
33
+ Arial, sans-serif;
33
34
  user-select: none;
34
35
  display: flex;
35
36
  flex-direction: row;
36
- align-items: baseline;
37
- gap: 5px;
37
+ align-items: flex-start;
38
+ justify-content: space-between;
39
+ width: 100%;
38
40
 
39
41
  min-height: 15px;
40
42
  font-weight: 400;
41
43
  margin-bottom: 2.5px;
42
44
 
45
+ .label-content {
46
+ display: flex;
47
+ flex-direction: row;
48
+ align-items: baseline;
49
+ gap: 5px;
50
+ flex: 1;
51
+ }
52
+
53
+ .action-section {
54
+ display: flex;
55
+ align-items: center;
56
+ margin-left: 8px;
57
+ }
58
+
43
59
  font-size: ${({ size = "sm" }) => size === "xs"
44
60
  ? "10px"
45
61
  : size === "sm"
@@ -1 +1,2 @@
1
1
  export { default } from "./FieldLabel";
2
+ export type { FieldLabelProps } from "./FieldLabel";
@@ -0,0 +1,25 @@
1
+ export interface SearchableTextAreaProps {
2
+ label?: string;
3
+ data?: Array<{
4
+ label: string;
5
+ value: string;
6
+ }>;
7
+ searchable?: boolean;
8
+ allowCustomValue?: boolean;
9
+ required?: boolean;
10
+ error?: string;
11
+ description?: string;
12
+ value?: string;
13
+ onChange?: (value: string) => void;
14
+ selectProps?: Record<string, any>;
15
+ textAreaPlaceholder?: string;
16
+ textAreaMinRows?: number;
17
+ textAreaMaxRows?: number;
18
+ textAreaProps?: Record<string, any>;
19
+ initialValue?: string;
20
+ }
21
+ declare function SearchableTextArea({ label, data, searchable, allowCustomValue, required, error, description, selectProps, value, onChange, textAreaPlaceholder, textAreaMinRows, textAreaMaxRows, textAreaProps, initialValue, }: SearchableTextAreaProps): import("react/jsx-runtime").JSX.Element;
22
+ declare namespace SearchableTextArea {
23
+ var displayName: string;
24
+ }
25
+ export default SearchableTextArea;
@@ -0,0 +1,181 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useRef } from "react";
3
+ import styled from "styled-components";
4
+ import { MoreHorizontal } from "lucide-react";
5
+ import { SelectBox } from "../SelectBox";
6
+ import FieldLabel from "../FieldLabel";
7
+ import DropDownMenu from "../DropDownMenu";
8
+ // Wrapper components for layout
9
+ const CombinedInputWrapper = styled.div `
10
+ display: flex;
11
+ flex-direction: column;
12
+ width: 100%;
13
+ position: relative;
14
+ `;
15
+ const TextAreaRow = styled.div `
16
+ position: relative;
17
+ display: flex;
18
+ align-items: flex-start;
19
+ width: 100%;
20
+ z-index: 1; /* Lower than SelectBoxWrapper */
21
+ `;
22
+ const SelectBoxWrapper = styled.div `
23
+ position: absolute;
24
+ width: 100%;
25
+ top: 0; /* Position at the top of the textarea */
26
+ left: 0;
27
+ z-index: 10; /* Ensure dropdown appears above textarea */
28
+ `;
29
+ const StyledSelectBox = styled(SelectBox) `
30
+ /* Completely hide the SelectBox and disable all interactions */
31
+ position: relative;
32
+ width: 100%;
33
+ opacity: 0;
34
+ pointer-events: none; /* Disable all interactions */
35
+ height: 0;
36
+ overflow: hidden;
37
+
38
+ /* Hide all child elements */
39
+ * {
40
+ opacity: 0;
41
+ pointer-events: none;
42
+ height: 0;
43
+ overflow: hidden;
44
+ }
45
+
46
+ /* Only allow dropdown portal to be visible and interactive when opened programmatically */
47
+ [data-floating-ui-portal] {
48
+ opacity: 1 !important;
49
+ pointer-events: auto !important;
50
+ z-index: 1000 !important;
51
+
52
+ * {
53
+ opacity: 1 !important;
54
+ pointer-events: auto !important;
55
+ height: auto !important;
56
+ overflow: visible !important;
57
+ }
58
+ }
59
+ `;
60
+ const StyledFieldLabel = styled(FieldLabel) `
61
+ .action-section {
62
+ margin-left: 2px !important; /* Reduce spacing from default 8px */
63
+ }
64
+
65
+ .label-content {
66
+ gap: 2px !important; /* Reduce gap from default 5px */
67
+ }
68
+ `;
69
+ // Styled TextArea that is now the primary input
70
+ const StyledTextArea = styled.textarea `
71
+ border: 1px solid
72
+ ${({ theme, $hasError }) => $hasError ? theme.palette.error.main : theme.palette.input.border};
73
+ border-radius: 4px;
74
+ padding: 10px;
75
+ font-family: ${({ theme }) => theme.typography.fontFamily};
76
+ font-size: 13px;
77
+ background-color: ${({ theme }) => theme.palette.input.background};
78
+ color: ${({ theme }) => theme.palette.text.primary};
79
+ resize: none;
80
+ outline: none;
81
+ transition: border-color 0.2s ease;
82
+ width: 100%;
83
+ min-height: ${({ $minRows = 3 }) => $minRows * 1.5 + 1.5}em;
84
+ ${({ $maxRows }) => $maxRows && `max-height: ${$maxRows * 1.5 + 1.5}em;`}
85
+ pointer-events: auto;
86
+ user-select: text;
87
+ z-index: 2;
88
+ position: relative;
89
+
90
+ &:focus {
91
+ border-color: ${({ theme }) => theme.palette.primary.main};
92
+ z-index: 3;
93
+ }
94
+
95
+ &::placeholder {
96
+ color: ${({ theme }) => theme.palette.text.secondary};
97
+ opacity: 0.5;
98
+ }
99
+ `;
100
+ function SearchableTextArea({ label, data, searchable, allowCustomValue, required, error, description, selectProps = {}, value, onChange, textAreaPlaceholder, textAreaMinRows = 3, textAreaMaxRows, textAreaProps = {}, initialValue = "", }) {
101
+ // Use controlled value if provided, otherwise use internal state
102
+ const [internalValue, setInternalValue] = useState(initialValue);
103
+ const [selectValue, setSelectValue] = useState(null);
104
+ const [selectKey, setSelectKey] = useState(0); // Force rerender key
105
+ // Ref to control the SelectBox dropdown
106
+ const selectBoxRef = useRef(null);
107
+ const textAreaValue = value !== undefined ? value : internalValue;
108
+ // Handle SelectBox selection - overrides textarea content then clears selectbox
109
+ const handleSelectChange = (newValue) => {
110
+ if (newValue) {
111
+ // Override textarea content with selected value
112
+ setInternalValue(newValue);
113
+ // Also call onChange if provided (for form integration)
114
+ if (onChange) {
115
+ onChange(newValue);
116
+ }
117
+ setTimeout(() => {
118
+ setSelectValue(null);
119
+ setSelectKey((prev) => prev + 1);
120
+ }, 100);
121
+ }
122
+ else {
123
+ setSelectValue(newValue);
124
+ }
125
+ };
126
+ // Handle textarea changes
127
+ const handleTextAreaChange = (event) => {
128
+ const newValue = event.target.value;
129
+ // Always update internal state for display purposes
130
+ setInternalValue(newValue);
131
+ // Also call onChange if provided (for form integration)
132
+ if (onChange) {
133
+ onChange(newValue);
134
+ }
135
+ };
136
+ // Removed keyboard shortcuts - textarea behaves normally
137
+ const handleSearchClick = () => {
138
+ if (selectBoxRef.current) {
139
+ const selectInput = selectBoxRef.current.querySelector("input");
140
+ if (selectInput) {
141
+ // Temporarily enable interactions to trigger dropdown
142
+ selectInput.style.pointerEvents = "auto";
143
+ selectInput.style.opacity = "1";
144
+ selectInput.style.height = "auto";
145
+ selectInput.focus();
146
+ selectInput.click();
147
+ // Hide again immediately after triggering
148
+ setTimeout(() => {
149
+ selectInput.style.pointerEvents = "none";
150
+ selectInput.style.opacity = "0";
151
+ selectInput.style.height = "0";
152
+ }, 50);
153
+ }
154
+ }
155
+ };
156
+ // Used to create red border when zod validation detects errors
157
+ const hasError = Boolean(error);
158
+ return (_jsxs(CombinedInputWrapper, { children: [label && (_jsx(StyledFieldLabel, { asterisk: required, error: error, description: description, actionComponent: _jsx(DropDownMenu, { data: [
159
+ {
160
+ value: "search",
161
+ label: "Select Recent Entry",
162
+ visible: true,
163
+ },
164
+ ], variant: "text", size: "xs", arrow: false, onItemSelect: (item) => {
165
+ if (item.value === "search") {
166
+ handleSearchClick();
167
+ }
168
+ }, buttonProps: {
169
+ style: {
170
+ minWidth: "auto",
171
+ border: "none",
172
+ background: "transparent",
173
+ padding: "0",
174
+ margin: "0",
175
+ height: "16px",
176
+ width: "16px",
177
+ },
178
+ }, children: _jsx(MoreHorizontal, { size: 16 }) }), children: label })), _jsxs(TextAreaRow, { children: [_jsx(StyledTextArea, Object.assign({ placeholder: textAreaPlaceholder || "Enter details about the move", "$minRows": textAreaMinRows, "$maxRows": textAreaMaxRows, "$hasError": hasError, value: textAreaValue, onChange: handleTextAreaChange }, textAreaProps)), _jsx(SelectBoxWrapper, { ref: selectBoxRef, children: _jsx(StyledSelectBox, Object.assign({ data: data, searchable: searchable, allowCustomValue: allowCustomValue, arrow: false, value: selectValue || undefined, onChange: handleSelectChange, hasError: hasError }, selectProps), selectKey) })] })] }));
179
+ }
180
+ SearchableTextArea.displayName = "SearchableTextArea";
181
+ export default SearchableTextArea;
@@ -0,0 +1,2 @@
1
+ export { default } from "./SearchableTextArea";
2
+ export type { SearchableTextAreaProps } from "./SearchableTextArea";
@@ -0,0 +1 @@
1
+ export { default } from "./SearchableTextArea";
@@ -33,7 +33,7 @@ const TableMenu = () => {
33
33
  const inputRef = useRef(null);
34
34
  if ((tableMenuOptions === null || tableMenuOptions === void 0 ? void 0 : tableMenuOptions.enabled) !== true)
35
35
  return null;
36
- const { addButtonOptions, filterOptions, tableCountOptions, exportOptions, compactOptions, columnSelectorOptions, actionOptions, searchOptions, children, } = tableMenuOptions;
36
+ const { addButtonOptions, filterOptions, tableCountOptions, exportOptions, compactOptions, columnSelectorOptions, searchOptions, children, } = tableMenuOptions;
37
37
  const queryFilter = useQueryFilter({
38
38
  defaultFilter: filterState,
39
39
  filterDefinitions: (filterOptions === null || filterOptions === void 0 ? void 0 : filterOptions.filterDefinitions) || [],
@@ -84,7 +84,7 @@ const TableMenu = () => {
84
84
  }, onItemSelect: handleSelectFilter, dropDownProps: {
85
85
  style: { width: 175, maxWidth: 400 },
86
86
  }, searchable: true, children: "Filter" })), (tableCountOptions === null || tableCountOptions === void 0 ? void 0 : tableCountOptions.recordsTotalEnabled) === true && (_jsx(InfoBadge, { total: totalRecords || data.length })), enableSelection === true &&
87
- (tableCountOptions === null || tableCountOptions === void 0 ? void 0 : tableCountOptions.selectionTotalEnabled) === true && (_jsx(InfoBadge, { total: getCalculatedSelectionTotal(), hint: "Selected Items", icon: CheckSquareIcon })), children] }), _jsxs(FlexedRow, { children: [(actionOptions === null || actionOptions === void 0 ? void 0 : actionOptions.enabled) === true && actionOptions.menu, (exportOptions === null || exportOptions === void 0 ? void 0 : exportOptions.enabled) === true && (_jsx(DropDownMenu, { variant: "outlined", size: "xs", data: [
87
+ (tableCountOptions === null || tableCountOptions === void 0 ? void 0 : tableCountOptions.selectionTotalEnabled) === true && (_jsx(InfoBadge, { total: getCalculatedSelectionTotal(), hint: "Selected Items", icon: CheckSquareIcon })), children] }), _jsxs(FlexedRow, { children: [(exportOptions === null || exportOptions === void 0 ? void 0 : exportOptions.enabled) === true && (_jsx(DropDownMenu, { variant: "outlined", size: "xs", data: [
88
88
  {
89
89
  label: "Export Visible Columns",
90
90
  value: TableExportOptions.ExportVisible,
@@ -227,10 +227,6 @@ export type TableMenuOptions = {
227
227
  recordsTotalEnabled?: boolean;
228
228
  selectionTotalEnabled?: boolean;
229
229
  };
230
- actionOptions?: {
231
- enabled?: boolean;
232
- menu?: React.ReactNode;
233
- };
234
230
  searchOptions?: {
235
231
  enabled?: boolean;
236
232
  placeholder?: string;
package/dist/index.d.ts CHANGED
@@ -14,6 +14,8 @@ export type { DropDownItem } from "./DropDownMenu";
14
14
  export { default as DateInput } from "./DateInput";
15
15
  export { default as TextArea } from "./TextArea";
16
16
  export { default as TextAreaInput } from "./TextAreaInput";
17
+ export { default as SearchableTextArea } from "./SearchableTextArea";
18
+ export type { SearchableTextAreaProps } from "./SearchableTextArea";
17
19
  export { default as TagBox } from "./TagBox";
18
20
  export type { TagBoxProps, TagboxOption } from "./TagBox";
19
21
  export { default as FieldLabel } from "./FieldLabel";
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ export { default as DropDownMenu } from "./DropDownMenu";
8
8
  export { default as DateInput } from "./DateInput";
9
9
  export { default as TextArea } from "./TextArea";
10
10
  export { default as TextAreaInput } from "./TextAreaInput";
11
+ export { default as SearchableTextArea } from "./SearchableTextArea";
11
12
  export { default as TagBox } from "./TagBox";
12
13
  export { default as FieldLabel } from "./FieldLabel";
13
14
  export { default as Modal } from "./Modal";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monolith-forensics/monolith-ui",
3
- "version": "1.3.91",
3
+ "version": "1.3.94",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Matt Danner (Monolith Forensics LLC)",