{"spec_id":"heatmap-annotated","library":"muix","language":"javascript","code":"// anyplot.ai\n// heatmap-annotated: Annotated Heatmap\n// Library: muix 7.29.1 | JavaScript 22.23.1\n// Quality: 90/100 | Created: 2026-08-05\n//# anyplot-orientation: square\n// anyplot.ai\n// heatmap-annotated: Annotated Heatmap\n// Library: MUI X Charts | React | Node 22\n// License: @mui/x-charts — MIT (community). Pro/Premium are out of scope.\n// Quality: pending | Created: 2026-08-05\n\nimport { ChartContainer } from \"@mui/x-charts/ChartContainer\";\nimport { ChartsXAxis } from \"@mui/x-charts/ChartsXAxis\";\nimport { ChartsYAxis } from \"@mui/x-charts/ChartsYAxis\";\nimport { useDrawingArea, useXScale, useYScale } from \"@mui/x-charts/hooks\";\n\nconst t = window.ANYPLOT_TOKENS;\nconst W = window.ANYPLOT_SIZE.width;\nconst H = window.ANYPLOT_SIZE.height;\nconst FONT = \"system-ui, -apple-system, sans-serif\";\nconst TITLE = \"heatmap-annotated · javascript · muix · anyplot.ai\";\n\n// --- Data: Pearson correlation matrix across daily wellness metrics --------\nconst VARIABLES = [\"Sleep\", \"Exercise\", \"Screen Time\", \"Stress\", \"Water\", \"Steps\", \"Mood\"];\n\n// Symmetric 7x7 matrix, diagonal = 1.00 (self-correlation)\nconst CORRELATIONS = [\n  [1.0, 0.35, -0.42, -0.58, 0.22, 0.31, 0.61],\n  [0.35, 1.0, -0.28, -0.33, 0.45, 0.82, 0.57],\n  [-0.42, -0.28, 1.0, 0.49, -0.18, -0.39, -0.44],\n  [-0.58, -0.33, 0.49, 1.0, -0.15, -0.36, -0.71],\n  [0.22, 0.45, -0.18, -0.15, 1.0, 0.28, 0.19],\n  [0.31, 0.82, -0.39, -0.36, 0.28, 1.0, 0.52],\n  [0.61, 0.57, -0.44, -0.71, 0.19, 0.52, 1.0],\n];\n\n// --- Diverging color scale (Imprint imprint_div: red -> midpoint -> blue) --\nfunction hexToRgb(hex) {\n  const v = parseInt(hex.replace(\"#\", \"\"), 16);\n  return [(v >> 16) & 255, (v >> 8) & 255, v & 255];\n}\nconst lerp = (a, b, f) => a + (b - a) * f;\n\nfunction divergingRgb(value) {\n  const [r0, g0, b0] = hexToRgb(t.div[0]); // -1 anchor (matte red)\n  const [r1, g1, b1] = hexToRgb(t.div[1]); // 0 anchor (theme midpoint)\n  const [r2, g2, b2] = hexToRgb(t.div[2]); // +1 anchor (blue)\n  const [ra, ga, ba] = value <= 0 ? [r0, g0, b0] : [r1, g1, b1];\n  const [rb, gb, bb] = value <= 0 ? [r1, g1, b1] : [r2, g2, b2];\n  const f = value <= 0 ? value + 1 : value;\n  return [lerp(ra, rb, f), lerp(ga, gb, f), lerp(ba, bb, f)].map(Math.round);\n}\n\n// Auto-contrast annotation text: dark ink on pale cells, light ink on saturated cells\nfunction contrastText([r, g, b]) {\n  const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n  return luminance > 0.55 ? \"#1A1A17\" : \"#FFFDF6\";\n}\n\n// --- Heatmap cells: colored rects + value annotations -----------------------\nfunction HeatmapCells() {\n  const xScale = useXScale(\"vars_x\");\n  const yScale = useYScale(\"vars_y\");\n  if (!xScale?.bandwidth || !yScale?.bandwidth) return null;\n  const bw = xScale.bandwidth();\n  const bh = yScale.bandwidth();\n  return (\n    <g>\n      {CORRELATIONS.map((row, ri) =>\n        row.map((value, ci) => {\n          const x0 = xScale(VARIABLES[ci]);\n          const y0 = yScale(VARIABLES[ri]);\n          if (x0 === undefined || y0 === undefined) return null;\n          const rgb = divergingRgb(value);\n          return (\n            <g key={`${ri}-${ci}`}>\n              <rect\n                x={x0 + 2} y={y0 + 2}\n                width={bw - 4} height={bh - 4}\n                fill={`rgb(${rgb.join(\",\")})`} rx={4}\n              />\n              <text\n                x={x0 + bw / 2} y={y0 + bh / 2 + 7}\n                textAnchor=\"middle\" fontSize={20} fontWeight=\"600\"\n                fill={contrastText(rgb)} fontFamily={FONT}\n              >\n                {value.toFixed(2)}\n              </text>\n            </g>\n          );\n        }),\n      )}\n    </g>\n  );\n}\n\n// Diverging colorbar legend in the right margin\nfunction Colorbar() {\n  const { left, top, width, height } = useDrawingArea();\n  const barX = left + width + 26;\n  const ticks = [-1, -0.5, 0, 0.5, 1];\n  return (\n    <g>\n      <defs>\n        <linearGradient id=\"divGrad\" x1=\"0\" y1=\"1\" x2=\"0\" y2=\"0\">\n          <stop offset=\"0%\" stopColor={t.div[0]} />\n          <stop offset=\"50%\" stopColor={t.div[1]} />\n          <stop offset=\"100%\" stopColor={t.div[2]} />\n        </linearGradient>\n      </defs>\n      <text\n        x={barX + 9} y={top - 14}\n        textAnchor=\"middle\" fontSize={13} fill={t.inkSoft} fontFamily={FONT}\n      >\n        Pearson r\n      </text>\n      <rect x={barX} y={top} width={18} height={height} fill=\"url(#divGrad)\" rx={3} />\n      {ticks.map((tick) => {\n        const ty = top + height * (1 - (tick + 1) / 2);\n        return (\n          <g key={tick}>\n            <line x1={barX + 18} y1={ty} x2={barX + 25} y2={ty} stroke={t.inkSoft} strokeWidth={1} />\n            <text x={barX + 30} y={ty + 4} fontSize={12} fill={t.inkSoft} fontFamily={FONT}>\n              {tick.toFixed(1)}\n            </text>\n          </g>\n        );\n      })}\n    </g>\n  );\n}\n\nfunction ChartTitle() {\n  return (\n    <text x={W / 2} y={38} textAnchor=\"middle\" fontSize={22} fontWeight=\"500\" fill={t.ink} fontFamily={FONT}>\n      {TITLE}\n    </text>\n  );\n}\n\nexport default function Chart() {\n  const margin = { left: 150, top: 74, right: 110, bottom: 96 };\n\n  return (\n    <ChartContainer\n      width={W}\n      height={H}\n      margin={margin}\n      series={[]}\n      skipAnimation\n      xAxis={[{ id: \"vars_x\", scaleType: \"band\", data: VARIABLES, categoryGapRatio: 0.04 }]}\n      yAxis={[{ id: \"vars_y\", scaleType: \"band\", data: VARIABLES, categoryGapRatio: 0.04 }]}\n    >\n      <ChartTitle />\n      <HeatmapCells />\n      <Colorbar />\n      <ChartsXAxis\n        axisId=\"vars_x\"\n        tickLabelStyle={{ fontSize: 14, fill: t.inkSoft, fontFamily: FONT }}\n      />\n      <ChartsYAxis\n        axisId=\"vars_y\"\n        tickLabelStyle={{ fontSize: 14, fill: t.inkSoft, fontFamily: FONT }}\n      />\n    </ChartContainer>\n  );\n}\n"}