@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.
- package/Button/Button.tsx +382 -0
- package/Button/index.ts +2 -0
- package/{src/components/Calendar/Calendar.js → Calendar/Calendar.tsx} +104 -93
- package/{src/components/Calendar/CalendarStyles.js → Calendar/CalendarStyles.tsx} +26 -36
- package/{src/components/Calendar/calendarHelpers.js → Calendar/calendarHelpers.ts} +10 -8
- package/Calendar/index.ts +1 -0
- package/CheckBox/CheckBox.tsx +61 -0
- package/CheckBox/index.ts +1 -0
- package/{src/components/DateInput/DateInput.js → DateInput/DateInput.tsx} +227 -93
- package/DateInput/index.ts +1 -0
- package/DropDownMenu/DropDownMenu.tsx +402 -0
- package/DropDownMenu/index.ts +1 -0
- package/Error/Error.tsx +51 -0
- package/Error/index.ts +1 -0
- package/{src/components/FieldLabel → FieldLabel}/FieldLabel.tsx +25 -22
- package/{src/components/FileInputField/FileInputField.js → FileInputField/FileInputField.tsx} +23 -15
- package/FileInputField/index.ts +1 -0
- package/Flyout/Flyout.tsx +172 -0
- package/Flyout/FlyoutHeader.tsx +14 -0
- package/Flyout/FlyoutTitle.tsx +10 -0
- package/Flyout/index.ts +3 -0
- package/FormSection/FormSection.tsx +71 -0
- package/FormSection/index.ts +1 -0
- package/Grid/Grid.tsx +18 -0
- package/Grid/index.ts +1 -0
- package/IconButton/IconButton.tsx +27 -0
- package/IconButton/index.ts +1 -0
- package/{src/components/Input → Input}/Input.tsx +57 -34
- package/Modal/Modal.tsx +172 -0
- package/Modal/index.ts +1 -0
- package/{src/components/Pill → Pill}/Pill.tsx +41 -11
- package/SelectBox/SelectBox.tsx +745 -0
- package/SelectBox/index.ts +1 -0
- package/Switch/Switch.tsx +204 -0
- package/Switch/index.ts +1 -0
- package/TagBox/TagBox.tsx +694 -0
- package/TagBox/TagBoxStyles.tsx +116 -0
- package/TagBox/index.ts +1 -0
- package/{src/components/TextArea → TextArea}/TextArea.tsx +35 -13
- package/{src/components/TextAreaInput → TextAreaInput}/TextAreaInput.tsx +11 -13
- package/{src/components/TextInput → TextInput}/TextInput.tsx +11 -13
- package/Tooltip/Tooltip.tsx +68 -0
- package/Tooltip/index.ts +1 -0
- package/{src/components/ArrowButton → core}/ArrowButton.tsx +17 -20
- package/core/ClearButton.tsx +51 -0
- package/core/StyledContent.tsx +50 -0
- package/core/StyledFloatContainer.tsx +7 -0
- package/core/Types/Size.ts +3 -0
- package/core/Types/Variant.ts +10 -0
- package/core/index.ts +6 -0
- package/dist/Button/Button.d.ts +19 -0
- package/dist/Button/Button.js +332 -0
- package/dist/Button/index.d.ts +2 -0
- package/dist/Button/index.js +8 -0
- package/dist/Calendar/Calendar.d.ts +15 -0
- package/dist/Calendar/Calendar.js +232 -0
- package/dist/Calendar/CalendarStyles.d.ts +36 -0
- package/dist/Calendar/CalendarStyles.js +170 -0
- package/dist/Calendar/calendarHelpers.d.ts +53 -0
- package/dist/Calendar/calendarHelpers.js +181 -0
- package/dist/Calendar/index.d.ts +1 -0
- package/dist/Calendar/index.js +8 -0
- package/dist/CheckBox/CheckBox.d.ts +11 -0
- package/dist/CheckBox/CheckBox.js +34 -0
- package/dist/CheckBox/index.d.ts +1 -0
- package/dist/CheckBox/index.js +8 -0
- package/dist/DateInput/DateInput.d.ts +24 -0
- package/dist/DateInput/DateInput.js +511 -0
- package/dist/DateInput/index.d.ts +1 -0
- package/dist/DateInput/index.js +8 -0
- package/dist/DropDownMenu/DropDownMenu.d.ts +36 -0
- package/dist/DropDownMenu/DropDownMenu.js +212 -0
- package/dist/DropDownMenu/index.d.ts +1 -0
- package/dist/DropDownMenu/index.js +8 -0
- package/dist/Error/Error.d.ts +4 -0
- package/dist/Error/Error.js +38 -0
- package/dist/Error/index.d.ts +1 -0
- package/dist/Error/index.js +8 -0
- package/dist/FieldLabel/FieldLabel.d.ts +19 -0
- package/dist/FieldLabel/FieldLabel.js +119 -0
- package/dist/FieldLabel/index.d.ts +1 -0
- package/dist/FieldLabel/index.js +8 -0
- package/dist/FileInputField/FileInputField.d.ts +18 -0
- package/dist/FileInputField/FileInputField.js +116 -0
- package/dist/FileInputField/index.d.ts +1 -0
- package/dist/FileInputField/index.js +8 -0
- package/dist/Flyout/Flyout.d.ts +10 -0
- package/dist/Flyout/Flyout.js +111 -0
- package/dist/Flyout/FlyoutHeader.d.ts +5 -0
- package/dist/Flyout/FlyoutHeader.js +12 -0
- package/dist/Flyout/FlyoutTitle.d.ts +2 -0
- package/dist/Flyout/FlyoutTitle.js +13 -0
- package/dist/Flyout/index.d.ts +3 -0
- package/dist/Flyout/index.js +12 -0
- package/dist/FormSection/FormSection.d.ts +9 -0
- package/dist/FormSection/FormSection.js +51 -0
- package/dist/FormSection/index.d.ts +1 -0
- package/dist/FormSection/index.js +8 -0
- package/dist/Grid/Grid.d.ts +6 -0
- package/dist/Grid/Grid.js +15 -0
- package/dist/Grid/index.d.ts +1 -0
- package/dist/Grid/index.js +8 -0
- package/dist/IconButton/IconButton.d.ts +5 -0
- package/dist/IconButton/IconButton.js +30 -0
- package/dist/IconButton/index.d.ts +1 -0
- package/dist/IconButton/index.js +8 -0
- package/dist/Input/Input.d.ts +21 -0
- package/dist/Input/Input.js +148 -0
- package/dist/Input/index.d.ts +1 -0
- package/dist/Input/index.js +8 -0
- package/dist/Modal/Modal.d.ts +14 -0
- package/dist/Modal/Modal.js +134 -0
- package/dist/Modal/index.d.ts +1 -0
- package/dist/Modal/index.js +8 -0
- package/dist/Pill/Pill.d.ts +11 -0
- package/dist/Pill/Pill.js +146 -0
- package/dist/Pill/index.d.ts +1 -0
- package/dist/Pill/index.js +8 -0
- package/dist/SelectBox/SelectBox.d.ts +45 -0
- package/dist/SelectBox/SelectBox.js +469 -0
- package/dist/SelectBox/index.d.ts +1 -0
- package/dist/SelectBox/index.js +8 -0
- package/dist/Switch/Switch.d.ts +18 -0
- package/dist/Switch/Switch.js +157 -0
- package/dist/Switch/index.d.ts +1 -0
- package/dist/Switch/index.js +8 -0
- package/dist/TagBox/TagBox.d.ts +38 -0
- package/dist/TagBox/TagBox.js +440 -0
- package/dist/TagBox/TagBoxStyles.d.ts +11 -0
- package/dist/TagBox/TagBoxStyles.js +113 -0
- package/dist/TagBox/index.d.ts +1 -0
- package/dist/TagBox/index.js +8 -0
- package/dist/TextArea/TextArea.d.ts +16 -0
- package/dist/TextArea/TextArea.js +80 -0
- package/dist/TextArea/index.d.ts +1 -0
- package/dist/TextArea/index.js +8 -0
- package/dist/TextAreaInput/TextAreaInput.d.ts +12 -0
- package/dist/TextAreaInput/TextAreaInput.js +23 -0
- package/dist/TextAreaInput/index.d.ts +1 -0
- package/dist/TextAreaInput/index.js +8 -0
- package/dist/TextInput/TextInput.d.ts +12 -0
- package/dist/TextInput/TextInput.js +30 -0
- package/dist/TextInput/index.d.ts +1 -0
- package/dist/TextInput/index.js +8 -0
- package/dist/Tooltip/Tooltip.d.ts +12 -0
- package/dist/Tooltip/Tooltip.js +53 -0
- package/dist/Tooltip/index.d.ts +1 -0
- package/dist/Tooltip/index.js +8 -0
- package/dist/core/ArrowButton.d.ts +6 -0
- package/dist/core/ArrowButton.js +48 -0
- package/dist/core/ClearButton.d.ts +6 -0
- package/dist/core/ClearButton.js +48 -0
- package/dist/core/StyledContent.d.ts +7 -0
- package/dist/core/StyledContent.js +46 -0
- package/dist/core/StyledFloatContainer.d.ts +2 -0
- package/dist/core/StyledFloatContainer.js +10 -0
- package/dist/core/Types/Size.d.ts +2 -0
- package/dist/core/Types/Size.js +2 -0
- package/dist/core/Types/Variant.d.ts +2 -0
- package/dist/core/Types/Variant.js +2 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +14 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +51 -0
- package/index.ts +22 -0
- package/package.json +12 -21
- package/{src/components/theme → theme}/components.js +0 -2
- package/{src/components/theme → theme}/index.js +0 -1
- package/{src/components/theme → theme}/variants.js +0 -1
- package/tsconfig.json +11 -11
- package/.gitattributes +0 -2
- package/rollup.config.js +0 -10
- package/src/components/ArrowButton/index.tsx +0 -1
- package/src/components/Button/Button.tsx +0 -278
- package/src/components/Button/index.ts +0 -1
- package/src/components/SelectBox/SelectBox.js +0 -543
- package/src/components/TagBox/TagBox.js +0 -563
- package/src/components/index.ts +0 -7
- package/src/index.ts +0 -1
- /package/{src/components/FieldLabel → FieldLabel}/index.ts +0 -0
- /package/{src/components/Input/index.tsx → Input/index.ts} +0 -0
- /package/{src/components/Pill → Pill}/index.ts +0 -0
- /package/{src/components/TextArea → TextArea}/index.ts +0 -0
- /package/{src/components/TextAreaInput → TextAreaInput}/index.ts +0 -0
- /package/{src/components/TextInput/index.tsx → TextInput/index.ts} +0 -0
- /package/{src/components/core/index.js → core/MonolithThemeProvider.js} +0 -0
- /package/{src/components/theme → theme}/breakpoints.js +0 -0
- /package/{src/components/theme → theme}/shadows.js +0 -0
- /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
|
|
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 "
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
{
|
|
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
|
-
: {
|
|
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
|
|
242
|
-
description
|
|
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
|
|
250
|
-
max
|
|
251
|
-
error
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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 = (
|
|
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
|
-
|
|
444
|
-
e.target !==
|
|
445
|
-
!
|
|
446
|
-
!
|
|
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
|
-
//
|
|
457
|
-
|
|
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
|
-
<
|
|
542
|
-
<
|
|
543
|
-
<
|
|
544
|
-
<
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
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";
|