<template>
  <div class="vrcp-color-picker" :style="{width:width>0?(width+'px'):'100%',height:height>0?(height+'px'):'100%'}">
    <a-popover v-model:visible="popoverVisible" 
        :title="title" :placement="placement" :trigger="trigger"
        :arrow-point-at-center="true" :get-popup-container="popupContainer">
      <template #content>
        <div class="vrcp-container">
          <!--菜单-->
          <div v-if="menus && menus.length>0" class="menus">
            <div v-for="(menu) in menus" :key="menu" class="menu" 
                :class="{'menu-selected':menuCode==menu}" @click.stop="menuCode=menu">
              {{ langs[menu] }}
            </div>
          </div>
          <!--渐变色条-->
          <div v-if="menuCode=='gradient'" class="gradient">
            <div class="setting">
              <div class="colors" ref="gradientSlider"
                  @dblclick.stop="tapDblGradientSlider" :style="{backgroundImage:colorGradient}"
                  :title="gradientValue.colors.length<gradientSize?langs.tipadd:''">
                <div v-for="(item,index) in gradientValue.colors" :key="index" 
                    class="slider" :class="{'slider-selected':gradientSelected==index}" 
                    :style="{left:`calc( (100% - 24px ) * ${item.pos} / 100 )`,zIndex:gradientSelected==index?2:1}" 
                    @mousedown="tapGradientSiderDown(index)"
                    @dblclick.stop="tapDblSlider(index)"
                    :title="gradientValue.colors.length>2?langs.tipremove:''">
                  <div class="point" :style="{backgroundColor: `rgba(${item.rgba.r},${item.rgba.g},${item.rgba.b})`}">
                    <span :style="{color: `rgba(${item.rgba.r},${item.rgba.g},${item.rgba.b})`, filter: 'invert(100%)'}">{{ index+1 }}</span>
                  </div>
                </div>
              </div>
              <div class="deg">
                <div style="flex: 1;padding-right: 10px;">
                  <a-slider v-model:value="gradientValue.deg" :min="0" :max="360" />
                </div>
                <input style="width: 36px;" :value="gradientValue.deg" @input="onGradientDegChange($event)">
              </div>
            </div>
            <div class="preview" :style="{backgroundImage:colorGradient}"></div>
          </div>
          <!--色块-->
          <div class="color-board" ref="colorBoard" @mousedown="tapColorBoardDown">
            <div :style="`background-color: hsl(${colorHsv.h}, 100%, 50%);`">
              <div class="point" :style="pointStyle"></div>
            </div>
            <div class="board-white"></div>
            <div class="board-black"></div>
          </div>
          <!--滑动-->
          <div class="color-slider">
            <div style="flex: 1">
              <div class="hue" ref="hueSlider" @mousedown="tapHueSiderDown">
                <div class="slider" style="cursor: pointer;" :style="hueSliderStyle"></div>
              </div>
              <div class="alpha" ref="alphaSlider" @mousedown="tapAlphaSiderDown">
                <div class="slider" style="cursor: pointer;" :style="alphaSliderStyle"></div>
                <div :style="`background: linear-gradient(to right, rgba(0,0,0,0), ${colorRgbString});width: 100%;height: 100%`"></div>
              </div>
            </div>
            <div class="diamond">
              <div style="cursor: pointer;" :style="`background-color: ${colorRgbaString};width: 100%;height: 100%;box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .15), inset 0 0 4px rgba(0, 0, 0, .25);`"></div>
            </div>
          </div>
          <!--数值-->
          <div class="color-value">
            <div class="hex">
              <input :value="colorHex" spellcheck="false" @input="onValueChange('hex',$event)"><div>Hex</div>
            </div>
            <div class="rgba">
              <input :value="colorRgba.r" @input="onValueChange('r',$event)"><div>R</div>
            </div>
            <div class="rgba">
              <input :value="colorRgba.g" @input="onValueChange('g',$event)"><div>G</div>
            </div>
            <div class="rgba">
              <input :value="colorRgba.b" @input="onValueChange('b',$event)"><div>B</div>
            </div>
            <div class="rgba">
              <input :value="colorRgba.a" @input="onValueChange('a',$event)"><div>A</div>
            </div>
          </div>
          <!--常设颜色和最近使用颜色-->
          <div class="preset">
            <template v-for="(item,index) in colorPreset" :key="index" >
              <div v-if="item=='refcolor'" class="refcolor" :title="langs.refcolor" @click="tapRefColor">
                <svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M868.304 147.536a164.68 164.68 0 0 0-117.264-48.568c-44.272 0-85.872 17.224-117.128 48.504L499.2 282.208l-55.76-55.76a30.088 30.088 0 0 0-42.568 0 30.088 30.088 0 0 0 0 42.568l76.808 76.808c0.08 0.08 0.136 0.176 0.216 0.264l7.008 7-291.904 291.968a124.76 124.76 0 0 0-35.208 108.68l-45.96 45.984a72.904 72.904 0 0 0-21.52 51.888 72.776 72.776 0 0 0 21.488 51.888 72.944 72.944 0 0 0 51.952 21.544h0.024a72.696 72.696 0 0 0 51.832-21.496l45.736-45.672a124.72 124.72 0 0 0 20.76 1.784c32.72 0 64.56-12.84 88.608-36.864l291.936-291.952 7.016 7.016c0.112 0.112 0.24 0.184 0.36 0.296l76.72 76.712a30.048 30.048 0 0 0 42.568 0 30.088 30.088 0 0 0 0-42.568l-55.76-55.752 134.752-134.72c64.592-64.56 64.592-169.656 0-234.288z m-540.16 632.664c-16.744 16.712-40.736 22.84-63.376 16.76a30.048 30.048 0 0 0-30.616 3.512 63.552 63.552 0 0 0-3.08 2.504l-58.064 58.032a13.048 13.048 0 0 1-9.232 3.824h-0.024a13.224 13.224 0 0 1-9.344-22.544l56.08-56.104c0.392-0.344 4.288-4.608 5.2-5.944 0.408-0.576 2.144-3.568 2.576-4.512 0.504-1.064 1.624-4.32 1.768-4.864 0.416-1.552 0.904-5 0.92-5.16a30.088 30.088 0 0 0-1.96-14.08c-6.456-22.864-0.304-47.136 16.568-64l291.928-291.96 92.6 92.6-291.944 291.936z m497.592-440.96L690.976 473.968l-149.2-149.184 134.712-134.736c39.832-39.824 109.36-39.792 149.248 0.056 41.096 41.144 41.096 108.04 0 149.136z"></path></svg>
              </div>
              <div v-else class="item" :style="{background: item, marginLeft: index%10?'6px':'0px'}" 
                  @click="tapPreset(item)"></div>
            </template>
          </div>
          <!--按钮-->
          <div class="button">
            <div @click="tapClear">{{langs.clear}}</div>
            <div @click="tapCancel">{{langs.cancel}}</div>
            <div @click="tapConfirm" style="font-weight: bold;">{{langs.confirm}}</div>
          </div>
        </div>
      </template>
      <div class="vrcp-card vrcp-full" :style="cardStyles"></div>
    </a-popover>
  </div>
