Keen-UI
Keen-UI copied to clipboard
UiColorPicker 0.1
I have worked a bit on a fix that immitates Keen-UI with vue-color
that's an wrapper for tinycolor2
.
It relies on:
- Bootstrap 3
- Vue-Color https://github.com/xiaokaike/vue-color
- TinyColor https://github.com/bgrins/TinyColor
Here's the full source of my component, it's far from perfect yet, but it has some features. I wasn't able to use UiTextbox as the popup would fail. Feel free to make a more proper implementation and hopefully add it to the Keen-UI library.
<template>
<div>
<div
class="input-group color-picker"
ref="colorpicker">
<span
class="input-group-addon color-picker-container">
<span
class="color-icon"
@click="togglePicker">
<i
class="material-icons"
v-if="icon">
{{ icon }}
</i>
</span>
<chrome-picker
:value="colors"
@input="updateFromPicker"
v-if="displayPicker">
</chrome-picker>
</span>
<div>
<label
v-if="label">
{{ label }}
</label>
<input
type="text"
:class="{
'form-control': true,
'focus': displayPicker
}"
v-model="colorValue"
@focus="showPicker"
@input="updateFromInput">
<div
class="help"
v-if="help">
{{ help }}
</div>
</div>
</div>
</div>
</template>
<script>
Vue.component('ChromePicker', require('vue-color/src/components/Chrome.vue'))
export default {
props: {
/**
* Bind color to external (preset) value.
*/
color: {
type: String,
default: ''
},
/**
*
*/
label: {
type: String,
default: 'Color'
},
/**
*
*/
icon: {
type: String,
default: 'invert_colors'
},
/**
*
*/
help: {
type: String,
default: null
}
},
data() {
return {
colors: {
hex: '#000000',
},
colorValue: this.color,
displayPicker: false,
}
},
/**
*
*/
mounted() {
this.setColor(this.color || '#000000');
},
methods: {
/**
*
* @param color
*/
setColor(color) {
this.updateColors(color);
this.colorValue = color;
},
/**
*
* @param color
*/
updateColors(color) {
let rgba = color.replace(/^rgba?\(|\s+|\)$/g,'').split(','),
hex = '#' + ((1 << 24) + (parseInt(rgba[0]) << 16) + (parseInt(rgba[1]) << 8) + parseInt(rgba[2])).toString(16).slice(1);
this.colors = {
hex: hex,
a: rgba[3],
}
},
/**
*
*/
showPicker() {
document.addEventListener('click', this.documentClick)
this.displayPicker = true
},
/**
*
*/
hidePicker() {
document.removeEventListener('click', this.documentClick)
this.displayPicker = false
},
/**
*
*/
togglePicker() {
this.displayPicker ? this.hidePicker() : this.showPicker()
},
/**
*
*/
updateFromInput() {
this.updateColors(this.colorValue)
},
/**
*
* @param color
*/
updateFromPicker(color) {
this.colors = color
this.colorValue = 'rgba(' + color.rgba.r + ', ' + color.rgba.g + ', ' + color.rgba.b + ', ' + color.rgba.a + ')'
},
/**
*
* @param e
*/
documentClick(e) {
console.log('document click')
let el = this.$refs.colorpicker,
target = e.target;
if (el !== target && !el.contains(target))
this.hidePicker()
}
},
watch: {
/**
*
* @param val
*/
colorValue(val) {
if (val) {
this.updateColors(val)
this.$emit('input', val)
}
}
}
}
</script>
<style lang="scss" scoped>
.input-group {
margin-bottom: 1rem;
}
label {
font-weight: bold;
color: rgba(0, 0, 0, 0.54);
font-size: 0.9375rem;
line-height: normal;
margin-left: 0.75rem;
}
.input-group-addon {
border-radius: 0;
border: none;
background-color: transparent;
padding: 0;
margin-bottom: 1rem;
i {
font-size: 1.5rem;
color: rgba(0, 0, 0, 0.54);
padding-top: 1.5rem;
}
}
.form-control {
border: none;
border-bottom: 1px solid #ececec;
border-radius: 0;
box-shadow: none;
padding: 0;
font-family: Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
margin-left: 0.75rem;
font-size: 1rem;
color: rgba(0, 0, 0, 0.87);
height: 2rem;
&:focus,
&.focus {
outline: none;
border-bottom: 2px solid #2196f3;
}
}
.vc-chrome {
position: absolute;
top: 45px;
left: 0;
z-index: 9;
margin-left: 2.3rem;
}
.help {
padding-top: 0.25rem;
margin-left: 0.75rem;
color: rgba(0, 0, 0, 0.54);
font-size: 0.875rem;
line-height: 1.2;
}
</style>