@monolith-forensics/monolith-ui 1.3.95 → 1.3.96

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.
@@ -5,26 +5,23 @@ export interface SelectableTextAreaProps {
5
5
  label: string;
6
6
  value: string;
7
7
  }>;
8
- searchable?: boolean;
9
- allowCustomValue?: boolean;
10
8
  required?: boolean;
11
9
  error?: string;
12
10
  description?: string;
13
11
  value?: string;
14
12
  onChange?: (value: string) => void;
15
13
  selectProps?: Record<string, any>;
16
- textAreaPlaceholder?: string;
17
- textAreaMinRows?: number;
18
- textAreaMaxRows?: number;
14
+ placeholder?: string;
19
15
  textAreaProps?: Record<string, any>;
20
16
  initialValue?: string;
17
+ showActionMenu?: boolean;
21
18
  actionMenuData?: Array<{
22
19
  label: string;
23
20
  value: string;
24
21
  }>;
25
22
  onActionMenuSelect?: (item: DropDownItem) => void;
26
23
  }
27
- declare function SelectableTextArea({ label, data, searchable, allowCustomValue, required, error, description, selectProps, value, onChange, textAreaPlaceholder, textAreaMinRows, textAreaMaxRows, textAreaProps, initialValue, actionMenuData, onActionMenuSelect, }: SelectableTextAreaProps): import("react/jsx-runtime").JSX.Element;
24
+ declare function SelectableTextArea({ label, data, required, error, description, selectProps, value, onChange, placeholder, textAreaProps, initialValue, showActionMenu, actionMenuData, onActionMenuSelect, }: SelectableTextAreaProps): import("react/jsx-runtime").JSX.Element;
28
25
  declare namespace SelectableTextArea {
29
26
  var displayName: string;
30
27
  }
@@ -57,19 +57,10 @@ const StyledSelectBox = styled(SelectBox) `
57
57
  }
58
58
  }
59
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
60
  // Styled TextArea that is now the primary input
70
61
  const StyledTextArea = styled.textarea `
71
62
  border: 1px solid
72
- ${({ theme, $hasError }) => $hasError ? theme.palette.error.main : theme.palette.input.border};
63
+ ${({ theme, hasError }) => hasError ? theme.palette.error.main : theme.palette.input.border};
73
64
  border-radius: 4px;
74
65
  padding: 10px;
75
66
  font-family: ${({ theme }) => theme.typography.fontFamily};
@@ -80,8 +71,6 @@ const StyledTextArea = styled.textarea `
80
71
  outline: none;
81
72
  transition: border-color 0.2s ease;
82
73
  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
74
  pointer-events: auto;
86
75
  user-select: text;
87
76
  z-index: 2;
@@ -97,7 +86,7 @@ const StyledTextArea = styled.textarea `
97
86
  opacity: 0.5;
98
87
  }
