'use strict';

var chunkQP2LHBCZ_cjs = require('./chunk-QP2LHBCZ.cjs');
var icons = require('@blueprintjs/icons');
var classnames = require('classnames');
var React2 = require('react');
var reactDayPicker = require('react-day-picker');
var input = require('@base-ui/react/input');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var classnames__default = /*#__PURE__*/_interopDefault(classnames);
var React2__default = /*#__PURE__*/_interopDefault(React2);

// src/shared/dateUtils.ts
function formatDateForInput(date) {
  if (date == null) return "";
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
}
function formatTime(date) {
  const hours = String(date.getHours()).padStart(2, "0");
  const minutes = String(date.getMinutes()).padStart(2, "0");
  return `${hours}:${minutes}`;
}
function parseDateFromInput(value) {
  if (!value) return void 0;
  const date = /* @__PURE__ */ new Date(value + "T00:00:00");
  return isNaN(date.getTime()) ? void 0 : date;
}
function formatDateForDisplay(date, fallback = "") {
  if (date == null) return fallback;
  return date.toLocaleDateString(void 0, {
    year: "numeric",
    month: "short",
    day: "numeric"
  });
}
function formatDatetimeForInput(date) {
  if (date == null) return "";
  return `${formatDateForInput(date)} ${formatTime(date)}`;
}
function parseDatetimeFromInput(value) {
  if (!value) return void 0;
  const normalized = value.includes("T") ? value : value.replace(/\s/u, "T");
  const date = new Date(normalized);
  return isNaN(date.getTime()) ? void 0 : date;
}
function isDateInRange(date, min, max) {
  if (min != null && date.getTime() < min.getTime()) return false;
  if (max != null && date.getTime() > max.getTime()) return false;
  return true;
}

// src/shared/calendar/calendarShared.ts
var DEFAULT_FROM_YEAR = (/* @__PURE__ */ new Date()).getFullYear() - 10;
var DEFAULT_TO_YEAR = (/* @__PURE__ */ new Date()).getFullYear() + 10;
function buildDisabledMatchers(min, max) {
  const matchers = [];
  if (min != null) {
    const before = {
      before: min
    };
    matchers.push(before);
  }
  if (max != null) {
    const after = {
      after: max
    };
    matchers.push(after);
  }
  return matchers;
}
var stopPropagation = (e) => {
  e.stopPropagation();
  const preventBaseUIHandler = e.preventBaseUIHandler;
  preventBaseUIHandler?.();
};

// src/shared/calendar/TimePicker.module.css
var TimePicker_default = {};

