You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
2.9 KiB
TypeScript
120 lines
2.9 KiB
TypeScript
5 years ago
|
import React, { Component } from 'react';
|
||
|
import { Flex } from '../Flex';
|
||
|
import { SessionIcon, SessionIconSize, SessionIconType } from '../icon';
|
||
|
|
||
|
interface Props {
|
||
|
handleDrop: (files: FileList) => void;
|
||
|
}
|
||
|
|
||
|
interface State {
|
||
|
dragging: boolean;
|
||
|
}
|
||
|
|
||
|
export class SessionFileDropzone extends Component<Props, State> {
|
||
|
private readonly dropRef: React.RefObject<any>;
|
||
|
private dragCounter: number;
|
||
|
|
||
|
constructor(props: any) {
|
||
|
super(props);
|
||
|
this.state = {
|
||
|
dragging: false,
|
||
|
};
|
||
|
|
||
|
this.dragCounter = 0;
|
||
|
this.dropRef = React.createRef();
|
||
|
}
|
||
|
|
||
|
public handleDrag = (e: any) => {
|
||
|
e.preventDefault();
|
||
|
e.stopPropagation();
|
||
|
};
|
||
|
|
||
|
public handleDragIn = (e: any) => {
|
||
|
e.preventDefault();
|
||
|
e.stopPropagation();
|
||
|
this.dragCounter++;
|
||
|
if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
|
||
|
this.setState({ dragging: true });
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public handleDragOut = (e: any) => {
|
||
|
e.preventDefault();
|
||
|
e.stopPropagation();
|
||
|
this.dragCounter--;
|
||
|
if (this.dragCounter === 0) {
|
||
|
this.setState({ dragging: false });
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public handleDrop = (e: any) => {
|
||
|
e.preventDefault();
|
||
|
e.stopPropagation();
|
||
|
this.setState({ dragging: false });
|
||
|
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
||
|
this.props.handleDrop(e.dataTransfer.files);
|
||
|
e.dataTransfer.clearData();
|
||
|
this.dragCounter = 0;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public componentDidMount() {
|
||
|
const div = this.dropRef.current;
|
||
|
div.addEventListener('dragenter', this.handleDragIn);
|
||
|
div.addEventListener('dragleave', this.handleDragOut);
|
||
|
div.addEventListener('dragover', this.handleDrag);
|
||
|
div.addEventListener('drop', this.handleDrop);
|
||
|
}
|
||
|
|
||
|
public componentWillUnmount() {
|
||
|
const div = this.dropRef.current;
|
||
|
div.removeEventListener('dragenter', this.handleDragIn);
|
||
|
div.removeEventListener('dragleave', this.handleDragOut);
|
||
|
div.removeEventListener('dragover', this.handleDrag);
|
||
|
div.removeEventListener('drop', this.handleDrop);
|
||
|
}
|
||
|
|
||
|
public render() {
|
||
|
return (
|
||
|
<div
|
||
|
style={{
|
||
|
display: 'inline-block',
|
||
|
position: 'absolute',
|
||
|
width: '100%',
|
||
|
height: '100%',
|
||
|
}}
|
||
|
ref={this.dropRef}
|
||
|
>
|
||
|
<div
|
||
|
style={{
|
||
|
border: 'dashed grey 4px',
|
||
|
backgroundColor: 'rgba(255,255,255,0.5)',
|
||
|
position: 'absolute',
|
||
|
top: 0,
|
||
|
bottom: 0,
|
||
|
left: 0,
|
||
|
right: 0,
|
||
|
zIndex: 100,
|
||
|
opacity: this.state.dragging ? 1.0 : 0,
|
||
|
transition: '0.25s',
|
||
|
}}
|
||
|
>
|
||
|
<Flex
|
||
|
container={true}
|
||
|
justifyContent="space-around"
|
||
|
height="100%"
|
||
|
alignItems="center"
|
||
|
>
|
||
|
<SessionIcon
|
||
|
iconSize={SessionIconSize.Max}
|
||
|
iconType={SessionIconType.CirclePlus}
|
||
|
/>
|
||
|
</Flex>
|
||
|
</div>
|
||
|
|
||
|
{this.props.children}
|
||
|
</div>
|
||
|
);
|
||
|
}
|
||
|
}
|