@a_ng_d/utils-ui-color-palette
Version:
Core utilities library for UI Color Palette - a color management plugin for design tools. This library provides the foundational color manipulation, contrast calculation, and palette generation features used in the plugin.
188 lines (187 loc) • 7.95 kB
JavaScript
var T = Object.defineProperty;
var m = (e, t, r) => t in e ? T(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
var a = (e, t, r) => m(e, typeof t != "symbol" ? t + "" : t, r);
import { c as A } from "../../index-Beb8qoyd.js";
/** @preserve
///// SAPC APCA - Advanced Perceptual Contrast Algorithm
///// Beta 0.1.9 W3 • contrast function only
///// DIST: W3 • Revision date: July 3, 2022
///// Function to parse color values and determine Lc contrast
///// Copyright © 2019-2022 by Andrew Somers. All Rights Reserved.
///// LICENSE: W3 LICENSE
///// CONTACT: Please use the ISSUES or DISCUSSIONS tab at:
///// https://github.com/Myndex/SAPC-APCA/
/////
///////////////////////////////////////////////////////////////////////////////
/////
///// MINIMAL IMPORTS:
///// import { APCAcontrast, sRGBtoY, displayP3toY,
///// calcAPCA, fontLookupAPCA } from 'apca-w3';
///// import { colorParsley } from 'colorparsley';
/////
///// FORWARD CONTRAST USAGE:
///// Lc = APCAcontrast( sRGBtoY( TEXTcolor ) , sRGBtoY( BACKGNDcolor ) );
///// Where the colors are sent as an rgba array [255,255,255,1]
/////
///// Retrieving an array of font sizes for the contrast:
///// fontArray = fontLookupAPCA(Lc);
/////
///// Live Demonstrator at https://www.myndex.com/APCA/
// */
const o = {
mainTRC: 2.4,
// 2.4 exponent for emulating actual monitor perception
// sRGB coefficients
sRco: 0.2126729,
sGco: 0.7151522,
sBco: 0.072175,
// G-4g constants for use with 2.4 exponent
normBG: 0.56,
normTXT: 0.57,
revTXT: 0.62,
revBG: 0.65,
// G-4g Clamps and Scalers
blkThrs: 0.022,
blkClmp: 1.414,
scaleBoW: 1.14,
scaleWoB: 1.14,
loBoWoffset: 0.027,
loWoBoffset: 0.027,
deltaYmin: 5e-4,
loClip: 0.1
};
function d(e, t, r = -1) {
const h = [0, 1.1];
if (isNaN(e) || isNaN(t) || Math.min(e, t) < h[0] || Math.max(e, t) > h[1])
return 0;
let n = 0, i = 0, s = "BoW";
return e = e > o.blkThrs ? e : e + Math.pow(o.blkThrs - e, o.blkClmp), t = t > o.blkThrs ? t : t + Math.pow(o.blkThrs - t, o.blkClmp), Math.abs(t - e) < o.deltaYmin ? 0 : (t > e ? (n = (Math.pow(t, o.normBG) - Math.pow(e, o.normTXT)) * o.scaleBoW, i = n < o.loClip ? 0 : n - o.loBoWoffset) : (s = "WoB", n = (Math.pow(t, o.revBG) - Math.pow(e, o.revTXT)) * o.scaleWoB, i = n > -0.1 ? 0 : n + o.loWoBoffset), r < 0 ? i * 100 : r == 0 ? Math.round(Math.abs(i) * 100) + "<sub>" + s + "</sub>" : Number.isInteger(r) ? (i * 100).toFixed(r) : 0);
}
function P(e, t = 2) {
const r = [
["Lc", 100, 200, 300, 400, 500, 600, 700, 800, 900],
[0, 999, 999, 999, 999, 999, 999, 999, 999, 999],
[10, 999, 999, 999, 999, 999, 999, 999, 999, 999],
[15, 777, 777, 777, 777, 777, 777, 777, 777, 777],
[20, 777, 777, 777, 777, 777, 777, 777, 777, 777],
[25, 777, 777, 777, 120, 120, 108, 96, 96, 96],
[30, 777, 777, 120, 108, 108, 96, 72, 72, 72],
[35, 777, 120, 108, 96, 72, 60, 48, 48, 48],
[40, 120, 108, 96, 60, 48, 42, 32, 32, 32],
[45, 108, 96, 72, 42, 32, 28, 24, 24, 24],
[50, 96, 72, 60, 32, 28, 24, 21, 21, 21],
[55, 80, 60, 48, 28, 24, 21, 18, 18, 18],
[60, 72, 48, 42, 24, 21, 18, 16, 16, 18],
[65, 68, 46, 32, 21.75, 19, 17, 15, 16, 18],
[70, 64, 44, 28, 19.5, 18, 16, 14.5, 16, 18],
[75, 60, 42, 24, 18, 16, 15, 14, 16, 18],
[80, 56, 38.25, 23, 17.25, 15.81, 14.81, 14, 16, 18],
[85, 52, 34.5, 22, 16.5, 15.625, 14.625, 14, 16, 18],
[90, 48, 32, 21, 16, 15.5, 14.5, 14, 16, 18],
[95, 45, 28, 19.5, 15.5, 15, 14, 13.5, 16, 18],
[100, 42, 26.5, 18.5, 15, 14.5, 13.5, 13, 16, 18],
[105, 39, 25, 18, 14.5, 14, 13, 12, 16, 18],
[110, 36, 24, 18, 14, 13, 12, 11, 16, 18],
[115, 34.5, 22.5, 17.25, 12.5, 11.875, 11.25, 10.625, 14.5, 16.5],
[120, 33, 21, 16.5, 11, 10.75, 10.5, 10.25, 13, 15],
[125, 32, 20, 16, 10, 10, 10, 10, 12, 14]
], h = [
["∆Lc", 100, 200, 300, 400, 500, 600, 700, 800, 900],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[10, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[15, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[20, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[25, 0, 0, 0, 12, 12, 12, 24, 24, 24],
[30, 0, 0, 12, 12, 36, 36, 24, 24, 24],
[35, 0, 12, 12, 36, 24, 18, 16, 16, 16],
[40, 12, 12, 24, 18, 16, 14, 8, 8, 8],
[45, 12, 24, 12, 10, 4, 4, 3, 3, 3],
[50, 16, 12, 12, 4, 4, 3, 3, 3, 3],
[55, 8, 12, 6, 4, 3, 3, 2, 2, 0],
[60, 4, 2, 10, 2.25, 2, 1, 1, 0, 0],
[65, 4, 2, 4, 2.25, 1, 1, 0.5, 0, 0],
[70, 4, 2, 4, 1.5, 2, 1, 0.5, 0, 0],
[75, 4, 3.75, 1, 0.75, 0.188, 0.188, 0, 0, 0],
[80, 4, 3.75, 1, 0.75, 0.188, 0.188, 0, 0, 0],
[85, 4, 2.5, 1, 0.5, 0.125, 0.125, 0, 0, 0],
[90, 3, 4, 1.5, 0.5, 0.5, 0.5, 0.5, 0, 0],
[95, 3, 1.5, 1, 0.5, 0.5, 0.5, 0.5, 0, 0],
[100, 3, 1.5, 0.5, 0.5, 0.5, 0.5, 1, 0, 0],
[105, 3, 1, 0, 0.5, 1, 1, 1, 0, 0],
[110, 1.5, 1.5, 0.75, 1.5, 1.125, 0.75, 0.375, 1.5, 1.5],
[115, 1.5, 1.5, 0.75, 1.5, 1.125, 0.75, 0.375, 1.5, 1.5],
[120, 1, 1, 0.5, 1, 0.75, 0.5, 0.25, 1, 1],
[125, 0, 0, 0, 0, 0, 0, 0, 0, 0]
], i = [0, 100, 200, 300, 400, 500, 600, 700, 800, 900].length;
let s = [e.toFixed(t), 0, 0, 0, 0, 0, 0, 0, 0, 0];
s.length;
let l = 777;
e = Math.abs(e);
const c = 0.2, u = e == 0 ? 1 : e * c | 0;
let C = 0, f = (e - r[u][C]) * c;
for (C++; C < i; C++)
l = r[u][C], l > 400 ? s[C] = l : e < 14.5 ? s[C] = 999 : e < 29.5 ? s[C] = 777 : l > 24 ? s[C] = Math.round(l - h[u][C] * f) : s[C] = l - (2 * h[u][C] * f | 0) * 0.5;
return s;
}
function g(e = [0, 0, 0]) {
function t(r) {
return Math.pow(r / 255, o.mainTRC);
}
return o.sRco * t(e[0]) + o.sGco * t(e[1]) + o.sBco * t(e[2]);
}
class W {
constructor({
backgroundColor: t = [0, 0, 0],
textColor: r = "#FFFFFF"
}) {
a(this, "backgroundColor");
a(this, "textColor");
a(this, "getWCAGContrast", () => A.contrast(A(this.backgroundColor).hex(), this.textColor));
a(this, "getAPCAContrast", () => Math.abs(
d(
g(A(this.textColor).rgb()),
g(this.backgroundColor)
)
));
a(this, "getWCAGScore", () => this.getWCAGContrast() < 4.5 ? "A" : this.getWCAGContrast() >= 4.5 && this.getWCAGContrast() < 7 ? "AA" : "AAA");
a(this, "getWCAGScoreColor", () => this.getWCAGScore() !== "A" ? {
r: 0.5294117647,
g: 0.8156862745,
b: 0.6941176471
} : {
r: 0.8274509804,
g: 0.7019607843,
b: 0.7803921569
});
a(this, "getAPCAScoreColor", () => this.getRecommendedUsage() !== "AVOID" ? {
r: 0.5294117647,
g: 0.8156862745,
b: 0.6941176471
} : {
r: 0.8274509804,
g: 0.7019607843,
b: 0.7803921569
});
a(this, "getMinFontSizes", () => P(this.getAPCAContrast()));
a(this, "getRecommendedUsage", () => this.getAPCAContrast() >= 90 ? "FLUENT_TEXT" : this.getAPCAContrast() >= 75 && this.getAPCAContrast() < 90 ? "CONTENT_TEXT" : this.getAPCAContrast() >= 60 && this.getAPCAContrast() < 75 ? "BODY_TEXT" : this.getAPCAContrast() >= 45 && this.getAPCAContrast() < 60 ? "HEADLINES" : this.getAPCAContrast() >= 30 && this.getAPCAContrast() < 45 ? "SPOT_TEXT" : this.getAPCAContrast() >= 15 && this.getAPCAContrast() < 30 ? "NON_TEXT" : this.getAPCAContrast() < 15 ? "AVOID" : "UNKNOWN");
a(this, "getContrastRatioForLightness", (t) => {
const r = A.lch(t, 0, 0).rgb();
return A.contrast(A(r).hex(), this.textColor);
});
a(this, "getLightnessForContrastRatio", (t, r = 0.1) => {
const h = A(this.textColor).luminance() > 0.5;
let n = 0, i = 100, s = h ? 20 : 80;
for (; i - n > r; ) {
s = (n + i) / 2;
const l = this.getContrastRatioForLightness(s);
h ? l < t ? i = s : n = s : l < t ? n = s : i = s;
}
return s;
});
this.backgroundColor = t, this.textColor = r;
}
}
export {
W as default
};
//# sourceMappingURL=contrast.js.map