/** Lowercase and strip diacritics so "etirements" matches "Étirements". */ function fold(value: string): string { return value.normalize('NFD').replace(/\p{M}/gu, '').toLowerCase(); } /** Filter `items` to those whose `name` contains `query` as a literal * substring, case- and accent-insensitive. Order is preserved and no result * cap applies. Empty/whitespace query returns everything. */ export function filterByName( items: T[], query: string, ): T[] { const q = fold(query.trim()); if (q === '') return items; return items.filter((item) => fold(item.name).includes(q)); }