'use strict';

var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var primitives_Calendar = require('./primitives/Calendar.js');
var primitives_Popover = require('./primitives/Popover.js');
var primitives_Field = require('./primitives/Field.js');
var utils$1 = require('./utils-BhM0B89p.js');
var utils = require('@bigbinary/neeto-commons-frontend/utils');
var pureDayjs = require('dayjs');
var customParseFormat = require('dayjs/plugin/customParseFormat');
var TimePickerPanel = require('./TimePickerPanel-DnQUpCam.js');
var primitives_Button = require('./primitives/Button.js');
var createLucideIcon = require('./createLucideIcon-D0tRgV6l.js');
var x = require('./x-Brw3FJst.js');

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

var pureDayjs__default = /*#__PURE__*/_interopDefault(pureDayjs);
var customParseFormat__default = /*#__PURE__*/_interopDefault(customParseFormat);

/**
 * @license lucide-react v0.577.0 - ISC
 *
 * This source code is licensed under the ISC license.
 * See the LICENSE file in the root directory of this source tree.
 */


const __iconNode = [
  ["path", { d: "M8 2v4", key: "1cmpym" }],
  ["path", { d: "M16 2v4", key: "4m81vk" }],
  ["rect", { width: "18", height: "18", x: "3", y: "4", rx: "2", key: "1hopcy" }],
  ["path", { d: "M3 10h18", key: "8toen8" }]
];
const Calendar = createLucideIcon.createLucideIcon("calendar", __iconNode);

const DEFAULT_DATE_FORMAT = "dd/MM/yyyy";
const DEFAULT_TIME_FORMAT = "HH:mm:ss";
const SIZE_CONFIG = {
  small: { trigger: "h-7 text-xs", icon: "size-3.5" },
  medium: { trigger: "h-8 text-sm", icon: "size-4" },
  large: { trigger: "h-10 text-sm", icon: "size-4" }
};

pureDayjs__default.default.extend(customParseFormat__default.default);
const toBrowserLocalDate = (date) => {
  const d = utils.dayjs(date);
  return new Date(
    d.year(),
    d.month(),
    d.date(),
    d.hour(),
    d.minute(),
    d.second()
  );
};
const toNativeDate = (value) => {
  if (value == null) return null;
  if (value instanceof Date) return value;
  if (typeof value.toDate === "function") {
    return toBrowserLocalDate(value.toDate());
  }
  if (typeof value === "string") {
    const parsed = new Date(value);
    if (!isNaN(parsed.getTime())) return toBrowserLocalDate(parsed);
  }
  return null;
};
const coerceDateValue = (value, type) => {
  if (value == null) return null;
  if (type === "range" && Array.isArray(value)) {
    return [toNativeDate(value[0]), toNativeDate(value[1])];
  }
  return toNativeDate(value);
};
const normalizeToDayjsFormat = (fmt) => fmt.replace(/\byyyy\b/g, "YYYY").replace(/\byy\b/g, "YY").replace(/\bdd\b/g, "DD").replace(/\bd\b/g, "D");
const normalizeToDateFnsFormat = (fmt) => fmt.replace(/YYYY/g, "yyyy").replace(/YY/g, "yy").replace(/DD/g, "dd").replace(/\bD\b/g, "d");
const formatDate = (date, formatStr) => {
  if (!date) return "";
  try {
    return pureDayjs__default.default(date).format(normalizeToDayjsFormat(formatStr));
  } catch {
    return "";
  }
};
const parseDate = (str, formatStr) => {
  if (!str) return null;
  const dayjsFmt = normalizeToDayjsFormat(formatStr);
  const parsed = pureDayjs__default.default(str, dayjsFmt);
  if (parsed.isValid()) return parsed.toDate();
  const fallbackFormats = [
    "DD/MM/YYYY",
    "MM/DD/YYYY",
    "YYYY-MM-DD",
    "DD-MM-YYYY",
    "DD/MM/YYYY HH:mm:ss",
    "DD/MM/YYYY HH:mm"
  ];
  for (const fmt of fallbackFormats) {
    if (fmt === dayjsFmt) continue;
    const attempt = pureDayjs__default.default(str, fmt);
    if (attempt.isValid()) return attempt.toDate();
  }
  return null;
};
const applyTimeToDate = (date, time) => {
  const result = new Date(date);
  result.setHours(time.hours, time.minutes, time.seconds ?? 0, 0);
  return result;
};
const applyTimezone = (date) => {
  const dateStr = pureDayjs__default.default(date).format("YYYY-MM-DD HH:mm:ss");
  return utils.dayjs(dateStr).toDate();
};
const toDayjs = (date) => utils.dayjs(date);
const getDisplayFormat = (dateFormat, timeFormat, showTime) => {
  const fmt = showTime ? `${dateFormat} ${timeFormat}` : dateFormat;
  return normalizeToDateFnsFormat(fmt);
};
const isDatePartComplete = (part, maskEnabled, singleDateLen) => maskEnabled ? part.length >= singleDateLen : part.length > 0;
const parseRangeText = (text, displayFormat, maskEnabled, singleDateLen) => {
  const parts = text.split(" - ");
  if (parts.length !== 2) return null;
  if (!isDatePartComplete(parts[0], maskEnabled, singleDateLen) || !isDatePartComplete(parts[1], maskEnabled, singleDateLen))
    return null;
  const from = parseDate(parts[0], displayFormat);
  const to = parseDate(parts[1], displayFormat);
  return from && to ? [from, to] : null;
};

