fix(CommandPalette): improve performances and avoid multiple recompute

This commit is contained in:
Benjamin Canac
2023-12-08 15:28:53 +01:00
parent ad33b26729
commit db508b218f

View File

@@ -62,7 +62,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { ref, computed, watch, toRef, onMounted, defineComponent } from 'vue' import { ref, computed, watch, toRef, onMounted, defineComponent, toRaw } from 'vue'
import { Combobox as HCombobox, ComboboxInput as HComboboxInput, ComboboxOptions as HComboboxOptions } from '@headlessui/vue' import { Combobox as HCombobox, ComboboxInput as HComboboxInput, ComboboxOptions as HComboboxOptions } from '@headlessui/vue'
import type { ComputedRef, PropType, ComponentPublicInstance } from 'vue' import type { ComputedRef, PropType, ComponentPublicInstance } from 'vue'
import { useDebounceFn } from '@vueuse/core' import { useDebounceFn } from '@vueuse/core'
@@ -227,52 +227,60 @@ export default defineComponent({
const { results } = useFuse(query, commands, options) const { results } = useFuse(query, commands, options)
const groups = computed(() => { function getGroupWithCommands (group: Group, commands: Command[]) {
const groups: Group[] = [] if (!group) {
return
const groupedCommands: Record<string, typeof results['value']> = {}
for (const command of results.value) {
if (!command.item.group) {
continue
}
groupedCommands[command.item.group] ||= []
groupedCommands[command.item.group].push(command)
} }
for (const key in groupedCommands) {
const q = toRaw(query)
let newCommands = [...commands]
if (group.filter && typeof group.filter === 'function') {
newCommands = group.filter(q, newCommands)
}
return {
...group,
commands: newCommands.slice(0, options.value.resultLimit)
}
}
const groups = computed(() => {
if (!results.value) {
return []
}
const groupedCommands: Record<string, Command[]> = results.value.reduce((acc, command) => {
const { item, ...data } = command
if (!item.group) {
return acc
}
acc[command.item.group] ||= []
acc[command.item.group].push({ ...item, ...data })
return acc
}, {})
const groups: Group[] = Object.entries(groupedCommands).map(([key, commands]) => {
const group = props.groups.find(group => group.key === key) const group = props.groups.find(group => group.key === key)
if (!group) { if (!group) {
continue return null
} }
let commands = groupedCommands[key].map((result) => { return getGroupWithCommands(group, commands)
const { item, ...data } = result }).filter(Boolean)
return { const searchGroups = props.groups.filter(group => !!group.search && searchResults.value[group.key]?.length).map(group => {
...item, const commands = (searchResults.value[group.key] || [])
...data
} as Command
})
if (group.filter && typeof group.filter === 'function') { return getGroupWithCommands(group, commands)
commands = group.filter(query.value, commands) })
}
groups.push({ ...group, commands: commands.slice(0, options.value.resultLimit) }) return [
} ...groups,
...searchGroups
for (const group of props.groups) { ]
if (group.search && searchResults.value[group.key]?.length) {
let commands = (searchResults.value[group.key] || [])
if (group.filter && typeof group.filter === 'function') {
commands = group.filter(query.value, commands)
}
groups.push({ ...group, commands: commands.slice(0, options.value.resultLimit) })
}
}
return groups
}) })
const debouncedSearch = useDebounceFn(async () => { const debouncedSearch = useDebounceFn(async () => {