{"version":3,"file":"presets-BUMiolmt.cjs","sources":["../src/utils/dom.ts","../src/core/DragController.ts","../src/core/EventManager.ts","../src/core/InteractionController.ts","../src/styles/index.ts","../src/constants/formats.ts","../src/views/BaseView.ts","../src/views/ViewRegistry.ts","../src/engines/MonthEngine.ts","../src/renderers/MonthRenderer.ts","../src/views/MonthView.ts","../src/engines/TimeEngine.ts","../src/renderers/TimeRenderer.ts","../src/views/TimeView.ts","../src/core/Calendar.ts","../src/presets.ts"],"sourcesContent":["/**\n * DOM utility functions for building calendar UI\n */\n\n/**\n * Create an HTML element with optional class and attributes\n *\n * @param tag - HTML tag name\n * @param className - CSS class string\n * @param attributes - Additional attributes to set\n * @returns Created element\n */\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\n  tag: K,\n  className?: string,\n  attributes?: Record<string, string>\n): HTMLElementTagNameMap[K] {\n  const el = document.createElement(tag);\n\n  if (className) {\n    el.className = className;\n  }\n\n  if (attributes) {\n    for (const [key, value] of Object.entries(attributes)) {\n      el.setAttribute(key, value);\n    }\n  }\n\n  return el;\n}\n\n/**\n * Set multiple styles on an element\n *\n * @param el - Target element\n * @param styles - Style properties to set\n */\nexport function setStyles(\n  el: HTMLElement,\n  styles: Partial<CSSStyleDeclaration>\n): void {\n  Object.assign(el.style, styles);\n}\n\n/**\n * Clear all child elements from an element\n *\n * @param el - Target element\n */\nexport function clearElement(el: HTMLElement): void {\n  el.innerHTML = '';\n}\n\n/**\n * Append multiple children to a parent element\n *\n * @param parent - Parent element\n * @param children - Children to append\n */\nexport function appendChildren(\n  parent: HTMLElement,\n  children: HTMLElement[]\n): void {\n  for (const child of children) {\n    parent.appendChild(child);\n  }\n}\n\n/**\n * Query selector with type safety\n *\n * @param selector - CSS selector\n * @param parent - Parent element to search within\n * @returns Found element or null\n */\nexport function querySelector<T extends HTMLElement>(\n  selector: string,\n  parent: HTMLElement | Document = document\n): T | null {\n  return parent.querySelector<T>(selector);\n}\n\n/**\n * Query all matching elements with type safety\n *\n * @param selector - CSS selector\n * @param parent - Parent element to search within\n * @returns NodeList of found elements\n */\nexport function querySelectorAll<T extends HTMLElement>(\n  selector: string,\n  parent: HTMLElement | Document = document\n): NodeListOf<T> {\n  return parent.querySelectorAll<T>(selector);\n}\n\n/**\n * Add event listener with automatic cleanup\n *\n * @param el - Target element\n * @param event - Event name\n * @param handler - Event handler\n * @param options - Event listener options\n * @returns Cleanup function\n */\nexport function addListener<K extends keyof HTMLElementEventMap>(\n  el: HTMLElement | Document,\n  event: K,\n  handler: (e: HTMLElementEventMap[K]) => void,\n  options?: boolean | AddEventListenerOptions\n): () => void {\n  el.addEventListener(event, handler as EventListener, options);\n  return () => el.removeEventListener(event, handler as EventListener, options);\n}\n\n/**\n * Get element's position relative to another element\n *\n * @param el - Target element\n * @param relativeTo - Reference element (default: document.body)\n * @returns Position object with top, left, width, height\n */\nexport function getRelativePosition(\n  el: HTMLElement,\n  relativeTo: HTMLElement = document.body\n): { top: number; left: number; width: number; height: number } {\n  const elRect = el.getBoundingClientRect();\n  const refRect = relativeTo.getBoundingClientRect();\n\n  return {\n    top: elRect.top - refRect.top,\n    left: elRect.left - refRect.left,\n    width: elRect.width,\n    height: elRect.height\n  };\n}\n","/**\n * Drag and drop controller for calendar events\n */\nimport type {\n  DateAdapter,\n  CalendarEvent,\n  DraggableConfig,\n  DragState,\n  DragMode,\n  DateFormatConfig,\n} from \"../types\";\nimport { createElement, setStyles, querySelectorAll } from \"../utils/dom\";\n\n/**\n * Handles drag and drop interactions for calendar events\n */\nexport class DragController<T> {\n  private state: DragState<T> | null = null;\n  private proxyElement: HTMLElement | null = null;\n  private boundOnMove: (e: MouseEvent) => void;\n  private boundOnUp: (e: MouseEvent) => void;\n\n  /**\n   * Safely compute cell width even when offsetWidth is 0 (e.g., JSDOM).\n   */\n  private resolveCellWidth(\n    container: HTMLElement,\n    columnCount: number,\n  ): number {\n    const rectWidth = container.getBoundingClientRect().width;\n    const computedWidth =\n      parseFloat(getComputedStyle(container).width || \"0\") || 0;\n    const baseWidth =\n      container.offsetWidth || rectWidth || computedWidth || columnCount || 1;\n    return baseWidth / Math.max(columnCount, 1);\n  }\n\n  /**\n   * Get the column count from a container's --tg-allday-columns CSS variable.\n   * Uses getComputedStyle to read both inline and stylesheet values (DRY helper).\n   */\n  private getAllDayColumnCount(container: HTMLElement): number {\n    const columnsVar = getComputedStyle(container).getPropertyValue(\n      \"--tg-allday-columns\",\n    );\n    return parseInt(columnsVar, 10) || 7;\n  }\n\n  constructor(\n    private adapter: DateAdapter<T>,\n    private config: Required<DraggableConfig>,\n    private onDrop: (\n      event: CalendarEvent,\n      newStart: Date,\n      newEnd: Date,\n    ) => void,\n    private onResize: (\n      event: CalendarEvent,\n      newStart: Date,\n      newEnd: Date,\n    ) => void,\n    private cellHeight: number = 60,\n    private dateFormats: Required<DateFormatConfig>,\n  ) {\n    this.boundOnMove = this.onMove.bind(this);\n    this.boundOnUp = this.onUp.bind(this);\n  }\n\n  /**\n   * Initialize drag for a month view event\n   */\n  initMonthDrag(\n    el: HTMLElement,\n    event: CalendarEvent,\n    renderCallback: () => void,\n  ): void {\n    if (!this.config.enabled) return;\n\n    el.onmousedown = (e: MouseEvent) => {\n      if (e.button !== 0) return;\n      // Runtime check: support dynamic disable\n      if (!this.config.enabled) return;\n      e.stopPropagation();\n\n      // Support both month view rows and all-day section\n      const row = el.closest(\".tg-month-row\") as HTMLElement | null;\n      const allDayContainer = el.closest(\n        \".tg-allday-events-container\",\n      ) as HTMLElement | null;\n\n      let cellW: number;\n      let columnCount: number;\n\n      if (row) {\n        // Month view\n        columnCount = 7;\n        cellW = this.resolveCellWidth(row, columnCount);\n      } else if (allDayContainer) {\n        // All-day section in time view - use getComputedStyle for stylesheet values\n        columnCount = this.getAllDayColumnCount(allDayContainer);\n        cellW = this.resolveCellWidth(allDayContainer, columnCount);\n      } else {\n        return;\n      }\n\n      let mode: DragMode = \"move\";\n\n      const target = e.target as HTMLElement;\n      if (target.classList.contains(\"tg-left\")) mode = \"resize-left\";\n      if (target.classList.contains(\"tg-right\")) mode = \"resize-right\";\n\n      // Calculate click offset in days within the event's span\n      // For multi-day events, this determines which day the user clicked on\n      const startDate = this.adapter.parse(event.start);\n      const endDate = this.adapter.parse(event.end);\n      const eventDurationDays =\n        this.adapter.diff(\n          this.adapter.startOf(endDate, \"day\"),\n          this.adapter.startOf(startDate, \"day\"),\n          \"day\",\n        ) + 1;\n\n      // Calculate click position relative to the event element\n      const elRect = el.getBoundingClientRect();\n      const clickXInEvent = e.clientX - elRect.left;\n      const eventWidth = elRect.width || cellW; // fallback to cellW if width is 0\n\n      // Calculate which day within the event was clicked\n      // For single-day events, this will always be 0\n      const clickOffsetDays = Math.max(\n        0,\n        Math.min(\n          eventDurationDays - 1,\n          Math.floor((clickXInEvent / eventWidth) * eventDurationDays),\n        ),\n      );\n\n      this.startDrag({\n        type: \"month\",\n        mode,\n        event,\n        startX: e.clientX,\n        startY: e.clientY,\n        startDate,\n        endDate,\n        cellW,\n        renderCallback,\n        clickOffsetDays,\n      });\n    };\n  }\n\n  /**\n   * Initialize drag for a time view event\n   */\n  initTimeDrag(\n    el: HTMLElement,\n    event: CalendarEvent,\n    renderCallback: () => void,\n  ): void {\n    if (!this.config.enabled) return;\n\n    el.onmousedown = (e: MouseEvent) => {\n      if (e.button !== 0) return;\n      // Runtime check: support dynamic disable\n      if (!this.config.enabled) return;\n      e.stopPropagation();\n\n      const col = el.closest(\".tg-day-column\") as HTMLElement | null;\n      if (!col) return;\n\n      const colRect = col.getBoundingClientRect();\n      let mode: DragMode = \"move\";\n\n      const target = e.target as HTMLElement;\n      if (target.classList.contains(\"tg-resize-v\")) {\n        mode = target.classList.contains(\"tg-top\")\n          ? \"resize-top\"\n          : \"resize-bottom\";\n      }\n\n      const startDate = this.adapter.parse(event.start);\n      const endDate = this.adapter.parse(event.end);\n\n      this.startDrag({\n        type: \"time\",\n        mode,\n        event,\n        startX: e.clientX,\n        startY: e.clientY,\n        startDate,\n        endDate,\n        colW: colRect.width,\n        renderCallback,\n        origStartMin:\n          this.adapter.hour(startDate) * 60 + this.adapter.minute(startDate),\n        origDuration: this.adapter.diff(endDate, startDate, \"minute\"),\n      });\n    };\n  }\n\n  /**\n   * Update cell height for time calculations\n   */\n  setCellHeight(height: number): void {\n    this.cellHeight = height;\n  }\n\n  /**\n   * Check if currently dragging an event\n   * Used by InteractionController to prevent conflicts with range selection\n   */\n  isDragging(): boolean {\n    return this.state !== null;\n  }\n\n  /**\n   * Cleanup resources\n   */\n  destroy(): void {\n    document.removeEventListener(\"mousemove\", this.boundOnMove);\n    document.removeEventListener(\"mouseup\", this.boundOnUp);\n    this.removeProxy();\n    this.state = null;\n  }\n\n  // ==========================================================================\n  // Private Methods\n  // ==========================================================================\n\n  private startDrag(stateData: DragState<T>): void {\n    this.state = stateData;\n    document.body.style.cursor = \"grabbing\";\n\n    // Mark source element\n    querySelectorAll(`[data-eid=\"${stateData.event.id}\"]`).forEach((el) => {\n      el.classList.add(\"tg-is-dragging-source\");\n    });\n\n    // Create proxy element\n    this.createProxy(stateData.event);\n\n    document.addEventListener(\"mousemove\", this.boundOnMove);\n    document.addEventListener(\"mouseup\", this.boundOnUp);\n  }\n\n  private createProxy(event: CalendarEvent): void {\n    // Check for existing proxy\n    this.proxyElement = document.getElementById(\n      \"tg-drag-proxy\",\n    ) as HTMLElement | null;\n\n    if (!this.proxyElement) {\n      this.proxyElement = createElement(\"div\", undefined, {\n        id: \"tg-drag-proxy\",\n      });\n      document.body.appendChild(this.proxyElement);\n    }\n\n    this.proxyElement.textContent = event.title;\n    setStyles(this.proxyElement, {\n      backgroundColor: event.color || \"#3b82f6\",\n      color: \"white\",\n      padding: \"4px 8px\",\n      fontSize: \"12px\",\n    });\n  }\n\n  private removeProxy(): void {\n    if (this.proxyElement) {\n      this.proxyElement.style.visibility = \"hidden\";\n    }\n  }\n\n  private onMove(e: MouseEvent): void {\n    if (!this.state) return;\n\n    // Update proxy position\n    if (this.proxyElement) {\n      setStyles(this.proxyElement, {\n        visibility: \"visible\",\n        left: `${e.clientX + 10}px`,\n        top: `${e.clientY + 10}px`,\n        transform: \"none\",\n      });\n    }\n\n    if (this.state.type === \"month\") {\n      this.handleMonthMove(e);\n    } else {\n      this.handleTimeMove(e);\n    }\n  }\n\n  private handleMonthMove(e: MouseEvent): void {\n    const s = this.state!;\n\n    // Support both month view rows and all-day section\n    const row = document\n      .elementFromPoint(e.clientX, e.clientY)\n      ?.closest(\".tg-month-row\") as HTMLElement | null;\n    const allDayContainer = document\n      .elementFromPoint(e.clientX, e.clientY)\n      ?.closest(\".tg-allday-events-container\") as HTMLElement | null;\n\n    let hoverDate: T;\n\n    if (row?.dataset[\"date\"]) {\n      // Month view row - recalculate cellW from current container width\n      const rowStart = this.adapter.parse(row.dataset[\"date\"]);\n      const rowRect = row.getBoundingClientRect();\n      const currentCellW = rowRect.width / 7;\n      const cellIdx = Math.floor(\n        (e.clientX - rowRect.left) / (currentCellW || 1),\n      );\n      hoverDate = this.adapter.add(\n        rowStart,\n        Math.max(0, Math.min(6, cellIdx)),\n        \"day\",\n      );\n    } else if (allDayContainer) {\n      // All-day section - find which column we're over\n      const rect = allDayContainer.getBoundingClientRect();\n      // Use getComputedStyle helper for stylesheet-defined values (DRY)\n      const columnCount = this.getAllDayColumnCount(allDayContainer);\n      const colWidth = rect.width / columnCount;\n      const colIdx = Math.floor((e.clientX - rect.left) / colWidth);\n\n      // Scope lookup to the current calendar container (SRP - avoid cross-calendar coupling)\n      const calendarContainer = allDayContainer.closest(\n        \".tg-time-view, .tg-calendar\",\n      );\n      if (!calendarContainer) return;\n\n      // Get base date from the first day column within THIS calendar instance\n      const dayColumn = calendarContainer.querySelector(\n        \".tg-day-column[data-date]\",\n      ) as HTMLElement | null;\n      if (dayColumn?.dataset[\"date\"]) {\n        const baseDate = this.adapter.parse(dayColumn.dataset[\"date\"]);\n        hoverDate = this.adapter.add(\n          baseDate,\n          Math.max(0, Math.min(columnCount - 1, colIdx)),\n          \"day\",\n        );\n      } else {\n        return;\n      }\n    } else {\n      return;\n    }\n\n    let newStart = s.startDate;\n    let newEnd = s.endDate;\n\n    if (s.mode === \"move\") {\n      // Calculate duration in calendar days (date part only, ignoring time)\n      // This correctly handles cross-midnight events like 22:00 -> 02:00 next day\n      const startDateOnly = this.adapter.startOf(s.startDate, \"day\");\n      const endDateOnly = this.adapter.startOf(s.endDate, \"day\");\n      const duration = this.adapter.diff(endDateOnly, startDateOnly, \"day\");\n\n      // Adjust for click offset: if user clicked in the middle of a multi-day event,\n      // the new start should account for that offset to keep the event under the cursor\n      const clickOffset = s.clickOffsetDays || 0;\n      const adjustedHoverDate = this.adapter.add(\n        hoverDate,\n        -clickOffset,\n        \"day\",\n      );\n\n      // DEBUG: Log drag calculation details\n      console.log(\"[DragController] handleMonthMove - move mode:\", {\n        eventTitle: s.event.title,\n        originalStart: this.adapter.format(s.startDate, \"yyyy-MM-dd HH:mm\"),\n        originalEnd: this.adapter.format(s.endDate, \"yyyy-MM-dd HH:mm\"),\n        startDateOnly: this.adapter.format(startDateOnly, \"yyyy-MM-dd\"),\n        endDateOnly: this.adapter.format(endDateOnly, \"yyyy-MM-dd\"),\n        duration,\n        clickOffset,\n        hoverDate: this.adapter.format(hoverDate, \"yyyy-MM-dd HH:mm\"),\n        adjustedHoverDate: this.adapter.format(\n          adjustedHoverDate,\n          \"yyyy-MM-dd HH:mm\",\n        ),\n        dateOnly: this.config.dateOnly,\n      });\n\n      if (this.config.dateOnly) {\n        // Date-only mode: calculate date difference and preserve time\n        const daysDiff = this.adapter.diff(\n          adjustedHoverDate,\n          startDateOnly,\n          \"day\",\n        );\n        newStart = this.adapter.add(s.startDate, daysDiff, \"day\");\n        newEnd = this.adapter.add(s.endDate, daysDiff, \"day\");\n      } else {\n        // Normal mode: preserve original time while adjusting date\n        const originalStartHour = this.adapter.hour(s.startDate);\n        const originalStartMinute = this.adapter.minute(s.startDate);\n        const originalEndHour = this.adapter.hour(s.endDate);\n        const originalEndMinute = this.adapter.minute(s.endDate);\n\n        newStart = this.adapter.setMinute(\n          this.adapter.setHour(adjustedHoverDate, originalStartHour),\n          originalStartMinute,\n        );\n        newEnd = this.adapter.setMinute(\n          this.adapter.setHour(\n            this.adapter.add(adjustedHoverDate, duration, \"day\"),\n            originalEndHour,\n          ),\n          originalEndMinute,\n        );\n      }\n\n      // DEBUG: Log calculated new dates\n      console.log(\n        \"[DragController] handleMonthMove - calculated newStart/newEnd:\",\n        {\n          newStart: this.adapter.format(newStart, \"yyyy-MM-dd HH:mm\"),\n          newEnd: this.adapter.format(newEnd, \"yyyy-MM-dd HH:mm\"),\n        },\n      );\n    } else if (s.mode === \"resize-right\") {\n      // Resize right: keep start unchanged, adjust end\n      newStart = s.startDate;\n      if (this.config.dateOnly) {\n        // Preserve time when resizing in date-only mode\n        const originalHour = this.adapter.hour(s.endDate);\n        const originalMinute = this.adapter.minute(s.endDate);\n        newEnd = this.adapter.setMinute(\n          this.adapter.setHour(hoverDate, originalHour),\n          originalMinute,\n        );\n\n        // Handle cross-midnight events: if end time is before start time on same day,\n        // set end to end of day (23:59)\n        if (\n          this.adapter.isSame(newEnd, newStart, \"day\") &&\n          this.adapter.isBefore(newEnd, newStart)\n        ) {\n          newEnd = this.adapter.setMinute(\n            this.adapter.setHour(hoverDate, 23),\n            59,\n          );\n        }\n      } else {\n        newEnd = hoverDate;\n      }\n      if (this.adapter.isBefore(newEnd, newStart)) {\n        newEnd = newStart;\n      }\n    } else if (s.mode === \"resize-left\") {\n      // Resize left: keep end unchanged, adjust start\n      newEnd = s.endDate;\n      if (this.config.dateOnly) {\n        // Preserve time when resizing in date-only mode\n        const originalHour = this.adapter.hour(s.startDate);\n        const originalMinute = this.adapter.minute(s.startDate);\n        newStart = this.adapter.setMinute(\n          this.adapter.setHour(hoverDate, originalHour),\n          originalMinute,\n        );\n\n        // Handle cross-midnight events: if start time is after end time on same day,\n        // set start to beginning of day (00:00)\n        if (\n          this.adapter.isSame(newStart, newEnd, \"day\") &&\n          this.adapter.isAfter(newStart, newEnd)\n        ) {\n          newStart = this.adapter.setMinute(\n            this.adapter.setHour(hoverDate, 0),\n            0,\n          );\n        }\n      } else {\n        newStart = hoverDate;\n      }\n      if (this.adapter.isAfter(newStart, newEnd)) {\n        newStart = newEnd;\n      }\n    }\n\n    this.renderMonthGhost(newStart, newEnd);\n    s.tentativeStart = newStart;\n    s.tentativeEnd = newEnd;\n  }\n\n  private handleTimeMove(e: MouseEvent): void {\n    const s = this.state!;\n    const col = document\n      .elementFromPoint(e.clientX, e.clientY)\n      ?.closest(\".tg-day-column\") as HTMLElement | null;\n\n    if (!col?.dataset[\"date\"]) return;\n\n    const newDateBase = this.adapter.parse(col.dataset[\"date\"]);\n    const rect = col.getBoundingClientRect();\n    const relY = e.clientY - rect.top;\n\n    const rawMins = (relY / this.cellHeight) * 60;\n    const snapMinutes = this.config.dateOnly\n      ? 1440 // Date-only mode: snap to full day (24 hours)\n      : this.config.snapMinutes || 15;\n    const snappedMins = Math.max(\n      0,\n      Math.min(1440, Math.round(rawMins / snapMinutes) * snapMinutes),\n    );\n\n    let newStart: T;\n    let newEnd: T;\n\n    if (s.mode === \"move\") {\n      if (this.config.dateOnly) {\n        // Date-only mode: only adjust date, keep original time\n        const daysDiff = this.adapter.diff(newDateBase, s.startDate, \"day\");\n        newStart = this.adapter.add(s.startDate, daysDiff, \"day\");\n        newEnd = this.adapter.add(s.endDate, daysDiff, \"day\");\n      } else {\n        // Normal mode: allow full time adjustment\n        newStart = this.adapter.setMinute(\n          this.adapter.setHour(newDateBase, 0),\n          snappedMins,\n        );\n        newEnd = this.adapter.add(newStart, s.origDuration || 60, \"minute\");\n      }\n    } else if (s.mode === \"resize-top\") {\n      // Resize top: adjust start time, keep end time unchanged\n      newEnd = s.endDate;\n\n      if (this.config.dateOnly) {\n        // Date-only mode: only adjust date, keep original time\n        const daysDiff = this.adapter.diff(newDateBase, s.startDate, \"day\");\n        newStart = this.adapter.add(s.startDate, daysDiff, \"day\");\n      } else {\n        if (this.adapter.isSame(newDateBase, s.endDate, \"day\")) {\n          // Same day: ensure start time is before end time with minimum 15 minutes\n          const endMin =\n            this.adapter.hour(s.endDate) * 60 + this.adapter.minute(s.endDate);\n          const startMins = Math.min(endMin - 15, snappedMins);\n          newStart = this.adapter.setMinute(\n            this.adapter.setHour(newDateBase, 0),\n            startMins,\n          );\n        } else {\n          // Different day: allow any time\n          newStart = this.adapter.setMinute(\n            this.adapter.setHour(newDateBase, 0),\n            snappedMins,\n          );\n        }\n      }\n\n      // Clamp newStart to not exceed newEnd (LSP/time invariant: start <= end)\n      // Prevents inverted dates when dragging top handle past end time\n      if (this.adapter.isAfter(newStart, newEnd)) {\n        newStart = newEnd;\n      }\n    } else {\n      // resize-bottom\n      if (this.config.dateOnly) {\n        // In date-only mode, resizing only changes the date part\n        newStart = s.startDate;\n        const daysDiff = this.adapter.diff(newDateBase, s.endDate, \"day\");\n        newEnd = this.adapter.add(s.endDate, daysDiff, \"day\");\n      } else {\n        newStart = s.startDate;\n\n        if (this.adapter.isSame(newDateBase, s.startDate, \"day\")) {\n          const endMins = Math.max((s.origStartMin || 0) + 15, snappedMins);\n          newEnd = this.adapter.setMinute(\n            this.adapter.setHour(newDateBase, 0),\n            endMins,\n          );\n        } else {\n          newEnd = s.endDate;\n        }\n      }\n    }\n\n    this.renderTimeGhost(newStart, newEnd);\n    s.tentativeStart = newStart;\n    s.tentativeEnd = newEnd;\n  }\n\n  private renderMonthGhost(start: T, end: T): void {\n    // Remove existing ghosts\n    querySelectorAll(\".tg-ghost-event\").forEach((el) => el.remove());\n\n    // Try month view rows first\n    const rows = querySelectorAll<HTMLElement>(\".tg-month-row\");\n\n    if (rows.length > 0) {\n      // Month view ghost rendering - use dynamic column width calculation\n      const columnCount = 7;\n      const colWidth = 100 / columnCount;\n\n      for (const row of rows) {\n        if (!row.dataset[\"date\"]) continue;\n\n        const rStart = this.adapter.parse(row.dataset[\"date\"]);\n        const rEnd = this.adapter.add(rStart, columnCount - 1, \"day\");\n\n        // Check if event overlaps this row\n        if (\n          !this.adapter.isBefore(end, rStart) &&\n          !this.adapter.isAfter(start, rEnd)\n        ) {\n          const dStart = this.adapter.isBefore(start, rStart) ? rStart : start;\n          const dEnd = this.adapter.isAfter(end, rEnd) ? rEnd : end;\n\n          const startIdx = this.adapter.diff(dStart, rStart, \"day\");\n          const span = this.adapter.diff(dEnd, dStart, \"day\") + 1;\n\n          const left = startIdx * colWidth;\n          const width = span * colWidth;\n          const ghostEndIdx = startIdx + span - 1;\n\n          // Calculate top position based on events that overlap with ghost's column range\n          // Only consider events whose columns intersect with the ghost's columns\n          const eventBars = row.querySelectorAll<HTMLElement>(\".tg-event-bar\");\n          let maxTop = 26; // Base offset for date numbers\n          for (const bar of eventBars) {\n            // Parse the bar's left percentage to determine its start column\n            const barLeftMatch = bar.style.left.match(/calc\\(\\s*([\\d.]+)%/);\n            const barWidthMatch = bar.style.width.match(/calc\\(\\s*([\\d.]+)%/);\n            if (!barLeftMatch?.[1] || !barWidthMatch?.[1]) continue;\n\n            const barLeftPct = parseFloat(barLeftMatch[1]);\n            const barWidthPct = parseFloat(barWidthMatch[1]);\n            const barStartIdx = Math.round(barLeftPct / colWidth);\n            const barSpan = Math.round(barWidthPct / colWidth);\n            const barEndIdx = barStartIdx + barSpan - 1;\n\n            // Check if this event overlaps with the ghost's column range\n            if (barStartIdx <= ghostEndIdx && barEndIdx >= startIdx) {\n              const barTop = parseFloat(bar.style.top) || 0;\n              const barHeight = bar.offsetHeight || 26;\n              maxTop = Math.max(maxTop, barTop + barHeight);\n            }\n          }\n\n          const ghost = createElement(\"div\", \"tg-ghost-event\");\n          setStyles(ghost, {\n            left: `calc(${left}% + 2px)`,\n            width: `calc(${width}% - 4px)`,\n            top: `${maxTop + 2}px`,\n            height: \"26px\",\n          });\n\n          row.appendChild(ghost);\n        }\n      }\n    } else {\n      // All-day section ghost rendering\n      const allDayContainer = document.querySelector(\n        \".tg-allday-events-container\",\n      ) as HTMLElement | null;\n\n      if (!allDayContainer) return;\n\n      // Use getComputedStyle helper for stylesheet-defined values (DRY)\n      const columnCount = this.getAllDayColumnCount(allDayContainer);\n\n      // Scope lookup to the current calendar container (SRP - avoid cross-calendar coupling)\n      const calendarContainer = allDayContainer.closest(\n        \".tg-time-view, .tg-calendar\",\n      );\n      if (!calendarContainer) return;\n\n      // Get day columns within THIS calendar instance\n      const dayColumns = Array.from(\n        calendarContainer.querySelectorAll<HTMLElement>(\n          \".tg-day-column[data-date]\",\n        ),\n      );\n      if (dayColumns.length === 0) return;\n\n      const firstColDateStr = dayColumns[0]?.dataset[\"date\"];\n      const lastColDateStr = dayColumns[dayColumns.length - 1]?.dataset[\"date\"];\n      if (!firstColDateStr || !lastColDateStr) return;\n\n      const firstColDate = this.adapter.parse(firstColDateStr);\n      const lastColDate = this.adapter.parse(lastColDateStr);\n\n      // Check if event overlaps visible range\n      if (\n        !this.adapter.isBefore(end, firstColDate, \"day\") &&\n        !this.adapter.isAfter(start, lastColDate, \"day\")\n      ) {\n        const dStart = this.adapter.isBefore(start, firstColDate)\n          ? firstColDate\n          : start;\n        const dEnd = this.adapter.isAfter(end, lastColDate) ? lastColDate : end;\n\n        const startIdx = this.adapter.diff(dStart, firstColDate, \"day\");\n        const span = this.adapter.diff(dEnd, dStart, \"day\") + 1;\n\n        const colWidth = 100 / columnCount;\n        const left = startIdx * colWidth;\n        const width = span * colWidth;\n        const ghostEndIdx = startIdx + span - 1;\n\n        // Calculate top position based on events that overlap with ghost's column range\n        // Use .tg-allday-event for all-day section (not .tg-event-bar which is for month view)\n        const eventBars =\n          allDayContainer.querySelectorAll<HTMLElement>(\".tg-allday-event\");\n        let maxTop = 0;\n        for (const bar of eventBars) {\n          // Parse the bar's left percentage to determine its start column\n          const barLeftMatch = bar.style.left.match(/calc\\(\\s*([\\d.]+)%/);\n          const barWidthMatch = bar.style.width.match(/calc\\(\\s*([\\d.]+)%/);\n          if (!barLeftMatch?.[1] || !barWidthMatch?.[1]) continue;\n\n          const barLeftPct = parseFloat(barLeftMatch[1]);\n          const barWidthPct = parseFloat(barWidthMatch[1]);\n          const barStartIdx = Math.round(barLeftPct / colWidth);\n          const barSpan = Math.round(barWidthPct / colWidth);\n          const barEndIdx = barStartIdx + barSpan - 1;\n\n          // Check if this event overlaps with the ghost's column range\n          if (barStartIdx <= ghostEndIdx && barEndIdx >= startIdx) {\n            const barTop = parseFloat(bar.style.top) || 0;\n            const barHeight = bar.offsetHeight || 22;\n            maxTop = Math.max(maxTop, barTop + barHeight);\n          }\n        }\n\n        const ghost = createElement(\"div\", \"tg-ghost-event\");\n        setStyles(ghost, {\n          left: `calc(${left}% + 2px)`,\n          width: `calc(${width}% - 4px)`,\n          top: `${maxTop + 4}px`,\n          height: \"22px\",\n        });\n\n        allDayContainer.appendChild(ghost);\n      }\n    }\n  }\n\n  private renderTimeGhost(start: T, end: T): void {\n    // Remove existing ghosts\n    querySelectorAll(\".tg-ghost-event\").forEach((el) => el.remove());\n\n    const dateStr = this.adapter.format(start, this.dateFormats.date);\n    const col = document.querySelector(\n      `.tg-day-column[data-date=\"${dateStr}\"]`,\n    ) as HTMLElement | null;\n\n    if (!col) return;\n\n    const startMin = this.adapter.hour(start) * 60 + this.adapter.minute(start);\n    const top = startMin * (this.cellHeight / 60);\n    const height =\n      this.adapter.diff(end, start, \"minute\") * (this.cellHeight / 60);\n\n    const ghost = createElement(\"div\", \"tg-ghost-event\");\n    setStyles(ghost, {\n      top: `${top}px`,\n      height: `${height}px`,\n      width: \"90%\",\n      left: \"5%\",\n    });\n\n    ghost.textContent = `${this.adapter.format(start, this.dateFormats.time)} - ${this.adapter.format(end, this.dateFormats.time)}`;\n    setStyles(ghost, {\n      color: \"#3b82f6\",\n      fontSize: \"10px\",\n      padding: \"2px\",\n    });\n\n    col.appendChild(ghost);\n  }\n\n  private onUp(_e: MouseEvent): void {\n    if (!this.state) return;\n\n    const s = this.state;\n\n    // Cleanup\n    document.body.style.cursor = \"\";\n    this.removeProxy();\n\n    querySelectorAll(\".tg-ghost-event\").forEach((el) => el.remove());\n    querySelectorAll(\".tg-is-dragging-source\").forEach((el) => {\n      el.classList.remove(\"tg-is-dragging-source\");\n    });\n\n    document.removeEventListener(\"mousemove\", this.boundOnMove);\n    document.removeEventListener(\"mouseup\", this.boundOnUp);\n\n    // Apply changes if we have tentative dates\n    if (s.tentativeStart && s.tentativeEnd) {\n      // Convert adapter dates to native Date objects\n      const newStart = this.toDate(s.tentativeStart);\n      const newEnd = this.toDate(s.tentativeEnd);\n\n      // DEBUG: Log final dates being applied\n      console.log(\"[DragController] onUp - applying changes:\", {\n        eventTitle: s.event.title,\n        mode: s.mode,\n        tentativeStart: this.adapter.format(\n          s.tentativeStart,\n          \"yyyy-MM-dd HH:mm\",\n        ),\n        tentativeEnd: this.adapter.format(s.tentativeEnd, \"yyyy-MM-dd HH:mm\"),\n        newStartDate: newStart.toISOString(),\n        newEndDate: newEnd.toISOString(),\n      });\n\n      // Call appropriate callback based on operation type\n      if (s.mode === \"move\") {\n        this.onDrop(s.event, newStart, newEnd);\n      } else {\n        // resize-left, resize-right, resize-top, resize-bottom\n        this.onResize(s.event, newStart, newEnd);\n      }\n      s.renderCallback();\n    } else {\n      // DEBUG: Log when no tentative dates\n      console.log(\"[DragController] onUp - no tentative dates, drag cancelled\");\n    }\n\n    this.state = null;\n  }\n\n  /**\n   * Convert adapter date to native Date object\n   */\n  private toDate(adapterDate: T): Date {\n    return new Date(\n      this.adapter.year(adapterDate),\n      this.adapter.month(adapterDate),\n      this.adapter.date(adapterDate),\n      this.adapter.hour(adapterDate),\n      this.adapter.minute(adapterDate),\n    );\n  }\n}\n","/**\n * Event data management\n */\nimport type { CalendarEvent } from '../types';\n\n/**\n * Manages calendar event data with CRUD operations\n */\nexport class EventManager {\n  private events: CalendarEvent[] = [];\n\n  /**\n   * Initialize with optional events\n   *\n   * @param initialEvents - Initial events to load\n   */\n  constructor(initialEvents?: CalendarEvent[]) {\n    if (initialEvents) {\n      this.events = [...initialEvents];\n    }\n  }\n\n  /**\n   * Add a new event\n   *\n   * @param event - Event to add\n   */\n  addEvent(event: CalendarEvent): void {\n    this.events.push(event);\n  }\n\n  /**\n   * Remove an event by ID\n   *\n   * @param id - Event ID to remove\n   * @returns true if event was found and removed\n   */\n  removeEvent(id: string): boolean {\n    const index = this.events.findIndex(e => e.id === id);\n\n    if (index > -1) {\n      this.events.splice(index, 1);\n      return true;\n    }\n\n    return false;\n  }\n\n  /**\n   * Update an existing event\n   *\n   * @param id - Event ID to update\n   * @param updates - Partial event data to merge\n   * @returns true if event was found and updated\n   */\n  updateEvent(id: string, updates: Partial<CalendarEvent>): boolean {\n    const event = this.events.find(e => e.id === id);\n\n    if (event) {\n      Object.assign(event, updates);\n      return true;\n    }\n\n    return false;\n  }\n\n  /**\n   * Get all events\n   *\n   * @returns Copy of events array\n   */\n  getEvents(): CalendarEvent[] {\n    return [...this.events];\n  }\n\n  /**\n   * Find an event by ID\n   *\n   * @param id - Event ID to find\n   * @returns Event or undefined if not found\n   */\n  findEvent(id: string): CalendarEvent | undefined {\n    return this.events.find(e => e.id === id);\n  }\n\n  /**\n   * Clear all events\n   */\n  clear(): void {\n    this.events = [];\n  }\n\n  /**\n   * Set events (replaces all existing)\n   *\n   * @param events - New events array\n   */\n  setEvents(events: CalendarEvent[]): void {\n    this.events = [...events];\n  }\n\n  /**\n   * Get number of events\n   */\n  get count(): number {\n    return this.events.length;\n  }\n}\n","/**\n * Interaction controller for calendar user interactions\n * Handles clicks, double-clicks, context menus, and range selections\n */\nimport type {\n\tDateAdapter,\n\tCalendarEvent,\n\tResolvedCalendarConfig,\n\tViewType,\n\tRangeSelectionState,\n} from \"../types\";\nimport type { DragController } from \"./DragController\";\nimport type { EventManager } from \"./EventManager\";\nimport { createElement, setStyles, querySelectorAll } from \"../utils/dom\";\n\n/**\n * Manages all user interactions with the calendar\n * Uses event delegation pattern for performance\n */\nexport class InteractionController<T> {\n\tprivate container: HTMLElement | null = null;\n\tprivate rangeState: RangeSelectionState<T> | null = null;\n\n\t// Bound event handlers for cleanup\n\tprivate boundHandleClick: (e: MouseEvent) => void;\n\tprivate boundHandleDblClick: (e: MouseEvent) => void;\n\tprivate boundHandleContextMenu: (e: MouseEvent) => void;\n\tprivate boundHandleMouseDown: (e: MouseEvent) => void;\n\tprivate boundHandleRangeMove: (e: MouseEvent) => void;\n\tprivate boundHandleRangeEnd: (e: MouseEvent) => void;\n\n\tconstructor(\n\t\tprivate adapter: DateAdapter<T>,\n\t\tprivate config: ResolvedCalendarConfig,\n\t\tprivate dragController: DragController<T>,\n\t\tprivate currentView: () => ViewType,\n\t\tprivate eventManager: EventManager,\n\t) {\n\t\t// Bind event handlers\n\t\tthis.boundHandleClick = this.handleClick.bind(this);\n\t\tthis.boundHandleDblClick = this.handleDblClick.bind(this);\n\t\tthis.boundHandleContextMenu = this.handleContextMenu.bind(this);\n\t\tthis.boundHandleMouseDown = this.handleMouseDown.bind(this);\n\t\tthis.boundHandleRangeMove = this.handleRangeMove.bind(this);\n\t\tthis.boundHandleRangeEnd = this.handleRangeEnd.bind(this);\n\t}\n\n\t// ==========================================================================\n\t// Public Methods\n\t// ==========================================================================\n\n\t/**\n\t * Initialize interaction listeners on the calendar container\n\t */\n\tinit(container: HTMLElement): void {\n\t\t// Clean up previous listeners if any\n\t\tthis.destroy();\n\n\t\tthis.container = container;\n\n\t\t// Add event listeners using event delegation\n\t\tcontainer.addEventListener(\"click\", this.boundHandleClick);\n\t\tcontainer.addEventListener(\"dblclick\", this.boundHandleDblClick);\n\t\tcontainer.addEventListener(\"contextmenu\", this.boundHandleContextMenu);\n\t\tcontainer.addEventListener(\"mousedown\", this.boundHandleMouseDown);\n\t}\n\n\t/**\n\t * Clean up all event listeners\n\t */\n\tdestroy(): void {\n\t\tif (this.container) {\n\t\t\tthis.container.removeEventListener(\"click\", this.boundHandleClick);\n\t\t\tthis.container.removeEventListener(\n\t\t\t\t\"dblclick\",\n\t\t\t\tthis.boundHandleDblClick,\n\t\t\t);\n\t\t\tthis.container.removeEventListener(\n\t\t\t\t\"contextmenu\",\n\t\t\t\tthis.boundHandleContextMenu,\n\t\t\t);\n\t\t\tthis.container.removeEventListener(\n\t\t\t\t\"mousedown\",\n\t\t\t\tthis.boundHandleMouseDown,\n\t\t\t);\n\t\t}\n\n\t\t// Clean up range selection listeners\n\t\tdocument.removeEventListener(\"mousemove\", this.boundHandleRangeMove);\n\t\tdocument.removeEventListener(\"mouseup\", this.boundHandleRangeEnd);\n\n\t\tthis.clearRangePreview();\n\t\tthis.rangeState = null;\n\t\tthis.container = null;\n\t}\n\n\t// ==========================================================================\n\t// Event Handlers\n\t// ==========================================================================\n\n\t/**\n\t * Handle click events\n\t */\n\tprivate handleClick(e: MouseEvent): void {\n\t\tconst target = e.target as HTMLElement;\n\n\t\t// 1. Check if clicking on an event - already handled by existing onEventClick\n\t\tconst eventEl = target.closest(\".tg-event-block, .tg-event-bar\");\n\t\tif (eventEl) {\n\t\t\treturn; // Let existing event click handler deal with it\n\t\t}\n\n\t\t// 2. Check if clicking on a date cell (month view)\n\t\tif (this.currentView() === \"month\") {\n\t\t\tconst cellEl = target.closest(\".tg-month-cell\");\n\t\t\tif (cellEl) {\n\t\t\t\tthis.handleDateClick(cellEl as HTMLElement);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// 3. Check if clicking on a time slot (week/day view)\n\t\tif (this.currentView() === \"week\" || this.currentView() === \"day\") {\n\t\t\tconst colEl = target.closest(\".tg-day-column\");\n\t\t\tif (colEl && !target.closest(\".tg-event-block\")) {\n\t\t\t\tthis.handleTimeSlotClick(e, colEl as HTMLElement);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Handle double-click events\n\t */\n\tprivate handleDblClick(e: MouseEvent): void {\n\t\tconst target = e.target as HTMLElement;\n\n\t\t// 1. Event double-click\n\t\tconst eventEl = target.closest(\".tg-event-block, .tg-event-bar\");\n\t\tif (eventEl) {\n\t\t\tconst eventId = eventEl.getAttribute(\"data-eid\");\n\t\t\tconst event = this.getEventById(eventId);\n\t\t\tif (event) {\n\t\t\t\tthis.config.onEventDoubleClick?.(event);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// 2. Date double-click (month view)\n\t\tif (this.currentView() === \"month\") {\n\t\t\tconst cellEl = target.closest(\".tg-month-cell\");\n\t\t\tif (cellEl) {\n\t\t\t\tconst date = this.getDateFromCell(cellEl as HTMLElement);\n\t\t\t\tif (date) {\n\t\t\t\t\tthis.config.onDateDoubleClick?.(this.toDate(date));\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// 3. Time slot double-click (week/day view)\n\t\tif (this.currentView() === \"week\" || this.currentView() === \"day\") {\n\t\t\tconst colEl = target.closest(\".tg-day-column\");\n\t\t\tif (colEl && !target.closest(\".tg-event-block\")) {\n\t\t\t\tconst dateTime = this.getDateTimeFromSlot(\n\t\t\t\t\te,\n\t\t\t\t\tcolEl as HTMLElement,\n\t\t\t\t);\n\t\t\t\tif (dateTime) {\n\t\t\t\t\tthis.config.onTimeSlotDoubleClick?.(this.toDate(dateTime));\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Handle context menu (right-click) events\n\t */\n\tprivate handleContextMenu(e: MouseEvent): void {\n\t\tconst target = e.target as HTMLElement;\n\n\t\t// Check if any context menu callback is defined\n\t\tconst hasContextMenu =\n\t\t\tthis.config.onEventContextMenu ||\n\t\t\tthis.config.onDateContextMenu ||\n\t\t\tthis.config.onTimeSlotContextMenu;\n\n\t\tif (!hasContextMenu) {\n\t\t\treturn; // Let default context menu show\n\t\t}\n\n\t\t// 1. Event context menu\n\t\tconst eventEl = target.closest(\".tg-event-block, .tg-event-bar\");\n\t\tif (eventEl && this.config.onEventContextMenu) {\n\t\t\te.preventDefault();\n\t\t\tconst eventId = eventEl.getAttribute(\"data-eid\");\n\t\t\tconst event = this.getEventById(eventId);\n\t\t\t// Debug logging\n\t\t\tconsole.log(\"[InteractionController] Context menu on event:\", {\n\t\t\t\teventId,\n\t\t\t\teventFound: !!event,\n\t\t\t\teventEl: eventEl.className,\n\t\t\t\tallEvents: this.eventManager.getEvents().map((e) => e.id),\n\t\t\t});\n\t\t\tif (event) {\n\t\t\t\tthis.config.onEventContextMenu(event, e.clientX, e.clientY);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// 2. Date context menu (month view)\n\t\tif (this.currentView() === \"month\" && this.config.onDateContextMenu) {\n\t\t\tconst cellEl = target.closest(\".tg-month-cell\");\n\t\t\tif (cellEl) {\n\t\t\t\te.preventDefault();\n\t\t\t\tconst date = this.getDateFromCell(cellEl as HTMLElement);\n\t\t\t\tif (date) {\n\t\t\t\t\tthis.config.onDateContextMenu(\n\t\t\t\t\t\tthis.toDate(date),\n\t\t\t\t\t\te.clientX,\n\t\t\t\t\t\te.clientY,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// 3. Time slot context menu (week/day view)\n\t\tif (\n\t\t\t(this.currentView() === \"week\" || this.currentView() === \"day\") &&\n\t\t\tthis.config.onTimeSlotContextMenu\n\t\t) {\n\t\t\tconst colEl = target.closest(\".tg-day-column\");\n\t\t\tif (colEl && !target.closest(\".tg-event-block\")) {\n\t\t\t\te.preventDefault();\n\t\t\t\tconst dateTime = this.getDateTimeFromSlot(\n\t\t\t\t\te,\n\t\t\t\t\tcolEl as HTMLElement,\n\t\t\t\t);\n\t\t\t\tif (dateTime) {\n\t\t\t\t\tthis.config.onTimeSlotContextMenu(\n\t\t\t\t\t\tthis.toDate(dateTime),\n\t\t\t\t\t\te.clientX,\n\t\t\t\t\t\te.clientY,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Handle mouse down for range selection\n\t */\n\tprivate handleMouseDown(e: MouseEvent): void {\n\t\t// Only left button\n\t\tif (e.button !== 0) return;\n\n\t\tconst target = e.target as HTMLElement;\n\n\t\t// Don't start range selection if clicking on events\n\t\tif (target.closest(\".tg-event-block, .tg-event-bar\")) return;\n\n\t\t// Don't start range selection if drag controller is active\n\t\tif (this.dragController.isDragging()) return;\n\n\t\t// Check if range selection callbacks are defined\n\t\tconst hasRangeSelect =\n\t\t\tthis.config.onDateRangeSelect || this.config.onTimeRangeSelect;\n\t\tif (!hasRangeSelect) return;\n\n\t\t// Handle month view range selection\n\t\tif (this.currentView() === \"month\" && this.config.onDateRangeSelect) {\n\t\t\tconst cellEl = target.closest(\".tg-month-cell\");\n\t\t\tif (!cellEl) return;\n\n\t\t\tconst date = this.getDateFromCell(cellEl as HTMLElement);\n\t\t\tif (!date) return;\n\n\t\t\tthis.rangeState = {\n\t\t\t\tisSelecting: true,\n\t\t\t\tstartDate: date,\n\t\t\t\tstartX: e.clientX,\n\t\t\t\tstartY: e.clientY,\n\t\t\t\tcurrentDate: date,\n\t\t\t\tviewType: \"month\",\n\t\t\t};\n\n\t\t\tdocument.addEventListener(\"mousemove\", this.boundHandleRangeMove);\n\t\t\tdocument.addEventListener(\"mouseup\", this.boundHandleRangeEnd);\n\n\t\t\t// Add selecting class to prevent text selection\n\t\t\tif (this.container) {\n\t\t\t\tthis.container.classList.add(\"tg-selecting\");\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle time view range selection\n\t\tif (\n\t\t\t(this.currentView() === \"week\" || this.currentView() === \"day\") &&\n\t\t\tthis.config.onTimeRangeSelect\n\t\t) {\n\t\t\tconst colEl = target.closest(\".tg-day-column\");\n\t\t\tif (!colEl) return;\n\n\t\t\tconst dateTime = this.getDateTimeFromSlot(e, colEl as HTMLElement);\n\t\t\tif (!dateTime) return;\n\n\t\t\tthis.rangeState = {\n\t\t\t\tisSelecting: true,\n\t\t\t\tstartDate: dateTime,\n\t\t\t\tstartX: e.clientX,\n\t\t\t\tstartY: e.clientY,\n\t\t\t\tcurrentDate: dateTime,\n\t\t\t\tviewType: \"time\",\n\t\t\t\tcolumnEl: colEl as HTMLElement,\n\t\t\t};\n\n\t\t\tdocument.addEventListener(\"mousemove\", this.boundHandleRangeMove);\n\t\t\tdocument.addEventListener(\"mouseup\", this.boundHandleRangeEnd);\n\n\t\t\t// Add selecting class to prevent text selection\n\t\t\tif (this.container) {\n\t\t\t\tthis.container.classList.add(\"tg-selecting\");\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/**\n\t * Handle mouse move during range selection\n\t */\n\tprivate handleRangeMove(e: MouseEvent): void {\n\t\tif (!this.rangeState?.isSelecting) return;\n\n\t\tconst target = document.elementFromPoint(e.clientX, e.clientY);\n\t\tif (!target) return;\n\n\t\tif (this.rangeState.viewType === \"month\") {\n\t\t\tconst cellEl = target.closest(\".tg-month-cell\");\n\t\t\tif (cellEl) {\n\t\t\t\tconst date = this.getDateFromCell(cellEl as HTMLElement);\n\t\t\t\tif (date) {\n\t\t\t\t\tthis.rangeState.currentDate = date;\n\t\t\t\t\tthis.renderMonthRangePreview();\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Time view\n\t\t\tconst colEl = target.closest(\".tg-day-column\");\n\t\t\tif (colEl) {\n\t\t\t\tconst dateTime = this.getDateTimeFromSlot(\n\t\t\t\t\te,\n\t\t\t\t\tcolEl as HTMLElement,\n\t\t\t\t);\n\t\t\t\tif (dateTime) {\n\t\t\t\t\tthis.rangeState.currentDate = dateTime;\n\t\t\t\t\tthis.renderTimeRangePreview();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Handle mouse up to complete range selection\n\t */\n\tprivate handleRangeEnd(_e: MouseEvent): void {\n\t\tif (!this.rangeState?.isSelecting) return;\n\n\t\t// Clean up\n\t\tdocument.removeEventListener(\"mousemove\", this.boundHandleRangeMove);\n\t\tdocument.removeEventListener(\"mouseup\", this.boundHandleRangeEnd);\n\n\t\tif (this.container) {\n\t\t\tthis.container.classList.remove(\"tg-selecting\");\n\t\t}\n\n\t\t// Trigger callback if we have both start and end dates\n\t\tif (this.rangeState.startDate && this.rangeState.currentDate) {\n\t\t\tconst startDate = this.rangeState.startDate;\n\t\t\tconst endDate = this.rangeState.currentDate;\n\n\t\t\t// Ensure start is before end\n\t\t\tconst isStartAfterEnd = this.adapter.isAfter(startDate, endDate);\n\n\t\t\tif (this.rangeState.viewType === \"month\") {\n\t\t\t\tconst start = this.toDate(\n\t\t\t\t\tisStartAfterEnd ? endDate : startDate,\n\t\t\t\t);\n\t\t\t\tconst end = this.toDate(isStartAfterEnd ? startDate : endDate);\n\t\t\t\tthis.config.onDateRangeSelect?.(start, end);\n\t\t\t} else {\n\t\t\t\tconst start = this.toDate(\n\t\t\t\t\tisStartAfterEnd ? endDate : startDate,\n\t\t\t\t);\n\t\t\t\tconst end = this.toDate(isStartAfterEnd ? startDate : endDate);\n\t\t\t\tthis.config.onTimeRangeSelect?.(start, end);\n\t\t\t}\n\t\t}\n\n\t\tthis.clearRangePreview();\n\t\tthis.rangeState = null;\n\t}\n\n\t// ==========================================================================\n\t// Helper Methods\n\t// ==========================================================================\n\n\t/**\n\t * Convert adapter date to native Date object\n\t */\n\tprivate toDate(adapterDate: T): Date {\n\t\treturn new Date(\n\t\t\tthis.adapter.year(adapterDate),\n\t\t\tthis.adapter.month(adapterDate),\n\t\t\tthis.adapter.date(adapterDate),\n\t\t\tthis.adapter.hour(adapterDate),\n\t\t\tthis.adapter.minute(adapterDate),\n\t\t);\n\t}\n\n\t/**\n\t * Get event by ID from event manager\n\t */\n\tprivate getEventById(eventId: string | null): CalendarEvent | undefined {\n\t\tif (!eventId) return undefined;\n\t\treturn this.eventManager.findEvent(eventId);\n\t}\n\n\t/**\n\t * Get date from a month view cell\n\t */\n\tprivate getDateFromCell(cellEl: HTMLElement): T | null {\n\t\tconst row = cellEl.closest(\".tg-month-row\") as HTMLElement;\n\t\tif (!row?.dataset[\"date\"]) return null;\n\n\t\tconst cells = Array.from(row.querySelectorAll(\".tg-month-cell\"));\n\t\tconst index = cells.indexOf(cellEl);\n\t\tif (index < 0) return null;\n\n\t\tconst rowStart = this.adapter.parse(row.dataset[\"date\"]);\n\t\tconst clickedDate = this.adapter.add(rowStart, index, \"day\");\n\t\treturn clickedDate;\n\t}\n\n\t/**\n\t * Get date-time from a time slot click\n\t */\n\tprivate getDateTimeFromSlot(e: MouseEvent, colEl: HTMLElement): T | null {\n\t\tconst dateStr = colEl.dataset[\"date\"];\n\t\tif (!dateStr) return null;\n\n\t\tconst rect = colEl.getBoundingClientRect();\n\t\tconst relY = e.clientY - rect.top;\n\n\t\tconst cellHeight = this.config.theme.cellHeight;\n\t\tconst snapMinutes = this.config.draggable.snapMinutes;\n\n\t\tconst rawMinutes = (relY / cellHeight) * 60;\n\t\tconst snappedMinutes = Math.max(\n\t\t\t0,\n\t\t\tMath.min(1440, Math.round(rawMinutes / snapMinutes) * snapMinutes),\n\t\t);\n\n\t\tconst date = this.adapter.parse(dateStr);\n\t\tconst dateTime = this.adapter.setMinute(\n\t\t\tthis.adapter.setHour(date, Math.floor(snappedMinutes / 60)),\n\t\t\tsnappedMinutes % 60,\n\t\t);\n\n\t\treturn dateTime;\n\t}\n\n\t/**\n\t * Handle date cell click\n\t */\n\tprivate handleDateClick(cellEl: HTMLElement): void {\n\t\tconst date = this.getDateFromCell(cellEl);\n\t\tif (date) {\n\t\t\tthis.config.onDateClick?.(this.toDate(date));\n\t\t}\n\t}\n\n\t/**\n\t * Handle time slot click\n\t */\n\tprivate handleTimeSlotClick(e: MouseEvent, colEl: HTMLElement): void {\n\t\tconst dateTime = this.getDateTimeFromSlot(e, colEl);\n\t\tif (dateTime) {\n\t\t\tthis.config.onTimeSlotClick?.(this.toDate(dateTime));\n\t\t}\n\t}\n\n\t// ==========================================================================\n\t// Range Preview Rendering\n\t// ==========================================================================\n\n\t/**\n\t * Render visual preview for month view range selection\n\t */\n\tprivate renderMonthRangePreview(): void {\n\t\tif (!this.rangeState?.startDate || !this.rangeState?.currentDate)\n\t\t\treturn;\n\n\t\t// Clear existing preview\n\t\tthis.clearRangePreview();\n\n\t\tconst startDate = this.adapter.isBefore(\n\t\t\tthis.rangeState.startDate,\n\t\t\tthis.rangeState.currentDate,\n\t\t)\n\t\t\t? this.rangeState.startDate\n\t\t\t: this.rangeState.currentDate;\n\t\tconst endDate = this.adapter.isAfter(\n\t\t\tthis.rangeState.startDate,\n\t\t\tthis.rangeState.currentDate,\n\t\t)\n\t\t\t? this.rangeState.startDate\n\t\t\t: this.rangeState.currentDate;\n\n\t\tconst rows = querySelectorAll<HTMLElement>(\".tg-month-row\");\n\n\t\tfor (const row of rows) {\n\t\t\tif (!row.dataset[\"date\"]) continue;\n\n\t\t\tconst rowStart = this.adapter.parse(row.dataset[\"date\"]);\n\t\t\tconst cells = Array.from(row.querySelectorAll(\".tg-month-cell\"));\n\t\t\tconst rowEnd = this.adapter.add(rowStart, cells.length - 1, \"day\");\n\n\t\t\t// Check if selection overlaps this row\n\t\t\tif (\n\t\t\t\t!this.adapter.isBefore(endDate, rowStart) &&\n\t\t\t\t!this.adapter.isAfter(startDate, rowEnd)\n\t\t\t) {\n\t\t\t\t// Calculate selection range within this row\n\t\t\t\tfor (let i = 0; i < cells.length; i++) {\n\t\t\t\t\tconst cellDate = this.adapter.add(rowStart, i, \"day\");\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t!this.adapter.isBefore(cellDate, startDate) &&\n\t\t\t\t\t\t!this.adapter.isAfter(cellDate, endDate)\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst cell = cells[i];\n\t\t\t\t\t\tif (cell) {\n\t\t\t\t\t\t\tcell.classList.add(\"tg-range-preview\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Render visual preview for time view range selection\n\t */\n\tprivate renderTimeRangePreview(): void {\n\t\tif (!this.rangeState?.startDate || !this.rangeState?.currentDate)\n\t\t\treturn;\n\n\t\t// Clear existing preview\n\t\tthis.clearRangePreview();\n\n\t\tconst startDate = this.adapter.isBefore(\n\t\t\tthis.rangeState.startDate,\n\t\t\tthis.rangeState.currentDate,\n\t\t)\n\t\t\t? this.rangeState.startDate\n\t\t\t: this.rangeState.currentDate;\n\t\tconst endDate = this.adapter.isAfter(\n\t\t\tthis.rangeState.startDate,\n\t\t\tthis.rangeState.currentDate,\n\t\t)\n\t\t\t? this.rangeState.startDate\n\t\t\t: this.rangeState.currentDate;\n\n\t\t// Check if selection is within a single day\n\t\tconst isSameDay = this.adapter.isSame(startDate, endDate, \"day\");\n\n\t\t// Handle single column selection\n\t\tif (isSameDay) {\n\t\t\t// Find the column for this date\n\t\t\tconst columns = querySelectorAll<HTMLElement>(\".tg-day-column\");\n\t\t\tlet col: HTMLElement | null = null;\n\t\t\tfor (const c of columns) {\n\t\t\t\tconst colDateStr = c.dataset[\"date\"];\n\t\t\t\tif (colDateStr) {\n\t\t\t\t\tconst colDate = this.adapter.parse(colDateStr);\n\t\t\t\t\tif (this.adapter.isSame(colDate, startDate, \"day\")) {\n\t\t\t\t\t\tcol = c;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!col) return;\n\n\t\t\tconst startMin =\n\t\t\t\tthis.adapter.hour(startDate) * 60 +\n\t\t\t\tthis.adapter.minute(startDate);\n\t\t\tconst endMin =\n\t\t\t\tthis.adapter.hour(endDate) * 60 + this.adapter.minute(endDate);\n\n\t\t\tconst cellHeight = this.config.theme.cellHeight;\n\t\t\tconst top = (startMin / 60) * cellHeight;\n\t\t\tconst height = ((endMin - startMin) / 60) * cellHeight;\n\n\t\t\tconst preview = createElement(\"div\", \"tg-time-range-preview\");\n\t\t\tsetStyles(preview, {\n\t\t\t\ttop: `${top}px`,\n\t\t\t\theight: `${Math.max(height, cellHeight / 4)}px`,\n\t\t\t\twidth: \"100%\",\n\t\t\t\tleft: \"0\",\n\t\t\t});\n\n\t\t\tcol.appendChild(preview);\n\t\t} else {\n\t\t\t// Multi-column selection - add simple visual indicator for each column\n\t\t\tconst columns = querySelectorAll<HTMLElement>(\".tg-day-column\");\n\t\t\tfor (const col of columns) {\n\t\t\t\tconst colDateStr = col.dataset[\"date\"];\n\t\t\t\tif (!colDateStr) continue;\n\n\t\t\t\tconst colDate = this.adapter.parse(colDateStr);\n\n\t\t\t\tif (\n\t\t\t\t\t!this.adapter.isBefore(colDate, startDate, \"day\") &&\n\t\t\t\t\t!this.adapter.isAfter(colDate, endDate, \"day\")\n\t\t\t\t) {\n\t\t\t\t\tcol.classList.add(\"tg-range-preview\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clear all range preview elements and classes\n\t */\n\tprivate clearRangePreview(): void {\n\t\t// Remove preview elements\n\t\tquerySelectorAll(\".tg-time-range-preview\").forEach((el) => el.remove());\n\n\t\t// Remove preview classes\n\t\tquerySelectorAll(\".tg-range-preview\").forEach((el) => {\n\t\t\tel.classList.remove(\"tg-range-preview\");\n\t\t});\n\t}\n}\n","import type { ThemeConfig } from \"../types\";\n\ntype ResolvedTheme = Required<ThemeConfig> & {\n  fontSize: Required<NonNullable<ThemeConfig[\"fontSize\"]>>;\n};\n\n/**\n * Apply theme values as CSS variables on the given element.\n */\nexport function applyThemeVariables(\n  target: HTMLElement,\n  theme: ResolvedTheme,\n): void {\n  target.style.setProperty(\"--tg-primary-color\", theme.primaryColor);\n  target.style.setProperty(\"--tg-primary-rgb\", hexToRgb(theme.primaryColor));\n  target.style.setProperty(\"--tg-cell-height\", `${theme.cellHeight}px`);\n  target.style.setProperty(\"--tg-font-header\", theme.fontSize.header);\n  target.style.setProperty(\"--tg-font-event\", theme.fontSize.event);\n}\n\n/**\n * Clear theme variables from the element.\n */\nexport function clearThemeVariables(target: HTMLElement): void {\n  target.style.removeProperty(\"--tg-primary-color\");\n  target.style.removeProperty(\"--tg-primary-rgb\");\n  target.style.removeProperty(\"--tg-cell-height\");\n  target.style.removeProperty(\"--tg-font-header\");\n  target.style.removeProperty(\"--tg-font-event\");\n}\n\n/**\n * Convert hex color to RGB string\n */\nfunction hexToRgb(hex: string): string {\n  const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n  if (result) {\n    return `${parseInt(result[1]!, 16)}, ${parseInt(result[2]!, 16)}, ${parseInt(result[3]!, 16)}`;\n  }\n  return \"59, 130, 246\"; // Default blue\n}\n","/**\n * Default date format configurations for the calendar\n * Uses unicode format tokens (compatible with date-fns and Day.js)\n */\nimport type { DateFormatConfig } from \"../types\";\n\n/**\n * Default date formats using unicode tokens\n * These are used when no custom dateFormats configuration is provided\n */\nexport const DEFAULT_DATE_FORMATS: Required<DateFormatConfig> = {\n  date: \"yyyy-MM-dd\",\n  dateTime: \"yyyy-MM-dd HH:mm\",\n  time: \"HH:mm\",\n  monthHeader: \"yyyy年 M月\",\n  dayHeader: \"yyyy年M月d日\",\n};\n\n/**\n * Internal data exchange format (ISO 8601)\n *\n * Used for:\n * - Public API return values (getCurrentDate)\n * - Event callbacks (onEventDrop)\n * - Internal data passing between components\n *\n * Design rationale:\n * - Ensures reliability: ISO format is standardized and unambiguous\n * - Separation of concerns: Data format ≠ Display format\n * - Parse reliability: All adapters can reliably parse ISO format\n *\n * Note: Display formats (dateFormats config) are used only for UI rendering\n */\nexport const INTERNAL_DATA_FORMAT = {\n  date: \"yyyy-MM-dd\",\n  dateTime: \"yyyy-MM-dd HH:mm\",\n} as const;\n","/**\n * BaseView - Abstract base class for all calendar views\n *\n * Provides a foundation for creating custom views with:\n * - Lifecycle hooks (mount, unmount, update)\n * - Access to calendar context (events, date, adapter)\n * - Headless mode support for custom rendering\n */\nimport type {\n  CalendarEvent,\n  DateAdapter,\n  ResolvedCalendarConfig,\n  ViewType,\n} from \"../types\";\nimport type { DragController } from \"../core/DragController\";\nimport type { EventManager } from \"../core/EventManager\";\n\n/**\n * Context provided to views for rendering and interaction\n */\nexport interface ViewContext<T = unknown> {\n  /** Current display date */\n  currentDate: T;\n  /** Date adapter for date operations */\n  adapter: DateAdapter<T>;\n  /** Event manager for CRUD operations */\n  eventManager: EventManager;\n  /** Drag controller for drag-and-drop */\n  dragController: DragController<T>;\n  /** Resolved calendar configuration */\n  config: ResolvedCalendarConfig;\n  /** Trigger a re-render of the view */\n  requestRender: () => void;\n  /**\n   * Navigate to a specific date\n   * Accepts adapter date type T, string (ISO format), or native Date\n   */\n  goToDate: (date: T | string | Date) => void;\n  /** Get the current view type */\n  getCurrentView: () => ViewType;\n}\n\n/**\n * View metadata for registration\n * Required for all view classes\n */\nexport interface ViewMeta {\n  /** Unique view type identifier */\n  type: string;\n  /** Display label for the view switcher */\n  label: string;\n  /** Short label for compact display (1-2 chars) */\n  shortLabel?: string;\n  /** Icon class or SVG string (optional) */\n  icon?: string;\n  /** Sort order in view switcher (lower = first) */\n  order?: number;\n}\n\n/**\n * Options for view rendering\n */\nexport interface ViewRenderOptions {\n  /** Preserved scroll position from previous render */\n  preservedScrollTop?: number | null;\n}\n\n/**\n * Interface for view class constructor with required static meta\n * This ensures compile-time type safety for view registration\n */\nexport interface ViewClass<T = unknown> {\n  /** Static metadata required for registration */\n  readonly meta: ViewMeta;\n  /** Constructor that creates a BaseView instance */\n  new (): BaseView<T>;\n}\n\n/**\n * Abstract base class for calendar views\n *\n * Subclasses MUST define a static `meta` property with at least `type` and `label`.\n * This is enforced at compile-time via the ViewClass interface.\n *\n * @example Extending BaseView for a custom view\n * ```typescript\n * class CustomView extends BaseView {\n *   static readonly meta: ViewMeta = {\n *     type: 'custom',\n *     label: 'Custom View',\n *     shortLabel: 'C',\n *     order: 100\n *   };\n *\n *   render(container: HTMLElement, events: CalendarEvent[], options?: ViewRenderOptions): void {\n *     // Custom rendering logic\n *   }\n * }\n * ```\n *\n * @example Headless mode (using provided engines/utilities)\n * ```typescript\n * class HeadlessCustomView extends BaseView {\n *   static readonly meta: ViewMeta = { type: 'headless', label: 'Headless' };\n *\n *   render(container: HTMLElement, events: CalendarEvent[]): void {\n *     // Use this.context.adapter for date operations\n *     const weekStart = this.context.adapter.startOf(this.context.currentDate, 'week');\n *\n *     // Use this.context.eventManager for event operations\n *     const allEvents = this.context.eventManager.getEvents();\n *\n *     // Completely custom rendering...\n *   }\n * }\n * ```\n */\nexport abstract class BaseView<T = unknown> {\n  /**\n   * View metadata - MUST be defined by subclasses as a static readonly property\n   * Used for registration and display in view switcher\n   *\n   * @example\n   * static readonly meta: ViewMeta = { type: 'myview', label: 'My View' };\n   */\n  static readonly meta: ViewMeta;\n\n  /** View context with calendar state and utilities */\n  protected context!: ViewContext<T>;\n\n  /** Whether the view is currently mounted */\n  protected mounted = false;\n\n  /**\n   * Initialize the view with context\n   * Called by the Calendar when switching to this view\n   */\n  init(context: ViewContext<T>): void {\n    this.context = context;\n  }\n\n  /**\n   * Render the view into the container\n   *\n   * @param container - DOM element to render into\n   * @param events - Events to display\n   * @param options - Additional render options\n   */\n  abstract render(\n    container: HTMLElement,\n    events: CalendarEvent[],\n    options?: ViewRenderOptions,\n  ): void;\n\n  /**\n   * Called when the view is mounted (first render)\n   * Override to add setup logic\n   */\n  onMount(): void {\n    this.mounted = true;\n  }\n\n  /**\n   * Called when the view is unmounted (switching away)\n   * Override to add cleanup logic\n   */\n  onUnmount(): void {\n    this.mounted = false;\n  }\n\n  /**\n   * Called when events are updated\n   * Override for optimized partial updates instead of full re-render\n   *\n   * @param events - Updated events array\n   * @returns true if handled, false to trigger full re-render\n   */\n  onEventsUpdate(_events: CalendarEvent[]): boolean {\n    return false; // Default: trigger full re-render\n  }\n\n  /**\n   * Called when the current date changes\n   * Override for optimized date navigation\n   *\n   * @param newDate - New current date\n   * @returns true if handled, false to trigger full re-render\n   */\n  onDateChange(_newDate: T): boolean {\n    return false; // Default: trigger full re-render\n  }\n\n  /**\n   * Get the navigation unit for prev/next buttons\n   * Override to customize navigation behavior\n   */\n  getNavigationUnit(): \"year\" | \"month\" | \"week\" | \"day\" {\n    return \"month\";\n  }\n\n  /**\n   * Get the header title for this view\n   * Override to customize the header display\n   */\n  getHeaderTitle(): string {\n    const format =\n      this.getNavigationUnit() === \"day\"\n        ? this.context.config.dateFormats.dayHeader\n        : this.context.config.dateFormats.monthHeader;\n    return this.context.adapter.format(this.context.currentDate, format);\n  }\n\n  /**\n   * Check if the view is currently mounted\n   */\n  isMounted(): boolean {\n    return this.mounted;\n  }\n\n  /**\n   * Get the view metadata from the constructor\n   */\n  getMeta(): ViewMeta {\n    return (this.constructor as ViewClass<T>).meta;\n  }\n}\n\n/**\n * Type for view constructor (legacy alias for ViewClass)\n * @deprecated Use ViewClass instead for better type safety\n */\nexport type ViewConstructor<T = unknown> = ViewClass<T>;\n","/**\n * ViewRegistry - Manages registration and retrieval of calendar views\n *\n * Supports:\n * - Type-safe view registration with compile-time validation\n * - Dynamic view discovery\n * - View ordering for UI display\n */\nimport { BaseView, type ViewClass, type ViewMeta } from \"./BaseView\";\n\n/**\n * Registration options for custom views\n */\nexport interface ViewRegistrationOptions {\n  /**\n   * If true, replaces existing view with same type\n   * @default false\n   */\n  override?: boolean;\n}\n\n/**\n * Internal view registration entry\n */\ninterface ViewEntry {\n  /** View constructor */\n  ctor: ViewClass;\n  /** View metadata (cached from constructor) */\n  meta: ViewMeta;\n}\n\n/**\n * ViewRegistry manages all registered calendar views\n *\n * @example Basic usage\n * ```typescript\n * const registry = new ViewRegistry();\n *\n * // Register a custom view\n * registry.register(CustomView);\n *\n * // Get all registered views for UI\n * const views = registry.getAll();\n *\n * // Create a view instance\n * const view = registry.create('custom');\n * ```\n *\n * @example Custom view definition\n * ```typescript\n * class CustomView extends BaseView {\n *   static readonly meta: ViewMeta = {\n *     type: 'custom',\n *     label: 'Custom View',\n *     shortLabel: 'C',\n *     order: 40\n *   };\n *\n *   render(container: HTMLElement, events: CalendarEvent[]): void {\n *     // Custom rendering...\n *   }\n * }\n *\n * registry.register(CustomView);\n * ```\n */\nexport class ViewRegistry {\n  private views: Map<string, ViewEntry> = new Map();\n\n  /**\n   * Register a view class\n   *\n   * @param ViewClass - View class extending BaseView with static meta property\n   * @param options - Registration options\n   * @throws Error if view type already exists and override is false\n   * @throws Error if ViewClass is missing required static meta property\n   * @throws Error if ViewClass does not extend BaseView\n   *\n   * @example\n   * ```typescript\n   * // Define a view with required static meta\n   * class MyView extends BaseView {\n   *   static readonly meta: ViewMeta = { type: 'my', label: 'My View' };\n   *   render(container, events) { ... }\n   * }\n   *\n   * registry.register(MyView);\n   * ```\n   */\n  register<T>(\n    ViewClassArg: ViewClass<T>,\n    options: ViewRegistrationOptions = {},\n  ): void {\n    // Validate that ViewClass extends BaseView\n    if (\n      !(ViewClassArg.prototype instanceof BaseView) &&\n      ViewClassArg !== (BaseView as unknown as ViewClass<T>)\n    ) {\n      throw new Error(\n        `View class must extend BaseView. Got: ${ViewClassArg.name || \"anonymous class\"}`,\n      );\n    }\n\n    // Type-safe access to meta - ViewClass interface guarantees it exists\n    const meta = ViewClassArg.meta;\n\n    // Runtime validation for meta (in case of incorrect usage)\n    if (!meta || typeof meta !== \"object\") {\n      throw new Error(\n        `View class '${ViewClassArg.name || \"anonymous\"}' must have a static 'meta' property of type ViewMeta`,\n      );\n    }\n\n    if (!meta.type || typeof meta.type !== \"string\") {\n      throw new Error(\n        `View class '${ViewClassArg.name || \"anonymous\"}' meta must have a 'type' string property`,\n      );\n    }\n\n    if (!meta.label || typeof meta.label !== \"string\") {\n      throw new Error(\n        `View class '${ViewClassArg.name || \"anonymous\"}' meta must have a 'label' string property`,\n      );\n    }\n\n    // Check for existing registration\n    if (this.views.has(meta.type) && !options.override) {\n      throw new Error(\n        `View type '${meta.type}' is already registered. Use { override: true } to replace.`,\n      );\n    }\n\n    this.views.set(meta.type, {\n      ctor: ViewClassArg as ViewClass,\n      meta: { ...meta },\n    });\n  }\n\n  /**\n   * Unregister a view by type\n   *\n   * @param type - View type to unregister\n   * @returns true if view was removed, false if not found\n   */\n  unregister(type: string): boolean {\n    return this.views.delete(type);\n  }\n\n  /**\n   * Check if a view type is registered\n   *\n   * @param type - View type to check\n   */\n  has(type: string): boolean {\n    return this.views.has(type);\n  }\n\n  /**\n   * Get view metadata by type\n   *\n   * @param type - View type\n   * @returns View metadata or undefined if not found\n   */\n  getMeta(type: string): ViewMeta | undefined {\n    return this.views.get(type)?.meta;\n  }\n\n  /**\n   * Create a view instance\n   *\n   * @param type - View type to create\n   * @returns New view instance or undefined if not found\n   */\n  create<T = unknown>(type: string): BaseView<T> | undefined {\n    const entry = this.views.get(type);\n    if (!entry) {\n      return undefined;\n    }\n\n    return new entry.ctor() as BaseView<T>;\n  }\n\n  /**\n   * Get all registered view metadata, sorted by order then type (stable sort)\n   *\n   * @returns Array of view metadata sorted by order (ascending), then by type (alphabetical) for stability\n   */\n  getAll(): ViewMeta[] {\n    const metas = Array.from(this.views.values()).map((entry) => entry.meta);\n\n    // Stable sort: primary by order (default 50), secondary by type (alphabetical)\n    return metas.sort((a, b) => {\n      const orderA = a.order ?? 50;\n      const orderB = b.order ?? 50;\n\n      if (orderA !== orderB) {\n        return orderA - orderB;\n      }\n\n      // Tie-breaker: sort alphabetically by type for stable ordering\n      return a.type.localeCompare(b.type);\n    });\n  }\n\n  /**\n   * Get all registered view types\n   *\n   * @returns Array of view type strings\n   */\n  getTypes(): string[] {\n    return Array.from(this.views.keys());\n  }\n\n  /**\n   * Clear all registered views\n   */\n  clear(): void {\n    this.views.clear();\n  }\n\n  /**\n   * Get the number of registered views\n   */\n  get size(): number {\n    return this.views.size;\n  }\n}\n\n/**\n * Factory function to create a new ViewRegistry instance\n * Use this instead of a global singleton for better tree-shaking\n *\n * @returns A new ViewRegistry instance\n */\nexport function createViewRegistry(): ViewRegistry {\n  return new ViewRegistry();\n}\n","/**\n * Month view layout engine\n * Handles grid generation and event layout calculation for month view\n */\nimport type {\n  DateAdapter,\n  CalendarEvent,\n  MonthLayoutItem,\n  GridCell,\n  DateFormatConfig,\n  VisibleDay,\n} from \"../types\";\nimport type { DayFilterContext, DayFilterResult } from \"../types\";\n\n/**\n * Engine for calculating month view layouts\n */\nexport class MonthEngine<T> {\n  constructor(\n    private adapter: DateAdapter<T>,\n    private firstDayOfWeek: number = 0,\n    private showWeekends: boolean = true,\n    private dateFormats: Required<DateFormatConfig>,\n  ) {}\n\n  /**\n   * Generate the grid of days for a month view\n   * Returns a 2D array of weeks, each containing 7 days\n   * Includes days from previous/next months to fill complete weeks\n   *\n   * @param currentDate - The current date to generate grid for\n   * @param dayFilter - Optional filter function to control which days are included\n   * @returns Array of weeks, each containing GridCell objects for visible days\n   */\n  generateGrid(\n    currentDate: T,\n    dayFilter?: (date: T, context: DayFilterContext) => DayFilterResult,\n  ): Array<Array<GridCell<T>>> {\n    // Get month boundaries\n    const monthStart = this.adapter.startOf(currentDate, \"month\");\n    const monthEnd = this.adapter.endOf(currentDate, \"month\");\n    const today = this.adapter.create();\n\n    // Adjust start to first day of week\n    let start = this.adapter.startOf(monthStart, \"week\");\n\n    // Adjust start based on firstDayOfWeek configuration\n    const currentDayOfWeek = this.adapter.day(start);\n    if (currentDayOfWeek !== this.firstDayOfWeek) {\n      let diff = this.firstDayOfWeek - currentDayOfWeek;\n      // Ensure we go backward to the correct start of week\n      if (diff > 0) {\n        diff = diff - 7; // Go to previous week\n      }\n      start = this.adapter.add(start, diff, \"day\");\n    }\n\n    // Calculate end to ensure we cover the entire month\n    let end = this.adapter.endOf(monthEnd, \"week\");\n\n    // Adjust end based on firstDayOfWeek\n    const endDayOfWeek = this.adapter.day(end);\n    const expectedEndDay = (this.firstDayOfWeek + 6) % 7;\n    if (endDayOfWeek !== expectedEndDay) {\n      const diff = (expectedEndDay - endDayOfWeek + 7) % 7;\n      if (diff > 0) {\n        end = this.adapter.add(end, diff, \"day\");\n      }\n    }\n\n    const weeks: Array<Array<GridCell<T>>> = [];\n    let curr = start;\n\n    while (\n      this.adapter.isBefore(curr, end) ||\n      this.adapter.isSame(curr, end, \"day\")\n    ) {\n      const days: Array<GridCell<T>> = [];\n\n      for (let i = 0; i < 7; i++) {\n        const dayOfWeek = this.adapter.day(curr);\n        const isWeekend = dayOfWeek === 0 || dayOfWeek === 6; // Sunday or Saturday\n\n        // Build filter context\n        const context: DayFilterContext = {\n          isWeekend,\n          dayOfWeek,\n          isToday: this.adapter.isSame(curr, today, \"day\"),\n          isThisMonth: this.adapter.isSame(curr, currentDate, \"month\"),\n        };\n\n        // Determine if this day should be included\n        let shouldInclude = true;\n        if (dayFilter) {\n          // Use dayFilter if provided (takes precedence)\n          const result = dayFilter(curr, context);\n          shouldInclude = typeof result === \"boolean\" ? result : result.visible;\n        } else if (!this.showWeekends && isWeekend) {\n          // Fallback to showWeekends for backward compatibility\n          shouldInclude = false;\n        }\n\n        if (shouldInclude) {\n          days.push({\n            date: curr,\n            dateStr: this.adapter.format(curr, this.dateFormats.date),\n          });\n        }\n\n        curr = this.adapter.add(curr, 1, \"day\");\n      }\n\n      // Only add week if it has days (could be empty if all days filtered)\n      if (days.length > 0) {\n        weeks.push(days);\n      }\n    }\n\n    return weeks;\n  }\n\n  /**\n   * Calculate layout for events within visible days\n   * Handles multi-day events, event overlapping, slot allocation, and event segmentation\n   *\n   * When events span across filtered (hidden) days, they are split into multiple segments.\n   * Each segment represents a contiguous visible portion of the event.\n   *\n   * @param events - All calendar events\n   * @param visibleDays - Array of visible days with their column indices\n   * @returns Array of MonthLayoutItem with positioning information (may include segmented events)\n   */\n  calculateLayoutWithVisibleDays(\n    events: CalendarEvent[],\n    visibleDays: VisibleDay<T>[],\n  ): MonthLayoutItem[] {\n    if (visibleDays.length === 0) {\n      return [];\n    }\n\n    const firstVisibleDate = visibleDays[0]!.date;\n    const lastVisibleDate = visibleDays[visibleDays.length - 1]!.date;\n\n    // Filter events that overlap with the visible date range\n    const rangeEvents = events.filter((e) => {\n      const eventStart = this.adapter.startOf(\n        this.adapter.parse(e.start),\n        \"day\",\n      );\n      const eventEnd = this.adapter.startOf(this.adapter.parse(e.end), \"day\");\n\n      return (\n        !this.adapter.isAfter(eventStart, lastVisibleDate, \"day\") &&\n        !this.adapter.isBefore(eventEnd, firstVisibleDate, \"day\")\n      );\n    });\n\n    // Calculate segments for each event\n    const visualItems: Array<MonthLayoutItem & { sortKey: number }> = [];\n\n    for (const event of rangeEvents) {\n      const eventStart = this.adapter.startOf(\n        this.adapter.parse(event.start),\n        \"day\",\n      );\n      const eventEnd = this.adapter.startOf(\n        this.adapter.parse(event.end),\n        \"day\",\n      );\n\n      // Find all visible days that this event covers\n      // Exclude disabled days (events should not be displayed on disabled days)\n      const coveredDays: Array<{ colIndex: number; date: T; dateStr: string }> =\n        [];\n\n      for (const day of visibleDays) {\n        // Skip disabled days - events should not appear on them\n        if (day.disabled) {\n          continue;\n        }\n\n        if (\n          !this.adapter.isBefore(day.date, eventStart, \"day\") &&\n          !this.adapter.isAfter(day.date, eventEnd, \"day\")\n        ) {\n          coveredDays.push({\n            colIndex: day.colIndex,\n            date: day.date,\n            dateStr: day.dateStr,\n          });\n        }\n      }\n\n      if (coveredDays.length === 0) {\n        continue; // Event doesn't cover any visible days\n      }\n\n      // Group consecutive covered days into segments\n      // IMPORTANT: Consecutive means actual calendar dates differ by exactly 1 day,\n      // NOT column indices. This ensures events are split when hidden days create gaps.\n      const segments: Array<{\n        startIdx: number;\n        span: number;\n        isEventStart: boolean;\n        isEventEnd: boolean;\n      }> = [];\n\n      let segmentStart = coveredDays[0]!;\n      let prevDay = segmentStart;\n      let segmentSpan = 1;\n\n      for (let i = 1; i < coveredDays.length; i++) {\n        const current = coveredDays[i]!;\n\n        // Check if this day is consecutive in actual calendar (differs by exactly 1 day)\n        const nextExpectedDate = this.adapter.add(prevDay.date, 1, \"day\");\n        const isConsecutive = this.adapter.isSame(\n          current.date,\n          nextExpectedDate,\n          \"day\",\n        );\n\n        if (isConsecutive) {\n          segmentSpan++;\n          prevDay = current;\n        } else {\n          // Non-consecutive: save current segment and start a new one\n          const isEventStart = this.adapter.isSame(\n            segmentStart.date,\n            eventStart,\n            \"day\",\n          );\n          const isEventEnd = this.adapter.isSame(prevDay.date, eventEnd, \"day\");\n\n          segments.push({\n            startIdx: segmentStart.colIndex,\n            span: segmentSpan,\n            isEventStart,\n            isEventEnd,\n          });\n\n          // Start new segment\n          segmentStart = current;\n          prevDay = current;\n          segmentSpan = 1;\n        }\n      }\n\n      // Don't forget the last segment\n      const isEventStartFinal = this.adapter.isSame(\n        segmentStart.date,\n        eventStart,\n        \"day\",\n      );\n      const isEventEndFinal = this.adapter.isSame(\n        prevDay.date,\n        eventEnd,\n        \"day\",\n      );\n\n      segments.push({\n        startIdx: segmentStart.colIndex,\n        span: segmentSpan,\n        isEventStart: isEventStartFinal,\n        isEventEnd: isEventEndFinal,\n      });\n\n      // Create layout items for each segment\n      const totalSegments = segments.length;\n      segments.forEach((seg, idx) => {\n        const item: MonthLayoutItem & { sortKey: number } = {\n          event,\n          startIdx: seg.startIdx,\n          span: seg.span,\n          slot: 0, // Will be calculated below\n          isStart: seg.isEventStart,\n          isEnd: seg.isEventEnd,\n          sortKey: seg.startIdx * 1000 - seg.span,\n          // Add segmentation info only if event was split\n          ...(totalSegments > 1 ? { segmentIndex: idx, totalSegments } : {}),\n        };\n        visualItems.push(item);\n      });\n    }\n\n    // Sort by start index, then by span (descending)\n    visualItems.sort((a, b) => a.sortKey - b.sortKey);\n\n    // Allocate vertical slots to prevent overlap\n    const slots: number[] = [];\n\n    for (const item of visualItems) {\n      let slotIdx = 0;\n\n      // Find first available slot\n      while (true) {\n        const slotEnd = slots[slotIdx];\n        if (slotEnd === undefined || slotEnd < item.startIdx) {\n          slots[slotIdx] = item.startIdx + item.span - 1;\n          item.slot = slotIdx;\n          break;\n        }\n        slotIdx++;\n      }\n    }\n\n    // Remove sortKey from result\n    return visualItems.map(({ sortKey: _sortKey, ...item }) => item);\n  }\n\n  /**\n   * Calculate layout for events within a week (legacy API for backward compatibility)\n   * Handles multi-day events, event overlapping, and slot allocation\n   *\n   * @deprecated Use calculateLayoutWithVisibleDays for proper dayFilter support\n   * @param events - All calendar events\n   * @param weekStart - Start date of the week\n   * @param weekEnd - End date of the week\n   * @returns Array of MonthLayoutItem with positioning information\n   */\n  calculateLayout(\n    events: CalendarEvent[],\n    weekStart: T,\n    weekEnd: T,\n  ): MonthLayoutItem[] {\n    // Build visible days array from weekStart to weekEnd\n    const visibleDays: VisibleDay<T>[] = [];\n    let curr = weekStart;\n    let colIndex = 0;\n\n    while (\n      this.adapter.isBefore(curr, weekEnd, \"day\") ||\n      this.adapter.isSame(curr, weekEnd, \"day\")\n    ) {\n      const dayOfWeek = this.adapter.day(curr);\n      const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;\n\n      // Apply showWeekends filter\n      if (this.showWeekends || !isWeekend) {\n        visibleDays.push({\n          date: curr,\n          dateStr: this.adapter.format(curr, this.dateFormats.date),\n          colIndex,\n        });\n        colIndex++;\n      }\n\n      curr = this.adapter.add(curr, 1, \"day\");\n    }\n\n    return this.calculateLayoutWithVisibleDays(events, visibleDays);\n  }\n\n  /**\n   * Get the number of weeks in a month grid\n   *\n   * @param currentDate - The current date\n   * @returns Number of weeks (4-6)\n   */\n  getWeekCount(currentDate: T): number {\n    return this.generateGrid(currentDate).length;\n  }\n}\n","/**\n * Month view renderer\n */\nimport type {\n  DateAdapter,\n  CalendarEvent,\n  ThemeConfig,\n  MonthLayoutItem,\n  DateFormatConfig,\n  DayFilterContext,\n  DayFilterResult,\n  DayRenderConfig,\n  VisibleDay,\n  EventRenderContext,\n} from \"../types\";\nimport type { MonthEngine } from \"../engines/MonthEngine\";\nimport type { DragController } from \"../core/DragController\";\nimport { createElement, clearElement } from \"../utils/dom\";\n\n/**\n * Renders the month view calendar\n */\nexport class MonthRenderer<T> {\n  /** Currently active popover element */\n  private activePopover: HTMLElement | null = null;\n  /** Bound handler for closing popover on outside click */\n  private popoverCloseHandler: ((e: MouseEvent) => void) | null = null;\n\n  constructor(\n    private engine: MonthEngine<T>,\n    private adapter: DateAdapter<T>,\n    // theme parameter kept for API consistency\n    // Theme values now applied via CSS variables (--tg-primary-color, etc.)\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    _theme: Required<ThemeConfig> & {\n      fontSize: Required<NonNullable<ThemeConfig[\"fontSize\"]>>;\n    },\n    private showEventCounts: boolean = false,\n    // dateFormats parameter kept for API consistency with other renderers\n    // Currently unused as formats are handled by engines/adapters\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    _dateFormats: Required<DateFormatConfig>,\n    private onRenderDateCell?: (\n      ctx: import(\"../types\").DateCellContext,\n    ) => void,\n    private onStyleEvent?: (\n      event: CalendarEvent,\n    ) => import(\"../types\").EventStyle,\n    private maxEventsPerRow?: number,\n    private onRenderMoreEventsPopover?: (\n      events: CalendarEvent[],\n      date: Date,\n      anchorEl: HTMLElement,\n      defaultRender: () => void,\n    ) => void,\n    private onRenderEvent?: (ctx: EventRenderContext) => void,\n  ) {}\n\n  /**\n   * Render the complete month view\n   */\n  render(\n    container: HTMLElement,\n    currentDate: T,\n    events: CalendarEvent[],\n    dragController: DragController<T>,\n    renderCallback: () => void,\n    onEventClick?: (event: CalendarEvent) => void,\n    dayFilter?: (date: T, context: DayFilterContext) => DayFilterResult,\n  ): void {\n    // Close any existing popover before re-rendering\n    this.closePopover();\n\n    clearElement(container);\n\n    // Generate grid with dayFilter\n    const weeks = this.engine.generateGrid(currentDate, dayFilter);\n\n    // Render header with day names (dynamically adjusts to number of visible columns)\n    const header = this.renderHeader(weeks[0]?.length || 7);\n    container.appendChild(header);\n\n    // Render body with weeks\n    const body = createElement(\"div\", \"tg-month-body\");\n\n    for (const weekDays of weeks) {\n      const row = this.renderWeekRow(\n        weekDays,\n        currentDate,\n        events,\n        dragController,\n        renderCallback,\n        onEventClick,\n        dayFilter,\n      );\n      body.appendChild(row);\n    }\n\n    container.appendChild(body);\n  }\n\n  // ==========================================================================\n  // Private Methods\n  // ==========================================================================\n\n  private renderHeader(columnCount: number): HTMLElement {\n    const header = createElement(\"div\", \"tg-month-header\");\n    // Weekday labels: Sunday through Saturday\n    const allDayNames = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n\n    // Generate day names based on firstDayOfWeek and actual column count\n    const dayNames: string[] = [];\n    const firstDay = (this.engine as any).firstDayOfWeek || 0;\n\n    // Generate labels for the actual number of visible columns\n    for (let i = 0; i < columnCount; i++) {\n      const dayIndex = (firstDay + i) % 7;\n      dayNames.push(allDayNames[dayIndex]!);\n    }\n\n    // Apply dynamic grid layout via CSS custom property\n    header.style.setProperty(\"--tg-grid-columns\", String(dayNames.length));\n    header.style.gridTemplateColumns = `repeat(var(--tg-grid-columns), 1fr)`;\n\n    for (const name of dayNames) {\n      const cell = createElement(\"div\", \"tg-month-header-cell\");\n      cell.textContent = name;\n      header.appendChild(cell);\n    }\n\n    return header;\n  }\n\n  private renderWeekRow(\n    weekDays: Array<{ date: T; dateStr: string }>,\n    currentDate: T,\n    events: CalendarEvent[],\n    dragController: DragController<T>,\n    renderCallback: () => void,\n    onEventClick?: (event: CalendarEvent) => void,\n    dayFilter?: (date: T, context: DayFilterContext) => DayFilterResult,\n  ): HTMLElement {\n    const row = createElement(\"div\", \"tg-month-row\");\n    row.dataset[\"date\"] = weekDays[0]!.dateStr;\n    const columnCount = weekDays.length;\n\n    // Apply dynamic grid layout via CSS custom property\n    row.style.setProperty(\"--tg-grid-columns\", String(weekDays.length));\n    row.style.gridTemplateColumns = `repeat(var(--tg-grid-columns), 1fr)`;\n\n    // Build VisibleDay array for layout calculation\n    // This enables proper event segmentation when days are filtered\n    // Also check dayFilter for disabled state to exclude events from disabled days\n    const visibleDays: VisibleDay<T>[] = weekDays.map((day, index) => {\n      let isDisabled = false;\n\n      if (dayFilter) {\n        const dayOfWeek = this.adapter.day(day.date);\n        const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;\n        const today = this.adapter.create();\n        const context: DayFilterContext = {\n          isWeekend,\n          dayOfWeek,\n          isToday: this.adapter.isSame(day.date, today, \"day\"),\n          isThisMonth: this.adapter.isSame(day.date, currentDate, \"month\"),\n        };\n\n        const result = dayFilter(day.date, context);\n        if (typeof result === \"object\" && result.disabled) {\n          isDisabled = true;\n        }\n      }\n\n      return {\n        date: day.date,\n        dateStr: day.dateStr,\n        colIndex: index,\n        disabled: isDisabled,\n      };\n    });\n\n    // Calculate layout with visible days support for event segmentation\n    const layout = this.engine.calculateLayoutWithVisibleDays(\n      events,\n      visibleDays,\n    );\n\n    // Split layout into visible and hidden events\n    const visibleLayout =\n      this.maxEventsPerRow !== undefined\n        ? layout.filter((item) => item.slot < this.maxEventsPerRow!)\n        : layout;\n\n    // Group hidden events by column index for \"+N more\" indicators\n    const hiddenEventsByColumn: Map<number, CalendarEvent[]> = new Map();\n    if (this.maxEventsPerRow !== undefined) {\n      for (const item of layout) {\n        if (item.slot >= this.maxEventsPerRow) {\n          // For each column the event spans, add it to hidden events\n          for (\n            let colIdx = item.startIdx;\n            colIdx < item.startIdx + item.span;\n            colIdx++\n          ) {\n            if (!hiddenEventsByColumn.has(colIdx)) {\n              hiddenEventsByColumn.set(colIdx, []);\n            }\n            // Avoid duplicates\n            const arr = hiddenEventsByColumn.get(colIdx)!;\n            if (!arr.find((e) => e.id === item.event.id)) {\n              arr.push(item.event);\n            }\n          }\n        }\n      }\n    }\n\n    // Calculate minimum row height based on visible events\n    // The actual height will be determined by flex: 1 to fill container evenly\n    const effectiveMaxSlot = visibleLayout.reduce(\n      (max, item) => Math.max(max, item.slot),\n      -1,\n    );\n    const baseHeight = 80; // Base height for date numbers and padding\n    let eventAreaHeight =\n      effectiveMaxSlot >= 0 ? 26 + (effectiveMaxSlot + 1) * 28 : 0;\n\n    // Add space for \"+N more\" indicator if there are hidden events\n    if (hiddenEventsByColumn.size > 0) {\n      eventAreaHeight += 24; // Height for the \"+N more\" row\n    }\n\n    const minHeight = Math.max(baseHeight, eventAreaHeight + 8);\n\n    // Set minimum row height via CSS custom property\n    // Rows will grow beyond this if container has extra space (flex: 1)\n    row.style.setProperty(\"--tg-row-min-height\", `${minHeight}px`);\n\n    // Pre-parse event times and group by date for O(1) lookup in renderDateCell\n    // This avoids O(days * events) parsing overhead\n    const eventsByDateStr: Map<string, CalendarEvent[]> = new Map();\n    for (const event of events) {\n      const eventStart = this.adapter.parse(event.start);\n      const eventEnd = this.adapter.parse(event.end);\n      // Check which days in this week the event covers\n      for (const day of weekDays) {\n        if (\n          !this.adapter.isBefore(eventEnd, day.date) &&\n          !this.adapter.isAfter(eventStart, day.date)\n        ) {\n          if (!eventsByDateStr.has(day.dateStr)) {\n            eventsByDateStr.set(day.dateStr, []);\n          }\n          eventsByDateStr.get(day.dateStr)!.push(event);\n        }\n      }\n    }\n\n    // Render date cells\n    for (const day of weekDays) {\n      const dayEvents = eventsByDateStr.get(day.dateStr) || [];\n      const cell = this.renderDateCell(day, currentDate, dayEvents, dayFilter);\n      row.appendChild(cell);\n    }\n\n    // Render visible event bars\n    for (const item of visibleLayout) {\n      const eventEl = this.renderEventBar(\n        item,\n        columnCount,\n        dragController,\n        renderCallback,\n        onEventClick,\n      );\n      row.appendChild(eventEl);\n    }\n\n    // Render \"+N more\" indicators for each column with hidden events\n    for (const [colIdx, hiddenEvents] of hiddenEventsByColumn) {\n      const moreEl = this.renderMoreIndicator(\n        colIdx,\n        hiddenEvents,\n        weekDays[colIdx]!,\n        columnCount,\n        effectiveMaxSlot,\n        onEventClick,\n      );\n      row.appendChild(moreEl);\n    }\n\n    return row;\n  }\n\n  /**\n   * Render a single date cell\n   * @param day - Day information\n   * @param currentDate - Current date for month comparison\n   * @param dayEvents - Pre-filtered events for this day (already parsed and filtered in renderWeekRow)\n   * @param dayFilter - Optional day filter function\n   */\n  private renderDateCell(\n    day: { date: T; dateStr: string },\n    currentDate: T,\n    dayEvents: CalendarEvent[],\n    dayFilter?: (date: T, context: DayFilterContext) => DayFilterResult,\n  ): HTMLElement {\n    const cell = createElement(\"div\", \"tg-month-cell\");\n\n    const dateNum = createElement(\"div\", \"tg-date-number\");\n    dateNum.textContent = String(this.adapter.date(day.date));\n\n    const today = this.adapter.create();\n    const isToday = this.adapter.isSame(day.date, today, \"day\");\n    const isPastDue = this.adapter.isBefore(day.date, today, \"day\");\n    const isFuture = this.adapter.isAfter(day.date, today, \"day\");\n    const isThisMonth =\n      this.adapter.month(day.date) === this.adapter.month(currentDate);\n\n    // Build filter context\n    const dayOfWeek = this.adapter.day(day.date);\n    const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;\n    const context: DayFilterContext = {\n      isWeekend,\n      dayOfWeek,\n      isToday,\n      isThisMonth,\n    };\n\n    // Apply dayFilter configuration if provided\n    if (dayFilter) {\n      const result = dayFilter(day.date, context);\n      if (typeof result === \"object\") {\n        const config = result as DayRenderConfig;\n        // Apply custom className\n        if (config.className) {\n          cell.classList.add(config.className);\n        }\n        // Apply custom inline styles\n        if (config.style) {\n          Object.assign(cell.style, config.style);\n        }\n        // Apply disabled state (styles defined in CSS)\n        if (config.disabled) {\n          cell.classList.add(\"tg-disabled\");\n        }\n      }\n    }\n\n    // Style based on month\n    if (isThisMonth) {\n      dateNum.classList.add(\"tg-current-month\");\n    } else {\n      dateNum.classList.add(\"tg-other-month\");\n    }\n\n    // Highlight today\n    if (isToday) {\n      dateNum.classList.add(\"tg-today\");\n    }\n\n    cell.appendChild(dateNum);\n\n    // Show event count badge if enabled\n    // Events are pre-filtered by renderWeekRow for performance\n    // Styles applied via CSS class, theme color via CSS variable --tg-primary-color\n    if (this.showEventCounts && dayEvents.length > 0) {\n      const badge = createElement(\"div\", \"tg-event-count-badge\");\n      badge.textContent = dayEvents.length.toString();\n      cell.appendChild(badge);\n    }\n\n    // Call custom render hook if provided\n    if (this.onRenderDateCell) {\n      // Convert T to Date using adapter API (avoids format string parsing issues)\n      const dateObj = new Date(\n        this.adapter.year(day.date),\n        this.adapter.month(day.date),\n        this.adapter.date(day.date),\n      );\n      this.onRenderDateCell({\n        date: dateObj,\n        events: dayEvents,\n        cellEl: cell,\n        isToday,\n        isPastDue,\n        isFuture,\n        isThisMonth,\n      });\n    }\n\n    return cell;\n  }\n\n  private renderEventBar(\n    item: MonthLayoutItem,\n    columnCount: number,\n    dragController: DragController<T>,\n    renderCallback: () => void,\n    onEventClick?: (event: CalendarEvent) => void,\n  ): HTMLElement {\n    const el = createElement(\"div\", \"tg-event-base tg-event-bar\");\n    el.dataset[\"eid\"] = item.event.id;\n\n    // Add segmentation data attributes and classes for styling\n    if (item.segmentIndex !== undefined && item.totalSegments !== undefined) {\n      el.dataset[\"segmentIndex\"] = String(item.segmentIndex);\n      el.dataset[\"totalSegments\"] = String(item.totalSegments);\n      el.classList.add(\"tg-event-segmented\");\n\n      // Add specific classes for first/last segments\n      if (item.segmentIndex === 0) {\n        el.classList.add(\"tg-event-segment-first\");\n      }\n      if (item.segmentIndex === item.totalSegments - 1) {\n        el.classList.add(\"tg-event-segment-last\");\n      }\n      // Middle segments\n      if (item.segmentIndex > 0 && item.segmentIndex < item.totalSegments - 1) {\n        el.classList.add(\"tg-event-segment-middle\");\n      }\n    }\n\n    // Apply custom styling if hook is provided\n    let bgColor = item.event.color || \"#3b82f6\";\n    let customOpacity: number | undefined;\n\n    if (this.onStyleEvent) {\n      const style = this.onStyleEvent(item.event);\n      if (style.className) {\n        el.classList.add(style.className);\n      }\n      if (style.color) {\n        bgColor = style.color;\n      }\n      if (style.opacity !== undefined) {\n        customOpacity = style.opacity;\n      }\n    }\n\n    // Calculate column width percentage based on actual number of visible columns\n    const colWidth = 100 / columnCount;\n\n    // Calculate position values\n    const xOffset = item.startIdx * colWidth;\n    const yOffset = 26 + item.slot * 28;\n\n    // Use left/top for correct positioning relative to parent container\n    // (transform with % is relative to element's own width, causing misalignment)\n    el.style.left = `calc(${xOffset}% + 2px)`;\n    el.style.top = `${yOffset}px`;\n    el.style.width = `calc(${item.span * colWidth}% - 4px)`;\n    el.style.backgroundColor = bgColor;\n\n    if (customOpacity !== undefined) {\n      el.style.opacity = customOpacity.toString();\n    }\n\n    // Default render function for event content\n    const defaultRender = () => {\n      el.textContent = item.event.title;\n    };\n\n    // Use custom render hook if provided, otherwise use default\n    if (this.onRenderEvent) {\n      const ctx: EventRenderContext = {\n        event: item.event,\n        el,\n        viewType: \"month\",\n        isAllDay: true, // Month view events are always rendered as all-day spans\n        isStart: item.isStart,\n        isEnd: item.isEnd,\n        defaultRender,\n      };\n      // Only add segment properties if they exist\n      if (item.segmentIndex !== undefined) {\n        ctx.segmentIndex = item.segmentIndex;\n      }\n      if (item.totalSegments !== undefined) {\n        ctx.totalSegments = item.totalSegments;\n      }\n      this.onRenderEvent(ctx);\n    } else {\n      defaultRender();\n    }\n\n    // Add resize handles\n    if (item.isStart) {\n      const leftHandle = createElement(\n        \"div\",\n        \"tg-resize-handle tg-resize-h tg-left\",\n      );\n      el.appendChild(leftHandle);\n    }\n\n    if (item.isEnd) {\n      const rightHandle = createElement(\n        \"div\",\n        \"tg-resize-handle tg-resize-h tg-right\",\n      );\n      el.appendChild(rightHandle);\n    }\n\n    // Event click handler\n    if (onEventClick) {\n      el.addEventListener(\"click\", (e) => {\n        e.stopPropagation();\n        onEventClick(item.event);\n      });\n    }\n\n    // Initialize drag\n    dragController.initMonthDrag(el, item.event, renderCallback);\n\n    return el;\n  }\n\n  /**\n   * Render the \"+N more\" indicator for a column\n   */\n  private renderMoreIndicator(\n    colIdx: number,\n    hiddenEvents: CalendarEvent[],\n    day: { date: T; dateStr: string },\n    columnCount: number,\n    visibleMaxSlot: number,\n    onEventClick?: (event: CalendarEvent) => void,\n  ): HTMLElement {\n    const el = createElement(\"div\", \"tg-more-indicator\");\n    el.textContent = `+${hiddenEvents.length} more`;\n\n    // Calculate position\n    const colWidth = 100 / columnCount;\n    const xOffset = colIdx * colWidth;\n    const yOffset = 26 + (visibleMaxSlot + 1) * 28 + 2; // Position below visible events\n\n    el.style.left = `calc(${xOffset}% + 2px)`;\n    el.style.top = `${yOffset}px`;\n    el.style.width = `calc(${colWidth}% - 4px)`;\n\n    // Convert adapter date to native Date\n    const dateObj = new Date(\n      this.adapter.year(day.date),\n      this.adapter.month(day.date),\n      this.adapter.date(day.date),\n    );\n\n    // Click handler for popover\n    el.addEventListener(\"click\", (e) => {\n      e.stopPropagation();\n\n      const defaultRender = () => {\n        this.renderDefaultPopover(el, hiddenEvents, dateObj, onEventClick);\n      };\n\n      if (this.onRenderMoreEventsPopover) {\n        this.onRenderMoreEventsPopover(\n          hiddenEvents,\n          dateObj,\n          el,\n          defaultRender,\n        );\n      } else {\n        defaultRender();\n      }\n    });\n\n    return el;\n  }\n\n  /**\n   * Render the default popover for hidden events\n   */\n  private renderDefaultPopover(\n    anchorEl: HTMLElement,\n    events: CalendarEvent[],\n    date: Date,\n    onEventClick?: (event: CalendarEvent) => void,\n  ): void {\n    // Close any existing popover\n    this.closePopover();\n\n    // Create popover container\n    const popover = createElement(\"div\", \"tg-more-popover\");\n    this.activePopover = popover;\n\n    // Header with date\n    const header = createElement(\"div\", \"tg-more-popover-header\");\n    header.textContent = date.toLocaleDateString(undefined, {\n      weekday: \"short\",\n      month: \"short\",\n      day: \"numeric\",\n    });\n    popover.appendChild(header);\n\n    // Event list\n    const list = createElement(\"div\", \"tg-more-popover-list\");\n    for (const event of events) {\n      const item = createElement(\"div\", \"tg-more-popover-item\");\n\n      // Apply custom styling if hook is provided\n      let dotColor = event.color || \"#3b82f6\";\n      let customOpacity: number | undefined;\n\n      if (this.onStyleEvent) {\n        const style = this.onStyleEvent(event);\n        if (style.className) {\n          item.classList.add(style.className);\n        }\n        if (style.color) {\n          dotColor = style.color;\n        }\n        if (style.opacity !== undefined) {\n          customOpacity = style.opacity;\n        }\n      }\n\n      // Color indicator\n      const colorDot = createElement(\"span\", \"tg-more-popover-dot\");\n      colorDot.style.backgroundColor = dotColor;\n      item.appendChild(colorDot);\n\n      // Title\n      const title = createElement(\"span\", \"tg-more-popover-title\");\n      title.textContent = event.title;\n      item.appendChild(title);\n\n      // Apply opacity to the whole item if specified\n      if (customOpacity !== undefined) {\n        item.style.opacity = customOpacity.toString();\n      }\n\n      // Click handler\n      if (onEventClick) {\n        item.addEventListener(\"click\", (e) => {\n          e.stopPropagation();\n          this.closePopover();\n          onEventClick(event);\n        });\n        item.style.cursor = \"pointer\";\n      }\n\n      list.appendChild(item);\n    }\n    popover.appendChild(list);\n\n    // Position the popover\n    document.body.appendChild(popover);\n    this.positionPopover(popover, anchorEl);\n\n    // Set up close handler\n    this.popoverCloseHandler = (e: MouseEvent) => {\n      if (!popover.contains(e.target as Node) && e.target !== anchorEl) {\n        this.closePopover();\n      }\n    };\n\n    // Delay adding the click listener to prevent immediate close\n    setTimeout(() => {\n      document.addEventListener(\"click\", this.popoverCloseHandler!);\n    }, 0);\n  }\n\n  /**\n   * Position the popover relative to the anchor element\n   */\n  private positionPopover(popover: HTMLElement, anchorEl: HTMLElement): void {\n    const anchorRect = anchorEl.getBoundingClientRect();\n    const popoverRect = popover.getBoundingClientRect();\n    const viewportHeight = window.innerHeight;\n    const viewportWidth = window.innerWidth;\n\n    // Default: position below the anchor\n    let top = anchorRect.bottom + 4;\n    let left = anchorRect.left;\n\n    // Adjust if popover would go off the bottom\n    if (top + popoverRect.height > viewportHeight - 8) {\n      top = anchorRect.top - popoverRect.height - 4;\n    }\n\n    // Adjust if popover would go off the right\n    if (left + popoverRect.width > viewportWidth - 8) {\n      left = viewportWidth - popoverRect.width - 8;\n    }\n\n    // Ensure popover doesn't go off the left\n    if (left < 8) {\n      left = 8;\n    }\n\n    popover.style.top = `${top}px`;\n    popover.style.left = `${left}px`;\n  }\n\n  /**\n   * Close the active popover\n   */\n  private closePopover(): void {\n    if (this.activePopover) {\n      this.activePopover.remove();\n      this.activePopover = null;\n    }\n\n    if (this.popoverCloseHandler) {\n      document.removeEventListener(\"click\", this.popoverCloseHandler);\n      this.popoverCloseHandler = null;\n    }\n  }\n}\n","/**\n * MonthView - Built-in month view implementation\n *\n * Extends BaseView and wraps the existing MonthRenderer\n * for backward compatibility while supporting the new view system.\n */\nimport type {\n  CalendarEvent,\n  DayFilterContext,\n  DayFilterResult,\n} from \"../types\";\nimport { BaseView, type ViewMeta, type ViewRenderOptions } from \"./BaseView\";\nimport { MonthEngine } from \"../engines/MonthEngine\";\nimport { MonthRenderer } from \"../renderers/MonthRenderer\";\n\n/**\n * Month view displaying a calendar grid\n *\n * Features:\n * - Full month grid layout\n * - Multi-day event spanning\n * - Day filtering support\n * - Event count badges (optional)\n * - \"+N more\" popover for overflow events\n */\nexport class MonthView<T = unknown> extends BaseView<T> {\n  static meta: ViewMeta = {\n    type: \"month\",\n    label: \"Month\",\n    shortLabel: \"M\",\n    order: 10,\n  };\n\n  private engine!: MonthEngine<T>;\n  private renderer!: MonthRenderer<T>;\n\n  /**\n   * Initialize the view with context and create engine/renderer\n   */\n  override init(context: typeof this.context): void {\n    super.init(context);\n\n    // Create engine\n    this.engine = new MonthEngine<T>(\n      this.context.adapter,\n      this.context.config.view.firstDayOfWeek,\n      this.context.config.view.showWeekends,\n      this.context.config.dateFormats,\n    );\n\n    // Create renderer\n    this.renderer = new MonthRenderer<T>(\n      this.engine,\n      this.context.adapter,\n      this.context.config.theme,\n      this.context.config.showEventCounts,\n      this.context.config.dateFormats,\n      this.context.config.onRenderDateCell,\n      this.context.config.onStyleEvent,\n      this.context.config.view.maxEventsPerRow,\n      this.context.config.onRenderMoreEventsPopover,\n      this.context.config.onRenderEvent,\n    );\n  }\n\n  /**\n   * Render the month view\n   */\n  render(\n    container: HTMLElement,\n    events: CalendarEvent[],\n    _options?: ViewRenderOptions,\n  ): void {\n    this.renderer.render(\n      container,\n      this.context.currentDate,\n      events,\n      this.context.dragController,\n      this.context.requestRender,\n      this.context.config.onEventClick,\n      this.context.config.view.dayFilter as\n        | ((date: T, context: DayFilterContext) => DayFilterResult)\n        | undefined,\n    );\n  }\n\n  /**\n   * Month view navigates by month\n   */\n  override getNavigationUnit(): \"month\" {\n    return \"month\";\n  }\n\n  /**\n   * Get the month engine for advanced usage\n   */\n  getEngine(): MonthEngine<T> {\n    return this.engine;\n  }\n\n  /**\n   * Get the month renderer for advanced usage\n   */\n  getRenderer(): MonthRenderer<T> {\n    return this.renderer;\n  }\n}\n","/**\n * Time view layout engine\n * Handles column generation and event layout calculation for week/day views\n */\nimport type {\n  DateAdapter,\n  CalendarEvent,\n  TimeLayoutItem,\n  TimeColumn,\n  ViewType,\n  DateFormatConfig,\n  DayFilterContext,\n  DayFilterResult,\n  TimeFilterResult,\n  TimeSlotConfig,\n  AllDayLayoutItem,\n} from \"../types\";\n\n/**\n * Internal event representation with calculated geometry\n */\ninterface EventGeometry {\n  event: CalendarEvent;\n  top: number;\n  height: number;\n  startMin: number;\n  endMin: number;\n  colIndex: number;\n  widthPercent: number;\n  leftPercent: number;\n  /** Whether this segment is the start of the original event */\n  isStart: boolean;\n  /** Whether this segment is the end of the original event */\n  isEnd: boolean;\n  /** Segment index for cross-midnight events (0-based) */\n  segmentIndex?: number;\n  /** Total segments for cross-midnight events */\n  totalSegments?: number;\n}\n\n/**\n * Engine for calculating time view (week/day) layouts\n */\nexport class TimeEngine<T> {\n  private cellHeight: number;\n\n  /**\n   * @param adapter - Date adapter instance\n   * @param cellHeight - Height of each hour cell in pixels (default: 60)\n   * @param showWeekends - Whether to show weekend columns (default: true)\n   * @param firstDayOfWeek - First day of week: 0 = Sunday, 1 = Monday (default: 0)\n   * @param dateFormats - Date format configuration\n   */\n  constructor(\n    private adapter: DateAdapter<T>,\n    cellHeight: number = 60,\n    private showWeekends: boolean = true,\n    private firstDayOfWeek: number = 0,\n    private dateFormats: Required<DateFormatConfig>,\n  ) {\n    this.cellHeight = cellHeight;\n  }\n\n  /**\n   * Generate columns for time view\n   * Returns 1 column for day view, up to 7 columns for week view\n   *\n   * @param currentDate - The current date\n   * @param viewType - 'day' or 'week'\n   * @param dayFilter - Optional filter function to control which days are included\n   * @returns Array of TimeColumn objects for visible days\n   */\n  generateColumns(\n    currentDate: T,\n    viewType: ViewType,\n    dayFilter?: (date: T, context: DayFilterContext) => DayFilterResult,\n  ): Array<TimeColumn<T>> {\n    const columns: Array<TimeColumn<T>> = [];\n    const today = this.adapter.create();\n\n    if (viewType === \"day\") {\n      // Day view - always show single day (filter doesn't apply to single day view)\n      columns.push({\n        date: currentDate,\n        dateStr: this.adapter.format(currentDate, this.dateFormats.date),\n      });\n    } else {\n      // Week view - generate columns starting from configured first day of week\n      let weekStart = this.adapter.startOf(currentDate, \"week\");\n\n      // Adjust to firstDayOfWeek\n      const currentDayOfWeek = this.adapter.day(weekStart);\n      if (currentDayOfWeek !== this.firstDayOfWeek) {\n        let diff = this.firstDayOfWeek - currentDayOfWeek;\n        if (diff > 0) {\n          // firstDayOfWeek is later in the week, move forward\n          weekStart = this.adapter.add(weekStart, diff, \"day\");\n        } else {\n          // firstDayOfWeek is earlier, move backward\n          weekStart = this.adapter.add(weekStart, diff, \"day\");\n        }\n      }\n\n      let curr = weekStart;\n      for (let i = 0; i < 7; i++) {\n        const dayOfWeek = this.adapter.day(curr);\n        const isWeekend = dayOfWeek === 0 || dayOfWeek === 6; // Sunday or Saturday\n\n        // Build filter context\n        const context: DayFilterContext = {\n          isWeekend,\n          dayOfWeek,\n          isToday: this.adapter.isSame(curr, today, \"day\"),\n          isThisMonth: this.adapter.isSame(curr, currentDate, \"month\"),\n        };\n\n        // Determine if this day should be included\n        let shouldInclude = true;\n        if (dayFilter) {\n          // Use dayFilter if provided (takes precedence)\n          const result = dayFilter(curr, context);\n          shouldInclude = typeof result === \"boolean\" ? result : result.visible;\n        } else if (!this.showWeekends && isWeekend) {\n          // Fallback to showWeekends for backward compatibility\n          shouldInclude = false;\n        }\n\n        if (shouldInclude) {\n          columns.push({\n            date: curr,\n            dateStr: this.adapter.format(curr, this.dateFormats.date),\n          });\n        }\n\n        curr = this.adapter.add(curr, 1, \"day\");\n      }\n    }\n\n    return columns;\n  }\n\n  /**\n   * Generate time slots for time axis\n   * Returns time slots (hours) that should be displayed\n   *\n   * @param timeFilter - Optional filter function to control which hours are displayed\n   * @returns Array of objects with hour and optional config\n   */\n  generateTimeSlots(\n    timeFilter?: (hour: number) => TimeFilterResult,\n  ): Array<{ hour: number; config?: TimeSlotConfig }> {\n    const slots: Array<{ hour: number; config?: TimeSlotConfig }> = [];\n\n    for (let hour = 0; hour < 24; hour++) {\n      if (!timeFilter) {\n        // No filter - include all hours\n        slots.push({ hour });\n        continue;\n      }\n\n      const result = timeFilter(hour);\n      if (typeof result === \"boolean\") {\n        // Simple boolean return\n        if (result) {\n          slots.push({ hour });\n        }\n      } else {\n        // Advanced config return\n        if (result.visible) {\n          slots.push({ hour, config: result });\n        }\n      }\n    }\n\n    return slots;\n  }\n\n  /**\n   * Calculate layout for events on a specific day\n   * Handles overlapping events using a column packing algorithm\n   * Supports both single-day events and cross-midnight event segments\n   *\n   * @param events - All calendar events\n   * @param dateStr - Target date string (YYYY-MM-DD)\n   * @returns Array of TimeLayoutItem with positioning information\n   */\n  calculateLayout(events: CalendarEvent[], dateStr: string): TimeLayoutItem[] {\n    // Step 1: Filter and calculate geometry for events on this date\n    // Now includes cross-midnight events that span this day\n    const dayEvents = this.filterAndCalculateGeometry(events, dateStr);\n\n    if (dayEvents.length === 0) {\n      return [];\n    }\n\n    // Step 2: Sort by start time, then by duration (longer first)\n    dayEvents.sort((a, b) => a.startMin - b.startMin || b.endMin - a.endMin);\n\n    // Step 3: Group overlapping events into clusters\n    const groups = this.groupOverlappingEvents(dayEvents);\n\n    // Step 4: Calculate column positions within each group\n    for (const group of groups) {\n      this.calculateColumnPositions(group);\n    }\n\n    // Step 5: Convert to TimeLayoutItem with segment info\n    return dayEvents.map((ev) => {\n      const item: TimeLayoutItem = {\n        event: ev.event,\n        top: ev.top,\n        height: ev.height,\n        leftPercent: ev.leftPercent,\n        widthPercent: ev.widthPercent,\n        colIndex: ev.colIndex,\n        startMin: ev.startMin,\n        endMin: ev.endMin,\n        isStart: ev.isStart,\n        isEnd: ev.isEnd,\n      };\n\n      // Add segment info only for cross-midnight events\n      if (ev.segmentIndex !== undefined && ev.totalSegments !== undefined) {\n        item.segmentIndex = ev.segmentIndex;\n        item.totalSegments = ev.totalSegments;\n      }\n\n      return item;\n    });\n  }\n\n  /**\n   * Check if an event is a single-day event (starts and ends on same day)\n   *\n   * @param event - Calendar event\n   * @returns true if event is single-day\n   */\n  isSingleDayEvent(event: CalendarEvent): boolean {\n    const start = this.adapter.parse(event.start);\n    const end = this.adapter.parse(event.end);\n    return this.adapter.isSame(start, end, \"day\");\n  }\n\n  /**\n   * Check if a timed event crosses midnight (spans multiple days but is not all-day)\n   * These events need special handling in time view to show on each day they span.\n   *\n   * @param event - Calendar event\n   * @returns true if event crosses midnight and is not an all-day event\n   */\n  isCrossMidnightEvent(event: CalendarEvent): boolean {\n    // All-day events are handled separately\n    if (this.isAllDayEvent(event)) {\n      return false;\n    }\n    return !this.isSingleDayEvent(event);\n  }\n\n  /**\n   * Get the number of days an event spans\n   *\n   * @param event - Calendar event\n   * @returns Number of days (1 for single-day events)\n   */\n  getEventDaySpan(event: CalendarEvent): number {\n    const start = this.adapter.startOf(this.adapter.parse(event.start), \"day\");\n    const end = this.adapter.startOf(this.adapter.parse(event.end), \"day\");\n    return this.adapter.diff(end, start, \"day\") + 1;\n  }\n\n  /**\n   * Check if an event is an all-day event\n   * An event is considered all-day if:\n   * - Start and end times are both 00:00 (same day or next day)\n   * - Duration covers the entire day (00:00 to 23:59 or similar)\n   *\n   * @param event - Calendar event\n   * @returns true if event is all-day\n   */\n  isAllDayEvent(event: CalendarEvent): boolean {\n    const start = this.adapter.parse(event.start);\n    const end = this.adapter.parse(event.end);\n\n    const startHour = this.adapter.hour(start);\n    const startMinute = this.adapter.minute(start);\n    const endHour = this.adapter.hour(end);\n    const endMinute = this.adapter.minute(end);\n\n    // Case 1: Both start and end are 00:00 (common pattern for all-day events)\n    if (\n      startHour === 0 &&\n      startMinute === 0 &&\n      endHour === 0 &&\n      endMinute === 0\n    ) {\n      return true;\n    }\n\n    // Case 2: Starts at 00:00 and ends at 23:59 (or close to midnight)\n    if (\n      startHour === 0 &&\n      startMinute === 0 &&\n      endHour === 23 &&\n      endMinute >= 59\n    ) {\n      return true;\n    }\n\n    return false;\n  }\n\n  /**\n   * Calculate layout for all-day events across visible columns\n   * Handles multi-day spanning events with segmentation support\n   *\n   * When events span across non-visible (filtered) columns, they are split into\n   * multiple segments. Each segment represents a contiguous visible portion.\n   *\n   * @param allDayEvents - Array of all-day events\n   * @param columns - Array of visible columns (from generateColumns)\n   * @returns Array of AllDayLayoutItem with positioning information (may include segmented events)\n   */\n  calculateAllDayLayout(\n    allDayEvents: CalendarEvent[],\n    columns: Array<TimeColumn<T>>,\n  ): AllDayLayoutItem[] {\n    if (columns.length === 0 || allDayEvents.length === 0) {\n      return [];\n    }\n\n    const firstColDate = columns[0]!.date;\n    const lastColDate = columns[columns.length - 1]!.date;\n\n    // Filter events that overlap with the visible columns range\n    const rangeEvents = allDayEvents.filter((event) => {\n      const eventStart = this.adapter.startOf(\n        this.adapter.parse(event.start),\n        \"day\",\n      );\n      const eventEnd = this.adapter.startOf(\n        this.adapter.parse(event.end),\n        \"day\",\n      );\n\n      return (\n        !this.adapter.isAfter(eventStart, lastColDate, \"day\") &&\n        !this.adapter.isBefore(eventEnd, firstColDate, \"day\")\n      );\n    });\n\n    // Calculate segments for each event\n    const visualItems: Array<AllDayLayoutItem & { sortKey: number }> = [];\n\n    for (const event of rangeEvents) {\n      const eventStart = this.adapter.startOf(\n        this.adapter.parse(event.start),\n        \"day\",\n      );\n      const eventEnd = this.adapter.startOf(\n        this.adapter.parse(event.end),\n        \"day\",\n      );\n\n      // Find all visible columns that this event covers\n      const coveredColumns: Array<{\n        colIndex: number;\n        date: T;\n        dateStr: string;\n      }> = [];\n\n      for (let i = 0; i < columns.length; i++) {\n        const col = columns[i]!;\n        if (\n          !this.adapter.isBefore(col.date, eventStart, \"day\") &&\n          !this.adapter.isAfter(col.date, eventEnd, \"day\")\n        ) {\n          coveredColumns.push({\n            colIndex: i,\n            date: col.date,\n            dateStr: col.dateStr,\n          });\n        }\n      }\n\n      if (coveredColumns.length === 0) {\n        continue; // Event doesn't cover any visible columns\n      }\n\n      // Group consecutive covered columns into segments\n      // IMPORTANT: Consecutive means actual calendar dates differ by exactly 1 day,\n      // NOT column indices. This ensures events are split when hidden days create gaps.\n      const segments: Array<{\n        startIdx: number;\n        span: number;\n        isEventStart: boolean;\n        isEventEnd: boolean;\n      }> = [];\n\n      let segmentStart = coveredColumns[0]!;\n      let prevCol = segmentStart;\n      let segmentSpan = 1;\n\n      for (let i = 1; i < coveredColumns.length; i++) {\n        const current = coveredColumns[i]!;\n\n        // Check if this column is consecutive in actual calendar (differs by exactly 1 day)\n        const nextExpectedDate = this.adapter.add(prevCol.date, 1, \"day\");\n        const isConsecutive = this.adapter.isSame(\n          current.date,\n          nextExpectedDate,\n          \"day\",\n        );\n\n        if (isConsecutive) {\n          segmentSpan++;\n          prevCol = current;\n        } else {\n          // Non-consecutive: save current segment and start a new one\n          const isEventStart = this.adapter.isSame(\n            segmentStart.date,\n            eventStart,\n            \"day\",\n          );\n          const isEventEnd = this.adapter.isSame(prevCol.date, eventEnd, \"day\");\n\n          segments.push({\n            startIdx: segmentStart.colIndex,\n            span: segmentSpan,\n            isEventStart,\n            isEventEnd,\n          });\n\n          // Start new segment\n          segmentStart = current;\n          prevCol = current;\n          segmentSpan = 1;\n        }\n      }\n\n      // Don't forget the last segment\n      const isEventStartFinal = this.adapter.isSame(\n        segmentStart.date,\n        eventStart,\n        \"day\",\n      );\n      const isEventEndFinal = this.adapter.isSame(\n        prevCol.date,\n        eventEnd,\n        \"day\",\n      );\n\n      segments.push({\n        startIdx: segmentStart.colIndex,\n        span: segmentSpan,\n        isEventStart: isEventStartFinal,\n        isEventEnd: isEventEndFinal,\n      });\n\n      // Create layout items for each segment\n      const totalSegments = segments.length;\n      segments.forEach((seg, idx) => {\n        const item: AllDayLayoutItem & { sortKey: number } = {\n          event,\n          startIdx: seg.startIdx,\n          span: seg.span,\n          slot: 0, // Will be calculated below\n          isStart: seg.isEventStart,\n          isEnd: seg.isEventEnd,\n          sortKey: seg.startIdx * 1000 - seg.span,\n          // Add segmentation info only if event was split\n          ...(totalSegments > 1 ? { segmentIndex: idx, totalSegments } : {}),\n        };\n        visualItems.push(item);\n      });\n    }\n\n    // Sort by start index, then by span (descending)\n    visualItems.sort((a, b) => a.sortKey - b.sortKey);\n\n    // Allocate vertical slots to prevent overlap (same as MonthEngine)\n    const slots: number[] = [];\n\n    for (const item of visualItems) {\n      let slotIdx = 0;\n\n      // Find first available slot\n      while (true) {\n        const slotEnd = slots[slotIdx];\n        if (slotEnd === undefined || slotEnd < item.startIdx) {\n          slots[slotIdx] = item.startIdx + item.span - 1;\n          item.slot = slotIdx;\n          break;\n        }\n        slotIdx++;\n      }\n    }\n\n    // Remove sortKey from result\n    return visualItems.map(({ sortKey: _sortKey, ...item }) => item);\n  }\n\n  /**\n   * Update cell height\n   *\n   * @param height - New cell height in pixels\n   */\n  setCellHeight(height: number): void {\n    this.cellHeight = height;\n  }\n\n  /**\n   * Get current cell height\n   */\n  getCellHeight(): number {\n    return this.cellHeight;\n  }\n\n  // ==========================================================================\n  // Private Methods\n  // ==========================================================================\n\n  /**\n   * Filter events for a specific date and calculate their geometry\n   * Supports both single-day events and cross-midnight events\n   *\n   * For cross-midnight events:\n   * - First day: shows from event start time to 23:59 (1440 minutes)\n   * - Middle days: shows full day (00:00 to 23:59)\n   * - Last day: shows from 00:00 to event end time\n   */\n  private filterAndCalculateGeometry(\n    events: CalendarEvent[],\n    dateStr: string,\n  ): EventGeometry[] {\n    const result: EventGeometry[] = [];\n    const targetDate = this.adapter.parse(dateStr);\n    const targetDayStart = this.adapter.startOf(targetDate, \"day\");\n\n    for (const event of events) {\n      // Skip all-day events (handled by calculateAllDayLayout)\n      if (this.isAllDayEvent(event)) {\n        continue;\n      }\n\n      const eventStart = this.adapter.parse(event.start);\n      const eventEnd = this.adapter.parse(event.end);\n      const eventStartDay = this.adapter.startOf(eventStart, \"day\");\n      const eventEndDay = this.adapter.startOf(eventEnd, \"day\");\n\n      // Check if this event touches the target date\n      const isOnTargetDate =\n        !this.adapter.isBefore(targetDayStart, eventStartDay, \"day\") &&\n        !this.adapter.isAfter(targetDayStart, eventEndDay, \"day\");\n\n      if (!isOnTargetDate) {\n        continue;\n      }\n\n      // Calculate segment info for cross-midnight events\n      const isStart = this.adapter.isSame(targetDayStart, eventStartDay, \"day\");\n      const isEnd = this.adapter.isSame(targetDayStart, eventEndDay, \"day\");\n      const totalDays =\n        this.adapter.diff(eventEndDay, eventStartDay, \"day\") + 1;\n      const segmentIndex = this.adapter.diff(\n        targetDayStart,\n        eventStartDay,\n        \"day\",\n      );\n\n      // Calculate start/end minutes for this day's segment\n      let startMin: number;\n      let endMin: number;\n\n      if (isStart && isEnd) {\n        // Single-day event: use actual times\n        startMin =\n          this.adapter.hour(eventStart) * 60 + this.adapter.minute(eventStart);\n        endMin =\n          this.adapter.hour(eventEnd) * 60 + this.adapter.minute(eventEnd);\n      } else if (isStart) {\n        // First day of multi-day: event start to end of day\n        startMin =\n          this.adapter.hour(eventStart) * 60 + this.adapter.minute(eventStart);\n        endMin = 24 * 60; // End of day (1440 minutes)\n      } else if (isEnd) {\n        // Last day of multi-day: start of day to event end\n        startMin = 0;\n        endMin =\n          this.adapter.hour(eventEnd) * 60 + this.adapter.minute(eventEnd);\n      } else {\n        // Middle day: full day\n        startMin = 0;\n        endMin = 24 * 60;\n      }\n\n      // Skip if segment has no duration (e.g., ends exactly at midnight)\n      if (endMin <= startMin) {\n        continue;\n      }\n\n      const pixelsPerMinute = this.cellHeight / 60;\n      const top = startMin * pixelsPerMinute;\n      const duration = endMin - startMin;\n      const height = Math.max(20, duration * pixelsPerMinute);\n\n      const geometry: EventGeometry = {\n        event,\n        top,\n        height,\n        startMin,\n        endMin,\n        colIndex: 0,\n        widthPercent: 100,\n        leftPercent: 0,\n        isStart,\n        isEnd,\n      };\n\n      // Add segment info only for multi-day events\n      if (totalDays > 1) {\n        geometry.segmentIndex = segmentIndex;\n        geometry.totalSegments = totalDays;\n      }\n\n      result.push(geometry);\n    }\n\n    return result;\n  }\n\n  /**\n   * Group events that overlap into clusters\n   * Events in the same cluster need to share horizontal space\n   */\n  private groupOverlappingEvents(events: EventGeometry[]): EventGeometry[][] {\n    if (events.length === 0) {\n      return [];\n    }\n\n    const groups: EventGeometry[][] = [];\n    let currentGroup: EventGeometry[] = [events[0]!];\n    let groupEnd = events[0]!.endMin;\n\n    for (let i = 1; i < events.length; i++) {\n      const ev = events[i]!;\n\n      // If event starts before current group ends, it overlaps\n      if (ev.startMin < groupEnd) {\n        currentGroup.push(ev);\n        groupEnd = Math.max(groupEnd, ev.endMin);\n      } else {\n        // No overlap - save current group and start new one\n        groups.push(currentGroup);\n        currentGroup = [ev];\n        groupEnd = ev.endMin;\n      }\n    }\n\n    // Don't forget the last group\n    groups.push(currentGroup);\n\n    return groups;\n  }\n\n  /**\n   * Calculate column positions for events within a group\n   * Uses a greedy column packing algorithm with smart expansion\n   */\n  private calculateColumnPositions(group: EventGeometry[]): void {\n    // Track the end time of each column\n    const columns: number[] = [];\n\n    for (const ev of group) {\n      let placed = false;\n\n      // Try to fit in an existing column\n      for (let i = 0; i < columns.length; i++) {\n        if (columns[i]! <= ev.startMin) {\n          columns[i] = ev.endMin;\n          ev.colIndex = i;\n          placed = true;\n          break;\n        }\n      }\n\n      // If no column available, create new one\n      if (!placed) {\n        columns.push(ev.endMin);\n        ev.colIndex = columns.length - 1;\n      }\n    }\n\n    const numCols = columns.length;\n\n    if (numCols === 1) {\n      // Single event - full width\n      for (const ev of group) {\n        ev.widthPercent = 100;\n        ev.leftPercent = 0;\n      }\n      return;\n    }\n\n    const offsetPerCol = 100 / numCols;\n\n    // Width multiplier determines how much each event extends into neighbor space\n    // Adjust based on column count for better visual balance\n    const widthMultiplier = numCols <= 3 ? 1.6 : numCols <= 5 ? 1.5 : 1.4;\n\n    for (const ev of group) {\n      const leftOffset = ev.colIndex * offsetPerCol;\n\n      // Check for available space to the right (expansion)\n      // Find how many subsequent columns are free during this event's time\n      let span = 1;\n      for (let c = ev.colIndex + 1; c < numCols; c++) {\n        // Check collision with any event in column 'c'\n        const hasCollision = group.some(\n          (other) =>\n            other.colIndex === c &&\n            other.startMin < ev.endMin &&\n            other.endMin > ev.startMin,\n        );\n\n        if (hasCollision) {\n          break;\n        }\n        span++;\n      }\n\n      // Calculate width with expansion\n      // Base width (overlapping) + spanned columns\n      const expandedWidth = offsetPerCol * (span - 1 + widthMultiplier);\n      const maxWidth = 100 - leftOffset;\n\n      ev.leftPercent = leftOffset;\n      ev.widthPercent = Math.min(expandedWidth, maxWidth);\n\n      // If expanded to the last column, ensure it hits the edge exactly\n      if (ev.colIndex + span === numCols) {\n        ev.widthPercent = maxWidth;\n      }\n    }\n  }\n}\n","/**\n * Time view (week/day) renderer\n */\nimport type {\n  DateAdapter,\n  CalendarEvent,\n  ThemeConfig,\n  ViewType,\n  TimeLayoutItem,\n  DateFormatConfig,\n  DayFilterContext,\n  DayFilterResult,\n  DayRenderConfig,\n  TimeFilterResult,\n  TimeFormatter,\n  AllDayLayoutItem,\n  EventRenderContext,\n} from \"../types\";\nimport type { TimeEngine } from \"../engines/TimeEngine\";\nimport type { DragController } from \"../core/DragController\";\nimport { createElement, clearElement } from \"../utils/dom\";\n\n/**\n * Renders the week/day time view calendar\n */\nexport class TimeRenderer<T> {\n  /** Current view type being rendered (updated on each render call) */\n  private currentViewType: ViewType = \"week\";\n  /** Currently active popover element */\n  private activePopover: HTMLElement | null = null;\n  /** Bound handler for closing popover on outside click */\n  private popoverCloseHandler: ((e: MouseEvent) => void) | null = null;\n\n  constructor(\n    private engine: TimeEngine<T>,\n    private adapter: DateAdapter<T>,\n    private theme: Required<ThemeConfig> & {\n      fontSize: Required<NonNullable<ThemeConfig[\"fontSize\"]>>;\n    },\n    private dateFormats: Required<DateFormatConfig>,\n    private onStyleEvent?: (\n      event: CalendarEvent,\n    ) => import(\"../types\").EventStyle,\n    private onRenderEvent?: (ctx: EventRenderContext) => void,\n    private maxEventsPerRow?: number,\n    private onRenderMoreEventsPopover?: (\n      events: CalendarEvent[],\n      date: Date,\n      anchorEl: HTMLElement,\n      defaultRender: () => void,\n    ) => void,\n  ) {}\n\n  /**\n   * Render the complete time view\n   */\n  render(\n    container: HTMLElement,\n    currentDate: T,\n    viewType: ViewType,\n    events: CalendarEvent[],\n    dragController: DragController<T>,\n    renderCallback: () => void,\n    onEventClick?: (event: CalendarEvent) => void,\n    initialScrollTop?: number | null,\n    dayFilter?: (date: T, context: DayFilterContext) => DayFilterResult,\n    timeFilter?: (hour: number) => TimeFilterResult,\n    timeFormatter?: TimeFormatter,\n  ): void {\n    // Store current view type for use in event rendering hooks\n    this.currentViewType = viewType;\n\n    clearElement(container);\n\n    // Generate columns with dayFilter\n    const columns = this.engine.generateColumns(\n      currentDate,\n      viewType,\n      dayFilter,\n    );\n\n    // Generate time slots with timeFilter\n    const timeSlots = this.engine.generateTimeSlots(timeFilter);\n\n    // Separate all-day events from timed events\n    const allDayEvents = events.filter((e) => this.engine.isAllDayEvent(e));\n    const timedEvents = events.filter((e) => !this.engine.isAllDayEvent(e));\n\n    // Render header\n    const header = this.renderHeader(columns, currentDate, dayFilter);\n    container.appendChild(header);\n\n    // Render all-day events section (if any)\n    if (allDayEvents.length > 0) {\n      const allDaySection = this.renderAllDaySection(\n        columns,\n        allDayEvents,\n        dragController,\n        renderCallback,\n        onEventClick,\n      );\n      container.appendChild(allDaySection);\n    }\n\n    // Render scrollable body\n    const scrollWrap = createElement(\"div\", \"tg-time-grid-container\");\n    const bodyInner = createElement(\"div\", \"tg-time-body\");\n\n    // Render time axis with timeSlots and timeFormatter\n    const axis = this.renderTimeAxis(timeSlots, timeFormatter);\n    bodyInner.appendChild(axis);\n\n    // Render day columns (only timed events)\n    for (const colData of columns) {\n      const col = this.renderDayColumn(\n        colData,\n        timedEvents,\n        dragController,\n        renderCallback,\n        onEventClick,\n        timeSlots,\n      );\n      bodyInner.appendChild(col);\n    }\n\n    scrollWrap.appendChild(bodyInner);\n    container.appendChild(scrollWrap);\n\n    // Restore scroll position synchronously after DOM insertion\n    // Using requestAnimationFrame ensures the DOM is rendered before scrolling\n    // This prevents the visual \"jump\" that setTimeout(0) causes\n    const restoreScroll = () => {\n      if (initialScrollTop !== null && initialScrollTop !== undefined) {\n        scrollWrap.scrollTop = initialScrollTop;\n      } else {\n        // Default scroll to first visible time slot >= 8:00 AM\n        const defaultHour = 8;\n        const targetSlotIndex = timeSlots.findIndex(\n          (slot) => slot.hour >= defaultHour,\n        );\n        if (targetSlotIndex >= 0) {\n          scrollWrap.scrollTop = targetSlotIndex * this.theme.cellHeight;\n        }\n      }\n    };\n\n    // Try synchronous restore first (works when container is already in DOM)\n    // Use rAF as fallback to ensure DOM is ready\n    if (container.isConnected) {\n      restoreScroll();\n    } else {\n      requestAnimationFrame(restoreScroll);\n    }\n  }\n\n  // ==========================================================================\n  // Private Methods\n  // ==========================================================================\n\n  private renderHeader(\n    columns: Array<{ date: T; dateStr: string }>,\n    currentDate: T,\n    dayFilter?: (date: T, context: DayFilterContext) => DayFilterResult,\n  ): HTMLElement {\n    const header = createElement(\"div\", \"tg-time-header\");\n    // padding-left is defined in CSS\n\n    // Weekday labels: Sunday through Saturday\n    const dayNames = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n    const today = this.adapter.create();\n\n    for (const col of columns) {\n      const cell = createElement(\"div\", \"tg-time-header-cell\");\n\n      // Build filter context\n      const dayOfWeek = this.adapter.day(col.date);\n      const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;\n      const isToday = this.adapter.isSame(col.date, today, \"day\");\n      const context: DayFilterContext = {\n        isWeekend,\n        dayOfWeek,\n        isToday,\n        isThisMonth: this.adapter.isSame(col.date, currentDate, \"month\"),\n      };\n\n      // Apply dayFilter configuration if provided\n      if (dayFilter) {\n        const result = dayFilter(col.date, context);\n        if (typeof result === \"object\") {\n          const config = result as DayRenderConfig;\n          if (config.className) {\n            cell.classList.add(config.className);\n          }\n          if (config.style) {\n            Object.assign(cell.style, config.style);\n          }\n          if (config.disabled) {\n            cell.classList.add(\"tg-disabled\");\n          }\n        }\n      }\n\n      // Highlight today using CSS class (default styling when no dayFilter)\n      if (isToday && !dayFilter) {\n        cell.classList.add(\"tg-today\");\n      }\n\n      const dayName = dayNames[dayOfWeek];\n      const dateNum = this.adapter.date(col.date);\n\n      // Use CSS classes instead of inline styles\n      const dayNameEl = createElement(\"div\");\n      dayNameEl.textContent = dayName!;\n\n      const dateNumEl = createElement(\"div\", \"tg-header-date\");\n      dateNumEl.textContent = String(dateNum);\n\n      cell.appendChild(dayNameEl);\n      cell.appendChild(dateNumEl);\n\n      header.appendChild(cell);\n    }\n\n    return header;\n  }\n\n  /**\n   * Render the all-day events section below the header\n   * Uses layout calculation for multi-day spanning events\n   * Supports maxEventsPerRow for collapsing events similar to month view\n   */\n  private renderAllDaySection(\n    columns: Array<{ date: T; dateStr: string }>,\n    allDayEvents: CalendarEvent[],\n    dragController: DragController<T>,\n    renderCallback: () => void,\n    onEventClick?: (event: CalendarEvent) => void,\n  ): HTMLElement {\n    const section = createElement(\"div\", \"tg-allday-section\");\n\n    // Left spacer (matches time axis width)\n    const spacer = createElement(\"div\", \"tg-allday-spacer\");\n    section.appendChild(spacer);\n\n    // Container for all-day events (positioned relatively)\n    const eventsContainer = createElement(\"div\", \"tg-allday-events-container\");\n    eventsContainer.style.setProperty(\n      \"--tg-allday-columns\",\n      String(columns.length),\n    );\n\n    // Calculate layout for all-day events\n    const layout = this.engine.calculateAllDayLayout(allDayEvents, columns);\n\n    // Split layout into visible and hidden events based on maxEventsPerRow\n    const visibleLayout =\n      this.maxEventsPerRow !== undefined\n        ? layout.filter((item) => item.slot < this.maxEventsPerRow!)\n        : layout;\n\n    // Group hidden events by column index for \"+N more\" indicators\n    const hiddenEventsByColumn: Map<number, CalendarEvent[]> = new Map();\n    if (this.maxEventsPerRow !== undefined) {\n      for (const item of layout) {\n        if (item.slot >= this.maxEventsPerRow) {\n          // For each column the event spans, add it to hidden events\n          for (\n            let colIdx = item.startIdx;\n            colIdx < item.startIdx + item.span;\n            colIdx++\n          ) {\n            if (!hiddenEventsByColumn.has(colIdx)) {\n              hiddenEventsByColumn.set(colIdx, []);\n            }\n            // Avoid duplicates\n            const arr = hiddenEventsByColumn.get(colIdx)!;\n            if (!arr.find((e) => e.id === item.event.id)) {\n              arr.push(item.event);\n            }\n          }\n        }\n      }\n    }\n\n    // Calculate section height based on visible max slot\n    const effectiveMaxSlot = visibleLayout.reduce(\n      (max, item) => Math.max(max, item.slot),\n      -1,\n    );\n    const rowHeight = 26; // Height of each all-day event row\n    const padding = 8; // Top and bottom padding\n    let sectionHeight =\n      effectiveMaxSlot >= 0 ? padding + (effectiveMaxSlot + 1) * rowHeight : 0;\n\n    // Add space for \"+N more\" indicator if there are hidden events\n    if (hiddenEventsByColumn.size > 0) {\n      sectionHeight += 22; // Height for the \"+N more\" row\n    }\n\n    eventsContainer.style.height = `${Math.max(sectionHeight, 28)}px`;\n\n    // Render visible all-day event bars\n    for (const item of visibleLayout) {\n      const eventEl = this.renderAllDayEventBar(\n        item,\n        columns.length,\n        dragController,\n        renderCallback,\n        onEventClick,\n      );\n      eventsContainer.appendChild(eventEl);\n    }\n\n    // Render \"+N more\" indicators for each column with hidden events\n    for (const [colIdx, hiddenEvents] of hiddenEventsByColumn) {\n      const moreEl = this.renderAllDayMoreIndicator(\n        colIdx,\n        hiddenEvents,\n        columns[colIdx]!,\n        columns.length,\n        effectiveMaxSlot,\n        onEventClick,\n      );\n      eventsContainer.appendChild(moreEl);\n    }\n\n    section.appendChild(eventsContainer);\n    return section;\n  }\n\n  /**\n   * Render a single all-day event bar with spanning and segmentation support\n   */\n  private renderAllDayEventBar(\n    item: AllDayLayoutItem,\n    columnCount: number,\n    dragController: DragController<T>,\n    renderCallback: () => void,\n    onEventClick?: (event: CalendarEvent) => void,\n  ): HTMLElement {\n    const el = createElement(\"div\", \"tg-event-base tg-allday-event\");\n    el.dataset[\"eid\"] = item.event.id;\n\n    // Add segmentation data attributes and classes for styling\n    if (item.segmentIndex !== undefined && item.totalSegments !== undefined) {\n      el.dataset[\"segmentIndex\"] = String(item.segmentIndex);\n      el.dataset[\"totalSegments\"] = String(item.totalSegments);\n      el.classList.add(\"tg-event-segmented\");\n\n      // Add specific classes for first/last segments\n      if (item.segmentIndex === 0) {\n        el.classList.add(\"tg-event-segment-first\");\n      }\n      if (item.segmentIndex === item.totalSegments - 1) {\n        el.classList.add(\"tg-event-segment-last\");\n      }\n      // Middle segments\n      if (item.segmentIndex > 0 && item.segmentIndex < item.totalSegments - 1) {\n        el.classList.add(\"tg-event-segment-middle\");\n      }\n    }\n\n    // Apply custom styling if hook is provided\n    let bgColor = item.event.color || \"#3b82f6\";\n    let customOpacity: number | undefined;\n\n    if (this.onStyleEvent) {\n      const style = this.onStyleEvent(item.event);\n      if (style.className) {\n        el.classList.add(style.className);\n      }\n      if (style.color) {\n        bgColor = style.color;\n      }\n      if (style.opacity !== undefined) {\n        customOpacity = style.opacity;\n      }\n    }\n\n    // Calculate position and size based on layout\n    const colWidth = 100 / columnCount;\n    const xOffset = item.startIdx * colWidth;\n    const yOffset = 4 + item.slot * 26; // 4px top padding, 26px row height\n\n    el.style.left = `calc(${xOffset}% + 2px)`;\n    el.style.top = `${yOffset}px`;\n    el.style.width = `calc(${item.span * colWidth}% - 4px)`;\n    el.style.backgroundColor = bgColor;\n\n    if (customOpacity !== undefined) {\n      el.style.opacity = customOpacity.toString();\n    }\n\n    // Default render function for event content\n    const defaultRender = () => {\n      // Title only (no time text for all-day events)\n      el.textContent = item.event.title;\n    };\n\n    // Use custom render hook if provided, otherwise use default\n    if (this.onRenderEvent) {\n      const ctx: EventRenderContext = {\n        event: item.event,\n        el,\n        viewType: this.currentViewType,\n        isAllDay: true,\n        isStart: item.isStart,\n        isEnd: item.isEnd,\n        defaultRender,\n      };\n      // Only add segment properties if they exist\n      if (item.segmentIndex !== undefined) {\n        ctx.segmentIndex = item.segmentIndex;\n      }\n      if (item.totalSegments !== undefined) {\n        ctx.totalSegments = item.totalSegments;\n      }\n      this.onRenderEvent(ctx);\n    } else {\n      defaultRender();\n    }\n\n    // Add resize handles for spanning events\n    if (item.isStart) {\n      const leftHandle = createElement(\n        \"div\",\n        \"tg-resize-handle tg-resize-h tg-left\",\n      );\n      el.appendChild(leftHandle);\n    }\n\n    if (item.isEnd) {\n      const rightHandle = createElement(\n        \"div\",\n        \"tg-resize-handle tg-resize-h tg-right\",\n      );\n      el.appendChild(rightHandle);\n    }\n\n    // Event click handler\n    if (onEventClick) {\n      el.addEventListener(\"click\", (e) => {\n        e.stopPropagation();\n        onEventClick(item.event);\n      });\n    }\n\n    // Initialize drag for all-day events (use month drag for horizontal movement)\n    dragController.initMonthDrag(el, item.event, renderCallback);\n\n    return el;\n  }\n\n  /**\n   * Render the \"+N more\" indicator for a column in all-day section\n   */\n  private renderAllDayMoreIndicator(\n    colIdx: number,\n    hiddenEvents: CalendarEvent[],\n    column: { date: T; dateStr: string },\n    columnCount: number,\n    visibleMaxSlot: number,\n    onEventClick?: (event: CalendarEvent) => void,\n  ): HTMLElement {\n    const el = createElement(\"div\", \"tg-more-indicator tg-allday-more\");\n    el.textContent = `+${hiddenEvents.length} more`;\n\n    // Calculate position\n    const colWidth = 100 / columnCount;\n    const xOffset = colIdx * colWidth;\n    const yOffset = 4 + (visibleMaxSlot + 1) * 26 + 2; // Position below visible events\n\n    el.style.left = `calc(${xOffset}% + 2px)`;\n    el.style.top = `${yOffset}px`;\n    el.style.width = `calc(${colWidth}% - 4px)`;\n\n    // Convert adapter date to native Date\n    const dateObj = new Date(\n      this.adapter.year(column.date),\n      this.adapter.month(column.date),\n      this.adapter.date(column.date),\n    );\n\n    // Click handler for popover\n    el.addEventListener(\"click\", (e) => {\n      e.stopPropagation();\n\n      const defaultRender = () => {\n        this.renderDefaultPopover(el, hiddenEvents, dateObj, onEventClick);\n      };\n\n      if (this.onRenderMoreEventsPopover) {\n        this.onRenderMoreEventsPopover(\n          hiddenEvents,\n          dateObj,\n          el,\n          defaultRender,\n        );\n      } else {\n        defaultRender();\n      }\n    });\n\n    return el;\n  }\n\n  /**\n   * Render the default popover for hidden events\n   */\n  private renderDefaultPopover(\n    anchorEl: HTMLElement,\n    events: CalendarEvent[],\n    date: Date,\n    onEventClick?: (event: CalendarEvent) => void,\n  ): void {\n    // Close any existing popover\n    this.closePopover();\n\n    // Create popover container\n    const popover = createElement(\"div\", \"tg-more-popover\");\n    this.activePopover = popover;\n\n    // Header with date\n    const header = createElement(\"div\", \"tg-more-popover-header\");\n    header.textContent = date.toLocaleDateString(undefined, {\n      weekday: \"short\",\n      month: \"short\",\n      day: \"numeric\",\n    });\n    popover.appendChild(header);\n\n    // Event list\n    const list = createElement(\"div\", \"tg-more-popover-list\");\n    for (const event of events) {\n      const item = createElement(\"div\", \"tg-more-popover-item\");\n\n      // Apply custom styling if hook is provided\n      let dotColor = event.color || \"#3b82f6\";\n      let customOpacity: number | undefined;\n\n      if (this.onStyleEvent) {\n        const style = this.onStyleEvent(event);\n        if (style.className) {\n          item.classList.add(style.className);\n        }\n        if (style.color) {\n          dotColor = style.color;\n        }\n        if (style.opacity !== undefined) {\n          customOpacity = style.opacity;\n        }\n      }\n\n      // Color indicator\n      const colorDot = createElement(\"span\", \"tg-more-popover-dot\");\n      colorDot.style.backgroundColor = dotColor;\n      item.appendChild(colorDot);\n\n      // Title\n      const title = createElement(\"span\", \"tg-more-popover-title\");\n      title.textContent = event.title;\n      item.appendChild(title);\n\n      // Apply opacity to the whole item if specified\n      if (customOpacity !== undefined) {\n        item.style.opacity = customOpacity.toString();\n      }\n\n      // Click handler\n      if (onEventClick) {\n        item.addEventListener(\"click\", (e) => {\n          e.stopPropagation();\n          this.closePopover();\n          onEventClick(event);\n        });\n        item.style.cursor = \"pointer\";\n      }\n\n      list.appendChild(item);\n    }\n    popover.appendChild(list);\n\n    // Position the popover\n    document.body.appendChild(popover);\n    this.positionPopover(popover, anchorEl);\n\n    // Set up close handler\n    this.popoverCloseHandler = (e: MouseEvent) => {\n      if (!popover.contains(e.target as Node) && e.target !== anchorEl) {\n        this.closePopover();\n      }\n    };\n\n    // Delay adding the click listener to prevent immediate close\n    setTimeout(() => {\n      document.addEventListener(\"click\", this.popoverCloseHandler!);\n    }, 0);\n  }\n\n  /**\n   * Position the popover relative to the anchor element\n   */\n  private positionPopover(popover: HTMLElement, anchorEl: HTMLElement): void {\n    const anchorRect = anchorEl.getBoundingClientRect();\n    const popoverRect = popover.getBoundingClientRect();\n    const viewportHeight = window.innerHeight;\n    const viewportWidth = window.innerWidth;\n\n    // Default: position below the anchor\n    let top = anchorRect.bottom + 4;\n    let left = anchorRect.left;\n\n    // Adjust if popover would go off the bottom\n    if (top + popoverRect.height > viewportHeight - 8) {\n      top = anchorRect.top - popoverRect.height - 4;\n    }\n\n    // Adjust if popover would go off the right\n    if (left + popoverRect.width > viewportWidth - 8) {\n      left = viewportWidth - popoverRect.width - 8;\n    }\n\n    // Ensure popover doesn't go off the left\n    if (left < 8) {\n      left = 8;\n    }\n\n    popover.style.top = `${top}px`;\n    popover.style.left = `${left}px`;\n  }\n\n  /**\n   * Close the active popover\n   */\n  private closePopover(): void {\n    if (this.activePopover) {\n      this.activePopover.remove();\n      this.activePopover = null;\n    }\n\n    if (this.popoverCloseHandler) {\n      document.removeEventListener(\"click\", this.popoverCloseHandler);\n      this.popoverCloseHandler = null;\n    }\n  }\n\n  private renderTimeAxis(\n    timeSlots: Array<{\n      hour: number;\n      config?: import(\"../types\").TimeSlotConfig;\n    }>,\n    timeFormatter?: TimeFormatter,\n  ): HTMLElement {\n    const axis = createElement(\"div\", \"tg-time-axis\");\n\n    for (let slotIndex = 0; slotIndex < timeSlots.length; slotIndex++) {\n      const slot = timeSlots[slotIndex]!;\n      const label = createElement(\"div\", \"tg-time-axis-label\");\n\n      // Apply custom label or formatter\n      if (slot.config?.label) {\n        label.textContent = slot.config.label;\n      } else if (timeFormatter) {\n        label.textContent = timeFormatter(slot.hour, 0);\n      } else {\n        label.textContent = `${slot.hour}:00`;\n      }\n\n      // Apply custom className\n      if (slot.config?.className) {\n        label.classList.add(slot.config.className);\n      }\n\n      // Use transform for GPU-accelerated positioning\n      const yOffset = slotIndex * this.theme.cellHeight;\n      label.style.transform = `translateY(${yOffset}px)`;\n      axis.appendChild(label);\n    }\n\n    return axis;\n  }\n\n  private renderDayColumn(\n    colData: { date: T; dateStr: string },\n    events: CalendarEvent[],\n    dragController: DragController<T>,\n    renderCallback: () => void,\n    onEventClick?: (event: CalendarEvent) => void,\n    timeSlots?: Array<{\n      hour: number;\n      config?: import(\"../types\").TimeSlotConfig;\n    }>,\n  ): HTMLElement {\n    const col = createElement(\"div\", \"tg-day-column\");\n    col.dataset[\"date\"] = colData.dateStr;\n\n    // Set height via CSS custom property for dynamic time slots\n    if (timeSlots && timeSlots.length > 0) {\n      const height = timeSlots.length * this.theme.cellHeight;\n      col.style.setProperty(\"--tg-column-height\", `${height}px`);\n      col.style.height = \"var(--tg-column-height)\";\n    }\n\n    // Calculate layout for events on this day\n    const layout = this.engine.calculateLayout(events, colData.dateStr);\n\n    for (const item of layout) {\n      const eventEl = this.renderEventBlock(\n        item,\n        dragController,\n        renderCallback,\n        onEventClick,\n      );\n      col.appendChild(eventEl);\n    }\n\n    return col;\n  }\n\n  private renderEventBlock(\n    item: TimeLayoutItem,\n    dragController: DragController<T>,\n    renderCallback: () => void,\n    onEventClick?: (event: CalendarEvent) => void,\n  ): HTMLElement {\n    const el = createElement(\"div\", \"tg-event-base tg-event-block\");\n    el.dataset[\"eid\"] = item.event.id;\n\n    // Add cross-midnight segment classes for visual styling\n    if (item.segmentIndex !== undefined && item.totalSegments !== undefined) {\n      el.dataset[\"segmentIndex\"] = String(item.segmentIndex);\n      el.dataset[\"totalSegments\"] = String(item.totalSegments);\n      el.classList.add(\"tg-event-segmented\");\n\n      // Add specific classes for first/last/middle segments\n      if (item.segmentIndex === 0) {\n        el.classList.add(\"tg-event-segment-first\");\n      }\n      if (item.segmentIndex === item.totalSegments - 1) {\n        el.classList.add(\"tg-event-segment-last\");\n      }\n      if (item.segmentIndex > 0 && item.segmentIndex < item.totalSegments - 1) {\n        el.classList.add(\"tg-event-segment-middle\");\n      }\n    }\n\n    // Add continuation classes for cross-midnight events\n    if (!item.isStart) {\n      el.classList.add(\"tg-event-continuation\");\n    }\n    if (!item.isEnd) {\n      el.classList.add(\"tg-event-continued\");\n    }\n\n    // Apply custom styling if hook is provided\n    let bgColor = item.event.color || \"#3b82f6\";\n    let customOpacity: number | undefined;\n\n    if (this.onStyleEvent) {\n      const style = this.onStyleEvent(item.event);\n      if (style.className) {\n        el.classList.add(style.className);\n      }\n      if (style.color) {\n        bgColor = style.color;\n      }\n      if (style.opacity !== undefined) {\n        customOpacity = style.opacity;\n      }\n    }\n\n    // Use transform for GPU-accelerated positioning\n    // translateX uses percentage for responsive width positioning\n    el.style.transform = `translate(${item.leftPercent}%, ${item.top}px)`;\n    el.style.width = `calc(${item.widthPercent}% - 2px)`;\n    el.style.height = `${item.height}px`;\n    el.style.backgroundColor = bgColor;\n\n    // Z-index: shorter duration events get higher z-index (appear on top)\n    // This ensures smaller events are always clickable, regardless of column position\n    // Duration in minutes (endMin - startMin), shorter = higher z-index\n    const duration = item.endMin - item.startMin;\n    // Invert: short events (e.g., 15min) get high z-index, long events (e.g., 120min) get low\n    // Base z-index 10, add inverse of duration (capped to reasonable range)\n    const durationZIndex = Math.max(\n      0,\n      Math.min(50, Math.floor((120 - duration) / 2)),\n    );\n    el.style.zIndex = `${10 + durationZIndex}`;\n\n    if (customOpacity !== undefined) {\n      el.style.opacity = customOpacity.toString();\n    }\n\n    // Check if this is an all-day event\n    const isAllDay = this.engine.isAllDayEvent(item.event);\n\n    // Parse time values for context\n    const startDate = this.adapter.parse(item.event.start);\n    const endDate = this.adapter.parse(item.event.end);\n    const startTime = this.adapter.format(startDate, this.dateFormats.time);\n    const endTime = this.adapter.format(endDate, this.dateFormats.time);\n\n    // Default render function for event content\n    const defaultRender = () => {\n      // Create content - hide time text for all-day events\n      if (!isAllDay) {\n        const timeText = createElement(\"div\", \"tg-time-text\");\n        // For cross-midnight segments, show appropriate time info\n        if (item.isStart && item.isEnd) {\n          // Single-day event: show full time range\n          timeText.textContent = `${startTime} - ${endTime}`;\n        } else if (item.isStart) {\n          // First segment: show start time with continuation indicator\n          timeText.textContent = `${startTime} →`;\n        } else if (item.isEnd) {\n          // Last segment: show continuation with end time\n          timeText.textContent = `→ ${endTime}`;\n        } else {\n          // Middle segment: show continuation\n          timeText.textContent = `→ →`;\n        }\n        el.appendChild(timeText);\n      }\n\n      const titleText = createElement(\"div\", \"tg-event-title\");\n      titleText.textContent = item.event.title;\n      el.appendChild(titleText);\n    };\n\n    // Use custom render hook if provided, otherwise use default\n    if (this.onRenderEvent) {\n      const ctx: EventRenderContext = {\n        event: item.event,\n        el,\n        viewType: this.currentViewType,\n        isAllDay,\n        isStart: item.isStart,\n        isEnd: item.isEnd,\n        defaultRender,\n      };\n      // Only add time properties for timed events\n      if (!isAllDay) {\n        ctx.startTime = startTime;\n        ctx.endTime = endTime;\n      }\n      // Add segment info for cross-midnight events\n      if (item.segmentIndex !== undefined) {\n        ctx.segmentIndex = item.segmentIndex;\n      }\n      if (item.totalSegments !== undefined) {\n        ctx.totalSegments = item.totalSegments;\n      }\n      this.onRenderEvent(ctx);\n    } else {\n      defaultRender();\n    }\n\n    // Add resize handles based on segment position\n    // Only add top handle if this is the event start\n    if (item.isStart) {\n      const resizeHandleTop = createElement(\n        \"div\",\n        \"tg-resize-handle tg-resize-v tg-top\",\n      );\n      el.appendChild(resizeHandleTop);\n    }\n\n    // Only add bottom handle if this is the event end\n    if (item.isEnd) {\n      const resizeHandleBottom = createElement(\n        \"div\",\n        \"tg-resize-handle tg-resize-v tg-bottom\",\n      );\n      el.appendChild(resizeHandleBottom);\n    }\n\n    // Event click handler\n    if (onEventClick) {\n      el.addEventListener(\"click\", (e) => {\n        e.stopPropagation();\n        onEventClick(item.event);\n      });\n    }\n\n    // Initialize drag\n    dragController.initTimeDrag(el, item.event, renderCallback);\n\n    return el;\n  }\n}\n","/**\n * TimeView - Built-in week/day view implementation\n *\n * Base class for time-based views (week and day).\n * Can be extended for custom time-based views.\n */\nimport type {\n  CalendarEvent,\n  DayFilterContext,\n  DayFilterResult,\n  TimeFilterResult,\n  TimeFormatter,\n  ViewType,\n} from \"../types\";\nimport { BaseView, type ViewMeta, type ViewRenderOptions } from \"./BaseView\";\nimport { TimeEngine } from \"../engines/TimeEngine\";\nimport { TimeRenderer } from \"../renderers/TimeRenderer\";\n\n/**\n * Base time view for week/day displays\n *\n * Features:\n * - Hourly time grid\n * - All-day events section\n * - Event overlap handling\n * - Time slot filtering\n * - Custom time formatting\n */\nexport class TimeView<T = unknown> extends BaseView<T> {\n  static meta: ViewMeta = {\n    type: \"time\",\n    label: \"Time\",\n    shortLabel: \"T\",\n    order: 20,\n  };\n\n  protected engine!: TimeEngine<T>;\n  protected renderer!: TimeRenderer<T>;\n  protected timeViewType: ViewType = \"week\";\n\n  /**\n   * Initialize the view with context and create engine/renderer\n   */\n  override init(context: typeof this.context): void {\n    super.init(context);\n\n    // Create engine\n    this.engine = new TimeEngine<T>(\n      this.context.adapter,\n      this.context.config.theme.cellHeight,\n      this.context.config.view.showWeekends,\n      this.context.config.view.firstDayOfWeek,\n      this.context.config.dateFormats,\n    );\n\n    // Create renderer with maxEventsPerRow and popover hook for all-day events\n    this.renderer = new TimeRenderer<T>(\n      this.engine,\n      this.context.adapter,\n      this.context.config.theme,\n      this.context.config.dateFormats,\n      this.context.config.onStyleEvent,\n      this.context.config.onRenderEvent,\n      this.context.config.view.maxEventsPerRow,\n      this.context.config.onRenderMoreEventsPopover,\n    );\n  }\n\n  /**\n   * Render the time view\n   */\n  render(\n    container: HTMLElement,\n    events: CalendarEvent[],\n    options?: ViewRenderOptions,\n  ): void {\n    this.renderer.render(\n      container,\n      this.context.currentDate,\n      this.timeViewType,\n      events,\n      this.context.dragController,\n      this.context.requestRender,\n      this.context.config.onEventClick,\n      options?.preservedScrollTop,\n      this.context.config.view.dayFilter as\n        | ((date: T, context: DayFilterContext) => DayFilterResult)\n        | undefined,\n      this.context.config.view.timeFilter as\n        | ((hour: number) => TimeFilterResult)\n        | undefined,\n      this.context.config.view.timeFormatter as TimeFormatter | undefined,\n    );\n  }\n\n  /**\n   * Get the time engine for advanced usage\n   */\n  getEngine(): TimeEngine<T> {\n    return this.engine;\n  }\n\n  /**\n   * Get the time renderer for advanced usage\n   */\n  getRenderer(): TimeRenderer<T> {\n    return this.renderer;\n  }\n}\n\n/**\n * WeekView - Week display with hourly grid\n */\nexport class WeekView<T = unknown> extends TimeView<T> {\n  static override meta: ViewMeta = {\n    type: \"week\",\n    label: \"Week\",\n    shortLabel: \"W\",\n    order: 20,\n  };\n\n  protected override timeViewType: ViewType = \"week\";\n\n  /**\n   * Week view navigates by week\n   */\n  override getNavigationUnit(): \"week\" {\n    return \"week\";\n  }\n}\n\n/**\n * DayView - Single day display with hourly grid\n */\nexport class DayView<T = unknown> extends TimeView<T> {\n  static override meta: ViewMeta = {\n    type: \"day\",\n    label: \"Day\",\n    shortLabel: \"D\",\n    order: 30,\n  };\n\n  protected override timeViewType: ViewType = \"day\";\n\n  /**\n   * Day view navigates by day\n   */\n  override getNavigationUnit(): \"day\" {\n    return \"day\";\n  }\n\n  /**\n   * Day view uses day header format\n   */\n  override getHeaderTitle(): string {\n    return this.context.adapter.format(\n      this.context.currentDate,\n      this.context.config.dateFormats.dayHeader,\n    );\n  }\n}\n","/**\n * Main Calendar class - the primary public API\n *\n * Supports extensible view system with:\n * - Built-in views (month, week, day)\n * - Custom view registration\n * - View class extension via standard inheritance\n */\nimport type {\n  CalendarConfig,\n  CalendarEvent,\n  ViewType,\n  ResolvedCalendarConfig,\n  DateAdapter,\n} from \"../types\";\nimport { NativeDateAdapter } from \"../adapters/NativeDateAdapter\";\nimport { DragController } from \"./DragController\";\nimport { EventManager } from \"./EventManager\";\nimport { InteractionController } from \"./InteractionController\";\nimport { applyThemeVariables } from \"../styles\";\nimport { createElement, clearElement } from \"../utils/dom\";\nimport { DEFAULT_DATE_FORMATS, INTERNAL_DATA_FORMAT } from \"../constants\";\nimport {\n  ViewRegistry,\n  BaseView,\n  type ViewContext,\n  type ViewMeta,\n  type ViewClass,\n  type ViewRegistrationOptions,\n} from \"../views\";\n\n/**\n * Extended calendar configuration with view registry support\n */\nexport interface ExtendedCalendarConfig extends CalendarConfig {\n  /**\n   * Custom view registry instance\n   * If not provided, creates a new empty registry\n   */\n  viewRegistry?: ViewRegistry;\n}\n\n/**\n * TaskGenius Calendar Component\n *\n * A lightweight, configurable calendar with drag-and-drop support\n * and extensible view system.\n *\n * @example Basic usage\n * ```typescript\n * const calendar = new Calendar('#app', {\n *   view: { type: 'week' },\n *   events: [\n *     { id: '1', title: 'Meeting', start: '2025-11-20 10:00', end: '2025-11-20 11:30' }\n *   ]\n * });\n * ```\n *\n * @example Custom view registration\n * ```typescript\n * // Define a custom view with required static meta\n * class CustomView extends BaseView {\n *   static readonly meta: ViewMeta = { type: 'custom', label: 'Custom', shortLabel: 'C', order: 40 };\n *\n *   render(container, events) {\n *     // Custom rendering logic\n *   }\n * }\n *\n * // Register and use\n * const calendar = new Calendar('#app', {});\n * calendar.registerView(CustomView);\n * calendar.setView('custom');\n * ```\n *\n * @example Extending existing views via class inheritance\n * ```typescript\n * class ExtendedMonthView extends MonthView {\n *   static readonly meta: ViewMeta = { type: 'extended-month', label: 'Extended Month', shortLabel: 'EM' };\n *\n *   render(container, events, options) {\n *     super.render(container, events, options);\n *     // Add custom elements after base rendering\n *   }\n * }\n *\n * calendar.registerView(ExtendedMonthView);\n * ```\n */\nexport class Calendar<T = Date> {\n  private container: HTMLElement;\n  private config: ResolvedCalendarConfig;\n  private adapter: DateAdapter<T>;\n  private currentDate: T;\n  private currentViewType: string;\n  private eventManager: EventManager;\n  private dragController: DragController<T>;\n  private interactionController: InteractionController<T>;\n\n  // View system\n  private viewRegistry: ViewRegistry;\n  private activeView: BaseView<T> | null = null;\n  private viewContext!: ViewContext<T>;\n\n  /**\n   * Create a new Calendar instance\n   *\n   * @param containerSelector - CSS selector or HTMLElement for the calendar container\n   * @param config - Calendar configuration options\n   */\n  constructor(\n    containerSelector: string | HTMLElement,\n    config: ExtendedCalendarConfig = {},\n  ) {\n    // 1. Initialize container\n    if (typeof containerSelector === \"string\") {\n      const el = document.querySelector(containerSelector);\n      if (!el) {\n        throw new Error(`Calendar container not found: ${containerSelector}`);\n      }\n      this.container = el as HTMLElement;\n    } else {\n      this.container = containerSelector;\n    }\n\n    // 2. Merge configuration with defaults\n    this.config = this.mergeConfig(config);\n\n    // 3. Initialize date adapter (defaults to zero-dependency NativeDateAdapter)\n    this.adapter = (config.dateAdapter ||\n      new NativeDateAdapter()) as unknown as DateAdapter<T>;\n    this.currentDate = this.adapter.create();\n    this.currentViewType = this.config.view.type;\n\n    // 4. Initialize event manager\n    this.eventManager = new EventManager(config.events);\n\n    // 5. Initialize drag controller\n    this.dragController = new DragController<T>(\n      this.adapter,\n      this.config.draggable,\n      this.handleEventDrop.bind(this),\n      this.handleEventResize.bind(this),\n      this.config.theme.cellHeight,\n      this.config.dateFormats,\n    );\n\n    // 5.5. Initialize interaction controller\n    this.interactionController = new InteractionController<T>(\n      this.adapter,\n      this.config,\n      this.dragController,\n      () => this.currentViewType as ViewType,\n      this.eventManager,\n    );\n\n    // 6. Initialize view registry (no built-in views by default for tree-shaking)\n    // Use createCalendar() from presets for batteries-included experience\n    this.viewRegistry = config.viewRegistry || new ViewRegistry();\n\n    // 7. Validate that views are registered for the requested view type\n    if (this.viewRegistry.size === 0) {\n      throw new Error(\n        `Calendar: No views registered. ` +\n          `Use createCalendar() for batteries-included setup, or register views manually:\\n` +\n          `  import { Calendar, ViewRegistry, MonthView, WeekView, DayView } from '@taskgenius/calendar';\\n` +\n          `  const registry = new ViewRegistry();\\n` +\n          `  registry.register(MonthView);\\n` +\n          `  new Calendar('#app', { viewRegistry: registry });`,\n      );\n    }\n\n    if (!this.viewRegistry.has(this.currentViewType)) {\n      const available = this.viewRegistry.getTypes().join(\", \") || \"none\";\n      throw new Error(\n        `Calendar: View type '${this.currentViewType}' is not registered. ` +\n          `Available views: ${available}. ` +\n          `Either change view.type in config or register the required view.`,\n      );\n    }\n\n    // 8. Create view context\n    this.viewContext = this.createViewContext();\n\n    // 9. Initial render\n    this.render();\n  }\n\n  // ==========================================================================\n  // View Management Public API\n  // ==========================================================================\n\n  /**\n   * Register a custom view\n   *\n   * @param ViewClassArg - View class extending BaseView with static meta\n   * @param options - Registration options\n   *\n   * @example\n   * ```typescript\n   * class CustomView extends BaseView {\n   *   static readonly meta: ViewMeta = { type: 'custom', label: 'Custom', shortLabel: 'C' };\n   *   render(container, events) { ... }\n   * }\n   *\n   * calendar.registerView(CustomView);\n   * ```\n   */\n  registerView(\n    ViewClassArg: ViewClass<T>,\n    options?: ViewRegistrationOptions,\n  ): void {\n    this.viewRegistry.register(ViewClassArg, options);\n    // Re-render to update view switcher if needed\n    this.render();\n  }\n\n  /**\n   * Unregister a view by type\n   *\n   * @param type - View type to unregister\n   * @returns true if view was removed\n   */\n  unregisterView(type: string): boolean {\n    const result = this.viewRegistry.unregister(type);\n    if (result) {\n      // If current view was unregistered, switch to first available\n      if (this.currentViewType === type) {\n        const types = this.viewRegistry.getTypes();\n        if (types.length > 0) {\n          this.setView(types[0]!);\n        }\n      }\n      this.render();\n    }\n    return result;\n  }\n\n  /**\n   * Get all registered view metadata\n   *\n   * @returns Array of view metadata sorted by order\n   */\n  getRegisteredViews(): ViewMeta[] {\n    return this.viewRegistry.getAll();\n  }\n\n  /**\n   * Check if a view type is registered\n   *\n   * @param type - View type to check\n   */\n  hasView(type: string): boolean {\n    return this.viewRegistry.has(type);\n  }\n\n  /**\n   * Get the view registry for advanced manipulation\n   */\n  getViewRegistry(): ViewRegistry {\n    return this.viewRegistry;\n  }\n\n  /**\n   * Set the calendar view type\n   *\n   * @param type - View type (built-in or custom registered type)\n   */\n  setView(type: string): void {\n    if (!this.viewRegistry.has(type)) {\n      console.warn(`View type '${type}' is not registered. Ignoring.`);\n      return;\n    }\n\n    // Unmount previous view\n    if (this.activeView) {\n      this.activeView.onUnmount();\n    }\n\n    this.currentViewType = type;\n    this.config.onViewChange?.(type as ViewType);\n    this.render();\n  }\n\n  /**\n   * Get the current view type\n   */\n  getView(): string {\n    return this.currentViewType;\n  }\n\n  /**\n   * Get the active view instance\n   */\n  getActiveView(): BaseView<T> | null {\n    return this.activeView;\n  }\n\n  // ==========================================================================\n  // Event Management Public API\n  // ==========================================================================\n\n  /**\n   * Add a new event\n   *\n   * @param event - Event to add\n   */\n  addEvent(event: CalendarEvent): void {\n    this.eventManager.addEvent(event);\n    this.render();\n  }\n\n  /**\n   * Remove an event by ID\n   *\n   * @param id - Event ID to remove\n   */\n  removeEvent(id: string): void {\n    this.eventManager.removeEvent(id);\n    this.render();\n  }\n\n  /**\n   * Update an existing event\n   *\n   * @param id - Event ID to update\n   * @param updates - Partial event data to merge\n   */\n  updateEvent(id: string, updates: Partial<CalendarEvent>): void {\n    this.eventManager.updateEvent(id, updates);\n    this.render();\n  }\n\n  /**\n   * Get all events\n   */\n  getEvents(): CalendarEvent[] {\n    return this.eventManager.getEvents();\n  }\n\n  /**\n   * Set all events (replaces existing)\n   *\n   * @param events - New events array\n   */\n  setEvents(events: CalendarEvent[]): void {\n    this.eventManager.setEvents(events);\n    this.render();\n  }\n\n  // ==========================================================================\n  // Navigation Public API\n  // ==========================================================================\n\n  /**\n   * Navigate to next period\n   */\n  next(): void {\n    const unit = this.getNavigationUnit();\n    this.currentDate = this.adapter.add(this.currentDate, 1, unit);\n    this.viewContext.currentDate = this.currentDate;\n    this.config.onDateChange?.(this.toDate(this.currentDate));\n    this.render();\n  }\n\n  /**\n   * Navigate to previous period\n   */\n  prev(): void {\n    const unit = this.getNavigationUnit();\n    this.currentDate = this.adapter.add(this.currentDate, -1, unit);\n    this.viewContext.currentDate = this.currentDate;\n    this.config.onDateChange?.(this.toDate(this.currentDate));\n    this.render();\n  }\n\n  /**\n   * Navigate to today\n   */\n  today(): void {\n    this.currentDate = this.adapter.create();\n    this.viewContext.currentDate = this.currentDate;\n    this.config.onDateChange?.(this.toDate(this.currentDate));\n    this.render();\n  }\n\n  /**\n   * Navigate to a specific date\n   *\n   * @param date - Date string or Date object\n   */\n  goToDate(date: string | Date): void {\n    this.currentDate = this.adapter.create(date);\n    this.viewContext.currentDate = this.currentDate;\n    this.config.onDateChange?.(this.toDate(this.currentDate));\n    this.render();\n  }\n\n  /**\n   * Get the current date in ISO format\n   *\n   * @returns Date string in YYYY-MM-DD format (ISO 8601)\n   */\n  getCurrentDate(): string {\n    return this.adapter.format(this.currentDate, INTERNAL_DATA_FORMAT.date);\n  }\n\n  // ==========================================================================\n  // Utility Public API\n  // ==========================================================================\n\n  /**\n   * Destroy the calendar instance and cleanup\n   */\n  destroy(): void {\n    if (this.activeView) {\n      this.activeView.onUnmount();\n    }\n    this.dragController.destroy();\n    this.interactionController.destroy();\n    clearElement(this.container);\n  }\n\n  /**\n   * Force re-render the calendar\n   */\n  refresh(): void {\n    this.render();\n  }\n\n  /**\n   * Enable or disable drag-and-drop functionality\n   *\n   * @param enabled - Whether drag-and-drop should be enabled\n   */\n  setDraggable(enabled: boolean): void {\n    this.config.draggable.enabled = enabled;\n  }\n\n  /**\n   * Check if drag-and-drop is currently enabled\n   */\n  isDraggable(): boolean {\n    return this.config.draggable.enabled;\n  }\n\n  // ==========================================================================\n  // Private Methods\n  // ==========================================================================\n\n  private createViewContext(): ViewContext<T> {\n    return {\n      currentDate: this.currentDate,\n      adapter: this.adapter,\n      eventManager: this.eventManager,\n      dragController: this.dragController,\n      config: this.config,\n      requestRender: () => this.render(),\n      goToDate: (date: T | string | Date) => {\n        // Handle all date input types via the adapter\n        if (typeof date === \"string\" || date instanceof Date) {\n          this.goToDate(date);\n        } else {\n          // For adapter-native type T, convert to Date first\n          const nativeDate = this.toDate(date);\n          this.goToDate(nativeDate);\n        }\n      },\n      getCurrentView: () => this.currentViewType as ViewType,\n    };\n  }\n\n  private render(): void {\n    // Check if we can do an incremental update (same view type, existing structure)\n    const existingCalendar = this.container.querySelector(\".tg-calendar\");\n    const existingViewBody =\n      existingCalendar?.querySelector(\".tg-view-container\");\n    const isSameView = this.activeView?.getMeta().type === this.currentViewType;\n\n    // Save scroll position for time views\n    let preservedScrollTop: number | null = null;\n    const existingScroll = this.container.querySelector(\n      \".tg-time-grid-container\",\n    );\n    if (existingScroll) {\n      preservedScrollTop = existingScroll.scrollTop;\n    }\n\n    // Incremental update: only update view body if structure exists and view type unchanged\n    if (existingCalendar && existingViewBody && isSameView && this.activeView) {\n      // Update context\n      this.viewContext.currentDate = this.currentDate;\n\n      // Update header title (in-place)\n      const titleEl = existingCalendar.querySelector(\".tg-title\");\n      if (titleEl) {\n        titleEl.textContent = this.getHeaderTitle();\n      }\n\n      // Update view switcher active state\n      const viewBtns = existingCalendar.querySelectorAll(\".tg-view-btn\");\n      viewBtns.forEach((btn) => {\n        const btnEl = btn as HTMLElement;\n        if (btnEl.dataset[\"viewType\"] === this.currentViewType) {\n          btnEl.classList.add(\"tg-active\");\n        } else {\n          btnEl.classList.remove(\"tg-active\");\n        }\n      });\n\n      // Clear only the view body, not the entire container\n      clearElement(existingViewBody as HTMLElement);\n\n      // Re-render view content into existing container\n      this.activeView.render(\n        existingViewBody as HTMLElement,\n        this.eventManager.getEvents(),\n        { preservedScrollTop },\n      );\n\n      return;\n    }\n\n    // Full rebuild: view type changed or first render\n    clearElement(this.container);\n\n    // Create main container\n    const mainContainer = createElement(\"div\", \"tg-calendar\");\n    this.applyTheme(mainContainer);\n\n    // Get or create view instance BEFORE rendering header\n    // This ensures activeView is set correctly for getHeaderTitle()\n    const view = this.getOrCreateView();\n    if (view) {\n      // Update context\n      this.viewContext.currentDate = this.currentDate;\n    }\n\n    // Render header with dynamic view switcher (after view is created)\n    const header = this.renderHeader();\n    mainContainer.appendChild(header);\n\n    // Render view body\n    const viewBody = createElement(\"div\", \"tg-view-container\");\n\n    if (view) {\n      // Render view\n      view.render(viewBody, this.eventManager.getEvents(), {\n        preservedScrollTop,\n      });\n    }\n\n    mainContainer.appendChild(viewBody);\n    this.container.appendChild(mainContainer);\n\n    // Initialize interaction listeners\n    this.interactionController.init(mainContainer);\n  }\n\n  private getOrCreateView(): BaseView<T> | null {\n    // Check if we need to switch views\n    if (\n      this.activeView &&\n      this.activeView.getMeta().type === this.currentViewType\n    ) {\n      return this.activeView;\n    }\n\n    // Unmount previous view\n    if (this.activeView) {\n      this.activeView.onUnmount();\n    }\n\n    // Create new view\n    const view = this.viewRegistry.create<T>(this.currentViewType);\n    if (!view) {\n      console.error(`Failed to create view: ${this.currentViewType}`);\n      return null;\n    }\n\n    // Initialize and mount\n    view.init(this.viewContext);\n    view.onMount();\n    this.activeView = view;\n\n    return view;\n  }\n\n  private renderHeader(): HTMLElement {\n    const header = createElement(\"div\", \"tg-header\");\n\n    // Title\n    const title = createElement(\"h1\", \"tg-title\");\n    title.textContent = this.getHeaderTitle();\n    header.appendChild(title);\n\n    // View switcher - dynamically populated from registry\n    const viewSwitch = createElement(\"div\", \"tg-view-switch\");\n    const registeredViews = this.viewRegistry.getAll();\n\n    for (const viewMeta of registeredViews) {\n      const btn = createElement(\"button\", \"tg-view-btn\");\n      btn.textContent = viewMeta.shortLabel || viewMeta.label.charAt(0);\n      btn.title = viewMeta.label;\n      btn.dataset[\"viewType\"] = viewMeta.type;\n\n      if (this.currentViewType === viewMeta.type) {\n        btn.classList.add(\"tg-active\");\n      }\n\n      btn.onclick = () => this.setView(viewMeta.type);\n      viewSwitch.appendChild(btn);\n    }\n    header.appendChild(viewSwitch);\n\n    // Navigation\n    const nav = createElement(\"div\", \"tg-nav\");\n\n    const prevBtn = createElement(\"button\", \"tg-nav-btn\");\n    prevBtn.textContent = \"Previous\";\n    prevBtn.onclick = () => this.prev();\n    nav.appendChild(prevBtn);\n\n    const todayBtn = createElement(\"button\", \"tg-nav-btn tg-today\");\n    todayBtn.textContent = \"Today\";\n    todayBtn.onclick = () => this.today();\n    nav.appendChild(todayBtn);\n\n    const nextBtn = createElement(\"button\", \"tg-nav-btn\");\n    nextBtn.textContent = \"Next\";\n    nextBtn.onclick = () => this.next();\n    nav.appendChild(nextBtn);\n\n    header.appendChild(nav);\n\n    return header;\n  }\n\n  private getHeaderTitle(): string {\n    // Use active view's header title if available\n    if (this.activeView) {\n      return this.activeView.getHeaderTitle();\n    }\n\n    // Fallback to default\n    const format =\n      this.currentViewType === \"day\"\n        ? this.config.headerFormat.day\n        : this.config.headerFormat.month;\n    return this.adapter.format(this.currentDate, format);\n  }\n\n  private getNavigationUnit(): \"year\" | \"month\" | \"week\" | \"day\" {\n    // Use active view's navigation unit if available\n    if (this.activeView) {\n      return this.activeView.getNavigationUnit();\n    }\n\n    // Fallback to default based on view type\n    switch (this.currentViewType) {\n      case \"month\":\n        return \"month\";\n      case \"week\":\n        return \"week\";\n      case \"day\":\n        return \"day\";\n      default:\n        return \"month\";\n    }\n  }\n\n  /**\n   * Convert adapter date to native Date object\n   */\n  private toDate(adapterDate: T): Date {\n    return new Date(\n      this.adapter.year(adapterDate),\n      this.adapter.month(adapterDate),\n      this.adapter.date(adapterDate),\n      this.adapter.hour(adapterDate),\n      this.adapter.minute(adapterDate),\n    );\n  }\n\n  private handleEventDrop(\n    event: CalendarEvent,\n    newStart: Date,\n    newEnd: Date,\n  ): void {\n    // DEBUG: Log incoming event drop\n    console.log(\"[Calendar] handleEventDrop:\", {\n      eventId: event.id,\n      eventTitle: event.title,\n      originalStart: event.start,\n      originalEnd: event.end,\n      newStart: newStart.toISOString(),\n      newEnd: newEnd.toISOString(),\n    });\n\n    // IMPORTANT: Call the callback BEFORE updating internal state\n    this.config.onEventDrop?.(event, newStart, newEnd);\n\n    // Convert Date objects to ISO format strings for internal event storage\n    const newStartStr = this.adapter.format(\n      this.adapter.create(newStart),\n      INTERNAL_DATA_FORMAT.dateTime,\n    );\n    const newEndStr = this.adapter.format(\n      this.adapter.create(newEnd),\n      INTERNAL_DATA_FORMAT.dateTime,\n    );\n\n    // DEBUG: Log formatted strings\n    console.log(\"[Calendar] handleEventDrop - updating to:\", {\n      newStartStr,\n      newEndStr,\n    });\n\n    this.eventManager.updateEvent(event.id, {\n      start: newStartStr,\n      end: newEndStr,\n    });\n  }\n\n  private handleEventResize(\n    event: CalendarEvent,\n    newStart: Date,\n    newEnd: Date,\n  ): void {\n    // IMPORTANT: Call the callback BEFORE updating internal state\n    this.config.onEventResize?.(event, newStart, newEnd);\n\n    // Convert Date objects to ISO format strings for internal event storage\n    const newStartStr = this.adapter.format(\n      this.adapter.create(newStart),\n      INTERNAL_DATA_FORMAT.dateTime,\n    );\n    const newEndStr = this.adapter.format(\n      this.adapter.create(newEnd),\n      INTERNAL_DATA_FORMAT.dateTime,\n    );\n\n    this.eventManager.updateEvent(event.id, {\n      start: newStartStr,\n      end: newEndStr,\n    });\n  }\n\n  private mergeConfig(config: CalendarConfig): ResolvedCalendarConfig {\n    // Merge dateFormats with defaults\n    const dateFormats = {\n      date: config.dateFormats?.date || DEFAULT_DATE_FORMATS.date,\n      dateTime: config.dateFormats?.dateTime || DEFAULT_DATE_FORMATS.dateTime,\n      time: config.dateFormats?.time || DEFAULT_DATE_FORMATS.time,\n      monthHeader:\n        config.dateFormats?.monthHeader ||\n        config.headerFormat?.month ||\n        DEFAULT_DATE_FORMATS.monthHeader,\n      dayHeader:\n        config.dateFormats?.dayHeader ||\n        config.headerFormat?.day ||\n        DEFAULT_DATE_FORMATS.dayHeader,\n    };\n\n    // Backward compatibility: convert showWeekends=false to dayFilter\n    let dayFilter = config.view?.dayFilter;\n    if (!dayFilter && config.view?.showWeekends === false) {\n      dayFilter = (\n        _date: unknown,\n        context: import(\"../types\").DayFilterContext,\n      ) => {\n        return !context.isWeekend;\n      };\n    }\n\n    const resolvedView: ResolvedCalendarConfig[\"view\"] = {\n      type: config.view?.type || \"week\",\n      showDateHeader: config.view?.showDateHeader ?? true,\n      showWeekNumbers: config.view?.showWeekNumbers ?? false,\n      firstDayOfWeek: config.view?.firstDayOfWeek ?? 0,\n      showWeekends: config.view?.showWeekends ?? true,\n    };\n\n    // Add optional properties only if they exist\n    if (config.view?.maxEventsPerRow !== undefined) {\n      resolvedView.maxEventsPerRow = config.view.maxEventsPerRow;\n    }\n\n    if (dayFilter) {\n      resolvedView.dayFilter = dayFilter;\n    }\n    if (config.view?.timeFilter) {\n      resolvedView.timeFilter = config.view.timeFilter;\n    }\n    if (config.view?.timeFormatter) {\n      resolvedView.timeFormatter = config.view.timeFormatter;\n    }\n\n    const resolved: ResolvedCalendarConfig = {\n      view: resolvedView,\n      draggable: {\n        enabled: config.draggable?.enabled ?? true,\n        snapMinutes: config.draggable?.snapMinutes ?? 15,\n        ghostOpacity: config.draggable?.ghostOpacity ?? 0.5,\n        dateOnly: config.draggable?.dateOnly ?? false,\n      },\n      theme: {\n        primaryColor: config.theme?.primaryColor || \"#3b82f6\",\n        cellHeight: config.theme?.cellHeight || 60,\n        fontSize: {\n          header: config.theme?.fontSize?.header || \"14px\",\n          event: config.theme?.fontSize?.event || \"12px\",\n        },\n      },\n      showEventCounts: config.showEventCounts ?? false,\n      dateFormats,\n      headerFormat: {\n        month: dateFormats.monthHeader,\n        day: dateFormats.dayHeader,\n      },\n    };\n\n    if (config.onEventClick) resolved.onEventClick = config.onEventClick;\n    if (config.onEventDoubleClick)\n      resolved.onEventDoubleClick = config.onEventDoubleClick;\n    if (config.onEventContextMenu)\n      resolved.onEventContextMenu = config.onEventContextMenu;\n    if (config.onEventDrop) resolved.onEventDrop = config.onEventDrop;\n    if (config.onEventResize) resolved.onEventResize = config.onEventResize;\n    if (config.onViewChange) resolved.onViewChange = config.onViewChange;\n    if (config.onDateChange) resolved.onDateChange = config.onDateChange;\n    if (config.onDateClick) resolved.onDateClick = config.onDateClick;\n    if (config.onDateDoubleClick)\n      resolved.onDateDoubleClick = config.onDateDoubleClick;\n    if (config.onDateContextMenu)\n      resolved.onDateContextMenu = config.onDateContextMenu;\n    if (config.onTimeSlotClick)\n      resolved.onTimeSlotClick = config.onTimeSlotClick;\n    if (config.onTimeSlotDoubleClick)\n      resolved.onTimeSlotDoubleClick = config.onTimeSlotDoubleClick;\n    if (config.onTimeSlotContextMenu)\n      resolved.onTimeSlotContextMenu = config.onTimeSlotContextMenu;\n    if (config.onDateRangeSelect)\n      resolved.onDateRangeSelect = config.onDateRangeSelect;\n    if (config.onTimeRangeSelect)\n      resolved.onTimeRangeSelect = config.onTimeRangeSelect;\n    if (config.onRenderDateCell)\n      resolved.onRenderDateCell = config.onRenderDateCell;\n    if (config.onStyleEvent) resolved.onStyleEvent = config.onStyleEvent;\n    if (config.onRenderMoreEventsPopover)\n      resolved.onRenderMoreEventsPopover = config.onRenderMoreEventsPopover;\n    if (config.onRenderEvent) resolved.onRenderEvent = config.onRenderEvent;\n\n    return resolved;\n  }\n\n  private applyTheme(target: HTMLElement): void {\n    applyThemeVariables(target, this.config.theme);\n  }\n}\n","/**\n * Preset utilities for quick calendar setup\n *\n * These factory functions provide convenient ways to create fully-configured\n * calendars with all built-in views and adapters pre-registered.\n *\n * Use these when you don't need fine-grained control over tree-shaking\n * and want a quick setup experience.\n */\nimport type { CalendarConfig } from \"./types\";\nimport { Calendar, type ExtendedCalendarConfig } from \"./core/Calendar\";\nimport { ViewRegistry } from \"./views/ViewRegistry\";\nimport { MonthView } from \"./views/MonthView\";\nimport { WeekView, DayView } from \"./views/TimeView\";\nimport { DayJsAdapter } from \"./adapters/DayJsAdapter\";\nimport type { Dayjs } from \"dayjs\";\n\n/**\n * Configuration for createFullCalendar factory\n */\nexport type FullCalendarConfig = CalendarConfig;\n\n/**\n * Create a fully-configured calendar with all built-in views\n *\n * This is a convenience factory for users who want the complete\n * calendar experience without manual view registration.\n *\n * Note: This function imports all built-in views and DayJsAdapter,\n * which will include them in your bundle. For minimal bundle size,\n * use the Calendar class directly and register only needed views.\n *\n * @param containerSelector - CSS selector or HTMLElement\n * @param config - Calendar configuration\n * @returns Configured Calendar instance with all views registered\n *\n * @example\n * ```typescript\n * import { createFullCalendar } from '@taskgenius/calendar/presets';\n *\n * const calendar = createFullCalendar('#app', {\n *   view: { type: 'week' },\n *   events: [...]\n * });\n * ```\n */\nexport function createFullCalendar(\n  containerSelector: string | HTMLElement,\n  config: FullCalendarConfig = {},\n): Calendar<Dayjs> {\n  // Create a pre-populated view registry\n  const viewRegistry = new ViewRegistry();\n  viewRegistry.register(MonthView);\n  viewRegistry.register(WeekView);\n  viewRegistry.register(DayView);\n\n  // Build extended config with DayJsAdapter by default\n  const extendedConfig: ExtendedCalendarConfig = {\n    ...config,\n    viewRegistry,\n    dateAdapter: new DayJsAdapter(),\n  };\n\n  return new Calendar<Dayjs>(containerSelector, extendedConfig);\n}\n\n/**\n * Create a calendar with only month view registered\n *\n * Use this for a lighter bundle when you only need the month view.\n *\n * @param containerSelector - CSS selector or HTMLElement\n * @param config - Calendar configuration\n * @returns Calendar with month view only\n *\n * @example\n * ```typescript\n * import { createMonthCalendar } from '@taskgenius/calendar/presets';\n *\n * const calendar = createMonthCalendar('#app', {\n *   events: [...]\n * });\n * ```\n */\nexport function createMonthCalendar(\n  containerSelector: string | HTMLElement,\n  config: CalendarConfig = {},\n): Calendar<Date> {\n  const viewRegistry = new ViewRegistry();\n  viewRegistry.register(MonthView);\n\n  return new Calendar<Date>(containerSelector, {\n    ...config,\n    view: { ...config.view, type: \"month\" },\n    viewRegistry,\n  });\n}\n\n/**\n * Create a calendar with only week view registered\n *\n * Use this for a lighter bundle when you only need the week view.\n *\n * @param containerSelector - CSS selector or HTMLElement\n * @param config - Calendar configuration\n * @returns Calendar with week view only\n *\n * @example\n * ```typescript\n * import { createWeekCalendar } from '@taskgenius/calendar/presets';\n *\n * const calendar = createWeekCalendar('#app', {\n *   events: [...]\n * });\n * ```\n */\nexport function createWeekCalendar(\n  containerSelector: string | HTMLElement,\n  config: CalendarConfig = {},\n): Calendar<Date> {\n  const viewRegistry = new ViewRegistry();\n  viewRegistry.register(WeekView);\n\n  return new Calendar<Date>(containerSelector, {\n    ...config,\n    view: { ...config.view, type: \"week\" },\n    viewRegistry,\n  });\n}\n\n/**\n * Create a calendar with only day view registered\n *\n * Use this for the lightest bundle when you only need the day view.\n *\n * @param containerSelector - CSS selector or HTMLElement\n * @param config - Calendar configuration\n * @returns Calendar with day view only\n *\n * @example\n * ```typescript\n * import { createDayCalendar } from '@taskgenius/calendar/presets';\n *\n * const calendar = createDayCalendar('#app', {\n *   events: [...]\n * });\n * ```\n */\nexport function createDayCalendar(\n  containerSelector: string | HTMLElement,\n  config: CalendarConfig = {},\n): Calendar<Date> {\n  const viewRegistry = new ViewRegistry();\n  viewRegistry.register(DayView);\n\n  return new Calendar<Date>(containerSelector, {\n    ...config,\n    view: { ...config.view, type: \"day\" },\n    viewRegistry,\n  });\n}\n\n/**\n * Register all built-in views to an existing ViewRegistry\n *\n * Utility function for programmatic registration of all built-in views.\n *\n * @param registry - ViewRegistry to register views to\n *\n * @example\n * ```typescript\n * import { ViewRegistry, registerBuiltInViews } from '@taskgenius/calendar';\n *\n * const registry = new ViewRegistry();\n * registerBuiltInViews(registry);\n *\n * const calendar = new Calendar('#app', { viewRegistry: registry });\n * ```\n */\nexport function registerBuiltInViews(registry: ViewRegistry): void {\n  if (!registry.has(\"month\")) {\n    registry.register(MonthView);\n  }\n  if (!registry.has(\"week\")) {\n    registry.register(WeekView);\n  }\n  if (!registry.has(\"day\")) {\n    registry.register(DayView);\n  }\n}\n\n/**\n * Create a standard calendar with NativeDateAdapter and all built-in views.\n *\n * This is the recommended entry point for users who want a batteries-included\n * experience without worrying about view registration.\n *\n * For tree-shaking optimization (smaller bundles), use `new Calendar()` directly\n * and register only the views you need.\n *\n * @param containerSelector - CSS selector or HTMLElement\n * @param config - Calendar configuration\n * @returns Configured Calendar instance with all built-in views registered\n *\n * @example\n * ```typescript\n * import { createCalendar } from '@taskgenius/calendar';\n *\n * // Batteries-included: all views registered automatically\n * const calendar = createCalendar('#app', {\n *   view: { type: 'week' },\n *   events: [...]\n * });\n * ```\n *\n * @example Tree-shaking mode (advanced)\n * ```typescript\n * import { Calendar, ViewRegistry, MonthView } from '@taskgenius/calendar';\n *\n * // Only include MonthView in bundle\n * const registry = new ViewRegistry();\n * registry.register(MonthView);\n *\n * const calendar = new Calendar('#app', {\n *   viewRegistry: registry,\n *   view: { type: 'month' }\n * });\n * ```\n */\nexport function createCalendar(\n  containerSelector: string | HTMLElement,\n  config: CalendarConfig = {},\n): Calendar<Date> {\n  const viewRegistry = new ViewRegistry();\n  registerBuiltInViews(viewRegistry);\n\n  return new Calendar<Date>(containerSelector, {\n    ...config,\n    viewRegistry,\n  });\n}\n"],"names":["createElement","tag","className","attributes","el","document","key","value","Object","entries","setAttribute","setStyles","styles","assign","style","clearElement","innerHTML","querySelectorAll","selector","parent","DragController","constructor","adapter","config","onDrop","onResize","cellHeight","dateFormats","this","state","proxyElement","boundOnMove","onMove","bind","boundOnUp","onUp","resolveCellWidth","container","columnCount","rectWidth","getBoundingClientRect","width","computedWidth","parseFloat","getComputedStyle","offsetWidth","Math","max","getAllDayColumnCount","columnsVar","getPropertyValue","parseInt","initMonthDrag","event","renderCallback","enabled","onmousedown","e","button","stopPropagation","row","closest","allDayContainer","cellW","mode","target","classList","contains","startDate","parse","start","endDate","end","eventDurationDays","diff","startOf","elRect","clickXInEvent","clientX","left","eventWidth","clickOffsetDays","min","floor","startDrag","type","startX","startY","clientY","initTimeDrag","col","colRect","colW","origStartMin","hour","minute","origDuration","setCellHeight","height","isDragging","destroy","removeEventListener","removeProxy","stateData","body","cursor","id","forEach","add","createProxy","addEventListener","getElementById","appendChild","textContent","title","backgroundColor","color","padding","fontSize","visibility","top","transform","handleMonthMove","handleTimeMove","s","_a","elementFromPoint","_b","hoverDate","dataset","rowStart","rowRect","currentCellW","cellIdx","rect","colWidth","colIdx","calendarContainer","dayColumn","querySelector","baseDate","newStart","newEnd","startDateOnly","endDateOnly","duration","clickOffset","adjustedHoverDate","dateOnly","daysDiff","originalStartHour","originalStartMinute","originalEndHour","originalEndMinute","setMinute","setHour","originalHour","originalMinute","isSame","isBefore","isAfter","renderMonthGhost","tentativeStart","tentativeEnd","newDateBase","rawMins","snapMinutes","snappedMins","round","endMin","startMins","endMins","renderTimeGhost","remove","rows","length","rStart","rEnd","dStart","dEnd","startIdx","span","ghostEndIdx","eventBars","maxTop","bar","barLeftMatch","match","barWidthMatch","barLeftPct","barWidthPct","barStartIdx","barSpan","barTop","barHeight","offsetHeight","ghost","dayColumns","Array","from","firstColDateStr","lastColDateStr","firstColDate","lastColDate","dateStr","format","date","time","_e","toDate","adapterDate","Date","year","month","EventManager","initialEvents","events","addEvent","push","removeEvent","index","findIndex","splice","updateEvent","updates","find","getEvents","findEvent","clear","setEvents","count","InteractionController","dragController","currentView","eventManager","rangeState","boundHandleClick","handleClick","boundHandleDblClick","handleDblClick","boundHandleContextMenu","handleContextMenu","boundHandleMouseDown","handleMouseDown","boundHandleRangeMove","handleRangeMove","boundHandleRangeEnd","handleRangeEnd","init","clearRangePreview","cellEl","handleDateClick","colEl","handleTimeSlotClick","eventEl","eventId","getAttribute","getEventById","onEventDoubleClick","call","getDateFromCell","_d","_c","onDateDoubleClick","dateTime","getDateTimeFromSlot","_f","onTimeSlotDoubleClick","onEventContextMenu","onDateContextMenu","onTimeSlotContextMenu","preventDefault","onDateRangeSelect","onTimeRangeSelect","isSelecting","currentDate","viewType","columnEl","renderMonthRangePreview","renderTimeRangePreview","isStartAfterEnd","indexOf","relY","theme","draggable","rawMinutes","snappedMinutes","onDateClick","onTimeSlotClick","cells","rowEnd","i","cellDate","cell","columns","c","colDateStr","colDate","startMin","preview","applyThemeVariables","setProperty","primaryColor","hex","result","exec","hexToRgb","header","DEFAULT_DATE_FORMATS","INTERNAL_DATA_FORMAT","BaseView","mounted","context","onMount","onUnmount","onEventsUpdate","_events","onDateChange","_newDate","getNavigationUnit","getHeaderTitle","dayHeader","monthHeader","isMounted","getMeta","meta","ViewRegistry","views","Map","register","ViewClassArg","options","prototype","Error","name","label","has","override","set","ctor","unregister","delete","get","create","entry","getAll","values","map","sort","a","b","orderA","order","orderB","localeCompare","getTypes","keys","size","MonthEngine","firstDayOfWeek","showWeekends","generateGrid","dayFilter","monthStart","monthEnd","endOf","today","currentDayOfWeek","day","endDayOfWeek","expectedEndDay","weeks","curr","days","dayOfWeek","isWeekend","isToday","isThisMonth","shouldInclude","visible","calculateLayoutWithVisibleDays","visibleDays","firstVisibleDate","lastVisibleDate","rangeEvents","filter","eventStart","eventEnd","visualItems","coveredDays","disabled","colIndex","segments","segmentStart","prevDay","segmentSpan","current","nextExpectedDate","isEventStart","isEventEnd","isEventStartFinal","isEventEndFinal","totalSegments","seg","idx","item","slot","isStart","isEnd","sortKey","segmentIndex","slots","slotIdx","slotEnd","_sortKey","calculateLayout","weekStart","weekEnd","getWeekCount","MonthRenderer","engine","_theme","showEventCounts","_dateFormats","onRenderDateCell","onStyleEvent","maxEventsPerRow","onRenderMoreEventsPopover","onRenderEvent","activePopover","popoverCloseHandler","render","onEventClick","closePopover","renderHeader","weekDays","renderWeekRow","allDayNames","dayNames","firstDay","dayIndex","String","gridTemplateColumns","isDisabled","layout","visibleLayout","hiddenEventsByColumn","arr","effectiveMaxSlot","reduce","eventAreaHeight","minHeight","eventsByDateStr","dayEvents","renderDateCell","renderEventBar","hiddenEvents","moreEl","renderMoreIndicator","dateNum","isPastDue","isFuture","badge","toString","dateObj","customOpacity","bgColor","opacity","xOffset","yOffset","defaultRender","ctx","isAllDay","leftHandle","rightHandle","visibleMaxSlot","renderDefaultPopover","anchorEl","popover","toLocaleDateString","weekday","list","dotColor","colorDot","positionPopover","setTimeout","anchorRect","popoverRect","viewportHeight","window","innerHeight","viewportWidth","innerWidth","bottom","_MonthView","super","view","renderer","_options","requestRender","getEngine","getRenderer","shortLabel","MonthView","TimeEngine","generateColumns","generateTimeSlots","timeFilter","filterAndCalculateGeometry","groups","groupOverlappingEvents","group","calculateColumnPositions","ev","leftPercent","widthPercent","isSingleDayEvent","isCrossMidnightEvent","isAllDayEvent","getEventDaySpan","startHour","startMinute","endHour","endMinute","calculateAllDayLayout","allDayEvents","coveredColumns","prevCol","getCellHeight","targetDate","targetDayStart","eventStartDay","eventEndDay","totalDays","pixelsPerMinute","geometry","currentGroup","groupEnd","placed","numCols","offsetPerCol","widthMultiplier","leftOffset","some","other","expandedWidth","maxWidth","TimeRenderer","currentViewType","initialScrollTop","timeFormatter","timeSlots","timedEvents","allDaySection","renderAllDaySection","scrollWrap","bodyInner","axis","renderTimeAxis","colData","renderDayColumn","restoreScroll","scrollTop","defaultHour","targetSlotIndex","isConnected","requestAnimationFrame","dayName","dayNameEl","dateNumEl","section","spacer","eventsContainer","sectionHeight","renderAllDayEventBar","renderAllDayMoreIndicator","column","slotIndex","renderEventBlock","durationZIndex","zIndex","startTime","endTime","timeText","titleText","resizeHandleTop","resizeHandleBottom","_TimeView","arguments","timeViewType","preservedScrollTop","TimeView","_WeekView","WeekView","_DayView","DayView","Calendar$1","containerSelector","activeView","mergeConfig","dateAdapter","NativeDateAdapter","handleEventDrop","handleEventResize","interactionController","viewRegistry","available","join","viewContext","createViewContext","registerView","unregisterView","types","setView","getRegisteredViews","hasView","getViewRegistry","onViewChange","getView","getActiveView","next","unit","prev","goToDate","getCurrentDate","refresh","setDraggable","isDraggable","nativeDate","getCurrentView","existingCalendar","existingViewBody","isSameView","existingScroll","titleEl","btn","btnEl","mainContainer","applyTheme","getOrCreateView","viewBody","viewSwitch","registeredViews","viewMeta","charAt","onclick","nav","prevBtn","todayBtn","nextBtn","headerFormat","onEventDrop","newStartStr","newEndStr","onEventResize","_g","_h","_i","_date","resolvedView","_j","showDateHeader","_k","showWeekNumbers","_l","_m","_n","_o","_p","_q","resolved","_r","_s","ghostOpacity","_t","_u","_v","_w","_y","_x","_A","_z","registerBuiltInViews","registry","removeProperty","Calendar","extendedConfig","DayJsAdapter"],"mappings":"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"}