Skip to content

Commit 71bf529

Browse files
committed
2 parents 1cf4e29 + 71e5f59 commit 71bf529

File tree

21 files changed

+1032
-19
lines changed

21 files changed

+1032
-19
lines changed
+208
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
import PropTypes from '../_util/vue-types';
2+
import { ConfigConsumerProps } from '../config-provider';
3+
import BaseMixin from '../_util/BaseMixin';
4+
import Pickr from '@simonwep/pickr/dist/pickr.es5.min';
5+
import Icon from '../icon';
6+
import LocaleReceiver from '../locale-provider/LocaleReceiver';
7+
import enUS from './locale/en_US';
8+
import debounce from 'lodash/debounce';
9+
10+
import { getOptionProps } from '../_util/props-util';
11+
let colors = '#194d33';
12+
export default {
13+
name: 'AColorPicker',
14+
mixins: [BaseMixin],
15+
model: {
16+
prop: 'value',
17+
event: 'change.value', //为了支持v-model直接返回颜色字符串 所以用了自定义的事件,与pickr自带change事件进行区分
18+
},
19+
props: {
20+
prefixCls: PropTypes.string,
21+
defaultValue: PropTypes.string, //默认值
22+
config: PropTypes.object, //pickr配置
23+
value: PropTypes.string, //颜色值
24+
locale: PropTypes.object, //双语包
25+
colorRounded: PropTypes.number, //颜色数值保留几位小数
26+
size: PropTypes.oneOf(['default', 'small', 'large']).def('default'), //尺寸
27+
getPopupContainer: PropTypes.func, //指定渲染容器
28+
disabled: PropTypes.bool.def(false), //是否禁用
29+
format: PropTypes.string, //颜色格式设置
30+
alpha: PropTypes.bool.def(false), //是否开启透明通道
31+
hue: PropTypes.bool.def(true), //是否开启色彩预选
32+
},
33+
inject: {
34+
configProvider: { default: () => ConfigConsumerProps },
35+
},
36+
data() {
37+
return {
38+
colors,
39+
myOpen: false,
40+
pickr: null,
41+
i18n: enUS,
42+
};
43+
},
44+
watch: {
45+
'configProvider.locale.ColorPicker': {
46+
handler(val) {
47+
if (this.locale) return;
48+
this.i18n = val;
49+
this.reInitialize();
50+
},
51+
},
52+
locale(val) {
53+
this.i18n = val.ColorPicker || val.lang;
54+
this.reInitialize();
55+
},
56+
value(val) {
57+
this.setColor(val);
58+
},
59+
disabled(val) {
60+
this.pickr[val ? 'disable' : 'enable']();
61+
},
62+
config: {
63+
handler() {
64+
this.reInitialize();
65+
},
66+
deep: true,
67+
},
68+
format(val) {
69+
const type = val.toLocaleUpperCase();
70+
let res = this.pickr.setColorRepresentation(type);
71+
if (res) {
72+
this.pickr.applyColor();
73+
} else {
74+
throw new TypeError('format was invalid');
75+
}
76+
},
77+
},
78+
mounted() {
79+
if (this.locale) {
80+
this.i18n = this.locale.ColorPicker || this.locale.lang;
81+
}
82+
this.createPickr();
83+
this.eventsBinding();
84+
},
85+
destroyed() {
86+
this.pickr.destroyAndRemove();
87+
},
88+
methods: {
89+
reInitialize() {
90+
this.pickr.destroyAndRemove();
91+
const dom = document.createElement('div');
92+
dom.id = 'color-picker' + this._uid;
93+
const box = this.$el.querySelector('#color-picker-box' + this._uid);
94+
box.appendChild(dom);
95+
this.createPickr();
96+
this.eventsBinding();
97+
},
98+
setColor: debounce(function(val) {
99+
this.pickr.setColor(val);
100+
}, 1000),
101+
eventsBinding() {
102+
const pickrEvents = [
103+
'init',
104+
'hide',
105+
'show',
106+
'save',
107+
'clear',
108+
'change',
109+
'changestop',
110+
'cancel',
111+
'swatchselect',
112+
];
113+
Object.keys(this.$listeners).forEach(event => {
114+
pickrEvents.includes(event) && this.pickr.on(event, this.$listeners[event]);
115+
});
116+
},
117+
createPickr() {
118+
const { getPopupContainer } = getOptionProps(this);
119+
const { getPopupContainer: getContextPopupContainer } = this.configProvider;
120+
const container = getPopupContainer || getContextPopupContainer;
121+
this.pickr = Pickr.create(
122+
Object.assign(
123+
{
124+
el: '#color-picker' + this._uid,
125+
container: (container && container(this.$el)) || document.body,
126+
theme: 'monolith', // or 'monolith', or 'nano'
127+
default: this.value || this.defaultValue || null, // 有默认颜色pickr才可以获取到_representation
128+
components: {
129+
// Main components
130+
preview: true,
131+
opacity: this.alpha,
132+
hue: this.hue,
133+
// Input / output Options
134+
interaction: {
135+
hex: true,
136+
rgba: true,
137+
input: true,
138+
clear: true,
139+
save: true,
140+
},
141+
},
142+
},
143+
this.config,
144+
{ i18n: this.i18n },
145+
),
146+
)
147+
.on('save', (color, instance) => {
148+
if (color) {
149+
let _representation = instance._representation || 'HEXA';
150+
color = color['to' + _representation]().toString(this.colorRounded || 0);
151+
}
152+
this.$emit('change.value', color || '');
153+
})
154+
.on('hide', () => {
155+
this.setState({ myOpen: false });
156+
});
157+
},
158+
handleOpenChange() {
159+
const open = !this.myOpen;
160+
this.setState({ myOpen: open });
161+
this.pickr[open ? 'show' : 'hide']();
162+
this.$emit('openChange', open);
163+
},
164+
getDefaultLocale() {
165+
const result = {
166+
...enUS,
167+
...this.$props.locale,
168+
};
169+
result.lang = {
170+
...result.lang,
171+
...(this.$props.locale || {}).lang,
172+
};
173+
return result;
174+
},
175+
renderColorPicker() {
176+
const { prefixCls: customizePrefixCls } = this.$props;
177+
const { getPrefixCls } = this.configProvider;
178+
const prefixCls = getPrefixCls('color-picker', customizePrefixCls);
179+
const { disabled } = getOptionProps(this);
180+
const classString = {
181+
[`${prefixCls}-box`]: true,
182+
[`${prefixCls}-open`]: this.myOpen,
183+
[`${prefixCls}-lg`]: this.size === 'large',
184+
[`${prefixCls}-sm`]: this.size === 'small',
185+
[`${prefixCls}-disabled`]: this.disabled,
186+
};
187+
return (
188+
<div class={classString} tabIndex={disabled ? -1 : 0} onClick={this.handleOpenChange}>
189+
<div class={`${prefixCls}-selection`}>
190+
<div id={'color-picker-box' + this._uid}>
191+
<div id={'color-picker' + this._uid}></div>
192+
</div>
193+
<Icon type="down" class={`${prefixCls}-icon`} />
194+
</div>
195+
</div>
196+
);
197+
},
198+
},
199+
render() {
200+
return (
201+
<LocaleReceiver
202+
componentName="ColorPicker"
203+
defaultLocale={this.getDefaultLocale}
204+
scopedSlots={{ default: this.renderColorPicker }}
205+
/>
206+
);
207+
},
208+
};

0 commit comments

Comments
 (0)