优化IconPicker组件

This commit is contained in:
jingrow 2025-11-02 13:52:09 +08:00
parent 463088f77c
commit 5abb859559

View File

@ -22,7 +22,7 @@
v-model:show="showPicker"
:width="900"
:placement="'right'"
:trap-focus="false"
:trap-focus="true"
:close-on-esc="true"
>
<n-drawer-content :title="t('Select Icon')" :closable="true">
@ -32,6 +32,7 @@
<div class="search-section">
<div class="search-controls">
<n-input
ref="searchInputRef"
v-model:value="searchQuery"
:placeholder="t('Search icon name...')"
clearable
@ -118,8 +119,10 @@
</template>
<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'
import { ref, computed, watch, nextTick } from 'vue'
import { useDebounceFn } from '@vueuse/core'
import { NButton, NDrawer, NDrawerContent, NInput, NSelect, useMessage } from 'naive-ui'
import type { InputInst } from 'naive-ui'
import { Icon } from '@iconify/vue'
import { getIconLibraryConfig, getAvailableIconLibraries, DEFAULT_ICON_LIBRARY } from '@/shared/utils/icon-libraries'
import { t } from '@/shared/i18n'
@ -153,6 +156,7 @@ const loading = ref(false)
const currentPage = ref(1)
const pageSize = ref(200) // 200
const hasMore = ref(true)
const searchInputRef = ref<InputInst | null>(null)
//
const currentLibraryConfig = computed(() => {
@ -316,6 +320,9 @@ function selectIcon(iconName: string) {
//
async function openPicker() {
// drawerwatch
showPicker.value = true
//
if (selectedIcon.value && selectedIcon.value.includes(':')) {
const [prefix, iconName] = selectedIcon.value.split(':')
@ -325,8 +332,6 @@ async function openPicker() {
if (correctLibrary) {
//
currentLibrary.value = correctLibrary.name
//
await loadAllIcons()
//
tempSelectedIcon.value = iconName
//
@ -335,7 +340,6 @@ async function openPicker() {
// All
if (currentLibraryConfig.value.name !== 'all') {
currentLibrary.value = 'all'
await loadAllIcons()
}
tempSelectedIcon.value = selectedIcon.value
// All使
@ -350,7 +354,6 @@ async function openPicker() {
tempSelectedIcon.value = ''
searchQuery.value = ''
}
showPicker.value = true
}
//
@ -385,15 +388,20 @@ function handleScroll(event: Event) {
}
}
//
const debouncedHandleSearch = useDebounceFn(() => {
currentPage.value = 1
}, 300)
//
function handleSearch() {
//
currentPage.value = 1
debouncedHandleSearch()
}
//
async function handleLibraryChange(newLibrary: string) {
currentLibrary.value = newLibrary
//
await loadAllIcons()
//
tempSelectedIcon.value = ''
@ -430,9 +438,20 @@ watch(() => props.modelValue, (newValue) => {
}
}, { immediate: true })
//
onMounted(() => {
loadAllIcons()
// drawer
watch(showPicker, async (isOpen) => {
if (isOpen) {
//
if (allIcons.value.length === 0) {
await loadAllIcons()
}
// drawer DOM
await nextTick()
setTimeout(() => {
searchInputRef.value?.focus()
}, 150)
}
})
//