'use client' import type { ComboboxChangeEventDetails } from '@langgenius/dify-ui/combobox' import type { ParentMode, SimpleDocumentDetail } from '@/models/datasets' import { cn } from '@langgenius/dify-ui/cn' import { Combobox, ComboboxEmpty, ComboboxInput, ComboboxInputGroup, ComboboxPopup, ComboboxPortal, ComboboxPositioner, ComboboxStatus, ComboboxTrigger, ComboboxValue, } from '@langgenius/dify-ui/combobox' import { useDebounce } from 'ahooks' import { useState } from 'react' import { useTranslation } from 'react-i18next' import Loading from '@/app/components/base/loading' import { ChunkingMode } from '@/models/datasets' import { useDocumentList } from '@/service/knowledge/use-document' import FileIcon from '../document-file-icon' import DocumentList from './document-list' type Props = Readonly<{ datasetId: string value?: SimpleDocumentDetail | null parentMode?: ParentMode onChange: (value: SimpleDocumentDetail) => void }> function getDocumentLabel(document: SimpleDocumentDetail) { return document.name } function getDocumentValue(document: SimpleDocumentDetail) { return document.id } function isSameDocument(item: SimpleDocumentDetail, value: SimpleDocumentDetail) { return item.id === value.id } function getDocumentExtension(document?: SimpleDocumentDetail | null) { if (!document) return '' const detailExtension = document.data_source_detail_dict?.upload_file?.extension if (detailExtension) return detailExtension const dataSourceInfo = document.data_source_info if (dataSourceInfo && 'upload_file' in dataSourceInfo) return dataSourceInfo.upload_file.extension return '' } function DocumentPickerTriggerValue({ document, parentMode, }: { document?: SimpleDocumentDetail | null parentMode?: ParentMode }) { const { t } = useTranslation() const isGeneralMode = document?.doc_form === ChunkingMode.text const isParentChild = document?.doc_form === ChunkingMode.parentChild const isQAMode = document?.doc_form === ChunkingMode.qa const parentModeLabel = (() => { if (!parentMode) return '--' return parentMode === 'paragraph' ? t(($) => $['parentMode.paragraph'], { ns: 'dataset' }) : t(($) => $['parentMode.fullDoc'], { ns: 'dataset' }) })() return ( {document?.name || '--'} {isGeneralMode && t(($) => $['chunkingMode.general'], { ns: 'dataset' })} {isQAMode && t(($) => $['chunkingMode.qa'], { ns: 'dataset' })} {isParentChild && `${t(($) => $['chunkingMode.parentChild'], { ns: 'dataset' })} ยท ${parentModeLabel}`} ) } export function DocumentPicker({ datasetId, value, parentMode, onChange }: Props) { const { t } = useTranslation() const [searchValue, setSearchValue] = useState('') const debouncedSearchValue = useDebounce(searchValue, { wait: 500 }) const { data } = useDocumentList({ datasetId, query: { keyword: debouncedSearchValue, page: 1, limit: 20, }, }) const documentsList = data?.data ?? [] const handleInputValueChange = (inputValue: string, details: ComboboxChangeEventDetails) => { if (details.reason !== 'item-press') setSearchValue(inputValue) } const handleOpenChange = (nextOpen: boolean) => { if (!nextOpen) setSearchValue('') } const handleDocumentChange = (document: SimpleDocumentDetail | null) => { if (!document) return onChange(document) setSearchValue('') } return ( items={documentsList} value={value ?? null} inputValue={searchValue} onOpenChange={handleOpenChange} onInputValueChange={handleInputValueChange} onValueChange={handleDocumentChange} isItemEqualToValue={isSameDocument} itemToStringLabel={getDocumentLabel} itemToStringValue={getDocumentValue} filter={null} > $['operation.search'], { ns: 'common' })} icon={false} className={cn( 'ml-1 flex size-auto rounded-lg border-0 bg-transparent px-2 py-1 hover:bg-state-base-hover focus-visible:bg-state-base-hover data-popup-open:bg-state-base-hover', )} > > {(document) => } $['operation.search'], { ns: 'common' })} className="w-90 rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-2 shadow-lg backdrop-blur-[5px]" > $['operation.search'], { ns: 'common' })} placeholder={t(($) => $['operation.search'], { ns: 'common' })} className="block h-4.5 grow px-1 py-0 text-[13px] text-text-primary" /> {data && ( {t(($) => $.noData, { ns: 'common' })} )} {!data && ( <> {t(($) => $.loading, { ns: 'common' })} > )} ) }