262 lines
11 KiB
Vue

<template>
<div class="grid-container h-screen">
<div class="wrapper">
<div class="grid-header">
<h1 class="text-center text-4xl font-bold">Batch Color Converter</h1>
<button @click="batchConvert" type="button">Convert</button>
</div>
<div class="grid-main">
<div class="input-container">
<textarea v-model="inputBox" class="resize-y w-full h-96 border border-gray-200 shadow rounded py-2 px-4" placeholder="#fff"></textarea>
</div>
<div class="output-wrapper">
<table class="font-ubuntu w-full">
<thead>
<tr>
<th class="p-4">Preview</th>
<th class="p-4">Hex(a)</th>
<th class="p-4">RGB(a)</th>
<th class="p-4">HSL(a)</th>
</tr>
</thead>
<tbody>
<tr v-for="(color, idx) in convertedColors" :key="idx" class="border-t border-gray-300">
<td v-show="color.error" class="text-center px-2 py-4 bg-red-200 text-red-700 font-bold" colspan="4">Error with {{ color.raw }}</td>
<td v-show="!color.error">
<div class="block mx-2 my-4" style="height: 25px" :style="{ background: color.hex }"></div>
</td>
<td v-show="!color.error" class="color-cell cursor-pointer"><div class="text-center px-2 py-4 border border-transparent hover:border-gray-500" v-on:click="updateClipboard(color.hex)">{{ color.hex }}</div></td>
<td v-show="!color.error" class="color-cell cursor-pointer"><div class="text-center px-2 py-4 border border-transparent hover:border-gray-500" v-on:click="updateClipboard(color.rgb)">{{ color.rgb }}</div></td>
<td v-show="!color.error" class="color-cell cursor-pointer"><div class="text-center px-2 py-4 border border-transparent hover:border-gray-500" v-on:click="updateClipboard(color.hsl)">{{ color.hsl }}</div></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="grid-footer">
<p>You can take a look at <a href="https://git.ditoforge.com/brian/batch-color-converter" title="Source code for this page" class="text-blue-400 font-bold hover:text-blue-700 transition">this terrible code over on my git server</a>.</p>
</div>
</div>
</div>
</template>
<script>
import { defineComponent, reactive, ref, computed, watch, onBeforeMount, onMounted } from 'vue'
import { Color } from './converters/index.js'
export default defineComponent({
emits: [],
props: {},
components: {},
setup(props, { attrs, slots, emit, expose }) {
let defaultInputs = [
"ccc",
"#db2777aa",
"rgb(64, 240, 18)",
"hsla(240, 86.9%, 50.7%, 0.8)",
]
let inputBox = ref("ccc\n#4f46e5\n#db2777aa\n")
let convertedColors = ref([])
let showStatusMessage = ref(false)
let showErrorMessage = ref(false)
//const hexRegex = /^\#?[a-fA-F0-9]{3,6}$/i
//const hexRegex = /^(?=(\#?)[a-fA-F0-9]$)(?:.{3}|.{6})$/i
const hexRegex = /^(\#?[a-fA-F0-9]{3}|\#?[a-fA-F0-9]{6})$/i
//const hexaRegex = /^(\#?)[a-fA-F0-9]{4,8}$/i
//const hexaRegex = /^(?=\#?[a-fA-F0-9]$)(?:.{4}|.{8})$/i
const hexaRegex = /^(\#?[a-fA-F0-9]{4}|\#?[a-fA-F0-9]{8})$/i
const rgbRegex = /^rgb\(\s*\d{1,3}\s*,?\s*\d{1,3}\s*,?\s*\d{1,3}\s*\)$/i
//const rgbaRegex = /^rgba\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*(0(\.[0-9])?|1(\.0)?)\s*\)/i
const rgbaRegex = /^rgb(a?)\(\s*\d{1,3}\s*,?\s*\d{1,3}\s*,?\s*\d{1,3}\s*(,|\/)*\s*((0(\.[0-9]{1,3}))?|(1(\.0{1,3}))?|([1-9][0-9]?|100))\s*\)$/i
const hslRegex = /^hsl\(\s*\d{1,3}\s*,?\s*\d{1,3}(\.[0-9])?%\s*,?\s*\d{1,3}(\.[0-9])?%\s*\)\s*$/i
//const hslaRegex = /^hsla\(\s*\d{1,3}\s*,*\s*\d{1,3}(\.[0-9])?%\s*,*\s*\d{1,3}(\.[0-9])?%\s*(,|\/)*\s*((0(\.[0-9]{1,3}))?|(1(\.0{1,3}))?)\s*\)/i
const hslaRegex = /^hsl(a?)\(\s*\d{1,3}\s*,?\s*\d{1,3}(\.[0-9])?%\s*,?\s*\d{1,3}(\.[0-9])?%\s*(,|\/)*\s*((0(\.[0-9]{1,3}))?|(1(\.0{1,3}))?|([1-9][0-9]?|100))\s*\)\s*$/i
// computed properties
/*let compVariable = computed(() => {
//return 'foo'
})*/
// watchers
/*watch(inputBox, (newValue, oldValue) => {
//
})*/
// lifecycle hooks
onBeforeMount(() => {
inputBox.value = defaultInputs.join("\n")
})
onMounted(() => {
batchConvert()
})
// methods
function batchConvert() {
convertedColors.value = []
// first attempt to split by new-line characters
let inputArray = inputBox.value.split('\n')
let count = inputArray.length
for (let i = 0; i < count; i++) {
// check for empty line, non hex(a)/rgb(a)/hsl(a) string
let inputLine = inputArray[i].toLowerCase().trim()
if (inputLine.length === 0) {
continue
}
let converted = {
error: false,
raw: inputLine,
hex: "",
rgb: "",
hsl: "",
}
let rgb = { red: null, green: null, blue: null, alpha: null }
let hsl = { hue: null, saturation: null, lightness: null, alpha: null }
if (hexRegex.test(inputLine)) {
let hexString = inputLine
// doing this just to add pound symbol for the table output
// if it doesn't already exist and to allow the use of
// the hex value without leading pound symbol
// for conversion to other formats.
hexString = hexString.replace('#', '')
rgb = Color.hexToRgb(hexString)
hsl = Color.rgbToHsl(rgb.red, rgb.green, rgb.blue)
converted.hex = "#" + hexString
converted.rgb = "rgb(" + rgb.red + ", " + rgb.green + ", " + rgb.blue + ")"
converted.hsl = "hsl(" + hsl.hue + ", " + hsl.saturation + "%, " + hsl.lightness + "%)"
} else if (hexaRegex.test(inputLine)) {
let hexString = inputLine
hexString = hexString.replace('#', '')
rgb = Color.hexaToRgba(hexString)
hsl = Color.rgbaToHsla(rgb.red, rgb.green, rgb.blue, rgb.alpha)
converted.hex = "#" + hexString
converted.rgb = "rgba(" + rgb.red + ", " + rgb.green + ", " + rgb.blue + ", " + rgb.alpha + ")"
converted.hsl = "hsla(" + hsl.hue + ", " + hsl.saturation + "%, " + hsl.lightness + "%, " + hsl.alpha + ")"
}
if (rgbRegex.test(inputLine)) {
// extract the values for red, green, blue.
let rgbStrArray = inputLine.split(',')
if (rgbStrArray.length !== 3) {
rgbStrArray = inputLine.split(' ')
}
let red = Number.parseInt(rgbStrArray[0].replace('rgb(', '').trim())
let green = Number.parseInt(rgbStrArray[1].trim())
let blue = Number.parseInt(rgbStrArray[2].replace(')', '').trim())
hsl = Color.rgbToHsl(red, green, blue)
converted.hex = "#" + Color.rgbToHex(red, green, blue)
converted.rgb = "rgb(" + red + ", " + green + ", " + blue + ")"
converted.hsl = converted.hsl = "hsl(" + hsl.hue + ", " + hsl.saturation + "%, " + hsl.lightness + "%)"
} else if (rgbaRegex.test(inputLine)) {
// extract the values for red, green, blue, alpha.
let alphaIndex = 3
let rgbaStrArray = inputLine.split(',')
if (rgbaStrArray.length !== 4) {
alphaIndex = 4
rgbaStrArray = inputLine.split(' ')
}
let red = Number.parseInt(rgbaStrArray[0].replace('rgb(', '').replace('rgba(', '').trim())
let green = Number.parseInt(rgbaStrArray[1].trim())
let blue = Number.parseInt(rgbaStrArray[2].trim())
let alpha = rgbaStrArray[alphaIndex].replace(')', '').trim()
if (alpha > 1) { alpha /= 100 }
hsl = Color.rgbToHsl(red, green, blue)
converted.hex = "#" + Color.rgbaToHexa(red, green, blue, alpha)
converted.rgb = "rgba(" + red + ", " + green + ", " + blue + ", " + alpha + ")"
converted.hsl = "hsla(" + hsl.hue + ", " + hsl.saturation + "%, " + hsl.lightness + "%, " + alpha + ")"
}
if (hslRegex.test(inputLine)) {
// extract the values for hue, saturation, lightness.
let hslStrArray = inputLine.split(',')
if (hslStrArray.length !== 3) {
hslStrArray = inputLine.split(' ')
}
let hue = hslStrArray[0].replace('hsl(', '').trim()
let saturation = hslStrArray[1].replace('%', '').trim()
let lightness = hslStrArray[2].replace('%', '').replace(')', '').trim()
rgb = Color.hslToRgb(hue, saturation, lightness)
converted.hex = "#" + Color.hslToHex(hue, saturation, lightness)
converted.rgb = "rgb(" + rgb.red + ", " + rgb.green + ", " + rgb.blue + ")"
converted.hsl = "hsl(" + hue + ", " + saturation + "%, " + lightness + "%)"
} else if (hslaRegex.test(inputLine)) {
// extract the values for hue, saturation, lightness, alpha.
let alphaIndex = 3
let hslaStrArray = inputLine.split(',')
if (hslaStrArray.length !== 4) {
alphaIndex = 4
hslaStrArray = inputLine.split(' ')
}
let hue = hslaStrArray[0].replace('hsl(', '').replace('hsla(', '').trim()
let saturation = hslaStrArray[1].replace('%', '').trim()
let lightness = hslaStrArray[2].replace('%', '').trim()
let alpha = hslaStrArray[alphaIndex].replace(')', '').trim()
if (alpha > 1) { alpha /= 100 }
rgb = Color.hslaToRgba(hue, saturation, lightness, alpha)
converted.hex = "#" + Color.hslaToHexa(hue, saturation, lightness, alpha)
converted.rgb = "rgb(" + rgb.red + ", " + rgb.green + ", " + rgb.blue + ", " + alpha + ")"
converted.hsl = "hsla(" + hue + ", " + saturation + "%, " + lightness + "%, " + alpha + ")"
}
convertedColors.value.push(converted)
}
}
function updateClipboard (text) {
clipboard.writeText(text).then(() => {
showErrorMessage = false
showStatusMessage = true
setTimeout(() => {
showStatusMessage = false
}, 1000)
})
.catch(() => {
showStatusMessage = false
showErrorMessage = true
setTimeout(() => {
showErrorMessage = false
}, 1000)
})
}
return {
inputBox,
convertedColors,
showStatusMessage,
showErrorMessage,
batchConvert,
updateClipboard,
}
},
})
</script>
<style>
@import './assets/base.css'
</style>