-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathPasteDropBox.tsx
More file actions
70 lines (57 loc) · 1.79 KB
/
PasteDropBox.tsx
File metadata and controls
70 lines (57 loc) · 1.79 KB
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
import { ClipboardEvent, Component, DragEvent, HTMLAttributes, PropsWithChildren } from 'react';
import { groupBy } from 'web-utility';
export interface PasteDropData {
kind: string;
type: string;
data: string | File;
}
export interface PasteDropEvent extends Record<
`${'kind' | 'type'}Map`,
Record<string, PasteDropData[]>
> {
type: string;
}
export interface PasteDropBoxProps extends Omit<
PropsWithChildren<HTMLAttributes<HTMLDivElement>>,
'onChange' | 'onDragOver' | 'onDrop' | 'onPaste'
> {
onChange?: (event: PasteDropEvent) => void;
}
export class PasteDropBox extends Component<PasteDropBoxProps> {
static async *transferData(items: DataTransferItemList) {
for (const item of items) {
const { kind, type } = item;
if (kind === 'file') {
const data = item.getAsFile();
if (data) yield { kind, type, data };
} else if (kind === 'string') {
const data = await new Promise<string>(resolve => item.getAsString(resolve));
yield { kind, type, data };
}
}
}
handlePasteDrop = async (event: ClipboardEvent | DragEvent) => {
event.preventDefault();
const items =
event.type === 'paste'
? (event as ClipboardEvent).clipboardData.items
: (event as DragEvent).dataTransfer.items;
const list = await Array.fromAsync(PasteDropBox.transferData(items));
const kindMap = groupBy(list, 'kind'),
typeMap = groupBy(list, 'type');
this.props.onChange?.({ type: event.type, kindMap, typeMap });
};
render() {
const { children, onChange, ...props } = this.props;
return (
<div
{...props}
onDragOver={event => event.preventDefault()}
onDrop={this.handlePasteDrop}
onPaste={this.handlePasteDrop}
>
{children}
</div>
);
}
}