{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "date-picker",
  "title": "Date picker",
  "description": "A date field component that allows users to enter and edit date.",
  "dependencies": [
    "date-fns",
    "@mdi/js",
    "react-day-picker"
  ],
  "registryDependencies": [
    "https://blok.sitecore.com/r/theme.json",
    "https://blok.sitecore.com/r/button.json",
    "https://blok.sitecore.com/r/calendar.json",
    "https://blok.sitecore.com/r/popover.json",
    "https://blok.sitecore.com/r/select.json"
  ],
  "files": [
    {
      "path": "src/components/ui/date-picker.tsx",
      "content": "\"use client\";\n\nimport { Icon } from \"@/lib/icon\";\nimport { mdiCalendarBlankOutline } from \"@mdi/js\";\nimport { type Locale, format } from \"date-fns\";\nimport * as React from \"react\";\nimport type { DateRange } from \"react-day-picker\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Calendar } from \"@/components/ui/calendar\";\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { cn } from \"@/lib/utils\";\n\ntype CalendarProps = React.ComponentProps<typeof Calendar>;\n\n/**\n * Optional ARIA strings for the date picker UI outside the calendar grid.\n * For DayPicker label creators (nav, days, etc.), use `calendarProps.ariaLabels`.\n */\nexport type DatePickerAriaLabels = {\n  /**\n   * `aria-label` on the popover trigger when **no date is selected** (empty state).\n   * When a date is shown, `aria-label` is omitted so the visible formatted date is the accessible name.\n   */\n  popoverTrigger?: string;\n};\n\nexport type DatePickerSimpleCalendarProps = Omit<\n  CalendarProps,\n  \"mode\" | \"selected\" | \"onSelect\"\n>;\n\nexport type DatePickerSimpleProps = {\n  /** Uncontrolled initial selection */\n  defaultValue?: Date;\n  /** Fires when the selected date changes */\n  onChange?: (date: Date | undefined) => void;\n  /** Trigger label when empty (e.g. translated placeholder) */\n  placeholder?: React.ReactNode;\n  /** `date-fns` format string for the trigger when a date is selected */\n  dateFormat?: string;\n  /** Used with `format()` and forwarded to `Calendar` */\n  locale?: Locale;\n  disabled?: boolean;\n  id?: string;\n  className?: string;\n  ariaLabels?: DatePickerAriaLabels;\n  /** Props forwarded to `Calendar`; `mode`, `selected`, and `onSelect` are fixed */\n  calendarProps?: DatePickerSimpleCalendarProps;\n} & (\n  | {\n      /** Controlled value; pass `undefined` to clear. Omit for uncontrolled usage. */\n      value: Date | undefined;\n    }\n  | { value?: never }\n);\n\nfunction DatePickerSimple(props: DatePickerSimpleProps) {\n  const {\n    defaultValue,\n    onChange,\n    placeholder = \"Pick a date\",\n    dateFormat = \"PPP\",\n    locale,\n    disabled,\n    id,\n    className,\n    ariaLabels,\n    calendarProps,\n  } = props;\n\n  const isControlled = \"value\" in props;\n  const valueProp = isControlled ? props.value : undefined;\n\n  const [internalDate, setInternalDate] = React.useState<Date | undefined>(\n    defaultValue,\n  );\n\n  const date = isControlled ? valueProp : internalDate;\n\n  const setDate = React.useCallback(\n    (next: Date | undefined) => {\n      if (!isControlled) {\n        setInternalDate(next);\n      }\n      onChange?.(next);\n    },\n    [isControlled, onChange],\n  );\n\n  const formatOpts = locale ? { locale } : undefined;\n  const mergedLocale = locale ?? calendarProps?.locale;\n\n  return (\n    <Popover>\n      <PopoverTrigger id={id} asChild>\n        <Button\n          type=\"button\"\n          id={id}\n          variant=\"outline\"\n          colorScheme=\"neutral\"\n          disabled={disabled}\n          aria-label={\n            date\n              ? undefined\n              : (ariaLabels?.popoverTrigger ??\n                (typeof placeholder === \"string\" ? placeholder : undefined))\n          }\n          className={cn(\n            \"border-input border-1 data-[state=open]:border-2 data-[state=open]:border-primary rounded-md text-md data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 bg-body-bg px-3 py-2 whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[2px] disabled:cursor-not-allowed disabled:opacity-50 h-10\",\n            !date && \"text-muted-foreground\",\n            className,\n          )}\n        >\n          <Icon\n            path={mdiCalendarBlankOutline}\n            size={1}\n            className=\"text-muted-foreground\"\n            aria-hidden\n          />\n          {date ? (\n            format(date, dateFormat, formatOpts)\n          ) : (\n            <span>{placeholder}</span>\n          )}\n        </Button>\n      </PopoverTrigger>\n      <PopoverContent\n        className=\"w-auto p-0\"\n        align=\"start\"\n        aria-label=\"Choose date\"\n      >\n        <Calendar\n          {...calendarProps}\n          mode=\"single\"\n          selected={date}\n          onSelect={setDate}\n          initialFocus={calendarProps?.initialFocus ?? true}\n          captionLayout={calendarProps?.captionLayout ?? \"dropdown\"}\n          locale={mergedLocale}\n          components={{\n            ...calendarProps?.components,\n          }}\n        />\n      </PopoverContent>\n    </Popover>\n  );\n}\n\nexport type DatePickerWithRangeCalendarProps = Omit<\n  CalendarProps,\n  \"mode\" | \"selected\" | \"onSelect\"\n>;\n\nexport type DatePickerWithRangeProps = {\n  defaultValue?: DateRange;\n  onChange?: (range: DateRange | undefined) => void;\n  placeholder?: React.ReactNode;\n  /** `date-fns` format for each boundary in the trigger */\n  rangeDateFormat?: string;\n  /** Between start and end when both are set */\n  rangeSeparator?: React.ReactNode;\n  locale?: Locale;\n  disabled?: boolean;\n  id?: string;\n  className?: string;\n  ariaLabels?: DatePickerAriaLabels;\n  calendarProps?: DatePickerWithRangeCalendarProps;\n} & ({ value: DateRange | undefined } | { value?: never });\n\nfunction DatePickerWithRange(props: DatePickerWithRangeProps) {\n  const {\n    defaultValue,\n    onChange,\n    placeholder = \"Pick a date\",\n    rangeDateFormat = \"LLL dd, y\",\n    rangeSeparator = \" - \",\n    locale,\n    disabled,\n    id,\n    className,\n    ariaLabels,\n    calendarProps,\n  } = props;\n\n  const isControlled = \"value\" in props;\n  const valueProp = isControlled ? props.value : undefined;\n\n  const [internalRange, setInternalRange] = React.useState<\n    DateRange | undefined\n  >(defaultValue);\n\n  const range = isControlled ? valueProp : internalRange;\n\n  const setRange = React.useCallback(\n    (next: DateRange | undefined) => {\n      if (!isControlled) {\n        setInternalRange(next);\n      }\n      onChange?.(next);\n    },\n    [isControlled, onChange],\n  );\n\n  const formatOpts = locale ? { locale } : undefined;\n  const mergedLocale = locale ?? calendarProps?.locale;\n\n  const triggerLabel = (() => {\n    if (!range?.from) {\n      return <span>{placeholder}</span>;\n    }\n    if (range.to) {\n      return (\n        <>\n          {format(range.from, rangeDateFormat, formatOpts)}\n          {rangeSeparator}\n          {format(range.to, rangeDateFormat, formatOpts)}\n        </>\n      );\n    }\n    return format(range.from, rangeDateFormat, formatOpts);\n  })();\n\n  return (\n    <Popover>\n      <PopoverTrigger id={id} asChild>\n        <Button\n          type=\"button\"\n          id={id}\n          variant=\"outline\"\n          colorScheme=\"neutral\"\n          disabled={disabled}\n          aria-label={\n            range?.from\n              ? undefined\n              : (ariaLabels?.popoverTrigger ??\n                (typeof placeholder === \"string\" ? placeholder : undefined))\n          }\n          className={cn(\n            \"border-input border-1 data-[state=open]:border-2 data-[state=open]:border-primary rounded-md text-md data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 bg-body-bg px-3 py-2 whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[2px] disabled:cursor-not-allowed disabled:opacity-50 h-10\",\n            !range?.from && \"text-muted-foreground\",\n            className,\n          )}\n        >\n          <Icon\n            path={mdiCalendarBlankOutline}\n            size={1}\n            className=\"text-muted-foreground\"\n            aria-hidden\n          />\n          {triggerLabel}\n        </Button>\n      </PopoverTrigger>\n      <PopoverContent\n        className=\"w-auto p-0\"\n        align=\"start\"\n        aria-label=\"Choose date\"\n      >\n        <Calendar\n          {...calendarProps}\n          mode=\"range\"\n          defaultMonth={range?.from ?? calendarProps?.defaultMonth}\n          selected={range}\n          onSelect={setRange}\n          numberOfMonths={calendarProps?.numberOfMonths ?? 2}\n          initialFocus={calendarProps?.initialFocus ?? true}\n          captionLayout={calendarProps?.captionLayout ?? \"dropdown\"}\n          locale={mergedLocale}\n          components={{\n            ...calendarProps?.components,\n          }}\n        />\n      </PopoverContent>\n    </Popover>\n  );\n}\n\nexport { DatePickerSimple, DatePickerWithRange };\n",
      "type": "registry:ui"
    },
    {
      "path": "src/lib/icon.tsx",
      "content": "import type { SVGProps } from \"react\";\n\ntype IconProps = SVGProps<SVGSVGElement> & {\n  path: string;\n  title?: string;\n  size?: number | string;\n  className?: string;\n  fill?: string;\n};\n\nexport function Icon({\n  path,\n  title,\n  size = 1,\n  className,\n  fill = \"currentColor\",\n  ...rest\n}: IconProps) {\n  return (\n    <svg\n      transform={`scale(${size})`}\n      viewBox=\"0 0 24 24\"\n      aria-label={title}\n      className={className}\n      {...rest}\n    >\n      {title ? <title>{title}</title> : null}\n      <path d={path} fill={fill} />\n    </svg>\n  );\n}\n",
      "type": "registry:lib"
    }
  ],
  "type": "registry:ui"
}