99
88
  `;
100
- function SelectableTextArea({ label, data, searchable, allowCustomValue, required, error, description, selectProps = {}, value, onChange, textAreaPlaceholder, textAreaMinRows = 3, textAreaMaxRows, textAreaProps = {}, initialValue = "", actionMenuData, onActionMenuSelect, }) {
89
+ function SelectableTextArea({ label, data, required, error, description, selectProps = {}, value, onChange, placeholder, textAreaProps = {}, initialValue = "", showActionMenu = false, actionMenuData, onActionMenuSelect, }) {
101
90
  // Use controlled value if provided, otherwise use internal state
102
91
  const [internalValue, setInternalValue] = useState(initialValue);
103
92
  const [selectValue, setSelectValue] = useState(null);
@@ -175,7 +164,7 @@ function SelectableTextArea({ label, data, searchable, allowCustomValue, require
175
164
  }
176
165
  }
177
166
  };
178
- return (_jsxs(CombinedInputWrapper, { children: [label && (_jsx(StyledFieldLabel, { asterisk: required, error: error, description: description, actionComponent: _jsx(DropDownMenu, { data: menuData, variant: "text", size: "xs", arrow: false, onItemSelect: handleActionMenuSelect, buttonProps: {
167
+ return (_jsxs(CombinedInputWrapper, { children: [label && (_jsx(FieldLabel, { asterisk: required, error: error, description: description, actionComponent: showActionMenu ? (_jsx(DropDownMenu, { data: menuData, variant: "text", size: "xs", arrow: false, onItemSelect: handleActionMenuSelect, buttonProps: {
179
168
  style: {
180
169
  minWidth: "auto",
181
170
  border: "none",
@@ -185,7 +174,7 @@ function SelectableTextArea({ label, data, searchable, allowCustomValue, require
185
174
  height: "16px",
186
175
  width: "16px",
187
176
  },
188
- }, 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) })] })] }));
177
+ }, children: _jsx(MoreHorizontal, { size: 16 }) })) : null, children: label })), _jsxs(TextAreaRow, { children: [_jsx(StyledTextArea, Object.assign({ placeholder: placeholder || "Enter details about the move", hasError: hasError, value: textAreaValue, onChange: handleTextAreaChange }, textAreaProps)), _jsx(SelectBoxWrapper, { ref: selectBoxRef, children: _jsx(StyledSelectBox, Object.assign({ data: data, arrow: false, value: selectValue || undefined, onChange: handleSelectChange, hasError: hasError }, selectProps), selectKey) })] })] }));
189
178
  }
190
179
  SelectableTextArea.displayName = "SelectableTextArea";
191
180
  export default SelectableTextArea;
@@ -1,5 +1,6 @@
1
1
  import { Size } from "../core";
2
- interface TextAreaInputProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
2
+ import { DropDownItem } from "..";
3
+ interface TextAreaInputProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange"> {
3
4
  variant?: "contained" | "filled" | "outlined" | "text";
4
5
  label?: string;
5
6
  error?: string;
@@ -13,6 +14,17 @@ interface TextAreaInputProps extends React.TextareaHTMLAttributes<HTMLTextAreaEl
13
14
  rowHeight: number;
14
15
  }) => void;
15
16
  cacheMeasurements?: boolean;
17
+ showActionMenu?: boolean;
18
+ actionMenuOptions?: Array<{
19
+ label: string;
20
+ value: string;
21
+ }>;
22
+ onActionMenuSelect?: (item: DropDownItem) => void;
23
+ onChange?: (value: string) => void;
24
+ data?: Array<{
25
+ label: string;
26
+ value: string;
27
+ }>;
16
28
  }
17
29
  declare const TextAreaInput: import("react").ForwardRefExoticComponent<TextAreaInputProps & import("react").RefAttributes<HTMLTextAreaElement>>;
18
30
  export default TextAreaInput;
@@ -10,13 +10,138 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { TextArea, FieldLabel } from "..";
14
- import { forwardRef } from "react";
13
+ import styled from "styled-components";
14
+ import { TextArea, FieldLabel, DropDownMenu, SelectBox, } from "..";
15
+ import { forwardRef, useRef, useState } from "react";
16
+ import { MoreHorizontal } from "lucide-react";
17
+ const TextAreaRow = styled.div `
18
+ position: relative;
19
+ display: flex;
20
+ align-items: flex-start;
21
+ width: 100%;
22
+ z-index: 1; /* Lower than SelectBoxWrapper */
23
+ `;
24
+ const SelectBoxWrapper = styled.div `
25
+ position: absolute;
26
+ width: 100%;
27
+ top: 0; /* Position at the top of the textarea */
28
+ left: 0;
29
+ z-index: 10; /* Ensure dropdown appears above textarea */
30
+ `;
31
+ const StyledSelectBox = styled(SelectBox) `
32
+ /* Completely hide the SelectBox and disable all interactions */
33
+ position: relative;
34
+ width: 100%;
35
+ opacity: 0;
36
+ pointer-events: none; /* Disable all interactions */
37
+ height: 0;
38
+ overflow: hidden;
39
+
40
+ /* Hide all child elements */
41
+ * {
42
+ opacity: 0;
43
+ pointer-events: none;
44
+ height: 0;
45
+ overflow: hidden;
46
+ }
47
+
48
+ /* Only allow dropdown portal to be visible and interactive when opened programmatically */
49
+ [data-floating-ui-portal] {
50
+ opacity: 1 !important;
51
+ pointer-events: auto !important;
52
+ z-index: 1000 !important;
53
+
54
+ * {
55
+ opacity: 1 !important;
56
+ pointer-events: auto !important;
57
+ height: auto !important;
58
+ overflow: visible !important;
59
+ }
60
+ }
61
+ `;
15
62
  const TextAreaInput = forwardRef((_a, ref) => {
16
- var { label, error, required, colSpan = 1, size = "sm", description, maxRows = 6, minRows = 3, onHeightChange, cacheMeasurements } = _a, rest = __rest(_a, ["label", "error", "required", "colSpan", "size", "description", "maxRows", "minRows", "onHeightChange", "cacheMeasurements"]);
63
+ var { label, error, required, colSpan = 1, size = "sm", description, maxRows = 6, minRows = 3, onHeightChange, cacheMeasurements, defaultValue, showActionMenu = false, actionMenuOptions = [
64
+ {
65
+ value: "recent",
66
+ label: "Select Recent Entry",
67
+ },
68
+ ], onActionMenuSelect, data, onChange } = _a, rest = __rest(_a, ["label", "error", "required", "colSpan", "size", "description", "maxRows", "minRows", "onHeightChange", "cacheMeasurements", "defaultValue", "showActionMenu", "actionMenuOptions", "onActionMenuSelect", "data", "onChange"]);
69
+ const [internalValue, setInternalValue] = useState(defaultValue);
70
+ const [selectValue, setSelectValue] = useState(null);
71
+ const [selectKey, setSelectKey] = useState(0); // Force rerender key
72
+ const hiddenSelectBoxRef = useRef(null);
73
+ // Handle menu item selection with custom callback or default behavior
74
+ const handleActionMenuSelect = (item) => {
75
+ if (onActionMenuSelect) {
76
+ onActionMenuSelect(item);
77
+ }
78
+ else {
79
+ // Default behavior: if item value is "recent", trigger handleMenuClick
80
+ if (item.value === "recent") {
81
+ handleMenuClick();
82
+ }
83
+ }
84
+ };
85
+ const handleMenuClick = () => {
86
+ if (hiddenSelectBoxRef.current) {
87
+ const selectInput = hiddenSelectBoxRef.current.querySelector("input");
88
+ if (selectInput) {
89
+ // Temporarily enable interactions to trigger dropdown
90
+ selectInput.style.pointerEvents = "auto";
91
+ selectInput.style.opacity = "1";
92
+ selectInput.style.height = "auto";
93
+ selectInput.focus();
94
+ selectInput.click();
95
+ // Hide again immediately after triggering
96
+ setTimeout(() => {
97
+ selectInput.style.pointerEvents = "none";
98
+ selectInput.style.opacity = "0";
99
+ selectInput.style.height = "0";
100
+ }, 50);
101
+ }
102
+ }
103
+ };
104
+ // Handle SelectBox selection - overrides textarea content then clears selectbox
105
+ const handleSelectChange = (newValue) => {
106
+ if (newValue) {
107
+ // Override textarea content with selected value
108
+ setInternalValue(newValue);
109
+ // Also call onChange if provided (for form integration)
110
+ if (onChange) {
111
+ onChange(newValue);
112
+ }
113
+ setTimeout(() => {
114
+ setSelectValue(null);
115
+ setSelectKey((prev) => prev + 1);
116
+ }, 100);
117
+ }
118
+ else {
119
+ setSelectValue(newValue);
120
+ }
121
+ };
122
+ // Handle textarea changes
123
+ const handleTextAreaChange = (event) => {
124
+ const newValue = event.target.value;
125
+ // Always update internal state for display purposes
126
+ setInternalValue(newValue);
127
+ // Also call onChange if provided (for form integration)
128
+ if (onChange) {
129
+ onChange(newValue);
130
+ }
131
+ };
17
132
  return (_jsxs("div", { style: {
18
133
  gridColumn: `span ${colSpan}`,
19
134
  height: "fit-content",
20
- }, children: [label && (_jsx(FieldLabel, { error: error, asterisk: required, size: size, description: description, children: label })), _jsx(TextArea, Object.assign({ ref: ref, size: size, maxRows: maxRows, minRows: minRows, onHeightChange: onHeightChange, cacheMeasurements: cacheMeasurements }, rest))] }));
135
+ }, children: [label && (_jsx(FieldLabel, { asterisk: required, error: error, description: description, size: size, actionComponent: showActionMenu ? (_jsx(DropDownMenu, { data: actionMenuOptions, variant: "text", size: "xs", arrow: false, onItemSelect: handleActionMenuSelect, buttonProps: {
136
+ style: {
137
+ minWidth: "auto",
138
+ border: "none",
139
+ background: "transparent",
140
+ padding: "0",
141
+ margin: "0",
142
+ height: "16px",
143
+ width: "16px",
144
+ },
145
+ }, children: _jsx(MoreHorizontal, { size: 16 }) })) : null, children: label })), _jsxs(TextAreaRow, { children: [_jsx(TextArea, Object.assign({ ref: ref, size: size, maxRows: maxRows, minRows: minRows, onHeightChange: onHeightChange, cacheMeasurements: cacheMeasurements, value: internalValue, onChange: handleTextAreaChange }, rest)), _jsx(SelectBoxWrapper, { ref: hiddenSelectBoxRef, children: _jsx(StyledSelectBox, { data: data, arrow: false, value: selectValue || undefined, onChange: handleSelectChange, hasError: !!error }, selectKey) })] })] }));
21
146
  });
22
147
  export default TextAreaInput;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monolith-forensics/monolith-ui",
3
- "version": "1.3.95",
3
+ "version": "1.3.96",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Matt Danner (Monolith Forensics LLC)",