[
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"extends\": \"next/core-web-vitals\"\n}\n"
  },
  {
    "path": ".gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n.yarn/install-state.gz\n\n# testing\n/coverage\n\n# next.js\n/.next/\n/out/\n\n# production\n/build\n\n# misc\n.DS_Store\n*.pem\n\n# debug\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# local env files\n.env*.local\n\n# vercel\n.vercel\n\n# typescript\n*.tsbuildinfo\nnext-env.d.ts\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2024 Gurbaaz Singh Nandra\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# shadcn-calendar-heatmap\n\nA modern, customizable calendar heatmap component built on top of [react-day-picker](https://react-day-picker.js.org/) following [shadcn/ui](https://ui.shadcn.com/) patterns.\n\n**Accessible. Unstyled. Customizable. Open Source.**\n\n![og](public/og.png)\n\n## ✨ Features\n\n- 🎨 **Fully Customizable** - Style with Tailwind CSS classes\n- 📅 **Multiple Data Modes** - Use direct date arrays or weighted dates with auto-categorization\n- 🔢 **Multi-month Support** - Display any number of months\n- ♿ **Accessible** - Built on react-day-picker with full keyboard navigation\n- 🎯 **Type Safe** - Written in TypeScript with full type definitions\n- 🌈 **Preset Variants** - GitHub streaks, temperature heatmaps, rainbow colors, and more\n\n## 🚀 Demo\n\nCheck out the live demo at [shadcn-calendar-heatmap.vercel.app](https://shadcn-calendar-heatmap.vercel.app)\n\n## 📦 Installation\n\nThis component follows the shadcn/ui philosophy - copy the component directly into your project.\n\n### 1. Install Dependencies\n\n```bash\nnpm install react-day-picker date-fns lucide-react\n# or\nyarn add react-day-picker date-fns lucide-react\n# or\npnpm add react-day-picker date-fns lucide-react\n```\n\n### 2. Copy the Component\n\nCopy [`components/ui/calendar-heatmap.tsx`](https://github.com/gurbaaz27/shadcn-calendar-heatmap/blob/main/components/ui/calendar-heatmap.tsx) into your project's components directory.\n\n### 3. Ensure you have the required utilities\n\nMake sure you have the `cn` utility function (standard in shadcn/ui projects):\n\n```typescript\n// lib/utils.ts\nimport { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs))\n}\n```\n\n## 📖 Usage\n\n### Basic Example - GitHub Contribution Graph\n\n```tsx\nimport { CalendarHeatmap } from \"@/components/ui/calendar-heatmap\"\n\nexport default function MyComponent() {\n  return (\n    <CalendarHeatmap\n      variantClassnames={[\n        \"text-white hover:text-white bg-green-400 hover:bg-green-400\",\n        \"text-white hover:text-white bg-green-500 hover:bg-green-500\",\n        \"text-white hover:text-white bg-green-700 hover:bg-green-700\",\n      ]}\n      datesPerVariant={[\n        [new Date('Jan 1, 2024'), new Date('Jan 15, 2024')],\n        [new Date('Jun 12, 2024'), new Date('July 1, 2024')],\n        [new Date('Jan 19, 2024'), new Date('Apr 14, 2024')],\n      ]}\n    />\n  )\n}\n```\n\n### Using Weighted Dates\n\nPass dates with numeric weights, and the component auto-categorizes them:\n\n```tsx\n<CalendarHeatmap\n  variantClassnames={[\n    \"text-white hover:text-white bg-blue-300 hover:bg-blue-300\",\n    \"text-white hover:text-white bg-green-500 hover:bg-green-500\",\n    \"text-white hover:text-white bg-amber-400 hover:bg-amber-400\",\n    \"text-white hover:text-white bg-red-700 hover:bg-red-700\",\n  ]}\n  weightedDates={[\n    { date: new Date('Jan 1, 2024'), weight: 2 },\n    { date: new Date('Jun 12, 2024'), weight: 8 },\n    { date: new Date('Apr 19, 2024'), weight: 13.5 },\n  ]}\n/>\n```\n\n### Multi-month Display\n\n```tsx\n<CalendarHeatmap\n  numberOfMonths={3}\n  variantClassnames={[...]}\n  datesPerVariant={[...]}\n/>\n```\n\n## 🔧 API Reference\n\n### Props\n\n| Prop | Type | Required | Description |\n|------|------|----------|-------------|\n| `variantClassnames` | `string[]` | ✅ | Array of Tailwind CSS classes for each intensity level |\n| `datesPerVariant` | `Date[][]` | ⚡ | 2D array where each inner array contains dates for that variant |\n| `weightedDates` | `WeightedDateEntry[]` | ⚡ | Array of `{ date: Date, weight: number }` objects |\n| `numberOfMonths` | `number` | ❌ | Number of months to display (default: 1) |\n| `showOutsideDays` | `boolean` | ❌ | Show days from adjacent months (default: true) |\n\n> ⚡ You must provide either `datesPerVariant` OR `weightedDates`, not both.\n\nThe component also accepts all props from [react-day-picker](https://react-day-picker.js.org/api/interfaces/DayPickerMultipleProps).\n\n### Types\n\n```typescript\ntype WeightedDateEntry = {\n  date: Date\n  weight: number\n}\n```\n\n## 🎨 Customization Examples\n\n### Temperature Heatmap\n\n```tsx\nconst Heatmap = [\n  \"text-white hover:text-white bg-blue-300 hover:bg-blue-300\",   // Cold\n  \"text-white hover:text-white bg-green-500 hover:bg-green-500\", // Mild\n  \"text-white hover:text-white bg-amber-400 hover:bg-amber-400\", // Warm\n  \"text-white hover:text-white bg-red-700 hover:bg-red-700\",     // Hot\n]\n```\n\n### Rainbow Colors\n\n```tsx\nconst Rainbow = [\n  \"text-white hover:text-white bg-violet-400 hover:bg-violet-400\",\n  \"text-white hover:text-white bg-indigo-400 hover:bg-indigo-400\",\n  \"text-white hover:text-white bg-blue-400 hover:bg-blue-400\",\n  \"text-white hover:text-white bg-green-400 hover:bg-green-400\",\n  \"text-white hover:text-white bg-yellow-400 hover:bg-yellow-400\",\n  \"text-white hover:text-white bg-orange-400 hover:bg-orange-400\",\n  \"text-white hover:text-white bg-red-400 hover:bg-red-400\",\n]\n```\n\n## ⭐ Star History\n\n<a href=\"https://star-history.com/#gurbaaz27/shadcn-calendar-heatmap&Date\">\n <picture>\n   <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=gurbaaz27/shadcn-calendar-heatmap&type=Date&theme=dark\" />\n   <source media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=gurbaaz27/shadcn-calendar-heatmap&type=Date\" />\n   <img alt=\"Star History Chart\" src=\"https://api.star-history.com/svg?repos=gurbaaz27/shadcn-calendar-heatmap&type=Date\" />\n </picture>\n</a>\n\n## 🤝 Contributing\n\nContributions are welcome! Feel free to open an issue or submit a pull request.\n\n## 📄 License\n\nMIT © [Gurbaaz Singh Nandra](https://x.com/GurbaazNandra)\n\n## 🔗 Links\n\n- [Live Demo](https://shadcn-calendar-heatmap.vercel.app)\n- [GitHub Repository](https://github.com/gurbaaz27/shadcn-calendar-heatmap)\n- [Twitter/X](https://x.com/GurbaazNandra)\n"
  },
  {
    "path": "app/(components)/copy-llms-button.tsx",
    "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { buttonVariants } from \"@/components/ui/button\"\nimport { cn } from \"@/lib/utils\"\nimport { Check, Copy } from \"lucide-react\"\n\ninterface CopyLlmsButtonProps {\n  content: string\n  className?: string\n}\n\nexport function CopyLlmsButton({ content, className }: CopyLlmsButtonProps) {\n  const [copied, setCopied] = useState(false)\n\n  const handleCopy = async () => {\n    await navigator.clipboard.writeText(content)\n    setCopied(true)\n    setTimeout(() => setCopied(false), 2000)\n  }\n\n  return (\n    <button\n      onClick={handleCopy}\n      className={cn(\n        buttonVariants({ variant: \"outline\" }),\n        \"relative !py-0 group\",\n        className\n      )}\n    >\n      {copied ? (\n        <Check className=\"mr-2 h-4 w-4\" />\n      ) : (\n        <Copy className=\"mr-2 h-4 w-4\" />\n      )}\n      {copied ? \"Copied\" : \"Copy llms.txt\"}\n    </button>\n  )\n}\n"
  },
  {
    "path": "app/(components)/example-code.tsx",
    "content": "import { Code } from \"@/components/code\"\n\nconst tsx = `import { CalendarHeatmap } from \"@/components/ui/calendar-heatmap\"\n\n// Github-style streak pattern\n<CalendarHeatmap\n  variantClassnames={[\n    \"text-white hover:text-white bg-green-400 hover:bg-green-400\",\n    \"text-white hover:text-white bg-green-500 hover:bg-green-500\",\n    \"text-white hover:text-white bg-green-700 hover:bg-green-700\",\n  ]}\n  datesPerVariant={[\n    [new Date('Jan 1, 2024'), new Date('Jan 15, 2024'), new Date('Feb 18, 2024')],\n    [new Date('Jun 12, 2024'), new Date('July 1, 2024'), new Date('Feb 29, 2024'), new Date('May 4, 2024')],\n    [new Date('Jan 19, 2024'), new Date('Apr 14, 2024')],\n  ]}\n/>\n\n// Or you may simply pass weighted array of dates,\n// and they would be slotted to different variants based on length of \\`variantClassnames\\`\n<CalendarHeatmap\n  variantClassnames={[\n    \"text-white hover:text-white bg-green-400 hover:bg-green-400\",\n    \"text-white hover:text-white bg-green-500 hover:bg-green-500\",\n    \"text-white hover:text-white bg-green-700 hover:bg-green-700\",\n  ]}\n  weightedDates={[\n    { date: new Date('Jan 1, 2024'), weight: 2 }, { date : new Date('Jan 15, 2024'), weight: 1.5 },\n    { date: new Date('Jun 12, 2024'), weight: 8 } , { date: new Date('July 1, 2024'), weight: 5 },\n    { date: new Date('Jan 19, 2024'), weight: 6 }, { date: new Date('Apr 19, 2024'), weight: 13.5 }\n  ]}\n/>\n\n// Component code at https://github.com/gurbaaz27/shadcn-calendar-heatmap/blob/main/components/ui/calendar-heatmap.tsx\n`\n\nconst code = `\\`\\`\\`tsx /maxLength={6}/ /render/ /slots/1 /.map((slot, idx)/1 /Slot/2,3,4 /props.char/2 /<FakeCaret />/\n${tsx}\n\\`\\`\\``\n\nexport function ExampleCode() {\n  return (\n    <div className=\"relative code-example w-full overflow-hidden lg:opacity-0 lg:animate-fade-in [animation-delay:5000ms] animate-none\">\n      <div className=\"w-full\">\n        <Code dark={false} code={code} toCopy={tsx} />\n        <Code dark={true} code={code} toCopy={tsx} />\n      </div>\n\n      <div className=\"hidden lg:[display:unset] absolute inset-x-0 top-0 -bottom-full code-example-overlay pointer-events-none z-20 [animation-delay:5000ms]\"></div>\n\n      {/* Anchor */}\n      <div className=\"code-example-anchor absolute pointer-events-none w-px h-px -top-[5.5rem]\" />\n    </div>\n  )\n}\n"
  },
  {
    "path": "app/(components)/example-variants.ts",
    "content": "import {\n  currentMonthFirstDate,\n  currentMonthLastDate,\n  randomDate,\n} from \"@/lib/utils\"\n\nexport const GithubStreak = [\n  \"text-white hover:text-white bg-green-400 hover:bg-green-400\",\n  \"text-white hover:text-white bg-green-500 hover:bg-green-500\",\n  \"text-white hover:text-white bg-green-700 hover:bg-green-700\",\n]\n\nexport const GithubStreakDates = [\n  [...Array(12)].map((_) =>\n    randomDate(currentMonthFirstDate(), currentMonthLastDate(3))\n  ),\n  [...Array(9)].map((_) =>\n    randomDate(currentMonthFirstDate(), currentMonthLastDate(3))\n  ),\n  [...Array(6)].map((_) =>\n    randomDate(currentMonthFirstDate(), currentMonthLastDate(3))\n  ),\n]\n\nexport const Heatmap = [\n  \"text-white hover:text-white bg-blue-300 hover:bg-blue-300\",\n  \"text-white hover:text-white bg-green-500 hover:bg-green-500\",\n  \"text-white hover:text-white bg-amber-400 hover:bg-amber-400\",\n  \"text-white hover:text-white bg-red-700 hover:bg-red-700\",\n]\n\nexport const HeatmapDatesWeight = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]\n\nexport const Rainbow = [\n  \"text-white hover:text-white bg-violet-400 hover:bg-violet-400\",\n  \"text-white hover:text-white bg-indigo-400 hover:bg-indigo-400\",\n  \"text-white hover:text-white bg-blue-400 hover:bg-blue-400\",\n  \"text-white hover:text-white bg-green-400 hover:bg-green-400\",\n  \"text-white hover:text-white bg-yellow-400 hover:bg-yellow-400\",\n  \"text-white hover:text-white bg-orange-400 hover:bg-orange-400\",\n  \"text-white hover:text-white bg-red-400 hover:bg-red-400\",\n]\n\nexport const RainbowDates = [\n  [...Array(3)].map((_) =>\n    randomDate(currentMonthFirstDate(), currentMonthLastDate(2))\n  ),\n  [...Array(2)].map((_) =>\n    randomDate(currentMonthFirstDate(), currentMonthLastDate(2))\n  ),\n  [...Array(1)].map((_) =>\n    randomDate(currentMonthFirstDate(), currentMonthLastDate(2))\n  ),\n  [...Array(3)].map((_) =>\n    randomDate(currentMonthFirstDate(), currentMonthLastDate(2))\n  ),\n  [...Array(2)].map((_) =>\n    randomDate(currentMonthFirstDate(), currentMonthLastDate(2))\n  ),\n  [...Array(1)].map((_) =>\n    randomDate(currentMonthFirstDate(), currentMonthLastDate(2))\n  ),\n  [...Array(3)].map((_) =>\n    randomDate(currentMonthFirstDate(), currentMonthLastDate(2))\n  ),\n]\n"
  },
  {
    "path": "app/globals.css",
    "content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n@layer base {\n  :root {\n    --background: 0 0% 100%;\n    --foreground: 240 10% 3.9%;\n    --card: 0 0% 100%;\n    --card-foreground: 240 10% 3.9%;\n    --popover: 0 0% 100%;\n    --popover-foreground: 240 10% 3.9%;\n    --primary: 240 5.9% 10%;\n    --primary-foreground: 0 0% 98%;\n    --secondary: 240 4.8% 95.9%;\n    --secondary-foreground: 240 5.9% 10%;\n    --muted: 240 4.8% 95.9%;\n    --muted-foreground: 240 3.8% 46.1%;\n    --accent: 240 4.8% 95.9%;\n    --accent-foreground: 240 5.9% 10%;\n    --destructive: 0 72.22% 50.59%;\n    --destructive-foreground: 0 0% 98%;\n    --border: 240 5.9% 90%;\n    --input: 240 5.9% 90%;\n    --ring: 240 5% 64.9%;\n    --radius: 0.5rem;\n  }\n\n  .dark {\n    --background: 240 10% 3.9%;\n    --foreground: 0 0% 98%;\n    --card: 240 10% 3.9%;\n    --card-foreground: 0 0% 98%;\n    --popover: 240 10% 3.9%;\n    --popover-foreground: 0 0% 98%;\n    --primary: 0 0% 98%;\n    --primary-foreground: 240 5.9% 10%;\n    --secondary: 240 3.7% 15.9%;\n    --secondary-foreground: 0 0% 98%;\n    --muted: 240 3.7% 15.9%;\n    --muted-foreground: 240 5% 64.9%;\n    --accent: 240 3.7% 15.9%;\n    --accent-foreground: 0 0% 98%;\n    --destructive: 0 62.8% 30.6%;\n    --destructive-foreground: 0 85.7% 97.3%;\n    --border: 240 3.7% 15.9%;\n    --input: 240 3.7% 15.9%;\n    --ring: 240 4.9% 83.9%;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --background: 240 10% 3.9%;\n    --foreground: 0 0% 98%;\n    --card: 240 10% 3.9%;\n    --card-foreground: 0 0% 98%;\n    --popover: 240 10% 3.9%;\n    --popover-foreground: 0 0% 98%;\n    --primary: 0 0% 98%;\n    --primary-foreground: 240 5.9% 10%;\n    --secondary: 240 3.7% 15.9%;\n    --secondary-foreground: 0 0% 98%;\n    --muted: 240 3.7% 15.9%;\n    --muted-foreground: 240 5% 64.9%;\n    --accent: 240 3.7% 15.9%;\n    --accent-foreground: 0 0% 98%;\n    --destructive: 0 62.8% 30.6%;\n    --destructive-foreground: 0 85.7% 97.3%;\n    --border: 240 3.7% 15.9%;\n    --input: 240 3.7% 15.9%;\n    --ring: 240 4.9% 83.9%;\n  }\n}\n\n@layer base {\n  * {\n    @apply border-border;\n  }\n  body {\n    /* @apply bg-background text-foreground selection:bg-[#6B2BF4] selection:text-foreground; */\n    @apply bg-background text-foreground;\n    /* font-feature-settings: \"rlig\" 1, \"calt\" 1; */\n    font-synthesis-weight: none;\n    text-rendering: optimizeLegibility;\n  }\n}\n\n@layer utilities {\n}\n\n[data-highlighted-chars] {\n  @apply bg-zinc-900 rounded;\n  box-shadow: 2px 2px 0 2px rgba(139, 139, 148, 0.5);\n}\n[data-highlighted-chars] .dark {\n  @apply bg-zinc-700/50 rounded;\n  box-shadow: 2px 2px 0 2px rgba(139, 139, 148, 0.5);\n}\n[data-highlighted-chars] * {\n  @apply !text-white;\n}\n[data-rehype-pretty-code-figure] pre {\n  @apply pb-4 pt-6 max-h-[650px] overflow-x-auto rounded-lg border !bg-transparent;\n}\n[data-rehype-pretty-code-figure] [data-line] {\n  @apply inline-block min-h-4 w-full py-0.5 px-4;\n}\n\n.code-example-overlay {\n  background-image: linear-gradient(\n    to bottom,\n    theme(\"colors.background\") 60%,\n    transparent\n  );\n  transform: translateY(0);\n  animation: move-overlay 4s ease-out forwards;\n  animation-delay: 3s;\n}\n.code-example-light {\n}\n.code-example-dark {\n  display: none;\n}\n@media (prefers-color-scheme: dark) {\n  .code-example-light {\n    display: none;\n  }\n  .code-example-dark {\n    display: unset;\n  }\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .code-example-overlay {\n    opacity: 0;\n    animation: none;\n  }\n}\n@keyframes move-overlay {\n  0% {\n    transform: translateY(0);\n  }\n  100% {\n    transform: translateY(-100%);\n  }\n}\n"
  },
  {
    "path": "app/layout.tsx",
    "content": "import \"./globals.css\"\nimport type { Metadata } from \"next\"\nimport { cn } from \"@/lib/utils\"\nimport { GeistSans } from \"geist/font/sans\"\nimport { JetBrains_Mono } from \"next/font/google\"\nimport { SiteHeader } from \"@/components/site-header\"\nimport { SiteFooter } from \"@/components/site-footer\"\nimport { Toaster } from \"@/components/ui/sonner\"\nimport { siteConfig } from \"@/config/site\"\n\nexport const fontMono = JetBrains_Mono({\n  subsets: [\"latin\"],\n  variable: \"--font-mono\",\n})\n\nexport const metadata: Metadata = {\n  title: {\n    default: siteConfig.title,\n    template: `%s - ${siteConfig.name}`,\n  },\n  metadataBase: new URL(siteConfig.url),\n  description: siteConfig.description,\n  keywords: [\n    \"React\",\n    \"Heatmap\",\n    \"Calendar\",\n    \"Next.js\",\n    \"Tailwind CSS\",\n    \"Server Components\",\n    \"Accessible\",\n    \"Shadcn\",\n  ],\n  authors: [\n    {\n      name: \"gurbaaz\",\n      url: \"https://gurbaaz.me\",\n    },\n  ],\n  creator: \"gurbaaz\",\n  openGraph: {\n    type: \"website\",\n    locale: \"en_IN\",\n    url: siteConfig.url,\n    title: siteConfig.name,\n    description: siteConfig.description,\n    siteName: siteConfig.name,\n    images: [\n      {\n        url: siteConfig.ogImage,\n        width: 1200,\n        height: 630,\n        alt: siteConfig.name,\n      },\n    ],\n  },\n  twitter: {\n    card: \"summary_large_image\",\n    title: siteConfig.name,\n    description: siteConfig.description,\n    images: [siteConfig.ogImage],\n    creator: \"@GurbaazNandra\",\n  },\n  icons: {\n    icon: \"/favicon.ico\",\n    shortcut: \"/favicon-16x16.png\",\n    apple: \"/apple-touch-icon.png\",\n  },\n}\n\nexport default function RootLayout({\n  children,\n}: Readonly<{\n  children: React.ReactNode\n}>) {\n  return (\n    <html lang=\"en\">\n      <body\n        className={cn(\n          \"min-h-[100dvh] bg-background font-sans antialiased\",\n          GeistSans.className\n        )}\n      >\n        <div className=\"relative flex min-h-[100dvh] flex-col bg-background\">\n          <SiteHeader />\n          <main className=\"flex-1 flex flex-col\">{children}</main>\n          <SiteFooter />\n        </div>\n        <Toaster />\n      </body>\n    </html>\n  )\n}\n"
  },
  {
    "path": "app/page.tsx",
    "content": "import {\n  PageActions,\n  PageHeader,\n  PageHeaderDescription,\n  PageHeaderHeading,\n  PageHeaderNotifier,\n} from \"@/components/page-header\"\nimport { buttonVariants } from \"@/components/ui/button\"\nimport { siteConfig } from \"@/config/site\"\nimport {\n  cn,\n  currentMonthFirstDate,\n  currentMonthLastDate,\n  randomDate,\n} from \"@/lib/utils\"\nimport Link from \"next/link\"\nimport { CalendarHeatmap } from \"@/components/ui/calendar-heatmap\"\nimport { Icons } from \"@/components/icons\"\nimport { Star } from \"lucide-react\"\nimport { ExampleCode } from \"./(components)/example-code\"\nimport { CopyLlmsButton } from \"./(components)/copy-llms-button\"\nimport { readFile } from \"fs/promises\"\nimport path from \"path\"\nimport {\n  GithubStreak,\n  GithubStreakDates,\n  Heatmap,\n  HeatmapDatesWeight,\n  Rainbow,\n  RainbowDates,\n} from \"./(components)/example-variants\"\n\nconst fadeUpClassname =\n  \"lg:motion-safe:opacity-0 lg:motion-safe:animate-fade-up\"\n\nasync function getRepoStarCount() {\n  const res = await fetch(`https://api.github.com/repos/${siteConfig.name}`)\n  const data = await res.json()\n  const starCount = data.stargazers_count\n\n  if (starCount > 999) {\n    return (starCount / 1000).toFixed(1) + \"K\"\n  }\n\n  return starCount\n}\n\nexport default async function IndexPage() {\n  const starCount = await getRepoStarCount()\n  const llmsContent = await readFile(\n    path.join(process.cwd(), \"public\", \"llms.txt\"),\n    \"utf-8\"\n  )\n\n  return (\n    <div className=\"container relative flex-1 flex flex-col justify-center items-center\">\n      <PageHeader>\n        <PageHeaderNotifier>\n          Excited to officially launch our new shadcn-based component!\n          <span className=\"mx-2\">🎉</span>\n        </PageHeaderNotifier>\n\n        <PageHeaderHeading className={cn(fadeUpClassname)}>\n          Modern alternative to primitive react heatmaps.\n        </PageHeaderHeading>\n\n        <CalendarHeatmap\n          className={cn(\n            fadeUpClassname,\n            \"lg:motion-safe:[animation-delay:1000ms]\"\n          )}\n          variantClassnames={GithubStreak}\n          datesPerVariant={GithubStreakDates}\n        />\n\n        <PageHeaderDescription\n          className={cn(\n            fadeUpClassname,\n            \"lg:motion-safe:[animation-delay:3000ms]\"\n          )}\n        >\n          Showcase Github streaks. Visualise user growth. Understand global\n          warming trends. <br></br>\n          Convey more with less.\n          <br></br>\n          Unstyled. Customizable. Open Source.\n        </PageHeaderDescription>\n\n        <PageActions\n          className={cn(\n            fadeUpClassname,\n            \"lg:motion-safe:[animation-delay:3000ms]\"\n          )}\n        >\n          <Link\n            target=\"_blank\"\n            rel=\"noreferrer\"\n            href={siteConfig.links.github}\n            className={cn(\n              \"relative !py-0 group\",\n              buttonVariants({ variant: \"outline\" })\n            )}\n          >\n            <Icons.gitHub className=\"mr-2 h-4 w-4\" />\n            <div className=\"flex items-center h-full\">\n              <div className=\"hidden md:[display:unset]\">{siteConfig.name}</div>\n              <div className=\"hidden md:[display:unset] h-full w-px bg-input group-hover:bg-foregrounds mx-4\" />\n              <Star size={16} className=\"mr-2\" />\n              <div>{starCount}</div>\n            </div>\n          </Link>\n          <CopyLlmsButton content={llmsContent} />\n        </PageActions>\n      </PageHeader>\n\n      <ExampleCode />\n\n      <PageHeader>\n        <PageHeaderHeading\n          className={cn(\n            fadeUpClassname,\n            \"lg:motion-safe:[animation-delay:4000ms]\",\n            \"text-3xl md:text-4xl\",\n            \"py-4\"\n          )}\n        >\n          Examples\n        </PageHeaderHeading>\n\n        <PageHeaderHeading\n          className={cn(\n            fadeUpClassname,\n            \"lg:motion-safe:[animation-delay:4000ms]\",\n            \"text-xl md:text-2xl\"\n          )}\n        >\n          Github Streaks\n        </PageHeaderHeading>\n\n        <CalendarHeatmap\n          className={cn(\n            fadeUpClassname,\n            \"lg:motion-safe:[animation-delay:1000ms]\"\n          )}\n          numberOfMonths={3}\n          variantClassnames={GithubStreak}\n          datesPerVariant={GithubStreakDates}\n        />\n\n        <PageHeaderHeading\n          className={cn(\n            fadeUpClassname,\n            \"lg:motion-safe:[animation-delay:4000ms]\",\n            \"text-xl md:text-2xl\"\n          )}\n        >\n          Temperature Heatmap\n        </PageHeaderHeading>\n\n        <CalendarHeatmap\n          className={cn(\n            fadeUpClassname,\n            \"lg:motion-safe:[animation-delay:4000ms]\"\n          )}\n          variantClassnames={Heatmap}\n          weightedDates={HeatmapDatesWeight.map((wgt) => ({\n            date: randomDate(currentMonthFirstDate(), currentMonthLastDate()),\n            weight: wgt,\n          }))}\n        />\n\n        <PageHeaderHeading\n          className={cn(\n            fadeUpClassname,\n            \"lg:motion-safe:[animation-delay:4000ms]\",\n            \"text-xl md:text-2xl\"\n          )}\n        >\n          Rainbow Colors\n        </PageHeaderHeading>\n\n        <CalendarHeatmap\n          className={cn(\n            fadeUpClassname,\n            \"lg:motion-safe:[animation-delay:4000ms]\"\n          )}\n          numberOfMonths={2}\n          variantClassnames={Rainbow}\n          datesPerVariant={RainbowDates}\n        />\n      </PageHeader>\n    </div>\n  )\n}\n\nexport const revalidate = 3600\n"
  },
  {
    "path": "components/code.tsx",
    "content": "import * as React from \"react\"\nimport { unified } from \"unified\"\nimport remarkParse from \"remark-parse\"\nimport remarkRehype from \"remark-rehype\"\nimport rehypeStringify from \"rehype-stringify\"\nimport rehypePrettyCode from \"rehype-pretty-code\"\nimport { CopyButton } from \"./copy-button\"\n\nexport async function Code({\n  code,\n  toCopy,\n  dark = true,\n}: {\n  code: string\n  toCopy?: string\n  dark?: boolean\n}) {\n  const highlightedCode = await highlightCode(code, dark)\n  return (\n    <div className={`relative code-example-${dark ? \"dark\" : \"light\"}`}>\n      <pre\n        dangerouslySetInnerHTML={{\n          __html: highlightedCode,\n        }}\n      />\n\n      {toCopy && (\n        <div className=\"absolute top-4 right-6\">\n          <CopyButton value={toCopy} />\n        </div>\n      )}\n    </div>\n  )\n}\n\nasync function highlightCode(code: string, dark: boolean) {\n  const file = await unified()\n    .use(remarkParse)\n    .use(remarkRehype)\n    .use(rehypePrettyCode, {\n      keepBackground: false,\n      theme: dark ? \"vesper\" : \"github-light\",\n    })\n    .use(rehypeStringify)\n    .process(code)\n\n  return String(file)\n}\n"
  },
  {
    "path": "components/copy-button.tsx",
    "content": "// Stolen from @shadcn/ui the man the machine!!\n\"use client\"\n\nimport * as React from \"react\"\nimport { CheckIcon, CopyIcon } from \"@radix-ui/react-icons\"\nimport type { DropdownMenuTriggerProps } from \"@radix-ui/react-dropdown-menu\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"./ui/button\"\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from \"./ui/dropdown-menu\"\n\ninterface CopyButtonProps extends React.HTMLAttributes<HTMLButtonElement> {\n  value: string\n  src?: string\n}\n\nexport async function copyToClipboardWithMeta(value: string) {\n  window && window.isSecureContext && navigator.clipboard.writeText(value)\n}\n\nexport function CopyButton({\n  value,\n  className,\n  src,\n  ...props\n}: CopyButtonProps) {\n  const [hasCopied, setHasCopied] = React.useState(false)\n\n  React.useEffect(() => {\n    setTimeout(() => {\n      setHasCopied(false)\n    }, 2000)\n  }, [hasCopied])\n\n  return (\n    <Button\n      size=\"icon\"\n      variant=\"ghost\"\n      className={cn(\n        \"relative z-10 h-6 w-6 text-zinc-50 hover:bg-zinc-700 hover:text-zinc-50\",\n        className\n      )}\n      onClick={() => {\n        copyToClipboardWithMeta(value)\n        setHasCopied(true)\n      }}\n      {...props}\n    >\n      <span className=\"sr-only\">Copy</span>\n      {hasCopied ? (\n        <CheckIcon className=\"h-3 w-3\" />\n      ) : (\n        <CopyIcon className=\"h-3 w-3\" />\n      )}\n    </Button>\n  )\n}\n\ninterface CopyWithClassNamesProps extends DropdownMenuTriggerProps {\n  value: string\n  classNames: string\n  className?: string\n}\n\nexport function CopyWithClassNames({\n  value,\n  classNames,\n  className,\n  ...props\n}: CopyWithClassNamesProps) {\n  const [hasCopied, setHasCopied] = React.useState(false)\n\n  React.useEffect(() => {\n    setTimeout(() => {\n      setHasCopied(false)\n    }, 2000)\n  }, [hasCopied])\n\n  const copyToClipboard = React.useCallback((value: string) => {\n    copyToClipboardWithMeta(value)\n    setHasCopied(true)\n  }, [])\n\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger asChild>\n        <Button\n          size=\"icon\"\n          variant=\"ghost\"\n          className={cn(\n            \"relative z-10 h-6 w-6 text-zinc-50 hover:bg-zinc-700 hover:text-zinc-50\",\n            className\n          )}\n        >\n          {hasCopied ? (\n            <CheckIcon className=\"h-3 w-3\" />\n          ) : (\n            <CopyIcon className=\"h-3 w-3\" />\n          )}\n          <span className=\"sr-only\">Copy</span>\n        </Button>\n      </DropdownMenuTrigger>\n      <DropdownMenuContent align=\"end\">\n        <DropdownMenuItem onClick={() => copyToClipboard(value)}>\n          Component\n        </DropdownMenuItem>\n        <DropdownMenuItem onClick={() => copyToClipboard(classNames)}>\n          Classname\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  )\n}\n\ninterface CopyNpmCommandButtonProps extends DropdownMenuTriggerProps {\n  commands: {\n    __npmCommand__: string\n    __yarnCommand__: string\n    __pnpmCommand__: string\n    __bunCommand__: string\n  }\n}\n\nexport function CopyNpmCommandButton({\n  commands,\n  className,\n  ...props\n}: CopyNpmCommandButtonProps) {\n  const [hasCopied, setHasCopied] = React.useState(false)\n\n  React.useEffect(() => {\n    setTimeout(() => {\n      setHasCopied(false)\n    }, 2000)\n  }, [hasCopied])\n\n  const copyCommand = React.useCallback(\n    (value: string, pm: \"npm\" | \"pnpm\" | \"yarn\" | \"bun\") => {\n      copyToClipboardWithMeta(value)\n      setHasCopied(true)\n    },\n    []\n  )\n\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger asChild>\n        <Button\n          size=\"icon\"\n          variant=\"ghost\"\n          className={cn(\n            \"relative z-10 h-6 w-6 hover:bg-zinc-700 hover:text-zinc-50\",\n            className\n          )}\n        >\n          {hasCopied ? (\n            <CheckIcon className=\"h-3 w-3\" />\n          ) : (\n            <CopyIcon className=\"h-3 w-3\" />\n          )}\n          <span className=\"sr-only\">Copy</span>\n        </Button>\n      </DropdownMenuTrigger>\n      <DropdownMenuContent align=\"end\">\n        <DropdownMenuItem\n          onClick={() => copyCommand(commands.__npmCommand__, \"npm\")}\n        >\n          npm\n        </DropdownMenuItem>\n        <DropdownMenuItem\n          onClick={() => copyCommand(commands.__yarnCommand__, \"yarn\")}\n        >\n          yarn\n        </DropdownMenuItem>\n        <DropdownMenuItem\n          onClick={() => copyCommand(commands.__pnpmCommand__, \"pnpm\")}\n        >\n          pnpm\n        </DropdownMenuItem>\n        <DropdownMenuItem\n          onClick={() => copyCommand(commands.__bunCommand__, \"bun\")}\n        >\n          bun\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  )\n}\n"
  },
  {
    "path": "components/icons.tsx",
    "content": "type IconProps = React.HTMLAttributes<SVGElement>\n\nexport const Icons = {\n  logo: (props: IconProps) => (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 256 256\" {...props}>\n      <rect width=\"256\" height=\"256\" fill=\"none\" />\n      <line\n        x1=\"208\"\n        y1=\"128\"\n        x2=\"128\"\n        y2=\"208\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"16\"\n      />\n      <line\n        x1=\"192\"\n        y1=\"40\"\n        x2=\"40\"\n        y2=\"192\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"16\"\n      />\n    </svg>\n  ),\n  twitter: (props: IconProps) => (\n    <svg\n      {...props}\n      height=\"23\"\n      viewBox=\"0 0 1200 1227\"\n      width=\"23\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path d=\"M714.163 519.284L1160.89 0H1055.03L667.137 450.887L357.328 0H0L468.492 681.821L0 1226.37H105.866L515.491 750.218L842.672 1226.37H1200L714.137 519.284H714.163ZM569.165 687.828L521.697 619.934L144.011 79.6944H306.615L611.412 515.685L658.88 583.579L1055.08 1150.3H892.476L569.165 687.854V687.828Z\" />\n    </svg>\n  ),\n  gitHub: (props: IconProps) => (\n    <svg viewBox=\"0 0 438.549 438.549\" {...props}>\n      <path\n        fill=\"currentColor\"\n        d=\"M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14.954 8.945.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-.571-.049-5.708-.144-15.417a2549.81 2549.81 0 01-.144-25.406l-6.567 1.136c-4.187.767-9.469 1.092-15.846 1-6.374-.089-12.991-.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-.572-1.335-.098-2.43 1.427-3.289 1.525-.859 4.281-1.276 8.28-1.276l5.708.853c3.807.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-.476 16.274-1.423 4.565-.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-.01-39.771-9.818-76.454-29.414-110.049z\"\n      ></path>\n    </svg>\n  ),\n  radix: (props: IconProps) => (\n    <svg viewBox=\"0 0 25 25\" fill=\"none\" {...props}>\n      <path\n        d=\"M12 25C7.58173 25 4 21.4183 4 17C4 12.5817 7.58173 9 12 9V25Z\"\n        fill=\"currentcolor\"\n      ></path>\n      <path d=\"M12 0H4V8H12V0Z\" fill=\"currentcolor\"></path>\n      <path\n        d=\"M17 8C19.2091 8 21 6.20914 21 4C21 1.79086 19.2091 0 17 0C14.7909 0 13 1.79086 13 4C13 6.20914 14.7909 8 17 8Z\"\n        fill=\"currentcolor\"\n      ></path>\n    </svg>\n  ),\n  aria: (props: IconProps) => (\n    <svg role=\"img\" viewBox=\"0 0 24 24\" fill=\"currentColor\" {...props}>\n      <path d=\"M13.966 22.624l-1.69-4.281H8.122l3.892-9.144 5.662 13.425zM8.884 1.376H0v21.248zm15.116 0h-8.884L24 22.624Z\" />\n    </svg>\n  ),\n  npm: (props: IconProps) => (\n    <svg viewBox=\"0 0 24 24\" {...props}>\n      <path\n        d=\"M1.763 0C.786 0 0 .786 0 1.763v20.474C0 23.214.786 24 1.763 24h20.474c.977 0 1.763-.786 1.763-1.763V1.763C24 .786 23.214 0 22.237 0zM5.13 5.323l13.837.019-.009 13.836h-3.464l.01-10.382h-3.456L12.04 19.17H5.113z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  ),\n  yarn: (props: IconProps) => (\n    <svg viewBox=\"0 0 24 24\" {...props}>\n      <path\n        d=\"M12 0C5.375 0 0 5.375 0 12s5.375 12 12 12 12-5.375 12-12S18.625 0 12 0zm.768 4.105c.183 0 .363.053.525.157.125.083.287.185.755 1.154.31-.088.468-.042.551-.019.204.056.366.19.463.375.477.917.542 2.553.334 3.605-.241 1.232-.755 2.029-1.131 2.576.324.329.778.899 1.117 1.825.278.774.31 1.478.273 2.015a5.51 5.51 0 0 0 .602-.329c.593-.366 1.487-.917 2.553-.931.714-.009 1.269.445 1.353 1.103a1.23 1.23 0 0 1-.945 1.362c-.649.158-.95.278-1.821.843-1.232.797-2.539 1.242-3.012 1.39a1.686 1.686 0 0 1-.704.343c-.737.181-3.266.315-3.466.315h-.046c-.783 0-1.214-.241-1.45-.491-.658.329-1.51.19-2.122-.134a1.078 1.078 0 0 1-.58-1.153 1.243 1.243 0 0 1-.153-.195c-.162-.25-.528-.936-.454-1.946.056-.723.556-1.367.88-1.71a5.522 5.522 0 0 1 .408-2.256c.306-.727.885-1.348 1.32-1.737-.32-.537-.644-1.367-.329-2.21.227-.602.412-.936.82-1.08h-.005c.199-.074.389-.153.486-.259a3.418 3.418 0 0 1 2.298-1.103c.037-.093.079-.185.125-.283.31-.658.639-1.029 1.024-1.168a.94.94 0 0 1 .328-.06zm.006.7c-.507.016-1.001 1.519-1.001 1.519s-1.27-.204-2.266.871c-.199.218-.468.334-.746.44-.079.028-.176.023-.417.672-.371.991.625 2.094.625 2.094s-1.186.839-1.626 1.881c-.486 1.144-.338 2.261-.338 2.261s-.843.732-.899 1.487c-.051.663.139 1.2.343 1.515.227.343.51.176.51.176s-.561.653-.037.931c.477.25 1.283.394 1.71-.037.31-.31.371-1.001.486-1.283.028-.065.12.111.209.199.097.093.264.195.264.195s-.755.324-.445 1.066c.102.246.468.403 1.066.398.222-.005 2.664-.139 3.313-.296.375-.088.505-.283.505-.283s1.566-.431 2.998-1.357c.917-.598 1.293-.76 2.034-.936.612-.148.57-1.098-.241-1.084-.839.009-1.575.44-2.196.825-1.163.718-1.742.672-1.742.672l-.018-.032c-.079-.13.371-1.293-.134-2.678-.547-1.515-1.413-1.881-1.344-1.997.297-.5 1.038-1.297 1.334-2.78.176-.899.13-2.377-.269-3.151-.074-.144-.732.241-.732.241s-.616-1.371-.788-1.483a.271.271 0 0 0-.157-.046z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  ),\n  pnpm: (props: IconProps) => (\n    <svg viewBox=\"0 0 24 24\" {...props}>\n      <path\n        d=\"M0 0v7.5h7.5V0zm8.25 0v7.5h7.498V0zm8.25 0v7.5H24V0zM8.25 8.25v7.5h7.498v-7.5zm8.25 0v7.5H24v-7.5zM0 16.5V24h7.5v-7.5zm8.25 0V24h7.498v-7.5zm8.25 0V24H24v-7.5z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  ),\n  react: (props: IconProps) => (\n    <svg viewBox=\"0 0 24 24\" {...props}>\n      <path\n        d=\"M14.23 12.004a2.236 2.236 0 0 1-2.235 2.236 2.236 2.236 0 0 1-2.236-2.236 2.236 2.236 0 0 1 2.235-2.236 2.236 2.236 0 0 1 2.236 2.236zm2.648-10.69c-1.346 0-3.107.96-4.888 2.622-1.78-1.653-3.542-2.602-4.887-2.602-.41 0-.783.093-1.106.278-1.375.793-1.683 3.264-.973 6.365C1.98 8.917 0 10.42 0 12.004c0 1.59 1.99 3.097 5.043 4.03-.704 3.113-.39 5.588.988 6.38.32.187.69.275 1.102.275 1.345 0 3.107-.96 4.888-2.624 1.78 1.654 3.542 2.603 4.887 2.603.41 0 .783-.09 1.106-.275 1.374-.792 1.683-3.263.973-6.365C22.02 15.096 24 13.59 24 12.004c0-1.59-1.99-3.097-5.043-4.032.704-3.11.39-5.587-.988-6.38-.318-.184-.688-.277-1.092-.278zm-.005 1.09v.006c.225 0 .406.044.558.127.666.382.955 1.835.73 3.704-.054.46-.142.945-.25 1.44-.96-.236-2.006-.417-3.107-.534-.66-.905-1.345-1.727-2.035-2.447 1.592-1.48 3.087-2.292 4.105-2.295zm-9.77.02c1.012 0 2.514.808 4.11 2.28-.686.72-1.37 1.537-2.02 2.442-1.107.117-2.154.298-3.113.538-.112-.49-.195-.964-.254-1.42-.23-1.868.054-3.32.714-3.707.19-.09.4-.127.563-.132zm4.882 3.05c.455.468.91.992 1.36 1.564-.44-.02-.89-.034-1.345-.034-.46 0-.915.01-1.36.034.44-.572.895-1.096 1.345-1.565zM12 8.1c.74 0 1.477.034 2.202.093.406.582.802 1.203 1.183 1.86.372.64.71 1.29 1.018 1.946-.308.655-.646 1.31-1.013 1.95-.38.66-.773 1.288-1.18 1.87-.728.063-1.466.098-2.21.098-.74 0-1.477-.035-2.202-.093-.406-.582-.802-1.204-1.183-1.86-.372-.64-.71-1.29-1.018-1.946.303-.657.646-1.313 1.013-1.954.38-.66.773-1.286 1.18-1.868.728-.064 1.466-.098 2.21-.098zm-3.635.254c-.24.377-.48.763-.704 1.16-.225.39-.435.782-.635 1.174-.265-.656-.49-1.31-.676-1.947.64-.15 1.315-.283 2.015-.386zm7.26 0c.695.103 1.365.23 2.006.387-.18.632-.405 1.282-.66 1.933-.2-.39-.41-.783-.64-1.174-.225-.392-.465-.774-.705-1.146zm3.063.675c.484.15.944.317 1.375.498 1.732.74 2.852 1.708 2.852 2.476-.005.768-1.125 1.74-2.857 2.475-.42.18-.88.342-1.355.493-.28-.958-.646-1.956-1.1-2.98.45-1.017.81-2.01 1.085-2.964zm-13.395.004c.278.96.645 1.957 1.1 2.98-.45 1.017-.812 2.01-1.086 2.964-.484-.15-.944-.318-1.37-.5-1.732-.737-2.852-1.706-2.852-2.474 0-.768 1.12-1.742 2.852-2.476.42-.18.88-.342 1.356-.494zm11.678 4.28c.265.657.49 1.312.676 1.948-.64.157-1.316.29-2.016.39.24-.375.48-.762.705-1.158.225-.39.435-.788.636-1.18zm-9.945.02c.2.392.41.783.64 1.175.23.39.465.772.705 1.143-.695-.102-1.365-.23-2.006-.386.18-.63.406-1.282.66-1.933zM17.92 16.32c.112.493.2.968.254 1.423.23 1.868-.054 3.32-.714 3.708-.147.09-.338.128-.563.128-1.012 0-2.514-.807-4.11-2.28.686-.72 1.37-1.536 2.02-2.44 1.107-.118 2.154-.3 3.113-.54zm-11.83.01c.96.234 2.006.415 3.107.532.66.905 1.345 1.727 2.035 2.446-1.595 1.483-3.092 2.295-4.11 2.295-.22-.005-.406-.05-.553-.132-.666-.38-.955-1.834-.73-3.703.054-.46.142-.944.25-1.438zm4.56.64c.44.02.89.034 1.345.034.46 0 .915-.01 1.36-.034-.44.572-.895 1.095-1.345 1.565-.455-.47-.91-.993-1.36-1.565z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  ),\n  tailwind: (props: IconProps) => (\n    <svg viewBox=\"0 0 24 24\" {...props}>\n      <path\n        d=\"M12.001,4.8c-3.2,0-5.2,1.6-6,4.8c1.2-1.6,2.6-2.2,4.2-1.8c0.913,0.228,1.565,0.89,2.288,1.624 C13.666,10.618,15.027,12,18.001,12c3.2,0,5.2-1.6,6-4.8c-1.2,1.6-2.6,2.2-4.2,1.8c-0.913-0.228-1.565-0.89-2.288-1.624 C16.337,6.182,14.976,4.8,12.001,4.8z M6.001,12c-3.2,0-5.2,1.6-6,4.8c1.2-1.6,2.6-2.2,4.2-1.8c0.913,0.228,1.565,0.89,2.288,1.624 c1.177,1.194,2.538,2.576,5.512,2.576c3.2,0,5.2-1.6,6-4.8c-1.2,1.6-2.6,2.2-4.2,1.8c-0.913-0.228-1.565-0.89-2.288-1.624 C10.337,13.382,8.976,12,6.001,12z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  ),\n  google: (props: IconProps) => (\n    <svg role=\"img\" viewBox=\"0 0 24 24\" {...props}>\n      <path\n        fill=\"currentColor\"\n        d=\"M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z\"\n      />\n    </svg>\n  ),\n  apple: (props: IconProps) => (\n    <svg role=\"img\" viewBox=\"0 0 24 24\" {...props}>\n      <path\n        d=\"M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  ),\n  paypal: (props: IconProps) => (\n    <svg role=\"img\" viewBox=\"0 0 24 24\" {...props}>\n      <path\n        d=\"M7.076 21.337H2.47a.641.641 0 0 1-.633-.74L4.944.901C5.026.382 5.474 0 5.998 0h7.46c2.57 0 4.578.543 5.69 1.81 1.01 1.15 1.304 2.42 1.012 4.287-.023.143-.047.288-.077.437-.983 5.05-4.349 6.797-8.647 6.797h-2.19c-.524 0-.968.382-1.05.9l-1.12 7.106zm14.146-14.42a3.35 3.35 0 0 0-.607-.541c-.013.076-.026.175-.041.254-.93 4.778-4.005 7.201-9.138 7.201h-2.19a.563.563 0 0 0-.556.479l-1.187 7.527h-.506l-.24 1.516a.56.56 0 0 0 .554.647h3.882c.46 0 .85-.334.922-.788.06-.26.76-4.852.816-5.09a.932.932 0 0 1 .923-.788h.58c3.76 0 6.705-1.528 7.565-5.946.36-1.847.174-3.388-.777-4.471z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  ),\n  spinner: (props: IconProps) => (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      {...props}\n    >\n      <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n    </svg>\n  ),\n}\n"
  },
  {
    "path": "components/page-header.tsx",
    "content": "import { cn } from \"../lib/utils\"\n\nfunction PageHeader({\n  className,\n  children,\n  ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n  return (\n    <section\n      className={cn(\n        \"mx-auto flex max-w-[800px] flex-col items-center gap-2 py-8 md:py-12 md:pb-8 lg:py-18 lg:pb-16\",\n        className\n      )}\n      {...props}\n    >\n      {children}\n    </section>\n  )\n}\n\nfunction PageHeaderNotifier({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLHeadingElement>) {\n  return (\n    <h1\n      className={cn(\n        \"text-center text-xs font-semibold leading-tight md:text-sm lg:leading-[1.1] min-w-fit backdrop-blur-[2px] p-2 rounded mb-2\",\n        className\n      )}\n      style={{\n        background: \"rgba(99, 86, 36, 0.1)\",\n      }}\n      {...props}\n    />\n  )\n}\n\nfunction PageHeaderHeading({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLHeadingElement>) {\n  return (\n    <h1\n      className={cn(\n        \"text-center text-3xl font-bold leading-tight tracking-tighter md:text-6xl lg:leading-[1.1] max-w-[330px] md:min-w-[750px] \",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction PageHeaderDescription({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLParagraphElement>) {\n  return (\n    <p\n      className={cn(\n        \"max-w-[750px] text-center text-base text-muted-foreground sm:text-lg text-pretty\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction PageActions({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n  return (\n    <div\n      className={cn(\n        \"flex w-full items-center justify-center space-x-4 py-4 md:pb-10\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  PageHeader,\n  PageHeaderNotifier,\n  PageHeaderHeading,\n  PageHeaderDescription,\n  PageActions,\n}\n"
  },
  {
    "path": "components/site-footer.tsx",
    "content": "import { siteConfig } from \"../config/site\"\n\nexport function SiteFooter() {\n  return (\n    <footer className=\"py-6 md:px-8 md:py-0\">\n      <div className=\"container flex flex-col items-center justify-between gap-4 md:h-24 md:flex-row\">\n        <p className=\"text-balance text-center text-sm leading-loose text-muted-foreground md:text-left\">\n          Built by{\" \"}\n          <a\n            href={siteConfig.links.twitter}\n            target=\"_blank\"\n            rel=\"noreferrer\"\n            className=\"font-medium underline underline-offset-4\"\n          >\n            GurbaazNandra\n          </a>\n          , website inspired from{\" \"}\n          <a\n            href=\"https://input-otp.rodz.dev/\"\n            target=\"_blank\"\n            rel=\"noreferrer\"\n            className=\"font-medium underline underline-offset-4\"\n          >\n            rodz\n          </a>\n          . The source code is available on{\" \"}\n          <a\n            href={siteConfig.links.github}\n            target=\"_blank\"\n            rel=\"noreferrer\"\n            className=\"font-medium underline underline-offset-4\"\n          >\n            GitHub\n          </a>\n          .\n        </p>\n      </div>\n    </footer>\n  )\n}\n"
  },
  {
    "path": "components/site-header.tsx",
    "content": "import Link from \"next/link\"\n\nimport { siteConfig } from \"../config/site\"\nimport { cn } from \"../lib/utils\"\nimport { buttonVariants } from \"./ui/button\"\nimport { Icons } from \"./icons\"\n\nexport function SiteHeader() {\n  return (\n    <header className=\"sticky top-0 z-50 w-full border-b border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60\">\n      <div className=\"container flex h-14 max-w-screen-2xl items-center\">\n        <div className=\"flex flex-1 items-center justify-between space-x-2 md:justify-end\">\n          <nav className=\"flex items-center\">\n            <Link\n              href={siteConfig.links.github}\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              <div\n                className={cn(\n                  buttonVariants({\n                    variant: \"ghost\",\n                  }),\n                  \"w-9 px-0\"\n                )}\n              >\n                <Icons.gitHub className=\"h-4 w-4\" />\n                <span className=\"sr-only\">GitHub</span>\n              </div>\n            </Link>\n            <Link\n              href={siteConfig.links.twitter}\n              target=\"_blank\"\n              rel=\"noreferrer\"\n            >\n              <div\n                className={cn(\n                  buttonVariants({\n                    variant: \"ghost\",\n                  }),\n                  \"w-9 px-0\"\n                )}\n              >\n                <Icons.twitter className=\"h-3 w-3 fill-current\" />\n                <span className=\"sr-only\">Twitter</span>\n              </div>\n            </Link>\n          </nav>\n        </div>\n      </div>\n    </header>\n  )\n}\n"
  },
  {
    "path": "components/ui/button.tsx",
    "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n  \"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n  {\n    variants: {\n      variant: {\n        default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n        destructive:\n          \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n        outline:\n          \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n        secondary:\n          \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n        ghost: \"hover:bg-accent hover:text-accent-foreground\",\n        link: \"text-primary underline-offset-4 hover:underline\",\n      },\n      size: {\n        default: \"h-10 px-4 py-2\",\n        sm: \"h-9 rounded-md px-3\",\n        lg: \"h-11 rounded-md px-8\",\n        icon: \"h-10 w-10\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n      size: \"default\",\n    },\n  }\n)\n\nexport interface ButtonProps\n  extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n    VariantProps<typeof buttonVariants> {\n  asChild?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n  ({ className, variant, size, asChild = false, ...props }, ref) => {\n    const Comp = asChild ? Slot : \"button\"\n    return (\n      <Comp\n        className={cn(buttonVariants({ variant, size, className }))}\n        ref={ref}\n        {...props}\n      />\n    )\n  }\n)\nButton.displayName = \"Button\"\n\nexport { Button, buttonVariants }\n"
  },
  {
    "path": "components/ui/calendar-heatmap.tsx",
    "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronLeft, ChevronRight } from \"lucide-react\"\nimport { DayPicker } from \"react-day-picker\"\n\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants } from \"@/components/ui/button\"\n\n// type utilities\ntype UnionKeys<T> = T extends T ? keyof T : never\ntype Expand<T> = T extends T ? { [K in keyof T]: T[K] } : never\ntype OneOf<T extends {}[]> = {\n  [K in keyof T]: Expand<\n    T[K] & Partial<Record<Exclude<UnionKeys<T[number]>, keyof T[K]>, never>>\n  >\n}[number]\n\n// types\nexport type Classname = string\nexport type WeightedDateEntry = {\n  date: Date\n  weight: number\n}\n\ninterface IDatesPerVariant {\n  datesPerVariant: Date[][]\n}\ninterface IWeightedDatesEntry {\n  weightedDates: WeightedDateEntry[]\n}\n\ntype VariantDatesInput = OneOf<[IDatesPerVariant, IWeightedDatesEntry]>\n\nexport type CalendarProps = React.ComponentProps<typeof DayPicker> & {\n  variantClassnames: Classname[]\n} & VariantDatesInput\n\n/// utlity functions\nfunction useModifers(\n  variantClassnames: Classname[],\n  datesPerVariant: Date[][]\n): [Record<string, Date[]>, Record<string, string>] {\n  const noOfVariants = variantClassnames.length\n\n  const variantLabels = [...Array(noOfVariants)].map(\n    (_, idx) => `__variant${idx}`\n  )\n\n  const modifiers = variantLabels.reduce((acc, key, index) => {\n    acc[key] = datesPerVariant[index]\n    return acc\n  }, {} as Record<string, Date[]>)\n\n  const modifiersClassNames = variantLabels.reduce((acc, key, index) => {\n    acc[key] = variantClassnames[index]\n    return acc\n  }, {} as Record<string, string>)\n\n  return [modifiers, modifiersClassNames]\n}\n\nfunction categorizeDatesPerVariant(\n  weightedDates: WeightedDateEntry[],\n  noOfVariants: number\n) {\n  const sortedEntries = weightedDates.sort((a, b) => a.weight - b.weight)\n\n  const categorizedRecord = [...Array(noOfVariants)].map(() => [] as Date[])\n\n  const minNumber = sortedEntries[0].weight\n  const maxNumber = sortedEntries[sortedEntries.length - 1].weight\n  const range = minNumber == maxNumber ? 1 : (maxNumber - minNumber) / noOfVariants;\n\n  sortedEntries.forEach((entry) => {\n    const category = Math.min(\n      Math.floor((entry.weight - minNumber) / range),\n      noOfVariants - 1\n    )\n    categorizedRecord[category].push(entry.date)\n  })\n\n  return categorizedRecord\n}\n\nfunction CalendarHeatmap({\n  variantClassnames,\n  datesPerVariant,\n  weightedDates,\n  className,\n  classNames,\n  showOutsideDays = true,\n  ...props\n}: CalendarProps) {\n  const noOfVariants = variantClassnames.length\n\n  weightedDates = weightedDates ?? []\n  datesPerVariant =\n    datesPerVariant ?? categorizeDatesPerVariant(weightedDates, noOfVariants)\n\n  const [modifiers, modifiersClassNames] = useModifers(\n    variantClassnames,\n    datesPerVariant\n  )\n\n  return (\n    <DayPicker\n      modifiers={modifiers}\n      modifiersClassNames={modifiersClassNames}\n      showOutsideDays={showOutsideDays}\n      className={cn(\"p-3\", className)}\n      classNames={{\n        months: \"flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0\",\n        month: \"space-y-4\",\n        caption: \"flex justify-center pt-1 relative items-center\",\n        caption_label: \"text-sm font-medium\",\n        nav: \"space-x-1 flex items-center\",\n        nav_button: cn(\n          buttonVariants({ variant: \"outline\" }),\n          \"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100\"\n        ),\n        nav_button_previous: \"absolute left-1\",\n        nav_button_next: \"absolute right-1\",\n        table: \"w-full border-collapse space-y-1\",\n        head_row: \"flex\",\n        head_cell:\n          \"text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]\",\n        row: \"flex w-full mt-2\",\n        cell: \"h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20\",\n        day: cn(\n          buttonVariants({ variant: \"ghost\" }),\n          \"h-9 w-9 p-0 font-normal aria-selected:opacity-100\"\n        ),\n        day_range_end: \"day-range-end\",\n        // day_selected:\n        //   \"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground\",\n        day_today: \"bg-accent text-accent-foreground\",\n        day_outside:\n          \"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30\",\n        day_disabled: \"text-muted-foreground opacity-50\",\n        day_range_middle:\n          \"aria-selected:bg-accent aria-selected:text-accent-foreground\",\n        day_hidden: \"invisible\",\n        ...classNames,\n      }}\n      components={{\n        IconLeft: ({ ...props }) => <ChevronLeft className=\"h-4 w-4\" />,\n        IconRight: ({ ...props }) => <ChevronRight className=\"h-4 w-4\" />,\n      }}\n      {...props}\n    />\n  )\n}\nCalendarHeatmap.displayName = \"CalendarHeatmap\"\n\nexport { CalendarHeatmap }\n"
  },
  {
    "path": "components/ui/dropdown-menu.tsx",
    "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\"\nimport { Check, ChevronRight, Circle } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst DropdownMenu = DropdownMenuPrimitive.Root\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger\n\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal\n\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub\n\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n    inset?: boolean\n  }\n>(({ className, inset, children, ...props }, ref) => (\n  <DropdownMenuPrimitive.SubTrigger\n    ref={ref}\n    className={cn(\n      \"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent\",\n      inset && \"pl-8\",\n      className\n    )}\n    {...props}\n  >\n    {children}\n    <ChevronRight className=\"ml-auto h-4 w-4\" />\n  </DropdownMenuPrimitive.SubTrigger>\n))\nDropdownMenuSubTrigger.displayName =\n  DropdownMenuPrimitive.SubTrigger.displayName\n\nconst DropdownMenuSubContent = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n  <DropdownMenuPrimitive.SubContent\n    ref={ref}\n    className={cn(\n      \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n      className\n    )}\n    {...props}\n  />\n))\nDropdownMenuSubContent.displayName =\n  DropdownMenuPrimitive.SubContent.displayName\n\nconst DropdownMenuContent = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n  <DropdownMenuPrimitive.Portal>\n    <DropdownMenuPrimitive.Content\n      ref={ref}\n      sideOffset={sideOffset}\n      className={cn(\n        \"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n        className\n      )}\n      {...props}\n    />\n  </DropdownMenuPrimitive.Portal>\n))\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName\n\nconst DropdownMenuItem = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n    inset?: boolean\n  }\n>(({ className, inset, ...props }, ref) => (\n  <DropdownMenuPrimitive.Item\n    ref={ref}\n    className={cn(\n      \"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n      inset && \"pl-8\",\n      className\n    )}\n    {...props}\n  />\n))\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n  <DropdownMenuPrimitive.CheckboxItem\n    ref={ref}\n    className={cn(\n      \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n      className\n    )}\n    checked={checked}\n    {...props}\n  >\n    <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n      <DropdownMenuPrimitive.ItemIndicator>\n        <Check className=\"h-4 w-4\" />\n      </DropdownMenuPrimitive.ItemIndicator>\n    </span>\n    {children}\n  </DropdownMenuPrimitive.CheckboxItem>\n))\nDropdownMenuCheckboxItem.displayName =\n  DropdownMenuPrimitive.CheckboxItem.displayName\n\nconst DropdownMenuRadioItem = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n  <DropdownMenuPrimitive.RadioItem\n    ref={ref}\n    className={cn(\n      \"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n      className\n    )}\n    {...props}\n  >\n    <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n      <DropdownMenuPrimitive.ItemIndicator>\n        <Circle className=\"h-2 w-2 fill-current\" />\n      </DropdownMenuPrimitive.ItemIndicator>\n    </span>\n    {children}\n  </DropdownMenuPrimitive.RadioItem>\n))\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName\n\nconst DropdownMenuLabel = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n    inset?: boolean\n  }\n>(({ className, inset, ...props }, ref) => (\n  <DropdownMenuPrimitive.Label\n    ref={ref}\n    className={cn(\n      \"px-2 py-1.5 text-sm font-semibold\",\n      inset && \"pl-8\",\n      className\n    )}\n    {...props}\n  />\n))\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName\n\nconst DropdownMenuSeparator = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n  <DropdownMenuPrimitive.Separator\n    ref={ref}\n    className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\n    {...props}\n  />\n))\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName\n\nconst DropdownMenuShortcut = ({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n  return (\n    <span\n      className={cn(\"ml-auto text-xs tracking-widest opacity-60\", className)}\n      {...props}\n    />\n  )\n}\nDropdownMenuShortcut.displayName = \"DropdownMenuShortcut\"\n\nexport {\n  DropdownMenu,\n  DropdownMenuTrigger,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuCheckboxItem,\n  DropdownMenuRadioItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuGroup,\n  DropdownMenuPortal,\n  DropdownMenuSub,\n  DropdownMenuSubContent,\n  DropdownMenuSubTrigger,\n  DropdownMenuRadioGroup,\n}\n"
  },
  {
    "path": "components/ui/select.tsx",
    "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as SelectPrimitive from \"@radix-ui/react-select\"\nimport { Check, ChevronDown, ChevronUp } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Select = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Trigger>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n  <SelectPrimitive.Trigger\n    ref={ref}\n    className={cn(\n      \"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1\",\n      className\n    )}\n    {...props}\n  >\n    {children}\n    <SelectPrimitive.Icon asChild>\n      <ChevronDown className=\"h-4 w-4 opacity-50\" />\n    </SelectPrimitive.Icon>\n  </SelectPrimitive.Trigger>\n))\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\nconst SelectScrollUpButton = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.ScrollUpButton\n    ref={ref}\n    className={cn(\n      \"flex cursor-default items-center justify-center py-1\",\n      className\n    )}\n    {...props}\n  >\n    <ChevronUp className=\"h-4 w-4\" />\n  </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\nconst SelectScrollDownButton = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.ScrollDownButton\n    ref={ref}\n    className={cn(\n      \"flex cursor-default items-center justify-center py-1\",\n      className\n    )}\n    {...props}\n  >\n    <ChevronDown className=\"h-4 w-4\" />\n  </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName =\n  SelectPrimitive.ScrollDownButton.displayName\n\nconst SelectContent = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = \"popper\", ...props }, ref) => (\n  <SelectPrimitive.Portal>\n    <SelectPrimitive.Content\n      ref={ref}\n      className={cn(\n        \"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2\",\n        position === \"popper\" &&\n          \"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1\",\n        className\n      )}\n      position={position}\n      {...props}\n    >\n      <SelectScrollUpButton />\n      <SelectPrimitive.Viewport\n        className={cn(\n          \"p-1\",\n          position === \"popper\" &&\n            \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]\"\n        )}\n      >\n        {children}\n      </SelectPrimitive.Viewport>\n      <SelectScrollDownButton />\n    </SelectPrimitive.Content>\n  </SelectPrimitive.Portal>\n))\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\nconst SelectLabel = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Label>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.Label\n    ref={ref}\n    className={cn(\"py-1.5 pl-8 pr-2 text-sm font-semibold\", className)}\n    {...props}\n  />\n))\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\nconst SelectItem = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Item>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n  <SelectPrimitive.Item\n    ref={ref}\n    className={cn(\n      \"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n      className\n    )}\n    {...props}\n  >\n    <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n      <SelectPrimitive.ItemIndicator>\n        <Check className=\"h-4 w-4\" />\n      </SelectPrimitive.ItemIndicator>\n    </span>\n\n    <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n  </SelectPrimitive.Item>\n))\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\nconst SelectSeparator = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Separator>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.Separator\n    ref={ref}\n    className={cn(\"-mx-1 my-1 h-px bg-muted\", className)}\n    {...props}\n  />\n))\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport {\n  Select,\n  SelectGroup,\n  SelectValue,\n  SelectTrigger,\n  SelectContent,\n  SelectLabel,\n  SelectItem,\n  SelectSeparator,\n  SelectScrollUpButton,\n  SelectScrollDownButton,\n}\n"
  },
  {
    "path": "components/ui/sonner.tsx",
    "content": "\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner } from \"sonner\"\n\ntype ToasterProps = React.ComponentProps<typeof Sonner>\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n  const { theme = \"system\" } = useTheme()\n\n  return (\n    <Sonner\n      theme={theme as ToasterProps[\"theme\"]}\n      className=\"toaster group\"\n      toastOptions={{\n        classNames: {\n          toast:\n            \"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg\",\n          description: \"group-[.toast]:text-muted-foreground\",\n          actionButton:\n            \"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground\",\n          cancelButton:\n            \"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground\",\n        },\n      }}\n      {...props}\n    />\n  )\n}\n\nexport { Toaster }\n"
  },
  {
    "path": "components.json",
    "content": "{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"default\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"tailwind.config.ts\",\n    \"css\": \"app/globals.css\",\n    \"baseColor\": \"slate\",\n    \"cssVariables\": true,\n    \"prefix\": \"\"\n  },\n  \"aliases\": {\n    \"components\": \"@/components\",\n    \"utils\": \"@/lib/utils\"\n  }\n}"
  },
  {
    "path": "config/site.ts",
    "content": "export const siteConfig = {\n  title: \"Shadcn Calendar Heatmap\",\n  name: \"gurbaaz27/shadcn-calendar-heatmap\",\n  url: \"https://shadcn-calendar-heatmap.vercel.app\",\n  ogImage: \"https://shadcn-calendar-heatmap.vercel.app/og.png\",\n  description:\n    \"Accessible. Unstyled. Customizable. Open Source. Build your own calendar heatmap effortlessly.\",\n  links: {\n    twitter: \"https://x.com/GurbaazNandra\",\n    github: \"https://github.com/gurbaaz27/shadcn-calendar-heatmap\",\n  },\n}\nexport type SiteConfig = typeof siteConfig\n"
  },
  {
    "path": "lib/utils.ts",
    "content": "import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs))\n}\n\nexport function randomDate(start: Date, end: Date) {\n  return new Date(\n    start.getTime() + Math.random() * (end.getTime() - start.getTime())\n  )\n}\n\nexport function currentMonthFirstDate() {\n  const date = new Date()\n  return new Date(date.getFullYear(), date.getMonth(), 1)\n}\n\nexport function currentMonthLastDate(month: number = 1) {\n  const date = new Date()\n  return new Date(date.getFullYear(), date.getMonth() + month, 0)\n}\n"
  },
  {
    "path": "next.config.mjs",
    "content": "/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nexport default nextConfig;\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"shadcn-calendar-heatmap\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"next dev\",\n    \"build\": \"next build\",\n    \"start\": \"next start\",\n    \"lint\": \"next lint\"\n  },\n  \"dependencies\": {\n    \"@radix-ui/react-dropdown-menu\": \"^2.1.1\",\n    \"@radix-ui/react-icons\": \"^1.3.0\",\n    \"@radix-ui/react-select\": \"^2.1.1\",\n    \"@radix-ui/react-slot\": \"^1.1.0\",\n    \"class-variance-authority\": \"^0.7.0\",\n    \"clsx\": \"^2.1.1\",\n    \"date-fns\": \"^3.6.0\",\n    \"geist\": \"^1.3.0\",\n    \"lucide-react\": \"^0.396.0\",\n    \"next\": \"14.2.4\",\n    \"next-themes\": \"^0.3.0\",\n    \"react\": \"^18\",\n    \"react-day-picker\": \"^8.10.1\",\n    \"react-dom\": \"^18\",\n    \"rehype-pretty-code\": \"^0.13.2\",\n    \"rehype-stringify\": \"^10.0.0\",\n    \"remark-parse\": \"^11.0.0\",\n    \"remark-rehype\": \"^11.1.0\",\n    \"sonner\": \"^1.5.0\",\n    \"tailwind-merge\": \"^2.3.0\",\n    \"tailwindcss-animate\": \"^1.0.7\",\n    \"unified\": \"^11.0.5\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^5\",\n    \"@types/node\": \"^20\",\n    \"@types/react\": \"^18\",\n    \"@types/react-dom\": \"^18\",\n    \"postcss\": \"^8\",\n    \"tailwindcss\": \"^3.4.1\",\n    \"eslint\": \"^8\",\n    \"eslint-config-next\": \"14.2.4\"\n  },\n  \"packageManager\": \"yarn@1.22.21+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72\"\n}\n"
  },
  {
    "path": "postcss.config.mjs",
    "content": "/** @type {import('postcss-load-config').Config} */\nconst config = {\n  plugins: {\n    tailwindcss: {},\n  },\n};\n\nexport default config;\n"
  },
  {
    "path": "public/llms.txt",
    "content": "# shadcn-calendar-heatmap\n\n> A customizable calendar heatmap component built on top of react-day-picker, following shadcn/ui patterns. Accessible, unstyled by default, and fully customizable with Tailwind CSS.\n\n## Overview\n\nshadcn-calendar-heatmap is a React component that transforms the DayPicker calendar into a heatmap visualization. It allows you to display dates with varying intensities using custom color variants - perfect for GitHub contribution graphs, temperature heatmaps, activity tracking, and more.\n\n## Installation\n\nThe component is designed to be copied directly into your project following the shadcn/ui philosophy. Copy the component from:\nhttps://github.com/gurbaaz27/shadcn-calendar-heatmap/blob/main/components/ui/calendar-heatmap.tsx\n\n### Dependencies\n\n- react-day-picker (^8.10.1)\n- tailwind-merge\n- class-variance-authority\n- lucide-react (for icons)\n\n## Component API\n\n### CalendarHeatmap Props\n\nThe component extends all props from `react-day-picker`'s DayPicker, plus:\n\n| Prop | Type | Required | Description |\n|------|------|----------|-------------|\n| `variantClassnames` | `string[]` | Yes | Array of Tailwind CSS classes for each intensity level |\n| `datesPerVariant` | `Date[][]` | One of these | 2D array where each inner array contains dates for that variant |\n| `weightedDates` | `WeightedDateEntry[]` | One of these | Array of `{ date: Date, weight: number }` objects |\n| `numberOfMonths` | `number` | No | Number of months to display (default: 1) |\n| `showOutsideDays` | `boolean` | No | Show days from adjacent months (default: true) |\n\n**Note:** You must provide either `datesPerVariant` OR `weightedDates`, not both.\n\n### WeightedDateEntry Type\n\n```typescript\ntype WeightedDateEntry = {\n  date: Date\n  weight: number\n}\n```\n\n## Usage Examples\n\n### Basic GitHub-style Contribution Graph\n\n```tsx\nimport { CalendarHeatmap } from \"@/components/ui/calendar-heatmap\"\n\n<CalendarHeatmap\n  variantClassnames={[\n    \"text-white hover:text-white bg-green-400 hover:bg-green-400\",\n    \"text-white hover:text-white bg-green-500 hover:bg-green-500\",\n    \"text-white hover:text-white bg-green-700 hover:bg-green-700\",\n  ]}\n  datesPerVariant={[\n    [new Date('Jan 1, 2024'), new Date('Jan 15, 2024')],  // Low intensity\n    [new Date('Jun 12, 2024'), new Date('July 1, 2024')], // Medium intensity\n    [new Date('Jan 19, 2024'), new Date('Apr 14, 2024')], // High intensity\n  ]}\n/>\n```\n\n### Using Weighted Dates (Auto-categorization)\n\nWhen you have numeric data associated with dates, use `weightedDates`. The component automatically categorizes dates into variants based on their weights:\n\n```tsx\n<CalendarHeatmap\n  variantClassnames={[\n    \"text-white hover:text-white bg-blue-300 hover:bg-blue-300\",\n    \"text-white hover:text-white bg-green-500 hover:bg-green-500\",\n    \"text-white hover:text-white bg-amber-400 hover:bg-amber-400\",\n    \"text-white hover:text-white bg-red-700 hover:bg-red-700\",\n  ]}\n  weightedDates={[\n    { date: new Date('Jan 1, 2024'), weight: 2 },\n    { date: new Date('Jan 15, 2024'), weight: 1.5 },\n    { date: new Date('Jun 12, 2024'), weight: 8 },\n    { date: new Date('July 1, 2024'), weight: 5 },\n    { date: new Date('Jan 19, 2024'), weight: 6 },\n    { date: new Date('Apr 19, 2024'), weight: 13.5 },\n  ]}\n/>\n```\n\n### Multi-month Display\n\n```tsx\n<CalendarHeatmap\n  numberOfMonths={3}\n  variantClassnames={[\n    \"text-white hover:text-white bg-green-400 hover:bg-green-400\",\n    \"text-white hover:text-white bg-green-500 hover:bg-green-500\",\n    \"text-white hover:text-white bg-green-700 hover:bg-green-700\",\n  ]}\n  datesPerVariant={[\n    [/* dates for variant 0 */],\n    [/* dates for variant 1 */],\n    [/* dates for variant 2 */],\n  ]}\n/>\n```\n\n### Rainbow Variant Example\n\n```tsx\nconst Rainbow = [\n  \"text-white hover:text-white bg-violet-400 hover:bg-violet-400\",\n  \"text-white hover:text-white bg-indigo-400 hover:bg-indigo-400\",\n  \"text-white hover:text-white bg-blue-400 hover:bg-blue-400\",\n  \"text-white hover:text-white bg-green-400 hover:bg-green-400\",\n  \"text-white hover:text-white bg-yellow-400 hover:bg-yellow-400\",\n  \"text-white hover:text-white bg-orange-400 hover:bg-orange-400\",\n  \"text-white hover:text-white bg-red-400 hover:bg-red-400\",\n]\n\n<CalendarHeatmap\n  numberOfMonths={2}\n  variantClassnames={Rainbow}\n  datesPerVariant={rainbowDates}\n/>\n```\n\n## How It Works\n\n1. **Variant Classes**: Each string in `variantClassnames` represents a color/style intensity level. The component creates DayPicker modifiers for each variant.\n\n2. **Date Mapping**: \n   - With `datesPerVariant`: Dates in the first array get the first variant class, second array gets second class, etc.\n   - With `weightedDates`: The component sorts dates by weight, divides the range into equal segments based on the number of variants, and assigns each date to its corresponding variant.\n\n3. **Styling**: The component uses Tailwind CSS classes. Include both normal and hover states in your variant classes for consistent interaction feedback.\n\n## Customization\n\n### Custom Styling\n\nOverride default calendar styles via the `classNames` prop:\n\n```tsx\n<CalendarHeatmap\n  variantClassnames={[...]}\n  datesPerVariant={[...]}\n  classNames={{\n    months: \"flex flex-col\",\n    month: \"space-y-2\",\n    caption: \"text-lg font-bold\",\n    // ... other DayPicker classNames\n  }}\n/>\n```\n\n### Additional Props\n\nSince the component extends DayPicker, you can use any DayPicker prop:\n\n```tsx\n<CalendarHeatmap\n  variantClassnames={[...]}\n  datesPerVariant={[...]}\n  fromDate={new Date('2024-01-01')}\n  toDate={new Date('2024-12-31')}\n  disabled={[new Date('2024-07-04')]}\n  onDayClick={(day) => console.log(day)}\n/>\n```\n\n## Links\n\n- Demo: https://shadcn-calendar-heatmap.vercel.app\n- GitHub: https://github.com/gurbaaz27/shadcn-calendar-heatmap\n- Component Source: https://github.com/gurbaaz27/shadcn-calendar-heatmap/blob/main/components/ui/calendar-heatmap.tsx\n\n## License\n\nMIT\n\n"
  },
  {
    "path": "tailwind.config.ts",
    "content": "import type { Config } from \"tailwindcss\"\n\nconst config = {\n  darkMode: [\"class\"],\n  content: [\n    \"./pages/**/*.{ts,tsx}\",\n    \"./components/**/*.{ts,tsx}\",\n    \"./app/**/*.{ts,tsx}\",\n    \"./src/**/*.{ts,tsx}\",\n  ],\n  prefix: \"\",\n  theme: {\n    container: {\n      center: true,\n      padding: \"2rem\",\n      screens: {\n        \"2xl\": \"1400px\",\n      },\n    },\n    extend: {\n      colors: {\n        border: \"hsl(var(--border))\",\n        input: \"hsl(var(--input))\",\n        ring: \"hsl(var(--ring))\",\n        background: \"hsl(var(--background))\",\n        foreground: \"hsl(var(--foreground))\",\n        primary: {\n          DEFAULT: \"hsl(var(--primary))\",\n          foreground: \"hsl(var(--primary-foreground))\",\n        },\n        secondary: {\n          DEFAULT: \"hsl(var(--secondary))\",\n          foreground: \"hsl(var(--secondary-foreground))\",\n        },\n        destructive: {\n          DEFAULT: \"hsl(var(--destructive))\",\n          foreground: \"hsl(var(--destructive-foreground))\",\n        },\n        muted: {\n          DEFAULT: \"hsl(var(--muted))\",\n          foreground: \"hsl(var(--muted-foreground))\",\n        },\n        accent: {\n          DEFAULT: \"hsl(var(--accent))\",\n          foreground: \"hsl(var(--accent-foreground))\",\n        },\n        popover: {\n          DEFAULT: \"hsl(var(--popover))\",\n          foreground: \"hsl(var(--popover-foreground))\",\n        },\n        card: {\n          DEFAULT: \"hsl(var(--card))\",\n          foreground: \"hsl(var(--card-foreground))\",\n        },\n      },\n      borderRadius: {\n        lg: \"var(--radius)\",\n        md: \"calc(var(--radius) - 2px)\",\n        sm: \"calc(var(--radius) - 4px)\",\n      },\n      keyframes: {\n        \"accordion-down\": {\n          from: { height: \"0\" },\n          to: { height: \"var(--radix-accordion-content-height)\" },\n        },\n        \"accordion-up\": {\n          from: { height: \"var(--radix-accordion-content-height)\" },\n          to: { height: \"0\" },\n        },\n        \"fade-in\": {\n          from: {\n            opacity: \"0\",\n          },\n          to: { opacity: \"1\" },\n        },\n        \"fade-up\": {\n          from: {\n            opacity: \"0\",\n            transform: \"translateY(var(--fade-distance, .25rem))\",\n          },\n          to: { opacity: \"1\", transform: \"translateY(0)\" },\n        },\n      },\n      animation: {\n        \"accordion-down\": \"accordion-down 0.2s ease-out\",\n        \"accordion-up\": \"accordion-up 0.2s ease-out\",\n        \"fade-in\": \"fade-in 0.3s ease-out forwards\",\n        \"fade-up\": \"fade-up 1s ease-out forwards\",\n      },\n    },\n  },\n  plugins: [require(\"tailwindcss-animate\")],\n} satisfies Config\n\nexport default config\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"preserve\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ],\n    \"paths\": {\n      \"@/*\": [\"./*\"]\n    }\n  },\n  \"include\": [\"next-env.d.ts\", \"**/*.ts\", \"**/*.tsx\", \".next/types/**/*.ts\"],\n  \"exclude\": [\"node_modules\"]\n}\n"
  }
]