IconPicker.vue
2.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<script lang="ts" setup>
import { NInput, NInputGroup, NInputGroupLabel, NPopover, NScrollbar } from 'naive-ui';
import '@/assets/external/iconfont/iconfont.js'
import iconfont from '@/assets/external/iconfont/iconfont.json'
import SvgIcon from './SvgIcon.vue';
import { computed, ref, unref } from 'vue';
import { useDesignStore } from '@/store/modules/designStore/designStore';
const props = defineProps({
value: {
type: String,
}
})
const emit = defineEmits(['update:value'])
const searchValue = ref<string>('')
const getIconList = computed(() => {
const icons = iconfont.glyphs.map(item => item.font_class)
const text = unref(searchValue)
return icons.filter(icon => icon.includes(text))
})
const designStore = useDesignStore()
const themeColor = computed(() => {
return designStore.getAppTheme
})
const handleChange = (icon: string) => {
emit('update:value', icon)
}
</script>
<template>
<NInputGroup class="icon-picker">
<NInput :value="value" placeholder="请选择图标" disabled />
<NPopover trigger="click">
<NInput v-model:value="searchValue" size="small" style="text-overflow: ellipsis;" />
<NScrollbar style="max-height: 120px; max-width: 210px; margin-top: 5px;">
<ul class="icon-list">
<li class="icon-item" v-for="icon in getIconList" :key="icon" @click="handleChange(icon)"
:style="{ border: icon === props.value ? `1px solid ${themeColor}` : '' }">
<SvgIcon :name="icon" prefix="iconfont" />
</li>
</ul>
</NScrollbar>
<template #trigger>
<NInputGroupLabel style="cursor: pointer;">
<SvgIcon :name="value || 'grid-one'" prefix="iconfont" style="cursor: pointer;" />
</NInputGroupLabel>
</template>
</NPopover>
</NInputGroup>
</template>
<style lang="scss" scoped>
.icon {
&-picker {
@include deep() {
.n-input__input-el {
text-overflow: ellipsis;
}
}
}
&-list {
display: flex;
list-style: none;
padding: 0;
justify-content: start;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
&-item {
box-sizing: border-box;
cursor: pointer;
width: 35px;
height: 35px;
display: flex;
justify-content: center;
align-items: center;
transition: transform .5s linear;
&:hover {
border: 1px solid v-bind("themeColor");
}
}
}
</style>