|
|
|
import PropTypes from '../_util/vue-types';
|
|
|
|
import { ConfigConsumerProps } from '../config-provider';
|
|
|
|
import BaseMixin from '../_util/BaseMixin';
|
|
|
|
import Pickr from '@simonwep/pickr/dist/pickr.es5.min';
|
|
|
|
import Icon from '../icon';
|
|
|
|
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
|
|
|
import enUS from './locale/en_US';
|
|
|
|
import debounce from 'lodash-es/debounce';
|
|
|
|
|
|
|
|
import { getOptionProps, findDOMNode } from '../_util/props-util';
|
|
|
|
let colors = '#194d33';
|
|
|
|
export default {
|
|
|
|
name: 'AColorPicker',
|
|
|
|
mixins: [BaseMixin],
|
|
|
|
model: {
|
|
|
|
prop: 'value',
|
|
|
|
event: 'change.value', //为了支持v-model直接返回颜色字符串 所以用了自定义的事件,与pickr自带change事件进行区分
|
|
|
|
},
|
|
|
|
props: {
|
|
|
|
prefixCls: PropTypes.string,
|
|
|
|
defaultValue: PropTypes.string, //默认值
|
|
|
|
config: PropTypes.object, //pickr配置
|
|
|
|
value: PropTypes.string, //颜色值
|
|
|
|
locale: PropTypes.object, //双语包
|
|
|
|
colorRounded: PropTypes.number, //颜色数值保留几位小数
|
|
|
|
size: PropTypes.oneOf(['default', 'small', 'large']).def('default'), //尺寸
|
|
|
|
getPopupContainer: PropTypes.func, //指定渲染容器
|
|
|
|
disabled: PropTypes.bool.def(false), //是否禁用
|
|
|
|
format: PropTypes.string, //颜色格式设置
|
|
|
|
alpha: PropTypes.bool.def(false), //是否开启透明通道
|
|
|
|
hue: PropTypes.bool.def(true), //是否开启色彩预选
|
|
|
|
},
|
|
|
|
inject: {
|
|
|
|
configProvider: { default: () => ConfigConsumerProps },
|
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
colors,
|
|
|
|
myOpen: false,
|
|
|
|
pickr: null,
|
|
|
|
i18n: enUS,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
'configProvider.locale.ColorPicker': {
|
|
|
|
handler(val) {
|
|
|
|
if (this.locale) return;
|
|
|
|
this.i18n = val;
|
|
|
|
this.reInitialize();
|
|
|
|
},
|
|
|
|
},
|
|
|
|
locale(val) {
|
|
|
|
this.i18n = val.ColorPicker || val.lang;
|
|
|
|
this.reInitialize();
|
|
|
|
},
|
|
|
|
value(val) {
|
|
|
|
this.setColor(val);
|
|
|
|
},
|
|
|
|
disabled(val) {
|
|
|
|
this.pickr[val ? 'disable' : 'enable']();
|
|
|
|
},
|
|
|
|
config: {
|
|
|
|
handler() {
|
|
|
|
this.reInitialize();
|
|
|
|
},
|
|
|
|
deep: true,
|
|
|
|
},
|
|
|
|
format(val) {
|
|
|
|
const type = val.toLocaleUpperCase();
|
|
|
|
let res = this.pickr.setColorRepresentation(type);
|
|
|
|
if (res) {
|
|
|
|
this.pickr.applyColor();
|
|
|
|
} else {
|
|
|
|
throw new TypeError('format was invalid');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
mounted() {
|
|
|
|
if (this.locale) {
|
|
|
|
this.i18n = this.locale.ColorPicker || this.locale.lang;
|
|
|
|
}
|
|
|
|
this.createPickr();
|
|
|
|
this.eventsBinding();
|
|
|
|
},
|
|
|
|
destroyed() {
|
|
|
|
this.pickr.destroyAndRemove();
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
reInitialize() {
|
|
|
|
this.pickr.destroyAndRemove();
|
|
|
|
const dom = document.createElement('div');
|
|
|
|
dom.id = 'color-picker' + this._uid;
|
|
|
|
const box = findDOMNode(this).querySelector('#color-picker-box' + this._uid);
|
|
|
|
box.appendChild(dom);
|
|
|
|
this.createPickr();
|
|
|
|
this.eventsBinding();
|
|
|
|
},
|
|
|
|
setColor: debounce(function(val) {
|
|
|
|
this.pickr.setColor(val);
|
|
|
|
}, 1000),
|
|
|
|
eventsBinding() {
|
|
|
|
const pickrEvents = [
|
|
|
|
'init',
|
|
|
|
'hide',
|
|
|
|
'show',
|
|
|
|
'save',
|
|
|
|
'clear',
|
|
|
|
'change',
|
|
|
|
'changestop',
|
|
|
|
'cancel',
|
|
|
|
'swatchselect',
|
|
|
|
];
|
|
|
|
Object.keys(this.$listeners).forEach(event => {
|
|
|
|
pickrEvents.includes(event) && this.pickr.on(event, this.$listeners[event]);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
createPickr() {
|
|
|
|
const { getPopupContainer } = getOptionProps(this);
|
|
|
|
const { getPopupContainer: getContextPopupContainer } = this.configProvider;
|
|
|
|
const container = getPopupContainer || getContextPopupContainer;
|
|
|
|
this.pickr = Pickr.create(
|
|
|
|
Object.assign(
|
|
|
|
{
|
|
|
|
el: '#color-picker' + this._uid,
|
|
|
|
container: (container && container(findDOMNode(this))) || document.body,
|
|
|
|
theme: 'monolith', // or 'monolith', or 'nano'
|
|
|
|
default: this.value || this.defaultValue || null, // 有默认颜色pickr才可以获取到_representation
|
|
|
|
components: {
|
|
|
|
// Main components
|
|
|
|
preview: true,
|
|
|
|
opacity: this.alpha,
|
|
|
|
hue: this.hue,
|
|
|
|
// Input / output Options
|
|
|
|
interaction: {
|
|
|
|
hex: true,
|
|
|
|
rgba: true,
|
|
|
|
input: true,
|
|
|
|
clear: true,
|
|
|
|
save: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
this.config,
|
|
|
|
{ i18n: this.i18n },
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.on('save', (color, instance) => {
|
|
|
|
if (color) {
|
|
|
|
let _representation = instance._representation || 'HEXA';
|
|
|
|
color = color['to' + _representation]().toString(this.colorRounded || 0);
|
|
|
|
}
|
|
|
|
this.$emit('change.value', color || '');
|
|
|
|
})
|
|
|
|
.on('hide', () => {
|
|
|
|
this.setState({ myOpen: false });
|
|
|
|
});
|
|
|
|
},
|
|
|
|
handleOpenChange() {
|
|
|
|
const open = !this.myOpen;
|
|
|
|
this.setState({ myOpen: open });
|
|
|
|
this.pickr[open ? 'show' : 'hide']();
|
|
|
|
this.$emit('openChange', open);
|
|
|
|
},
|
|
|
|
getDefaultLocale() {
|
|
|
|
const result = {
|
|
|
|
...enUS,
|
|
|
|
...this.$props.locale,
|
|
|
|
};
|
|
|
|
result.lang = {
|
|
|
|
...result.lang,
|
|
|
|
...(this.$props.locale || {}).lang,
|
|
|
|
};
|
|
|
|
return result;
|
|
|
|
},
|
|
|
|
renderColorPicker() {
|
|
|
|
const { prefixCls: customizePrefixCls } = this.$props;
|
|
|
|
const { getPrefixCls } = this.configProvider;
|
|
|
|
const prefixCls = getPrefixCls('color-picker', customizePrefixCls);
|
|
|
|
const { disabled } = getOptionProps(this);
|
|
|
|
const classString = {
|
|
|
|
[prefixCls]: true,
|
|
|
|
[`${prefixCls}-open`]: this.myOpen,
|
|
|
|
[`${prefixCls}-lg`]: this.size === 'large',
|
|
|
|
[`${prefixCls}-sm`]: this.size === 'small',
|
|
|
|
[`${prefixCls}-disabled`]: this.disabled,
|
|
|
|
};
|
|
|
|
return (
|
|
|
|
<div class={classString} tabindex={disabled ? -1 : 0} onClick={this.handleOpenChange}>
|
|
|
|
<div class={`${prefixCls}-selection`}>
|
|
|
|
<div id={'color-picker-box' + this._uid}>
|
|
|
|
<div id={'color-picker' + this._uid}></div>
|
|
|
|
</div>
|
|
|
|
<Icon type="down" class={`${prefixCls}-icon`} />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<LocaleReceiver
|
|
|
|
componentName="ColorPicker"
|
|
|
|
defaultLocale={this.getDefaultLocale}
|
|
|
|
scopedSlots={{ default: this.renderColorPicker }}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
},
|
|
|
|
};
|