@monolith-forensics/monolith-ui 1.0.10 → 1.1.0

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.
Files changed (189) hide show
  1. package/Button/Button.tsx +382 -0
  2. package/Button/index.ts +2 -0
  3. package/{src/components/Calendar/Calendar.js → Calendar/Calendar.tsx} +104 -93
  4. package/{src/components/Calendar/CalendarStyles.js → Calendar/CalendarStyles.tsx} +26 -36
  5. package/{src/components/Calendar/calendarHelpers.js → Calendar/calendarHelpers.ts} +10 -8
  6. package/Calendar/index.ts +1 -0
  7. package/CheckBox/CheckBox.tsx +61 -0
  8. package/CheckBox/index.ts +1 -0
  9. package/{src/components/DateInput/DateInput.js → DateInput/DateInput.tsx} +227 -93
  10. package/DateInput/index.ts +1 -0
  11. package/DropDownMenu/DropDownMenu.tsx +402 -0
  12. package/DropDownMenu/index.ts +1 -0
  13. package/Error/Error.tsx +51 -0
  14. package/Error/index.ts +1 -0
  15. package/{src/components/FieldLabel → FieldLabel}/FieldLabel.tsx +25 -22
  16. package/{src/components/FileInputField/FileInputField.js → FileInputField/FileInputField.tsx} +23 -15
  17. package/FileInputField/index.ts +1 -0
  18. package/Flyout/Flyout.tsx +172 -0
  19. package/Flyout/FlyoutHeader.tsx +14 -0
  20. package/Flyout/FlyoutTitle.tsx +10 -0
  21. package/Flyout/index.ts +3 -0
  22. package/FormSection/FormSection.tsx +71 -0
  23. package/FormSection/index.ts +1 -0
  24. package/Grid/Grid.tsx +18 -0
  25. package/Grid/index.ts +1 -0
  26. package/IconButton/IconButton.tsx +27 -0
  27. package/IconButton/index.ts +1 -0
  28. package/{src/components/Input → Input}/Input.tsx +57 -34
  29. package/Modal/Modal.tsx +172 -0
  30. package/Modal/index.ts +1 -0
  31. package/{src/components/Pill → Pill}/Pill.tsx +41 -11
  32. package/SelectBox/SelectBox.tsx +745 -0
  33. package/SelectBox/index.ts +1 -0
  34. package/Switch/Switch.tsx +204 -0
  35. package/Switch/index.ts +1 -0
  36. package/TagBox/TagBox.tsx +694 -0
  37. package/TagBox/TagBoxStyles.tsx +116 -0
  38. package/TagBox/index.ts +1 -0
  39. package/{src/components/TextArea → TextArea}/TextArea.tsx +35 -13
  40. package/{src/components/TextAreaInput → TextAreaInput}/TextAreaInput.tsx +11 -13
  41. package/{src/components/TextInput → TextInput}/TextInput.tsx +11 -13
  42. package/Tooltip/Tooltip.tsx +68 -0
  43. package/Tooltip/index.ts +1 -0
  44. package/{src/components/ArrowButton → core}/ArrowButton.tsx +17 -20
  45. package/core/ClearButton.tsx +51 -0
  46. package/core/StyledContent.tsx +50 -0
  47. package/core/StyledFloatContainer.tsx +7 -0
  48. package/core/Types/Size.ts +3 -0
  49. package/core/Types/Variant.ts +10 -0
  50. package/core/index.ts +6 -0
  51. package/dist/Button/Button.d.ts +19 -0
  52. package/dist/Button/Button.js +332 -0
  53. package/dist/Button/index.d.ts +2 -0
  54. package/dist/Button/index.js +8 -0
  55. package/dist/Calendar/Calendar.d.ts +15 -0
  56. package/dist/Calendar/Calendar.js +232 -0
  57. package/dist/Calendar/CalendarStyles.d.ts +36 -0
  58. package/dist/Calendar/CalendarStyles.js +170 -0
  59. package/dist/Calendar/calendarHelpers.d.ts +53 -0
  60. package/dist/Calendar/calendarHelpers.js +181 -0
  61. package/dist/Calendar/index.d.ts +1 -0
  62. package/dist/Calendar/index.js +8 -0
  63. package/dist/CheckBox/CheckBox.d.ts +11 -0
  64. package/dist/CheckBox/CheckBox.js +34 -0
  65. package/dist/CheckBox/index.d.ts +1 -0
  66. package/dist/CheckBox/index.js +8 -0
  67. package/dist/DateInput/DateInput.d.ts +24 -0
  68. package/dist/DateInput/DateInput.js +511 -0
  69. package/dist/DateInput/index.d.ts +1 -0
  70. package/dist/DateInput/index.js +8 -0
  71. package/dist/DropDownMenu/DropDownMenu.d.ts +36 -0
  72. package/dist/DropDownMenu/DropDownMenu.js +212 -0
  73. package/dist/DropDownMenu/index.d.ts +1 -0
  74. package/dist/DropDownMenu/index.js +8 -0
  75. package/dist/Error/Error.d.ts +4 -0
  76. package/dist/Error/Error.js +38 -0
  77. package/dist/Error/index.d.ts +1 -0
  78. package/dist/Error/index.js +8 -0
  79. package/dist/FieldLabel/FieldLabel.d.ts +19 -0
  80. package/dist/FieldLabel/FieldLabel.js +119 -0
  81. package/dist/FieldLabel/index.d.ts +1 -0
  82. package/dist/FieldLabel/index.js +8 -0
  83. package/dist/FileInputField/FileInputField.d.ts +18 -0
  84. package/dist/FileInputField/FileInputField.js +116 -0
  85. package/dist/FileInputField/index.d.ts +1 -0
  86. package/dist/FileInputField/index.js +8 -0
  87. package/dist/Flyout/Flyout.d.ts +10 -0
  88. package/dist/Flyout/Flyout.js +111 -0
  89. package/dist/Flyout/FlyoutHeader.d.ts +5 -0
  90. package/dist/Flyout/FlyoutHeader.js +12 -0
  91. package/dist/Flyout/FlyoutTitle.d.ts +2 -0
  92. package/dist/Flyout/FlyoutTitle.js +13 -0
  93. package/dist/Flyout/index.d.ts +3 -0
  94. package/dist/Flyout/index.js +12 -0
  95. package/dist/FormSection/FormSection.d.ts +9 -0
  96. package/dist/FormSection/FormSection.js +51 -0
  97. package/dist/FormSection/index.d.ts +1 -0
  98. package/dist/FormSection/index.js +8 -0
  99. package/dist/Grid/Grid.d.ts +6 -0
  100. package/dist/Grid/Grid.js +15 -0
  101. package/dist/Grid/index.d.ts +1 -0
  102. package/dist/Grid/index.js +8 -0
  103. package/dist/IconButton/IconButton.d.ts +5 -0
  104. package/dist/IconButton/IconButton.js +30 -0
  105. package/dist/IconButton/index.d.ts +1 -0
  106. package/dist/IconButton/index.js +8 -0
  107. package/dist/Input/Input.d.ts +21 -0
  108. package/dist/Input/Input.js +148 -0
  109. package/dist/Input/index.d.ts +1 -0
  110. package/dist/Input/index.js +8 -0
  111. package/dist/Modal/Modal.d.ts +14 -0
  112. package/dist/Modal/Modal.js +134 -0
  113. package/dist/Modal/index.d.ts +1 -0
  114. package/dist/Modal/index.js +8 -0
  115. package/dist/Pill/Pill.d.ts +11 -0
  116. package/dist/Pill/Pill.js +146 -0
  117. package/dist/Pill/index.d.ts +1 -0
  118. package/dist/Pill/index.js +8 -0
  119. package/dist/SelectBox/SelectBox.d.ts +45 -0
  120. package/dist/SelectBox/SelectBox.js +469 -0
  121. package/dist/SelectBox/index.d.ts +1 -0
  122. package/dist/SelectBox/index.js +8 -0
  123. package/dist/Switch/Switch.d.ts +18 -0
  124. package/dist/Switch/Switch.js +157 -0
  125. package/dist/Switch/index.d.ts +1 -0
  126. package/dist/Switch/index.js +8 -0
  127. package/dist/TagBox/TagBox.d.ts +38 -0
  128. package/dist/TagBox/TagBox.js +440 -0
  129. package/dist/TagBox/TagBoxStyles.d.ts +11 -0
  130. package/dist/TagBox/TagBoxStyles.js +113 -0
  131. package/dist/TagBox/index.d.ts +1 -0
  132. package/dist/TagBox/index.js +8 -0
  133. package/dist/TextArea/TextArea.d.ts +16 -0
  134. package/dist/TextArea/TextArea.js +80 -0
  135. package/dist/TextArea/index.d.ts +1 -0
  136. package/dist/TextArea/index.js +8 -0
  137. package/dist/TextAreaInput/TextAreaInput.d.ts +12 -0
  138. package/dist/TextAreaInput/TextAreaInput.js +23 -0
  139. package/dist/TextAreaInput/index.d.ts +1 -0
  140. package/dist/TextAreaInput/index.js +8 -0
  141. package/dist/TextInput/TextInput.d.ts +12 -0
  142. package/dist/TextInput/TextInput.js +30 -0
  143. package/dist/TextInput/index.d.ts +1 -0
  144. package/dist/TextInput/index.js +8 -0
  145. package/dist/Tooltip/Tooltip.d.ts +12 -0
  146. package/dist/Tooltip/Tooltip.js +53 -0
  147. package/dist/Tooltip/index.d.ts +1 -0
  148. package/dist/Tooltip/index.js +8 -0
  149. package/dist/core/ArrowButton.d.ts +6 -0
  150. package/dist/core/ArrowButton.js +48 -0
  151. package/dist/core/ClearButton.d.ts +6 -0
  152. package/dist/core/ClearButton.js +48 -0
  153. package/dist/core/StyledContent.d.ts +7 -0
  154. package/dist/core/StyledContent.js +46 -0
  155. package/dist/core/StyledFloatContainer.d.ts +2 -0
  156. package/dist/core/StyledFloatContainer.js +10 -0
  157. package/dist/core/Types/Size.d.ts +2 -0
  158. package/dist/core/Types/Size.js +2 -0
  159. package/dist/core/Types/Variant.d.ts +2 -0
  160. package/dist/core/Types/Variant.js +2 -0
  161. package/dist/core/index.d.ts +6 -0
  162. package/dist/core/index.js +14 -0
  163. package/dist/index.d.ts +22 -0
  164. package/dist/index.js +51 -0
  165. package/index.ts +22 -0
  166. package/package.json +12 -21
  167. package/{src/components/theme → theme}/components.js +0 -2
  168. package/{src/components/theme → theme}/index.js +0 -1
  169. package/{src/components/theme → theme}/variants.js +0 -1
  170. package/tsconfig.json +11 -11
  171. package/.gitattributes +0 -2
  172. package/rollup.config.js +0 -10
  173. package/src/components/ArrowButton/index.tsx +0 -1
  174. package/src/components/Button/Button.tsx +0 -278
  175. package/src/components/Button/index.ts +0 -1
  176. package/src/components/SelectBox/SelectBox.js +0 -543
  177. package/src/components/TagBox/TagBox.js +0 -563
  178. package/src/components/index.ts +0 -7
  179. package/src/index.ts +0 -1
  180. /package/{src/components/FieldLabel → FieldLabel}/index.ts +0 -0
  181. /package/{src/components/Input/index.tsx → Input/index.ts} +0 -0
  182. /package/{src/components/Pill → Pill}/index.ts +0 -0
  183. /package/{src/components/TextArea → TextArea}/index.ts +0 -0
  184. /package/{src/components/TextAreaInput → TextAreaInput}/index.ts +0 -0
  185. /package/{src/components/TextInput/index.tsx → TextInput/index.ts} +0 -0
  186. /package/{src/components/core/index.js → core/MonolithThemeProvider.js} +0 -0
  187. /package/{src/components/theme → theme}/breakpoints.js +0 -0
  188. /package/{src/components/theme → theme}/shadows.js +0 -0
  189. /package/{src/components/theme → theme}/typography.js +0 -0
