Commit f2bcd4adaffe9040123e3e55cc4a912a438e3925
1 parent
b924d14d
Color keyboard control
Showing
13 changed files
with
1303 additions
and
642 deletions
Show diff stats
examples/routers/color-picker.vue
1 | 1 | <template> |
2 | 2 | <div style="margin: 100px;"> |
3 | - {{ color }} | |
3 | + {{color}} | |
4 | 4 | <!--<Input placeholder="请输入..." size="large" style="width: 50px;"></Input>--> |
5 | - <color-picker @on-change="c1" @on-active-change="c2" v-model="color" placement="bottom-start" size="large"></color-picker> | |
6 | - <Date-picker transfer type="date" placeholder="选择日期" style="width: 200px"></Date-picker> | |
7 | - <color-picker :transfer="true" ref="xxx" v-model="color" format="rgb" alpha :recommend="true"></color-picker> | |
8 | - <color-picker v-model="color2" format="hsv" :alpha="true" :recommend="false"></color-picker> | |
5 | + <color-picker | |
6 | + v-model="color" | |
7 | + placement="bottom-start" | |
8 | + size="large" | |
9 | + @on-change="c1" | |
10 | + @on-active-change="c2"></color-picker> | |
11 | + <Date-picker | |
12 | + transfer | |
13 | + type="date" | |
14 | + placeholder="选择日期" | |
15 | + style="width: 200px"></Date-picker> | |
16 | + <color-picker | |
17 | + ref="xxx" | |
18 | + :transfer="true" | |
19 | + v-model="color" | |
20 | + :recommend="true" | |
21 | + format="rgb" | |
22 | + alpha | |
23 | + @on-change="onChange" | |
24 | + @on-active-change="onActiveChange"></color-picker> | |
25 | + <color-picker | |
26 | + v-model="color2" | |
27 | + :alpha="true" | |
28 | + :recommend="false" | |
29 | + format="hsv"></color-picker> | |
9 | 30 | <!--<Date-picker type="date" placeholder="选择日期" style="width: 200px"></Date-picker>--> |
10 | - <color-picker v-model="color" placement="bottom-start" size="small"></color-picker> | |
11 | - <Date-picker type="date" placeholder="选择日期" size="small" style="width: 200px"></Date-picker> | |
31 | + <color-picker | |
32 | + v-model="color" | |
33 | + placement="bottom-start" | |
34 | + size="small"></color-picker> | |
35 | + <Date-picker | |
36 | + type="date" | |
37 | + placeholder="选择日期" | |
38 | + size="small" | |
39 | + style="width: 200px"></Date-picker> | |
40 | + <color-picker | |
41 | + ref="yyy" | |
42 | + :colors="colors" | |
43 | + v-model="color" | |
44 | + transfer | |
45 | + format="rgb" | |
46 | + alpha></color-picker> | |
12 | 47 | <Button @click="setColor">set color</Button> |
13 | 48 | |
14 | 49 | <br><br><br><br> |
15 | 50 | {{openState}} |
16 | - <ColorPicker v-model="color7" :hue="false" @on-open-change="onOpenChange"></ColorPicker> | |
51 | + <ColorPicker | |
52 | + v-model="color7" | |
53 | + :hue="false" | |
54 | + @on-open-change="onOpenChange"></ColorPicker> | |
55 | + <ColorPicker | |
56 | + v-model="color7" | |
57 | + :hue="false" | |
58 | + :hide-drop-down="hideDropDown" | |
59 | + transfer | |
60 | + @on-open-change="onOpenChange"></ColorPicker> | |
61 | + | |
62 | + <br><br><br><br> | |
63 | + <ColorPicker | |
64 | + v-model="color7" | |
65 | + disabled></ColorPicker> | |
17 | 66 | </div> |
18 | 67 | </template> |
68 | + | |
19 | 69 | <script> |
20 | - export default { | |
21 | - props: {}, | |
22 | - data () { | |
23 | - return { | |
24 | - color: 'rgba(12,34,255,.85)', | |
25 | - color2: '', | |
26 | - color7: '#19be6b', | |
27 | - openState: false, | |
28 | - }; | |
70 | +export default { | |
71 | + props: {}, | |
72 | + | |
73 | + data() { | |
74 | + return { | |
75 | + color: 'rgba(12,34,255,.85)', | |
76 | + color2: '', | |
77 | + color7: '#19be6b', | |
78 | + openState: false, | |
79 | + colors: [ | |
80 | + '#2d8cf0', | |
81 | + '#19be6b', | |
82 | + '#ff9900', | |
83 | + '#ed3f14', | |
84 | + '#00b5ff', | |
85 | + '#19c919', | |
86 | + '#f9e31c', | |
87 | + '#ea1a1a', | |
88 | + '#9b1dea', | |
89 | + '#00c2b1', | |
90 | + '#ac7a33', | |
91 | + '#1d35ea', | |
92 | + '#8bc34a', | |
93 | + '#f16b62', | |
94 | + '#ea4ca3', | |
95 | + '#0d94aa', | |
96 | + '#febd79', | |
97 | + '#5d4037', | |
98 | + '#00bcd4', | |
99 | + '#f06292', | |
100 | + '#cddc39', | |
101 | + '#607d8b', | |
102 | + '#000000', | |
103 | + '#ffffff', | |
104 | + '#2d8cf0', | |
105 | + '#19be6b', | |
106 | + '#ff9900', | |
107 | + '#ed3f14', | |
108 | + '#00b5ff', | |
109 | + '#19c919', | |
110 | + '#f9e31c', | |
111 | + '#ea1a1a', | |
112 | + '#9b1dea', | |
113 | + '#00c2b1', | |
114 | + '#ac7a33', | |
115 | + '#1d35ea', | |
116 | + '#8bc34a', | |
117 | + '#f16b62', | |
118 | + '#ea4ca3', | |
119 | + '#0d94aa', | |
120 | + '#febd79', | |
121 | + '#5d4037', | |
122 | + ], | |
123 | + hideDropDown: false, | |
124 | + }; | |
125 | + }, | |
126 | + | |
127 | + computed: {}, | |
128 | + | |
129 | + mounted() { | |
130 | + setInterval(this.toggleShowHide, 2000); | |
131 | + }, | |
132 | + | |
133 | + methods: { | |
134 | + setColor() { | |
135 | + this.color = '#26bc77'; | |
136 | + }, | |
137 | + c1(d) { | |
138 | + console.log(d); | |
139 | + }, | |
140 | + c2(d) { | |
141 | + console.log(d); | |
142 | + }, | |
143 | + onOpenChange(state) { | |
144 | + this.openState = state; | |
145 | + }, | |
146 | + onChange(d) { | |
147 | + console.log(d); | |
148 | + }, | |
149 | + onActiveChange(d) { | |
150 | + console.log(d); | |
151 | + }, | |
152 | + toggleShowHide() { | |
153 | + this.hideDropDown = !this.hideDropDown; | |
29 | 154 | }, |
30 | - computed: {}, | |
31 | - methods: { | |
32 | - setColor () { | |
33 | - this.color = '#26bc77'; | |
34 | - }, | |
35 | - c1 (d) { | |
36 | - console.log(d); | |
37 | - }, | |
38 | - c2 (d) { | |
39 | - console.log(d); | |
40 | - }, | |
41 | - onOpenChange(state){ | |
42 | - this.openState = state; | |
43 | - } | |
44 | - } | |
45 | - }; | |
155 | + }, | |
156 | +}; | |
46 | 157 | </script> | ... | ... |
src/components/color-picker/alpha.vue
1 | 1 | <template> |
2 | - <div class="ivu-color-picker-alpha"> | |
3 | - <div class="ivu-color-picker-alpha-checkboard-wrap"> | |
4 | - <div class="ivu-color-picker-alpha-checkerboard"></div> | |
2 | + <div | |
3 | + :class="[prefixCls + '-alpha']" | |
4 | + tabindex="0" | |
5 | + @click="$el.focus()" | |
6 | + @keydown.esc="handleEscape" | |
7 | + @keydown.left="handleLeft" | |
8 | + @keydown.right="handleRight" | |
9 | + @keydown.up="handleUp" | |
10 | + @keydown.down="handleDown" | |
11 | + > | |
12 | + <div :class="[prefixCls + '-alpha-checkboard-wrap']"> | |
13 | + <div :class="[prefixCls + '-alpha-checkerboard']"></div> | |
5 | 14 | </div> |
6 | - <div class="ivu-color-picker-alpha-gradient" :style="{background: gradientColor}"></div> | |
7 | - <div class="ivu-color-picker-alpha-container" ref="container" | |
8 | - @mousedown="handleMouseDown" | |
9 | - @touchmove="handleChange" | |
10 | - @touchstart="handleChange"> | |
11 | - <div class="ivu-color-picker-alpha-pointer" :style="{left: colors.a * 100 + '%'}"> | |
12 | - <div class="ivu-color-picker-alpha-picker"></div> | |
15 | + <div | |
16 | + :style="gradientStyle" | |
17 | + :class="[prefixCls + '-alpha-gradient']"></div> | |
18 | + <div | |
19 | + ref="container" | |
20 | + :class="[prefixCls + '-alpha-container']" | |
21 | + @mousedown="handleMouseDown" | |
22 | + @touchmove="handleChange" | |
23 | + @touchstart="handleChange"> | |
24 | + <div | |
25 | + :style="{top: 0, left: `${value.a * 100}%`}" | |
26 | + :class="[prefixCls + '-alpha-pointer']"> | |
27 | + <div :class="[prefixCls + '-alpha-picker']"></div> | |
13 | 28 | </div> |
14 | 29 | </div> |
15 | 30 | </div> |
16 | 31 | </template> |
32 | + | |
17 | 33 | <script> |
18 | - export default { | |
19 | - name: 'Alpha', | |
20 | - props: { | |
21 | - value: Object, | |
22 | - onChange: Function | |
34 | +import HSAMixin from './hsaMixin'; | |
35 | +import Prefixes from './prefixMixin'; | |
36 | +import {clamp, toRGBAString} from './utils'; | |
37 | + | |
38 | +export default { | |
39 | + name: 'Alpha', | |
40 | + | |
41 | + mixins: [HSAMixin, Prefixes], | |
42 | + | |
43 | + data() { | |
44 | + const normalStep = 1; | |
45 | + const jumpStep = 10; | |
46 | + | |
47 | + return { | |
48 | + left: -normalStep, | |
49 | + right: normalStep, | |
50 | + up: jumpStep, | |
51 | + down: -jumpStep, | |
52 | + powerKey: 'shiftKey', | |
53 | + }; | |
54 | + }, | |
55 | + | |
56 | + computed: { | |
57 | + gradientStyle() { | |
58 | + const {r, g, b} = this.value.rgba; | |
59 | + const start = toRGBAString({r, g, b, a: 0}); | |
60 | + const finish = toRGBAString({r, g, b, a: 1}); | |
61 | + | |
62 | + return {background: `linear-gradient(to right, ${start} 0%, ${finish} 100%)`}; | |
23 | 63 | }, |
24 | - computed: { | |
25 | - colors () { | |
26 | - return this.value; | |
27 | - }, | |
28 | - gradientColor () { | |
29 | - const rgba = this.colors.rgba; | |
30 | - const rgbStr = [rgba.r, rgba.g, rgba.b].join(','); | |
31 | - return 'linear-gradient(to right, rgba(' + rgbStr + ', 0) 0%, rgba(' + rgbStr + ', 1) 100%)'; | |
64 | + }, | |
65 | + | |
66 | + methods: { | |
67 | + change(newAlpha) { | |
68 | + const {h, s, l} = this.value.hsl; | |
69 | + const {a} = this.value; | |
70 | + | |
71 | + if (a !== newAlpha) { | |
72 | + this.$emit('change', {h, s, l, a: newAlpha, source: 'rgba'}); | |
32 | 73 | } |
33 | 74 | }, |
34 | - methods: { | |
35 | - handleChange (e, skip) { | |
36 | - !skip && e.preventDefault(); | |
37 | - const container = this.$refs.container; | |
38 | - const containerWidth = container.clientWidth; | |
75 | + handleSlide(e, direction) { | |
76 | + e.preventDefault(); | |
77 | + e.stopPropagation(); | |
39 | 78 | |
40 | - const xOffset = container.getBoundingClientRect().left + window.pageXOffset; | |
41 | - const pageX = e.pageX || (e.touches ? e.touches[0].pageX : 0); | |
42 | - const left = pageX - xOffset; | |
79 | + this.change(clamp(e[this.powerKey] ? direction : Math.round(this.value.hsl.a * 100 + direction) / 100, 0, 1)); | |
80 | + }, | |
81 | + handleChange(e) { | |
82 | + e.preventDefault(); | |
83 | + e.stopPropagation(); | |
43 | 84 | |
44 | - let a; | |
45 | - if (left < 0) { | |
46 | - a = 0; | |
47 | - } else if (left > containerWidth) { | |
48 | - a = 1; | |
49 | - } else { | |
50 | - a = Math.round(left * 100 / containerWidth) / 100; | |
51 | - } | |
85 | + const left = this.getLeft(e); | |
52 | 86 | |
53 | - if (this.colors.a !== a) { | |
54 | - this.$emit('change', { | |
55 | - h: this.colors.hsl.h, | |
56 | - s: this.colors.hsl.s, | |
57 | - l: this.colors.hsl.l, | |
58 | - a: a, | |
59 | - source: 'rgba' | |
60 | - }); | |
61 | - } | |
62 | - }, | |
63 | - handleMouseDown (e) { | |
64 | - this.handleChange(e, true); | |
65 | - window.addEventListener('mousemove', this.handleChange); | |
66 | - window.addEventListener('mouseup', this.handleMouseUp); | |
67 | - }, | |
68 | - handleMouseUp () { | |
69 | - this.unbindEventListeners(); | |
70 | - }, | |
71 | - unbindEventListeners () { | |
72 | - window.removeEventListener('mousemove', this.handleChange); | |
73 | - window.removeEventListener('mouseup', this.handleMouseUp); | |
87 | + if (left < 0) { | |
88 | + this.change(0); | |
89 | + return; | |
74 | 90 | } |
75 | - } | |
76 | - }; | |
77 | -</script> | |
78 | 91 | \ No newline at end of file |
92 | + | |
93 | + const {clientWidth} = this.$refs.container; | |
94 | + | |
95 | + if (left > clientWidth) { | |
96 | + this.change(1); | |
97 | + return; | |
98 | + } | |
99 | + | |
100 | + this.change(Math.round(left * 100 / clientWidth) / 100); | |
101 | + }, | |
102 | + }, | |
103 | +}; | |
104 | +</script> | ... | ... |
src/components/color-picker/color-picker.vue
1 | 1 | <template> |
2 | - <div :class="classes" v-clickoutside="handleClose"> | |
3 | - <div ref="reference" @click="toggleVisible" :class="wrapClasses"> | |
4 | - <input type="hidden" :name="name" :value="currentValue"> | |
5 | - <i class="ivu-icon ivu-icon-arrow-down-b ivu-input-icon ivu-input-icon-normal"></i> | |
6 | - <div :class="inputClasses"> | |
2 | + <div | |
3 | + v-click-outside.capture="handleClose" | |
4 | + v-click-outside:mousedown.capture="handleClose" | |
5 | + :class="classes"> | |
6 | + <div | |
7 | + ref="reference" | |
8 | + :class="wrapClasses" | |
9 | + @click="toggleVisible"> | |
10 | + <input | |
11 | + :name="name" | |
12 | + :value="currentValue" | |
13 | + type="hidden"> | |
14 | + <i :class="arrowClasses"></i> | |
15 | + <div | |
16 | + ref="input" | |
17 | + :tabindex="disabled ? undefined : 0" | |
18 | + :class="inputClasses" | |
19 | + @keydown.tab="onTab" | |
20 | + @keydown.esc="onEscape" | |
21 | + @keydown.up="onArrow" | |
22 | + @keydown.down="onArrow" | |
23 | + > | |
7 | 24 | <div :class="[prefixCls + '-color']"> |
8 | - <div :class="[prefixCls + '-color-empty']" v-show="value === '' && !visible"> | |
9 | - <i class="ivu-icon ivu-icon-ios-close-empty"></i> | |
25 | + <div | |
26 | + v-show="value === '' && !visible" | |
27 | + :class="[prefixCls + '-color-empty']"> | |
28 | + <i :class="[iconPrefixCls, iconPrefixCls + '-ios-close-empty']"></i> | |
10 | 29 | </div> |
11 | - <div v-show="value || visible" :style="{backgroundColor: displayedColor}"></div> | |
30 | + <div | |
31 | + v-show="value || visible" | |
32 | + :style="displayedColorStyle"></div> | |
12 | 33 | </div> |
13 | 34 | </div> |
14 | 35 | </div> |
15 | 36 | <transition name="transition-drop"> |
16 | 37 | <Drop |
38 | + v-transfer-dom | |
17 | 39 | v-show="visible" |
18 | - @click.native="handleTransferClick" | |
19 | - :class="{ [prefixCls + '-transfer']: transfer }" | |
20 | - class-name="ivu-transfer-no-max-height" | |
21 | - :placement="placement" | |
22 | 40 | ref="drop" |
41 | + :placement="placement" | |
23 | 42 | :data-transfer="transfer" |
24 | - v-transfer-dom> | |
25 | - <div :class="[prefixCls + '-picker']"> | |
26 | - <div :class="[prefixCls + '-picker-wrapper']"> | |
27 | - <div :class="[prefixCls + '-picker-panel']"> | |
28 | - <Saturation v-model="saturationColors" @change="childChange"></Saturation> | |
43 | + :class="dropClasses" | |
44 | + > | |
45 | + <transition name="fade"> | |
46 | + <div | |
47 | + v-if="visible" | |
48 | + :class="[prefixCls + '-picker']"> | |
49 | + <div :class="[prefixCls + '-picker-wrapper']"> | |
50 | + <div :class="[prefixCls + '-picker-panel']"> | |
51 | + <Saturation | |
52 | + ref="saturation" | |
53 | + v-model="saturationColors" | |
54 | + :focused="visible" | |
55 | + @change="childChange" | |
56 | + @keydown.native.tab="handleFirstTab" | |
57 | + ></Saturation> | |
58 | + </div> | |
59 | + <div | |
60 | + v-if="hue" | |
61 | + :class="[prefixCls + '-picker-hue-slider']"> | |
62 | + <Hue | |
63 | + v-model="saturationColors" | |
64 | + @change="childChange"></Hue> | |
65 | + </div> | |
66 | + <div | |
67 | + v-if="alpha" | |
68 | + :class="[prefixCls + '-picker-alpha-slider']"> | |
69 | + <Alpha | |
70 | + v-model="saturationColors" | |
71 | + @change="childChange"></Alpha> | |
72 | + </div> | |
73 | + <recommend-colors | |
74 | + v-if="colors.length" | |
75 | + :list="colors" | |
76 | + :class="[prefixCls + '-picker-colors']" | |
77 | + @picker-color="handleSelectColor"></recommend-colors> | |
78 | + <recommend-colors | |
79 | + v-if="!colors.length && recommend" | |
80 | + :list="recommendedColor" | |
81 | + :class="[prefixCls + '-picker-colors']" | |
82 | + @picker-color="handleSelectColor"></recommend-colors> | |
29 | 83 | </div> |
30 | - <div v-if="hue" :class="[prefixCls + '-picker-hue-slider']"> | |
31 | - <Hue v-model="saturationColors" @change="childChange"></Hue> | |
84 | + <div :class="[prefixCls + '-confirm']"> | |
85 | + <span :class="[prefixCls + '-confirm-color']">{{formatColor}}</span> | |
86 | + <i-button | |
87 | + ref="clear" | |
88 | + :tabindex="0" | |
89 | + size="small" | |
90 | + type="ghost" | |
91 | + @click.native="handleClear" | |
92 | + @keydown.enter="handleClear" | |
93 | + @keydown.native.esc="closer" | |
94 | + >{{t('i.datepicker.clear')}}</i-button> | |
95 | + <i-button | |
96 | + ref="ok" | |
97 | + :tabindex="0" | |
98 | + size="small" | |
99 | + type="primary" | |
100 | + @click.native="handleSuccess" | |
101 | + @keydown.native.tab="handleLastTab" | |
102 | + @keydown.enter="handleSuccess" | |
103 | + @keydown.native.esc="closer" | |
104 | + >{{t('i.datepicker.ok')}}</i-button> | |
32 | 105 | </div> |
33 | - <div v-if="alpha" :class="[prefixCls + '-picker-alpha-slider']"> | |
34 | - <Alpha v-model="saturationColors" @change="childChange"></Alpha> | |
35 | - </div> | |
36 | - <recommend-colors | |
37 | - v-if="colors.length" | |
38 | - :list="colors" | |
39 | - :class="[prefixCls + '-picker-colors']" | |
40 | - @picker-color="handleSelectColor"></recommend-colors> | |
41 | - <recommend-colors | |
42 | - v-if="!colors.length && recommend" | |
43 | - :list="recommendedColor" | |
44 | - :class="[prefixCls + '-picker-colors']" | |
45 | - @picker-color="handleSelectColor"></recommend-colors> | |
46 | - </div> | |
47 | - <div :class="[prefixCls + '-confirm']"> | |
48 | - <span :class="[prefixCls + '-confirm-color']">{{ formatColor }}</span> | |
49 | - <Confirm @on-pick-success="handleSuccess" @on-pick-clear="handleClear"></Confirm> | |
50 | 106 | </div> |
51 | - </div> | |
107 | + </transition> | |
52 | 108 | </Drop> |
53 | 109 | </transition> |
54 | 110 | </div> |
55 | 111 | </template> |
56 | -<script> | |
57 | - import tinycolor from 'tinycolor2'; | |
58 | - | |
59 | - import clickoutside from '../../directives/clickoutside'; | |
60 | - import TransferDom from '../../directives/transfer-dom'; | |
61 | - | |
62 | - import Drop from '../../components/select/dropdown.vue'; | |
63 | - import RecommendColors from './recommend-colors.vue'; | |
64 | - import Confirm from '../date-picker/base/confirm.vue'; | |
65 | - import Saturation from './saturation.vue'; | |
66 | - import Hue from './hue.vue'; | |
67 | - import Alpha from './alpha.vue'; | |
68 | - | |
69 | - import { oneOf } from '../../utils/assist'; | |
70 | - import Emitter from '../../mixins/emitter'; | |
71 | - | |
72 | - const prefixCls = 'ivu-color-picker'; | |
73 | - const inputPrefixCls = 'ivu-input'; | |
74 | - | |
75 | - function _colorChange (data, oldHue) { | |
76 | - data = data === '' ? '#2d8cf0' : data; | |
77 | - const alpha = data && data.a; | |
78 | - let color; | |
79 | - | |
80 | - // hsl is better than hex between conversions | |
81 | - if (data && data.hsl) { | |
82 | - color = tinycolor(data.hsl); | |
83 | - } else if (data && data.hex && data.hex.length > 0) { | |
84 | - color = tinycolor(data.hex); | |
85 | - } else { | |
86 | - color = tinycolor(data); | |
87 | - } | |
88 | - | |
89 | - if (color && (color._a === undefined || color._a === null)) { | |
90 | - color.setAlpha(alpha || 1); | |
91 | - } | |
92 | 112 | |
93 | - const hsl = color.toHsl(); | |
94 | - const hsv = color.toHsv(); | |
113 | +<script> | |
114 | +import tinycolor from 'tinycolor2'; | |
115 | +import vClickOutside from 'v-click-outside-x/index'; | |
116 | +import TransferDom from '../../directives/transfer-dom'; | |
117 | +import Drop from '../../components/select/dropdown.vue'; | |
118 | +import RecommendColors from './recommend-colors.vue'; | |
119 | +import Saturation from './saturation.vue'; | |
120 | +import Hue from './hue.vue'; | |
121 | +import Alpha from './alpha.vue'; | |
122 | +import Locale from '../../mixins/locale'; | |
123 | +import {oneOf} from '../../utils/assist'; | |
124 | +import Emitter from '../../mixins/emitter'; | |
125 | +import Prefixes from './prefixMixin'; | |
126 | +import {changeColor, toRGBAString} from './utils'; | |
95 | 127 | |
96 | - if (hsl.s === 0) { | |
97 | - hsv.h = hsl.h = data.h || (data.hsl && data.hsl.h) || oldHue || 0; | |
98 | - } | |
128 | +export default { | |
129 | + name: 'ColorPicker', | |
99 | 130 | |
100 | - // when the hsv.v is less than 0.0164 (base on test) | |
101 | - // because of possible loss of precision | |
102 | - // the result of hue and saturation would be miscalculated | |
103 | - if (hsv.v < 0.0164) { | |
104 | - hsv.h = data.h || (data.hsv && data.hsv.h) || 0; | |
105 | - hsv.s = data.s || (data.hsv && data.hsv.s) || 0; | |
106 | - } | |
131 | + components: {Drop, RecommendColors, Saturation, Hue, Alpha}, | |
107 | 132 | |
108 | - if (hsl.l < 0.01) { | |
109 | - hsl.h = data.h || (data.hsl && data.hsl.h) || 0; | |
110 | - hsl.s = data.s || (data.hsl && data.hsl.s) || 0; | |
111 | - } | |
133 | + directives: {clickOutside: vClickOutside.directive, TransferDom}, | |
112 | 134 | |
113 | - return { | |
114 | - hsl: hsl, | |
115 | - hex: color.toHexString().toUpperCase(), | |
116 | - rgba: color.toRgb(), | |
117 | - hsv: hsv, | |
118 | - oldHue: data.h || oldHue || hsl.h, | |
119 | - source: data.source, | |
120 | - a: data.a || color.getAlpha() | |
121 | - }; | |
122 | - } | |
135 | + mixins: [Emitter, Locale, Prefixes], | |
123 | 136 | |
124 | - export default { | |
125 | - name: 'ColorPicker', | |
126 | - mixins: [ Emitter ], | |
127 | - components: { Drop, Confirm, RecommendColors, Saturation, Hue, Alpha }, | |
128 | - directives: { clickoutside, TransferDom }, | |
129 | - props: { | |
130 | - value: { | |
131 | - type: String | |
132 | - }, | |
133 | - hue: { | |
134 | - type: Boolean, | |
135 | - default: true | |
137 | + props: { | |
138 | + value: { | |
139 | + type: String, | |
140 | + default: undefined, | |
141 | + }, | |
142 | + hue: { | |
143 | + type: Boolean, | |
144 | + default: true, | |
145 | + }, | |
146 | + alpha: { | |
147 | + type: Boolean, | |
148 | + default: false, | |
149 | + }, | |
150 | + recommend: { | |
151 | + type: Boolean, | |
152 | + default: false, | |
153 | + }, | |
154 | + format: { | |
155 | + type: String, | |
156 | + validator(value) { | |
157 | + return oneOf(value, ['hsl', 'hsv', 'hex', 'rgb']); | |
136 | 158 | }, |
137 | - alpha: { | |
138 | - type: Boolean, | |
139 | - default: false | |
159 | + default: undefined, | |
160 | + }, | |
161 | + colors: { | |
162 | + type: Array, | |
163 | + default() { | |
164 | + return []; | |
140 | 165 | }, |
141 | - recommend: { | |
142 | - type: Boolean, | |
143 | - default: false | |
166 | + }, | |
167 | + disabled: { | |
168 | + type: Boolean, | |
169 | + default: false, | |
170 | + }, | |
171 | + size: { | |
172 | + type: String, | |
173 | + validator(value) { | |
174 | + return oneOf(value, ['small', 'large', 'default']); | |
144 | 175 | }, |
145 | - format: { | |
146 | - validator (value) { | |
147 | - return oneOf(value, ['hsl', 'hsv', 'hex', 'rgb']); | |
148 | - } | |
176 | + default: 'default', | |
177 | + }, | |
178 | + hideDropDown: { | |
179 | + type: Boolean, | |
180 | + default: false, | |
181 | + }, | |
182 | + placement: { | |
183 | + type: String, | |
184 | + validator(value) { | |
185 | + return oneOf(value, [ | |
186 | + 'top', | |
187 | + 'top-start', | |
188 | + 'top-end', | |
189 | + 'bottom', | |
190 | + 'bottom-start', | |
191 | + 'bottom-end', | |
192 | + 'left', | |
193 | + 'left-start', | |
194 | + 'left-end', | |
195 | + 'right', | |
196 | + 'right-start', | |
197 | + 'right-end', | |
198 | + ]); | |
149 | 199 | }, |
150 | - colors: { | |
151 | - type: Array, | |
152 | - default () { | |
153 | - return []; | |
154 | - } | |
200 | + default: 'bottom', | |
201 | + }, | |
202 | + transfer: { | |
203 | + type: Boolean, | |
204 | + default: false, | |
205 | + }, | |
206 | + name: { | |
207 | + type: String, | |
208 | + default: undefined, | |
209 | + }, | |
210 | + }, | |
211 | + | |
212 | + data() { | |
213 | + return { | |
214 | + val: changeColor(this.value), | |
215 | + currentValue: this.value, | |
216 | + dragging: false, | |
217 | + visible: false, | |
218 | + recommendedColor: [ | |
219 | + '#2d8cf0', | |
220 | + '#19be6b', | |
221 | + '#ff9900', | |
222 | + '#ed3f14', | |
223 | + '#00b5ff', | |
224 | + '#19c919', | |
225 | + '#f9e31c', | |
226 | + '#ea1a1a', | |
227 | + '#9b1dea', | |
228 | + '#00c2b1', | |
229 | + '#ac7a33', | |
230 | + '#1d35ea', | |
231 | + '#8bc34a', | |
232 | + '#f16b62', | |
233 | + '#ea4ca3', | |
234 | + '#0d94aa', | |
235 | + '#febd79', | |
236 | + '#5d4037', | |
237 | + '#00bcd4', | |
238 | + '#f06292', | |
239 | + '#cddc39', | |
240 | + '#607d8b', | |
241 | + '#000000', | |
242 | + '#ffffff', | |
243 | + ], | |
244 | + }; | |
245 | + }, | |
246 | + | |
247 | + computed: { | |
248 | + arrowClasses() { | |
249 | + return [ | |
250 | + this.iconPrefixCls, | |
251 | + `${this.iconPrefixCls}-arrow-down-b`, | |
252 | + `${this.inputPrefixCls}-icon`, | |
253 | + `${this.inputPrefixCls}-icon-normal`, | |
254 | + ]; | |
255 | + }, | |
256 | + transition() { | |
257 | + return oneOf(this.placement, ['bottom-start', 'bottom', 'bottom-end']) ? 'slide-up' : 'fade'; | |
258 | + }, | |
259 | + saturationColors: { | |
260 | + get() { | |
261 | + return this.val; | |
155 | 262 | }, |
156 | - disabled: { | |
157 | - type: Boolean, | |
158 | - default: false | |
263 | + set(newVal) { | |
264 | + this.val = newVal; | |
265 | + this.$emit('on-active-change', this.formatColor); | |
159 | 266 | }, |
160 | - size: { | |
161 | - validator (value) { | |
162 | - return oneOf(value, ['small', 'large', 'default']); | |
267 | + }, | |
268 | + classes() { | |
269 | + return [ | |
270 | + `${this.prefixCls}`, | |
271 | + { | |
272 | + [`${this.prefixCls}-transfer`]: this.transfer, | |
163 | 273 | }, |
164 | - default: 'default' | |
165 | - }, | |
166 | - placement: { | |
167 | - validator (value) { | |
168 | - return oneOf(value, ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end']); | |
274 | + ]; | |
275 | + }, | |
276 | + wrapClasses() { | |
277 | + return [ | |
278 | + `${this.prefixCls}-rel`, | |
279 | + `${this.prefixCls}-${this.size}`, | |
280 | + `${this.inputPrefixCls}-wrapper`, | |
281 | + `${this.inputPrefixCls}-wrapper-${this.size}`, | |
282 | + { | |
283 | + [`${this.prefixCls}-disabled`]: this.disabled, | |
169 | 284 | }, |
170 | - default: 'bottom' | |
171 | - }, | |
172 | - transfer: { | |
173 | - type: Boolean, | |
174 | - default: false | |
175 | - }, | |
176 | - name: { | |
177 | - type: String | |
178 | - } | |
285 | + ]; | |
179 | 286 | }, |
180 | - data () { | |
181 | - return { | |
182 | - val: _colorChange(this.value), | |
183 | - currentValue: this.value, | |
184 | - prefixCls: prefixCls, | |
185 | - visible: false, | |
186 | - disableCloseUnderTransfer: false, // transfer 模式下,点击Drop也会触发关闭 | |
187 | - recommendedColor: [ | |
188 | - '#2d8cf0', | |
189 | - '#19be6b', | |
190 | - '#ff9900', | |
191 | - '#ed3f14', | |
192 | - '#00b5ff', | |
193 | - '#19c919', | |
194 | - '#f9e31c', | |
195 | - '#ea1a1a', | |
196 | - '#9b1dea', | |
197 | - '#00c2b1', | |
198 | - '#ac7a33', | |
199 | - '#1d35ea', | |
200 | - '#8bc34a', | |
201 | - '#f16b62', | |
202 | - '#ea4ca3', | |
203 | - '#0d94aa', | |
204 | - '#febd79', | |
205 | - '#5d4037', | |
206 | - '#00bcd4', | |
207 | - '#f06292', | |
208 | - '#cddc39', | |
209 | - '#607d8b', | |
210 | - '#000000', | |
211 | - '#ffffff' | |
212 | - ] | |
213 | - }; | |
214 | - }, | |
215 | - computed: { | |
216 | - transition () { | |
217 | - if (this.placement === 'bottom-start' || this.placement === 'bottom' || this.placement === 'bottom-end') { | |
218 | - return 'slide-up'; | |
219 | - } else { | |
220 | - return 'fade'; | |
221 | - } | |
222 | - }, | |
223 | - saturationColors: { | |
224 | - get () { | |
225 | - return this.val; | |
287 | + inputClasses() { | |
288 | + return [ | |
289 | + `${this.prefixCls}-input`, | |
290 | + `${this.inputPrefixCls}`, | |
291 | + `${this.inputPrefixCls}-${this.size}`, | |
292 | + { | |
293 | + [`${this.prefixCls}-focused`]: this.visible, | |
294 | + [`${this.prefixCls}-disabled`]: this.disabled, | |
226 | 295 | }, |
227 | - set (newVal) { | |
228 | - this.val = newVal; | |
229 | - this.$emit('on-active-change', this.formatColor); | |
296 | + ]; | |
297 | + }, | |
298 | + dropClasses() { | |
299 | + return [ | |
300 | + `${this.transferPrefixCls}-no-max-height`, | |
301 | + { | |
302 | + [`${this.prefixCls}-transfer`]: this.transfer, | |
303 | + [`${this.prefixCls}-hide-drop`]: this.hideDropDown, | |
304 | + }, | |
305 | + ]; | |
306 | + }, | |
307 | + displayedColorStyle() { | |
308 | + return {backgroundColor: toRGBAString(this.visible ? this.saturationColors.rgba : tinycolor(this.value).toRgb())}; | |
309 | + }, | |
310 | + formatColor() { | |
311 | + const {format, saturationColors} = this; | |
312 | + | |
313 | + if (format) { | |
314 | + if (format === 'hsl') { | |
315 | + return tinycolor(saturationColors.hsl).toHslString(); | |
230 | 316 | } |
231 | - }, | |
232 | - classes () { | |
233 | - return [ | |
234 | - `${prefixCls}`, | |
235 | - { | |
236 | - [`${prefixCls}-transfer`]: this.transfer | |
237 | - } | |
238 | - ]; | |
239 | - }, | |
240 | - wrapClasses () { | |
241 | - return [ | |
242 | - `${prefixCls}-rel`, | |
243 | - `${prefixCls}-${this.size}`, | |
244 | - `${inputPrefixCls}-wrapper`, | |
245 | - `${inputPrefixCls}-wrapper-${this.size}` | |
246 | - ]; | |
247 | - }, | |
248 | - inputClasses () { | |
249 | - return [ | |
250 | - `${prefixCls}-input`, | |
251 | - `${inputPrefixCls}`, | |
252 | - `${inputPrefixCls}-${this.size}`, | |
253 | - { | |
254 | - [`${inputPrefixCls}-disabled`]: this.disabled | |
255 | - } | |
256 | - ]; | |
257 | - }, | |
258 | - displayedColor () { | |
259 | - let color; | |
260 | - if (this.visible) { | |
261 | - const rgba = this.saturationColors.rgba; | |
262 | - color = { | |
263 | - r: rgba.r, | |
264 | - g: rgba.g, | |
265 | - b: rgba.b, | |
266 | - a: rgba.a | |
267 | - }; | |
268 | - } else { | |
269 | - color = tinycolor(this.value).toRgb(); | |
317 | + | |
318 | + if (format === 'hsv') { | |
319 | + return tinycolor(saturationColors.hsv).toHsvString(); | |
270 | 320 | } |
271 | - return `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`; | |
272 | - }, | |
273 | - formatColor () { | |
274 | - const value = this.saturationColors; | |
275 | - const format = this.format; | |
276 | - let color; | |
277 | 321 | |
278 | - const rgba = `rgba(${value.rgba.r}, ${value.rgba.g}, ${value.rgba.b}, ${value.rgba.a})`; | |
279 | - if (format) { | |
280 | - if (format === 'hsl') { | |
281 | - color = tinycolor(value.hsl).toHslString(); | |
282 | - } else if (format === 'hsv') { | |
283 | - color = tinycolor(value.hsv).toHsvString(); | |
284 | - } else if (format === 'hex') { | |
285 | - color = value.hex; | |
286 | - } else if (format === 'rgb') { | |
287 | - color = rgba; | |
288 | - } | |
289 | - } else if (this.alpha) { | |
290 | - color = rgba; | |
291 | - } else { | |
292 | - color = value.hex; | |
322 | + if (format === 'hex') { | |
323 | + return saturationColors.hex; | |
293 | 324 | } |
294 | - return color; | |
295 | - } | |
296 | - }, | |
297 | - watch: { | |
298 | - value (newVal) { | |
299 | - this.val = _colorChange(newVal); | |
300 | - }, | |
301 | - visible (val) { | |
302 | - this.val = _colorChange(this.value); | |
303 | - if (val) { | |
304 | - this.$refs.drop.update(); | |
305 | - } else { | |
306 | - this.$refs.drop.destroy(); | |
325 | + | |
326 | + if (format === 'rgb') { | |
327 | + return toRGBAString(saturationColors.rgba); | |
307 | 328 | } |
308 | - this.$emit('on-open-change', Boolean(val)); | |
329 | + } else if (this.alpha) { | |
330 | + return toRGBAString(saturationColors.rgba); | |
309 | 331 | } |
332 | + | |
333 | + return saturationColors.hex; | |
310 | 334 | }, |
311 | - methods: { | |
312 | - // 开启 transfer 时,点击 Drop 即会关闭,这里不让其关闭 | |
313 | - handleTransferClick () { | |
314 | - if (this.transfer) this.disableCloseUnderTransfer = true; | |
315 | - }, | |
316 | - handleClose () { | |
317 | - if (this.disableCloseUnderTransfer) { | |
318 | - this.disableCloseUnderTransfer = false; | |
319 | - return false; | |
335 | + }, | |
336 | + | |
337 | + watch: { | |
338 | + value(newVal) { | |
339 | + this.val = changeColor(newVal); | |
340 | + }, | |
341 | + visible(val) { | |
342 | + this.val = changeColor(this.value); | |
343 | + this.$refs.drop[val ? 'update' : 'destroy'](); | |
344 | + this.$emit('on-open-change', Boolean(val)); | |
345 | + }, | |
346 | + }, | |
347 | + | |
348 | + mounted() { | |
349 | + this.$on('on-escape-keydown', this.closer); | |
350 | + this.$on('on-dragging', this.setDragging); | |
351 | + }, | |
352 | + | |
353 | + methods: { | |
354 | + setDragging(value) { | |
355 | + this.dragging = value; | |
356 | + }, | |
357 | + handleClose(event) { | |
358 | + if (this.visible) { | |
359 | + if (this.dragging || event.type === 'mousedown') { | |
360 | + event.preventDefault(); | |
361 | + return; | |
320 | 362 | } |
321 | - this.visible = false; | |
322 | - }, | |
323 | - toggleVisible () { | |
324 | - this.visible = !this.visible; | |
325 | - }, | |
326 | - childChange (data) { | |
327 | - this.colorChange(data); | |
328 | - }, | |
329 | - colorChange (data, oldHue) { | |
330 | - this.oldHue = this.saturationColors.hsl.h; | |
331 | - this.saturationColors = _colorChange(data, oldHue || this.oldHue); | |
332 | - }, | |
333 | - isValidHex (hex) { | |
334 | - return tinycolor(hex).isValid(); | |
335 | - }, | |
336 | - simpleCheckForValidColor (data) { | |
337 | - const keysToCheck = ['r', 'g', 'b', 'a', 'h', 's', 'l', 'v']; | |
338 | - let checked = 0; | |
339 | - let passed = 0; | |
340 | 363 | |
341 | - for (let i = 0; i < keysToCheck.length; i++) { | |
342 | - const letter = keysToCheck[i]; | |
343 | - if (data[letter]) { | |
344 | - checked++; | |
345 | - if (!isNaN(data[letter])) { | |
346 | - passed++; | |
347 | - } | |
364 | + if (this.transfer) { | |
365 | + const {$el} = this.$refs.drop; | |
366 | + if ($el === event.target || $el.contains(event.target)) { | |
367 | + return; | |
348 | 368 | } |
349 | 369 | } |
350 | 370 | |
351 | - if (checked === passed) { | |
352 | - return data; | |
353 | - } | |
354 | - }, | |
355 | - handleSuccess () { | |
356 | - const color = this.formatColor; | |
357 | - this.currentValue = color; | |
358 | - this.$emit('input', color); | |
359 | - this.$emit('on-change', color); | |
360 | - this.dispatch('FormItem', 'on-form-change', color); | |
361 | - this.handleClose(); | |
362 | - }, | |
363 | - handleClear () { | |
364 | - this.currentValue = ''; | |
365 | - this.$emit('input', ''); | |
366 | - this.$emit('on-change', ''); | |
367 | - this.dispatch('FormItem', 'on-form-change', ''); | |
368 | - this.handleClose(); | |
369 | - }, | |
370 | - handleSelectColor (color) { | |
371 | - this.val = _colorChange(color); | |
371 | + this.closer(event); | |
372 | + return; | |
373 | + } | |
374 | + | |
375 | + this.visible = false; | |
376 | + }, | |
377 | + toggleVisible() { | |
378 | + if (this.disabled) { | |
379 | + return; | |
380 | + } | |
381 | + | |
382 | + this.visible = !this.visible; | |
383 | + this.$refs.input.focus(); | |
384 | + }, | |
385 | + childChange(data) { | |
386 | + this.colorChange(data); | |
387 | + }, | |
388 | + colorChange(data, oldHue) { | |
389 | + this.oldHue = this.saturationColors.hsl.h; | |
390 | + this.saturationColors = changeColor(data, oldHue || this.oldHue); | |
391 | + }, | |
392 | + closer(event) { | |
393 | + if (event) { | |
394 | + event.preventDefault(); | |
395 | + event.stopPropagation(); | |
396 | + } | |
397 | + | |
398 | + this.visible = false; | |
399 | + this.$refs.input.focus(); | |
400 | + }, | |
401 | + handleButtons(event, value) { | |
402 | + this.currentValue = value; | |
403 | + this.$emit('input', value); | |
404 | + this.$emit('on-change', value); | |
405 | + this.dispatch('FormItem', 'on-form-change', value); | |
406 | + this.closer(event); | |
407 | + }, | |
408 | + handleSuccess(event) { | |
409 | + this.handleButtons(event, this.formatColor); | |
410 | + this.$emit('on-pick-success'); | |
411 | + }, | |
412 | + handleClear(event) { | |
413 | + this.handleButtons(event, ''); | |
414 | + this.$emit('on-pick-clear'); | |
415 | + }, | |
416 | + handleSelectColor(color) { | |
417 | + this.val = changeColor(color); | |
418 | + this.$emit('on-active-change', this.formatColor); | |
419 | + }, | |
420 | + handleFirstTab(event) { | |
421 | + if (event.shiftKey) { | |
422 | + event.preventDefault(); | |
423 | + event.stopPropagation(); | |
424 | + this.$refs.ok.$el.focus(); | |
372 | 425 | } |
373 | - } | |
374 | - }; | |
426 | + }, | |
427 | + handleLastTab(event) { | |
428 | + if (!event.shiftKey) { | |
429 | + event.preventDefault(); | |
430 | + event.stopPropagation(); | |
431 | + this.$refs.saturation.$el.focus(); | |
432 | + } | |
433 | + }, | |
434 | + onTab(event) { | |
435 | + if (this.visible) { | |
436 | + event.preventDefault(); | |
437 | + } | |
438 | + }, | |
439 | + onEscape(event) { | |
440 | + if (this.visible) { | |
441 | + this.closer(event); | |
442 | + } | |
443 | + }, | |
444 | + onArrow(event) { | |
445 | + if (!this.visible) { | |
446 | + event.preventDefault(); | |
447 | + event.stopPropagation(); | |
448 | + this.visible = true; | |
449 | + } | |
450 | + }, | |
451 | + }, | |
452 | +}; | |
375 | 453 | </script> | ... | ... |
1 | +import Emitter from '../../mixins/emitter'; | |
2 | +import handleEscapeMixin from './handleEscapeMixin'; | |
3 | +import {getTouches} from './utils'; | |
4 | + | |
5 | +export default { | |
6 | + mixins: [Emitter, handleEscapeMixin], | |
7 | + | |
8 | + props: { | |
9 | + focused: { | |
10 | + type: Boolean, | |
11 | + default: false, | |
12 | + }, | |
13 | + value: { | |
14 | + type: Object, | |
15 | + default: undefined, | |
16 | + }, | |
17 | + }, | |
18 | + | |
19 | + beforeDestroy() { | |
20 | + this.unbindEventListeners(); | |
21 | + }, | |
22 | + | |
23 | + created() { | |
24 | + if (this.focused) { | |
25 | + setTimeout(() => this.$el.focus(), 1); | |
26 | + } | |
27 | + }, | |
28 | + | |
29 | + methods: { | |
30 | + handleLeft(e) { | |
31 | + this.handleSlide(e, this.left, 'left'); | |
32 | + }, | |
33 | + handleRight(e) { | |
34 | + this.handleSlide(e, this.right, 'right'); | |
35 | + }, | |
36 | + handleUp(e) { | |
37 | + this.handleSlide(e, this.up, 'up'); | |
38 | + }, | |
39 | + handleDown(e) { | |
40 | + this.handleSlide(e, this.down, 'down'); | |
41 | + }, | |
42 | + handleMouseDown(e) { | |
43 | + this.dispatch('ColorPicker', 'on-dragging', true); | |
44 | + this.handleChange(e, true); | |
45 | + window.addEventListener('mousemove', this.handleChange, false); | |
46 | + window.addEventListener('mouseup', this.handleMouseUp, false); | |
47 | + }, | |
48 | + handleMouseUp() { | |
49 | + this.unbindEventListeners(); | |
50 | + }, | |
51 | + unbindEventListeners() { | |
52 | + window.removeEventListener('mousemove', this.handleChange); | |
53 | + window.removeEventListener('mouseup', this.handleMouseUp); | |
54 | + // This timeout is required so that the click handler for click-outside | |
55 | + // has the chance to run before the mouseup removes the dragging flag. | |
56 | + setTimeout(() => this.dispatch('ColorPicker', 'on-dragging', false), 1); | |
57 | + }, | |
58 | + getLeft(e) { | |
59 | + const {container} = this.$refs; | |
60 | + const xOffset = container.getBoundingClientRect().left + window.pageXOffset; | |
61 | + const pageX = e.pageX || getTouches(e, 'PageX'); | |
62 | + | |
63 | + return pageX - xOffset; | |
64 | + }, | |
65 | + getTop(e) { | |
66 | + const {container} = this.$refs; | |
67 | + const yOffset = container.getBoundingClientRect().top + window.pageYOffset; | |
68 | + const pageY = e.pageY || getTouches(e, 'PageY'); | |
69 | + | |
70 | + return pageY - yOffset; | |
71 | + }, | |
72 | + }, | |
73 | +}; | ... | ... |
src/components/color-picker/hue.vue
1 | 1 | <template> |
2 | - <div class="ivu-color-picker-hue"> | |
3 | - <div class="ivu-color-picker-hue-container" ref="container" | |
4 | - @mousedown="handleMouseDown" | |
5 | - @touchmove="handleChange" | |
6 | - @touchstart="handleChange"> | |
7 | - <div class="ivu-color-picker-hue-pointer" :style="{top: 0, left: pointerLeft}"> | |
8 | - <div class="ivu-color-picker-hue-picker"></div> | |
2 | + <div | |
3 | + :class="[prefixCls + '-hue']" | |
4 | + tabindex="0" | |
5 | + @click="$el.focus()" | |
6 | + @keydown.esc="handleEscape" | |
7 | + @keydown.left="handleLeft" | |
8 | + @keydown.right="handleRight" | |
9 | + @keydown.up="handleUp" | |
10 | + @keydown.down="handleDown" | |
11 | + > | |
12 | + <div | |
13 | + ref="container" | |
14 | + :class="[prefixCls + '-hue-container']" | |
15 | + @mousedown="handleMouseDown" | |
16 | + @touchmove="handleChange" | |
17 | + @touchstart="handleChange"> | |
18 | + <div | |
19 | + :style="{top: 0, left: `${percent}%`}" | |
20 | + :class="[prefixCls + '-hue-pointer']"> | |
21 | + <div :class="[prefixCls + '-hue-picker']"></div> | |
9 | 22 | </div> |
10 | 23 | </div> |
11 | 24 | </div> |
12 | 25 | </template> |
26 | + | |
13 | 27 | <script> |
14 | - export default { | |
15 | - name: 'Hue', | |
16 | - props: { | |
17 | - value: Object | |
18 | - }, | |
19 | - data () { | |
20 | - return { | |
21 | - oldHue: 0, | |
22 | - pullDirection: '' | |
23 | - }; | |
24 | - }, | |
25 | - computed: { | |
26 | - colors () { | |
27 | - const h = this.value.hsl.h; | |
28 | - if (h !== 0 && h - this.oldHue > 0) this.pullDirection = 'right'; | |
29 | - if (h !== 0 && h - this.oldHue < 0) this.pullDirection = 'left'; | |
30 | - this.oldHue = h; | |
28 | +import HASMixin from './hsaMixin'; | |
29 | +import Prefixes from './prefixMixin'; | |
30 | +import {clamp} from './utils'; | |
31 | + | |
32 | +export default { | |
33 | + name: 'Hue', | |
34 | + | |
35 | + mixins: [HASMixin, Prefixes], | |
36 | + | |
37 | + data() { | |
38 | + const normalStep = 1 / 360 * 25; | |
39 | + const jumpStep = 20 * normalStep; | |
40 | + | |
41 | + return { | |
42 | + left: -normalStep, | |
43 | + right: normalStep, | |
44 | + up: jumpStep, | |
45 | + down: -jumpStep, | |
46 | + powerKey: 'shiftKey', | |
47 | + percent: clamp(this.value.hsl.h * 100 / 360, 0, 100), | |
48 | + }; | |
49 | + }, | |
50 | + | |
51 | + methods: { | |
52 | + change(percent) { | |
53 | + this.percent = clamp(percent, 0, 100); | |
31 | 54 | |
32 | - return this.value; | |
33 | - }, | |
34 | - pointerLeft () { | |
35 | - if (this.colors.hsl.h === 0 && this.pullDirection === 'right') return '100%'; | |
36 | - return (this.colors.hsl.h * 100) / 360 + '%'; | |
55 | + const {h, s, l, a} = this.value.hsl; | |
56 | + const newHue = clamp(percent / 100 * 360, 0, 360); | |
57 | + | |
58 | + if (h !== newHue) { | |
59 | + this.$emit('change', {h: newHue, s, l, a, source: 'hsl'}); | |
37 | 60 | } |
38 | 61 | }, |
39 | - methods: { | |
40 | - handleChange (e, skip) { | |
41 | - !skip && e.preventDefault(); | |
62 | + handleSlide(e, direction) { | |
63 | + e.preventDefault(); | |
64 | + e.stopPropagation(); | |
42 | 65 | |
43 | - const container = this.$refs.container; | |
44 | - const containerWidth = container.clientWidth; | |
66 | + if (e[this.powerKey]) { | |
67 | + this.change(direction < 0 ? 0 : 100); | |
68 | + return; | |
69 | + } | |
45 | 70 | |
46 | - const xOffset = container.getBoundingClientRect().left + window.pageXOffset; | |
47 | - const pageX = e.pageX || (e.touches ? e.touches[0].pageX : 0); | |
48 | - const left = pageX - xOffset; | |
71 | + this.change(this.percent + direction); | |
72 | + }, | |
73 | + handleChange(e) { | |
74 | + e.preventDefault(); | |
75 | + e.stopPropagation(); | |
49 | 76 | |
50 | - let h; | |
51 | - let percent; | |
77 | + const left = this.getLeft(e); | |
52 | 78 | |
53 | - if (left < 0) { | |
54 | - h = 0; | |
55 | - } else if (left > containerWidth) { | |
56 | - h = 360; | |
57 | - } else { | |
58 | - percent = left * 100 / containerWidth; | |
59 | - h = (360 * percent / 100); | |
60 | - } | |
79 | + if (left < 0) { | |
80 | + this.change(0); | |
81 | + return; | |
82 | + } | |
61 | 83 | |
62 | - if (this.colors.hsl.h !== h) { | |
63 | - this.$emit('change', { | |
64 | - h: h, | |
65 | - s: this.colors.hsl.s, | |
66 | - l: this.colors.hsl.l, | |
67 | - a: this.colors.hsl.a, | |
68 | - source: 'hsl' | |
69 | - }); | |
70 | - } | |
71 | - }, | |
72 | - handleMouseDown (e) { | |
73 | - this.handleChange(e, true); | |
74 | - window.addEventListener('mousemove', this.handleChange); | |
75 | - window.addEventListener('mouseup', this.handleMouseUp); | |
76 | - }, | |
77 | - handleMouseUp () { | |
78 | - this.unbindEventListeners(); | |
79 | - }, | |
80 | - unbindEventListeners () { | |
81 | - window.removeEventListener('mousemove', this.handleChange); | |
82 | - window.removeEventListener('mouseup', this.handleMouseUp); | |
84 | + const {clientWidth} = this.$refs.container; | |
85 | + | |
86 | + if (left > clientWidth) { | |
87 | + this.change(100); | |
88 | + return; | |
83 | 89 | } |
84 | - } | |
85 | - }; | |
86 | -</script> | |
87 | 90 | \ No newline at end of file |
91 | + | |
92 | + this.change(left * 100 / clientWidth); | |
93 | + }, | |
94 | + }, | |
95 | +}; | |
96 | +</script> | ... | ... |
src/components/color-picker/index.js
src/components/color-picker/recommend-colors.vue
1 | 1 | <template> |
2 | - <div> | |
2 | + <div | |
3 | + ref="reference" | |
4 | + tabindex="0" | |
5 | + @click="handleClick" | |
6 | + @keydown.esc="handleEscape" | |
7 | + @keydown.enter="handleEnter" | |
8 | + @keydown.left="handleArrow($event, 'x', left)" | |
9 | + @keydown.right="handleArrow($event, 'x', right)" | |
10 | + @keydown.up="handleArrow($event, 'y', up)" | |
11 | + @keydown.down="handleArrow($event, 'y', down)" | |
12 | + @blur="blurColor" | |
13 | + @focus="focusColor" | |
14 | + > | |
3 | 15 | <template v-for="(item, index) in list"> |
4 | - <span @click="handleClick(index)"><em :style="{'background': item}"></em></span> | |
5 | - <br v-if="(index + 1) % 12 === 0 && index !== 0 && (index + 1) !== list.length"> | |
16 | + <div | |
17 | + :key="item + ':' + index" | |
18 | + :class="[prefixCls + '-picker-colors-wrapper']"> | |
19 | + <div :data-color-id="index"> | |
20 | + <div | |
21 | + :style="{background: item}" | |
22 | + :class="[prefixCls + '-picker-colors-wrapper-color']" | |
23 | + ></div> | |
24 | + <div | |
25 | + :ref="'color-circle-' + index" | |
26 | + :class="[prefixCls + '-picker-colors-wrapper-circle', hideClass]"></div> | |
27 | + </div> | |
28 | + </div> | |
29 | + <br v-if="lineBreak(list, index)"> | |
6 | 30 | </template> |
7 | 31 | </div> |
8 | 32 | </template> |
33 | + | |
9 | 34 | <script> |
10 | - export default { | |
11 | - props: { | |
12 | - list: Array | |
35 | +import Emitter from '../../mixins/emitter'; | |
36 | +import HandleEscapeMixin from './handleEscapeMixin'; | |
37 | +import Prefixes from './prefixMixin'; | |
38 | +import {clamp} from './utils'; | |
39 | + | |
40 | +export default { | |
41 | + name: 'RecommendedColors', | |
42 | + | |
43 | + mixins: [Emitter, HandleEscapeMixin, Prefixes], | |
44 | + | |
45 | + props: { | |
46 | + list: { | |
47 | + type: Array, | |
48 | + default: undefined, | |
13 | 49 | }, |
14 | - methods: { | |
15 | - handleClick (index) { | |
16 | - this.$emit('picker-color', this.list[index]); | |
50 | + }, | |
51 | + | |
52 | + data() { | |
53 | + const columns = 12; | |
54 | + const rows = Math.ceil(this.list.length / columns); | |
55 | + const normalStep = 1; | |
56 | + | |
57 | + return { | |
58 | + left: -normalStep, | |
59 | + right: normalStep, | |
60 | + up: -normalStep, | |
61 | + down: normalStep, | |
62 | + powerKey: 'shiftKey', | |
63 | + grid: {x: 1, y: 1}, | |
64 | + rows, | |
65 | + columns, | |
66 | + }; | |
67 | + }, | |
68 | + | |
69 | + computed: { | |
70 | + hideClass() { | |
71 | + return `${this.prefixCls}-hide`; | |
72 | + }, | |
73 | + linearIndex() { | |
74 | + return this.getLinearIndex(this.grid); | |
75 | + }, | |
76 | + currentCircle() { | |
77 | + return this.$refs[`color-circle-${this.linearIndex}`][0]; | |
78 | + }, | |
79 | + }, | |
80 | + | |
81 | + methods: { | |
82 | + getLinearIndex(grid) { | |
83 | + return this.columns * (grid.y - 1) + grid.x - 1; | |
84 | + }, | |
85 | + getMaxLimit(axis) { | |
86 | + return axis === 'x' ? this.columns : this.rows; | |
87 | + }, | |
88 | + handleArrow(e, axis, direction) { | |
89 | + e.preventDefault(); | |
90 | + e.stopPropagation(); | |
91 | + | |
92 | + this.blurColor(); | |
93 | + | |
94 | + const grid = {...this.grid}; | |
95 | + | |
96 | + if (e[this.powerKey]) { | |
97 | + if (direction < 0) { | |
98 | + grid[axis] = 1; | |
99 | + } else { | |
100 | + grid[axis] = this.getMaxLimit(axis); | |
101 | + } | |
102 | + } else { | |
103 | + grid[axis] += direction; | |
104 | + } | |
105 | + | |
106 | + const index = this.getLinearIndex(grid); | |
107 | + | |
108 | + if (index >= 0 && index < this.list.length) { | |
109 | + this.grid[axis] = clamp(grid[axis], 1, this.getMaxLimit(axis)); | |
110 | + } | |
111 | + | |
112 | + this.focusColor(); | |
113 | + }, | |
114 | + blurColor() { | |
115 | + this.currentCircle.classList.add(this.hideClass); | |
116 | + }, | |
117 | + focusColor() { | |
118 | + this.currentCircle.classList.remove(this.hideClass); | |
119 | + }, | |
120 | + handleEnter(e) { | |
121 | + this.handleClick(e, this.currentCircle); | |
122 | + }, | |
123 | + handleClick(e, circle) { | |
124 | + e.preventDefault(); | |
125 | + e.stopPropagation(); | |
126 | + | |
127 | + this.$refs.reference.focus(); | |
128 | + | |
129 | + const target = circle || e.target; | |
130 | + const colorId = target.dataset.colorId || target.parentElement.dataset.colorId; | |
131 | + | |
132 | + if (colorId) { | |
133 | + this.blurColor(); | |
134 | + const id = Number(colorId) + 1; | |
135 | + this.grid.x = id % this.columns || this.columns; | |
136 | + this.grid.y = Math.ceil(id / this.columns); | |
137 | + this.focusColor(); | |
138 | + this.$emit('picker-color', this.list[colorId]); | |
139 | + this.$emit('change', {hex: this.list[colorId], source: 'hex'}); | |
17 | 140 | } |
18 | - } | |
19 | - }; | |
20 | -</script> | |
21 | 141 | \ No newline at end of file |
142 | + }, | |
143 | + lineBreak(list, index) { | |
144 | + if (!index) { | |
145 | + return false; | |
146 | + } | |
147 | + | |
148 | + const nextIndex = index + 1; | |
149 | + | |
150 | + return nextIndex < list.length && nextIndex % this.columns === 0; | |
151 | + }, | |
152 | + }, | |
153 | +}; | |
154 | +</script> | ... | ... |
src/components/color-picker/saturation.vue
1 | 1 | <template> |
2 | - <div class="ivu-color-picker-saturation-wrapper"> | |
2 | + <div | |
3 | + :class="[prefixCls + '-saturation-wrapper']" | |
4 | + tabindex="0" | |
5 | + @keydown.esc="handleEscape" | |
6 | + @click="$el.focus()" | |
7 | + @keydown.left="handleLeft" | |
8 | + @keydown.right="handleRight" | |
9 | + @keydown.up="handleUp" | |
10 | + @keydown.down="handleDown" | |
11 | + > | |
3 | 12 | <div |
4 | - class="ivu-color-picker-saturation" | |
5 | - :style="{background: bgColor}" | |
6 | 13 | ref="container" |
14 | + :style="bgColorStyle" | |
15 | + :class="[prefixCls + '-saturation']" | |
7 | 16 | @mousedown="handleMouseDown"> |
8 | - <div class="ivu-color-picker-saturation--white"></div> | |
9 | - <div class="ivu-color-picker-saturation--black"></div> | |
10 | - <div class="ivu-color-picker-saturation-pointer" :style="{top: pointerTop, left: pointerLeft}"> | |
11 | - <div class="ivu-color-picker-saturation-circle"></div> | |
17 | + <div :class="[prefixCls + '-saturation--white']"></div> | |
18 | + <div :class="[prefixCls + '-saturation--black']"></div> | |
19 | + <div | |
20 | + :style="pointerStyle" | |
21 | + :class="[prefixCls + '-saturation-pointer']"> | |
22 | + <div :class="[prefixCls + '-saturation-circle']"></div> | |
12 | 23 | </div> |
13 | 24 | </div> |
14 | 25 | </div> |
15 | 26 | </template> |
27 | + | |
16 | 28 | <script> |
17 | - import throttle from 'lodash.throttle'; | |
29 | +import HSAMixin from './hsaMixin'; | |
30 | +import Prefixes from './prefixMixin'; | |
31 | +import {clamp, getIncrement} from './utils'; | |
32 | + | |
33 | +export default { | |
34 | + name: 'Saturation', | |
35 | + | |
36 | + mixins: [HSAMixin, Prefixes], | |
37 | + | |
38 | + data() { | |
39 | + const normalStep = 0.01; | |
40 | + | |
41 | + return { | |
42 | + left: -normalStep, | |
43 | + right: normalStep, | |
44 | + up: normalStep, | |
45 | + down: -normalStep, | |
46 | + multiplier: 10, | |
47 | + powerKey: 'shiftKey', | |
48 | + }; | |
49 | + }, | |
50 | + | |
51 | + computed: { | |
52 | + bgColorStyle() { | |
53 | + return {background: `hsl(${this.value.hsv.h}, 100%, 50%)`}; | |
54 | + }, | |
55 | + pointerStyle() { | |
56 | + return {top: `${-(this.value.hsv.v * 100) + 1 + 100}%`, left: `${this.value.hsv.s * 100}%`}; | |
57 | + }, | |
58 | + }, | |
59 | + | |
60 | + methods: { | |
61 | + change(h, s, v, a) { | |
62 | + this.$emit('change', {h, s, v, a, source: 'hsva'}); | |
63 | + }, | |
64 | + handleSlide(e, direction, key) { | |
65 | + e.preventDefault(); | |
66 | + e.stopPropagation(); | |
67 | + | |
68 | + const isPowerKey = e[this.powerKey]; | |
69 | + const increment = isPowerKey ? direction * this.multiplier : direction; | |
70 | + const {h, s, v, a} = this.value.hsv; | |
71 | + const saturation = clamp(s + getIncrement(key, ['left', 'right'], increment), 0, 1); | |
72 | + const bright = clamp(v + getIncrement(key, ['up', 'down'], increment), 0, 1); | |
73 | + | |
74 | + this.change(h, saturation, bright, a); | |
75 | + }, | |
76 | + handleChange(e) { | |
77 | + e.preventDefault(); | |
78 | + e.stopPropagation(); | |
79 | + | |
80 | + const {clientWidth, clientHeight} = this.$refs.container; | |
81 | + const left = clamp(this.getLeft(e), 0, clientWidth); | |
82 | + const top = clamp(this.getTop(e), 0, clientHeight); | |
83 | + const saturation = left / clientWidth; | |
84 | + const bright = clamp(1 - top / clientHeight, 0, 1); | |
18 | 85 | |
19 | - export default { | |
20 | - name: 'Saturation', | |
21 | - props: { | |
22 | - value: Object | |
86 | + this.change(this.value.hsv.h, saturation, bright, this.value.hsv.a); | |
23 | 87 | }, |
24 | - data () { | |
25 | - return {}; | |
88 | + handleMouseDown(e) { | |
89 | + HSAMixin.methods.handleMouseDown.call(this, e); | |
90 | + window.addEventListener('mouseup', this.handleChange, false); | |
26 | 91 | }, |
27 | - computed: { | |
28 | - colors () { | |
29 | - return this.value; | |
30 | - }, | |
31 | - bgColor () { | |
32 | - return `hsl(${this.colors.hsv.h}, 100%, 50%)`; | |
33 | - }, | |
34 | - pointerTop () { | |
35 | - return (-(this.colors.hsv.v * 100) + 1) + 100 + '%'; | |
36 | - }, | |
37 | - pointerLeft () { | |
38 | - return this.colors.hsv.s * 100 + '%'; | |
39 | - } | |
92 | + unbindEventListeners(e) { | |
93 | + HSAMixin.methods.unbindEventListeners.call(this, e); | |
94 | + window.removeEventListener('mouseup', this.handleChange); | |
40 | 95 | }, |
41 | - methods: { | |
42 | - throttle: throttle((fn, data) => {fn(data);}, 20, | |
43 | - { | |
44 | - 'leading': true, | |
45 | - 'trailing': false | |
46 | - }), | |
47 | - handleChange (e, skip) { | |
48 | - !skip && e.preventDefault(); | |
49 | - const container = this.$refs.container; | |
50 | - const containerWidth = container.clientWidth; | |
51 | - const containerHeight = container.clientHeight; | |
52 | - const xOffset = container.getBoundingClientRect().left + window.pageXOffset; | |
53 | - const yOffset = container.getBoundingClientRect().top + window.pageYOffset; | |
54 | - const pageX = e.pageX || (e.touches ? e.touches[0].pageX : 0); | |
55 | - const pageY = e.pageY || (e.touches ? e.touches[0].pageY : 0); | |
56 | - let left = pageX - xOffset; | |
57 | - let top = pageY - yOffset; | |
58 | - if (left < 0) { | |
59 | - left = 0; | |
60 | - } else if (left > containerWidth) { | |
61 | - left = containerWidth; | |
62 | - } else if (top < 0) { | |
63 | - top = 0; | |
64 | - } else if (top > containerHeight) { | |
65 | - top = containerHeight; | |
66 | - } | |
67 | - const saturation = left / containerWidth; | |
68 | - let bright = -(top / containerHeight) + 1; | |
69 | - bright = bright > 0 ? bright : 0; | |
70 | - bright = bright > 1 ? 1 : bright; | |
71 | - this.throttle(this.onChange, { | |
72 | - h: this.colors.hsv.h, | |
73 | - s: saturation, | |
74 | - v: bright, | |
75 | - a: this.colors.hsv.a, | |
76 | - source: 'hsva' | |
77 | - }); | |
78 | - }, | |
79 | - onChange (param) { | |
80 | - this.$emit('change', param); | |
81 | - }, | |
82 | - handleMouseDown () { | |
83 | - // this.handleChange(e, true) | |
84 | - window.addEventListener('mousemove', this.handleChange); | |
85 | - window.addEventListener('mouseup', this.handleChange); | |
86 | - window.addEventListener('mouseup', this.handleMouseUp); | |
87 | - }, | |
88 | - handleMouseUp () { | |
89 | - this.unbindEventListeners(); | |
90 | - }, | |
91 | - unbindEventListeners () { | |
92 | - window.removeEventListener('mousemove', this.handleChange); | |
93 | - window.removeEventListener('mouseup', this.handleChange); | |
94 | - window.removeEventListener('mouseup', this.handleMouseUp); | |
95 | - } | |
96 | - } | |
97 | - }; | |
98 | -</script> | |
99 | 96 | \ No newline at end of file |
97 | + }, | |
98 | +}; | |
99 | +</script> | ... | ... |
1 | +import tinycolor from 'tinycolor2'; | |
2 | +import {oneOf} from '../../utils/assist'; | |
3 | + | |
4 | +function setAlpha(data, alpha) { | |
5 | + const color = tinycolor(data); | |
6 | + const {_a} = color; | |
7 | + | |
8 | + if (_a === undefined || _a === null) { | |
9 | + color.setAlpha(alpha || 1); | |
10 | + } | |
11 | + | |
12 | + return color; | |
13 | +} | |
14 | + | |
15 | +function getColor(data, colorData) { | |
16 | + const alpha = colorData && colorData.a; | |
17 | + | |
18 | + if (colorData) { | |
19 | + // hsl is better than hex between conversions | |
20 | + if (colorData.hsl) { | |
21 | + return setAlpha(colorData.hsl, alpha); | |
22 | + } | |
23 | + | |
24 | + if (colorData.hex && colorData.hex.length > 0) { | |
25 | + return setAlpha(colorData.hex, alpha); | |
26 | + } | |
27 | + } | |
28 | + | |
29 | + return setAlpha(colorData, alpha); | |
30 | +} | |
31 | + | |
32 | +export function changeColor(data, oldHue) { | |
33 | + const colorData = data === '' ? '#2d8cf0' : data; | |
34 | + const color = getColor(data, colorData); | |
35 | + const hsl = color.toHsl(); | |
36 | + const hsv = color.toHsv(); | |
37 | + | |
38 | + if (hsl.s === 0) { | |
39 | + hsl.h = colorData.h || (colorData.hsl && colorData.hsl.h) || oldHue || 0; | |
40 | + hsv.h = hsl.h; | |
41 | + } | |
42 | + | |
43 | + // when the hsv.v is less than 0.0164 (base on test) | |
44 | + // because of possible loss of precision | |
45 | + // the result of hue and saturation would be miscalculated | |
46 | + if (hsv.v < 0.0164) { | |
47 | + hsv.h = colorData.h || (colorData.hsv && colorData.hsv.h) || 0; | |
48 | + hsv.s = colorData.s || (colorData.hsv && colorData.hsv.s) || 0; | |
49 | + } | |
50 | + | |
51 | + if (hsl.l < 0.01) { | |
52 | + hsl.h = colorData.h || (colorData.hsl && colorData.hsl.h) || 0; | |
53 | + hsl.s = colorData.s || (colorData.hsl && colorData.hsl.s) || 0; | |
54 | + } | |
55 | + | |
56 | + return { | |
57 | + hsl, | |
58 | + hex: color.toHexString().toUpperCase(), | |
59 | + rgba: color.toRgb(), | |
60 | + hsv, | |
61 | + oldHue: colorData.h || oldHue || hsl.h, | |
62 | + source: colorData.source, | |
63 | + a: colorData.a || color.getAlpha(), | |
64 | + }; | |
65 | +} | |
66 | + | |
67 | +export function clamp(value, min, max) { | |
68 | + if (value < min) { | |
69 | + return min; | |
70 | + } | |
71 | + | |
72 | + if (value > max) { | |
73 | + return max; | |
74 | + } | |
75 | + | |
76 | + return value; | |
77 | +} | |
78 | + | |
79 | +export function getIncrement(key, keys, increment) { | |
80 | + return oneOf(key, keys) ? increment : 0; | |
81 | +} | |
82 | + | |
83 | +export function getTouches(e, prop) { | |
84 | + return e.touches ? e.touches[0][prop] : 0; | |
85 | +} | |
86 | + | |
87 | +export function toRGBAString(rgba) { | |
88 | + const {r, g, b, a} = rgba; | |
89 | + | |
90 | + return `rgba(${[r, g, b, a].join(',')})`; | |
91 | +} | |
92 | + | |
93 | +export function isValidHex(hex) { | |
94 | + return tinycolor(hex).isValid(); | |
95 | +} | |
96 | + | |
97 | +function checkIteratee(data, counts, letter) { | |
98 | + let {checked, passed} = counts; | |
99 | + const value = data[letter]; | |
100 | + | |
101 | + if (value) { | |
102 | + checked += 1; | |
103 | + | |
104 | + if (Number.isFinite(value)) { | |
105 | + passed += 1; | |
106 | + } | |
107 | + } | |
108 | + | |
109 | + return {checked, passed}; | |
110 | +} | |
111 | + | |
112 | +const keysToCheck = ['r', 'g', 'b', 'a', 'h', 's', 'l', 'v']; | |
113 | + | |
114 | +export function simpleCheckForValidColor(data) { | |
115 | + const results = keysToCheck.reduce(checkIteratee.bind(null, data), {checked: 0, passed: 0}); | |
116 | + | |
117 | + return results.checked === results.passed ? data : undefined; | |
118 | +} | ... | ... |
src/styles/components/color-picker.less
1 | -@color-picker-prefix-cls: ~"@{css-prefix}color-picker"; | |
1 | +@color-picker-prefix-cls: ~'@{css-prefix}color-picker'; | |
2 | 2 | |
3 | 3 | .@{color-picker-prefix-cls} { |
4 | 4 | display: inline-block; |
5 | + &-hide { | |
6 | + display: none; | |
7 | + &-drop { | |
8 | + visibility: hidden; | |
9 | + } | |
10 | + } | |
11 | + &-disabled { | |
12 | + background-color: @input-disabled-bg; | |
13 | + opacity: 1; | |
14 | + cursor: @cursor-disabled; | |
15 | + color: #ccc; | |
16 | + } | |
17 | + & > div:first-child:hover { | |
18 | + .ivu-input { | |
19 | + border-color: @input-hover-border-color; | |
20 | + } | |
21 | + } | |
22 | + & > div:first-child.@{color-picker-prefix-cls}-disabled:hover { | |
23 | + .ivu-input { | |
24 | + border-color: tint(@input-border-color, 20%); | |
25 | + } | |
26 | + } | |
5 | 27 | & .@{select-dropdown-prefix-cls} { |
6 | 28 | padding: 0; |
7 | 29 | } |
8 | - &-rel{ | |
30 | + &-focused { | |
31 | + box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%); | |
32 | + } | |
33 | + &-rel { | |
9 | 34 | line-height: 0; |
10 | 35 | } |
11 | - &-color{ | |
36 | + &-color { | |
12 | 37 | width: 18px; |
13 | 38 | height: 18px; |
14 | 39 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==); |
15 | 40 | border-radius: 2px; |
16 | 41 | position: relative; |
17 | 42 | top: 2px; |
18 | - div{ | |
43 | + div { | |
19 | 44 | width: 100%; |
20 | 45 | height: 100%; |
21 | - box-shadow: inset 0 0 0 1px rgba(0,0,0,.15); | |
46 | + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15); | |
22 | 47 | border-radius: 2px; |
23 | 48 | } |
24 | - &-empty{ | |
49 | + &-empty { | |
25 | 50 | background: #fff; |
26 | 51 | overflow: hidden; |
27 | 52 | text-align: center; |
28 | - i{ | |
53 | + i { | |
29 | 54 | font-size: 18px; |
30 | 55 | } |
31 | 56 | } |
57 | + &-focused { | |
58 | + box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%); | |
59 | + } | |
32 | 60 | } |
33 | - &-large &-color{ | |
61 | + &-large &-color { | |
34 | 62 | width: 20px; |
35 | 63 | height: 20px; |
36 | 64 | top: 1px; |
37 | - &-empty{ | |
38 | - i{ | |
65 | + &-empty { | |
66 | + i { | |
39 | 67 | font-size: 20px; |
40 | 68 | } |
41 | 69 | } |
42 | 70 | } |
43 | - &-small &-color{ | |
71 | + &-small &-color { | |
44 | 72 | width: 14px; |
45 | 73 | height: 14px; |
46 | 74 | top: 3px; |
47 | - &-empty{ | |
48 | - i{ | |
75 | + &-empty { | |
76 | + i { | |
49 | 77 | font-size: 14px; |
50 | 78 | } |
51 | 79 | } |
52 | 80 | } |
53 | 81 | |
54 | - &-picker{ | |
55 | - &-wrapper{ | |
82 | + &-picker { | |
83 | + &-wrapper { | |
56 | 84 | padding: 8px 8px 0; |
57 | 85 | } |
58 | - &-panel{ | |
86 | + &-panel { | |
59 | 87 | width: 240px; |
60 | 88 | margin: 0 auto; |
61 | 89 | box-sizing: initial; |
62 | 90 | position: relative; |
63 | 91 | } |
64 | - &-hue-slider, &-alpha-slider{ | |
92 | + &-hue-slider, | |
93 | + &-alpha-slider { | |
65 | 94 | height: 10px; |
66 | 95 | margin-top: 8px; |
67 | 96 | position: relative; |
68 | 97 | } |
69 | - &-colors{ | |
98 | + &-colors { | |
70 | 99 | margin-top: 8px; |
71 | 100 | overflow: hidden; |
72 | - span{ | |
73 | - display: inline-block; | |
101 | + outline: 0; | |
102 | + border: 1px solid @input-border-color; | |
103 | + transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out; | |
104 | + &:hover { | |
105 | + border: 1px solid @input-hover-border-color; | |
106 | + } | |
107 | + &:focus { | |
108 | + box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%); | |
109 | + } | |
110 | + &-wrapper { | |
111 | + display: inline; | |
74 | 112 | width: 20px; |
75 | 113 | height: 20px; |
76 | 114 | float: left; |
77 | - em{ | |
115 | + position: relative; | |
116 | + &-color { | |
117 | + outline: 0; | |
78 | 118 | display: block; |
119 | + position: absolute; | |
79 | 120 | width: 16px; |
80 | 121 | height: 16px; |
81 | 122 | margin: 2px; |
82 | 123 | cursor: pointer; |
83 | 124 | border-radius: 2px; |
84 | - box-shadow: inset 0 0 0 1px rgba(0,0,0,.15); | |
125 | + border: 1px solid @input-border-color; | |
126 | + transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out; | |
127 | + &:hover { | |
128 | + border: 1px solid @input-hover-border-color; | |
129 | + } | |
130 | + &:focus { | |
131 | + box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%); | |
132 | + } | |
133 | + } | |
134 | + &-circle { | |
135 | + cursor: pointer; | |
136 | + top: 10px; | |
137 | + left: 10px; | |
138 | + position: absolute; | |
139 | + width: 4px; | |
140 | + height: 4px; | |
141 | + 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); | |
142 | + border-radius: 50%; | |
143 | + transform: translate(-2px, -2px); | |
85 | 144 | } |
86 | 145 | } |
87 | 146 | } |
88 | - .@{picker-prefix-cls}-confirm{ | |
147 | + .@{picker-prefix-cls}-confirm { | |
89 | 148 | margin-top: 8px; |
90 | 149 | } |
91 | 150 | } |
92 | 151 | |
93 | - &-saturation{ | |
94 | - &-wrapper{ | |
152 | + &-saturation { | |
153 | + &-wrapper { | |
95 | 154 | width: 100%; |
96 | 155 | padding-bottom: 75%; |
97 | 156 | position: relative; |
98 | 157 | overflow: hidden; |
158 | + outline: 0; | |
159 | + border: 1px solid @input-border-color; | |
160 | + box-shadow: @shadow-base; | |
161 | + transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out; | |
162 | + &:hover { | |
163 | + border: 1px solid @input-hover-border-color; | |
164 | + } | |
165 | + &:focus { | |
166 | + box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%); | |
167 | + } | |
99 | 168 | } |
100 | - &, &--white, &--black{ | |
169 | + &, | |
170 | + &--white, | |
171 | + &--black { | |
101 | 172 | cursor: pointer; |
102 | 173 | position: absolute; |
103 | 174 | top: 0; |
... | ... | @@ -105,26 +176,26 @@ |
105 | 176 | right: 0; |
106 | 177 | bottom: 0; |
107 | 178 | } |
108 | - &--white{ | |
109 | - background: linear-gradient(to right, #fff, rgba(255,255,255,0)); | |
179 | + &--white { | |
180 | + background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0)); | |
110 | 181 | } |
111 | - &--black{ | |
112 | - background: linear-gradient(to top, #000, rgba(0,0,0,0)); | |
182 | + &--black { | |
183 | + background: linear-gradient(to top, #000, rgba(0, 0, 0, 0)); | |
113 | 184 | } |
114 | - &-pointer{ | |
185 | + &-pointer { | |
115 | 186 | cursor: pointer; |
116 | 187 | position: absolute; |
117 | 188 | } |
118 | - &-circle{ | |
189 | + &-circle { | |
119 | 190 | width: 4px; |
120 | 191 | height: 4px; |
121 | - 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); | |
192 | + 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); | |
122 | 193 | border-radius: 50%; |
123 | 194 | transform: translate(-2px, -2px); |
124 | 195 | } |
125 | 196 | } |
126 | 197 | |
127 | - &-hue{ | |
198 | + &-hue { | |
128 | 199 | position: absolute; |
129 | 200 | top: 0; |
130 | 201 | right: 0; |
... | ... | @@ -132,35 +203,55 @@ |
132 | 203 | left: 0; |
133 | 204 | border-radius: 2px; |
134 | 205 | background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%); |
135 | - &-container{ | |
206 | + outline: 0; | |
207 | + border: 1px solid @input-border-color; | |
208 | + box-shadow: @shadow-base; | |
209 | + transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out; | |
210 | + &:hover { | |
211 | + border: 1px solid @input-hover-border-color; | |
212 | + } | |
213 | + &:focus { | |
214 | + box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%); | |
215 | + } | |
216 | + &-container { | |
136 | 217 | cursor: pointer; |
137 | 218 | margin: 0 2px; |
138 | 219 | position: relative; |
139 | 220 | height: 100%; |
140 | 221 | } |
141 | - &-pointer{ | |
222 | + &-pointer { | |
142 | 223 | z-index: 2; |
143 | 224 | position: absolute; |
144 | 225 | } |
145 | - &-picker{ | |
226 | + &-picker { | |
146 | 227 | cursor: pointer; |
147 | 228 | margin-top: 1px; |
148 | 229 | width: 4px; |
149 | 230 | border-radius: 1px; |
150 | 231 | height: 8px; |
151 | - box-shadow: 0 0 2px rgba(0, 0, 0, .6); | |
232 | + box-shadow: 0 0 2px rgba(0, 0, 0, 0.6); | |
152 | 233 | background: #fff; |
153 | 234 | transform: translateX(-2px); |
154 | 235 | } |
155 | 236 | } |
156 | 237 | |
157 | - &-alpha{ | |
238 | + &-alpha { | |
158 | 239 | position: absolute; |
159 | 240 | top: 0; |
160 | 241 | right: 0; |
161 | 242 | bottom: 0; |
162 | 243 | left: 0; |
163 | - &-checkboard-wrap{ | |
244 | + outline: 0; | |
245 | + border: 1px solid @input-border-color; | |
246 | + box-shadow: @shadow-base; | |
247 | + transition: border @transition-time @ease-in-out, box-shadow @transition-time @ease-in-out; | |
248 | + &:hover { | |
249 | + border: 1px solid @input-hover-border-color; | |
250 | + } | |
251 | + &:focus { | |
252 | + box-shadow: 0 0 0 2px fade(@input-hover-border-color, 20%); | |
253 | + } | |
254 | + &-checkboard-wrap { | |
164 | 255 | position: absolute; |
165 | 256 | top: 0; |
166 | 257 | right: 0; |
... | ... | @@ -169,7 +260,7 @@ |
169 | 260 | overflow: hidden; |
170 | 261 | border-radius: 2px; |
171 | 262 | } |
172 | - &-checkerboard{ | |
263 | + &-checkerboard { | |
173 | 264 | position: absolute; |
174 | 265 | top: 0; |
175 | 266 | right: 0; |
... | ... | @@ -177,7 +268,7 @@ |
177 | 268 | left: 0; |
178 | 269 | background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==); |
179 | 270 | } |
180 | - &-gradient{ | |
271 | + &-gradient { | |
181 | 272 | position: absolute; |
182 | 273 | top: 0; |
183 | 274 | right: 0; |
... | ... | @@ -185,32 +276,37 @@ |
185 | 276 | left: 0; |
186 | 277 | border-radius: 2px; |
187 | 278 | } |
188 | - &-container{ | |
279 | + &-container { | |
189 | 280 | cursor: pointer; |
190 | 281 | position: relative; |
191 | 282 | z-index: 2; |
192 | 283 | height: 100%; |
193 | 284 | margin: 0 3px; |
194 | 285 | } |
195 | - &-pointer{ | |
286 | + &-pointer { | |
196 | 287 | z-index: 2; |
197 | 288 | position: absolute; |
198 | 289 | } |
199 | - &-picker{ | |
290 | + &-picker { | |
200 | 291 | cursor: pointer; |
201 | 292 | width: 4px; |
202 | 293 | border-radius: 1px; |
203 | 294 | height: 8px; |
204 | - box-shadow: 0 0 2px rgba(0, 0, 0, .6); | |
295 | + box-shadow: 0 0 2px rgba(0, 0, 0, 0.6); | |
205 | 296 | background: #fff; |
206 | 297 | margin-top: 1px; |
207 | 298 | transform: translateX(-2px); |
208 | 299 | } |
209 | 300 | } |
210 | 301 | |
211 | - &-confirm{ | |
302 | + &-confirm { | |
303 | + margin-top: 8px; | |
212 | 304 | position: relative; |
213 | - &-color{ | |
305 | + border-top: 1px solid @border-color-split; | |
306 | + text-align: right; | |
307 | + padding: 8px; | |
308 | + clear: both; | |
309 | + &-color { | |
214 | 310 | position: absolute; |
215 | 311 | top: 11px; |
216 | 312 | left: 8px; | ... | ... |
src/styles/mixins/input.less
... | ... | @@ -6,7 +6,6 @@ |
6 | 6 | } |
7 | 7 | |
8 | 8 | .active(@color: @input-hover-border-color) { |
9 | - border-color: tint(@color, 20%); | |
10 | 9 | outline: 0; |
11 | 10 | box-shadow: 0 0 0 2px fade(@color, 20%); |
12 | 11 | } |
... | ... | @@ -266,4 +265,4 @@ |
266 | 265 | &-append { |
267 | 266 | border-left: 0; |
268 | 267 | } |
269 | -} | |
270 | 268 | \ No newline at end of file |
269 | +} | ... | ... |