Skip to content

Commit 69ffdf6

Browse files
authored
feat: Support wildcard filtering in AutoComplete component (#594)
* feat: add wildcard search support to autocomplete component Signed-off-by: jiwlee <[email protected]> * feat: add wildcard filter option to AutoComplete in Storybook Signed-off-by: jiwlee <[email protected]> * chore: add [email protected] Signed-off-by: jiwlee <[email protected]> * refactor: replace manual regex with minimatch for pattern matching Signed-off-by: jiwlee <[email protected]> * feat: apply minimatch when props.wildcard is true Signed-off-by: jiwlee <[email protected]> * feat: update autocomplete to use glob options instead of wildcard Signed-off-by: jiwlee <[email protected]> * chore: update autocomplete story to use a predefined list of items Signed-off-by: jiwlee <[email protected]> --------- Signed-off-by: jiwlee <[email protected]>
1 parent 5cf3610 commit 69ffdf6

File tree

4 files changed

+55
-20
lines changed

4 files changed

+55
-20
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"core-js": "^3.32.1",
2626
"foundation-sites": "^6.4.3",
2727
"history": "^4.10.1",
28+
"minimatch": "5.1.6",
2829
"prop-types": "^15.8.1",
2930
"react-autocomplete": "1.8.1",
3031
"react-form": "^2.16.0",

v2/components/autocomplete/autocomplete.stories.tsx

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,41 @@ export default {
99
items: {control: {type: 'object'}},
1010
inputStyle: {control: {disable: true}},
1111
placeholder: {control: {type: 'text'}},
12+
glob: {control: {type: 'boolean'}},
1213
},
1314
};
1415

15-
export const Primary = (args: any) => (
16-
<div style={{width: '50%', paddingBottom: '6em'}}>
17-
<Autocomplete {...args} items={['hello', 'world']} />
18-
</div>
19-
);
16+
export const Primary = (args: any) => {
17+
const [input, setInput] = React.useState('');
18+
19+
const items = [
20+
'User',
21+
'AppServer',
22+
'AuthService',
23+
'Backend',
24+
'Cache',
25+
'Config',
26+
'Database',
27+
'Frontend',
28+
'Logger',
29+
'utils.js',
30+
'data-01.csv',
31+
'data-02.csv',
32+
'data-final.csv',
33+
'src/index.js',
34+
'src/components/Button.js',
35+
'src/components/Input.ts',
36+
'test/app.test.js',
37+
'.env',
38+
'README.md',
39+
];
40+
41+
return (
42+
<div style={{width: '50%', paddingBottom: '6em'}}>
43+
<Autocomplete {...args} items={items} value={input} onChange={(e) => setInput(e.target.value)} />
44+
</div>
45+
);
46+
};
2047

2148
Primary.args = {
2249
placeholder: 'Type something here',

v2/components/autocomplete/autocomplete.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {Input, InputProps, SetInputFxn, useDebounce, useInput} from '../input/in
55
import ThemeDiv from '../theme-div/theme-div';
66

77
import './autocomplete.scss';
8+
import {Minimatch, IOptions} from 'minimatch';
89

910
interface AutocompleteProps extends InputProps {
1011
inputref?: React.MutableRefObject<HTMLInputElement>;
@@ -53,6 +54,7 @@ export const RenderAutocomplete = (
5354
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
5455
className?: string;
5556
style?: React.CSSProperties;
57+
glob?: boolean | IOptions;
5658
}
5759
) => {
5860
const [curItems, setCurItems] = React.useState(props.items || []);
@@ -80,9 +82,20 @@ export const RenderAutocomplete = (
8082
React.useEffect(() => {
8183
const filtered = (props.items || []).filter((i) => {
8284
if (i) {
85+
const searchValue = debouncedVal?.toLowerCase() || '';
86+
87+
const useGlob = typeof props.glob === 'boolean' ? props.glob : !!props.glob;
88+
const globOptions = typeof props.glob === 'boolean' ? null : props.glob;
89+
90+
const globMatcher = useGlob && searchValue ? new Minimatch(searchValue, globOptions) : null;
91+
92+
if (globMatcher) {
93+
return props.abbreviations !== undefined ? globMatcher.match(i) || globMatcher.match(props.abbreviations?.get(i) ?? '') : globMatcher.match(i);
94+
}
95+
8396
return props.abbreviations !== undefined
84-
? i.toLowerCase().includes(debouncedVal?.toLowerCase()) || props.abbreviations.get(i)?.includes(debouncedVal?.toLowerCase())
85-
: i.toLowerCase().includes(debouncedVal?.toLowerCase());
97+
? i.toLowerCase().includes(searchValue) || props.abbreviations.get(i)?.toLowerCase().includes(searchValue)
98+
: i.toLowerCase().includes(searchValue);
8699
}
87100
return false;
88101
});

yarn.lock

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3169,11 +3169,6 @@ ansi-regex@^2.0.0:
31693169
version "2.1.1"
31703170
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
31713171

3172-
ansi-regex@^3.0.0:
3173-
version "3.0.1"
3174-
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1"
3175-
integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==
3176-
31773172
ansi-regex@^4.1.0:
31783173
version "4.1.0"
31793174
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
@@ -8374,6 +8369,13 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
83748369
version "1.0.1"
83758370
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
83768371

8372+
8373+
version "5.1.6"
8374+
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
8375+
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
8376+
dependencies:
8377+
brace-expansion "^2.0.1"
8378+
83778379
minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
83788380
version "3.1.2"
83798381
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
@@ -11175,13 +11177,6 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1:
1117511177
dependencies:
1117611178
ansi-regex "^2.0.0"
1117711179

11178-
strip-ansi@^4.0.0:
11179-
version "4.0.0"
11180-
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
11181-
integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==
11182-
dependencies:
11183-
ansi-regex "^3.0.0"
11184-
1118511180
strip-ansi@^5.1.0:
1118611181
version "5.2.0"
1118711182
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
@@ -11190,7 +11185,6 @@ strip-ansi@^5.1.0:
1119011185
ansi-regex "^4.1.0"
1119111186

1119211187
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
11193-
name strip-ansi-cjs
1119411188
version "6.0.1"
1119511189
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
1119611190
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==

0 commit comments

Comments
 (0)