{ "$schema": "https://blode.co/ui/schema/registry-item.json", "name": "calendar", "title": "Calendar", "author": "Matthew Blode", "description": "A date field component that allows users to pick dates.", "dependencies": ["react-day-picker@latest", "date-fns"], "registryDependencies": ["button"], "files": [ { "path": "ui/calendar.tsx", "content": "\"use client\";\n\nimport { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from \"blode-icons-react\";\nimport * as React from \"react\";\nimport { DayPicker, getDefaultClassNames } from \"react-day-picker\";\nimport type { DayButton, Locale } from \"react-day-picker\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Button, buttonVariants } from \"@/components/ui/button\";\n\nconst CalendarDayButton = ({\n className,\n day,\n modifiers,\n locale,\n ...props\n}: React.ComponentProps & { locale?: Partial }) => {\n const defaultClassNames = getDefaultClassNames();\n\n const ref = React.useRef(null);\n React.useEffect(() => {\n if (modifiers.focused) {\n ref.current?.focus();\n }\n }, [modifiers.focused]);\n\n return (\n span]:text-xs [&>span]:opacity-70\",\n defaultClassNames.day,\n className,\n )}\n data-day={day.date.toLocaleDateString(locale?.code ?? \"en-US\")}\n data-range-end={modifiers.range_end}\n data-range-middle={modifiers.range_middle}\n data-range-start={modifiers.range_start}\n data-selected-single={\n modifiers.selected &&\n !modifiers.range_start &&\n !modifiers.range_end &&\n !modifiers.range_middle\n }\n ref={ref}\n size=\"icon\"\n variant=\"ghost\"\n {...props}\n />\n );\n};\n\nconst Calendar = ({\n className,\n classNames,\n showOutsideDays = true,\n captionLayout = \"label\",\n buttonVariant = \"ghost\",\n locale,\n formatters,\n components,\n ...props\n}: React.ComponentProps & {\n buttonVariant?: React.ComponentProps[\"variant\"];\n}) => {\n const defaultClassNames = getDefaultClassNames();\n\n return (\n svg]:rotate-180`,\n String.raw`rtl:**:[.rdp-button\\_previous>svg]:rotate-180`,\n className,\n )}\n classNames={{\n button_next: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) select-none p-0 aria-disabled:opacity-50\",\n defaultClassNames.button_next,\n ),\n button_previous: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) select-none p-0 aria-disabled:opacity-50\",\n defaultClassNames.button_previous,\n ),\n caption_label: cn(\n \"select-none font-medium\",\n captionLayout === \"label\"\n ? \"text-sm\"\n : \"cn-calendar-caption-label flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground\",\n defaultClassNames.caption_label,\n ),\n day: cn(\n \"group/day relative aspect-square h-full w-full select-none rounded-(--cell-radius) p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)\",\n props.showWeekNumber\n ? \"[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)\"\n : \"[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)\",\n defaultClassNames.day,\n ),\n disabled: cn(\"text-muted-foreground opacity-50\", defaultClassNames.disabled),\n dropdown: cn(\"absolute inset-0 bg-popover opacity-0\", defaultClassNames.dropdown),\n dropdown_root: cn(\n \"cn-calendar-dropdown-root relative rounded-(--cell-radius)\",\n defaultClassNames.dropdown_root,\n ),\n dropdowns: cn(\n \"flex h-(--cell-size) w-full items-center justify-center gap-1.5 font-medium text-sm\",\n defaultClassNames.dropdowns,\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 month_grid: \"w-full border-collapse\",\n months: cn(\"relative flex flex-col gap-4 md:flex-row\", defaultClassNames.months),\n nav: cn(\n \"absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1\",\n defaultClassNames.nav,\n ),\n outside: cn(\n \"text-muted-foreground aria-selected:text-muted-foreground\",\n defaultClassNames.outside,\n ),\n range_end: cn(\n \"relative isolate z-0 rounded-r-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:left-0 after:w-4 after:bg-muted\",\n defaultClassNames.range_end,\n ),\n range_middle: cn(\"rounded-none\", defaultClassNames.range_middle),\n range_start: cn(\n \"relative isolate z-0 rounded-l-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:right-0 after:w-4 after:bg-muted\",\n defaultClassNames.range_start,\n ),\n root: cn(\"w-fit\", defaultClassNames.root),\n today: cn(\n \"rounded-(--cell-radius) bg-muted text-foreground data-[selected=true]:rounded-none\",\n defaultClassNames.today,\n ),\n week: cn(\"mt-2 flex w-full\", defaultClassNames.week),\n week_number: cn(\n \"select-none text-[0.8rem] text-muted-foreground\",\n defaultClassNames.week_number,\n ),\n week_number_header: cn(\"w-(--cell-size) select-none\", defaultClassNames.week_number_header),\n weekday: cn(\n \"flex-1 select-none rounded-(--cell-radius) font-normal text-[0.8rem] text-muted-foreground\",\n defaultClassNames.weekday,\n ),\n weekdays: cn(\"flex\", defaultClassNames.weekdays),\n ...classNames,\n }}\n components={{\n // react-day-picker requires render components passed via the `components` prop\n /* oxlint-disable react/no-unstable-nested-components */\n Chevron: ({ className: chevronClassName, orientation, ...chevronProps }) => {\n if (orientation === \"left\") {\n return (\n \n );\n }\n\n if (orientation === \"right\") {\n return (\n \n );\n }\n\n return ;\n },\n DayButton: ({ ...dayButtonProps }) => (\n \n ),\n Root: ({ className: rootClassName, rootRef, ...rootProps }) => (\n
\n ),\n WeekNumber: ({ children, ...weekNumberProps }) => (\n \n
\n {children}\n
\n \n ),\n /* oxlint-enable react/no-unstable-nested-components */\n ...components,\n }}\n formatters={{\n formatMonthDropdown: (date) =>\n date.toLocaleString(locale?.code ?? \"en-US\", { month: \"short\" }),\n ...formatters,\n }}\n locale={locale}\n showOutsideDays={showOutsideDays}\n {...props}\n />\n );\n};\n\nexport { Calendar, CalendarDayButton };\n", "type": "registry:ui", "target": "" } ], "type": "registry:ui" }