@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.
Files changed (32) hide show
  1. package/dist/{DatePicker-BC9AOZJ2.js → DatePicker-CMlA-hNW.js} +478 -280
  2. package/dist/DatePicker-CMlA-hNW.js.map +1 -0
  3. package/dist/{TranslationProvider-BJjfFEgX.js → TranslationProvider-DKdbPweu.js} +9 -2
  4. package/dist/{TranslationProvider-BJjfFEgX.js.map → TranslationProvider-DKdbPweu.js.map} +1 -1
  5. package/dist/cjs/{DatePicker-aGLz-3Bz.js → DatePicker-CBxWLALJ.js} +477 -279
  6. package/dist/cjs/DatePicker-CBxWLALJ.js.map +1 -0
  7. package/dist/cjs/{TranslationProvider-C1JDwKEN.js → TranslationProvider-Cao2ugzJ.js} +9 -2
  8. package/dist/cjs/{TranslationProvider-C1JDwKEN.js.map → TranslationProvider-Cao2ugzJ.js.map} +1 -1
  9. package/dist/cjs/components/DatePicker.js +1 -1
  10. package/dist/cjs/components/TranslationProvider.js +1 -1
  11. package/dist/cjs/components/index.js +2 -2
  12. package/dist/cjs/formik/Form.js +1 -0
  13. package/dist/cjs/formik/Form.js.map +1 -1
  14. package/dist/cjs/index.js +5 -5
  15. package/dist/components/DatePicker/DatePickerFooter.d.ts +1 -1
  16. package/dist/components/DatePicker/RangeCalendar.d.ts +2 -1
  17. package/dist/components/DatePicker/RangeTimeSection.d.ts +37 -0
  18. package/dist/components/DatePicker/SegmentedTimeInput.d.ts +7 -1
  19. package/dist/components/DatePicker/TimeSection.d.ts +3 -0
  20. package/dist/components/DatePicker/types.d.ts +5 -2
  21. package/dist/components/DatePicker/useRangePicker.d.ts +4 -2
  22. package/dist/components/DatePicker/utils.d.ts +2 -1
  23. package/dist/components/DatePicker.js +1 -1
  24. package/dist/components/TranslationProvider.js +1 -1
  25. package/dist/components/index.js +2 -2
  26. package/dist/formik/Form.js +1 -0
  27. package/dist/formik/Form.js.map +1 -1
  28. package/dist/index.js +2 -2
  29. package/dist/translations/index.d.ts +7 -0
  30. package/package.json +1 -1
  31. package/dist/DatePicker-BC9AOZJ2.js.map +0 -1
  32. 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, timeFormat, showTime, type) => {
198
- const single = showTime ? `${dateFormat.toUpperCase()} ${timeFormat}` : dateFormat.toUpperCase();
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" && !pendingRange?.[0]) {
272
- from = hoveredDate;
273
- if (to && hoveredDate.getTime() > to.getTime()) to = null;
274
- } else if (rangeStep === "to" && !pendingRange?.[1] && !isSameDay(from, hoveredDate)) {
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
- okLabel = "OK",
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(primitives_Button.Button, { size: "sm", onClick: onOk, className: "text-xs", children: okLabel })
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
- value,
659
- minuteStep,
660
- onChange,
661
- onErrorChange,
662
- invalid = false,
663
- disabled = false,
664
- autoFocus = false,
665
- "aria-describedby": ariaDescribedBy
666
- }) => {
667
- const { t } = reactI18next.useTranslation();
668
- const fieldRef = React.useRef(null);
669
- const step = minuteStep ?? 1;
670
- const [time, setTime] = React.useState(
671
- () => segmentedTimeFromValue(value, step)
672
- );
673
- const lastEmittedRef = React.useRef(value);
674
- React.useEffect(() => {
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
- if (segmentEl) {
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
- fieldRef.current?.focus();
749
- update(focusSegment(time, Number(segmentEl.dataset.segment), step));
750
- return;
751
- }
752
- update(focusFirstEmptySegment(time));
753
- };
754
- const segmentText = (index) => {
755
- const { text, done } = time[SEGMENT_KEYS[index]];
756
- if (!text) return PLACEHOLDERS[index];
757
- return index < 2 && !done ? `${text}_` : text;
758
- };
759
- return /* @__PURE__ */ jsxRuntime.jsx(
760
- "div",
761
- {
762
- ref: fieldRef,
763
- role: "group",
764
- tabIndex: disabled ? -1 : 0,
765
- "aria-label": t("neetoatoms.datePicker.timeField", "Time"),
766
- "aria-describedby": ariaDescribedBy,
767
- "aria-invalid": invalid || void 0,
768
- "aria-disabled": disabled || void 0,
769
- "data-testid": "datepicker-time-input",
770
- className: utils$1.cn(
771
- "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",
772
- "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
773
- invalid && "border-destructive",
774
- disabled && "pointer-events-none cursor-not-allowed opacity-50"
775
- ),
776
- onBlur: () => update(finishActiveSegment(time, step)),
777
- onKeyDown: handleKeyDown,
778
- onMouseDown: handleMouseDown,
779
- onPaste: handlePaste,
780
- children: SEGMENT_KEYS.map((key, index) => /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
781
- index === 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "px-0.5 text-muted-foreground", children: ":" }),
782
- index === 2 && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "w-1" }),
783
- /* @__PURE__ */ jsxRuntime.jsx(
784
- "span",
785
- {
786
- "data-segment": index,
787
- "data-testid": `datepicker-time-${key}`,
788
- className: utils$1.cn(
789
- "min-w-[2ch] px-0.5 text-center whitespace-pre",
790
- !time[key].text && "text-muted-foreground",
791
- index === time.active && "group-focus/time:shadow-[inset_0_-1.5px_0_var(--color-muted-foreground)]"
792
- ),
793
- children: segmentText(index)
794
- }
795
- )
796
- ] }, key))
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", { onMouseOver: onHoverIn, onMouseLeave: onHoverOut, children: /* @__PURE__ */ jsxRuntime.jsx(
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 [rangeSelectionStep, setRangeSelectionStep] = React.useState(
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
- setRangeSelectionStep("from");
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
- if (showTime || needConfirm) {
1047
- if (rangeSelectionStep === "from") {
1048
- const existingTo = pendingRange?.[1] ?? committed?.[1] ?? null;
1049
- const nextTo = existingTo && triggerDate <= existingTo ? existingTo : null;
1050
- setPendingRange([triggerDate, nextTo]);
1051
- } else {
1052
- const existingFrom = pendingRange?.[0] ?? committed?.[0] ?? null;
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 (rangeSelectionStep === "from" || !pendingRange?.[0]) {
1059
- const existingTo = pendingRange?.[1] ?? committed?.[1] ?? null;
1060
- const nextTo = existingTo && triggerDate <= existingTo ? existingTo : null;
1061
- setPendingRange([triggerDate, nextTo]);
1062
- setRangeSelectionStep("to");
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 [from, to] = orderRange(pendingRange[0], triggerDate);
1066
- setRangeSelectionStep("from");
1067
- setPendingRange(null);
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
- rangeSelectionStep,
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: rangeSelectionStep
1291
+ rangeStep: activeEndpoint
1107
1292
  }),
1108
- [pendingRange, committed, hoveredDate, rangeSelectionStep]
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
- rangeSelectionStep,
1113
- setRangeSelectionStep,
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 noop = () => {
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
- rangeSelectionStep,
1363
- setRangeSelectionStep,
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) commitValue(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" && pendingRange?.[0] && pendingRange?.[1] && !(showTime && hasTimeError)) {
1444
- const [fromBase, toBase] = orderRange(
1445
- pendingRange[0],
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
- pendingRange,
1461
- pendingTime,
1462
- pendingTimeTo,
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(toDate ? utils$2.dateToTimeValue(toDate) : INITIAL_TIME_VALUE);
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 (type === "range" && (showTime || needConfirm)) {
1543
- const committedRange = currentValue;
1544
- const fromValue = pendingRange?.[0] ?? committedRange?.[0] ?? null;
1545
- const toValue = pendingRange?.[1] ?? committedRange?.[1] ?? null;
1546
- if (rangeSelectionStep === "from" && fromValue) {
1547
- setRangeSelectionStep("to");
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
- commitValue(
1627
- showTime && minuteStep ? [
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
- TimeSection,
2036
+ RangeTimeSection,
1844
2037
  {
2038
+ activeEndpoint,
1845
2039
  className: TIME_SECTION_CLASS_NAME,
1846
2040
  disabled,
1847
- hasTime: true,
1848
- optional: false,
2041
+ fromDateLabel: formatDate(draftFrom, dateFormat),
2042
+ fromTimeRef,
2043
+ fromValue: pendingTime,
2044
+ isOrderInvalid: isRangeOrderInvalid,
2045
+ minuteStep,
1849
2046
  showError: isTimeErrorRequested,
1850
2047
  timezoneLabel,
1851
- value: rangeSelectionStep === "from" ? pendingTime : pendingTimeTo,
1852
- onChange: rangeSelectionStep === "from" ? setPendingTime : setPendingTimeTo,
1853
- minuteStep,
2048
+ isEndOnStartDay,
2049
+ toDateLabel: formatDate(draftTo, dateFormat),
2050
+ toValue: pendingTimeTo,
2051
+ onEndpointSelect: handleEndpointSelect,
1854
2052
  onErrorChange: setHasTimeError,
1855
- onHasTimeChange: noop
1856
- },
1857
- rangeSelectionStep
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
- onOk: handleOk,
1886
- okLabel: type === "range" && (showTime || needConfirm) && rangeSelectionStep === "from" ? "Next" : "OK"
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-aGLz-3Bz.js.map
2118
+ //# sourceMappingURL=DatePicker-CBxWLALJ.js.map