wwf
2025-05-20 938c3e5a587ce950a94964ea509b9e7f8834dfae
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
import { useEffect, useRef, useState } from 'react'
 
type UploaderHookProps = {
  onFileChange: (file: File | null) => void
  containerRef: React.RefObject<HTMLDivElement>
  enabled?: boolean
}
 
export const useUploader = ({ onFileChange, containerRef, enabled = true }: UploaderHookProps) => {
  const [dragging, setDragging] = useState(false)
  const fileUploader = useRef<HTMLInputElement>(null)
 
  const handleDragEnter = (e: DragEvent) => {
    e.preventDefault()
    e.stopPropagation()
    if (e.dataTransfer?.types.includes('Files'))
      setDragging(true)
  }
 
  const handleDragOver = (e: DragEvent) => {
    e.preventDefault()
    e.stopPropagation()
  }
 
  const handleDragLeave = (e: DragEvent) => {
    e.preventDefault()
    e.stopPropagation()
    if (e.relatedTarget === null || !containerRef.current?.contains(e.relatedTarget as Node))
      setDragging(false)
  }
 
  const handleDrop = (e: DragEvent) => {
    e.preventDefault()
    e.stopPropagation()
    setDragging(false)
    if (!e.dataTransfer)
      return
    const files = [...e.dataTransfer.files]
    if (files.length > 0)
      onFileChange(files[0])
  }
 
  const fileChangeHandle = enabled
    ? (e: React.ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files?.[0] || null
      onFileChange(file)
    }
    : null
 
  const removeFile = enabled
    ? () => {
      if (fileUploader.current)
        fileUploader.current.value = ''
 
      onFileChange(null)
    }
    : null
 
  useEffect(() => {
    if (!enabled)
      return
 
    const current = containerRef.current
    if (current) {
      current.addEventListener('dragenter', handleDragEnter)
      current.addEventListener('dragover', handleDragOver)
      current.addEventListener('dragleave', handleDragLeave)
      current.addEventListener('drop', handleDrop)
    }
    return () => {
      if (current) {
        current.removeEventListener('dragenter', handleDragEnter)
        current.removeEventListener('dragover', handleDragOver)
        current.removeEventListener('dragleave', handleDragLeave)
        current.removeEventListener('drop', handleDrop)
      }
    }
  }, [containerRef, enabled])
 
  return {
    dragging: enabled ? dragging : false,
    fileUploader,
    fileChangeHandle,
    removeFile,
  }
}