diff --git a/package-lock.json b/package-lock.json
index 6e6ea7cf9a9..245089157ce 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,6 +19,7 @@
"@turf/centroid": "^7.1.0",
"base64-arraybuffer": "^1.0.2",
"canvas-fit": "^1.5.0",
+ "color": "^5.0.0",
"color-alpha": "1.0.4",
"color-normalize": "1.5.0",
"color-parse": "2.0.0",
@@ -2738,6 +2739,19 @@
"node": ">=0.8"
}
},
+ "node_modules/color": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/color/-/color-5.0.0.tgz",
+ "integrity": "sha512-16BlyiuyLq3MLxpRWyOTiWsO3ii/eLQLJUQXBSNcxMBBSnyt1ee9YUdaozQp03ifwm5woztEZGDbk9RGVuCsdw==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^3.0.1",
+ "color-string": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/color-alpha": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/color-alpha/-/color-alpha-1.0.4.tgz",
@@ -2835,6 +2849,48 @@
"integrity": "sha512-nKqUYlo0vZATVOFHY810BSYjmCARrG7e5R3UE3CQlyjJTvv5kSSmPG1kzm/oDyyqjehM+lW1RnEt9It9GNa5JA==",
"license": "MIT"
},
+ "node_modules/color-string": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.0.1.tgz",
+ "integrity": "sha512-5z9FbYTZPAo8iKsNEqRNv+OlpBbDcoE+SY9GjLfDUHEfcNNV7tS9eSAlFHEaub/r5tBL9LtskAeq1l9SaoZ5tQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/color-string/node_modules/color-name": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.0.tgz",
+ "integrity": "sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20"
+ }
+ },
+ "node_modules/color/node_modules/color-convert": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.0.tgz",
+ "integrity": "sha512-TVoqAq8ZDIpK5lsQY874DDnu65CSsc9vzq0wLpNQ6UMBq81GSZocVazPiBbYGzngzBOIRahpkTzCLVe2at4MfA==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.6"
+ }
+ },
+ "node_modules/color/node_modules/color-name": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.0.tgz",
+ "integrity": "sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20"
+ }
+ },
"node_modules/colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
@@ -3166,6 +3222,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
"integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "license": "ISC",
"engines": {
"node": ">=12"
}
@@ -10037,12 +10094,10 @@
}
},
"node_modules/tinycolor2": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
- "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==",
- "engines": {
- "node": "*"
- }
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
+ "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==",
+ "license": "MIT"
},
"node_modules/tinyqueue": {
"version": "2.0.3",
diff --git a/package.json b/package.json
index afef26c7980..dffda8af19a 100644
--- a/package.json
+++ b/package.json
@@ -77,6 +77,7 @@
"@turf/centroid": "^7.1.0",
"base64-arraybuffer": "^1.0.2",
"canvas-fit": "^1.5.0",
+ "color": "^5.0.0",
"color-alpha": "1.0.4",
"color-normalize": "1.5.0",
"color-parse": "2.0.0",
diff --git a/src/components/color/attributes.js b/src/components/color/attributes.js
index 710cc5eb145..7823787f164 100644
--- a/src/components/color/attributes.js
+++ b/src/components/color/attributes.js
@@ -25,6 +25,6 @@ exports.borderLine = '#BEC8D9';
// with axis.color and Color.interp we aren't using lightLine
// itself anymore, instead interpolating between axis.color
-// and the background color using tinycolor.mix. lightFraction
+// and the background color using Color.mix. lightFraction
// gives back exactly lightLine if the other colors are defaults.
exports.lightFraction = 100 * (0xe - 0x4) / (0xf - 0x4);
diff --git a/src/components/color/index.js b/src/components/color/index.js
index 50eccc4a73e..4af743babcc 100644
--- a/src/components/color/index.js
+++ b/src/components/color/index.js
@@ -1,56 +1,48 @@
'use strict';
-var tinycolor = require('tinycolor2');
-var isNumeric = require('fast-isnumeric');
-var isTypedArray = require('../../lib/array').isTypedArray;
+const isNumeric = require('fast-isnumeric');
+const isTypedArray = require('../../lib/array').isTypedArray;
+const color = require('color').default
-var color = module.exports = {};
+const { background, defaultLine, defaults, lightLine } = require('./attributes');
-var colorAttrs = require('./attributes');
-color.defaults = colorAttrs.defaults;
-var defaultLine = color.defaultLine = colorAttrs.defaultLine;
-color.lightLine = colorAttrs.lightLine;
-var background = color.background = colorAttrs.background;
-
-/*
- * tinyRGB: turn a tinycolor into an rgb string, but
- * unlike the built-in tinycolor.toRgbString this never includes alpha
- */
-color.tinyRGB = function(tc) {
- var c = tc.toRgb();
- return 'rgb(' + Math.round(c.r) + ', ' +
- Math.round(c.g) + ', ' + Math.round(c.b) + ')';
-};
-
-color.rgb = function(cstr) { return color.tinyRGB(tinycolor(cstr)); };
+const rgb = cstr => {
+ const { r, g, b } = color(cstr).rgb().object();
+ return `rgb(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)})`;
+}
-color.opacity = function(cstr) { return cstr ? tinycolor(cstr).getAlpha() : 0; };
+const opacity = cstr => cstr ? color(cstr).alpha() : 0;
-color.addOpacity = function(cstr, op) {
- var c = tinycolor(cstr).toRgb();
- return 'rgba(' + Math.round(c.r) + ', ' +
- Math.round(c.g) + ', ' + Math.round(c.b) + ', ' + op + ')';
+const addOpacity = (cstr, op) => {
+ const c = color(cstr).rgb().object();
+ return `rgba(${Math.round(c.r)}, ${Math.round(c.g)}, ${Math.round(c.b)}, ${op})`;
};
// combine two colors into one apparent color
// if back has transparency or is missing,
-// color.background is assumed behind it
-color.combine = function(front, back) {
- var fc = tinycolor(front).toRgb();
- if(fc.a === 1) return tinycolor(front).toRgbString();
-
- var bc = tinycolor(back || background).toRgb();
- var bcflat = bc.a === 1 ? bc : {
- r: 255 * (1 - bc.a) + bc.r * bc.a,
- g: 255 * (1 - bc.a) + bc.g * bc.a,
- b: 255 * (1 - bc.a) + bc.b * bc.a
+// background is assumed behind it
+const combine = (front, back = background) => {
+ const fc = color(front).rgb().object();
+ fc.alpha ||= 1;
+ if(fc.alpha === 1) return color(front).rgb().string();
+
+ const bc = color(back).rgb().object();
+ bc.alpha ||= 1;
+ const bcflat = bc.alpha === 1
+ ? bc
+ : {
+ r: 255 * (1 - bc.alpha) + bc.r * bc.alpha,
+ g: 255 * (1 - bc.alpha) + bc.g * bc.alpha,
+ b: 255 * (1 - bc.alpha) + bc.b * bc.alpha
+ };
+
+ const fcflat = {
+ r: bcflat.r * (1 - fc.alpha) + fc.r * fc.alpha,
+ g: bcflat.g * (1 - fc.alpha) + fc.g * fc.alpha,
+ b: bcflat.b * (1 - fc.alpha) + fc.b * fc.alpha
};
- var fcflat = {
- r: bcflat.r * (1 - fc.a) + fc.r * fc.a,
- g: bcflat.g * (1 - fc.a) + fc.g * fc.a,
- b: bcflat.b * (1 - fc.a) + fc.b * fc.a
- };
- return tinycolor(fcflat).toRgbString();
+
+ return color(fcflat).string();
};
/*
@@ -59,17 +51,17 @@ color.combine = function(front, back) {
* Ignores alpha channel values.
* The resulting color is computed as: factor * first + (1 - factor) * second.
*/
-color.interpolate = function(first, second, factor) {
- var fc = tinycolor(first).toRgb();
- var sc = tinycolor(second).toRgb();
+const interpolate = (first, second, factor) => {
+ const fc = color(first).rgb().object();
+ const sc = color(second).rgb().object();
- var ic = {
+ const ic = {
r: factor * fc.r + (1 - factor) * sc.r,
g: factor * fc.g + (1 - factor) * sc.g,
b: factor * fc.b + (1 - factor) * sc.b,
};
- return tinycolor(ic).toRgbString();
+ return color(ic).rgb().string();
};
/*
@@ -80,34 +72,28 @@ color.interpolate = function(first, second, factor) {
* If lightAmount / darkAmount are used, we adjust by these percentages,
* otherwise we go all the way to white or black.
*/
-color.contrast = function(cstr, lightAmount, darkAmount) {
- var tc = tinycolor(cstr);
+const contrast = (cstr, lightAmount, darkAmount) => {
+ let c = color(cstr)
- if(tc.getAlpha() !== 1) tc = tinycolor(color.combine(cstr, background));
+ if(c.alpha() !== 1) c = color(combine(cstr, background));
- var newColor = tc.isDark() ?
- (lightAmount ? tc.lighten(lightAmount) : background) :
- (darkAmount ? tc.darken(darkAmount) : defaultLine);
+ // TODO: Should the API change such that lightAmount/darkAmount are passed in as decimal instead of percent number?
+ const newColor = color(
+ c.isDark()
+ ? (lightAmount ? c.lighten(lightAmount / 100) : background)
+ : (darkAmount ? c.darken(darkAmount / 100) : defaultLine)
+ );
- return newColor.toString();
+ return newColor.rgb().string();
};
-color.stroke = function(s, c) {
- var tc = tinycolor(c);
- s.style({stroke: color.tinyRGB(tc), 'stroke-opacity': tc.getAlpha()});
-};
+const stroke = (s, cstr) => s.style({ stroke: rgb(cstr), 'stroke-opacity': opacity(cstr) });
-color.fill = function(s, c) {
- var tc = tinycolor(c);
- s.style({
- fill: color.tinyRGB(tc),
- 'fill-opacity': tc.getAlpha()
- });
-};
+const fill = (s, cstr) => s.style({ fill: rgb(cstr), 'fill-opacity': opacity(cstr) });
// search container for colors with the deprecated rgb(fractions) format
// and convert them to rgb(0-255 values)
-color.clean = function(container) {
+const clean = container => {
if(!container || typeof container !== 'object') return;
var keys = Object.keys(container);
@@ -134,13 +120,13 @@ color.clean = function(container) {
var el0 = val[0];
if(!Array.isArray(el0) && el0 && typeof el0 === 'object') {
- for(j = 0; j < val.length; j++) color.clean(val[j]);
+ for(j = 0; j < val.length; j++) clean(val[j]);
}
- } else if(val && typeof val === 'object' && !isTypedArray(val)) color.clean(val);
+ } else if(val && typeof val === 'object' && !isTypedArray(val)) clean(val);
}
};
-function cleanOne(val) {
+const cleanOne = val => {
if(isNumeric(val) || typeof val !== 'string') return val;
var valTrim = val.trim();
@@ -181,3 +167,51 @@ function cleanOne(val) {
if(rgba) return 'rgba(' + rgbStr + ', ' + parts[3] + ')';
return 'rgb(' + rgbStr + ')';
}
+
+const equals = (cstr1, cstr2) => cstr1 && cstr2 && color(cstr1).rgb().string() === color(cstr2).rgb().string();
+
+const isValid = cstr => {
+ try { return cstr && !!color(cstr); }
+ catch { return false; }
+}
+
+const mix = (cstr1, cstr2, weight) => color(cstr1).mix(color(cstr2), weight / 100).rgb().string();
+
+const mostReadable = (baseColor, colorList = []) => {
+ let bestColor;
+ let bestContrast = -Infinity;
+
+ for (const cstr of colorList) {
+ const contrast = color(baseColor).contrast(color(cstr));
+ if (contrast > bestContrast) {
+ bestContrast = contrast;
+ bestColor = color(cstr).rgb().string();
+ }
+ }
+
+ // Fall back to black/white if provided colors don't have proper contrast level
+ return bestColor && color(baseColor).level(color(bestColor))
+ ? bestColor
+ : mostReadable(baseColor, ["#000", "#fff"]);
+};
+
+module.exports = {
+ addOpacity,
+ background,
+ clean,
+ color,
+ combine,
+ contrast,
+ defaultLine,
+ defaults,
+ equals,
+ fill,
+ interpolate,
+ isValid,
+ lightLine,
+ mix,
+ mostReadable,
+ opacity,
+ rgb,
+ stroke
+}
diff --git a/src/components/colorbar/draw.js b/src/components/colorbar/draw.js
index 794ff699918..0c2401e1ede 100644
--- a/src/components/colorbar/draw.js
+++ b/src/components/colorbar/draw.js
@@ -1,7 +1,6 @@
'use strict';
var d3 = require('@plotly/d3');
-var tinycolor = require('tinycolor2');
var Plots = require('../../plots/plots');
var Registry = require('../../registry');
@@ -548,10 +547,9 @@ function drawColorBar(g, opts, gd) {
if(opts._fillgradient) {
Drawing.gradient(fillEl, gd, opts._id, isVertical ? 'vertical' : 'horizontalreversed', opts._fillgradient, 'fill');
} else {
- // tinycolor can't handle exponents and
- // at this scale, removing it makes no difference.
+ // The color library can't handle exponents and at this scale, removing it makes no difference.
var colorString = fillColormap(d).replace('e-', '');
- fillEl.attr('fill', tinycolor(colorString).toHexString());
+ fillEl.attr('fill', Color.color(colorString).hex());
}
});
@@ -716,8 +714,8 @@ function drawColorBar(g, opts, gd) {
if(!isVertical && (
borderwidth || (
- tinycolor(bgcolor).getAlpha() &&
- !tinycolor.equals(fullLayout.paper_bgcolor, bgcolor)
+ Color.opacity(bgcolor) &&
+ !Color.equals(fullLayout.paper_bgcolor, bgcolor)
)
)) {
// for horizontal colorbars when there is a border line or having different background color
diff --git a/src/components/colorscale/helpers.js b/src/components/colorscale/helpers.js
index bc476e0a9b5..275b134fc35 100644
--- a/src/components/colorscale/helpers.js
+++ b/src/components/colorscale/helpers.js
@@ -1,7 +1,6 @@
'use strict';
var d3 = require('@plotly/d3');
-var tinycolor = require('tinycolor2');
var isNumeric = require('fast-isnumeric');
var Lib = require('../../lib');
@@ -167,8 +166,8 @@ function makeColorScaleFunc(specs, opts) {
var _range = new Array(N);
for(var i = 0; i < N; i++) {
- var rgba = tinycolor(range[i]).toRgb();
- _range[i] = [rgba.r, rgba.g, rgba.b, rgba.a];
+ const { r, g, b, alpha = 1 } = Color.color(range[i]).rgb().object();
+ _range[i] = [r, g, b, alpha];
}
var _sclFunc = d3.scale.linear()
@@ -189,14 +188,14 @@ function makeColorScaleFunc(specs, opts) {
} else if(returnArray) {
sclFunc = function(v) {
if(isNumeric(v)) return _sclFunc(v);
- else if(tinycolor(v).isValid()) return v;
- else return Color.defaultLine;
+ if(Color.isValid(v)) return v;
+ return Color.defaultLine;
};
} else {
sclFunc = function(v) {
if(isNumeric(v)) return colorArray2rbga(_sclFunc(v));
- else if(tinycolor(v).isValid()) return v;
- else return Color.defaultLine;
+ if(Color.isValid(v)) return v;
+ return Color.defaultLine;
};
}
@@ -216,10 +215,10 @@ function colorArray2rbga(colorArray) {
r: colorArray[0],
g: colorArray[1],
b: colorArray[2],
- a: colorArray[3]
+ alpha: colorArray[3]
};
- return tinycolor(colorObj).toRgbString();
+ return Color.color(colorObj).rgb().string();
}
module.exports = {
diff --git a/src/components/colorscale/scales.js b/src/components/colorscale/scales.js
index 7230f458bc7..c2cef9f44ff 100644
--- a/src/components/colorscale/scales.js
+++ b/src/components/colorscale/scales.js
@@ -1,6 +1,6 @@
'use strict';
-var tinycolor = require('tinycolor2');
+const Color = require('../color');
var scales = {
Greys: [
@@ -170,7 +170,7 @@ function isValidScaleArray(scl) {
for(var i = 0; i < scl.length; i++) {
var si = scl[i];
- if(si.length !== 2 || +si[0] < highestVal || !tinycolor(si[1]).isValid()) {
+ if(si.length !== 2 || +si[0] < highestVal || !Color.isValid(si[1])) {
return false;
}
diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js
index 3cb3b447eeb..73be5ab8f9b 100644
--- a/src/components/drawing/index.js
+++ b/src/components/drawing/index.js
@@ -4,7 +4,6 @@ var d3 = require('@plotly/d3');
var Lib = require('../../lib');
var numberFormat = Lib.numberFormat;
var isNumeric = require('fast-isnumeric');
-var tinycolor = require('tinycolor2');
var Registry = require('../../registry');
var Color = require('../color');
@@ -491,11 +490,10 @@ function gradientWithBounds(sel, gd, gradientID, type, colorscale, prop, start,
stops.enter().append('stop');
stops.each(function(d) {
- var tc = tinycolor(d[1]);
d3.select(this).attr({
offset: d[0] + '%',
- 'stop-color': Color.tinyRGB(tc),
- 'stop-opacity': tc.getAlpha()
+ 'stop-color': Color.rgb(d[1]),
+ 'stop-opacity': Color.opacity(d[1])
});
});
});
@@ -549,9 +547,8 @@ drawing.pattern = function(sel, calledBy, gd, patternID, shape, size, solidity,
var patternTag;
var patternAttrs = {};
- var fgC = tinycolor(fgcolor);
- var fgRGB = Color.tinyRGB(fgC);
- var fgAlpha = fgC.getAlpha();
+ var fgRGB = Color.rgb(fgcolor);
+ var fgAlpha = Color.opacity(fgcolor);
var opacity = fgopacity * fgAlpha;
switch(shape) {
@@ -704,9 +701,8 @@ drawing.pattern = function(sel, calledBy, gd, patternID, shape, size, solidity,
});
if(bgcolor) {
- var bgC = tinycolor(bgcolor);
- var bgRGB = Color.tinyRGB(bgC);
- var bgAlpha = bgC.getAlpha();
+ var bgRGB = Color.rgb(bgcolor);
+ var bgAlpha = Color.opacity(bgcolor);
var rects = el.selectAll('rect').data([0]);
rects.exit().remove();
diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js
index 41ee1352f62..e72c7a31d8c 100644
--- a/src/components/fx/hover.js
+++ b/src/components/fx/hover.js
@@ -2,7 +2,6 @@
var d3 = require('@plotly/d3');
var isNumeric = require('fast-isnumeric');
-var tinycolor = require('tinycolor2');
var Lib = require('../../lib');
var pushUnique = Lib.pushUnique;
@@ -2128,8 +2127,9 @@ function createSpikelines(gd, closestPoints, opts) {
hLinePointX = xa._offset + hLinePoint.x;
hLinePointY = ya._offset + hLinePoint.y;
}
- var dfltHLineColor = tinycolor.readability(hLinePoint.color, contrastColor) < 1.5 ?
- Color.contrast(contrastColor) : hLinePoint.color;
+ var dfltHLineColor = Color.color(hLinePoint.color).contrast(Color.color(contrastColor)) < 1.5
+ ? Color.contrast(contrastColor)
+ : hLinePoint.color;
var yMode = ya.spikemode;
var yThickness = ya.spikethickness;
var yColor = ya.spikecolor || dfltHLineColor;
@@ -2207,8 +2207,10 @@ function createSpikelines(gd, closestPoints, opts) {
vLinePointX = xa._offset + vLinePoint.x;
vLinePointY = ya._offset + vLinePoint.y;
}
- var dfltVLineColor = tinycolor.readability(vLinePoint.color, contrastColor) < 1.5 ?
- Color.contrast(contrastColor) : vLinePoint.color;
+
+ var dfltVLineColor = Color.color(vLinePoint.color).contrast(Color.color(contrastColor)) < 1.5
+ ? Color.contrast(contrastColor)
+ : vLinePoint.color;
var xMode = xa.spikemode;
var xThickness = xa.spikethickness;
var xColor = xa.spikecolor || dfltVLineColor;
diff --git a/src/lib/coerce.js b/src/lib/coerce.js
index 9fa59255bc1..bad6067c23b 100644
--- a/src/lib/coerce.js
+++ b/src/lib/coerce.js
@@ -1,7 +1,6 @@
'use strict';
var isNumeric = require('fast-isnumeric');
-var tinycolor = require('tinycolor2');
var extendFlat = require('./extend').extendFlat;
@@ -169,7 +168,7 @@ exports.valObjectMeta = {
coerceFunction: function(v, propOut, dflt) {
if(isTypedArraySpec(v)) v = decodeTypedArraySpec(v);
- if(tinycolor(v).isValid()) propOut.set(v);
+ if(Color.isValid(v)) propOut.set(v);
else propOut.set(dflt);
}
},
@@ -181,11 +180,8 @@ exports.valObjectMeta = {
requiredOpts: [],
otherOpts: ['dflt'],
coerceFunction: function(v, propOut, dflt) {
- function isColor(color) {
- return tinycolor(color).isValid();
- }
if(!Array.isArray(v) || !v.length) propOut.set(dflt);
- else if(v.every(isColor)) propOut.set(v);
+ else if(v.every(color => Color.isValid(color))) propOut.set(v);
else propOut.set(dflt);
}
},
@@ -454,7 +450,7 @@ exports.coerce = function(containerIn, containerOut, attributes, attribute, dflt
* Variation on coerce
*
* Uses coerce to get attribute value if user input is valid,
- * returns attribute default if user input it not valid or
+ * returns attribute default if user input is not valid or
* returns false if there is no user input.
*/
exports.coerce2 = function(containerIn, containerOut, attributes, attribute, dflt) {
diff --git a/src/lib/gl_format_color.js b/src/lib/gl_format_color.js
index e42170c3d2d..ff4f8c38afc 100644
--- a/src/lib/gl_format_color.js
+++ b/src/lib/gl_format_color.js
@@ -1,10 +1,10 @@
'use strict';
var isNumeric = require('fast-isnumeric');
-var tinycolor = require('tinycolor2');
var rgba = require('color-normalize');
var Colorscale = require('../components/colorscale');
+var Color = require('../components/color');
var colorDflt = require('../components/color/attributes').defaultLine;
var isArrayOrTypedArray = require('./array').isArrayOrTypedArray;
@@ -78,11 +78,10 @@ function parseColorScale(cont) {
return colorscale.map(function(elem) {
var index = elem[0];
- var color = tinycolor(elem[1]);
- var rgb = color.toRgb();
+ const { r, g, b, alpha = 1 } = Color.color(elem[1]).rgb().object();
return {
index: index,
- rgb: [rgb.r, rgb.g, rgb.b, rgb.a]
+ rgb: [r, g, b, alpha]
};
});
}
diff --git a/src/plot_api/helpers.js b/src/plot_api/helpers.js
index d57be1bc622..c72539e884a 100644
--- a/src/plot_api/helpers.js
+++ b/src/plot_api/helpers.js
@@ -139,8 +139,7 @@ exports.cleanLayout = function(layout) {
*/
if(layout.dragmode === 'rotate') layout.dragmode = 'orbit';
- // sanitize rgb(fractions) and rgba(fractions) that old tinycolor
- // supported, but new tinycolor does not because they're not valid css
+ // sanitize rgb(fractions) and rgba(fractions) because they're not valid css
Color.clean(layout);
// clean the layout container in layout.template
@@ -277,8 +276,7 @@ exports.cleanData = function(data) {
if(emptyContainer(trace, 'marker')) delete trace.marker;
}
- // sanitize rgb(fractions) and rgba(fractions) that old tinycolor
- // supported, but new tinycolor does not because they're not valid css
+ // sanitize rgb(fractions) and rgba(fractions) because they're not valid css
Color.clean(trace);
// remove obsolete autobin(x|y) attributes, but only if true
diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js
index f8fa211ad8f..7972b949021 100644
--- a/src/plots/cartesian/dragbox.js
+++ b/src/plots/cartesian/dragbox.js
@@ -3,7 +3,6 @@
var d3 = require('@plotly/d3');
var Lib = require('../../lib');
var numberFormat = Lib.numberFormat;
-var tinycolor = require('tinycolor2');
var supportsPassive = require('has-passive-events');
var Registry = require('../../registry');
@@ -334,9 +333,9 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) {
y0 = transformedCoords[1];
box = {l: x0, r: x0, w: 0, t: y0, b: y0, h: 0};
- lum = gd._hmpixcount ?
- (gd._hmlumcount / gd._hmpixcount) :
- tinycolor(gd._fullLayout.plot_bgcolor).getLuminance();
+ lum = gd._hmpixcount
+ ? (gd._hmlumcount / gd._hmpixcount)
+ : Color.color(gd._fullLayout.plot_bgcolor).luminosity();
path0 = 'M0,0H' + pw + 'V' + ph + 'H0V0';
dimmed = false;
zoomMode = 'xy';
diff --git a/src/plots/cartesian/line_grid_defaults.js b/src/plots/cartesian/line_grid_defaults.js
index 8808c31f7dd..bc31edc9f74 100644
--- a/src/plots/cartesian/line_grid_defaults.js
+++ b/src/plots/cartesian/line_grid_defaults.js
@@ -1,6 +1,6 @@
'use strict';
-var colorMix = require('tinycolor2').mix;
+const Color = require('../../components/color');
var colorAttrs = require('../../components/color/attributes');
var Lib = require('../../lib');
@@ -32,7 +32,7 @@ module.exports = function handleLineGridDefaults(containerIn, containerOut, coer
delete containerOut.linewidth;
}
- var gridColorDflt = colorMix(dfltColor, opts.bgColor, opts.blend || colorAttrs.lightFraction).toRgbString();
+ var gridColorDflt = Color.mix(dfltColor, opts.bgColor, opts.blend || colorAttrs.lightFraction);
var gridColor = coerce2('gridcolor', gridColorDflt);
var gridWidth = coerce2('gridwidth');
var gridDash = coerce2('griddash');
@@ -49,7 +49,7 @@ module.exports = function handleLineGridDefaults(containerIn, containerOut, coer
}
if(opts.hasMinor) {
- var minorGridColorDflt = colorMix(containerOut.gridcolor, opts.bgColor, 67).toRgbString();
+ var minorGridColorDflt = Color.mix(containerOut.gridcolor, opts.bgColor, 67);
var minorGridColor = coerce2('minor.gridcolor', minorGridColorDflt);
var minorGridWidth = coerce2('minor.gridwidth', containerOut.gridwidth || 1);
var minorGridDash = coerce2('minor.griddash', containerOut.griddash || 'solid');
diff --git a/src/plots/gl3d/layout/axis_defaults.js b/src/plots/gl3d/layout/axis_defaults.js
index ae041637a70..2336dc3d8f2 100644
--- a/src/plots/gl3d/layout/axis_defaults.js
+++ b/src/plots/gl3d/layout/axis_defaults.js
@@ -1,6 +1,6 @@
'use strict';
-var colorMix = require('tinycolor2').mix;
+const Color = require('../../../components/color');
var Lib = require('../../../lib');
var Template = require('../../../plot_api/plot_template');
@@ -58,7 +58,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, options) {
},
options.fullLayout);
- coerce('gridcolor', colorMix(containerOut.color, options.bgColor, gridLightness).toRgbString());
+ coerce('gridcolor', Color.mix(containerOut.color, options.bgColor, gridLightness));
coerce('title.text', axName[0]); // shouldn't this be on-par with 2D?
containerOut.setScale = Lib.noop;
diff --git a/src/plots/polar/polar.js b/src/plots/polar/polar.js
index da7da52c1b6..146c3a40f63 100644
--- a/src/plots/polar/polar.js
+++ b/src/plots/polar/polar.js
@@ -1,7 +1,6 @@
'use strict';
var d3 = require('@plotly/d3');
-var tinycolor = require('tinycolor2');
var Registry = require('../../registry');
var Lib = require('../../lib');
@@ -935,7 +934,7 @@ proto.updateHoverAndMainDrag = function(fullLayout) {
dimmed = false;
var polarLayoutNow = gd._fullLayout[_this.id];
- lum = tinycolor(polarLayoutNow.bgcolor).getLuminance();
+ lum = Color.color(polarLayoutNow.bgcolor).luminosity();
zb = dragBox.makeZoombox(zoomlayer, lum, cx, cy, path0);
zb.attr('fill-rule', 'evenodd');
diff --git a/src/plots/ternary/ternary.js b/src/plots/ternary/ternary.js
index 06a457d6d3e..18ced390ce2 100644
--- a/src/plots/ternary/ternary.js
+++ b/src/plots/ternary/ternary.js
@@ -1,7 +1,6 @@
'use strict';
var d3 = require('@plotly/d3');
-var tinycolor = require('tinycolor2');
var Registry = require('../../registry');
var Lib = require('../../lib');
@@ -593,7 +592,7 @@ proto.initInteractions = function() {
};
mins = mins0;
span0 = _this.aaxis.range[1] - mins0.a;
- lum = tinycolor(_this.graphDiv._fullLayout[_this.id].bgcolor).getLuminance();
+ lum = Color.color(_this.graphDiv._fullLayout[_this.id].bgcolor).luminosity();
path0 = 'M0,' + _this.h + 'L' + (_this.w / 2) + ', 0L' + _this.w + ',' + _this.h + 'Z';
dimmed = false;
diff --git a/src/traces/bar/helpers.js b/src/traces/bar/helpers.js
index d1f30a23246..87f0915ff52 100644
--- a/src/traces/bar/helpers.js
+++ b/src/traces/bar/helpers.js
@@ -1,7 +1,7 @@
'use strict';
+const Color = require('../../components/color');
var isNumeric = require('fast-isnumeric');
-var tinycolor = require('tinycolor2');
var isArrayOrTypedArray = require('../../lib').isArrayOrTypedArray;
exports.coerceString = function(attributeDefinition, value, defaultValue) {
@@ -34,7 +34,7 @@ exports.coerceNumber = function(attributeDefinition, value, defaultValue) {
};
exports.coerceColor = function(attributeDefinition, value, defaultValue) {
- if(tinycolor(value).isValid()) return value;
+ if(Color.isValid(value)) return value;
return (defaultValue !== undefined) ?
defaultValue :
diff --git a/src/traces/carpet/axis_defaults.js b/src/traces/carpet/axis_defaults.js
index 1b45c87f6e5..8147e87d31c 100644
--- a/src/traces/carpet/axis_defaults.js
+++ b/src/traces/carpet/axis_defaults.js
@@ -135,7 +135,7 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, options)
dataAttr: letter
});
- var gridColor = coerce2('gridcolor', addOpacity(dfltColor, 0.3));
+ var gridColor = coerce('gridcolor', addOpacity(dfltColor, 0.3));
var gridWidth = coerce2('gridwidth');
var gridDash = coerce2('griddash');
var showGrid = coerce('showgrid');
diff --git a/src/traces/heatmap/plot.js b/src/traces/heatmap/plot.js
index 2db0d0eb3b2..e7a851da763 100644
--- a/src/traces/heatmap/plot.js
+++ b/src/traces/heatmap/plot.js
@@ -1,7 +1,6 @@
'use strict';
var d3 = require('@plotly/d3');
-var tinycolor = require('tinycolor2');
var Registry = require('../../registry');
var Drawing = require('../../components/drawing');
@@ -203,19 +202,19 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
var xb, xi, v, row, c;
function setColor(v, pixsize) {
- if(v !== undefined) {
- var c = sclFunc(v);
- c[0] = Math.round(c[0]);
- c[1] = Math.round(c[1]);
- c[2] = Math.round(c[2]);
-
- pixcount += pixsize;
- rcount += c[0] * pixsize;
- gcount += c[1] * pixsize;
- bcount += c[2] * pixsize;
- return c;
- }
- return [0, 0, 0, 0];
+ if (v === undefined || pixsize === undefined) return [0, 0, 0, 0];
+
+ var c = sclFunc(v);
+ c[0] = Math.round(c[0]);
+ c[1] = Math.round(c[1]);
+ c[2] = Math.round(c[2]);
+
+ pixcount += pixsize;
+ rcount += c[0] * pixsize;
+ gcount += c[1] * pixsize;
+ bcount += c[2] * pixsize;
+
+ return c;
}
function interpColor(r0, r1, xinterp, yinterp) {
@@ -341,13 +340,17 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
}
}
- rcount = Math.round(rcount / pixcount);
- gcount = Math.round(gcount / pixcount);
- bcount = Math.round(bcount / pixcount);
- var avgColor = tinycolor('rgb(' + rcount + ',' + gcount + ',' + bcount + ')');
+ // Guard against dividing by zero and the resulting bad color string
+ if (pixcount) {
+ rcount = Math.round(rcount / pixcount);
+ gcount = Math.round(gcount / pixcount);
+ bcount = Math.round(bcount / pixcount);
- gd._hmpixcount = (gd._hmpixcount||0) + pixcount;
- gd._hmlumcount = (gd._hmlumcount||0) + pixcount * avgColor.getLuminance();
+ const cstr = `rgb(${rcount}, ${gcount}, ${bcount})`;
+
+ gd._hmpixcount = (gd._hmpixcount || 0) + pixcount;
+ gd._hmlumcount = (gd._hmlumcount || 0) + pixcount * Color.color(cstr).luminosity();
+ }
var image3 = plotGroup.selectAll('image')
.data(cd);
@@ -536,7 +539,7 @@ module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) {
fontColor = Color.contrast(
d.z === undefined ? gd._fullLayout.plot_bgcolor :
'rgba(' +
- sclFunc(d.z).join() +
+ sclFunc(d.z).map(Math.round).join() +
')'
);
}
diff --git a/src/traces/parcats/parcats.js b/src/traces/parcats/parcats.js
index 39f75d3b674..8ce8fa93905 100644
--- a/src/traces/parcats/parcats.js
+++ b/src/traces/parcats/parcats.js
@@ -3,11 +3,11 @@
var d3 = require('@plotly/d3');
var interpolateNumber = require('d3-interpolate').interpolateNumber;
var Plotly = require('../../plot_api/plot_api');
+const Color = require('../../components/color');
var Fx = require('../../components/fx');
var Lib = require('../../lib');
var strTranslate = Lib.strTranslate;
var Drawing = require('../../components/drawing');
-var tinycolor = require('tinycolor2');
var svgTextUtils = require('../../lib/svg_text_utils');
function performPlot(parcatsModels, graphDiv, layout, svg) {
@@ -426,7 +426,7 @@ function mouseoverPath(d) {
var hoverCenterX = d.parcatsViewModel.x + pathCenterX;
var hoverCenterY = d.parcatsViewModel.y + pathCenterY;
- var textColor = tinycolor.mostReadable(d.model.color, ['black', 'white']);
+ var textColor = Color.mostReadable(d.model.color);
var count = d.model.count;
var prob = count / d.parcatsViewModel.model.count;
@@ -575,9 +575,7 @@ function stylePathsNoHover(pathSelection) {
function stylePathsHover(pathSelection) {
pathSelection
.attr('fill-opacity', 0.8)
- .attr('stroke', function(d) {
- return tinycolor.mostReadable(d.model.color, ['black', 'white']);
- })
+ .attr('stroke', d => Color.mostReadable(d.model.color))
.attr('stroke-width', 0.3);
}
@@ -936,7 +934,7 @@ function createHoverLabelForColorHovermode(gd, rootBBox, bandElement) {
var hovertext = hoverinfoParts.join('
');
// Compute text color
- var textColor = tinycolor.mostReadable(bandViewModel.color, ['black', 'white']);
+ var textColor = Color.mostReadable(bandViewModel.color);
return {
trace: trace,
diff --git a/src/traces/pie/calc.js b/src/traces/pie/calc.js
index 1fe5541e7d5..914ab513677 100644
--- a/src/traces/pie/calc.js
+++ b/src/traces/pie/calc.js
@@ -1,7 +1,6 @@
'use strict';
var isNumeric = require('fast-isnumeric');
-var tinycolor = require('tinycolor2');
var Color = require('../../components/color');
@@ -89,15 +88,12 @@ function calc(gd, trace) {
function makePullColorFn(colorMap) {
return function pullColor(color, id) {
- if(!color) return false;
+ if(!color || !Color.isValid(color)) return false;
- color = tinycolor(color);
- if(!color.isValid()) return false;
+ const newColor = Color.addOpacity(color, color.getAlpha());
+ if(!colorMap[id]) colorMap[id] = newColor;
- color = Color.addOpacity(color, color.getAlpha());
- if(!colorMap[id]) colorMap[id] = color;
-
- return color;
+ return newColor;
};
}
@@ -154,11 +150,11 @@ function generateExtendedColors(colorList, extendedColorWays) {
colors = colorList.slice();
for(i = 0; i < colorList.length; i++) {
- colors.push(tinycolor(colorList[i]).lighten(20).toHexString());
+ colors.push(Color.color(colorList[i]).lighten(0.2).hex());
}
for(i = 0; i < colorList.length; i++) {
- colors.push(tinycolor(colorList[i]).darken(20).toHexString());
+ colors.push(Color.color(colorList[i]).darken(0.2).hex());
}
extendedColorWays[colorString] = colors;
}
diff --git a/src/traces/sankey/defaults.js b/src/traces/sankey/defaults.js
index d9ca15fea65..8a51fa30577 100644
--- a/src/traces/sankey/defaults.js
+++ b/src/traces/sankey/defaults.js
@@ -3,7 +3,6 @@
var Lib = require('../../lib');
var attributes = require('./attributes');
var Color = require('../../components/color');
-var tinycolor = require('tinycolor2');
var handleDomainDefaults = require('../../plots/domain').defaults;
var handleHoverLabelDefaults = require('../../components/fx/hoverlabel_defaults');
var Template = require('../../plot_api/plot_template');
@@ -63,23 +62,20 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
handleHoverLabelDefaults(linkIn, linkOut, coerceLink, hoverlabelDefault);
coerceLink('hovertemplate');
- var darkBG = tinycolor(layout.paper_bgcolor).getLuminance() < 0.333;
+ var darkBG = Color.color(layout.paper_bgcolor).luminosity() < 0.333;
var defaultLinkColor = darkBG ? 'rgba(255, 255, 255, 0.6)' : 'rgba(0, 0, 0, 0.2)';
var linkColor = coerceLink('color', defaultLinkColor);
function makeDefaultHoverColor(_linkColor) {
- var tc = tinycolor(_linkColor);
- if(!tc.isValid()) {
- // hopefully the user-specified color is valid, but if not that can be caught elsewhere
- return _linkColor;
- }
- var alpha = tc.getAlpha();
- if(alpha <= 0.8) {
- tc.setAlpha(alpha + 0.2);
- } else {
- tc = darkBG ? tc.brighten() : tc.darken();
- }
- return tc.toRgbString();
+ // hopefully the user-specified color is valid, but if not that can be caught elsewhere
+ if(!Color.isValid(_linkColor)) return _linkColor;
+
+ const c = Color.color(_linkColor);
+ const alpha = c.alpha();
+
+ return alpha <= 0.8
+ ? c.alpha(alpha + 0.2).rgb().string()
+ : (darkBG ? c.lighten(0.1) : c.darken(0.1)).rgb().string()
}
coerceLink('hovercolor', Array.isArray(linkColor) ?
diff --git a/src/traces/sankey/plot.js b/src/traces/sankey/plot.js
index 2ac7ec7206e..8b179c767cb 100644
--- a/src/traces/sankey/plot.js
+++ b/src/traces/sankey/plot.js
@@ -64,11 +64,11 @@ function nodeNonHoveredStyle(sankeyNode, d, sankey) {
function linkHoveredStyle(d, sankey, visitNodes, sankeyLink) {
sankeyLink.style('fill', function(l) {
if(!l.link.concentrationscale) {
- return l.tinyColorHoverHue;
+ return l.hoverRgb;
}
}).style('fill-opacity', function(l) {
if(!l.link.concentrationscale) {
- return l.tinyColorHoverAlpha;
+ return l.hoverAlpha;
}
});
@@ -80,11 +80,11 @@ function linkHoveredStyle(d, sankey, visitNodes, sankeyLink) {
.filter(function(l) {return l.link.label === label;})
.style('fill', function(l) {
if(!l.link.concentrationscale) {
- return l.tinyColorHoverHue;
+ return l.hoverRgb;
}
}).style('fill-opacity', function(l) {
if(!l.link.concentrationscale) {
- return l.tinyColorHoverAlpha;
+ return l.hoverAlpha;
}
});
}
@@ -100,9 +100,9 @@ function linkHoveredStyle(d, sankey, visitNodes, sankeyLink) {
function linkNonHoveredStyle(d, sankey, visitNodes, sankeyLink) {
sankeyLink.style('fill', function(l) {
- return l.tinyColorHue;
+ return l.rgb;
}).style('fill-opacity', function(l) {
- return l.tinyColorAlpha;
+ return l.alpha;
});
sankeyLink.each(function(curLink) {
@@ -111,8 +111,8 @@ function linkNonHoveredStyle(d, sankey, visitNodes, sankeyLink) {
ownTrace(sankey, d)
.selectAll('.' + cn.sankeyLink)
.filter(function(l) {return l.link.label === label;})
- .style('fill', function(l) {return l.tinyColorHue;})
- .style('fill-opacity', function(l) {return l.tinyColorAlpha;});
+ .style('fill', l => l.rgb)
+ .style('fill-opacity', l => l.alpha);
}
});
@@ -321,7 +321,7 @@ module.exports = function plot(gd, calcData) {
incomingLabel + d.node.targetLinks.length,
outgoingLabel + d.node.sourceLinks.length
].filter(renderableValuePresent).join('
'),
- color: castHoverOption(obj, 'bgcolor') || d.tinyColorHue,
+ color: castHoverOption(obj, 'bgcolor') || d.rgb,
borderColor: castHoverOption(obj, 'bordercolor'),
fontFamily: castHoverOption(obj, 'font.family'),
fontSize: castHoverOption(obj, 'font.size'),
diff --git a/src/traces/sankey/render.js b/src/traces/sankey/render.js
index a07d18a9c9e..74e17425729 100644
--- a/src/traces/sankey/render.js
+++ b/src/traces/sankey/render.js
@@ -7,7 +7,6 @@ var d3Sankey = require('@plotly/d3-sankey');
var d3SankeyCircular = require('@plotly/d3-sankey-circular');
var c = require('./constants');
-var tinycolor = require('tinycolor2');
var Color = require('../../components/color');
var Drawing = require('../../components/drawing');
var Lib = require('../../lib');
@@ -151,7 +150,7 @@ function sankeyModel(layout, d, traceIndex) {
links: flowLinks
};
if(link.concentrationscale) {
- link.color = tinycolor(link.concentrationscale(link.flow.labelConcentration));
+ link.color = link.concentrationscale(link.flow.labelConcentration);
}
}
}
@@ -298,8 +297,6 @@ function sankeyModel(layout, d, traceIndex) {
}
function linkModel(d, l, i) {
- var tc = tinycolor(l.color);
- var htc = tinycolor(l.hovercolor);
var basicKey = l.source.label + '|' + l.target.label;
var key = basicKey + '__' + i;
@@ -313,10 +310,10 @@ function linkModel(d, l, i) {
traceId: d.key,
pointNumber: l.pointNumber,
link: l,
- tinyColorHue: Color.tinyRGB(tc),
- tinyColorAlpha: tc.getAlpha(),
- tinyColorHoverHue: Color.tinyRGB(htc),
- tinyColorHoverAlpha: htc.getAlpha(),
+ rgb: Color.rgb(l.color),
+ alpha: Color.opacity(l.color),
+ hoverRgb: Color.rgb(l.hovercolor),
+ hoverAlpha: Color.opacity(l.hovercolor),
linkPath: linkPath,
linkLineColor: d.linkLineColor,
linkLineWidth: d.linkLineWidth,
@@ -535,7 +532,6 @@ function linkPath() {
}
function nodeModel(d, n) {
- var tc = tinycolor(n.color);
var zoneThicknessPad = c.nodePadAcross;
var zoneLengthPad = d.nodePad / 2;
n.dx = n.x1 - n.x0;
@@ -577,9 +573,9 @@ function nodeModel(d, n) {
sizeAcross: d.width,
forceLayouts: d.forceLayouts,
horizontal: d.horizontal,
- darkBackground: tc.getBrightness() <= 128,
- tinyColorHue: Color.tinyRGB(tc),
- tinyColorAlpha: tc.getAlpha(),
+ darkBackground: Color.color(n.color).isDark(),
+ rgb: Color.rgb(n.color),
+ alpha: Color.opacity(n.color),
valueFormat: d.valueFormat,
valueSuffix: d.valueSuffix,
sankey: d.sankey,
@@ -937,18 +933,10 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
.call(attachPointerEvents, sankey, callbacks.linkEvents);
sankeyLink
- .style('stroke', function(d) {
- return salientEnough(d) ? Color.tinyRGB(tinycolor(d.linkLineColor)) : d.tinyColorHue;
- })
- .style('stroke-opacity', function(d) {
- return salientEnough(d) ? Color.opacity(d.linkLineColor) : d.tinyColorAlpha;
- })
- .style('fill', function(d) {
- return d.tinyColorHue;
- })
- .style('fill-opacity', function(d) {
- return d.tinyColorAlpha;
- })
+ .style('stroke', d => salientEnough(d) ? Color.rgb(d.linkLineColor) : d.rgb)
+ .style('stroke-opacity', d => salientEnough(d) ? Color.opacity(d.linkLineColor) : d.alpha)
+ .style('fill', d => d.rgb)
+ .style('fill-opacity', d => d.alpha)
.style('stroke-width', function(d) {
return salientEnough(d) ? d.linkLineWidth : 1;
})
@@ -1022,10 +1010,10 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
nodeRect
.style('stroke-width', function(d) {return d.nodeLineWidth;})
- .style('stroke', function(d) {return Color.tinyRGB(tinycolor(d.nodeLineColor));})
+ .style('stroke', function(d) {return Color.rgb(d.nodeLineColor);})
.style('stroke-opacity', function(d) {return Color.opacity(d.nodeLineColor);})
- .style('fill', function(d) {return d.tinyColorHue;})
- .style('fill-opacity', function(d) {return d.tinyColorAlpha;});
+ .style('fill', d => d.rgb)
+ .style('fill-opacity', d => d.alpha);
nodeRect.transition()
.ease(c.ease).duration(c.duration)
diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js
index 6314d97a1b0..2e46116330f 100644
--- a/test/jasmine/tests/axes_test.js
+++ b/test/jasmine/tests/axes_test.js
@@ -7,7 +7,6 @@ var Plots = require('../../../src/plots/plots');
var Lib = require('../../../src/lib');
var Loggers = require('../../../src/lib/loggers');
var Color = require('../../../src/components/color');
-var tinycolor = require('tinycolor2');
var handleTickValueDefaults = require('../../../src/plots/cartesian/tick_value_defaults');
var Cartesian = require('../../../src/plots/cartesian');
@@ -467,11 +466,11 @@ describe('Test axes', function() {
yaxis: {}
};
supplyLayoutDefaults(layoutIn, layoutOut, fullData);
- var lightLine = tinycolor(Color.lightLine).toRgbString();
+ var lightLine = Color.color(Color.lightLine).rgb().string();
expect(layoutOut.xaxis.gridwidth).toBe(1);
- expect(tinycolor(layoutOut.xaxis.gridcolor).toRgbString()).toBe(lightLine);
+ expect(Color.color(layoutOut.xaxis.gridcolor).rgb().string()).toBe(lightLine);
expect(layoutOut.yaxis.gridwidth).toBe(1);
- expect(tinycolor(layoutOut.yaxis.gridcolor).toRgbString()).toBe(lightLine);
+ expect(Color.color(layoutOut.yaxis.gridcolor).rgb().string()).toBe(lightLine);
});
it('should set gridcolor/gridwidth to undefined if showgrid is false', function() {
@@ -566,11 +565,9 @@ describe('Test axes', function() {
var frac = 100 * (0xe - 0x4) / (0xf - 0x4);
supplyLayoutDefaults(layoutIn, layoutOut, fullData);
- expect(layoutOut.xaxis.gridcolor)
- .toEqual(tinycolor.mix('red', bgColor, frac).toRgbString());
+ expect(layoutOut.xaxis.gridcolor).toEqual(Color.mix('red', bgColor, frac));
expect(layoutOut.yaxis.gridcolor).toEqual('blue');
- expect(layoutOut.yaxis2.gridcolor)
- .toEqual(tinycolor.mix('#444', bgColor, frac).toRgbString());
+ expect(layoutOut.yaxis2.gridcolor).toEqual(Color.mix('#444', bgColor, frac));
});
it('should default to a dark color for tickfont when plotting background is light', function() {
@@ -583,7 +580,7 @@ describe('Test axes', function() {
};
supplyLayoutDefaults(layoutIn, layoutOut, fullData);
- expect(layoutOut.xaxis.tickfont.color).toEqual('#444');
+ expect(layoutOut.xaxis.tickfont.color).toEqual('rgb(68, 68, 68)');
});
it('should default to a light color for tickfont when plotting background is dark', function() {
@@ -596,7 +593,7 @@ describe('Test axes', function() {
};
supplyLayoutDefaults(layoutIn, layoutOut, fullData);
- expect(layoutOut.xaxis.tickfont.color).toEqual('#fff');
+ expect(layoutOut.xaxis.tickfont.color).toEqual('rgb(255, 255, 255)');
});
it('should not coerce ticklabelposition on *multicategory* axes for now', function() {
diff --git a/test/jasmine/tests/color_test.js b/test/jasmine/tests/color_test.js
index 990092529b7..a3f617d737f 100644
--- a/test/jasmine/tests/color_test.js
+++ b/test/jasmine/tests/color_test.js
@@ -155,7 +155,7 @@ describe('Test color:', function() {
}
};
- Color.fill(mockElement, 'rgba(255,255,0,0.5');
+ Color.fill(mockElement, 'rgba(255,255,0,0.5)');
});
});
@@ -168,7 +168,7 @@ describe('Test color:', function() {
}
};
- Color.stroke(mockElement, 'rgba(255,255,0,0.5');
+ Color.stroke(mockElement, 'rgba(255,255,0,0.5)');
});
});
@@ -176,19 +176,19 @@ describe('Test color:', function() {
it('should darken light colors', function() {
var out = Color.contrast('#eee', 10, 20);
- expect(out).toEqual('#bbbbbb');
+ expect(out).toEqual('rgb(190, 190, 190)');
});
it('should darken light colors (2)', function() {
var out = Color.contrast('#fdae61', 10, 20);
- expect(out).toEqual('#f57a03');
+ expect(out).toEqual('rgb(252, 139, 28)');
});
it('should lighten dark colors', function() {
var out = Color.contrast('#2b83ba', 10, 20);
- expect(out).toEqual('#449dd4');
+ expect(out).toEqual('rgb(47, 144, 205)');
});
});
});
diff --git a/test/jasmine/tests/gl3dlayout_test.js b/test/jasmine/tests/gl3dlayout_test.js
index ceb049d24f3..75d271f7b6c 100644
--- a/test/jasmine/tests/gl3dlayout_test.js
+++ b/test/jasmine/tests/gl3dlayout_test.js
@@ -1,7 +1,6 @@
var Plotly = require('../../../lib/index');
var Gl3d = require('../../../src/plots/gl3d');
-var tinycolor = require('tinycolor2');
var Color = require('../../../src/components/color');
var createGraphDiv = require('../assets/create_graph_div');
@@ -378,10 +377,10 @@ describe('Test Gl3d layout defaults', function() {
supplyLayoutDefaults(layoutIn, layoutOut, fullData);
expect(layoutOut.scene.xaxis.gridcolor)
- .toEqual(tinycolor.mix('red', bgColor, frac).toRgbString());
+ .toEqual(Color.mix('red', bgColor, frac));
expect(layoutOut.scene.yaxis.gridcolor).toEqual('blue');
expect(layoutOut.scene.zaxis.gridcolor)
- .toEqual(tinycolor.mix('#444', bgColor, frac).toRgbString());
+ .toEqual(Color.mix('#444', bgColor, frac));
});
it('should disable converting numeric strings using axis.autotypenumbers', function() {
diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js
index ba3211c458a..7e716fc4f78 100644
--- a/test/jasmine/tests/hover_label_test.js
+++ b/test/jasmine/tests/hover_label_test.js
@@ -949,10 +949,10 @@ describe('hover info', function() {
fontColor: 'rgb(255, 255, 255)'
}, {
bgcolor: 'rgb(0, 200, 0)',
- bordercolor: 'rgb(255, 255, 255)',
+ bordercolor: 'rgb(68, 68, 68)',
fontSize: 13,
fontFamily: 'Arial',
- fontColor: 'rgb(255, 255, 255)'
+ fontColor: 'rgb(68, 68, 68)'
}, {
bgcolor: 'rgb(255, 127, 14)',
bordercolor: 'rgb(68, 68, 68)',