|
|
@ -1,8 +1,5 @@ |
|
|
|
import { CharCode } from '../constants'; |
|
|
|
|
|
|
|
const cssColorRegex = |
|
|
|
/^(?:(#?)([0-9a-f]{3}|[0-9a-f]{6})|((?:rgb|hsl)a?)\((-?\d+%?)[,\s]+(-?\d+%?)[,\s]+(-?\d+%?)[,\s]*(-?[\d.]+%?)?\))$/i; |
|
|
|
|
|
|
|
function adjustLight(color: number, amount: number) { |
|
|
|
const cc = color + amount; |
|
|
|
const c = amount < 0 ? (cc < 0 ? 0 : cc) : cc > 255 ? 255 : cc; |
|
|
@ -10,10 +7,12 @@ function adjustLight(color: number, amount: number) { |
|
|
|
return Math.round(c); |
|
|
|
} |
|
|
|
|
|
|
|
// TODO@d13 leaving as is for now, updating to the color library breaks our existing darkened colors
|
|
|
|
export function darken(color: string, percentage: number) { |
|
|
|
return lighten(color, -percentage); |
|
|
|
} |
|
|
|
|
|
|
|
// TODO@d13 leaving as is for now, updating to the color library breaks our existing lightened colors
|
|
|
|
export function lighten(color: string, percentage: number) { |
|
|
|
const rgba = toRgba(color); |
|
|
|
if (rgba == null) return color; |
|
|
@ -24,28 +23,17 @@ export function lighten(color: string, percentage: number) { |
|
|
|
} |
|
|
|
|
|
|
|
export function opacity(color: string, percentage: number) { |
|
|
|
const rgba = toRgba(color); |
|
|
|
const rgba = Color.from(color); |
|
|
|
if (rgba == null) return color; |
|
|
|
|
|
|
|
const [r, g, b, a] = rgba; |
|
|
|
return `rgba(${r}, ${g}, ${b}, ${a * (percentage / 100)})`; |
|
|
|
return rgba.transparent(percentage / 100).toString(); |
|
|
|
} |
|
|
|
|
|
|
|
export function mix(color1: string, color2: string, percentage: number) { |
|
|
|
const rgba1 = toRgba(color1); |
|
|
|
const rgba2 = toRgba(color2); |
|
|
|
const rgba1 = Color.from(color1); |
|
|
|
const rgba2 = Color.from(color2); |
|
|
|
if (rgba1 == null || rgba2 == null) return color1; |
|
|
|
const [r1, g1, b1, a1] = rgba1; |
|
|
|
const [r2, g2, b2, a2] = rgba2; |
|
|
|
return `rgba(${mixChannel(r1, r2, percentage)}, ${mixChannel(g1, g2, percentage)}, ${mixChannel( |
|
|
|
b1, |
|
|
|
b2, |
|
|
|
percentage, |
|
|
|
)}, ${mixChannel(a1, a2, percentage)})`;
|
|
|
|
} |
|
|
|
|
|
|
|
function mixChannel(channel1: number, channel2: number, percentage: number) { |
|
|
|
return channel1 + ((channel2 - channel1) * percentage) / 100; |
|
|
|
return rgba1.mix(rgba2, percentage / 100).toString(); |
|
|
|
} |
|
|
|
|
|
|
|
export function scale(value1: string, value2: string, steps: number): string[] { |
|
|
@ -53,48 +41,22 @@ export function scale(value1: string, value2: string, steps: number): string[] { |
|
|
|
const color1 = Color.from(value1); |
|
|
|
const color2 = Color.from(value2); |
|
|
|
|
|
|
|
colors.push(color1); |
|
|
|
colors.push(color1.toString()); |
|
|
|
const range = steps - 1; |
|
|
|
for (let i = 1; i < range; i++) { |
|
|
|
const newColor = color1.mix(color2, i / range); |
|
|
|
colors.push(newColor); |
|
|
|
colors.push(newColor.toString()); |
|
|
|
} |
|
|
|
colors.push(color2); |
|
|
|
colors.push(color2.toString()); |
|
|
|
|
|
|
|
return colors.map(color => color.toString()); |
|
|
|
return colors; |
|
|
|
} |
|
|
|
|
|
|
|
export function toRgba(color: string) { |
|
|
|
color = color.trim(); |
|
|
|
|
|
|
|
const result = cssColorRegex.exec(color); |
|
|
|
const result = parseString(color); |
|
|
|
if (result == null) return null; |
|
|
|
|
|
|
|
if (result[1] === '#') { |
|
|
|
const hex = result[2]; |
|
|
|
switch (hex.length) { |
|
|
|
case 3: |
|
|
|
return [parseInt(hex[0] + hex[0], 16), parseInt(hex[1] + hex[1], 16), parseInt(hex[2] + hex[2], 16), 1]; |
|
|
|
case 6: |
|
|
|
return [ |
|
|
|
parseInt(hex.substring(0, 2), 16), |
|
|
|
parseInt(hex.substring(2, 4), 16), |
|
|
|
parseInt(hex.substring(4, 6), 16), |
|
|
|
1, |
|
|
|
]; |
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
switch (result[3]) { |
|
|
|
case 'rgb': |
|
|
|
return [parseInt(result[4], 10), parseInt(result[5], 10), parseInt(result[6], 10), 1]; |
|
|
|
case 'rgba': |
|
|
|
return [parseInt(result[4], 10), parseInt(result[5], 10), parseInt(result[6], 10), parseFloat(result[7])]; |
|
|
|
default: |
|
|
|
return null; |
|
|
|
} |
|
|
|
return [result.rgba.r, result.rgba.g, result.rgba.b, result.rgba.a]; |
|
|
|
} |
|
|
|
|
|
|
|
function mixColors(col1: Color, col2: Color, factor: number): Color { |
|
|
@ -711,6 +673,7 @@ export function format(color: Color): string { |
|
|
|
return formatRGBA(color); |
|
|
|
} |
|
|
|
|
|
|
|
const cssColorRegex = /^((?:rgb|hsl)a?)\((-?\d+%?)[,\s]+(-?\d+%?)[,\s]+(-?\d+%?)[,\s]*(-?[\d.]+%?)?\)$/i; |
|
|
|
export function parseString(value: string): Color | null { |
|
|
|
const length = value.length; |
|
|
|
|
|
|
@ -762,8 +725,9 @@ export function parseString(value: string): Color | null { |
|
|
|
* @param hex string (#RGB, #RGBA, #RRGGBB or #RRGGBBAA). |
|
|
|
*/ |
|
|
|
export function parseHex(hex: string): Color | null { |
|
|
|
const length = hex.length; |
|
|
|
hex = hex.trim(); |
|
|
|
|
|
|
|
const length = hex.length; |
|
|
|
if (length === 0) { |
|
|
|
// Invalid color
|
|
|
|
return null; |
|
|
|