From 70dce9fd59a7d2fb0882a8c237d2b489e503b2a6 Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Tue, 7 Oct 2025 17:16:00 +0200 Subject: [PATCH] Improves event resize handle interaction Enhances the resize handle indicator for calendar events by using cached event elements for efficiency. This eliminates the need to constantly query the DOM, and only refreshes the cache on relevant event changes. Additionally updates the resize indicator style for improved visual clarity and user experience. --- src/managers/ResizeHandleManager.ts | 57 +++++++++++------------------ wwwroot/css/calendar-events-css.css | 36 +++++++++++++----- 2 files changed, 49 insertions(+), 44 deletions(-) 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 {