@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.
@@ -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, 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, 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, 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 [_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);
@@ -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
- e.stopPropagation();
263
+ if (inputRef.current)
264
+ inputRef.current.value = "";
234
265
  setIsOpen(false);
235
- handleChange(undefined);
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
- handleChange(item);
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 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]);
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
- 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);
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
- 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);
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 (!_value) {
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 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
- };
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
- }, [_value]);
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
- 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) => {
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: 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));
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: 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) ===
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
- : _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));
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
- TooltipContent?: React.FC<{
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,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.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",