added TailwindCSS and got it working as it was before

This commit is contained in:
Brian 2022-03-24 14:24:30 -06:00
parent 9979483be8
commit b023279be5
Signed by: brian
GPG Key ID: DE1A5390A3B84CD8
16 changed files with 2519 additions and 149 deletions

View File

@ -1,13 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="index,follow">
<meta name="googlebot" content="index,follow">
<meta name="format-detection" content="telephone=no">
<meta http-equiv="x-dns-prefetch-control" content="off">
<meta name="google" content="notranslate">
<meta name="google" content="nositelinkssearchbox">
<meta name="rating" content="General">
<meta name="subject" content="CSS color conversion tool">
<meta name="description" content="Convert colors in a batch among HSL(a), RGB(a), and Hex">
<title>Batch Color Converter</title>
<!-- Privacy -->
<meta name="twitter:dnt" content="on">
<!-- analytics -->
<!-- none -->
<script type="module" src="/src/main.js"></script>
</head>
<body class="font-open-sans antialiased bg-zinc-50 dark:bg-slate-900">
<div id="app" class="min-h-screen">
<!-- -->
</div>
<!-- END OF LINE. -->
</body>
</html>

69
index.php Normal file
View File

@ -0,0 +1,69 @@
<?php
require_once "env.php";
?><!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="index,follow">
<meta name="googlebot" content="index,follow">
<meta name="format-detection" content="telephone=no">
<meta http-equiv="x-dns-prefetch-control" content="off">
<meta name="google" content="notranslate">
<meta name="google" content="nositelinkssearchbox">
<meta name="rating" content="General">
<meta name="url" content="<?php echo $domain; ?>/">
<meta name="subject" content="CSS color conversion tool">
<meta name="description" content="Convert colors in a batch among HSL(a), RGB(a), and Hex">
<title>Batch Color Converter</title>
<!-- Privacy -->
<meta name="twitter:dnt" content="on">
<!-- analytics -->
<!-- none -->
<!-- Helps prevent duplicate content issues -->
<link href="<?php echo $domain; ?>" rel="canonical">
<!-- Android web manifest file -->
<!-- <link href="<?php echo $domain; ?>/.webmanifest" rel="manifest"> -->
<!-- Files listing who was involved in this site and copyrights -->
<link href="<?php echo $domain; ?>/humans.txt" rel="author">
<link href="<?php echo $domain; ?>/gpl-3.0-standalone.html" rel="copyright">
<!-- Favicon -->
<link href="<?php echo $domain; ?>/favicon.ico" rel="icon" sizes="16x16" type="image/icon">
<link href="<?php echo $domain; ?>/favicon.svg" rel="icon" type="image/svg+xml">
<link href="<?php echo $domain; ?>/favicon.png" rel="icon" sizes="192x192">
<!-- Font preloads (should be done for each font file) -->
<!-- Open Sans license: fonts/OpenSans/LICENSE.txt -->
<link href="<?php echo $domain; ?>/fonts/OpenSans/OpenSans-Regular.woff2" rel="preload" as="font" type="font/woff2" crossorigin="anonymous">
<link href="<?php echo $domain; ?>/fonts/OpenSans/OpenSans-Bold.woff2" rel="preload" as="font" type="font/woff2" crossorigin="anonymous">
<!-- Open Sans license: fonts/Ubuntu/UFL.txt -->
<link href="<?php echo $domain; ?>/fonts/Ubuntu/Ubuntu-Regular.woff2" rel="preload" as="font" type="font/woff2" crossorigin="anonymous">
<link href="<?php echo $domain; ?>/fonts/Ubuntu/Ubuntu-Bold.woff2" rel="preload" as="font" type="font/woff2" crossorigin="anonymous">
<!-- CSS -->
<link href="<?php echo $domain; ?>/css/vendor/tailwind-2.2.4.min.css" rel="stylesheet" media="screen">
<link href="<?php echo $domain; ?>/css/app.css" rel="stylesheet" media="screen">
<!-- JS that must be executed before the document is loaded -->
<script src="<?php echo $domain; ?>/js/vendor/vue-2.6.14.min.js" defer></script>
<script src="<?php echo $domain; ?>/js/app.js" defer></script>
<!-- -->
</head>
<body class="font-open-sans antialiased">
<!-- END OF LINE. -->
</body>
</html>

