2 //= require cal-heatmap/dist/cal-heatmap
4 //= require cal-heatmap/dist/plugins/Tooltip
6 /* global CalHeatmap, Tooltip */
7 document.addEventListener("DOMContentLoaded", () => {
8 const heatmapElement = document.querySelector("#cal-heatmap");
10 if (!heatmapElement) {
14 const heatmapData = heatmapElement.dataset.heatmap ? JSON.parse(heatmapElement.dataset.heatmap) : [];
15 const displayName = heatmapElement.dataset.displayName;
16 const colorScheme = document.documentElement.getAttribute("data-bs-theme") ?? "auto";
17 const rangeColors = ["#14432a", "#166b34", "#37a446", "#4dd05a"];
18 const startDate = new Date(Date.now() - (365 * 24 * 60 * 60 * 1000));
19 const monthNames = OSM.i18n.t("date.abbr_month_names");
21 const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
23 let cal = new CalHeatmap();
24 let currentTheme = getTheme();
26 function renderHeatmap() {
28 cal = new CalHeatmap();
31 itemSelector: "#cal-heatmap",
37 text: (timestamp) => monthNames[new Date(timestamp).getUTCMonth() + 1],
41 dynamicDimension: true
63 range: currentTheme === "dark" ? rangeColors : Array.from(rangeColors).reverse(),
64 domain: [10, 20, 30, 40]
69 text: (date, value) => getTooltipText(date, value)
73 cal.on("mouseover", (event, _timestamp, value) => {
74 if (value) event.target.style.cursor = "pointer";
77 cal.on("click", (_event, timestamp) => {
78 if (!displayName) return;
79 for (const { date, max_id } of heatmapData) {
80 if (!max_id) continue;
81 if (timestamp !== Date.parse(date)) continue;
82 const params = new URLSearchParams([["before", max_id + 1]]);
83 location = `/user/${encodeURIComponent(displayName)}/history?${params}`;
88 function getTooltipText(date, value) {
89 const localizedDate = OSM.i18n.l("date.formats.long", date);
92 return OSM.i18n.t("javascripts.heatmap.tooltip.contributions", { count: value, date: localizedDate });
95 return OSM.i18n.t("javascripts.heatmap.tooltip.no_contributions", { date: localizedDate });
99 if (colorScheme === "auto") {
100 return mediaQuery.matches ? "dark" : "light";
106 if (colorScheme === "auto") {
107 mediaQuery.addEventListener("change", (e) => {
108 currentTheme = e.matches ? "dark" : "light";