diff --git a/ColorPickerPOC/ColorPickerPOC.js b/ColorPickerPOC/ColorPickerPOC.js
index d8b6d5931c..ce7c26ee1c 100644
--- a/ColorPickerPOC/ColorPickerPOC.js
+++ b/ColorPickerPOC/ColorPickerPOC.js
@@ -12,7 +12,7 @@ import Skinnable from '../Skinnable';
import TabLayout, {Tab} from '../TabLayout';
import ColorPickerGrid from './ColorPickerGrid';
-import ColorPickerSlider from './ColorPickerSlider';
+import ColorPickerSlider, {ColorPickerSliderHSL} from './ColorPickerSlider'; // eslint-disable-line no-unused-vars
import ColorPickerSpectrum from './ColorPickerSpectrum';
import {generateOppositeColor} from './utils';
@@ -201,6 +201,7 @@ const ColorPickerPOCBase = ({color = '#eb4034', colors = [], css, onChangeColor,
+ {/* */}
diff --git a/ColorPickerPOC/ColorPickerSlider.js b/ColorPickerPOC/ColorPickerSlider.js
index 8c628c0c36..7328dd3177 100644
--- a/ColorPickerPOC/ColorPickerSlider.js
+++ b/ColorPickerPOC/ColorPickerSlider.js
@@ -1,90 +1,281 @@
import {Cell, Row} from '@enact/ui/Layout';
import PropTypes from 'prop-types';
-import {useCallback} from 'react';
+import {useCallback, useState} from 'react';
import Slider from '../Slider';
-import {generateOppositeColor, hexToRGB, rgbObjectToHex} from './utils';
+import {generateOppositeColor, hexToHSL, hexToRGB, hslToHex, hslToRGBString, rgbObjectToHex} from './utils';
import componentCss from './ColorPickerSlider.module.less';
+const hueGradient = (saturation, lightness) => {
+ return `linear-gradient(to right,
+ hsla(0, ${saturation}%, ${lightness}%, 1),
+ hsla(10, ${saturation}%, ${lightness}%, 1),
+ hsla(20, ${saturation}%, ${lightness}%, 1),
+ hsla(30, ${saturation}%, ${lightness}%, 1),
+ hsla(40, ${saturation}%, ${lightness}%, 1),
+ hsla(50, ${saturation}%, ${lightness}%, 1),
+ hsla(60, ${saturation}%, ${lightness}%, 1),
+ hsla(70, ${saturation}%, ${lightness}%, 1),
+ hsla(80, ${saturation}%, ${lightness}%, 1),
+ hsla(90, ${saturation}%, ${lightness}%, 1),
+ hsla(100, ${saturation}%, ${lightness}%, 1),
+ hsla(110, ${saturation}%, ${lightness}%, 1),
+ hsla(120, ${saturation}%, ${lightness}%, 1),
+ hsla(130, ${saturation}%, ${lightness}%, 1),
+ hsla(140, ${saturation}%, ${lightness}%, 1),
+ hsla(150, ${saturation}%, ${lightness}%, 1),
+ hsla(160, ${saturation}%, ${lightness}%, 1),
+ hsla(170, ${saturation}%, ${lightness}%, 1),
+ hsla(180, ${saturation}%, ${lightness}%, 1),
+ hsla(190, ${saturation}%, ${lightness}%, 1),
+ hsla(200, ${saturation}%, ${lightness}%, 1),
+ hsla(210, ${saturation}%, ${lightness}%, 1),
+ hsla(220, ${saturation}%, ${lightness}%, 1),
+ hsla(230, ${saturation}%, ${lightness}%, 1),
+ hsla(240, ${saturation}%, ${lightness}%, 1),
+ hsla(250, ${saturation}%, ${lightness}%, 1),
+ hsla(260, ${saturation}%, ${lightness}%, 1),
+ hsla(270, ${saturation}%, ${lightness}%, 1),
+ hsla(280, ${saturation}%, ${lightness}%, 1),
+ hsla(290, ${saturation}%, ${lightness}%, 1),
+ hsla(300, ${saturation}%, ${lightness}%, 1),
+ hsla(310, ${saturation}%, ${lightness}%, 1),
+ hsla(320, ${saturation}%, ${lightness}%, 1),
+ hsla(330, ${saturation}%, ${lightness}%, 1),
+ hsla(340, ${saturation}%, ${lightness}%, 1),
+ hsla(350, ${saturation}%, ${lightness}%, 1),
+ hsla(360, ${saturation}%, ${lightness}%, 1))`;
+};
+
+const lightnessGradient = (hue, saturation) => {
+ return `linear-gradient(to right,
+ hsla(${hue}, ${saturation}%, 0%, 1),
+ hsla(${hue}, ${saturation}%, 20%, 1),
+ hsla(${hue}, ${saturation}%, 40%, 1),
+ hsla(${hue}, ${saturation}%, 60%, 1),
+ hsla(${hue}, ${saturation}%, 80%, 1),
+ hsla(${hue}, ${saturation}%, 100%, 1))`;
+};
+
const ColorPickerSlider = ({selectedColor, selectedColorHandler, ...props}) => {
const {red, green, blue} = hexToRGB(selectedColor);
+ const [localRed, setLocalRed] = useState(red);
+ const [localGreen, setLocalGreen] = useState(green);
+ const [localBlue, setLocalBlue] = useState(blue);
const changeValueRed = useCallback((ev) => {
- selectedColorHandler(rgbObjectToHex({red: ev.value, green, blue}));
- }, [blue, green, selectedColorHandler]);
+ setLocalRed(ev.value);
+ }, []);
const changeValueGreen = useCallback((ev) => {
- selectedColorHandler(rgbObjectToHex({red, green: ev.value, blue}));
- }, [blue, red, selectedColorHandler]);
+ setLocalGreen(ev.value);
+ }, []);
const changeValueBlue = useCallback((ev) => {
- selectedColorHandler(rgbObjectToHex({red, green, blue: ev.value}));
- }, [green, red, selectedColorHandler]);
+ setLocalBlue(ev.value);
+ }, []);
+
+ const changeSelectedColor = useCallback(() => {
+ selectedColorHandler(rgbObjectToHex({red: localRed, green: localGreen, blue: localBlue}));
+ }, [localBlue, localGreen, localRed, selectedColorHandler]);
return (
Red |
-
+
|
{red} |
+ >{localRed} |
|
Green |
-
+
|
- {green} |
+ {localGreen} |
|
|
Blue |
-
+
|
- {blue} |
+ {localBlue} |
+ |
+ |
+
+ );
+};
+
+const ColorPickerSliderHSL = ({selectedColor, selectedColorHandler, ...props}) => {
+ const {h, s, l} = hexToHSL(selectedColor);
+
+ const [hue, setHue] = useState(h);
+ const [saturation, setSaturation] = useState(s);
+ const [lightness, setLightness] = useState(l);
+
+ const changeValueHue = useCallback((ev) => {
+ setHue(ev.value);
+ }, []);
+
+ const changeValueSaturation = useCallback((ev) => {
+ setSaturation(ev.value);
+ }, []);
+
+ const changeValueLightness = useCallback((ev) => {
+ setLightness(ev.value);
+ }, []);
+
+ const changeSelectedColor = useCallback(() => {
+ selectedColorHandler(hslToHex({h: hue, s: saturation, l: lightness}));
+ }, [hue, saturation, lightness, selectedColorHandler]);
+
+ return (
+
+
+ Hue |
+
+
+
+ |
+ {hue} |
+
+ |
+
+ Saturation |
+
+
+
+ |
+ {saturation}% |
+
+ |
+
+ Lightness |
+
+
+
+ |
+ {lightness}% |
|
@@ -96,4 +287,13 @@ ColorPickerSlider.propTypes = {
selectedColorHandler: PropTypes.func
};
+ColorPickerSliderHSL.propTypes = {
+ selectedColor: PropTypes.string,
+ selectedColorHandler: PropTypes.func
+};
+
+export {
+ ColorPickerSlider,
+ ColorPickerSliderHSL
+};
export default ColorPickerSlider;
diff --git a/ColorPickerPOC/ColorPickerSlider.module.less b/ColorPickerPOC/ColorPickerSlider.module.less
index 446a836f62..2ba045213b 100644
--- a/ColorPickerPOC/ColorPickerSlider.module.less
+++ b/ColorPickerPOC/ColorPickerSlider.module.less
@@ -4,6 +4,7 @@
.labelText {
font-size: 42px;
+ margin-bottom: 12px;
}
.outputText {
@@ -13,16 +14,38 @@
color: #444444;
display: grid;
justify-content: end;
- padding-right: 24px;
+ margin-left: 30px;
+ padding-right: 21px;
+}
+
+.outputTextPercent {
+ align-content: center;
+ background-color: #eeeeee;
+ border-radius: 12px;
+ color: #444444;
+ display: grid;
+ justify-content: end;
+ margin-left: 30px;
}
.slider {
- --sand-focus-bg-color-rgb: transparent;
--sand-progress-bg-color-rgb: transparent;
- --sand-progress-slider-color: transparent;
border-radius: 99px;
height: 42px;
- margin-left: 0;
+ margin-left: 18px;
+ margin-right: 18px;
+
+ .knob {
+ &::before {
+ border-radius: 99px;
+ height: 120px;
+ width: 120px;
+ }
+ }
+}
+
+.sliderCell {
+ border-radius: 99px;
}
.sliderContainer {
diff --git a/ColorPickerPOC/utils.js b/ColorPickerPOC/utils.js
index 5892b544e2..97163dfb1b 100644
--- a/ColorPickerPOC/utils.js
+++ b/ColorPickerPOC/utils.js
@@ -35,6 +35,47 @@ const generateOppositeColor = (hexColor) => {
return luminance > 128 ? '#101720CC' : '#FFFFFFCC';
};
+const hexToHSL = (hexColor) => {
+ // Convert hex to RGB first
+ let r = 0, g = 0, b = 0;
+ r = parseInt(hexColor.slice(1, 3), 16);
+ g = parseInt(hexColor.slice(3, 5), 16);
+ b = parseInt(hexColor.slice(5), 16);
+
+ // Then convert RGB to HSL
+ r /= 255;
+ g /= 255;
+ b /= 255;
+ let cmin = Math.min(r, g, b),
+ cmax = Math.max(r, g, b),
+ delta = cmax - cmin,
+ h, s, l;
+
+ if (delta === 0) {
+ h = 0;
+ } else if (cmax === r) {
+ h = ((g - b) / delta) % 6;
+ } else if (cmax === g) {
+ h = (b - r) / delta + 2;
+ } else {
+ h = (r - g) / delta + 4;
+ }
+
+ h = Math.round(h * 60);
+
+ if (h < 0) {
+ h += 360;
+ }
+
+ l = (cmax + cmin) / 2;
+ s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
+
+ s = +(s * 100).toFixed(1);
+ l = +(l * 100).toFixed(1);
+
+ return {h: Math.round(h), s: Math.round(s), l: Math.round(l)};
+};
+
const hexToRGB = (hexColor) => {
let internalColor = hexColor.replace('#', '').split('');
@@ -45,6 +86,83 @@ const hexToRGB = (hexColor) => {
};
};
+const hslToHex = ({h, s, l}) => {
+ s /= 100;
+ l /= 100;
+
+ let c = (1 - Math.abs(2 * l - 1)) * s,
+ x = c * (1 - Math.abs((h / 60) % 2 - 1)),
+ m = l - c / 2,
+ r = 0,
+ g = 0,
+ b = 0;
+
+ if (0 <= h && h < 60) {
+ r = c; g = x; b = 0;
+ } else if (60 <= h && h < 120) {
+ r = x; g = c; b = 0;
+ } else if (120 <= h && h < 180) {
+ r = 0; g = c; b = x;
+ } else if (180 <= h && h < 240) {
+ r = 0; g = x; b = c;
+ } else if (240 <= h && h < 300) {
+ r = x; g = 0; b = c;
+ } else if (300 <= h && h < 360) {
+ r = c; g = 0; b = x;
+ }
+ // Having obtained RGB, convert channels to hex
+ r = Math.round((r + m) * 255).toString(16);
+ g = Math.round((g + m) * 255).toString(16);
+ b = Math.round((b + m) * 255).toString(16);
+
+ // Prepend 0s, if necessary
+ if (r.length === 1) {
+ r = "0" + r;
+ }
+
+ if (g.length === 1) {
+ g = "0" + g;
+ }
+
+ if (b.length === 1) {
+ b = "0" + b;
+ }
+
+ return "#" + r + g + b;
+};
+
+const hslToRGBString = ({h, s, l}) => {
+ s /= 100;
+ l /= 100;
+
+ let c = (1 - Math.abs(2 * l - 1)) * s,
+ x = c * (1 - Math.abs((h / 60) % 2 - 1)),
+ m = l - c / 2,
+ r = 0,
+ g = 0,
+ b = 0;
+
+ if (0 <= h && h < 60) {
+ r = c; g = x; b = 0;
+ } else if (60 <= h && h < 120) {
+ r = x; g = c; b = 0;
+ } else if (120 <= h && h < 180) {
+ r = 0; g = c; b = x;
+ } else if (180 <= h && h < 240) {
+ r = 0; g = x; b = c;
+ } else if (240 <= h && h < 300) {
+ r = x; g = 0; b = c;
+ } else if (300 <= h && h < 360) {
+ r = c; g = 0; b = x;
+ }
+
+ // Having obtained RGB, convert channels to hex
+ r = Math.round((r + m) * 255);
+ g = Math.round((g + m) * 255);
+ b = Math.round((b + m) * 255);
+ return r + ',' + g + ',' + b;
+};
+
const rgbObjectToHex = (rgbColor) => {
let {red, green, blue} = rgbColor;
red = red < 16 ? `0${red.toString(16)}` : red.toString(16);
@@ -57,7 +175,10 @@ const rgbObjectToHex = (rgbColor) => {
export {
generateOppositeColor,
getHexColorFromGradient,
+ hexToHSL,
hexToRGB,
+ hslToHex,
+ hslToRGBString,
rgbObjectToHex,
rgbStringToHex
};