1
1
import { debouncedRef } from '@vueuse/core'
2
2
import Fuse from 'fuse.js'
3
3
4
- const regexSearchShape = / ^ \/ (?< regex > . + ) \/ (?< flags > [ a - z ] * ) $ / s
4
+ type Key < T extends string > = T | { name : T , weight : number }
5
5
6
- const fuzzy = < T > ( list : Ref < T [ ] > , keys : string [ ] ) => {
6
+ const fuzzy = < T extends string , Item extends Record < T , unknown > = Record < T , unknown > > ( list : Ref < Item [ ] > , keys : Key < T > [ ] ) : Fuse < Item > => {
7
7
return new Fuse ( list . value , { includeScore : true , keys } )
8
8
}
9
9
10
- export const useSearch = < T extends Record < string , any > > ( list : Ref < T [ ] > , { keys, searchQuery = ref ( '' ) } : { keys : string [ ] , searchQuery ?: Ref < string > } ) => {
10
+ const regexSearchShape = / ^ \/ (?< regex > .+ ) \/ (?< flags > [ a - z ] * ) $ / s
11
+
12
+ const toKeyName = < T extends string > ( key : Key < T > ) : T => {
13
+ if ( typeof key === 'object' ) {
14
+ return key . name
15
+ }
16
+
17
+ return key
18
+ }
19
+
20
+ export const useSearch = < T extends string , Item extends Record < T , unknown > = Record < T , unknown > > ( list : Ref < Item [ ] > , { keys, searchQuery = ref ( '' ) } : { keys : Key < T > [ ] , searchQuery ?: Ref < string > } ) => {
11
21
const filterer = computed ( ( ) => fuzzy ( list , keys ) )
12
22
const searchQueryDebounced = debouncedRef ( searchQuery , 50 )
13
23
const searchResults = computed ( ( ) => {
@@ -25,7 +35,14 @@ export const useSearch = <T extends Record<string, any>>(list: Ref<T[]>, { keys,
25
35
26
36
return list . value . filter ( ( item ) => {
27
37
return keys . some ( ( key ) => {
28
- return searchRegex . test ( item [ key ] )
38
+ const k = toKeyName ( key )
39
+ const v = item [ k ]
40
+
41
+ if ( typeof v === 'string' ) {
42
+ return searchRegex . test ( v )
43
+ }
44
+
45
+ return false
29
46
} )
30
47
} )
31
48
} catch ( error ) {
@@ -45,7 +62,14 @@ export const useSearch = <T extends Record<string, any>>(list: Ref<T[]>, { keys,
45
62
// 4. If all else fails, do a case-insensitive full-text match.
46
63
return list . value . filter ( ( item ) => {
47
64
return keys . some ( ( key ) => {
48
- return item [ key ] . toLowerCase ( ) . includes ( searchQueryDebounced . value . toLowerCase ( ) )
65
+ const k = toKeyName ( key )
66
+ const v = item [ k ]
67
+
68
+ if ( typeof v === 'string' ) {
69
+ return v . toLowerCase ( ) . includes ( searchQueryDebounced . value . toLowerCase ( ) )
70
+ }
71
+
72
+ return false
49
73
} )
50
74
} )
51
75
} )
0 commit comments