@tabuckner/random-contrast-compliant-ts
Version:
This project was bootstrapped with [TSDX](https://github.com/jaredpalmer/tsdx).
173 lines (144 loc) • 11.1 kB
JavaScript
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var _parseColor = require('parse-color');
var _parseColor__default = _interopDefault(_parseColor);
var CONFIG_DEFAULTS = {
defaultContrastMinimum: 4.5,
defaultContrastMaximum: 10
};
// Precomputed linear color channel values, for use in contrast calculations.
// See https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
//
// Algorithm, for c in 0 to 255:
// f(c) {
// c = c / 255;
// return c < 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
// }
//
// This lookup table is needed since there is no `pow` in SASS.
var LINEAR_CHANNEL_VALUES = [0, .0003035269835488375, .000607053967097675, .0009105809506465125, .00121410793419535, .0015176349177441874, .001821161901293025, .0021246888848418626, .0024282158683907, .0027317428519395373, .003035269835488375, .003346535763899161, .003676507324047436, .004024717018496307, .004391442037410293, .004776953480693729, .005181516702338386, .005605391624202723, .006048833022857054, .006512090792594475, .006995410187265387, .007499032043226175, .008023192985384994, .008568125618069307, .009134058702220787, .00972121732023785, .010329823029626936, .010960094006488246, .011612245179743885, .012286488356915872, .012983032342173012, .013702083047289686, .014443843596092545, .01520851442291271, .01599629336550963, .016807375752887384, .017641954488384078, .018500220128379697, .019382360956935723, .0202885630566524, .021219010376003555, .022173884793387385, .02315336617811041, .024157632448504756, .02518685962736163, .026241221894849898, .027320891639074894, .028426039504420793, .0295568344378088, .030713443732993635, .03189603307301153, .033104766570885055, .03433980680868217, .03560131487502034, .03688945040110004, .0382043715953465, .03954623527673284, .04091519690685319, .042311410620809675, .043735029256973465, .04518620438567554, .046665086336880095, .04817182422688942, .04970656598412723, .05126945837404324, .052860647023180246, .05448027644244237, .05612849004960009, .05780543019106723, .0595112381629812, .06124605423161761, .06301001765316767, .06480326669290577, .06662593864377289, .06847816984440017, .07036009569659588, .07227185068231748, .07421356838014963, .07618538148130785, .07818742180518633, .08021982031446832, .0822827071298148, .08437621154414882, .08650046203654976, .08865558628577294, .09084171118340768, .09305896284668745, .0953074666309647, .09758734714186246, .09989872824711389, .10224173308810132, .10461648409110419, .10702310297826761, .10946171077829933, .1119324278369056, .11443537382697373, .11697066775851084, .11953842798834562, .12213877222960187, .12477181756095049, .12743768043564743, .1301364766903643, .13286832155381798, .13563332965520566, .13843161503245183, .14126329114027164, .14412847085805777, .14702726649759498, .14995978981060856, .15292615199615017, .1559264637078274, .1589608350608804, .162029375639111, .1651321945016676, .16826940018969075, .1714411007328226, .17464740365558504, .17788841598362912, .18116424424986022, .184474994500441, .18782077230067787, .19120168274079138, .1946178304415758, .19806931955994886, .20155625379439707, .20507873639031693, .20863687014525575, .21223075741405523, .21586050011389926, .2195261997292692, .2232279573168085, .22696587351009836, .23074004852434915, .23455058216100522, .238397573812271, .24228112246555486, .24620132670783548, .25015828472995344, .25415209433082675, .2581828529215958, .26225065752969623, .26635560480286247, .2704977910130658, .27467731206038465, .2788942634768104, .2831487404299921, .2874408377269175, .29177064981753587, .2961382707983211, .3005437944157765, .3049873140698863, .30946892281750854, .31398871337571754, .31854677812509186, .32314320911295075, .3277780980565422, .33245153634617935, .33716361504833037, .3419144249086609, .3467040563550296, .35153259950043936, .3564001441459435, .3613067797835095, .3662525955988395, .3712376804741491, .3762621229909065, .38132601143253014, .386429433787049, .39157247774972326, .39675523072562685, .4019777798321958, .4072402119017367, .41254261348390375, .4178850708481375, .4232676699860717, .4286904966139066, .43415363617474895, .4396571738409188, .44520119451622786, .45078578283822346, .45641102318040466, .4620769996544071, .467783796112159, .47353149614800955, .4793201831008268, .4851499400560704, .4910208498478356, .4969329950608704, .5028864580325687, .5088813208549338, .5149176653765214, .5209955732043543, .5271151257058131, .5332764040105052, .5394794890121072, .5457244613701866, .5520114015120001, .5583403896342679, .5647115057049292, .5711248294648731, .5775804404296506, .5840784178911641, .5906188409193369, .5972017883637634, .6038273388553378, .6104955708078648, .6172065624196511, .6239603916750761, .6307571363461468, .6375968739940326, .6444796819705821, .6514056374198242, .6583748172794485, .665387298282272, .6724431569576875, .6795424696330938, .6866853124353135, .6938717612919899, .7011018919329731, .7083757798916868, .7156935005064807, .7230551289219693, .7304607400903537, .7379104087727308, .7454042095403874, .7529422167760779, .7605245046752924, .768151147247507, .7758222183174236, .7835377915261935, .7912979403326302, .799102738014409, .8069522576692516, .8148465722161012, .8227857543962835, .8307698767746546, .83879901174074, .846873231509858, .8549926081242338, .8631572134541023, .8713671191987972, .8796223968878317, .8879231178819663, .8962693533742664, .9046611743911496, .9130986517934192, .9215818562772946, .9301108583754237, .938685728457888, .9473065367331999, .9559733532492861, .9646862478944651, .9734452903984125, .9822505503331171, .9911020971138298, 1];
var parseColor = function parseColor(cssString) {
var _parsedColor = _parseColor__default(cssString);
var rgbObj = mapArrayToObject(_parsedColor.rgb, ['red', 'green', 'blue']);
var hslObj = mapArrayToObject(_parsedColor.hsl, ['hue', 'saturation', 'lightness']);
var hsvObj = mapArrayToObject(_parsedColor.hsv, ['hue', 'saturation', 'value']);
var cmykObj = mapArrayToObject(_parsedColor.cmyk, ['cyan', 'magenta', 'yellow', 'black']);
var keyword = _parsedColor.keyword,
hex = _parsedColor.hex;
var rgbaObj = mapArrayToObject(_parsedColor.rgba, ['red', 'green', 'blue', 'alpha']);
var hslaObj = mapArrayToObject(_parsedColor.hsla, ['hue', 'saturation', 'lightness', 'alpha']);
var hsvaObj = mapArrayToObject(_parsedColor.hsva, ['hue', 'saturation', 'value', 'alpha']);
var cmykaObj = mapArrayToObject(_parsedColor.cmyka, ['cyan', 'magenta', 'yellow', 'black', 'alpha']);
var returnObj = {
rgb: rgbObj,
hsl: hslObj,
hsv: hsvObj,
cmyk: cmykObj,
keyword: keyword,
hex: hex,
rgba: rgbaObj,
hsla: hslaObj,
hsva: hsvaObj,
cmyka: cmykaObj
};
return returnObj;
};
var mapArrayToObject = function mapArrayToObject(orderedArr, orderedObjectKeysArr) {
var returnObj = {};
for (var _iterator = orderedObjectKeysArr, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var key = _ref;
returnObj[key] = undefined;
}
for (var i = 0; i < orderedArr.length; i++) {
var sourceElement = orderedArr[i];
var correspondingKey = orderedObjectKeysArr[i];
returnObj[correspondingKey] = sourceElement;
}
return returnObj;
};
var buildRgbString = function buildRgbString(red, green, blue) {
return "rgb(" + red + ", " + green + ", " + blue + ")";
};
var randomValue = function randomValue(range) {
return Math.floor(Math.random() * range);
};
/**
* Given a `backgroundColor`, optional `contrastRatioMinimum`, and optional `contrastRatioMaximum`
* returns a random `IParsedColor`.
* @param backgroundColor A Valid CSS string for the background color.
* @param contrastRatioMinimum A valid CSS string for the foreground color.
* @param contrastRatioMaximum Maximum WCAG contrast ratio.
*/
var getRandomContrastCompliant = function getRandomContrastCompliant(backgroundColor, contrastRatioMinimum, contrastRatioMaximum) {
if (contrastRatioMinimum === void 0) {
contrastRatioMinimum = CONFIG_DEFAULTS.defaultContrastMinimum;
}
if (contrastRatioMaximum === void 0) {
contrastRatioMaximum = CONFIG_DEFAULTS.defaultContrastMaximum;
}
var backgroundRgbValue = parseColor(backgroundColor).rgb;
var randomRgbValue = getRandomIRgbValue();
var randomRgbContrast = contrast(backgroundRgbValue, randomRgbValue);
var isTooLow = randomRgbContrast < contrastRatioMinimum;
var isTooHigh = randomRgbContrast > contrastRatioMaximum;
var isInvalidContrast = isTooLow || isTooHigh;
while (isInvalidContrast) {
randomRgbValue = getRandomIRgbValue();
randomRgbContrast = contrast(backgroundRgbValue, randomRgbValue);
isTooLow = randomRgbContrast < contrastRatioMinimum;
isTooHigh = randomRgbContrast > contrastRatioMaximum;
isInvalidContrast = isTooLow || isTooHigh;
}
return parseColor(buildRgbString(randomRgbValue.red, randomRgbValue.green, randomRgbValue.blue));
};
/**
* Given an `rgbValue`, returns its Luminance.
*
* Read More: https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
* @param rgbValue an object matching `IRgbValue`
*/
var luminance = function luminance(rgbValue) {
var red = rgbValue.red,
green = rgbValue.green,
blue = rgbValue.blue;
if (!isValidRgbProperty(red) || !isValidRgbProperty(green) || !isValidRgbProperty(blue)) {
throw new Error('Supplied `rgbValue`' + JSON.stringify(rgbValue) + ' parameter is invalid.');
}
var redLinearChannelValue = LINEAR_CHANNEL_VALUES[red + 1];
var greenLinearChannelValue = LINEAR_CHANNEL_VALUES[green + 1];
var blueLinearChannelValue = LINEAR_CHANNEL_VALUES[blue + 1];
return .2126 * redLinearChannelValue + .7152 * greenLinearChannelValue + .0722 * blueLinearChannelValue;
};
var isValidRgbProperty = function isValidRgbProperty(value) {
return value >= 0 && value <= 255;
};
/**
* Given a `background`, and `foreground` color, returns the relative contrast.
*
* Read More: https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
* @param background a background color that matches `IRgbValue`
* @param foreGround a foreground color that matches `IRgbValue`
*/
var contrast = function contrast(background, foreground) {
var backgroundLuminance = luminance(background) + .05;
var foregroundLuminance = luminance(foreground) + .05;
return Math.max(backgroundLuminance, foregroundLuminance) / Math.min(backgroundLuminance, foregroundLuminance);
};
var getRandomIRgbValue = function getRandomIRgbValue() {
return {
red: randomValue(255),
blue: randomValue(255),
green: randomValue(255)
};
};
exports.getRandomContrastCompliant = getRandomContrastCompliant;
//# sourceMappingURL=random-contrast-compliant-ts.cjs.development.js.map