2024-06-20 11:47:26 +00:00
|
|
|
import Fuse from 'fuse.js'
|
2024-10-13 17:37:01 +00:00
|
|
|
import type { Ref } from 'vue'
|
|
|
|
import { isRef, watch } from 'vue'
|
2024-06-20 11:47:26 +00:00
|
|
|
|
|
|
|
type Path<T> = T extends object ? {
|
|
|
|
[K in keyof T]:
|
2024-10-13 17:37:01 +00:00
|
|
|
`${Exclude<K, symbol>}${'' | `.${Path<T[K]>}`}`
|
2024-06-20 11:47:26 +00:00
|
|
|
}[keyof T] : never
|
|
|
|
|
|
|
|
export const useFuzzySearch = <T> (items: T[] | Ref<T[]>, keys: Path<T>[] | string[]) => {
|
|
|
|
const fuse = new Fuse<T>([], { keys })
|
|
|
|
let documents = items
|
|
|
|
|
|
|
|
const setDocuments = (newDocuments: T[]) => {
|
|
|
|
documents = newDocuments
|
|
|
|
fuse.setCollection(documents)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isRef<T[]>(items)) {
|
|
|
|
fuse.setCollection(items.value)
|
|
|
|
watch(items, () => setDocuments(items.value))
|
|
|
|
} else {
|
|
|
|
setDocuments(items)
|
|
|
|
}
|
|
|
|
|
|
|
|
const search = (query: string | null) => {
|
|
|
|
query = query?.trim() ?? null
|
|
|
|
|
2024-10-13 17:37:01 +00:00
|
|
|
return query
|
|
|
|
? fuse.search(query).map(result => result.item)
|
2024-06-20 11:47:26 +00:00
|
|
|
: isRef(documents) ? documents.value : documents
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
search,
|
2024-10-13 17:37:01 +00:00
|
|
|
setDocuments,
|
2024-06-20 11:47:26 +00:00
|
|
|
}
|
|
|
|
}
|