Skip to content

feat: allow controlling opacity in stringToHslaColor #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading