Skip to content

Commit

Permalink
change getContrastColor -> invertColor while improving implementation…
Browse files Browse the repository at this point in the history
… and writing new tests
  • Loading branch information
michael-gee committed Feb 3, 2024
1 parent f275375 commit 984609a
Show file tree
Hide file tree
Showing 14 changed files with 112 additions and 130 deletions.
7 changes: 7 additions & 0 deletions site/docs/api-reference/invertColor.md
@@ -0,0 +1,7 @@
---
sidebar_position: 2
tags:
- validation
---

# invertColor
2 changes: 1 addition & 1 deletion site/docs/api-reference/isEmpty.md
@@ -1,5 +1,5 @@
---
sidebar_position: 2
sidebar_position: 3
tags:
- validation
---
Expand Down
2 changes: 1 addition & 1 deletion site/docs/api-reference/isNil.md
@@ -1,5 +1,5 @@
---
sidebar_position: 3
sidebar_position: 4
tags:
- validation
---
Expand Down
2 changes: 1 addition & 1 deletion site/docs/api-reference/omit.md
@@ -1,5 +1,5 @@
---
sidebar_position: 4
sidebar_position: 5
tags:
- object
---
Expand Down
2 changes: 1 addition & 1 deletion site/docs/api-reference/pick.md
@@ -1,5 +1,5 @@
---
sidebar_position: 5
sidebar_position: 6
tags:
- object
---
Expand Down
2 changes: 1 addition & 1 deletion site/docs/api-reference/uniq.md
@@ -1,5 +1,5 @@
---
sidebar_position: 6
sidebar_position: 7
tags:
- array
---
Expand Down
74 changes: 0 additions & 74 deletions src/getContrastColor/getContrastColor.test.ts

This file was deleted.

46 changes: 0 additions & 46 deletions src/getContrastColor/getContrastColor.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/getContrastColor/index.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/invertColor/index.ts
@@ -0,0 +1 @@
export * from './invertColor';
39 changes: 39 additions & 0 deletions src/invertColor/invertColor.test.ts
@@ -0,0 +1,39 @@
import { describe, it, expect } from 'vitest';
import { invertColor } from './invertColor';

describe('invertColor()', () => {
describe('when the color is provided as a string', () => {
it('should invert the color to the expected value', () => {
expect(invertColor('#000000')).toBe('#FFFFFF');
expect(invertColor('#FFFFFF')).toBe('#000000');
expect(invertColor('#0E0099')).toBe('#F1FF66');
expect(invertColor('#00FF00')).toBe('#FF00FF');
expect(invertColor('#FF0100')).toBe('#00FEFF');
});
});

describe('when the color is provided as an RGB array', () => {
it('should invert the color to the expected value', () => {
expect(invertColor([0, 0, 0])).toBe('#FFFFFF');
expect(invertColor([255, 255, 255])).toBe('#000000');
expect(invertColor([121, 52, 38])).toBe('#86CBD9');
});
});

describe('when the color is provided as a string and the bw option is true', () => {
it('should return black for light colors and white for dark colors', () => {
expect(invertColor('#000000', { bw: true })).toBe('#FFFFFF');
expect(invertColor('FFFFFF', { bw: true })).toBe('#000000');
expect(invertColor('#400B06', { bw: true })).toBe('#FFFFFF');
expect(invertColor('C1EC00', { bw: true })).toBe('#000000');
expect(invertColor('#005856', { bw: true })).toBe('#FFFFFF');
});
});

describe('when the color is provided as an RGB array and the bw option is true', () => {
it('should return black for light colors and white for dark colors', () => {
expect(invertColor([0, 0, 0], { bw: true })).toBe('#FFFFFF');
expect(invertColor([255, 255, 255], { bw: true })).toBe('#000000');
});
});
});
56 changes: 56 additions & 0 deletions src/invertColor/invertColor.ts
@@ -0,0 +1,56 @@
/**
* @name invertColor
* @description - Inverts the color by converting it to its complementary color.
*
* If the color is provided as a string, it should be in hexadecimal format (#RRGGBB).
* If the color is provided as an RGB array, it should be in the format [R, G, B].
* @param color - The color to invert.
* @param options.bw - If true, returns black (#000000) for light colors and white (#FFFFFF) for dark colors.
* @returns The inverted color in hexadecimal format (#RRGGBB).
*/

export type RGB = [red: number, green: number, blue: number];

export function invertColor(color: string | RGB, options?: { bw: boolean }) {
let r, g, b;

if (typeof color === 'string') {
let hex = color;

if (hex.indexOf('#') === 0) {
hex = color.slice(1);
}
// convert 3-digit hex to 6-digits.
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
if (hex.length !== 6) {
throw new Error('Invalid HEX color.');
}

r = parseInt(hex.substring(0, 2), 16);
g = parseInt(hex.substring(2, 4), 16);
b = parseInt(hex.substring(4, 6), 16);
} else {
r = color[0] as number;
g = color[1] as number;
b = color[2] as number;
}

if (options?.bw) {
// https://stackoverflow.com/a/3943023/112731
return r * 0.299 + g * 0.587 + b * 0.114 > 186 ? '#000000' : '#FFFFFF';
}

r = (255 - r).toString(16).toUpperCase();
g = (255 - g).toString(16).toUpperCase();
b = (255 - b).toString(16).toUpperCase();

return '#' + _padZero(r) + _padZero(g) + _padZero(b);
}

function _padZero(str: string, len: number = 2) {
len = len || 2;
const zeros = new Array(len).join('0');
return (zeros + str).slice(-len);
}
6 changes: 3 additions & 3 deletions src/main.d.ts
@@ -1,7 +1,7 @@
export type RGB = [red: number, green: number, blue: number];
export declare function getContrastColor(color: string | RGB, options?: {
returnAs: 'text' | 'hex' | 'rgb';
}): number[] | "black" | "white" | "#000" | "#fff";
export declare function invertColor(color: string | RGB, options?: {
bw: boolean;
}): string;
export declare function isEmpty(value: string | object | unknown[] | Set<unknown> | Map<unknown, unknown>): boolean;
export declare function isNil(value: unknown): boolean;
export declare function omit(object: Record<string, unknown>, properties: string | string[]): {
Expand Down
2 changes: 1 addition & 1 deletion src/main.ts
@@ -1,4 +1,4 @@
export * from './getContrastColor';
export * from './invertColor';
export * from './isEmpty';
export * from './isNil';
export * from './omit';
Expand Down

0 comments on commit 984609a

Please sign in to comment.