/
useSearch.ts
69 lines (56 loc) · 1.5 KB
/
useSearch.ts
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
import type { IFuseOptions } from 'fuse.js'
import Fuse from 'fuse.js'
import type { ComputedRef, Ref } from 'vue'
import { computed, onMounted, ref, watch } from 'vue'
export interface Command {
id?: string
title: string
subtitle?: string
icon?: string
shortcut?: string[]
section?: string
command?: () => void
listItemProps?: Record<string, unknown>
}
export function createCommand(action: Command) {
return action
}
interface Options<T> {
fuseOptions?: IFuseOptions<T>
}
export function useSearch(search: Ref<string>, list: ComputedRef<Command[]>, options?: Options<Command>) {
const result = ref<Command[]>(list.value)
onMounted(() => {
const fuse = new Fuse<Command>(list.value, {
keys: ['title'],
...options?.fuseOptions,
})
watch(search, (pattern) => {
if (!pattern) {
result.value = list.value
return
}
result.value = fuse.search(pattern).map(i => i.item)
}, { immediate: false })
})
return result
}
export function useSortedActions(commands: Ref<Command[]>) {
return computed(() => {
const sections: Record<string, Command[]> = {}
commands.value.forEach((item) => {
if (!item.section) {
if (sections.Uncategorized)
sections.Uncategorized.push(item)
else
sections.Uncategorized = [item]
return
}
if (sections[item.section])
sections[item.section].push(item)
else
sections[item.section] = [item]
})
return sections
})
}