@monolith-forensics/monolith-ui 1.4.2 → 1.4.3
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.
- package/dist/DateInput/DateInput.d.ts +2 -1
- package/dist/DropDownMenu/DropDownMenu.js +2 -2
- package/dist/DropDownMenu/components/MenuItemList.d.ts +0 -2
- package/dist/DropDownMenu/components/MenuItemList.js +4 -100
- package/dist/DropDownMenu/types.d.ts +0 -3
- package/dist/FieldLabel/FieldLabel.d.ts +2 -2
- package/dist/SelectBox/types.d.ts +2 -1
- package/dist/Switch/Switch.d.ts +2 -2
- package/dist/TagBox/types.d.ts +2 -1
- package/dist/TextAreaInput/TextAreaInput.d.ts +9 -17
- package/dist/TextAreaInput/TextAreaInput.js +105 -45
- package/dist/TextInput/TextInput.d.ts +2 -1
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import moment from "moment";
|
|
2
|
+
import { ReactNode } from "react";
|
|
2
3
|
import { Size, Variant } from "../core";
|
|
3
4
|
type DateInputProps = {
|
|
4
5
|
className?: string;
|
|
@@ -7,7 +8,7 @@ type DateInputProps = {
|
|
|
7
8
|
value?: string | null | undefined;
|
|
8
9
|
format?: FormatOptions;
|
|
9
10
|
label?: string;
|
|
10
|
-
description?:
|
|
11
|
+
description?: ReactNode;
|
|
11
12
|
arrow?: boolean;
|
|
12
13
|
size?: Size;
|
|
13
14
|
variant?: Variant;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from "react";
|
|
3
3
|
import { Menu, MenuItemList, StyledInnerItemContainer } from "./components";
|
|
4
|
-
export const DropDownMenu = ({ data, children, defaultValue, variant, arrow, size, searchable,
|
|
4
|
+
export const DropDownMenu = ({ data, children, defaultValue, variant, arrow, size, searchable, loading, onScroll, onScrollToTop, onScrollToBottom, onSearch, manualSearch, multiselect, renderOption, onItemSelect, onChange, buttonProps, TooltipContent, dropDownProps, query, disabled, }) => {
|
|
5
5
|
var _a;
|
|
6
6
|
const isObjectArray = (_a = Object.keys((data === null || data === void 0 ? void 0 : data[0]) || {})) === null || _a === void 0 ? void 0 : _a.includes("label");
|
|
7
7
|
const [selected, setSelected] = useState(defaultValue || []);
|
|
@@ -25,5 +25,5 @@ export const DropDownMenu = ({ data, children, defaultValue, variant, arrow, siz
|
|
|
25
25
|
const handleScrollToBottom = (e) => {
|
|
26
26
|
onScrollToBottom === null || onScrollToBottom === void 0 ? void 0 : onScrollToBottom(e);
|
|
27
27
|
};
|
|
28
|
-
return (_jsx(Menu, { label: children, disabled: disabled, arrow: arrow, buttonSize: size, variant: variant, multiselect: multiselect, buttonProps: buttonProps, onMenuClose: handleMenuClose, dropDownProps: dropDownProps, children: _jsxs(StyledInnerItemContainer, { children: [loading && _jsx("div", { children: "Loading..." }), !loading && (_jsx(MenuItemList, { menuItems: data, searchable: searchable,
|
|
28
|
+
return (_jsx(Menu, { label: children, disabled: disabled, arrow: arrow, buttonSize: size, variant: variant, multiselect: multiselect, buttonProps: buttonProps, onMenuClose: handleMenuClose, dropDownProps: dropDownProps, children: _jsxs(StyledInnerItemContainer, { children: [loading && _jsx("div", { children: "Loading..." }), !loading && (_jsx(MenuItemList, { menuItems: data, searchable: searchable, onSearch: onSearch, manualSearch: manualSearch, selected: selected, TooltipContent: TooltipContent, multiselect: multiselect, size: size, handleAddItem: handleAddItem, handleRemoveItem: handleRemoveItem, onItemSelect: onItemSelect, renderOption: renderOption, onScroll: onScroll, onScrollToTop: onScrollToTop, onScrollToBottom: handleScrollToBottom, query: query }))] }) }));
|
|
29
29
|
};
|
|
@@ -10,8 +10,6 @@ export declare const MenuItemList: React.FC<{
|
|
|
10
10
|
selected?: DropDownItem[];
|
|
11
11
|
TooltipContent?: ComponentType<any>;
|
|
12
12
|
multiselect?: boolean;
|
|
13
|
-
grouped?: boolean;
|
|
14
|
-
onAddNew?: (value: string) => void;
|
|
15
13
|
size?: Size;
|
|
16
14
|
handleAddItem: (item: DropDownItem) => void;
|
|
17
15
|
handleRemoveItem: (item: DropDownItem) => void;
|
|
@@ -13,7 +13,6 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
13
13
|
import { useLayoutEffect, useRef, useState } from "react";
|
|
14
14
|
import styled from "styled-components";
|
|
15
15
|
import { FixedSizeList } from "react-window";
|
|
16
|
-
import { Plus } from "lucide-react";
|
|
17
16
|
import CheckBox from "../../CheckBox";
|
|
18
17
|
import { DropDownMenu } from "../DropDownMenu";
|
|
19
18
|
import { MenuItem } from "./MenuItem";
|
|
@@ -31,71 +30,11 @@ const filterMenuItems = (menuItems, searchValue) => {
|
|
|
31
30
|
return (_c = item.toLowerCase) === null || _c === void 0 ? void 0 : _c.call(item).includes(searchValue.toLowerCase());
|
|
32
31
|
});
|
|
33
32
|
};
|
|
34
|
-
const buildGroupedDisplayList = (items) => {
|
|
35
|
-
const groups = {};
|
|
36
|
-
for (const item of items) {
|
|
37
|
-
const key = item.group || "Other";
|
|
38
|
-
if (!groups[key])
|
|
39
|
-
groups[key] = [];
|
|
40
|
-
groups[key].push(item);
|
|
41
|
-
}
|
|
42
|
-
const sortedKeys = Object.keys(groups).sort((a, b) => a.localeCompare(b));
|
|
43
|
-
const result = [];
|
|
44
|
-
for (const key of sortedKeys) {
|
|
45
|
-
result.push({
|
|
46
|
-
_isGroupHeader: true,
|
|
47
|
-
label: key,
|
|
48
|
-
value: `__group__${key}`,
|
|
49
|
-
});
|
|
50
|
-
result.push(...groups[key]);
|
|
51
|
-
}
|
|
52
|
-
return result;
|
|
53
|
-
};
|
|
54
33
|
const ListViewPort = styled.div.attrs({ className: "ListViewPort" }) `
|
|
55
34
|
display: flex;
|
|
56
35
|
flex-direction: column;
|
|
57
36
|
`;
|
|
58
|
-
const
|
|
59
|
-
display: flex;
|
|
60
|
-
align-items: center;
|
|
61
|
-
gap: 8px;
|
|
62
|
-
color: ${(props) => props.theme.palette.text.secondary};
|
|
63
|
-
font-weight: 500;
|
|
64
|
-
user-select: none;
|
|
65
|
-
padding: ${({ $size }) => $size === "xs"
|
|
66
|
-
? "2px 8px"
|
|
67
|
-
: $size === "sm"
|
|
68
|
-
? "4px 10px"
|
|
69
|
-
: $size === "md"
|
|
70
|
-
? "4px 12px"
|
|
71
|
-
: $size === "lg"
|
|
72
|
-
? "5px 14px"
|
|
73
|
-
: $size === "xl"
|
|
74
|
-
? "6px 16px"
|
|
75
|
-
: "2px 8px"};
|
|
76
|
-
font-size: ${({ $size }) => $size === "xs"
|
|
77
|
-
? "10px"
|
|
78
|
-
: $size === "sm"
|
|
79
|
-
? "11px"
|
|
80
|
-
: $size === "md"
|
|
81
|
-
? "13px"
|
|
82
|
-
: $size === "lg"
|
|
83
|
-
? "15px"
|
|
84
|
-
: $size === "xl"
|
|
85
|
-
? "17px"
|
|
86
|
-
: "10px"};
|
|
87
|
-
|
|
88
|
-
.group-line {
|
|
89
|
-
border-top: 1px solid ${(props) => props.theme.palette.divider};
|
|
90
|
-
flex: 1;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.group-label {
|
|
94
|
-
white-space: nowrap;
|
|
95
|
-
min-width: fit-content;
|
|
96
|
-
}
|
|
97
|
-
`;
|
|
98
|
-
export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, selected, TooltipContent, multiselect, grouped, onAddNew, size, handleAddItem, handleRemoveItem, onItemSelect, renderOption, onScroll, onScrollToTop, onScrollToBottom, query, }) => {
|
|
37
|
+
export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, selected, TooltipContent, multiselect, size, handleAddItem, handleRemoveItem, onItemSelect, renderOption, onScroll, onScrollToTop, onScrollToBottom, query, }) => {
|
|
99
38
|
var _a;
|
|
100
39
|
const [searchValue, setSearchValue] = useState("");
|
|
101
40
|
const _b = query !== null && query !== void 0 ? query : {}, { queryKey, queryFn, getNextPageParam, initialPageParam } = _b, rest = __rest(_b, ["queryKey", "queryFn", "getNextPageParam", "initialPageParam"]);
|
|
@@ -130,29 +69,6 @@ export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, se
|
|
|
130
69
|
const filteredItems = searchable
|
|
131
70
|
? filterMenuItems(visibleItems, searchValue)
|
|
132
71
|
: visibleItems;
|
|
133
|
-
const hasExactMatch = searchValue.trim() !== "" &&
|
|
134
|
-
filteredItems.some((item) => {
|
|
135
|
-
var _a, _b;
|
|
136
|
-
return ((_a = item === null || item === void 0 ? void 0 : item.label) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === searchValue.trim().toLowerCase() ||
|
|
137
|
-
((_b = item === null || item === void 0 ? void 0 : item.value) === null || _b === void 0 ? void 0 : _b.toString().toLowerCase()) ===
|
|
138
|
-
searchValue.trim().toLowerCase();
|
|
139
|
-
});
|
|
140
|
-
const displayItems = (() => {
|
|
141
|
-
let items = grouped
|
|
142
|
-
? buildGroupedDisplayList(filteredItems)
|
|
143
|
-
: filteredItems;
|
|
144
|
-
if (onAddNew && searchValue.trim() && !hasExactMatch) {
|
|
145
|
-
items = [
|
|
146
|
-
...items,
|
|
147
|
-
{
|
|
148
|
-
_isAddNew: true,
|
|
149
|
-
label: `Add "${searchValue.trim()}"`,
|
|
150
|
-
value: searchValue.trim(),
|
|
151
|
-
},
|
|
152
|
-
];
|
|
153
|
-
}
|
|
154
|
-
return items;
|
|
155
|
-
})();
|
|
156
72
|
const isObjectArray = (_a = Object.keys((visibleItems === null || visibleItems === void 0 ? void 0 : visibleItems[0]) || {})) === null || _a === void 0 ? void 0 : _a.includes("label");
|
|
157
73
|
const isLoading = isLoadingInfiniteQuery;
|
|
158
74
|
const handleOnScroll = (event) => {
|
|
@@ -198,7 +114,7 @@ export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, se
|
|
|
198
114
|
}, [targetElm.current, isLoading]);
|
|
199
115
|
const overscanCount = 10;
|
|
200
116
|
const itemHeight = 25;
|
|
201
|
-
const itemCount = (
|
|
117
|
+
const itemCount = (filteredItems === null || filteredItems === void 0 ? void 0 : filteredItems.length) || 0;
|
|
202
118
|
const height = viewPortDimensions.height
|
|
203
119
|
? viewPortDimensions.height
|
|
204
120
|
: itemCount * itemHeight < 200
|
|
@@ -218,20 +134,8 @@ export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, se
|
|
|
218
134
|
alignItems: "center",
|
|
219
135
|
height: "100%",
|
|
220
136
|
padding: "10px 0",
|
|
221
|
-
}, children: [_jsx("div", { style: { fontSize: "12px" }, children: "Loading..." }), _jsx(Loader, {})] })), !isLoading && (_jsx(ListViewPort, { ref: targetElm, children: _jsx(FixedSizeList, { itemData:
|
|
222
|
-
const item = data === null || data === void 0 ? void 0 : data[index];
|
|
223
|
-
if (!item)
|
|
224
|
-
return null;
|
|
225
|
-
if (item._isGroupHeader) {
|
|
226
|
-
return (_jsxs(GroupHeader, { "$size": size, style: style, children: [_jsx("span", { className: "group-line" }), _jsx("span", { className: "group-label", children: item.label }), _jsx("span", { className: "group-line" })] }, item.value));
|
|
227
|
-
}
|
|
228
|
-
if (item._isAddNew) {
|
|
229
|
-
return (_jsx(MenuItem, { className: "MenuItem", size: size, leftSection: _jsx(Plus, { size: 14 }), onClick: (e) => {
|
|
230
|
-
e.preventDefault();
|
|
231
|
-
e.stopPropagation();
|
|
232
|
-
onAddNew === null || onAddNew === void 0 ? void 0 : onAddNew(item.value);
|
|
233
|
-
}, style: style, children: item.label }, "__add_new__"));
|
|
234
|
-
}
|
|
137
|
+
}, children: [_jsx("div", { style: { fontSize: "12px" }, children: "Loading..." }), _jsx(Loader, {})] })), !isLoading && (_jsx(ListViewPort, { ref: targetElm, children: _jsx(FixedSizeList, { itemData: filteredItems, overscanCount: overscanCount, height: height, width: width, itemCount: itemCount, itemSize: itemHeight, outerRef: listElm, children: ({ data, index, style }) => {
|
|
138
|
+
const item = (data === null || data === void 0 ? void 0 : data[index]) || {};
|
|
235
139
|
const isSelected = !!(selected === null || selected === void 0 ? void 0 : selected.find((s) => {
|
|
236
140
|
return isObjectArray ? (s === null || s === void 0 ? void 0 : s.value) === (item === null || item === void 0 ? void 0 : item.value) : s === item;
|
|
237
141
|
}));
|
|
@@ -15,7 +15,6 @@ export type DropDownItem = {
|
|
|
15
15
|
rightSection?: React.ReactNode;
|
|
16
16
|
disabled?: boolean;
|
|
17
17
|
visible?: boolean;
|
|
18
|
-
group?: string;
|
|
19
18
|
};
|
|
20
19
|
export type SearchInputProps = React.ComponentPropsWithoutRef<typeof Input>;
|
|
21
20
|
export type StyledContentProps = {
|
|
@@ -43,8 +42,6 @@ export type DropDownMenuProps = {
|
|
|
43
42
|
onSearch?: (value: string) => void;
|
|
44
43
|
searchable?: boolean;
|
|
45
44
|
manualSearch?: boolean;
|
|
46
|
-
grouped?: boolean;
|
|
47
|
-
onAddNew?: (value: string) => void;
|
|
48
45
|
loading?: boolean;
|
|
49
46
|
arrow?: boolean;
|
|
50
47
|
dropDownProps?: ComponentPropsWithoutRef<typeof StyledContent>;
|
|
@@ -3,7 +3,7 @@ import { Size } from "../core";
|
|
|
3
3
|
interface InfoComponentProps {
|
|
4
4
|
className?: string;
|
|
5
5
|
children?: ReactNode;
|
|
6
|
-
description?:
|
|
6
|
+
description?: ReactNode;
|
|
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>>;
|
|
@@ -11,7 +11,7 @@ export interface FieldLabelProps {
|
|
|
11
11
|
className?: string;
|
|
12
12
|
children?: ReactNode;
|
|
13
13
|
error?: string;
|
|
14
|
-
description?:
|
|
14
|
+
description?: ReactNode;
|
|
15
15
|
size?: Size;
|
|
16
16
|
asterisk?: boolean;
|
|
17
17
|
style?: React.CSSProperties;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
1
2
|
import { Size, Variant } from "../core";
|
|
2
3
|
export type Option = {
|
|
3
4
|
label: string;
|
|
@@ -23,7 +24,7 @@ export type SelectBoxProps = {
|
|
|
23
24
|
searchable?: boolean;
|
|
24
25
|
clearable?: boolean;
|
|
25
26
|
label?: string;
|
|
26
|
-
description?:
|
|
27
|
+
description?: ReactNode;
|
|
27
28
|
required?: boolean;
|
|
28
29
|
error?: string;
|
|
29
30
|
openOnFocus?: boolean;
|
package/dist/Switch/Switch.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CSSProperties } from "react";
|
|
1
|
+
import { CSSProperties, ReactNode } from "react";
|
|
2
2
|
import { Size } from "../core";
|
|
3
3
|
export type SwitchProps = {
|
|
4
4
|
className?: string;
|
|
@@ -6,7 +6,7 @@ export type SwitchProps = {
|
|
|
6
6
|
size?: Exclude<Size, "xxs">;
|
|
7
7
|
label?: string;
|
|
8
8
|
labelPosition?: "left" | "right";
|
|
9
|
-
description?:
|
|
9
|
+
description?: ReactNode;
|
|
10
10
|
error?: string;
|
|
11
11
|
required?: boolean;
|
|
12
12
|
disabled?: boolean;
|
package/dist/TagBox/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
1
2
|
import { Size, Variant } from "../core";
|
|
2
3
|
export type Option = {
|
|
3
4
|
label: string;
|
|
@@ -22,7 +23,7 @@ export interface TagBoxProps {
|
|
|
22
23
|
searchable?: boolean;
|
|
23
24
|
clearable?: boolean;
|
|
24
25
|
label?: string;
|
|
25
|
-
description?:
|
|
26
|
+
description?: ReactNode;
|
|
26
27
|
required?: boolean;
|
|
27
28
|
error?: string;
|
|
28
29
|
openOnFocus?: boolean;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { ReactNode } from "react";
|
|
2
2
|
import { Size } from "../core";
|
|
3
|
-
import {
|
|
3
|
+
import { DropDownItem } from "..";
|
|
4
4
|
export type InsertableItem = {
|
|
5
5
|
label: string;
|
|
6
6
|
value: string;
|
|
7
|
-
group?: string;
|
|
8
7
|
};
|
|
9
8
|
export interface TextAreaInputProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
10
9
|
variant?: "contained" | "filled" | "outlined" | "text";
|
|
@@ -13,28 +12,21 @@ export interface TextAreaInputProps extends React.TextareaHTMLAttributes<HTMLTex
|
|
|
13
12
|
required?: boolean;
|
|
14
13
|
colSpan?: number;
|
|
15
14
|
size?: Size;
|
|
16
|
-
description?:
|
|
15
|
+
description?: ReactNode;
|
|
17
16
|
maxRows?: number;
|
|
18
17
|
minRows?: number;
|
|
19
18
|
cacheMeasurements?: boolean;
|
|
20
19
|
onHeightChange?: (height: number, meta: {
|
|
21
20
|
rowHeight: number;
|
|
22
21
|
}) => void;
|
|
22
|
+
showActionMenu?: boolean;
|
|
23
|
+
actionMenuOptions?: Array<{
|
|
24
|
+
value: string;
|
|
25
|
+
label: string;
|
|
26
|
+
}>;
|
|
27
|
+
onActionMenuSelect?: (item: DropDownItem) => void;
|
|
23
28
|
insertableItems?: InsertableItem[];
|
|
24
29
|
onInsertItem?: (item: InsertableItem) => void;
|
|
25
|
-
groupInsertableItems?: boolean;
|
|
26
|
-
/** Callback when the user creates a new item by typing a value in the search box that doesn't match any existing option. */
|
|
27
|
-
onAddNewItem?: (value: string) => void;
|
|
28
|
-
/**
|
|
29
|
-
* Visual style of the insert menu trigger.
|
|
30
|
-
* - `"ellipsis"` renders a minimal `...` icon button.
|
|
31
|
-
* - `"dropdown"` renders an outlined button with a label and arrow (default).
|
|
32
|
-
*/
|
|
33
|
-
insertMenuVariant?: "ellipsis" | "dropdown";
|
|
34
|
-
/** Label for the insert dropdown trigger button. Only used when `insertMenuVariant` is `"dropdown"`. Defaults to "Insert". */
|
|
35
|
-
insertMenuLabel?: string;
|
|
36
|
-
/** Additional props forwarded to the DropDownMenu component. */
|
|
37
|
-
insertMenuProps?: Partial<DropDownMenuProps>;
|
|
38
30
|
}
|
|
39
31
|
declare const TextAreaInput: React.ForwardRefExoticComponent<TextAreaInputProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
40
32
|
export default TextAreaInput;
|
|
@@ -11,9 +11,34 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
import styled from "styled-components";
|
|
14
|
-
import { forwardRef, useRef,
|
|
15
|
-
import { TextArea, FieldLabel, DropDownMenu } from "..";
|
|
14
|
+
import { forwardRef, useState, useRef, useEffect } from "react";
|
|
15
|
+
import { TextArea, FieldLabel, DropDownMenu, SelectBox, } from "..";
|
|
16
16
|
import { MoreHorizontal } from "lucide-react";
|
|
17
|
+
const DEFAULT_ACTIONS = [
|
|
18
|
+
{ value: "clear", label: "Clear Text" },
|
|
19
|
+
{ value: "insert", label: "Insert Item" },
|
|
20
|
+
];
|
|
21
|
+
const TextAreaWrapper = styled.div `
|
|
22
|
+
position: relative;
|
|
23
|
+
`;
|
|
24
|
+
const InsertMenuOverlay = styled.div `
|
|
25
|
+
position: absolute;
|
|
26
|
+
top: 0;
|
|
27
|
+
left: 0;
|
|
28
|
+
right: 0;
|
|
29
|
+
z-index: 10;
|
|
30
|
+
opacity: ${({ $visible }) => ($visible ? 1 : 0)};
|
|
31
|
+
pointer-events: ${({ $visible }) => ($visible ? "auto" : "none")};
|
|
32
|
+
transform: ${({ $visible }) => $visible ? "translateY(0)" : "translateY(-4px)"};
|
|
33
|
+
transition:
|
|
34
|
+
opacity 0.2s ease,
|
|
35
|
+
transform 0.2s ease;
|
|
36
|
+
`;
|
|
37
|
+
const StyledInsertSelectBox = styled(SelectBox) `
|
|
38
|
+
width: 100%;
|
|
39
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
40
|
+
border: 1px solid ${({ theme }) => theme.palette.primary.main};
|
|
41
|
+
`;
|
|
17
42
|
const StyledMoreHorizontal = styled(MoreHorizontal) `
|
|
18
43
|
color: ${({ theme }) => theme.palette.text.secondary};
|
|
19
44
|
&:hover {
|
|
@@ -21,8 +46,21 @@ const StyledMoreHorizontal = styled(MoreHorizontal) `
|
|
|
21
46
|
}
|
|
22
47
|
`;
|
|
23
48
|
const TextAreaInput = forwardRef((props, ref) => {
|
|
24
|
-
const {
|
|
49
|
+
const {
|
|
50
|
+
// UI
|
|
51
|
+
label, error, required, colSpan = 1, size = "sm", description, maxRows = 6, minRows = 3, onHeightChange, cacheMeasurements,
|
|
52
|
+
// Action menu
|
|
53
|
+
showActionMenu = false, actionMenuOptions = DEFAULT_ACTIONS, onActionMenuSelect,
|
|
54
|
+
// Insertable items
|
|
55
|
+
insertableItems, onInsertItem } = props,
|
|
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"]);
|
|
58
|
+
// State for insert menu visibility
|
|
59
|
+
const [showInsertMenu, setShowInsertMenu] = useState(false);
|
|
60
|
+
const [triggerSelectBoxOpen, setTriggerSelectBoxOpen] = useState(false);
|
|
25
61
|
const textareaRef = useRef(null);
|
|
62
|
+
const insertMenuRef = useRef(null);
|
|
63
|
+
// Merge refs
|
|
26
64
|
const mergedRef = (node) => {
|
|
27
65
|
textareaRef.current = node;
|
|
28
66
|
if (typeof ref === "function") {
|
|
@@ -32,50 +70,79 @@ const TextAreaInput = forwardRef((props, ref) => {
|
|
|
32
70
|
ref.current = node;
|
|
33
71
|
}
|
|
34
72
|
};
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
group: item.group,
|
|
39
|
-
})), [insertableItems]);
|
|
40
|
-
const insertAtCursor = (text) => {
|
|
41
|
-
var _a;
|
|
42
|
-
const textarea = textareaRef.current;
|
|
43
|
-
if (!textarea)
|
|
73
|
+
// Handle click outside to close insert menu
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (!showInsertMenu)
|
|
44
76
|
return;
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
nativeSet === null || nativeSet === void 0 ? void 0 : nativeSet.call(textarea, newValue);
|
|
51
|
-
textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
52
|
-
textarea.focus();
|
|
53
|
-
textarea.setSelectionRange(start + text.length, start + text.length);
|
|
54
|
-
};
|
|
55
|
-
const handleItemSelect = (item) => {
|
|
56
|
-
const insertable = {
|
|
57
|
-
label: item.label,
|
|
58
|
-
value: String(item.value),
|
|
59
|
-
group: item.group,
|
|
77
|
+
const handleClickOutside = (event) => {
|
|
78
|
+
if (insertMenuRef.current &&
|
|
79
|
+
!insertMenuRef.current.contains(event.target)) {
|
|
80
|
+
setShowInsertMenu(false);
|
|
81
|
+
}
|
|
60
82
|
};
|
|
61
|
-
|
|
62
|
-
|
|
83
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
84
|
+
return () => {
|
|
85
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
86
|
+
};
|
|
87
|
+
}, [showInsertMenu]);
|
|
88
|
+
const handleActionSelect = (item) => {
|
|
89
|
+
if (item.value === "insert" && (insertableItems === null || insertableItems === void 0 ? void 0 : insertableItems.length)) {
|
|
90
|
+
setShowInsertMenu(true);
|
|
91
|
+
// Trigger SelectBox to open using the new enhanced props
|
|
92
|
+
setTriggerSelectBoxOpen(true);
|
|
93
|
+
}
|
|
94
|
+
else if (item.value === "clear") {
|
|
95
|
+
// Built-in clear functionality
|
|
96
|
+
const textarea = textareaRef.current;
|
|
97
|
+
if (textarea) {
|
|
98
|
+
textarea.value = "";
|
|
99
|
+
textarea.focus();
|
|
100
|
+
// Trigger change event so controlled components update
|
|
101
|
+
const event = new Event("input", { bubbles: true });
|
|
102
|
+
textarea.dispatchEvent(event);
|
|
103
|
+
}
|
|
104
|
+
onActionMenuSelect === null || onActionMenuSelect === void 0 ? void 0 : onActionMenuSelect(item);
|
|
63
105
|
}
|
|
64
106
|
else {
|
|
65
|
-
|
|
107
|
+
onActionMenuSelect === null || onActionMenuSelect === void 0 ? void 0 : onActionMenuSelect(item);
|
|
66
108
|
}
|
|
67
109
|
};
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
110
|
+
const handleSelectBoxOpened = () => {
|
|
111
|
+
// Reset the trigger after SelectBox has opened
|
|
112
|
+
setTriggerSelectBoxOpen(false);
|
|
113
|
+
};
|
|
114
|
+
const handleInsertSelect = (value, option) => {
|
|
115
|
+
console.log("Selected value:", value, "Selected option:", option); // Debug log
|
|
116
|
+
// SelectBox passes (value, option) - we want the full option object
|
|
117
|
+
const item = option;
|
|
118
|
+
if (!item || !item.value) {
|
|
119
|
+
console.warn("Invalid item selected:", item);
|
|
120
|
+
setShowInsertMenu(false);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (onInsertItem) {
|
|
124
|
+
onInsertItem(item);
|
|
71
125
|
}
|
|
72
126
|
else {
|
|
73
|
-
|
|
127
|
+
// Default behavior: insert at current cursor position
|
|
128
|
+
const textarea = textareaRef.current;
|
|
129
|
+
if (textarea) {
|
|
130
|
+
const start = textarea.selectionStart;
|
|
131
|
+
const end = textarea.selectionEnd;
|
|
132
|
+
const currentValue = textarea.value;
|
|
133
|
+
const newValue = currentValue.slice(0, start) + item.value + currentValue.slice(end);
|
|
134
|
+
textarea.value = newValue;
|
|
135
|
+
textarea.focus();
|
|
136
|
+
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
|
+
}
|
|
74
141
|
}
|
|
142
|
+
setShowInsertMenu(false);
|
|
75
143
|
};
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"aria-label": "Insert item",
|
|
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 ? (_jsx(DropDownMenu, { data: actionMenuOptions, variant: "text", size: "xs", arrow: false, onItemSelect: handleActionSelect, buttonProps: {
|
|
145
|
+
"aria-label": "Open actions",
|
|
79
146
|
style: {
|
|
80
147
|
minWidth: "auto",
|
|
81
148
|
border: "none",
|
|
@@ -85,14 +152,7 @@ const TextAreaInput = forwardRef((props, ref) => {
|
|
|
85
152
|
height: 16,
|
|
86
153
|
width: 16,
|
|
87
154
|
},
|
|
88
|
-
},
|
|
89
|
-
style: { width: 200, maxWidth: 400 },
|
|
90
|
-
} }, insertMenuProps, { children: _jsx(StyledMoreHorizontal, { size: 16 }) }))) : (_jsx(DropDownMenu, Object.assign({ data: dropdownData, variant: "outlined", size: "xs", arrow: true, searchable: true, grouped: groupInsertableItems, onAddNew: handleAddNew, onItemSelect: handleItemSelect, buttonProps: {
|
|
91
|
-
title: insertMenuLabel,
|
|
92
|
-
size: "xxs",
|
|
93
|
-
}, dropDownProps: {
|
|
94
|
-
style: { width: 200, maxWidth: 400 },
|
|
95
|
-
} }, insertMenuProps, { children: insertMenuLabel })))) : null, children: label })), _jsx(TextArea, Object.assign({ ref: mergedRef, size: size, maxRows: maxRows, minRows: minRows, onHeightChange: onHeightChange, cacheMeasurements: cacheMeasurements }, rest))] }));
|
|
155
|
+
}, children: _jsx(StyledMoreHorizontal, { size: 16 }) })) : 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, placeholder: "Select item to insert...", searchable: true, clearable: false, arrow: false, focused: showInsertMenu, openOnFocus: true, triggerOpen: triggerSelectBoxOpen, onOpened: handleSelectBoxOpened, onChange: handleInsertSelect, size: size }) }))] })] }));
|
|
96
156
|
});
|
|
97
157
|
TextAreaInput.displayName = "TextAreaInput";
|
|
98
158
|
export default TextAreaInput;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { InputProps } from "../Input/Input";
|
|
2
2
|
import { Size } from "../core";
|
|
3
|
+
import { ReactNode } from "react";
|
|
3
4
|
export type TextInputProps = InputProps & {
|
|
4
5
|
className?: string;
|
|
5
6
|
label?: string;
|
|
@@ -7,7 +8,7 @@ export type TextInputProps = InputProps & {
|
|
|
7
8
|
required?: boolean;
|
|
8
9
|
size?: Size;
|
|
9
10
|
colSpan?: number;
|
|
10
|
-
description?:
|
|
11
|
+
description?: ReactNode;
|
|
11
12
|
inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
|
|
12
13
|
style?: React.CSSProperties;
|
|
13
14
|
password?: boolean;
|