UNPKG

@ctrl/tinycolor

Version:

Fast, small color manipulation and conversion for JavaScript

83 lines (82 loc) 3.49 kB
"use strict"; 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;