|
| 1 | +import { styled } from "@linaria/react"; |
| 2 | +import { useEffect, useState } from "react"; |
| 3 | + |
| 4 | +export interface GlobalDropzoneProps { |
| 5 | + onFileDrop: (file: File) => void; |
| 6 | +} |
| 7 | + |
| 8 | +export const GlobalDropzone = ({ onFileDrop }: GlobalDropzoneProps) => { |
| 9 | + const [state, setState] = useState(""); |
| 10 | + useEffect(() => { |
| 11 | + const dragend = () => { |
| 12 | + setState(""); |
| 13 | + }; |
| 14 | + |
| 15 | + const dragover = (e: DragEvent) => { |
| 16 | + setState("over"); |
| 17 | + console.log(e.dataTransfer, e.dataTransfer?.files[0]); |
| 18 | + e.preventDefault(); |
| 19 | + e.stopPropagation(); |
| 20 | + }; |
| 21 | + |
| 22 | + const drop = async (e: DragEvent) => { |
| 23 | + setState(""); |
| 24 | + e.preventDefault(); |
| 25 | + e.stopPropagation(); |
| 26 | + |
| 27 | + if (e.dataTransfer && e.dataTransfer.files.length > 0) { |
| 28 | + const file = e.dataTransfer.files[0]; |
| 29 | + onFileDrop(file); |
| 30 | + } |
| 31 | + }; |
| 32 | + |
| 33 | + const ab = new AbortController(); |
| 34 | + |
| 35 | + window.addEventListener('dragleave', dragend, { signal: ab.signal }); |
| 36 | + window.addEventListener('dragover', dragover, { signal: ab.signal }); |
| 37 | + window.addEventListener('drop', drop, { signal: ab.signal }); |
| 38 | + |
| 39 | + return () => { |
| 40 | + ab.abort(); |
| 41 | + }; |
| 42 | + }, []); |
| 43 | + |
| 44 | + return ( |
| 45 | + <DropZoneEffect |
| 46 | + data-drop-state={state} |
| 47 | + > |
| 48 | + Drop file here |
| 49 | + </DropZoneEffect> |
| 50 | + ) |
| 51 | +} |
| 52 | + |
| 53 | +const DropZoneEffect = styled.div` |
| 54 | + position: fixed; |
| 55 | + inset: 0; |
| 56 | + width: 100vw; |
| 57 | + height: 100vh; |
| 58 | + pointer-events: none; |
| 59 | + background: rgba(240, 240, 240, 1); |
| 60 | + transition-property: backdrop-filter, opacity; |
| 61 | + transition-duration: 0.1s; |
| 62 | + transition-timing-function: ease-in-out; |
| 63 | + opacity: 0; |
| 64 | +
|
| 65 | + font-size: 2rem; |
| 66 | +
|
| 67 | + display: flex; |
| 68 | + justify-content: center; |
| 69 | + align-items: center; |
| 70 | + &[data-drop-state="over"] { |
| 71 | + opacity: 0.9; |
| 72 | + backdrop-filter: blur(2px); |
| 73 | + transition-duration: 0.3s; |
| 74 | + } |
| 75 | +`; |
0 commit comments