UNPKG

devextreme

Version:

JavaScript/TypeScript Component Suite for Responsive Web Development

283 lines (269 loc) • 8.24 kB
/** * DevExtreme (cjs/__internal/utils/color.helpers.js) * Version: 26.1.4 * Build date: Fri Jul 24 2026 * * Copyright (c) 2012 - 2026 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertTo01Bounds = convertTo01Bounds; exports.hslToRgb = hslToRgb; exports.hsvToRgb = hsvToRgb; exports.hueToRgb = hueToRgb; exports.isIntegerBetweenMinAndMax = isIntegerBetweenMinAndMax; exports.makeColorTint = makeColorTint; exports.modifyColorTint = modifyColorTint; exports.normalize = normalize; exports.parseColor = parseColor; exports.toHexFromRgb = toHexFromRgb; exports.toHslFromRgb = toHslFromRgb; exports.toHsvFromRgb = toHsvFromRgb; function makeColorTint(colorPart, h) { let colorTint = h; if ("r" === colorPart) { colorTint = h + 1 / 3 } if ("b" === colorPart) { colorTint = h - 1 / 3 } return colorTint } function modifyColorTint(colorTint) { let tint = colorTint; if (tint < 0) { tint += 1 } if (tint > 1) { tint -= 1 } return tint } function hueToRgb(p, q, colorTint) { const tint = modifyColorTint(colorTint); if (tint < 1 / 6) { return p + 6 * (q - p) * tint } if (tint < .5) { return q } if (tint < 2 / 3) { return p + (q - p) * (2 / 3 - tint) * 6 } return p } function convertTo01Bounds(n, max) { const bounded = Math.min(max, Math.max(0, n)); if (Math.abs(bounded - max) < 1e-6) { return 1 } return bounded % max / max } function hsvToRgb(h, s, v) { const index = Math.floor(h % 360 / 60); const vMin = (100 - s) * v / 100; const a = h % 60 / 60 * (v - vMin); const vInc = vMin + a; const vDec = v - a; let r = 0; let g = 0; let b = 0; switch (index) { case 0: r = v; g = vInc; b = vMin; break; case 1: r = vDec; g = v; b = vMin; break; case 2: r = vMin; g = v; b = vInc; break; case 3: r = vMin; g = vDec; b = v; break; case 4: r = vInc; g = vMin; b = v; break; case 5: r = v; g = vMin; b = vDec } return [Math.round(2.55 * r), Math.round(2.55 * g), Math.round(2.55 * b)] } function hslToRgb(h, s, l) { let r = 0; let g = 0; let b = 0; const h01 = convertTo01Bounds(h, 360); const s01 = convertTo01Bounds(s, 100); const l01 = convertTo01Bounds(l, 100); if (0 === s01) { r = l01; g = l01; b = l01 } else { const q = l01 < .5 ? l01 * (1 + s01) : l01 + s01 - l01 * s01; const p = 2 * l01 - q; r = hueToRgb(p, q, makeColorTint("r", h01)); g = hueToRgb(p, q, makeColorTint("g", h01)); b = hueToRgb(p, q, makeColorTint("b", h01)) } return [Math.round(255 * r), Math.round(255 * g), Math.round(255 * b)] } const standardColorTypes = [{ re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, process: colorString => [parseInt(colorString[1], 10), parseInt(colorString[2], 10), parseInt(colorString[3], 10)] }, { re: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d*\.*\d+)\)$/, process: colorString => [parseInt(colorString[1], 10), parseInt(colorString[2], 10), parseInt(colorString[3], 10), parseFloat(colorString[4])] }, { re: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/, process: colorString => [parseInt(colorString[1], 16), parseInt(colorString[2], 16), parseInt(colorString[3], 16)] }, { re: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/, process: colorString => [parseInt(colorString[1], 16), parseInt(colorString[2], 16), parseInt(colorString[3], 16), Number((parseInt(colorString[4], 16) / 255).toFixed(2))] }, { re: /^#([a-f0-9]{1})([a-f0-9]{1})([a-f0-9]{1})([a-f0-9]{1})$/, process: colorString => [parseInt(colorString[1] + colorString[1], 16), parseInt(colorString[2] + colorString[2], 16), parseInt(colorString[3] + colorString[3], 16), Number((parseInt(colorString[4] + colorString[4], 16) / 255).toFixed(2))] }, { re: /^#([a-f0-9]{1})([a-f0-9]{1})([a-f0-9]{1})$/, process: colorString => [parseInt(colorString[1] + colorString[1], 16), parseInt(colorString[2] + colorString[2], 16), parseInt(colorString[3] + colorString[3], 16)] }, { re: /^hsv\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, process(colorString) { const h = parseInt(colorString[1], 10); const s = parseInt(colorString[2], 10); const v = parseInt(colorString[3], 10); const rgb = hsvToRgb(h, s, v); return [rgb[0], rgb[1], rgb[2], 1, [h, s, v]] } }, { re: /^hsl\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, process(colorString) { const h = parseInt(colorString[1], 10); const s = parseInt(colorString[2], 10); const l = parseInt(colorString[3], 10); const rgb = hslToRgb(h, s, l); return [rgb[0], rgb[1], rgb[2], 1, null, [h, s, l]] } }]; function parseColor(color) { if ("transparent" === color) { return [0, 0, 0, 0] } for (const colorType of standardColorTypes) { const match = colorType.re.exec(color); if (match) { return colorType.process(match) } } return null } function normalize(colorComponent) { let def = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0; let max = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 255; if (void 0 === colorComponent || Number.isNaN(colorComponent) || colorComponent < 0) { return def } return colorComponent > max ? max : colorComponent } function toHexFromRgb(r, g, b) { return `#${(16777216|r<<16|g<<8|b).toString(16).slice(1)}` } function toHsvFromRgb(r, g, b) { const max = Math.max(r, g, b); const min = Math.min(r, g, b); const delta = max - min; let H = 0; let S = 0; let V = max; S = 0 === max ? 0 : 1 - min / max; if (max === min) { H = 0 } else { switch (max) { case r: H = (g - b) / delta * 60; if (g < b) { H += 360 } break; case g: H = (b - r) / delta * 60 + 120; break; case b: H = (r - g) / delta * 60 + 240 } } S *= 100; V *= 100 / 255; return { h: Math.round(H), s: Math.round(S), v: Math.round(V) } } function calculateHue(r, g, b, delta) { const max = Math.max(r, g, b); switch (max) { case r: return (g - b) / delta + (g < b ? 6 : 0); case g: return (b - r) / delta + 2; case b: return (r - g) / delta + 4; default: return 0 } } function toHslFromRgb(r, g, b) { const r01 = convertTo01Bounds(r, 255); const g01 = convertTo01Bounds(g, 255); const b01 = convertTo01Bounds(b, 255); const max = Math.max(r01, g01, b01); const min = Math.min(r01, g01, b01); const maxMinSum = max + min; let h = 0; let s = 0; const l = maxMinSum / 2; if (max === min) { h = 0; s = 0 } else { const delta = max - min; if (l > .5) { s = delta / (2 - maxMinSum) } else { s = delta / maxMinSum } h = calculateHue(r01, g01, b01, delta); h /= 6 } return { h: Math.round(360 * h), s: Math.round(100 * s), l: Math.round(100 * l) } } function isIntegerBetweenMinAndMax(value) { let min = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0; let max = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : 255; if ("number" !== typeof value || value % 1 !== 0 || value < min || value > max || isNaN(value)) { return false } return true }