- Update drag handler to work without requestUpdate calls - Remove duplicate modal methods (using WysiwygModalManager) - Clean up unused imports and methods - Ensure all DOM updates are programmatic - Add comprehensive test files for all features - Follow separation of concerns principles
129 lines
3.5 KiB
TypeScript
129 lines
3.5 KiB
TypeScript
import { type IBlock } from './wysiwyg.types.js';
|
|
|
|
export class WysiwygDragDropHandler {
|
|
private component: any;
|
|
private draggedBlockId: string | null = null;
|
|
private dragOverBlockId: string | null = null;
|
|
private dragOverPosition: 'before' | 'after' | null = null;
|
|
|
|
constructor(component: any) {
|
|
this.component = component;
|
|
}
|
|
|
|
/**
|
|
* Gets the current drag state
|
|
*/
|
|
get dragState() {
|
|
return {
|
|
draggedBlockId: this.draggedBlockId,
|
|
dragOverBlockId: this.dragOverBlockId,
|
|
dragOverPosition: this.dragOverPosition
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Handles drag start
|
|
*/
|
|
handleDragStart(e: DragEvent, block: IBlock): void {
|
|
if (!e.dataTransfer) return;
|
|
|
|
this.draggedBlockId = block.id;
|
|
e.dataTransfer.effectAllowed = 'move';
|
|
e.dataTransfer.setData('text/plain', block.id);
|
|
|
|
// Update component state (for parent drag handler access)
|
|
this.component.draggedBlockId = this.draggedBlockId;
|
|
|
|
// The parent component already handles adding dragging classes programmatically
|
|
}
|
|
|
|
/**
|
|
* Handles drag end
|
|
*/
|
|
handleDragEnd(): void {
|
|
this.draggedBlockId = null;
|
|
this.dragOverBlockId = null;
|
|
this.dragOverPosition = null;
|
|
|
|
// Update component state
|
|
this.component.draggedBlockId = null;
|
|
this.component.dragOverBlockId = null;
|
|
this.component.dragOverPosition = null;
|
|
|
|
// The parent component already handles removing dragging classes programmatically
|
|
}
|
|
|
|
/**
|
|
* Handles drag over
|
|
*/
|
|
handleDragOver(e: DragEvent, block: IBlock): void {
|
|
e.preventDefault();
|
|
if (!e.dataTransfer || !this.draggedBlockId || this.draggedBlockId === block.id) return;
|
|
|
|
e.dataTransfer.dropEffect = 'move';
|
|
|
|
const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
|
|
const midpoint = rect.top + rect.height / 2;
|
|
|
|
this.dragOverBlockId = block.id;
|
|
this.dragOverPosition = e.clientY < midpoint ? 'before' : 'after';
|
|
|
|
// Update component state
|
|
this.component.dragOverBlockId = this.dragOverBlockId;
|
|
this.component.dragOverPosition = this.dragOverPosition;
|
|
|
|
// The parent component already handles drag-over classes programmatically
|
|
}
|
|
|
|
/**
|
|
* Handles drag leave
|
|
*/
|
|
handleDragLeave(block: IBlock): void {
|
|
if (this.dragOverBlockId === block.id) {
|
|
this.dragOverBlockId = null;
|
|
this.dragOverPosition = null;
|
|
|
|
// Update component state
|
|
this.component.dragOverBlockId = null;
|
|
this.component.dragOverPosition = null;
|
|
|
|
// The parent component already handles removing drag-over classes programmatically
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles drop
|
|
*/
|
|
handleDrop(e: DragEvent, targetBlock: IBlock): void {
|
|
e.preventDefault();
|
|
|
|
if (!this.draggedBlockId || this.draggedBlockId === targetBlock.id) return;
|
|
|
|
// The parent component already has a handleDrop method that handles this programmatically
|
|
// We'll delegate to that to ensure proper programmatic rendering
|
|
this.component.handleDrop(e, targetBlock);
|
|
}
|
|
|
|
|
|
/**
|
|
* Checks if a block is being dragged
|
|
*/
|
|
isDragging(blockId: string): boolean {
|
|
return this.draggedBlockId === blockId;
|
|
}
|
|
|
|
/**
|
|
* Checks if a block has drag over state
|
|
*/
|
|
isDragOver(blockId: string): boolean {
|
|
return this.dragOverBlockId === blockId;
|
|
}
|
|
|
|
/**
|
|
* Gets drag over CSS classes for a block
|
|
*/
|
|
getDragOverClasses(blockId: string): string {
|
|
if (!this.isDragOver(blockId)) return '';
|
|
return this.dragOverPosition === 'before' ? 'drag-over-before' : 'drag-over-after';
|
|
}
|
|
} |