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
98
| <template>
| <span ref="elRef" :class="[$attrs.class, 'app-iconify anticon']" :style="getWrapStyle"></span>
| </template>
| <script lang="ts">
| import type { PropType } from 'vue';
| import {
| defineComponent,
| ref,
| watch,
| onMounted,
| nextTick,
| unref,
| computed,
| CSSProperties,
| } from 'vue';
| import Iconify from '@purge-icons/generated';
| import { isString } from '/@/utils/is';
| import { propTypes } from '/@/utils/propTypes';
|
| export default defineComponent({
| name: 'GIcon',
| props: {
| // icon name
| icon: propTypes.string,
| // icon color
| color: propTypes.string,
| // icon size
| size: {
| type: [String, Number] as PropType<string | number>,
| default: 16,
| },
| prefix: propTypes.string.def(''),
| },
| setup(props) {
| const elRef = ref<ElRef>(null);
|
| const getIconRef = computed(() => {
| const { icon, prefix } = props;
| return `${prefix ? prefix + ':' : ''}${icon}`;
| });
|
| const update = async () => {
| const el = unref(elRef);
| if (el) {
| await nextTick();
| const icon = unref(getIconRef);
| if (!icon) return;
| const svg = Iconify.renderSVG(icon, {});
| if (svg) {
| el.textContent = '';
| el.appendChild(svg);
| } else {
| const span = document.createElement('span');
| span.className = 'iconify';
| span.dataset.icon = icon;
| el.textContent = '';
| el.appendChild(span);
| }
| }
| };
|
| const getWrapStyle = computed(
| (): CSSProperties => {
| const { size, color } = props;
| let fs = size;
| if (isString(size)) {
| fs = parseInt(size, 10);
| }
| return {
| fontSize: `${fs}px`,
| color,
| display: 'inline-flex',
| };
| }
| );
|
| watch(() => props.icon, update, { flush: 'post' });
|
| onMounted(update);
|
| return { elRef, getWrapStyle };
| },
| });
| </script>
| <style lang="less">
| .app-iconify {
| display: inline-block;
| vertical-align: middle;
| }
|
| span.iconify {
| display: block;
| min-width: 1em;
| min-height: 1em;
| background: @iconify-bg-color;
| border-radius: 100%;
| }
| </style>
|
|