feat: added color-picker-converter.vue

This commit is contained in:
Corentin Thomasset 2021-04-01 18:47:42 +02:00
parent f1d8d55cce
commit 4fdc09a787
No known key found for this signature in database
GPG key ID: DBD997E935996158
3 changed files with 237 additions and 7 deletions

50
package-lock.json generated
View file

@ -2765,6 +2765,12 @@
"source-map": "^0.6.0"
}
},
"@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
"dev": true
},
"@types/compression": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.0.tgz",
@ -3842,6 +3848,21 @@
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": {
"color-convert": "^1.9.0"
},
"dependencies": {
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
}
}
},
"anymatch": {
@ -5198,20 +5219,35 @@
"requires": {
"color-convert": "^1.9.1",
"color-string": "^1.5.4"
},
"dependencies": {
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
}
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "1.1.3"
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"color-string": {
"version": "1.5.4",

View file

@ -17,6 +17,8 @@
"@nuxtjs/pwa": "^3.0.2",
"@nuxtjs/toast": "^3.3.1",
"bip39": "^3.0.3",
"color-convert": "^2.0.1",
"color-name": "^1.1.4",
"core-js": "^3.6.5",
"crypto-js": "^4.0.0",
"nuxt": "^2.14.12",
@ -32,6 +34,8 @@
"@nuxtjs/eslint-module": "^2.0.0",
"@nuxtjs/svg": "^0.1.12",
"@nuxtjs/vuetify": "^1.11.2",
"@types/color-convert": "^2.0.0",
"@types/color-name": "^1.1.1",
"@types/crypto-js": "^4.0.1",
"@vue/test-utils": "^1.1.0",
"babel-core": "7.0.0-bridge.0",

View file

@ -0,0 +1,190 @@
<template>
<ToolWrapper :config="config()">
<v-row no-gutters align="center" align-content="center" justify="center">
<v-col cols="12" sm="6" align="center">
<v-color-picker
v-model="rgbPicker"
flat
canvas-height="300"
hide-inputs
mode="rgba"
@input="(v) => updateColors(v, 'picker')"
/>
</v-col>
<v-col cols="12" sm="6" align="center">
<v-text-field
ref="hex"
outlined
label="hex"
:value="hex"
:rules="rules.hex"
append-icon="mdi-content-copy"
@input="(v) => updateColors(v, 'hex')"
@click:append="copy(hex)"
/>
<v-text-field
ref="rgb"
outlined
label="rgb"
:value="rgb"
:rules="rules.rgb"
append-icon="mdi-content-copy"
@input="(v) => updateColors(v, 'rgb')"
@click:append="copy(rgb)"
/>
<v-text-field
ref="hsl"
outlined
label="hsl"
:value="hsl"
:rules="rules.hsl"
append-icon="mdi-content-copy"
@input="(v) => updateColors(v, 'hsl')"
@click:append="copy(hsl)"
/>
<v-combobox
ref="keyword"
:value="keyword"
outlined
label="css keyword"
:items="colorsName"
:rules="rules.keyword"
no-data-text="This is not an authorized color name."
append-icon="mdi-content-copy"
@change="(v) => updateColors(v, 'keyword')"
@click:append="copy(keyword)"
/>
</v-col>
</v-row>
</ToolWrapper>
</template>
<script lang="ts">
import {Component} from 'nuxt-property-decorator'
import colors from 'color-name'
import convert from 'color-convert'
import {CopyableMixin} from '~/mixins/copyable.mixin'
import Tool from '~/components/Tool.vue'
import {ToolConfig} from '~/types/ToolConfig'
import type {VForm} from '~/types/VForm'
const required = (v: unknown) => !!v || 'A value is required'
@Component({
mixins: [CopyableMixin]
})
export default class ColorPickerConverter extends Tool {
config(): ToolConfig {
return {
title: 'Color picker/converter',
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus distinctio dolor dolorum eaque eligendi, facilis impedit laboriosam odit placeat.',
icon: 'mdi-palette',
keywords: ['rgb', 'hsl', 'hex', 'keyword', 'css', 'picker']
}
}
rgbPicker = {
r: 76,
g: 175,
b: 80
}
colorsName = Object.keys(colors).sort()
valid = true
rules = {
hex: [
required,
(v: string) => /^#(?:[0-9a-fA-F]{6})$/.test(v) || 'Format should be like #112233'
],
rgb: [
required,
(v: string) => /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/.test(v) || 'Format should be like rgb(255, 0, 0)'
],
hsl: [
required,
(v: string) => /^hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)$/.test(v) || 'Format should be like hsl(360, 100%, 50%)'
],
keywords: [
required,
(v: string) => this.colorsName.includes(v) || 'Value should be from the list'
]
}
hex = '#4CAF50'
rgb = 'rgb(76, 175, 80)'
hsl = 'hsl(122, 39%, 49%)'
keyword = 'mediumseagreen'
setHSL(r: number, g: number, b: number) {
const [h, s, l] = convert.rgb.hsl(r, g, b)
this.hsl = `hsl(${Math.floor(h)}, ${Math.floor(s)}%, ${Math.floor(l)}%)`
}
setRGB(r: number, g: number, b: number) {
this.rgb = `rgb(${r}, ${g}, ${b})`
}
setHEX(r: number, g: number, b: number) {
const result = convert.rgb.hex(r, g, b)
this.hex = `#${result}`
}
setKeyword(r: number, g: number, b: number) {
this.keyword = convert.rgb.keyword(r, g, b)
}
updateColors(value: string, fromType: string) {
if (fromType === 'picker' || (this.$refs[fromType] as VForm)?.validate()) {
if (fromType === 'rgb') {
const [r, g, b] = value.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/)?.slice(1).map(v => parseInt(v)) ?? [0, 0, 0]
this.rgbPicker = {r, g, b}
this.setHEX(r, g, b)
this.setHSL(r, g, b)
this.setKeyword(r, g, b)
} else if (fromType === 'hex') {
const [r, g, b] = convert.hex.rgb(value.replace(/#/g, ''))
this.rgbPicker = {r, g, b}
this.setRGB(r, g, b)
this.setHSL(r, g, b)
this.setKeyword(r, g, b)
} else if (fromType === 'hsl') {
const [h, s, l] = value.match(/^hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)$/)?.slice(1).map(v => parseInt(v)) ?? [0, 0, 0]
// @ts-ignore
const [r, g, b] = convert.hsl.rgb(h, s, l)
this.rgbPicker = {r, g, b}
this.setRGB(r, g, b)
this.setHEX(r, g, b)
this.setKeyword(r, g, b)
} else if (fromType === 'keyword') {
try {
// @ts-ignore
const [r, g, b] = convert.keyword.rgb(value)
this.rgbPicker = {r, g, b}
this.setRGB(r, g, b)
this.setHEX(r, g, b)
this.setHSL(r, g, b)
} catch (ignored) {
// ignored
}
} else if (fromType === 'picker') {
const {r, g, b} = value as unknown as { r: number, g: number, b: number }
this.setRGB(r, g, b)
this.setHEX(r, g, b)
this.setHSL(r, g, b)
this.setKeyword(r, g, b)
}
}
}
mounted() {
this.updateColors(this.hex, 'hex')
}
}
</script>
<style scoped lang="less">
::v-deep .v-input__icon {
height: 18px !important;
}
</style>