import { type DragEvent as ReactDragEvent, type Dispatch, type SetStateAction, useCallback, useMemo, } from 'react'; import { ASSET_DRAG_MIME_TYPE, getDraggedAssetId, hasDataTransferType, } from './ImageCanvasEditorModel'; import type { EditorAsset, EditorAssetFolder } from './ImageCanvasEditorTypes'; type UploadFilesToCanvasOptions = { folderId?: string; canvasPoint: { x: number; y: number }; addToCanvas: true; }; type UseImageCanvasCanvasDropWorkflowOptions = { assets: EditorAsset[]; assetFolders: EditorAssetFolder[]; setUploadDropTarget: Dispatch>; updateAssetMoveDropFolder: (folderId: string | null) => void; getCanvasDropPoint: (clientX: number, clientY: number) => { x: number; y: number; }; addAssetLayer: ( asset: EditorAsset, position?: { x: number; y: number }, ) => void; addUploadedFiles: ( files: FileList | File[], options: UploadFilesToCanvasOptions, ) => void; }; export function useImageCanvasCanvasDropWorkflow({ assets, assetFolders, setUploadDropTarget, updateAssetMoveDropFolder, getCanvasDropPoint, addAssetLayer, addUploadedFiles, }: UseImageCanvasCanvasDropWorkflowOptions) { const handleCanvasDragOver = useCallback( (event: ReactDragEvent) => { if (hasDataTransferType(event.dataTransfer, ASSET_DRAG_MIME_TYPE)) { event.preventDefault(); setUploadDropTarget('canvas'); event.dataTransfer.dropEffect = 'copy'; return; } if (hasDataTransferType(event.dataTransfer, 'Files')) { event.preventDefault(); setUploadDropTarget('canvas'); event.dataTransfer.dropEffect = 'copy'; } }, [setUploadDropTarget], ); const handleCanvasDragLeave = useCallback( (event: ReactDragEvent) => { if (!event.currentTarget.contains(event.relatedTarget as Node | null)) { setUploadDropTarget((currentTarget) => currentTarget === 'canvas' ? null : currentTarget, ); } }, [setUploadDropTarget], ); const handleCanvasDrop = useCallback( (event: ReactDragEvent) => { const draggedAssetId = getDraggedAssetId(event.dataTransfer); if (draggedAssetId) { const draggedAsset = assets.find((asset) => asset.id === draggedAssetId); if (!draggedAsset) { return; } event.preventDefault(); setUploadDropTarget(null); updateAssetMoveDropFolder(null); addAssetLayer( draggedAsset, getCanvasDropPoint(event.clientX, event.clientY), ); return; } const files = event.dataTransfer.files; if (!files.length) { return; } event.preventDefault(); setUploadDropTarget(null); updateAssetMoveDropFolder(null); const canvasPoint = getCanvasDropPoint(event.clientX, event.clientY); const defaultFolder = assetFolders.find((folder) => folder.systemDefault) ?? assetFolders[0]; addUploadedFiles(files, { folderId: defaultFolder?.id, canvasPoint, addToCanvas: true, }); }, [ addAssetLayer, addUploadedFiles, assetFolders, assets, getCanvasDropPoint, setUploadDropTarget, updateAssetMoveDropFolder, ], ); return useMemo( () => ({ handleCanvasDragOver, handleCanvasDragLeave, handleCanvasDrop, }), [handleCanvasDragLeave, handleCanvasDragOver, handleCanvasDrop], ); }