<script lang="ts" setup>
|
import { propTypes } from '@/utils/propTypes'
|
import Iconify from '@purge-icons/generated'
|
import { useDesign } from '@/hooks/web/useDesign'
|
|
defineOptions({ name: 'Icon' })
|
|
const { getPrefixCls } = useDesign()
|
|
const prefixCls = getPrefixCls('icon')
|
|
const props = defineProps({
|
// icon name
|
icon: propTypes.string,
|
// icon color
|
color: propTypes.string,
|
// icon size
|
size: propTypes.number.def(16),
|
// icon svg class
|
svgClass: propTypes.string.def('')
|
})
|
|
const elRef = ref<ElRef>(null)
|
|
const isLocal = computed(() => props.icon?.startsWith('svg-icon:'))
|
|
const symbolId = computed(() => {
|
return unref(isLocal) ? `#icon-${props.icon.split('svg-icon:')[1]}` : props.icon
|
})
|
|
const getIconifyStyle = computed(() => {
|
const { color, size } = props
|
return {
|
fontSize: `${size}px`,
|
height: '1em',
|
color
|
}
|
})
|
|
const getSvgClass = computed(() => {
|
const { svgClass } = props
|
return `iconify ${svgClass}`
|
})
|
|
const updateIcon = async (icon: string) => {
|
if (unref(isLocal)) return
|
|
const el = unref(elRef)
|
if (!el) return
|
|
await nextTick()
|
|
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)
|
}
|
}
|
|
watch(
|
() => props.icon,
|
(icon: string) => {
|
updateIcon(icon)
|
}
|
)
|
</script>
|
|
<template>
|
<ElIcon :class="prefixCls" :color="color" :size="size">
|
<svg v-if="isLocal" :class="getSvgClass" aria-hidden="true">
|
<use :xlink:href="symbolId" />
|
</svg>
|
|
<span v-else ref="elRef" :class="$attrs.class" :style="getIconifyStyle">
|
<span :class="getSvgClass" :data-icon="symbolId"></span>
|
</span>
|
</ElIcon>
|
</template>
|