{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "date-picker",
  "title": "date-picker",
  "dependencies": [
    "class-variance-authority@^0.7",
    "react-day-picker@^10.0.2"
  ],
  "registryDependencies": [
    "@dwellir/dwellir-theme",
    "@dwellir/utils",
    "@dwellir/button",
    "@dwellir/calendar",
    "@dwellir/popover",
    "@dwellir/rune-icons"
  ],
  "files": [
    {
      "path": "components/ui/date-picker.tsx",
      "content": "'use client';\n\nimport type { VariantProps } from 'class-variance-authority';\nimport { type ComponentProps, useId, useState } from 'react';\nimport type { DateRange, PropsBase } from 'react-day-picker';\nimport { RuneCalendar } from '@/components/brand/rune-icons';\nimport { Button, type buttonVariants } from '@/components/ui/button';\nimport { Calendar } from '@/components/ui/calendar';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\nimport { cn } from '@/lib/utils';\n\n/*\n * A Button that opens a Calendar in a Popover. DatePicker picks one day and\n * closes; DateRangePicker shows two months and stays open until Escape or a\n * click outside, so the reader can adjust both ends.\n * A fixed locale, so the server and the browser print the same label.\n */\nconst DATE = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium' });\n\nfunction formatDate(date: Date) {\n  return DATE.format(date);\n}\n\n/*\n * ICU versions space a range's dash differently: Node prints thin spaces,\n * Chromium plain ones. Plain spaces keep the server and browser label equal.\n */\nfunction formatDateRange({ from, to }: DateRange) {\n  if (!from) return '';\n  return to\n    ? DATE.formatRange(from, to).replace(/[\\u2009\\u202f]/g, ' ')\n    : `${DATE.format(from)} to …`;\n}\n\ntype Controllable<T> = {\n  value?: T;\n  defaultValue?: T;\n  onValueChange?: (next: T | undefined) => void;\n};\n\n/*\n * Value and setter. Controlled when the value prop is present, even as\n * undefined (nothing picked); else it starts from defaultValue.\n */\nfunction useControllable<T>(props: Controllable<T>) {\n  const [own, setOwn] = useState(props.defaultValue);\n  const controlled = 'value' in props;\n  const set = (next: T | undefined) => {\n    if (!controlled) setOwn(next);\n    props.onValueChange?.(next);\n  };\n  return [controlled ? props.value : own, set] as const;\n}\n\ntype TriggerProps = Omit<\n  ComponentProps<'button'>,\n  'value' | 'defaultValue' | 'onChange' | 'children'\n> &\n  VariantProps<typeof buttonVariants> & {\n    /* The label while nothing is picked. */\n    placeholder?: string;\n    /* Where the calendar lines up with the trigger. */\n    align?: ComponentProps<typeof PopoverContent>['align'];\n    /* Calendar options other than the selection: disabled days, month bounds, locale. */\n    calendarProps?: PropsBase & Pick<ComponentProps<typeof Calendar>, 'buttonVariant'>;\n    /* The calendar popup's name for screen readers. By default the trigger names it. */\n    popupLabel?: string;\n  };\n\n/*\n * The popup is a dialog, so it needs a name: the trigger's labels, or the trigger\n * itself, unless popupLabel sets one.\n */\nfunction usePopupName(trigger: { id?: string; 'aria-labelledby'?: string }, popupLabel?: string) {\n  const fallbackId = useId();\n  const triggerId = trigger.id ?? fallbackId;\n  const popup = popupLabel\n    ? { 'aria-label': popupLabel }\n    : { 'aria-labelledby': trigger['aria-labelledby'] ?? triggerId };\n  return [triggerId, popup] as const;\n}\n\n/*\n * A filled trigger keeps its own text colour: the muted one is too faint on the\n * secondary fill in the dark theme. On hover the placeholder takes full ink,\n * since muted text on the hover tint falls under 4.5:1 in the dark theme.\n */\nconst MUTED_PLACEHOLDER = new Set(['outline', 'ghost']);\n\n/* The outline Button by default; data-empty mutes the placeholder on an unfilled trigger. */\nfunction DatePickerTrigger({\n  label,\n  empty,\n  className,\n  variant = 'outline',\n  ...props\n}: Omit<TriggerProps, 'placeholder' | 'align' | 'calendarProps' | 'popupLabel'> & {\n  label: string;\n  empty: boolean;\n}) {\n  return (\n    <PopoverTrigger asChild>\n      <Button\n        data-empty={empty || undefined}\n        variant={variant}\n        className={cn(\n          MUTED_PLACEHOLDER.has(variant ?? 'outline') &&\n            'data-[empty=true]:text-muted-foreground data-[empty=true]:hover:text-foreground',\n          className,\n        )}\n        {...props}\n      >\n        <RuneCalendar size={24} aria-hidden=\"true\" />\n        {label}\n      </Button>\n    </PopoverTrigger>\n  );\n}\n\ntype DatePickerProps = TriggerProps & {\n  value?: Date;\n  defaultValue?: Date;\n  onValueChange?: (date: Date | undefined) => void;\n  formatValue?: (date: Date) => string;\n};\n\nfunction DatePicker(props: DatePickerProps) {\n  const {\n    value: _value,\n    defaultValue: _defaultValue,\n    onValueChange: _onValueChange,\n    formatValue = formatDate,\n    placeholder = 'Pick a date',\n    align = 'start',\n    calendarProps,\n    popupLabel,\n    ...trigger\n  } = props;\n  const [open, setOpen] = useState(false);\n  const [date, setDate] = useControllable(props);\n  const [triggerId, popupName] = usePopupName(trigger, popupLabel);\n  return (\n    <Popover open={open} onOpenChange={setOpen}>\n      <DatePickerTrigger\n        label={date ? formatValue(date) : placeholder}\n        empty={!date}\n        {...trigger}\n        id={triggerId}\n      />\n      <PopoverContent align={align} className=\"w-auto p-0\" {...popupName}>\n        <Calendar\n          defaultMonth={date}\n          {...calendarProps}\n          mode=\"single\"\n          selected={date}\n          onSelect={(next) => {\n            setDate(next);\n            setOpen(false);\n          }}\n        />\n      </PopoverContent>\n    </Popover>\n  );\n}\n\ntype DateRangePickerProps = TriggerProps & {\n  value?: DateRange;\n  defaultValue?: DateRange;\n  onValueChange?: (range: DateRange | undefined) => void;\n  formatValue?: (range: DateRange) => string;\n};\n\nfunction DateRangePicker(props: DateRangePickerProps) {\n  const {\n    value: _value,\n    defaultValue: _defaultValue,\n    onValueChange: _onValueChange,\n    formatValue = formatDateRange,\n    placeholder = 'Pick a date range',\n    align = 'start',\n    calendarProps,\n    popupLabel,\n    ...trigger\n  } = props;\n  const [range, setRange] = useControllable(props);\n  const [triggerId, popupName] = usePopupName(trigger, popupLabel);\n  return (\n    <Popover>\n      <DatePickerTrigger\n        label={range?.from ? formatValue(range) : placeholder}\n        empty={!range?.from}\n        {...trigger}\n        id={triggerId}\n      />\n      <PopoverContent align={align} className=\"w-auto p-0\" {...popupName}>\n        <Calendar\n          defaultMonth={range?.from}\n          numberOfMonths={2}\n          {...calendarProps}\n          mode=\"range\"\n          selected={range}\n          onSelect={setRange}\n        />\n      </PopoverContent>\n    </Popover>\n  );\n}\n\nexport { DatePicker, DateRangePicker, formatDate, formatDateRange };\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}