Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | 3x 99x 99x 7x 7x 7x 5x 99x 2x 2x 2x 99x 7x 7x 7x 7x 3x 99x 99x | // src/hooks/useDragAndDrop.ts
import { useState, useCallback } from 'react';
interface UseDragAndDropOptions {
/**
* Callback function that is triggered when files are dropped onto the element.
* @param files The FileList object from the drop event.
*/
onFilesDropped: (files: FileList) => void;
/**
* A boolean to disable the drag-and-drop functionality.
*/
disabled?: boolean;
}
/**
* A reusable hook to manage drag-and-drop functionality for a UI element.
*
* @param options - Configuration for the hook, including the onDrop callback and disabled state.
* @returns An object containing the `isDragging` state and props to be spread onto the dropzone element.
*/
export const useDragAndDrop = <T extends HTMLElement>({
onFilesDropped,
disabled = false,
}: UseDragAndDropOptions) => {
const [isDragging, setIsDragging] = useState(false);
const handleDragEnter = useCallback(
(e: React.DragEvent<T>) => {
e.preventDefault();
e.stopPropagation();
if (!disabled) {
setIsDragging(true);
}
},
[disabled],
);
const handleDragLeave = useCallback((e: React.DragEvent<T>) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
}, []);
const handleDrop = useCallback(
(e: React.DragEvent<T>) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
if (!disabled && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
onFilesDropped(e.dataTransfer.files);
}
},
[disabled, onFilesDropped],
);
// onDragOver must also be handled to allow onDrop to fire.
const handleDragOver = handleDragEnter;
return {
isDragging,
dropzoneProps: {
onDragEnter: handleDragEnter,
onDragLeave: handleDragLeave,
onDrop: handleDrop,
onDragOver: handleDragOver,
},
};
};
|