CommonIcon.vue 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { computed } from 'vue'
  4. import log from '#shared/utils/log.ts'
  5. import { useIcons } from './useIcons.ts'
  6. import { usePrivateIcon } from './usePrivateIcon.ts'
  7. import type { Animations, Sizes } from './types.ts'
  8. export interface Props {
  9. size?: Sizes
  10. fixedSize?: { width: number; height: number }
  11. name: string
  12. label?: string
  13. decorative?: boolean
  14. animation?: Animations
  15. }
  16. const props = withDefaults(defineProps<Props>(), {
  17. size: 'medium',
  18. decorative: false,
  19. })
  20. const emit = defineEmits<{
  21. click: [MouseEvent]
  22. }>()
  23. const onClick = (event: MouseEvent) => {
  24. emit('click', event)
  25. }
  26. const { iconClass, finalSize } = usePrivateIcon(props)
  27. const { icons, aliases } = useIcons()
  28. const iconName = computed(() => {
  29. const alias = aliases[props.name]
  30. const name = alias || props.name
  31. if (!icons[name]) {
  32. log.warn(`Icon ${name} not found`)
  33. }
  34. return name
  35. })
  36. </script>
  37. <template>
  38. <svg
  39. xmlns="http://www.w3.org/2000/svg"
  40. class="icon fill-current"
  41. :class="iconClass"
  42. :width="finalSize.width"
  43. :height="finalSize.height"
  44. :aria-label="decorative ? undefined : $t(label || iconName)"
  45. :aria-hidden="decorative"
  46. @click="onClick"
  47. >
  48. <use :href="`#icon-${iconName}`" />
  49. </svg>
  50. </template>