Skip to content

Commit

Permalink
feat: allow controlling opacity in stringToHslaColor
Browse files Browse the repository at this point in the history
  • Loading branch information
spawnia committed Aug 22, 2024
1 parent cb6dc97 commit fc36880
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 29 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
},
"dependencies": {
"date-fns": "3.0.1",
"lodash": "4.17.15"
"lodash": "4.17.21"
},
"devDependencies": {
"@babel/core": "^7.13.1",
Expand Down Expand Up @@ -79,5 +79,5 @@
"ts-node": "^9.1.1",
"typescript": "^5.3.3"
},
"packageManager": "yarn@4.1.1"
"packageManager": "yarn@4.4.0"
}
25 changes: 21 additions & 4 deletions src/stringToColor.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { uniq } from 'lodash';

import { randomString, stringToHslaColor } from './stringToColor';
import { stringToHslaColor } from './stringToColor';

describe('stringToHslaColor', () => {
it.each(['test', 'test'])(
Expand All @@ -12,11 +12,17 @@ describe('stringToHslaColor', () => {
},
);

it('allows setting the opacity', () => {
expect(stringToHslaColor('test', { opacity: 1.23 })).toStrictEqual(
'hsla(58, 98%, 48%, 1.23)',
);
});

it('returns various hsla colors for various inputs', () => {
const testStrings = ['t', 'te', 'tes', 'test'];
expect(uniq(testStrings.map(stringToHslaColor)).length).toBe(
testStrings.length,
);
expect(
uniq(testStrings.map((string) => stringToHslaColor(string))).length,
).toBe(testStrings.length);
});

it('returns a valid color for a random string', () => {
Expand All @@ -32,3 +38,14 @@ function isValidColor(color: string): boolean {

return element.style.borderColor.length !== 0;
}

/** Generates a random string with a length of 1-11 chars. */
function randomString(): string {
// Cut off the constant 0. from the beginning
const fractionStart = 2;

// Unequal distribution at the edges, but sufficiently random for the purposes of this function
const randomLengthEnd = Math.round(Math.random() * 11) + 3;

return Math.random().toString(36).substring(fractionStart, randomLengthEnd);
}
33 changes: 19 additions & 14 deletions src/stringToColor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ function hashCode(string: string): number {
return hash;
}

function getHslColor(hash: number): string {
function hashToHslaColor(hash: number, opacity: number): string {
const h = range(hash, 0, 360);
const s = range(hash, 50, 100);
const l = range(hash, 20, 50);
const a = opacity.toString();

return `hsla(${h}, ${s}%, ${l}%, 1)`;
// https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl#values
return `hsla(${h}, ${s}%, ${l}%, ${a})`;
}

function range(hash: number, min: number, max: number): number {
Expand All @@ -24,19 +26,22 @@ function range(hash: number, min: number, max: number): number {
return x + min;
}

export function stringToHslaColor(string: string): string {
return getHslColor(hashCode(string));
}
export type StringToHslaColorOptions = { opacity?: number };

/**
* Generates a random string with a length of 1-11 chars.
* Provides a hsla color value for use in CSS, based on the contents of the given string.
*
* See https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl.
*
* @example stringToHslaColor('test') becomes 'hsla(58, 98%, 48%, 1)' (yellow)
*
* This function tries to provide a good spread of colors for different inputs.
* However, it does not guarantee uniqueness - think of it like hashing.
* It is pure, meaning that the result is only dependent on the inputs.
*/
export function randomString(): string {
// Cut off the constant 0. from the beginning
const fractionStart = 2;

// Unequal distribution at the edges, but sufficiently random for the purposes of this function
const randomLengthEnd = Math.round(Math.random() * 11) + 3;

return Math.random().toString(36).substring(fractionStart, randomLengthEnd);
export function stringToHslaColor(
string: string,
{ opacity = 1 }: StringToHslaColorOptions = {},
): string {
return hashToHslaColor(hashCode(string), opacity);
}
11 changes: 2 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1805,7 +1805,7 @@ __metadata:
eslint-plugin-unused-imports: "npm:^3.1.0"
jest: "npm:^29.7.0"
jest-environment-jsdom: "npm:^29.7.0"
lodash: "npm:4.17.15"
lodash: "npm:4.17.21"
prettier: "npm:^3.1.0"
rollup: "npm:^2.45.2"
rollup-plugin-peer-deps-external: "npm:^2.2.4"
Expand Down Expand Up @@ -7406,14 +7406,7 @@ __metadata:
languageName: node
linkType: hard

"lodash@npm:4.17.15":
version: 4.17.15
resolution: "lodash@npm:4.17.15"
checksum: 10c0/c029ab298357d007252d5802348f1deb343099ba734ae6e6776a908e4995db5b8ed4ae51ff83a2937a1f6e3c41a0c8941eb941926e1a7f2ddfc3d235ec1e8aa7
languageName: node
linkType: hard

"lodash@npm:^4.17.4":
"lodash@npm:4.17.21, lodash@npm:^4.17.4":
version: 4.17.21
resolution: "lodash@npm:4.17.21"
checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c
Expand Down

0 comments on commit fc36880

Please sign in to comment.