Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | 1x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 6x 6x 3x 3x 6x 6x 6x 6x 6x 6x 6x 6x 3x 1x 5x 5x 5x 5x 5x 5x 5x 1x 1x 34x 34x 34x 34x 1x 5x 5x 5x 5x 5x 1x 1x 34x 34x 34x 34x 34x 26x 26x 1x 34x 34x 34x | import { Color } from "../../coreTable/CoreTableConstants" import { rgb, color, RGBColor } from "d3-color" import { interpolate } from "d3-interpolate" import { difference, groupBy, minBy } from "../../clientUtils/Util" export const interpolateArray = ( scaleArr: string[] ): ((t: number) => string) => { const N = scaleArr.length - 2 // -1 for spacings, -1 for number of interpolate fns const intervalWidth = 1 / N const intervals: Array<(t: number) => string> = [] for (let i = 0; i <= N; i++) { intervals[i] = interpolate(rgb(scaleArr[i]), rgb(scaleArr[i + 1])) } return (t: number): string => { if (t < 0 || t > 1) throw new Error("Outside the allowed range of [0, 1]") const i = Math.floor(t * N) const intervalOffset = i * intervalWidth return intervals[i](t / intervalWidth - intervalOffset / intervalWidth) } } export function getLeastUsedColor( availableColors: Color[], usedColors: Color[] ): Color | undefined { // If there are unused colors, return the first available const unusedColors = difference(availableColors, usedColors) if (unusedColors.length > 0) return unusedColors[0] // If all colors are used, we want to count the times each color is used, and use the most // unused one. const colorCounts = Object.entries(groupBy(usedColors)).map( ([color, arr]): any[] => [color, arr.length] ) const mostUnusedColor = minBy(colorCounts, ([, count]) => count) as [ string, number ] return mostUnusedColor[0] } // Taken from https://github.com/Qix-/color/blob/594a9af778f9a89541510bd1ae24061c82f24693/index.js#L287-L292 function getYiq(rgb: RGBColor): number { // YIQ equation from http://24ways.org/2010/calculating-color-contrast return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000 } export function isDarkColor(colorSpecifier: string): boolean | undefined { const rgb = color(colorSpecifier)?.rgb() if (!rgb) return undefined return getYiq(rgb) < 128 } // See https://observablehq.com/@danielgavrilov/darken-colors-to-meet-a-target-contrast-ratio function darkenColorToTargetYiq(colorHex: Color, targetYiq: number): Color { const c = color(colorHex)?.rgb() if (!c) return colorHex const darkenCoeff = getYiq(c) / targetYiq - 1.0 if (darkenCoeff > 0) return c.darker(darkenCoeff).hex() return c.hex() } export function darkenColorForLine(colorHex: Color): Color { return darkenColorToTargetYiq(colorHex, 170) } export function darkenColorForText(colorHex: Color): Color { return darkenColorToTargetYiq(colorHex, 125) } export function darkenColorForHighContrastText(colorHex: Color): Color { return darkenColorToTargetYiq(colorHex, 105) } |