UNPKG

use-material-you

Version:

React hook to create dynamic schemes and variants based on M3/material-color-utilities

1,302 lines 120 kB
import * as X from "react"; /** * @license * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ function v(e) { return e < 0 ? -1 : e === 0 ? 0 : 1; } function it(e, t, r) { return (1 - r) * e + r * t; } function Ht(e, t, r) { return r < e ? e : r > t ? t : r; } function gt(e, t, r) { return r < e ? e : r > t ? t : r; } function pt(e) { return e = e % 360, e < 0 && (e = e + 360), e; } function j(e) { return e = e % 360, e < 0 && (e = e + 360), e; } function Vt(e, t) { return 180 - Math.abs(Math.abs(e - t) - 180); } function xt(e, t) { const r = e[0] * t[0][0] + e[1] * t[0][1] + e[2] * t[0][2], n = e[0] * t[1][0] + e[1] * t[1][1] + e[2] * t[1][2], a = e[0] * t[2][0] + e[1] * t[2][1] + e[2] * t[2][2]; return [r, n, a]; } /** * @license * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const Lt = [ [0.41233895, 0.35762064, 0.18051042], [0.2126, 0.7152, 0.0722], [0.01932141, 0.11916382, 0.95034478] ], qt = [ [ 3.2413774792388685, -1.5376652402851851, -0.49885366846268053 ], [ -0.9691452513005321, 1.8758853451067872, 0.04156585616912061 ], [ 0.05562093689691305, -0.20395524564742123, 1.0571799111220335 ] ], Tt = [95.047, 100, 108.883]; function yt(e, t, r) { return (255 << 24 | (e & 255) << 16 | (t & 255) << 8 | r & 255) >>> 0; } function Ft(e) { const t = nt(e[0]), r = nt(e[1]), n = nt(e[2]); return yt(t, r, n); } function Ut(e) { return e >> 24 & 255; } function Pt(e) { return e >> 16 & 255; } function bt(e) { return e >> 8 & 255; } function At(e) { return e & 255; } function St(e, t, r) { const n = qt, a = n[0][0] * e + n[0][1] * t + n[0][2] * r, o = n[1][0] * e + n[1][1] * t + n[1][2] * r, i = n[2][0] * e + n[2][1] * t + n[2][2] * r, c = nt(a), u = nt(o), f = nt(i); return yt(c, u, f); } function Yt(e) { const t = Z(Pt(e)), r = Z(bt(e)), n = Z(At(e)); return xt([t, r, n], Lt); } function Wt(e, t, r) { const n = Tt, a = (e + 16) / 116, o = t / 500 + a, i = a - r / 200, c = dt(o), u = dt(a), f = dt(i), h = c * n[0], g = u * n[1], y = f * n[2]; return St(h, g, y); } function Nt(e) { const t = Z(Pt(e)), r = Z(bt(e)), n = Z(At(e)), a = Lt, o = a[0][0] * t + a[0][1] * r + a[0][2] * n, i = a[1][0] * t + a[1][1] * r + a[1][2] * n, c = a[2][0] * t + a[2][1] * r + a[2][2] * n, u = Tt, f = o / u[0], h = i / u[1], g = c / u[2], y = ct(f), m = ct(h), d = ct(g), l = 116 * m - 16, M = 500 * (y - m), w = 200 * (m - d); return [l, M, w]; } function jt(e) { const t = et(e), r = nt(t); return yt(r, r, r); } function Et(e) { const t = Yt(e)[1]; return 116 * ct(t / 100) - 16; } function et(e) { return 100 * dt((e + 16) / 116); } function kt(e) { return ct(e / 100) * 116 - 16; } function Z(e) { const t = e / 255; return t <= 0.040449936 ? t / 12.92 * 100 : Math.pow((t + 0.055) / 1.055, 2.4) * 100; } function nt(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, Ht(0, 255, Math.round(r * 255)); } function Kt() { return Tt; } function ct(e) { const t = 0.008856451679035631, r = 24389 / 27; return e > t ? Math.pow(e, 1 / 3) : (r * e + 16) / 116; } function dt(e) { const t = 0.008856451679035631, r = 24389 / 27, n = e * e * e; return n > t ? n : (116 * e - 16) / r; } /** * @license * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class K { /** * 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(t = Kt(), r = 200 / Math.PI * et(50) / 100, n = 50, a = 2, o = !1) { const i = t, c = i[0] * 0.401288 + i[1] * 0.650173 + i[2] * -0.051461, u = i[0] * -0.250268 + i[1] * 1.204414 + i[2] * 0.045854, f = i[0] * -2079e-6 + i[1] * 0.048952 + i[2] * 0.953127, h = 0.8 + a / 10, g = h >= 0.9 ? it(0.59, 0.69, (h - 0.9) * 10) : it(0.525, 0.59, (h - 0.8) * 10); let y = o ? 1 : h * (1 - 1 / 3.6 * Math.exp((-r - 42) / 92)); y = y > 1 ? 1 : y < 0 ? 0 : y; const m = h, d = [ y * (100 / c) + 1 - y, y * (100 / u) + 1 - y, y * (100 / f) + 1 - y ], l = 1 / (5 * r + 1), M = l * l * l * l, w = 1 - M, p = M * r + 0.1 * w * w * Math.cbrt(5 * r), b = et(n) / t[1], D = 1.48 + Math.sqrt(b), T = 0.725 / Math.pow(b, 0.2), F = T, A = [ Math.pow(p * d[0] * c / 100, 0.42), Math.pow(p * d[1] * u / 100, 0.42), Math.pow(p * d[2] * f / 100, 0.42) ], x = [ 400 * A[0] / (A[0] + 27.13), 400 * A[1] / (A[1] + 27.13), 400 * A[2] / (A[2] + 27.13) ], R = (2 * x[0] + x[1] + 0.05 * x[2]) * T; return new K(b, R, T, F, g, m, d, p, Math.pow(p, 0.25), D); } /** * 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(t, r, n, a, o, i, c, u, f, h) { this.n = t, this.aw = r, this.nbb = n, this.ncb = a, this.c = o, this.nc = i, this.rgbD = c, this.fl = u, this.fLRoot = f, this.z = h; } } K.DEFAULT = K.make(); /** * @license * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class U { /** * 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(t, r, n, a, o, i, c, u, f) { this.hue = t, this.chroma = r, this.j = n, this.q = a, this.m = o, this.s = i, this.jstar = c, this.astar = u, this.bstar = f; } /** * 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(t) { const r = this.jstar - t.jstar, n = this.astar - t.astar, a = this.bstar - t.bstar, o = Math.sqrt(r * r + n * n + a * a); 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(t) { return U.fromIntInViewingConditions(t, K.DEFAULT); } /** * @param argb ARGB representation of a color. * @param viewingConditions Information about the environment where the color * was observed. * @return CAM16 color. */ static fromIntInViewingConditions(t, r) { const n = (t & 16711680) >> 16, a = (t & 65280) >> 8, o = t & 255, i = Z(n), c = Z(a), u = Z(o), f = 0.41233895 * i + 0.35762064 * c + 0.18051042 * u, h = 0.2126 * i + 0.7152 * c + 0.0722 * u, g = 0.01932141 * i + 0.11916382 * c + 0.95034478 * u, y = 0.401288 * f + 0.650173 * h - 0.051461 * g, m = -0.250268 * f + 1.204414 * h + 0.045854 * g, d = -2079e-6 * f + 0.048952 * h + 0.953127 * g, l = r.rgbD[0] * y, M = r.rgbD[1] * m, w = r.rgbD[2] * d, p = Math.pow(r.fl * Math.abs(l) / 100, 0.42), b = Math.pow(r.fl * Math.abs(M) / 100, 0.42), D = Math.pow(r.fl * Math.abs(w) / 100, 0.42), T = v(l) * 400 * p / (p + 27.13), F = v(M) * 400 * b / (b + 27.13), A = v(w) * 400 * D / (D + 27.13), x = (11 * T + -12 * F + A) / 11, R = (T + F - 2 * A) / 9, B = (20 * T + 20 * F + 21 * A) / 20, N = (40 * T + 20 * F + A) / 20, G = Math.atan2(R, x) * 180 / Math.PI, O = G < 0 ? G + 360 : G >= 360 ? G - 360 : G, rt = O * Math.PI / 180, ut = N * r.nbb, tt = 100 * Math.pow(ut / r.aw, r.c * r.z), lt = 4 / r.c * Math.sqrt(tt / 100) * (r.aw + 4) * r.fLRoot, Mt = O < 20.14 ? O + 360 : O, It = 0.25 * (Math.cos(Mt * Math.PI / 180 + 2) + 3.8), wt = 5e4 / 13 * It * r.nc * r.ncb * Math.sqrt(x * x + R * R) / (B + 0.305), mt = Math.pow(wt, 0.9) * Math.pow(1.64 - Math.pow(0.29, r.n), 0.73), Dt = mt * Math.sqrt(tt / 100), Bt = Dt * r.fLRoot, zt = 50 * Math.sqrt(mt * r.c / (r.aw + 4)), _t = (1 + 100 * 7e-3) * tt / (1 + 7e-3 * tt), Rt = 1 / 0.0228 * Math.log(1 + 0.0228 * Bt), Gt = Rt * Math.cos(rt), vt = Rt * Math.sin(rt); return new U(O, Dt, tt, lt, Bt, zt, _t, Gt, vt); } /** * @param j CAM16 lightness * @param c CAM16 chroma * @param h CAM16 hue */ static fromJch(t, r, n) { return U.fromJchInViewingConditions(t, r, n, K.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(t, r, n, a) { const o = 4 / a.c * Math.sqrt(t / 100) * (a.aw + 4) * a.fLRoot, i = r * a.fLRoot, c = r / Math.sqrt(t / 100), u = 50 * Math.sqrt(c * a.c / (a.aw + 4)), f = n * Math.PI / 180, h = (1 + 100 * 7e-3) * t / (1 + 7e-3 * t), g = 1 / 0.0228 * Math.log(1 + 0.0228 * i), y = g * Math.cos(f), m = g * Math.sin(f); return new U(n, r, t, o, i, u, h, y, m); } /** * @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(t, r, n) { return U.fromUcsInViewingConditions(t, r, n, K.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(t, r, n, a) { const o = r, i = n, c = Math.sqrt(o * o + i * i), f = (Math.exp(c * 0.0228) - 1) / 0.0228 / a.fLRoot; let h = Math.atan2(i, o) * (180 / Math.PI); h < 0 && (h += 360); const g = t / (1 - (t - 100) * 7e-3); return U.fromJchInViewingConditions(g, f, h, a); } /** * @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(K.DEFAULT); } /** * @param viewingConditions Information about the environment where the color * will be viewed. * @return ARGB representation of color */ viewed(t) { const r = this.chroma === 0 || this.j === 0 ? 0 : this.chroma / Math.sqrt(this.j / 100), n = Math.pow(r / Math.pow(1.64 - Math.pow(0.29, t.n), 0.73), 1 / 0.9), a = this.hue * Math.PI / 180, o = 0.25 * (Math.cos(a + 2) + 3.8), i = t.aw * Math.pow(this.j / 100, 1 / t.c / t.z), c = o * (5e4 / 13) * t.nc * t.ncb, u = i / t.nbb, f = Math.sin(a), h = Math.cos(a), g = 23 * (u + 0.305) * n / (23 * c + 11 * n * h + 108 * n * f), y = g * h, m = g * f, d = (460 * u + 451 * y + 288 * m) / 1403, l = (460 * u - 891 * y - 261 * m) / 1403, M = (460 * u - 220 * y - 6300 * m) / 1403, w = Math.max(0, 27.13 * Math.abs(d) / (400 - Math.abs(d))), p = v(d) * (100 / t.fl) * Math.pow(w, 1 / 0.42), b = Math.max(0, 27.13 * Math.abs(l) / (400 - Math.abs(l))), D = v(l) * (100 / t.fl) * Math.pow(b, 1 / 0.42), T = Math.max(0, 27.13 * Math.abs(M) / (400 - Math.abs(M))), F = v(M) * (100 / t.fl) * Math.pow(T, 1 / 0.42), A = p / t.rgbD[0], x = D / t.rgbD[1], R = F / t.rgbD[2], B = 1.86206786 * A - 1.01125463 * x + 0.14918677 * R, N = 0.38752654 * A + 0.62144744 * x - 897398e-8 * R, Y = -0.0158415 * A - 0.03412294 * x + 1.04996444 * R; return St(B, N, Y); } /// Given color expressed in XYZ and viewed in [viewingConditions], convert to /// CAM16. static fromXyzInViewingConditions(t, r, n, a) { const o = 0.401288 * t + 0.650173 * r - 0.051461 * n, i = -0.250268 * t + 1.204414 * r + 0.045854 * n, c = -2079e-6 * t + 0.048952 * r + 0.953127 * n, u = a.rgbD[0] * o, f = a.rgbD[1] * i, h = a.rgbD[2] * c, g = Math.pow(a.fl * Math.abs(u) / 100, 0.42), y = Math.pow(a.fl * Math.abs(f) / 100, 0.42), m = Math.pow(a.fl * Math.abs(h) / 100, 0.42), d = v(u) * 400 * g / (g + 27.13), l = v(f) * 400 * y / (y + 27.13), M = v(h) * 400 * m / (m + 27.13), w = (11 * d + -12 * l + M) / 11, p = (d + l - 2 * M) / 9, b = (20 * d + 20 * l + 21 * M) / 20, D = (40 * d + 20 * l + M) / 20, F = Math.atan2(p, w) * 180 / Math.PI, A = F < 0 ? F + 360 : F >= 360 ? F - 360 : F, x = A * Math.PI / 180, R = D * a.nbb, B = 100 * Math.pow(R / a.aw, a.c * a.z), N = 4 / a.c * Math.sqrt(B / 100) * (a.aw + 4) * a.fLRoot, Y = A < 20.14 ? A + 360 : A, G = 1 / 4 * (Math.cos(Y * Math.PI / 180 + 2) + 3.8), rt = 5e4 / 13 * G * a.nc * a.ncb * Math.sqrt(w * w + p * p) / (b + 0.305), ut = Math.pow(rt, 0.9) * Math.pow(1.64 - Math.pow(0.29, a.n), 0.73), tt = ut * Math.sqrt(B / 100), lt = tt * a.fLRoot, Mt = 50 * Math.sqrt(ut * a.c / (a.aw + 4)), It = (1 + 100 * 7e-3) * B / (1 + 7e-3 * B), Ct = Math.log(1 + 0.0228 * lt) / 0.0228, wt = Ct * Math.cos(x), mt = Ct * Math.sin(x); return new U(A, tt, B, N, lt, Mt, It, wt, mt); } /// XYZ representation of CAM16 seen in [viewingConditions]. xyzInViewingConditions(t) { const r = this.chroma === 0 || this.j === 0 ? 0 : this.chroma / Math.sqrt(this.j / 100), n = Math.pow(r / Math.pow(1.64 - Math.pow(0.29, t.n), 0.73), 1 / 0.9), a = this.hue * Math.PI / 180, o = 0.25 * (Math.cos(a + 2) + 3.8), i = t.aw * Math.pow(this.j / 100, 1 / t.c / t.z), c = o * (5e4 / 13) * t.nc * t.ncb, u = i / t.nbb, f = Math.sin(a), h = Math.cos(a), g = 23 * (u + 0.305) * n / (23 * c + 11 * n * h + 108 * n * f), y = g * h, m = g * f, d = (460 * u + 451 * y + 288 * m) / 1403, l = (460 * u - 891 * y - 261 * m) / 1403, M = (460 * u - 220 * y - 6300 * m) / 1403, w = Math.max(0, 27.13 * Math.abs(d) / (400 - Math.abs(d))), p = v(d) * (100 / t.fl) * Math.pow(w, 1 / 0.42), b = Math.max(0, 27.13 * Math.abs(l) / (400 - Math.abs(l))), D = v(l) * (100 / t.fl) * Math.pow(b, 1 / 0.42), T = Math.max(0, 27.13 * Math.abs(M) / (400 - Math.abs(M))), F = v(M) * (100 / t.fl) * Math.pow(T, 1 / 0.42), A = p / t.rgbD[0], x = D / t.rgbD[1], R = F / t.rgbD[2], B = 1.86206786 * A - 1.01125463 * x + 0.14918677 * R, N = 0.38752654 * A + 0.62144744 * x - 897398e-8 * R, Y = -0.0158415 * A - 0.03412294 * x + 1.04996444 * R; return [B, N, Y]; } } /** * @license * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class C { /** * 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(t) { return (t + 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(t) { const r = t / 100; let n = 0; return r <= 31308e-7 ? n = r * 12.92 : n = 1.055 * Math.pow(r, 1 / 2.4) - 0.055, n * 255; } static chromaticAdaptation(t) { const r = Math.pow(Math.abs(t), 0.42); return v(t) * 400 * r / (r + 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(t) { const r = xt(t, C.SCALED_DISCOUNT_FROM_LINRGB), n = C.chromaticAdaptation(r[0]), a = C.chromaticAdaptation(r[1]), o = C.chromaticAdaptation(r[2]), i = (11 * n + -12 * a + o) / 11, c = (n + a - 2 * o) / 9; return Math.atan2(c, i); } static areInCyclicOrder(t, r, n) { const a = C.sanitizeRadians(r - t), o = C.sanitizeRadians(n - t); return a < 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(t, r, n) { return (r - t) / (n - t); } static lerpPoint(t, r, n) { return [ t[0] + (n[0] - t[0]) * r, t[1] + (n[1] - t[1]) * r, t[2] + (n[2] - t[2]) * r ]; } /** * 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(t, r, n, a) { const o = C.intercept(t[a], r, n[a]); return C.lerpPoint(t, o, n); } static isBounded(t) { return 0 <= t && t <= 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(t, r) { const n = C.Y_FROM_LINRGB[0], a = C.Y_FROM_LINRGB[1], o = C.Y_FROM_LINRGB[2], i = r % 4 <= 1 ? 0 : 100, c = r % 2 === 0 ? 0 : 100; if (r < 4) { const u = i, f = c, h = (t - u * a - f * o) / n; return C.isBounded(h) ? [h, u, f] : [-1, -1, -1]; } else if (r < 8) { const u = i, f = c, h = (t - f * n - u * o) / a; return C.isBounded(h) ? [f, h, u] : [-1, -1, -1]; } else { const u = i, f = c, h = (t - u * n - f * a) / o; return C.isBounded(h) ? [u, f, 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(t, r) { let n = [-1, -1, -1], a = n, o = 0, i = 0, c = !1, u = !0; for (let f = 0; f < 12; f++) { const h = C.nthVertex(t, f); if (h[0] < 0) continue; const g = C.hueOf(h); if (!c) { n = h, a = h, o = g, i = g, c = !0; continue; } (u || C.areInCyclicOrder(o, g, i)) && (u = !1, C.areInCyclicOrder(o, r, g) ? (a = h, i = g) : (n = h, o = g)); } return [n, a]; } static midpoint(t, r) { return [ (t[0] + r[0]) / 2, (t[1] + r[1]) / 2, (t[2] + r[2]) / 2 ]; } static criticalPlaneBelow(t) { return Math.floor(t - 0.5); } static criticalPlaneAbove(t) { return Math.ceil(t - 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(t, r) { const n = C.bisectToSegment(t, r); let a = n[0], o = C.hueOf(a), i = n[1]; for (let c = 0; c < 3; c++) if (a[c] !== i[c]) { let u = -1, f = 255; a[c] < i[c] ? (u = C.criticalPlaneBelow(C.trueDelinearized(a[c])), f = C.criticalPlaneAbove(C.trueDelinearized(i[c]))) : (u = C.criticalPlaneAbove(C.trueDelinearized(a[c])), f = C.criticalPlaneBelow(C.trueDelinearized(i[c]))); for (let h = 0; h < 8 && !(Math.abs(f - u) <= 1); h++) { const g = Math.floor((u + f) / 2), y = C.CRITICAL_PLANES[g], m = C.setCoordinate(a, y, i, c), d = C.hueOf(m); C.areInCyclicOrder(o, r, d) ? (i = m, f = g) : (a = m, o = d, u = g); } } return C.midpoint(a, i); } static inverseChromaticAdaptation(t) { const r = Math.abs(t), n = Math.max(0, 27.13 * r / (400 - r)); return v(t) * Math.pow(n, 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(t, r, n) { let a = Math.sqrt(n) * 11; const o = K.DEFAULT, i = 1 / Math.pow(1.64 - Math.pow(0.29, o.n), 0.73), u = 0.25 * (Math.cos(t + 2) + 3.8) * (5e4 / 13) * o.nc * o.ncb, f = Math.sin(t), h = Math.cos(t); for (let g = 0; g < 5; g++) { const y = a / 100, m = r === 0 || a === 0 ? 0 : r / Math.sqrt(y), d = Math.pow(m * i, 1 / 0.9), M = o.aw * Math.pow(y, 1 / o.c / o.z) / o.nbb, w = 23 * (M + 0.305) * d / (23 * u + 11 * d * h + 108 * d * f), p = w * h, b = w * f, D = (460 * M + 451 * p + 288 * b) / 1403, T = (460 * M - 891 * p - 261 * b) / 1403, F = (460 * M - 220 * p - 6300 * b) / 1403, A = C.inverseChromaticAdaptation(D), x = C.inverseChromaticAdaptation(T), R = C.inverseChromaticAdaptation(F), B = xt([A, x, R], C.LINRGB_FROM_SCALED_DISCOUNT); if (B[0] < 0 || B[1] < 0 || B[2] < 0) return 0; const N = C.Y_FROM_LINRGB[0], Y = C.Y_FROM_LINRGB[1], G = C.Y_FROM_LINRGB[2], O = N * B[0] + Y * B[1] + G * B[2]; if (O <= 0) return 0; if (g === 4 || Math.abs(O - n) < 2e-3) return B[0] > 100.01 || B[1] > 100.01 || B[2] > 100.01 ? 0 : Ft(B); a = a - (O - n) * a / (2 * O); } 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(t, r, n) { if (r < 1e-4 || n < 1e-4 || n > 99.9999) return jt(n); t = j(t); const a = t / 180 * Math.PI, o = et(n), i = C.findResultByJ(a, r, o); if (i !== 0) return i; const c = C.bisectToLimit(o, a); return Ft(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(t, r, n) { return U.fromInt(C.solveToInt(t, r, n)); } } C.SCALED_DISCOUNT_FROM_LINRGB = [ [ 0.001200833568784504, 0.002389694492170889, 2795742885861124e-19 ], [ 5891086651375999e-19, 0.0029785502573438758, 3270666104008398e-19 ], [ 10146692491640572e-20, 5364214359186694e-19, 0.0032979401770712076 ] ]; C.LINRGB_FROM_SCALED_DISCOUNT = [ [ 1373.2198709594231, -1100.4251190754821, -7.278681089101213 ], [ -271.815969077903, 559.6580465940733, -32.46047482791194 ], [ 1.9622899599665666, -57.173814538844006, 308.7233197812385 ] ]; C.Y_FROM_LINRGB = [0.2126, 0.7152, 0.0722]; C.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 ]; /** * @license * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class S { static from(t, r, n) { return new S(C.solveToInt(t, r, n)); } /** * @param argb ARGB representation of a color. * @return HCT representation of a color in default viewing conditions */ static fromInt(t) { return new S(t); } 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(t) { this.setInternalState(C.solveToInt(t, 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(t) { this.setInternalState(C.solveToInt(this.internalHue, t, 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(t) { this.setInternalState(C.solveToInt(this.internalHue, this.internalChroma, t)); } constructor(t) { this.argb = t; const r = U.fromInt(t); this.internalHue = r.hue, this.internalChroma = r.chroma, this.internalTone = Et(t), this.argb = t; } setInternalState(t) { const r = U.fromInt(t); this.internalHue = r.hue, this.internalChroma = r.chroma, this.internalTone = Et(t), this.argb = t; } /** * 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(t) { const n = U.fromInt(this.toInt()).xyzInViewingConditions(t), a = U.fromXyzInViewingConditions(n[0], n[1], n[2], K.make()); return S.from(a.hue, a.chroma, kt(n[1])); } } /** * @license * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class L { /** * 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(t, r) { return t = gt(0, 100, t), r = gt(0, 100, r), L.ratioOfYs(et(t), et(r)); } static ratioOfYs(t, r) { const n = t > r ? t : r, a = n === r ? t : r; return (n + 5) / (a + 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(t, r) { if (t < 0 || t > 100) return -1; const n = et(t), a = r * (n + 5) - 5, o = L.ratioOfYs(a, n), i = Math.abs(o - r); if (o < r && i > 0.04) return -1; const c = kt(a) + 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(t, r) { if (t < 0 || t > 100) return -1; const n = et(t), a = (n + 5) / r - 5, o = L.ratioOfYs(n, a), i = Math.abs(o - r); if (o < r && i > 0.04) return -1; const c = kt(a) - 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(t, r) { const n = L.lighter(t, r); return n < 0 ? 100 : n; } /** * 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(t, r) { const n = L.darker(t, r); return n < 0 ? 0 : n; } } /** * @license * Copyright 2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class ht { /** * 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(t) { const r = Math.round(t.hue) >= 90 && Math.round(t.hue) <= 111, n = Math.round(t.chroma) > 16, a = Math.round(t.tone) < 65; return r && n && a; } /** * 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(t) { return ht.isDisliked(t) ? S.from(t.hue, t.chroma, 70) : t; } } /** * @license * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ class P { /** * 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 ToneDeltaConstraint. */ static fromPalette(t) { return new P(t.name ?? "", t.palette, t.tone, t.isBackground ?? !1, t.background, t.secondBackground, t.contrastCurve, t.toneDeltaPair); } /** * 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 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(t, r, n, a, o, i, c, u) { if (this.name = t, this.palette = r, this.tone = n, this.isBackground = a, this.background = o, this.secondBackground = i, this.contrastCurve = c, this.toneDeltaPair = u, this.hctCache = /* @__PURE__ */ new Map(), !o && i) throw new Error(`Color ${t} has secondBackgrounddefined, but background is not defined.`); if (!o && c) throw new Error(`Color ${t} has contrastCurvedefined, but background is not defined.`); if (o && !c) throw new Error(`Color ${t} has backgrounddefined, but contrastCurve is not defined.`); } /** * Return 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(t) { return this.getHct(t).toInt(); } /** * Return 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(t) { const r = this.hctCache.get(t); if (r != null) return r; const n = this.getTone(t), a = this.palette(t).getHct(n); return this.hctCache.size > 4 && this.hctCache.clear(), this.hctCache.set(t, a), a; } /** * Return 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(t) { const r = t.contrastLevel < 0; if (this.toneDeltaPair) { const n = this.toneDeltaPair(t), a = n.roleA, o = n.roleB, i = n.delta, c = n.polarity, u = n.stayTogether, h = this.background(t).getTone(t), g = c === "nearer" || c === "lighter" && !t.isDark || c === "darker" && t.isDark, y = g ? a : o, m = g ? o : a, d = this.name === y.name, l = t.isDark ? 1 : -1, M = y.contrastCurve.get(t.contrastLevel), w = m.contrastCurve.get(t.contrastLevel), p = y.tone(t); let b = L.ratioOfTones(h, p) >= M ? p : P.foregroundTone(h, M); const D = m.tone(t); let T = L.ratioOfTones(h, D) >= w ? D : P.foregroundTone(h, w); return r && (b = P.foregroundTone(h, M), T = P.foregroundTone(h, w)), (T - b) * l >= i || (T = gt(0, 100, b + i * l), (T - b) * l >= i || (b = gt(0, 100, T - i * l))), 50 <= b && b < 60 ? l > 0 ? (b = 60, T = Math.max(T, b + i * l)) : (b = 49, T = Math.min(T, b + i * l)) : 50 <= T && T < 60 && (u ? l > 0 ? (b = 60, T = Math.max(T, b + i * l)) : (b = 49, T = Math.min(T, b + i * l)) : l > 0 ? T = 60 : T = 49), d ? b : T; } else { let n = this.tone(t); if (this.background == null) return n; const a = this.background(t).getTone(t), o = this.contrastCurve.get(t.contrastLevel); if (L.ratioOfTones(a, n) >= o || (n = P.foregroundTone(a, o)), r && (n = P.foregroundTone(a, o)), this.isBackground && 50 <= n && n < 60 && (L.ratioOfTones(49, a) >= o ? n = 49 : n = 60), this.secondBackground) { const [i, c] = [this.background, this.secondBackground], [u, f] = [i(t).getTone(t), c(t).getTone(t)], [h, g] = [Math.max(u, f), Math.min(u, f)]; if (L.ratioOfTones(h, n) >= o && L.ratioOfTones(g, n) >= o) return n; const y = L.lighter(h, o), m = L.darker(g, o), d = []; return y !== -1 && d.push(y), m !== -1 && d.push(m), P.tonePrefersLightForeground(u) || P.tonePrefersLightForeground(f) ? y < 0 ? 100 : y : d.length === 1 ? d[0] : m < 0 ? 0 : m; } return n; } } /** * Given a background tone, find 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(t, r) { const n = L.lighterUnsafe(t, r), a = L.darkerUnsafe(t, r), o = L.ratioOfTones(n, t), i = L.ratioOfTones(a, t); if (P.tonePrefersLightForeground(t)) { const u = Math.abs(o - i) < 0.1 && o < r && i < r; return o >= r || o >= i || u ? n : a; } else return i >= r || i >= o ? a : n; } /** * 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(t) { return Math.round(t) < 60; } /** * Returns whether [tone] can reach a contrast ratio of 4.5 with a lighter * color. */ static toneAllowsLightForeground(t) { return Math.round(t) <= 49; } /** * Adjust a tone such that white has 4.5 contrast, if the tone is * reasonably close to supporting it. */ static enableLightForeground(t) { return