| | |
| | | :style="getWrapStyle" |
| | | ></span> |
| | | </template> |
| | | <script lang="ts"> |
| | | <script lang="ts" setup> |
| | | import type { PropType } from 'vue'; |
| | | import { |
| | | defineComponent, |
| | | ref, |
| | | watch, |
| | | onMounted, |
| | | nextTick, |
| | | unref, |
| | | computed, |
| | | CSSProperties, |
| | | } from 'vue'; |
| | | import { ref, watch, onMounted, nextTick, unref, computed, CSSProperties } from 'vue'; |
| | | import SvgIcon from './src/SvgIcon.vue'; |
| | | import Iconify from '@purge-icons/generated'; |
| | | import { isString } from '/@/utils/is'; |
| | | import { propTypes } from '/@/utils/propTypes'; |
| | | import { isString } from '@/utils/is'; |
| | | import { propTypes } from '@/utils/propTypes'; |
| | | |
| | | const SVG_END_WITH_FLAG = '|svg'; |
| | | export default defineComponent({ |
| | | name: 'Icon', |
| | | components: { SvgIcon }, |
| | | props: { |
| | | // icon name |
| | | icon: propTypes.string, |
| | | // icon color |
| | | color: propTypes.string, |
| | | // icon size |
| | | size: { |
| | | type: [String, Number] as PropType<string | number>, |
| | | default: 16, |
| | | }, |
| | | spin: propTypes.bool.def(false), |
| | | prefix: propTypes.string.def(''), |
| | | |
| | | defineOptions({ name: 'Icon' }); |
| | | |
| | | const props = defineProps({ |
| | | // icon name |
| | | icon: propTypes.string, |
| | | // icon color |
| | | color: propTypes.string, |
| | | // icon size |
| | | size: { |
| | | type: [String, Number] as PropType<string | number>, |
| | | default: 16, |
| | | }, |
| | | setup(props) { |
| | | const elRef = ref(null); |
| | | |
| | | const isSvgIcon = computed(() => props.icon?.endsWith(SVG_END_WITH_FLAG)); |
| | | const getSvgIcon = computed(() => props.icon.replace(SVG_END_WITH_FLAG, '')); |
| | | const getIconRef = computed(() => `${props.prefix ? props.prefix + ':' : ''}${props.icon}`); |
| | | |
| | | const update = async () => { |
| | | if (unref(isSvgIcon)) return; |
| | | |
| | | const el: any = unref(elRef); |
| | | if (!el) return; |
| | | |
| | | 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: color, |
| | | display: 'inline-flex', |
| | | }; |
| | | }); |
| | | |
| | | watch(() => props.icon, update, { flush: 'post' }); |
| | | |
| | | onMounted(update); |
| | | |
| | | return { elRef, getWrapStyle, isSvgIcon, getSvgIcon }; |
| | | }, |
| | | spin: propTypes.bool.def(false), |
| | | prefix: propTypes.string.def(''), |
| | | }); |
| | | |
| | | const elRef = ref(null); |
| | | |
| | | const isSvgIcon = computed(() => props.icon?.endsWith(SVG_END_WITH_FLAG)); |
| | | const getSvgIcon = computed(() => props.icon.replace(SVG_END_WITH_FLAG, '')); |
| | | const getIconRef = computed(() => `${props.prefix ? props.prefix + ':' : ''}${props.icon}`); |
| | | |
| | | const update = async () => { |
| | | if (unref(isSvgIcon)) return; |
| | | |
| | | const el: any = unref(elRef); |
| | | if (!el) return; |
| | | |
| | | 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: color, |
| | | display: 'inline-flex', |
| | | }; |
| | | }); |
| | | |
| | | watch(() => props.icon, update, { flush: 'post' }); |
| | | |
| | | onMounted(update); |
| | | </script> |
| | | <style lang="less"> |
| | | .app-iconify { |