mirror of https://github.com/ElemeFE/element
Add ColorPicker component.
parent
080a996f3f
commit
42bd58d9fe
|
@ -59,5 +59,6 @@
|
|||
"carousel-item": "./packages/carousel-item/index.js",
|
||||
"collapse": "./packages/collapse/index.js",
|
||||
"collapse-item": "./packages/collapse-item/index.js",
|
||||
"cascader": "./packages/cascader/index.js"
|
||||
"cascader": "./packages/cascader/index.js",
|
||||
"color-picker": "./packages/color-picker/index.js"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
color1: '#ff0',
|
||||
color2: null,
|
||||
color3: 'rgba(128, 33, 22, 0.8)',
|
||||
color4: null
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.demo-box.demo-color-picker .source {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.demo-box.demo-color-picker .block {
|
||||
padding: 30px 24px;
|
||||
overflow: hidden;
|
||||
border-bottom: solid 1px #EFF2F6;
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.demo-box.demo-color-picker .demonstration {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
width: 25%;
|
||||
color: #8492a6;
|
||||
line-height: 44px;
|
||||
}
|
||||
</style>
|
||||
|
||||
## ColorPicker
|
||||
|
||||
ColorPicker is a color picker component that is used to solve the need to select a color in certain scenes.
|
||||
|
||||
### Color
|
||||
|
||||
:::demo ColorPicker usage is similar to DatePicker and requires v-model to bind a variable in a Vue instance. The bind variable's data type needs to be a string.
|
||||
```html
|
||||
<div class="block">
|
||||
<span class="demonstration">Default value</span>
|
||||
<el-color-picker v-model="color1"></el-color-picker>
|
||||
</div>
|
||||
<div class="block">
|
||||
<span class="demonstration">Empty</span>
|
||||
<el-color-picker v-model="color2"></el-color-picker>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
color1: '#ff0',
|
||||
color2: null
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Color and alpha
|
||||
|
||||
:::demo ColorPicker supports normal colors, also supports alpha-channel colors, through the show-alpha attribute to control whether to support the use of transparency.
|
||||
```html
|
||||
<div class="block">
|
||||
<span class="demonstration">Default value</span>
|
||||
<el-color-picker v-model="color3" show-alpha></el-color-picker>
|
||||
</div>
|
||||
<div class="block">
|
||||
<span class="demonstration">Empty</span>
|
||||
<el-color-picker v-model="color4" show-alpha></el-color-picker>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
color3: 'rgba(128, 33, 22, 0.8)',
|
||||
color4: null
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Attributes
|
||||
| Attribute | Description | Type | Accepted Values | Default |
|
||||
|---------- |-------- |---------- |------------- |-------- |
|
||||
| show-alpha | Whether to display the alpha slider. | Boolean | — | false |
|
||||
| color-format | Write the v-model's color format. In the case of show-alpha is true, the default value is rgb, otherwise hex. | string | hsl, hsv, hex, rgb | hex |
|
|
@ -0,0 +1,100 @@
|
|||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
color1: '#ff0',
|
||||
color2: null,
|
||||
color3: 'rgba(128, 33, 22, 0.8)',
|
||||
color4: null
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.demo-box.demo-color-picker .source {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.demo-box.demo-color-picker .block {
|
||||
padding: 30px 24px;
|
||||
overflow: hidden;
|
||||
border-bottom: solid 1px #EFF2F6;
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.demo-box.demo-color-picker .demonstration {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
width: 25%;
|
||||
color: #8492a6;
|
||||
line-height: 44px;
|
||||
}
|
||||
</style>
|
||||
|
||||
## ColorPicker
|
||||
|
||||
ColorPicker 是一个颜色选择器,该组件是用来解决某些场景下需要选择颜色的需求。
|
||||
|
||||
### 选择颜色
|
||||
|
||||
:::demo ColorPicker 用法与 DatePicker 类似,需要使用 v-model 来与 Vue 实例中的一个变量进行双向绑定,绑定的变量需要是字符串类型。
|
||||
```html
|
||||
<div class="block">
|
||||
<span class="demonstration">有默认值</span>
|
||||
<el-color-picker v-model="color1"></el-color-picker>
|
||||
</div>
|
||||
<div class="block">
|
||||
<span class="demonstration">无默认值</span>
|
||||
<el-color-picker v-model="color2"></el-color-picker>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
color1: '#ff0',
|
||||
color2: null
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### 选择颜色和透明度
|
||||
|
||||
:::demo ColorPicker 支持普通颜色,也支持带 Alpha 通道的颜色,通过 show-alpha 属性即可控制是否支持透明度的使用。
|
||||
```html
|
||||
<div class="block">
|
||||
<span class="demonstration">有默认值</span>
|
||||
<el-color-picker v-model="color3" show-alpha></el-color-picker>
|
||||
</div>
|
||||
<div class="block">
|
||||
<span class="demonstration">无默认值</span>
|
||||
<el-color-picker v-model="color4" show-alpha></el-color-picker>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
color3: 'rgba(128, 33, 22, 0.8)',
|
||||
color4: null
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Attributes
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
|---------- |-------- |---------- |------------- |-------- |
|
||||
| show-alpha | 是否显示透明度 Slider。 | Boolean | — | false |
|
||||
| color-format | 写入 v-model 的颜色的格式。在 show-alpha 为 true 的情况下,默认值为 rgb,否则为 hex。 | string | hsl, hsv, hex, rgb | hex |
|
|
@ -219,6 +219,10 @@
|
|||
{
|
||||
"path": "/collapse",
|
||||
"title": "Collapse 折叠面板"
|
||||
},
|
||||
{
|
||||
"path": "/color-picker",
|
||||
"title": "ColorPicker"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -445,6 +449,10 @@
|
|||
{
|
||||
"path": "/collapse",
|
||||
"title": "Collapse"
|
||||
},
|
||||
{
|
||||
"path": "/color-picker",
|
||||
"title": "ColorPicker"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-button>Test</el-button>
|
||||
<el-button @click="value = '#fff'">Change Value</el-button>
|
||||
<div>Value: {{ value }}</div>
|
||||
<el-color-picker v-model="value"></el-color-picker>
|
||||
|
||||
<div>Value2: {{ value2 }}</div>
|
||||
<el-color-picker v-model="value2" show-alpha></el-color-picker>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -13,7 +18,10 @@
|
|||
},
|
||||
|
||||
data() {
|
||||
return {};
|
||||
return {
|
||||
value: '#bfcbd9',
|
||||
value2: null
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
var cooking = require('cooking');
|
||||
var gen = require('../../build/gen-single-config');
|
||||
|
||||
cooking.set(gen(__dirname, 'ElColorPicker'));
|
||||
|
||||
module.exports = cooking.resolve();
|
|
@ -0,0 +1,8 @@
|
|||
import ColorPicker from './src/main';
|
||||
|
||||
/* istanbul ignore next */
|
||||
ColorPicker.install = function(Vue) {
|
||||
Vue.component(ColorPicker.name, ColorPicker);
|
||||
};
|
||||
|
||||
export default ColorPicker;
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "element-color-picker",
|
||||
"version": "0.0.0",
|
||||
"description": "A color-picker component for Vue.js.",
|
||||
"keywords": [
|
||||
"element",
|
||||
"vue",
|
||||
"component"
|
||||
],
|
||||
"main": "./lib/index.js",
|
||||
"repository": "https://github.com/ElemeFE/element/tree/master/packages/color-picker",
|
||||
"author": "elemefe",
|
||||
"license": "MIT",
|
||||
"dependencies": {}
|
||||
}
|
|
@ -0,0 +1,289 @@
|
|||
const hsv2hsl = function(hue, sat, val) {
|
||||
return [
|
||||
hue,
|
||||
(sat * val / ((hue = (2 - sat) * val) < 1 ? hue : 2 - hue)) || 0,
|
||||
hue / 2
|
||||
];
|
||||
};
|
||||
|
||||
// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
|
||||
// <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
|
||||
const isOnePointZero = function(n) {
|
||||
return typeof n === 'string' && n.indexOf('.') !== -1 && parseFloat(n) === 1;
|
||||
};
|
||||
|
||||
const isPercentage = function(n) {
|
||||
return typeof n === 'string' && n.indexOf('%') !== -1;
|
||||
};
|
||||
|
||||
// Take input from [0, n] and return it as [0, 1]
|
||||
const bound01 = function(value, max) {
|
||||
if (isOnePointZero(value)) value = '100%';
|
||||
|
||||
const processPercent = isPercentage(value);
|
||||
value = Math.min(max, Math.max(0, parseFloat(value)));
|
||||
|
||||
// Automatically convert percentage into number
|
||||
if (processPercent) {
|
||||
value = parseInt(value * max, 10) / 100;
|
||||
}
|
||||
|
||||
// Handle floating point rounding errors
|
||||
if ((Math.abs(value - max) < 0.000001)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Convert into [0, 1] range if it isn't already
|
||||
return (value % max) / parseFloat(max);
|
||||
};
|
||||
|
||||
const INT_HEX_MAP = { 10: 'A', 11: 'B', 12: 'C', 13: 'D', 14: 'E', 15: 'F' };
|
||||
|
||||
const toHex = function({ r, g, b }) {
|
||||
const hexOne = function(value) {
|
||||
value = Math.min(Math.round(value), 255);
|
||||
const high = Math.floor(value / 16);
|
||||
const low = value % 16;
|
||||
return '' + (INT_HEX_MAP[high] || high) + (INT_HEX_MAP[low] || low);
|
||||
};
|
||||
|
||||
if (isNaN(r) || isNaN(g) || isNaN(b)) return '';
|
||||
|
||||
return '#' + hexOne(r) + hexOne(g) + hexOne(b);
|
||||
};
|
||||
|
||||
const HEX_INT_MAP = { A: 10, B: 11, C: 12, D: 13, E: 14, F: 15 };
|
||||
|
||||
const parseHexChannel = function(hex) {
|
||||
if (hex.length === 2) {
|
||||
return (HEX_INT_MAP[hex[0].toUpperCase()] || +hex[0]) * 16 + (HEX_INT_MAP[hex[1].toUpperCase()] || +hex[1]);
|
||||
}
|
||||
|
||||
return HEX_INT_MAP[hex[1].toUpperCase()] || +hex[1];
|
||||
};
|
||||
|
||||
const hsl2hsv = function(hue, sat, light) {
|
||||
sat *= light < 0.5 ? light : 1 - light;
|
||||
|
||||
return [ // [hue, saturation, value]
|
||||
// Range should be between 0 - 1
|
||||
hue, // Hue stays the same
|
||||
2 * sat / (light + sat), // Saturation
|
||||
light + sat // Value
|
||||
];
|
||||
};
|
||||
|
||||
// `rgbToHsv`
|
||||
// Converts an RGB color value to HSV
|
||||
// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
|
||||
// *Returns:* { h, s, v } in [0,1]
|
||||
const rgb2hsv = function(r, g, b) {
|
||||
r = bound01(r, 255);
|
||||
g = bound01(g, 255);
|
||||
b = bound01(b, 255);
|
||||
|
||||
const max = Math.max(r, g, b);
|
||||
const min = Math.min(r, g, b);
|
||||
let h, s;
|
||||
let v = max;
|
||||
|
||||
const d = max - min;
|
||||
s = max === 0 ? 0 : d / max;
|
||||
|
||||
if (max === min) {
|
||||
h = 0; // achromatic
|
||||
} else {
|
||||
switch (max) {
|
||||
case r:
|
||||
h = (g - b) / d + (g < b ? 6 : 0);
|
||||
break;
|
||||
case g:
|
||||
h = (b - r) / d + 2;
|
||||
break;
|
||||
case b:
|
||||
h = (r - g) / d + 4;
|
||||
break;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
|
||||
return { h: Math.round(h * 360), s: Math.round(s * 100), v: Math.round(v * 100) };
|
||||
};
|
||||
|
||||
// `hsvToRgb`
|
||||
// Converts an HSV color value to RGB.
|
||||
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
|
||||
// *Returns:* { r, g, b } in the set [0, 255]
|
||||
const hsv2rgb = function(h, s, v) {
|
||||
h = bound01(h, 360) * 6;
|
||||
s = bound01(s, 100);
|
||||
v = bound01(v, 100);
|
||||
|
||||
const i = Math.floor(h);
|
||||
const f = h - i;
|
||||
const p = v * (1 - s);
|
||||
const q = v * (1 - f * s);
|
||||
const t = v * (1 - (1 - f) * s);
|
||||
const mod = i % 6;
|
||||
const r = [v, q, p, p, t, v][mod];
|
||||
const g = [t, v, v, q, p, p][mod];
|
||||
const b = [p, p, t, v, v, q][mod];
|
||||
|
||||
return {
|
||||
r: Math.round(r * 255),
|
||||
g: Math.round(g * 255),
|
||||
b: Math.round(b * 255)
|
||||
};
|
||||
};
|
||||
|
||||
export default class Color {
|
||||
constructor(options) {
|
||||
this._hue = 0;
|
||||
this._saturation = 100;
|
||||
this._value = 100;
|
||||
this._alpha = 100;
|
||||
|
||||
this.enableAlpha = false;
|
||||
this.format = 'hex';
|
||||
this.value = '';
|
||||
|
||||
options = options || {};
|
||||
|
||||
for (let option in options) {
|
||||
if (options.hasOwnProperty(option)) {
|
||||
this[option] = options[option];
|
||||
}
|
||||
}
|
||||
|
||||
this.doOnChange();
|
||||
}
|
||||
|
||||
set(prop, value) {
|
||||
if (arguments.length === 1 && typeof prop === 'object') {
|
||||
for (let p in prop) {
|
||||
if (prop.hasOwnProperty(p)) {
|
||||
this.set(p, prop[p]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this['_' + prop] = value;
|
||||
this.doOnChange();
|
||||
}
|
||||
|
||||
get(prop) {
|
||||
return this['_' + prop];
|
||||
}
|
||||
|
||||
toRgb() {
|
||||
return hsv2rgb(this._hue, this._saturation, this._value);
|
||||
}
|
||||
|
||||
fromString(value) {
|
||||
if (!value) {
|
||||
this._hue = 0;
|
||||
this._saturation = 100;
|
||||
this._value = 100;
|
||||
|
||||
this.doOnChange();
|
||||
return;
|
||||
}
|
||||
|
||||
const fromHSV = (h, s, v) => {
|
||||
this._hue = h;
|
||||
this._saturation = s;
|
||||
this._value = v;
|
||||
|
||||
this.doOnChange();
|
||||
};
|
||||
|
||||
if (value.indexOf('hsl') !== -1) {
|
||||
const parts = value.replace(/hsla|hsl|\(|\)/gm, '')
|
||||
.split(/\s|,/g, '').filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
|
||||
|
||||
if (parts.length > 3) {
|
||||
const { h, s, v } = hsl2hsv(parts[0], parts[1], parts[2]);
|
||||
fromHSV(h, s, v);
|
||||
}
|
||||
if (parts.length === 4) {
|
||||
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||
}
|
||||
} else if (value.indexOf('hsv') !== -1) {
|
||||
const parts = value.replace(/hsva|hsv|\(|\)/gm, '')
|
||||
.split(/\s|,/g, '').filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
|
||||
|
||||
if (parts.length >= 3) {
|
||||
fromHSV(parts[0], parts[1], parts[2]);
|
||||
}
|
||||
|
||||
if (parts.length === 4) {
|
||||
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||
}
|
||||
} else if (value.indexOf('rgb') !== -1) {
|
||||
const parts = value.replace(/rgba|rgb|\(|\)/gm, '')
|
||||
.split(/\s|,/g).filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
|
||||
|
||||
if (parts.length >= 3) {
|
||||
const { h, s, v } = rgb2hsv(parts[0], parts[1], parts[2]);
|
||||
fromHSV(h, s, v);
|
||||
}
|
||||
|
||||
if (parts.length === 4) {
|
||||
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||
}
|
||||
} else if (value.indexOf('#') !== -1) {
|
||||
const hex = value.replace('#', '').trim();
|
||||
let r, g, b;
|
||||
|
||||
if (hex.length === 3) {
|
||||
r = parseHexChannel(hex[0] + hex[0]);
|
||||
g = parseHexChannel(hex[1] + hex[1]);
|
||||
b = parseHexChannel(hex[2] + hex[2]);
|
||||
} else if (hex.length === 6) {
|
||||
r = parseHexChannel(hex.substring(0, 2));
|
||||
g = parseHexChannel(hex.substring(2, 4));
|
||||
b = parseHexChannel(hex.substring(4));
|
||||
}
|
||||
|
||||
const { h, s, v } = rgb2hsv(r, g, b);
|
||||
fromHSV(h, s, v);
|
||||
}
|
||||
}
|
||||
|
||||
doOnChange() {
|
||||
const { _hue, _saturation, _value, _alpha, format } = this;
|
||||
|
||||
if (this.enableAlpha) {
|
||||
switch (format) {
|
||||
case 'hsl':
|
||||
const hsl = hsv2hsl(_hue, _saturation / 100, _value / 100);
|
||||
this.value = `hsla(${ _hue }, ${ hsl[1] * 100 }%, ${ hsl[2] * 100 }%, ${ _alpha / 100})`;
|
||||
break;
|
||||
case 'hsv':
|
||||
this.value = `hsva(${ _hue }, ${ _saturation }%, ${ _value }%, ${ _alpha / 100})`;
|
||||
break;
|
||||
default:
|
||||
const { r, g, b } = hsv2rgb(_hue, _saturation, _value);
|
||||
this.value = `rgba(${r}, ${g}, ${b}, ${ _alpha / 100 })`;
|
||||
}
|
||||
} else {
|
||||
switch (format) {
|
||||
case 'hsl':
|
||||
const hsl = hsv2hsl(_hue, _saturation / 100, _value / 100);
|
||||
this.value = `hsl(${ _hue }, ${ hsl[1] * 100 }%, ${ hsl[2] * 100 }%)`;
|
||||
break;
|
||||
case 'hsv':
|
||||
this.value = `hsv(${ _hue }, ${ _saturation }%, ${ _value }%)`;
|
||||
break;
|
||||
case 'rgb':
|
||||
const { r, g, b } = hsv2rgb(_hue, _saturation, _value);
|
||||
this.value = `rgb(${r}, ${g}, ${b})`;
|
||||
break;
|
||||
default:
|
||||
this.value = toHex(hsv2rgb(_hue, _saturation, _value));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,137 @@
|
|||
<template>
|
||||
<div class="el-color-alpha-slider" :class="{ 'is-vertical': vertical }">
|
||||
<div class="el-color-alpha-slider__bar"
|
||||
@click="handleClick"
|
||||
ref="bar"
|
||||
:style="{
|
||||
background: background
|
||||
}">
|
||||
</div>
|
||||
<div class="el-color-alpha-slider__thumb"
|
||||
ref="thumb"
|
||||
:style="{
|
||||
left: thumbLeft + 'px',
|
||||
top: thumbTop + 'px'
|
||||
}">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import draggable from '../draggable';
|
||||
|
||||
export default {
|
||||
name: 'el-color-alpha-slider',
|
||||
|
||||
props: {
|
||||
color: {
|
||||
required: true
|
||||
},
|
||||
vertical: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'color._alpha'() {
|
||||
this.update();
|
||||
},
|
||||
|
||||
'color.value'() {
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleClick(event) {
|
||||
const thumb = this.$refs.thumb;
|
||||
const target = event.target;
|
||||
|
||||
if (target !== thumb) {
|
||||
this.handleDrag(event);
|
||||
}
|
||||
},
|
||||
|
||||
handleDrag(event) {
|
||||
const rect = this.$el.getBoundingClientRect();
|
||||
const { thumb } = this.$refs;
|
||||
|
||||
if (!this.vertical) {
|
||||
let left = event.clientX - rect.left;
|
||||
left = Math.max(thumb.offsetWidth / 2, left);
|
||||
left = Math.min(left, rect.width - thumb.offsetWidth / 2);
|
||||
|
||||
this.color._alpha = Math.round((left - thumb.offsetWidth / 2) / (rect.width - thumb.offsetWidth) * 100);
|
||||
} else {
|
||||
let top = event.clientY - rect.top;
|
||||
top = Math.max(thumb.offsetHeight / 2, top);
|
||||
top = Math.min(top, rect.height - thumb.offsetHeight / 2);
|
||||
|
||||
this.color._alpha = Math.round((top - thumb.offsetHeight / 2) / (rect.height - thumb.offsetHeight) * 100);
|
||||
}
|
||||
},
|
||||
|
||||
getThumbLeft() {
|
||||
if (this.vertical) return 0;
|
||||
const el = this.$el;
|
||||
const alpha = this.color._alpha;
|
||||
|
||||
if (!el) return 0;
|
||||
const thumb = this.$refs.thumb;
|
||||
return Math.round(alpha * (el.offsetWidth - thumb.offsetWidth / 2) / 100);
|
||||
},
|
||||
|
||||
getThumbTop() {
|
||||
if (!this.vertical) return 0;
|
||||
const el = this.$el;
|
||||
const alpha = this.color._alpha;
|
||||
|
||||
if (!el) return 0;
|
||||
const thumb = this.$refs.thumb;
|
||||
return Math.round(alpha * (el.offsetHeight - thumb.offsetHeight / 2) / 100);
|
||||
},
|
||||
|
||||
getBackground() {
|
||||
if (this.color && this.color.value) {
|
||||
const { r, g, b } = this.color.toRgb();
|
||||
return `linear-gradient(to right, rgba(${r}, ${g}, ${b}, 0) 0%, rgba(${r}, ${g}, ${b}, 1) 100%)`;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
update() {
|
||||
this.thumbLeft = this.getThumbLeft();
|
||||
this.thumbTop = this.getThumbTop();
|
||||
this.background = this.getBackground();
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
thumbLeft: 0,
|
||||
thumbTop: 0,
|
||||
background: null
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const { bar, thumb } = this.$refs;
|
||||
|
||||
const dragConfig = {
|
||||
drag: (event) => {
|
||||
this.handleDrag(event);
|
||||
},
|
||||
end: (event) => {
|
||||
this.handleDrag(event);
|
||||
}
|
||||
};
|
||||
|
||||
draggable(bar, dragConfig);
|
||||
draggable(thumb, dragConfig);
|
||||
this.update();
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,121 @@
|
|||
<template>
|
||||
<div class="el-color-hue-slider" :class="{ 'is-vertical': vertical }">
|
||||
<div class="el-color-hue-slider__bar" @click="handleClick" ref="bar"></div>
|
||||
<div class="el-color-hue-slider__thumb"
|
||||
:style="{
|
||||
left: thumbLeft + 'px',
|
||||
top: thumbTop + 'px'
|
||||
}"
|
||||
ref="thumb">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import draggable from '../draggable';
|
||||
|
||||
export default {
|
||||
name: 'el-color-hue-slider',
|
||||
|
||||
props: {
|
||||
color: {
|
||||
required: true
|
||||
},
|
||||
|
||||
vertical: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
thumbLeft: 0,
|
||||
thumbTop: 0
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
'color.value'() {
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleClick(event) {
|
||||
const thumb = this.$refs.thumb;
|
||||
const target = event.target;
|
||||
|
||||
if (target !== thumb) {
|
||||
this.handleDrag(event);
|
||||
}
|
||||
},
|
||||
|
||||
handleDrag(event) {
|
||||
const rect = this.$el.getBoundingClientRect();
|
||||
const { thumb } = this.$refs;
|
||||
let hue;
|
||||
|
||||
if (!this.vertical) {
|
||||
let left = event.clientX - rect.left;
|
||||
left = Math.min(left, rect.width - thumb.offsetWidth / 2);
|
||||
left = Math.max(thumb.offsetWidth / 2, left);
|
||||
|
||||
hue = Math.round((left - thumb.offsetWidth / 2) / (rect.width - thumb.offsetWidth) * 360);
|
||||
} else {
|
||||
let top = event.clientY - rect.top;
|
||||
top = Math.min(top, rect.height - thumb.offsetHeight / 2);
|
||||
top = Math.max(thumb.offsetHeight / 2, top);
|
||||
|
||||
hue = Math.round((top - thumb.offsetHeight / 2) / (rect.height - thumb.offsetHeight) * 360);
|
||||
}
|
||||
|
||||
this.color.set('hue', hue);
|
||||
},
|
||||
|
||||
getThumbLeft() {
|
||||
if (this.vertical) return 0;
|
||||
const el = this.$el;
|
||||
const hue = this.color.get('hue');
|
||||
|
||||
if (!el) return 0;
|
||||
const thumb = this.$refs.thumb;
|
||||
return Math.round(hue * (el.offsetWidth - thumb.offsetWidth / 2) / 360);
|
||||
},
|
||||
|
||||
getThumbTop() {
|
||||
if (!this.vertical) return 0;
|
||||
const el = this.$el;
|
||||
const hue = this.color.get('hue');
|
||||
|
||||
if (!el) return 0;
|
||||
const thumb = this.$refs.thumb;
|
||||
return Math.round(hue * (el.offsetHeight - thumb.offsetHeight / 2) / 360);
|
||||
},
|
||||
|
||||
update() {
|
||||
this.thumbLeft = this.getThumbLeft();
|
||||
this.thumbTop = this.getThumbTop();
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const { bar, thumb } = this.$refs;
|
||||
|
||||
const dragConfig = {
|
||||
drag: (event) => {
|
||||
this.handleDrag(event);
|
||||
},
|
||||
end: (event) => {
|
||||
this.handleDrag(event);
|
||||
}
|
||||
};
|
||||
|
||||
draggable(bar, dragConfig);
|
||||
draggable(thumb, dragConfig);
|
||||
this.update();
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,74 @@
|
|||
<template>
|
||||
<transition name="el-zoom-in-top" @after-leave="doDestroy">
|
||||
<div
|
||||
class="el-color-dropdown"
|
||||
v-show="showPopper">
|
||||
<div class="el-color-dropdown__main-wrapper">
|
||||
<hue-slider ref="hue" :color="color" vertical style="float: right;"></hue-slider>
|
||||
<sv-panel ref="sl" :color="color"></sv-panel>
|
||||
</div>
|
||||
<alpha-slider v-if="showAlpha" ref="alpha" :color="color"></alpha-slider>
|
||||
<div class="el-color-dropdown__btns">
|
||||
<a href="JavaScript:" class="el-color-dropdown__link-btn" @click="$emit('clear')">{{ t('el.colorpicker.clear') }}</a>
|
||||
<button class="el-color-dropdown__btn" @click="confirmValue">{{ t('el.colorpicker.confirm') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
<style>
|
||||
</style>
|
||||
<script type="babel">
|
||||
import SvPanel from './sv-panel';
|
||||
import HueSlider from './hue-slider';
|
||||
import AlphaSlider from './alpha-slider';
|
||||
import Popper from 'element-ui/src/utils/vue-popper';
|
||||
import Clickoutside from 'element-ui/src/utils/clickoutside';
|
||||
import Locale from 'element-ui/src/mixins/locale';
|
||||
|
||||
export default {
|
||||
name: 'el-color-picker-dropdown',
|
||||
|
||||
mixins: [Popper, Locale],
|
||||
|
||||
components: {
|
||||
SvPanel,
|
||||
HueSlider,
|
||||
AlphaSlider
|
||||
},
|
||||
|
||||
directives: { Clickoutside },
|
||||
|
||||
props: {
|
||||
color: {
|
||||
required: true
|
||||
},
|
||||
showAlpha: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
confirmValue() {
|
||||
this.$emit('pick');
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$parent.popperElm = this.popperElm = this.$el;
|
||||
this.referenceElm = this.$parent.$el;
|
||||
},
|
||||
|
||||
watch: {
|
||||
showPopper(val) {
|
||||
if (val === true) {
|
||||
this.$nextTick(() => {
|
||||
const { sl, hue, alpha } = this.$refs;
|
||||
sl && sl.update();
|
||||
hue && hue.update();
|
||||
alpha && alpha.update();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,97 @@
|
|||
<template>
|
||||
<div class="el-color-svpanel"
|
||||
:style="{
|
||||
backgroundColor: background
|
||||
}">
|
||||
<div class="el-color-svpanel__white"></div>
|
||||
<div class="el-color-svpanel__black"></div>
|
||||
<div class="el-color-svpanel__cursor"
|
||||
:style="{
|
||||
top: cursorTop + 'px',
|
||||
left: cursorLeft + 'px'
|
||||
}">
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
<script type="babel">
|
||||
import draggable from '../draggable';
|
||||
|
||||
export default {
|
||||
name: 'el-sl-panel',
|
||||
|
||||
props: {
|
||||
color: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'color.value'() {
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
update() {
|
||||
const saturation = this.color.get('saturation');
|
||||
const value = this.color.get('value');
|
||||
|
||||
const el = this.$el;
|
||||
let { width, height } = el.getBoundingClientRect();
|
||||
|
||||
if (!height) height = width * 3 / 4;
|
||||
|
||||
this.cursorLeft = saturation * width / 100;
|
||||
this.cursorTop = (100 - value) * height / 100;
|
||||
|
||||
this.background = 'hsl(' + this.color.get('hue') + ', 100%, 50%)';
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const handleDrag = (event) => {
|
||||
const el = this.$el;
|
||||
const rect = el.getBoundingClientRect();
|
||||
|
||||
let left = event.clientX - rect.left;
|
||||
let top = event.clientY - rect.top;
|
||||
left = Math.max(0, left);
|
||||
left = Math.min(left, rect.width);
|
||||
|
||||
top = Math.max(0, top);
|
||||
top = Math.min(top, rect.height);
|
||||
|
||||
this.cursorLeft = left;
|
||||
this.cursorTop = top;
|
||||
this.color.set({
|
||||
saturation: left / rect.width * 100,
|
||||
value: 100 - top / rect.height * 100
|
||||
});
|
||||
};
|
||||
|
||||
draggable(this.$el, {
|
||||
drag: (event) => {
|
||||
handleDrag(event);
|
||||
},
|
||||
end: (event) => {
|
||||
handleDrag(event);
|
||||
}
|
||||
});
|
||||
|
||||
this.update();
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
cursorTop: 0,
|
||||
cursorLeft: 0,
|
||||
background: 'hsl(0, 100%, 50%)'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,34 @@
|
|||
let isDragging = false;
|
||||
|
||||
export default function(element, options) {
|
||||
const moveFn = function(event) {
|
||||
if (options.drag) {
|
||||
options.drag(event);
|
||||
}
|
||||
};
|
||||
const upFn = function(event) {
|
||||
document.removeEventListener('mousemove', moveFn);
|
||||
document.removeEventListener('mouseup', upFn);
|
||||
document.onselectstart = null;
|
||||
document.ondragstart = null;
|
||||
|
||||
isDragging = false;
|
||||
|
||||
if (options.end) {
|
||||
options.end(event);
|
||||
}
|
||||
};
|
||||
element.addEventListener('mousedown', function(event) {
|
||||
if (isDragging) return;
|
||||
document.onselectstart = function() { return false; };
|
||||
document.ondragstart = function() { return false; };
|
||||
|
||||
document.addEventListener('mousemove', moveFn);
|
||||
document.addEventListener('mouseup', upFn);
|
||||
isDragging = true;
|
||||
|
||||
if (options.start) {
|
||||
options.start(event);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
<template>
|
||||
<div class="el-color-picker" v-clickoutside="hide">
|
||||
<div class="el-color-picker__trigger" @click.stop="showPicker = !showPicker">
|
||||
<span class="el-color-picker__color" :class="{ 'is-alpha': showAlpha }">
|
||||
<span class="el-color-picker__color-inner"
|
||||
:style="{
|
||||
backgroundColor: value ? value : 'transparent'
|
||||
}"></span>
|
||||
<span class="el-color-picker__empty el-icon-close" v-if="!value"></span>
|
||||
</span>
|
||||
<span class="el-color-picker__icon el-icon-caret-bottom"></span>
|
||||
</div>
|
||||
<picker-dropdown
|
||||
ref="dropdown"
|
||||
class="el-color-picker__panel"
|
||||
v-model="showPicker"
|
||||
@pick="confirmValue"
|
||||
@clear="clearValue"
|
||||
:color="color"
|
||||
:show-alpha="showAlpha">
|
||||
</picker-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import Color from './color';
|
||||
import PickerDropdown from './components/picker-dropdown.vue';
|
||||
import Clickoutside from 'element-ui/src/utils/clickoutside';
|
||||
|
||||
export default {
|
||||
name: 'ElColorPicker',
|
||||
|
||||
props: {
|
||||
value: {
|
||||
type: String
|
||||
},
|
||||
showAlpha: {
|
||||
type: Boolean
|
||||
},
|
||||
colorFormat: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
|
||||
directives: { Clickoutside },
|
||||
|
||||
watch: {
|
||||
value(val) {
|
||||
if (val && val !== this.color.value) {
|
||||
this.color.fromString(val);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
confirmValue(value) {
|
||||
this.$emit('input', this.color.value);
|
||||
this.showPicker = false;
|
||||
},
|
||||
clearValue() {
|
||||
this.$emit('input', null);
|
||||
this.showPicker = false;
|
||||
},
|
||||
hide() {
|
||||
this.showPicker = false;
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const value = this.value;
|
||||
if (value) {
|
||||
this.color.fromString(value);
|
||||
}
|
||||
this.popperElm = this.$refs.dropdown.$el;
|
||||
},
|
||||
|
||||
data() {
|
||||
const color = new Color({
|
||||
enableAlpha: this.showAlpha,
|
||||
format: this.colorFormat
|
||||
});
|
||||
return {
|
||||
color,
|
||||
showPicker: false
|
||||
};
|
||||
},
|
||||
|
||||
components: {
|
||||
PickerDropdown
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,250 @@
|
|||
@import "./common/var.css";
|
||||
|
||||
@component-namespace el-color {
|
||||
@component hue-slider {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
width: 240px;
|
||||
height: 12px;
|
||||
background-color: #f00;
|
||||
padding: 0 2px;
|
||||
|
||||
@descendent bar {
|
||||
position: relative;
|
||||
background: linear-gradient(
|
||||
to right, #f00 0%,
|
||||
#ff0 17%, #0f0 33%,
|
||||
#0ff 50%, #00f 67%,
|
||||
#f0f 83%, #f00 100%);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@descendent thumb {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
border-radius: 1px;
|
||||
background: #fff;
|
||||
border: 1px solid #f0f0f0;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@when vertical {
|
||||
width: 12px;
|
||||
height: 180px;
|
||||
padding: 2px 0;
|
||||
|
||||
.el-color-hue-slider__bar {
|
||||
background: linear-gradient(
|
||||
to bottom, #f00 0%,
|
||||
#ff0 17%, #0f0 33%,
|
||||
#0ff 50%, #00f 67%,
|
||||
#f0f 83%, #f00 100%);
|
||||
}
|
||||
|
||||
.el-color-hue-slider__thumb {
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@component svpanel {
|
||||
position: relative;
|
||||
width: 240px;
|
||||
height: 180px;
|
||||
|
||||
@descendent white, black {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
@descendent white {
|
||||
background: linear-gradient(to right, #fff, rgba(255,255,255,0));
|
||||
}
|
||||
|
||||
@descendent black {
|
||||
background: linear-gradient(to top, #000, rgba(0,0,0,0));
|
||||
}
|
||||
|
||||
@descendent cursor {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
|
||||
> div {
|
||||
cursor: head;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
box-shadow: 0 0 0 1.5px #fff, inset 0 0 1px 1px rgba(0,0,0,0.3), 0 0 1px 2px rgba(0,0,0,0.4);
|
||||
border-radius: 50%;
|
||||
transform: translate(-2px, -2px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@component alpha-slider {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
width: 240px;
|
||||
height: 12px;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
||||
|
||||
@descendent bar {
|
||||
position: relative;
|
||||
background: linear-gradient(
|
||||
to right, rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 1) 100%);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@descendent thumb {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
border-radius: 1px;
|
||||
background: #fff;
|
||||
border: 1px solid #f0f0f0;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@when vertical {
|
||||
width: 20px;
|
||||
height: 180px;
|
||||
|
||||
.el-color-alpha-slider__bar {
|
||||
background: linear-gradient(
|
||||
to bottom, rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 1) 100%);
|
||||
}
|
||||
|
||||
.el-color-alpha-slider__thumb {
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@component dropdown {
|
||||
width: 260px;
|
||||
|
||||
@descendent main-wrapper {
|
||||
margin-bottom: 6px;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
@descendent btns {
|
||||
margin-top: 6px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@descendent btn {
|
||||
border: 1px solid #dcdcdc;
|
||||
color: #333;
|
||||
line-height: 24px;
|
||||
border-radius: 2px;
|
||||
padding: 0 20px;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
font-size: 12px;
|
||||
|
||||
&[disabled] {
|
||||
color: #cccccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
@descendent link-btn {
|
||||
cursor: pointer;
|
||||
color: var(--color-primary);
|
||||
text-decoration: none;
|
||||
padding: 15px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@component picker {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
||||
@descendent trigger {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
height: 36px;
|
||||
padding: 6px;
|
||||
border: 1px solid #bfcbd9;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@descendent color {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
vertical-align: middle;
|
||||
border: 1px solid #666;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
text-align: center;
|
||||
|
||||
@when alpha {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
||||
}
|
||||
}
|
||||
|
||||
@descendent color-inner {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
@descendent empty {
|
||||
font-size: 12px;
|
||||
vertical-align: middle;
|
||||
margin-top: -2px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
@descendent icon {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
margin-left: 8px;
|
||||
width: 12px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
@descendent panel {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
padding: 6px;
|
||||
background-color: var(--color-white);
|
||||
border: 1px solid var(--color-base-gray);
|
||||
box-shadow: var(--dropdown-menu-box-shadow);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,3 +60,4 @@
|
|||
@import "./collapse.css";
|
||||
@import "./collapse-item.css";
|
||||
@import "./cascader.css";
|
||||
@import "./color-picker.css";
|
||||
|
|
|
@ -61,6 +61,7 @@ import CarouselItem from '../packages/carousel-item';
|
|||
import Collapse from '../packages/collapse';
|
||||
import CollapseItem from '../packages/collapse-item';
|
||||
import Cascader from '../packages/cascader';
|
||||
import ColorPicker from '../packages/color-picker';
|
||||
import locale from 'element-ui/src/locale';
|
||||
|
||||
const components = [
|
||||
|
@ -120,7 +121,8 @@ const components = [
|
|||
CarouselItem,
|
||||
Collapse,
|
||||
CollapseItem,
|
||||
Cascader
|
||||
Cascader,
|
||||
ColorPicker
|
||||
];
|
||||
|
||||
const install = function(Vue, opts = {}) {
|
||||
|
@ -214,5 +216,6 @@ module.exports = {
|
|||
CarouselItem,
|
||||
Collapse,
|
||||
CollapseItem,
|
||||
Cascader
|
||||
Cascader,
|
||||
ColorPicker
|
||||
};
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Изчисти'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Сега',
|
||||
today: 'Днес',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Ryd'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Nu',
|
||||
today: 'I dag',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Leeren'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Jetzt',
|
||||
today: 'Heute',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Καθαρισμός'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Τώρα',
|
||||
today: 'Σήμερα',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Clear'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Now',
|
||||
today: 'Today',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'Confirmar',
|
||||
clear: 'Limpiar'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Ahora',
|
||||
today: 'Hoy',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'باشد',
|
||||
clear: 'خذف'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'اکنون',
|
||||
today: 'امروز',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Tyhjennä'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Nyt',
|
||||
today: 'Tänään',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Effacer'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Maintenant',
|
||||
today: 'Auj.',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'YA',
|
||||
clear: 'Kosongkan'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Sekarang',
|
||||
today: 'Hari ini',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Pulisci'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Ora',
|
||||
today: 'Oggi',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'はい',
|
||||
clear: 'クリア'
|
||||
},
|
||||
datepicker: {
|
||||
now: '現在',
|
||||
today: '今日',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: '확인',
|
||||
clear: '초기화'
|
||||
},
|
||||
datepicker: {
|
||||
now: '지금',
|
||||
today: '오늘',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Tøm'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Nå',
|
||||
today: 'I dag',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'Bevestig',
|
||||
clear: 'Legen'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Nu',
|
||||
today: 'Vandaag',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Wyczyść'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Teraz',
|
||||
today: 'Dzisiaj',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'Confirmar',
|
||||
clear: 'Limpar'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Agora',
|
||||
today: 'Hoje',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'Confirmar',
|
||||
clear: 'Limpar'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Agora',
|
||||
today: 'Hoje',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Очистить'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Сейчас',
|
||||
today: 'Сегодня',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Zmazať'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Teraz',
|
||||
today: 'Dnes',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Töm'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Nu',
|
||||
today: 'Idag',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'ตกลง',
|
||||
clear: 'ล้างข้อมูล'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'ตอนนี้',
|
||||
today: 'วันนี้',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Temizle'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Şimdi',
|
||||
today: 'Bugün',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: 'OK',
|
||||
clear: 'Xóa'
|
||||
},
|
||||
datepicker: {
|
||||
now: 'Hiện tại',
|
||||
today: 'Hôm nay',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: '确定',
|
||||
clear: '清空'
|
||||
},
|
||||
datepicker: {
|
||||
now: '此刻',
|
||||
today: '今天',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
export default {
|
||||
el: {
|
||||
colorpicker: {
|
||||
confirm: '確認',
|
||||
clear: '清空'
|
||||
},
|
||||
datepicker: {
|
||||
now: '現在',
|
||||
today: '今天',
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
import { createTest, createVue, destroyVM } from '../util';
|
||||
import ColorPicker from 'packages/color-picker';
|
||||
|
||||
describe('ColorPicker', () => {
|
||||
let vm;
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy(true);
|
||||
destroyVM(vm);
|
||||
const dropdown = document.querySelector('.el-color-dropdown');
|
||||
if (dropdown && dropdown.parentNode) dropdown.parentNode.removeChild(dropdown);
|
||||
});
|
||||
|
||||
it('should works', () => {
|
||||
vm = createTest(ColorPicker, true);
|
||||
expect(vm.$el).to.exist;
|
||||
});
|
||||
|
||||
it('should show alpha slider when show-alpha=true', (done) => {
|
||||
const vm = createVue({
|
||||
template: `
|
||||
<el-color-picker v-model="color" show-alpha></el-color-picker>
|
||||
`,
|
||||
|
||||
data() {
|
||||
return {
|
||||
color: null
|
||||
};
|
||||
}
|
||||
}, true);
|
||||
|
||||
const trigger = vm.$el.querySelector('.el-color-picker__trigger');
|
||||
trigger.click();
|
||||
|
||||
setTimeout(() => {
|
||||
const alphaSlider = document.querySelector('.el-color-alpha-slider');
|
||||
expect(alphaSlider).to.exist;
|
||||
done();
|
||||
}, ANIMATION_TIME);
|
||||
});
|
||||
|
||||
it('should show color picker when click trigger', (done) => {
|
||||
vm = createTest(ColorPicker, true);
|
||||
|
||||
const trigger = vm.$el.querySelector('.el-color-picker__trigger');
|
||||
trigger.click();
|
||||
|
||||
vm.$nextTick(() => {
|
||||
const dropdown = document.querySelector('.el-color-dropdown');
|
||||
expect(dropdown).to.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
const ANIMATION_TIME = 300;
|
||||
|
||||
it('should pick a color when confirm button click', (done) => {
|
||||
const vm = createVue({
|
||||
template: `
|
||||
<el-color-picker v-model="color"></el-color-picker>
|
||||
`,
|
||||
|
||||
data() {
|
||||
return {
|
||||
color: null
|
||||
};
|
||||
}
|
||||
}, true);
|
||||
|
||||
const trigger = vm.$el.querySelector('.el-color-picker__trigger');
|
||||
trigger.click();
|
||||
|
||||
setTimeout(() => {
|
||||
const dropdown = document.querySelector('.el-color-dropdown__btn');
|
||||
dropdown.click();
|
||||
vm.$nextTick(() => {
|
||||
expect(vm.color).to.equal('#FF0000');
|
||||
done();
|
||||
});
|
||||
}, ANIMATION_TIME);
|
||||
});
|
||||
|
||||
it('should init the right color when open', (done) => {
|
||||
const vm = createVue({
|
||||
template: `
|
||||
<el-color-picker v-model="color"></el-color-picker>
|
||||
`,
|
||||
|
||||
data() {
|
||||
return {
|
||||
color: '#0f0'
|
||||
};
|
||||
}
|
||||
}, true);
|
||||
|
||||
const trigger = vm.$el.querySelector('.el-color-picker__trigger');
|
||||
trigger.click();
|
||||
|
||||
setTimeout(() => {
|
||||
const dropdown = document.querySelector('.el-color-dropdown__btn');
|
||||
dropdown.click();
|
||||
vm.$nextTick(() => {
|
||||
const hueBar = document.querySelector('.el-color-hue-slider__thumb');
|
||||
const top = parseInt(hueBar.style.top, 10);
|
||||
expect(top > 10).to.be.true;
|
||||
done();
|
||||
});
|
||||
}, ANIMATION_TIME);
|
||||
});
|
||||
|
||||
it('should clear a color when clear button click', (done) => {
|
||||
const vm = createVue({
|
||||
template: `
|
||||
<el-color-picker v-model="color"></el-color-picker>
|
||||
`,
|
||||
|
||||
data() {
|
||||
return {
|
||||
color: '#f00'
|
||||
};
|
||||
}
|
||||
}, true);
|
||||
|
||||
const trigger = vm.$el.querySelector('.el-color-picker__trigger');
|
||||
trigger.click();
|
||||
|
||||
setTimeout(() => {
|
||||
const clearBtn = document.querySelector('.el-color-dropdown__link-btn');
|
||||
clearBtn.click();
|
||||
setTimeout(() => {
|
||||
expect(vm.color).to.equal(null);
|
||||
done();
|
||||
}, 30);
|
||||
}, ANIMATION_TIME);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue