github-contributions-ui 1.0.3 → 1.0.4
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.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/readme.md +1 -0
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/GithubActivity.tsx"],"sourcesContent":["import \"./styles.css\";\r\n\r\nexport { default as GithubActivity } from \"./GithubActivity\";","import { 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 [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={[\"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":["import \"./styles.css\";\r\n\r\nexport { default as GithubActivity } from \"./GithubActivity\";","\"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 [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={[\"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"]}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/GithubActivity.tsx"],"sourcesContent":["import { 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 [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={[\"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\",\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 [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={[\"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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "github-contributions-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "GitHub contributions graph React component",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"style": "./dist/styles.css",
|
|
10
10
|
"sideEffects": [
|
|
11
|
-
"
|
|
11
|
+
"**/*.css"
|
|
12
12
|
],
|
|
13
13
|
"exports": {
|
|
14
14
|
".": {
|