<template> 
 | 
  <el-color-picker 
 | 
    v-model="theme" 
 | 
    :predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]" 
 | 
    class="theme-picker" 
 | 
    popper-class="theme-picker-dropdown" 
 | 
  /> 
 | 
</template> 
 | 
  
 | 
<script> 
 | 
const version = require('element-ui/package.json').version // element-ui version from node_modules 
 | 
const ORIGINAL_THEME = '#409EFF' // default color 
 | 
  
 | 
export default { 
 | 
  data() { 
 | 
    return { 
 | 
      chalk: '', // content of theme-chalk css 
 | 
      theme: '' 
 | 
    } 
 | 
  }, 
 | 
  computed: { 
 | 
    defaultTheme() { 
 | 
      return this.$store.state.settings.theme 
 | 
    } 
 | 
  }, 
 | 
  watch: { 
 | 
    defaultTheme: { 
 | 
      handler: function(val, oldVal) { 
 | 
        this.theme = val 
 | 
      }, 
 | 
      immediate: true 
 | 
    }, 
 | 
    async theme(val) { 
 | 
      await this.setTheme(val) 
 | 
    } 
 | 
  }, 
 | 
  created() { 
 | 
    if(this.defaultTheme !== ORIGINAL_THEME) { 
 | 
      this.setTheme(this.defaultTheme) 
 | 
    } 
 | 
  }, 
 | 
  
 | 
  methods: { 
 | 
    async setTheme(val) { 
 | 
      const oldVal = this.chalk ? this.theme : ORIGINAL_THEME 
 | 
      if (typeof val !== 'string') return 
 | 
      const themeCluster = this.getThemeCluster(val.replace('#', '')) 
 | 
      const originalCluster = this.getThemeCluster(oldVal.replace('#', '')) 
 | 
  
 | 
      const getHandler = (variable, id) => { 
 | 
        return () => { 
 | 
          const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', '')) 
 | 
          const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster) 
 | 
  
 | 
          let styleTag = document.getElementById(id) 
 | 
          if (!styleTag) { 
 | 
            styleTag = document.createElement('style') 
 | 
            styleTag.setAttribute('id', id) 
 | 
            document.head.appendChild(styleTag) 
 | 
          } 
 | 
          styleTag.innerText = newStyle 
 | 
        } 
 | 
      } 
 | 
  
 | 
      if (!this.chalk) { 
 | 
        const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css` 
 | 
        await this.getCSSString(url, 'chalk') 
 | 
      } 
 | 
  
 | 
      const chalkHandler = getHandler('chalk', 'chalk-style') 
 | 
  
 | 
      chalkHandler() 
 | 
  
 | 
      const styles = [].slice.call(document.querySelectorAll('style')) 
 | 
        .filter(style => { 
 | 
          const text = style.innerText 
 | 
          return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text) 
 | 
        }) 
 | 
      styles.forEach(style => { 
 | 
        const { innerText } = style 
 | 
        if (typeof innerText !== 'string') return 
 | 
        style.innerText = this.updateStyle(innerText, originalCluster, themeCluster) 
 | 
      }) 
 | 
  
 | 
      this.$emit('change', val) 
 | 
    }, 
 | 
  
 | 
    updateStyle(style, oldCluster, newCluster) { 
 | 
      let newStyle = style 
 | 
      oldCluster.forEach((color, index) => { 
 | 
        newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index]) 
 | 
      }) 
 | 
      return newStyle 
 | 
    }, 
 | 
  
 | 
    getCSSString(url, variable) { 
 | 
      return new Promise(resolve => { 
 | 
        const xhr = new XMLHttpRequest() 
 | 
        xhr.onreadystatechange = () => { 
 | 
          if (xhr.readyState === 4 && xhr.status === 200) { 
 | 
            this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '') 
 | 
            resolve() 
 | 
          } 
 | 
        } 
 | 
        xhr.open('GET', url) 
 | 
        xhr.send() 
 | 
      }) 
 | 
    }, 
 | 
  
 | 
    getThemeCluster(theme) { 
 | 
      const tintColor = (color, tint) => { 
 | 
        let red = parseInt(color.slice(0, 2), 16) 
 | 
        let green = parseInt(color.slice(2, 4), 16) 
 | 
        let blue = parseInt(color.slice(4, 6), 16) 
 | 
  
 | 
        if (tint === 0) { // when primary color is in its rgb space 
 | 
          return [red, green, blue].join(',') 
 | 
        } else { 
 | 
          red += Math.round(tint * (255 - red)) 
 | 
          green += Math.round(tint * (255 - green)) 
 | 
          blue += Math.round(tint * (255 - blue)) 
 | 
  
 | 
          red = red.toString(16) 
 | 
          green = green.toString(16) 
 | 
          blue = blue.toString(16) 
 | 
  
 | 
          return `#${red}${green}${blue}` 
 | 
        } 
 | 
      } 
 | 
  
 | 
      const shadeColor = (color, shade) => { 
 | 
        let red = parseInt(color.slice(0, 2), 16) 
 | 
        let green = parseInt(color.slice(2, 4), 16) 
 | 
        let blue = parseInt(color.slice(4, 6), 16) 
 | 
  
 | 
        red = Math.round((1 - shade) * red) 
 | 
        green = Math.round((1 - shade) * green) 
 | 
        blue = Math.round((1 - shade) * blue) 
 | 
  
 | 
        red = red.toString(16) 
 | 
        green = green.toString(16) 
 | 
        blue = blue.toString(16) 
 | 
  
 | 
        return `#${red}${green}${blue}` 
 | 
      } 
 | 
  
 | 
      const clusters = [theme] 
 | 
      for (let i = 0; i <= 9; i++) { 
 | 
        clusters.push(tintColor(theme, Number((i / 10).toFixed(2)))) 
 | 
      } 
 | 
      clusters.push(shadeColor(theme, 0.1)) 
 | 
      return clusters 
 | 
    } 
 | 
  } 
 | 
} 
 | 
</script> 
 | 
  
 | 
<style> 
 | 
.theme-message, 
 | 
.theme-picker-dropdown { 
 | 
  z-index: 99999 !important; 
 | 
} 
 | 
  
 | 
.theme-picker .el-color-picker__trigger { 
 | 
  height: 26px !important; 
 | 
  width: 26px !important; 
 | 
  padding: 2px; 
 | 
} 
 | 
  
 | 
.theme-picker-dropdown .el-color-dropdown__link-btn { 
 | 
  display: none; 
 | 
} 
 | 
</style> 
 |