// src/shared/calendar/TimePicker.tsx
var NUMERIC_INPUT_PATTERN = "[0-9]*";
var SEGMENT_LIMITS = {
  hours: {
    min: 0,
    max: 23
  },
  minutes: {
    min: 0,
    max: 59
  }
};
var TimePicker = /* @__PURE__ */ React2__default.default.memo(function TimePickerFn({
  value,
  onChange,
  label = "Time"
}) {
  const valueTimestamp = value?.getTime() ?? null;
  const valueSegments = React2.useMemo(() => segmentsFromTimestamp(valueTimestamp), [valueTimestamp]);
  const [draftSegments, setDraftSegments] = React2.useState(valueSegments);
  const [prevSegments, setPrevSegments] = React2.useState(valueSegments);
  if (prevSegments.hours !== valueSegments.hours || prevSegments.minutes !== valueSegments.minutes) {
    setPrevSegments(valueSegments);
    setDraftSegments(valueSegments);
  }
  const hourText = draftSegments.hours;
  const minuteText = draftSegments.minutes;
  const hourInvalid = isSegmentInvalid(hourText, "hours");
  const minuteInvalid = isSegmentInvalid(minuteText, "minutes");
  const handleSegmentChange = React2.useCallback((segment, nextText) => {
    setDraftSegments((prev) => replaceSegmentText(prev, {
      segment,
      nextText
    }));
  }, []);
  const emitChange = React2.useCallback((hours, minutes) => {
    const nextDate = value != null ? new Date(value.getTime()) : /* @__PURE__ */ new Date();
    nextDate.setHours(hours, minutes, 0, 0);
    onChange?.(nextDate);
  }, [onChange, value]);
  const handleSegmentBlur = React2.useCallback((segment, text) => {
    const parsedSegment = parseNumber(text);
    if (parsedSegment == null) {
      setDraftSegments(valueSegments);
      return;
    }
    const clampedSegment = clampSegment(parsedSegment, segment);
    setDraftSegments((prev) => replaceSegmentText(prev, {
      segment,
      nextText: formatSegment(clampedSegment, segment)
    }));
    const currentHours = Number(valueSegments.hours);
    const currentMinutes = Number(valueSegments.minutes);
    const nextHours = segment === "hours" ? clampedSegment : currentHours;
    const nextMinutes = segment === "minutes" ? clampedSegment : currentMinutes;
    if (nextHours !== currentHours || nextMinutes !== currentMinutes) {
      emitChange(nextHours, nextMinutes);
    }
  }, [emitChange, valueSegments]);
  const handleHourChange = React2.useCallback((nextText) => handleSegmentChange("hours", nextText), [handleSegmentChange]);
  const handleMinuteChange = React2.useCallback((nextText) => handleSegmentChange("minutes", nextText), [handleSegmentChange]);
  const handleHourBlur = React2.useCallback(() => handleSegmentBlur("hours", hourText), [handleSegmentBlur, hourText]);
  const handleMinuteBlur = React2.useCallback(() => handleSegmentBlur("minutes", minuteText), [handleSegmentBlur, minuteText]);
  return /* @__PURE__ */ React2__default.default.createElement("div", {
    className: TimePicker_default.osdkTimePickerRoot,
    role: "group",
    "aria-label": label
  }, /* @__PURE__ */ React2__default.default.createElement(input.Input, {
    type: "text",
    inputMode: "numeric",
    pattern: NUMERIC_INPUT_PATTERN,
    value: hourText,
    onValueChange: handleHourChange,
    onBlur: handleHourBlur,
    className: TimePicker_default.osdkTimePickerInput,
    "aria-label": `${label} hours`,
    "aria-invalid": hourInvalid || void 0
  }), /* @__PURE__ */ React2__default.default.createElement("span", {
    className: TimePicker_default.osdkTimePickerSeparator,
    "aria-hidden": "true"
  }, ":"), /* @__PURE__ */ React2__default.default.createElement(input.Input, {
    type: "text",
    inputMode: "numeric",
    pattern: NUMERIC_INPUT_PATTERN,
    value: minuteText,
    onValueChange: handleMinuteChange,
    onBlur: handleMinuteBlur,
    className: TimePicker_default.osdkTimePickerInput,
    "aria-label": `${label} minutes`,
    "aria-invalid": minuteInvalid || void 0
  }));
});
function replaceSegmentText(segments, {
  segment,
  nextText
}) {
  return {
    ...segments,
    [segment]: nextText
  };
}
function segmentsFromTimestamp(valueTimestamp) {
  if (valueTimestamp == null) {
    return {
      hours: formatSegment(0, "hours"),
      minutes: formatSegment(0, "minutes")
    };
  }
  const value = new Date(valueTimestamp);
  return {
    hours: formatSegment(value.getHours(), "hours"),
    minutes: formatSegment(value.getMinutes(), "minutes")
  };
}
function formatSegment(value, segment) {
  return segment === "hours" ? String(value) : String(value).padStart(2, "0");
}
function parseNumber(text) {
  if (!/^\d{1,2}$/u.test(text)) {
    return void 0;
  }
  const parsed = Number(text);
  return Number.isNaN(parsed) ? void 0 : parsed;
}
function parseSegment(text, segment) {
  const parsed = parseNumber(text);
  if (parsed == null) {
    return void 0;
  }
  const {
    min,
    max
  } = SEGMENT_LIMITS[segment];
  return parsed >= min && parsed <= max ? parsed : void 0;
}
function isSegmentInvalid(text, segment) {
  return parseSegment(text, segment) == null;
}
function clampSegment(value, segment) {
  const {
    min,
    max
  } = SEGMENT_LIMITS[segment];
  return Math.min(Math.max(value, min), max);
}

// src/shared/calendar/DateCalendar.module.css
var DateCalendar_default = {};

