mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-19 14:31:47 +01:00
chore(CommandPalette): handle loading state (#221)
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
>
|
||||
<div :class="ui.wrapper">
|
||||
<div v-show="searchable" :class="ui.input.wrapper">
|
||||
<UIcon v-if="icon" :name="icon" :class="[ui.input.icon.base, ui.input.icon.size]" aria-hidden="true" />
|
||||
<UIcon v-if="iconName" :name="iconName" :class="iconClass" aria-hidden="true" />
|
||||
<ComboboxInput
|
||||
ref="comboboxInput"
|
||||
:value="query"
|
||||
@@ -74,6 +74,7 @@ import type { Group, Command } from '../../types/command-palette'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UButton from '../elements/Button.vue'
|
||||
import type { Button as ButtonType } from '../../types/button'
|
||||
import { classNames } from '../../utils'
|
||||
import CommandPaletteGroup from './CommandPaletteGroup.vue'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
@@ -112,6 +113,10 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
groups: {
|
||||
type: Array as PropType<Group[]>,
|
||||
default: () => []
|
||||
@@ -120,6 +125,10 @@ export default defineComponent({
|
||||
type: String,
|
||||
default: () => appConfig.ui.commandPalette.default.icon
|
||||
},
|
||||
loadingIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.commandPalette.default.loadingIcon
|
||||
},
|
||||
selectedIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.commandPalette.default.selectedIcon
|
||||
@@ -175,6 +184,7 @@ export default defineComponent({
|
||||
const query = ref('')
|
||||
const comboboxInput = ref<ComponentPublicInstance<HTMLInputElement>>()
|
||||
const comboboxApi = ref(null)
|
||||
const isLoading = ref(false)
|
||||
|
||||
onMounted(() => {
|
||||
if (props.autoselect) {
|
||||
@@ -231,10 +241,17 @@ export default defineComponent({
|
||||
|
||||
const debouncedSearch = useDebounceFn(async () => {
|
||||
const searchableGroups = props.groups.filter(group => !!group.search)
|
||||
if (!searchableGroups.length) {
|
||||
return
|
||||
}
|
||||
|
||||
isLoading.value = true
|
||||
|
||||
await Promise.all(searchableGroups.map(async (group) => {
|
||||
searchResults.value[group.key] = await group.search(query.value)
|
||||
}))
|
||||
|
||||
isLoading.value = false
|
||||
}, props.debounce)
|
||||
|
||||
watch(query, () => {
|
||||
@@ -247,6 +264,22 @@ export default defineComponent({
|
||||
}, 0)
|
||||
})
|
||||
|
||||
const iconName = computed(() => {
|
||||
if ((props.loading || isLoading.value) && props.loadingIcon) {
|
||||
return props.loadingIcon
|
||||
}
|
||||
|
||||
return props.icon
|
||||
})
|
||||
|
||||
const iconClass = computed(() => {
|
||||
return classNames(
|
||||
ui.value.input.icon.base,
|
||||
ui.value.input.icon.size,
|
||||
((props.loading || isLoading.value) && props.loadingIcon) && 'animate-spin'
|
||||
)
|
||||
})
|
||||
|
||||
// Methods
|
||||
|
||||
function activateFirstOption () {
|
||||
@@ -292,6 +325,8 @@ export default defineComponent({
|
||||
groups,
|
||||
comboboxInput,
|
||||
query,
|
||||
iconName,
|
||||
iconClass,
|
||||
onSelect,
|
||||
onClear
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user