{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "monthpicker",
  "type": "registry:ui",
  "title": "Month Picker",
  "author": "@greenkdev",
  "description": "A month picker component.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "button"
  ],
  "files": [
    {
      "path": "src/components/ui/monthpicker.tsx",
      "content": "\"use client\";\nimport * as React from \"react\";\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\nimport { buttonVariants } from \"./button\";\nimport { cn } from \"@/lib/utils\";\n\ntype Month = {\n    number: number;\n    name: string;\n};\n\nconst MONTHS: Month[][] = [\n    [\n        { number: 0, name: \"Jan\" },\n        { number: 1, name: \"Feb\" },\n        { number: 2, name: \"Mar\" },\n        { number: 3, name: \"Apr\" },\n    ],\n    [\n        { number: 4, name: \"May\" },\n        { number: 5, name: \"Jun\" },\n        { number: 6, name: \"Jul\" },\n        { number: 7, name: \"Aug\" },\n    ],\n    [\n        { number: 8, name: \"Sep\" },\n        { number: 9, name: \"Oct\" },\n        { number: 10, name: \"Nov\" },\n        { number: 11, name: \"Dec\" },\n    ],\n];\n\ntype MonthCalProps = {\n    selectedMonth?: Date;\n    onMonthSelect?: (date: Date) => void;\n    onYearForward?: () => void;\n    onYearBackward?: () => void;\n    callbacks?: {\n        yearLabel?: (year: number) => string;\n        monthLabel?: (month: Month) => string;\n    };\n    variant?: {\n        calendar?: {\n            main?: ButtonVariant;\n            selected?: ButtonVariant;\n        };\n        chevrons?: ButtonVariant;\n    };\n    minDate?: Date;\n    maxDate?: Date;\n    disabledDates?: Date[];\n};\n\ntype ButtonVariant = \"default\" | \"outline\" | \"ghost\" | \"link\" | \"destructive\" | \"secondary\" | null | undefined;\n\nfunction MonthPicker({\n    onMonthSelect,\n    selectedMonth,\n    minDate,\n    maxDate,\n    disabledDates,\n    callbacks,\n    onYearBackward,\n    onYearForward,\n    variant,\n    className,\n    ...props\n}: React.HTMLAttributes<HTMLDivElement> & MonthCalProps) {\n    return (\n        <div className={cn(\"min-w-[200px] w-[280px] p-3\", className)} {...props}>\n            <div className=\"flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0\">\n                <div className=\"space-y-4 w-full\">\n                    <MonthCal\n                        onMonthSelect={onMonthSelect}\n                        callbacks={callbacks}\n                        selectedMonth={selectedMonth}\n                        onYearBackward={onYearBackward}\n                        onYearForward={onYearForward}\n                        variant={variant}\n                        minDate={minDate}\n                        maxDate={maxDate}\n                        disabledDates={disabledDates}\n                    ></MonthCal>\n                </div>\n            </div>\n        </div>\n    );\n}\n\nfunction MonthCal({ selectedMonth, onMonthSelect, callbacks, variant, minDate, maxDate, disabledDates, onYearBackward, onYearForward }: MonthCalProps) {\n    const [year, setYear] = React.useState<number>(selectedMonth?.getFullYear() ?? new Date().getFullYear());\n    const [month, setMonth] = React.useState<number>(selectedMonth?.getMonth() ?? new Date().getMonth());\n    const [menuYear, setMenuYear] = React.useState<number>(year);\n\n    if (minDate && maxDate && minDate > maxDate) minDate = maxDate;\n\n    const disabledDatesMapped = disabledDates?.map((d) => {\n        return { year: d.getFullYear(), month: d.getMonth() };\n    });\n\n    return (\n        <>\n            <div className=\"flex justify-center pt-1 relative items-center\">\n                <div className=\"text-sm font-medium\">{callbacks?.yearLabel ? callbacks?.yearLabel(menuYear) : menuYear}</div>\n                <div className=\"space-x-1 flex items-center\">\n                    <button\n                        onClick={() => {\n                            setMenuYear(menuYear - 1);\n                            if (onYearBackward) onYearBackward();\n                        }}\n                        className={cn(buttonVariants({ variant: variant?.chevrons ?? \"outline\" }), \"inline-flex items-center justify-center h-7 w-7 p-0 absolute left-1\")}\n                    >\n                        <ChevronLeft className=\"opacity-50 h-4 w-4\" />\n                    </button>\n                    <button\n                        onClick={() => {\n                            setMenuYear(menuYear + 1);\n                            if (onYearForward) onYearForward();\n                        }}\n                        className={cn(buttonVariants({ variant: variant?.chevrons ?? \"outline\" }), \"inline-flex items-center justify-center h-7 w-7 p-0 absolute right-1\")}\n                    >\n                        <ChevronRight className=\"opacity-50 h-4 w-4\" />\n                    </button>\n                </div>\n            </div>\n            <table className=\"w-full border-collapse space-y-1\">\n                <tbody>\n                    {MONTHS.map((monthRow, a) => {\n                        return (\n                            <tr key={\"row-\" + a} className=\"flex w-full mt-2\">\n                                {monthRow.map((m) => {\n                                    return (\n                                        <td\n                                            key={m.number}\n                                            className=\"h-10 w-1/4 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                                        >\n                                            <button\n                                                onClick={() => {\n                                                    setMonth(m.number);\n                                                    setYear(menuYear);\n                                                    if (onMonthSelect) onMonthSelect(new Date(menuYear, m.number));\n                                                }}\n                                                disabled={\n                                                    (maxDate ? menuYear > maxDate?.getFullYear() || (menuYear == maxDate?.getFullYear() && m.number > maxDate.getMonth()) : false) ||\n                                                    (minDate ? menuYear < minDate?.getFullYear() || (menuYear == minDate?.getFullYear() && m.number < minDate.getMonth()) : false) ||\n                                                    (disabledDatesMapped ? disabledDatesMapped?.some((d) => d.year == menuYear && d.month == m.number) : false)\n                                                }\n                                                className={cn(\n                                                    buttonVariants({ variant: month == m.number && menuYear == year ? variant?.calendar?.selected ?? \"default\" : variant?.calendar?.main ?? \"ghost\" }),\n                                                    \"h-full w-full p-0 font-normal aria-selected:opacity-100\"\n                                                )}\n                                            >\n                                                {callbacks?.monthLabel ? callbacks.monthLabel(m) : m.name}\n                                            </button>\n                                        </td>\n                                    );\n                                })}\n                            </tr>\n                        );\n                    })}\n                </tbody>\n            </table>\n        </>\n    );\n}\n\nMonthPicker.displayName = \"MonthPicker\";\n\nexport { MonthPicker };\n",
      "type": "registry:ui"
    }
  ]
}