{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "date-picker",
  "title": "Date Picker",
  "description": "Single-date and date-range pickers with a calendar popover.",
  "dependencies": [
    "react-day-picker",
    "date-fns",
    "lucide-react"
  ],
  "registryDependencies": [
    "calendar",
    "popover",
    "button"
  ],
  "files": [
    {
      "path": "ui/date-picker.tsx",
      "content": "'use client'\n\nimport { format, isValid, parseISO } from 'date-fns'\nimport { CalendarIcon, X } from 'lucide-react'\nimport { useState } from 'react'\nimport { Button } from '@/components/ui/button'\nimport { Calendar } from '@/components/ui/calendar'\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'\nimport { toISODate } from '@/lib/date'\nimport { cn } from '@/lib/utils'\n\ninterface DatePickerProps {\n  value: string\n  onChange: (value: string) => void\n  placeholder?: string\n  disabled?: boolean\n  className?: string\n}\n\nexport function DatePicker({\n  value,\n  onChange,\n  placeholder = 'Pick a date',\n  disabled,\n  className,\n}: DatePickerProps) {\n  const [open, setOpen] = useState(false)\n  const parsed = value ? parseISO(value) : undefined\n  const date = parsed && isValid(parsed) ? parsed : undefined\n\n  const clear = () => {\n    onChange('')\n    setOpen(false)\n  }\n\n  return (\n    <Popover onOpenChange={setOpen} open={open}>\n      <div className={cn('group relative w-full', className)}>\n        <PopoverTrigger asChild>\n          <Button\n            className={cn(\n              'w-full cursor-pointer justify-start px-3 text-left font-normal',\n              !date && 'text-muted-foreground',\n            )}\n            disabled={disabled}\n            variant=\"outline\"\n          >\n            <CalendarIcon\n              className={cn(\n                'mr-2 size-4 opacity-50 transition-opacity',\n                date && !disabled && 'group-hover:opacity-0',\n              )}\n            />\n            {date ? format(date, 'PPP') : <span>{placeholder}</span>}\n          </Button>\n        </PopoverTrigger>\n\n        {date && !disabled && (\n          <button\n            aria-label=\"Clear date\"\n            className=\"absolute top-1/2 left-3 z-10 flex size-4 -translate-y-1/2 cursor-pointer items-center justify-center text-muted-foreground opacity-0 transition-opacity hover:text-destructive focus-visible:opacity-100 group-hover:opacity-100\"\n            onClick={clear}\n            type=\"button\"\n          >\n            <X className=\"size-4\" />\n          </button>\n        )}\n      </div>\n\n      <PopoverContent align=\"start\" className=\"w-auto p-0\">\n        <Calendar\n          autoFocus\n          captionLayout=\"dropdown\"\n          defaultMonth={date}\n          endMonth={new Date(new Date().getFullYear() + 1, 11)}\n          mode=\"single\"\n          onSelect={(selected) => {\n            if (selected) {\n              onChange(toISODate(selected))\n              setOpen(false)\n            }\n          }}\n          selected={date}\n          startMonth={new Date(2015, 0)}\n        />\n      </PopoverContent>\n    </Popover>\n  )\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "ui/date-range-picker.tsx",
      "content": "'use client'\n\nimport { format, parseISO } from 'date-fns'\nimport { CalendarRange, X } from 'lucide-react'\nimport { type ComponentProps, useState } from 'react'\nimport type { DateRange } from 'react-day-picker'\nimport { Button } from '@/components/ui/button'\nimport { Calendar } from '@/components/ui/calendar'\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'\nimport { toISODate } from '@/lib/date'\nimport { cn } from '@/lib/utils'\n\nexport interface DateRangeValue {\n  from: string\n  to: string\n}\n\ninterface DateRangePickerProps {\n  value: DateRangeValue | null\n  onChange: (value: DateRangeValue | null) => void\n  placeholder?: string\n  numberOfMonths?: number\n  align?: ComponentProps<typeof PopoverContent>['align']\n  triggerVariant?: ComponentProps<typeof Button>['variant']\n  triggerClassName?: string\n  formatLabel?: (value: DateRangeValue) => string\n}\n\nconst defaultFormatLabel = (value: DateRangeValue) => {\n  const from = parseISO(value.from)\n  const to = parseISO(value.to)\n  const pattern = from.getFullYear() === to.getFullYear() ? 'd MMM' : 'd MMM yyyy'\n  return `${format(from, pattern)} – ${format(to, pattern)}`\n}\n\nexport function DateRangePicker({\n  value,\n  onChange,\n  placeholder = 'Pick a range',\n  numberOfMonths = 2,\n  align = 'end',\n  triggerVariant = 'outline',\n  triggerClassName,\n  formatLabel = defaultFormatLabel,\n}: DateRangePickerProps) {\n  const [open, setOpen] = useState(false)\n  const [draft, setDraft] = useState<DateRange | undefined>()\n  const hasValue = value !== null\n\n  const handleOpenChange = (next: boolean) => {\n    if (next) {\n      setDraft(value ? { from: parseISO(value.from), to: parseISO(value.to) } : undefined)\n    }\n    setOpen(next)\n  }\n\n  const applyDraft = () => {\n    if (!(draft?.from && draft.to)) return\n    onChange({\n      from: toISODate(draft.from),\n      to: toISODate(draft.to),\n    })\n    setOpen(false)\n  }\n\n  const reset = () => {\n    setDraft(undefined)\n    onChange(null)\n    setOpen(false)\n  }\n\n  return (\n    <Popover onOpenChange={handleOpenChange} open={open}>\n      <div className=\"group relative inline-flex shrink-0\">\n        <PopoverTrigger asChild>\n          <Button\n            className={cn('cursor-pointer', triggerClassName)}\n            size=\"sm\"\n            variant={hasValue ? 'secondary' : triggerVariant}\n          >\n            <CalendarRange\n              className={cn('size-4 transition-opacity', hasValue && 'group-hover:opacity-0')}\n            />\n            {hasValue ? formatLabel(value) : placeholder}\n          </Button>\n        </PopoverTrigger>\n\n        {hasValue && (\n          <button\n            aria-label=\"Clear range\"\n            className=\"absolute top-1/2 left-3 z-10 flex size-4 -translate-y-1/2 cursor-pointer items-center justify-center text-muted-foreground opacity-0 transition-opacity hover:text-destructive focus-visible:opacity-100 group-hover:opacity-100\"\n            onClick={(event) => {\n              event.stopPropagation()\n              reset()\n            }}\n            type=\"button\"\n          >\n            <X className=\"size-4\" />\n          </button>\n        )}\n      </div>\n      <PopoverContent align={align} className=\"w-auto p-0\">\n        <Calendar\n          autoFocus\n          captionLayout=\"dropdown\"\n          defaultMonth={draft?.from}\n          endMonth={new Date(new Date().getFullYear() + 1, 11)}\n          mode=\"range\"\n          numberOfMonths={numberOfMonths}\n          onSelect={setDraft}\n          selected={draft}\n          startMonth={new Date(2015, 0)}\n        />\n        <div className=\"flex items-center justify-between gap-2 border-t p-2\">\n          <Button\n            className=\"cursor-pointer\"\n            disabled={!(hasValue || draft?.from)}\n            onClick={reset}\n            size=\"sm\"\n            variant=\"ghost\"\n          >\n            Reset\n          </Button>\n          <div className=\"flex gap-2\">\n            <Button\n              className=\"cursor-pointer\"\n              onClick={() => setOpen(false)}\n              size=\"sm\"\n              variant=\"ghost\"\n            >\n              Cancel\n            </Button>\n            <Button\n              className=\"cursor-pointer\"\n              disabled={!(draft?.from && draft.to)}\n              onClick={applyDraft}\n              size=\"sm\"\n            >\n              Apply\n            </Button>\n          </div>\n        </div>\n      </PopoverContent>\n    </Popover>\n  )\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "lib/date.ts",
      "content": "import { format } from 'date-fns'\n\nexport const toISODate = (date: Date): string => format(date, 'yyyy-MM-dd')\n",
      "type": "registry:lib"
    }
  ],
  "type": "registry:component"
}
