{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "date-picker",
  "type": "registry:ui",
  "title": "DatePicker",
  "description": "Calendar date picker and date range picker with monospace display and quick range presets.",
  "registryDependencies": [
    "https://ui.arpitbhayani.me/r/aui.json"
  ],
  "files": [
    {
      "path": "ui/date-picker.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface DateRange {\n  from?: Date;\n  to?: Date;\n}\n\nexport interface DatePickerProps {\n  value?: Date;\n  onChange: (date: Date) => void;\n  placeholder?: string;\n  className?: string;\n}\n\nexport interface DateRangePickerProps {\n  value?: DateRange;\n  onChange: (range: DateRange) => void;\n  presets?: Array<{ label: string; range: DateRange }>;\n  placeholder?: string;\n  className?: string;\n}\n\nfunction formatDate(d?: Date) {\n  if (!d) return \"\";\n  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, \"0\")}-${String(d.getDate()).padStart(2, \"0\")}`;\n}\n\nconst MONTH_NAMES = [\n  \"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\n  \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"\n];\n\nexport function DatePicker({\n  value,\n  onChange,\n  placeholder = \"Pick a date\",\n  className,\n}: DatePickerProps) {\n  const [isOpen, setIsOpen] = React.useState(false);\n  const [viewDate, setViewDate] = React.useState(() => value ? new Date(value) : new Date());\n  const ref = React.useRef<HTMLDivElement>(null);\n\n  React.useEffect(() => {\n    if (!isOpen) return;\n    const handleClick = (e: MouseEvent) => {\n      if (ref.current && !ref.current.contains(e.target as Node)) {\n        setIsOpen(false);\n      }\n    };\n    document.addEventListener(\"mousedown\", handleClick);\n    return () => document.removeEventListener(\"mousedown\", handleClick);\n  }, [isOpen]);\n\n  const year = viewDate.getFullYear();\n  const month = viewDate.getMonth();\n  const daysInMonth = new Date(year, month + 1, 0).getDate();\n  const firstDay = new Date(year, month, 1).getDay();\n\n  return (\n    <div ref={ref} className={cn(\"relative inline-block\", className)}>\n      <button\n        type=\"button\"\n        className={cn(\n          \"inline-flex h-9 items-center gap-2 rounded-md border border-input bg-background px-3 py-1 font-mono text-xs shadow-xs hover:bg-muted\",\n          isOpen && \"ring-1 ring-ring\"\n        )}\n        onClick={() => setIsOpen(!isOpen)}\n      >\n        <span>📅</span>\n        <span className={value ? \"text-foreground font-semibold\" : \"text-muted-foreground\"}>\n          {value ? formatDate(value) : placeholder}\n        </span>\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute top-full mt-1 left-0 z-50 rounded-md border border-border bg-popover p-3 shadow-md animate-in fade-in-0\">\n          <div className=\"flex items-center justify-between mb-2\">\n            <button\n              type=\"button\"\n              className=\"h-6 w-6 rounded border border-border flex items-center justify-center text-xs\"\n              onClick={() => setViewDate(new Date(year, month - 1, 1))}\n            >\n              ‹\n            </button>\n            <span className=\"font-heading text-xs font-semibold\">\n              {MONTH_NAMES[month]} {year}\n            </span>\n            <button\n              type=\"button\"\n              className=\"h-6 w-6 rounded border border-border flex items-center justify-center text-xs\"\n              onClick={() => setViewDate(new Date(year, month + 1, 1))}\n            >\n              ›\n            </button>\n          </div>\n\n          <div className=\"grid grid-cols-7 gap-1 text-center font-mono text-xs\">\n            {[\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"].map((d) => (\n              <span key={d} className=\"text-muted-foreground text-[10px] py-1\">{d}</span>\n            ))}\n            {Array.from({ length: firstDay }).map((_, i) => (\n              <span key={`empty-${i}`} />\n            ))}\n            {Array.from({ length: daysInMonth }).map((_, i) => {\n              const day = i + 1;\n              const isSelected = value && value.getFullYear() === year && value.getMonth() === month && value.getDate() === day;\n              return (\n                <button\n                  key={day}\n                  type=\"button\"\n                  className={cn(\n                    \"h-7 w-7 rounded-xs text-xs flex items-center justify-center hover:bg-accent\",\n                    isSelected && \"bg-primary text-white font-bold\"\n                  )}\n                  onClick={() => {\n                    onChange(new Date(year, month, day));\n                    setIsOpen(false);\n                  }}\n                >\n                  {day}\n                </button>\n              );\n            })}\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n\nexport function DateRangePicker({\n  value,\n  onChange,\n  presets,\n  placeholder = \"Select date range...\",\n  className,\n}: DateRangePickerProps) {\n  const [isOpen, setIsOpen] = React.useState(false);\n  const [selectingFrom, setSelectingFrom] = React.useState<Date | undefined>(value?.from);\n  const [viewDate, setViewDate] = React.useState(() => value?.from ? new Date(value.from) : new Date());\n  const ref = React.useRef<HTMLDivElement>(null);\n\n  React.useEffect(() => {\n    if (!isOpen) return;\n    const handleClick = (e: MouseEvent) => {\n      if (ref.current && !ref.current.contains(e.target as Node)) setIsOpen(false);\n    };\n    document.addEventListener(\"mousedown\", handleClick);\n    return () => document.removeEventListener(\"mousedown\", handleClick);\n  }, [isOpen]);\n\n  const year = viewDate.getFullYear();\n  const month = viewDate.getMonth();\n  const daysInMonth = new Date(year, month + 1, 0).getDate();\n  const firstDay = new Date(year, month, 1).getDay();\n\n  const handleDayClick = (day: number) => {\n    const clicked = new Date(year, month, day);\n    if (!selectingFrom || (value?.from && value?.to)) {\n      setSelectingFrom(clicked);\n      onChange({ from: clicked, to: undefined });\n    } else {\n      if (clicked < selectingFrom) {\n        onChange({ from: clicked, to: selectingFrom });\n      } else {\n        onChange({ from: selectingFrom, to: clicked });\n      }\n      setSelectingFrom(undefined);\n      setIsOpen(false);\n    }\n  };\n\n  const displayText = value?.from && value?.to\n    ? `${formatDate(value.from)} → ${formatDate(value.to)}`\n    : value?.from\n    ? `${formatDate(value.from)} → ...`\n    : placeholder;\n\n  return (\n    <div ref={ref} className={cn(\"relative inline-block\", className)}>\n      <button\n        type=\"button\"\n        className={cn(\n          \"inline-flex h-9 items-center gap-2 rounded-md border border-input bg-background px-3 py-1 font-mono text-xs shadow-xs hover:bg-muted\",\n          isOpen && \"ring-1 ring-ring\"\n        )}\n        onClick={() => setIsOpen(!isOpen)}\n      >\n        <span>📅</span>\n        <span className={value?.from ? \"text-foreground font-semibold\" : \"text-muted-foreground\"}>\n          {displayText}\n        </span>\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute top-full mt-1 left-0 z-50 rounded-md border border-border bg-popover p-3 shadow-md animate-in fade-in-0 flex gap-3\">\n          <div className=\"flex flex-col gap-1 border-r border-border pr-3\">\n            {[\n              { label: \"Today\", get: () => ({ from: new Date(), to: new Date() }) },\n              { label: \"Last 7d\", get: () => { const to = new Date(); const from = new Date(); from.setDate(to.getDate() - 7); return { from, to }; } },\n              { label: \"Last 30d\", get: () => { const to = new Date(); const from = new Date(); from.setDate(to.getDate() - 30); return { from, to }; } },\n            ].map((p) => (\n              <button\n                key={p.label}\n                type=\"button\"\n                className=\"text-left font-mono text-xs px-2 py-1 rounded hover:bg-muted text-muted-foreground hover:text-foreground\"\n                onClick={() => {\n                  onChange(p.get());\n                  setIsOpen(false);\n                }}\n              >\n                {p.label}\n              </button>\n            ))}\n          </div>\n\n          <div>\n            <div className=\"flex items-center justify-between mb-2\">\n              <button\n                type=\"button\"\n                className=\"h-6 w-6 rounded border border-border flex items-center justify-center text-xs\"\n                onClick={() => setViewDate(new Date(year, month - 1, 1))}\n              >\n                ‹\n              </button>\n              <span className=\"font-heading text-xs font-semibold\">\n                {MONTH_NAMES[month]} {year}\n              </span>\n              <button\n                type=\"button\"\n                className=\"h-6 w-6 rounded border border-border flex items-center justify-center text-xs\"\n                onClick={() => setViewDate(new Date(year, month + 1, 1))}\n              >\n                ›\n              </button>\n            </div>\n\n            <div className=\"grid grid-cols-7 gap-1 text-center font-mono text-xs\">\n              {[\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"].map((d) => (\n                <span key={d} className=\"text-muted-foreground text-[10px] py-1\">{d}</span>\n              ))}\n              {Array.from({ length: firstDay }).map((_, i) => (\n                <span key={`empty-${i}`} />\n              ))}\n              {Array.from({ length: daysInMonth }).map((_, i) => {\n                const day = i + 1;\n                const thisDate = new Date(year, month, day);\n                const isFrom = value?.from && formatDate(thisDate) === formatDate(value.from);\n                const isTo = value?.to && formatDate(thisDate) === formatDate(value.to);\n                const inRange = value?.from && value?.to && thisDate > value.from && thisDate < value.to;\n\n                return (\n                  <button\n                    key={day}\n                    type=\"button\"\n                    className={cn(\n                      \"h-7 w-7 rounded-xs text-xs flex items-center justify-center hover:bg-accent\",\n                      (isFrom || isTo) && \"bg-primary text-white font-bold\",\n                      inRange && \"bg-primary/10 text-primary\"\n                    )}\n                    onClick={() => handleDayClick(day)}\n                  >\n                    {day}\n                  </button>\n                );\n              })}\n            </div>\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n",
      "type": "registry:ui"
    }
  ]
}