preview-document-picker.tsx 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useCallback } from 'react'
  4. import { useBoolean } from 'ahooks'
  5. import { RiArrowDownSLine } from '@remixicon/react'
  6. import { useTranslation } from 'react-i18next'
  7. import FileIcon from '../document-file-icon'
  8. import DocumentList from './document-list'
  9. import {
  10. PortalToFollowElem,
  11. PortalToFollowElemContent,
  12. PortalToFollowElemTrigger,
  13. } from '@/app/components/base/portal-to-follow-elem'
  14. import cn from '@/utils/classnames'
  15. import Loading from '@/app/components/base/loading'
  16. import type { DocumentItem } from '@/models/datasets'
  17. type Props = {
  18. className?: string
  19. value: DocumentItem
  20. files: DocumentItem[]
  21. onChange: (value: DocumentItem) => void
  22. }
  23. const PreviewDocumentPicker: FC<Props> = ({
  24. className,
  25. value,
  26. files,
  27. onChange,
  28. }) => {
  29. const { t } = useTranslation()
  30. const { name, extension } = value
  31. const [open, {
  32. set: setOpen,
  33. toggle: togglePopup,
  34. }] = useBoolean(false)
  35. const ArrowIcon = RiArrowDownSLine
  36. const handleChange = useCallback((item: DocumentItem) => {
  37. onChange(item)
  38. setOpen(false)
  39. }, [onChange, setOpen])
  40. return (
  41. <PortalToFollowElem
  42. open={open}
  43. onOpenChange={setOpen}
  44. placement='bottom-start'
  45. offset={4}
  46. >
  47. <PortalToFollowElemTrigger onClick={togglePopup}>
  48. <div className={cn('flex items-center h-6 px-1 rounded-md hover:bg-state-base-hover select-none', open && 'bg-state-base-hover', className)}>
  49. <FileIcon name={name} extension={extension} size='md' />
  50. <div className='flex flex-col items-start ml-1'>
  51. <div className='flex items-center space-x-0.5'>
  52. <span className={cn('system-md-semibold max-w-[200px] truncate text-text-primary')}> {name || '--'}</span>
  53. <ArrowIcon className={'h-[18px] w-[18px] text-text-primary'} />
  54. </div>
  55. </div>
  56. </div>
  57. </PortalToFollowElemTrigger>
  58. <PortalToFollowElemContent className='z-[11]'>
  59. <div className='w-[392px] p-1 rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-[5px]'>
  60. {files?.length > 1 && <div className='pl-2 flex items-center h-8 system-xs-medium-uppercase text-text-tertiary'>{t('dataset.preprocessDocument', { num: files.length })}</div>}
  61. {files?.length > 0
  62. ? (
  63. <DocumentList
  64. list={files}
  65. onChange={handleChange}
  66. />
  67. )
  68. : (<div className='mt-2 flex items-center justify-center w-[360px] h-[100px]'>
  69. <Loading />
  70. </div>)}
  71. </div>
  72. </PortalToFollowElemContent>
  73. </PortalToFollowElem>
  74. )
  75. }
  76. export default React.memo(PreviewDocumentPicker)