@monolith-forensics/monolith-ui 1.2.41 → 1.2.44
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/Calendar/calendarHelpers.d.ts +1 -1
- package/dist/FileViewer/FileViewer.js +13 -2
- package/dist/FileViewer/viewers/ImageViewer.js +3 -4
- package/dist/FileViewer/viewers/PdfViewer.js +27 -23
- package/dist/FormSection/FormSection.d.ts +5 -2
- package/dist/FormSection/FormSection.js +18 -2
- package/dist/SelectBox/SelectBox.js +95 -84
- package/dist/SelectBox/types.d.ts +2 -2
- package/dist/TagBox/TagBox.d.ts +1 -1
- package/dist/TagBox/TagBox.js +131 -77
- package/package.json +2 -2
|
@@ -35,7 +35,7 @@ export declare const CALENDAR_MONTHS: {
|
|
|
35
35
|
};
|
|
36
36
|
export declare const CALENDAR_WEEKS = 6;
|
|
37
37
|
export declare const zeroPad: (value: number, length: number) => string;
|
|
38
|
-
export declare const getMonthDays: (month?: number, year?: number) =>
|
|
38
|
+
export declare const getMonthDays: (month?: number, year?: number) => 28 | 29 | 30 | 31;
|
|
39
39
|
export declare const getMonthFirstDay: (month?: number, year?: number) => number;
|
|
40
40
|
export declare const isDate: (date: Date) => boolean;
|
|
41
41
|
export declare const isSameMonth: (date: Date, basedate?: Date) => boolean;
|
|
@@ -62,7 +62,7 @@ const StyledActionsMenu = styled.div `
|
|
|
62
62
|
gap: 10px;
|
|
63
63
|
align-items: center;
|
|
64
64
|
`;
|
|
65
|
-
const StyledContainer = styled.div `
|
|
65
|
+
const StyledContainer = styled.div.attrs({ className: "FileViewer-container" }) `
|
|
66
66
|
position: fixed;
|
|
67
67
|
top: 0;
|
|
68
68
|
left: 0;
|
|
@@ -81,6 +81,7 @@ const StyledContainer = styled.div `
|
|
|
81
81
|
// scroll bar
|
|
82
82
|
::-webkit-scrollbar {
|
|
83
83
|
width: 14px;
|
|
84
|
+
height: 14px;
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
::-webkit-scrollbar-track {
|
|
@@ -93,9 +94,19 @@ const StyledContainer = styled.div `
|
|
|
93
94
|
border-radius: 10px;
|
|
94
95
|
border: 4px solid rgba(0, 0, 0, 0);
|
|
95
96
|
background-clip: padding-box;
|
|
97
|
+
|
|
98
|
+
&:hover {
|
|
99
|
+
background-color: ${(props) => props.theme.palette.primary.main};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
::-webkit-scrollbar-corner {
|
|
104
|
+
background: rgba(0, 0, 0, 0.5);
|
|
96
105
|
}
|
|
97
106
|
`;
|
|
98
|
-
const StyledInnerContainer = styled.div
|
|
107
|
+
const StyledInnerContainer = styled.div.attrs({
|
|
108
|
+
className: "FileViewer-inner-container",
|
|
109
|
+
}) `
|
|
99
110
|
display: flex;
|
|
100
111
|
flex-direction: column;
|
|
101
112
|
flex: 1 1 auto;
|
|
@@ -3,11 +3,10 @@ import { useEffect, useState } from "react";
|
|
|
3
3
|
import styled from "styled-components";
|
|
4
4
|
import Loader from "../../Loader";
|
|
5
5
|
const ImageViewerContainer = styled.div `
|
|
6
|
-
|
|
7
|
-
justify-content: center;
|
|
6
|
+
height: 100%;
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
text-align: center;
|
|
9
|
+
padding: 10px;
|
|
11
10
|
`;
|
|
12
11
|
// Updated Image styled-component to remove max-width and max-height
|
|
13
12
|
const Image = styled.img `
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
1
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
13
|
import { useState } from "react";
|
|
3
14
|
import { Document, Page, pdfjs } from "react-pdf";
|
|
@@ -6,29 +17,15 @@ import "react-pdf/dist/esm/Page/TextLayer.css";
|
|
|
6
17
|
import styled from "styled-components";
|
|
7
18
|
import Loader from "../../Loader";
|
|
8
19
|
pdfjs.GlobalWorkerOptions.workerSrc = new URL("pdfjs-dist/build/pdf.worker.min.mjs", import.meta.url).toString();
|
|
9
|
-
const StyledContainer = styled.div
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
flex: 1 1 auto;
|
|
14
|
-
height: 0px;
|
|
15
|
-
|
|
16
|
-
&[data-loading="true"] > * {
|
|
17
|
-
justify-content: center;
|
|
18
|
-
}
|
|
19
|
-
`;
|
|
20
|
-
const StyledDocument = styled(Document) `
|
|
21
|
-
display: flex;
|
|
22
|
-
flex-direction: column;
|
|
23
|
-
gap: 10px;
|
|
24
|
-
|
|
25
|
-
background-color: transparent;
|
|
26
|
-
|
|
27
|
-
// width: 100%;
|
|
28
|
-
`;
|
|
20
|
+
const StyledContainer = styled.div ``;
|
|
21
|
+
const StyledDocument = styled(Document).attrs({
|
|
22
|
+
className: "PdfViewer-document",
|
|
23
|
+
}) ``;
|
|
29
24
|
const StyledPage = styled(Page) `
|
|
30
25
|
width: fit-content;
|
|
31
26
|
background-color: transparent;
|
|
27
|
+
margin: 0 auto;
|
|
28
|
+
margin-bottom: 10px;
|
|
32
29
|
`;
|
|
33
30
|
const StyledLoader = styled.div `
|
|
34
31
|
display: flex;
|
|
@@ -36,18 +33,25 @@ const StyledLoader = styled.div `
|
|
|
36
33
|
justify-content: center;
|
|
37
34
|
align-items: center;
|
|
38
35
|
gap: 10px;
|
|
36
|
+
|
|
37
|
+
position: absolute;
|
|
38
|
+
top: 50%;
|
|
39
|
+
left: 50%;
|
|
40
|
+
transform: translate(-50%, -50%);
|
|
39
41
|
`;
|
|
40
42
|
export const PdfViewer = ({ file, zoomFactor = 1, }) => {
|
|
41
43
|
const [loading, setLoading] = useState(true);
|
|
42
44
|
const [numPages, setNumPages] = useState();
|
|
43
45
|
const [pageNumber, setPageNumber] = useState(1);
|
|
44
|
-
function onDocumentLoadSuccess(
|
|
46
|
+
function onDocumentLoadSuccess(_a) {
|
|
47
|
+
var { numPages } = _a, rest = __rest(_a, ["numPages"]);
|
|
48
|
+
console.log(rest);
|
|
45
49
|
setLoading(false);
|
|
46
50
|
setNumPages(numPages);
|
|
47
51
|
}
|
|
48
52
|
// viewport width
|
|
49
|
-
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
|
|
50
|
-
return (_jsx(StyledContainer, { className: "PdfViewer",
|
|
53
|
+
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0) / 1.15;
|
|
54
|
+
return (_jsx(StyledContainer, { className: "PdfViewer", children: _jsx(StyledDocument, { file: file.url, onLoadSuccess: onDocumentLoadSuccess, loading: _jsxs(StyledLoader, { children: [_jsx(Loader, { size: 50 }), _jsx("div", { children: "Loading PDF..." })] }), onClick: (e) => {
|
|
51
55
|
e.stopPropagation();
|
|
52
56
|
}, children: Array.from(new Array(numPages), (el, index) => (_jsx(StyledPage, { pageNumber: index + 1, scale: zoomFactor, width: vw }, `page_${index + 1}`))) }) }));
|
|
53
57
|
};
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
+
import { LucideIcon } from "lucide-react";
|
|
1
2
|
import { ReactNode } from "react";
|
|
2
3
|
import { Size } from "../core";
|
|
3
4
|
interface FormSectionProps {
|
|
4
5
|
children?: ReactNode;
|
|
5
6
|
className?: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
6
8
|
title?: string | ReactNode;
|
|
7
9
|
open?: boolean;
|
|
8
10
|
defaultOpen?: boolean;
|
|
9
11
|
onOpenChange?: (open: boolean) => void;
|
|
10
12
|
allowCollapse?: boolean;
|
|
11
13
|
size?: Size;
|
|
12
|
-
|
|
14
|
+
icon?: LucideIcon;
|
|
15
|
+
iconColor?: string;
|
|
13
16
|
}
|
|
14
|
-
declare const FormSection: ({ title, children, open, defaultOpen, onOpenChange, allowCollapse, size, style, }: FormSectionProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
declare const FormSection: ({ title, children, open, defaultOpen, onOpenChange, allowCollapse, size, style, icon: Icon, iconColor, }: FormSectionProps) => import("react/jsx-runtime").JSX.Element;
|
|
15
18
|
export default FormSection;
|
|
@@ -56,7 +56,23 @@ const StyledContainer = styled.div `
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
`;
|
|
59
|
-
const
|
|
59
|
+
const resolveIconSize = (size) => {
|
|
60
|
+
switch (size) {
|
|
61
|
+
case "xs":
|
|
62
|
+
return 12;
|
|
63
|
+
case "sm":
|
|
64
|
+
return 14;
|
|
65
|
+
case "md":
|
|
66
|
+
return 18;
|
|
67
|
+
case "lg":
|
|
68
|
+
return 24;
|
|
69
|
+
case "xl":
|
|
70
|
+
return 28;
|
|
71
|
+
default:
|
|
72
|
+
return 18;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const FormSection = ({ title, children, open, defaultOpen = true, onOpenChange, allowCollapse = true, size, style, icon: Icon, iconColor, }) => {
|
|
60
76
|
const [_open, setOpen] = useState(defaultOpen);
|
|
61
77
|
const openState = open !== null && open !== void 0 ? open : _open;
|
|
62
78
|
return (_jsxs(StyledContainer, { className: "mfui-FormSection", size: size, style: style, children: [_jsxs("div", { className: "section-header", onClick: (e) => {
|
|
@@ -64,6 +80,6 @@ const FormSection = ({ title, children, open, defaultOpen = true, onOpenChange,
|
|
|
64
80
|
setOpen(!openState);
|
|
65
81
|
onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(!openState);
|
|
66
82
|
}
|
|
67
|
-
}, children: [_jsx("h3", { children: title }), _jsx("div", { className: "section-line" }), !!allowCollapse ? (_jsx(ChevronDownIcon, { size: 18, className: openState ? "open" : "" })) : ("")] }), _jsx("div", { className: "section-content", "data-open": openState, children: children })] }));
|
|
83
|
+
}, children: [Icon && _jsx(Icon, { size: resolveIconSize(size), color: iconColor }), _jsx("h3", { children: title }), _jsx("div", { className: "section-line" }), !!allowCollapse ? (_jsx(ChevronDownIcon, { size: 18, className: openState ? "open" : "" })) : ("")] }), _jsx("div", { className: "section-content", "data-open": openState, children: children })] }));
|
|
68
84
|
};
|
|
69
85
|
export default FormSection;
|
|
@@ -160,14 +160,62 @@ const StyledItem = styled.div `
|
|
|
160
160
|
color: ${(props) => props.theme.palette.text.primary};
|
|
161
161
|
}
|
|
162
162
|
`;
|
|
163
|
+
/**
|
|
164
|
+
*
|
|
165
|
+
* Attempts to resolve the value to an Option object
|
|
166
|
+
* if the value is a string, it will attempt to find the corresponding Option object
|
|
167
|
+
* if the value is an Option object, it will attempt to find the corresponding Option object
|
|
168
|
+
* if the value is not found, it will return the value as is so that custom values can be displayed without a lookup
|
|
169
|
+
*/
|
|
170
|
+
const resolveValue = (value, data) => {
|
|
171
|
+
if (value === undefined)
|
|
172
|
+
return undefined;
|
|
173
|
+
let foundOption = null;
|
|
174
|
+
if (typeof value === "string") {
|
|
175
|
+
foundOption = data.find((item) => item.value === value);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
foundOption = data.find((item) => item.value === value.value);
|
|
179
|
+
}
|
|
180
|
+
if (foundOption)
|
|
181
|
+
return foundOption;
|
|
182
|
+
if (typeof value === "string") {
|
|
183
|
+
return { value, label: value };
|
|
184
|
+
}
|
|
185
|
+
return value;
|
|
186
|
+
};
|
|
163
187
|
const SelectBox = styled(({ className, data = [], placeholder = "Select...", arrow = true, onChange, onSearch, searchFn, onScroll, loading, defaultValue, value, onItemAdded, size = "sm", variant = "outlined", width = "100%", allowCustomValue = false, searchable = false, clearable = false, label, description, required = false, error, openOnFocus = true, renderOption, actionComponent, focused, grouped, OptionTooltip, // Custom tooltip component for search menu items
|
|
164
188
|
DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
165
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
189
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
166
190
|
const theme = useTheme();
|
|
167
191
|
const isObjectArray = (_a = Object.keys((data === null || data === void 0 ? void 0 : data[0]) || {})) === null || _a === void 0 ? void 0 : _a.includes("label");
|
|
168
|
-
const
|
|
192
|
+
const isControlled = value !== undefined;
|
|
193
|
+
const resolvedOptions = data.map((item) => ({
|
|
194
|
+
value: isObjectArray ? item.value : item,
|
|
195
|
+
label: isObjectArray ? item.label : item,
|
|
196
|
+
group: isObjectArray ? item.group : undefined,
|
|
197
|
+
data: isObjectArray ? item.data : undefined,
|
|
198
|
+
}));
|
|
199
|
+
/**
|
|
200
|
+
* Get the correct option if the default value is a string
|
|
201
|
+
* otherwise, use the default value as is
|
|
202
|
+
* this allows setting the value with a string or Option object
|
|
203
|
+
*/
|
|
204
|
+
const resolvedDefaultValue = resolveValue(defaultValue, resolvedOptions);
|
|
205
|
+
/**
|
|
206
|
+
* Get the correct option if the value is a string
|
|
207
|
+
* otherwise, use the value as is
|
|
208
|
+
* this allows setting the value with a string or Option object
|
|
209
|
+
*/
|
|
210
|
+
const resolvedValue = resolveValue(value, resolvedOptions);
|
|
211
|
+
const [valueState, setValueState] = useState(resolvedDefaultValue);
|
|
212
|
+
/**
|
|
213
|
+
* Get the correct value based on whether the component is controlled or not
|
|
214
|
+
* if controlled, use the controlled value, otherwise use the resolved value
|
|
215
|
+
*/
|
|
216
|
+
const _value = isControlled ? resolvedValue : valueState;
|
|
217
|
+
const [inputValue, setInputValue] = useState((_value === null || _value === void 0 ? void 0 : _value.label) || "");
|
|
169
218
|
const [isOpen, setIsOpen] = useState(false);
|
|
170
|
-
const [selected, setSelected] = useState(null);
|
|
171
219
|
const [searchValue, setSearchValue] = useState("");
|
|
172
220
|
const [customItems, setCustomItems] = useState([]);
|
|
173
221
|
const [placement, setPlacement] = useState("bottom-start");
|
|
@@ -176,18 +224,17 @@ DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
|
176
224
|
const containerRef = useRef(null);
|
|
177
225
|
const scrollContainerRef = useRef(null);
|
|
178
226
|
// Remove duplicates from search dropdown data
|
|
179
|
-
const uniqueItems = Array.from(new Map([...
|
|
180
|
-
isObjectArray ? item.value : item,
|
|
181
|
-
item,
|
|
182
|
-
])).values());
|
|
227
|
+
const uniqueItems = Array.from(new Map([...resolvedOptions, ...customItems].map((item) => [item.value, item])).values());
|
|
183
228
|
// search filter for dropdown items
|
|
184
229
|
const filteredItems = uniqueItems
|
|
185
230
|
.filter((item) => {
|
|
186
|
-
|
|
187
|
-
return
|
|
231
|
+
var _a;
|
|
232
|
+
return (_a = item.label) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(searchValue.toLowerCase());
|
|
188
233
|
})
|
|
189
234
|
.sort((a, b) => {
|
|
190
235
|
if (grouped) {
|
|
236
|
+
if (!a.group || !b.group)
|
|
237
|
+
return 0;
|
|
191
238
|
const aValue = a.group;
|
|
192
239
|
const bValue = b.group;
|
|
193
240
|
return aValue.localeCompare(bValue);
|
|
@@ -195,8 +242,8 @@ DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
|
195
242
|
if (!sort)
|
|
196
243
|
return 0;
|
|
197
244
|
// Secondary sort by label/value to ensure consistent ordering
|
|
198
|
-
const aLabel =
|
|
199
|
-
const bLabel =
|
|
245
|
+
const aLabel = a.label;
|
|
246
|
+
const bLabel = b.label;
|
|
200
247
|
return aLabel.localeCompare(bLabel);
|
|
201
248
|
});
|
|
202
249
|
const groupedItems = grouped
|
|
@@ -242,8 +289,8 @@ DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
|
242
289
|
};
|
|
243
290
|
const handleInputChange = (e) => {
|
|
244
291
|
const value = e.target.value;
|
|
292
|
+
setInputValue(value || "");
|
|
245
293
|
debouncedHandleChange(value);
|
|
246
|
-
setInputValue(value);
|
|
247
294
|
setIsOpen(true);
|
|
248
295
|
};
|
|
249
296
|
const debouncedHandleChange = useDebouncedCallback((value) => {
|
|
@@ -254,9 +301,7 @@ DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
|
254
301
|
setSearchValue(value);
|
|
255
302
|
}
|
|
256
303
|
if (allowCustomValue && value) {
|
|
257
|
-
const existingItem =
|
|
258
|
-
? item.label.toLowerCase() === value.toLowerCase()
|
|
259
|
-
: item.toLowerCase() === value.toLowerCase());
|
|
304
|
+
const existingItem = resolvedOptions.find((item) => item.value.toLowerCase() === value.toLowerCase());
|
|
260
305
|
if (existingItem)
|
|
261
306
|
handleChangeSelection(existingItem);
|
|
262
307
|
else
|
|
@@ -265,23 +310,21 @@ DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
|
265
310
|
update();
|
|
266
311
|
}, debounceTime);
|
|
267
312
|
const handleBlur = () => {
|
|
268
|
-
var _a, _b;
|
|
269
313
|
// add custom value if prop is set
|
|
270
314
|
// and input value is not empty
|
|
271
315
|
// and no item is selected
|
|
272
|
-
if (allowCustomValue && !
|
|
273
|
-
handleAddItem(
|
|
316
|
+
if (allowCustomValue && !_value && !!inputValue) {
|
|
317
|
+
handleAddItem(inputValue);
|
|
274
318
|
}
|
|
275
319
|
setIsOpen(false);
|
|
276
320
|
setSearchValue("");
|
|
277
321
|
};
|
|
278
322
|
const handleClear = (e) => {
|
|
279
323
|
e.preventDefault();
|
|
280
|
-
|
|
281
|
-
inputRef.current.value = "";
|
|
324
|
+
setInputValue("");
|
|
282
325
|
setIsOpen(false);
|
|
283
326
|
handleChangeSelection(null);
|
|
284
|
-
|
|
327
|
+
!isControlled && setValueState(null);
|
|
285
328
|
setSearchValue("");
|
|
286
329
|
searchFn === null || searchFn === void 0 ? void 0 : searchFn("");
|
|
287
330
|
update();
|
|
@@ -295,23 +338,21 @@ DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
|
295
338
|
setIsOpen(false);
|
|
296
339
|
};
|
|
297
340
|
const handleChangeSelection = useCallback((option) => {
|
|
298
|
-
|
|
299
|
-
onChange === null || onChange === void 0 ? void 0 : onChange((option === null || option === void 0 ? void 0 : option.value) ||
|
|
341
|
+
!isControlled && setValueState(option);
|
|
342
|
+
onChange === null || onChange === void 0 ? void 0 : onChange((option === null || option === void 0 ? void 0 : option.value) || null, option);
|
|
300
343
|
}, [onChange]);
|
|
301
344
|
const handleAddItem = useCallback((newItem) => {
|
|
302
|
-
const newValue =
|
|
303
|
-
? { label: newItem, value: newItem }
|
|
304
|
-
: newItem;
|
|
345
|
+
const newValue = { label: newItem, value: newItem };
|
|
305
346
|
setCustomItems((prev) => [...prev, newValue]);
|
|
306
347
|
handleChangeSelection(newValue);
|
|
307
348
|
onItemAdded === null || onItemAdded === void 0 ? void 0 : onItemAdded(newValue);
|
|
308
349
|
}, [onItemAdded, isObjectArray, handleChangeSelection]);
|
|
309
350
|
const handleKeyDown = (e) => {
|
|
310
|
-
var _a
|
|
311
|
-
const currentInputValue =
|
|
351
|
+
var _a;
|
|
352
|
+
const currentInputValue = inputValue;
|
|
312
353
|
// Escape key
|
|
313
354
|
if (e.key === "Escape") {
|
|
314
|
-
const reference = (
|
|
355
|
+
const reference = (_a = refs === null || refs === void 0 ? void 0 : refs.reference) === null || _a === void 0 ? void 0 : _a.current;
|
|
315
356
|
reference === null || reference === void 0 ? void 0 : reference.blur();
|
|
316
357
|
setSearchValue("");
|
|
317
358
|
update();
|
|
@@ -326,52 +367,41 @@ DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
|
326
367
|
// Arrow down
|
|
327
368
|
if (e.key === "ArrowDown") {
|
|
328
369
|
e.preventDefault();
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
onChange === null || onChange === void 0 ? void 0 : onChange((newItem === null || newItem === void 0 ? void 0 : newItem.value) || newItem, newItem);
|
|
338
|
-
return newItem;
|
|
339
|
-
});
|
|
370
|
+
let newItem = filteredItems[0]; // Loop back to the first item
|
|
371
|
+
const index = filteredItems.findIndex((item) => item.value === (_value === null || _value === void 0 ? void 0 : _value.value));
|
|
372
|
+
if (index < filteredItems.length - 1) {
|
|
373
|
+
newItem = filteredItems[index + 1];
|
|
374
|
+
}
|
|
375
|
+
!isControlled && setValueState(newItem);
|
|
376
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newItem.value, newItem);
|
|
340
377
|
return;
|
|
341
378
|
}
|
|
342
379
|
// Arrow up
|
|
343
380
|
if (e.key === "ArrowUp") {
|
|
344
381
|
e.preventDefault();
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
}
|
|
353
|
-
onChange === null || onChange === void 0 ? void 0 : onChange((newItem === null || newItem === void 0 ? void 0 : newItem.value) || newItem, newItem);
|
|
354
|
-
return newItem;
|
|
355
|
-
});
|
|
382
|
+
let newItem = filteredItems[filteredItems.length - 1]; // Loop back to the last item
|
|
383
|
+
const index = filteredItems.findIndex((item) => item.value === (_value === null || _value === void 0 ? void 0 : _value.value));
|
|
384
|
+
if (index > 0) {
|
|
385
|
+
newItem = filteredItems[index - 1];
|
|
386
|
+
}
|
|
387
|
+
!isControlled && setValueState(newItem);
|
|
388
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newItem.value, newItem);
|
|
356
389
|
return;
|
|
357
390
|
}
|
|
358
391
|
// Tab key
|
|
359
392
|
if (e.key === "Tab") {
|
|
360
|
-
if (allowCustomValue && !
|
|
393
|
+
if (allowCustomValue && !_value && !!currentInputValue) {
|
|
361
394
|
handleAddItem(currentInputValue);
|
|
362
395
|
setSearchValue("");
|
|
363
396
|
}
|
|
364
|
-
else if (!
|
|
397
|
+
else if (!_value) {
|
|
365
398
|
// clear input
|
|
366
|
-
|
|
367
|
-
inputRef.current.value = "";
|
|
368
|
-
}
|
|
399
|
+
setInputValue("");
|
|
369
400
|
}
|
|
370
401
|
setSearchValue("");
|
|
371
402
|
setIsOpen(false);
|
|
372
403
|
return;
|
|
373
404
|
}
|
|
374
|
-
// setSelected(null); // Reset selected value when input value changes
|
|
375
405
|
};
|
|
376
406
|
const handleFocus = () => {
|
|
377
407
|
if (openOnFocus) {
|
|
@@ -407,26 +437,13 @@ DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
|
407
437
|
document.addEventListener("click", close);
|
|
408
438
|
return () => document.removeEventListener("click", close);
|
|
409
439
|
}, [refs.floating, refs.reference, handleBlur]);
|
|
410
|
-
// Handle default value
|
|
411
|
-
useEffect(() => {
|
|
412
|
-
if (defaultValue) {
|
|
413
|
-
const isOption = defaultValue.value !== undefined;
|
|
414
|
-
const searchPattern = isOption
|
|
415
|
-
? defaultValue.value
|
|
416
|
-
: defaultValue;
|
|
417
|
-
setSelected(data.find((item) => isObjectArray
|
|
418
|
-
? item.value === searchPattern
|
|
419
|
-
: item === searchPattern) || null);
|
|
420
|
-
}
|
|
421
|
-
}, [data, defaultValue, isObjectArray]);
|
|
422
440
|
// handle input value change
|
|
423
441
|
useEffect(() => {
|
|
424
|
-
if (
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
: selected;
|
|
442
|
+
if (_value) {
|
|
443
|
+
const newValue = _value.label;
|
|
444
|
+
setInputValue(newValue || "");
|
|
428
445
|
}
|
|
429
|
-
}, [
|
|
446
|
+
}, [_value]);
|
|
430
447
|
// handle scroll item into view
|
|
431
448
|
useEffect(() => {
|
|
432
449
|
var _a, _b;
|
|
@@ -434,7 +451,7 @@ DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
|
434
451
|
if (item) {
|
|
435
452
|
item.scrollIntoView({ block: "nearest" });
|
|
436
453
|
}
|
|
437
|
-
}, [
|
|
454
|
+
}, [_value]);
|
|
438
455
|
// make calls to onSearch callback
|
|
439
456
|
useEffect(() => {
|
|
440
457
|
if (searchable) {
|
|
@@ -456,7 +473,7 @@ DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
|
456
473
|
setDropDownHeight(bottomHeight);
|
|
457
474
|
};
|
|
458
475
|
}, [topHeight, bottomHeight, isOpen]);
|
|
459
|
-
return (_jsxs("div", { className: className, children: [label && (_jsx(FieldLabel, { error: error, asterisk: required, size: size, description: description, children: label })), _jsxs(StyledInputContainer, { ref: refs.setReference, onMouseDown: () => setIsOpen(true), width: width, onKeyDown: handleKeyDown, "data-open": isOpen, children: [_jsx(Input, { ref: inputRef, onChange: handleInputChange, onFocus: handleFocus, autoFocus: focused, placeholder: placeholder, size: size, readOnly: !searchable, "data-button-right": arrow || clearable, style: isOpen ? { borderColor: theme.palette.primary.main } : {} }), clearable && (
|
|
476
|
+
return (_jsxs("div", { className: className, children: [label && (_jsx(FieldLabel, { error: error, asterisk: required, size: size, description: description, children: label })), _jsxs(StyledInputContainer, { ref: refs.setReference, onMouseDown: () => setIsOpen(true), width: width, onKeyDown: handleKeyDown, "data-open": isOpen, children: [_jsx(Input, { ref: inputRef, value: inputValue, onChange: handleInputChange, onFocus: handleFocus, autoFocus: focused, placeholder: placeholder, size: size, readOnly: !searchable && !allowCustomValue, "data-button-right": arrow || clearable, style: isOpen ? { borderColor: theme.palette.primary.main } : {} }), clearable && (_value || !!inputValue) ? (_jsx(ClearButton, { className: "input-btn", onClick: handleClear, onMouseDown: (e) => {
|
|
460
477
|
e.preventDefault();
|
|
461
478
|
e.stopPropagation();
|
|
462
479
|
} })) : arrow ? (_jsx(ArrowButton, { onClick: (e) => {
|
|
@@ -476,16 +493,10 @@ DropDownProps = {}, debounceTime = 150, sort = false, }) => {
|
|
|
476
493
|
: "",
|
|
477
494
|
}, variant: variant, "data-empty": filteredItems.length === 0 }, DropDownProps, { children: [loading && _jsx(Loader, {}), !loading && actionComponent && (_jsx(ActionMenu, { children: actionComponent })), !loading && filteredItems.length === 0 && (_jsx(EmptyComponent, { children: "No Items" })), !loading && (_jsx(StyledInnerItemContainer, { ref: scrollContainerRef, "data-scroll-active": scrollActive, onScroll: onScroll, children: grouped
|
|
478
495
|
? groups.map((group, index) => (_jsxs("div", { children: [_jsx(GroupTitle, { size: size, children: group.label }), group.items.map((item, index) => {
|
|
479
|
-
return (_jsx(Tooltip, { content: OptionTooltip ? (_jsx(OptionTooltip, { data: item.data })) : null, side: "left", children: _jsx(StyledItem, { className: "mfFloatingItem", onClick: (e) => handleItemClick(e, item), "data-selected":
|
|
480
|
-
? (selected === null || selected === void 0 ? void 0 : selected.value) ===
|
|
481
|
-
item.value
|
|
482
|
-
: selected === item, size: size, children: (renderOption === null || renderOption === void 0 ? void 0 : renderOption(item)) || (_jsx(_Fragment, { children: (item === null || item === void 0 ? void 0 : item.label) || item })) }, index) }, index));
|
|
496
|
+
return (_jsx(Tooltip, { content: OptionTooltip ? (_jsx(OptionTooltip, { data: item.data })) : null, side: "left", children: _jsx(StyledItem, { className: "mfFloatingItem", onClick: (e) => handleItemClick(e, item), "data-selected": (_value === null || _value === void 0 ? void 0 : _value.value) === item.value, size: size, children: (renderOption === null || renderOption === void 0 ? void 0 : renderOption(item)) || _jsx(_Fragment, { children: item === null || item === void 0 ? void 0 : item.label }) }, index) }, index));
|
|
483
497
|
})] }, group.label)))
|
|
484
498
|
: filteredItems.map((item, index) => {
|
|
485
|
-
return (_jsx(Tooltip, { content: OptionTooltip ? (_jsx(OptionTooltip, { data: item.data })) : null, side: "left", children: _jsx(StyledItem, { className: "mfFloatingItem", onClick: (e) => handleItemClick(e, item), "data-selected":
|
|
486
|
-
? (selected === null || selected === void 0 ? void 0 : selected.value) ===
|
|
487
|
-
(item === null || item === void 0 ? void 0 : item.value)
|
|
488
|
-
: selected === item, size: size, children: (renderOption === null || renderOption === void 0 ? void 0 : renderOption(item)) || (_jsx(_Fragment, { children: (item === null || item === void 0 ? void 0 : item.label) || item })) }, index) }, index));
|
|
499
|
+
return (_jsx(Tooltip, { content: OptionTooltip ? (_jsx(OptionTooltip, { data: item.data })) : null, side: "left", children: _jsx(StyledItem, { className: "mfFloatingItem", onClick: (e) => handleItemClick(e, item), "data-selected": (_value === null || _value === void 0 ? void 0 : _value.value) === item.value, size: size, children: (renderOption === null || renderOption === void 0 ? void 0 : renderOption(item)) || _jsx(_Fragment, { children: item === null || item === void 0 ? void 0 : item.label }) }, index) }, index));
|
|
489
500
|
}) }))] })) }) }))] }));
|
|
490
501
|
}) `
|
|
491
502
|
position: relative;
|
|
@@ -34,9 +34,9 @@ export interface SelectBoxProps {
|
|
|
34
34
|
OptionTooltip?: (props: {
|
|
35
35
|
data: any;
|
|
36
36
|
}) => JSX.Element | React.ReactNode;
|
|
37
|
-
onChange?: (value:
|
|
37
|
+
onChange?: (value: string | null, item: Option | string | null) => void;
|
|
38
38
|
onScroll?: (e: any) => void;
|
|
39
39
|
onSearch?: (value: string) => void;
|
|
40
40
|
searchFn?: (value: string) => void;
|
|
41
|
-
onItemAdded?: (item:
|
|
41
|
+
onItemAdded?: (item: Option | string) => void;
|
|
42
42
|
}
|
package/dist/TagBox/TagBox.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { TagBoxProps } from "./types";
|
|
2
|
-
declare const TagBox: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<TagBoxProps, never>> & string & Omit<({ className, data, placeholder, arrow, defaultValue, value, grouped, searchFn, onChange, onScroll, onSearch, onItemAdded, size, variant, width, allowCustomValue, searchable, clearable, openOnFocus, label, description, required, error, loading, sort, renderOption, OptionTooltip, }: TagBoxProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
|
|
2
|
+
declare const TagBox: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<TagBoxProps, never>> & string & Omit<({ className, data, placeholder, arrow, defaultValue, value, grouped, searchFn, onChange, onScroll, onSearch, onItemAdded, size, variant, width, allowCustomValue, searchable, clearable, openOnFocus, label, description, required, error, loading, sort, renderOption, OptionTooltip, DropDownProps, }: TagBoxProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
|
|
3
3
|
export default TagBox;
|
package/dist/TagBox/TagBox.js
CHANGED
|
@@ -11,8 +11,8 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
13
|
import styled from "styled-components";
|
|
14
|
-
import { useFloating, flip, offset, autoUpdate } from "@floating-ui/react";
|
|
15
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
14
|
+
import { useFloating, flip, offset, autoUpdate, FloatingPortal, } from "@floating-ui/react";
|
|
15
|
+
import { useCallback, useEffect, useRef, useState, } from "react";
|
|
16
16
|
import { Input, Tooltip, FieldLabel, Pill, Loader } from "..";
|
|
17
17
|
import { ArrowButton, ClearButton, StyledFloatContainer, StyledContent, } from "../core";
|
|
18
18
|
const StyledInputContainer = styled.div `
|
|
@@ -138,6 +138,13 @@ const StyledInputContainer = styled.div `
|
|
|
138
138
|
border: 1px solid ${(props) => props.theme.palette.primary.main};
|
|
139
139
|
}
|
|
140
140
|
`;
|
|
141
|
+
const StyledInnerItemContainer = styled.div `
|
|
142
|
+
overflow-y: auto;
|
|
143
|
+
|
|
144
|
+
&[data-scroll-active="true"] {
|
|
145
|
+
padding-right: 5px;
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
141
148
|
// styled input with forwardRef
|
|
142
149
|
const StyledInput = styled((_a) => {
|
|
143
150
|
var { className, inputRef } = _a, props = __rest(_a, ["className", "inputRef"]);
|
|
@@ -234,9 +241,6 @@ const StyledInnerContainer = styled.div `
|
|
|
234
241
|
padding-right: 30px;
|
|
235
242
|
}
|
|
236
243
|
`;
|
|
237
|
-
const ExtendedStyledContent = styled(StyledContent) `
|
|
238
|
-
overflow-y: auto;
|
|
239
|
-
`;
|
|
240
244
|
const StyledItem = styled.div `
|
|
241
245
|
line-height: 1;
|
|
242
246
|
color: ${(props) => props.theme.palette.text.primary};
|
|
@@ -292,30 +296,85 @@ const EmptyComponent = styled.div `
|
|
|
292
296
|
font-size: 1 rem;
|
|
293
297
|
color: ${(props) => props.theme.palette.text.secondary};
|
|
294
298
|
`;
|
|
295
|
-
|
|
299
|
+
/**
|
|
300
|
+
*
|
|
301
|
+
* Attempts to resolve the value to an Option object
|
|
302
|
+
* if the value is a string, it will attempt to find the corresponding Option object
|
|
303
|
+
* if the value is an Option object, it will attempt to find the corresponding Option object
|
|
304
|
+
* if the value is not found, it will return the value as is so that custom values can be displayed without a lookup
|
|
305
|
+
*/
|
|
306
|
+
const resolveValues = (value, data) => {
|
|
307
|
+
if (value === undefined)
|
|
308
|
+
return undefined;
|
|
309
|
+
const resolvedValues = [];
|
|
310
|
+
for (const item of value) {
|
|
311
|
+
if (typeof item === "string") {
|
|
312
|
+
const found = data.find((option) => option.value === item);
|
|
313
|
+
resolvedValues.push(found || { value: item, label: item });
|
|
314
|
+
}
|
|
315
|
+
else if (typeof item === "object") {
|
|
316
|
+
const found = data.find((option) => option.value === item.value);
|
|
317
|
+
resolvedValues.push(found || item);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return resolvedValues;
|
|
321
|
+
};
|
|
322
|
+
const TagBox = styled(({ className, data = [], placeholder = "Select tags", arrow = true, defaultValue, value, grouped, searchFn, onChange, onScroll, onSearch, onItemAdded, size = "sm", variant = "outlined", width = "100%", allowCustomValue = false, searchable = false, clearable = false, openOnFocus = true, label, description, required = false, error, loading = false, sort = false, renderOption, OptionTooltip, DropDownProps = {}, }) => {
|
|
296
323
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
297
324
|
const isObjectArray = (_a = data === null || data === void 0 ? void 0 : data[0]) === null || _a === void 0 ? void 0 : _a.hasOwnProperty("label");
|
|
325
|
+
const isControlled = value !== undefined;
|
|
326
|
+
/**
|
|
327
|
+
* Resolve the options to a consistent format
|
|
328
|
+
* also remove duplicates
|
|
329
|
+
*/
|
|
330
|
+
const resolvedOptions = Array.from(new Map(data
|
|
331
|
+
.map((item) => ({
|
|
332
|
+
value: isObjectArray ? item.value : item,
|
|
333
|
+
label: isObjectArray ? item.label : item,
|
|
334
|
+
group: isObjectArray ? item.group : undefined,
|
|
335
|
+
data: isObjectArray ? item.data : undefined,
|
|
336
|
+
}))
|
|
337
|
+
.map((item) => [item.value, item])).values());
|
|
338
|
+
/**
|
|
339
|
+
* Get the correct option if the default value is a string
|
|
340
|
+
* otherwise, use the default value as is
|
|
341
|
+
* this allows setting the value with a string or Option object
|
|
342
|
+
*/
|
|
343
|
+
const resolvedDefaultValue = resolveValues(defaultValue, resolvedOptions);
|
|
344
|
+
/**
|
|
345
|
+
* Get the correct option if the value is a string
|
|
346
|
+
* otherwise, use the value as is
|
|
347
|
+
* this allows setting the value with a string or Option object
|
|
348
|
+
*/
|
|
349
|
+
const resolvedValue = resolveValues(value, resolvedOptions);
|
|
350
|
+
const [valueState, setValueState] = useState(resolvedDefaultValue || []);
|
|
351
|
+
/**
|
|
352
|
+
* Get the correct value based on whether the component is controlled or not
|
|
353
|
+
* if controlled, use the controlled value, otherwise use the resolved value
|
|
354
|
+
*/
|
|
355
|
+
const _value = (isControlled ? resolvedValue : valueState) || [];
|
|
298
356
|
const [isOpen, setIsOpen] = useState(false);
|
|
299
|
-
const [
|
|
300
|
-
const [preSelected, setPreSelected] = useState(null);
|
|
357
|
+
const [preSelected, setPreSelected] = useState();
|
|
301
358
|
const [customItems, setCustomItems] = useState([]);
|
|
302
359
|
const [searchValue, setSearchValue] = useState("");
|
|
360
|
+
const [placement, setPlacement] = useState("bottom-start");
|
|
361
|
+
const [dropDownHeight, setDropDownHeight] = useState(null);
|
|
303
362
|
const inputRef = useRef(null);
|
|
363
|
+
const containerRef = useRef(null);
|
|
304
364
|
const scrollContainerRef = useRef(null);
|
|
305
|
-
const filteredItems =
|
|
365
|
+
const filteredItems = resolvedOptions
|
|
306
366
|
.concat(customItems) // Add custom items to the list
|
|
307
367
|
.filter((item) => {
|
|
308
|
-
const isSelected = !!(
|
|
309
|
-
? selectedItem.value === item.value
|
|
310
|
-
: selectedItem === item));
|
|
368
|
+
const isSelected = !!(_value === null || _value === void 0 ? void 0 : _value.find((selectedItem) => selectedItem.value === item.value));
|
|
311
369
|
return !isSelected;
|
|
312
370
|
})
|
|
313
371
|
.filter((item) => {
|
|
314
|
-
|
|
315
|
-
return itemValue.toLowerCase().includes(searchValue.toLowerCase());
|
|
372
|
+
return item.value.toLowerCase().includes(searchValue.toLowerCase());
|
|
316
373
|
})
|
|
317
374
|
.sort((a, b) => {
|
|
318
375
|
if (grouped) {
|
|
376
|
+
if (!a.group || !b.group)
|
|
377
|
+
return 0;
|
|
319
378
|
const aValue = a.group;
|
|
320
379
|
const bValue = b.group;
|
|
321
380
|
return aValue.localeCompare(bValue);
|
|
@@ -323,8 +382,8 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
323
382
|
if (!sort)
|
|
324
383
|
return 0;
|
|
325
384
|
// Secondary sort by label/value to ensure consistent ordering
|
|
326
|
-
const aLabel =
|
|
327
|
-
const bLabel =
|
|
385
|
+
const aLabel = a.label;
|
|
386
|
+
const bLabel = b.label;
|
|
328
387
|
return aLabel.localeCompare(bLabel);
|
|
329
388
|
});
|
|
330
389
|
const groupedItems = grouped
|
|
@@ -375,17 +434,16 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
375
434
|
if (inputRef === null || inputRef === void 0 ? void 0 : inputRef.current)
|
|
376
435
|
inputRef.current.value = "";
|
|
377
436
|
onChange === null || onChange === void 0 ? void 0 : onChange([]);
|
|
378
|
-
|
|
437
|
+
!isControlled && setValueState([]);
|
|
379
438
|
setSearchValue("");
|
|
380
439
|
searchFn === null || searchFn === void 0 ? void 0 : searchFn("");
|
|
381
440
|
setIsOpen(false);
|
|
382
441
|
};
|
|
383
442
|
const handleChangeSelection = useCallback((option) => {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}, [onChange]);
|
|
443
|
+
const newValue = [..._value, option];
|
|
444
|
+
!isControlled && setValueState(newValue);
|
|
445
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
|
|
446
|
+
}, [onChange, _value]);
|
|
389
447
|
const handleFocus = () => {
|
|
390
448
|
var _a, _b;
|
|
391
449
|
if (openOnFocus) {
|
|
@@ -405,35 +463,26 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
405
463
|
setSearchValue("");
|
|
406
464
|
handleChangeSelection(item);
|
|
407
465
|
};
|
|
408
|
-
const handleRemoveItem = (item
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
: idx !== index);
|
|
413
|
-
onChange === null || onChange === void 0 ? void 0 : onChange(newItems);
|
|
414
|
-
return newItems;
|
|
415
|
-
});
|
|
466
|
+
const handleRemoveItem = (item) => {
|
|
467
|
+
const newItems = _value.filter((prevItem, idx) => prevItem.value !== item.value);
|
|
468
|
+
!isControlled && setValueState(newItems);
|
|
469
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newItems);
|
|
416
470
|
};
|
|
417
471
|
const handleAddItem = useCallback((newItem) => {
|
|
418
|
-
const existingItem =
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
472
|
+
const existingItem = resolvedOptions
|
|
473
|
+
.concat(customItems)
|
|
474
|
+
.find((item) => {
|
|
475
|
+
return item.label.toLowerCase() === newItem.toLowerCase();
|
|
422
476
|
});
|
|
423
477
|
if (!existingItem) {
|
|
424
|
-
const newValue =
|
|
425
|
-
? { label: newItem, value: newItem }
|
|
426
|
-
: newItem;
|
|
478
|
+
const newValue = { label: newItem, value: newItem }; // Create a new option object
|
|
427
479
|
setCustomItems([...customItems, newValue]);
|
|
428
480
|
handleChangeSelection(newValue);
|
|
429
481
|
onItemAdded === null || onItemAdded === void 0 ? void 0 : onItemAdded(newValue);
|
|
430
482
|
}
|
|
431
483
|
else {
|
|
432
484
|
// check if the item is already selected
|
|
433
|
-
const isSelected = !!
|
|
434
|
-
? selectedItem.value ===
|
|
435
|
-
existingItem.value
|
|
436
|
-
: selectedItem === existingItem);
|
|
485
|
+
const isSelected = !!_value.find((selectedItem) => selectedItem.value === existingItem.value);
|
|
437
486
|
if (!isSelected) {
|
|
438
487
|
handleChangeSelection(existingItem);
|
|
439
488
|
}
|
|
@@ -441,9 +490,9 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
441
490
|
}, [
|
|
442
491
|
onItemAdded,
|
|
443
492
|
isObjectArray,
|
|
444
|
-
|
|
493
|
+
resolvedOptions,
|
|
445
494
|
handleChangeSelection,
|
|
446
|
-
|
|
495
|
+
_value,
|
|
447
496
|
customItems,
|
|
448
497
|
]);
|
|
449
498
|
const handleKeyDown = (e) => {
|
|
@@ -461,7 +510,7 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
461
510
|
if (e.key === "Enter") {
|
|
462
511
|
if (preSelected) {
|
|
463
512
|
handleItemClick(preSelected);
|
|
464
|
-
setPreSelected(
|
|
513
|
+
setPreSelected(undefined);
|
|
465
514
|
setSearchValue("");
|
|
466
515
|
update();
|
|
467
516
|
return;
|
|
@@ -482,20 +531,16 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
482
531
|
}
|
|
483
532
|
// Backspace key
|
|
484
533
|
if (e.key === "Backspace" && currentInputValue === "") {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
return newItems;
|
|
489
|
-
});
|
|
534
|
+
const newItems = _value === null || _value === void 0 ? void 0 : _value.slice(0, _value.length - 1);
|
|
535
|
+
!isControlled && setValueState(newItems);
|
|
536
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newItems);
|
|
490
537
|
}
|
|
491
538
|
// Arrow down
|
|
492
539
|
if (e.key === "ArrowDown") {
|
|
493
540
|
e.preventDefault();
|
|
494
541
|
setPreSelected((prev) => {
|
|
495
542
|
let newItem = filteredItems[0]; // Loop back to the first item
|
|
496
|
-
const index = filteredItems.findIndex((item) =>
|
|
497
|
-
? item.value === (prev === null || prev === void 0 ? void 0 : prev.value)
|
|
498
|
-
: item === prev);
|
|
543
|
+
const index = filteredItems.findIndex((item) => item.value === (prev === null || prev === void 0 ? void 0 : prev.value));
|
|
499
544
|
if (index < filteredItems.length - 1) {
|
|
500
545
|
newItem = filteredItems[index + 1];
|
|
501
546
|
}
|
|
@@ -507,9 +552,7 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
507
552
|
e.preventDefault();
|
|
508
553
|
setPreSelected((prev) => {
|
|
509
554
|
let newItem = filteredItems[filteredItems.length - 1]; // Loop back to the last item
|
|
510
|
-
const index = filteredItems.findIndex((item) =>
|
|
511
|
-
? item.value === (prev === null || prev === void 0 ? void 0 : prev.value)
|
|
512
|
-
: item === prev);
|
|
555
|
+
const index = filteredItems.findIndex((item) => item.value === (prev === null || prev === void 0 ? void 0 : prev.value));
|
|
513
556
|
if (index > 0) {
|
|
514
557
|
newItem = filteredItems[index - 1];
|
|
515
558
|
}
|
|
@@ -521,6 +564,14 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
521
564
|
setIsOpen(false);
|
|
522
565
|
}
|
|
523
566
|
};
|
|
567
|
+
// handle scroll item into view
|
|
568
|
+
useEffect(() => {
|
|
569
|
+
var _a, _b;
|
|
570
|
+
const item = (_b = (_a = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current) === null || _a === void 0 ? void 0 : _a.querySelector) === null || _b === void 0 ? void 0 : _b.call(_a, ".mfFloatingItem[data-highlighted=true]");
|
|
571
|
+
if (item) {
|
|
572
|
+
item.scrollIntoView({ block: "nearest" });
|
|
573
|
+
}
|
|
574
|
+
}, [preSelected]);
|
|
524
575
|
// Close on outside click
|
|
525
576
|
useEffect(() => {
|
|
526
577
|
const close = (e) => {
|
|
@@ -542,7 +593,7 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
542
593
|
// update when selection changes
|
|
543
594
|
useEffect(() => {
|
|
544
595
|
update();
|
|
545
|
-
}, [
|
|
596
|
+
}, [_value]);
|
|
546
597
|
const referenceEl = (_b = refs === null || refs === void 0 ? void 0 : refs.reference) === null || _b === void 0 ? void 0 : _b.current;
|
|
547
598
|
const contentWidth = ((_e = (_d = (_c = referenceEl === null || referenceEl === void 0 ? void 0 : referenceEl.getClientRects) === null || _c === void 0 ? void 0 : _c.call(referenceEl)) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.width) || "100%";
|
|
548
599
|
const scrollEl = scrollContainerRef === null || scrollContainerRef === void 0 ? void 0 : scrollContainerRef.current;
|
|
@@ -552,9 +603,7 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
552
603
|
return (_jsxs("div", { className: className + " mfTagBox", children: [label && (_jsx(FieldLabel, { error: error, asterisk: required, size: size, description: description, children: label })), _jsxs(StyledInputContainer, { className: "styledInputContainer", ref: refs.setReference, onMouseDown: () => {
|
|
553
604
|
setIsOpen(true);
|
|
554
605
|
handleFocus();
|
|
555
|
-
}, onFocus: handleFocus, size: size, variant: variant, onKeyDown: handleKeyDown, "data-open": isOpen, children: [_jsx(StyledInnerContainer, { size: size, "data-button-right": arrow || clearable, children: _jsxs(PillContainer, { size: size, children: [
|
|
556
|
-
allowCustomValue ||
|
|
557
|
-
(selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length) === 0) && (_jsx(StyledInput, { inputRef: inputRef, onChange: (e) => {
|
|
606
|
+
}, onFocus: handleFocus, size: size, variant: variant, onKeyDown: handleKeyDown, "data-open": isOpen, tabIndex: 0, children: [_jsx(StyledInnerContainer, { size: size, "data-button-right": arrow || clearable, children: _jsxs(PillContainer, { size: size, children: [_value === null || _value === void 0 ? void 0 : _value.map((item, index) => (_jsx(Pill, { size: "xs", onRemove: () => handleRemoveItem(item), children: (renderOption === null || renderOption === void 0 ? void 0 : renderOption(item)) || _jsx(_Fragment, { children: item === null || item === void 0 ? void 0 : item.label }) }, index))), (searchable || allowCustomValue || (_value === null || _value === void 0 ? void 0 : _value.length) === 0) && (_jsx(StyledInput, { inputRef: inputRef, onChange: (e) => {
|
|
558
607
|
if (searchFn !== undefined) {
|
|
559
608
|
searchFn === null || searchFn === void 0 ? void 0 : searchFn(e.target.value);
|
|
560
609
|
}
|
|
@@ -563,7 +612,7 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
563
612
|
}
|
|
564
613
|
update();
|
|
565
614
|
}, placeholder: placeholder, size: size, readOnly: !(searchable || allowCustomValue) }))] }) }), clearable &&
|
|
566
|
-
(((_f =
|
|
615
|
+
(((_f = _value === null || _value === void 0 ? void 0 : _value.length) !== null && _f !== void 0 ? _f : 0) > 0 || !!((_g = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _g === void 0 ? void 0 : _g.value)) ? (_jsx(ClearButton, { onClick: handleClear, onMouseDown: (e) => {
|
|
567
616
|
e.preventDefault();
|
|
568
617
|
e.stopPropagation();
|
|
569
618
|
} })) : arrow ? (_jsx(ArrowButton, { onClick: (e) => {
|
|
@@ -572,27 +621,32 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
|
|
|
572
621
|
e.preventDefault();
|
|
573
622
|
e.stopPropagation();
|
|
574
623
|
toggleOpen();
|
|
575
|
-
} })) : null] }), isOpen && (_jsx(
|
|
576
|
-
|
|
624
|
+
} })) : null] }), isOpen && (_jsx(FloatingPortal, { preserveTabOrder: true, children: _jsx(StyledFloatContainer, { ref: (ref) => {
|
|
625
|
+
containerRef.current = ref;
|
|
626
|
+
refs.setFloating(ref);
|
|
627
|
+
}, style: floatingStyles, className: "mfFloating", children: _jsxs(StyledContent, Object.assign({ className: "mfFloatingContent", style: {
|
|
628
|
+
width: contentWidth,
|
|
629
|
+
maxWidth: contentWidth,
|
|
630
|
+
maxHeight: DropDownProps.autoHeight
|
|
631
|
+
? (dropDownHeight || 250) - 10
|
|
632
|
+
: "",
|
|
633
|
+
}, variant: variant, "data-empty": filteredItems.length === 0 }, DropDownProps, { children: [loading && _jsx(Loader, {}), !loading && filteredItems.length === 0 && (_jsx(EmptyComponent, { children: "No Items" })), !loading && (_jsx(StyledInnerItemContainer, { ref: scrollContainerRef, "data-scroll-active": scrollActive, onScroll: onScroll, children: grouped
|
|
634
|
+
? groups.map((group) => (_jsxs("div", { children: [_jsx(GroupTitle, { size: size, children: group.label }), group.items.map((item, index) => {
|
|
635
|
+
return (_jsx(Tooltip, { content: OptionTooltip ? (_jsx(OptionTooltip, { data: item.data })) : null, side: "left", children: _jsx(StyledItem, { className: "mfFloatingItem", onClick: (e) => {
|
|
636
|
+
e.preventDefault();
|
|
637
|
+
e.stopPropagation();
|
|
638
|
+
handleItemClick(item);
|
|
639
|
+
}, "data-highlighted": (preSelected === null || preSelected === void 0 ? void 0 : preSelected.value) === item.value, size: size, children: (renderOption === null || renderOption === void 0 ? void 0 : renderOption(item)) || (_jsx(_Fragment, { children: typeof item === "string"
|
|
640
|
+
? item
|
|
641
|
+
: item === null || item === void 0 ? void 0 : item.label })) }, index) }, index));
|
|
642
|
+
})] }, group.label)))
|
|
643
|
+
: filteredItems.map((item, index) => {
|
|
577
644
|
return (_jsx(Tooltip, { content: OptionTooltip ? (_jsx(OptionTooltip, { data: item.data })) : null, side: "left", children: _jsx(StyledItem, { className: "mfFloatingItem", onClick: (e) => {
|
|
578
645
|
e.preventDefault();
|
|
579
646
|
e.stopPropagation();
|
|
580
647
|
handleItemClick(item);
|
|
581
|
-
}, "data-highlighted":
|
|
582
|
-
|
|
583
|
-
item.value
|
|
584
|
-
: preSelected === item, size: size, children: (renderOption === null || renderOption === void 0 ? void 0 : renderOption(item)) || (_jsx(_Fragment, { children: (item === null || item === void 0 ? void 0 : item.label) || item })) }, index) }, index));
|
|
585
|
-
})] }, group.label)))
|
|
586
|
-
: filteredItems.map((item, index) => {
|
|
587
|
-
return (_jsx(Tooltip, { content: OptionTooltip ? (_jsx(OptionTooltip, { data: item.data })) : null, side: "left", children: _jsx(StyledItem, { className: "mfFloatingItem", onClick: (e) => {
|
|
588
|
-
e.preventDefault();
|
|
589
|
-
e.stopPropagation();
|
|
590
|
-
handleItemClick(item);
|
|
591
|
-
}, "data-highlighted": isObjectArray
|
|
592
|
-
? (preSelected === null || preSelected === void 0 ? void 0 : preSelected.value) ===
|
|
593
|
-
item.value
|
|
594
|
-
: preSelected === item, size: size, children: (renderOption === null || renderOption === void 0 ? void 0 : renderOption(item)) || (_jsx(_Fragment, { children: (item === null || item === void 0 ? void 0 : item.label) || item })) }, index) }, index));
|
|
595
|
-
})] }) }))] }));
|
|
648
|
+
}, "data-highlighted": (preSelected === null || preSelected === void 0 ? void 0 : preSelected.value) === item.value, size: size, children: (renderOption === null || renderOption === void 0 ? void 0 : renderOption(item)) || _jsx(_Fragment, { children: item === null || item === void 0 ? void 0 : item.label }) }, index) }, index));
|
|
649
|
+
}) }))] })) }) }))] }));
|
|
596
650
|
}) `
|
|
597
651
|
position: relative;
|
|
598
652
|
cursor: pointer;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monolith-forensics/monolith-ui",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.44",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"author": "Matt Danner (Monolith Forensics LLC)",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@uiw/codemirror-theme-vscode": "^4.23.6",
|
|
51
51
|
"@uiw/react-codemirror": "^4.23.6",
|
|
52
52
|
"deepmerge": "^4.3.1",
|
|
53
|
-
"lucide-react": "^0.
|
|
53
|
+
"lucide-react": "^0.469.0",
|
|
54
54
|
"moment": "^2.29.1",
|
|
55
55
|
"overlayscrollbars": "^2.6.0",
|
|
56
56
|
"overlayscrollbars-react": "^0.5.6",
|