UNPKG

rgb-hex

Version:
74 lines (59 loc) 1.97 kB
// TODO: Remove this ignore comment. // eslint-disable-next-line no-mixed-operators const toHex = (red, green, blue, alpha) => ((blue | green << 8 | red << 16) | 1 << 24).toString(16).slice(1) + alpha; export default function rgbHex(red, green, blue, alpha) { let isPercent = (red + (alpha || '')).toString().includes('%'); if (typeof red === 'string' && !green) { // Single string parameter. const parsed = parseCssRgbString(red); if (!parsed) { throw new TypeError('Invalid or unsupported color format.'); } isPercent = false; [red, green, blue, alpha] = parsed; } else if (alpha !== undefined) { alpha = Number.parseFloat(alpha); } if (typeof red !== 'number' || typeof green !== 'number' || typeof blue !== 'number' || red > 255 || green > 255 || blue > 255 ) { throw new TypeError('Expected three numbers below 256'); } if (typeof alpha === 'number') { if (!isPercent && alpha >= 0 && alpha <= 1) { alpha = Math.round(255 * alpha); } else if (isPercent && alpha >= 0 && alpha <= 100) { alpha = Math.round(255 * alpha / 100); } else { throw new TypeError(`Expected alpha value (${alpha}) as a fraction or percentage`); } alpha = (alpha | 1 << 8).toString(16).slice(1); // eslint-disable-line no-mixed-operators } else { alpha = ''; } return toHex(red, green, blue, alpha); } const parseCssRgbString = input => { const parts = input.replace(/rgba?\(([^)]+)\)/, '$1').split(/[,\s/]+/).filter(Boolean); if (parts.length < 3) { return; } const parseValue = (value, max) => { value = value.trim(); if (value.endsWith('%')) { return Math.min(Number.parseFloat(value) * max / 100, max); } return Math.min(Number.parseFloat(value), max); }; const red = parseValue(parts[0], 255); const green = parseValue(parts[1], 255); const blue = parseValue(parts[2], 255); let alpha; if (parts.length === 4) { alpha = parseValue(parts[3], 1); } return [red, green, blue, alpha]; };