feat: SvgIcon 组件支持传入本地图片,网络图片增加载入和失败状态

This commit is contained in:
Hooray Hu
2024-08-14 17:49:03 +08:00
parent 1e155369b2
commit e79bd1dc50
3 changed files with 61 additions and 5 deletions
+1
View File
@@ -25,6 +25,7 @@
"dependencies": {
"@headlessui/vue": "^1.7.22",
"@imengyu/vue3-context-menu": "^1.4.2",
"@vueuse/components": "^10.11.1",
"@vueuse/core": "^10.11.0",
"@vueuse/integrations": "^10.11.0",
"axios": "^1.7.3",
+44 -1
View File
@@ -14,6 +14,9 @@ importers:
'@imengyu/vue3-context-menu':
specifier: ^1.4.2
version: 1.4.2
'@vueuse/components':
specifier: ^10.11.1
version: 10.11.1(vue@3.4.35(typescript@5.5.4))
'@vueuse/core':
specifier: ^10.11.0
version: 10.11.0(vue@3.4.35(typescript@5.5.4))
@@ -2306,9 +2309,15 @@ packages:
'@vue/shared@3.4.35':
resolution: {integrity: sha512-hvuhBYYDe+b1G8KHxsQ0diDqDMA8D9laxWZhNAjE83VZb5UDaXl9Xnz7cGdDSyiHM90qqI/CyGMcpBpiDy6VVQ==}
'@vueuse/components@10.11.1':
resolution: {integrity: sha512-ThcreQCX/eq61sLkLKjigD4PQvs3Wy4zglICvQH9tP6xl87y5KsQEoizn6OI+R3hrOgwQHLJe7Y0wLLh3fBKcg==}
'@vueuse/core@10.11.0':
resolution: {integrity: sha512-x3sD4Mkm7PJ+pcq3HX8PLPBadXCAlSDR/waK87dz0gQE+qJnaaFhc/dZVfJz+IUYzTMVGum2QlR7ImiJQN4s6g==}
'@vueuse/core@10.11.1':
resolution: {integrity: sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==}
'@vueuse/core@9.13.0':
resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==}
@@ -2356,12 +2365,18 @@ packages:
'@vueuse/metadata@10.11.0':
resolution: {integrity: sha512-kQX7l6l8dVWNqlqyN3ePW3KmjCQO3ZMgXuBMddIu83CmucrsBfXlH+JoviYyRBws/yLTQO8g3Pbw+bdIoVm4oQ==}
'@vueuse/metadata@10.11.1':
resolution: {integrity: sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==}
'@vueuse/metadata@9.13.0':
resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==}
'@vueuse/shared@10.11.0':
resolution: {integrity: sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==}
'@vueuse/shared@10.11.1':
resolution: {integrity: sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==}
'@vueuse/shared@9.13.0':
resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==}
@@ -8584,6 +8599,15 @@ snapshots:
'@vue/shared@3.4.35': {}
'@vueuse/components@10.11.1(vue@3.4.35(typescript@5.5.4))':
dependencies:
'@vueuse/core': 10.11.1(vue@3.4.35(typescript@5.5.4))
'@vueuse/shared': 10.11.1(vue@3.4.35(typescript@5.5.4))
vue-demi: 0.14.10(vue@3.4.35(typescript@5.5.4))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
'@vueuse/core@10.11.0(vue@3.4.35(typescript@5.5.4))':
dependencies:
'@types/web-bluetooth': 0.0.20
@@ -8594,6 +8618,16 @@ snapshots:
- '@vue/composition-api'
- vue
'@vueuse/core@10.11.1(vue@3.4.35(typescript@5.5.4))':
dependencies:
'@types/web-bluetooth': 0.0.20
'@vueuse/metadata': 10.11.1
'@vueuse/shared': 10.11.1(vue@3.4.35(typescript@5.5.4))
vue-demi: 0.14.10(vue@3.4.35(typescript@5.5.4))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
'@vueuse/core@9.13.0(vue@3.4.35(typescript@5.5.4))':
dependencies:
'@types/web-bluetooth': 0.0.16
@@ -8620,11 +8654,20 @@ snapshots:
'@vueuse/metadata@10.11.0': {}
'@vueuse/metadata@10.11.1': {}
'@vueuse/metadata@9.13.0': {}
'@vueuse/shared@10.11.0(vue@3.4.35(typescript@5.5.4))':
dependencies:
vue-demi: 0.14.8(vue@3.4.35(typescript@5.5.4))
vue-demi: 0.14.10(vue@3.4.35(typescript@5.5.4))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
'@vueuse/shared@10.11.1(vue@3.4.35(typescript@5.5.4))':
dependencies:
vue-demi: 0.14.10(vue@3.4.35(typescript@5.5.4))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
+16 -4
View File
@@ -1,4 +1,5 @@
<script setup lang="ts">
import { UseImage } from '@vueuse/components'
import { Icon } from '@iconify/vue'
defineOptions({
@@ -14,7 +15,10 @@ const props = defineProps<{
}>()
const outputType = computed(() => {
if (/^https?:\/\//.test(props.name)) {
const hasPathFeatures = (str: string) => {
return /^\.{1,2}\//.test(str) || str.startsWith('/') || str.includes('/')
}
if (/^https?:\/\//.test(props.name) || hasPathFeatures(props.name) || !props.name) {
return 'img'
}
else if (/i-[^:]+:[^:]+/.test(props.name)) {
@@ -56,11 +60,19 @@ const style = computed(() => {
</script>
<template>
<i class="relative h-[1em] w-[1em] flex-inline items-center justify-center fill-current leading-[1em]" :class="{ [name]: outputType === 'unocss' }" :style="style">
<Icon v-if="outputType === 'iconify'" :icon="name" />
<i class="relative h-[1em] w-[1em] flex-inline items-center justify-center fill-current leading-[1em]" :style="style">
<i v-if="outputType === 'unocss'" class="h-[1em] w-[1em]" :class="name" />
<Icon v-else-if="outputType === 'iconify'" :icon="name" />
<svg v-else-if="outputType === 'svg'" class="h-[1em] w-[1em]" aria-hidden="true">
<use :xlink:href="`#icon-${name}`" />
</svg>
<img v-else-if="outputType === 'img'" :src="name" class="h-[1em] w-[1em]">
<UseImage v-else-if="outputType === 'img'" :src="name" class="h-[1em] w-[1em]">
<template #loading>
<i class="i-line-md:loading-loop h-[1em] w-[1em]" />
</template>
<template #error>
<i class="i-tdesign:image-error h-[1em] w-[1em]" />
</template>
</UseImage>
</i>
</template>