diff --git a/apis/nucleus/package.json b/apis/nucleus/package.json index 897dc95b8..ecb1e8767 100644 --- a/apis/nucleus/package.json +++ b/apis/nucleus/package.json @@ -16,6 +16,7 @@ "@testing-library/react": "^14.3.1", "extend": "3.0.2", "node-event-emitter": "0.0.1", + "qlik-chart-modules": "0.77.0", "react": "18.3.1", "react-dom": "18.3.1", "react-test-renderer": "18.3.1", diff --git a/apis/nucleus/src/components/listbox/assets/__tests__/styling.test.js b/apis/nucleus/src/components/listbox/assets/__tests__/styling.test.js index 33c45289a..e54800173 100644 --- a/apis/nucleus/src/components/listbox/assets/__tests__/styling.test.js +++ b/apis/nucleus/src/components/listbox/assets/__tests__/styling.test.js @@ -1,10 +1,4 @@ -import getStyling, { - CONTRAST_THRESHOLD, - DEFAULT_SELECTION_COLORS, - getContrast, - getContrastingColor, - getOverridesAsObject, -} from '../styling'; +import getStyling, { DEFAULT_SELECTION_COLORS, getOverridesAsObject } from '../styling'; describe('styling', () => { let theme = {}; @@ -116,14 +110,14 @@ describe('styling', () => { expect(styles.search.color).toEqual('object.listBox,content,color'); }); it('search - should get desired color if contrasting enough', () => { - themeApi.getStyle = () => '#999'; + themeApi.getStyle = () => '#888888'; const styles = getStyling({ app, themeApi, theme, components: [] }); - expect(styles.search.color).toEqual('#999'); + expect(styles.search.color).toEqual('#888888'); }); it('search - should get a better contrasting color if not good contrast against white', () => { themeApi.getStyle = () => '#aaa'; const styles = getStyling({ app, themeApi, theme, components: [] }); - expect(styles.search.color).toEqual('#000'); + expect(styles.search.color).toEqual('#000000'); }); it('header', () => { components = [ @@ -165,7 +159,7 @@ describe('styling', () => { }, ]; const POSSIBLE_COLOR = 'rgb(255, 255, 255)'; - const CONTRASTING_TO_POSSIBLE = '#000'; + const CONTRASTING_TO_POSSIBLE = '#000000'; themeApi.getStyle = (a, b, c) => (c === 'backgroundColor' ? POSSIBLE_COLOR : `${a},${b},${c}`); components[0].content.fontColor.color = '#FFFFFF'; @@ -200,66 +194,6 @@ describe('styling', () => { }); }); - const hasEnoughContrast = (a, b) => getContrast(a, b) > CONTRAST_THRESHOLD; - - describe('contrast', () => { - it('should return undefined for unsupported or invalid color(s)', () => { - expect(getContrast('rgb(0,0,0)', 'transparent')).toEqual(undefined); - expect(getContrast('rgb(0,0,0)', 'asdasd')).toEqual(undefined); - expect(getContrast('dsadasd', 'rgb(0,0,0)')).toEqual(undefined); - }); - - it('should fallback to false when contrast is undefined for unsupported or invalid color(s)', () => { - expect(hasEnoughContrast('#ddd', 'white')).toEqual(false); - expect(hasEnoughContrast('#ccc', 'white')).toEqual(false); - expect(hasEnoughContrast('rgb(0,0,0)', 'transparent')).toEqual(false); - expect(hasEnoughContrast('transparent', 'transparent')).toEqual(false); - expect(hasEnoughContrast('red', 'blue')).toEqual(true); - expect(hasEnoughContrast('misspelled', 'hey hey')).toEqual(false); - expect(hasEnoughContrast('misspelled', 'hey hey')).toEqual(false); - expect(hasEnoughContrast('transparent', 'transparent')).toEqual(false); - expect(hasEnoughContrast(' hsl (0, 0 , 0 , 1.0 )', '#FFF')).toEqual(false); - expect(hasEnoughContrast('hsl(0, 0, 0, 1)', '#FFF')).toEqual(false); - expect(hasEnoughContrast('hsl(0,0,0,1.0)', '#FFF')).toEqual(false); - expect(hasEnoughContrast(undefined, '#FFF')).toEqual(false); - expect(hasEnoughContrast('', '#FFF')).toEqual(false); - }); - it('should detect transparent colors and then always return false since we do not know color is behind the transparent color', () => { - expect(hasEnoughContrast(' rgba (0, 0 , 0 , 0.2 )', '#FFF')).toEqual(false); - expect(hasEnoughContrast(' hsla (0, 0 , 0 , 0.2 )', '#FFF')).toEqual(false); - expect(hasEnoughContrast(' rgba (0, 0 , 0 , .2 )', '#FFF')).toEqual(false); - expect(hasEnoughContrast(' hsla (0, 0 , 0 , .2 )', '#FFF')).toEqual(false); - expect(hasEnoughContrast('rgba(0, 0, 0, 0)', '#FFF')).toEqual(false); - expect(hasEnoughContrast('rgba(0,0,0,0)', '#FFF')).toEqual(false); - expect(hasEnoughContrast('hsla(0, 0, 0, 0)', '#FFF')).toEqual(false); - expect(hasEnoughContrast('hsla(0,0,0,0)', '#FFF')).toEqual(false); - expect(hasEnoughContrast('transparent', '#FFF')).toEqual(false); - }); - it('should fallback to false for unsupported formats', () => { - expect(hasEnoughContrast('rgb(0 0 0 / 0%', '#FFF')).toEqual(false); - expect(hasEnoughContrast('rgb(0 0 0 / 100%)', '#FFF')).toEqual(false); - expect(hasEnoughContrast('rgb(255 255 255 / 0%)', '#000')).toEqual(false); - expect(hasEnoughContrast('rgb(255 255 255 / 100%)', '#000')).toEqual(false); - }); - - it('should not detect as transparent colors', () => { - expect(hasEnoughContrast('rgba(0, 0, 0, 1)', '#FFF')).toEqual(true); - expect(hasEnoughContrast('hsla(0,0,0,1.0)', '#FFF')).toEqual(true); - expect(hasEnoughContrast('rgba(0,0,0,1.0)', '#FFF')).toEqual(true); - expect(hasEnoughContrast('red', '#FFF')).toEqual(true); - }); - }); - - describe('get contrasting color', () => { - it('should prefer light color even though contrast is higher for desired color', () => { - const bg = '#474747'; - const c1 = getContrast('#000', bg); - const c2 = getContrast('#fff', bg); - expect(c1 > c2).toBeTruthy(); // although it does not make sense when comparing with the eye - expect(getContrastingColor(bg, '#000')).toEqual('#FFF'); - }); - }); - describe('getSelectionColors', () => { let themeSelectionColorsEnabled; diff --git a/apis/nucleus/src/components/listbox/assets/styling.js b/apis/nucleus/src/components/listbox/assets/styling.js index 01298892b..4e7254c67 100644 --- a/apis/nucleus/src/components/listbox/assets/styling.js +++ b/apis/nucleus/src/components/listbox/assets/styling.js @@ -1,12 +1,6 @@ -import { Color } from '@nebula.js/theme'; +import { createColor, getContrastingColor } from 'qlik-chart-modules'; import { resolveBgColor, resolveBgImage } from '../../../utils/style/styling-props'; -const LIGHT = '#FFF'; -const DARK = '#000'; - -export const CONTRAST_THRESHOLD = 1.5; -const LIGHT_PREFERRED_THRESHOLD = 3; - export const DEFAULT_SELECTION_COLORS = { selected: '#00873D', alternative: '#E4E4E4', @@ -15,46 +9,6 @@ export const DEFAULT_SELECTION_COLORS = { possible: '#FFFFFF', }; -export const getContrast = (desired, background) => { - let contrast = false; - - const des = new Color(desired); - const bg = new Color(background); - - if (bg.isInvalid() || des.isInvalid() || bg.getAlpha() < 1 || des.getAlpha() < 1) { - return undefined; - } - - try { - contrast = Color.getContrast(des, bg); - } catch (err) { - contrast = undefined; - } - return contrast; -}; - -export function getContrastingColor(backgroundColor, desiredTextColor = undefined, dark = DARK, light = LIGHT) { - const lightColor = new Color(light); - const bg = new Color(backgroundColor); - const des = new Color(desiredTextColor); - if (bg.isInvalid() || des.isInvalid() || bg.getAlpha() < 1 || des.getAlpha() < 1) { - return desiredTextColor; - } - - // Always prioritise light color if it gives better contrast than desired color's. - const lightColorContrast = getContrast(lightColor, bg); - const desiredColorContrast = getContrast(des, bg); - const useLightColor = lightColorContrast > desiredColorContrast || lightColorContrast > LIGHT_PREFERRED_THRESHOLD; - - let contrastingColor; - if (desiredTextColor && desiredColorContrast > CONTRAST_THRESHOLD && !useLightColor) { - contrastingColor = desiredTextColor; - } else { - contrastingColor = useLightColor ? light : dark; - } - return contrastingColor; -} - const SUPPORTED_COMPONENTS = ['theme', 'selections']; export function getOverridesAsObject(components = []) { @@ -141,9 +95,9 @@ function getSearchColor(getListboxStyle) { } function getSearchBGColor(bgCol, getListboxStyle) { - const searchBgColorObj = new Color(getListboxStyle('', 'backgroundColor')); + const searchBgColorObj = createColor(getListboxStyle('', 'backgroundColor')); searchBgColorObj.setAlpha(0.7); - return searchBgColorObj.isInvalid() ? bgCol : searchBgColorObj.toRGBA(); + return searchBgColorObj.isInvalid() ? bgCol : searchBgColorObj.getRGBA(); } export default function getStyles({ diff --git a/apis/nucleus/src/utils/style/__tests__/styling-props.test.js b/apis/nucleus/src/utils/style/__tests__/styling-props.test.js index e3f12022b..8a222a60f 100644 --- a/apis/nucleus/src/utils/style/__tests__/styling-props.test.js +++ b/apis/nucleus/src/utils/style/__tests__/styling-props.test.js @@ -62,7 +62,7 @@ describe('Styling property resolver', () => { jest.spyOn(resolveColor, 'default').mockReturnValue('resolvedColor'); const color = resolveBgColor(bgCompLayout, t); expect(resolveColor.default).toHaveBeenCalledTimes(0); - expect(color).toBe('rgb(255, 0, 0)'); + expect(color).toBe('rgb(255,0,0)'); }); test('should resolve background color by picker', () => { @@ -87,7 +87,7 @@ describe('Styling property resolver', () => { const color = resolveBgColor(bgCompLayout, t); expect(resolveColor.default).toHaveBeenCalledTimes(0); - expect(color).toBe('rgb(255, 0, 0)'); + expect(color).toBe('rgb(255,0,0)'); }); test('should resolve background color by theme', () => { diff --git a/apis/theme/package.json b/apis/theme/package.json index 96a00930e..90004c84f 100644 --- a/apis/theme/package.json +++ b/apis/theme/package.json @@ -4,8 +4,8 @@ "private": true, "main": "src/index.js", "devDependencies": { - "d3-color": "3.1.0", "extend": "3.0.2", - "node-event-emitter": "0.0.1" + "node-event-emitter": "0.0.1", + "qlik-chart-modules": "0.77.0" } } diff --git a/apis/theme/src/contraster/__tests__/contraster.test.js b/apis/theme/src/__tests__/contraster.test.js similarity index 83% rename from apis/theme/src/contraster/__tests__/contraster.test.js rename to apis/theme/src/__tests__/contraster.test.js index 054e1b86b..631ac46cf 100644 --- a/apis/theme/src/contraster/__tests__/contraster.test.js +++ b/apis/theme/src/__tests__/contraster.test.js @@ -1,6 +1,5 @@ +import * as chartModules from 'qlik-chart-modules'; import create from '../contraster'; -import * as luminanceModule from '../luminance'; -import * as contrastModule from '../contrast'; describe('contraster', () => { let luminanceMock; @@ -10,8 +9,8 @@ describe('contraster', () => { luminanceMock = jest.fn(); contrastMock = jest.fn(); - jest.spyOn(luminanceModule, 'default').mockImplementation(luminanceMock); - jest.spyOn(contrastModule, 'default').mockImplementation(contrastMock); + jest.spyOn(chartModules, 'getLuminance').mockImplementation(luminanceMock); + jest.spyOn(chartModules, 'getContrastRatio').mockImplementation(contrastMock); }); afterEach(() => { diff --git a/apis/theme/src/__tests__/theme.test.js b/apis/theme/src/__tests__/theme.test.js index b4506f387..67c493ed9 100644 --- a/apis/theme/src/__tests__/theme.test.js +++ b/apis/theme/src/__tests__/theme.test.js @@ -1,9 +1,9 @@ import * as EventEmitter from 'node-event-emitter'; +import * as chartModules from 'qlik-chart-modules'; import * as setThemeModule from '../set-theme'; import * as paletterResolverFnModule from '../palette-resolver'; import * as styleResolverFnModule from '../style-resolver'; -import * as contrasterFnModule from '../contraster/contraster'; -import * as luminanceFnModule from '../contraster/luminance'; +import * as contrasterFnModule from '../contraster'; import create from '../index'; jest.mock('node-event-emitter'); @@ -32,7 +32,7 @@ describe('theme', () => { jest.spyOn(styleResolverFnModule, 'default').mockImplementation(styleResolverFnMock); styleResolverFnMock.resolveRawTheme = 'raw'; jest.spyOn(contrasterFnModule, 'default').mockImplementation(contrasterFnMock); - jest.spyOn(luminanceFnModule, 'default').mockImplementation(luminanceFnMock); + jest.spyOn(chartModules, 'getLuminance').mockImplementation(luminanceFnMock); emitter = { prototype: { emit: emitterEmitMock, diff --git a/apis/theme/src/color-scale.js b/apis/theme/src/color-scale.js index a1a8d12c0..587ae5a44 100644 --- a/apis/theme/src/color-scale.js +++ b/apis/theme/src/color-scale.js @@ -1,4 +1,4 @@ -import { color, rgb } from 'd3-color'; +import { createColor, getBlendedColor } from 'qlik-chart-modules'; /** * Gets this mapping between the scaled value and the color parts @@ -10,7 +10,7 @@ function limitFunction(scaledValue, numParts) { /* * Color-Scale doesn't calculate exact color blends based of the scaled value. It instead shifts the value inwards to achieve * a better color representation at the edges. Primarily this is done to allow setting custom limits to where each color begins - * and ends. If a color begins and ends at 1, it should not be visible. The simplest way to achive this is to remove 1 and 0 + * and ends. If a color begins and ends at 1, it should not be visible. The simplest way to achieve this is to remove 1 and 0 * from the possible numbers that can be used. Colors that are not equal to 1 or 0 should not be affected. */ @@ -24,21 +24,13 @@ function getLevel(scale, level) { return Math.min(level || scale.startLevel, scale.colorParts.length - 1); } -function blend(c1, c2, t) { - const r = Math.floor(c1.r + (c2.r - c1.r) * t); - const g = Math.floor(c1.g + (c2.g - c1.g) * t); - const b = Math.floor(c1.b + (c2.b - c1.b) * t); - const a = Math.floor(c1.opacity + (c2.opacity - c1.opacity) * t); - return rgb(r, g, b, a); -} - class ColorScale { constructor(nanColor) { this.colorParts = []; this.startLevel = 0; this.max = 1; this.min = 0; - this.nanColor = color(nanColor); + this.nanColor = createColor(nanColor); } /** @@ -55,7 +47,7 @@ class ColorScale { if (!this.colorParts[level]) { this.colorParts[level] = []; } - this.colorParts[level].push([color(color1), color(color2)]); + this.colorParts[level].push([createColor(color1), createColor(color2)]); } /** @@ -86,7 +78,7 @@ class ColorScale { } const t = k - f; - const uc = blend(c1, c2, t); + const uc = getBlendedColor(c1, c2, t); return uc; } } diff --git a/apis/theme/src/contraster/contraster.js b/apis/theme/src/contraster.js similarity index 67% rename from apis/theme/src/contraster/contraster.js rename to apis/theme/src/contraster.js index b422176de..6de81f1bf 100644 --- a/apis/theme/src/contraster/contraster.js +++ b/apis/theme/src/contraster.js @@ -1,6 +1,5 @@ /* eslint no-cond-assign: 0 */ -import luminance from './luminance'; -import contrast from './contrast'; +import { getContrastRatio, getLuminance } from 'qlik-chart-modules'; const MAX_SIZE = 1000; @@ -8,7 +7,7 @@ export default function colorFn(colors = ['#333333', '#ffffff']) { let cache = {}; let n = 0; - const luminances = colors.map(luminance); + const luminances = colors.map(getLuminance); return { getBestContrastColor(colorString) { @@ -17,9 +16,9 @@ export default function colorFn(colors = ['#333333', '#ffffff']) { cache = {}; n = 0; } - const L = luminance(colorString); + const L = getLuminance(colorString); - const contrasts = luminances.map((lum) => contrast(L, lum)); + const contrasts = luminances.map((lum) => getContrastRatio(L, lum)); const c = colors[contrasts.indexOf(Math.max(...contrasts))]; cache[colorString] = c; diff --git a/apis/theme/src/contraster/__tests__/contrast.test.js b/apis/theme/src/contraster/__tests__/contrast.test.js deleted file mode 100644 index 6c13b8b3c..000000000 --- a/apis/theme/src/contraster/__tests__/contrast.test.js +++ /dev/null @@ -1,22 +0,0 @@ -import contrast from '../contrast'; - -describe('contrast', () => { - test('should be 1 for same luminance', () => { - expect(contrast(0, 0)).toBe(1); - }); - - test('should be 21 when delta in luminance is 1', () => { - expect(contrast(0, 1)).toBe(21); - }); - - test('should return same value even when luminances are in wrong order', () => { - const v = 2.6; - const lums = [0.2, 0.6]; - expect(contrast(...lums)).toBe(v); - expect(contrast(...lums.reverse())).toBe(v); - }); - - test('should be 1.72727 when luminances are [0.9, 0.5]', () => { - expect(contrast(0.9, 0.5)).toBe(1.72727); - }); -}); diff --git a/apis/theme/src/contraster/__tests__/luminance.test.js b/apis/theme/src/contraster/__tests__/luminance.test.js deleted file mode 100644 index 3898e2f7d..000000000 --- a/apis/theme/src/contraster/__tests__/luminance.test.js +++ /dev/null @@ -1,31 +0,0 @@ -import * as d3ColorUtil from 'd3-color'; -import luminance from '../luminance'; - -describe('luminance', () => { - let d3ColorMock; - - beforeAll(() => { - d3ColorMock = jest.fn(); - jest.spyOn(d3ColorUtil, 'color').mockImplementation(d3ColorMock); - }); - - afterEach(() => { - jest.resetAllMocks(); - jest.restoreAllMocks(); - }); - - test('for #ffffff should be 1', () => { - d3ColorMock.mockReturnValue({ rgb: () => ({ r: 255, g: 255, b: 255 }) }); - expect(luminance('#ffffff')).toBe(1); - }); - - test('for #000000 should be 0', () => { - d3ColorMock.mockReturnValue({ rgb: () => ({ r: 0, g: 0, b: 0 }) }); - expect(luminance('#000000')).toBe(0); - }); - - test('for #ff6633 should be 0.31002', () => { - d3ColorMock.mockReturnValue({ rgb: () => ({ r: 255, g: 102, b: 51 }) }); - expect(luminance('#ff6633')).toBe(0.31002); - }); -}); diff --git a/apis/theme/src/contraster/contrast.js b/apis/theme/src/contraster/contrast.js deleted file mode 100644 index 2d2ca8397..000000000 --- a/apis/theme/src/contraster/contrast.js +++ /dev/null @@ -1,4 +0,0 @@ -// https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html#contrast-ratiodef -export default function contrast(L1, L2) { - return +((Math.max(L1, L2) + 0.05) / (Math.min(L1, L2) + 0.05)).toFixed(5); -} diff --git a/apis/theme/src/contraster/luminance.js b/apis/theme/src/contraster/luminance.js deleted file mode 100644 index 638a119fc..000000000 --- a/apis/theme/src/contraster/luminance.js +++ /dev/null @@ -1,12 +0,0 @@ -import { color } from 'd3-color'; - -export default function luminance(colStr) { - const c = color(colStr).rgb(); - const { r, g, b } = c; - - // https://www.w3.org/TR/WCAG20/#relativeluminancedef - const [sR, sG, sB] = [r, g, b].map((v) => v / 255); - const [R, G, B] = [sR, sG, sB].map((v) => (v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4)); - - return +(0.2126 * R + 0.7152 * G + 0.0722 * B).toFixed(5); -} diff --git a/apis/theme/src/index.js b/apis/theme/src/index.js index 7d81f7f0a..fd8fcf3c3 100644 --- a/apis/theme/src/index.js +++ b/apis/theme/src/index.js @@ -1,12 +1,10 @@ +import { createColor, getLuminance } from 'qlik-chart-modules'; import EventEmitter from 'node-event-emitter'; -import { color as d3color } from 'd3-color'; import setTheme from './set-theme'; import paletteResolverFn from './palette-resolver'; import styleResolverFn from './style-resolver'; -import contrasterFn from './contraster/contraster'; -import luminance from './contraster/luminance'; -import Color from './utils/color/color'; +import contrasterFn from './contraster'; export default function theme() { let resolvedThemeJSON; @@ -114,10 +112,7 @@ export default function theme() { return styleResolverInstanceCache[basePath].getStyle(path, attribute); }, /** - * Validates a color string using d3-color. - * See https://www.npmjs.com/package/d3-color - * Additionally supports the non-standard engine - * format ARGB(0-255,0-255,0-255,0-255) + * Validates a color string, including support for non-standard color format ARGB(0-255,0-255,0-255,0-255). * @param {string} specifier * @returns {string|undefined} The resolved color or undefined * @ignore @@ -129,25 +124,12 @@ export default function theme() { * theme.validateColor("FOO"); // returns undefined */ validateColor(...args) { - /* Added this to support the non-standard ARGB format from engine */ - const colorString = args[0]; - let matches; - /* eslint-disable no-cond-assign */ - if ( - typeof colorString === 'string' && - (matches = /^ARGB\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i.exec(colorString)) - ) { - // ARGB(255,255,255,255) - const a = parseInt(matches[1], 10) / 255; - const r = parseInt(matches[2], 10); - const g = parseInt(matches[3], 10); - const b = parseInt(matches[4], 10); - return `rgba(${r},${g},${b},${a})`; + const c = createColor(...args); + if (c.isInvalid()) { + return undefined; } - /* eslint-enable no-cond-assign */ - const c = d3color(...args); - return c ? c.toString() : undefined; + return c.getAlpha() === 1 ? c.getRGB() : c.getRGBA(); }, }; @@ -164,7 +146,7 @@ export default function theme() { // try to determine if the theme color is light or dark const textColor = externalAPI.getStyle('', '', 'color'); - const textColorLuminance = luminance(textColor); + const textColorLuminance = getLuminance(textColor); // if it appears dark, create an inverse that is light and vice versa const inverseTextColor = textColorLuminance < 0.2 ? '#ffffff' : '#333333'; // instantiate a contraster that uses those two colors when determining the best contrast for an arbitrary color @@ -187,5 +169,3 @@ export default function theme() { internalAPI, }; } - -export { Color }; diff --git a/apis/theme/src/palette-resolver.js b/apis/theme/src/palette-resolver.js index b625c894f..6336cb6f4 100644 --- a/apis/theme/src/palette-resolver.js +++ b/apis/theme/src/palette-resolver.js @@ -1,4 +1,4 @@ -import Color from './utils/color/color'; +import { createColor } from 'qlik-chart-modules'; /** * @interface Theme~ScalePalette @@ -105,12 +105,12 @@ export default function theme(resolvedTheme) { if (c.alpha === undefined || c.alpha >= 1 || c.alpha < 0) { return color; } - const rgbaColor = new Color(color); + const rgbaColor = createColor(color); rgbaColor.setAlpha(c.alpha); if (rgbaColor.isInvalid()) { return color; } - return rgbaColor.toRGBA(); + return rgbaColor.getRGBA(); }, }; } diff --git a/apis/theme/src/theme-scale-generator.js b/apis/theme/src/theme-scale-generator.js index d4ba03f14..7c794b2ef 100644 --- a/apis/theme/src/theme-scale-generator.js +++ b/apis/theme/src/theme-scale-generator.js @@ -1,4 +1,4 @@ -import { color } from 'd3-color'; +import { createColor } from 'qlik-chart-modules'; import ColorScale from './color-scale'; /* Calculates a value that expands from 0.5 out to 0 and 1 @@ -59,7 +59,7 @@ function generateLevel(scale, current, size) { break; } } - level.push(color(c).formatHex()); + level.push(createColor(c).getHex()); } return level; } diff --git a/apis/theme/src/utils/color/__tests__/color.test.js b/apis/theme/src/utils/color/__tests__/color.test.js deleted file mode 100644 index d122ff92d..000000000 --- a/apis/theme/src/utils/color/__tests__/color.test.js +++ /dev/null @@ -1,198 +0,0 @@ -/* eslint-disable no-underscore-dangle */ -import Color from '../color'; - -describe('Color', () => { - const r = 100; // same as rgb(100, 128, 200) - const g = 128; - const b = 200; - const a = 0.5; - const rgbString = `rgb(${[r, g, b].join(',')})`; - - // same as rgb(100, 128, 200) - const hash = '#6480c8'; - - // same as #AABBCC / rgb(170, 187, 204) - const shorthash = '#ABC'; - - // same as rgb(100, 128, 200) - const hsl = 'hsl(223.2 , 47.6 , 58.8)'; - - const unsing = 6586568; - - test('Color generators', () => { - let c; - - c = new Color(r, g, b); - expect([c._r, c._g, c._b, c._a]).toEqual([r, g, b, 1]); - - c = new Color(r, g, b, a); - expect([c._r, c._g, c._b, c._a]).toEqual([r, g, b, a]); - - c = new Color(unsing); - expect([c._r, c._g, c._b, c._a]).toEqual([r, g, b, 1]); - - c = new Color(`rgb(${r},${g},${b})`); - expect([c._r, c._g, c._b, c._a]).toEqual([r, g, b, 1]); - - c = new Color(`rgba(${r},${g},${b},${a})`); - expect([c._r, c._g, c._b, c._a]).toEqual([r, g, b, a]); - - c = new Color(`ARGB(${102},${r},${g},${b})`); - expect([c._r, c._g, c._b, c._a]).toEqual([r, g, b, 0.4]); - - c = new Color(hash); - expect([c._r, c._g, c._b, c._a]).toEqual([r, g, b, 1]); - - c = new Color(shorthash); - expect([c._r, c._g, c._b, c._a]).toEqual([170, 187, 204, 1]); - - c = new Color(hsl); - expect([c._r, c._g, c._b, c._a]).toEqual([r, g, b, 1]); - }); - - test('Color to string conversion', () => { - const c = new Color(r, g, b); - expect(c.toRGB()).toEqual(rgbString); - expect(c.toHex()).toEqual(hash); - expect(c.toNumber()).toEqual(unsing); - }); - - test('Color interpolation', () => { - const c1 = new Color(100, 200, 100); - const c2 = new Color(200, 100, 0); - const shouldBlendTo0 = new Color(100, 200, 100); - const shouldBlendTo05 = new Color(150, 150, 50); - const shouldBlendTo075 = new Color(175, 125, 25); - const shouldBlendTo1 = new Color(200, 100, 0); - let blended; - - blended = Color.getBlend(c1, c2, 0); - expect([blended._r, blended._g, blended._b]).toEqual([shouldBlendTo0._r, shouldBlendTo0._g, shouldBlendTo0._b]); - - blended = Color.getBlend(c1, c2, 0.5); - expect([blended._r, blended._g, blended._b]).toEqual([shouldBlendTo05._r, shouldBlendTo05._g, shouldBlendTo05._b]); - - blended = Color.getBlend(c1, c2, 0.75); - expect([blended._r, blended._g, blended._b]).toEqual([ - shouldBlendTo075._r, - shouldBlendTo075._g, - shouldBlendTo075._b, - ]); - - blended = Color.getBlend(c1, c2, 1); - expect([blended._r, blended._g, blended._b]).toEqual([shouldBlendTo1._r, shouldBlendTo1._g, shouldBlendTo1._b]); - }); - - test('from HSV to RGB and back', () => { - // Note: due to rounding the convertion back will not always be exact - let colorString = 'hsv(0,0,0)'; - - let c1 = new Color(colorString); - expect(c1.toHSV()).toEqual(colorString); - expect(c1.toHex()).toEqual('#000000'); - - colorString = 'hsv(0,0,100)'; - c1 = new Color(colorString); - expect(c1.toHSV()).toEqual(colorString); - expect(c1.toHex()).toEqual('#ffffff'); - - colorString = 'hsv(0,100,100)'; - c1 = new Color(colorString); - expect(c1.toHSV()).toEqual(colorString); - expect(c1.toHex()).toEqual('#ff0000'); - - colorString = 'hsv(120,100,100)'; - c1 = new Color(colorString); - expect(c1.toHSV()).toEqual(colorString); - expect(c1.toHex()).toEqual('#00ff00'); - - colorString = 'hsv(300,100,100)'; - c1 = new Color(colorString); - expect(c1.toHSV()).toEqual(colorString); - expect(c1.toHex()).toEqual('#ff00ff'); - - colorString = 'hsv(180,100,50)'; - c1 = new Color(colorString); - expect(c1.toHex()).toEqual('#008080'); - }); - - describe('Color equality', () => { - const rgb = new Color(100, 128, 200); - const rgba = new Color(100, 128, 200, 0.4); - - test('with Color', () => { - expect(rgb.isEqual(new Color(100, 128, 200))).toEqual(true); - expect(rgb.isEqual(new Color(100, 128, 200, 1))).toEqual(true); - expect(rgb.isEqual(new Color('rgb(100,128,200)'))).toEqual(true); - expect(rgb.isEqual(new Color('rgba(100,128,200,1)'))).toEqual(true); - expect(rgb.isEqual(new Color('#6480c8'))).toEqual(true); - expect(rgb.isEqual(new Color('hsl(223.2 , 47.6 , 58.8)'))).toEqual(true); - expect(rgb.isEqual(new Color(6586568))).toEqual(true); - expect(rgb.isEqual(new Color(101, 129, 201))).toEqual(false); - expect(rgb.isEqual(new Color('rgb(101,129,201)'))).toEqual(false); - expect(rgb.isEqual(new Color(100, 128, 200, 0.4))).toEqual(false); - expect(rgb.isEqual(new Color('rgba(100,128,200,0.4)'))).toEqual(false); - expect(rgba.isEqual(new Color(100, 128, 200, 0.4))).toEqual(true); - expect(rgba.isEqual(new Color('rgba(100,128,200,0.4)'))).toEqual(true); - expect(rgba.isEqual(new Color('hsla(223.2,47.6,58.8,0.4)'))).toEqual(true); - expect(rgba.isEqual(new Color(100, 128, 200, 0.6))).toEqual(false); - expect(rgba.isEqual(new Color('rgba(100,128,200,0.6)'))).toEqual(false); - expect(rgba.isEqual(new Color(100, 128, 200))).toEqual(false); - expect(rgba.isEqual(new Color('rgb(100,128,200)'))).toEqual(false); - expect(rgba.isEqual(new Color('#6480c8'))).toEqual(false); - expect(rgba.isEqual(new Color('hsl(223.2 , 47.6 , 58.8)'))).toEqual(false); - expect(rgba.isEqual(new Color(6586568))).toEqual(false); - }); - - test('with string', () => { - expect(rgb.isEqual('rgb(100,128,200)')).toEqual(true); - expect(rgb.isEqual('rgba(100,128,200,1)')).toEqual(true); - expect(rgb.isEqual('ARGB(255,100,128,200)')).toEqual(true); - expect(rgb.isEqual('#6480c8')).toEqual(true); - expect(rgb.isEqual('hsl(223.2 , 47.6 , 58.8)')).toEqual(true); - expect(rgb.isEqual('rgb(101,129,201)')).toEqual(false); - expect(rgb.isEqual('rgba(100,128,200,0.4)')).toEqual(false); - expect(rgba.isEqual('rgba(100,128,200,0.4)')).toEqual(true); - expect(rgba.isEqual('ARGB(102,100,128,200)')).toEqual(true); - expect(rgba.isEqual('hsla(223.2,47.6,58.8,0.4)')).toEqual(true); - expect(rgba.isEqual('rgba(100,128,200,0.6)')).toEqual(false); - expect(rgba.isEqual('rgb(100,128,200)')).toEqual(false); - expect(rgba.isEqual('#6480c8')).toEqual(false); - expect(rgba.isEqual('hsl(223.2 , 47.6 , 58.8)')).toEqual(false); - }); - - test('with number', () => { - expect(rgb.isEqual(6586568)).toEqual(true); - expect(rgba.isEqual(6586568)).toEqual(false); - }); - - test('with invalid value', () => { - expect(rgb.isEqual(null)).toEqual(false); - expect(rgb.isEqual(undefined)).toEqual(false); - expect(rgb.isEqual('')).toEqual(false); - }); - }); - - describe('utility functions', () => { - describe('isDark', () => { - test('#000', () => { - expect(Color.isDark('#000')).toEqual(true); - }); - test('black', () => { - expect(Color.isDark('black')).toEqual(true); - }); - test('blue', () => { - expect(Color.isDark('blue')).toEqual(true); - }); - test('white', () => { - expect(Color.isDark('white')).toEqual(false); - }); - test('hsl(0,0,48)', () => { - expect(Color.isDark('hsl(0,0,48)')).toEqual(true); - }); - test('hsl(0,0,50)', () => { - expect(Color.isDark('hsl(0,0,50)')).toEqual(false); - }); - }); - }); -}); diff --git a/apis/theme/src/utils/color/color.js b/apis/theme/src/utils/color/color.js deleted file mode 100644 index b2fb90f23..000000000 --- a/apis/theme/src/utils/color/color.js +++ /dev/null @@ -1,911 +0,0 @@ -/* eslint-disable no-param-reassign */ -/* eslint-disable camelcase */ -/* eslint-disable no-nested-ternary */ -/* eslint-disable no-cond-assign */ -/* eslint-disable prefer-destructuring */ -/* eslint-disable no-underscore-dangle */ - -import CSSColors from './css-colors'; - -/** - * Module which defines a color object - * @private - * @exports objects.views/charts/representation/color - * @expose module:objects.views/charts/representation/color~Color - */ - -// color formats -const rgb = /^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$/i; -const rgba = /^rgba\((\d{1,3}),(\d{1,3}),(\d{1,3}),(\d(\.\d+)?)\)$/i; -const hex = /^#([A-f0-9]{2})([A-f0-9]{2})([A-f0-9]{2})$/i; -const hexShort = /^#([A-f0-9])([A-f0-9])([A-f0-9])$/i; -const hsl = /^hsl\(\s*(\d+(\.\d+)?)\s*,\s*(\d+(\.\d+)?%?)\s*,\s*(\d+(\.\d+)?%?)\s*\)$/i; -const hsla = /^hsla\(\s*(\d+(\.\d+)?)\s*,\s*(\d+(\.\d+)?%?)\s*,\s*(\d+(\.\d+)?%?)\s*,(\d(\.\d+)?)\)$/i; -const { floor } = Math; -const { round } = Math; - -/** - * @class - * @classdesc Class which provides color transformation functionality - * @description This is a constructor. - * @private - * @param {object} - Parameters to create a color from different notations - * @example - * // a few ways of instantiating a red color - * var red; - * red = new Color(255, 0, 0, 1); // rgba as parameters - * red = new Color('#ff0000'); // hex - * red = new Color('rgb(255,0,0)');//rgb as string - * red = new Color('hsl(0, 100, 50)');// hsl as string - * red = new Color(16711680);// uint - */ -export default class Color { - constructor(...args) { - let r = 0; - let g = 0; - let b = 0; - let a = 1; - let h; - let s; - let lcs; - let l; - let v; - let c; - let h_; - let x; - let rgb_; - let m; - let matches; - let colorString; - - this._invalid = false; - - if (args[0] instanceof Color) { - r = args[0]._r; - g = args[0]._g; - b = args[0]._b; - a = args[0]._a; - this._invalid = args[0]._invalid; - } else if (args.length < 3) { - if (typeof args[0] === 'string') { - colorString = args[0]; - - if ((matches = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i.exec(colorString))) { - r = parseInt(matches[1], 10); - g = parseInt(matches[2], 10); - b = parseInt(matches[3], 10); - } else if ( - (matches = /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d(\.\d+)?)\s*\)$/i.exec(colorString)) - ) { - // rgba(1, 2, 3, 0.4) - r = parseInt(matches[1], 10); - g = parseInt(matches[2], 10); - b = parseInt(matches[3], 10); - a = parseFloat(matches[4]); - } else if ( - (matches = /^ARGB\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i.exec(colorString)) - ) { - // ARGB(255,255,255,255) - a = parseInt(matches[1], 10) / 255; - r = parseInt(matches[2], 10); - g = parseInt(matches[3], 10); - b = parseInt(matches[4], 10); - } else if ((matches = /^#([A-f0-9]{2})([A-f0-9]{2})([A-f0-9]{2})$/i.exec(colorString))) { - // #aBc123 - r = parseInt(matches[1], 16); - g = parseInt(matches[2], 16); - b = parseInt(matches[3], 16); - a = 1; - } else if ((matches = /^#([A-f0-9])([A-f0-9])([A-f0-9])$/i.exec(colorString))) { - // #a5F - r = parseInt(matches[1] + matches[1], 16); - g = parseInt(matches[2] + matches[2], 16); - b = parseInt(matches[3] + matches[3], 16); - a = 1; - } else if ( - (matches = /^hsl\(\s*(\d+(\.\d+)?)\s*,\s*(\d+(\.\d+)?%?)\s*,\s*(\d+(\.\d+)?%?)\s*\)$/i.exec(colorString)) - ) { - // hsl(1, 2, 3) - h = parseFloat(matches[1]); - s = parseFloat(matches[3]); - l = parseFloat(matches[5]); - - h %= 360; - s /= 100; - l /= 100; - - h = h < 0 ? 0 : h > 360 ? 360 : h; - s = s < 0 ? 0 : s > 1 ? 1 : s; - l = l < 0 ? 0 : l > 1 ? 1 : l; - - c = l <= 0.5 ? 2 * l * s : (2 - 2 * l) * s; - h_ = h / 60; - x = c * (1 - Math.abs((h_ % 2) - 1)); - - rgb_ = []; - - h_ = Math.floor(h_); - switch (h_) { - case 0: - rgb_ = [c, x, 0]; - break; - case 1: - rgb_ = [x, c, 0]; - break; - case 2: - rgb_ = [0, c, x]; - break; - case 3: - rgb_ = [0, x, c]; - break; - case 4: - rgb_ = [x, 0, c]; - break; - case 5: - rgb_ = [c, 0, x]; - break; - default: - rgb_ = [0, 0, 0]; - } - - m = l - 0.5 * c; - - r = rgb_[0] + m; - g = rgb_[1] + m; - b = rgb_[2] + m; - - r = round(255 * r); - g = round(255 * g); - b = round(255 * b); - a = 1.0; - } else if ( - (matches = /^hsla\(\s*(\d+(\.\d+)?)\s*,\s*(\d+(\.\d+)?%?)\s*,\s*(\d+(\.\d+)?%?)\s*,(\d(\.\d+)?)\)$/i.exec( - colorString - )) - ) { - // hsla(1,2,3,0.4) - h = parseFloat(matches[1]); - s = parseFloat(matches[3]); - l = parseFloat(matches[5]); - a = parseFloat(matches[7]); - - h %= 360; - s /= 100; - l /= 100; - - h = h < 0 ? 0 : h > 360 ? 360 : h; - s = s < 0 ? 0 : s > 1 ? 1 : s; - l = l < 0 ? 0 : l > 1 ? 1 : l; - - c = l <= 0.5 ? 2 * l * s : (2 - 2 * l) * s; - h_ = h / 60; - x = c * (1 - Math.abs((h_ % 2) - 1)); - - rgb_ = []; - - h_ = Math.floor(h_); - switch (h_) { - case 0: - rgb_ = [c, x, 0]; - break; - case 1: - rgb_ = [x, c, 0]; - break; - case 2: - rgb_ = [0, c, x]; - break; - case 3: - rgb_ = [0, x, c]; - break; - case 4: - rgb_ = [x, 0, c]; - break; - case 5: - rgb_ = [c, 0, x]; - break; - default: - rgb_ = [0, 0, 0]; - } - - m = l - 0.5 * c; - - r = rgb_[0] + m; - g = rgb_[1] + m; - b = rgb_[2] + m; - - r = round(255 * r); - g = round(255 * g); - b = round(255 * b); - } else if ( - (matches = /^hsv\(\s*(\d+(\.\d+)?)\s*,\s*(\d+(\.\d+)?%?)\s*,\s*(\d+(\.\d+)?%?)\s*\)$/i.exec(colorString)) - ) { - // hsv(1, 2, 3) { - h = parseFloat(matches[1]); - s = parseFloat(matches[3]); - v = parseFloat(matches[5]); - - h %= 360; - s /= 100; - v /= 100; - - h = h < 0 ? 0 : h > 360 ? 360 : h; - s = s < 0 ? 0 : s > 1 ? 1 : s; - v = v < 0 ? 0 : v > 1 ? 1 : v; - - c = v * s; - h_ = h / 60; - x = c * (1 - Math.abs((h_ % 2) - 1)); - - rgb_ = []; - - h_ = Math.floor(h_); - switch (h_) { - case 0: - rgb_ = [c, x, 0]; - break; - case 1: - rgb_ = [x, c, 0]; - break; - case 2: - rgb_ = [0, c, x]; - break; - case 3: - rgb_ = [0, x, c]; - break; - case 4: - rgb_ = [x, 0, c]; - break; - case 5: - rgb_ = [c, 0, x]; - break; - default: - rgb_ = [0, 0, 0]; - } - - m = v - c; - - r = rgb_[0] + m; - g = rgb_[1] + m; - b = rgb_[2] + m; - - r = round(255 * r); - g = round(255 * g); - b = round(255 * b); - a = 1.0; - } else if (CSSColors[colorString.toLowerCase()]) { - lcs = colorString.toLowerCase(); - r = CSSColors[lcs].r; - g = CSSColors[lcs].g; - b = CSSColors[lcs].b; - a = typeof CSSColors[lcs].a === 'number' ? CSSColors[lcs].a : 1.0; - } else { - this._invalid = true; - } - } else if (typeof args[0] === 'number' && args[0] >= 0 && args[1] === 'argb') { - a = (0xff000000 & args[0]) >>> 24; - a /= 255; - r = (0xff0000 & args[0]) >> 16; - g = (0x00ff00 & args[0]) >> 8; - b = 0x0000ff & args[0]; - } else if (typeof args[0] === 'number' && args[0] >= 0) { - r = (0xff0000 & args[0]) >> 16; - g = (0x00ff00 & args[0]) >> 8; - b = 0x0000ff & args[0]; - } else { - this._invalid = true; - } - } else if (args.length >= 3) { - r = args[0]; - g = args[1]; - b = args[2]; - a = arguments.length >= 4 ? args[3] : 1; - } else { - this._invalid = true; - } - - if (Number.isNaN(+r + g + b + a)) { - this._invalid = true; - } - - this._r = floor(r); - this._g = floor(g); - this._b = floor(b); - this._a = a; - - // object to cache string representations in various color spaces - this._spaces = {}; - } - - isInvalid() { - return this._invalid; - } - - /** - * Sets alpha value of color - * @private - * @param {number} a - Alpha value of the color - */ - setAlpha(a) { - this._a = a; - this._spaces = {}; - } - - /** - * Gets the alpha value of this color - * @private - * @returns {number} - */ - getAlpha() { - return this._a; - } - - /** - * Returns an rgb string representation of this color. - * @private - * @return {string} An rgb string representation of this color - */ - toRGB() { - if (!this._spaces.rgb) { - this._spaces.rgb = Color.toRGB(this); - } - return this._spaces.rgb; - } - - /** - * Returns an rgba string representation of this color. - * @private - * @return {string} An rgba string representation of this color. - */ - toRGBA() { - if (!this._spaces.rgba) { - this._spaces.rgba = Color.toRGBA(this); - } - return this._spaces.rgba; - } - - toString() { - if (!this._spaces.rgb) { - this._spaces.rgb = Color.toRGB(this); - } - return this._spaces.rgb; - } - - /** - * Returns a hex string representation of this color. - * @private - * @return {string} - */ - toHex() { - if (!this._spaces.hex) { - this._spaces.hex = Color.toHex(this); - } - return this._spaces.hex; - } - - /** - * Returns a hsl string representation of this color using "bi-hexcone" model for lightness - * @private - * @param {boolean} luma - Whether to use luma calculation - * @return {string} In format hsl(0,0,0) - */ - toHSL(luma) { - if (!this._spaces.hsl) { - this._spaces.hsl = Color.toHSL(this, luma); - } - return this._spaces.hsl; - } - - /** - * Returns a hsla string representation of this color using "bi-hexcone" model for lightness - * @private - * @param {boolean} luma - Whether to use luma calculation - * @return {string} In format hsla(0,0,0,0) - */ - toHSLA(luma) { - if (!this._spaces.hsla) { - this._spaces.hsla = Color.toHSLA(this, luma); - } - return this._spaces.hsla; - } - - /** - * Return the color components in hsv space using "hexcone" model for value (lightness) - * @private - * @param {Color|string} c - * @returns {object} The color components in hsv space {h:0-360, s:0-100, v:0-100} - */ - toHSV() { - const hsvComp = this.toHSVComponents(); - return `hsv(${hsvComp.h},${hsvComp.s},${hsvComp.v})`; - } - - /** - * Return the color components in hsv space using "hexcone" model for value (lightness) - * @private - * @param {Color|string} c - * @returns {object} The color components in hsv space {h:0-360, s:0-100, v:0-100} - */ - toHSVComponents() { - if (!this._spaces.hsvComp) { - this._spaces.hsvComp = Color.toHSVComponents(this); - } - return this._spaces.hsvComp; - } - - /** - * Returns a uint representation of this color - * @private - * @return {number} - */ - toNumber() { - if (!this._spaces.num) { - this._spaces.num = Color.toNumber(this); - } - return this._spaces.num; - } - - /** - * Checks if this color is perceived as dark. - * @private - * @return {string} True if the luminance is below 160, false otherwise. - */ - isDark() { - return this.isInvalid() || this.getLuminance() < 125; // luminace calc option #2 - // return this.getLuminance() < 160; //luminace calc option #3 - } - - /** - * Calculates the perceived luminance of the color. - * @private - * @return {number} A value in the range 0-255 where a low value is considered dark and vice versa. - */ - getLuminance() { - // alpha channel is not considered - if (typeof this._lumi === 'undefined') { - // calculate luminance - // this._lumi = 0.2126 * this._r + 0.7152 * this._g + 0.0722 * this._b; // option 1 - this._lumi = 0.299 * this._r + 0.587 * this._g + 0.114 * this._b; // option 2 - // this._lumi = Math.sqrt( 0.241 * this._r * this._r + 0.691 * this._g * this._g + 0.068 * this._b * this._b ); // option 3 - } - - return this._lumi; - } - - /** - * Shifts the color towards a lighter or darker shade - * @private - * @param {number} value - A value in the range -100-100 to shift the color with along the HSL lightness. - * @return {string} The shifted color as hsla string. - */ - shiftLuminance(value) { - const chsla = this.toHSLA(); - const matches = /^hsla\(\s*(\d+(\.\d+)?)\s*,\s*(\d+(\.\d+)?%?)\s*,\s*(\d+(\.\d+)?%?)\s*,(\d(\.\d+)?)\)$/i.exec( - chsla - ); - - const h = parseFloat(matches[1]); - const s = parseFloat(matches[3]); - let l = parseFloat(matches[5]); - const a = parseFloat(matches[7]); - // l *= 1 + value / 100; - // l = Math.max( 0, l % 100 ); - l += value; - l = Math.max(0, Math.min(l, 100)); - - // if( value > 0 ){ - // s = s*0.2; //removing saturation to avoid the border from being too light - // } - - return `hsla(${h},${s},${l},${a})`; - } - - /** - * Compares two colors. - * @private - * @param {Color} c The color to compare with. - * @return {boolean} True if the rgba channels are the same, false otherwise - */ - isEqual(c) { - if (c instanceof Color) { - return this._r === c._r && this._g === c._g && this._b === c._b && this._a === c._a; - } - - c = new Color(c); - return this._r === c._r && this._g === c._g && this._b === c._b && this._a === c._a; - } - - /** - * Linearly interpolates each channel of two colors. - * @private - * @param {Color} c2 The other color. - * @param {number} t The interpolation value in the range (0-1). - * @return {string} The blend as an rgb string. - */ - blend(c2, t) { - const r = floor(this._r + (c2._r - this._r) * t); - const g = floor(this._g + (c2._g - this._g) * t); - const b = floor(this._b + (c2._b - this._b) * t); - const a = floor(this._a + (c2._a - this._a) * t); - - return `rgba(${[r, g, b, a].join(',')})`; - } - - createShiftedColor(v) { - if (v === undefined || Number.isNaN(+v)) { - v = 1; - } - const lumi = this.getLuminance(); - const greenMultiplier = this._g < 126 ? 1 : 1 + this._g / 512; - const hsla_string = this.shiftLuminance( - (lumi * greenMultiplier < 220 ? 0.8 + 4 * (1 / (lumi + 1)) : -(0.8 + 1 * (lumi / 255))) * 20 * v - ); - - return new Color(hsla_string); - } - - /** - * Returns an rgb string representation of this color - * @private - * @param {Color|string} c - * @returns {string} An rgb string with channel values within range 0-255. - */ - static toRGB(c) { - if (c instanceof Color) { - return `rgb(${[c._r, c._g, c._b].join(',')})`; - } - - if (typeof c === 'string') { - c = Color.toNumber(c); - } - - const r = (c & 0xff0000) >> 16; - const g = (c & 0x00ff00) >> 8; - const b = c & 0x0000ff; - - return `rgb(${r},${g},${b})`; - } - - /** - * - * @private - * @param c - * @param a - * @returns {string} The color rgb format. - */ - static toRGBA(c, a) { - if (c instanceof Color) { - return `rgba(${[c._r, c._g, c._b, typeof a !== 'undefined' ? a : c._a].join(',')})`; - } - - if (typeof c === 'string') { - c = Color.toNumber(c); - } - - const r = (c & 0xff0000) >> 16; - const g = (c & 0x00ff00) >> 8; - const b = c & 0x0000ff; - - return `rgba(${r},${g},${b},${typeof a !== 'undefined' ? a : c._a})`; - } - - /** - * - * @private - * @param {Color|string} c - * @returns {string} The color in hexadecimal space. - */ - static toHex(c) { - let r; - let g; - let b; - if (c instanceof Color) { - r = c._r.toString(16); - g = c._g.toString(16); - b = c._b.toString(16); - if (r.length === 1) { - r = `0${r}`; - } - if (g.length === 1) { - g = `0${g}`; - } - if (b.length === 1) { - b = `0${b}`; - } - return `#${[r, g, b].join('')}`; - } - - if (typeof c === 'string') { - c = Color.toNumber(c); - } - - r = ((c & 0xff0000) >> 16).toString(16); - g = ((c & 0x00ff00) >> 8).toString(16); - b = (c & 0x0000ff).toString(16); - - if (r.length === 1) { - r = `0${r}`; - } - if (g.length === 1) { - g = `0${g}`; - } - if (b.length === 1) { - b = `0${b}`; - } - - return `#${r}${g}${b}`; - } - - /** - * Return the color in hsl space using "bi-hexcone" model for lightness - * @private - * @param {Color|string} c - * @param {boolean} luma - Whether to use luma calculation - * @returns {string} The color in hsl space. - */ - static toHSL(c, luma) { - let h = 0; - let s; - let l; - let ch; - if (typeof c === 'string') { - c = new Color(c); - } - - // red, green, blue, hue, saturation, lightness/luma, max, min, chroma - const r = c._r / 255; - const g = c._g / 255; - const b = c._b / 255; - - const max = Math.max(r, g, b); - const min = Math.min(r, g, b); - if (luma) { - // Y'709 http://en.wikipedia.org/wiki/Rec._709 - // Y′709 = 0.21R + 0.72G + 0.07B - l = 0.21 * r + 0.72 * g + 0.07 * b; - } else { - l = (max + min) / 2; - } - - if (max === min) { - // greyscale - s = 0; - h = 0; - } else { - ch = max - min; - s = l > 0.5 ? ch / (2 - max - min) : ch / (max + min); - switch (max) { - case r: - h = (g - b) / ch + (g < b ? 6 : 0); - break; - case g: - h = (b - r) / ch + 2; - break; - case b: - h = (r - g) / ch + 4; - break; - default: - break; - } - h /= 6; - } - - return `hsl(${h * 360},${s * 100},${l * 100})`; - } - - /** - * Return the color in hsla space using "bi-hexcone" model for lightness - * @private - * @param {Color|string} c - * @param {boolean} luma - Whether to use luma calculation - * @returns {string} The color in hsla space. - */ - static toHSLA(c, luma) { - let h = 0; - let s; - let l; - let ch; - if (typeof c === 'string') { - c = new Color(c); - } - - // red, green, blue, hue, saturation, lightness/luma, max, min, chroma - const r = c._r / 255; - const g = c._g / 255; - const b = c._b / 255; - const a = c._a; - - const max = Math.max(r, g, b); - const min = Math.min(r, g, b); - if (luma) { - // Y'709 http://en.wikipedia.org/wiki/Rec._709 - // Y′709 = 0.21R + 0.72G + 0.07B - l = 0.21 * r + 0.72 * g + 0.07 * b; - } else { - l = (max + min) / 2; - } - - if (max === min) { - // greyscale - s = 0; - h = 0; - } else { - ch = max - min; - s = l > 0.5 ? ch / (2 - max - min) : ch / (max + min); - switch (max) { - case r: - h = (g - b) / ch + (g < b ? 6 : 0); - break; - case g: - h = (b - r) / ch + 2; - break; - case b: - h = (r - g) / ch + 4; - break; - default: - break; - } - h /= 6; - } - - return `hsla(${h * 360},${s * 100},${l * 100},${a})`; - } - - /** - * Return the color components in hsv space using "hexcone" model for value (lightness) - * @private - * @param {Color|string} c - * @returns {object} The color components in hsv space {h:0-360, s:0-100, v:0-100} - */ - static toHSVComponents(c) { - let h = 0; - let s; - let ch; - if (typeof c === 'string') { - c = new Color(c); - } - - // red, green, blue, hue, saturation, value/luma, max, min, chroma - const r = c._r / 255; - const g = c._g / 255; - const b = c._b / 255; - - const max = Math.max(r, g, b); - const min = Math.min(r, g, b); - - const v = max; - - if (max === min) { - // greyscale - s = 0; - h = 0; - } else { - ch = max - min; - s = ch === 0 ? 0 : ch / v; - switch (max) { - case r: - h = (g - b) / ch + (g < b ? 6 : 0); - break; - case g: - h = (b - r) / ch + 2; - break; - case b: - h = (r - g) / ch + 4; - break; - default: - break; - } - h /= 6; - } - - return { h: (h * 360) % 360, s: s * 100, v: v * 100 }; - } - - /** - * Returns an number representation of the color - * @private - * @param {Color|string} c - * @returns {Number} Unsigned integer in the range 0-16 777 216 - */ - static toNumber(...args) { - if (args.length === 1 && args[0] instanceof Color) { - return (args[0]._r << 16) + (args[0]._g << 8) + args[0]._b; - } - - let r = 0; - let g = 0; - let b = 0; - let matches; - let colorString; - - if (args.length === 1) { - if (typeof args[0] === 'string') { - colorString = args[0]; - - if ((matches = /^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$/i.exec(colorString))) { - r = parseInt(matches[1], 10); - g = parseInt(matches[2], 10); - b = parseInt(matches[3], 10); - } else if ((matches = /^#([A-f0-9]{2})([A-f0-9]{2})([A-f0-9]{2})$/i.exec(colorString))) { - r = parseInt(matches[1], 16); - g = parseInt(matches[2], 16); - b = parseInt(matches[3], 16); - } else if ((matches = /^#([A-f0-9])([A-f0-9])([A-f0-9])$/i.exec(colorString))) { - r = parseInt(matches[1] + matches[1], 16); - g = parseInt(matches[2] + matches[2], 16); - b = parseInt(matches[3] + matches[3], 16); - } - } - } - return (r << 16) + (g << 8) + b; - } - - static blend(c1, c2, t) { - c1 = Color.toNumber(c1); - c2 = Color.toNumber(c2); - - const r1 = (c1 & 0xff0000) >> 16; - const g1 = (c1 & 0x00ff00) >> 8; - const b1 = c1 & 0x0000ff; - const r2 = (c2 & 0xff0000) >> 16; - const g2 = (c2 & 0x00ff00) >> 8; - const b2 = c2 & 0x0000ff; - const r = r1 + (r2 - r1) * t; - const g = g1 + (g2 - g1) * t; - const b = b1 + (b2 - b1) * t; - - return (r << 16) + (g << 8) + b; - } - - static getBlend(c1, c2, t) { - const r = c1._r + (c2._r - c1._r) * t; - const g = c1._g + (c2._g - c1._g) * t; - const b = c1._b + (c2._b - c1._b) * t; - const a = c1._a + (c2._a - c1._a) * t; - - return new Color(r, g, b, a); - } - - static isCSSColor(color) { - if (arguments.length > 1 || typeof color !== 'string') { - return false; - } - return ( - rgb.test(color) || - rgba.test(color) || - hex.test(color) || - hexShort.test(color) || - hsl.test(color) || - hsla.test(color) || - CSSColors[color.toLowerCase()] - ); - } - - static getBestContrast(color, cl, cd) { - const lum = color.getLuminance(); - return Math.abs(lum - cl.getLuminance()) > Math.abs(lum - cd.getLuminance()) ? cl : cd; - } - - static getContrast(color1, color2) { - if (!color1 || !color2) { - return undefined; - } - - const l1 = color1.getLuminance() / 100; - const l2 = color2.getLuminance() / 100; - - if (l1 > l2) { - return (l1 + 0.05) / (l2 + 0.05); - } - - return (l2 + 0.05) / (l1 + 0.05); - } - - static isDark(...args) { - const C = new Color(...args); - return C.isDark(...args); - } - - static useDarkLabel(areaColor, bgIsDark) { - return areaColor._a > 0.5 ? !areaColor.isDark() : !bgIsDark; - } -} diff --git a/apis/theme/src/utils/color/css-colors.js b/apis/theme/src/utils/color/css-colors.js deleted file mode 100644 index 03141a233..000000000 --- a/apis/theme/src/utils/color/css-colors.js +++ /dev/null @@ -1,157 +0,0 @@ -const colorStruct = { - aliceblue: { r: 240, g: 248, b: 255 }, - antiquewhite: { r: 250, g: 235, b: 215 }, - aqua: { r: 0, g: 255, b: 255 }, - aquamarine: { r: 127, g: 255, b: 212 }, - azure: { r: 240, g: 255, b: 255 }, - beige: { r: 245, g: 245, b: 220 }, - bisque: { r: 255, g: 228, b: 196 }, - black: { r: 0, g: 0, b: 0 }, - blanchedalmond: { r: 255, g: 235, b: 205 }, - blue: { r: 0, g: 0, b: 255 }, - blueviolet: { r: 138, g: 43, b: 226 }, - brown: { r: 165, g: 42, b: 42 }, - burlywood: { r: 222, g: 184, b: 135 }, - cadetblue: { r: 95, g: 158, b: 160 }, - chartreuse: { r: 127, g: 255, b: 0 }, - chocolate: { r: 210, g: 105, b: 30 }, - coral: { r: 255, g: 127, b: 80 }, - cornflowerblue: { r: 100, g: 149, b: 237 }, - cornsilk: { r: 255, g: 248, b: 220 }, - crimson: { r: 220, g: 20, b: 60 }, - cyan: { r: 0, g: 255, b: 255 }, - darkblue: { r: 0, g: 0, b: 139 }, - darkcyan: { r: 0, g: 139, b: 139 }, - darkgoldenrod: { r: 184, g: 134, b: 11 }, - darkgray: { r: 169, g: 169, b: 169 }, - darkgreen: { r: 0, g: 100, b: 0 }, - darkgrey: { r: 169, g: 169, b: 169 }, - darkkhaki: { r: 189, g: 183, b: 107 }, - darkmagenta: { r: 139, g: 0, b: 139 }, - darkolivegreen: { r: 85, g: 107, b: 47 }, - darkorange: { r: 255, g: 140, b: 0 }, - darkorchid: { r: 153, g: 50, b: 204 }, - darkred: { r: 139, g: 0, b: 0 }, - darksalmon: { r: 233, g: 150, b: 122 }, - darkseagreen: { r: 143, g: 188, b: 143 }, - darkslateblue: { r: 72, g: 61, b: 139 }, - darkslategray: { r: 47, g: 79, b: 79 }, - darkslategrey: { r: 47, g: 79, b: 79 }, - darkturquoise: { r: 0, g: 206, b: 209 }, - darkviolet: { r: 148, g: 0, b: 211 }, - deeppink: { r: 255, g: 20, b: 147 }, - deepskyblue: { r: 0, g: 191, b: 255 }, - dimgray: { r: 105, g: 105, b: 105 }, - dimgrey: { r: 105, g: 105, b: 105 }, - dodgerblue: { r: 30, g: 144, b: 255 }, - firebrick: { r: 178, g: 34, b: 34 }, - floralwhite: { r: 255, g: 250, b: 240 }, - forestgreen: { r: 34, g: 139, b: 34 }, - fuchsia: { r: 255, g: 0, b: 255 }, - gainsboro: { r: 220, g: 220, b: 220 }, - ghostwhite: { r: 248, g: 248, b: 255 }, - gold: { r: 255, g: 215, b: 0 }, - goldenrod: { r: 218, g: 165, b: 32 }, - gray: { r: 128, g: 128, b: 128 }, - green: { r: 0, g: 128, b: 0 }, - greenyellow: { r: 173, g: 255, b: 47 }, - grey: { r: 128, g: 128, b: 128 }, - honeydew: { r: 240, g: 255, b: 240 }, - hotpink: { r: 255, g: 105, b: 180 }, - indianred: { r: 205, g: 92, b: 92 }, - indigo: { r: 75, g: 0, b: 130 }, - ivory: { r: 255, g: 255, b: 240 }, - khaki: { r: 240, g: 230, b: 140 }, - lavender: { r: 230, g: 230, b: 250 }, - lavenderblush: { r: 255, g: 240, b: 245 }, - lawngreen: { r: 124, g: 252, b: 0 }, - lemonchiffon: { r: 255, g: 250, b: 205 }, - lightblue: { r: 173, g: 216, b: 230 }, - lightcoral: { r: 240, g: 128, b: 128 }, - lightcyan: { r: 224, g: 255, b: 255 }, - lightgoldenrodyellow: { r: 250, g: 250, b: 210 }, - lightgray: { r: 211, g: 211, b: 211 }, - lightgreen: { r: 144, g: 238, b: 144 }, - lightgrey: { r: 211, g: 211, b: 211 }, - lightpink: { r: 255, g: 182, b: 193 }, - lightsalmon: { r: 255, g: 160, b: 122 }, - lightseagreen: { r: 32, g: 178, b: 170 }, - lightskyblue: { r: 135, g: 206, b: 250 }, - lightslategray: { r: 119, g: 136, b: 153 }, - lightslategrey: { r: 119, g: 136, b: 153 }, - lightsteelblue: { r: 176, g: 196, b: 222 }, - lightyellow: { r: 255, g: 255, b: 224 }, - lime: { r: 0, g: 255, b: 0 }, - limegreen: { r: 50, g: 205, b: 50 }, - linen: { r: 250, g: 240, b: 230 }, - magenta: { r: 255, g: 0, b: 255 }, - maroon: { r: 128, g: 0, b: 0 }, - mediumaquamarine: { r: 102, g: 205, b: 170 }, - mediumblue: { r: 0, g: 0, b: 205 }, - mediumorchid: { r: 186, g: 85, b: 211 }, - mediumpurple: { r: 147, g: 112, b: 219 }, - mediumseagreen: { r: 60, g: 179, b: 113 }, - mediumslateblue: { r: 123, g: 104, b: 238 }, - mediumspringgreen: { r: 0, g: 250, b: 154 }, - mediumturquoise: { r: 72, g: 209, b: 204 }, - mediumvioletred: { r: 199, g: 21, b: 133 }, - midnightblue: { r: 25, g: 25, b: 112 }, - mintcream: { r: 245, g: 255, b: 250 }, - mistyrose: { r: 255, g: 228, b: 225 }, - moccasin: { r: 255, g: 228, b: 181 }, - navajowhite: { r: 255, g: 222, b: 173 }, - navy: { r: 0, g: 0, b: 128 }, - oldlace: { r: 253, g: 245, b: 230 }, - olive: { r: 128, g: 128, b: 0 }, - olivedrab: { r: 107, g: 142, b: 35 }, - orange: { r: 255, g: 165, b: 0 }, - orangered: { r: 255, g: 69, b: 0 }, - orchid: { r: 218, g: 112, b: 214 }, - palegoldenrod: { r: 238, g: 232, b: 170 }, - palegreen: { r: 152, g: 251, b: 152 }, - paleturquoise: { r: 175, g: 238, b: 238 }, - palevioletred: { r: 219, g: 112, b: 147 }, - papayawhip: { r: 255, g: 239, b: 213 }, - peachpuff: { r: 255, g: 218, b: 185 }, - peru: { r: 205, g: 133, b: 63 }, - pink: { r: 255, g: 192, b: 203 }, - plum: { r: 221, g: 160, b: 221 }, - powderblue: { r: 176, g: 224, b: 230 }, - purple: { r: 128, g: 0, b: 128 }, - red: { r: 255, g: 0, b: 0 }, - rosybrown: { r: 188, g: 143, b: 143 }, - royalblue: { r: 65, g: 105, b: 225 }, - saddlebrown: { r: 139, g: 69, b: 19 }, - salmon: { r: 250, g: 128, b: 114 }, - sandybrown: { r: 244, g: 164, b: 96 }, - seagreen: { r: 46, g: 139, b: 87 }, - seashell: { r: 255, g: 245, b: 238 }, - sienna: { r: 160, g: 82, b: 45 }, - silver: { r: 192, g: 192, b: 192 }, - skyblue: { r: 135, g: 206, b: 235 }, - slateblue: { r: 106, g: 90, b: 205 }, - slategray: { r: 112, g: 128, b: 144 }, - slategrey: { r: 112, g: 128, b: 144 }, - snow: { r: 255, g: 250, b: 250 }, - springgreen: { r: 0, g: 255, b: 127 }, - steelblue: { r: 70, g: 130, b: 180 }, - tan: { r: 210, g: 180, b: 140 }, - teal: { r: 0, g: 128, b: 128 }, - thistle: { r: 216, g: 191, b: 216 }, - tomato: { r: 255, g: 99, b: 71 }, - transparent: { - r: 255, - g: 255, - b: 255, - a: 0, - }, - turquoise: { r: 64, g: 224, b: 208 }, - violet: { r: 238, g: 130, b: 238 }, - wheat: { r: 245, g: 222, b: 179 }, - white: { r: 255, g: 255, b: 255 }, - whitesmoke: { r: 245, g: 245, b: 245 }, - yellow: { r: 255, g: 255, b: 0 }, - yellowgreen: { r: 154, g: 205, b: 50 }, -}; - -export default colorStruct; diff --git a/apis/theme/src/utils/color/index.js b/apis/theme/src/utils/color/index.js deleted file mode 100644 index 5da93fd2a..000000000 --- a/apis/theme/src/utils/color/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Color from './color'; - -export default Color; diff --git a/yarn.lock b/yarn.lock index aa913c957..ee2a8515c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7108,11 +7108,6 @@ csstype@^3.1.3: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== -d3-color@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" - integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== - d3-require@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/d3-require/-/d3-require-1.3.0.tgz#2b97f5e2ebcb64ac0c63c11f30056aea1c74f0ec" @@ -14703,6 +14698,11 @@ qix-faker@0.3.0: dependencies: faker "^4.1.0" +qlik-chart-modules@0.77.0: + version "0.77.0" + resolved "https://registry.yarnpkg.com/qlik-chart-modules/-/qlik-chart-modules-0.77.0.tgz#37aa0b54967a809b819e100ea55bfcda01c5b8ea" + integrity sha512-0FcEIshl+f2YBKDgDPGR+lCC6rWJBViPnty5a17qtJHAOcn3Lar/9NY0YPPk3O+Vxm/4pDbXpUN72x4U/0al1Q== + qs@6.10.3: version "6.10.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" @@ -16145,7 +16145,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -16171,15 +16171,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -16328,7 +16319,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -16356,13 +16347,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -17603,7 +17587,7 @@ wordwrap@~0.0.2: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" integrity sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -17630,15 +17614,6 @@ wrap-ansi@^6.0.1: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"