-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(bug): fixes an issue with saturation and lightness where addition…
…s/subtractions. Fixes #2
- Loading branch information
Showing
13 changed files
with
1,256 additions
and
1,151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import {HslaTuple} from "./hsla"; | ||
|
||
export type HslTuple = [number, string, string]; | ||
|
||
/** | ||
* Converts the given HSL Tuple into a proper HSL color | ||
* @param {HslTuple|HslaTuple} tuple | ||
* @return {string} | ||
*/ | ||
export function hslTupleToHsl([H, S, L]: HslTuple | HslaTuple): string { | ||
return `hsl(${H}, ${S}, ${L})`; | ||
} | ||
|
||
/** | ||
* Adds lightness to the given HSL(a) tuple and returns a new one | ||
* @param {HslTuple|HslaTuple} tuple | ||
* @param {number} amount | ||
* @return {HslTuple|HslaTuple} | ||
*/ | ||
export function addLightnessToHslTuple(tuple: HslTuple | HslaTuple, amount: number): typeof tuple extends HslTuple ? HslTuple : HslaTuple { | ||
const [H, S, inputL, A] = tuple; | ||
const outputL = `${Math.max(0, Math.min(100, parseFloat(inputL) + amount))}%`; | ||
return A != null ? [H, S, outputL, A] : (([H, S, outputL] as unknown) as HslaTuple); | ||
} | ||
|
||
/** | ||
* Adds saturation to the given HSL(a) tuple and returns a new one | ||
* @param {HslTuple|HslaTuple} tuple | ||
* @param {number} amount | ||
* @return {HslTuple|HslaTuple} | ||
*/ | ||
export function addSaturationToToHslTuple(tuple: HslTuple | HslaTuple, amount: number): typeof tuple extends HslTuple ? HslTuple : HslaTuple { | ||
const [H, inputS, L, A] = tuple; | ||
const outputS = `${Math.max(0, Math.min(100, parseFloat(inputS) + amount))}%`; | ||
return A != null ? [H, outputS, L, A] : (([H, outputS, L] as unknown) as HslaTuple); | ||
} | ||
|
||
/** | ||
* Converts a string-represented HSL color to a tuple: [HUE: number, SATURATION: string, LIGHTNESS: string]. | ||
* @param {string} hsl - The HSL color to convert. | ||
* @returns {HslTuple} The HSL color in a tuple representation. | ||
* @throws {TypeError} If the first argument is not of type 'string'. | ||
* @throws {TypeError} If the 'hue' couldn't be decoded from the given string. | ||
* @throws {TypeError} If the 'saturation' couldn't be decoded from the given string. | ||
* @throws {TypeError} If the 'lightness' couldn't be decoded from the given string. | ||
*/ | ||
export function hslStringToHslTuple(hsl: string): HslTuple { | ||
if (typeof hsl !== "string") throw new TypeError(`first argument to 'hslStringToHslTuple' must be of type 'string'!`); | ||
|
||
const result = hsl.slice(hsl.indexOf("(") + 1, hsl.lastIndexOf(")")).split(","); | ||
|
||
const HUE = parseInt(result[0]); | ||
const SATURATION = result[1].trim(); | ||
const LIGHTNESS = result[2].trim(); | ||
|
||
if (isNaN(HUE)) throw new TypeError(`Couldn't decode the 'hue' value for the given hsl color: ${hsl}`); | ||
if (isNaN(parseInt(SATURATION))) throw new TypeError(`Couldn't decode the 'saturation' value for the given hsl color: ${hsl}`); | ||
if (isNaN(parseInt(LIGHTNESS))) throw new TypeError(`Couldn't decode the 'lightness' value for the given hsl color: ${hsl}`); | ||
|
||
return [HUE, SATURATION.slice(SATURATION.length - 1) !== "%" ? `${SATURATION}%` : SATURATION, LIGHTNESS.slice(LIGHTNESS.length - 1) !== "%" ? `${LIGHTNESS}%` : LIGHTNESS]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import {hslStringToHslTuple} from "./hsl"; | ||
|
||
export type HslaTuple = [number, string, string, number]; | ||
|
||
/** | ||
* Converts the given HSLa Tuple into a proper HSLa color | ||
* @param {HslaTuple} tuple | ||
* @return {string} | ||
*/ | ||
export function hslaTupleToHsla([H, S, L, A]: HslaTuple): string { | ||
return `hsla(${H}, ${S}, ${L}, ${A})`; | ||
} | ||
|
||
/** | ||
* Converts a string-represented HSLa color to a tuple: [HUE: number, SATURATION: string, LIGHTNESS: string, ALPHA: number]. | ||
* @param {string} hsla - The HSLA color to convert. | ||
* @returns {HslaTuple} The HSLA color in a tuple representation. | ||
* @throws {TypeError} If the 'alpha' couldn't be decoded from the given string. | ||
*/ | ||
export function hslaStringToHslaTuple(hsla: string): HslaTuple { | ||
if (typeof hsla !== "string") throw new TypeError(`first argument to 'hslaStringToHslaTuple' must be of type 'string'!`); | ||
|
||
const [HUE, SATURATION, LIGHTNESS] = hslStringToHslTuple(hsla); | ||
const result = hsla.slice(hsla.indexOf("(") + 1, hsla.lastIndexOf(")")).split(","); | ||
const ALPHA = parseFloat(result[result.length - 1]); | ||
|
||
if (isNaN(ALPHA)) throw new TypeError(`Couldn't decode the 'alpha' value for the given hsla color: ${hsla}`); | ||
|
||
return [HUE, SATURATION.slice(SATURATION.length - 1) !== "%" ? `${SATURATION}%` : SATURATION, LIGHTNESS.slice(LIGHTNESS.length - 1) !== "%" ? `${LIGHTNESS}%` : LIGHTNESS, ALPHA]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
export type HsvTuple = [number, number, number]; | ||
|
||
/** | ||
* Converts the given HSV Tuple into a proper HSV color | ||
* @param {HsvTuple} tuple | ||
* @param{"hsb"|"hsv"} hsbOrHsv | ||
* @return {string} | ||
*/ | ||
export function hsvTupleToHsv([H, S, V]: HsvTuple, hsbOrHsv: "hsb" | "hsv" = "hsb"): string { | ||
return `${hsbOrHsv}(${H}, ${S}, ${V})`; | ||
} | ||
|
||
/** | ||
* Generates a tuple-representation of an HSV/HSB color. | ||
* @param {string} hsvString - An HSV/HSB string. For instance, hsb(5, 10, 20). | ||
* @returns {HsvTuple} A tuple representation of the HSV color. | ||
* @throws {TypeError} If the first argument is not of type 'string'. | ||
* @throws {TypeError} If an HSV color couldn't be extracted from the given string. | ||
*/ | ||
export function hsvStringToHsvTuple(hsvString: string): HsvTuple { | ||
if (typeof hsvString !== "string") throw new TypeError(`first argument must be of type 'string'!`); | ||
let hsv = hsvString.match(/hsv\((.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/); | ||
if (hsv == null) hsv = hsvString.match(/hsb\((.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/); | ||
|
||
if (hsv == null) throw new TypeError(`Couldn't decode an HSV color from the given input: ${hsvString}`); | ||
|
||
const h = parseFloat(hsv[1]); | ||
const s = parseFloat(hsv[2]); | ||
const v = parseFloat(hsv[3]); | ||
|
||
if (isNaN(h)) throw new TypeError(`Couldn't decode the 'Hue' value of the given HSV color: '${hsvString}'.`); | ||
if (isNaN(s)) throw new TypeError(`Couldn't decode the 'Saturation' value of the given HSV color: '${hsvString}'.`); | ||
if (isNaN(v)) throw new TypeError(`Couldn't decode the 'Value/Brightness' value of the given HSV color: '${hsvString}'.`); | ||
|
||
return [h, s, v]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/** | ||
* A map between HTML color names and their hex values. | ||
* @type {Record<string, string>} | ||
*/ | ||
export const HTML_COLOR: Record<string, string> = { | ||
aliceblue: "#f0f8ff", | ||
antiquewhite: "#faebd7", | ||
aqua: "#00ffff", | ||
aquamarine: "#7fffd4", | ||
azure: "#f0ffff", | ||
beige: "#f5f5dc", | ||
bisque: "#ffe4c4", | ||
black: "#000000", | ||
blanchedalmond: "#ffebcd", | ||
blue: "#0000ff", | ||
blueviolet: "#8a2be2", | ||
brown: "#a52a2a", | ||
burlywood: "#deb887", | ||
cadetblue: "#5f9ea0", | ||
chartreuse: "#7fff00", | ||
chocolate: "#d2691e", | ||
coral: "#ff7f50", | ||
cornflowerblue: "#6495ed", | ||
cornsilk: "#fff8dc", | ||
crimson: "#dc143c", | ||
cyan: "#00ffff", | ||
darkblue: "#00008b", | ||
darkcyan: "#008b8b", | ||
darkgoldenrod: "#b8860b", | ||
darkgray: "#a9a9a9", | ||
darkgreen: "#006400", | ||
darkkhaki: "#bdb76b", | ||
darkmagenta: "#8b008b", | ||
darkolivegreen: "#556b2f", | ||
darkorange: "#ff8c00", | ||
darkorchid: "#9932cc", | ||
darkred: "#8b0000", | ||
darksalmon: "#e9967a", | ||
darkseagreen: "#8fbc8f", | ||
darkslateblue: "#483d8b", | ||
darkslategray: "#2f4f4f", | ||
darkturquoise: "#00ced1", | ||
darkviolet: "#9400d3", | ||
deeppink: "#ff1493", | ||
deepskyblue: "#00bfff", | ||
dimgray: "#696969", | ||
dodgerblue: "#1e90ff", | ||
firebrick: "#b22222", | ||
floralwhite: "#fffaf0", | ||
forestgreen: "#228b22", | ||
fuchsia: "#ff00ff", | ||
gainsboro: "#dcdcdc", | ||
ghostwhite: "#f8f8ff", | ||
gold: "#ffd700", | ||
goldenrod: "#daa520", | ||
gray: "#808080", | ||
green: "#008000", | ||
greenyellow: "#adff2f", | ||
honeydew: "#f0fff0", | ||
hotpink: "#ff69b4", | ||
"indianred ": "#cd5c5c", | ||
indigo: "#4b0082", | ||
ivory: "#fffff0", | ||
khaki: "#f0e68c", | ||
lavender: "#e6e6fa", | ||
lavenderblush: "#fff0f5", | ||
lawngreen: "#7cfc00", | ||
lemonchiffon: "#fffacd", | ||
lightblue: "#add8e6", | ||
lightcoral: "#f08080", | ||
lightcyan: "#e0ffff", | ||
lightgoldenrodyellow: "#fafad2", | ||
lightgrey: "#d3d3d3", | ||
lightgreen: "#90ee90", | ||
lightpink: "#ffb6c1", | ||
lightsalmon: "#ffa07a", | ||
lightseagreen: "#20b2aa", | ||
lightskyblue: "#87cefa", | ||
lightslategray: "#778899", | ||
lightsteelblue: "#b0c4de", | ||
lightyellow: "#ffffe0", | ||
lime: "#00ff00", | ||
limegreen: "#32cd32", | ||
linen: "#faf0e6", | ||
magenta: "#ff00ff", | ||
maroon: "#800000", | ||
mediumaquamarine: "#66cdaa", | ||
mediumblue: "#0000cd", | ||
mediumorchid: "#ba55d3", | ||
mediumpurple: "#9370d8", | ||
mediumseagreen: "#3cb371", | ||
mediumslateblue: "#7b68ee", | ||
mediumspringgreen: "#00fa9a", | ||
mediumturquoise: "#48d1cc", | ||
mediumvioletred: "#c71585", | ||
midnightblue: "#191970", | ||
mintcream: "#f5fffa", | ||
mistyrose: "#ffe4e1", | ||
moccasin: "#ffe4b5", | ||
navajowhite: "#ffdead", | ||
navy: "#000080", | ||
oldlace: "#fdf5e6", | ||
olive: "#808000", | ||
olivedrab: "#6b8e23", | ||
orange: "#ffa500", | ||
orangered: "#ff4500", | ||
orchid: "#da70d6", | ||
palegoldenrod: "#eee8aa", | ||
palegreen: "#98fb98", | ||
paleturquoise: "#afeeee", | ||
palevioletred: "#d87093", | ||
papayawhip: "#ffefd5", | ||
peachpuff: "#ffdab9", | ||
peru: "#cd853f", | ||
pink: "#ffc0cb", | ||
plum: "#dda0dd", | ||
powderblue: "#b0e0e6", | ||
purple: "#800080", | ||
red: "#ff0000", | ||
rosybrown: "#bc8f8f", | ||
royalblue: "#4169e1", | ||
saddlebrown: "#8b4513", | ||
salmon: "#fa8072", | ||
sandybrown: "#f4a460", | ||
seagreen: "#2e8b57", | ||
seashell: "#fff5ee", | ||
sienna: "#a0522d", | ||
silver: "#c0c0c0", | ||
skyblue: "#87ceeb", | ||
slateblue: "#6a5acd", | ||
slategray: "#708090", | ||
snow: "#fffafa", | ||
springgreen: "#00ff7f", | ||
steelblue: "#4682b4", | ||
tan: "#d2b48c", | ||
teal: "#008080", | ||
thistle: "#d8bfd8", | ||
tomato: "#ff6347", | ||
turquoise: "#40e0d0", | ||
violet: "#ee82ee", | ||
wheat: "#f5deb3", | ||
white: "#ffffff", | ||
whitesmoke: "#f5f5f5", | ||
yellow: "#ffff00", | ||
yellowgreen: "#9acd32" | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
export type RgbTuple = [number, number, number]; | ||
|
||
/** | ||
* Converts the given RGB Tuple into a proper RGB color | ||
* @param {RgbTuple} tuple | ||
* @return {string} | ||
*/ | ||
export function rgbTupleToRgb([R, G, B]: RgbTuple): string { | ||
return `rgb(${R}, ${G}, ${B})`; | ||
} | ||
|
||
/** | ||
* Generates a tuple-representation of an RGB color: [RED: number, GREEN: number, BLUE: number]. | ||
* @param {string} rgbString - An RGB string. For instance, rgb(RGB_MAX_VALUE, RGB_MAX_VALUE, RGB_MAX_VALUE). | ||
* @returns {RgbTuple} A tuple representation of the RGB color. | ||
* @throws {TypeError} If the first argument is not of type 'string'. | ||
* @throws {TypeError} If an RGB color couldn't be extracted from the given string. | ||
*/ | ||
export function rgbStringToRgbTuple(rgbString: string): RgbTuple { | ||
if (typeof rgbString !== "string") throw new TypeError(`first argument must be of type 'string'!`); | ||
const rgb = rgbString.match(/rgb\((.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/); | ||
if (rgb == null) throw new TypeError(`'rgbToHex()' couldn't decode an RGB color from the given input: ${rgbString}`); | ||
|
||
const r = parseFloat(rgb[1]); | ||
const g = parseFloat(rgb[2]); | ||
const b = parseFloat(rgb[3]); | ||
|
||
if (isNaN(r)) throw new TypeError(`'rgbToString()' couldn't decode the 'red' value of the given RGB color: '${rgbString}'.`); | ||
if (isNaN(g)) throw new TypeError(`'rgbToString()' couldn't decode the 'green' value of the given RGB color: '${rgbString}'.`); | ||
if (isNaN(b)) throw new TypeError(`'rgbToString()' couldn't decode the 'blue' value of the given RGB color: '${rgbString}'.`); | ||
|
||
return [r, g, b]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import {RgbTuple} from "./rgb"; | ||
|
||
export type RgbaTuple = [number, number, number, number]; | ||
|
||
/** | ||
* Converts the given RGBa Tuple into a proper RGBa color | ||
* @param {RgbaTuple|RgbTuple} tuple | ||
* @return {string} | ||
*/ | ||
export function rgbaTupleToRgba([R, G, B, A]: RgbTuple | RgbaTuple): string { | ||
return `rgba(${R}, ${G}, ${B}, ${A})`; | ||
} | ||
|
||
/** | ||
* Generates a tuple-representation of an RGBa color: [RED: number, GREEN: number, BLUE: number, ALPHA: number]. | ||
* @param {string} rgbaString - An RGBa string. For instance, rgb(RGB_MAX_VALUE, RGB_MAX_VALUE, RGB_MAX_VALUE, 0.4). | ||
* @returns {RgbaTuple} A tuple representation of the RGBa color. | ||
* @throws {TypeError} If the first argument is not of type 'string'. | ||
* @throws {TypeError} If an RGBa color couldn't be extracted from the given string. | ||
*/ | ||
export function rgbaStringToRgbaTuple(rgbaString: string): RgbaTuple { | ||
if (typeof rgbaString !== "string") throw new TypeError(`first argument must be of type 'string'!`); | ||
const rgba = rgbaString.match(/rgba\((.+)\s*,\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/); | ||
if (rgba == null) throw new TypeError(`Couldn't decode an RGBa color from the given input: ${rgbaString}`); | ||
|
||
const r = parseFloat(rgba[1]); | ||
const g = parseFloat(rgba[2]); | ||
const b = parseFloat(rgba[3]); | ||
const a = parseFloat(rgba[4]); | ||
|
||
if (isNaN(r)) throw new TypeError(`Couldn't decode the 'red' value of the given RGBa color: '${rgbaString}'.`); | ||
if (isNaN(g)) throw new TypeError(`Couldn't decode the 'green' value of the given RGBa color: '${rgbaString}'.`); | ||
if (isNaN(b)) throw new TypeError(`Couldn't decode the 'blue' value of the given RGBa color: '${rgbaString}'.`); | ||
if (isNaN(a)) throw new TypeError(`Couldn't decode the 'alpha' value of the given RGBa color: '${rgbaString}'.`); | ||
|
||
return [r, g, b, a]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/** | ||
* The maximum possible RGB value | ||
* @type {number} | ||
*/ | ||
export const RGB_MAX_VALUE: number = 255; |
Oops, something went wrong.