{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "activity-heatmap",
  "type": "registry:ui",
  "title": "ActivityHeatmap",
  "description": "نقشهٔ فعالیت سالانه با ماه‌های شمسی؛ هفته از شنبه شروع می‌شود",
  "dependencies": [
    "@kashi-ui/persian@^1.8.0"
  ],
  "registryDependencies": [
    "https://kashi.sepantapouya.com/r/chart.json",
    "https://kashi.sepantapouya.com/r/cx.json",
    "https://kashi.sepantapouya.com/r/kashi-provider.json"
  ],
  "files": [
    {
      "path": "registry/kashi/ActivityHeatmap.tsx",
      "type": "registry:ui",
      "target": "components/kashi/ActivityHeatmap.tsx",
      "content": "\"use client\";\n\nimport { JALALI_MONTHS, formatJalali, formatNumber, jalaliMonthLength, toGregorian, toISODate, toJalali } from \"@kashi-ui/persian\";\nimport { useRef, useState } from \"react\";\nimport { cx } from \"./cx\";\nimport { ChartTip } from \"./Chart\";\nimport { useKashi } from \"./KashiProvider\";\n\nexport interface ActivityHeatmapProps {\n  /** تعداد فعالیت در هر روز؛ کلید تاریخ میلادی YYYY-MM-DD */\n  data: Record<string, number>;\n  /** سال شمسی @default سال جاری */\n  year?: number;\n  /** نام دسترس‌پذیر، مثل «فعالیت تیم در سال ۱۴۰۵» */\n  label?: string;\n  /** واحد در راهنما @default «فعالیت» */\n  unit?: string;\n  className?: string;\n}\n\n\n/** نقشهٔ فعالیت سالانه با ماه‌های شمسی؛ هفته از شنبه شروع می‌شود */\nexport function ActivityHeatmap({ data, year = toJalali(new Date()).jy, label, unit, className }: ActivityHeatmapProps) {\n  const { messages: M, digits: D, locale, n, months: MONTHS } = useKashi();\n  const H = M.heatmap;\n  const num = (v: number) => formatNumber(v, { digits: D });\n  unit ??= H.unit;\n  const days: { date: Date; value: number }[] = [];\n  for (let m = 1; m <= 12; m++) for (let d = 1; d <= jalaliMonthLength(year, m); d++) {\n    const date = toGregorian(year, m, d);\n    days.push({ date, value: data[toISODate(date)] ?? 0 });\n  }\n  const max = Math.max(0, ...days.map((d) => d.value));\n  const level = (v: number) => (v <= 0 || max === 0 ? 0 : Math.max(1, Math.ceil((v / max) * 4)));\n  // شنبه سطر اول\n  const row = (d: Date) => (d.getDay() + 1) % 7;\n  const offset = row(days[0].date);\n  const col = (i: number) => Math.floor((i + offset) / 7);\n  const monthStarts = MONTHS.map((name, m) => ({ name, col: col(days.findIndex((d) => toJalali(d.date).jm === m + 1)) }));\n  const total = days.reduce((s, d) => s + d.value, 0);\n  const monthly = MONTHS.map((name, m) => ({ name, sum: days.filter((d) => toJalali(d.date).jm === m + 1).reduce((s, d) => s + d.value, 0) }));\n  const box = useRef<HTMLElement>(null);\n  const [tip, setTip] = useState<{ x: number; y: number; i: number } | null>(null);\n  const name = label ?? H.inYear(unit, n(year));\n\n  return (\n    <figure ref={box} className={cx(\"k-heatmap\", className)} style={{ margin: 0 }} onPointerLeave={() => setTip(null)}>\n      <div className=\"k-heatmap__scroll\">\n        <div role=\"img\" aria-label={`${name}: ${num(total)} ${unit}`}>\n          <div className=\"k-heatmap__months\" aria-hidden=\"true\">\n            {monthStarts.map((m) => <span key={m.name} style={{ gridColumn: m.col + 1 }}>{m.name}</span>)}\n          </div>\n          <div className=\"k-heatmap__body\" aria-hidden=\"true\">\n            <div className=\"k-heatmap__days\">{H.weekdays.map((w, i) => <span key={i}>{w}</span>)}</div>\n            <div\n              className=\"k-heatmap__grid\"\n              onPointerOver={(e) => {\n                const cell = (e.target as HTMLElement).closest<HTMLElement>(\"[data-i]\");\n                if (!cell || !box.current) return setTip(null);\n                const b = box.current.getBoundingClientRect(), r = cell.getBoundingClientRect();\n                setTip({ x: r.left + r.width / 2 - b.left, y: r.top - b.top - 2, i: Number(cell.dataset.i) });\n              }}\n            >\n              {Array.from({ length: offset }, (_, i) => <span key={`e${i}`} className=\"k-heatmap__cell\" data-empty=\"\" />)}\n              {days.map((d, i) => (\n                <span key={d.date.getTime()} className=\"k-heatmap__cell\" data-l={level(d.value)} data-i={i} data-active={tip?.i === i ? \"\" : undefined} />\n              ))}\n            </div>\n          </div>\n        </div>\n      </div>\n      {tip && <ChartTip x={tip.x} y={tip.y} width={box.current?.clientWidth} title={formatJalali(days[tip.i].date, { style: \"full\", digits: D, locale })} rows={[{ value: `${num(days[tip.i].value)} ${unit}` }]} />}\n      <figcaption className=\"k-heatmap__foot\">\n        <span>{H.total(num(total), unit, n(year))}</span>\n        <span className=\"k-heatmap__scale\" aria-hidden=\"true\">{H.less} {[0, 1, 2, 3, 4].map((l) => <span key={l} className=\"k-heatmap__cell\" data-l={l} />)} {H.more}</span>\n      </figcaption>\n      <table className=\"k-sr-only\">\n        <caption>{H.byMonth(name)}</caption>\n        <tbody>{monthly.map((m) => <tr key={m.name}><th scope=\"row\">{m.name}</th><td>{num(m.sum)}</td></tr>)}</tbody>\n      </table>\n    </figure>\n  );\n}\n"
    }
  ]
}