1743
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,9 @@
},
"devDependencies": {
"@vitejs/plugin-vue": "^2.2.2",
"autoprefixer": "^10.4.4",
"postcss": "^8.4.12",
"tailwindcss": "^3.0.23",
"vite": "^2.8.4"
}
}

6
postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@ -1,81 +1,261 @@
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import TheWelcome from './components/TheWelcome.vue'
</script>
<template>
<header>
<img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" />
<div class="grid-container h-screen">
<div class="wrapper">
<HelloWorld msg="You did it!" />
<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>
</header>
<main>
<TheWelcome />
</main>
</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';
@import './assets/base.css'
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}
header {
line-height: 1.5;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
.logo {
margin: 0 2rem 0 0;
}
}
</style>

81
src/App.vue.old Normal file
View File

@ -0,0 +1,81 @@
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import TheWelcome from './components/TheWelcome.vue'
</script>
<template>
<header>
<img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" />
<div class="wrapper">
<HelloWorld msg="You did it!" />
</div>
</header>
<main>
<TheWelcome />
</main>
</template>
<style>
@import './assets/base.css';
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}
header {
line-height: 1.5;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
.logo {
margin: 0 2rem 0 0;
}
}
</style>

View File

@ -1,74 +1,55 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
.grid-container {
@apply grid grid-flow-row grid-rows-1 grid-cols-1 gap-8;
/*display: grid;*/
/*grid-template-columns: 1fr;*/
/*grid-template-rows: 1fr;*/
/*gap: 2em 2em;*/
/*grid-auto-flow: row;*/
grid-template-areas:
"wrapper";
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
.wrapper {
@apply grid grid-flow-row grid-cols-1 gap-8;
/*display: grid;*/
/*grid-template-columns: 1fr;*/
grid-template-rows: auto 1fr auto;
/*gap: 2em 2em;*/
/*grid-auto-flow: row;*/
grid-template-areas:
"grid-header"
"grid-main"
"grid-footer";
grid-area: wrapper;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
.grid-header {
@apply p-6;
grid-area: grid-header;
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
position: relative;
font-weight: normal;
.grid-main {
@apply grid grid-flow-col grid-rows-1 gap-8;
/*display: grid;*/
grid-template-columns: 30% 1fr;
/*grid-template-rows: 1fr;*/
/*gap: 2em 2em;*/
/*grid-auto-flow: row;*/
grid-template-areas:
"input-container output-wrapper";
grid-area: grid-main;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition: color 0.5s, background-color 0.5s;
line-height: 1.6;
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
.input-container {
grid-area: input-container;
}
.output-wrapper {
grid-area: output-wrapper;
}
.grid-footer {
@apply p-6;
grid-area: grid-footer;
}

52
src/converters/hex.js Normal file
View File

@ -0,0 +1,52 @@
import { sanitizeAlphaFloat } from '../helpers'
const hexToRgb = (hexString) => {
let hex = 'ffffff'
if (hexString.length === 3) {
hex = ''
hex += hexString.substr(2, 1) + hexString.substr(2, 1)
hex += hexString.substr(1, 1) + hexString.substr(1, 1)
hex += hexString.substr(0, 1) + hexString.substr(0, 1)
} else {
hex = hexString
}
let bigint = Number.parseInt(hex, 16)
let redNum = (bigint >> 16) & 255
let greenNum = (bigint >> 8) & 255
let blueNum = bigint & 255
return { "red": redNum, "green": greenNum, "blue": blueNum }
}
const hexaToRgba = (hexString) => {
let hex = 'ffffff'
let alphaHex = 'ff'
let alpha = 1
if (hexString.length === 4) {
alphaHex = hexString.substr(3, 1) + hexString.substr(3, 1)
hex = ''
hex += hexString.substr(2, 1) + hexString.substr(2, 1)
hex += hexString.substr(1, 1) + hexString.substr(1, 1)
hex += hexString.substr(0, 1) + hexString.substr(0, 1)
} else {
alphaHex = hexString.substr(6, 2)
hex = hexString.substr(0, 6)
}
let rgb = hexToRgb(hex)
alpha = Number.parseFloat((Number.parseInt(alphaHex, 16) / 255)).toFixed(1)
return { "red": rgb.red, "green": rgb.green, "blue": rgb.blue, "alpha": alpha }
}
const hexToHsl = (hexString) => {
console.error('hex to HSL not implemented yet')
}
const hexaToHsla = (hexString) => {
console.error('hexa to HSLa not implemented yet')
}
export { hexToRgb, hexaToRgba, hexToHsl, hexaToHsla }

81
src/converters/hsl.js Normal file
View File

@ -0,0 +1,81 @@
import { sanitizeAlphaFloat } from '../helpers'
const hslToHex = (hue, saturation, lightness) => {
let rgb = hslToRgb(hue, saturation, lightness)
let red = rgb.red.toString(16)
let green = rgb.green.toString(16)
let blue = rgb.blue.toString(16)
if (red.length === 1) { red = "0" + red }
if (green.length === 1) { green = "0" + green }
if (blue.length === 1) { blue = "0" + blue }
return "" + red + green + blue
}
const hslaToHexa = (hue, saturation, lightness, alpha) => {
let rgb = hslToRgb(hue, saturation, lightness)
let red = rgb.red.toString(16)
let green = rgb.green.toString(16)
let blue = rgb.blue.toString(16)
let alphaHex = Math.round(sanitizeAlphaFloat(alpha) * 255).toString(16)
if (red.length === 1) { red = "0" + red }
if (green.length === 1) { green = "0" + green }
if (blue.length === 1) { blue = "0" + blue }
return "" + red + green + blue + alphaHex
}
const hslToRgb = (hue, saturation, lightness) => {
if (hue === 360) { hue = 0 }
if (hue < 0) { hue += 360 }
saturation /= 100
lightness /= 100
let chroma = (1 - Math.abs(2 * lightness - 1)) * saturation,
xComponent = chroma * (1 - Math.abs((hue / 60) % 2 - 1)),
lightnessMatch = lightness - (chroma / 2),
red = 0,
green = 0,
blue = 0
// set red and green if hue between 0 and 119
if (0 <= hue && hue < 60) {
red = chroma
green = xComponent
} else if (60 <= hue && hue < 120) {
red = xComponent
green = chroma
}
// set green and blue if hue between 120 and 239
else if (120 <= hue && hue < 180) {
green = chroma
blue = xComponent
} else if (180 <= hue && hue < 240) {
green = xComponent
blue = chroma
}
// set red and blue if hue between 0 and 119
else if (240 <= hue && hue < 300) {
red = xComponent
blue = chroma
} else if (300 <= hue && hue < 360) {
red = chroma
blue = xComponent
}
red = Math.round((red + lightnessMatch) * 255)
green = Math.round((green + lightnessMatch) * 255)
blue = Math.round((blue + lightnessMatch) * 255)
return { "red": red, "green": green, "blue": blue }
}
const hslaToRgba = (hue, saturation, lightness, alpha) => {
let rgb = hslToRgb(hue, saturation, lightness)
return { "red": rgb.red, "green": rgb.green, "blue": rgb.blue, "alpha": sanitizeAlphaFloat(alpha) }
}
export { hslToHex, hslaToHexa, hslToRgb, hslaToRgba }

11
src/converters/index.js Normal file
View File

@ -0,0 +1,11 @@
import { hexToRgb, hexaToRgba, hexToHsl, hexaToHsla } from './hex.js'
import { hslToHex, hslaToHexa, hslToRgb, hslaToRgba } from './hsl.js'
import { rgbToHex, rgbaToHexa, rgbToHsl, rgbaToHsla } from './rgb.js'
const Color = {
hexToRgb, hexaToRgba, hexToHsl, hexaToHsla,
hslToHex, hslaToHexa, hslToRgb, hslaToRgba,
rgbToHex, rgbaToHexa, rgbToHsl, rgbaToHsla,
}
export { Color }

66
src/converters/rgb.js Normal file
View File

@ -0,0 +1,66 @@
import { sanitizeAlphaFloat } from '../helpers'
const rgbToHex = (redNum, greenNum, blueNum) => {
let red = redNum.toString(16)
let green = greenNum.toString(16)
let blue = blueNum.toString(16)
if (red.length === 1) { red = "0" + red }
if (green.length === 1) { green = "0" + green }
if (blue.length === 1) { blue = "0" + blue }
return "" + red + green + blue
}
const rgbaToHexa = (redNum, greenNum, blueNum, alphaNum) => {
let hex = rgbToHex(redNum, greenNum, blueNum)
let alpha = Math.round(sanitizeAlphaFloat(alphaNum) * 255).toString(16)
if (alpha.length == 1) { alpha = "0" + alpha }
return hex + alpha
}
const rgbToHsl = (redNum, greenNum, blueNum) => {
let hue = 0, saturation = 0, lightness = 0
let redFrac = Number.parseFloat(redNum / 255),
greenFrac = Number.parseFloat(greenNum / 255),
blueFrac = Number.parseFloat(blueNum / 255)
let channelMin = Math.min(redFrac, blueFrac, greenFrac),
channelMax = Math.max(redFrac, blueFrac, greenFrac),
delta = channelMax - channelMin
if (delta === 0) { hue = 0 }
// Red is the maximum color
else if (channelMax === redFrac) {
hue = ((greenFrac - blueFrac) / delta) % 6
}
// Green is the maximum color
else if (channelMax === greenFrac) {
hue = (blueFrac - redFrac) / delta + 2
}
// Green is the maximum color
else {
hue = (redFrac - greenFrac) / delta + 4
}
hue = Math.round(hue * 60)
// Make negative hues positive behind 360°
if (hue < 0) { hue += 360 }
lightness = (channelMax + channelMin) / 2
if (delta === 0) { saturation = 0 }
else { saturation = delta / (1 - Math.abs(2 * lightness - 1)) }
lightness = +(lightness * 100).toFixed(1)
saturation = +(saturation * 100).toFixed(1)
return { "hue": hue, "saturation": saturation, "lightness": lightness }
}
const rgbaToHsla = (redNum, greenNum, blueNum, alphaNum) => {
let hsl = rgbToHsl(redNum, greenNum, blueNum)
hsl.alpha = sanitizeAlphaFloat(alphaNum)
return hsl
}
export { rgbToHex, rgbaToHexa, rgbToHsl, rgbaToHsla }

13
src/helpers/index.js Normal file
View File

@ -0,0 +1,13 @@
const sanitizeAlphaFloat = (alphaRaw) => {
let alpha = Number.parseFloat(1)
if (alphaRaw >= 0 && alphaRaw <= 1) {
alpha = Number.parseFloat(alphaRaw)
} else if (alphaRaw < 0) {
alpha = Number.parseFloat(0)
}
return alpha.toFixed(1)
}
export { sanitizeAlphaFloat }

43
src/index.css Normal file
View File

@ -0,0 +1,43 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@font-face {
font-family: "Open Sans";
src: url(../fonts/OpenSans/OpenSans-Regular.woff2) format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Open Sans";
src: url(../fonts/OpenSans/OpenSans-Bold.woff2) format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Ubuntu";
src: url(../fonts/Ubuntu/Ubuntu-Regular.woff2) format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Ubuntu";
src: url(../fonts/Ubuntu/Ubuntu-Bold.woff2) format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
}
.font-open-sans {
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Open Sans", "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
.font-ubuntu {
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Ubuntu", "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}

View File

@ -1,4 +1,5 @@
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
createApp(App).mount('#app')

15
tailwind.config.js Normal file
View File

@ -0,0 +1,15 @@
module.exports = {
darkMode: "class",
content: [
"./index.html",
"./index.php",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}