github-contributions-ui 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -85,9 +85,8 @@ function buildGrid(dayMap, year) {
85
85
  const week = [];
86
86
  for (let d = 0; d < 7; d++) {
87
87
  const iso = cur.toISOString().slice(0, 10);
88
- if (cur > end) {
89
- week.push(null);
90
- } else {
88
+ if (cur > end) week.push(null);
89
+ else {
91
90
  week.push(
92
91
  (_a = dayMap.get(iso)) != null ? _a : {
93
92
  date: iso,
@@ -126,7 +125,7 @@ function Tooltip({ day, x, y }) {
126
125
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
127
126
  "div",
128
127
  {
129
- className: "fixed z-50 pointer-events-none -translate-x-1/2 -translate-y-full px-2.5 py-1.5 rounded-md text-xs font-mono whitespace-nowrap shadow-xl bg-neutral-900 text-white dark:bg-white dark:text-neutral-900",
128
+ className: "fixed z-50 pointer-events-none -translate-x-1/2 -translate-y-full px-2.5 py-1.5 rounded-md text-xs font-mono whitespace-nowrap shadow-xl bg-neutral-900 text-white",
130
129
  style: { left: x, top: y - 8 },
131
130
  children: [
132
131
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("b", { children: [
@@ -145,7 +144,7 @@ function Skeleton() {
145
144
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex gap-[3px] animate-pulse opacity-40", children: Array.from({ length: 53 }).map((_, w) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col gap-[3px]", children: Array.from({ length: 7 }).map((_2, d) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
146
145
  "div",
147
146
  {
148
- className: "w-[13px] h-[13px] rounded-[3px] bg-neutral-300 dark:bg-neutral-700"
147
+ className: "w-[13px] h-[13px] rounded-[3px] bg-neutral-700"
149
148
  },
150
149
  d
151
150
  )) }, w)) });
@@ -161,7 +160,7 @@ function YearPill({
161
160
  onClick,
162
161
  className: [
163
162
  "px-2.5 py-0.5 rounded-full text-[11px] font-medium transition-colors duration-150",
164
- active ? "bg-neutral-900 text-white dark:bg-white dark:text-neutral-900" : "bg-neutral-100 text-neutral-600 hover:bg-neutral-200 dark:bg-neutral-800 dark:text-neutral-400 dark:hover:bg-neutral-700"
163
+ active ? "bg-white text-neutral-900" : "bg-neutral-800 text-neutral-400 hover:bg-neutral-700"
165
164
  ].join(" "),
166
165
  children: label
167
166
  }
@@ -169,89 +168,6 @@ function YearPill({
169
168
  }
170
169
  function GithubActivity({ username, theme = "dark", className }) {
171
170
  var _a;
172
- const STYLES = `
173
- .gcu .relative{position:relative}
174
- .gcu .absolute{position:absolute}
175
- .gcu .fixed{position:fixed}
176
- .gcu .z-50{z-index:50}
177
- .gcu .pointer-events-none{pointer-events:none}
178
- .gcu .flex{display:flex}
179
- .gcu .flex-col{flex-direction:column}
180
- .gcu .flex-wrap{flex-wrap:wrap}
181
- .gcu .items-center{align-items:center}
182
- .gcu .justify-start{justify-content:flex-start}
183
- .gcu .inline-block{display:inline-block}
184
- .gcu .w-full{width:100%}
185
- .gcu .w-\\[10px\\]{width:10px}
186
- .gcu .w-\\[13px\\]{width:13px}
187
- .gcu .h-\\[10px\\]{height:10px}
188
- .gcu .h-\\[13px\\]{height:13px}
189
- .gcu .h-\\[18px\\]{height:18px}
190
- .gcu .gap-\\[3px\\]{gap:3px}
191
- .gcu .gap-1{gap:0.25rem}
192
- .gcu .gap-1\\.5{gap:0.375rem}
193
- .gcu .gap-x-6{column-gap:1.5rem}
194
- .gcu .gap-y-1{row-gap:0.25rem}
195
- .gcu .mb-4{margin-bottom:1rem}
196
- .gcu .mt-3{margin-top:0.75rem}
197
- .gcu .mt-4{margin-top:1rem}
198
- .gcu .mr-1{margin-right:0.25rem}
199
- .gcu .ml-1{margin-left:0.25rem}
200
- .gcu .p-4{padding:1rem}
201
- .gcu .pt-3{padding-top:0.75rem}
202
- .gcu .pt-px{padding-top:1px}
203
- .gcu .pb-1{padding-bottom:0.25rem}
204
- .gcu .pr-1\\.5{padding-right:0.375rem}
205
- .gcu .px-2\\.5{padding-left:0.625rem;padding-right:0.625rem}
206
- .gcu .py-1\\.5{padding-top:0.375rem;padding-bottom:0.375rem}
207
- .gcu .py-0\\.5{padding-top:0.125rem;padding-bottom:0.125rem}
208
- .gcu .rounded-\\[2px\\]{border-radius:2px}
209
- .gcu .rounded-\\[3px\\]{border-radius:3px}
210
- .gcu .rounded-md{border-radius:0.375rem}
211
- .gcu .rounded-full{border-radius:9999px}
212
- .gcu .rounded-xl{border-radius:0.75rem}
213
- .gcu .text-right{text-align:right}
214
- .gcu .text-\\[10px\\]{font-size:10px}
215
- .gcu .text-\\[11px\\]{font-size:11px}
216
- .gcu .text-xs{font-size:0.75rem}
217
- .gcu .text-sm{font-size:0.875rem}
218
- .gcu .font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}
219
- .gcu .font-medium{font-weight:500}
220
- .gcu .font-semibold{font-weight:600}
221
- .gcu .select-none{-webkit-user-select:none;-ms-user-select:none;user-select:none}
222
- .gcu .whitespace-nowrap{white-space:nowrap}
223
- .gcu .overflow-x-auto{overflow-x:auto}
224
- .gcu .overflow-y-visible{overflow-y:visible}
225
- .gcu .border{border-width:1px;border-style:solid;border-color:#e5e5e5}
226
- .gcu .border-t{border-top-width:1px;border-top-style:solid;border-top-color:#e5e5e5}
227
- .gcu .transition-transform{transition-property:transform;transition-timing-function:ease;transition-duration:0.1s}
228
- .gcu .transition-colors{transition-property:color,background-color,border-color;transition-timing-function:ease;transition-duration:0.15s}
229
- .gcu .duration-100{transition-duration:0.1s}
230
- .gcu .duration-150{transition-duration:0.15s}
231
- .gcu .hover\\:scale-125:hover{transform:scale(1.25)}
232
- .gcu .text-neutral-500{color:#6b7280}
233
- .gcu .text-neutral-400{color:#9ca3af}
234
- .gcu .text-neutral-700{color:#374151}
235
- .gcu .text-neutral-200{color:#e5e7eb}
236
- .gcu .bg-white{background-color:#fff}
237
- .gcu .bg-neutral-900{background-color:#171717}
238
- .gcu .bg-neutral-950{background-color:#0a0a0a}
239
- .gcu .bg-neutral-300{background-color:#d4d4d4}
240
- .gcu .text-white{color:#fff}
241
- .gcu .border-neutral-200{border-color:#e5e5e5}
242
- .gcu .border-neutral-800{border-color:#262626}
243
- .gcu .border-neutral-100{border-color:#f5f5f5}
244
- .gcu .shadow-xl{box-shadow:0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04)}
245
- `;
246
- (0, import_react.useEffect)(() => {
247
- if (typeof document === "undefined") return;
248
- const id = "github-contributions-ui-inline";
249
- if (document.getElementById(id)) return;
250
- const style = document.createElement("style");
251
- style.id = id;
252
- style.textContent = STYLES;
253
- document.head.appendChild(style);
254
- }, []);
255
171
  const [allDays, setAllDays] = (0, import_react.useState)(/* @__PURE__ */ new Map());
256
172
  const [years, setYears] = (0, import_react.useState)([]);
257
173
  const [selectedYear, setSelectedYear] = (0, import_react.useState)("last");
@@ -266,21 +182,17 @@ function GithubActivity({ username, theme = "dark", className }) {
266
182
  (0, import_react.useEffect)(() => {
267
183
  if (!username) return;
268
184
  let mounted = true;
269
- setLoading(true);
270
- setError(false);
271
185
  (async () => {
272
- var _a2;
273
186
  try {
187
+ setLoading(true);
274
188
  const res = await fetch(
275
189
  `https://github-contributions-api.jogruber.de/v4/${username}?y=all`
276
190
  );
277
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
191
+ if (!res.ok) throw new Error();
278
192
  const json = await res.json();
279
- const raw = (_a2 = json.contributions) != null ? _a2 : [];
280
- if (!raw.length) throw new Error("empty data");
281
193
  const map = /* @__PURE__ */ new Map();
282
194
  const yearSet = /* @__PURE__ */ new Set();
283
- raw.forEach((c) => {
195
+ json.contributions.forEach((c) => {
284
196
  map.set(c.date, {
285
197
  date: c.date,
286
198
  count: c.count,
@@ -288,17 +200,14 @@ function GithubActivity({ username, theme = "dark", className }) {
288
200
  });
289
201
  yearSet.add(new Date(c.date).getFullYear());
290
202
  });
291
- if (mounted) {
292
- setAllDays(map);
293
- setYears(Array.from(yearSet).sort((a, b) => b - a));
294
- setLoading(false);
295
- }
296
- } catch (err) {
297
- console.warn("GithubActivity fetch error:", err);
298
- if (mounted) {
299
- setError(true);
300
- setLoading(false);
301
- }
203
+ if (!mounted) return;
204
+ setAllDays(map);
205
+ setYears(Array.from(yearSet).sort((a, b) => b - a));
206
+ setError(false);
207
+ } catch {
208
+ if (mounted) setError(true);
209
+ } finally {
210
+ if (mounted) setLoading(false);
302
211
  }
303
212
  })();
304
213
  return () => {
@@ -315,12 +224,11 @@ function GithubActivity({ username, theme = "dark", className }) {
315
224
  }
316
225
  return new Date(d.date).getFullYear() === selectedYear;
317
226
  });
318
- const sum = entries.reduce((s, d) => s + d.count, 0);
227
+ setTotal(entries.reduce((s, d) => s + d.count, 0));
319
228
  const best = entries.reduce(
320
229
  (b, d) => !b || d.count > b.count ? d : b,
321
230
  null
322
231
  );
323
- setTotal(sum);
324
232
  setBestDay(best && best.count > 0 ? best : null);
325
233
  }, [allDays, selectedYear]);
326
234
  const grid = (0, import_react.useMemo)(
@@ -329,19 +237,9 @@ function GithubActivity({ username, theme = "dark", className }) {
329
237
  );
330
238
  const labels = (0, import_react.useMemo)(() => monthLabels(grid), [grid]);
331
239
  const outlineColor = theme === "light" ? "#333" : "#f0f0f0";
332
- const bestDateLabel = bestDay ? new Date(bestDay.date).toLocaleDateString("en-US", {
333
- month: "short",
334
- day: "numeric",
335
- year: "numeric"
336
- }) : null;
337
- const periodLabel = selectedYear === "last" ? " in the last year" : ` in ${selectedYear}`;
338
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: ["gcu w-full font-mono", className].join(" ").trim(), children: [
339
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1 mb-4 text-xs text-neutral-500 dark:text-neutral-400", children: [
340
- loading ? "Loading\u2026" : error ? "Unavailable" : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
341
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-semibold text-neutral-700 dark:text-neutral-200", children: total == null ? void 0 : total.toLocaleString() }),
342
- " contributions",
343
- periodLabel
344
- ] }),
240
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: ["w-full font-mono", className].join(" ").trim(), children: [
241
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1 mb-4 text-xs text-neutral-400", children: [
242
+ loading ? "Loading\u2026" : error ? "Unavailable" : `${total == null ? void 0 : total.toLocaleString()} contributions ${selectedYear === "last" ? "in the last year" : `in ${selectedYear}`}`,
345
243
  bestDay && !loading && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1.5", children: [
346
244
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
347
245
  "span",
@@ -351,16 +249,11 @@ function GithubActivity({ username, theme = "dark", className }) {
351
249
  }
352
250
  ),
353
251
  "Best day:",
354
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "font-semibold text-neutral-700 dark:text-neutral-200", children: [
355
- bestDay.count,
356
- " contributions"
357
- ] }),
358
- "on ",
359
- bestDateLabel
252
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-neutral-200 font-semibold", children: bestDay.count })
360
253
  ] })
361
254
  ] }),
362
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "border border-neutral-200 dark:border-neutral-800 rounded-xl p-4 bg-white dark:bg-neutral-950", children: error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm italic text-neutral-400", children: "GitHub activity unavailable." }) : loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
363
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "overflow-x-auto overflow-y-visible pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
255
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "border border-neutral-800 rounded-xl p-4 bg-neutral-950", children: error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm italic text-neutral-400", children: "GitHub activity unavailable." }) : loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
256
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "overflow-x-auto pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
364
257
  "div",
365
258
  {
366
259
  className: "relative",
@@ -376,11 +269,11 @@ function GithubActivity({ username, theme = "dark", className }) {
376
269
  children: labels.map(({ label, col }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
377
270
  "span",
378
271
  {
379
- className: "absolute text-[11px] select-none text-neutral-500 dark:text-neutral-400",
272
+ className: "absolute text-[11px] text-neutral-400",
380
273
  style: { left: col * STEP },
381
274
  children: label
382
275
  },
383
- `${label}-${col}`
276
+ label + col
384
277
  ))
385
278
  }
386
279
  ),
@@ -388,14 +281,14 @@ function GithubActivity({ username, theme = "dark", className }) {
388
281
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
389
282
  "div",
390
283
  {
391
- className: "flex flex-col gap-[3px] pt-px shrink-0",
284
+ className: "flex flex-col gap-[3px]",
392
285
  style: { width: DAY_COL_W - GAP },
393
286
  children: Array.from({ length: 7 }).map((_, i) => {
394
287
  var _a2;
395
288
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
396
289
  "div",
397
290
  {
398
- className: "h-[13px] text-[10px] leading-[13px] text-right pr-1.5 select-none text-neutral-500 dark:text-neutral-400",
291
+ className: "h-[13px] text-[10px] text-right pr-1.5 text-neutral-400",
399
292
  children: (_a2 = DAY_LABELS[i]) != null ? _a2 : ""
400
293
  },
401
294
  i
@@ -406,10 +299,9 @@ function GithubActivity({ username, theme = "dark", className }) {
406
299
  grid.map((week, wi) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col gap-[3px]", children: week.map((day, di) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
407
300
  "div",
408
301
  {
409
- className: "w-[13px] h-[13px] rounded-[3px] transition-transform duration-100 hover:scale-125",
302
+ className: "w-[13px] h-[13px] rounded-[3px] transition-transform hover:scale-125",
410
303
  style: {
411
304
  backgroundColor: day ? colors[day.level] : "transparent",
412
- cursor: day ? "pointer" : "default",
413
305
  outline: bestDay && (day == null ? void 0 : day.date) === bestDay.date ? `2px solid ${outlineColor}` : "none",
414
306
  outlineOffset: "1px"
415
307
  },
@@ -430,8 +322,8 @@ function GithubActivity({ username, theme = "dark", className }) {
430
322
  ]
431
323
  }
432
324
  ) }),
433
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-start gap-1 mt-3", children: [
434
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[11px] text-neutral-500 dark:text-neutral-400 mr-1", children: "Less" }),
325
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1 mt-3 text-[11px] text-neutral-400", children: [
326
+ "Less",
435
327
  colors.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
436
328
  "div",
437
329
  {
@@ -440,9 +332,9 @@ function GithubActivity({ username, theme = "dark", className }) {
440
332
  },
441
333
  i
442
334
  )),
443
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[11px] text-neutral-500 dark:text-neutral-400 ml-1", children: "More" })
335
+ "More"
444
336
  ] }),
445
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5 mt-4 pt-3 border-t border-neutral-100 dark:border-neutral-800", children: [
337
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5 mt-4 pt-3 border-t border-neutral-800", children: [
446
338
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[11px] text-neutral-400 mr-1", children: "Year:" }),
447
339
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
448
340
  YearPill,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/GithubActivity.tsx"],"sourcesContent":[" \"use client\";\n export { default as GithubActivity } from \"./GithubActivity\";\n","\"use client\";\r\n\r\nimport { memo, useEffect, useState, useMemo } from \"react\";\r\n\r\ntype Theme = \"light\" | \"dark\" | \"blue\" | \"purple\";\r\n\r\ninterface Day {\r\n date: string;\r\n count: number;\r\n level: 0 | 1 | 2 | 3 | 4;\r\n}\r\n\r\ninterface Props {\r\n username: string;\r\n theme?: Theme;\r\n className?: string;\r\n}\r\n\r\n/* ---------- Constants ---------- */\r\n\r\nconst MONTHS = [\r\n \"Jan\",\r\n \"Feb\",\r\n \"Mar\",\r\n \"Apr\",\r\n \"May\",\r\n \"Jun\",\r\n \"Jul\",\r\n \"Aug\",\r\n \"Sep\",\r\n \"Oct\",\r\n \"Nov\",\r\n \"Dec\",\r\n];\r\nconst DAY_LABELS: Record<number, string> = { 1: \"Mon\", 3: \"Wed\", 5: \"Fri\" };\r\n\r\nconst CELL = 13;\r\nconst GAP = 3;\r\nconst STEP = CELL + GAP;\r\nconst DAY_COL_W = 30;\r\n\r\n/* ---------- Color Themes ---------- */\r\n\r\nconst LIGHT = [\"#ebedf0\", \"#9be9a8\", \"#40c463\", \"#30a14e\", \"#216e39\"];\r\nconst DARK = [\"#21262d\", \"#0e4429\", \"#006d32\", \"#26a641\", \"#39d353\"];\r\nconst BLUE = [\"#21262d\", \"#a3c9ff\", \"#5fa3ff\", \"#2f7bff\", \"#0b5cff\"];\r\nconst PURPLE = [\"#21262d\", \"#d8b4ff\", \"#c084fc\", \"#a855f7\", \"#7e22ce\"];\r\n\r\nconst COLOR_MAP: Record<Theme, string[]> = {\r\n light: LIGHT,\r\n dark: DARK,\r\n blue: BLUE,\r\n purple: PURPLE,\r\n};\r\n\r\n/* ---------- Utilities ---------- */\r\n\r\nfunction toLevel(count: number): 0 | 1 | 2 | 3 | 4 {\r\n if (count === 0) return 0;\r\n if (count <= 3) return 1;\r\n if (count <= 6) return 2;\r\n if (count <= 9) return 3;\r\n return 4;\r\n}\r\n\r\nfunction buildGrid(\r\n dayMap: Map<string, Day>,\r\n year: number | \"last\",\r\n): (Day | null)[][] {\r\n let start: Date;\r\n let end: Date;\r\n\r\n if (year === \"last\") {\r\n end = new Date();\r\n start = new Date(end);\r\n start.setFullYear(start.getFullYear() - 1);\r\n start.setDate(start.getDate() + 1);\r\n } else {\r\n start = new Date(year, 0, 1);\r\n end =\r\n year === new Date().getFullYear() ? new Date() : new Date(year, 11, 31);\r\n }\r\n\r\n start.setDate(start.getDate() - start.getDay());\r\n\r\n const weeks: (Day | null)[][] = [];\r\n const cur = new Date(start);\r\n\r\n while (cur <= end) {\r\n const week: (Day | null)[] = [];\r\n\r\n for (let d = 0; d < 7; d++) {\r\n const iso = cur.toISOString().slice(0, 10);\r\n\r\n if (cur > end) {\r\n week.push(null);\r\n } else {\r\n week.push(\r\n dayMap.get(iso) ?? {\r\n date: iso,\r\n count: 0,\r\n level: 0,\r\n },\r\n );\r\n }\r\n\r\n cur.setDate(cur.getDate() + 1);\r\n }\r\n\r\n weeks.push(week);\r\n }\r\n\r\n return weeks;\r\n}\r\n\r\nfunction monthLabels(grid: (Day | null)[][]) {\r\n const out: { label: string; col: number }[] = [];\r\n let last = -1;\r\n\r\n grid.forEach((week, i) => {\r\n const first = week.find(Boolean);\r\n if (!first) return;\r\n\r\n const m = new Date(first.date).getMonth();\r\n\r\n if (m !== last) {\r\n out.push({ label: MONTHS[m], col: i });\r\n last = m;\r\n }\r\n });\r\n\r\n return out;\r\n}\r\n\r\n/* ---------- UI Components ---------- */\r\n\r\nfunction Tooltip({ day, x, y }: { day: Day; x: number; y: number }) {\r\n const label = new Date(day.date).toLocaleDateString(\"en-US\", {\r\n weekday: \"long\",\r\n year: \"numeric\",\r\n month: \"long\",\r\n day: \"numeric\",\r\n });\r\n\r\n return (\r\n <div\r\n className=\"fixed z-50 pointer-events-none -translate-x-1/2 -translate-y-full px-2.5 py-1.5 rounded-md text-xs font-mono whitespace-nowrap shadow-xl bg-neutral-900 text-white dark:bg-white dark:text-neutral-900\"\r\n style={{ left: x, top: y - 8 }}\r\n >\r\n <b>\r\n {day.count} contribution{day.count !== 1 ? \"s\" : \"\"}\r\n </b>{\" \"}\r\n · {label}\r\n </div>\r\n );\r\n}\r\n\r\nfunction Skeleton() {\r\n return (\r\n <div className=\"flex gap-[3px] animate-pulse opacity-40\">\r\n {Array.from({ length: 53 }).map((_, w) => (\r\n <div key={w} className=\"flex flex-col gap-[3px]\">\r\n {Array.from({ length: 7 }).map((_, d) => (\r\n <div\r\n key={d}\r\n className=\"w-[13px] h-[13px] rounded-[3px] bg-neutral-300 dark:bg-neutral-700\"\r\n />\r\n ))}\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n\r\nfunction YearPill({\r\n label,\r\n active,\r\n onClick,\r\n}: {\r\n label: string;\r\n active: boolean;\r\n onClick: () => void;\r\n}) {\r\n return (\r\n <button\r\n onClick={onClick}\r\n className={[\r\n \"px-2.5 py-0.5 rounded-full text-[11px] font-medium transition-colors duration-150\",\r\n active\r\n ? \"bg-neutral-900 text-white dark:bg-white dark:text-neutral-900\"\r\n : \"bg-neutral-100 text-neutral-600 hover:bg-neutral-200 dark:bg-neutral-800 dark:text-neutral-400 dark:hover:bg-neutral-700\",\r\n ].join(\" \")}\r\n >\r\n {label}\r\n </button>\r\n );\r\n}\r\n\r\n/* ---------- Main Component ---------- */\r\n\r\nfunction GithubActivity({ username, theme = \"dark\", className }: Props) {\r\n const STYLES = `\r\n .gcu .relative{position:relative}\r\n .gcu .absolute{position:absolute}\r\n .gcu .fixed{position:fixed}\r\n .gcu .z-50{z-index:50}\r\n .gcu .pointer-events-none{pointer-events:none}\r\n .gcu .flex{display:flex}\r\n .gcu .flex-col{flex-direction:column}\r\n .gcu .flex-wrap{flex-wrap:wrap}\r\n .gcu .items-center{align-items:center}\r\n .gcu .justify-start{justify-content:flex-start}\r\n .gcu .inline-block{display:inline-block}\r\n .gcu .w-full{width:100%}\r\n .gcu .w-\\\\[10px\\\\]{width:10px}\r\n .gcu .w-\\\\[13px\\\\]{width:13px}\r\n .gcu .h-\\\\[10px\\\\]{height:10px}\r\n .gcu .h-\\\\[13px\\\\]{height:13px}\r\n .gcu .h-\\\\[18px\\\\]{height:18px}\r\n .gcu .gap-\\\\[3px\\\\]{gap:3px}\r\n .gcu .gap-1{gap:0.25rem}\r\n .gcu .gap-1\\\\.5{gap:0.375rem}\r\n .gcu .gap-x-6{column-gap:1.5rem}\r\n .gcu .gap-y-1{row-gap:0.25rem}\r\n .gcu .mb-4{margin-bottom:1rem}\r\n .gcu .mt-3{margin-top:0.75rem}\r\n .gcu .mt-4{margin-top:1rem}\r\n .gcu .mr-1{margin-right:0.25rem}\r\n .gcu .ml-1{margin-left:0.25rem}\r\n .gcu .p-4{padding:1rem}\r\n .gcu .pt-3{padding-top:0.75rem}\r\n .gcu .pt-px{padding-top:1px}\r\n .gcu .pb-1{padding-bottom:0.25rem}\r\n .gcu .pr-1\\\\.5{padding-right:0.375rem}\r\n .gcu .px-2\\\\.5{padding-left:0.625rem;padding-right:0.625rem}\r\n .gcu .py-1\\\\.5{padding-top:0.375rem;padding-bottom:0.375rem}\r\n .gcu .py-0\\\\.5{padding-top:0.125rem;padding-bottom:0.125rem}\r\n .gcu .rounded-\\\\[2px\\\\]{border-radius:2px}\r\n .gcu .rounded-\\\\[3px\\\\]{border-radius:3px}\r\n .gcu .rounded-md{border-radius:0.375rem}\r\n .gcu .rounded-full{border-radius:9999px}\r\n .gcu .rounded-xl{border-radius:0.75rem}\r\n .gcu .text-right{text-align:right}\r\n .gcu .text-\\\\[10px\\\\]{font-size:10px}\r\n .gcu .text-\\\\[11px\\\\]{font-size:11px}\r\n .gcu .text-xs{font-size:0.75rem}\r\n .gcu .text-sm{font-size:0.875rem}\r\n .gcu .font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace}\r\n .gcu .font-medium{font-weight:500}\r\n .gcu .font-semibold{font-weight:600}\r\n .gcu .select-none{-webkit-user-select:none;-ms-user-select:none;user-select:none}\r\n .gcu .whitespace-nowrap{white-space:nowrap}\r\n .gcu .overflow-x-auto{overflow-x:auto}\r\n .gcu .overflow-y-visible{overflow-y:visible}\r\n .gcu .border{border-width:1px;border-style:solid;border-color:#e5e5e5}\r\n .gcu .border-t{border-top-width:1px;border-top-style:solid;border-top-color:#e5e5e5}\r\n .gcu .transition-transform{transition-property:transform;transition-timing-function:ease;transition-duration:0.1s}\r\n .gcu .transition-colors{transition-property:color,background-color,border-color;transition-timing-function:ease;transition-duration:0.15s}\r\n .gcu .duration-100{transition-duration:0.1s}\r\n .gcu .duration-150{transition-duration:0.15s}\r\n .gcu .hover\\\\:scale-125:hover{transform:scale(1.25)}\r\n .gcu .text-neutral-500{color:#6b7280}\r\n .gcu .text-neutral-400{color:#9ca3af}\r\n .gcu .text-neutral-700{color:#374151}\r\n .gcu .text-neutral-200{color:#e5e7eb}\r\n .gcu .bg-white{background-color:#fff}\r\n .gcu .bg-neutral-900{background-color:#171717}\r\n .gcu .bg-neutral-950{background-color:#0a0a0a}\r\n .gcu .bg-neutral-300{background-color:#d4d4d4}\r\n .gcu .text-white{color:#fff}\r\n .gcu .border-neutral-200{border-color:#e5e5e5}\r\n .gcu .border-neutral-800{border-color:#262626}\r\n .gcu .border-neutral-100{border-color:#f5f5f5}\r\n .gcu .shadow-xl{box-shadow:0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04)}\r\n `;\r\n\r\n useEffect(() => {\r\n if (typeof document === \"undefined\") return;\r\n const id = \"github-contributions-ui-inline\";\r\n if (document.getElementById(id)) return;\r\n const style = document.createElement(\"style\");\r\n style.id = id;\r\n style.textContent = STYLES;\r\n document.head.appendChild(style);\r\n }, []);\r\n const [allDays, setAllDays] = useState<Map<string, Day>>(new Map());\r\n const [years, setYears] = useState<number[]>([]);\r\n const [selectedYear, setSelectedYear] = useState<number | \"last\">(\"last\");\r\n const [total, setTotal] = useState<number | null>(null);\r\n const [bestDay, setBestDay] = useState<Day | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [error, setError] = useState(false);\r\n const [tip, setTip] = useState<{ day: Day; x: number; y: number } | null>(\r\n null,\r\n );\r\n\r\n const colors = COLOR_MAP[theme] ?? COLOR_MAP.dark;\r\n\r\n /* Fetch Contributions */\r\n\r\n useEffect(() => {\r\n if (!username) return;\r\n\r\n let mounted = true;\r\n setLoading(true);\r\n setError(false);\r\n\r\n (async () => {\r\n try {\r\n const res = await fetch(\r\n `https://github-contributions-api.jogruber.de/v4/${username}?y=all`,\r\n );\r\n\r\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n\r\n const json = await res.json();\r\n const raw: { date: string; count: number }[] = json.contributions ?? [];\r\n\r\n if (!raw.length) throw new Error(\"empty data\");\r\n\r\n const map = new Map<string, Day>();\r\n const yearSet = new Set<number>();\r\n\r\n raw.forEach((c) => {\r\n map.set(c.date, {\r\n date: c.date,\r\n count: c.count,\r\n level: toLevel(c.count),\r\n });\r\n\r\n yearSet.add(new Date(c.date).getFullYear());\r\n });\r\n\r\n if (mounted) {\r\n setAllDays(map);\r\n setYears(Array.from(yearSet).sort((a, b) => b - a));\r\n setLoading(false);\r\n }\r\n } catch (err) {\r\n console.warn(\"GithubActivity fetch error:\", err);\r\n\r\n if (mounted) {\r\n setError(true);\r\n setLoading(false);\r\n }\r\n }\r\n })();\r\n\r\n return () => {\r\n mounted = false;\r\n };\r\n }, [username]);\r\n\r\n /* Stats Calculation */\r\n\r\n useEffect(() => {\r\n if (!allDays.size) return;\r\n\r\n const entries = Array.from(allDays.values()).filter((d) => {\r\n if (selectedYear === \"last\") {\r\n const oneYearAgo = new Date();\r\n oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);\r\n return new Date(d.date) >= oneYearAgo;\r\n }\r\n\r\n return new Date(d.date).getFullYear() === selectedYear;\r\n });\r\n\r\n const sum = entries.reduce((s, d) => s + d.count, 0);\r\n\r\n const best = entries.reduce<Day | null>(\r\n (b, d) => (!b || d.count > b.count ? d : b),\r\n null,\r\n );\r\n\r\n setTotal(sum);\r\n setBestDay(best && best.count > 0 ? best : null);\r\n }, [allDays, selectedYear]);\r\n\r\n /* Rendering Helpers */\r\n\r\n const grid = useMemo(\r\n () => (allDays.size ? buildGrid(allDays, selectedYear) : []),\r\n [allDays, selectedYear],\r\n );\r\n\r\n const labels = useMemo(() => monthLabels(grid), [grid]);\r\n\r\n const outlineColor = theme === \"light\" ? \"#333\" : \"#f0f0f0\";\r\n\r\n const bestDateLabel = bestDay\r\n ? new Date(bestDay.date).toLocaleDateString(\"en-US\", {\r\n month: \"short\",\r\n day: \"numeric\",\r\n year: \"numeric\",\r\n })\r\n : null;\r\n\r\n const periodLabel =\r\n selectedYear === \"last\" ? \" in the last year\" : ` in ${selectedYear}`;\r\n\r\n return (\r\n <section className={[\"gcu w-full font-mono\", className].join(\" \").trim()}>\r\n <div className=\"flex flex-wrap items-center gap-x-6 gap-y-1 mb-4 text-xs text-neutral-500 dark:text-neutral-400\">\r\n {loading ? (\r\n \"Loading…\"\r\n ) : error ? (\r\n \"Unavailable\"\r\n ) : (\r\n <>\r\n <span className=\"font-semibold text-neutral-700 dark:text-neutral-200\">\r\n {total?.toLocaleString()}\r\n </span>\r\n {\" contributions\"}\r\n {periodLabel}\r\n </>\r\n )}\r\n\r\n {bestDay && !loading && (\r\n <span className=\"flex items-center gap-1.5\">\r\n <span\r\n className=\"inline-block w-[10px] h-[10px] rounded-[2px]\"\r\n style={{ backgroundColor: colors[4] }}\r\n />\r\n Best day:\r\n <span className=\"font-semibold text-neutral-700 dark:text-neutral-200\">\r\n {bestDay.count} contributions\r\n </span>\r\n on {bestDateLabel}\r\n </span>\r\n )}\r\n </div>\r\n\r\n <div className=\"border border-neutral-200 dark:border-neutral-800 rounded-xl p-4 bg-white dark:bg-neutral-950\">\r\n {error ? (\r\n <p className=\"text-sm italic text-neutral-400\">\r\n GitHub activity unavailable.\r\n </p>\r\n ) : loading ? (\r\n <Skeleton />\r\n ) : (\r\n <>\r\n <div className=\"overflow-x-auto overflow-y-visible pb-1\">\r\n <div\r\n className=\"relative\"\r\n style={{\r\n minWidth: grid.length * STEP + DAY_COL_W + 8,\r\n }}\r\n >\r\n <div\r\n className=\"relative h-[18px] mb-1\"\r\n style={{ marginLeft: DAY_COL_W }}\r\n >\r\n {labels.map(({ label, col }) => (\r\n <span\r\n key={`${label}-${col}`}\r\n className=\"absolute text-[11px] select-none text-neutral-500 dark:text-neutral-400\"\r\n style={{ left: col * STEP }}\r\n >\r\n {label}\r\n </span>\r\n ))}\r\n </div>\r\n\r\n <div className=\"flex gap-[3px]\">\r\n <div\r\n className=\"flex flex-col gap-[3px] pt-px shrink-0\"\r\n style={{ width: DAY_COL_W - GAP }}\r\n >\r\n {Array.from({ length: 7 }).map((_, i) => (\r\n <div\r\n key={i}\r\n className=\"h-[13px] text-[10px] leading-[13px] text-right pr-1.5 select-none text-neutral-500 dark:text-neutral-400\"\r\n >\r\n {DAY_LABELS[i] ?? \"\"}\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {grid.map((week, wi) => (\r\n <div key={wi} className=\"flex flex-col gap-[3px]\">\r\n {week.map((day, di) => (\r\n <div\r\n key={di}\r\n className=\"w-[13px] h-[13px] rounded-[3px] transition-transform duration-100 hover:scale-125\"\r\n style={{\r\n backgroundColor: day\r\n ? colors[day.level]\r\n : \"transparent\",\r\n cursor: day ? \"pointer\" : \"default\",\r\n outline:\r\n bestDay && day?.date === bestDay.date\r\n ? `2px solid ${outlineColor}`\r\n : \"none\",\r\n outlineOffset: \"1px\",\r\n }}\r\n onMouseEnter={(e) => {\r\n if (!day) return;\r\n\r\n const r = e.currentTarget.getBoundingClientRect();\r\n\r\n setTip({\r\n day,\r\n x: r.left + r.width / 2,\r\n y: r.top,\r\n });\r\n }}\r\n onMouseLeave={() => setTip(null)}\r\n />\r\n ))}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex items-center justify-start gap-1 mt-3\">\r\n <span className=\"text-[11px] text-neutral-500 dark:text-neutral-400 mr-1\">\r\n Less\r\n </span>\r\n\r\n {colors.map((c, i) => (\r\n <div\r\n key={i}\r\n className=\"w-[13px] h-[13px] rounded-[3px]\"\r\n style={{ backgroundColor: c }}\r\n />\r\n ))}\r\n\r\n <span className=\"text-[11px] text-neutral-500 dark:text-neutral-400 ml-1\">\r\n More\r\n </span>\r\n </div>\r\n\r\n <div className=\"flex flex-wrap items-center gap-1.5 mt-4 pt-3 border-t border-neutral-100 dark:border-neutral-800\">\r\n <span className=\"text-[11px] text-neutral-400 mr-1\">Year:</span>\r\n\r\n <YearPill\r\n label=\"Last year\"\r\n active={selectedYear === \"last\"}\r\n onClick={() => setSelectedYear(\"last\")}\r\n />\r\n\r\n {years.map((y) => (\r\n <YearPill\r\n key={y}\r\n label={String(y)}\r\n active={selectedYear === y}\r\n onClick={() => setSelectedYear(y)}\r\n />\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n\r\n {tip && <Tooltip day={tip.day} x={tip.x} y={tip.y} />}\r\n </section>\r\n );\r\n}\r\n\r\nexport default memo(GithubActivity);\r\n"],"mappings":"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","names":["_","_a"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/GithubActivity.tsx"],"sourcesContent":[" \"use client\";\n export { default as GithubActivity } from \"./GithubActivity\";\n","\"use client\";\r\n\r\nimport { memo, useEffect, useState, useMemo } from \"react\";\r\n\r\ntype Theme = \"light\" | \"dark\" | \"blue\" | \"purple\";\r\n\r\ninterface Day {\r\n date: string;\r\n count: number;\r\n level: 0 | 1 | 2 | 3 | 4;\r\n}\r\n\r\ninterface Props {\r\n username: string;\r\n theme?: Theme;\r\n className?: string;\r\n}\r\n\r\n/* ---------- Constants ---------- */\r\n\r\nconst MONTHS = [\r\n \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\r\n \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\",\r\n];\r\n\r\nconst DAY_LABELS: Record<number, string> = { 1: \"Mon\", 3: \"Wed\", 5: \"Fri\" };\r\n\r\nconst CELL = 13;\r\nconst GAP = 3;\r\nconst STEP = CELL + GAP;\r\nconst DAY_COL_W = 30;\r\n\r\n/* ---------- Graph Color Themes ---------- */\r\n\r\nconst LIGHT = [\"#ebedf0\", \"#9be9a8\", \"#40c463\", \"#30a14e\", \"#216e39\"];\r\nconst DARK = [\"#21262d\", \"#0e4429\", \"#006d32\", \"#26a641\", \"#39d353\"];\r\nconst BLUE = [\"#21262d\", \"#a3c9ff\", \"#5fa3ff\", \"#2f7bff\", \"#0b5cff\"];\r\nconst PURPLE = [\"#21262d\", \"#d8b4ff\", \"#c084fc\", \"#a855f7\", \"#7e22ce\"];\r\n\r\nconst COLOR_MAP: Record<Theme, string[]> = {\r\n light: LIGHT,\r\n dark: DARK,\r\n blue: BLUE,\r\n purple: PURPLE,\r\n};\r\n\r\n/* ---------- Utilities ---------- */\r\n\r\nfunction toLevel(count: number): 0 | 1 | 2 | 3 | 4 {\r\n if (count === 0) return 0;\r\n if (count <= 3) return 1;\r\n if (count <= 6) return 2;\r\n if (count <= 9) return 3;\r\n return 4;\r\n}\r\n\r\nfunction buildGrid(\r\n dayMap: Map<string, Day>,\r\n year: number | \"last\",\r\n): (Day | null)[][] {\r\n let start: Date;\r\n let end: Date;\r\n\r\n if (year === \"last\") {\r\n end = new Date();\r\n start = new Date(end);\r\n start.setFullYear(start.getFullYear() - 1);\r\n start.setDate(start.getDate() + 1);\r\n } else {\r\n start = new Date(year, 0, 1);\r\n end =\r\n year === new Date().getFullYear()\r\n ? new Date()\r\n : new Date(year, 11, 31);\r\n }\r\n\r\n start.setDate(start.getDate() - start.getDay());\r\n\r\n const weeks: (Day | null)[][] = [];\r\n const cur = new Date(start);\r\n\r\n while (cur <= end) {\r\n const week: (Day | null)[] = [];\r\n\r\n for (let d = 0; d < 7; d++) {\r\n const iso = cur.toISOString().slice(0, 10);\r\n\r\n if (cur > end) week.push(null);\r\n else {\r\n week.push(\r\n dayMap.get(iso) ?? {\r\n date: iso,\r\n count: 0,\r\n level: 0,\r\n },\r\n );\r\n }\r\n\r\n cur.setDate(cur.getDate() + 1);\r\n }\r\n\r\n weeks.push(week);\r\n }\r\n\r\n return weeks;\r\n}\r\n\r\nfunction monthLabels(grid: (Day | null)[][]) {\r\n const out: { label: string; col: number }[] = [];\r\n let last = -1;\r\n\r\n grid.forEach((week, i) => {\r\n const first = week.find(Boolean);\r\n if (!first) return;\r\n\r\n const m = new Date(first.date).getMonth();\r\n\r\n if (m !== last) {\r\n out.push({ label: MONTHS[m], col: i });\r\n last = m;\r\n }\r\n });\r\n\r\n return out;\r\n}\r\n\r\n/* ---------- UI Components ---------- */\r\n\r\nfunction Tooltip({ day, x, y }: { day: Day; x: number; y: number }) {\r\n const label = new Date(day.date).toLocaleDateString(\"en-US\", {\r\n weekday: \"long\",\r\n year: \"numeric\",\r\n month: \"long\",\r\n day: \"numeric\",\r\n });\r\n\r\n return (\r\n <div\r\n className=\"fixed z-50 pointer-events-none -translate-x-1/2 -translate-y-full px-2.5 py-1.5 rounded-md text-xs font-mono whitespace-nowrap shadow-xl bg-neutral-900 text-white\"\r\n style={{ left: x, top: y - 8 }}\r\n >\r\n <b>\r\n {day.count} contribution{day.count !== 1 ? \"s\" : \"\"}\r\n </b>{\" \"}\r\n · {label}\r\n </div>\r\n );\r\n}\r\n\r\nfunction Skeleton() {\r\n return (\r\n <div className=\"flex gap-[3px] animate-pulse opacity-40\">\r\n {Array.from({ length: 53 }).map((_, w) => (\r\n <div key={w} className=\"flex flex-col gap-[3px]\">\r\n {Array.from({ length: 7 }).map((_, d) => (\r\n <div\r\n key={d}\r\n className=\"w-[13px] h-[13px] rounded-[3px] bg-neutral-700\"\r\n />\r\n ))}\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n\r\nfunction YearPill({\r\n label,\r\n active,\r\n onClick,\r\n}: {\r\n label: string;\r\n active: boolean;\r\n onClick: () => void;\r\n}) {\r\n return (\r\n <button\r\n onClick={onClick}\r\n className={[\r\n \"px-2.5 py-0.5 rounded-full text-[11px] font-medium transition-colors duration-150\",\r\n active\r\n ? \"bg-white text-neutral-900\"\r\n : \"bg-neutral-800 text-neutral-400 hover:bg-neutral-700\",\r\n ].join(\" \")}\r\n >\r\n {label}\r\n </button>\r\n );\r\n}\r\n\r\n/* ---------- Main Component ---------- */\r\n\r\nfunction GithubActivity({ username, theme = \"dark\", className }: Props) {\r\n const [allDays, setAllDays] = useState<Map<string, Day>>(new Map());\r\n const [years, setYears] = useState<number[]>([]);\r\n const [selectedYear, setSelectedYear] =\r\n useState<number | \"last\">(\"last\");\r\n\r\n const [total, setTotal] = useState<number | null>(null);\r\n const [bestDay, setBestDay] = useState<Day | null>(null);\r\n\r\n const [loading, setLoading] = useState(true);\r\n const [error, setError] = useState(false);\r\n\r\n const [tip, setTip] = useState<{ day: Day; x: number; y: number } | null>(\r\n null,\r\n );\r\n\r\n const colors = COLOR_MAP[theme] ?? COLOR_MAP.dark;\r\n\r\n /* ---------- Fetch ---------- */\r\n\r\n useEffect(() => {\r\n if (!username) return;\r\n\r\n let mounted = true;\r\n\r\n (async () => {\r\n try {\r\n setLoading(true);\r\n const res = await fetch(\r\n `https://github-contributions-api.jogruber.de/v4/${username}?y=all`,\r\n );\r\n\r\n if (!res.ok) throw new Error();\r\n\r\n const json = await res.json();\r\n\r\n const map = new Map<string, Day>();\r\n const yearSet = new Set<number>();\r\n\r\n json.contributions.forEach((c: any) => {\r\n map.set(c.date, {\r\n date: c.date,\r\n count: c.count,\r\n level: toLevel(c.count),\r\n });\r\n\r\n yearSet.add(new Date(c.date).getFullYear());\r\n });\r\n\r\n if (!mounted) return;\r\n\r\n setAllDays(map);\r\n setYears(Array.from(yearSet).sort((a, b) => b - a));\r\n setError(false);\r\n } catch {\r\n if (mounted) setError(true);\r\n } finally {\r\n if (mounted) setLoading(false);\r\n }\r\n })();\r\n\r\n return () => {\r\n mounted = false;\r\n };\r\n }, [username]);\r\n\r\n /* ---------- Stats ---------- */\r\n\r\n useEffect(() => {\r\n if (!allDays.size) return;\r\n\r\n const entries = Array.from(allDays.values()).filter((d) => {\r\n if (selectedYear === \"last\") {\r\n const oneYearAgo = new Date();\r\n oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);\r\n return new Date(d.date) >= oneYearAgo;\r\n }\r\n return new Date(d.date).getFullYear() === selectedYear;\r\n });\r\n\r\n setTotal(entries.reduce((s, d) => s + d.count, 0));\r\n\r\n const best = entries.reduce<Day | null>(\r\n (b, d) => (!b || d.count > b.count ? d : b),\r\n null,\r\n );\r\n\r\n setBestDay(best && best.count > 0 ? best : null);\r\n }, [allDays, selectedYear]);\r\n\r\n /* ---------- Rendering ---------- */\r\n\r\n const grid = useMemo(\r\n () => (allDays.size ? buildGrid(allDays, selectedYear) : []),\r\n [allDays, selectedYear],\r\n );\r\n\r\n const labels = useMemo(() => monthLabels(grid), [grid]);\r\n\r\n const outlineColor = theme === \"light\" ? \"#333\" : \"#f0f0f0\";\r\n\r\n return (\r\n <section className={[\"w-full font-mono\", className].join(\" \").trim()}>\r\n {/* Stats */}\r\n <div className=\"flex flex-wrap items-center gap-x-6 gap-y-1 mb-4 text-xs text-neutral-400\">\r\n {loading\r\n ? \"Loading…\"\r\n : error\r\n ? \"Unavailable\"\r\n : `${total?.toLocaleString()} contributions ${selectedYear === \"last\"\r\n ? \"in the last year\"\r\n : `in ${selectedYear}`\r\n }`}\r\n\r\n {bestDay && !loading && (\r\n <span className=\"flex items-center gap-1.5\">\r\n <span\r\n className=\"inline-block w-[10px] h-[10px] rounded-[2px]\"\r\n style={{ backgroundColor: colors[4] }}\r\n />\r\n Best day:\r\n <span className=\"text-neutral-200 font-semibold\">\r\n {bestDay.count}\r\n </span>\r\n </span>\r\n )}\r\n </div>\r\n\r\n {/* Main Card */}\r\n <div className=\"border border-neutral-800 rounded-xl p-4 bg-neutral-950\">\r\n {error ? (\r\n <p className=\"text-sm italic text-neutral-400\">\r\n GitHub activity unavailable.\r\n </p>\r\n ) : loading ? (\r\n <Skeleton />\r\n ) : (\r\n <>\r\n <div className=\"overflow-x-auto pb-1\">\r\n <div\r\n className=\"relative\"\r\n style={{\r\n minWidth: grid.length * STEP + DAY_COL_W + 8,\r\n }}\r\n >\r\n {/* Months */}\r\n <div\r\n className=\"relative h-[18px] mb-1\"\r\n style={{ marginLeft: DAY_COL_W }}\r\n >\r\n {labels.map(({ label, col }) => (\r\n <span\r\n key={label + col}\r\n className=\"absolute text-[11px] text-neutral-400\"\r\n style={{ left: col * STEP }}\r\n >\r\n {label}\r\n </span>\r\n ))}\r\n </div>\r\n\r\n {/* Grid */}\r\n <div className=\"flex gap-[3px]\">\r\n <div\r\n className=\"flex flex-col gap-[3px]\"\r\n style={{ width: DAY_COL_W - GAP }}\r\n >\r\n {Array.from({ length: 7 }).map((_, i) => (\r\n <div\r\n key={i}\r\n className=\"h-[13px] text-[10px] text-right pr-1.5 text-neutral-400\"\r\n >\r\n {DAY_LABELS[i] ?? \"\"}\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {grid.map((week, wi) => (\r\n <div key={wi} className=\"flex flex-col gap-[3px]\">\r\n {week.map((day, di) => (\r\n <div\r\n key={di}\r\n className=\"w-[13px] h-[13px] rounded-[3px] transition-transform hover:scale-125\"\r\n style={{\r\n backgroundColor: day\r\n ? colors[day.level]\r\n : \"transparent\",\r\n outline:\r\n bestDay && day?.date === bestDay.date\r\n ? `2px solid ${outlineColor}`\r\n : \"none\",\r\n outlineOffset: \"1px\",\r\n }}\r\n onMouseEnter={(e) => {\r\n if (!day) return;\r\n const r =\r\n e.currentTarget.getBoundingClientRect();\r\n setTip({\r\n day,\r\n x: r.left + r.width / 2,\r\n y: r.top,\r\n });\r\n }}\r\n onMouseLeave={() => setTip(null)}\r\n />\r\n ))}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Legend */}\r\n <div className=\"flex items-center gap-1 mt-3 text-[11px] text-neutral-400\">\r\n Less\r\n {colors.map((c, i) => (\r\n <div\r\n key={i}\r\n className=\"w-[13px] h-[13px] rounded-[3px]\"\r\n style={{ backgroundColor: c }}\r\n />\r\n ))}\r\n More\r\n </div>\r\n\r\n {/* Years */}\r\n <div className=\"flex flex-wrap items-center gap-1.5 mt-4 pt-3 border-t border-neutral-800\">\r\n <span className=\"text-[11px] text-neutral-400 mr-1\">\r\n Year:\r\n </span>\r\n\r\n <YearPill\r\n label=\"Last year\"\r\n active={selectedYear === \"last\"}\r\n onClick={() => setSelectedYear(\"last\")}\r\n />\r\n\r\n {years.map((y) => (\r\n <YearPill\r\n key={y}\r\n label={String(y)}\r\n active={selectedYear === y}\r\n onClick={() => setSelectedYear(y)}\r\n />\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n\r\n {tip && <Tooltip day={tip.day} x={tip.x} y={tip.y} />}\r\n </section>\r\n );\r\n}\r\n\r\nexport default memo(GithubActivity);"],"mappings":"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","names":["_","_a"]}
package/dist/index.js CHANGED
@@ -60,9 +60,8 @@ function buildGrid(dayMap, year) {
60
60
  const week = [];
61
61
  for (let d = 0; d < 7; d++) {
62
62
  const iso = cur.toISOString().slice(0, 10);
63
- if (cur > end) {
64
- week.push(null);
65
- } else {
63
+ if (cur > end) week.push(null);
64
+ else {
66
65
  week.push(
67
66
  (_a = dayMap.get(iso)) != null ? _a : {
68
67
  date: iso,
@@ -101,7 +100,7 @@ function Tooltip({ day, x, y }) {
101
100
  return /* @__PURE__ */ jsxs(
102
101
  "div",
103
102
  {
104
- className: "fixed z-50 pointer-events-none -translate-x-1/2 -translate-y-full px-2.5 py-1.5 rounded-md text-xs font-mono whitespace-nowrap shadow-xl bg-neutral-900 text-white dark:bg-white dark:text-neutral-900",
103
+ className: "fixed z-50 pointer-events-none -translate-x-1/2 -translate-y-full px-2.5 py-1.5 rounded-md text-xs font-mono whitespace-nowrap shadow-xl bg-neutral-900 text-white",
105
104
  style: { left: x, top: y - 8 },
106
105
  children: [
107
106
  /* @__PURE__ */ jsxs("b", { children: [
@@ -120,7 +119,7 @@ function Skeleton() {
120
119
  return /* @__PURE__ */ jsx("div", { className: "flex gap-[3px] animate-pulse opacity-40", children: Array.from({ length: 53 }).map((_, w) => /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-[3px]", children: Array.from({ length: 7 }).map((_2, d) => /* @__PURE__ */ jsx(
121
120
  "div",
122
121
  {
123
- className: "w-[13px] h-[13px] rounded-[3px] bg-neutral-300 dark:bg-neutral-700"
122
+ className: "w-[13px] h-[13px] rounded-[3px] bg-neutral-700"
124
123
  },
125
124
  d
126
125
  )) }, w)) });
@@ -136,7 +135,7 @@ function YearPill({
136
135
  onClick,
137
136
  className: [
138
137
  "px-2.5 py-0.5 rounded-full text-[11px] font-medium transition-colors duration-150",
139
- active ? "bg-neutral-900 text-white dark:bg-white dark:text-neutral-900" : "bg-neutral-100 text-neutral-600 hover:bg-neutral-200 dark:bg-neutral-800 dark:text-neutral-400 dark:hover:bg-neutral-700"
138
+ active ? "bg-white text-neutral-900" : "bg-neutral-800 text-neutral-400 hover:bg-neutral-700"
140
139
  ].join(" "),
141
140
  children: label
142
141
  }
@@ -144,89 +143,6 @@ function YearPill({
144
143
  }
145
144
  function GithubActivity({ username, theme = "dark", className }) {
146
145
  var _a;
147
- const STYLES = `
148
- .gcu .relative{position:relative}
149
- .gcu .absolute{position:absolute}
150
- .gcu .fixed{position:fixed}
151
- .gcu .z-50{z-index:50}
152
- .gcu .pointer-events-none{pointer-events:none}
153
- .gcu .flex{display:flex}
154
- .gcu .flex-col{flex-direction:column}
155
- .gcu .flex-wrap{flex-wrap:wrap}
156
- .gcu .items-center{align-items:center}
157
- .gcu .justify-start{justify-content:flex-start}
158
- .gcu .inline-block{display:inline-block}
159
- .gcu .w-full{width:100%}
160
- .gcu .w-\\[10px\\]{width:10px}
161
- .gcu .w-\\[13px\\]{width:13px}
162
- .gcu .h-\\[10px\\]{height:10px}
163
- .gcu .h-\\[13px\\]{height:13px}
164
- .gcu .h-\\[18px\\]{height:18px}
165
- .gcu .gap-\\[3px\\]{gap:3px}
166
- .gcu .gap-1{gap:0.25rem}
167
- .gcu .gap-1\\.5{gap:0.375rem}
168
- .gcu .gap-x-6{column-gap:1.5rem}
169
- .gcu .gap-y-1{row-gap:0.25rem}
170
- .gcu .mb-4{margin-bottom:1rem}
171
- .gcu .mt-3{margin-top:0.75rem}
172
- .gcu .mt-4{margin-top:1rem}
173
- .gcu .mr-1{margin-right:0.25rem}
174
- .gcu .ml-1{margin-left:0.25rem}
175
- .gcu .p-4{padding:1rem}
176
- .gcu .pt-3{padding-top:0.75rem}
177
- .gcu .pt-px{padding-top:1px}
178
- .gcu .pb-1{padding-bottom:0.25rem}
179
- .gcu .pr-1\\.5{padding-right:0.375rem}
180
- .gcu .px-2\\.5{padding-left:0.625rem;padding-right:0.625rem}
181
- .gcu .py-1\\.5{padding-top:0.375rem;padding-bottom:0.375rem}
182
- .gcu .py-0\\.5{padding-top:0.125rem;padding-bottom:0.125rem}
183
- .gcu .rounded-\\[2px\\]{border-radius:2px}
184
- .gcu .rounded-\\[3px\\]{border-radius:3px}
185
- .gcu .rounded-md{border-radius:0.375rem}
186
- .gcu .rounded-full{border-radius:9999px}
187
- .gcu .rounded-xl{border-radius:0.75rem}
188
- .gcu .text-right{text-align:right}
189
- .gcu .text-\\[10px\\]{font-size:10px}
190
- .gcu .text-\\[11px\\]{font-size:11px}
191
- .gcu .text-xs{font-size:0.75rem}
192
- .gcu .text-sm{font-size:0.875rem}
193
- .gcu .font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}
194
- .gcu .font-medium{font-weight:500}
195
- .gcu .font-semibold{font-weight:600}
196
- .gcu .select-none{-webkit-user-select:none;-ms-user-select:none;user-select:none}
197
- .gcu .whitespace-nowrap{white-space:nowrap}
198
- .gcu .overflow-x-auto{overflow-x:auto}
199
- .gcu .overflow-y-visible{overflow-y:visible}
200
- .gcu .border{border-width:1px;border-style:solid;border-color:#e5e5e5}
201
- .gcu .border-t{border-top-width:1px;border-top-style:solid;border-top-color:#e5e5e5}
202
- .gcu .transition-transform{transition-property:transform;transition-timing-function:ease;transition-duration:0.1s}
203
- .gcu .transition-colors{transition-property:color,background-color,border-color;transition-timing-function:ease;transition-duration:0.15s}
204
- .gcu .duration-100{transition-duration:0.1s}
205
- .gcu .duration-150{transition-duration:0.15s}
206
- .gcu .hover\\:scale-125:hover{transform:scale(1.25)}
207
- .gcu .text-neutral-500{color:#6b7280}
208
- .gcu .text-neutral-400{color:#9ca3af}
209
- .gcu .text-neutral-700{color:#374151}
210
- .gcu .text-neutral-200{color:#e5e7eb}
211
- .gcu .bg-white{background-color:#fff}
212
- .gcu .bg-neutral-900{background-color:#171717}
213
- .gcu .bg-neutral-950{background-color:#0a0a0a}
214
- .gcu .bg-neutral-300{background-color:#d4d4d4}
215
- .gcu .text-white{color:#fff}
216
- .gcu .border-neutral-200{border-color:#e5e5e5}
217
- .gcu .border-neutral-800{border-color:#262626}
218
- .gcu .border-neutral-100{border-color:#f5f5f5}
219
- .gcu .shadow-xl{box-shadow:0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04)}
220
- `;
221
- useEffect(() => {
222
- if (typeof document === "undefined") return;
223
- const id = "github-contributions-ui-inline";
224
- if (document.getElementById(id)) return;
225
- const style = document.createElement("style");
226
- style.id = id;
227
- style.textContent = STYLES;
228
- document.head.appendChild(style);
229
- }, []);
230
146
  const [allDays, setAllDays] = useState(/* @__PURE__ */ new Map());
231
147
  const [years, setYears] = useState([]);
232
148
  const [selectedYear, setSelectedYear] = useState("last");
@@ -241,21 +157,17 @@ function GithubActivity({ username, theme = "dark", className }) {
241
157
  useEffect(() => {
242
158
  if (!username) return;
243
159
  let mounted = true;
244
- setLoading(true);
245
- setError(false);
246
160
  (async () => {
247
- var _a2;
248
161
  try {
162
+ setLoading(true);
249
163
  const res = await fetch(
250
164
  `https://github-contributions-api.jogruber.de/v4/${username}?y=all`
251
165
  );
252
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
166
+ if (!res.ok) throw new Error();
253
167
  const json = await res.json();
254
- const raw = (_a2 = json.contributions) != null ? _a2 : [];
255
- if (!raw.length) throw new Error("empty data");
256
168
  const map = /* @__PURE__ */ new Map();
257
169
  const yearSet = /* @__PURE__ */ new Set();
258
- raw.forEach((c) => {
170
+ json.contributions.forEach((c) => {
259
171
  map.set(c.date, {
260
172
  date: c.date,
261
173
  count: c.count,
@@ -263,17 +175,14 @@ function GithubActivity({ username, theme = "dark", className }) {
263
175
  });
264
176
  yearSet.add(new Date(c.date).getFullYear());
265
177
  });
266
- if (mounted) {
267
- setAllDays(map);
268
- setYears(Array.from(yearSet).sort((a, b) => b - a));
269
- setLoading(false);
270
- }
271
- } catch (err) {
272
- console.warn("GithubActivity fetch error:", err);
273
- if (mounted) {
274
- setError(true);
275
- setLoading(false);
276
- }
178
+ if (!mounted) return;
179
+ setAllDays(map);
180
+ setYears(Array.from(yearSet).sort((a, b) => b - a));
181
+ setError(false);
182
+ } catch {
183
+ if (mounted) setError(true);
184
+ } finally {
185
+ if (mounted) setLoading(false);
277
186
  }
278
187
  })();
279
188
  return () => {
@@ -290,12 +199,11 @@ function GithubActivity({ username, theme = "dark", className }) {
290
199
  }
291
200
  return new Date(d.date).getFullYear() === selectedYear;
292
201
  });
293
- const sum = entries.reduce((s, d) => s + d.count, 0);
202
+ setTotal(entries.reduce((s, d) => s + d.count, 0));
294
203
  const best = entries.reduce(
295
204
  (b, d) => !b || d.count > b.count ? d : b,
296
205
  null
297
206
  );
298
- setTotal(sum);
299
207
  setBestDay(best && best.count > 0 ? best : null);
300
208
  }, [allDays, selectedYear]);
301
209
  const grid = useMemo(
@@ -304,19 +212,9 @@ function GithubActivity({ username, theme = "dark", className }) {
304
212
  );
305
213
  const labels = useMemo(() => monthLabels(grid), [grid]);
306
214
  const outlineColor = theme === "light" ? "#333" : "#f0f0f0";
307
- const bestDateLabel = bestDay ? new Date(bestDay.date).toLocaleDateString("en-US", {
308
- month: "short",
309
- day: "numeric",
310
- year: "numeric"
311
- }) : null;
312
- const periodLabel = selectedYear === "last" ? " in the last year" : ` in ${selectedYear}`;
313
- return /* @__PURE__ */ jsxs("section", { className: ["gcu w-full font-mono", className].join(" ").trim(), children: [
314
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1 mb-4 text-xs text-neutral-500 dark:text-neutral-400", children: [
315
- loading ? "Loading\u2026" : error ? "Unavailable" : /* @__PURE__ */ jsxs(Fragment, { children: [
316
- /* @__PURE__ */ jsx("span", { className: "font-semibold text-neutral-700 dark:text-neutral-200", children: total == null ? void 0 : total.toLocaleString() }),
317
- " contributions",
318
- periodLabel
319
- ] }),
215
+ return /* @__PURE__ */ jsxs("section", { className: ["w-full font-mono", className].join(" ").trim(), children: [
216
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1 mb-4 text-xs text-neutral-400", children: [
217
+ loading ? "Loading\u2026" : error ? "Unavailable" : `${total == null ? void 0 : total.toLocaleString()} contributions ${selectedYear === "last" ? "in the last year" : `in ${selectedYear}`}`,
320
218
  bestDay && !loading && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
321
219
  /* @__PURE__ */ jsx(
322
220
  "span",
@@ -326,16 +224,11 @@ function GithubActivity({ username, theme = "dark", className }) {
326
224
  }
327
225
  ),
328
226
  "Best day:",
329
- /* @__PURE__ */ jsxs("span", { className: "font-semibold text-neutral-700 dark:text-neutral-200", children: [
330
- bestDay.count,
331
- " contributions"
332
- ] }),
333
- "on ",
334
- bestDateLabel
227
+ /* @__PURE__ */ jsx("span", { className: "text-neutral-200 font-semibold", children: bestDay.count })
335
228
  ] })
336
229
  ] }),
337
- /* @__PURE__ */ jsx("div", { className: "border border-neutral-200 dark:border-neutral-800 rounded-xl p-4 bg-white dark:bg-neutral-950", children: error ? /* @__PURE__ */ jsx("p", { className: "text-sm italic text-neutral-400", children: "GitHub activity unavailable." }) : loading ? /* @__PURE__ */ jsx(Skeleton, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
338
- /* @__PURE__ */ jsx("div", { className: "overflow-x-auto overflow-y-visible pb-1", children: /* @__PURE__ */ jsxs(
230
+ /* @__PURE__ */ jsx("div", { className: "border border-neutral-800 rounded-xl p-4 bg-neutral-950", children: error ? /* @__PURE__ */ jsx("p", { className: "text-sm italic text-neutral-400", children: "GitHub activity unavailable." }) : loading ? /* @__PURE__ */ jsx(Skeleton, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
231
+ /* @__PURE__ */ jsx("div", { className: "overflow-x-auto pb-1", children: /* @__PURE__ */ jsxs(
339
232
  "div",
340
233
  {
341
234
  className: "relative",
@@ -351,11 +244,11 @@ function GithubActivity({ username, theme = "dark", className }) {
351
244
  children: labels.map(({ label, col }) => /* @__PURE__ */ jsx(
352
245
  "span",
353
246
  {
354
- className: "absolute text-[11px] select-none text-neutral-500 dark:text-neutral-400",
247
+ className: "absolute text-[11px] text-neutral-400",
355
248
  style: { left: col * STEP },
356
249
  children: label
357
250
  },
358
- `${label}-${col}`
251
+ label + col
359
252
  ))
360
253
  }
361
254
  ),
@@ -363,14 +256,14 @@ function GithubActivity({ username, theme = "dark", className }) {
363
256
  /* @__PURE__ */ jsx(
364
257
  "div",
365
258
  {
366
- className: "flex flex-col gap-[3px] pt-px shrink-0",
259
+ className: "flex flex-col gap-[3px]",
367
260
  style: { width: DAY_COL_W - GAP },
368
261
  children: Array.from({ length: 7 }).map((_, i) => {
369
262
  var _a2;
370
263
  return /* @__PURE__ */ jsx(
371
264
  "div",
372
265
  {
373
- className: "h-[13px] text-[10px] leading-[13px] text-right pr-1.5 select-none text-neutral-500 dark:text-neutral-400",
266
+ className: "h-[13px] text-[10px] text-right pr-1.5 text-neutral-400",
374
267
  children: (_a2 = DAY_LABELS[i]) != null ? _a2 : ""
375
268
  },
376
269
  i
@@ -381,10 +274,9 @@ function GithubActivity({ username, theme = "dark", className }) {
381
274
  grid.map((week, wi) => /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-[3px]", children: week.map((day, di) => /* @__PURE__ */ jsx(
382
275
  "div",
383
276
  {
384
- className: "w-[13px] h-[13px] rounded-[3px] transition-transform duration-100 hover:scale-125",
277
+ className: "w-[13px] h-[13px] rounded-[3px] transition-transform hover:scale-125",
385
278
  style: {
386
279
  backgroundColor: day ? colors[day.level] : "transparent",
387
- cursor: day ? "pointer" : "default",
388
280
  outline: bestDay && (day == null ? void 0 : day.date) === bestDay.date ? `2px solid ${outlineColor}` : "none",
389
281
  outlineOffset: "1px"
390
282
  },
@@ -405,8 +297,8 @@ function GithubActivity({ username, theme = "dark", className }) {
405
297
  ]
406
298
  }
407
299
  ) }),
408
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-start gap-1 mt-3", children: [
409
- /* @__PURE__ */ jsx("span", { className: "text-[11px] text-neutral-500 dark:text-neutral-400 mr-1", children: "Less" }),
300
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 mt-3 text-[11px] text-neutral-400", children: [
301
+ "Less",
410
302
  colors.map((c, i) => /* @__PURE__ */ jsx(
411
303
  "div",
412
304
  {
@@ -415,9 +307,9 @@ function GithubActivity({ username, theme = "dark", className }) {
415
307
  },
416
308
  i
417
309
  )),
418
- /* @__PURE__ */ jsx("span", { className: "text-[11px] text-neutral-500 dark:text-neutral-400 ml-1", children: "More" })
310
+ "More"
419
311
  ] }),
420
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5 mt-4 pt-3 border-t border-neutral-100 dark:border-neutral-800", children: [
312
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5 mt-4 pt-3 border-t border-neutral-800", children: [
421
313
  /* @__PURE__ */ jsx("span", { className: "text-[11px] text-neutral-400 mr-1", children: "Year:" }),
422
314
  /* @__PURE__ */ jsx(
423
315
  YearPill,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/GithubActivity.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { memo, useEffect, useState, useMemo } from \"react\";\r\n\r\ntype Theme = \"light\" | \"dark\" | \"blue\" | \"purple\";\r\n\r\ninterface Day {\r\n date: string;\r\n count: number;\r\n level: 0 | 1 | 2 | 3 | 4;\r\n}\r\n\r\ninterface Props {\r\n username: string;\r\n theme?: Theme;\r\n className?: string;\r\n}\r\n\r\n/* ---------- Constants ---------- */\r\n\r\nconst MONTHS = [\r\n \"Jan\",\r\n \"Feb\",\r\n \"Mar\",\r\n \"Apr\",\r\n \"May\",\r\n \"Jun\",\r\n \"Jul\",\r\n \"Aug\",\r\n \"Sep\",\r\n \"Oct\",\r\n \"Nov\",\r\n \"Dec\",\r\n];\r\nconst DAY_LABELS: Record<number, string> = { 1: \"Mon\", 3: \"Wed\", 5: \"Fri\" };\r\n\r\nconst CELL = 13;\r\nconst GAP = 3;\r\nconst STEP = CELL + GAP;\r\nconst DAY_COL_W = 30;\r\n\r\n/* ---------- Color Themes ---------- */\r\n\r\nconst LIGHT = [\"#ebedf0\", \"#9be9a8\", \"#40c463\", \"#30a14e\", \"#216e39\"];\r\nconst DARK = [\"#21262d\", \"#0e4429\", \"#006d32\", \"#26a641\", \"#39d353\"];\r\nconst BLUE = [\"#21262d\", \"#a3c9ff\", \"#5fa3ff\", \"#2f7bff\", \"#0b5cff\"];\r\nconst PURPLE = [\"#21262d\", \"#d8b4ff\", \"#c084fc\", \"#a855f7\", \"#7e22ce\"];\r\n\r\nconst COLOR_MAP: Record<Theme, string[]> = {\r\n light: LIGHT,\r\n dark: DARK,\r\n blue: BLUE,\r\n purple: PURPLE,\r\n};\r\n\r\n/* ---------- Utilities ---------- */\r\n\r\nfunction toLevel(count: number): 0 | 1 | 2 | 3 | 4 {\r\n if (count === 0) return 0;\r\n if (count <= 3) return 1;\r\n if (count <= 6) return 2;\r\n if (count <= 9) return 3;\r\n return 4;\r\n}\r\n\r\nfunction buildGrid(\r\n dayMap: Map<string, Day>,\r\n year: number | \"last\",\r\n): (Day | null)[][] {\r\n let start: Date;\r\n let end: Date;\r\n\r\n if (year === \"last\") {\r\n end = new Date();\r\n start = new Date(end);\r\n start.setFullYear(start.getFullYear() - 1);\r\n start.setDate(start.getDate() + 1);\r\n } else {\r\n start = new Date(year, 0, 1);\r\n end =\r\n year === new Date().getFullYear() ? new Date() : new Date(year, 11, 31);\r\n }\r\n\r\n start.setDate(start.getDate() - start.getDay());\r\n\r\n const weeks: (Day | null)[][] = [];\r\n const cur = new Date(start);\r\n\r\n while (cur <= end) {\r\n const week: (Day | null)[] = [];\r\n\r\n for (let d = 0; d < 7; d++) {\r\n const iso = cur.toISOString().slice(0, 10);\r\n\r\n if (cur > end) {\r\n week.push(null);\r\n } else {\r\n week.push(\r\n dayMap.get(iso) ?? {\r\n date: iso,\r\n count: 0,\r\n level: 0,\r\n },\r\n );\r\n }\r\n\r\n cur.setDate(cur.getDate() + 1);\r\n }\r\n\r\n weeks.push(week);\r\n }\r\n\r\n return weeks;\r\n}\r\n\r\nfunction monthLabels(grid: (Day | null)[][]) {\r\n const out: { label: string; col: number }[] = [];\r\n let last = -1;\r\n\r\n grid.forEach((week, i) => {\r\n const first = week.find(Boolean);\r\n if (!first) return;\r\n\r\n const m = new Date(first.date).getMonth();\r\n\r\n if (m !== last) {\r\n out.push({ label: MONTHS[m], col: i });\r\n last = m;\r\n }\r\n });\r\n\r\n return out;\r\n}\r\n\r\n/* ---------- UI Components ---------- */\r\n\r\nfunction Tooltip({ day, x, y }: { day: Day; x: number; y: number }) {\r\n const label = new Date(day.date).toLocaleDateString(\"en-US\", {\r\n weekday: \"long\",\r\n year: \"numeric\",\r\n month: \"long\",\r\n day: \"numeric\",\r\n });\r\n\r\n return (\r\n <div\r\n className=\"fixed z-50 pointer-events-none -translate-x-1/2 -translate-y-full px-2.5 py-1.5 rounded-md text-xs font-mono whitespace-nowrap shadow-xl bg-neutral-900 text-white dark:bg-white dark:text-neutral-900\"\r\n style={{ left: x, top: y - 8 }}\r\n >\r\n <b>\r\n {day.count} contribution{day.count !== 1 ? \"s\" : \"\"}\r\n </b>{\" \"}\r\n · {label}\r\n </div>\r\n );\r\n}\r\n\r\nfunction Skeleton() {\r\n return (\r\n <div className=\"flex gap-[3px] animate-pulse opacity-40\">\r\n {Array.from({ length: 53 }).map((_, w) => (\r\n <div key={w} className=\"flex flex-col gap-[3px]\">\r\n {Array.from({ length: 7 }).map((_, d) => (\r\n <div\r\n key={d}\r\n className=\"w-[13px] h-[13px] rounded-[3px] bg-neutral-300 dark:bg-neutral-700\"\r\n />\r\n ))}\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n\r\nfunction YearPill({\r\n label,\r\n active,\r\n onClick,\r\n}: {\r\n label: string;\r\n active: boolean;\r\n onClick: () => void;\r\n}) {\r\n return (\r\n <button\r\n onClick={onClick}\r\n className={[\r\n \"px-2.5 py-0.5 rounded-full text-[11px] font-medium transition-colors duration-150\",\r\n active\r\n ? \"bg-neutral-900 text-white dark:bg-white dark:text-neutral-900\"\r\n : \"bg-neutral-100 text-neutral-600 hover:bg-neutral-200 dark:bg-neutral-800 dark:text-neutral-400 dark:hover:bg-neutral-700\",\r\n ].join(\" \")}\r\n >\r\n {label}\r\n </button>\r\n );\r\n}\r\n\r\n/* ---------- Main Component ---------- */\r\n\r\nfunction GithubActivity({ username, theme = \"dark\", className }: Props) {\r\n const STYLES = `\r\n .gcu .relative{position:relative}\r\n .gcu .absolute{position:absolute}\r\n .gcu .fixed{position:fixed}\r\n .gcu .z-50{z-index:50}\r\n .gcu .pointer-events-none{pointer-events:none}\r\n .gcu .flex{display:flex}\r\n .gcu .flex-col{flex-direction:column}\r\n .gcu .flex-wrap{flex-wrap:wrap}\r\n .gcu .items-center{align-items:center}\r\n .gcu .justify-start{justify-content:flex-start}\r\n .gcu .inline-block{display:inline-block}\r\n .gcu .w-full{width:100%}\r\n .gcu .w-\\\\[10px\\\\]{width:10px}\r\n .gcu .w-\\\\[13px\\\\]{width:13px}\r\n .gcu .h-\\\\[10px\\\\]{height:10px}\r\n .gcu .h-\\\\[13px\\\\]{height:13px}\r\n .gcu .h-\\\\[18px\\\\]{height:18px}\r\n .gcu .gap-\\\\[3px\\\\]{gap:3px}\r\n .gcu .gap-1{gap:0.25rem}\r\n .gcu .gap-1\\\\.5{gap:0.375rem}\r\n .gcu .gap-x-6{column-gap:1.5rem}\r\n .gcu .gap-y-1{row-gap:0.25rem}\r\n .gcu .mb-4{margin-bottom:1rem}\r\n .gcu .mt-3{margin-top:0.75rem}\r\n .gcu .mt-4{margin-top:1rem}\r\n .gcu .mr-1{margin-right:0.25rem}\r\n .gcu .ml-1{margin-left:0.25rem}\r\n .gcu .p-4{padding:1rem}\r\n .gcu .pt-3{padding-top:0.75rem}\r\n .gcu .pt-px{padding-top:1px}\r\n .gcu .pb-1{padding-bottom:0.25rem}\r\n .gcu .pr-1\\\\.5{padding-right:0.375rem}\r\n .gcu .px-2\\\\.5{padding-left:0.625rem;padding-right:0.625rem}\r\n .gcu .py-1\\\\.5{padding-top:0.375rem;padding-bottom:0.375rem}\r\n .gcu .py-0\\\\.5{padding-top:0.125rem;padding-bottom:0.125rem}\r\n .gcu .rounded-\\\\[2px\\\\]{border-radius:2px}\r\n .gcu .rounded-\\\\[3px\\\\]{border-radius:3px}\r\n .gcu .rounded-md{border-radius:0.375rem}\r\n .gcu .rounded-full{border-radius:9999px}\r\n .gcu .rounded-xl{border-radius:0.75rem}\r\n .gcu .text-right{text-align:right}\r\n .gcu .text-\\\\[10px\\\\]{font-size:10px}\r\n .gcu .text-\\\\[11px\\\\]{font-size:11px}\r\n .gcu .text-xs{font-size:0.75rem}\r\n .gcu .text-sm{font-size:0.875rem}\r\n .gcu .font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace}\r\n .gcu .font-medium{font-weight:500}\r\n .gcu .font-semibold{font-weight:600}\r\n .gcu .select-none{-webkit-user-select:none;-ms-user-select:none;user-select:none}\r\n .gcu .whitespace-nowrap{white-space:nowrap}\r\n .gcu .overflow-x-auto{overflow-x:auto}\r\n .gcu .overflow-y-visible{overflow-y:visible}\r\n .gcu .border{border-width:1px;border-style:solid;border-color:#e5e5e5}\r\n .gcu .border-t{border-top-width:1px;border-top-style:solid;border-top-color:#e5e5e5}\r\n .gcu .transition-transform{transition-property:transform;transition-timing-function:ease;transition-duration:0.1s}\r\n .gcu .transition-colors{transition-property:color,background-color,border-color;transition-timing-function:ease;transition-duration:0.15s}\r\n .gcu .duration-100{transition-duration:0.1s}\r\n .gcu .duration-150{transition-duration:0.15s}\r\n .gcu .hover\\\\:scale-125:hover{transform:scale(1.25)}\r\n .gcu .text-neutral-500{color:#6b7280}\r\n .gcu .text-neutral-400{color:#9ca3af}\r\n .gcu .text-neutral-700{color:#374151}\r\n .gcu .text-neutral-200{color:#e5e7eb}\r\n .gcu .bg-white{background-color:#fff}\r\n .gcu .bg-neutral-900{background-color:#171717}\r\n .gcu .bg-neutral-950{background-color:#0a0a0a}\r\n .gcu .bg-neutral-300{background-color:#d4d4d4}\r\n .gcu .text-white{color:#fff}\r\n .gcu .border-neutral-200{border-color:#e5e5e5}\r\n .gcu .border-neutral-800{border-color:#262626}\r\n .gcu .border-neutral-100{border-color:#f5f5f5}\r\n .gcu .shadow-xl{box-shadow:0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04)}\r\n `;\r\n\r\n useEffect(() => {\r\n if (typeof document === \"undefined\") return;\r\n const id = \"github-contributions-ui-inline\";\r\n if (document.getElementById(id)) return;\r\n const style = document.createElement(\"style\");\r\n style.id = id;\r\n style.textContent = STYLES;\r\n document.head.appendChild(style);\r\n }, []);\r\n const [allDays, setAllDays] = useState<Map<string, Day>>(new Map());\r\n const [years, setYears] = useState<number[]>([]);\r\n const [selectedYear, setSelectedYear] = useState<number | \"last\">(\"last\");\r\n const [total, setTotal] = useState<number | null>(null);\r\n const [bestDay, setBestDay] = useState<Day | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [error, setError] = useState(false);\r\n const [tip, setTip] = useState<{ day: Day; x: number; y: number } | null>(\r\n null,\r\n );\r\n\r\n const colors = COLOR_MAP[theme] ?? COLOR_MAP.dark;\r\n\r\n /* Fetch Contributions */\r\n\r\n useEffect(() => {\r\n if (!username) return;\r\n\r\n let mounted = true;\r\n setLoading(true);\r\n setError(false);\r\n\r\n (async () => {\r\n try {\r\n const res = await fetch(\r\n `https://github-contributions-api.jogruber.de/v4/${username}?y=all`,\r\n );\r\n\r\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n\r\n const json = await res.json();\r\n const raw: { date: string; count: number }[] = json.contributions ?? [];\r\n\r\n if (!raw.length) throw new Error(\"empty data\");\r\n\r\n const map = new Map<string, Day>();\r\n const yearSet = new Set<number>();\r\n\r\n raw.forEach((c) => {\r\n map.set(c.date, {\r\n date: c.date,\r\n count: c.count,\r\n level: toLevel(c.count),\r\n });\r\n\r\n yearSet.add(new Date(c.date).getFullYear());\r\n });\r\n\r\n if (mounted) {\r\n setAllDays(map);\r\n setYears(Array.from(yearSet).sort((a, b) => b - a));\r\n setLoading(false);\r\n }\r\n } catch (err) {\r\n console.warn(\"GithubActivity fetch error:\", err);\r\n\r\n if (mounted) {\r\n setError(true);\r\n setLoading(false);\r\n }\r\n }\r\n })();\r\n\r\n return () => {\r\n mounted = false;\r\n };\r\n }, [username]);\r\n\r\n /* Stats Calculation */\r\n\r\n useEffect(() => {\r\n if (!allDays.size) return;\r\n\r\n const entries = Array.from(allDays.values()).filter((d) => {\r\n if (selectedYear === \"last\") {\r\n const oneYearAgo = new Date();\r\n oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);\r\n return new Date(d.date) >= oneYearAgo;\r\n }\r\n\r\n return new Date(d.date).getFullYear() === selectedYear;\r\n });\r\n\r\n const sum = entries.reduce((s, d) => s + d.count, 0);\r\n\r\n const best = entries.reduce<Day | null>(\r\n (b, d) => (!b || d.count > b.count ? d : b),\r\n null,\r\n );\r\n\r\n setTotal(sum);\r\n setBestDay(best && best.count > 0 ? best : null);\r\n }, [allDays, selectedYear]);\r\n\r\n /* Rendering Helpers */\r\n\r\n const grid = useMemo(\r\n () => (allDays.size ? buildGrid(allDays, selectedYear) : []),\r\n [allDays, selectedYear],\r\n );\r\n\r\n const labels = useMemo(() => monthLabels(grid), [grid]);\r\n\r\n const outlineColor = theme === \"light\" ? \"#333\" : \"#f0f0f0\";\r\n\r\n const bestDateLabel = bestDay\r\n ? new Date(bestDay.date).toLocaleDateString(\"en-US\", {\r\n month: \"short\",\r\n day: \"numeric\",\r\n year: \"numeric\",\r\n })\r\n : null;\r\n\r\n const periodLabel =\r\n selectedYear === \"last\" ? \" in the last year\" : ` in ${selectedYear}`;\r\n\r\n return (\r\n <section className={[\"gcu w-full font-mono\", className].join(\" \").trim()}>\r\n <div className=\"flex flex-wrap items-center gap-x-6 gap-y-1 mb-4 text-xs text-neutral-500 dark:text-neutral-400\">\r\n {loading ? (\r\n \"Loading…\"\r\n ) : error ? (\r\n \"Unavailable\"\r\n ) : (\r\n <>\r\n <span className=\"font-semibold text-neutral-700 dark:text-neutral-200\">\r\n {total?.toLocaleString()}\r\n </span>\r\n {\" contributions\"}\r\n {periodLabel}\r\n </>\r\n )}\r\n\r\n {bestDay && !loading && (\r\n <span className=\"flex items-center gap-1.5\">\r\n <span\r\n className=\"inline-block w-[10px] h-[10px] rounded-[2px]\"\r\n style={{ backgroundColor: colors[4] }}\r\n />\r\n Best day:\r\n <span className=\"font-semibold text-neutral-700 dark:text-neutral-200\">\r\n {bestDay.count} contributions\r\n </span>\r\n on {bestDateLabel}\r\n </span>\r\n )}\r\n </div>\r\n\r\n <div className=\"border border-neutral-200 dark:border-neutral-800 rounded-xl p-4 bg-white dark:bg-neutral-950\">\r\n {error ? (\r\n <p className=\"text-sm italic text-neutral-400\">\r\n GitHub activity unavailable.\r\n </p>\r\n ) : loading ? (\r\n <Skeleton />\r\n ) : (\r\n <>\r\n <div className=\"overflow-x-auto overflow-y-visible pb-1\">\r\n <div\r\n className=\"relative\"\r\n style={{\r\n minWidth: grid.length * STEP + DAY_COL_W + 8,\r\n }}\r\n >\r\n <div\r\n className=\"relative h-[18px] mb-1\"\r\n style={{ marginLeft: DAY_COL_W }}\r\n >\r\n {labels.map(({ label, col }) => (\r\n <span\r\n key={`${label}-${col}`}\r\n className=\"absolute text-[11px] select-none text-neutral-500 dark:text-neutral-400\"\r\n style={{ left: col * STEP }}\r\n >\r\n {label}\r\n </span>\r\n ))}\r\n </div>\r\n\r\n <div className=\"flex gap-[3px]\">\r\n <div\r\n className=\"flex flex-col gap-[3px] pt-px shrink-0\"\r\n style={{ width: DAY_COL_W - GAP }}\r\n >\r\n {Array.from({ length: 7 }).map((_, i) => (\r\n <div\r\n key={i}\r\n className=\"h-[13px] text-[10px] leading-[13px] text-right pr-1.5 select-none text-neutral-500 dark:text-neutral-400\"\r\n >\r\n {DAY_LABELS[i] ?? \"\"}\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {grid.map((week, wi) => (\r\n <div key={wi} className=\"flex flex-col gap-[3px]\">\r\n {week.map((day, di) => (\r\n <div\r\n key={di}\r\n className=\"w-[13px] h-[13px] rounded-[3px] transition-transform duration-100 hover:scale-125\"\r\n style={{\r\n backgroundColor: day\r\n ? colors[day.level]\r\n : \"transparent\",\r\n cursor: day ? \"pointer\" : \"default\",\r\n outline:\r\n bestDay && day?.date === bestDay.date\r\n ? `2px solid ${outlineColor}`\r\n : \"none\",\r\n outlineOffset: \"1px\",\r\n }}\r\n onMouseEnter={(e) => {\r\n if (!day) return;\r\n\r\n const r = e.currentTarget.getBoundingClientRect();\r\n\r\n setTip({\r\n day,\r\n x: r.left + r.width / 2,\r\n y: r.top,\r\n });\r\n }}\r\n onMouseLeave={() => setTip(null)}\r\n />\r\n ))}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex items-center justify-start gap-1 mt-3\">\r\n <span className=\"text-[11px] text-neutral-500 dark:text-neutral-400 mr-1\">\r\n Less\r\n </span>\r\n\r\n {colors.map((c, i) => (\r\n <div\r\n key={i}\r\n className=\"w-[13px] h-[13px] rounded-[3px]\"\r\n style={{ backgroundColor: c }}\r\n />\r\n ))}\r\n\r\n <span className=\"text-[11px] text-neutral-500 dark:text-neutral-400 ml-1\">\r\n More\r\n </span>\r\n </div>\r\n\r\n <div className=\"flex flex-wrap items-center gap-1.5 mt-4 pt-3 border-t border-neutral-100 dark:border-neutral-800\">\r\n <span className=\"text-[11px] text-neutral-400 mr-1\">Year:</span>\r\n\r\n <YearPill\r\n label=\"Last year\"\r\n active={selectedYear === \"last\"}\r\n onClick={() => setSelectedYear(\"last\")}\r\n />\r\n\r\n {years.map((y) => (\r\n <YearPill\r\n key={y}\r\n label={String(y)}\r\n active={selectedYear === y}\r\n onClick={() => setSelectedYear(y)}\r\n />\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n\r\n {tip && <Tooltip day={tip.day} x={tip.x} y={tip.y} />}\r\n </section>\r\n );\r\n}\r\n\r\nexport default memo(GithubActivity);\r\n"],"mappings":"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","names":["_","_a"]}
1
+ {"version":3,"sources":["../src/GithubActivity.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { memo, useEffect, useState, useMemo } from \"react\";\r\n\r\ntype Theme = \"light\" | \"dark\" | \"blue\" | \"purple\";\r\n\r\ninterface Day {\r\n date: string;\r\n count: number;\r\n level: 0 | 1 | 2 | 3 | 4;\r\n}\r\n\r\ninterface Props {\r\n username: string;\r\n theme?: Theme;\r\n className?: string;\r\n}\r\n\r\n/* ---------- Constants ---------- */\r\n\r\nconst MONTHS = [\r\n \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\r\n \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\",\r\n];\r\n\r\nconst DAY_LABELS: Record<number, string> = { 1: \"Mon\", 3: \"Wed\", 5: \"Fri\" };\r\n\r\nconst CELL = 13;\r\nconst GAP = 3;\r\nconst STEP = CELL + GAP;\r\nconst DAY_COL_W = 30;\r\n\r\n/* ---------- Graph Color Themes ---------- */\r\n\r\nconst LIGHT = [\"#ebedf0\", \"#9be9a8\", \"#40c463\", \"#30a14e\", \"#216e39\"];\r\nconst DARK = [\"#21262d\", \"#0e4429\", \"#006d32\", \"#26a641\", \"#39d353\"];\r\nconst BLUE = [\"#21262d\", \"#a3c9ff\", \"#5fa3ff\", \"#2f7bff\", \"#0b5cff\"];\r\nconst PURPLE = [\"#21262d\", \"#d8b4ff\", \"#c084fc\", \"#a855f7\", \"#7e22ce\"];\r\n\r\nconst COLOR_MAP: Record<Theme, string[]> = {\r\n light: LIGHT,\r\n dark: DARK,\r\n blue: BLUE,\r\n purple: PURPLE,\r\n};\r\n\r\n/* ---------- Utilities ---------- */\r\n\r\nfunction toLevel(count: number): 0 | 1 | 2 | 3 | 4 {\r\n if (count === 0) return 0;\r\n if (count <= 3) return 1;\r\n if (count <= 6) return 2;\r\n if (count <= 9) return 3;\r\n return 4;\r\n}\r\n\r\nfunction buildGrid(\r\n dayMap: Map<string, Day>,\r\n year: number | \"last\",\r\n): (Day | null)[][] {\r\n let start: Date;\r\n let end: Date;\r\n\r\n if (year === \"last\") {\r\n end = new Date();\r\n start = new Date(end);\r\n start.setFullYear(start.getFullYear() - 1);\r\n start.setDate(start.getDate() + 1);\r\n } else {\r\n start = new Date(year, 0, 1);\r\n end =\r\n year === new Date().getFullYear()\r\n ? new Date()\r\n : new Date(year, 11, 31);\r\n }\r\n\r\n start.setDate(start.getDate() - start.getDay());\r\n\r\n const weeks: (Day | null)[][] = [];\r\n const cur = new Date(start);\r\n\r\n while (cur <= end) {\r\n const week: (Day | null)[] = [];\r\n\r\n for (let d = 0; d < 7; d++) {\r\n const iso = cur.toISOString().slice(0, 10);\r\n\r\n if (cur > end) week.push(null);\r\n else {\r\n week.push(\r\n dayMap.get(iso) ?? {\r\n date: iso,\r\n count: 0,\r\n level: 0,\r\n },\r\n );\r\n }\r\n\r\n cur.setDate(cur.getDate() + 1);\r\n }\r\n\r\n weeks.push(week);\r\n }\r\n\r\n return weeks;\r\n}\r\n\r\nfunction monthLabels(grid: (Day | null)[][]) {\r\n const out: { label: string; col: number }[] = [];\r\n let last = -1;\r\n\r\n grid.forEach((week, i) => {\r\n const first = week.find(Boolean);\r\n if (!first) return;\r\n\r\n const m = new Date(first.date).getMonth();\r\n\r\n if (m !== last) {\r\n out.push({ label: MONTHS[m], col: i });\r\n last = m;\r\n }\r\n });\r\n\r\n return out;\r\n}\r\n\r\n/* ---------- UI Components ---------- */\r\n\r\nfunction Tooltip({ day, x, y }: { day: Day; x: number; y: number }) {\r\n const label = new Date(day.date).toLocaleDateString(\"en-US\", {\r\n weekday: \"long\",\r\n year: \"numeric\",\r\n month: \"long\",\r\n day: \"numeric\",\r\n });\r\n\r\n return (\r\n <div\r\n className=\"fixed z-50 pointer-events-none -translate-x-1/2 -translate-y-full px-2.5 py-1.5 rounded-md text-xs font-mono whitespace-nowrap shadow-xl bg-neutral-900 text-white\"\r\n style={{ left: x, top: y - 8 }}\r\n >\r\n <b>\r\n {day.count} contribution{day.count !== 1 ? \"s\" : \"\"}\r\n </b>{\" \"}\r\n · {label}\r\n </div>\r\n );\r\n}\r\n\r\nfunction Skeleton() {\r\n return (\r\n <div className=\"flex gap-[3px] animate-pulse opacity-40\">\r\n {Array.from({ length: 53 }).map((_, w) => (\r\n <div key={w} className=\"flex flex-col gap-[3px]\">\r\n {Array.from({ length: 7 }).map((_, d) => (\r\n <div\r\n key={d}\r\n className=\"w-[13px] h-[13px] rounded-[3px] bg-neutral-700\"\r\n />\r\n ))}\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n\r\nfunction YearPill({\r\n label,\r\n active,\r\n onClick,\r\n}: {\r\n label: string;\r\n active: boolean;\r\n onClick: () => void;\r\n}) {\r\n return (\r\n <button\r\n onClick={onClick}\r\n className={[\r\n \"px-2.5 py-0.5 rounded-full text-[11px] font-medium transition-colors duration-150\",\r\n active\r\n ? \"bg-white text-neutral-900\"\r\n : \"bg-neutral-800 text-neutral-400 hover:bg-neutral-700\",\r\n ].join(\" \")}\r\n >\r\n {label}\r\n </button>\r\n );\r\n}\r\n\r\n/* ---------- Main Component ---------- */\r\n\r\nfunction GithubActivity({ username, theme = \"dark\", className }: Props) {\r\n const [allDays, setAllDays] = useState<Map<string, Day>>(new Map());\r\n const [years, setYears] = useState<number[]>([]);\r\n const [selectedYear, setSelectedYear] =\r\n useState<number | \"last\">(\"last\");\r\n\r\n const [total, setTotal] = useState<number | null>(null);\r\n const [bestDay, setBestDay] = useState<Day | null>(null);\r\n\r\n const [loading, setLoading] = useState(true);\r\n const [error, setError] = useState(false);\r\n\r\n const [tip, setTip] = useState<{ day: Day; x: number; y: number } | null>(\r\n null,\r\n );\r\n\r\n const colors = COLOR_MAP[theme] ?? COLOR_MAP.dark;\r\n\r\n /* ---------- Fetch ---------- */\r\n\r\n useEffect(() => {\r\n if (!username) return;\r\n\r\n let mounted = true;\r\n\r\n (async () => {\r\n try {\r\n setLoading(true);\r\n const res = await fetch(\r\n `https://github-contributions-api.jogruber.de/v4/${username}?y=all`,\r\n );\r\n\r\n if (!res.ok) throw new Error();\r\n\r\n const json = await res.json();\r\n\r\n const map = new Map<string, Day>();\r\n const yearSet = new Set<number>();\r\n\r\n json.contributions.forEach((c: any) => {\r\n map.set(c.date, {\r\n date: c.date,\r\n count: c.count,\r\n level: toLevel(c.count),\r\n });\r\n\r\n yearSet.add(new Date(c.date).getFullYear());\r\n });\r\n\r\n if (!mounted) return;\r\n\r\n setAllDays(map);\r\n setYears(Array.from(yearSet).sort((a, b) => b - a));\r\n setError(false);\r\n } catch {\r\n if (mounted) setError(true);\r\n } finally {\r\n if (mounted) setLoading(false);\r\n }\r\n })();\r\n\r\n return () => {\r\n mounted = false;\r\n };\r\n }, [username]);\r\n\r\n /* ---------- Stats ---------- */\r\n\r\n useEffect(() => {\r\n if (!allDays.size) return;\r\n\r\n const entries = Array.from(allDays.values()).filter((d) => {\r\n if (selectedYear === \"last\") {\r\n const oneYearAgo = new Date();\r\n oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);\r\n return new Date(d.date) >= oneYearAgo;\r\n }\r\n return new Date(d.date).getFullYear() === selectedYear;\r\n });\r\n\r\n setTotal(entries.reduce((s, d) => s + d.count, 0));\r\n\r\n const best = entries.reduce<Day | null>(\r\n (b, d) => (!b || d.count > b.count ? d : b),\r\n null,\r\n );\r\n\r\n setBestDay(best && best.count > 0 ? best : null);\r\n }, [allDays, selectedYear]);\r\n\r\n /* ---------- Rendering ---------- */\r\n\r\n const grid = useMemo(\r\n () => (allDays.size ? buildGrid(allDays, selectedYear) : []),\r\n [allDays, selectedYear],\r\n );\r\n\r\n const labels = useMemo(() => monthLabels(grid), [grid]);\r\n\r\n const outlineColor = theme === \"light\" ? \"#333\" : \"#f0f0f0\";\r\n\r\n return (\r\n <section className={[\"w-full font-mono\", className].join(\" \").trim()}>\r\n {/* Stats */}\r\n <div className=\"flex flex-wrap items-center gap-x-6 gap-y-1 mb-4 text-xs text-neutral-400\">\r\n {loading\r\n ? \"Loading…\"\r\n : error\r\n ? \"Unavailable\"\r\n : `${total?.toLocaleString()} contributions ${selectedYear === \"last\"\r\n ? \"in the last year\"\r\n : `in ${selectedYear}`\r\n }`}\r\n\r\n {bestDay && !loading && (\r\n <span className=\"flex items-center gap-1.5\">\r\n <span\r\n className=\"inline-block w-[10px] h-[10px] rounded-[2px]\"\r\n style={{ backgroundColor: colors[4] }}\r\n />\r\n Best day:\r\n <span className=\"text-neutral-200 font-semibold\">\r\n {bestDay.count}\r\n </span>\r\n </span>\r\n )}\r\n </div>\r\n\r\n {/* Main Card */}\r\n <div className=\"border border-neutral-800 rounded-xl p-4 bg-neutral-950\">\r\n {error ? (\r\n <p className=\"text-sm italic text-neutral-400\">\r\n GitHub activity unavailable.\r\n </p>\r\n ) : loading ? (\r\n <Skeleton />\r\n ) : (\r\n <>\r\n <div className=\"overflow-x-auto pb-1\">\r\n <div\r\n className=\"relative\"\r\n style={{\r\n minWidth: grid.length * STEP + DAY_COL_W + 8,\r\n }}\r\n >\r\n {/* Months */}\r\n <div\r\n className=\"relative h-[18px] mb-1\"\r\n style={{ marginLeft: DAY_COL_W }}\r\n >\r\n {labels.map(({ label, col }) => (\r\n <span\r\n key={label + col}\r\n className=\"absolute text-[11px] text-neutral-400\"\r\n style={{ left: col * STEP }}\r\n >\r\n {label}\r\n </span>\r\n ))}\r\n </div>\r\n\r\n {/* Grid */}\r\n <div className=\"flex gap-[3px]\">\r\n <div\r\n className=\"flex flex-col gap-[3px]\"\r\n style={{ width: DAY_COL_W - GAP }}\r\n >\r\n {Array.from({ length: 7 }).map((_, i) => (\r\n <div\r\n key={i}\r\n className=\"h-[13px] text-[10px] text-right pr-1.5 text-neutral-400\"\r\n >\r\n {DAY_LABELS[i] ?? \"\"}\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {grid.map((week, wi) => (\r\n <div key={wi} className=\"flex flex-col gap-[3px]\">\r\n {week.map((day, di) => (\r\n <div\r\n key={di}\r\n className=\"w-[13px] h-[13px] rounded-[3px] transition-transform hover:scale-125\"\r\n style={{\r\n backgroundColor: day\r\n ? colors[day.level]\r\n : \"transparent\",\r\n outline:\r\n bestDay && day?.date === bestDay.date\r\n ? `2px solid ${outlineColor}`\r\n : \"none\",\r\n outlineOffset: \"1px\",\r\n }}\r\n onMouseEnter={(e) => {\r\n if (!day) return;\r\n const r =\r\n e.currentTarget.getBoundingClientRect();\r\n setTip({\r\n day,\r\n x: r.left + r.width / 2,\r\n y: r.top,\r\n });\r\n }}\r\n onMouseLeave={() => setTip(null)}\r\n />\r\n ))}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Legend */}\r\n <div className=\"flex items-center gap-1 mt-3 text-[11px] text-neutral-400\">\r\n Less\r\n {colors.map((c, i) => (\r\n <div\r\n key={i}\r\n className=\"w-[13px] h-[13px] rounded-[3px]\"\r\n style={{ backgroundColor: c }}\r\n />\r\n ))}\r\n More\r\n </div>\r\n\r\n {/* Years */}\r\n <div className=\"flex flex-wrap items-center gap-1.5 mt-4 pt-3 border-t border-neutral-800\">\r\n <span className=\"text-[11px] text-neutral-400 mr-1\">\r\n Year:\r\n </span>\r\n\r\n <YearPill\r\n label=\"Last year\"\r\n active={selectedYear === \"last\"}\r\n onClick={() => setSelectedYear(\"last\")}\r\n />\r\n\r\n {years.map((y) => (\r\n <YearPill\r\n key={y}\r\n label={String(y)}\r\n active={selectedYear === y}\r\n onClick={() => setSelectedYear(y)}\r\n />\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n\r\n {tip && <Tooltip day={tip.day} x={tip.x} y={tip.y} />}\r\n </section>\r\n );\r\n}\r\n\r\nexport default memo(GithubActivity);"],"mappings":"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","names":["_","_a"]}
package/dist/styles.css CHANGED
@@ -1,2 +1,2 @@
1
1
  /*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */
2
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-leading:initial;--tw-outline-style:solid;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}.pointer-events-none{pointer-events:none}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.z-50{z-index:50}.flex{display:flex}.grid{display:grid}.inline-block{display:inline-block}.h-\[10px\]{height:10px}.h-\[13px\]{height:13px}.h-\[18px\]{height:18px}.w-\[10px\]{width:10px}.w-\[13px\]{width:13px}.w-full{width:100%}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-full{--tw-translate-y:-100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-start{justify-content:flex-start}.gap-\[3px\]{gap:3px}.overflow-x-auto{overflow-x:auto}.overflow-y-visible{overflow-y:visible}.rounded-\[2px\]{border-radius:2px}.rounded-\[3px\]{border-radius:3px}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.pt-px{padding-top:1px}.text-right{text-align:right}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-\[13px\]{--tw-leading:13px;line-height:13px}.whitespace-nowrap{white-space:nowrap}.italic{font-style:italic}.opacity-40{opacity:.4}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.hover\:scale-125:hover{--tw-scale-x:125%;--tw-scale-y:125%;--tw-scale-z:125%;scale:var(--tw-scale-x) var(--tw-scale-y)}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-outline-style:solid;--tw-duration:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}.pointer-events-none{pointer-events:none}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.z-50{z-index:50}.flex{display:flex}.grid{display:grid}.inline-block{display:inline-block}.h-\[10px\]{height:10px}.h-\[13px\]{height:13px}.h-\[18px\]{height:18px}.w-\[10px\]{width:10px}.w-\[13px\]{width:13px}.w-full{width:100%}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-full{--tw-translate-y:-100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.gap-\[3px\]{gap:3px}.overflow-x-auto{overflow-x:auto}.rounded-\[2px\]{border-radius:2px}.rounded-\[3px\]{border-radius:3px}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.text-right{text-align:right}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.whitespace-nowrap{white-space:nowrap}.italic{font-style:italic}.opacity-40{opacity:.4}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.duration-150{--tw-duration:.15s;transition-duration:.15s}@media (hover:hover){.hover\:scale-125:hover{--tw-scale-x:125%;--tw-scale-y:125%;--tw-scale-z:125%;scale:var(--tw-scale-x) var(--tw-scale-y)}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-duration{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-contributions-ui",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "GitHub contributions graph React component",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",