File size: 3,633 Bytes
3857bd9 fdb7c58 d088c21 fdb7c58 cd201c7 494bbae cd201c7 fdb7c58 d088c21 929d75e cd201c7 fdb7c58 cd201c7 3857bd9 98fcc8e 3857bd9 98fcc8e 3857bd9 98fcc8e 3857bd9 cd201c7 82437bb fbae805 82437bb 494bbae fdb7c58 d088c21 929d75e d088c21 929d75e fdb7c58 cd201c7 82437bb cd201c7 3857bd9 82437bb 3857bd9 cd201c7 3857bd9 cd201c7 fdb7c58 3857bd9 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
import React, { useEffect, useState } from "react";
import ActivityCalendar from "react-activity-calendar";
import { Tooltip, Avatar } from "@mui/material";
import Link from "next/link";
import { aggregateToWeeklyData } from "../utils/weeklyCalendar";
import WeeklyHeatmap from "./WeeklyHeatmap";
import { getHeatmapTheme, getHeatmapColorIntensity } from "../utils/heatmapColors";
type ViewMode = 'daily' | 'weekly';
type HeatmapProps = {
data: Array<{ date: string; count: number; level: number }>;
color: string;
providerName: string;
fullName: string;
avatarUrl: string;
authorId: string;
showHeader?: boolean;
viewMode: ViewMode;
};
const Heatmap: React.FC<HeatmapProps> = ({
data,
color,
providerName,
fullName,
avatarUrl,
authorId,
showHeader = true,
viewMode
}) => {
// Process data based on view mode
const processedData = viewMode === 'weekly' ? aggregateToWeeklyData(data) : data;
// Track theme state for proper ActivityCalendar theming
const [isDarkMode, setIsDarkMode] = useState(false);
useEffect(() => {
// Check initial theme
const checkTheme = () => {
setIsDarkMode(document.documentElement.classList.contains('dark'));
};
checkTheme();
// Watch for theme changes
const observer = new MutationObserver(checkTheme);
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['class']
});
return () => observer.disconnect();
}, []);
// Use theme-aware colors
const emptyColor = isDarkMode ? "#374151" : "#d1d5db";
// Create the correct color progression based on current theme
const getThemeAwareColors = () => {
const colors = [emptyColor]; // level 0
for (let level = 1; level <= 4; level++) {
const intensity = getHeatmapColorIntensity(level, color, isDarkMode);
if (intensity) {
colors.push(intensity);
}
}
return colors;
};
const themeColors = getThemeAwareColors();
return (
<div className="flex flex-col items-center w-full mx-auto">
{showHeader && (
<div className="flex flex-col sm:flex-row items-center mb-4 w-full justify-center">
{avatarUrl && (
<Avatar src={avatarUrl} alt={fullName} className="mb-2 sm:mb-0 sm:mr-4" sx={{ width: 48, height: 48 }} />
)}
<div className="text-center sm:text-left">
<h2 className="text-lg font-semibold">
<Link
href={`https://huggingface.co/${authorId}`}
target="_blank"
rel="noopener noreferrer"
className="hover:text-blue-500 hover:underline"
>
{fullName}
</Link>
</h2>
</div>
</div>
)}
<div className="w-full overflow-x-auto flex justify-center">
{viewMode === 'weekly' ? (
<WeeklyHeatmap data={processedData} color={color} />
) : (
<ActivityCalendar
key={`${isDarkMode}-${color}`} // Force re-render on theme change
data={processedData}
theme={{
light: themeColors,
dark: themeColors
}}
blockSize={11}
blockMargin={2}
hideTotalCount
renderBlock={(block, activity) => (
<Tooltip
title={`${activity.count} new repos on ${activity.date}`}
arrow
>
{block}
</Tooltip>
)}
/>
)}
</div>
</div>
);
};
export default Heatmap;
|