<template>
|
<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">
|
<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>
|
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,
|
},
|
},
|
|
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;
|
}
|
|
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>
|