Skip to content

Commit

Permalink
feat: Update v1.2.3
Browse files Browse the repository at this point in the history
aminekun90 committed Jul 25, 2024

Verified

This commit was signed with the committer’s verified signature.
timofurrer Timo Furrer
1 parent 2fef871 commit c73e2cd
Showing 6 changed files with 140 additions and 73 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "advanced-color-utils",
"version": "1.0.2",
"version": "1.0.3",
"description": "Unleash the full potential of color manipulation with the ColorUtils library! Designed for developers who need precise control over color processing",
"main": "dist/ColorUtils.js",
"types": "dist/ColorUtils.d.ts",
51 changes: 0 additions & 51 deletions src/ColorUtils.js

This file was deleted.

69 changes: 53 additions & 16 deletions src/ColorUtils.ts
Original file line number Diff line number Diff line change
@@ -4,6 +4,37 @@ import { LogPerf } from "@color-utils/decorators/LogPerf";

export class ColorUtils {

/**
* Generate a complementary color for a given hex color.
* @param {string} hex - The hex color string (e.g., '#ff0000').
* @returns {string} The complementary hex color string.
*/
public static getComplementaryColor(hex: string): string {
const complementary = chroma(hex).set('hsl.h', (chroma(hex).get('hsl.h') + 180) % 360);
return complementary.hex();
}

/**
* Generate a color palette based on a given hex color and the desired number of colors.
* @param {string} hex - The hex color string (e.g., '#ff0000').
* @param {number} numColors - The number of colors in the palette.
* @returns {string[]} The array of hex color strings in the palette.
*/
public static generateColorPalette(hex: string, numColors: number): string[] {
return chroma.scale([hex, chroma(hex).set('hsl.h', (chroma(hex).get('hsl.h') + 180) % 360)])
.mode('lab')
.colors(numColors);
}

/**
* Convert an RGB color to a hex color string.
* @param {RGBColor} rgb - The RGB color object.
* @returns {string} The hex color string.
*/
public static rgbToHex(rgb: RGBColor): string {
return chroma(rgb.R, rgb.G, rgb.B).hex();
}

/**
* Convert a hex color to an RGB object.
* @param {string} hex - The hex color string (e.g., "#ff0000").
@@ -14,6 +45,15 @@ export class ColorUtils {
return { R: rgb[0], G: rgb[1], B: rgb[2] };
}

/**
* Convert a LAB color to a hex color string.
* @param {LabColor} lab - The LAB color object.
* @returns {string} The hex color string.
*/
public static labToHex(lab: LabColor): string {
return chroma.lab(lab.L, lab.a, lab.b).hex();
}

/**
* Convert a hex color to a LAB object.
* @param {string} hex - The hex color string (e.g., "#ff0000").
@@ -25,31 +65,28 @@ export class ColorUtils {
}

/**
* Get a specified number of distinct colors from a list based on a similarity threshold.
* @param {string[]} hexColors - The list of hex color strings.
* @param {number} numColors - The number of distinct colors to retrieve.
* @param {number} threshold - The threshold for color similarity (lower values mean more similar).
* @returns {string[]} The list of distinct hex color strings.
*/
* Get a specified number of distinct colors from a list based on a similarity threshold.
* @param {string[]} hexColors - The list of hex color strings.
* @param {number} numColors - The number of distinct colors to retrieve.
* @param {number} threshold - The threshold for color similarity (lower values mean more similar).
* @returns {string[]} The list of distinct hex color strings.
*/
@LogPerf("info")
public static getDistinctColors(hexColors: string[], numColors: number, threshold: number): string[] {
if (numColors <= 0) return [];

const distinctColors: string[] = [];
const labColors = hexColors.map(hex => this.hexToLab(hex));

outerLoop: for (let i = 0; i < labColors.length; i++) {
for (let i = 0; i < labColors.length && distinctColors.length < numColors; i++) {
const labColor = labColors[i];
for (let j = 0; j < distinctColors.length; j++) {
const distinctLab = this.hexToLab(distinctColors[j]);
if (diff(labColor, distinctLab) <= threshold) {
continue outerLoop;
}
}
if (distinctColors.length < numColors) {
const isDistinct = distinctColors.every(distinctHex => {
const distinctLab = this.hexToLab(distinctHex);
return diff(labColor, distinctLab) > threshold;
});

if (isDistinct) {
distinctColors.push(hexColors[i]);
} else {
break;
}
}

85 changes: 83 additions & 2 deletions src/__tests__/ColorUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ColorUtils } from "@color-utils/ColorUtils";
import { generateRandomColor } from "@color-utils/helper/generateColor";
import { ColorUtils } from "../ColorUtils";
import { generateRandomColor } from "../helper/generateColor";
describe("getDistinctColors",()=>{
it("should return the correct number of distinct colors", () => {
const colors = ["#ff0000", "#ff1100", "#00ff00", "#0000ff", "#00ffff", "#ff00ff", "#ffff00", "#000000", "#ffffff"];
@@ -18,6 +18,22 @@ describe("getDistinctColors",()=>{
const filteredColors = ColorUtils.getDistinctColors(colors, numberOfColors, threshold);
expect(filteredColors).toEqual(expect.arrayContaining(["#ff0000", "#00ff00"]));
});
it("should return empty array when empty colors are given", () => {
const colors:Array<string> = [];
const numberOfColors = 2;
const threshold = 2;

const filteredColors = ColorUtils.getDistinctColors(colors, numberOfColors, threshold);
expect(filteredColors).toStrictEqual([]);
});
it("should return empty array numberOfColors is 0", () => {
const colors:Array<string> = ["#ff0000", "#ff0001", "#ff0002", "#00ff00", "#0000ff"];
const numberOfColors = 0;
const threshold = 2;

const filteredColors = ColorUtils.getDistinctColors(colors, numberOfColors, threshold);
expect(filteredColors).toStrictEqual([]);
});
});

describe('ColorUtils Performance', () => {
@@ -37,4 +53,69 @@ describe('ColorUtils Performance', () => {
expect(distinctColors).toBeInstanceOf(Array);
expect(distinctColors.length).toBe(numColorsToRetrieve);
});
});

describe('ColorUtils Features', () => {
it('should generate a complementary color', () => {
const complementaryColor = ColorUtils.getComplementaryColor('#ff0000');
expect(complementaryColor).toBe('#00ffff');
});

it('should generate a color palette', () => {
const palette = ColorUtils.generateColorPalette('#ff0000', 5);
expect(palette.length).toBe(5);
palette.forEach(color => expect(color).toMatch(/^#[0-9a-fA-F]{6}$/));
});

it('should convert RGB to Hex', () => {
const rgb = { R: 255, G: 0, B: 0 };
const hex = ColorUtils.rgbToHex(rgb);
expect(hex).toBe('#ff0000');
});

it('should convert LAB to Hex', () => {
const lab = { L: 53.23288, a: 80.10933, b: 67.22006 };
const hex = ColorUtils.labToHex(lab);
expect(hex).toBe('#ff0000');
});

it('should get distinct colors', () => {
const colors = ['#ff0000', '#00ff00', '#0000ff', '#ff00ff'];
const numColorsToRetrieve = 2;
const threshold = 20;
const distinctColors = ColorUtils.getDistinctColors(colors, numColorsToRetrieve, threshold);
expect(distinctColors.length).toBe(2);
distinctColors.forEach(color => expect(color).toMatch(/^#[0-9a-fA-F]{6}$/));
});

// Unit tests for hexToRgb
it('should convert hex to RGB correctly', () => {
const hex = '#ff0000';
const rgb = ColorUtils.hexToRgb(hex);
expect(rgb).toEqual({ R: 255, G: 0, B: 0 });
});

it('should handle shorthand hex codes', () => {
const hex = '#0f0';
const rgb = ColorUtils.hexToRgb(hex);
expect(rgb).toEqual({ R: 0, G: 255, B: 0 });
});

it('should handle case-insensitive hex codes', () => {
const hex = '#00FF00';
const rgb = ColorUtils.hexToRgb(hex);
expect(rgb).toEqual({ R: 0, G: 255, B: 0 });
});

it('should convert hex to RGB correctly for black', () => {
const hex = '#000000';
const rgb = ColorUtils.hexToRgb(hex);
expect(rgb).toEqual({ R: 0, G: 0, B: 0 });
});

it('should convert hex to RGB correctly for white', () => {
const hex = '#ffffff';
const rgb = ColorUtils.hexToRgb(hex);
expect(rgb).toEqual({ R: 255, G: 255, B: 255 });
});
});
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -19,5 +19,5 @@
}
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
"exclude": ["node_modules", "src/**/__tests__/*"]
}

0 comments on commit c73e2cd

Please sign in to comment.