<template>
  <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners"></div>
  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
    <use :xlink:href="iconName" />
  </svg>
</template>

<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal, isNumber } from '@/utils/validate';

export default {
  name: 'SvgIcon',
  props: {
    size: {
      type: [String, Number],
      default: '',
    },
    width: {
      type: [String, Number],
      default: '1rem',
    },
    height: {
      type: [String, Number],
      default: '1rem',
    },
    iconClass: {
      type: String,
      required: true,
    },
    className: {
      type: String,
      default: '',
    },
  },
  computed: {
    _width() {
      return this._getSize(this.width, this.size);
    },
    _height() {
      return this._getSize(this.height, this.size);
    },
    isExternal() {
      return isExternal(this.iconClass);
    },
    iconName() {
      return `#icon-${this.iconClass}`;
    },
    svgClass() {
      const classes = ['svg-icon', this.iconClass];
      if (this.className) {
        classes.push(this.className);
      }
      return classes.join(' ');
    },
    styleExternalIcon() {
      return {
        mask: `url(${this.iconClass}) no-repeat 50% 50%`,
        '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`,
      };
    },
  },
  methods: {
    /**
     * 获取尺寸
     * @param {String|Number} value
     * @param {String|Number} size
     */
    _getSize(value, size) {
      if (size) {
        if (isNumber(size)) return `${size}px`;
        return size;
      }
      if (isNumber(value)) {
        return `${value}px`;
      }
      return value;
    },
  },
};
</script>

<style scoped>
.svg-icon {
  width: v-bind(_width);
  height: v-bind(_height);
  overflow: hidden;
  vertical-align: -0.15em;
  fill: currentColor;
}

.svg-external-icon {
  display: inline-block;
  background-color: currentColor;
  mask-size: cover !important;
}
</style>
