mirror of
https://github.com/streamich/react-use.git
synced 2025-12-08 18:02:14 +00:00
86 lines
2.2 KiB
TypeScript
86 lines
2.2 KiB
TypeScript
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<boolean>(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;
|