Skip to content

Commit

Permalink
feat: add color class
Browse files Browse the repository at this point in the history
  • Loading branch information
falkoschumann committed Jun 12, 2024
1 parent ca8a0e3 commit aa6af82
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 0 deletions.
85 changes: 85 additions & 0 deletions packages/shared/src/color.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
const FACTOR = 0.7;

export class Color {
#value;

constructor(red, green, blue) {
if (green === undefined && blue === undefined) {
if (typeof red === 'string') {
this.#value = parseInt(red, 16);
return;
}

this.#value = Number(red);
return;
}

this.#value =
((red & 0xff) << 16) | ((green & 0xff) << 8) | ((blue & 0xff) << 0);
}

get rgb() {
return this.#value;
}

get red() {
return (this.rgb >> 16) & 0xff;
}

get green() {
return (this.rgb >> 8) & 0xff;
}

get blue() {
return (this.rgb >> 0) & 0xff;
}

brighter(factor = FACTOR) {
if (Number.isNaN(this.rgb)) {
return new Color();
}

let red = this.red;
let green = this.green;
let blue = this.blue;

const inverse = Math.floor(1 / (1 - factor));
if (red === 0 && green === 0 && blue === 0) {
return new Color(inverse, inverse, inverse);
}

if (red > 0 && red < inverse) red = inverse;
if (green > 0 && green < inverse) green = inverse;
if (blue > 0 && blue < inverse) blue = inverse;

return new Color(
Math.min(Math.floor(red / FACTOR), 255),
Math.min(Math.floor(green / FACTOR), 255),
Math.min(Math.floor(blue / FACTOR), 255),
);
}

darker(factor = FACTOR) {
if (Number.isNaN(this.rgb)) {
return new Color();
}

return new Color(
Math.max(Math.floor(this.red * factor), 0),
Math.max(Math.floor(this.green * factor), 0),
Math.max(Math.floor(this.blue * factor), 0),
);
}

valueOf() {
return this.rgb;
}

toString() {
if (Number.isNaN(this.rgb)) {
return 'Invalid Color';
}

return this.rgb.toString(16).padStart(6, '0');
}
}
1 change: 1 addition & 0 deletions packages/shared/src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './clock.js';
export * from './color.js';
export * from './configurable-responses.js';
export * from './duration.js';
export * from './logging.js';
Expand Down
59 changes: 59 additions & 0 deletions packages/shared/test/color.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { describe, expect, test } from '@jest/globals';

import { Color } from '../src';

describe('Color', () => {
test('Creates a color instance from RGB values', () => {
const color = new Color(14, 83, 255);

expect(color.rgb).toEqual(0x0e53ff);
expect(color.red).toEqual(14);
expect(color.green).toEqual(83);
expect(color.blue).toEqual(255);
expect(color.valueOf()).toEqual(0x0e53ff);
expect(color.toString()).toEqual('0e53ff');
});

test('Creates a color instance from RGB value', () => {
const color = new Color(0x0e53ff);

expect(color.valueOf()).toEqual(0x0e53ff);
});

test('Creates a color instance from RGB string', () => {
const color = new Color('0e53ff');

expect(color.valueOf()).toEqual(0x0e53ff);
});

test('Creates invalid color', () => {
const color = new Color();

expect(color.valueOf()).toEqual(Number.NaN);
expect(color.toString()).toEqual('Invalid Color');
});

test('Returns darker color', () => {
const color = new Color('0e53ff');

const newColor = color.darker();

expect(newColor.toString()).toEqual('093ab2');
});

test('Returns brighter color', () => {
const color = new Color('093ab2');

const newColor = color.brighter();

expect(newColor.toString()).toEqual('0c52fe');
});

test('Returns grey when color is black', () => {
const color = new Color('000000');

const newColor = color.brighter();

expect(newColor.toString()).toEqual('030303');
});
});

0 comments on commit aa6af82

Please sign in to comment.