90 lines
2.7 KiB
TypeScript
90 lines
2.7 KiB
TypeScript
|
|
export class ResizeHandleManager {
|
||
|
|
private resizeZoneHeight =15; // Must match CSS ::after height
|
||
|
|
private lastHoveredEvent: HTMLElement | null = null;
|
||
|
|
|
||
|
|
public initialize(): void {
|
||
|
|
this.setupEventListeners();
|
||
|
|
}
|
||
|
|
|
||
|
|
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<HTMLElement>('swp-day-columns swp-event');
|
||
|
|
|
||
|
|
if (eventElement) {
|
||
|
|
this.lastHoveredEvent = eventElement;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private handleGlobalMouseMove(e: MouseEvent): void {
|
||
|
|
// Check all events to see if mouse is in their resize zone
|
||
|
|
const events = document.querySelectorAll<HTMLElement>('swp-day-columns swp-event');
|
||
|
|
|
||
|
|
events.forEach(eventElement => {
|
||
|
|
const rect = eventElement.getBoundingClientRect();
|
||
|
|
const mouseY = e.clientY;
|
||
|
|
const mouseX = e.clientX;
|
||
|
|
|
||
|
|
// 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
|
||
|
|
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');
|
||
|
|
} else {
|
||
|
|
this.hideResizeIndicator(eventElement);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
private showResizeIndicator(eventElement: HTMLElement): void {
|
||
|
|
// Check if indicator already exists
|
||
|
|
let indicator = eventElement.querySelector<HTMLElement>('swp-resize-indicator');
|
||
|
|
|
||
|
|
if (!indicator) {
|
||
|
|
indicator = document.createElement('swp-resize-indicator');
|
||
|
|
eventElement.appendChild(indicator);
|
||
|
|
}
|
||
|
|
|
||
|
|
eventElement.setAttribute('data-resize-hover', 'true');
|
||
|
|
}
|
||
|
|
|
||
|
|
private hideResizeIndicator(eventElement: HTMLElement): void {
|
||
|
|
const indicator = eventElement.querySelector<HTMLElement>('swp-resize-indicator');
|
||
|
|
if (indicator) {
|
||
|
|
indicator.remove();
|
||
|
|
}
|
||
|
|
eventElement.removeAttribute('data-resize-hover');
|
||
|
|
}
|
||
|
|
|
||
|
|
private handleGlobalMouseOut(e: MouseEvent): void {
|
||
|
|
const target = e.target as HTMLElement;
|
||
|
|
const eventElement = target.closest<HTMLElement>('swp-day-columns swp-event');
|
||
|
|
|
||
|
|
if (eventElement) {
|
||
|
|
// Don't remove immediately - let mousemove handle it
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
}
|