@ctrl/tinycolor
Version:
Fast, small color manipulation and conversion for JavaScript
83 lines (82 loc) • 3.49 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.mostReadable = exports.isReadable = exports.readability = void 0;
const index_js_1 = require("./index.js");
// Readability Functions
// ---------------------
// <http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)
/**
* AKA `contrast`
*
* Analyze the 2 colors and returns the color contrast defined by (WCAG Version 2)
*/
function readability(color1, color2) {
const c1 = new index_js_1.TinyColor(color1);
const c2 = new index_js_1.TinyColor(color2);
return ((Math.max(c1.getLuminance(), c2.getLuminance()) + 0.05) /
(Math.min(c1.getLuminance(), c2.getLuminance()) + 0.05));
}
exports.readability = readability;
/**
* Ensure that foreground and background color combinations meet WCAG2 guidelines.
* The third argument is an object.
* the 'level' property states 'AA' or 'AAA' - if missing or invalid, it defaults to 'AA';
* the 'size' property states 'large' or 'small' - if missing or invalid, it defaults to 'small'.
* If the entire object is absent, isReadable defaults to {level:"AA",size:"small"}.
*
* Example
* ```ts
* new TinyColor().isReadable('#000', '#111') => false
* new TinyColor().isReadable('#000', '#111', { level: 'AA', size: 'large' }) => false
* ```
*/
function isReadable(color1, color2, wcag2 = { level: 'AA', size: 'small' }) {
const readabilityLevel = readability(color1, color2);
switch ((wcag2.level ?? 'AA') + (wcag2.size ?? 'small')) {
case 'AAsmall':
case 'AAAlarge':
return readabilityLevel >= 4.5;
case 'AAlarge':
return readabilityLevel >= 3;
case 'AAAsmall':
return readabilityLevel >= 7;
default:
return false;
}
}
exports.isReadable = isReadable;
/**
* Given a base color and a list of possible foreground or background
* colors for that base, returns the most readable color.
* Optionally returns Black or White if the most readable color is unreadable.
*
* @param baseColor - the base color.
* @param colorList - array of colors to pick the most readable one from.
* @param args - and object with extra arguments
*
* Example
* ```ts
* new TinyColor().mostReadable('#123', ['#124", "#125'], { includeFallbackColors: false }).toHexString(); // "#112255"
* new TinyColor().mostReadable('#123', ['#124", "#125'],{ includeFallbackColors: true }).toHexString(); // "#ffffff"
* new TinyColor().mostReadable('#a8015a', ["#faf3f3"], { includeFallbackColors:true, level: 'AAA', size: 'large' }).toHexString(); // "#faf3f3"
* new TinyColor().mostReadable('#a8015a', ["#faf3f3"], { includeFallbackColors:true, level: 'AAA', size: 'small' }).toHexString(); // "#ffffff"
* ```
*/
function mostReadable(baseColor, colorList, args = { includeFallbackColors: false, level: 'AA', size: 'small' }) {
let bestColor = null;
let bestScore = 0;
const { includeFallbackColors, level, size } = args;
for (const color of colorList) {
const score = readability(baseColor, color);
if (score > bestScore) {
bestScore = score;
bestColor = new index_js_1.TinyColor(color);
}
}
if (isReadable(baseColor, bestColor, { level, size }) || !includeFallbackColors) {
return bestColor;
}
args.includeFallbackColors = false;
return mostReadable(baseColor, ['#fff', '#000'], args);
}
exports.mostReadable = mostReadable;
;