{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "date-picker",
  "type": "registry:ui",
  "description": "Select a date from a calendar popover.",
  "dependencies": [
    "@base-ui/react",
    "lucide-react"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "components/ui/date-picker.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Popover as BasePopover } from \"@base-ui/react/popover\"\nimport { ChevronLeft, ChevronRight, Calendar } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\nconst DAYS = [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"] as const\n\nfunction getDaysInMonth(year: number, month: number) {\n    return new Date(year, month + 1, 0).getDate()\n}\n\nfunction getFirstDayOfMonth(year: number, month: number) {\n    return new Date(year, month, 1).getDay()\n}\n\nfunction formatDate(date: Date) {\n    return date.toLocaleDateString(\"en-US\", {\n        month: \"short\",\n        day: \"numeric\",\n        year: \"numeric\",\n    })\n}\n\nfunction getMonthName(month: number) {\n    return new Date(2000, month).toLocaleDateString(\"en-US\", { month: \"long\" })\n}\n\nfunction isSameDay(a: Date | null, b: Date | null) {\n    if (!a || !b) return false\n    return (\n        a.getFullYear() === b.getFullYear() &&\n        a.getMonth() === b.getMonth() &&\n        a.getDate() === b.getDate()\n    )\n}\n\nfunction isToday(date: Date) {\n    return isSameDay(date, new Date())\n}\n\ninterface DatePickerProps {\n    value?: Date | null\n    onChange?: (date: Date | null) => void\n    placeholder?: string\n    disabled?: boolean\n    className?: string\n}\n\nfunction DatePicker({\n    value = null,\n    onChange,\n    placeholder = \"Select date\",\n    disabled = false,\n    className,\n}: DatePickerProps) {\n    const [open, setOpen] = React.useState(false)\n    const [selectedDate, setSelectedDate] = React.useState<Date | null>(value)\n    const [pendingDate, setPendingDate] = React.useState<Date | null>(value)\n    const [displayMonth, setDisplayMonth] = React.useState(\n        value ? value.getMonth() : new Date().getMonth()\n    )\n    const [displayYear, setDisplayYear] = React.useState(\n        value ? value.getFullYear() : new Date().getFullYear()\n    )\n\n    React.useEffect(() => {\n        setSelectedDate(value)\n        setPendingDate(value)\n    }, [value])\n\n    const daysInMonth = getDaysInMonth(displayYear, displayMonth)\n    const firstDay = getFirstDayOfMonth(displayYear, displayMonth)\n\n    const prevMonthDays = getDaysInMonth(\n        displayMonth === 0 ? displayYear - 1 : displayYear,\n        displayMonth === 0 ? 11 : displayMonth - 1\n    )\n\n    const calendarDays: { day: number; month: number; year: number; isCurrentMonth: boolean }[] = []\n\n    // Previous month trailing days\n    for (let i = firstDay - 1; i >= 0; i--) {\n        const prevMonth = displayMonth === 0 ? 11 : displayMonth - 1\n        const prevYear = displayMonth === 0 ? displayYear - 1 : displayYear\n        calendarDays.push({\n            day: prevMonthDays - i,\n            month: prevMonth,\n            year: prevYear,\n            isCurrentMonth: false,\n        })\n    }\n\n    // Current month days\n    for (let i = 1; i <= daysInMonth; i++) {\n        calendarDays.push({\n            day: i,\n            month: displayMonth,\n            year: displayYear,\n            isCurrentMonth: true,\n        })\n    }\n\n    // Next month leading days\n    const remaining = 42 - calendarDays.length\n    for (let i = 1; i <= remaining; i++) {\n        const nextMonth = displayMonth === 11 ? 0 : displayMonth + 1\n        const nextYear = displayMonth === 11 ? displayYear + 1 : displayYear\n        calendarDays.push({\n            day: i,\n            month: nextMonth,\n            year: nextYear,\n            isCurrentMonth: false,\n        })\n    }\n\n    function handlePrevMonth() {\n        if (displayMonth === 0) {\n            setDisplayMonth(11)\n            setDisplayYear(displayYear - 1)\n        } else {\n            setDisplayMonth(displayMonth - 1)\n        }\n    }\n\n    function handleNextMonth() {\n        if (displayMonth === 11) {\n            setDisplayMonth(0)\n            setDisplayYear(displayYear + 1)\n        } else {\n            setDisplayMonth(displayMonth + 1)\n        }\n    }\n\n    function handleDayClick(day: number, month: number, year: number) {\n        setPendingDate(new Date(year, month, day))\n    }\n\n    function handleApply() {\n        setSelectedDate(pendingDate)\n        onChange?.(pendingDate)\n        setOpen(false)\n    }\n\n    function handleCancel() {\n        setPendingDate(selectedDate)\n        if (selectedDate) {\n            setDisplayMonth(selectedDate.getMonth())\n            setDisplayYear(selectedDate.getFullYear())\n        }\n        setOpen(false)\n    }\n\n    return (\n        <BasePopover.Root open={open} onOpenChange={setOpen}>\n            <BasePopover.Trigger\n                disabled={disabled}\n                className={cn(\n                    \"inline-flex h-10 w-full max-w-[280px] items-center gap-2 rounded-base border-2 border-black bg-white px-3 py-2 text-sm font-medium text-black shadow-brutal transition-colors hover:bg-main/10 focus-brutal disabled:cursor-not-allowed disabled:opacity-50\",\n                    className\n                )}\n            >\n                <Calendar className=\"h-4 w-4 shrink-0 opacity-60\" />\n                <span className={cn(\"flex-1 text-left\", !selectedDate && \"text-black/50\")}>\n                    {selectedDate ? formatDate(selectedDate) : placeholder}\n                </span>\n            </BasePopover.Trigger>\n            <BasePopover.Portal>\n                <BasePopover.Positioner sideOffset={4} side=\"bottom\" align=\"start\">\n                    <BasePopover.Popup className=\"z-50 w-[300px] rounded-base border-2 border-black bg-white shadow-brutal transition-opacity data-ending-style:opacity-0 data-starting-style:opacity-0\">\n                        {/* Header */}\n                        <div className=\"flex items-center justify-between border-b-2 border-black px-3 py-2\">\n                            <button\n                                type=\"button\"\n                                onClick={handlePrevMonth}\n                                className=\"inline-flex h-7 w-7 items-center justify-center rounded-base border-2 border-black bg-white text-black transition-colors hover:bg-main/20 focus-brutal\"\n                                aria-label=\"Previous month\"\n                            >\n                                <ChevronLeft className=\"h-4 w-4\" />\n                            </button>\n                            <span className=\"text-sm font-bold text-black\">\n                                {getMonthName(displayMonth)} {displayYear}\n                            </span>\n                            <button\n                                type=\"button\"\n                                onClick={handleNextMonth}\n                                className=\"inline-flex h-7 w-7 items-center justify-center rounded-base border-2 border-black bg-white text-black transition-colors hover:bg-main/20 focus-brutal\"\n                                aria-label=\"Next month\"\n                            >\n                                <ChevronRight className=\"h-4 w-4\" />\n                            </button>\n                        </div>\n\n                        {/* Day headers */}\n                        <div className=\"grid grid-cols-7 px-2 pt-2\">\n                            {DAYS.map((day) => (\n                                <div\n                                    key={day}\n                                    className=\"flex h-8 items-center justify-center text-xs font-bold text-black/50\"\n                                >\n                                    {day}\n                                </div>\n                            ))}\n                        </div>\n\n                        {/* Calendar grid */}\n                        <div className=\"grid grid-cols-7 px-2 pb-2\">\n                            {calendarDays.map((d, i) => {\n                                const cellDate = new Date(d.year, d.month, d.day)\n                                const isSelected = isSameDay(pendingDate, cellDate)\n                                const isTodayDate = isToday(cellDate)\n\n                                return (\n                                    <button\n                                        key={i}\n                                        type=\"button\"\n                                        onClick={() => handleDayClick(d.day, d.month, d.year)}\n                                        className={cn(\n                                            \"flex h-8 w-full items-center justify-center text-sm transition-colors rounded-base\",\n                                            d.isCurrentMonth\n                                                ? \"text-black font-medium\"\n                                                : \"text-black/30\",\n                                            isSelected &&\n                                                \"bg-main border-2 border-black font-bold text-black shadow-brutal\",\n                                            !isSelected && d.isCurrentMonth && \"hover:bg-main/20\",\n                                            isTodayDate && !isSelected && \"border-2 border-black/30\"\n                                        )}\n                                    >\n                                        {d.day}\n                                    </button>\n                                )\n                            })}\n                        </div>\n\n                        {/* Footer */}\n                        <div className=\"flex items-center justify-end gap-2 border-t-2 border-black px-3 py-2\">\n                            <button\n                                type=\"button\"\n                                onClick={handleCancel}\n                                className=\"inline-flex h-8 items-center justify-center rounded-base border-2 border-black bg-white px-4 text-sm font-bold text-black transition-colors hover:bg-main/10 focus-brutal\"\n                            >\n                                Cancel\n                            </button>\n                            <button\n                                type=\"button\"\n                                onClick={handleApply}\n                                className=\"inline-flex h-8 items-center justify-center rounded-base border-2 border-black bg-black px-4 text-sm font-bold text-white transition-colors hover:bg-black/80 focus-brutal\"\n                            >\n                                Apply\n                            </button>\n                        </div>\n                    </BasePopover.Popup>\n                </BasePopover.Positioner>\n            </BasePopover.Portal>\n        </BasePopover.Root>\n    )\n}\nDatePicker.displayName = \"DatePicker\"\n\nexport { DatePicker }\nexport type { DatePickerProps }\n",
      "type": "registry:ui"
    }
  ]
}