@wistia/kaleidoscope 0.0.3-beta.744e55dd.c7dc7eb → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # @wistia/kaleidoscope
2
+
3
+ ## 0.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#4288](https://github.com/wistia/vhs/pull/4288) [`c1defa3`](https://github.com/wistia/vhs/commit/c1defa3b9b4fd4627a153f8420018c2b0c5e7e40) Thanks [@bim-kryant](https://github.com/bim-kryant)! - Added utilities to derive background colors from a primary color, and to derive accented versions of a background color.
8
+
9
+ Set up sub-path imports.
10
+
11
+ ## 0.0.2
12
+
13
+ ### Patch Changes
14
+
15
+ - [#4174](https://github.com/wistia/vhs/pull/4174) [`2797755`](https://github.com/wistia/vhs/commit/27977554f82fd390be1f64fa884523364df471d1) Thanks [@bim-kryant](https://github.com/bim-kryant)! - Added adjustColorForProperContrast and getBestColorForText
16
+
17
+ ## 0.0.1
18
+
19
+ ### Patch Changes
20
+
21
+ - [#4150](https://github.com/wistia/vhs/pull/4150) [`1b36fa3`](https://github.com/wistia/vhs/commit/1b36fa36cab47bb82c0e9b16231a74352924ab5e) Thanks [@bim-kryant](https://github.com/bim-kryant)! - Added colorContrastRatiosByShape
@@ -1,6 +1,6 @@
1
1
 
2
2
  /*
3
- * @license @wistia/kaleidoscope v0.0.3-beta.744e55dd.c7dc7eb
3
+ * @license @wistia/kaleidoscope v0.0.3
4
4
  *
5
5
  * Copyright (c) 2026, Wistia, Inc. and its affiliates.
6
6
  *
@@ -1344,4 +1344,4 @@ const getSlightAccentedBackgroundColor = (_backgroundColor, { shouldReturnWhiteF
1344
1344
  //#endregion
1345
1345
  export { getBrandLightBackgroundColor as a, ColorScale as c, Color as d, getBrandedColorScale as i, adjustColorForProperContrast as l, getHeavyAccentedBackgroundColor as n, getBrandDarkBackgroundColor as o, getColorLightnessClassification as r, getBestColorForText as s, getSlightAccentedBackgroundColor as t, colorContrastRatiosByShape as u };
1346
1346
 
1347
- //# sourceMappingURL=color-K4N47FR5.js.map
1347
+ //# sourceMappingURL=color-bUFJKFtM.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"color-K4N47FR5.js","names":["HEX_RADIX","WHITE","BLACK","ACHROMATIC_CHROMA","#towardsLightness","WHITE","BLACK","#classBreaks","#colors","#correctLightness","#domainBreaks","#domainOutputs","#gamma","#max","#min","#mode","#options","#padding","#sampleRange","#stops","#colorAt","#withOptions","#mapDomain","#toPosition","#correctPosition","#interpolateAt","WHITE","ALMOST_BLACK","ALMOST_WHITE","FLARE"],"sources":["../src/private/clamp.ts","../src/private/colorSpace.ts","../src/private/parseColor.ts","../src/Color.ts","../src/colorContrastRatiosByShape.ts","../src/private/preciseContrast.ts","../src/adjustColorForProperContrast.ts","../src/ColorScale.ts","../src/getBestColorForText.ts","../src/getBrandDarkBackgroundColor.ts","../src/getBrandLightBackgroundColor.ts","../src/private/maxChroma.ts","../src/private/perceivedLightness.ts","../src/private/buildBrandedColorScale.ts","../src/getBrandedColorScale.ts","../src/getColorLightnessClassification.ts","../src/private/getAccentedBackgroundByLightness.ts","../src/private/getBackgroundAccentFromPrimaryColor.ts","../src/private/getAccentedBackground.ts","../src/getHeavyAccentedBackgroundColor.ts","../src/getSlightAccentedBackgroundColor.ts"],"sourcesContent":["/** Restrict `value` to the inclusive range between `min` and `max`. */\nexport const clamp = (value: number, min: number, max: number): number =>\n Math.min(Math.max(value, min), max);\n","// oxlint-disable id-length -- single-letter names mirror the color-space formulas\nimport type { Hsl, Lab, RgbTuple } from '../types';\nimport { clamp } from './clamp';\n\nconst D65_WHITE_POINT = { x: 0.95047, y: 1, z: 1.08883 };\n\nconst DEGREES_PER_RADIAN = 180 / Math.PI;\n\n/** Slack allowed on a linear channel before a color counts as out of gamut. */\nconst GAMUT_EPSILON = 1e-6;\n\n/** Enough halvings to place the gamut boundary well inside a single 0–255 step. */\nconst GAMUT_SEARCH_ITERATIONS = 25;\n\n// CIE standard constants: 216/24389 and 24389/27. Their product, 8, is the L* below\n// which the Lab transfer function stays linear.\nconst LAB_EPSILON = 216 / 24389;\nconst LAB_KAPPA = 24389 / 27;\nconst LAB_LINEAR_LIGHTNESS_THRESHOLD = 8;\n\n/** Gamma-decode a 0–255 sRGB channel into linear light. */\nconst linearize = (channel: number): number => {\n const normalized = channel / 255;\n return normalized <= 0.04045 ? normalized / 12.92 : ((normalized + 0.055) / 1.055) ** 2.4;\n};\n\n/**\n * Gamma-encode linear light back into a 0–255 sRGB channel. The sign is carried through\n * the exponent so that out-of-gamut Lab values produce a negative channel rather than NaN.\n * Inverse of linearize.\n */\nconst compand = (linear: number): number => {\n const magnitude = Math.abs(linear);\n const encoded =\n magnitude <= 0.0031308 ? magnitude * 12.92 : 1.055 * magnitude ** (1 / 2.4) - 0.055;\n return encoded * Math.sign(linear) * 255;\n};\n\nconst pivot = (value: number): number =>\n value > LAB_EPSILON ? Math.cbrt(value) : (LAB_KAPPA * value + 16) / 116;\n\nconst hueToChannel = (start: number, end: number, givenHue: number): number => {\n let hue = givenHue;\n if (hue < 0) {\n hue += 1;\n }\n if (hue > 1) {\n hue -= 1;\n }\n if (hue < 1 / 6) {\n return start + (end - start) * 6 * hue;\n }\n if (hue < 1 / 2) {\n return end;\n }\n if (hue < 2 / 3) {\n return start + (end - start) * (2 / 3 - hue) * 6;\n }\n return start;\n};\n\n/**\n * WCAG relative luminance (0–1).\n *\n * @see https://www.w3.org/WAI/GL/wiki/Relative_luminance\n */\nexport const relativeLuminance = (red: number, green: number, blue: number): number =>\n 0.2126 * linearize(red) + 0.7152 * linearize(green) + 0.0722 * linearize(blue);\n\nexport const rgbToHsl = (red: number, green: number, blue: number): Hsl => {\n const r = red / 255;\n const g = green / 255;\n const b = blue / 255;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const lightness = (max + min) / 2;\n const delta = max - min;\n\n if (delta === 0) {\n return { hue: 0, lightness: lightness * 100, saturation: 0 };\n }\n\n const saturation = lightness > 0.5 ? delta / (2 - max - min) : delta / (max + min);\n\n let hue: number;\n if (max === r) {\n hue = (g - b) / delta + (g < b ? 6 : 0);\n } else if (max === g) {\n hue = (b - r) / delta + 2;\n } else {\n hue = (r - g) / delta + 4;\n }\n\n return { hue: (hue / 6) * 360, lightness: lightness * 100, saturation: saturation * 100 };\n};\n\nexport const hslToRgb = ({ hue, lightness, saturation }: Hsl): RgbTuple => {\n const h = hue / 360;\n const s = saturation / 100;\n const l = lightness / 100;\n const end = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const start = 2 * l - end;\n\n return [\n hueToChannel(start, end, h + 1 / 3) * 255,\n hueToChannel(start, end, h) * 255,\n hueToChannel(start, end, h - 1 / 3) * 255,\n ];\n};\n\nexport const rgbToLab = (red: number, green: number, blue: number): Lab => {\n const r = linearize(red);\n const g = linearize(green);\n const b = linearize(blue);\n\n const x = (0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / D65_WHITE_POINT.x;\n const y = (0.2126729 * r + 0.7151522 * g + 0.072175 * b) / D65_WHITE_POINT.y;\n const z = (0.0193339 * r + 0.119192 * g + 0.9503041 * b) / D65_WHITE_POINT.z;\n\n const fx = pivot(x);\n const fy = pivot(y);\n const fz = pivot(z);\n\n return { a: 500 * (fx - fy), b: 200 * (fy - fz), lightness: 116 * fy - 16 };\n};\n\n/**\n * OKLab in polar form: perceptual lightness (0–1), chroma (0 at gray, ~0.4 at the most\n * saturated sRGB colors) and hue in degrees. Unlike CIELAB, a fixed `hue` here reads as\n * one hue at every lightness — CIELAB's hue lines bend, which is why lightening a blue\n * along them walks it towards purple.\n *\n * @see https://bottosson.github.io/posts/oklab/\n */\nexport type Oklch = {\n readonly chroma: number;\n readonly hue: number;\n readonly lightness: number;\n};\n\nexport const rgbToOklch = (red: number, green: number, blue: number): Oklch => {\n const r = linearize(red);\n const g = linearize(green);\n const b = linearize(blue);\n\n const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);\n const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);\n const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);\n\n const aAxis = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;\n const bAxis = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;\n\n return {\n chroma: Math.hypot(aAxis, bAxis),\n hue: (Math.atan2(bAxis, aAxis) * DEGREES_PER_RADIAN + 360) % 360,\n lightness: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n };\n};\n\n/** Linear-light sRGB, which runs 0–1 and goes outside that range when out of gamut. */\nconst oklchToLinearRgb = ({ chroma, hue, lightness }: Oklch): RgbTuple => {\n const radians = hue / DEGREES_PER_RADIAN;\n const aAxis = Math.cos(radians) * chroma;\n const bAxis = Math.sin(radians) * chroma;\n\n const l = (lightness + 0.3963377774 * aAxis + 0.2158037573 * bAxis) ** 3;\n const m = (lightness - 0.1055613458 * aAxis - 0.0638541728 * bAxis) ** 3;\n const s = (lightness - 0.0894841775 * aAxis - 1.291485548 * bAxis) ** 3;\n\n return [\n 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,\n ];\n};\n\nconst fitsGamut = (oklch: Oklch): boolean =>\n oklchToLinearRgb(oklch).every(\n (channel) => channel >= -GAMUT_EPSILON && channel <= 1 + GAMUT_EPSILON,\n );\n\n/**\n * The most chroma this lightness and hue can hold inside sRGB, found by bisection. A hue\n * only gets so colorful before the gamut runs out, and that ceiling drops away sharply as\n * a color approaches white or black.\n */\nconst maximumChroma = (oklch: Oklch): number => {\n let low = 0;\n let high = oklch.chroma;\n\n for (let iteration = 0; iteration < GAMUT_SEARCH_ITERATIONS; iteration += 1) {\n const mid = (low + high) / 2;\n if (fitsGamut({ ...oklch, chroma: mid })) {\n low = mid;\n } else {\n high = mid;\n }\n }\n\n return low;\n};\n\n/**\n * Convert to sRGB, pulling chroma in until the color fits rather than clamping each\n * channel independently. Clamping is what bends the hue of an out-of-gamut color — a\n * lightened red whose red channel pins at 255 while green keeps climbing arrives at\n * yellow. Trading colorfulness for an exact hue and lightness keeps the family intact.\n */\nexport const oklchToRgb = (oklch: Oklch): RgbTuple => {\n const inGamut = fitsGamut(oklch) ? oklch : { ...oklch, chroma: maximumChroma(oklch) };\n const [red, green, blue] = oklchToLinearRgb(inGamut);\n\n return [compand(clamp(red, 0, 1)), compand(clamp(green, 0, 1)), compand(clamp(blue, 0, 1))];\n};\n\nexport const labToRgb = ({ a, b, lightness }: Lab): RgbTuple => {\n const fy = (lightness + 16) / 116;\n const fx = fy + a / 500;\n const fz = fy - b / 200;\n\n const x = (fx ** 3 > LAB_EPSILON ? fx ** 3 : (116 * fx - 16) / LAB_KAPPA) * D65_WHITE_POINT.x;\n const y =\n (lightness > LAB_LINEAR_LIGHTNESS_THRESHOLD ? fy ** 3 : lightness / LAB_KAPPA) *\n D65_WHITE_POINT.y;\n const z = (fz ** 3 > LAB_EPSILON ? fz ** 3 : (116 * fz - 16) / LAB_KAPPA) * D65_WHITE_POINT.z;\n\n return [\n compand(3.2404542 * x - 1.5371385 * y - 0.4985314 * z),\n compand(-0.969266 * x + 1.8760108 * y + 0.041556 * z),\n compand(0.0556434 * x - 0.2040259 * y + 1.0572252 * z),\n ];\n};\n","// oxlint-disable id-length -- r/g/b/a are the canonical names for color channels\nimport type { ColorInput, RgbaTuple } from '../types';\nimport { clamp } from './clamp';\n\nconst HEX_PATTERN = /^#?([\\da-f]{3,4}|[\\da-f]{6}|[\\da-f]{8})$/i;\nconst RGB_FUNCTION_PATTERN = /^rgba?\\(([^)]*)\\)$/i;\nconst NUMBER_PATTERN = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)$/;\nconst PERCENTAGE_PATTERN = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)%$/;\nconst SEPARATOR_PATTERN = /[\\s,]+/;\n\nconst MAX_CHANNEL = 255;\nconst HEX_RADIX = 16;\n\nconst toChannel = (value: number): number => clamp(value, 0, MAX_CHANNEL);\nconst toAlpha = (value: number): number => clamp(value, 0, 1);\n\n/**\n * Read a numeric token, where a percentage is taken as a fraction of `percentageOf`. A\n * channel is `128` or `50%` (of 255); an alpha is `0.5` or `50%` (of 1).\n */\nconst parseNumericToken = (token: string | undefined, percentageOf: number): number | null => {\n if (token === undefined) {\n return null;\n }\n if (PERCENTAGE_PATTERN.test(token)) {\n return (Number(token.slice(0, -1)) / 100) * percentageOf;\n }\n if (NUMBER_PATTERN.test(token)) {\n return Number(token);\n }\n return null;\n};\n\nconst parseChannelToken = (token: string | undefined): number | null => {\n const value = parseNumericToken(token, MAX_CHANNEL);\n return value === null ? null : toChannel(value);\n};\n\nconst parseAlphaToken = (token: string | undefined): number | null => {\n const value = parseNumericToken(token, 1);\n return value === null ? null : toAlpha(value);\n};\n\nconst parseHex = (value: string): RgbaTuple | null => {\n const match = HEX_PATTERN.exec(value);\n const digits = match?.[1];\n if (digits === undefined) {\n return null;\n }\n\n // #rgb and #rgba are shorthand for each digit repeated: #1a2 -> #11aa22\n const expanded = digits.length <= 4 ? digits.replaceAll(/./g, '$&$&') : digits;\n\n return [\n Number.parseInt(expanded.slice(0, 2), HEX_RADIX),\n Number.parseInt(expanded.slice(2, 4), HEX_RADIX),\n Number.parseInt(expanded.slice(4, 6), HEX_RADIX),\n expanded.length === 8 ? Number.parseInt(expanded.slice(6, 8), HEX_RADIX) / MAX_CHANNEL : 1,\n ];\n};\n\nconst parseRgbFunction = (value: string): RgbaTuple | null => {\n const match = RGB_FUNCTION_PATTERN.exec(value);\n const body = match?.[1];\n if (body === undefined) {\n return null;\n }\n\n // Modern syntax puts alpha behind a slash: rgb(41 73 229 / 50%)\n const [channelSource, alphaSource, ...extraSources] = body.split('/');\n if (channelSource === undefined || extraSources.length > 0) {\n return null;\n }\n\n const tokens = channelSource.trim().split(SEPARATOR_PATTERN).filter(Boolean);\n const alphaTokens = (alphaSource ?? '').trim().split(SEPARATOR_PATTERN).filter(Boolean);\n if (alphaTokens.length > 1) {\n return null;\n }\n\n const [redToken, greenToken, blueToken, legacyAlphaToken, ...extraTokens] = tokens;\n if (extraTokens.length > 0) {\n return null;\n }\n if (alphaSource !== undefined && legacyAlphaToken !== undefined) {\n return null;\n }\n\n const red = parseChannelToken(redToken);\n const green = parseChannelToken(greenToken);\n const blue = parseChannelToken(blueToken);\n if (red === null || green === null || blue === null) {\n return null;\n }\n\n const alphaToken = alphaTokens[0] ?? legacyAlphaToken;\n if (alphaToken === undefined) {\n return [red, green, blue, 1];\n }\n\n const alpha = parseAlphaToken(alphaToken);\n return alpha === null ? null : [red, green, blue, alpha];\n};\n\n/**\n * Read any supported color representation into RGBA channels, or `null` when the input\n * is not a color this package understands.\n */\nexport const parseColor = (input: ColorInput): RgbaTuple | null => {\n if (typeof input === 'string') {\n const trimmed = input.trim();\n return parseHex(trimmed) ?? parseRgbFunction(trimmed);\n }\n\n if (Array.isArray(input)) {\n const [red, green, blue, alpha = 1] = input;\n if (![red, green, blue, alpha].every((value) => Number.isFinite(value))) {\n return null;\n }\n return [toChannel(red), toChannel(green), toChannel(blue), toAlpha(alpha)];\n }\n\n const { r, g, b, a = 1 } = input;\n if (![r, g, b, a].every((value) => Number.isFinite(value))) {\n return null;\n }\n return [toChannel(r), toChannel(g), toChannel(b), toAlpha(a)];\n};\n","import type { Oklch } from './private/colorSpace';\nimport type { ColorInput, Hsl, InterpolationMode, Lab, RgbaTuple } from './types';\n// oxlint-disable id-length -- r/g/b/a are the canonical names for color channels\nimport { clamp } from './private/clamp';\nimport {\n hslToRgb,\n labToRgb,\n oklchToRgb,\n relativeLuminance,\n rgbToHsl,\n rgbToLab,\n rgbToOklch,\n} from './private/colorSpace';\nimport { parseColor } from './private/parseColor';\n\nconst HEX_RADIX = 16;\n\n/** The ends of the OKLab lightness axis: white and black. */\nconst MAX_LIGHTNESS = 1;\nconst MIN_LIGHTNESS = 0;\n\nconst DEFAULT_INTERPOLATION_MODE: InterpolationMode = 'oklch';\n\nconst WHITE = '#ffffff';\nconst BLACK = '#000000';\n\n/** Wistia brand blue (`#2949e5`) — what an unreadable input resolves to. */\nconst FALLBACK_CHANNELS: RgbaTuple = [41, 73, 229, 1];\n\nconst toHexPair = (channel: number): string =>\n Math.round(channel).toString(HEX_RADIX).padStart(2, '0');\n\n/**\n * Truncated rather than rounded, so a ratio can never climb across a WCAG threshold on\n * its way to one decimal — 4.4501 reports as 4.4, not as a passing 4.5.\n */\nconst truncateToTenth = (ratio: number): number => Math.floor(ratio * 10) / 10;\n\nconst interpolate = (from: number, to: number, ratio: number): number => from + (to - from) * ratio;\n\n/**\n * Interpolate through linear light rather than gamma-encoded sRGB, which keeps blends\n * between saturated colors from sagging through a muddy midpoint.\n */\nconst interpolateLinear = (from: number, to: number, ratio: number): number =>\n Math.sqrt(from ** 2 * (1 - ratio) + to ** 2 * ratio);\n\n/** Below this much chroma a color reads as gray, and its hue stops meaning anything. */\nconst ACHROMATIC_CHROMA = 1e-4;\n\nconst HALF_TURN = 180;\nconst FULL_TURN = 360;\n\n/**\n * Interpolate hue the short way round the wheel — blue to yellow crosses green or magenta,\n * never both. A gray has no hue of its own to offer, so it borrows the other end's rather\n * than dragging the blend through unrelated hues on the way to white or black.\n */\nconst interpolateHue = (from: Oklch, to: Oklch, ratio: number): number => {\n if (from.chroma < ACHROMATIC_CHROMA) {\n return to.hue;\n }\n if (to.chroma < ACHROMATIC_CHROMA) {\n return from.hue;\n }\n\n const difference = ((to.hue - from.hue + HALF_TURN + FULL_TURN) % FULL_TURN) - HALF_TURN;\n return from.hue + difference * ratio;\n};\n\n/**\n * An immutable sRGB color with transformation methods like lighten, darken, tint, shade.\n * Also includes methods to calculate contrast ratio against another color, relative luminance, etc.\n *\n * @example\n * ```ts\n * new Color('#2949e5').lighten(0.5).toHex(); // '#89aaff'\n * new Color('#2949e5').withAlpha(0.5).toRgba(); // 'rgba(41, 73, 229, 0.5)'\n * new Color('#2949e5').contrast('#ffffff'); // 6.6\n * ```\n */\nexport class Color {\n /**\n * Read `input` into a color, returning `null` when it cannot be parsed.\n */\n static parse(input: ColorInput): Color | null {\n const channels = parseColor(input);\n return channels === null ? null : new Color(channels);\n }\n\n static fromHsl(hsl: Hsl, alpha = 1): Color {\n const [red, green, blue] = hslToRgb(hsl);\n return new Color([red, green, blue, alpha]);\n }\n\n static fromLab(lab: Lab, alpha = 1): Color {\n const [red, green, blue] = labToRgb(lab);\n return new Color([red, green, blue, alpha]);\n }\n\n /** Red channel, 0–255. Kept unrounded so that chained operations don't accumulate error. */\n readonly r: number;\n\n /** Green channel, 0–255. Kept unrounded so that chained operations don't accumulate error. */\n readonly g: number;\n\n /** Blue channel, 0–255. Kept unrounded so that chained operations don't accumulate error. */\n readonly b: number;\n\n /** Alpha channel, 0–1. */\n readonly a: number;\n\n /**\n * @param input - any supported color representation. Input that cannot be read as a\n * color resolves to brand blue rather than failing, so a malformed value degrades to\n * a usable color instead of interrupting a render.\n */\n constructor(input: ColorInput) {\n const [red, green, blue, alpha] = parseColor(input) ?? FALLBACK_CHANNELS;\n this.r = red;\n this.g = green;\n this.b = blue;\n this.a = alpha;\n }\n\n /** `#rrggbb`. Alpha is dropped — use {@link Color.toHexWithAlpha} to keep it. */\n toHex(): string {\n return `#${toHexPair(this.r)}${toHexPair(this.g)}${toHexPair(this.b)}`;\n }\n\n /** `#rrggbbaa`. */\n toHexWithAlpha(): string {\n return `${this.toHex()}${toHexPair(this.a * 255)}`;\n }\n\n /** `rgb(41, 73, 229)`. */\n toRgb(): string {\n return `rgb(${Math.round(this.r)}, ${Math.round(this.g)}, ${Math.round(this.b)})`;\n }\n\n /** `rgba(41, 73, 229, 0.5)`. */\n toRgba(): string {\n return `rgba(${Math.round(this.r)}, ${Math.round(this.g)}, ${Math.round(this.b)}, ${this.a})`;\n }\n\n /** Rounded channels, ready to hand to another color library. */\n toRgbaTuple(): RgbaTuple {\n return [Math.round(this.r), Math.round(this.g), Math.round(this.b), this.a];\n }\n\n toHsl(): Hsl {\n return rgbToHsl(this.r, this.g, this.b);\n }\n\n toLab(): Lab {\n return rgbToLab(this.r, this.g, this.b);\n }\n\n /** Hex when fully opaque, `rgba()` otherwise, so the alpha is never silently lost. */\n toString(): string {\n return this.a === 1 ? this.toHex() : this.toRgba();\n }\n\n /**\n * WCAG relative luminance, from 0 (black) to 1 (white). Alpha is ignored — luminance\n * is only meaningful once a color has been composited onto a background.\n */\n luminance(): number {\n return relativeLuminance(this.r, this.g, this.b);\n }\n\n /**\n * WCAG contrast ratio against `other`, from 1 (identical) to 21 (black on white),\n * reported to one decimal place.\n *\n * @see {@link colorContrastRatiosByShape} for the ratio each kind of content needs\n */\n contrast(other: ColorInput): number {\n const ownLuminance = this.luminance();\n const otherLuminance = new Color(other).luminance();\n const lighter = Math.max(ownLuminance, otherLuminance);\n const darker = Math.min(ownLuminance, otherLuminance);\n return truncateToTenth((lighter + 0.05) / (darker + 0.05));\n }\n\n /**\n * Raise perceptual lightness `ratio` (0–1) of the way to white, holding the hue steady.\n *\n * The hue is held in OKLCh, so a lightened color stays recognizably itself: a blue\n * lightens to a paler blue instead of drifting purple, and a red that runs out of sRGB\n * gives up colorfulness rather than sliding towards orange. That is the difference from\n * {@link Color.tint}, which stirs white into the channels and lets the hue land where it\n * may.\n */\n lighten(ratio: number): Color {\n return this.#towardsLightness(MAX_LIGHTNESS, ratio);\n }\n\n /** Lower perceptual lightness `ratio` (0–1) of the way to black, holding the hue steady. */\n darken(ratio: number): Color {\n return this.#towardsLightness(MIN_LIGHTNESS, ratio);\n }\n\n /** Mix `ratio` (0–1) of white in. */\n tint(ratio: number, mode: InterpolationMode = DEFAULT_INTERPOLATION_MODE): Color {\n return this.blend(WHITE, ratio, mode);\n }\n\n /** Mix `ratio` (0–1) of black in. */\n shade(ratio: number, mode: InterpolationMode = DEFAULT_INTERPOLATION_MODE): Color {\n return this.blend(BLACK, ratio, mode);\n }\n\n /**\n * Mix towards `other`, where `ratio` 0 keeps this color and 1 returns `other`. Alpha is\n * always interpolated linearly, whichever `mode` the channels travel through.\n */\n blend(\n other: ColorInput,\n ratio = 0.5,\n mode: InterpolationMode = DEFAULT_INTERPOLATION_MODE,\n ): Color {\n const target = new Color(other);\n const amount = clamp(ratio, 0, 1);\n const alpha = interpolate(this.a, target.a, amount);\n\n if (mode === 'oklch') {\n const from = rgbToOklch(this.r, this.g, this.b);\n const to = rgbToOklch(target.r, target.g, target.b);\n const [red, green, blue] = oklchToRgb({\n chroma: interpolate(from.chroma, to.chroma, amount),\n hue: interpolateHue(from, to, amount),\n lightness: interpolate(from.lightness, to.lightness, amount),\n });\n\n return new Color([red, green, blue, alpha]);\n }\n\n if (mode === 'lab') {\n const from = this.toLab();\n const to = target.toLab();\n return Color.fromLab(\n {\n a: interpolate(from.a, to.a, amount),\n b: interpolate(from.b, to.b, amount),\n lightness: interpolate(from.lightness, to.lightness, amount),\n },\n alpha,\n );\n }\n\n const blendChannel = mode === 'lrgb' ? interpolateLinear : interpolate;\n return new Color([\n blendChannel(this.r, target.r, amount),\n blendChannel(this.g, target.g, amount),\n blendChannel(this.b, target.b, amount),\n alpha,\n ]);\n }\n\n /** Replace the alpha channel with `alpha` (0–1). */\n withAlpha(alpha: number): Color {\n return new Color([this.r, this.g, this.b, alpha]);\n }\n\n /**\n * Replace HSL lightness with `lightness` (0–100), leaving hue and saturation alone.\n * Use this to hit an absolute lightness; use {@link Color.lighten} to step relative to\n * where the color already is.\n */\n withLightness(lightness: number): Color {\n const { hue, saturation } = this.toHsl();\n return Color.fromHsl({ hue, lightness: clamp(lightness, 0, 100), saturation }, this.a);\n }\n\n /**\n * Travel `ratio` of the way to `target` along the OKLab lightness axis, keeping hue and\n * as much colorfulness as the sRGB gamut has room for at the lightness we arrive at.\n */\n #towardsLightness(target: number, ratio: number): Color {\n const { chroma, hue, lightness } = rgbToOklch(this.r, this.g, this.b);\n const [red, green, blue] = oklchToRgb({\n chroma,\n hue,\n lightness: interpolate(lightness, target, clamp(ratio, 0, 1)),\n });\n\n return new Color([red, green, blue, this.a]);\n }\n}\n","export const colorContrastRatiosByShape = {\n nonText: 3.0, // 3.0:1 - https://www.w3.org/TR/WCAG21/#non-text-contrast\n largeText: 3.0, // 3.0:1 - https://www.w3.org/TR/WCAG21/#contrast-minimum\n paragraphText: 4.5, // 4.5:1 - https://www.w3.org/TR/WCAG21/#contrast-minimum\n smallText: 5.5, // We're making this up, but it should be more than the paragraph text\n} as const;\n\n/** The kind of content a color has to be legible as, which sets the ratio it has to clear. */\nexport type ColorShape = keyof typeof colorContrastRatiosByShape;\n","import type { Color } from '../Color';\n\n/**\n * The WCAG contrast ratio between two colors at full precision, unlike\n * {@link Color.contrast}, which truncates to one decimal.\n *\n * Use this to compare two ratios against each other; use `Color.contrast` to decide\n * whether one clears a required ratio. Truncation is fine for the second and ruinous for\n * the first: near-identical ratios collapse to the same tenth and tie, which sends a\n * direction probe the long way round or ranks two candidates arbitrarily.\n */\nexport const preciseContrast = (color: Color, other: Color): number => {\n const ownLuminance = color.luminance();\n const otherLuminance = other.luminance();\n return (\n (Math.max(ownLuminance, otherLuminance) + 0.05) /\n (Math.min(ownLuminance, otherLuminance) + 0.05)\n );\n};\n","import type { ColorShape } from './colorContrastRatiosByShape';\nimport type { ColorInput } from './types';\nimport { Color } from './Color';\nimport { colorContrastRatiosByShape } from './colorContrastRatiosByShape';\nimport { clamp } from './private/clamp';\nimport { preciseContrast } from './private/preciseContrast';\n\nconst WHITE = '#ffffff';\nconst BLACK = '#000000';\n\n/** One HSL lightness percentage point — the step the search walks the foreground by. */\nconst LIGHTNESS_STEP = 1;\n\n/** How far to probe each way when deciding which direction gains contrast faster. */\nconst PROBE_RATIO = 0.1;\n\n/** HSL lightness bands where a color is close enough to an extreme to have nowhere to go. */\nconst NEARLY_BLACK_LIGHTNESS = 10;\nconst NEARLY_WHITE_LIGHTNESS = 80;\n\n/** Contrast of a color against itself, and the floor of the WCAG ratio. */\nconst MIN_CONTRAST = 1.0;\n\n/** The ends of the luminance range: the search has run out of room once it lands on one. */\nconst MAX_LUMINANCE = 1;\nconst MIN_LUMINANCE = 0;\n\n/**\n * Backstop on the search. Flipping direction at the extremes should always converge well\n * before this, so reaching it means something is wrong, not that the budget was tight.\n */\nconst MAX_ITERATIONS = 1000;\n\nexport type AdjustColorForProperContrastOptions = {\n /** What the foreground sits on. Never adjusted. */\n readonly backgroundColor: ColorInput;\n\n /** The color to nudge until it is legible. Returned untouched if it already is. */\n readonly foregroundColor: ColorInput;\n\n /** What the foreground is. Defaults to `paragraphText` (4.5:1). */\n readonly shape?: ColorShape;\n};\n\n/**\n * Walk `foregroundColor` towards white or black until it clears the contrast ratio\n * `shape` requires against `backgroundColor`.\n *\n * Hue is pinned for the whole walk, so the result still reads as the color you passed in\n * — a washed-out brand blue stays blue rather than drifting towards its neighbors. The\n * direction is whichever gains contrast faster, reversing if it hits an extreme with the\n * ratio still unmet. Text-grade ratios that can't be met either way settle on plain white\n * or black, since at that point nothing else beats them.\n *\n * @example\n * ```ts\n * // Already legible, so nothing moves.\n * adjustColorForProperContrast({\n * foregroundColor: '#2949e5',\n * backgroundColor: '#ffffff',\n * }).toHex(); // '#2949e5'\n *\n * // A brand blue on itself, darkened until it separates.\n * adjustColorForProperContrast({\n * foregroundColor: '#2949e5',\n * backgroundColor: '#2949e5',\n * shape: 'nonText',\n * }).toHex();\n * ```\n */\nexport const adjustColorForProperContrast = ({\n backgroundColor,\n foregroundColor,\n shape = 'paragraphText',\n}: AdjustColorForProperContrastOptions): Color => {\n const background = new Color(backgroundColor);\n const foreground = new Color(foregroundColor);\n const requiredContrast = colorContrastRatiosByShape[shape];\n\n const initialContrast = foreground.contrast(background);\n if (initialContrast >= requiredContrast) {\n return foreground;\n }\n\n const { hue, lightness: initialLightness } = foreground.toHsl();\n\n let shouldBeLighter =\n initialLightness < NEARLY_BLACK_LIGHTNESS ||\n preciseContrast(foreground.tint(PROBE_RATIO, 'rgb'), background) >\n preciseContrast(foreground.shade(PROBE_RATIO, 'rgb'), background);\n\n // A nearly-white foreground gains a sliver of contrast by lightening, but can never gain\n // enough — the only way out is down.\n if (initialLightness > NEARLY_WHITE_LIGHTNESS && initialContrast === MIN_CONTRAST) {\n shouldBeLighter = false;\n }\n\n let adjusted = foreground;\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration += 1) {\n if (adjusted.contrast(background) >= requiredContrast) {\n return adjusted;\n }\n\n const luminance = adjusted.luminance();\n // Out of room at white or black with the ratio still unmet. Nothing beats an extreme\n // at the stricter text ratios, so take it; the looser ones get a second pass back the\n // other way, which may land on a color truer to the original than an extreme would be.\n if (iteration > 0 && (luminance === MAX_LUMINANCE || luminance === MIN_LUMINANCE)) {\n if (requiredContrast > colorContrastRatiosByShape.nonText) {\n const white = new Color(WHITE);\n const black = new Color(BLACK);\n return white.contrast(background) > black.contrast(background) ? white : black;\n }\n\n shouldBeLighter = !shouldBeLighter;\n adjusted = foreground;\n }\n\n const { lightness, saturation } = adjusted.toHsl();\n const stepped = Color.fromHsl(\n {\n hue,\n lightness: clamp(lightness + (shouldBeLighter ? LIGHTNESS_STEP : -LIGHTNESS_STEP), 0, 100),\n saturation,\n },\n adjusted.a,\n );\n\n // Snap to the 8-bit color the caller will actually render. Color keeps channels\n // unrounded, so measuring contrast on them can clear the ratio by a hair that\n // rounding to hex then gives back, handing back a color that doesn't actually pass the required contrast.\n adjusted = new Color(stepped.toRgbaTuple());\n }\n\n // Never converged. Hand back the closest we got rather than interrupting a render.\n return adjusted;\n};\n","import type { ColorInput, InterpolationMode } from './types';\nimport { Color } from './Color';\nimport { clamp } from './private/clamp';\n\ntype Stop = {\n readonly color: Color;\n readonly position: number;\n};\n\nconst DEFAULT_DOMAIN: [number, number] = [0, 1];\nconst DEFAULT_MODE: InterpolationMode = 'lrgb';\nconst DEFAULT_PADDING: [number, number] = [0, 0];\n\n/** Ceiling on the binary search in `correctLightness` */\nconst MAX_LIGHTNESS_ITERATIONS = 20;\nconst LIGHTNESS_TOLERANCE = 0.01;\n\nexport type ColorScaleOptions = {\n /**\n * Quantize the scale into bands instead of leaving it continuous: a count of equally sized\n * classes across the domain, or explicit class breaks.\n */\n readonly classes?: number | number[];\n\n /**\n * Redistribute stops so that perceived lightness moves evenly from end to end. Worth\n * turning on for any scale a reader is meant to rank by eye.\n */\n readonly correctLightness?: boolean;\n\n /**\n * The input range, `[0, 1]` by default. Two values set the ends; supply one value per\n * color to pin each color to a position, or more than two to warp the scale.\n */\n readonly domain?: number[];\n\n /** Bias the scale towards one end. Above 1 favors the start, below 1 the end. */\n readonly gamma?: number;\n\n /** The color space blends travel through. */\n readonly mode?: InterpolationMode;\n\n /** Trim `[start, end]` fractions off the scale, dropping its most extreme colors. */\n readonly padding?: [number, number] | number;\n};\n\nconst toPaddingPair = (padding: ColorScaleOptions['padding']): [number, number] => {\n const pair: [number, number] =\n typeof padding === 'number' ? [padding, padding] : (padding ?? DEFAULT_PADDING);\n return [clamp(pair[0], 0, 1), clamp(pair[1], 0, 1)];\n};\n\nconst toClassBreaks = (\n classes: ColorScaleOptions['classes'],\n min: number,\n max: number,\n): number[] | null => {\n if (classes === undefined) {\n return null;\n }\n if (Array.isArray(classes)) {\n return classes.length === 0 ? null : classes;\n }\n if (classes < 1) {\n return [min, max];\n }\n return Array.from({ length: classes + 1 }, (_, index) => min + (index / classes) * (max - min));\n};\n\n/** The index of the class `value` falls into, or -1 when it sits below the first break. */\nconst toClassIndex = (value: number, breaks: number[]): number => {\n let index = 0;\n while (index < breaks.length - 1 && value >= (breaks[index] ?? Number.POSITIVE_INFINITY)) {\n index += 1;\n }\n return index - 1;\n};\n\n/**\n * A continuous scale between two or more colors — the chroma.js `scale` model, as an\n * immutable class. Every configuration method returns a new scale, so a configured scale\n * is safe to hold onto and share.\n *\n * @example\n * ```ts\n * const scale = new ColorScale(['#2949e5', '#ffffff']);\n * scale.at(0.5).toHex(); // the midpoint color\n * scale.colors(5).map((color) => color.toHex()); // five evenly spaced colors\n * scale.correctLightness().domain([0, 100]).at(72); // perceptually even, read in %\n * ```\n */\nexport class ColorScale {\n readonly #classBreaks: number[] | null;\n readonly #colors: [Color, ...Color[]];\n readonly #correctLightness: boolean;\n readonly #domainBreaks: number[] | null;\n readonly #domainOutputs: number[] | null;\n readonly #gamma: number;\n readonly #max: number;\n readonly #min: number;\n readonly #mode: InterpolationMode;\n readonly #options: ColorScaleOptions;\n readonly #padding: [number, number];\n readonly #sampleRange: [number, number];\n readonly #stops: [Stop, ...Stop[]];\n\n /**\n * @param colors - the colors the scale runs through; a single color makes a flat scale\n * @throws {TypeError} when `colors` is empty or `domain` has fewer than two values\n */\n constructor(colors: readonly ColorInput[], options: ColorScaleOptions = {}) {\n const [firstColor, ...remainingColors] = colors.map((color) => new Color(color));\n if (firstColor === undefined) {\n throw new TypeError('A color scale needs at least one color.');\n }\n\n // A lone color still has to interpolate against something, so it becomes both ends.\n this.#colors =\n remainingColors.length === 0 ? [firstColor, firstColor] : [firstColor, ...remainingColors];\n this.#options = options;\n this.#mode = options.mode ?? DEFAULT_MODE;\n this.#gamma = options.gamma ?? 1;\n this.#padding = toPaddingPair(options.padding);\n this.#correctLightness = options.correctLightness ?? false;\n\n const domain = options.domain ?? DEFAULT_DOMAIN;\n const min = domain[0];\n const max = domain.at(-1);\n if (min === undefined || max === undefined || domain.length < 2) {\n throw new TypeError('A color scale domain needs at least two values.');\n }\n this.#min = min;\n this.#max = max;\n\n const count = this.#colors.length;\n let positions: number[];\n let domainBreaks: number[] | null = null;\n let domainOutputs: number[] | null = null;\n\n if (domain.length === count && min !== max) {\n // One domain value per color pins each color to its own position.\n positions = domain.map((value) => (value - min) / (max - min));\n } else {\n positions = this.#colors.map((_, index) => index / (count - 1));\n\n if (domain.length > 2 && min !== max) {\n const breaks = domain.map((value) => (value - min) / (max - min));\n const outputs = domain.map((_, index) => index / (domain.length - 1));\n // Only warp the scale when the intermediate values aren't already evenly spaced.\n if (!breaks.every((value, index) => outputs[index] === value)) {\n domainBreaks = breaks;\n domainOutputs = outputs;\n }\n }\n }\n\n this.#domainBreaks = domainBreaks;\n this.#domainOutputs = domainOutputs;\n\n const [firstStopColor, ...remainingStopColors] = this.#colors;\n this.#stops = [\n { color: firstStopColor, position: positions[0] ?? 0 },\n ...remainingStopColors.map((color, index) => ({\n color,\n position: positions[index + 1] ?? 1,\n })),\n ];\n\n this.#classBreaks = toClassBreaks(options.classes, min, max);\n const firstBreak = this.#classBreaks?.[0];\n const lastBreak = this.#classBreaks?.at(-1);\n this.#sampleRange =\n firstBreak === undefined || lastBreak === undefined ? [min, max] : [firstBreak, lastBreak];\n }\n\n /** The color at `value`, read through the scale's domain, classes, gamma and padding. */\n at(value: number): Color {\n if (!Number.isFinite(value)) {\n throw new TypeError(`A color scale cannot be sampled at ${String(value)}.`);\n }\n return this.#colorAt(value, false);\n }\n\n /** `count` colors spread evenly across the domain. */\n colors(count: number): Color[] {\n if (!Number.isInteger(count) || count < 0) {\n throw new TypeError(`A color scale cannot produce ${String(count)} colors.`);\n }\n if (count === 0) {\n return [];\n }\n\n const [start, end] = this.#sampleRange;\n if (count === 1) {\n return [this.at(start + (end - start) / 2)];\n }\n\n const span = end - start;\n return Array.from({ length: count }, (_, index) =>\n this.at(start + (index / (count - 1)) * span),\n );\n }\n\n mode(mode: InterpolationMode): ColorScale {\n return this.#withOptions({ mode });\n }\n\n domain(domain: number[]): ColorScale {\n return this.#withOptions({ domain });\n }\n\n gamma(gamma: number): ColorScale {\n return this.#withOptions({ gamma });\n }\n\n padding(padding: [number, number] | number): ColorScale {\n return this.#withOptions({ padding });\n }\n\n correctLightness(correctLightness = true): ColorScale {\n return this.#withOptions({ correctLightness });\n }\n\n classes(classes: number | number[]): ColorScale {\n return this.#withOptions({ classes });\n }\n\n #withOptions(overrides: ColorScaleOptions): ColorScale {\n return new ColorScale(this.#colors, { ...this.#options, ...overrides });\n }\n\n #colorAt(value: number, bypassValueMapping: boolean): Color {\n let position = clamp(\n this.#mapDomain(bypassValueMapping ? value : this.#toPosition(value)),\n 0,\n 1,\n );\n\n if (!bypassValueMapping && this.#correctLightness) {\n position = this.#correctPosition(position);\n }\n\n if (this.#gamma !== 1) {\n position **= this.#gamma;\n }\n\n const [paddingStart, paddingEnd] = this.#padding;\n position = paddingStart + position * (1 - paddingStart - paddingEnd);\n\n return this.#interpolateAt(clamp(position, 0, 1));\n }\n\n /** Map a domain value onto the scale's unpadded 0–1 range. */\n #toPosition(value: number): number {\n const breaks = this.#classBreaks;\n if (breaks !== null && breaks.length > 2) {\n return toClassIndex(value, breaks) / (breaks.length - 2);\n }\n if (this.#max === this.#min) {\n return 1;\n }\n return (value - this.#min) / (this.#max - this.#min);\n }\n\n /** Warp the scale so that intermediate domain values land where the caller placed them. */\n #mapDomain(position: number): number {\n const breaks = this.#domainBreaks;\n const outputs = this.#domainOutputs;\n if (breaks === null || outputs === null || position <= 0 || position >= 1) {\n return position;\n }\n\n let index = 0;\n while (index < breaks.length - 2 && position >= (breaks[index + 1] ?? 1)) {\n index += 1;\n }\n\n const start = breaks[index] ?? 0;\n const end = breaks[index + 1] ?? 1;\n const outputStart = outputs[index] ?? 0;\n const outputEnd = outputs[index + 1] ?? 1;\n if (end === start) {\n return outputStart;\n }\n return outputStart + ((position - start) / (end - start)) * (outputEnd - outputStart);\n }\n\n /**\n * Nudge `position` until the color there carries the Lab lightness an evenly lit scale\n * would have, by bisecting between the ends.\n */\n #correctPosition(position: number): number {\n const startLightness = this.#colorAt(0, true).toLab().lightness;\n const endLightness = this.#colorAt(1, true).toLab().lightness;\n const isDescending = startLightness > endLightness;\n const idealLightness = startLightness + (endLightness - startLightness) * position;\n\n let low = 0;\n let high = 1;\n let corrected = position;\n let difference = this.#colorAt(corrected, true).toLab().lightness - idealLightness;\n\n for (\n let iteration = 0;\n iteration < MAX_LIGHTNESS_ITERATIONS && Math.abs(difference) > LIGHTNESS_TOLERANCE;\n iteration += 1\n ) {\n // Already lighter than ideal: search the darker half, and vice versa.\n if (isDescending === difference < 0) {\n high = corrected;\n corrected += (low - corrected) / 2;\n } else {\n low = corrected;\n corrected += (high - corrected) / 2;\n }\n difference = this.#colorAt(corrected, true).toLab().lightness - idealLightness;\n }\n\n return corrected;\n }\n\n #interpolateAt(position: number): Color {\n const stops = this.#stops;\n\n for (const [index, stop] of stops.entries()) {\n if (position <= stop.position) {\n return stop.color;\n }\n\n const next = stops[index + 1];\n if (next === undefined) {\n return stop.color;\n }\n\n if (position < next.position) {\n const ratio = (position - stop.position) / (next.position - stop.position);\n return stop.color.blend(next.color, ratio, this.#mode);\n }\n }\n\n return stops[0].color;\n }\n}\n","import type { ColorShape } from './colorContrastRatiosByShape';\nimport type { ColorInput } from './types';\nimport { Color } from './Color';\nimport { colorContrastRatiosByShape } from './colorContrastRatiosByShape';\nimport { preciseContrast } from './private/preciseContrast';\n\nconst WHITE = '#ffffff';\nconst BLACK = '#000000';\n\nexport type BestColorForTextOptions = {\n /** Always excluded from the result.*/\n readonly backgroundColor: ColorInput;\n\n /**\n * Colors that are part of the palette but should not be considered as candidates.\n * Useful in scenarios like the webinar pages color derivation logic, where we might include derived colors\n * in the palette used by some fields, like `lowEmphasisTextColor`, but we want to exclude the derived colors\n * from other fields, like `mainTextColor`.\n */\n readonly exclude?: readonly ColorInput[];\n\n /**\n * The colors to choose from. Black and white are included automatically, so an empty/absent palette\n * still yields whichever of the two has best contrast against `backgroundColor`.\n */\n readonly palette?: readonly ColorInput[];\n\n /** The type of text/shape that will use the resulting color. Defaults to `paragraphText` (4.5:1). */\n readonly shape?: ColorShape;\n};\n\n/**\n * Picks a color most suitable for a given text (or non-text) shape against the given background color.\n * Accepts an optional color palette, but white and black are always included as options in addition to the palette.\n * Also accepts a set of colors from the palette that should be excluded from consideration.\n *\n * @example\n * ```ts\n * getBestColorForText({ backgroundColor: '#2949e5' }).toHex(); // '#ffffff'\n * ```\n */\nexport const getBestColorForText = ({\n backgroundColor,\n exclude = [],\n palette = [],\n shape = 'paragraphText',\n}: BestColorForTextOptions): Color => {\n const background = new Color(backgroundColor);\n const requiredContrast = colorContrastRatiosByShape[shape];\n\n const excluded = new Set(\n // Always exclude the background color in addition to the colorsToExclude\n [...exclude, background]\n .map((color) => new Color(color).toHex())\n // If one of the excluded colors is black or white, don't exclude it.\n // We always need black and white as potential text color options.\n .filter((hex) => hex !== WHITE && hex !== BLACK),\n );\n\n const candidates = [\n ...new Map(\n [WHITE, BLACK, ...palette].map((color) => {\n const candidate = new Color(color);\n return [candidate.toHex(), candidate];\n }),\n ).values(),\n ].filter((color) => !excluded.has(color.toHex()));\n\n const white = new Color(WHITE);\n const black = new Color(BLACK);\n\n // Rank candidates in order of least contrast first, otherwise we would always return either black or white.\n const ranked = candidates\n .map((color) => ({ color, ratio: preciseContrast(color, background) }))\n .toSorted((one, two) => one.ratio - two.ratio);\n\n // Which side of the background text belongs on: light text on a dark background, dark\n // text on a light one. Settled by measuring both extremes rather than by a lightness\n // threshold, so the crossover falls where contrast actually flips, near luminance 0.18.\n //\n // Worth preferring because the WCAG ratio is symmetric and cannot say that dark-on-dark\n // and light-on-dark read differently at the same number. Without this, a background\n // around luminance 0.12 takes black at 3.3:1 — enough to clear largeText, and murky to\n // read — over a light candidate that costs nothing.\n\n // Optically, should the text be lighter or darker than the background?\n const prefersLighterText =\n preciseContrast(white, background) > preciseContrast(black, background);\n const backgroundLuminance = background.luminance();\n const isPreferredSide = (color: Color): boolean =>\n prefersLighterText\n ? color.luminance() >= backgroundLuminance\n : color.luminance() <= backgroundLuminance;\n\n const passing = ranked.filter(({ color }) => color.contrast(background) >= requiredContrast);\n\n // The least-contrasting passing candidate on the preferred side. There is always one\n // when anything passes at all: the preferred side is the one whose extreme contrasts\n // more, and both extremes are always in the pool. So falling through means nothing\n // cleared the ratio, and the most contrast on offer is that same extreme.\n return (\n passing.find(({ color }) => isPreferredSide(color))?.color ??\n (prefersLighterText ? white : black)\n );\n};\n","import type { ColorInput } from './types';\nimport { Color } from './Color';\n\nconst MAX_PAGE_SATURATION = 50;\n\nconst ALMOST_BLACK = 5;\nconst ALMOST_WHITE = 95;\nconst DESIRED_BACKGROUND_LIGHTNESS = 18;\nconst MINIMUM_CONTRAST_BETWEEN_PRIMARY_AND_BACKGROUND = 1.5;\nconst SEARCH_INCREMENT = 0.5;\n\nconst constructColorWithNewSaturationAndLightness = (\n primaryColor: Color,\n saturation: number,\n lightness: number,\n): Color => Color.fromHsl({ hue: primaryColor.toHsl().hue, lightness, saturation }, primaryColor.a);\n\n/**\n * Generates a dark background color from a given primary color, preserving the hue of the primary color.\n *\n * @example\n * ```ts\n * getBrandDarkBackgroundColor('#2949e5').toHex(); // '#242942'\n * ```\n *\n * @see {@link getBrandLightBackgroundColor} for the light counterpart\n */\nexport const getBrandDarkBackgroundColor = (_primaryColor: ColorInput): Color => {\n const primaryColor = new Color(_primaryColor);\n const { lightness: brandLightness, saturation } = primaryColor.toHsl();\n\n // If the color is close to black or white, zero out the saturation so\n // we end up with gray instead of red\n const hasNoUsableHue = brandLightness < ALMOST_BLACK || brandLightness > ALMOST_WHITE;\n const pageSaturation = hasNoUsableHue ? 0 : Math.min(MAX_PAGE_SATURATION, saturation);\n\n const initialBackgroundColorOption = constructColorWithNewSaturationAndLightness(\n primaryColor,\n pageSaturation,\n DESIRED_BACKGROUND_LIGHTNESS,\n );\n\n // If the initial background color option meets our desired contrast, just use it.\n if (\n initialBackgroundColorOption.contrast(primaryColor) >=\n MINIMUM_CONTRAST_BETWEEN_PRIMARY_AND_BACKGROUND\n ) {\n return initialBackgroundColorOption;\n }\n\n // Otherwise if the initial background color option did not have the desired contrast,\n // tweak the lightness until we get a color that does meet the desired contrast.\n // Return black if we run out of options.\n let backgroundColorWithIncreasedContrast = initialBackgroundColorOption;\n for (\n let pageLightness = DESIRED_BACKGROUND_LIGHTNESS;\n pageLightness >= 0;\n pageLightness -= SEARCH_INCREMENT\n ) {\n const candidate = constructColorWithNewSaturationAndLightness(\n primaryColor,\n pageSaturation,\n pageLightness,\n );\n if (\n candidate.contrast(primaryColor) > backgroundColorWithIncreasedContrast.contrast(primaryColor)\n ) {\n backgroundColorWithIncreasedContrast = candidate;\n }\n if (\n backgroundColorWithIncreasedContrast.contrast(primaryColor) >=\n MINIMUM_CONTRAST_BETWEEN_PRIMARY_AND_BACKGROUND\n ) {\n break;\n }\n }\n\n return backgroundColorWithIncreasedContrast;\n};\n","import type { ColorInput } from './types';\nimport { Color } from './Color';\n\n/** Enough saturation for the brand hue to register, for a primary that has barely any. */\nconst MIN_SATURATION = 5;\n\n/** HSL lightness bands where a primary is close enough to an extreme to have no usable hue. */\nconst ALMOST_BLACK = 5;\nconst ALMOST_WHITE = 95;\n\n/**\n *\n * Generates a light background color from a given primary color, preserving the hue of the primary color.\n *\n * @example\n * ```ts\n * getBrandLightBackgroundColor('#2949e5').toHex(); // '#ebeefd'\n * ```\n *\n * @see {@link getBrandDarkBackgroundColor} for the dark counterpart\n */\nexport const getBrandLightBackgroundColor = (_primaryColor: ColorInput): Color => {\n const primaryColor = new Color(_primaryColor);\n const { lightness, saturation } = primaryColor.toHsl();\n\n // If the new color is close to black or white, zero out the saturation so\n // we end up with gray instead of pink\n const hasNoHue = saturation === 0 || lightness < ALMOST_BLACK || lightness > ALMOST_WHITE;\n const targetSaturation = hasNoHue ? 0 : Math.max(MIN_SATURATION, saturation);\n\n // Make the current color *almost* white and then darken it just a bit\n // to get a nice looking light background color based on the primary color\n const derived = primaryColor.tint(0.95, 'rgb').shade(0.02, 'rgb');\n\n return Color.fromHsl({ ...derived.toHsl(), saturation: targetSaturation }, derived.a);\n};\n","import { oklchToRgb, rgbToOklch } from './colorSpace';\n\n/**\n * Below this a color has no perceptible hue.\n */\nexport const ACHROMATIC_CHROMA = 1e-4;\n\n/**\n * More chroma than sRGB holds anywhere. The widest point is magenta at 0.32\n */\nconst UNREACHABLE_CHROMA = 0.5;\n\n/**\n * The most chroma sRGB can hold at the given lightness and hue.\n *\n * Read from {@link oklchToRgb}, which already clamps by max chroma so that we don't have to\n * re-implement searching for max possible chroma.\n */\nexport const maxChroma = (lightness: number, hue: number): number => {\n const [red, green, blue] = oklchToRgb({ chroma: UNREACHABLE_CHROMA, hue, lightness });\n\n return rgbToOklch(red, green, blue).chroma;\n};\n","import type { Color } from '../Color';\n\n/**\n * Flare is the ambient light reflecting off a screen, as defined by WCAG guidelines.\n * See https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum\n */\nconst FLARE = 0.05;\nconst FLOOR = Math.cbrt(FLARE);\nconst SPAN = Math.cbrt(1 + FLARE) - FLOOR;\n\n/**\n * Get the perceived lightness of a color, with ambient lighting factored in according\n * to WCAG guidelines.\n */\nexport const perceivedLightness = (color: Color): number =>\n (Math.cbrt(color.luminance() + FLARE) - FLOOR) / SPAN;\n","import { Color } from '../Color';\nimport { ColorScale } from '../ColorScale';\nimport { getBrandDarkBackgroundColor } from '../getBrandDarkBackgroundColor';\nimport { getBrandLightBackgroundColor } from '../getBrandLightBackgroundColor';\nimport { clamp } from './clamp';\nimport { oklchToRgb, rgbToOklch } from './colorSpace';\nimport { ACHROMATIC_CHROMA, maxChroma } from './maxChroma';\nimport { perceivedLightness } from './perceivedLightness';\n\nexport const DEFAULT_COLOR_SCALE_STEPS = 12;\n\n/**\n * Using the primary color, derive the light/dark variants of the background color,\n * and use these three colors as all the fixed stops on the scale.\n * Including the primary color in addition to the two background extremes allows the scale\n * to maintain the vibrancy of the primary color.\n * Sort stops by luminance, just in case.\n */\nconst brandScaleStops = (primary: Color): Color[] => {\n const stops = [\n getBrandLightBackgroundColor(primary),\n primary,\n getBrandDarkBackgroundColor(primary),\n ];\n\n return stops.toSorted((one, two) => two.luminance() - one.luminance());\n};\n\nconst ARC_SAMPLES = 128;\n\nconst DEGREES_TO_RADIANS = Math.PI / 180;\n\n/**\n * How far apart two colors look: perceived lightness versus OKLab's chroma.\n *\n * We use perceptual distance rather than a lightness calculation because the color scale\n * can cover a lot of ground without changing lightness significantly. Between an almost white color\n * and a light yellow there is not much lightness difference, but there is actually enough\n * \"distance\" between the colors to perceive more than one step between them.\n *\n * Contrast ratio does not matter significantly here because these are background colors.\n */\nconst perceptualDistance = (one: Color, two: Color): number => {\n const from = rgbToOklch(one.r, one.g, one.b);\n const to = rgbToOklch(two.r, two.g, two.b);\n\n return Math.hypot(\n perceivedLightness(one) - perceivedLightness(two),\n from.chroma * Math.cos(from.hue * DEGREES_TO_RADIANS) -\n to.chroma * Math.cos(to.hue * DEGREES_TO_RADIANS),\n from.chroma * Math.sin(from.hue * DEGREES_TO_RADIANS) -\n to.chroma * Math.sin(to.hue * DEGREES_TO_RADIANS),\n );\n};\n\n/**\n * Maps between a position on the scale and how far along its length that position sits.\n */\nconst arcLength = (colorAt: (position: number) => Color) => {\n const points = Array.from({ length: ARC_SAMPLES + 1 }, (_, index) =>\n colorAt(index / ARC_SAMPLES),\n );\n const travelled = [0];\n for (let index = 1; index <= ARC_SAMPLES; index += 1) {\n const from = points[index - 1];\n const to = points[index];\n const step = from === undefined || to === undefined ? 0 : perceptualDistance(from, to);\n\n travelled.push((travelled[index - 1] ?? 0) + step);\n }\n const total = travelled.at(-1) ?? 0;\n\n return {\n distanceOf: (position: number): number => {\n if (total === 0) {\n return position;\n }\n const scaled = clamp(position, 0, 1) * ARC_SAMPLES;\n const lower = Math.min(Math.floor(scaled), ARC_SAMPLES - 1);\n const within = scaled - lower;\n const from = travelled[lower] ?? 0;\n const to = travelled[lower + 1] ?? total;\n\n return (from + (to - from) * within) / total;\n },\n positionAt: (distance: number): number => {\n if (total === 0) {\n return distance;\n }\n const target = clamp(distance, 0, 1) * total;\n for (let index = 1; index <= ARC_SAMPLES; index += 1) {\n const to = travelled[index] ?? total;\n if (to >= target) {\n const from = travelled[index - 1] ?? 0;\n const span = to - from;\n\n return (index - 1 + (span === 0 ? 0 : (target - from) / span)) / ARC_SAMPLES;\n }\n }\n\n return 1;\n },\n };\n};\n\nexport type BrandScaleOptions = {\n /** How many steps the scale is divided into. */\n readonly steps?: number;\n};\n\n// Where `color` falls on the color scale, as a position from 0–1.\nexport const positionOnScale = (scale: ColorScale, color: Color): number => {\n const target = color.luminance();\n let low = 0;\n let high = 1;\n\n for (let iteration = 0; iteration < 30; iteration += 1) {\n const middle = (low + high) / 2;\n if (scale.at(middle).luminance() > target) {\n low = middle;\n } else {\n high = middle;\n }\n }\n\n return (low + high) / 2;\n};\n\n/**\n * How colorful a color is as a share of the most sRGB allows at its lightness and hue.\n * 0 for a gray, 1 for a color that maxes out lightness/saturation.\n */\nconst gamutFraction = (color: Color): number => {\n const { chroma, hue, lightness } = rgbToOklch(color.r, color.g, color.b);\n const available = maxChroma(lightness, hue);\n\n return chroma < ACHROMATIC_CHROMA || available < ACHROMATIC_CHROMA\n ? 0\n : Math.min(1, chroma / available);\n};\n\ntype Anchor = {\n readonly fraction: number;\n readonly position: number;\n};\n\n/**\n * What fraction of the color gamut is represented by a given position\n */\nconst fractionAt = (anchors: readonly Anchor[], position: number): number => {\n const first = anchors.at(0);\n const last = anchors.at(-1);\n if (first === undefined || last === undefined) {\n return 0;\n }\n if (position <= first.position) {\n return first.fraction;\n }\n\n for (let index = 1; index < anchors.length; index += 1) {\n const previous = anchors[index - 1];\n const next = anchors[index];\n if (previous === undefined || next === undefined) {\n break;\n }\n if (position <= next.position) {\n const span = next.position - previous.position;\n const ratio = span === 0 ? 0 : (position - previous.position) / span;\n\n return previous.fraction + (next.fraction - previous.fraction) * ratio;\n }\n }\n\n return last.fraction;\n};\n\nexport type BrandedColorScale = {\n /** The color at a given position (0 - 1), from the scale. */\n readonly at: (position: number) => Color;\n /** The color at step `index` */\n readonly atStep: (index: number) => Color;\n readonly positionOf: (color: Color) => number;\n /** The step where the primary color falls. */\n readonly primaryStep: number;\n /** Where a given color falls, as a step index — fractional when it sits between two. */\n readonly stepOf: (color: Color) => number;\n readonly steps: number;\n};\n\n/**\n * Builds a color scale using the derived light/dark background colors based on the given primary color,\n * with the primary color slotted into the scale wherever it fits based on lightness.\n *\n * It's important to include the primary color in the scale because the light/dark derived background colors\n * do not have the same saturation as the primary color, and we want the scale to reflect the vibrancy\n * of the primary color.\n */\nexport const buildBrandedColorScale = (\n primary: Color,\n options: BrandScaleOptions = {},\n): BrandedColorScale => {\n const { steps = DEFAULT_COLOR_SCALE_STEPS } = options;\n const scale = new ColorScale(brandScaleStops(primary), { mode: 'oklch' });\n const stops = brandScaleStops(primary);\n const anchors = stops\n .map((stop) => ({ fraction: gamutFraction(stop), position: positionOnScale(scale, stop) }))\n .toSorted((one, two) => one.position - two.position);\n\n const colorAt = (position: number): Color => {\n const base = scale.at(position);\n const { hue, lightness } = rgbToOklch(base.r, base.g, base.b);\n const [red, green, blue] = oklchToRgb({\n chroma: fractionAt(anchors, position) * maxChroma(lightness, hue),\n hue,\n lightness,\n });\n\n return new Color([red, green, blue, base.a]);\n };\n\n const measured = arcLength(colorAt);\n\n const at = (distance: number): Color => colorAt(measured.positionAt(distance));\n const distanceOf = (color: Color): number => measured.distanceOf(positionOnScale(scale, color));\n\n const last = Math.max(0, steps - 1);\n const primaryDistance = distanceOf(primary);\n\n // The primary step should almost never be placed into either end of the scale.\n // This will only occur for primary colors that are truly extreme, like black or white.\n const ownsFirst = stops.at(0)?.toHex() === primary.toHex();\n const ownsLast = stops.at(-1)?.toHex() === primary.toHex();\n const lowest = ownsFirst ? 0 : Math.min(1, last);\n const highest = ownsLast ? last : Math.max(lowest, last - 1);\n const primaryStep = clamp(Math.round(primaryDistance * last), lowest, highest);\n\n const distanceOfStep = (index: number): number => {\n if (index === primaryStep) {\n return primaryDistance;\n }\n if (index < primaryStep) {\n return (index / primaryStep) * primaryDistance;\n }\n\n return primaryDistance + ((index - primaryStep) / (last - primaryStep)) * (1 - primaryDistance);\n };\n\n return {\n at,\n atStep: (index) => (index === primaryStep ? primary : at(distanceOfStep(index))),\n positionOf: distanceOf,\n primaryStep,\n stepOf: (color) => {\n const found = distanceOf(color);\n if (found <= primaryDistance) {\n return primaryDistance === 0 ? 0 : (found / primaryDistance) * primaryStep;\n }\n\n return (\n primaryStep + ((found - primaryDistance) / (1 - primaryDistance)) * (last - primaryStep)\n );\n },\n steps,\n };\n};\n","import type { ColorInput } from './types';\nimport { Color } from './Color';\nimport {\n buildBrandedColorScale,\n DEFAULT_COLOR_SCALE_STEPS,\n} from './private/buildBrandedColorScale';\n\nexport type BrandColorScaleOptions = {\n /** How many steps the scale is divided into. */\n readonly steps?: number;\n};\n\n/**\n * Builds a color scale using the derived light/dark background colors based on the given primary color,\n * with the primary color slotted into the scale wherever it fits based on lightness.\n *\n * It's important to include the primary color in the scale because the light/dark derived background colors\n * do not have the same saturation as the primary color, and we want the scale to reflect the vibrancy\n * of the primary color.\n *\n * @example\n * ```ts\n * getBrandedColorScale('#2949e5').map((color) => color.toHex());\n * // ['#ebeefd', '#d4dbfa', '#bdc8f7', '#a5b5f4', '#8da2f1', '#748eef',\n * // '#5b7aec', '#4263e8', '#2949e5', '#2539ba', '#213080', '#171f45']\n * // ^ the primary, at its own lightness\n * ```\n */\nexport const getBrandedColorScale = (\n primaryColor: ColorInput,\n { steps = DEFAULT_COLOR_SCALE_STEPS }: BrandColorScaleOptions = {},\n): Color[] => {\n const scale = buildBrandedColorScale(new Color(primaryColor), { steps });\n\n return Array.from({ length: steps }, (_, index) => scale.atStep(index));\n};\n","import type { ColorInput } from './types';\nimport { Color } from './Color';\n\nexport type ColorLightnessClassification = 'dark' | 'light' | 'midtone' | 'veryDark';\n\n/**\n * The WCAG value for typical ambient light causing flare on a screen\n * https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum\n */\nconst FLARE = 0.05;\n\n/**\n * Below this a background is close enough to black that there is no more visual\n * room to darken the color without reading as black.\n */\nconst VERY_DARK_MAX = 0.05;\n\n/**\n * This number represents the crossover where white stops having more contrast than black,\n * so any values with luminance greater than this value are no longer considered \"dark\".\n *\n * Don't round this number, otherwise we'll potentially classify some backgrounds as \"midtone\"\n * even though light content reads better on them, and we should always have light content on dark backgrounds.\n */\nconst DARK_MAX = Math.sqrt(FLARE * (1 + FLARE)) - FLARE;\n\n/** Above this a background is close enough to white that it needs no lightening at all. */\nconst LIGHT_MIN = 0.8;\n\n/**\n * Classify a color's lightness based on relative luminance.\n *\n * @example\n * ```ts\n * getColorLightnessClassification('#000000'); // 'veryDark'\n * getColorLightnessClassification('#2949e5'); // 'dark'\n * getColorLightnessClassification('#7f7f7f'); // 'midtone'\n * getColorLightnessClassification('#ffffff'); // 'light'\n * ```\n */\nexport const getColorLightnessClassification = (\n color: ColorInput,\n): ColorLightnessClassification => {\n const parsed = new Color(color);\n const luminance = parsed.luminance();\n\n if (luminance < VERY_DARK_MAX) {\n return 'veryDark';\n }\n if (luminance < DARK_MAX) {\n return 'dark';\n }\n\n return luminance < LIGHT_MIN ? 'midtone' : 'light';\n};\n","import type { getBackgroundAccentFromPrimaryColor } from './getBackgroundAccentFromPrimaryColor';\nimport { Color } from '../Color';\nimport { getColorLightnessClassification } from '../getColorLightnessClassification';\nimport { DEFAULT_COLOR_SCALE_STEPS } from './buildBrandedColorScale';\nimport { clamp } from './clamp';\nimport { oklchToRgb, rgbToOklch } from './colorSpace';\nimport { ACHROMATIC_CHROMA, maxChroma } from './maxChroma';\nimport { perceivedLightness } from './perceivedLightness';\n\n/**\n * Get the total distance between the lightest and darkest page background colors, measured in lightness.\n * This determines the actual step size we'll use, which correlates to the size of the step between colors\n * in a branded color scale.\n */\nconst MAX_BACKGROUND_LIGHTNESS = 0.95;\nconst MIN_BACKGROUND_LIGHTNESS = 0.09;\nconst STEP_SIZE_IN_LIGHTNESS =\n (MAX_BACKGROUND_LIGHTNESS - MIN_BACKGROUND_LIGHTNESS) / (DEFAULT_COLOR_SCALE_STEPS - 1);\n\n/**\n * Move the background color by the given distance to generate an accented background color.\n * This is used when no primary color has been provided, meaning the background color was not derived from the primary color.\n * The size of the steps used by this utility should match the size of the steps used in the\n * corresponding {@link getBackgroundAccentFromPrimaryColor} utility.\n */\nexport const getAccentedBackgroundByLightness = (\n backgroundColor: Color,\n distanceInSteps: number,\n): Color => {\n const { chroma, hue, lightness } = rgbToOklch(\n backgroundColor.r,\n backgroundColor.g,\n backgroundColor.b,\n );\n const maxPossibleChroma = maxChroma(lightness, hue);\n\n // If there is no perceptible chroma for this color or for the max possible chroma for this hue/lightness,\n // don't try to add any chroma into the result.\n const share =\n chroma < ACHROMATIC_CHROMA || maxPossibleChroma < ACHROMATIC_CHROMA\n ? 0\n : Math.min(1, chroma / maxPossibleChroma);\n\n const atLightness = (candidate: number): Color => {\n const [red, green, blue] = oklchToRgb({\n chroma: share * maxChroma(candidate, hue),\n hue,\n lightness: candidate,\n });\n\n return new Color([red, green, blue, backgroundColor.a]);\n };\n\n const band = getColorLightnessClassification(backgroundColor);\n const towards = band === 'dark' || band === 'veryDark' ? 1 : -1;\n const target = clamp(\n perceivedLightness(backgroundColor) + towards * distanceInSteps * STEP_SIZE_IN_LIGHTNESS,\n 0,\n 1,\n );\n\n let low = 0;\n let high = 1;\n for (let iteration = 0; iteration < 30; iteration += 1) {\n const middle = (low + high) / 2;\n if (perceivedLightness(atLightness(middle)) < target) {\n low = middle;\n } else {\n high = middle;\n }\n }\n\n return atLightness((low + high) / 2);\n};\n","import type { Color } from '../Color';\nimport { getColorLightnessClassification } from '../getColorLightnessClassification';\nimport { buildBrandedColorScale } from './buildBrandedColorScale';\nimport { clamp } from './clamp';\n\n/**\n * Using a branded color scale based on the primary color,\n * move the given background color by the given distance along the scale\n * to generate an accented version of the background color.\n */\nexport const getBackgroundAccentFromPrimaryColor = (\n backgroundColor: Color,\n stepDistance: number,\n primaryColor: Color,\n): Color => {\n const scale = buildBrandedColorScale(primaryColor);\n const last = scale.steps - 1;\n const colorLightnessClass = getColorLightnessClassification(backgroundColor);\n const towards =\n colorLightnessClass === 'dark' || colorLightnessClass === 'veryDark'\n ? -stepDistance\n : stepDistance;\n const from = clamp(Math.round(scale.stepOf(backgroundColor)), 0, last);\n\n return scale.atStep(clamp(from + towards, 0, last));\n};\n","import type { Color } from '../Color';\nimport { getAccentedBackgroundByLightness } from './getAccentedBackgroundByLightness';\nimport { getBackgroundAccentFromPrimaryColor } from './getBackgroundAccentFromPrimaryColor';\n\ntype AccentedBackgroundOptions = {\n readonly backgroundColor: Color;\n readonly primaryColor?: Color | undefined;\n readonly stepDistance: number;\n};\n\n/**\n * A background `distance` steps off `background`, always in the direction away from it:\n * darker when the background is light, lighter when it is dark.\n *\n * Gets a an accented color spaced apart from the given background color by the given distance.\n * If a primary color is included, we will derive the accent color using a color scale.\n */\nexport const getAccentedBackground = ({\n backgroundColor,\n stepDistance,\n primaryColor,\n}: AccentedBackgroundOptions): Color =>\n primaryColor === undefined\n ? getAccentedBackgroundByLightness(backgroundColor, stepDistance)\n : getBackgroundAccentFromPrimaryColor(backgroundColor, stepDistance, primaryColor);\n","import type { getBrandedColorScale } from './getBrandedColorScale';\nimport type { getSlightAccentedBackgroundColor } from './getSlightAccentedBackgroundColor';\nimport type { ColorInput } from './types';\nimport { Color } from './Color';\nimport { getAccentedBackground } from './private/getAccentedBackground';\n\nexport type HeavyAccentedBackgroundColorOptions = {\n readonly primaryColor?: ColorInput;\n};\n\n/**\n * Get an accented version of a background color that is a two steps lighter/darker.\n * Use this when the color contrast of the accented background color is not significant,\n * such as for card/panel background colors.\n * \n * Accepts an optional primary color, used when the background color has been derived from the primary color,\n * and we want the accented versions of the background color to come from the color scale, see {@link getBrandedColorScale}\n\n * See {@link getSlightAccentedBackgroundColor} for a single step away from the background color instead of two.\n\n *\n * @example\n * ```ts\n * getHeavyAccentedBackgroundColor('#f5f5f5').toHex(); // '#cbcbcb'\n * getHeavyAccentedBackgroundColor('#f5f5f5', { primaryColor: '#2949e5' }).toHex(); // '#adbbf5'\n * ```\n */\nexport const getHeavyAccentedBackgroundColor = (\n _backgroundColor: ColorInput,\n { primaryColor }: HeavyAccentedBackgroundColorOptions = {},\n): Color => {\n const backgroundColor = new Color(_backgroundColor);\n\n return getAccentedBackground({\n backgroundColor,\n stepDistance: 2,\n primaryColor: primaryColor === undefined ? undefined : new Color(primaryColor),\n });\n};\n","import type { getBrandedColorScale } from './getBrandedColorScale';\nimport type { getHeavyAccentedBackgroundColor } from './getHeavyAccentedBackgroundColor';\nimport type { ColorInput } from './types';\nimport { Color } from './Color';\nimport { getAccentedBackground } from './private/getAccentedBackground';\n\nconst WHITE = '#ffffff';\n\nexport type SlightAccentedBackgroundColorOptions = {\n readonly shouldReturnWhiteForWhiteBackground?: boolean;\n /**\n * Optional primary color, which is used when the background color is derived from the primary color,\n * so we'll calculate the accented background color using a color scale.\n */\n readonly primaryColor?: ColorInput;\n};\n\n/**\n * Get an accented version of a background color that is a single step lighter/darker.\n * Use this when the color contrast of the accented background color is not significant,\n * such as for card/panel background colors.\n * \n * Accepts an optional primary color, used when the background color has been derived from the primary color,\n * and we want the accented versions of the background color to come from the color scale, see {@link getBrandedColorScale}\n\n * See {@link getHeavyAccentedBackgroundColor} for two steps away from the background color instead of one.\n *\n * @example\n * ```ts\n * getSlightAccentedBackgroundColor('#f5f5f5').toHex(); // '#e0e0e0'\n * getSlightAccentedBackgroundColor('#f5f5f5', { primaryColor: '#2949e5' }).toHex(); // '#cdd5f9'\n * getSlightAccentedBackgroundColor('#ffffff', { shouldReturnWhiteForWhiteBackground: true }).toHex(); // '#ffffff'\n * ```\n */\nexport const getSlightAccentedBackgroundColor = (\n _backgroundColor: ColorInput,\n {\n shouldReturnWhiteForWhiteBackground = false,\n primaryColor,\n }: SlightAccentedBackgroundColorOptions = {},\n): Color => {\n const backgroundColor = new Color(_backgroundColor);\n\n if (shouldReturnWhiteForWhiteBackground && backgroundColor.toHex() === WHITE) {\n return backgroundColor;\n }\n\n return getAccentedBackground({\n backgroundColor,\n stepDistance: 1,\n primaryColor: primaryColor === undefined ? undefined : new Color(primaryColor),\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"color-bUFJKFtM.js","names":["HEX_RADIX","WHITE","BLACK","ACHROMATIC_CHROMA","#towardsLightness","WHITE","BLACK","#classBreaks","#colors","#correctLightness","#domainBreaks","#domainOutputs","#gamma","#max","#min","#mode","#options","#padding","#sampleRange","#stops","#colorAt","#withOptions","#mapDomain","#toPosition","#correctPosition","#interpolateAt","WHITE","ALMOST_BLACK","ALMOST_WHITE","FLARE"],"sources":["../src/private/clamp.ts","../src/private/colorSpace.ts","../src/private/parseColor.ts","../src/Color.ts","../src/colorContrastRatiosByShape.ts","../src/private/preciseContrast.ts","../src/adjustColorForProperContrast.ts","../src/ColorScale.ts","../src/getBestColorForText.ts","../src/getBrandDarkBackgroundColor.ts","../src/getBrandLightBackgroundColor.ts","../src/private/maxChroma.ts","../src/private/perceivedLightness.ts","../src/private/buildBrandedColorScale.ts","../src/getBrandedColorScale.ts","../src/getColorLightnessClassification.ts","../src/private/getAccentedBackgroundByLightness.ts","../src/private/getBackgroundAccentFromPrimaryColor.ts","../src/private/getAccentedBackground.ts","../src/getHeavyAccentedBackgroundColor.ts","../src/getSlightAccentedBackgroundColor.ts"],"sourcesContent":["/** Restrict `value` to the inclusive range between `min` and `max`. */\nexport const clamp = (value: number, min: number, max: number): number =>\n Math.min(Math.max(value, min), max);\n","// oxlint-disable id-length -- single-letter names mirror the color-space formulas\nimport type { Hsl, Lab, RgbTuple } from '../types';\nimport { clamp } from './clamp';\n\nconst D65_WHITE_POINT = { x: 0.95047, y: 1, z: 1.08883 };\n\nconst DEGREES_PER_RADIAN = 180 / Math.PI;\n\n/** Slack allowed on a linear channel before a color counts as out of gamut. */\nconst GAMUT_EPSILON = 1e-6;\n\n/** Enough halvings to place the gamut boundary well inside a single 0–255 step. */\nconst GAMUT_SEARCH_ITERATIONS = 25;\n\n// CIE standard constants: 216/24389 and 24389/27. Their product, 8, is the L* below\n// which the Lab transfer function stays linear.\nconst LAB_EPSILON = 216 / 24389;\nconst LAB_KAPPA = 24389 / 27;\nconst LAB_LINEAR_LIGHTNESS_THRESHOLD = 8;\n\n/** Gamma-decode a 0–255 sRGB channel into linear light. */\nconst linearize = (channel: number): number => {\n const normalized = channel / 255;\n return normalized <= 0.04045 ? normalized / 12.92 : ((normalized + 0.055) / 1.055) ** 2.4;\n};\n\n/**\n * Gamma-encode linear light back into a 0–255 sRGB channel. The sign is carried through\n * the exponent so that out-of-gamut Lab values produce a negative channel rather than NaN.\n * Inverse of linearize.\n */\nconst compand = (linear: number): number => {\n const magnitude = Math.abs(linear);\n const encoded =\n magnitude <= 0.0031308 ? magnitude * 12.92 : 1.055 * magnitude ** (1 / 2.4) - 0.055;\n return encoded * Math.sign(linear) * 255;\n};\n\nconst pivot = (value: number): number =>\n value > LAB_EPSILON ? Math.cbrt(value) : (LAB_KAPPA * value + 16) / 116;\n\nconst hueToChannel = (start: number, end: number, givenHue: number): number => {\n let hue = givenHue;\n if (hue < 0) {\n hue += 1;\n }\n if (hue > 1) {\n hue -= 1;\n }\n if (hue < 1 / 6) {\n return start + (end - start) * 6 * hue;\n }\n if (hue < 1 / 2) {\n return end;\n }\n if (hue < 2 / 3) {\n return start + (end - start) * (2 / 3 - hue) * 6;\n }\n return start;\n};\n\n/**\n * WCAG relative luminance (0–1).\n *\n * @see https://www.w3.org/WAI/GL/wiki/Relative_luminance\n */\nexport const relativeLuminance = (red: number, green: number, blue: number): number =>\n 0.2126 * linearize(red) + 0.7152 * linearize(green) + 0.0722 * linearize(blue);\n\nexport const rgbToHsl = (red: number, green: number, blue: number): Hsl => {\n const r = red / 255;\n const g = green / 255;\n const b = blue / 255;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const lightness = (max + min) / 2;\n const delta = max - min;\n\n if (delta === 0) {\n return { hue: 0, lightness: lightness * 100, saturation: 0 };\n }\n\n const saturation = lightness > 0.5 ? delta / (2 - max - min) : delta / (max + min);\n\n let hue: number;\n if (max === r) {\n hue = (g - b) / delta + (g < b ? 6 : 0);\n } else if (max === g) {\n hue = (b - r) / delta + 2;\n } else {\n hue = (r - g) / delta + 4;\n }\n\n return { hue: (hue / 6) * 360, lightness: lightness * 100, saturation: saturation * 100 };\n};\n\nexport const hslToRgb = ({ hue, lightness, saturation }: Hsl): RgbTuple => {\n const h = hue / 360;\n const s = saturation / 100;\n const l = lightness / 100;\n const end = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const start = 2 * l - end;\n\n return [\n hueToChannel(start, end, h + 1 / 3) * 255,\n hueToChannel(start, end, h) * 255,\n hueToChannel(start, end, h - 1 / 3) * 255,\n ];\n};\n\nexport const rgbToLab = (red: number, green: number, blue: number): Lab => {\n const r = linearize(red);\n const g = linearize(green);\n const b = linearize(blue);\n\n const x = (0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / D65_WHITE_POINT.x;\n const y = (0.2126729 * r + 0.7151522 * g + 0.072175 * b) / D65_WHITE_POINT.y;\n const z = (0.0193339 * r + 0.119192 * g + 0.9503041 * b) / D65_WHITE_POINT.z;\n\n const fx = pivot(x);\n const fy = pivot(y);\n const fz = pivot(z);\n\n return { a: 500 * (fx - fy), b: 200 * (fy - fz), lightness: 116 * fy - 16 };\n};\n\n/**\n * OKLab in polar form: perceptual lightness (0–1), chroma (0 at gray, ~0.4 at the most\n * saturated sRGB colors) and hue in degrees. Unlike CIELAB, a fixed `hue` here reads as\n * one hue at every lightness — CIELAB's hue lines bend, which is why lightening a blue\n * along them walks it towards purple.\n *\n * @see https://bottosson.github.io/posts/oklab/\n */\nexport type Oklch = {\n readonly chroma: number;\n readonly hue: number;\n readonly lightness: number;\n};\n\nexport const rgbToOklch = (red: number, green: number, blue: number): Oklch => {\n const r = linearize(red);\n const g = linearize(green);\n const b = linearize(blue);\n\n const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);\n const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);\n const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);\n\n const aAxis = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;\n const bAxis = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;\n\n return {\n chroma: Math.hypot(aAxis, bAxis),\n hue: (Math.atan2(bAxis, aAxis) * DEGREES_PER_RADIAN + 360) % 360,\n lightness: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n };\n};\n\n/** Linear-light sRGB, which runs 0–1 and goes outside that range when out of gamut. */\nconst oklchToLinearRgb = ({ chroma, hue, lightness }: Oklch): RgbTuple => {\n const radians = hue / DEGREES_PER_RADIAN;\n const aAxis = Math.cos(radians) * chroma;\n const bAxis = Math.sin(radians) * chroma;\n\n const l = (lightness + 0.3963377774 * aAxis + 0.2158037573 * bAxis) ** 3;\n const m = (lightness - 0.1055613458 * aAxis - 0.0638541728 * bAxis) ** 3;\n const s = (lightness - 0.0894841775 * aAxis - 1.291485548 * bAxis) ** 3;\n\n return [\n 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,\n ];\n};\n\nconst fitsGamut = (oklch: Oklch): boolean =>\n oklchToLinearRgb(oklch).every(\n (channel) => channel >= -GAMUT_EPSILON && channel <= 1 + GAMUT_EPSILON,\n );\n\n/**\n * The most chroma this lightness and hue can hold inside sRGB, found by bisection. A hue\n * only gets so colorful before the gamut runs out, and that ceiling drops away sharply as\n * a color approaches white or black.\n */\nconst maximumChroma = (oklch: Oklch): number => {\n let low = 0;\n let high = oklch.chroma;\n\n for (let iteration = 0; iteration < GAMUT_SEARCH_ITERATIONS; iteration += 1) {\n const mid = (low + high) / 2;\n if (fitsGamut({ ...oklch, chroma: mid })) {\n low = mid;\n } else {\n high = mid;\n }\n }\n\n return low;\n};\n\n/**\n * Convert to sRGB, pulling chroma in until the color fits rather than clamping each\n * channel independently. Clamping is what bends the hue of an out-of-gamut color — a\n * lightened red whose red channel pins at 255 while green keeps climbing arrives at\n * yellow. Trading colorfulness for an exact hue and lightness keeps the family intact.\n */\nexport const oklchToRgb = (oklch: Oklch): RgbTuple => {\n const inGamut = fitsGamut(oklch) ? oklch : { ...oklch, chroma: maximumChroma(oklch) };\n const [red, green, blue] = oklchToLinearRgb(inGamut);\n\n return [compand(clamp(red, 0, 1)), compand(clamp(green, 0, 1)), compand(clamp(blue, 0, 1))];\n};\n\nexport const labToRgb = ({ a, b, lightness }: Lab): RgbTuple => {\n const fy = (lightness + 16) / 116;\n const fx = fy + a / 500;\n const fz = fy - b / 200;\n\n const x = (fx ** 3 > LAB_EPSILON ? fx ** 3 : (116 * fx - 16) / LAB_KAPPA) * D65_WHITE_POINT.x;\n const y =\n (lightness > LAB_LINEAR_LIGHTNESS_THRESHOLD ? fy ** 3 : lightness / LAB_KAPPA) *\n D65_WHITE_POINT.y;\n const z = (fz ** 3 > LAB_EPSILON ? fz ** 3 : (116 * fz - 16) / LAB_KAPPA) * D65_WHITE_POINT.z;\n\n return [\n compand(3.2404542 * x - 1.5371385 * y - 0.4985314 * z),\n compand(-0.969266 * x + 1.8760108 * y + 0.041556 * z),\n compand(0.0556434 * x - 0.2040259 * y + 1.0572252 * z),\n ];\n};\n","// oxlint-disable id-length -- r/g/b/a are the canonical names for color channels\nimport type { ColorInput, RgbaTuple } from '../types';\nimport { clamp } from './clamp';\n\nconst HEX_PATTERN = /^#?([\\da-f]{3,4}|[\\da-f]{6}|[\\da-f]{8})$/i;\nconst RGB_FUNCTION_PATTERN = /^rgba?\\(([^)]*)\\)$/i;\nconst NUMBER_PATTERN = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)$/;\nconst PERCENTAGE_PATTERN = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)%$/;\nconst SEPARATOR_PATTERN = /[\\s,]+/;\n\nconst MAX_CHANNEL = 255;\nconst HEX_RADIX = 16;\n\nconst toChannel = (value: number): number => clamp(value, 0, MAX_CHANNEL);\nconst toAlpha = (value: number): number => clamp(value, 0, 1);\n\n/**\n * Read a numeric token, where a percentage is taken as a fraction of `percentageOf`. A\n * channel is `128` or `50%` (of 255); an alpha is `0.5` or `50%` (of 1).\n */\nconst parseNumericToken = (token: string | undefined, percentageOf: number): number | null => {\n if (token === undefined) {\n return null;\n }\n if (PERCENTAGE_PATTERN.test(token)) {\n return (Number(token.slice(0, -1)) / 100) * percentageOf;\n }\n if (NUMBER_PATTERN.test(token)) {\n return Number(token);\n }\n return null;\n};\n\nconst parseChannelToken = (token: string | undefined): number | null => {\n const value = parseNumericToken(token, MAX_CHANNEL);\n return value === null ? null : toChannel(value);\n};\n\nconst parseAlphaToken = (token: string | undefined): number | null => {\n const value = parseNumericToken(token, 1);\n return value === null ? null : toAlpha(value);\n};\n\nconst parseHex = (value: string): RgbaTuple | null => {\n const match = HEX_PATTERN.exec(value);\n const digits = match?.[1];\n if (digits === undefined) {\n return null;\n }\n\n // #rgb and #rgba are shorthand for each digit repeated: #1a2 -> #11aa22\n const expanded = digits.length <= 4 ? digits.replaceAll(/./g, '$&$&') : digits;\n\n return [\n Number.parseInt(expanded.slice(0, 2), HEX_RADIX),\n Number.parseInt(expanded.slice(2, 4), HEX_RADIX),\n Number.parseInt(expanded.slice(4, 6), HEX_RADIX),\n expanded.length === 8 ? Number.parseInt(expanded.slice(6, 8), HEX_RADIX) / MAX_CHANNEL : 1,\n ];\n};\n\nconst parseRgbFunction = (value: string): RgbaTuple | null => {\n const match = RGB_FUNCTION_PATTERN.exec(value);\n const body = match?.[1];\n if (body === undefined) {\n return null;\n }\n\n // Modern syntax puts alpha behind a slash: rgb(41 73 229 / 50%)\n const [channelSource, alphaSource, ...extraSources] = body.split('/');\n if (channelSource === undefined || extraSources.length > 0) {\n return null;\n }\n\n const tokens = channelSource.trim().split(SEPARATOR_PATTERN).filter(Boolean);\n const alphaTokens = (alphaSource ?? '').trim().split(SEPARATOR_PATTERN).filter(Boolean);\n if (alphaTokens.length > 1) {\n return null;\n }\n\n const [redToken, greenToken, blueToken, legacyAlphaToken, ...extraTokens] = tokens;\n if (extraTokens.length > 0) {\n return null;\n }\n if (alphaSource !== undefined && legacyAlphaToken !== undefined) {\n return null;\n }\n\n const red = parseChannelToken(redToken);\n const green = parseChannelToken(greenToken);\n const blue = parseChannelToken(blueToken);\n if (red === null || green === null || blue === null) {\n return null;\n }\n\n const alphaToken = alphaTokens[0] ?? legacyAlphaToken;\n if (alphaToken === undefined) {\n return [red, green, blue, 1];\n }\n\n const alpha = parseAlphaToken(alphaToken);\n return alpha === null ? null : [red, green, blue, alpha];\n};\n\n/**\n * Read any supported color representation into RGBA channels, or `null` when the input\n * is not a color this package understands.\n */\nexport const parseColor = (input: ColorInput): RgbaTuple | null => {\n if (typeof input === 'string') {\n const trimmed = input.trim();\n return parseHex(trimmed) ?? parseRgbFunction(trimmed);\n }\n\n if (Array.isArray(input)) {\n const [red, green, blue, alpha = 1] = input;\n if (![red, green, blue, alpha].every((value) => Number.isFinite(value))) {\n return null;\n }\n return [toChannel(red), toChannel(green), toChannel(blue), toAlpha(alpha)];\n }\n\n const { r, g, b, a = 1 } = input;\n if (![r, g, b, a].every((value) => Number.isFinite(value))) {\n return null;\n }\n return [toChannel(r), toChannel(g), toChannel(b), toAlpha(a)];\n};\n","import type { Oklch } from './private/colorSpace';\nimport type { ColorInput, Hsl, InterpolationMode, Lab, RgbaTuple } from './types';\n// oxlint-disable id-length -- r/g/b/a are the canonical names for color channels\nimport { clamp } from './private/clamp';\nimport {\n hslToRgb,\n labToRgb,\n oklchToRgb,\n relativeLuminance,\n rgbToHsl,\n rgbToLab,\n rgbToOklch,\n} from './private/colorSpace';\nimport { parseColor } from './private/parseColor';\n\nconst HEX_RADIX = 16;\n\n/** The ends of the OKLab lightness axis: white and black. */\nconst MAX_LIGHTNESS = 1;\nconst MIN_LIGHTNESS = 0;\n\nconst DEFAULT_INTERPOLATION_MODE: InterpolationMode = 'oklch';\n\nconst WHITE = '#ffffff';\nconst BLACK = '#000000';\n\n/** Wistia brand blue (`#2949e5`) — what an unreadable input resolves to. */\nconst FALLBACK_CHANNELS: RgbaTuple = [41, 73, 229, 1];\n\nconst toHexPair = (channel: number): string =>\n Math.round(channel).toString(HEX_RADIX).padStart(2, '0');\n\n/**\n * Truncated rather than rounded, so a ratio can never climb across a WCAG threshold on\n * its way to one decimal — 4.4501 reports as 4.4, not as a passing 4.5.\n */\nconst truncateToTenth = (ratio: number): number => Math.floor(ratio * 10) / 10;\n\nconst interpolate = (from: number, to: number, ratio: number): number => from + (to - from) * ratio;\n\n/**\n * Interpolate through linear light rather than gamma-encoded sRGB, which keeps blends\n * between saturated colors from sagging through a muddy midpoint.\n */\nconst interpolateLinear = (from: number, to: number, ratio: number): number =>\n Math.sqrt(from ** 2 * (1 - ratio) + to ** 2 * ratio);\n\n/** Below this much chroma a color reads as gray, and its hue stops meaning anything. */\nconst ACHROMATIC_CHROMA = 1e-4;\n\nconst HALF_TURN = 180;\nconst FULL_TURN = 360;\n\n/**\n * Interpolate hue the short way round the wheel — blue to yellow crosses green or magenta,\n * never both. A gray has no hue of its own to offer, so it borrows the other end's rather\n * than dragging the blend through unrelated hues on the way to white or black.\n */\nconst interpolateHue = (from: Oklch, to: Oklch, ratio: number): number => {\n if (from.chroma < ACHROMATIC_CHROMA) {\n return to.hue;\n }\n if (to.chroma < ACHROMATIC_CHROMA) {\n return from.hue;\n }\n\n const difference = ((to.hue - from.hue + HALF_TURN + FULL_TURN) % FULL_TURN) - HALF_TURN;\n return from.hue + difference * ratio;\n};\n\n/**\n * An immutable sRGB color with transformation methods like lighten, darken, tint, shade.\n * Also includes methods to calculate contrast ratio against another color, relative luminance, etc.\n *\n * @example\n * ```ts\n * new Color('#2949e5').lighten(0.5).toHex(); // '#89aaff'\n * new Color('#2949e5').withAlpha(0.5).toRgba(); // 'rgba(41, 73, 229, 0.5)'\n * new Color('#2949e5').contrast('#ffffff'); // 6.6\n * ```\n */\nexport class Color {\n /**\n * Read `input` into a color, returning `null` when it cannot be parsed.\n */\n static parse(input: ColorInput): Color | null {\n const channels = parseColor(input);\n return channels === null ? null : new Color(channels);\n }\n\n static fromHsl(hsl: Hsl, alpha = 1): Color {\n const [red, green, blue] = hslToRgb(hsl);\n return new Color([red, green, blue, alpha]);\n }\n\n static fromLab(lab: Lab, alpha = 1): Color {\n const [red, green, blue] = labToRgb(lab);\n return new Color([red, green, blue, alpha]);\n }\n\n /** Red channel, 0–255. Kept unrounded so that chained operations don't accumulate error. */\n readonly r: number;\n\n /** Green channel, 0–255. Kept unrounded so that chained operations don't accumulate error. */\n readonly g: number;\n\n /** Blue channel, 0–255. Kept unrounded so that chained operations don't accumulate error. */\n readonly b: number;\n\n /** Alpha channel, 0–1. */\n readonly a: number;\n\n /**\n * @param input - any supported color representation. Input that cannot be read as a\n * color resolves to brand blue rather than failing, so a malformed value degrades to\n * a usable color instead of interrupting a render.\n */\n constructor(input: ColorInput) {\n const [red, green, blue, alpha] = parseColor(input) ?? FALLBACK_CHANNELS;\n this.r = red;\n this.g = green;\n this.b = blue;\n this.a = alpha;\n }\n\n /** `#rrggbb`. Alpha is dropped — use {@link Color.toHexWithAlpha} to keep it. */\n toHex(): string {\n return `#${toHexPair(this.r)}${toHexPair(this.g)}${toHexPair(this.b)}`;\n }\n\n /** `#rrggbbaa`. */\n toHexWithAlpha(): string {\n return `${this.toHex()}${toHexPair(this.a * 255)}`;\n }\n\n /** `rgb(41, 73, 229)`. */\n toRgb(): string {\n return `rgb(${Math.round(this.r)}, ${Math.round(this.g)}, ${Math.round(this.b)})`;\n }\n\n /** `rgba(41, 73, 229, 0.5)`. */\n toRgba(): string {\n return `rgba(${Math.round(this.r)}, ${Math.round(this.g)}, ${Math.round(this.b)}, ${this.a})`;\n }\n\n /** Rounded channels, ready to hand to another color library. */\n toRgbaTuple(): RgbaTuple {\n return [Math.round(this.r), Math.round(this.g), Math.round(this.b), this.a];\n }\n\n toHsl(): Hsl {\n return rgbToHsl(this.r, this.g, this.b);\n }\n\n toLab(): Lab {\n return rgbToLab(this.r, this.g, this.b);\n }\n\n /** Hex when fully opaque, `rgba()` otherwise, so the alpha is never silently lost. */\n toString(): string {\n return this.a === 1 ? this.toHex() : this.toRgba();\n }\n\n /**\n * WCAG relative luminance, from 0 (black) to 1 (white). Alpha is ignored — luminance\n * is only meaningful once a color has been composited onto a background.\n */\n luminance(): number {\n return relativeLuminance(this.r, this.g, this.b);\n }\n\n /**\n * WCAG contrast ratio against `other`, from 1 (identical) to 21 (black on white),\n * reported to one decimal place.\n *\n * @see {@link colorContrastRatiosByShape} for the ratio each kind of content needs\n */\n contrast(other: ColorInput): number {\n const ownLuminance = this.luminance();\n const otherLuminance = new Color(other).luminance();\n const lighter = Math.max(ownLuminance, otherLuminance);\n const darker = Math.min(ownLuminance, otherLuminance);\n return truncateToTenth((lighter + 0.05) / (darker + 0.05));\n }\n\n /**\n * Raise perceptual lightness `ratio` (0–1) of the way to white, holding the hue steady.\n *\n * The hue is held in OKLCh, so a lightened color stays recognizably itself: a blue\n * lightens to a paler blue instead of drifting purple, and a red that runs out of sRGB\n * gives up colorfulness rather than sliding towards orange. That is the difference from\n * {@link Color.tint}, which stirs white into the channels and lets the hue land where it\n * may.\n */\n lighten(ratio: number): Color {\n return this.#towardsLightness(MAX_LIGHTNESS, ratio);\n }\n\n /** Lower perceptual lightness `ratio` (0–1) of the way to black, holding the hue steady. */\n darken(ratio: number): Color {\n return this.#towardsLightness(MIN_LIGHTNESS, ratio);\n }\n\n /** Mix `ratio` (0–1) of white in. */\n tint(ratio: number, mode: InterpolationMode = DEFAULT_INTERPOLATION_MODE): Color {\n return this.blend(WHITE, ratio, mode);\n }\n\n /** Mix `ratio` (0–1) of black in. */\n shade(ratio: number, mode: InterpolationMode = DEFAULT_INTERPOLATION_MODE): Color {\n return this.blend(BLACK, ratio, mode);\n }\n\n /**\n * Mix towards `other`, where `ratio` 0 keeps this color and 1 returns `other`. Alpha is\n * always interpolated linearly, whichever `mode` the channels travel through.\n */\n blend(\n other: ColorInput,\n ratio = 0.5,\n mode: InterpolationMode = DEFAULT_INTERPOLATION_MODE,\n ): Color {\n const target = new Color(other);\n const amount = clamp(ratio, 0, 1);\n const alpha = interpolate(this.a, target.a, amount);\n\n if (mode === 'oklch') {\n const from = rgbToOklch(this.r, this.g, this.b);\n const to = rgbToOklch(target.r, target.g, target.b);\n const [red, green, blue] = oklchToRgb({\n chroma: interpolate(from.chroma, to.chroma, amount),\n hue: interpolateHue(from, to, amount),\n lightness: interpolate(from.lightness, to.lightness, amount),\n });\n\n return new Color([red, green, blue, alpha]);\n }\n\n if (mode === 'lab') {\n const from = this.toLab();\n const to = target.toLab();\n return Color.fromLab(\n {\n a: interpolate(from.a, to.a, amount),\n b: interpolate(from.b, to.b, amount),\n lightness: interpolate(from.lightness, to.lightness, amount),\n },\n alpha,\n );\n }\n\n const blendChannel = mode === 'lrgb' ? interpolateLinear : interpolate;\n return new Color([\n blendChannel(this.r, target.r, amount),\n blendChannel(this.g, target.g, amount),\n blendChannel(this.b, target.b, amount),\n alpha,\n ]);\n }\n\n /** Replace the alpha channel with `alpha` (0–1). */\n withAlpha(alpha: number): Color {\n return new Color([this.r, this.g, this.b, alpha]);\n }\n\n /**\n * Replace HSL lightness with `lightness` (0–100), leaving hue and saturation alone.\n * Use this to hit an absolute lightness; use {@link Color.lighten} to step relative to\n * where the color already is.\n */\n withLightness(lightness: number): Color {\n const { hue, saturation } = this.toHsl();\n return Color.fromHsl({ hue, lightness: clamp(lightness, 0, 100), saturation }, this.a);\n }\n\n /**\n * Travel `ratio` of the way to `target` along the OKLab lightness axis, keeping hue and\n * as much colorfulness as the sRGB gamut has room for at the lightness we arrive at.\n */\n #towardsLightness(target: number, ratio: number): Color {\n const { chroma, hue, lightness } = rgbToOklch(this.r, this.g, this.b);\n const [red, green, blue] = oklchToRgb({\n chroma,\n hue,\n lightness: interpolate(lightness, target, clamp(ratio, 0, 1)),\n });\n\n return new Color([red, green, blue, this.a]);\n }\n}\n","export const colorContrastRatiosByShape = {\n nonText: 3.0, // 3.0:1 - https://www.w3.org/TR/WCAG21/#non-text-contrast\n largeText: 3.0, // 3.0:1 - https://www.w3.org/TR/WCAG21/#contrast-minimum\n paragraphText: 4.5, // 4.5:1 - https://www.w3.org/TR/WCAG21/#contrast-minimum\n smallText: 5.5, // We're making this up, but it should be more than the paragraph text\n} as const;\n\n/** The kind of content a color has to be legible as, which sets the ratio it has to clear. */\nexport type ColorShape = keyof typeof colorContrastRatiosByShape;\n","import type { Color } from '../Color';\n\n/**\n * The WCAG contrast ratio between two colors at full precision, unlike\n * {@link Color.contrast}, which truncates to one decimal.\n *\n * Use this to compare two ratios against each other; use `Color.contrast` to decide\n * whether one clears a required ratio. Truncation is fine for the second and ruinous for\n * the first: near-identical ratios collapse to the same tenth and tie, which sends a\n * direction probe the long way round or ranks two candidates arbitrarily.\n */\nexport const preciseContrast = (color: Color, other: Color): number => {\n const ownLuminance = color.luminance();\n const otherLuminance = other.luminance();\n return (\n (Math.max(ownLuminance, otherLuminance) + 0.05) /\n (Math.min(ownLuminance, otherLuminance) + 0.05)\n );\n};\n","import type { ColorShape } from './colorContrastRatiosByShape';\nimport type { ColorInput } from './types';\nimport { Color } from './Color';\nimport { colorContrastRatiosByShape } from './colorContrastRatiosByShape';\nimport { clamp } from './private/clamp';\nimport { preciseContrast } from './private/preciseContrast';\n\nconst WHITE = '#ffffff';\nconst BLACK = '#000000';\n\n/** One HSL lightness percentage point — the step the search walks the foreground by. */\nconst LIGHTNESS_STEP = 1;\n\n/** How far to probe each way when deciding which direction gains contrast faster. */\nconst PROBE_RATIO = 0.1;\n\n/** HSL lightness bands where a color is close enough to an extreme to have nowhere to go. */\nconst NEARLY_BLACK_LIGHTNESS = 10;\nconst NEARLY_WHITE_LIGHTNESS = 80;\n\n/** Contrast of a color against itself, and the floor of the WCAG ratio. */\nconst MIN_CONTRAST = 1.0;\n\n/** The ends of the luminance range: the search has run out of room once it lands on one. */\nconst MAX_LUMINANCE = 1;\nconst MIN_LUMINANCE = 0;\n\n/**\n * Backstop on the search. Flipping direction at the extremes should always converge well\n * before this, so reaching it means something is wrong, not that the budget was tight.\n */\nconst MAX_ITERATIONS = 1000;\n\nexport type AdjustColorForProperContrastOptions = {\n /** What the foreground sits on. Never adjusted. */\n readonly backgroundColor: ColorInput;\n\n /** The color to nudge until it is legible. Returned untouched if it already is. */\n readonly foregroundColor: ColorInput;\n\n /** What the foreground is. Defaults to `paragraphText` (4.5:1). */\n readonly shape?: ColorShape;\n};\n\n/**\n * Walk `foregroundColor` towards white or black until it clears the contrast ratio\n * `shape` requires against `backgroundColor`.\n *\n * Hue is pinned for the whole walk, so the result still reads as the color you passed in\n * — a washed-out brand blue stays blue rather than drifting towards its neighbors. The\n * direction is whichever gains contrast faster, reversing if it hits an extreme with the\n * ratio still unmet. Text-grade ratios that can't be met either way settle on plain white\n * or black, since at that point nothing else beats them.\n *\n * @example\n * ```ts\n * // Already legible, so nothing moves.\n * adjustColorForProperContrast({\n * foregroundColor: '#2949e5',\n * backgroundColor: '#ffffff',\n * }).toHex(); // '#2949e5'\n *\n * // A brand blue on itself, darkened until it separates.\n * adjustColorForProperContrast({\n * foregroundColor: '#2949e5',\n * backgroundColor: '#2949e5',\n * shape: 'nonText',\n * }).toHex();\n * ```\n */\nexport const adjustColorForProperContrast = ({\n backgroundColor,\n foregroundColor,\n shape = 'paragraphText',\n}: AdjustColorForProperContrastOptions): Color => {\n const background = new Color(backgroundColor);\n const foreground = new Color(foregroundColor);\n const requiredContrast = colorContrastRatiosByShape[shape];\n\n const initialContrast = foreground.contrast(background);\n if (initialContrast >= requiredContrast) {\n return foreground;\n }\n\n const { hue, lightness: initialLightness } = foreground.toHsl();\n\n let shouldBeLighter =\n initialLightness < NEARLY_BLACK_LIGHTNESS ||\n preciseContrast(foreground.tint(PROBE_RATIO, 'rgb'), background) >\n preciseContrast(foreground.shade(PROBE_RATIO, 'rgb'), background);\n\n // A nearly-white foreground gains a sliver of contrast by lightening, but can never gain\n // enough — the only way out is down.\n if (initialLightness > NEARLY_WHITE_LIGHTNESS && initialContrast === MIN_CONTRAST) {\n shouldBeLighter = false;\n }\n\n let adjusted = foreground;\n\n for (let iteration = 0; iteration < MAX_ITERATIONS; iteration += 1) {\n if (adjusted.contrast(background) >= requiredContrast) {\n return adjusted;\n }\n\n const luminance = adjusted.luminance();\n // Out of room at white or black with the ratio still unmet. Nothing beats an extreme\n // at the stricter text ratios, so take it; the looser ones get a second pass back the\n // other way, which may land on a color truer to the original than an extreme would be.\n if (iteration > 0 && (luminance === MAX_LUMINANCE || luminance === MIN_LUMINANCE)) {\n if (requiredContrast > colorContrastRatiosByShape.nonText) {\n const white = new Color(WHITE);\n const black = new Color(BLACK);\n return white.contrast(background) > black.contrast(background) ? white : black;\n }\n\n shouldBeLighter = !shouldBeLighter;\n adjusted = foreground;\n }\n\n const { lightness, saturation } = adjusted.toHsl();\n const stepped = Color.fromHsl(\n {\n hue,\n lightness: clamp(lightness + (shouldBeLighter ? LIGHTNESS_STEP : -LIGHTNESS_STEP), 0, 100),\n saturation,\n },\n adjusted.a,\n );\n\n // Snap to the 8-bit color the caller will actually render. Color keeps channels\n // unrounded, so measuring contrast on them can clear the ratio by a hair that\n // rounding to hex then gives back, handing back a color that doesn't actually pass the required contrast.\n adjusted = new Color(stepped.toRgbaTuple());\n }\n\n // Never converged. Hand back the closest we got rather than interrupting a render.\n return adjusted;\n};\n","import type { ColorInput, InterpolationMode } from './types';\nimport { Color } from './Color';\nimport { clamp } from './private/clamp';\n\ntype Stop = {\n readonly color: Color;\n readonly position: number;\n};\n\nconst DEFAULT_DOMAIN: [number, number] = [0, 1];\nconst DEFAULT_MODE: InterpolationMode = 'lrgb';\nconst DEFAULT_PADDING: [number, number] = [0, 0];\n\n/** Ceiling on the binary search in `correctLightness` */\nconst MAX_LIGHTNESS_ITERATIONS = 20;\nconst LIGHTNESS_TOLERANCE = 0.01;\n\nexport type ColorScaleOptions = {\n /**\n * Quantize the scale into bands instead of leaving it continuous: a count of equally sized\n * classes across the domain, or explicit class breaks.\n */\n readonly classes?: number | number[];\n\n /**\n * Redistribute stops so that perceived lightness moves evenly from end to end. Worth\n * turning on for any scale a reader is meant to rank by eye.\n */\n readonly correctLightness?: boolean;\n\n /**\n * The input range, `[0, 1]` by default. Two values set the ends; supply one value per\n * color to pin each color to a position, or more than two to warp the scale.\n */\n readonly domain?: number[];\n\n /** Bias the scale towards one end. Above 1 favors the start, below 1 the end. */\n readonly gamma?: number;\n\n /** The color space blends travel through. */\n readonly mode?: InterpolationMode;\n\n /** Trim `[start, end]` fractions off the scale, dropping its most extreme colors. */\n readonly padding?: [number, number] | number;\n};\n\nconst toPaddingPair = (padding: ColorScaleOptions['padding']): [number, number] => {\n const pair: [number, number] =\n typeof padding === 'number' ? [padding, padding] : (padding ?? DEFAULT_PADDING);\n return [clamp(pair[0], 0, 1), clamp(pair[1], 0, 1)];\n};\n\nconst toClassBreaks = (\n classes: ColorScaleOptions['classes'],\n min: number,\n max: number,\n): number[] | null => {\n if (classes === undefined) {\n return null;\n }\n if (Array.isArray(classes)) {\n return classes.length === 0 ? null : classes;\n }\n if (classes < 1) {\n return [min, max];\n }\n return Array.from({ length: classes + 1 }, (_, index) => min + (index / classes) * (max - min));\n};\n\n/** The index of the class `value` falls into, or -1 when it sits below the first break. */\nconst toClassIndex = (value: number, breaks: number[]): number => {\n let index = 0;\n while (index < breaks.length - 1 && value >= (breaks[index] ?? Number.POSITIVE_INFINITY)) {\n index += 1;\n }\n return index - 1;\n};\n\n/**\n * A continuous scale between two or more colors — the chroma.js `scale` model, as an\n * immutable class. Every configuration method returns a new scale, so a configured scale\n * is safe to hold onto and share.\n *\n * @example\n * ```ts\n * const scale = new ColorScale(['#2949e5', '#ffffff']);\n * scale.at(0.5).toHex(); // the midpoint color\n * scale.colors(5).map((color) => color.toHex()); // five evenly spaced colors\n * scale.correctLightness().domain([0, 100]).at(72); // perceptually even, read in %\n * ```\n */\nexport class ColorScale {\n readonly #classBreaks: number[] | null;\n readonly #colors: [Color, ...Color[]];\n readonly #correctLightness: boolean;\n readonly #domainBreaks: number[] | null;\n readonly #domainOutputs: number[] | null;\n readonly #gamma: number;\n readonly #max: number;\n readonly #min: number;\n readonly #mode: InterpolationMode;\n readonly #options: ColorScaleOptions;\n readonly #padding: [number, number];\n readonly #sampleRange: [number, number];\n readonly #stops: [Stop, ...Stop[]];\n\n /**\n * @param colors - the colors the scale runs through; a single color makes a flat scale\n * @throws {TypeError} when `colors` is empty or `domain` has fewer than two values\n */\n constructor(colors: readonly ColorInput[], options: ColorScaleOptions = {}) {\n const [firstColor, ...remainingColors] = colors.map((color) => new Color(color));\n if (firstColor === undefined) {\n throw new TypeError('A color scale needs at least one color.');\n }\n\n // A lone color still has to interpolate against something, so it becomes both ends.\n this.#colors =\n remainingColors.length === 0 ? [firstColor, firstColor] : [firstColor, ...remainingColors];\n this.#options = options;\n this.#mode = options.mode ?? DEFAULT_MODE;\n this.#gamma = options.gamma ?? 1;\n this.#padding = toPaddingPair(options.padding);\n this.#correctLightness = options.correctLightness ?? false;\n\n const domain = options.domain ?? DEFAULT_DOMAIN;\n const min = domain[0];\n const max = domain.at(-1);\n if (min === undefined || max === undefined || domain.length < 2) {\n throw new TypeError('A color scale domain needs at least two values.');\n }\n this.#min = min;\n this.#max = max;\n\n const count = this.#colors.length;\n let positions: number[];\n let domainBreaks: number[] | null = null;\n let domainOutputs: number[] | null = null;\n\n if (domain.length === count && min !== max) {\n // One domain value per color pins each color to its own position.\n positions = domain.map((value) => (value - min) / (max - min));\n } else {\n positions = this.#colors.map((_, index) => index / (count - 1));\n\n if (domain.length > 2 && min !== max) {\n const breaks = domain.map((value) => (value - min) / (max - min));\n const outputs = domain.map((_, index) => index / (domain.length - 1));\n // Only warp the scale when the intermediate values aren't already evenly spaced.\n if (!breaks.every((value, index) => outputs[index] === value)) {\n domainBreaks = breaks;\n domainOutputs = outputs;\n }\n }\n }\n\n this.#domainBreaks = domainBreaks;\n this.#domainOutputs = domainOutputs;\n\n const [firstStopColor, ...remainingStopColors] = this.#colors;\n this.#stops = [\n { color: firstStopColor, position: positions[0] ?? 0 },\n ...remainingStopColors.map((color, index) => ({\n color,\n position: positions[index + 1] ?? 1,\n })),\n ];\n\n this.#classBreaks = toClassBreaks(options.classes, min, max);\n const firstBreak = this.#classBreaks?.[0];\n const lastBreak = this.#classBreaks?.at(-1);\n this.#sampleRange =\n firstBreak === undefined || lastBreak === undefined ? [min, max] : [firstBreak, lastBreak];\n }\n\n /** The color at `value`, read through the scale's domain, classes, gamma and padding. */\n at(value: number): Color {\n if (!Number.isFinite(value)) {\n throw new TypeError(`A color scale cannot be sampled at ${String(value)}.`);\n }\n return this.#colorAt(value, false);\n }\n\n /** `count` colors spread evenly across the domain. */\n colors(count: number): Color[] {\n if (!Number.isInteger(count) || count < 0) {\n throw new TypeError(`A color scale cannot produce ${String(count)} colors.`);\n }\n if (count === 0) {\n return [];\n }\n\n const [start, end] = this.#sampleRange;\n if (count === 1) {\n return [this.at(start + (end - start) / 2)];\n }\n\n const span = end - start;\n return Array.from({ length: count }, (_, index) =>\n this.at(start + (index / (count - 1)) * span),\n );\n }\n\n mode(mode: InterpolationMode): ColorScale {\n return this.#withOptions({ mode });\n }\n\n domain(domain: number[]): ColorScale {\n return this.#withOptions({ domain });\n }\n\n gamma(gamma: number): ColorScale {\n return this.#withOptions({ gamma });\n }\n\n padding(padding: [number, number] | number): ColorScale {\n return this.#withOptions({ padding });\n }\n\n correctLightness(correctLightness = true): ColorScale {\n return this.#withOptions({ correctLightness });\n }\n\n classes(classes: number | number[]): ColorScale {\n return this.#withOptions({ classes });\n }\n\n #withOptions(overrides: ColorScaleOptions): ColorScale {\n return new ColorScale(this.#colors, { ...this.#options, ...overrides });\n }\n\n #colorAt(value: number, bypassValueMapping: boolean): Color {\n let position = clamp(\n this.#mapDomain(bypassValueMapping ? value : this.#toPosition(value)),\n 0,\n 1,\n );\n\n if (!bypassValueMapping && this.#correctLightness) {\n position = this.#correctPosition(position);\n }\n\n if (this.#gamma !== 1) {\n position **= this.#gamma;\n }\n\n const [paddingStart, paddingEnd] = this.#padding;\n position = paddingStart + position * (1 - paddingStart - paddingEnd);\n\n return this.#interpolateAt(clamp(position, 0, 1));\n }\n\n /** Map a domain value onto the scale's unpadded 0–1 range. */\n #toPosition(value: number): number {\n const breaks = this.#classBreaks;\n if (breaks !== null && breaks.length > 2) {\n return toClassIndex(value, breaks) / (breaks.length - 2);\n }\n if (this.#max === this.#min) {\n return 1;\n }\n return (value - this.#min) / (this.#max - this.#min);\n }\n\n /** Warp the scale so that intermediate domain values land where the caller placed them. */\n #mapDomain(position: number): number {\n const breaks = this.#domainBreaks;\n const outputs = this.#domainOutputs;\n if (breaks === null || outputs === null || position <= 0 || position >= 1) {\n return position;\n }\n\n let index = 0;\n while (index < breaks.length - 2 && position >= (breaks[index + 1] ?? 1)) {\n index += 1;\n }\n\n const start = breaks[index] ?? 0;\n const end = breaks[index + 1] ?? 1;\n const outputStart = outputs[index] ?? 0;\n const outputEnd = outputs[index + 1] ?? 1;\n if (end === start) {\n return outputStart;\n }\n return outputStart + ((position - start) / (end - start)) * (outputEnd - outputStart);\n }\n\n /**\n * Nudge `position` until the color there carries the Lab lightness an evenly lit scale\n * would have, by bisecting between the ends.\n */\n #correctPosition(position: number): number {\n const startLightness = this.#colorAt(0, true).toLab().lightness;\n const endLightness = this.#colorAt(1, true).toLab().lightness;\n const isDescending = startLightness > endLightness;\n const idealLightness = startLightness + (endLightness - startLightness) * position;\n\n let low = 0;\n let high = 1;\n let corrected = position;\n let difference = this.#colorAt(corrected, true).toLab().lightness - idealLightness;\n\n for (\n let iteration = 0;\n iteration < MAX_LIGHTNESS_ITERATIONS && Math.abs(difference) > LIGHTNESS_TOLERANCE;\n iteration += 1\n ) {\n // Already lighter than ideal: search the darker half, and vice versa.\n if (isDescending === difference < 0) {\n high = corrected;\n corrected += (low - corrected) / 2;\n } else {\n low = corrected;\n corrected += (high - corrected) / 2;\n }\n difference = this.#colorAt(corrected, true).toLab().lightness - idealLightness;\n }\n\n return corrected;\n }\n\n #interpolateAt(position: number): Color {\n const stops = this.#stops;\n\n for (const [index, stop] of stops.entries()) {\n if (position <= stop.position) {\n return stop.color;\n }\n\n const next = stops[index + 1];\n if (next === undefined) {\n return stop.color;\n }\n\n if (position < next.position) {\n const ratio = (position - stop.position) / (next.position - stop.position);\n return stop.color.blend(next.color, ratio, this.#mode);\n }\n }\n\n return stops[0].color;\n }\n}\n","import type { ColorShape } from './colorContrastRatiosByShape';\nimport type { ColorInput } from './types';\nimport { Color } from './Color';\nimport { colorContrastRatiosByShape } from './colorContrastRatiosByShape';\nimport { preciseContrast } from './private/preciseContrast';\n\nconst WHITE = '#ffffff';\nconst BLACK = '#000000';\n\nexport type BestColorForTextOptions = {\n /** Always excluded from the result.*/\n readonly backgroundColor: ColorInput;\n\n /**\n * Colors that are part of the palette but should not be considered as candidates.\n * Useful in scenarios like the webinar pages color derivation logic, where we might include derived colors\n * in the palette used by some fields, like `lowEmphasisTextColor`, but we want to exclude the derived colors\n * from other fields, like `mainTextColor`.\n */\n readonly exclude?: readonly ColorInput[];\n\n /**\n * The colors to choose from. Black and white are included automatically, so an empty/absent palette\n * still yields whichever of the two has best contrast against `backgroundColor`.\n */\n readonly palette?: readonly ColorInput[];\n\n /** The type of text/shape that will use the resulting color. Defaults to `paragraphText` (4.5:1). */\n readonly shape?: ColorShape;\n};\n\n/**\n * Picks a color most suitable for a given text (or non-text) shape against the given background color.\n * Accepts an optional color palette, but white and black are always included as options in addition to the palette.\n * Also accepts a set of colors from the palette that should be excluded from consideration.\n *\n * @example\n * ```ts\n * getBestColorForText({ backgroundColor: '#2949e5' }).toHex(); // '#ffffff'\n * ```\n */\nexport const getBestColorForText = ({\n backgroundColor,\n exclude = [],\n palette = [],\n shape = 'paragraphText',\n}: BestColorForTextOptions): Color => {\n const background = new Color(backgroundColor);\n const requiredContrast = colorContrastRatiosByShape[shape];\n\n const excluded = new Set(\n // Always exclude the background color in addition to the colorsToExclude\n [...exclude, background]\n .map((color) => new Color(color).toHex())\n // If one of the excluded colors is black or white, don't exclude it.\n // We always need black and white as potential text color options.\n .filter((hex) => hex !== WHITE && hex !== BLACK),\n );\n\n const candidates = [\n ...new Map(\n [WHITE, BLACK, ...palette].map((color) => {\n const candidate = new Color(color);\n return [candidate.toHex(), candidate];\n }),\n ).values(),\n ].filter((color) => !excluded.has(color.toHex()));\n\n const white = new Color(WHITE);\n const black = new Color(BLACK);\n\n // Rank candidates in order of least contrast first, otherwise we would always return either black or white.\n const ranked = candidates\n .map((color) => ({ color, ratio: preciseContrast(color, background) }))\n .toSorted((one, two) => one.ratio - two.ratio);\n\n // Which side of the background text belongs on: light text on a dark background, dark\n // text on a light one. Settled by measuring both extremes rather than by a lightness\n // threshold, so the crossover falls where contrast actually flips, near luminance 0.18.\n //\n // Worth preferring because the WCAG ratio is symmetric and cannot say that dark-on-dark\n // and light-on-dark read differently at the same number. Without this, a background\n // around luminance 0.12 takes black at 3.3:1 — enough to clear largeText, and murky to\n // read — over a light candidate that costs nothing.\n\n // Optically, should the text be lighter or darker than the background?\n const prefersLighterText =\n preciseContrast(white, background) > preciseContrast(black, background);\n const backgroundLuminance = background.luminance();\n const isPreferredSide = (color: Color): boolean =>\n prefersLighterText\n ? color.luminance() >= backgroundLuminance\n : color.luminance() <= backgroundLuminance;\n\n const passing = ranked.filter(({ color }) => color.contrast(background) >= requiredContrast);\n\n // The least-contrasting passing candidate on the preferred side. There is always one\n // when anything passes at all: the preferred side is the one whose extreme contrasts\n // more, and both extremes are always in the pool. So falling through means nothing\n // cleared the ratio, and the most contrast on offer is that same extreme.\n return (\n passing.find(({ color }) => isPreferredSide(color))?.color ??\n (prefersLighterText ? white : black)\n );\n};\n","import type { ColorInput } from './types';\nimport { Color } from './Color';\n\nconst MAX_PAGE_SATURATION = 50;\n\nconst ALMOST_BLACK = 5;\nconst ALMOST_WHITE = 95;\nconst DESIRED_BACKGROUND_LIGHTNESS = 18;\nconst MINIMUM_CONTRAST_BETWEEN_PRIMARY_AND_BACKGROUND = 1.5;\nconst SEARCH_INCREMENT = 0.5;\n\nconst constructColorWithNewSaturationAndLightness = (\n primaryColor: Color,\n saturation: number,\n lightness: number,\n): Color => Color.fromHsl({ hue: primaryColor.toHsl().hue, lightness, saturation }, primaryColor.a);\n\n/**\n * Generates a dark background color from a given primary color, preserving the hue of the primary color.\n *\n * @example\n * ```ts\n * getBrandDarkBackgroundColor('#2949e5').toHex(); // '#242942'\n * ```\n *\n * @see {@link getBrandLightBackgroundColor} for the light counterpart\n */\nexport const getBrandDarkBackgroundColor = (_primaryColor: ColorInput): Color => {\n const primaryColor = new Color(_primaryColor);\n const { lightness: brandLightness, saturation } = primaryColor.toHsl();\n\n // If the color is close to black or white, zero out the saturation so\n // we end up with gray instead of red\n const hasNoUsableHue = brandLightness < ALMOST_BLACK || brandLightness > ALMOST_WHITE;\n const pageSaturation = hasNoUsableHue ? 0 : Math.min(MAX_PAGE_SATURATION, saturation);\n\n const initialBackgroundColorOption = constructColorWithNewSaturationAndLightness(\n primaryColor,\n pageSaturation,\n DESIRED_BACKGROUND_LIGHTNESS,\n );\n\n // If the initial background color option meets our desired contrast, just use it.\n if (\n initialBackgroundColorOption.contrast(primaryColor) >=\n MINIMUM_CONTRAST_BETWEEN_PRIMARY_AND_BACKGROUND\n ) {\n return initialBackgroundColorOption;\n }\n\n // Otherwise if the initial background color option did not have the desired contrast,\n // tweak the lightness until we get a color that does meet the desired contrast.\n // Return black if we run out of options.\n let backgroundColorWithIncreasedContrast = initialBackgroundColorOption;\n for (\n let pageLightness = DESIRED_BACKGROUND_LIGHTNESS;\n pageLightness >= 0;\n pageLightness -= SEARCH_INCREMENT\n ) {\n const candidate = constructColorWithNewSaturationAndLightness(\n primaryColor,\n pageSaturation,\n pageLightness,\n );\n if (\n candidate.contrast(primaryColor) > backgroundColorWithIncreasedContrast.contrast(primaryColor)\n ) {\n backgroundColorWithIncreasedContrast = candidate;\n }\n if (\n backgroundColorWithIncreasedContrast.contrast(primaryColor) >=\n MINIMUM_CONTRAST_BETWEEN_PRIMARY_AND_BACKGROUND\n ) {\n break;\n }\n }\n\n return backgroundColorWithIncreasedContrast;\n};\n","import type { ColorInput } from './types';\nimport { Color } from './Color';\n\n/** Enough saturation for the brand hue to register, for a primary that has barely any. */\nconst MIN_SATURATION = 5;\n\n/** HSL lightness bands where a primary is close enough to an extreme to have no usable hue. */\nconst ALMOST_BLACK = 5;\nconst ALMOST_WHITE = 95;\n\n/**\n *\n * Generates a light background color from a given primary color, preserving the hue of the primary color.\n *\n * @example\n * ```ts\n * getBrandLightBackgroundColor('#2949e5').toHex(); // '#ebeefd'\n * ```\n *\n * @see {@link getBrandDarkBackgroundColor} for the dark counterpart\n */\nexport const getBrandLightBackgroundColor = (_primaryColor: ColorInput): Color => {\n const primaryColor = new Color(_primaryColor);\n const { lightness, saturation } = primaryColor.toHsl();\n\n // If the new color is close to black or white, zero out the saturation so\n // we end up with gray instead of pink\n const hasNoHue = saturation === 0 || lightness < ALMOST_BLACK || lightness > ALMOST_WHITE;\n const targetSaturation = hasNoHue ? 0 : Math.max(MIN_SATURATION, saturation);\n\n // Make the current color *almost* white and then darken it just a bit\n // to get a nice looking light background color based on the primary color\n const derived = primaryColor.tint(0.95, 'rgb').shade(0.02, 'rgb');\n\n return Color.fromHsl({ ...derived.toHsl(), saturation: targetSaturation }, derived.a);\n};\n","import { oklchToRgb, rgbToOklch } from './colorSpace';\n\n/**\n * Below this a color has no perceptible hue.\n */\nexport const ACHROMATIC_CHROMA = 1e-4;\n\n/**\n * More chroma than sRGB holds anywhere. The widest point is magenta at 0.32\n */\nconst UNREACHABLE_CHROMA = 0.5;\n\n/**\n * The most chroma sRGB can hold at the given lightness and hue.\n *\n * Read from {@link oklchToRgb}, which already clamps by max chroma so that we don't have to\n * re-implement searching for max possible chroma.\n */\nexport const maxChroma = (lightness: number, hue: number): number => {\n const [red, green, blue] = oklchToRgb({ chroma: UNREACHABLE_CHROMA, hue, lightness });\n\n return rgbToOklch(red, green, blue).chroma;\n};\n","import type { Color } from '../Color';\n\n/**\n * Flare is the ambient light reflecting off a screen, as defined by WCAG guidelines.\n * See https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum\n */\nconst FLARE = 0.05;\nconst FLOOR = Math.cbrt(FLARE);\nconst SPAN = Math.cbrt(1 + FLARE) - FLOOR;\n\n/**\n * Get the perceived lightness of a color, with ambient lighting factored in according\n * to WCAG guidelines.\n */\nexport const perceivedLightness = (color: Color): number =>\n (Math.cbrt(color.luminance() + FLARE) - FLOOR) / SPAN;\n","import { Color } from '../Color';\nimport { ColorScale } from '../ColorScale';\nimport { getBrandDarkBackgroundColor } from '../getBrandDarkBackgroundColor';\nimport { getBrandLightBackgroundColor } from '../getBrandLightBackgroundColor';\nimport { clamp } from './clamp';\nimport { oklchToRgb, rgbToOklch } from './colorSpace';\nimport { ACHROMATIC_CHROMA, maxChroma } from './maxChroma';\nimport { perceivedLightness } from './perceivedLightness';\n\nexport const DEFAULT_COLOR_SCALE_STEPS = 12;\n\n/**\n * Using the primary color, derive the light/dark variants of the background color,\n * and use these three colors as all the fixed stops on the scale.\n * Including the primary color in addition to the two background extremes allows the scale\n * to maintain the vibrancy of the primary color.\n * Sort stops by luminance, just in case.\n */\nconst brandScaleStops = (primary: Color): Color[] => {\n const stops = [\n getBrandLightBackgroundColor(primary),\n primary,\n getBrandDarkBackgroundColor(primary),\n ];\n\n return stops.toSorted((one, two) => two.luminance() - one.luminance());\n};\n\nconst ARC_SAMPLES = 128;\n\nconst DEGREES_TO_RADIANS = Math.PI / 180;\n\n/**\n * How far apart two colors look: perceived lightness versus OKLab's chroma.\n *\n * We use perceptual distance rather than a lightness calculation because the color scale\n * can cover a lot of ground without changing lightness significantly. Between an almost white color\n * and a light yellow there is not much lightness difference, but there is actually enough\n * \"distance\" between the colors to perceive more than one step between them.\n *\n * Contrast ratio does not matter significantly here because these are background colors.\n */\nconst perceptualDistance = (one: Color, two: Color): number => {\n const from = rgbToOklch(one.r, one.g, one.b);\n const to = rgbToOklch(two.r, two.g, two.b);\n\n return Math.hypot(\n perceivedLightness(one) - perceivedLightness(two),\n from.chroma * Math.cos(from.hue * DEGREES_TO_RADIANS) -\n to.chroma * Math.cos(to.hue * DEGREES_TO_RADIANS),\n from.chroma * Math.sin(from.hue * DEGREES_TO_RADIANS) -\n to.chroma * Math.sin(to.hue * DEGREES_TO_RADIANS),\n );\n};\n\n/**\n * Maps between a position on the scale and how far along its length that position sits.\n */\nconst arcLength = (colorAt: (position: number) => Color) => {\n const points = Array.from({ length: ARC_SAMPLES + 1 }, (_, index) =>\n colorAt(index / ARC_SAMPLES),\n );\n const travelled = [0];\n for (let index = 1; index <= ARC_SAMPLES; index += 1) {\n const from = points[index - 1];\n const to = points[index];\n const step = from === undefined || to === undefined ? 0 : perceptualDistance(from, to);\n\n travelled.push((travelled[index - 1] ?? 0) + step);\n }\n const total = travelled.at(-1) ?? 0;\n\n return {\n distanceOf: (position: number): number => {\n if (total === 0) {\n return position;\n }\n const scaled = clamp(position, 0, 1) * ARC_SAMPLES;\n const lower = Math.min(Math.floor(scaled), ARC_SAMPLES - 1);\n const within = scaled - lower;\n const from = travelled[lower] ?? 0;\n const to = travelled[lower + 1] ?? total;\n\n return (from + (to - from) * within) / total;\n },\n positionAt: (distance: number): number => {\n if (total === 0) {\n return distance;\n }\n const target = clamp(distance, 0, 1) * total;\n for (let index = 1; index <= ARC_SAMPLES; index += 1) {\n const to = travelled[index] ?? total;\n if (to >= target) {\n const from = travelled[index - 1] ?? 0;\n const span = to - from;\n\n return (index - 1 + (span === 0 ? 0 : (target - from) / span)) / ARC_SAMPLES;\n }\n }\n\n return 1;\n },\n };\n};\n\nexport type BrandScaleOptions = {\n /** How many steps the scale is divided into. */\n readonly steps?: number;\n};\n\n// Where `color` falls on the color scale, as a position from 0–1.\nexport const positionOnScale = (scale: ColorScale, color: Color): number => {\n const target = color.luminance();\n let low = 0;\n let high = 1;\n\n for (let iteration = 0; iteration < 30; iteration += 1) {\n const middle = (low + high) / 2;\n if (scale.at(middle).luminance() > target) {\n low = middle;\n } else {\n high = middle;\n }\n }\n\n return (low + high) / 2;\n};\n\n/**\n * How colorful a color is as a share of the most sRGB allows at its lightness and hue.\n * 0 for a gray, 1 for a color that maxes out lightness/saturation.\n */\nconst gamutFraction = (color: Color): number => {\n const { chroma, hue, lightness } = rgbToOklch(color.r, color.g, color.b);\n const available = maxChroma(lightness, hue);\n\n return chroma < ACHROMATIC_CHROMA || available < ACHROMATIC_CHROMA\n ? 0\n : Math.min(1, chroma / available);\n};\n\ntype Anchor = {\n readonly fraction: number;\n readonly position: number;\n};\n\n/**\n * What fraction of the color gamut is represented by a given position\n */\nconst fractionAt = (anchors: readonly Anchor[], position: number): number => {\n const first = anchors.at(0);\n const last = anchors.at(-1);\n if (first === undefined || last === undefined) {\n return 0;\n }\n if (position <= first.position) {\n return first.fraction;\n }\n\n for (let index = 1; index < anchors.length; index += 1) {\n const previous = anchors[index - 1];\n const next = anchors[index];\n if (previous === undefined || next === undefined) {\n break;\n }\n if (position <= next.position) {\n const span = next.position - previous.position;\n const ratio = span === 0 ? 0 : (position - previous.position) / span;\n\n return previous.fraction + (next.fraction - previous.fraction) * ratio;\n }\n }\n\n return last.fraction;\n};\n\nexport type BrandedColorScale = {\n /** The color at a given position (0 - 1), from the scale. */\n readonly at: (position: number) => Color;\n /** The color at step `index` */\n readonly atStep: (index: number) => Color;\n readonly positionOf: (color: Color) => number;\n /** The step where the primary color falls. */\n readonly primaryStep: number;\n /** Where a given color falls, as a step index — fractional when it sits between two. */\n readonly stepOf: (color: Color) => number;\n readonly steps: number;\n};\n\n/**\n * Builds a color scale using the derived light/dark background colors based on the given primary color,\n * with the primary color slotted into the scale wherever it fits based on lightness.\n *\n * It's important to include the primary color in the scale because the light/dark derived background colors\n * do not have the same saturation as the primary color, and we want the scale to reflect the vibrancy\n * of the primary color.\n */\nexport const buildBrandedColorScale = (\n primary: Color,\n options: BrandScaleOptions = {},\n): BrandedColorScale => {\n const { steps = DEFAULT_COLOR_SCALE_STEPS } = options;\n const scale = new ColorScale(brandScaleStops(primary), { mode: 'oklch' });\n const stops = brandScaleStops(primary);\n const anchors = stops\n .map((stop) => ({ fraction: gamutFraction(stop), position: positionOnScale(scale, stop) }))\n .toSorted((one, two) => one.position - two.position);\n\n const colorAt = (position: number): Color => {\n const base = scale.at(position);\n const { hue, lightness } = rgbToOklch(base.r, base.g, base.b);\n const [red, green, blue] = oklchToRgb({\n chroma: fractionAt(anchors, position) * maxChroma(lightness, hue),\n hue,\n lightness,\n });\n\n return new Color([red, green, blue, base.a]);\n };\n\n const measured = arcLength(colorAt);\n\n const at = (distance: number): Color => colorAt(measured.positionAt(distance));\n const distanceOf = (color: Color): number => measured.distanceOf(positionOnScale(scale, color));\n\n const last = Math.max(0, steps - 1);\n const primaryDistance = distanceOf(primary);\n\n // The primary step should almost never be placed into either end of the scale.\n // This will only occur for primary colors that are truly extreme, like black or white.\n const ownsFirst = stops.at(0)?.toHex() === primary.toHex();\n const ownsLast = stops.at(-1)?.toHex() === primary.toHex();\n const lowest = ownsFirst ? 0 : Math.min(1, last);\n const highest = ownsLast ? last : Math.max(lowest, last - 1);\n const primaryStep = clamp(Math.round(primaryDistance * last), lowest, highest);\n\n const distanceOfStep = (index: number): number => {\n if (index === primaryStep) {\n return primaryDistance;\n }\n if (index < primaryStep) {\n return (index / primaryStep) * primaryDistance;\n }\n\n return primaryDistance + ((index - primaryStep) / (last - primaryStep)) * (1 - primaryDistance);\n };\n\n return {\n at,\n atStep: (index) => (index === primaryStep ? primary : at(distanceOfStep(index))),\n positionOf: distanceOf,\n primaryStep,\n stepOf: (color) => {\n const found = distanceOf(color);\n if (found <= primaryDistance) {\n return primaryDistance === 0 ? 0 : (found / primaryDistance) * primaryStep;\n }\n\n return (\n primaryStep + ((found - primaryDistance) / (1 - primaryDistance)) * (last - primaryStep)\n );\n },\n steps,\n };\n};\n","import type { ColorInput } from './types';\nimport { Color } from './Color';\nimport {\n buildBrandedColorScale,\n DEFAULT_COLOR_SCALE_STEPS,\n} from './private/buildBrandedColorScale';\n\nexport type BrandColorScaleOptions = {\n /** How many steps the scale is divided into. */\n readonly steps?: number;\n};\n\n/**\n * Builds a color scale using the derived light/dark background colors based on the given primary color,\n * with the primary color slotted into the scale wherever it fits based on lightness.\n *\n * It's important to include the primary color in the scale because the light/dark derived background colors\n * do not have the same saturation as the primary color, and we want the scale to reflect the vibrancy\n * of the primary color.\n *\n * @example\n * ```ts\n * getBrandedColorScale('#2949e5').map((color) => color.toHex());\n * // ['#ebeefd', '#d4dbfa', '#bdc8f7', '#a5b5f4', '#8da2f1', '#748eef',\n * // '#5b7aec', '#4263e8', '#2949e5', '#2539ba', '#213080', '#171f45']\n * // ^ the primary, at its own lightness\n * ```\n */\nexport const getBrandedColorScale = (\n primaryColor: ColorInput,\n { steps = DEFAULT_COLOR_SCALE_STEPS }: BrandColorScaleOptions = {},\n): Color[] => {\n const scale = buildBrandedColorScale(new Color(primaryColor), { steps });\n\n return Array.from({ length: steps }, (_, index) => scale.atStep(index));\n};\n","import type { ColorInput } from './types';\nimport { Color } from './Color';\n\nexport type ColorLightnessClassification = 'dark' | 'light' | 'midtone' | 'veryDark';\n\n/**\n * The WCAG value for typical ambient light causing flare on a screen\n * https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum\n */\nconst FLARE = 0.05;\n\n/**\n * Below this a background is close enough to black that there is no more visual\n * room to darken the color without reading as black.\n */\nconst VERY_DARK_MAX = 0.05;\n\n/**\n * This number represents the crossover where white stops having more contrast than black,\n * so any values with luminance greater than this value are no longer considered \"dark\".\n *\n * Don't round this number, otherwise we'll potentially classify some backgrounds as \"midtone\"\n * even though light content reads better on them, and we should always have light content on dark backgrounds.\n */\nconst DARK_MAX = Math.sqrt(FLARE * (1 + FLARE)) - FLARE;\n\n/** Above this a background is close enough to white that it needs no lightening at all. */\nconst LIGHT_MIN = 0.8;\n\n/**\n * Classify a color's lightness based on relative luminance.\n *\n * @example\n * ```ts\n * getColorLightnessClassification('#000000'); // 'veryDark'\n * getColorLightnessClassification('#2949e5'); // 'dark'\n * getColorLightnessClassification('#7f7f7f'); // 'midtone'\n * getColorLightnessClassification('#ffffff'); // 'light'\n * ```\n */\nexport const getColorLightnessClassification = (\n color: ColorInput,\n): ColorLightnessClassification => {\n const parsed = new Color(color);\n const luminance = parsed.luminance();\n\n if (luminance < VERY_DARK_MAX) {\n return 'veryDark';\n }\n if (luminance < DARK_MAX) {\n return 'dark';\n }\n\n return luminance < LIGHT_MIN ? 'midtone' : 'light';\n};\n","import type { getBackgroundAccentFromPrimaryColor } from './getBackgroundAccentFromPrimaryColor';\nimport { Color } from '../Color';\nimport { getColorLightnessClassification } from '../getColorLightnessClassification';\nimport { DEFAULT_COLOR_SCALE_STEPS } from './buildBrandedColorScale';\nimport { clamp } from './clamp';\nimport { oklchToRgb, rgbToOklch } from './colorSpace';\nimport { ACHROMATIC_CHROMA, maxChroma } from './maxChroma';\nimport { perceivedLightness } from './perceivedLightness';\n\n/**\n * Get the total distance between the lightest and darkest page background colors, measured in lightness.\n * This determines the actual step size we'll use, which correlates to the size of the step between colors\n * in a branded color scale.\n */\nconst MAX_BACKGROUND_LIGHTNESS = 0.95;\nconst MIN_BACKGROUND_LIGHTNESS = 0.09;\nconst STEP_SIZE_IN_LIGHTNESS =\n (MAX_BACKGROUND_LIGHTNESS - MIN_BACKGROUND_LIGHTNESS) / (DEFAULT_COLOR_SCALE_STEPS - 1);\n\n/**\n * Move the background color by the given distance to generate an accented background color.\n * This is used when no primary color has been provided, meaning the background color was not derived from the primary color.\n * The size of the steps used by this utility should match the size of the steps used in the\n * corresponding {@link getBackgroundAccentFromPrimaryColor} utility.\n */\nexport const getAccentedBackgroundByLightness = (\n backgroundColor: Color,\n distanceInSteps: number,\n): Color => {\n const { chroma, hue, lightness } = rgbToOklch(\n backgroundColor.r,\n backgroundColor.g,\n backgroundColor.b,\n );\n const maxPossibleChroma = maxChroma(lightness, hue);\n\n // If there is no perceptible chroma for this color or for the max possible chroma for this hue/lightness,\n // don't try to add any chroma into the result.\n const share =\n chroma < ACHROMATIC_CHROMA || maxPossibleChroma < ACHROMATIC_CHROMA\n ? 0\n : Math.min(1, chroma / maxPossibleChroma);\n\n const atLightness = (candidate: number): Color => {\n const [red, green, blue] = oklchToRgb({\n chroma: share * maxChroma(candidate, hue),\n hue,\n lightness: candidate,\n });\n\n return new Color([red, green, blue, backgroundColor.a]);\n };\n\n const band = getColorLightnessClassification(backgroundColor);\n const towards = band === 'dark' || band === 'veryDark' ? 1 : -1;\n const target = clamp(\n perceivedLightness(backgroundColor) + towards * distanceInSteps * STEP_SIZE_IN_LIGHTNESS,\n 0,\n 1,\n );\n\n let low = 0;\n let high = 1;\n for (let iteration = 0; iteration < 30; iteration += 1) {\n const middle = (low + high) / 2;\n if (perceivedLightness(atLightness(middle)) < target) {\n low = middle;\n } else {\n high = middle;\n }\n }\n\n return atLightness((low + high) / 2);\n};\n","import type { Color } from '../Color';\nimport { getColorLightnessClassification } from '../getColorLightnessClassification';\nimport { buildBrandedColorScale } from './buildBrandedColorScale';\nimport { clamp } from './clamp';\n\n/**\n * Using a branded color scale based on the primary color,\n * move the given background color by the given distance along the scale\n * to generate an accented version of the background color.\n */\nexport const getBackgroundAccentFromPrimaryColor = (\n backgroundColor: Color,\n stepDistance: number,\n primaryColor: Color,\n): Color => {\n const scale = buildBrandedColorScale(primaryColor);\n const last = scale.steps - 1;\n const colorLightnessClass = getColorLightnessClassification(backgroundColor);\n const towards =\n colorLightnessClass === 'dark' || colorLightnessClass === 'veryDark'\n ? -stepDistance\n : stepDistance;\n const from = clamp(Math.round(scale.stepOf(backgroundColor)), 0, last);\n\n return scale.atStep(clamp(from + towards, 0, last));\n};\n","import type { Color } from '../Color';\nimport { getAccentedBackgroundByLightness } from './getAccentedBackgroundByLightness';\nimport { getBackgroundAccentFromPrimaryColor } from './getBackgroundAccentFromPrimaryColor';\n\ntype AccentedBackgroundOptions = {\n readonly backgroundColor: Color;\n readonly primaryColor?: Color | undefined;\n readonly stepDistance: number;\n};\n\n/**\n * A background `distance` steps off `background`, always in the direction away from it:\n * darker when the background is light, lighter when it is dark.\n *\n * Gets a an accented color spaced apart from the given background color by the given distance.\n * If a primary color is included, we will derive the accent color using a color scale.\n */\nexport const getAccentedBackground = ({\n backgroundColor,\n stepDistance,\n primaryColor,\n}: AccentedBackgroundOptions): Color =>\n primaryColor === undefined\n ? getAccentedBackgroundByLightness(backgroundColor, stepDistance)\n : getBackgroundAccentFromPrimaryColor(backgroundColor, stepDistance, primaryColor);\n","import type { getBrandedColorScale } from './getBrandedColorScale';\nimport type { getSlightAccentedBackgroundColor } from './getSlightAccentedBackgroundColor';\nimport type { ColorInput } from './types';\nimport { Color } from './Color';\nimport { getAccentedBackground } from './private/getAccentedBackground';\n\nexport type HeavyAccentedBackgroundColorOptions = {\n readonly primaryColor?: ColorInput;\n};\n\n/**\n * Get an accented version of a background color that is a two steps lighter/darker.\n * Use this when the color contrast of the accented background color is not significant,\n * such as for card/panel background colors.\n * \n * Accepts an optional primary color, used when the background color has been derived from the primary color,\n * and we want the accented versions of the background color to come from the color scale, see {@link getBrandedColorScale}\n\n * See {@link getSlightAccentedBackgroundColor} for a single step away from the background color instead of two.\n\n *\n * @example\n * ```ts\n * getHeavyAccentedBackgroundColor('#f5f5f5').toHex(); // '#cbcbcb'\n * getHeavyAccentedBackgroundColor('#f5f5f5', { primaryColor: '#2949e5' }).toHex(); // '#adbbf5'\n * ```\n */\nexport const getHeavyAccentedBackgroundColor = (\n _backgroundColor: ColorInput,\n { primaryColor }: HeavyAccentedBackgroundColorOptions = {},\n): Color => {\n const backgroundColor = new Color(_backgroundColor);\n\n return getAccentedBackground({\n backgroundColor,\n stepDistance: 2,\n primaryColor: primaryColor === undefined ? undefined : new Color(primaryColor),\n });\n};\n","import type { getBrandedColorScale } from './getBrandedColorScale';\nimport type { getHeavyAccentedBackgroundColor } from './getHeavyAccentedBackgroundColor';\nimport type { ColorInput } from './types';\nimport { Color } from './Color';\nimport { getAccentedBackground } from './private/getAccentedBackground';\n\nconst WHITE = '#ffffff';\n\nexport type SlightAccentedBackgroundColorOptions = {\n readonly shouldReturnWhiteForWhiteBackground?: boolean;\n /**\n * Optional primary color, which is used when the background color is derived from the primary color,\n * so we'll calculate the accented background color using a color scale.\n */\n readonly primaryColor?: ColorInput;\n};\n\n/**\n * Get an accented version of a background color that is a single step lighter/darker.\n * Use this when the color contrast of the accented background color is not significant,\n * such as for card/panel background colors.\n * \n * Accepts an optional primary color, used when the background color has been derived from the primary color,\n * and we want the accented versions of the background color to come from the color scale, see {@link getBrandedColorScale}\n\n * See {@link getHeavyAccentedBackgroundColor} for two steps away from the background color instead of one.\n *\n * @example\n * ```ts\n * getSlightAccentedBackgroundColor('#f5f5f5').toHex(); // '#e0e0e0'\n * getSlightAccentedBackgroundColor('#f5f5f5', { primaryColor: '#2949e5' }).toHex(); // '#cdd5f9'\n * getSlightAccentedBackgroundColor('#ffffff', { shouldReturnWhiteForWhiteBackground: true }).toHex(); // '#ffffff'\n * ```\n */\nexport const getSlightAccentedBackgroundColor = (\n _backgroundColor: ColorInput,\n {\n shouldReturnWhiteForWhiteBackground = false,\n primaryColor,\n }: SlightAccentedBackgroundColorOptions = {},\n): Color => {\n const backgroundColor = new Color(_backgroundColor);\n\n if (shouldReturnWhiteForWhiteBackground && backgroundColor.toHex() === WHITE) {\n return backgroundColor;\n }\n\n return getAccentedBackground({\n backgroundColor,\n stepDistance: 1,\n primaryColor: primaryColor === undefined ? undefined : new Color(primaryColor),\n });\n};\n"],"mappings":"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"}
@@ -1,11 +1,11 @@
1
1
 
2
2
  /*
3
- * @license @wistia/kaleidoscope v0.0.3-beta.744e55dd.c7dc7eb
3
+ * @license @wistia/kaleidoscope v0.0.3
4
4
  *
5
5
  * Copyright (c) 2026, Wistia, Inc. and its affiliates.
6
6
  *
7
7
  * This source code is unlicensed, all rights reserved.
8
8
  */
9
9
 
10
- import { a as getBrandLightBackgroundColor, c as ColorScale, d as Color, i as getBrandedColorScale, l as adjustColorForProperContrast, n as getHeavyAccentedBackgroundColor, o as getBrandDarkBackgroundColor, r as getColorLightnessClassification, s as getBestColorForText, t as getSlightAccentedBackgroundColor, u as colorContrastRatiosByShape } from "../color-K4N47FR5.js";
10
+ import { a as getBrandLightBackgroundColor, c as ColorScale, d as Color, i as getBrandedColorScale, l as adjustColorForProperContrast, n as getHeavyAccentedBackgroundColor, o as getBrandDarkBackgroundColor, r as getColorLightnessClassification, s as getBestColorForText, t as getSlightAccentedBackgroundColor, u as colorContrastRatiosByShape } from "../color-bUFJKFtM.js";
11
11
  export { Color, ColorScale, adjustColorForProperContrast, colorContrastRatiosByShape, getBestColorForText, getBrandDarkBackgroundColor, getBrandLightBackgroundColor, getBrandedColorScale, getColorLightnessClassification, getHeavyAccentedBackgroundColor, getSlightAccentedBackgroundColor };
@@ -1,11 +1,11 @@
1
1
 
2
2
  /*
3
- * @license @wistia/kaleidoscope v0.0.3-beta.744e55dd.c7dc7eb
3
+ * @license @wistia/kaleidoscope v0.0.3
4
4
  *
5
5
  * Copyright (c) 2026, Wistia, Inc. and its affiliates.
6
6
  *
7
7
  * This source code is unlicensed, all rights reserved.
8
8
  */
9
9
 
10
- import { A as GENERIC_FONT_FAMILIES, C as ELEVATION_HARDNESSES, D as OFFSET_ORIGINS, E as INVERT_RULES, F as COLOR_ANCHOR_NAMES, I as OPTIONAL_COLOR_ANCHORS, L as REQUIRED_COLOR_ANCHORS, M as ANCHORS_REQUIRED_BY_TREATMENT, N as ANCHOR_GROUPS, O as COLOR_RELATIONSHIPS, P as ANCHOR_REF_PREFIX, R as REQUIRED_DIMENSION_ANCHORS, S as ELEVATION_DEPTHS, T as ORNAMENTAL_BORDER_STYLES, _ as GRADIENT_POSITIONS, a as TEXTURE_INTENSITIES, b as MIN_GRADIENT_STOPS, c as OPTIONAL_SETTING_NAMES, d as SURFACE_NAMES, f as AMBIENT_MOTIONS, g as GRADIENT_EXTENTS, h as GRADIENT_DIRECTIONS, i as TREATMENTS, j as MAX_COLOR_SCALE_OFFSET, k as COLOR_TONES, l as REQUIRED_SETTING_NAMES, m as TRANSITIONS, n as TYPE_CASES, o as TEXTURE_KINDS, p as MOTION_SPEEDS, r as TYPE_ROLES, s as ALL_SETTING_NAMES, t as DOCUMENT_KEYS, u as STACKABLE_ON, v as GRADIENT_SHAPE_OPTIONS, w as BORDER_STYLES, x as ELEVATION_COLOR_SOURCE_KEYWORDS, y as MAX_GRADIENT_STOPS, z as REQUIRED_FONT_ANCHORS } from "../vocabulary-CsAxpvD3.js";
10
+ import { A as GENERIC_FONT_FAMILIES, C as ELEVATION_HARDNESSES, D as OFFSET_ORIGINS, E as INVERT_RULES, F as COLOR_ANCHOR_NAMES, I as OPTIONAL_COLOR_ANCHORS, L as REQUIRED_COLOR_ANCHORS, M as ANCHORS_REQUIRED_BY_TREATMENT, N as ANCHOR_GROUPS, O as COLOR_RELATIONSHIPS, P as ANCHOR_REF_PREFIX, R as REQUIRED_DIMENSION_ANCHORS, S as ELEVATION_DEPTHS, T as ORNAMENTAL_BORDER_STYLES, _ as GRADIENT_POSITIONS, a as TEXTURE_INTENSITIES, b as MIN_GRADIENT_STOPS, c as OPTIONAL_SETTING_NAMES, d as SURFACE_NAMES, f as AMBIENT_MOTIONS, g as GRADIENT_EXTENTS, h as GRADIENT_DIRECTIONS, i as TREATMENTS, j as MAX_COLOR_SCALE_OFFSET, k as COLOR_TONES, l as REQUIRED_SETTING_NAMES, m as TRANSITIONS, n as TYPE_CASES, o as TEXTURE_KINDS, p as MOTION_SPEEDS, r as TYPE_ROLES, s as ALL_SETTING_NAMES, t as DOCUMENT_KEYS, u as STACKABLE_ON, v as GRADIENT_SHAPE_OPTIONS, w as BORDER_STYLES, x as ELEVATION_COLOR_SOURCE_KEYWORDS, y as MAX_GRADIENT_STOPS, z as REQUIRED_FONT_ANCHORS } from "../vocabulary-CpT99K6y.js";
11
11
  export { ALL_SETTING_NAMES, AMBIENT_MOTIONS, ANCHORS_REQUIRED_BY_TREATMENT, ANCHOR_GROUPS, ANCHOR_REF_PREFIX, BORDER_STYLES, COLOR_ANCHOR_NAMES, COLOR_RELATIONSHIPS, COLOR_TONES, DOCUMENT_KEYS, ELEVATION_COLOR_SOURCE_KEYWORDS, ELEVATION_DEPTHS, ELEVATION_HARDNESSES, GENERIC_FONT_FAMILIES, GRADIENT_DIRECTIONS, GRADIENT_EXTENTS, GRADIENT_POSITIONS, GRADIENT_SHAPE_OPTIONS, INVERT_RULES, MAX_COLOR_SCALE_OFFSET, MAX_GRADIENT_STOPS, MIN_GRADIENT_STOPS, MOTION_SPEEDS, OFFSET_ORIGINS, OPTIONAL_COLOR_ANCHORS, OPTIONAL_SETTING_NAMES, ORNAMENTAL_BORDER_STYLES, REQUIRED_COLOR_ANCHORS, REQUIRED_DIMENSION_ANCHORS, REQUIRED_FONT_ANCHORS, REQUIRED_SETTING_NAMES, STACKABLE_ON, SURFACE_NAMES, TEXTURE_INTENSITIES, TEXTURE_KINDS, TRANSITIONS, TREATMENTS, TYPE_CASES, TYPE_ROLES };
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
 
2
2
  /*
3
- * @license @wistia/kaleidoscope v0.0.3-beta.744e55dd.c7dc7eb
3
+ * @license @wistia/kaleidoscope v0.0.3
4
4
  *
5
5
  * Copyright (c) 2026, Wistia, Inc. and its affiliates.
6
6
  *
7
7
  * This source code is unlicensed, all rights reserved.
8
8
  */
9
9
 
10
- import { a as getBrandLightBackgroundColor, c as ColorScale, d as Color, i as getBrandedColorScale, l as adjustColorForProperContrast, n as getHeavyAccentedBackgroundColor, o as getBrandDarkBackgroundColor, r as getColorLightnessClassification, s as getBestColorForText, t as getSlightAccentedBackgroundColor, u as colorContrastRatiosByShape } from "./color-K4N47FR5.js";
11
- import { A as GENERIC_FONT_FAMILIES, C as ELEVATION_HARDNESSES, D as OFFSET_ORIGINS, E as INVERT_RULES, F as COLOR_ANCHOR_NAMES, I as OPTIONAL_COLOR_ANCHORS, L as REQUIRED_COLOR_ANCHORS, M as ANCHORS_REQUIRED_BY_TREATMENT, N as ANCHOR_GROUPS, O as COLOR_RELATIONSHIPS, P as ANCHOR_REF_PREFIX, R as REQUIRED_DIMENSION_ANCHORS, S as ELEVATION_DEPTHS, T as ORNAMENTAL_BORDER_STYLES, _ as GRADIENT_POSITIONS, a as TEXTURE_INTENSITIES, b as MIN_GRADIENT_STOPS, c as OPTIONAL_SETTING_NAMES, d as SURFACE_NAMES, f as AMBIENT_MOTIONS, g as GRADIENT_EXTENTS, h as GRADIENT_DIRECTIONS, i as TREATMENTS, j as MAX_COLOR_SCALE_OFFSET, k as COLOR_TONES, l as REQUIRED_SETTING_NAMES, m as TRANSITIONS, n as TYPE_CASES, o as TEXTURE_KINDS, p as MOTION_SPEEDS, r as TYPE_ROLES, s as ALL_SETTING_NAMES, t as DOCUMENT_KEYS, u as STACKABLE_ON, v as GRADIENT_SHAPE_OPTIONS, w as BORDER_STYLES, x as ELEVATION_COLOR_SOURCE_KEYWORDS, y as MAX_GRADIENT_STOPS, z as REQUIRED_FONT_ANCHORS } from "./vocabulary-CsAxpvD3.js";
10
+ import { a as getBrandLightBackgroundColor, c as ColorScale, d as Color, i as getBrandedColorScale, l as adjustColorForProperContrast, n as getHeavyAccentedBackgroundColor, o as getBrandDarkBackgroundColor, r as getColorLightnessClassification, s as getBestColorForText, t as getSlightAccentedBackgroundColor, u as colorContrastRatiosByShape } from "./color-bUFJKFtM.js";
11
+ import { A as GENERIC_FONT_FAMILIES, C as ELEVATION_HARDNESSES, D as OFFSET_ORIGINS, E as INVERT_RULES, F as COLOR_ANCHOR_NAMES, I as OPTIONAL_COLOR_ANCHORS, L as REQUIRED_COLOR_ANCHORS, M as ANCHORS_REQUIRED_BY_TREATMENT, N as ANCHOR_GROUPS, O as COLOR_RELATIONSHIPS, P as ANCHOR_REF_PREFIX, R as REQUIRED_DIMENSION_ANCHORS, S as ELEVATION_DEPTHS, T as ORNAMENTAL_BORDER_STYLES, _ as GRADIENT_POSITIONS, a as TEXTURE_INTENSITIES, b as MIN_GRADIENT_STOPS, c as OPTIONAL_SETTING_NAMES, d as SURFACE_NAMES, f as AMBIENT_MOTIONS, g as GRADIENT_EXTENTS, h as GRADIENT_DIRECTIONS, i as TREATMENTS, j as MAX_COLOR_SCALE_OFFSET, k as COLOR_TONES, l as REQUIRED_SETTING_NAMES, m as TRANSITIONS, n as TYPE_CASES, o as TEXTURE_KINDS, p as MOTION_SPEEDS, r as TYPE_ROLES, s as ALL_SETTING_NAMES, t as DOCUMENT_KEYS, u as STACKABLE_ON, v as GRADIENT_SHAPE_OPTIONS, w as BORDER_STYLES, x as ELEVATION_COLOR_SOURCE_KEYWORDS, y as MAX_GRADIENT_STOPS, z as REQUIRED_FONT_ANCHORS } from "./vocabulary-CpT99K6y.js";
12
12
  export { ALL_SETTING_NAMES, AMBIENT_MOTIONS, ANCHORS_REQUIRED_BY_TREATMENT, ANCHOR_GROUPS, ANCHOR_REF_PREFIX, BORDER_STYLES, COLOR_ANCHOR_NAMES, COLOR_RELATIONSHIPS, COLOR_TONES, Color, ColorScale, DOCUMENT_KEYS, ELEVATION_COLOR_SOURCE_KEYWORDS, ELEVATION_DEPTHS, ELEVATION_HARDNESSES, GENERIC_FONT_FAMILIES, GRADIENT_DIRECTIONS, GRADIENT_EXTENTS, GRADIENT_POSITIONS, GRADIENT_SHAPE_OPTIONS, INVERT_RULES, MAX_COLOR_SCALE_OFFSET, MAX_GRADIENT_STOPS, MIN_GRADIENT_STOPS, MOTION_SPEEDS, OFFSET_ORIGINS, OPTIONAL_COLOR_ANCHORS, OPTIONAL_SETTING_NAMES, ORNAMENTAL_BORDER_STYLES, REQUIRED_COLOR_ANCHORS, REQUIRED_DIMENSION_ANCHORS, REQUIRED_FONT_ANCHORS, REQUIRED_SETTING_NAMES, STACKABLE_ON, SURFACE_NAMES, TEXTURE_INTENSITIES, TEXTURE_KINDS, TRANSITIONS, TREATMENTS, TYPE_CASES, TYPE_ROLES, adjustColorForProperContrast, colorContrastRatiosByShape, getBestColorForText, getBrandDarkBackgroundColor, getBrandLightBackgroundColor, getBrandedColorScale, getColorLightnessClassification, getHeavyAccentedBackgroundColor, getSlightAccentedBackgroundColor };
@@ -1,6 +1,6 @@
1
1
 
2
2
  /*
3
- * @license @wistia/kaleidoscope v0.0.3-beta.744e55dd.c7dc7eb
3
+ * @license @wistia/kaleidoscope v0.0.3
4
4
  *
5
5
  * Copyright (c) 2026, Wistia, Inc. and its affiliates.
6
6
  *
@@ -273,4 +273,4 @@ const DOCUMENT_KEYS = [
273
273
  //#endregion
274
274
  export { GENERIC_FONT_FAMILIES as A, ELEVATION_HARDNESSES as C, OFFSET_ORIGINS as D, INVERT_RULES as E, COLOR_ANCHOR_NAMES as F, OPTIONAL_COLOR_ANCHORS as I, REQUIRED_COLOR_ANCHORS as L, ANCHORS_REQUIRED_BY_TREATMENT as M, ANCHOR_GROUPS as N, COLOR_RELATIONSHIPS as O, ANCHOR_REF_PREFIX as P, REQUIRED_DIMENSION_ANCHORS as R, ELEVATION_DEPTHS as S, ORNAMENTAL_BORDER_STYLES as T, GRADIENT_POSITIONS as _, TEXTURE_INTENSITIES as a, MIN_GRADIENT_STOPS as b, OPTIONAL_SETTING_NAMES as c, SURFACE_NAMES as d, AMBIENT_MOTIONS as f, GRADIENT_EXTENTS as g, GRADIENT_DIRECTIONS as h, TREATMENTS as i, MAX_COLOR_SCALE_OFFSET as j, COLOR_TONES as k, REQUIRED_SETTING_NAMES as l, TRANSITIONS as m, TYPE_CASES as n, TEXTURE_KINDS as o, MOTION_SPEEDS as p, TYPE_ROLES as r, ALL_SETTING_NAMES as s, DOCUMENT_KEYS as t, STACKABLE_ON as u, GRADIENT_SHAPE_OPTIONS as v, BORDER_STYLES as w, ELEVATION_COLOR_SOURCE_KEYWORDS as x, MAX_GRADIENT_STOPS as y, REQUIRED_FONT_ANCHORS as z };
275
275
 
276
- //# sourceMappingURL=vocabulary-CsAxpvD3.js.map
276
+ //# sourceMappingURL=vocabulary-CpT99K6y.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"vocabulary-CsAxpvD3.js","names":[],"sources":["../src/styleVocabulary/anchors.ts","../src/styleVocabulary/anchorValues.ts","../src/styleVocabulary/backgroundColor.ts","../src/styleVocabulary/border.ts","../src/styleVocabulary/elevation.ts","../src/styleVocabulary/gradientShape.ts","../src/styleVocabulary/motion.ts","../src/styleVocabulary/surfaces.ts","../src/styleVocabulary/texture.ts","../src/styleVocabulary/treatment.ts","../src/styleVocabulary/typography.ts","../src/styleVocabulary/index.ts"],"sourcesContent":["import type { Dimension, FontStack, SingleColor, BrandKitTokenRef } from './anchorValues';\nimport type { GradientStops } from './gradientShape';\nimport type { Treatment } from './treatment';\n\nexport const ANCHOR_GROUPS = ['dimensions', 'colors', 'fonts'] as const;\nexport type AnchorGroup = (typeof ANCHOR_GROUPS)[number];\n\n/**\n * Like the required color and font anchors, the required dimension anchors map up to Brand Kit\n * options. A Style may hard-code one instead: Glass does, because the glass effect needs\n * generous rounding.\n */\nexport const REQUIRED_DIMENSION_ANCHORS = ['borderRadius'] as const;\nexport type RequiredDimensionAnchor = (typeof REQUIRED_DIMENSION_ANCHORS)[number];\n\nexport const COLOR_ANCHOR_NAMES = ['pageBackground', 'primary', 'ground', 'gradientStops'] as const;\nexport type ColorAnchorName = (typeof COLOR_ANCHOR_NAMES)[number];\n\n/**\n * The required color anchors should correlate to whatever Brand Kit tokens exist,\n * currently pageBackgroundColor and primaryColor.\n * If an accentColor is supported in the future, we'll add it here.\n */\nexport const REQUIRED_COLOR_ANCHORS = ['pageBackground', 'primary'] as const;\nexport type RequiredColorAnchor = (typeof REQUIRED_COLOR_ANCHORS)[number];\n\n/**\n * These colors are optional, based on which Style and/or treatment is applied to a surface.\n * Glass styles use the ground color as the background for the glass effect: dark or light.\n * The aurora styles use the ground color as a hard-coded value for the backgrounds of cards and panels.\n */\nexport const OPTIONAL_COLOR_ANCHORS = ['ground', 'gradientStops'] as const;\nexport type OptionalColorAnchor = (typeof OPTIONAL_COLOR_ANCHORS)[number];\n\n/**\n * Like the required color anchors, the required font anchors map up to the options defined by Brand Kits.\n */\nexport const REQUIRED_FONT_ANCHORS = ['heading', 'body'] as const;\nexport type RequiredFontAnchor = (typeof REQUIRED_FONT_ANCHORS)[number];\n\nexport const ANCHOR_REF_PREFIX = 'anchors.';\n\nexport type ColorAnchorRef = `anchors.colors.${ColorAnchorName}`;\nexport type FontAnchorRef = `anchors.fonts.${RequiredFontAnchor}`;\nexport type DimensionAnchorRef = `anchors.dimensions.${RequiredDimensionAnchor}`;\n\ntype ColorAnchorValue<Name extends ColorAnchorName> = Name extends 'gradientStops'\n ? GradientStops\n : SingleColor;\n\nexport type ColorAnchors = Readonly<{ [Name in RequiredColorAnchor]: ColorAnchorValue<Name> }> &\n Readonly<{ [Name in OptionalColorAnchor]?: ColorAnchorValue<Name> }>;\n\nexport type DimensionAnchors = Readonly<Record<RequiredDimensionAnchor, Dimension>>;\n\n// check in about this type\nexport type FontAnchors = Readonly<Record<RequiredFontAnchor, FontStack | BrandKitTokenRef>>;\n\n/**\n * All the possible anchors referenced in a style doc. Options defined by the schema.\n */\nexport type Anchors = {\n readonly colors: ColorAnchors;\n readonly dimensions: DimensionAnchors;\n readonly fonts: FontAnchors;\n};\n\n/** Which colors a treatment cannot resolve without. Checked by `validateStyleDocument`. */\nexport const ANCHORS_REQUIRED_BY_TREATMENT: Readonly<\n Record<Treatment, readonly ColorAnchorName[]>\n> = {\n flat: [],\n glassy: ['ground'],\n gradient: ['gradientStops'],\n none: [],\n};\n","export type BrandKitTokenRef = `$${string}`;\n\nexport type LiteralColor = `#${string}` | `rgb(${string})` | `rgba(${string})`;\n\nexport const COLOR_RELATIONSHIPS = ['same', 'complementary', 'analogous', 'triad'] as const;\nexport type ColorRelationship = (typeof COLOR_RELATIONSHIPS)[number];\n\nexport const COLOR_TONES = ['dark', 'light'] as const;\nexport type ColorTone = (typeof COLOR_TONES)[number];\n\n/**\n * A color derived from a brand token. `relation` turns its hue, then `tone` takes the result to\n * the brand's dark or light background color. Both are optional; with neither, we use the token itself.\n */\nexport type RelatedColor = {\n readonly from: BrandKitTokenRef;\n readonly relation?: ColorRelationship;\n readonly tone?: ColorTone;\n};\n\nexport type SingleColor = LiteralColor | RelatedColor | BrandKitTokenRef;\n\n/**\n * The CSS generic families a hard-coded font stack must end in, so a face that fails to load\n * still falls back to the right kind of type.\n */\nexport const GENERIC_FONT_FAMILIES = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-monospace',\n 'ui-rounded',\n 'math',\n] as const;\nexport type GenericFontFamily = (typeof GENERIC_FONT_FAMILIES)[number];\n\nexport type FontStack = `${string}${GenericFontFamily}`;\n\n/** A length: a brand token, a number in pixels */\nexport type Dimension = BrandKitTokenRef | number;\n\nexport const MAX_COLOR_SCALE_OFFSET = 11;\nexport type ColorScaleOffset = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11;\n","import type { ColorAnchorRef } from './anchors';\nimport type { ColorScaleOffset } from './anchorValues';\n\n/**\n * Where a background's `offset` starts counting from.\n *\n * - `source` — at the source color itself: `colors.primary · 2` is two steps off the primary color.\n * - `parent` — on the source's scale, at the step nearest in lightness to the fill of the surface\n * this one sits on, stepping away from it based on whether the parent is light or dark.\n *\n * The page sits on nothing, so it cannot count from `parent`.\n * A surface that sits on several\n * parents counts from the closest parent.\n */\nexport const OFFSET_ORIGINS = ['source', 'parent'] as const;\nexport type OffsetOrigin = (typeof OFFSET_ORIGINS)[number];\n\n/**\n * When a background color no longer meets accessible contrast against its parent surface, how do we handle that?\n *\n * - `never` — Do nothing. the fill is always what `backgroundColor` resolves to.\n *\n * - `when-indistinct` — Invert the background and foreground colors: the text color\n * becomes the fill and the fill becomes the text. The pair maintains accessible contrast\n * and compatibility with the color scheme.\n */\nexport const INVERT_RULES = ['never', 'when-indistinct'] as const;\nexport type InvertRule = (typeof INVERT_RULES)[number];\n\n/**\n * What color does this background fill reference--a color anchor or the parent surface's background color?\n */\nexport type BackgroundSource = ColorAnchorRef | 'parent';\n\n/**\n * A surface's own fill: where it steps from, how many steps along that source's scale it sits,\n * where those steps start counting ({@link OffsetOrigin}), and whether it may\n * {@link InvertRule | invert} with its text.\n *\n * A `flat` surface at `parent · 0` paints exactly its parent's fill and cannot be seen,\n * which works out to the same effect as `treatment: \"none\"` applied to a surface.\n */\nexport type BackgroundColor = {\n readonly from: OffsetOrigin;\n readonly invert: InvertRule;\n readonly offset: ColorScaleOffset;\n readonly source: BackgroundSource;\n};\n","// The `border` setting: the line along a surface's edge, and the ornaments drawn just outside it.\n\nimport type { ColorAnchorRef } from './anchors';\nimport type { ColorScaleOffset } from './anchorValues';\n\nexport const BORDER_STYLES = ['solid', 'dashed', 'dotted', 'double', 'scalloped', 'lace'] as const;\nexport type BorderStyle = (typeof BORDER_STYLES)[number];\n\n/** The border styles drawn as ornaments outside the edge, rather than as a CSS line. */\nexport const ORNAMENTAL_BORDER_STYLES = ['scalloped', 'lace'] as const;\n\nexport type BorderSource = ColorAnchorRef | 'surface';\n\n/**\n * A surface's border, expressed similarly to how CSS rules work.\n * `width` is provided in pixels, where `0` is effectively no border. Decimal values are acceptable.\n * `source` indicates whether the border color is derived based on the surface background or a separate color value.\n * `style` supports all the definitions in the schema\n * `offset` indicates how much space exists between the edge of the surface and the start of the border.\n */\nexport type Border = {\n readonly offset: ColorScaleOffset;\n readonly source: BorderSource;\n readonly style: BorderStyle;\n readonly width: number;\n};\n","// The `elevation` setting: how far a surface lifts off what is behind it, and in what color.\n\nimport type { ColorAnchorRef } from './anchors';\nimport type { SingleColor } from './anchorValues';\n\nexport const ELEVATION_DEPTHS = ['none', 'low', 'medium', 'high'] as const;\nexport type ElevationDepth = (typeof ELEVATION_DEPTHS)[number];\n\nexport const ELEVATION_HARDNESSES = ['soft', 'hard', 'glow'] as const;\nexport type ElevationHardness = (typeof ELEVATION_HARDNESSES)[number];\n\nexport const ELEVATION_COLOR_SOURCE_KEYWORDS = ['shade'] as const;\nexport type ElevationColorSourceKeyword = (typeof ELEVATION_COLOR_SOURCE_KEYWORDS)[number];\n\nexport type ElevationColorSource = ElevationColorSourceKeyword | ColorAnchorRef | SingleColor;\n\n/**\n * How a surface lifts against its backgroung to appear 3D, and in what color.\n * Alphas, blur radii and offsets are engine-owned based on the value of `hardness`.\n * When `depth` is `none` no shadow/elevation is rendered.\n */\nexport type Elevation = {\n readonly depth: ElevationDepth;\n readonly hardness: ElevationHardness;\n readonly source: ElevationColorSource;\n};\n","import type { SingleColor } from './anchorValues';\n\nexport const MIN_GRADIENT_STOPS = 2;\nexport const MAX_GRADIENT_STOPS = 6;\n\nexport type GradientStops = readonly SingleColor[];\n\nexport const GRADIENT_SHAPE_OPTIONS = ['glows', 'linear', 'radial', 'beams'] as const;\nexport type GradientShapeOption = (typeof GRADIENT_SHAPE_OPTIONS)[number];\n\nexport const GRADIENT_DIRECTIONS = [\n 'to-top',\n 'to-top-right',\n 'to-right',\n 'to-bottom-right',\n 'to-bottom',\n 'to-bottom-left',\n 'to-left',\n 'to-top-left',\n] as const;\nexport type GradientDirection = (typeof GRADIENT_DIRECTIONS)[number];\n\nexport const GRADIENT_POSITIONS = [\n 'center',\n 'top',\n 'top-right',\n 'right',\n 'bottom-right',\n 'bottom',\n 'bottom-left',\n 'left',\n 'top-left',\n] as const;\nexport type GradientPosition = (typeof GRADIENT_POSITIONS)[number];\n\n/**\n * How far a `radial` gradient's last stop reaches: `near` ends at the closest edge, so the corners\n * hold the final color; `far` carries it to the furthest corner.\n */\nexport const GRADIENT_EXTENTS = ['near', 'far'] as const;\nexport type GradientExtent = (typeof GRADIENT_EXTENTS)[number];\n\n/**\n * A gradient shape and whatever supporting info required to draw it.\n * `glows` and `beams` are placed by the engine and take no other args\n * `linear` says which direction it runs\n * `radial` supports where it's centered and how far it reaches.\n */\nexport type GradientShape =\n | { readonly kind: 'beams' }\n | { readonly kind: 'glows' }\n | { readonly direction: GradientDirection; readonly kind: 'linear' }\n | {\n readonly extent: GradientExtent;\n readonly kind: 'radial';\n readonly position: GradientPosition;\n };\n","export const AMBIENT_MOTIONS = ['none', 'drift', 'pulse'] as const;\nexport type AmbientMotion = (typeof AMBIENT_MOTIONS)[number];\n\n/** Rate of ambient motion. Exact durations are owned by the engine. */\nexport const MOTION_SPEEDS = ['slow', 'medium', 'fast'] as const;\nexport type MotionSpeed = (typeof MOTION_SPEEDS)[number];\n\n/** How a surface moves between states — hover, focus, active. Easings are engine-owned. */\nexport const TRANSITIONS = ['none', 'quick', 'smooth'] as const;\nexport type Transition = (typeof TRANSITIONS)[number];\n\n/**\n * Does this surface have any non-interactive animation?\n * `transition` is how it moves when its state changes. A card can transition smoothly on hover while sitting\n * perfectly still otherwise.\n * When `ambient` is `none`, no motion is rendered.\n *\n * Every ambient motion will degrade according to the `prefers-reduced-motion` setting.\n * The engine owns this fallback so style docs do not have to provide this.\n */\nexport type Motion = {\n readonly ambient: AmbientMotion;\n readonly speed: MotionSpeed;\n readonly transition: Transition;\n};\n","import type { BackgroundColor } from './backgroundColor';\nimport type { Border } from './border';\nimport type { Elevation } from './elevation';\nimport type { GradientShape } from './gradientShape';\nimport type { Motion } from './motion';\nimport type { Radius } from './radius';\nimport type { TextColor } from './textColor';\nimport type { Texture } from './texture';\nimport type { Treatment } from './treatment';\n\n/** Surfaces every Style must define. A Style cannot add or opt out of any. */\nexport const SURFACE_NAMES = ['page', 'panel', 'card', 'buttonPrimary', 'buttonSecondary'] as const;\nexport type SurfaceName = (typeof SURFACE_NAMES)[number];\n\nexport const STACKABLE_ON: Readonly<Record<SurfaceName, readonly SurfaceName[]>> = {\n page: [],\n panel: ['page'],\n card: ['page'],\n buttonPrimary: ['page', 'panel', 'card'],\n buttonSecondary: ['page', 'panel', 'card'],\n};\n\nexport const REQUIRED_SETTING_NAMES = [\n 'treatment',\n 'backgroundColor',\n 'textColor',\n 'border',\n 'elevation',\n 'motion',\n 'radius',\n 'texture',\n] as const;\nexport type RequiredSettingName = (typeof REQUIRED_SETTING_NAMES)[number];\n\nexport const OPTIONAL_SETTING_NAMES = ['gradientShape'] as const;\nexport type OptionalSettingName = (typeof OPTIONAL_SETTING_NAMES)[number];\n\nexport const ALL_SETTING_NAMES: readonly (RequiredSettingName | OptionalSettingName)[] = [\n ...REQUIRED_SETTING_NAMES,\n ...OPTIONAL_SETTING_NAMES,\n];\n\ntype RequiredSettings = {\n readonly backgroundColor: BackgroundColor;\n readonly border: Border;\n readonly elevation: Elevation;\n readonly motion: Motion;\n readonly radius: Radius;\n readonly textColor: TextColor;\n readonly texture: Texture;\n};\n\n/**\n * All required settings plus a conditional setting: if the treatment is `gradient`, `gradientShape` is required.\n * Otherwise if the treatment is not `gradient`, `gradientShape` must not be present.\n */\nexport type SurfaceSettings = RequiredSettings &\n (\n | { readonly gradientShape: GradientShape; readonly treatment: 'gradient' }\n | { readonly gradientShape?: never; readonly treatment: Exclude<Treatment, 'gradient'> }\n );\n\n/**\n * All possible surfaces and their settings, required to be provided by a Style document.\n */\nexport type Surfaces = Readonly<Record<SurfaceName, SurfaceSettings>>;\n","/**\n * - `grain` — fine, even film noise\n * - `static` — sharp, high-contrast speckles, like screen noise\n * - `halftone` — a regular dot screen, as in print\n */\nexport const TEXTURE_KINDS = ['none', 'grain', 'static', 'halftone'] as const;\nexport type TextureKind = (typeof TEXTURE_KINDS)[number];\n\nexport const TEXTURE_INTENSITIES = ['low', 'medium', 'high'] as const;\nexport type TextureIntensity = (typeof TEXTURE_INTENSITIES)[number];\n\n/**\n * A texture laid over the surface's fill: which one, and how strong it is.\n *\n * It is separate from `treatment` because textures can be stacked on top of treatments:\n * grain on glass, static on a gradient.\n *\n * When `kind` is `none`, no texture is applied.\n */\nexport type Texture = {\n readonly intensity: TextureIntensity;\n readonly kind: TextureKind;\n};\n","/**\n * What visual treatment is applied to a surface?\n * `gradient` renders `colors.gradientStops` based on the values provided in `gradientShape`\n * `glassy` renders a semi-translucent glass effect, best over a background with visual noise/texture as opposed to a flat color.\n * `flat` renders a flat color\n * `none` renders no background and lets the parent show through\n */\nexport const TREATMENTS = ['none', 'flat', 'glassy', 'gradient'] as const;\nexport type Treatment = (typeof TREATMENTS)[number];\n","import type { FontAnchorRef } from './anchors';\n\nexport const TYPE_CASES = ['as-typed', 'upper'] as const;\nexport type TypeCase = (typeof TYPE_CASES)[number];\n\nexport const TYPE_ROLES = ['heading', 'body', 'button'] as const;\nexport type TypeRoleName = (typeof TYPE_ROLES)[number];\n\nexport type TypeRole = {\n readonly case: TypeCase;\n readonly font: FontAnchorRef;\n readonly fontSize: number;\n readonly fontWeight: number;\n};\n\n/**\n * Rules for the type face, weight, case, and size\n *\n * `fontSize` is provided in pixels\n * `fontWeight` is a CSS weight from 1 - 1000\n * `font` references an anchor. We don't support providing a custom font name here because we don't\n * have a mechanism to load that font into the DOM.\n */\nexport type Typography = Readonly<Record<TypeRoleName, TypeRole>>;\n","/**\n * The shape of a Kaleidoscope Style document.\n *\n * A style document provides a set of instructions on how to render a set of surfaces,\n * based on abstractified representations of CSS rules.\n *\n * The engine takes these instructions and \"inflates\" them into actual CSS that can be applied\n * to embeds and/or hosted pages.\n */\nimport type { Anchors } from './anchors';\nimport type { Surfaces } from './surfaces';\nimport type { Typography } from './typography';\n\n/** The top-level keys in a Style document */\nexport const DOCUMENT_KEYS = [\n 'id',\n 'name',\n 'schemaVersion',\n 'typography',\n 'anchors',\n 'surfaces',\n] as const;\n\nexport type StyleDocument = {\n readonly anchors: Anchors;\n readonly id: string;\n readonly name: string;\n readonly schemaVersion: 1;\n readonly surfaces: Surfaces;\n readonly typography: Typography;\n};\n\nexport * from './anchors';\nexport * from './anchorValues';\nexport * from './backgroundColor';\nexport * from './border';\nexport * from './elevation';\nexport * from './gradientShape';\nexport * from './motion';\n// `radius` declares only types\nexport type * from './radius';\nexport * from './surfaces';\n// `textColor` declares only types\nexport type * from './textColor';\nexport * from './texture';\nexport * from './treatment';\nexport * from './typography';\n"],"mappings":";;;;;;;;;;AAIA,MAAa,gBAAgB;CAAC;CAAc;CAAU;AAAO;;;;;;AAQ7D,MAAa,6BAA6B,CAAC,cAAc;AAGzD,MAAa,qBAAqB;CAAC;CAAkB;CAAW;CAAU;AAAe;;;;;;AAQzF,MAAa,yBAAyB,CAAC,kBAAkB,SAAS;;;;;;AAQlE,MAAa,yBAAyB,CAAC,UAAU,eAAe;;;;AAMhE,MAAa,wBAAwB,CAAC,WAAW,MAAM;AAGvD,MAAa,oBAAoB;;AA4BjC,MAAa,gCAET;CACF,MAAM,CAAC;CACP,QAAQ,CAAC,QAAQ;CACjB,UAAU,CAAC,eAAe;CAC1B,MAAM,CAAC;AACT;;;ACvEA,MAAa,sBAAsB;CAAC;CAAQ;CAAiB;CAAa;AAAO;AAGjF,MAAa,cAAc,CAAC,QAAQ,OAAO;;;;;AAmB3C,MAAa,wBAAwB;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAQA,MAAa,yBAAyB;;;;;;;;;;;;;;AChCtC,MAAa,iBAAiB,CAAC,UAAU,QAAQ;;;;;;;;;;AAYjD,MAAa,eAAe,CAAC,SAAS,iBAAiB;;;ACrBvD,MAAa,gBAAgB;CAAC;CAAS;CAAU;CAAU;CAAU;CAAa;AAAM;;AAIxF,MAAa,2BAA2B,CAAC,aAAa,MAAM;;;ACJ5D,MAAa,mBAAmB;CAAC;CAAQ;CAAO;CAAU;AAAM;AAGhE,MAAa,uBAAuB;CAAC;CAAQ;CAAQ;AAAM;AAG3D,MAAa,kCAAkC,CAAC,OAAO;;;ACTvD,MAAa,qBAAqB;AAClC,MAAa,qBAAqB;AAIlC,MAAa,yBAAyB;CAAC;CAAS;CAAU;CAAU;AAAO;AAG3E,MAAa,sBAAsB;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,qBAAqB;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;AAOA,MAAa,mBAAmB,CAAC,QAAQ,KAAK;;;ACvC9C,MAAa,kBAAkB;CAAC;CAAQ;CAAS;AAAO;;AAIxD,MAAa,gBAAgB;CAAC;CAAQ;CAAU;AAAM;;AAItD,MAAa,cAAc;CAAC;CAAQ;CAAS;AAAQ;;;;ACGrD,MAAa,gBAAgB;CAAC;CAAQ;CAAS;CAAQ;CAAiB;AAAiB;AAGzF,MAAa,eAAsE;CACjF,MAAM,CAAC;CACP,OAAO,CAAC,MAAM;CACd,MAAM,CAAC,MAAM;CACb,eAAe;EAAC;EAAQ;EAAS;CAAM;CACvC,iBAAiB;EAAC;EAAQ;EAAS;CAAM;AAC3C;AAEA,MAAa,yBAAyB;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,yBAAyB,CAAC,eAAe;AAGtD,MAAa,oBAA4E,CACvF,GAAG,wBACH,GAAG,sBACL;;;;;;;;ACnCA,MAAa,gBAAgB;CAAC;CAAQ;CAAS;CAAU;AAAU;AAGnE,MAAa,sBAAsB;CAAC;CAAO;CAAU;AAAM;;;;;;;;;;ACD3D,MAAa,aAAa;CAAC;CAAQ;CAAQ;CAAU;AAAU;;;ACL/D,MAAa,aAAa,CAAC,YAAY,OAAO;AAG9C,MAAa,aAAa;CAAC;CAAW;CAAQ;AAAQ;;;;ACStD,MAAa,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"vocabulary-CpT99K6y.js","names":[],"sources":["../src/styleVocabulary/anchors.ts","../src/styleVocabulary/anchorValues.ts","../src/styleVocabulary/backgroundColor.ts","../src/styleVocabulary/border.ts","../src/styleVocabulary/elevation.ts","../src/styleVocabulary/gradientShape.ts","../src/styleVocabulary/motion.ts","../src/styleVocabulary/surfaces.ts","../src/styleVocabulary/texture.ts","../src/styleVocabulary/treatment.ts","../src/styleVocabulary/typography.ts","../src/styleVocabulary/index.ts"],"sourcesContent":["import type { Dimension, FontStack, SingleColor, BrandKitTokenRef } from './anchorValues';\nimport type { GradientStops } from './gradientShape';\nimport type { Treatment } from './treatment';\n\nexport const ANCHOR_GROUPS = ['dimensions', 'colors', 'fonts'] as const;\nexport type AnchorGroup = (typeof ANCHOR_GROUPS)[number];\n\n/**\n * Like the required color and font anchors, the required dimension anchors map up to Brand Kit\n * options. A Style may hard-code one instead: Glass does, because the glass effect needs\n * generous rounding.\n */\nexport const REQUIRED_DIMENSION_ANCHORS = ['borderRadius'] as const;\nexport type RequiredDimensionAnchor = (typeof REQUIRED_DIMENSION_ANCHORS)[number];\n\nexport const COLOR_ANCHOR_NAMES = ['pageBackground', 'primary', 'ground', 'gradientStops'] as const;\nexport type ColorAnchorName = (typeof COLOR_ANCHOR_NAMES)[number];\n\n/**\n * The required color anchors should correlate to whatever Brand Kit tokens exist,\n * currently pageBackgroundColor and primaryColor.\n * If an accentColor is supported in the future, we'll add it here.\n */\nexport const REQUIRED_COLOR_ANCHORS = ['pageBackground', 'primary'] as const;\nexport type RequiredColorAnchor = (typeof REQUIRED_COLOR_ANCHORS)[number];\n\n/**\n * These colors are optional, based on which Style and/or treatment is applied to a surface.\n * Glass styles use the ground color as the background for the glass effect: dark or light.\n * The aurora styles use the ground color as a hard-coded value for the backgrounds of cards and panels.\n */\nexport const OPTIONAL_COLOR_ANCHORS = ['ground', 'gradientStops'] as const;\nexport type OptionalColorAnchor = (typeof OPTIONAL_COLOR_ANCHORS)[number];\n\n/**\n * Like the required color anchors, the required font anchors map up to the options defined by Brand Kits.\n */\nexport const REQUIRED_FONT_ANCHORS = ['heading', 'body'] as const;\nexport type RequiredFontAnchor = (typeof REQUIRED_FONT_ANCHORS)[number];\n\nexport const ANCHOR_REF_PREFIX = 'anchors.';\n\nexport type ColorAnchorRef = `anchors.colors.${ColorAnchorName}`;\nexport type FontAnchorRef = `anchors.fonts.${RequiredFontAnchor}`;\nexport type DimensionAnchorRef = `anchors.dimensions.${RequiredDimensionAnchor}`;\n\ntype ColorAnchorValue<Name extends ColorAnchorName> = Name extends 'gradientStops'\n ? GradientStops\n : SingleColor;\n\nexport type ColorAnchors = Readonly<{ [Name in RequiredColorAnchor]: ColorAnchorValue<Name> }> &\n Readonly<{ [Name in OptionalColorAnchor]?: ColorAnchorValue<Name> }>;\n\nexport type DimensionAnchors = Readonly<Record<RequiredDimensionAnchor, Dimension>>;\n\n// check in about this type\nexport type FontAnchors = Readonly<Record<RequiredFontAnchor, FontStack | BrandKitTokenRef>>;\n\n/**\n * All the possible anchors referenced in a style doc. Options defined by the schema.\n */\nexport type Anchors = {\n readonly colors: ColorAnchors;\n readonly dimensions: DimensionAnchors;\n readonly fonts: FontAnchors;\n};\n\n/** Which colors a treatment cannot resolve without. Checked by `validateStyleDocument`. */\nexport const ANCHORS_REQUIRED_BY_TREATMENT: Readonly<\n Record<Treatment, readonly ColorAnchorName[]>\n> = {\n flat: [],\n glassy: ['ground'],\n gradient: ['gradientStops'],\n none: [],\n};\n","export type BrandKitTokenRef = `$${string}`;\n\nexport type LiteralColor = `#${string}` | `rgb(${string})` | `rgba(${string})`;\n\nexport const COLOR_RELATIONSHIPS = ['same', 'complementary', 'analogous', 'triad'] as const;\nexport type ColorRelationship = (typeof COLOR_RELATIONSHIPS)[number];\n\nexport const COLOR_TONES = ['dark', 'light'] as const;\nexport type ColorTone = (typeof COLOR_TONES)[number];\n\n/**\n * A color derived from a brand token. `relation` turns its hue, then `tone` takes the result to\n * the brand's dark or light background color. Both are optional; with neither, we use the token itself.\n */\nexport type RelatedColor = {\n readonly from: BrandKitTokenRef;\n readonly relation?: ColorRelationship;\n readonly tone?: ColorTone;\n};\n\nexport type SingleColor = LiteralColor | RelatedColor | BrandKitTokenRef;\n\n/**\n * The CSS generic families a hard-coded font stack must end in, so a face that fails to load\n * still falls back to the right kind of type.\n */\nexport const GENERIC_FONT_FAMILIES = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-monospace',\n 'ui-rounded',\n 'math',\n] as const;\nexport type GenericFontFamily = (typeof GENERIC_FONT_FAMILIES)[number];\n\nexport type FontStack = `${string}${GenericFontFamily}`;\n\n/** A length: a brand token, a number in pixels */\nexport type Dimension = BrandKitTokenRef | number;\n\nexport const MAX_COLOR_SCALE_OFFSET = 11;\nexport type ColorScaleOffset = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11;\n","import type { ColorAnchorRef } from './anchors';\nimport type { ColorScaleOffset } from './anchorValues';\n\n/**\n * Where a background's `offset` starts counting from.\n *\n * - `source` — at the source color itself: `colors.primary · 2` is two steps off the primary color.\n * - `parent` — on the source's scale, at the step nearest in lightness to the fill of the surface\n * this one sits on, stepping away from it based on whether the parent is light or dark.\n *\n * The page sits on nothing, so it cannot count from `parent`.\n * A surface that sits on several\n * parents counts from the closest parent.\n */\nexport const OFFSET_ORIGINS = ['source', 'parent'] as const;\nexport type OffsetOrigin = (typeof OFFSET_ORIGINS)[number];\n\n/**\n * When a background color no longer meets accessible contrast against its parent surface, how do we handle that?\n *\n * - `never` — Do nothing. the fill is always what `backgroundColor` resolves to.\n *\n * - `when-indistinct` — Invert the background and foreground colors: the text color\n * becomes the fill and the fill becomes the text. The pair maintains accessible contrast\n * and compatibility with the color scheme.\n */\nexport const INVERT_RULES = ['never', 'when-indistinct'] as const;\nexport type InvertRule = (typeof INVERT_RULES)[number];\n\n/**\n * What color does this background fill reference--a color anchor or the parent surface's background color?\n */\nexport type BackgroundSource = ColorAnchorRef | 'parent';\n\n/**\n * A surface's own fill: where it steps from, how many steps along that source's scale it sits,\n * where those steps start counting ({@link OffsetOrigin}), and whether it may\n * {@link InvertRule | invert} with its text.\n *\n * A `flat` surface at `parent · 0` paints exactly its parent's fill and cannot be seen,\n * which works out to the same effect as `treatment: \"none\"` applied to a surface.\n */\nexport type BackgroundColor = {\n readonly from: OffsetOrigin;\n readonly invert: InvertRule;\n readonly offset: ColorScaleOffset;\n readonly source: BackgroundSource;\n};\n","// The `border` setting: the line along a surface's edge, and the ornaments drawn just outside it.\n\nimport type { ColorAnchorRef } from './anchors';\nimport type { ColorScaleOffset } from './anchorValues';\n\nexport const BORDER_STYLES = ['solid', 'dashed', 'dotted', 'double', 'scalloped', 'lace'] as const;\nexport type BorderStyle = (typeof BORDER_STYLES)[number];\n\n/** The border styles drawn as ornaments outside the edge, rather than as a CSS line. */\nexport const ORNAMENTAL_BORDER_STYLES = ['scalloped', 'lace'] as const;\n\nexport type BorderSource = ColorAnchorRef | 'surface';\n\n/**\n * A surface's border, expressed similarly to how CSS rules work.\n * `width` is provided in pixels, where `0` is effectively no border. Decimal values are acceptable.\n * `source` indicates whether the border color is derived based on the surface background or a separate color value.\n * `style` supports all the definitions in the schema\n * `offset` indicates how much space exists between the edge of the surface and the start of the border.\n */\nexport type Border = {\n readonly offset: ColorScaleOffset;\n readonly source: BorderSource;\n readonly style: BorderStyle;\n readonly width: number;\n};\n","// The `elevation` setting: how far a surface lifts off what is behind it, and in what color.\n\nimport type { ColorAnchorRef } from './anchors';\nimport type { SingleColor } from './anchorValues';\n\nexport const ELEVATION_DEPTHS = ['none', 'low', 'medium', 'high'] as const;\nexport type ElevationDepth = (typeof ELEVATION_DEPTHS)[number];\n\nexport const ELEVATION_HARDNESSES = ['soft', 'hard', 'glow'] as const;\nexport type ElevationHardness = (typeof ELEVATION_HARDNESSES)[number];\n\nexport const ELEVATION_COLOR_SOURCE_KEYWORDS = ['shade'] as const;\nexport type ElevationColorSourceKeyword = (typeof ELEVATION_COLOR_SOURCE_KEYWORDS)[number];\n\nexport type ElevationColorSource = ElevationColorSourceKeyword | ColorAnchorRef | SingleColor;\n\n/**\n * How a surface lifts against its backgroung to appear 3D, and in what color.\n * Alphas, blur radii and offsets are engine-owned based on the value of `hardness`.\n * When `depth` is `none` no shadow/elevation is rendered.\n */\nexport type Elevation = {\n readonly depth: ElevationDepth;\n readonly hardness: ElevationHardness;\n readonly source: ElevationColorSource;\n};\n","import type { SingleColor } from './anchorValues';\n\nexport const MIN_GRADIENT_STOPS = 2;\nexport const MAX_GRADIENT_STOPS = 6;\n\nexport type GradientStops = readonly SingleColor[];\n\nexport const GRADIENT_SHAPE_OPTIONS = ['glows', 'linear', 'radial', 'beams'] as const;\nexport type GradientShapeOption = (typeof GRADIENT_SHAPE_OPTIONS)[number];\n\nexport const GRADIENT_DIRECTIONS = [\n 'to-top',\n 'to-top-right',\n 'to-right',\n 'to-bottom-right',\n 'to-bottom',\n 'to-bottom-left',\n 'to-left',\n 'to-top-left',\n] as const;\nexport type GradientDirection = (typeof GRADIENT_DIRECTIONS)[number];\n\nexport const GRADIENT_POSITIONS = [\n 'center',\n 'top',\n 'top-right',\n 'right',\n 'bottom-right',\n 'bottom',\n 'bottom-left',\n 'left',\n 'top-left',\n] as const;\nexport type GradientPosition = (typeof GRADIENT_POSITIONS)[number];\n\n/**\n * How far a `radial` gradient's last stop reaches: `near` ends at the closest edge, so the corners\n * hold the final color; `far` carries it to the furthest corner.\n */\nexport const GRADIENT_EXTENTS = ['near', 'far'] as const;\nexport type GradientExtent = (typeof GRADIENT_EXTENTS)[number];\n\n/**\n * A gradient shape and whatever supporting info required to draw it.\n * `glows` and `beams` are placed by the engine and take no other args\n * `linear` says which direction it runs\n * `radial` supports where it's centered and how far it reaches.\n */\nexport type GradientShape =\n | { readonly kind: 'beams' }\n | { readonly kind: 'glows' }\n | { readonly direction: GradientDirection; readonly kind: 'linear' }\n | {\n readonly extent: GradientExtent;\n readonly kind: 'radial';\n readonly position: GradientPosition;\n };\n","export const AMBIENT_MOTIONS = ['none', 'drift', 'pulse'] as const;\nexport type AmbientMotion = (typeof AMBIENT_MOTIONS)[number];\n\n/** Rate of ambient motion. Exact durations are owned by the engine. */\nexport const MOTION_SPEEDS = ['slow', 'medium', 'fast'] as const;\nexport type MotionSpeed = (typeof MOTION_SPEEDS)[number];\n\n/** How a surface moves between states — hover, focus, active. Easings are engine-owned. */\nexport const TRANSITIONS = ['none', 'quick', 'smooth'] as const;\nexport type Transition = (typeof TRANSITIONS)[number];\n\n/**\n * Does this surface have any non-interactive animation?\n * `transition` is how it moves when its state changes. A card can transition smoothly on hover while sitting\n * perfectly still otherwise.\n * When `ambient` is `none`, no motion is rendered.\n *\n * Every ambient motion will degrade according to the `prefers-reduced-motion` setting.\n * The engine owns this fallback so style docs do not have to provide this.\n */\nexport type Motion = {\n readonly ambient: AmbientMotion;\n readonly speed: MotionSpeed;\n readonly transition: Transition;\n};\n","import type { BackgroundColor } from './backgroundColor';\nimport type { Border } from './border';\nimport type { Elevation } from './elevation';\nimport type { GradientShape } from './gradientShape';\nimport type { Motion } from './motion';\nimport type { Radius } from './radius';\nimport type { TextColor } from './textColor';\nimport type { Texture } from './texture';\nimport type { Treatment } from './treatment';\n\n/** Surfaces every Style must define. A Style cannot add or opt out of any. */\nexport const SURFACE_NAMES = ['page', 'panel', 'card', 'buttonPrimary', 'buttonSecondary'] as const;\nexport type SurfaceName = (typeof SURFACE_NAMES)[number];\n\nexport const STACKABLE_ON: Readonly<Record<SurfaceName, readonly SurfaceName[]>> = {\n page: [],\n panel: ['page'],\n card: ['page'],\n buttonPrimary: ['page', 'panel', 'card'],\n buttonSecondary: ['page', 'panel', 'card'],\n};\n\nexport const REQUIRED_SETTING_NAMES = [\n 'treatment',\n 'backgroundColor',\n 'textColor',\n 'border',\n 'elevation',\n 'motion',\n 'radius',\n 'texture',\n] as const;\nexport type RequiredSettingName = (typeof REQUIRED_SETTING_NAMES)[number];\n\nexport const OPTIONAL_SETTING_NAMES = ['gradientShape'] as const;\nexport type OptionalSettingName = (typeof OPTIONAL_SETTING_NAMES)[number];\n\nexport const ALL_SETTING_NAMES: readonly (RequiredSettingName | OptionalSettingName)[] = [\n ...REQUIRED_SETTING_NAMES,\n ...OPTIONAL_SETTING_NAMES,\n];\n\ntype RequiredSettings = {\n readonly backgroundColor: BackgroundColor;\n readonly border: Border;\n readonly elevation: Elevation;\n readonly motion: Motion;\n readonly radius: Radius;\n readonly textColor: TextColor;\n readonly texture: Texture;\n};\n\n/**\n * All required settings plus a conditional setting: if the treatment is `gradient`, `gradientShape` is required.\n * Otherwise if the treatment is not `gradient`, `gradientShape` must not be present.\n */\nexport type SurfaceSettings = RequiredSettings &\n (\n | { readonly gradientShape: GradientShape; readonly treatment: 'gradient' }\n | { readonly gradientShape?: never; readonly treatment: Exclude<Treatment, 'gradient'> }\n );\n\n/**\n * All possible surfaces and their settings, required to be provided by a Style document.\n */\nexport type Surfaces = Readonly<Record<SurfaceName, SurfaceSettings>>;\n","/**\n * - `grain` — fine, even film noise\n * - `static` — sharp, high-contrast speckles, like screen noise\n * - `halftone` — a regular dot screen, as in print\n */\nexport const TEXTURE_KINDS = ['none', 'grain', 'static', 'halftone'] as const;\nexport type TextureKind = (typeof TEXTURE_KINDS)[number];\n\nexport const TEXTURE_INTENSITIES = ['low', 'medium', 'high'] as const;\nexport type TextureIntensity = (typeof TEXTURE_INTENSITIES)[number];\n\n/**\n * A texture laid over the surface's fill: which one, and how strong it is.\n *\n * It is separate from `treatment` because textures can be stacked on top of treatments:\n * grain on glass, static on a gradient.\n *\n * When `kind` is `none`, no texture is applied.\n */\nexport type Texture = {\n readonly intensity: TextureIntensity;\n readonly kind: TextureKind;\n};\n","/**\n * What visual treatment is applied to a surface?\n * `gradient` renders `colors.gradientStops` based on the values provided in `gradientShape`\n * `glassy` renders a semi-translucent glass effect, best over a background with visual noise/texture as opposed to a flat color.\n * `flat` renders a flat color\n * `none` renders no background and lets the parent show through\n */\nexport const TREATMENTS = ['none', 'flat', 'glassy', 'gradient'] as const;\nexport type Treatment = (typeof TREATMENTS)[number];\n","import type { FontAnchorRef } from './anchors';\n\nexport const TYPE_CASES = ['as-typed', 'upper'] as const;\nexport type TypeCase = (typeof TYPE_CASES)[number];\n\nexport const TYPE_ROLES = ['heading', 'body', 'button'] as const;\nexport type TypeRoleName = (typeof TYPE_ROLES)[number];\n\nexport type TypeRole = {\n readonly case: TypeCase;\n readonly font: FontAnchorRef;\n readonly fontSize: number;\n readonly fontWeight: number;\n};\n\n/**\n * Rules for the type face, weight, case, and size\n *\n * `fontSize` is provided in pixels\n * `fontWeight` is a CSS weight from 1 - 1000\n * `font` references an anchor. We don't support providing a custom font name here because we don't\n * have a mechanism to load that font into the DOM.\n */\nexport type Typography = Readonly<Record<TypeRoleName, TypeRole>>;\n","/**\n * The shape of a Kaleidoscope Style document.\n *\n * A style document provides a set of instructions on how to render a set of surfaces,\n * based on abstractified representations of CSS rules.\n *\n * The engine takes these instructions and \"inflates\" them into actual CSS that can be applied\n * to embeds and/or hosted pages.\n */\nimport type { Anchors } from './anchors';\nimport type { Surfaces } from './surfaces';\nimport type { Typography } from './typography';\n\n/** The top-level keys in a Style document */\nexport const DOCUMENT_KEYS = [\n 'id',\n 'name',\n 'schemaVersion',\n 'typography',\n 'anchors',\n 'surfaces',\n] as const;\n\nexport type StyleDocument = {\n readonly anchors: Anchors;\n readonly id: string;\n readonly name: string;\n readonly schemaVersion: 1;\n readonly surfaces: Surfaces;\n readonly typography: Typography;\n};\n\nexport * from './anchors';\nexport * from './anchorValues';\nexport * from './backgroundColor';\nexport * from './border';\nexport * from './elevation';\nexport * from './gradientShape';\nexport * from './motion';\n// `radius` declares only types\nexport type * from './radius';\nexport * from './surfaces';\n// `textColor` declares only types\nexport type * from './textColor';\nexport * from './texture';\nexport * from './treatment';\nexport * from './typography';\n"],"mappings":";;;;;;;;;;AAIA,MAAa,gBAAgB;CAAC;CAAc;CAAU;AAAO;;;;;;AAQ7D,MAAa,6BAA6B,CAAC,cAAc;AAGzD,MAAa,qBAAqB;CAAC;CAAkB;CAAW;CAAU;AAAe;;;;;;AAQzF,MAAa,yBAAyB,CAAC,kBAAkB,SAAS;;;;;;AAQlE,MAAa,yBAAyB,CAAC,UAAU,eAAe;;;;AAMhE,MAAa,wBAAwB,CAAC,WAAW,MAAM;AAGvD,MAAa,oBAAoB;;AA4BjC,MAAa,gCAET;CACF,MAAM,CAAC;CACP,QAAQ,CAAC,QAAQ;CACjB,UAAU,CAAC,eAAe;CAC1B,MAAM,CAAC;AACT;;;ACvEA,MAAa,sBAAsB;CAAC;CAAQ;CAAiB;CAAa;AAAO;AAGjF,MAAa,cAAc,CAAC,QAAQ,OAAO;;;;;AAmB3C,MAAa,wBAAwB;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAQA,MAAa,yBAAyB;;;;;;;;;;;;;;AChCtC,MAAa,iBAAiB,CAAC,UAAU,QAAQ;;;;;;;;;;AAYjD,MAAa,eAAe,CAAC,SAAS,iBAAiB;;;ACrBvD,MAAa,gBAAgB;CAAC;CAAS;CAAU;CAAU;CAAU;CAAa;AAAM;;AAIxF,MAAa,2BAA2B,CAAC,aAAa,MAAM;;;ACJ5D,MAAa,mBAAmB;CAAC;CAAQ;CAAO;CAAU;AAAM;AAGhE,MAAa,uBAAuB;CAAC;CAAQ;CAAQ;AAAM;AAG3D,MAAa,kCAAkC,CAAC,OAAO;;;ACTvD,MAAa,qBAAqB;AAClC,MAAa,qBAAqB;AAIlC,MAAa,yBAAyB;CAAC;CAAS;CAAU;CAAU;AAAO;AAG3E,MAAa,sBAAsB;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,qBAAqB;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;AAOA,MAAa,mBAAmB,CAAC,QAAQ,KAAK;;;ACvC9C,MAAa,kBAAkB;CAAC;CAAQ;CAAS;AAAO;;AAIxD,MAAa,gBAAgB;CAAC;CAAQ;CAAU;AAAM;;AAItD,MAAa,cAAc;CAAC;CAAQ;CAAS;AAAQ;;;;ACGrD,MAAa,gBAAgB;CAAC;CAAQ;CAAS;CAAQ;CAAiB;AAAiB;AAGzF,MAAa,eAAsE;CACjF,MAAM,CAAC;CACP,OAAO,CAAC,MAAM;CACd,MAAM,CAAC,MAAM;CACb,eAAe;EAAC;EAAQ;EAAS;CAAM;CACvC,iBAAiB;EAAC;EAAQ;EAAS;CAAM;AAC3C;AAEA,MAAa,yBAAyB;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,yBAAyB,CAAC,eAAe;AAGtD,MAAa,oBAA4E,CACvF,GAAG,wBACH,GAAG,sBACL;;;;;;;;ACnCA,MAAa,gBAAgB;CAAC;CAAQ;CAAS;CAAU;AAAU;AAGnE,MAAa,sBAAsB;CAAC;CAAO;CAAU;AAAM;;;;;;;;;;ACD3D,MAAa,aAAa;CAAC;CAAQ;CAAQ;CAAU;AAAU;;;ACL/D,MAAa,aAAa,CAAC,YAAY,OAAO;AAG9C,MAAa,aAAa;CAAC;CAAW;CAAQ;AAAQ;;;;ACStD,MAAa,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;CACA;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wistia/kaleidoscope",
3
- "version": "0.0.3-beta.744e55dd.c7dc7eb",
3
+ "version": "0.0.3",
4
4
  "description": "Shared logic and token engine for Wistia's audience-facing design system",
5
5
  "type": "module",
6
6
  "module": "dist/index.js",
@@ -42,7 +42,7 @@
42
42
  "typecheck": "tsc"
43
43
  },
44
44
  "devDependencies": {
45
- "@repo/config": "workspace:*",
45
+ "@repo/config": "0.0.0",
46
46
  "@storybook/addon-a11y": "^10.5.10",
47
47
  "@storybook/addon-docs": "^10.5.10",
48
48
  "@storybook/react-vite": "^10.5.10",
@@ -50,7 +50,7 @@
50
50
  "@types/react": "^19.2.18",
51
51
  "@types/react-dom": "^19.2.5",
52
52
  "@vitest/coverage-v8": "^5.0.0",
53
- "@wistia/ui": "workspace:*",
53
+ "@wistia/ui": "2.2.0",
54
54
  "check-export-map": "^1.3.1",
55
55
  "react": "^19.2.8",
56
56
  "react-dom": "^19.2.8",
@@ -72,4 +72,4 @@
72
72
  "url": "https://github.com/wistia/vhs/issues"
73
73
  },
74
74
  "homepage": "https://github.com/wistia/vhs#readme"
75
- }
75
+ }