{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"event-calendar-agenda-view","type":"registry:ui","title":"Chronological agenda grouped by day - a day header row plus a clean time / dot / title table.","description":"Chronological agenda grouped by day - a day header row plus a clean time / dot / title table.","dependencies":["date-fns","radix-ui"],"registryDependencies":["@neui/event-calendar","@neui/event-calendar-event","@neui/event-calendar-lib","@neui/event-calendar-types","@neui/icon-stack","scroll-area"],"files":[{"path":"event-calendar-agenda-view.tsx","type":"registry:ui","content":"// Title: Event Calendar Agenda View\n// Description: Chronological agenda grouped by day - a day header row plus a clean time / dot / title table.\n\n\"use client\"\n\nimport { useMemo, type HTMLAttributes } from \"react\"\nimport {\n EventCalendarViewContext,\n useEventCalendar,\n useEventCalendarSelector,\n useEventCalendarSettings,\n useEventCalendarViewConfig,\n} from \"@/components/neui/event-calendar/event-calendar\"\nimport { EventCalendarEvent } from \"@/components/neui/event-calendar/event-calendar-event\"\nimport {\n getDayKey,\n getRangeKey,\n toZoned,\n zonedStartOfDay,\n} from \"@/components/neui/event-calendar/event-calendar-lib\"\nimport type {\n EventCalendarDateRange,\n EventCalendarSegment,\n} from \"@/components/neui/event-calendar/event-calendar-types\"\nimport { IconStack } from \"@/components/neui/icon-stack\"\nimport { addDays, format } from \"date-fns\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ScrollArea } from \"@/components/ui/scroll-area\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\n// The agenda window length is the agendaDayCount SETTING (the store derives\n// visibleRange from it); a per-view prop here would silently disagree.\ninterface EventCalendarAgendaViewProps extends HTMLAttributes {\n asChild?: boolean\n}\n\nfunction EventCalendarAgendaView({\n className,\n asChild = false,\n ...props\n}: EventCalendarAgendaViewProps) {\n const instance = useEventCalendar()\n const settings = useEventCalendarSettings()\n const viewConfig = useEventCalendarViewConfig()\n const visibleRange = useEventCalendarSelector<\n unknown,\n EventCalendarDateRange\n >((state) => state.visibleRange, {\n isEqual: (a, b) => getRangeKey(a) === getRangeKey(b),\n })\n // Subscribe to event changes via the day-bucket content of the whole range\n useEventCalendarSelector((state) => state.events)\n\n const days = useMemo(() => {\n const result: Date[] = []\n let cursor = zonedStartOfDay(visibleRange.start, settings.timeZone)\n while (cursor < visibleRange.end) {\n result.push(cursor)\n cursor = zonedStartOfDay(\n addDays(toZoned(cursor, settings.timeZone), 1),\n settings.timeZone\n )\n }\n return result\n }, [visibleRange, settings.timeZone])\n\n const index = instance.internals.getIndex()\n const groups = days\n .map((day) => ({\n day,\n bucket: index.byDay.get(getDayKey(day, settings.timeZone)),\n }))\n .filter((group) => {\n const total =\n (group.bucket?.allDay.length ?? 0) + (group.bucket?.timed.length ?? 0)\n return total > 0\n })\n\n const isToday = (day: Date) =>\n getDayKey(day, settings.timeZone) ===\n getDayKey(new Date(), settings.timeZone)\n\n const native = viewConfig.scrollbars === \"native\"\n\n const body = (\n <>\n {groups.length === 0 ? (\n \n {viewConfig.renderNoEvents?.() ?? (\n <>\n \n \n \n \n {settings.i18n.labels.noEvents}\n \n \n )}\n \n ) : (\n // Drop the very last row's bottom border so it does not double up with\n // the calendar container's own bottom border. Targets the last day\n // group's last child (its last agenda item); per-item `border-b` is\n // kept everywhere else, including each day's internal rows.\n
*:last-child>*:last-child]:border-b-0\">\n {groups.map(({ day, bucket }) => {\n const items = [...(bucket?.allDay ?? []), ...(bucket?.timed ?? [])]\n const zoned = toZoned(day, settings.timeZone)\n const weekday = format(zoned, \"EEEE\", { locale: settings.locale })\n const dayDate = format(zoned, \"MMMM d, yyyy\", {\n locale: settings.locale,\n })\n return (\n \n {/* Group header: weekday (leading) + full date (trailing) */}\n \n \n {weekday}\n \n \n {dayDate}\n \n
\n {items.map((segment) => (\n \n ))}\n \n )\n })}\n \n )}\n \n )\n\n const Comp = asChild ? Slot.Root : \"div\"\n\n return (\n \n \n {native ? (\n \n {body}\n \n ) : (\n {body}\n )}\n \n \n )\n}\n\n/**\n * One agenda row: a full-width, selectable table row - time column, color dot,\n * and title (all replaceable via renderAgendaEvent). Clicking selects the\n * event (drag/resize stay off in the agenda).\n */\nfunction EventCalendarAgendaItem({\n segment,\n}: {\n segment: EventCalendarSegment\n}) {\n const viewConfig = useEventCalendarViewConfig()\n return (\n \n )\n}\n\nexport { EventCalendarAgendaView }\nexport type { EventCalendarAgendaViewProps }","target":"components/neui/event-calendar/event-calendar-agenda-view.tsx"}]}