UNPKG

@grafana/ui

Version:
1 lines 2.75 kB
{"version":3,"file":"filter.mjs","sources":["../../../../src/components/Combobox/filter.ts"],"sourcesContent":["import uFuzzy from '@leeoniya/ufuzzy';\n\nimport { ALL_OPTION_VALUE, ComboboxOption } from './types';\n\n// https://catonmat.net/my-favorite-regex :)\nconst REGEXP_NON_ASCII = /[^ -~]/m;\n// https://www.asciitable.com/\n// matches only these: `~!@#$%^&*()_+-=[]\\{}|;':\",./<>?\nconst REGEXP_ONLY_SYMBOLS = /^[\\x21-\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7E]+$/m;\n// limit max terms in needle that qualify for re-ordering\nconst outOfOrderLimit = 5;\n// beyond 25 chars fall back to substring search\nconst maxNeedleLength = 25;\n// beyond 5 terms fall back to substring match\nconst maxFuzzyTerms = 5;\n// when number of matches <= 1e4, do ranking + sorting by quality\nconst rankThreshold = 1e4;\n\n// typo tolerance mode\nconst uf = new uFuzzy({ intraMode: 1 });\n\nexport function itemToString<T extends string | number>(item?: ComboboxOption<T> | null) {\n if (item == null) {\n return '';\n }\n return item.label ?? item.value.toString();\n}\n\n//TODO: Remove when MutliCombobox async has been merged\nexport function itemFilter<T extends string | number>(inputValue: string) {\n const lowerCasedInputValue = inputValue.toLowerCase();\n\n return (item: ComboboxOption<T>) => {\n return (\n !inputValue ||\n item.label?.toLowerCase().includes(lowerCasedInputValue) ||\n item.value?.toString().toLowerCase().includes(lowerCasedInputValue) ||\n item.value.toString() === ALL_OPTION_VALUE\n );\n };\n}\n\nexport function fuzzyFind<T extends string | number>(\n options: Array<ComboboxOption<T>>,\n haystack: string[],\n needle: string\n) {\n let matches: Array<ComboboxOption<T>> = [];\n\n if (needle === '') {\n matches = options;\n }\n // fallback to substring matches to avoid badness\n else if (\n // contains non-ascii\n REGEXP_NON_ASCII.test(needle) ||\n // is only ascii symbols (operators)\n REGEXP_ONLY_SYMBOLS.test(needle) ||\n // too long (often copy-paste from somewhere)\n needle.length > maxNeedleLength ||\n uf.split(needle).length > maxFuzzyTerms\n ) {\n for (let i = 0; i < haystack.length; i++) {\n let item = haystack[i];\n\n if (item.includes(needle)) {\n matches.push(options[i]);\n }\n }\n }\n // fuzzy search\n else {\n const [idxs, info, order] = uf.search(haystack, needle, outOfOrderLimit, rankThreshold);\n\n if (idxs?.length) {\n if (info && order) {\n matches = order.map((idx) => options[info.idx[idx]]);\n } else {\n matches = idxs.map((idx) => options[idx]);\n }\n }\n }\n\n return matches;\n}\n"],"names":[],"mappings":";;AAmBW,IAAI,MAAA,CAAO,EAAE,SAAA,EAAW,GAAG"}