Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Switch references to new color library
  • Loading branch information
camdecoster committed Aug 21, 2025
commit b15bdca973257f2216b89eadd2925b94e222b5c2
2 changes: 1 addition & 1 deletion src/components/color/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
24 changes: 23 additions & 1 deletion src/components/color/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,30 @@ const cleanOne = val => {
const equals = (cstr1, cstr2) => cstr1 && cstr2 && color(cstr1).rgb().string() === color(cstr2).rgb().string();

const isValid = cstr => {
try { return !!color(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,
Expand All @@ -188,6 +208,8 @@ module.exports = {
interpolate,
isValid,
lightLine,
mix,
mostReadable,
opacity,
rgb,
stroke
Expand Down
10 changes: 4 additions & 6 deletions src/components/colorbar/draw.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

var d3 = require('@plotly/d3');
var tinycolor = require('tinycolor2');

var Plots = require('../../plots/plots');
var Registry = require('../../registry');
Expand Down Expand Up @@ -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());
}
});

Expand Down Expand Up @@ -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
Expand Down
17 changes: 8 additions & 9 deletions src/components/colorscale/helpers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

var d3 = require('@plotly/d3');
var tinycolor = require('tinycolor2');
var isNumeric = require('fast-isnumeric');

var Lib = require('../../lib');
Expand Down Expand Up @@ -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()
Expand All @@ -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;
};
}

Expand All @@ -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 = {
Expand Down
4 changes: 2 additions & 2 deletions src/components/colorscale/scales.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

var tinycolor = require('tinycolor2');
const Color = require('../color');

var scales = {
Greys: [
Expand Down Expand Up @@ -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;
}

Expand Down
16 changes: 6 additions & 10 deletions src/components/drawing/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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])
});
});
});
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
Expand Down
11 changes: 6 additions & 5 deletions src/components/fx/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(contrastColor) < 1.5
? Color.contrast(contrastColor)
: hLinePoint.color;
var yMode = ya.spikemode;
var yThickness = ya.spikethickness;
var yColor = ya.spikecolor || dfltHLineColor;
Expand Down Expand Up @@ -2207,8 +2207,9 @@ 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(contrastColor) < 1.5
? Color.contrast(contrastColor)
: vLinePoint.color;
var xMode = xa.spikemode;
var xThickness = xa.spikethickness;
var xColor = xa.spikecolor || dfltVLineColor;
Expand Down
8 changes: 2 additions & 6 deletions src/lib/coerce.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

var isNumeric = require('fast-isnumeric');
var tinycolor = require('tinycolor2');

var extendFlat = require('./extend').extendFlat;

Expand Down Expand Up @@ -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);
}
},
Expand All @@ -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);
}
},
Expand Down
6 changes: 2 additions & 4 deletions src/lib/gl_format_color.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

var isNumeric = require('fast-isnumeric');
var tinycolor = require('tinycolor2');
var rgba = require('color-normalize');

var Colorscale = require('../components/colorscale');
Expand Down Expand Up @@ -78,11 +77,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]
};
});
}
Expand Down
6 changes: 2 additions & 4 deletions src/plot_api/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions src/plots/cartesian/dragbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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';
Expand Down
6 changes: 3 additions & 3 deletions src/plots/cartesian/line_grid_defaults.js
Original file line number Diff line number Diff line change
@@ -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');

Expand Down Expand Up @@ -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');
Expand All @@ -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');
Expand Down
4 changes: 2 additions & 2 deletions src/plots/gl3d/layout/axis_defaults.js
Original file line number Diff line number Diff line change
@@ -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');
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions src/plots/polar/polar.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

var d3 = require('@plotly/d3');
var tinycolor = require('tinycolor2');

var Registry = require('../../registry');
var Lib = require('../../lib');
Expand Down Expand Up @@ -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');
Expand Down
3 changes: 1 addition & 2 deletions src/plots/ternary/ternary.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

var d3 = require('@plotly/d3');
var tinycolor = require('tinycolor2');

var Registry = require('../../registry');
var Lib = require('../../lib');
Expand Down Expand Up @@ -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;

Expand Down
Loading
Loading