github-contributions-ui 1.0.16 → 1.0.17

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.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\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\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\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 for (let d = 0; d < 7; d++) {\r\n const iso = cur.toISOString().slice(0, 10);\r\n if (cur > end) week.push(null);\r\n else week.push(dayMap.get(iso) ?? { date: iso, count: 0, level: 0 });\r\n cur.setDate(cur.getDate() + 1);\r\n }\r\n weeks.push(week);\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 grid.forEach((week, i) => {\r\n const first = week.find(Boolean);\r\n if (!first) return;\r\n const m = new Date(first.date).getMonth();\r\n if (m !== last) {\r\n out.push({ label: MONTHS[m], col: i });\r\n last = m;\r\n }\r\n });\r\n return out;\r\n}\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 return (\r\n <div\r\n className=\"gcu 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: 45 }).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\n// ─── YearPill — fully inline styles, zero Tailwind dependency ─────────────────\r\ntype YearPillProps = { label: string; active: boolean; onClick: () => void };\r\n\r\nexport function YearPill({ label, active, onClick }: YearPillProps) {\r\n const [hovered, setHovered] = useState(false);\r\n\r\n const baseStyle: React.CSSProperties = {\r\n padding: \"2px 10px\",\r\n fontSize: 12,\r\n fontWeight: 500,\r\n borderRadius: 9999,\r\n border: \"none\",\r\n cursor: \"pointer\",\r\n transition: \"background-color 0.15s ease, color 0.15s ease\",\r\n userSelect: \"none\",\r\n outline: \"none\",\r\n // Active = white pill with dark text\r\n // Inactive = dark pill with muted text, slightly lighter on hover\r\n backgroundColor: active ? \"#ffffff\" : hovered ? \"#3f3f46\" : \"#262626\",\r\n color: active ? \"#000000\" : \"#ffffff\",\r\n };\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n onClick={onClick}\r\n style={baseStyle}\r\n onMouseEnter={() => setHovered(true)}\r\n onMouseLeave={() => setHovered(false)}\r\n >\r\n {label}\r\n </button>\r\n );\r\n}\r\n\r\n// ─── Main ─────────────────────────────────────────────────────────────────────\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 .-translate-x-1\\\\/2{transform:translateX(-50%)}\r\n .gcu .-translate-y-full{transform:translateY(-100%)}\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 .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-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 .border{border-width:1px;border-style:solid;border-color:#262626}\r\n .gcu .border-neutral-800{border-color:#262626}\r\n .gcu .border-t{border-top-width:1px;border-top-style:solid;border-top-color:#262626}\r\n .gcu .transition-transform{transition-property:transform;transition-duration:0.1s;transition-timing-function:ease}\r\n @keyframes gcu-pulse{50%{opacity:.5}}\r\n .gcu .animate-pulse{animation:gcu-pulse 2s cubic-bezier(0.4,0,0.6,1) infinite}\r\n .gcu .hover\\\\:scale-125:hover{transform:scale(1.25)}\r\n .gcu .text-neutral-400{color:#9ca3af}\r\n .gcu .text-neutral-200{color:#e5e7eb}\r\n .gcu .bg-neutral-700{background-color:#3f3f46}\r\n .gcu .bg-neutral-900{background-color:#171717}\r\n .gcu .bg-neutral-950{background-color:#0a0a0a}\r\n .gcu .text-white{color:#fff}\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\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 useEffect(() => {\r\n if (!username) return;\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 if (!res.ok) throw new Error();\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: { date: string; count: number }) => {\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 yearSet.add(new Date(c.date).getFullYear());\r\n });\r\n\r\n if (!mounted) return;\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 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 const best = entries.reduce<Day | null>(\r\n (b, d) => (!b || d.count > b.count ? d : b),\r\n null,\r\n );\r\n setBestDay(best && best.count > 0 ? best : null);\r\n }, [allDays, selectedYear]);\r\n\r\n const grid = useMemo(\r\n () => (allDays.size ? buildGrid(allDays, selectedYear) : []),\r\n [allDays, selectedYear],\r\n );\r\n const labels = useMemo(() => monthLabels(grid), [grid]);\r\n const outlineColor = theme === \"light\" ? \"#333\" : \"#f0f0f0\";\r\n\r\n return (\r\n <section\r\n className={[\"gcu w-full font-mono\", className].filter(Boolean).join(\" \")}\r\n >\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\" ? \"in the last year\" : `in ${selectedYear}`}`}\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} contributions on {bestDay.date}\r\n </span>\r\n </span>\r\n )}\r\n </div>\r\n\r\n {/* 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 text-neutral-400 italic\">\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={{ minWidth: grid.length * STEP + DAY_COL_W + 8 }}\r\n >\r\n {/* Month labels */}\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 = e.currentTarget.getBoundingClientRect();\r\n setTip({ day, x: r.left + r.width / 2, y: r.top });\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 {/* Year selector */}\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\">Year:</span>\r\n <YearPill\r\n label=\"Last year\"\r\n active={selectedYear === \"last\"}\r\n onClick={() => setSelectedYear(\"last\")}\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","../src/components/Styles.ts","../src/components/Colors.ts","../src/components/BuildGrid.ts","../src/components/Tooltip.tsx","../src/components/YearPillProps.tsx","../src/components/MonthLabels.ts","../src/components/Skeleton.tsx"],"sourcesContent":["\"use client\";\r\nimport { memo, useEffect, useState, useMemo } from \"react\";\r\nimport { STYLES } from \"./components/Styles\";\r\nimport { LIGHT, DARK, BLUE, PURPLE, GRAY } from \"./components/Colors\";\r\nimport { buildGrid } from \"./components/BuildGrid\";\r\nimport { Tooltip } from \"./components/Tooltip\";\r\nimport { YearPill } from \"./components/YearPillProps\";\r\nimport { monthLabels } from \"./components/MonthLabels\";\r\nimport { Skeleton } from \"./components/Skeleton\";\r\nimport { Day } from \"./types/Day\";\r\n\r\ntype Theme = \"light\" | \"dark\" | \"blue\" | \"purple\" | \"gray\";\r\n\r\ninterface Props {\r\n username: string;\r\n theme?: Theme;\r\n className?: string;\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\nconst COLOR_MAP: Record<Theme, string[]> = {\r\n light: LIGHT,\r\n dark: DARK,\r\n blue: BLUE,\r\n purple: PURPLE,\r\n gray: GRAY,\r\n};\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\n// ─── YearPill ─────────────────────────────────────────────────────────────────\r\n\r\n// ─── Main ─────────────────────────────────────────────────────────────────────\r\nfunction GithubActivity({ username, theme = \"dark\", className }: Props) {\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\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 useEffect(() => {\r\n if (!username) return;\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 if (!res.ok) throw new Error();\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: { date: string; count: number }) => {\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 yearSet.add(new Date(c.date).getFullYear());\r\n });\r\n\r\n if (!mounted) return;\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 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 const best = entries.reduce<Day | null>(\r\n (b, d) => (!b || d.count > b.count ? d : b),\r\n null,\r\n );\r\n setBestDay(best && best.count > 0 ? best : null);\r\n }, [allDays, selectedYear]);\r\n\r\n const grid = useMemo(\r\n () => (allDays.size ? buildGrid(allDays, selectedYear) : []),\r\n [allDays, selectedYear],\r\n );\r\n const labels = useMemo(\r\n () => monthLabels(grid, selectedYear),\r\n [grid, selectedYear],\r\n );\r\n const outlineColor = theme === \"light\" ? \"#333\" : \"#f0f0f0\";\r\n\r\n return (\r\n <section\r\n className={[\"gcu w-full font-mono\", className].filter(Boolean).join(\" \")}\r\n style={{}}\r\n >\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\" ? \"in the last year\" : `in ${selectedYear}`}`}\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} contributions on {bestDay.date}\r\n </span>\r\n </span>\r\n )}\r\n </div>\r\n\r\n {/* 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 text-neutral-400 italic\">\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={{ minWidth: grid.length * STEP + DAY_COL_W + 8 }}\r\n >\r\n {/* Month labels */}\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 = e.currentTarget.getBoundingClientRect();\r\n setTip({ day, x: r.left + r.width / 2, y: r.top });\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 {/* Year selector */}\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\">Year:</span>\r\n <YearPill\r\n label=\"Last year\"\r\n active={selectedYear === \"last\"}\r\n onClick={() => setSelectedYear(\"last\")}\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","export 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 .-translate-x-1\\\\/2{transform:translateX(-50%)}\r\n .gcu .-translate-y-full{transform:translateY(-100%)}\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 .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-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 .border{border-width:1px;border-style:solid;border-color:#262626}\r\n .gcu .border-neutral-800{border-color:#262626}\r\n .gcu .border-t{border-top-width:1px;border-top-style:solid;border-top-color:#262626}\r\n .gcu .transition-transform{transition-property:transform;transition-duration:0.1s;transition-timing-function:ease}\r\n @keyframes gcu-pulse{50%{opacity:.5}}\r\n .gcu .animate-pulse{animation:gcu-pulse 2s cubic-bezier(0.4,0,0.6,1) infinite}\r\n .gcu .hover\\\\:scale-125:hover{transform:scale(1.25)}\r\n .gcu .text-neutral-400{color:#9ca3af}\r\n .gcu .text-neutral-200{color:#e5e7eb}\r\n .gcu .bg-neutral-700{background-color:#3f3f46}\r\n .gcu .bg-neutral-900{background-color:#171717}\r\n .gcu .bg-neutral-950{background-color:#0a0a0a}\r\n .gcu .text-white{color:#fff}\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","export const LIGHT = [\"#ebedf0\", \"#9be9a8\", \"#40c463\", \"#30a14e\", \"#216e39\"];\r\nexport const DARK = [\"#21262d\", \"#0e4429\", \"#006d32\", \"#26a641\", \"#39d353\"];\r\nexport const BLUE = [\"#21262d\", \"#a3c9ff\", \"#5fa3ff\", \"#2f7bff\", \"#0b5cff\"];\r\nexport const PURPLE = [\"#21262d\", \"#d8b4ff\", \"#c084fc\", \"#a855f7\", \"#7e22ce\"];\r\nexport const GRAY = [\"#21262d\", \"#6a737d\", \"#8b949e\", \"#c0c0c8\", \"#e0e0e0\"];","import { Day } from \"../types/Day\";\r\n\r\nexport function buildGrid(\r\n dayMap: Map<string, Day>,\r\n year: number | \"last\",\r\n): (Day | null)[][] {\r\n // Determine the logical range\r\n let rangeStart: Date;\r\n let end: Date;\r\n\r\n if (year === \"last\") {\r\n end = new Date();\r\n rangeStart = new Date(end);\r\n rangeStart.setFullYear(rangeStart.getFullYear() - 1);\r\n rangeStart.setDate(rangeStart.getDate() + 1);\r\n } else {\r\n rangeStart = 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 // Rewind to the Sunday of the week containing rangeStart.\r\n // Days in that partial first week that fall before rangeStart render as null.\r\n const gridStart = new Date(rangeStart);\r\n gridStart.setDate(gridStart.getDate() - gridStart.getDay());\r\n\r\n const weeks: (Day | null)[][] = [];\r\n const cur = new Date(gridStart);\r\n\r\n while (cur <= end) {\r\n const week: (Day | null)[] = [];\r\n for (let d = 0; d < 7; d++) {\r\n if (cur < rangeStart || cur > end) {\r\n week.push(null);\r\n } else {\r\n const iso = cur.toISOString().slice(0, 10);\r\n week.push(dayMap.get(iso) ?? { date: iso, count: 0, level: 0 });\r\n }\r\n cur.setDate(cur.getDate() + 1);\r\n }\r\n weeks.push(week);\r\n }\r\n\r\n return weeks;\r\n}\r\n","import { Day } from \"../types/Day\";\r\n\r\nexport function 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 return (\r\n <div\r\n className=\"gcu 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}","\"use client\";\r\n\r\nimport React, { useState } from \"react\";\r\n\r\ntype YearPillProps = { label: string; active: boolean; onClick: () => void };\r\n\r\nexport function YearPill({ label, active, onClick }: YearPillProps) {\r\n const [hovered, setHovered] = useState(false);\r\n\r\n const baseStyle: React.CSSProperties = {\r\n padding: \"2px 10px\",\r\n fontSize: 12,\r\n fontWeight: 500,\r\n borderRadius: 9999,\r\n border: \"none\",\r\n cursor: \"pointer\",\r\n transition: \"background-color 0.15s ease, color 0.15s ease\",\r\n userSelect: \"none\",\r\n outline: \"none\",\r\n backgroundColor: active ? \"#ffffff\" : hovered ? \"#3f3f46\" : \"#262626\",\r\n color: active ? \"#000000\" : \"#ffffff\",\r\n };\r\n\r\n return (\r\n <button\r\n type=\"button\"\r\n onClick={onClick}\r\n style={baseStyle}\r\n onMouseEnter={() => setHovered(true)}\r\n onMouseLeave={() => setHovered(false)}\r\n >\r\n {label}\r\n </button>\r\n );\r\n}\r\n","import { Day } from \"../types/Day\";\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\n\r\nexport function monthLabels(grid: (Day | null)[][], year: number | \"last\") {\r\n const out: { label: string; col: number }[] = [];\r\n let lastMonth = -1;\r\n grid.forEach((week, i) => {\r\n const first = week.find(Boolean);\r\n if (!first) return;\r\n const m = new Date(first.date).getMonth();\r\n if (m !== lastMonth) {\r\n // If the very first column is a partial week whose first real day\r\n // isn't Sunday (index > 0), the month label belongs to a prior-month\r\n // sliver and would collide with the next label. Suppress it.\r\n const isOrphanedSliver =\r\n i === 0 &&\r\n week.findIndex(Boolean) > 0 &&\r\n (year !== \"last\" ? m !== 0 : true);\r\n if (!isOrphanedSliver) {\r\n out.push({ label: MONTHS[m], col: i });\r\n }\r\n lastMonth = m;\r\n }\r\n });\r\n return out;\r\n}\r\n","export function Skeleton() {\r\n return (\r\n <div className=\"flex gap-[3px] mx-auto animate-pulse opacity-40\">\r\n {Array.from({ length: 40 }).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"],"mappings":"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","names":["useState","jsx","_","jsx","jsxs","useState","_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-outline-style:solid;--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{display:inline}.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}.justify-start{justify-content:flex-start}.gap-\[3px\]{gap:3px}.overflow-x-auto{overflow-x:auto}.rounded-\[2px\]{border-radius:2px}.rounded-\[3px\]{border-radius:3px}.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}.whitespace-nowrap{white-space:nowrap}.italic{font-style:italic}.opacity-40{opacity:.4}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;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)}.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-outline-style{syntax:"*";inherits:false;initial-value:solid}@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-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}.mx-auto{margin-inline:auto}.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}.justify-start{justify-content:flex-start}.gap-\[3px\]{gap:3px}.overflow-x-auto{overflow-x:auto}.rounded-\[2px\]{border-radius:2px}.rounded-\[3px\]{border-radius:3px}.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}.whitespace-nowrap{white-space:nowrap}.italic{font-style:italic}.opacity-40{opacity:.4}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;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)}.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)}}::-webkit-scrollbar{display:none}@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-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.16",
3
+ "version": "1.0.17",
4
4
  "description": "GitHub contributions graph React component",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -38,7 +38,7 @@
38
38
  ],
39
39
  "repository": {
40
40
  "type": "git",
41
- "url": "https://github.com/bichitrabehera/github-contributions-ui.git"
41
+ "url": "git+https://github.com/bichitrabehera/github-contributions-ui.git"
42
42
  },
43
43
  "homepage": "https://github.com/bichitrabehera/github-contributions-ui#readme",
44
44
  "bugs": {
package/readme.md CHANGED
@@ -61,7 +61,7 @@ export default App;
61
61
  | Prop | Type | Required | Description |
62
62
  | ---------- | ----------------------------------------- | -------- | --------------------------- |
63
63
  | `username` | string | ✅ | GitHub username |
64
- | `theme` | `"light" \| "dark" \| "blue" \| "purple"` | ❌ | UI theme (default: `light`) |
64
+ | `theme` | `"light" \| "dark" \| "blue" \| "purple"` | ❌ | UI theme (default: `dark`) |
65
65
 
66
66
  ### Example
67
67