@@ -1,17 +1,27 @@
1
1
  import moment from "moment";
2
- import { useFloating, flip, offset } from "@floating-ui/react";
3
- import { useEffect, useMemo, useRef, useState } from "react";
2
+ import { useFloating, flip, offset, FloatingPortal } from "@floating-ui/react";
3
+ import React, {
4
+ MutableRefObject,
5
+ useEffect,
6
+ useMemo,
7
+ useRef,
8
+ useState,
9
+ } from "react";
4
10
  import styled from "styled-components";
5
- import FieldLabel from "../FieldLabel/FieldLabel.js";
6
- import Calendar from "../Calendar/Calendar.js";
11
+ import { FieldLabel, Calendar } from "..";
7
12
  import {
8
- ArrowButton,
9
- ClearButton,
10
13
  StyledContent,
11
14
  StyledFloatContainer,
12
- } from "../SelectBox/SelectBox.js";
13
-
14
- const StyledInputContainer = styled.div`
15
+ ArrowButton,
16
+ ClearButton,
17
+ Size,
18
+ Variant,
19
+ } from "../core";
20
+
21
+ const StyledInputContainer = styled.div<{
22
+ size: Size;
23
+ variant: Variant;
24
+ }>`
15
25
  position: relative;
16
26
 
17
27
  caret-color: transparent;
