Fully functional Colorpicker with Preview
This commit is contained in:
parent
98710bffbe
commit
8fd475dec2
|
@ -0,0 +1,27 @@
|
||||||
|
<script>
|
||||||
|
import FlatButton from "./FlatButton.svelte";
|
||||||
|
|
||||||
|
export let format = "hex";
|
||||||
|
export let onclick = format => {};
|
||||||
|
|
||||||
|
let colorFormats = ["hex", "rgb", "hsl"];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.flatbutton-group {
|
||||||
|
font-weight: 500;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="flatbutton-group">
|
||||||
|
{#each colorFormats as text}
|
||||||
|
<FlatButton
|
||||||
|
selected={format === text}
|
||||||
|
{text}
|
||||||
|
on:click={() => onclick(text)} />
|
||||||
|
{/each}
|
||||||
|
</div>
|
|
@ -1,10 +1,17 @@
|
||||||
<script>
|
<script>
|
||||||
import {onMount} from "svelte"
|
import { onMount, createEventDispatcher } from "svelte";
|
||||||
import { getAndConvertHexa, getAndConvertRgba, getHSLA, hsvaToHexa, hsvaToRgba, getColorFormat, convertToHSVA } from "./utils.js"
|
|
||||||
|
import {
|
||||||
|
getColorFormat,
|
||||||
|
convertToHSVA,
|
||||||
|
convertHsvaToFormat
|
||||||
|
} from "./utils.js";
|
||||||
import Slider from "./Slider.svelte";
|
import Slider from "./Slider.svelte";
|
||||||
import Palette from "./Palette.svelte";
|
import Palette from "./Palette.svelte";
|
||||||
|
import ButtonGroup from "./ButtonGroup.svelte";
|
||||||
|
import Input from "./Input.svelte";
|
||||||
|
|
||||||
export let value = "rgba(255,255,255,1)";
|
export let value = "#3ec1d3ff";
|
||||||
export let format = "hexa";
|
export let format = "hexa";
|
||||||
|
|
||||||
let h = null;
|
let h = null;
|
||||||
|
@ -12,24 +19,20 @@
|
||||||
let v = null;
|
let v = null;
|
||||||
let a = null;
|
let a = null;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
format = getColorFormat(value)
|
format = getColorFormat(value);
|
||||||
if(format) {
|
if (format) {
|
||||||
let hsva = convertToHSVA(value, format)
|
convertAndSetHSVA()
|
||||||
setHSVA(hsva)
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
const hsvaIsNull = () => [h,s,v,a].every(c => c === null)
|
const hsvaIsNull = () => [h, s, v, a].every(c => c === null);
|
||||||
|
|
||||||
function setFormatAndConvert() {
|
function convertAndSetHSVA() {
|
||||||
if (value.startsWith('#')) {
|
let hsva = convertToHSVA(value, format);
|
||||||
format = "hexa"
|
setHSVA(hsva);
|
||||||
return getAndConvertHexa(value)
|
|
||||||
} else if (value.startsWith('rgba')) {
|
|
||||||
format = "rgba"
|
|
||||||
return getAndConvertRgba(value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setHSVA([hue, sat, val, alpha]) {
|
function setHSVA([hue, sat, val, alpha]) {
|
||||||
|
@ -40,53 +43,81 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
//fired by choosing a color from the palette
|
//fired by choosing a color from the palette
|
||||||
function setSaturationAndValue({detail}) {
|
function setSaturationAndValue({ detail }) {
|
||||||
s = detail.s
|
s = detail.s;
|
||||||
v = detail.v
|
v = detail.v;
|
||||||
let res = convertHSVA()
|
value = convertHsvaToFormat([h, s, v, a], format);
|
||||||
console.log("SAT-VAL", res)
|
dispatch("change", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setHue(hue) {
|
function setHue(hue) {
|
||||||
h = hue
|
h = hue;
|
||||||
let res = convertHSVA()
|
value = convertHsvaToFormat([h, s, v, a], format);
|
||||||
console.log("HUE",res)
|
dispatch("change", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAlpha(alpha) {
|
function setAlpha(alpha) {
|
||||||
a = alpha
|
a = alpha === "1.00" ? "1" :alpha;
|
||||||
let res = convertHSVA()
|
value = convertHsvaToFormat([h, s, v, a], format);
|
||||||
console.log("ALPHA",res)
|
dispatch("change", value)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertHSVA() {
|
function changeFormatAndConvert(f) {
|
||||||
let hsva = [h, s, v, a]
|
format = f;
|
||||||
let _value = format === "hexa" ? hsvaToHexa(hsva, true) : hsvaToRgba(hsva, true)
|
value = convertHsvaToFormat([h, s, v, a], format);
|
||||||
return _value;
|
|
||||||
// onchange(_value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// $: {
|
function handleColorInput(text) {
|
||||||
// if(!hsvaIsNull()) {
|
let f = getColorFormat(text)
|
||||||
// let hsva = [h, s, v, a]
|
if(f) {
|
||||||
// // let t = value + "abs"
|
format = f;
|
||||||
// value = format === "hexa" ? hsvaToHexa(hsva) : hsvaToRgba(hsva)
|
value = text
|
||||||
// debugger
|
convertAndSetHSVA()
|
||||||
// // console.log("VAL", value)
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.colorpicker-container {
|
.colorpicker-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border: 1px solid #e8e8ef;
|
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
box-shadow: 0 0.15em 1.5em 0 rgba(0,0,0,.1), 0 0 1em 0 rgba(0,0,0,.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 8px;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #d2d2d2
|
||||||
|
}
|
||||||
|
|
||||||
|
.alpha-hue-panel {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 25px 1fr;
|
||||||
|
grid-gap: 15px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
/* padding: 8px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-color {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid #dedada;
|
||||||
|
}
|
||||||
|
|
||||||
|
.format-input-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -94,7 +125,24 @@
|
||||||
|
|
||||||
<Palette on:change={setSaturationAndValue} {h} {s} {v} {a} />
|
<Palette on:change={setSaturationAndValue} {h} {s} {v} {a} />
|
||||||
|
|
||||||
|
<div class="control-panel">
|
||||||
|
<div class="alpha-hue-panel">
|
||||||
|
<div>
|
||||||
|
<div class="selected-color" style={`background: ${value}`} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
<Slider type="hue" value={h} on:change={hue => setHue(hue.detail)} />
|
<Slider type="hue" value={h} on:change={hue => setHue(hue.detail)} />
|
||||||
|
<Slider
|
||||||
|
type="alpha"
|
||||||
|
value={a}
|
||||||
|
on:change={alpha => setAlpha(alpha.detail)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="format-input-panel">
|
||||||
|
<ButtonGroup {format} onclick={changeFormatAndConvert} />
|
||||||
|
<Input {value} on:input={event => handleColorInput(event.target.value)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Slider type="alpha" value={a} on:change={alpha => setAlpha(alpha.detail)} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
<script>
|
||||||
|
import Colorpicker from "./Colorpicker.svelte"
|
||||||
|
import {createEventDispatcher} from "svelte"
|
||||||
|
import {buildStyle} from "./helpers.js"
|
||||||
|
import { fade } from 'svelte/transition';
|
||||||
|
|
||||||
|
export let value = "#3ec1d3ff"
|
||||||
|
export let format = "hexa";
|
||||||
|
export let width = "25px"
|
||||||
|
export let open = true;
|
||||||
|
export let fullwidth = false;
|
||||||
|
|
||||||
|
let colorPreview = null
|
||||||
|
let positionSide = "top"
|
||||||
|
|
||||||
|
$: width = fullwidth ? "100%" : width
|
||||||
|
$: style = buildStyle({width, background: value})
|
||||||
|
$: colorStyle = buildStyle({[positionSide]: `28px`})
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
function openColorpicker(event) {
|
||||||
|
if(colorPreview) {
|
||||||
|
const {top: spaceAbove, width, bottom} = colorPreview.getBoundingClientRect()
|
||||||
|
const spaceBelow = window.innerHeight - bottom;
|
||||||
|
|
||||||
|
if (spaceAbove > spaceBelow) {
|
||||||
|
positionSide = "bottom"
|
||||||
|
} else {
|
||||||
|
positionSide = "top"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onColorChange(color) {
|
||||||
|
value = color.detail;
|
||||||
|
dispatch("change", color.detail)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="color-preview-container">
|
||||||
|
<div bind:this={colorPreview} class="color-preview" {style} on:click={openColorpicker}></div>
|
||||||
|
{#if open}
|
||||||
|
<div class="color-preview" style={colorStyle}>
|
||||||
|
<Colorpicker on:change={onColorChange} {format} {value} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{#if open}
|
||||||
|
<div on:click|self={() => open = false} class="overlay"></div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.color-preview-container{
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
height: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-preview {
|
||||||
|
position: absolute;
|
||||||
|
flex: 1;
|
||||||
|
height: 25px;
|
||||||
|
z-index: 2;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay{
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<script>
|
||||||
|
export let text = "";
|
||||||
|
export let selected = false;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.flatbutton {
|
||||||
|
padding: 3px 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: black;
|
||||||
|
background-color: #dadada;
|
||||||
|
border: 1px solid #d4d4d4;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin: 5px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #003cb0;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="flatbutton" class:selected on:click>{text}</div>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<script>
|
||||||
|
export let value = "";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 185px;
|
||||||
|
font-size: 14px;
|
||||||
|
background: #f1f3f4;
|
||||||
|
border-radius: 8px;
|
||||||
|
height: 27px;
|
||||||
|
outline-color: #003cb0;
|
||||||
|
color: #565252;
|
||||||
|
text-align: center;
|
||||||
|
/* border: none; */
|
||||||
|
border: 1px solid #dadada;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<input on:input type="text" {value} maxlength="25" />
|
||||||
|
</div>
|
|
@ -42,6 +42,7 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 175px;
|
height: 175px;
|
||||||
cursor: crosshair;
|
cursor: crosshair;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker {
|
.picker {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { onMount, createEventDispatcher } from "svelte";
|
import { onMount, createEventDispatcher } from "svelte";
|
||||||
import dragable from "./drag.js";
|
import dragable from "./drag.js";
|
||||||
|
|
||||||
export let value = 1
|
export let value = 1;
|
||||||
export let type = "hue";
|
export let type = "hue";
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
@ -11,20 +11,22 @@
|
||||||
let sliderWidth = 0;
|
let sliderWidth = 0;
|
||||||
|
|
||||||
function handleClick(mouseX) {
|
function handleClick(mouseX) {
|
||||||
const { left } = slider.getBoundingClientRect();
|
const { left, width } = slider.getBoundingClientRect();
|
||||||
let clickPosition = mouseX - left;
|
let clickPosition = mouseX - left;
|
||||||
|
|
||||||
if (clickPosition >= 0 && clickPosition <= sliderWidth) {
|
let percentageClick = (clickPosition / sliderWidth).toFixed(2)
|
||||||
let percentageClick = clickPosition / sliderWidth;
|
|
||||||
|
if (percentageClick >= 0 && percentageClick <= 1) {
|
||||||
let value =
|
let value =
|
||||||
type === "hue"
|
type === "hue"
|
||||||
? 360 * percentageClick.toString()
|
? 360 * percentageClick
|
||||||
: percentageClick.toString();
|
: percentageClick;
|
||||||
dispatch("change", value);
|
dispatch("change", value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: thumbPosition = type === "hue" ? sliderWidth * (value / 360) : sliderWidth * (value)
|
$: thumbPosition =
|
||||||
|
type === "hue" ? sliderWidth * (value / 360) : sliderWidth * value;
|
||||||
|
|
||||||
$: style = `transform: translateX(${thumbPosition - 6}px);`;
|
$: style = `transform: translateX(${thumbPosition - 6}px);`;
|
||||||
</script>
|
</script>
|
||||||
|
@ -34,10 +36,11 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
width: 220px;
|
width: 185px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
margin: 10px 0px;
|
margin: 10px 0px;
|
||||||
border: 1px solid #e8e8ef;
|
border: 1px solid #e8e8ef;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hue {
|
.hue {
|
||||||
|
@ -62,9 +65,10 @@
|
||||||
bottom: -3px;
|
bottom: -3px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
width: 12px;
|
width: 12px;
|
||||||
border: 1px solid black;
|
border: 1px solid #777676;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
cursor:grab;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
export const buildStyle = styles => {
|
||||||
|
let str = ""
|
||||||
|
for (let s in styles) {
|
||||||
|
if (styles[s]) {
|
||||||
|
let key = convertCamel(s)
|
||||||
|
str += `${key}: ${styles[s]}; `
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
export const convertCamel = str => {
|
||||||
|
return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`)
|
||||||
|
}
|
|
@ -1,2 +1,3 @@
|
||||||
import Colorpicker from './Colorpicker.svelte';
|
import Colorpreview from './Colorpreview.svelte';
|
||||||
export default Colorpicker;
|
|
||||||
|
export default Colorpreview;
|
||||||
|
|
|
@ -1,139 +1,161 @@
|
||||||
export const isValidHex = (str) => /^#(?:[A-F0-9]{3}$|[A-F0-9]{6}$|[A-F0-9]{8})$/gi.test(str)
|
export const isValidHex = str =>
|
||||||
|
/^#(?:[A-F0-9]{3}$|[A-F0-9]{4}$|[A-F0-9]{6}$|[A-F0-9]{8})$/gi.test(str);
|
||||||
|
|
||||||
const getHexaValues = (hexString) => hexString.match(/[A-F0-9]{2}/gi);
|
const getHexaValues = hexString => {
|
||||||
|
if (hexString.length <= 5) {
|
||||||
|
let hexArr = hexString.match(/[A-F0-9]/gi);
|
||||||
|
let t = hexArr.map(c => (c += c));
|
||||||
|
return t;
|
||||||
|
} else {
|
||||||
|
return hexString.match(/[A-F0-9]{2}/gi);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const isValidRgb = (str) => {
|
export const isValidRgb = str => {
|
||||||
const hasValidStructure = /^(?:rgba\(|rgb\()[0-9,.\s]*\)$/gi.test(str);
|
const hasValidStructure = /^(?:rgba\(|rgb\()(?:[0-9,\s]|\.(?=\d))*\)$/gi.test(str);
|
||||||
if(hasValidStructure) {
|
if (hasValidStructure) {
|
||||||
return testRgbaValues(str.toLowerCase());
|
return testRgbaValues(str.toLowerCase());
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const findNonNumericChars = /[a-z()%\s]/gi
|
const findNonNumericChars = /[a-z()\s]/gi;
|
||||||
|
|
||||||
export const getNumericValues = (str) => str.replace(findNonNumericChars, '').split(',').map(c => Number(c));
|
export const getNumericValues = str =>
|
||||||
|
str
|
||||||
|
.replace(findNonNumericChars, "")
|
||||||
|
.split(",")
|
||||||
|
.map(v => v !== "" ? v : undefined);
|
||||||
|
|
||||||
export const testRgbaValues = (str) => {
|
export const testRgbaValues = str => {
|
||||||
const rgba = getNumericValues(str)
|
const rgba = getNumericValues(str);
|
||||||
let [ r, g, b, a ] = rgba;
|
const [r, g, b, a] = rgba;
|
||||||
|
|
||||||
let isValidLengthRange = (str.startsWith("rgb(") && rgba.length === 3) || (str.startsWith("rgba(") && rgba.length === 4);
|
let isValidLengthRange =
|
||||||
let isValidColorRange = [ r, g, b ].every((v) => v >= 0 && v <= 255);
|
(str.startsWith("rgb(") && rgba.length === 3) ||
|
||||||
let isValidAlphaRange = str.startsWith("rgba(") ? a >= 0 && a <= 1 : true;
|
(str.startsWith("rgba(") && rgba.length === 4);
|
||||||
|
let isValidColorRange = [r, g, b].every(v => v >= 0 && v <= 255);
|
||||||
|
let isValidAlphaRange = str.startsWith("rgba(") ? `${a}`.length <= 4 && a >= 0 && a <= 1 : true;
|
||||||
|
|
||||||
return isValidLengthRange && isValidColorRange && isValidAlphaRange;
|
return isValidLengthRange && isValidColorRange && isValidAlphaRange;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isValidHsl = (str) => {
|
export const isValidHsl = str => {
|
||||||
const hasValidStructure = /^(?:hsl\(|hsla\()[0-9,.\s]*\)$/gi.test(str)
|
const hasValidStructure = /^(?:hsl\(|hsla\()(?:[0-9,%\s]|\.(?=\d))*\)$/gi.test(str);
|
||||||
if(hasValidStructure) {
|
if (hasValidStructure) {
|
||||||
return testHslaValues(str.toLowerCase())
|
return testHslaValues(str.toLowerCase());
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export const testHslaValues = (str) => {
|
export const testHslaValues = str => {
|
||||||
|
const hsla = getNumericValues(str);
|
||||||
|
const [h, s, l, a] = hsla;
|
||||||
|
const isUndefined = [h,s,l].some(v => v === undefined)
|
||||||
|
|
||||||
const hsla = getNumericValues(str)
|
if(isUndefined) return false;
|
||||||
const [h, s, l, a] = hsla
|
|
||||||
|
|
||||||
let isValidLengthRange = (str.startsWith("hsl(") && hsla.length === 3) || (str.startsWith("hsla(") && hsla.length === 4);
|
let isValidLengthRange =
|
||||||
let isValidColorRange = (h >= 0 && h <= 360) && [s, l].every(v => v >= 0 && v <= 100)
|
(str.startsWith("hsl(") && hsla.length === 3) ||
|
||||||
let isValidAlphaRange = str.startsWith("hsla(") ? (a >= 0 && a <= 1) : true
|
(str.startsWith("hsla(") && hsla.length === 4);
|
||||||
|
let isValidHue = h >= 0 && h <= 360
|
||||||
|
let isValidSatLum = [s, l].every(v => v.endsWith('%') && parseInt(v) >= 0 && parseInt(v) <= 100 )
|
||||||
|
let isValidAlphaRange = str.startsWith("hsla(") ? `${a}`.length <= 4 && a >= 0 && a <= 1 : true;
|
||||||
|
|
||||||
return isValidLengthRange && isValidColorRange && isValidAlphaRange;
|
return isValidLengthRange && isValidHue && isValidSatLum && isValidAlphaRange;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const getColorFormat = (color) => {
|
export const getColorFormat = color => {
|
||||||
if(typeof color === "string") {
|
if (typeof color === "string") {
|
||||||
if(isValidHex(color)) {
|
if (isValidHex(color)) {
|
||||||
return 'hex'
|
return "hex";
|
||||||
}else if(isValidRgb(color)) {
|
} else if (isValidRgb(color)) {
|
||||||
return 'rgb'
|
return "rgb";
|
||||||
}else if(isValidHsl(color)) {
|
} else if (isValidHsl(color)) {
|
||||||
return 'hsl'
|
return "hsl";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export const convertToHSVA = (value, format) => {
|
export const convertToHSVA = (value, format) => {
|
||||||
switch(format) {
|
switch (format) {
|
||||||
case "hex":
|
case "hex":
|
||||||
return getAndConvertHexa(value)
|
return getAndConvertHexa(value);
|
||||||
case "rgb":
|
case "rgb":
|
||||||
return getAndConvertRgba(value)
|
return getAndConvertRgba(value);
|
||||||
case "hsl":
|
case "hsl":
|
||||||
return getAndConvertHsla(value)
|
return getAndConvertHsla(value);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export const convertHsvaToFormat = (hsva, format) => {
|
export const convertHsvaToFormat = (hsva, format) => {
|
||||||
switch(format) {
|
switch (format) {
|
||||||
case "hex":
|
case "hex":
|
||||||
return hsvaToHexa(hsva, true)
|
return hsvaToHexa(hsva, true);
|
||||||
case "rgb":
|
case "rgb":
|
||||||
return hsvaToRgba(hsva, true)
|
return hsvaToRgba(hsva, true);
|
||||||
case "hsl":
|
case "hsl":
|
||||||
return hsvaToHsla(hsva, true)
|
return hsvaToHsla(hsva);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export const getAndConvertHexa = color => {
|
||||||
export const getAndConvertHexa = (color) => {
|
let [rHex, gHex, bHex, aHex] = getHexaValues(color);
|
||||||
let [ rHex, gHex, bHex, aHex ] = getHexaValues(color);
|
return hexaToHSVA([rHex, gHex, bHex], aHex);
|
||||||
return hexaToHSVA([ rHex, gHex, bHex ], aHex);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export const getAndConvertRgba = color => {
|
export const getAndConvertRgba = color => {
|
||||||
let rgba = getNumericValues(color);
|
let rgba = getNumericValues(color);
|
||||||
return rgbaToHSVA(rgba);
|
return rgbaToHSVA(rgba);
|
||||||
}
|
};
|
||||||
|
|
||||||
export const getAndConvertHsla = color => {
|
export const getAndConvertHsla = color => {
|
||||||
let hsla = getNumericValues(color);
|
let hsla = getNumericValues(color);
|
||||||
return hslaToHSVA(hsla)
|
return hslaToHSVA(hsla);
|
||||||
}
|
|
||||||
|
|
||||||
export const getHSLA = ([hue, sat, val, a]) => {
|
|
||||||
const [ h, s, l ] = _hsvToHSL([hue, sat, val]);
|
|
||||||
return `hsla(${h}, ${s}, ${l}, ${a})`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hexaToHSVA = (hex, alpha = 'FF') => {
|
|
||||||
const rgba = hex.map((v) => parseInt(v, 16)).concat(Number((parseInt(alpha, 16) / 255).toFixed(2)));
|
export const hexaToHSVA = (hex, alpha = "FF") => {
|
||||||
|
const rgba = hex
|
||||||
|
.map(v => parseInt(v, 16))
|
||||||
|
.concat(Number((parseInt(alpha, 16) / 255).toFixed(2)));
|
||||||
return rgbaToHSVA(rgba);
|
return rgbaToHSVA(rgba);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const rgbaToHSVA = (rgba) => {
|
export const rgbaToHSVA = rgba => {
|
||||||
const [ r, g, b, a = 1 ] = rgba;
|
const [r, g, b, a = 1] = rgba;
|
||||||
let hsv = _rgbToHSV([ r, g, b ]);
|
let hsv = _rgbToHSV([r, g, b]);
|
||||||
return [ ...hsv, a ];
|
return [...hsv, a];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hslaToHSVA = ([h, s, l, a = 1]) => {
|
export const hslaToHSVA = ([h, s, l, a = 1]) => {
|
||||||
let hsv = _hslToHSV([h, s, l])
|
let hsv = _hslToHSV([h, s, l]);
|
||||||
return [...hsv, a]
|
return [...hsv, a];
|
||||||
}
|
|
||||||
|
|
||||||
export const hsvaToHexa = (hsva, asString = false) => {
|
|
||||||
const [ r, g, b, a ] = hsvaToRgba(hsva);
|
|
||||||
|
|
||||||
const hexa = [ r, g, b ].map((v) => Math.round(v).toString(16)).concat(Math.round((a * 255)).toString(16));
|
|
||||||
return asString ? `#${hexa.join('')}` : hexa
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hsvaToRgba = ([h, s, v, a], asString = false) => {
|
export const hsvaToHexa = (hsva, asString = false) => {
|
||||||
let rgb = _hsvToRgb([ h, s, v ]).map(x => Math.round(x));
|
const [r, g, b, a] = hsvaToRgba(hsva);
|
||||||
let rgba = [ ...rgb, a ];
|
|
||||||
return asString ? `rgba(${rgba.join(",")})` : rgba
|
const hexa = [r, g, b]
|
||||||
|
.map(v => {
|
||||||
|
let hex = Math.round(v).toString(16)
|
||||||
|
return hex.length === 1 ? `0${hex}` : hex
|
||||||
|
})
|
||||||
|
.concat(Math.round(a * 255).toString(16));
|
||||||
|
return asString ? `#${hexa.join("")}` : hexa;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hsvaToRgba = ([h, s, v, a = 1], asString = false) => {
|
||||||
|
let rgb = _hsvToRgb([h, s, v]).map(x => Math.round(x));
|
||||||
|
let rgba = [...rgb, a < 1 ? _fixNum(a, 2) : a];
|
||||||
|
return asString ? `rgba(${rgba.join(",")})` : rgba;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hsvaToHsla = ([h, s, v, a = 1], asString = false) => {
|
export const hsvaToHsla = ([h, s, v, a = 1], asString = false) => {
|
||||||
let hsl = _hsvToHSL([h, s, v])
|
let [hue, sat, lum] = _hsvToHSL([h, s, v]);
|
||||||
let hsla = [...hsl, a]
|
let hsla = [hue, sat + "%", lum + "%", a < 1 ? _fixNum(a, 2) : a];
|
||||||
return asString ? `hsla(${hsla.join(",")})` : hsla
|
return `hsla(${hsla.join(",")})`;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const _hslToHSV = (hsl) => {
|
export const _hslToHSV = hsl => {
|
||||||
const h = hsl[0];
|
const h = hsl[0];
|
||||||
let s = hsl[1] / 100;
|
let s = hsl[1] / 100;
|
||||||
let l = hsl[2] / 100;
|
let l = hsl[2] / 100;
|
||||||
|
@ -141,16 +163,16 @@ export const _hslToHSV = (hsl) => {
|
||||||
const lmin = Math.max(l, 0.01);
|
const lmin = Math.max(l, 0.01);
|
||||||
|
|
||||||
l *= 2;
|
l *= 2;
|
||||||
s *= (l <= 1) ? l : 2 - l;
|
s *= l <= 1 ? l : 2 - l;
|
||||||
smin *= lmin <= 1 ? lmin : 2 - lmin;
|
smin *= lmin <= 1 ? lmin : 2 - lmin;
|
||||||
const v = (l + s) / 2;
|
const v = (l + s) / 2;
|
||||||
const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
|
const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
|
||||||
|
|
||||||
return [h, sv * 100, v * 100];
|
return [h, sv * 100, v * 100];
|
||||||
}
|
};
|
||||||
|
|
||||||
//Credit : https://github.com/Qix-/color-convert
|
//Credit : https://github.com/Qix-/color-convert
|
||||||
export const _rgbToHSV = (rgb) => {
|
export const _rgbToHSV = rgb => {
|
||||||
let rdif;
|
let rdif;
|
||||||
let gdif;
|
let gdif;
|
||||||
let bdif;
|
let bdif;
|
||||||
|
@ -190,12 +212,12 @@ export const _rgbToHSV = (rgb) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const hsvResult = [ h * 360, s * 100, v * 100 ].map((v) => Math.round(v));
|
const hsvResult = [h * 360, s * 100, v * 100].map(v => Math.round(v));
|
||||||
return hsvResult;
|
return hsvResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
//Credit : https://github.com/Qix-/color-convert
|
//Credit : https://github.com/Qix-/color-convert
|
||||||
export const _hsvToRgb = (hsv) => {
|
export const _hsvToRgb = hsv => {
|
||||||
const h = hsv[0] / 60;
|
const h = hsv[0] / 60;
|
||||||
const s = hsv[1] / 100;
|
const s = hsv[1] / 100;
|
||||||
let v = hsv[2] / 100;
|
let v = hsv[2] / 100;
|
||||||
|
@ -209,23 +231,22 @@ export const _hsvToRgb = (hsv) => {
|
||||||
|
|
||||||
switch (hi) {
|
switch (hi) {
|
||||||
case 0:
|
case 0:
|
||||||
return [ v, t, p ];
|
return [v, t, p];
|
||||||
case 1:
|
case 1:
|
||||||
return [ q, v, p ];
|
return [q, v, p];
|
||||||
case 2:
|
case 2:
|
||||||
return [ p, v, t ];
|
return [p, v, t];
|
||||||
case 3:
|
case 3:
|
||||||
return [ p, q, v ];
|
return [p, q, v];
|
||||||
case 4:
|
case 4:
|
||||||
return [ t, p, v ];
|
return [t, p, v];
|
||||||
case 5:
|
case 5:
|
||||||
return [ v, p, q ];
|
return [v, p, q];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//Credit : https://github.com/Qix-/color-convert
|
//Credit : https://github.com/Qix-/color-convert
|
||||||
export const _hsvToHSL = (hsv) => {
|
export const _hsvToHSL = hsv => {
|
||||||
|
|
||||||
const h = hsv[0];
|
const h = hsv[0];
|
||||||
const s = hsv[1] / 100;
|
const s = hsv[1] / 100;
|
||||||
const v = hsv[2] / 100;
|
const v = hsv[2] / 100;
|
||||||
|
@ -240,5 +261,8 @@ export const _hsvToHSL = (hsv) => {
|
||||||
sl = sl || 0;
|
sl = sl || 0;
|
||||||
l /= 2;
|
l /= 2;
|
||||||
|
|
||||||
return [ h, Number((sl * 100).toFixed(1)), Number((l * 100).toFixed(1)) ];
|
return [_fixNum(h, 0), _fixNum(sl * 100, 0), _fixNum(l * 100, 0)];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const _fixNum = (value, decimalPlaces) =>
|
||||||
|
Number(parseFloat(value).toFixed(decimalPlaces));
|
||||||
|
|
Loading…
Reference in New Issue