@monolith-forensics/monolith-ui 1.1.55 → 1.1.57

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.
@@ -1,6 +1,15 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
11
  import moment from "moment";
3
- import { useFloating, flip, offset, FloatingPortal } from "@floating-ui/react";
12
+ import { useFloating, flip, offset, FloatingPortal, useDismiss, useInteractions, autoUpdate, } from "@floating-ui/react";
4
13
  import { useEffect, useMemo, useRef, useState, } from "react";
5
14
  import styled from "styled-components";
6
15
  import { FieldLabel, Calendar } from "..";
@@ -236,14 +245,17 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
236
245
  const isDateOnly = format.match(/(HH|h|mm|ss|SSS|A|Z)/) === null;
237
246
  const mainRef = useRef(null);
238
247
  const typedKeys = useRef("");
239
- const { refs, floatingStyles } = useFloating({
248
+ const { refs, floatingStyles, context } = useFloating({
240
249
  open: isOpen,
241
250
  onOpenChange: setIsOpen,
242
251
  placement: "bottom-start",
243
252
  strategy: "absolute",
244
253
  // Handle collisions with the viewport
245
254
  middleware: [flip(), offset(5)],
255
+ whileElementsMounted: autoUpdate,
246
256
  });
257
+ const dismiss = useDismiss(context);
258
+ const { getReferenceProps } = useInteractions([dismiss]);
247
259
  const segments = useMemo(() => parseTimestamp(moment(value).toISOString(), format, utc), [value, format, utc]);
248
260
  const checkValidRange = (value) => {
249
261
  if (min && moment(value).isBefore(min))
@@ -252,11 +264,6 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
252
264
  return false;
253
265
  return true;
254
266
  };
255
- const toggleOpen = () => {
256
- setIsOpen((prev) => {
257
- return !prev;
258
- });
259
- };
260
267
  const handleClear = (e) => {
261
268
  e.preventDefault();
262
269
  e.stopPropagation();
@@ -286,7 +293,6 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
286
293
  input.focus();
287
294
  }
288
295
  }
289
- toggleOpen();
290
296
  setIsOpen(true);
291
297
  setSelectedSegment(segments[0]);
292
298
  };
@@ -320,6 +326,7 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
320
326
  const next = segments[prev.index + 2];
321
327
  return next || prev;
322
328
  });
329
+ typedKeys.current = ""; // clear typed keys when moving to next segment
323
330
  }
324
331
  // Left Arrow
325
332
  if (e.key === "ArrowLeft") {
@@ -330,6 +337,7 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
330
337
  const next = segments[prev.index - 2];
331
338
  return next || prev;
332
339
  });
340
+ typedKeys.current = ""; // clear typed keys when moving to next segment
333
341
  }
334
342
  // Up Arrow
335
343
  if (e.key === "ArrowUp") {
@@ -369,7 +377,7 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
369
377
  }
370
378
  // handle paste
371
379
  if (e.key === "v" && (e.metaKey || e.ctrlKey)) {
372
- return;
380
+ handlePaste();
373
381
  }
374
382
  // only allow numbers
375
383
  if (e.key.match(/[0-9]/)) {
@@ -384,7 +392,8 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
384
392
  setValue((prev) => {
385
393
  if (!(selectedSegment === null || selectedSegment === void 0 ? void 0 : selectedSegment.momentType))
386
394
  return prev;
387
- const newValue = moment(prev)
395
+ const momentValue = utc ? moment.utc(prev) : moment(prev);
396
+ const newValue = moment(momentValue)
388
397
  .set(selectedSegment.momentType, parseInt(tempValue, 10) -
389
398
  (selectedSegment.type === "month" ? 1 : 0))
390
399
  .toISOString();
@@ -398,7 +407,6 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
398
407
  typedKeys.current = "";
399
408
  }
400
409
  }
401
- e.preventDefault();
402
410
  };
403
411
  const handleWheelEvent = (e) => {
404
412
  if (!selectedSegment)
@@ -430,10 +438,8 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
430
438
  });
431
439
  }
432
440
  };
