import { getHeatmapCellColor } from "@/src/features/score-analytics/lib/color-scales"; import { cn } from "@/src/utils/tailwind"; import { useState } from "react"; import chroma from "chroma-js"; export interface HeatmapLegendProps { min: number; max: number; scoreNumber?: 1 | 2; title?: string; className?: string; orientation?: "horizontal" | "vertical"; steps?: number; } /** * Check if a color is light/white (similar to empty cells) * @param color - Hex color string * @returns true if color is light (lightness > 85%) */ function isLightColor(color: string): boolean { try { const lightness = chroma(color).get("hsl.l"); return lightness > 0.85; // 85% threshold } catch { return false; } } export function HeatmapLegend({ min, max, scoreNumber = 1, title, className, orientation = "horizontal", steps = 5, }: HeatmapLegendProps) { const [hoveredIdx, setHoveredIdx] = useState(null); // Generate colors using the same function as the heatmap cells const colors = Array.from({ length: steps }, (_, i) => { const value = min + ((max - min) * i) / (steps - 1); return getHeatmapCellColor(scoreNumber, value, min, max); }); // Generate labels const labels = Array.from({ length: steps }, (_, i) => { const value = min + ((max - min) * i) / (steps - 1); return value.toFixed(0); }); if (orientation === "vertical") { return (
{title && (
{title}
)}
{colors .slice() .reverse() .map((color, idx) => { const labelIdx = steps - 1 - idx; const isHovered = hoveredIdx === idx; const isLight = isLightColor(color); return (
setHoveredIdx(idx)} onMouseLeave={() => setHoveredIdx(null)} /> {labels[labelIdx]}
); })}
); } // Horizontal orientation return (
{min}
{colors.map((color, idx) => { const isHovered = hoveredIdx === idx; const isLight = isLightColor(color); return (
setHoveredIdx(idx)} onMouseLeave={() => setHoveredIdx(null)} /> ); })}
{max}
); }