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 | +} | ... | ... |