@bigbinary/neeto-atoms 1.1.2 → 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-BiUWzq-V.js → DatePicker-CMlA-hNW.js} +475 -272
- 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-C_nezxpH.js → DatePicker-CBxWLALJ.js} +474 -271
- 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 +1 -0
- 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-BiUWzq-V.js.map +0 -1
- package/dist/cjs/DatePicker-C_nezxpH.js.map +0 -1
|
@@ -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;
|
|
@@ -1354,8 +1550,9 @@ const DatePicker = React.forwardRef(
|
|
|
1354
1550
|
};
|
|
1355
1551
|
const {
|
|
1356
1552
|
pendingRange,
|
|
1357
|
-
|
|
1358
|
-
|
|
1553
|
+
setPendingRange,
|
|
1554
|
+
activeEndpoint,
|
|
1555
|
+
setActiveEndpoint,
|
|
1359
1556
|
handleRangeSelect,
|
|
1360
1557
|
handleHoverIn,
|
|
1361
1558
|
handleHoverOut,
|
|
@@ -1369,9 +1566,38 @@ const DatePicker = React.forwardRef(
|
|
|
1369
1566
|
commitValue,
|
|
1370
1567
|
setOpen
|
|
1371
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
|
+
};
|
|
1372
1597
|
React.useEffect(() => {
|
|
1373
1598
|
if (type !== "range" || !open) return;
|
|
1374
|
-
const { from, to } = getPreviewParts();
|
|
1599
|
+
const { from, to: previewTo } = getPreviewParts();
|
|
1600
|
+
const to = previewTo ?? (showTime ? from : null);
|
|
1375
1601
|
const fromWithTime = from && showTime ? applyTimeToDate(from, pendingTime) : from;
|
|
1376
1602
|
const toWithTime = to && showTime ? applyTimeToDate(to, pendingTimeTo) : to;
|
|
1377
1603
|
const fromText = fromWithTime ? formatDate(fromWithTime, displayFormat) : "";
|
|
@@ -1405,7 +1631,9 @@ const DatePicker = React.forwardRef(
|
|
|
1405
1631
|
maskEnabled,
|
|
1406
1632
|
singleDateLen
|
|
1407
1633
|
);
|
|
1408
|
-
if (range)
|
|
1634
|
+
if (!range) return;
|
|
1635
|
+
if (isRangeConfirm) applyTypedRange(range);
|
|
1636
|
+
else commitValue(range);
|
|
1409
1637
|
};
|
|
1410
1638
|
const commitPendingOnClose = React.useCallback(() => {
|
|
1411
1639
|
const hasOkButton = showTime || needConfirm;
|
|
@@ -1435,14 +1663,9 @@ const DatePicker = React.forwardRef(
|
|
|
1435
1663
|
hasTimeError
|
|
1436
1664
|
]);
|
|
1437
1665
|
const closePopover = React.useCallback(() => {
|
|
1438
|
-
if (type === "range"
|
|
1439
|
-
const
|
|
1440
|
-
|
|
1441
|
-
pendingRange[1]
|
|
1442
|
-
);
|
|
1443
|
-
const fromFinal = showTime ? applyTimeToDate(fromBase, pendingTime) : fromBase;
|
|
1444
|
-
const toFinal = showTime ? applyTimeToDate(toBase, pendingTimeTo) : toBase;
|
|
1445
|
-
commitValue([fromFinal, toFinal]);
|
|
1666
|
+
if (type === "range") {
|
|
1667
|
+
const canCommit = draftRange && !(showTime && (hasTimeError || isRangeOrderInvalid)) && !isSameRange(draftRange, committedRange);
|
|
1668
|
+
if (canCommit) commitValue(draftRange);
|
|
1446
1669
|
} else {
|
|
1447
1670
|
commitPendingOnClose();
|
|
1448
1671
|
}
|
|
@@ -1452,9 +1675,9 @@ const DatePicker = React.forwardRef(
|
|
|
1452
1675
|
commitPendingOnClose,
|
|
1453
1676
|
setOpen,
|
|
1454
1677
|
type,
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1678
|
+
draftRange,
|
|
1679
|
+
committedRange,
|
|
1680
|
+
isRangeOrderInvalid,
|
|
1458
1681
|
showTime,
|
|
1459
1682
|
resetTransientState,
|
|
1460
1683
|
hasTimeError
|
|
@@ -1477,7 +1700,10 @@ const DatePicker = React.forwardRef(
|
|
|
1477
1700
|
setPendingTime(
|
|
1478
1701
|
fromDate ? utils$2.dateToTimeValue(fromDate) : INITIAL_TIME_VALUE
|
|
1479
1702
|
);
|
|
1480
|
-
setPendingTimeTo(
|
|
1703
|
+
setPendingTimeTo(
|
|
1704
|
+
toDate ? utils$2.dateToTimeValue(toDate) : getDefaultEndTime(minuteStep)
|
|
1705
|
+
);
|
|
1706
|
+
if (fromDate) setCalendarMonth(fromDate);
|
|
1481
1707
|
return;
|
|
1482
1708
|
}
|
|
1483
1709
|
const dateVal = currentValue;
|
|
@@ -1513,11 +1739,6 @@ const DatePicker = React.forwardRef(
|
|
|
1513
1739
|
setCalendarMonth(now);
|
|
1514
1740
|
if (type === "range") {
|
|
1515
1741
|
handleRangeSelect(void 0, now);
|
|
1516
|
-
if (showTime) {
|
|
1517
|
-
const nowTime = utils$2.dateToTimeValue(now);
|
|
1518
|
-
if (rangeSelectionStep === "from") setPendingTime(nowTime);
|
|
1519
|
-
else setPendingTimeTo(nowTime);
|
|
1520
|
-
}
|
|
1521
1742
|
return;
|
|
1522
1743
|
}
|
|
1523
1744
|
if (showTime || needConfirm) {
|
|
@@ -1534,30 +1755,12 @@ const DatePicker = React.forwardRef(
|
|
|
1534
1755
|
setIsTimeErrorRequested(true);
|
|
1535
1756
|
return;
|
|
1536
1757
|
}
|
|
1537
|
-
if (
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
setCalendarMonth(
|
|
1544
|
-
new Date(fromValue.getFullYear(), fromValue.getMonth(), 1)
|
|
1545
|
-
);
|
|
1546
|
-
if (showTime && pendingRange?.[0]) {
|
|
1547
|
-
setPendingTimeTo(INITIAL_TIME_VALUE);
|
|
1548
|
-
}
|
|
1549
|
-
return;
|
|
1550
|
-
}
|
|
1551
|
-
if (rangeSelectionStep === "to" && fromValue && toValue) {
|
|
1552
|
-
const [fromBase, toBase] = orderRange(fromValue, toValue);
|
|
1553
|
-
const fromFinal = showTime ? applyTimeToDate(fromBase, pendingTime) : fromBase;
|
|
1554
|
-
const toFinal = showTime ? applyTimeToDate(toBase, pendingTimeTo) : toBase;
|
|
1555
|
-
commitValue([fromFinal, toFinal], showTime);
|
|
1556
|
-
onOk?.([fromFinal, toFinal]);
|
|
1557
|
-
resetTransientState();
|
|
1558
|
-
setOpen(false);
|
|
1559
|
-
return;
|
|
1560
|
-
}
|
|
1758
|
+
if (isRangeConfirm) {
|
|
1759
|
+
if (!draftRange || isRangeOrderInvalid) return;
|
|
1760
|
+
commitValue(draftRange, showTime);
|
|
1761
|
+
onOk?.(draftRange);
|
|
1762
|
+
resetTransientState();
|
|
1763
|
+
setOpen(false);
|
|
1561
1764
|
return;
|
|
1562
1765
|
}
|
|
1563
1766
|
if (pendingDate) {
|
|
@@ -1618,12 +1821,8 @@ const DatePicker = React.forwardRef(
|
|
|
1618
1821
|
singleDateLen
|
|
1619
1822
|
);
|
|
1620
1823
|
if (range) {
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
roundToMinuteStep(range[0], minuteStep),
|
|
1624
|
-
roundToMinuteStep(range[1], minuteStep)
|
|
1625
|
-
] : range
|
|
1626
|
-
);
|
|
1824
|
+
const snapped = showTime && minuteStep ? range.map((date) => roundToMinuteStep(date, minuteStep)) : range;
|
|
1825
|
+
commitValue(orderRange(snapped[0], snapped[1]));
|
|
1627
1826
|
}
|
|
1628
1827
|
} else {
|
|
1629
1828
|
const parsed = parseDate(inputText, displayFormat);
|
|
@@ -1677,6 +1876,20 @@ const DatePicker = React.forwardRef(
|
|
|
1677
1876
|
);
|
|
1678
1877
|
const calendarStartMonth = normalizedMinDate ?? (calendarMonth < defaultStartMonth ? calendarMonth : defaultStartMonth);
|
|
1679
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
|
+
};
|
|
1680
1893
|
const handleGridPickerSelect = (date) => {
|
|
1681
1894
|
commitValue(date);
|
|
1682
1895
|
setOpen(false);
|
|
@@ -1801,26 +2014,10 @@ const DatePicker = React.forwardRef(
|
|
|
1801
2014
|
startMonth: calendarStartMonth,
|
|
1802
2015
|
endMonth: calendarEndMonth
|
|
1803
2016
|
}
|
|
1804
|
-
) : showTime ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1805
|
-
RangeCalendar,
|
|
1806
|
-
{
|
|
1807
|
-
className: SHOW_TIME_CALENDAR_CLASS_NAME,
|
|
1808
|
-
todayDate,
|
|
1809
|
-
weekStartsOn,
|
|
1810
|
-
month: calendarMonth,
|
|
1811
|
-
onMonthChange: setCalendarMonth,
|
|
1812
|
-
selected: memoizedRangeSelected,
|
|
1813
|
-
onSelect: handleRangeSelect,
|
|
1814
|
-
disabled: calendarDisabled,
|
|
1815
|
-
startMonth: calendarStartMonth,
|
|
1816
|
-
endMonth: calendarEndMonth,
|
|
1817
|
-
onHoverIn: handleHoverIn,
|
|
1818
|
-
onHoverOut: handleHoverOut,
|
|
1819
|
-
numberOfMonths: 1
|
|
1820
|
-
}
|
|
1821
2017
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1822
2018
|
RangeCalendar,
|
|
1823
2019
|
{
|
|
2020
|
+
className: utils$1.cn(showTime && SHOW_TIME_CALENDAR_CLASS_NAME),
|
|
1824
2021
|
todayDate,
|
|
1825
2022
|
weekStartsOn,
|
|
1826
2023
|
month: calendarMonth,
|
|
@@ -1831,25 +2028,31 @@ const DatePicker = React.forwardRef(
|
|
|
1831
2028
|
startMonth: calendarStartMonth,
|
|
1832
2029
|
endMonth: calendarEndMonth,
|
|
1833
2030
|
onHoverIn: handleHoverIn,
|
|
1834
|
-
onHoverOut: handleHoverOut
|
|
2031
|
+
onHoverOut: handleHoverOut,
|
|
2032
|
+
onKeyDown: showTime ? handleRangeCalendarKeyDown : void 0
|
|
1835
2033
|
}
|
|
1836
2034
|
) }),
|
|
1837
2035
|
showTime && type === "range" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1838
|
-
|
|
2036
|
+
RangeTimeSection,
|
|
1839
2037
|
{
|
|
2038
|
+
activeEndpoint,
|
|
1840
2039
|
className: TIME_SECTION_CLASS_NAME,
|
|
1841
2040
|
disabled,
|
|
1842
|
-
|
|
1843
|
-
|
|
2041
|
+
fromDateLabel: formatDate(draftFrom, dateFormat),
|
|
2042
|
+
fromTimeRef,
|
|
2043
|
+
fromValue: pendingTime,
|
|
2044
|
+
isOrderInvalid: isRangeOrderInvalid,
|
|
2045
|
+
minuteStep,
|
|
1844
2046
|
showError: isTimeErrorRequested,
|
|
1845
2047
|
timezoneLabel,
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
2048
|
+
isEndOnStartDay,
|
|
2049
|
+
toDateLabel: formatDate(draftTo, dateFormat),
|
|
2050
|
+
toValue: pendingTimeTo,
|
|
2051
|
+
onEndpointSelect: handleEndpointSelect,
|
|
1849
2052
|
onErrorChange: setHasTimeError,
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
2053
|
+
onFromChange: setPendingTime,
|
|
2054
|
+
onToChange: setPendingTimeTo
|
|
2055
|
+
}
|
|
1853
2056
|
),
|
|
1854
2057
|
showTime && type !== "range" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1855
2058
|
TimeSection,
|
|
@@ -1875,10 +2078,10 @@ const DatePicker = React.forwardRef(
|
|
|
1875
2078
|
timezone,
|
|
1876
2079
|
onTimezoneChange,
|
|
1877
2080
|
nowDisabled: calendarDisabled(todayDate),
|
|
1878
|
-
showNow,
|
|
2081
|
+
showNow: showNow && !(type === "range" && showTime),
|
|
1879
2082
|
onNow: handleNow,
|
|
1880
|
-
|
|
1881
|
-
|
|
2083
|
+
okDisabled: isRangeConfirm && (!draftRange || isRangeOrderInvalid),
|
|
2084
|
+
onOk: handleOk
|
|
1882
2085
|
}
|
|
1883
2086
|
)
|
|
1884
2087
|
]
|
|
@@ -1912,4 +2115,4 @@ const DatePicker = React.forwardRef(
|
|
|
1912
2115
|
DatePicker.displayName = "DatePicker";
|
|
1913
2116
|
|
|
1914
2117
|
exports.DatePicker = DatePicker;
|
|
1915
|
-
//# sourceMappingURL=DatePicker-
|
|
2118
|
+
//# sourceMappingURL=DatePicker-CBxWLALJ.js.map
|