Merge pull request #3662 from Xotic750/color_picker_tabs
Keyboard control for color picker
This commit is contained in:
commit
653d12ac9b
13 changed files with 1314 additions and 652 deletions
|
@ -1,46 +1,157 @@
|
|||
<template>
|
||||
<div style="margin: 100px;">
|
||||
{{ color }}
|
||||
{{color}}
|
||||
<!--<Input placeholder="请输入..." size="large" style="width: 50px;"></Input>-->
|
||||
<color-picker @on-change="c1" @on-active-change="c2" v-model="color" placement="bottom-start" size="large"></color-picker>
|
||||
<Date-picker transfer type="date" placeholder="选择日期" style="width: 200px"></Date-picker>
|
||||
<color-picker :transfer="true" ref="xxx" v-model="color" format="rgb" alpha :recommend="true"></color-picker>
|
||||
<color-picker v-model="color2" format="hsv" :alpha="true" :recommend="false"></color-picker>
|
||||
<color-picker
|
||||
v-model="color"
|
||||
placement="bottom-start"
|
||||
size="large"
|
||||
@on-change="c1"
|
||||
@on-active-change="c2"></color-picker>
|
||||
<Date-picker
|
||||
transfer
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
style="width: 200px"></Date-picker>
|
||||
<color-picker
|
||||
ref="xxx"
|
||||
:transfer="true"
|
||||
v-model="color"
|
||||
:recommend="true"
|
||||
format="rgb"
|
||||
alpha
|
||||
@on-change="onChange"
|
||||
@on-active-change="onActiveChange"></color-picker>
|
||||
<color-picker
|
||||
v-model="color2"
|
||||
:alpha="true"
|
||||
:recommend="false"
|
||||
format="hsv"></color-picker>
|
||||
<!--<Date-picker type="date" placeholder="选择日期" style="width: 200px"></Date-picker>-->
|
||||
<color-picker v-model="color" placement="bottom-start" size="small"></color-picker>
|
||||
<Date-picker type="date" placeholder="选择日期" size="small" style="width: 200px"></Date-picker>
|
||||
<color-picker
|
||||
v-model="color"
|
||||
placement="bottom-start"
|
||||
size="small"></color-picker>
|
||||
<Date-picker
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
size="small"
|
||||
style="width: 200px"></Date-picker>
|
||||
<color-picker
|
||||
ref="yyy"
|
||||
:colors="colors"
|
||||
v-model="color"
|
||||
transfer
|
||||
format="rgb"
|
||||
alpha></color-picker>
|
||||
<Button @click="setColor">set color</Button>
|
||||
|
||||
<br><br><br><br>
|
||||
{{openState}}
|
||||
<ColorPicker v-model="color7" :hue="false" @on-open-change="onOpenChange"></ColorPicker>
|
||||
<ColorPicker
|
||||
v-model="color7"
|
||||
:hue="false"
|
||||
@on-open-change="onOpenChange"></ColorPicker>
|
||||
<ColorPicker
|
||||
v-model="color7"
|
||||
:hue="false"
|
||||
:hide-drop-down="hideDropDown"
|
||||
transfer
|
||||
@on-open-change="onOpenChange"></ColorPicker>
|
||||
|
||||
<br><br><br><br>
|
||||
<ColorPicker
|
||||
v-model="color7"
|
||||
disabled></ColorPicker>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {},
|
||||
data () {
|
||||
return {
|
||||
color: 'rgba(12,34,255,.85)',
|
||||
color2: '',
|
||||
color7: '#19be6b',
|
||||
openState: false,
|
||||
};
|
||||
export default {
|
||||
props: {},
|
||||
|
||||
data() {
|
||||
return {
|
||||
color: 'rgba(12,34,255,.85)',
|
||||
color2: '',
|
||||
color7: '#19be6b',
|
||||
openState: false,
|
||||
colors: [
|
||||
'#2d8cf0',
|
||||
'#19be6b',
|
||||
'#ff9900',
|
||||
'#ed3f14',
|
||||
'#00b5ff',
|
||||
'#19c919',
|
||||
'#f9e31c',
|
||||
'#ea1a1a',
|
||||
'#9b1dea',
|
||||
'#00c2b1',
|
||||
'#ac7a33',
|
||||
'#1d35ea',
|
||||
'#8bc34a',
|
||||
'#f16b62',
|
||||
'#ea4ca3',
|
||||
'#0d94aa',
|
||||
'#febd79',
|
||||
'#5d4037',
|
||||
'#00bcd4',
|
||||
'#f06292',
|
||||
'#cddc39',
|
||||
'#607d8b',
|
||||
'#000000',
|
||||
'#ffffff',
|
||||
'#2d8cf0',
|
||||
'#19be6b',
|
||||
'#ff9900',
|
||||
'#ed3f14',
|
||||
'#00b5ff',
|
||||
'#19c919',
|
||||
'#f9e31c',
|
||||
'#ea1a1a',
|
||||
'#9b1dea',
|
||||
'#00c2b1',
|
||||
'#ac7a33',
|
||||
'#1d35ea',
|
||||
'#8bc34a',
|
||||
'#f16b62',
|
||||
'#ea4ca3',
|
||||
'#0d94aa',
|
||||
'#febd79',
|
||||
'#5d4037',
|
||||
],
|
||||
hideDropDown: false,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {},
|
||||
|
||||
mounted() {
|
||||
setInterval(this.toggleShowHide, 2000);
|
||||
},
|
||||
|
||||
methods: {
|
||||
setColor() {
|
||||
this.color = '#26bc77';
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
setColor () {
|
||||
this.color = '#26bc77';
|
||||
},
|
||||
c1 (d) {
|
||||
console.log(d);
|
||||
},
|
||||
c2 (d) {
|
||||
console.log(d);
|
||||
},
|
||||
onOpenChange(state){
|
||||
this.openState = state;
|
||||
}
|
||||
}
|
||||
};
|
||||
c1(d) {
|
||||
console.log(d);
|
||||
},
|
||||
c2(d) {
|
||||
console.log(d);
|
||||
},
|
||||
onOpenChange(state) {
|
||||
this.openState = state;
|
||||
},
|
||||
onChange(d) {
|
||||
console.log(d);
|
||||
},
|
||||
onActiveChange(d) {
|
||||
console.log(d);
|
||||
},
|
||||
toggleShowHide() {
|
||||
this.hideDropDown = !this.hideDropDown;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,77 +1,103 @@
|
|||
<template>
|
||||
<div class="ivu-color-picker-alpha">
|
||||
<div class="ivu-color-picker-alpha-checkboard-wrap">
|
||||
<div class="ivu-color-picker-alpha-checkerboard"></div>
|
||||
<div
|
||||
:class="[prefixCls + '-alpha']"
|
||||
tabindex="0"
|
||||
@click="$el.focus()"
|
||||
@keydown.esc="handleEscape"
|
||||
@keydown.left="handleLeft"
|
||||
@keydown.right="handleRight"
|
||||
@keydown.up="handleUp"
|
||||
@keydown.down="handleDown"
|
||||
>
|
||||
<div :class="[prefixCls + '-alpha-checkboard-wrap']">
|
||||
<div :class="[prefixCls + '-alpha-checkerboard']"></div>
|
||||
</div>
|
||||
<div class="ivu-color-picker-alpha-gradient" :style="{background: gradientColor}"></div>
|
||||
<div class="ivu-color-picker-alpha-container" ref="container"
|
||||
@mousedown="handleMouseDown"
|
||||
@touchmove="handleChange"
|
||||
@touchstart="handleChange">
|
||||
<div class="ivu-color-picker-alpha-pointer" :style="{left: colors.a * 100 + '%'}">
|
||||
<div class="ivu-color-picker-alpha-picker"></div>
|
||||
<div
|
||||
:style="gradientStyle"
|
||||
:class="[prefixCls + '-alpha-gradient']"></div>
|
||||
<div
|
||||
ref="container"
|
||||
:class="[prefixCls + '-alpha-container']"
|
||||
@mousedown="handleMouseDown"
|
||||
@touchmove="handleChange"
|
||||
@touchstart="handleChange">
|
||||
<div
|
||||
:style="{top: 0, left: `${value.a * 100}%`}"
|
||||
:class="[prefixCls + '-alpha-pointer']">
|
||||
<div :class="[prefixCls + '-alpha-picker']"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Alpha',
|
||||
props: {
|
||||
value: Object,
|
||||
onChange: Function
|
||||
import HSAMixin from './hsaMixin';
|
||||
import Prefixes from './prefixMixin';
|
||||
import {clamp, toRGBAString} from './utils';
|
||||
|
||||
export default {
|
||||
name: 'Alpha',
|
||||
|
||||
mixins: [HSAMixin, Prefixes],
|
||||
|
||||
data() {
|
||||
const normalStep = 1;
|
||||
const jumpStep = 10;
|
||||
|
||||
return {
|
||||
left: -normalStep,
|
||||
right: normalStep,
|
||||
up: jumpStep,
|
||||
down: -jumpStep,
|
||||
powerKey: 'shiftKey',
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
gradientStyle() {
|
||||
const {r, g, b} = this.value.rgba;
|
||||
const start = toRGBAString({r, g, b, a: 0});
|
||||
const finish = toRGBAString({r, g, b, a: 1});
|
||||
|
||||
return {background: `linear-gradient(to right, ${start} 0%, ${finish} 100%)`};
|
||||
},
|
||||
computed: {
|
||||
colors () {
|
||||
return this.value;
|
||||
},
|
||||
gradientColor () {
|
||||
const rgba = this.colors.rgba;
|
||||
const rgbStr = [rgba.r, rgba.g, rgba.b].join(',');
|
||||
return 'linear-gradient(to right, rgba(' + rgbStr + ', 0) 0%, rgba(' + rgbStr + ', 1) 100%)';
|
||||
},
|
||||
|
||||
methods: {
|
||||
change(newAlpha) {
|
||||
const {h, s, l} = this.value.hsl;
|
||||
const {a} = this.value;
|
||||
|
||||
if (a !== newAlpha) {
|
||||
this.$emit('change', {h, s, l, a: newAlpha, source: 'rgba'});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange (e, skip) {
|
||||
!skip && e.preventDefault();
|
||||
const container = this.$refs.container;
|
||||
const containerWidth = container.clientWidth;
|
||||
handleSlide(e, direction) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const xOffset = container.getBoundingClientRect().left + window.pageXOffset;
|
||||
const pageX = e.pageX || (e.touches ? e.touches[0].pageX : 0);
|
||||
const left = pageX - xOffset;
|
||||
this.change(clamp(e[this.powerKey] ? direction : Math.round(this.value.hsl.a * 100 + direction) / 100, 0, 1));
|
||||
},
|
||||
handleChange(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
let a;
|
||||
if (left < 0) {
|
||||
a = 0;
|
||||
} else if (left > containerWidth) {
|
||||
a = 1;
|
||||
} else {
|
||||
a = Math.round(left * 100 / containerWidth) / 100;
|
||||
}
|
||||
const left = this.getLeft(e);
|
||||
|
||||
if (this.colors.a !== a) {
|
||||
this.$emit('change', {
|
||||
h: this.colors.hsl.h,
|
||||
s: this.colors.hsl.s,
|
||||
l: this.colors.hsl.l,
|
||||
a: a,
|
||||
source: 'rgba'
|
||||
});
|
||||
}
|
||||
},
|
||||
handleMouseDown (e) {
|
||||
this.handleChange(e, true);
|
||||
window.addEventListener('mousemove', this.handleChange);
|
||||
window.addEventListener('mouseup', this.handleMouseUp);
|
||||
},
|
||||
handleMouseUp () {
|
||||
this.unbindEventListeners();
|
||||
},
|
||||
unbindEventListeners () {
|
||||
window.removeEventListener('mousemove', this.handleChange);
|
||||
window.removeEventListener('mouseup', this.handleMouseUp);
|
||||
if (left < 0) {
|
||||
this.change(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
const {clientWidth} = this.$refs.container;
|
||||
|
||||
if (left > clientWidth) {
|
||||
this.change(1);
|
||||
return;
|
||||
}
|
||||
|
||||
this.change(Math.round(left * 100 / clientWidth) / 100);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,375 +1,453 @@
|
|||
<template>
|
||||
<div :class="classes" v-clickoutside="handleClose">
|
||||
<div ref="reference" @click="toggleVisible" :class="wrapClasses">
|
||||
<input type="hidden" :name="name" :value="currentValue">
|
||||
<i class="ivu-icon ivu-icon-arrow-down-b ivu-input-icon ivu-input-icon-normal"></i>
|
||||
<div :class="inputClasses">
|
||||
<div
|
||||
v-click-outside.capture="handleClose"
|
||||
v-click-outside:mousedown.capture="handleClose"
|
||||
:class="classes">
|
||||
<div
|
||||
ref="reference"
|
||||
:class="wrapClasses"
|
||||
@click="toggleVisible">
|
||||
<input
|
||||
:name="name"
|
||||
:value="currentValue"
|
||||
type="hidden">
|
||||
<i :class="arrowClasses"></i>
|
||||
<div
|
||||
ref="input"
|
||||
:tabindex="disabled ? undefined : 0"
|
||||
:class="inputClasses"
|
||||
@keydown.tab="onTab"
|
||||
@keydown.esc="onEscape"
|
||||
@keydown.up="onArrow"
|
||||
@keydown.down="onArrow"
|
||||
>
|
||||
<div :class="[prefixCls + '-color']">
|
||||
<div :class="[prefixCls + '-color-empty']" v-show="value === '' && !visible">
|
||||
<i class="ivu-icon ivu-icon-ios-close-empty"></i>
|
||||
<div
|
||||
v-show="value === '' && !visible"
|
||||
:class="[prefixCls + '-color-empty']">
|
||||
<i :class="[iconPrefixCls, iconPrefixCls + '-ios-close-empty']"></i>
|
||||
</div>
|
||||
<div v-show="value || visible" :style="{backgroundColor: displayedColor}"></div>
|
||||
<div
|
||||
v-show="value || visible"
|
||||
:style="displayedColorStyle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<transition name="transition-drop">
|
||||
<Drop
|
||||
v-transfer-dom
|
||||
v-show="visible"
|
||||
@click.native="handleTransferClick"
|
||||
:class="{ [prefixCls + '-transfer']: transfer }"
|
||||
class-name="ivu-transfer-no-max-height"
|
||||
:placement="placement"
|
||||
ref="drop"
|
||||
:placement="placement"
|
||||
:data-transfer="transfer"
|
||||
v-transfer-dom>
|
||||
<div :class="[prefixCls + '-picker']">
|
||||
<div :class="[prefixCls + '-picker-wrapper']">
|
||||
<div :class="[prefixCls + '-picker-panel']">
|
||||
<Saturation v-model="saturationColors" @change="childChange"></Saturation>
|
||||
:class="dropClasses"
|
||||
>
|
||||
<transition name="fade">
|
||||
<div
|
||||
v-if="visible"
|
||||
:class="[prefixCls + '-picker']">
|
||||
<div :class="[prefixCls + '-picker-wrapper']">
|
||||
<div :class="[prefixCls + '-picker-panel']">
|
||||
<Saturation
|
||||
ref="saturation"
|
||||
v-model="saturationColors"
|
||||
:focused="visible"
|
||||
@change="childChange"
|
||||
@keydown.native.tab="handleFirstTab"
|
||||
></Saturation>
|
||||
</div>
|
||||
<div
|
||||
v-if="hue"
|
||||
:class="[prefixCls + '-picker-hue-slider']">
|
||||
<Hue
|
||||
v-model="saturationColors"
|
||||
@change="childChange"></Hue>
|
||||
</div>
|
||||
<div
|
||||
v-if="alpha"
|
||||
:class="[prefixCls + '-picker-alpha-slider']">
|
||||
<Alpha
|
||||
v-model="saturationColors"
|
||||
@change="childChange"></Alpha>
|
||||
</div>
|
||||
<recommend-colors
|
||||
v-if="colors.length"
|
||||
:list="colors"
|
||||
:class="[prefixCls + '-picker-colors']"
|
||||
@picker-color="handleSelectColor"></recommend-colors>
|
||||
<recommend-colors
|
||||
v-if="!colors.length && recommend"
|
||||
:list="recommendedColor"
|
||||
:class="[prefixCls + '-picker-colors']"
|
||||
@picker-color="handleSelectColor"></recommend-colors>
|
||||
</div>
|
||||
<div v-if="hue" :class="[prefixCls + '-picker-hue-slider']">
|
||||
<Hue v-model="saturationColors" @change="childChange"></Hue>
|
||||
<div :class="[prefixCls + '-confirm']">
|
||||
<span :class="[prefixCls + '-confirm-color']">{{formatColor}}</span>
|
||||
<i-button
|
||||
ref="clear"
|
||||
:tabindex="0"
|
||||
size="small"
|
||||
type="ghost"
|
||||
@click.native="handleClear"
|
||||
@keydown.enter="handleClear"
|
||||
@keydown.native.esc="closer"
|
||||
>{{t('i.datepicker.clear')}}</i-button>
|
||||
<i-button
|
||||
ref="ok"
|
||||
:tabindex="0"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click.native="handleSuccess"
|
||||
@keydown.native.tab="handleLastTab"
|
||||
@keydown.enter="handleSuccess"
|
||||
@keydown.native.esc="closer"
|
||||
>{{t('i.datepicker.ok')}}</i-button>
|
||||
</div>
|
||||
<div v-if="alpha" :class="[prefixCls + '-picker-alpha-slider']">
|
||||
<Alpha v-model="saturationColors" @change="childChange"></Alpha>
|
||||
</div>
|
||||
<recommend-colors
|
||||
v-if="colors.length"
|
||||
:list="colors"
|
||||
:class="[prefixCls + '-picker-colors']"
|
||||
@picker-color="handleSelectColor"></recommend-colors>
|
||||
<recommend-colors
|
||||
v-if="!colors.length && recommend"
|
||||
:list="recommendedColor"
|
||||
:class="[prefixCls + '-picker-colors']"
|
||||
@picker-color="handleSelectColor"></recommend-colors>
|
||||
</div>
|
||||
<div :class="[prefixCls + '-confirm']">
|
||||
<span :class="[prefixCls + '-confirm-color']">{{ formatColor }}</span>
|
||||
<Confirm @on-pick-success="handleSuccess" @on-pick-clear="handleClear"></Confirm>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</Drop>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import tinycolor from 'tinycolor2';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import vClickOutside from 'v-click-outside-x/index';
|
||||
import TransferDom from '../../directives/transfer-dom';
|
||||
import Drop from '../../components/select/dropdown.vue';
|
||||
import RecommendColors from './recommend-colors.vue';
|
||||
import Saturation from './saturation.vue';
|
||||
import Hue from './hue.vue';
|
||||
import Alpha from './alpha.vue';
|
||||
import Locale from '../../mixins/locale';
|
||||
import {oneOf} from '../../utils/assist';
|
||||
import Emitter from '../../mixins/emitter';
|
||||
import Prefixes from './prefixMixin';
|
||||
import {changeColor, toRGBAString} from './utils';
|
||||
|
||||
import clickoutside from '../../directives/clickoutside';
|
||||
import TransferDom from '../../directives/transfer-dom';
|
||||
export default {
|
||||
name: 'ColorPicker',
|
||||
|
||||
import Drop from '../../components/select/dropdown.vue';
|
||||
import RecommendColors from './recommend-colors.vue';
|
||||
import Confirm from '../date-picker/base/confirm.vue';
|
||||
import Saturation from './saturation.vue';
|
||||
import Hue from './hue.vue';
|
||||
import Alpha from './alpha.vue';
|
||||
components: {Drop, RecommendColors, Saturation, Hue, Alpha},
|
||||
|
||||
import { oneOf } from '../../utils/assist';
|
||||
import Emitter from '../../mixins/emitter';
|
||||
directives: {clickOutside: vClickOutside.directive, TransferDom},
|
||||
|
||||
const prefixCls = 'ivu-color-picker';
|
||||
const inputPrefixCls = 'ivu-input';
|
||||
mixins: [Emitter, Locale, Prefixes],
|
||||
|
||||
function _colorChange (data, oldHue) {
|
||||
data = data === '' ? '#2d8cf0' : data;
|
||||
const alpha = data && data.a;
|
||||
let color;
|
||||
|
||||
// hsl is better than hex between conversions
|
||||
if (data && data.hsl) {
|
||||
color = tinycolor(data.hsl);
|
||||
} else if (data && data.hex && data.hex.length > 0) {
|
||||
color = tinycolor(data.hex);
|
||||
} else {
|
||||
color = tinycolor(data);
|
||||
}
|
||||
|
||||
if (color && (color._a === undefined || color._a === null)) {
|
||||
color.setAlpha(alpha || 1);
|
||||
}
|
||||
|
||||
const hsl = color.toHsl();
|
||||
const hsv = color.toHsv();
|
||||
|
||||
if (hsl.s === 0) {
|
||||
hsv.h = hsl.h = data.h || (data.hsl && data.hsl.h) || oldHue || 0;
|
||||
}
|
||||
|
||||
// when the hsv.v is less than 0.0164 (base on test)
|
||||
// because of possible loss of precision
|
||||
// the result of hue and saturation would be miscalculated
|
||||
if (hsv.v < 0.0164) {
|
||||
hsv.h = data.h || (data.hsv && data.hsv.h) || 0;
|
||||
hsv.s = data.s || (data.hsv && data.hsv.s) || 0;
|
||||
}
|
||||
|
||||
if (hsl.l < 0.01) {
|
||||
hsl.h = data.h || (data.hsl && data.hsl.h) || 0;
|
||||
hsl.s = data.s || (data.hsl && data.hsl.s) || 0;
|
||||
}
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
hue: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
alpha: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
recommend: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
format: {
|
||||
type: String,
|
||||
validator(value) {
|
||||
return oneOf(value, ['hsl', 'hsv', 'hex', 'rgb']);
|
||||
},
|
||||
default: undefined,
|
||||
},
|
||||
colors: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
validator(value) {
|
||||
return oneOf(value, ['small', 'large', 'default']);
|
||||
},
|
||||
default: 'default',
|
||||
},
|
||||
hideDropDown: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
placement: {
|
||||
type: String,
|
||||
validator(value) {
|
||||
return oneOf(value, [
|
||||
'top',
|
||||
'top-start',
|
||||
'top-end',
|
||||
'bottom',
|
||||
'bottom-start',
|
||||
'bottom-end',
|
||||
'left',
|
||||
'left-start',
|
||||
'left-end',
|
||||
'right',
|
||||
'right-start',
|
||||
'right-end',
|
||||
]);
|
||||
},
|
||||
default: 'bottom',
|
||||
},
|
||||
transfer: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
hsl: hsl,
|
||||
hex: color.toHexString().toUpperCase(),
|
||||
rgba: color.toRgb(),
|
||||
hsv: hsv,
|
||||
oldHue: data.h || oldHue || hsl.h,
|
||||
source: data.source,
|
||||
a: data.a || color.getAlpha()
|
||||
val: changeColor(this.value),
|
||||
currentValue: this.value,
|
||||
dragging: false,
|
||||
visible: false,
|
||||
recommendedColor: [
|
||||
'#2d8cf0',
|
||||
'#19be6b',
|
||||
'#ff9900',
|
||||
'#ed3f14',
|
||||
'#00b5ff',
|
||||
'#19c919',
|
||||
'#f9e31c',
|
||||
'#ea1a1a',
|
||||
'#9b1dea',
|
||||
'#00c2b1',
|
||||
'#ac7a33',
|
||||
'#1d35ea',
|
||||
'#8bc34a',
|
||||
'#f16b62',
|
||||
'#ea4ca3',
|
||||
'#0d94aa',
|
||||
'#febd79',
|
||||
'#5d4037',
|
||||
'#00bcd4',
|
||||
'#f06292',
|
||||
'#cddc39',
|
||||
'#607d8b',
|
||||
'#000000',
|
||||
'#ffffff',
|
||||
],
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
export default {
|
||||
name: 'ColorPicker',
|
||||
mixins: [ Emitter ],
|
||||
components: { Drop, Confirm, RecommendColors, Saturation, Hue, Alpha },
|
||||
directives: { clickoutside, TransferDom },
|
||||
props: {
|
||||
value: {
|
||||
type: String
|
||||
computed: {
|
||||
arrowClasses() {
|
||||
return [
|
||||
this.iconPrefixCls,
|
||||
`${this.iconPrefixCls}-arrow-down-b`,
|
||||
`${this.inputPrefixCls}-icon`,
|
||||
`${this.inputPrefixCls}-icon-normal`,
|
||||
];
|
||||
},
|
||||
transition() {
|
||||
return oneOf(this.placement, ['bottom-start', 'bottom', 'bottom-end']) ? 'slide-up' : 'fade';
|
||||
},
|
||||
saturationColors: {
|
||||
get() {
|
||||
return this.val;
|
||||
},
|
||||
hue: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
set(newVal) {
|
||||
this.val = newVal;
|
||||
this.$emit('on-active-change', this.formatColor);
|
||||
},
|
||||
alpha: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
recommend: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
format: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['hsl', 'hsv', 'hex', 'rgb']);
|
||||
}
|
||||
},
|
||||
colors: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
size: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['small', 'large', 'default']);
|
||||
},
|
||||
classes() {
|
||||
return [
|
||||
`${this.prefixCls}`,
|
||||
{
|
||||
[`${this.prefixCls}-transfer`]: this.transfer,
|
||||
},
|
||||
default: 'default'
|
||||
},
|
||||
placement: {
|
||||
validator (value) {
|
||||
return oneOf(value, ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end']);
|
||||
];
|
||||
},
|
||||
wrapClasses() {
|
||||
return [
|
||||
`${this.prefixCls}-rel`,
|
||||
`${this.prefixCls}-${this.size}`,
|
||||
`${this.inputPrefixCls}-wrapper`,
|
||||
`${this.inputPrefixCls}-wrapper-${this.size}`,
|
||||
{
|
||||
[`${this.prefixCls}-disabled`]: this.disabled,
|
||||
},
|
||||
default: 'bottom'
|
||||
},
|
||||
transfer: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
name: {
|
||||
type: String
|
||||
}
|
||||
];
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
val: _colorChange(this.value),
|
||||
currentValue: this.value,
|
||||
prefixCls: prefixCls,
|
||||
visible: false,
|
||||
disableCloseUnderTransfer: false, // transfer 模式下,点击Drop也会触发关闭
|
||||
recommendedColor: [
|
||||
'#2d8cf0',
|
||||
'#19be6b',
|
||||
'#ff9900',
|
||||
'#ed3f14',
|
||||
'#00b5ff',
|
||||
'#19c919',
|
||||
'#f9e31c',
|
||||
'#ea1a1a',
|
||||
'#9b1dea',
|
||||
'#00c2b1',
|
||||
'#ac7a33',
|
||||
'#1d35ea',
|
||||
'#8bc34a',
|
||||
'#f16b62',
|
||||
'#ea4ca3',
|
||||
'#0d94aa',
|
||||
'#febd79',
|
||||
'#5d4037',
|
||||
'#00bcd4',
|
||||
'#f06292',
|
||||
'#cddc39',
|
||||
'#607d8b',
|
||||
'#000000',
|
||||
'#ffffff'
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
transition () {
|
||||
if (this.placement === 'bottom-start' || this.placement === 'bottom' || this.placement === 'bottom-end') {
|
||||
return 'slide-up';
|
||||
} else {
|
||||
return 'fade';
|
||||
}
|
||||
},
|
||||
saturationColors: {
|
||||
get () {
|
||||
return this.val;
|
||||
inputClasses() {
|
||||
return [
|
||||
`${this.prefixCls}-input`,
|
||||
`${this.inputPrefixCls}`,
|
||||
`${this.inputPrefixCls}-${this.size}`,
|
||||
{
|
||||
[`${this.prefixCls}-focused`]: this.visible,
|
||||
[`${this.prefixCls}-disabled`]: this.disabled,
|
||||
},
|
||||
set (newVal) {
|
||||
this.val = newVal;
|
||||
this.$emit('on-active-change', this.formatColor);
|
||||
}
|
||||
},
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`,
|
||||
{
|
||||
[`${prefixCls}-transfer`]: this.transfer
|
||||
}
|
||||
];
|
||||
},
|
||||
wrapClasses () {
|
||||
return [
|
||||
`${prefixCls}-rel`,
|
||||
`${prefixCls}-${this.size}`,
|
||||
`${inputPrefixCls}-wrapper`,
|
||||
`${inputPrefixCls}-wrapper-${this.size}`
|
||||
];
|
||||
},
|
||||
inputClasses () {
|
||||
return [
|
||||
`${prefixCls}-input`,
|
||||
`${inputPrefixCls}`,
|
||||
`${inputPrefixCls}-${this.size}`,
|
||||
{
|
||||
[`${inputPrefixCls}-disabled`]: this.disabled
|
||||
}
|
||||
];
|
||||
},
|
||||
displayedColor () {
|
||||
let color;
|
||||
if (this.visible) {
|
||||
const rgba = this.saturationColors.rgba;
|
||||
color = {
|
||||
r: rgba.r,
|
||||
g: rgba.g,
|
||||
b: rgba.b,
|
||||
a: rgba.a
|
||||
};
|
||||
} else {
|
||||
color = tinycolor(this.value).toRgb();
|
||||
}
|
||||
return `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`;
|
||||
},
|
||||
formatColor () {
|
||||
const value = this.saturationColors;
|
||||
const format = this.format;
|
||||
let color;
|
||||
];
|
||||
},
|
||||
dropClasses() {
|
||||
return [
|
||||
`${this.transferPrefixCls}-no-max-height`,
|
||||
{
|
||||
[`${this.prefixCls}-transfer`]: this.transfer,
|
||||
[`${this.prefixCls}-hide-drop`]: this.hideDropDown,
|
||||
},
|
||||
];
|
||||
},
|
||||
displayedColorStyle() {
|
||||
return {backgroundColor: toRGBAString(this.visible ? this.saturationColors.rgba : tinycolor(this.value).toRgb())};
|
||||
},
|
||||
formatColor() {
|
||||
const {format, saturationColors} = this;
|
||||
|
||||
const rgba = `rgba(${value.rgba.r}, ${value.rgba.g}, ${value.rgba.b}, ${value.rgba.a})`;
|
||||
if (format) {
|
||||
if (format === 'hsl') {
|
||||
color = tinycolor(value.hsl).toHslString();
|
||||
} else if (format === 'hsv') {
|
||||
color = tinycolor(value.hsv).toHsvString();
|
||||
} else if (format === 'hex') {
|
||||
color = value.hex;
|
||||
} else if (format === 'rgb') {
|
||||
color = rgba;
|
||||
}
|
||||
} else if (this.alpha) {
|
||||
color = rgba;
|
||||
} else {
|
||||
color = value.hex;
|
||||
if (format) {
|
||||
if (format === 'hsl') {
|
||||
return tinycolor(saturationColors.hsl).toHslString();
|
||||
}
|
||||
return color;
|
||||
|
||||
if (format === 'hsv') {
|
||||
return tinycolor(saturationColors.hsv).toHsvString();
|
||||
}
|
||||
|
||||
if (format === 'hex') {
|
||||
return saturationColors.hex;
|
||||
}
|
||||
|
||||
if (format === 'rgb') {
|
||||
return toRGBAString(saturationColors.rgba);
|
||||
}
|
||||
} else if (this.alpha) {
|
||||
return toRGBAString(saturationColors.rgba);
|
||||
}
|
||||
|
||||
return saturationColors.hex;
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(newVal) {
|
||||
this.val = changeColor(newVal);
|
||||
},
|
||||
visible(val) {
|
||||
this.val = changeColor(this.value);
|
||||
this.$refs.drop[val ? 'update' : 'destroy']();
|
||||
this.$emit('on-open-change', Boolean(val));
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$on('on-escape-keydown', this.closer);
|
||||
this.$on('on-dragging', this.setDragging);
|
||||
},
|
||||
|
||||
methods: {
|
||||
setDragging(value) {
|
||||
this.dragging = value;
|
||||
},
|
||||
handleClose(event) {
|
||||
if (this.visible) {
|
||||
if (this.dragging || event.type === 'mousedown') {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.transfer) {
|
||||
const {$el} = this.$refs.drop;
|
||||
if ($el === event.target || $el.contains(event.target)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.closer(event);
|
||||
return;
|
||||
}
|
||||
|
||||
this.visible = false;
|
||||
},
|
||||
toggleVisible() {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.visible = !this.visible;
|
||||
this.$refs.input.focus();
|
||||
},
|
||||
childChange(data) {
|
||||
this.colorChange(data);
|
||||
},
|
||||
colorChange(data, oldHue) {
|
||||
this.oldHue = this.saturationColors.hsl.h;
|
||||
this.saturationColors = changeColor(data, oldHue || this.oldHue);
|
||||
},
|
||||
closer(event) {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
this.visible = false;
|
||||
this.$refs.input.focus();
|
||||
},
|
||||
handleButtons(event, value) {
|
||||
this.currentValue = value;
|
||||
this.$emit('input', value);
|
||||
this.$emit('on-change', value);
|
||||
this.dispatch('FormItem', 'on-form-change', value);
|
||||
this.closer(event);
|
||||
},
|
||||
handleSuccess(event) {
|
||||
this.handleButtons(event, this.formatColor);
|
||||
this.$emit('on-pick-success');
|
||||
},
|
||||
handleClear(event) {
|
||||
this.handleButtons(event, '');
|
||||
this.$emit('on-pick-clear');
|
||||
},
|
||||
handleSelectColor(color) {
|
||||
this.val = changeColor(color);
|
||||
this.$emit('on-active-change', this.formatColor);
|
||||
},
|
||||
handleFirstTab(event) {
|
||||
if (event.shiftKey) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.$refs.ok.$el.focus();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (newVal) {
|
||||
this.val = _colorChange(newVal);
|
||||
},
|
||||
visible (val) {
|
||||
this.val = _colorChange(this.value);
|
||||
if (val) {
|
||||
this.$refs.drop.update();
|
||||
} else {
|
||||
this.$refs.drop.destroy();
|
||||
}
|
||||
this.$emit('on-open-change', Boolean(val));
|
||||
handleLastTab(event) {
|
||||
if (!event.shiftKey) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.$refs.saturation.$el.focus();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 开启 transfer 时,点击 Drop 即会关闭,这里不让其关闭
|
||||
handleTransferClick () {
|
||||
if (this.transfer) this.disableCloseUnderTransfer = true;
|
||||
},
|
||||
handleClose () {
|
||||
if (this.disableCloseUnderTransfer) {
|
||||
this.disableCloseUnderTransfer = false;
|
||||
return false;
|
||||
}
|
||||
this.visible = false;
|
||||
},
|
||||
toggleVisible () {
|
||||
this.visible = !this.visible;
|
||||
},
|
||||
childChange (data) {
|
||||
this.colorChange(data);
|
||||
},
|
||||
colorChange (data, oldHue) {
|
||||
this.oldHue = this.saturationColors.hsl.h;
|
||||
this.saturationColors = _colorChange(data, oldHue || this.oldHue);
|
||||
},
|
||||
isValidHex (hex) {
|
||||
return tinycolor(hex).isValid();
|
||||
},
|
||||
simpleCheckForValidColor (data) {
|
||||
const keysToCheck = ['r', 'g', 'b', 'a', 'h', 's', 'l', 'v'];
|
||||
let checked = 0;
|
||||
let passed = 0;
|
||||
|
||||
for (let i = 0; i < keysToCheck.length; i++) {
|
||||
const letter = keysToCheck[i];
|
||||
if (data[letter]) {
|
||||
checked++;
|
||||
if (!isNaN(data[letter])) {
|
||||
passed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (checked === passed) {
|
||||
return data;
|
||||
}
|
||||
},
|
||||
handleSuccess () {
|
||||
const color = this.formatColor;
|
||||
this.currentValue = color;
|
||||
this.$emit('input', color);
|
||||
this.$emit('on-change', color);
|
||||
this.dispatch('FormItem', 'on-form-change', color);
|
||||
this.handleClose();
|
||||
},
|
||||
handleClear () {
|
||||
this.currentValue = '';
|
||||
this.$emit('input', '');
|
||||
this.$emit('on-change', '');
|
||||
this.dispatch('FormItem', 'on-form-change', '');
|
||||
this.handleClose();
|
||||
},
|
||||
handleSelectColor (color) {
|
||||
this.val = _colorChange(color);
|
||||
onTab(event) {
|
||||
if (this.visible) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
onEscape(event) {
|
||||
if (this.visible) {
|
||||
this.closer(event);
|
||||
}
|
||||
},
|
||||
onArrow(event) {
|
||||
if (!this.visible) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.visible = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
7
src/components/color-picker/handleEscapeMixin.js
Normal file
7
src/components/color-picker/handleEscapeMixin.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
export default {
|
||||
methods: {
|
||||
handleEscape(e) {
|
||||
this.dispatch('ColorPicker', 'on-escape-keydown', e);
|
||||
},
|
||||
},
|
||||
};
|
73
src/components/color-picker/hsaMixin.js
Normal file
73
src/components/color-picker/hsaMixin.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
import Emitter from '../../mixins/emitter';
|
||||
import handleEscapeMixin from './handleEscapeMixin';
|
||||
import {getTouches} from './utils';
|
||||
|
||||
export default {
|
||||
mixins: [Emitter, handleEscapeMixin],
|
||||
|
||||
props: {
|
||||
focused: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
value: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.unbindEventListeners();
|
||||
},
|
||||
|
||||
created() {
|
||||
if (this.focused) {
|
||||
setTimeout(() => this.$el.focus(), 1);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleLeft(e) {
|
||||
this.handleSlide(e, this.left, 'left');
|
||||
},
|
||||
handleRight(e) {
|
||||
this.handleSlide(e, this.right, 'right');
|
||||
},
|
||||
handleUp(e) {
|
||||
this.handleSlide(e, this.up, 'up');
|
||||
},
|
||||
handleDown(e) {
|
||||
this.handleSlide(e, this.down, 'down');
|
||||
},
|
||||
handleMouseDown(e) {
|
||||
this.dispatch('ColorPicker', 'on-dragging', true);
|
||||
this.handleChange(e, true);
|
||||
window.addEventListener('mousemove', this.handleChange, false);
|
||||
window.addEventListener('mouseup', this.handleMouseUp, false);
|
||||
},
|
||||
handleMouseUp() {
|
||||
this.unbindEventListeners();
|
||||
},
|
||||
unbindEventListeners() {
|
||||
window.removeEventListener('mousemove', this.handleChange);
|
||||
window.removeEventListener('mouseup', this.handleMouseUp);
|
||||
// This timeout is required so that the click handler for click-outside
|
||||
// has the chance to run before the mouseup removes the dragging flag.
|
||||
setTimeout(() => this.dispatch('ColorPicker', 'on-dragging', false), 1);
|
||||
},
|
||||
getLeft(e) {
|
||||
const {container} = this.$refs;
|
||||
const xOffset = container.getBoundingClientRect().left + window.pageXOffset;
|
||||
const pageX = e.pageX || getTouches(e, 'PageX');
|
||||
|
||||
return pageX - xOffset;
|
||||
},
|
||||
getTop(e) {
|
||||
const {container} = this.$refs;
|
||||
const yOffset = container.getBoundingClientRect().top + window.pageYOffset;
|
||||
const pageY = e.pageY || getTouches(e, 'PageY');
|
||||
|
||||
return pageY - yOffset;
|
||||
},
|
||||
},
|
||||
};
|
|
@ -1,86 +1,95 @@
|
|||
<template>
|
||||
<div class="ivu-color-picker-hue">
|
||||
<div class="ivu-color-picker-hue-container" ref="container"
|
||||
@mousedown="handleMouseDown"
|
||||
@touchmove="handleChange"
|
||||
@touchstart="handleChange">
|
||||
<div class="ivu-color-picker-hue-pointer" :style="{top: 0, left: pointerLeft}">
|
||||
<div class="ivu-color-picker-hue-picker"></div>
|
||||
<div
|
||||
:class="[prefixCls + '-hue']"
|
||||
tabindex="0"
|
||||
@click="$el.focus()"
|
||||
@keydown.esc="handleEscape"
|
||||
@keydown.left="handleLeft"
|
||||
@keydown.right="handleRight"
|
||||
@keydown.up="handleUp"
|
||||
@keydown.down="handleDown"
|
||||
>
|
||||
<div
|
||||
ref="container"
|
||||
:class="[prefixCls + '-hue-container']"
|
||||
@mousedown="handleMouseDown"
|
||||
@touchmove="handleChange"
|
||||
@touchstart="handleChange">
|
||||
<div
|
||||
:style="{top: 0, left: `${percent}%`}"
|
||||
:class="[prefixCls + '-hue-pointer']">
|
||||
<div :class="[prefixCls + '-hue-picker']"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Hue',
|
||||
props: {
|
||||
value: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
oldHue: 0,
|
||||
pullDirection: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
colors () {
|
||||
const h = this.value.hsl.h;
|
||||
if (h !== 0 && h - this.oldHue > 0) this.pullDirection = 'right';
|
||||
if (h !== 0 && h - this.oldHue < 0) this.pullDirection = 'left';
|
||||
this.oldHue = h;
|
||||
import HASMixin from './hsaMixin';
|
||||
import Prefixes from './prefixMixin';
|
||||
import {clamp} from './utils';
|
||||
|
||||
return this.value;
|
||||
},
|
||||
pointerLeft () {
|
||||
if (this.colors.hsl.h === 0 && this.pullDirection === 'right') return '100%';
|
||||
return (this.colors.hsl.h * 100) / 360 + '%';
|
||||
export default {
|
||||
name: 'Hue',
|
||||
|
||||
mixins: [HASMixin, Prefixes],
|
||||
|
||||
data() {
|
||||
const normalStep = 1 / 360 * 25;
|
||||
const jumpStep = 20 * normalStep;
|
||||
|
||||
return {
|
||||
left: -normalStep,
|
||||
right: normalStep,
|
||||
up: jumpStep,
|
||||
down: -jumpStep,
|
||||
powerKey: 'shiftKey',
|
||||
percent: clamp(this.value.hsl.h * 100 / 360, 0, 100),
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
change(percent) {
|
||||
this.percent = clamp(percent, 0, 100);
|
||||
|
||||
const {h, s, l, a} = this.value.hsl;
|
||||
const newHue = clamp(percent / 100 * 360, 0, 360);
|
||||
|
||||
if (h !== newHue) {
|
||||
this.$emit('change', {h: newHue, s, l, a, source: 'hsl'});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange (e, skip) {
|
||||
!skip && e.preventDefault();
|
||||
handleSlide(e, direction) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const container = this.$refs.container;
|
||||
const containerWidth = container.clientWidth;
|
||||
|
||||
const xOffset = container.getBoundingClientRect().left + window.pageXOffset;
|
||||
const pageX = e.pageX || (e.touches ? e.touches[0].pageX : 0);
|
||||
const left = pageX - xOffset;
|
||||
|
||||
let h;
|
||||
let percent;
|
||||
|
||||
if (left < 0) {
|
||||
h = 0;
|
||||
} else if (left > containerWidth) {
|
||||
h = 360;
|
||||
} else {
|
||||
percent = left * 100 / containerWidth;
|
||||
h = (360 * percent / 100);
|
||||
}
|
||||
|
||||
if (this.colors.hsl.h !== h) {
|
||||
this.$emit('change', {
|
||||
h: h,
|
||||
s: this.colors.hsl.s,
|
||||
l: this.colors.hsl.l,
|
||||
a: this.colors.hsl.a,
|
||||
source: 'hsl'
|
||||
});
|
||||
}
|
||||
},
|
||||
handleMouseDown (e) {
|
||||
this.handleChange(e, true);
|
||||
window.addEventListener('mousemove', this.handleChange);
|
||||
window.addEventListener('mouseup', this.handleMouseUp);
|
||||
},
|
||||
handleMouseUp () {
|
||||
this.unbindEventListeners();
|
||||
},
|
||||
unbindEventListeners () {
|
||||
window.removeEventListener('mousemove', this.handleChange);
|
||||
window.removeEventListener('mouseup', this.handleMouseUp);
|
||||
if (e[this.powerKey]) {
|
||||
this.change(direction < 0 ? 0 : 100);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
this.change(this.percent + direction);
|
||||
},
|
||||
handleChange(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const left = this.getLeft(e);
|
||||
|
||||
if (left < 0) {
|
||||
this.change(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const {clientWidth} = this.$refs.container;
|
||||
|
||||
if (left > clientWidth) {
|
||||
this.change(100);
|
||||
return;
|
||||
}
|
||||
|
||||
this.change(left * 100 / clientWidth);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
import ColorPicker from './color-picker.vue';
|
||||
export default ColorPicker;
|
||||
|
||||
export default ColorPicker;
|
||||
|
|
10
src/components/color-picker/prefixMixin.js
Normal file
10
src/components/color-picker/prefixMixin.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
export default {
|
||||
data() {
|
||||
return {
|
||||
prefixCls: 'ivu-color-picker',
|
||||
inputPrefixCls: 'ivu-input',
|
||||
iconPrefixCls: 'ivu-icon',
|
||||
transferPrefixCls: 'ivu-transfer',
|
||||
};
|
||||
},
|
||||
};
|
|
@ -1,20 +1,153 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
ref="reference"
|
||||
tabindex="0"
|
||||
@click="handleClick"
|
||||
@keydown.esc="handleEscape"
|
||||
@keydown.enter="handleEnter"
|
||||
@keydown.left="handleArrow($event, 'x', left)"
|
||||
@keydown.right="handleArrow($event, 'x', right)"
|
||||
@keydown.up="handleArrow($event, 'y', up)"
|
||||
@keydown.down="handleArrow($event, 'y', down)"
|
||||
@blur="blurColor"
|
||||
@focus="focusColor"
|
||||
>
|
||||
<template v-for="(item, index) in list">
|
||||
<span @click="handleClick(index)"><em :style="{'background': item}"></em></span>
|
||||
<br v-if="(index + 1) % 12 === 0 && index !== 0 && (index + 1) !== list.length">
|
||||
<div
|
||||
:key="item + ':' + index"
|
||||
:class="[prefixCls + '-picker-colors-wrapper']">
|
||||
<div :data-color-id="index">
|
||||
<div
|
||||
:style="{background: item}"
|
||||
:class="[prefixCls + '-picker-colors-wrapper-color']"
|
||||
></div>
|
||||
<div
|
||||
:ref="'color-circle-' + index"
|
||||
:class="[prefixCls + '-picker-colors-wrapper-circle', hideClass]"></div>
|
||||
</div>
|
||||
</div>
|
||||
<br v-if="lineBreak(list, index)">
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
list: Array
|
||||
import Emitter from '../../mixins/emitter';
|
||||
import HandleEscapeMixin from './handleEscapeMixin';
|
||||
import Prefixes from './prefixMixin';
|
||||
import {clamp} from './utils';
|
||||
|
||||
export default {
|
||||
name: 'RecommendedColors',
|
||||
|
||||
mixins: [Emitter, HandleEscapeMixin, Prefixes],
|
||||
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default: undefined,
|
||||
},
|
||||
methods: {
|
||||
handleClick (index) {
|
||||
this.$emit('picker-color', this.list[index]);
|
||||
},
|
||||
|
||||
data() {
|
||||
const columns = 12;
|
||||
const rows = Math.ceil(this.list.length / columns);
|
||||
const normalStep = 1;
|
||||
|
||||
return {
|
||||
left: -normalStep,
|
||||
right: normalStep,
|
||||
up: -normalStep,
|
||||
down: normalStep,
|
||||
powerKey: 'shiftKey',
|
||||
grid: {x: 1, y: 1},
|
||||
rows,
|
||||
columns,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
hideClass() {
|
||||
return `${this.prefixCls}-hide`;
|
||||
},
|
||||
linearIndex() {
|
||||
return this.getLinearIndex(this.grid);
|
||||
},
|
||||
currentCircle() {
|
||||
return this.$refs[`color-circle-${this.linearIndex}`][0];
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
getLinearIndex(grid) {
|
||||
return this.columns * (grid.y - 1) + grid.x - 1;
|
||||
},
|
||||
getMaxLimit(axis) {
|
||||
return axis === 'x' ? this.columns : this.rows;
|
||||
},
|
||||
handleArrow(e, axis, direction) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.blurColor();
|
||||
|
||||
const grid = {...this.grid};
|
||||
|
||||
if (e[this.powerKey]) {
|
||||
if (direction < 0) {
|
||||
grid[axis] = 1;
|
||||
} else {
|
||||
grid[axis] = this.getMaxLimit(axis);
|
||||
}
|
||||
} else {
|
||||
grid[axis] += direction;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
const index = this.getLinearIndex(grid);
|
||||
|
||||
if (index >= 0 && index < this.list.length) {
|
||||
this.grid[axis] = clamp(grid[axis], 1, this.getMaxLimit(axis));
|
||||
}
|
||||
|
||||
this.focusColor();
|
||||
},
|
||||
blurColor() {
|
||||
this.currentCircle.classList.add(this.hideClass);
|
||||
},
|
||||
focusColor() {
|
||||
this.currentCircle.classList.remove(this.hideClass);
|
||||
},
|
||||
handleEnter(e) {
|
||||
this.handleClick(e, this.currentCircle);
|
||||
},
|
||||
handleClick(e, circle) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.$refs.reference.focus();
|
||||
|
||||
const target = circle || e.target;
|
||||
const colorId = target.dataset.colorId || target.parentElement.dataset.colorId;
|
||||
|
||||
if (colorId) {
|
||||
this.blurColor();
|
||||
const id = Number(colorId) + 1;
|
||||
this.grid.x = id % this.columns || this.columns;
|
||||
this.grid.y = Math.ceil(id / this.columns);
|
||||
this.focusColor();
|
||||
this.$emit('picker-color', this.list[colorId]);
|
||||
this.$emit('change', {hex: this.list[colorId], source: 'hex'});
|
||||
}
|
||||
},
|
||||
lineBreak(list, index) {
|
||||
if (!index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nextIndex = index + 1;
|
||||
|
||||
return nextIndex < list.length && nextIndex % this.columns === 0;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,98 +1,98 @@
|
|||
<template>
|
||||
<div class="ivu-color-picker-saturation-wrapper">
|
||||
<div
|
||||
:class="[prefixCls + '-saturation-wrapper']"
|
||||
tabindex="0"
|
||||
@keydown.esc="handleEscape"
|
||||
@click="$el.focus()"
|
||||
@keydown.left="handleLeft"
|
||||
@keydown.right="handleRight"
|
||||
@keydown.up="handleUp"
|
||||
@keydown.down="handleDown"
|
||||
>
|
||||
<div
|
||||
class="ivu-color-picker-saturation"
|
||||
:style="{background: bgColor}"
|
||||
ref="container"
|
||||
:style="bgColorStyle"
|
||||
:class="[prefixCls + '-saturation']"
|
||||
@mousedown="handleMouseDown">
|
||||
<div class="ivu-color-picker-saturation--white"></div>
|
||||
<div class="ivu-color-picker-saturation--black"></div>
|
||||
<div class="ivu-color-picker-saturation-pointer" :style="{top: pointerTop, left: pointerLeft}">
|
||||
<div class="ivu-color-picker-saturation-circle"></div>
|
||||
<div :class="[prefixCls + '-saturation--white']"></div>
|
||||
<div :class="[prefixCls + '-saturation--black']"></div>
|
||||
<div
|
||||
:style="pointerStyle"
|
||||
:class="[prefixCls + '-saturation-pointer']">
|
||||
<div :class="[prefixCls + '-saturation-circle']"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import throttle from 'lodash.throttle';
|
||||
|
||||
export default {
|
||||
name: 'Saturation',
|
||||
props: {
|
||||
value: Object
|
||||
<script>
|
||||
import HSAMixin from './hsaMixin';
|
||||
import Prefixes from './prefixMixin';
|
||||
import {clamp, getIncrement} from './utils';
|
||||
|
||||
export default {
|
||||
name: 'Saturation',
|
||||
|
||||
mixins: [HSAMixin, Prefixes],
|
||||
|
||||
data() {
|
||||
const normalStep = 0.01;
|
||||
|
||||
return {
|
||||
left: -normalStep,
|
||||
right: normalStep,
|
||||
up: normalStep,
|
||||
down: -normalStep,
|
||||
multiplier: 10,
|
||||
powerKey: 'shiftKey',
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
bgColorStyle() {
|
||||
return {background: `hsl(${this.value.hsv.h}, 100%, 50%)`};
|
||||
},
|
||||
data () {
|
||||
return {};
|
||||
pointerStyle() {
|
||||
return {top: `${-(this.value.hsv.v * 100) + 1 + 100}%`, left: `${this.value.hsv.s * 100}%`};
|
||||
},
|
||||
computed: {
|
||||
colors () {
|
||||
return this.value;
|
||||
},
|
||||
bgColor () {
|
||||
return `hsl(${this.colors.hsv.h}, 100%, 50%)`;
|
||||
},
|
||||
pointerTop () {
|
||||
return (-(this.colors.hsv.v * 100) + 1) + 100 + '%';
|
||||
},
|
||||
pointerLeft () {
|
||||
return this.colors.hsv.s * 100 + '%';
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
change(h, s, v, a) {
|
||||
this.$emit('change', {h, s, v, a, source: 'hsva'});
|
||||
},
|
||||
methods: {
|
||||
throttle: throttle((fn, data) => {fn(data);}, 20,
|
||||
{
|
||||
'leading': true,
|
||||
'trailing': false
|
||||
}),
|
||||
handleChange (e, skip) {
|
||||
!skip && e.preventDefault();
|
||||
const container = this.$refs.container;
|
||||
const containerWidth = container.clientWidth;
|
||||
const containerHeight = container.clientHeight;
|
||||
const xOffset = container.getBoundingClientRect().left + window.pageXOffset;
|
||||
const yOffset = container.getBoundingClientRect().top + window.pageYOffset;
|
||||
const pageX = e.pageX || (e.touches ? e.touches[0].pageX : 0);
|
||||
const pageY = e.pageY || (e.touches ? e.touches[0].pageY : 0);
|
||||
let left = pageX - xOffset;
|
||||
let top = pageY - yOffset;
|
||||
if (left < 0) {
|
||||
left = 0;
|
||||
} else if (left > containerWidth) {
|
||||
left = containerWidth;
|
||||
} else if (top < 0) {
|
||||
top = 0;
|
||||
} else if (top > containerHeight) {
|
||||
top = containerHeight;
|
||||
}
|
||||
const saturation = left / containerWidth;
|
||||
let bright = -(top / containerHeight) + 1;
|
||||
bright = bright > 0 ? bright : 0;
|
||||
bright = bright > 1 ? 1 : bright;
|
||||
this.throttle(this.onChange, {
|
||||
h: this.colors.hsv.h,
|
||||
s: saturation,
|
||||
v: bright,
|
||||
a: this.colors.hsv.a,
|
||||
source: 'hsva'
|
||||
});
|
||||
},
|
||||
onChange (param) {
|
||||
this.$emit('change', param);
|
||||
},
|
||||
handleMouseDown () {
|
||||
// this.handleChange(e, true)
|
||||
window.addEventListener('mousemove', this.handleChange);
|
||||
window.addEventListener('mouseup', this.handleChange);
|
||||
window.addEventListener('mouseup', this.handleMouseUp);
|
||||
},
|
||||
handleMouseUp () {
|
||||
this.unbindEventListeners();
|
||||
},
|
||||
unbindEventListeners () {
|
||||
window.removeEventListener('mousemove', this.handleChange);
|
||||
window.removeEventListener('mouseup', this.handleChange);
|
||||
window.removeEventListener('mouseup', this.handleMouseUp);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
handleSlide(e, direction, key) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const isPowerKey = e[this.powerKey];
|
||||
const increment = isPowerKey ? direction * this.multiplier : direction;
|
||||
const {h, s, v, a} = this.value.hsv;
|
||||
const saturation = clamp(s + getIncrement(key, ['left', 'right'], increment), 0, 1);
|
||||
const bright = clamp(v + getIncrement(key, ['up', 'down'], increment), 0, 1);
|
||||
|
||||
this.change(h, saturation, bright, a);
|
||||
},
|
||||
handleChange(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const {clientWidth, clientHeight} = this.$refs.container;
|
||||
const left = clamp(this.getLeft(e), 0, clientWidth);
|
||||
const top = clamp(this.getTop(e), 0, clientHeight);
|
||||
const saturation = left / clientWidth;
|
||||
const bright = clamp(1 - top / clientHeight, 0, 1);
|
||||
|
||||
this.change(this.value.hsv.h, saturation, bright, this.value.hsv.a);
|
||||
},
|
||||
handleMouseDown(e) {
|
||||
HSAMixin.methods.handleMouseDown.call(this, e);
|
||||
window.addEventListener('mouseup', this.handleChange, false);
|
||||
},
|
||||
unbindEventListeners(e) {
|
||||
HSAMixin.methods.unbindEventListeners.call(this, e);
|
||||
window.removeEventListener('mouseup', this.handleChange);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
118
src/components/color-picker/utils.js
Normal file
118
src/components/color-picker/utils.js
Normal file
|
@ -0,0 +1,118 @@
|
|||
import tinycolor from 'tinycolor2';
|
||||
import {oneOf} from '../../utils/assist';
|
||||
|
||||
function setAlpha(data, alpha) {
|
||||
const color = tinycolor(data);
|
||||
const {_a} = color;
|
||||
|
||||
if (_a === undefined || _a === null) {
|
||||
color.setAlpha(alpha || 1);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
function getColor(data, colorData) {
|
||||
const alpha = colorData && colorData.a;
|
||||
|
||||
if (colorData) {
|
||||
// hsl is better than hex between conversions
|
||||
if (colorData.hsl) {
|
||||
return setAlpha(colorData.hsl, alpha);
|
||||
}
|
||||
|
||||
if (colorData.hex && colorData.hex.length > 0) {
|
||||
return setAlpha(colorData.hex, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
return setAlpha(colorData, alpha);
|
||||
}
|
||||
|
||||
export function changeColor(data, oldHue) {
|
||||
const colorData = data === '' ? '#2d8cf0' : data;
|
||||
const color = getColor(data, colorData);
|
||||
const hsl = color.toHsl();
|
||||
const hsv = color.toHsv();
|
||||
|
||||
if (hsl.s === 0) {
|
||||
hsl.h = colorData.h || (colorData.hsl && colorData.hsl.h) || oldHue || 0;
|
||||
hsv.h = hsl.h;
|
||||
}
|
||||
|
||||
// when the hsv.v is less than 0.0164 (base on test)
|
||||
// because of possible loss of precision
|
||||
// the result of hue and saturation would be miscalculated
|
||||
if (hsv.v < 0.0164) {
|
||||
hsv.h = colorData.h || (colorData.hsv && colorData.hsv.h) || 0;
|
||||
hsv.s = colorData.s || (colorData.hsv && colorData.hsv.s) || 0;
|
||||
}
|
||||
|
||||
if (hsl.l < 0.01) {
|
||||
hsl.h = colorData.h || (colorData.hsl && colorData.hsl.h) || 0;
|
||||
hsl.s = colorData.s || (colorData.hsl && colorData.hsl.s) || 0;
|
||||
}
|
||||
|
||||
return {
|
||||
hsl,
|
||||
hex: color.toHexString().toUpperCase(),
|
||||
rgba: color.toRgb(),
|
||||
hsv,
|
||||
oldHue: colorData.h || oldHue || hsl.h,
|
||||
source: colorData.source,
|
||||
a: colorData.a || color.getAlpha(),
|
||||
};
|
||||
}
|
||||
|
||||
export function clamp(value, min, max) {
|
||||
if (value < min) {
|
||||
return min;
|
||||
}
|
||||
|
||||
if (value > max) {
|
||||
return max;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
export function getIncrement(key, keys, increment) {
|
||||
return oneOf(key, keys) ? increment : 0;
|
||||
}
|
||||
|
||||
export function getTouches(e, prop) {
|
||||
return e.touches ? e.touches[0][prop] : 0;
|
||||
}
|
||||
|
||||
export function toRGBAString(rgba) {
|
||||
const {r, g, b, a} = rgba;
|
||||
|
||||
return `rgba(${[r, g, b, a].join(',')})`;
|
||||
}
|
||||
|
||||
export function isValidHex(hex) {
|
||||
return tinycolor(hex).isValid();
|
||||
}
|
||||
|
||||
function checkIteratee(data, counts, letter) {
|
||||
let {checked, passed} = counts;
|
||||
const value = data[letter];
|
||||
|
||||
if (value) {
|
||||
checked += 1;
|
||||
|
||||
if (Number.isFinite(value)) {
|
||||
passed += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return {checked, passed};
|
||||
}
|
||||
|
||||
const keysToCheck = ['r', 'g', 'b', 'a', 'h', 's', 'l', 'v'];
|
||||
|
||||
export function simpleCheckForValidColor(data) {
|
||||
const results = keysToCheck.reduce(checkIteratee.bind(null, data), {checked: 0, passed: 0});
|
||||
|
||||
return results.checked === results.passed ? data : undefined;
|
||||
}
|
|
@ -1,103 +1,174 @@
|
|||
@color-picker-prefix-cls: ~"@{css-prefix}color-picker";
|
||||
@color-picker-prefix-cls: ~'@{css-prefix}color-picker';
|
||||
|
||||
.@{color-picker-prefix-cls} {
|
||||
display: inline-block;
|
||||
&-hide {
|
||||
display: none;
|
||||
&-drop {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
&-disabled {
|
||||
background-color: @input-disabled-bg;
|
||||
opacity: 1;
|
||||
cursor: @cursor-disabled;
|
||||
color: #ccc;
|
||||
}
|
||||
& > div:first-child:hover {
|
||||
.ivu-input {
|
||||
border-color: @input-hover-border-color;
|
||||
}
|
||||
}
|
||||
& > div:first-child.@{color-picker-prefix-cls}-disabled:hover {
|
||||
.ivu-input {
|
||||
border-color: tint(@input-border-color, 20%);
|
||||
}
|
||||
}
|
||||
& .@{select-dropdown-prefix-cls} {
|
||||
padding: 0;
|
||||
}
|
||||
&-rel{
|
||||
&-focused {
|
||||
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||
}
|
||||
&-rel {
|
||||
line-height: 0;
|
||||
}
|
||||
&-color{
|
||||
&-color {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
||||
border-radius: 2px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
div{
|
||||
div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-shadow: inset 0 0 0 1px rgba(0,0,0,.15);
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
|
||||
border-radius: 2px;
|
||||
}
|
||||
&-empty{
|
||||
&-empty {
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
i{
|
||||
i {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
&-focused {
|
||||
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||
}
|
||||
}
|
||||
&-large &-color{
|
||||
&-large &-color {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
top: 1px;
|
||||
&-empty{
|
||||
i{
|
||||
&-empty {
|
||||
i {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-small &-color{
|
||||
&-small &-color {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
top: 3px;
|
||||
&-empty{
|
||||
i{
|
||||
&-empty {
|
||||
i {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-picker{
|
||||
&-wrapper{
|
||||
&-picker {
|
||||
&-wrapper {
|
||||
padding: 8px 8px 0;
|
||||
}
|
||||
&-panel{
|
||||
&-panel {
|
||||
width: 240px;
|
||||
margin: 0 auto;
|
||||
box-sizing: initial;
|
||||
position: relative;
|
||||
}
|
||||
&-hue-slider, &-alpha-slider{
|
||||
&-hue-slider,
|
||||
&-alpha-slider {
|
||||
height: 10px;
|
||||
margin-top: 8px;
|
||||
position: relative;
|
||||
}
|
||||
&-colors{
|
||||
&-colors {
|
||||
margin-top: 8px;
|
||||
overflow: hidden;
|
||||
span{
|
||||
display: inline-block;
|
||||
outline: 0;
|
||||
border: 1px solid @input-border-color;
|
||||
transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out;
|
||||
&:hover {
|
||||
border: 1px solid @input-hover-border-color;
|
||||
}
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||
}
|
||||
&-wrapper {
|
||||
display: inline;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
float: left;
|
||||
em{
|
||||
position: relative;
|
||||
&-color {
|
||||
outline: 0;
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 2px;
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
box-shadow: inset 0 0 0 1px rgba(0,0,0,.15);
|
||||
border: 1px solid @input-border-color;
|
||||
transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out;
|
||||
&:hover {
|
||||
border: 1px solid @input-hover-border-color;
|
||||
}
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||
}
|
||||
}
|
||||
&-circle {
|
||||
cursor: pointer;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
position: absolute;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
.@{picker-prefix-cls}-confirm{
|
||||
.@{picker-prefix-cls}-confirm {
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&-saturation{
|
||||
&-wrapper{
|
||||
&-saturation {
|
||||
&-wrapper {
|
||||
width: 100%;
|
||||
padding-bottom: 75%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
outline: 0;
|
||||
border: 1px solid @input-border-color;
|
||||
box-shadow: @shadow-base;
|
||||
transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out;
|
||||
&:hover {
|
||||
border: 1px solid @input-hover-border-color;
|
||||
}
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||
}
|
||||
}
|
||||
&, &--white, &--black{
|
||||
&,
|
||||
&--white,
|
||||
&--black {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -105,26 +176,26 @@
|
|||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
&--white{
|
||||
background: linear-gradient(to right, #fff, rgba(255,255,255,0));
|
||||
&--white {
|
||||
background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
|
||||
}
|
||||
&--black{
|
||||
background: linear-gradient(to top, #000, rgba(0,0,0,0));
|
||||
&--black {
|
||||
background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
|
||||
}
|
||||
&-pointer{
|
||||
&-pointer {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
}
|
||||
&-circle{
|
||||
&-circle {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
box-shadow: 0 0 0 1.5px #fff, inset 0 0 1px 1px rgba(0,0,0,.3), 0 0 1px 2px rgba(0,0,0,.4);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
&-hue{
|
||||
&-hue {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
@ -132,35 +203,55 @@
|
|||
left: 0;
|
||||
border-radius: 2px;
|
||||
background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
|
||||
&-container{
|
||||
outline: 0;
|
||||
border: 1px solid @input-border-color;
|
||||
box-shadow: @shadow-base;
|
||||
transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out;
|
||||
&:hover {
|
||||
border: 1px solid @input-hover-border-color;
|
||||
}
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||
}
|
||||
&-container {
|
||||
cursor: pointer;
|
||||
margin: 0 2px;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
&-pointer{
|
||||
&-pointer {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
}
|
||||
&-picker{
|
||||
&-picker {
|
||||
cursor: pointer;
|
||||
margin-top: 1px;
|
||||
width: 4px;
|
||||
border-radius: 1px;
|
||||
height: 8px;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, .6);
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
|
||||
background: #fff;
|
||||
transform: translateX(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
&-alpha{
|
||||
&-alpha {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
&-checkboard-wrap{
|
||||
outline: 0;
|
||||
border: 1px solid @input-border-color;
|
||||
box-shadow: @shadow-base;
|
||||
transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out;
|
||||
&:hover {
|
||||
border: 1px solid @input-hover-border-color;
|
||||
}
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%);
|
||||
}
|
||||
&-checkboard-wrap {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
@ -169,7 +260,7 @@
|
|||
overflow: hidden;
|
||||
border-radius: 2px;
|
||||
}
|
||||
&-checkerboard{
|
||||
&-checkerboard {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
@ -177,7 +268,7 @@
|
|||
left: 0;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
||||
}
|
||||
&-gradient{
|
||||
&-gradient {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
@ -185,32 +276,37 @@
|
|||
left: 0;
|
||||
border-radius: 2px;
|
||||
}
|
||||
&-container{
|
||||
&-container {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
height: 100%;
|
||||
margin: 0 3px;
|
||||
}
|
||||
&-pointer{
|
||||
&-pointer {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
}
|
||||
&-picker{
|
||||
&-picker {
|
||||
cursor: pointer;
|
||||
width: 4px;
|
||||
border-radius: 1px;
|
||||
height: 8px;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, .6);
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
|
||||
background: #fff;
|
||||
margin-top: 1px;
|
||||
transform: translateX(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
&-confirm{
|
||||
&-confirm {
|
||||
margin-top: 8px;
|
||||
position: relative;
|
||||
&-color{
|
||||
border-top: 1px solid @border-color-split;
|
||||
text-align: right;
|
||||
padding: 8px;
|
||||
clear: both;
|
||||
&-color {
|
||||
position: absolute;
|
||||
top: 11px;
|
||||
left: 8px;
|
||||
|
|
|
@ -266,4 +266,4 @@
|
|||
&-append {
|
||||
border-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue