use-material-you
Version:
React hook to create dynamic schemes and variants based on M3/material-color-utilities
1,285 lines • 162 kB
JavaScript
import * as Fe from "react";
function X(a) {
return a < 0 ? -1 : a === 0 ? 0 : 1;
}
function he(a, e, t) {
return (1 - t) * a + t * e;
}
function je(a, e, t) {
return t < a ? a : t > e ? e : t;
}
function G(a, e, t) {
return t < a ? a : t > e ? e : t;
}
function Ae(a) {
return a = a % 360, a < 0 && (a = a + 360), a;
}
function W(a) {
return a = a % 360, a < 0 && (a = a + 360), a;
}
function Je(a, e) {
return 180 - Math.abs(Math.abs(a - e) - 180);
}
function Ie(a, e) {
const t = a[0] * e[0][0] + a[1] * e[0][1] + a[2] * e[0][2], r = a[0] * e[1][0] + a[1] * e[1][1] + a[2] * e[1][2], n = a[0] * e[2][0] + a[1] * e[2][1] + a[2] * e[2][2];
return [t, r, n];
}
const Ue = [
[0.41233895, 0.35762064, 0.18051042],
[0.2126, 0.7152, 0.0722],
[0.01932141, 0.11916382, 0.95034478]
], Qe = [
[
3.2413774792388685,
-1.5376652402851851,
-0.49885366846268053
],
[
-0.9691452513005321,
1.8758853451067872,
0.04156585616912061
],
[
0.05562093689691305,
-0.20395524564742123,
1.0571799111220335
]
], Be = [95.047, 100, 108.883];
function Se(a, e, t) {
return (255 << 24 | (a & 255) << 16 | (e & 255) << 8 | t & 255) >>> 0;
}
function Ne(a) {
const e = ie(a[0]), t = ie(a[1]), r = ie(a[2]);
return Se(e, t, r);
}
function Ze(a) {
return a >> 24 & 255;
}
function ke(a) {
return a >> 16 & 255;
}
function Ce(a) {
return a >> 8 & 255;
}
function be(a) {
return a & 255;
}
function ze(a, e, t) {
const r = Qe, n = r[0][0] * a + r[0][1] * e + r[0][2] * t, o = r[1][0] * a + r[1][1] * e + r[1][2] * t, i = r[2][0] * a + r[2][1] * e + r[2][2] * t, c = ie(n), f = ie(o), p = ie(i);
return Se(c, f, p);
}
function et(a) {
const e = te(ke(a)), t = te(Ce(a)), r = te(be(a));
return Ie([e, t, r], Ue);
}
function tt(a, e, t) {
const r = Be, n = (a + 16) / 116, o = e / 500 + n, i = n - t / 200, c = Te(o), f = Te(n), p = Te(i), h = c * r[0], y = f * r[1], P = p * r[2];
return ze(h, y, P);
}
function Ge(a) {
const e = te(ke(a)), t = te(Ce(a)), r = te(be(a)), n = Ue, o = n[0][0] * e + n[0][1] * t + n[0][2] * r, i = n[1][0] * e + n[1][1] * t + n[1][2] * r, c = n[2][0] * e + n[2][1] * t + n[2][2] * r, f = Be, p = o / f[0], h = i / f[1], y = c / f[2], P = fe(p), g = fe(h), m = fe(y), d = 116 * g - 16, T = 500 * (P - g), D = 200 * (g - m);
return [d, T, D];
}
function rt(a) {
const e = ae(a), t = ie(e);
return Se(t, t, t);
}
function Ve(a) {
const e = et(a)[1];
return 116 * fe(e / 100) - 16;
}
function ae(a) {
return 100 * Te((a + 16) / 116);
}
function ve(a) {
return fe(a / 100) * 116 - 16;
}
function te(a) {
const e = a / 255;
return e <= 0.040449936 ? e / 12.92 * 100 : Math.pow((e + 0.055) / 1.055, 2.4) * 100;
}
function ie(a) {
const e = a / 100;
let t = 0;
return e <= 31308e-7 ? t = e * 12.92 : t = 1.055 * Math.pow(e, 1 / 2.4) - 0.055, je(0, 255, Math.round(t * 255));
}
function nt() {
return Be;
}
function fe(a) {
const e = 0.008856451679035631, t = 24389 / 27;
return a > e ? Math.pow(a, 1 / 3) : (t * a + 16) / 116;
}
function Te(a) {
const e = 0.008856451679035631, t = 24389 / 27, r = a * a * a;
return r > e ? r : (116 * a - 16) / t;
}
class Z {
/**
* Create ViewingConditions from a simple, physically relevant, set of
* parameters.
*
* @param whitePoint White point, measured in the XYZ color space.
* default = D65, or sunny day afternoon
* @param adaptingLuminance The luminance of the adapting field. Informally,
* how bright it is in the room where the color is viewed. Can be
* calculated from lux by multiplying lux by 0.0586. default = 11.72,
* or 200 lux.
* @param backgroundLstar The lightness of the area surrounding the color.
* measured by L* in L*a*b*. default = 50.0
* @param surround A general description of the lighting surrounding the
* color. 0 is pitch dark, like watching a movie in a theater. 1.0 is a
* dimly light room, like watching TV at home at night. 2.0 means there
* is no difference between the lighting on the color and around it.
* default = 2.0
* @param discountingIlluminant Whether the eye accounts for the tint of the
* ambient lighting, such as knowing an apple is still red in green light.
* default = false, the eye does not perform this process on
* self-luminous objects like displays.
*/
static make(e = nt(), t = 200 / Math.PI * ae(50) / 100, r = 50, n = 2, o = !1) {
const i = e, c = i[0] * 0.401288 + i[1] * 0.650173 + i[2] * -0.051461, f = i[0] * -0.250268 + i[1] * 1.204414 + i[2] * 0.045854, p = i[0] * -2079e-6 + i[1] * 0.048952 + i[2] * 0.953127, h = 0.8 + n / 10, y = h >= 0.9 ? he(0.59, 0.69, (h - 0.9) * 10) : he(0.525, 0.59, (h - 0.8) * 10);
let P = o ? 1 : h * (1 - 1 / 3.6 * Math.exp((-t - 42) / 92));
P = P > 1 ? 1 : P < 0 ? 0 : P;
const g = h, m = [
P * (100 / c) + 1 - P,
P * (100 / f) + 1 - P,
P * (100 / p) + 1 - P
], d = 1 / (5 * t + 1), T = d * d * d * d, D = 1 - T, A = T * t + 0.1 * D * D * Math.cbrt(5 * t), C = ae(r) / e[1], v = 1.48 + Math.sqrt(C), M = 0.725 / Math.pow(C, 0.2), O = M, k = [
Math.pow(A * m[0] * c / 100, 0.42),
Math.pow(A * m[1] * f / 100, 0.42),
Math.pow(A * m[2] * p / 100, 0.42)
], F = [
400 * k[0] / (k[0] + 27.13),
400 * k[1] / (k[1] + 27.13),
400 * k[2] / (k[2] + 27.13)
], N = (2 * F[0] + F[1] + 0.05 * F[2]) * M;
return new Z(C, N, M, O, y, g, m, A, Math.pow(A, 0.25), v);
}
/**
* Parameters are intermediate values of the CAM16 conversion process. Their
* names are shorthand for technical color science terminology, this class
* would not benefit from documenting them individually. A brief overview
* is available in the CAM16 specification, and a complete overview requires
* a color science textbook, such as Fairchild's Color Appearance Models.
*/
constructor(e, t, r, n, o, i, c, f, p, h) {
this.n = e, this.aw = t, this.nbb = r, this.ncb = n, this.c = o, this.nc = i, this.rgbD = c, this.fl = f, this.fLRoot = p, this.z = h;
}
}
Z.DEFAULT = Z.make();
class q {
/**
* All of the CAM16 dimensions can be calculated from 3 of the dimensions, in
* the following combinations:
* - {j or q} and {c, m, or s} and hue
* - jstar, astar, bstar
* Prefer using a static method that constructs from 3 of those dimensions.
* This constructor is intended for those methods to use to return all
* possible dimensions.
*
* @param hue
* @param chroma informally, colorfulness / color intensity. like saturation
* in HSL, except perceptually accurate.
* @param j lightness
* @param q brightness; ratio of lightness to white point's lightness
* @param m colorfulness
* @param s saturation; ratio of chroma to white point's chroma
* @param jstar CAM16-UCS J coordinate
* @param astar CAM16-UCS a coordinate
* @param bstar CAM16-UCS b coordinate
*/
constructor(e, t, r, n, o, i, c, f, p) {
this.hue = e, this.chroma = t, this.j = r, this.q = n, this.m = o, this.s = i, this.jstar = c, this.astar = f, this.bstar = p;
}
/**
* CAM16 instances also have coordinates in the CAM16-UCS space, called J*,
* a*, b*, or jstar, astar, bstar in code. CAM16-UCS is included in the CAM16
* specification, and is used to measure distances between colors.
*/
distance(e) {
const t = this.jstar - e.jstar, r = this.astar - e.astar, n = this.bstar - e.bstar, o = Math.sqrt(t * t + r * r + n * n);
return 1.41 * Math.pow(o, 0.63);
}
/**
* @param argb ARGB representation of a color.
* @return CAM16 color, assuming the color was viewed in default viewing
* conditions.
*/
static fromInt(e) {
return q.fromIntInViewingConditions(e, Z.DEFAULT);
}
/**
* @param argb ARGB representation of a color.
* @param viewingConditions Information about the environment where the color
* was observed.
* @return CAM16 color.
*/
static fromIntInViewingConditions(e, t) {
const r = (e & 16711680) >> 16, n = (e & 65280) >> 8, o = e & 255, i = te(r), c = te(n), f = te(o), p = 0.41233895 * i + 0.35762064 * c + 0.18051042 * f, h = 0.2126 * i + 0.7152 * c + 0.0722 * f, y = 0.01932141 * i + 0.11916382 * c + 0.95034478 * f, P = 0.401288 * p + 0.650173 * h - 0.051461 * y, g = -0.250268 * p + 1.204414 * h + 0.045854 * y, m = -2079e-6 * p + 0.048952 * h + 0.953127 * y, d = t.rgbD[0] * P, T = t.rgbD[1] * g, D = t.rgbD[2] * m, A = Math.pow(t.fl * Math.abs(d) / 100, 0.42), C = Math.pow(t.fl * Math.abs(T) / 100, 0.42), v = Math.pow(t.fl * Math.abs(D) / 100, 0.42), M = X(d) * 400 * A / (A + 27.13), O = X(T) * 400 * C / (C + 27.13), k = X(D) * 400 * v / (v + 27.13), F = (11 * M + -12 * O + k) / 11, N = (M + O - 2 * k) / 9, L = (20 * M + 20 * O + 21 * k) / 20, U = (40 * M + 20 * O + k) / 20, Q = Math.atan2(N, F) * 180 / Math.PI, z = W(Q), oe = z * Math.PI / 180, me = U * t.nbb, re = 100 * Math.pow(me / t.aw, t.c * t.z), pe = 4 / t.c * Math.sqrt(re / 100) * (t.aw + 4) * t.fLRoot, we = z < 20.14 ? z + 360 : z, xe = 0.25 * (Math.cos(we * Math.PI / 180 + 2) + 3.8), De = 5e4 / 13 * xe * t.nc * t.ncb * Math.sqrt(F * F + N * N) / (L + 0.305), ge = Math.pow(De, 0.9) * Math.pow(1.64 - Math.pow(0.29, t.n), 0.73), Le = ge * Math.sqrt(re / 100), Me = Le * t.fLRoot, Xe = 50 * Math.sqrt(ge * t.c / (t.aw + 4)), qe = (1 + 100 * 7e-3) * re / (1 + 7e-3 * re), Oe = 1 / 0.0228 * Math.log(1 + 0.0228 * Me), We = Oe * Math.cos(oe), $e = Oe * Math.sin(oe);
return new q(z, Le, re, pe, Me, Xe, qe, We, $e);
}
/**
* @param j CAM16 lightness
* @param c CAM16 chroma
* @param h CAM16 hue
*/
static fromJch(e, t, r) {
return q.fromJchInViewingConditions(e, t, r, Z.DEFAULT);
}
/**
* @param j CAM16 lightness
* @param c CAM16 chroma
* @param h CAM16 hue
* @param viewingConditions Information about the environment where the color
* was observed.
*/
static fromJchInViewingConditions(e, t, r, n) {
const o = 4 / n.c * Math.sqrt(e / 100) * (n.aw + 4) * n.fLRoot, i = t * n.fLRoot, c = t / Math.sqrt(e / 100), f = 50 * Math.sqrt(c * n.c / (n.aw + 4)), p = r * Math.PI / 180, h = (1 + 100 * 7e-3) * e / (1 + 7e-3 * e), y = 1 / 0.0228 * Math.log(1 + 0.0228 * i), P = y * Math.cos(p), g = y * Math.sin(p);
return new q(r, t, e, o, i, f, h, P, g);
}
/**
* @param jstar CAM16-UCS lightness.
* @param astar CAM16-UCS a dimension. Like a* in L*a*b*, it is a Cartesian
* coordinate on the Y axis.
* @param bstar CAM16-UCS b dimension. Like a* in L*a*b*, it is a Cartesian
* coordinate on the X axis.
*/
static fromUcs(e, t, r) {
return q.fromUcsInViewingConditions(e, t, r, Z.DEFAULT);
}
/**
* @param jstar CAM16-UCS lightness.
* @param astar CAM16-UCS a dimension. Like a* in L*a*b*, it is a Cartesian
* coordinate on the Y axis.
* @param bstar CAM16-UCS b dimension. Like a* in L*a*b*, it is a Cartesian
* coordinate on the X axis.
* @param viewingConditions Information about the environment where the color
* was observed.
*/
static fromUcsInViewingConditions(e, t, r, n) {
const o = t, i = r, c = Math.sqrt(o * o + i * i), p = (Math.exp(c * 0.0228) - 1) / 0.0228 / n.fLRoot;
let h = Math.atan2(i, o) * (180 / Math.PI);
h < 0 && (h += 360);
const y = e / (1 - (e - 100) * 7e-3);
return q.fromJchInViewingConditions(y, p, h, n);
}
/**
* @return ARGB representation of color, assuming the color was viewed in
* default viewing conditions, which are near-identical to the default
* viewing conditions for sRGB.
*/
toInt() {
return this.viewed(Z.DEFAULT);
}
/**
* @param viewingConditions Information about the environment where the color
* will be viewed.
* @return ARGB representation of color
*/
viewed(e) {
const t = this.chroma === 0 || this.j === 0 ? 0 : this.chroma / Math.sqrt(this.j / 100), r = Math.pow(t / Math.pow(1.64 - Math.pow(0.29, e.n), 0.73), 1 / 0.9), n = this.hue * Math.PI / 180, o = 0.25 * (Math.cos(n + 2) + 3.8), i = e.aw * Math.pow(this.j / 100, 1 / e.c / e.z), c = o * (5e4 / 13) * e.nc * e.ncb, f = i / e.nbb, p = Math.sin(n), h = Math.cos(n), y = 23 * (f + 0.305) * r / (23 * c + 11 * r * h + 108 * r * p), P = y * h, g = y * p, m = (460 * f + 451 * P + 288 * g) / 1403, d = (460 * f - 891 * P - 261 * g) / 1403, T = (460 * f - 220 * P - 6300 * g) / 1403, D = Math.max(0, 27.13 * Math.abs(m) / (400 - Math.abs(m))), A = X(m) * (100 / e.fl) * Math.pow(D, 1 / 0.42), C = Math.max(0, 27.13 * Math.abs(d) / (400 - Math.abs(d))), v = X(d) * (100 / e.fl) * Math.pow(C, 1 / 0.42), M = Math.max(0, 27.13 * Math.abs(T) / (400 - Math.abs(T))), O = X(T) * (100 / e.fl) * Math.pow(M, 1 / 0.42), k = A / e.rgbD[0], F = v / e.rgbD[1], N = O / e.rgbD[2], L = 1.86206786 * k - 1.01125463 * F + 0.14918677 * N, U = 0.38752654 * k + 0.62144744 * F - 897398e-8 * N, $ = -0.0158415 * k - 0.03412294 * F + 1.04996444 * N;
return ze(L, U, $);
}
/// Given color expressed in XYZ and viewed in [viewingConditions], convert to
/// CAM16.
static fromXyzInViewingConditions(e, t, r, n) {
const o = 0.401288 * e + 0.650173 * t - 0.051461 * r, i = -0.250268 * e + 1.204414 * t + 0.045854 * r, c = -2079e-6 * e + 0.048952 * t + 0.953127 * r, f = n.rgbD[0] * o, p = n.rgbD[1] * i, h = n.rgbD[2] * c, y = Math.pow(n.fl * Math.abs(f) / 100, 0.42), P = Math.pow(n.fl * Math.abs(p) / 100, 0.42), g = Math.pow(n.fl * Math.abs(h) / 100, 0.42), m = X(f) * 400 * y / (y + 27.13), d = X(p) * 400 * P / (P + 27.13), T = X(h) * 400 * g / (g + 27.13), D = (11 * m + -12 * d + T) / 11, A = (m + d - 2 * T) / 9, C = (20 * m + 20 * d + 21 * T) / 20, v = (40 * m + 20 * d + T) / 20, O = Math.atan2(A, D) * 180 / Math.PI, k = O < 0 ? O + 360 : O >= 360 ? O - 360 : O, F = k * Math.PI / 180, N = v * n.nbb, L = 100 * Math.pow(N / n.aw, n.c * n.z), U = 4 / n.c * Math.sqrt(L / 100) * (n.aw + 4) * n.fLRoot, $ = k < 20.14 ? k + 360 : k, Q = 1 / 4 * (Math.cos($ * Math.PI / 180 + 2) + 3.8), oe = 5e4 / 13 * Q * n.nc * n.ncb * Math.sqrt(D * D + A * A) / (C + 0.305), me = Math.pow(oe, 0.9) * Math.pow(1.64 - Math.pow(0.29, n.n), 0.73), re = me * Math.sqrt(L / 100), pe = re * n.fLRoot, we = 50 * Math.sqrt(me * n.c / (n.aw + 4)), xe = (1 + 100 * 7e-3) * L / (1 + 7e-3 * L), Ee = Math.log(1 + 0.0228 * pe) / 0.0228, De = Ee * Math.cos(F), ge = Ee * Math.sin(F);
return new q(k, re, L, U, pe, we, xe, De, ge);
}
/// XYZ representation of CAM16 seen in [viewingConditions].
xyzInViewingConditions(e) {
const t = this.chroma === 0 || this.j === 0 ? 0 : this.chroma / Math.sqrt(this.j / 100), r = Math.pow(t / Math.pow(1.64 - Math.pow(0.29, e.n), 0.73), 1 / 0.9), n = this.hue * Math.PI / 180, o = 0.25 * (Math.cos(n + 2) + 3.8), i = e.aw * Math.pow(this.j / 100, 1 / e.c / e.z), c = o * (5e4 / 13) * e.nc * e.ncb, f = i / e.nbb, p = Math.sin(n), h = Math.cos(n), y = 23 * (f + 0.305) * r / (23 * c + 11 * r * h + 108 * r * p), P = y * h, g = y * p, m = (460 * f + 451 * P + 288 * g) / 1403, d = (460 * f - 891 * P - 261 * g) / 1403, T = (460 * f - 220 * P - 6300 * g) / 1403, D = Math.max(0, 27.13 * Math.abs(m) / (400 - Math.abs(m))), A = X(m) * (100 / e.fl) * Math.pow(D, 1 / 0.42), C = Math.max(0, 27.13 * Math.abs(d) / (400 - Math.abs(d))), v = X(d) * (100 / e.fl) * Math.pow(C, 1 / 0.42), M = Math.max(0, 27.13 * Math.abs(T) / (400 - Math.abs(T))), O = X(T) * (100 / e.fl) * Math.pow(M, 1 / 0.42), k = A / e.rgbD[0], F = v / e.rgbD[1], N = O / e.rgbD[2], L = 1.86206786 * k - 1.01125463 * F + 0.14918677 * N, U = 0.38752654 * k + 0.62144744 * F - 897398e-8 * N, $ = -0.0158415 * k - 0.03412294 * F + 1.04996444 * N;
return [L, U, $];
}
}
class x {
/**
* Sanitizes a small enough angle in radians.
*
* @param angle An angle in radians; must not deviate too much
* from 0.
* @return A coterminal angle between 0 and 2pi.
*/
static sanitizeRadians(e) {
return (e + Math.PI * 8) % (Math.PI * 2);
}
/**
* Delinearizes an RGB component, returning a floating-point
* number.
*
* @param rgbComponent 0.0 <= rgb_component <= 100.0, represents
* linear R/G/B channel
* @return 0.0 <= output <= 255.0, color channel converted to
* regular RGB space
*/
static trueDelinearized(e) {
const t = e / 100;
let r = 0;
return t <= 31308e-7 ? r = t * 12.92 : r = 1.055 * Math.pow(t, 1 / 2.4) - 0.055, r * 255;
}
static chromaticAdaptation(e) {
const t = Math.pow(Math.abs(e), 0.42);
return X(e) * 400 * t / (t + 27.13);
}
/**
* Returns the hue of a linear RGB color in CAM16.
*
* @param linrgb The linear RGB coordinates of a color.
* @return The hue of the color in CAM16, in radians.
*/
static hueOf(e) {
const t = Ie(e, x.SCALED_DISCOUNT_FROM_LINRGB), r = x.chromaticAdaptation(t[0]), n = x.chromaticAdaptation(t[1]), o = x.chromaticAdaptation(t[2]), i = (11 * r + -12 * n + o) / 11, c = (r + n - 2 * o) / 9;
return Math.atan2(c, i);
}
static areInCyclicOrder(e, t, r) {
const n = x.sanitizeRadians(t - e), o = x.sanitizeRadians(r - e);
return n < o;
}
/**
* Solves the lerp equation.
*
* @param source The starting number.
* @param mid The number in the middle.
* @param target The ending number.
* @return A number t such that lerp(source, target, t) = mid.
*/
static intercept(e, t, r) {
return (t - e) / (r - e);
}
static lerpPoint(e, t, r) {
return [
e[0] + (r[0] - e[0]) * t,
e[1] + (r[1] - e[1]) * t,
e[2] + (r[2] - e[2]) * t
];
}
/**
* Intersects a segment with a plane.
*
* @param source The coordinates of point A.
* @param coordinate The R-, G-, or B-coordinate of the plane.
* @param target The coordinates of point B.
* @param axis The axis the plane is perpendicular with. (0: R, 1:
* G, 2: B)
* @return The intersection point of the segment AB with the plane
* R=coordinate, G=coordinate, or B=coordinate
*/
static setCoordinate(e, t, r, n) {
const o = x.intercept(e[n], t, r[n]);
return x.lerpPoint(e, o, r);
}
static isBounded(e) {
return 0 <= e && e <= 100;
}
/**
* Returns the nth possible vertex of the polygonal intersection.
*
* @param y The Y value of the plane.
* @param n The zero-based index of the point. 0 <= n <= 11.
* @return The nth possible vertex of the polygonal intersection
* of the y plane and the RGB cube, in linear RGB coordinates, if
* it exists. If this possible vertex lies outside of the cube,
* [-1.0, -1.0, -1.0] is returned.
*/
static nthVertex(e, t) {
const r = x.Y_FROM_LINRGB[0], n = x.Y_FROM_LINRGB[1], o = x.Y_FROM_LINRGB[2], i = t % 4 <= 1 ? 0 : 100, c = t % 2 === 0 ? 0 : 100;
if (t < 4) {
const f = i, p = c, h = (e - f * n - p * o) / r;
return x.isBounded(h) ? [h, f, p] : [-1, -1, -1];
} else if (t < 8) {
const f = i, p = c, h = (e - p * r - f * o) / n;
return x.isBounded(h) ? [p, h, f] : [-1, -1, -1];
} else {
const f = i, p = c, h = (e - f * r - p * n) / o;
return x.isBounded(h) ? [f, p, h] : [-1, -1, -1];
}
}
/**
* Finds the segment containing the desired color.
*
* @param y The Y value of the color.
* @param targetHue The hue of the color.
* @return A list of two sets of linear RGB coordinates, each
* corresponding to an endpoint of the segment containing the
* desired color.
*/
static bisectToSegment(e, t) {
let r = [-1, -1, -1], n = r, o = 0, i = 0, c = !1, f = !0;
for (let p = 0; p < 12; p++) {
const h = x.nthVertex(e, p);
if (h[0] < 0)
continue;
const y = x.hueOf(h);
if (!c) {
r = h, n = h, o = y, i = y, c = !0;
continue;
}
(f || x.areInCyclicOrder(o, y, i)) && (f = !1, x.areInCyclicOrder(o, t, y) ? (n = h, i = y) : (r = h, o = y));
}
return [r, n];
}
static midpoint(e, t) {
return [
(e[0] + t[0]) / 2,
(e[1] + t[1]) / 2,
(e[2] + t[2]) / 2
];
}
static criticalPlaneBelow(e) {
return Math.floor(e - 0.5);
}
static criticalPlaneAbove(e) {
return Math.ceil(e - 0.5);
}
/**
* Finds a color with the given Y and hue on the boundary of the
* cube.
*
* @param y The Y value of the color.
* @param targetHue The hue of the color.
* @return The desired color, in linear RGB coordinates.
*/
static bisectToLimit(e, t) {
const r = x.bisectToSegment(e, t);
let n = r[0], o = x.hueOf(n), i = r[1];
for (let c = 0; c < 3; c++)
if (n[c] !== i[c]) {
let f = -1, p = 255;
n[c] < i[c] ? (f = x.criticalPlaneBelow(x.trueDelinearized(n[c])), p = x.criticalPlaneAbove(x.trueDelinearized(i[c]))) : (f = x.criticalPlaneAbove(x.trueDelinearized(n[c])), p = x.criticalPlaneBelow(x.trueDelinearized(i[c])));
for (let h = 0; h < 8 && !(Math.abs(p - f) <= 1); h++) {
const y = Math.floor((f + p) / 2), P = x.CRITICAL_PLANES[y], g = x.setCoordinate(n, P, i, c), m = x.hueOf(g);
x.areInCyclicOrder(o, t, m) ? (i = g, p = y) : (n = g, o = m, f = y);
}
}
return x.midpoint(n, i);
}
static inverseChromaticAdaptation(e) {
const t = Math.abs(e), r = Math.max(0, 27.13 * t / (400 - t));
return X(e) * Math.pow(r, 1 / 0.42);
}
/**
* Finds a color with the given hue, chroma, and Y.
*
* @param hueRadians The desired hue in radians.
* @param chroma The desired chroma.
* @param y The desired Y.
* @return The desired color as a hexadecimal integer, if found; 0
* otherwise.
*/
static findResultByJ(e, t, r) {
let n = Math.sqrt(r) * 11;
const o = Z.DEFAULT, i = 1 / Math.pow(1.64 - Math.pow(0.29, o.n), 0.73), f = 0.25 * (Math.cos(e + 2) + 3.8) * (5e4 / 13) * o.nc * o.ncb, p = Math.sin(e), h = Math.cos(e);
for (let y = 0; y < 5; y++) {
const P = n / 100, g = t === 0 || n === 0 ? 0 : t / Math.sqrt(P), m = Math.pow(g * i, 1 / 0.9), T = o.aw * Math.pow(P, 1 / o.c / o.z) / o.nbb, D = 23 * (T + 0.305) * m / (23 * f + 11 * m * h + 108 * m * p), A = D * h, C = D * p, v = (460 * T + 451 * A + 288 * C) / 1403, M = (460 * T - 891 * A - 261 * C) / 1403, O = (460 * T - 220 * A - 6300 * C) / 1403, k = x.inverseChromaticAdaptation(v), F = x.inverseChromaticAdaptation(M), N = x.inverseChromaticAdaptation(O), L = Ie([k, F, N], x.LINRGB_FROM_SCALED_DISCOUNT);
if (L[0] < 0 || L[1] < 0 || L[2] < 0)
return 0;
const U = x.Y_FROM_LINRGB[0], $ = x.Y_FROM_LINRGB[1], Q = x.Y_FROM_LINRGB[2], z = U * L[0] + $ * L[1] + Q * L[2];
if (z <= 0)
return 0;
if (y === 4 || Math.abs(z - r) < 2e-3)
return L[0] > 100.01 || L[1] > 100.01 || L[2] > 100.01 ? 0 : Ne(L);
n = n - (z - r) * n / (2 * z);
}
return 0;
}
/**
* Finds an sRGB color with the given hue, chroma, and L*, if
* possible.
*
* @param hueDegrees The desired hue, in degrees.
* @param chroma The desired chroma.
* @param lstar The desired L*.
* @return A hexadecimal representing the sRGB color. The color
* has sufficiently close hue, chroma, and L* to the desired
* values, if possible; otherwise, the hue and L* will be
* sufficiently close, and chroma will be maximized.
*/
static solveToInt(e, t, r) {
if (t < 1e-4 || r < 1e-4 || r > 99.9999)
return rt(r);
e = W(e);
const n = e / 180 * Math.PI, o = ae(r), i = x.findResultByJ(n, t, o);
if (i !== 0)
return i;
const c = x.bisectToLimit(o, n);
return Ne(c);
}
/**
* Finds an sRGB color with the given hue, chroma, and L*, if
* possible.
*
* @param hueDegrees The desired hue, in degrees.
* @param chroma The desired chroma.
* @param lstar The desired L*.
* @return An CAM16 object representing the sRGB color. The color
* has sufficiently close hue, chroma, and L* to the desired
* values, if possible; otherwise, the hue and L* will be
* sufficiently close, and chroma will be maximized.
*/
static solveToCam(e, t, r) {
return q.fromInt(x.solveToInt(e, t, r));
}
}
x.SCALED_DISCOUNT_FROM_LINRGB = [
[
0.001200833568784504,
0.002389694492170889,
2795742885861124e-19
],
[
5891086651375999e-19,
0.0029785502573438758,
3270666104008398e-19
],
[
10146692491640572e-20,
5364214359186694e-19,
0.0032979401770712076
]
];
x.LINRGB_FROM_SCALED_DISCOUNT = [
[
1373.2198709594231,
-1100.4251190754821,
-7.278681089101213
],
[
-271.815969077903,
559.6580465940733,
-32.46047482791194
],
[
1.9622899599665666,
-57.173814538844006,
308.7233197812385
]
];
x.Y_FROM_LINRGB = [0.2126, 0.7152, 0.0722];
x.CRITICAL_PLANES = [
0.015176349177441876,
0.045529047532325624,
0.07588174588720938,
0.10623444424209313,
0.13658714259697685,
0.16693984095186062,
0.19729253930674434,
0.2276452376616281,
0.2579979360165119,
0.28835063437139563,
0.3188300904430532,
0.350925934958123,
0.3848314933096426,
0.42057480301049466,
0.458183274052838,
0.4976837250274023,
0.5391024159806381,
0.5824650784040898,
0.6277969426914107,
0.6751227633498623,
0.7244668422128921,
0.775853049866786,
0.829304845476233,
0.8848452951698498,
0.942497089126609,
1.0022825574869039,
1.0642236851973577,
1.1283421258858297,
1.1946592148522128,
1.2631959812511864,
1.3339731595349034,
1.407011200216447,
1.4823302800086415,
1.5599503113873272,
1.6398909516233677,
1.7221716113234105,
1.8068114625156377,
1.8938294463134073,
1.9832442801866852,
2.075074464868551,
2.1693382909216234,
2.2660538449872063,
2.36523901573795,
2.4669114995532007,
2.5710888059345764,
2.6777882626779785,
2.7870270208169257,
2.898822059350997,
3.0131901897720907,
3.1301480604002863,
3.2497121605402226,
3.3718988244681087,
3.4967242352587946,
3.624204428461639,
3.754355295633311,
3.887192587735158,
4.022731918402185,
4.160988767090289,
4.301978482107941,
4.445716283538092,
4.592217266055746,
4.741496401646282,
4.893568542229298,
5.048448422192488,
5.20615066083972,
5.3666897647573375,
5.5300801301023865,
5.696336044816294,
5.865471690767354,
6.037501145825082,
6.212438385869475,
6.390297286737924,
6.571091626112461,
6.7548350853498045,
6.941541251256611,
7.131223617812143,
7.323895587840543,
7.5195704746346665,
7.7182615035334345,
7.919981813454504,
8.124744458384042,
8.332562408825165,
8.543448553206703,
8.757415699253682,
8.974476575321063,
9.194643831691977,
9.417930041841839,
9.644347703669503,
9.873909240696694,
10.106627003236781,
10.342513269534024,
10.58158024687427,
10.8238400726681,
11.069304815507364,
11.317986476196008,
11.569896988756009,
11.825048221409341,
12.083451977536606,
12.345119996613247,
12.610063955123938,
12.878295467455942,
13.149826086772048,
13.42466730586372,
13.702830557985108,
13.984327217668513,
14.269168601521828,
14.55736596900856,
14.848930523210871,
15.143873411576273,
15.44220572664832,
15.743938506781891,
16.04908273684337,
16.35764934889634,
16.66964922287304,
16.985093187232053,
17.30399201960269,
17.62635644741625,
17.95219714852476,
18.281524751807332,
18.614349837764564,
18.95068293910138,
19.290534541298456,
19.633915083172692,
19.98083495742689,
20.331304511189067,
20.685334046541502,
21.042933821039977,
21.404114048223256,
21.76888489811322,
22.137256497705877,
22.50923893145328,
22.884842241736916,
23.264076429332462,
23.6469514538663,
24.033477234264016,
24.42366364919083,
24.817520537484558,
25.21505769858089,
25.61628489293138,
26.021211842414342,
26.429848230738664,
26.842203703840827,
27.258287870275353,
27.678110301598522,
28.10168053274597,
28.529008062403893,
28.96010235337422,
29.39497283293396,
29.83362889318845,
30.276079891419332,
30.722335150426627,
31.172403958865512,
31.62629557157785,
32.08401920991837,
32.54558406207592,
33.010999283389665,
33.4802739966603,
33.953417292456834,
34.430438229418264,
34.911345834551085,
35.39614910352207,
35.88485700094671,
36.37747846067349,
36.87402238606382,
37.37449765026789,
37.87891309649659,
38.38727753828926,
38.89959975977785,
39.41588851594697,
39.93615253289054,
40.460400508064545,
40.98864111053629,
41.520882981230194,
42.05713473317016,
42.597404951718396,
43.141702194811224,
43.6900349931913,
44.24241185063697,
44.798841244188324,
45.35933162437017,
45.92389141541209,
46.49252901546552,
47.065252796817916,
47.64207110610409,
48.22299226451468,
48.808024568002054,
49.3971762874833,
49.9904556690408,
50.587870934119984,
51.189430279724725,
51.79514187861014,
52.40501387947288,
53.0190544071392,
53.637271562750364,
54.259673423945976,
54.88626804504493,
55.517063457223934,
56.15206766869424,
56.79128866487574,
57.43473440856916,
58.08241284012621,
58.734331877617365,
59.39049941699807,
60.05092333227251,
60.715611475655585,
61.38457167773311,
62.057811747619894,
62.7353394731159,
63.417162620860914,
64.10328893648692,
64.79372614476921,
65.48848194977529,
66.18756403501224,
66.89098006357258,
67.59873767827808,
68.31084450182222,
69.02730813691093,
69.74813616640164,
70.47333615344107,
71.20291564160104,
71.93688215501312,
72.67524319850172,
73.41800625771542,
74.16517879925733,
74.9167682708136,
75.67278210128072,
76.43322770089146,
77.1981124613393,
77.96744375590167,
78.74122893956174,
79.51947534912904,
80.30219030335869,
81.08938110306934,
81.88105503125999,
82.67721935322541,
83.4778813166706,
84.28304815182372,
85.09272707154808,
85.90692527145302,
86.72564993000343,
87.54890820862819,
88.3767072518277,
89.2090541872801,
90.04595612594655,
90.88742016217518,
91.73345337380438,
92.58406282226491,
93.43925555268066,
94.29903859396902,
95.16341895893969,
96.03240364439274,
96.9059996312159,
97.78421388448044,
98.6670533535366,
99.55452497210776
];
class E {
static from(e, t, r) {
return new E(x.solveToInt(e, t, r));
}
/**
* @param argb ARGB representation of a color.
* @return HCT representation of a color in default viewing conditions
*/
static fromInt(e) {
return new E(e);
}
toInt() {
return this.argb;
}
/**
* A number, in degrees, representing ex. red, orange, yellow, etc.
* Ranges from 0 <= hue < 360.
*/
get hue() {
return this.internalHue;
}
/**
* @param newHue 0 <= newHue < 360; invalid values are corrected.
* Chroma may decrease because chroma has a different maximum for any given
* hue and tone.
*/
set hue(e) {
this.setInternalState(x.solveToInt(e, this.internalChroma, this.internalTone));
}
get chroma() {
return this.internalChroma;
}
/**
* @param newChroma 0 <= newChroma < ?
* Chroma may decrease because chroma has a different maximum for any given
* hue and tone.
*/
set chroma(e) {
this.setInternalState(x.solveToInt(this.internalHue, e, this.internalTone));
}
/** Lightness. Ranges from 0 to 100. */
get tone() {
return this.internalTone;
}
/**
* @param newTone 0 <= newTone <= 100; invalid valids are corrected.
* Chroma may decrease because chroma has a different maximum for any given
* hue and tone.
*/
set tone(e) {
this.setInternalState(x.solveToInt(this.internalHue, this.internalChroma, e));
}
/** Sets a property of the Hct object. */
setValue(e, t) {
this[e] = t;
}
toString() {
return `HCT(${this.hue.toFixed(0)}, ${this.chroma.toFixed(0)}, ${this.tone.toFixed(0)})`;
}
static isBlue(e) {
return e >= 250 && e < 270;
}
static isYellow(e) {
return e >= 105 && e < 125;
}
static isCyan(e) {
return e >= 170 && e < 207;
}
constructor(e) {
this.argb = e;
const t = q.fromInt(e);
this.internalHue = t.hue, this.internalChroma = t.chroma, this.internalTone = Ve(e), this.argb = e;
}
setInternalState(e) {
const t = q.fromInt(e);
this.internalHue = t.hue, this.internalChroma = t.chroma, this.internalTone = Ve(e), this.argb = e;
}
/**
* Translates a color into different [ViewingConditions].
*
* Colors change appearance. They look different with lights on versus off,
* the same color, as in hex code, on white looks different when on black.
* This is called color relativity, most famously explicated by Josef Albers
* in Interaction of Color.
*
* In color science, color appearance models can account for this and
* calculate the appearance of a color in different settings. HCT is based on
* CAM16, a color appearance model, and uses it to make these calculations.
*
* See [ViewingConditions.make] for parameters affecting color appearance.
*/
inViewingConditions(e) {
const r = q.fromInt(this.toInt()).xyzInViewingConditions(e), n = q.fromXyzInViewingConditions(r[0], r[1], r[2], Z.make());
return E.from(n.hue, n.chroma, ve(r[1]));
}
}
class _ {
/**
* Returns a contrast ratio, which ranges from 1 to 21.
*
* @param toneA Tone between 0 and 100. Values outside will be clamped.
* @param toneB Tone between 0 and 100. Values outside will be clamped.
*/
static ratioOfTones(e, t) {
return e = G(0, 100, e), t = G(0, 100, t), _.ratioOfYs(ae(e), ae(t));
}
static ratioOfYs(e, t) {
const r = e > t ? e : t, n = r === t ? e : t;
return (r + 5) / (n + 5);
}
/**
* Returns a tone >= tone parameter that ensures ratio parameter.
* Return value is between 0 and 100.
* Returns -1 if ratio cannot be achieved with tone parameter.
*
* @param tone Tone return value must contrast with.
* Range is 0 to 100. Invalid values will result in -1 being returned.
* @param ratio Contrast ratio of return value and tone.
* Range is 1 to 21, invalid values have undefined behavior.
*/
static lighter(e, t) {
if (e < 0 || e > 100)
return -1;
const r = ae(e), n = t * (r + 5) - 5, o = _.ratioOfYs(n, r), i = Math.abs(o - t);
if (o < t && i > 0.04)
return -1;
const c = ve(n) + 0.4;
return c < 0 || c > 100 ? -1 : c;
}
/**
* Returns a tone <= tone parameter that ensures ratio parameter.
* Return value is between 0 and 100.
* Returns -1 if ratio cannot be achieved with tone parameter.
*
* @param tone Tone return value must contrast with.
* Range is 0 to 100. Invalid values will result in -1 being returned.
* @param ratio Contrast ratio of return value and tone.
* Range is 1 to 21, invalid values have undefined behavior.
*/
static darker(e, t) {
if (e < 0 || e > 100)
return -1;
const r = ae(e), n = (r + 5) / t - 5, o = _.ratioOfYs(r, n), i = Math.abs(o - t);
if (o < t && i > 0.04)
return -1;
const c = ve(n) - 0.4;
return c < 0 || c > 100 ? -1 : c;
}
/**
* Returns a tone >= tone parameter that ensures ratio parameter.
* Return value is between 0 and 100.
* Returns 100 if ratio cannot be achieved with tone parameter.
*
* This method is unsafe because the returned value is guaranteed to be in
* bounds for tone, i.e. between 0 and 100. However, that value may not reach
* the ratio with tone. For example, there is no color lighter than T100.
*
* @param tone Tone return value must contrast with.
* Range is 0 to 100. Invalid values will result in 100 being returned.
* @param ratio Desired contrast ratio of return value and tone parameter.
* Range is 1 to 21, invalid values have undefined behavior.
*/
static lighterUnsafe(e, t) {
const r = _.lighter(e, t);
return r < 0 ? 100 : r;
}
/**
* Returns a tone >= tone parameter that ensures ratio parameter.
* Return value is between 0 and 100.
* Returns 100 if ratio cannot be achieved with tone parameter.
*
* This method is unsafe because the returned value is guaranteed to be in
* bounds for tone, i.e. between 0 and 100. However, that value may not reach
* the [ratio with [tone]. For example, there is no color darker than T0.
*
* @param tone Tone return value must contrast with.
* Range is 0 to 100. Invalid values will result in 0 being returned.
* @param ratio Desired contrast ratio of return value and tone parameter.
* Range is 1 to 21, invalid values have undefined behavior.
*/
static darkerUnsafe(e, t) {
const r = _.darker(e, t);
return r < 0 ? 0 : r;
}
}
class de {
/**
* Returns true if a color is disliked.
*
* @param hct A color to be judged.
* @return Whether the color is disliked.
*
* Disliked is defined as a dark yellow-green that is not neutral.
*/
static isDisliked(e) {
const t = Math.round(e.hue) >= 90 && Math.round(e.hue) <= 111, r = Math.round(e.chroma) > 16, n = Math.round(e.tone) < 65;
return t && r && n;
}
/**
* If a color is disliked, lighten it to make it likable.
*
* @param hct A color to be judged.
* @return A new color if the original color is disliked, or the original
* color if it is acceptable.
*/
static fixIfDisliked(e) {
return de.isDisliked(e) ? E.from(e.hue, e.chroma, 70) : e;
}
}
function at(a, e, t) {
if (a.name !== t.name)
throw new Error(`Attempting to extend color ${a.name} with color ${t.name} of different name for spec version ${e}.`);
if (a.isBackground !== t.isBackground)
throw new Error(`Attempting to extend color ${a.name} as a ${a.isBackground ? "background" : "foreground"} with color ${t.name} as a ${t.isBackground ? "background" : "foreground"} for spec version ${e}.`);
}
function R(a, e, t) {
return at(a, e, t), l.fromPalette({
name: a.name,
palette: (r) => r.specVersion === e ? t.palette(r) : a.palette(r),
tone: (r) => r.specVersion === e ? t.tone(r) : a.tone(r),
isBackground: a.isBackground,
chromaMultiplier: (r) => {
const n = r.specVersion === e ? t.chromaMultiplier : a.chromaMultiplier;
return n !== void 0 ? n(r) : 1;
},
background: (r) => {
const n = r.specVersion === e ? t.background : a.background;
return n !== void 0 ? n(r) : void 0;
},
secondBackground: (r) => {
const n = r.specVersion === e ? t.secondBackground : a.secondBackground;
return n !== void 0 ? n(r) : void 0;
},
contrastCurve: (r) => {
const n = r.specVersion === e ? t.contrastCurve : a.contrastCurve;
return n !== void 0 ? n(r) : void 0;
},
toneDeltaPair: (r) => {
const n = r.specVersion === e ? t.toneDeltaPair : a.toneDeltaPair;
return n !== void 0 ? n(r) : void 0;
}
});
}
class l {
/**
* Create a DynamicColor defined by a TonalPalette and HCT tone.
*
* @param args Functions with DynamicScheme as input. Must provide a palette
* and tone. May provide a background DynamicColor and ToneDeltaPair.
*/
static fromPalette(e) {
return new l(e.name ?? "", e.palette, e.tone ?? l.getInitialToneFromBackground(e.background), e.isBackground ?? !1, e.chromaMultiplier, e.background, e.secondBackground, e.contrastCurve, e.toneDeltaPair);
}
static getInitialToneFromBackground(e) {
return e === void 0 ? (t) => 50 : (t) => e(t) ? e(t).getTone(t) : 50;
}
/**
* The base constructor for DynamicColor.
*
* _Strongly_ prefer using one of the convenience constructors. This class is
* arguably too flexible to ensure it can support any scenario. Functional
* arguments allow overriding without risks that come with subclasses.
*
* For example, the default behavior of adjust tone at max contrast
* to be at a 7.0 ratio with its background is principled and
* matches accessibility guidance. That does not mean it's the desired
* approach for _every_ design system, and every color pairing,
* always, in every case.
*
* @param name The name of the dynamic color. Defaults to empty.
* @param palette Function that provides a TonalPalette given DynamicScheme. A
* TonalPalette is defined by a hue and chroma, so this replaces the need
* to specify hue/chroma. By providing a tonal palette, when contrast
* adjustments are made, intended chroma can be preserved.
* @param tone Function that provides a tone, given a DynamicScheme.
* @param isBackground Whether this dynamic color is a background, with some
* other color as the foreground. Defaults to false.
* @param chromaMultiplier A factor that multiplies the chroma for this color.
* @param background The background of the dynamic color (as a function of a
* `DynamicScheme`), if it exists.
* @param secondBackground A second background of the dynamic color (as a
* function of a `DynamicScheme`), if it exists.
* @param contrastCurve A `ContrastCurve` object specifying how its contrast
* against its background should behave in various contrast levels
* options.
* @param toneDeltaPair A `ToneDeltaPair` object specifying a tone delta
* constraint between two colors. One of them must be the color being
* constructed.
*/
constructor(e, t, r, n, o, i, c, f, p) {
if (this.name = e, this.palette = t, this.tone = r, this.isBackground = n, this.chromaMultiplier = o, this.background = i, this.secondBackground = c, this.contrastCurve = f, this.toneDeltaPair = p, this.hctCache = /* @__PURE__ */ new Map(), !i && c)
throw new Error(`Color ${e} has secondBackgrounddefined, but background is not defined.`);
if (!i && f)
throw new Error(`Color ${e} has contrastCurvedefined, but background is not defined.`);
if (i && !f)
throw new Error(`Color ${e} has backgrounddefined, but contrastCurve is not defined.`);
}
/**
* Returns a deep copy of this DynamicColor.
*/
clone() {
return l.fromPalette({
name: this.name,
palette: this.palette,
tone: this.tone,
isBackground: this.isBackground,
chromaMultiplier: this.chromaMultiplier,
background: this.background,
secondBackground: this.secondBackground,
contrastCurve: this.contrastCurve,
toneDeltaPair: this.toneDeltaPair
});
}
/**
* Clears the cache of HCT values for this color. For testing or debugging
* purposes.
*/
clearCache() {
this.hctCache.clear();
}
/**
* Returns a ARGB integer (i.e. a hex code).
*
* @param scheme Defines the conditions of the user interface, for example,
* whether or not it is dark mode or light mode, and what the desired
* contrast level is.
*/
getArgb(e) {
return this.getHct(e).toInt();
}
/**
* Returns a color, expressed in the HCT color space, that this
* DynamicColor is under the conditions in scheme.
*
* @param scheme Defines the conditions of the user interface, for example,
* whether or not it is dark mode or light mode, and what the desired
* contrast level is.
*/
getHct(e) {
const t = this.hctCache.get(e);
if (t != null)
return t;
const r = _e(e.specVersion).getHct(e, this);
return this.hctCache.size > 4 && this.hctCache.clear(), this.hctCache.set(e, r), r;
}
/**
* Returns a tone, T in the HCT color space, that this DynamicColor is under
* the conditions in scheme.
*
* @param scheme Defines the conditions of the user interface, for example,
* whether or not it is dark mode or light mode, and what the desired
* contrast level is.
*/
getTone(e) {
return _e(e.specVersion).getTone(e, this);
}
/**
* Given a background tone, finds a foreground tone, while ensuring they reach
* a contrast ratio that is as close to [ratio] as possible.
*
* @param bgTone Tone in HCT. Range is 0 to 100, undefined behavior when it
* falls outside that range.
* @param ratio The contrast ratio desired between bgTone and the return
* value.
*/
static foregroundTone(e, t) {
const r = _.lighterUnsafe(e, t), n = _.darkerUnsafe(e, t), o = _.ratioOfTones(r, e), i = _.ratioOfTones(n, e);
if (l.tonePrefersLightForeground(e)) {
const f = Math.abs(o - i) < 0.1 && o < t && i < t;
return o >= t || o >= i || f ? r : n;
} else
return i >= t || i >= o ? n : r;
}
/**
* Returns whether [tone] prefers a light foreground.
*
* People prefer white foregrounds on ~T60-70. Observed over time, and also
* by Andrew Somers during research for APCA.
*
* T60 used as to create the smallest discontinuity possible when skipping
* down to T49 in order to ensure light foregrounds.
* Since `tertiaryContainer` in dark monochrome scheme requires a tone of
* 60, it should not be adjusted. Therefore, 60 is excluded here.
*/
static tonePrefersLightForeground(e) {
return Math.round(e) < 60;
}
/**
* Returns whether [tone] can reach a contrast ratio of 4.5 with a lighter
* color.
*/
static toneAllowsLightForeground(e) {
return Math.round(e) <= 49;
}
/**
* Adjusts a tone such that white has 4.5 contrast, if the tone is
* reasonably close to supporting it.
*/
static enableLightForeground(e) {
return l.tonePrefersLightForeground(e) && !l.toneAllowsLightForeground(e) ? 49 : e;
}
}
class ot {
getHct(e, t) {
const r = t.getTone(e);
return t.palette(e).getHct(r);
}
getTone(e, t) {
const r = e.contrastLevel < 0, n = t.toneDeltaPair ? t.toneDeltaPair(e) : void 0;
if (n) {
const o = n.roleA, i = n.roleB, c = n.delta, f = n.polarity, p = n.stayTogether, h = f === "nearer" || f === "lighter" && !e.isDark || f === "darker" && e.isDark, y = h ? o : i, P = h ? i : o, g = t.name === y.name, m = e.isDark ? 1 : -1;
let d = y.tone(e), T = P.tone(e);
if (t.background && y.contrastCurve && P.contrastCurve) {
const D = t.background(e), A = y.contrastCurve(e), C = P.contrastCurve(e);
if (D && A && C) {
const v = D.getTone(e), M = A.get(e.contrastLevel), O = C.get(e.contrastLevel);
_.ratioOfTones(v, d) < M && (d = l.foregroundTone(v, M)), _.ratioOfTones(v, T) < O && (T = l.foregroundTone(v, O)), r && (d = l.foregroundTone(v, M), T = l.foregroundTone(v, O));
}
}
return (T - d) * m < c && (T = G(0, 100, d + c * m), (T - d) * m >= c || (d = G(0, 100, T - c * m))), 50 <= d && d < 60 ? m > 0 ? (d = 60, T = Math.max(T, d + c * m)) : (d = 49, T = Math.min(T, d + c * m)) : 50 <= T && T < 60 && (p ? m > 0 ? (d = 60, T = Math.max(T, d + c * m)) : (d = 49, T = Math.min(T, d + c * m)) : m > 0 ? T = 60 : T = 49), g ? d : T;
} else {
let o = t.tone(e);
if (t.background == null || t.background(e) === void 0 || t.contrastCurve == null || t.contrastCurve(e) === void 0)
return o;
const i = t.background(e).getTone(e), c = t.contrastCurve(e).get(e.contrastLevel);
if (_.ratioOfTones(i, o) >= c || (o = l.foregroundTone(i, c)), r && (o = l.foregroundTone(i, c)), t.isBackground && 50 <= o && o < 60 && (_.ratioOfTones(49, i) >= c ? o = 49 : o = 60), t.secondBackground == null || t.secondBackground(e) === void 0)
return o;
const [f, p] = [t.background, t.secondBackground], [h, y] = [f(e).getTone(e), p(e).getTone(e)], [P, g] = [Math.max(h, y), Math.min(h, y)];
if (_.ratioOfTones(P, o) >= c && _.ratioOfTones(g, o) >= c)
return o;
const m = _.lighter(P, c), d = _.darker(g, c), T = [];
return m !== -1 && T.push(m), d !== -1 && T.push(d), l.tonePrefersLightForeground(h) || l.tonePrefersLightForeground(y) ? m < 0 ? 100 : m : T.length === 1 ? T[0] : d < 0 ? 0 : d;
}
}
}
class it {
getHct(e, t) {
const r = t.palette(e), n = t.getTone(e), o = r.hue, i = r.chroma * (t.chromaMultiplier ? t.chromaMultiplier(e) : 1);
return E.from(o, i, n);
}
getTone(e, t) {
const r = t.toneDeltaPair ? t.toneDeltaPair(e) : void 0;
if (r) {
const n = r.roleA, o = r.roleB, i = r.polarity, c = r.constraint, f = i === "darker" || i === "relative_lighter" && e.isDark || i === "relative_darker" && !e.isDark ? -r.delta : r.delta, p = t.name === n.name, h = p ? n : o, y = p ? o : n;
let P = h.tone(e), g = y.getTone(e);
const m = f * (p ? 1 : -1);
if (c === "exact" ? P = G(0, 100, g + m) : c === "nearer" ? m > 0 ? P = G(0, 100, G(g, g + m, P)) : P = G(0, 100, G(g + m, g, P)) : c === "farther" && (m > 0 ? P = G(g + m, 100, P) : P = G(0, g + m, P)), t.background && t.contrastCurve) {
const d = t.background(e), T = t.contrastCurve(e);
if (d && T) {
const D = d.getTone(e), A = T.get(e.contrastLevel);
P = _.ratioOfTones(D, P) >= A && e.contrastLevel >= 0 ? P : l.foregroundTone(D, A);
}
}
return t.isBackground && !t.name.endsWith("_fixed_dim") && (P >= 57 ? P = G(65, 100, P) : P = G(0, 49, P)), P;
} else {
let n = t.tone(e);
if (t.background == null || t.background(e) === void 0 || t.contrastCurve == null || t.contrastCurve(e) === void 0)
return n;
const o = t.background(e).getTone(e), i = t.contrastCurve(e).get(e.contrastLevel);
if (n = _.ratioOfTones(o, n) >= i && e.contrastLevel >= 0 ? n : l.foregroundTone(o, i), t.isBackground && !t.name.endsWith("_fixed_dim") && (n >= 57 ? n = G(65, 100, n) : n = G(0, 49, n)), t.secondBackground == null || t.secondBackground(e) === void 0)
return n;
const [c, f] = [t.background, t.secondBackground], [p, h] = [c(e).getTone(e), f(e).getTone(e)], [y, P] = [Math.max(p, h), Math.min(p, h)];
if (_.ratioOfTones(y, n) >= i && _.ratioOfTones(P, n) >= i)
return n;
const g = _.lighter(y, i), m = _.darker(P, i), d = [];
return g !== -1 && d.push(g), m !== -1 && d.push(m), l.tonePrefersLightForeground(p) || l.tonePrefersLightForeground(h) ? g < 0 ? 100 : g : d.length === 1 ? d[0] : m < 0 ? 0 : m;
}
}
}
const st = new ot(), ct =