@innosolutions/inno-calendar 1.0.72 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/LICENSE +48 -48
  3. package/README.md +333 -305
  4. package/dist/components/event/event-card.d.ts +4 -28
  5. package/dist/components/event/event-card.d.ts.map +1 -1
  6. package/dist/components/header/calendar-header.d.ts +14 -3
  7. package/dist/components/header/calendar-header.d.ts.map +1 -1
  8. package/dist/components/index.cjs +1 -1
  9. package/dist/components/index.d.ts +7 -6
  10. package/dist/components/index.d.ts.map +1 -1
  11. package/dist/components/index.mjs +48 -57
  12. package/dist/components/index.mjs.map +1 -1
  13. package/dist/components/inno-calendar.d.ts +139 -72
  14. package/dist/components/inno-calendar.d.ts.map +1 -1
  15. package/dist/components/primitives/field-layer.d.ts +22 -0
  16. package/dist/components/primitives/field-layer.d.ts.map +1 -0
  17. package/dist/components/primitives/index.d.ts +3 -0
  18. package/dist/components/primitives/index.d.ts.map +1 -1
  19. package/dist/components/primitives/multi-day-banner.d.ts.map +1 -1
  20. package/dist/components/primitives/quick-create.d.ts +44 -0
  21. package/dist/components/primitives/quick-create.d.ts.map +1 -0
  22. package/dist/components/primitives/recurrence-field.d.ts +102 -0
  23. package/dist/components/primitives/recurrence-field.d.ts.map +1 -0
  24. package/dist/components/primitives/week-all-day-row.d.ts.map +1 -1
  25. package/dist/components/primitives/when-row.d.ts +41 -0
  26. package/dist/components/primitives/when-row.d.ts.map +1 -0
  27. package/dist/components/shell/calendar-settings.d.ts +28 -0
  28. package/dist/components/shell/calendar-settings.d.ts.map +1 -0
  29. package/dist/components/shell/calendar-sidebar.d.ts +27 -0
  30. package/dist/components/shell/calendar-sidebar.d.ts.map +1 -0
  31. package/dist/components/shell/filter-panel.d.ts +10 -0
  32. package/dist/components/shell/filter-panel.d.ts.map +1 -0
  33. package/dist/components/shell/index.d.ts +5 -0
  34. package/dist/components/shell/index.d.ts.map +1 -0
  35. package/dist/components/shell/mini-month.d.ts +16 -0
  36. package/dist/components/shell/mini-month.d.ts.map +1 -0
  37. package/dist/components/ui/index.d.ts +0 -2
  38. package/dist/components/ui/index.d.ts.map +1 -1
  39. package/dist/components/views/agenda-view.d.ts +14 -15
  40. package/dist/components/views/agenda-view.d.ts.map +1 -1
  41. package/dist/components/views/day-events-expansion.d.ts +1 -1
  42. package/dist/components/views/day-events-expansion.d.ts.map +1 -1
  43. package/dist/components/views/day-view.d.ts +2 -6
  44. package/dist/components/views/day-view.d.ts.map +1 -1
  45. package/dist/components/views/index.d.ts +2 -1
  46. package/dist/components/views/index.d.ts.map +1 -1
  47. package/dist/components/views/month-view.d.ts +2 -12
  48. package/dist/components/views/month-view.d.ts.map +1 -1
  49. package/dist/components/views/resource-columns-view.d.ts +23 -0
  50. package/dist/components/views/resource-columns-view.d.ts.map +1 -0
  51. package/dist/components/views/timeline-view.d.ts +2 -6
  52. package/dist/components/views/timeline-view.d.ts.map +1 -1
  53. package/dist/components/views/week-view.d.ts +10 -6
  54. package/dist/components/views/week-view.d.ts.map +1 -1
  55. package/dist/components/views/year-view.d.ts +2 -6
  56. package/dist/components/views/year-view.d.ts.map +1 -1
  57. package/dist/core/constants.d.ts +39 -1
  58. package/dist/core/constants.d.ts.map +1 -1
  59. package/dist/core/context/drag-drop-context.d.ts +15 -1
  60. package/dist/core/context/drag-drop-context.d.ts.map +1 -1
  61. package/dist/core/context/event-card-context.d.ts +16 -0
  62. package/dist/core/context/event-card-context.d.ts.map +1 -0
  63. package/dist/core/context/inno-calendar-provider.d.ts +10 -1
  64. package/dist/core/context/inno-calendar-provider.d.ts.map +1 -1
  65. package/dist/core/context/slot-selection-context.d.ts +16 -0
  66. package/dist/core/context/slot-selection-context.d.ts.map +1 -1
  67. package/dist/core/index.cjs +1 -1
  68. package/dist/core/index.d.ts +3 -1
  69. package/dist/core/index.d.ts.map +1 -1
  70. package/dist/core/index.mjs +155 -149
  71. package/dist/core/index.mjs.map +1 -1
  72. package/dist/core/types.d.ts +44 -514
  73. package/dist/core/types.d.ts.map +1 -1
  74. package/dist/core/utils/date-input.d.ts +8 -0
  75. package/dist/core/utils/date-input.d.ts.map +1 -0
  76. package/dist/core/utils/grid-utils.d.ts.map +1 -1
  77. package/dist/core/utils/index.d.ts +1 -0
  78. package/dist/core/utils/index.d.ts.map +1 -1
  79. package/dist/core/utils/time-format.d.ts +33 -0
  80. package/dist/core/utils/time-format.d.ts.map +1 -0
  81. package/dist/core/utils/view-storage.d.ts +2 -2
  82. package/dist/core/utils/view-storage.d.ts.map +1 -1
  83. package/dist/core/z-layers.d.ts +21 -0
  84. package/dist/core/z-layers.d.ts.map +1 -0
  85. package/dist/index.cjs +1 -1
  86. package/dist/index.d.ts +0 -1
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.mjs +228 -234
  89. package/dist/index.mjs.map +1 -1
  90. package/dist/inno-calendar-DFEaWcSi.cjs +11 -0
  91. package/dist/inno-calendar-DFEaWcSi.cjs.map +1 -0
  92. package/dist/inno-calendar-R7LPGSJU.js +7454 -0
  93. package/dist/inno-calendar-R7LPGSJU.js.map +1 -0
  94. package/dist/lib/index.cjs +1 -1
  95. package/dist/lib/index.mjs +1 -1
  96. package/dist/position-utils-BH6T1FL5.js +1125 -0
  97. package/dist/position-utils-BH6T1FL5.js.map +1 -0
  98. package/dist/position-utils-BVt-Bp93.cjs +2 -0
  99. package/dist/position-utils-BVt-Bp93.cjs.map +1 -0
  100. package/dist/styles/index.css +1 -1
  101. package/dist/use-slot-selection-CSsSyfAi.cjs +2 -0
  102. package/dist/use-slot-selection-CSsSyfAi.cjs.map +1 -0
  103. package/dist/use-slot-selection-CT1z9v9X.js +357 -0
  104. package/dist/use-slot-selection-CT1z9v9X.js.map +1 -0
  105. package/dist/utils-B6yFEsav.js +9 -0
  106. package/dist/utils-B6yFEsav.js.map +1 -0
  107. package/dist/utils-IjLH3w2e.cjs +2 -0
  108. package/dist/utils-IjLH3w2e.cjs.map +1 -0
  109. package/dist/utils.cjs +1 -1
  110. package/dist/utils.d.ts +1 -1
  111. package/dist/utils.d.ts.map +1 -1
  112. package/dist/utils.mjs +108 -104
  113. package/dist/z-layers-CpHPAMdp.js +637 -0
  114. package/dist/z-layers-CpHPAMdp.js.map +1 -0
  115. package/dist/z-layers-D1DivrJg.cjs +2 -0
  116. package/dist/z-layers-D1DivrJg.cjs.map +1 -0
  117. package/package.json +117 -138
  118. package/AGENT.md +0 -1783
  119. package/dist/agenda-widget-B0t3TCcV.js +0 -4141
  120. package/dist/agenda-widget-B0t3TCcV.js.map +0 -1
  121. package/dist/agenda-widget-i2tjGr5U.cjs +0 -2
  122. package/dist/agenda-widget-i2tjGr5U.cjs.map +0 -1
  123. package/dist/components/calendar.d.ts +0 -45
  124. package/dist/components/calendar.d.ts.map +0 -1
  125. package/dist/components/event/event-page-transition.d.ts +0 -32
  126. package/dist/components/event/event-page-transition.d.ts.map +0 -1
  127. package/dist/components/filters/calendar-filter-sidebar.d.ts +0 -54
  128. package/dist/components/filters/calendar-filter-sidebar.d.ts.map +0 -1
  129. package/dist/components/filters/index.d.ts +0 -9
  130. package/dist/components/filters/index.d.ts.map +0 -1
  131. package/dist/components/filters/schedule-type-filter.d.ts +0 -31
  132. package/dist/components/filters/schedule-type-filter.d.ts.map +0 -1
  133. package/dist/components/filters/user-filter.d.ts +0 -31
  134. package/dist/components/filters/user-filter.d.ts.map +0 -1
  135. package/dist/components/header/components/index.d.ts +0 -8
  136. package/dist/components/header/components/index.d.ts.map +0 -1
  137. package/dist/components/integrated-calendar.d.ts +0 -37
  138. package/dist/components/integrated-calendar.d.ts.map +0 -1
  139. package/dist/components/settings/badge-variant-setting.d.ts +0 -25
  140. package/dist/components/settings/badge-variant-setting.d.ts.map +0 -1
  141. package/dist/components/settings/index.d.ts +0 -10
  142. package/dist/components/settings/index.d.ts.map +0 -1
  143. package/dist/components/settings/slot-duration-setting.d.ts +0 -20
  144. package/dist/components/settings/slot-duration-setting.d.ts.map +0 -1
  145. package/dist/components/settings/visible-hours-setting.d.ts +0 -23
  146. package/dist/components/settings/visible-hours-setting.d.ts.map +0 -1
  147. package/dist/components/settings/working-hours-setting.d.ts +0 -41
  148. package/dist/components/settings/working-hours-setting.d.ts.map +0 -1
  149. package/dist/components/ui/dialog.d.ts +0 -35
  150. package/dist/components/ui/dialog.d.ts.map +0 -1
  151. package/dist/components/ui/select.d.ts +0 -12
  152. package/dist/components/ui/select.d.ts.map +0 -1
  153. package/dist/components/widget/agenda-dropdown.d.ts +0 -20
  154. package/dist/components/widget/agenda-dropdown.d.ts.map +0 -1
  155. package/dist/components/widget/agenda-widget.d.ts +0 -27
  156. package/dist/components/widget/agenda-widget.d.ts.map +0 -1
  157. package/dist/components/widget/index.d.ts +0 -6
  158. package/dist/components/widget/index.d.ts.map +0 -1
  159. package/dist/index-D2U2F80P.cjs +0 -2
  160. package/dist/index-D2U2F80P.cjs.map +0 -1
  161. package/dist/index-DtaLkIY8.js +0 -2777
  162. package/dist/index-DtaLkIY8.js.map +0 -1
  163. package/dist/position-utils-D_KpwRus.js +0 -1053
  164. package/dist/position-utils-D_KpwRus.js.map +0 -1
  165. package/dist/position-utils-ksZ_IjXC.cjs +0 -2
  166. package/dist/position-utils-ksZ_IjXC.cjs.map +0 -1
  167. package/dist/presets/default/default-calendar.d.ts +0 -44
  168. package/dist/presets/default/default-calendar.d.ts.map +0 -1
  169. package/dist/presets/default/index.d.ts +0 -2
  170. package/dist/presets/default/index.d.ts.map +0 -1
  171. package/dist/presets/index.cjs +0 -2
  172. package/dist/presets/index.cjs.map +0 -1
  173. package/dist/presets/index.d.ts +0 -3
  174. package/dist/presets/index.d.ts.map +0 -1
  175. package/dist/presets/index.mjs +0 -6
  176. package/dist/presets/index.mjs.map +0 -1
  177. package/dist/presets/tailwind/index.d.ts +0 -2
  178. package/dist/presets/tailwind/index.d.ts.map +0 -1
  179. package/dist/presets/tailwind/tailwind-calendar.d.ts +0 -122
  180. package/dist/presets/tailwind/tailwind-calendar.d.ts.map +0 -1
  181. package/dist/slot-selection-context-CLYZU6ul.cjs +0 -2
  182. package/dist/slot-selection-context-CLYZU6ul.cjs.map +0 -1
  183. package/dist/slot-selection-context-Ct5cVcKW.js +0 -611
  184. package/dist/slot-selection-context-Ct5cVcKW.js.map +0 -1
  185. package/dist/tailwind-calendar-BbUb61uY.cjs +0 -2
  186. package/dist/tailwind-calendar-BbUb61uY.cjs.map +0 -1
  187. package/dist/tailwind-calendar-DrwGVSF-.js +0 -400
  188. package/dist/tailwind-calendar-DrwGVSF-.js.map +0 -1
  189. package/dist/use-calendar-BK0nQYJq.cjs +0 -2
  190. package/dist/use-calendar-BK0nQYJq.cjs.map +0 -1
  191. package/dist/use-calendar-DJI35SSd.js +0 -175
  192. package/dist/use-calendar-DJI35SSd.js.map +0 -1
  193. package/dist/use-slot-selection-CCE11R4j.cjs +0 -2
  194. package/dist/use-slot-selection-CCE11R4j.cjs.map +0 -1
  195. package/dist/use-slot-selection-CX1w8EdM.js +0 -188
  196. package/dist/use-slot-selection-CX1w8EdM.js.map +0 -1
  197. package/dist/week-view-BXmaRChB.cjs +0 -11
  198. package/dist/week-view-BXmaRChB.cjs.map +0 -1
  199. package/dist/week-view-BeasFcyR.js +0 -3520
  200. package/dist/week-view-BeasFcyR.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inno-calendar-DFEaWcSi.cjs","sources":["../src/core/context/event-card-context.tsx","../src/components/ui/popover.tsx","../src/components/ui/sheet.tsx","../src/components/ui/tooltip.tsx","../src/components/event/event-card.tsx","../src/components/ui/button.tsx","../src/components/ui/dropdown-menu.tsx","../src/components/event/event-popover.tsx","../src/components/shell/calendar-settings.tsx","../src/components/header/calendar-header.tsx","../src/components/ui/badge.tsx","../src/components/header/components/date-navigator.tsx","../src/components/header/components/today-button.tsx","../src/components/primitives/quick-create.tsx","../src/components/primitives/scroll-navigator.tsx","../src/components/shell/mini-month.tsx","../src/components/shell/calendar-sidebar.tsx","../src/components/shell/filter-panel.tsx","../src/components/views/agenda-view.tsx","../src/components/views/day-events-expansion.tsx","../src/components/primitives/multi-day-banner.tsx","../src/components/primitives/selectable-slot.tsx","../src/components/views/day-view.tsx","../src/components/views/month-view.tsx","../src/components/primitives/week-all-day-row.tsx","../src/components/primitives/field-layer.tsx","../src/components/primitives/recurrence-field.tsx","../src/components/primitives/when-row.tsx","../src/components/views/resource-columns-view.tsx","../src/components/views/timeline-view.tsx","../src/components/views/week-view.tsx","../src/components/views/year-view.tsx","../src/components/inno-calendar.tsx"],"sourcesContent":["/**\n * The consumer's event chip.\n *\n * A context rather than a prop threaded through five views: the chip is drawn\n * deep inside each grid, and passing a renderer down by hand would mean every\n * view knowing about it — and a new view forgetting to.\n *\n * What the consumer replaces is the chip's *content*. The shell around it —\n * positioned, draggable, resizable, keyboard-reachable, opening the popover on\n * click — stays the calendar's, because that is the part the grid has to agree\n * with. An app that owned it too would have to re-implement drag to keep it.\n */\n\nimport { createContext, type ReactNode, useContext } from 'react';\nimport type { CalendarEvent, TCalendarView } from '../types';\n\n/** Where the chip is being drawn, for a renderer that cares. */\nexport interface IEventCardArgs {\n\tview: TCalendarView;\n\t/** A month cell or a crowded column — usually one line, no detail. */\n\tcompact: boolean;\n}\n\nexport type TEventCardRenderer<TData = Record<string, unknown>> = (\n\tevent: CalendarEvent<TData>,\n\targs: IEventCardArgs\n) => ReactNode;\n\nconst EventCardContext = createContext<TEventCardRenderer<never> | null>(null);\n\nexport function EventCardProvider<TData>({\n\trender,\n\tchildren,\n}: {\n\trender: TEventCardRenderer<TData>;\n\tchildren: ReactNode;\n}) {\n\treturn (\n\t\t<EventCardContext.Provider value={render as TEventCardRenderer<never>}>\n\t\t\t{children}\n\t\t</EventCardContext.Provider>\n\t);\n}\n\n/** Null when the consumer passed no `eventCard` — draw the built-in chip. */\nexport function useOptionalEventCard<\n\tTData = Record<string, unknown>,\n>(): TEventCardRenderer<TData> | null {\n\treturn useContext(EventCardContext) as TEventCardRenderer<TData> | null;\n}\n","import * as PopoverPrimitive from '@radix-ui/react-popover';\nimport * as React from 'react';\n\nimport { cn } from '../../lib/utils';\n\nconst Popover = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\n\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nconst PopoverContent = React.forwardRef<\n\tReact.ElementRef<typeof PopoverPrimitive.Content>,\n\tReact.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (\n\t<PopoverPrimitive.Portal>\n\t\t<PopoverPrimitive.Content\n\t\t\tref={ref}\n\t\t\talign={align}\n\t\t\tsideOffset={sideOffset}\n\t\t\tclassName={cn(\n\t\t\t\t'z-50 w-72 rounded-xl border bg-white text-popover-foreground outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t</PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };\n","/**\n * Sheet — Radix Dialog-based slide-in panel (shadcn-style).\n *\n * A slide-in panel that appears from the right edge of the screen.\n * Built on `@radix-ui/react-dialog` (optional peer dependency).\n *\n * @example\n * ```tsx\n * <Sheet open={open} onOpenChange={setOpen}>\n * <SheetTrigger asChild><button>Open</button></SheetTrigger>\n * <SheetContent>\n * <SheetHeader>\n * <SheetTitle>Title</SheetTitle>\n * </SheetHeader>\n * <p>Body content</p>\n * </SheetContent>\n * </Sheet>\n * ```\n */\n\nimport * as SheetPrimitive from '@radix-ui/react-dialog';\nimport { X } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '../../lib/utils';\n\nconst Sheet = SheetPrimitive.Root;\n\nconst SheetTrigger = SheetPrimitive.Trigger;\n\nconst SheetClose = SheetPrimitive.Close;\n\nconst SheetPortal = SheetPrimitive.Portal;\n\nconst SheetOverlay = React.forwardRef<\n\tReact.ElementRef<typeof SheetPrimitive.Overlay>,\n\tReact.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Overlay\n\t\tclassName={cn(\n\t\t\t'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t\tref={ref}\n\t/>\n));\nSheetOverlay.displayName = SheetPrimitive.Overlay.displayName;\n\nconst SheetContent = React.forwardRef<\n\tReact.ElementRef<typeof SheetPrimitive.Content>,\n\tReact.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n\t<SheetPortal>\n\t\t<SheetOverlay />\n\t\t<SheetPrimitive.Content\n\t\t\tref={ref}\n\t\t\tclassName={cn(\n\t\t\t\t'fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500',\n\t\t\t\t// Right-side slide\n\t\t\t\t'inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right',\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t<SheetPrimitive.Close className=\"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary\">\n\t\t\t\t<X className=\"size-4\" />\n\t\t\t\t<span className=\"sr-only\">Close</span>\n\t\t\t</SheetPrimitive.Close>\n\t\t</SheetPrimitive.Content>\n\t</SheetPortal>\n));\nSheetContent.displayName = 'SheetContent';\n\nconst SheetHeader = ({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n\t<div\n\t\tclassName={cn('flex flex-col space-y-2 text-center sm:text-left', className)}\n\t\t{...props}\n\t/>\n);\nSheetHeader.displayName = 'SheetHeader';\n\nconst SheetTitle = React.forwardRef<\n\tReact.ElementRef<typeof SheetPrimitive.Title>,\n\tReact.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Title\n\t\tref={ref}\n\t\tclassName={cn('text-lg font-semibold text-foreground', className)}\n\t\t{...props}\n\t/>\n));\nSheetTitle.displayName = SheetPrimitive.Title.displayName;\n\nconst SheetDescription = React.forwardRef<\n\tReact.ElementRef<typeof SheetPrimitive.Description>,\n\tReact.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Description\n\t\tref={ref}\n\t\tclassName={cn('text-sm text-muted-foreground', className)}\n\t\t{...props}\n\t/>\n));\nSheetDescription.displayName = SheetPrimitive.Description.displayName;\n\nexport {\n\tSheet,\n\tSheetClose,\n\tSheetContent,\n\tSheetDescription,\n\tSheetHeader,\n\tSheetOverlay,\n\tSheetPortal,\n\tSheetTitle,\n\tSheetTrigger,\n};\n","import * as TooltipPrimitive from '@radix-ui/react-tooltip';\nimport * as React from 'react';\n\nimport { cn } from '../../lib/utils';\n\nconst TooltipProvider = TooltipPrimitive.Provider;\n\nconst Tooltip = TooltipPrimitive.Root;\n\nconst TooltipTrigger = TooltipPrimitive.Trigger;\n\nconst TooltipContent = React.forwardRef<\n\tReact.ElementRef<typeof TooltipPrimitive.Content>,\n\tReact.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n\t<TooltipPrimitive.Content\n\t\tref={ref}\n\t\tsideOffset={sideOffset}\n\t\tclassName={cn(\n\t\t\t'z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n\t\t\tclassName\n\t\t)}\n\t\t{...props}\n\t/>\n));\nTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\n","/**\n * Event Card Component\n *\n * A versatile event display component with multiple variants:\n * - full: Full card with all details (for day/week views)\n * - compact: Compact single-line (for month view cells)\n * - dot: Dot indicator only (for mini calendars)\n *\n * Supports badge variants:\n * - colored: Full colored background\n * - dot: Neutral background with colored dot\n * - mixed: Colored background with dot\n *\n * Styling matches agenda-v2 production design:\n * - Soft backgrounds with dark mode support\n * - Colored borders and text for better readability\n * - SVG dots with fill classes\n * - Canceled event states\n * - Drag & drop support for event repositioning\n *\n * @template TData - Custom event data type\n */\n\nimport {\n\ttype CSSProperties,\n\ttype ReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport { CANCELED_CHIP, COMPACT_WIDTH, DEFAULT_HOUR_HEIGHT, PORTALLED } from '../../core/constants';\nimport { useOptionalDragDrop, useOptionalInnoCalendar } from '../../core/context';\nimport { useOptionalEventCard } from '../../core/context/event-card-context';\nimport type { CalendarEvent, TBadgeVariant, TEventColor } from '../../core/types';\nimport { formatEventTimeDisplay } from '../../core/utils/event-utils';\nimport { reactNodeToText } from '../../core/utils/react-node-utils';\nimport { formatClockCompact } from '../../core/utils/time-format';\nimport { cn } from '../../lib/utils';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { Sheet, SheetContent, SheetTitle, SheetTrigger } from '../ui/sheet';\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/tooltip';\n\nconst DETAIL_LABEL = 'Event details';\n\n/** Tracks the one width at which floating surfaces stop floating. */\nfunction useCompact() {\n\tconst [compact, setCompact] = useState(\n\t\ttypeof window !== 'undefined' && window.innerWidth < COMPACT_WIDTH\n\t);\n\tuseEffect(() => {\n\t\tconst onResize = () => setCompact(window.innerWidth < COMPACT_WIDTH);\n\t\twindow.addEventListener('resize', onResize);\n\t\treturn () => window.removeEventListener('resize', onResize);\n\t}, []);\n\treturn compact;\n}\n\n/** Radix dispatches these on the element that was actually hit, so `closest`\n * is enough to tell a portalled child of the card from a real outside. */\nconst keepOpenForPortalled = (event: {\n\ttarget: EventTarget | null;\n\tpreventDefault: () => void;\n}) => {\n\tif ((event.target as Element | null)?.closest?.(PORTALLED)) {\n\t\tevent.preventDefault();\n\t}\n};\n\n/**\n * The detail popover, however the event happens to be drawn.\n *\n * Declared once because there were three copies at two different widths, and\n * only one of them capped its height or survived a dialog opening on top of it\n * — so the same card ran off the screen from a week block but not from a\n * month cell.\n */\nfunction DetailPopover({\n\topen,\n\tonOpenChange,\n\ttrigger,\n\tchildren,\n}: {\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\ttrigger: ReactNode;\n\tchildren: ReactNode;\n}) {\n\t// A popover positions itself with a transform on a wrapper it owns, so a card\n\t// wider than the space beside the event has nowhere to be put: flipping sides\n\t// only changes which half falls off the screen, and no breakpoint fixes that.\n\t// Narrow viewports get a sheet instead, which portals to the body and owns\n\t// the whole width — the same thing the event form does.\n\tconst compact = useCompact();\n\n\tif (compact) {\n\t\treturn (\n\t\t\t<Sheet open={open} onOpenChange={onOpenChange}>\n\t\t\t\t<SheetTrigger asChild>{trigger}</SheetTrigger>\n\t\t\t\t<SheetContent\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'inset-x-0 inset-y-auto bottom-0 flex h-auto max-h-[85dvh] w-full',\n\t\t\t\t\t\t'max-w-none flex-col rounded-t-xl border-l-0 border-t p-0',\n\t\t\t\t\t\t'data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<SheetTitle className=\"sr-only\">{DETAIL_LABEL}</SheetTitle>\n\t\t\t\t\t{children}\n\t\t\t\t</SheetContent>\n\t\t\t</Sheet>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Popover open={open} onOpenChange={onOpenChange}>\n\t\t\t<PopoverTrigger asChild>{trigger}</PopoverTrigger>\n\t\t\t<PopoverContent\n\t\t\t\t// Beside the event and aligned to its top, the way Google does it. The\n\t\t\t\t// default — bottom, centred — is measured against the trigger, so an\n\t\t\t\t// all-day block puts the card hundreds of pixels down the page and\n\t\t\t\t// often off it.\n\t\t\t\tside=\"right\"\n\t\t\t\talign=\"start\"\n\t\t\t\tsideOffset={8}\n\t\t\t\tcollisionPadding={12}\n\t\t\t\t// Radix calls anything outside this node \"outside\", including the\n\t\t\t\t// confirmation a Delete inside the card opens: it takes focus as it\n\t\t\t\t// mounts, and the card was dismissed underneath it before the request\n\t\t\t\t// was ever sent — taking its `onSuccess` with it.\n\t\t\t\tonFocusOutside={keepOpenForPortalled}\n\t\t\t\tonPointerDownOutside={keepOpenForPortalled}\n\t\t\t\t// Capped to the room Radix measured between the trigger and the edge of\n\t\t\t\t// the viewport, and a column so the content can pin a footer and scroll\n\t\t\t\t// the rest — the same shape the event form uses.\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex max-h-[var(--radix-popover-content-available-height)] w-96',\n\t\t\t\t\t'max-w-[calc(100vw-1.5rem)] flex-col overflow-hidden p-0'\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n\n// ============================================================================\n// COLOR UTILITIES (matches agenda-v2 transformers.ts)\n// ============================================================================\n\n/**\n * Get color classes for an event - matches agenda-v2 styling\n * Uses soft backgrounds with darker text for better readability\n */\n/**\n * Google's inline time on a one-line chip: the start only, minutes dropped when\n * they are zero — \"10am\", \"9:30am\".\n */\nfunction compactStart(date: Date, locale?: string): string {\n\treturn formatClockCompact(date, { locale });\n}\n\nexport function getEventColorClasses(color?: TEventColor): {\n\tbg: string;\n\ttext: string;\n\tdot: string;\n\tdotFill: string;\n\tborder: string;\n} {\n\tconst colorMap: Record<\n\t\tTEventColor,\n\t\t{\n\t\t\tbg: string;\n\t\t\ttext: string;\n\t\t\tdot: string;\n\t\t\tdotFill: string;\n\t\t\tborder: string;\n\t\t}\n\t> = {\n\t\tblue: {\n\t\t\tbg: 'bg-blue-50 dark:bg-blue-950/30',\n\t\t\ttext: 'text-blue-700 dark:text-blue-300',\n\t\t\tdot: 'bg-blue-500',\n\t\t\tdotFill: 'fill-blue-600 dark:fill-blue-500',\n\t\t\tborder: 'border-blue-400 dark:border-blue-600',\n\t\t},\n\t\tgreen: {\n\t\t\tbg: 'bg-green-50 dark:bg-green-950/30',\n\t\t\ttext: 'text-green-700 dark:text-green-300',\n\t\t\tdot: 'bg-green-500',\n\t\t\tdotFill: 'fill-green-600 dark:fill-green-500',\n\t\t\tborder: 'border-green-400 dark:border-green-600',\n\t\t},\n\t\tred: {\n\t\t\tbg: 'bg-red-50 dark:bg-red-950/30',\n\t\t\ttext: 'text-red-700 dark:text-red-300',\n\t\t\tdot: 'bg-red-500',\n\t\t\tdotFill: 'fill-red-600 dark:fill-red-500',\n\t\t\tborder: 'border-red-400 dark:border-red-600',\n\t\t},\n\t\tyellow: {\n\t\t\tbg: 'bg-yellow-50 dark:bg-yellow-950/30',\n\t\t\ttext: 'text-yellow-700 dark:text-yellow-300',\n\t\t\tdot: 'bg-yellow-500',\n\t\t\tdotFill: 'fill-yellow-600 dark:fill-yellow-500',\n\t\t\tborder: 'border-yellow-400 dark:border-yellow-600',\n\t\t},\n\t\tpurple: {\n\t\t\tbg: 'bg-purple-50 dark:bg-purple-950/30',\n\t\t\ttext: 'text-purple-700 dark:text-purple-300',\n\t\t\tdot: 'bg-purple-500',\n\t\t\tdotFill: 'fill-purple-600 dark:fill-purple-500',\n\t\t\tborder: 'border-purple-400 dark:border-purple-600',\n\t\t},\n\t\torange: {\n\t\t\tbg: 'bg-orange-50 dark:bg-orange-950/30',\n\t\t\ttext: 'text-orange-700 dark:text-orange-300',\n\t\t\tdot: 'bg-orange-500',\n\t\t\tdotFill: 'fill-orange-600 dark:fill-orange-500',\n\t\t\tborder: 'border-orange-400 dark:border-orange-600',\n\t\t},\n\t\tpink: {\n\t\t\tbg: 'bg-pink-50 dark:bg-pink-950/30',\n\t\t\ttext: 'text-pink-700 dark:text-pink-300',\n\t\t\tdot: 'bg-pink-500',\n\t\t\tdotFill: 'fill-pink-600 dark:fill-pink-500',\n\t\t\tborder: 'border-pink-400 dark:border-pink-600',\n\t\t},\n\t\tteal: {\n\t\t\tbg: 'bg-teal-50 dark:bg-teal-950/30',\n\t\t\ttext: 'text-teal-700 dark:text-teal-300',\n\t\t\tdot: 'bg-teal-500',\n\t\t\tdotFill: 'fill-teal-600 dark:fill-teal-500',\n\t\t\tborder: 'border-teal-400 dark:border-teal-600',\n\t\t},\n\t\tgray: {\n\t\t\tbg: 'bg-gray-50 dark:bg-gray-950/30',\n\t\t\ttext: 'text-gray-700 dark:text-gray-300',\n\t\t\tdot: 'bg-gray-500',\n\t\t\tdotFill: 'fill-gray-600 dark:fill-gray-500',\n\t\t\tborder: 'border-gray-400 dark:border-gray-600',\n\t\t},\n\t\tindigo: {\n\t\t\tbg: 'bg-indigo-50 dark:bg-indigo-950/30',\n\t\t\ttext: 'text-indigo-700 dark:text-indigo-300',\n\t\t\tdot: 'bg-indigo-500',\n\t\t\tdotFill: 'fill-indigo-600 dark:fill-indigo-500',\n\t\t\tborder: 'border-indigo-400 dark:border-indigo-600',\n\t\t},\n\t};\n\n\treturn colorMap[color ?? 'blue'];\n}\n\n// ============================================================================\n// TIME FORMATTING\n// ============================================================================\n\n/**\n * Check if a date is at the start of today (past detection)\n */\nfunction startOfDay(date: Date): Date {\n\tconst d = new Date(date);\n\td.setHours(0, 0, 0, 0);\n\treturn d;\n}\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * Props for the {@link EventCard} component.\n *\n * @template TData - Consumer's custom data type on the event\n *\n * @example\n * ```tsx\n * <EventCard\n * event={myEvent}\n * variant=\"full\"\n * badgeVariant=\"colored\"\n * renderPopover={({ event, onClose }) => <MyPopover event={event} onClose={onClose} />}\n * />\n * ```\n */\nexport interface EventCardProps<TData = Record<string, unknown>> {\n\t/** The calendar event to render */\n\tevent: CalendarEvent<TData>;\n\t/**\n\t * Visual variant controlling the card's layout:\n\t * - `'full'` — Bordered card with title, time, type, location (day/week views)\n\t * - `'compact'` — Single-line with marquee title and time pill (month view)\n\t * - `'dot'` — Colored circle indicator (mini calendars)\n\t *\n\t * @default 'full'\n\t */\n\tvariant?: 'full' | 'compact' | 'dot';\n\t/**\n\t * Badge coloring mode:\n\t * - `'colored'` — Full colored background matching event color\n\t * - `'dot'` — Neutral background with a small colored dot\n\t * - `'mixed'` — Colored background **and** dot indicator\n\t *\n\t * @default 'colored'\n\t */\n\tbadgeVariant?: TBadgeVariant;\n\t/** Called when the event is clicked (only fires when `disablePopover` is `true`) */\n\tonClick?: ((event: CalendarEvent<TData>) => void) | undefined;\n\t/** Additional CSS classes merged onto the root element */\n\tclassName?: string;\n\t/** Whether to display the time range. @default true */\n\tshowTime?: boolean;\n\t/** Whether to display the event description. @default false */\n\tshowDescription?: boolean;\n\t/** Whether to display participant count. @default false */\n\tshowParticipants?: boolean;\n\t/** Inline styles forwarded to the root element (used for grid positioning) */\n\tstyle?: CSSProperties;\n\t/**\n\t * When `true`, clicking opens no built-in popover — instead `onClick` fires.\n\t * Use this when you handle event details externally (e.g. a dialog/drawer).\n\t *\n\t * @default false\n\t */\n\tdisablePopover?: boolean;\n\t/**\n\t * Custom popover content rendered inside the built-in Radix popover shell.\n\t * Receives the event and an `onClose` callback. When omitted the package's\n\t * default {@link EventPopoverContent} is shown.\n\t *\n\t * @example\n\t * ```tsx\n\t * renderPopover={({ event, onClose }) => (\n\t * <MyCustomPopover event={event} onClose={onClose} />\n\t * )}\n\t * ```\n\t */\n\trenderPopover?:\n\t\t| ((props: { event: CalendarEvent<TData>; onClose: () => void }) => ReactNode)\n\t\t| undefined;\n\t/**\n\t * Enable native HTML5 drag on this card for event repositioning.\n\t * Requires the calendar to be wrapped in a {@link DragDropProvider}.\n\t *\n\t * @default false\n\t */\n\tenableDrag?: boolean;\n\t/**\n\t * Enable page transition effect when clicking the event.\n\t * Creates an expanding overlay that fills the screen with the event's color.\n\t *\n\t * @default false\n\t */\n\tenablePageTransition?: boolean;\n\t/**\n\t * Duration of the page transition in milliseconds.\n\t * Only used when `enablePageTransition` is `true`.\n\t *\n\t * @default 400\n\t */\n\tpageTransitionDuration?: number;\n\n\t/**\n\t * How event details are displayed when the user clicks this card.\n\t *\n\t * - `'popover'` — (Default) Radix popover anchored to the card\n\t * - `'dialog'` — Centered modal dialog overlay\n\t * - `'sheet'` — Slide-in side panel from the right\n\t * - `'custom'` — No built-in container; uses `renderEventDetail` callback\n\t *\n\t * @default 'popover'\n\t */\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function EventCard<TData = Record<string, unknown>>({\n\tevent,\n\tvariant = 'full',\n\tbadgeVariant = 'colored',\n\tonClick,\n\tclassName,\n\tshowTime = true,\n\tshowDescription = false,\n\tshowParticipants = false,\n\tstyle,\n\tdisablePopover = false,\n\trenderPopover,\n\tenableDrag = false,\n\tenablePageTransition = false,\n\tpageTransitionDuration: _pageTransitionDuration = 400,\n}: EventCardProps<TData>) {\n\tconst colors = getEventColorClasses(event.color);\n\tconst [popoverOpen, setPopoverOpen] = useState(false);\n\tconst [isDragging, setIsDragging] = useState(false);\n\tconst [_transitionActive, setTransitionActive] = useState(false);\n\tconst [_transitionRect, setTransitionRect] = useState<DOMRect | null>(null);\n\tconst cardRef = useRef<HTMLButtonElement>(null);\n\n\t// Get drag-drop context\n\tconst dragDrop = useOptionalDragDrop();\n\n\t// Auto-open popover when this event matches focusEventId from context\n\tconst calendarCtx = useOptionalInnoCalendar();\n\tuseEffect(() => {\n\t\tif (!disablePopover && calendarCtx?.focusEventId && calendarCtx.focusEventId === event.id) {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsetPopoverOpen(true);\n\t\t\t\tcalendarCtx.clearFocusEventId();\n\t\t\t}, 300);\n\t\t\treturn () => clearTimeout(timer);\n\t\t}\n\t}, [calendarCtx?.focusEventId, event.id, disablePopover]);\n\n\t// Check if event is in the past (ended before start of today)\n\tconst isPast = event.endDate < startOfDay(new Date());\n\n\t// Check if event is canceled\n\tconst isCanceled = event.isCanceled ?? false;\n\n\t// Don't allow dragging for cancelled or past events\n\tconst canDrag = enableDrag && dragDrop && !isCanceled && !isPast;\n\n\t// Extract rich data from event.data for display\n\t// Reads from event.data first (recommended), then falls back to\n\t// deprecated top-level fields for backward compatibility.\n\tconst eventCardData = event.data as Record<string, unknown> | undefined;\n\tconst cardMeetingTookPlace =\n\t\t(eventCardData?.meetingTookPlace as boolean | undefined) ?? event.meetingTookPlace ?? false;\n\n\t// Status icons (matches agenda-v2)\n\tconst statusIcon = isCanceled ? (\n\t\t<XIcon className=\"h-3 w-3 text-zinc-800 dark:text-zinc-200\" />\n\t) : cardMeetingTookPlace ? (\n\t\t<CheckIcon className={cn('h-3 w-3', colors.text)} />\n\t) : null;\n\n\tconst cardProductName = eventCardData?.productName as ReactNode | undefined;\n\tconst cardExtendedProps = eventCardData?.extendedProps as ReactNode[] | undefined;\n\tconst cardNrParticipant = eventCardData?.nrParticipant as number | undefined;\n\tconst cardSiteName = eventCardData?.siteName as ReactNode | undefined;\n\tconst cardSiteCity = eventCardData?.siteCity as ReactNode | undefined;\n\tconst hasLocation = !!cardSiteName || !!cardSiteCity;\n\n\t// Handle click\n\tconst handleClick = useCallback(() => {\n\t\tif (isDragging) return; // Don't open popover during drag\n\t\tif (disablePopover && onClick) {\n\t\t\tonClick(event);\n\t\t\treturn;\n\t\t}\n\n\t\tif (enablePageTransition && cardRef.current) {\n\t\t\t// Start page transition\n\t\t\tconst rect = cardRef.current.getBoundingClientRect();\n\t\t\tsetTransitionRect(rect);\n\t\t\tsetTransitionActive(true);\n\t\t} else if (!disablePopover) {\n\t\t\tsetPopoverOpen(true);\n\t\t}\n\t}, [isDragging, disablePopover, onClick, event, enablePageTransition]);\n\n\t// Handle transition complete - open popover after animation\n\t// @ts-expect-error -- transition scaffolding for future page-transition feature\n\tconst _handleTransitionComplete = useCallback(() => {\n\t\tsetTransitionActive(false);\n\t\tsetTransitionRect(null);\n\t\tif (!disablePopover) {\n\t\t\tsetPopoverOpen(true);\n\t\t}\n\t}, [disablePopover]);\n\n\t// Handle popover close\n\tconst handleClose = useCallback(() => {\n\t\tsetPopoverOpen(false);\n\t}, []);\n\n\t// Drag handlers (matches agenda-v2)\n\tconst handleDragStart = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\tif (!canDrag) return;\n\t\t\te.dataTransfer.effectAllowed = 'move';\n\t\t\te.dataTransfer.setData('text/plain', event.id);\n\t\t\tsetIsDragging(true);\n\t\t\tdragDrop?.startDrag?.(event);\n\t\t},\n\t\t[canDrag, event, dragDrop]\n\t);\n\n\tconst handleDragEnd = useCallback(() => {\n\t\tsetIsDragging(false);\n\t\tif (dragDrop?.isDragging) {\n\t\t\tdragDrop.endDrag?.();\n\t\t}\n\t}, [dragDrop]);\n\n\t// ========================================================================\n\t// EVENT DETAIL WRAPPER — the popover, beside the event\n\t// ========================================================================\n\n\t/** Resolved content to display inside whichever container (popover/dialog/sheet) */\n\t// No fallback card: `eventDetail` is what a detail *is*, and a built-in one\n\t// that nobody has ever seen is a second layout to keep working.\n\tconst detailContent = renderPopover?.({ event, onClose: handleClose });\n\n\t/**\n\t * Wraps a trigger element with the appropriate detail container.\n\t */\n\tconst wrapWithDetail = (trigger: ReactNode): ReactNode => (\n\t\t<DetailPopover open={popoverOpen} onOpenChange={setPopoverOpen} trigger={trigger}>\n\t\t\t<div className={cn('flex min-h-0 flex-1 flex-col', !renderPopover && 'p-4')}>\n\t\t\t\t{detailContent}\n\t\t\t</div>\n\t\t</DetailPopover>\n\t);\n\n\t// ========================================================================\n\t// DOT VARIANT\n\t// ========================================================================\n\n\tif (variant === 'dot') {\n\t\tconst dotButton = (\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={handleClick}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'size-2 rounded-full cursor-pointer transition-opacity',\n\t\t\t\t\tcolors.dot,\n\t\t\t\t\tevent.isCanceled && 'opacity-50',\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\tstyle={style}\n\t\t\t\taria-label={reactNodeToText(event.title)}\n\t\t\t/>\n\t\t);\n\n\t\tif (disablePopover) {\n\t\t\treturn (\n\t\t\t\t<TooltipProvider delayDuration={300}>\n\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t<TooltipTrigger asChild>{dotButton}</TooltipTrigger>\n\t\t\t\t\t\t<TooltipContent>\n\t\t\t\t\t\t\t<div className=\"flex flex-col gap-0.5\">\n\t\t\t\t\t\t\t\t<div className=\"font-medium\">{event.title}</div>\n\t\t\t\t\t\t\t\t<div className=\"text-xs opacity-80\">{formatEventTimeDisplay(event)}</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t</Tooltip>\n\t\t\t\t</TooltipProvider>\n\t\t\t);\n\t\t}\n\n\t\treturn wrapWithDetail(\n\t\t\t<TooltipProvider delayDuration={300}>\n\t\t\t\t<Tooltip>\n\t\t\t\t\t<TooltipTrigger asChild>{dotButton}</TooltipTrigger>\n\t\t\t\t\t<TooltipContent>\n\t\t\t\t\t\t<div className=\"font-medium\">{event.title}</div>\n\t\t\t\t\t</TooltipContent>\n\t\t\t\t</Tooltip>\n\t\t\t</TooltipProvider>\n\t\t);\n\t}\n\n\t// ========================================================================\n\t// COMPACT VARIANT (matches agenda-v2 - marquee title, time pill, drag support)\n\t// ========================================================================\n\n\tif (variant === 'compact') {\n\t\tconst compactContent = (\n\t\t\t<div\n\t\t\t\trole=\"button\"\n\t\t\t\ttabIndex={0}\n\t\t\t\tdraggable={!!canDrag}\n\t\t\t\tonDragStart={handleDragStart}\n\t\t\t\tonDragEnd={handleDragEnd}\n\t\t\t\tonClick={disablePopover ? handleClick : undefined}\n\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\tif (e.key === 'Enter' || e.key === ' ') {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\thandleClick();\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'group flex w-full relative items-center shadow-[0_0_1px_rgba(0,0,0,0.3)] gap-0 rounded px-1.5 py-1 text-left text-xs transition-colors hover:opacity-80',\n\t\t\t\t\tcanDrag ? 'cursor-grab active:cursor-grabbing' : 'cursor-pointer',\n\t\t\t\t\tisDragging && 'opacity-50',\n\t\t\t\t\t// Cancelled events wear the shared graphic code instead of a colour\n\t\t\t\t\tisCanceled\n\t\t\t\t\t\t? CANCELED_CHIP\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\tbadgeVariant === 'colored' && [colors.bg, colors.text],\n\t\t\t\t\t\t\t\tbadgeVariant === 'mixed' && [colors.bg, colors.text],\n\t\t\t\t\t\t\t\tbadgeVariant === 'dot' && 'bg-muted/50',\n\t\t\t\t\t\t\t],\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\tstyle={style}\n\t\t\t>\n\t\t\t\t{/* Colored dot for dot/mixed variants (matches agenda-v2 - no isCanceled check) */}\n\t\t\t\t{['dot', 'mixed'].includes(badgeVariant) && !isCanceled && (\n\t\t\t\t\t<svg\n\t\t\t\t\t\twidth=\"8\"\n\t\t\t\t\t\theight=\"8\"\n\t\t\t\t\t\tviewBox=\"0 0 8 8\"\n\t\t\t\t\t\tclassName=\"event-dot absolute -top-1 -left-1 shrink-0\"\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tfocusable=\"false\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<circle cx=\"4\" cy=\"4\" r=\"4\" className={colors.dotFill} />\n\t\t\t\t\t</svg>\n\t\t\t\t)}\n\n\t\t\t\t{/* Title with marquee effect */}\n\t\t\t\t<span className=\"flex-1 min-w-0 overflow-hidden\">\n\t\t\t\t\t<span className=\"\">\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclassName=\"relative block overflow-hidden whitespace-nowrap text-xs leading-tight\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tmaskImage:\n\t\t\t\t\t\t\t\t\t'linear-gradient(to right, transparent 0, black 8px, black calc(100% - 8px), transparent 100%)',\n\t\t\t\t\t\t\t\tWebkitMaskImage:\n\t\t\t\t\t\t\t\t\t'linear-gradient(to right, transparent 0, black 8px, black calc(100% - 8px), transparent 100%)',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span className=\"inline-flex event-marquee\">\n\t\t\t\t\t\t\t\t<span className=\"shrink-0 px-1\">{event.title}</span>\n\t\t\t\t\t\t\t\t<span className=\"shrink-0 px-1\">•</span>\n\t\t\t\t\t\t\t\t<span aria-hidden=\"true\" className=\"shrink-0 px-1\">\n\t\t\t\t\t\t\t\t\t{event.title}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<span aria-hidden=\"true\" className=\"shrink-0 px-1\">\n\t\t\t\t\t\t\t\t\t•\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t{/* Time pill with dashed border - shows \"All day\" for all-day events */}\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'w-fit mt-0.5 text-[10px] px-1 py-0.5 border border-dashed rounded-full font-medium',\n\t\t\t\t\t\t\t\tcolors.border\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{formatEventTimeDisplay(event)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</span>\n\t\t\t\t</span>\n\t\t\t\t{/* Status icon on right (matches agenda-v2) */}\n\t\t\t\t<div className=\"flex gap-0.5\">{statusIcon}</div>\n\t\t\t</div>\n\t\t);\n\n\t\tif (disablePopover) {\n\t\t\treturn (\n\t\t\t\t<TooltipProvider delayDuration={300}>\n\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t<TooltipTrigger asChild>{compactContent}</TooltipTrigger>\n\t\t\t\t\t\t<TooltipContent>\n\t\t\t\t\t\t\t<div className=\"flex flex-col gap-0.5\">\n\t\t\t\t\t\t\t\t<div className=\"font-medium\">{event.title}</div>\n\t\t\t\t\t\t\t\t<div className=\"text-xs text-muted-foreground tabular-nums\">\n\t\t\t\t\t\t\t\t\t{formatEventTimeDisplay(event)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t</Tooltip>\n\t\t\t\t</TooltipProvider>\n\t\t\t);\n\t\t}\n\n\t\treturn wrapWithDetail(compactContent);\n\t}\n\n\t// ========================================================================\n\t// FULL VARIANT (matches agenda-v2 - border, hover shadow, colored text)\n\t// ========================================================================\n\n\tconst fullContent = (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={handleClick}\n\t\t\tclassName={cn(\n\t\t\t\t'group relative flex w-full flex-col gap-1 rounded-md px-2 py-1.5 text-left',\n\t\t\t\t'ring-1 ring-inset ring-black/[0.06] dark:ring-white/10',\n\t\t\t\t'transition-shadow hover:shadow-[0_1px_4px_rgba(0,0,0,0.12)]',\n\t\t\t\t'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n\t\t\t\t// Cancelled events wear the shared graphic code instead of a colour\n\t\t\t\tisCanceled\n\t\t\t\t\t? CANCELED_CHIP\n\t\t\t\t\t: [\n\t\t\t\t\t\t\tbadgeVariant === 'colored' && [colors.bg, colors.text],\n\t\t\t\t\t\t\tbadgeVariant === 'mixed' && [colors.bg, colors.text],\n\t\t\t\t\t\t\tbadgeVariant === 'dot' && 'bg-muted/50',\n\t\t\t\t\t\t],\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tstyle={style}\n\t\t>\n\t\t\t{/* Header row */}\n\t\t\t<div className=\"flex items-start justify-between gap-1\">\n\t\t\t\t<div className=\"flex items-center gap-1.5 min-w-0\">\n\t\t\t\t\t{/* Colored dot for dot/mixed variants */}\n\t\t\t\t\t{['dot', 'mixed'].includes(badgeVariant) && !isCanceled && (\n\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\twidth=\"8\"\n\t\t\t\t\t\t\theight=\"8\"\n\t\t\t\t\t\t\tviewBox=\"0 0 8 8\"\n\t\t\t\t\t\t\tclassName=\"event-dot shrink-0\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\tfocusable=\"false\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<circle cx=\"4\" cy=\"4\" r=\"4\" className={colors.dotFill} />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t)}\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'text-sm font-medium truncate',\n\t\t\t\t\t\t\t!isCanceled && badgeVariant !== 'dot' && colors.text,\n\t\t\t\t\t\t\tisCanceled && 'line-through'\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{event.title}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t\t{/* Status icon (matches agenda-v2) */}\n\t\t\t\t{statusIcon}\n\t\t\t</div>\n\n\t\t\t{/* Product / activity name */}\n\t\t\t{cardProductName && (\n\t\t\t\t<p className=\"text-xs text-muted-foreground truncate\">{cardProductName}</p>\n\t\t\t)}\n\n\t\t\t{/* Extended props — arbitrary JSX from consumer */}\n\t\t\t{cardExtendedProps && cardExtendedProps.length > 0 && (\n\t\t\t\t<div className=\"flex flex-col text-xs text-muted-foreground\">\n\t\t\t\t\t{cardExtendedProps.map((node, i) => (\n\t\t\t\t\t\t<div key={i}>{node}</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Participant count (skip 0 — meaningless for solo event types) */}\n\t\t\t{cardNrParticipant != null && cardNrParticipant > 0 && (\n\t\t\t\t<div className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n\t\t\t\t\t<UsersIcon className=\"h-3 w-3 shrink-0\" />\n\t\t\t\t\t<span>\n\t\t\t\t\t\t{cardNrParticipant} participant{cardNrParticipant !== 1 ? 's' : ''}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Time display — hidden for all-day events where times are meaningless */}\n\t\t\t{showTime && (\n\t\t\t\t<div className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n\t\t\t\t\t<ClockIcon className=\"h-3 w-3 shrink-0\" />\n\t\t\t\t\t<span>{formatEventTimeDisplay(event)}</span>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Location: site name + city */}\n\t\t\t{hasLocation && (\n\t\t\t\t<div className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n\t\t\t\t\t<MapPinIcon className=\"h-3 w-3 shrink-0\" />\n\t\t\t\t\t<span className=\"truncate\">\n\t\t\t\t\t\t{cardSiteName}\n\t\t\t\t\t\t{cardSiteName && cardSiteCity ? ', ' : ''}\n\t\t\t\t\t\t{cardSiteCity}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Description */}\n\t\t\t{showDescription && event.description && (\n\t\t\t\t<p className=\"text-xs text-muted-foreground line-clamp-2\">{event.description}</p>\n\t\t\t)}\n\n\t\t\t{/* Named participants list (matches agenda-v2) */}\n\t\t\t{showParticipants && event.participants && event.participants.length > 0 && (\n\t\t\t\t<div className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n\t\t\t\t\t<UsersIcon className=\"h-3 w-3 shrink-0\" />\n\t\t\t\t\t<span className=\"truncate\">{event.participants.map((p) => p.name).join(', ')}</span>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</button>\n\t);\n\n\tif (disablePopover) {\n\t\treturn (\n\t\t\t<TooltipProvider delayDuration={300}>\n\t\t\t\t<Tooltip>\n\t\t\t\t\t<TooltipTrigger asChild>{fullContent}</TooltipTrigger>\n\t\t\t\t\t<TooltipContent>\n\t\t\t\t\t\t<div className=\"flex flex-col gap-0.5\">\n\t\t\t\t\t\t\t<div className=\"font-medium\">{event.title}</div>\n\t\t\t\t\t\t\t<div className=\"text-xs text-muted-foreground tabular-nums\">\n\t\t\t\t\t\t\t\t{formatEventTimeDisplay(event)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</TooltipContent>\n\t\t\t\t</Tooltip>\n\t\t\t</TooltipProvider>\n\t\t);\n\t}\n\n\treturn wrapWithDetail(fullContent);\n}\n\n// ============================================================================\n// CLOCK ICON (inline SVG to avoid lucide-react dependency)\n// ============================================================================\n\nfunction ClockIcon({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName={className}\n\t\t>\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t<polyline points=\"12 6 12 12 16 14\" />\n\t\t</svg>\n\t);\n}\n\n/**\n * Check Icon (inline SVG to avoid lucide-react dependency)\n */\nfunction CheckIcon({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName={className}\n\t\t>\n\t\t\t<path d=\"M20 6 9 17l-5-5\" />\n\t\t</svg>\n\t);\n}\n\n/**\n * X Icon (inline SVG to avoid lucide-react dependency)\n */\nfunction XIcon({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName={className}\n\t\t>\n\t\t\t<path d=\"M18 6 6 18\" />\n\t\t\t<path d=\"m6 6 12 12\" />\n\t\t</svg>\n\t);\n}\n\n/**\n * Users Icon (inline SVG to avoid lucide-react dependency)\n */\nfunction UsersIcon({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName={className}\n\t\t>\n\t\t\t<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n\t\t\t<circle cx=\"9\" cy=\"7\" r=\"4\" />\n\t\t\t<path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\n\t\t\t<path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n\t\t</svg>\n\t);\n}\n\nfunction MapPinIcon({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName={className}\n\t\t>\n\t\t\t<path d=\"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\" />\n\t\t\t<circle cx=\"12\" cy=\"10\" r=\"3\" />\n\t\t</svg>\n\t);\n}\n\n// ============================================================================\n// EVENT BLOCK (positioned in time grid - matches agenda-v2)\n// ============================================================================\n\nexport interface EventBlockProps<TData = Record<string, unknown>> {\n\t/** The event to display */\n\tevent: CalendarEvent<TData>;\n\t/** Position in the grid */\n\tposition: {\n\t\ttop: number;\n\t\tleft: number;\n\t\twidth: number;\n\t\tminWidth?: number;\n\t};\n\t/** Pixels per hour */\n\thourHeight?: number;\n\t/** Badge variant for coloring style */\n\tbadgeVariant?: TBadgeVariant;\n\t/** Click handler */\n\tonClick?: ((event: CalendarEvent<TData>) => void) | undefined;\n\t/** Additional CSS classes */\n\tclassName?: string;\n\t/** Disable popover and use onClick instead */\n\tdisablePopover?: boolean;\n\t/** Custom popover content */\n\trenderPopover?:\n\t\t| ((props: { event: CalendarEvent<TData>; onClose: () => void }) => ReactNode)\n\t\t| undefined;\n\t/** Enable drag support for repositioning */\n\tenableDrag?: boolean;\n}\n\n/**\n * EventBlock - Positioned event in day/week time grid\n * Matches agenda-v2 styling:\n * - Height calculated from event duration\n * - Shows time when duration > 25 minutes\n * - Uses colored/dot/mixed badge variants\n * - Drag & drop support for event repositioning\n */\nexport function EventBlock<TData = Record<string, unknown>>({\n\tevent,\n\tposition,\n\thourHeight = DEFAULT_HOUR_HEIGHT,\n\tbadgeVariant = 'colored',\n\tonClick,\n\tclassName,\n\tdisablePopover = false,\n\trenderPopover,\n\tenableDrag = true,\n}: EventBlockProps<TData>) {\n\tconst colors = getEventColorClasses(event.color);\n\tconst [popoverOpen, setPopoverOpen] = useState(false);\n\tconst [isDragging, setIsDragging] = useState(false);\n\n\t// Get drag-drop context\n\tconst dragDrop = useOptionalDragDrop();\n\n\t// Auto-open popover when this event matches focusEventId from context\n\tconst calendarCtx = useOptionalInnoCalendar();\n\tuseEffect(() => {\n\t\tif (!disablePopover && calendarCtx?.focusEventId && calendarCtx.focusEventId === event.id) {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsetPopoverOpen(true);\n\t\t\t\tcalendarCtx.clearFocusEventId();\n\t\t\t}, 300);\n\t\t\treturn () => clearTimeout(timer);\n\t\t}\n\t}, [calendarCtx?.focusEventId, event.id, disablePopover]);\n\n\t// Calculate duration and height\n\tconst durationInMinutes = (event.endDate.getTime() - event.startDate.getTime()) / (1000 * 60);\n\tconst heightInPixels = (durationInMinutes / 60) * hourHeight - 8;\n\n\t// Check if event is in the past\n\tconst isPast = event.endDate < startOfDay(new Date());\n\tconst isCanceled = event.isCanceled ?? false;\n\n\t// Don't allow dragging for cancelled or past events\n\tconst canDrag = enableDrag && dragDrop && !isCanceled && !isPast;\n\n\t// Whether the chip can hold more than one line at the current density.\n\t// Google shows a 30-minute event as a single \"Title, 10am\" line; at 48px an\n\t// hour that is 16px of usable height, so the gate has to be pixels.\n\tconst isVeryShortEvent = heightInPixels < 32;\n\tconst isShortEvent = durationInMinutes < 35;\n\tconst showTime = durationInMinutes > 20;\n\t// Show additional details when the card has enough vertical space\n\tconst showDetails = durationInMinutes >= 45;\n\n\t// Extract rich data from event.data for display\n\tconst eventData = event.data as Record<string, unknown> | undefined;\n\t// const scheduleTypeName =\n\t// event.scheduleTypeName ||\n\t// (eventData?.scheduleTypeName as string | undefined) ||\n\t// (eventData?.typeName as string | undefined);\n\tconst productName = eventData?.productName as ReactNode | undefined;\n\tconst extendedProps = eventData?.extendedProps as ReactNode[] | undefined;\n\tconst nrParticipant = eventData?.nrParticipant as number | undefined;\n\tconst siteName = eventData?.siteName as ReactNode | undefined;\n\tconst siteCity = eventData?.siteCity as ReactNode | undefined;\n\tconst hasLocation = !!siteName || !!siteCity;\n\n\t// Determine color variant\n\tconst isDotVariant = badgeVariant === 'dot';\n\n\t// Handle click\n\tconst handleClick = useCallback(() => {\n\t\tif (isDragging) return; // Don't open popover during drag\n\t\tif (disablePopover && onClick) {\n\t\t\tonClick(event);\n\t\t} else if (!disablePopover) {\n\t\t\tsetPopoverOpen(true);\n\t\t}\n\t}, [isDragging, disablePopover, onClick, event]);\n\n\t// Handle popover close\n\tconst handleClose = useCallback(() => {\n\t\tsetPopoverOpen(false);\n\t}, []);\n\n\t// Drag handlers (matches agenda-v2)\n\tconst handleDragStart = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\tif (!canDrag) return;\n\t\t\te.dataTransfer.effectAllowed = 'move';\n\t\t\te.dataTransfer.setData('text/plain', event.id);\n\t\t\t// Set custom drag image with some offset\n\t\t\tconst target = e.currentTarget as HTMLElement;\n\t\t\tconst rect = target.getBoundingClientRect();\n\t\t\te.dataTransfer.setDragImage(target, e.clientX - rect.left, e.clientY - rect.top);\n\t\t\tsetIsDragging(true);\n\t\t\tdragDrop?.startDrag?.(event);\n\t\t},\n\t\t[canDrag, event, dragDrop]\n\t);\n\n\tconst handleDragEnd = useCallback(() => {\n\t\tsetIsDragging(false);\n\t\tif (dragDrop?.isDragging) {\n\t\t\tdragDrop.endDrag?.();\n\t\t}\n\t}, [dragDrop]);\n\n\t// ========================================================================\n\t// RESIZE\n\t// ========================================================================\n\t// Pointer events rather than HTML5 drag: dragging the bottom edge is a\n\t// gesture on the chip, not a transfer of it, and pointer capture keeps the\n\t// gesture alive when the cursor leaves the element.\n\n\t/** Live height delta while resizing, in pixels. Null when idle. */\n\tconst [resizeDelta, setResizeDelta] = useState<number | null>(null);\n\tconst isResizing = resizeDelta !== null;\n\n\t/** Snap to the grid the user can actually see. */\n\tconst snapMinutes = calendarCtx?.slotDuration ?? 15;\n\tconst canResize = canDrag && !!dragDrop?.resizeEvent;\n\n\tconst handleResizeStart = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\tif (!canResize) return;\n\t\t\t// Must not start a drag or open the popover.\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\n\t\t\tconst handle = e.currentTarget as HTMLElement;\n\t\t\thandle.setPointerCapture(e.pointerId);\n\n\t\t\tconst startY = e.clientY;\n\t\t\tconst originalEnd = event.endDate;\n\t\t\tconst minEnd = new Date(event.startDate.getTime() + snapMinutes * 60_000);\n\t\t\tlet latestEnd = originalEnd;\n\n\t\t\tconst move = (ev: PointerEvent) => {\n\t\t\t\tconst deltaMinutes = ((ev.clientY - startY) / hourHeight) * 60;\n\t\t\t\tconst snapped = Math.round(deltaMinutes / snapMinutes) * snapMinutes;\n\t\t\t\tconst next = new Date(originalEnd.getTime() + snapped * 60_000);\n\n\t\t\t\t// Never shorter than one slot — dragging past the start would otherwise\n\t\t\t\t// produce an event that ends before it begins.\n\t\t\t\tlatestEnd = next < minEnd ? minEnd : next;\n\t\t\t\tsetResizeDelta(((latestEnd.getTime() - originalEnd.getTime()) / 3_600_000) * hourHeight);\n\t\t\t};\n\n\t\t\tconst finish = () => {\n\t\t\t\thandle.removeEventListener('pointermove', move);\n\t\t\t\thandle.removeEventListener('pointerup', finish);\n\t\t\t\thandle.removeEventListener('pointercancel', cancel);\n\t\t\t\tsetResizeDelta(null);\n\t\t\t\tif (latestEnd.getTime() !== originalEnd.getTime()) {\n\t\t\t\t\tdragDrop?.resizeEvent?.(event, latestEnd);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst cancel = () => {\n\t\t\t\thandle.removeEventListener('pointermove', move);\n\t\t\t\thandle.removeEventListener('pointerup', finish);\n\t\t\t\thandle.removeEventListener('pointercancel', cancel);\n\t\t\t\tsetResizeDelta(null);\n\t\t\t};\n\n\t\t\thandle.addEventListener('pointermove', move);\n\t\t\thandle.addEventListener('pointerup', finish);\n\t\t\thandle.addEventListener('pointercancel', cancel);\n\t\t},\n\t\t[canResize, event, hourHeight, snapMinutes, dragDrop]\n\t);\n\n\tconst eventCalendar = useOptionalInnoCalendar();\n\tconst renderCard = useOptionalEventCard<TData>();\n\t/** The consumer's chip, when it gave one. */\n\tconst custom = renderCard?.(event, {\n\t\tview: eventCalendar?.view ?? 'week',\n\t\t// Under ~20 minutes there is room for one line and nothing else.\n\t\tcompact: isVeryShortEvent,\n\t});\n\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent) => {\n\t\t\tif (e.key === 'Enter' || e.key === ' ') {\n\t\t\t\te.preventDefault();\n\t\t\t\thandleClick();\n\t\t\t}\n\t\t},\n\t\t[handleClick]\n\t);\n\n\tconst blockButton = (\n\t\t<div\n\t\t\trole=\"button\"\n\t\t\ttabIndex={0}\n\t\t\tdraggable={!!canDrag}\n\t\t\tonDragStart={handleDragStart}\n\t\t\tonDragEnd={handleDragEnd}\n\t\t\tonKeyDown={handleKeyDown}\n\t\t\tonClick={isDragging || isResizing ? undefined : handleClick}\n\t\t\tclassName={cn(\n\t\t\t\t'group relative flex w-full select-none overflow-hidden rounded-md text-xs text-left',\n\t\t\t\t// The fill is the colour. A hairline inset ring gives the block an edge\n\t\t\t\t// where two of them meet, without the accent bar competing with it.\n\t\t\t\t'ring-1 ring-inset ring-black/[0.06] dark:ring-white/10',\n\t\t\t\t// No resting shadow: a grid of chips each casting one reads as clutter.\n\t\t\t\t// It lifts on hover, which is the only time depth means anything here.\n\t\t\t\t'transition-shadow hover:shadow-[0_1px_4px_rgba(0,0,0,0.12)]',\n\t\t\t\t'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n\t\t\t\tcanDrag ? 'cursor-grab active:cursor-grabbing' : 'cursor-pointer',\n\t\t\t\tisDragging && 'opacity-50',\n\t\t\t\t// Cancelled events wear the shared graphic code instead of a colour\n\t\t\t\tisCanceled\n\t\t\t\t\t? CANCELED_CHIP\n\t\t\t\t\t: [\n\t\t\t\t\t\t\t// Colored/mixed variants\n\t\t\t\t\t\t\t!isDotVariant && [colors.bg, colors.text],\n\t\t\t\t\t\t\t// Dot variant - neutral background\n\t\t\t\t\t\t\tisDotVariant && 'bg-neutral-50 dark:bg-neutral-900',\n\t\t\t\t\t\t],\n\t\t\t\t// Very short events: single-row inline layout\n\t\t\t\tisVeryShortEvent\n\t\t\t\t\t? 'flex-row items-center gap-1.5 px-2 py-0'\n\t\t\t\t\t: // Short events: vertical but no padding\n\t\t\t\t\t\tisShortEvent\n\t\t\t\t\t\t? 'flex-col gap-0.5 px-2 py-0 justify-center'\n\t\t\t\t\t\t: // Normal events: standard vertical layout\n\t\t\t\t\t\t\t'flex-col gap-0.5 px-2 py-1.5',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tstyle={{\n\t\t\t\theight: `${Math.max(heightInPixels + (resizeDelta ?? 0), 20)}px`,\n\t\t\t}}\n\t\t>\n\t\t\t{/* Resize handle. Invisible until the chip is hovered, so it never\n competes with the event's own content, and generous enough to hit. */}\n\t\t\t{canResize && (\n\t\t\t\t<div\n\t\t\t\t\trole=\"separator\"\n\t\t\t\t\taria-label=\"Resize event\"\n\t\t\t\t\tonPointerDown={handleResizeStart}\n\t\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'absolute inset-x-0 bottom-0 z-10 cursor-ns-resize',\n\t\t\t\t\t\t'opacity-0 transition-opacity group-hover:opacity-100',\n\t\t\t\t\t\t// Short chips get a thinner zone so it cannot cover the whole event\n\t\t\t\t\t\t// and steal the click that opens it.\n\t\t\t\t\t\tisVeryShortEvent ? 'h-1.5' : 'h-2',\n\t\t\t\t\t\tisResizing && 'opacity-100'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'mx-auto block h-0.5 w-6 rounded-full bg-current opacity-40',\n\t\t\t\t\t\t\tisVeryShortEvent ? 'mt-px' : 'mt-0.5'\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{/* The consumer's chip, when it gave one. The shell above stays ours:\n it is what the grid positions, drags and opens a popover from. */}\n\t\t\t{custom}\n\t\t\t{!custom &&\n\t\t\t\t(isVeryShortEvent ? (\n\t\t\t\t\t/* Single-row layout for very short events (≤20min) */\n\t\t\t\t\t<>\n\t\t\t\t\t\t{/* Colored dot for dot/mixed variants */}\n\t\t\t\t\t\t{['mixed', 'dot'].includes(badgeVariant) && !isCanceled && (\n\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\twidth=\"8\"\n\t\t\t\t\t\t\t\theight=\"8\"\n\t\t\t\t\t\t\t\tviewBox=\"0 0 8 8\"\n\t\t\t\t\t\t\t\tclassName=\"event-dot shrink-0\"\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\tfocusable=\"false\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<circle cx=\"4\" cy=\"4\" r=\"4\" className={colors.dotFill} />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'truncate leading-none text-[11px]',\n\t\t\t\t\t\t\t\t!isCanceled && isDotVariant && 'text-foreground'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span className=\"font-semibold\">{event.title}</span>\n\t\t\t\t\t\t\t{!event.isAllDay && (\n\t\t\t\t\t\t\t\t<span className=\"opacity-75\">, {compactStart(event.startDate)}</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\t/* Standard stacked layout for events > 20min */\n\t\t\t\t\t<>\n\t\t\t\t\t\t<div className=\"flex items-start gap-1.5 min-w-0\">\n\t\t\t\t\t\t\t{/* Colored dot for dot/mixed variants */}\n\t\t\t\t\t\t\t{['mixed', 'dot'].includes(badgeVariant) && !isCanceled && (\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\twidth=\"8\"\n\t\t\t\t\t\t\t\t\theight=\"8\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 8 8\"\n\t\t\t\t\t\t\t\t\tclassName=\"event-dot shrink-0\"\n\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\tfocusable=\"false\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<circle cx=\"4\" cy=\"4\" r=\"4\" className={colors.dotFill} />\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<div className=\"flex-1 min-w-0 overflow-hidden\">\n\t\t\t\t\t\t\t\t{/* Title + schedule type name */}\n\t\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t'font-semibold truncate leading-tight',\n\t\t\t\t\t\t\t\t\t\t!isCanceled && isDotVariant && 'text-foreground'\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{event.title}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t{/* Product / activity name */}\n\t\t\t\t\t\t{showDetails && productName && (\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'text-[11px] truncate leading-tight',\n\t\t\t\t\t\t\t\t\tisDotVariant ? 'text-muted-foreground' : 'opacity-80'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{productName}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{/* Extended props — arbitrary JSX from consumer */}\n\t\t\t\t\t\t{showDetails && extendedProps && extendedProps.length > 0 && (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex flex-col text-[11px] leading-tight',\n\t\t\t\t\t\t\t\t\tisDotVariant ? 'text-muted-foreground' : 'opacity-80'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{extendedProps.map((node, i) => (\n\t\t\t\t\t\t\t\t\t<div key={i}>{node}</div>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{/* Participant count — a detail, not a headline. On a medium chip it used\n to push the time out of view. All-day events have no duration to gate\n on, so they keep it. */}\n\t\t\t\t\t\t{(showDetails || event.isAllDay) && nrParticipant != null && nrParticipant > 0 && (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex items-center gap-1 text-[11px] leading-tight',\n\t\t\t\t\t\t\t\t\tisDotVariant ? 'text-muted-foreground' : 'opacity-80'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<UsersIcon className=\"h-3 w-3 shrink-0\" />\n\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t{nrParticipant} participant{nrParticipant !== 1 ? 's' : ''}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{/* Time display — hidden for all-day events */}\n\t\t\t\t\t\t{showTime && (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex items-center gap-1 text-[11px] tabular-nums leading-tight',\n\t\t\t\t\t\t\t\t\tisDotVariant ? 'text-muted-foreground' : 'opacity-90'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<ClockIcon className=\"h-3 w-3 shrink-0\" />\n\t\t\t\t\t\t\t\t<span>{formatEventTimeDisplay(event)}</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{/* Location: site name + city */}\n\t\t\t\t\t\t{showDetails && hasLocation && (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex items-center gap-1 text-[11px] truncate leading-tight',\n\t\t\t\t\t\t\t\t\tisDotVariant ? 'text-muted-foreground' : 'opacity-80'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<MapPinIcon className=\"h-3 w-3 shrink-0\" />\n\t\t\t\t\t\t\t\t<span className=\"truncate\">\n\t\t\t\t\t\t\t\t\t{siteName}\n\t\t\t\t\t\t\t\t\t{siteName && siteCity ? ', ' : ''}\n\t\t\t\t\t\t\t\t\t{siteCity}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</>\n\t\t\t\t))}\n\t\t</div>\n\t);\n\n\tconst tooltipContent = (\n\t\t<TooltipContent>\n\t\t\t<div className=\"flex flex-col gap-0.5\">\n\t\t\t\t<div className=\"font-medium\">{event.title}</div>\n\t\t\t\t{productName && <div className=\"text-xs text-muted-foreground\">{productName}</div>}\n\t\t\t\t{extendedProps &&\n\t\t\t\t\textendedProps.length > 0 &&\n\t\t\t\t\textendedProps.map((node, i) => (\n\t\t\t\t\t\t<div key={i} className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t{node}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t{nrParticipant != null && (\n\t\t\t\t\t<div className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t{nrParticipant} participant{nrParticipant !== 1 ? 's' : ''}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"text-xs text-muted-foreground tabular-nums\">\n\t\t\t\t\t{formatEventTimeDisplay(event)}\n\t\t\t\t</div>\n\t\t\t\t{hasLocation && (\n\t\t\t\t\t<div className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t{siteName}\n\t\t\t\t\t\t{siteName && siteCity ? ', ' : ''}\n\t\t\t\t\t\t{siteCity}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</TooltipContent>\n\t);\n\n\tif (disablePopover) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName=\"absolute p-0.5\"\n\t\t\t\tstyle={{\n\t\t\t\t\ttop: `${position.top}px`,\n\t\t\t\t\tleft: `${position.left}%`,\n\t\t\t\t\twidth: position.minWidth\n\t\t\t\t\t\t? `max(${position.minWidth}px, ${position.width}%)`\n\t\t\t\t\t\t: `${position.width}%`,\n\t\t\t\t\tminWidth: position.minWidth ? `${position.minWidth}px` : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<TooltipProvider delayDuration={300}>\n\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t<TooltipTrigger asChild>{blockButton}</TooltipTrigger>\n\t\t\t\t\t\t{tooltipContent}\n\t\t\t\t\t</Tooltip>\n\t\t\t\t</TooltipProvider>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"absolute p-0.5\"\n\t\t\tstyle={{\n\t\t\t\ttop: `${position.top}px`,\n\t\t\t\tleft: `${position.left}%`,\n\t\t\t\twidth: position.minWidth\n\t\t\t\t\t? `max(${position.minWidth}px, ${position.width}%)`\n\t\t\t\t\t: `${position.width}%`,\n\t\t\t\tminWidth: position.minWidth ? `${position.minWidth}px` : undefined,\n\t\t\t}}\n\t\t>\n\t\t\t<DetailPopover open={popoverOpen} onOpenChange={setPopoverOpen} trigger={blockButton}>\n\t\t\t\t<div className=\"flex min-h-0 flex-1 flex-col\">\n\t\t\t\t\t{renderPopover?.({ event, onClose: handleClose })}\n\t\t\t\t</div>\n\t\t\t</DetailPopover>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// MULTI-DAY EVENT BAR (for week/month views - matches agenda-v2)\n// ============================================================================\n\nexport interface MultiDayEventBarProps<TData = Record<string, unknown>> {\n\t/** The event to display */\n\tevent: CalendarEvent<TData>;\n\t/** Number of days the event spans */\n\tspanDays: number;\n\t/** Whether this is the start of the event span */\n\tisStart: boolean;\n\t/** Whether this is the end of the event span */\n\tisEnd: boolean;\n\t/** Click handler */\n\tonClick?: (event: CalendarEvent<TData>) => void;\n\t/** Additional CSS classes */\n\tclassName?: string;\n\t/** Disable popover and use onClick instead */\n\tdisablePopover?: boolean;\n\t/** Custom popover content */\n\trenderPopover?: (props: { event: CalendarEvent<TData>; onClose: () => void }) => ReactNode;\n}\n\n/**\n * MultiDayEventBar - Horizontal bar for multi-day events in week/month views\n */\nexport function MultiDayEventBar<TData = Record<string, unknown>>({\n\tevent,\n\tspanDays,\n\tisStart,\n\tisEnd,\n\tonClick,\n\tclassName,\n\tdisablePopover = false,\n\trenderPopover,\n}: MultiDayEventBarProps<TData>) {\n\tconst colors = getEventColorClasses(event.color);\n\tconst [popoverOpen, setPopoverOpen] = useState(false);\n\n\tconst isCanceled = event.isCanceled ?? false;\n\n\t// Handle click\n\tconst handleClick = useCallback(() => {\n\t\tif (disablePopover && onClick) {\n\t\t\tonClick(event);\n\t\t} else if (!disablePopover) {\n\t\t\tsetPopoverOpen(true);\n\t\t}\n\t}, [disablePopover, onClick, event]);\n\n\t// Handle popover close\n\tconst handleClose = useCallback(() => {\n\t\tsetPopoverOpen(false);\n\t}, []);\n\n\tconst barButton = (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={handleClick}\n\t\t\tclassName={cn(\n\t\t\t\t'flex h-5 items-center px-1.5 text-xs font-medium transition-opacity hover:opacity-80',\n\t\t\t\t// Cancelled events get gray background with strikethrough\n\t\t\t\tisCanceled\n\t\t\t\t\t? 'bg-zinc-200 dark:bg-zinc-700 text-zinc-500 dark:text-zinc-400 line-through'\n\t\t\t\t\t: [colors.dot, 'text-white'],\n\t\t\t\tisStart && 'rounded-l',\n\t\t\t\tisEnd && 'rounded-r',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tstyle={{ width: `${spanDays * 100}%` }}\n\t\t>\n\t\t\t{isStart && <span className=\"truncate\">{event.title}</span>}\n\t\t</button>\n\t);\n\n\tconst tooltipContent = (\n\t\t<TooltipContent>\n\t\t\t<div className=\"flex flex-col gap-0.5\">\n\t\t\t\t<div className=\"font-medium\">{event.title}</div>\n\t\t\t\t<div className=\"text-xs text-muted-foreground tabular-nums\">\n\t\t\t\t\t{formatEventTimeDisplay(event)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</TooltipContent>\n\t);\n\n\tif (disablePopover) {\n\t\treturn (\n\t\t\t<TooltipProvider delayDuration={300}>\n\t\t\t\t<Tooltip>\n\t\t\t\t\t<TooltipTrigger asChild>{barButton}</TooltipTrigger>\n\t\t\t\t\t{tooltipContent}\n\t\t\t\t</Tooltip>\n\t\t\t</TooltipProvider>\n\t\t);\n\t}\n\n\treturn (\n\t\t<DetailPopover open={popoverOpen} onOpenChange={setPopoverOpen} trigger={barButton}>\n\t\t\t<div className=\"flex min-h-0 flex-1 flex-col\">\n\t\t\t\t{renderPopover?.({ event, onClose: handleClose })}\n\t\t\t</div>\n\t\t</DetailPopover>\n\t);\n}\n\n// ============================================================================\n// MARQUEE ANIMATION CSS INJECTION\n// ============================================================================\n\n// Inject marquee animation CSS into document head (runs once)\nif (\n\ttypeof window !== 'undefined' &&\n\t!document.getElementById('inno-calendar-event-marquee-style')\n) {\n\tconst style = document.createElement('style');\n\tstyle.id = 'inno-calendar-event-marquee-style';\n\tstyle.innerHTML = `\n@keyframes event-marquee {\n 0% { transform: translateX(0); }\n 100% { transform: translateX(-50%); }\n}\n.event-marquee {\n animation: event-marquee 28s linear infinite;\n will-change: transform;\n}\n`;\n\tdocument.head.appendChild(style);\n}\n\nexport default EventCard;\n","/**\n * Button Component\n *\n * A versatile button component with multiple variants and sizes.\n * Built with class-variance-authority for type-safe variants.\n */\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { type ButtonHTMLAttributes, forwardRef } from 'react';\nimport { cn } from '../../lib/utils';\n\n// ============================================================================\n// VARIANTS\n// ============================================================================\n\nconst buttonVariants = cva(\n\t'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: 'bg-primary text-primary-foreground shadow hover:bg-primary/90',\n\t\t\t\tdestructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',\n\t\t\t\toutline:\n\t\t\t\t\t'border border-input active:!bg-zinc-100 hover:!bg-zinc-50 active:bg-white !bg-white hover:bg-accent hover:text-accent-foreground',\n\t\t\t\tsecondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',\n\t\t\t\tghost: 'hover:bg-accent hover:text-accent-foreground',\n\t\t\t\tlink: 'text-primary underline-offset-4 hover:underline',\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: 'h-9 px-4 py-2',\n\t\t\t\tsm: 'h-8 rounded-md px-3 text-xs',\n\t\t\t\tlg: 'h-10 rounded-md px-8',\n\t\t\t\ticon: 'h-9 w-9',\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: 'default',\n\t\t\tsize: 'default',\n\t\t},\n\t}\n);\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface ButtonProps\n\textends ButtonHTMLAttributes<HTMLButtonElement>,\n\t\tVariantProps<typeof buttonVariants> {\n\t/** Loading state - disables button and shows spinner */\n\tloading?: boolean;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nconst Button = forwardRef<HTMLButtonElement, ButtonProps>(\n\t({ className, variant, size, loading, disabled, children, ...props }, ref) => {\n\t\treturn (\n\t\t\t<button\n\t\t\t\tclassName={cn(buttonVariants({ variant, size, className }))}\n\t\t\t\tref={ref}\n\t\t\t\tdisabled={disabled || loading}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{loading && (\n\t\t\t\t\t<svg\n\t\t\t\t\t\tclassName=\"animate-spin -ml-1 mr-2 size-4\"\n\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<circle\n\t\t\t\t\t\t\tclassName=\"opacity-25\"\n\t\t\t\t\t\t\tcx=\"12\"\n\t\t\t\t\t\t\tcy=\"12\"\n\t\t\t\t\t\t\tr=\"10\"\n\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\tstrokeWidth=\"4\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\tclassName=\"opacity-75\"\n\t\t\t\t\t\t\tfill=\"currentColor\"\n\t\t\t\t\t\t\td=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t)}\n\t\t\t\t{children}\n\t\t\t</button>\n\t\t);\n\t}\n);\n\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n","/**\n * DropdownMenu Component\n *\n * A dropdown menu for displaying a list of actions or options.\n * Uses Radix UI dropdown primitives.\n */\n\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { Check, ChevronRight, Circle } from 'lucide-react';\nimport * as React from 'react';\nimport { cn } from '../../lib/utils';\n\n// ============================================================================\n// ROOT\n// ============================================================================\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group;\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal;\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub;\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\n// ============================================================================\n// SUB TRIGGER\n// ============================================================================\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n\tReact.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n\t\tinset?: boolean;\n\t}\n>(({ className, inset, children, ...props }, ref) => (\n\t<DropdownMenuPrimitive.SubTrigger\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t'flex cursor-default select-none items-center rounded-lg px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',\n\t\t\tinset && 'pl-8',\n\t\t\tclassName\n\t\t)}\n\t\t{...props}\n\t>\n\t\t{children}\n\t\t<ChevronRight className=\"ml-auto h-4 w-4\" />\n\t</DropdownMenuPrimitive.SubTrigger>\n));\nDropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;\n\n// ============================================================================\n// SUB CONTENT\n// ============================================================================\n\nconst DropdownMenuSubContent = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n\tReact.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n\t<DropdownMenuPrimitive.SubContent\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n\t\t\tclassName\n\t\t)}\n\t\t{...props}\n\t/>\n));\nDropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;\n\n// ============================================================================\n// CONTENT\n// ============================================================================\n\nconst DropdownMenuContent = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.Content>,\n\tReact.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n\t<DropdownMenuPrimitive.Portal>\n\t\t<DropdownMenuPrimitive.Content\n\t\t\tref={ref}\n\t\t\tsideOffset={sideOffset}\n\t\t\tclassName={cn(\n\t\t\t\t'z-50 rounded-xl border bg-popover p-1 text-popover-foreground shadow-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t</DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\n// ============================================================================\n// ITEM\n// ============================================================================\n\nconst DropdownMenuItem = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.Item>,\n\tReact.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n\t\tinset?: boolean;\n\t}\n>(({ className, inset, ...props }, ref) => (\n\t<DropdownMenuPrimitive.Item\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t'relative flex cursor-pointer select-none items-center rounded-lg px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n\t\t\tinset && 'pl-8',\n\t\t\tclassName\n\t\t)}\n\t\t{...props}\n\t/>\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\n// ============================================================================\n// CHECKBOX ITEM\n// ============================================================================\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n\tReact.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked = false, ...props }, ref) => (\n\t<DropdownMenuPrimitive.CheckboxItem\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n\t\t\tclassName\n\t\t)}\n\t\tchecked={checked}\n\t\t{...props}\n\t>\n\t\t<span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n\t\t\t<DropdownMenuPrimitive.ItemIndicator>\n\t\t\t\t<Check className=\"h-4 w-4\" />\n\t\t\t</DropdownMenuPrimitive.ItemIndicator>\n\t\t</span>\n\t\t{children}\n\t</DropdownMenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;\n\n// ============================================================================\n// RADIO ITEM\n// ============================================================================\n\nconst DropdownMenuRadioItem = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n\tReact.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n\t<DropdownMenuPrimitive.RadioItem\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n\t\t\tclassName\n\t\t)}\n\t\t{...props}\n\t>\n\t\t<span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n\t\t\t<DropdownMenuPrimitive.ItemIndicator>\n\t\t\t\t<Circle className=\"h-2 w-2 fill-current\" />\n\t\t\t</DropdownMenuPrimitive.ItemIndicator>\n\t\t</span>\n\t\t{children}\n\t</DropdownMenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;\n\n// ============================================================================\n// LABEL\n// ============================================================================\n\nconst DropdownMenuLabel = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.Label>,\n\tReact.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n\t\tinset?: boolean;\n\t}\n>(({ className, inset, ...props }, ref) => (\n\t<DropdownMenuPrimitive.Label\n\t\tref={ref}\n\t\tclassName={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)}\n\t\t{...props}\n\t/>\n));\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;\n\n// ============================================================================\n// SEPARATOR\n// ============================================================================\n\nconst DropdownMenuSeparator = React.forwardRef<\n\tReact.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n\tReact.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n\t<DropdownMenuPrimitive.Separator\n\t\tref={ref}\n\t\tclassName={cn('-mx-1 my-1 h-px bg-muted', className)}\n\t\t{...props}\n\t/>\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\n// ============================================================================\n// SHORTCUT\n// ============================================================================\n\nconst DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => (\n\t<span className={cn('ml-auto text-xs tracking-widest opacity-60', className)} {...props} />\n);\nDropdownMenuShortcut.displayName = 'DropdownMenuShortcut';\n\nexport {\n\tDropdownMenu,\n\tDropdownMenuCheckboxItem,\n\tDropdownMenuContent,\n\tDropdownMenuGroup,\n\tDropdownMenuItem,\n\tDropdownMenuLabel,\n\tDropdownMenuPortal,\n\tDropdownMenuRadioGroup,\n\tDropdownMenuRadioItem,\n\tDropdownMenuSeparator,\n\tDropdownMenuShortcut,\n\tDropdownMenuSub,\n\tDropdownMenuSubContent,\n\tDropdownMenuSubTrigger,\n\tDropdownMenuTrigger,\n};\n","/**\n * Event Popover Component\n *\n * Google Calendar-style event preview popover.\n * - Desktop: Shows as popover positioned near the event\n * - Mobile: Falls back to dialog/modal\n * - Fully headless with callback props for actions\n * - Slot-based customization for all UI elements\n *\n * @template TData - Custom event data type\n */\n\nimport {\n forwardRef,\n type HTMLAttributes,\n type ReactNode,\n useCallback,\n useEffect,\n useState,\n} from \"react\";\nimport type { CalendarEvent, ICalendarUser } from \"../../core/types\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"../ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/popover\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../ui/tooltip\";\n\n// ============================================================================\n// INLINE SVG ICONS\n// ============================================================================\n\nfunction PencilIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\" />\n <path d=\"m15 5 4 4\" />\n </svg>\n );\n}\n\nfunction TrashIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M3 6h18\" />\n <path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\" />\n <path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\" />\n <line x1=\"10\" x2=\"10\" y1=\"11\" y2=\"17\" />\n <line x1=\"14\" x2=\"14\" y1=\"11\" y2=\"17\" />\n </svg>\n );\n}\n\nfunction XIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nfunction BanIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"m4.9 4.9 14.2 14.2\" />\n </svg>\n );\n}\n\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\nfunction CheckCircleIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"m9 12 2 2 4-4\" />\n </svg>\n );\n}\n\nfunction ChevronDownIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n );\n}\n\nfunction UsersIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n );\n}\n\nfunction MapPinIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\" />\n <circle cx=\"12\" cy=\"10\" r=\"3\" />\n </svg>\n );\n}\n\nfunction CalendarIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M8 2v4\" />\n <path d=\"M16 2v4\" />\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\" />\n <path d=\"M3 10h18\" />\n </svg>\n );\n}\n\nfunction FileTextIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\" />\n <path d=\"M14 2v4a2 2 0 0 0 2 2h4\" />\n <path d=\"M10 9H8\" />\n <path d=\"M16 13H8\" />\n <path d=\"M16 17H8\" />\n </svg>\n );\n}\n\nfunction LoaderIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn(\"animate-spin\", className)}\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * Extended participant type with confirmation/organizer info\n */\nexport interface IEventParticipant extends ICalendarUser {\n /** Whether this participant is the event organizer */\n isOrganizer?: boolean;\n /** Confirmation status: null/undefined = pending, true = accepted, false = declined */\n isConfirmed?: boolean | null | undefined;\n /** Whether this participant is a client (external) */\n isClient?: boolean;\n /** Profile picture URL */\n profilePicture?: string;\n}\n\n/**\n * Extended event type for the built-in popover display.\n *\n * Adds popover-specific fields on top of {@link CalendarEvent}.\n * If you use a custom `renderPopover`, you do **not** need to conform\n * to this interface — it is only used by the package's default\n * {@link EventPopoverContent} component.\n *\n * @template TData - Consumer's custom data type\n *\n * @example\n * ```ts\n * const popoverEvent: IPopoverEvent<MyData> = {\n * ...baseEvent,\n * meetingTookPlace: true,\n * participantsNames: ['Jane Doe', 'John Smith'],\n * };\n * ```\n */\nexport interface IPopoverEvent<\n TData = Record<string, unknown>,\n> extends CalendarEvent<TData> {\n /** Detailed participant list with RSVP status */\n participantDetails?: IEventParticipant[];\n /** Simple participant names for display (fallback when participantDetails unavailable) */\n participantsNames?: string[];\n /** Location or address to display in the popover */\n address?: string;\n /** Schedule type accent color (hex). Falls back to {@link CalendarEvent.hexColor} */\n scheduleTypeColor?: string;\n /** Human-readable recurrence summary (e.g. \"Every Monday\") */\n recurrenceSummary?: string;\n\n // --- Domain-specific status fields (popover-only) ---\n\n /**\n * Whether the meeting has been confirmed as having taken place.\n * Controls the \"Confirm Meeting\" action button visibility and the\n * completed checkmark display.\n */\n meetingTookPlace?: boolean;\n\n /**\n * Whether the event has been accepted by the host/organizer.\n * Controls the \"Accept\" action button visibility and participant\n * confirmed count display.\n */\n isAccepted?: boolean;\n\n /**\n * Free-text reason for cancellation. Displayed below the canceled\n * status badge when present.\n */\n cancelReason?: string | null;\n\n /** Cancellation reason code (numeric, for consumer logic) */\n cancelReasonCode?: number | null;\n /** Date when the event was canceled */\n canceledDate?: Date | null;\n}\n\n/**\n * Labels for i18n support\n */\nexport interface IEventPopoverLabels {\n edit?: string;\n delete?: string;\n cancel?: string;\n close?: string;\n going?: string;\n notGoing?: string;\n confirmMeeting?: string;\n completed?: string;\n canceled?: string;\n participants?: string;\n guest?: string;\n guests?: string;\n confirmed?: string;\n organizer?: string;\n client?: string;\n more?: string;\n noDateProvided?: string;\n eventNotFound?: string;\n cancellationNote?: string;\n canceledOn?: string;\n acceptThisEvent?: string;\n acceptAllEvents?: string;\n deleteConfirmTitle?: string;\n deleteConfirmDescription?: string;\n}\n\n/**\n * Default labels\n */\nconst DEFAULT_LABELS: Required<IEventPopoverLabels> = {\n edit: \"Edit\",\n delete: \"Delete\",\n cancel: \"Cancel Event\",\n close: \"Close\",\n going: \"Going\",\n notGoing: \"Not Going\",\n confirmMeeting: \"Confirm meeting took place\",\n completed: \"Completed\",\n canceled: \"Canceled\",\n participants: \"Participants\",\n guest: \"guest\",\n guests: \"guests\",\n confirmed: \"confirmed\",\n organizer: \"Organizer\",\n client: \"Client\",\n more: \"more\",\n noDateProvided: \"No date provided\",\n eventNotFound: \"Event not found\",\n cancellationNote: \"Cancellation Note\",\n canceledOn: \"Canceled on\",\n acceptThisEvent: \"Accept this event only\",\n acceptAllEvents: \"Accept all events\",\n deleteConfirmTitle: \"Delete Event\",\n deleteConfirmDescription:\n \"Are you sure you want to delete this event? This action cannot be undone.\",\n};\n\n/**\n * EventPopover props\n */\nexport interface EventPopoverProps<TData = Record<string, unknown>> {\n /** The event to display */\n event: IPopoverEvent<TData>;\n /** Trigger element */\n children: ReactNode;\n /** Controlled open state */\n open?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Whether popover is loading data */\n isLoading?: boolean;\n /** i18n labels */\n labels?: Partial<IEventPopoverLabels>;\n\n // ============================================================================\n // ACTION CALLBACKS\n // ============================================================================\n\n /** Called when edit button is clicked */\n onEdit?: (event: IPopoverEvent<TData>) => void;\n /** Called when delete button is clicked */\n onDelete?: (event: IPopoverEvent<TData>) => void;\n /** Called when cancel event button is clicked */\n onCancel?: (event: IPopoverEvent<TData>) => void;\n /** Called when accept/going button is clicked */\n onAccept?: (event: IPopoverEvent<TData>) => void;\n /** Called when decline/not going button is clicked */\n onDecline?: (event: IPopoverEvent<TData>) => void;\n /** Called when confirm meeting button is clicked */\n onConfirmMeeting?: (event: IPopoverEvent<TData>) => void;\n\n // ============================================================================\n // PERMISSION FLAGS\n // ============================================================================\n\n /** Whether user can edit this event */\n canEdit?: boolean;\n /** Whether user can delete this event (admin only) */\n canDelete?: boolean;\n /** Whether user can cancel this event */\n canCancel?: boolean;\n\n // ============================================================================\n // CURRENT USER STATE\n // ============================================================================\n\n // Note: currentUserId can be derived from currentUserAcceptStatus if needed\n /** Whether current user is a participant */\n isCurrentUserParticipant?: boolean;\n /** Whether current user is a client (clients don't see RSVP) */\n isCurrentUserClient?: boolean;\n /** Current user's acceptance status: null = pending, true = accepted, false = declined */\n currentUserAcceptStatus?: boolean | null;\n\n // ============================================================================\n // LOADING STATES\n // ============================================================================\n\n /** Whether accept mutation is loading */\n isAcceptLoading?: boolean;\n /** Whether decline mutation is loading */\n isDeclineLoading?: boolean;\n /** Whether confirm meeting mutation is loading */\n isConfirmLoading?: boolean;\n /** Whether delete mutation is loading */\n isDeleteLoading?: boolean;\n\n // ============================================================================\n // SLOTS\n // ============================================================================\n\n /** Custom render for participant row */\n renderParticipant?: (\n participant: IEventParticipant,\n index: number,\n ) => ReactNode;\n /** Custom render for the header actions */\n renderHeaderActions?: (props: { onClose: () => void }) => ReactNode;\n /** Custom render for cancel reason */\n renderCancelReason?: (event: IPopoverEvent<TData>) => ReactNode;\n /** Custom render for delete confirmation dialog */\n renderDeleteConfirmation?: (props: {\n onConfirm: () => void;\n onCancel: () => void;\n isLoading?: boolean;\n }) => ReactNode;\n\n // ============================================================================\n // FORMATTING\n // ============================================================================\n\n /** Format date for display */\n formatDate?: (date: Date, format?: string) => string;\n /** Format time range */\n formatTimeRange?: (start: Date, end: Date) => string;\n\n // ============================================================================\n // STYLING\n // ============================================================================\n\n /** Additional class for popover content */\n className?: string;\n /** Popover width */\n width?: number;\n}\n\n// ============================================================================\n// HELPER COMPONENTS\n// ============================================================================\n\ninterface IconButtonProps extends HTMLAttributes<HTMLButtonElement> {\n label: string;\n variant?: \"ghost\" | \"destructive\";\n}\n\nconst IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n (\n { onClick, label, children, className, variant = \"ghost\", ...props },\n ref,\n ) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n ref={ref}\n onClick={onClick}\n className={cn(\n \"h-8 w-8 rounded-full flex items-center justify-center transition-colors\",\n variant === \"ghost\" &&\n \"hover:bg-zinc-100 dark:hover:bg-zinc-800 text-zinc-600 dark:text-zinc-400\",\n variant === \"destructive\" &&\n \"hover:bg-red-50 dark:hover:bg-red-950/30 text-zinc-600 dark:text-zinc-400 hover:text-red-600\",\n className,\n )}\n aria-label={label}\n {...props}\n >\n {children}\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" className=\"text-xs\">\n {label}\n </TooltipContent>\n </Tooltip>\n );\n },\n);\nIconButton.displayName = \"IconButton\";\n\n// ============================================================================\n// AVATAR COMPONENT\n// ============================================================================\n\ninterface AvatarProps {\n src?: string | null | undefined;\n alt: string;\n initials: string;\n className?: string;\n isClient?: boolean;\n}\n\nfunction Avatar({ src, alt, initials, className, isClient }: AvatarProps) {\n const [imgError, setImgError] = useState(false);\n\n return (\n <div\n className={cn(\n \"relative h-7 w-7 rounded-full overflow-hidden shrink-0\",\n className,\n )}\n >\n {src && !imgError ? (\n <img\n src={src}\n alt={alt}\n className=\"h-full w-full object-cover\"\n onError={() => setImgError(true)}\n />\n ) : (\n <div\n className={cn(\n \"h-full w-full flex items-center justify-center text-[10px] font-medium\",\n isClient\n ? \"bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300\"\n : \"bg-zinc-200 dark:bg-zinc-700 text-zinc-700 dark:text-zinc-300\",\n )}\n >\n {initials}\n </div>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// PARTICIPANT ROW\n// ============================================================================\n\ninterface ParticipantRowProps {\n participant: IEventParticipant;\n isEventCanceled?: boolean | undefined;\n labels: Required<IEventPopoverLabels>;\n}\n\nfunction ParticipantRow({\n participant,\n isEventCanceled = false,\n labels,\n}: ParticipantRowProps) {\n const name = participant.name || \"Unknown\";\n const initials = name\n .split(\" \")\n .map((n) => n[0])\n .join(\"\")\n .toUpperCase()\n .slice(0, 2);\n\n const isOrganizer = participant.isOrganizer ?? false;\n const confirmStatus = participant.isConfirmed;\n const isConfirmed = confirmStatus === true;\n const isDeclined = confirmStatus === false;\n const isClient = participant.isClient ?? false;\n const avatar = participant.profilePicture || participant.avatar;\n\n const showCanceled = isEventCanceled;\n\n return (\n <div\n className={cn(\n \"flex items-center gap-3 py-0\",\n showCanceled && \"opacity-60\",\n )}\n >\n <div className=\"relative\">\n <Avatar\n src={avatar}\n alt={name}\n initials={initials}\n isClient={isClient}\n className={cn(showCanceled && \"grayscale\")}\n />\n {showCanceled || isDeclined ? (\n <div className=\"absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 rounded-full bg-white dark:bg-zinc-900 flex items-center justify-center\">\n <div className=\"h-3 w-3 rounded-full bg-red-100 dark:bg-red-900/50 flex items-center justify-center\">\n <XIcon className=\"h-2 w-2 text-red-600 dark:text-red-400 stroke-[3]\" />\n </div>\n </div>\n ) : isConfirmed ? (\n <div className=\"absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 rounded-full bg-white dark:bg-zinc-900 flex items-center justify-center\">\n <div className=\"h-3 w-3 rounded-full bg-green-100 dark:bg-green-900/50 flex items-center justify-center\">\n <CheckIcon className=\"h-2 w-2 text-green-600 dark:text-green-400 stroke-[3]\" />\n </div>\n </div>\n ) : null}\n </div>\n <div className=\"!h-fit min-w-0 gap-0\">\n <div className=\"gap-0\">\n <span\n className={cn(\n \"text-sm text-zinc-900 dark:text-zinc-100 truncate\",\n showCanceled && \"line-through text-zinc-500 dark:text-zinc-500\",\n )}\n >\n {name}\n </span>\n </div>\n {isClient && (\n <div className=\"text-[10px] px-1.5 w-fit py-0.5 rounded bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300 font-medium\">\n {labels.client}\n </div>\n )}\n {isOrganizer && !showCanceled && (\n <div className=\"text-xs text-zinc-500\">{labels.organizer}</div>\n )}\n </div>\n </div>\n );\n}\n\n// ============================================================================\n// SIMPLE DIALOG (for mobile)\n// ============================================================================\n\ninterface SimpleDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n title?: ReactNode;\n children: ReactNode;\n}\n\nfunction SimpleDialog({\n open,\n onOpenChange,\n title,\n children,\n}: SimpleDialogProps) {\n // Close on escape\n useEffect(() => {\n if (!open) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onOpenChange(false);\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [open, onOpenChange]);\n\n // Prevent body scroll when open\n useEffect(() => {\n if (open) {\n document.body.style.overflow = \"hidden\";\n } else {\n document.body.style.overflow = \"\";\n }\n return () => {\n document.body.style.overflow = \"\";\n };\n }, [open]);\n\n if (!open) return null;\n\n return (\n <div className=\"fixed inset-0 z-50\">\n {/* Backdrop */}\n <div\n className=\"fixed inset-0 bg-black/50 backdrop-blur-sm\"\n onClick={() => onOpenChange(false)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n onOpenChange(false);\n }\n }}\n />\n {/* Content */}\n <div className=\"fixed inset-x-4 top-[50%] translate-y-[-50%] max-w-md mx-auto\">\n <div className=\"bg-white dark:bg-zinc-900 rounded-2xl shadow-xl overflow-hidden\">\n {title && <div className=\"sr-only\">{title}</div>}\n {children}\n </div>\n </div>\n </div>\n );\n}\n\n// ============================================================================\n// ALERT DIALOG (for delete confirmation)\n// ============================================================================\n\ninterface AlertDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n title: string;\n description: string;\n cancelLabel: string;\n confirmLabel: string;\n onConfirm: () => void;\n isLoading?: boolean;\n}\n\nfunction AlertDialog({\n open,\n onOpenChange,\n title,\n description,\n cancelLabel,\n confirmLabel,\n onConfirm,\n isLoading,\n}: AlertDialogProps) {\n if (!open) return null;\n\n return (\n <div className=\"fixed inset-0 z-[60]\">\n {/* Backdrop */}\n <div\n className=\"fixed inset-0 bg-black/50 backdrop-blur-sm\"\n onClick={() => onOpenChange(false)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n onOpenChange(false);\n }\n }}\n />\n {/* Content */}\n <div className=\"fixed inset-x-4 top-[50%] translate-y-[-50%] max-w-md mx-auto\">\n <div className=\"bg-white dark:bg-zinc-900 rounded-lg shadow-xl p-6\">\n <h2 className=\"text-lg font-semibold text-zinc-900 dark:text-zinc-100\">\n {title}\n </h2>\n <p className=\"mt-2 text-sm text-zinc-600 dark:text-zinc-400\">\n {description}\n </p>\n <div className=\"mt-4 flex justify-end gap-3\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onOpenChange(false)}\n >\n {cancelLabel}\n </Button>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n onClick={onConfirm}\n disabled={isLoading}\n >\n {isLoading && <LoaderIcon className=\"h-4 w-4 mr-2\" />}\n <TrashIcon className=\"h-4 w-4 mr-2\" />\n {confirmLabel}\n </Button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n// ============================================================================\n// DATE/TIME FORMATTING HELPERS\n// ============================================================================\n\nfunction defaultFormatDate(date: Date, _format?: string): string {\n return date.toLocaleDateString(undefined, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n });\n}\n\nfunction defaultFormatTimeRange(start: Date, end: Date): string {\n const timeOptions: Intl.DateTimeFormatOptions = {\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false,\n };\n return `${start.toLocaleTimeString(undefined, timeOptions)} – ${end.toLocaleTimeString(undefined, timeOptions)}`;\n}\n\nfunction formatCanceledDate(date: Date): string {\n return date.toLocaleDateString(undefined, {\n day: \"2-digit\",\n month: \"short\",\n year: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\n// ============================================================================\n// MEDIA QUERY HOOK\n// ============================================================================\n\nfunction useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(() => {\n if (typeof window !== \"undefined\") {\n return window.matchMedia(query).matches;\n }\n return false;\n });\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const mediaQuery = window.matchMedia(query);\n const handler = (e: MediaQueryListEvent) => setMatches(e.matches);\n\n mediaQuery.addEventListener(\"change\", handler);\n return () => mediaQuery.removeEventListener(\"change\", handler);\n }, [query]);\n\n return matches;\n}\n\n// ============================================================================\n// POPOVER CONTENT\n// ============================================================================\n\ninterface EventPopoverContentProps<TData = Record<string, unknown>> {\n event: IPopoverEvent<TData>;\n labels: Required<IEventPopoverLabels>;\n isLoading?: boolean | undefined;\n onClose: () => void;\n onEdit?: ((event: IPopoverEvent<TData>) => void) | undefined;\n onDelete?: ((event: IPopoverEvent<TData>) => void) | undefined;\n onCancel?: ((event: IPopoverEvent<TData>) => void) | undefined;\n onAccept?: ((event: IPopoverEvent<TData>) => void) | undefined;\n onDecline?: ((event: IPopoverEvent<TData>) => void) | undefined;\n onConfirmMeeting?: ((event: IPopoverEvent<TData>) => void) | undefined;\n\n // ============================================================================\n // PERMISSION FLAGS\n // ============================================================================\n\n canEdit?: boolean | undefined;\n canDelete?: boolean | undefined;\n canCancel?: boolean | undefined;\n isCurrentUserParticipant?: boolean | undefined;\n isCurrentUserClient?: boolean | undefined;\n currentUserAcceptStatus?: boolean | null | undefined;\n isAcceptLoading?: boolean | undefined;\n isDeclineLoading?: boolean | undefined;\n isConfirmLoading?: boolean | undefined;\n isDeleteLoading?: boolean | undefined;\n renderParticipant?:\n | ((participant: IEventParticipant, index: number) => ReactNode)\n | undefined;\n renderHeaderActions?:\n | ((props: { onClose: () => void }) => ReactNode)\n | undefined;\n renderCancelReason?: ((event: IPopoverEvent<TData>) => ReactNode) | undefined;\n renderDeleteConfirmation?:\n | ((props: {\n onConfirm: () => void;\n onCancel: () => void;\n isLoading?: boolean;\n }) => ReactNode)\n | undefined;\n formatDate?: ((date: Date, format?: string) => string) | undefined;\n formatTimeRange?: ((start: Date, end: Date) => string) | undefined;\n}\n\nfunction EventPopoverContentInner<TData = Record<string, unknown>>({\n event,\n labels,\n isLoading,\n onClose,\n onEdit,\n onDelete,\n onCancel,\n onAccept,\n onDecline,\n onConfirmMeeting,\n canEdit = true,\n canDelete = false,\n canCancel = true,\n isCurrentUserParticipant = false,\n isCurrentUserClient = false,\n currentUserAcceptStatus,\n isAcceptLoading = false,\n isDeclineLoading = false,\n isConfirmLoading = false,\n isDeleteLoading = false,\n renderParticipant,\n renderHeaderActions,\n renderCancelReason,\n renderDeleteConfirmation,\n formatDate = defaultFormatDate,\n formatTimeRange = defaultFormatTimeRange,\n}: EventPopoverContentProps<TData>) {\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n\n // Derived state\n const isEditable = !(event.isCanceled || event.meetingTookPlace);\n const isRecurring = event.isRecurring ?? false;\n\n const participantDetails = event.participantDetails;\n const participantNames = event.participantsNames || [];\n const hasParticipantDetails =\n participantDetails && participantDetails.length > 0;\n\n const hasCurrentUserAccepted = currentUserAcceptStatus === true;\n const hasCurrentUserDeclined = currentUserAcceptStatus === false;\n const showRsvpButtons =\n isCurrentUserParticipant && !isCurrentUserClient && isEditable;\n\n const confirmedCount = hasParticipantDetails\n ? participantDetails.filter((p) => p.isConfirmed).length\n : event.isAccepted\n ? participantNames.length\n : 0;\n\n const totalParticipants = hasParticipantDetails\n ? participantDetails.length\n : participantNames.length;\n\n const eventColor = event.scheduleTypeColor || event.hexColor || \"#039BE5\";\n\n // Format date/time\n const formatDateRange = useCallback(() => {\n if (!event.startDate) return labels.noDateProvided;\n return formatDate(event.startDate);\n }, [event.startDate, formatDate, labels.noDateProvided]);\n\n const getTimeRange = useCallback(() => {\n if (!(event.startDate && event.endDate)) return null;\n return formatTimeRange(event.startDate, event.endDate);\n }, [event.startDate, event.endDate, formatTimeRange]);\n\n // Handlers\n const handleEdit = () => {\n onClose();\n onEdit?.(event);\n };\n\n const handleCancel = () => {\n onClose();\n onCancel?.(event);\n };\n\n const handleDelete = () => {\n setShowDeleteConfirm(true);\n };\n\n const confirmDelete = () => {\n onDelete?.(event);\n setShowDeleteConfirm(false);\n };\n\n // Loading state\n if (isLoading) {\n return (\n <div className=\"flex h-48 items-center justify-center\">\n <LoaderIcon className=\"h-6 w-6 text-zinc-400\" />\n </div>\n );\n }\n\n return (\n <TooltipProvider delayDuration={300}>\n <div className=\"flex flex-col gap-0.5 p-3\">\n {/* Header with action buttons */}\n <div className=\"flex items-start justify-end gap-0.5\">\n {renderHeaderActions ? (\n renderHeaderActions({ onClose })\n ) : (\n <>\n {isEditable && canEdit && onEdit && (\n <IconButton onClick={handleEdit} label={labels.edit}>\n <PencilIcon className=\"h-[18px] w-[18px]\" />\n </IconButton>\n )}\n {isEditable && canCancel && onCancel && (\n <IconButton onClick={handleCancel} label={labels.cancel}>\n <BanIcon className=\"h-[18px] w-[18px]\" />\n </IconButton>\n )}\n {canDelete && onDelete && (\n <IconButton\n onClick={handleDelete}\n label={labels.delete}\n variant=\"destructive\"\n >\n <TrashIcon className=\"h-[18px] w-[18px]\" />\n </IconButton>\n )}\n <IconButton onClick={onClose} label={labels.close}>\n <XIcon className=\"h-[18px] w-[18px]\" />\n </IconButton>\n </>\n )}\n </div>\n\n {/* Event Title & Time */}\n <div>\n <div className=\"flex items-start gap-2\">\n {/* Color indicator */}\n <div\n className=\"w-4 h-4 rounded mt-1 shrink-0\"\n style={{ backgroundColor: eventColor }}\n />\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <h2\n className={cn(\n \"text-[22px] font-normal text-zinc-900 dark:text-zinc-100 leading-tight\",\n event.isCanceled && \"line-through opacity-60\",\n )}\n >\n {event.title}\n </h2>\n {/* Inline status badges */}\n {event.meetingTookPlace && (\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400 text-xs font-medium\">\n <CheckCircleIcon className=\"h-3 w-3\" />\n {labels.completed}\n </span>\n )}\n {event.isCanceled && (\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-400 text-xs font-medium\">\n <XIcon className=\"h-3 w-3\" />\n {labels.canceled}\n </span>\n )}\n </div>\n <div className=\"mt-1 text-sm text-zinc-600 dark:text-zinc-400\">\n <span>{formatDateRange()}</span>\n {getTimeRange() && (\n <>\n <span className=\"mx-1.5\">·</span>\n <span>{getTimeRange()}</span>\n </>\n )}\n </div>\n {isRecurring && event.recurrenceSummary && (\n <div className=\"text-sm text-zinc-500 dark:text-zinc-500\">\n {event.recurrenceSummary}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Cancellation Note Section */}\n {event.isCanceled && (\n <div className=\"mx-4 p-3 rounded-lg bg-red-50 dark:bg-red-950/30\">\n {renderCancelReason ? (\n renderCancelReason(event)\n ) : (\n <div className=\"flex items-start gap-0\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium text-red-700 dark:text-red-400\">\n {labels.cancellationNote}\n </div>\n {event.cancelReason && (\n <div className=\"mt-1 text-sm text-red-600/80 dark:text-red-400/80 italic\">\n &quot;{event.cancelReason}&quot;\n </div>\n )}\n {event.canceledDate && (\n <div className=\"mt-1.5 text-xs text-red-500/70 dark:text-red-400/60\">\n {labels.canceledOn}{\" \"}\n {formatCanceledDate(event.canceledDate)}\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Content sections */}\n <div className=\"space-y-0.5\">\n {/* Location */}\n {event.address && (\n <div className=\"flex items-start gap-2\">\n <MapPinIcon className=\"h-5 w-5 text-zinc-400 mt-0.5 shrink-0\" />\n <span className=\"text-sm text-zinc-700 dark:text-zinc-300\">\n {event.address}\n </span>\n </div>\n )}\n\n {/* Participants */}\n {(hasParticipantDetails || participantNames.length > 0) && (\n <div className=\"flex items-start gap-2 py-0\">\n <UsersIcon className=\"h-5 w-5 text-zinc-400 mt-0.5 shrink-0\" />\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-0\">\n <span className=\"text-sm text-zinc-900 dark:text-zinc-100 font-medium\">\n {totalParticipants}{\" \"}\n {totalParticipants !== 1 ? labels.guests : labels.guest}\n </span>\n {totalParticipants > 0 && (\n <span className=\"text-xs text-zinc-500\">\n ({confirmedCount} {labels.confirmed})\n </span>\n )}\n </div>\n <div className=\"mt-2 space-y-2\">\n {hasParticipantDetails\n ? participantDetails\n .slice(0, 6)\n .map((p, idx) =>\n renderParticipant ? (\n renderParticipant(p, idx)\n ) : (\n <ParticipantRow\n key={p.id}\n participant={p}\n isEventCanceled={event.isCanceled}\n labels={labels}\n />\n ),\n )\n : participantNames.slice(0, 6).map((name, idx) => {\n const fallbackParticipant: IEventParticipant = {\n id: String(idx),\n name,\n email: \"\",\n isConfirmed: event.isAccepted,\n isOrganizer: idx === 0,\n isClient: false,\n };\n return renderParticipant ? (\n renderParticipant(fallbackParticipant, idx)\n ) : (\n <ParticipantRow\n key={name}\n participant={fallbackParticipant}\n isEventCanceled={event.isCanceled}\n labels={labels}\n />\n );\n })}\n {totalParticipants > 6 && (\n <div className=\"text-xs text-zinc-500 py-1.5 pl-10\">\n +{totalParticipants - 6} {labels.more}\n </div>\n )}\n </div>\n </div>\n </div>\n )}\n\n {/* Description */}\n {event.description && (\n <div className=\"flex items-start gap-2\">\n <FileTextIcon className=\"h-5 w-5 text-zinc-400 mt-0.5 shrink-0\" />\n <p className=\"text-sm text-zinc-700 dark:text-zinc-300 whitespace-pre-wrap\">\n {event.description}\n </p>\n </div>\n )}\n\n {/* Calendar/Organizer */}\n <div className=\"flex items-start gap-2\">\n <CalendarIcon className=\"h-5 w-5 text-zinc-400 mt-0.5 shrink-0\" />\n <div className=\"text-sm text-zinc-700 dark:text-zinc-300\">\n {(hasParticipantDetails &&\n participantDetails.find((p) => p.isOrganizer)?.name) ||\n participantNames[0] ||\n \"Calendar\"}\n </div>\n </div>\n </div>\n\n {/* RSVP Section */}\n {showRsvpButtons && onAccept && onDecline && (\n <div className=\"border-t border-zinc-100 dark:border-zinc-800 mt-3 py-3\">\n <div className=\"flex items-center gap-2\">\n {/* Going button with recurring dropdown */}\n {isRecurring ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <div className=\"flex\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n className={cn(\n \"rounded-r-none gap-1.5 h-8 !border-none !bg-green-100 text-green-800 hover:!bg-green-200\",\n hasCurrentUserAccepted &&\n \"!bg-green-700 !text-white hover:!bg-green-700\",\n )}\n onClick={(e) => {\n e.stopPropagation();\n if (!hasCurrentUserAccepted) {\n onAccept(event);\n }\n }}\n disabled={isAcceptLoading}\n >\n {isAcceptLoading ? (\n <LoaderIcon className=\"h-3.5 w-3.5\" />\n ) : (\n <>\n {hasCurrentUserAccepted && (\n <CheckIcon className=\"h-3.5 w-3.5\" />\n )}\n {labels.going}\n </>\n )}\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n className={cn(\n \"rounded-l-none px-1.5 h-8 !border-none !bg-green-100 text-green-800 hover:!bg-green-200\",\n hasCurrentUserAccepted &&\n \"!bg-green-700 !text-white hover:!bg-green-700\",\n )}\n >\n <ChevronDownIcon className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\">\n <DropdownMenuItem\n className={cn(\n \"gap-1.5 h-8 !border-none !bg-green-50 text-green-800 hover:!bg-green-100\",\n hasCurrentUserAccepted &&\n \"!bg-green-700 !text-white hover:!bg-green-700\",\n )}\n onClick={() => onAccept(event)}\n >\n <CheckIcon className=\"h-3.5 w-3.5 mr-2 text-green-600\" />\n {labels.acceptThisEvent}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => onAccept(event)}>\n <CheckIcon className=\"h-3.5 w-3.5 mr-2 text-green-600\" />\n {labels.acceptAllEvents}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : (\n <Button\n size=\"sm\"\n variant=\"outline\"\n className={cn(\n \"gap-1.5 h-8 !border-none !bg-green-100 text-green-800 hover:!bg-green-200\",\n hasCurrentUserAccepted &&\n \"!bg-green-700 !text-white hover:!bg-green-700\",\n )}\n onClick={() => {\n if (!hasCurrentUserAccepted) {\n onAccept(event);\n }\n }}\n disabled={isAcceptLoading}\n >\n {isAcceptLoading ? (\n <LoaderIcon className=\"h-3.5 w-3.5\" />\n ) : (\n <>\n {hasCurrentUserAccepted && (\n <CheckIcon className=\"h-3.5 w-3.5\" />\n )}\n {labels.going}\n </>\n )}\n </Button>\n )}\n\n {/* Not Going button */}\n <Button\n size=\"sm\"\n variant=\"outline\"\n className={cn(\n \"gap-1.5 h-8 !border-none !bg-rose-100 text-rose-800 hover:!bg-rose-200\",\n hasCurrentUserDeclined &&\n \"!bg-rose-700 !text-white hover:!bg-rose-700\",\n )}\n onClick={() => {\n if (!hasCurrentUserDeclined) {\n onDecline(event);\n }\n }}\n disabled={isDeclineLoading}\n >\n {isDeclineLoading ? (\n <LoaderIcon className=\"h-3.5 w-3.5\" />\n ) : (\n <>\n {hasCurrentUserDeclined && (\n <XIcon className=\"h-3.5 w-3.5\" />\n )}\n {labels.notGoing}\n </>\n )}\n </Button>\n </div>\n </div>\n )}\n\n {/* Confirm meeting took place */}\n {isCurrentUserParticipant &&\n hasCurrentUserAccepted &&\n !event.meetingTookPlace &&\n !event.isCanceled &&\n onConfirmMeeting && (\n <div className=\"border-t border-zinc-100 dark:border-zinc-800 py-3\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"w-full h-9 hover:!bg-green-100 hover:text-green-700 text-green-700 !bg-green-100 !border-none dark:text-green-400 dark:hover:bg-green-950/30\"\n onClick={() => onConfirmMeeting(event)}\n disabled={isConfirmLoading}\n >\n {isConfirmLoading && <LoaderIcon className=\"h-4 w-4 mr-2\" />}\n {labels.confirmMeeting}\n </Button>\n </div>\n )}\n </div>\n\n {/* Delete Confirmation Dialog */}\n {renderDeleteConfirmation ? (\n showDeleteConfirm &&\n renderDeleteConfirmation({\n onConfirm: confirmDelete,\n onCancel: () => setShowDeleteConfirm(false),\n isLoading: isDeleteLoading,\n })\n ) : (\n <AlertDialog\n open={showDeleteConfirm}\n onOpenChange={setShowDeleteConfirm}\n title={labels.deleteConfirmTitle}\n description={labels.deleteConfirmDescription}\n cancelLabel={labels.cancel}\n confirmLabel={labels.delete}\n onConfirm={confirmDelete}\n isLoading={isDeleteLoading}\n />\n )}\n </TooltipProvider>\n );\n}\n\n// ============================================================================\n// MAIN COMPONENT\n// ============================================================================\n\nexport function EventPopover<TData = Record<string, unknown>>({\n event,\n children,\n open,\n onOpenChange,\n isLoading,\n labels: customLabels,\n onEdit,\n onDelete,\n onCancel,\n onAccept,\n onDecline,\n onConfirmMeeting,\n canEdit = true,\n canDelete = false,\n canCancel = true,\n isCurrentUserParticipant,\n isCurrentUserClient,\n currentUserAcceptStatus,\n isAcceptLoading,\n isDeclineLoading,\n isConfirmLoading,\n isDeleteLoading,\n renderParticipant,\n renderHeaderActions,\n renderCancelReason,\n renderDeleteConfirmation,\n formatDate,\n formatTimeRange,\n className,\n width = 360,\n}: EventPopoverProps<TData>): React.JSX.Element {\n const isDesktop = useMediaQuery(\"(min-width: 768px)\");\n const labels = { ...DEFAULT_LABELS, ...customLabels };\n\n const handleClose = useCallback(() => {\n onOpenChange?.(false);\n }, [onOpenChange]);\n\n const contentProps: EventPopoverContentProps<TData> = {\n event,\n labels,\n isLoading,\n onClose: handleClose,\n onEdit,\n onDelete,\n onCancel,\n onAccept,\n onDecline,\n onConfirmMeeting,\n canEdit,\n canDelete,\n canCancel,\n isCurrentUserParticipant,\n isCurrentUserClient,\n currentUserAcceptStatus,\n isAcceptLoading,\n isDeclineLoading,\n isConfirmLoading,\n isDeleteLoading,\n renderParticipant,\n renderHeaderActions,\n renderCancelReason,\n renderDeleteConfirmation,\n formatDate,\n formatTimeRange,\n };\n\n // Desktop: Use Popover with smart positioning\n if (isDesktop) {\n return (\n <Popover open={open ?? false} onOpenChange={onOpenChange ?? (() => {})}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <PopoverContent\n className={cn(\n \"p-0 shadow-lg !rounded-2xl bg-white dark:bg-zinc-900 overflow-hidden border z-50\",\n className,\n )}\n style={{ width }}\n align=\"center\"\n side=\"bottom\"\n sideOffset={4}\n >\n <EventPopoverContentInner {...contentProps} />\n </PopoverContent>\n </Popover>\n );\n }\n\n // Mobile: Use Dialog\n return (\n <>\n {children}\n <SimpleDialog\n open={open ?? false}\n onOpenChange={onOpenChange ?? (() => {})}\n title={event.title}\n >\n <EventPopoverContentInner {...contentProps} />\n </SimpleDialog>\n </>\n );\n}\n\nexport default EventPopover;\n","/**\n * The built-in settings panel.\n *\n * The package already owns these preferences — slot duration, visible hours,\n * working hours, badge style — and persists them. Until now it shipped the\n * state without the UI, so every consuming app rebuilt the same four controls\n * on top of the same context. This is that UI, once.\n *\n * Anything a consumer locks through `preferencesConfig.locked` is hidden rather\n * than shown disabled: a control you are not allowed to touch is noise.\n */\n\nimport type { TBadgeVariant, TSlotDuration } from '../../core/types';\nimport { useOptionalInnoCalendar } from '../../core/context/inno-calendar-provider';\nimport { cn } from '../../lib/utils';\n\nexport interface CalendarSettingsLabels {\n\ttitle: string;\n\tinterval: string;\n\tdayStart: string;\n\tdayEnd: string;\n\tworkingHoursOnly: string;\n\teventStyle: string;\n\tbadgeDot: string;\n\tbadgeColored: string;\n\tbadgeMixed: string;\n\tminutes: string;\n}\n\nconst DEFAULT_LABELS: CalendarSettingsLabels = {\n\ttitle: 'Calendar settings',\n\tinterval: 'Time interval',\n\tdayStart: 'Day starts',\n\tdayEnd: 'Day ends',\n\tworkingHoursOnly: 'Working hours only',\n\teventStyle: 'Event style',\n\tbadgeDot: 'Dot',\n\tbadgeColored: 'Colour',\n\tbadgeMixed: 'Mixed',\n\tminutes: 'min',\n};\n\nconst SLOT_DURATIONS: TSlotDuration[] = [15, 30, 60];\nconst HOURS = Array.from({ length: 25 }, (_, i) => i);\n\nfunction Row({ label, children }: { label: string; children: React.ReactNode }) {\n\treturn (\n\t\t<div className=\"flex items-center justify-between gap-4\">\n\t\t\t<span className=\"text-sm text-foreground\">{label}</span>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n\n/** A small segmented control — enough for three or fewer options. */\nfunction Segmented<T extends string | number>({\n\toptions,\n\tvalue,\n\tonChange,\n}: {\n\toptions: { value: T; label: string }[];\n\tvalue: T;\n\tonChange: (next: T) => void;\n}) {\n\treturn (\n\t\t<div className=\"flex overflow-hidden rounded-md border border-border\">\n\t\t\t{options.map((option) => (\n\t\t\t\t<button\n\t\t\t\t\tkey={String(option.value)}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => onChange(option.value)}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'px-2.5 py-1 text-xs',\n\t\t\t\t\t\toption.value === value\n\t\t\t\t\t\t\t? 'bg-primary text-primary-foreground'\n\t\t\t\t\t\t\t: 'bg-background hover:bg-accent hover:text-accent-foreground'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{option.label}\n\t\t\t\t</button>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\nfunction HourSelect({\n\tvalue,\n\tonChange,\n\tlabel,\n}: {\n\tvalue: number;\n\tonChange: (next: number) => void;\n\tlabel: string;\n}) {\n\treturn (\n\t\t<select\n\t\t\taria-label={label}\n\t\t\tvalue={value}\n\t\t\tonChange={(e) => onChange(Number(e.target.value))}\n\t\t\tclassName={cn(\n\t\t\t\t'rounded-md border border-border bg-background px-2 py-1 text-xs',\n\t\t\t\t'focus:outline-none focus:ring-1 focus:ring-ring'\n\t\t\t)}\n\t\t>\n\t\t\t{HOURS.map((hour) => (\n\t\t\t\t<option key={hour} value={hour}>\n\t\t\t\t\t{String(hour).padStart(2, '0')}:00\n\t\t\t\t</option>\n\t\t\t))}\n\t\t</select>\n\t);\n}\n\nexport interface CalendarSettingsProps {\n\tlabels?: Partial<CalendarSettingsLabels> | undefined;\n}\n\nexport function CalendarSettings({ labels }: CalendarSettingsProps) {\n\tconst calendar = useOptionalInnoCalendar();\n\tconst text = { ...DEFAULT_LABELS, ...labels };\n\n\t// Rendered outside a provider (the header is exported standalone) — nothing\n\t// to configure, so say nothing.\n\tif (!calendar) return null;\n\n\tconst {\n\t\tslotDuration,\n\t\tsetSlotDuration,\n\t\tvisibleHours,\n\t\tsetVisibleHours,\n\t\tshowWorkingHoursOnly,\n\t\tsetShowWorkingHoursOnly,\n\t\tbadgeVariant,\n\t\tsetBadgeVariant,\n\t\tisPreferenceLocked,\n\t} = calendar;\n\n\tconst locked = (key: Parameters<typeof isPreferenceLocked>[0]) =>\n\t\tisPreferenceLocked(key);\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<p className=\"text-sm font-medium\">{text.title}</p>\n\n\t\t\t{!locked('slotDuration') && (\n\t\t\t\t<Row label={text.interval}>\n\t\t\t\t\t<Segmented\n\t\t\t\t\t\tvalue={slotDuration}\n\t\t\t\t\t\tonChange={(v) => setSlotDuration(v as TSlotDuration)}\n\t\t\t\t\t\toptions={SLOT_DURATIONS.map((d) => ({\n\t\t\t\t\t\t\tvalue: d,\n\t\t\t\t\t\t\tlabel: `${d} ${text.minutes}`,\n\t\t\t\t\t\t}))}\n\t\t\t\t\t/>\n\t\t\t\t</Row>\n\t\t\t)}\n\n\t\t\t{!locked('visibleHours') && (\n\t\t\t\t<>\n\t\t\t\t\t<Row label={text.dayStart}>\n\t\t\t\t\t\t<HourSelect\n\t\t\t\t\t\t\tlabel={text.dayStart}\n\t\t\t\t\t\t\tvalue={visibleHours.start}\n\t\t\t\t\t\t\tonChange={(start) =>\n\t\t\t\t\t\t\t\tsetVisibleHours((prev) => ({\n\t\t\t\t\t\t\t\t\t...prev,\n\t\t\t\t\t\t\t\t\tstart: Math.min(start, prev.end - 1),\n\t\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</Row>\n\t\t\t\t\t<Row label={text.dayEnd}>\n\t\t\t\t\t\t<HourSelect\n\t\t\t\t\t\t\tlabel={text.dayEnd}\n\t\t\t\t\t\t\tvalue={visibleHours.end}\n\t\t\t\t\t\t\tonChange={(end) =>\n\t\t\t\t\t\t\t\tsetVisibleHours((prev) => ({\n\t\t\t\t\t\t\t\t\t...prev,\n\t\t\t\t\t\t\t\t\tend: Math.max(end, prev.start + 1),\n\t\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</Row>\n\t\t\t\t</>\n\t\t\t)}\n\n\t\t\t{!locked('showWorkingHoursOnly') && (\n\t\t\t\t<Row label={text.workingHoursOnly}>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\trole=\"switch\"\n\t\t\t\t\t\taria-checked={showWorkingHoursOnly}\n\t\t\t\t\t\tonClick={() => setShowWorkingHoursOnly(!showWorkingHoursOnly)}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'relative h-5 w-9 rounded-full transition-colors',\n\t\t\t\t\t\t\tshowWorkingHoursOnly ? 'bg-primary' : 'bg-muted'\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'absolute top-0.5 size-4 rounded-full bg-background transition-all',\n\t\t\t\t\t\t\t\tshowWorkingHoursOnly ? 'left-[18px]' : 'left-0.5'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</button>\n\t\t\t\t</Row>\n\t\t\t)}\n\n\t\t\t{!locked('badgeVariant') && (\n\t\t\t\t<Row label={text.eventStyle}>\n\t\t\t\t\t<Segmented\n\t\t\t\t\t\tvalue={badgeVariant}\n\t\t\t\t\t\tonChange={(v) => setBadgeVariant(v as TBadgeVariant)}\n\t\t\t\t\t\toptions={[\n\t\t\t\t\t\t\t{ value: 'dot' as const, label: text.badgeDot },\n\t\t\t\t\t\t\t{ value: 'colored' as const, label: text.badgeColored },\n\t\t\t\t\t\t\t{ value: 'mixed' as const, label: text.badgeMixed },\n\t\t\t\t\t\t]}\n\t\t\t\t\t/>\n\t\t\t\t</Row>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","/**\n * Calendar Header Component\n *\n * Navigation and view controls for the calendar.\n * Matches the production agenda-v2 implementation.\n *\n * Features:\n * - Styled TodayButton with calendar icon\n * - DateNavigator with event count and range text\n * - Calendar View dropdown (Day, Week, Month, Year)\n * - Timeline View dropdown (Resource views)\n * - Settings popover slot (via settingsContent prop)\n * - Filter row slot (via filterContent prop)\n * - Add event button\n */\n\nimport { type ReactNode, useMemo } from 'react';\nimport { CONTROL, CONTROL_ICON } from '../../core/constants';\nimport type { CalendarEvent, ICalendarHeaderConfig, TCalendarView } from '../../core/types';\nimport { endOfWeek, startOfWeek } from '../../core/utils/date-utils';\nimport { cn } from '../../lib/utils';\nimport { CalendarSettings } from '../shell/calendar-settings';\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\n\n// ============================================================================\n// ICONS (Inline SVGs for zero dependencies)\n// ============================================================================\n\nfunction GanttChartSquare({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n\t\t\t<path d=\"M9 8h7\" />\n\t\t\t<path d=\"M8 12h6\" />\n\t\t\t<path d=\"M11 16h5\" />\n\t\t</svg>\n\t);\n}\n\nfunction ChevronDown({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<path d=\"m6 9 6 6 6-6\" />\n\t\t</svg>\n\t);\n}\n\nfunction Gear({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\tclassName={className}\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<circle cx=\"12\" cy=\"12\" r=\"3\" />\n\t\t\t<path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z\" />\n\t\t</svg>\n\t);\n}\n\nfunction LayoutList({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<rect width=\"7\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\" />\n\t\t\t<rect width=\"7\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\" />\n\t\t\t<path d=\"M14 4h7\" />\n\t\t\t<path d=\"M14 9h7\" />\n\t\t\t<path d=\"M14 15h7\" />\n\t\t\t<path d=\"M14 20h7\" />\n\t\t</svg>\n\t);\n}\n\n/** Schedule: a list of lines, each with its bullet. */\n/** Four days: four narrow columns. */\nfunction ColumnsFour({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n\t\t\t<path d=\"M8 3v18\" />\n\t\t\t<path d=\"M12 3v18\" />\n\t\t\t<path d=\"M16 3v18\" />\n\t\t</svg>\n\t);\n}\n\nfunction ListIcon({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<path d=\"M8 6h13\" />\n\t\t\t<path d=\"M8 12h13\" />\n\t\t\t<path d=\"M8 18h13\" />\n\t\t\t<path d=\"M3 6h.01\" />\n\t\t\t<path d=\"M3 12h.01\" />\n\t\t\t<path d=\"M3 18h.01\" />\n\t\t</svg>\n\t);\n}\n\nfunction Columns({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n\t\t\t<path d=\"M12 3v18\" />\n\t\t</svg>\n\t);\n}\n\nfunction Grid2X2({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n\t\t\t<path d=\"M3 12h18\" />\n\t\t\t<path d=\"M12 3v18\" />\n\t\t</svg>\n\t);\n}\n\nfunction Grid3X3({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n\t\t\t<path d=\"M3 9h18\" />\n\t\t\t<path d=\"M3 15h18\" />\n\t\t\t<path d=\"M9 3v18\" />\n\t\t\t<path d=\"M15 3v18\" />\n\t\t</svg>\n\t);\n}\n\n// function ListIcon({ className }: { className?: string }) {\n// return (\n// <svg\n// className={className}\n// xmlns=\"http://www.w3.org/2000/svg\"\n// width=\"24\"\n// height=\"24\"\n// viewBox=\"0 0 24 24\"\n// fill=\"none\"\n// stroke=\"currentColor\"\n// strokeWidth=\"2\"\n// strokeLinecap=\"round\"\n// strokeLinejoin=\"round\"\n// >\n// <line x1=\"8\" x2=\"21\" y1=\"6\" y2=\"6\" />\n// <line x1=\"8\" x2=\"21\" y1=\"12\" y2=\"12\" />\n// <line x1=\"8\" x2=\"21\" y1=\"18\" y2=\"18\" />\n// <line x1=\"3\" x2=\"3.01\" y1=\"6\" y2=\"6\" />\n// <line x1=\"3\" x2=\"3.01\" y1=\"12\" y2=\"12\" />\n// <line x1=\"3\" x2=\"3.01\" y1=\"18\" y2=\"18\" />\n// </svg>\n// );\n// }\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface ViewOption {\n\tvalue: TCalendarView;\n\tlabel: string;\n\ticon: React.ComponentType<{ className?: string }>;\n}\n\nexport interface CalendarHeaderProps<TData = Record<string, unknown>> {\n\t/** Current date */\n\tcurrentDate: Date;\n\t/** Current view */\n\tview: TCalendarView;\n\t/** Events for count display */\n\tevents?: CalendarEvent<TData>[];\n\t/** Navigate to today */\n\tonNavigateToday?: () => void;\n\t/** Navigate prev */\n\tonNavigatePrev?: () => void;\n\t/** Navigate next */\n\tonNavigateNext?: () => void;\n\t/** Navigate callback (legacy) */\n\tonNavigate?: (direction: 'prev' | 'next' | 'today') => void;\n\t/** View change callback */\n\tonViewChange?: (view: TCalendarView) => void;\n\t/** Add event callback */\n\tonAddEvent?: () => void;\n\t/** Available calendar views to show */\n\tavailableViews?: readonly TCalendarView[];\n\t/** Show timeline views dropdown */\n\tshowTimelineViews?: boolean;\n\t/** Available timeline views */\n\ttimelineViews?: TCalendarView[];\n\t/** Settings content (rendered in popover) */\n\tsettingsContent?: ReactNode;\n\t/** Show settings button */\n\tshowSettings?: boolean;\n\t/** Filter row content */\n\tfilterContent?: ReactNode;\n\n\t/**\n\t * Rendered before \"Today\". The calendar puts the sidebar's sheet trigger\n\t * here at the widths where the rail itself is hidden.\n\t */\n\tleadingAction?: ReactNode;\n\t/** Additional actions to render */\n\tactions?: ReactNode;\n\t/** Additional CSS classes */\n\tclassName?: string;\n\t/** Week starts on (0 = Sunday, 1 = Monday) */\n\tweekStartsOn?: 0 | 1;\n\t/** Intl locale for the toolbar title. */\n\tlocale?: string;\n\t/** Text of the Today pill. @default 'Today' */\n\ttodayLabel?: string;\n\t/**\n\t * Granular header visibility configuration.\n\t * When provided, individual keys override `showTimelineViews`, `showSettings`,\n\t * and other visibility props for a clean single-object API.\n\t *\n\t * @see {@link ICalendarHeaderConfig}\n\t */\n\theaderConfig?: ICalendarHeaderConfig;\n\t/** Labels for i18n */\n\tlabels?: {\n\t\ttoday?: string;\n\t\tday?: string;\n\t\t/** Quoted: a key cannot start with a digit unquoted. */\n\t\t'4day'?: string;\n\t\tweek?: string;\n\t\tmonth?: string;\n\t\tyear?: string;\n\t\tagenda?: string;\n\t\taddEvent?: string;\n\t\tcalendarView?: string;\n\t\tresourceView?: string;\n\t};\n}\n\n// ============================================================================\n// VIEW CONFIGURATION\n// ============================================================================\n\n/** Calendar grid views */\nconst CALENDAR_VIEWS: ViewOption[] = [\n\t{ value: 'day', label: 'Day', icon: LayoutList },\n\t{ value: '4day', label: '4 days', icon: ColumnsFour },\n\t{ value: 'week', label: 'Week', icon: Columns },\n\t{ value: 'month', label: 'Month', icon: Grid2X2 },\n\t{ value: 'year', label: 'Year', icon: Grid3X3 },\n\t{ value: 'agenda', label: 'Schedule', icon: ListIcon },\n];\n\n/** Keyboard shortcuts, shown in the menu and handled by the calendar. */\nconst VIEW_SHORTCUTS: Partial<Record<TCalendarView, string>> = {\n\tday: 'D',\n\t// Google's own shortcut for the four-day view.\n\t'4day': 'X',\n\tweek: 'W',\n\tmonth: 'M',\n\tyear: 'Y',\n\tagenda: 'A',\n};\n\n/** Timeline/Resource views */\n/**\n * One entry per distinct layout. `timeline-day`/`resource-day` both render\n * vertical columns and `timeline-week`/`resource-week` are identical lanes, so\n * offering all four only ever made the menu look like it had duplicates.\n */\nconst TIMELINE_VIEWS: ViewOption[] = [\n\t{ value: 'timeline-3day', label: '3 Days', icon: GanttChartSquare },\n\t{ value: 'timeline-week', label: 'Week', icon: GanttChartSquare },\n];\n\n/** Kept so a persisted value still resolves to a label. */\nconst RESOURCE_VIEWS: ViewOption[] = [\n\t{ value: 'timeline-day', label: 'Day', icon: GanttChartSquare },\n\t{ value: 'resource-day', label: 'Day', icon: GanttChartSquare },\n\t{ value: 'resource-week', label: 'Week', icon: GanttChartSquare },\n];\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\n/**\n * The toolbar title, the way Google writes it: month and year, widening to a\n * range only when the visible week straddles two months.\n */\nfunction useToolbarTitle(\n\tcurrentDate: Date,\n\tview: TCalendarView,\n\tweekStartsOn: 0 | 1,\n\tlocale?: string\n): string {\n\tconst monthYear = (d: Date) =>\n\t\tnew Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(d);\n\n\tif (view === 'day' || view === 'timeline-day' || view === 'resource-day') {\n\t\treturn new Intl.DateTimeFormat(locale, {\n\t\t\tmonth: 'long',\n\t\t\tday: 'numeric',\n\t\t\tyear: 'numeric',\n\t\t}).format(currentDate);\n\t}\n\n\tif (view === 'year') {\n\t\treturn new Intl.DateTimeFormat(locale, { year: 'numeric' }).format(currentDate);\n\t}\n\n\tconst start = startOfWeek(currentDate, weekStartsOn);\n\tconst end = endOfWeek(currentDate, weekStartsOn);\n\tif (view === 'month' || start.getMonth() === end.getMonth()) {\n\t\treturn monthYear(currentDate);\n\t}\n\n\tconst short = (d: Date) => new Intl.DateTimeFormat(locale, { month: 'short' }).format(d);\n\treturn `${short(start)} – ${short(end)} ${end.getFullYear()}`;\n}\n\nfunction NavChevron({ dir }: { dir: 'prev' | 'next' }) {\n\treturn (\n\t\t<svg viewBox=\"0 0 24 24\" className=\"size-5\" fill=\"none\" aria-hidden=\"true\">\n\t\t\t<path\n\t\t\t\td={dir === 'prev' ? 'M15 18L9 12l6-6' : 'M9 18l6-6-6-6'}\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n\n/** \"Resources · 7 days\" reads better in one list than a bare \"7 Days\". */\nfunction resourceLabel(option: ViewOption): string {\n\treturn `People · ${option.label}`;\n}\n\nexport function CalendarHeader<TData = Record<string, unknown>>({\n\tcurrentDate,\n\tview,\n\tonNavigateToday,\n\tonNavigatePrev,\n\tonNavigateNext,\n\tonNavigate,\n\tonViewChange,\n\tonAddEvent: _onAddEvent,\n\tavailableViews = ['day', '4day', 'week', 'month', 'agenda'],\n\tshowTimelineViews: _showTimelineViews = false,\n\ttimelineViews: _timelineViews,\n\tsettingsContent,\n\tshowSettings = true,\n\tfilterContent,\n\tleadingAction,\n\tactions,\n\tclassName,\n\tweekStartsOn = 1,\n\tlocale,\n\ttodayLabel = 'Today',\n\theaderConfig,\n\tlabels = {},\n}: CalendarHeaderProps<TData>) {\n\t// Resolve visibility from headerConfig (overrides legacy individual booleans)\n\tconst resolvedShowSettings = headerConfig?.showSettings ?? showSettings;\n\n\tconst toolbarTitle = useToolbarTitle(currentDate, view, weekStartsOn, locale);\n\n\tconst resolvedShowToday = headerConfig?.showToday ?? true;\n\tconst resolvedShowDateNav = headerConfig?.showDateNavigator ?? true;\n\tconst resolvedShowCalViews = headerConfig?.showCalendarViews ?? true;\n\tconst resolvedShowFilters = headerConfig?.showFilters ?? true;\n\t// Merge labels\n\tconst mergedLabels = useMemo(\n\t\t() => ({\n\t\t\ttoday: 'Today',\n\t\t\taddEvent: 'Add Event',\n\t\t\tsettings: 'Settings',\n\t\t\tcalendarView: 'Calendar View',\n\t\t\tresourceView: 'Resource View',\n\t\t\t...labels,\n\t\t}),\n\t\t[labels]\n\t);\n\n\t// Handle navigation (support both new and legacy callbacks)\n\tconst handleToday = () => {\n\t\tonNavigateToday?.();\n\t\tonNavigate?.('today');\n\t};\n\tconst handlePrev = () => {\n\t\tonNavigatePrev?.();\n\t\tonNavigate?.('prev');\n\t};\n\tconst handleNext = () => {\n\t\tonNavigateNext?.();\n\t\tonNavigate?.('next');\n\t};\n\n\t// Filter available views. The names are translatable: `labels.day` and\n\t// friends were declared but never read, so every view read as English\n\t// whatever language the app was in.\n\tconst viewLabel = (option: ViewOption) =>\n\t\t(mergedLabels as Record<string, string | undefined>)[option.value] ?? option.label;\n\n\tconst calendarViewOptions = CALENDAR_VIEWS.filter((v) => availableViews.includes(v.value));\n\n\t// Get current timeline view label\n\tconst currentCalendarView = CALENDAR_VIEWS.find((v) => v.value === view);\n\tconst currentViewLabel =\n\t\t(currentCalendarView && viewLabel(currentCalendarView)) ??\n\t\t(() => {\n\t\t\tconst found = [...TIMELINE_VIEWS, ...RESOURCE_VIEWS].find((v) => v.value === view);\n\t\t\treturn found ? resourceLabel(found) : view;\n\t\t})();\n\n\treturn (\n\t\t<div className={cn('flex flex-col w-full gap-3 mb-2', className)}>\n\t\t\t{/* Main header row: Today + Date + View selectors + Settings + Add */}\n\t\t\t<div className=\"flex lg:flex-row flex-col w-full justify-between gap-3\">\n\t\t\t\t{/* Left: Today + arrows + title, on one row as Google lays it out */}\n\t\t\t\t<div className=\"flex items-center justify-between gap-2\">\n\t\t\t\t\t<div className=\"flex items-center gap-2 min-w-0\">\n\t\t\t\t\t\t{leadingAction}\n\t\t\t\t\t\t{resolvedShowToday && (\n\t\t\t\t\t\t\t<button type=\"button\" onClick={handleToday} className={CONTROL}>\n\t\t\t\t\t\t\t\t{todayLabel}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{resolvedShowDateNav && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<div className=\"flex shrink-0 items-center\">\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\taria-label=\"Previous\"\n\t\t\t\t\t\t\t\t\t\tonClick={handlePrev}\n\t\t\t\t\t\t\t\t\t\tclassName={CONTROL_ICON}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<NavChevron dir=\"prev\" />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\taria-label=\"Next\"\n\t\t\t\t\t\t\t\t\t\tonClick={handleNext}\n\t\t\t\t\t\t\t\t\t\tclassName={CONTROL_ICON}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<NavChevron dir=\"next\" />\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<h2 className=\"truncate text-[22px] font-normal leading-tight\">{toolbarTitle}</h2>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Right: View selectors and controls */}\n\t\t\t\t<div className=\"flex items-center gap-1.5 sm:gap-2 overflow-x-auto pb-1 -mb-1 scrollbar-none\">\n\t\t\t\t\t{/* One view menu, as Google has it: the calendar views, then this\n product's resource views, each with its keyboard shortcut. */}\n\t\t\t\t\t{onViewChange && resolvedShowCalViews && (\n\t\t\t\t\t\t<DropdownMenu>\n\t\t\t\t\t\t\t<DropdownMenuTrigger className={cn(CONTROL, 'gap-1.5')}>\n\t\t\t\t\t\t\t\t<span>{currentViewLabel}</span>\n\t\t\t\t\t\t\t\t<ChevronDown className=\"size-3.5 opacity-60\" />\n\t\t\t\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t\t\t\t<DropdownMenuContent align=\"end\" className=\"min-w-[220px]\">\n\t\t\t\t\t\t\t\t{resolvedShowCalViews &&\n\t\t\t\t\t\t\t\t\tcalendarViewOptions.map((viewOption) => (\n\t\t\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\t\t\tkey={viewOption.value}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => onViewChange(viewOption.value)}\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(view === viewOption.value && 'bg-accent')}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<span>{viewLabel(viewOption)}</span>\n\t\t\t\t\t\t\t\t\t\t\t{VIEW_SHORTCUTS[viewOption.value] && (\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"ml-auto pl-6 text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t{VIEW_SHORTCUTS[viewOption.value]}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t\t\t</DropdownMenu>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Custom actions */}\n\t\t\t\t\t{actions}\n\n\t\t\t\t\t{/* Settings. Adding is the sidebar's Create button, so this is the\n only icon that earns a place next to the view menu. */}\n\t\t\t\t\t{resolvedShowSettings && (\n\t\t\t\t\t\t<Popover>\n\t\t\t\t\t\t\t<PopoverTrigger\n\t\t\t\t\t\t\t\taria-label={mergedLabels.settings ?? 'Settings'}\n\t\t\t\t\t\t\t\tclassName={CONTROL_ICON}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Gear className=\"size-5\" />\n\t\t\t\t\t\t\t</PopoverTrigger>\n\t\t\t\t\t\t\t<PopoverContent align=\"end\" className=\"w-80 p-4\">\n\t\t\t\t\t\t\t\t{settingsContent ?? <CalendarSettings />}\n\t\t\t\t\t\t\t</PopoverContent>\n\t\t\t\t\t\t</Popover>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Filter row */}\n\t\t\t{resolvedShowFilters && filterContent && (\n\t\t\t\t<div className=\"flex items-center gap-2 pb-1 -mb-1 scrollbar-none\">{filterContent}</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nexport default CalendarHeader;\n","/**\n * Badge Component\n *\n * Displays a small badge with optional variants.\n */\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type * as React from 'react';\nimport { cn } from '../../lib/utils';\n\n// ============================================================================\n// VARIANTS\n// ============================================================================\n\nconst badgeVariants = cva(\n\t'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',\n\t\t\t\tsecondary:\n\t\t\t\t\t'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',\n\t\t\t\tdestructive:\n\t\t\t\t\t'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',\n\t\t\t\toutline: 'text-foreground',\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: { variant: 'default' },\n\t}\n);\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface BadgeProps\n\textends React.HTMLAttributes<HTMLDivElement>,\n\t\tVariantProps<typeof badgeVariants> {}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n\treturn <div className={cn(badgeVariants({ variant }), className)} {...props} />;\n}\n\nexport { Badge, badgeVariants };\n","/**\n * DateNavigator - Navigation Controls with Date Range\n *\n * Shows month/year title, event count badge, and prev/next navigation.\n * Matches the production agenda-v2 implementation.\n */\n\nimport type { CalendarEvent, TCalendarView } from '../../../core/types';\nimport { getEventsCountInView, getRangeText } from '../../../core/utils/grid-utils';\nimport { cn } from '../../../lib/utils';\nimport { Badge } from '../../ui/badge';\nimport { Button } from '../../ui/button';\n\n// ============================================================================\n// ICONS (Inline SVGs for zero dependencies)\n// ============================================================================\n\nfunction ChevronLeft({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<path d=\"m15 18-6-6 6-6\" />\n\t\t</svg>\n\t);\n}\n\nfunction ChevronRight({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"24\"\n\t\t\theight=\"24\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t>\n\t\t\t<path d=\"m9 18 6-6-6-6\" />\n\t\t</svg>\n\t);\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst MONTH_NAMES = [\n\t'January',\n\t'February',\n\t'March',\n\t'April',\n\t'May',\n\t'June',\n\t'July',\n\t'August',\n\t'September',\n\t'October',\n\t'November',\n\t'December',\n];\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface DateNavigatorProps<TData = Record<string, unknown>> {\n\t/** Current date */\n\tdate: Date;\n\t/** Current view */\n\tview: TCalendarView;\n\t/** Events to count */\n\tevents?: CalendarEvent<TData>[];\n\t/** Navigate to previous period */\n\tonNavigatePrev?: () => void;\n\t/** Navigate to next period */\n\tonNavigateNext?: () => void;\n\t/** Week starts on (0 = Sunday, 1 = Monday) */\n\tweekStartsOn?: 0 | 1;\n\t/** Show event count badge */\n\tshowEventCount?: boolean;\n\t/** Additional CSS classes */\n\tclassName?: string;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function DateNavigator<TData = Record<string, unknown>>({\n\tdate,\n\tview,\n\tevents = [],\n\tonNavigatePrev,\n\tonNavigateNext,\n\tweekStartsOn = 1,\n\tshowEventCount = true,\n\tclassName,\n}: DateNavigatorProps<TData>) {\n\tconst month = MONTH_NAMES[date.getMonth()];\n\tconst year = date.getFullYear();\n\tconst eventCount = showEventCount ? getEventsCountInView(events, date, view, weekStartsOn) : 0;\n\tconst rangeText = getRangeText(date, view);\n\n\treturn (\n\t\t<div className={cn('min-w-0 flex-1', className)}>\n\t\t\t{/* Title row with month/year and event count */}\n\t\t\t<div className=\"flex items-center gap-1.5 sm:gap-2 flex-wrap\">\n\t\t\t\t<span className=\"text-base sm:text-lg font-semibold truncate\">\n\t\t\t\t\t{month} {year}\n\t\t\t\t</span>\n\t\t\t\t{showEventCount && (\n\t\t\t\t\t<Badge variant=\"outline\" className=\"px-1 sm:px-1.5 text-[10px] sm:text-xs shrink-0\">\n\t\t\t\t\t\t{eventCount}\n\t\t\t\t\t</Badge>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Navigation row */}\n\t\t\t<div className=\"flex items-center gap-1.5 sm:gap-2\">\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\tclassName=\"size-5 sm:size-6 [&_svg]:size-3 sm:[&_svg]:size-4\"\n\t\t\t\t\tonClick={onNavigatePrev}\n\t\t\t\t>\n\t\t\t\t\t<ChevronLeft />\n\t\t\t\t</Button>\n\n\t\t\t\t<p className=\"text-xs sm:text-sm text-muted-foreground truncate\">{rangeText}</p>\n\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\tclassName=\"size-5 sm:size-6 [&_svg]:size-3 sm:[&_svg]:size-4\"\n\t\t\t\t\tonClick={onNavigateNext}\n\t\t\t\t>\n\t\t\t\t\t<ChevronRight />\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default DateNavigator;\n","/**\n * TodayButton - Styled Calendar Icon Button\n *\n * A visual button showing today's date that navigates to today.\n * Matches the production agenda-v2 implementation.\n */\n\nimport { cn } from '../../../lib/utils';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst MONTH_NAMES = [\n\t'JAN',\n\t'FEB',\n\t'MAR',\n\t'APR',\n\t'MAY',\n\t'JUN',\n\t'JUL',\n\t'AUG',\n\t'SEP',\n\t'OCT',\n\t'NOV',\n\t'DEC',\n];\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface TodayButtonProps {\n\t/** Click handler - should navigate to today */\n\tonClick?: () => void;\n\t/** Additional CSS classes */\n\tclassName?: string;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function TodayButton({ onClick, className }: TodayButtonProps) {\n\tconst today = new Date();\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName={cn(\n\t\t\t\t'flex size-11 sm:size-14 flex-col items-start overflow-hidden rounded-lg border shrink-0',\n\t\t\t\t'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',\n\t\t\t\t'hover:bg-accent/50 transition-colors',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tonClick={onClick}\n\t\t>\n\t\t\t<p className=\"flex h-4 sm:h-6 w-full items-center justify-center bg-primary text-center text-[10px] sm:text-xs font-semibold text-primary-foreground\">\n\t\t\t\t{MONTH_NAMES[today.getMonth()]}\n\t\t\t</p>\n\t\t\t<p className=\"flex w-full flex-1 items-center justify-center text-sm sm:text-lg font-bold\">\n\t\t\t\t{today.getDate()}\n\t\t\t</p>\n\t\t</button>\n\t);\n}\n\nexport default TodayButton;\n","/**\n * The event card — the surface Google opens when you drag a slot.\n *\n * A surface, and nothing else. It floats beside the slot it is for, follows a\n * drag of its handle, closes on Escape or a click outside, caps itself to the\n * room below wherever it landed, and becomes a sheet on a phone. What goes\n * inside is entirely the consumer's `eventForm` — the title, the fields, the\n * buttons.\n *\n * That line is deliberate. Everything the calendar owns here is about *where\n * the card is*, which the grid has to agree with; everything about *what an\n * event is* belongs to the app, which is the only place that knows.\n */\n\nimport { X } from 'lucide-react';\nimport {\n\ttype ReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { COMPACT_WIDTH, PORTALLED } from '../../core/constants';\nimport type { CalendarEvent, ISelectionResult } from '../../core/types';\nimport { IC_Z_CARD } from '../../core/z-layers';\nimport { cn } from '../../lib/utils';\n\nconst CARD_WIDTH = 380;\nconst WIDE_WIDTH = 520;\n/** Below this the card becomes a sheet: there is no room to float beside anything. */\nconst MARGIN = 12;\n/** Breathing room between the card and whatever it is sitting beside. */\nconst GAP = 8;\n\n/** What the card was opened for. */\nexport interface IEventFormArgs<TData = Record<string, unknown>> {\n\t/** The slot: where it starts, where it ends, and whose column it was in. */\n\tselection: ISelectionResult;\n\t/** The event being edited, when the card was opened on one. */\n\tevent?: CalendarEvent<TData> | undefined;\n}\n\n/** What the card gives back. */\nexport interface IEventFormActions {\n\t/** Dismiss the card — after a save, or from your own Cancel. */\n\tclose: () => void;\n\t/**\n\t * Ask for the wider card. \"More options\" is yours, so the width has to be\n\t * too: only your form knows whether it has more to show.\n\t */\n\texpand: (wide: boolean) => void;\n}\n\nexport type TEventFormRenderer<TData = Record<string, unknown>> = (\n\targs: IEventFormArgs<TData>,\n\tactions: IEventFormActions\n) => ReactNode;\n\nexport interface QuickCreateProps<TData = Record<string, unknown>> {\n\targs: IEventFormArgs<TData>;\n\t/**\n\t * Where to put the card. Omit it — opening from a link, say — and it places\n\t * itself near the top of the viewport instead.\n\t *\n\t * `align` says what `x` means: `center` for a drag, where the card wants to\n\t * sit under the pointer, and `end` for a landmark it should sit *beside*\n\t * rather than cover — the current-time line, a day cell. It still slides\n\t * back into view when the chosen side has no room.\n\t */\n\tanchor?:\n\t\t| { x: number; y: number; align?: 'center' | 'start' | 'end' }\n\t\t| undefined;\n\t/** Everything inside the card. */\n\trender: TEventFormRenderer<TData>;\n\t/** For the close button, which is the card's own. */\n\tcloseLabel?: string | undefined;\n\tonClose: () => void;\n}\n\nexport function QuickCreate<TData = Record<string, unknown>>({\n\targs,\n\tanchor,\n\trender,\n\tcloseLabel = 'Close',\n\tonClose,\n}: QuickCreateProps<TData>) {\n\tconst [wide, setWide] = useState(false);\n\tconst cardRef = useRef<HTMLDivElement>(null);\n\n\t/**\n\t * Never wider or taller than the screen. A fixed 520 is fine on a laptop and\n\t * half a phone off the edge — and the card positions itself, so nothing else\n\t * would pull it back.\n\t */\n\tconst [viewport, setViewport] = useState(() =>\n\t\ttypeof window === 'undefined'\n\t\t\t? { width: 1024, height: 768 }\n\t\t\t: { width: window.innerWidth, height: window.innerHeight }\n\t);\n\tuseEffect(() => {\n\t\tconst onResize = () =>\n\t\t\tsetViewport({ width: window.innerWidth, height: window.innerHeight });\n\t\twindow.addEventListener('resize', onResize);\n\t\treturn () => window.removeEventListener('resize', onResize);\n\t}, []);\n\n\t/**\n\t * On a phone the card stops floating and becomes a sheet across the bottom,\n\t * the way Google's does: at this width there is no \"beside\" left to anchor\n\t * to, and a 380px card centred on a 360px screen is worse than a full one.\n\t */\n\tconst compact = viewport.width < COMPACT_WIDTH;\n\n\tconst width = compact\n\t\t? viewport.width - MARGIN * 2\n\t\t: Math.min(wide ? WIDE_WIDTH : CARD_WIDTH, viewport.width - MARGIN * 2);\n\n\tconst [position, setPosition] = useState<{\n\t\tleft: number;\n\t\ttop: number;\n\t\tmaxHeight: number;\n\t}>({ left: anchor?.x ?? 0, top: anchor?.y ?? 0, maxHeight: 0 });\n\n\t/**\n\t * Place the card, and cap it to the room below wherever it lands.\n\t *\n\t * The height has to be measured, not assumed: guests get added, \"More\n\t * options\" doubles the card, a search opens a list. So this re-runs whenever\n\t * the card resizes — a capped height alone is not enough, because a card\n\t * anchored halfway down the screen may only have half that room beneath it.\n\t */\n\tuseLayoutEffect(() => {\n\t\tconst card = cardRef.current;\n\t\tif (!card || compact) return;\n\n\t\tconst place = () => {\n\t\t\tconst { innerHeight: vh, innerWidth: vw } = window;\n\t\t\tconst room = vh - MARGIN * 2;\n\t\t\t// `scrollHeight` is what it *wants* to be; `offsetHeight` is what a\n\t\t\t// previous cap already made it, which would ratchet it smaller.\n\t\t\tconst wanted = Math.min(card.scrollHeight, room);\n\n\t\t\tconst desiredTop = anchor ? anchor.y - 40 : 96;\n\t\t\tconst top = Math.min(\n\t\t\t\tMath.max(MARGIN, desiredTop),\n\t\t\t\tMath.max(MARGIN, vh - wanted - MARGIN)\n\t\t\t);\n\n\t\t\t// Beside, and on whichever side has room: pinned against the left edge\n\t\t\t// because today happens to be the first column is not \"beside\" anything.\n\t\t\tconst sides = !anchor\n\t\t\t\t? [(vw - width) / 2]\n\t\t\t\t: anchor.align === 'end'\n\t\t\t\t\t? [anchor.x - width - GAP, anchor.x + GAP]\n\t\t\t\t\t: anchor.align === 'start'\n\t\t\t\t\t\t? [anchor.x + GAP, anchor.x - width - GAP]\n\t\t\t\t\t\t: [anchor.x - width / 2];\n\t\t\tconst fits = (x: number) => x >= MARGIN && x + width <= vw - MARGIN;\n\t\t\tconst chosen = sides.find(fits) ?? sides[0] ?? MARGIN;\n\t\t\tconst left = Math.min(Math.max(MARGIN, chosen), vw - width - MARGIN);\n\n\t\t\tconst next = { left, top, maxHeight: vh - top - MARGIN };\n\t\t\tsetPosition((prev) =>\n\t\t\t\tprev.left === next.left &&\n\t\t\t\tprev.top === next.top &&\n\t\t\t\tprev.maxHeight === next.maxHeight\n\t\t\t\t\t? prev\n\t\t\t\t\t: next\n\t\t\t);\n\t\t};\n\n\t\tplace();\n\n\t\t// Absent in jsdom and in server rendering; the card is placed once\n\t\t// either way, it simply stops following content that grows later.\n\t\tif (typeof ResizeObserver === 'undefined') return;\n\n\t\t// Setting a cap changes the height, which would fire this again — the\n\t\t// equality guard above is what stops that becoming a loop.\n\t\tconst observer = new ResizeObserver(place);\n\t\tobserver.observe(card);\n\t\treturn () => observer.disconnect();\n\t}, [anchor, width, compact, viewport.height]);\n\n\t// Escape closes; so does a click outside. Both match Google and every other\n\t// transient surface in the calendar.\n\tuseEffect(() => {\n\t\tconst onKey = (e: KeyboardEvent) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\te.stopPropagation();\n\t\t\t\tonClose();\n\t\t\t}\n\t\t};\n\t\tconst onPointerDown = (e: PointerEvent) => {\n\t\t\tconst target = e.target as HTMLElement | null;\n\n\t\t\t// A menu that is already open disables pointer events on the body\n\t\t\t// while it dismisses itself, so the click that closes it hit-tests to\n\t\t\t// the document rather than to the trigger underneath. That is not a\n\t\t\t// click outside the card — and treating it as one closed the whole\n\t\t\t// form on the second click of a select.\n\t\t\tif (\n\t\t\t\t!target ||\n\t\t\t\ttarget === document.body ||\n\t\t\t\ttarget === document.documentElement\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (cardRef.current?.contains(target as Node)) return;\n\t\t\t// Without this, picking a date or a select option closes the whole\n\t\t\t// card. See `PORTALLED`.\n\t\t\tif (target?.closest?.(PORTALLED)) return;\n\t\t\tonClose();\n\t\t};\n\t\tdocument.addEventListener('keydown', onKey, true);\n\t\t// Deferred: the pointerup that ended the drag would otherwise close it.\n\t\tconst id = window.setTimeout(\n\t\t\t() => document.addEventListener('pointerdown', onPointerDown),\n\t\t\t0\n\t\t);\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('keydown', onKey, true);\n\t\t\tdocument.removeEventListener('pointerdown', onPointerDown);\n\t\t\twindow.clearTimeout(id);\n\t\t};\n\t}, [onClose]);\n\n\t// The handle drags the card, as it does in Google.\n\tconst onHandleDown = useCallback((e: React.PointerEvent) => {\n\t\tconst startX = e.clientX;\n\t\tconst startY = e.clientY;\n\t\tlet origin = { left: 0, top: 0, maxHeight: 0 };\n\t\tsetPosition((p) => {\n\t\t\torigin = p;\n\t\t\treturn p;\n\t\t});\n\n\t\tconst move = (ev: PointerEvent) => {\n\t\t\tconst top = origin.top + (ev.clientY - startY);\n\t\t\tsetPosition({\n\t\t\t\tleft: origin.left + (ev.clientX - startX),\n\t\t\t\ttop,\n\t\t\t\t// Dragged down, it has less room beneath it.\n\t\t\t\tmaxHeight: window.innerHeight - top - MARGIN,\n\t\t\t});\n\t\t};\n\t\tconst up = () => {\n\t\t\tdocument.removeEventListener('pointermove', move);\n\t\t\tdocument.removeEventListener('pointerup', up);\n\t\t};\n\t\tdocument.addEventListener('pointermove', move);\n\t\tdocument.addEventListener('pointerup', up);\n\t}, []);\n\n\tif (typeof document === 'undefined') return null;\n\n\tconst card = (\n\t\t<div\n\t\t\tref={cardRef}\n\t\t\trole=\"dialog\"\n\t\t\tclassName={cn(\n\t\t\t\t'ic-quick-create fixed flex flex-col overflow-hidden rounded-2xl',\n\t\t\t\t'bg-popover text-popover-foreground shadow-2xl ring-1 ring-border'\n\t\t\t)}\n\t\t\tstyle={\n\t\t\t\tcompact\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tleft: MARGIN,\n\t\t\t\t\t\t\tright: MARGIN,\n\t\t\t\t\t\t\tbottom: MARGIN,\n\t\t\t\t\t\t\tzIndex: IC_Z_CARD,\n\t\t\t\t\t\t\tmaxHeight: `calc(100dvh - ${MARGIN * 2}px)`,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tleft: position.left,\n\t\t\t\t\t\t\ttop: position.top,\n\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\tzIndex: IC_Z_CARD,\n\t\t\t\t\t\t\t// The room below wherever it landed — not the whole\n\t\t\t\t\t\t\t// viewport, or a card anchored halfway down runs off it.\n\t\t\t\t\t\t\tmaxHeight: position.maxHeight || undefined,\n\t\t\t\t\t\t}\n\t\t\t}\n\t\t\tonPointerDown={(e) => e.stopPropagation()}\n\t\t>\n\t\t\t{/* Handle + close. The only chrome the card keeps: one moves it, the\n\t\t\t other dismisses it, and both are about the surface rather than\n\t\t\t about what is on it. */}\n\t\t\t<div className=\"flex shrink-0 items-center justify-between px-3 pt-2\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\taria-label=\"Move\"\n\t\t\t\t\tonPointerDown={onHandleDown}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'flex size-7 cursor-grab items-center justify-center rounded-full',\n\t\t\t\t\t\t'text-muted-foreground active:cursor-grabbing',\n\t\t\t\t\t\t'hover:bg-accent hover:text-accent-foreground'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"flex flex-col gap-[3px]\">\n\t\t\t\t\t\t<span className=\"block h-[1.5px] w-3.5 rounded bg-current\" />\n\t\t\t\t\t\t<span className=\"block h-[1.5px] w-3.5 rounded bg-current\" />\n\t\t\t\t\t</span>\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\taria-label={closeLabel}\n\t\t\t\t\tonClick={onClose}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'flex size-7 items-center justify-center rounded-full',\n\t\t\t\t\t\t'text-muted-foreground hover:bg-accent hover:text-accent-foreground'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<X className=\"size-4\" />\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div className=\"flex min-h-0 flex-1 flex-col\">\n\t\t\t\t{render(args, { close: onClose, expand: setWide })}\n\t\t\t</div>\n\t\t</div>\n\t);\n\n\treturn createPortal(card, document.body);\n}\n","/**\n * Scroll Navigator — D-pad style floating controller for calendar scrolling.\n *\n * A game-controller-inspired navigation widget that provides directional\n * scrolling (up/down/left/right) plus an analog joystick center for\n * free-form drag-to-scroll. Each arrow button only enables when scroll\n * is possible in that direction.\n *\n * The center joystick works like a real analog stick: press and drag in any\n * direction — the further from center, the faster it scrolls. The inner dot\n * visually tracks your drag direction so you always know which way you're\n * scrolling.\n *\n * Arrow keys on the keyboard also scroll the calendar when the container\n * or the D-pad is focused.\n *\n * @example\n * ```tsx\n * <ScrollNavigator containerRef={scrollContainerRef} />\n * ```\n *\n * @module\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface ScrollNavigatorProps {\n /** Ref to the scrollable container element */\n containerRef: React.RefObject<HTMLDivElement | null>;\n /** Current date displayed above the D-pad for orientation */\n currentDate?: Date;\n /** Additional CSS class on the root wrapper */\n className?: string;\n}\n\ninterface ScrollState {\n canUp: boolean;\n canDown: boolean;\n canLeft: boolean;\n canRight: boolean;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\n/** Pixels per button-click scroll */\nconst SCROLL_STEP = 200;\n/** ms between continuous scroll ticks when holding a button */\nconst HOLD_INTERVAL = 60;\n/** ms before continuous scrolling kicks in after mousedown */\nconst HOLD_DELAY = 300;\n/** Max visual displacement of the joystick dot (px) */\nconst JOYSTICK_DOT_MAX = 7;\n/** Pixels of pointer displacement that maps to max scroll speed */\nconst JOYSTICK_DEAD_ZONE = 2;\nconst JOYSTICK_MAX_DISPLACEMENT = 40;\n/** Max scroll pixels per animation frame at full tilt */\nconst JOYSTICK_MAX_SPEED = 18;\n\n// ============================================================================\n// CHEVRON SVG PATHS (compact 12×12)\n// ============================================================================\n\nfunction ChevronUp() {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m18 15-6-6-6 6\" />\n </svg>\n );\n}\n\nfunction ChevronDown() {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n );\n}\n\nfunction ChevronLeft() {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n );\n}\n\nfunction ChevronRight() {\n return (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n );\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function ScrollNavigator({\n containerRef,\n currentDate,\n className,\n}: ScrollNavigatorProps) {\n const [scrollState, setScrollState] = useState<ScrollState>({\n canUp: false,\n canDown: false,\n canLeft: false,\n canRight: false,\n });\n\n // Joystick inner-dot visual offset (px from center)\n const [dotOffset, setDotOffset] = useState({ x: 0, y: 0 });\n const [isDragging, setIsDragging] = useState(false);\n\n // Track if any scroll is possible (controls visibility)\n const hasAnyScroll =\n scrollState.canUp ||\n scrollState.canDown ||\n scrollState.canLeft ||\n scrollState.canRight;\n\n // Refs for hold-to-scroll\n const holdTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const holdIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n // Joystick drag state\n const joystickRef = useRef<HTMLButtonElement>(null);\n const isDraggingRef = useRef(false);\n const dragOriginRef = useRef({ x: 0, y: 0 });\n const displacementRef = useRef({ x: 0, y: 0 });\n const animFrameRef = useRef<number>(0);\n\n // Viewport-tracking: keeps navigator visible when page scrolls\n const navRef = useRef<HTMLDivElement>(null);\n\n // ---- Scroll state detection ------------------------------------------\n\n const checkScrollState = useCallback(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const threshold = 4;\n setScrollState({\n canUp: el.scrollTop > threshold,\n canDown: el.scrollTop + el.clientHeight < el.scrollHeight - threshold,\n canLeft: el.scrollLeft > threshold,\n canRight: el.scrollLeft + el.clientWidth < el.scrollWidth - threshold,\n });\n }, [containerRef]);\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n checkScrollState();\n\n el.addEventListener(\"scroll\", checkScrollState, { passive: true });\n\n const ro = new ResizeObserver(checkScrollState);\n ro.observe(el);\n\n const mo = new MutationObserver(checkScrollState);\n mo.observe(el, { childList: true, subtree: true });\n\n return () => {\n el.removeEventListener(\"scroll\", checkScrollState);\n ro.disconnect();\n mo.disconnect();\n };\n }, [containerRef, checkScrollState]);\n\n // ---- Directional scroll actions ---------------------------------------\n\n const scrollBy = useCallback(\n (dx: number, dy: number) => {\n containerRef.current?.scrollBy({ left: dx, top: dy, behavior: \"smooth\" });\n },\n [containerRef],\n );\n\n const scrollUp = useCallback(() => scrollBy(0, -SCROLL_STEP), [scrollBy]);\n const scrollDown = useCallback(() => scrollBy(0, SCROLL_STEP), [scrollBy]);\n const scrollLeft = useCallback(() => scrollBy(-SCROLL_STEP, 0), [scrollBy]);\n const scrollRight = useCallback(() => scrollBy(SCROLL_STEP, 0), [scrollBy]);\n\n // ---- Hold-to-scroll (press and hold a direction) ---------------------\n\n const clearHold = useCallback(() => {\n if (holdTimerRef.current) {\n clearTimeout(holdTimerRef.current);\n holdTimerRef.current = null;\n }\n if (holdIntervalRef.current) {\n clearInterval(holdIntervalRef.current);\n holdIntervalRef.current = null;\n }\n }, []);\n\n const startHold = useCallback((action: () => void) => {\n action();\n holdTimerRef.current = setTimeout(() => {\n holdIntervalRef.current = setInterval(action, HOLD_INTERVAL);\n }, HOLD_DELAY);\n }, []);\n\n useEffect(() => clearHold, [clearHold]);\n\n // ---- Keyboard: arrow keys on the container ---------------------------\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n // Only intercept bare arrow keys (no modifiers) to avoid breaking text inputs\n if (e.ctrlKey || e.metaKey || e.altKey) return;\n // Skip if the focus is inside an input/textarea/contenteditable\n const tag = (e.target as HTMLElement).tagName;\n if (\n tag === \"INPUT\" ||\n tag === \"TEXTAREA\" ||\n (e.target as HTMLElement).isContentEditable\n )\n return;\n\n switch (e.key) {\n case \"ArrowUp\":\n e.preventDefault();\n scrollUp();\n break;\n case \"ArrowDown\":\n e.preventDefault();\n scrollDown();\n break;\n case \"ArrowLeft\":\n e.preventDefault();\n scrollLeft();\n break;\n case \"ArrowRight\":\n e.preventDefault();\n scrollRight();\n break;\n }\n };\n\n el.addEventListener(\"keydown\", handleKeyDown);\n return () => el.removeEventListener(\"keydown\", handleKeyDown);\n }, [containerRef, scrollUp, scrollDown, scrollLeft, scrollRight]);\n\n // ---- Viewport tracking: follow visible area when page scrolls -------\n\n useEffect(() => {\n if (!hasAnyScroll) return;\n const nav = navRef.current;\n if (!nav) return;\n\n let rafId = 0;\n\n const updatePosition = () => {\n const offsetParent = nav.offsetParent as HTMLElement | null;\n if (!offsetParent) return;\n\n const parentRect = offsetParent.getBoundingClientRect();\n const viewportH = window.innerHeight;\n\n // When the calendar fits inside the viewport, default CSS bottom works fine\n if (parentRect.height <= viewportH) {\n nav.style.removeProperty(\"top\");\n nav.style.removeProperty(\"bottom\");\n return;\n }\n\n // The visible bottom edge of the calendar within the viewport\n const visibleBottom = Math.min(parentRect.bottom, viewportH);\n const localY = visibleBottom - parentRect.top;\n const navH = nav.offsetHeight;\n const desiredTop = localY - navH - 12;\n\n // Clamp so the navigator stays within the calendar bounds\n const minTop = 12;\n const maxTop = offsetParent.clientHeight - navH - 12;\n const clamped = Math.max(minTop, Math.min(desiredTop, maxTop));\n\n nav.style.top = `${clamped}px`;\n nav.style.bottom = \"auto\";\n };\n\n const onScroll = () => {\n cancelAnimationFrame(rafId);\n rafId = requestAnimationFrame(updatePosition);\n };\n\n // Listen to all scrollable ancestors + window\n const scrollTargets: (HTMLElement | Window)[] = [window];\n let parent = nav.parentElement;\n while (parent) {\n const style = getComputedStyle(parent);\n if (/(auto|scroll)/.test(style.overflow + style.overflowY)) {\n scrollTargets.push(parent);\n }\n parent = parent.parentElement;\n }\n\n for (const target of scrollTargets) {\n target.addEventListener(\"scroll\", onScroll, { passive: true });\n }\n window.addEventListener(\"resize\", onScroll, { passive: true });\n\n // Set initial position\n updatePosition();\n\n return () => {\n cancelAnimationFrame(rafId);\n for (const target of scrollTargets) {\n target.removeEventListener(\"scroll\", onScroll);\n }\n window.removeEventListener(\"resize\", onScroll);\n };\n }, [hasAnyScroll]);\n\n // ---- Joystick: analog stick with visual dot tracking -----------------\n\n const stopJoystick = useCallback(() => {\n isDraggingRef.current = false;\n setIsDragging(false);\n setDotOffset({ x: 0, y: 0 });\n displacementRef.current = { x: 0, y: 0 };\n if (animFrameRef.current) cancelAnimationFrame(animFrameRef.current);\n }, []);\n\n const handleJoystickDown = useCallback(\n (e: React.PointerEvent) => {\n e.preventDefault();\n isDraggingRef.current = true;\n setIsDragging(true);\n dragOriginRef.current = { x: e.clientX, y: e.clientY };\n displacementRef.current = { x: 0, y: 0 };\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n\n // Continuous scroll loop — speed proportional to displacement\n const tick = () => {\n if (!isDraggingRef.current) return;\n const el = containerRef.current;\n if (el) {\n const { x, y } = displacementRef.current;\n const dist = Math.sqrt(x * x + y * y);\n if (dist > JOYSTICK_DEAD_ZONE) {\n const factor = Math.min(dist / JOYSTICK_MAX_DISPLACEMENT, 1);\n const speed = factor * JOYSTICK_MAX_SPEED;\n // Normalize direction\n el.scrollLeft += (x / dist) * speed;\n el.scrollTop += (y / dist) * speed;\n }\n }\n animFrameRef.current = requestAnimationFrame(tick);\n };\n animFrameRef.current = requestAnimationFrame(tick);\n },\n [containerRef],\n );\n\n const handleJoystickMove = useCallback((e: React.PointerEvent) => {\n if (!isDraggingRef.current) return;\n\n // Raw displacement from press origin\n const rawX = e.clientX - dragOriginRef.current.x;\n const rawY = e.clientY - dragOriginRef.current.y;\n displacementRef.current = { x: rawX, y: rawY };\n\n // Clamp visual dot offset to max radius\n const dist = Math.sqrt(rawX * rawX + rawY * rawY);\n if (dist < JOYSTICK_DEAD_ZONE) {\n setDotOffset({ x: 0, y: 0 });\n } else {\n const clampedDist = Math.min(dist, JOYSTICK_MAX_DISPLACEMENT);\n const scale =\n (clampedDist / JOYSTICK_MAX_DISPLACEMENT) * JOYSTICK_DOT_MAX;\n setDotOffset({\n x: (rawX / dist) * scale,\n y: (rawY / dist) * scale,\n });\n }\n }, []);\n\n // ---- D-pad keyboard when focused -------------------------------------\n\n const handleDpadKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n switch (e.key) {\n case \"ArrowUp\":\n e.preventDefault();\n scrollUp();\n break;\n case \"ArrowDown\":\n e.preventDefault();\n scrollDown();\n break;\n case \"ArrowLeft\":\n e.preventDefault();\n scrollLeft();\n break;\n case \"ArrowRight\":\n e.preventDefault();\n scrollRight();\n break;\n }\n },\n [scrollUp, scrollDown, scrollLeft, scrollRight],\n );\n\n // Don't render when there's nothing to scroll\n if (!hasAnyScroll) return null;\n\n // Format current date for display\n const dateLabel = currentDate\n ? currentDate.toLocaleDateString(undefined, {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n })\n : null;\n\n return (\n <div\n ref={navRef}\n className={`inno-scroll-nav-wrapper ${className ?? \"\"}`}\n role=\"toolbar\"\n aria-label=\"Scroll navigation\"\n onKeyDown={handleDpadKeyDown}\n >\n {/* Floating date indicator */}\n {dateLabel && (\n <div className=\"inno-scroll-nav-date\" aria-live=\"polite\">\n {dateLabel}\n </div>\n )}\n\n <div className=\"inno-scroll-nav\">\n {/* Up */}\n <button\n type=\"button\"\n className={`inno-scroll-nav-btn inno-scroll-nav-up ${!scrollState.canUp ? \"inno-scroll-nav-btn-disabled\" : \"\"}`}\n aria-label=\"Scroll up\"\n disabled={!scrollState.canUp}\n onPointerDown={() => startHold(scrollUp)}\n onPointerUp={clearHold}\n onPointerLeave={clearHold}\n tabIndex={scrollState.canUp ? 0 : -1}\n >\n <ChevronUp />\n </button>\n\n {/* Left */}\n <button\n type=\"button\"\n className={`inno-scroll-nav-btn inno-scroll-nav-left ${!scrollState.canLeft ? \"inno-scroll-nav-btn-disabled\" : \"\"}`}\n aria-label=\"Scroll left\"\n disabled={!scrollState.canLeft}\n onPointerDown={() => startHold(scrollLeft)}\n onPointerUp={clearHold}\n onPointerLeave={clearHold}\n tabIndex={scrollState.canLeft ? 0 : -1}\n >\n <ChevronLeft />\n </button>\n\n {/* Center joystick */}\n <button\n ref={joystickRef}\n type=\"button\"\n className={`inno-scroll-nav-joystick ${isDragging ? \"inno-scroll-nav-joystick-active\" : \"\"}`}\n aria-label=\"Drag to scroll freely\"\n onPointerDown={handleJoystickDown}\n onPointerMove={handleJoystickMove}\n onPointerUp={stopJoystick}\n onPointerCancel={stopJoystick}\n tabIndex={0}\n >\n <span\n className=\"inno-scroll-nav-joystick-dot\"\n style={{\n transform: `translate(${dotOffset.x}px, ${dotOffset.y}px)`,\n }}\n />\n </button>\n\n {/* Right */}\n <button\n type=\"button\"\n className={`inno-scroll-nav-btn inno-scroll-nav-right ${!scrollState.canRight ? \"inno-scroll-nav-btn-disabled\" : \"\"}`}\n aria-label=\"Scroll right\"\n disabled={!scrollState.canRight}\n onPointerDown={() => startHold(scrollRight)}\n onPointerUp={clearHold}\n onPointerLeave={clearHold}\n tabIndex={scrollState.canRight ? 0 : -1}\n >\n <ChevronRight />\n </button>\n\n {/* Down */}\n <button\n type=\"button\"\n className={`inno-scroll-nav-btn inno-scroll-nav-down ${!scrollState.canDown ? \"inno-scroll-nav-btn-disabled\" : \"\"}`}\n aria-label=\"Scroll down\"\n disabled={!scrollState.canDown}\n onPointerDown={() => startHold(scrollDown)}\n onPointerUp={clearHold}\n onPointerLeave={clearHold}\n tabIndex={scrollState.canDown ? 0 : -1}\n >\n <ChevronDown />\n </button>\n </div>\n </div>\n );\n}\n\nexport default ScrollNavigator;\n","/**\n * The mini month navigator that sits at the top of Google's sidebar.\n *\n * Its job is jumping — a month at a glance, one click to any day — so it is\n * deliberately dense and unlabelled beyond single-letter weekdays.\n */\n\nimport { useMemo, useState } from 'react';\nimport {\n\taddMonths,\n\tisSameDay,\n\tisSameMonth,\n\tisToday,\n\tstartOfMonth,\n\tstartOfWeek,\n} from '../../core/utils/date-utils';\nimport { cn } from '../../lib/utils';\n\nexport interface MiniMonthProps {\n\t/** The date the grid is currently showing. */\n\tselected: Date;\n\tonSelect: (date: Date) => void;\n\tlocale?: string | undefined;\n\tweekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined;\n\tclassName?: string | undefined;\n}\n\nfunction Chevron({ dir }: { dir: 'prev' | 'next' }) {\n\treturn (\n\t\t<svg viewBox=\"0 0 24 24\" className=\"size-4\" fill=\"none\" aria-hidden=\"true\">\n\t\t\t<path\n\t\t\t\td={dir === 'prev' ? 'M15 18L9 12l6-6' : 'M9 18l6-6-6-6'}\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n\nexport function MiniMonth({\n\tselected,\n\tonSelect,\n\tlocale,\n\tweekStartsOn = 1,\n\tclassName,\n}: MiniMonthProps) {\n\t// The mini calendar browses independently of the grid — you can look at\n\t// next month without navigating there until you click a day.\n\tconst [cursor, setCursor] = useState(() => startOfMonth(selected));\n\n\tconst weeks = useMemo(() => {\n\t\tconst gridStart = startOfWeek(startOfMonth(cursor), weekStartsOn);\n\t\treturn Array.from({ length: 6 }, (_, week) =>\n\t\t\tArray.from({ length: 7 }, (_, day) => {\n\t\t\t\tconst date = new Date(gridStart);\n\t\t\t\tdate.setDate(gridStart.getDate() + week * 7 + day);\n\t\t\t\treturn date;\n\t\t\t})\n\t\t);\n\t}, [cursor, weekStartsOn]);\n\n\tconst weekdayLetters = useMemo(() => {\n\t\tconst base = startOfWeek(new Date(), weekStartsOn);\n\t\tconst fmt = new Intl.DateTimeFormat(locale, { weekday: 'narrow' });\n\t\treturn Array.from({ length: 7 }, (_, i) => {\n\t\t\tconst d = new Date(base);\n\t\t\td.setDate(base.getDate() + i);\n\t\t\treturn fmt.format(d);\n\t\t});\n\t}, [locale, weekStartsOn]);\n\n\tconst monthLabel = new Intl.DateTimeFormat(locale, {\n\t\tmonth: 'long',\n\t\tyear: 'numeric',\n\t}).format(cursor);\n\n\treturn (\n\t\t<div className={cn('select-none', className)}>\n\t\t\t<div className=\"mb-1 flex items-center justify-between pl-2\">\n\t\t\t\t<span className=\"text-sm font-medium\">{monthLabel}</span>\n\t\t\t\t<div className=\"flex items-center\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\taria-label=\"Previous month\"\n\t\t\t\t\t\tonClick={() => setCursor((c) => addMonths(c, -1))}\n\t\t\t\t\t\tclassName=\"flex size-7 items-center justify-center rounded-full text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Chevron dir=\"prev\" />\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\taria-label=\"Next month\"\n\t\t\t\t\t\tonClick={() => setCursor((c) => addMonths(c, 1))}\n\t\t\t\t\t\tclassName=\"flex size-7 items-center justify-center rounded-full text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Chevron dir=\"next\" />\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"grid grid-cols-7\">\n\t\t\t\t{weekdayLetters.map((letter, i) => (\n\t\t\t\t\t<span\n\t\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: fixed 7-day row\n\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\tclassName=\"flex h-7 items-center justify-center text-[10px] text-muted-foreground\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{letter}\n\t\t\t\t\t</span>\n\t\t\t\t))}\n\n\t\t\t\t{weeks.flat().map((date) => {\n\t\t\t\t\tconst outside = !isSameMonth(date, cursor);\n\t\t\t\t\tconst today = isToday(date);\n\t\t\t\t\tconst active = isSameDay(date, selected);\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={date.toISOString()}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => onSelect(date)}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'flex h-7 items-center justify-center rounded-full text-xs',\n\t\t\t\t\t\t\t\t'hover:bg-accent hover:text-accent-foreground',\n\t\t\t\t\t\t\t\toutside && 'text-muted-foreground/60',\n\t\t\t\t\t\t\t\tactive && !today && 'bg-accent font-medium text-accent-foreground',\n\t\t\t\t\t\t\t\ttoday && 'bg-primary font-medium text-primary-foreground hover:bg-primary'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{date.getDate()}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","/**\n * The left rail, as Google lays it out: a raised Create button, the mini month\n * navigator, then whatever the consumer wants below — which in an ERP is the\n * filters that used to sit in a row above the grid.\n *\n * Hidden below `lg`; on smaller screens the grid takes the full width and the\n * filters live behind the header's filter toggle as before.\n */\n\nimport type { ReactNode } from 'react';\nimport { SlidersHorizontal } from 'lucide-react';\nimport { CONTROL, CONTROL_ICON } from '../../core/constants';\nimport { cn } from '../../lib/utils';\nimport {\n\tSheet,\n\tSheetContent,\n\tSheetTitle,\n\tSheetTrigger,\n} from '../ui/sheet';\nimport { MiniMonth } from './mini-month';\n\nexport interface CalendarSidebarProps {\n\tselected: Date;\n\tonSelect: (date: Date) => void;\n\tlocale?: string | undefined;\n\tweekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined;\n\t/** Renders the Create button when provided. */\n\tonCreate?: (() => void) | undefined;\n\tcreateLabel?: string | undefined;\n\t/** Filters, calendar toggles — anything the app wants under the mini month. */\n\tchildren?: ReactNode;\n\tclassName?: string | undefined;\n}\n\nfunction Plus() {\n\treturn (\n\t\t<svg viewBox=\"0 0 24 24\" className=\"size-4\" fill=\"none\" aria-hidden=\"true\">\n\t\t\t<path\n\t\t\t\td=\"M12 5v14M5 12h14\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n\nexport function CalendarSidebar({\n\tselected,\n\tonSelect,\n\tlocale,\n\tweekStartsOn,\n\tonCreate,\n\tcreateLabel = 'Create',\n\tchildren,\n\tclassName,\n}: CalendarSidebarProps) {\n\treturn (\n\t\t<aside\n\t\t\tclassName={cn(\n\t\t\t\t'ic-sidebar hidden w-64 shrink-0 flex-col gap-5 overflow-y-auto',\n\t\t\t\t'py-2 pr-3 lg:flex',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t>\n\t\t\t<SidebarContents\n\t\t\t\tselected={selected}\n\t\t\t\tonSelect={onSelect}\n\t\t\t\t{...(locale && { locale })}\n\t\t\t\t{...(weekStartsOn !== undefined && { weekStartsOn })}\n\t\t\t\t{...(onCreate && { onCreate })}\n\t\t\t\t{...(createLabel && { createLabel })}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</SidebarContents>\n\t\t</aside>\n\t);\n}\n\n/**\n * What the rail holds. Shared with the sheet below `lg`, where the rail is\n * hidden — without it the filters simply do not exist on a phone.\n */\nfunction SidebarContents({\n\tselected,\n\tonSelect,\n\tonCreate,\n\tcreateLabel = 'Create',\n\tlocale,\n\tweekStartsOn,\n\tchildren,\n}: CalendarSidebarProps) {\n\treturn (\n\t\t<>\n\t\t\t{onCreate && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={onCreate}\n\t\t\t\t\tclassName={cn(CONTROL, 'w-fit gap-2 bg-popover shadow-sm')}\n\t\t\t\t>\n\t\t\t\t\t<Plus />\n\t\t\t\t\t<span>{createLabel}</span>\n\t\t\t\t</button>\n\t\t\t)}\n\n\t\t\t<MiniMonth\n\t\t\t\tselected={selected}\n\t\t\t\tonSelect={onSelect}\n\t\t\t\t{...(locale && { locale })}\n\t\t\t\t{...(weekStartsOn !== undefined && { weekStartsOn })}\n\t\t\t/>\n\n\t\t\t{/* A container query root: filter blocks written with `@`-variants adapt\n\t\t\t to this 256px rail instead of the viewport, which is what makes a\n\t\t\t four-column filter row collapse to one here. */}\n\t\t\t{children && <div className=\"@container min-w-0\">{children}</div>}\n\t\t</>\n\t);\n}\n\nexport interface SidebarSheetProps extends CalendarSidebarProps {\n\t/** Button text and the sheet's accessible name. */\n\tlabel?: string | undefined;\n}\n\n/**\n * The rail as a sheet, for the widths where it is hidden. Its trigger lives in\n * the header, so the filters are one tap away rather than unreachable.\n */\nexport function SidebarSheet({\n\tlabel = 'Filters',\n\topen,\n\tonOpenChange,\n\t...rest\n}: SidebarSheetProps & {\n\topen?: boolean | undefined;\n\tonOpenChange?: ((open: boolean) => void) | undefined;\n}) {\n\treturn (\n\t\t<Sheet {...(open !== undefined && { open })} {...(onOpenChange && { onOpenChange })}>\n\t\t\t<SheetTrigger asChild>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\taria-label={label}\n\t\t\t\t\tclassName={cn(CONTROL_ICON, 'lg:hidden')}\n\t\t\t\t>\n\t\t\t\t\t<SlidersHorizontal className=\"size-4\" />\n\t\t\t\t</button>\n\t\t\t</SheetTrigger>\n\t\t\t{/* The package's sheet slides from the right; the rail belongs on the\n\t\t\t left, so the side is flipped here rather than adding a prop only\n\t\t\t this one caller would use. */}\n\t\t\t<SheetContent\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'left-0 right-auto w-72 max-w-[85vw] overflow-y-auto border-l-0 border-r p-4',\n\t\t\t\t\t'data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left'\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<SheetTitle className=\"sr-only\">{label}</SheetTitle>\n\t\t\t\t<div className=\"@container flex flex-col gap-5\">\n\t\t\t\t\t<SidebarContents {...rest} />\n\t\t\t\t</div>\n\t\t\t</SheetContent>\n\t\t</Sheet>\n\t);\n}\n","/**\n * The filter panel — the rail's frame, and nothing inside it.\n *\n * The calendar owns where filters live: a column beside the grid on a wide\n * screen, a sheet you pull out below one. What a filter *is* — which options,\n * how they are searched, what they send to your API — is the app's, and the\n * app renders it here.\n */\n\nimport type { ReactNode } from 'react';\nimport { cn } from '../../lib/utils';\n\nexport interface FilterPanelProps {\n\t/** The app's filters. */\n\tchildren: ReactNode;\n\t/** Heading above them. */\n\ttitle?: string | undefined;\n\tclassName?: string | undefined;\n}\n\nexport function FilterPanel({ children, title, className }: FilterPanelProps) {\n\treturn (\n\t\t<div className={cn('flex flex-col gap-4', className)}>\n\t\t\t{title && (\n\t\t\t\t<div className=\"px-1 text-sm font-medium\">{title}</div>\n\t\t\t)}\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n","/**\n * Schedule — Google's list view.\n *\n * A day is a row: its number and weekday on the left, its events stacked on the\n * right as one compact line each. Days with nothing on them are skipped\n * entirely, which is the whole point of the view — it answers \"what is coming\n * up\" without the reader scanning empty grid.\n *\n * The dot is not decoration: filled means the invitation was accepted, hollow\n * means it has not been, so a column of hollow dots reads as \"nobody replied\".\n */\n\nimport { useMemo } from 'react';\nimport type { CalendarEvent, TOnEventClick } from '../../core/types';\nimport { isSameDay, isToday } from '../../core/utils/date-utils';\nimport { getViewDateRange } from '../../core/utils/grid-utils';\nimport { formatClock } from '../../core/utils/time-format';\nimport { cn } from '../../lib/utils';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\n\nexport interface IAgendaLabels {\n\tallDay: string;\n\tempty: string;\n}\n\nconst DEFAULT_LABELS: IAgendaLabels = {\n\tallDay: 'All day',\n\tempty: 'Nothing scheduled',\n};\n\nexport interface AgendaViewProps<TData = Record<string, unknown>> {\n\tevents: CalendarEvent<TData>[];\n\t/** The list runs from here; the range matches the view's own. */\n\tdate: Date;\n\t/** Overrides the view's range when a consumer wants a longer list. */\n\tdaysAhead?: number;\n\tlocale?: string | undefined;\n\t/** @default false — 24-hour */\n\thour12?: boolean | undefined;\n\tlabels?: Partial<IAgendaLabels> | undefined;\n\t/** Shown when nothing falls in the range. */\n\temptyState?: React.ReactNode;\n\tonEventClick?: TOnEventClick<TData>;\n\tclassName?: string;\n\trenderEvent?: (props: { event: CalendarEvent<TData>; variant: 'full' }) => React.ReactNode;\n\trenderPopover?: (props: { event: CalendarEvent<TData>; onClose: () => void }) => React.ReactNode;\n}\n\n// ---------------------------------------------------------------------------\n\nconst isAcceptedEvent = (event: CalendarEvent) =>\n\t(event.data as { isAccepted?: boolean } | undefined)?.isAccepted ?? event.isAccepted ?? true;\n\nfunction Dot({ event }: { event: CalendarEvent }) {\n\tconst color = event.hexColor ?? 'var(--primary)';\n\n\treturn (\n\t\t<span\n\t\t\taria-hidden=\"true\"\n\t\t\tclassName=\"size-2.5 shrink-0 rounded-full\"\n\t\t\tstyle={\n\t\t\t\tisAcceptedEvent(event)\n\t\t\t\t\t? { background: color }\n\t\t\t\t\t: { border: `2px solid ${color}`, background: 'transparent' }\n\t\t\t}\n\t\t/>\n\t);\n}\n\nfunction NowLine() {\n\treturn (\n\t\t<div className=\"relative my-0.5 h-0\" aria-hidden=\"true\">\n\t\t\t<div className=\"absolute inset-x-0 flex items-center\">\n\t\t\t\t<span className=\"size-2 shrink-0 rounded-full bg-red-500\" />\n\t\t\t\t<span className=\"h-px flex-1 bg-red-500\" />\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction Row<TData>({\n\tevent,\n\ttime,\n\towners,\n\tonEventClick,\n\trenderPopover,\n}: {\n\tevent: CalendarEvent<TData>;\n\ttime: string;\n\t/** Whose event it is — only shown when the list holds more than one agenda. */\n\towners?: string | undefined;\n\tonEventClick?: TOnEventClick<TData> | undefined;\n\trenderPopover?:\n\t\t| ((props: { event: CalendarEvent<TData>; onClose: () => void }) => React.ReactNode)\n\t\t| undefined;\n}) {\n\tconst line = (\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t'flex w-full items-center gap-3 rounded px-2 py-1.5 text-left',\n\t\t\t\t'hover:bg-accent hover:text-accent-foreground',\n\t\t\t\tevent.isCanceled && 'text-muted-foreground line-through'\n\t\t\t)}\n\t\t>\n\t\t\t<Dot event={event as CalendarEvent} />\n\t\t\t<span className=\"w-28 shrink-0 text-sm tabular-nums text-muted-foreground\">{time}</span>\n\t\t\t<span className=\"min-w-0 flex-1 truncate text-sm\">{event.title}</span>\n\t\t\t{owners && (\n\t\t\t\t<span className=\"max-w-[35%] shrink-0 truncate text-xs text-muted-foreground\">\n\t\t\t\t\t{owners}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</span>\n\t);\n\n\t// A consumer's own card wins; otherwise the row is just a click.\n\tif (renderPopover) {\n\t\treturn (\n\t\t\t<Popover>\n\t\t\t\t<PopoverTrigger asChild>\n\t\t\t\t\t<button type=\"button\" className=\"w-full\">\n\t\t\t\t\t\t{line}\n\t\t\t\t\t</button>\n\t\t\t\t</PopoverTrigger>\n\t\t\t\t<PopoverContent className=\"w-96 p-0\" align=\"start\">\n\t\t\t\t\t{renderPopover({\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\t// Radix owns the open state; Escape is the way back out of it.\n\t\t\t\t\t\tonClose: () =>\n\t\t\t\t\t\t\tdocument.dispatchEvent(\n\t\t\t\t\t\t\t\tnew KeyboardEvent('keydown', { key: 'Escape', bubbles: true })\n\t\t\t\t\t\t\t),\n\t\t\t\t\t})}\n\t\t\t\t</PopoverContent>\n\t\t\t</Popover>\n\t\t);\n\t}\n\n\treturn (\n\t\t<button type=\"button\" className=\"w-full\" onClick={(e) => onEventClick?.(event, e)}>\n\t\t\t{line}\n\t\t</button>\n\t);\n}\n\n// ---------------------------------------------------------------------------\n\nexport function AgendaView<TData = Record<string, unknown>>({\n\tevents,\n\tdate,\n\tdaysAhead,\n\tlocale,\n\thour12,\n\tlabels,\n\temptyState,\n\tonEventClick,\n\tclassName,\n\trenderEvent,\n\trenderPopover,\n}: AgendaViewProps<TData>) {\n\tconst text = { ...DEFAULT_LABELS, ...labels };\n\n\t/**\n\t * One group per day that has something on it, in order. An event is filed\n\t * under the day it starts on, as it is in the grid.\n\t */\n\tconst groups = useMemo(() => {\n\t\tconst range = getViewDateRange(date, 'agenda');\n\t\tconst from = new Date(range.startDate);\n\t\tfrom.setHours(0, 0, 0, 0);\n\t\tconst to =\n\t\t\tdaysAhead === undefined ? range.endDate : new Date(from.getTime() + daysAhead * 86_400_000);\n\n\t\tconst byDay = new Map<string, { day: Date; events: CalendarEvent<TData>[] }>();\n\n\t\tfor (const event of events) {\n\t\t\tif (event.endDate < from || event.startDate > to) continue;\n\n\t\t\tconst day = new Date(event.startDate);\n\t\t\tday.setHours(0, 0, 0, 0);\n\t\t\t// Something already running when the list starts belongs to its first\n\t\t\t// visible day, not to a header nobody can see.\n\t\t\tif (day < from) day.setTime(from.getTime());\n\n\t\t\tconst key = day.toDateString();\n\t\t\tconst group = byDay.get(key) ?? { day, events: [] };\n\t\t\tgroup.events.push(event);\n\t\t\tbyDay.set(key, group);\n\t\t}\n\n\t\treturn [...byDay.values()]\n\t\t\t.sort((a, b) => a.day.getTime() - b.day.getTime())\n\t\t\t.map((group) => ({\n\t\t\t\t...group,\n\t\t\t\tevents: group.events.sort((a, b) => a.startDate.getTime() - b.startDate.getTime()),\n\t\t\t}));\n\t}, [events, date, daysAhead]);\n\n\tif (groups.length === 0) {\n\t\treturn (\n\t\t\t<div className={cn('flex h-full flex-col items-center justify-center py-12', className)}>\n\t\t\t\t{emptyState ?? <p className=\"text-sm text-muted-foreground\">{text.empty}</p>}\n\t\t\t</div>\n\t\t);\n\t}\n\n\tconst now = new Date();\n\n\t/**\n\t * Several people's agendas merged into one list read as one person's unless\n\t * each row says whose it is. One agenda on screen and the names are noise,\n\t * so this turns itself on only when there is more than one.\n\t */\n\tconst resources = new Set<string>();\n\tfor (const group of groups) {\n\t\tfor (const event of group.events) {\n\t\t\tfor (const person of event.participants ?? []) resources.add(person.id);\n\t\t}\n\t}\n\tconst showOwners = resources.size > 1;\n\n\tconst ownersOf = (event: CalendarEvent<TData>) =>\n\t\tshowOwners\n\t\t\t? (event.participants ?? [])\n\t\t\t\t\t.map((p) => p.name)\n\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t.join(', ')\n\t\t\t: undefined;\n\n\tconst timeOf = (event: CalendarEvent<TData>) => {\n\t\tif (event.isAllDay) return text.allDay;\n\t\tconst start = formatClock(event.startDate, { locale, hour12 });\n\t\t// A multi-day event ends on another day; its clock time here would read\n\t\t// as if it finished earlier the same morning.\n\t\tif (!isSameDay(event.startDate, event.endDate)) return start;\n\t\treturn `${start} – ${formatClock(event.endDate, { locale, hour12 })}`;\n\t};\n\n\treturn (\n\t\t<div className={cn('flex h-full flex-col overflow-auto', className)}>\n\t\t\t{groups.map(({ day, events: dayEvents }) => {\n\t\t\t\tconst today = isToday(day);\n\t\t\t\t// The red line goes where now falls among today's events.\n\t\t\t\tconst nowIndex = today ? dayEvents.findIndex((event) => event.endDate > now) : -1;\n\n\t\t\t\treturn (\n\t\t\t\t\t<div key={day.toDateString()} className={cn('flex border-b last:border-b-0')}>\n\t\t\t\t\t\t<div className={cn('flex w-32 shrink-0 items-center gap-2 py-3 pl-4')}>\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex size-9 items-center justify-center rounded-full text-xl',\n\t\t\t\t\t\t\t\t\ttoday ? 'bg-primary font-medium text-primary-foreground' : 'text-foreground'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{day.getDate()}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'text-[11px] font-medium uppercase tracking-wide',\n\t\t\t\t\t\t\t\t\ttoday ? 'text-primary' : 'text-muted-foreground'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{new Intl.DateTimeFormat(locale, {\n\t\t\t\t\t\t\t\t\tmonth: 'short',\n\t\t\t\t\t\t\t\t\tweekday: 'short',\n\t\t\t\t\t\t\t\t}).format(day)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div className=\"min-w-0 flex-1 py-2 pr-4\">\n\t\t\t\t\t\t\t{dayEvents.map((event, index) => (\n\t\t\t\t\t\t\t\t<div key={event.id}>\n\t\t\t\t\t\t\t\t\t{index === nowIndex && <NowLine />}\n\t\t\t\t\t\t\t\t\t{renderEvent ? (\n\t\t\t\t\t\t\t\t\t\trenderEvent({ event, variant: 'full' })\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<Row\n\t\t\t\t\t\t\t\t\t\t\tevent={event}\n\t\t\t\t\t\t\t\t\t\t\ttime={timeOf(event)}\n\t\t\t\t\t\t\t\t\t\t\towners={ownersOf(event) || undefined}\n\t\t\t\t\t\t\t\t\t\t\tonEventClick={onEventClick}\n\t\t\t\t\t\t\t\t\t\t\trenderPopover={renderPopover}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t{/* Everything today has already ended. */}\n\t\t\t\t\t\t\t{today && nowIndex === -1 && <NowLine />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t})}\n\t\t</div>\n\t);\n}\n\nexport default AgendaView;\n","/**\n * Day Events Expansion Overlay\n *\n * A morphing overlay that expands from a month-view day cell to reveal\n * all events for that day. Provides a smooth, professional alternative\n * to the simple popover when clicking \"+N more\" in month view.\n *\n * ## How it works\n *\n * 1. User clicks \"+N more\" in a month cell\n * 2. The cell's bounding rect is captured\n * 3. A fixed overlay appears at the cell's exact position/size\n * 4. CSS transitions smoothly expand it to a larger dialog-like panel\n * 5. All day events are shown inside with full detail\n * 6. On close, the overlay morphs back to the cell and fades out\n *\n * ## Usage\n *\n * ```tsx\n * <DayEventsExpansion\n * isOpen={isOpen}\n * onClose={() => setIsOpen(false)}\n * date={selectedDate}\n * events={dayEvents}\n * anchorRect={cellRect}\n * />\n * ```\n *\n * @module\n */\n\nimport {\n\ttype ReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport type { CalendarEvent, TBadgeVariant, TOnEventClick } from '../../core/types';\nimport { cn } from '../../lib/utils';\nimport { EventCard } from '../event/event-card';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * Props for the {@link DayEventsExpansion} overlay component.\n *\n * @template TData - Custom event data type\n *\n * @example\n * ```tsx\n * <DayEventsExpansion\n * isOpen={expandedDay !== null}\n * onClose={() => setExpandedDay(null)}\n * date={expandedDate}\n * events={dayEvents}\n * anchorRect={cellRect}\n * badgeVariant=\"colored\"\n * onEventClick={(e) => openDetail(e)}\n * />\n * ```\n */\nexport interface DayEventsExpansionProps<TData = Record<string, unknown>> {\n\t/** Whether the expansion overlay is visible */\n\tisOpen: boolean;\n\t/** Called when the overlay should close (Escape, backdrop click, close button) */\n\tonClose: () => void;\n\t/** The date whose events are being shown */\n\tdate: Date;\n\t/** All events for this day */\n\tevents: CalendarEvent<TData>[];\n\t/** Bounding rect of the source day cell (used as animation origin) */\n\tanchorRect: DOMRect | null;\n\t/** Badge variant for event cards. @default 'colored' */\n\tbadgeVariant?: TBadgeVariant;\n\t/** Event click handler */\n\tonEventClick?: TOnEventClick<TData> | undefined;\n\t/** Custom event renderer */\n\trenderEvent?:\n\t\t| ((props: { event: CalendarEvent<TData>; variant: 'compact' }) => ReactNode)\n\t\t| undefined;\n\t/** Custom popover content renderer */\n\trenderPopover?:\n\t\t| ((props: { event: CalendarEvent<TData>; onClose: () => void }) => ReactNode)\n\t\t| undefined;\n\t/** Additional CSS classes for the overlay panel */\n\tclassName?: string;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\n/** Width of the expanded panel */\nconst PANEL_WIDTH = 360;\n/** Maximum height of the expanded panel */\nconst PANEL_MAX_HEIGHT = 480;\n/** Duration of the morph animation in ms */\nconst ANIMATION_DURATION = 280;\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function DayEventsExpansion<TData = Record<string, unknown>>({\n\tisOpen,\n\tonClose,\n\tdate,\n\tevents,\n\tanchorRect,\n\tbadgeVariant = 'colored',\n\tonEventClick,\n\trenderEvent,\n\trenderPopover,\n\tclassName,\n}: DayEventsExpansionProps<TData>) {\n\tconst overlayRef = useRef<HTMLDivElement>(null);\n\tconst panelRef = useRef<HTMLDivElement>(null);\n\tconst [phase, setPhase] = useState<'closed' | 'entering' | 'open' | 'exiting'>('closed');\n\n\t// Persist the anchor rect so the close animation can morph back to the\n\t// original cell position even after the parent clears its state.\n\tconst lastAnchorRef = useRef<DOMRect | null>(null);\n\tif (anchorRect) {\n\t\tlastAnchorRef.current = anchorRect;\n\t}\n\tconst effectiveAnchorRect = anchorRect ?? lastAnchorRef.current;\n\n\t// Sort events by start time\n\tconst sortedEvents = useMemo(\n\t\t() => [...events].sort((a, b) => a.startDate.getTime() - b.startDate.getTime()),\n\t\t[events]\n\t);\n\n\t// Calculate the expanded panel position (centered around the anchor, clamped to viewport)\n\tconst expandedPosition = useMemo(() => {\n\t\tconst rect = effectiveAnchorRect;\n\t\tif (!rect)\n\t\t\treturn {\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0,\n\t\t\t\twidth: PANEL_WIDTH,\n\t\t\t\tmaxHeight: PANEL_MAX_HEIGHT,\n\t\t\t};\n\n\t\tconst viewportWidth = typeof window !== 'undefined' ? window.innerWidth : 1200;\n\t\tconst viewportHeight = typeof window !== 'undefined' ? window.innerHeight : 800;\n\n\t\t// Center horizontally relative to anchor\n\t\tlet left = rect.left + rect.width / 2 - PANEL_WIDTH / 2;\n\t\t// Clamp to viewport with 16px padding\n\t\tleft = Math.max(16, Math.min(left, viewportWidth - PANEL_WIDTH - 16));\n\n\t\t// Position vertically: try to center on anchor, but prefer below if space allows\n\t\tconst naturalHeight = Math.min(events.length * 68 + 80, PANEL_MAX_HEIGHT);\n\t\tlet top = rect.top + rect.height / 2 - naturalHeight / 2;\n\t\t// Clamp to viewport with 16px padding\n\t\ttop = Math.max(16, Math.min(top, viewportHeight - naturalHeight - 16));\n\n\t\treturn { top, left, width: PANEL_WIDTH, maxHeight: PANEL_MAX_HEIGHT };\n\t}, [effectiveAnchorRect, events.length]);\n\n\t// Handle open/close transitions\n\tuseLayoutEffect(() => {\n\t\tif (isOpen && effectiveAnchorRect) {\n\t\t\tsetPhase('entering');\n\t\t\t// Trigger expansion on next frame for CSS transition\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tsetPhase('open');\n\t\t\t\t});\n\t\t\t});\n\t\t} else if (!isOpen && (phase === 'open' || phase === 'entering')) {\n\t\t\tsetPhase('exiting');\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsetPhase('closed');\n\t\t\t\t// Clear stored anchor after close animation completes\n\t\t\t\tlastAnchorRef.current = null;\n\t\t\t}, ANIMATION_DURATION);\n\t\t\treturn () => clearTimeout(timer);\n\t\t}\n\t}, [isOpen, effectiveAnchorRect]);\n\n\t// Keyboard: Escape to close\n\tuseEffect(() => {\n\t\tif (phase === 'closed') return;\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\te.stopPropagation();\n\t\t\t\tonClose();\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', handleKeyDown);\n\t\treturn () => document.removeEventListener('keydown', handleKeyDown);\n\t}, [phase, onClose]);\n\n\t// Focus trap: focus the panel when open\n\tuseEffect(() => {\n\t\tif (phase === 'open' && panelRef.current) {\n\t\t\tpanelRef.current.focus();\n\t\t}\n\t}, [phase]);\n\n\t// Handle backdrop click\n\tconst handleBackdropClick = useCallback(\n\t\t(e: React.MouseEvent) => {\n\t\t\tif (e.target === overlayRef.current) {\n\t\t\t\tonClose();\n\t\t\t}\n\t\t},\n\t\t[onClose]\n\t);\n\n\t// Don't render anything when fully closed\n\tif (phase === 'closed') return null;\n\n\t// Compute styles for the morph effect\n\tconst isCollapsed = phase === 'entering' || phase === 'exiting';\n\tconst morphRect = effectiveAnchorRect;\n\n\tconst panelStyle: React.CSSProperties =\n\t\tisCollapsed && morphRect\n\t\t\t? {\n\t\t\t\t\t// Collapsed state: match the day cell exactly\n\t\t\t\t\tposition: 'fixed',\n\t\t\t\t\ttop: morphRect.top,\n\t\t\t\t\tleft: morphRect.left,\n\t\t\t\t\twidth: morphRect.width,\n\t\t\t\t\theight: morphRect.height,\n\t\t\t\t\tmaxHeight: morphRect.height,\n\t\t\t\t\topacity: phase === 'entering' ? 0.7 : 0,\n\t\t\t\t\ttransform: 'scale(1)',\n\t\t\t\t\tborderRadius: '8px',\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\t// Expanded state: full panel\n\t\t\t\t\tposition: 'fixed',\n\t\t\t\t\ttop: expandedPosition.top,\n\t\t\t\t\tleft: expandedPosition.left,\n\t\t\t\t\twidth: expandedPosition.width,\n\t\t\t\t\tmaxHeight: expandedPosition.maxHeight,\n\t\t\t\t\topacity: 1,\n\t\t\t\t\ttransform: 'scale(1)',\n\t\t\t\t\tborderRadius: '12px',\n\t\t\t\t};\n\n\tconst backdropOpacity = isCollapsed ? 0 : 1;\n\n\t// Format the date for the header\n\tconst dateStr = date.toLocaleDateString(undefined, {\n\t\tweekday: 'long',\n\t\tmonth: 'long',\n\t\tday: 'numeric',\n\t});\n\n\treturn (\n\t\t<>\n\t\t\t{/* Backdrop */}\n\t\t\t<div\n\t\t\t\tref={overlayRef}\n\t\t\t\trole=\"presentation\"\n\t\t\t\tonClick={handleBackdropClick}\n\t\t\t\tclassName=\"ic-expansion-backdrop\"\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: 'fixed',\n\t\t\t\t\tinset: 0,\n\t\t\t\t\tzIndex: 40,\n\t\t\t\t\tbackgroundColor: 'rgba(0, 0, 0, 0.2)',\n\t\t\t\t\topacity: backdropOpacity,\n\t\t\t\t\ttransition: `opacity ${ANIMATION_DURATION}ms cubic-bezier(0.32, 0.72, 0, 1)`,\n\t\t\t\t}}\n\t\t\t/>\n\n\t\t\t{/* Expansion panel */}\n\t\t\t<div\n\t\t\t\tref={panelRef}\n\t\t\t\trole=\"dialog\"\n\t\t\t\taria-modal=\"true\"\n\t\t\t\taria-label={`Events for ${dateStr}`}\n\t\t\t\ttabIndex={-1}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'ic-expansion-panel',\n\t\t\t\t\t'!bg-white border border-border shadow-2xl overflow-hidden',\n\t\t\t\t\t'focus:outline-none',\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\tstyle={{\n\t\t\t\t\t...panelStyle,\n\t\t\t\t\tzIndex: 41,\n\t\t\t\t\ttransition: `all ${ANIMATION_DURATION}ms cubic-bezier(0.32, 0.72, 0, 1)`,\n\t\t\t\t\twillChange: 'top, left, width, height, max-height, opacity, border-radius',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{/* Header */}\n\t\t\t\t<div className=\"flex items-center justify-between px-4 py-3 border-b bg-muted/30\">\n\t\t\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t\t\t<span className=\"text-sm font-semibold text-foreground\">{dateStr}</span>\n\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t{events.length} event{events.length !== 1 ? 's' : ''}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\tclassName=\"flex items-center justify-center size-7 rounded-full hover:bg-muted transition-colors text-muted-foreground hover:text-foreground\"\n\t\t\t\t\t\taria-label=\"Close\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\twidth=\"14\"\n\t\t\t\t\t\t\theight=\"14\"\n\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<path d=\"M18 6 6 18\" />\n\t\t\t\t\t\t\t<path d=\"m6 6 12 12\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Events list */}\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"overflow-y-auto px-3 py-2 space-y-1.5\"\n\t\t\t\t\tstyle={{ maxHeight: `${PANEL_MAX_HEIGHT - 64}px` }}\n\t\t\t\t>\n\t\t\t\t\t{sortedEvents.map((event) => (\n\t\t\t\t\t\t<div key={event.id} onPointerDown={(e) => e.stopPropagation()}>\n\t\t\t\t\t\t\t{renderEvent ? (\n\t\t\t\t\t\t\t\trenderEvent({ event, variant: 'compact' })\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<EventCard\n\t\t\t\t\t\t\t\t\tevent={event}\n\t\t\t\t\t\t\t\t\tvariant=\"compact\"\n\t\t\t\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\t\t\t\tonClick={onEventClick}\n\t\t\t\t\t\t\t\t\trenderPopover={renderPopover}\n\t\t\t\t\t\t\t\t\tshowTime\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\n\t\t\t\t\t{events.length === 0 && (\n\t\t\t\t\t\t<div className=\"py-6 text-center text-sm text-muted-foreground\">No events</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n\nexport default DayEventsExpansion;\n","/**\n * Multi-Day Event Banner\n *\n * Displays multi-day and all-day events in a banner above the time grid.\n * Used in Day view (week view uses {@link WeekAllDayRow} for column-aligned layout).\n *\n * Each event pill supports Radix UI `Popover` (or `Tooltip` when popover\n * is disabled), matching the interaction model of `EventBlock`.\n *\n * All-day events are shown with an \"All day\" badge instead of confusing\n * time indicators. Multi-day events show directional arrows (→) to\n * indicate continuation.\n */\n\nimport { type ReactNode, useCallback, useState } from 'react';\nimport { CANCELED_CHIP } from '../../core/constants';\nimport type { CalendarEvent, TOnEventClick } from '../../core/types';\nimport { detectAllDayEvent, isSameDay } from '../../core/utils/date-utils';\nimport { formatEventTimeDisplay } from '../../core/utils/event-utils';\nimport { cn } from '../../lib/utils';\nimport { getEventColorClasses } from '../event/event-card';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface MultiDayBannerProps<TData = Record<string, unknown>> {\n\t/** Multi-day events to display */\n\tevents: CalendarEvent<TData>[];\n\t/** Reference date (for determining start/end indicators) */\n\tdate: Date;\n\t/** Click handler (fires only when popover is disabled) */\n\tonEventClick?: TOnEventClick<TData> | undefined;\n\t/**\n\t * When `true`, clicking opens no built-in popover — instead `onEventClick`\n\t * fires directly. @default false\n\t */\n\tdisablePopover?: boolean;\n\t/**\n\t * Custom popover content rendered inside the built-in Radix popover.\n\t * When omitted a lightweight default popover is shown.\n\t */\n\trenderPopover?:\n\t\t| ((props: { event: CalendarEvent<TData>; onClose: () => void }) => ReactNode)\n\t\t| undefined;\n\t/** Additional CSS classes */\n\tclassName?: string;\n}\n\n// ============================================================================\n// BANNER EVENT PILL (with Popover / Tooltip support)\n// ============================================================================\n\ninterface BannerEventPillProps<TData> {\n\tevent: CalendarEvent<TData>;\n\tdate: Date;\n\tonEventClick: TOnEventClick<TData> | undefined;\n\tdisablePopover: boolean;\n\trenderPopover:\n\t\t| ((props: { event: CalendarEvent<TData>; onClose: () => void }) => ReactNode)\n\t\t| undefined;\n}\n\nfunction BannerEventPill<TData>({\n\tevent,\n\tdate,\n\tonEventClick,\n\tdisablePopover,\n\trenderPopover,\n}: BannerEventPillProps<TData>) {\n\tconst [popoverOpen, setPopoverOpen] = useState(false);\n\tconst colors = getEventColorClasses(event.color);\n\tconst isAllDay = detectAllDayEvent(event);\n\tconst isStart = isSameDay(event.startDate, date);\n\tconst isEnd = isSameDay(event.endDate, date);\n\tconst isSingleDayAllDay = isAllDay && isSameDay(event.startDate, event.endDate);\n\n\tconst handleClick = useCallback(() => {\n\t\tif (disablePopover && onEventClick) {\n\t\t\tonEventClick(event);\n\t\t} else if (!disablePopover) {\n\t\t\tsetPopoverOpen(true);\n\t\t}\n\t}, [disablePopover, onEventClick, event]);\n\n\tconst handleClose = useCallback(() => {\n\t\tsetPopoverOpen(false);\n\t}, []);\n\n\tconst pillButton = (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={handleClick}\n\t\t\ttitle={formatEventTimeDisplay(event)}\n\t\t\tclassName={cn(\n\t\t\t\t'inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[10px] font-medium transition-opacity hover:opacity-80',\n\t\t\t\t'sm:px-2 sm:py-1 sm:text-xs',\n\t\t\t\tevent.isCanceled ? CANCELED_CHIP : [colors.bg, colors.text]\n\t\t\t)}\n\t\t>\n\t\t\t{!isSingleDayAllDay && isStart && !isEnd && '→ '}\n\t\t\t{!isSingleDayAllDay && !isStart && isEnd && ' ←'}\n\t\t\t{!isSingleDayAllDay && !isStart && !isEnd && '↔ '}\n\t\t\t<span className=\"truncate max-w-24 sm:max-w-32\">{event.title}</span>\n\t\t\t{isSingleDayAllDay && <span className=\"text-[9px] opacity-70 sm:text-[10px]\">All day</span>}\n\t\t</button>\n\t);\n\n\tconst tooltipContent = (\n\t\t<TooltipContent>\n\t\t\t<div className=\"flex flex-col gap-0.5\">\n\t\t\t\t<div className=\"font-medium\">{event.title}</div>\n\t\t\t\t<div className=\"text-xs text-muted-foreground tabular-nums\">\n\t\t\t\t\t{formatEventTimeDisplay(event)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</TooltipContent>\n\t);\n\n\tif (disablePopover) {\n\t\treturn (\n\t\t\t<Tooltip>\n\t\t\t\t<TooltipTrigger asChild>{pillButton}</TooltipTrigger>\n\t\t\t\t{tooltipContent}\n\t\t\t</Tooltip>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Popover open={popoverOpen} onOpenChange={setPopoverOpen}>\n\t\t\t<PopoverTrigger asChild>{pillButton}</PopoverTrigger>\n\t\t\t<PopoverContent className=\"w-80\">\n\t\t\t\t{renderPopover ? (\n\t\t\t\t\trenderPopover({ event, onClose: handleClose })\n\t\t\t\t) : (\n\t\t\t\t\t<BannerDefaultPopoverContent event={event} onClose={handleClose} />\n\t\t\t\t)}\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n\n// ============================================================================\n// DEFAULT POPOVER CONTENT (lightweight fallback)\n// ============================================================================\n\nfunction BannerDefaultPopoverContent<TData>({\n\tevent,\n\tonClose,\n}: {\n\tevent: CalendarEvent<TData>;\n\tonClose: () => void;\n}) {\n\tconst colors = getEventColorClasses(event.color);\n\tconst isCanceled = event.isCanceled ?? false;\n\n\treturn (\n\t\t<div className=\"space-y-3\">\n\t\t\t<div className=\"flex items-start gap-3\">\n\t\t\t\t<div className={cn('size-4 rounded shrink-0 mt-0.5', colors.dot)} />\n\t\t\t\t<div className=\"flex-1 min-w-0\">\n\t\t\t\t\t<h3 className={cn('font-semibold text-lg', isCanceled && 'line-through opacity-50')}>\n\t\t\t\t\t\t{event.title}\n\t\t\t\t\t</h3>\n\t\t\t\t\t<div className=\"flex items-center gap-1 text-sm text-muted-foreground mt-1 tabular-nums\">\n\t\t\t\t\t\t{formatEventTimeDisplay(event)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{event.description && <p className=\"text-sm text-muted-foreground\">{event.description}</p>}\n\n\t\t\t<div className=\"flex flex-wrap gap-1.5\">\n\t\t\t\t{event.isAllDay && (\n\t\t\t\t\t<span className=\"text-xs bg-muted px-2 py-0.5 rounded-full font-medium\">All day</span>\n\t\t\t\t)}\n\t\t\t\t{isCanceled && (\n\t\t\t\t\t<span className=\"text-xs bg-red-100 dark:bg-red-950/30 text-red-700 dark:text-red-300 px-2 py-0.5 rounded-full font-medium\">\n\t\t\t\t\t\tCanceled\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t<div className=\"flex justify-end pt-2 border-t\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={onClose}\n\t\t\t\t\tclassName=\"text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md hover:bg-muted transition-colors\"\n\t\t\t\t>\n\t\t\t\t\tClose\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function MultiDayBanner<TData = Record<string, unknown>>({\n\tevents,\n\tdate,\n\tonEventClick,\n\tdisablePopover = false,\n\trenderPopover,\n\tclassName,\n}: MultiDayBannerProps<TData>) {\n\tif (events.length === 0) return null;\n\n\t// Separate all-day from multi-day events for distinct labeling\n\tconst hasAllDay = events.some((e) => detectAllDayEvent(e) && isSameDay(e.startDate, e.endDate));\n\tconst hasMultiDay = events.some(\n\t\t(e) =>\n\t\t\t!isSameDay(e.startDate, e.endDate) ||\n\t\t\t(detectAllDayEvent(e) && !isSameDay(e.startDate, e.endDate))\n\t);\n\n\tconst label =\n\t\thasAllDay && hasMultiDay ? 'All day / Multi-day' : hasAllDay ? 'All day' : 'Multi-day';\n\n\treturn (\n\t\t<div className={cn('border-b bg-muted/20 px-2 py-1.5 space-y-1', 'sm:px-4 sm:py-2', className)}>\n\t\t\t{/* Label */}\n\t\t\t<span className=\"text-[10px] font-medium text-muted-foreground sm:text-xs\">{label}</span>\n\n\t\t\t{/* Events */}\n\t\t\t<div className=\"flex flex-wrap gap-1\">\n\t\t\t\t{events.map((event) => (\n\t\t\t\t\t<BannerEventPill\n\t\t\t\t\t\tkey={event.id}\n\t\t\t\t\t\tevent={event}\n\t\t\t\t\t\tdate={date}\n\t\t\t\t\t\tonEventClick={onEventClick}\n\t\t\t\t\t\tdisablePopover={disablePopover}\n\t\t\t\t\t\trenderPopover={renderPopover}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default MultiDayBanner;\n","/**\n * Selectable Slot Component\n *\n * A unified component for handling slot interactions in calendar views.\n * Supports:\n * - Single click (quick event creation)\n * - Click and drag (range selection)\n * - Touch support for mobile\n * - Visual feedback during selection\n * - Drag & drop receiving for event repositioning\n *\n * This component consolidates the interaction logic that was previously\n * scattered across different view components.\n */\n\nimport { type ReactNode, useCallback, useEffect, useRef, useState } from 'react';\nimport { useOptionalDragDrop } from '../../core/context';\nimport type { ITimeSlot } from '../../core/types';\nimport { cn } from '../../lib/utils';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface SelectableSlotProps {\n\t/** The time slot this component represents */\n\tslot: ITimeSlot;\n\t/** Called when selection starts on this slot */\n\tonSelectionStart?: (slot: ITimeSlot) => void;\n\t/** Called when pointer moves over this slot during selection */\n\tonSelectionMove?: (slot: ITimeSlot) => void;\n\t/** Called when selection ends on this slot */\n\tonSelectionEnd?: () => void;\n\t/** Whether this slot is currently in the selection range */\n\tisSelected?: boolean;\n\t/** Whether a selection is in progress (for hover effects) */\n\tisSelecting?: boolean;\n\t/** Whether this slot is disabled (non-working hours) */\n\tdisabled?: boolean;\n\t/** Accessibility label */\n\tariaLabel?: string;\n\t/** Child content */\n\tchildren?: ReactNode;\n\t/** Additional classes */\n\tclassName?: string;\n\t/** Height of the slot (for time grid positioning) */\n\theight?: string | number;\n\t/** Inline style for positioning */\n\tstyle?: React.CSSProperties;\n\t/** Custom data attributes */\n\tdataAttributes?: Record<string, string>;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\n/** Minimum drag distance to differentiate from click (in pixels) */\nconst DRAG_THRESHOLD = 5;\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function SelectableSlot({\n\tslot,\n\tonSelectionStart,\n\tonSelectionMove,\n\tonSelectionEnd,\n\tisSelected = false,\n\tisSelecting = false,\n\tdisabled = false,\n\tariaLabel,\n\tchildren,\n\tclassName,\n\theight,\n\tstyle,\n\tdataAttributes,\n}: SelectableSlotProps) {\n\t// Track if this is a drag or click\n\tconst startPositionRef = useRef<{ x: number; y: number } | null>(null);\n\tconst isDraggingRef = useRef(false);\n\tconst isMouseDownRef = useRef(false);\n\tconst buttonRef = useRef<HTMLButtonElement>(null);\n\tconst [isDragOver, setIsDragOver] = useState(false);\n\n\t// Get drag-drop context for receiving dropped events\n\tconst dragDrop = useOptionalDragDrop();\n\n\t// Handle pointer down (mouse or touch)\n\tconst handlePointerDown = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\tif (disabled) return;\n\n\t\t\t// Only handle primary button (left click) or touch\n\t\t\tif (e.button !== 0 && e.pointerType === 'mouse') return;\n\n\t\t\t// Prevent text selection during drag\n\t\t\te.preventDefault();\n\n\t\t\t// Store start position for drag detection\n\t\t\tstartPositionRef.current = { x: e.clientX, y: e.clientY };\n\t\t\tisDraggingRef.current = false;\n\t\t\tisMouseDownRef.current = true;\n\n\t\t\t// Start selection\n\t\t\tonSelectionStart?.(slot);\n\t\t},\n\t\t[disabled, slot, onSelectionStart]\n\t);\n\n\t// Handle pointer move - check for drag threshold\n\tconst handlePointerMove = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\tif (!(startPositionRef.current && isMouseDownRef.current && !disabled)) return;\n\n\t\t\t// Check if we've moved enough to be a drag\n\t\t\tconst dx = e.clientX - startPositionRef.current.x;\n\t\t\tconst dy = e.clientY - startPositionRef.current.y;\n\t\t\tconst distance = Math.sqrt(dx * dx + dy * dy);\n\n\t\t\tif (distance >= DRAG_THRESHOLD) {\n\t\t\t\tisDraggingRef.current = true;\n\t\t\t}\n\t\t},\n\t\t[disabled]\n\t);\n\n\t// Handle pointer enter - key for multi-cell selection\n\tconst handlePointerEnter = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\tif (disabled) return;\n\n\t\t\t// Check if any pointer button is pressed (works for both mouse and touch)\n\t\t\t// e.buttons is a bitmask: 1 = primary button (left), 2 = secondary, etc.\n\t\t\tif (e.buttons > 0 || isSelecting) {\n\t\t\t\tonSelectionMove?.(slot);\n\t\t\t}\n\t\t},\n\t\t[disabled, isSelecting, slot, onSelectionMove]\n\t);\n\n\t// Handle pointer up\n\tconst handlePointerUp = useCallback(() => {\n\t\tif (disabled) return;\n\n\t\t// End selection\n\t\tonSelectionEnd?.();\n\n\t\t// Reset tracking\n\t\tstartPositionRef.current = null;\n\t\tisDraggingRef.current = false;\n\t\tisMouseDownRef.current = false;\n\t}, [disabled, onSelectionEnd]);\n\n\t// Drag & drop handlers for receiving events\n\tconst handleDragOver = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\tif (!dragDrop?.isDragging || disabled) return;\n\t\t\te.preventDefault();\n\t\t\te.dataTransfer.dropEffect = 'move';\n\t\t\tsetIsDragOver(true);\n\t\t\t// Update preview position in drag context\n\t\t\t// For month view (no hour/minute), use current time\n\t\t\tconst now = new Date();\n\t\t\tconst hour = slot.hour ?? now.getHours();\n\t\t\tconst minute = slot.minute ?? (now.getMinutes() >= 30 ? 30 : 0);\n\t\t\tdragDrop.updateDragPreview?.(slot.date, hour, minute);\n\t\t},\n\t\t[dragDrop, disabled, slot]\n\t);\n\n\tconst handleDragLeave = useCallback(() => {\n\t\tsetIsDragOver(false);\n\t}, []);\n\n\tconst handleDrop = useCallback(\n\t\t(e: React.DragEvent) => {\n\t\t\te.preventDefault();\n\t\t\tsetIsDragOver(false);\n\t\t\tif (!dragDrop?.isDragging || disabled) return;\n\t\t\t// End drag and trigger the drop callback in DragDropProvider\n\t\t\tdragDrop.endDrag?.();\n\t\t},\n\t\t[dragDrop, disabled]\n\t);\n\n\t// Add global pointer up listener to handle cases where mouse is released outside\n\tuseEffect(() => {\n\t\tconst handleGlobalPointerUp = () => {\n\t\t\tif (isMouseDownRef.current) {\n\t\t\t\tisMouseDownRef.current = false;\n\t\t\t\tstartPositionRef.current = null;\n\t\t\t\tisDraggingRef.current = false;\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener('pointerup', handleGlobalPointerUp);\n\t\twindow.addEventListener('pointercancel', handleGlobalPointerUp);\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener('pointerup', handleGlobalPointerUp);\n\t\t\twindow.removeEventListener('pointercancel', handleGlobalPointerUp);\n\t\t};\n\t}, []);\n\n\t// Handle keyboard for accessibility\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent) => {\n\t\t\tif (disabled) return;\n\n\t\t\tif (e.key === 'Enter' || e.key === ' ') {\n\t\t\t\te.preventDefault();\n\t\t\t\tonSelectionStart?.(slot);\n\t\t\t\tonSelectionEnd?.();\n\t\t\t}\n\t\t},\n\t\t[disabled, slot, onSelectionStart, onSelectionEnd]\n\t);\n\n\treturn (\n\t\t<button\n\t\t\tref={buttonRef}\n\t\t\ttype=\"button\"\n\t\t\taria-label={ariaLabel}\n\t\t\taria-disabled={disabled}\n\t\t\taria-pressed={isSelected}\n\t\t\tdisabled={disabled}\n\t\t\tonPointerDown={handlePointerDown}\n\t\t\tonPointerMove={handlePointerMove}\n\t\t\tonPointerUp={handlePointerUp}\n\t\t\tonPointerEnter={handlePointerEnter}\n\t\t\tonKeyDown={handleKeyDown}\n\t\t\tonDragOver={handleDragOver}\n\t\t\tonDragLeave={handleDragLeave}\n\t\t\tonDrop={handleDrop}\n\t\t\tclassName={cn(\n\t\t\t\t'select-none touch-none cursor-pointer transition-colors',\n\t\t\t\t'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset',\n\t\t\t\t// Hover state (only when not in selection)\n\t\t\t\t!(isSelecting || disabled) && 'hover:bg-blue-50/60',\n\t\t\t\t// Selection state — blue tint matching the primary color\n\t\t\t\tisSelected && 'bg-blue-100/70',\n\t\t\t\t// Drag over state - visual feedback when event is dragged over\n\t\t\t\tisDragOver && 'bg-primary/20 ring-2 ring-primary ring-inset',\n\t\t\t\t// Disabled state\n\t\t\t\tdisabled && 'cursor-not-allowed opacity-50',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tstyle={{ height, ...style }}\n\t\t\t{...dataAttributes}\n\t\t>\n\t\t\t{children}\n\t\t</button>\n\t);\n}\n\n// ============================================================================\n// SPECIALIZED SLOT COMPONENTS\n// ============================================================================\n\n/**\n * TimeSlot - For day/week views with configurable time granularity\n * Supports 15, 30, or 60 minute slot durations\n * Accepts either a `slot` prop OR individual `date/hour/minute` props\n */\ninterface TimeSlotProps extends Omit<SelectableSlotProps, 'slot'> {\n\t/** Direct slot object (preferred) */\n\tslot?: ITimeSlot;\n\t/** Date for the slot (alternative to slot prop) */\n\tdate?: Date;\n\t/** Hour for the slot (alternative to slot prop) */\n\thour?: number;\n\t/** Minute for the slot (alternative to slot prop) */\n\tminute?: number;\n}\n\nexport function TimeSlot({\n\tslot: slotProp,\n\tdate,\n\thour,\n\tminute,\n\tariaLabel,\n\t...props\n}: TimeSlotProps) {\n\t// Use provided slot or construct from individual props\n\tconst slot: ITimeSlot = slotProp ?? { date: date!, hour: hour ?? 0, minute: minute ?? 0 };\n\tconst label =\n\t\tariaLabel ??\n\t\t`Add event at ${(slot.hour ?? 0).toString().padStart(2, '0')}:${(slot.minute ?? 0).toString().padStart(2, '0')} on ${slot.date.toLocaleDateString()}`;\n\n\treturn <SelectableSlot slot={slot} ariaLabel={label} {...props} />;\n}\n\n/**\n * DaySlot - For month/year views with day granularity\n * Renders as a day cell\n * Accepts either a `slot` prop OR a `date` prop\n */\ninterface DaySlotProps extends Omit<SelectableSlotProps, 'slot'> {\n\t/** Direct slot object (preferred) */\n\tslot?: ITimeSlot;\n\t/** Date for the slot (alternative to slot prop) */\n\tdate?: Date;\n}\n\nexport function DaySlot({ slot: slotProp, date, ariaLabel, ...props }: DaySlotProps) {\n\t// Use provided slot or construct from date\n\tconst slot: ITimeSlot = slotProp ?? { date: date! };\n\tconst label = ariaLabel ?? `Select ${slot.date.toLocaleDateString()}`;\n\n\treturn <SelectableSlot slot={slot} ariaLabel={label} {...props} />;\n}\n\nexport type { TimeSlotProps, DaySlotProps };\nexport default SelectableSlot;\n","/**\n * Day View Component\n *\n * Full day time grid showing events hour by hour.\n * Features:\n * - Hourly time slots with event positioning\n * - Current time indicator\n * - Working hours highlighting\n * - Click to add event\n * - Drag to select time range\n *\n * Ported from agenda-v2 to maintain exact styling parity.\n */\n\nimport { useCallback, useLayoutEffect, useMemo, useRef } from 'react';\nimport { DEFAULT_HOUR_HEIGHT } from '../../core/constants';\nimport { useOptionalSlotSelection } from '../../core/context/slot-selection-context';\nimport type {\n\tCalendarEvent,\n\tITimeSlot,\n\tIVisibleHours,\n\tTBadgeVariant,\n\tTOnEventClick,\n\tTOnSlotSelect,\n} from '../../core/types';\nimport {\n\tformatHourLabel,\n\tgetVisibleHoursArray,\n\tisToday,\n\tisWorkingHour,\n\tseparateEventsByDuration,\n\ttype TWorkingHours,\n} from '../../core/utils/date-utils';\nimport { getEventsForDay } from '../../core/utils/event-utils';\nimport { calculateOverlappingPositions } from '../../core/utils/position-utils';\nimport { cn } from '../../lib/utils';\nimport { EventBlock } from '../event/event-card';\nimport { MultiDayBanner } from '../primitives/multi-day-banner';\nimport { TimeSlot } from '../primitives/selectable-slot';\n\n// ============================================================================\n// CONSTANTS (matches agenda-v2)\n// ============================================================================\n\nconst HOUR_HEIGHT = DEFAULT_HOUR_HEIGHT; // single source of truth\nconst HOUR_COLUMN_WIDTH = 72; // width of hour labels column\nconst MIN_EVENT_CARD_WIDTH = 80; // minimum width in pixels for event cards\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface DayViewProps<TData = Record<string, unknown>> {\n\t/** Events to display */\n\tevents: CalendarEvent<TData>[];\n\t/** The date to display */\n\tdate: Date;\n\t/** Visible hours range */\n\tvisibleHours?: IVisibleHours;\n\t/** Working hours per day */\n\tworkingHours?: TWorkingHours;\n\t/** Slot duration in minutes */\n\tslotDuration?: number;\n\t/** Badge variant for events */\n\tbadgeVariant?: TBadgeVariant;\n\t/** Event click handler */\n\tonEventClick?: TOnEventClick<TData>;\n\t/** Slot select handler */\n\tonSlotSelect?: TOnSlotSelect;\n\t/** Additional CSS classes */\n\tclassName?: string;\n\t/** Custom event renderer */\n\trenderEvent?: (props: {\n\t\tevent: CalendarEvent<TData>;\n\t\tposition: { top: number; height: number; left: number; width: number };\n\t}) => React.ReactNode;\n\t/** Custom popover content renderer */\n\trenderPopover?: (props: { event: CalendarEvent<TData>; onClose: () => void }) => React.ReactNode;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function DayView<TData = Record<string, unknown>>({\n\tevents,\n\tdate,\n\tvisibleHours = { startHour: 0, endHour: 24 },\n\tworkingHours,\n\tslotDuration = 30,\n\tbadgeVariant = 'colored',\n\tonEventClick,\n\tonSlotSelect: _onSlotSelect,\n\tclassName,\n\trenderEvent,\n\trenderPopover,\n}: DayViewProps<TData>) {\n\t// Calculate slot configuration based on slotDuration\n\tconst slotsPerHour = 60 / slotDuration;\n\tconst slotHeightPercent = 100 / slotsPerHour;\n\n\t// Generate slot minutes for each hour (e.g., [0, 30] for 30min, [0, 15, 30, 45] for 15min)\n\tconst slotMinutes = useMemo(() => {\n\t\tconst minutes: number[] = [];\n\t\tfor (let i = 0; i < slotsPerHour; i++) {\n\t\t\tminutes.push(i * slotDuration);\n\t\t}\n\t\treturn minutes;\n\t}, [slotsPerHour, slotDuration]);\n\n\t// Get events for this day\n\tconst dayEvents = useMemo(() => getEventsForDay(events, date), [events, date]);\n\n\t// Separate single-day and multi-day events\n\tconst { singleDay, multiDay } = useMemo(() => separateEventsByDuration(dayEvents), [dayEvents]);\n\n\t// Calculate positions for overlapping events\n\tconst eventPositions = useMemo(() => {\n\t\tconst positions = calculateOverlappingPositions(singleDay, date, visibleHours, HOUR_HEIGHT);\n\t\t// Convert array to Map for fast lookup\n\t\tconst map = new Map<string, { top: number; height: number; left: number; width: number }>();\n\t\tfor (const positioned of positions) {\n\t\t\tmap.set(positioned.event.id, positioned.position);\n\t\t}\n\t\treturn map;\n\t}, [singleDay, date, visibleHours]);\n\n\t// Hours to display\n\tconst hours = useMemo(() => getVisibleHoursArray(visibleHours), [visibleHours]);\n\n\t// Current time indicator position\n\tconst now = new Date();\n\tconst showCurrentTime = isToday(date);\n\tconst currentTimeTop = useMemo(() => {\n\t\tif (!showCurrentTime) return 0;\n\t\tconst currentHour = now.getHours() + now.getMinutes() / 60;\n\t\tif (currentHour < visibleHours.startHour || currentHour > visibleHours.endHour) {\n\t\t\treturn -1; // Out of visible range\n\t\t}\n\t\treturn (currentHour - visibleHours.startHour) * HOUR_HEIGHT;\n\t}, [showCurrentTime, visibleHours, now]);\n\n\t// Ref for scrollable container - used to auto-scroll to working hours\n\tconst scrollContainerRef = useRef<HTMLDivElement>(null);\n\n\t// Auto-scroll to current time (if today) or working hours on mount\n\tuseLayoutEffect(() => {\n\t\tconst container = scrollContainerRef.current;\n\t\tif (!container) return;\n\n\t\t// Use requestAnimationFrame to ensure DOM is fully rendered\n\t\tconst performScroll = () => {\n\t\t\tlet scrollToHour: number;\n\n\t\t\t// Priority 1: If viewing today, scroll to current time\n\t\t\tif (showCurrentTime) {\n\t\t\t\tconst currentHour = new Date().getHours();\n\t\t\t\t// Scroll to 1 hour before current time for context\n\t\t\t\tscrollToHour = Math.max(currentHour - 1, visibleHours.startHour);\n\t\t\t} else {\n\t\t\t\t// Priority 2: Scroll to working hours\n\t\t\t\tconst dayOfWeek = date.getDay();\n\t\t\t\tconst todayWorkingHours = workingHours?.[dayOfWeek];\n\n\t\t\t\t// Check if day has enabled working hours\n\t\t\t\tif (todayWorkingHours?.enabled && todayWorkingHours.from > 0) {\n\t\t\t\t\t// Scroll to 1 hour before working hours, but not before visible range\n\t\t\t\t\tscrollToHour = Math.max(todayWorkingHours.from - 1, visibleHours.startHour);\n\t\t\t\t} else {\n\t\t\t\t\t// Default to 7 AM if no working hours defined, disabled, or starts at midnight\n\t\t\t\t\tscrollToHour = Math.max(7, visibleHours.startHour);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Calculate pixel position\n\t\t\tconst scrollTop = (scrollToHour - visibleHours.startHour) * HOUR_HEIGHT;\n\n\t\t\t// Scroll to position (instant on initial load for better UX)\n\t\t\tcontainer.scrollTo({\n\t\t\t\ttop: scrollTop,\n\t\t\t\tbehavior: 'instant',\n\t\t\t});\n\t\t};\n\n\t\t// Use double requestAnimationFrame to ensure layout is complete\n\t\trequestAnimationFrame(() => {\n\t\t\trequestAnimationFrame(performScroll);\n\t\t});\n\t}, [date, workingHours, visibleHours, showCurrentTime]);\n\n\t// Get slot selection context (optional - works without provider)\n\tconst slotSelection = useOptionalSlotSelection();\n\n\t// Create selection handlers for time slots\n\tconst handleSelectionStart = useCallback(\n\t\t(slot: ITimeSlot) => {\n\t\t\tslotSelection?.startSelection(slot);\n\t\t},\n\t\t[slotSelection]\n\t);\n\n\tconst handleSelectionMove = useCallback(\n\t\t(slot: ITimeSlot) => {\n\t\t\tslotSelection?.updateSelection(slot);\n\t\t},\n\t\t[slotSelection]\n\t);\n\n\tconst handleSelectionEnd = useCallback(() => {\n\t\tslotSelection?.endSelection();\n\t}, [slotSelection]);\n\n\t// Handle multi-day event click\n\tconst handleMultiDayEventClick = useCallback(\n\t\t(event: CalendarEvent<TData>) => {\n\t\t\tonEventClick?.(event);\n\t\t},\n\t\t[onEventClick]\n\t);\n\n\t// Format header date like Google Calendar\n\tconst headerDay = date.toLocaleDateString([], { weekday: 'short' });\n\tconst headerDate = date.getDate();\n\tconst today = isToday(date);\n\n\treturn (\n\t\t<div className={cn('flex flex-col h-full', className)}>\n\t\t\t{/* Header - Google Calendar style */}\n\t\t\t<div className={cn('flex items-center gap-3 border-b px-4 py-3', today && undefined)}>\n\t\t\t\t{/* Day column with name + circled date */}\n\t\t\t\t<div className=\"flex flex-col items-center\">\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'text-[11px] font-medium uppercase tracking-wide',\n\t\t\t\t\t\t\ttoday ? 'text-primary' : 'text-muted-foreground'\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{headerDay}\n\t\t\t\t\t</span>\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex items-center justify-center rounded-full mt-0.5',\n\t\t\t\t\t\t\t'size-12 text-3xl font-normal',\n\t\t\t\t\t\t\ttoday ? 'bg-primary text-primary-foreground' : 'text-foreground'\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{headerDate}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Multi-day events banner */}\n\t\t\t{multiDay.length > 0 && (\n\t\t\t\t<MultiDayBanner\n\t\t\t\t\tevents={multiDay}\n\t\t\t\t\tdate={date}\n\t\t\t\t\tonEventClick={handleMultiDayEventClick}\n\t\t\t\t\tdisablePopover={!!onEventClick && !renderPopover}\n\t\t\t\t\trenderPopover={renderPopover}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Time grid */}\n\t\t\t<div ref={scrollContainerRef} className={cn('flex-1')}>\n\t\t\t\t<div className=\"relative min-h-full\">\n\t\t\t\t\t{/* Hour rows */}\n\t\t\t\t\t{hours.map((hour, index) => {\n\t\t\t\t\t\tconst isWorking = isWorkingHour(date, hour, workingHours);\n\t\t\t\t\t\tconst isDisabled = !isWorking;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={hour}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'relative flex',\n\t\t\t\t\t\t\t\t\tisDisabled && 'bg-calendar-disabled-hour',\n\t\t\t\t\t\t\t\t\tisDisabled ? undefined : undefined\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\tstyle={{ height: HOUR_HEIGHT }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{/* Hour label */}\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclassName={cn('relative flex-shrink-0 border-r border-border/50 bg-background')}\n\t\t\t\t\t\t\t\t\tstyle={{ width: HOUR_COLUMN_WIDTH }}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div className=\"absolute -top-2.5 right-1 sm:right-2 flex h-5 items-center\">\n\t\t\t\t\t\t\t\t\t\t{index !== 0 && (\n\t\t\t\t\t\t\t\t\t\t\t<span className={cn('text-[10px] sm:text-xs text-muted-foreground')}>\n\t\t\t\t\t\t\t\t\t\t\t\t{formatHourLabel(hour)}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t{/* Time slot area */}\n\t\t\t\t\t\t\t\t<div className=\"relative flex-1\">\n\t\t\t\t\t\t\t\t\t{/* Today highlight */}\n\t\t\t\t\t\t\t\t\t{showCurrentTime && !isDisabled && (\n\t\t\t\t\t\t\t\t\t\t<div className=\"absolute inset-0 bg-primary/5\" />\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Top border (except first row) */}\n\t\t\t\t\t\t\t\t\t{index !== 0 && (\n\t\t\t\t\t\t\t\t\t\t<div className=\"pointer-events-none absolute inset-x-0 top-0 border-b border-border/50\" />\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Dashed lines for sub-hour divisions */}\n\t\t\t\t\t\t\t\t\t{slotMinutes.slice(1).map((minute) => (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tkey={minute}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"pointer-events-none absolute inset-x-0 border-b border-dashed border-border/30\"\n\t\t\t\t\t\t\t\t\t\t\tstyle={{ top: `${(minute / 60) * 100}%` }}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t))}\n\n\t\t\t\t\t\t\t\t\t{/* Dynamic time slots based on slotDuration */}\n\t\t\t\t\t\t\t\t\t{slotMinutes.map((minute, slotIndex) => {\n\t\t\t\t\t\t\t\t\t\tconst slot: ITimeSlot = { date, hour, minute };\n\n\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t<TimeSlot\n\t\t\t\t\t\t\t\t\t\t\t\tkey={minute}\n\t\t\t\t\t\t\t\t\t\t\t\tslot={slot}\n\t\t\t\t\t\t\t\t\t\t\t\tonSelectionStart={handleSelectionStart}\n\t\t\t\t\t\t\t\t\t\t\t\tonSelectionMove={handleSelectionMove}\n\t\t\t\t\t\t\t\t\t\t\t\tonSelectionEnd={handleSelectionEnd}\n\t\t\t\t\t\t\t\t\t\t\t\tisSelected={slotSelection?.isSlotSelected(slot) ?? false}\n\t\t\t\t\t\t\t\t\t\t\t\tisSelecting={slotSelection?.isSelecting ?? false}\n\t\t\t\t\t\t\t\t\t\t\t\tdisabled={isDisabled}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"absolute inset-x-0\"\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\ttop: `${slotIndex * slotHeightPercent}%`,\n\t\t\t\t\t\t\t\t\t\t\t\t\theight: `${slotHeightPercent}%`,\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\tariaLabel={`Add event at ${formatHourLabel(hour)}:${String(minute).padStart(2, '0')}`}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\n\t\t\t\t\t{/* Events layer - positioned within the content area */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"absolute top-0 bottom-0 right-0 pointer-events-none\"\n\t\t\t\t\t\tstyle={{ left: HOUR_COLUMN_WIDTH }}\n\t\t\t\t\t>\n\t\t\t\t\t\t{singleDay.map((event) => {\n\t\t\t\t\t\t\tconst position = eventPositions.get(event.id);\n\t\t\t\t\t\t\tif (!position) return null;\n\n\t\t\t\t\t\t\t// Calculate minimum width - ensure events are readable\n\t\t\t\t\t\t\tconst calculatedWidth = `calc(${position.width}% - 2px)`;\n\t\t\t\t\t\t\tconst minWidthStyle = `max(${MIN_EVENT_CARD_WIDTH}px, ${calculatedWidth})`;\n\n\t\t\t\t\t\t\tif (renderEvent) {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tkey={event.id}\n\t\t\t\t\t\t\t\t\t\tclassName=\"absolute pointer-events-auto p-0.5\"\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\ttop: `${position.top}px`,\n\t\t\t\t\t\t\t\t\t\t\tleft: `${position.left}%`,\n\t\t\t\t\t\t\t\t\t\t\twidth: minWidthStyle,\n\t\t\t\t\t\t\t\t\t\t\tminWidth: `${MIN_EVENT_CARD_WIDTH}px`,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{renderEvent({ event: event as CalendarEvent<TData>, position })}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<EventBlock\n\t\t\t\t\t\t\t\t\tkey={event.id}\n\t\t\t\t\t\t\t\t\tevent={event as CalendarEvent<TData>}\n\t\t\t\t\t\t\t\t\tposition={{\n\t\t\t\t\t\t\t\t\t\ttop: position.top,\n\t\t\t\t\t\t\t\t\t\tleft: position.left,\n\t\t\t\t\t\t\t\t\t\twidth: position.width,\n\t\t\t\t\t\t\t\t\t\tminWidth: MIN_EVENT_CARD_WIDTH,\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\thourHeight={HOUR_HEIGHT}\n\t\t\t\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\t\t\t\tonClick={onEventClick}\n\t\t\t\t\t\t\t\t\tdisablePopover={!!onEventClick && !renderPopover}\n\t\t\t\t\t\t\t\t\trenderPopover={renderPopover}\n\t\t\t\t\t\t\t\t\tclassName={cn('pointer-events-auto')}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Current time indicator */}\n\t\t\t\t\t{showCurrentTime && currentTimeTop >= 0 && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tdata-ic-now=\"\"\n\t\t\t\t\t\t\tclassName={cn('absolute left-0 right-0 z-20 flex items-center pointer-events-none')}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\ttop: currentTimeTop,\n\t\t\t\t\t\t\t\tleft: HOUR_COLUMN_WIDTH,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div className=\"h-2.5 w-2.5 -ml-1 rounded-full bg-red-500\" />\n\t\t\t\t\t\t\t<div className=\"flex-1 h-0.5 bg-red-500\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default DayView;\n","/**\n * Month View Component\n *\n * Traditional calendar month grid with event indicators.\n * Features:\n * - 6-week grid with days from adjacent months\n * - Event dots/compact cards\n * - Today highlighting\n * - Click to view day / add event\n * - Drag to select date range\n * - Show-more expansion: morphing overlay reveals all day events\n * - Optional popover for \"+N more\" events (instead of redirecting to day view)\n *\n * Ported from agenda-v2 to maintain exact styling parity.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { useOptionalSlotSelection } from '../../core/context/slot-selection-context';\nimport type {\n\tCalendarEvent,\n\tITimeSlot,\n\tTBadgeVariant,\n\tTOnEventClick,\n\tTOnSlotSelect,\n} from '../../core/types';\nimport { generateMonthGrid, isToday } from '../../core/utils/date-utils';\nimport { getEventsForDay } from '../../core/utils/event-utils';\nimport { cn } from '../../lib/utils';\nimport { EventCard } from '../event/event-card';\nimport { DaySlot } from '../primitives/selectable-slot';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { DayEventsExpansion } from './day-events-expansion';\n\n// ============================================================================\n// CONSTANTS (matches agenda-v2)\n// ============================================================================\n\nconst WEEKDAY_LABELS_MONDAY_START = [\n\t{ full: 'Monday', short: 'Mon', tiny: 'M' },\n\t{ full: 'Tuesday', short: 'Tue', tiny: 'T' },\n\t{ full: 'Wednesday', short: 'Wed', tiny: 'W' },\n\t{ full: 'Thursday', short: 'Thu', tiny: 'T' },\n\t{ full: 'Friday', short: 'Fri', tiny: 'F' },\n\t{ full: 'Saturday', short: 'Sat', tiny: 'S' },\n\t{ full: 'Sunday', short: 'Sun', tiny: 'S' },\n];\nconst WEEKDAY_LABELS_SUNDAY_START = [\n\t{ full: 'Sunday', short: 'Sun', tiny: 'S' },\n\t{ full: 'Monday', short: 'Mon', tiny: 'M' },\n\t{ full: 'Tuesday', short: 'Tue', tiny: 'T' },\n\t{ full: 'Wednesday', short: 'Wed', tiny: 'W' },\n\t{ full: 'Thursday', short: 'Thu', tiny: 'T' },\n\t{ full: 'Friday', short: 'Fri', tiny: 'F' },\n\t{ full: 'Saturday', short: 'Sat', tiny: 'S' },\n];\nconst MAX_EVENTS_SHOWN = 3;\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface MonthViewProps<TData = Record<string, unknown>> {\n\t/** Events to display */\n\tevents: CalendarEvent<TData>[];\n\t/** The date (any day in the month to show) */\n\tdate: Date;\n\t/** First day of week (0 = Sunday, 1 = Monday) */\n\tweekStartsOn?: 0 | 1;\n\t/** Badge variant for events */\n\tbadgeVariant?: TBadgeVariant;\n\t/** Event click handler */\n\tonEventClick?: TOnEventClick<TData>;\n\t/** Slot select handler */\n\tonSlotSelect?: TOnSlotSelect;\n\t/** Day click handler */\n\tonDayClick?: (date: Date) => void;\n\t/** Additional CSS classes */\n\tclassName?: string;\n\t/** Custom event renderer */\n\trenderEvent?: (props: { event: CalendarEvent<TData>; variant: 'compact' }) => React.ReactNode;\n\t/** Custom popover content renderer */\n\trenderPopover?: (props: { event: CalendarEvent<TData>; onClose: () => void }) => React.ReactNode;\n\t/**\n\t * How to handle overflow events when a day has more than 3.\n\t *\n\t * - `'dayView'` — Clicking \"+N more\" redirects to day view (via `onDayClick`)\n\t * - `'popover'` — Opens a small popover listing all day events\n\t * - `'expand'` — **Recommended.** The cell morphs into a smooth expansion\n\t * overlay that reveals all events in a dialog-like panel with transitions.\n\t *\n\t * @default 'expand'\n\t */\n\tshowMoreMode?: 'dayView' | 'popover' | 'expand';\n\t/**\n\t * Show remaining events in a popover instead of redirecting to day view.\n\t * @deprecated Use `showMoreMode=\"popover\"` instead. Will be removed in next major version.\n\t * @default false\n\t */\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function MonthView<TData = Record<string, unknown>>({\n\tevents,\n\tdate,\n\tweekStartsOn = 1,\n\tbadgeVariant = 'colored',\n\tonEventClick,\n\tonSlotSelect: _onSlotSelect,\n\tonDayClick,\n\tclassName,\n\trenderEvent,\n\trenderPopover,\n\tshowMoreMode: _showMoreMode,\n}: MonthViewProps<TData>) {\n\t// Resolve showMoreMode: new prop takes precedence over deprecated boolean\n\tconst showMoreMode = _showMoreMode ?? 'expand';\n\n\t// Track which day's popover is open (by date string key) — for 'popover' mode\n\tconst [openPopoverDay, setOpenPopoverDay] = useState<string | null>(null);\n\n\t// Track expansion overlay state — for 'expand' mode\n\tconst [expandedDay, setExpandedDay] = useState<{\n\t\tdate: Date;\n\t\tevents: CalendarEvent<TData>[];\n\t\trect: DOMRect;\n\t} | null>(null);\n\n\t// Generate month grid cells\n\tconst cells = useMemo(() => generateMonthGrid(date, weekStartsOn), [date, weekStartsOn]);\n\n\t// Events by date for quick lookup\n\tconst eventsByDate = useMemo(() => {\n\t\tconst map = new Map<string, CalendarEvent<TData>[]>();\n\t\tfor (const cell of cells) {\n\t\t\tconst dayKey = cell.date.toDateString();\n\t\t\tconst dayEvents = getEventsForDay(events, cell.date) as CalendarEvent<TData>[];\n\t\t\t// Sort by start time\n\t\t\tdayEvents.sort((a, b) => a.startDate.getTime() - b.startDate.getTime());\n\t\t\tmap.set(dayKey, dayEvents);\n\t\t}\n\t\treturn map;\n\t}, [cells, events]);\n\n\t// Get slot selection context (optional - works without provider)\n\tconst slotSelection = useOptionalSlotSelection();\n\n\t// Create selection handlers for day slots\n\tconst handleSelectionStart = useCallback(\n\t\t(slot: ITimeSlot) => {\n\t\t\tslotSelection?.startSelection(slot);\n\t\t},\n\t\t[slotSelection]\n\t);\n\n\tconst handleSelectionMove = useCallback(\n\t\t(slot: ITimeSlot) => {\n\t\t\tslotSelection?.updateSelection(slot);\n\t\t},\n\t\t[slotSelection]\n\t);\n\n\tconst handleSelectionEnd = useCallback(() => {\n\t\tslotSelection?.endSelection();\n\t}, [slotSelection]);\n\n\t// Handle day click (navigate to day view)\n\tconst handleDayClick = useCallback(\n\t\t(cellDate: Date) => {\n\t\t\tonDayClick?.(cellDate);\n\t\t},\n\t\t[onDayClick]\n\t);\n\n\t// Get weekday labels based on weekStartsOn\n\tconst weekdayLabels =\n\t\tweekStartsOn === 0 ? WEEKDAY_LABELS_SUNDAY_START : WEEKDAY_LABELS_MONDAY_START;\n\n\treturn (\n\t\t<div className={cn('flex flex-col h-full overflow-hidden', className)}>\n\t\t\t{/* Scrollable container - horizontal on mobile, vertical overflow when needed */}\n\t\t\t<div className=\"flex flex-col flex-1 overflow-auto\">\n\t\t\t\t<div className=\"flex flex-col flex-1 min-w-[560px] sm:min-w-0\">\n\t\t\t\t\t{/* Weekday headers - Google Calendar style */}\n\t\t\t\t\t<div className={cn('grid grid-cols-7 border-b !sticky !top-0 bg-background z-10')}>\n\t\t\t\t\t\t{weekdayLabels.map((label, index) => (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={label.full}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'py-2 sm:py-2.5 text-center text-[11px] uppercase font-medium tracking-wide text-muted-foreground',\n\t\t\t\t\t\t\t\t\tindex >= 5 && 'text-muted-foreground/70', // Weekend\n\t\t\t\t\t\t\t\t\tundefined\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{/* Show short on mobile, full on desktop */}\n\t\t\t\t\t\t\t\t<span className=\"sm:hidden\">{label.short}</span>\n\t\t\t\t\t\t\t\t<span className=\"hidden sm:inline\">{label.short}</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Calendar grid - each row sizes independently based on content */}\n\t\t\t\t\t<div className={cn('grid grid-cols-7 auto-rows-min')}>\n\t\t\t\t\t\t{cells.map((cell) => {\n\t\t\t\t\t\t\tconst dayKey = cell.date.toDateString();\n\t\t\t\t\t\t\tconst dayEvents = eventsByDate.get(dayKey) || [];\n\t\t\t\t\t\t\tconst today = isToday(cell.date);\n\t\t\t\t\t\t\tconst isWeekend = cell.date.getDay() === 0 || cell.date.getDay() === 6;\n\t\t\t\t\t\t\tconst hasMoreEvents = dayEvents.length > MAX_EVENTS_SHOWN;\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<DaySlot\n\t\t\t\t\t\t\t\t\tkey={dayKey}\n\t\t\t\t\t\t\t\t\tdate={cell.date}\n\t\t\t\t\t\t\t\t\tdataAttributes={{\n\t\t\t\t\t\t\t\t\t\t'data-day-key': dayKey,\n\t\t\t\t\t\t\t\t\t\t// The landmark a month view has instead of a time line.\n\t\t\t\t\t\t\t\t\t\t...(today && { 'data-ic-today': '' }),\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tonSelectionStart={handleSelectionStart}\n\t\t\t\t\t\t\t\t\tonSelectionMove={handleSelectionMove}\n\t\t\t\t\t\t\t\t\tonSelectionEnd={handleSelectionEnd}\n\t\t\t\t\t\t\t\t\tisSelected={slotSelection?.isSlotSelected({ date: cell.date }) ?? false}\n\t\t\t\t\t\t\t\t\tisSelecting={slotSelection?.isSelecting ?? false}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t'relative flex flex-col border-r border-b text-left min-h-[80px] sm:min-h-[100px] overflow-hidden',\n\t\t\t\t\t\t\t\t\t\t'[&:nth-child(7n)]:border-r-0',\n\t\t\t\t\t\t\t\t\t\t!cell.isCurrentMonth && 'bg-muted/20',\n\t\t\t\t\t\t\t\t\t\tisWeekend && cell.isCurrentMonth && 'bg-muted/10',\n\t\t\t\t\t\t\t\t\t\ttoday && !cell.isCurrentMonth && isWeekend && undefined\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tariaLabel={`${cell.date.toLocaleDateString()} - ${dayEvents.length} events. Click to create event, double-click to view day.`}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{/* Day number header - Google Calendar style */}\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t'flex items-center justify-center p-1',\n\t\t\t\t\t\t\t\t\t\t\t!cell.isCurrentMonth && 'text-muted-foreground/40'\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\thandleDayClick(cell.date);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t'flex items-center justify-center rounded-full transition-colors',\n\t\t\t\t\t\t\t\t\t\t\t\t'size-7 text-sm font-normal',\n\t\t\t\t\t\t\t\t\t\t\t\ttoday ? 'bg-primary text-primary-foreground' : 'hover:bg-muted'\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{cell.date.getDate()}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t{/* Events list */}\n\t\t\t\t\t\t\t\t\t<div className={cn('flex-1 overflow-hidden px-2 pt-1 pb-1 space-y-1')}>\n\t\t\t\t\t\t\t\t\t\t{dayEvents.slice(0, MAX_EVENTS_SHOWN).map((event) => (\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tkey={event.id}\n\t\t\t\t\t\t\t\t\t\t\t\tonPointerDown={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t// Stop propagation to prevent slot selection when clicking event\n\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{renderEvent ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\trenderEvent({ event, variant: 'compact' })\n\t\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<EventCard\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tevent={event}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"compact\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={onEventClick}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisablePopover={!!onEventClick && !renderPopover}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trenderPopover={renderPopover}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tshowTime={false}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tenableDrag\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t))}\n\n\t\t\t\t\t\t\t\t\t\t{/* More events indicator — three modes: expand, popover, dayView */}\n\t\t\t\t\t\t\t\t\t\t{hasMoreEvents && showMoreMode === 'expand' && (\n\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\tonPointerDown={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t// Capture the cell rect for the morph animation origin\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst cellEl = document.querySelector(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t`[data-day-key=\"${dayKey}\"]`\n\t\t\t\t\t\t\t\t\t\t\t\t\t) as HTMLElement | null;\n\t\t\t\t\t\t\t\t\t\t\t\t\tsetExpandedDay({\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdate: cell.date,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tevents: dayEvents,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trect:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcellEl?.getBoundingClientRect() ??\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnew DOMRect(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twindow.innerWidth / 2 - 180,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twindow.innerHeight / 2 - 240,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'w-full text-left text-xs text-muted-foreground hover:text-foreground hover:underline px-1.5 cursor-pointer'\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t+{dayEvents.length - MAX_EVENTS_SHOWN} more\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t\t{hasMoreEvents && showMoreMode === 'popover' && (\n\t\t\t\t\t\t\t\t\t\t\t<Popover\n\t\t\t\t\t\t\t\t\t\t\t\topen={openPopoverDay === dayKey}\n\t\t\t\t\t\t\t\t\t\t\t\tonOpenChange={(open) => setOpenPopoverDay(open ? dayKey : null)}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<PopoverTrigger asChild>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonPointerDown={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetOpenPopoverDay(dayKey);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'w-full text-left text-xs text-muted-foreground hover:text-foreground hover:underline px-1.5 cursor-pointer'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t+{dayEvents.length - MAX_EVENTS_SHOWN} more\n\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t</PopoverTrigger>\n\t\t\t\t\t\t\t\t\t\t\t\t<PopoverContent\n\t\t\t\t\t\t\t\t\t\t\t\t\talign=\"start\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tside=\"right\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tsideOffset={8}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-72 max-h-80 overflow-y-auto p-2\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tonPointerDown={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{/* Day header */}\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-between mb-2 pb-2 border-b\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-sm font-medium\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{cell.date.toLocaleDateString(undefined, {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tweekday: 'short',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tmonth: 'short',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tday: 'numeric',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{dayEvents.length} events\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{/* All events for the day */}\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"space-y-1.5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{dayEvents.map((event) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div key={event.id}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{renderEvent ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trenderEvent({ event, variant: 'compact' })\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<EventCard\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tevent={event}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"compact\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetOpenPopoverDay(null);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonEventClick?.(e);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisablePopover={!!onEventClick && !renderPopover}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trenderPopover={renderPopover}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tshowTime\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t</PopoverContent>\n\t\t\t\t\t\t\t\t\t\t\t</Popover>\n\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t\t{hasMoreEvents && showMoreMode === 'dayView' && (\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tonPointerDown={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleDayClick(cell.date);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'w-full text-left text-xs text-muted-foreground hover:text-foreground hover:underline px-1.5 cursor-pointer'\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t+{dayEvents.length - MAX_EVENTS_SHOWN} more\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</DaySlot>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Day events expansion overlay — rendered outside grid to avoid clipping */}\n\t\t\t<DayEventsExpansion<TData>\n\t\t\t\tisOpen={expandedDay !== null}\n\t\t\t\tonClose={() => setExpandedDay(null)}\n\t\t\t\tdate={expandedDay?.date ?? new Date()}\n\t\t\t\tevents={expandedDay?.events ?? []}\n\t\t\t\tanchorRect={expandedDay?.rect ?? null}\n\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\tonEventClick={onEventClick}\n\t\t\t\trenderEvent={renderEvent}\n\t\t\t\trenderPopover={renderPopover}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\nexport default MonthView;\n","/**\n * Week All-Day Row\n *\n * Renders all-day and multi-day events in a column-aligned grid that\n * matches the week view's day columns. Unlike the flat `MultiDayBanner`,\n * each event occupies exactly the columns corresponding to the days it\n * spans within the visible week.\n *\n * Each event pill supports Radix UI `Popover` (or `Tooltip` when popover\n * is disabled), matching the interaction model of `EventBlock` and\n * `MultiDayEventBar`. When a consumer provides `renderPopover`, clicking\n * a pill opens the custom popover. Otherwise a built-in default is shown.\n *\n * Layout:\n * [gutter] [Mon] [Tue] [Wed] [Thu] [Fri] [Sat] [Sun]\n * [ ] [===== Event A (Mon–Wed) =====] [ ] [ ]\n * [ ] [ ] [======= Event B (Tue–Fri) =======] [ ]\n *\n * Uses CSS Grid for precise column spanning and a row-packing algorithm\n * to stack overlapping events vertically.\n *\n * @example\n * ```tsx\n * <WeekAllDayRow\n * events={weekMultiDayEvents}\n * weekDays={weekDays}\n * hourColumnWidth={56}\n * minDayColumnWidth={120}\n * dayColumnWidths={dayColumnWidths}\n * onEventClick={handleClick}\n * renderPopover={({ event, onClose }) => <MyPopover event={event} onClose={onClose} />}\n * />\n * ```\n */\n\nimport { type ReactNode, useCallback, useMemo, useState } from 'react';\nimport { CANCELED_CHIP } from '../../core/constants';\nimport type { CalendarEvent, TOnEventClick } from '../../core/types';\nimport { detectAllDayEvent, isSameDay, startOfDay } from '../../core/utils/date-utils';\nimport { formatEventTimeDisplay } from '../../core/utils/event-utils';\nimport { cn } from '../../lib/utils';\nimport { getEventColorClasses } from '../event/event-card';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\n/** Height of each packed event row in pixels */\nconst EVENT_ROW_HEIGHT = 26;\n/** Vertical gap between packed event rows */\nconst EVENT_ROW_GAP = 2;\n/** Maximum visible rows before showing \"+N more\" */\nconst MAX_VISIBLE_ROWS = 4;\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface WeekAllDayRowProps<TData = Record<string, unknown>> {\n\t/** All-day and multi-day events to display */\n\tevents: CalendarEvent<TData>[];\n\t/** Array of 7 Date objects representing the visible week days (in order) */\n\tweekDays: Date[];\n\t/** Width of the hour/gutter column in pixels (must match week grid) */\n\thourColumnWidth: number;\n\t/** Minimum width of each day column in pixels */\n\tminDayColumnWidth: number;\n\t/** Dynamic widths per day column (length 7, matching weekDays) */\n\tdayColumnWidths: number[];\n\t/** Event click handler (fires only when popover is disabled) */\n\tonEventClick?: TOnEventClick<TData> | undefined;\n\t/**\n\t * When `true`, clicking opens no built-in popover — instead `onEventClick`\n\t * fires directly. Use when the consumer handles navigation themselves.\n\t * @default false\n\t */\n\tdisablePopover?: boolean;\n\t/**\n\t * Custom popover content rendered inside the built-in Radix popover.\n\t * When omitted a lightweight default popover is shown.\n\t *\n\t * @example\n\t * renderPopover={({ event, onClose }) => (\n\t * <MyCustomPopover event={event} onClose={onClose} />\n\t * )}\n\t */\n\trenderPopover?:\n\t\t| ((props: { event: CalendarEvent<TData>; onClose: () => void }) => ReactNode)\n\t\t| undefined;\n\t/** Additional CSS classes for the container */\n\tclassName?: string;\n}\n\n// ============================================================================\n// INTERNAL TYPES\n// ============================================================================\n\ninterface PackedEvent<TData> {\n\tevent: CalendarEvent<TData>;\n\t/** 0-based start column index within the week */\n\tstartCol: number;\n\t/** 0-based end column index within the week (inclusive) */\n\tendCol: number;\n\t/** 0-based packed row index */\n\trow: number;\n\t/** Whether the event continues before the visible week */\n\tcontinuesBefore: boolean;\n\t/** Whether the event continues after the visible week */\n\tcontinuesAfter: boolean;\n\t/** Whether this is a single-day all-day event */\n\tisSingleDayAllDay: boolean;\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\n/**\n * Find the column index (0-6) for a given date within the weekDays array.\n * Returns -1 if the date is before the week, 7 if after.\n */\nfunction findDayColumn(date: Date, weekDays: Date[]): number {\n\tconst dayStart = startOfDay(date);\n\n\tfor (let i = 0; i < weekDays.length; i++) {\n\t\tconst weekDay = weekDays[i];\n\t\tif (weekDay && isSameDay(dayStart, weekDay)) return i;\n\t}\n\n\t// Date is outside the week — check if before or after\n\tconst firstDay = weekDays[0];\n\tif (firstDay && dayStart < startOfDay(firstDay)) return -1;\n\treturn 7;\n}\n\n/**\n * Row-packing algorithm: assigns the lowest available row to each event\n * so that no two events overlap in the same row and column range.\n *\n * Events are sorted by span width (widest first) then by start column\n * for a visually clean layout.\n */\nfunction packEventsIntoRows<TData>(\n\tevents: Array<{\n\t\tevent: CalendarEvent<TData>;\n\t\tstartCol: number;\n\t\tendCol: number;\n\t\tcontinuesBefore: boolean;\n\t\tcontinuesAfter: boolean;\n\t\tisSingleDayAllDay: boolean;\n\t}>\n): PackedEvent<TData>[] {\n\t// Sort: wider spans first, then by start column for visual consistency\n\tconst sorted = [...events].sort((a, b) => {\n\t\tconst spanA = a.endCol - a.startCol;\n\t\tconst spanB = b.endCol - b.startCol;\n\t\tif (spanB !== spanA) return spanB - spanA; // wider first\n\t\treturn a.startCol - b.startCol; // then by start col\n\t});\n\n\t// rows[r][c] = true if column c is occupied in row r\n\tconst rows: boolean[][] = [];\n\n\treturn sorted.map((entry) => {\n\t\t// Find the first row where all columns startCol..endCol are free\n\t\tlet assignedRow = -1;\n\n\t\tfor (let r = 0; r < rows.length; r++) {\n\t\t\tconst row = rows[r];\n\t\t\tif (!row) continue;\n\t\t\tlet free = true;\n\t\t\tfor (let c = entry.startCol; c <= entry.endCol; c++) {\n\t\t\t\tif (row[c]) {\n\t\t\t\t\tfree = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (free) {\n\t\t\t\tassignedRow = r;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// No free row found — create a new one\n\t\tif (assignedRow === -1) {\n\t\t\tassignedRow = rows.length;\n\t\t\trows.push(new Array<boolean>(7).fill(false));\n\t\t}\n\n\t\t// Occupy columns in the assigned row\n\t\tconst assignedRowArr = rows[assignedRow];\n\t\tif (assignedRowArr) {\n\t\t\tfor (let c = entry.startCol; c <= entry.endCol; c++) {\n\t\t\t\tassignedRowArr[c] = true;\n\t\t\t}\n\t\t}\n\n\t\treturn { ...entry, row: assignedRow };\n\t});\n}\n\n// ============================================================================\n// ALL-DAY EVENT PILL (with Popover / Tooltip support)\n// ============================================================================\n\ninterface AllDayEventPillProps<TData> {\n\tpe: PackedEvent<TData>;\n\tonEventClick: TOnEventClick<TData> | undefined;\n\tdisablePopover: boolean;\n\trenderPopover:\n\t\t| ((props: { event: CalendarEvent<TData>; onClose: () => void }) => ReactNode)\n\t\t| undefined;\n}\n\n/**\n * Single event pill inside the all-day row.\n *\n * - With popover enabled: wraps in Radix `<Popover>` (custom or default content).\n * - With popover disabled + onClick: fires `onEventClick`, shows a `<Tooltip>`.\n * - Matches the same interaction model as `EventBlock` and `MultiDayEventBar`.\n */\nfunction AllDayEventPill<TData>({\n\tpe,\n\tonEventClick,\n\tdisablePopover,\n\trenderPopover,\n}: AllDayEventPillProps<TData>) {\n\tconst [popoverOpen, setPopoverOpen] = useState(false);\n\tconst colors = getEventColorClasses(pe.event.color);\n\n\tconst handleClick = useCallback(() => {\n\t\tif (disablePopover && onEventClick) {\n\t\t\tonEventClick(pe.event);\n\t\t} else if (!disablePopover) {\n\t\t\tsetPopoverOpen(true);\n\t\t}\n\t}, [disablePopover, onEventClick, pe.event]);\n\n\tconst handleClose = useCallback(() => {\n\t\tsetPopoverOpen(false);\n\t}, []);\n\n\t// Shared button content\n\tconst pillButton = (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={handleClick}\n\t\t\tclassName={cn(\n\t\t\t\t'inline-flex items-center gap-1 rounded text-[10px] font-medium transition-opacity hover:opacity-80 mx-0.5 overflow-hidden w-full',\n\t\t\t\t'sm:text-xs',\n\t\t\t\tpe.event.isCanceled ? CANCELED_CHIP : [colors.bg, colors.text],\n\t\t\t\tpe.continuesBefore && 'rounded-l-none -ml-0.5 pl-1',\n\t\t\t\tpe.continuesAfter && 'rounded-r-none -mr-0.5 pr-1'\n\t\t\t)}\n\t\t\tstyle={{\n\t\t\t\theight: EVENT_ROW_HEIGHT,\n\t\t\t\tlineHeight: `${EVENT_ROW_HEIGHT}px`,\n\t\t\t\tpaddingLeft: pe.continuesBefore ? 4 : 6,\n\t\t\t\tpaddingRight: pe.continuesAfter ? 4 : 6,\n\t\t\t}}\n\t\t>\n\t\t\t{pe.continuesBefore && <span className=\"text-[9px] opacity-60 flex-shrink-0\">◂</span>}\n\t\t\t<span className=\"truncate\">{pe.event.title}</span>\n\t\t\t{pe.isSingleDayAllDay && (\n\t\t\t\t<span className=\"text-[9px] opacity-70 flex-shrink-0 hidden sm:inline\">All day</span>\n\t\t\t)}\n\t\t\t{pe.continuesAfter && <span className=\"text-[9px] opacity-60 flex-shrink-0\">▸</span>}\n\t\t</button>\n\t);\n\n\t// Tooltip content (shown on hover when popover is disabled)\n\tconst tooltipContent = (\n\t\t<TooltipContent>\n\t\t\t<div className=\"flex flex-col gap-0.5\">\n\t\t\t\t<div className=\"font-medium\">{pe.event.title}</div>\n\t\t\t\t<div className=\"text-xs text-muted-foreground tabular-nums\">\n\t\t\t\t\t{formatEventTimeDisplay(pe.event)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</TooltipContent>\n\t);\n\n\t// Grid placement style — applied to the wrapper div, not the button\n\tconst gridStyle: React.CSSProperties = {\n\t\tgridColumn: `${pe.startCol + 2} / ${pe.endCol + 3}`,\n\t\tgridRow: pe.row + 1,\n\t};\n\n\t// Popover disabled → only tooltip + direct onClick\n\tif (disablePopover) {\n\t\treturn (\n\t\t\t<div style={gridStyle}>\n\t\t\t\t<Tooltip>\n\t\t\t\t\t<TooltipTrigger asChild>{pillButton}</TooltipTrigger>\n\t\t\t\t\t{tooltipContent}\n\t\t\t\t</Tooltip>\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Popover enabled → Radix Popover with consumer or default content\n\treturn (\n\t\t<div style={gridStyle}>\n\t\t\t<Popover open={popoverOpen} onOpenChange={setPopoverOpen}>\n\t\t\t\t<PopoverTrigger asChild>{pillButton}</PopoverTrigger>\n\t\t\t\t<PopoverContent className=\"w-80\">\n\t\t\t\t\t{renderPopover ? (\n\t\t\t\t\t\trenderPopover({ event: pe.event, onClose: handleClose })\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<DefaultAllDayPopoverContent event={pe.event} onClose={handleClose} />\n\t\t\t\t\t)}\n\t\t\t\t</PopoverContent>\n\t\t\t</Popover>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// DEFAULT POPOVER CONTENT (lightweight fallback)\n// ============================================================================\n\nfunction DefaultAllDayPopoverContent<TData>({\n\tevent,\n\tonClose,\n}: {\n\tevent: CalendarEvent<TData>;\n\tonClose: () => void;\n}) {\n\tconst colors = getEventColorClasses(event.color);\n\tconst isCanceled = event.isCanceled ?? false;\n\n\treturn (\n\t\t<div className=\"space-y-3\">\n\t\t\t<div className=\"flex items-start gap-3\">\n\t\t\t\t<div className={cn('size-4 rounded shrink-0 mt-0.5', colors.dot)} />\n\t\t\t\t<div className=\"flex-1 min-w-0\">\n\t\t\t\t\t<h3 className={cn('font-semibold text-lg', isCanceled && 'line-through opacity-50')}>\n\t\t\t\t\t\t{event.title}\n\t\t\t\t\t</h3>\n\t\t\t\t\t<div className=\"flex items-center gap-1 text-sm text-muted-foreground mt-1 tabular-nums\">\n\t\t\t\t\t\t{formatEventTimeDisplay(event)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{event.description && <p className=\"text-sm text-muted-foreground\">{event.description}</p>}\n\n\t\t\t<div className=\"flex flex-wrap gap-1.5\">\n\t\t\t\t{event.isAllDay && (\n\t\t\t\t\t<span className=\"text-xs bg-muted px-2 py-0.5 rounded-full font-medium\">All day</span>\n\t\t\t\t)}\n\t\t\t\t{isCanceled && (\n\t\t\t\t\t<span className=\"text-xs bg-red-100 dark:bg-red-950/30 text-red-700 dark:text-red-300 px-2 py-0.5 rounded-full font-medium\">\n\t\t\t\t\t\tCanceled\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t<div className=\"flex justify-end pt-2 border-t\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={onClose}\n\t\t\t\t\tclassName=\"text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md hover:bg-muted transition-colors\"\n\t\t\t\t>\n\t\t\t\t\tClose\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// MAIN COMPONENT\n// ============================================================================\n\nexport function WeekAllDayRow<TData = Record<string, unknown>>({\n\tevents,\n\tweekDays,\n\thourColumnWidth,\n\tminDayColumnWidth,\n\tdayColumnWidths,\n\tonEventClick,\n\tdisablePopover = false,\n\trenderPopover,\n\tclassName,\n}: WeekAllDayRowProps<TData>) {\n\tconst packedEvents = useMemo(() => {\n\t\tif (events.length === 0) return [];\n\n\t\t// Map each event to its column range within the visible week\n\t\tconst mapped = events\n\t\t\t.map((event) => {\n\t\t\t\tconst rawStart = findDayColumn(event.startDate, weekDays);\n\t\t\t\tconst rawEnd = findDayColumn(event.endDate, weekDays);\n\n\t\t\t\t// Clamp to visible week range [0, 6]\n\t\t\t\tconst startCol = Math.max(0, rawStart);\n\t\t\t\tconst endCol = Math.min(6, rawEnd);\n\n\t\t\t\t// Skip events entirely outside the visible week\n\t\t\t\tif (startCol > 6 || endCol < 0) return null;\n\n\t\t\t\tconst continuesBefore = rawStart < 0;\n\t\t\t\tconst continuesAfter = rawEnd > 6;\n\t\t\t\tconst isAllDay = detectAllDayEvent(event);\n\t\t\t\tconst isSingleDayAllDay = isAllDay && isSameDay(event.startDate, event.endDate);\n\n\t\t\t\treturn {\n\t\t\t\t\tevent,\n\t\t\t\t\tstartCol,\n\t\t\t\t\tendCol,\n\t\t\t\t\tcontinuesBefore,\n\t\t\t\t\tcontinuesAfter,\n\t\t\t\t\tisSingleDayAllDay,\n\t\t\t\t};\n\t\t\t})\n\t\t\t.filter(Boolean) as Array<{\n\t\t\tevent: CalendarEvent<TData>;\n\t\t\tstartCol: number;\n\t\t\tendCol: number;\n\t\t\tcontinuesBefore: boolean;\n\t\t\tcontinuesAfter: boolean;\n\t\t\tisSingleDayAllDay: boolean;\n\t\t}>;\n\n\t\treturn packEventsIntoRows(mapped);\n\t}, [events, weekDays]);\n\n\tif (packedEvents.length === 0) return null;\n\n\t// Compute number of visible rows and whether we need a \"+N more\" overflow\n\tconst totalRows = Math.max(...packedEvents.map((e) => e.row)) + 1;\n\tconst visibleRows = Math.min(totalRows, MAX_VISIBLE_ROWS);\n\tconst hasOverflow = totalRows > MAX_VISIBLE_ROWS;\n\tconst hiddenCount = hasOverflow\n\t\t? packedEvents.filter((e) => e.row >= MAX_VISIBLE_ROWS).length\n\t\t: 0;\n\n\t// Build CSS grid column template to match the week grid exactly\n\tconst gridTemplateColumns = [\n\t\t`${hourColumnWidth}px`,\n\t\t...dayColumnWidths.map((w) => {\n\t\t\tconst needsExpansion = w > minDayColumnWidth;\n\t\t\treturn needsExpansion ? `${w}px` : `minmax(${minDayColumnWidth}px, 1fr)`;\n\t\t}),\n\t].join(' ');\n\n\t// Container height: rows + gaps + padding\n\tconst containerHeight = visibleRows * EVENT_ROW_HEIGHT + (visibleRows - 1) * EVENT_ROW_GAP + 8; // 4px top + 4px bottom padding\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn('ic-all-day-row border-b bg-muted/20 relative', className)}\n\t\t\tstyle={{\n\t\t\t\tdisplay: 'grid',\n\t\t\t\tgridTemplateColumns,\n\t\t\t\tgridTemplateRows: `repeat(${visibleRows}, ${EVENT_ROW_HEIGHT}px)`,\n\t\t\t\tgap: `${EVENT_ROW_GAP}px 0`,\n\t\t\t\tpaddingTop: 4,\n\t\t\t\tpaddingBottom: 4,\n\t\t\t\tminHeight: containerHeight,\n\t\t\t}}\n\t\t>\n\t\t\t{/* Gutter label */}\n\t\t\t<div\n\t\t\t\tclassName=\"flex items-start justify-center pt-1 text-[10px] font-medium text-muted-foreground\"\n\t\t\t\tstyle={{\n\t\t\t\t\tgridColumn: 1,\n\t\t\t\t\tgridRow: `1 / span ${visibleRows}`,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<span className=\"hidden sm:inline\">All day</span>\n\t\t\t</div>\n\n\t\t\t{/* Column separator lines (visual alignment with week header) */}\n\t\t\t{weekDays.map((day, i) => (\n\t\t\t\t<div\n\t\t\t\t\tkey={day.toDateString()}\n\t\t\t\t\tclassName=\"pointer-events-none border-r last:border-r-0\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tgridColumn: i + 2,\n\t\t\t\t\t\tgridRow: `1 / span ${visibleRows}`,\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t))}\n\n\t\t\t{/* Packed events */}\n\t\t\t{packedEvents\n\t\t\t\t.filter((pe) => pe.row < MAX_VISIBLE_ROWS)\n\t\t\t\t.map((pe) => (\n\t\t\t\t\t<AllDayEventPill\n\t\t\t\t\t\tkey={pe.event.id}\n\t\t\t\t\t\tpe={pe}\n\t\t\t\t\t\tonEventClick={onEventClick}\n\t\t\t\t\t\tdisablePopover={disablePopover}\n\t\t\t\t\t\trenderPopover={renderPopover}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\n\t\t\t{/* Overflow indicator */}\n\t\t\t{hasOverflow && (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"text-[10px] text-muted-foreground font-medium px-2 flex items-center\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tgridColumn: `2 / ${weekDays.length + 2}`,\n\t\t\t\t\t\tgridRow: visibleRows,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t+{hiddenCount} more\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nexport default WeekAllDayRow;\n","/**\n * A panel anchored under its trigger.\n *\n * Portalled, because inside a card it would be clipped by the scrolling body —\n * and because a dropdown rendered in the flow pushes everything below it down,\n * which reads as the form jumping while you type.\n *\n * Tagged `data-ic-layer` so the card knows a click in here is a click on\n * itself, not the outside click that dismisses it.\n */\n\nimport { type ReactNode, useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { IC_Z_LAYER } from '../../core/z-layers';\nimport { cn } from '../../lib/utils';\n\nexport interface FieldLayerProps {\n\t/** What the panel hangs from. */\n\tanchorRef: React.RefObject<HTMLElement | null>;\n\tonClose: () => void;\n\tchildren: ReactNode;\n\t/** Take the trigger's width — right for a list of completions. */\n\tmatchWidth?: boolean | undefined;\n\tclassName?: string | undefined;\n}\n\n/** Whatever transient menu is open right now, by its close callback. */\nlet openMenuClose: (() => void) | null = null;\n\n/**\n * One transient menu at a time, across components that cannot see each other:\n * a pill's list, the date calendar, the recurrence dropdown. Claiming the slot\n * closes whoever held it; the returned release forgets the claim on unmount.\n *\n * Module-level on purpose — outside-click listeners alone cannot give this\n * guarantee, because a menu that opens in the same gesture attaches its\n * dismiss listener a tick later.\n */\nexport function claimMenuSlot(close: () => void): () => void {\n\tif (openMenuClose && openMenuClose !== close) openMenuClose();\n\topenMenuClose = close;\n\treturn () => {\n\t\tif (openMenuClose === close) openMenuClose = null;\n\t};\n}\n\nexport function FieldLayer({\n\tanchorRef,\n\tonClose,\n\tchildren,\n\tmatchWidth,\n\tclassName,\n}: FieldLayerProps) {\n\tconst ref = useRef<HTMLDivElement>(null);\n\tconst [pos, setPos] = useState<{ left: number; top: number } | null>(null);\n\n\t// Mounting is opening: take the one menu slot, closing whichever other\n\t// menu holds it. Through a ref so the claim survives `onClose` changing\n\t// identity on every parent render.\n\tconst closeRef = useRef(onClose);\n\tcloseRef.current = onClose;\n\tuseEffect(() => claimMenuSlot(() => closeRef.current()), []);\n\n\tuseLayoutEffect(() => {\n\t\tconst anchor = anchorRef.current;\n\t\tconst panel = ref.current;\n\t\tif (!anchor || !panel) return;\n\n\t\tconst rect = anchor.getBoundingClientRect();\n\t\tconst height = panel.offsetHeight;\n\t\tconst width = matchWidth ? rect.width : panel.offsetWidth;\n\n\t\t// Below the pill, unless that would run off the bottom.\n\t\tconst below = rect.bottom + 4;\n\t\tconst top =\n\t\t\tbelow + height > window.innerHeight - 8 ? Math.max(8, rect.top - height - 4) : below;\n\n\t\tsetPos({\n\t\t\tleft: Math.min(Math.max(8, rect.left), window.innerWidth - width - 8),\n\t\t\ttop,\n\t\t});\n\t}, [anchorRef, matchWidth]);\n\n\tuseEffect(() => {\n\t\tconst onKey = (e: KeyboardEvent) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\t// The card also closes on Escape; this layer is the inner one.\n\t\t\t\te.stopPropagation();\n\t\t\t\tonClose();\n\t\t\t}\n\t\t};\n\t\tconst onDown = (e: PointerEvent) => {\n\t\t\tconst target = e.target as Node;\n\t\t\tif (ref.current?.contains(target) || anchorRef.current?.contains(target)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tonClose();\n\t\t};\n\t\tdocument.addEventListener('keydown', onKey, true);\n\t\t// Capture, so a control that stops pointerdown from bubbling still\n\t\t// dismisses the layer; deferred, so the press that opened it does not.\n\t\tconst id = window.setTimeout(() => document.addEventListener('pointerdown', onDown, true), 0);\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('keydown', onKey, true);\n\t\t\tdocument.removeEventListener('pointerdown', onDown, true);\n\t\t\twindow.clearTimeout(id);\n\t\t};\n\t}, [onClose, anchorRef]);\n\n\tif (typeof document === 'undefined') return null;\n\n\treturn createPortal(\n\t\t<div\n\t\t\tref={ref}\n\t\t\tdata-ic-layer=\"\"\n\t\t\tclassName={cn(\n\t\t\t\t'fixed rounded-lg border bg-popover p-2 text-popover-foreground shadow-lg',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tstyle={{\n\t\t\t\tleft: pos?.left ?? -9999,\n\t\t\t\ttop: pos?.top ?? -9999,\n\t\t\t\tzIndex: IC_Z_LAYER,\n\t\t\t\tvisibility: pos ? 'visible' : 'hidden',\n\t\t\t\t...(matchWidth && { width: anchorRef.current?.offsetWidth }),\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</div>,\n\t\tdocument.body\n\t);\n}\n","/**\n * Recurrence, the way Google asks for it: a dropdown of presets read off the\n * event's own start date, and a Custom dialog for everything else.\n *\n * The value is a plain rule — frequency, interval, weekdays, an end — not the\n * column names of anybody's database. Consumers map it on the way out, which is\n * what lets one calendar sit in front of an RRULE store and a bespoke one.\n *\n * `supports` exists because backends differ in what they can *keep*. Offering\n * \"monthly on the second Wednesday\" to a store that only records \"monthly\"\n * produces an event that silently repeats on the wrong days.\n */\n\nimport { ChevronDown } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { IC_Z_LAYER, IC_Z_MODAL } from '../../core/z-layers';\nimport { cn } from '../../lib/utils';\nimport { claimMenuSlot } from './field-layer';\n\nexport type TRecurrenceFreq = 'daily' | 'weekly' | 'monthly' | 'yearly';\nexport type TWeekday = 'MO' | 'TU' | 'WE' | 'TH' | 'FR' | 'SA' | 'SU';\n\nconst WEEKDAY_BY_INDEX: TWeekday[] = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];\n\nexport interface IRecurrence {\n\tfreq: TRecurrenceFreq;\n\t/** Every N days/weeks/months/years. */\n\tinterval: number;\n\t/** Weekly only. */\n\tbyWeekday?: TWeekday[];\n\t/**\n\t * Monthly only: the same date each month, or the same weekday-of-month\n\t * (\"the second Wednesday\").\n\t */\n\tmonthly?: 'date' | 'weekday';\n\t/** ISO `yyyy-mm-dd`. Mutually exclusive with `count`. */\n\tuntil?: string | null;\n\t/** Number of occurrences. Mutually exclusive with `until`. */\n\tcount?: number | null;\n}\n\nexport interface IRecurrenceSupport {\n\tfreqs?: TRecurrenceFreq[];\n\t/** \"Monthly on the second Wednesday\". @default true */\n\tmonthlyByWeekday?: boolean;\n\t/** Ending after N occurrences. @default true */\n\tcount?: boolean;\n\t/** Ending on a date. @default true */\n\tuntil?: boolean;\n\t/**\n\t * Every rule must end. Google's default is \"Never\", which only works where a\n\t * series is a rule the server evaluates; a store that materialises each\n\t * occurrence as a row cannot hold an infinite one, and will reject it.\n\t *\n\t * With this on, \"Never\" is not offered and presets carry `defaultUntil`.\n\t * @default false\n\t */\n\trequireEnd?: boolean;\n\t/**\n\t * How far a preset runs when `requireEnd` is set. @default one year out\n\t */\n\tdefaultUntil?: (start: Date) => string;\n}\n\nexport interface IRecurrenceLabels {\n\tdoesNotRepeat: string;\n\tdaily: string;\n\t/** \"Weekly on Wednesday\" */\n\tweeklyOn: (weekday: string) => string;\n\t/** \"Monthly on the second Wednesday\" */\n\tmonthlyOnWeekday: (ordinal: number, weekday: string) => string;\n\t/** \"Monthly on day 12\" */\n\tmonthlyOnDate: (day: number) => string;\n\t/** \"Annually on 12 August\" */\n\tannuallyOn: (date: string) => string;\n\teveryWeekday: string;\n\tcustom: string;\n\t/** The pill's text once a custom rule is set. */\n\tsummary: (rule: IRecurrence) => string;\n\n\t// Custom dialog\n\tcustomTitle: string;\n\trepeatEvery: string;\n\trepeatOn: string;\n\tends: string;\n\tnever: string;\n\tendsOn: string;\n\tendsAfter: string;\n\toccurrences: string;\n\tcancel: string;\n\tdone: string;\n\tunit: Record<TRecurrenceFreq, string>;\n}\n\nconst ORDINALS = ['first', 'second', 'third', 'fourth', 'last'];\n\nconst DEFAULT_LABELS: IRecurrenceLabels = {\n\tdoesNotRepeat: 'Does not repeat',\n\tdaily: 'Daily',\n\tweeklyOn: (weekday) => `Weekly on ${weekday}`,\n\tmonthlyOnWeekday: (ordinal, weekday) =>\n\t\t`Monthly on the ${ORDINALS[ordinal - 1] ?? `${ordinal}th`} ${weekday}`,\n\tmonthlyOnDate: (day) => `Monthly on day ${day}`,\n\tannuallyOn: (date) => `Annually on ${date}`,\n\teveryWeekday: 'Every weekday (Monday to Friday)',\n\tcustom: 'Custom…',\n\tsummary: (rule) =>\n\t\t`Every ${rule.interval > 1 ? `${rule.interval} ` : ''}${\n\t\t\t{ daily: 'day', weekly: 'week', monthly: 'month', yearly: 'year' }[rule.freq]\n\t\t}`,\n\tcustomTitle: 'Custom recurrence',\n\trepeatEvery: 'Repeat every',\n\trepeatOn: 'Repeat on',\n\tends: 'Ends',\n\tnever: 'Never',\n\tendsOn: 'On',\n\tendsAfter: 'After',\n\toccurrences: 'occurrences',\n\tcancel: 'Cancel',\n\tdone: 'Done',\n\tunit: { daily: 'day', weekly: 'week', monthly: 'month', yearly: 'year' },\n};\n\n// ---------------------------------------------------------------------------\n\n/** Which occurrence of its weekday a date is — the 2nd Wednesday, say. */\nexport function weekdayOrdinal(date: Date): number {\n\treturn Math.floor((date.getDate() - 1) / 7) + 1;\n}\n\nexport const weekdayOf = (date: Date): TWeekday => WEEKDAY_BY_INDEX[date.getDay()] as TWeekday;\n\nconst isWeekdayRule = (rule: IRecurrence) =>\n\trule.freq === 'weekly' &&\n\trule.interval === 1 &&\n\trule.byWeekday?.length === 5 &&\n\t['MO', 'TU', 'WE', 'TH', 'FR'].every((d) => rule.byWeekday?.includes(d as TWeekday));\n\nconst sameRule = (a: IRecurrence | null, b: IRecurrence | null) =>\n\tJSON.stringify(a ?? null) === JSON.stringify(b ?? null);\n\n/** Local `yyyy-mm-dd` — `toISOString` would shift the day across the offset. */\nfunction isoDate(date: Date): string {\n\tconst pad = (n: number) => String(n).padStart(2, '0');\n\treturn `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;\n}\n\nconst oneYearOn = (start: Date) => {\n\tconst until = new Date(start);\n\tuntil.setFullYear(until.getFullYear() + 1);\n\treturn isoDate(until);\n};\n\n/** The presets Google offers, all of them read off the start date. */\nexport function recurrencePresets(\n\tstart: Date,\n\tlabels: IRecurrenceLabels,\n\tlocale?: string,\n\tsupports?: IRecurrenceSupport\n): { rule: IRecurrence | null; label: string }[] {\n\tconst freqs = supports?.freqs ?? ['daily', 'weekly', 'monthly', 'yearly'];\n\tconst weekdayName = new Intl.DateTimeFormat(locale, { weekday: 'long' }).format(start);\n\tconst dayMonth = new Intl.DateTimeFormat(locale, {\n\t\tday: 'numeric',\n\t\tmonth: 'long',\n\t}).format(start);\n\n\t// A store that cannot keep an endless series gets every preset bounded,\n\t// rather than a save that fails once the user has filled the card in.\n\tconst end: Partial<IRecurrence> = supports?.requireEnd\n\t\t? { until: (supports.defaultUntil ?? oneYearOn)(start) }\n\t\t: {};\n\n\tconst out: { rule: IRecurrence | null; label: string }[] = [\n\t\t{ rule: null, label: labels.doesNotRepeat },\n\t];\n\n\tif (freqs.includes('daily')) {\n\t\tout.push({ rule: { freq: 'daily', interval: 1, ...end }, label: labels.daily });\n\t}\n\tif (freqs.includes('weekly')) {\n\t\tout.push({\n\t\t\trule: { freq: 'weekly', interval: 1, byWeekday: [weekdayOf(start)], ...end },\n\t\t\tlabel: labels.weeklyOn(weekdayName),\n\t\t});\n\t}\n\tif (freqs.includes('monthly')) {\n\t\tout.push(\n\t\t\tsupports?.monthlyByWeekday === false\n\t\t\t\t? {\n\t\t\t\t\t\trule: { freq: 'monthly', interval: 1, monthly: 'date', ...end },\n\t\t\t\t\t\tlabel: labels.monthlyOnDate(start.getDate()),\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\trule: { freq: 'monthly', interval: 1, monthly: 'weekday', ...end },\n\t\t\t\t\t\tlabel: labels.monthlyOnWeekday(weekdayOrdinal(start), weekdayName),\n\t\t\t\t\t}\n\t\t);\n\t}\n\tif (freqs.includes('yearly')) {\n\t\tout.push({\n\t\t\trule: { freq: 'yearly', interval: 1, ...end },\n\t\t\tlabel: labels.annuallyOn(dayMonth),\n\t\t});\n\t}\n\tif (freqs.includes('weekly')) {\n\t\tout.push({\n\t\t\trule: {\n\t\t\t\tfreq: 'weekly',\n\t\t\t\tinterval: 1,\n\t\t\t\tbyWeekday: ['MO', 'TU', 'WE', 'TH', 'FR'],\n\t\t\t\t...end,\n\t\t\t},\n\t\t\tlabel: labels.everyWeekday,\n\t\t});\n\t}\n\n\treturn out;\n}\n\n// ---------------------------------------------------------------------------\n\nconst controlClass = cn(\n\t'rounded-md border border-input bg-background px-2 py-1 text-sm',\n\t'outline-none focus:border-primary'\n);\n\nfunction CustomDialog({\n\tvalue,\n\tstart,\n\tlabels,\n\tlocale,\n\tweekStartsOn = 1,\n\tsupports,\n\tonCancel,\n\tonDone,\n}: {\n\tvalue: IRecurrence | null;\n\tstart: Date;\n\tlabels: IRecurrenceLabels;\n\tlocale?: string | undefined;\n\tweekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined;\n\tsupports?: IRecurrenceSupport | undefined;\n\tonCancel: () => void;\n\tonDone: (rule: IRecurrence) => void;\n}) {\n\tconst [rule, setRule] = useState<IRecurrence>(() => {\n\t\tconst seed = value ?? {\n\t\t\tfreq: 'weekly' as const,\n\t\t\tinterval: 1,\n\t\t\tbyWeekday: [weekdayOf(start)],\n\t\t};\n\t\tif (!supports?.requireEnd || seed.until || seed.count != null) return seed;\n\t\treturn { ...seed, until: (supports.defaultUntil ?? oneYearOn)(start) };\n\t});\n\tconst set = (patch: Partial<IRecurrence>) => setRule((r) => ({ ...r, ...patch }));\n\n\tconst freqs = supports?.freqs ?? ['daily', 'weekly', 'monthly', 'yearly'];\n\tconst ending: 'never' | 'on' | 'after' =\n\t\trule.count != null ? 'after' : rule.until ? 'on' : 'never';\n\n\tconst letters = Array.from({ length: 7 }, (_, i) => {\n\t\tconst index = (weekStartsOn + i) % 7;\n\t\tconst date = new Date(2024, 0, 7 + index); // 7 Jan 2024 was a Sunday\n\t\treturn {\n\t\t\tkey: WEEKDAY_BY_INDEX[index] as TWeekday,\n\t\t\tletter: new Intl.DateTimeFormat(locale, { weekday: 'narrow' }).format(date),\n\t\t};\n\t});\n\n\tconst toggleDay = (day: TWeekday) => {\n\t\tconst on = rule.byWeekday ?? [];\n\t\tconst next = on.includes(day) ? on.filter((d) => d !== day) : [...on, day];\n\t\t// A weekly rule with no day repeats on nothing; keep at least the start's.\n\t\tset({ byWeekday: next.length ? next : [weekdayOf(start)] });\n\t};\n\n\tif (typeof document === 'undefined') return null;\n\n\treturn createPortal(\n\t\t<div\n\t\t\tdata-ic-layer=\"\"\n\t\t\tclassName=\"fixed inset-0 flex items-center justify-center bg-black/40\"\n\t\t\tstyle={{ zIndex: IC_Z_MODAL }}\n\t\t\tonPointerDown={(e) => {\n\t\t\t\tif (e.target === e.currentTarget) onCancel();\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\trole=\"dialog\"\n\t\t\t\taria-label={labels.customTitle}\n\t\t\t\tclassName=\"w-[340px] rounded-xl bg-popover p-5 text-popover-foreground shadow-2xl\"\n\t\t\t>\n\t\t\t\t<h3 className=\"mb-4 text-base font-medium\">{labels.customTitle}</h3>\n\n\t\t\t\t<div className=\"mb-4 flex items-center gap-2\">\n\t\t\t\t\t<span className=\"text-sm\">{labels.repeatEvery}</span>\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\tmin={1}\n\t\t\t\t\t\tmax={99}\n\t\t\t\t\t\taria-label={labels.repeatEvery}\n\t\t\t\t\t\tvalue={rule.interval}\n\t\t\t\t\t\tonChange={(e) => set({ interval: Math.max(1, Number(e.target.value) || 1) })}\n\t\t\t\t\t\tclassName={cn(controlClass, 'w-16')}\n\t\t\t\t\t/>\n\t\t\t\t\t<select\n\t\t\t\t\t\taria-label={labels.repeatEvery}\n\t\t\t\t\t\tvalue={rule.freq}\n\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\tconst freq = e.target.value as TRecurrenceFreq;\n\t\t\t\t\t\t\tset({\n\t\t\t\t\t\t\t\tfreq,\n\t\t\t\t\t\t\t\t...(freq === 'weekly' && !rule.byWeekday?.length\n\t\t\t\t\t\t\t\t\t? { byWeekday: [weekdayOf(start)] }\n\t\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t\t...(freq === 'monthly' && !rule.monthly\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\tmonthly: supports?.monthlyByWeekday === false ? 'date' : 'weekday',\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName={cn(controlClass, 'flex-1')}\n\t\t\t\t\t>\n\t\t\t\t\t\t{freqs.map((freq) => (\n\t\t\t\t\t\t\t<option key={freq} value={freq}>\n\t\t\t\t\t\t\t\t{labels.unit[freq]}\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</select>\n\t\t\t\t</div>\n\n\t\t\t\t{rule.freq === 'weekly' && (\n\t\t\t\t\t<div className=\"mb-4\">\n\t\t\t\t\t\t<p className=\"mb-2 text-sm\">{labels.repeatOn}</p>\n\t\t\t\t\t\t<div className=\"flex gap-1.5\">\n\t\t\t\t\t\t\t{letters.map(({ key, letter }) => {\n\t\t\t\t\t\t\t\tconst on = rule.byWeekday?.includes(key);\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\tkey={key}\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\taria-pressed={on}\n\t\t\t\t\t\t\t\t\t\taria-label={key}\n\t\t\t\t\t\t\t\t\t\tonClick={() => toggleDay(key)}\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t'size-8 rounded-full text-xs font-medium',\n\t\t\t\t\t\t\t\t\t\t\ton ? 'bg-primary text-primary-foreground' : 'bg-muted hover:bg-accent'\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{letter}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t<fieldset className=\"mb-5\">\n\t\t\t\t\t<legend className=\"mb-2 text-sm\">{labels.ends}</legend>\n\t\t\t\t\t<div className=\"flex flex-col gap-2\">\n\t\t\t\t\t\t{!supports?.requireEnd && (\n\t\t\t\t\t\t\t<label className=\"flex items-center gap-3 text-sm\">\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\t\tname=\"ic-recurrence-ends\"\n\t\t\t\t\t\t\t\t\tchecked={ending === 'never'}\n\t\t\t\t\t\t\t\t\tonChange={() => set({ until: null, count: null })}\n\t\t\t\t\t\t\t\t\tclassName=\"size-4 accent-[var(--primary)]\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t{labels.never}\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{supports?.until !== false && (\n\t\t\t\t\t\t\t<label className=\"flex items-center gap-3 text-sm\">\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\t\tname=\"ic-recurrence-ends\"\n\t\t\t\t\t\t\t\t\tchecked={ending === 'on'}\n\t\t\t\t\t\t\t\t\tonChange={() =>\n\t\t\t\t\t\t\t\t\t\tset({\n\t\t\t\t\t\t\t\t\t\t\tcount: null,\n\t\t\t\t\t\t\t\t\t\t\tuntil: (supports?.defaultUntil ?? oneYearOn)(start),\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tclassName=\"size-4 accent-[var(--primary)]\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<span className=\"w-12\">{labels.endsOn}</span>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\ttype=\"date\"\n\t\t\t\t\t\t\t\t\taria-label={labels.endsOn}\n\t\t\t\t\t\t\t\t\tdisabled={ending !== 'on'}\n\t\t\t\t\t\t\t\t\tvalue={rule.until ?? ''}\n\t\t\t\t\t\t\t\t\tonChange={(e) => set({ until: e.target.value, count: null })}\n\t\t\t\t\t\t\t\t\tclassName={cn(controlClass, 'flex-1 disabled:opacity-50')}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{supports?.count !== false && (\n\t\t\t\t\t\t\t<label className=\"flex items-center gap-3 text-sm\">\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\t\tname=\"ic-recurrence-ends\"\n\t\t\t\t\t\t\t\t\tchecked={ending === 'after'}\n\t\t\t\t\t\t\t\t\tonChange={() => set({ until: null, count: 13 })}\n\t\t\t\t\t\t\t\t\tclassName=\"size-4 accent-[var(--primary)]\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<span className=\"w-12\">{labels.endsAfter}</span>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\t\t\tmin={1}\n\t\t\t\t\t\t\t\t\tmax={999}\n\t\t\t\t\t\t\t\t\taria-label={labels.occurrences}\n\t\t\t\t\t\t\t\t\tdisabled={ending !== 'after'}\n\t\t\t\t\t\t\t\t\tvalue={rule.count ?? ''}\n\t\t\t\t\t\t\t\t\tonChange={(e) =>\n\t\t\t\t\t\t\t\t\t\tset({ count: Math.max(1, Number(e.target.value) || 1), until: null })\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tclassName={cn(controlClass, 'w-16 disabled:opacity-50')}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">{labels.occurrences}</span>\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</fieldset>\n\n\t\t\t\t<div className=\"flex justify-end gap-2\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onCancel}\n\t\t\t\t\t\tclassName=\"h-9 rounded-md px-3 text-sm font-medium text-primary hover:bg-accent\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{labels.cancel}\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => onDone(rule)}\n\t\t\t\t\t\tclassName=\"h-9 rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground hover:bg-primary/80\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{labels.done}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>,\n\t\tdocument.body\n\t);\n}\n\n// ---------------------------------------------------------------------------\n\nexport interface RecurrenceFieldProps {\n\t/** `null` means it does not repeat. */\n\tvalue: IRecurrence | null;\n\tonChange: (rule: IRecurrence | null) => void;\n\t/** The presets are read off this — \"Weekly on Wednesday\" needs the day. */\n\tstart: Date;\n\tlocale?: string | undefined;\n\tweekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined;\n\t/** What the consumer's store can actually keep. */\n\tsupports?: IRecurrenceSupport | undefined;\n\tlabels?: Partial<IRecurrenceLabels> | undefined;\n\tdisabled?: boolean | undefined;\n}\n\nexport function RecurrenceField({\n\tvalue,\n\tonChange,\n\tstart,\n\tlocale,\n\tweekStartsOn,\n\tsupports,\n\tlabels,\n\tdisabled,\n}: RecurrenceFieldProps) {\n\tconst text = { ...DEFAULT_LABELS, ...labels };\n\tconst [open, setOpen] = useState(false);\n\tconst [custom, setCustom] = useState(false);\n\tconst ref = useRef<HTMLDivElement>(null);\n\n\tconst presets = recurrencePresets(start, text, locale, supports);\n\tconst matched = presets.find((p) => sameRule(p.rule, value));\n\n\t// A rule the presets do not cover still needs a name on the pill.\n\tconst current =\n\t\tmatched?.label ??\n\t\t(value ? (isWeekdayRule(value) ? text.everyWeekday : text.summary(value)) : text.doesNotRepeat);\n\n\t// Open means holding the one menu slot: taking it closes whichever other\n\t// menu (a time list, the date calendar) is showing, and vice versa.\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\treturn claimMenuSlot(() => setOpen(false));\n\t}, [open]);\n\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tconst onDown = (e: PointerEvent) => {\n\t\t\tif (!ref.current?.contains(e.target as Node)) setOpen(false);\n\t\t};\n\t\t// Capture, so a control that stops pointerdown from bubbling still\n\t\t// dismisses the menu; deferred, so the press that opened it does not.\n\t\tconst id = window.setTimeout(() => document.addEventListener('pointerdown', onDown, true), 0);\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('pointerdown', onDown, true);\n\t\t\twindow.clearTimeout(id);\n\t\t};\n\t}, [open]);\n\n\treturn (\n\t\t<div ref={ref} className=\"relative w-fit\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\tonClick={() => setOpen((v) => !v)}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex items-center gap-1 rounded-md px-2 py-1 text-sm',\n\t\t\t\t\t'hover:bg-accent hover:text-accent-foreground',\n\t\t\t\t\t'disabled:cursor-not-allowed disabled:opacity-50',\n\t\t\t\t\topen && 'bg-accent text-accent-foreground'\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{current}\n\t\t\t\t<ChevronDown className={cn('size-4', open && 'rotate-180')} />\n\t\t\t</button>\n\n\t\t\t{open && (\n\t\t\t\t<div\n\t\t\t\t\tdata-ic-layer=\"\"\n\t\t\t\t\trole=\"listbox\"\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'absolute left-0 top-full mt-1 w-64 rounded-lg border p-1',\n\t\t\t\t\t\t'bg-popover text-popover-foreground shadow-lg'\n\t\t\t\t\t)}\n\t\t\t\t\tstyle={{ zIndex: IC_Z_LAYER }}\n\t\t\t\t>\n\t\t\t\t\t{presets.map((preset) => (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={preset.label}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\t\taria-selected={preset === matched}\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tonChange(preset.rule);\n\t\t\t\t\t\t\t\tsetOpen(false);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'w-full rounded px-3 py-1.5 text-left text-sm',\n\t\t\t\t\t\t\t\t'hover:bg-accent hover:text-accent-foreground',\n\t\t\t\t\t\t\t\tpreset === matched && 'bg-accent font-medium'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{preset.label}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t))}\n\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\taria-selected={!matched && Boolean(value)}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetOpen(false);\n\t\t\t\t\t\t\tsetCustom(true);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"w-full rounded px-3 py-1.5 text-left text-sm hover:bg-accent hover:text-accent-foreground\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{text.custom}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{custom && (\n\t\t\t\t<CustomDialog\n\t\t\t\t\tvalue={value}\n\t\t\t\t\tstart={start}\n\t\t\t\t\tlabels={text}\n\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t{...(weekStartsOn !== undefined && { weekStartsOn })}\n\t\t\t\t\t{...(supports && { supports })}\n\t\t\t\t\tonCancel={() => setCustom(false)}\n\t\t\t\t\tonDone={(rule) => {\n\t\t\t\t\t\tonChange(rule);\n\t\t\t\t\t\tsetCustom(false);\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","/**\n * The \"when\" of an event, laid out the way Google lays it out: a date pill and\n * two time pills on one line, an All-day checkbox under them, and a month grid\n * or a list of times behind whichever pill you press.\n *\n * Why pills rather than `datetime-local`: the native control makes you type\n * into three segments in an order that differs per browser and per OS, and it\n * cannot show a duration beside each end time. Picking \"16:30 (1 h)\" from a\n * list is the whole reason Google's version reads as fast as it does.\n *\n * The time pills are also inputs: the list offers the usual slots, and a time\n * between them — a 7-minute call, a 20-minute visit — is typed straight into\n * the pill (\"9:07\", \"907\", \"9h07\") and committed on Enter or blur.\n *\n * One menu at a time: the pills share a single open slot, so clicking one\n * closes whichever was open — no hover-opening; a menu only ever appears on\n * click or focus.\n *\n * Fully controlled. It never holds a date of its own — the card owns the range,\n * this only proposes changes to it.\n */\n\nimport { Clock } from 'lucide-react';\nimport { type ReactNode, useEffect, useRef, useState } from 'react';\nimport { formatClock, parseClockText } from '../../core/utils/time-format';\nimport { cn } from '../../lib/utils';\nimport { MiniMonth } from '../shell/mini-month';\nimport { FieldLayer } from './field-layer';\n\nconst MINUTE = 60_000;\nconst DAY_MINUTES = 24 * 60;\n\nexport interface IWhenLabels {\n\tallDay: string;\n\tstartDate: string;\n\tstartTime: string;\n\tendTime: string;\n\tendDate: string;\n\t/**\n\t * \"1 h 30\" beside an end time. A function because plurals and word order\n\t * belong to the consumer's i18n, not to a calendar.\n\t */\n\tduration: (minutes: number) => string;\n}\n\nconst DEFAULT_LABELS: IWhenLabels = {\n\tallDay: 'All day',\n\tstartDate: 'Start date',\n\tstartTime: 'Start time',\n\tendTime: 'End time',\n\tendDate: 'End date',\n\tduration: (minutes) => {\n\t\tconst hours = Math.floor(minutes / 60);\n\t\tconst rest = minutes % 60;\n\t\tif (!hours) return `${rest} min`;\n\t\treturn rest ? `${hours} h ${rest}` : `${hours} h`;\n\t},\n};\n\nexport interface WhenRowProps {\n\tstart: Date;\n\tend: Date;\n\tallDay?: boolean | undefined;\n\t/** Only the keys that moved. */\n\tonChange: (next: { start?: Date; end?: Date; allDay?: boolean }) => void;\n\tlocale?: string | undefined;\n\t/** @default false — 24-hour */\n\thour12?: boolean | undefined;\n\t/** Granularity of the time lists. @default 15 */\n\tstep?: number | undefined;\n\tweekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined;\n\tlabels?: Partial<IWhenLabels> | undefined;\n\t/** Hide the All-day checkbox for domains where every event has a time. */\n\tshowAllDay?: boolean | undefined;\n\t/**\n\t * Rendered under the All-day checkbox — the recurrence pill, which Google\n\t * groups with the time because changing the date changes what it can say.\n\t */\n\tchildren?: ReactNode;\n\tdisabled?: boolean | undefined;\n}\n\n// ---------------------------------------------------------------------------\n\nconst startOfDay = (date: Date) => {\n\tconst next = new Date(date);\n\tnext.setHours(0, 0, 0, 0);\n\treturn next;\n};\n\nconst endOfDay = (date: Date) => {\n\tconst next = new Date(date);\n\tnext.setHours(23, 59, 59, 999);\n\treturn next;\n};\n\n/** Move a date to another day, keeping its clock time. */\nfunction onDay(date: Date, day: Date) {\n\tconst next = new Date(day);\n\tnext.setHours(date.getHours(), date.getMinutes(), 0, 0);\n\treturn next;\n}\n\nconst sameDay = (a: Date, b: Date) =>\n\ta.getFullYear() === b.getFullYear() &&\n\ta.getMonth() === b.getMonth() &&\n\ta.getDate() === b.getDate();\n\n// ---------------------------------------------------------------------------\n\n/** Which pill's menu is open — one slot for the whole row. */\ntype TWhenMenu = 'startDate' | 'startTime' | 'endTime' | 'endDate';\n\ninterface IMenuSlot {\n\topen: boolean;\n\tonOpen: () => void;\n\tonClose: () => void;\n}\n\n/**\n * Same horizontal padding as the card's rows, so a pill's *text* sits on the\n * same line as \"Add location\" below it — see the negative margin on the group.\n * The date and two times have to fit one line at the card's narrow width, so\n * this is tight on purpose.\n */\nconst pillClass = cn(\n\t'rounded-md px-2 py-1 text-sm whitespace-nowrap',\n\t'hover:bg-accent hover:text-accent-foreground',\n\t'focus:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n\t'disabled:cursor-not-allowed disabled:opacity-50'\n);\n\nfunction DatePill({\n\tvalue,\n\tonSelect,\n\tlabel,\n\tlocale,\n\tweekStartsOn,\n\tdisabled,\n\tmenu,\n}: {\n\tvalue: Date;\n\tonSelect: (date: Date) => void;\n\tlabel: string;\n\tlocale?: string | undefined;\n\tweekStartsOn?: WhenRowProps['weekStartsOn'];\n\tdisabled?: boolean | undefined;\n\tmenu: IMenuSlot;\n}) {\n\tconst ref = useRef<HTMLButtonElement>(null);\n\tconst { open, onOpen, onClose } = menu;\n\n\t// Short forms: \"Wednesday, 12 August\" alongside two times overflows the\n\t// card and wraps, which costs more clarity than the long weekday buys.\n\tconst text = new Intl.DateTimeFormat(locale, {\n\t\tweekday: 'short',\n\t\tday: 'numeric',\n\t\tmonth: 'short',\n\t}).format(value);\n\n\treturn (\n\t\t<>\n\t\t\t<button\n\t\t\t\tref={ref}\n\t\t\t\ttype=\"button\"\n\t\t\t\taria-label={label}\n\t\t\t\taria-expanded={open}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tif (open) onClose();\n\t\t\t\t\telse onOpen();\n\t\t\t\t}}\n\t\t\t\tclassName={cn(pillClass, open && 'bg-accent text-accent-foreground')}\n\t\t\t>\n\t\t\t\t{text}\n\t\t\t</button>\n\n\t\t\t{open && (\n\t\t\t\t<FieldLayer anchorRef={ref} onClose={onClose} className=\"w-64\">\n\t\t\t\t\t<MiniMonth\n\t\t\t\t\t\tselected={value}\n\t\t\t\t\t\tonSelect={(date) => {\n\t\t\t\t\t\t\tonSelect(date);\n\t\t\t\t\t\t\tonClose();\n\t\t\t\t\t\t}}\n\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\t{...(weekStartsOn !== undefined && { weekStartsOn })}\n\t\t\t\t\t/>\n\t\t\t\t</FieldLayer>\n\t\t\t)}\n\t\t</>\n\t);\n}\n\nfunction TimePill({\n\tvalue,\n\toptions,\n\tonSelect,\n\tonType,\n\tlabel,\n\tlocale,\n\thour12,\n\tdisabled,\n\tmenu,\n}: {\n\tvalue: Date;\n\t/** Pre-built so the end list can carry durations the start list cannot. */\n\toptions: { at: Date; text: string; hint?: string }[];\n\tonSelect: (date: Date) => void;\n\t/** A time typed into the pill, already parsed to a clock reading. */\n\tonType: (hours: number, minutes: number) => void;\n\tlabel: string;\n\tlocale?: string | undefined;\n\thour12?: boolean | undefined;\n\tdisabled?: boolean | undefined;\n\tmenu: IMenuSlot;\n}) {\n\tconst ref = useRef<HTMLInputElement>(null);\n\tconst listRef = useRef<HTMLDivElement>(null);\n\tconst { open, onOpen, onClose } = menu;\n\n\t/** Non-null while the pill holds keystrokes the value does not have yet. */\n\tconst [draft, setDraft] = useState<string | null>(null);\n\t/** A press began in the list — the blur it causes must not commit the draft. */\n\tconst picking = useRef(false);\n\n\t// Open on the current value rather than at midnight — otherwise every pick\n\t// starts with the same long scroll.\n\tuseEffect(() => {\n\t\tif (!open) {\n\t\t\t// A press that started in the list but was released elsewhere never\n\t\t\t// fires the pointerup that clears the flag; the close does it instead,\n\t\t\t// or every later blur would skip its commit.\n\t\t\tpicking.current = false;\n\t\t\treturn;\n\t\t}\n\t\tconst current = listRef.current?.querySelector<HTMLElement>('[data-current=\"true\"]');\n\t\t// Guarded: jsdom has no layout, so it has no scrollIntoView either.\n\t\tcurrent?.scrollIntoView?.({ block: 'center' });\n\t}, [open]);\n\n\tconst commit = () => {\n\t\tif (draft === null) return;\n\t\tconst parsed = parseClockText(draft);\n\t\tif (parsed) onType(parsed.hours, parsed.minutes);\n\t\tsetDraft(null);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<input\n\t\t\t\tref={ref}\n\t\t\t\ttype=\"text\"\n\t\t\t\t// A text field with a list of completions behind it — the ARIA 1.2\n\t\t\t\t// combobox pattern, which is also what lets it carry aria-expanded.\n\t\t\t\trole=\"combobox\"\n\t\t\t\taria-label={label}\n\t\t\t\taria-haspopup=\"listbox\"\n\t\t\t\taria-expanded={open}\n\t\t\t\tautoComplete=\"off\"\n\t\t\t\tspellCheck={false}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tvalue={draft ?? formatClock(value, { locale, hour12 })}\n\t\t\t\tonFocus={(e) => {\n\t\t\t\t\tonOpen();\n\t\t\t\t\te.currentTarget.select();\n\t\t\t\t}}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tif (!open) onOpen();\n\t\t\t\t}}\n\t\t\t\tonChange={(e) => setDraft(e.target.value)}\n\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\tif (e.key === 'Enter') {\n\t\t\t\t\t\t// The card is a form; a committed time must not submit it.\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tcommit();\n\t\t\t\t\t\tonClose();\n\t\t\t\t\t} else if (e.key === 'Escape') {\n\t\t\t\t\t\t// The open list eats the first Escape (FieldLayer, in capture),\n\t\t\t\t\t\t// so this runs once the list is gone — and reverts the text.\n\t\t\t\t\t\tsetDraft(null);\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t\tonBlur={() => {\n\t\t\t\t\tif (picking.current) return;\n\t\t\t\t\tcommit();\n\t\t\t\t\tonClose();\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\n\t\t\t\t\tpillClass,\n\t\t\t\t\t'bg-transparent',\n\t\t\t\t\thour12 ? 'w-24' : 'w-[4.5rem]',\n\t\t\t\t\topen && 'bg-accent text-accent-foreground'\n\t\t\t\t)}\n\t\t\t/>\n\n\t\t\t{open && (\n\t\t\t\t<FieldLayer anchorRef={ref} onClose={onClose} className=\"p-1\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tref={listRef}\n\t\t\t\t\t\trole=\"listbox\"\n\t\t\t\t\t\taria-label={label}\n\t\t\t\t\t\tonPointerDown={() => {\n\t\t\t\t\t\t\tpicking.current = true;\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonPointerUp={() => {\n\t\t\t\t\t\t\t// Cleared after the click this press becomes has run.\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tpicking.current = false;\n\t\t\t\t\t\t\t}, 0);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"max-h-64 w-44 overflow-y-auto\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{options.map((option) => {\n\t\t\t\t\t\t\tconst current =\n\t\t\t\t\t\t\t\toption.at.getHours() === value.getHours() &&\n\t\t\t\t\t\t\t\toption.at.getMinutes() === value.getMinutes();\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={option.at.toISOString()}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\t\t\t\t// Two adjacent spans read as one word (\"10:1515 min\") to a\n\t\t\t\t\t\t\t\t\t// screen reader, so the name is spelled out.\n\t\t\t\t\t\t\t\t\taria-label={option.hint ? `${option.text}, ${option.hint}` : option.text}\n\t\t\t\t\t\t\t\t\taria-selected={current}\n\t\t\t\t\t\t\t\t\tdata-current={current}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetDraft(null);\n\t\t\t\t\t\t\t\t\t\tonSelect(option.at);\n\t\t\t\t\t\t\t\t\t\tonClose();\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t'flex w-full items-center gap-2 rounded px-2 py-1 text-left text-sm',\n\t\t\t\t\t\t\t\t\t\t'hover:bg-accent hover:text-accent-foreground',\n\t\t\t\t\t\t\t\t\t\tcurrent && 'bg-accent font-medium text-accent-foreground'\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span>{option.text}</span>\n\t\t\t\t\t\t\t\t\t{option.hint && (\n\t\t\t\t\t\t\t\t\t\t<span className=\"ml-auto text-xs text-muted-foreground\">{option.hint}</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\t\t\t\t</FieldLayer>\n\t\t\t)}\n\t\t</>\n\t);\n}\n\n// ---------------------------------------------------------------------------\n\nexport function WhenRow({\n\tstart,\n\tend,\n\tallDay = false,\n\tonChange,\n\tlocale,\n\thour12,\n\tstep = 15,\n\tweekStartsOn,\n\tlabels,\n\tshowAllDay = true,\n\tchildren,\n\tdisabled,\n}: WhenRowProps) {\n\tconst text = { ...DEFAULT_LABELS, ...labels };\n\t// `1`, not `step`: a typed end can put a 7-minute duration here, and moving\n\t// the start must carry it, not round it back up to a slot.\n\tconst duration = Math.max(1, Math.round((end.getTime() - start.getTime()) / MINUTE));\n\n\tconst [openMenu, setOpenMenu] = useState<TWhenMenu | null>(null);\n\tconst menuFor = (id: TWhenMenu): IMenuSlot => ({\n\t\topen: openMenu === id,\n\t\tonOpen: () => setOpenMenu(id),\n\t\t// Guarded: a late close from a menu that already lost the slot must not\n\t\t// shut the one that took it.\n\t\tonClose: () => setOpenMenu((current) => (current === id ? null : current)),\n\t});\n\n\t/** Every slot in the day, for the start pill. */\n\tconst startOptions = Array.from({ length: Math.floor(DAY_MINUTES / step) }, (_, i) => {\n\t\tconst at = new Date(startOfDay(start).getTime() + i * step * MINUTE);\n\t\treturn { at, text: formatClock(at, { locale, hour12 }) };\n\t});\n\n\t/**\n\t * The end list runs forward from the start, so every entry is a real\n\t * duration — and one that crosses midnight simply keeps counting.\n\t */\n\tconst endOptions = Array.from({ length: Math.floor(DAY_MINUTES / step) }, (_, i) => {\n\t\tconst minutes = (i + 1) * step;\n\t\tconst at = new Date(start.getTime() + minutes * MINUTE);\n\t\treturn {\n\t\t\tat,\n\t\t\ttext: formatClock(at, { locale, hour12 }),\n\t\t\thint: text.duration(minutes),\n\t\t};\n\t});\n\n\t/** Moving the start carries the event with it; the duration is not news. */\n\tconst moveStart = (next: Date) =>\n\t\tonChange({ start: next, end: new Date(next.getTime() + duration * MINUTE) });\n\n\tconst typeStart = (hours: number, minutes: number) => {\n\t\tconst next = new Date(start);\n\t\tnext.setHours(hours, minutes, 0, 0);\n\t\tmoveStart(next);\n\t};\n\n\t/**\n\t * The end list counts forward from the start; a typed time follows the same\n\t * rule — an earlier clock on the same day means the next one.\n\t */\n\tconst typeEnd = (hours: number, minutes: number) => {\n\t\tconst next = new Date(end);\n\t\tnext.setHours(hours, minutes, 0, 0);\n\t\tif (next <= start) {\n\t\t\tif (!sameDay(start, end)) {\n\t\t\t\t// An end before its start is the classic broken event; hold the line.\n\t\t\t\tonChange({ end: start });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnext.setDate(next.getDate() + 1);\n\t\t}\n\t\tonChange({ end: next });\n\t};\n\n\tconst setStartDay = (day: Date) => {\n\t\tconst nextStart = allDay ? startOfDay(day) : onDay(start, day);\n\t\tonChange({\n\t\t\tstart: nextStart,\n\t\t\tend: allDay\n\t\t\t\t? endOfDay(nextStart > end ? day : end)\n\t\t\t\t: new Date(nextStart.getTime() + duration * MINUTE),\n\t\t});\n\t};\n\n\tconst setEndDay = (day: Date) => {\n\t\t// An end before its start is the classic broken event; hold the line.\n\t\tconst next = allDay ? endOfDay(day) : onDay(end, day);\n\t\tonChange({ end: next < start ? (allDay ? endOfDay(start) : start) : next });\n\t};\n\n\tconst toggleAllDay = () => {\n\t\tif (allDay) {\n\t\t\t// Back to a timed event: the working slot the grid would have given.\n\t\t\tconst nextStart = onDay(new Date(start.setHours(9, 0, 0, 0)), start);\n\t\t\tonChange({\n\t\t\t\tallDay: false,\n\t\t\t\tstart: nextStart,\n\t\t\t\tend: new Date(nextStart.getTime() + 60 * MINUTE),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tonChange({ allDay: true, start: startOfDay(start), end: endOfDay(end) });\n\t};\n\n\t// Google only shows the second date when it says something new — an event\n\t// that ends on another day, or an all-day one that might.\n\tconst showEndDate = allDay || !sameDay(start, end);\n\n\treturn (\n\t\t<div className=\"flex items-start px-4 py-1.5\">\n\t\t\t<span className=\"flex w-8 shrink-0 items-start pt-1.5 text-muted-foreground\">\n\t\t\t\t<Clock className=\"size-4\" />\n\t\t\t</span>\n\n\t\t\t{/* Pulled left by the pills' own padding, so every row in the card\n\t\t\t starts its text at the same x. */}\n\t\t\t<div className=\"-ml-2 flex min-w-0 flex-1 flex-col gap-0.5\">\n\t\t\t\t<div className=\"flex flex-wrap items-center gap-0.5\">\n\t\t\t\t\t<DatePill\n\t\t\t\t\t\tvalue={start}\n\t\t\t\t\t\tonSelect={setStartDay}\n\t\t\t\t\t\tlabel={text.startDate}\n\t\t\t\t\t\tmenu={menuFor('startDate')}\n\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\t{...(weekStartsOn !== undefined && { weekStartsOn })}\n\t\t\t\t\t\t{...(disabled && { disabled })}\n\t\t\t\t\t/>\n\n\t\t\t\t\t{!allDay && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<TimePill\n\t\t\t\t\t\t\t\tvalue={start}\n\t\t\t\t\t\t\t\toptions={startOptions}\n\t\t\t\t\t\t\t\tonSelect={moveStart}\n\t\t\t\t\t\t\t\tonType={typeStart}\n\t\t\t\t\t\t\t\tlabel={text.startTime}\n\t\t\t\t\t\t\t\tmenu={menuFor('startTime')}\n\t\t\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\t\t\t{...(hour12 !== undefined && { hour12 })}\n\t\t\t\t\t\t\t\t{...(disabled && { disabled })}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<span className=\"text-sm text-muted-foreground\">–</span>\n\t\t\t\t\t\t\t<TimePill\n\t\t\t\t\t\t\t\tvalue={end}\n\t\t\t\t\t\t\t\toptions={endOptions}\n\t\t\t\t\t\t\t\tonSelect={(next) => onChange({ end: next })}\n\t\t\t\t\t\t\t\tonType={typeEnd}\n\t\t\t\t\t\t\t\tlabel={text.endTime}\n\t\t\t\t\t\t\t\tmenu={menuFor('endTime')}\n\t\t\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\t\t\t{...(hour12 !== undefined && { hour12 })}\n\t\t\t\t\t\t\t\t{...(disabled && { disabled })}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{showEndDate && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{allDay && <span className=\"text-sm text-muted-foreground\">–</span>}\n\t\t\t\t\t\t\t<DatePill\n\t\t\t\t\t\t\t\tvalue={end}\n\t\t\t\t\t\t\t\tonSelect={setEndDay}\n\t\t\t\t\t\t\t\tlabel={text.endDate}\n\t\t\t\t\t\t\t\tmenu={menuFor('endDate')}\n\t\t\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\t\t\t{...(weekStartsOn !== undefined && { weekStartsOn })}\n\t\t\t\t\t\t\t\t{...(disabled && { disabled })}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t{showAllDay && (\n\t\t\t\t\t<div className=\"py-1 pl-2\">\n\t\t\t\t\t\t{/* The calendar's own tick, not the app's: it is one box inside\n\t\t\t\t\t\t a layout the time row owns, and injecting a component for it\n\t\t\t\t\t\t was the last thing holding the controls system up. */}\n\t\t\t\t\t\t<label className=\"flex w-fit cursor-pointer items-center gap-2 text-sm\">\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\tchecked={allDay}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\tonChange={toggleAllDay}\n\t\t\t\t\t\t\t\tclassName=\"size-4 shrink-0 accent-[var(--primary)] disabled:cursor-not-allowed disabled:opacity-50\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{text.allDay}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","/**\n * Resource columns — one day, one vertical column per person.\n *\n * This is how Google shows a day when several people are selected: a single\n * shared time gutter on the left, then a column each, name and avatar above.\n * The timeline views answer a different question (\"what does the week look like\n * across everyone\") by laying people out as horizontal lanes; this one answers\n * \"what does today look like for each of them\" and reads far better for 2–6\n * people.\n *\n * Deliberately a separate component rather than a generalisation of WeekView:\n * WeekView renders the primary screen in every consuming app, and the column\n * source is threaded through its selection, drag and overlap maths. Sharing\n * that code would be tidier and riskier.\n */\n\nimport { useMemo } from 'react';\nimport { DEFAULT_HOUR_HEIGHT, MINUTES_IN_HOUR } from '../../core/constants';\nimport { useOptionalSlotSelection } from '../../core/context/slot-selection-context';\nimport type {\n\tCalendarEvent,\n\tICalendarUser,\n\tITimeSlot,\n\tTBadgeVariant,\n\tTOnEventClick,\n} from '../../core/types';\nimport { isToday } from '../../core/utils/date-utils';\nimport { formatClock } from '../../core/utils/time-format';\nimport { cn } from '../../lib/utils';\nimport { EventBlock } from '../event/event-card';\nimport { TimeSlot } from '../primitives';\n\nconst HOUR_HEIGHT = DEFAULT_HOUR_HEIGHT;\nconst GUTTER_WIDTH = 64;\nconst HEADER_HEIGHT = 76;\nconst MIN_COLUMN_WIDTH = 140;\n/** Week mode multiplies columns by seven, so lanes have to be tighter. */\nconst MIN_COLUMN_WIDTH_MULTIDAY = 96;\n\nexport interface ResourceColumnsViewProps<\n\tTData extends Record<string, unknown> = Record<string, unknown>,\n> {\n\tevents: CalendarEvent<TData>[];\n\t/** The days being shown — one for a day view, seven for a week. */\n\tdates: Date[];\n\t/** One column per entry, in order. */\n\tresources: ICalendarUser[];\n\tvisibleHours: { startHour: number; endHour: number };\n\tslotDuration?: number;\n\tbadgeVariant?: TBadgeVariant;\n\tlocale?: string | undefined;\n\tonEventClick?: TOnEventClick<TData> | undefined;\n\trenderPopover?:\n\t\t| ((props: { event: CalendarEvent<TData>; onClose: () => void }) => React.ReactNode)\n\t\t| undefined;\n\tclassName?: string | undefined;\n}\n\n/** Which column an event belongs to, mirroring the timeline's resolution order. */\nfunction resourceIdOf(event: CalendarEvent): string | undefined {\n\tif (event.resourceId) return event.resourceId;\n\tconst data = event.data as { user?: { id?: string }; userId?: string } | undefined;\n\tif (data?.userId) return String(data.userId);\n\tif (data?.user?.id) return data.user.id;\n\tif (event.user?.id) return event.user.id;\n\treturn event.participants?.[0]?.id;\n}\n\nfunction minutesFromMidnight(d: Date) {\n\treturn d.getHours() * MINUTES_IN_HOUR + d.getMinutes();\n}\n\n/** Side-by-side placement for events that overlap inside one column. */\nfunction layoutColumn<TData extends Record<string, unknown>>(\n\tevents: CalendarEvent<TData>[],\n\tstartHour: number\n) {\n\tconst sorted = [...events].sort((a, b) => a.startDate.getTime() - b.startDate.getTime());\n\n\t// Group into runs of mutually overlapping events; each run shares the width.\n\tconst groups: CalendarEvent<TData>[][] = [];\n\tfor (const event of sorted) {\n\t\tconst group = groups.at(-1);\n\t\tconst overlapsGroup = group?.some((e) => e.endDate.getTime() > event.startDate.getTime());\n\t\tif (group && overlapsGroup) group.push(event);\n\t\telse groups.push([event]);\n\t}\n\n\treturn groups.flatMap((group) =>\n\t\tgroup.map((event, index) => {\n\t\t\tconst top =\n\t\t\t\t((minutesFromMidnight(event.startDate) - startHour * MINUTES_IN_HOUR) / MINUTES_IN_HOUR) *\n\t\t\t\tHOUR_HEIGHT;\n\t\t\tconst height = Math.max(\n\t\t\t\t18,\n\t\t\t\t((event.endDate.getTime() - event.startDate.getTime()) / (1000 * 60 * MINUTES_IN_HOUR)) *\n\t\t\t\t\tHOUR_HEIGHT\n\t\t\t);\n\t\t\tconst width = 100 / group.length;\n\t\t\treturn { event, top, height, left: width * index, width };\n\t\t})\n\t);\n}\n\nexport function ResourceColumnsView<\n\tTData extends Record<string, unknown> = Record<string, unknown>,\n>({\n\tevents,\n\tdates,\n\tresources,\n\tvisibleHours,\n\tbadgeVariant,\n\tslotDuration: slotMinutes = 30,\n\tlocale,\n\tonEventClick,\n\trenderPopover,\n\tclassName,\n}: ResourceColumnsViewProps<TData>) {\n\tconst hours = useMemo(\n\t\t() =>\n\t\t\tArray.from(\n\t\t\t\t{ length: Math.max(1, visibleHours.endHour - visibleHours.startHour) },\n\t\t\t\t(_, i) => visibleHours.startHour + i\n\t\t\t),\n\t\t[visibleHours.startHour, visibleHours.endHour]\n\t);\n\n\tconst dayKeys = useMemo(() => dates.map((d) => d.toDateString()), [dates]);\n\n\tconst dayEvents = useMemo(\n\t\t() => events.filter((e) => dayKeys.includes(e.startDate.toDateString())),\n\t\t[events, dayKeys]\n\t);\n\n\t/**\n\t * Columns come from the `resources` prop, but a resource view must never\n\t * render blank just because that list is empty or its ids don't line up with\n\t * the events — derive the missing columns from the events themselves, the way\n\t * the timeline view does.\n\t */\n\tconst columns = useMemo(() => {\n\t\tconst known = new Map(resources.map((r) => [r.id, r]));\n\n\t\tfor (const event of dayEvents) {\n\t\t\tconst id = resourceIdOf(event as CalendarEvent);\n\t\t\tif (!id || known.has(id)) continue;\n\t\t\tconst participant = event.participants?.find((p) => p.id === id);\n\t\t\tconst user = (event.data as { user?: ICalendarUser } | undefined)?.user;\n\t\t\tknown.set(id, participant ?? user ?? { id, name: id });\n\t\t}\n\n\t\treturn [...known.values()];\n\t}, [resources, dayEvents]);\n\n\t/** Keyed by `${dayKey}|${resourceId}` — one bucket per rendered column. */\n\tconst byCell = useMemo(() => {\n\t\tconst map = new Map<string, CalendarEvent<TData>[]>();\n\t\tfor (const key of dayKeys) for (const column of columns) map.set(`${key}|${column.id}`, []);\n\t\tfor (const event of dayEvents) {\n\t\t\tconst id = resourceIdOf(event as CalendarEvent);\n\t\t\tif (!id) continue;\n\t\t\tmap.get(`${event.startDate.toDateString()}|${id}`)?.push(event);\n\t\t}\n\t\treturn map;\n\t}, [dayEvents, columns, dayKeys]);\n\n\tconst nowOffset = useMemo(() => {\n\t\tif (!dates.some(isToday)) return null;\n\t\tconst now = new Date();\n\t\tconst offset =\n\t\t\t((minutesFromMidnight(now) - visibleHours.startHour * MINUTES_IN_HOUR) / MINUTES_IN_HOUR) *\n\t\t\tHOUR_HEIGHT;\n\t\treturn offset >= 0 && offset <= hours.length * HOUR_HEIGHT ? offset : null;\n\t}, [dates, visibleHours.startHour, hours.length]);\n\n\tconst gridHeight = hours.length * HOUR_HEIGHT;\n\n\tif (columns.length === 0) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex h-full items-center justify-center p-8 text-center',\n\t\t\t\t\t'text-sm text-muted-foreground',\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\tSelect at least one person to see their day.\n\t\t\t</div>\n\t\t);\n\t}\n\n\tconst multiDay = dates.length > 1;\n\n\t// `TimeSlot` is the shared primitive the week and day grids already use: it\n\t// owns drag-to-select *and* the drop target for drag-to-move. Reusing it is\n\t// what keeps this view's interactions identical to theirs rather than a\n\t// second implementation that drifts.\n\tconst slotSelection = useOptionalSlotSelection();\n\tconst slotsPerHour = Math.max(1, Math.round(MINUTES_IN_HOUR / slotMinutes));\n\tconst slotHeight = HOUR_HEIGHT / slotsPerHour;\n\tconst perPersonWidth = multiDay ? MIN_COLUMN_WIDTH_MULTIDAY : MIN_COLUMN_WIDTH;\n\n\treturn (\n\t\t<div className={cn('flex h-full flex-col', className)}>\n\t\t\t{/* A single scroll container for header and grid. With many people the\n\t\t\t columns overflow horizontally, and the names have to travel with the\n\t\t\t columns they label — so they share one scroller rather than sitting in\n\t\t\t two. `min-w-max` lets the columns fill the width when there is room\n\t\t\t and overflow when there is not. */}\n\t\t\t<div className=\"relative flex-1 overflow-auto\">\n\t\t\t\t<div className=\"min-w-max\">\n\t\t\t\t\t{/* Header. One day: the date sits in the gutter and people head the\n\t\t\t columns. Several days: the date spans its people. */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"sticky top-0 z-30 flex border-b bg-background\"\n\t\t\t\t\t\tstyle={{ height: HEADER_HEIGHT }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"sticky left-0 z-10 flex shrink-0 flex-col items-center justify-center bg-background\"\n\t\t\t\t\t\t\tstyle={{ width: GUTTER_WIDTH }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{!multiDay && dates[0] && (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<span className=\"text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t{new Intl.DateTimeFormat(locale, { weekday: 'short' }).format(dates[0])}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t'mt-0.5 flex size-9 items-center justify-center rounded-full text-xl',\n\t\t\t\t\t\t\t\t\t\t\tisToday(dates[0])\n\t\t\t\t\t\t\t\t\t\t\t\t? 'bg-primary font-medium text-primary-foreground'\n\t\t\t\t\t\t\t\t\t\t\t\t: 'text-foreground'\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{dates[0].getDate()}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t{dates.map((day) => (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={day.toDateString()}\n\t\t\t\t\t\t\t\tclassName=\"flex flex-1 flex-col border-r last:border-r-0\"\n\t\t\t\t\t\t\t\tstyle={{ minWidth: perPersonWidth * columns.length }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{multiDay && (\n\t\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-center gap-1.5 pt-1\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t{new Intl.DateTimeFormat(locale, { weekday: 'short' }).format(day)}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t'flex size-6 items-center justify-center rounded-full text-sm',\n\t\t\t\t\t\t\t\t\t\t\t\tisToday(day)\n\t\t\t\t\t\t\t\t\t\t\t\t\t? 'bg-primary font-medium text-primary-foreground'\n\t\t\t\t\t\t\t\t\t\t\t\t\t: 'text-foreground'\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{day.getDate()}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t<div className=\"flex flex-1\">\n\t\t\t\t\t\t\t\t\t{columns.map((resource) => (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tkey={resource.id}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex min-w-0 flex-1 flex-col items-center justify-center gap-0.5 px-1\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{!multiDay && (\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"max-w-full truncate text-[13px]\">{resource.name}</span>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t{resource.avatar ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\t\t\tsrc={resource.avatar}\n\t\t\t\t\t\t\t\t\t\t\t\t\talt={resource.name}\n\t\t\t\t\t\t\t\t\t\t\t\t\ttitle={resource.name}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'rounded-full object-cover',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmultiDay ? 'size-5' : 'size-7'\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\t\ttitle={resource.name}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'flex items-center justify-center rounded-full bg-muted font-medium text-muted-foreground',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmultiDay ? 'size-5 text-[10px]' : 'size-7 text-xs'\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{resource.name.charAt(0).toUpperCase()}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t{multiDay && (\n\t\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\t\ttitle={resource.name}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-full truncate text-center text-[10px] leading-tight text-muted-foreground\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{resource.name}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Grid */}\n\t\t\t\t\t<div className=\"relative flex\" style={{ height: gridHeight }}>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn('sticky left-0 z-10 shrink-0 border-r bg-background')}\n\t\t\t\t\t\t\tstyle={{ width: GUTTER_WIDTH }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{hours.map((hour, index) => (\n\t\t\t\t\t\t\t\t<div key={hour} className=\"relative\" style={{ height: HOUR_HEIGHT }}>\n\t\t\t\t\t\t\t\t\t{index !== 0 && (\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn('absolute -top-2 right-2 text-[10px] text-muted-foreground')}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{formatClock(new Date(2000, 0, 1, hour), { locale })}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t{dates.map((day) => (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={day.toDateString()}\n\t\t\t\t\t\t\t\tclassName=\"flex flex-1 border-r last:border-r-0\"\n\t\t\t\t\t\t\t\tstyle={{ minWidth: perPersonWidth * columns.length }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{columns.map((resource) => {\n\t\t\t\t\t\t\t\t\tconst laid = layoutColumn(\n\t\t\t\t\t\t\t\t\t\tbyCell.get(`${day.toDateString()}|${resource.id}`) ?? [],\n\t\t\t\t\t\t\t\t\t\tvisibleHours.startHour\n\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tkey={resource.id}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"relative flex-1 border-r border-border/40 last:border-r-0\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{hours.map((hour) => (\n\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={hour}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn('relative border-b border-border/60')}\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{ height: HOUR_HEIGHT }}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{Array.from({ length: slotsPerHour }, (_, i) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst minute = i * slotMinutes;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst slot: ITimeSlot = {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdate: day,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thour,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tminute,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tresourceId: resource.id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<TimeSlot\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={minute}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tslot={slot}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonSelectionStart={(s) => slotSelection?.startSelection(s)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonSelectionMove={(s) => slotSelection?.updateSelection(s)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonSelectionEnd={() => slotSelection?.endSelection()}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tisSelected={slotSelection?.isSlotSelected(slot) ?? false}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tisSelecting={slotSelection?.isSelecting ?? false}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"absolute inset-x-0\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{ top: i * slotHeight, height: slotHeight }}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t))}\n\n\t\t\t\t\t\t\t\t\t\t\t{laid.map(({ event, top, height, left, width }) => (\n\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={event.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"pointer-events-none absolute z-10 px-0.5\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{ top, height, left: `${left}%`, width: `${width}%` }}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<EventBlock\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tevent={event}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tposition={{ top: 0, left: 0, width: 100 }}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\thourHeight={HOUR_HEIGHT}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{...(badgeVariant && { badgeVariant })}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={onEventClick}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t/* Without this the block renders a popover trigger with\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t no content and swallows the click, so the consumer's\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t onEventClick never fires. Same rule as the week view. */\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisablePopover={!!onEventClick && !renderPopover}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trenderPopover={renderPopover}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'!relative !inset-auto h-full w-full pointer-events-auto'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\n\t\t\t\t\t\t{nowOffset !== null && (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tdata-ic-now=\"\"\n\t\t\t\t\t\t\t\tclassName=\"pointer-events-none absolute left-0 right-0 z-20 flex items-center\"\n\t\t\t\t\t\t\t\tstyle={{ top: nowOffset }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span className=\"ml-[58px] size-3 shrink-0 rounded-full bg-red-500\" />\n\t\t\t\t\t\t\t\t<span className=\"h-0.5 flex-1 bg-red-500\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","/**\n * Timeline View Component\n *\n * Horizontal timeline showing users/resources on Y-axis and time on X-axis.\n * Events display as colored bars with proper stacking for overlapping events.\n *\n * Features:\n * - User avatars and names on left column\n * - For 1-day: Hour columns across top (8am-6pm etc)\n * - For 3-day: Day headers with hour columns below each day\n * - For 7-day (week): Date columns across top\n * - Colored event bars with schedule type colors\n * - Proper event stacking when multiple events overlap\n * - Dynamic row heights to accommodate stacked events\n * - Click to view event details\n *\n * @template TData - Custom event data type\n */\n\nimport type React from \"react\";\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { useOptionalDragDrop } from \"../../core/context/drag-drop-context\";\nimport type {\n CalendarEvent,\n ICalendarUser,\n IResourceColumnConfig,\n ISelectionResult,\n} from \"../../core/types\";\nimport { endOfDay, isToday, isWeekend, startOfDay } from \"../../core/utils\";\nimport { cn } from \"../../lib/utils\";\nimport { EventCard } from \"../event/event-card\";\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst EVENT_HEIGHT = 44; // Height of each event bar\nconst EVENT_GAP = 4; // Gap between stacked events\nconst MIN_ROW_HEIGHT = 56; // Minimum height per user row\nconst ROW_PADDING = 8; // Vertical padding in rows\n\n// Column widths for different modes\nconst MIN_HOUR_COLUMN_WIDTH = 80; // Minimum width of each hour column\nconst MIN_DATE_COLUMN_WIDTH = 100; // Minimum width of each date column (week view)\nconst USER_COLUMN_WIDTH = 140; // Width of user info column\n\n// Dynamic width constants\nconst MIN_EVENT_CARD_WIDTH = 100; // Minimum width for single-column events to be readable\nconst MAX_SINGLE_COL_EVENTS_BEFORE_EXPAND = 2; // If more than this many single-column events in a column, expand it\n\n// Default hours to show\nconst DEFAULT_START_HOUR = 8;\nconst DEFAULT_END_HOUR = 18;\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface TimelineUser {\n id: string;\n name: string;\n avatar?: string | undefined;\n email?: string | undefined;\n}\n\ninterface PositionedEvent<TData> {\n event: CalendarEvent<TData>;\n startCol: number;\n spanCols: number;\n stackIndex: number; // Vertical position in stack\n}\n\ninterface UserRow<TData> {\n user: TimelineUser;\n events: PositionedEvent<TData>[];\n maxStack: number; // Maximum number of stacked events\n}\n\ninterface HourColumn {\n hour: number;\n dayIndex: number; // Which day (0, 1, 2 for 3-day)\n date: Date;\n}\n\n// ============================================================================\n// PROPS\n// ============================================================================\n\nexport interface TimelineViewProps<TData = Record<string, unknown>> {\n /** Number of days to display - 1 for day, 3 for 3-day, 7 for week */\n daysToShow?: 1 | 3 | 7;\n\n /** Events to display */\n events: CalendarEvent<TData>[];\n\n /** Users/resources to display as rows */\n users?: ICalendarUser[];\n\n /**\n * Resources that should always be rendered as rows even if they have no events.\n * Rows for these resources without any events appear at the bottom of the list,\n * after all event-containing rows. If a resource listed here also has events in\n * the provided `events`, its row is positioned naturally among the event rows\n * (not forced to the bottom) and the events are still attached to it.\n *\n * Intended to be wired by the calendar only for resource views\n * (`resource-day`, `resource-week`).\n */\n alwaysShowResources?: ICalendarUser[];\n\n /** Currently selected/focused date */\n selectedDate?: Date;\n\n /** Callback when selected date changes */\n onDateChange?: (date: Date) => void;\n\n /** Callback when an event is clicked */\n onEventClick?: (event: CalendarEvent<TData>) => void;\n\n /** Visible hours range */\n visibleHours?: { from: number; to: number };\n\n /** Additional CSS class */\n className?: string;\n\n /** Function to get user ID from event (defaults to checking event.data.userId) */\n getEventUserId?: (event: CalendarEvent<TData>) => string | undefined;\n\n /** Custom popover content for events */\n renderPopover?:\n | ((props: {\n event: CalendarEvent<TData>;\n onClose: () => void;\n }) => React.ReactNode)\n | undefined;\n\n\n /**\n * Callback when a user clicks an empty time slot.\n * Receives the date, hour, and resource (user) ID.\n */\n onSlotClick?: ((date: Date, hour?: number, resourceId?: string) => void) | undefined;\n\n /**\n * Callback after a user drags to select a time range on the timeline.\n * The result includes `resourceId` identifying which user row was selected.\n */\n onSlotSelect?: ((selection: ISelectionResult) => void) | undefined;\n\n /**\n * Enable HTML5 drag & drop for events in the timeline.\n * When `true`, events can be dragged to a different time slot or resource row.\n * Requires the calendar to be wrapped in a `DragDropProvider` (automatic when\n * using `<InnoCalendar>`).\n *\n * @default true\n */\n enableDrag?: boolean;\n\n /**\n * Visual configuration for the resource (left) column.\n * Combines a name-rendering variant (`text` / `marquee`) with an\n * orthogonal `showAvatar` sub-variant that applies to both.\n *\n * @default { variant: 'text', showAvatar: true }\n */\n resourceColumnConfig?: IResourceColumnConfig;\n}\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Get initials from name\n */\nfunction getInitials(name: string): string {\n return name\n .split(\" \")\n .map((n) => n[0])\n .join(\"\")\n .toUpperCase()\n .slice(0, 2);\n}\n\n/**\n * Generate array of dates for timeline columns (week view)\n */\nfunction generateDateColumns(startDate: Date, numDays: number): Date[] {\n const dates: Date[] = [];\n for (let i = 0; i < numDays; i++) {\n const date = new Date(startDate);\n date.setDate(date.getDate() + i);\n dates.push(date);\n }\n return dates;\n}\n\n/**\n * Generate hour columns for day/3-day views\n */\nfunction generateHourColumns(\n dates: Date[],\n startHour: number,\n endHour: number,\n): HourColumn[] {\n const columns: HourColumn[] = [];\n dates.forEach((date, dayIndex) => {\n for (let hour = startHour; hour < endHour; hour++) {\n columns.push({ hour, dayIndex, date });\n }\n });\n return columns;\n}\n\n/**\n * Format hour for display in 24h format (e.g., \"09:00\", \"14:00\")\n */\nfunction formatHour(hour: number): string {\n return `${hour.toString().padStart(2, \"0\")}:00`;\n}\n\n/**\n * Format date for column header (e.g., \"Mon 05\")\n */\nfunction formatColumnDate(date: Date): { day: string; date: string } {\n const dayName = date.toLocaleDateString(\"en-US\", { weekday: \"short\" });\n const dateNum = String(date.getDate()).padStart(2, \"0\");\n return { day: dayName, date: dateNum };\n}\n\n/**\n * Format full date for day header\n */\nfunction formatDayHeader(date: Date): string {\n return date.toLocaleDateString(\"en-US\", {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n });\n}\n\n// formatDateRange removed - not currently used but kept for future reference\n// function formatDateRange(startDate: Date, endDate: Date): string { ... }\n\n/**\n * Calculate stack positions for overlapping events\n * Returns events with their stack index (vertical position)\n */\nfunction calculateEventStacks<TData>(\n events: Array<{\n event: CalendarEvent<TData>;\n startCol: number;\n spanCols: number;\n }>,\n): PositionedEvent<TData>[] {\n // Sort by start column, then by span (longer events first)\n const sorted = [...events].sort((a, b) => {\n if (a.startCol !== b.startCol) return a.startCol - b.startCol;\n return b.spanCols - a.spanCols;\n });\n\n const result: PositionedEvent<TData>[] = [];\n const stacks: Array<number> = []; // End column of each stack level\n\n for (const item of sorted) {\n // Find first available stack level\n let stackIndex = 0;\n while (\n stacks[stackIndex] !== undefined &&\n (stacks[stackIndex] as number) > item.startCol\n ) {\n stackIndex++;\n }\n\n // Assign to this stack level\n stacks[stackIndex] = item.startCol + item.spanCols;\n result.push({\n ...item,\n stackIndex,\n });\n }\n\n return result;\n}\n\n/**\n * Position an event on the hour-mode grid (day / 3-day / week timelines).\n *\n * Returns a SINGLE continuous span — `startCol` on the first visible day the\n * event touches through `startCol + spanCols` on the last. A multi-day event\n * used to be emitted once per overlapping day, which produced duplicate React\n * keys (every segment shared `event.id`) and repeated the title/time label on\n * each day. Collapsing to one span renders it as a single bar that also covers\n * the hidden night hours between days — which is accurate, the event runs\n * through them. Single-day events touch exactly one day, so they yield the\n * same start/span they always did.\n *\n * Columns are fractional so an 08:15 start lands a quarter into the 08:00\n * column instead of snapping to a whole hour. Returns `null` when no visible\n * day contributes a slice (event entirely outside the window or its visible\n * portion falls outside working hours).\n */\nfunction computeHourModeSpan<TData>(\n event: CalendarEvent<TData>,\n dateColumns: Date[],\n startHour: number,\n endHour: number,\n hoursPerDay: number,\n): { startCol: number; spanCols: number } | null {\n const eventStartHour =\n event.startDate.getHours() + event.startDate.getMinutes() / 60;\n const eventEndHour =\n event.endDate.getHours() + event.endDate.getMinutes() / 60;\n\n let spanStartCol = Number.POSITIVE_INFINITY;\n let spanEndCol = Number.NEGATIVE_INFINITY;\n\n for (let dayIdx = 0; dayIdx < dateColumns.length; dayIdx++) {\n const dayDate = dateColumns[dayIdx]!;\n const dayStart = startOfDay(dayDate);\n const dayEnd = endOfDay(dayDate);\n\n // Skip days the event doesn't overlap\n if (!(event.startDate <= dayEnd && event.endDate >= dayStart)) continue;\n\n // Clip the event to this day's working hours: the event's own start hour\n // only applies on the day it actually begins, its end hour only on the\n // day it ends; interior days span the full working window.\n let startHourInDay =\n event.startDate >= dayStart\n ? Math.max(startHour, eventStartHour)\n : startHour;\n let endHourInDay =\n event.endDate <= dayEnd ? Math.min(endHour, eventEndHour) : endHour;\n\n // Clamp to the visible hours range\n startHourInDay = Math.max(startHour, Math.min(endHour, startHourInDay));\n endHourInDay = Math.max(startHour, Math.min(endHour, endHourInDay));\n\n if (endHourInDay > startHourInDay) {\n const dayStartCol = dayIdx * hoursPerDay + (startHourInDay - startHour);\n const dayEndCol = dayIdx * hoursPerDay + (endHourInDay - startHour);\n spanStartCol = Math.min(spanStartCol, dayStartCol);\n spanEndCol = Math.max(spanEndCol, dayEndCol);\n }\n }\n\n if (spanEndCol > spanStartCol) {\n return { startCol: spanStartCol, spanCols: spanEndCol - spanStartCol };\n }\n return null;\n}\n\n// ============================================================================\n// AVATAR COMPONENT (inline for zero dependencies)\n// ============================================================================\n\ninterface AvatarProps {\n src?: string | undefined;\n alt?: string | undefined;\n fallback: string;\n className?: string | undefined;\n}\n\nfunction Avatar({ src, alt, fallback, className }: AvatarProps) {\n return (\n <div\n className={cn(\n \"relative flex shrink-0 overflow-hidden rounded-sm border bg-muted\",\n className,\n )}\n >\n {src ? (\n <img\n src={src}\n alt={alt}\n className=\"aspect-square h-full w-full object-cover\"\n />\n ) : (\n <div className=\"flex h-full w-full items-center justify-center bg-muted text-muted-foreground\">\n {fallback}\n </div>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// MARQUEE TEXT COMPONENT\n// ============================================================================\n\ninterface MarqueeTextProps {\n text: string;\n className?: string;\n}\n\nconst MARQUEE_PX_PER_SECOND = 18; // scroll speed when overflowing — slow enough to read comfortably\nconst MARQUEE_MIN_DURATION = 10; // never faster than this many seconds per loop\nconst MARQUEE_GAP_PX = 32; // visual gap between text repetitions (matches CSS)\n\n/**\n * Horizontally scrolls long text only when it actually overflows its\n * container. When the text fits, it renders as a single static span — so\n * the same component is safe for short names without any animation cost.\n *\n * The duplicate trailing span + a -50% transform keeps the loop seamless.\n * Animation is paused on hover/focus and disabled entirely under\n * `prefers-reduced-motion` (handled by CSS).\n */\nfunction MarqueeText({ text, className }: MarqueeTextProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n const measureRef = useRef<HTMLSpanElement>(null);\n const [state, setState] = useState<{ active: boolean; durationSec: number }>({\n active: false,\n durationSec: 0,\n });\n\n useLayoutEffect(() => {\n const container = containerRef.current;\n const measure = measureRef.current;\n if (!container || !measure) return;\n\n const update = () => {\n // Use offsetWidth on the measure span (single copy, no gap), so the\n // measurement stays stable regardless of whether the duplicate is\n // currently mounted.\n const textWidth = measure.offsetWidth;\n const containerWidth = container.clientWidth;\n // +1 tolerance for sub-pixel rounding noise\n if (textWidth > containerWidth + 1) {\n const distance = textWidth + MARQUEE_GAP_PX;\n const durationSec = Math.max(\n MARQUEE_MIN_DURATION,\n distance / MARQUEE_PX_PER_SECOND,\n );\n setState((prev) =>\n prev.active && Math.abs(prev.durationSec - durationSec) < 0.1\n ? prev\n : { active: true, durationSec },\n );\n } else {\n setState((prev) => (prev.active ? { active: false, durationSec: 0 } : prev));\n }\n };\n\n update();\n const ro = new ResizeObserver(update);\n ro.observe(container);\n ro.observe(measure);\n return () => ro.disconnect();\n // `text` re-runs the measurement when the prop changes; the effect reads\n // it indirectly through the DOM (measure.offsetWidth), so the linter\n // can't see the dependency.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [text]);\n\n return (\n <div\n ref={containerRef}\n className={cn(\n \"ic-marquee relative min-w-0 overflow-hidden\",\n state.active && \"ic-marquee--active\",\n className,\n )}\n >\n <div\n className=\"ic-marquee-track inline-flex whitespace-nowrap will-change-transform\"\n style={\n state.active ? { animationDuration: `${state.durationSec}s` } : undefined\n }\n >\n <span ref={measureRef} className=\"ic-marquee-copy\">\n {text}\n </span>\n {state.active && (\n <span aria-hidden=\"true\" className=\"ic-marquee-copy\">\n {text}\n </span>\n )}\n </div>\n </div>\n );\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nconst DEFAULT_DAYS_TO_SHOW = 7;\n\nexport function TimelineView<TData = Record<string, unknown>>({\n daysToShow = DEFAULT_DAYS_TO_SHOW,\n events,\n users = [],\n alwaysShowResources,\n selectedDate: selectedDateProp,\n onDateChange: _onDateChange,\n onEventClick,\n onSlotClick,\n onSlotSelect,\n visibleHours,\n className,\n getEventUserId,\n renderPopover,\n enableDrag = true,\n resourceColumnConfig,\n}: TimelineViewProps<TData>) {\n // Defaults are intentionally smarter than the inherited package behaviour:\n // - `marquee` so long resource names auto-scroll on overflow without the\n // consumer having to opt in.\n // - `auto` avatar so resources with no image URL render no chip instead of\n // a meaningless initials placeholder.\n const resourceVariant = resourceColumnConfig?.variant ?? \"marquee\";\n const showAvatarMode: boolean | \"auto\" =\n resourceColumnConfig?.showAvatar ?? \"auto\";\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Drag & drop context (optional — works without DragDropProvider)\n const dragDrop = useOptionalDragDrop();\n\n // ========================================================================\n // SLOT SELECTION STATE (click-to-create & drag-to-select)\n // ========================================================================\n\n const [selection, setSelection] = useState<{\n resourceId: string;\n startCol: number;\n endCol: number;\n isSelecting: boolean;\n } | null>(null);\n\n /** Whether any pointer button is currently held down for selection */\n const isSelectingRef = useRef(false);\n\n // ========================================================================\n // DROP TARGET HIGHLIGHT STATE\n // ========================================================================\n\n const [dropHighlight, setDropHighlight] = useState<{\n resourceId: string;\n colIndex: number;\n spanCols: number;\n } | null>(null);\n\n // Use provided selectedDate or default to today\n const selectedDate = selectedDateProp ?? new Date();\n\n // Determine if we're in hour mode - all timeline views now show hours\n const isHourMode = true; // Always show hours in timeline views\n const startHour = visibleHours?.from ?? DEFAULT_START_HOUR;\n const endHour = visibleHours?.to ?? DEFAULT_END_HOUR;\n const hoursPerDay = endHour - startHour;\n\n // Calculate start date based on view type\n const viewStartDate = useMemo(() => {\n const date = new Date(selectedDate);\n // For 1-day or 3-day, just use the selected date\n if (daysToShow === 1 || daysToShow === 3) {\n date.setHours(0, 0, 0, 0);\n return date;\n }\n // For week view, start from beginning of week (Monday)\n const dayOfWeek = date.getDay();\n const diff = dayOfWeek === 0 ? -6 : 1 - dayOfWeek; // Monday start\n date.setDate(date.getDate() + diff);\n date.setHours(0, 0, 0, 0);\n return date;\n }, [selectedDate, daysToShow]);\n\n // Generate date columns\n const dateColumns = useMemo(\n () => generateDateColumns(viewStartDate, daysToShow),\n [viewStartDate, daysToShow],\n );\n\n // Generate hour columns for hour mode\n const hourColumns = useMemo(\n () =>\n isHourMode ? generateHourColumns(dateColumns, startHour, endHour) : [],\n [isHourMode, dateColumns, startHour, endHour],\n );\n\n // Default function to get user ID from event\n // Reads from event.resourceId first (standard CalendarEvent field),\n // then falls back to event.data, event.user, and event.participants\n // for backward compatibility.\n const defaultGetEventUserId = (\n event: CalendarEvent<TData>,\n ): string | undefined => {\n // 0. event.resourceId (standard CalendarEvent field — always preferred)\n if (event.resourceId) return event.resourceId;\n // 1. event.data (recommended location for custom data)\n const data = event.data as Record<string, unknown> | undefined;\n if (data?.userId) return String(data.userId);\n if (\n data?.user &&\n typeof data.user === \"object\" &&\n (data.user as { id?: string }).id\n ) {\n return String((data.user as { id: string }).id);\n }\n // 2. Deprecated top-level event.user (backward compat)\n if (event.user?.id) return event.user.id;\n // 3. Participants fallback\n if (event.participants?.[0]?.id) return event.participants[0].id;\n return undefined;\n };\n\n const getUserIdFromEvent = getEventUserId ?? defaultGetEventUserId;\n\n // Build user list from both provided users and event participants\n const effectiveUsers = useMemo(() => {\n const userMap = new Map<string, TimelineUser>();\n\n // Add users from props\n for (const user of users) {\n userMap.set(user.id, {\n id: user.id,\n name: user.name,\n avatar: user.avatar ?? undefined,\n email: user.email,\n });\n }\n\n // Also extract unique users from events\n for (const event of events) {\n // 1. Check event.data.user (recommended location)\n const eventData = event.data as Record<string, unknown> | undefined;\n const dataUser = eventData?.user as\n | { id?: string; name?: string; avatar?: string; email?: string }\n | undefined;\n if (dataUser?.id && !userMap.has(dataUser.id)) {\n userMap.set(dataUser.id, {\n id: dataUser.id,\n name: dataUser.name ?? \"\",\n avatar: dataUser.avatar ?? undefined,\n email: dataUser.email,\n });\n }\n // 2. Deprecated top-level event.user (backward compat)\n if (event.user?.id && !userMap.has(event.user.id)) {\n userMap.set(event.user.id, {\n id: event.user.id,\n name: event.user.name,\n avatar: event.user.avatar ?? undefined,\n email: event.user.email,\n });\n }\n // Also check participants\n for (const participant of event.participants || []) {\n if (participant.id && !userMap.has(participant.id)) {\n userMap.set(participant.id, {\n id: participant.id,\n name: participant.name,\n avatar: participant.avatar ?? undefined,\n email: participant.email,\n });\n }\n }\n }\n\n return Array.from(userMap.values());\n }, [users, events]);\n\n // Build user rows with positioned events\n const userRows = useMemo(() => {\n const rows: UserRow<TData>[] = [];\n\n // Group events by user\n const eventsByUser = new Map<string, CalendarEvent<TData>[]>();\n for (const user of effectiveUsers) {\n eventsByUser.set(user.id, []);\n }\n eventsByUser.set(\"unassigned\", []);\n\n for (const event of events) {\n const userId = getUserIdFromEvent(event) ?? \"unassigned\";\n const list = eventsByUser.get(userId) ?? eventsByUser.get(\"unassigned\")!;\n list.push(event);\n }\n\n // Helper to position events\n const positionEventsForUser = (userEvents: CalendarEvent<TData>[]) => {\n const rawPositioned: Array<{\n event: CalendarEvent<TData>;\n startCol: number;\n spanCols: number;\n }> = [];\n\n for (const event of userEvents) {\n if (isHourMode) {\n // Hour-based positioning (day / 3-day / week timelines). One span\n // per event — multi-day events render as a single continuous bar\n // rather than one duplicate-keyed segment per day.\n const span = computeHourModeSpan(\n event,\n dateColumns,\n startHour,\n endHour,\n hoursPerDay,\n );\n if (span) {\n rawPositioned.push({ event, ...span });\n }\n } else {\n // Date-based positioning for week view\n const eventStart = startOfDay(event.startDate);\n const eventEnd = endOfDay(event.endDate);\n\n let startCol = -1;\n let endCol = -1;\n\n for (let i = 0; i < dateColumns.length; i++) {\n const colDate = dateColumns[i]!;\n const colStart = startOfDay(colDate);\n const colEnd = endOfDay(colDate);\n\n if (eventStart <= colEnd && eventEnd >= colStart) {\n if (startCol === -1) startCol = i;\n endCol = i;\n }\n }\n\n if (startCol !== -1) {\n rawPositioned.push({\n event,\n startCol,\n spanCols: endCol - startCol + 1,\n });\n }\n }\n }\n\n return rawPositioned;\n };\n\n // Process each user\n for (const user of effectiveUsers) {\n const userEvents = eventsByUser.get(user.id) ?? [];\n const rawPositioned = positionEventsForUser(userEvents);\n const positionedEvents = calculateEventStacks(rawPositioned);\n const maxStack = positionedEvents.reduce(\n (max, e) => Math.max(max, e.stackIndex + 1),\n 0,\n );\n\n rows.push({\n user,\n events: positionedEvents,\n maxStack: Math.max(maxStack, 1),\n });\n }\n\n // Add unassigned row if needed\n const unassignedEvents = eventsByUser.get(\"unassigned\") ?? [];\n if (unassignedEvents.length > 0) {\n const rawPositioned = positionEventsForUser(unassignedEvents);\n const positionedEvents = calculateEventStacks(rawPositioned);\n const maxStack = positionedEvents.reduce(\n (max, e) => Math.max(max, e.stackIndex + 1),\n 0,\n );\n\n rows.push({\n user: {\n id: \"unassigned\",\n name: \"Unassigned\",\n avatar: undefined,\n email: undefined,\n },\n events: positionedEvents,\n maxStack: Math.max(maxStack, 1),\n });\n }\n\n // Append empty rows for alwaysShowResources that have no events and are not\n // already represented. These always appear at the bottom so that rows with\n // events take visual priority.\n if (alwaysShowResources?.length) {\n const existingIds = new Set(rows.map((r) => r.user.id));\n for (const resource of alwaysShowResources) {\n if (existingIds.has(resource.id)) continue;\n rows.push({\n user: {\n id: resource.id,\n name: resource.name,\n avatar: resource.avatar ?? undefined,\n email: resource.email,\n },\n events: [],\n maxStack: 1,\n });\n existingIds.add(resource.id);\n }\n }\n\n return rows;\n }, [\n effectiveUsers,\n events,\n dateColumns,\n isHourMode,\n hoursPerDay,\n startHour,\n endHour,\n getUserIdFromEvent,\n alwaysShowResources,\n ]);\n\n // Count short events per hour-column so we can widen crowded columns.\n // Events fit \"within\" a column when their span ≤ 1 hour — these are the\n // ones at risk of being unreadably narrow if the column stays at minimum\n // width. Keyed by floor(startCol) because fractional starts (e.g. 08:15)\n // still belong to the 08:00 hour bucket for width-budget purposes.\n const singleColEventCounts = useMemo(() => {\n const counts = new Map<number, number>();\n\n for (const row of userRows) {\n for (const pe of row.events) {\n if (pe.spanCols <= 1) {\n const colKey = Math.floor(pe.startCol);\n const currentCount = counts.get(colKey) ?? 0;\n counts.set(colKey, currentCount + 1);\n }\n }\n }\n\n return counts;\n }, [userRows]);\n\n // Calculate dynamic column widths - only expand columns that have single-column events\n // Columns without single-column events stay at minimum width\n const columnWidths = useMemo(() => {\n const totalColumns = isHourMode ? hourColumns.length : dateColumns.length;\n const baseMinWidth = isHourMode\n ? MIN_HOUR_COLUMN_WIDTH\n : MIN_DATE_COLUMN_WIDTH;\n const widths: number[] = [];\n\n for (let col = 0; col < totalColumns; col++) {\n const singleColCount = singleColEventCounts.get(col) ?? 0;\n\n // If this column has single-column events, it needs at least MIN_EVENT_CARD_WIDTH\n // If many single-column events stack in same column, expand further\n if (singleColCount > MAX_SINGLE_COL_EVENTS_BEFORE_EXPAND) {\n // Expand for heavy stacking (similar to week-view logic)\n widths.push(\n MIN_EVENT_CARD_WIDTH +\n (singleColCount - MAX_SINGLE_COL_EVENTS_BEFORE_EXPAND) * 20,\n );\n } else if (singleColCount > 0) {\n // Has single-column events, use MIN_EVENT_CARD_WIDTH\n widths.push(Math.max(baseMinWidth, MIN_EVENT_CARD_WIDTH));\n } else {\n // No single-column events, use base minimum (events spanning multiple columns\n // will still fit because their total width = sum of columns they span)\n widths.push(baseMinWidth);\n }\n }\n\n return widths;\n }, [\n isHourMode,\n hourColumns.length,\n dateColumns.length,\n singleColEventCounts,\n ]);\n\n // Calculate row height based on max stacked events\n const getRowHeight = (maxStack: number) => {\n return Math.max(\n MIN_ROW_HEIGHT,\n maxStack * (EVENT_HEIGHT + EVENT_GAP) + ROW_PADDING * 2,\n );\n };\n // Calculate total width based on dynamic column widths\n const totalWidth =\n USER_COLUMN_WIDTH + columnWidths.reduce((sum, w) => sum + w, 0);\n\n // Get cumulative positions for columns (for event positioning)\n const columnPositions = useMemo(() => {\n const positions: number[] = [0];\n for (let i = 0; i < columnWidths.length; i++) {\n positions.push(positions[i]! + columnWidths[i]!);\n }\n return positions;\n }, [columnWidths]);\n\n // Interpolate a pixel offset for a fractional column index. Events use\n // sub-hour positioning (e.g. col=0.25 for an 08:15 start in an 08:00–\n // anchored column), so direct array indexing won't work — we linearly\n // interpolate between adjacent integer column boundaries.\n const pixelAtCol = useCallback(\n (col: number): number => {\n const maxIdx = columnPositions.length - 1;\n if (col <= 0) return columnPositions[0] ?? 0;\n if (col >= maxIdx) return columnPositions[maxIdx] ?? 0;\n const floor = Math.floor(col);\n const a = columnPositions[floor] ?? 0;\n const b = columnPositions[floor + 1] ?? a;\n return a + (col - floor) * (b - a);\n },\n [columnPositions],\n );\n\n // Auto-scroll to today's time slot on mount\n useLayoutEffect(() => {\n const container = scrollRef.current;\n if (!container) return;\n\n const scrollToToday = () => {\n // Find today's column index\n let todayColIndex = -1;\n const now = new Date();\n const currentHour = now.getHours();\n\n if (isHourMode) {\n // In hour mode, find the column for current hour on today\n for (let i = 0; i < hourColumns.length; i++) {\n const col = hourColumns[i];\n if (col && isToday(col.date) && col.hour <= currentHour && col.hour + 1 > currentHour) {\n todayColIndex = i;\n break;\n }\n }\n // If current hour not in visible range, scroll to first column of today\n if (todayColIndex === -1) {\n for (let i = 0; i < hourColumns.length; i++) {\n const col = hourColumns[i];\n if (col && isToday(col.date)) {\n todayColIndex = i;\n break;\n }\n }\n }\n } else {\n // In date mode, find today's date column\n for (let i = 0; i < dateColumns.length; i++) {\n if (isToday(dateColumns[i]!)) {\n todayColIndex = i;\n break;\n }\n }\n }\n\n // If today is in view, scroll to it\n if (todayColIndex !== -1) {\n const scrollLeft = (columnPositions[todayColIndex] ?? 0) + USER_COLUMN_WIDTH;\n // Center the today column in view (subtract half container width)\n const containerWidth = container.clientWidth;\n const centeredScroll = Math.max(0, scrollLeft - containerWidth / 3);\n\n container.scrollTo({\n left: centeredScroll,\n behavior: 'instant',\n });\n }\n };\n\n // Use double requestAnimationFrame to ensure layout is complete\n requestAnimationFrame(() => {\n requestAnimationFrame(scrollToToday);\n });\n }, [selectedDate, hourColumns, dateColumns, columnPositions, isHourMode]);\n\n // ========================================================================\n // DRAG & DROP HANDLERS\n // ========================================================================\n\n /**\n * Resolve column index AND sub-hour minute from a clientX position.\n * The minute is snapped to 15-minute intervals for UX.\n */\n const resolveColumnAndMinute = useCallback(\n (clientX: number, gridEl: HTMLElement): { colIndex: number; minute: number } | null => {\n const rect = gridEl.getBoundingClientRect();\n const x = clientX - rect.left + gridEl.scrollLeft;\n\n for (let i = 0; i < columnPositions.length - 1; i++) {\n const colStart = columnPositions[i]!;\n const colEnd = columnPositions[i + 1]!;\n if (x >= colStart && x < colEnd) {\n const fraction = (x - colStart) / (colEnd - colStart);\n const rawMinute = Math.floor(fraction * 60);\n const snappedMinute = Math.round(rawMinute / 15) * 15;\n return { colIndex: i, minute: Math.min(snappedMinute, 45) };\n }\n }\n return null;\n },\n [columnPositions],\n );\n\n /**\n * Build a Date from a column index, optionally with minutes.\n */\n const dateFromColumn = useCallback(\n (colIndex: number, minute?: number): { date: Date; hour?: number } => {\n if (isHourMode && hourColumns[colIndex]) {\n const col = hourColumns[colIndex]!;\n const d = new Date(col.date);\n d.setHours(col.hour, minute ?? 0, 0, 0);\n return { date: d, hour: col.hour };\n }\n if (!isHourMode && dateColumns[colIndex]) {\n return { date: new Date(dateColumns[colIndex]!) };\n }\n return { date: new Date() };\n },\n [isHourMode, hourColumns, dateColumns],\n );\n\n /** Handle dragover on a resource row — update preview position + highlight */\n const handleRowDragOver = useCallback(\n (e: React.DragEvent<HTMLDivElement>, userId: string) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n if (!dragDrop?.isDragging || !dragDrop.dragState) return;\n\n const gridEl = e.currentTarget;\n const resolved = resolveColumnAndMinute(e.clientX, gridEl);\n if (!resolved) return;\n\n const { colIndex, minute } = resolved;\n const { date, hour } = dateFromColumn(colIndex, minute);\n dragDrop.updateDragPreview(date, hour, minute, userId);\n\n // Calculate how many columns the dragged event spans for highlight\n const { originalStartDate, originalEndDate } = dragDrop.dragState;\n const durationMs = originalEndDate.getTime() - originalStartDate.getTime();\n const totalCols = isHourMode ? hourColumns.length : dateColumns.length;\n\n let spanCols: number;\n if (isHourMode) {\n const durationHours = durationMs / (1000 * 60 * 60);\n spanCols = Math.max(1, Math.ceil(durationHours));\n } else {\n const durationDays = durationMs / (1000 * 60 * 60 * 24);\n spanCols = Math.max(1, Math.ceil(durationDays));\n }\n\n // Clamp to available columns\n spanCols = Math.min(spanCols, totalCols - colIndex);\n\n setDropHighlight({ resourceId: userId, colIndex, spanCols });\n },\n [dragDrop, resolveColumnAndMinute, dateFromColumn, isHourMode, hourColumns.length, dateColumns.length],\n );\n\n /** Clear drop highlight when dragging leaves the row entirely */\n const handleRowDragLeave = useCallback(\n (e: React.DragEvent<HTMLDivElement>) => {\n const relatedTarget = e.relatedTarget as HTMLElement | null;\n if (!e.currentTarget.contains(relatedTarget)) {\n setDropHighlight(null);\n }\n },\n [],\n );\n\n /** Handle drop on a resource row */\n const handleRowDrop = useCallback(\n (e: React.DragEvent<HTMLDivElement>, _userId: string) => {\n e.preventDefault();\n setDropHighlight(null);\n if (!dragDrop?.isDragging) return;\n dragDrop.endDrag();\n },\n [dragDrop],\n );\n\n // ========================================================================\n // SLOT SELECTION HANDLERS (click-to-create & drag-to-select)\n // ========================================================================\n\n /**\n * Check whether a cell is within the current selection range for a given row.\n */\n const isCellSelected = useCallback(\n (resourceId: string, colIndex: number): boolean => {\n if (!selection || selection.resourceId !== resourceId) return false;\n const minCol = Math.min(selection.startCol, selection.endCol);\n const maxCol = Math.max(selection.startCol, selection.endCol);\n return colIndex >= minCol && colIndex <= maxCol;\n },\n [selection],\n );\n\n /**\n * Check whether a cell is within the drop highlight range.\n */\n const isCellDropTarget = useCallback(\n (resourceId: string, colIndex: number): boolean => {\n if (!dropHighlight || dropHighlight.resourceId !== resourceId) return false;\n return (\n colIndex >= dropHighlight.colIndex &&\n colIndex < dropHighlight.colIndex + dropHighlight.spanCols\n );\n },\n [dropHighlight],\n );\n\n /** Start slot selection on pointer-down */\n const handleCellPointerDown = useCallback(\n (resourceId: string, colIndex: number, e: React.PointerEvent) => {\n // Only primary button (left click) or touch\n if (e.button !== 0 && e.pointerType === 'mouse') return;\n if (!(onSlotSelect || onSlotClick)) return;\n e.preventDefault();\n isSelectingRef.current = true;\n setSelection({ resourceId, startCol: colIndex, endCol: colIndex, isSelecting: true });\n },\n [onSlotSelect, onSlotClick],\n );\n\n /** Extend selection on pointer-enter while button is held */\n const handleCellPointerEnter = useCallback(\n (resourceId: string, colIndex: number, e: React.PointerEvent) => {\n if (!isSelectingRef.current) return;\n if (!selection || selection.resourceId !== resourceId) return;\n if (e.buttons === 0) {\n // Button released outside — finish\n isSelectingRef.current = false;\n return;\n }\n setSelection((prev) => (prev ? { ...prev, endCol: colIndex } : null));\n },\n [selection],\n );\n\n /** Complete selection on pointer-up and fire callbacks */\n const handleCellPointerUp = useCallback(() => {\n if (!isSelectingRef.current || !selection) return;\n isSelectingRef.current = false;\n\n const minCol = Math.min(selection.startCol, selection.endCol);\n const maxCol = Math.max(selection.startCol, selection.endCol);\n\n const startInfo = dateFromColumn(minCol);\n const endInfo = dateFromColumn(maxCol);\n\n // Build start date\n const startDate = new Date(startInfo.date);\n\n // Build end date — end of the last selected column\n const endDate = new Date(endInfo.date);\n if (isHourMode && endInfo.hour !== undefined) {\n endDate.setHours(endInfo.hour + 1, 0, 0, 0);\n } else if (!isHourMode) {\n // Date mode: end of the selected day\n endDate.setHours(23, 59, 59, 999);\n }\n\n const result: ISelectionResult = {\n startDate,\n endDate,\n resourceId: selection.resourceId,\n };\n\n // Single-column click — also fire onSlotClick for compatibility\n if (minCol === maxCol && onSlotClick) {\n onSlotClick(startInfo.date, startInfo.hour, selection.resourceId);\n }\n\n onSlotSelect?.(result);\n\n // Visual feedback: keep selection visible briefly, then clear\n setSelection((prev) => (prev ? { ...prev, isSelecting: false } : null));\n setTimeout(() => setSelection(null), 150);\n }, [selection, dateFromColumn, isHourMode, onSlotClick, onSlotSelect]);\n\n // Global pointer-up listener to finish selection even when released outside\n useEffect(() => {\n const handleGlobalPointerUp = () => {\n if (isSelectingRef.current) {\n handleCellPointerUp();\n }\n };\n window.addEventListener('pointerup', handleGlobalPointerUp);\n window.addEventListener('pointercancel', handleGlobalPointerUp);\n return () => {\n window.removeEventListener('pointerup', handleGlobalPointerUp);\n window.removeEventListener('pointercancel', handleGlobalPointerUp);\n };\n }, [handleCellPointerUp]);\n\n // Clear drop highlight when drag ends externally\n useEffect(() => {\n if (!dragDrop?.isDragging) {\n setDropHighlight(null);\n }\n }, [dragDrop?.isDragging]);\n\n return (\n <div className={cn(\"flex h-full flex-col\", className)}>\n {/* Navigation header */}\n <div className=\"ic-timeline-scroll-container flex-1\" ref={scrollRef}>\n <div className=\"relative\" style={{ minWidth: totalWidth }}>\n {/* Header row(s) */}\n {isHourMode ? (\n // Hour mode: Day headers + Hour sub-headers - sticky wrapper with flex child (sticky + flex breaks sticky)\n <div className=\"ic-timeline-header sticky top-0 z-20 border-b bg-background\">\n {daysToShow > 1 ? (\n // Multi-day: Resources cell spans both day-header + hour-header rows\n <div className=\"flex\">\n {/* Resources column — spans full height of both rows */}\n <div\n className=\"flex shrink-0 items-center justify-center border-r bg-background px-2 sticky left-0 z-10\"\n style={{ width: USER_COLUMN_WIDTH }}\n >\n <span className=\"text-[10px] font-medium uppercase text-muted-foreground\">\n Resources\n </span>\n </div>\n {/* Right side: day headers + hour headers stacked */}\n <div className=\"flex min-w-0 flex-col\">\n {/* Day headers row */}\n <div className=\"flex border-b\">\n {dateColumns.map((date, dayIdx) => {\n const today = isToday(date);\n const dayStartCol = dayIdx * hoursPerDay;\n const dayWidth = columnWidths\n .slice(dayStartCol, dayStartCol + hoursPerDay)\n .reduce((sum, w) => sum + w, 0);\n return (\n <div\n key={`day-${date.toISOString()}`}\n className={cn(\n \"flex shrink-0 items-center justify-center border-r py-1.5 font-medium\",\n today\n ? \"bg-primary/10 text-primary\"\n : \"bg-muted/30\",\n )}\n style={{ width: dayWidth }}\n >\n <span className=\"text-xs\">\n {formatDayHeader(date)}\n </span>\n </div>\n );\n })}\n </div>\n {/* Hour headers row */}\n <div className=\"flex\">\n {hourColumns.map((col, idx) => {\n const isFirstOfDay = col.hour === startHour;\n const today = isToday(col.date);\n const colWidth = columnWidths[idx] ?? MIN_HOUR_COLUMN_WIDTH;\n return (\n <div\n key={`hour-${col.dayIndex}-${col.hour}`}\n className={cn(\n \"flex shrink-0 items-center justify-center py-1.5 text-[10px] text-muted-foreground\",\n isFirstOfDay && idx > 0\n ? \"border-l-2 border-l-border\"\n : \"border-r border-r-border/50\",\n today && \"bg-primary/5\",\n )}\n style={{ width: colWidth }}\n >\n {formatHour(col.hour)}\n </div>\n );\n })}\n </div>\n </div>\n </div>\n ) : (\n // Single-day: simple single row\n <div className=\"flex\">\n <div\n className=\"flex shrink-0 items-center border-r bg-background px-2 py-2\"\n style={{ width: USER_COLUMN_WIDTH }}\n >\n <span className=\"text-[10px] font-medium uppercase text-muted-foreground\">\n Resources\n </span>\n </div>\n {hourColumns.map((col, idx) => {\n const isFirstOfDay = col.hour === startHour;\n const today = isToday(col.date);\n const colWidth = columnWidths[idx] ?? MIN_HOUR_COLUMN_WIDTH;\n return (\n <div\n key={`hour-${col.dayIndex}-${col.hour}`}\n className={cn(\n \"flex shrink-0 items-center justify-center py-1.5 text-[10px] text-muted-foreground\",\n isFirstOfDay && idx > 0\n ? \"border-l-2 border-l-border\"\n : \"border-r border-r-border/50\",\n today && \"bg-primary/5\",\n )}\n style={{ width: colWidth }}\n >\n {formatHour(col.hour)}\n </div>\n );\n })}\n </div>\n )}\n </div>\n ) : (\n // Date mode (week view): Date headers - sticky wrapper with flex child\n <div className=\"ic-timeline-header sticky top-0 z-20 border-b bg-background\">\n <div className=\"flex\">\n {/* User column header - sticky wrapper */}\n <div\n className=\"sticky left-0 z-10\"\n style={{ width: USER_COLUMN_WIDTH }}\n >\n <div className=\"flex h-full items-center border-r bg-background px-2 sm:px-4 py-2\">\n <span className=\"text-[10px] sm:text-xs font-medium uppercase text-muted-foreground\">\n Resources\n </span>\n </div>\n </div>\n\n {/* Date headers - Google Calendar style */}\n {dateColumns.map((date, idx) => {\n const formatted = formatColumnDate(date);\n const today = isToday(date);\n const weekend = isWeekend(date);\n const colWidth = columnWidths[idx] ?? MIN_DATE_COLUMN_WIDTH;\n\n return (\n <div\n key={date.toISOString()}\n className={cn(\n \"flex shrink-0 flex-col items-center justify-center border-r py-2\",\n weekend && \"bg-muted/30\",\n )}\n style={{ width: colWidth }}\n >\n {/* Day name - small uppercase */}\n <span\n className={cn(\n \"text-[11px] font-medium uppercase tracking-wide\",\n today ? \"text-primary\" : \"text-muted-foreground\",\n )}\n >\n {formatted.day}\n </span>\n {/* Date number - circled if today */}\n <span\n className={cn(\n \"flex items-center justify-center rounded-full mt-0.5 transition-colors\",\n \"size-8 text-lg font-normal\",\n today\n ? \"bg-primary text-primary-foreground\"\n : \"text-foreground\",\n )}\n >\n {formatted.date}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n )}\n\n {/* User rows */}\n {userRows.map((row) => {\n const rowHeight = getRowHeight(row.maxStack);\n\n return (\n <div\n key={row.user.id}\n className={cn(\n \"relative flex border-b\",\n )}\n style={{ height: rowHeight }}\n >\n {/* User info cell - sticky wrapper with flex child (sticky + flex breaks sticky) */}\n <div\n className=\"sticky left-0 z-10\"\n style={{ width: USER_COLUMN_WIDTH }}\n >\n <div\n className={cn(\n \"flex h-full items-center gap-2 sm:gap-3 border-r bg-background px-2 sm:px-4\",\n )}\n >\n {(() => {\n // 'auto' → render only when the user actually has an\n // image URL; otherwise the chip would be a meaningless\n // initials placeholder.\n const hasImage = !!row.user.avatar;\n const renderAvatar =\n showAvatarMode === true ||\n (showAvatarMode === \"auto\" && hasImage);\n if (!renderAvatar) return null;\n return (\n <Avatar\n className=\"size-7\"\n src={row.user.avatar}\n alt={row.user.name}\n fallback={getInitials(row.user.name)}\n />\n );\n })()}\n {resourceVariant === \"marquee\" ? (\n <MarqueeText\n text={row.user.name}\n className=\"flex-1 text-xs sm:text-sm font-medium\"\n />\n ) : (\n <span className=\"min-w-0 flex-1 truncate text-xs sm:text-sm font-medium\">\n {row.user.name}\n </span>\n )}\n </div>\n </div>\n\n {/* Date/Hour cells background — interactive for slot selection & drag-drop */}\n <div\n className=\"ic-timeline-grid relative flex\"\n onDragOver={(e) => handleRowDragOver(e, row.user.id)}\n onDragLeave={handleRowDragLeave}\n onDrop={(e) => handleRowDrop(e, row.user.id)}\n >\n {isHourMode\n ? // Hour mode cells — interactive buttons for slot selection\n hourColumns.map((col, idx) => {\n const isFirstOfDay = col.hour === startHour && idx > 0;\n const colWidth =\n columnWidths[idx] ?? MIN_HOUR_COLUMN_WIDTH;\n const cellSelected = isCellSelected(row.user.id, idx);\n const cellDropTarget = isCellDropTarget(row.user.id, idx);\n const isInteractive = !!(onSlotSelect || onSlotClick);\n return (\n <div\n key={`cell-${col.dayIndex}-${col.hour}`}\n role={isInteractive ? 'button' : undefined}\n tabIndex={isInteractive ? 0 : undefined}\n aria-label={\n isInteractive\n ? `Select ${formatHour(col.hour)} on ${col.date.toLocaleDateString()} for ${row.user.name}`\n : undefined\n }\n onPointerDown={(e) => handleCellPointerDown(row.user.id, idx, e)}\n onPointerEnter={(e) => handleCellPointerEnter(row.user.id, idx, e)}\n onPointerUp={handleCellPointerUp}\n onKeyDown={(e) => {\n if (isInteractive && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n const info = dateFromColumn(idx);\n onSlotClick?.(info.date, info.hour, row.user.id);\n onSlotSelect?.({\n startDate: info.date,\n endDate: (() => {\n const end = new Date(info.date);\n if (info.hour !== undefined) end.setHours(info.hour + 1, 0, 0, 0);\n return end;\n })(),\n resourceId: row.user.id,\n });\n }\n }}\n className={cn(\n \"shrink-0 select-none touch-none transition-colors\",\n isInteractive && \"cursor-pointer\",\n isFirstOfDay\n ? \"border-l-2 border-l-border\"\n : \"border-r border-r-border/50\",\n isToday(col.date) && \"bg-primary/5\",\n // Hover — subtle feedback (only when not selecting or dragging)\n isInteractive && !selection?.isSelecting && !dragDrop?.isDragging && \"hover:bg-blue-50/60\",\n // Slot selection highlight\n cellSelected && \"bg-blue-100/70\",\n // Drop target highlight\n cellDropTarget && \"bg-primary/20 ring-2 ring-primary ring-inset\",\n )}\n style={{ width: colWidth }}\n />\n );\n })\n : // Date mode cells — interactive buttons for slot selection\n dateColumns.map((date, idx) => {\n const colWidth =\n columnWidths[idx] ?? MIN_DATE_COLUMN_WIDTH;\n const cellSelected = isCellSelected(row.user.id, idx);\n const cellDropTarget = isCellDropTarget(row.user.id, idx);\n const isInteractive = !!(onSlotSelect || onSlotClick);\n return (\n <div\n key={date.toISOString()}\n role={isInteractive ? 'button' : undefined}\n tabIndex={isInteractive ? 0 : undefined}\n aria-label={\n isInteractive\n ? `Select ${date.toLocaleDateString()} for ${row.user.name}`\n : undefined\n }\n onPointerDown={(e) => handleCellPointerDown(row.user.id, idx, e)}\n onPointerEnter={(e) => handleCellPointerEnter(row.user.id, idx, e)}\n onPointerUp={handleCellPointerUp}\n onKeyDown={(e) => {\n if (isInteractive && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n const info = dateFromColumn(idx);\n onSlotClick?.(info.date, undefined, row.user.id);\n onSlotSelect?.({\n startDate: info.date,\n endDate: (() => {\n const end = new Date(info.date);\n end.setHours(23, 59, 59, 999);\n return end;\n })(),\n resourceId: row.user.id,\n });\n }\n }}\n className={cn(\n \"shrink-0 select-none touch-none transition-colors\",\n isInteractive && \"cursor-pointer\",\n \"border-r\",\n isWeekend(date) && \"bg-muted/30\",\n isToday(date) && \"bg-primary/5\",\n // Hover — subtle feedback\n isInteractive && !selection?.isSelecting && !dragDrop?.isDragging && \"hover:bg-blue-50/60\",\n // Slot selection highlight\n cellSelected && \"bg-blue-100/70\",\n // Drop target highlight\n cellDropTarget && \"bg-primary/20 ring-2 ring-primary ring-inset\",\n )}\n style={{ width: colWidth }}\n />\n );\n })}\n\n {/* Event bars using EventCard compact variant */}\n {row.events.map((pe) => {\n // Interpolate pixel positions for sub-hour precision —\n // pe.startCol / pe.spanCols are fractional (e.g. 0.25 for\n // an 08:15 start), so direct array indexing wouldn't land\n // on the right pixel.\n const startPos = pixelAtCol(pe.startCol);\n const endPos = pixelAtCol(pe.startCol + pe.spanCols);\n const left = startPos + 2;\n const width = endPos - startPos - 4; // 4px for margins\n const top =\n ROW_PADDING + pe.stackIndex * (EVENT_HEIGHT + EVENT_GAP);\n\n // Wrapper-level drag fallback. The inner <EventCard> is\n // draggable and, being innermost, captures the drag first;\n // this wrapper only matters when something inside it does\n // not set draggable itself.\n const isPlaceholder =\n (pe.event.data as Record<string, unknown> | undefined)\n ?.isPlaceholder === true;\n const eventIsPast =\n pe.event.endDate < startOfDay(new Date());\n const eventCanDrag =\n enableDrag &&\n !!dragDrop &&\n !pe.event.isCanceled &&\n !eventIsPast &&\n !isPlaceholder;\n\n return (\n // biome-ignore lint/a11y/noStaticElementInteractions: drag is a fallback for slot overrides; primary keyboard/click interaction lives on the inner EventCard (which has role=\"button\")\n <div\n key={pe.event.id}\n className={cn(\n \"absolute\",\n eventCanDrag &&\n \"cursor-grab active:cursor-grabbing\",\n )}\n style={{\n left,\n width: Math.max(width, 0), // No forced minimum - columns are guaranteed wide enough\n top,\n height: EVENT_HEIGHT,\n }}\n draggable={eventCanDrag || undefined}\n onDragStart={\n eventCanDrag\n ? (e) => {\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\n \"text/plain\",\n pe.event.id,\n );\n dragDrop?.startDrag(pe.event);\n }\n : undefined\n }\n >\n <EventCard\n event={pe.event}\n variant=\"compact\"\n enableDrag={enableDrag}\n onClick={onEventClick}\n renderPopover={renderPopover}\n className=\"h-full w-full\"\n />\n </div>\n );\n })}\n </div>\n </div>\n );\n })}\n\n {/* Empty state */}\n {userRows.length === 0 && (\n <div className=\"flex items-center justify-center py-20 text-muted-foreground\">\n No users or events to display\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport default TimelineView;\n","/**\n * Week View Component\n *\n * 7-day grid showing a full week with time slots.\n * Features:\n * - Day columns with hour rows\n * - Multi-day event spanning\n * - Current time indicator\n * - Working hours highlighting\n * - Drag to select time range\n *\n * Ported from agenda-v2 to maintain exact styling parity.\n */\n\nimport { useCallback, useLayoutEffect, useMemo, useRef } from 'react';\nimport { DEFAULT_HOUR_HEIGHT } from '../../core/constants';\nimport { useOptionalSlotSelection } from '../../core/context/slot-selection-context';\nimport type {\n\tCalendarEvent,\n\tITimeSlot,\n\tIVisibleHours,\n\tTBadgeVariant,\n\tTOnEventClick,\n\tTOnSlotSelect,\n} from '../../core/types';\nimport {\n\taddDays,\n\tformatHourLabel,\n\tgetVisibleHoursArray,\n\tgetWeekDays,\n\tisToday,\n\tisWorkingHour,\n\tseparateEventsByDuration,\n\ttype TWorkingHours,\n} from '../../core/utils/date-utils';\nimport { getEventsForDay } from '../../core/utils/event-utils';\nimport { calculateOverlappingPositions } from '../../core/utils/position-utils';\nimport { cn } from '../../lib/utils';\nimport { EventBlock } from '../event/event-card';\nimport { TimeSlot } from '../primitives/selectable-slot';\nimport { WeekAllDayRow } from '../primitives/week-all-day-row';\n\n// ============================================================================\n// CONSTANTS (matches agenda-v2)\n// ============================================================================\n\nconst HOUR_HEIGHT = DEFAULT_HOUR_HEIGHT; // single source of truth\nconst HOUR_COLUMN_WIDTH = 56; // narrower for Google Calendar style\nconst DAY_HEADER_HEIGHT = 72; // taller for stacked day/date layout\nconst MIN_DAY_COLUMN_WIDTH = 120; // minimum width per day column\nconst MIN_EVENT_CARD_WIDTH = 100; // minimum width in pixels for event cards to be readable\nconst MAX_EVENTS_BEFORE_EXPAND = 3; // max overlapping events before column expands\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface WeekViewProps<TData = Record<string, unknown>> {\n\t/** Events to display */\n\tevents: CalendarEvent<TData>[];\n\t/** The date (any day in the week to show) */\n\tdate: Date;\n\t/**\n\t * How many columns, starting at `date` rather than at the week's start.\n\t *\n\t * This is what makes Google's \"4 days\" a rolling window: it begins on the day\n\t * you are looking at and moves with you, where a week snaps to Monday.\n\t * Omitted, the calendar week containing `date` is shown.\n\t */\n\tdays?: number;\n\t/** First day of week (0 = Sunday, 1 = Monday) */\n\tweekStartsOn?: 0 | 1;\n\t/** Visible hours range */\n\tvisibleHours?: IVisibleHours;\n\t/** Working hours per day */\n\tworkingHours?: TWorkingHours;\n\t/** Slot duration in minutes */\n\tslotDuration?: number;\n\t/** Badge variant for events */\n\tbadgeVariant?: TBadgeVariant;\n\t/** Event click handler */\n\tonEventClick?: TOnEventClick<TData>;\n\t/** Slot select handler */\n\tonSlotSelect?: TOnSlotSelect;\n\t/** Day click handler */\n\tonDayClick?: (date: Date) => void;\n\t/** Additional CSS classes */\n\tclassName?: string;\n\t/** Custom event renderer */\n\trenderEvent?: (props: {\n\t\tevent: CalendarEvent<TData>;\n\t\tposition: { top: number; height: number; left: number; width: number };\n\t}) => React.ReactNode;\n\t/** Custom popover content renderer */\n\trenderPopover?: (props: { event: CalendarEvent<TData>; onClose: () => void }) => React.ReactNode;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function WeekView<TData = Record<string, unknown>>({\n\tevents,\n\tdate,\n\tdays,\n\tweekStartsOn = 1,\n\tvisibleHours = { startHour: 0, endHour: 24 },\n\tworkingHours,\n\tslotDuration = 30,\n\tbadgeVariant = 'colored',\n\tonEventClick,\n\tonSlotSelect: _onSlotSelect,\n\tonDayClick,\n\tclassName,\n\trenderEvent,\n\trenderPopover,\n}: WeekViewProps<TData>) {\n\t// Calculate slot configuration based on slotDuration\n\tconst slotsPerHour = 60 / slotDuration;\n\tconst slotHeightPercent = 100 / slotsPerHour;\n\n\t// Generate slot minutes for each hour\n\tconst slotMinutes = useMemo(() => {\n\t\tconst minutes: number[] = [];\n\t\tfor (let i = 0; i < slotsPerHour; i++) {\n\t\t\tminutes.push(i * slotDuration);\n\t\t}\n\t\treturn minutes;\n\t}, [slotsPerHour, slotDuration]);\n\n\t// Week days\n\tconst weekDays = useMemo(() => {\n\t\tif (!days) return getWeekDays(date, weekStartsOn);\n\t\tconst start = new Date(date);\n\t\tstart.setHours(0, 0, 0, 0);\n\t\treturn Array.from({ length: days }, (_, i) => addDays(start, i));\n\t}, [date, weekStartsOn, days]);\n\n\t// Hours array\n\tconst hours = useMemo(() => getVisibleHoursArray(visibleHours), [visibleHours]);\n\n\t// Events per day\n\tconst eventsPerDay = useMemo(() => {\n\t\tconst map = new Map<\n\t\t\tstring,\n\t\t\t{\n\t\t\t\tsingleDay: CalendarEvent<TData>[];\n\t\t\t\tmultiDay: CalendarEvent<TData>[];\n\t\t\t\tpositions: Map<string, { top: number; height: number; left: number; width: number }>;\n\t\t\t\tmaxOverlapping: number; // Track max overlapping events for dynamic width\n\t\t\t}\n\t\t>();\n\n\t\tfor (const day of weekDays) {\n\t\t\tconst dayKey = day.toDateString();\n\t\t\tconst dayEvents = getEventsForDay(events, day);\n\t\t\tconst { singleDay, multiDay } = separateEventsByDuration(dayEvents);\n\t\t\tconst positionsArray = calculateOverlappingPositions(\n\t\t\t\tsingleDay,\n\t\t\t\tday,\n\t\t\t\tvisibleHours,\n\t\t\t\tHOUR_HEIGHT\n\t\t\t);\n\n\t\t\t// Convert array to Map for fast lookup and find max overlapping\n\t\t\tconst positions = new Map<\n\t\t\t\tstring,\n\t\t\t\t{ top: number; height: number; left: number; width: number }\n\t\t\t>();\n\t\t\tlet maxOverlapping = 1;\n\n\t\t\tfor (const positioned of positionsArray) {\n\t\t\t\tpositions.set(positioned.event.id, positioned.position);\n\t\t\t\t// Calculate number of overlapping events based on width percentage\n\t\t\t\t// width of 100% = 1 event, 50% = 2 events, 33% = 3 events, etc.\n\t\t\t\tif (positioned.position.width > 0) {\n\t\t\t\t\tconst overlapping = Math.round(100 / positioned.position.width);\n\t\t\t\t\tmaxOverlapping = Math.max(maxOverlapping, overlapping);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmap.set(dayKey, {\n\t\t\t\tsingleDay: singleDay as CalendarEvent<TData>[],\n\t\t\t\tmultiDay: multiDay as CalendarEvent<TData>[],\n\t\t\t\tpositions,\n\t\t\t\tmaxOverlapping,\n\t\t\t});\n\t\t}\n\n\t\treturn map;\n\t}, [weekDays, events, visibleHours]);\n\n\t// All multi-day events for the week (shown in banner)\n\tconst weekMultiDayEvents = useMemo(() => {\n\t\tconst unique = new Map<string, CalendarEvent<TData>>();\n\t\tfor (const { multiDay } of eventsPerDay.values()) {\n\t\t\tfor (const event of multiDay) {\n\t\t\t\tunique.set(event.id, event);\n\t\t\t}\n\t\t}\n\t\treturn Array.from(unique.values());\n\t}, [eventsPerDay]);\n\n\t// Current time position\n\tconst now = new Date();\n\tconst todayIndex = weekDays.findIndex((d) => isToday(d));\n\tconst currentTimeTop = useMemo(() => {\n\t\tif (todayIndex < 0) return -1;\n\t\tconst currentHour = now.getHours() + now.getMinutes() / 60;\n\t\tif (currentHour < visibleHours.startHour || currentHour > visibleHours.endHour) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn (currentHour - visibleHours.startHour) * HOUR_HEIGHT;\n\t}, [todayIndex, visibleHours, now]);\n\n\t// Ref for scrollable container - used to auto-scroll to working hours\n\tconst scrollContainerRef = useRef<HTMLDivElement>(null);\n\n\t// Auto-scroll to current time (if today is visible) or working hours on mount/week change\n\tuseLayoutEffect(() => {\n\t\tconst container = scrollContainerRef.current;\n\t\tif (!container) return;\n\n\t\t// Use requestAnimationFrame to ensure DOM is fully rendered\n\t\tconst performScroll = () => {\n\t\t\tlet scrollToHour: number;\n\n\t\t\t// Priority 1: If today is in the current week, scroll to current time\n\t\t\tif (todayIndex !== -1) {\n\t\t\t\tconst currentHour = new Date().getHours();\n\t\t\t\t// Scroll to 1 hour before current time for context\n\t\t\t\tscrollToHour = Math.max(currentHour - 1, visibleHours.startHour);\n\t\t\t} else {\n\t\t\t\t// Priority 2: Use working hours\n\t\t\t\t// Try to get working hours for the first day of the week or Monday\n\t\t\t\tconst today = new Date();\n\t\t\t\tconst dayOfWeek = today.getDay();\n\n\t\t\t\t// Try to get working hours for today (must be enabled), fallback to Monday (1)\n\t\t\t\tlet targetWorkingHours = workingHours?.[dayOfWeek];\n\t\t\t\tif (!targetWorkingHours?.enabled || targetWorkingHours.from === 0) {\n\t\t\t\t\t// Fallback to Monday's working hours if enabled\n\t\t\t\t\tconst mondayHours = workingHours?.[1];\n\t\t\t\t\tif (mondayHours?.enabled) {\n\t\t\t\t\t\ttargetWorkingHours = mondayHours;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Check if we have enabled working hours\n\t\t\t\tif (targetWorkingHours?.enabled && targetWorkingHours.from > 0) {\n\t\t\t\t\tscrollToHour = Math.max(targetWorkingHours.from - 1, visibleHours.startHour);\n\t\t\t\t} else {\n\t\t\t\t\t// Default to 7 AM if no working hours defined or disabled\n\t\t\t\t\tscrollToHour = Math.max(7, visibleHours.startHour);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Calculate pixel position\n\t\t\tconst scrollTop = (scrollToHour - visibleHours.startHour) * HOUR_HEIGHT;\n\n\t\t\t// Scroll to position (instant on initial load for better UX)\n\t\t\tcontainer.scrollTo({\n\t\t\t\ttop: scrollTop,\n\t\t\t\tbehavior: 'instant',\n\t\t\t});\n\t\t};\n\n\t\t// Use double requestAnimationFrame to ensure layout is complete\n\t\trequestAnimationFrame(() => {\n\t\t\trequestAnimationFrame(performScroll);\n\t\t});\n\t}, [date, workingHours, visibleHours, todayIndex]);\n\n\t// Get slot selection context (optional - works without provider)\n\tconst slotSelection = useOptionalSlotSelection();\n\n\t// Create selection handlers for time slots (matches agenda-v2)\n\tconst handleSelectionStart = useCallback(\n\t\t(slot: ITimeSlot) => {\n\t\t\tslotSelection?.startSelection(slot);\n\t\t},\n\t\t[slotSelection]\n\t);\n\n\tconst handleSelectionMove = useCallback(\n\t\t(slot: ITimeSlot) => {\n\t\t\tslotSelection?.updateSelection(slot);\n\t\t},\n\t\t[slotSelection]\n\t);\n\n\tconst handleSelectionEnd = useCallback(() => {\n\t\tslotSelection?.endSelection();\n\t}, [slotSelection]);\n\n\t// Handle multi-day event click\n\tconst handleMultiDayEventClick = useCallback(\n\t\t(event: CalendarEvent<TData>) => {\n\t\t\tonEventClick?.(event);\n\t\t},\n\t\t[onEventClick]\n\t);\n\n\t// Calculate min width for the grid to allow horizontal scrolling\n\tconst gridMinWidth = HOUR_COLUMN_WIDTH + 7 * MIN_DAY_COLUMN_WIDTH;\n\n\t// Calculate dynamic column widths based on max overlapping events per day\n\tconst dayColumnWidths = useMemo(() => {\n\t\tconst widths: number[] = [];\n\t\tfor (const day of weekDays) {\n\t\t\tconst dayKey = day.toDateString();\n\t\t\tconst dayData = eventsPerDay.get(dayKey);\n\t\t\tconst maxOverlapping = dayData?.maxOverlapping ?? 1;\n\n\t\t\t// If more than MAX_EVENTS_BEFORE_EXPAND events overlap, expand the column\n\t\t\t// Each event needs at least MIN_EVENT_CARD_WIDTH pixels\n\t\t\tif (maxOverlapping > MAX_EVENTS_BEFORE_EXPAND) {\n\t\t\t\twidths.push(Math.max(MIN_DAY_COLUMN_WIDTH, maxOverlapping * MIN_EVENT_CARD_WIDTH));\n\t\t\t} else {\n\t\t\t\twidths.push(MIN_DAY_COLUMN_WIDTH);\n\t\t\t}\n\t\t}\n\t\treturn widths;\n\t}, [weekDays, eventsPerDay]);\n\n\t// Calculate actual grid width based on dynamic column widths\n\tconst actualGridWidth = HOUR_COLUMN_WIDTH + dayColumnWidths.reduce((sum, w) => sum + w, 0);\n\n\treturn (\n\t\t<div className={cn('ic-week-view flex flex-col h-full', className)}>\n\t\t\t{/* Column-aligned all-day / multi-day events row */}\n\t\t\t{weekMultiDayEvents.length > 0 && (\n\t\t\t\t<WeekAllDayRow\n\t\t\t\t\tevents={weekMultiDayEvents}\n\t\t\t\t\tweekDays={weekDays}\n\t\t\t\t\thourColumnWidth={HOUR_COLUMN_WIDTH}\n\t\t\t\t\tminDayColumnWidth={MIN_DAY_COLUMN_WIDTH}\n\t\t\t\t\tdayColumnWidths={dayColumnWidths}\n\t\t\t\t\tonEventClick={handleMultiDayEventClick}\n\t\t\t\t\tdisablePopover={!!onEventClick && !renderPopover}\n\t\t\t\t\trenderPopover={renderPopover}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Scrollable container for header + grid - overflow-auto is REQUIRED for scroll-to-working-hours */}\n\t\t\t<div ref={scrollContainerRef} className={cn('ic-week-scroll-container flex-1')}>\n\t\t\t\t{/* Single container for both header and grid - ensures columns align */}\n\t\t\t\t<div style={{ minWidth: Math.max(gridMinWidth, actualGridWidth) }}>\n\t\t\t\t\t{/* Week header - sticky at top, uses flex to match grid columns */}\n\t\t\t\t\t<div className=\"ic-week-header sticky top-0 z-20 border-b bg-background\">\n\t\t\t\t\t\t<div className=\"flex\">\n\t\t\t\t\t\t\t{/* Empty corner for hour column with timezone - matches hour column width */}\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName=\"flex-shrink-0 flex items-end justify-center pb-2 text-[10px] text-muted-foreground/70\"\n\t\t\t\t\t\t\t\tstyle={{ width: HOUR_COLUMN_WIDTH, height: DAY_HEADER_HEIGHT }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span className=\"hidden sm:inline\">\n\t\t\t\t\t\t\t\t\tGMT\n\t\t\t\t\t\t\t\t\t{(() => {\n\t\t\t\t\t\t\t\t\t\tconst offset = new Date().getTimezoneOffset();\n\t\t\t\t\t\t\t\t\t\tconst hrs = Math.abs(Math.floor(offset / 60));\n\t\t\t\t\t\t\t\t\t\tconst sign = offset <= 0 ? '+' : '-';\n\t\t\t\t\t\t\t\t\t\treturn hrs > 0 ? `${sign}${String(hrs).padStart(2, '0')}` : '';\n\t\t\t\t\t\t\t\t\t})()}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{/* Day headers - must match grid column widths exactly */}\n\t\t\t\t\t\t\t{weekDays.map((day, dayIndex) => {\n\t\t\t\t\t\t\t\tconst today = isToday(day);\n\t\t\t\t\t\t\t\tconst columnWidth = dayColumnWidths[dayIndex] ?? MIN_DAY_COLUMN_WIDTH;\n\t\t\t\t\t\t\t\t// Only use fixed width if column needs expansion for many events\n\t\t\t\t\t\t\t\tconst needsExpansion = columnWidth > MIN_DAY_COLUMN_WIDTH;\n\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tkey={day.toDateString()}\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t'flex-1 flex flex-col items-center justify-center border-r last:border-r-0 py-2'\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\theight: DAY_HEADER_HEIGHT,\n\t\t\t\t\t\t\t\t\t\t\tminWidth: needsExpansion ? columnWidth : MIN_DAY_COLUMN_WIDTH,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{/* Day name - small uppercase */}\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t'text-[11px] font-medium uppercase tracking-wide',\n\t\t\t\t\t\t\t\t\t\t\t\ttoday ? 'text-primary' : 'text-muted-foreground'\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{day.toLocaleDateString([], { weekday: 'short' })}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t{/* Date number - large, circled if today */}\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => onDayClick?.(day)}\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t'flex items-center justify-center rounded-full transition-colors mt-0.5',\n\t\t\t\t\t\t\t\t\t\t\t\t'size-10 text-2xl font-normal',\n\t\t\t\t\t\t\t\t\t\t\t\ttoday\n\t\t\t\t\t\t\t\t\t\t\t\t\t? 'bg-primary text-primary-foreground'\n\t\t\t\t\t\t\t\t\t\t\t\t\t: 'text-foreground hover:bg-muted'\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{day.getDate()}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Time grid - within same width container as header */}\n\t\t\t\t\t<div className=\"relative flex\">\n\t\t\t\t\t\t{/* Hour labels column - sticky left to stay visible when scrolling horizontally */}\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn('ic-hour-column sticky left-0 z-10 bg-background border-r')}\n\t\t\t\t\t\t\tstyle={{ width: HOUR_COLUMN_WIDTH }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{hours.map((hour, index) => (\n\t\t\t\t\t\t\t\t<div key={hour} className=\"relative\" style={{ height: HOUR_HEIGHT }}>\n\t\t\t\t\t\t\t\t\t<div className=\"absolute -top-2.5 right-1 sm:right-2 flex h-5 items-center\">\n\t\t\t\t\t\t\t\t\t\t{index !== 0 && (\n\t\t\t\t\t\t\t\t\t\t\t<span className={cn('text-[10px] sm:text-xs text-muted-foreground')}>\n\t\t\t\t\t\t\t\t\t\t\t\t{formatHourLabel(hour)}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t{/* Week grid - day columns */}\n\t\t\t\t\t\t<div className=\"ic-week-grid relative flex-1\">\n\t\t\t\t\t\t\t<div className=\"flex divide-x\">\n\t\t\t\t\t\t\t\t{weekDays.map((day, dayIndex) => {\n\t\t\t\t\t\t\t\t\tconst dayKey = day.toDateString();\n\t\t\t\t\t\t\t\t\tconst dayData = eventsPerDay.get(dayKey);\n\t\t\t\t\t\t\t\t\tconst columnWidth = dayColumnWidths[dayIndex] ?? MIN_DAY_COLUMN_WIDTH;\n\t\t\t\t\t\t\t\t\t// Only use fixed width if column needs expansion for many events\n\t\t\t\t\t\t\t\t\tconst needsExpansion = columnWidth > MIN_DAY_COLUMN_WIDTH;\n\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tkey={day.toDateString()}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"ic-day-column relative flex-1\"\n\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\tminWidth: needsExpansion ? columnWidth : MIN_DAY_COLUMN_WIDTH,\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{/* Hour slots */}\n\t\t\t\t\t\t\t\t\t\t\t{hours.map((hour, index) => {\n\t\t\t\t\t\t\t\t\t\t\t\tconst isWorking = isWorkingHour(day, hour, workingHours);\n\t\t\t\t\t\t\t\t\t\t\t\tconst isDisabled = !isWorking;\n\n\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={hour}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t'relative',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tisDisabled && 'bg-calendar-disabled-hour',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tisToday(day) && !isDisabled && 'bg-primary/5'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{ height: HOUR_HEIGHT }}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{/* Top border (except first row) */}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{index !== 0 && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"pointer-events-none absolute inset-x-0 top-0 border-b border-border/50\" />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{/* Dashed lines for sub-hour divisions */}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{slotMinutes.slice(1).map((minute) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={minute}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"pointer-events-none absolute inset-x-0 border-b border-dashed border-border/30\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{ top: `${(minute / 60) * 100}%` }}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t))}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{/* Dynamic time slots based on slotDuration */}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{slotMinutes.map((minute, slotIndex) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst slot: ITimeSlot = {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdate: day,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thour,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tminute,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<TimeSlot\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={minute}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tslot={slot}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonSelectionStart={handleSelectionStart}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonSelectionMove={handleSelectionMove}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonSelectionEnd={handleSelectionEnd}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tisSelected={slotSelection?.isSlotSelected(slot) ?? false}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tisSelecting={slotSelection?.isSelecting ?? false}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={isDisabled}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"absolute inset-x-0\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttop: `${slotIndex * slotHeightPercent}%`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\theight: `${slotHeightPercent}%`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tariaLabel={`Add event on ${day.toLocaleDateString()} at ${formatHourLabel(hour)}:${String(minute).padStart(2, '0')}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t})}\n\n\t\t\t\t\t\t\t\t\t\t\t{/* Events for this day - positioned within the day column */}\n\t\t\t\t\t\t\t\t\t\t\t{dayData?.singleDay.map((event) => {\n\t\t\t\t\t\t\t\t\t\t\t\tconst position = dayData.positions.get(event.id);\n\t\t\t\t\t\t\t\t\t\t\t\tif (!position) return null;\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Calculate minimum width - ensure events are readable\n\t\t\t\t\t\t\t\t\t\t\t\tconst calculatedWidth = `calc(${position.width}% - 2px)`;\n\t\t\t\t\t\t\t\t\t\t\t\tconst minWidthStyle = `max(${MIN_EVENT_CARD_WIDTH}px, ${calculatedWidth})`;\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (renderEvent) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={event.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"absolute pointer-events-auto p-0.5\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttop: `${position.top}px`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tleft: `${position.left}%`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: minWidthStyle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tminWidth: `${MIN_EVENT_CARD_WIDTH}px`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{renderEvent({ event, position })}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<EventBlock\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={event.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tevent={event}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tposition={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttop: position.top,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tleft: position.left,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: position.width,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tminWidth: MIN_EVENT_CARD_WIDTH,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\thourHeight={HOUR_HEIGHT}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={onEventClick}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisablePopover={!!onEventClick && !renderPopover}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\trenderPopover={renderPopover}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn('pointer-events-auto')}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t})}\n\n\t\t\t\t\t\t\t\t\t\t\t{/* Current time indicator for this day */}\n\t\t\t\t\t\t\t\t\t\t\t{dayIndex === todayIndex && currentTimeTop >= 0 && (\n\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\tdata-ic-now=\"\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'absolute left-0 right-0 z-20 flex items-center pointer-events-none'\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\tstyle={{ top: currentTimeTop }}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"h-2 w-2 -ml-1 rounded-full bg-red-500\" />\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div className=\"flex-1 h-0.5 bg-red-500\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{/* End of width container that wraps header + grid */}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default WeekView;\n","/**\n * Year View Component\n *\n * 12-month overview with mini calendars.\n * Features:\n * - All 12 months displayed\n * - Colored event dots on days\n * - Click month to navigate to month view\n * - Click day to navigate to day view\n *\n * Ported from agenda-v2 to maintain exact styling parity.\n */\n\nimport { useMemo } from 'react';\nimport type { CalendarEvent } from '../../core/types';\nimport { generateMonthGrid, getYearMonths, isToday } from '../../core/utils/date-utils';\nimport { getEventsForDay } from '../../core/utils/event-utils';\nimport { cn } from '../../lib/utils';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst WEEKDAY_LABELS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\nconst MONTH_NAMES = [\n\t'January',\n\t'February',\n\t'March',\n\t'April',\n\t'May',\n\t'June',\n\t'July',\n\t'August',\n\t'September',\n\t'October',\n\t'November',\n\t'December',\n];\n\n// ============================================================================\n// COLOR HELPERS\n// ============================================================================\n\n/**\n * Get background color style from event's hexColor (schedule type color)\n * Falls back to primary if not available\n */\nfunction getEventDotStyle(event: CalendarEvent): React.CSSProperties {\n\tconst hexColor = (event as { hexColor?: string }).hexColor;\n\tif (hexColor) {\n\t\treturn { backgroundColor: hexColor };\n\t}\n\treturn {};\n}\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface YearViewProps<TData = Record<string, unknown>> {\n\t/** Events to display */\n\tevents: CalendarEvent<TData>[];\n\t/** The year to display */\n\tyear: number;\n\t/** Month click handler */\n\tonMonthClick?: (date: Date) => void;\n\t/** Day click handler */\n\tonDayClick?: (date: Date) => void;\n\t/** Additional CSS classes */\n\tclassName?: string;\n}\n\n// ============================================================================\n// DAY CELL COMPONENT\n// ============================================================================\n\ninterface DayCellProps {\n\tday: number;\n\tdate: Date;\n\tevents: CalendarEvent[];\n\tisCurrentMonth: boolean;\n\tonDayClick?: ((date: Date) => void) | undefined;\n}\n\nfunction DayCell({ day, date, events, isCurrentMonth, onDayClick }: DayCellProps) {\n\tconst today = isToday(date);\n\tconst maxIndicators = 3;\n\tconst eventCount = events.length;\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={() => onDayClick?.(date)}\n\t\t\tclassName={cn(\n\t\t\t\t'flex h-9 sm:h-11 flex-1 flex-col items-center justify-start gap-0.5 rounded-md pt-0.5 sm:pt-1',\n\t\t\t\t'hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',\n\t\t\t\t'transition-colors',\n\t\t\t\t!isCurrentMonth && 'opacity-40'\n\t\t\t)}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex size-5 sm:size-6 items-center justify-center rounded-full text-[10px] sm:text-xs font-medium',\n\t\t\t\t\ttoday && 'bg-primary font-semibold text-primary-foreground'\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{day}\n\t\t\t</div>\n\n\t\t\t{eventCount > 0 && (\n\t\t\t\t<div className=\"mt-0.5 flex items-center gap-0.5\">\n\t\t\t\t\t{eventCount <= maxIndicators ? (\n\t\t\t\t\t\tevents.map((event) => (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={event.id}\n\t\t\t\t\t\t\t\tclassName=\"size-1 sm:size-1.5 rounded-full bg-primary\"\n\t\t\t\t\t\t\t\tstyle={getEventDotStyle(event)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{/* Show first 3 dots for 4+ events */}\n\t\t\t\t\t\t\t{events.slice(0, maxIndicators).map((event) => (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tkey={event.id}\n\t\t\t\t\t\t\t\t\tclassName=\"size-1 sm:size-1.5 rounded-full bg-primary\"\n\t\t\t\t\t\t\t\t\tstyle={getEventDotStyle(event)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t<span className=\"text-[6px] sm:text-[7px] font-medium text-muted-foreground\">\n\t\t\t\t\t\t\t\t+{eventCount - maxIndicators}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</button>\n\t);\n}\n\n// ============================================================================\n// MINI MONTH COMPONENT\n// ============================================================================\n\ninterface MiniMonthProps<TData = Record<string, unknown>> {\n\tdate: Date;\n\tevents: CalendarEvent<TData>[];\n\tonMonthClick?: ((date: Date) => void) | undefined;\n\tonDayClick?: ((date: Date) => void) | undefined;\n}\n\nfunction MiniMonth<TData = Record<string, unknown>>({\n\tdate,\n\tevents,\n\tonMonthClick,\n\tonDayClick,\n}: MiniMonthProps<TData>) {\n\t// Use Sunday start for year view (matches Google Calendar)\n\tconst cells = useMemo(() => generateMonthGrid(date, 0), [date]);\n\n\treturn (\n\t\t<div className=\"flex flex-col\">\n\t\t\t{/* Month header */}\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={() => onMonthClick?.(date)}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'w-full rounded-t-lg border px-2 sm:px-3 py-1.5 sm:py-2 text-xs sm:text-sm font-semibold',\n\t\t\t\t\t'hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',\n\t\t\t\t\t'transition-colors'\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{MONTH_NAMES[date.getMonth()]}\n\t\t\t</button>\n\n\t\t\t{/* Month body */}\n\t\t\t<div className=\"flex-1 space-y-1.5 sm:space-y-2 rounded-b-lg border border-t-0 p-2 sm:p-3\">\n\t\t\t\t{/* Weekday headers */}\n\t\t\t\t<div className=\"grid grid-cols-7 gap-x-0.5 text-center\">\n\t\t\t\t\t{WEEKDAY_LABELS.map((label, i) => (\n\t\t\t\t\t\t<div key={i} className=\"text-[9px] sm:text-xs font-medium text-muted-foreground\">\n\t\t\t\t\t\t\t<span className=\"sm:hidden\">{label[0]}</span>\n\t\t\t\t\t\t\t<span className=\"hidden sm:inline\">{label}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Days grid */}\n\t\t\t\t<div className=\"grid grid-cols-7 gap-x-0.5 gap-y-1\">\n\t\t\t\t\t{cells.map((cell, index) => {\n\t\t\t\t\t\tconst dayEvents = getEventsForDay(events, cell.date);\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<DayCell\n\t\t\t\t\t\t\t\tkey={`${index + 1}-${cell.date.toISOString()}`}\n\t\t\t\t\t\t\t\tday={cell.date.getDate()}\n\t\t\t\t\t\t\t\tdate={cell.date}\n\t\t\t\t\t\t\t\tevents={dayEvents as CalendarEvent[]}\n\t\t\t\t\t\t\t\tisCurrentMonth={cell.isCurrentMonth}\n\t\t\t\t\t\t\t\tonDayClick={onDayClick}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// YEAR VIEW COMPONENT\n// ============================================================================\n\nexport function YearView<TData = Record<string, unknown>>({\n\tevents,\n\tyear,\n\tonMonthClick,\n\tonDayClick,\n\tclassName,\n}: YearViewProps<TData>) {\n\t// All months in the year\n\tconst months = useMemo(() => getYearMonths(year), [year]);\n\n\treturn (\n\t\t<div className={cn('flex flex-col h-full', className)}>\n\t\t\t{/* Year header */}\n\t\t\t<div className=\"flex items-center justify-center border-b px-4 py-3\">\n\t\t\t\t<h2 className=\"text-lg font-semibold\">{year}</h2>\n\t\t\t</div>\n\n\t\t\t{/* Months grid */}\n\t\t\t<div className=\"flex-1 overflow-auto p-4\">\n\t\t\t\t<div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n\t\t\t\t\t{months.map((monthDate) => (\n\t\t\t\t\t\t<MiniMonth\n\t\t\t\t\t\t\tkey={monthDate.getMonth()}\n\t\t\t\t\t\t\tdate={monthDate}\n\t\t\t\t\t\t\tevents={events}\n\t\t\t\t\t\t\tonMonthClick={onMonthClick}\n\t\t\t\t\t\t\tonDayClick={onDayClick}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default YearView;\n","/**\n * InnoCalendar Component\n *\n * A ready-to-use calendar that matches agenda-v2's Calendar component exactly.\n * Wraps InnoCalendarProvider and provides all the functionality.\n *\n * Features:\n * - Multiple view modes (day, week, month, year, agenda, timeline)\n * - Drag-to-select time/date ranges for event creation\n * - Event click handling\n * - Header with navigation controls\n */\n\nimport {\n\tforwardRef,\n\ttype ReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseImperativeHandle,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport { DEFAULT_HOUR_HEIGHT } from '../core/constants';\nimport { DragDropProvider, type IDropResult } from '../core/context/drag-drop-context';\nimport { EventCardProvider, type TEventCardRenderer } from '../core/context/event-card-context';\nimport { InnoCalendarProvider, useInnoCalendar } from '../core/context/inno-calendar-provider';\nimport { SlotSelectionProvider } from '../core/context/slot-selection-context';\nimport type { IPreferencesConfig } from '../core/preferences';\nimport type {\n\tCalendarEvent,\n\tICalendarHeaderConfig,\n\tICalendarRefHandle,\n\tICalendarUser,\n\tIResourceColumnConfig,\n\tIScheduleType,\n\tISelectionResult,\n\tIViewPersistenceConfig,\n\tTCalendarView,\n\tTSelectionMode,\n} from '../core/types';\nimport { addDays, getWeekDays as getWeekDates } from '../core/utils/date-utils';\nimport { cn } from '../lib/utils';\nimport { CalendarHeader, type CalendarHeaderProps } from './header/calendar-header';\nimport { QuickCreate, type TEventFormRenderer } from './primitives/quick-create';\nimport { ScrollNavigator } from './primitives/scroll-navigator';\nimport { CalendarSidebar, SidebarSheet } from './shell/calendar-sidebar';\nimport { FilterPanel } from './shell/filter-panel';\nimport { TooltipProvider } from './ui/tooltip';\nimport {\n\tAgendaView,\n\tDayView,\n\ttype IAgendaLabels,\n\tMonthView,\n\tResourceColumnsView,\n\tTimelineView,\n\tWeekView,\n\tYearView,\n} from './views';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * Props for the main `<InnoCalendar>` component.\n *\n * This is the primary entry point for rendering a fully-featured calendar.\n * It wraps an `InnoCalendarProvider` internally — you only need to pass\n * data and callbacks.\n *\n * @template TEventData - Shape of your custom `event.data` bag\n *\n * @example\n * ```tsx\n * <InnoCalendar\n * events={myEvents}\n * initialView=\"week\"\n * onEventClick={(e) => openDialog(e)}\n * onSlotSelect={(sel) => createEvent(sel.startDate, sel.endDate)}\n * eventDetail={(event, { close }) => <MyDetail event={event} onClose={close} />}\n * />\n * ```\n */\nexport interface InnoCalendarProps<\n\tTEventData extends Record<string, unknown> = Record<string, unknown>,\n> {\n\t// === DATA ===\n\n\t/** The events to display. */\n\tevents?: CalendarEvent<TEventData>[];\n\t/** Users / participants available for filtering and resource views */\n\tusers?: ICalendarUser[];\n\t/**\n\t * Resources that must always be rendered as rows in the resource-based views\n\t * (`resource-day`, `resource-week`, `timeline-day`, `timeline-3day`,\n\t * `timeline-week`) even when they have no events in the current data. Rows\n\t * without events appear at the bottom so event-containing rows keep visual\n\t * priority. If a resource listed here also has events, its row is positioned\n\t * naturally among the event rows.\n\t *\n\t * Only applied to the resource/timeline views above — ignored in `day`,\n\t * `week`, `month`, `year`, and `agenda` views. Updates to this array are\n\t * reflected immediately the next time one of those views renders.\n\t *\n\t * Provide enough info (at minimum `id` and `name`) to render the row header.\n\t *\n\t * @example\n\t * ```tsx\n\t * <InnoCalendar\n\t * events={events}\n\t * alwaysShowResources={[\n\t * { id: 'room-1', name: 'Meeting Room A', avatar: '/rooms/a.jpg' },\n\t * { id: 'room-2', name: 'Meeting Room B' },\n\t * ]}\n\t * />\n\t * ```\n\t */\n\talwaysShowResources?: ICalendarUser[];\n\t/** Event category definitions for built-in schedule type filtering */\n\tscheduleTypes?: IScheduleType[];\n\n\t// === INITIAL STATE ===\n\n\t/**\n\t * Initial calendar view.\n\t * @default 'week'\n\t */\n\tinitialView?: TCalendarView;\n\t/** Initial date the calendar navigates to. @default `new Date()` */\n\tinitialDate?: Date;\n\t/** Pre-selected user filter. `'all'` shows all users. @default 'all' */\n\tinitialSelectedUserId?: string | 'all';\n\t/** Pre-selected schedule type IDs for client-side filtering */\n\tinitialScheduleTypeIds?: number[];\n\t/** Pre-selected participant IDs for client-side filtering */\n\tinitialParticipantIds?: string[];\n\t/** Working-hours view override from URL or consumer logic */\n\tinitialWorkingHoursView?: 'default' | 'enabled' | 'disabled';\n\t/** Pre-filled search query for text filtering */\n\tinitialSearchQuery?: string;\n\n\t// === PREFERENCES ===\n\n\t/**\n\t * View-persistence configuration. By default the calendar reads the user's\n\t * last selected view from localStorage on mount and writes back on every\n\t * change. Pass `{ enabled: false }` to opt out, or `{ storageKey: '...' }`\n\t * to scope persistence per context — one key per tab, say, so each tab\n\t * remembers its own view.\n\t *\n\t * @example\n\t * ```tsx\n\t * <InnoCalendar viewPersistence={{ enabled: false }} />\n\t * ```\n\t *\n\t * @see {@link IViewPersistenceConfig}\n\t */\n\tviewPersistence?: IViewPersistenceConfig;\n\n\t/**\n\t * Preferences configuration (defaults, locked keys, storage key).\n\t * See `IPreferencesConfig` for full details.\n\t */\n\tpreferencesConfig?: IPreferencesConfig;\n\n\t// === CALLBACKS ===\n\n\t/** Fires when a user clicks on an event (useful when not using popovers) */\n\tonEventClick?: (event: CalendarEvent<TEventData>) => void;\n\t/** Fires when a user clicks an empty time slot */\n\tonSlotClick?: (date: Date, hour?: number) => void;\n\t/** Fires after a user drags to select a time range */\n\t/**\n\t * A drag finished. Given this, you own what happens next and the built-in\n\t * card never opens.\n\t *\n\t * `anchor` is where the drag ended, in viewport coordinates — the same point\n\t * the built-in card places itself against. Without it a consumer's own card\n\t * has to guess, and lands centred instead of beside the slot.\n\t */\n\tonSlotSelect?: (selection: ISelectionResult, meta: { anchor: { x: number; y: number } }) => void;\n\t/** Fires when the header \"Add\" button is clicked */\n\tonAddEvent?: () => void;\n\t/** Fires after an event is drag-dropped to a new time/resource */\n\tonEventDrop?: (result: IDropResult<TEventData>) => void;\n\t/** Fires when the visible date changes (navigation) */\n\tonDateChange?: (date: Date, view: TCalendarView) => void;\n\t/** Fires when the view mode changes (e.g. week → month) */\n\tonViewChange?: (view: TCalendarView) => void;\n\n\t// === UI OPTIONS ===\n\n\t/** Additional CSS classes on the root container */\n\tclassName?: string;\n\t/** Intl locale for dates and times in built-in surfaces. @default browser */\n\tlocale?: string;\n\t/** Whether to render the built-in header bar. @default true */\n\tshowHeader?: boolean;\n\t/** Minimum drag-selection length in minutes. @default 30 */\n\tminSelectionMinutes?: number;\n\t/**\n\t * How to handle overflow events in month view when a day has more than 3.\n\t *\n\t * - `'dayView'` — Clicking \"+N more\" redirects to day view\n\t * - `'popover'` — Opens a small popover listing all day events\n\t * - `'expand'` — The cell morphs into a smooth expansion overlay\n\t *\n\t * @default 'expand'\n\t */\n\tshowMoreMode?: 'dayView' | 'popover' | 'expand';\n\t/**\n\t * When `true`, clicking \"+N more\" in month view opens a popover\n\t * listing all day events instead of navigating to day view.\n\t * @deprecated Use `showMoreMode=\"popover\"` instead. Will be removed in next major version.\n\t * @default false\n\t */\n\tshowMoreEventsInPopover?: boolean;\n\t/**\n\t * Show a translucent loading overlay over the calendar grid.\n\t * Enable this while refetching data after filter/date changes.\n\t * @default false\n\t */\n\tisLoading?: boolean;\n\n\t// === CUSTOM RENDERING ===\n\n\t/**\n\t * Draw the detail yourself — what opens when an event is clicked.\n\t *\n\t * The third of the trio, beside `eventCard` and `eventForm`: the chip, the\n\t * detail, the form. The calendar supplies the popover it sits in, placed\n\t * beside the event; this is what goes inside. Omit it for the built-in one.\n\t *\n\t * `edit` is present only when an `eventForm` is there to open.\n\t *\n\t * @example\n\t * ```tsx\n\t * eventDetail={(agenda, { close, edit }) => (\n\t * <EventDetail agenda={agenda} onClose={close} onEdit={edit} />\n\t * )}\n\t * ```\n\t */\n\teventDetail?: (\n\t\tevent: CalendarEvent<TEventData>,\n\t\tactions: { close: () => void; edit?: (() => void) | undefined }\n\t) => ReactNode;\n\n\t/**\n\t * Everything inside the event card.\n\t *\n\t * The calendar supplies the surface — floated beside the slot, draggable,\n\t * dismissed on Escape or a click outside, a sheet on a phone — and hands you\n\t * what it was opened for: the slot, and the event when there is one. The\n\t * title, the categories, the time, the fields and the buttons are all yours,\n\t * because they are all about what an event *is*, which only you know.\n\t *\n\t * `expand(true)` widens the card, for when your own \"More options\" opens.\n\t *\n\t * @example\n\t * ```tsx\n\t * eventForm={({ selection, event }, { close }) => (\n\t * <EventForm selection={selection} event={event} onDone={close} />\n\t * )}\n\t * ```\n\t */\n\teventForm?: TEventFormRenderer<TEventData>;\n\n\t// === EXTENSIBILITY ===\n\n\t/**\n\t * The filters, rendered by you.\n\t *\n\t * The calendar owns where they live — a column beside the grid on a wide\n\t * screen, a sheet you pull out below one — and nothing else. What a filter is,\n\t * how it is searched and what it sends are all yours, the same way the event\n\t * card and the form are.\n\t *\n\t * `close` puts the sheet away, for a filter that applies on tap.\n\t *\n\t * @example\n\t * ```tsx\n\t * filters={({ close }) => <AgendaFilters onDone={close} />}\n\t * labels={{ filters: t('labels.filters') }}\n\t * ```\n\t */\n\tfilters?: (actions: { close: () => void }) => ReactNode;\n\n\t/**\n\t * Every word the calendar says.\n\t *\n\t * One prop rather than three: `headerLabels`, `agendaLabels` and a filters\n\t * title were the same kind of thing arriving by three routes, and a fourth\n\t * region would have wanted a fourth.\n\t */\n\tlabels?: {\n\t\theader?: Partial<CalendarHeaderProps['labels']>;\n\t\tagenda?: Partial<IAgendaLabels>;\n\t\t/** Heading above the filter rail. */\n\t\tfilters?: string;\n\t};\n\n\t/**\n\t * Draw the event chip yourself.\n\t *\n\t * Receives your event — typed by this calendar's `TEventData` — and returns\n\t * what goes inside the chip. The shell around it stays the calendar's: it is\n\t * what gets positioned in the grid, dragged, resized and clicked to open the\n\t * popover, so an app that owned it too would have to re-implement all of it\n\t * to keep the grid working.\n\t *\n\t * @example\n\t * ```tsx\n\t * <InnoCalendar<AgendaData>\n\t * eventCard={(agenda) => <EventCard agenda={agenda} />}\n\t * />\n\t * ```\n\t */\n\teventCard?: TEventCardRenderer<TEventData>;\n\n\t/**\n\t * Draw the event form yourself — the rows below the card's time row.\n\t *\n\t * Receives the draft, the setters, whether \"More options\" is open and a way\n\t * to tell Save it may not proceed. The card keeps the title, the categories,\n\t * the time and the buttons; everything past that is yours.\n\t *\n\t * @example\n\t * ```tsx\n\t * <InnoCalendar<AgendaData>\n\t * eventForm={(draft) => <EventForm {...draft} />}\n\t * />\n\t * ```\n\t */\n\n\t// === HEADER CONFIGURATION ===\n\n\t/**\n\t * Fine-grained visibility control for header sections.\n\t * Each key defaults to `true` when omitted, so you only specify what to hide.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Hide settings gear and resource views\n\t * <InnoCalendar headerConfig={{ showSettings: false, showResourceViews: false }} />\n\t * ```\n\t *\n\t * @see {@link ICalendarHeaderConfig}\n\t */\n\theaderConfig?: ICalendarHeaderConfig;\n\n\t/**\n\t * Visual configuration for the resource (left) column in timeline /\n\t * resource views. Pick a name-rendering variant and toggle the avatar\n\t * without writing a custom `resourceHeader` slot.\n\t *\n\t * @example\n\t * ```tsx\n\t * <InnoCalendar\n\t * resourceColumnConfig={{ variant: 'marquee', showAvatar: false }}\n\t * />\n\t * ```\n\t *\n\t * @see {@link IResourceColumnConfig}\n\t */\n\tresourceColumnConfig?: IResourceColumnConfig;\n\n\t// === EVENT DETAIL MODE ===\n\n\t// === CONTENT SLOTS ===\n\n\t/** Custom React content rendered inside the settings dropdown panel */\n\tsettingsContent?: ReactNode;\n\t/** Custom React content rendered as the filter sidebar / row */\n\tfilterContent?: ReactNode;\n\n\t/**\n\t * Show Google's left rail — Create button, mini month navigator, then\n\t * `sidebarContent`. Hidden below `lg`, where the grid takes the full width.\n\t * @default false\n\t */\n\tshowSidebar?: boolean;\n\n\t/** Rendered under the mini month. Filters and calendar toggles live here. */\n\tsidebarContent?: ReactNode;\n\n\t/** Label for the sidebar's Create button. @default 'Create' */\n\tcreateLabel?: string;\n\t/** Custom header actions (replaces the default \"+\" add button) */\n\theaderActions?: ReactNode;\n\n\t/**\n\t * When set, the event with this ID will auto-open its popover after the\n\t * calendar renders. Ideal for deep-linking from other pages.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Navigate to agenda with event pre-selected\n\t * <InnoCalendar events={events} focusEventId={eventIdFromUrl} />\n\t * ```\n\t */\n\tfocusEventId?: string | null;\n}\n\n// Stable empty defaults — see the note in inno-calendar-provider.tsx.\nconst NO_EVENTS: never[] = [];\nconst NO_USERS: never[] = [];\n\n/**\n * The views the built-in header offers. Also what may be restored from storage,\n * so a value saved before a view was retired cannot strand somebody in it.\n *\n * `year` is deliberately absent: it renders every event in the year at once.\n */\nconst MENU_VIEWS: readonly TCalendarView[] = ['day', '4day', 'week', 'month', 'agenda'];\n\n// ============================================================================\n// HELPER: Determine selection mode based on view\n// ============================================================================\n\nfunction getSelectionMode(view: TCalendarView): TSelectionMode {\n\tswitch (view) {\n\t\tcase 'day':\n\t\tcase '4day':\n\t\tcase 'week':\n\t\t\treturn 'time';\n\t\tcase 'month':\n\t\tcase 'year':\n\t\tcase 'agenda':\n\t\tcase 'timeline-day':\n\t\tcase 'timeline-3day':\n\t\tcase 'timeline-week':\n\t\tdefault:\n\t\t\treturn 'day';\n\t}\n}\n\n// ============================================================================\n// INNER CALENDAR (uses context)\n// ============================================================================\n\ninterface InnerCalendarProps<TEventData extends Record<string, unknown> = Record<string, unknown>> {\n\tonEventClick?: (event: CalendarEvent<TEventData>) => void;\n\tonSlotClick?: (date: Date, hour?: number) => void;\n\tonSlotSelect?: (selection: ISelectionResult, meta: { anchor: { x: number; y: number } }) => void;\n\tonAddEvent?: () => void;\n\t/** Resources always shown as rows in resource views (see InnoCalendarProps) */\n\talwaysShowResources?: ICalendarUser[];\n\tclassName?: string | undefined;\n\tshowHeader?: boolean;\n\tminSelectionMinutes?: number;\n\tshowMoreMode?: 'dayView' | 'popover' | 'expand';\n\tshowMoreEventsInPopover?: boolean;\n\tisLoading?: boolean;\n\teventCard?: TEventCardRenderer<TEventData>;\n\teventForm?: TEventFormRenderer<TEventData>;\n\tsettingsContent?: ReactNode;\n\tfilterContent?: ReactNode;\n\theaderActions?: ReactNode;\n\teventDetail?: (\n\t\tevent: CalendarEvent<TEventData>,\n\t\tactions: { close: () => void; edit?: (() => void) | undefined }\n\t) => ReactNode;\n\t/** Ref to parent InnoCalendar for exposing imperative methods */\n\tcalendarRef?: React.Ref<ICalendarRefHandle>;\n\t/** Header visibility config */\n\theaderConfig?: ICalendarHeaderConfig;\n\t/** Resource column visual config (timeline / resource views only) */\n\tresourceColumnConfig?: IResourceColumnConfig;\n\tfilters?: ((actions: { close: () => void }) => ReactNode) | undefined;\n\tlabels?: InnoCalendarProps<TEventData>['labels'] | undefined;\n\tquickCreateDerive?:\n\t\t| ((draft: Record<string, unknown>, changed: string) => Record<string, unknown> | null)\n\t\t| undefined;\n\tshowSidebar?: boolean | undefined;\n\tsidebarContent?: ReactNode;\n\tcreateLabel?: string | undefined;\n\t/** Intl locale for the quick-create card */\n\tlocale?: string | undefined;\n}\n\nfunction InnerCalendar<TEventData extends Record<string, unknown> = Record<string, unknown>>({\n\tonEventClick,\n\tonSlotClick,\n\tonSlotSelect,\n\tonAddEvent,\n\talwaysShowResources,\n\tclassName,\n\tshowHeader = true,\n\tminSelectionMinutes = 30,\n\tshowMoreMode,\n\tshowMoreEventsInPopover = false,\n\tisLoading = false,\n\teventCard,\n\teventForm,\n\tsettingsContent,\n\tfilterContent,\n\theaderActions,\n\teventDetail,\n\tcalendarRef,\n\theaderConfig,\n\tresourceColumnConfig,\n\tfilters,\n\tlabels,\n\tshowSidebar = false,\n\tsidebarContent,\n\tcreateLabel,\n\tlocale,\n}: InnerCalendarProps<TEventData>) {\n\t// Resolve show-more mode: new prop takes priority, then deprecated boolean\n\tconst resolvedShowMoreMode = showMoreMode ?? (showMoreEventsInPopover ? 'popover' : 'expand');\n\tconst {\n\t\tview,\n\t\tsetView,\n\t\tselectedDate,\n\t\tsetSelectedDate,\n\t\tslotDuration,\n\t\tfilteredEvents,\n\t\tusers,\n\t\tvisibleHours: contextVisibleHours,\n\t\tworkingHours,\n\t\tbadgeVariant,\n\t\tshowWorkingHoursOnly,\n\t\tclearFocusEventId,\n\t} = useInnoCalendar<TEventData>();\n\n\t// When showWorkingHoursOnly is enabled, narrow visible hours to the\n\t// working hours range instead of the user-configured visible hours.\n\tconst effectiveVisibleHours = useMemo(() => {\n\t\tif (!showWorkingHoursOnly || !workingHours) {\n\t\t\treturn {\n\t\t\t\tstartHour: contextVisibleHours.start,\n\t\t\t\tendHour: contextVisibleHours.end,\n\t\t\t};\n\t\t}\n\n\t\t// Compute the earliest \"from\" and latest \"to\" across all enabled days\n\t\tlet minFrom = 24;\n\t\tlet maxTo = 0;\n\t\tfor (const dayKey of Object.keys(workingHours)) {\n\t\t\tconst day = workingHours[Number(dayKey)];\n\t\t\tif (!day || day.enabled === false) continue;\n\t\t\tif (day.from < minFrom) minFrom = day.from;\n\t\t\tif (day.to > maxTo) maxTo = day.to;\n\t\t}\n\n\t\t// If no enabled days found, fall back to context visible hours\n\t\tif (minFrom >= maxTo) {\n\t\t\treturn {\n\t\t\t\tstartHour: contextVisibleHours.start,\n\t\t\t\tendHour: contextVisibleHours.end,\n\t\t\t};\n\t\t}\n\n\t\treturn { startHour: minFrom, endHour: maxTo };\n\t}, [showWorkingHoursOnly, workingHours, contextVisibleHours]);\n\n\t// Use effective visible hours for views\n\tconst visibleHours = effectiveVisibleHours;\n\n\t// Ref for the view container (defined later, used for scroll methods)\n\tconst innerViewContainerRef = useRef<HTMLDivElement>(null);\n\n\t// Expose imperative methods via ref\n\t/**\n\t * The imperative handle, built once and kept — the calendar uses it too:\n\t * \"Add\" with no handler of its own reads `getNowAnchor` to place the card\n\t * beside the current-time line.\n\t */\n\t/**\n\t * `api` is built before `openNow`, and `openNow` reads `api` — so the two can\n\t * only meet through a ref. Assigned the moment `openNow` exists, below.\n\t */\n\tconst openNowRef = useRef<(() => void) | null>(null);\n\n\tconst api = useMemo<ICalendarRefHandle>(\n\t\t() => ({\n\t\t\tscrollToToday: () => {\n\t\t\t\t// Navigate to today's date in the current view\n\t\t\t\tconst today = new Date();\n\t\t\t\tsetSelectedDate(today, view);\n\n\t\t\t\t// After a short delay, scroll the view container to show current time\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tconst container = innerViewContainerRef.current?.querySelector<HTMLDivElement>(\n\t\t\t\t\t\t\t\".ic-timeline-scroll-container, [class*='overflow-auto']\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!container) return;\n\n\t\t\t\t\t\t// For time-based views, scroll to current hour\n\t\t\t\t\t\tconst currentHour = today.getHours();\n\t\t\t\t\t\tconst hourHeight = DEFAULT_HOUR_HEIGHT;\n\t\t\t\t\t\tconst scrollTop = (currentHour - effectiveVisibleHours.startHour) * hourHeight;\n\n\t\t\t\t\t\tif (scrollTop > 0) {\n\t\t\t\t\t\t\tcontainer.scrollTo({\n\t\t\t\t\t\t\t\ttop: Math.max(0, scrollTop - 100), // Offset to show some context\n\t\t\t\t\t\t\t\tbehavior: 'smooth',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\topenForm: (args) => {\n\t\t\t\t// Editing keeps the event's own times; a link that just says \"new\"\n\t\t\t\t// gets the slot happening now, snapped and anchored exactly as the Add\n\t\t\t\t// button does — the raw wall clock is not a slot anyone can point at.\n\t\t\t\tif (!args?.start && !args?.event) return openNowRef.current?.();\n\n\t\t\t\tconst start = args?.start ?? (args?.event as CalendarEvent<TEventData>).startDate;\n\t\t\t\tconst end =\n\t\t\t\t\targs?.end ??\n\t\t\t\t\t(args?.event\n\t\t\t\t\t\t? (args.event as CalendarEvent<TEventData>).endDate\n\t\t\t\t\t\t: new Date(start.getTime() + 30 * 60_000));\n\t\t\t\tsetQuickCreate({\n\t\t\t\t\tselection: {\n\t\t\t\t\t\tstartDate: start,\n\t\t\t\t\t\tendDate: end,\n\t\t\t\t\t\t...(args?.resourceId !== undefined && {\n\t\t\t\t\t\t\tresourceId: args.resourceId,\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t\t...(args?.anchor && { anchor: args.anchor }),\n\t\t\t\t\t...(args?.event && {\n\t\t\t\t\t\tevent: args.event as CalendarEvent<TEventData>,\n\t\t\t\t\t}),\n\t\t\t\t});\n\t\t\t},\n\t\t\tgetNowAnchor: () => {\n\t\t\t\tconst root = innerViewContainerRef.current;\n\t\t\t\t// The time line where the views have one, today's cell where they do\n\t\t\t\t// not — both mean \"here is now\" to somebody looking at the grid.\n\t\t\t\tconst marker =\n\t\t\t\t\troot?.querySelector<HTMLElement>('[data-ic-now]') ??\n\t\t\t\t\troot?.querySelector<HTMLElement>('[data-ic-today]');\n\t\t\t\tif (!marker) return null;\n\n\t\t\t\tconst rect = marker.getBoundingClientRect();\n\t\t\t\tif (rect.width === 0 && rect.height === 0) return null;\n\n\t\t\t\t// Scrolled out of sight: the caller should scroll to it before asking\n\t\t\t\t// again, rather than have something open pointing off-screen.\n\t\t\t\tconst visible =\n\t\t\t\t\trect.bottom > 0 &&\n\t\t\t\t\trect.top < window.innerHeight &&\n\t\t\t\t\trect.right > 0 &&\n\t\t\t\t\trect.left < window.innerWidth;\n\t\t\t\tif (!visible) return null;\n\n\t\t\t\treturn { x: rect.left, y: rect.top + rect.height / 2 };\n\t\t\t},\n\t\t\tscrollToWorkingHours: () => {\n\t\t\t\t// Find the earliest working hour across all days\n\t\t\t\tlet targetHour = 8; // Default fallback\n\t\t\t\tif (workingHours) {\n\t\t\t\t\tfor (const dayKey of Object.keys(workingHours)) {\n\t\t\t\t\t\tconst day = workingHours[Number(dayKey)];\n\t\t\t\t\t\tif (day?.enabled && day.from < targetHour) {\n\t\t\t\t\t\t\ttargetHour = Math.max(day.from - 1, 0); // 1 hour before\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tconst container = innerViewContainerRef.current?.querySelector<HTMLDivElement>(\n\t\t\t\t\t\t\t\".ic-timeline-scroll-container, [class*='overflow-auto']\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!container) return;\n\n\t\t\t\t\t\tconst hourHeight = DEFAULT_HOUR_HEIGHT;\n\t\t\t\t\t\tconst scrollTop = (targetHour - effectiveVisibleHours.startHour) * hourHeight;\n\n\t\t\t\t\t\tcontainer.scrollTo({\n\t\t\t\t\t\t\ttop: Math.max(0, scrollTop),\n\t\t\t\t\t\t\tbehavior: 'smooth',\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\tgetViewRect: () => {\n\t\t\t\treturn innerViewContainerRef.current?.getBoundingClientRect() ?? null;\n\t\t\t},\n\t\t\tfocusEvent: (eventId: string) => {\n\t\t\t\tclearFocusEventId();\n\t\t\t\t// Setting via context will trigger the EventCard/EventBlock useEffect\n\t\t\t\t// We need to set it through the provider, so dispatch via a micro-task\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tclearFocusEventId();\n\t\t\t\t});\n\t\t\t\t// Directly re-set focusEventId through the provider's exposed method\n\t\t\t\t// Since we can't call setFocusEventId from here, we use the same\n\t\t\t\t// prop-sync mechanism: consumers should update the focusEventId prop.\n\t\t\t\t// For imperative use, we fall back to finding the element on the DOM.\n\t\t\t\tconst el = innerViewContainerRef.current?.querySelector<HTMLElement>(\n\t\t\t\t\t`[data-event-id=\"${eventId}\"]`\n\t\t\t\t);\n\t\t\t\tif (el) {\n\t\t\t\t\tsetTimeout(() => el.click(), 150);\n\t\t\t\t}\n\t\t\t},\n\t\t}),\n\t\t[setSelectedDate, view, effectiveVisibleHours, workingHours, clearFocusEventId]\n\t);\n\tuseImperativeHandle(calendarRef, () => api, [api]);\n\n\tconst previousView = useRef(view);\n\tuseEffect(() => {\n\t\tif (previousView.current === view) return;\n\t\tpreviousView.current = view;\n\t\t// Only the time grids have an hour to land on: Schedule is a list that\n\t\t// already starts at today, and month and year have no hours at all.\n\t\tif (view === 'month' || view === 'year' || view === 'agenda') return;\n\t\tconst id = setTimeout(() => api.scrollToToday(), 300);\n\t\treturn () => clearTimeout(id);\n\t}, [view, api]);\n\n\t// Determine selection mode based on current view\n\tconst selectionMode = useMemo(() => getSelectionMode(view), [view]);\n\n\t// ---- Quick create -------------------------------------------------------\n\t// Available only when the source can create. The card opens where the drag\n\t// ended, so we track the pointer rather than guessing from the grid.\n\tconst pointerRef = useRef({ x: 0, y: 0 });\n\tconst [quickCreate, setQuickCreate] = useState<{\n\t\tselection: ISelectionResult;\n\t\tanchor?: { x: number; y: number; align?: 'center' | 'start' | 'end' };\n\t\t/** Present when the card was opened on an event. */\n\t\tevent?: CalendarEvent<TEventData>;\n\t} | null>(null);\n\n\tuseEffect(() => {\n\t\tconst track = (e: PointerEvent) => {\n\t\t\tpointerRef.current = { x: e.clientX, y: e.clientY };\n\t\t};\n\t\tdocument.addEventListener('pointerdown', track, true);\n\t\tdocument.addEventListener('pointerup', track, true);\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('pointerdown', track, true);\n\t\t\tdocument.removeEventListener('pointerup', track, true);\n\t\t};\n\t}, []);\n\n\t// Handle selection complete — a consumer handler wins; otherwise quick-create\n\t// when the source supports it; otherwise the legacy onSlotClick bridge.\n\tconst handleSlotSelect = useCallback(\n\t\t(selection: ISelectionResult) => {\n\t\t\tif (onSlotSelect) {\n\t\t\t\tonSlotSelect(selection, { anchor: { ...pointerRef.current } });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (eventForm) {\n\t\t\t\t// Beside the slot it is for, not on top of it: `start` puts the card\n\t\t\t\t// to the right of where the drag ended and flips left when that edge\n\t\t\t\t// has no room. Centred on the pointer, it covered the very slot you\n\t\t\t\t// had just chosen.\n\t\t\t\tsetQuickCreate({\n\t\t\t\t\tselection,\n\t\t\t\t\tanchor: { ...pointerRef.current, align: 'start' },\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (onSlotClick) {\n\t\t\t\tconst hour = selection.startDate.getHours();\n\t\t\t\tonSlotClick(selection.startDate, hour);\n\t\t\t}\n\t\t},\n\t\t[onSlotSelect, onSlotClick, eventForm]\n\t);\n\n\t// Handle day click from month/year views -> navigate to day view\n\tconst handleDayClick = useCallback(\n\t\t(date: Date) => {\n\t\t\tsetView('day');\n\t\t\tsetSelectedDate(date, 'day');\n\t\t},\n\t\t[setSelectedDate, setView]\n\t);\n\n\t// Handle month click from year view -> navigate to month view\n\tconst handleMonthClick = useCallback(\n\t\t(date: Date) => {\n\t\t\tsetView('month');\n\t\t\tsetSelectedDate(date, 'month');\n\t\t},\n\t\t[setSelectedDate, setView]\n\t);\n\n\t// Type-safe event click handler\n\tconst handleEventClick = useCallback(\n\t\t(event: CalendarEvent<TEventData>) => {\n\t\t\tonEventClick?.(event);\n\t\t},\n\t\t[onEventClick]\n\t);\n\n\t// Timeline-specific slot click adapter — timeline's onSlotClick has an extra\n\t// `resourceId` parameter that isn't part of the standard InnoCalendar callback.\n\t// Wrap the consumer's callback so the signatures are compatible.\n\tconst handleTimelineSlotClick = useCallback(\n\t\t(date: Date, hour?: number, _resourceId?: string) => {\n\t\t\tonSlotClick?.(date, hour);\n\t\t},\n\t\t[onSlotClick]\n\t);\n\n\t/**\n\t * Opening the card on an existing event. The event goes through whole — the\n\t * form is the only thing that knows how to read it.\n\t */\n\tconst openEventForm = useCallback(\n\t\t(event: CalendarEvent<TEventData>, range?: { start: Date; end: Date }) => {\n\t\t\tsetQuickCreate({\n\t\t\t\tselection: {\n\t\t\t\t\tstartDate: range?.start ?? event.startDate,\n\t\t\t\t\tendDate: range?.end ?? event.endDate,\n\t\t\t\t},\n\t\t\t\tevent,\n\t\t\t});\n\t\t},\n\t\t[]\n\t);\n\n\t/**\n\t * \"Add\" with no handler of your own opens the card on the slot happening\n\t * right now, beside the current-time line the way Google's does — not\n\t * floating over the middle of the grid, where it says nothing about which\n\t * slot it is for.\n\t *\n\t * If now is already on screen the card opens immediately; otherwise the grid\n\t * glides there first, because an anchor read mid-scroll points at the wrong\n\t * row by the time the scroll finishes.\n\t */\n\tconst openNow = useCallback(() => {\n\t\tconst start = new Date();\n\t\tconst step = minSelectionMinutes ?? 30;\n\t\tstart.setMinutes(Math.floor(start.getMinutes() / step) * step, 0, 0);\n\t\tconst end = new Date(start.getTime() + step * 60_000);\n\n\t\tconst beside = () => {\n\t\t\tconst point = api.getNowAnchor();\n\t\t\treturn point ? { ...point, align: 'end' as const } : undefined;\n\t\t};\n\n\t\tconst open = (anchor: ReturnType<typeof beside>) =>\n\t\t\tsetQuickCreate({\n\t\t\t\tselection: { startDate: start, endDate: end },\n\t\t\t\t...(anchor && { anchor }),\n\t\t\t});\n\n\t\tconst now = beside();\n\t\tif (now) return open(now);\n\n\t\tapi.scrollToToday();\n\t\t// Long enough for the smooth scroll to settle; the card follows it in.\n\t\tsetTimeout(() => open(beside()), 450);\n\t}, [api, minSelectionMinutes]);\n\n\topenNowRef.current = openNow;\n\n\tconst handleAdd = onAddEvent ?? (eventForm ? openNow : undefined);\n\n\t/** The popover's Edit, supplied by the calendar rather than by every app. */\n\tconst popover = useMemo(\n\t\t() =>\n\t\t\teventDetail\n\t\t\t\t? ({ event, onClose }: { event: CalendarEvent<TEventData>; onClose: () => void }) =>\n\t\t\t\t\t\teventDetail(event, {\n\t\t\t\t\t\t\tclose: onClose,\n\t\t\t\t\t\t\t...(eventForm && {\n\t\t\t\t\t\t\t\tedit: () => {\n\t\t\t\t\t\t\t\t\tonClose();\n\t\t\t\t\t\t\t\t\t// Deferred: the click that opened this is still propagating,\n\t\t\t\t\t\t\t\t\t// and the card would read it as the outside click.\n\t\t\t\t\t\t\t\t\tsetTimeout(() => openEventForm(event), 0);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t})\n\t\t\t\t: undefined,\n\t\t[eventDetail, eventForm, openEventForm]\n\t);\n\n\t// Render current view with required props from context\n\tconst renderView = () => {\n\t\t// Cast events to base type for view components\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Generic type needs to be cast for view components\n\t\tconst viewEvents = filteredEvents as any;\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Generic type needs to be cast for view components\n\t\tconst viewEventClick = handleEventClick as any;\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Generic type needs to be cast for view components\n\t\tconst viewRenderPopover = popover as any;\n\n\t\tswitch (view) {\n\t\t\t// Google has no separate \"resource day\": the day view itself splits into\n\t\t\t// one column per person as soon as more than one is selected, and stays a\n\t\t\t// single column otherwise. The view name never has to say which.\n\t\t\tcase 'day':\n\t\t\t\tif (users.length > 1) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<ResourceColumnsView\n\t\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\t\tdates={[selectedDate]}\n\t\t\t\t\t\t\tresources={users}\n\t\t\t\t\t\t\tvisibleHours={visibleHours}\n\t\t\t\t\t\t\tslotDuration={slotDuration}\n\t\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<DayView\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tdate={selectedDate}\n\t\t\t\t\t\tvisibleHours={visibleHours}\n\t\t\t\t\t\tworkingHours={workingHours}\n\t\t\t\t\t\tslotDuration={slotDuration}\n\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t// Google's rolling four days: the same grid, begun where you are rather\n\t\t\t// than at the week's start.\n\t\t\tcase '4day':\n\t\t\t\tif (users.length > 1) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<ResourceColumnsView\n\t\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\t\tdates={Array.from({ length: 4 }, (_, i) => addDays(selectedDate, i))}\n\t\t\t\t\t\t\tresources={users}\n\t\t\t\t\t\t\tvisibleHours={visibleHours}\n\t\t\t\t\t\t\tslotDuration={slotDuration}\n\t\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<WeekView\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tdate={selectedDate}\n\t\t\t\t\t\tdays={4}\n\t\t\t\t\t\tvisibleHours={visibleHours}\n\t\t\t\t\t\tworkingHours={workingHours}\n\t\t\t\t\t\tslotDuration={slotDuration}\n\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t/>\n\t\t\t\t);\n\n\t\t\t// Same rule as the day view: several people selected turns each day into\n\t\t\t// a set of per-person columns.\n\t\t\tcase 'week':\n\t\t\t\tif (users.length > 1) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<ResourceColumnsView\n\t\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\t\tdates={getWeekDates(selectedDate)}\n\t\t\t\t\t\t\tresources={users}\n\t\t\t\t\t\t\tvisibleHours={visibleHours}\n\t\t\t\t\t\t\tslotDuration={slotDuration}\n\t\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<WeekView\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tdate={selectedDate}\n\t\t\t\t\t\tvisibleHours={visibleHours}\n\t\t\t\t\t\tworkingHours={workingHours}\n\t\t\t\t\t\tslotDuration={slotDuration}\n\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\tcase 'month':\n\t\t\t\treturn (\n\t\t\t\t\t<MonthView\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tdate={selectedDate}\n\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\tonDayClick={handleDayClick}\n\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t\tshowMoreMode={resolvedShowMoreMode}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\tcase 'year':\n\t\t\t\treturn (\n\t\t\t\t\t<YearView\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tyear={selectedDate.getFullYear()}\n\t\t\t\t\t\tonMonthClick={handleMonthClick}\n\t\t\t\t\t\tonDayClick={handleDayClick}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\tcase 'agenda':\n\t\t\t\treturn (\n\t\t\t\t\t<AgendaView\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tdate={selectedDate}\n\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\t{...(labels?.agenda && { labels: labels.agenda })}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t// Resource views — delegate to TimelineView with matching day count\n\t\t\t// One day, a column per person — Google's shape when several people are\n\t\t\t// selected. The week/timeline variants stay as horizontal lanes.\n\t\t\tcase 'resource-day':\n\t\t\t\treturn (\n\t\t\t\t\t<ResourceColumnsView\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tdates={[selectedDate]}\n\t\t\t\t\t\tresources={users}\n\t\t\t\t\t\tvisibleHours={visibleHours}\n\t\t\t\t\t\tslotDuration={slotDuration}\n\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\tcase 'resource-week':\n\t\t\t\treturn (\n\t\t\t\t\t<TimelineView\n\t\t\t\t\t\tdaysToShow={7}\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tusers={users}\n\t\t\t\t\t\t{...(alwaysShowResources && { alwaysShowResources })}\n\t\t\t\t\t\tselectedDate={selectedDate}\n\t\t\t\t\t\tvisibleHours={{\n\t\t\t\t\t\t\tfrom: effectiveVisibleHours.startHour,\n\t\t\t\t\t\t\tto: effectiveVisibleHours.endHour,\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\tonSlotSelect={handleSlotSelect}\n\t\t\t\t\t\tonSlotClick={handleTimelineSlotClick}\n\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t\t{...(resourceColumnConfig && { resourceColumnConfig })}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t// Timeline views\n\t\t\t// Same shape as resource-day: one day across people reads as columns.\n\t\t\tcase 'timeline-day':\n\t\t\t\treturn (\n\t\t\t\t\t<ResourceColumnsView\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tdates={[selectedDate]}\n\t\t\t\t\t\tresources={users}\n\t\t\t\t\t\tvisibleHours={visibleHours}\n\t\t\t\t\t\tslotDuration={slotDuration}\n\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\tcase 'timeline-3day':\n\t\t\t\treturn (\n\t\t\t\t\t<TimelineView\n\t\t\t\t\t\tdaysToShow={3}\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tusers={users}\n\t\t\t\t\t\t{...(alwaysShowResources && { alwaysShowResources })}\n\t\t\t\t\t\tselectedDate={selectedDate}\n\t\t\t\t\t\tvisibleHours={{\n\t\t\t\t\t\t\tfrom: effectiveVisibleHours.startHour,\n\t\t\t\t\t\t\tto: effectiveVisibleHours.endHour,\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\tonSlotSelect={handleSlotSelect}\n\t\t\t\t\t\tonSlotClick={handleTimelineSlotClick}\n\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t\t{...(resourceColumnConfig && { resourceColumnConfig })}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\tcase 'timeline-week':\n\t\t\t\treturn (\n\t\t\t\t\t<TimelineView\n\t\t\t\t\t\tdaysToShow={7}\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tusers={users}\n\t\t\t\t\t\t{...(alwaysShowResources && { alwaysShowResources })}\n\t\t\t\t\t\tselectedDate={selectedDate}\n\t\t\t\t\t\tvisibleHours={{\n\t\t\t\t\t\t\tfrom: effectiveVisibleHours.startHour,\n\t\t\t\t\t\t\tto: effectiveVisibleHours.endHour,\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\tonSlotSelect={handleSlotSelect}\n\t\t\t\t\t\tonSlotClick={handleTimelineSlotClick}\n\t\t\t\t\t\trenderPopover={viewRenderPopover}\n\t\t\t\t\t\t{...(resourceColumnConfig && { resourceColumnConfig })}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\tdefault:\n\t\t\t\treturn (\n\t\t\t\t\t<MonthView\n\t\t\t\t\t\tevents={viewEvents}\n\t\t\t\t\t\tdate={selectedDate}\n\t\t\t\t\t\tbadgeVariant={badgeVariant}\n\t\t\t\t\t\tonEventClick={viewEventClick}\n\t\t\t\t\t\tonDayClick={handleDayClick}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t}\n\t};\n\n\t// ---- View container ref -------------------------------------------------\n\tconst viewContainerRef = useRef<HTMLDivElement>(null);\n\n\t// Sync innerViewContainerRef with viewContainerRef for imperative methods\n\tuseEffect(() => {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Assigning ref.current for sync\n\t\t(innerViewContainerRef as any).current = viewContainerRef.current;\n\t});\n\n\t// Held here rather than inside the sheet: a filter that applies on tap should\n\t// be able to put the sheet away, and only its parent can do that.\n\tconst [sidebarSheetOpen, setSidebarSheetOpen] = useState(false);\n\n\t/** The rail's contents. Rendered twice — in the rail, and in its sheet. */\n\tconst sidebarNode = (\n\t\t<>\n\t\t\t{filters && (\n\t\t\t\t<FilterPanel {...(labels?.filters && { title: labels.filters })}>\n\t\t\t\t\t{filters({ close: () => setSidebarSheetOpen(false) })}\n\t\t\t\t</FilterPanel>\n\t\t\t)}\n\t\t\t{sidebarContent}\n\t\t</>\n\t);\n\n\tconst grid = (\n\t\t<TooltipProvider delayDuration={300}>\n\t\t\t<SlotSelectionProvider\n\t\t\t\tmode={selectionMode}\n\t\t\t\tonSelect={handleSlotSelect}\n\t\t\t\tminDurationMinutes={minSelectionMinutes}\n\t\t\t\tslotDurationMinutes={slotDuration}\n\t\t\t\t// Not while the card is open: a click on the grid should put it away,\n\t\t\t\t// the way Google's does. Left enabled, that click ends a fresh selection\n\t\t\t\t// and opens a second card, so the first never appears to close.\n\t\t\t\tenabled={Boolean(onSlotSelect || onSlotClick || eventForm) && !quickCreate}\n\t\t\t>\n\t\t\t\t<div className={cn('inno-calendar-root flex h-full gap-4 p-4', className)}>\n\t\t\t\t\t{showSidebar && (\n\t\t\t\t\t\t<CalendarSidebar\n\t\t\t\t\t\t\tselected={selectedDate}\n\t\t\t\t\t\t\tonSelect={(date) => setSelectedDate(date, view)}\n\t\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\t\t{...(handleAdd && { onCreate: handleAdd })}\n\t\t\t\t\t\t\t{...(createLabel && { createLabel })}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{sidebarNode}\n\t\t\t\t\t\t</CalendarSidebar>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<div className=\"flex min-w-0 flex-1 flex-col\">\n\t\t\t\t\t\t{showHeader && (\n\t\t\t\t\t\t\t<CalendarHeader\n\t\t\t\t\t\t\t\tcurrentDate={selectedDate}\n\t\t\t\t\t\t\t\tview={view}\n\t\t\t\t\t\t\t\t{...(showSidebar && {\n\t\t\t\t\t\t\t\t\t// Below `lg` the rail is hidden, so its contents — the mini\n\t\t\t\t\t\t\t\t\t// month, Create, and every filter — would otherwise be\n\t\t\t\t\t\t\t\t\t// unreachable rather than merely out of the way.\n\t\t\t\t\t\t\t\t\tleadingAction: (\n\t\t\t\t\t\t\t\t\t\t<SidebarSheet\n\t\t\t\t\t\t\t\t\t\t\topen={sidebarSheetOpen}\n\t\t\t\t\t\t\t\t\t\t\tonOpenChange={setSidebarSheetOpen}\n\t\t\t\t\t\t\t\t\t\t\tselected={selectedDate}\n\t\t\t\t\t\t\t\t\t\t\tonSelect={(date) => setSelectedDate(date, view)}\n\t\t\t\t\t\t\t\t\t\t\t{...(locale && { locale })}\n\t\t\t\t\t\t\t\t\t\t\t{...(handleAdd && {\n\t\t\t\t\t\t\t\t\t\t\t\t// The sheet is the whole screen at this width, so leaving it\n\t\t\t\t\t\t\t\t\t\t\t\t// up would hide the card it just opened.\n\t\t\t\t\t\t\t\t\t\t\t\tonCreate: () => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tsetSidebarSheetOpen(false);\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleAdd();\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t{...(createLabel && { createLabel })}\n\t\t\t\t\t\t\t\t\t\t\t{...(labels?.filters && { label: labels.filters })}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{sidebarNode}\n\t\t\t\t\t\t\t\t\t\t</SidebarSheet>\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t{...(labels?.header && { labels: labels.header })}\n\t\t\t\t\t\t\t\tevents={filteredEvents}\n\t\t\t\t\t\t\t\tonViewChange={setView}\n\t\t\t\t\t\t\t\tonNavigateToday={() => setSelectedDate(new Date(), view)}\n\t\t\t\t\t\t\t\tonNavigatePrev={() => {\n\t\t\t\t\t\t\t\t\tconst prev = new Date(selectedDate);\n\t\t\t\t\t\t\t\t\tif (view === 'day' || view === 'timeline-day' || view === 'resource-day')\n\t\t\t\t\t\t\t\t\t\tprev.setDate(prev.getDate() - 1);\n\t\t\t\t\t\t\t\t\telse if (view === 'timeline-3day') prev.setDate(prev.getDate() - 3);\n\t\t\t\t\t\t\t\t\telse if (view === '4day') prev.setDate(prev.getDate() - 4);\n\t\t\t\t\t\t\t\t\telse if (view === 'week' || view === 'timeline-week' || view === 'resource-week')\n\t\t\t\t\t\t\t\t\t\tprev.setDate(prev.getDate() - 7);\n\t\t\t\t\t\t\t\t\telse if (view === 'month') prev.setMonth(prev.getMonth() - 1);\n\t\t\t\t\t\t\t\t\telse if (view === 'year') prev.setFullYear(prev.getFullYear() - 1);\n\t\t\t\t\t\t\t\t\telse prev.setDate(prev.getDate() - 7);\n\t\t\t\t\t\t\t\t\tsetSelectedDate(prev, view);\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tonNavigateNext={() => {\n\t\t\t\t\t\t\t\t\tconst next = new Date(selectedDate);\n\t\t\t\t\t\t\t\t\tif (view === 'day' || view === 'timeline-day' || view === 'resource-day')\n\t\t\t\t\t\t\t\t\t\tnext.setDate(next.getDate() + 1);\n\t\t\t\t\t\t\t\t\telse if (view === 'timeline-3day') next.setDate(next.getDate() + 3);\n\t\t\t\t\t\t\t\t\telse if (view === '4day') next.setDate(next.getDate() + 4);\n\t\t\t\t\t\t\t\t\telse if (view === 'week' || view === 'timeline-week' || view === 'resource-week')\n\t\t\t\t\t\t\t\t\t\tnext.setDate(next.getDate() + 7);\n\t\t\t\t\t\t\t\t\telse if (view === 'month') next.setMonth(next.getMonth() + 1);\n\t\t\t\t\t\t\t\t\telse if (view === 'year') next.setFullYear(next.getFullYear() + 1);\n\t\t\t\t\t\t\t\t\telse next.setDate(next.getDate() + 7);\n\t\t\t\t\t\t\t\t\tsetSelectedDate(next, view);\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tavailableViews={MENU_VIEWS}\n\t\t\t\t\t\t\t\tshowTimelineViews\n\t\t\t\t\t\t\t\t// The header ships its own settings panel now, so this must not be\n\t\t\t\t\t\t\t\t// gated on the consumer supplying content. Hide it with\n\t\t\t\t\t\t\t\t// headerConfig.showSettings instead.\n\t\t\t\t\t\t\t\tshowSettings\n\t\t\t\t\t\t\t\t{...(!headerActions && handleAdd && { onAddEvent: handleAdd })}\n\t\t\t\t\t\t\t\tactions={headerActions}\n\t\t\t\t\t\t\t\tsettingsContent={settingsContent}\n\t\t\t\t\t\t\t\tfilterContent={filterContent}\n\t\t\t\t\t\t\t\t{...(headerConfig && { headerConfig })}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<div className=\"relative flex-1 min-h-0\">\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tref={viewContainerRef}\n\t\t\t\t\t\t\t\tclassName={cn('h-full border rounded-lg bg-white overflow-x-auto')}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{renderView()}\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{/* Loading overlay — shown during data fetching */}\n\t\t\t\t\t\t\t{isLoading && (\n\t\t\t\t\t\t\t\t<div className=\"inno-calendar-loading-overlay\">\n\t\t\t\t\t\t\t\t\t<div className=\"inno-calendar-spinner\" />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* D-pad scroll navigator — appears when content is scrollable */}\n\t\t\t\t\t\t\t<ScrollNavigator containerRef={viewContainerRef} currentDate={selectedDate} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{quickCreate && eventForm && (\n\t\t\t\t\t\t<QuickCreate<TEventData>\n\t\t\t\t\t\t\targs={{\n\t\t\t\t\t\t\t\tselection: quickCreate.selection,\n\t\t\t\t\t\t\t\t...(quickCreate.event && { event: quickCreate.event }),\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t{...(quickCreate.anchor && { anchor: quickCreate.anchor })}\n\t\t\t\t\t\t\trender={eventForm}\n\t\t\t\t\t\t\tonClose={() => setQuickCreate(null)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</SlotSelectionProvider>\n\t\t</TooltipProvider>\n\t);\n\n\t// Only when the consumer gave one: a provider that always renders would make\n\t// every chip read a context that is never set.\n\treturn eventCard ? (\n\t\t<EventCardProvider<TEventData> render={eventCard}>{grid}</EventCardProvider>\n\t) : (\n\t\tgrid\n\t);\n}\n\n// ============================================================================\n// INTEGRATED CALENDAR (wraps provider)\n// ============================================================================\n\n/**\n * InnoCalendar - A fully-featured calendar component with optional ref for imperative control.\n *\n * @example\n * ```tsx\n * const calendarRef = useRef<ICalendarRefHandle>(null);\n *\n * // Scroll to today programmatically\n * <button onClick={() => calendarRef.current?.scrollToToday()}>Go to Today</button>\n *\n * <InnoCalendar\n * ref={calendarRef}\n * events={events}\n * onEventClick={(e) => console.log(e)}\n * />\n * ```\n */\nfunction InnoCalendarInner<TEventData extends Record<string, unknown> = Record<string, unknown>>(\n\t{\n\t\tevents = NO_EVENTS,\n\t\tusers = NO_USERS,\n\t\talwaysShowResources,\n\t\tscheduleTypes = [],\n\t\tinitialView,\n\t\tinitialDate,\n\t\tinitialSelectedUserId,\n\t\tinitialScheduleTypeIds,\n\t\tinitialParticipantIds,\n\t\tinitialWorkingHoursView,\n\t\tinitialSearchQuery,\n\t\tpreferencesConfig,\n\t\tviewPersistence,\n\t\tonEventClick,\n\t\tonSlotClick,\n\t\tonSlotSelect,\n\t\tonAddEvent,\n\t\tonEventDrop,\n\t\tonDateChange,\n\t\tonViewChange,\n\t\tclassName,\n\t\tshowHeader = true,\n\t\tminSelectionMinutes = 30,\n\t\tshowMoreMode,\n\t\tshowMoreEventsInPopover = false,\n\t\tisLoading = false,\n\t\teventDetail,\n\t\tsettingsContent,\n\t\tfilterContent,\n\t\theaderActions,\n\t\tfocusEventId,\n\t\theaderConfig,\n\t\tresourceColumnConfig,\n\t\tfilters,\n\t\tlabels,\n\t\teventCard,\n\t\teventForm,\n\t\tshowSidebar,\n\t\tsidebarContent,\n\t\tcreateLabel,\n\t\tlocale,\n\t}: InnoCalendarProps<TEventData>,\n\tref: React.ForwardedRef<ICalendarRefHandle>\n) {\n\t// A `source` fetches in the background; surface that in the same overlay the\n\t// `isLoading` prop drives, so consumers don't wire a second spinner.\n\n\t// Only the ones that say something — an empty list is not a filter, and\n\n\t// The calendar needs the handle too — a drop opens the card through it — so\n\t// it keeps its own and passes yours along.\n\tconst selfRef = useRef<ICalendarRefHandle | null>(null);\n\tconst setRefs = useCallback(\n\t\t(handle: ICalendarRefHandle | null) => {\n\t\t\tselfRef.current = handle;\n\t\t\tif (typeof ref === 'function') ref(handle);\n\t\t\telse if (ref) ref.current = handle;\n\t\t},\n\t\t[ref]\n\t);\n\n\t/**\n\t * A drag or resize opens the card on the new times rather than writing them.\n\t *\n\t * The default when there is an `eventForm` and you passed no handler of your\n\t * own: a reschedule that mails the participants and syncs a calendar should\n\t * be confirmed, not assumed. Pass `onEventDrop` to take it back, or omit\n\t * `eventForm` to get the optimistic save with undo instead.\n\t */\n\tconst handleDrop = useMemo(() => {\n\t\tif (onEventDrop) return onEventDrop;\n\t\tif (!eventForm) return undefined;\n\t\treturn (result: IDropResult<TEventData>) =>\n\t\t\t// Deferred: the pointerup that ended the drag would otherwise read as\n\t\t\t// the outside click that dismisses the card.\n\t\t\tsetTimeout(\n\t\t\t\t() =>\n\t\t\t\t\tselfRef.current?.openForm({\n\t\t\t\t\t\tevent: result.event,\n\t\t\t\t\t\tstart: result.newStartDate,\n\t\t\t\t\t\tend: result.newEndDate,\n\t\t\t\t\t}),\n\t\t\t\t0\n\t\t\t);\n\t}, [onEventDrop, eventForm]);\n\n\tconst inner = (\n\t\t<InnerCalendar<TEventData>\n\t\t\t{...(onEventClick && { onEventClick })}\n\t\t\t{...(onSlotClick && { onSlotClick })}\n\t\t\t{...(onSlotSelect && { onSlotSelect })}\n\t\t\t{...(onAddEvent && { onAddEvent })}\n\t\t\t{...(alwaysShowResources && { alwaysShowResources })}\n\t\t\t{...(eventDetail && { eventDetail })}\n\t\t\tclassName={className}\n\t\t\tshowHeader={showHeader}\n\t\t\tminSelectionMinutes={minSelectionMinutes}\n\t\t\t{...(showMoreMode && { showMoreMode })}\n\t\t\tshowMoreEventsInPopover={showMoreEventsInPopover}\n\t\t\tisLoading={isLoading}\n\t\t\t{...(eventCard && { eventCard })}\n\t\t\t{...(eventForm && { eventForm })}\n\t\t\tsettingsContent={settingsContent}\n\t\t\tfilterContent={filterContent}\n\t\t\theaderActions={headerActions}\n\t\t\tcalendarRef={setRefs}\n\t\t\t{...(headerConfig && { headerConfig })}\n\t\t\t{...(resourceColumnConfig && { resourceColumnConfig })}\n\t\t\t{...(filters && { filters })}\n\t\t\t{...(labels && { labels })}\n\t\t\t{...(labels?.agenda && { agendaLabels: labels.agenda })}\n\t\t\t{...(showSidebar !== undefined && { showSidebar })}\n\t\t\tsidebarContent={sidebarContent}\n\t\t\t{...(createLabel && { createLabel })}\n\t\t\t{...(locale && { locale })}\n\t\t/>\n\t);\n\n\tconst provider = (children: ReactNode) => (\n\t\t<InnoCalendarProvider<TEventData>\n\t\t\tinitialEvents={events}\n\t\t\tinitialUsers={users}\n\t\t\tinitialScheduleTypes={scheduleTypes}\n\t\t\tallowedViews={MENU_VIEWS}\n\t\t\t{...(initialView && { initialView })}\n\t\t\t{...(initialDate && { initialDate })}\n\t\t\t{...(initialSelectedUserId && { initialSelectedUserId })}\n\t\t\t{...(initialScheduleTypeIds && { initialScheduleTypeIds })}\n\t\t\t{...(initialParticipantIds && { initialParticipantIds })}\n\t\t\t{...(initialWorkingHoursView && { initialWorkingHoursView })}\n\t\t\t{...(initialSearchQuery && { initialSearchQuery })}\n\t\t\t{...(preferencesConfig && { preferencesConfig })}\n\t\t\t{...(viewPersistence && { viewPersistence })}\n\t\t\t{...(onDateChange && { onDateChange })}\n\t\t\t{...(onViewChange && { onViewChange })}\n\t\t\t{...(focusEventId && { initialFocusEventId: focusEventId })}\n\t\t>\n\t\t\t{children}\n\t\t</InnoCalendarProvider>\n\t);\n\n\t// A drop can become a write, so the drag context wraps the provider.\n\treturn (\n\t\t<DragDropProvider<TEventData> {...(handleDrop && { onEventDrop: handleDrop })}>\n\t\t\t{provider(inner)}\n\t\t</DragDropProvider>\n\t);\n}\n\n/**\n * InnoCalendar with forwardRef for imperative methods.\n * Accepts a ref that exposes scrollToToday, scrollToWorkingHours, and getViewRect.\n */\nexport const InnoCalendar = forwardRef(InnoCalendarInner) as <\n\tTEventData extends Record<string, unknown> = Record<string, unknown>,\n>(\n\tprops: InnoCalendarProps<TEventData> & {\n\t\tref?: React.Ref<ICalendarRefHandle>;\n\t}\n) => React.ReactElement;\n\nexport default InnoCalendar;\n"],"names":["EventCardContext","createContext","EventCardProvider","render","children","useOptionalEventCard","useContext","Popover","PopoverPrimitive","PopoverTrigger","PopoverAnchor","PopoverContent","React","className","align","sideOffset","props","ref","jsx","cn","Sheet","SheetPrimitive","SheetTrigger","SheetClose","SheetPortal","SheetOverlay","SheetContent","jsxs","X","SheetHeader","SheetTitle","SheetDescription","TooltipProvider","TooltipPrimitive","Tooltip","TooltipTrigger","TooltipContent","DETAIL_LABEL","useCompact","compact","setCompact","useState","COMPACT_WIDTH","useEffect","onResize","keepOpenForPortalled","event","PORTALLED","DetailPopover","open","onOpenChange","trigger","compactStart","date","locale","formatClockCompact","getEventColorClasses","color","startOfDay","d","EventCard","variant","badgeVariant","onClick","showTime","showDescription","showParticipants","style","disablePopover","renderPopover","enableDrag","enablePageTransition","_pageTransitionDuration","colors","popoverOpen","setPopoverOpen","isDragging","setIsDragging","_transitionActive","setTransitionActive","_transitionRect","setTransitionRect","cardRef","useRef","dragDrop","useOptionalDragDrop","calendarCtx","useOptionalInnoCalendar","timer","isPast","isCanceled","canDrag","eventCardData","cardMeetingTookPlace","statusIcon","XIcon","CheckIcon","cardProductName","cardExtendedProps","cardNrParticipant","cardSiteName","cardSiteCity","hasLocation","handleClick","useCallback","rect","handleClose","handleDragStart","e","handleDragEnd","detailContent","wrapWithDetail","dotButton","reactNodeToText","formatEventTimeDisplay","compactContent","CANCELED_CHIP","fullContent","node","i","UsersIcon","ClockIcon","MapPinIcon","p","EventBlock","position","hourHeight","DEFAULT_HOUR_HEIGHT","durationInMinutes","heightInPixels","isVeryShortEvent","isShortEvent","showDetails","eventData","productName","extendedProps","nrParticipant","siteName","siteCity","isDotVariant","target","resizeDelta","setResizeDelta","isResizing","snapMinutes","canResize","handleResizeStart","handle","startY","originalEnd","minEnd","latestEnd","move","ev","deltaMinutes","snapped","next","finish","cancel","eventCalendar","custom","handleKeyDown","blockButton","Fragment","tooltipContent","MultiDayEventBar","spanDays","isStart","isEnd","barButton","buttonVariants","cva","Button","forwardRef","size","loading","disabled","DropdownMenu","DropdownMenuPrimitive","DropdownMenuTrigger","DropdownMenuSubTrigger","inset","ChevronRight","DropdownMenuSubContent","DropdownMenuContent","DropdownMenuItem","DropdownMenuCheckboxItem","checked","Check","DropdownMenuRadioItem","Circle","DropdownMenuLabel","DropdownMenuSeparator","PencilIcon","TrashIcon","BanIcon","CheckCircleIcon","ChevronDownIcon","CalendarIcon","FileTextIcon","LoaderIcon","DEFAULT_LABELS","IconButton","label","Avatar","src","alt","initials","isClient","imgError","setImgError","ParticipantRow","participant","isEventCanceled","labels","name","n","isOrganizer","confirmStatus","isConfirmed","isDeclined","avatar","showCanceled","SimpleDialog","title","AlertDialog","description","cancelLabel","confirmLabel","onConfirm","isLoading","defaultFormatDate","_format","defaultFormatTimeRange","start","end","timeOptions","formatCanceledDate","useMediaQuery","query","matches","setMatches","mediaQuery","handler","EventPopoverContentInner","onClose","onEdit","onDelete","onCancel","onAccept","onDecline","onConfirmMeeting","canEdit","canDelete","canCancel","isCurrentUserParticipant","isCurrentUserClient","currentUserAcceptStatus","isAcceptLoading","isDeclineLoading","isConfirmLoading","isDeleteLoading","renderParticipant","renderHeaderActions","renderCancelReason","renderDeleteConfirmation","formatDate","formatTimeRange","showDeleteConfirm","setShowDeleteConfirm","isEditable","isRecurring","participantDetails","participantNames","hasParticipantDetails","hasCurrentUserAccepted","hasCurrentUserDeclined","showRsvpButtons","confirmedCount","totalParticipants","eventColor","formatDateRange","getTimeRange","handleEdit","handleCancel","handleDelete","confirmDelete","idx","fallbackParticipant","EventPopover","customLabels","width","isDesktop","contentProps","SLOT_DURATIONS","HOURS","_","Row","Segmented","options","value","onChange","option","HourSelect","hour","CalendarSettings","calendar","text","slotDuration","setSlotDuration","visibleHours","setVisibleHours","showWorkingHoursOnly","setShowWorkingHoursOnly","setBadgeVariant","isPreferenceLocked","locked","key","v","prev","GanttChartSquare","ChevronDown","Gear","LayoutList","ColumnsFour","ListIcon","Columns","Grid2X2","Grid3X3","CALENDAR_VIEWS","VIEW_SHORTCUTS","TIMELINE_VIEWS","RESOURCE_VIEWS","useToolbarTitle","currentDate","view","weekStartsOn","monthYear","startOfWeek","endOfWeek","short","NavChevron","dir","resourceLabel","CalendarHeader","onNavigateToday","onNavigatePrev","onNavigateNext","onNavigate","onViewChange","_onAddEvent","availableViews","_showTimelineViews","_timelineViews","settingsContent","showSettings","filterContent","leadingAction","actions","todayLabel","headerConfig","resolvedShowSettings","toolbarTitle","resolvedShowToday","resolvedShowDateNav","resolvedShowCalViews","resolvedShowFilters","mergedLabels","useMemo","handleToday","handlePrev","handleNext","viewLabel","calendarViewOptions","currentCalendarView","currentViewLabel","found","CONTROL","CONTROL_ICON","viewOption","badgeVariants","Badge","ChevronLeft","MONTH_NAMES","DateNavigator","events","showEventCount","month","year","eventCount","getEventsCountInView","rangeText","getRangeText","TodayButton","today","CARD_WIDTH","WIDE_WIDTH","MARGIN","GAP","QuickCreate","args","anchor","closeLabel","wide","setWide","viewport","setViewport","setPosition","useLayoutEffect","card","place","vh","vw","room","wanted","desiredTop","top","sides","fits","x","chosen","observer","onKey","onPointerDown","id","onHandleDown","startX","origin","up","IC_Z_CARD","createPortal","SCROLL_STEP","HOLD_INTERVAL","HOLD_DELAY","JOYSTICK_DOT_MAX","JOYSTICK_DEAD_ZONE","JOYSTICK_MAX_DISPLACEMENT","JOYSTICK_MAX_SPEED","ChevronUp","ScrollNavigator","containerRef","scrollState","setScrollState","dotOffset","setDotOffset","hasAnyScroll","holdTimerRef","holdIntervalRef","joystickRef","isDraggingRef","dragOriginRef","displacementRef","animFrameRef","navRef","checkScrollState","el","threshold","ro","mo","scrollBy","dx","dy","scrollUp","scrollDown","scrollLeft","scrollRight","clearHold","startHold","action","tag","nav","rafId","updatePosition","offsetParent","parentRect","viewportH","localY","navH","minTop","maxTop","clamped","onScroll","scrollTargets","parent","stopJoystick","handleJoystickDown","tick","y","dist","speed","handleJoystickMove","rawX","rawY","scale","handleDpadKeyDown","dateLabel","Chevron","MiniMonth","selected","onSelect","cursor","setCursor","startOfMonth","weeks","gridStart","week","day","weekdayLetters","base","fmt","monthLabel","c","addMonths","letter","outside","isSameMonth","isToday","active","isSameDay","Plus","CalendarSidebar","onCreate","createLabel","SidebarContents","SidebarSheet","rest","SlidersHorizontal","FilterPanel","isAcceptedEvent","Dot","NowLine","time","owners","onEventClick","line","AgendaView","daysAhead","hour12","emptyState","renderEvent","groups","range","getViewDateRange","from","to","byDay","group","a","b","now","resources","person","showOwners","ownersOf","timeOf","formatClock","dayEvents","nowIndex","index","PANEL_WIDTH","PANEL_MAX_HEIGHT","ANIMATION_DURATION","DayEventsExpansion","isOpen","anchorRect","overlayRef","panelRef","phase","setPhase","lastAnchorRef","effectiveAnchorRect","sortedEvents","expandedPosition","viewportWidth","viewportHeight","left","naturalHeight","handleBackdropClick","isCollapsed","morphRect","panelStyle","backdropOpacity","dateStr","BannerEventPill","isAllDay","detectAllDayEvent","isSingleDayAllDay","pillButton","BannerDefaultPopoverContent","MultiDayBanner","hasAllDay","hasMultiDay","DRAG_THRESHOLD","SelectableSlot","slot","onSelectionStart","onSelectionMove","onSelectionEnd","isSelected","isSelecting","ariaLabel","height","dataAttributes","startPositionRef","isMouseDownRef","buttonRef","isDragOver","setIsDragOver","handlePointerDown","handlePointerMove","handlePointerEnter","handlePointerUp","handleDragOver","minute","handleDragLeave","handleDrop","handleGlobalPointerUp","TimeSlot","slotProp","DaySlot","HOUR_HEIGHT","HOUR_COLUMN_WIDTH","MIN_EVENT_CARD_WIDTH","DayView","workingHours","_onSlotSelect","slotsPerHour","slotHeightPercent","slotMinutes","minutes","getEventsForDay","singleDay","multiDay","separateEventsByDuration","eventPositions","positions","calculateOverlappingPositions","map","positioned","hours","getVisibleHoursArray","showCurrentTime","currentTimeTop","currentHour","scrollContainerRef","container","performScroll","scrollToHour","dayOfWeek","todayWorkingHours","scrollTop","slotSelection","useOptionalSlotSelection","handleSelectionStart","handleSelectionMove","handleSelectionEnd","handleMultiDayEventClick","headerDay","headerDate","isDisabled","isWorkingHour","formatHourLabel","slotIndex","calculatedWidth","minWidthStyle","WEEKDAY_LABELS_MONDAY_START","WEEKDAY_LABELS_SUNDAY_START","MAX_EVENTS_SHOWN","MonthView","onDayClick","_showMoreMode","showMoreMode","openPopoverDay","setOpenPopoverDay","expandedDay","setExpandedDay","cells","generateMonthGrid","eventsByDate","cell","dayKey","handleDayClick","cellDate","weekdayLabels","isWeekend","hasMoreEvents","cellEl","EVENT_ROW_HEIGHT","EVENT_ROW_GAP","MAX_VISIBLE_ROWS","findDayColumn","weekDays","dayStart","weekDay","firstDay","packEventsIntoRows","sorted","spanA","spanB","rows","entry","assignedRow","r","row","free","assignedRowArr","AllDayEventPill","pe","gridStyle","DefaultAllDayPopoverContent","WeekAllDayRow","hourColumnWidth","minDayColumnWidth","dayColumnWidths","packedEvents","mapped","rawStart","rawEnd","startCol","endCol","continuesBefore","continuesAfter","totalRows","visibleRows","hasOverflow","hiddenCount","gridTemplateColumns","w","containerHeight","openMenuClose","claimMenuSlot","close","FieldLayer","anchorRef","matchWidth","pos","setPos","closeRef","panel","below","onDown","IC_Z_LAYER","WEEKDAY_BY_INDEX","ORDINALS","weekday","ordinal","rule","weekdayOrdinal","weekdayOf","isWeekdayRule","sameRule","isoDate","pad","oneYearOn","until","recurrencePresets","supports","freqs","weekdayName","dayMonth","out","controlClass","CustomDialog","onDone","setRule","seed","set","patch","ending","letters","toggleDay","on","IC_Z_MODAL","freq","RecurrenceField","setOpen","setCustom","presets","matched","current","preset","MINUTE","DAY_MINUTES","endOfDay","onDay","sameDay","pillClass","DatePill","menu","onOpen","TimePill","onType","listRef","draft","setDraft","picking","commit","parsed","parseClockText","WhenRow","allDay","step","showAllDay","duration","openMenu","setOpenMenu","menuFor","startOptions","at","endOptions","moveStart","typeStart","typeEnd","setStartDay","nextStart","setEndDay","toggleAllDay","showEndDate","Clock","GUTTER_WIDTH","HEADER_HEIGHT","MIN_COLUMN_WIDTH","MIN_COLUMN_WIDTH_MULTIDAY","resourceIdOf","data","minutesFromMidnight","MINUTES_IN_HOUR","layoutColumn","startHour","overlapsGroup","ResourceColumnsView","dates","dayKeys","columns","known","user","byCell","column","nowOffset","offset","gridHeight","slotHeight","perPersonWidth","resource","laid","s","EVENT_HEIGHT","EVENT_GAP","MIN_ROW_HEIGHT","ROW_PADDING","MIN_HOUR_COLUMN_WIDTH","USER_COLUMN_WIDTH","MAX_SINGLE_COL_EVENTS_BEFORE_EXPAND","DEFAULT_START_HOUR","DEFAULT_END_HOUR","getInitials","generateDateColumns","startDate","numDays","generateHourColumns","endHour","dayIndex","formatHour","formatDayHeader","calculateEventStacks","result","stacks","item","stackIndex","computeHourModeSpan","dateColumns","hoursPerDay","eventStartHour","eventEndHour","spanStartCol","spanEndCol","dayIdx","dayDate","dayEnd","startHourInDay","endHourInDay","dayStartCol","dayEndCol","fallback","MARQUEE_PX_PER_SECOND","MARQUEE_MIN_DURATION","MARQUEE_GAP_PX","MarqueeText","measureRef","state","setState","measure","update","textWidth","containerWidth","distance","durationSec","DEFAULT_DAYS_TO_SHOW","TimelineView","daysToShow","users","alwaysShowResources","selectedDateProp","_onDateChange","onSlotClick","onSlotSelect","getEventUserId","resourceColumnConfig","resourceVariant","showAvatarMode","scrollRef","selection","setSelection","isSelectingRef","dropHighlight","setDropHighlight","selectedDate","isHourMode","viewStartDate","diff","hourColumns","getUserIdFromEvent","effectiveUsers","userMap","dataUser","userRows","eventsByUser","userId","positionEventsForUser","userEvents","rawPositioned","span","positionedEvents","maxStack","max","unassignedEvents","existingIds","singleColEventCounts","counts","colKey","currentCount","columnWidths","totalColumns","baseMinWidth","widths","col","singleColCount","getRowHeight","totalWidth","sum","columnPositions","pixelAtCol","maxIdx","floor","scrollToToday","todayColIndex","centeredScroll","resolveColumnAndMinute","clientX","gridEl","colStart","colEnd","fraction","rawMinute","snappedMinute","dateFromColumn","colIndex","handleRowDragOver","resolved","originalStartDate","originalEndDate","durationMs","totalCols","spanCols","durationHours","handleRowDragLeave","relatedTarget","handleRowDrop","_userId","isCellSelected","resourceId","minCol","maxCol","isCellDropTarget","handleCellPointerDown","handleCellPointerEnter","handleCellPointerUp","startInfo","endInfo","endDate","dayWidth","isFirstOfDay","colWidth","rowHeight","hasImage","cellSelected","cellDropTarget","isInteractive","info","startPos","endPos","isPlaceholder","eventIsPast","eventCanDrag","DAY_HEADER_HEIGHT","MIN_DAY_COLUMN_WIDTH","MAX_EVENTS_BEFORE_EXPAND","WeekView","days","getWeekDays","addDays","eventsPerDay","positionsArray","maxOverlapping","overlapping","weekMultiDayEvents","unique","todayIndex","targetWorkingHours","mondayHours","gridMinWidth","actualGridWidth","hrs","sign","columnWidth","needsExpansion","dayData","WEEKDAY_LABELS","getEventDotStyle","hexColor","DayCell","isCurrentMonth","maxIndicators","onMonthClick","YearView","months","getYearMonths","monthDate","NO_EVENTS","NO_USERS","MENU_VIEWS","getSelectionMode","InnerCalendar","onAddEvent","showHeader","minSelectionMinutes","showMoreEventsInPopover","eventCard","eventForm","headerActions","eventDetail","calendarRef","filters","showSidebar","sidebarContent","resolvedShowMoreMode","setView","setSelectedDate","filteredEvents","contextVisibleHours","clearFocusEventId","useInnoCalendar","effectiveVisibleHours","minFrom","maxTo","innerViewContainerRef","openNowRef","api","setQuickCreate","root","marker","targetHour","eventId","useImperativeHandle","previousView","selectionMode","pointerRef","quickCreate","track","handleSlotSelect","handleMonthClick","handleEventClick","handleTimelineSlotClick","_resourceId","openEventForm","openNow","beside","point","handleAdd","popover","renderView","viewEvents","viewEventClick","viewRenderPopover","getWeekDates","viewContainerRef","sidebarSheetOpen","setSidebarSheetOpen","sidebarNode","grid","SlotSelectionProvider","InnoCalendarInner","scheduleTypes","initialView","initialDate","initialSelectedUserId","initialScheduleTypeIds","initialParticipantIds","initialWorkingHoursView","initialSearchQuery","preferencesConfig","viewPersistence","onEventDrop","onDateChange","focusEventId","selfRef","setRefs","inner","provider","InnoCalendarProvider","DragDropProvider","InnoCalendar"],"mappings":"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"}