43 lines
971 B
Vue
43 lines
971 B
Vue
<script setup>
|
||
import { computed } from 'vue';
|
||
import * as LucideIcons from 'lucide-vue-next';
|
||
|
||
const props = defineProps({
|
||
name: {
|
||
type: String,
|
||
required: true,
|
||
},
|
||
size: {
|
||
type: [Number, String],
|
||
default: 24,
|
||
},
|
||
color: {
|
||
type: String,
|
||
default: 'currentColor',
|
||
},
|
||
strokeWidth: {
|
||
type: [Number, String],
|
||
default: 2,
|
||
},
|
||
});
|
||
|
||
const icon = computed(() => {
|
||
// Lucide 图标通常是 PascalCase,用户输入可能是 kebab-case
|
||
const pascalName = props.name
|
||
.split('-')
|
||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||
.join('');
|
||
|
||
return LucideIcons[pascalName] || LucideIcons[props.name] || null;
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<component :is="icon" v-if="icon" :size="size" :color="color" :stroke-width="strokeWidth" class="lucide-icon" />
|
||
<span
|
||
v-else
|
||
class="lucide-icon-fallback"
|
||
:style="{ width: size + 'px', height: size + 'px', display: 'inline-block' }"
|
||
></span>
|
||
</template>
|