|
1 | 1 | // region Types |
| 2 | +/** |
| 3 | + * Includes the leading #. All letters are lowercase. Will always have 6 or 8 characters, excluding the #. |
| 4 | + **/ |
2 | 5 | export type Hex = string & { __hex: true }; |
3 | 6 |
|
4 | 7 | /** |
@@ -106,26 +109,33 @@ export function normalizeHue(hue: number): number { |
106 | 109 | export function StringToHex(hex: string): Hex | null { |
107 | 110 | const hexVal = hex.replace(/^#/, ''); |
108 | 111 | if (![3, 4, 6, 8].includes(hexVal.length)) return null; |
109 | | - if (/^[0-9a-f]+$/i.test(hexVal)) return hexVal as Hex; |
110 | | - return null; |
| 112 | + if (!/^[0-9a-f]+$/i.test(hexVal)) return null; |
| 113 | + |
| 114 | + const isShortHand = hexVal.length === 3 || hexVal.length === 4; |
| 115 | + const hexString = hexVal |
| 116 | + .toLowerCase() |
| 117 | + .split('') |
| 118 | + .map(char => char.repeat(isShortHand ? 2 : 1)) |
| 119 | + .join(''); |
| 120 | + return `#${hexString}` as Hex; |
111 | 121 | } |
112 | 122 |
|
113 | 123 | export function HexToRgb(hex: Hex): Rgb { |
114 | 124 | const hexVal = StringToHex(hex); |
115 | 125 | if (!hexVal) return { R: 0, G: 0, B: 0, colorspace: 'rgba' }; |
116 | | - const isShortHand = hex.length === 3 || hex.length === 4; |
117 | 126 |
|
118 | | - const R = parseInt(isShortHand ? hexVal.substring(0, 1).repeat(2) : hexVal.substring(0, 2), 16); |
119 | | - const G = parseInt(isShortHand ? hexVal.substring(1, 2).repeat(2) : hexVal.substring(2, 4), 16); |
120 | | - const B = parseInt(isShortHand ? hexVal.substring(2, 3).repeat(2) : hexVal.substring(4, 6), 16); |
121 | | - const a = parseInt(isShortHand ? hexVal.substring(3, 4).repeat(2) : hexVal.substring(6, 8), 16); |
| 127 | + const R = parseInt(hexVal.substring(1, 3), 16); |
| 128 | + const G = parseInt(hexVal.substring(3, 5), 16); |
| 129 | + const B = parseInt(hexVal.substring(5, 7), 16); |
| 130 | + const a = parseInt(hexVal.substring(7, 9), 16); |
122 | 131 | const rgba: Rgb = { colorspace: 'rgba', R, G, B }; |
123 | | - if (hex.length === 4 || hex.length === 8) rgba.a = a; |
| 132 | + const hexLength = hexVal.length - 1; |
| 133 | + if (hexLength === 4 || hexLength === 8) rgba.a = a; |
124 | 134 | return rgba; |
125 | 135 | } |
126 | 136 |
|
127 | 137 | export function RgbToHex({ R, G, B, a }: Rgb): Hex { |
128 | | - return `${[R, G, B, ...(a! < 1 ? [Math.round(a! * 255)] : [])] |
| 138 | + return `#${[R, G, B, ...(a! < 1 ? [Math.round(a! * 255)] : [])] |
129 | 139 | .map(n => (Number.isNaN(n) ? 10 : Math.round(Math.min(Math.max(n, 0), 255))).toString(16).padStart(2, '0')) |
130 | 140 | .join('')}` as Hex; |
131 | 141 | } |
|
0 commit comments