{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "date-picker",
  "title": "Date Picker",
  "description": "A text field with a docked date picker.",
  "dependencies": [
    "@base-ui/react@^1.7.0",
    "lucide-react@^1.33.0"
  ],
  "registryDependencies": [
    "https://guillermo-rebolledo.github.io/materialcn/r/button.json",
    "https://guillermo-rebolledo.github.io/materialcn/r/calendar.json",
    "https://guillermo-rebolledo.github.io/materialcn/r/calendar-utils.json",
    "https://guillermo-rebolledo.github.io/materialcn/r/field.json",
    "https://guillermo-rebolledo.github.io/materialcn/r/input.json",
    "https://guillermo-rebolledo.github.io/materialcn/r/materialcn-theme.json",
    "https://guillermo-rebolledo.github.io/materialcn/r/utils.json"
  ],
  "files": [
    {
      "path": "src/components/ui/date-picker.tsx",
      "content": "import { useId, useRef, useState, type ComponentProps } from \"react\"\nimport { Popover as PopoverPrimitive } from \"@base-ui/react/popover\"\nimport { CalendarDaysIcon, XIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"./button\"\nimport { Calendar, type CalendarProps } from \"./calendar\"\nimport { isDateSelectable } from \"./calendar-utils\"\nimport { Field, FieldDescription, FieldError, FieldLabel } from \"./field\"\nimport { Input } from \"./input\"\n\ntype DatePickerProps = Omit<ComponentProps<\"div\">, \"defaultValue\" | \"onChange\"> &\n  Pick<CalendarProps, \"defaultMonth\" | \"isDateUnavailable\" | \"locale\" | \"max\" | \"min\"> & {\n    disabled?: boolean\n    error?: string\n    formatDate?: (date: Date, locale: string) => string\n    invalid?: boolean\n    label: string\n    onValueChange: (date: Date | null) => void\n    parseDate?: (text: string, locale: string) => Date | null\n    readOnly?: boolean\n    supportingText?: string\n    value: Date | null\n  }\n\nfunction defaultFormat(date: Date, locale: string) {\n  return new Intl.DateTimeFormat(locale, { year: \"numeric\", month: \"short\", day: \"numeric\" }).format(date)\n}\n\nfunction defaultParse(text: string) {\n  const timestamp = Date.parse(text)\n  return Number.isNaN(timestamp) ? null : new Date(timestamp)\n}\n\nfunction DatePicker({\n  className,\n  defaultMonth,\n  disabled = false,\n  error,\n  formatDate = defaultFormat,\n  invalid = false,\n  isDateUnavailable,\n  label,\n  locale = \"en-US\",\n  max,\n  min,\n  onValueChange,\n  parseDate = defaultParse,\n  readOnly = false,\n  supportingText,\n  value,\n  ...props\n}: DatePickerProps) {\n  const [open, setOpen] = useState(false)\n  const sourceKey = value\n    ? `${value.getFullYear()}-${value.getMonth()}-${value.getDate()}-${locale}`\n    : `empty-${locale}`\n  const [draftState, setDraftState] = useState(() => ({\n    sourceKey,\n    text: value ? formatDate(value, locale) : \"\",\n  }))\n  if (draftState.sourceKey !== sourceKey) {\n    setDraftState({\n      sourceKey,\n      text: value ? formatDate(value, locale) : \"\",\n    })\n  }\n  const draft = draftState.text\n  const triggerRef = useRef<HTMLButtonElement>(null)\n  const calendarRef = useRef<HTMLDivElement>(null)\n  const id = useId()\n  const errorId = `${id}-error`\n  const parsedDraft = draft ? parseDate(draft, locale) : null\n  const draftInvalid = Boolean(\n    draft &&\n      (!parsedDraft || !isDateSelectable(parsedDraft, { isDateUnavailable, max, min })),\n  )\n  const ariaInvalid = invalid || draftInvalid\n\n  const select = (date: Date) => {\n    onValueChange(date)\n    setDraftState({\n      sourceKey: `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}-${locale}`,\n      text: formatDate(date, locale),\n    })\n    setOpen(false)\n  }\n\n  return (\n    <PopoverPrimitive.Root open={open} onOpenChange={setOpen}>\n      <div\n        {...props}\n        data-slot=\"date-picker\"\n        className={cn(\"relative flex flex-col gap-2\", className)}\n      >\n        <Field data-invalid={ariaInvalid || undefined} data-disabled={disabled || undefined}>\n          <FieldLabel htmlFor={id}>{label}</FieldLabel>\n          <div className=\"relative\">\n            <Input\n              id={id}\n              value={draft}\n              disabled={disabled}\n              readOnly={readOnly}\n              aria-invalid={ariaInvalid || undefined}\n              aria-describedby={error || draftInvalid ? errorId : undefined}\n              placeholder={new Intl.DateTimeFormat(locale).format(new Date(2026, 7, 24))}\n              className=\"pr-24\"\n              onChange={(event) => setDraftState({ sourceKey, text: event.target.value })}\n              onBlur={() => {\n                if (!draft) return onValueChange(null)\n                if (parsedDraft && !draftInvalid) onValueChange(parsedDraft)\n              }}\n            />\n            <div className=\"absolute inset-y-0 right-1 flex items-center\">\n              {value && !disabled && !readOnly && (\n                <Button aria-label=\"Clear date\" size=\"icon-sm\" variant=\"ghost\" onClick={() => { onValueChange(null); setDraftState({ sourceKey: `empty-${locale}`, text: \"\" }) }}>\n                  <XIcon aria-hidden=\"true\" />\n                </Button>\n              )}\n              <PopoverPrimitive.Trigger\n                ref={triggerRef}\n                disabled={disabled || readOnly}\n                render={<Button aria-label=\"Choose date\" size=\"icon-sm\" variant=\"ghost\" />}\n              >\n                <CalendarDaysIcon aria-hidden=\"true\" />\n              </PopoverPrimitive.Trigger>\n            </div>\n          </div>\n          {supportingText && <FieldDescription>{supportingText}</FieldDescription>}\n          {(error || draftInvalid) && (\n            <FieldError id={errorId}>\n              {error ?? \"Enter an available date within the allowed range\"}\n            </FieldError>\n          )}\n        </Field>\n        <PopoverPrimitive.Portal>\n          <PopoverPrimitive.Positioner align=\"end\" side=\"bottom\" sideOffset={8} className=\"isolate z-(--m3-z-menu)\">\n            <PopoverPrimitive.Popup\n            aria-label={`${label} calendar`}\n            data-slot=\"date-picker-popover\"\n            initialFocus={() =>\n              calendarRef.current?.querySelector<HTMLButtonElement>('[role=\"gridcell\"][tabindex=\"0\"]') ?? true\n            }\n              className=\"max-w-[calc(100vw-2rem)] origin-(--transform-origin) outline-none transition-[transform,opacity] duration-(--m3-spring-effects-fast-duration) ease-(--m3-spring-effects-fast) data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:scale-95 data-ending-style:opacity-0 motion-reduce:transition-none\"\n            >\n              <Calendar\n              selected={value}\n              ref={calendarRef}\n                onSelect={select}\n                defaultMonth={defaultMonth ?? value ?? undefined}\n                locale={locale}\n                min={min}\n                max={max}\n                isDateUnavailable={isDateUnavailable}\n              />\n            </PopoverPrimitive.Popup>\n          </PopoverPrimitive.Positioner>\n        </PopoverPrimitive.Portal>\n      </div>\n    </PopoverPrimitive.Root>\n  )\n}\n\nexport { DatePicker, type DatePickerProps }\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "forms"
  ],
  "type": "registry:ui"
}