diff --git a/web/app/components/datasets/common/document-picker/__tests__/index.spec.tsx b/web/app/components/datasets/common/document-picker/__tests__/index.spec.tsx index a6c2078836..f934ef545e 100644 --- a/web/app/components/datasets/common/document-picker/__tests__/index.spec.tsx +++ b/web/app/components/datasets/common/document-picker/__tests__/index.spec.tsx @@ -148,6 +148,30 @@ describe('DocumentPicker', () => { expect(trigger).not.toHaveFocus() }) + it('should keep focus in the search input when deleting from an empty result', async () => { + const user = userEvent.setup() + mockUseDocumentList.mockImplementation(({ query }) => ({ + data: query.keyword === 'missing' + ? { data: [] } + : mockDocumentListData, + })) + + renderDocumentPicker() + + const trigger = screen.getByRole('combobox', { name: 'Document 1' }) + await user.click(trigger) + + const searchInput = screen.getByPlaceholderText('common.operation.search') + await user.type(searchInput, 'missing') + expect(await screen.findByText('common.noData')).toBeInTheDocument() + + await user.keyboard('{Backspace}{Backspace}{Backspace}{Backspace}{Backspace}{Backspace}{Backspace}') + + expect(trigger).toHaveAttribute('aria-expanded', 'true') + expect(searchInput).toHaveFocus() + expect(trigger).not.toHaveFocus() + }) + it('should keep focus in the search input while typing quickly', async () => { const user = userEvent.setup() renderDocumentPicker() diff --git a/web/app/components/datasets/common/document-picker/index.tsx b/web/app/components/datasets/common/document-picker/index.tsx index 5a15cc4a3b..9f06727ed9 100644 --- a/web/app/components/datasets/common/document-picker/index.tsx +++ b/web/app/components/datasets/common/document-picker/index.tsx @@ -13,7 +13,8 @@ import { ComboboxValue, } from '@langgenius/dify-ui/combobox' import { RiArrowDownSLine } from '@remixicon/react' -import { useDeferredValue, useState } from 'react' +import { useDebounce } from 'ahooks' +import { useState } from 'react' import { useTranslation } from 'react-i18next' import { GeneralChunk, ParentChildChunk } from '@/app/components/base/icons/src/vender/knowledge' import Loading from '@/app/components/base/loading' @@ -106,12 +107,12 @@ export function DocumentPicker({ }: Props) { const { t } = useTranslation() const [searchValue, setSearchValue] = useState('') - const deferredSearchValue = useDeferredValue(searchValue) + const debouncedSearchValue = useDebounce(searchValue, { wait: 500 }) const { data } = useDocumentList({ datasetId, query: { - keyword: deferredSearchValue, + keyword: debouncedSearchValue, page: 1, limit: 20, }, @@ -175,19 +176,16 @@ export function DocumentPicker({ className="block h-4.5 grow px-1 py-0 text-[13px] text-text-primary" /> + {data ? ( - documentsList.length > 0 - ? ( - - ) - : ( - - {t('noData', { ns: 'common' })} - - ) + + + {t('noData', { ns: 'common' })} + + ) : (