UNPKG

@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
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 };