diff --git a/src/managers/ResizeHandleManager.ts b/src/managers/ResizeHandleManager.ts index f43d5e4..df14582 100644 --- a/src/managers/ResizeHandleManager.ts +++ b/src/managers/ResizeHandleManager.ts @@ -1,39 +1,37 @@ +import { eventBus } from '../core/EventBus'; +import { CoreEvents } from '../constants/CoreEvents'; + export class ResizeHandleManager { - private resizeZoneHeight =15; // Must match CSS ::after height - private lastHoveredEvent: HTMLElement | null = null; + private resizeZoneHeight = 15; // Must match CSS ::after height + private cachedEvents: HTMLElement[] = []; public initialize(): void { + this.refreshEventCache(); this.setupEventListeners(); } + private refreshEventCache(): void { + this.cachedEvents = Array.from( + document.querySelectorAll('swp-day-columns swp-event') + ); + } + private setupEventListeners(): void { - - // Listen to global mouseover from document - document.addEventListener('mouseover', (e: MouseEvent) => { - this.handleGlobalMouseOver(e); - }); - document.addEventListener('mousemove', (e: MouseEvent) => { this.handleGlobalMouseMove(e); }); - document.addEventListener('mouseout', (e: MouseEvent) => { - this.handleGlobalMouseOut(e); - }); - } - - private handleGlobalMouseOver(e: MouseEvent): void { - const target = e.target as HTMLElement; - const eventElement = target.closest('swp-day-columns swp-event'); - - if (eventElement) { - this.lastHoveredEvent = eventElement; - } + eventBus.on(CoreEvents.GRID_RENDERED, () => this.refreshEventCache()); + eventBus.on(CoreEvents.EVENTS_RENDERED, () => this.refreshEventCache()); + eventBus.on(CoreEvents.EVENT_CREATED, () => this.refreshEventCache()); + eventBus.on(CoreEvents.EVENT_UPDATED, () => this.refreshEventCache()); + eventBus.on(CoreEvents.EVENT_DELETED, () => this.refreshEventCache()); + eventBus.on('drag:end', () => this.refreshEventCache()); } private handleGlobalMouseMove(e: MouseEvent): void { - // Check all events to see if mouse is in their resize zone - const events = document.querySelectorAll('swp-day-columns swp-event'); + // Check all cached events to see if mouse is in their resize zone + const events = this.cachedEvents; events.forEach(eventElement => { const rect = eventElement.getBoundingClientRect(); @@ -43,13 +41,13 @@ export class ResizeHandleManager { // Check if mouse is within element bounds horizontally const isInHorizontalBounds = mouseX >= rect.left && mouseX <= rect.right; - // Check if mouse is in bottom 25px of the element + // Check if mouse is in bottom resize zone of the element const distanceFromBottom = rect.bottom - mouseY; const isInResizeZone = distanceFromBottom >= 0 && distanceFromBottom <= this.resizeZoneHeight; if (isInHorizontalBounds && isInResizeZone) { this.showResizeIndicator(eventElement); - console.log('✅ In resize zone - bottom 25px'); + console.log(`✅ In resize zone - bottom ${this.resizeZoneHeight}px`); } else { this.hideResizeIndicator(eventElement); } @@ -75,15 +73,4 @@ export class ResizeHandleManager { } eventElement.removeAttribute('data-resize-hover'); } - - private handleGlobalMouseOut(e: MouseEvent): void { - const target = e.target as HTMLElement; - const eventElement = target.closest('swp-day-columns swp-event'); - - if (eventElement) { - // Don't remove immediately - let mousemove handle it - } - } - - } diff --git a/wwwroot/css/calendar-events-css.css b/wwwroot/css/calendar-events-css.css index 1607f07..0a4f544 100644 --- a/wwwroot/css/calendar-events-css.css +++ b/wwwroot/css/calendar-events-css.css @@ -73,17 +73,34 @@ swp-day-columns swp-event:hover { /* Resize handle indicator - created by JavaScript */ swp-resize-indicator { position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 15px; - background-image: url('data:image/svg+xml;utf8,'); - background-position: center center; - background-repeat: no-repeat; + bottom: -3px; + left: 50%; + transform: translateX(-50%); + width: 40px; + height: 6px; + background: var(--color-primary); + border-radius: 3px; pointer-events: none; - z-index: 10; + z-index: 30; opacity: 0; - animation: fadeIn 0.8s ease forwards; + animation: fadeIn 0.3s ease forwards; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); +} + +/* Grip dots on handle */ +swp-resize-indicator::before { + content: ''; + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + width: 12px; + height: 2px; + background: rgba(255, 255, 255, 0.7); + border-radius: 1px; + box-shadow: + -5px 0 0 rgba(255, 255, 255, 0.7), + 5px 0 0 rgba(255, 255, 255, 0.7); } @keyframes fadeIn { @@ -97,6 +114,7 @@ swp-resize-indicator { swp-day-columns swp-event[data-resize-hover="true"] { cursor: ns-resize; + overflow: visible; } swp-day-columns swp-event-time {