1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
<template>
<svg
v-if="spriteLoaded"
:class="computedClass"
:style="colorStyle"
:width="`${size}px`"
:height="`${size}px`"
fill="currentColor"
:aria-hidden="ariaHidden"
:role="ariaRole"
:aria-label="ariaLabel || undefined"
>
<use :href="`#icon-${shape}`" />
</svg>
</template>
<script setup>
import { computed, ref, onMounted } from 'vue'
const props = defineProps({
shape: { type: String, required: true },
size: { type: Number, default: 20 },
inline: { type: Boolean, default: false },
class: { type: String, default: '', alias: 'customClass' },
role: { type: String, default: '', alias: 'iconRole' },
hex: {
type: String,
default: '',
validator: (value) => /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(value),
},
ariaLabel: { type: String, default: '' },
})
const iconRoleColorMap = {
clickable: 'highlight',
navigation: 'highlight',
sort: 'highlight',
accept: 'good',
attention: 'warning',
info: 'font-primary',
info_alt: 'font-inverted',
inactive: 'font-inactive',
new: 'red-1',
'status-green': 'green-1',
'status-red': 'red-1',
'status-yellow': 'yellow-1',
}
const isDecorative = computed(() => !props.ariaLabel || props.ariaLabel.trim() === '')
const ariaHidden = computed(() => isDecorative.value)
const ariaRole = computed(() => (isDecorative.value ? undefined : 'img'))
const computedClass = computed(() => [
'sui-icon',
`sui-icon--${props.shape}`,
{ 'sui-icon--inline': props.inline },
props.class,
])
const colorStyle = computed(() => {
if (props.hex) {
return { color: props.hex }
}
if (props.role) {
// iconRole
const colorVar = iconRoleColorMap[props.role]
return colorVar ? { color: `var(--color--${colorVar})` } : {}
}
return { color: 'var(--color--font-primary)' }
})
const spriteLoaded = ref(false)
const loadSprite = async () => {
if (window.__STUDIP_ICON_SPRITE_LOADED__) {
spriteLoaded.value = true
return
}
if (!document.getElementById('svg-sprite')) {
const spritePath = window.STUDIP?.URLHelper?.getURL
? window.STUDIP.URLHelper.getURL('assets/images/icons/icons.svg', {}, true)
: './assets/images/icons/icons.svg'
const res = await fetch(spritePath)
const svgText = await res.text()
const div = document.createElement('div')
div.innerHTML = svgText
const svg = div.querySelector('svg')
svg.id = 'svg-sprite'
svg.style.display = 'none'
document.body.prepend(svg)
}
window.__STUDIP_ICON_SPRITE_LOADED__ = true
spriteLoaded.value = true
}
onMounted(loadSprite)
</script>
|