@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.
@@ -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
- :hover {
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?: string;
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
- if (e.deltaY > 0) {
415
- setValue((prev) => {
416
- if (selectedSegment.type === "separator")
417
- return prev;
418
- const newValue = prev
419
- ? moment(prev).subtract(1, selectedSegment.type).toISOString()
420
- : moment().toISOString();
421
- if (!checkValidRange(newValue))
422
- return prev;
423
- onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
424
- return newValue;
425
- });
426
- }
427
- else {
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 "./types";
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, value, onItemAdded, size, variant, width, allowCustomValue, searchable, clearable, label, description, required, error, openOnFocus, renderOption, actionComponent, focused, grouped, TooltipContent, DropDownProps, }: SelectBoxProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
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, 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, TooltipContent, DropDownProps = {}, }) => {
155
- var _a, _b, _c, _d, _e, _f, _g;
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 [_value, handleChange] = useUncontrolled({
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
- e.stopPropagation();
261
+ if (inputRef.current)
262
+ inputRef.current.value = "";
234
263
  setIsOpen(false);
235
- handleChange(undefined);
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
- handleChange(item);
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 isNewItem = data.every((item) => item.label.toLowerCase() !==
248
- newItem.toLowerCase());
249
- if (isNewItem) {
250
- const newValue = isObjectArray
251
- ? { label: newItem, value: newItem }
252
- : newItem;
253
- setCustomItems((prev) => {
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
- let newItem = filteredItems[0]; // Loop back to the first item
296
- const index = filteredItems.findIndex((item) => isObjectArray
297
- ? item.value === (_value === null || _value === void 0 ? void 0 : _value.value)
298
- : item === _value);
299
- if (index < filteredItems.length - 1) {
300
- newItem = filteredItems[index + 1];
301
- }
302
- handleChange === null || handleChange === void 0 ? void 0 : handleChange(newItem, newItem);
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
- let newItem = filteredItems[filteredItems.length - 1]; // Loop back to the last item
308
- const index = filteredItems.findIndex((item) => isObjectArray
309
- ? item.value === (_value === null || _value === void 0 ? void 0 : _value.value)
310
- : item === _value);
311
- if (index > 0) {
312
- newItem = filteredItems[index - 1];
313
- }
314
- handleChange === null || handleChange === void 0 ? void 0 : handleChange(newItem, newItem);
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 (!_value) {
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 handleBlur = () => {
353
- var _a;
354
- if (allowCustomValue && ((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value)) {
355
- handleAddItem(inputRef.current.value);
356
- setSearchValue("");
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
- }, [_value]);
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
- 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: isObjectArray ? (_value === null || _value === void 0 ? void 0 : _value.label) || "" : _value || "", onChange: debouncedHandleOnChange, onFocus: handleFocus, autoFocus: focused, placeholder: placeholder, size: size, readOnly: !searchable, "data-button-right": arrow || clearable }), clearable && _value ? (_jsx(ClearButton, { className: "input-btn", onClick: handleClear, onMouseDown: (e) => {
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: TooltipContent ? (_jsx(TooltipContent, { data: item.data })) : null, side: "left", children: _jsx(StyledItem, { className: "mfFloatingItem", onClick: (e) => handleItemClick(e, item), "data-selected": isObjectArray
439
- ? (_value === null || _value === void 0 ? void 0 : _value.value) === item.value
440
- : _value === 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));
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: TooltipContent ? (_jsx(TooltipContent, { data: item.data })) : null, side: "left", children: _jsx(StyledItem, { className: "mfFloatingItem", onClick: (e) => handleItemClick(e, item), "data-selected": isObjectArray
444
- ? (_value === null || _value === void 0 ? void 0 : _value.value) ===
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
- : _value === 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));
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
- TooltipContent?: React.FC<{
35
+ OptionTooltip?: React.FC<{
37
36
  data: any;
38
37
  }>;
39
38
  DropDownProps?: any;
39
+ debounceTime?: number;
40
40
  }
@@ -0,0 +1,2 @@
1
+ import { Segment } from "../DateInput/DateInput";
2
+ export default function parseTimestamp(timestamp: string, format: string, utc?: boolean): Segment[];
@@ -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.60",
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",