@codecademy/gamut

68.2.268.2.3-alpha.794432.0
dist/DatePicker/utils/dateSelect.js
+dist/DatePicker/utils/dateSelect.jsNew file
+146
Index: package/dist/DatePicker/utils/dateSelect.js
===================================================================
--- package/dist/DatePicker/utils/dateSelect.js
+++ package/dist/DatePicker/utils/dateSelect.js
@@ -0,0 +1,146 @@
+import { isDateInRange, isSameDay } from '../Calendar/utils/dateGrid';
+export const isRangeProps = props => props.mode === 'range';
+/** True if any disabled date falls within [start, end] (inclusive, by calendar day). */
+export const rangeContainsDisabled = ({
+  start,
+  end,
+  disabledDates
+}) => {
+  return disabledDates.some(date => isSameDay(date, start) || isSameDay(date, end) || isDateInRange(date, start, end));
+};
+export const handleDateSelectSingle = ({
+  date,
+  selectedDate,
+  setSelection
+}) => {
+  // If clicked date is the same as Start Date: Clear Start Date
+  if (selectedDate && date.getTime() === selectedDate.getTime()) {
+    setSelection(null);
+    return;
+  }
+  // If clicked date is not the same as Start Date: Set Start Date to clicked date
+  setSelection(date);
+};
+const applyRangeOrNewStart = ({
+  start,
+  end,
+  clickedDate,
+  disabledDates,
+  setSelection
+}) => {
+  // if range contains disabled dates, set start date to clicked date and end date to null
+  if (rangeContainsDisabled({
+    start,
+    end,
+    disabledDates
+  })) {
+    setSelection(clickedDate, null);
+  } else {
+    setSelection(start, end);
+  }
+};
+export const handleDateSelectRange = ({
+  date,
+  activeRangePart,
+  startDate,
+  endDate,
+  setSelection,
+  disabledDates = []
+}) => {
+  // Range mode: field targeting (start or end input was focused)
+  if (activeRangePart === 'start') {
+    if (date.getTime() === startDate?.getTime()) {
+      setSelection(null, endDate);
+      return;
+    }
+    const newEnd = endDate != null && date.getTime() <= endDate.getTime() ? endDate : null;
+    if (newEnd != null) {
+      applyRangeOrNewStart({
+        start: date,
+        end: newEnd,
+        clickedDate: date,
+        disabledDates,
+        setSelection
+      });
+    } else {
+      setSelection(date, newEnd);
+    }
+    return;
+  }
+  if (activeRangePart === 'end') {
+    if (date.getTime() === endDate?.getTime()) {
+      setSelection(startDate, null);
+      return;
+    }
+    const newStart = startDate != null && date.getTime() >= startDate.getTime() ? startDate : null;
+    if (newStart != null) {
+      applyRangeOrNewStart({
+        start: newStart,
+        end: date,
+        clickedDate: date,
+        disabledDates,
+        setSelection
+      });
+    } else {
+      setSelection(newStart, date);
+    }
+    return;
+  }
+
+  // Range selection mode (no field focused: calendar drives both)
+  if (startDate && endDate) {
+    // if start date is end date and is clicked, clears everything
+    if (startDate.getTime() === endDate.getTime() && date.getTime() === startDate.getTime()) {
+      setSelection(null, null);
+      return;
+    }
+    // if clicked on start date, end date becomes start date
+    if (date.getTime() === startDate.getTime()) {
+      setSelection(endDate, null);
+      return;
+    }
+    // if clicked on end date, clears end date and start remains
+    if (date.getTime() === endDate.getTime()) {
+      setSelection(startDate, null);
+      return;
+    }
+    // If clicked date > Start: Updates End Date to new date (Start remains)
+    if (date.getTime() > startDate.getTime()) {
+      applyRangeOrNewStart({
+        start: startDate,
+        end: date,
+        clickedDate: date,
+        disabledDates,
+        setSelection
+      });
+      return;
+    }
+    // If clicked date < Start: Updates Start Date to new date (End remains) - extends range to the left
+    applyRangeOrNewStart({
+      start: date,
+      end: endDate,
+      clickedDate: date,
+      disabledDates,
+      setSelection
+    });
+    return;
+  }
+  // Start is Set, End is Empty
+  if (startDate && !endDate) {
+    // If clicked date < Start: Restarts selection with clicked date as new Start
+    if (date.getTime() < startDate.getTime()) {
+      setSelection(date, null);
+    } else {
+      // If clicked date > Start: Sets it as End Date (if range valid)
+      applyRangeOrNewStart({
+        start: startDate,
+        end: date,
+        clickedDate: date,
+        disabledDates,
+        setSelection
+      });
+    }
+    return;
+  }
+  setSelection(date, null);
+};
\ No newline at end of file