{"$schema":"https://ui.shadcn.com/schema/registry-item.json","author":"Eduardo Calvo <edu@smoothui.dev>","css":{},"dependencies":["lucide-react","react-day-picker"],"description":"Calendar date picker grid for SmoothUI built on react-day-picker.","devDependencies":[],"files":[{"content":"\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\";\nimport { type ComponentProps, useEffect, useRef } from \"react\";\nimport {\n  type DayButton,\n  DayPicker,\n  getDefaultClassNames,\n} from \"react-day-picker\";\n\nexport type CalendarProps = ComponentProps<typeof DayPicker>;\n\nconst CalendarDayButton = ({\n  className,\n  day,\n  modifiers,\n  ...props\n}: ComponentProps<typeof DayButton>) => {\n  const defaultClassNames = getDefaultClassNames();\n  const ref = useRef<HTMLButtonElement>(null);\n\n  useEffect(() => {\n    if (modifiers.focused) {\n      ref.current?.focus();\n    }\n  }, [modifiers.focused]);\n\n  return (\n    <button\n      {...props}\n      className={cn(\n        \"flex aspect-square size-auto w-full min-w-(--cell-size) flex-col items-center justify-center gap-1 rounded-md p-0 font-normal text-sm leading-none\",\n        \"hover:bg-foreground/10\",\n        \"group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10\",\n        \"group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50\",\n        // Use foreground fill — primary can be near-invisible in dark themes\n        \"data-[selected-single=true]:bg-foreground data-[selected-single=true]:text-background\",\n        \"data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-foreground data-[range-start=true]:text-background\",\n        \"data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-foreground data-[range-end=true]:text-background\",\n        \"data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-foreground/15 data-[range-middle=true]:text-foreground\",\n        defaultClassNames.day_button,\n        className\n      )}\n      data-day={`${day.date.getFullYear()}-${day.date.getMonth() + 1}-${day.date.getDate()}`}\n      data-range-end={modifiers.range_end || undefined}\n      data-range-middle={modifiers.range_middle || undefined}\n      data-range-start={modifiers.range_start || undefined}\n      data-selected-single={\n        modifiers.selected &&\n        !modifiers.range_start &&\n        !modifiers.range_end &&\n        !modifiers.range_middle\n          ? \"true\"\n          : undefined\n      }\n      ref={ref}\n      type=\"button\"\n    />\n  );\n};\n\nconst CalendarChevron = ({\n  orientation,\n  className: chevronClass,\n  ...chevronProps\n}: {\n  className?: string;\n  orientation?: \"left\" | \"right\" | \"up\" | \"down\";\n} & ComponentProps<\"svg\">) => {\n  const Icon = orientation === \"left\" ? ChevronLeftIcon : ChevronRightIcon;\n  return <Icon className={cn(\"size-4\", chevronClass)} {...chevronProps} />;\n};\n\n/**\n * SmoothUI Calendar — react-day-picker with SmoothUI surface tokens.\n * Compose with Popover for a date-picker field.\n */\nexport default function Calendar({\n  className,\n  classNames,\n  showOutsideDays = true,\n  ...props\n}: CalendarProps) {\n  const defaultClassNames = getDefaultClassNames();\n\n  return (\n    <DayPicker\n      className={cn(\"group/calendar w-fit p-3 [--cell-size:2rem]\", className)}\n      classNames={{\n        button_next: cn(\n          \"inline-flex size-(--cell-size) select-none items-center justify-center rounded-md p-0 text-muted-foreground hover:bg-foreground/10 hover:text-foreground disabled:opacity-50\",\n          defaultClassNames.button_next\n        ),\n        button_previous: cn(\n          \"inline-flex size-(--cell-size) select-none items-center justify-center rounded-md p-0 text-muted-foreground hover:bg-foreground/10 hover:text-foreground disabled:opacity-50\",\n          defaultClassNames.button_previous\n        ),\n        caption_label: cn(\n          \"select-none font-medium text-sm\",\n          defaultClassNames.caption_label\n        ),\n        day: cn(\n          \"group/day relative aspect-square h-full w-full select-none p-0 text-center\",\n          \"[&:first-child[data-selected=true]_button]:rounded-l-md\",\n          \"[&:last-child[data-selected=true]_button]:rounded-r-md\",\n          defaultClassNames.day\n        ),\n        disabled: cn(\n          \"text-muted-foreground/40 opacity-50\",\n          defaultClassNames.disabled\n        ),\n        hidden: cn(\"invisible\", defaultClassNames.hidden),\n        month: cn(\"flex w-full flex-col gap-4\", defaultClassNames.month),\n        month_caption: cn(\n          \"flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)\",\n          defaultClassNames.month_caption\n        ),\n        months: cn(\n          \"relative flex flex-col gap-4 md:flex-row\",\n          defaultClassNames.months\n        ),\n        nav: cn(\n          \"absolute inset-x-0 top-0 flex w-full items-center justify-between\",\n          defaultClassNames.nav\n        ),\n        outside: cn(\"text-muted-foreground/50\", defaultClassNames.outside),\n        range_end: cn(\n          \"rounded-r-md bg-primary/15\",\n          defaultClassNames.range_end\n        ),\n        range_middle: cn(\n          \"rounded-none bg-primary/15\",\n          defaultClassNames.range_middle\n        ),\n        range_start: cn(\n          \"rounded-l-md bg-primary/15\",\n          defaultClassNames.range_start\n        ),\n        root: cn(\"w-fit\", defaultClassNames.root),\n        today: cn(\n          \"rounded-md bg-foreground/10 font-medium text-foreground data-[selected=true]:rounded-none\",\n          defaultClassNames.today\n        ),\n        week: cn(\"mt-2 flex w-full\", defaultClassNames.week),\n        weekday: cn(\n          \"flex-1 select-none rounded-md font-normal text-[0.8rem] text-muted-foreground\",\n          defaultClassNames.weekday\n        ),\n        weekdays: cn(\"flex\", defaultClassNames.weekdays),\n        ...classNames,\n      }}\n      components={{\n        Chevron: CalendarChevron,\n        DayButton: CalendarDayButton,\n      }}\n      data-slot=\"calendar\"\n      showOutsideDays={showOutsideDays}\n      {...props}\n    />\n  );\n}\n","path":"index.tsx","target":"components/smoothui/calendar/index.tsx","type":"registry:ui"}],"name":"calendar","registryDependencies":["https://smoothui.dev/r/smooth-button.json"],"title":"Calendar","type":"registry:ui"}