reanimated-color-picker
Version:
A Pure JavaScript Color Picker for React Native
1,682 lines (1,564 loc) • 62.9 kB
JavaScript
// If you find yourself wondering why all of this is within a single function,
// the reason is that to execute each method on the UI thread, you must include the 'worklet' directive.
// Functions marked with this directive are transformed by the Reanimated Babel plugin
// into IIFE — IMMEDIATELY INVOKED FUNCTION EXPRESSION: `const fun = (function{})()`.
// Due to the presence of numerous methods,
// this transformation can lead to a slow initial execution.
// To address this issue, I consolidated them into a single worklet function.
export const colorKitUI = () => {
'worklet';
const NAMED_COLORS = {
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',
darkgrey: '#a9a9a9',
darkkhaki: '#bdb76b',
darkmagenta: '#8b008b',
darkolivegreen: '#556b2f',
darkorange: '#ff8c00',
darkorchid: '#9932cc',
darkred: '#8b0000',
darksalmon: '#e9967a',
darkseagreen: '#8fbc8f',
darkslateblue: '#483d8b',
darkslategrey: '#2f4f4f',
darkturquoise: '#00ced1',
darkviolet: '#9400d3',
deeppink: '#ff1493',
deepskyblue: '#00bfff',
dimgray: '#696969',
dimgrey: '#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',
grey: '#808080',
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',
lightgray: '#d3d3d3',
lightgreen: '#90ee90',
lightgrey: '#d3d3d3',
lightpink: '#ffb6c1',
lightsalmon: '#ffa07a',
lightseagreen: '#20b2aa',
lightskyblue: '#87cefa',
lightslategrey: '#778899',
lightsteelblue: '#b0c4de',
lightyellow: '#ffffe0',
lime: '#00ff00',
limegreen: '#32cd32',
linen: '#faf0e6',
magenta: '#ff00ff',
maroon: '#800000',
mediumaquamarine: '#66cdaa',
mediumblue: '#0000cd',
mediumorchid: '#ba55d3',
mediumpurple: '#9370db',
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: '#db7093',
papayawhip: '#ffefd5',
peachpuff: '#ffdab9',
peru: '#cd853f',
pink: '#ffc0cb',
plum: '#dda0dd',
powderblue: '#b0e0e6',
purple: '#800080',
rebeccapurple: '#663399',
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',
};
const COLORS_REGEX = {
// #rgb
hex3: /^#([A-Fa-f0-9]{3})$/,
// #rgba
hex4: /^#([A-Fa-f0-9]{3}[A-Fa-f0-9]{1})$/,
// #rrggbb
hex6: /^#([A-Fa-f0-9]{6})$/,
// #rrggbbaa
hex8: /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,
hsl: [
// hsl(360deg, 100%, 100%) hsl(360, 100%, 100%)
/^hsl\s*\(\s*(\d{1,3})(?:deg)?\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*\)$/i,
// hsl(360deg 100% 100%) hsl(360 100% 100%)
/^hsl\s*\(\s*(\d{1,3})(?:deg)?\s+([\d.]+)%\s+([\d.]+)%\s*\)$/i,
],
hsla: [
// hsla(360deg, 100%, 100%, 1.0) hsla(360, 100%, 100%, 1.0) hsl(360deg, 100%, 100%, 1.0) hsl(360, 100%, 100%, 1.0)
/^hsla?\s*\(\s*(\d{1,3})(?:deg)?\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*,\s*(\d|\d\.\d+)\s*\)$/i,
// hsla(360deg 100% 100% / 1.0) hsla(360 100% 100% / 1.0) hsl(360deg 100% 100% / 1.0) hsl(360 100% 100% / 1.0)
/^hsla?\s*\(\s*(\d{1,3})(?:deg)?\s+([\d.]+)%\s+([\d.]+)%\s*\/\s*(\d|\d\.\d+)\s*\)$/i,
],
hsv: [
// hsv(360deg, 000%, 000%) hsv(360, 100%, 100%)
/^hsv\s*\(\s*(\d{1,3})(?:deg)?\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*\)$/i,
// hsv(360deg 000% 000%) hsv(360 100% 100%)
/^hsv\s*\(\s*(\d{1,3})(?:deg)?\s+([\d.]+)%\s+([\d.]+)%\s*\)$/i,
],
hsva: [
// hsva(360deg, 100%, 100%, 1.0) hsva(360, 100%, 100%, 1.0) hsv(360deg, 100%, 100%, 1.0) hsv(360, 100%, 100%, 1.0)
/^hsva?\s*\(\s*(\d{1,3})(?:deg)?\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*,\s*(\d|\d\.\d+)\s*\)$/i,
// hsva(360deg 100% 100% / 1.0) hsva(360 100% 100% / 1.0) hsv(360deg 100% 100% / 1.0) hsv(360 100% 100% / 1.0)
/^hsva?\s*\(\s*(\d{1,3})(?:deg)?\s+([\d.]+)%\s+([\d.]+)%\s*\/\s*(\d|\d\.\d+)\s*\)$/i,
],
hwb: [
// hwb(360deg, 100%, 100%) hwb(360, 100%, 100%)
/^hwb\s*\(\s*(\d{1,3})(?:deg)?\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*\)$/i,
// hwb(360deg 100% 100%) hwb(360 100% 100%)
/^hwb\s*\(\s*(\d{1,3})(?:deg)?\s+([\d.]+)%\s+([\d.]+)%\s*\)$/i,
],
hwba: [
// hwba(360deg, 100%, 100%, 1.0) hwba(360, 100%, 100%, 1.0) hwb(360deg, 100%, 100%, 1.0) hwb(360, 100%, 100%, 1.0)
/^hwba?\s*\(\s*(\d{1,3})(?:deg)?\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*,\s*(\d|\d\.\d+)\s*\)$/i,
// hwb(360deg 100% 100% 1.0) hwb(360 100% 100% / 1.0) hwba(360deg 100% 100% 1.0) hwba(360 100% 100% / 1.0)
/^hwba?\s*\(\s*(\d{1,3})(?:deg)?\s+([\d.]+)%\s+([\d.]+)%\s*\/\s*(\d|\d\.\d+)\s*\)$/i,
],
rgb: [
// rgb(255, 255, 255)
/^rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i,
// rgb(255 255 255)
/^rgb\s*\(\s*(\d{1,3})\s+(\d{1,3})\s+(\d{1,3})\s*\)$/i,
],
rgba: [
// rgba(255, 255, 255, 1.0) rgb(255, 255, 255, 1.0)
/^rgba?\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*([\d.]+)\s*\)$/i,
// rgba(255 255 255 / 1.0) rgb(255 255 255 / 1.0)
/^rgba?\s*\(\s*(\d{1,3})\s+(\d{1,3})\s+(\d{1,3})\s*\/\s*([\d.]+)\s*\)$/i,
],
};
// * MARK: General utilities
const clamp = (value, min, max) => {
return Math.max(min, Math.min(value, max));
};
const clampRGB = value => {
return clamp(value, 0, 255);
};
const clampHue = value => {
return clamp(value, 0, 360);
};
const clamp100 = value => {
return clamp(value, 0, 100);
};
const clampAlpha = value => {
return clamp(+value.toFixed(2), 0, 1);
};
const randomNumber = (min, max) => {
return Math.random() * (max - min) + min;
};
const numberToHexString = c => {
c = clampRGB(Math.round(c));
const hex = c.toString(16).padStart(2, '0');
return hex;
};
const calculateHueValue = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
};
/** - Identify the color format of a given `string` or `object` */
const detectColorFormat = color => {
// color int
if (typeof color === 'number') {
if (color >>> 0 === color && color >= 0 && color <= 0xffffffff) return 'hex8';
return null;
}
// color string
if (typeof color === 'string') {
color = color.trim().toLowerCase();
for (const key in COLORS_REGEX) {
const format = key;
const entry = COLORS_REGEX[format];
if (Array.isArray(entry)) {
for (let i = 0; i < entry.length; i++) {
if (entry[i].test(color)) return format;
}
continue;
}
if (entry.test(color)) return format;
}
}
// color object
if (typeof color === 'object') {
const rgbaKeys = ['r', 'g', 'b', 'a'];
const isRgbaOb = rgbaKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isRgbaOb) return 'rgba';
const rgbKeys = ['r', 'g', 'b'];
const isRgbOb = rgbKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isRgbOb) return 'rgb';
const hslaKeys = ['h', 's', 'l', 'a'];
const isHslaOb = hslaKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHslaOb) return 'hsla';
const hslKeys = ['h', 's', 'l'];
const isHslOb = hslKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHslOb) return 'hsl';
const hsvaKeys = ['h', 's', 'v', 'a'];
const isHsvaOb = hsvaKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHsvaOb) return 'hsva';
const hsvKeys = ['h', 's', 'v'];
const isHsvOb = hsvKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHsvOb) return 'hsv';
const hwbaKeys = ['h', 'w', 'b', 'a'];
const isHwbaOb = hwbaKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHwbaOb) return 'hwba';
const hwbKeys = ['h', 'w', 'b'];
const isHwbOb = hwbKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHwbOb) return 'hwb';
}
return null;
};
// * MARK: RGB
/** - Parse `RGB` or `RGBA` color string to an `object` */
const RGB_string_to_object = color => {
color = color.trim().toLowerCase();
const colorType = detectColorFormat(color);
if (!colorType || !colorType.includes('rgb')) {
console.error(
'[colorKit.getRgbObject] is unable to parse the string into an `RGB` object. As a result, the color "black" will be returned instead.',
);
return {
r: 0,
g: 0,
b: 0,
a: 1,
};
}
let matches = null;
const entry = COLORS_REGEX[colorType];
if (Array.isArray(entry)) {
for (let i = 0; i < entry.length; i++) {
if (entry[i].test(color)) matches = color.match(entry[i]);
}
} else {
matches = color.match(entry);
}
if (!matches || matches.length < 4) {
console.error(
'[colorKit.getRgbObject] An error occurred while attempting to destructuring `RGB` values from the given string. As a result, the color "black" will be returned instead.',
);
return {
r: 0,
g: 0,
b: 0,
a: 1,
};
}
const r = parseInt(matches[1], 10),
g = parseInt(matches[2], 10),
b = parseInt(matches[3], 10),
a = parseFloat(matches[4] ?? '1');
return {
r: clampRGB(r),
g: clampRGB(g),
b: clampRGB(b),
a: clampAlpha(a),
};
};
/** - Ensure that the `RGB` object values are within the correct range and that it has the alpha channel */
const normalize_RGB_object = color => {
return {
r: clampRGB(color.r),
g: clampRGB(color.g),
b: clampRGB(color.b),
a: clampAlpha(color.a ?? 1),
};
};
/** - Convert an `RGB` or `RGBA` color to its corresponding `Hex` color */
const RGB_to_HEX = color => {
const { r, g, b, a } = typeof color === 'string' ? RGB_string_to_object(color) : normalize_RGB_object(color);
const red = numberToHexString(r),
green = numberToHexString(g),
blue = numberToHexString(b),
alpha = a === 1 ? '' : numberToHexString(a * 255);
return `#${red + green + blue + alpha}`;
};
/** - Convert `RGB` or `RGBA` color to an `RGBA` object representation */
const RGB_to_RGB = color => {
return typeof color === 'string' ? RGB_string_to_object(color) : normalize_RGB_object(color);
};
/** - Convert an `RGB` or `RGBA` color to an `HSLA` object representation */
const RGB_to_HSLA = color => {
const rgb = typeof color === 'string' ? RGB_string_to_object(color) : normalize_RGB_object(color),
r = rgb.r / 255,
g = rgb.g / 255,
b = rgb.b / 255,
a = rgb.a;
const max = Math.max(r, g, b),
min = Math.min(r, g, b);
let h = 0,
s,
l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
if (max === r) {
h = (g - b) / d + (g < b ? 6 : 0);
} else if (max === g) {
h = (b - r) / d + 2;
} else if (max === b) {
h = (r - g) / d + 4;
}
h /= 6;
}
h = clampHue(h * 360);
s = clamp100(s * 100);
l = clamp100(l * 100);
return {
h,
s,
l,
a: clampAlpha(a),
};
};
/** - Convert `RGB` or `RGBA` color to an `HSVA` object representation */
const RGB_to_HSVA = color => {
const rgb = typeof color === 'string' ? RGB_string_to_object(color) : normalize_RGB_object(color),
r = rgb.r / 255,
g = rgb.g / 255,
b = rgb.b / 255,
a = rgb.a;
const max = Math.max(r, g, b),
min = Math.min(r, g, b),
d = max - min,
v = max,
s = max === 0 ? 0 : d / max;
let h = 0;
if (max === min) {
h = 0;
} else {
if (max === r) {
h = (g - b) / d + (g < b ? 6 : 0);
} else if (max === g) {
h = (b - r) / d + 2;
} else if (max === b) {
h = (r - g) / d + 4;
}
h = h / 6;
}
return {
h: clampHue(h * 360),
s: clamp100(s * 100),
v: clamp100(v * 100),
a: clampAlpha(a),
};
};
/** - Convert `RGB` or `RGBA` color to an `HWBA` object representation */
const RGB_to_HWBA = color => {
const rgb = typeof color === 'string' ? RGB_string_to_object(color) : normalize_RGB_object(color),
red = rgb.r / 255,
green = rgb.g / 255,
blue = rgb.b / 255,
a = rgb.a;
const { h } = RGB_to_HSLA(color);
const white = Math.min(red, green, blue) * 100;
const black = (1 - Math.max(red, green, blue)) * 100;
return {
h: clampHue(h),
w: clamp100(white),
b: clamp100(black),
a: clampAlpha(a),
};
};
/** - Return the `RGB` color as a string, an array, or an object */
const RGB_types = ({ r, g, b, a }) => {
return {
string: forceAlpha => {
r = Math.round(r);
g = Math.round(g);
b = Math.round(b);
// auto
if (typeof forceAlpha === 'undefined') {
if (typeof a === 'number' && a !== 1) return `rgba(${r}, ${g}, ${b}, ${a})`;
return `rgb(${r}, ${g}, ${b})`;
}
if (forceAlpha) return `rgba(${r}, ${g}, ${b}, ${a ?? 1})`;
return `rgb(${r}, ${g}, ${b})`;
},
array: (roundValues = true) => {
if (roundValues) {
r = Math.round(r);
g = Math.round(g);
b = Math.round(b);
}
return [r, g, b, a];
},
object: (roundValues = true) => {
if (roundValues) {
r = Math.round(r);
g = Math.round(g);
b = Math.round(b);
}
return {
r,
g,
b,
a,
};
},
};
};
// * MARK: HSL
/** - Parse `HSL` or `HSLA` color string to an `object` */
const HSL_string_to_object = color => {
color = color.trim().toLowerCase();
const colorType = detectColorFormat(color);
if (!colorType || !colorType.includes('hsl')) {
console.error(
'[colorKit.getHslObject] is unable to parse the string into an `HSL` object. As a result, the color "black" will be returned instead.',
);
return {
h: 0,
s: 0,
l: 0,
a: 1,
};
}
let matches = null;
const entry = COLORS_REGEX[colorType];
if (Array.isArray(entry)) {
for (let i = 0; i < entry.length; i++) {
if (entry[i].test(color)) matches = color.match(entry[i]);
}
} else {
matches = color.match(entry);
}
if (!matches || matches.length < 3) {
console.error(
'[colorKit.getHslObject] An error occurred while attempting to destructuring `HSL` values from the given string. As a result, the color "black" will be returned instead.',
);
return {
h: 0,
s: 0,
l: 0,
a: 1,
};
}
const h = parseInt(matches[1], 10),
s = parseInt(matches[2], 10),
l = parseInt(matches[3], 10),
a = parseFloat(matches[4] ?? '1');
return {
h: clampHue(h),
s: clamp100(s),
l: clamp100(l),
a: clampAlpha(a),
};
};
/** - Ensure that the `HSL` object values are within the correct range and that it has the alpha channel */
const normalize_HSL_object = color => {
return {
h: clampHue(color.h),
s: clamp100(color.s),
l: clamp100(color.l),
a: clampAlpha(color.a ?? 1),
};
};
/** - Convert `HSL` or `HSLA` color to an `RGBA` object representation */
const HSL_to_RGBA = color => {
const hsla = typeof color === 'string' ? HSL_string_to_object(color) : normalize_HSL_object(color);
const h = hsla.h / 360,
s = hsla.s / 100,
l = hsla.l / 100,
a = hsla.a;
const q = l < 0.5 ? l * (1 + s) : l + s - l * s,
p = 2 * l - q;
const r = calculateHueValue(p, q, h + 1 / 3),
g = calculateHueValue(p, q, h),
b = calculateHueValue(p, q, h - 1 / 3);
return {
r: clampRGB(r * 255),
g: clampRGB(g * 255),
b: clampRGB(b * 255),
a: clampAlpha(a),
};
};
/** - Convert `HSL` or `HSLA` color to `HEX` color */
const HSL_to_HEX = color => {
const hsla = typeof color === 'string' ? HSL_string_to_object(color) : normalize_HSL_object(color);
const rgb = HSL_to_RGBA(hsla);
const r = numberToHexString(rgb.r),
g = numberToHexString(rgb.g),
b = numberToHexString(rgb.b),
a = rgb.a === 1 ? '' : numberToHexString(rgb.a * 255);
return `#${r + g + b + a}`;
};
/** - Convert `HSL` or `HSLA` color to an `HSVA` object representation */
const HSL_to_HSVA = color => {
const hsla = typeof color === 'string' ? HSL_string_to_object(color) : normalize_HSL_object(color);
const h = hsla.h;
const s = hsla.s / 100,
l = hsla.l / 100,
a = hsla.a ?? 1,
v = l + s * Math.min(l, 1 - l),
sNew = v === 0 ? 0 : 2 - (2 * l) / v;
return {
h: clampHue(h),
s: clamp100(sNew * 100),
v: clamp100(v * 100),
a: clampAlpha(a),
};
};
/** - Convert `HSL` or `HSLA` color to an `HWBA` object representation */
const HSL_to_HWBA = color => {
const hsva = HSL_to_HSVA(color);
return HSV_to_HWBA(hsva);
};
/** - Convert `HSL` or `HSLA` color to an `HSLA` object representation */
const HSL_to_HSL = color => {
return typeof color === 'string' ? HSL_string_to_object(color) : normalize_HSL_object(color);
};
/** - Return the `HSL` color as a string, an array, or an object */
const HSL_types = ({ h, s, l, a }) => {
return {
string: forceAlpha => {
h = Math.round(h);
s = Math.round(s);
l = Math.round(l);
// auto
if (typeof forceAlpha === 'undefined') {
if (typeof a === 'number' && a !== 1) return `hsla(${h}, ${s}%, ${l}%, ${a})`;
return `hsl(${h}, ${s}%, ${l}%)`;
}
if (forceAlpha) return `hsla(${h}, ${s}%, ${l}%, ${a ?? 1})`;
return `hsl(${h}, ${s}%, ${l}%)`;
},
array: (roundValues = true) => {
if (roundValues) {
h = Math.round(h);
s = Math.round(s);
l = Math.round(l);
}
return [h, s, l, a];
},
object: (roundValues = true) => {
if (roundValues) {
h = Math.round(h);
s = Math.round(s);
l = Math.round(l);
}
return {
h,
s,
l,
a,
};
},
};
};
// * MARK: HWB
/** - Parse `HWB` or `HWBA` color strong to an `object` */
const HWB_string_to_object = color => {
color = color.trim().toLowerCase();
const colorType = detectColorFormat(color);
if (!colorType || !colorType.includes('hwb')) {
console.error(
'[colorKit.getHwbObject] is unable to parse the string into an `HWB` object. As a result, the color "black" will be returned instead.',
);
return {
h: 0,
w: 0,
b: 0,
a: 1,
};
}
let matches = null;
const entry = COLORS_REGEX[colorType];
if (Array.isArray(entry)) {
for (let i = 0; i < entry.length; i++) {
if (entry[i].test(color)) matches = color.match(entry[i]);
}
} else {
matches = color.match(entry);
}
if (!matches || matches.length < 4) {
console.error(
'[colorKit.getHwbObject] An error occurred while attempting to destructuring `HWB` values from the given string. As a result, the color "black" will be returned instead.',
);
return {
h: 0,
w: 0,
b: 0,
a: 1,
};
}
const h = parseInt(matches[1], 10),
w = parseInt(matches[2], 10),
b = parseInt(matches[3], 10),
a = parseFloat(matches[4] ?? '1');
return {
h: clampHue(h),
w: clamp100(w),
b: clamp100(b),
a: clampAlpha(a),
};
};
/** - Ensure that the `HWB` object values are within the correct range and that it has the alpha channel */
const normalize_HWB_object = color => {
return {
h: clampHue(color.h),
w: clamp100(color.w),
b: clamp100(color.b),
a: clampAlpha(color.a ?? 1),
};
};
/** - Convert `HWB` or `HWBA` color to an `RGBA` object representation */
const HWB_to_RGBA = color => {
const hwba = typeof color === 'string' ? HWB_string_to_object(color) : normalize_HWB_object(color);
const h = hwba.h / 360,
w = hwba.w / 100,
b = hwba.b / 100,
a = hwba.a;
if (w + b >= 1) {
const gray = clampRGB((w * 255) / (w + b));
return {
r: gray,
g: gray,
b: gray,
a,
};
}
const red = calculateHueValue(0, 1, h + 1 / 3) * (1 - w - b) + w,
green = calculateHueValue(0, 1, h) * (1 - w - b) + w,
blue = calculateHueValue(0, 1, h - 1 / 3) * (1 - w - b) + w;
return {
r: clampRGB(red * 255),
g: clampRGB(green * 255),
b: clampRGB(blue * 255),
a: clampAlpha(a),
};
};
/** - Convert `HWB` or `HWBA` color to an `Hex` color */
const HWB_to_HEX = color => {
const rgba = HWB_to_RGBA(color);
return RGB_to_HEX(rgba);
};
/** - Convert `HWB` or `HWBA` color to an `HSVA` object representation */
function HWB_to_HSVA(color) {
const hwba = typeof color === 'string' ? HWB_string_to_object(color) : normalize_HWB_object(color);
const h = hwba.h % 360,
w = hwba.w / 100,
b = hwba.b / 100,
a = hwba.a;
const v = (1 - b) * 100;
let s = (1 - w / (v / 100)) * 100;
s = isNaN(s) ? 0 : s;
return {
h: clampHue(h),
s: clamp100(s),
v: clamp100(v),
a: clampAlpha(a),
};
}
/** - Convert `HWB` or `HWBA` color to an `HSLA` object representation */
const HWB_to_HSLA = color => {
const hsva = HWB_to_HSVA(color);
return HSV_to_HSLA(hsva);
};
/** - Convert `HWB` or `HWBA` color to an `HWBA` object representation */
const HWB_to_HWB = color => {
return typeof color === 'string' ? HWB_string_to_object(color) : normalize_HWB_object(color);
};
/** - Return the `HWB` color as a string, an array, or an object */
const HWB_types = ({ h, w, b, a }) => {
return {
string: forceAlpha => {
h = Math.round(h);
w = Math.round(w);
b = Math.round(b);
// auto
if (typeof forceAlpha === 'undefined') {
if (typeof a === 'number' && a !== 1) return `hwb(${h} ${w}% ${b}% / ${a})`;
return `hwb(${h}, ${w}%, ${b}%)`;
}
if (forceAlpha) return `hwb(${h} ${w}% ${b}% / ${a ?? 1})`;
return `hwb(${h} ${w}% ${b}%)`;
},
array: (roundValues = true) => {
if (roundValues) {
h = Math.round(h);
w = Math.round(w);
b = Math.round(b);
}
return [h, w, b, a];
},
object: (roundValues = true) => {
if (roundValues) {
h = Math.round(h);
w = Math.round(w);
b = Math.round(b);
}
return {
h,
w,
b,
a,
};
},
};
};
// * MARK: HSV
/** - Parse `HSV` or `HSVA` color string to an `object` */
const HSV_string_to_object = color => {
color = color.trim().toLowerCase();
const colorType = detectColorFormat(color);
if (!colorType || !colorType.includes('hsv')) {
console.error(
'[colorKit.getHsvObject] is unable to parse the string into an `HSV` object. As a result, the color "black" will be returned instead.',
);
return {
h: 0,
s: 0,
v: 0,
a: 1,
};
}
let matches = null;
const entry = COLORS_REGEX[colorType];
if (Array.isArray(entry)) {
for (let i = 0; i < entry.length; i++) {
if (entry[i].test(color)) matches = color.match(entry[i]);
}
} else {
matches = color.match(entry);
}
if (!matches || matches.length < 4) {
console.error(
'[colorKit.getHsvObject] An error occurred while attempting to destructuring `HSV` values from the given string. As a result, the color "black" will be returned instead.',
);
return {
h: 0,
s: 0,
v: 0,
a: 1,
};
}
const h = parseInt(matches[1], 10),
s = parseInt(matches[2], 10),
v = parseInt(matches[3], 10),
a = parseFloat(matches[4] ?? '1');
return {
h: clampHue(h),
s: clamp100(s),
v: clamp100(v),
a: clampAlpha(a),
};
};
/** - Ensure that the `HSV` object values are within the correct range and that it has the alpha channel */
const normalize_HSV_object = color => {
return {
h: clampHue(color.h),
s: clamp100(color.s),
v: clamp100(color.v),
a: clampAlpha(color.a ?? 1),
};
};
/** - Convert `HSV` color to an `RGBA` object representation */
const HSV_to_RGBA = color => {
const hsva = typeof color === 'string' ? HSV_string_to_object(color) : normalize_HSV_object(color);
const h = hsva.h / 360,
s = hsva.s / 100,
v = hsva.v / 100,
a = hsva.a;
const i = Math.floor(h * 6),
f = h * 6 - i,
p = v * (1 - s),
q = v * (1 - f * s),
t = v * (1 - (1 - f) * s);
let r = 0,
g = 0,
b = 0;
if (i % 6 === 0) {
r = v;
g = t;
b = p;
} else if (i % 6 === 1) {
r = q;
g = v;
b = p;
} else if (i % 6 === 2) {
r = p;
g = v;
b = t;
} else if (i % 6 === 3) {
r = p;
g = q;
b = v;
} else if (i % 6 === 4) {
r = t;
g = p;
b = v;
} else if (i % 6 === 5) {
r = v;
g = p;
b = q;
}
return {
r: clampRGB(r * 255),
g: clampRGB(g * 255),
b: clampRGB(b * 255),
a: clampAlpha(a),
};
};
/** - Convert `HSV` color to an `HSLA` object representation */
const HSV_to_HSLA = color => {
const hsva = typeof color === 'string' ? HSV_string_to_object(color) : normalize_HSV_object(color);
const h = hsva.h,
s = hsva.s / 100,
v = hsva.v / 100,
a = hsva.a;
const l = ((2 - s) * v) / 2,
sl = s * v,
sln = l !== 0 && l !== 1 ? sl / (l < 0.5 ? l * 2 : 2 - l * 2) : sl;
return {
h: clampHue(h),
s: clamp100(sln * 100),
l: clamp100(l * 100),
a: clampAlpha(a),
};
};
/** - Convert `HSV` color to an `Hex` color */
const HSV_to_HEX = color => {
const rgba = HSV_to_RGBA(color);
const hex = RGB_to_HEX(rgba);
return hex;
};
/** - Convert `HSV` color to an `HWBA` object representation */
const HSV_to_HWBA = color => {
const { h, s, v, a } = typeof color === 'string' ? HSV_string_to_object(color) : normalize_HSV_object(color);
const w = (1 - s / 100) * v,
b = (1 - v / 100) * 100;
return {
h: clampHue(h),
w: clamp100(w),
b: clamp100(b),
a: clampAlpha(a),
};
};
/** - Convert `HSV` color to an `HSVA` object representation */
const HSV_to_HSV = color => {
return typeof color === 'string' ? HSV_string_to_object(color) : normalize_HSV_object(color);
};
/** - Return the `HSV` color as a string, an array, or an object */
const HSV_types = ({ h, s, v, a }) => {
return {
string: forceAlpha => {
h = Math.round(h);
s = Math.round(s);
v = Math.round(v);
// auto
if (typeof forceAlpha === 'undefined') {
if (typeof a === 'number' && a !== 1) return `hsva(${h}, ${s}%, ${v}%, ${a})`;
return `hsv(${h}, ${s}%, ${v}%)`;
}
if (forceAlpha) return `hsva(${h}, ${s}%, ${v}%, ${a ?? 1})`;
return `hsv(${h}, ${s}%, ${v}%)`;
},
array: (roundValues = true) => {
if (roundValues) {
h = Math.round(h);
s = Math.round(s);
v = Math.round(v);
}
return [h, s, v, a];
},
object: (roundValues = true) => {
if (roundValues) {
h = Math.round(h);
s = Math.round(s);
v = Math.round(v);
}
return {
h,
s,
v,
a,
};
},
};
};
// * MARK: HEX
/** - Convert any `HEX` color to 8-digit `HEX` color (#rrggbbaa) */
const normalize_HEX = color => {
if (typeof color === 'number') {
return '#' + color.toString(16).padStart(8, '0');
}
color = color.trim().toLowerCase();
const colorType = detectColorFormat(color);
if (!colorType || !colorType.includes('hex')) {
console.error(
'[colorKit.normalizeHexColor] is unable to normalize the `HEX` string provided. As a result, the color "black" will be returned instead.',
);
return '#000000ff';
}
const hex = color.replace(/^#/, '').split('');
if (hex.length === 3) return `#${hex.map(x => x + x).join('')}ff`;
if (hex.length === 4) return `#${hex.map(x => x + x).join('')}`;
if (hex.length === 6) return `#${hex.join('')}ff`;
return color;
};
/** - Convert any `HEX` color to an `RGBA` object representation */
const HEX_to_RGBA = color => {
const hex = normalize_HEX(color);
let matches = null;
const entry = COLORS_REGEX.hex8;
if (Array.isArray(entry)) {
for (let i = 0; i < entry.length; i++) {
if (entry[i].test(hex)) matches = hex.match(entry[i]);
}
} else {
matches = hex.match(entry);
}
if (!matches || matches.length < 4) {
console.error(
'[colorKit.HEX_RGBA] An error occurred while attempting to destructuring `HEX` values from the given string. As a result, the color "black" will be returned instead.',
);
return {
r: 0,
g: 0,
b: 0,
a: 1,
};
}
const r = parseInt(matches[1], 16),
g = parseInt(matches[2], 16),
b = parseInt(matches[3], 16),
a = parseInt(matches[4], 16) / 255;
return {
r: clampRGB(r),
g: clampRGB(g),
b: clampRGB(b),
a: clampAlpha(a),
};
};
/** - Convert any `HEX` color to an `HSVA` object representation */
const HEX_to_HSVA = color => {
const rgb = HEX_to_RGBA(color);
const hsva = RGB_to_HSVA(rgb);
return hsva;
};
/** - Convert any `HEX` color to an `HSLA` object representation */
const HEX_to_HSLA = color => {
const rgb = HEX_to_RGBA(color);
return RGB_to_HSLA(rgb);
};
/** - Convert any `HEX` color to an `HWBA` object representation */
const HEX_to_HWBA = color => {
const rgba = HEX_to_RGBA(color);
return RGB_to_HWBA(rgba);
};
// * MARK: Color conversions
/** - Convert `HSL`, `HSV`, `HWB`, or `RGB` color to the `HEX` color format. */
const HEX = color => {
// named color
if (typeof color === 'string') {
color = color.trim().toLowerCase();
if (NAMED_COLORS.hasOwnProperty(color)) {
color = NAMED_COLORS[color];
}
}
const colorType = detectColorFormat(color);
// RGB to HEX
if (colorType === 'rgb' || colorType === 'rgba') {
return RGB_to_HEX(color);
}
// HSL to HEX
if (colorType === 'hsl' || colorType === 'hsla') {
return HSL_to_HEX(color);
}
// HSV to HEX
if (colorType === 'hsv' || colorType === 'hsva') {
return HSV_to_HEX(color);
}
// HWB to HEX
if (colorType === 'hwb' || colorType === 'hwba') {
return HWB_to_HEX(color);
}
// HEX
if (colorType !== null && colorType !== void 0 && colorType.includes('hex')) {
return normalize_HEX(color);
}
// ! error
console.error(
'[colorKit.HEX] An error occurred while attempting to convert the provided parameter into an `HEX` color. As a result, the default color "black" will be used instead.',
);
return '#000000';
};
/** - Convert `HSL`, `HSV`, `HWB`, or `HEX` color to the `RGB` color format. */
const RGB = color => {
// named color
if (typeof color === 'string') {
color = color.trim().toLowerCase();
if (NAMED_COLORS.hasOwnProperty(color)) {
color = NAMED_COLORS[color];
}
}
const colorType = detectColorFormat(color);
// HEX to RGB
if (colorType !== null && colorType !== void 0 && colorType.includes('hex')) {
const rgb = HEX_to_RGBA(color);
return RGB_types(rgb);
}
// HSL to RGB
if (colorType === 'hsl' || colorType === 'hsla') {
const rgb = HSL_to_RGBA(color);
return RGB_types(rgb);
}
// HSV to RGB
if (colorType === 'hsv' || colorType === 'hsva') {
const rgb = HSV_to_RGBA(color);
return RGB_types(rgb);
}
// HWB to RGB
if (colorType === 'hwb' || colorType === 'hwba') {
const rgb = HWB_to_RGBA(color);
return RGB_types(rgb);
}
// RGB to normalized RGB
if (colorType === 'rgb' || colorType === 'rgba') {
const rgba = RGB_to_RGB(color);
return RGB_types(rgba);
}
// ! error
console.error(
'[colorKit.RGB] An error occurred while attempting to convert the provided parameter into an `RGB` color. As a result, the default color "black" will be used instead.',
);
return RGB_types({
r: 0,
g: 0,
b: 0,
a: 1,
});
};
/** - Convert `HEX`, `HSV`, `HWB`, or `RGB` color to the `HSL` color format. */
const HSL = color => {
// named color
if (typeof color === 'string') {
color = color.trim().toLowerCase();
if (NAMED_COLORS.hasOwnProperty(color)) {
color = NAMED_COLORS[color];
}
}
const colorType = detectColorFormat(color);
// HEX to HSL
if (colorType !== null && colorType !== void 0 && colorType.includes('hex')) {
const hsla = HEX_to_HSLA(color);
return HSL_types(hsla);
}
// RGB to HSL
if (colorType === 'rgb' || colorType === 'rgba') {
const hsla = RGB_to_HSLA(color);
return HSL_types(hsla);
}
// HSV to HSL
if (colorType === 'hsv' || colorType === 'hsva') {
const hsla = HSV_to_HSLA(color);
return HSL_types(hsla);
}
// HWB to HSL
if (colorType === 'hwb' || colorType === 'hwba') {
const hsla = HWB_to_HSLA(color);
return HSL_types(hsla);
}
// HSL to normalized HSL
if (colorType === 'hsl' || colorType === 'hsla') {
const hsla = HSL_to_HSL(color);
return HSL_types(hsla);
}
// ! error
console.error(
'[colorKit.HSL] An error occurred while attempting to convert the provided parameter into an `HSL` color. As a result, the default color "black" will be used instead.',
);
return HSL_types({
h: 0,
s: 0,
l: 0,
a: 1,
});
};
/** - Convert `HSL`, `HEX`, `HSV`, or `RGB` color to the `HWB` color format. */
const HWB = color => {
// named color
if (typeof color === 'string') {
color = color.trim().toLowerCase();
if (NAMED_COLORS.hasOwnProperty(color)) {
color = NAMED_COLORS[color];
}
}
const colorType = detectColorFormat(color);
// HEX to HWB
if (colorType !== null && colorType !== void 0 && colorType.includes('hex')) {
const hwba = HEX_to_HWBA(color);
return HWB_types(hwba);
}
// RGB to HWB
if (colorType === 'rgb' || colorType === 'rgba') {
const hwba = RGB_to_HWBA(color);
return HWB_types(hwba);
}
// HSL to HWB
if (colorType === 'hsl' || colorType === 'hsla') {
const hwba = HSL_to_HWBA(color);
return HWB_types(hwba);
}
// HSV to HWB
if (colorType === 'hsv' || colorType === 'hsva') {
const hwba = HSV_to_HWBA(color);
return HWB_types(hwba);
}
// HWB to normalized HWB
if (colorType === 'hwb' || colorType === 'hwba') {
const hwba = HWB_to_HWB(color);
return HWB_types(hwba);
}
// ! error
console.error(
'[colorKit.HWB] An error occurred while attempting to convert the provided parameter into an `HWB` color. As a result, the default color "black" will be used instead.',
);
return HWB_types({
h: 0,
w: 0,
b: 100,
a: 1,
});
};
/** - Convert `HSL`, `HEX`, `HWB`, or `RGB` color to the `HSV` color format. */
const HSV = color => {
// named color
if (typeof color === 'string') {
color = color.trim().toLowerCase();
if (NAMED_COLORS.hasOwnProperty(color)) {
color = NAMED_COLORS[color];
}
}
const colorType = detectColorFormat(color);
// HEX to HSV
if (colorType !== null && colorType !== void 0 && colorType.includes('hex')) {
const hsva = HEX_to_HSVA(color);
return HSV_types(hsva);
}
// RGB to HSV
if (colorType === 'rgb' || colorType === 'rgba') {
const hsva = RGB_to_HSVA(color);
return HSV_types(hsva);
}
// HSL to HSV
if (colorType === 'hsl' || colorType === 'hsla') {
const hsva = HSL_to_HSVA(color);
return HSV_types(hsva);
}
// HWB to HSV
if (colorType === 'hwb' || colorType === 'hwba') {
const hsva = HWB_to_HSVA(color);
return HSV_types(hsva);
}
// HSV to normalized HSV
if (colorType === 'hsv' || colorType === 'hsva') {
const hsva = HSV_to_HSV(color);
return HSV_types(hsva);
}
// ! error
console.error(
'[colorKit.HSV] An error occurred while attempting to convert the provided parameter into an `HSV` color. As a result, the default color "black" will be used instead.',
);
return HSV_types({
h: 0,
s: 0,
v: 0,
a: 1,
});
};
// * MARK: Color Information
/** - Identify the color format of a given `string` or `object`, and return `null` for invalid colors. */
const getFormat = color => {
// color int
if (typeof color === 'number') {
if (color >>> 0 === color && color >= 0 && color <= 0xffffffff) return 'hex8';
return null;
}
// color string
if (typeof color === 'string') {
color = color.trim().toLowerCase();
if (NAMED_COLORS.hasOwnProperty(color)) return 'named';
for (const key in COLORS_REGEX) {
const format = key;
const entry = COLORS_REGEX[format];
if (Array.isArray(entry)) {
for (let i = 0; i < entry.length; i++) if (entry[i].test(color)) return format;
continue;
}
if (entry.test(color)) return format;
}
}
// color object
if (typeof color === 'object') {
const rgbaKeys = ['r', 'g', 'b', 'a'];
const isRgbaOb = rgbaKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isRgbaOb) return 'rgba';
const rgbKeys = ['r', 'g', 'b'];
const isRgbOb = rgbKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isRgbOb) return 'rgb';
const hslaKeys = ['h', 's', 'l', 'a'];
const isHslaOb = hslaKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHslaOb) return 'hsla';
const hslKeys = ['h', 's', 'l'];
const isHslOb = hslKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHslOb) return 'hsl';
const hsvaKeys = ['h', 's', 'v', 'a'];
const isHsvaOb = hsvaKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHsvaOb) return 'hsva';
const hsvKeys = ['h', 's', 'v'];
const isHsvOb = hsvKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHsvOb) return 'hsv';
const hwbaKeys = ['h', 'w', 'b', 'a'];
const isHwbaOb = hwbaKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHwbaOb) return 'hwba';
const hwbKeys = ['h', 'w', 'b'];
const isHwbOb = hwbKeys.every(k => color.hasOwnProperty(k) && typeof color[k] === 'number');
if (isHwbOb) return 'hwb';
}
return null;
};
/** - Get the `red` channel value of a given color. */
const getRed = color => {
const { r } = RGB(color).object();
return r;
};
/** - Get the `green` channel value of a given color. */
const getGreen = color => {
const { g } = RGB(color).object();
return g;
};
/** - Get the `blue` channel value of a given color. */
const getBlue = color => {
const { b } = RGB(color).object();
return b;
};
/** - Get the `hue` channel value of a given color. */
const getHue = color => {
const { h } = HSL(color).object();
return h;
};
/** - Get the `saturation` value of a given color. */
const getSaturation = color => {
const { s } = HSL(color).object();
return s;
};
/**
* - Get color's HSL `luminosity` channel value.
* - If you want the overall `luminosity` of a color use `getLuminanceWCAG` method.
*/
const getLuminance = color => {
const { l } = HSL(color).object();
return l;
};
/** - Get the HSV's `value` (brightness) channel value of a given color. */
const getBrightness = color => {
const { v } = HSV(color).object();
return v;
};
/** - Returns the perceived `luminance` of a color, from `0-1` as defined by Web Content Accessibility Guidelines (Version 2.0). */
const getLuminanceWCAG = color => {
const { r, g, b } = RGB(color).object(false);
const a = [r, g, b].map(v => (v / 255 <= 0.03928 ? v / 255 / 12.92 : Math.pow((v / 255 + 0.055) / 1.055, 2.4)));
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
};
/** - Returns a boolean indicating whether the color is considered "dark" or not */
const isDark = color => {
const luminance = getLuminanceWCAG(color);
return luminance < 0.5;
};
/** - Returns a boolean indicating whether the color is considered "light" or not */
const isLight = color => {
const luminance = getLuminanceWCAG(color);
return luminance >= 0.5;
};
/**
* - Check if two colors are similar within a specified tolerance.
*
* @example
* const tolerance = 0;
* const isEqual = colorKit.areColorsEqual('#f00', 'red', tolerance); // true
*/
const areColorsEqual = (color1, color2, tolerance = 0) => {
const rgb1 = RGB(color1).object();
const rgb2 = RGB(color2).object();
const deltaR = rgb1.r - rgb2.r;
const deltaG = rgb1.g - rgb2.g;
const deltaB = rgb1.b - rgb2.b;
const difference = Math.sqrt(deltaR * deltaR + deltaG * deltaG + deltaB * deltaB);
return difference <= tolerance;
};
/** - Calculates the contrast ratio between two colors, useful for ensuring accessibility and readability. */
const contrastRatio = (color1, color2) => {
const luminance1 = getLuminanceWCAG(color1);
const luminance2 = getLuminanceWCAG(color2);
const contrast = (Math.max(luminance1, luminance2) + 0.05) / (Math.min(luminance1, luminance2) + 0.05);
return Math.round(contrast * 100) / 100;
};
// * MARK: Color Manipulation
const returnColorObject = color => {
return {
hex() {
return HEX(color);
},
rgb() {
return RGB(color);
},
hsl() {
return HSL(color);
},
hsv() {
return HSV(color);
},
hwb() {
return HWB(color);
},
};
};
// * MARK: Red Manuipulation
/** Set the `red` value of a color to a specific amount. */
const setRed = (color, amount) => {
const { g, b, a } = RGB(color).object();
const newR = clampRGB(amount);
const newColor = {
r: newR,
g,
b,
a,
};
return returnColorObject(newColor);
};
/**
* Increase the `red` value of a color by the given percentage/amount.
*
* @example
* increaseRed('rgb(100, 100, 100)', 20).hex();
* increaseRed('rgb(100, 100, 100)', '20%').rgb().string();
*/
const increaseRed = (color, amount) => {
const { r, g, b, a } = RGB(color).object();
const red = typeof amount === 'string' ? r + r * (parseFloat(amount) / 100) : r + amount;
const newR = clampRGB(red);
const newColor = {
r: newR,
g,
b,
a,
};
return returnColorObject(newColor);
};
/**
* Decrease the `red` value of a color by the given percentage/amount
*
* @example
* decreaseRed('rgb(100, 100, 100)', 20).hex();
* decreaseRed('rgb(100, 100, 100)', '20%').rgb().string();
*/
const decreaseRed = (color, amount) => {
const { r, g, b, a } = RGB(color).object();
const red = typeof amount === 'string' ? r - r * (parseFloat(amount) / 100) : r - amount;
const newR = clampRGB(red);
const newColor = {
r: newR,
g,
b,
a,
};
return returnColorObject(newColor);
};
// * MARK: Green Manuipulation
/** - Set the `green` value of a color to a specific amount. */
const setGreen = (color, amount) => {
const { r, b, a } = RGB(color).object();
const newG = clampRGB(amount);
const newColor = {
r,
g: newG,
b,
a,
};
return returnColorObject(newColor);
};
/**
* Increase the `green` value of a color by the given percentage.
*
* @example
* increaseGreen('rgb(100, 100, 100)', 20).hex();
* increaseGreen('rgb(100, 100, 100)', '20%').rgb().string();
*/
const increaseGreen = (color, amount) => {
const { r, g, b, a } = RGB(color).object();
const green = typeof amount === 'string' ? g + g * (parseFloat(amount) / 100) : g + amount;
const newG = clampRGB(green);
const newColor = {
r,
g: newG,
b,
a,
};
return returnColorObject(newColor);
};
/**
* Decrease the `green` value of a color by the given percentage.
*
* @example
* decreaseGreen('rgb(100, 100, 100)', 20).hex();
* decreaseGreen('rgb(100, 100, 100)', '20%').rgb().string();
*/
const decreaseGreen = (color, amount) => {
const { r, g, b, a } = RGB(color).object();
const green = typeof amount === 'string' ? g - g * (parseFloat(amount) / 100) : g - amount;
const newG = clampRGB(green);
const newColor = {
r,
g: newG,
b,
a,
};
return returnColorObject(newColor);
};
// * MARK: Blue Manuipulation
/** - Set the `blue` value of a color to a specific amount. */
const setBlue = (color, amount) => {
const { r, g, a } = RGB(color).object();
const newB = clampRGB(amount);
const newColor = {
r,
g,
b: newB,
a,
};
return returnColorObject(newColor);
};
/**
* Increase the `blue` value of a color by the given percentage.
*
* @example
* increaseBlue('rgb(100, 100, 100)', 20).hex();
* increaseBlue('rgb(100, 100, 100)', '20%').rgb().string();
*/
const increaseBlue = (color, amount) => {
const { r, g, b, a } = RGB(color).object();
const blue = typeof amount === 'string' ? b + b * (parseFloat(amount) / 100) : b + amount;
const newB = clampRGB(blue);
const newColor = {
r,
g,
b: newB,
a,
};
return returnColorObject(newColor);
};
/**
* Decrease the `blue` value of a color by the given percentage.
*
* @example
* decreaseBlue('rgb(100, 100, 100)', 20).hex();
* decreaseBlue('rgb(100, 100, 100)', '20%').rgb().string();
*/
const decreaseBlue = (color, amount) => {
const { r, g, b, a } = RGB(color).object();
const blue = typeof amount === 'string' ? b - b * (parseFloat(amount) / 100) : b - amount;
const newB = clampRGB(blue);
const newColor = {
r,
g,
b: newB,
a,
};
return returnColorObject(newColor);
};
//* MARK: Alpha Manuipulation
/** - Get the `alpha` value of a given color. */
const getAlpha = color => {
const { a } = RGB(color).object();