import {
  DateUtils
} from "./chunk.A4LR62QO.js";
import {
  FormControlController
} from "./chunk.C3WIBDGG.js";
import {
  HasSlotController
} from "./chunk.IVMQWO2L.js";
import {
  LocalizeController
} from "./chunk.X3FE7OHE.js";
import {
  watch
} from "./chunk.X2OQMWGY.js";
import {
  SolidElement,
  customElement
} from "./chunk.H53WQBDK.js";
import {
  __decorateClass
} from "./chunk.S3NI7NKU.js";

// src/components/datepicker/datepicker.ts
import { css, html, nothing } from "lit";
import { property, query, state } from "lit/decorators.js";
import cx from "classix";
var isoDateConverter = {
  fromAttribute(value) {
    if (!value) return null;
    const cleaned = value.trim().replace(/[./]/g, "-");
    const match = cleaned.match(/^(\d{4})-(\d{2})-(\d{2})$/);
    if (!match) return null;
    const iso = `${match[1]}-${match[2]}-${match[3]}`;
    const d = new Date(+match[1], +match[2] - 1, +match[3]);
    if (d.getFullYear() !== +match[1] || d.getMonth() !== +match[2] - 1 || d.getDate() !== +match[3]) {
      return null;
    }
    return iso;
  },
  toAttribute(value) {
    return value != null ? value : "";
  }
};
var viewMonthConverter = {
  fromAttribute(value) {
    if (!value) return null;
    const cleaned = value.trim().replace(/[./]/g, "-");
    let m = cleaned.match(/^(\d{2})-(\d{4})$/);
    let month;
    let year;
    if (m) {
      month = Number(m[1]);
      year = Number(m[2]);
    } else {
      m = cleaned.match(/^(\d{4})-(\d{2})$/);
      if (!m) return null;
      year = Number(m[1]);
      month = Number(m[2]);
    }
    if (!year || !month || month < 1 || month > 12) return null;
    return new Date(year, month - 1, 1);
  },
  toAttribute(value) {
    if (!value) return "";
    const year = value.getFullYear();
    const month = String(value.getMonth() + 1).padStart(2, "0");
    return `${year}-${month}`;
  }
};
var disabledDatesConverter = {
  fromAttribute(value) {
    if (!value) return [];
    let rawList = [];
    const trimmed = value.trim();
    if (trimmed.startsWith("[")) {
      try {
        const parsed = JSON.parse(trimmed);
        if (Array.isArray(parsed)) {
          rawList = parsed.map(String);
        }
      } catch (e) {
        return [];
      }
    } else {
      rawList = trimmed.split(/[\s,]+/).map((v) => v.trim()).filter(Boolean);
    }
    const result = [];
    for (const raw of rawList) {
      const cleaned = raw.replace(/[-/]/g, ".");
      const parts = cleaned.split(".");
      if (parts.length !== 3) continue;
      const [yyyy, mm, dd] = parts.map(Number);
      if (!yyyy || !mm || !dd) continue;
      const date = new Date(yyyy, mm - 1, dd);
      if (date.getFullYear() !== yyyy || date.getMonth() !== mm - 1 || date.getDate() !== dd) continue;
      const iso = `${yyyy}-${String(mm).padStart(2, "0")}-${String(dd).padStart(2, "0")}`;
      result.push(iso);
    }
    return result;
  },
  toAttribute(value) {
    return value ? value.join(",") : "";
  }
};
var SdDatepicker = class extends SolidElement {
  constructor() {
    super();
    /** Localize controller used to fetch localized terms/labels. */
    this.localize = new LocalizeController(this);
    this.hasSlotController = new HasSlotController(this, "label", "help-text", "tooltip");
    this.formControlController = new FormControlController(this, {
      assumeInteractionOn: ["sd-blur", "sd-input"]
    });
    this.locale = "en-US";
    this.value = null;
    this.range = false;
    this.rangeStart = null;
    this.rangeEnd = null;
    this.allowSameDayRange = false;
    this.min = void 0;
    this.max = void 0;
    this.viewMonth = null;
    this.firstDayOfWeek = null;
    this.disabledWeekends = false;
    this.disabledDates = [];
    this.isDateDisabled = null;
    this.size = "lg";
    this.alignment = "left";
    this.label = "";
    this.helpText = "";
    this.floatingLabel = false;
    this.disabled = false;
    this.required = false;
    this.visuallyDisabled = false;
    this.styleOnValid = false;
    this.readonly = false;
    this.placement = "bottom";
    this.placeholder = "";
    this.name = "";
    this.form = "";
    this.open = false;
    this.today = DateUtils.startOfDayLocal(/* @__PURE__ */ new Date());
    this.disabledDatesSet = /* @__PURE__ */ new Set();
    this.previewEnd = null;
    this.statusNavText = "";
    this.statusSelectText = "";
    this.hasFocus = false;
    this.showValidStyle = false;
    this.showInvalidStyle = false;
    this.currentPlacement = this.placement;
    this.inputValue = "";
    /** Internal flag used when tabbing from header into grid to pick initial tabbable day. */
    this.tabbingIntoGrid = false;
    /** Bump counter ensuring live region text updates are recognized. */
    this.statusBumpCounter = 0;
    this.onFocusOut = (ev) => {
      const next = ev.relatedTarget;
      if (next && this.contains(next)) return;
      if (this.open) {
        this.hide();
        this.emit("sd-datepicker-close");
      }
      this.hasFocus = false;
    };
    this.onFocusIn = (ev) => {
      if (this.disabled || this.visuallyDisabled) return;
      const path = ev.composedPath();
      const fromHeader = path.some(
        (n) => {
          var _a, _b;
          return n instanceof HTMLElement && (((_a = n.classList) == null ? void 0 : _a.contains("nav")) || ((_b = n.classList) == null ? void 0 : _b.contains("month-label")));
        }
      );
      if (fromHeader) {
        this.tabbingIntoGrid = true;
      }
    };
    this.handleInput = (ev) => {
      var _a, _b, _c, _d, _e;
      if (this.disabled || this.visuallyDisabled || this.readonly) {
        (_a = ev.preventDefault) == null ? void 0 : _a.call(ev);
        (_b = ev.stopPropagation) == null ? void 0 : _b.call(ev);
        return;
      }
      const input = ev.target;
      const raw = input.value;
      const oldPos = (_c = input.selectionStart) != null ? _c : raw.length;
      const isDeleting = (_d = ev.inputType) == null ? void 0 : _d.startsWith("delete");
      if (!this.range) {
        const inputEl = input;
        const rawText = inputEl.value;
        const oldCaret = (_e = inputEl.selectionStart) != null ? _e : rawText.length;
        const digits = rawText.replace(/\D/g, "").slice(0, 8);
        const d = digits.slice(0, 2);
        const m = digits.slice(2, 4);
        const y = digits.slice(4, 8);
        let nextFormatted = "";
        if (d.length > 0) {
          nextFormatted += d;
          if (d.length === 2) {
            nextFormatted += ".";
          }
        }
        if (m.length > 0 && d.length === 2) {
          nextFormatted += m;
          if (m.length === 2) {
            nextFormatted += ".";
          }
        }
        if (y.length > 0 && d.length === 2 && m.length === 2) {
          nextFormatted += y;
        }
        nextFormatted = nextFormatted.replace(/\.\.+/g, ".");
        const prevFormatted = this.inputValue || "";
        this.inputValue = nextFormatted;
        let newCaret = oldCaret;
        const dotIdxs = (s) => {
          const idxs = [];
          for (let i = 0; i < s.length; i++) if (s[i] === ".") idxs.push(i);
          return idxs;
        };
        const prevDots = dotIdxs(prevFormatted);
        const nextDots = dotIdxs(nextFormatted);
        const prevBefore = prevDots.filter((i) => i < oldCaret).length;
        const nextBefore = nextDots.filter((i) => i < oldCaret).length;
        const insertedBefore = nextBefore - prevBefore;
        if (insertedBefore > 0) {
          newCaret += insertedBefore;
        } else {
          const dotInsertedAtCaret = !prevDots.includes(oldCaret) && nextDots.includes(oldCaret);
          if (dotInsertedAtCaret) newCaret += 1;
        }
        newCaret = Math.min(Math.max(0, newCaret), nextFormatted.length);
        requestAnimationFrame(() => {
          var _a2;
          const el = (_a2 = this.input) != null ? _a2 : inputEl;
          if (el) {
            el.value = this.inputValue;
            el.setSelectionRange(newCaret, newCaret);
          }
        });
        if (/^\d{2}\.\d{2}\.\d{4}$/.test(nextFormatted)) {
          const parsed = this.parseInputText(nextFormatted);
          this.applyParsedInput(parsed);
        } else {
          this.showInvalidStyle = false;
          this.showValidStyle = false;
        }
        return;
      } else {
        const allDigits = raw.replace(/\D/g, "");
        const startDigits = allDigits.slice(0, 8);
        const endDigits = allDigits.slice(8, 16);
        const startDMY = this.buildDmyFromDigits(startDigits);
        const endDMY = this.buildDmyFromDigits(endDigits);
        let formatted;
        if (startDigits.length === 0) {
          formatted = "";
        } else if (startDigits.length < 8) {
          formatted = startDMY;
        } else {
          if (endDigits.length > 0) {
            formatted = `${startDMY} - ${endDMY}`;
          } else {
            formatted = isDeleting ? startDMY : `${startDMY} -`;
          }
        }
        const digitsBefore = this.countDigitsBeforeCaret(raw, oldPos);
        let newPos;
        if (digitsBefore <= 8) {
          const withinStartPos = this.digitIndexToDmyCaretPos(Math.min(digitsBefore, 8));
          newPos = Math.min(withinStartPos, startDMY.length);
        } else {
          const offsetBase = startDigits.length < 8 ? startDMY.length : startDMY.length + 3;
          const endDigitIdx = Math.min(digitsBefore - 8, 8);
          const withinEndPos = this.digitIndexToDmyCaretPos(endDigitIdx);
          newPos = offsetBase + Math.min(withinEndPos, endDMY.length);
        }
        this.inputValue = formatted;
        let committed = false;
        if (/^\d{2}\.\d{2}\.\d{4}$/.test(startDMY)) {
          const startIso = this.dmyToIso(startDMY);
          const pStart = startIso ? DateUtils.parseLocalISO(startIso) : null;
          const startOk = !!pStart && !this.isDisabled(pStart) && this.inMinMax(pStart);
          if (startOk && this.rangeStart !== startIso) {
            this.rangeStart = startIso;
            this.previewEnd = null;
            this.viewMonth = new Date(pStart.getFullYear(), pStart.getMonth(), 1);
            this.focusedDate = DateUtils.startOfDayLocal(pStart);
            committed = true;
          }
        } else {
          if (this.rangeStart) {
            this.rangeStart = null;
            committed = true;
          }
          if (this.rangeEnd) {
            this.rangeEnd = null;
            committed = true;
          }
        }
        if (/^\d{2}\.\d{2}\.\d{4}$/.test(endDMY) && this.rangeStart) {
          const pStart = DateUtils.parseLocalISO(this.rangeStart);
          const endIso = this.dmyToIso(endDMY);
          const pEnd = endIso ? DateUtils.parseLocalISO(endIso) : null;
          const endOk = !!pEnd && !this.isDisabled(pEnd) && this.inMinMax(pEnd);
          if (endOk) {
            const [a, b] = DateUtils.compareDates(pStart, pEnd) <= 0 ? [pStart, pEnd] : [pEnd, pStart];
            const sameDay = DateUtils.isSameDay(a, b);
            const rangeOk = (this.allowSameDayRange || !sameDay) && !this.wouldRangeContainDisabled(a, b);
            if (rangeOk) {
              const normalizedStart = DateUtils.toLocalISODate(DateUtils.startOfDayLocal(a));
              const normalizedEnd = DateUtils.toLocalISODate(DateUtils.startOfDayLocal(b));
              if (this.rangeStart !== normalizedStart || this.rangeEnd !== normalizedEnd) {
                this.rangeStart = normalizedStart;
                this.rangeEnd = normalizedEnd;
                this.viewMonth = new Date(b.getFullYear(), b.getMonth(), 1);
                this.focusedDate = DateUtils.startOfDayLocal(b);
                committed = true;
              }
            }
          }
        } else {
          if (this.rangeEnd) {
            this.rangeEnd = null;
            committed = true;
          }
        }
        this.showInvalidStyle = false;
        this.showValidStyle = !!(this.rangeStart && this.rangeEnd);
        if (committed) {
          this.emit("sd-range-select", { detail: { start: this.rangeStart, end: this.rangeEnd } });
          this.emit("sd-change", { detail: { value: this.value, rangeStart: this.rangeStart, rangeEnd: this.rangeEnd } });
        }
        Promise.resolve().then(() => {
          requestAnimationFrame(() => {
            var _a2;
            const el = (_a2 = this.input) != null ? _a2 : input;
            if (el) {
              el.value = this.inputValue;
              el.setSelectionRange(newPos, newPos);
            }
          });
        });
      }
      if (!this.open && this.hasFocus && !this.disabled && !this.visuallyDisabled) {
        this.show();
      }
      if (this.range) {
        const s = this.rangeStart ? DateUtils.parseLocalISO(this.rangeStart) : null;
        const e = this.rangeEnd ? DateUtils.parseLocalISO(this.rangeEnd) : null;
        if (s && !e) {
          this.setNavStatus(`${this.termStartSelected()}: ${this.formatSelectionLabel(s)}`);
        } else if (s && e) {
          this.setNavStatus(
            `${this.termStartSelected()}: ${this.formatSelectionLabel(s)}; ${this.termEndSelected()}: ${this.formatSelectionLabel(e)}`
          );
        }
      } else if (this.value) {
        const v = DateUtils.parseLocalISO(this.value);
        this.setNavStatus(`${this.formatSelectionLabel(v)}`);
      }
    };
    this.handleInputBlur = () => {
      if (this.disabled || this.visuallyDisabled) {
        this.handleBlur();
        return;
      }
      const parsed = this.parseInputText(this.inputValue);
      if (!parsed.valid) {
        this.inputValue = this.formatInputValue();
        this.showInvalidStyle = !!this.inputValue && !this.value && !this.rangeStart;
      } else {
        this.applyParsedInput(parsed);
      }
      this.handleBlur();
    };
    this.handleCurrentPlacement = (e) => {
      const incomingPlacement = e.detail;
      if (incomingPlacement) {
        this.currentPlacement = incomingPlacement;
      }
    };
    this.handleHeaderKeyDown = (ev, type, direction, isLastHeaderControl) => {
      if (this.disabled || this.visuallyDisabled || this.readonly) {
        return;
      }
      if (ev.key === "Tab" && !ev.shiftKey) {
        if (isLastHeaderControl) {
          ev.preventDefault();
          ev.stopPropagation();
          this.tabbingIntoGrid = true;
          this.focusInitialGridDay();
        }
        return;
      }
      if (ev.key === "Enter" || ev.key === " ") {
        ev.preventDefault();
        ev.stopPropagation();
        if (type === "month") this.setMonth(direction);
        else this.setYear(direction);
      }
    };
    this.onKeyDown = (ev) => {
      var _a, _b;
      if (this.disabled || this.visuallyDisabled || this.readonly) {
        ev.preventDefault();
        ev.stopPropagation();
        return;
      }
      const key = ev.key;
      let handled = true;
      const next = new Date(this.focusedDate);
      switch (key) {
        case "ArrowLeft":
          next.setDate(next.getDate() - 1);
          break;
        case "ArrowRight":
          next.setDate(next.getDate() + 1);
          break;
        case "ArrowUp":
          next.setDate(next.getDate() - 7);
          break;
        case "ArrowDown":
          next.setDate(next.getDate() + 7);
          break;
        case "Escape": {
          if (this.previewEnd) {
            this.previewEnd = null;
            this.setNavStatus(this.localize.term("selectionCleared"));
          } else if (this.range && this.rangeStart && !this.rangeEnd) {
            this.rangeStart = null;
            this.setNavStatus(this.localize.term("selectionCleared"));
            this.emit("sd-range-select", { detail: { start: this.rangeStart, end: this.rangeEnd } });
          }
          if (this.open) {
            this.hide();
            this.emit("sd-datepicker-close");
          }
          break;
        }
        case "Enter":
        case " ":
          this.selectDate(this.focusedDate);
          break;
        default:
          handled = false;
      }
      if (handled) {
        ev.preventDefault();
        const viewMonth = (_a = this.viewMonth) != null ? _a : this.ensureViewMonth();
        const monthChanged = next.getMonth() !== viewMonth.getMonth() || next.getFullYear() !== viewMonth.getFullYear();
        if (monthChanged) {
          const nextViewMonth = new Date(next.getFullYear(), next.getMonth(), 1);
          this.viewMonth = nextViewMonth;
          const monthLabel = this.formatMonthYear(nextViewMonth);
          this.setNavStatus(monthLabel);
        }
        const fd = DateUtils.startOfDayLocal(next);
        if (fd.getTime() !== ((_b = this.focusedDate) == null ? void 0 : _b.getTime())) {
          this.focusedDate = fd;
        }
        const dayLabel = fd.toLocaleDateString(this.locale, {
          weekday: "long",
          day: "numeric",
          month: "long",
          year: "numeric"
        });
        this.setNavStatus(dayLabel);
        this.requestUpdate();
        requestAnimationFrame(() => {
          const root = this.shadowRoot;
          const btn = root == null ? void 0 : root.querySelector("button.day.focused");
          btn == null ? void 0 : btn.focus({ preventScroll: true });
        });
      }
    };
    this.handleInputKeyDown = (ev) => {
      if ((this.disabled || this.visuallyDisabled || this.readonly) && ev.key !== "Tab") {
        ev.preventDefault();
        ev.stopPropagation();
        return;
      }
      if (ev.key === "ArrowLeft" || ev.key === "ArrowRight" || ev.key === "ArrowUp" || ev.key === "ArrowDown" || ev.key === "Home" || ev.key === "End" || ev.key === "PageUp" || ev.key === "PageDown") {
        return;
      }
      if (ev.key === "Escape" && this.open) {
        ev.preventDefault();
        this.hide();
        this.emit("sd-datepicker-close");
        return;
      }
      if (ev.key === "Enter" && !this.open && !this.disabled && !this.visuallyDisabled && !this.readonly) {
        ev.preventDefault();
        this.show();
      }
    };
    this.handleOutsideClick = this.handleOutsideClick.bind(this);
  }
  connectedCallback() {
    var _a;
    super.connectedCallback();
    this.syncDisabledDatesSet();
    document.addEventListener("click", this.handleOutsideClick);
    this.addEventListener("focusout", this.onFocusOut);
    this.updateComplete.then(() => {
      this.formControlController.updateValidity();
    });
    const initialSingle = this.value ? DateUtils.parseLocalISO(this.value) : null;
    const initialRangeStart = this.rangeStart ? DateUtils.parseLocalISO(this.rangeStart) : null;
    const initialFallback = DateUtils.startOfDayLocal(/* @__PURE__ */ new Date());
    const initial = this.range && initialRangeStart ? initialRangeStart : initialSingle != null ? initialSingle : initialFallback;
    const effectiveViewMonth = (_a = this.viewMonth) != null ? _a : new Date(initial.getFullYear(), initial.getMonth(), 1);
    this.viewMonth = effectiveViewMonth;
    this.focusedDate = DateUtils.clampDateToMonth(initial, effectiveViewMonth);
    if (this.firstDayOfWeek === null || this.firstDayOfWeek === void 0) {
      this.firstDayOfWeek = 1;
    }
    this.inputValue = this.formatInputValue();
    this.setAttribute("role", "group");
    this.setAttribute(
      "aria-label",
      this.range ? this.localize.term("datePickerRange") : this.localize.term("datePicker")
    );
    this.addEventListener("focusin", this.onFocusIn);
  }
  firstUpdated() {
    this.formControlController.updateValidity();
  }
  handleOpenChange() {
    if (this.popup) {
      this.popup.active = this.open && !this.disabled && !this.visuallyDisabled;
    }
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    this.removeEventListener("focusin", this.onFocusIn);
    this.removeEventListener("focusout", this.onFocusOut);
    document.removeEventListener("click", this.handleOutsideClick);
  }
  handleLocaleChange() {
    if (this.firstDayOfWeek === null) {
      this.firstDayOfWeek = 1;
    }
    this.requestUpdate();
  }
  handleViewMonthChange() {
    var _a;
    if (!this.viewMonth) return;
    const pivot = this.focusedDate || this.range && this.rangeEnd && DateUtils.parseLocalISO(this.rangeEnd) || this.range && this.rangeStart && DateUtils.parseLocalISO(this.rangeStart) || this.value && DateUtils.parseLocalISO(this.value) || this.today;
    if (!pivot) return;
    const clamped = DateUtils.clampDateToMonth(pivot, this.viewMonth);
    if (clamped.getTime() !== ((_a = this.focusedDate) == null ? void 0 : _a.getTime())) {
      this.focusedDate = clamped;
    }
  }
  handleDisabledDatesChange() {
    this.syncDisabledDatesSet();
    this.requestUpdate();
  }
  handleValueChange() {
    const v = this.value ? DateUtils.parseLocalISO(this.value) : null;
    if (v) {
      this.viewMonth = new Date(v.getFullYear(), v.getMonth(), 1);
      this.focusedDate = DateUtils.startOfDayLocal(v);
    }
    this.inputValue = this.formatInputValue();
    this.updateComplete.then(() => {
      var _a;
      const el = this.input;
      if (el) {
        el.value = (_a = this.inputValue) != null ? _a : "";
        const end = el.value.length;
        el.setSelectionRange(end, end);
      }
      this.formControlController.updateValidity();
    });
    this.emit("sd-change", {
      detail: {
        value: this.value,
        rangeStart: this.rangeStart,
        rangeEnd: this.rangeEnd
      }
    });
  }
  handleRangeChange() {
    const rs = this.rangeStart ? DateUtils.parseLocalISO(this.rangeStart) : null;
    const re = this.rangeEnd ? DateUtils.parseLocalISO(this.rangeEnd) : null;
    const pivot = rs != null ? rs : re;
    if (pivot) {
      this.viewMonth = new Date(pivot.getFullYear(), pivot.getMonth(), 1);
      this.focusedDate = DateUtils.startOfDayLocal(pivot);
    }
    if (this.previewEnd !== null) this.previewEnd = null;
    this.inputValue = this.formatInputValue();
    this.updateComplete.then(() => {
      var _a;
      const el = this.input;
      if (el) {
        el.value = (_a = this.inputValue) != null ? _a : "";
        const end = el.value.length;
        el.setSelectionRange(end, end);
      }
      this.formControlController.updateValidity();
    });
    this.emit("sd-change", {
      detail: {
        value: this.value,
        rangeStart: this.rangeStart,
        rangeEnd: this.rangeEnd
      }
    });
  }
  handleDisabledChange() {
    this.formControlController.setValidity(this.disabled);
    if (this.disabled || this.visuallyDisabled) {
      this.open = false;
    }
  }
  handleSizeChange() {
    this.size = this.floatingLabel && this.size === "sm" ? "md" : this.size;
  }
  get validity() {
    const defaultValidity = { valid: true };
    return this.input instanceof HTMLInputElement ? this.input.validity : defaultValidity;
  }
  get validationMessage() {
    return (this.input instanceof HTMLInputElement ? this.input.validationMessage : "") || "";
  }
  checkValidity() {
    if (this.input instanceof HTMLInputElement) {
      return this.input.checkValidity();
    }
    return true;
  }
  getForm() {
    return this.formControlController.getForm();
  }
  reportValidity() {
    this.formControlController.fakeUserInteraction();
    return this.input instanceof HTMLInputElement ? this.input.reportValidity() : true;
  }
  setCustomValidity(message) {
    var _a;
    (_a = this.input) == null ? void 0 : _a.setCustomValidity(message);
    this.formControlController.updateValidity();
  }
  handleInvalid(event) {
    this.formControlController.setValidity(false);
    this.formControlController.emitInvalidEvent(event);
    this.invalidMessage.textContent = event.target.validationMessage;
  }
  /** Parses a local ISO date string to a Date or returns null. */
  parseISO(iso) {
    return DateUtils.parseLocalISO(iso);
  }
  inMinMax(d) {
    const normalizeBound = (value) => {
      if (value === void 0 || value === null) return null;
      if (value instanceof Date) {
        return DateUtils.startOfDayLocal(value);
      }
      if (typeof value === "number") {
        return DateUtils.startOfDayLocal(new Date(value));
      }
      if (typeof value === "string") {
        const parsed = this.parseISO(value);
        return parsed ? DateUtils.startOfDayLocal(parsed) : null;
      }
      return null;
    };
    const min = normalizeBound(this.min);
    const max = normalizeBound(this.max);
    if (min && d < min) return false;
    if (max && d > max) return false;
    return true;
  }
  /** Returns true if the date matches any date in disabledDatesSet. */
  isInDisabledDates(d) {
    if (!this.disabledDatesSet || this.disabledDatesSet.size === 0) return false;
    const yyyy = d.getFullYear();
    const mm = String(d.getMonth() + 1).padStart(2, "0");
    const dd = String(d.getDate()).padStart(2, "0");
    const iso = `${yyyy}-${mm}-${dd}`;
    return this.disabledDatesSet.has(iso);
  }
  /** Returns true if the date is Saturday or Sunday. */
  isWeekend(d) {
    const day = d.getDay();
    return day === 0 || day === 6;
  }
  /** Returns true if the date is disabled */
  isDisabled(d) {
    var _a;
    if (!this.inMinMax(d)) return true;
    if (this.disabledWeekends && this.isWeekend(d)) return true;
    if (this.isInDisabledDates(d)) return true;
    if ((_a = this.isDateDisabled) == null ? void 0 : _a.call(this, d)) return true;
    return false;
  }
  /** Updates the hidden live region for navigation feedback. */
  setNavStatus(text) {
    this.statusNavText = text;
  }
  /** Announces an assertive message with a slight delay to ensure SR pick-up. */
  announceSelect(message, delayMs = 40) {
    setTimeout(() => {
      this.statusBumpCounter++;
      const bump = "\u200B".repeat(this.statusBumpCounter % 3);
      this.statusSelectText = message + bump;
    }, delayMs);
  }
  /** Returns localized selection label for announcements. */
  formatSelectionLabel(d) {
    if (this.locale === "de-DE") {
      return d.toLocaleDateString("de-DE", { day: "numeric", month: "long", year: "numeric" });
    }
    const day = d.getDate();
    const ordinal = this.ordinal(day);
    const month = d.toLocaleDateString("en-US", { month: "long" });
    const year = d.getFullYear();
    return `${ordinal} of ${month} ${year}`;
  }
  /** English ordinal for day numbers (1st, 2nd, 3rd...). */
  ordinal(day) {
    const suffixes = ["th", "st", "nd", "rd"];
    const lastTwoDigits = day % 100;
    const suffix = suffixes[(lastTwoDigits - 20) % 10] || suffixes[lastTwoDigits] || suffixes[0];
    return day + suffix;
  }
  /** Syncs disabledDatesSet from the disabledDates property */
  syncDisabledDatesSet() {
    let arr = [];
    if (Array.isArray(this.disabledDates)) {
      arr = this.disabledDates;
    } else if (typeof this.disabledDates === "string") {
      const s = this.disabledDates.trim();
      if (s.startsWith("[")) {
        try {
          const parsed = JSON.parse(s);
          if (Array.isArray(parsed)) arr = parsed;
        } catch (e) {
          arr = [];
        }
      } else if (s.length > 0) {
        arr = s.split(",").map((v) => v.trim()).filter(Boolean);
      }
    }
    this.disabledDatesSet = new Set(arr);
  }
  /** Returns true if the range between two dates contains any disabled dates. */
  wouldRangeContainDisabled(a, b) {
    const start = DateUtils.compareDates(a, b) <= 0 ? DateUtils.startOfDayLocal(a) : DateUtils.startOfDayLocal(b);
    const end = DateUtils.compareDates(a, b) <= 0 ? DateUtils.startOfDayLocal(b) : DateUtils.startOfDayLocal(a);
    const cursor = new Date(start);
    while (DateUtils.compareDates(cursor, end) <= 0) {
      if (this.isDisabled(cursor)) return true;
      cursor.setDate(cursor.getDate() + 1);
    }
    return false;
  }
  termStartSelected() {
    var _a, _b;
    return (_b = (_a = this.localize) == null ? void 0 : _a.term) == null ? void 0 : _b.call(_a, "startDateSelected");
  }
  termEndSelected() {
    var _a, _b;
    return (_b = (_a = this.localize) == null ? void 0 : _a.term) == null ? void 0 : _b.call(_a, "endDateSelected");
  }
  /** UI formatting: internal ISO → DD.MM.YYYY */
  isoToDmy(iso) {
    if (!iso) return "";
    let d = DateUtils.parseLocalISO(iso);
    if (!d) {
      d = DateUtils.parseLocalISO(iso.replace(/-/g, "."));
    }
    if (!d) return "";
    const dd = String(d.getDate()).padStart(2, "0");
    const mm = String(d.getMonth() + 1).padStart(2, "0");
    const yyyy = String(d.getFullYear());
    return `${dd}.${mm}.${yyyy}`;
  }
  /** UI parsing: DD.MM.YYYY → internal ISO (YYYY-MM-DD), returns null if invalid */
  dmyToIso(dmy) {
    if (!dmy) return null;
    const m = dmy.match(/^(\d{2})\.(\d{2})\.(\d{4})$/);
    if (!m) return null;
    const dd = Number(m[1]);
    const mm = Number(m[2]);
    const yyyy = Number(m[3]);
    const d = new Date(yyyy, mm - 1, dd);
    if (d.getFullYear() !== yyyy || d.getMonth() !== mm - 1 || d.getDate() !== dd) return null;
    const localMidnight = DateUtils.startOfDayLocal(d);
    return DateUtils.toLocalISODate(localMidnight);
  }
  formatInputValue() {
    const loc = (this.locale || "").toLowerCase();
    const langAttr = (this.getAttribute("lang") || "").toLowerCase();
    const isGerman = loc.startsWith("de") || langAttr.startsWith("de");
    const separator = isGerman ? "\u2013" : "-";
    if (!this.range) {
      return this.isoToDmy(this.value);
    }
    const start = this.isoToDmy(this.rangeStart);
    const end = this.isoToDmy(this.rangeEnd);
    if (start && end) return `${start} ${separator} ${end}`;
    if (start && !end) return `${start} ${separator}`;
    return "";
  }
  /** Parses input text (DD.MM.YYYY) into normalized internal ISO values with validation flag. */
  parseInputText(text) {
    var _a, _b;
    const trimmed = text.trim();
    if (this.range) {
      const parts = trimmed.split(/\s*-\s*/);
      if (parts.length === 1) {
        const startCandidate = parts[0];
        if (!startCandidate) return { start: null, end: null, valid: true };
        const isoStart = this.dmyToIso(startCandidate);
        if (!isoStart) return { start: null, end: null, valid: false };
        return { start: isoStart, end: null, valid: true };
      } else if (parts.length >= 2) {
        const startCandidate = (_a = parts[0]) != null ? _a : "";
        const endCandidate = (_b = parts[1]) != null ? _b : "";
        const isoStart = startCandidate ? this.dmyToIso(startCandidate) : null;
        const isoEnd = endCandidate ? this.dmyToIso(endCandidate) : null;
        if (startCandidate && !isoStart) return { start: null, end: null, valid: false };
        if (endCandidate && !isoEnd) return { start: null, end: null, valid: false };
        return { start: isoStart, end: isoEnd, valid: true };
      }
      return { start: null, end: null, valid: false };
    }
    if (!trimmed) return { single: null, valid: true };
    const iso = this.dmyToIso(trimmed);
    if (!iso) return { single: null, valid: false };
    return { single: iso, valid: true };
  }
  /** Applies parsed input into component state; returns true if state changed. */
  applyParsedInput(parsed) {
    var _a, _b, _c, _d;
    if (!parsed.valid) {
      this.showInvalidStyle = true;
      this.showValidStyle = false;
      this.formControlController.setValidity(false);
      return false;
    }
    const inBoundsIso = (iso) => {
      if (!iso) return true;
      const d = DateUtils.parseLocalISO(iso);
      if (!this.inMinMax(d)) return false;
      if (this.isDisabled(d)) return false;
      return true;
    };
    let changed = false;
    if (this.range) {
      const startIso = (_a = parsed.start) != null ? _a : null;
      const endIso = (_b = parsed.end) != null ? _b : null;
      if (!inBoundsIso(startIso) || endIso && !inBoundsIso(endIso)) {
        this.showInvalidStyle = true;
        this.showValidStyle = false;
        return false;
      }
      let rs = startIso ? DateUtils.parseLocalISO(startIso) : null;
      let re = endIso ? DateUtils.parseLocalISO(endIso) : null;
      if (rs && re) {
        if (DateUtils.compareDates(rs, re) > 0) {
          const tmp = rs;
          rs = re;
          re = tmp;
        }
        if (!this.allowSameDayRange && DateUtils.isSameDay(rs, re)) {
          this.showInvalidStyle = true;
          this.showValidStyle = false;
          return false;
        }
        if (this.wouldRangeContainDisabled(rs, re)) {
          this.showInvalidStyle = true;
          this.showValidStyle = false;
          return false;
        }
      }
      const newStart = rs ? DateUtils.toLocalISODate(DateUtils.startOfDayLocal(rs)) : null;
      const newEnd = re ? DateUtils.toLocalISODate(DateUtils.startOfDayLocal(re)) : null;
      if (this.rangeStart !== newStart || this.rangeEnd !== newEnd) {
        this.rangeStart = newStart;
        this.rangeEnd = newEnd;
        this.previewEnd = null;
        changed = true;
        const pivot = (_c = rs != null ? rs : re) != null ? _c : this.today;
        this.viewMonth = new Date(pivot.getFullYear(), pivot.getMonth(), 1);
        this.focusedDate = DateUtils.startOfDayLocal(pivot);
        this.emit("sd-range-select", { detail: { start: this.rangeStart, end: this.rangeEnd } });
      }
      this.showInvalidStyle = false;
      if (this.range) {
        this.showValidStyle = !!(this.rangeStart && this.rangeEnd && this.styleOnValid);
      } else {
        this.showValidStyle = !!(this.value && this.styleOnValid);
      }
      this.formControlController.setValidity(true);
      this.updateComplete.then(() => {
        this.formControlController.updateValidity();
      });
      return true;
    }
    const singleIso = (_d = parsed.single) != null ? _d : null;
    if (!inBoundsIso(singleIso)) {
      this.input.setCustomValidity(this.localize.term("datePickerRange"));
      this.formControlController.setValidity(false);
      this.showInvalidStyle = true;
      this.showValidStyle = false;
      return false;
    }
    const v = singleIso ? DateUtils.parseLocalISO(singleIso) : null;
    const newValue = v ? DateUtils.toLocalISODate(DateUtils.startOfDayLocal(v)) : null;
    if (this.value !== newValue) {
      this.value = newValue;
      changed = true;
      if (v) {
        this.viewMonth = new Date(v.getFullYear(), v.getMonth(), 1);
        this.focusedDate = DateUtils.startOfDayLocal(v);
      }
      this.emit("sd-select", { detail: { value: this.value, date: v != null ? v : null } });
    }
    this.showInvalidStyle = false;
    this.showValidStyle = !!this.value;
    this.inputValue = this.formatInputValue();
    return changed;
  }
  /** Converts up to 8 digits into DD, DD.MM, or DD.MM.YYYY. */
  buildDmyFromDigits(digits) {
    const capped = digits.slice(0, 8);
    const d = capped.slice(0, 2);
    const m = capped.slice(2, 4);
    const y = capped.slice(4, 8);
    let out = d;
    if (m.length) out += "." + m;
    if (y.length) out += "." + y;
    return out;
  }
  /** Maps digit count before caret to caret position in DD.MM.YYYY string. */
  digitIndexToDmyCaretPos(digitIdx) {
    if (digitIdx <= 2) return digitIdx;
    if (digitIdx <= 4) return 2 + 1 + (digitIdx - 2);
    return 2 + 1 + 2 + 1 + (digitIdx - 4);
  }
  /** Counts how many digits appear before the caret in the raw string. */
  countDigitsBeforeCaret(raw, caretPos) {
    return raw.slice(0, caretPos).replace(/\D/g, "").length;
  }
  handleOutsideClick(event) {
    var _a, _b;
    const path = (_b = (_a = event.composedPath) == null ? void 0 : _a.call(event)) != null ? _b : [];
    if (!path.includes(this)) {
      this.hide();
      this.hasFocus = false;
      this.emit("sd-datepicker-close");
    }
  }
  show() {
    if (this.open || this.disabled || this.visuallyDisabled || this.readonly) {
      this.open = false;
      return;
    }
    this.open = true;
  }
  hide() {
    if (!this.open || this.disabled) {
      this.open = false;
      return;
    }
    this.open = false;
  }
  handleMouseDown(event) {
    if (this.visuallyDisabled || this.disabled || this.readonly) {
      event.preventDefault();
      event.stopPropagation();
      return;
    }
    event.preventDefault();
    if (!this.open) this.show();
  }
  handleBlur() {
    this.hasFocus = false;
    this.emit("sd-blur");
  }
  handleFocus() {
    this.hasFocus = true;
    if (!this.open && !this.disabled && !this.visuallyDisabled && !this.readonly) {
      this.show();
    }
    this.emit("sd-focus");
  }
  setMonth(offset) {
    var _a;
    const viewMonth = (_a = this.viewMonth) != null ? _a : this.ensureViewMonth();
    const next = new Date(viewMonth.getFullYear(), viewMonth.getMonth() + offset, 1);
    if (next.getMonth() === viewMonth.getMonth() && next.getFullYear() === viewMonth.getFullYear()) return;
    this.viewMonth = next;
    const monthLabel = this.formatMonthYear(next);
    this.setNavStatus(monthLabel);
    this.emit("sd-month-change", { detail: { month: next } });
  }
  setYear(offset) {
    var _a;
    const viewMonth = (_a = this.viewMonth) != null ? _a : this.ensureViewMonth();
    const next = new Date(viewMonth.getFullYear() + offset, viewMonth.getMonth(), 1);
    if (next.getFullYear() === viewMonth.getFullYear() && next.getMonth() === viewMonth.getMonth()) {
      return;
    }
    this.viewMonth = next;
    const monthLabel = this.formatMonthYear(next);
    this.setNavStatus(monthLabel);
    this.emit("sd-month-year", { detail: { month: next } });
  }
  focusInitialGridDay() {
    var _a;
    let target = null;
    if (!this.range && this.value) {
      const v = DateUtils.parseLocalISO(this.value);
      if (v) target = DateUtils.startOfDayLocal(v);
    }
    if (this.range) {
      const rs = this.rangeStart ? DateUtils.parseLocalISO(this.rangeStart) : null;
      const re = this.rangeEnd ? DateUtils.parseLocalISO(this.rangeEnd) : null;
      if (re) target = DateUtils.startOfDayLocal(re);
      else if (rs) target = DateUtils.startOfDayLocal(rs);
    }
    const viewMonth = (_a = this.viewMonth) != null ? _a : this.ensureViewMonth();
    const inViewAndEnabled = (d) => {
      if (!d) return false;
      const sameMonth = d.getFullYear() === viewMonth.getFullYear() && d.getMonth() === viewMonth.getMonth();
      return sameMonth && !this.isDisabled(d);
    };
    if (!inViewAndEnabled(target)) {
      const { weeks } = this.getMonthMatrix(viewMonth);
      const todayInView = weeks.flat().find(
        (day) => day.getMonth() === viewMonth.getMonth() && DateUtils.isSameDay(day, this.today) && !this.isDisabled(day)
      );
      if (todayInView) {
        target = DateUtils.startOfDayLocal(todayInView);
      } else {
        const firstEnabled = weeks.flat().find((day) => day.getMonth() === viewMonth.getMonth() && !this.isDisabled(day));
        target = firstEnabled ? DateUtils.startOfDayLocal(firstEnabled) : null;
      }
    }
    if (target) {
      this.focusedDate = target;
    }
    this.requestUpdate();
    requestAnimationFrame(() => {
      const root = this.shadowRoot;
      const selectedBtn = (root == null ? void 0 : root.querySelector("button.day.selected")) || (root == null ? void 0 : root.querySelector("button.day.focused")) || (root == null ? void 0 : root.querySelector('button.day[tabindex="0"]')) || (root == null ? void 0 : root.querySelector("button.day"));
      selectedBtn == null ? void 0 : selectedBtn.focus({ preventScroll: true });
    });
  }
  selectSingleDate(d) {
    if (this.readonly) return;
    if (this.isDisabled(d)) return;
    const localMidnight = DateUtils.startOfDayLocal(d);
    const iso = DateUtils.toLocalISODate(localMidnight);
    if (this.value === iso) return;
    this.value = iso;
    const announce = `${this.formatSelectionLabel(localMidnight)}, ${this.localize.term("selected")}`;
    this.announceSelect(announce);
    this.emit("sd-select", { detail: { value: this.value, date: localMidnight } });
    this.inputValue = this.formatInputValue();
    this.updateComplete.then(() => {
      var _a;
      const el = this.input;
      if (el) {
        el.value = (_a = this.inputValue) != null ? _a : "";
        Promise.resolve().then(() => {
          requestAnimationFrame(() => {
            const end = el.value.length;
            el.setSelectionRange(end, end);
          });
        });
      }
    });
  }
  selectRangeDate(d) {
    if (this.readonly) return;
    const day = DateUtils.startOfDayLocal(d);
    const rs = this.rangeStart ? DateUtils.parseLocalISO(this.rangeStart) : null;
    const re = this.rangeEnd ? DateUtils.parseLocalISO(this.rangeEnd) : null;
    if (!rs && !re) {
      if (this.isDisabled(day)) return;
      this.rangeStart = DateUtils.toLocalISODate(day);
      this.rangeEnd = null;
      this.previewEnd = null;
      const startLabel = this.formatSelectionLabel(day);
      this.announceSelect(`${this.termStartSelected()}: ${startLabel}`, 40);
      this.emit("sd-range-select", { detail: { start: this.rangeStart, end: this.rangeEnd } });
      this.inputValue = this.formatInputValue();
      this.updateComplete.then(() => {
        var _a;
        const el = this.input;
        if (el) {
          el.value = (_a = this.inputValue) != null ? _a : "";
          Promise.resolve().then(() => {
            requestAnimationFrame(() => {
              const end = el.value.length;
              el.setSelectionRange(end, end);
            });
          });
        }
      });
      return;
    }
    if (rs && !re) {
      if (this.isDisabled(day)) return;
      if (DateUtils.isSameDay(rs, day)) {
        if (!this.allowSameDayRange) {
          this.rangeStart = DateUtils.toLocalISODate(day);
          this.rangeEnd = null;
          this.previewEnd = null;
          const startLabel2 = this.formatSelectionLabel(day);
          this.announceSelect(`${this.termStartSelected()}: ${startLabel2}`, 40);
          this.emit("sd-range-select", { detail: { start: this.rangeStart, end: this.rangeEnd } });
          this.inputValue = this.formatInputValue();
          this.updateComplete.then(() => {
            var _a;
            const el = this.input;
            if (el) {
              el.value = (_a = this.inputValue) != null ? _a : "";
              Promise.resolve().then(() => {
                requestAnimationFrame(() => {
                  const end2 = el.value.length;
                  el.setSelectionRange(end2, end2);
                });
              });
            }
          });
          return;
        }
        this.rangeStart = DateUtils.toLocalISODate(day);
        this.rangeEnd = DateUtils.toLocalISODate(day);
        this.previewEnd = null;
        const label = this.formatSelectionLabel(day);
        this.announceSelect(`${this.termStartSelected()}: ${label}`, 40);
        this.announceSelect(`${this.termEndSelected()}: ${label}`, 140);
        this.emit("sd-range-select", { detail: { start: this.rangeStart, end: this.rangeEnd } });
        this.inputValue = this.formatInputValue();
        this.updateComplete.then(() => {
          var _a;
          const el = this.input;
          if (el) {
            el.value = (_a = this.inputValue) != null ? _a : "";
            Promise.resolve().then(() => {
              requestAnimationFrame(() => {
                const end2 = el.value.length;
                el.setSelectionRange(end2, end2);
              });
            });
          }
        });
        return;
      }
      const rsDate = DateUtils.parseLocalISO(this.rangeStart);
      if (this.wouldRangeContainDisabled(rsDate, day)) return;
      const [start, end] = DateUtils.compareDates(rsDate, day) <= 0 ? [rsDate, day] : [day, rsDate];
      this.rangeStart = DateUtils.toLocalISODate(start);
      this.rangeEnd = DateUtils.toLocalISODate(end);
      this.previewEnd = null;
      const startLabel = this.formatSelectionLabel(start);
      const endLabel = this.formatSelectionLabel(end);
      this.announceSelect(`${this.termStartSelected()}: ${startLabel}`, 40);
      this.announceSelect(`${this.termEndSelected()}: ${endLabel}`, 140);
      this.emit("sd-range-select", { detail: { start: this.rangeStart, end: this.rangeEnd } });
      this.inputValue = this.formatInputValue();
      this.updateComplete.then(() => {
        var _a;
        const el = this.input;
        if (el) {
          el.value = (_a = this.inputValue) != null ? _a : "";
          Promise.resolve().then(() => {
            requestAnimationFrame(() => {
              const caretEnd = el.value.length;
              el.setSelectionRange(caretEnd, caretEnd);
            });
          });
        }
      });
      return;
    }
    if (rs && re) {
      if (this.isDisabled(day)) return;
      this.rangeStart = DateUtils.toLocalISODate(day);
      this.rangeEnd = null;
      this.previewEnd = null;
      const startLabel = this.formatSelectionLabel(day);
      this.announceSelect(`${this.termStartSelected()}: ${startLabel}`, 40);
      this.emit("sd-range-select", { detail: { start: this.rangeStart, end: this.rangeEnd } });
      this.inputValue = this.formatInputValue();
      this.updateComplete.then(() => {
        var _a;
        const el = this.input;
        if (el) {
          el.value = (_a = this.inputValue) != null ? _a : "";
          Promise.resolve().then(() => {
            requestAnimationFrame(() => {
              const end = el.value.length;
              el.setSelectionRange(end, end);
            });
          });
        }
      });
    }
  }
  selectDate(d) {
    if (this.readonly) return;
    if (this.range) this.selectRangeDate(d);
    else this.selectSingleDate(d);
  }
  ensureViewMonth() {
    if (this.viewMonth) {
      return this.viewMonth;
    }
    const initialSingle = this.value ? DateUtils.parseLocalISO(this.value) : null;
    const initialRangeStart = this.rangeStart ? DateUtils.parseLocalISO(this.rangeStart) : null;
    const initialFallback = DateUtils.startOfDayLocal(/* @__PURE__ */ new Date());
    const initial = this.range && initialRangeStart ? initialRangeStart : initialSingle != null ? initialSingle : initialFallback;
    const effectiveViewMonth = new Date(initial.getFullYear(), initial.getMonth(), 1);
    this.viewMonth = effectiveViewMonth;
    return effectiveViewMonth;
  }
  getMonthMatrix(monthRef) {
    var _a;
    const fdw = (_a = this.firstDayOfWeek) != null ? _a : 1;
    const firstOfMonth = new Date(monthRef.getFullYear(), monthRef.getMonth(), 1);
    const start = new Date(firstOfMonth);
    const offset = (firstOfMonth.getDay() - fdw + 7) % 7;
    start.setDate(firstOfMonth.getDate() - offset);
    const weeks = [];
    const cursor = start;
    for (let w = 0; w < 6; w++) {
      const row = [];
      for (let d = 0; d < 7; d++) {
        row.push(new Date(cursor));
        cursor.setDate(cursor.getDate() + 1);
      }
      weeks.push(row);
    }
    const isRowOutsideMonth = (row) => row.every((d) => d.getMonth() !== monthRef.getMonth());
    while (weeks.length > 0 && isRowOutsideMonth(weeks[weeks.length - 1])) {
      weeks.pop();
    }
    return { weeks };
  }
  formatMonthYear(d) {
    try {
      return new Intl.DateTimeFormat(this.locale, { month: "long", year: "numeric" }).format(d);
    } catch (e) {
      return `${d.toLocaleString(void 0, { month: "long" })} ${d.getFullYear()}`;
    }
  }
  weekdayLabels() {
    var _a;
    const fdw = (_a = this.firstDayOfWeek) != null ? _a : 1;
    const base = new Date(2021, 7, 1);
    const labels = [];
    for (let i = 0; i < 7; i++) {
      const day = new Date(base);
      day.setDate(base.getDate() + (fdw + i) % 7);
      try {
        labels.push(new Intl.DateTimeFormat(this.locale, { weekday: "short" }).format(day));
      } catch (e) {
        labels.push(day.toLocaleDateString(void 0, { weekday: "short" }));
      }
    }
    return labels;
  }
  /** Chooses a tabbable day when tabbing into the grid (today or first enabled). */
  getTabTargetDayForCurrentView(weeks) {
    var _a;
    const viewMonth = (_a = this.viewMonth) != null ? _a : this.ensureViewMonth();
    const inViewToday = weeks.flat().find((d) => d.getMonth() === viewMonth.getMonth() && DateUtils.isSameDay(d, this.today) && !this.isDisabled(d));
    if (inViewToday) return DateUtils.startOfDayLocal(inViewToday);
    const firstEnabled = weeks.flat().find((d) => d.getMonth() === viewMonth.getMonth() && !this.isDisabled(d));
    return firstEnabled ? DateUtils.startOfDayLocal(firstEnabled) : null;
  }
  /** Mouse enter on a day: updates preview end when selecting a range. */
  onDayMouseEnter(day) {
    if (!this.range || this.readonly) return;
    const rs = this.rangeStart ? DateUtils.parseLocalISO(this.rangeStart) : null;
    const re = this.rangeEnd ? DateUtils.parseLocalISO(this.rangeEnd) : null;
    if (rs && !re) {
      const local = DateUtils.startOfDayLocal(day);
      this.previewEnd = this.isDisabled(local) ? null : local;
      this.requestUpdate();
    }
  }
  onGridMouseLeave() {
    if (this.previewEnd !== null) {
      this.previewEnd = null;
      this.requestUpdate();
    }
  }
  renderCalendar() {
    var _a, _b;
    const viewMonth = (_a = this.viewMonth) != null ? _a : this.ensureViewMonth();
    const { weeks } = this.getMonthMatrix(viewMonth);
    const monthLabel = this.formatMonthYear(viewMonth);
    const weekdays = this.weekdayLabels();
    const selectedSingle = this.value ? this.parseISO(this.value) : null;
    const rs = this.rangeStart ? this.parseISO(this.rangeStart) : null;
    const re = this.rangeEnd ? this.parseISO(this.rangeEnd) : null;
    const pe = this.previewEnd;
    const isInPreviewRange = (day) => {
      if (!this.range || !rs || re || !pe) return false;
      return DateUtils.isBetweenInclusive(day, rs, pe);
    };
    const tabTarget = this.getTabTargetDayForCurrentView(weeks);
    return html`<div part="datepicker" class="${cx(
      "w-[284px] z-50 bg-white py-3 px-4",
      this.open ? "block shadow-listbox" : "hidden",
      ((_b = this.currentPlacement) == null ? void 0 : _b.startsWith("bottom")) ? "border-r-2 border-b-2 border-l-2 form-control__listbox-border-bottom-right-radius form-control__listbox-border-bottom-left-radius" : "border-r-2 border-t-2 border-l-2 form-control__listbox-border-top-right-radius form-control__listbox-border-top-left-radius",
      "border-primary"
    )}"><div class="flex flex-row items-center w-full justify-between mb-3" part="header"><div class="flex items-center"><button type="button" tabindex="0" class="nav prev w-6 h-6 hover:cursor-pointer sd-interactive" part="prev-year-button" @click="${() => this.setYear(-1)}" @keydown="${(ev) => this.handleHeaderKeyDown(ev, "year", -1, false)}" aria-label="${this.localize.term("previousYear")}"><sd-6-22-0-icon library="_internal" name="chevrons-sm-left" class="h-6 w-6"></sd-6-22-0-icon></button> <button type="button" tabindex="0" class="nav prev w-6 h-6 hover:cursor-pointer sd-interactive" part="prev-month-button" @click="${() => this.setMonth(-1)}" @keydown="${(ev) => this.handleHeaderKeyDown(ev, "month", -1, false)}" aria-label="${this.localize.term("previousMonth")}"><sd-6-22-0-icon library="_internal" name="chevron-sm-left" class="h-6 w-6"></sd-6-22-0-icon></button></div><div tabindex="-1" class="month-label flex justify-center sd-headline sd-headline--size-base" part="month-label" aria-live="polite">${monthLabel}</div><div class="flex items-center"><button type="button" tabindex="0" class="nav next w-6 h-6 hover:cursor-pointer sd-interactive" part="next-month-button" @click="${() => this.setMonth(1)}" @keydown="${(ev) => this.handleHeaderKeyDown(ev, "month", 1, false)}" aria-label="${this.localize.term("nextMonth")}"><sd-6-22-0-icon library="_internal" name="chevron-sm-right" class="h-6 w-6"></sd-6-22-0-icon></button> <button type="button" tabindex="0" class="nav next w-6 h-6 hover:cursor-pointer sd-interactive" part="next-year-button" @click="${() => this.setYear(1)}" @keydown="${(ev) => this.handleHeaderKeyDown(ev, "year", 1, true)}" aria-label="${this.localize.term("nextYear")}"><sd-6-22-0-icon library="_internal" name="chevrons-sm-right" class="h-6 w-6"></sd-6-22-0-icon></button></div></div><sd-6-22-0-divider></sd-6-22-0-divider><div class="sr-only" aria-live="polite" aria-atomic="true">${this.statusNavText}</div><div class="sr-only" aria-live="assertive" aria-atomic="true">${this.statusSelectText}</div><div class="sr-only" id="keyboard-hint">${this.localize.term("datePickerInfo")}</div><div class="grid mt-2" role="grid" aria-describedby="keyboard-hint" aria-label="${monthLabel}" part="grid" @mouseleave="${this.onGridMouseLeave}" @focusin="${() => {
      this.tabbingIntoGrid = false;
    }}"><div class="grid-row grid-head grid grid-cols-7 gap-y-[1px]" role="row">${weekdays.map(
      (w, colIndex) => html`<div role="columnheader" aria-colindex="${colIndex + 1}" part="weekday" class="cell head flex items-center justify-center font-bold text-black text-sm leading-none h-8" aria-label="${w}" title="${w}" id="${"col-" + (colIndex + 1)}">${w}</div>`
    )}</div>${weeks.map(
      (week, rowIndex) => html`<div class="grid-row grid grid-cols-7 ${rowIndex === 0 ? "mt-2" : ""}" role="row" aria-rowindex="${rowIndex + 2}">${week.map((day, colIndex) => {
        const inMonth = day.getMonth() === viewMonth.getMonth();
        const disabled = this.isDisabled(day) || !this.inMinMax(day);
        const isFocused = DateUtils.isSameDay(day, this.focusedDate);
        const isToday = DateUtils.isSameDay(day, this.today);
        const isSelectedSingle = !this.range && selectedSingle ? DateUtils.isSameDay(day, selectedSingle) : false;
        const isRangeStart = this.range && rs ? DateUtils.isSameDay(day, rs) : false;
        const isRangeEnd = this.range && re ? DateUtils.isSameDay(day, re) : false;
        const inSelectedRange = this.range && rs && re ? DateUtils.isBetweenInclusive(day, rs, re) : false;
        const inPreviewRange = isInPreviewRange(day) && !disabled;
        let tabIndex = -1;
        const isTabTarget = tabTarget && DateUtils.isSameDay(day, tabTarget);
        if (this.tabbingIntoGrid && isTabTarget) {
          tabIndex = 0;
        } else if (!this.tabbingIntoGrid && isFocused) {
          tabIndex = 0;
        }
        const isWeekendDay = this.isWeekend(day);
        const label = day.toLocaleDateString(this.locale, {
          weekday: "long",
          day: "numeric",
          month: "long",
          year: "numeric"
        });
        const roleDesc = isRangeStart ? this.localize.term("startDateSelected") : isRangeEnd ? this.localize.term("endDateSelected") : void 0;
        return html`<button type="button" part="day" class="${cx(
          "cell day flex items-center justify-center focus-visible:outline focus:outline-2 focus:outline-primary -outline-offset-2 rounded w-[36px]",
          this.size === "sm" ? "text-sm h-6" : "text-base h-8",
          isRangeStart || isRangeEnd ? !isFocused ? "outline-none sd-6-22-0-datepicker__date-item--selected-color-background sd-6-22-0-datepicker__date-item--selected-color-text hover:sd-6-22-0-datepicker__date-item--selected--hover-color-background hover:sd-6-22-0-datepicker__date-item--selected--hover-color-text" : "outline-none sd-6-22-0-datepicker__date-item--selected--hover-color-background sd-6-22-0-datepicker__date-item--selected--hover-color-text" : "hover:sd-6-22-0-datepicker__date-item--hover--default-color-text",
          !isRangeStart && !isRangeEnd && !inSelectedRange && "hover:sd-6-22-0-datepicker__date-item--hover--default-color-background",
          isSelectedSingle ? "selected outline-none border-primary sd-6-22-0-datepicker__date-item--selected-color-background sd-6-22-0-datepicker__date-item--selected-color-text hover:sd-6-22-0-datepicker__date-item--selected--hover-color-text hover:sd-6-22-0-datepicker__date-item--selected--hover-color-background" : !inMonth ? this.disabledWeekends && isWeekendDay ? "out-month weekend-day text-neutral-500" : isWeekendDay ? "out-month weekend-day text-neutral-700" : "out-month text-neutral-700 hover:sd-6-22-0-datepicker__date-item--hover--prev-next-color-text hover:sd-6-22-0-datepicker__date-item--hover--prev-next-color-background" : this.isInDisabledDates(day) || !this.inMinMax(day) ? "out-month text-neutral-500" : this.disabledWeekends && isWeekendDay ? "weekend-day text-neutral-500" : "in-month sd-6-22-0-datepicker__date-item--default-color-text",
          isRangeStart ? "rounded-l-md rounded-r-none" : "",
          isRangeEnd ? "range-end rounded-r-md rounded-l-none" : "",
          inSelectedRange && !isRangeStart && !isRangeEnd ? "in-range selected sd-6-22-0-datepicker__date-item--range-color-background rounded-none hover:sd-6-22-0-datepicker__date-item--selected--hover-color-background hover:sd-6-22-0-datepicker__date-item--selected--hover-color-text" : "",
          !inSelectedRange && inPreviewRange && !isRangeStart && !isRangeEnd ? "in-preview-range bg-primary-100 text-primary-500 rounded-none" : "",
          isToday && !isSelectedSingle && !isRangeStart && !isRangeEnd && isFocused ? "today border-[1px] border-primary sd-6-22-0-datepicker__date-item--current-font-weight" : "",
          disabled ? "disabled cursor-not-allowed hover:bg-transparent" : "cursor-pointer",
          isFocused && !isToday ? "focused outline outline-2 outline-primary" : ""
        )}" role="gridcell" aria-colindex="${colIndex + 1}" aria-labelledby="${"col-" + (colIndex + 1)}" .tabIndex="${tabIndex}" ?disabled="${disabled || this.disabled || this.readonly}" aria-disabled="${disabled || this.visuallyDisabled || this.disabled || this.readonly ? "true" : "false"}" aria-selected="${isSelectedSingle || inSelectedRange || isRangeStart || isRangeEnd ? "true" : "false"}" aria-current="${isToday ? "date" : nothing}" aria-label="${label}" aria-roledescription="${roleDesc != null ? roleDesc : nothing}" @focus="${() => this.focusedDate = DateUtils.startOfDayLocal(day)}" @mouseenter="${() => this.onDayMouseEnter(day)}" @keydown="${this.onKeyDown}" @click="${() => {
          this.focusedDate = DateUtils.startOfDayLocal(day);
          this.selectDate(day);
        }}">${day.getDate()}</button>`;
      })}</div>`
    )}</div></div>`;
  }
  render() {
    var _a, _b;
    const slots = {
      label: this.hasSlotController.test("label"),
      helpText: this.hasSlotController.test("help-text"),
      tooltip: this.hasSlotController.test("tooltip")
    };
    const hasLabel = this.label ? true : !!slots["label"];
    const hasHelpText = this.helpText ? true : !!slots["helpText"];
    const hasTooltip = !!slots["tooltip"];
    const hasValue = this.value !== null && String(this.value).length > 0 || this.range && this.rangeStart !== null || this.rangeEnd !== null;
    const isFloatingLabelActive = this.floatingLabel && hasLabel && (this.hasFocus || this.open || hasValue) && !this.disabled && !this.visuallyDisabled;
    const iconColor = this.disabled || this.visuallyDisabled ? "text-neutral-500" : "icon-color";
    const iconMarginLeft = { sm: "ml-1", md: "ml-2", lg: "ml-2" }[this.size];
    const iconSize = { sm: "text-base", md: "text-lg", lg: "text-xl" }[this.size];
    const inputState = this.disabled ? "disabled" : this.visuallyDisabled && !this.hasFocus ? "visuallyDisabled" : this.readonly ? "readonly" : this.hasFocus && this.showInvalidStyle ? "activeInvalid" : this.hasFocus && this.styleOnValid && this.showValidStyle ? "activeValid" : this.hasFocus || this.open ? "active" : this.showInvalidStyle ? "invalid" : this.styleOnValid && this.showValidStyle ? "valid" : "default";
    const borderColor = {
      disabled: "border-neutral-500",
      visuallyDisabled: "border-neutral-500",
      readonly: "border-neutral-800",
      activeInvalid: "border-error border-2",
      activeValid: "border-success border-2",
      active: "border-primary border-2",
      invalid: "border-error",
      valid: "border-success",
      default: "form-control-color-border"
    }[inputState];
    const textSize = this.size === "sm" ? "text-sm" : "text-base";
    return html`<div part="form-control" class="${cx(
      "min-w-[284px]",
      this.open && "z-50",
      (this.disabled || this.visuallyDisabled) && "cursor-not-allowed"
    )}">${hasLabel && !this.floatingLabel || hasTooltip ? html`<div class="flex items-center gap-1 mb-2"><label part="form-control-label" id="label" class="${cx(
      hasLabel ? "inline-block" : "hidden",
      this.visuallyDisabled || this.disabled ? "text-neutral-500" : "form-control-color-text",
      textSize
    )}" for="input" aria-hidden="${hasLabel ? "false" : "true"}"><slot name="label">${this.label}</slot></label> ${slots["tooltip"] ? html`<slot name="tooltip"></slot>` : ""}</div>` : null}<div part="form-control-input" class="${cx(
      "relative w-full",
      this.disabled && "pointer-events-none",
      this.visuallyDisabled && "cursor-not-allowed"
    )}">${hasLabel && this.floatingLabel ? html`<label id="label" part="form-control-floating-label" class="${cx(
      "absolute left-4 z-20 pointer-events-none transition-all duration-200 form-control--filled__floating-label-color-text",
      !isFloatingLabelActive ? "top-1/2 -translate-y-1/2 form-control-color-text" : this.size === "lg" ? "top-2 text-xs" : "top-1 text-xs",
      isFloatingLabelActive && "mt-1"
    )}" for="input"><span class="${cx(
      "leading-none",
      (this.visuallyDisabled || this.disabled) && "text-neutral-500",
      isFloatingLabelActive && !this.visuallyDisabled && !this.disabled && "form-control--filled__floating-label-color-text"
    )}">${this.label}</span></label>` : null}<div part="border" class="${cx(
      "absolute top-0 w-full h-full pointer-events-none border form-control-border-radius z-10 transition-[border] duration-medium ease-in-out",
      borderColor,
      this.open && (((_a = this.currentPlacement) == null ? void 0 : _a.startsWith("bottom")) ? this.open && this.alignment === "left" ? "rounded-bl-none" : "rounded-br-none" : this.open && this.alignment === "left" ? "rounded-tl-none" : "rounded-tr-none")
    )}"></div><sd-6-22-0-popup @sd-current-placement="${this.handleCurrentPlacement}" class="${cx(
      "inline-flex relative w-full",
      ((_b = this.currentPlacement) == null ? void 0 : _b.startsWith("bottom")) ? "origin-top" : "origin-bottom"
    )}" placement="${this.alignment === "left" ? `${this.placement}-start` : `${this.placement}-end`}" flip shift auto-size="vertical" auto-size-padding="10" exportparts="popup:popup__content,"><div part="base" class="${cx(
      "px-4 flex flex-row items-center rounded-default transition-colors ease-in-out duration-medium hover:duration-fast w-full",
      !this.disabled && !this.readonly && !this.visuallyDisabled ? "hover:[@media(hover:hover)]:form-control--hover-color-background" : "",
      this.readonly ? "form-control--read-only-color-background" : "bg-white",
      inputState === "disabled" || inputState === "visuallyDisabled" ? "text-neutral-500" : "text-black",
      inputState === "invalid" && "form-control--invalid-color-background",
      inputState === "active" && "shadow"
    )}" slot="anchor"><input id="input" type="text" role="combobox" aria-expanded="${this.open ? "true" : "false"}" aria-haspopup="dialog" aria-controls="calendar-grid" aria-describedby="${hasHelpText ? "help-text" : void 0}" aria-invalid="${this.showInvalidStyle ? "true" : "false"}" aria-label="${this.range ? "Select date range" : "Select a date"}" class="${cx(
      "min-w-0 grow focus:outline-none bg-transparent hover:cursor-pointer text-black",
      this.visuallyDisabled || this.disabled ? "placeholder:text-neutral-500 cursor-not-allowed" : "placeholder:text-neutral-700",
      { sm: "h-8", md: "h-10", lg: "h-12" }[this.size],
      textSize,
      this.floatingLabel && "mt-4"
    )}" autocomplete="off" spellcheck="false" placeholder="${!this.floatingLabel || isFloatingLabelActive ? this.placeholder || this.localize.term(this.range ? "dateRangePlaceholder" : "datePlaceholder") : ""}" ?disabled="${this.disabled}" ?required="${this.required}" ?readonly="${this.readonly || this.visuallyDisabled}" @input="${this.handleInput}" @click="${this.handleMouseDown}" @keydown="${this.handleInputKeyDown}" @focus="${this.handleFocus}" @blur="${this.handleInputBlur}" @invalid="${this.handleInvalid}"> ${this.showInvalidStyle ? html`<sd-6-22-0-icon part="invalid-icon" class="${cx("text-error", iconMarginLeft, iconSize)}" library="_internal" name="risk"></sd-6-22-0-icon>` : ""} ${this.showValidStyle && this.styleOnValid ? html`<sd-6-22-0-icon class="${cx("text-success shrink-0", iconMarginLeft, iconSize)}" library="_internal" name="confirm-circle" part="valid-icon"></sd-6-22-0-icon>` : ""}<sd-6-22-0-icon class="${cx(iconColor, iconMarginLeft, iconSize, "hover:cursor-pointer")}" library="_internal" name="calendar" @click="${this.show}"></sd-6-22-0-icon></div>${this.renderCalendar()}</sd-6-22-0-popup></div><slot name="help-text" part="form-control-help-text" id="help-text" class="${cx(
      "text-sm mt-1",
      hasHelpText ? "block" : "hidden",
      this.visuallyDisabled || this.disabled ? "text-neutral-500" : "text-neutral-700"
    )}" aria-hidden="${!hasHelpText}">${this.helpText}</slot></div>${this.formControlController.renderInvalidMessage(this.size)}`;
  }
};
SdDatepicker.styles = [
  ...SolidElement.styles,
  css`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */@layer theme,base,components,utilities;
:host{position:relative;display:inline-block;width:100%;--tw-outline-style:none;outline-style:none}:host([required]) #label::after{content:' *'}:host([visually-disabled]) input{caret-color:transparent}.today:hover{border-color:rgba(var(--sd-datepicker__date-item--hover--default-color-border,rgba(var(--sd-color-primary-500))))}.in-range,.today{color:rgba(var(--sd-datepicker__date-item--current-color-text,rgba(var(--sd-color-primary))))}.icon-color{color:rgb(var(--sd-color-icon-fill-primary))}.month-label{color:rgb(var(--sd-color-border-primary))!important}`
];
__decorateClass([
  property({ type: String, reflect: true })
], SdDatepicker.prototype, "locale", 2);
__decorateClass([
  property({ type: String, converter: isoDateConverter, reflect: true })
], SdDatepicker.prototype, "value", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], SdDatepicker.prototype, "range", 2);
__decorateClass([
  property({ attribute: "range-start", converter: isoDateConverter, reflect: true })
], SdDatepicker.prototype, "rangeStart", 2);
__decorateClass([
  property({ attribute: "range-end", converter: isoDateConverter, reflect: true })
], SdDatepicker.prototype, "rangeEnd", 2);
__decorateClass([
  property({ type: Boolean })
], SdDatepicker.prototype, "allowSameDayRange", 2);
__decorateClass([
  property({ type: String, converter: isoDateConverter, reflect: true })
], SdDatepicker.prototype, "min", 2);
__decorateClass([
  property({ type: String, converter: isoDateConverter, reflect: true })
], SdDatepicker.prototype, "max", 2);
__decorateClass([
  property({ attribute: "view-month", converter: viewMonthConverter })
], SdDatepicker.prototype, "viewMonth", 2);
__decorateClass([
  property({ type: Number })
], SdDatepicker.prototype, "firstDayOfWeek", 2);
__decorateClass([
  property({ type: Boolean, reflect: true, attribute: "disabled-weekends" })
], SdDatepicker.prototype, "disabledWeekends", 2);
__decorateClass([
  property({ attribute: "disabled-dates", converter: disabledDatesConverter })
], SdDatepicker.prototype, "disabledDates", 2);
__decorateClass([
  property({ attribute: false })
], SdDatepicker.prototype, "isDateDisabled", 2);
__decorateClass([
  property({ type: String, reflect: true })
], SdDatepicker.prototype, "size", 2);
__decorateClass([
  property({ type: String })
], SdDatepicker.prototype, "alignment", 2);
__decorateClass([
  property({ type: String, reflect: true })
], SdDatepicker.prototype, "label", 2);
__decorateClass([
  property({ type: String, attribute: "help-text", reflect: true })
], SdDatepicker.prototype, "helpText", 2);
__decorateClass([
  property({ attribute: "floating-label", type: Boolean, reflect: true })
], SdDatepicker.prototype, "floatingLabel", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], SdDatepicker.prototype, "disabled", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], SdDatepicker.prototype, "required", 2);
__decorateClass([
  property({ type: Boolean, attribute: "visually-disabled" })
], SdDatepicker.prototype, "visuallyDisabled", 2);
__decorateClass([
  property({ type: Boolean, reflect: true, attribute: "style-on-valid" })
], SdDatepicker.prototype, "styleOnValid", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], SdDatepicker.prototype, "readonly", 2);
__decorateClass([
  property({ type: String, reflect: true })
], SdDatepicker.prototype, "placement", 2);
__decorateClass([
  property({ type: String, reflect: true })
], SdDatepicker.prototype, "placeholder", 2);
__decorateClass([
  property({ reflect: true })
], SdDatepicker.prototype, "name", 2);
__decorateClass([
  property({ type: String, reflect: true })
], SdDatepicker.prototype, "form", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "open", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "focusedDate", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "today", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "disabledDatesSet", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "previewEnd", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "statusNavText", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "statusSelectText", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "hasFocus", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "showValidStyle", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "showInvalidStyle", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "currentPlacement", 2);
__decorateClass([
  state()
], SdDatepicker.prototype, "inputValue", 2);
__decorateClass([
  query("sd-6-22-0-popup")
], SdDatepicker.prototype, "popup", 2);
__decorateClass([
  query("#invalid-message")
], SdDatepicker.prototype, "invalidMessage", 2);
__decorateClass([
  query("#input")
], SdDatepicker.prototype, "input", 2);
__decorateClass([
  watch("open", { waitUntilFirstUpdate: true })
], SdDatepicker.prototype, "handleOpenChange", 1);
__decorateClass([
  watch("locale")
], SdDatepicker.prototype, "handleLocaleChange", 1);
__decorateClass([
  watch("viewMonth")
], SdDatepicker.prototype, "handleViewMonthChange", 1);
__decorateClass([
  watch("disabledDates")
], SdDatepicker.prototype, "handleDisabledDatesChange", 1);
__decorateClass([
  watch("value")
], SdDatepicker.prototype, "handleValueChange", 1);
__decorateClass([
  watch("rangeStart"),
  watch("rangeEnd")
], SdDatepicker.prototype, "handleRangeChange", 1);
__decorateClass([
  watch(["disabled", "visually-disabled"], { waitUntilFirstUpdate: true })
], SdDatepicker.prototype, "handleDisabledChange", 1);
__decorateClass([
  watch(["size", "floatingLabel"])
], SdDatepicker.prototype, "handleSizeChange", 1);
SdDatepicker = __decorateClass([
  customElement("sd-6-22-0-datepicker")
], SdDatepicker);

export {
  SdDatepicker
};
