You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

file-image-item.tsx 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import { useState } from 'react'
  2. import {
  3. RiCloseLine,
  4. RiDownloadLine,
  5. } from '@remixicon/react'
  6. import FileImageRender from '../file-image-render'
  7. import type { FileEntity } from '../types'
  8. import {
  9. downloadFile,
  10. fileIsUploaded,
  11. } from '../utils'
  12. import Button from '@/app/components/base/button'
  13. import ProgressCircle from '@/app/components/base/progress-bar/progress-circle'
  14. import { ReplayLine } from '@/app/components/base/icons/src/vender/other'
  15. import ImagePreview from '@/app/components/base/image-uploader/image-preview'
  16. type FileImageItemProps = {
  17. file: FileEntity
  18. showDeleteAction?: boolean
  19. showDownloadAction?: boolean
  20. canPreview?: boolean
  21. onRemove?: (fileId: string) => void
  22. onReUpload?: (fileId: string) => void
  23. }
  24. const FileImageItem = ({
  25. file,
  26. showDeleteAction,
  27. showDownloadAction,
  28. canPreview,
  29. onRemove,
  30. onReUpload,
  31. }: FileImageItemProps) => {
  32. const { id, progress, base64Url, url, name } = file
  33. const [imagePreviewUrl, setImagePreviewUrl] = useState('')
  34. const download_url = url ? `${url}&as_attachment=true` : base64Url
  35. return (
  36. <>
  37. <div
  38. className='group/file-image relative cursor-pointer'
  39. onClick={() => canPreview && setImagePreviewUrl(base64Url || url || '')}
  40. >
  41. {
  42. showDeleteAction && (
  43. <Button
  44. className='absolute -right-1.5 -top-1.5 z-[11] hidden h-5 w-5 rounded-full p-0 group-hover/file-image:flex'
  45. onClick={() => onRemove?.(id)}
  46. >
  47. <RiCloseLine className='h-4 w-4 text-components-button-secondary-text' />
  48. </Button>
  49. )
  50. }
  51. <FileImageRender
  52. className='h-[68px] w-[68px] shadow-md'
  53. imageUrl={base64Url || url || ''}
  54. showDownloadAction={showDownloadAction}
  55. />
  56. {
  57. progress >= 0 && !fileIsUploaded(file) && (
  58. <div className='absolute inset-0 z-10 flex items-center justify-center border-[2px] border-effects-image-frame bg-background-overlay-alt'>
  59. <ProgressCircle
  60. percentage={progress}
  61. size={12}
  62. circleStrokeColor='stroke-components-progress-white-border'
  63. circleFillColor='fill-transparent'
  64. sectorFillColor='fill-components-progress-white-progress'
  65. />
  66. </div>
  67. )
  68. }
  69. {
  70. progress === -1 && (
  71. <div className='absolute inset-0 z-10 flex items-center justify-center border-[2px] border-state-destructive-border bg-background-overlay-destructive'>
  72. <ReplayLine
  73. className='h-5 w-5'
  74. onClick={() => onReUpload?.(id)}
  75. />
  76. </div>
  77. )
  78. }
  79. {
  80. showDownloadAction && (
  81. <div className='absolute inset-0.5 z-10 hidden bg-background-overlay-alt bg-opacity-[0.3] group-hover/file-image:block'>
  82. <div
  83. className='absolute bottom-0.5 right-0.5 flex h-6 w-6 items-center justify-center rounded-lg bg-components-actionbar-bg shadow-md'
  84. onClick={(e) => {
  85. e.stopPropagation()
  86. downloadFile(download_url || '', name)
  87. }}
  88. >
  89. <RiDownloadLine className='h-4 w-4 text-text-tertiary' />
  90. </div>
  91. </div>
  92. )
  93. }
  94. </div>
  95. {
  96. imagePreviewUrl && canPreview && (
  97. <ImagePreview
  98. title={name}
  99. url={imagePreviewUrl}
  100. onCancel={() => setImagePreviewUrl('')}
  101. />
  102. )
  103. }
  104. </>
  105. )
  106. }
  107. export default FileImageItem