{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"contribution-heatmap","type":"registry:component","title":"Contribution heatmap","description":"A year of activity at a glance, sweeping in week by week.","author":"Yash Bavadiya <https://xevrion.dev>","dependencies":["motion"],"registryDependencies":["utils"],"files":[{"path":"components/contribution-heatmap.tsx","type":"registry:component","content":"\"use client\";\n\nimport { memo, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { useInView } from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\nimport contributions from \"@/lib/contributions.json\";\n\n// `level` (0 to 4) overrides the thresholds, for data that arrives already\n// bucketed, like GitHub's own graph.\nexport type ContributionDay = { date: string; count: number; level?: number };\n\n// GitHub's own proportions: 10px squares on a 13px pitch.\nconst CELL = 10;\nconst PITCH = 13;\n// Per column, so the whole year sweeps in under half a second (53 x 8ms)\n// and reads as one left-to-right gesture rather than 53 separate ones.\nconst STAGGER_MS = 8;\n// One hue, light to dark: the foreground ink at rising opacity. Level 0\n// stays faintly visible so empty days still read as part of the grid.\nconst LEVELS = [\n  \"bg-foreground/[0.07]\",\n  \"bg-foreground/25\",\n  \"bg-foreground/45\",\n  \"bg-foreground/70\",\n  \"bg-foreground\",\n];\n// Lower bounds for levels 1 to 4.\nconst THRESHOLDS = [1, 4, 7, 10];\nconst EASE_OUT = \"ease-[cubic-bezier(0.23,1,0.32,1)]\";\n\nconst shortDate = new Intl.DateTimeFormat(\"en-US\", {\n  month: \"short\",\n  day: \"numeric\",\n  timeZone: \"UTC\",\n});\nconst longDate = new Intl.DateTimeFormat(\"en-US\", {\n  weekday: \"long\",\n  month: \"long\",\n  day: \"numeric\",\n  year: \"numeric\",\n  timeZone: \"UTC\",\n});\nconst monthName = new Intl.DateTimeFormat(\"en-US\", { month: \"short\", timeZone: \"UTC\" });\nconst number = new Intl.NumberFormat(\"en-US\");\n\nfunction phrase(count: number) {\n  if (count === 0) return \"No contributions\";\n  return `${number.format(count)} contribution${count === 1 ? \"\" : \"s\"}`;\n}\n\nfunction levelOf(count: number, thresholds: number[]) {\n  let level = 0;\n  for (const t of thresholds) if (count >= t) level++;\n  return level;\n}\n\n/**\n * `data` runs oldest to newest and starts on a Sunday, one entry per day,\n * so each column is one week.\n */\nexport function ContributionHeatmap({\n  data,\n  thresholds = THRESHOLDS,\n  className,\n}: {\n  data: ContributionDay[];\n  thresholds?: number[];\n  className?: string;\n}) {\n  const weeks = Math.ceil(data.length / 7);\n  const wrapRef = useRef<HTMLDivElement>(null);\n  const scrollRef = useRef<HTMLDivElement>(null);\n  const gridRef = useRef<HTMLDivElement>(null);\n  const tipRef = useRef<HTMLDivElement>(null);\n  const tipText = useRef<HTMLSpanElement>(null);\n  const inView = useInView(gridRef, { once: true, amount: 0.4 });\n  // Roving tabindex: the grid is one tab stop, arrows move within it.\n  const [focusIndex, setFocusIndex] = useState(data.length - 1);\n\n  const cells = useMemo(\n    () =>\n      data.map((d) => {\n        const date = new Date(`${d.date}T00:00:00Z`);\n        return {\n          level: d.level ?? levelOf(d.count, thresholds),\n          tip: `${phrase(d.count)} on ${shortDate.format(date)}`,\n          label: `${phrase(d.count)} on ${longDate.format(date)}`,\n          date,\n        };\n      }),\n    [data, thresholds],\n  );\n\n  // A month is labelled at the column holding its 1st. Labels closer than\n  // 3 columns would collide, so the earlier one gives way.\n  const months = useMemo(() => {\n    const out: { col: number; name: string }[] = [];\n    cells.forEach((cell, i) => {\n      if (cell.date.getUTCDate() !== 1) return;\n      const col = Math.floor(i / 7);\n      if (out.length && col - out[out.length - 1].col < 3) out.pop();\n      out.push({ col, name: monthName.format(cell.date) });\n    });\n    return out;\n  }, [cells]);\n\n  // On a narrow screen, open on the most recent weeks, the part people\n  // actually look at.\n  useLayoutEffect(() => {\n    const el = scrollRef.current;\n    if (el) el.scrollLeft = el.scrollWidth;\n  }, []);\n\n  // The tooltip is moved and rewritten directly, so sweeping across 371\n  // cells never re-renders them. It jumps with no transition: a tooltip\n  // that glides between cells lags behind the pointer.\n  const show = (el: HTMLElement) => {\n    const wrap = wrapRef.current;\n    const tip = tipRef.current;\n    const text = tipText.current;\n    const cell = cells[Number(el.dataset.i)];\n    if (!wrap || !tip || !text || !cell) return;\n    text.textContent = cell.tip;\n    const box = wrap.getBoundingClientRect();\n    const rect = el.getBoundingClientRect();\n    // Undo any scale an ancestor applies, like the index preview does.\n    const scale = wrap.offsetWidth / box.width || 1;\n    const width = tip.offsetWidth;\n    const centre = (rect.left - box.left + rect.width / 2) * scale;\n    // Clamped inside the chart so it never widens the page at the edges.\n    const x = Math.min(Math.max(centre - width / 2, 0), wrap.offsetWidth - width);\n    const y = (rect.top - box.top) * scale - tip.offsetHeight - 6;\n    tip.style.transform = `translate(${x}px, ${y}px)`;\n    tip.dataset.show = \"true\";\n  };\n  const hide = () => {\n    if (tipRef.current) tipRef.current.dataset.show = \"false\";\n  };\n\n  const cellFrom = (target: EventTarget) =>\n    (target as HTMLElement).closest<HTMLElement>(\"[data-i]\");\n\n  const move = (next: number) => {\n    const i = Math.min(Math.max(next, 0), data.length - 1);\n    setFocusIndex(i);\n    gridRef.current?.querySelector<HTMLElement>(`[data-i=\"${i}\"]`)?.focus();\n  };\n\n  return (\n    <div\n      ref={wrapRef}\n      // Sized to its content rather than a fixed width, so it only scrolls\n      // when the screen is genuinely too narrow for the year.\n      className={cn(\"relative flex w-fit max-w-full text-xs text-muted-foreground\", className)}\n    >\n      {/* Stays put while the weeks scroll, so rows keep their names. */}\n      <div aria-hidden className=\"mt-[23px] mr-[5px] flex shrink-0 flex-col\">\n        {[\"\", \"Mon\", \"\", \"Wed\", \"\", \"Fri\", \"\"].map((day, i) => (\n          <span key={i} style={{ height: PITCH, lineHeight: `${CELL}px` }}>\n            {day}\n          </span>\n        ))}\n      </div>\n\n      <div\n        ref={scrollRef}\n        // 3px of room on every side, so focus and hover rings aren't clipped\n        // by the scroll container.\n        className=\"min-w-0 flex-1 overflow-x-auto overscroll-x-contain p-[3px]\"\n        onScroll={hide}\n      >\n        <div style={{ width: weeks * PITCH - (PITCH - CELL) }}>\n          <div aria-hidden className=\"relative h-5\">\n            {months.map((m) => (\n              <span\n                key={m.col}\n                className=\"absolute top-0 leading-none\"\n                style={{ left: m.col * PITCH }}\n              >\n                {m.name}\n              </span>\n            ))}\n          </div>\n\n          <div\n            ref={gridRef}\n            role=\"grid\"\n            aria-label={`Contributions over the last ${weeks} weeks`}\n            aria-readonly\n            data-shown={inView}\n            className=\"group flex flex-col\"\n            style={{ gap: PITCH - CELL }}\n            onPointerOver={(e) => {\n              if (e.pointerType === \"touch\") return;\n              const el = cellFrom(e.target);\n              if (el) show(el);\n            }}\n            onPointerDown={(e) => {\n              if (e.pointerType !== \"touch\") return;\n              const el = cellFrom(e.target);\n              if (el) show(el);\n            }}\n            onPointerLeave={(e) => {\n              if (e.pointerType !== \"touch\") hide();\n            }}\n            onFocus={(e) => {\n              const el = cellFrom(e.target);\n              if (!el) return;\n              setFocusIndex(Number(el.dataset.i));\n              show(el);\n            }}\n            onBlur={(e) => {\n              if (!gridRef.current?.contains(e.relatedTarget as Node)) hide();\n            }}\n            onKeyDown={(e) => {\n              const el = cellFrom(e.target);\n              if (!el) return;\n              if (e.key === \"Escape\") return hide();\n              const i = Number(el.dataset.i);\n              const day = i % 7;\n              const next = {\n                ArrowUp: day > 0 ? i - 1 : i,\n                ArrowDown: day < 6 ? i + 1 : i,\n                ArrowLeft: i - 7,\n                ArrowRight: i + 7,\n                Home: day,\n                End: (weeks - 1) * 7 + day,\n              }[e.key];\n              if (next === undefined) return;\n              e.preventDefault();\n              move(next);\n            }}\n          >\n            {Array.from({ length: 7 }, (_, day) => (\n              <div key={day} role=\"row\" className=\"flex\" style={{ gap: PITCH - CELL }}>\n                {Array.from({ length: weeks }, (_, week) => {\n                  const i = week * 7 + day;\n                  const cell = cells[i];\n                  if (!cell) return <div key={week} role=\"presentation\" style={{ width: CELL }} />;\n                  return (\n                    <Cell\n                      key={week}\n                      index={i}\n                      column={week}\n                      level={cell.level}\n                      label={cell.label}\n                      focusable={i === focusIndex}\n                    />\n                  );\n                })}\n              </div>\n            ))}\n          </div>\n        </div>\n      </div>\n\n      {/* Appears in 100ms and leaves in 75ms, so it never lingers. */}\n      <div\n        ref={tipRef}\n        aria-hidden\n        data-show=\"false\"\n        className=\"pointer-events-none absolute top-0 left-0 z-10 opacity-0 transition-opacity duration-75 ease-out data-[show=true]:opacity-100 data-[show=true]:duration-100\"\n      >\n        <span\n          ref={tipText}\n          className=\"block rounded-md bg-foreground px-2 py-1 text-[13px] font-medium whitespace-nowrap text-background\"\n        />\n      </div>\n    </div>\n  );\n}\n\n// Memoised so moving focus re-renders only the two cells whose tabindex\n// changed, not all 371.\nconst Cell = memo(function Cell({\n  index,\n  column,\n  level,\n  label,\n  focusable,\n}: {\n  index: number;\n  column: number;\n  level: number;\n  label: string;\n  focusable: boolean;\n}) {\n  return (\n    <div\n      role=\"gridcell\"\n      data-i={index}\n      tabIndex={focusable ? 0 : -1}\n      aria-label={label}\n      className={cn(\n        \"shrink-0 rounded-[2px] focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-1 focus-visible:outline-foreground\",\n        // Rings the hovered day outside itself, so it shows on the darkest\n        // level too.\n        \"hover:outline-1 hover:outline-offset-1 hover:outline-foreground/50\",\n        // Settles from 0.6, not 0: a square growing from nothing reads as a\n        // pop, one settling from slightly small reads as arriving.\n        \"scale-[0.6] opacity-0 transition-[opacity,scale] duration-300 group-data-[shown=true]:scale-100 group-data-[shown=true]:opacity-100\",\n        \"motion-reduce:scale-100 motion-reduce:transition-none\",\n        EASE_OUT,\n        LEVELS[level],\n      )}\n      style={{ width: CELL, height: CELL, transitionDelay: `${column * STAGGER_MS}ms` }}\n    />\n  );\n});\n\nexport function HeatmapLegend({ className }: { className?: string }) {\n  return (\n    // Hidden from screen readers: every cell already names its own count.\n    <div aria-hidden className={cn(\"flex items-center gap-1 text-xs text-muted-foreground\", className)}>\n      <span className=\"mr-1\">Less</span>\n      {LEVELS.map((l) => (\n        <span\n          key={l}\n          aria-hidden\n          className={cn(\"rounded-[2px]\", l)}\n          style={{ width: CELL, height: CELL }}\n        />\n      ))}\n      <span className=\"ml-1\">More</span>\n    </div>\n  );\n}\n\n// Yash's real year, refreshed from his public GitHub graph on every build\n// by scripts/fetch-contributions.ts.\nconst YEAR: ContributionDay[] = contributions.days;\nconst TOTAL = YEAR.reduce((sum, d) => sum + d.count, 0);\n\nexport default function ContributionHeatmapDemo() {\n  return (\n    <div className=\"flex w-fit max-w-full flex-col gap-4\">\n      <p className=\"text-[15px] text-muted-foreground\">\n        <span className=\"font-semibold text-foreground tabular-nums\">{number.format(TOTAL)}</span>{\" \"}\n        contributions in the last year by{\" \"}\n        <a\n          href={`https://github.com/${contributions.user}`}\n          target=\"_blank\"\n          rel=\"noreferrer\"\n          className=\"rounded-sm font-medium text-foreground underline decoration-foreground/25 underline-offset-2 outline-hidden transition-[text-decoration-color] duration-150 ease-out hover:decoration-foreground focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-foreground\"\n        >\n          @{contributions.user}\n        </a>\n      </p>\n      <ContributionHeatmap data={YEAR} />\n      <HeatmapLegend className=\"self-end\" />\n    </div>\n  );\n}\n"},{"path":"lib/contributions.json","type":"registry:lib","target":"lib/contributions.json","content":"{\"user\":\"xevrion\",\"days\":[{\"date\":\"2025-09-28\",\"count\":0,\"level\":0},{\"date\":\"2025-09-29\",\"count\":0,\"level\":0},{\"date\":\"2025-09-30\",\"count\":0,\"level\":0},{\"date\":\"2025-10-01\",\"count\":0,\"level\":0},{\"date\":\"2025-10-02\",\"count\":0,\"level\":0},{\"date\":\"2025-10-03\",\"count\":5,\"level\":1},{\"date\":\"2025-10-04\",\"count\":10,\"level\":1},{\"date\":\"2025-10-05\",\"count\":0,\"level\":0},{\"date\":\"2025-10-06\",\"count\":0,\"level\":0},{\"date\":\"2025-10-07\",\"count\":1,\"level\":1},{\"date\":\"2025-10-08\",\"count\":0,\"level\":0},{\"date\":\"2025-10-09\",\"count\":1,\"level\":1},{\"date\":\"2025-10-10\",\"count\":0,\"level\":0},{\"date\":\"2025-10-11\",\"count\":2,\"level\":1},{\"date\":\"2025-10-12\",\"count\":7,\"level\":1},{\"date\":\"2025-10-13\",\"count\":0,\"level\":0},{\"date\":\"2025-10-14\",\"count\":2,\"level\":1},{\"date\":\"2025-10-15\",\"count\":0,\"level\":0},{\"date\":\"2025-10-16\",\"count\":0,\"level\":0},{\"date\":\"2025-10-17\",\"count\":0,\"level\":0},{\"date\":\"2025-10-18\",\"count\":0,\"level\":0},{\"date\":\"2025-10-19\",\"count\":1,\"level\":1},{\"date\":\"2025-10-20\",\"count\":1,\"level\":1},{\"date\":\"2025-10-21\",\"count\":2,\"level\":1},{\"date\":\"2025-10-22\",\"count\":0,\"level\":0},{\"date\":\"2025-10-23\",\"count\":6,\"level\":1},{\"date\":\"2025-10-24\",\"count\":0,\"level\":0},{\"date\":\"2025-10-25\",\"count\":3,\"level\":1},{\"date\":\"2025-10-26\",\"count\":2,\"level\":1},{\"date\":\"2025-10-27\",\"count\":1,\"level\":1},{\"date\":\"2025-10-28\",\"count\":0,\"level\":0},{\"date\":\"2025-10-29\",\"count\":2,\"level\":1},{\"date\":\"2025-10-30\",\"count\":1,\"level\":1},{\"date\":\"2025-10-31\",\"count\":12,\"level\":1},{\"date\":\"2025-11-01\",\"count\":8,\"level\":1},{\"date\":\"2025-11-02\",\"count\":11,\"level\":1},{\"date\":\"2025-11-03\",\"count\":11,\"level\":1},{\"date\":\"2025-11-04\",\"count\":4,\"level\":1},{\"date\":\"2025-11-05\",\"count\":9,\"level\":1},{\"date\":\"2025-11-06\",\"count\":14,\"level\":1},{\"date\":\"2025-11-07\",\"count\":0,\"level\":0},{\"date\":\"2025-11-08\",\"count\":12,\"level\":1},{\"date\":\"2025-11-09\",\"count\":26,\"level\":2},{\"date\":\"2025-11-10\",\"count\":7,\"level\":1},{\"date\":\"2025-11-11\",\"count\":1,\"level\":1},{\"date\":\"2025-11-12\",\"count\":2,\"level\":1},{\"date\":\"2025-11-13\",\"count\":7,\"level\":1},{\"date\":\"2025-11-14\",\"count\":1,\"level\":1},{\"date\":\"2025-11-15\",\"count\":2,\"level\":1},{\"date\":\"2025-11-16\",\"count\":1,\"level\":1},{\"date\":\"2025-11-17\",\"count\":7,\"level\":1},{\"date\":\"2025-11-18\",\"count\":4,\"level\":1},{\"date\":\"2025-11-19\",\"count\":0,\"level\":0},{\"date\":\"2025-11-20\",\"count\":0,\"level\":0},{\"date\":\"2025-11-21\",\"count\":0,\"level\":0},{\"date\":\"2025-11-22\",\"count\":0,\"level\":0},{\"date\":\"2025-11-23\",\"count\":0,\"level\":0},{\"date\":\"2025-11-24\",\"count\":1,\"level\":1},{\"date\":\"2025-11-25\",\"count\":0,\"level\":0},{\"date\":\"2025-11-26\",\"count\":9,\"level\":1},{\"date\":\"2025-11-27\",\"count\":12,\"level\":1},{\"date\":\"2025-11-28\",\"count\":7,\"level\":1},{\"date\":\"2025-11-29\",\"count\":3,\"level\":1},{\"date\":\"2025-11-30\",\"count\":19,\"level\":2},{\"date\":\"2025-12-01\",\"count\":7,\"level\":1},{\"date\":\"2025-12-02\",\"count\":23,\"level\":2},{\"date\":\"2025-12-03\",\"count\":4,\"level\":1},{\"date\":\"2025-12-04\",\"count\":17,\"level\":2},{\"date\":\"2025-12-05\",\"count\":46,\"level\":4},{\"date\":\"2025-12-06\",\"count\":12,\"level\":1},{\"date\":\"2025-12-07\",\"count\":27,\"level\":2},{\"date\":\"2025-12-08\",\"count\":0,\"level\":0},{\"date\":\"2025-12-09\",\"count\":0,\"level\":0},{\"date\":\"2025-12-10\",\"count\":17,\"level\":2},{\"date\":\"2025-12-11\",\"count\":3,\"level\":1},{\"date\":\"2025-12-12\",\"count\":14,\"level\":1},{\"date\":\"2025-12-13\",\"count\":4,\"level\":1},{\"date\":\"2025-12-14\",\"count\":2,\"level\":1},{\"date\":\"2025-12-15\",\"count\":30,\"level\":3},{\"date\":\"2025-12-16\",\"count\":0,\"level\":0},{\"date\":\"2025-12-17\",\"count\":4,\"level\":1},{\"date\":\"2025-12-18\",\"count\":1,\"level\":1},{\"date\":\"2025-12-19\",\"count\":8,\"level\":1},{\"date\":\"2025-12-20\",\"count\":8,\"level\":1},{\"date\":\"2025-12-21\",\"count\":0,\"level\":0},{\"date\":\"2025-12-22\",\"count\":6,\"level\":1},{\"date\":\"2025-12-23\",\"count\":3,\"level\":1},{\"date\":\"2025-12-24\",\"count\":10,\"level\":1},{\"date\":\"2025-12-25\",\"count\":3,\"level\":1},{\"date\":\"2025-12-26\",\"count\":6,\"level\":1},{\"date\":\"2025-12-27\",\"count\":4,\"level\":1},{\"date\":\"2025-12-28\",\"count\":2,\"level\":1},{\"date\":\"2025-12-29\",\"count\":2,\"level\":1},{\"date\":\"2025-12-30\",\"count\":5,\"level\":1},{\"date\":\"2025-12-31\",\"count\":0,\"level\":0},{\"date\":\"2026-01-01\",\"count\":1,\"level\":1},{\"date\":\"2026-01-02\",\"count\":7,\"level\":1},{\"date\":\"2026-01-03\",\"count\":0,\"level\":0},{\"date\":\"2026-01-04\",\"count\":4,\"level\":1},{\"date\":\"2026-01-05\",\"count\":4,\"level\":1},{\"date\":\"2026-01-06\",\"count\":2,\"level\":1},{\"date\":\"2026-01-07\",\"count\":3,\"level\":1},{\"date\":\"2026-01-08\",\"count\":14,\"level\":1},{\"date\":\"2026-01-09\",\"count\":3,\"level\":1},{\"date\":\"2026-01-10\",\"count\":26,\"level\":2},{\"date\":\"2026-01-11\",\"count\":34,\"level\":3},{\"date\":\"2026-01-12\",\"count\":42,\"level\":3},{\"date\":\"2026-01-13\",\"count\":2,\"level\":1},{\"date\":\"2026-01-14\",\"count\":0,\"level\":0},{\"date\":\"2026-01-15\",\"count\":1,\"level\":1},{\"date\":\"2026-01-16\",\"count\":1,\"level\":1},{\"date\":\"2026-01-17\",\"count\":0,\"level\":0},{\"date\":\"2026-01-18\",\"count\":2,\"level\":1},{\"date\":\"2026-01-19\",\"count\":2,\"level\":1},{\"date\":\"2026-01-20\",\"count\":1,\"level\":1},{\"date\":\"2026-01-21\",\"count\":3,\"level\":1},{\"date\":\"2026-01-22\",\"count\":2,\"level\":1},{\"date\":\"2026-01-23\",\"count\":0,\"level\":0},{\"date\":\"2026-01-24\",\"count\":6,\"level\":1},{\"date\":\"2026-01-25\",\"count\":21,\"level\":2},{\"date\":\"2026-01-26\",\"count\":25,\"level\":2},{\"date\":\"2026-01-27\",\"count\":30,\"level\":3},{\"date\":\"2026-01-28\",\"count\":23,\"level\":2},{\"date\":\"2026-01-29\",\"count\":4,\"level\":1},{\"date\":\"2026-01-30\",\"count\":0,\"level\":0},{\"date\":\"2026-01-31\",\"count\":4,\"level\":1},{\"date\":\"2026-02-01\",\"count\":9,\"level\":1},{\"date\":\"2026-02-02\",\"count\":2,\"level\":1},{\"date\":\"2026-02-03\",\"count\":1,\"level\":1},{\"date\":\"2026-02-04\",\"count\":1,\"level\":1},{\"date\":\"2026-02-05\",\"count\":14,\"level\":1},{\"date\":\"2026-02-06\",\"count\":6,\"level\":1},{\"date\":\"2026-02-07\",\"count\":2,\"level\":1},{\"date\":\"2026-02-08\",\"count\":1,\"level\":1},{\"date\":\"2026-02-09\",\"count\":1,\"level\":1},{\"date\":\"2026-02-10\",\"count\":14,\"level\":1},{\"date\":\"2026-02-11\",\"count\":4,\"level\":1},{\"date\":\"2026-02-12\",\"count\":4,\"level\":1},{\"date\":\"2026-02-13\",\"count\":4,\"level\":1},{\"date\":\"2026-02-14\",\"count\":9,\"level\":1},{\"date\":\"2026-02-15\",\"count\":3,\"level\":1},{\"date\":\"2026-02-16\",\"count\":4,\"level\":1},{\"date\":\"2026-02-17\",\"count\":5,\"level\":1},{\"date\":\"2026-02-18\",\"count\":5,\"level\":1},{\"date\":\"2026-02-19\",\"count\":6,\"level\":1},{\"date\":\"2026-02-20\",\"count\":28,\"level\":2},{\"date\":\"2026-02-21\",\"count\":4,\"level\":1},{\"date\":\"2026-02-22\",\"count\":1,\"level\":1},{\"date\":\"2026-02-23\",\"count\":0,\"level\":0},{\"date\":\"2026-02-24\",\"count\":7,\"level\":1},{\"date\":\"2026-02-25\",\"count\":12,\"level\":1},{\"date\":\"2026-02-26\",\"count\":4,\"level\":1},{\"date\":\"2026-02-27\",\"count\":22,\"level\":2},{\"date\":\"2026-02-28\",\"count\":37,\"level\":3},{\"date\":\"2026-03-01\",\"count\":7,\"level\":1},{\"date\":\"2026-03-02\",\"count\":8,\"level\":1},{\"date\":\"2026-03-03\",\"count\":18,\"level\":2},{\"date\":\"2026-03-04\",\"count\":9,\"level\":1},{\"date\":\"2026-03-05\",\"count\":5,\"level\":1},{\"date\":\"2026-03-06\",\"count\":19,\"level\":2},{\"date\":\"2026-03-07\",\"count\":8,\"level\":1},{\"date\":\"2026-03-08\",\"count\":6,\"level\":1},{\"date\":\"2026-03-09\",\"count\":15,\"level\":2},{\"date\":\"2026-03-10\",\"count\":4,\"level\":1},{\"date\":\"2026-03-11\",\"count\":4,\"level\":1},{\"date\":\"2026-03-12\",\"count\":41,\"level\":3},{\"date\":\"2026-03-13\",\"count\":12,\"level\":1},{\"date\":\"2026-03-14\",\"count\":7,\"level\":1},{\"date\":\"2026-03-15\",\"count\":5,\"level\":1},{\"date\":\"2026-03-16\",\"count\":1,\"level\":1},{\"date\":\"2026-03-17\",\"count\":4,\"level\":1},{\"date\":\"2026-03-18\",\"count\":37,\"level\":3},{\"date\":\"2026-03-19\",\"count\":5,\"level\":1},{\"date\":\"2026-03-20\",\"count\":4,\"level\":1},{\"date\":\"2026-03-21\",\"count\":9,\"level\":1},{\"date\":\"2026-03-22\",\"count\":32,\"level\":3},{\"date\":\"2026-03-23\",\"count\":34,\"level\":3},{\"date\":\"2026-03-24\",\"count\":15,\"level\":2},{\"date\":\"2026-03-25\",\"count\":18,\"level\":2},{\"date\":\"2026-03-26\",\"count\":28,\"level\":2},{\"date\":\"2026-03-27\",\"count\":3,\"level\":1},{\"date\":\"2026-03-28\",\"count\":2,\"level\":1},{\"date\":\"2026-03-29\",\"count\":2,\"level\":1},{\"date\":\"2026-03-30\",\"count\":4,\"level\":1},{\"date\":\"2026-03-31\",\"count\":9,\"level\":1},{\"date\":\"2026-04-01\",\"count\":7,\"level\":1},{\"date\":\"2026-04-02\",\"count\":5,\"level\":1},{\"date\":\"2026-04-03\",\"count\":12,\"level\":1},{\"date\":\"2026-04-04\",\"count\":3,\"level\":1},{\"date\":\"2026-04-05\",\"count\":24,\"level\":2},{\"date\":\"2026-04-06\",\"count\":50,\"level\":4},{\"date\":\"2026-04-07\",\"count\":8,\"level\":1},{\"date\":\"2026-04-08\",\"count\":7,\"level\":1},{\"date\":\"2026-04-09\",\"count\":12,\"level\":1},{\"date\":\"2026-04-10\",\"count\":23,\"level\":2},{\"date\":\"2026-04-11\",\"count\":45,\"level\":4},{\"date\":\"2026-04-12\",\"count\":7,\"level\":1},{\"date\":\"2026-04-13\",\"count\":7,\"level\":1},{\"date\":\"2026-04-14\",\"count\":29,\"level\":2},{\"date\":\"2026-04-15\",\"count\":6,\"level\":1},{\"date\":\"2026-04-16\",\"count\":26,\"level\":2},{\"date\":\"2026-04-17\",\"count\":36,\"level\":3},{\"date\":\"2026-04-18\",\"count\":34,\"level\":3},{\"date\":\"2026-04-19\",\"count\":10,\"level\":1},{\"date\":\"2026-04-20\",\"count\":35,\"level\":3},{\"date\":\"2026-04-21\",\"count\":11,\"level\":1},{\"date\":\"2026-04-22\",\"count\":4,\"level\":1},{\"date\":\"2026-04-23\",\"count\":3,\"level\":1},{\"date\":\"2026-04-24\",\"count\":2,\"level\":1},{\"date\":\"2026-04-25\",\"count\":38,\"level\":3},{\"date\":\"2026-04-26\",\"count\":9,\"level\":1},{\"date\":\"2026-04-27\",\"count\":4,\"level\":1},{\"date\":\"2026-04-28\",\"count\":6,\"level\":1},{\"date\":\"2026-04-29\",\"count\":4,\"level\":1},{\"date\":\"2026-04-30\",\"count\":22,\"level\":2},{\"date\":\"2026-05-01\",\"count\":8,\"level\":1},{\"date\":\"2026-05-02\",\"count\":1,\"level\":1},{\"date\":\"2026-05-03\",\"count\":5,\"level\":1},{\"date\":\"2026-05-04\",\"count\":2,\"level\":1},{\"date\":\"2026-05-05\",\"count\":5,\"level\":1},{\"date\":\"2026-05-06\",\"count\":10,\"level\":1},{\"date\":\"2026-05-07\",\"count\":3,\"level\":1},{\"date\":\"2026-05-08\",\"count\":6,\"level\":1},{\"date\":\"2026-05-09\",\"count\":6,\"level\":1},{\"date\":\"2026-05-10\",\"count\":3,\"level\":1},{\"date\":\"2026-05-11\",\"count\":5,\"level\":1},{\"date\":\"2026-05-12\",\"count\":7,\"level\":1},{\"date\":\"2026-05-13\",\"count\":11,\"level\":1},{\"date\":\"2026-05-14\",\"count\":9,\"level\":1},{\"date\":\"2026-05-15\",\"count\":3,\"level\":1},{\"date\":\"2026-05-16\",\"count\":0,\"level\":0},{\"date\":\"2026-05-17\",\"count\":4,\"level\":1},{\"date\":\"2026-05-18\",\"count\":6,\"level\":1},{\"date\":\"2026-05-19\",\"count\":3,\"level\":1},{\"date\":\"2026-05-20\",\"count\":8,\"level\":1},{\"date\":\"2026-05-21\",\"count\":3,\"level\":1},{\"date\":\"2026-05-22\",\"count\":2,\"level\":1},{\"date\":\"2026-05-23\",\"count\":14,\"level\":1},{\"date\":\"2026-05-24\",\"count\":7,\"level\":1},{\"date\":\"2026-05-25\",\"count\":9,\"level\":1},{\"date\":\"2026-05-26\",\"count\":11,\"level\":1},{\"date\":\"2026-05-27\",\"count\":9,\"level\":1},{\"date\":\"2026-05-28\",\"count\":8,\"level\":1},{\"date\":\"2026-05-29\",\"count\":0,\"level\":0},{\"date\":\"2026-05-30\",\"count\":8,\"level\":1},{\"date\":\"2026-05-31\",\"count\":6,\"level\":1},{\"date\":\"2026-06-01\",\"count\":6,\"level\":1},{\"date\":\"2026-06-02\",\"count\":0,\"level\":0},{\"date\":\"2026-06-03\",\"count\":8,\"level\":1},{\"date\":\"2026-06-04\",\"count\":6,\"level\":1},{\"date\":\"2026-06-05\",\"count\":36,\"level\":3},{\"date\":\"2026-06-06\",\"count\":34,\"level\":3},{\"date\":\"2026-06-07\",\"count\":8,\"level\":1},{\"date\":\"2026-06-08\",\"count\":6,\"level\":1},{\"date\":\"2026-06-09\",\"count\":3,\"level\":1},{\"date\":\"2026-06-10\",\"count\":2,\"level\":1},{\"date\":\"2026-06-11\",\"count\":5,\"level\":1},{\"date\":\"2026-06-12\",\"count\":13,\"level\":1},{\"date\":\"2026-06-13\",\"count\":38,\"level\":3},{\"date\":\"2026-06-14\",\"count\":4,\"level\":1},{\"date\":\"2026-06-15\",\"count\":13,\"level\":1},{\"date\":\"2026-06-16\",\"count\":27,\"level\":2},{\"date\":\"2026-06-17\",\"count\":29,\"level\":2},{\"date\":\"2026-06-18\",\"count\":17,\"level\":2},{\"date\":\"2026-06-19\",\"count\":4,\"level\":1},{\"date\":\"2026-06-20\",\"count\":44,\"level\":4},{\"date\":\"2026-06-21\",\"count\":12,\"level\":1},{\"date\":\"2026-06-22\",\"count\":12,\"level\":1},{\"date\":\"2026-06-23\",\"count\":8,\"level\":1},{\"date\":\"2026-06-24\",\"count\":31,\"level\":3},{\"date\":\"2026-06-25\",\"count\":41,\"level\":3},{\"date\":\"2026-06-26\",\"count\":49,\"level\":4},{\"date\":\"2026-06-27\",\"count\":35,\"level\":3},{\"date\":\"2026-06-28\",\"count\":6,\"level\":1},{\"date\":\"2026-06-29\",\"count\":13,\"level\":1},{\"date\":\"2026-06-30\",\"count\":14,\"level\":1},{\"date\":\"2026-07-01\",\"count\":2,\"level\":1},{\"date\":\"2026-07-02\",\"count\":4,\"level\":1},{\"date\":\"2026-07-03\",\"count\":27,\"level\":2},{\"date\":\"2026-07-04\",\"count\":12,\"level\":1},{\"date\":\"2026-07-05\",\"count\":2,\"level\":1},{\"date\":\"2026-07-06\",\"count\":2,\"level\":1},{\"date\":\"2026-07-07\",\"count\":20,\"level\":2},{\"date\":\"2026-07-08\",\"count\":12,\"level\":1},{\"date\":\"2026-07-09\",\"count\":3,\"level\":1},{\"date\":\"2026-07-10\",\"count\":8,\"level\":1},{\"date\":\"2026-07-11\",\"count\":1,\"level\":1},{\"date\":\"2026-07-12\",\"count\":3,\"level\":1},{\"date\":\"2026-07-13\",\"count\":36,\"level\":3},{\"date\":\"2026-07-14\",\"count\":18,\"level\":2},{\"date\":\"2026-07-15\",\"count\":17,\"level\":2},{\"date\":\"2026-07-16\",\"count\":3,\"level\":1},{\"date\":\"2026-07-17\",\"count\":2,\"level\":1},{\"date\":\"2026-07-18\",\"count\":35,\"level\":3},{\"date\":\"2026-07-19\",\"count\":4,\"level\":1},{\"date\":\"2026-07-20\",\"count\":75,\"level\":4},{\"date\":\"2026-07-21\",\"count\":24,\"level\":2},{\"date\":\"2026-07-22\",\"count\":25,\"level\":2},{\"date\":\"2026-07-23\",\"count\":26,\"level\":2},{\"date\":\"2026-07-24\",\"count\":5,\"level\":1},{\"date\":\"2026-07-25\",\"count\":24,\"level\":2},{\"date\":\"2026-07-26\",\"count\":5,\"level\":1},{\"date\":\"2026-07-27\",\"count\":28,\"level\":2},{\"date\":\"2026-07-28\",\"count\":15,\"level\":2},{\"date\":\"2026-07-29\",\"count\":6,\"level\":1},{\"date\":\"2026-07-30\",\"count\":22,\"level\":2},{\"date\":\"2026-07-31\",\"count\":30,\"level\":3},{\"date\":\"2026-08-01\",\"count\":13,\"level\":1},{\"date\":\"2026-08-02\",\"count\":1,\"level\":1},{\"date\":\"2026-08-03\",\"count\":1,\"level\":1},{\"date\":\"2026-08-04\",\"count\":4,\"level\":1},{\"date\":\"2026-08-05\",\"count\":7,\"level\":1},{\"date\":\"2026-08-06\",\"count\":1,\"level\":1},{\"date\":\"2026-08-07\",\"count\":19,\"level\":2},{\"date\":\"2026-08-08\",\"count\":3,\"level\":1},{\"date\":\"2026-08-09\",\"count\":10,\"level\":1},{\"date\":\"2026-08-10\",\"count\":10,\"level\":1},{\"date\":\"2026-08-11\",\"count\":4,\"level\":1},{\"date\":\"2026-08-12\",\"count\":29,\"level\":2},{\"date\":\"2026-08-13\",\"count\":4,\"level\":1},{\"date\":\"2026-08-14\",\"count\":9,\"level\":1},{\"date\":\"2026-08-15\",\"count\":21,\"level\":2},{\"date\":\"2026-08-16\",\"count\":1,\"level\":1},{\"date\":\"2026-08-17\",\"count\":1,\"level\":1},{\"date\":\"2026-08-18\",\"count\":21,\"level\":2},{\"date\":\"2026-08-19\",\"count\":7,\"level\":1},{\"date\":\"2026-08-20\",\"count\":6,\"level\":1},{\"date\":\"2026-08-21\",\"count\":9,\"level\":1},{\"date\":\"2026-08-22\",\"count\":1,\"level\":1},{\"date\":\"2026-08-23\",\"count\":36,\"level\":3},{\"date\":\"2026-08-24\",\"count\":0,\"level\":0},{\"date\":\"2026-08-25\",\"count\":30,\"level\":3},{\"date\":\"2026-08-26\",\"count\":8,\"level\":1},{\"date\":\"2026-08-27\",\"count\":0,\"level\":0},{\"date\":\"2026-08-28\",\"count\":87,\"level\":4},{\"date\":\"2026-08-29\",\"count\":34,\"level\":3},{\"date\":\"2026-08-30\",\"count\":13,\"level\":1},{\"date\":\"2026-08-31\",\"count\":14,\"level\":1},{\"date\":\"2026-09-01\",\"count\":2,\"level\":1},{\"date\":\"2026-09-02\",\"count\":3,\"level\":1},{\"date\":\"2026-09-03\",\"count\":5,\"level\":1},{\"date\":\"2026-09-04\",\"count\":19,\"level\":2},{\"date\":\"2026-09-05\",\"count\":2,\"level\":1},{\"date\":\"2026-09-06\",\"count\":22,\"level\":2},{\"date\":\"2026-09-07\",\"count\":0,\"level\":0},{\"date\":\"2026-09-08\",\"count\":26,\"level\":2},{\"date\":\"2026-09-09\",\"count\":3,\"level\":1},{\"date\":\"2026-09-10\",\"count\":13,\"level\":1},{\"date\":\"2026-09-11\",\"count\":8,\"level\":1},{\"date\":\"2026-09-12\",\"count\":35,\"level\":3},{\"date\":\"2026-09-13\",\"count\":6,\"level\":1},{\"date\":\"2026-09-14\",\"count\":42,\"level\":3},{\"date\":\"2026-09-15\",\"count\":47,\"level\":4},{\"date\":\"2026-09-16\",\"count\":2,\"level\":1},{\"date\":\"2026-09-17\",\"count\":2,\"level\":1},{\"date\":\"2026-09-18\",\"count\":1,\"level\":1},{\"date\":\"2026-09-19\",\"count\":0,\"level\":0},{\"date\":\"2026-09-20\",\"count\":26,\"level\":2},{\"date\":\"2026-09-21\",\"count\":28,\"level\":2},{\"date\":\"2026-09-22\",\"count\":28,\"level\":2},{\"date\":\"2026-09-23\",\"count\":36,\"level\":3},{\"date\":\"2026-09-24\",\"count\":17,\"level\":2},{\"date\":\"2026-09-25\",\"count\":6,\"level\":1},{\"date\":\"2026-09-26\",\"count\":58,\"level\":4},{\"date\":\"2026-09-27\",\"count\":17,\"level\":2},{\"date\":\"2026-09-28\",\"count\":11,\"level\":1},{\"date\":\"2026-09-29\",\"count\":4,\"level\":1},{\"date\":\"2026-09-30\",\"count\":0,\"level\":0},{\"date\":\"2026-10-01\",\"count\":17,\"level\":2}]}\n"}],"categories":["data"],"docs":"From ui lab: https://lab.xevrion.dev/lab/contribution-heatmap"}