{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "date-picker",
  "title": "Date Picker",
  "description": "Single-date and date-range pickers that open a calendar in a popover.",
  "dependencies": [
    "date-fns@^4.4.0",
    "lucide-react@^1.27.0",
    "react-day-picker@^10.0.1"
  ],
  "registryDependencies": [
    "@pestoui/button",
    "@pestoui/calendar",
    "@pestoui/popover",
    "@pestoui/style",
    "@pestoui/utils"
  ],
  "files": [
    {
      "path": "pestoui/ui/date-picker.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { format, isSameYear } from \"date-fns\"\nimport { CalendarIcon } from \"lucide-react\"\nimport type { DateRange } from \"react-day-picker\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { Calendar } from \"@/components/ui/calendar\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\"\n\n/* Controlled the moment the consumer passes a `value` prop. Pinned on the first\n   render so clearing a selection back to `undefined` cannot silently hand\n   control to the internal state mid-flight. */\nfunction useDateSelection<T>(\n  controlled: boolean,\n  valueProp: T | undefined,\n  defaultValue: T | undefined,\n  onValueChange: ((value: T | undefined) => void) | undefined\n) {\n  const [internal, setInternal] = React.useState<T | undefined>(defaultValue)\n\n  const setValue = React.useCallback(\n    (next: T | undefined) => {\n      if (!controlled) setInternal(next)\n      onValueChange?.(next)\n    },\n    [controlled, onValueChange]\n  )\n\n  return [controlled ? valueProp : internal, setValue] as const\n}\n\n/* Shared trigger — a raised outline pill, not a boxed field, so it reads as an\n   action. `data-empty` dims it while the placeholder is showing. */\nfunction DatePickerTrigger({\n  className,\n  empty = false,\n  variant = \"outline\",\n  size = \"default\",\n  children,\n  ...props\n}: Omit<React.ComponentProps<typeof Button>, \"asChild\"> & {\n  empty?: boolean\n}) {\n  return (\n    <Button\n      variant={variant}\n      size={size}\n      data-empty={empty}\n      className={cn(\n        \"justify-start gap-2.5 font-normal data-[empty=true]:text-muted-foreground\",\n        className\n      )}\n      {...props}\n    >\n      {/* The glyph is this trigger's whole press response: Button drops its own\n          box press under `aria-haspopup`, because the popover is positioned\n          against that box. Squeezing the icon leaves the box's measured size\n          alone. */}\n      <CalendarIcon\n        aria-hidden=\"true\"\n        className=\"text-muted-foreground transition-[scale] duration-fast ease-out-expo group-active/button:scale-(--press-squeeze) group-active/button:duration-spring-press group-active/button:ease-spring-press\"\n      />\n      <span className=\"truncate\">{children}</span>\n    </Button>\n  )\n}\n\ntype DatePickerBaseProps = Omit<\n  React.ComponentProps<typeof Button>,\n  \"align\" | \"asChild\" | \"children\" | \"defaultValue\" | \"value\"\n> & {\n  /** Where the popover lines up against the trigger. */\n  align?: React.ComponentProps<typeof PopoverContent>[\"align\"]\n  /** date-fns pattern used for the trigger label. */\n  dateFormat?: string\n  placeholder?: string\n}\n\ntype DatePickerProps = DatePickerBaseProps & {\n  defaultValue?: Date\n  onValueChange?: (value: Date | undefined) => void\n  value?: Date\n}\n\nfunction DatePicker(props: DatePickerProps) {\n  const controlled = React.useRef(\"value\" in props).current\n  const {\n    align = \"start\",\n    className,\n    dateFormat = \"MMM d, yyyy\",\n    defaultValue,\n    onValueChange,\n    placeholder = \"Pick a date\",\n    value: valueProp,\n    ...triggerProps\n  } = props\n\n  const [open, setOpen] = React.useState(false)\n  const [value, setValue] = useDateSelection<Date>(\n    controlled,\n    valueProp,\n    defaultValue,\n    onValueChange\n  )\n\n  return (\n    <Popover open={open} onOpenChange={setOpen}>\n      <PopoverTrigger asChild>\n        <DatePickerTrigger\n          data-slot=\"date-picker\"\n          empty={!value}\n          className={cn(\"min-w-44\", className)}\n          {...triggerProps}\n        >\n          {value ? format(value, dateFormat) : placeholder}\n        </DatePickerTrigger>\n      </PopoverTrigger>\n      <PopoverContent align={align} className=\"w-auto p-0\">\n        <Calendar\n          mode=\"single\"\n          autoFocus\n          selected={value}\n          defaultMonth={value}\n          onSelect={(next) => {\n            setValue(next)\n            setOpen(false)\n          }}\n        />\n      </PopoverContent>\n    </Popover>\n  )\n}\n\ntype DateRangePickerProps = DatePickerBaseProps & {\n  defaultValue?: DateRange\n  numberOfMonths?: number\n  onValueChange?: (value: DateRange | undefined) => void\n  value?: DateRange\n}\n\n/* \"Aug 4 - Aug 12, 2026\" while the range sits inside one year; both years are\n   spelled out once it straddles a boundary, where a bare \"Dec 28\" is ambiguous. */\nfunction formatDateRange(range: DateRange | undefined, dateFormat: string) {\n  if (!range?.from) return undefined\n  if (!range.to) return format(range.from, dateFormat)\n\n  return isSameYear(range.from, range.to)\n    ? `${format(range.from, \"MMM d\")} - ${format(range.to, dateFormat)}`\n    : `${format(range.from, dateFormat)} - ${format(range.to, dateFormat)}`\n}\n\nfunction DateRangePicker(props: DateRangePickerProps) {\n  const controlled = React.useRef(\"value\" in props).current\n  const {\n    align = \"start\",\n    className,\n    dateFormat = \"MMM d, yyyy\",\n    defaultValue,\n    numberOfMonths = 2,\n    onValueChange,\n    placeholder = \"Pick a date range\",\n    value: valueProp,\n    ...triggerProps\n  } = props\n\n  const [open, setOpen] = React.useState(false)\n  const [value, setValue] = useDateSelection<DateRange>(\n    controlled,\n    valueProp,\n    defaultValue,\n    onValueChange\n  )\n\n  const label = formatDateRange(value, dateFormat)\n\n  return (\n    <Popover open={open} onOpenChange={setOpen}>\n      <PopoverTrigger asChild>\n        <DatePickerTrigger\n          data-slot=\"date-range-picker\"\n          empty={!label}\n          className={cn(\"min-w-60\", className)}\n          {...triggerProps}\n        >\n          {label ?? placeholder}\n        </DatePickerTrigger>\n      </PopoverTrigger>\n      <PopoverContent align={align} className=\"w-auto p-0\">\n        <Calendar\n          mode=\"range\"\n          autoFocus\n          selected={value}\n          defaultMonth={value?.from}\n          numberOfMonths={numberOfMonths}\n          onSelect={(next) => {\n            setValue(next)\n            /* Hold the popover open until both ends are committed. */\n            if (next?.from && next.to) setOpen(false)\n          }}\n        />\n      </PopoverContent>\n    </Popover>\n  )\n}\n\nexport { DatePicker, DateRangePicker }\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}