const TIMEZONE_OPTIONS = [
  { label: "Local", value: "" },
  { label: "UTC", value: "utc" }
];
const TimezoneSelect = ({
  value,
  onChange,
  className
}) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils$1.cn("flex items-center gap-1.5 text-sm", className), children: [
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs", children: "Timezone" }),
  /* @__PURE__ */ jsxRuntime.jsx(
    "select",
    {
      value: value ?? "",
      onChange: (e) => onChange(e.target.value || void 0),
      className: utils$1.cn(
        "rounded-md border border-input bg-background px-2 py-0.5 text-xs",
        "focus:outline-none focus:ring-1 focus:ring-ring"
      ),
      "aria-label": "Select timezone",
      children: TIMEZONE_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.value, children: opt.label }, opt.value))
    }
  )
] });
TimezoneSelect.displayName = "TimezoneSelect";

const DatePickerFooter = ({
  showTime,
  needConfirm,
  timezone,
  onTimezoneChange,
  onNow,
  onOk,
  className
}) => {
  const showOkButton = showTime || needConfirm;
  return /* @__PURE__ */ jsxRuntime.jsxs(
    "div",
    {
      className: utils$1.cn(
        "flex items-center border-t border-border px-3 py-2",
        className
      ),
      children: [
        /* @__PURE__ */ jsxRuntime.jsx(primitives_Button.Button, { variant: "ghost", size: "sm", onClick: onNow, className: "text-xs", children: "Now" }),
        /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
        onTimezoneChange && /* @__PURE__ */ jsxRuntime.jsx(
          TimezoneSelect,
          {
            value: timezone,
            onChange: onTimezoneChange,
            className: "me-2"
          }
        ),
        showOkButton && /* @__PURE__ */ jsxRuntime.jsx(primitives_Button.Button, { size: "sm", onClick: onOk, className: "text-xs", children: "OK" })
      ]
    }
  );
};
DatePickerFooter.displayName = "DatePickerFooter";

