96 lines
3.3 KiB
TypeScript
96 lines
3.3 KiB
TypeScript
/**
|
|
* Custom hook for handling drag-and-drop from asset carousel to file inputs
|
|
* Enables dragging assets from "My Files" carousel into batch processing tools
|
|
*/
|
|
|
|
import { useEffect } from 'react';
|
|
|
|
interface UseDragFromCarouselOptions {
|
|
onAssetDrop: (assetIds: string[]) => void;
|
|
enabled?: boolean;
|
|
}
|
|
|
|
export function useDragFromCarousel({ onAssetDrop, enabled = true }: UseDragFromCarouselOptions) {
|
|
useEffect(() => {
|
|
if (!enabled) return;
|
|
|
|
const handleDragOver = (e: DragEvent) => {
|
|
// Check if dragging from carousel (has asset-id data)
|
|
const types = Array.from(e.dataTransfer?.types || []);
|
|
if (types.includes('application/x-asset-id')) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
e.dataTransfer!.dropEffect = 'copy';
|
|
|
|
// Add visual feedback
|
|
const target = e.currentTarget as HTMLElement;
|
|
if (target) {
|
|
target.classList.add('drag-over');
|
|
}
|
|
}
|
|
};
|
|
|
|
const handleDragLeave = (e: DragEvent) => {
|
|
const target = e.currentTarget as HTMLElement;
|
|
if (target) {
|
|
target.classList.remove('drag-over');
|
|
}
|
|
};
|
|
|
|
const handleDrop = (e: DragEvent) => {
|
|
const types = Array.from(e.dataTransfer?.types || []);
|
|
|
|
// Only handle if it's our asset drag
|
|
if (types.includes('application/x-asset-id')) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
const target = e.currentTarget as HTMLElement;
|
|
if (target) {
|
|
target.classList.remove('drag-over');
|
|
}
|
|
|
|
// Get asset ID from drag data
|
|
const assetId = e.dataTransfer?.getData('application/x-asset-id');
|
|
|
|
if (assetId) {
|
|
// Single asset
|
|
onAssetDrop([assetId]);
|
|
}
|
|
}
|
|
};
|
|
|
|
const attachListeners = () => {
|
|
// Find all file upload drop zones
|
|
const dropZones = document.querySelectorAll('[data-file-drop-zone]');
|
|
|
|
dropZones.forEach(zone => {
|
|
zone.addEventListener('dragover', handleDragOver as EventListener);
|
|
zone.addEventListener('dragleave', handleDragLeave as EventListener);
|
|
zone.addEventListener('drop', handleDrop as EventListener);
|
|
});
|
|
|
|
return dropZones;
|
|
};
|
|
|
|
// Initial attachment with a small delay to ensure DOM is ready
|
|
const timeoutId = setTimeout(() => {
|
|
attachListeners();
|
|
}, 100);
|
|
|
|
// Also try to attach immediately
|
|
const initialZones = attachListeners();
|
|
|
|
return () => {
|
|
clearTimeout(timeoutId);
|
|
|
|
// Clean up all drop zones
|
|
const dropZones = document.querySelectorAll('[data-file-drop-zone]');
|
|
dropZones.forEach(zone => {
|
|
zone.removeEventListener('dragover', handleDragOver as EventListener);
|
|
zone.removeEventListener('dragleave', handleDragLeave as EventListener);
|
|
zone.removeEventListener('drop', handleDrop as EventListener);
|
|
});
|
|
};
|
|
}, [onAssetDrop, enabled]);
|
|
}
|