From fc368803004ec815e3a058f71c9bb02b17442cb8 Mon Sep 17 00:00:00 2001 From: Benedikt Franke Date: Thu, 22 Aug 2024 09:43:09 +0200 Subject: [PATCH] feat: allow controlling opacity in `stringToHslaColor` --- package.json | 4 ++-- src/stringToColor.test.ts | 25 +++++++++++++++++++++---- src/stringToColor.ts | 33 +++++++++++++++++++-------------- yarn.lock | 11 ++--------- 4 files changed, 44 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 92ea0e6..acc4338 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ }, "dependencies": { "date-fns": "3.0.1", - "lodash": "4.17.15" + "lodash": "4.17.21" }, "devDependencies": { "@babel/core": "^7.13.1", @@ -79,5 +79,5 @@ "ts-node": "^9.1.1", "typescript": "^5.3.3" }, - "packageManager": "yarn@4.1.1" + "packageManager": "yarn@4.4.0" } diff --git a/src/stringToColor.test.ts b/src/stringToColor.test.ts index e1708d5..8d6424a 100644 --- a/src/stringToColor.test.ts +++ b/src/stringToColor.test.ts @@ -1,6 +1,6 @@ import { uniq } from 'lodash'; -import { randomString, stringToHslaColor } from './stringToColor'; +import { stringToHslaColor } from './stringToColor'; describe('stringToHslaColor', () => { it.each(['test', 'test'])( @@ -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', () => { @@ -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); +} diff --git a/src/stringToColor.ts b/src/stringToColor.ts index 10d94e3..2298fa4 100644 --- a/src/stringToColor.ts +++ b/src/stringToColor.ts @@ -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 { @@ -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); } diff --git a/yarn.lock b/yarn.lock index 46c5152..49f378d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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" @@ -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