src/components/explore/DistributionChart.svelte (85 lines of code) (raw):

<script> import { scaleLinear } from 'd3-scale'; import { tooltip as tooltipAction } from '@graph-paper/core/actions'; import { distributionComparisonGraph } from '../../utils/constants'; import { formatCompact } from '../../utils/formatters'; import { store } from '../../state/store'; export let innerHeight; export let innerWidth; export let density; export let topTick; export let sampleCount; export let tooltipLocation; export let activeCategoricalProbeLabels; let height = (innerHeight * distributionComparisonGraph.heightMult) / 2; let color = 'var(--digital-blue-350)'; let binSelector = 'bin'; let offsetX = distributionComparisonGraph.alignOffsetX; let width = innerWidth * distributionComparisonGraph.widthMult - distributionComparisonGraph.right - distributionComparisonGraph.left; let maxHeight = height - distributionComparisonGraph.top; let minHeight = distributionComparisonGraph.bottom; let isCategoricalProbe = $store.probe.details && $store.probe.details.kind === 'categorical'; let formatPercent = (t) => Intl.NumberFormat('en-US', { style: 'percent', maximumFractionDigits: 2, }).format(t); $: y = scaleLinear().domain([0, topTick]).range([minHeight, maxHeight]); const bucketWidth = (width * 1.0101) / density.length; const spaceBetweenBars = bucketWidth / 10; const barOffsetX = spaceBetweenBars / 2; const barWidth = bucketWidth - spaceBetweenBars; const buildBucketTxt = (index, bin) => { if (isCategoricalProbe) { return activeCategoricalProbeLabels[index]; } return index === density.length - 1 ? `sample value ≥ ${bin}` : `${bin} ≤ sample value ≤ ${density[index + 1][binSelector]}`; }; </script> <style> .hovd { opacity: 0; } .hovd:hover { opacity: 1; fill: var(--cool-gray-100); z-index: 999; } </style> <g style="fill: {color};"> {#each density as { bin, value }, i} <rect stroke={color} x={offsetX + i * bucketWidth + barOffsetX} y={maxHeight - y(value) + minHeight} height={y(value) - minHeight} width={barWidth} /> {/each} </g> <g style="fill: {'#fafafa'};"> {#each density as { bin, value }, i} {@const bucketTxt = buildBucketTxt(i, bin)} {@const valTxt = ` | ${formatPercent(value)} of samples (${formatCompact( sampleCount * value )})`} <rect x={offsetX + i * bucketWidth + barOffsetX} y="0" height={maxHeight} width={barWidth} class="hovd" use:tooltipAction={{ text: bucketTxt + valTxt, location: tooltipLocation, alignment: 'center', }} /> {/each} </g>