diff --git a/src-ui/src/app/utils/text-search.spec.ts b/src-ui/src/app/utils/text-search.spec.ts index daa432851..a1225c1d0 100644 --- a/src-ui/src/app/utils/text-search.spec.ts +++ b/src-ui/src/app/utils/text-search.spec.ts @@ -14,4 +14,20 @@ describe('text search utilities', () => { expect(matchesSearchText('Tax\u00e9s 2026', 'taxe 26')).toBeTruthy() expect(matchesSearchText('taxes 2026', 'tax receipt')).toBeFalsy() }) + + it('matches a large set of tag names without blocking input', () => { + const tagNames = Array.from( + { length: 1280 }, + (_, index) => + `Customer Party ${index} Jos\u00e9 M\u00fcller \u00c5ngstr\u00f6m` + ) + + const start = performance.now() + const matches = tagNames.filter((name) => matchesSearchText(name, 'party')) + const duration = performance.now() - start + + expect(matches).toHaveLength(tagNames.length) + // The previous implementation took roughly 500 ms for this workload. + expect(duration).toBeLessThan(250) + }) }) diff --git a/src-ui/src/app/utils/text-search.ts b/src-ui/src/app/utils/text-search.ts index 883ace368..f7f552408 100644 --- a/src-ui/src/app/utils/text-search.ts +++ b/src-ui/src/app/utils/text-search.ts @@ -1,10 +1,17 @@ -import { normalizeSync } from 'normalize-diacritics' +import { diacritics } from 'normalize-diacritics/diacritics' export type SearchTextValue = string | number | boolean | bigint | null | undefined export function normalizeSearchText(value: SearchTextValue): string { - return normalizeSync(String(value ?? '')).toLocaleLowerCase() + const normalized = diacritics.reduce( + (text, replacement) => { + return text.replace(replacement.diacritics, replacement.letter) + }, + String(value ?? '') + ) + + return normalized.toLocaleLowerCase() } export function matchesSearchText(