From d5f1f4eb5cffde05f4e88b546fbece9cd51e353f Mon Sep 17 00:00:00 2001 From: Leon Sorokin Date: Thu, 6 Feb 2025 03:33:08 -0600 Subject: [PATCH] ComboBox: Fall back to substring matching for symbols/operators (#100148) --- .../src/components/Combobox/filter.test.ts | 13 +++++++++++++ .../grafana-ui/src/components/Combobox/filter.ts | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/packages/grafana-ui/src/components/Combobox/filter.test.ts b/packages/grafana-ui/src/components/Combobox/filter.test.ts index f7a5eb534fd..8b3c13ed354 100644 --- a/packages/grafana-ui/src/components/Combobox/filter.test.ts +++ b/packages/grafana-ui/src/components/Combobox/filter.test.ts @@ -58,4 +58,17 @@ describe('combobox filter', () => { expect(matches.map((m) => m.value)).toEqual(['台南市', '南投縣']); }); }); + + describe('operators', () => { + it('should do substring match when needle is only symbols', () => { + const needle = '='; + + const stringOptions = ['=', '<=', '>', '!~']; + const options = stringOptions.map((value) => ({ value })); + + const matches = fuzzyFind(options, stringOptions, needle); + + expect(matches.map((m) => m.value)).toEqual(['=', '<=']); + }); + }); }); diff --git a/packages/grafana-ui/src/components/Combobox/filter.ts b/packages/grafana-ui/src/components/Combobox/filter.ts index a03cbec475c..7653286f42a 100644 --- a/packages/grafana-ui/src/components/Combobox/filter.ts +++ b/packages/grafana-ui/src/components/Combobox/filter.ts @@ -4,6 +4,9 @@ import { ALL_OPTION_VALUE, ComboboxOption } from './types'; // https://catonmat.net/my-favorite-regex :) const REGEXP_NON_ASCII = /[^ -~]/m; +// https://www.asciitable.com/ +// matches only these: `~!@#$%^&*()_+-=[]\{}|;':",./<>? +const REGEXP_ONLY_SYMBOLS = /^[\x21-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]+$/m; // limit max terms in needle that qualify for re-ordering const outOfOrderLimit = 5; // beyond 25 chars fall back to substring search @@ -51,6 +54,8 @@ export function fuzzyFind( else if ( // contains non-ascii REGEXP_NON_ASCII.test(needle) || + // is only ascii symbols (operators) + REGEXP_ONLY_SYMBOLS.test(needle) || // too long (often copy-paste from somewhere) needle.length > maxNeedleLength || uf.split(needle).length > maxFuzzyTerms