</template>


<script>
import { defineComponent } from 'vue';
import * as colorUtils from './vrColorUtils';

//基于antdv版本2或3的纯色和渐变色选择器（缓存最近选择颜色），支持vue2或vue3
export default defineComponent({
  name: "VrColorPicker",
  emits: ['update:modelValue','change'],
  props:{
    width: { //显示色块宽度，0为使用父元素的宽度
      type: Number,
      default: 0
    },
    height: { //显示色块高度，0为使用父元素的高度
      type: Number,
      default: 24
    },
    title:{ //弹出选择框的标题
      type: String,
      default: ""
    },
    trigger:{ //什么情况下弹出选择框
      type: String,
      default: "click" //hover/focus/click/contextmenu
    },
    placement:{ //弹出选择框位置
      type: String,
      default: "rightBottom" //top left right bottom topLeft topRight bottomLeft bottomRight leftTop leftBottom rightTop rightBottom
    },
    mode: { //颜色模式
      type: String,
      default: 'both', //pure, gradient, both
    },
    modelValue: { //颜色值，支持hex和gradient
      type: String,
      default: ''
    },
    hexAlphaReset: { //在点击选择色板和色调的颜色时，是否重设透明度为1
      type: Boolean,
      default: true,
    },
    gradientSize: { //gradient时允许的最多颜色点
      type: Number,
      default: 5
    },
    presetSize: { //显示预设常用颜色和选择颜色的最多数量，最好为11的倍数
      type: Number,
      default: 20
    },
    preset: { //预设常用颜色
      type: Array,
      default() {
        return [
          '#D0021B', '#F5A623', '#F8E71C', '#BD10E0', '#9013FE', '#4A90E2', '#50E3C2',
          '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF'
        ]
      }
    },
    popupContainer: { //弹出框的渲染父节点，默认渲染到 body 上
      type: Function,
      default: ()=>{
        return document.body;
      }
    },
    langs: { //语言定义
      type: Object,
      default: ()=>{
        return {
          pure: "纯色",
          gradient: "渐变色",
          clear: "清除",
          cancel: "取消",
          confirm: "确定",
          tipadd: "双击新增",
          tipremove: "双击删除",
          refcolor: "拾色中按Esc可退出",
        }
      }
    },
  },
  data(){
    return{
      popoverVisible: false,
      menuCode: "gradient", //默认把弹出框的位置留够，解决popover箭头不对的问题
      colorHex: "",
      colorGradient: "",
      colorHsv: {h:0,s:0,v:0},
      colorRgba: {r:0,g:0,b:0, a:1},
      colorCache: [],
      gradientValue: {
        deg: 0,
        colors: []
      },
      gradientSelected: 0,
      pointStyle: {top:'50%',left:'50%'},
      hueSliderStyle: {left: '0px'},
      alphaSliderStyle: {left: 'calc(100% - 6px)'},
      manualClose: false,
    }
  },
  computed:{
    menus(){
      if(this.mode=='both') return ['pure','gradient'];
      return [];
    },
    cardStyles(){
      if(this.menuCode=='pure'){
        return {backgroundColor:this.colorHex};
      }
      if(this.menuCode=='gradient'){
        return {backgroundImage:colorUtils.toGradient(this.gradientValue)};
      }
      return {};
    },
    colorRgbString(){
      return `rgba(${this.colorRgba.r},${this.colorRgba.g},${this.colorRgba.b})`;
    },
    colorRgbaString(){
      return `rgba(${this.colorRgba.r},${this.colorRgba.g},${this.colorRgba.b},${this.colorRgba.a})`;
    },
    colorPreset(){
      const p = [];
      if('EyeDropper' in window){
        p.push('refcolor')
      }
      p.push(...this.preset);
      this.colorCache.forEach((color)=>{
        if(this.menuCode=='pure'){
          if(colorUtils.isHex(color)) p.push(color);
        }else{
          p.push(color);
        }
      })
      return p.slice(0,this.presetSize);
    }
  },
  watch:{
    modelValue:{
      handler(val) {
        this.$nextTick(()=>{
          this.set(val || "");
        });
      },
      immediate: true
    },
    popoverVisible:{
      handler(val) {
        if(val){
          //打开
          this.manualClose = false;
        }else if(!this.manualClose){
          //关闭时，且非人工
          this.tapCancel();
        }
      },
      immediate: true
    },
    colorRgba:{
      handler(val) {
        this.colorHex = colorUtils.rgba2hex8(val);
        if(this.menuCode=='gradient'){
          const color = this.gradientValue.colors[this.gradientSelected];
          if(color) Object.assign( color.rgba, val);
        }
      },
      deep: true,
      immediate: true,
    },
    gradientValue:{
      handler(val) {
        this.colorGradient = colorUtils.toGradient(val);
      },
      deep: true,
      immediate: true,
    },
  },
  mounted(){
    this.colorCache = colorUtils.cache.get();
    this.menuCode = this.mode=='both'?'pure':this.mode;
    if(!['pure','gradient'].includes(this.menuCode)) this.menuCode = 'pure';
  },
  methods:{
    set(val){
      if(colorUtils.isHex(val)){
        this.menuCode = "pure";
        this.setHex(val);
        this.gradientValue = colorUtils.parseGradient("",val);
      }else if(colorUtils.isGradient(val)){
        this.menuCode = "gradient";
        this.gradientValue = colorUtils.parseGradient(val);
        this.setHex(colorUtils.rgba2hex8(this.gradientValue.colors[0].rgba));
      }else{
        this.set("#FFFFFF");
      }
      this.gradientSelected = 0;
    },
    setHex(hex){
      this.colorHex = hex || "";
      Object.assign(this.colorRgba, colorUtils.hex82rgba(hex));
      Object.assign(this.colorHsv, colorUtils.rgb2hsv(this.colorRgba));
      this.pointStyle = {top: (100 - this.colorHsv.v * 100)+'%',left: (this.colorHsv.s * 100)+'%'};
      this.hueSliderStyle = {left: (this.colorHsv.h / 360 * 100)+'%'};
      const a = this.colorRgba.a*100;
      this.alphaSliderStyle = {left: a>97?`calc(${a}% - 6px)`:(a+'%')};
    },
    //颜色板中取色
    tapColorBoardDown(event){
      this.generateColorBoarValue(event);
      window.addEventListener('mousemove', this.generateColorBoarValue)
      window.addEventListener('mouseup', this.onColorBoardUp)
    },
    onColorBoardUp(){
      window.removeEventListener('mousemove', this.generateColorBoarValue)
      window.removeEventListener('mouseup', this.onColorBoardUp)
    },
    generateColorBoarValue(event){
      const w = this.$refs.colorBoard.clientWidth;
      const h = this.$refs.colorBoard.clientHeight;
      let x = event.pageX - this.$refs.colorBoard.getBoundingClientRect().left;
      let y = event.pageY - this.$refs.colorBoard.getBoundingClientRect().top;
      x = (x < w && x > 0) ? x : (x > w ? w : 0);
      y = (y < h && y > 0) ? y : (y > h ? h : 0);
      // 计算饱和度和亮度
      this.colorHsv.s = Math.floor((x / w) * 100 + 0.5) / 100;
      this.colorHsv.v = Math.floor((1 - y / h) * 100 + 0.5) / 100;
      // hsv转化为rgb
      Object.assign(this.colorRgba, colorUtils.hsv2rgb(this.colorHsv));
      // 移动背景板圆圈
      this.pointStyle = {top: `${y}px`,left: `${x}px`};
      if(this.hexAlphaReset){
        this.colorRgba.a = 1;
        this.alphaSliderStyle = {left: 'calc(100% - 6px)'};
      }
    },
    //色调滑动条中取色
    tapHueSiderDown(event){
      this.generateHueSiderValue(event);
      window.addEventListener('mousemove', this.generateHueSiderValue)
      window.addEventListener('mouseup', this.onHueSiderUp)
    },
    onHueSiderUp(){
      window.removeEventListener('mousemove', this.generateHueSiderValue)
      window.removeEventListener('mouseup', this.onHueSiderUp)
    },
    generateHueSiderValue(event) {
      const w = this.$refs.hueSlider.clientWidth;
      let x = event.pageX - this.$refs.hueSlider.getBoundingClientRect().left;
      x = (x < w && x > 0) ? x : (x > w ? w : 0);
      // 计算色调
      this.colorHsv.h = Math.floor((x / w) * 360 + 0.5);
      // hsv转化为rgb
      Object.assign(this.colorRgba, colorUtils.hsv2rgb(this.colorHsv));
      // 移动滑块，slider宽度为6
      this.hueSliderStyle = {left: `${x >= (w - 6) ? (w - 6) : x}px`};
      if(this.hexAlphaReset){
        this.colorRgba.a = 1;
        this.alphaSliderStyle = {left: 'calc(100% - 6px)'};
      }
    },
    //透明度滑动条中取色
    tapAlphaSiderDown(event){
      this.generateAlphaSiderValue(event);
      window.addEventListener('mousemove', this.generateAlphaSiderValue)
      window.addEventListener('mouseup', this.onAlphaSiderUp)
    },
    onAlphaSiderUp(){
      window.removeEventListener('mousemove', this.generateAlphaSiderValue)
      window.removeEventListener('mouseup', this.onAlphaSiderUp)
    },
    generateAlphaSiderValue(event){
      const w = this.$refs.alphaSlider.clientWidth;
      let x = event.pageX - this.$refs.alphaSlider.getBoundingClientRect().left;
      x = (x < w && x > 0) ? x : (x > w ? w : 0);
      // 计算透明度
      this.colorRgba.a = Math.floor((x / w) * 100 + 0.5) / 100;
      // 移动滑块，slider宽度为6
      this.alphaSliderStyle = {left: `${x >= (w - 6) ? (w - 6) : x}px`};
    },
    //处理输入数值
    onValueChange(type,event){
      const val = event.target.value;
      if(type=='hex'){
        Object.assign(this.colorRgba, colorUtils.hex82rgba(val));
        Object.assign(this.colorHsv, colorUtils.rgb2hsv(this.colorRgba));
      }else if(['r','g','b','a'].includes(type)){
        let dval = 255;
        if(/^\d+$/.test(val) && parseInt(val)>=0  && parseInt(val)<=255){
          dval = parseInt(val);
        }
        this.colorRgba[type] = dval;
        Object.assign(this.colorHsv, colorUtils.rgb2hsv(this.colorRgba));
      }
    },
    //处理渐近色
    tapGradientSiderDown(index){
      this.gradientSelected = index;
      this.setHex(colorUtils.rgba2hex8(this.gradientValue.colors[index].rgba));
      //this.generateGradientSiderValue(event);
      window.addEventListener('mousemove', this.generateGradientSiderValue)
      window.addEventListener('mouseup', this.onGradientSiderUp)
    },
    onGradientSiderUp(){
      window.removeEventListener('mousemove', this.generateGradientSiderValue)
      window.removeEventListener('mouseup', this.onGradientSiderUp)
    },
    generateGradientSiderValue(event){
      const color = this.gradientValue.colors[this.gradientSelected];
      if(!color) return;
      color.pos = this.getGradientSiderPos(event);
    },
    getGradientSiderPos(event){
      let w = this.$refs.gradientSlider.clientWidth - 24;
      let x = event.pageX - this.$refs.gradientSlider.getBoundingClientRect().left;
      x = (x < w && x > 0) ? x : (x > w ? w : 0);
      // 计算位置，slider宽度为24
      return Math.floor((x / w) * 100 + 0.5);
    },
    tapDblGradientSlider(event){
      if(this.gradientValue.colors.length>=this.gradientSize) return;
      //找到点击的位置
      const pos = this.getGradientSiderPos(event);
      let idx = 0;
      let rgba = {};
      for(const color of this.gradientValue.colors){
        Object.assign(rgba,color.rgba);
        if(pos<color.pos) break;
        idx++;
      }
      if(idx>=this.gradientValue.colors.length){
        this.gradientValue.colors.push({ pos, rgba })
        this.gradientSelected = idx;
      }else{
        this.gradientValue.colors.splice(idx,0,{ pos, rgba })
        this.gradientSelected = idx;
      }
    },
    tapDblSlider(index){
      if(this.gradientValue.colors.length<3) return;
      if(this.gradientValue.colors[index]){
        this.gradientValue.colors.splice(index,1);
        this.gradientSelected = index-1;
        if(this.gradientSelected<0) this.gradientSelected=0;
      }
    },
    onGradientDegChange(event){
      const val = event.target.value;
      if(/^\d+$/.test(val) && parseInt(val)>=0  && parseInt(val)<=360){
        this.gradientValue.deg = parseInt(val);
      }
    },
    //常用色
    tapPreset(val){
      if(this.menuCode=='pure'){
        if(colorUtils.isHex(val)) this.setHex(val);
      }else if(this.menuCode=='gradient'){
        if(colorUtils.isHex(val)){
          this.gradientValue.colors[this.gradientSelected].rgba = colorUtils.hex82rgba(val);
          this.setHex(val);
        }else{
          this.gradientValue = colorUtils.parseGradient(val);
          this.gradientSelected = 0;
          this.setHex(colorUtils.rgba2hex8(this.gradientValue.colors[0].rgba));
        }
      }
    },
    async tapRefColor(){
      if('EyeDropper' in window){
        new window.EyeDropper().open().then(res=>{
          if(colorUtils.isHex(res && res.sRGBHex)) this.tapPreset(res.sRGBHex);
        });
      }
    },
    //按钮
    tapClear(){
      this.manualClose = true;
      this.popoverVisible = false;
      this.set("");
      this.$emit('update:modelValue',"");
      this.$emit('change');
    },
    tapCancel(){
      this.manualClose = true;
      this.popoverVisible = false;
      this.set(this.modelValue);
    },
    tapConfirm(){
      this.manualClose = true;
      this.popoverVisible = false;
      let dcolor = "";
      if(this.menuCode=='gradient'){
        dcolor = colorUtils.toGradient(this.gradientValue);
      }else{
        dcolor = this.colorHex;
      }
      this.$emit('update:modelValue',dcolor);
      this.$emit('change');
      //缓存
      if(!this.colorPreset.includes(dcolor)){
        this.colorCache.unshift(dcolor);
        this.colorCache = colorUtils.cache.set(this.colorCache);
      }
    }
  }
})
</script>

