@monolith-forensics/monolith-ui 1.1.60 → 1.1.64
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/CalendarStyles.js +1 -1
- package/dist/DateInput/DateInput.d.ts +14 -1
- package/dist/DateInput/DateInput.js +15 -91
- package/dist/SelectBox/SelectBox.d.ts +2 -2
- package/dist/SelectBox/SelectBox.js +125 -92
- package/dist/SelectBox/types.d.ts +3 -2
- package/dist/Utilities/parseTimestamp.d.ts +2 -0
- package/dist/Utilities/parseTimestamp.js +66 -0
- package/package.json +7 -5
|
@@ -51,7 +51,7 @@ export const CalendarDate = styled(CalendarCell) `
|
|
|
51
51
|
grid-row: ${({ index }) => Math.floor((index || 0) / 7) + 2} / span 1;
|
|
52
52
|
transition: all 0.2s ease-out;
|
|
53
53
|
border-radius: 5px;
|
|
54
|
-
|
|
54
|
+
&:hover {
|
|
55
55
|
background: ${({ theme }) => theme.palette.action.hover};
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import moment from "moment";
|
|
1
2
|
import React from "react";
|
|
2
3
|
import { Size, Variant } from "../core";
|
|
3
4
|
interface DateInputProps {
|
|
4
5
|
className?: string;
|
|
5
6
|
defaultValue?: string | null | undefined;
|
|
6
|
-
format?:
|
|
7
|
+
format?: FormatOptions;
|
|
7
8
|
label?: string;
|
|
8
9
|
description?: string;
|
|
9
10
|
arrow?: boolean;
|
|
@@ -20,5 +21,17 @@ interface DateInputProps {
|
|
|
20
21
|
utc?: boolean;
|
|
21
22
|
closeOnSelect?: boolean;
|
|
22
23
|
}
|
|
24
|
+
type DateFormatOptions = "MM/DD/YYYY" | "DD/MM/YYYY" | "YYYY-MM-DD";
|
|
25
|
+
type TimeFormatOptions = "HH:mm:ss" | "h:mm:ss A" | "HH:mm:ss.SSS";
|
|
26
|
+
type FormatOptions = DateFormatOptions | `${DateFormatOptions} ${TimeFormatOptions}`;
|
|
27
|
+
export type Segment = {
|
|
28
|
+
value: string;
|
|
29
|
+
text: string;
|
|
30
|
+
placeholder: string;
|
|
31
|
+
type: moment.unitOfTime.DurationConstructor | "separator";
|
|
32
|
+
index: number;
|
|
33
|
+
momentType?: moment.unitOfTime.All | moment.unitOfTime.DurationConstructor;
|
|
34
|
+
pattern?: string;
|
|
35
|
+
};
|
|
23
36
|
declare const DateInput: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<DateInputProps, never>> & string & Omit<({ className, defaultValue, format, label, description, arrow, size, variant, clearable, required, onChange, min, max, error, enableCalendar, utc, closeOnSelect, }: DateInputProps) => import("react/jsx-runtime").JSX.Element, keyof React.Component<any, {}, any>>;
|
|
24
37
|
export default DateInput;
|
|
@@ -14,6 +14,7 @@ import { useEffect, useMemo, useRef, useState, } from "react";
|
|
|
14
14
|
import styled from "styled-components";
|
|
15
15
|
import { FieldLabel, Calendar } from "..";
|
|
16
16
|
import { StyledContent, StyledFloatContainer, ArrowButton, ClearButton, } from "../core";
|
|
17
|
+
import parseTimestamp from "../Utilities/parseTimestamp";
|
|
17
18
|
const StyledInputContainer = styled.div `
|
|
18
19
|
position: relative;
|
|
19
20
|
|
|
@@ -172,71 +173,6 @@ const InputSegment = styled.div `
|
|
|
172
173
|
: "10px"};
|
|
173
174
|
}
|
|
174
175
|
`;
|
|
175
|
-
function parseTimestamp(timestamp, format, utc = false) {
|
|
176
|
-
// Define patterns to identify datetime components and their placeholders
|
|
177
|
-
const patterns = [
|
|
178
|
-
{ pattern: "YYYY", placeholder: "YYYY", type: "year", momentType: "year" },
|
|
179
|
-
{ pattern: "MM", placeholder: "MM", type: "month", momentType: "month" },
|
|
180
|
-
{ pattern: "DD", placeholder: "DD", type: "day", momentType: "date" },
|
|
181
|
-
{ pattern: "HH", placeholder: "HH", type: "hour", momentType: "hour" },
|
|
182
|
-
{ pattern: "h", placeholder: "h", type: "hour", momentType: "hour" },
|
|
183
|
-
{ pattern: "mm", placeholder: "mm", type: "minute", momentType: "minute" },
|
|
184
|
-
{ pattern: "ss", placeholder: "ss", type: "second", momentType: "second" },
|
|
185
|
-
{
|
|
186
|
-
pattern: "SSS",
|
|
187
|
-
placeholder: "SSS",
|
|
188
|
-
type: "millisecond",
|
|
189
|
-
momentType: "millisecond",
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
pattern: "A",
|
|
193
|
-
placeholder: "AM/PM",
|
|
194
|
-
type: "meridiem",
|
|
195
|
-
momentType: "meridiem",
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
pattern: "Z",
|
|
199
|
-
placeholder: "Z",
|
|
200
|
-
type: "timezone",
|
|
201
|
-
momentType: "timezone",
|
|
202
|
-
},
|
|
203
|
-
];
|
|
204
|
-
// Helper function to split format into datetime components and separators
|
|
205
|
-
function splitFormat(format) {
|
|
206
|
-
return format.split(/(YYYY|MM|DD|HH|h|mm|ss|SSS|Z)/).filter((s) => s);
|
|
207
|
-
}
|
|
208
|
-
// Helper function to match segments to their placeholders and types
|
|
209
|
-
function matchSegment(segment) {
|
|
210
|
-
const pattern = patterns.find((p) => p.pattern === segment);
|
|
211
|
-
return pattern
|
|
212
|
-
? pattern
|
|
213
|
-
: {
|
|
214
|
-
pattern: segment,
|
|
215
|
-
placeholder: segment,
|
|
216
|
-
type: "separator",
|
|
217
|
-
value: "",
|
|
218
|
-
text: "",
|
|
219
|
-
index: -1,
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
const segments = splitFormat(format).map((segment, i) => {
|
|
223
|
-
const { pattern, placeholder, type, momentType } = matchSegment(segment);
|
|
224
|
-
const value = timestamp
|
|
225
|
-
? utc === true
|
|
226
|
-
? moment.utc(timestamp).format(pattern)
|
|
227
|
-
: moment(timestamp).format(pattern)
|
|
228
|
-
: placeholder;
|
|
229
|
-
return {
|
|
230
|
-
value,
|
|
231
|
-
text: value,
|
|
232
|
-
placeholder,
|
|
233
|
-
type,
|
|
234
|
-
momentType,
|
|
235
|
-
index: i,
|
|
236
|
-
};
|
|
237
|
-
});
|
|
238
|
-
return segments;
|
|
239
|
-
}
|
|
240
176
|
const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:ss", label, description, arrow = true, size = "sm", variant = "outlined", clearable = false, required = false, onChange = () => { }, min, max, error, enableCalendar = false, utc = false, closeOnSelect = true, }) => {
|
|
241
177
|
const [value, setValue] = useState(defaultValue);
|
|
242
178
|
const [selectedSegment, setSelectedSegment] = useState();
|
|
@@ -411,32 +347,20 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
|
|
|
411
347
|
const handleWheelEvent = (e) => {
|
|
412
348
|
if (!selectedSegment)
|
|
413
349
|
return;
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
setValue((prev) => {
|
|
429
|
-
if (selectedSegment.type === "separator")
|
|
430
|
-
return prev;
|
|
431
|
-
const newValue = prev
|
|
432
|
-
? moment(prev).add(1, selectedSegment.type).toISOString()
|
|
433
|
-
: moment().toISOString();
|
|
434
|
-
if (!checkValidRange(newValue))
|
|
435
|
-
return prev;
|
|
436
|
-
onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
|
|
437
|
-
return newValue;
|
|
438
|
-
});
|
|
439
|
-
}
|
|
350
|
+
setValue((prev) => {
|
|
351
|
+
if (selectedSegment.type === "separator")
|
|
352
|
+
return prev;
|
|
353
|
+
if (!prev)
|
|
354
|
+
return isDateOnly ? moment().format(format) : moment().toISOString();
|
|
355
|
+
let newValue = e.deltaY > 0
|
|
356
|
+
? moment(prev).subtract(1, selectedSegment.type).toISOString()
|
|
357
|
+
: moment(prev).add(1, selectedSegment.type).toISOString();
|
|
358
|
+
if (!checkValidRange(newValue))
|
|
359
|
+
return prev;
|
|
360
|
+
newValue = isDateOnly ? moment(newValue).format(format) : newValue;
|
|
361
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
|
|
362
|
+
return newValue;
|
|
363
|
+
});
|
|
440
364
|
};
|
|
441
365
|
const handlePaste = (e) => __awaiter(void 0, void 0, void 0, function* () {
|
|
442
366
|
const pastedText = yield window.navigator.clipboard.readText();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SelectBoxProps } from "
|
|
1
|
+
import { SelectBoxProps } from "..";
|
|
2
2
|
export declare const StyledInputContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
3
3
|
width?: string | number | null;
|
|
4
4
|
}>> & string;
|
|
5
|
-
declare const SelectBox: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<SelectBoxProps, never>> & string & Omit<({ className, data, placeholder, arrow, onChange, onSearch, searchFn, onScroll, loading, defaultValue,
|
|
5
|
+
declare const SelectBox: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<SelectBoxProps, never>> & string & Omit<({ className, data, placeholder, arrow, onChange, onSearch, searchFn, onScroll, loading, defaultValue, onItemAdded, size, variant, width, allowCustomValue, searchable, clearable, label, description, required, error, openOnFocus, renderOption, actionComponent, focused, grouped, OptionTooltip, DropDownProps, debounceTime, sort, }: SelectBoxProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
|
|
6
6
|
export default SelectBox;
|
|
@@ -15,7 +15,6 @@ import { useFloating, flip, offset, FloatingPortal, autoUpdate, } from "@floatin
|
|
|
15
15
|
import { useCallback, useEffect, useRef, useState, } from "react";
|
|
16
16
|
import { Input, FieldLabel, Tooltip } from "..";
|
|
17
17
|
import { useDebouncedCallback } from "use-debounce";
|
|
18
|
-
import { useUncontrolled } from "@mantine/hooks";
|
|
19
18
|
import { StyledContent, StyledFloatContainer, ArrowButton, ClearButton, } from "../core";
|
|
20
19
|
export const StyledInputContainer = styled.div `
|
|
21
20
|
font-family: ${({ theme }) => theme.typography.fontFamily};
|
|
@@ -136,6 +135,7 @@ const StyledItem = styled.div `
|
|
|
136
135
|
? "6px 16px"
|
|
137
136
|
: "2px 8px"};
|
|
138
137
|
|
|
138
|
+
// Mantine-Dev syntax, styles if the item is disabled
|
|
139
139
|
&[data-disabled] {
|
|
140
140
|
color: ${(props) => props.theme.palette.text.secondary};
|
|
141
141
|
pointer-events: "none";
|
|
@@ -146,20 +146,19 @@ const StyledItem = styled.div `
|
|
|
146
146
|
color: ${(props) => props.theme.palette.text.primary};
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
// Custom prop, checks if item is selected and returns true
|
|
149
150
|
&[data-selected="true"] {
|
|
150
151
|
background-color: ${(props) => props.theme.palette.divider};
|
|
151
152
|
color: ${(props) => props.theme.palette.text.primary};
|
|
152
153
|
}
|
|
153
154
|
`;
|
|
154
|
-
const SelectBox = styled(({ className, data = [], placeholder = "Select...", arrow = true, onChange, onSearch, searchFn, onScroll, loading, defaultValue,
|
|
155
|
-
|
|
155
|
+
const SelectBox = styled(({ className, data = [], placeholder = "Select...", arrow = true, onChange, onSearch, searchFn, onScroll, loading, defaultValue, 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
|
|
156
|
+
DropDownProps = {}, debounceTime = 300, sort = false, }) => {
|
|
157
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
156
158
|
const isObjectArray = (_a = Object.keys((data === null || data === void 0 ? void 0 : data[0]) || {})) === null || _a === void 0 ? void 0 : _a.includes("label");
|
|
157
|
-
const [
|
|
158
|
-
value,
|
|
159
|
-
defaultValue,
|
|
160
|
-
onChange,
|
|
161
|
-
});
|
|
159
|
+
const [inputValue, setInputValue] = useState("");
|
|
162
160
|
const [isOpen, setIsOpen] = useState(false);
|
|
161
|
+
const [selected, setSelected] = useState(null);
|
|
163
162
|
const [searchValue, setSearchValue] = useState("");
|
|
164
163
|
const [customItems, setCustomItems] = useState([]);
|
|
165
164
|
const [placement, setPlacement] = useState("bottom-start");
|
|
@@ -167,10 +166,12 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
167
166
|
const inputRef = useRef(null);
|
|
168
167
|
const containerRef = useRef(null);
|
|
169
168
|
const scrollContainerRef = useRef(null);
|
|
169
|
+
// Remove duplicates from search dropdown data
|
|
170
170
|
const uniqueItems = Array.from(new Map([...data, ...customItems].map((item) => [
|
|
171
171
|
isObjectArray ? item.value : item,
|
|
172
172
|
item,
|
|
173
173
|
])).values());
|
|
174
|
+
// search filter for dropdown items
|
|
174
175
|
const filteredItems = uniqueItems
|
|
175
176
|
.filter((item) => {
|
|
176
177
|
const itemValue = (isObjectArray ? item.label : item);
|
|
@@ -182,6 +183,8 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
182
183
|
const bValue = b.group;
|
|
183
184
|
return aValue.localeCompare(bValue);
|
|
184
185
|
}
|
|
186
|
+
if (!sort)
|
|
187
|
+
return 0;
|
|
185
188
|
// Secondary sort by label/value to ensure consistent ordering
|
|
186
189
|
const aLabel = isObjectArray ? a.label : a;
|
|
187
190
|
const bLabel = isObjectArray ? b.label : b;
|
|
@@ -228,11 +231,40 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
228
231
|
return !prev;
|
|
229
232
|
});
|
|
230
233
|
};
|
|
234
|
+
const handleInputChange = (e) => {
|
|
235
|
+
const value = e.target.value;
|
|
236
|
+
setInputValue(value);
|
|
237
|
+
setIsOpen(true);
|
|
238
|
+
};
|
|
239
|
+
const debouncedHandleChange = useDebouncedCallback((value) => {
|
|
240
|
+
if (searchFn) {
|
|
241
|
+
searchFn(value);
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
setSearchValue(value);
|
|
245
|
+
}
|
|
246
|
+
if (allowCustomValue && value) {
|
|
247
|
+
const existingItem = data.find((item) => isObjectArray
|
|
248
|
+
? item.label.toLowerCase() === value.toLowerCase()
|
|
249
|
+
: item.toLowerCase() === value.toLowerCase());
|
|
250
|
+
if (existingItem)
|
|
251
|
+
handleChangeSelection(existingItem);
|
|
252
|
+
}
|
|
253
|
+
update();
|
|
254
|
+
}, debounceTime);
|
|
255
|
+
const handleBlur = () => {
|
|
256
|
+
var _a, _b;
|
|
257
|
+
if (((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value) && allowCustomValue) {
|
|
258
|
+
handleAddItem((_b = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _b === void 0 ? void 0 : _b.value);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
231
261
|
const handleClear = (e) => {
|
|
232
262
|
e.preventDefault();
|
|
233
|
-
|
|
263
|
+
if (inputRef.current)
|
|
264
|
+
inputRef.current.value = "";
|
|
234
265
|
setIsOpen(false);
|
|
235
|
-
|
|
266
|
+
handleChangeSelection(null);
|
|
267
|
+
setSelected(null);
|
|
236
268
|
setSearchValue("");
|
|
237
269
|
searchFn === null || searchFn === void 0 ? void 0 : searchFn("");
|
|
238
270
|
update();
|
|
@@ -240,32 +272,21 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
240
272
|
const handleItemClick = (event, item) => {
|
|
241
273
|
event.preventDefault();
|
|
242
274
|
event.stopPropagation();
|
|
243
|
-
|
|
275
|
+
handleChangeSelection(item);
|
|
244
276
|
setIsOpen(false);
|
|
245
277
|
};
|
|
278
|
+
const handleChangeSelection = useCallback((option) => {
|
|
279
|
+
setSelected(option);
|
|
280
|
+
onChange === null || onChange === void 0 ? void 0 : onChange((option === null || option === void 0 ? void 0 : option.value) || option, option);
|
|
281
|
+
}, [onChange]);
|
|
246
282
|
const handleAddItem = useCallback((newItem) => {
|
|
247
|
-
const
|
|
248
|
-
newItem
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
prev.push(newValue);
|
|
255
|
-
return prev;
|
|
256
|
-
});
|
|
257
|
-
handleChange(newValue);
|
|
258
|
-
onItemAdded === null || onItemAdded === void 0 ? void 0 : onItemAdded(newValue);
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
const item = data.find((item) => {
|
|
262
|
-
return isObjectArray
|
|
263
|
-
? item.label.toLowerCase() === newItem.toLowerCase()
|
|
264
|
-
: item.toLowerCase() === newItem.toLowerCase();
|
|
265
|
-
});
|
|
266
|
-
handleChange(item);
|
|
267
|
-
}
|
|
268
|
-
}, [onItemAdded, isObjectArray, data, handleChange]);
|
|
283
|
+
const newValue = isObjectArray
|
|
284
|
+
? { label: newItem, value: newItem }
|
|
285
|
+
: newItem;
|
|
286
|
+
setCustomItems((prev) => [...prev, newValue]);
|
|
287
|
+
handleChangeSelection(newValue);
|
|
288
|
+
onItemAdded === null || onItemAdded === void 0 ? void 0 : onItemAdded(newValue);
|
|
289
|
+
}, [onItemAdded, isObjectArray, handleChangeSelection]);
|
|
269
290
|
const handleKeyDown = (e) => {
|
|
270
291
|
var _a, _b;
|
|
271
292
|
const currentInputValue = (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.value;
|
|
@@ -292,26 +313,32 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
292
313
|
// Arrow down
|
|
293
314
|
if (e.key === "ArrowDown") {
|
|
294
315
|
e.preventDefault();
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
316
|
+
setSelected((prev) => {
|
|
317
|
+
let newItem = filteredItems[0]; // Loop back to the first item
|
|
318
|
+
const index = filteredItems.findIndex((item) => isObjectArray
|
|
319
|
+
? item.value === (prev === null || prev === void 0 ? void 0 : prev.value)
|
|
320
|
+
: item === prev);
|
|
321
|
+
if (index < filteredItems.length - 1) {
|
|
322
|
+
newItem = filteredItems[index + 1];
|
|
323
|
+
}
|
|
324
|
+
onChange === null || onChange === void 0 ? void 0 : onChange((newItem === null || newItem === void 0 ? void 0 : newItem.value) || newItem, newItem);
|
|
325
|
+
return newItem;
|
|
326
|
+
});
|
|
303
327
|
}
|
|
304
328
|
// Arrow up
|
|
305
329
|
if (e.key === "ArrowUp") {
|
|
306
330
|
e.preventDefault();
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
331
|
+
setSelected((prev) => {
|
|
332
|
+
let newItem = filteredItems[filteredItems.length - 1]; // Loop back to the last item
|
|
333
|
+
const index = filteredItems.findIndex((item) => isObjectArray
|
|
334
|
+
? item.value === (prev === null || prev === void 0 ? void 0 : prev.value)
|
|
335
|
+
: item === prev);
|
|
336
|
+
if (index > 0) {
|
|
337
|
+
newItem = filteredItems[index - 1];
|
|
338
|
+
}
|
|
339
|
+
onChange === null || onChange === void 0 ? void 0 : onChange((newItem === null || newItem === void 0 ? void 0 : newItem.value) || newItem, newItem);
|
|
340
|
+
return newItem;
|
|
341
|
+
});
|
|
315
342
|
}
|
|
316
343
|
// Tab key
|
|
317
344
|
if (e.key === "Tab") {
|
|
@@ -319,7 +346,7 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
319
346
|
handleAddItem(currentInputValue);
|
|
320
347
|
setSearchValue("");
|
|
321
348
|
}
|
|
322
|
-
else if (!
|
|
349
|
+
else if (!selected) {
|
|
323
350
|
// clear input
|
|
324
351
|
if (inputRef.current) {
|
|
325
352
|
inputRef.current.value = "";
|
|
@@ -329,33 +356,22 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
329
356
|
setIsOpen(false);
|
|
330
357
|
}
|
|
331
358
|
};
|
|
332
|
-
const handleOnChange = (e) => {
|
|
333
|
-
// Simulate clear event when the input is changed to an empty string
|
|
334
|
-
if (e.target.value === "") {
|
|
335
|
-
handleClear(e);
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
if (searchFn !== undefined) {
|
|
339
|
-
searchFn === null || searchFn === void 0 ? void 0 : searchFn(e.target.value);
|
|
340
|
-
}
|
|
341
|
-
else {
|
|
342
|
-
setSearchValue(e.target.value);
|
|
343
|
-
update();
|
|
344
|
-
}
|
|
345
|
-
};
|
|
346
|
-
const debouncedHandleOnChange = useDebouncedCallback(handleOnChange, 300);
|
|
347
359
|
const handleFocus = () => {
|
|
348
360
|
if (openOnFocus) {
|
|
349
361
|
setIsOpen(true);
|
|
350
362
|
}
|
|
351
363
|
};
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
364
|
+
const referenceEl = (_b = refs === null || refs === void 0 ? void 0 : refs.reference) === null || _b === void 0 ? void 0 : _b.current;
|
|
365
|
+
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%";
|
|
366
|
+
const scrollEl = scrollContainerRef === null || scrollContainerRef === void 0 ? void 0 : scrollContainerRef.current;
|
|
367
|
+
const scrollActive = scrollEl
|
|
368
|
+
? (scrollEl === null || scrollEl === void 0 ? void 0 : scrollEl.scrollHeight) > (scrollEl === null || scrollEl === void 0 ? void 0 : scrollEl.clientHeight)
|
|
369
|
+
: false;
|
|
370
|
+
// get height between bottom of the floating container and the bottom of the viewport
|
|
371
|
+
const bottomHeight = window.innerHeight - ((_f = referenceEl === null || referenceEl === void 0 ? void 0 : referenceEl.getBoundingClientRect()) === null || _f === void 0 ? void 0 : _f.bottom) - 10;
|
|
372
|
+
// get height between top of the floating container and the top of the viewport
|
|
373
|
+
const topHeight = (((_g = referenceEl === null || referenceEl === void 0 ? void 0 : referenceEl.getBoundingClientRect()) === null || _g === void 0 ? void 0 : _g.top) -
|
|
374
|
+
10);
|
|
359
375
|
// Close on outside click
|
|
360
376
|
useEffect(() => {
|
|
361
377
|
const close = (e) => {
|
|
@@ -374,6 +390,31 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
374
390
|
document.addEventListener("click", close);
|
|
375
391
|
return () => document.removeEventListener("click", close);
|
|
376
392
|
}, [refs.floating, refs.reference]);
|
|
393
|
+
// Handle default value
|
|
394
|
+
useEffect(() => {
|
|
395
|
+
if (defaultValue) {
|
|
396
|
+
const isOption = defaultValue.value !== undefined;
|
|
397
|
+
const searchPattern = isOption
|
|
398
|
+
? defaultValue.value
|
|
399
|
+
: defaultValue;
|
|
400
|
+
setSelected(data.find((item) => isObjectArray
|
|
401
|
+
? item.value === searchPattern
|
|
402
|
+
: item === searchPattern) || null);
|
|
403
|
+
}
|
|
404
|
+
}, [data, defaultValue, isObjectArray]);
|
|
405
|
+
// handle input value change
|
|
406
|
+
useEffect(() => {
|
|
407
|
+
if (inputRef.current) {
|
|
408
|
+
if (!selected) {
|
|
409
|
+
inputRef.current.value = "";
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
inputRef.current.value = isObjectArray
|
|
413
|
+
? selected.label
|
|
414
|
+
: selected;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}, [selected]);
|
|
377
418
|
// handle scroll item into view
|
|
378
419
|
useEffect(() => {
|
|
379
420
|
var _a, _b;
|
|
@@ -381,7 +422,7 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
381
422
|
if (item) {
|
|
382
423
|
item.scrollIntoView({ block: "nearest" });
|
|
383
424
|
}
|
|
384
|
-
}, [
|
|
425
|
+
}, [selected]);
|
|
385
426
|
// make calls to onSearch callback
|
|
386
427
|
useEffect(() => {
|
|
387
428
|
if (searchable) {
|
|
@@ -389,17 +430,6 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
389
430
|
onSearch === null || onSearch === void 0 ? void 0 : onSearch(searchValue);
|
|
390
431
|
}
|
|
391
432
|
}, [searchValue]);
|
|
392
|
-
const referenceEl = (_b = refs === null || refs === void 0 ? void 0 : refs.reference) === null || _b === void 0 ? void 0 : _b.current;
|
|
393
|
-
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%";
|
|
394
|
-
const scrollEl = scrollContainerRef === null || scrollContainerRef === void 0 ? void 0 : scrollContainerRef.current;
|
|
395
|
-
const scrollActive = scrollEl
|
|
396
|
-
? (scrollEl === null || scrollEl === void 0 ? void 0 : scrollEl.scrollHeight) > (scrollEl === null || scrollEl === void 0 ? void 0 : scrollEl.clientHeight)
|
|
397
|
-
: false;
|
|
398
|
-
// get height between bottom of the floating container and the bottom of the viewport
|
|
399
|
-
const bottomHeight = window.innerHeight - ((_f = referenceEl === null || referenceEl === void 0 ? void 0 : referenceEl.getBoundingClientRect()) === null || _f === void 0 ? void 0 : _f.bottom) - 10;
|
|
400
|
-
// get height between top of the floating container and the top of the viewport
|
|
401
|
-
const topHeight = (((_g = referenceEl === null || referenceEl === void 0 ? void 0 : referenceEl.getBoundingClientRect()) === null || _g === void 0 ? void 0 : _g.top) -
|
|
402
|
-
10);
|
|
403
433
|
useEffect(() => {
|
|
404
434
|
if (bottomHeight < 250) {
|
|
405
435
|
setPlacement("top-start");
|
|
@@ -414,12 +444,14 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
414
444
|
setDropDownHeight(bottomHeight);
|
|
415
445
|
};
|
|
416
446
|
}, [topHeight, bottomHeight, isOpen]);
|
|
417
|
-
|
|
447
|
+
useEffect(() => {
|
|
448
|
+
debouncedHandleChange(inputValue);
|
|
449
|
+
}, [inputValue, debouncedHandleChange]);
|
|
450
|
+
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, onBlur: handleBlur }), clearable && (selected || !!((_h = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _h === void 0 ? void 0 : _h.value)) ? (_jsx(ClearButton, { className: "input-btn", onClick: handleClear, onMouseDown: (e) => {
|
|
418
451
|
e.preventDefault();
|
|
419
452
|
e.stopPropagation();
|
|
420
453
|
} })) : arrow ? (_jsx(ArrowButton, { onClick: (e) => {
|
|
421
454
|
e.preventDefault();
|
|
422
|
-
// e.stopPropagation();
|
|
423
455
|
}, onMouseDown: (e) => {
|
|
424
456
|
e.preventDefault();
|
|
425
457
|
e.stopPropagation();
|
|
@@ -435,15 +467,16 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
435
467
|
: "",
|
|
436
468
|
}, variant: variant, "data-empty": filteredItems.length === 0 }, DropDownProps, { children: [actionComponent && _jsx(ActionMenu, { children: actionComponent }), _jsxs(StyledInnerItemContainer, { ref: scrollContainerRef, "data-scroll-active": scrollActive, onScroll: onScroll, children: [loading && _jsx("div", { children: "Loading..." }), !loading && grouped
|
|
437
469
|
? groups.map((group, index) => (_jsxs("div", { children: [_jsx(GroupTitle, { size: size, children: group.label }), group.items.map((item, index) => {
|
|
438
|
-
return (_jsx(Tooltip, { content:
|
|
439
|
-
? (
|
|
440
|
-
|
|
470
|
+
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": isObjectArray
|
|
471
|
+
? (selected === null || selected === void 0 ? void 0 : selected.value) ===
|
|
472
|
+
item.value
|
|
473
|
+
: 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));
|
|
441
474
|
})] }, group.label)))
|
|
442
475
|
: filteredItems.map((item, index) => {
|
|
443
|
-
return (_jsx(Tooltip, { content:
|
|
444
|
-
? (
|
|
476
|
+
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": isObjectArray
|
|
477
|
+
? (selected === null || selected === void 0 ? void 0 : selected.value) ===
|
|
445
478
|
(item === null || item === void 0 ? void 0 : item.value)
|
|
446
|
-
:
|
|
479
|
+
: 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));
|
|
447
480
|
})] })] })) }) }))] }));
|
|
448
481
|
}) `
|
|
449
482
|
position: relative;
|
|
@@ -8,7 +8,6 @@ export type Option = {
|
|
|
8
8
|
export interface SelectBoxProps {
|
|
9
9
|
className?: string;
|
|
10
10
|
defaultValue?: Option | string;
|
|
11
|
-
value?: Option | string;
|
|
12
11
|
data?: Option[] | string[];
|
|
13
12
|
placeholder?: string;
|
|
14
13
|
arrow?: boolean;
|
|
@@ -33,8 +32,10 @@ export interface SelectBoxProps {
|
|
|
33
32
|
actionComponent?: JSX.Element;
|
|
34
33
|
focused?: boolean;
|
|
35
34
|
grouped?: boolean;
|
|
36
|
-
|
|
35
|
+
OptionTooltip?: React.FC<{
|
|
37
36
|
data: any;
|
|
38
37
|
}>;
|
|
39
38
|
DropDownProps?: any;
|
|
39
|
+
debounceTime?: number;
|
|
40
|
+
sort?: boolean;
|
|
40
41
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import moment from "moment";
|
|
2
|
+
export default function parseTimestamp(timestamp, format, utc = false) {
|
|
3
|
+
// Define patterns to identify datetime components and their placeholders
|
|
4
|
+
const patterns = [
|
|
5
|
+
{ pattern: "YYYY", placeholder: "YYYY", type: "year", momentType: "year" },
|
|
6
|
+
{ pattern: "MM", placeholder: "MM", type: "month", momentType: "month" },
|
|
7
|
+
{ pattern: "DD", placeholder: "DD", type: "day", momentType: "date" },
|
|
8
|
+
{ pattern: "HH", placeholder: "HH", type: "hour", momentType: "hour" },
|
|
9
|
+
{ pattern: "h", placeholder: "h", type: "hour", momentType: "hour" },
|
|
10
|
+
{ pattern: "mm", placeholder: "mm", type: "minute", momentType: "minute" },
|
|
11
|
+
{ pattern: "ss", placeholder: "ss", type: "second", momentType: "second" },
|
|
12
|
+
{
|
|
13
|
+
pattern: "SSS",
|
|
14
|
+
placeholder: "SSS",
|
|
15
|
+
type: "millisecond",
|
|
16
|
+
momentType: "millisecond",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
pattern: "A",
|
|
20
|
+
placeholder: "AM/PM",
|
|
21
|
+
type: "meridiem",
|
|
22
|
+
momentType: "meridiem",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
pattern: "Z",
|
|
26
|
+
placeholder: "Z",
|
|
27
|
+
type: "timezone",
|
|
28
|
+
momentType: "timezone",
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
// Helper function to split format into datetime components and separators
|
|
32
|
+
function splitFormat(format) {
|
|
33
|
+
return format.split(/(YYYY|MM|DD|HH|h|mm|ss|SSS|Z)/).filter((s) => s);
|
|
34
|
+
}
|
|
35
|
+
// Helper function to match segments to their placeholders and types
|
|
36
|
+
function matchSegment(segment) {
|
|
37
|
+
const pattern = patterns.find((p) => p.pattern === segment);
|
|
38
|
+
return pattern
|
|
39
|
+
? pattern
|
|
40
|
+
: {
|
|
41
|
+
pattern: segment,
|
|
42
|
+
placeholder: segment,
|
|
43
|
+
type: "separator",
|
|
44
|
+
value: "",
|
|
45
|
+
text: "",
|
|
46
|
+
index: -1,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const segments = splitFormat(format).map((segment, i) => {
|
|
50
|
+
const { pattern, placeholder, type, momentType } = matchSegment(segment);
|
|
51
|
+
const value = timestamp
|
|
52
|
+
? utc === true
|
|
53
|
+
? moment.utc(timestamp).format(pattern)
|
|
54
|
+
: moment(timestamp).format(pattern)
|
|
55
|
+
: placeholder;
|
|
56
|
+
return {
|
|
57
|
+
value,
|
|
58
|
+
text: value,
|
|
59
|
+
placeholder,
|
|
60
|
+
type,
|
|
61
|
+
momentType,
|
|
62
|
+
index: i,
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
return segments;
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monolith-forensics/monolith-ui",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.64",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"author": "Matt Danner (Monolith Forensics LLC)",
|
|
@@ -12,13 +12,15 @@
|
|
|
12
12
|
"files": [
|
|
13
13
|
"dist/"
|
|
14
14
|
],
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"registry": "https://registry.npmjs.org/"
|
|
17
|
+
},
|
|
15
18
|
"scripts": {
|
|
16
19
|
"clean": "rm -r ./dist",
|
|
17
20
|
"build": "tsc",
|
|
18
|
-
"patch": "yarn version --patch",
|
|
19
|
-
"minor": "yarn version --minor",
|
|
20
|
-
"major": "yarn version --major"
|
|
21
|
-
"release": "yarn version --patch --deferred && yarn build && npm publish && yarn clean"
|
|
21
|
+
"release-patch": "yarn version --patch --deferred && yarn build && npm publish && yarn clean",
|
|
22
|
+
"release-minor": "yarn version --minor --deferred && yarn build && npm publish && yarn clean",
|
|
23
|
+
"release-major": "yarn version --major --deferred && yarn build && npm publish && yarn clean"
|
|
22
24
|
},
|
|
23
25
|
"dependencies": {
|
|
24
26
|
"@floating-ui/react": "^0.26.16",
|