diff --git a/src/v2/features/headerdrawer/HeaderDrawerRenderer.ts b/src/v2/features/headerdrawer/HeaderDrawerRenderer.ts index 9927f29..5fed51b 100644 --- a/src/v2/features/headerdrawer/HeaderDrawerRenderer.ts +++ b/src/v2/features/headerdrawer/HeaderDrawerRenderer.ts @@ -218,8 +218,10 @@ export class HeaderDrawerRenderer { // Remember if drawer was already expanded this.wasExpandedBeforeDrag = this.headerDrawerManager.isExpanded(); - // Expand drawer with animation - this.headerDrawerManager.expand(); + // Expand to at least 1 row if collapsed, otherwise keep current height + if (!this.wasExpandedBeforeDrag) { + this.headerDrawerManager.expandToRows(1); + } // Store reference to source element this.sourceElement = payload.element; @@ -228,10 +230,16 @@ export class HeaderDrawerRenderer { const item = document.createElement('swp-header-item'); item.dataset.eventId = payload.eventId; item.dataset.itemType = payload.itemType; - item.dataset.date = payload.sourceDate; item.dataset.duration = String(payload.duration); item.textContent = payload.title; + // Set start/end as ISO dates (for recalculateDrawerLayout) + const startDate = new Date(payload.sourceDate); + const endDate = new Date(payload.sourceDate); + endDate.setDate(endDate.getDate() + payload.duration - 1); + item.dataset.start = startDate.toISOString(); + item.dataset.end = endDate.toISOString(); + // Apply color class if present if (payload.colorClass) { item.classList.add(payload.colorClass); @@ -259,13 +267,19 @@ export class HeaderDrawerRenderer { private handleDragMove(payload: IDragMoveHeaderPayload): void { if (!this.currentItem) return; - // Update column position (duration=1 for now) + // Update column position const col = payload.columnIndex + 1; const duration = parseInt(this.currentItem.dataset.duration || '1', 10); const endCol = col + duration; this.currentItem.style.gridArea = `1 / ${col} / 2 / ${endCol}`; - this.currentItem.dataset.date = payload.dateKey; + + // Update start/end dates based on new position + const startDate = new Date(payload.dateKey); + const endDate = new Date(payload.dateKey); + endDate.setDate(endDate.getDate() + duration - 1); + this.currentItem.dataset.start = startDate.toISOString(); + this.currentItem.dataset.end = endDate.toISOString(); } /** @@ -286,13 +300,74 @@ export class HeaderDrawerRenderer { // Remove dragging state this.currentItem.classList.remove('dragging'); - // TODO: Emit event to persist allDay=true change + // Recalculate layout for all items in drawer + this.recalculateDrawerLayout(); // Clear references this.currentItem = null; this.sourceElement = null; } + /** + * Recalculate layout for all items currently in the drawer + * Called after drop to reposition items and adjust height + */ + private recalculateDrawerLayout(): void { + const drawer = document.querySelector('swp-header-drawer'); + if (!drawer) return; + + const items = Array.from(drawer.querySelectorAll('swp-header-item')) as HTMLElement[]; + if (items.length === 0) return; + + // Get visible dates from existing items + const visibleDates = this.getVisibleDatesFromDOM(); + if (visibleDates.length === 0) return; + + // Build layout data from DOM items + const itemData = items.map(item => ({ + element: item, + start: new Date(item.dataset.start || ''), + end: new Date(item.dataset.end || '') + })); + + // Calculate new layout using track algorithm + const tracks: boolean[][] = [new Array(visibleDates.length).fill(false)]; + + for (const item of itemData) { + const startCol = this.getColIndex(item.start, visibleDates); + const endCol = this.getColIndex(item.end, visibleDates); + + const colStart = Math.max(0, startCol); + const colEnd = (endCol !== -1 ? endCol : visibleDates.length - 1) + 1; + + const row = this.findAvailableRow(tracks, colStart, colEnd); + + for (let c = colStart; c < colEnd; c++) { + tracks[row][c] = true; + } + + // Update element position + item.element.style.gridArea = `${row + 1} / ${colStart + 1} / ${row + 2} / ${colEnd + 1}`; + } + + // Update drawer height + const rowCount = tracks.length; + this.headerDrawerManager.expandToRows(rowCount); + } + + /** + * Get visible dates from header columns in DOM + */ + private getVisibleDatesFromDOM(): string[] { + const columns = document.querySelectorAll('swp-day-column'); + const dates: string[] = []; + columns.forEach(col => { + const date = (col as HTMLElement).dataset.date; + if (date && !dates.includes(date)) dates.push(date); + }); + return dates; + } + /** * Cleanup preview item and restore source visibility */ diff --git a/wwwroot/css/v2/calendar-v2-layout.css b/wwwroot/css/v2/calendar-v2-layout.css index 7edd7ab..45fe8af 100644 --- a/wwwroot/css/v2/calendar-v2-layout.css +++ b/wwwroot/css/v2/calendar-v2-layout.css @@ -77,9 +77,6 @@ swp-header-drawer { grid-template-columns: subgrid; grid-column: 1 / -1; grid-row: 2; - grid-auto-rows: 28px; - gap: 2px 0; - height: 0; overflow: hidden; background: var(--color-background-alt); border-bottom: 1px solid var(--color-border);