forked from plotly/dash
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdropdownSearch.ts
More file actions
92 lines (78 loc) · 2.27 KB
/
dropdownSearch.ts
File metadata and controls
92 lines (78 loc) · 2.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import React from 'react';
import {
Search,
AllSubstringsIndexStrategy,
UnorderedSearchIndex,
} from 'js-search';
import {sanitizeOptions} from './optionTypes';
import {DetailedOption, DropdownProps, OptionValue} from '../types';
// Custom tokenizer, see https://github.com/bvaughn/js-search/issues/43
// Split on spaces
const REGEX = /\s+/;
const TOKENIZER = {
tokenize(text: string) {
return text.split(REGEX).filter(
// Filter empty tokens
text => text
);
},
};
export interface SanitizedOptions {
options: DetailedOption[];
indexes: string[];
valueSet: Set<OptionValue>;
}
// Single-pass sanitization via sanitizeOptions, plus detection of
// search/element labels for indexing.
export function sanitizeDropdownOptions(
options: DropdownProps['options']
): SanitizedOptions {
const {options: sanitized, valueSet} = sanitizeOptions(options);
const indexes = ['value'];
let hasElement = false,
hasSearch = false;
for (const option of sanitized) {
if (option.search) {
hasSearch = true;
}
if (React.isValidElement(option.label)) {
hasElement = true;
}
if (hasSearch && hasElement) {
break;
}
}
if (!hasElement) {
indexes.push('label');
}
if (hasSearch) {
indexes.push('search');
}
return {options: sanitized, indexes, valueSet};
}
export function filterOptions(
options: SanitizedOptions,
searchValue?: string,
search_order?: 'index' | 'original'
): DetailedOption[] {
if (!searchValue) {
return options.options;
}
const search = new Search('value');
search.searchIndex = new UnorderedSearchIndex();
search.indexStrategy = new AllSubstringsIndexStrategy();
search.tokenizer = TOKENIZER;
options.indexes.forEach(index => {
search.addIndex(index);
});
if (options.options.length > 0) {
search.addDocuments(options.options);
}
const searchResults =
(search.search(searchValue) as DetailedOption[]) || [];
if (search_order === 'original') {
const resultSet = new Set(searchResults);
return options.options.filter(option => resultSet.has(option));
}
return searchResults;
}