mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-30 11:47:55 +01:00
fix(CommandPalette): reactivity issue + improve results
Resolves #95, resolves #96
This commit is contained in:
@@ -188,17 +188,15 @@
|
|||||||
<UCommandPalette
|
<UCommandPalette
|
||||||
v-model="form.persons"
|
v-model="form.persons"
|
||||||
multiple
|
multiple
|
||||||
|
:placeholder="false"
|
||||||
|
:options="{
|
||||||
|
fuseOptions: {
|
||||||
|
includeMatches: true
|
||||||
|
}
|
||||||
|
}"
|
||||||
:groups="[{
|
:groups="[{
|
||||||
key: 'persons',
|
key: 'persons',
|
||||||
commands: people,
|
commands: people
|
||||||
customQuery,
|
|
||||||
options: {
|
|
||||||
fuseOptions: {
|
|
||||||
includeMatches: true,
|
|
||||||
useExtendedSearch: true,
|
|
||||||
keys: ['name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]"
|
}]"
|
||||||
command-attribute="name"
|
command-attribute="name"
|
||||||
/>
|
/>
|
||||||
@@ -275,13 +273,14 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
const isModalOpen = ref(false)
|
const isModalOpen = ref(false)
|
||||||
|
|
||||||
const people = [
|
const people = ref([
|
||||||
{ id: 1, name: 'Durward Reynolds', disabled: false },
|
{ id: 1, name: 'Durward Reynolds', disabled: false },
|
||||||
{ id: 2, name: 'Kenton Towne', disabled: false },
|
{ id: 2, name: 'Kenton Towne', disabled: false },
|
||||||
{ id: 3, name: 'Therese Wunsch', disabled: false },
|
{ id: 3, name: 'Therese Wunsch', disabled: false },
|
||||||
{ id: 4, name: 'Benedict Kessler', disabled: true },
|
{ id: 4, name: 'Benedict Kessler', disabled: true },
|
||||||
{ id: 5, name: 'Katelyn Rohan', disabled: false, static: '1' }
|
{ id: 5, name: 'Katelyn Rohan', disabled: false }
|
||||||
]
|
])
|
||||||
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
email: '',
|
email: '',
|
||||||
description: '',
|
description: '',
|
||||||
@@ -290,8 +289,8 @@ const form = reactive({
|
|||||||
notifications: [],
|
notifications: [],
|
||||||
terms: false,
|
terms: false,
|
||||||
personId: null,
|
personId: null,
|
||||||
person: ref(people[0]),
|
person: ref(people.value[0]),
|
||||||
persons: ref([people[0]])
|
persons: ref([people.value[0]])
|
||||||
})
|
})
|
||||||
|
|
||||||
const { $toast } = useNuxtApp()
|
const { $toast } = useNuxtApp()
|
||||||
@@ -323,8 +322,6 @@ function openContextMenu () {
|
|||||||
isContextMenuOpen.value = true
|
isContextMenuOpen.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const customQuery = query => computed(() => query.value ? `${query.value} | =1` : '')
|
|
||||||
|
|
||||||
function toggleModalIsOpen () {
|
function toggleModalIsOpen () {
|
||||||
isModalOpen.value = !isModalOpen.value
|
isModalOpen.value = !isModalOpen.value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
</CommandPaletteGroup>
|
</CommandPaletteGroup>
|
||||||
</ComboboxOptions>
|
</ComboboxOptions>
|
||||||
|
|
||||||
<div v-else class="flex flex-col items-center justify-center flex-1 px-6 py-14 sm:px-14">
|
<div v-else-if="placeholder" class="flex flex-col items-center justify-center flex-1 px-6 py-14 sm:px-14">
|
||||||
<Icon :name="emptyIcon" class="w-6 h-6 mx-auto u-text-gray-400" aria-hidden="true" />
|
<Icon :name="emptyIcon" class="w-6 h-6 mx-auto u-text-gray-400" aria-hidden="true" />
|
||||||
<p class="mt-4 text-sm text-center u-text-gray-900">
|
<p class="mt-4 text-sm text-center u-text-gray-900">
|
||||||
{{ query ? "We couldn't find any items with that term. Please try again." : "We couldn't find any items." }}
|
{{ query ? "We couldn't find any items with that term. Please try again." : "We couldn't find any items." }}
|
||||||
@@ -45,6 +45,7 @@ import { ref, computed, onMounted } from 'vue'
|
|||||||
import { Combobox, ComboboxInput, ComboboxOptions } from '@headlessui/vue'
|
import { Combobox, ComboboxInput, ComboboxOptions } from '@headlessui/vue'
|
||||||
import type { ComputedRef, PropType, ComponentPublicInstance } from 'vue'
|
import type { ComputedRef, PropType, ComponentPublicInstance } from 'vue'
|
||||||
import { useFuse } from '@vueuse/integrations/useFuse'
|
import { useFuse } from '@vueuse/integrations/useFuse'
|
||||||
|
import { groupBy, map } from 'lodash-es'
|
||||||
import { defu } from 'defu'
|
import { defu } from 'defu'
|
||||||
import type { UseFuseOptions } from '@vueuse/integrations/useFuse'
|
import type { UseFuseOptions } from '@vueuse/integrations/useFuse'
|
||||||
import type { Group, Command } from '../../types/command-palette'
|
import type { Group, Command } from '../../types/command-palette'
|
||||||
@@ -108,6 +109,10 @@ const props = defineProps({
|
|||||||
autoselect: {
|
autoselect: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -117,13 +122,6 @@ const query = ref('')
|
|||||||
const comboboxInput = ref<ComponentPublicInstance<HTMLInputElement>>()
|
const comboboxInput = ref<ComponentPublicInstance<HTMLInputElement>>()
|
||||||
const comboboxApi = ref(null)
|
const comboboxApi = ref(null)
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
updateQuery: (q) => {
|
|
||||||
query.value = q
|
|
||||||
},
|
|
||||||
comboboxApi
|
|
||||||
})
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.autoselect) {
|
if (props.autoselect) {
|
||||||
activateFirstOption()
|
activateFirstOption()
|
||||||
@@ -149,15 +147,14 @@ const options: ComputedRef<Partial<UseFuseOptions<Command>>> = computed(() => de
|
|||||||
matchAllWhenSearchEmpty: true
|
matchAllWhenSearchEmpty: true
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const fuse = props.groups.reduce((acc, group) => {
|
const commands = computed(() => props.groups.reduce((acc, group) => {
|
||||||
// FIXME: useFuse is not watching data correctly, so we need to add an id
|
return acc.concat(group.commands.map(command => ({ ...command, group: group.key })))
|
||||||
const fuse = useFuse(group.customQuery ? group.customQuery(query) : query, group.commands, defu({}, group.options || {}, options.value))
|
}, [] as Command[]))
|
||||||
acc[group.key] = fuse
|
|
||||||
return acc
|
|
||||||
}, {})
|
|
||||||
|
|
||||||
const groups = computed(() => props.groups.map((group) => {
|
const { results } = useFuse(query, commands, options)
|
||||||
const commands = fuse[group.key].results.value.map((result) => {
|
|
||||||
|
const groups = computed(() => map(groupBy(results.value, command => command.item.group), (results, key) => {
|
||||||
|
const commands = results.map((result) => {
|
||||||
const { item, ...data } = result
|
const { item, ...data } = result
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -167,10 +164,10 @@ const groups = computed(() => props.groups.map((group) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...group,
|
...props.groups.find(group => group.key === key),
|
||||||
commands: commands.slice(0, group.options?.resultLimit || options.value.resultLimit)
|
commands: commands.slice(0, options.value.resultLimit)
|
||||||
}
|
}
|
||||||
}).filter(group => group.commands.length))
|
}))
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
|
||||||
@@ -200,6 +197,14 @@ function onClear () {
|
|||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
updateQuery: (q) => {
|
||||||
|
query.value = q
|
||||||
|
},
|
||||||
|
comboboxApi,
|
||||||
|
results
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|||||||
2
src/runtime/types/command-palette.d.ts
vendored
2
src/runtime/types/command-palette.d.ts
vendored
@@ -1,4 +1,3 @@
|
|||||||
import type { Ref, ComputedRef } from 'vue'
|
|
||||||
import type { UseFuseOptions } from '@vueuse/integrations/useFuse'
|
import type { UseFuseOptions } from '@vueuse/integrations/useFuse'
|
||||||
import type { Avatar } from './avatar'
|
import type { Avatar } from './avatar'
|
||||||
|
|
||||||
@@ -19,6 +18,5 @@ export interface Group {
|
|||||||
active?: string
|
active?: string
|
||||||
inactive?: string
|
inactive?: string
|
||||||
commands: Command[]
|
commands: Command[]
|
||||||
customQuery?: (query: Ref<string>) => ComputedRef<string>
|
|
||||||
options?: Partial<UseFuseOptions<Command>>
|
options?: Partial<UseFuseOptions<Command>>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user