const DatePicker = React.forwardRef(
  ({
    value,
    defaultValue,
    onChange,
    type = "date",
    dateFormat = DEFAULT_DATE_FORMAT,
    timeFormat = DEFAULT_TIME_FORMAT,
    showTime = false,
    timePickerFormat = "24",
    showSeconds = false,
    minDate,
    maxDate,
    placeholder,
    label,
    error,
    helpText,
    size = "medium",
    disabled = false,
    allowClear = true,
    required = false,
    timezone,
    onTimezoneChange,
    onOk,
    needConfirm = false,
    onOpenChange,
    className,
    labelProps
  }, ref) => {
    const generatedId = React.useId();
    const errorId = `error_${generatedId}`;
    const helpTextId = `helpText_${generatedId}`;
    const containerRef = React.useRef(null);
    const inputRef = React.useRef(null);
    const cursorPosRef = React.useRef(null);
    const popoverContentId = React.useRef(
      `datepicker-popover-${generatedId}`
    ).current;
    const [open, setOpen] = React.useState(false);
    const [internalValue, setInternalValue] = React.useState(coerceDateValue(defaultValue, type) ?? null);
    const currentValue = value !== void 0 ? coerceDateValue(value, type) : internalValue;
    const [calendarMonth, setCalendarMonth] = React.useState(
      (type === "date" ? value ?? defaultValue : null) ?? /* @__PURE__ */ new Date()
    );
    const [rangeSelectionStep, setRangeSelectionStep] = React.useState(
      "from"
    );
    const [pendingDate, setPendingDate] = React.useState(null);
    const [pendingTime, setPendingTime] = React.useState({
      hours: 0,
      minutes: 0,
      seconds: 0
    });
    const displayFormat = getDisplayFormat(dateFormat, timeFormat, showTime);
    const sizeConfig = SIZE_CONFIG[size];
    const maskEnabled = TimePickerPanel.isFixedWidthFormat(displayFormat);
    const maskTemplate = React.useMemo(
      () => maskEnabled ? type === "range" ? TimePickerPanel.buildRangeMaskTemplate(displayFormat) : TimePickerPanel.buildMaskTemplate(displayFormat) : null,
      [displayFormat, type, maskEnabled]
    );
    const singlePlaceholder = showTime ? `${dateFormat.toUpperCase()} ${timeFormat}` : dateFormat.toUpperCase();
    const defaultPlaceholder = type === "range" ? `${singlePlaceholder} - ${singlePlaceholder}` : singlePlaceholder;
    const getDisplayText = React.useCallback(() => {
      if (type === "range") {
        const rangeValue = currentValue;
        if (!rangeValue || !rangeValue[0] && !rangeValue[1]) return "";
        const from = rangeValue[0] ? formatDate(rangeValue[0], displayFormat) : "";
        const to = rangeValue[1] ? formatDate(rangeValue[1], displayFormat) : "";
        return `${from} - ${to}`;
      }
      return formatDate(currentValue, displayFormat);
    }, [currentValue, displayFormat, type]);
    const [inputText, setInputText] = React.useState(() => getDisplayText());
    React.useEffect(() => {
      if (!open) setInputText(getDisplayText());
    }, [getDisplayText, open]);
    const closePopover = React.useCallback(() => {
      setOpen(false);
      onOpenChange?.(false);
      setInputText(getDisplayText());
    }, [onOpenChange, getDisplayText]);
    const openPopover = React.useCallback(() => {
      setOpen(true);
      onOpenChange?.(true);
      setRangeSelectionStep("from");
      const dateVal = type === "date" ? currentValue : null;
      if (dateVal) {
        setCalendarMonth(dateVal);
        setPendingDate(dateVal);
        setPendingTime(TimePickerPanel.dateToTimeValue(dateVal));
      } else {
        setPendingDate(null);
        setPendingTime({ hours: 0, minutes: 0, seconds: 0 });
      }
    }, [type, currentValue, onOpenChange]);
    React.useEffect(() => {
      if (!open) return;
      const handlePointerDown = (e) => {
        const target = e.target;
        if (containerRef.current?.contains(target)) return;
        const popoverEl = document.getElementById(popoverContentId);
        if (popoverEl?.contains(target)) return;
        closePopover();
      };
      document.addEventListener("pointerdown", handlePointerDown);
      return () => document.removeEventListener("pointerdown", handlePointerDown);
    }, [open, closePopover]);
    const commitValue = (date) => {
      if (date === null) {
        setInternalValue(null);
        onChange?.(null, "");
        setInputText("");
        return;
      }
      if (Array.isArray(date)) {
        setInternalValue(date);
        const converted2 = [
          applyTimezone(date[0]),
          applyTimezone(date[1])
        ];
        const formatted2 = [
          formatDate(date[0], displayFormat),
          formatDate(date[1], displayFormat)
        ];
        onChange?.([toDayjs(converted2[0]), toDayjs(converted2[1])], formatted2);
        setInputText(`${formatted2[0]} - ${formatted2[1]}`);
        return;
      }
      setInternalValue(date);
      const converted = applyTimezone(date);
      const formatted = formatDate(date, displayFormat);
      onChange?.(toDayjs(converted), formatted);
      setInputText(formatted);
    };
    const handleDateSelect = (selected) => {
      if (!selected) return;
      setCalendarMonth(selected);
      if (showTime || needConfirm) {
        setPendingDate(selected);
      } else {
        commitValue(selected);
        setOpen(false);
        onOpenChange?.(false);
      }
    };
    const handleRangeSelect = (range) => {
      if (!range) return;
      const from = range.from ?? null;
      const to = range.to ?? null;
      if (rangeSelectionStep === "from") {
        setInternalValue([from, null]);
        setRangeSelectionStep("to");
      } else {
        if (from && to) {
          if (showTime || needConfirm) {
            setPendingDate(from);
          } else {
            commitValue([from, to]);
            setOpen(false);
            onOpenChange?.(false);
          }
        } else if (from) {
          setInternalValue([from, null]);
        }
        setRangeSelectionStep("from");
      }
    };
    const handleTimeChange = (time) => {
      setPendingTime(time);
    };
    const handleNow = () => {
      const d = utils.dayjs(/* @__PURE__ */ new Date());
      const now = new Date(
        d.year(),
        d.month(),
        d.date(),
        d.hour(),
        d.minute(),
        d.second()
      );
      if (showTime || needConfirm) {
        setPendingDate(now);
        setPendingTime(TimePickerPanel.dateToTimeValue(now));
      } else {
        commitValue(now);
        setOpen(false);
        onOpenChange?.(false);
      }
    };
    const handleOk = () => {
      if (pendingDate) {
        const finalDate = showTime ? applyTimeToDate(pendingDate, pendingTime) : pendingDate;
        commitValue(finalDate);
        onOk?.(finalDate);
      }
      setOpen(false);
      onOpenChange?.(false);
    };
    const handleClear = (e) => {
      e.stopPropagation();
      e.preventDefault();
      commitValue(null);
    };
    React.useLayoutEffect(() => {
      if (cursorPosRef.current !== null && inputRef.current && document.activeElement === inputRef.current) {
        inputRef.current.setSelectionRange(
          cursorPosRef.current,
          cursorPosRef.current
        );
        cursorPosRef.current = null;
      }
    });
    const singleDateLen = React.useMemo(
      () => TimePickerPanel.buildMaskTemplate(displayFormat).pattern.length,
      [displayFormat]
    );
    const parseAndApplyRange = (text) => {
      const parts = text.split(" - ");
      if (!isDatePartComplete(parts[0] ?? "", maskEnabled, singleDateLen))
        return;
      const from = parseDate(parts[0], displayFormat);
      if (from) setCalendarMonth(from);
      const range = parseRangeText(
        text,
        displayFormat,
        maskEnabled,
        singleDateLen
      );
      if (range) commitValue(range);
    };
    const handleInputChange = (e) => {
      let text = e.target.value;
      if (maskTemplate) {
        const masked = TimePickerPanel.applyMask(
          text,
          maskTemplate,
          inputText,
          e.target.selectionStart
        );
        text = masked.text;
        cursorPosRef.current = masked.cursorPosition;
      }
      setInputText(text);
      if (type === "range") {
        parseAndApplyRange(text);
        return;
      }
      const isComplete = maskTemplate ? text.length >= maskTemplate.pattern.length : true;
      if (!isComplete) return;
      const parsed = parseDate(text, displayFormat);
      if (!parsed) return;
      setCalendarMonth(parsed);
      if (showTime || needConfirm) {
        setPendingDate(parsed);
        setPendingTime(TimePickerPanel.dateToTimeValue(parsed));
      } else {
        commitValue(parsed);
      }
    };
    const handleInputKeyDown = (e) => {
      if (e.key === "Escape") return closePopover();
      if (e.key !== "Enter") return;
      if (type === "range") {
        const range = parseRangeText(
          inputText,
          displayFormat,
          maskEnabled,
          singleDateLen
        );
        if (range) commitValue(range);
      } else {
        const parsed = parseDate(inputText, displayFormat);
        if (parsed) commitValue(parsed);
      }
      setOpen(false);
      onOpenChange?.(false);
    };
    const handleInputFocus = () => {
      if (!open) openPopover();
    };
    const hasField = !!(label || error || helpText);
    const showFooter = showTime || needConfirm || !!onTimezoneChange;
    const todayDayjs = utils.dayjs(/* @__PURE__ */ new Date());
    const todayDate = new Date(
      todayDayjs.year(),
      todayDayjs.month(),
      todayDayjs.date()
    );
    const ariaDescribedBy = [error ? errorId : null, helpText ? helpTextId : null].filter(Boolean).join(" ") || void 0;
    const calendarDisabled = React.useCallback(
      (date) => {
        if (minDate && date < new Date(minDate.setHours(0, 0, 0, 0)))
          return true;
        if (maxDate && date > new Date(maxDate.setHours(23, 59, 59, 999)))
          return true;
        return false;
      },
      [minDate, maxDate]
    );
    const calendarSelected = React.useCallback(() => {
      if (showTime || needConfirm) return pendingDate ?? void 0;
      return currentValue ?? void 0;
    }, [showTime, needConfirm, pendingDate, currentValue]);
    const triggerContent = /* @__PURE__ */ jsxRuntime.jsxs(primitives_Popover.Popover, { open, children: [
      /* @__PURE__ */ jsxRuntime.jsx(primitives_Popover.PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
        "div",
        {
          ref: containerRef,
          className: utils$1.cn(
            "relative flex w-full items-center gap-2 rounded-md border border-input bg-background pe-8 ps-3",
            "focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
            disabled && "cursor-not-allowed opacity-50",
            !!error && "border-destructive ring-destructive/20 ring-3",
            sizeConfig.trigger,
            !hasField && className
          ),
          children: [
            /* @__PURE__ */ jsxRuntime.jsx(
              Calendar,
              {
                className: utils$1.cn("shrink-0 text-muted-foreground", sizeConfig.icon)
              }
            ),
            /* @__PURE__ */ jsxRuntime.jsx(
              "input",
              {
                ref: inputRef,
                type: "text",
                disabled,
                "aria-label": label || "Pick a date",
                "aria-describedby": ariaDescribedBy,
                "aria-invalid": !!error || void 0,
                placeholder: placeholder ?? defaultPlaceholder,
                value: inputText,
                onChange: handleInputChange,
                onKeyDown: handleInputKeyDown,
                onFocus: handleInputFocus,
                className: utils$1.cn(
                  "min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground",
                  "disabled:cursor-not-allowed",
                  sizeConfig.trigger.split(" ").find((c) => c.startsWith("text-"))
                )
              }
            ),
            timezone && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground", children: timezone.toUpperCase() }),
            allowClear && /* @__PURE__ */ jsxRuntime.jsx(
              "button",
              {
                type: "button",
                onPointerDown: (e) => e.preventDefault(),
                onClick: handleClear,
                className: utils$1.cn(
                  "absolute inset-y-0 end-2 flex items-center text-muted-foreground hover:text-foreground focus:outline-none",
                  !(inputText && !disabled) && "invisible"
                ),
                "aria-label": "Clear date",
                tabIndex: -1,
                children: /* @__PURE__ */ jsxRuntime.jsx(x.X, { className: sizeConfig.icon })
              }
            )
          ]
        }
      ) }),
      open && /* @__PURE__ */ jsxRuntime.jsxs(
        primitives_Popover.PopoverContent,
        {
          id: popoverContentId,
          className: "w-auto p-0",
          align: "start",
          onOpenAutoFocus: (e) => e.preventDefault(),
          onCloseAutoFocus: (e) => e.preventDefault(),
          onPointerDownOutside: (e) => e.preventDefault(),
          onInteractOutside: (e) => e.preventDefault(),
          children: [
            /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils$1.cn("flex", showTime && "flex-row"), children: [
              type === "date" ? /* @__PURE__ */ jsxRuntime.jsx(
                primitives_Calendar.Calendar,
                {
                  mode: "single",
                  captionLayout: "dropdown",
                  today: todayDate,
                  month: calendarMonth,
                  onMonthChange: setCalendarMonth,
                  selected: calendarSelected(),
                  onSelect: handleDateSelect,
                  disabled: calendarDisabled,
                  ...minDate && { fromDate: minDate },
                  ...maxDate && { toDate: maxDate }
                }
              ) : /* @__PURE__ */ jsxRuntime.jsx(
                primitives_Calendar.Calendar,
                {
                  mode: "range",
                  numberOfMonths: 2,
                  captionLayout: "dropdown",
                  today: todayDate,
                  className: "[&_[data-outside][data-selected=true]]:!bg-transparent [&_[data-outside][data-selected=true]]:after:!bg-transparent [&_[data-outside]_button]:!bg-transparent [&_[data-outside]_button]:!text-muted-foreground",
                  month: calendarMonth,
                  onMonthChange: setCalendarMonth,
                  selected: currentValue ? {
                    from: currentValue[0] ?? void 0,
                    to: currentValue[1] ?? void 0
                  } : void 0,
                  onSelect: handleRangeSelect,
                  disabled: calendarDisabled,
                  ...minDate && { fromDate: minDate },
                  ...maxDate && { toDate: maxDate }
                }
              ),
              showTime && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-inline-start border-border", children: /* @__PURE__ */ jsxRuntime.jsx(
                TimePickerPanel.TimePickerPanel,
                {
                  value: pendingTime,
                  onChange: handleTimeChange,
                  format: timePickerFormat,
                  showSeconds,
                  disabled
                }
              ) })
            ] }),
            showFooter && /* @__PURE__ */ jsxRuntime.jsx(
              DatePickerFooter,
              {
                showTime,
                needConfirm,
                timezone,
                onTimezoneChange,
                onNow: handleNow,
                onOk: handleOk
              }
            )
          ]
        }
      )
    ] });
    if (!hasField) {
      return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className, children: triggerContent });
    }
    return /* @__PURE__ */ jsxRuntime.jsxs(
      primitives_Field.Field,
      {
        ref,
        "data-disabled": disabled || void 0,
        "data-invalid": !!error || void 0,
        className,
        children: [
          label && /* @__PURE__ */ jsxRuntime.jsxs(
            primitives_Field.FieldLabel,
            {
              ...labelProps,
              children: [
                label,
                required && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "text-destructive", children: "*" })
              ]
            }
          ),
          /* @__PURE__ */ jsxRuntime.jsxs(primitives_Field.FieldContent, { children: [
            triggerContent,
            !!error && /* @__PURE__ */ jsxRuntime.jsx(primitives_Field.FieldError, { id: errorId, children: error }),
            helpText && /* @__PURE__ */ jsxRuntime.jsx(primitives_Field.FieldDescription, { id: helpTextId, children: helpText })
          ] })
        ]
      }
    );
  }
);
DatePicker.displayName = "DatePicker";

exports.DatePicker = DatePicker;
//# sourceMappingURL=DatePicker-DY_EEmx1.js.map
