git-contri-merged
Version:
A React component to display merged GitHub contribution graphs from multiple contributors
1,082 lines (1,081 loc) • 35.6 kB
JavaScript
import { jsxs as S, jsx as f, Fragment as yt } from "react/jsx-runtime";
import { useState as M, useRef as wt, useCallback as bt, useEffect as xt, useMemo as Ct } from "react";
function St(t, e) {
if (t.match(/^[a-z]+:\/\//i))
return t;
if (t.match(/^\/\//))
return window.location.protocol + t;
if (t.match(/^[a-z]+:/i))
return t;
const n = document.implementation.createHTMLDocument(), r = n.createElement("base"), i = n.createElement("a");
return n.head.appendChild(r), n.body.appendChild(i), e && (r.href = e), i.href = t, i.href;
}
const vt = /* @__PURE__ */ (() => {
let t = 0;
const e = () => (
// eslint-disable-next-line no-bitwise
`0000${(Math.random() * 36 ** 4 << 0).toString(36)}`.slice(-4)
);
return () => (t += 1, `u${e()}${t}`);
})();
function $(t) {
const e = [];
for (let n = 0, r = t.length; n < r; n++)
e.push(t[n]);
return e;
}
let F = null;
function et(t = {}) {
return F || (t.includeStyleProperties ? (F = t.includeStyleProperties, F) : (F = $(window.getComputedStyle(document.documentElement)), F));
}
function U(t, e) {
const r = (t.ownerDocument.defaultView || window).getComputedStyle(t).getPropertyValue(e);
return r ? parseFloat(r.replace("px", "")) : 0;
}
function Et(t) {
const e = U(t, "border-left-width"), n = U(t, "border-right-width");
return t.clientWidth + e + n;
}
function $t(t) {
const e = U(t, "border-top-width"), n = U(t, "border-bottom-width");
return t.clientHeight + e + n;
}
function nt(t, e = {}) {
const n = e.width || Et(t), r = e.height || $t(t);
return { width: n, height: r };
}
function Rt() {
let t, e;
try {
e = process;
} catch {
}
const n = e && e.env ? e.env.devicePixelRatio : null;
return n && (t = parseInt(n, 10), Number.isNaN(t) && (t = 1)), t || window.devicePixelRatio || 1;
}
const C = 16384;
function Dt(t) {
(t.width > C || t.height > C) && (t.width > C && t.height > C ? t.width > t.height ? (t.height *= C / t.width, t.width = C) : (t.width *= C / t.height, t.height = C) : t.width > C ? (t.height *= C / t.width, t.width = C) : (t.width *= C / t.height, t.height = C));
}
function O(t) {
return new Promise((e, n) => {
const r = new Image();
r.onload = () => {
r.decode().then(() => {
requestAnimationFrame(() => e(r));
});
}, r.onerror = n, r.crossOrigin = "anonymous", r.decoding = "async", r.src = t;
});
}
async function Tt(t) {
return Promise.resolve().then(() => new XMLSerializer().serializeToString(t)).then(encodeURIComponent).then((e) => `data:image/svg+xml;charset=utf-8,${e}`);
}
async function Ft(t, e, n) {
const r = "http://www.w3.org/2000/svg", i = document.createElementNS(r, "svg"), o = document.createElementNS(r, "foreignObject");
return i.setAttribute("width", `${e}`), i.setAttribute("height", `${n}`), i.setAttribute("viewBox", `0 0 ${e} ${n}`), o.setAttribute("width", "100%"), o.setAttribute("height", "100%"), o.setAttribute("x", "0"), o.setAttribute("y", "0"), o.setAttribute("externalResourcesRequired", "true"), i.appendChild(o), o.appendChild(t), Tt(i);
}
const w = (t, e) => {
if (t instanceof e)
return !0;
const n = Object.getPrototypeOf(t);
return n === null ? !1 : n.constructor.name === e.name || w(n, e);
};
function kt(t) {
const e = t.getPropertyValue("content");
return `${t.cssText} content: '${e.replace(/'|"/g, "")}';`;
}
function Lt(t, e) {
return et(e).map((n) => {
const r = t.getPropertyValue(n), i = t.getPropertyPriority(n);
return `${n}: ${r}${i ? " !important" : ""};`;
}).join(" ");
}
function Pt(t, e, n, r) {
const i = `.${t}:${e}`, o = n.cssText ? kt(n) : Lt(n, r);
return document.createTextNode(`${i}{${o}}`);
}
function z(t, e, n, r) {
const i = window.getComputedStyle(t, n), o = i.getPropertyValue("content");
if (o === "" || o === "none")
return;
const s = vt();
try {
e.className = `${e.className} ${s}`;
} catch {
return;
}
const a = document.createElement("style");
a.appendChild(Pt(s, n, i, r)), e.appendChild(a);
}
function It(t, e, n) {
z(t, e, ":before", n), z(t, e, ":after", n);
}
const J = "application/font-woff", X = "image/jpeg", At = {
woff: J,
woff2: J,
ttf: "application/font-truetype",
eot: "application/vnd.ms-fontobject",
png: "image/png",
jpg: X,
jpeg: X,
gif: "image/gif",
tiff: "image/tiff",
svg: "image/svg+xml",
webp: "image/webp"
};
function Mt(t) {
const e = /\.([^./]*?)$/g.exec(t);
return e ? e[1] : "";
}
function V(t) {
const e = Mt(t).toLowerCase();
return At[e] || "";
}
function Ut(t) {
return t.split(/,/)[1];
}
function B(t) {
return t.search(/^(data:)/) !== -1;
}
function Ot(t, e) {
return `data:${e};base64,${t}`;
}
async function rt(t, e, n) {
const r = await fetch(t, e);
if (r.status === 404)
throw new Error(`Resource "${r.url}" not found`);
const i = await r.blob();
return new Promise((o, s) => {
const a = new FileReader();
a.onerror = s, a.onloadend = () => {
try {
o(n({ res: r, result: a.result }));
} catch (c) {
s(c);
}
}, a.readAsDataURL(i);
});
}
const j = {};
function Ht(t, e, n) {
let r = t.replace(/\?.*/, "");
return n && (r = t), /ttf|otf|eot|woff2?/i.test(r) && (r = r.replace(/.*\//, "")), e ? `[${e}]${r}` : r;
}
async function _(t, e, n) {
const r = Ht(t, e, n.includeQueryParams);
if (j[r] != null)
return j[r];
n.cacheBust && (t += (/\?/.test(t) ? "&" : "?") + (/* @__PURE__ */ new Date()).getTime());
let i;
try {
const o = await rt(t, n.fetchRequestInit, ({ res: s, result: a }) => (e || (e = s.headers.get("Content-Type") || ""), Ut(a)));
i = Ot(o, e);
} catch (o) {
i = n.imagePlaceholder || "";
let s = `Failed to fetch resource: ${t}`;
o && (s = typeof o == "string" ? o : o.message), s && console.warn(s);
}
return j[r] = i, i;
}
async function Wt(t) {
const e = t.toDataURL();
return e === "data:," ? t.cloneNode(!1) : O(e);
}
async function jt(t, e) {
if (t.currentSrc) {
const o = document.createElement("canvas"), s = o.getContext("2d");
o.width = t.clientWidth, o.height = t.clientHeight, s == null || s.drawImage(t, 0, 0, o.width, o.height);
const a = o.toDataURL();
return O(a);
}
const n = t.poster, r = V(n), i = await _(n, r, e);
return O(i);
}
async function Bt(t, e) {
var n;
try {
if (!((n = t == null ? void 0 : t.contentDocument) === null || n === void 0) && n.body)
return await H(t.contentDocument.body, e, !0);
} catch {
}
return t.cloneNode(!1);
}
async function Vt(t, e) {
return w(t, HTMLCanvasElement) ? Wt(t) : w(t, HTMLVideoElement) ? jt(t, e) : w(t, HTMLIFrameElement) ? Bt(t, e) : t.cloneNode(ot(t));
}
const _t = (t) => t.tagName != null && t.tagName.toUpperCase() === "SLOT", ot = (t) => t.tagName != null && t.tagName.toUpperCase() === "SVG";
async function Gt(t, e, n) {
var r, i;
if (ot(e))
return e;
let o = [];
return _t(t) && t.assignedNodes ? o = $(t.assignedNodes()) : w(t, HTMLIFrameElement) && (!((r = t.contentDocument) === null || r === void 0) && r.body) ? o = $(t.contentDocument.body.childNodes) : o = $(((i = t.shadowRoot) !== null && i !== void 0 ? i : t).childNodes), o.length === 0 || w(t, HTMLVideoElement) || await o.reduce((s, a) => s.then(() => H(a, n)).then((c) => {
c && e.appendChild(c);
}), Promise.resolve()), e;
}
function qt(t, e, n) {
const r = e.style;
if (!r)
return;
const i = window.getComputedStyle(t);
i.cssText ? (r.cssText = i.cssText, r.transformOrigin = i.transformOrigin) : et(n).forEach((o) => {
let s = i.getPropertyValue(o);
o === "font-size" && s.endsWith("px") && (s = `${Math.floor(parseFloat(s.substring(0, s.length - 2))) - 0.1}px`), w(t, HTMLIFrameElement) && o === "display" && s === "inline" && (s = "block"), o === "d" && e.getAttribute("d") && (s = `path(${e.getAttribute("d")})`), r.setProperty(o, s, i.getPropertyPriority(o));
});
}
function Yt(t, e) {
w(t, HTMLTextAreaElement) && (e.innerHTML = t.value), w(t, HTMLInputElement) && e.setAttribute("value", t.value);
}
function zt(t, e) {
if (w(t, HTMLSelectElement)) {
const n = e, r = Array.from(n.children).find((i) => t.value === i.getAttribute("value"));
r && r.setAttribute("selected", "");
}
}
function Jt(t, e, n) {
return w(e, Element) && (qt(t, e, n), It(t, e, n), Yt(t, e), zt(t, e)), e;
}
async function Xt(t, e) {
const n = t.querySelectorAll ? t.querySelectorAll("use") : [];
if (n.length === 0)
return t;
const r = {};
for (let o = 0; o < n.length; o++) {
const a = n[o].getAttribute("xlink:href");
if (a) {
const c = t.querySelector(a), h = document.querySelector(a);
!c && h && !r[a] && (r[a] = await H(h, e, !0));
}
}
const i = Object.values(r);
if (i.length) {
const o = "http://www.w3.org/1999/xhtml", s = document.createElementNS(o, "svg");
s.setAttribute("xmlns", o), s.style.position = "absolute", s.style.width = "0", s.style.height = "0", s.style.overflow = "hidden", s.style.display = "none";
const a = document.createElementNS(o, "defs");
s.appendChild(a);
for (let c = 0; c < i.length; c++)
a.appendChild(i[c]);
t.appendChild(s);
}
return t;
}
async function H(t, e, n) {
return !n && e.filter && !e.filter(t) ? null : Promise.resolve(t).then((r) => Vt(r, e)).then((r) => Gt(t, r, e)).then((r) => Jt(t, r, e)).then((r) => Xt(r, e));
}
const it = /url\((['"]?)([^'"]+?)\1\)/g, Kt = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g, Qt = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;
function Zt(t) {
const e = t.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1");
return new RegExp(`(url\\(['"]?)(${e})(['"]?\\))`, "g");
}
function Nt(t) {
const e = [];
return t.replace(it, (n, r, i) => (e.push(i), n)), e.filter((n) => !B(n));
}
async function te(t, e, n, r, i) {
try {
const o = n ? St(e, n) : e, s = V(e);
let a;
return i || (a = await _(o, s, r)), t.replace(Zt(e), `$1${a}$3`);
} catch {
}
return t;
}
function ee(t, { preferredFontFormat: e }) {
return e ? t.replace(Qt, (n) => {
for (; ; ) {
const [r, , i] = Kt.exec(n) || [];
if (!i)
return "";
if (i === e)
return `src: ${r};`;
}
}) : t;
}
function st(t) {
return t.search(it) !== -1;
}
async function at(t, e, n) {
if (!st(t))
return t;
const r = ee(t, n);
return Nt(r).reduce((o, s) => o.then((a) => te(a, s, e, n)), Promise.resolve(r));
}
async function k(t, e, n) {
var r;
const i = (r = e.style) === null || r === void 0 ? void 0 : r.getPropertyValue(t);
if (i) {
const o = await at(i, null, n);
return e.style.setProperty(t, o, e.style.getPropertyPriority(t)), !0;
}
return !1;
}
async function ne(t, e) {
await k("background", t, e) || await k("background-image", t, e), await k("mask", t, e) || await k("-webkit-mask", t, e) || await k("mask-image", t, e) || await k("-webkit-mask-image", t, e);
}
async function re(t, e) {
const n = w(t, HTMLImageElement);
if (!(n && !B(t.src)) && !(w(t, SVGImageElement) && !B(t.href.baseVal)))
return;
const r = n ? t.src : t.href.baseVal, i = await _(r, V(r), e);
await new Promise((o, s) => {
t.onload = o, t.onerror = e.onImageErrorHandler ? (...c) => {
try {
o(e.onImageErrorHandler(...c));
} catch (h) {
s(h);
}
} : s;
const a = t;
a.decode && (a.decode = o), a.loading === "lazy" && (a.loading = "eager"), n ? (t.srcset = "", t.src = i) : t.href.baseVal = i;
});
}
async function oe(t, e) {
const r = $(t.childNodes).map((i) => ct(i, e));
await Promise.all(r).then(() => t);
}
async function ct(t, e) {
w(t, Element) && (await ne(t, e), await re(t, e), await oe(t, e));
}
function ie(t, e) {
const { style: n } = t;
e.backgroundColor && (n.backgroundColor = e.backgroundColor), e.width && (n.width = `${e.width}px`), e.height && (n.height = `${e.height}px`);
const r = e.style;
return r != null && Object.keys(r).forEach((i) => {
n[i] = r[i];
}), t;
}
const K = {};
async function Q(t) {
let e = K[t];
if (e != null)
return e;
const r = await (await fetch(t)).text();
return e = { url: t, cssText: r }, K[t] = e, e;
}
async function Z(t, e) {
let n = t.cssText;
const r = /url\(["']?([^"')]+)["']?\)/g, o = (n.match(/url\([^)]+\)/g) || []).map(async (s) => {
let a = s.replace(r, "$1");
return a.startsWith("https://") || (a = new URL(a, t.url).href), rt(a, e.fetchRequestInit, ({ result: c }) => (n = n.replace(s, `url(${c})`), [s, c]));
});
return Promise.all(o).then(() => n);
}
function N(t) {
if (t == null)
return [];
const e = [], n = /(\/\*[\s\S]*?\*\/)/gi;
let r = t.replace(n, "");
const i = new RegExp("((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})", "gi");
for (; ; ) {
const c = i.exec(r);
if (c === null)
break;
e.push(c[0]);
}
r = r.replace(i, "");
const o = /@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi, s = "((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})", a = new RegExp(s, "gi");
for (; ; ) {
let c = o.exec(r);
if (c === null) {
if (c = a.exec(r), c === null)
break;
o.lastIndex = a.lastIndex;
} else
a.lastIndex = o.lastIndex;
e.push(c[0]);
}
return e;
}
async function se(t, e) {
const n = [], r = [];
return t.forEach((i) => {
if ("cssRules" in i)
try {
$(i.cssRules || []).forEach((o, s) => {
if (o.type === CSSRule.IMPORT_RULE) {
let a = s + 1;
const c = o.href, h = Q(c).then((d) => Z(d, e)).then((d) => N(d).forEach((l) => {
try {
i.insertRule(l, l.startsWith("@import") ? a += 1 : i.cssRules.length);
} catch (g) {
console.error("Error inserting rule from remote css", {
rule: l,
error: g
});
}
})).catch((d) => {
console.error("Error loading remote css", d.toString());
});
r.push(h);
}
});
} catch (o) {
const s = t.find((a) => a.href == null) || document.styleSheets[0];
i.href != null && r.push(Q(i.href).then((a) => Z(a, e)).then((a) => N(a).forEach((c) => {
s.insertRule(c, s.cssRules.length);
})).catch((a) => {
console.error("Error loading remote stylesheet", a);
})), console.error("Error inlining remote css file", o);
}
}), Promise.all(r).then(() => (t.forEach((i) => {
if ("cssRules" in i)
try {
$(i.cssRules || []).forEach((o) => {
n.push(o);
});
} catch (o) {
console.error(`Error while reading CSS rules from ${i.href}`, o);
}
}), n));
}
function ae(t) {
return t.filter((e) => e.type === CSSRule.FONT_FACE_RULE).filter((e) => st(e.style.getPropertyValue("src")));
}
async function ce(t, e) {
if (t.ownerDocument == null)
throw new Error("Provided element is not within a Document");
const n = $(t.ownerDocument.styleSheets), r = await se(n, e);
return ae(r);
}
function lt(t) {
return t.trim().replace(/["']/g, "");
}
function le(t) {
const e = /* @__PURE__ */ new Set();
function n(r) {
(r.style.fontFamily || getComputedStyle(r).fontFamily).split(",").forEach((o) => {
e.add(lt(o));
}), Array.from(r.children).forEach((o) => {
o instanceof HTMLElement && n(o);
});
}
return n(t), e;
}
async function ue(t, e) {
const n = await ce(t, e), r = le(t);
return (await Promise.all(n.filter((o) => r.has(lt(o.style.fontFamily))).map((o) => {
const s = o.parentStyleSheet ? o.parentStyleSheet.href : null;
return at(o.cssText, s, e);
}))).join(`
`);
}
async function fe(t, e) {
const n = e.fontEmbedCSS != null ? e.fontEmbedCSS : e.skipFonts ? null : await ue(t, e);
if (n) {
const r = document.createElement("style"), i = document.createTextNode(n);
r.appendChild(i), t.firstChild ? t.insertBefore(r, t.firstChild) : t.appendChild(r);
}
}
async function he(t, e = {}) {
const { width: n, height: r } = nt(t, e), i = await H(t, e, !0);
return await fe(i, e), await ct(i, e), ie(i, e), await Ft(i, n, r);
}
async function de(t, e = {}) {
const { width: n, height: r } = nt(t, e), i = await he(t, e), o = await O(i), s = document.createElement("canvas"), a = s.getContext("2d"), c = e.pixelRatio || Rt(), h = e.canvasWidth || n, d = e.canvasHeight || r;
return s.width = h * c, s.height = d * c, e.skipAutoScale || Dt(s), s.style.width = `${h}`, s.style.height = `${d}`, e.backgroundColor && (a.fillStyle = e.backgroundColor, a.fillRect(0, 0, s.width, s.height)), a.drawImage(o, 0, 0, s.width, s.height), s;
}
async function ge(t, e = {}) {
return (await de(t, e)).toDataURL();
}
async function me(t, e, n) {
var c, h, d;
const r = (/* @__PURE__ */ new Date()).getFullYear(), i = e || r, o = `${i}-01-01T00:00:00Z`, s = `${i}-12-31T23:59:59Z`, a = `
query($username: String!, $from: DateTime!, $to: DateTime!) {
user(login: $username) {
contributionsCollection(from: $from, to: $to) {
contributionCalendar {
totalContributions
weeks {
contributionDays {
date
contributionCount
color
}
}
}
}
}
viewer {
login
contributionsCollection(from: $from, to: $to) {
contributionCalendar {
totalContributions
weeks {
contributionDays {
date
contributionCount
color
}
}
}
}
}
}
`;
try {
const l = {
"Content-Type": "application/json"
};
n && (l.Authorization = `Bearer ${n}`);
const g = await fetch("https://api.github.com/graphql", {
method: "POST",
headers: l,
body: JSON.stringify({
query: a,
variables: { username: t, from: o, to: s }
})
});
if (!g.ok)
throw new Error(`GitHub API error: ${g.statusText}`);
const u = await g.json();
if (u.errors && (!u.errors.find((v) => v.message.includes("Could not resolve to a User")) || !((c = u.data) != null && c.viewer)))
throw new Error(`GraphQL errors: ${JSON.stringify(u.errors)}`);
let m;
if ((h = u.data) != null && h.viewer && u.data.viewer.login.toLowerCase() === t.toLowerCase())
m = u.data.viewer.contributionsCollection.contributionCalendar;
else if ((d = u.data) != null && d.user)
m = u.data.user.contributionsCollection.contributionCalendar;
else
throw new Error(`User ${t} not found`);
const b = [], R = m.weeks;
for (const D of R)
for (const v of D.contributionDays)
b.push({
date: v.date,
count: v.contributionCount,
level: we(v.contributionCount)
});
return b;
} catch (l) {
throw console.error(`Error fetching contributions for ${t}:`, l), l;
}
}
async function pe(t, e, n) {
const r = /* @__PURE__ */ new Map(), i = (/* @__PURE__ */ new Date()).getFullYear(), o = e || [i];
for (const s of t)
try {
const a = [];
for (const c of o) {
const h = await me(s, c, n);
a.push(...h);
}
r.set(s, a);
} catch (a) {
console.error(`Failed to fetch contributions for ${s}:`, a);
}
return r;
}
async function ye(t, e) {
try {
const [n, r] = t.split("/");
if (!n || !r)
throw new Error('Invalid repository name. Format should be "owner/repo"');
const i = [];
let o = 1;
const s = 100;
for (; ; ) {
const a = {
Accept: "application/vnd.github.v3+json"
};
e && (a.Authorization = `Bearer ${e}`);
const c = await fetch(
`https://api.github.com/repos/${n}/${r}/contributors?per_page=${s}&page=${o}`,
{ headers: a }
);
if (!c.ok)
throw new Error(`GitHub API error: ${c.statusText}`);
const h = await c.json();
if (h.length === 0)
break;
for (const d of h)
d.login && d.type === "User" && i.push(d.login);
if (h.length < s)
break;
o++;
}
return i;
} catch (n) {
throw console.error(`Error fetching contributors for ${t}:`, n), n;
}
}
function we(t) {
return t === 0 ? 0 : t <= 3 ? 1 : t <= 6 ? 2 : t <= 9 ? 3 : 4;
}
function be(t) {
const e = /* @__PURE__ */ new Map(), n = {};
for (const [i, o] of t.entries())
for (const s of o) {
const c = (e.get(s.date) || 0) + s.count;
e.set(s.date, c);
const h = new Date(s.date).getFullYear();
n[h] = (n[h] || 0) + s.count;
}
const r = Array.from(e.entries()).map(([i, o]) => ({
date: i,
count: o,
level: xe(o)
})).sort((i, o) => new Date(i.date).getTime() - new Date(o.date).getTime());
return {
total: n,
contributions: r
};
}
function xe(t) {
return t === 0 ? 0 : t <= 5 ? 1 : t <= 10 ? 2 : t <= 15 ? 3 : 4;
}
function ut(t, e, n) {
const r = [], i = new Map(
t.map((s) => [s.date, s])
), o = new Date(e);
for (; o <= n; ) {
const s = o.toISOString().split("T")[0], a = i.get(s);
a ? r.push(a) : r.push({
date: s,
count: 0,
level: 0
}), o.setDate(o.getDate() + 1);
}
return r;
}
function Ce(t) {
if (t.length === 0) {
const n = /* @__PURE__ */ new Date(), r = /* @__PURE__ */ new Date();
return r.setFullYear(r.getFullYear() - 1), { start: r, end: n };
}
const e = t.map((n) => new Date(n.date));
return {
start: new Date(Math.min(...e.map((n) => n.getTime()))),
end: new Date(Math.max(...e.map((n) => n.getTime())))
};
}
function Se(t) {
if (t.length === 0) return [];
const e = [];
let n = [];
const r = new Date(t[0].date), i = r.getDay();
for (let o = 0; o < i; o++) {
const s = new Date(r);
s.setDate(s.getDate() - (i - o)), n.push({
date: s.toISOString().split("T")[0],
count: 0,
level: 0
});
}
for (const o of t)
n.push(o), n.length === 7 && (e.push(n), n = []);
if (n.length > 0) {
const o = new Date(n[n.length - 1].date);
for (; n.length < 7; )
o.setDate(o.getDate() + 1), n.push({
date: o.toISOString().split("T")[0],
count: 0,
level: 0
});
e.push(n);
}
return e;
}
const ve = {
level0: "#ebedf0",
level1: "#9be9a8",
level2: "#40c463",
level3: "#30a14e",
level4: "#216e39",
text: "#24292f",
background: "#ffffff"
}, Ee = {
level0: "#161b22",
level1: "#0e4429",
level2: "#006d32",
level3: "#26a641",
level4: "#39d353",
text: "#c9d1d9",
background: "#0d1117"
};
function ft(t) {
return t === "light" ? ve : Ee;
}
const $e = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], tt = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], ht = ({
contributions: t,
theme: e,
blockSize: n = 12,
blockMargin: r = 3,
showWeekdayLabels: i = !0,
showMonthLabels: o = !0
}) => {
const s = Se(t), a = (l) => e[`level${l}`], c = (l) => {
if (!o || l >= s.length) return null;
const g = s[l][0], m = new Date(g.date).getMonth();
if (l === 0)
return tt[m];
const b = s[l - 1][0], D = new Date(b.date).getMonth();
return m !== D ? tt[m] : null;
}, d = i ? 30 : 0;
return /* @__PURE__ */ S(
"svg",
{
width: d + s.length * (n + r) + r,
height: o ? 7 * (n + r) + 30 : 7 * (n + r) + 10,
style: { fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' },
children: [
o && /* @__PURE__ */ f("g", { transform: `translate(${d}, 0)`, children: (() => {
const l = [];
if (s.forEach((g, u) => {
const m = c(u);
m && l.push({
x: u * (n + r),
label: m
});
}), l.length > 1) {
const g = l[0], u = l[1], m = 2 * (n + r);
u.x - g.x < m && l.shift();
}
return l.map((g, u) => /* @__PURE__ */ f(
"text",
{
x: g.x,
y: 10,
fontSize: "10",
fill: e.text,
children: g.label
},
`month-${u}-${g.label}`
));
})() }),
i && /* @__PURE__ */ f("g", { transform: `translate(0, ${o ? 20 : 0})`, children: [1, 3, 5].map((l) => /* @__PURE__ */ f(
"text",
{
x: 0,
y: l * (n + r) + n,
fontSize: "9",
fill: e.text,
textAnchor: "start",
children: $e[l]
},
`weekday-${l}`
)) }),
/* @__PURE__ */ f("g", { transform: `translate(${d}, ${o ? 20 : 0})`, children: s.map(
(l, g) => l.map((u, m) => {
const b = g * (n + r), R = m * (n + r);
return /* @__PURE__ */ f(
"rect",
{
x: b,
y: R,
width: n,
height: n,
rx: 2,
ry: 2,
fill: a(u.level),
"data-date": u.date,
"data-count": u.count,
children: /* @__PURE__ */ f("title", { children: `${u.date}: ${u.count} contribution${u.count !== 1 ? "s" : ""}` })
},
`${u.date}`
);
})
) })
]
}
);
}, Te = (t) => {
const {
years: e,
colorScheme: n = "light",
blockSize: r = 12,
blockMargin: i = 3,
fontSize: o = 14,
showWeekdayLabels: s = !0,
showMonthLabels: a = !0,
loading: c,
error: h,
githubToken: d,
onDataLoad: l,
onContributorsLoad: g
} = t, [u, m] = M(null), [b, R] = M([]), [D, v] = M(!0), [G, q] = M(null), P = wt(null), p = ft(n), L = "usernames" in t ? t.usernames : void 0, E = "repoName" in t ? t.repoName : void 0, dt = bt(async () => {
if (P.current !== null)
try {
const y = await ge(P.current, {
cacheBust: !0,
filter: (T) => {
var A;
return !((A = T.classList) != null && A.contains("download-btn"));
},
backgroundColor: p.background,
style: {
display: "inline-block",
height: "auto"
}
}), x = document.createElement("a");
x.download = `${E || "merged-contributions"}.png`, x.href = y, x.click();
} catch (y) {
console.error("Failed to download image", y);
}
}, [P, E, p.background]);
if (xt(() => {
(L || E) && (async () => {
try {
v(!0), q(null);
let x = [];
if (E) {
const W = await ye(E, d);
x = W, R(W), g == null || g(W);
} else L && (x = L, R(L));
if (x.length === 0) {
v(!1);
return;
}
const T = await pe(x, e, d), I = be(T), { start: A, end: mt } = Ce(I.contributions), pt = ut(I.contributions, A, mt), Y = {
...I,
contributions: pt
};
m(Y), l == null || l(Y);
} catch (x) {
const T = x instanceof Error ? x : new Error("Failed to load contributions");
q(T), console.error("Error loading contributions:", T);
} finally {
v(!1);
}
})();
}, [L, E, e, l, g, d]), D)
return c ? /* @__PURE__ */ f(yt, { children: c }) : /* @__PURE__ */ f("div", { style: { padding: "20px", color: p.text }, children: "Loading contributions..." });
if (G)
return /* @__PURE__ */ f("div", { style: { padding: "20px", color: p.text }, children: h || `Error: ${G.message}` });
if (!u || u.contributions.length === 0)
return /* @__PURE__ */ f("div", { style: { padding: "20px", color: p.text }, children: "No contributions found" });
const gt = Object.values(u.total).reduce(
(y, x) => y + x,
0
);
return /* @__PURE__ */ S(
"div",
{
ref: P,
style: {
padding: "20px",
backgroundColor: p.background,
borderRadius: "6px",
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
},
children: [
/* @__PURE__ */ S("div", { style: { marginBottom: "16px", display: "flex", justifyContent: "space-between", alignItems: "flex-start" }, children: [
/* @__PURE__ */ S("div", { children: [
/* @__PURE__ */ f("h3", { style: { margin: "0 0 8px 0", color: p.text, fontSize: o }, children: E ? `${E} - Merged Contributions` : "Merged Contributions" }),
/* @__PURE__ */ S("div", { style: { color: p.text, fontSize: o - 2, opacity: 0.8 }, children: [
b.length,
" contributor",
b.length !== 1 ? "s" : "",
" • ",
gt,
" total contributions"
] }),
/* @__PURE__ */ f("div", { style: { color: p.text, fontSize: o - 3, opacity: 0.6, marginTop: "4px" }, children: b.length <= 10 ? b.join(", ") : `${b.slice(0, 10).join(", ")} and ${b.length - 10} more` })
] }),
/* @__PURE__ */ S(
"button",
{
className: "download-btn",
onClick: dt,
style: {
background: "transparent",
border: `1px solid ${p.text}`,
borderRadius: "4px",
cursor: "pointer",
padding: "6px 10px",
color: p.text,
opacity: 0.7,
display: "flex",
alignItems: "center",
gap: "6px",
fontSize: o - 2,
transition: "all 0.2s ease"
},
onMouseEnter: (y) => {
y.currentTarget.style.opacity = "1", y.currentTarget.style.backgroundColor = p.text + "10";
},
onMouseLeave: (y) => {
y.currentTarget.style.opacity = "0.7", y.currentTarget.style.backgroundColor = "transparent";
},
title: "Download as Image",
children: [
/* @__PURE__ */ S("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
/* @__PURE__ */ f("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
/* @__PURE__ */ f("polyline", { points: "7 10 12 15 17 10" }),
/* @__PURE__ */ f("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
] }),
"Download"
]
}
)
] }),
/* @__PURE__ */ f(
ht,
{
contributions: u.contributions,
theme: p,
blockSize: r,
blockMargin: i,
showWeekdayLabels: s,
showMonthLabels: a
}
),
/* @__PURE__ */ S("div", { style: { marginTop: "12px", display: "flex", alignItems: "center", gap: "8px", fontSize: o - 3 }, children: [
/* @__PURE__ */ f("span", { style: { color: p.text, opacity: 0.6 }, children: "Less" }),
[0, 1, 2, 3, 4].map((y) => /* @__PURE__ */ f(
"div",
{
style: {
width: r,
height: r,
backgroundColor: p[`level${y}`],
borderRadius: "2px"
},
title: `Level ${y}`
},
y
)),
/* @__PURE__ */ f("span", { style: { color: p.text, opacity: 0.6 }, children: "More" })
] })
]
}
);
}, Fe = ({
colorScheme: t,
blockSize: e = 12,
blockMargin: n = 3
}) => {
const r = ft(t), i = Ct(() => {
const o = (/* @__PURE__ */ new Date()).getFullYear(), s = new Date(o, 0, 1), a = new Date(o, 11, 31);
return ut([], s, a);
}, []);
return /* @__PURE__ */ S(
"div",
{
style: {
padding: "20px",
backgroundColor: r.background,
borderRadius: "6px",
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
},
children: [
/* @__PURE__ */ S("div", { style: { marginBottom: "16px", display: "flex", justifyContent: "space-between", alignItems: "flex-start" }, children: [
/* @__PURE__ */ S("div", { children: [
/* @__PURE__ */ f(
"div",
{
style: {
height: "20px",
width: "250px",
backgroundColor: r.level0,
borderRadius: "4px",
marginBottom: "8px"
}
}
),
/* @__PURE__ */ f(
"div",
{
style: {
height: "14px",
width: "180px",
backgroundColor: r.level0,
borderRadius: "4px",
marginBottom: "4px"
}
}
),
/* @__PURE__ */ f(
"div",
{
style: {
height: "12px",
width: "300px",
backgroundColor: r.level0,
borderRadius: "4px",
marginTop: "4px"
}
}
)
] }),
/* @__PURE__ */ f(
"div",
{
style: {
height: "28px",
width: "80px",
backgroundColor: r.level0,
borderRadius: "4px",
opacity: 0.5
}
}
)
] }),
/* @__PURE__ */ f("div", { className: "skeleton-shimmer", style: { display: "inline-block", borderRadius: "4px" }, children: /* @__PURE__ */ f(
ht,
{
contributions: i,
theme: r,
blockSize: e,
blockMargin: n,
showWeekdayLabels: !0,
showMonthLabels: !0
}
) }),
/* @__PURE__ */ S(
"div",
{
style: {
marginTop: "12px",
display: "flex",
gap: "8px",
alignItems: "center"
},
children: [
/* @__PURE__ */ f(
"div",
{
style: {
height: "10px",
width: "30px",
backgroundColor: r.level0,
borderRadius: "2px"
}
}
),
/* @__PURE__ */ f("div", { style: { display: "flex", gap: "3px" }, children: [0, 1, 2, 3, 4].map((o) => /* @__PURE__ */ f(
"div",
{
style: {
width: e,
height: e,
backgroundColor: r.level0,
borderRadius: "2px"
}
},
o
)) }),
/* @__PURE__ */ f(
"div",
{
style: {
height: "10px",
width: "30px",
backgroundColor: r.level0,
borderRadius: "2px"
}
}
)
]
}
)
]
}
);
};
export {
Te as MergedGitHubCalendar,
Fe as SkeletonCalendar,
Ee as darkTheme,
ft as getTheme,
ve as lightTheme
};