-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
/
Copy pathuseDrop.ts
99 lines (81 loc) Β· 2.5 KB
/
useDrop.ts
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { useCallback, useEffect, useMemo, useState } from 'react';
import { noop, off, on } 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 createProcess = (options: DropAreaOptions) => (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 (event.clipboardData) {
const text = event.clipboardData.getData('text');
(options.onText || noop)(text, event);
return;
}
};
const useDrop = (options: DropAreaOptions = {}, args = []): DropAreaState => {
const { onFiles, onText, onUri } = options;
const [over, setOverRaw] = useState<boolean>(false);
const setOver = useCallback(setOverRaw, []);
const process = useMemo(() => createProcess(options), [onFiles, onText, onUri]);
useEffect(() => {
const onDragOver = (event) => {
event.preventDefault();
setOver(true);
};
const onDragEnter = (event) => {
event.preventDefault();
setOver(true);
};
const onDragLeave = () => {
setOver(false);
};
const onDragExit = () => {
setOver(false);
};
const onDrop = (event) => {
event.preventDefault();
setOver(false);
process(event.dataTransfer, event);
};
const onPaste = (event) => {
process(event.clipboardData, event);
};
on(document, 'dragover', onDragOver);
on(document, 'dragenter', onDragEnter);
on(document, 'dragleave', onDragLeave);
on(document, 'dragexit', onDragExit);
on(document, 'drop', onDrop);
if (onText) {
on(document, 'paste', onPaste);
}
return () => {
off(document, 'dragover', onDragOver);
off(document, 'dragenter', onDragEnter);
off(document, 'dragleave', onDragLeave);
off(document, 'dragexit', onDragExit);
off(document, 'drop', onDrop);
off(document, 'paste', onPaste);
};
}, [process, ...args]);
return { over };
};
export default useDrop;