import { useMemo, useState } from 'react'; import useMountedState from './useMountedState'; import { noop } from './misc/util'; export interface DropAreaState { over: boolean; } export interface DropAreaBond { onDragOver: React.DragEventHandler; onDragEnter: React.DragEventHandler; onDragLeave: React.DragEventHandler; onDrop: React.DragEventHandler; onPaste: React.ClipboardEventHandler; } export interface DropAreaOptions { onFiles?: (files: File[], event?) => void; onText?: (text: string, event?) => void; onUri?: (url: string, event?) => void; } /* const defaultState: DropAreaState = { over: false, }; */ const createProcess = (options: DropAreaOptions, mounted: boolean) => (dataTransfer: DataTransfer, event) => { const uri = dataTransfer.getData('text/uri-list'); if (uri) { (options.onUri || noop)(uri, event); return; } if (dataTransfer.files && dataTransfer.files.length) { (options.onFiles || noop)(Array.from(dataTransfer.files), event); return; } if (dataTransfer.items && dataTransfer.items.length) { dataTransfer.items[0].getAsString((text) => { if (mounted) { (options.onText || noop)(text, event); } }); } }; const createBond = (process, setOver): DropAreaBond => ({ onDragOver: (event) => { event.preventDefault(); }, onDragEnter: (event) => { event.preventDefault(); setOver(true); }, onDragLeave: () => { setOver(false); }, onDrop: (event) => { event.preventDefault(); event.persist(); setOver(false); process(event.dataTransfer, event); }, onPaste: (event) => { event.persist(); process(event.clipboardData, event); }, }); const useDropArea = (options: DropAreaOptions = {}): [DropAreaBond, DropAreaState] => { const { onFiles, onText, onUri } = options; const isMounted = useMountedState(); const [over, setOver] = useState(false); const process = useMemo(() => createProcess(options, isMounted()), [onFiles, onText, onUri]); const bond: DropAreaBond = useMemo(() => createBond(process, setOver), [process, setOver]); return [bond, { over }]; }; export default useDropArea;