{"_id":"github-contrib-graph","_rev":"5-08e9bffe53e14cc85d1ddf90b4c028c0","name":"github-contrib-graph","dist-tags":{"latest":"3.1.1"},"versions":{"3.0.0":{"name":"github-contrib-graph","version":"3.0.0","keywords":["github","contributions","graph","widget","react","typescript","calendar"],"author":{"name":"Jigyansu Rout"},"license":"Apache-2.0","_id":"github-contrib-graph@3.0.0","maintainers":[{"name":"iamjr15","email":"jigyanshu15@gmail.com"}],"homepage":"https://github-contribution-graph.netlify.app","bugs":{"url":"https://github.com/iamjr15/github-contribution-graph/issues"},"dist":{"shasum":"50f171437749be61e4c85c2e9c20d3d11e7b4c09","tarball":"https://registry.npmjs.org/github-contrib-graph/-/github-contrib-graph-3.0.0.tgz","fileCount":26,"integrity":"sha512-xZgdjavRfzb14wdJgjNYi8uDGm5UT5C+U0Upx73CvtgGdEvhHyO+dnm1qZrwBJY5AIeZWk6nTPFLcS3tGXNQeQ==","signatures":[{"sig":"MEUCIAx8rrED7wTfe95F0lnC4EN4z3EmDo3QesOWsQZBFq8PAiEAjPV5Hv/RyegJR1759nqUIMUDRPY3Na1hK6fYvhBod80=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":283784},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./vanilla":{"types":"./dist/vanilla.d.ts","import":"./dist/vanilla.js","require":"./dist/vanilla.cjs"},"./styles.css":"./dist/gh.css","./package.json":"./package.json"},"gitHead":"a906f33397d3d1bab95e7de0d72078ecf15f8a39","scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","test":"vitest run","build":"tsup && cp src/styles/gh.css dist/gh.css","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build && npm run test"},"_npmUser":{"name":"iamjr15","email":"jigyanshu15@gmail.com"},"repository":{"url":"git+https://github.com/iamjr15/github-contribution-graph.git","type":"git","directory":"packages/github-contribution-graph"},"_npmVersion":"11.6.0","description":"Lightweight, customizable GitHub contribution graph widget for any website","directories":{},"sideEffects":["*.css","./dist/browser.global.js"],"_nodeVersion":"24.10.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","jsdom":"^25.0.1","react":"^18.3.1","vitest":"^2.1.6","react-dom":"^18.3.1","typescript":"^5.7.2","@types/react":"^18.3.12","@types/react-dom":"^18.3.1","@vitest/coverage-v8":"^2.1.6","@testing-library/dom":"^10.4.0","@testing-library/react":"^16.0.1"},"peerDependencies":{"react":">=16.8.0","react-dom":">=16.8.0"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/github-contrib-graph_3.0.0_1765221654085_0.6158130665684312","host":"s3://npm-registry-packages-npm-production"}},"3.0.1":{"name":"github-contrib-graph","version":"3.0.1","keywords":["github","contributions","graph","widget","react","typescript","calendar"],"author":{"name":"Jigyansu Rout"},"license":"Apache-2.0","_id":"github-contrib-graph@3.0.1","maintainers":[{"name":"iamjr15","email":"jigyanshu15@gmail.com"}],"homepage":"https://github-contribution-graph.netlify.app","bugs":{"url":"https://github.com/iamjr15/github-contribution-graph/issues"},"dist":{"shasum":"ef9a10ae7cc76b13c8cd4d3feb9dbb665f76d97e","tarball":"https://registry.npmjs.org/github-contrib-graph/-/github-contrib-graph-3.0.1.tgz","fileCount":26,"integrity":"sha512-qy3TY5s8fDFk0+4VoMJBXhvQ6h/j+e1B0B5/6UgsSA67MvvuvnOD7tIRpJD1mX2ln1BUoW6gUt0m2cGiwYocsQ==","signatures":[{"sig":"MEQCIDwqqmu/SLN/raoD1bXVI8/uOCxoPAgJw65vo2Kwwt1fAiBKNirgqI2ftdNYpI81djO2Osn0rrIONCpjFDS2X0TZ4A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":283619},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./vanilla":{"types":"./dist/vanilla.d.ts","import":"./dist/vanilla.js","require":"./dist/vanilla.cjs"},"./styles.css":"./dist/gh.css","./package.json":"./package.json"},"gitHead":"a906f33397d3d1bab95e7de0d72078ecf15f8a39","scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","test":"vitest run","build":"tsup && cp src/styles/gh.css dist/gh.css","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build && npm run test"},"_npmUser":{"name":"iamjr15","email":"jigyanshu15@gmail.com"},"repository":{"url":"git+https://github.com/iamjr15/github-contribution-graph.git","type":"git","directory":"packages/github-contribution-graph"},"_npmVersion":"11.6.0","description":"Lightweight, customizable GitHub contribution graph widget for any website","directories":{},"sideEffects":["*.css","./dist/browser.global.js"],"_nodeVersion":"24.10.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","jsdom":"^25.0.1","react":"^18.3.1","vitest":"^2.1.6","react-dom":"^18.3.1","typescript":"^5.7.2","@types/react":"^18.3.12","@types/react-dom":"^18.3.1","@vitest/coverage-v8":"^2.1.6","@testing-library/dom":"^10.4.0","@testing-library/react":"^16.0.1"},"peerDependencies":{"react":">=16.8.0","react-dom":">=16.8.0"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/github-contrib-graph_3.0.1_1765222330874_0.7766954154452701","host":"s3://npm-registry-packages-npm-production"}},"3.0.2":{"name":"github-contrib-graph","version":"3.0.2","keywords":["github","contributions","graph","widget","react","typescript","calendar"],"author":{"name":"Jigyansu Rout"},"license":"Apache-2.0","_id":"github-contrib-graph@3.0.2","maintainers":[{"name":"iamjr15","email":"jigyanshu15@gmail.com"}],"homepage":"https://githubgraph.jigyansurout.com","bugs":{"url":"https://github.com/iamjr15/github-contribution-graph/issues"},"dist":{"shasum":"fd149640f7ecd052693a16abcfff6538ee1ab705","tarball":"https://registry.npmjs.org/github-contrib-graph/-/github-contrib-graph-3.0.2.tgz","fileCount":26,"integrity":"sha512-I0220w42NVVBqCVu5+X8nblBcEIzjI0dM7SMitGUHTtstNHhPlc4CscOtQ1raF6h72EbDePRXQu97at0nnFH+A==","signatures":[{"sig":"MEQCIB/6hy3iGWP2AhwVTgGispGmjXBOcqx10cuakTLoVMrbAiB27ngjEnqZBJL365rXQU2KeP7CvzzMMHOacH51OGJLrA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":284502},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./vanilla":{"types":"./dist/vanilla.d.ts","import":"./dist/vanilla.js","require":"./dist/vanilla.cjs"},"./styles.css":"./dist/gh.css","./package.json":"./package.json"},"gitHead":"39d53b3ab08e7b1077bca9bf1f66d3977d398e72","scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","test":"vitest run","build":"tsup && cp src/styles/gh.css dist/gh.css","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build && npm run test"},"_npmUser":{"name":"iamjr15","email":"jigyanshu15@gmail.com"},"repository":{"url":"git+https://github.com/iamjr15/github-contribution-graph.git","type":"git","directory":"packages/github-contribution-graph"},"_npmVersion":"11.6.0","description":"Lightweight, customizable GitHub contribution graph widget for any website","directories":{},"sideEffects":["*.css","./dist/browser.global.js"],"_nodeVersion":"24.10.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","jsdom":"^25.0.1","react":"^18.3.1","vitest":"^2.1.6","react-dom":"^18.3.1","typescript":"^5.7.2","@types/react":"^18.3.12","@types/react-dom":"^18.3.1","@vitest/coverage-v8":"^2.1.6","@testing-library/dom":"^10.4.0","@testing-library/react":"^16.0.1"},"peerDependencies":{"react":">=16.8.0","react-dom":">=16.8.0"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/github-contrib-graph_3.0.2_1765288980460_0.09407252577203207","host":"s3://npm-registry-packages-npm-production"}},"3.1.0":{"name":"github-contrib-graph","version":"3.1.0","keywords":["github","contributions","graph","widget","react","typescript","calendar"],"author":{"name":"Jigyansu Rout"},"license":"Apache-2.0","_id":"github-contrib-graph@3.1.0","maintainers":[{"name":"iamjr15","email":"jigyanshu15@gmail.com"}],"homepage":"https://githubgraph.jigyansurout.com","bugs":{"url":"https://github.com/iamjr15/github-contribution-graph/issues"},"dist":{"shasum":"ff22b5646c4ee34b3e8bcb7882c7a236d9e95aa4","tarball":"https://registry.npmjs.org/github-contrib-graph/-/github-contrib-graph-3.1.0.tgz","fileCount":26,"integrity":"sha512-+xhr/8H0+ZzHcMDHJhaQR+unDzRhJ0C+6nqj00XoOeskcMwLUui2qEg6djjvn6PN/Gk/SmmAu4O2jUmXZjtIHQ==","signatures":[{"sig":"MEUCIAw3eQXal5C4PcpcUZFPj7GPAibQUnIe4VP/zLggx6TgAiEA77vcpYClQ0ckGEKZ3NTCeDWk0HPa5g+aB9wYZFcR9DE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":306418},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./vanilla":{"types":"./dist/vanilla.d.ts","import":"./dist/vanilla.js","require":"./dist/vanilla.cjs"},"./styles.css":"./dist/gh.css","./package.json":"./package.json"},"gitHead":"a70a5bd6a8298d600175b0691bf58f5a3c421c72","scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","test":"vitest run","build":"tsup && cp src/styles/gh.css dist/gh.css","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build && npm run test"},"_npmUser":{"name":"iamjr15","email":"jigyanshu15@gmail.com"},"repository":{"url":"git+https://github.com/iamjr15/github-contribution-graph.git","type":"git","directory":"packages/github-contribution-graph"},"_npmVersion":"10.9.4","description":"Lightweight, customizable GitHub contribution graph widget for any website","directories":{},"sideEffects":["*.css","./dist/browser.global.js"],"_nodeVersion":"22.22.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","jsdom":"^25.0.1","react":"^18.3.1","vitest":"^2.1.6","react-dom":"^18.3.1","typescript":"^5.7.2","@types/react":"^18.3.12","@types/react-dom":"^18.3.1","@vitest/coverage-v8":"^2.1.6","@testing-library/dom":"^10.4.0","@testing-library/react":"^16.0.1"},"peerDependencies":{"react":">=16.8.0","react-dom":">=16.8.0"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/github-contrib-graph_3.1.0_1773259377845_0.6920278533199824","host":"s3://npm-registry-packages-npm-production"}},"3.1.1":{"name":"github-contrib-graph","version":"3.1.1","description":"Lightweight, customizable GitHub contribution graph widget for any website","keywords":["github","contributions","graph","widget","react","typescript","calendar"],"author":{"name":"Jigyansu Rout"},"license":"Apache-2.0","repository":{"type":"git","url":"git+https://github.com/iamjr15/github-contribution-graph.git","directory":"packages/github-contribution-graph"},"homepage":"https://githubgraph.jigyansurout.com","bugs":{"url":"https://github.com/iamjr15/github-contribution-graph/issues"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./vanilla":{"types":"./dist/vanilla.d.ts","import":"./dist/vanilla.js","require":"./dist/vanilla.cjs"},"./styles.css":"./dist/gh.css","./package.json":"./package.json"},"sideEffects":["*.css","./dist/browser.global.js"],"scripts":{"build":"tsup && cp src/styles/gh.css dist/gh.css","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","lint":"eslint src --ext .ts,.tsx","typecheck":"tsc --noEmit","prepublishOnly":"npm run build && npm run test"},"peerDependencies":{"react":">=16.8.0","react-dom":">=16.8.0"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true}},"devDependencies":{"@testing-library/dom":"^10.4.0","@testing-library/react":"^16.0.1","@types/react":"^18.3.12","@types/react-dom":"^18.3.1","@vitest/coverage-v8":"^2.1.6","jsdom":"^25.0.1","react":"^18.3.1","react-dom":"^18.3.1","tsup":"^8.3.5","typescript":"^5.7.2","vitest":"^2.1.6"},"engines":{"node":">=18.0.0"},"publishConfig":{"access":"public"},"gitHead":"249abedc3ac9db15205dfe3bef61030c964ce3a0","_id":"github-contrib-graph@3.1.1","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-QqbXuHzvvvcG6Ha1ohA+olMpYVVPudmA9IXovo6maqTyNzM1xiEGjMkF8Ta02qvkROSfeJ/ZogBebJG3AWzIfw==","shasum":"01a484e41854c5427c31dee2f58cda268d80884a","tarball":"https://registry.npmjs.org/github-contrib-graph/-/github-contrib-graph-3.1.1.tgz","fileCount":26,"unpackedSize":453330,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCLvP9ONn90PfTltbTiJ6F+GsyGO2EUD5CUcJ1edamXOAIgBKcPF+MEyuhUEy/qFVRZHWWKSXv/QmzavJAleYlKvc8="}]},"_npmUser":{"name":"iamjr15","email":"jigyanshu15@gmail.com"},"directories":{},"maintainers":[{"name":"iamjr15","email":"jigyanshu15@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/github-contrib-graph_3.1.1_1777927857038_0.23236516824867737"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-08T19:20:53.962Z","modified":"2026-05-04T20:50:57.301Z","3.0.0":"2025-12-08T19:20:54.222Z","3.0.1":"2025-12-08T19:32:11.038Z","3.0.2":"2025-12-09T14:03:00.610Z","3.1.0":"2026-03-11T20:02:57.994Z","3.1.1":"2026-05-04T20:50:57.184Z"},"bugs":{"url":"https://github.com/iamjr15/github-contribution-graph/issues"},"author":{"name":"Jigyansu Rout"},"license":"Apache-2.0","homepage":"https://githubgraph.jigyansurout.com","keywords":["github","contributions","graph","widget","react","typescript","calendar"],"repository":{"type":"git","url":"git+https://github.com/iamjr15/github-contribution-graph.git","directory":"packages/github-contribution-graph"},"description":"Lightweight, customizable GitHub contribution graph widget for any website","maintainers":[{"name":"iamjr15","email":"jigyanshu15@gmail.com"}],"readme":"# github-contrib-graph\n\nA lightweight, customizable GitHub contribution graph widget for React, vanilla JavaScript, and plain HTML pages.\n\n[![npm version](https://img.shields.io/npm/v/github-contrib-graph.svg)](https://npmjs.com/package/github-contrib-graph)\n[![npm downloads](https://img.shields.io/npm/dm/github-contrib-graph.svg)](https://npmjs.com/package/github-contrib-graph)\n[![License](https://img.shields.io/npm/l/github-contrib-graph.svg)](https://github.com/iamjr15/github-contribution-graph/blob/main/LICENSE)\n\n> Package name: `github-contrib-graph`.\n> Repository name: `github-contribution-graph`.\n> The npm package named `github-contribution-graph` is a different package.\n\n## Features\n\n- React component and data-fetching hook\n- Vanilla JavaScript widget class\n- Script-tag browser bundle for static sites\n- Built-in dark and light themes\n- Custom theming through props or CSS variables\n- Class hooks for every major rendered element\n- Per-day class, style, attribute, tooltip, and content render hooks\n- Replaceable header, footer legend, and GitHub attribution\n- Fully custom React rendering when you only want the package to fetch data\n- Hosted API by default, with support for your own API endpoint\n- TypeScript definitions for all public APIs\n\n## Installation\n\n```bash\nnpm install github-contrib-graph\n```\n\n## Quick Start\n\n### React\n\n```tsx\nimport { GitHubContributionGraph } from 'github-contrib-graph/react';\nimport 'github-contrib-graph/styles.css';\n\nexport function ProfileActivity() {\n  return (\n    <GitHubContributionGraph\n      username=\"octocat\"\n      theme=\"midnight\"\n      onDataLoaded={(data) => {\n        console.log(data.contributionsCollection.contributionCalendar.totalContributions);\n      }}\n    />\n  );\n}\n```\n\n### Vanilla JavaScript\n\n```js\nimport { GitHubContributionWidget } from 'github-contrib-graph/vanilla';\nimport 'github-contrib-graph/styles.css';\n\nconst widget = new GitHubContributionWidget({\n  username: 'octocat',\n  container: '#my-graph',\n  theme: 'void',\n});\n\nawait widget.render();\n```\n\n```html\n<div id=\"my-graph\"></div>\n```\n\n### Script Tag\n\nUse this when you do not have a bundler.\n\n```html\n<link rel=\"stylesheet\" href=\"https://unpkg.com/github-contrib-graph@latest/dist/gh.css\">\n\n<div\n  id=\"gh\"\n  data-login=\"octocat\"\n  data-show-thumbnail=\"true\"\n  data-show-header=\"true\"\n  data-show-footer=\"true\"\n></div>\n\n<script src=\"https://unpkg.com/github-contrib-graph@latest/dist/browser.global.js\"></script>\n```\n\nFor production pages, pin a version instead of using `@latest`:\n\n```html\n<link rel=\"stylesheet\" href=\"https://unpkg.com/github-contrib-graph@3.1.1/dist/gh.css\">\n<script src=\"https://unpkg.com/github-contrib-graph@3.1.1/dist/browser.global.js\"></script>\n```\n\nThe browser bundle auto-renders an element with `id=\"gh\"` and `data-login`. It also exposes `window.renderGitHubWidget()` for manual re-rendering after you change `data-login`.\n\n## Data Attributes\n\n| Attribute | Default | Description |\n| --- | --- | --- |\n| `data-login` | required | GitHub username to render |\n| `data-show-thumbnail` | `\"true\"` | Show or hide the GitHub attribution icon |\n| `data-show-header` | `\"true\"` | Show or hide the contribution total and avatar |\n| `data-show-footer` | `\"true\"` | Show or hide the Less/More legend |\n\n## React API\n\n```tsx\nimport { GitHubContributionGraph } from 'github-contrib-graph/react';\n\n<GitHubContributionGraph\n  username=\"octocat\"\n  apiEndpoint=\"https://your-domain.com/api/ghcg/fetch-data\"\n  theme=\"default\"\n  showHeader={true}\n  showFooter={true}\n  showThumbnail={true}\n  showMonthLabels={true}\n  showWeekdayLabels={true}\n  showTooltips={true}\n  dayLabels={['', 'Mon', '', 'Wed', '', 'Fri', '']}\n  footerLabels={{ less: 'Less', more: 'More' }}\n  classNames={{ root: 'my-graph-root', dayCell: 'my-day-cell' }}\n  dayClassName={({ day }) => (day.contributionCount > 0 ? 'has-activity' : '')}\n  dayStyle={({ day }) => ({\n    opacity: day.contributionCount === 0 ? '0.45' : '1',\n  })}\n  dayAttributes={({ day }) => ({\n    'aria-label': `${day.contributionCount} contributions on ${day.date}`,\n  })}\n  tooltipFormatter={({ day, date }) =>\n    `${day.contributionCount} contributions on ${date.toLocaleDateString()}`\n  }\n  monthLabelFormatter={(month) => month.name.slice(0, 3)}\n  className=\"my-graph\"\n  style={{ margin: 20 }}\n  onDataLoaded={(data) => {}}\n  onError={(error) => {}}\n  onLoading={(isLoading) => {}}\n/>;\n```\n\n### `useContributionData`\n\n```tsx\nimport { useContributionData } from 'github-contrib-graph/react';\n\nfunction TotalContributions() {\n  const { data, loading, error, refetch } = useContributionData('octocat', {\n    autoFetch: true,\n  });\n\n  if (loading) return <div>Loading...</div>;\n  if (error) return <div>{error.message}</div>;\n\n  return (\n    <button onClick={refetch}>\n      {data?.contributionsCollection.contributionCalendar.totalContributions}\n    </button>\n  );\n}\n```\n\n## Vanilla API\n\n```js\nimport { GitHubContributionWidget } from 'github-contrib-graph/vanilla';\n\nconst widget = new GitHubContributionWidget({\n  username: 'octocat',\n  container: '#my-graph',\n  apiEndpoint: 'https://your-domain.com/api/ghcg/fetch-data',\n  theme: 'void',\n  showHeader: true,\n  showFooter: true,\n  showThumbnail: true,\n  showMonthLabels: true,\n  showWeekdayLabels: true,\n  showTooltips: true,\n  classNames: {\n    root: 'profile-graph',\n    dayCell: 'profile-graph__day',\n  },\n  dayStyle: ({ day }) => ({\n    transform: day.contributionCount > 20 ? 'scale(1.15)' : 'scale(1)',\n  }),\n  onDataLoaded: (data) => {},\n  onError: (error) => {},\n});\n\nawait widget.render();\nawait widget.refresh();\nconst data = widget.getData();\nwidget.destroy();\nawait widget.update({ username: 'another-user' });\n```\n\n## Themes\n\nBuilt-in presets:\n\n- `default`\n- `void`\n- `slate`\n- `midnight`\n- `glacier`\n- `cyber`\n\nPass a preset name:\n\n```tsx\n<GitHubContributionGraph username=\"octocat\" theme=\"cyber\" />\n```\n\nOr pass a custom theme object:\n\n```js\nconst widget = new GitHubContributionWidget({\n  username: 'octocat',\n  theme: {\n    bgColor: '#111111',\n    textColor: '#eeeeee',\n    cellLevel0: '#222222',\n    cellLevel1: '#0e4429',\n    cellLevel2: '#006d32',\n    cellLevel3: '#26a641',\n    cellLevel4: '#39d353',\n    borderColor: '#333333',\n    fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n  },\n});\n```\n\nYou can also override CSS variables directly on the widget root:\n\n```css\n.my-graph {\n  --gh-bg-color: #000000;\n  --gh-text-default-color: #ffffff;\n  --gh-cell-level0-color: #111111;\n  --gh-border-card-color: #333333;\n  --gh-font-default-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n}\n```\n\nThe rendered root receives the `ghContributionGraph` class, so styles work even when your container is not `#gh`.\n\n## Customization\n\nThe package has layered customization. You can use only the built-in presets, override the default DOM with class and render hooks, or skip the default DOM entirely in React and render your own calendar from the fetched data.\n\n### Theme Object\n\nEvery theme key can be passed through the `theme` prop or config option. String values are used as-is. Numeric values are converted to `px`.\n\n```tsx\n<GitHubContributionGraph\n  username=\"octocat\"\n  theme={{\n    bgColor: '#080c10',\n    textColor: '#f4f7fb',\n    inactiveTextColor: '#7d8794',\n    linkHoverColor: '#8ab4ff',\n    cellLevel0: '#18202a',\n    cellLevel1: '#163b2a',\n    cellLevel2: '#196c3d',\n    cellLevel3: '#32a852',\n    cellLevel4: '#7ee787',\n    cellSize: 13,\n    cellGap: 4,\n    cellRadius: 4,\n    cellBorderColor: 'rgba(255,255,255,0.08)',\n    cellOutlineColor: 'transparent',\n    tooltipBgColor: '#f4f7fb',\n    tooltipTextColor: '#080c10',\n    tooltipPadding: '8px 10px',\n    tooltipRadius: 8,\n    tooltipFontSize: 12,\n    borderColor: '#27313d',\n    borderWidth: 1,\n    cardPadding: 18,\n    cardPaddingBlock: 10,\n    cardRadius: 10,\n    canvasPaddingTop: 8,\n    canvasMarginInline: 12,\n    headerHeight: 28,\n    headerMarginBottom: 8,\n    headerFontSize: 14,\n    avatarSize: 24,\n    footerPadding: '8px 32px',\n    footerFontSize: 12,\n    fontFamily: 'Inter, ui-sans-serif, system-ui, sans-serif',\n  }}\n/>\n```\n\nThe matching CSS variables are:\n\n| Theme key | CSS variable |\n| --- | --- |\n| `bgColor` | `--gh-bg-color` |\n| `textColor` | `--gh-text-default-color` |\n| `inactiveTextColor` | `--gh-text-inactive-color` |\n| `linkHoverColor` | `--gh-link-hover-color` |\n| `cellLevel0` - `cellLevel4` | `--gh-cell-level0-color` - `--gh-cell-level4-color` |\n| `cellSize` | `--gh-cell-size` |\n| `cellGap` | `--gh-cell-gap` |\n| `cellRadius` | `--gh-cell-radius` |\n| `cellBorderColor` | `--gh-cell-border-color` |\n| `cellOutlineColor` | `--gh-cell-outline-color` |\n| `tooltipBgColor` | `--gh-cell-info-bg-color` |\n| `tooltipTextColor` | `--gh-tooltip-text-color` |\n| `tooltipPadding` | `--gh-tooltip-padding` |\n| `tooltipRadius` | `--gh-tooltip-radius` |\n| `tooltipFontSize` | `--gh-tooltip-font-size` |\n| `borderColor` | `--gh-border-card-color` |\n| `borderWidth` | `--gh-border-card-width` |\n| `cardPadding` | `--gh-card-padding` |\n| `cardPaddingBlock` | `--gh-card-padding-block` |\n| `cardRadius` | `--gh-card-radius` |\n| `canvasPaddingTop` | `--gh-canvas-padding-top` |\n| `canvasMarginInline` | `--gh-canvas-margin-inline` |\n| `headerHeight` | `--gh-header-height` |\n| `headerMarginBottom` | `--gh-header-margin-bottom` |\n| `headerFontSize` | `--gh-header-font-size` |\n| `avatarSize` | `--gh-avatar-size` |\n| `footerPadding` | `--gh-footer-padding` |\n| `footerFontSize` | `--gh-footer-font-size` |\n| `fontFamily` | `--gh-font-default-family` |\n\n### Labels, Tooltips, Classes, And Cells\n\n```tsx\n<GitHubContributionGraph\n  username=\"octocat\"\n  showMonthLabels\n  showWeekdayLabels\n  showTooltips\n  dayLabels={['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']}\n  footerLabels={{ less: 'Quiet', more: 'Busy' }}\n  classNames={{\n    root: 'activity',\n    header: 'activity__header',\n    total: 'activity__total',\n    profile: 'activity__profile',\n    profileLink: 'activity__profile-link',\n    avatar: 'activity__avatar',\n    card: 'activity__card',\n    canvas: 'activity__canvas',\n    table: 'activity__table',\n    monthLabel: 'activity__month',\n    dayLabel: 'activity__weekday',\n    dayCell: 'activity__day',\n    tooltip: 'activity__tooltip',\n    footer: 'activity__footer',\n    footerLegend: 'activity__legend',\n    thumbnail: 'activity__thumbnail',\n    thumbnailLink: 'activity__thumbnail-link',\n  }}\n  dayClassName={({ day }) =>\n    day.contributionCount >= 10 ? 'activity__day--hot' : undefined\n  }\n  dayStyle={({ day }) => ({\n    opacity: day.contributionCount === 0 ? '0.35' : '1',\n    borderRadius: day.contributionCount >= 10 ? 6 : 2,\n  })}\n  dayAttributes={({ day }) => ({\n    'aria-label': `${day.contributionCount} contributions on ${day.date}`,\n    'data-busy': day.contributionCount >= 10,\n  })}\n  tooltipFormatter={({ day, date, username }) =>\n    `${username} made ${day.contributionCount} contributions on ${date.toLocaleDateString()}`\n  }\n  monthLabelFormatter={(month) => month.name.toUpperCase()}\n/>\n```\n\nEvery day cell also receives these default attributes, which makes CSS-only custom designs straightforward:\n\n```css\n.activity__day[data-level='FOURTH_QUARTILE'] {\n  box-shadow: 0 0 0 2px color-mix(in srgb, var(--gh-cell-level4-color), white 20%);\n}\n\n.activity__day[data-count='0'] {\n  opacity: 0.4;\n}\n```\n\n### Replace Individual Sections\n\nThe default renderer can replace the header, footer, thumbnail, or the contents inside each day cell. These hooks return DOM nodes or strings.\n\n```ts\nconst widget = new GitHubContributionWidget({\n  username: 'octocat',\n  container: '#my-graph',\n  renderHeader: ({ username, totalContributions, user }) => {\n    const header = document.createElement('header');\n    header.className = 'activity-header';\n\n    const avatar = document.createElement('img');\n    avatar.src = user.avatarUrl;\n    avatar.alt = `${username}'s avatar`;\n\n    const name = document.createElement('strong');\n    name.textContent = username;\n\n    const total = document.createElement('span');\n    total.textContent = `${totalContributions.toLocaleString()} contributions`;\n\n    header.append(avatar, name, total);\n    return header;\n  },\n  renderDayContents: ({ day }) => {\n    const dot = document.createElement('span');\n    dot.className = 'activity-dot';\n    dot.textContent = day.contributionCount > 0 ? String(day.contributionCount) : '';\n    return dot;\n  },\n  renderFooter: ({ labels }) => {\n    const footer = document.createElement('footer');\n    footer.textContent = `${labels.less} / ${labels.more}`;\n    return footer;\n  },\n  renderThumbnail: () => null,\n});\n```\n\nWhen using the React component, `renderHeader`, `renderFooter`, `renderThumbnail`, and `renderDayContents` still belong to the default DOM renderer, so they return DOM nodes. Use the React `render` prop if you want JSX-level control.\n\n### Fully Custom React Render\n\nThe `render` prop lets React users use the package only for fetching and state management. You receive the raw GitHub contribution calendar and can render every pixel yourself.\n\n```tsx\n<GitHubContributionGraph\n  username=\"octocat\"\n  render={({ data, loading, error, refresh }) => {\n    if (loading) return <p>Loading activity...</p>;\n    if (error) return <button onClick={refresh}>Retry</button>;\n\n    const calendar = data?.contributionsCollection.contributionCalendar;\n\n    return (\n      <section className=\"activity-board\">\n        <strong>{calendar?.totalContributions.toLocaleString()} contributions</strong>\n        <div className=\"activity-grid\">\n          {calendar?.weeks.flatMap((week) =>\n            week.contributionDays.map((day) => (\n              <span\n                key={day.date}\n                className=\"activity-cell\"\n                data-level={day.contributionLevel}\n                title={`${day.contributionCount} on ${day.date}`}\n              />\n            ))\n          )}\n        </div>\n      </section>\n    );\n  }}\n/>\n```\n\n## API Endpoint\n\nBy default, the package fetches contribution data from:\n\n```text\nhttps://githubgraph.jigyansurout.com/api/ghcg/fetch-data?login={username}\n```\n\nThe response shape matches the GitHub GraphQL contribution calendar:\n\n```json\n{\n  \"user\": {\n    \"avatarUrl\": \"https://avatars.githubusercontent.com/...\",\n    \"contributionsCollection\": {\n      \"contributionCalendar\": {\n        \"totalContributions\": 1234,\n        \"months\": [],\n        \"weeks\": []\n      }\n    }\n  }\n}\n```\n\nUse `apiEndpoint` if you want to run your own backend.\n\n## Self-Hosting\n\nThis repository includes a Cloudflare Pages Functions backend at `functions/api/ghcg/fetch-data.js`.\n\n1. Fork or clone the repository.\n2. Create a GitHub personal access token with enough access to read the contribution calendar you want to show.\n3. Add `GITHUB_TOKEN` to your Cloudflare Pages environment variables.\n4. Use `npm run build` as the build command.\n5. Use `cf-dist` as the Pages output directory.\n6. Deploy with the repository root as the project root so Cloudflare can discover `functions/`.\n7. Pass your endpoint to the widget:\n\n```tsx\n<GitHubContributionGraph\n  username=\"octocat\"\n  apiEndpoint=\"https://your-domain.com/api/ghcg/fetch-data\"\n/>\n```\n\nLocal development:\n\n```bash\nnpm install\necho \"GITHUB_TOKEN=your_token\" > .env\nnpm run build\nnpm run dev\n```\n\n## Troubleshooting\n\n- Use `github-contrib-graph`, not `github-contribution-graph`, when installing from npm.\n- For script-tag usage, place the `<script>` after the graph container or call `window.renderGitHubWidget()` after adding the container.\n- Make sure `data-login` or `username` is a valid GitHub username.\n- If you self-host, confirm your API returns `{ \"user\": ... }` and includes CORS headers for browser usage.\n- If private contributions are missing, check the permissions and visibility available to your GitHub token.\n\n## Browser Support\n\n- Modern browsers with ES2020 support\n- Node.js 18+\n\n## License\n\nApache-2.0\n","readmeFilename":"README.md"}