@umbrajs/core
Version:
Umbra is a theme management library that allows you to create semantic color themes that are easy to dynamically customize, change retroactively and scale progressively
1,397 lines (1,396 loc) • 39.2 kB
JavaScript
var Ft = Object.defineProperty;
var Lt = (t, n, e) => n in t ? Ft(t, n, { enumerable: !0, configurable: !0, writable: !0, value: e }) : t[n] = e;
var ot = (t, n, e) => Lt(t, typeof n != "symbol" ? n + "" : n, e);
const Ot = {
grad: 0.9,
turn: 360,
rad: 360 / (Math.PI * 2)
}, M = (t) => typeof t == "string" ? t.length > 0 : typeof t == "number", p = (t, n = 0, e = Math.pow(10, n)) => Math.round(e * t) / e + 0, k = (t, n = 0, e = 1) => t > e ? e : t > n ? t : n, kt = (t) => (t = isFinite(t) ? t % 360 : 0, t > 0 ? t : t + 360), Wt = (t, n = "deg") => Number(t) * (Ot[n] || 1), Y = (t) => ({
r: k(t.r, 0, 255),
g: k(t.g, 0, 255),
b: k(t.b, 0, 255),
a: k(t.a)
}), tt = (t) => ({
r: p(t.r),
g: p(t.g),
b: p(t.b),
a: p(t.a, 3)
}), _t = ({ r: t, g: n, b: e, a: o = 1 }) => !M(t) || !M(n) || !M(e) ? null : Y({
r: Number(t),
g: Number(n),
b: Number(e),
a: Number(o)
}), _ = (t) => {
const n = t / 255;
return n < 0.04045 ? n / 12.92 : Math.pow((n + 0.055) / 1.055, 2.4);
}, G = (t) => (t > 31308e-7 ? 1.055 * Math.pow(t, 0.4166666666666667) - 0.055 : 12.92 * t) * 255, Gt = /^#([0-9a-f]{3,8})$/i, zt = (t) => {
const n = Gt.exec(t);
return n ? (t = n[1], t.length <= 4 ? {
r: parseInt(t[0] + t[0], 16),
g: parseInt(t[1] + t[1], 16),
b: parseInt(t[2] + t[2], 16),
a: t.length === 4 ? p(parseInt(t[3] + t[3], 16) / 255, 2) : 1
} : t.length === 6 || t.length === 8 ? {
r: parseInt(t.substr(0, 2), 16),
g: parseInt(t.substr(2, 2), 16),
b: parseInt(t.substr(4, 2), 16),
a: t.length === 8 ? p(parseInt(t.substr(6, 2), 16) / 255, 2) : 1
} : null) : null;
}, B = (t) => {
const n = t.toString(16);
return n.length < 2 ? "0" + n : n;
}, jt = (t) => {
const { r: n, g: e, b: o, a: r } = tt(t), a = r < 1 ? B(p(r * 255)) : "";
return "#" + B(n) + B(e) + B(o) + a;
}, Vt = (t) => ({
h: kt(t.h),
s: k(t.s, 0, 100),
v: k(t.v, 0, 100),
a: k(t.a)
}), Xt = (t) => ({
h: p(t.h),
s: p(t.s),
v: p(t.v),
a: p(t.a, 3)
}), Ut = ({ h: t, s: n, v: e, a: o = 1 }) => {
if (!M(t) || !M(n) || !M(e)) return null;
const r = Vt({
h: Number(t),
s: Number(n),
v: Number(e),
a: Number(o)
});
return Mt(r);
}, yt = ({ r: t, g: n, b: e, a: o }) => {
const r = Math.max(t, n, e), a = r - Math.min(t, n, e), s = a ? r === t ? (n - e) / a : r === n ? 2 + (e - t) / a : 4 + (t - n) / a : 0;
return {
h: 60 * (s < 0 ? s + 6 : s),
s: r ? a / r * 100 : 0,
v: r / 255 * 100,
a: o
};
}, Mt = ({ h: t, s: n, v: e, a: o }) => {
t = t / 360 * 6, n = n / 100, e = e / 100;
const r = Math.floor(t), a = e * (1 - n), s = e * (1 - (t - r) * n), i = e * (1 - (1 - t + r) * n), c = r % 6;
return {
r: [e, s, a, a, i, e][c] * 255,
g: [i, e, e, s, a, a][c] * 255,
b: [a, a, i, e, e, s][c] * 255,
a: o
};
}, vt = (t) => ({
h: kt(t.h),
s: k(t.s, 0, 100),
l: k(t.l, 0, 100),
a: k(t.a)
}), Rt = (t) => ({
h: p(t.h),
s: p(t.s),
l: p(t.l),
a: p(t.a, 3)
}), Qt = ({ h: t, s: n, l: e, a: o = 1 }) => {
if (!M(t) || !M(n) || !M(e)) return null;
const r = vt({
h: Number(t),
s: Number(n),
l: Number(e),
a: Number(o)
});
return Ht(r);
}, qt = ({ h: t, s: n, l: e, a: o }) => (n *= (e < 50 ? e : 100 - e) / 100, {
h: t,
s: n > 0 ? 2 * n / (e + n) * 100 : 0,
v: e + n,
a: o
}), Kt = ({ h: t, s: n, v: e, a: o }) => {
const r = (200 - n) * e / 100;
return {
h: t,
s: r > 0 && r < 200 ? n * e / 100 / (r <= 100 ? r : 200 - r) * 100 : 0,
l: r / 2,
a: o
};
}, Ht = (t) => Mt(qt(t)), E = (t) => Kt(yt(t)), Jt = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s*,\s*([+-]?\d*\.?\d+)%\s*,\s*([+-]?\d*\.?\d+)%\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, Zt = /^hsla?\(\s*([+-]?\d*\.?\d+)(deg|rad|grad|turn)?\s+([+-]?\d*\.?\d+)%\s+([+-]?\d*\.?\d+)%\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, Yt = (t) => {
const n = Jt.exec(t) || Zt.exec(t);
if (!n) return null;
const e = vt({
h: Wt(n[1], n[2]),
s: Number(n[3]),
l: Number(n[4]),
a: n[5] === void 0 ? 1 : Number(n[5]) / (n[6] ? 100 : 1)
});
return Ht(e);
}, tn = (t) => {
const { h: n, s: e, l: o, a: r } = Rt(E(t));
return r < 1 ? `hsla(${n}, ${e}%, ${o}%, ${r})` : `hsl(${n}, ${e}%, ${o}%)`;
}, nn = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*,\s*([+-]?\d*\.?\d+)(%)?\s*(?:,\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, en = /^rgba?\(\s*([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)(%)?\s*(?:\/\s*([+-]?\d*\.?\d+)(%)?\s*)?\)$/i, rn = (t) => {
const n = nn.exec(t) || en.exec(t);
return !n || n[2] !== n[4] || n[4] !== n[6] ? null : Y({
r: Number(n[1]) / (n[2] ? 100 / 255 : 1),
g: Number(n[3]) / (n[4] ? 100 / 255 : 1),
b: Number(n[5]) / (n[6] ? 100 / 255 : 1),
a: n[7] === void 0 ? 1 : Number(n[7]) / (n[8] ? 100 : 1)
});
}, on = (t) => {
const { r: n, g: e, b: o, a: r } = tt(t);
return r < 1 ? `rgba(${n}, ${e}, ${o}, ${r})` : `rgb(${n}, ${e}, ${o})`;
}, Q = {
string: [
[zt, "hex"],
[rn, "rgb"],
[Yt, "hsl"]
],
object: [
[_t, "rgb"],
[Qt, "hsl"],
[Ut, "hsv"]
]
}, at = (t, n) => {
for (let e = 0; e < n.length; e++) {
const o = n[e][0](t);
if (o) return [o, n[e][1]];
}
return [null, void 0];
}, St = (t) => typeof t == "string" ? at(t.trim(), Q.string) : typeof t == "object" && t !== null ? at(t, Q.object) : [null, void 0], de = (t) => St(t)[1], an = (t, n) => ({
r: t.r,
g: t.g,
b: t.b,
a: n
}), z = (t, n) => {
const e = E(t);
return {
h: e.h,
s: k(e.s + n * 100, 0, 100),
l: e.l,
a: e.a
};
}, j = (t) => (t.r * 299 + t.g * 587 + t.b * 114) / 1e3 / 255, st = (t, n) => {
const e = E(t);
return {
h: e.h,
s: e.s,
l: k(e.l + n * 100, 0, 100),
a: e.a
};
}, sn = (t) => ({
r: 255 - t.r,
g: 255 - t.g,
b: 255 - t.b,
a: t.a
});
class L {
constructor(n) {
ot(this, "rgba");
const e = St(n)[0];
this.rgba = e || { r: 0, g: 0, b: 0, a: 1 };
}
/**
* Returns a boolean indicating whether or not an input has been parsed successfully.
* Note: If parsing is unsuccessful, UmbraSwatch defaults to black (does not throws an error).
*/
isValid() {
return this.rgba !== null;
}
/**
* Returns the brightness of a color (from 0 to 1).
* The calculation logic is modified from WCAG.
* https://www.w3.org/TR/AERT/#color-contrast
*/
brightness() {
return p(j(this.rgba), 2);
}
/**
* Same as calling `brightness() < 0.5`.
*/
isDark() {
return j(this.rgba) < 0.5;
}
/**
* Same as calling `brightness() >= 0.5`.
* */
isLight() {
return j(this.rgba) >= 0.5;
}
/**
* Returns the hexadecimal representation of a color.
* When the alpha channel value of the color is less than 1,
* it outputs #rrggbbaa format instead of #rrggbb.
*/
toHex() {
return jt(this.rgba);
}
/**
* Converts a color to RGB color space and returns an object.
* Always includes an alpha value from 0 to 1.
*/
toRgb() {
return tt(this.rgba);
}
/**
* Converts a color to RGB color space and returns a string representation.
* Outputs an alpha value only if it is less than 1.
*/
toRgbString() {
return on(this.rgba);
}
/**
* Converts a color to HSL color space and returns an object.
* Always includes an alpha value from 0 to 1.
*/
toHsl() {
return Rt(E(this.rgba));
}
/**
* Converts a color to HSL color space and returns a string representation.
* Always includes an alpha value from 0 to 1.
*/
toHslString() {
return tn(this.rgba);
}
/**
* Converts a color to HSV color space and returns an object.
* Always includes an alpha value from 0 to 1.
*/
toHsv() {
return Xt(yt(this.rgba));
}
/**
* Creates a new instance containing an inverted (opposite) version of the color.
*/
invert() {
return g(sn(this.rgba));
}
/**
* Increases the HSL saturation of a color by the given amount.
*/
saturate(n = 0.1) {
return g(z(this.rgba, n));
}
/**
* Decreases the HSL saturation of a color by the given amount.
*/
desaturate(n = 0.1) {
return g(z(this.rgba, -n));
}
/**
* Makes a gray color with the same lightness as a source color.
*/
grayscale() {
return g(z(this.rgba, -1));
}
/**
* Increases the HSL lightness of a color by the given amount.
*/
lighten(n = 0.1) {
return g(st(this.rgba, n));
}
/**
* Increases the HSL lightness of a color by the given amount.
*/
darken(n = 0.1) {
return g(st(this.rgba, -n));
}
/**
* Changes the HSL hue of a color by the given amount.
*/
rotate(n = 15) {
return this.hue(this.hue() + n);
}
alpha(n) {
return typeof n == "number" ? g(an(this.rgba, n)) : p(this.rgba.a, 3);
}
hue(n) {
const e = E(this.rgba);
return typeof n == "number" ? g({ h: n, s: e.s, l: e.l, a: e.a }) : p(e.h);
}
/**
* Determines whether two values are the same color.
*/
isEqual(n) {
return this.toHex() === g(n).toHex();
}
}
const g = (t) => t instanceof L ? t : new L(t), it = [], un = (t) => {
t.forEach((n) => {
it.indexOf(n) < 0 && (n(L, Q), it.push(n));
});
}, me = () => new L({
r: Math.random() * 255,
g: Math.random() * 255,
b: Math.random() * 255
}), T = {
readability: 70,
insertion: 9,
range: {
light: [0.5, 2, 5, 8, 11, 13, 17, 24, 42, 46, 58, 87],
dark: [5, 9, 13, 17, 20, 25, 30, 41, 46, 51, 74, 94]
}
}, cn = {
name: "warning",
color: "#ff0000"
}, ln = {
name: "success",
color: "#00ff00"
}, O = {
background: "#090233",
foreground: "#ff5555",
accents: ["#ffffff", cn, ln],
settings: T,
inversed: {
background: "#ff5555",
foreground: "#090233",
accents: ["#5200ff"]
}
};
let ut = 0, w = [];
function fn(t) {
if (!t) return;
ut++;
const n = w.find((o) => o.selector === t);
return n ? w[n.index].iterations++ : w.push({ index: w.length, selector: t, iterations: 1 }), `${n ? `${w[n.index].iterations}` : "1"}-${ut}`;
}
function gn({ outputs: t, target: n, alias: e, rangeMapping: o = !0 }) {
const r = fn(n.selector), a = t.flattened.filter(({ name: s }) => !hn(s));
if (n.element && xn(n.element, a), n.selector && dn(n.selector, a, r), e) {
const i = Object.entries(e).map(([c, u]) => ({ name: "--" + c, color: `var(--${u})` }));
i.forEach((c) => n.element && q(n.element, c)), n.selector && mn(n.selector, i, r);
}
return o && n.selector && bn(t, r), t;
}
function hn(t) {
return /(?:background|foreground).*text/i.test(t);
}
function At(t, { selector: n = ":root", meta: e = "1", marker: o = "theme" }) {
const r = new CSSStyleSheet();
return r.replace(
`${o}-${e}, ${n} {${t.map(({ name: a, color: s }) => `${a}: ${s};`).join("")}}`
), r;
}
function dn(t = ":root", n, e) {
const o = "theme", r = At(n, { meta: e, marker: o, selector: t });
nt(r, t, o);
}
function mn(t = ":root", n, e) {
const o = "alias", r = At(n, { meta: e, marker: o, selector: t });
nt(r, t, o);
}
function bn(t, n) {
const e = "range-mapping", o = t.formated.filter(
(a) => !["base", "background", "foreground"].includes(a.name)
), r = [];
if (o.forEach((a) => {
const s = `.base-${a.name}`, i = [];
i.push(`--base: var(--${a.name});`);
for (let c = 1; c <= 12; c++) {
const u = c * 10;
i.push(`--base-${u}: var(--${a.name}-${u});`);
}
i.push(`--base-text: var(--${a.name}-text);`), r.push(`${s} { ${i.join(" ")} }`);
}), r.length > 0) {
const a = r.join(`
`), s = new CSSStyleSheet();
s.replace(`${e}-${n || "1"} { } ${a}`), nt(s, "range-mapping", e);
}
}
function nt(t, n, e = "theme") {
const o = [...document.adoptedStyleSheets].filter((r) => {
const a = r.cssRules[0].cssText.includes(e), s = r.cssRules[0].cssText.includes(n);
return !a || !s;
});
document.adoptedStyleSheets = [...o, t];
}
const q = (t, { name: n, color: e }) => {
t.style.setProperty(n, e);
};
function xn(t, n) {
t && (n.forEach(({ name: e, color: o }) => q(t, { name: e, color: o })), q(t, {
name: "color",
color: "var(--base-text)"
}));
}
const pn = ({
input: t,
output: n = Bt().output,
formater: e = ct,
callback: o
}) => {
let r = 0;
function a(h) {
return h !== "accent" ? h : (r++, r > 1 ? h + r : h);
}
function s(h, l = ct) {
return {
name: a(h.name),
background: l(h.background),
shades: h.range.map((m) => l(m)),
foreground: l(h.foreground)
};
}
const i = n.map((h) => s(h, e)), c = Mn({
prefix: "--",
formated: i
}), u = kn(n, e), f = {
flattened: c,
formated: i,
output: n,
input: t,
stable: u
};
return {
...f,
attach: ({ target: h, alias: l, rangeMapping: m }) => document ? (o && o(f), gn({
outputs: f,
alias: typeof l == "boolean" ? void 0 : l,
rangeMapping: m,
target: h || {
selector: ":root"
}
})) : f
};
}, ct = Ct;
function kn(t, n = Ct) {
const e = t.find((r) => r.name === "base");
if (!e)
throw new Error("Base range not found in output");
const o = t.filter((r) => r.name !== "base");
return {
background: n(e.background),
foreground: n(e.foreground),
baseRange: e.range.map((r) => n(r)),
accents: o.map((r) => ({
name: r.name,
color: yn(r, n),
range: r.range.map((a) => n(a))
}))
};
}
function yn(t, n) {
let e = -1, o = t.range[0];
return t.range.forEach((r) => {
const a = r.toHsl();
a.s > e && (e = a.s, o = r);
}), n(o);
}
function Ct(t) {
return t.toHex();
}
function be(t) {
const n = t.toRgb();
return `rgb(${n.r}, ${n.g}, ${n.b})`;
}
function Mn({ formated: t, prefix: n }) {
const e = [];
t.forEach((r) => {
const a = n + r.name;
e.push({ name: a, color: r.background }), e.push(...o(r.shades, a)), e.push({
name: a + "-text",
color: r.foreground
});
});
function o(r, a) {
return !Array.isArray(r) || r.length === 0 ? [] : r.map((s, i) => {
if (s == null)
return null;
const c = (+i + 1) * 10;
return {
name: a + "-" + c,
color: s
};
}).filter((s) => s !== null);
}
return vn(e);
}
function vn(t) {
const n = "--foreground", e = "--background", o = t.filter((f) => f && f.name), r = o.filter((f) => f.name.startsWith(e)), a = o.filter((f) => f.name.startsWith(n)), s = o.filter(
(f) => !f.name.startsWith(e) && !f.name.startsWith(n)
), c = [...r, ...a.reverse(), ...s].filter(({ name: f }) => !u(f));
function u(f) {
return /(?:background|foreground).*contrast/i.test(f);
}
return c;
}
const v = {
x: 96.422,
y: 100,
z: 82.521
}, Rn = (t) => ({
x: k(t.x, 0, v.x),
y: k(t.y, 0, v.y),
z: k(t.z, 0, v.z),
a: k(t.a)
}), Hn = (t) => ({
x: t.x * 1.0478112 + t.y * 0.0228866 + t.z * -0.050127,
y: t.x * 0.0295424 + t.y * 0.9904844 + t.z * -0.0170491,
z: t.x * -92345e-7 + t.y * 0.0150436 + t.z * 0.7521316,
a: t.a
}), Sn = (t) => ({
x: t.x * 0.9555766 + t.y * -0.0230393 + t.z * 0.0631636,
y: t.x * -0.0282895 + t.y * 1.0099416 + t.z * 0.0210077,
z: t.x * 0.0122982 + t.y * -0.020483 + t.z * 1.3299098
}), An = (t) => {
const n = Sn(t);
return Y({
r: G(0.032404542 * n.x - 0.015371385 * n.y - 4985314e-9 * n.z),
g: G(-969266e-8 * n.x + 0.018760108 * n.y + 41556e-8 * n.z),
b: G(556434e-9 * n.x - 2040259e-9 * n.y + 0.010572252 * n.z),
a: t.a
});
}, Cn = (t) => {
const n = _(t.r), e = _(t.g), o = _(t.b), r = {
x: (n * 0.4124564 + e * 0.3575761 + o * 0.1804375) * 100,
y: (n * 0.2126729 + e * 0.7151522 + o * 0.072175) * 100,
z: (n * 0.0193339 + e * 0.119192 + o * 0.9503041) * 100,
a: t.a
};
return Rn(Hn(r));
}, I = 216 / 24389, A = 24389 / 27, Dn = (t) => ({
// CIE Lightness values less than 0% must be clamped to 0%.
// Values greater than 100% are permitted for forwards compatibility with HDR.
l: k(t.l, 0, 400),
// A and B axis values are signed (allow both positive and negative values)
// and theoretically unbounded (but in practice do not exceed ±160).
a: t.a,
b: t.b,
alpha: k(t.alpha)
}), lt = (t) => {
const n = Cn(t);
let e = n.x / v.x, o = n.y / v.y, r = n.z / v.z;
return e = e > I ? Math.cbrt(e) : (A * e + 16) / 116, o = o > I ? Math.cbrt(o) : (A * o + 16) / 116, r = r > I ? Math.cbrt(r) : (A * r + 16) / 116, {
l: 116 * o - 16,
a: 500 * (e - o),
b: 200 * (o - r),
alpha: n.a
};
}, In = (t) => {
const n = (t.l + 16) / 116, e = t.a / 500 + n, o = n - t.b / 200;
return An({
x: (Math.pow(e, 3) > I ? Math.pow(e, 3) : (116 * e - 16) / A) * v.x,
y: (t.l > A * I ? Math.pow((t.l + 16) / 116, 3) : t.l / A) * v.y,
z: (Math.pow(o, 3) > I ? Math.pow(o, 3) : (116 * o - 16) / A) * v.z,
a: t.alpha
});
}, Tn = (t, n, e) => {
const o = lt(t), r = lt(n), a = Dn({
l: o.l * (1 - e) + r.l * e,
a: o.a * (1 - e) + r.a * e,
b: o.b * (1 - e) + r.b * e,
alpha: o.alpha * (1 - e) + r.alpha * e
});
return In(a);
}, $n = (t) => {
t.prototype.mix = function(e, o = 0.5) {
const r = e instanceof t ? e : new t(e), a = Tn(this.toRgb(), r.toRgb(), o);
return new t(a);
};
function n(e, o, r = 5) {
const a = [], s = 1 / (r - 1);
for (let i = 0; i <= r - 1; i++)
a.push(e.mix(o, s * i));
return a;
}
t.prototype.tints = function(e) {
return n(this, "#fff", e);
}, t.prototype.shades = function(e) {
return n(this, "#000", e);
}, t.prototype.tones = function(e) {
return n(this, "#808080", e);
};
};
/** @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 b = {
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 wn(t, n, e = -1) {
const o = [0, 1.1];
if (isNaN(t) || isNaN(n) || Math.min(t, n) < o[0] || Math.max(t, n) > o[1])
return 0;
let r = 0, a = 0, s = "BoW";
return t = t > b.blkThrs ? t : t + Math.pow(b.blkThrs - t, b.blkClmp), n = n > b.blkThrs ? n : n + Math.pow(b.blkThrs - n, b.blkClmp), Math.abs(n - t) < b.deltaYmin ? 0 : (n > t ? (r = (Math.pow(n, b.normBG) - Math.pow(t, b.normTXT)) * b.scaleBoW, a = r < b.loClip ? 0 : r - b.loBoWoffset) : (s = "WoB", r = (Math.pow(n, b.revBG) - Math.pow(t, b.revTXT)) * b.scaleWoB, a = r > -0.1 ? 0 : r + b.loWoBoffset), e < 0 ? a * 100 : e == 0 ? Math.round(Math.abs(a) * 100) + "<sub>" + s + "</sub>" : Number.isInteger(e) ? (a * 100).toFixed(e) : 0);
}
function ft(t = [0, 0, 0]) {
function n(e) {
return Math.pow(e / 255, b.mainTRC);
}
return b.sRco * n(t[0]) + b.sGco * n(t[1]) + b.sBco * n(t[2]);
}
function V() {
return `#${Math.floor(Math.random() * 16777215).toString(16)}`;
}
function xe(t = { amount: 1 }) {
return {
background: V(),
foreground: V(),
accents: Array.from({ length: t.amount }, () => V()),
settings: { ...T, ...t }
};
}
function En(t, n, e) {
return { readability: N(t, n), index: e };
}
function Nn({ range: t, shades: n, color: e }) {
const o = n.map((a, s) => En(a, e, s)).reduce((a, s) => a.readability < s.readability ? a : s), r = [...t];
return r[o.index] = e.toRgbString(), r;
}
function Pn(t) {
return t.reduce((n, e) => (typeof e == "string" && !/^[+-]=\d+(?:\.\d+)?$/.test(e) && e !== "primer" && n.push(e), n), []);
}
function Dt({ number: t, fallback: n }) {
return typeof t > "u" ? n : t;
}
un([$n]);
const Bn = {
readability: T.readability || 11
};
function Fn(t, n) {
const e = g(t).toRgb(), o = g(n).toRgb();
return wn(ft([e.r, e.g, e.b]), ft([o.r, o.g, o.b]));
}
const N = (t, n) => {
const e = g(t), o = g(n), r = Fn(e, o);
return Math.abs(Number(r));
}, It = (t) => {
const n = g(t.foreground), e = g(t.background);
return Tt({
color: n,
contrast: e,
condition: (o) => {
const r = N(o, e), a = Dt({
fallback: Bn.readability,
number: t.readability
});
return r >= a;
}
});
};
function Tt({ color: t, contrast: n, condition: e }) {
let a = t, s = 0;
if (e(a, s)) return a;
for (; !e(a, s) && s < 120; )
s += 1, a = Ln({
power: 0.01,
color: a,
contrast: n
});
return a;
}
const Ln = ({ color: t, contrast: n, power: e }) => {
const o = t.isDark() === n.isDark();
function r() {
return t.isDark() ? t.lighten(e) : t.darken(e);
}
function a() {
return n.isDark() ? t.lighten(e) : t.darken(e);
}
return o ? r() : a();
};
function $t(t, n) {
const e = n.map((r) => Math.abs(N(t, r))), o = e.indexOf(Math.max(...e));
return n[o];
}
const gt = (t, n) => $t(t, [
n.background || g("white"),
n.foreground || g("black")
]);
function K(t, n, e = 50) {
const o = g(t), r = g(n);
return g(o).mix(r, e / 100);
}
function F(t, n, e = 0, o = 100) {
if (typeof t == "number")
return Math.max(e, Math.min(o, t));
const r = t.match(/^([+-])=(\d+(?:\.\d+)?)$/);
if (!r)
return console.warn(`Invalid relative value: ${t}, treating as current (${n})`), n;
const [, a, s] = r, i = parseFloat(s);
return a === "+" ? Math.min(o, n + i) : Math.max(e, n - i);
}
function On(t, n, e) {
if (typeof e == "number")
return K(t, n, e);
const o = g(t), r = g(n), a = o.toHsl(), s = r.toHsl(), i = F(e.mix, 0);
let c, u, f;
e.hue !== void 0 ? typeof e.hue == "number" ? c = e.hue / 100 : c = F(e.hue, i) / 100 : c = i / 100, e.saturation !== void 0 ? u = F(e.saturation, i) / 100 : u = i / 100, e.lightness !== void 0 ? f = F(e.lightness, i) / 100 : f = i / 100;
let h;
const l = s.h - a.h;
if (Math.abs(l) <= 180)
h = a.h + l * c;
else {
const d = l > 0 ? l - 360 : l + 360;
h = (a.h + d * c + 360) % 360;
}
const m = a.s + (s.s - a.s) * u, y = a.l + (s.l - a.l) * f;
return g({
h,
s: Math.max(0, Math.min(100, m)),
l: Math.max(0, Math.min(100, y)),
a: a.a + (s.a - a.a) * c
// Use hue mix for alpha
});
}
function Wn(t) {
var c;
const n = g(t.foreground).isDark(), e = g(t.background).isDark(), o = g(t.background), r = g(t.foreground), a = (c = t.settings) == null ? void 0 : c.readability;
if (n !== e)
return {
background: t.foreground,
foreground: t.background
};
const s = It({ foreground: r, background: o, readability: a });
if (s.isDark() !== e)
return {
background: s.toRgbString(),
foreground: t.background
};
function i() {
const u = o.isDark() ? g("white") : g("black"), f = o.isDark() ? g("black") : g("white"), h = N(o, f);
return Tt({
color: o,
contrast: r,
condition: (l) => N(l, u) < h
}).toRgbString();
}
return {
background: i(),
foreground: t.foreground
};
}
const _n = (t, n) => n ? {
...n,
inversed: t
} : {
...t,
...Wn(t),
inversed: t
}, Gn = (t) => g(t).isDark();
function pe(t, n) {
return $t(t, [n.background || t, n.foreground || t]);
}
const zn = {
linear: (t) => t,
easeIn: (t) => t * t,
easeOut: (t) => 1 - Math.pow(1 - t, 2),
easeInOut: (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2,
easeInCubic: (t) => t * t * t,
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
easeInOutCubic: (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2,
easeInQuart: (t) => t * t * t * t,
easeOutQuart: (t) => 1 - Math.pow(1 - t, 4),
easeInOutQuart: (t) => t < 0.5 ? 8 * t * t * t * t : 1 - Math.pow(-2 * t + 2, 4) / 2
};
function ht(t = {}) {
const {
easing: n = "linear",
count: e = 12,
min: o = 0,
max: r = 100
} = t, a = zn[n];
return Array.from({ length: e }, (s, i) => {
const c = i / (e - 1), u = a(c), f = o + u * (r - o);
return Math.round(f);
});
}
function P(t, n, e) {
const o = t ?? n ?? e;
return o ? Array.isArray(o) ? o.map((r) => typeof r == "string" ? r.startsWith("#") || isNaN(parseInt(r, 10)) ? r : parseInt(r, 10) : r) : ht(typeof o == "string" ? { easing: o } : o) : [];
}
const wt = [0.5, 2, 5, 8, 11, 13, 17, 24, "primer", 42, 46, 58], jn = wt, Et = [
{ mix: 15, hue: "next", saturation: "+=99" },
{ mix: 20, hue: "next", saturation: "+=99" },
{ mix: 25, hue: "next", saturation: "+=99" },
{ mix: 32, hue: "next", saturation: "+=99" },
{ mix: 42, hue: "next", saturation: "+=99" },
{ mix: 52, hue: "next", saturation: "+=99" },
{ mix: 66, hue: "next", saturation: "+=99" },
{ mix: 81, hue: "next", saturation: "+=99" },
"primer",
{ mix: "+=16", hue: "prev", saturation: "-=99" },
{ mix: "+=22", hue: "prev", saturation: "-=92" },
{ mix: "+=21", hue: "prev", saturation: "-=99" }
], Vn = [
{ mix: 3, hue: "next" },
{ mix: 5, hue: "next", saturation: "+=99" },
14,
24,
35,
49,
68,
88,
"primer",
{ mix: "+=5", hue: 0, saturation: "-=4" },
{ mix: "+=6", hue: 0, saturation: "-=12" },
{ mix: "+=35", hue: 0, saturation: "-=29" }
], Xn = [
{ mix: 2, hue: "next+=0.5", saturation: "+=99" },
{ mix: 9, hue: "next+=10", saturation: "+=99" },
{ mix: 18, hue: "next+=14", saturation: "+=99" },
{ mix: 31, hue: "next+=11", saturation: "+=99" },
{ mix: 42, hue: "next+=10", saturation: "+=99" },
{ mix: 54, hue: "next+=7", saturation: "+=99" },
{ mix: 61, hue: "next+=4", saturation: "+=99" },
{ mix: 79, hue: "next+=2", saturation: "+=99" },
"primer",
{ mix: "+=12", hue: 0, saturation: "-=4" },
{ mix: "+=2", hue: 0, saturation: "-=12" },
{ mix: "+=28", hue: 0, saturation: "-=29" }
], dt = [
{ mix: 8, hue: "next", saturation: 90 },
{ mix: 25, hue: "next-=10", saturation: 90 },
{ mix: 52, hue: "next-=10", saturation: 90 },
"primer",
{ mix: "+=2", hue: "+=5" },
{ mix: "+=2", hue: "+=5" },
{ mix: "+=5", hue: "+=2", saturation: "-=32" },
"+=4",
"+=2",
"+=2",
{ mix: "+=5", hue: "+=5", saturation: "+=22" },
"+=20"
], X = [
{ mix: 10, hue: "next", saturation: 90 },
{ mix: 25, hue: "next", saturation: 90 },
{ mix: 52, hue: "next", saturation: 90 },
"primer",
"+=6",
"+=4",
"+=3",
"+=3",
"+=5",
"+=2",
"+=5",
"+=15"
], U = [
{ mix: 9, hue: "next", saturation: 60 },
{ mix: 15, hue: "next-=5", saturation: 39 },
{ mix: 18, hue: "next-=5", saturation: 70 },
{ mix: 20, hue: "next-=5", saturation: 99 },
{ mix: 24, hue: "next-=5", saturation: 99 },
{ mix: 30, hue: "next-=5", saturation: 99 },
{ mix: 43, hue: "next-=5", saturation: 90 },
{ mix: 56, hue: "next-=5", saturation: 90 },
"primer",
{ mix: "+=30", hue: "prev-=0", saturation: "-=90" },
{ mix: "+=20", hue: "prev-=5", saturation: "-=90" },
{ mix: "+=18", hue: "prev-=10", saturation: "-=90" }
], mt = [
{ mix: 9, hue: "next+=10", saturation: 90 },
{ mix: 15, hue: "next+=10", saturation: 99 },
{ mix: 25, hue: "next+=10", saturation: 90 },
{ mix: 30, hue: "next+=10", saturation: 99 },
{ mix: 44, hue: "next+=10", saturation: 99 },
{ mix: 60, hue: "next+=10", saturation: 99 },
{ mix: 73, hue: "next+=10", saturation: 90 },
{ mix: 86, hue: "next+=10", saturation: 90 },
"primer",
{ mix: "+=25", hue: "prev-=0", saturation: "-=90" },
{ mix: "+=10", hue: "prev-=0", saturation: "-=90" },
{ mix: "+=7", hue: "prev-=0", saturation: "-=90" }
], x = {
range: {
light: Vn,
dark: Et
}
}, J = [
{
name: "gray",
hex: "#8B8D98",
range: { light: wt, dark: jn }
},
{
name: "blue",
hex: "#0090FF",
range: x.range
},
{
name: "red",
hex: "#E5484D",
range: x.range
},
{
name: "green",
hex: "#30A46C",
range: x.range
},
{
name: "tomato",
hex: "#E54D2E",
range: x.range
},
{
name: "crimson",
hex: "#E93D82",
range: x.range
},
{
name: "pink",
hex: "#D6409F",
range: x.range
},
{
name: "plum",
hex: "#AB4ABA",
range: x.range
},
{
name: "purple",
hex: "#8E4EC6",
range: x.range
},
{
name: "violet",
hex: "#6E56CF",
range: x.range
},
{
name: "iris",
hex: "#5B5BD6",
range: x.range
},
{
name: "indigo",
hex: "#3E63DD",
range: x.range
},
{
name: "cyan",
hex: "#00A2C7",
range: x.range
},
{
name: "teal",
hex: "#12A594",
range: x.range
},
{
name: "jade",
hex: "#29A383",
range: x.range
},
{
name: "grass",
hex: "#46A758",
range: x.range
},
{
name: "bronze",
hex: "#A18072",
range: x.range
},
{
name: "gold",
hex: "#978365",
range: x.range
},
{
name: "brown",
hex: "#AD7F58",
range: x.range
},
{
name: "orange",
hex: "#F76B15",
range: {
light: Xn,
dark: Et
}
},
{
name: "amber",
hex: "#FFC53D",
range: {
light: dt,
dark: U
}
},
{
name: "yellow",
hex: "#FFDC00",
range: {
light: dt,
dark: U
}
},
{
name: "lime",
hex: "#BDEE63",
range: {
light: X,
dark: U
}
},
{
name: "mint",
hex: "#86EAD4",
range: {
light: X,
dark: mt
}
},
{
name: "sky",
hex: "#7CE2FE",
range: {
light: X,
dark: mt
}
}
], Nt = /* @__PURE__ */ new Map();
J.forEach((t) => {
Nt.set(t.name.toLowerCase(), t);
});
function Un(t) {
return Nt.get(t.toLowerCase());
}
function Qn(t, n) {
const e = t.toRgb(), o = n.toRgb(), r = e.r - o.r, a = e.g - o.g, s = e.b - o.b;
return Math.sqrt(2 * r * r + 4 * a * a + 3 * s * s);
}
function qn(t) {
const n = g(t);
let e = J[0], o = 1 / 0;
for (const r of J) {
const a = g(r.hex), s = Qn(n, a);
s < o && (o = s, e = r);
}
return e;
}
function Pt(t) {
const n = Un(t);
if (n)
return {
hex: n.hex,
preset: n
};
const e = qn(t);
return {
hex: t,
preset: e
};
}
const et = /^[+-]=\d+(?:\.\d+)?$/, Kn = 0, Jn = 100, Zn = "accent";
function Yn(t) {
return typeof t == "string" && et.test(t);
}
function bt(t) {
return typeof t == "string" && !et.test(t) && t !== "primer";
}
function xt(t, n) {
const e = t.match(/^([+-])=(\d+(?:\.\d+)?)$/);
if (!e) return n;
const [, o, r] = e, a = parseFloat(r);
return o === "+" ? Math.min(Jn, n + a) : Math.max(Kn, n - a);
}
function te(t, n, e, o, r, a, s, i) {
if (typeof t == "string") {
const c = t.match(/^(next|prev)([+-]=)(\d+(?:\.\d+)?)$/);
if (c) {
const [, u, f, h] = c, l = parseFloat(h), m = f === "+=" ? l : -l;
let y;
if (u === "next") {
const S = e.find((D) => D > n);
S !== void 0 ? y = o[e.indexOf(S)].toHsl().h : y = i.toHsl().h;
} else {
const S = e.filter((D) => D < n);
if (S.length > 0) {
const D = S[S.length - 1];
y = o[e.indexOf(D)].toHsl().h;
} else
y = s.toHsl().h;
}
let d = (y + m) % 360;
d < 0 && (d += 360);
const R = r.toHsl(), C = a.toHsl();
Math.abs(C.h - R.h) < 1 && (C.h = d);
let H = C.h - R.h, $ = d;
return Math.abs(H) > 180 && (H = H > 0 ? H - 360 : H + 360, d > R.h + 180 ? $ = d - 360 : d < R.h - 180 && ($ = d + 360)), ($ - R.h) / H * 100;
}
}
if (t === "next") {
const c = e.find((d) => d > n);
let u;
c !== void 0 ? u = o[e.indexOf(c)].toHsl().h : u = i.toHsl().h;
const f = r.toHsl(), h = a.toHsl();
Math.abs(h.h - f.h) < 1 && (h.h = u);
let l = h.h - f.h, m = u;
return Math.abs(l) > 180 && (l = l > 0 ? l - 360 : l + 360, u > f.h + 180 ? m = u - 360 : u < f.h - 180 && (m = u + 360)), (m - f.h) / l * 100;
}
if (t === "prev") {
const c = e.filter((d) => d < n);
let u;
if (c.length > 0) {
const d = c[c.length - 1];
u = o[e.indexOf(d)].toHsl().h;
} else
u = s.toHsl().h;
const f = r.toHsl(), h = a.toHsl();
Math.abs(h.h - f.h) < 1 && (h.h = u);
let l = h.h - f.h, m = u;
return Math.abs(l) > 180 && (l = l > 0 ? l - 360 : l + 360, u > f.h + 180 ? m = u - 360 : u < f.h - 180 && (m = u + 360)), (m - f.h) / l * 100;
}
return t;
}
function rt({ from: t, to: n, range: e, accentColor: o }) {
const r = e.map((l) => l === "primer" && o ? o : l), a = Pn(r), s = [], i = [];
r.forEach((l, m) => {
bt(l) && (s.push(m), i.push(g(l)));
});
let c = 0, u = t, f = t, h = a.length > 0 ? g(a[0]) : n;
return r.map((l, m) => {
if (Yn(l)) {
c = xt(l, c);
const d = K(u, h, c);
return u = d, d;
}
if (bt(l)) {
const d = g(l);
return u = d, f = d, a.shift(), h = a.length > 0 ? g(a[0]) : n, c = 0, d;
}
if (typeof l == "object") {
const d = l.mix, R = typeof d == "string";
typeof d == "number" ? c = d : typeof d == "string" && (c = xt(d, c));
const C = R ? u : f, H = te(
l.hue,
m,
s,
i,
C,
h,
t,
n
), $ = {
mix: c,
hue: H,
saturation: l.saturation,
lightness: l.lightness
}, W = On(C, h, $);
return u = W, W;
}
c = l;
const y = K(f, h, c);
return u = y, y;
});
}
function ne({ input: t, adjusted: n, range: e, color: o }) {
if (!o) return e;
const r = rt({
from: n.background,
to: n.foreground,
range: Z(n, t.settings)
});
return Nn({ range: e, shades: r, color: g(o) });
}
function ee(t, n, e) {
const o = t.slice();
return o[n] = e, o;
}
function re(t, n, e) {
var l;
const o = typeof n == "string", r = o ? n : n.color, a = (l = e.settings) == null ? void 0 : l.insertion, s = !o && n.range, i = pt(t, e.settings, !0), c = i.some((m) => m === "primer");
let u;
if (!s && r && !c) {
const { preset: m } = Pt(r), d = t.background.isDark() ? m.range.dark : m.range.light;
u = P(d);
} else
u = o ? i : pt(t, n, !1) || i;
return u.some((m) => m === "primer") || u.every((m) => typeof m == "string" && m !== "primer") ? u : a && r ? ee(u, a, r) : !a && r ? ne({ input: e, adjusted: t, range: u, color: r }) : u;
}
function oe(t, n) {
return n.accents.map((e) => {
const o = typeof e == "string", r = o ? void 0 : e.name;
let a = o ? e : e.color;
if (a) {
const { hex: i } = Pt(a);
a = i;
}
const s = re(n, e, t);
return {
name: r || Zn,
background: gt(n.foreground, n),
foreground: gt(n.background, n),
range: rt({
from: n.background,
to: n.foreground,
range: s,
accentColor: a
// Pass accent color to replace "primer" keyword
})
};
});
}
function Z(t, n) {
const e = t.background.isDark(), o = n == null ? void 0 : n.range, r = T.range, a = r && typeof r == "object" && !Array.isArray(r) && ("light" in r || "dark" in r) ? e ? r.dark : r.light : void 0;
if (o && typeof o == "object" && !Array.isArray(o) && ("light" in o || "dark" in o)) {
const s = e ? o.dark : o.light;
return P(s, void 0, a);
}
return P(o, void 0, a);
}
function ae(t) {
return !t || !Array.isArray(t) ? !1 : t.some((n) => typeof n == "string" && n !== "primer" && !et.test(n));
}
function pt(t, n, e = !1) {
const o = t.background.isDark(), r = n == null ? void 0 : n.range, a = T.range, s = a && typeof a == "object" && !Array.isArray(a) && ("light" in a || "dark" in a) ? o ? a.dark : a.light : void 0;
let i;
if (r && typeof r == "object" && !Array.isArray(r) && ("light" in r || "dark" in r) ? i = o ? r.dark : r.light : i = r, e) {
const c = ae(i) ? void 0 : i;
return P(c, void 0, s);
}
return P(i, void 0, s);
}
function se(t, n) {
const { background: e, foreground: o } = n, r = t.baseRange ? Z(n, { range: t.baseRange }) : Z(n, t.settings);
return {
name: "base",
background: e,
foreground: o,
range: rt({ from: e, to: o, range: r })
};
}
function ie(t, n) {
return [se(t, n), ...oe(t, n)];
}
function Bt(t = O) {
const n = ue(t), e = ce(n);
return fe({
input: n,
output: ie(n, e),
inversed: n.inversed
});
}
function ue(t = O) {
const n = {
...T,
..."settings" in t ? t.settings : {}
}, e = {
settings: n,
inversed: {
...n,
..."inversed" in t && t.inversed && "settings" in t.inversed ? t.inversed.settings : {}
}
}, o = "inversed" in t && t.inversed ? {
...t.inversed,
settings: e.inversed
} : void 0;
return {
...O,
...t,
settings: e.settings,
inversed: o
};
}
function ce(t = O) {
var r;
const n = g(t.background), e = It({
readability: Dt({ number: (r = t.settings) == null ? void 0 : r.readability, fallback: 4 }),
foreground: g(t.foreground),
background: n
});
return {
accents: Array.isArray(t.accents) ? t.accents : [t.accents],
background: n,
foreground: e
};
}
function le(t) {
if (!t) return;
const n = typeof t == "string";
return {
element: t instanceof HTMLElement || t === null ? t : void 0,
selector: n ? t : void 0
};
}
function fe({
input: t,
output: n,
inversed: e
}) {
function o(r) {
var s, i;
const a = r || ((s = t.settings) == null ? void 0 : s.formater);
return pn({ output: n, formater: a, input: t, callback: (i = t.settings) == null ? void 0 : i.callback });
}
return {
input: t,
output: n,
isDark: () => Gn(t.background),
format: (r) => o(r),
inverse: () => Bt(_n(t, e)),
apply: (r) => {
var f;
const { alias: a, formater: s } = r || {}, i = le(r == null ? void 0 : r.target), u = o(s).attach({ alias: a, target: i });
return (f = t.settings) != null && f.callback && t.settings.callback(u), u;
}
};
}
export {
L as UmbraSwatch,
gn as attach,
K as colorMix,
J as colorPresets,
T as defaultSettings,
zn as easingFunctions,
un as extend,
qn as findClosestPreset,
pe as findContrast,
pn as format,
ht as generateTints,
de as getFormat,
Un as getPresetByName,
N as getReadability,
Ct as hex,
_n as inverse,
Gn as isDark,
$t as mostReadable,
me as random,
xe as randomScheme,
Pt as resolveColorPreset,
P as resolveTints,
be as rgb,
g as swatch,
Bt as umbra,
ie as umbraGenerate,
fe as umbraHydrate
};