@@ -40,7 +50,9 @@ const StyledInputContainer = styled.div`
40
50
  return theme.palette.input.border;
41
51
  }
42
52
  }};
43
- font-weight: 500;
53
+
54
+ font-family: ${({ theme }) => theme.typography.fontFamily};
55
+
44
56
  color: ${(props) => props.theme.palette.text.primary};
45
57
  font-size: ${({ size }) =>
46
58
  size === "xs"
@@ -130,7 +142,9 @@ const StyledInputContainer = styled.div`
130
142
  }
131
143
  `;
132
144
 
133
- const InputSegment = styled.div`
145
+ const InputSegment = styled.div<{
146
+ size: Size;
147
+ }>`
134
148
  user-select: none;
135
149
  display: flex;
136
150
  flex-direction: row;
@@ -174,7 +188,21 @@ const InputSegment = styled.div`
174
188
  }
175
189
  `;
176
190
 
177
- function parseTimestamp(timestamp, format, utc = false) {
191
+ type Segment = {
192
+ value: string;
193
+ text: string;
194
+ placeholder: string;
195
+ type: moment.unitOfTime.DurationConstructor | "separator";
196
+ index: number;
197
+ momentType?: moment.unitOfTime.All | moment.unitOfTime.DurationConstructor;
198
+ pattern?: string;
199
+ };
200
+
201
+ function parseTimestamp(
202
+ timestamp: string,
203
+ format: string,
204
+ utc = false
205
+ ): Segment[] {
178
206
  // Define patterns to identify datetime components and their placeholders
179
207
  const patterns = [
180
208
  { pattern: "YYYY", placeholder: "YYYY", type: "year", momentType: "year" },
@@ -188,7 +216,7 @@ function parseTimestamp(timestamp, format, utc = false) {
188
216
  pattern: "SSS",
189
217
  placeholder: "SSS",
190
218
  type: "millisecond",
191
- moment: "millisecond",
219
+ momentType: "millisecond",
192
220
  },
193
221
  {
194
222
  pattern: "A",
@@ -196,20 +224,32 @@ function parseTimestamp(timestamp, format, utc = false) {
196
224
  type: "meridiem",
197
225
  momentType: "meridiem",
198
226
  },
199
- { pattern: "Z", placeholder: "Z", type: "timezone", moment: "timezone" },
200
- ];
227
+ {
228
+ pattern: "Z",
229
+ placeholder: "Z",
230
+ type: "timezone",
231
+ momentType: "timezone",
232
+ },
233
+ ] as Segment[];
201
234
 
202
235
  // Helper function to split format into datetime components and separators
203
- function splitFormat(format) {
236
+ function splitFormat(format: string) {
204
237
  return format.split(/(YYYY|MM|DD|HH|h|mm|ss|SSS|Z)/).filter((s) => s);
205
238
  }
206
239
 
207
240
  // Helper function to match segments to their placeholders and types
208
- function matchSegment(segment) {
241
+ function matchSegment(segment: string): Segment {
209
242
  const pattern = patterns.find((p) => p.pattern === segment);
210
243
  return pattern
211
244
  ? pattern
212
- : { pattern: segment, placeholder: segment, type: "separator" };
245
+ : {
246
+ pattern: segment,
247
+ placeholder: segment,
248
+ type: "separator",
249
+ value: "",
250
+ text: "",
251
+ index: -1,
252
+ };
213
253
  }
214
254
 
215
255
  const segments = splitFormat(format).map((segment, i) => {
@@ -233,35 +273,58 @@ function parseTimestamp(timestamp, format, utc = false) {
233
273
  return segments;
234
274
  }
235
275
 
276
+ interface DateInputProps {
277
+ className?: string;
278
+ defaultValue?: string | null;
279
+ format?: string;
280
+ label?: string;
281
+ description?: string;
282
+ arrow?: boolean;
283
+ size?: Size;
284
+ variant?: Variant;
285
+ clearable?: boolean;
286
+ required?: boolean;
287
+ onChange?: (value: string | null) => void;
288
+ min?: Date;
289
+ max?: Date;
290
+ error?: string;
291
+ width?: string;
292
+ enableCalendar?: boolean;
293
+ utc?: boolean;
294
+ closeOnSelect?: boolean;
295
+ }
296
+
236
297
  const DateInput = styled(
237
298
  ({
238
299
  className,
239
- defaultValue,
300
+ defaultValue = null,
240
301
  format = "YYYY-MM-DD HH:mm:ss",
241
- label = null,
242
- description = null,
302
+ label,
303
+ description,
243
304
  arrow = true,
244
305
  size = "sm",
245
306
  variant = "outlined",
246
307
  clearable = false,
247
308
  required = false,
248
309
  onChange = () => {},
249
- min = null,
250
- max = null,
251
- error = false,
252
- width = null,
310
+ min,
311
+ max,
312
+ error,
253
313
  enableCalendar = false,
254
314
  utc = false,
255
315
  closeOnSelect = true,
256
- }) => {
257
- const [value, setValue] = useState(defaultValue);
258
- const [selectedSegment, setSelectedSegment] = useState(null);
316
+ }: DateInputProps) => {
317
+ const [value, setValue] = useState<string | null>(defaultValue);
318
+ const [selectedSegment, setSelectedSegment] = useState<
319
+ Segment | null | undefined
320
+ >();
259
321
  const [isOpen, setIsOpen] = useState(false);
260
322
 
261
323
  // Check if format is date only and does not include time
262
324
  const isDateOnly = format.match(/(HH|h|mm|ss|SSS|A|Z)/) === null;
263
325
 
264
- const mainRef = useRef(null);
326
+ const mainRef: MutableRefObject<HTMLElement | null> =
327
+ useRef<HTMLElement>(null);
265
328
 
266
329
  const typedKeys = useRef("");
267
330
 
@@ -274,13 +337,12 @@ const DateInput = styled(
274
337
  middleware: [flip(), offset(5)],
275
338
  });
276
339
 
277
- const segments = useMemo(
278
- () =>
279
- parseTimestamp(value ? moment(value).toISOString() : null, format, utc),
280
- [value, format]
340
+ const segments: Segment[] = useMemo(
341
+ () => parseTimestamp(moment(value).toISOString(), format, utc),
342
+ [value, format, utc]
281
343
  );
282
344
 
283
- const checkValidRange = (value) => {
345
+ const checkValidRange = (value: string) => {
284
346
  if (min && moment(value).isBefore(min)) return false;
285
347
  if (max && moment(value).isAfter(max)) return false;
286
348
  return true;
@@ -292,7 +354,7 @@ const DateInput = styled(
292
354
  });
293
355
  };
294
356
 
295
- const handleClear = (e) => {
357
+ const handleClear = (e: React.MouseEvent) => {
296
358
  e.preventDefault();
297
359
  e.stopPropagation();
298
360
 
@@ -301,18 +363,32 @@ const DateInput = styled(
301
363
  setIsOpen(false);
302
364
  };
303
365
 
304
- const handleSegmentClick = (e, segment) => {
366
+ const handleSegmentClick = (e: React.MouseEvent, segment: Segment) => {
305
367
  e.stopPropagation();
306
368
  e.preventDefault();
307
369
  if (segment.type === "separator") return;
308
- mainRef.current.querySelector("div[data-type='input']").focus();
370
+ if (mainRef?.current) {
371
+ const input: HTMLInputElement | null = mainRef.current.querySelector(
372
+ "div[data-type='input']"
373
+ );
374
+ if (input) {
375
+ input.focus();
376
+ }
377
+ }
309
378
  setSelectedSegment(segment);
310
379
  };
311
380
 
312
- const handleContainerClick = (e) => {
381
+ const handleContainerClick = (e: React.MouseEvent) => {
313
382
  e.stopPropagation();
314
383
  e.preventDefault();
315
- mainRef.current.querySelector("div[data-type='input']").focus();
384
+ if (mainRef?.current) {
385
+ const input: HTMLInputElement | null = mainRef.current.querySelector(
386
+ "div[data-type='input']"
387
+ );
388
+ if (input) {
389
+ input.focus();
390
+ }
391
+ }
316
392
  toggleOpen();
317
393
  setIsOpen(true);
318
394
  setSelectedSegment(segments[0]);
@@ -320,24 +396,20 @@ const DateInput = styled(
320
396
 
321
397
  const nextSegment = () => {
322
398
  setSelectedSegment((prev) => {
399
+ if (!prev) return segments[0];
323
400
  const next = segments[prev.index + 2];
324
401
  return next || prev;
325
402
  });
326
403
  };
327
404
 
328
- const prevSegment = () => {
329
- setSelectedSegment((prev) => {
330
- const next = segments[prev.index - 2];
331
- return next || prev;
332
- });
333
- };
334
-
335
405
  // prevent click and drag selection
336
- const handleMouseDown = (e) => {
406
+ const handleMouseDown = (
407
+ e: React.MouseEvent<HTMLDivElement, MouseEvent>
408
+ ) => {
337
409
  e.preventDefault();
338
410
  };
339
411
 
340
- const handleKeyDown = (e) => {
412
+ const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
341
413
  if (!selectedSegment) return;
342
414
  // tab
343
415
  if (e.key === "Tab") {
@@ -350,6 +422,7 @@ const DateInput = styled(
350
422
  e.preventDefault();
351
423
 
352
424
  setSelectedSegment((prev) => {
425
+ if (!prev) return segments[0];
353
426
  const next = segments[prev.index + 2];
354
427
  return next || prev;
355
428
  });
@@ -358,6 +431,7 @@ const DateInput = styled(
358
431
  if (e.key === "ArrowLeft") {
359
432
  e.preventDefault();
360
433
  setSelectedSegment((prev) => {
434
+ if (!prev) return segments[0];
361
435
  const next = segments[prev.index - 2];
362
436
  return next || prev;
363
437
  });
@@ -368,6 +442,7 @@ const DateInput = styled(
368
442
  e.preventDefault();
369
443
 
370
444
  setValue((prev) => {
445
+ if (selectedSegment.type === "separator") return prev;
371
446
  let newValue = prev
372
447
  ? moment(prev).add(1, selectedSegment.type).toISOString()
373
448
  : moment().toISOString();
@@ -385,6 +460,7 @@ const DateInput = styled(
385
460
  e.preventDefault();
386
461
 
387
462
  setValue((prev) => {
463
+ if (selectedSegment.type === "separator") return prev;
388
464
  let newValue = prev
389
465
  ? moment(prev).subtract(1, selectedSegment.type).toISOString()
390
466
  : moment().toISOString();
@@ -399,6 +475,11 @@ const DateInput = styled(
399
475
  });
400
476
  }
401
477
 
478
+ // handle paste
479
+ if (e.key === "v" && (e.metaKey || e.ctrlKey)) {
480
+ return;
481
+ }
482
+
402
483
  // only allow numbers
403
484
  if (e.key.match(/[0-9]/)) {
404
485
  e.preventDefault();
@@ -415,6 +496,7 @@ const DateInput = styled(
415
496
  }
416
497
 
417
498
  setValue((prev) => {
499
+ if (!selectedSegment?.momentType) return prev;
418
500
  const newValue = moment(prev)
419
501
  .set(
420
502
  selectedSegment.momentType,
@@ -436,14 +518,57 @@ const DateInput = styled(
436
518
  e.preventDefault();
437
519
  };
438
520
 
521
+ const handleWheelEvent = (e: WheelEvent) => {
522
+ if (!selectedSegment) return;
523
+
524
+ if (e.deltaY > 0) {
525
+ setValue((prev) => {
526
+ if (selectedSegment.type === "separator") return prev;
527
+ const newValue = prev
528
+ ? moment(prev).subtract(1, selectedSegment.type).toISOString()
529
+ : moment().toISOString();
530
+ if (!checkValidRange(newValue)) return prev;
531
+ onChange?.(newValue);
532
+ return newValue;
533
+ });
534
+ } else {
535
+ setValue((prev) => {
536
+ if (selectedSegment.type === "separator") return prev;
537
+ const newValue = prev
538
+ ? moment(prev).add(1, selectedSegment.type).toISOString()
539
+ : moment().toISOString();
540
+ if (!checkValidRange(newValue)) return prev;
541
+ onChange?.(newValue);
542
+ return newValue;
543
+ });
544
+ }
545
+ };
546
+
547
+ const handlePaste = (e: React.ClipboardEvent<HTMLDivElement>) => {
548
+ e.preventDefault();
549
+ const pastedText = e?.clipboardData?.getData?.("text");
550
+ if (!pastedText) return;
551
+
552
+ // check if pasted text is a valid timestamp
553
+ if (!moment(pastedText).isValid()) return;
554
+
555
+ const parsedTimestamp = moment.utc(pastedText).toISOString();
556
+
557
+ setValue(parsedTimestamp);
558
+ };
559
+
439
560
  // Close on outside click
440
561
  useEffect(() => {
441
- const close = (e) => {
562
+ const close = (e: MouseEvent) => {
563
+ const target = e.target as Node;
564
+ const referenceElement = refs?.reference?.current as Node;
565
+ const floatingElement = refs?.floating?.current as Node;
566
+
442
567
  if (
443
- refs.floating.current && // Check if the floating element exists
444
- e.target !== refs.reference.current && // Check if the target is not the reference (input)
445
- !refs.reference.current.contains(e.target) && // Check if the target is not inside the reference (input)
446
- !refs.floating.current.contains(e.target) // Check if the target is not inside the floating element (content)
568
+ floatingElement && // Check if the floating element exists
569
+ e.target !== referenceElement && // Check if the target is not the reference (input)
570
+ !referenceElement.contains(target) && // Check if the target is not inside the reference (input)
571
+ !floatingElement.contains(target) // Check if the target is not inside the floating element (content)
447
572
  ) {
448
573
  setIsOpen(false);
449
574
  }
@@ -453,11 +578,18 @@ const DateInput = styled(
453
578
  return () => document.removeEventListener("click", close);
454
579
  }, [refs.floating]);
455
580
 
456
- // const contentWidth =
457
- // refs?.reference?.current?.getClientRects?.()?.[0]?.width || "100%";
581
+ // Global Wheel Event when segement selected
582
+ useEffect(() => {
583
+ if (selectedSegment) {
584
+ document.addEventListener("wheel", handleWheelEvent);
585
+ }
586
+ return () => {
587
+ document.removeEventListener("wheel", handleWheelEvent);
588
+ };
589
+ }, [selectedSegment]);
458
590
 
459
591
  return (
460
- <div>
592
+ <div className={className}>
461
593
  {label && (
462
594
  <FieldLabel
463
595
  error={error}
@@ -476,6 +608,7 @@ const DateInput = styled(
476
608
  onClick={handleContainerClick}
477
609
  onMouseDown={handleMouseDown}
478
610
  onKeyDown={handleKeyDown}
611
+ onPaste={handlePaste}
479
612
  onFocus={(e) => {
480
613
  e.preventDefault();
481
614
  setSelectedSegment(segments[0]);
@@ -484,7 +617,6 @@ const DateInput = styled(
484
617
  role="textbox"
485
618
  size={size}
486
619
  variant={variant}
487
- width={width}
488
620
  data-button-right={arrow || clearable}
489
621
  >
490
622
  {segments.map((segment, i) => {
@@ -538,42 +670,44 @@ const DateInput = styled(
538
670
  ) : null}
539
671
  </StyledInputContainer>
540
672
  {enableCalendar && isOpen && (
541
- <StyledFloatContainer ref={refs.setFloating} style={floatingStyles}>
542
- <StyledContent maxDropdownHeight="fit-content">
543
- <div>
544
- <Calendar
545
- key={1}
546
- date={moment(value).toDate()}
547
- clearable={false}
548
- min={min}
549
- max={max}
550
- // hourFormat={hourFormat}
551
- onDateChanged={(date) => {
552
- setValue((prev) => {
553
- // make copy of prev variable
554
- const oldValue = moment(prev).toISOString();
555
-
556
- const result = `${moment(date).format(
557
- "YYYY-MM-DD"
558
- )}T${moment(prev || undefined).format("HH:mm:ss")}`;
559
-
560
- let isoResult = moment(result).toISOString();
561
-
562
- if (!checkValidRange(result)) return oldValue;
563
-
564
- if (isDateOnly) {
565
- isoResult = moment(result).format("YYYY-MM-DD");
566
- }
567
- onChange?.(isoResult);
568
- setIsOpen(closeOnSelect ? false : true);
569
- return isoResult;
570
- });
571
- }}
572
- includeTime={false}
573
- />
574
- </div>
575
- </StyledContent>
576
- </StyledFloatContainer>
673
+ <FloatingPortal preserveTabOrder>
674
+ <StyledFloatContainer ref={refs.setFloating} style={floatingStyles}>
675
+ <StyledContent maxDropdownHeight="fit-content">
676
+ <div>
677
+ <Calendar
678
+ key={1}
679
+ value={moment(value).toDate()}
680
+ clearable={false}
681
+ min={min}
682
+ max={max}
683
+ // hourFormat={hourFormat}
684
+ onChange={(date) => {
685
+ setValue((prev) => {
686
+ // make copy of prev variable
687
+ const oldValue = moment(prev).toISOString();
688
+
689
+ const result = `${moment(date).format(
690
+ "YYYY-MM-DD"
691
+ )}T${moment(prev || undefined).format("HH:mm:ss")}`;
692
+
693
+ let isoResult = moment(result).toISOString();
694
+
695
+ if (!checkValidRange(result)) return oldValue;
696
+
697
+ if (isDateOnly) {
698
+ isoResult = moment(result).format("YYYY-MM-DD");
699
+ }
700
+ onChange?.(isoResult);
701
+ setIsOpen(closeOnSelect ? false : true);
702
+ return isoResult;
703
+ });
704
+ }}
705
+ includeTime={false}
706
+ />
707
+ </div>
708
+ </StyledContent>
709
+ </StyledFloatContainer>
710
+ </FloatingPortal>
577
711
  )}
578
712
  </div>
579
713
  );
@@ -0,0 +1 @@
1
+ export { default } from "./DateInput";