@bigbinary/neeto-atoms 1.1.1 → 1.1.3
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/dist/{DatePicker-BC9AOZJ2.js → DatePicker-CMlA-hNW.js} +478 -280
- package/dist/DatePicker-CMlA-hNW.js.map +1 -0
- package/dist/{TranslationProvider-BJjfFEgX.js → TranslationProvider-DKdbPweu.js} +9 -2
- package/dist/{TranslationProvider-BJjfFEgX.js.map → TranslationProvider-DKdbPweu.js.map} +1 -1
- package/dist/cjs/{DatePicker-aGLz-3Bz.js → DatePicker-CBxWLALJ.js} +477 -279
- package/dist/cjs/DatePicker-CBxWLALJ.js.map +1 -0
- package/dist/cjs/{TranslationProvider-C1JDwKEN.js → TranslationProvider-Cao2ugzJ.js} +9 -2
- package/dist/cjs/{TranslationProvider-C1JDwKEN.js.map → TranslationProvider-Cao2ugzJ.js.map} +1 -1
- package/dist/cjs/components/DatePicker.js +1 -1
- package/dist/cjs/components/TranslationProvider.js +1 -1
- package/dist/cjs/components/index.js +2 -2
- package/dist/cjs/formik/Form.js +1 -0
- package/dist/cjs/formik/Form.js.map +1 -1
- package/dist/cjs/index.js +5 -5
- package/dist/components/DatePicker/DatePickerFooter.d.ts +1 -1
- package/dist/components/DatePicker/RangeCalendar.d.ts +2 -1
- package/dist/components/DatePicker/RangeTimeSection.d.ts +37 -0
- package/dist/components/DatePicker/SegmentedTimeInput.d.ts +7 -1
- package/dist/components/DatePicker/TimeSection.d.ts +3 -0
- package/dist/components/DatePicker/types.d.ts +5 -2
- package/dist/components/DatePicker/useRangePicker.d.ts +4 -2
- package/dist/components/DatePicker/utils.d.ts +2 -1
- package/dist/components/DatePicker.js +1 -1
- package/dist/components/TranslationProvider.js +1 -1
- package/dist/components/index.js +2 -2
- package/dist/formik/Form.js +1 -0
- package/dist/formik/Form.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/translations/index.d.ts +7 -0
- package/package.json +1 -1
- package/dist/DatePicker-BC9AOZJ2.js.map +0 -1
- package/dist/cjs/DatePicker-aGLz-3Bz.js.map +0 -1
|
@@ -194,8 +194,8 @@ const getDisplayFormat = (dateFormat, timeFormat, showTime) => {
|
|
|
194
194
|
const fmt = showTime ? `${dateFormat} ${timeFormat}` : dateFormat;
|
|
195
195
|
return normalizeToDateFnsFormat(fmt);
|
|
196
196
|
};
|
|
197
|
-
const getDatePlaceholder = (dateFormat,
|
|
198
|
-
const single =
|
|
197
|
+
const getDatePlaceholder = (dateFormat, type) => {
|
|
198
|
+
const single = dateFormat.toUpperCase();
|
|
199
199
|
return type === "range" ? `${single} - ${single}` : single;
|
|
200
200
|
};
|
|
201
201
|
const isDatePartComplete = (part, maskEnabled, singleDateLen) => maskEnabled ? part.length >= singleDateLen : part.length > 0;
|
|
@@ -208,6 +208,7 @@ const parseRangeText = (text, displayFormat, maskEnabled, singleDateLen) => {
|
|
|
208
208
|
const to = parseDate(parts[1], displayFormat);
|
|
209
209
|
return from && to ? [from, to] : null;
|
|
210
210
|
};
|
|
211
|
+
const startOfDay = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
211
212
|
const startOfWeek = (date, weekStartsOn = 0) => {
|
|
212
213
|
const d = new Date(date);
|
|
213
214
|
const diff = (d.getDay() - weekStartsOn + 7) % 7;
|
|
@@ -268,10 +269,12 @@ const computeRangePreview = ({
|
|
|
268
269
|
let from = pendingRange ? pendingRange[0] : committed?.[0] ?? null;
|
|
269
270
|
let to = pendingRange ? pendingRange[1] : committed?.[1] ?? null;
|
|
270
271
|
if (hoveredDate) {
|
|
271
|
-
if (rangeStep === "from"
|
|
272
|
-
from
|
|
273
|
-
|
|
274
|
-
|
|
272
|
+
if (rangeStep === "from") {
|
|
273
|
+
if (!(from && to)) {
|
|
274
|
+
from = hoveredDate;
|
|
275
|
+
if (to && hoveredDate.getTime() > to.getTime()) to = null;
|
|
276
|
+
}
|
|
277
|
+
} else if (!isSameDay(from, hoveredDate)) {
|
|
275
278
|
to = hoveredDate;
|
|
276
279
|
if (from && hoveredDate.getTime() < from.getTime()) from = null;
|
|
277
280
|
}
|
|
@@ -317,7 +320,7 @@ const DatePickerFooter = ({
|
|
|
317
320
|
showNow = true,
|
|
318
321
|
onNow,
|
|
319
322
|
onOk,
|
|
320
|
-
|
|
323
|
+
okDisabled = false,
|
|
321
324
|
className
|
|
322
325
|
}) => {
|
|
323
326
|
const showOkButton = showTime || needConfirm;
|
|
@@ -349,7 +352,16 @@ const DatePickerFooter = ({
|
|
|
349
352
|
className: "me-2"
|
|
350
353
|
}
|
|
351
354
|
),
|
|
352
|
-
showOkButton && /* @__PURE__ */ jsxRuntime.jsx(
|
|
355
|
+
showOkButton && /* @__PURE__ */ jsxRuntime.jsx(
|
|
356
|
+
primitives_Button.Button,
|
|
357
|
+
{
|
|
358
|
+
size: "sm",
|
|
359
|
+
disabled: okDisabled,
|
|
360
|
+
onClick: onOk,
|
|
361
|
+
className: "text-xs",
|
|
362
|
+
children: "OK"
|
|
363
|
+
}
|
|
364
|
+
)
|
|
353
365
|
]
|
|
354
366
|
}
|
|
355
367
|
);
|
|
@@ -654,149 +666,160 @@ const parsePastedTime = (text, step = 1) => {
|
|
|
654
666
|
};
|
|
655
667
|
|
|
656
668
|
const PLACEHOLDERS = ["hh", "mm", "--"];
|
|
657
|
-
const SegmentedTimeInput = (
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
if (utils$2.timeValueEquals(value, lastEmittedRef.current)) return;
|
|
676
|
-
lastEmittedRef.current = value;
|
|
677
|
-
setTime(segmentedTimeFromValue(value, step));
|
|
678
|
-
}, [value]);
|
|
679
|
-
const error = getSegmentedTimeError(time);
|
|
680
|
-
React.useEffect(() => {
|
|
681
|
-
onErrorChange(error);
|
|
682
|
-
}, [error, onErrorChange]);
|
|
683
|
-
React.useEffect(() => {
|
|
684
|
-
const snapped = segmentedTimeToValue(time);
|
|
685
|
-
if (snapped && !utils$2.timeValueEquals(snapped, value)) {
|
|
686
|
-
lastEmittedRef.current = snapped;
|
|
687
|
-
onChange(snapped);
|
|
688
|
-
}
|
|
689
|
-
}, []);
|
|
690
|
-
React.useEffect(() => {
|
|
691
|
-
if (autoFocus) fieldRef.current?.focus();
|
|
692
|
-
}, [autoFocus]);
|
|
693
|
-
const update = (next) => {
|
|
694
|
-
setTime(next);
|
|
695
|
-
const nextValue = segmentedTimeToValue(next);
|
|
696
|
-
if (!nextValue || utils$2.timeValueEquals(nextValue, lastEmittedRef.current)) {
|
|
697
|
-
return;
|
|
698
|
-
}
|
|
699
|
-
lastEmittedRef.current = nextValue;
|
|
700
|
-
onChange(nextValue);
|
|
701
|
-
};
|
|
702
|
-
const consume = (event) => {
|
|
703
|
-
event.preventDefault();
|
|
704
|
-
event.stopPropagation();
|
|
705
|
-
};
|
|
706
|
-
const handleKeyDown = (event) => {
|
|
707
|
-
const { key } = event;
|
|
708
|
-
if (key === "Tab") {
|
|
709
|
-
if (!event.shiftKey || time.active !== 2) return;
|
|
710
|
-
consume(event);
|
|
711
|
-
update(togglePeriod(time));
|
|
712
|
-
return;
|
|
713
|
-
}
|
|
714
|
-
if ((event.metaKey || event.ctrlKey) && key === "Backspace") {
|
|
715
|
-
consume(event);
|
|
716
|
-
update(emptySegmentedTime());
|
|
717
|
-
return;
|
|
718
|
-
}
|
|
719
|
-
if (event.metaKey || event.ctrlKey || event.altKey) return;
|
|
720
|
-
let next = null;
|
|
721
|
-
if (/^[0-9]$/.test(key)) next = typeDigit(time, key, step);
|
|
722
|
-
else if (/^[ap]$/i.test(key)) {
|
|
723
|
-
next = typePeriod(time, key.toLowerCase(), step);
|
|
724
|
-
} else if (/^m$/i.test(key))
|
|
725
|
-
next = time;
|
|
726
|
-
else if (key === ":" || key === " " || key === "ArrowRight") {
|
|
727
|
-
next = nextSegment(time, step);
|
|
728
|
-
} else if (key === "ArrowLeft") next = previousSegment(time);
|
|
729
|
-
else if (key === "ArrowUp") next = stepSegment(time, 1, step);
|
|
730
|
-
else if (key === "ArrowDown") next = stepSegment(time, -1, step);
|
|
731
|
-
else if (key === "Backspace" || key === "Delete") next = backspace(time);
|
|
732
|
-
if (!next) return;
|
|
733
|
-
consume(event);
|
|
734
|
-
update(next);
|
|
735
|
-
};
|
|
736
|
-
const handlePaste = (event) => {
|
|
737
|
-
event.preventDefault();
|
|
738
|
-
const pasted = parsePastedTime(event.clipboardData.getData("text"), step);
|
|
739
|
-
if (pasted) update({ ...segmentedTimeFromValue(pasted, step), active: 2 });
|
|
740
|
-
};
|
|
741
|
-
const handleMouseDown = (event) => {
|
|
742
|
-
if (disabled) return;
|
|
743
|
-
const segmentEl = event.target.closest(
|
|
744
|
-
"[data-segment]"
|
|
669
|
+
const SegmentedTimeInput = React.forwardRef(
|
|
670
|
+
({
|
|
671
|
+
value,
|
|
672
|
+
minuteStep,
|
|
673
|
+
onChange,
|
|
674
|
+
onErrorChange,
|
|
675
|
+
invalid = false,
|
|
676
|
+
disabled = false,
|
|
677
|
+
autoFocus = false,
|
|
678
|
+
"aria-label": ariaLabel,
|
|
679
|
+
"aria-describedby": ariaDescribedBy,
|
|
680
|
+
"data-testid": dataTestId = "datepicker-time-input"
|
|
681
|
+
}, ref) => {
|
|
682
|
+
const { t } = reactI18next.useTranslation();
|
|
683
|
+
const fieldRef = React.useRef(null);
|
|
684
|
+
const step = minuteStep ?? 1;
|
|
685
|
+
const [time, setTime] = React.useState(
|
|
686
|
+
() => segmentedTimeFromValue(value, step)
|
|
745
687
|
);
|
|
746
|
-
|
|
688
|
+
const lastEmittedRef = React.useRef(value);
|
|
689
|
+
React.useEffect(() => {
|
|
690
|
+
if (utils$2.timeValueEquals(value, lastEmittedRef.current)) return;
|
|
691
|
+
lastEmittedRef.current = value;
|
|
692
|
+
setTime(segmentedTimeFromValue(value, step));
|
|
693
|
+
}, [value]);
|
|
694
|
+
const error = getSegmentedTimeError(time);
|
|
695
|
+
React.useEffect(() => {
|
|
696
|
+
onErrorChange(error);
|
|
697
|
+
}, [error, onErrorChange]);
|
|
698
|
+
React.useEffect(() => {
|
|
699
|
+
const snapped = segmentedTimeToValue(time);
|
|
700
|
+
if (snapped && !utils$2.timeValueEquals(snapped, value)) {
|
|
701
|
+
lastEmittedRef.current = snapped;
|
|
702
|
+
onChange(snapped);
|
|
703
|
+
}
|
|
704
|
+
}, []);
|
|
705
|
+
React.useEffect(() => {
|
|
706
|
+
if (autoFocus) fieldRef.current?.focus();
|
|
707
|
+
}, [autoFocus]);
|
|
708
|
+
React.useImperativeHandle(ref, () => ({
|
|
709
|
+
focusHour: () => {
|
|
710
|
+
fieldRef.current?.focus();
|
|
711
|
+
setTime((current) => ({ ...current, active: 0 }));
|
|
712
|
+
}
|
|
713
|
+
}));
|
|
714
|
+
const update = (next) => {
|
|
715
|
+
setTime(next);
|
|
716
|
+
const nextValue = segmentedTimeToValue(next);
|
|
717
|
+
if (!nextValue || utils$2.timeValueEquals(nextValue, lastEmittedRef.current)) {
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
lastEmittedRef.current = nextValue;
|
|
721
|
+
onChange(nextValue);
|
|
722
|
+
};
|
|
723
|
+
const consume = (event) => {
|
|
747
724
|
event.preventDefault();
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
)
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
725
|
+
event.stopPropagation();
|
|
726
|
+
};
|
|
727
|
+
const handleKeyDown = (event) => {
|
|
728
|
+
const { key } = event;
|
|
729
|
+
if (key === "Tab") {
|
|
730
|
+
if (!event.shiftKey || time.active !== 2) return;
|
|
731
|
+
consume(event);
|
|
732
|
+
update(togglePeriod(time));
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
if ((event.metaKey || event.ctrlKey) && key === "Backspace") {
|
|
736
|
+
consume(event);
|
|
737
|
+
update(emptySegmentedTime());
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
if (event.metaKey || event.ctrlKey || event.altKey) return;
|
|
741
|
+
let next = null;
|
|
742
|
+
if (/^[0-9]$/.test(key)) next = typeDigit(time, key, step);
|
|
743
|
+
else if (/^[ap]$/i.test(key)) {
|
|
744
|
+
next = typePeriod(time, key.toLowerCase(), step);
|
|
745
|
+
} else if (/^m$/i.test(key))
|
|
746
|
+
next = time;
|
|
747
|
+
else if (key === ":" || key === " " || key === "ArrowRight") {
|
|
748
|
+
next = nextSegment(time, step);
|
|
749
|
+
} else if (key === "ArrowLeft") next = previousSegment(time);
|
|
750
|
+
else if (key === "ArrowUp") next = stepSegment(time, 1, step);
|
|
751
|
+
else if (key === "ArrowDown") next = stepSegment(time, -1, step);
|
|
752
|
+
else if (key === "Backspace" || key === "Delete") next = backspace(time);
|
|
753
|
+
if (!next) return;
|
|
754
|
+
consume(event);
|
|
755
|
+
update(next);
|
|
756
|
+
};
|
|
757
|
+
const handlePaste = (event) => {
|
|
758
|
+
event.preventDefault();
|
|
759
|
+
const pasted = parsePastedTime(event.clipboardData.getData("text"), step);
|
|
760
|
+
if (pasted)
|
|
761
|
+
update({ ...segmentedTimeFromValue(pasted, step), active: 2 });
|
|
762
|
+
};
|
|
763
|
+
const handleMouseDown = (event) => {
|
|
764
|
+
if (disabled) return;
|
|
765
|
+
const segmentEl = event.target.closest(
|
|
766
|
+
"[data-segment]"
|
|
767
|
+
);
|
|
768
|
+
if (segmentEl) {
|
|
769
|
+
event.preventDefault();
|
|
770
|
+
fieldRef.current?.focus();
|
|
771
|
+
update(focusSegment(time, Number(segmentEl.dataset.segment), step));
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
update(focusFirstEmptySegment(time));
|
|
775
|
+
};
|
|
776
|
+
const segmentText = (index) => {
|
|
777
|
+
const { text, done } = time[SEGMENT_KEYS[index]];
|
|
778
|
+
if (!text) return PLACEHOLDERS[index];
|
|
779
|
+
return index < 2 && !done ? `${text}_` : text;
|
|
780
|
+
};
|
|
781
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
782
|
+
"div",
|
|
783
|
+
{
|
|
784
|
+
ref: fieldRef,
|
|
785
|
+
role: "group",
|
|
786
|
+
tabIndex: disabled ? -1 : 0,
|
|
787
|
+
"aria-label": ariaLabel ?? t("neetoatoms.datePicker.timeField", "Time"),
|
|
788
|
+
"aria-describedby": ariaDescribedBy,
|
|
789
|
+
"aria-invalid": invalid || void 0,
|
|
790
|
+
"aria-disabled": disabled || void 0,
|
|
791
|
+
"data-testid": dataTestId,
|
|
792
|
+
className: utils$1.cn(
|
|
793
|
+
"group/time flex h-9 w-full cursor-text items-center rounded-md border border-input bg-transparent px-3 text-sm tabular-nums outline-none select-none",
|
|
794
|
+
"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
795
|
+
invalid && "border-destructive",
|
|
796
|
+
disabled && "pointer-events-none cursor-not-allowed opacity-50"
|
|
797
|
+
),
|
|
798
|
+
onBlur: () => update(finishActiveSegment(time, step)),
|
|
799
|
+
onKeyDown: handleKeyDown,
|
|
800
|
+
onMouseDown: handleMouseDown,
|
|
801
|
+
onPaste: handlePaste,
|
|
802
|
+
children: SEGMENT_KEYS.map((key, index) => /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
|
|
803
|
+
index === 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "px-0.5 text-muted-foreground", children: ":" }),
|
|
804
|
+
index === 2 && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "w-1" }),
|
|
805
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
806
|
+
"span",
|
|
807
|
+
{
|
|
808
|
+
"data-segment": index,
|
|
809
|
+
"data-testid": `datepicker-time-${key}`,
|
|
810
|
+
className: utils$1.cn(
|
|
811
|
+
"min-w-[2ch] px-0.5 text-center whitespace-pre",
|
|
812
|
+
!time[key].text && "text-muted-foreground",
|
|
813
|
+
index === time.active && "group-focus/time:shadow-[inset_0_-1.5px_0_var(--color-muted-foreground)]"
|
|
814
|
+
),
|
|
815
|
+
children: segmentText(index)
|
|
816
|
+
}
|
|
817
|
+
)
|
|
818
|
+
] }, key))
|
|
819
|
+
}
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
);
|
|
800
823
|
SegmentedTimeInput.displayName = "SegmentedTimeInput";
|
|
801
824
|
|
|
802
825
|
const ERROR_DEFAULTS = {
|
|
@@ -998,9 +1021,10 @@ const RangeCalendar = ({
|
|
|
998
1021
|
endMonth,
|
|
999
1022
|
onHoverIn,
|
|
1000
1023
|
onHoverOut,
|
|
1024
|
+
onKeyDown,
|
|
1001
1025
|
numberOfMonths = 2,
|
|
1002
1026
|
className
|
|
1003
|
-
}) => /* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
1027
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx("div", { onKeyDown, onMouseLeave: onHoverOut, onMouseOver: onHoverIn, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1004
1028
|
primitives_Calendar.Calendar,
|
|
1005
1029
|
{
|
|
1006
1030
|
mode: "range",
|
|
@@ -1022,6 +1046,180 @@ const RangeCalendar = ({
|
|
|
1022
1046
|
}
|
|
1023
1047
|
) });
|
|
1024
1048
|
|
|
1049
|
+
const ENDPOINT_LABELS = {
|
|
1050
|
+
from: "Start",
|
|
1051
|
+
to: "End"
|
|
1052
|
+
};
|
|
1053
|
+
const RangeTimeSection = ({
|
|
1054
|
+
fromDateLabel,
|
|
1055
|
+
toDateLabel,
|
|
1056
|
+
isEndOnStartDay,
|
|
1057
|
+
fromValue,
|
|
1058
|
+
toValue,
|
|
1059
|
+
onFromChange,
|
|
1060
|
+
onToChange,
|
|
1061
|
+
activeEndpoint,
|
|
1062
|
+
onEndpointSelect,
|
|
1063
|
+
minuteStep,
|
|
1064
|
+
onErrorChange,
|
|
1065
|
+
showError,
|
|
1066
|
+
isOrderInvalid,
|
|
1067
|
+
timezoneLabel,
|
|
1068
|
+
fromTimeRef,
|
|
1069
|
+
disabled = false,
|
|
1070
|
+
className
|
|
1071
|
+
}) => {
|
|
1072
|
+
const { t } = reactI18next.useTranslation();
|
|
1073
|
+
const id = React.useId();
|
|
1074
|
+
const hintId = `datepicker-time-hint-${id}`;
|
|
1075
|
+
const orderErrorId = `datepicker-time-order-error-${id}`;
|
|
1076
|
+
const [errors, setErrors] = React.useState({ from: null, to: null });
|
|
1077
|
+
const hasError = !!(errors.from || errors.to);
|
|
1078
|
+
React.useEffect(() => {
|
|
1079
|
+
onErrorChange(hasError);
|
|
1080
|
+
}, [hasError, onErrorChange]);
|
|
1081
|
+
const handleErrorChange = React.useCallback(
|
|
1082
|
+
(endpoint, error) => setErrors((previous) => ({ ...previous, [endpoint]: error })),
|
|
1083
|
+
[]
|
|
1084
|
+
);
|
|
1085
|
+
const handleFromErrorChange = React.useCallback(
|
|
1086
|
+
(error) => handleErrorChange("from", error),
|
|
1087
|
+
[handleErrorChange]
|
|
1088
|
+
);
|
|
1089
|
+
const handleToErrorChange = React.useCallback(
|
|
1090
|
+
(error) => handleErrorChange("to", error),
|
|
1091
|
+
[handleErrorChange]
|
|
1092
|
+
);
|
|
1093
|
+
const showHint = (minuteStep ?? 1) > 1;
|
|
1094
|
+
const endpoints = [
|
|
1095
|
+
{
|
|
1096
|
+
endpoint: "from",
|
|
1097
|
+
dateLabel: fromDateLabel,
|
|
1098
|
+
value: fromValue,
|
|
1099
|
+
onChange: onFromChange,
|
|
1100
|
+
onFieldErrorChange: handleFromErrorChange
|
|
1101
|
+
},
|
|
1102
|
+
{
|
|
1103
|
+
endpoint: "to",
|
|
1104
|
+
dateLabel: isEndOnStartDay ? t("neetoatoms.datePicker.sameDay", "Same day") : toDateLabel,
|
|
1105
|
+
value: toValue,
|
|
1106
|
+
onChange: onToChange,
|
|
1107
|
+
onFieldErrorChange: handleToErrorChange
|
|
1108
|
+
}
|
|
1109
|
+
];
|
|
1110
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils$1.cn("flex flex-col gap-2", className), children: [
|
|
1111
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-3", children: endpoints.map(
|
|
1112
|
+
({ endpoint, dateLabel, value, onChange, onFieldErrorChange }) => {
|
|
1113
|
+
const isActive = endpoint === activeEndpoint;
|
|
1114
|
+
const endpointLabel = t(
|
|
1115
|
+
`neetoatoms.datePicker.${endpoint === "from" ? "start" : "end"}`,
|
|
1116
|
+
ENDPOINT_LABELS[endpoint]
|
|
1117
|
+
);
|
|
1118
|
+
const error = errors[endpoint];
|
|
1119
|
+
const errorId = `datepicker-${endpoint}-time-error-${id}`;
|
|
1120
|
+
const errorMessage = showError && error ? t(
|
|
1121
|
+
`neetoatoms.datePicker.errors.${error}`,
|
|
1122
|
+
ERROR_DEFAULTS[error]
|
|
1123
|
+
) : null;
|
|
1124
|
+
const isInvalid = !!errorMessage || endpoint === "to" && isOrderInvalid;
|
|
1125
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
1126
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1127
|
+
"button",
|
|
1128
|
+
{
|
|
1129
|
+
type: "button",
|
|
1130
|
+
"aria-pressed": isActive,
|
|
1131
|
+
tabIndex: -1,
|
|
1132
|
+
"data-testid": `datepicker-${endpoint}-endpoint`,
|
|
1133
|
+
disabled,
|
|
1134
|
+
className: utils$1.cn(
|
|
1135
|
+
"flex min-w-0 items-baseline gap-1.5 rounded-sm text-start text-sm outline-none",
|
|
1136
|
+
"focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
1137
|
+
isActive ? "font-medium text-foreground" : "text-muted-foreground hover:text-foreground"
|
|
1138
|
+
),
|
|
1139
|
+
onClick: () => onEndpointSelect(endpoint),
|
|
1140
|
+
children: [
|
|
1141
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: endpointLabel }),
|
|
1142
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs font-normal text-muted-foreground", children: dateLabel || t("neetoatoms.datePicker.pickADay", "Pick a day") })
|
|
1143
|
+
]
|
|
1144
|
+
}
|
|
1145
|
+
),
|
|
1146
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1147
|
+
SegmentedTimeInput,
|
|
1148
|
+
{
|
|
1149
|
+
"aria-describedby": [
|
|
1150
|
+
showHint ? hintId : null,
|
|
1151
|
+
errorMessage ? errorId : null,
|
|
1152
|
+
endpoint === "to" && isOrderInvalid ? orderErrorId : null
|
|
1153
|
+
].filter(Boolean).join(" ") || void 0,
|
|
1154
|
+
"aria-label": t(
|
|
1155
|
+
`neetoatoms.datePicker.${endpoint === "from" ? "startTime" : "endTime"}`,
|
|
1156
|
+
`${ENDPOINT_LABELS[endpoint]} time`
|
|
1157
|
+
),
|
|
1158
|
+
"data-testid": `datepicker-${endpoint}-time-input`,
|
|
1159
|
+
disabled,
|
|
1160
|
+
invalid: isInvalid,
|
|
1161
|
+
minuteStep,
|
|
1162
|
+
ref: endpoint === "from" ? fromTimeRef : void 0,
|
|
1163
|
+
value,
|
|
1164
|
+
onChange,
|
|
1165
|
+
onErrorChange: onFieldErrorChange
|
|
1166
|
+
}
|
|
1167
|
+
),
|
|
1168
|
+
errorMessage && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1169
|
+
"p",
|
|
1170
|
+
{
|
|
1171
|
+
id: errorId,
|
|
1172
|
+
className: "text-xs text-destructive",
|
|
1173
|
+
"data-testid": `datepicker-${endpoint}-time-error`,
|
|
1174
|
+
role: "alert",
|
|
1175
|
+
children: errorMessage
|
|
1176
|
+
}
|
|
1177
|
+
)
|
|
1178
|
+
] }, endpoint);
|
|
1179
|
+
}
|
|
1180
|
+
) }),
|
|
1181
|
+
showHint && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1182
|
+
"p",
|
|
1183
|
+
{
|
|
1184
|
+
id: hintId,
|
|
1185
|
+
className: "text-xs text-muted-foreground",
|
|
1186
|
+
"data-testid": "datepicker-time-hint",
|
|
1187
|
+
children: t("neetoatoms.datePicker.timeHint", {
|
|
1188
|
+
step: minuteStep,
|
|
1189
|
+
first: stepExamples(minuteStep)[0],
|
|
1190
|
+
second: stepExamples(minuteStep)[1],
|
|
1191
|
+
defaultValue: "Only {{step}}-minute steps are allowed, like {{first}} or {{second}}."
|
|
1192
|
+
})
|
|
1193
|
+
}
|
|
1194
|
+
),
|
|
1195
|
+
isOrderInvalid && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1196
|
+
"p",
|
|
1197
|
+
{
|
|
1198
|
+
id: orderErrorId,
|
|
1199
|
+
className: "text-xs text-destructive",
|
|
1200
|
+
"data-testid": "datepicker-time-order-error",
|
|
1201
|
+
role: "alert",
|
|
1202
|
+
children: t(
|
|
1203
|
+
"neetoatoms.datePicker.errors.endBeforeStart",
|
|
1204
|
+
"End time must be after the start time."
|
|
1205
|
+
)
|
|
1206
|
+
}
|
|
1207
|
+
),
|
|
1208
|
+
timezoneLabel && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1209
|
+
"p",
|
|
1210
|
+
{
|
|
1211
|
+
className: "mt-1 flex items-center gap-2 text-xs text-muted-foreground",
|
|
1212
|
+
"data-testid": "datepicker-timezone",
|
|
1213
|
+
children: [
|
|
1214
|
+
/* @__PURE__ */ jsxRuntime.jsx(Globe, { "aria-hidden": true, className: "size-3.5 shrink-0" }),
|
|
1215
|
+
timezoneLabel
|
|
1216
|
+
]
|
|
1217
|
+
}
|
|
1218
|
+
)
|
|
1219
|
+
] });
|
|
1220
|
+
};
|
|
1221
|
+
RangeTimeSection.displayName = "RangeTimeSection";
|
|
1222
|
+
|
|
1025
1223
|
const useRangePicker = ({
|
|
1026
1224
|
currentValue,
|
|
1027
1225
|
showTime,
|
|
@@ -1030,52 +1228,49 @@ const useRangePicker = ({
|
|
|
1030
1228
|
setOpen
|
|
1031
1229
|
}) => {
|
|
1032
1230
|
const [pendingRange, setPendingRange] = React.useState(null);
|
|
1033
|
-
const [
|
|
1034
|
-
"from"
|
|
1035
|
-
);
|
|
1231
|
+
const [activeEndpoint, setActiveEndpoint] = React.useState("from");
|
|
1036
1232
|
const [hoveredDate, setHoveredDate] = React.useState(null);
|
|
1037
1233
|
const committed = currentValue ?? null;
|
|
1038
1234
|
const resetTransientState = React.useCallback(() => {
|
|
1039
1235
|
setPendingRange(null);
|
|
1040
|
-
|
|
1236
|
+
setActiveEndpoint("from");
|
|
1041
1237
|
setHoveredDate(null);
|
|
1042
1238
|
}, []);
|
|
1043
1239
|
const handleRangeSelect = React.useCallback(
|
|
1044
1240
|
(_range, triggerDate) => {
|
|
1045
1241
|
if (!triggerDate) return;
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
const nextFrom = existingFrom && triggerDate >= existingFrom ? existingFrom : null;
|
|
1054
|
-
setPendingRange([nextFrom, triggerDate]);
|
|
1055
|
-
}
|
|
1242
|
+
const from = pendingRange ? pendingRange[0] : committed?.[0] ?? null;
|
|
1243
|
+
const to = pendingRange ? pendingRange[1] : committed?.[1] ?? null;
|
|
1244
|
+
const isBeforeFrom = !!from && triggerDate < startOfDay(from);
|
|
1245
|
+
if (activeEndpoint === "from" || !from) {
|
|
1246
|
+
const nextTo = to && triggerDate <= to ? to : null;
|
|
1247
|
+
setPendingRange([triggerDate, nextTo]);
|
|
1248
|
+
setActiveEndpoint("to");
|
|
1056
1249
|
return;
|
|
1057
1250
|
}
|
|
1058
|
-
if (
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1251
|
+
if (showTime || needConfirm) {
|
|
1252
|
+
if (isBeforeFrom) {
|
|
1253
|
+
setPendingRange([triggerDate, null]);
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
setPendingRange([from, triggerDate]);
|
|
1257
|
+
setActiveEndpoint("from");
|
|
1063
1258
|
return;
|
|
1064
1259
|
}
|
|
1065
|
-
const [
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
commitValue([from, to]);
|
|
1260
|
+
const [orderedFrom, orderedTo] = orderRange(from, triggerDate);
|
|
1261
|
+
resetTransientState();
|
|
1262
|
+
commitValue([orderedFrom, orderedTo]);
|
|
1069
1263
|
setOpen(false);
|
|
1070
1264
|
},
|
|
1071
1265
|
[
|
|
1072
|
-
|
|
1266
|
+
activeEndpoint,
|
|
1073
1267
|
pendingRange,
|
|
1074
1268
|
committed,
|
|
1075
1269
|
showTime,
|
|
1076
1270
|
needConfirm,
|
|
1077
1271
|
commitValue,
|
|
1078
|
-
setOpen
|
|
1272
|
+
setOpen,
|
|
1273
|
+
resetTransientState
|
|
1079
1274
|
]
|
|
1080
1275
|
);
|
|
1081
1276
|
const handleHoverIn = React.useCallback(
|
|
@@ -1088,29 +1283,25 @@ const useRangePicker = ({
|
|
|
1088
1283
|
[hoveredDate]
|
|
1089
1284
|
);
|
|
1090
1285
|
const handleHoverOut = React.useCallback(() => setHoveredDate(null), []);
|
|
1091
|
-
const memoizedRangeSelected = React.useMemo(() => {
|
|
1092
|
-
const { from, to } = computeRangePreview({
|
|
1093
|
-
pendingRange,
|
|
1094
|
-
committed,
|
|
1095
|
-
hoveredDate,
|
|
1096
|
-
rangeStep: rangeSelectionStep
|
|
1097
|
-
});
|
|
1098
|
-
if (!from && !to) return void 0;
|
|
1099
|
-
return { from: from ?? void 0, to: to ?? void 0 };
|
|
1100
|
-
}, [pendingRange, committed, hoveredDate, rangeSelectionStep]);
|
|
1101
1286
|
const getPreviewParts = React.useCallback(
|
|
1102
1287
|
() => computeRangePreview({
|
|
1103
1288
|
pendingRange,
|
|
1104
1289
|
committed,
|
|
1105
1290
|
hoveredDate,
|
|
1106
|
-
rangeStep:
|
|
1291
|
+
rangeStep: activeEndpoint
|
|
1107
1292
|
}),
|
|
1108
|
-
[pendingRange, committed, hoveredDate,
|
|
1293
|
+
[pendingRange, committed, hoveredDate, activeEndpoint]
|
|
1109
1294
|
);
|
|
1295
|
+
const memoizedRangeSelected = React.useMemo(() => {
|
|
1296
|
+
const { from, to } = getPreviewParts();
|
|
1297
|
+
if (!from && !to) return void 0;
|
|
1298
|
+
return { from: from ?? void 0, to: to ?? void 0 };
|
|
1299
|
+
}, [getPreviewParts]);
|
|
1110
1300
|
return {
|
|
1111
1301
|
pendingRange,
|
|
1112
|
-
|
|
1113
|
-
|
|
1302
|
+
setPendingRange,
|
|
1303
|
+
activeEndpoint,
|
|
1304
|
+
setActiveEndpoint,
|
|
1114
1305
|
hoveredDate,
|
|
1115
1306
|
handleRangeSelect,
|
|
1116
1307
|
handleHoverIn,
|
|
@@ -1188,8 +1379,12 @@ const YearPicker = ({
|
|
|
1188
1379
|
const TIME_SECTION_CLASS_NAME = "w-0 min-w-full border-t border-border px-3 py-3";
|
|
1189
1380
|
const SHOW_TIME_CALENDAR_CLASS_NAME = "[--cell-size:--spacing(8.125)]";
|
|
1190
1381
|
const DEFAULT_ADDED_TIME = { hours: 12, minutes: 0, seconds: 0 };
|
|
1191
|
-
const
|
|
1192
|
-
|
|
1382
|
+
const getDefaultEndTime = (minuteStep = 1) => ({
|
|
1383
|
+
hours: 23,
|
|
1384
|
+
minutes: Math.floor(59 / minuteStep) * minuteStep,
|
|
1385
|
+
seconds: 0
|
|
1386
|
+
});
|
|
1387
|
+
const isSameRange = (a, b) => a?.[0]?.getTime() === b?.[0]?.getTime() && a?.[1]?.getTime() === b?.[1]?.getTime();
|
|
1193
1388
|
const DatePicker = React.forwardRef(
|
|
1194
1389
|
({
|
|
1195
1390
|
value,
|
|
@@ -1238,6 +1433,7 @@ const DatePicker = React.forwardRef(
|
|
|
1238
1433
|
const containerRef = React.useRef(null);
|
|
1239
1434
|
const inputRef = React.useRef(null);
|
|
1240
1435
|
const cursorPosRef = React.useRef(null);
|
|
1436
|
+
const fromTimeRef = React.useRef(null);
|
|
1241
1437
|
const popoverContentId = React.useRef(
|
|
1242
1438
|
`datepicker-popover-${generatedId}`
|
|
1243
1439
|
).current;
|
|
@@ -1279,12 +1475,7 @@ const DatePicker = React.forwardRef(
|
|
|
1279
1475
|
);
|
|
1280
1476
|
const sizeConfig = SIZE_CONFIG[size];
|
|
1281
1477
|
const maskEnabled = utils$2.isFixedWidthFormat(displayFormat);
|
|
1282
|
-
const defaultPlaceholder = getDatePlaceholder(
|
|
1283
|
-
dateFormat,
|
|
1284
|
-
timeFormat,
|
|
1285
|
-
showTime,
|
|
1286
|
-
type
|
|
1287
|
-
);
|
|
1478
|
+
const defaultPlaceholder = getDatePlaceholder(dateFormat, type);
|
|
1288
1479
|
const maskTemplate = React.useMemo(
|
|
1289
1480
|
() => maskEnabled ? type === "range" ? utils$2.buildRangeMaskTemplate(displayFormat) : utils$2.buildMaskTemplate(displayFormat) : null,
|
|
1290
1481
|
[displayFormat, type, maskEnabled]
|
|
@@ -1359,8 +1550,9 @@ const DatePicker = React.forwardRef(
|
|
|
1359
1550
|
};
|
|
1360
1551
|
const {
|
|
1361
1552
|
pendingRange,
|
|
1362
|
-
|
|
1363
|
-
|
|
1553
|
+
setPendingRange,
|
|
1554
|
+
activeEndpoint,
|
|
1555
|
+
setActiveEndpoint,
|
|
1364
1556
|
handleRangeSelect,
|
|
1365
1557
|
handleHoverIn,
|
|
1366
1558
|
handleHoverOut,
|
|
@@ -1374,9 +1566,38 @@ const DatePicker = React.forwardRef(
|
|
|
1374
1566
|
commitValue,
|
|
1375
1567
|
setOpen
|
|
1376
1568
|
});
|
|
1569
|
+
const isRangeConfirm = type === "range" && (showTime || needConfirm);
|
|
1570
|
+
const committedRange = type === "range" ? currentValue : null;
|
|
1571
|
+
const [draftFrom, draftTo] = orderRange(
|
|
1572
|
+
pendingRange ? pendingRange[0] : committedRange?.[0] ?? null,
|
|
1573
|
+
pendingRange ? pendingRange[1] : committedRange?.[1] ?? null
|
|
1574
|
+
);
|
|
1575
|
+
const draftEnd = draftTo ?? (showTime ? draftFrom : null);
|
|
1576
|
+
const isEndOnStartDay = showTime && !!draftFrom && isSameDay(draftFrom, draftEnd);
|
|
1577
|
+
const draftRange = React.useMemo(() => {
|
|
1578
|
+
if (!draftFrom || !draftEnd) return null;
|
|
1579
|
+
return showTime ? [
|
|
1580
|
+
applyTimeToDate(draftFrom, pendingTime),
|
|
1581
|
+
applyTimeToDate(draftEnd, pendingTimeTo)
|
|
1582
|
+
] : [draftFrom, draftEnd];
|
|
1583
|
+
}, [draftFrom, draftEnd, showTime, pendingTime, pendingTimeTo]);
|
|
1584
|
+
const isRangeOrderInvalid = showTime && !!draftRange && draftRange[1].getTime() <= draftRange[0].getTime();
|
|
1585
|
+
const applyTypedRange = (range) => {
|
|
1586
|
+
const snapped = range.map(
|
|
1587
|
+
(date) => showTime && minuteStep ? roundToMinuteStep(date, minuteStep) : date
|
|
1588
|
+
);
|
|
1589
|
+
const [from, to] = orderRange(snapped[0], snapped[1]);
|
|
1590
|
+
setPendingRange([startOfDay(from), startOfDay(to)]);
|
|
1591
|
+
setActiveEndpoint("from");
|
|
1592
|
+
if (showTime) {
|
|
1593
|
+
setPendingTime(utils$2.dateToTimeValue(from));
|
|
1594
|
+
setPendingTimeTo(utils$2.dateToTimeValue(to));
|
|
1595
|
+
}
|
|
1596
|
+
};
|
|
1377
1597
|
React.useEffect(() => {
|
|
1378
1598
|
if (type !== "range" || !open) return;
|
|
1379
|
-
const { from, to } = getPreviewParts();
|
|
1599
|
+
const { from, to: previewTo } = getPreviewParts();
|
|
1600
|
+
const to = previewTo ?? (showTime ? from : null);
|
|
1380
1601
|
const fromWithTime = from && showTime ? applyTimeToDate(from, pendingTime) : from;
|
|
1381
1602
|
const toWithTime = to && showTime ? applyTimeToDate(to, pendingTimeTo) : to;
|
|
1382
1603
|
const fromText = fromWithTime ? formatDate(fromWithTime, displayFormat) : "";
|
|
@@ -1410,7 +1631,9 @@ const DatePicker = React.forwardRef(
|
|
|
1410
1631
|
maskEnabled,
|
|
1411
1632
|
singleDateLen
|
|
1412
1633
|
);
|
|
1413
|
-
if (range)
|
|
1634
|
+
if (!range) return;
|
|
1635
|
+
if (isRangeConfirm) applyTypedRange(range);
|
|
1636
|
+
else commitValue(range);
|
|
1414
1637
|
};
|
|
1415
1638
|
const commitPendingOnClose = React.useCallback(() => {
|
|
1416
1639
|
const hasOkButton = showTime || needConfirm;
|
|
@@ -1440,14 +1663,9 @@ const DatePicker = React.forwardRef(
|
|
|
1440
1663
|
hasTimeError
|
|
1441
1664
|
]);
|
|
1442
1665
|
const closePopover = React.useCallback(() => {
|
|
1443
|
-
if (type === "range"
|
|
1444
|
-
const
|
|
1445
|
-
|
|
1446
|
-
pendingRange[1]
|
|
1447
|
-
);
|
|
1448
|
-
const fromFinal = showTime ? applyTimeToDate(fromBase, pendingTime) : fromBase;
|
|
1449
|
-
const toFinal = showTime ? applyTimeToDate(toBase, pendingTimeTo) : toBase;
|
|
1450
|
-
commitValue([fromFinal, toFinal]);
|
|
1666
|
+
if (type === "range") {
|
|
1667
|
+
const canCommit = draftRange && !(showTime && (hasTimeError || isRangeOrderInvalid)) && !isSameRange(draftRange, committedRange);
|
|
1668
|
+
if (canCommit) commitValue(draftRange);
|
|
1451
1669
|
} else {
|
|
1452
1670
|
commitPendingOnClose();
|
|
1453
1671
|
}
|
|
@@ -1457,9 +1675,9 @@ const DatePicker = React.forwardRef(
|
|
|
1457
1675
|
commitPendingOnClose,
|
|
1458
1676
|
setOpen,
|
|
1459
1677
|
type,
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1678
|
+
draftRange,
|
|
1679
|
+
committedRange,
|
|
1680
|
+
isRangeOrderInvalid,
|
|
1463
1681
|
showTime,
|
|
1464
1682
|
resetTransientState,
|
|
1465
1683
|
hasTimeError
|
|
@@ -1482,7 +1700,10 @@ const DatePicker = React.forwardRef(
|
|
|
1482
1700
|
setPendingTime(
|
|
1483
1701
|
fromDate ? utils$2.dateToTimeValue(fromDate) : INITIAL_TIME_VALUE
|
|
1484
1702
|
);
|
|
1485
|
-
setPendingTimeTo(
|
|
1703
|
+
setPendingTimeTo(
|
|
1704
|
+
toDate ? utils$2.dateToTimeValue(toDate) : getDefaultEndTime(minuteStep)
|
|
1705
|
+
);
|
|
1706
|
+
if (fromDate) setCalendarMonth(fromDate);
|
|
1486
1707
|
return;
|
|
1487
1708
|
}
|
|
1488
1709
|
const dateVal = currentValue;
|
|
@@ -1518,11 +1739,6 @@ const DatePicker = React.forwardRef(
|
|
|
1518
1739
|
setCalendarMonth(now);
|
|
1519
1740
|
if (type === "range") {
|
|
1520
1741
|
handleRangeSelect(void 0, now);
|
|
1521
|
-
if (showTime) {
|
|
1522
|
-
const nowTime = utils$2.dateToTimeValue(now);
|
|
1523
|
-
if (rangeSelectionStep === "from") setPendingTime(nowTime);
|
|
1524
|
-
else setPendingTimeTo(nowTime);
|
|
1525
|
-
}
|
|
1526
1742
|
return;
|
|
1527
1743
|
}
|
|
1528
1744
|
if (showTime || needConfirm) {
|
|
@@ -1539,30 +1755,12 @@ const DatePicker = React.forwardRef(
|
|
|
1539
1755
|
setIsTimeErrorRequested(true);
|
|
1540
1756
|
return;
|
|
1541
1757
|
}
|
|
1542
|
-
if (
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
setCalendarMonth(
|
|
1549
|
-
new Date(fromValue.getFullYear(), fromValue.getMonth(), 1)
|
|
1550
|
-
);
|
|
1551
|
-
if (showTime && pendingRange?.[0]) {
|
|
1552
|
-
setPendingTimeTo(INITIAL_TIME_VALUE);
|
|
1553
|
-
}
|
|
1554
|
-
return;
|
|
1555
|
-
}
|
|
1556
|
-
if (rangeSelectionStep === "to" && fromValue && toValue) {
|
|
1557
|
-
const [fromBase, toBase] = orderRange(fromValue, toValue);
|
|
1558
|
-
const fromFinal = showTime ? applyTimeToDate(fromBase, pendingTime) : fromBase;
|
|
1559
|
-
const toFinal = showTime ? applyTimeToDate(toBase, pendingTimeTo) : toBase;
|
|
1560
|
-
commitValue([fromFinal, toFinal], showTime);
|
|
1561
|
-
onOk?.([fromFinal, toFinal]);
|
|
1562
|
-
resetTransientState();
|
|
1563
|
-
setOpen(false);
|
|
1564
|
-
return;
|
|
1565
|
-
}
|
|
1758
|
+
if (isRangeConfirm) {
|
|
1759
|
+
if (!draftRange || isRangeOrderInvalid) return;
|
|
1760
|
+
commitValue(draftRange, showTime);
|
|
1761
|
+
onOk?.(draftRange);
|
|
1762
|
+
resetTransientState();
|
|
1763
|
+
setOpen(false);
|
|
1566
1764
|
return;
|
|
1567
1765
|
}
|
|
1568
1766
|
if (pendingDate) {
|
|
@@ -1623,12 +1821,8 @@ const DatePicker = React.forwardRef(
|
|
|
1623
1821
|
singleDateLen
|
|
1624
1822
|
);
|
|
1625
1823
|
if (range) {
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
roundToMinuteStep(range[0], minuteStep),
|
|
1629
|
-
roundToMinuteStep(range[1], minuteStep)
|
|
1630
|
-
] : range
|
|
1631
|
-
);
|
|
1824
|
+
const snapped = showTime && minuteStep ? range.map((date) => roundToMinuteStep(date, minuteStep)) : range;
|
|
1825
|
+
commitValue(orderRange(snapped[0], snapped[1]));
|
|
1632
1826
|
}
|
|
1633
1827
|
} else {
|
|
1634
1828
|
const parsed = parseDate(inputText, displayFormat);
|
|
@@ -1682,6 +1876,20 @@ const DatePicker = React.forwardRef(
|
|
|
1682
1876
|
);
|
|
1683
1877
|
const calendarStartMonth = normalizedMinDate ?? (calendarMonth < defaultStartMonth ? calendarMonth : defaultStartMonth);
|
|
1684
1878
|
const calendarEndMonth = normalizedMaxDate ?? (calendarMonth > defaultEndMonth ? calendarMonth : defaultEndMonth);
|
|
1879
|
+
const handleEndpointSelect = (endpoint) => {
|
|
1880
|
+
setActiveEndpoint(endpoint);
|
|
1881
|
+
const date = endpoint === "from" ? draftFrom : draftEnd;
|
|
1882
|
+
if (!date) return;
|
|
1883
|
+
const monthsAhead = (date.getFullYear() - calendarMonth.getFullYear()) * 12 + date.getMonth() - calendarMonth.getMonth();
|
|
1884
|
+
if (monthsAhead < 0 || monthsAhead > 1) {
|
|
1885
|
+
setCalendarMonth(new Date(date.getFullYear(), date.getMonth(), 1));
|
|
1886
|
+
}
|
|
1887
|
+
};
|
|
1888
|
+
const handleRangeCalendarKeyDown = (e) => {
|
|
1889
|
+
if (e.key !== "Tab" || e.shiftKey || !draftRange) return;
|
|
1890
|
+
e.preventDefault();
|
|
1891
|
+
fromTimeRef.current?.focusHour();
|
|
1892
|
+
};
|
|
1685
1893
|
const handleGridPickerSelect = (date) => {
|
|
1686
1894
|
commitValue(date);
|
|
1687
1895
|
setOpen(false);
|
|
@@ -1806,26 +2014,10 @@ const DatePicker = React.forwardRef(
|
|
|
1806
2014
|
startMonth: calendarStartMonth,
|
|
1807
2015
|
endMonth: calendarEndMonth
|
|
1808
2016
|
}
|
|
1809
|
-
) : showTime ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1810
|
-
RangeCalendar,
|
|
1811
|
-
{
|
|
1812
|
-
className: SHOW_TIME_CALENDAR_CLASS_NAME,
|
|
1813
|
-
todayDate,
|
|
1814
|
-
weekStartsOn,
|
|
1815
|
-
month: calendarMonth,
|
|
1816
|
-
onMonthChange: setCalendarMonth,
|
|
1817
|
-
selected: memoizedRangeSelected,
|
|
1818
|
-
onSelect: handleRangeSelect,
|
|
1819
|
-
disabled: calendarDisabled,
|
|
1820
|
-
startMonth: calendarStartMonth,
|
|
1821
|
-
endMonth: calendarEndMonth,
|
|
1822
|
-
onHoverIn: handleHoverIn,
|
|
1823
|
-
onHoverOut: handleHoverOut,
|
|
1824
|
-
numberOfMonths: 1
|
|
1825
|
-
}
|
|
1826
2017
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1827
2018
|
RangeCalendar,
|
|
1828
2019
|
{
|
|
2020
|
+
className: utils$1.cn(showTime && SHOW_TIME_CALENDAR_CLASS_NAME),
|
|
1829
2021
|
todayDate,
|
|
1830
2022
|
weekStartsOn,
|
|
1831
2023
|
month: calendarMonth,
|
|
@@ -1836,25 +2028,31 @@ const DatePicker = React.forwardRef(
|
|
|
1836
2028
|
startMonth: calendarStartMonth,
|
|
1837
2029
|
endMonth: calendarEndMonth,
|
|
1838
2030
|
onHoverIn: handleHoverIn,
|
|
1839
|
-
onHoverOut: handleHoverOut
|
|
2031
|
+
onHoverOut: handleHoverOut,
|
|
2032
|
+
onKeyDown: showTime ? handleRangeCalendarKeyDown : void 0
|
|
1840
2033
|
}
|
|
1841
2034
|
) }),
|
|
1842
2035
|
showTime && type === "range" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1843
|
-
|
|
2036
|
+
RangeTimeSection,
|
|
1844
2037
|
{
|
|
2038
|
+
activeEndpoint,
|
|
1845
2039
|
className: TIME_SECTION_CLASS_NAME,
|
|
1846
2040
|
disabled,
|
|
1847
|
-
|
|
1848
|
-
|
|
2041
|
+
fromDateLabel: formatDate(draftFrom, dateFormat),
|
|
2042
|
+
fromTimeRef,
|
|
2043
|
+
fromValue: pendingTime,
|
|
2044
|
+
isOrderInvalid: isRangeOrderInvalid,
|
|
2045
|
+
minuteStep,
|
|
1849
2046
|
showError: isTimeErrorRequested,
|
|
1850
2047
|
timezoneLabel,
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
2048
|
+
isEndOnStartDay,
|
|
2049
|
+
toDateLabel: formatDate(draftTo, dateFormat),
|
|
2050
|
+
toValue: pendingTimeTo,
|
|
2051
|
+
onEndpointSelect: handleEndpointSelect,
|
|
1854
2052
|
onErrorChange: setHasTimeError,
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
2053
|
+
onFromChange: setPendingTime,
|
|
2054
|
+
onToChange: setPendingTimeTo
|
|
2055
|
+
}
|
|
1858
2056
|
),
|
|
1859
2057
|
showTime && type !== "range" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1860
2058
|
TimeSection,
|
|
@@ -1880,10 +2078,10 @@ const DatePicker = React.forwardRef(
|
|
|
1880
2078
|
timezone,
|
|
1881
2079
|
onTimezoneChange,
|
|
1882
2080
|
nowDisabled: calendarDisabled(todayDate),
|
|
1883
|
-
showNow,
|
|
2081
|
+
showNow: showNow && !(type === "range" && showTime),
|
|
1884
2082
|
onNow: handleNow,
|
|
1885
|
-
|
|
1886
|
-
|
|
2083
|
+
okDisabled: isRangeConfirm && (!draftRange || isRangeOrderInvalid),
|
|
2084
|
+
onOk: handleOk
|
|
1887
2085
|
}
|
|
1888
2086
|
)
|
|
1889
2087
|
]
|
|
@@ -1917,4 +2115,4 @@ const DatePicker = React.forwardRef(
|
|
|
1917
2115
|
DatePicker.displayName = "DatePicker";
|
|
1918
2116
|
|
|
1919
2117
|
exports.DatePicker = DatePicker;
|
|
1920
|
-
//# sourceMappingURL=DatePicker-
|
|
2118
|
+
//# sourceMappingURL=DatePicker-CBxWLALJ.js.map
|