{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "date-range-picker",
  "type": "registry:ui",
  "title": "Date Range Picker",
  "description": "Controlled/uncontrolled date-range input — Button + Popover + range-mode Calendar.",
  "dependencies": [
    "@saasflare/ui"
  ],
  "files": [
    {
      "path": "components/ui/date-range-picker.tsx",
      "type": "registry:ui",
      "content": "// @draft\n\"use client\"\n\n/**\n * @fileoverview Saasflare DateRangePicker — controlled/uncontrolled date-range\n * input. Composes the existing Button, Popover, and Calendar (in range mode).\n * @author Saasflare™\n *\n * Drops into form contexts as a trigger button that opens a popover with a\n * two-month range calendar. Emits `{ from, to }` via `onChange`. Built\n * exclusively from existing Saasflare primitives — no new third-party deps\n * (Calendar already wraps react-day-picker).\n *\n * @module packages/ui/components/ui/date-range-picker\n * @package ui\n * @layer core\n *\n * @example\n * const [range, setRange] = useState<DateRange | undefined>();\n * <DateRangePicker value={range} onChange={setRange} />\n */\n\nimport * as React from \"react\"\nimport { cn } from \"@saasflare/ui\"\nimport { useSaasflareProps, type SaasflareComponentProps } from \"@saasflare/ui\"\nimport { Button } from \"@saasflare/ui\"\nimport { Calendar } from \"@saasflare/ui/calendar\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"@saasflare/ui\"\n\n/** Inline calendar glyph — the local phosphor barrel doesn't ship a\n * Calendar icon, and adding one for a single use isn't worth the surface. */\nfunction CalendarIcon(props: React.SVGProps<SVGSVGElement>) {\n    return (\n        <svg\n            xmlns=\"http://www.w3.org/2000/svg\"\n            viewBox=\"0 0 24 24\"\n            fill=\"none\"\n            stroke=\"currentColor\"\n            strokeWidth=\"2\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            aria-hidden=\"true\"\n            {...props}\n        >\n            <rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\" ry=\"2\" />\n            <line x1=\"16\" x2=\"16\" y1=\"2\" y2=\"6\" />\n            <line x1=\"8\" x2=\"8\" y1=\"2\" y2=\"6\" />\n            <line x1=\"3\" x2=\"21\" y1=\"10\" y2=\"10\" />\n        </svg>\n    )\n}\n\n/** Inclusive date range, identical shape to react-day-picker's `DateRange`. */\nexport interface DateRange {\n    from: Date | undefined\n    to?: Date | undefined\n}\n\n/** Props for the DateRangePicker component. */\nexport interface DateRangePickerProps extends SaasflareComponentProps {\n    /** Controlled value. Pass `null` for a controlled-but-empty picker. */\n    value?: DateRange | null\n    /** Uncontrolled default value. */\n    defaultValue?: DateRange\n    /** Called when the user picks a new range (`undefined` on deselect — writing it back to state keeps the picker controlled and clears it). */\n    onChange?: (range: DateRange | undefined) => void\n    /** Placeholder shown in the trigger when no range is set. */\n    placeholder?: string\n    /** Number of months shown side-by-side. Default: `2`. */\n    numberOfMonths?: number\n    /** Earliest pickable date. */\n    minDate?: Date\n    /** Latest pickable date. */\n    maxDate?: Date\n    /** Disable the trigger. */\n    disabled?: boolean\n    /** Format function for the trigger label. Default: locale-aware `toLocaleDateString`. */\n    formatRange?: (range: DateRange) => string\n    /** Additional class names on the trigger. */\n    className?: string\n}\n\nfunction defaultFormat(range: DateRange): string {\n    const fmt = (d: Date) =>\n        d.toLocaleDateString(undefined, {\n            year: \"numeric\",\n            month: \"short\",\n            day: \"numeric\",\n        })\n    if (!range.from) return \"\"\n    if (!range.to) return fmt(range.from)\n    return `${fmt(range.from)} – ${fmt(range.to)}`\n}\n\n/**\n * Date-range input + popover calendar. Composes Button + Popover + Calendar.\n *\n * @component\n * @layer core\n */\nexport function DateRangePicker({\n    value,\n    defaultValue,\n    onChange,\n    placeholder = \"Pick a date range\",\n    numberOfMonths = 2,\n    minDate,\n    maxDate,\n    disabled = false,\n    formatRange = defaultFormat,\n    className,\n    surface,\n    radius,\n    animated,\n    iconWeight,\n}: DateRangePickerProps) {\n    const sf = useSaasflareProps({ surface, radius, animated, iconWeight })\n\n    /* Latched controlled-ness — see DatePicker: keeps the component controlled\n     * after the parent stores the `undefined` emitted on deselect, so a\n     * controlled clear actually renders. */\n    const wasControlled = React.useRef(value !== undefined)\n    if (value !== undefined) wasControlled.current = true\n    const isControlled = wasControlled.current\n    const [internal, setInternal] = React.useState<DateRange | undefined>(defaultValue)\n    const range = isControlled ? (value ?? undefined) : internal\n\n    const handleSelect = (next: DateRange | undefined) => {\n        if (!isControlled) setInternal(next)\n        onChange?.(next)\n    }\n\n    const label = range && range.from ? formatRange(range) : placeholder\n\n    return (\n        <Popover>\n            <PopoverTrigger asChild>\n                <Button\n                    type=\"button\"\n                    variant=\"outline\"\n                    intent=\"neutral\"\n                    disabled={disabled}\n                    surface={sf.surface}\n                    radius={sf.radius}\n                    animated={sf.animated}\n                    data-slot=\"date-range-picker-trigger\"\n                    className={cn(\n                        \"min-w-56 justify-start gap-2 font-normal\",\n                        !range?.from && \"text-muted-foreground\",\n                        className,\n                    )}\n                >\n                    <CalendarIcon className=\"size-4\" />\n                    <span className=\"truncate\">{label}</span>\n                </Button>\n            </PopoverTrigger>\n            <PopoverContent\n                data-slot=\"date-range-picker-content\"\n                align=\"start\"\n                className=\"w-auto p-0\"\n            >\n                <Calendar\n                    mode=\"range\"\n                    selected={range}\n                    onSelect={handleSelect}\n                    numberOfMonths={numberOfMonths}\n                    defaultMonth={range?.from ?? new Date()}\n                    iconWeight={sf.iconWeight}\n                    disabled={\n                        minDate || maxDate\n                            ? (date: Date) =>\n                                  (minDate ? date < minDate : false) ||\n                                  (maxDate ? date > maxDate : false)\n                            : undefined\n                    }\n                />\n            </PopoverContent>\n        </Popover>\n    )\n}\n",
      "target": "components/ui/date-range-picker.tsx"
    }
  ],
  "$meta": {
    "source": "https://ui.saasflare.io/r/date-range-picker.json"
  }
}