<style scoped>
.vrcp-full {
  width: 100%;
  height: 100%;
}
.vrcp-container {
  width: 254px;
  user-select: none;
}
.vrcp-container input {
  font-size: 12px;
  box-sizing: border-box;
  width: 100%;
  height: 24px;
  padding: 0;
  margin: 0;
  outline: none;
  text-align: center;
  border-radius: 3px;
  border: 1px solid #cccccc;
}
.vrcp-container .menus {
  display: flex;
  border-bottom: 1px solid #e8e8e8;
}
.vrcp-container .menus .menu {
  position: relative;
  padding: 3px 6px;
  margin-right: 20px;
  cursor: pointer;
}
.vrcp-container .menus .menu::after {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  content: "";
  height: 2px;
  overflow: hidden;
  display: block;
  background: #004f98;
  transform: scaleX(0);
  transition: all 0.3s;
}
.vrcp-container .menus .menu:hover::after {
  height: 1px;
  transform: scaleX(1);
}
.vrcp-container .menus .menu-selected::after {
  transform: scaleX(1);
}
.vrcp-container .gradient {
  width: 100%;
  margin-top: 10px;
  display: flex;
}
.vrcp-container .gradient .setting {
  flex: 1;
  padding-right: 10px;
}
.vrcp-container .gradient .setting .colors {
  width: 100%;
  height: 12px;
  position: relative;
  border-radius: 3px;
  margin-top: 6px;
}
.vrcp-container .gradient .setting .colors .slider {
  position: absolute;
  top: -6px;
  width: 24px;
  height: 24px;
  border: 1px solid #ffffff;
  border-radius: 3px;
  opacity: 0.8;
  box-shadow: 0 0 2px rgba(0,0,0,0.6);
  box-sizing: border-box;
  cursor: pointer;
}
.vrcp-container .gradient .setting .colors .slider .point {
  box-sizing: border-box;
  width: 22px;
  height: 22px;
  border: 1px solid #ffffff;
  border-radius: 3px;
  opacity: 0.8;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.vrcp-container .gradient .setting .colors .slider .point span {
  font-size: 6px;
  pointer-events: none;
}
.vrcp-container .gradient .setting .colors .slider-selected {
  border: 1px solid #666666;
}
.vrcp-container .gradient .setting .deg {
  margin-top: 8px;
  width: 100%;
  height: 24px;
  display: flex;
  align-items: center;
}
.vrcp-container .gradient .preview {
  width: 50px;
  height: 50px;
}
.vrcp-container .color-board {
  width: 100%;
  height: 100px;
  margin-top: 10px;
  cursor: pointer;
  position: relative;
  margin-bottom: 10px;
  box-shadow: 1px 1px 1px rgba(0,0,0,0.1);
}
.vrcp-container .color-board div {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
.vrcp-container .color-board .point {
  box-sizing: border-box;
  width: 9px;
  height: 9px;
  background-color: transparent;
  border: 2px solid #999;
  border-radius: 50%;
  transform: translate(-50%,-50%);
  position: absolute;
  z-index: 9;
}
.vrcp-container .color-board .board-white {
  background: linear-gradient(to right,white,#ffffff00);
}
.vrcp-container .color-board .board-black {
  background: linear-gradient(to top,black,#ffffff00);
}
.vrcp-container .color-slider {
  width: 100%;
  display: flex;
  margin-top: 10px;
}
.vrcp-container .color-slider .hue {
  position: relative;
  margin-bottom: 6px;
  height: 10px;
  background: linear-gradient(90deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red);
  box-shadow: 1px 1px 1px rgba(0,0,0,0.1);
}
.vrcp-container .color-slider .alpha {
  position: relative;
  height: 10px;
  box-shadow: 1px 1px 1px rgba(0,0,0,0.1);
  background: #fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAWElEQVRIiWM8fubkfwYygKWJOSM5+mCAhRLNoxaPWjxq8ajFoxbTyeL/DAfJ0Xjs3Cl7Siwmu4Yht1aDgZEYx6MWj1o8avGoxaMWD3qLya5X//4nqx6HAQC7RBGFzolqTAAAAABJRU5ErkJggg==");
  background-size: 10px 10px;
}
.vrcp-container .color-slider .slider {
  position: absolute;
  box-shadow: 0 0 2px rgba(0,0,0,0.6);
  box-sizing: border-box;
  width: 6px;
  height: 100%;
  background-color: #fff;
}
.vrcp-container .color-slider .diamond {
  position: relative;
  margin-left: 5px;
  width: 26px;
  height: 26px;
  border-radius: 3px;
  overflow: hidden;
  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAWElEQVRIiWM8fubkfwYygKWJOSM5+mCAhRLNoxaPWjxq8ajFoxbTyeL/DAfJ0Xjs3Cl7Siwmu4Yht1aDgZEYx6MWj1o8avGoxaMWD3qLya5X//4nqx6HAQC7RBGFzolqTAAAAABJRU5ErkJggg==");
  background-size: 10px 10px;
}
.vrcp-container .color-value {
  width: 100%;
  display: flex;
  margin-top: 10px;
}
.vrcp-container .color-value div {
  text-align: center;
}
.vrcp-container .color-value div div {
  font-size: 12px;
}
.vrcp-container .color-value .hex {
  flex: 1;
}
.vrcp-container .color-value .rgba {
  width: 36px;
  margin-left: 6px;
}
.vrcp-container .preset {
  width: 100%;
  margin-top: 5px;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
}
.vrcp-container .preset .item {
  width: 20px;
  height: 20px;
  margin-bottom: 6px;
  border: 1px solid #ccc;
  border-radius: 6px;
  cursor: pointer;
}
.vrcp-container .preset .item:hover {
  border: 1px solid blue;
}
.vrcp-container .preset .refcolor {
  width: 20px;
  height: 20px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.vrcp-container .preset .refcolor .icon {
  width: 20px;
  height: 20px;
  fill: #004f98;
  transform: rotate(0deg);
  transition: all 0.2s;
}
.vrcp-container .preset .refcolor:hover .icon {
  transform: rotate(90deg);
}
.vrcp-container .button {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
}
.vrcp-container .button div {
  width: 28%;
  height: 28px;
  line-height: 28px;
  text-align: center;
  cursor: pointer;
  border: 1px solid #efefef;
  border-radius: 6px;
}
.vrcp-card {
  cursor: pointer;
  border: 1px solid #e8e8e8;
  border-radius: 6px;
  overflow: hidden;
}
</style>
