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