image-preview.tsx 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import type { FC } from 'react'
  2. import { useRef } from 'react'
  3. import { t } from 'i18next'
  4. import { createPortal } from 'react-dom'
  5. import { RiCloseLine, RiExternalLinkLine } from '@remixicon/react'
  6. import Tooltip from '@/app/components/base/tooltip'
  7. import { randomString } from '@/utils'
  8. type ImagePreviewProps = {
  9. url: string
  10. title: string
  11. onCancel: () => void
  12. }
  13. const ImagePreview: FC<ImagePreviewProps> = ({
  14. url,
  15. title,
  16. onCancel,
  17. }) => {
  18. const selector = useRef(`copy-tooltip-${randomString(4)}`)
  19. const openInNewTab = () => {
  20. // Open in a new window, considering the case when the page is inside an iframe
  21. if (url.startsWith('http')) {
  22. window.open(url, '_blank')
  23. }
  24. else if (url.startsWith('data:image')) {
  25. // Base64 image
  26. const win = window.open()
  27. win?.document.write(`<img src="${url}" alt="${title}" />`)
  28. }
  29. else {
  30. console.error('Unable to open image', url)
  31. }
  32. }
  33. return createPortal(
  34. <div className='fixed inset-0 p-8 flex items-center justify-center bg-black/80 z-[1000]' onClick={e => e.stopPropagation()}>
  35. {/* eslint-disable-next-line @next/next/no-img-element */}
  36. <img
  37. alt={title}
  38. src={url}
  39. className='max-w-full max-h-full'
  40. />
  41. <div
  42. className='absolute top-6 right-6 flex items-center justify-center w-8 h-8 bg-white/8 rounded-lg backdrop-blur-[2px] cursor-pointer'
  43. onClick={onCancel}
  44. >
  45. <RiCloseLine className='w-4 h-4 text-white' />
  46. </div>
  47. <Tooltip
  48. selector={selector.current}
  49. content={(t('common.operation.openInNewTab') ?? 'Open in new tab')}
  50. className='z-10'
  51. >
  52. <div
  53. className='absolute top-6 right-16 flex items-center justify-center w-8 h-8 rounded-lg cursor-pointer'
  54. onClick={openInNewTab}
  55. >
  56. <RiExternalLinkLine className='w-4 h-4 text-white' />
  57. </div>
  58. </Tooltip>
  59. </div>,
  60. document.body,
  61. )
  62. }
  63. export default ImagePreview