ngx-input-color
Version:
Angular color input component and color picker (with HSL, HSV, RGB, CMYK, HEX, alpha, eye-dropper, etc)
1 lines • 243 kB
Source Map (JSON)
{"version":3,"file":"ngx-input-color.mjs","sources":["../../../projects/ngx-input-color/src/models/ColorFormats.enum.ts","../../../projects/ngx-input-color/src/utils/conversion.ts","../../../projects/ngx-input-color/src/utils/css-color-names.ts","../../../projects/ngx-input-color/src/utils/color-helper.ts","../../../projects/ngx-input-color/src/models/ColorInspector.enum.ts","../../../projects/ngx-input-color/src/utils/get-offset-position.ts","../../../projects/ngx-input-color/src/slider/slider.component.ts","../../../projects/ngx-input-color/src/slider/slider.component.html","../../../projects/ngx-input-color/src/saturation/saturation.component.ts","../../../projects/ngx-input-color/src/saturation/saturation.component.html","../../../projects/ngx-input-color/src/lib/inspectors/picker/picker.component.ts","../../../projects/ngx-input-color/src/lib/inspectors/picker/picker.component.html","../../../projects/ngx-input-color/src/lib/inspectors/cmyk/cmyk.component.ts","../../../projects/ngx-input-color/src/lib/inspectors/cmyk/cmyk.component.html","../../../projects/ngx-input-color/src/lib/inspectors/hsl/hsl.component.ts","../../../projects/ngx-input-color/src/lib/inspectors/hsl/hsl.component.html","../../../projects/ngx-input-color/src/lib/inspectors/rgb/rgb.component.ts","../../../projects/ngx-input-color/src/lib/inspectors/rgb/rgb.component.html","../../../projects/ngx-input-color/src/pipes/enum-to-array.pipe.ts","../../../projects/ngx-input-color/src/lib/ngx-input-color/ngx-input-color.component.ts","../../../projects/ngx-input-color/src/lib/ngx-input-color/ngx-input-color.component.html","../../../projects/ngx-input-color/src/range-slider/range-slider.component.ts","../../../projects/ngx-input-color/src/range-slider/range-slider.component.html","../../../projects/ngx-input-color/src/directives/ngx-input-color.directive.ts","../../../projects/ngx-input-color/src/ngx-input-color.module.ts","../../../projects/ngx-input-color/src/utils/build-gradient.ts","../../../projects/ngx-input-color/src/lib/ngx-input-gradient/default-gradients.ts","../../../projects/ngx-input-color/src/lib/ngx-input-gradient/ngx-input-gradient.component.ts","../../../projects/ngx-input-color/src/lib/ngx-input-gradient/ngx-input-gradient.component.html","../../../projects/ngx-input-color/src/utils/box-shadow.ts","../../../projects/ngx-input-color/src/lib/ngx-box-shadow/ngx-box-shadow.component.ts","../../../projects/ngx-input-color/src/lib/ngx-box-shadow/ngx-box-shadow.component.html","../../../projects/ngx-input-color/src/ngx-input-gradient.module.ts","../../../projects/ngx-input-color/src/ngx-input-box-shadow.module.ts","../../../projects/ngx-input-color/src/directives/ngx-input-gradient.directive.ts","../../../projects/ngx-input-color/src/directives/ngx-input-box-shadow.directive.ts","../../../projects/ngx-input-color/src/public-api.ts","../../../projects/ngx-input-color/src/ngx-input-color.ts"],"sourcesContent":["export enum ColorFormats {\r\n HEX,\r\n RGBA,\r\n HSLA,\r\n HSVA,\r\n CMYK,\r\n}\r\n\r\n","import { CMYK, HSL, HSLA, HSV, HSVA, RGB, RGBA } from './interfaces';\r\n\r\nexport function hexToRgb(hex: string): RGBA {\r\n let h = hex.replace(/^#/, '');\r\n if (h.length === 3)\r\n h = h\r\n .split('')\r\n .map((x) => x + x)\r\n .join('');\r\n if (h.length === 6) h += 'ff';\r\n if (h.length === 8) {\r\n const r = parseInt(h.slice(0, 2), 16);\r\n const g = parseInt(h.slice(2, 4), 16);\r\n const b = parseInt(h.slice(4, 6), 16);\r\n const a = parseInt(h.slice(6, 8), 16) / 255;\r\n return { r, g, b, a: a };\r\n }\r\n throw new Error('Invalid hex color');\r\n}\r\nexport function parseRgbString(str: string): RGBA {\r\n const m = str.match(/rgba?\\(([^)]+)\\)/);\r\n if (!m) throw new Error('Invalid rgb string');\r\n const parts = m[1].split(',').map((x) => +x.trim());\r\n return {\r\n r: parts[0],\r\n g: parts[1],\r\n b: parts[2],\r\n a: parts[3] !== undefined ? parts[3] : 1,\r\n };\r\n}\r\nfunction clamp(value: number, min: number, max: number): number {\r\n return Math.max(min, Math.min(max, value));\r\n}\r\n\r\nexport function parseHslString(str: string): HSLA {\r\n const m = str.match(/hsla?\\(([^)]+)\\)/i);\r\n if (!m) throw new Error('Invalid hsl/hsla string');\r\n\r\n const parts = m[1].split(',').map((x) => x.trim());\r\n\r\n const h = clamp(parseFloat(parts[0]), 0, 360);\r\n const s = clamp(parseFloat(parts[1]), 0, 100);\r\n const l = clamp(parseFloat(parts[2]), 0, 100);\r\n const a = parts[3] !== undefined ? clamp(parseFloat(parts[3]), 0, 1) : 1;\r\n\r\n return { h, s, l, a };\r\n}\r\nexport function parseHsvString(str: string): HSVA {\r\n const m = str.match(/hsva?\\(([^)]+)\\)/i);\r\n if (!m) throw new Error('Invalid hsv(a) string');\r\n\r\n const parts = m[1].split(',').map((x) => x.trim());\r\n\r\n const h = clamp(parseFloat(parts[0]), 0, 360);\r\n const s = clamp(parseFloat(parts[1]), 0, 100);\r\n const v = clamp(parseFloat(parts[2]), 0, 100);\r\n const a = parts[3] !== undefined ? clamp(parseFloat(parts[3]), 0, 1) : 1;\r\n\r\n return { h, s, v, a };\r\n}\r\n\r\nexport function parseCmykString(str: string): CMYK {\r\n const m = str.match(/cmyk\\(([^)]+)\\)/i);\r\n if (!m) throw new Error('Invalid cmyk string');\r\n\r\n const parts = m[1].split(',').map((x) => x.trim());\r\n\r\n return {\r\n c: clamp(parseFloat(parts[0]), 0, 100),\r\n m: clamp(parseFloat(parts[1]), 0, 100),\r\n y: clamp(parseFloat(parts[2]), 0, 100),\r\n k: clamp(parseFloat(parts[3]), 0, 100),\r\n };\r\n}\r\n\r\n/**\r\n * Take input from [0, n] and return it as [0, 1]\r\n * @hidden\r\n */\r\nexport function bound01(n: any, max: number): number {\r\n if (isOnePointZero(n)) {\r\n n = '100%';\r\n }\r\n\r\n const isPercent = isPercentage(n);\r\n n = max === 360 ? n : Math.min(max, Math.max(0, parseFloat(n)));\r\n\r\n // Automatically convert percentage into number\r\n if (isPercent) {\r\n n = parseInt(String(n * max), 10) / 100;\r\n }\r\n\r\n // Handle floating point rounding errors\r\n if (Math.abs(n - max) < 0.000001) {\r\n return 1;\r\n }\r\n\r\n // Convert into [0, 1] range if it isn't already\r\n if (max === 360) {\r\n // If n is a hue given in degrees,\r\n // wrap around out-of-range values into [0, 360] range\r\n // then convert into [0, 1].\r\n n = (n < 0 ? (n % max) + max : n % max) / parseFloat(String(max));\r\n } else {\r\n // If n not a hue given in degrees\r\n // Convert into [0, 1] range if it isn't already.\r\n n = (n % max) / parseFloat(String(max));\r\n }\r\n\r\n return n;\r\n}\r\n/**\r\n * Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1\r\n * <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>\r\n * @hidden\r\n */\r\nexport function isOnePointZero(n: string | number): boolean {\r\n return typeof n === 'string' && n.indexOf('.') !== -1 && parseFloat(n) === 1;\r\n}\r\n\r\n/**\r\n * Check to see if string passed in is a percentage\r\n * @hidden\r\n */\r\nexport function isPercentage(n: string | number): boolean {\r\n return typeof n === 'string' && n.indexOf('%') !== -1;\r\n}\r\n/**\r\n * convert all properties in an interface to a number\r\n */\r\nexport type Numberify<T> = {\r\n [P in keyof T]: number;\r\n};\r\n\r\n/**\r\n * Replace a decimal with it's percentage value\r\n * @hidden\r\n */\r\nexport function convertToPercentage(n: number | string): number | string {\r\n if (Number(n) <= 1) {\r\n return `${Number(n) * 100}%`;\r\n }\r\n\r\n return n;\r\n}\r\n\r\n/**\r\n * Force a hex value to have 2 characters\r\n * @hidden\r\n */\r\nexport function pad2(c: string): string {\r\n return c.length === 1 ? '0' + c : String(c);\r\n}\r\n\r\n// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:\r\n// <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>\r\n\r\n/**\r\n * Handle bounds / percentage checking to conform to CSS color spec\r\n * <http://www.w3.org/TR/css3-color/>\r\n * *Assumes:* r, g, b in [0, 255] or [0, 1]\r\n * *Returns:* { r, g, b } in [0, 255]\r\n */\r\nexport function rgbToRgb(r: number | string, g: number | string, b: number | string): Numberify<RGB> {\r\n return {\r\n r: bound01(r, 255) * 255,\r\n g: bound01(g, 255) * 255,\r\n b: bound01(b, 255) * 255,\r\n };\r\n}\r\n\r\n/**\r\n * Converts an RGB color value to HSL.\r\n * *Assumes:* r, g, and b are contained in [0, 255]\r\n * *Returns:* { h: 0-360, s: 0-100, l: 0-100 }\r\n */\r\nexport function rgbToHsl(r: number, g: number, b: number): Numberify<HSL> {\r\n r = r / 255;\r\n g = g / 255;\r\n b = b / 255;\r\n const max = Math.max(r, g, b);\r\n const min = Math.min(r, g, b);\r\n let h = 0;\r\n let s = 0;\r\n const l = (max + min) / 2;\r\n if (max === min) {\r\n s = 0;\r\n h = 0;\r\n } else {\r\n const d = max - min;\r\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\r\n switch (max) {\r\n case r:\r\n h = (g - b) / d + (g < b ? 6 : 0);\r\n break;\r\n case g:\r\n h = (b - r) / d + 2;\r\n break;\r\n case b:\r\n h = (r - g) / d + 4;\r\n break;\r\n }\r\n h /= 6;\r\n }\r\n h = (h * 360) % 360;\r\n if (h < 0) h += 360;\r\n return {\r\n h: max === min ? 0 : h,\r\n s: l === 0 || l === 1 ? 0 : s * 100,\r\n l: l * 100,\r\n };\r\n}\r\n\r\n/**\r\n * Converts an HSL color value to RGB.\r\n * *Assumes:* h in [0, 360], s and l in [0, 100]\r\n * *Returns:* { r, g, b } in [0, 255]\r\n */\r\nexport function hslToRgba(h: number | string, s: number | string, l: number | string, a: number = 1): RGBA {\r\n h = +h;\r\n s = +s;\r\n l = +l;\r\n h = ((h % 360) + 360) % 360;\r\n s = Math.max(0, Math.min(100, s));\r\n l = Math.max(0, Math.min(100, l));\r\n h = h / 360;\r\n s = s / 100;\r\n l = l / 100;\r\n\r\n let r: number, g: number, b: number;\r\n\r\n if (s === 0) {\r\n r = g = b = l; // achromatic\r\n } else {\r\n const hue2rgb = (p: number, q: number, t: number): number => {\r\n if (t < 0) t += 1;\r\n if (t > 1) t -= 1;\r\n if (t < 1 / 6) return p + (q - p) * 6 * t;\r\n if (t < 1 / 2) return q;\r\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\r\n return p;\r\n };\r\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\r\n const p = 2 * l - q;\r\n r = hue2rgb(p, q, h + 1 / 3);\r\n g = hue2rgb(p, q, h);\r\n b = hue2rgb(p, q, h - 1 / 3);\r\n }\r\n\r\n return {\r\n r: Math.round(r * 255),\r\n g: Math.round(g * 255),\r\n b: Math.round(b * 255),\r\n a: Math.max(0, Math.min(1, a)),\r\n };\r\n}\r\n\r\n/**\r\n * Converts an RGB color value to HSV\r\n * *Assumes:* r, g, and b are contained in [0, 255]\r\n * *Returns:* { h: 0-360, s: 0-100, v: 0-100 }\r\n */\r\nexport function rgbToHsv(r: number, g: number, b: number): Numberify<HSV> {\r\n r = r / 255;\r\n g = g / 255;\r\n b = b / 255;\r\n const max = Math.max(r, g, b);\r\n const min = Math.min(r, g, b);\r\n let h = 0;\r\n let s = 0;\r\n const v = max;\r\n const d = max - min;\r\n s = max === 0 ? 0 : d / max;\r\n if (max === min) {\r\n h = 0;\r\n } else {\r\n switch (max) {\r\n case r:\r\n h = (g - b) / d + (g < b ? 6 : 0);\r\n break;\r\n case g:\r\n h = (b - r) / d + 2;\r\n break;\r\n case b:\r\n h = (r - g) / d + 4;\r\n break;\r\n }\r\n h /= 6;\r\n }\r\n h = (h * 360) % 360;\r\n if (h < 0) h += 360;\r\n return {\r\n h: max === min ? 0 : h,\r\n s: max === 0 ? 0 : s * 100,\r\n v: v * 100,\r\n };\r\n}\r\n\r\n/**\r\n * Converts an HSV color value to RGB.\r\n * *Assumes:* h in [0, 360], s and v in [0, 100]\r\n * *Returns:* { r, g, b } in [0, 255]\r\n */\r\nexport function hsvToRgb(h: number | string, s: number | string, v: number | string): Numberify<RGB> {\r\n h = +h;\r\n s = +s;\r\n v = +v;\r\n h = ((h % 360) + 360) % 360;\r\n s = Math.max(0, Math.min(100, s));\r\n v = Math.max(0, Math.min(100, v));\r\n s = s / 100;\r\n v = v / 100;\r\n let r = 0,\r\n g = 0,\r\n b = 0;\r\n const hi = Math.floor(h / 60) % 6;\r\n const f = h / 60 - Math.floor(h / 60);\r\n const p = v * (1 - s);\r\n const q = v * (1 - f * s);\r\n const t = v * (1 - (1 - f) * s);\r\n switch (hi) {\r\n case 0:\r\n r = v;\r\n g = t;\r\n b = p;\r\n break;\r\n case 1:\r\n r = q;\r\n g = v;\r\n b = p;\r\n break;\r\n case 2:\r\n r = p;\r\n g = v;\r\n b = t;\r\n break;\r\n case 3:\r\n r = p;\r\n g = q;\r\n b = v;\r\n break;\r\n case 4:\r\n r = t;\r\n g = p;\r\n b = v;\r\n break;\r\n case 5:\r\n r = v;\r\n g = p;\r\n b = q;\r\n break;\r\n }\r\n return {\r\n r: Math.max(0, Math.min(255, Math.round(r * 255))),\r\n g: Math.max(0, Math.min(255, Math.round(g * 255))),\r\n b: Math.max(0, Math.min(255, Math.round(b * 255))),\r\n };\r\n}\r\n\r\n/**\r\n * Converts an RGB/RGBA color to hex\r\n */\r\nexport function rgbaToHex(\r\n r: number,\r\n g: number,\r\n b: number,\r\n a: number = 1,\r\n allowAlpha: boolean = true,\r\n allow3Char: boolean = false\r\n): string {\r\n const toHex = (n: number) => n.toString(16).padStart(2, '0');\r\n\r\n const rHex = toHex(Math.round(r));\r\n const gHex = toHex(Math.round(g));\r\n const bHex = toHex(Math.round(b));\r\n const aHex = toHex(Math.round(a * 255));\r\n\r\n // Try compressing to #rgb or #rgba if allowed and all characters are duplicated\r\n if (allow3Char && (!allowAlpha || aHex === 'ff')) {\r\n const canShorten =\r\n rHex[0] === rHex[1] && gHex[0] === gHex[1] && bHex[0] === bHex[1] && (!allowAlpha || aHex[0] === aHex[1]);\r\n\r\n if (canShorten) {\r\n return '#' + rHex[0] + gHex[0] + bHex[0] + (allowAlpha && aHex !== 'ff' ? aHex[0] : '');\r\n }\r\n }\r\n\r\n return '#' + rHex + gHex + bHex + (allowAlpha && aHex !== 'ff' ? aHex : '');\r\n}\r\n\r\n/**\r\n * Converts an RGBA color to an ARGB Hex8 string\r\n * Rarely used, but required for \"toFilter()\"\r\n *\r\n * *Assumes:* r, g, b are contained in the set [0, 255] and a in [0, 1]\r\n * *Returns:* a 8 character argb hex\r\n */\r\nexport function rgbaToArgbHex(r: number, g: number, b: number, a: number): string {\r\n const hex = [\r\n pad2(convertDecimalToHex(a)),\r\n pad2(Math.round(r).toString(16)),\r\n pad2(Math.round(g).toString(16)),\r\n pad2(Math.round(b).toString(16)),\r\n ];\r\n\r\n return hex.join('');\r\n}\r\n\r\n/**\r\n * Converts CMYK to RBG\r\n * Assumes c, m, y, k are in the set [0, 100]\r\n */\r\nexport function cmykToRgb(c: number, m: number, y: number, k: number) {\r\n const cConv = c / 100;\r\n const mConv = m / 100;\r\n const yConv = y / 100;\r\n const kConv = k / 100;\r\n\r\n const r = 255 * (1 - cConv) * (1 - kConv);\r\n const g = 255 * (1 - mConv) * (1 - kConv);\r\n const b = 255 * (1 - yConv) * (1 - kConv);\r\n\r\n return { r, g, b };\r\n}\r\n\r\nexport function rgbToCmyk(r: number, g: number, b: number) {\r\n let c = 1 - r / 255;\r\n let m = 1 - g / 255;\r\n let y = 1 - b / 255;\r\n let k = Math.min(c, m, y);\r\n\r\n if (k === 1) {\r\n c = 0;\r\n m = 0;\r\n y = 0;\r\n } else {\r\n c = ((c - k) / (1 - k)) * 100;\r\n m = ((m - k) / (1 - k)) * 100;\r\n y = ((y - k) / (1 - k)) * 100;\r\n }\r\n\r\n k *= 100;\r\n\r\n return {\r\n c: Math.round(c),\r\n m: Math.round(m),\r\n y: Math.round(y),\r\n k: Math.round(k),\r\n };\r\n}\r\n\r\n/** Converts a decimal to a hex value */\r\nexport function convertDecimalToHex(d: string | number): string {\r\n return Math.round(parseFloat(d as string) * 255).toString(16);\r\n}\r\n\r\n/** Converts a hex value to a decimal */\r\nexport function convertHexToDecimal(h: string): number {\r\n return parseIntFromHex(h) / 255;\r\n}\r\n\r\n/** Parse a base-16 hex value into a base-10 integer */\r\nexport function parseIntFromHex(val: string): number {\r\n return parseInt(val, 16);\r\n}\r\n\r\nexport function numberInputToObject(color: number): RGB {\r\n return {\r\n r: color >> 16,\r\n g: (color & 0xff00) >> 8,\r\n b: color & 0xff,\r\n };\r\n}\r\n\r\nexport function rgbToHslaString(r: number, g: number, b: number, a = 1): string {\r\n const { h, s, l } = rgbToHsl(r, g, b);\r\n return `hsla(${Math.round(h)}, ${Math.round(s)}%, ${Math.round(l)}%, ${+a.toFixed(2)})`;\r\n}\r\nexport function rgbToHsvString(r: number, g: number, b: number, a = 1): string {\r\n const { h, s, v } = rgbToHsv(r, g, b);\r\n return `hsva(${Math.round(h)}, ${Math.round(s)}%, ${Math.round(v)}%, ${+a.toFixed(2)})`;\r\n}\r\nexport function rgbToCmykString(r: number, g: number, b: number): string {\r\n const { c, m, y, k } = rgbToCmyk(r, g, b);\r\n return `cmyk(${Math.round(c)}%, ${Math.round(m)}%, ${Math.round(y)}%, ${Math.round(k)}%)`;\r\n}\r\n","// List of all CSS color names and their hex values (W3C + extended)\r\nexport const colorNames: Record<string, string> = {\r\n aliceblue: '#f0f8ff', antiquewhite: '#faebd7', aqua: '#00ffff', aquamarine: '#7fffd4', azure: '#f0ffff',\r\n beige: '#f5f5dc', bisque: '#ffe4c4', black: '#000000', blanchedalmond: '#ffebcd', blue: '#0000ff',\r\n blueviolet: '#8a2be2', brown: '#a52a2a', burlywood: '#deb887', cadetblue: '#5f9ea0', chartreuse: '#7fff00',\r\n chocolate: '#d2691e', coral: '#ff7f50', cornflowerblue: '#6495ed', cornsilk: '#fff8dc', crimson: '#dc143c',\r\n cyan: '#00ffff', darkblue: '#00008b', darkcyan: '#008b8b', darkgoldenrod: '#b8860b', darkgray: '#a9a9a9',\r\n darkgreen: '#006400', darkgrey: '#a9a9a9', darkkhaki: '#bdb76b', darkmagenta: '#8b008b', darkolivegreen: '#556b2f',\r\n darkorange: '#ff8c00', darkorchid: '#9932cc', darkred: '#8b0000', darksalmon: '#e9967a', darkseagreen: '#8fbc8f',\r\n darkslateblue: '#483d8b', darkslategray: '#2f4f4f', darkslategrey: '#2f4f4f', darkturquoise: '#00ced1',\r\n darkviolet: '#9400d3', deeppink: '#ff1493', deepskyblue: '#00bfff', dimgray: '#696969', dimgrey: '#696969',\r\n dodgerblue: '#1e90ff', firebrick: '#b22222', floralwhite: '#fffaf0', forestgreen: '#228b22', fuchsia: '#ff00ff',\r\n gainsboro: '#dcdcdc', ghostwhite: '#f8f8ff', gold: '#ffd700', goldenrod: '#daa520', gray: '#808080',\r\n green: '#008000', greenyellow: '#adff2f', grey: '#808080', honeydew: '#f0fff0', hotpink: '#ff69b4',\r\n indianred: '#cd5c5c', indigo: '#4b0082', ivory: '#fffff0', khaki: '#f0e68c', lavender: '#e6e6fa',\r\n lavenderblush: '#fff0f5', lawngreen: '#7cfc00', lemonchiffon: '#fffacd', lightblue: '#add8e6', lightcoral: '#f08080',\r\n lightcyan: '#e0ffff', lightgoldenrodyellow: '#fafad2', lightgray: '#d3d3d3', lightgreen: '#90ee90', lightgrey: '#d3d3d3',\r\n lightpink: '#ffb6c1', lightsalmon: '#ffa07a', lightseagreen: '#20b2aa', lightskyblue: '#87cefa', lightslategray: '#778899',\r\n lightslategrey: '#778899', lightsteelblue: '#b0c4de', lightyellow: '#ffffe0', lime: '#00ff00', limegreen: '#32cd32',\r\n linen: '#faf0e6', magenta: '#ff00ff', maroon: '#800000', mediumaquamarine: '#66cdaa', mediumblue: '#0000cd',\r\n mediumorchid: '#ba55d3', mediumpurple: '#9370db', mediumseagreen: '#3cb371', mediumslateblue: '#7b68ee',\r\n mediumspringgreen: '#00fa9a', mediumturquoise: '#48d1cc', mediumvioletred: '#c71585', midnightblue: '#191970',\r\n mintcream: '#f5fffa', mistyrose: '#ffe4e1', moccasin: '#ffe4b5', navajowhite: '#ffdead', navy: '#000080',\r\n oldlace: '#fdf5e6', olive: '#808000', olivedrab: '#6b8e23', orange: '#ffa500', orangered: '#ff4500',\r\n orchid: '#da70d6', palegoldenrod: '#eee8aa', palegreen: '#98fb98', paleturquoise: '#afeeee', palevioletred: '#db7093',\r\n papayawhip: '#ffefd5', peachpuff: '#ffdab9', peru: '#cd853f', pink: '#ffc0cb', plum: '#dda0dd', powderblue: '#b0e0e6',\r\n purple: '#800080', rebeccapurple: '#663399', red: '#ff0000', rosybrown: '#bc8f8f', royalblue: '#4169e1',\r\n saddlebrown: '#8b4513', salmon: '#fa8072', sandybrown: '#f4a460', seagreen: '#2e8b57', seashell: '#fff5ee',\r\n sienna: '#a0522d', silver: '#c0c0c0', skyblue: '#87ceeb', slateblue: '#6a5acd', slategray: '#708090',\r\n slategrey: '#708090', snow: '#fffafa', springgreen: '#00ff7f', steelblue: '#4682b4', tan: '#d2b48c',\r\n teal: '#008080', thistle: '#d8bfd8', tomato: '#ff6347', turquoise: '#40e0d0', violet: '#ee82ee', wheat: '#f5deb3',\r\n white: '#ffffff', whitesmoke: '#f5f5f5', yellow: '#ffff00', yellowgreen: '#9acd32'\r\n};\r\n","import {\r\n cmykToRgb,\r\n hexToRgb,\r\n hslToRgba,\r\n hsvToRgb,\r\n parseCmykString,\r\n parseHslString,\r\n parseHsvString,\r\n parseRgbString,\r\n rgbaToHex,\r\n rgbToCmyk,\r\n rgbToCmykString,\r\n rgbToHsl,\r\n rgbToHslaString,\r\n rgbToHsv,\r\n rgbToHsvString,\r\n} from './conversion';\r\nimport { colorNames } from './css-color-names';\r\nimport { CMYK, HSL, HSLA, HSV, HSVA, RGB, RGBA } from './interfaces';\r\nexport type ColorInput = string | CMYK | HSLA | HSVA | RGBA | NgxColor;\r\nexport type OutputType = 'CMYK' | 'HSL' | 'HSV' | 'RGB' | 'HEX';\r\n\r\nexport class NgxColor {\r\n private _rgb: RGBA = { r: 0, g: 0, b: 0, a: 1 };\r\n private _name: string = '';\r\n\r\n constructor(input?: ColorInput) {\r\n if (!input) return;\r\n if (input instanceof NgxColor) {\r\n this._rgb = { ...input._rgb };\r\n this._name = input._name;\r\n return;\r\n }\r\n if (typeof input === 'object') {\r\n if ('r' in input && 'g' in input && 'b' in input) {\r\n this._rgb = { r: +input.r, g: +input.g, b: +input.b, a: (input as any).a !== undefined ? +input.a : 1 };\r\n return;\r\n }\r\n if ('h' in input && 's' in input && 'l' in input) {\r\n this._rgb = NgxColor.hslaToRgba(input as HSLA);\r\n return;\r\n }\r\n if ('h' in input && 's' in input && 'v' in input) {\r\n this._rgb = NgxColor.hsvaToRgba(input as HSVA);\r\n return;\r\n }\r\n if ('c' in input && 'm' in input && 'y' in input && 'k' in input) {\r\n this._rgb = NgxColor.cmykToRgba(input as CMYK);\r\n return;\r\n }\r\n }\r\n if (typeof input === 'string') {\r\n const name = input.trim().toLowerCase();\r\n if (colorNames[name]) {\r\n this._rgb = hexToRgb(colorNames[name]);\r\n this._name = name;\r\n return;\r\n } else if (/^#?[0-9a-f]{3,8}$/i.test(name)) {\r\n this._rgb = hexToRgb(name);\r\n return;\r\n }\r\n if (name.includes('rgb')) {\r\n this._rgb = parseRgbString(name);\r\n return;\r\n }\r\n if (name.includes('hsl')) {\r\n this._rgb = NgxColor.hslaToRgba(parseHslString(name));\r\n return;\r\n }\r\n if (name.includes('hsv')) {\r\n this._rgb = NgxColor.hsvaToRgba(parseHsvString(name));\r\n return;\r\n }\r\n if (name.includes('cmyk')) {\r\n this._rgb = NgxColor.cmykToRgba(parseCmykString(name));\r\n return;\r\n }\r\n throw new Error('Unknown color string: ' + input);\r\n }\r\n }\r\n\r\n get isValid(): boolean {\r\n return (\r\n typeof this._rgb.r === 'number' &&\r\n typeof this._rgb.g === 'number' &&\r\n typeof this._rgb.b === 'number' &&\r\n !isNaN(this._rgb.r) &&\r\n !isNaN(this._rgb.g) &&\r\n !isNaN(this._rgb.b)\r\n );\r\n }\r\n\r\n async name() {\r\n if (this._name) return this._name;\r\n const hex = this.toHexString();\r\n for (const [n, h] of Object.entries(colorNames)) {\r\n if (h.toLowerCase() === hex.toLowerCase()) return n;\r\n }\r\n return '';\r\n }\r\n\r\n toRgb(): RGBA {\r\n return this._rgb;\r\n }\r\n\r\n toRgbString(): string {\r\n const { r, g, b, a } = this.toRgb();\r\n return a === 1\r\n ? `rgb(${Math.round(r)},${Math.round(g)},${Math.round(b)})`\r\n : `rgba(${Math.round(r)},${Math.round(g)},${Math.round(b)},${+a.toFixed(3)})`;\r\n }\r\n\r\n toHexString(allowAlpha = true): string {\r\n const { r, g, b, a } = this.toRgb();\r\n return rgbaToHex(r, g, b, a, allowAlpha && a < 1);\r\n }\r\n\r\n toHsl(): HSLA {\r\n return NgxColor.rgbToHsla(this.toRgb());\r\n }\r\n\r\n toHsv(): HSVA {\r\n return NgxColor.rgbToHsva(this.toRgb());\r\n }\r\n\r\n toCmyk(): CMYK {\r\n return NgxColor.rgbToCmyk(this.toRgb());\r\n }\r\n\r\n static cmykToRgba(cmyk: CMYK): RGBA {\r\n const { c, m, y, k } = cmyk;\r\n return { ...cmykToRgb(c, m, y, k), a: (cmyk as any).a !== undefined ? +(cmyk as any).a : 1 };\r\n }\r\n\r\n static rgbToCmyk(rgba: RGBA): CMYK {\r\n const { r, g, b } = rgba;\r\n return rgbToCmyk(r, g, b);\r\n }\r\n\r\n static rgbToHsla(rgba: RGBA): HSLA {\r\n const { r, g, b, a } = rgba;\r\n return { ...rgbToHsl(r, g, b), a };\r\n }\r\n\r\n static rgbToHsva(rgba: RGBA): HSVA {\r\n const { r, g, b, a } = rgba;\r\n return { ...rgbToHsv(r, g, b), a };\r\n }\r\n\r\n static hsvaToRgba(hsva: HSVA): RGBA {\r\n const { h, s, v, a } = hsva;\r\n return { ...hsvToRgb(h, s, v), a: a !== undefined ? a : 1 };\r\n }\r\n\r\n static hslaToRgba(hsla: HSLA): RGBA {\r\n const { h, s, l, a } = hsla;\r\n return { ...hslToRgba(h, s, l), a: a !== undefined ? a : 1 };\r\n }\r\n\r\n equals(other?: NgxColor): boolean {\r\n if (!other) return false;\r\n return this.toHexString().toLowerCase() === other.toHexString().toLowerCase();\r\n }\r\n\r\n isDark(): boolean {\r\n const { r, g, b, a } = this.toRgb();\r\n return a < 0.5 ? false : 0.299 * r + 0.587 * g + 0.114 * b < 128;\r\n }\r\n\r\n isLight(): boolean {\r\n return !this.isDark();\r\n }\r\n\r\n async getOutputResult(outputType: OutputType): Promise<string> {\r\n const { r, g, b, a } = this._rgb;\r\n\r\n switch (outputType) {\r\n case 'CMYK':\r\n return rgbToCmykString(r, g, b);\r\n\r\n case 'HSL':\r\n return rgbToHslaString(r, g, b, a);\r\n\r\n case 'HSV':\r\n return rgbToHsvString(r, g, b, a);\r\n\r\n case 'RGB':\r\n return a < 1 ? `rgba(${r}, ${g}, ${b}, ${+a.toFixed(2)})` : `rgb(${r}, ${g}, ${b})`;\r\n\r\n case 'HEX':\r\n return this.toHexString(true);\r\n\r\n default:\r\n let name = await this.name();\r\n return name ?? this.toHexString(true);\r\n }\r\n }\r\n}\r\n","export enum ColorInspector {\r\n Picker,\r\n RGB,\r\n HSL,\r\n CMYK,\r\n}\r\n","export function getOffsetPosition(\r\n evt: MouseEvent | TouchEvent,\r\n parent: HTMLElement\r\n) {\r\n let position = {\r\n x: 0,\r\n y: 0,\r\n };\r\n\r\n if (evt instanceof MouseEvent) {\r\n position.x = evt.pageX;\r\n position.y = evt.pageY;\r\n } else if (evt.touches && evt.touches.length > 0) {\r\n position.x = evt.touches[0].pageX;\r\n position.y = evt.touches[0].pageY;\r\n }\r\n\r\n // Adjust for the parent's offset\r\n let parentRect = parent.getBoundingClientRect();\r\n position.x -= parentRect.left + window.scrollX;\r\n position.y -= parentRect.top + window.scrollY;\r\n\r\n return position;\r\n}\r\n","import { CommonModule } from '@angular/common';\r\nimport {\r\n ChangeDetectionStrategy,\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n HostListener,\r\n Input,\r\n Output,\r\n ViewChild,\r\n forwardRef,\r\n type OnInit,\r\n} from '@angular/core';\r\nimport { getOffsetPosition } from '../utils/get-offset-position';\r\nimport {\r\n AbstractControl,\r\n ControlValueAccessor,\r\n FormControl,\r\n NG_VALIDATORS,\r\n NG_VALUE_ACCESSOR,\r\n ValidationErrors,\r\n Validator,\r\n Validators,\r\n} from '@angular/forms';\r\n\r\n@Component({\r\n selector: 'slider',\r\n standalone: true,\r\n imports: [CommonModule],\r\n templateUrl: './slider.component.html',\r\n styleUrls: ['./slider.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => SliderComponent),\r\n multi: true,\r\n },\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => SliderComponent),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class SliderComponent implements OnInit, ControlValueAccessor, Validator {\r\n @Input() step = 1;\r\n @Input() min = 0;\r\n @Input() max = 100;\r\n @Input() background?: string;\r\n @Input() isBgTransparent = false;\r\n @Output() change = new EventEmitter<number>();\r\n isDragging = false;\r\n @ViewChild('slider', { static: true }) slider!: ElementRef<HTMLDivElement>;\r\n @ViewChild('thumb', { static: true }) thumb!: ElementRef<HTMLDivElement>;\r\n x = 0;\r\n myControl = new FormControl<number | null>(null);\r\n isDisabled = false;\r\n _onChange = (value: any) => {};\r\n _onTouched = () => {};\r\n _validatorOnChange = () => {};\r\n private sliderRect?: DOMRect;\r\n private thumbRect?: DOMRect;\r\n constructor() {}\r\n ngOnInit(): void {\r\n this.myControl.setValidators([Validators.min(this.min), Validators.max(this.max)]);\r\n }\r\n\r\n private updateRects() {\r\n this.sliderRect = this.slider.nativeElement.getBoundingClientRect();\r\n this.thumbRect = this.thumb.nativeElement.getBoundingClientRect();\r\n }\r\n\r\n writeValue(val?: number | string | null): void {\r\n let value = 0;\r\n if (!val) value = 0;\r\n else if (+val < +this.min) value = +this.min;\r\n else if (+val > +this.max) value = +this.max;\r\n else value = +val;\r\n this.myControl.setValue(value, { emitEvent: false });\r\n this.updateRects();\r\n const sliderRec = this.sliderRect!;\r\n const thumbRec = this.thumbRect!;\r\n this.x = ((value - this.min) * (sliderRec.width - thumbRec.width)) / (this.max - this.min);\r\n if (val !== value) {\r\n this.valueChanged(value);\r\n }\r\n }\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n return this.myControl.errors;\r\n }\r\n registerOnValidatorChange?(fn: () => void): void {\r\n this._validatorOnChange = fn;\r\n }\r\n\r\n registerOnChange(fn: any): void {\r\n this._onChange = fn;\r\n }\r\n registerOnTouched(fn: any): void {\r\n this._onTouched = fn;\r\n }\r\n setDisabledState?(disabled: boolean): void {\r\n this.isDisabled = disabled;\r\n if (disabled) this.myControl.disable();\r\n else this.myControl.enable();\r\n }\r\n\r\n dragStart(ev: MouseEvent | TouchEvent) {\r\n ev.stopPropagation();\r\n ev.preventDefault();\r\n this.isDragging = true;\r\n this.updateRects();\r\n this.updatePosition(ev);\r\n }\r\n\r\n @HostListener('document:mousemove', ['$event'])\r\n @HostListener('document:touchmove', ['$event'])\r\n onDrag(ev: MouseEvent | TouchEvent) {\r\n if (!this.isDragging) return;\r\n this.updatePosition(ev);\r\n }\r\n\r\n @HostListener('window:resize', ['$event'])\r\n onResize() {\r\n this.writeValue(this.myControl.value);\r\n }\r\n\r\n private updatePosition(ev: MouseEvent | TouchEvent) {\r\n if (!this.isDragging) return;\r\n if (!this.sliderRect || !this.thumbRect) this.updateRects();\r\n let position = getOffsetPosition(ev, this.slider.nativeElement);\r\n let thumbRec = this.thumbRect!;\r\n position.x -= thumbRec.width / 2;\r\n let sliderRec = this.sliderRect!;\r\n if (position.x < 0) {\r\n this.x = 0;\r\n } else if (position.x > sliderRec.width - thumbRec.width) {\r\n this.x = sliderRec.width - thumbRec.width;\r\n } else {\r\n this.x = position.x;\r\n }\r\n this.setValueByPosition(thumbRec, sliderRec);\r\n }\r\n\r\n setValueByPosition(thumbRec: DOMRect, sliderRec: DOMRect) {\r\n const percentage = this.x / (sliderRec.width - thumbRec.width);\r\n let newValue = this.min + percentage * (this.max - this.min);\r\n const stepDecimalPlaces = (this.step.toString().split('.')[1] || '').length;\r\n newValue = parseFloat((Math.round(newValue / this.step) * this.step).toFixed(stepDecimalPlaces));\r\n let value = Math.min(Math.max(newValue, this.min), this.max);\r\n if (this.myControl.value !== value) {\r\n this.valueChanged(value);\r\n }\r\n }\r\n\r\n @HostListener('document:mouseup', ['$event'])\r\n @HostListener('document:touchend', ['$event'])\r\n onDragEnd(ev: MouseEvent | TouchEvent) {\r\n this.isDragging = false;\r\n }\r\n\r\n valueChanged(value: number) {\r\n this.myControl.setValue(value, { emitEvent: false });\r\n this._onChange(value);\r\n this.change.emit(value);\r\n }\r\n}\r\n","<div class=\"slider-container\">\r\n <ng-content></ng-content>\r\n <div\r\n #slider\r\n class=\"slider\"\r\n (mousedown)=\"dragStart($event)\"\r\n (touchstart)=\"dragStart($event)\"\r\n [ngStyle]=\"{ '--ngx-slider-bg': background }\"\r\n [class.bg-transparent]=\"isBgTransparent\">\r\n <div class=\"thumb\" #thumb [style.left.px]=\"x\" [title]=\"myControl.value\"></div>\r\n </div>\r\n</div>\r\n","import { CommonModule } from '@angular/common';\r\nimport { Component, ElementRef, EventEmitter, HostListener, Input, Output, ViewChild, forwardRef } from '@angular/core';\r\nimport { getOffsetPosition } from '../utils/get-offset-position';\r\nimport {\r\n NG_VALUE_ACCESSOR,\r\n ControlValueAccessor,\r\n FormControl,\r\n AbstractControl,\r\n ValidationErrors,\r\n} from '@angular/forms';\r\nimport { IPosition } from '../models/IPosition';\r\n\r\n@Component({\r\n selector: 'saturation',\r\n standalone: true,\r\n imports: [CommonModule],\r\n templateUrl: './saturation.component.html',\r\n styleUrl: './saturation.component.scss',\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => SaturationComponent),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class SaturationComponent implements ControlValueAccessor {\r\n @Input() width?: number;\r\n @Input() height?: number;\r\n @Input() color = 'red';\r\n @Input() step = 1;\r\n @Input() min: IPosition = { x: 0, y: 0 };\r\n @Input() max = { x: 100, y: 100 };\r\n @Output() change = new EventEmitter<IPosition>();\r\n\r\n isDragging = false;\r\n @ViewChild('saturation', { static: true }) saturation!: ElementRef<HTMLDivElement>;\r\n @ViewChild('thumb', { static: true }) thumb!: ElementRef<HTMLDivElement>;\r\n x = 0;\r\n y = 0;\r\n myControl = new FormControl<IPosition | null>(null);\r\n isDisabled = false;\r\n _onChange = (value: any) => {};\r\n _onTouched = () => {};\r\n _validatorOnChange = () => {};\r\n\r\n private saturationRect?: DOMRect;\r\n private thumbRect?: DOMRect;\r\n\r\n constructor() {}\r\n\r\n private updateRects() {\r\n this.saturationRect = this.saturation.nativeElement.getBoundingClientRect();\r\n this.thumbRect = this.thumb.nativeElement.getBoundingClientRect();\r\n }\r\n\r\n writeValue(val?: IPosition | null): void {\r\n if (!val) val = { x: 0, y: 0 };\r\n let value: IPosition = val;\r\n this.myControl.setValue(value, { emitEvent: false });\r\n this.updateRects();\r\n const saturationRec = this.saturationRect!;\r\n const thumbRec = this.thumbRect!;\r\n this.x = ((value.x - this.min.x) * (saturationRec.width - thumbRec.width / 2)) / (this.max.x - this.min.x);\r\n this.y = ((value.y - this.min.y) * (saturationRec.height - thumbRec.height / 2)) / (this.max.y - this.min.y);\r\n if (val !== value) {\r\n this.valueChanged(value);\r\n }\r\n }\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n return this.myControl.errors;\r\n }\r\n registerOnValidatorChange?(fn: () => void): void {\r\n this._validatorOnChange = fn;\r\n }\r\n\r\n registerOnChange(fn: any): void {\r\n this._onChange = fn;\r\n }\r\n registerOnTouched(fn: any): void {\r\n this._onTouched = fn;\r\n }\r\n setDisabledState?(disabled: boolean): void {\r\n this.isDisabled = disabled;\r\n if (disabled) this.myControl.disable();\r\n else this.myControl.enable();\r\n }\r\n\r\n dragStart(ev: MouseEvent | TouchEvent) {\r\n ev.stopPropagation();\r\n ev.preventDefault();\r\n this.isDragging = true;\r\n this.updateRects();\r\n this.updatePosition(ev);\r\n }\r\n\r\n @HostListener('window:resize', ['$event'])\r\n onResize() {\r\n this.writeValue(this.myControl.value);\r\n }\r\n\r\n @HostListener('document:mousemove', ['$event'])\r\n @HostListener('document:touchmove', ['$event'])\r\n onDrag(ev: MouseEvent | TouchEvent) {\r\n if (!this.isDragging) return;\r\n this.updatePosition(ev);\r\n }\r\n\r\n private updatePosition(ev: MouseEvent | TouchEvent) {\r\n if (!this.isDragging) return;\r\n if (!this.saturationRect || !this.thumbRect) this.updateRects();\r\n let position = getOffsetPosition(ev, this.saturation.nativeElement);\r\n let thumbRec = this.thumbRect!;\r\n let saturationRec = this.saturationRect!;\r\n if (position.x < 0) {\r\n this.x = 0;\r\n } else if (position.x > saturationRec.width - (thumbRec.width / 2 - 3)) {\r\n this.x = saturationRec.width - (thumbRec.width / 2 - 3);\r\n } else {\r\n this.x = position.x;\r\n }\r\n // this.x = this.x - thumbRec.width / 2;\r\n\r\n if (position.y < 0) {\r\n this.y = 0;\r\n } else if (position.y > saturationRec.height - (thumbRec.height / 2 - 3)) {\r\n this.y = saturationRec.height - (thumbRec.height / 2 - 3);\r\n } else {\r\n this.y = position.y;\r\n }\r\n // this.y = this.y - thumbRec.height / 2;\r\n this.setValueByPosition(thumbRec, saturationRec);\r\n }\r\n\r\n @HostListener('document:mouseup', ['$event'])\r\n @HostListener('document:touchend', ['$event'])\r\n onDragEnd(ev: MouseEvent | TouchEvent) {\r\n this.isDragging = false;\r\n }\r\n\r\n setValueByPosition(thumbRec: DOMRect, saturationRec: DOMRect) {\r\n const percentageX = this.x / (saturationRec.width - thumbRec.width);\r\n let newValueX = this.min.x + percentageX * (this.max.x - this.min.x);\r\n newValueX = Math.round(newValueX / this.step) * this.step;\r\n let valueX = Math.min(Math.max(newValueX, this.min.x), this.max.x);\r\n //-----------------------------\r\n const percentageY = this.y / (saturationRec.height - thumbRec.height);\r\n let newValueY = this.min.y + percentageY * (this.max.y - this.min.y);\r\n newValueY = Math.round(newValueY / this.step) * this.step;\r\n let valueY = Math.min(Math.max(newValueY, this.min.y), this.max.y);\r\n const newValue = { x: valueX, y: valueY };\r\n if (!this.myControl.value || this.myControl.value.x !== valueX || this.myControl.value.y !== valueY) {\r\n this.valueChanged(newValue);\r\n }\r\n }\r\n\r\n valueChanged(value: IPosition) {\r\n this.myControl.setValue(value, { emitEvent: false });\r\n this._onChange(value);\r\n this.change.emit(value);\r\n }\r\n}\r\n","<div\r\n class=\"saturation-container\"\r\n [style.width.px]=\"width\"\r\n [style.height.px]=\"height\"\r\n (mousedown)=\"dragStart($event)\"\r\n (touchstart)=\"dragStart($event)\">\r\n <div class=\"saturation\" #saturation>\r\n <div class=\"s-bg\" [style.background]=\"color\"></div>\r\n <div class=\"s-white\"></div>\r\n <div class=\"s-black\"></div>\r\n </div>\r\n <div class=\"thumb\" #thumb [style.left.px]=\"x\" [style.top.px]=\"y\"></div>\r\n</div>\r\n","import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';\r\nimport { NgxColor } from '../../../utils/color-helper';\r\nimport { IPosition } from '../../../models/IPosition';\r\nimport { HSVA } from '../../../utils/interfaces';\r\n\r\n@Component({\r\n selector: 'app-picker',\r\n templateUrl: './picker.component.html',\r\n styleUrls: ['./picker.component.scss'],\r\n})\r\nexport class PickerComponent implements OnInit {\r\n hue = 300;\r\n baseColor = 'rgb(0,0,0)';\r\n alphaBgColor = '#000';\r\n\r\n board: IPosition = { x: 1, y: 0 };\r\n alpha = 1;\r\n private inputColor?: NgxColor;\r\n @Input() simpleMode = false;\r\n\r\n @Input() set color(c: NgxColor) {\r\n if (c.equals(this.inputColor)) return;\r\n this.inputColor = c;\r\n const shva = c.toHsv();\r\n this.hue = shva.h;\r\n this.board = { x: shva.s, y: 100 - shva.v };\r\n this.alpha = shva.a ?? 1;\r\n const pureColor = new NgxColor({ h: this.hue, s: 100, v: 100, a: 1 });\r\n this.baseColor = pureColor.toHexString(false);\r\n this.alphaBgColor = this.inputColor.toHexString(false);\r\n }\r\n @Output() colorChange = new EventEmitter<NgxColor | undefined>();\r\n\r\n constructor() {}\r\n\r\n ngOnInit() {}\r\n\r\n generateColor() {\r\n try {\r\n const hsva: HSVA = { h: this.hue, s: this.board.x, v: 100 - this.board.y, a: this.alpha };\r\n const color = new NgxColor(hsva);\r\n const pureColor = new NgxColor({ h: this.hue, s: 100, v: 100, a: 1 });\r\n this.baseColor = pureColor.toHexString(false);\r\n this.alphaBgColor = color.toHexString(false);\r\n\r\n if (color.equals(this.inputColor) == false) {\r\n this.inputColor = color;\r\n this.colorChange.emit(color);\r\n }\r\n } catch (error) {\r\n this.colorChange.emit(undefined);\r\n }\r\n }\r\n}\r\n","<saturation\r\n [height]=\"simpleMode ? 150 : 160\"\r\n [(ngModel)]=\"board\"\r\n [min]=\"{ x: 0, y: 0 }\"\r\n [max]=\"{ x: 100, y: 100 }\"\r\n [step]=\"1\"\r\n [color]=\"baseColor\"\r\n (change)=\"generateColor()\"></saturation>\r\n<slider\r\n [(ngModel)]=\"hue\"\r\n [min]=\"0\"\r\n [max]=\"360\"\r\n [step]=\"1\"\r\n (change)=\"generateColor()\"\r\n background=\"linear-gradient(to right,red 0%,#ff0 17%,lime 33%,cyan 50%,blue 66%,#f0f 83%,red 100%)\"></slider>\r\n<slider\r\n [(ngModel)]=\"alpha\"\r\n [min]=\"0\"\r\n [max]=\"1\"\r\n [step]=\"0.1\"\r\n (change)=\"generateColor()\"\r\n [isBgTransparent]=\"true\"\r\n [background]=\"'linear-gradient(to right,transparent,' + alphaBgColor + ')'\"></slider>\r\n","import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';\r\nimport { NgxColor } from '../../../utils/color-helper';\r\nimport { CMYK } from '../../../utils/interfaces';\r\n\r\n@Component({\r\n selector: 'app-cmyk',\r\n templateUrl: './cmyk.component.html',\r\n styleUrls: ['./cmyk.component.scss'],\r\n})\r\nexport class CmykComponent implements OnInit {\r\n cyanSliderBackground = '';\r\n magentaSliderBackground = '';\r\n yellowSliderBackground = '';\r\n keySliderBackground = '';\r\n\r\n cyan: number = 0;\r\n magenta: number = 0;\r\n yellow: number = 0;\r\n key: number = 0;\r\n private inputColor?: NgxColor;\r\n\r\n @Input() set color(c: NgxColor) {\r\n if (c.equals(this.inputColor)) return;\r\n this.inputColor = c;\r\n const cmyk = c.toCmyk();\r\n this.cyan = cmyk.c;\r\n this.magenta = cmyk.m;\r\n this.yellow = cmyk.y;\r\n this.key = cmyk.k;\r\n this.updateSliderBackgrounds(cmyk);\r\n }\r\n @Output() colorChange = new EventEmitter<NgxColor | undefined>();\r\n constructor() {}\r\n\r\n ngOnInit() {}\r\n generateColor() {\r\n try {\r\n const cmyk: CMYK = { c: this.cyan, m: this.magenta, y: this.yellow, k: this.key };\r\n const color = new NgxColor(cmyk);\r\n this.updateSliderBackgrounds(cmyk);\r\n if (color.equals(this.inputColor) == false) {\r\n this.inputColor = color;\r\n this.colorChange.emit(color);\r\n }\r\n } catch (error) {\r\n this.colorChange.emit(undefined);\r\n }\r\n }\r\n\r\n private updateSliderBackgrounds(cmyk: CMYK) {\r\n this.cyanSliderBackground = this.getChannelGradient('c', cmyk);\r\n this.magentaSliderBackground = this.getChannelGradient('m', cmyk);\r\n this.yellowSliderBackground = this.getChannelGradient('y', cmyk);\r\n this.keySliderBackground = this.getChannelGradient('k', cmyk);\r\n }\r\n\r\n private getChannelGradient(channel: keyof CMYK, cmyk: CMYK): string {\r\n let baseColor = this.cloneColor(cmyk);\r\n baseColor[channel] = channel == 'k' ? 1 : 0;\r\n let startColor = NgxColor.cmykToRgba(baseColor);\r\n let s = `rgb(${startColor.r}, ${startColor.g}, ${startColor.b})`;\r\n baseColor[channel] = 100;\r\n let endColor = NgxColor.cmykToRgba(baseColor);\r\n let e = `rgb(${endColor.r}, ${endColor.g}, ${endColor.b})`;\r\n\r\n return `linear-gradient(to right, ${s},${e})`;\r\n }\r\n private isCmykEqual(a?: CMYK, b?: CMYK): boolean {\r\n if (!a || !b) return false;\r\n return a.c === b.c && a.m === b.m && a.y === b.y && a.k === b.k;\r\n }\r\n\r\n private cloneColor(cmyk: CMYK): CMYK {\r\n return JSON.parse(JSON.stringify(cmyk));\r\n // return Object.assign({}, cmyk);\r\n }\r\n}\r\n","<slider\r\n [(ngModel)]=\"cyan\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n [step]=\"1\"\r\n (change)=\"generateColor()\"\r\n [background]=\"cyanSliderBackground\">\r\n <div class=\"slider-title\">\r\n <span>Cyan</span>\r\n <input type=\"number\" [(ngModel)]=\"cyan\" min=\"0\" max=\"100\" step=\"1\" />\r\n </div>\r\n</slider>\r\n<slider\r\n [(ngModel)]=\"magenta\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n [step]=\"1\"\r\n (change)=\"generateColor()\"\r\n [background]=\"magentaSliderBackground\">\r\n <div class=\"slider-title\">\r\n <span>Magenta</span>\r\n <input type=\"number\" [(ngModel)]=\"magenta\" min=\"0\" max=\"100\" step=\"1\" />\r\n </div>\r\n</slider>\r\n<slider\r\n [(ngModel)]=\"yellow\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n [step]=\"1\"\r\n (change)=\"generateColor()\"\r\n [background]=\"yellowSliderBackground\">\r\n <div class=\"slider-title\">\r\n <span>Yellow</span>\r\n <input type=\"number\" [(ngModel)]=\"yellow\" min=\"0\" max=\"100\" step=\"1\" />\r\n </div>\r\n</slider>\r\n<slider\r\n [(ngModel)]=\"key\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n [step]=\"1\"\r\n (change)=\"generateColor()\"\r\n [background]=\"keySliderBackground\">\r\n <div class=\"slider-title\">\r\n <span>Key</span>\r\n <input type=\"number\" [(ngModel)]=\"key\" min=\"0\" max=\"100\" step=\"1\" />\r\n </div>\r\n</slider>\r\n","import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';\r\nimport { NgxColor } from '../../../utils/color-helper';\r\nimport { HSLA } from '../../../utils/interfaces';\r\n\r\n\r\n@Component({\r\n selector: 'app-hsl',\r\n templateUrl: './hsl.component.html',\r\n styleUrls: ['./hsl.component.scss'],\r\n})\r\nexport class HslComponent implements OnInit {\r\n hue: number = 0;\r\n saturation: number = 0;\r\n luminance: number = 0;\r\n alpha: number = 1;\r\n baseColor = 'rgb(0,0,0)';\r\n private inputColor?: NgxColor;\r\n\r\n @Input() set color(c: NgxColor) {\r\n if (c.equals(this.inputColor)) return;\r\n this.inputColor = c;\r\n const hsla = c.toHsl();\r\n this.hue = hsla.h;\r\n this.saturation = hsla.s;\r\n this.luminance = hsla.l;\r\n this.alpha = hsla.a ?? 1;\r\n this.baseColor = c.toHexString(false);\r\n }\r\n @Output() colorChange = new EventEmitter<NgxColor | undefined>();\r\n constructor() {}\r\n\r\n ngOnInit() {}\r\n\r\n generateColor() {\r\n try {\r\n const hsla: HSLA = { h: this.hue, s: this.saturation, l: this.luminance, a: this.alpha };\r\n const color = new NgxColor(hsla);\r\n this.baseColor = color.toHexString(false);\r\n if (color.equals(this.inputColor) == false) {\r\n this.inputColor = color;\r\n this.colorChange.emit(color);\r\n }\r\n } catch (error) {\r\n this.colorChange.emit(undefined);\r\n }\r\n }\r\n}\r\n","<slider\r\n [(ngModel)]=\"hue\"\r\n [min]=\"0\"\r\n [max]=\"360\"\r\n [step]=\"1\"\r\n (change)=\"generateColor()\"\r\n background=\"linear-gradient(to right,red 0%,#ff0 17%,lime 33%,cyan 50%,blue 66%,#f0f 83%,red 100%)\">\r\n <div class=\"slider-title\">\r\n <span>Hue</span>\r\n <input type=\"number\" [(ngModel)]=\"hue\" min=\"0\" max=\"360\" step=\"1\" />\r\n </div>\r\n</slider>\r\n<slider\r\n [(ngModel)]=\"saturation\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n [step]=\"1\"\r\n (change)=\"generateColor()\"\r\n [background]=\"'linear-gradient(to right,#808080,' + baseColor + ')'\">\r\n <div class=\"slider-title\">\r\n <span>Saturation</span>\r\n <input type=\"number\" [(ngModel)]=\"saturation\" min=\"0\" max=\"100\" step=\"1\" />\r\n </div>\r\n</slider>\r\n<slider\r\n [(ngModel)]=\"luminance\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n [step]=\"1\"\r\n (change)=\"generateColor()\"\r\n [background]=\"'linear-gradient(to right,black,' + baseColor + ',white)'\">\r\n <div class=\"slider-title\">\r\n <span>Luminance</span>\r\n <input type=\"number\" [(ngModel)]=\"luminance\" min=\"0\" max=\"100\" step=\"1\" />\r\n </div>\r\n</slider>\r\n<slider\r\n [(ngModel)]=\"alpha\"\r\n [min]=\"0\"\r\n [max]=\"1\"\r\n [step]=\"0.1\"\r\n (change)=\"generateColor()\"\r\n [isBgTransparent]=\"true\"\r\n [background]=\"'linear-gradient(to right,transparent,' + baseColor + ')'\">\r\n <div class=\"slider-title\">\r\n <span>Alpha</span>\r\n <input type=\"number\" [(ngModel)]=\"alpha\" min=\"0\" max=\"1\" step=\"0.1\" />\r\n </div>\r\n</slider>\r\n","import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';\r\nimport { NgxColor } from '../../../utils/color-helper';\r\nimport { RGBA } from '../../../utils/interfaces';\r\n\r\n@Component({\r\n selector: 'app-rgb',\r\n templateUrl: './rgb.component.html',\r\n styleUrls: ['./rgb.component.scss'],\r\n})\r\nexport class RgbComponent implements OnInit {\r\n redSliderBackground = '';\r\n greenSliderBackground = '';\r\n blueSliderBackground = '';\r\n\r\n baseColor = 'rgb(0,0,0)';\r\n red: number = 0;\r\n green: number = 0;\r\n blue: number = 0;\r\n alpha: number = 1;\r\n\r\n private inputColor?: NgxColor;\r\n @Input() set color(c: NgxColor) {\r\n if (c.equals(this.inputColor)) return;\r\n this.inputColor = c;\r\n const rgba = c.toRgb();\r\n this.red = rgba.r;\r\n this.green = rgba.g;\r\n this.blue = rgba.b;\r\n this.alpha = rgba.a ?? 1;\r\n this.updateRgbSliderColor(rgba as any);\r\n }\r\n @Output() colorChange = new EventEmitter<NgxColor | undefined>();\r\n constructor() {}\r\n\r\n ngOnInit() {}\r\n\r