433
- const handlePaste = (e) => {
434
- var _a, _b;
435
- e.preventDefault();
436
- const pastedText = (_b = (_a = e === null || e === void 0 ? void 0 : e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData) === null || _b === void 0 ? void 0 : _b.call(_a, "text");
441
+ const handlePaste = (e) => __awaiter(void 0, void 0, void 0, function* () {
442
+ const pastedText = yield window.navigator.clipboard.readText();
437
443
  if (!pastedText)
438
444
  return;
439
445
  // check if pasted text is a valid timestamp
@@ -441,7 +447,7 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
441
447
  return;
442
448
  const parsedTimestamp = moment.utc(pastedText).toISOString();
443
449
  setValue(parsedTimestamp);
444
- };
450
+ });
445
451
  // Close on outside click
446
452
  useEffect(() => {
447
453
  const close = (e) => {
@@ -473,9 +479,11 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
473
479
  return (_jsxs("div", { className: className, children: [label && (_jsx(FieldLabel, { error: error, asterisk: required, size: size, description: description, children: label })), _jsxs(StyledInputContainer, { ref: (ref) => {
474
480
  mainRef.current = ref;
475
481
  refs.setReference(ref);
476
- }, onClick: handleContainerClick, onMouseDown: handleMouseDown, onKeyDown: handleKeyDown, onPaste: handlePaste, onFocus: (e) => {
482
+ }, onClick: handleContainerClick, onMouseDown: handleMouseDown, onKeyDown: handleKeyDown, onFocus: (e) => {
477
483
  e.preventDefault();
478
484
  setSelectedSegment(segments[0]);
485
+ }, onBlur: () => {
486
+ setSelectedSegment(null);
479
487
  }, "data-empty": !value, role: "textbox", size: size, variant: variant, "data-button-right": arrow || clearable, children: [segments.map((segment, i) => {
480
488
  if (segment.type === "separator") {
481
489
  return (_jsx("div", { className: "separator", tabIndex: -1, onClick: (e) => {
@@ -483,8 +491,8 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
483
491
  e.stopPropagation();
484
492
  }, onFocus: (e) => e.preventDefault(), onPointerDown: (e) => e.preventDefault(), "data-type": "separator", "data-identifier": segment.type, "data-has-space": segment.text.includes(" "), "data-placeholder": segment.placeholder, "data-value": segment.value, children: segment.text }, i));
485
493
  }
486
- return (_jsx(InputSegment, { className: "input", contentEditable: true, suppressContentEditableWarning: true, tabIndex: i === 0 ? 0 : -1, onClick: (e) => handleSegmentClick(e, segment), "data-type": "input", size: size, "data-identifier": segment.type, "data-has-space": segment.text.includes(" "), "data-placeholder": segment.placeholder, "data-value": segment.value, "data-selected": (selectedSegment === null || selectedSegment === void 0 ? void 0 : selectedSegment.index) === segment.index, children: value ? segment.text : segment.placeholder }, i));
487
- }), utc && _jsx("div", { style: { marginLeft: 5 }, children: "UTC" }), clearable && value ? (_jsx(ClearButton, { onClick: handleClear })) : arrow ? (_jsx(ArrowButton, {})) : null] }), enableCalendar && isOpen && (_jsx(FloatingPortal, { preserveTabOrder: true, children: _jsx(StyledFloatContainer, { ref: refs.setFloating, style: floatingStyles, children: _jsx(StyledContent, { maxDropdownHeight: "fit-content", children: _jsx("div", { children: _jsx(Calendar, { defaultValue: value ? moment(value).toDate() : undefined, clearable: false, min: min, max: max, onChange: (date) => {
494
+ return (_jsx(InputSegment, { className: "input", tabIndex: i === 0 ? 0 : -1, onClick: (e) => handleSegmentClick(e, segment), "data-type": "input", size: size, "data-identifier": segment.type, "data-has-space": segment.text.includes(" "), "data-placeholder": segment.placeholder, "data-value": segment.value, "data-selected": (selectedSegment === null || selectedSegment === void 0 ? void 0 : selectedSegment.index) === segment.index, children: value ? segment.text : segment.placeholder }, i));
495
+ }), utc && _jsx("div", { style: { marginLeft: 5 }, children: "UTC" }), clearable && value ? (_jsx(ClearButton, { onClick: handleClear })) : arrow ? (_jsx(ArrowButton, {})) : null] }), enableCalendar && isOpen && (_jsx(FloatingPortal, { preserveTabOrder: true, children: _jsx(StyledFloatContainer, Object.assign({ ref: refs.setFloating, style: floatingStyles }, getReferenceProps(), { children: _jsx(StyledContent, { maxDropdownHeight: "fit-content", children: _jsx("div", { children: _jsx(Calendar, { value: value ? moment(value).toDate() : undefined, clearable: false, min: min, max: max, onChange: (date) => {
488
496
  setValue((prev) => {
489
497
  // make copy of prev variable
490
498
  const oldValue = moment(prev).toISOString();
@@ -499,6 +507,6 @@ const DateInput = styled(({ className, defaultValue, format = "YYYY-MM-DD HH:mm:
499
507
  setIsOpen(closeOnSelect ? false : true);
500
508
  return isoResult;
501
509
  });
502
- }, includeTime: false }, 1) }) }) }) }))] }));
510
+ }, includeTime: false }, 1) }) }) })) }))] }));
503
511
  }) ``;
504
512
  export default DateInput;
@@ -1,14 +1,5 @@
1
1
  import { ReactNode } from "react";
