@monolith-forensics/monolith-ui 1.1.60 → 1.1.63
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 +123 -92
- package/dist/SelectBox/types.d.ts +2 -2
- package/dist/Utilities/parseTimestamp.d.ts +2 -0
- package/dist/Utilities/parseTimestamp.js +66 -0
- package/package.json +5 -2
|
@@ -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, }: 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, }) => {
|
|
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);
|
|
@@ -228,11 +229,40 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
228
229
|
return !prev;
|
|
229
230
|
});
|
|
230
231
|
};
|
|
232
|
+
const handleInputChange = (e) => {
|
|
233
|
+
const value = e.target.value;
|
|
234
|
+
setInputValue(value);
|
|
235
|
+
setIsOpen(true);
|
|
236
|
+
};
|
|
237
|
+
const debouncedHandleChange = useDebouncedCallback((value) => {
|
|
238
|
+
if (searchFn) {
|
|
239
|
+
searchFn(value);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
setSearchValue(value);
|
|
243
|
+
}
|
|
244
|
+
if (allowCustomValue && value) {
|
|
245
|
+
const existingItem = data.find((item) => isObjectArray
|
|
246
|
+
? item.label.toLowerCase() === value.toLowerCase()
|
|
247
|
+
: item.toLowerCase() === value.toLowerCase());
|
|
248
|
+
if (existingItem)
|
|
249
|
+
handleChangeSelection(existingItem);
|
|
250
|
+
}
|
|
251
|
+
update();
|
|
252
|
+
}, debounceTime);
|
|
253
|
+
const handleBlur = () => {
|
|
254
|
+
var _a, _b;
|
|
255
|
+
if (((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value) && allowCustomValue) {
|
|
256
|
+
handleAddItem((_b = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _b === void 0 ? void 0 : _b.value);
|
|
257
|
+
}
|
|
258
|
+
};
|
|
231
259
|
const handleClear = (e) => {
|
|
232
260
|
e.preventDefault();
|
|
233
|
-
|
|
261
|
+
if (inputRef.current)
|
|
262
|
+
inputRef.current.value = "";
|
|
234
263
|
setIsOpen(false);
|
|
235
|
-
|
|
264
|
+
handleChangeSelection(null);
|
|
265
|
+
setSelected(null);
|
|
236
266
|
setSearchValue("");
|
|
237
267
|
searchFn === null || searchFn === void 0 ? void 0 : searchFn("");
|
|
238
268
|
update();
|
|
@@ -240,32 +270,21 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
240
270
|
const handleItemClick = (event, item) => {
|
|
241
271
|
event.preventDefault();
|
|
242
272
|
event.stopPropagation();
|
|
243
|
-
|
|
273
|
+
handleChangeSelection(item);
|
|
244
274
|
setIsOpen(false);
|
|
245
275
|
};
|
|
276
|
+
const handleChangeSelection = useCallback((option) => {
|
|
277
|
+
setSelected(option);
|
|
278
|
+
onChange === null || onChange === void 0 ? void 0 : onChange((option === null || option === void 0 ? void 0 : option.value) || option, option);
|
|
279
|
+
}, [onChange]);
|
|
246
280
|
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]);
|
|
281
|
+
const newValue = isObjectArray
|
|
282
|
+
? { label: newItem, value: newItem }
|
|
283
|
+
: newItem;
|
|
284
|
+
setCustomItems((prev) => [...prev, newValue]);
|
|
285
|
+
handleChangeSelection(newValue);
|
|
286
|
+
onItemAdded === null || onItemAdded === void 0 ? void 0 : onItemAdded(newValue);
|
|
287
|
+
}, [onItemAdded, isObjectArray, handleChangeSelection]);
|
|
269
288
|
const handleKeyDown = (e) => {
|
|
270
289
|
var _a, _b;
|
|
271
290
|
const currentInputValue = (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.value;
|
|
@@ -292,26 +311,32 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
292
311
|
// Arrow down
|
|
293
312
|
if (e.key === "ArrowDown") {
|
|
294
313
|
e.preventDefault();
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
314
|
+
setSelected((prev) => {
|
|
315
|
+
let newItem = filteredItems[0]; // Loop back to the first item
|
|
316
|
+
const index = filteredItems.findIndex((item) => isObjectArray
|
|
317
|
+
? item.value === (prev === null || prev === void 0 ? void 0 : prev.value)
|
|
318
|
+
: item === prev);
|
|
319
|
+
if (index < filteredItems.length - 1) {
|
|
320
|
+
newItem = filteredItems[index + 1];
|
|
321
|
+
}
|
|
322
|
+
onChange === null || onChange === void 0 ? void 0 : onChange((newItem === null || newItem === void 0 ? void 0 : newItem.value) || newItem, newItem);
|
|
323
|
+
return newItem;
|
|
324
|
+
});
|
|
303
325
|
}
|
|
304
326
|
// Arrow up
|
|
305
327
|
if (e.key === "ArrowUp") {
|
|
306
328
|
e.preventDefault();
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
329
|
+
setSelected((prev) => {
|
|
330
|
+
let newItem = filteredItems[filteredItems.length - 1]; // Loop back to the last item
|
|
331
|
+
const index = filteredItems.findIndex((item) => isObjectArray
|
|
332
|
+
? item.value === (prev === null || prev === void 0 ? void 0 : prev.value)
|
|
333
|
+
: item === prev);
|
|
334
|
+
if (index > 0) {
|
|
335
|
+
newItem = filteredItems[index - 1];
|
|
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
|
+
});
|
|
315
340
|
}
|
|
316
341
|
// Tab key
|
|
317
342
|
if (e.key === "Tab") {
|
|
@@ -319,7 +344,7 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
319
344
|
handleAddItem(currentInputValue);
|
|
320
345
|
setSearchValue("");
|
|
321
346
|
}
|
|
322
|
-
else if (!
|
|
347
|
+
else if (!selected) {
|
|
323
348
|
// clear input
|
|
324
349
|
if (inputRef.current) {
|
|
325
350
|
inputRef.current.value = "";
|
|
@@ -329,33 +354,22 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
329
354
|
setIsOpen(false);
|
|
330
355
|
}
|
|
331
356
|
};
|
|
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
357
|
const handleFocus = () => {
|
|
348
358
|
if (openOnFocus) {
|
|
349
359
|
setIsOpen(true);
|
|
350
360
|
}
|
|
351
361
|
};
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
362
|
+
const referenceEl = (_b = refs === null || refs === void 0 ? void 0 : refs.reference) === null || _b === void 0 ? void 0 : _b.current;
|
|
363
|
+
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%";
|
|
364
|
+
const scrollEl = scrollContainerRef === null || scrollContainerRef === void 0 ? void 0 : scrollContainerRef.current;
|
|
365
|
+
const scrollActive = scrollEl
|
|
366
|
+
? (scrollEl === null || scrollEl === void 0 ? void 0 : scrollEl.scrollHeight) > (scrollEl === null || scrollEl === void 0 ? void 0 : scrollEl.clientHeight)
|
|
367
|
+
: false;
|
|
368
|
+
// get height between bottom of the floating container and the bottom of the viewport
|
|
369
|
+
const bottomHeight = window.innerHeight - ((_f = referenceEl === null || referenceEl === void 0 ? void 0 : referenceEl.getBoundingClientRect()) === null || _f === void 0 ? void 0 : _f.bottom) - 10;
|
|
370
|
+
// get height between top of the floating container and the top of the viewport
|
|
371
|
+
const topHeight = (((_g = referenceEl === null || referenceEl === void 0 ? void 0 : referenceEl.getBoundingClientRect()) === null || _g === void 0 ? void 0 : _g.top) -
|
|
372
|
+
10);
|
|
359
373
|
// Close on outside click
|
|
360
374
|
useEffect(() => {
|
|
361
375
|
const close = (e) => {
|
|
@@ -374,6 +388,31 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
374
388
|
document.addEventListener("click", close);
|
|
375
389
|
return () => document.removeEventListener("click", close);
|
|
376
390
|
}, [refs.floating, refs.reference]);
|
|
391
|
+
// Handle default value
|
|
392
|
+
useEffect(() => {
|
|
393
|
+
if (defaultValue) {
|
|
394
|
+
const isOption = defaultValue.value !== undefined;
|
|
395
|
+
const searchPattern = isOption
|
|
396
|
+
? defaultValue.value
|
|
397
|
+
: defaultValue;
|
|
398
|
+
setSelected(data.find((item) => isObjectArray
|
|
399
|
+
? item.value === searchPattern
|
|
400
|
+
: item === searchPattern) || null);
|
|
401
|
+
}
|
|
402
|
+
}, [data, defaultValue, isObjectArray]);
|
|
403
|
+
// handle input value change
|
|
404
|
+
useEffect(() => {
|
|
405
|
+
if (inputRef.current) {
|
|
406
|
+
if (!selected) {
|
|
407
|
+
inputRef.current.value = "";
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
inputRef.current.value = isObjectArray
|
|
411
|
+
? selected.label
|
|
412
|
+
: selected;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}, [selected]);
|
|
377
416
|
// handle scroll item into view
|
|
378
417
|
useEffect(() => {
|
|
379
418
|
var _a, _b;
|
|
@@ -381,7 +420,7 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
381
420
|
if (item) {
|
|
382
421
|
item.scrollIntoView({ block: "nearest" });
|
|
383
422
|
}
|
|
384
|
-
}, [
|
|
423
|
+
}, [selected]);
|
|
385
424
|
// make calls to onSearch callback
|
|
386
425
|
useEffect(() => {
|
|
387
426
|
if (searchable) {
|
|
@@ -389,17 +428,6 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
389
428
|
onSearch === null || onSearch === void 0 ? void 0 : onSearch(searchValue);
|
|
390
429
|
}
|
|
391
430
|
}, [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
431
|
useEffect(() => {
|
|
404
432
|
if (bottomHeight < 250) {
|
|
405
433
|
setPlacement("top-start");
|
|
@@ -414,12 +442,14 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
414
442
|
setDropDownHeight(bottomHeight);
|
|
415
443
|
};
|
|
416
444
|
}, [topHeight, bottomHeight, isOpen]);
|
|
417
|
-
|
|
445
|
+
useEffect(() => {
|
|
446
|
+
debouncedHandleChange(inputValue);
|
|
447
|
+
}, [inputValue, debouncedHandleChange]);
|
|
448
|
+
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
449
|
e.preventDefault();
|
|
419
450
|
e.stopPropagation();
|
|
420
451
|
} })) : arrow ? (_jsx(ArrowButton, { onClick: (e) => {
|
|
421
452
|
e.preventDefault();
|
|
422
|
-
// e.stopPropagation();
|
|
423
453
|
}, onMouseDown: (e) => {
|
|
424
454
|
e.preventDefault();
|
|
425
455
|
e.stopPropagation();
|
|
@@ -435,15 +465,16 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
|
|
|
435
465
|
: "",
|
|
436
466
|
}, 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
467
|
? 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
|
-
|
|
468
|
+
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
|
|
469
|
+
? (selected === null || selected === void 0 ? void 0 : selected.value) ===
|
|
470
|
+
item.value
|
|
471
|
+
: 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
472
|
})] }, group.label)))
|
|
442
473
|
: filteredItems.map((item, index) => {
|
|
443
|
-
return (_jsx(Tooltip, { content:
|
|
444
|
-
? (
|
|
474
|
+
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
|
|
475
|
+
? (selected === null || selected === void 0 ? void 0 : selected.value) ===
|
|
445
476
|
(item === null || item === void 0 ? void 0 : item.value)
|
|
446
|
-
:
|
|
477
|
+
: 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
478
|
})] })] })) }) }))] }));
|
|
448
479
|
}) `
|
|
449
480
|
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,9 @@ 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
40
|
}
|
|
@@ -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.63",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"author": "Matt Danner (Monolith Forensics LLC)",
|
|
@@ -12,13 +12,16 @@
|
|
|
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
21
|
"patch": "yarn version --patch",
|
|
19
22
|
"minor": "yarn version --minor",
|
|
20
23
|
"major": "yarn version --major",
|
|
21
|
-
"release": "yarn version --patch --deferred && yarn build && npm publish && yarn clean"
|
|
24
|
+
"release-patch": "yarn version --patch --deferred && yarn build && npm publish && yarn clean"
|
|
22
25
|
},
|
|
23
26
|
"dependencies": {
|
|
24
27
|
"@floating-ui/react": "^0.26.16",
|