Adds drag column change event handling
Introduces support for moving events between columns during drag Tracks column changes and updates event positioning dynamically Enables smooth cross-column event dragging experience
This commit is contained in:
parent
159b023f60
commit
8b95f2735f
4 changed files with 79 additions and 4 deletions
|
|
@ -35,6 +35,7 @@ export const CoreEvents = {
|
||||||
EVENT_DRAG_MOVE: 'event:drag-move',
|
EVENT_DRAG_MOVE: 'event:drag-move',
|
||||||
EVENT_DRAG_END: 'event:drag-end',
|
EVENT_DRAG_END: 'event:drag-end',
|
||||||
EVENT_DRAG_CANCEL: 'event:drag-cancel',
|
EVENT_DRAG_CANCEL: 'event:drag-cancel',
|
||||||
|
EVENT_DRAG_COLUMN_CHANGE: 'event:drag-column-change',
|
||||||
|
|
||||||
// System events
|
// System events
|
||||||
ERROR: 'system:error',
|
ERROR: 'system:error',
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import { ICalendarEvent } from '../../types/CalendarTypes';
|
import { ICalendarEvent, IEventBus } from '../../types/CalendarTypes';
|
||||||
import { EventService } from '../../storage/events/EventService';
|
import { EventService } from '../../storage/events/EventService';
|
||||||
import { DateService } from '../../core/DateService';
|
import { DateService } from '../../core/DateService';
|
||||||
import { IGridConfig } from '../../core/IGridConfig';
|
import { IGridConfig } from '../../core/IGridConfig';
|
||||||
import { calculateEventPosition } from '../../utils/PositionUtils';
|
import { calculateEventPosition } from '../../utils/PositionUtils';
|
||||||
|
import { CoreEvents } from '../../constants/CoreEvents';
|
||||||
|
import { IDragColumnChangePayload } from '../../types/DragTypes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EventRenderer - Renders calendar events to the DOM
|
* EventRenderer - Renders calendar events to the DOM
|
||||||
|
|
@ -16,8 +18,35 @@ export class EventRenderer {
|
||||||
constructor(
|
constructor(
|
||||||
private eventService: EventService,
|
private eventService: EventService,
|
||||||
private dateService: DateService,
|
private dateService: DateService,
|
||||||
private gridConfig: IGridConfig
|
private gridConfig: IGridConfig,
|
||||||
) {}
|
private eventBus: IEventBus
|
||||||
|
) {
|
||||||
|
this.setupDragListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup listeners for drag-drop events
|
||||||
|
*/
|
||||||
|
private setupDragListeners(): void {
|
||||||
|
this.eventBus.on(CoreEvents.EVENT_DRAG_COLUMN_CHANGE, (e) => {
|
||||||
|
const payload = (e as CustomEvent<IDragColumnChangePayload>).detail;
|
||||||
|
this.handleColumnChange(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle event moving to a new column during drag
|
||||||
|
*/
|
||||||
|
private handleColumnChange(payload: IDragColumnChangePayload): void {
|
||||||
|
const eventsLayer = payload.newColumn.querySelector('swp-events-layer');
|
||||||
|
if (!eventsLayer) return;
|
||||||
|
|
||||||
|
// Move element to new column
|
||||||
|
eventsLayer.appendChild(payload.element);
|
||||||
|
|
||||||
|
// Preserve Y position
|
||||||
|
payload.element.style.top = `${payload.currentY}px`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render events for visible dates into day columns
|
* Render events for visible dates into day columns
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@ import {
|
||||||
IDragStartPayload,
|
IDragStartPayload,
|
||||||
IDragMovePayload,
|
IDragMovePayload,
|
||||||
IDragEndPayload,
|
IDragEndPayload,
|
||||||
IDragCancelPayload
|
IDragCancelPayload,
|
||||||
|
IDragColumnChangePayload
|
||||||
} from '../types/DragTypes';
|
} from '../types/DragTypes';
|
||||||
|
|
||||||
interface DragState {
|
interface DragState {
|
||||||
|
|
@ -17,6 +18,7 @@ interface DragState {
|
||||||
startY: number;
|
startY: number;
|
||||||
mouseOffset: IMousePosition;
|
mouseOffset: IMousePosition;
|
||||||
columnElement: HTMLElement;
|
columnElement: HTMLElement;
|
||||||
|
currentColumn: HTMLElement;
|
||||||
targetY: number;
|
targetY: number;
|
||||||
currentY: number;
|
currentY: number;
|
||||||
animationId: number;
|
animationId: number;
|
||||||
|
|
@ -36,6 +38,7 @@ export class DragDropManager {
|
||||||
private mouseDownPosition: IMousePosition | null = null;
|
private mouseDownPosition: IMousePosition | null = null;
|
||||||
private pendingElement: HTMLElement | null = null;
|
private pendingElement: HTMLElement | null = null;
|
||||||
private pendingMouseOffset: IMousePosition | null = null;
|
private pendingMouseOffset: IMousePosition | null = null;
|
||||||
|
private container: HTMLElement | null = null;
|
||||||
|
|
||||||
private readonly DRAG_THRESHOLD = 5;
|
private readonly DRAG_THRESHOLD = 5;
|
||||||
private readonly INTERPOLATION_FACTOR = 0.3;
|
private readonly INTERPOLATION_FACTOR = 0.3;
|
||||||
|
|
@ -49,6 +52,7 @@ export class DragDropManager {
|
||||||
* Initialize drag-drop on a container element
|
* Initialize drag-drop on a container element
|
||||||
*/
|
*/
|
||||||
init(container: HTMLElement): void {
|
init(container: HTMLElement): void {
|
||||||
|
this.container = container;
|
||||||
container.addEventListener('pointerdown', this.handlePointerDown);
|
container.addEventListener('pointerdown', this.handlePointerDown);
|
||||||
document.addEventListener('pointermove', this.handlePointerMove);
|
document.addEventListener('pointermove', this.handlePointerMove);
|
||||||
document.addEventListener('pointerup', this.handlePointerUp);
|
document.addEventListener('pointerup', this.handlePointerUp);
|
||||||
|
|
@ -169,6 +173,7 @@ export class DragDropManager {
|
||||||
startY,
|
startY,
|
||||||
mouseOffset,
|
mouseOffset,
|
||||||
columnElement,
|
columnElement,
|
||||||
|
currentColumn: columnElement,
|
||||||
targetY: Math.max(0, targetY),
|
targetY: Math.max(0, targetY),
|
||||||
currentY: startY,
|
currentY: startY,
|
||||||
animationId: 0
|
animationId: 0
|
||||||
|
|
@ -193,6 +198,22 @@ export class DragDropManager {
|
||||||
private updateDragTarget(e: PointerEvent): void {
|
private updateDragTarget(e: PointerEvent): void {
|
||||||
if (!this.dragState) return;
|
if (!this.dragState) return;
|
||||||
|
|
||||||
|
// Check for column change
|
||||||
|
const columnAtPoint = this.getColumnAtPoint(e.clientX);
|
||||||
|
if (columnAtPoint && columnAtPoint !== this.dragState.currentColumn) {
|
||||||
|
const payload: IDragColumnChangePayload = {
|
||||||
|
eventId: this.dragState.eventId,
|
||||||
|
element: this.dragState.element,
|
||||||
|
previousColumn: this.dragState.currentColumn,
|
||||||
|
newColumn: columnAtPoint,
|
||||||
|
currentY: this.dragState.currentY
|
||||||
|
};
|
||||||
|
|
||||||
|
this.eventBus.emit(CoreEvents.EVENT_DRAG_COLUMN_CHANGE, payload);
|
||||||
|
this.dragState.currentColumn = columnAtPoint;
|
||||||
|
this.dragState.columnElement = columnAtPoint;
|
||||||
|
}
|
||||||
|
|
||||||
const columnRect = this.dragState.columnElement.getBoundingClientRect();
|
const columnRect = this.dragState.columnElement.getBoundingClientRect();
|
||||||
const targetY = e.clientY - columnRect.top - this.dragState.mouseOffset.y;
|
const targetY = e.clientY - columnRect.top - this.dragState.mouseOffset.y;
|
||||||
|
|
||||||
|
|
@ -204,6 +225,22 @@ export class DragDropManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find column element at given X coordinate
|
||||||
|
*/
|
||||||
|
private getColumnAtPoint(clientX: number): HTMLElement | null {
|
||||||
|
if (!this.container) return null;
|
||||||
|
|
||||||
|
const columns = this.container.querySelectorAll('swp-day-column');
|
||||||
|
for (const col of columns) {
|
||||||
|
const rect = col.getBoundingClientRect();
|
||||||
|
if (clientX >= rect.left && clientX <= rect.right) {
|
||||||
|
return col as HTMLElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private animateDrag = (): void => {
|
private animateDrag = (): void => {
|
||||||
if (!this.dragState) return;
|
if (!this.dragState) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,3 +37,11 @@ export interface IDragCancelPayload {
|
||||||
element: HTMLElement;
|
element: HTMLElement;
|
||||||
startY: number; // Position to animate back to
|
startY: number; // Position to animate back to
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IDragColumnChangePayload {
|
||||||
|
eventId: string;
|
||||||
|
element: HTMLElement;
|
||||||
|
previousColumn: HTMLElement;
|
||||||
|
newColumn: HTMLElement;
|
||||||
|
currentY: number;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue