{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"event-calendar-month-view","type":"registry:ui","title":"ARIA-grid month view with week rows, day cells, event chips, and overflow counts.","description":"ARIA-grid month view with week rows, day cells, event chips, and overflow counts.","dependencies":["date-fns","radix-ui"],"registryDependencies":["@neui/event-calendar","@neui/event-calendar-dnd","@neui/event-calendar-event","@neui/event-calendar-lib","@neui/event-calendar-types","popover","scroll-area"],"files":[{"path":"event-calendar-month-view.tsx","type":"registry:ui","content":"// Title: Event Calendar Month View\n// Description: ARIA-grid month view with week rows, day cells, event chips, and overflow counts.\n\n\"use client\"\n\nimport {\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type HTMLAttributes,\n type Ref,\n} from \"react\"\nimport {\n EventCalendarViewContext,\n useEventCalendar,\n useEventCalendarDay,\n useEventCalendarSelector,\n useEventCalendarSettings,\n useEventCalendarViewConfig,\n useEventCalendarViewSettings,\n useEventCalendarWeek,\n} from \"@/components/neui/event-calendar/event-calendar\"\nimport {\n useEventCalendarGestures,\n wasRecentChipPress,\n wasRecentDrag,\n} from \"@/components/neui/event-calendar/event-calendar-dnd\"\nimport {\n EVENT_CALENDAR_GHOST,\n EventCalendarEvent,\n} from \"@/components/neui/event-calendar/event-calendar-event\"\nimport {\n getDayKey,\n getRangeKey,\n resolveOffDay,\n toZoned,\n zonedStartOfDay,\n} from \"@/components/neui/event-calendar/event-calendar-lib\"\nimport type {\n EventCalendarDateRange,\n EventCalendarDragState,\n EventCalendarEventId,\n EventCalendarSegment,\n} from \"@/components/neui/event-calendar/event-calendar-types\"\nimport { addDays, format, getWeek } from \"date-fns\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/components/ui/popover\"\nimport { ScrollArea } from \"@/components/ui/scroll-area\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\n// Layout-effect on the client (measure before paint, no flash), plain effect on\n// the server (never runs there) to avoid the SSR useLayoutEffect warning.\nconst useIsoLayoutEffect =\n typeof window !== \"undefined\" ? useLayoutEffect : useEffect\n\n// An occurrence key encodes the start instant and is also the chip's React key,\n// so committing a move re-keys the chip: React remounts it and the browser\n// drops focus to
. The chip that owns focus is recorded here so the cell\n// rendering its replacement can hand focus back. Module scope because the drop\n// can land in a different cell than the one the chip left, and only one element\n// holds focus at a time anyway.\nlet focusedChip: {\n node: HTMLElement\n eventId: EventCalendarEventId\n recurrenceIndex?: number\n} | null = null\n\n/** Give focus back to the recorded chip's replacement, if `root` renders it. */\nfunction restoreChipFocus(\n root: HTMLElement | null,\n segments: EventCalendarSegment[]\n) {\n const pending = focusedChip\n // Only a chip removed WHILE focused needs help: a node still in the tree, or\n // a focus that has already moved on by itself, is left alone.\n if (!root || !pending || pending.node.isConnected) return\n const active = document.activeElement\n if (active && active !== document.body) return\n const index = segments.findIndex(\n (segment) =>\n segment.occurrence.eventId === pending.eventId &&\n segment.occurrence.recurrenceIndex === pending.recurrenceIndex\n )\n if (index < 0) return\n const chip = root.querySelectorAll