From abdda0afabf9c49b7acd7a6d1f8a5e025a2d4a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=BCl=C3=B6p=20Kov=C3=A1cs?= Date: Tue, 7 Jun 2022 16:05:45 +0200 Subject: [PATCH] Support the three/four/six-value syntax variants of --- theatre/shared/src/utils/color.ts | 52 ++++++++++++++++--- .../simpleEditors/RgbaPropEditor.tsx | 5 +- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/theatre/shared/src/utils/color.ts b/theatre/shared/src/utils/color.ts index 93a022c..655a648 100644 --- a/theatre/shared/src/utils/color.ts +++ b/theatre/shared/src/utils/color.ts @@ -1,10 +1,29 @@ import {clamp} from 'lodash-es' +/** + * Robust check for a valid hex value (without the "#") in a string + * + * @remarks + * + * Supports all the syntax variants of + * {@link https://google.com}: + * + * + * ```javascript + * #RGB // The three-value syntax + * #RGBA // The four-value syntax + * #RRGGBB // The six-value syntax + * #RRGGBBAA // The eight-value syntax + * ``` + */ +export const validHexRegExp = /^#*([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i + export function parseRgbaFromHex(rgba: string) { rgba = rgba.trim().toLowerCase() - const hex = rgba.match(/^#?([0-9a-f]{8})$/i) - if (!hex) { + const match = rgba.match(validHexRegExp) + + if (!match) { return { r: 0, g: 0, @@ -13,12 +32,13 @@ export function parseRgbaFromHex(rgba: string) { } } - const match = hex[1] + const hex = _hexInEightValueSyntax(match[1]) + return { - r: parseInt(match.substr(0, 2), 16) / 255, - g: parseInt(match.substr(2, 2), 16) / 255, - b: parseInt(match.substr(4, 2), 16) / 255, - a: parseInt(match.substr(6, 2), 16) / 255, + r: parseInt(hex.substr(0, 2), 16) / 255, + g: parseInt(hex.substr(2, 2), 16) / 255, + b: parseInt(hex.substr(4, 2), 16) / 255, + a: parseInt(hex.substr(6, 2), 16) / 255, } } @@ -126,3 +146,21 @@ export type Laba = { b: number alpha: number } + +/** + * Returns a hex string in the eight-value syntax + */ +function _hexInEightValueSyntax(hex: string): string { + switch (hex.length) { + case 3: + return `${hex.repeat(2)}ff` + case 4: + const rgb = hex.substr(0, 3) + const alpha = hex[3] + return `${rgb.repeat(2)}${alpha.repeat(2)}` + case 6: + return `${hex}ff` + } + + return hex +} diff --git a/theatre/studio/src/propEditors/simpleEditors/RgbaPropEditor.tsx b/theatre/studio/src/propEditors/simpleEditors/RgbaPropEditor.tsx index 67b879e..424ffb6 100644 --- a/theatre/studio/src/propEditors/simpleEditors/RgbaPropEditor.tsx +++ b/theatre/studio/src/propEditors/simpleEditors/RgbaPropEditor.tsx @@ -1,5 +1,6 @@ import type {PropTypeConfig_Rgba} from '@theatre/core/propTypes' -import type {Rgba} from '@theatre/shared/utils/color' +import type {Rgba} from '@theatre/shared/utils/color'; +import { validHexRegExp} from '@theatre/shared/utils/color' import { decorateRgba, rgba2hex, @@ -114,7 +115,7 @@ function RgbaPropEditor({ temporarilySetValue={noop} discardTemporaryValue={noop} permanentlySetValue={onChange} - isValid={(v) => !!v.match(/^#?([0-9a-f]{8})$/i)} + isValid={(v) => !!v.match(validHexRegExp)} /> {popoverNode}