index.vue 3.44 KB
<template>
  <div class="zui-tag">
    <template v-if="showQuarter">
      <div :class="computedClass">
        <div class="quarter-content">
          <slot></slot>
        </div>
        <div class="quarter-bg" :style="colorStyle"></div>
      </div>
    </template>
    <template v-else-if="showCoupon">
      <div :class="computedClass">
        <div class="coupon-container" :style="colorStyle">
          <div class="left-coupon" :style="leftCoupon" v-if="showCoupon"></div>
          <slot></slot>
          <div class="right-coupon" :style="rightCoupon" v-if="showCoupon"></div>
        </div>
      </div>
    </template>
    <template v-else>
      <div :class="computedClass" :style="[colorStyle, sizeStyle]">
        <slot></slot>
      </div>
    </template>
  </div>
</template>

<script>
export default {
  name: "Tag",
  props: {
    size: {
      type: String, // tiny, small, large
      default: "large"
    },
    shape: {
      // square, circle, fillet, quarter, coupon, bubble
      type: String,
      default: "square"
    },
    sharp: {
      // top-left, top-right, bottom-left, bottom-right
      type: String,
      default: ""
    },
    type: {
      // fill ghost
      type: String,
      default: "ghost"
    },
    fillColor: {
      type: String,
      default: ""
    },
    fontWeight: {
      // normal, bold, bolder
      type: String,
      default: "normal"
    },
    fontColor: {
      type: String,
      default: ""
    }
  },
  data: function() {
    return {
      sizeStyle: {}
    };
  },
  mounted() {
    this.$nextTick(() => {
      if (this.shape === "circle") {
        var radius = this.$el.offsetHeight / 2;
        this.$set(this.sizeStyle, "paddingLeft", radius / 2 + "px");
        this.$set(this.sizeStyle, "paddingRight", radius / 2 + "px");
        this.$set(this.sizeStyle, "borderRadius", radius + "px");
        if (this.sharp) {
          this.$set(
            this.sizeStyle,
            this.transformCamelCase("border-" + this.sharp + "-radius"),
            0
          );
        }
      }
    });
  },
  computed: {
    computedClass: function() {
      return [
        "default",
        "size-" + this.size,
        "shape-" + this.shape,
        "type-" + this.type,
        "font-weight-" + this.fontWeight
      ];
    },
    colorStyle: function() {
      var style = {};
      if (this.type === "fill") {
        // eslint-disable-next-line
        this.fillColor && (style.background = this.fillColor);
      }
      if (this.fontColor) {
        if (this.type === "ghost") {
          style.borderColor = this.fontColor;
        }
        style.color = this.fontColor;
      }
      return style;
    },
    leftCoupon: function() {
      return {
        background: this.fillColor
          ? "radial-gradient(circle at left, transparent 33%, " +
            this.fillColor +
            " 33%)"
          : ""
      };
    },
    rightCoupon: function() {
      return {
        background: this.fillColor
          ? "radial-gradient(circle at right, transparent 33%, " +
            this.fillColor +
            " 33%)"
          : ""
      };
    },
    showQuarter: function() {
      return this.shape === "quarter";
    },
    showCoupon: function() {
      return this.shape === "coupon";
    }
  },
  methods: {
    transformCamelCase: function(str) {
      var re = /-(\w)/g;
      return str.replace(re, function($0, $1) {
        return $1.toUpperCase();
      });
    }
  }
};
</script>

<style>
@import "./index.css";
</style>