2
2
  import { Size, Variant } from "../core";
3
- 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>, {
4
- width?: string | number | null;
5
- }>> & string;
6
- type Option = {
7
- label: string;
8
- value: any;
9
- group?: string;
10
- data?: any;
11
- };
12
3
  interface SelectBoxProps {
13
4
  className?: string;
14
5
  defaultValue?: Option | string;
@@ -41,5 +32,14 @@ interface SelectBoxProps {
41
32
  }>;
42
33
  DropDownProps?: any;
43
34
  }
35
+ type Option = {
36
+ label: string;
37
+ value: any;
38
+ group?: string;
39
+ data?: any;
40
+ };
41
+ 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>, {
42
+ width?: string | number | null;
43
+ }>> & string;
44
44
  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, TooltipContent, DropDownProps, }: SelectBoxProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
45
45
  export default SelectBox;
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
13
13
  import styled from "styled-components";
14
- import { useFloating, flip, offset, FloatingPortal, } from "@floating-ui/react";
14
+ import { useFloating, flip, offset, FloatingPortal, autoUpdate, } from "@floating-ui/react";
15
15
  import { useCallback, useEffect, useRef, useState, } from "react";
16
16
  import { Input, FieldLabel, Tooltip } from "..";
17
17
  import { useDebouncedCallback } from "use-debounce";
@@ -162,8 +162,11 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
162
162
  const inputRef = useRef(null);
163
163
  const containerRef = useRef(null);
164
164
  const scrollContainerRef = useRef(null);
165
- const filteredItems = data
166
- .concat(customItems) // Add custom items to the list
165
+ const uniqueItems = Array.from(new Map([...data, ...customItems].map(item => [
166
+ isObjectArray ? item.value : item,
167
+ item
168
+ ])).values());
169
+ const filteredItems = uniqueItems
167
170
  .filter((item) => {
168
171
  const itemValue = (isObjectArray ? item.label : item);
169
172
  return itemValue === null || itemValue === void 0 ? void 0 : itemValue.toLowerCase().includes(searchValue.toLowerCase());
@@ -174,8 +177,10 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
174
177
  const bValue = b.group;
175
178
  return aValue.localeCompare(bValue);
176
179
  }
177
- // return current sort order
178
- return 0;
180
+ // Secondary sort by label/value to ensure consistent ordering
181
+ const aLabel = isObjectArray ? a.label : a;
182
+ const bLabel = isObjectArray ? b.label : b;
183
+ return aLabel.localeCompare(bLabel);
179
184
  });
180
185
  const groupedItems = grouped
181
186
  ? filteredItems.reduce((acc, item) => {
@@ -206,6 +211,7 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
206
211
  strategy: "absolute",
207
212
  // Handle collisions with the viewport
208
213
  middleware: [flip(), offset(5)],
214
+ whileElementsMounted: autoUpdate,
209
215
  });
210
216
  const toggleOpen = () => {
211
217
  setIsOpen((prev) => {
@@ -283,7 +289,6 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
283
289
  // TODO: decide what to do when user presses enter after typing a search value
284
290
  }
285
291
  toggleOpen();
286
- // setIsOpen(false);
287
292
  }
288
293
  // Arrow down
289
294
  if (e.key === "ArrowDown") {
@@ -351,6 +356,13 @@ const SelectBox = styled(({ className, data = [], placeholder = "Select...", arr
351
356
  setIsOpen(true);
352
357
  }
353
358
  };
359
+ const handleBlur = () => {
360
+ var _a;
361
+ if (allowCustomValue && ((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value)) {
362
+ handleAddItem(inputRef.current.value);
363
+ setSearchValue("");
364
+ }
365
+ };
354
366
  // Close on outside click
355
367
  useEffect(() => {
356
368
  const close = (e) => {
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
13
13
  import styled from "styled-components";
14
- import { useFloating, flip, offset } from "@floating-ui/react";
14
+ import { useFloating, flip, offset, autoUpdate } from "@floating-ui/react";
15
15
  import { useCallback, useEffect, useRef, useState } from "react";
16
16
  import { Input, Tooltip, FieldLabel, Pill } from "..";
17
17
  import { ArrowButton, ClearButton, StyledFloatContainer, StyledContent, } from "../core";
@@ -344,6 +344,7 @@ const TagBox = styled(({ className, data = [], placeholder = "Select tags", arro
344
344
  strategy: "absolute",
345
345
  // Handle collisions with the viewport
346
346
  middleware: [flip(), offset(5)],
347
+ whileElementsMounted: autoUpdate,
347
348
  });
348
349
  const toggleOpen = () => {
349
350
  setIsOpen((prev) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monolith-forensics/monolith-ui",
3
- "version": "1.1.55",
3
+ "version": "1.1.57",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Matt Danner (Monolith Forensics LLC)",