uploader.tsx 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import type { ChangeEvent, FC } from 'react'
  2. import { useState } from 'react'
  3. import { useLocalFileUploader } from './hooks'
  4. import type { ImageFile } from '@/types/app'
  5. import { ALLOW_FILE_EXTENSIONS } from '@/types/app'
  6. type UploaderProps = {
  7. children: (hovering: boolean) => JSX.Element
  8. onUpload: (imageFile: ImageFile) => void
  9. closePopover?: () => void
  10. limit?: number
  11. disabled?: boolean
  12. }
  13. const Uploader: FC<UploaderProps> = ({
  14. children,
  15. onUpload,
  16. closePopover,
  17. limit,
  18. disabled,
  19. }) => {
  20. const [hovering, setHovering] = useState(false)
  21. const { handleLocalFileUpload } = useLocalFileUploader({
  22. limit,
  23. onUpload,
  24. disabled,
  25. })
  26. const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
  27. const file = e.target.files?.[0]
  28. if (!file)
  29. return
  30. handleLocalFileUpload(file)
  31. closePopover?.()
  32. }
  33. return (
  34. <div
  35. className='relative'
  36. onMouseEnter={() => setHovering(true)}
  37. onMouseLeave={() => setHovering(false)}
  38. >
  39. {children(hovering)}
  40. <input
  41. className='absolute block inset-0 opacity-0 text-[0] w-full disabled:cursor-not-allowed cursor-pointer'
  42. onClick={e => ((e.target as HTMLInputElement).value = '')}
  43. type='file'
  44. accept={ALLOW_FILE_EXTENSIONS.map(ext => `.${ext}`).join(',')}
  45. onChange={handleChange}
  46. disabled={disabled}
  47. />
  48. </div>
  49. )
  50. }
  51. export default Uploader