@monolith-forensics/monolith-ui 1.3.113 → 1.4.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.
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Size } from "../core";
|
|
3
3
|
import { DropDownItem } from "..";
|
|
4
|
+
import { DropDownMenuProps } from "../DropDownMenu/types";
|
|
4
5
|
export type InsertableItem = {
|
|
5
6
|
label: string;
|
|
6
7
|
value: string;
|
|
8
|
+
group?: string;
|
|
7
9
|
};
|
|
8
10
|
export interface TextAreaInputProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
9
11
|
variant?: "contained" | "filled" | "outlined" | "text";
|
|
@@ -20,13 +22,28 @@ export interface TextAreaInputProps extends React.TextareaHTMLAttributes<HTMLTex
|
|
|
20
22
|
rowHeight: number;
|
|
21
23
|
}) => void;
|
|
22
24
|
showActionMenu?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Visual style of the action menu trigger.
|
|
27
|
+
* - `"ellipsis"` renders a minimal `...` icon button (default).
|
|
28
|
+
* - `"dropdown"` renders an outlined button with a label and arrow, similar to the Table Filter menu.
|
|
29
|
+
*/
|
|
30
|
+
actionMenuVariant?: "ellipsis" | "dropdown";
|
|
23
31
|
actionMenuOptions?: Array<{
|
|
24
32
|
value: string;
|
|
25
33
|
label: string;
|
|
26
34
|
}>;
|
|
27
35
|
onActionMenuSelect?: (item: DropDownItem) => void;
|
|
36
|
+
/** Label displayed on the actions dropdown button. Only used when `actionMenuVariant` is `"dropdown"`. Defaults to "Actions". */
|
|
37
|
+
actionMenuLabel?: string;
|
|
38
|
+
/** Icon rendered in the left section of the actions dropdown button. Only used when `actionMenuVariant` is `"dropdown"`. Defaults to MoreHorizontal. */
|
|
39
|
+
actionMenuIcon?: React.ReactNode;
|
|
40
|
+
/** Whether the actions dropdown is searchable. Only used when `actionMenuVariant` is `"dropdown"`. Defaults to false. */
|
|
41
|
+
actionMenuSearchable?: boolean;
|
|
42
|
+
/** Additional props forwarded to the DropDownMenu component. Only used when `actionMenuVariant` is `"dropdown"`. */
|
|
43
|
+
actionMenuProps?: Partial<DropDownMenuProps>;
|
|
28
44
|
insertableItems?: InsertableItem[];
|
|
29
45
|
onInsertItem?: (item: InsertableItem) => void;
|
|
46
|
+
groupInsertableItems?: boolean;
|
|
30
47
|
}
|
|
31
48
|
declare const TextAreaInput: React.ForwardRefExoticComponent<TextAreaInputProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
32
49
|
export default TextAreaInput;
|
|
@@ -50,11 +50,11 @@ const TextAreaInput = forwardRef((props, ref) => {
|
|
|
50
50
|
// UI
|
|
51
51
|
label, error, required, colSpan = 1, size = "sm", description, maxRows = 6, minRows = 3, onHeightChange, cacheMeasurements,
|
|
52
52
|
// Action menu
|
|
53
|
-
showActionMenu = false, actionMenuOptions = DEFAULT_ACTIONS, onActionMenuSelect,
|
|
53
|
+
showActionMenu = false, actionMenuVariant = "ellipsis", actionMenuOptions = DEFAULT_ACTIONS, onActionMenuSelect, actionMenuLabel = "Actions", actionMenuIcon, actionMenuSearchable = false, actionMenuProps,
|
|
54
54
|
// Insertable items
|
|
55
|
-
insertableItems, onInsertItem } = props,
|
|
55
|
+
insertableItems, onInsertItem, groupInsertableItems } = props,
|
|
56
56
|
// Rest of props for TextArea
|
|
57
|
-
rest = __rest(props, ["label", "error", "required", "colSpan", "size", "description", "maxRows", "minRows", "onHeightChange", "cacheMeasurements", "showActionMenu", "actionMenuOptions", "onActionMenuSelect", "insertableItems", "onInsertItem"]);
|
|
57
|
+
rest = __rest(props, ["label", "error", "required", "colSpan", "size", "description", "maxRows", "minRows", "onHeightChange", "cacheMeasurements", "showActionMenu", "actionMenuVariant", "actionMenuOptions", "onActionMenuSelect", "actionMenuLabel", "actionMenuIcon", "actionMenuSearchable", "actionMenuProps", "insertableItems", "onInsertItem", "groupInsertableItems"]);
|
|
58
58
|
// State for insert menu visibility
|
|
59
59
|
const [showInsertMenu, setShowInsertMenu] = useState(false);
|
|
60
60
|
const [triggerSelectBoxOpen, setTriggerSelectBoxOpen] = useState(false);
|
|
@@ -75,10 +75,16 @@ const TextAreaInput = forwardRef((props, ref) => {
|
|
|
75
75
|
if (!showInsertMenu)
|
|
76
76
|
return;
|
|
77
77
|
const handleClickOutside = (event) => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
var _a, _b, _c;
|
|
79
|
+
const target = event.target;
|
|
80
|
+
// Ignore clicks inside the insert menu container
|
|
81
|
+
if ((_a = insertMenuRef.current) === null || _a === void 0 ? void 0 : _a.contains(target))
|
|
82
|
+
return;
|
|
83
|
+
// Ignore clicks inside the SelectBox floating portal dropdown
|
|
84
|
+
const floatingEl = (_c = (_b = target).closest) === null || _c === void 0 ? void 0 : _c.call(_b, ".mfFloating");
|
|
85
|
+
if (floatingEl)
|
|
86
|
+
return;
|
|
87
|
+
setShowInsertMenu(false);
|
|
82
88
|
};
|
|
83
89
|
document.addEventListener("mousedown", handleClickOutside);
|
|
84
90
|
return () => {
|
|
@@ -86,6 +92,7 @@ const TextAreaInput = forwardRef((props, ref) => {
|
|
|
86
92
|
};
|
|
87
93
|
}, [showInsertMenu]);
|
|
88
94
|
const handleActionSelect = (item) => {
|
|
95
|
+
var _a;
|
|
89
96
|
if (item.value === "insert" && (insertableItems === null || insertableItems === void 0 ? void 0 : insertableItems.length)) {
|
|
90
97
|
setShowInsertMenu(true);
|
|
91
98
|
// Trigger SelectBox to open using the new enhanced props
|
|
@@ -95,11 +102,10 @@ const TextAreaInput = forwardRef((props, ref) => {
|
|
|
95
102
|
// Built-in clear functionality
|
|
96
103
|
const textarea = textareaRef.current;
|
|
97
104
|
if (textarea) {
|
|
98
|
-
|
|
105
|
+
const nativeSet = (_a = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value")) === null || _a === void 0 ? void 0 : _a.set;
|
|
106
|
+
nativeSet === null || nativeSet === void 0 ? void 0 : nativeSet.call(textarea, "");
|
|
107
|
+
textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
99
108
|
textarea.focus();
|
|
100
|
-
// Trigger change event so controlled components update
|
|
101
|
-
const event = new Event("input", { bubbles: true });
|
|
102
|
-
textarea.dispatchEvent(event);
|
|
103
109
|
}
|
|
104
110
|
onActionMenuSelect === null || onActionMenuSelect === void 0 ? void 0 : onActionMenuSelect(item);
|
|
105
111
|
}
|
|
@@ -112,6 +118,7 @@ const TextAreaInput = forwardRef((props, ref) => {
|
|
|
112
118
|
setTriggerSelectBoxOpen(false);
|
|
113
119
|
};
|
|
114
120
|
const handleInsertSelect = (value, option) => {
|
|
121
|
+
var _a;
|
|
115
122
|
console.log("Selected value:", value, "Selected option:", option); // Debug log
|
|
116
123
|
// SelectBox passes (value, option) - we want the full option object
|
|
117
124
|
const item = option;
|
|
@@ -131,28 +138,40 @@ const TextAreaInput = forwardRef((props, ref) => {
|
|
|
131
138
|
const end = textarea.selectionEnd;
|
|
132
139
|
const currentValue = textarea.value;
|
|
133
140
|
const newValue = currentValue.slice(0, start) + item.value + currentValue.slice(end);
|
|
134
|
-
|
|
141
|
+
// Use the native setter so React's synthetic event system
|
|
142
|
+
// recognises the change on controlled inputs
|
|
143
|
+
const nativeSet = (_a = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value")) === null || _a === void 0 ? void 0 : _a.set;
|
|
144
|
+
nativeSet === null || nativeSet === void 0 ? void 0 : nativeSet.call(textarea, newValue);
|
|
145
|
+
// Dispatch as a bubbling event so React's onChange fires
|
|
146
|
+
textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
135
147
|
textarea.focus();
|
|
136
148
|
textarea.setSelectionRange(start + item.value.length, start + item.value.length);
|
|
137
|
-
// Trigger change event
|
|
138
|
-
const event = new Event("input", { bubbles: true });
|
|
139
|
-
textarea.dispatchEvent(event);
|
|
140
149
|
}
|
|
141
150
|
}
|
|
142
151
|
setShowInsertMenu(false);
|
|
143
152
|
};
|
|
144
|
-
return (_jsxs("div", { style: { gridColumn: `span ${colSpan}`, height: "fit-content" }, children: [label && (_jsx(FieldLabel, { asterisk: required, error: error, description: description, size: size, actionComponent: showActionMenu
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
return (_jsxs("div", { style: { gridColumn: `span ${colSpan}`, height: "fit-content" }, children: [label && (_jsx(FieldLabel, { asterisk: required, error: error, description: description, size: size, actionComponent: showActionMenu
|
|
154
|
+
? actionMenuVariant === "dropdown"
|
|
155
|
+
? (_jsx(DropDownMenu, Object.assign({ data: actionMenuOptions, variant: "outlined", size: "xs", arrow: true, searchable: actionMenuSearchable, onItemSelect: handleActionSelect, buttonProps: {
|
|
156
|
+
title: actionMenuLabel,
|
|
157
|
+
size: "xxs",
|
|
158
|
+
leftSection: actionMenuIcon,
|
|
159
|
+
}, dropDownProps: {
|
|
160
|
+
style: { width: 175, maxWidth: 400 },
|
|
161
|
+
} }, actionMenuProps, { children: actionMenuLabel })))
|
|
162
|
+
: (_jsx(DropDownMenu, { data: actionMenuOptions, variant: "text", size: "xs", arrow: false, onItemSelect: handleActionSelect, buttonProps: {
|
|
163
|
+
"aria-label": "Open actions",
|
|
164
|
+
style: {
|
|
165
|
+
minWidth: "auto",
|
|
166
|
+
border: "none",
|
|
167
|
+
background: "transparent",
|
|
168
|
+
padding: 0,
|
|
169
|
+
margin: 0,
|
|
170
|
+
height: 16,
|
|
171
|
+
width: 16,
|
|
172
|
+
},
|
|
173
|
+
}, children: _jsx(StyledMoreHorizontal, { size: 16 }) }))
|
|
174
|
+
: null, children: label })), _jsxs(TextAreaWrapper, { children: [_jsx(TextArea, Object.assign({ ref: mergedRef, size: size, maxRows: maxRows, minRows: minRows, onHeightChange: onHeightChange, cacheMeasurements: cacheMeasurements }, rest)), showInsertMenu && (insertableItems === null || insertableItems === void 0 ? void 0 : insertableItems.length) && (_jsx(InsertMenuOverlay, { ref: insertMenuRef, "$visible": showInsertMenu, children: _jsx(StyledInsertSelectBox, { data: insertableItems, grouped: groupInsertableItems, searchable: true, clearable: false, arrow: false, focused: showInsertMenu, openOnFocus: true, triggerOpen: triggerSelectBoxOpen, onOpened: handleSelectBoxOpened, onChange: handleInsertSelect, size: size }) }))] })] }));
|
|
156
175
|
});
|
|
157
176
|
TextAreaInput.displayName = "TextAreaInput";
|
|
158
177
|
export default TextAreaInput;
|