parsley/app/javascript/components/AppIconicIcon.vue

161 lines
3.6 KiB
Vue

<template>
<svg v-bind="svgAttributes" v-html="svgContent" :class="calculatedClasses"></svg>
</template>
<script>
import Caret from "../iconic/svg/smart/caret";
import Check from "../iconic/svg/smart/check";
import CircleCheck from "../iconic/svg/smart/circle-check";
import Link from "../iconic/svg/smart/link";
import Lock from "../iconic/svg/smart/lock";
import Menu from "../iconic/svg/smart/menu";
import QuestionMark from "../iconic/svg/smart/question-mark.svg"
import Person from "../iconic/svg/smart/person";
import Pencil from "../iconic/svg/smart/pencil";
import Star from "../iconic/svg/smart/star";
import StarEmpty from "../iconic/svg/smart/star-empty";
import Warning from "../iconic/svg/smart/warning";
import X from "../iconic/svg/smart/x";
const APIS = {};
const LOADED_APIS = {};
window._Iconic = {
smartIconApis: APIS
};
let globalIdCounter = 0;
const iconMap = {
caret: Caret,
check: Check,
'circle-check': CircleCheck,
link: Link,
lock: Lock,
menu: Menu,
pencil: Pencil,
person: Person,
'question-mark': QuestionMark,
star: Star,
'star-empty': StarEmpty,
warning: Warning,
x: X
};
export default {
props: {
icon: {
type: String,
required: true,
validator: (i) => iconMap[i] !== undefined
},
size: {
type: String,
default: "lg",
validator: (s) => ["sm", "md", "lg"].indexOf(s) >= 0
},
iconSizeOverride: {
type: String,
validator: (s) => ["sm", "md", "lg", null].indexOf(s) >= 0
},
displaySizeOverride: {
type: String,
validator: (s) => ["sm", "md", "lg", null].indexOf(s) >= 0
}
},
data() {
return {
calculatedClasses: []
}
},
computed: {
svgData() {
return iconMap[this.icon];
},
svgAttributes() {
return this.svgData.attributes;
},
svgName() {
return this.svgAttributes['data-icon'];
},
svgContent() {
let content = String(this.svgData.content);
for (let idRep of this.svgData.idReplacements) {
let newId = `__new_id_${globalIdCounter}`;
globalIdCounter += 1;
content = content.replace(new RegExp(idRep, "g"), newId);
}
return content;
}
},
methods: {
rebind() {
const apis = APIS;
if (apis && this.svgName && apis[this.svgName]) {
const iconApi = apis[this.svgName](this.$el);
for (let func in iconApi) this.$el[func] = iconApi[func]
} else {
this.$el.update = function() {}
}
this.calculatedClasses = (this.svgAttributes.class || "").split(" ");
this.calculatedClasses.push(`iconic-${this.size}`);
if (this.iconSizeOverride) {
this.calculatedClasses.push(`iconic-icon-${this.iconSizeOverride}`);
}
if (this.displaySizeOverride) {
this.calculatedClasses.push(`iconic-size-${this.displaySizeOverride}`);
}
this.$el.update();
}
},
created() {
if (LOADED_APIS[this.svgName] !== true) {
for (let sb of this.svgData.scriptBlocks) {
try {
new Function(sb)(window);
} catch (e) {
console.log(sb);
console.log(e);
}
}
LOADED_APIS[this.svgName] = true;
}
},
mounted() {
this.$watch(
function() { return [this.$attrs, this.icon, this.fluid] },
function() {
this.rebind()
},
{
immediate: true
}
);
}
}
</script>