parsley/app/javascript/components/AppIcon.vue
2018-08-29 16:58:07 -05:00

158 lines
3.7 KiB
Vue

<template>
<span class="icon" :class="sizeClass" @click="$emit('click', $event)" :style="{padding: wrapperPadding}">
<img ref="img" :class="['iconic', 'iconic-fluid', size]" :data-src="iconUrl" v-bind="extraIconAttributes" />
</span>
</template>
<script>
import IconicJs from "../iconic/js/iconic.min";
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 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 X from "../iconic/svg/smart/x";
const iconicInstance = IconicJs({
autoInjectSelector: null
});
class IconData {
constructor(url, dataAttributes) {
this.url = url;
this.dataAttributes = dataAttributes || [];
}
}
class SizeData {
constructor(bulmaIconClass, defaultPadding) {
this.bulmaIconClass = bulmaIconClass;
this.defaultPadding = defaultPadding;
}
}
const iconMap = {
'caret-bottom': new IconData(Caret, {direction: 'bottom'}),
'caret-top': new IconData(Caret, {direction: 'top'}),
check: new IconData(Check),
'circle-check': new IconData(CircleCheck),
'link-broken': new IconData(Link, {state: 'broken'}),
'link-intact': new IconData(Link, {state: 'intact'}),
'lock-locked': new IconData(Lock, {state: 'locked'}),
'lock-unlocked': new IconData(Lock, {state: 'unlocked'}),
pencil: new IconData(Pencil),
person: new IconData(Person),
star: new IconData(Star),
'star-empty': new IconData(StarEmpty),
x: new IconData(X)
};
const sizeMap = {
sm: new SizeData('is-small', '2px'),
md: new SizeData('', '3px'),
lg: new SizeData('is-medium', '4px'),
xl: new SizeData('is-large', '5px')
};
export default {
props: {
icon: {
validator: (i) => iconMap[i] !== undefined
},
size: {
required: false,
type: String,
validator: (s) => sizeMap[s] !== undefined,
default: 'md'
},
padding: {
type: String,
required: false,
default: null
}
},
data() {
return {
injectedSvg: null
}
},
computed: {
iconData() {
return iconMap[this.icon];
},
iconUrl() {
return this.iconData.url;
},
extraIconAttributes() {
const attrs = {};
for (let attr in this.iconData.dataAttributes) {
attrs[`data-${attr}`] = this.iconData.dataAttributes[attr];
}
return attrs;
},
sizeClass() {
return sizeMap[this.size].bulmaIconClass;
},
wrapperPadding() {
return this.padding || sizeMap[this.size].defaultPadding;
}
},
mounted() {
const self = this;
iconicInstance.inject(this.$refs.img, {
each: function(svg) { self.injectedSvg = svg; }
});
},
updated() {
for(let attr in this.extraIconAttributes) {
this.injectedSvg.setAttribute(attr, this.extraIconAttributes[attr]);
}
iconicInstance.update(this.injectedSvg);
}
}
</script>
<style lang="scss" scoped>
.icon /deep/ svg {
/*width: 100%;*/
/*height: 100%;*/
/*&.sm {*/
/*width: 0.75em;*/
/*height: 0.75em;*/
/*}*/
/*&.md {*/
/*width: 1em;*/
/*height: 1em;*/
/*}*/
/*&.lg {*/
/*width: 1.33em;*/
/*height: 1.33em;*/
/*}*/
/*&.xl {*/
/*width: 2em;*/
/*height: 2em;*/
/*}*/
}
</style>