// src/shared/calendar/DateCalendar.tsx
var CLASS_NAMES = {
  root: DateCalendar_default.calendar,
  months: DateCalendar_default.calendarMonths,
  table: DateCalendar_default.calendarMonthGrid,
  head_cell: DateCalendar_default.calendarWeekday,
  cell: DateCalendar_default.calendarDay,
  day: DateCalendar_default.calendarDayButton,
  day_selected: DateCalendar_default.calendarSelected,
  day_today: DateCalendar_default.calendarToday,
  day_outside: DateCalendar_default.calendarOutside,
  day_disabled: DateCalendar_default.calendarDisabled,
  day_hidden: DateCalendar_default.calendarHidden,
  nav: DateCalendar_default.calendarNav,
  nav_button_previous: classnames__default.default(DateCalendar_default.calendarNavButton, DateCalendar_default.calendarNavPrev),
  nav_button_next: classnames__default.default(DateCalendar_default.calendarNavButton, DateCalendar_default.calendarNavNext),
  caption: DateCalendar_default.calendarMonthCaption,
  caption_label: DateCalendar_default.calendarVhidden,
  caption_dropdowns: DateCalendar_default.calendarCaptionDropdowns,
  dropdown: DateCalendar_default.calendarDropdown,
  dropdown_month: DateCalendar_default.calendarDropdown,
  dropdown_year: DateCalendar_default.calendarDropdown,
  nav_icon: DateCalendar_default.calendarChevron,
  vhidden: DateCalendar_default.calendarVhidden,
  tfoot: DateCalendar_default.calendarFooter
};
var NAV_ICON_SIZE = 12;
function IconLeft() {
  return /* @__PURE__ */ React2__default.default.createElement(icons.ChevronLeft, {
    size: NAV_ICON_SIZE
  });
}
function IconRight() {
  return /* @__PURE__ */ React2__default.default.createElement(icons.ChevronRight, {
    size: NAV_ICON_SIZE
  });
}
var CALENDAR_COMPONENTS = {
  IconLeft,
  IconRight
};
function DateCalendar({
  dateSelected,
  onSelect,
  onTimeChange,
  onClear,
  month,
  onMonthChange,
  min,
  max,
  todayButtonText = "Today",
  clearButtonText = "Clear"
}) {
  const disabled = React2.useMemo(() => buildDisabledMatchers(min, max), [min, max]);
  const showTime = onTimeChange != null;
  const fromYear = min != null ? min.getFullYear() : DEFAULT_FROM_YEAR;
  const toYear = max != null ? max.getFullYear() : DEFAULT_TO_YEAR;
  const today = /* @__PURE__ */ new Date();
  const todayMidnight = new Date(today.getFullYear(), today.getMonth(), today.getDate());
  const isTodaySelectable = isDateInRange(todayMidnight, min, max);
  const applySelectedTime = React2.useCallback((selected) => {
    if (!showTime) {
      return selected;
    }
    if (dateSelected == null) {
      return selected;
    }
    const date = new Date(selected.getTime());
    date.setHours(dateSelected.getHours(), dateSelected.getMinutes(), 0, 0);
    return date;
  }, [dateSelected, showTime]);
  const handleSelect = React2.useCallback((selected) => {
    onSelect(selected == null ? void 0 : applySelectedTime(selected));
  }, [applySelectedTime, onSelect]);
  const handleTodayClick = React2.useCallback(() => {
    if (!isTodaySelectable) {
      return;
    }
    onSelect(/* @__PURE__ */ new Date());
  }, [isTodaySelectable, onSelect]);
  const calendarFooter = /* @__PURE__ */ React2__default.default.createElement(React2__default.default.Fragment, null, showTime && /* @__PURE__ */ React2__default.default.createElement("div", {
    className: DateCalendar_default.calendarTimeFooter
  }, /* @__PURE__ */ React2__default.default.createElement(TimePicker, {
    value: dateSelected ?? null,
    onChange: onTimeChange
  })), /* @__PURE__ */ React2__default.default.createElement("div", {
    className: DateCalendar_default.calendarActionBar
  }, /* @__PURE__ */ React2__default.default.createElement(chunkQP2LHBCZ_cjs.ActionButton, {
    type: "button",
    appearance: "minimal",
    disabled: !isTodaySelectable,
    onClick: handleTodayClick
  }, todayButtonText), onClear != null && /* @__PURE__ */ React2__default.default.createElement(chunkQP2LHBCZ_cjs.ActionButton, {
    type: "button",
    appearance: "minimal",
    onClick: onClear
  }, clearButtonText)));
  return /* @__PURE__ */ React2__default.default.createElement(reactDayPicker.DayPicker, {
    mode: "single",
    selected: dateSelected,
    onSelect: handleSelect,
    month,
    onMonthChange,
    disabled,
    defaultMonth: dateSelected,
    classNames: CLASS_NAMES,
    components: CALENDAR_COMPONENTS,
    footer: calendarFooter,
    captionLayout: "dropdown-buttons",
    fromYear,
    toYear,
    showOutsideDays: true,
    fixedWeeks: true
  });
}

exports.CALENDAR_COMPONENTS = CALENDAR_COMPONENTS;
exports.CLASS_NAMES = CLASS_NAMES;
exports.DEFAULT_FROM_YEAR = DEFAULT_FROM_YEAR;
exports.DEFAULT_TO_YEAR = DEFAULT_TO_YEAR;
exports.DateCalendar = DateCalendar;
exports.DateCalendar_default = DateCalendar_default;
exports.TimePicker = TimePicker;
exports.buildDisabledMatchers = buildDisabledMatchers;
exports.formatDateForDisplay = formatDateForDisplay;
exports.formatDateForInput = formatDateForInput;
exports.formatDatetimeForInput = formatDatetimeForInput;
exports.isDateInRange = isDateInRange;
exports.parseDateFromInput = parseDateFromInput;
exports.parseDatetimeFromInput = parseDatetimeFromInput;
exports.stopPropagation = stopPropagation;
//# sourceMappingURL=chunk-CUFFPIPP.cjs.map
//# sourceMappingURL=chunk-CUFFPIPP.cjs.map