diff options
Diffstat (limited to 'src/alf/util')
-rw-r--r-- | src/alf/util/__tests__/colors.test.ts | 48 | ||||
-rw-r--r-- | src/alf/util/colorGeneration.ts | 28 |
2 files changed, 76 insertions, 0 deletions
diff --git a/src/alf/util/__tests__/colors.test.ts b/src/alf/util/__tests__/colors.test.ts new file mode 100644 index 000000000..350b6ff4a --- /dev/null +++ b/src/alf/util/__tests__/colors.test.ts @@ -0,0 +1,48 @@ +import {jest} from '@jest/globals' + +import {logger} from '#/logger' +import {transparentifyColor} from '../colorGeneration' + +jest.mock('#/logger', () => ({ + logger: {warn: jest.fn()}, +})) + +describe('transparentifyColor', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + it('converts hsl() to hsla()', () => { + const result = transparentifyColor('hsl(120 100% 50%)', 0.5) + expect(result).toBe('hsla(120 100% 50%, 0.5)') + }) + + it('converts hsl() to hsla() - fully transparent', () => { + const result = transparentifyColor('hsl(120 100% 50%)', 0) + expect(result).toBe('hsla(120 100% 50%, 0)') + }) + + it('converts rgb() to rgba()', () => { + const result = transparentifyColor('rgb(255 0 0)', 0.75) + expect(result).toBe('rgba(255 0 0, 0.75)') + }) + + it('expands 3-digit hex and appends alpha channel', () => { + const result = transparentifyColor('#abc', 0.4) + expect(result).toBe('#aabbcc66') + }) + + it('appends alpha to 6-digit hex', () => { + const result = transparentifyColor('#aabbcc', 0.4) + expect(result).toBe('#aabbcc66') + }) + + it('returns the original string and warns for unsupported formats', () => { + const unsupported = 'blue' + const result = transparentifyColor(unsupported, 0.5) + expect(result).toBe(unsupported) + expect(logger.warn).toHaveBeenCalledWith( + `Could not make '${unsupported}' transparent`, + ) + }) +}) diff --git a/src/alf/util/colorGeneration.ts b/src/alf/util/colorGeneration.ts index 8d769b51b..574ab0a49 100644 --- a/src/alf/util/colorGeneration.ts +++ b/src/alf/util/colorGeneration.ts @@ -1,3 +1,5 @@ +import {logger} from '#/logger' + export const BLUE_HUE = 211 export const RED_HUE = 346 export const GREEN_HUE = 152 @@ -19,3 +21,29 @@ export function generateScale(start: number, end: number) { export const defaultScale = generateScale(6, 100) // dim shifted 6% lighter export const dimScale = generateScale(12, 100) + +export function transparentifyColor(color: string, alpha: number) { + if (color.startsWith('hsl(')) { + return 'hsla(' + color.slice('hsl('.length, -1) + `, ${alpha})` + } else if (color.startsWith('rgb(')) { + return 'rgba(' + color.slice('rgb('.length, -1) + `, ${alpha})` + } else if (color.startsWith('#')) { + if (color.length === 7) { + const alphaHex = Math.round(alpha * 255).toString(16) + // Per MDN: If there is only one number, it is duplicated: e means ee + // https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color + return color.slice(0, 7) + alphaHex.padStart(2, alphaHex) + } else if (color.length === 4) { + // convert to 6-digit hex before adding alpha + const [r, g, b] = color.slice(1).split('') + const alphaHex = Math.round(alpha * 255).toString(16) + return `#${r.repeat(2)}${g.repeat(2)}${b.repeat(2)}${alphaHex.padStart( + 2, + alphaHex, + )}` + } + } else { + logger.warn(`Could not make '${color}' transparent`) + } + return color +} |