@rapidmx/web-client 0.14.1 → 0.16.0

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 (314) hide show
  1. package/README.md +373 -373
  2. package/apps/admin/branding/index.tsx +39 -39
  3. package/apps/admin/data-requests/index.tsx +482 -480
  4. package/apps/admin/domains/[uid].tsx +164 -163
  5. package/apps/admin/escrow-scopes/[uid].tsx +348 -348
  6. package/apps/admin/index.tsx +127 -124
  7. package/apps/admin/mailboxes/[uid].tsx +269 -224
  8. package/apps/admin/mailboxes/new/index.tsx +28 -28
  9. package/apps/admin/plugins/index.tsx +15 -15
  10. package/apps/admin/retention-policy/index.tsx +39 -39
  11. package/apps/admin/signing-certificates/index.tsx +343 -343
  12. package/apps/escrow/audit-log/index.tsx +196 -196
  13. package/apps/escrow/matters/[uid].tsx +621 -621
  14. package/apps/shared/appearance/AppearanceForm.tsx +9 -1
  15. package/apps/shared/auth/adminAccess.ts +99 -99
  16. package/apps/shared/calendar/bookingPlugin.ts +100 -0
  17. package/apps/shared/calendar/calendarLiveUpdates.ts +27 -0
  18. package/apps/shared/components/admin/layout/AdminShell.tsx +378 -346
  19. package/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.tsx +238 -0
  20. package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +152 -152
  21. package/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.tsx +194 -0
  22. package/apps/shared/components/admin/settings/BrandingForm.tsx +423 -423
  23. package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +119 -119
  24. package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +53 -4
  25. package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +198 -198
  26. package/apps/shared/components/admin/settings/PluginsManager.tsx +64 -10
  27. package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +182 -182
  28. package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +288 -288
  29. package/apps/shared/components/admin/setup/SetupWizard.tsx +444 -444
  30. package/apps/shared/components/admin/usePagedList.tsx +129 -129
  31. package/apps/shared/components/calendar/AppointmentQuickForm.tsx +327 -0
  32. package/apps/shared/components/calendar/DescriptionEditor.tsx +274 -0
  33. package/apps/shared/components/calendar/EventDescriptionView.tsx +70 -0
  34. package/apps/shared/components/calendar/EventDetails.tsx +401 -0
  35. package/apps/shared/components/calendar/EventEditor.tsx +635 -0
  36. package/apps/shared/components/calendar/EventExpandedForm.tsx +210 -0
  37. package/apps/shared/components/calendar/EventFormParts.tsx +591 -0
  38. package/apps/shared/components/calendar/EventModal.tsx +206 -946
  39. package/apps/shared/components/calendar/EventQuickForm.tsx +116 -0
  40. package/apps/shared/components/calendar/EventShell.tsx +202 -0
  41. package/apps/shared/components/calendar/FindATime.tsx +379 -0
  42. package/apps/shared/components/calendar/GuestInput.tsx +100 -0
  43. package/apps/shared/components/calendar/LazyDescriptionEditor.tsx +70 -0
  44. package/apps/shared/components/calendar/MonthView.tsx +185 -173
  45. package/apps/shared/components/calendar/QuickCreateFaces.tsx +87 -0
  46. package/apps/shared/components/calendar/QuickCreateTabs.tsx +81 -0
  47. package/apps/shared/components/calendar/QuickFaceFrame.tsx +81 -0
  48. package/apps/shared/components/calendar/RecurrenceEditor.tsx +227 -222
  49. package/apps/shared/components/calendar/RequestChangeForm.tsx +240 -0
  50. package/apps/shared/components/calendar/SplitDayView.tsx +144 -143
  51. package/apps/shared/components/calendar/TaskQuickForm.tsx +289 -0
  52. package/apps/shared/components/calendar/TimeGridView.tsx +246 -244
  53. package/apps/shared/components/calendar/allDay.ts +124 -124
  54. package/apps/shared/components/calendar/eventDialogFields.ts +86 -0
  55. package/apps/shared/components/calendar/eventForm.ts +108 -0
  56. package/apps/shared/components/calendar/eventFormat.ts +210 -0
  57. package/apps/shared/components/calendar/findTimeGrid.ts +90 -0
  58. package/apps/shared/components/calendar/layout/CalendarShell.tsx +201 -200
  59. package/apps/shared/components/calendar/swipeNavigation.ts +14 -0
  60. package/apps/shared/components/contacts/ContactForm.tsx +383 -383
  61. package/apps/shared/components/contacts/ContactsSidebar.tsx +1 -1
  62. package/apps/shared/components/contacts/ContactsToolbar.tsx +103 -98
  63. package/apps/shared/components/contacts/layout/ContactsShell.tsx +217 -216
  64. package/apps/shared/components/escrow/layout/EscrowShell.tsx +155 -155
  65. package/apps/shared/components/layout/AppShell.tsx +480 -480
  66. package/apps/shared/components/layout/FloatingActionButton.tsx +31 -0
  67. package/apps/shared/components/layout/KeyEnrollmentGate.tsx +398 -398
  68. package/apps/shared/components/layout/MailboxProvisioning.tsx +168 -168
  69. package/apps/shared/components/layout/ResponsiveToolbar.tsx +315 -315
  70. package/apps/shared/components/layout/ThemeSwitch.tsx +84 -84
  71. package/apps/shared/components/layout/UserMenu.tsx +439 -372
  72. package/apps/shared/components/mail/ConversationList.tsx +323 -271
  73. package/apps/shared/components/mail/ConversationThreadPane.tsx +130 -5
  74. package/apps/shared/components/mail/InviteCard.tsx +387 -0
  75. package/apps/shared/components/mail/MailSelectionBar.tsx +236 -227
  76. package/apps/shared/components/mail/MessageDetailPane.tsx +1559 -1537
  77. package/apps/shared/components/mail/SwipeRow.tsx +120 -0
  78. package/apps/shared/components/mail/compose/ComposeContext.tsx +312 -312
  79. package/apps/shared/components/mail/compose/ComposeToolbar.tsx +422 -422
  80. package/apps/shared/components/mail/compose/ComposeWindow.tsx +1681 -1673
  81. package/apps/shared/components/mail/compose/RecipientInput.tsx +54 -11
  82. package/apps/shared/components/mail/compose/RichTextEditor.tsx +147 -147
  83. package/apps/shared/components/mail/compose/composeFlushRegistry.ts +60 -60
  84. package/apps/shared/components/mail/compose/quotedBody.ts +161 -161
  85. package/apps/shared/components/mail/invite/InviteRowChip.tsx +104 -0
  86. package/apps/shared/components/mail/invite/InviteRsvpPopover.tsx +271 -0
  87. package/apps/shared/components/mail/invite/InviteTimeline.tsx +200 -0
  88. package/apps/shared/components/mail/invite/ProposeTimeForm.tsx +109 -0
  89. package/apps/shared/components/mail/invite/inviteFormat.ts +110 -0
  90. package/apps/shared/components/mail/invite/inviteStore.ts +114 -0
  91. package/apps/shared/components/mail/layout/FolderBadgeChip.tsx +21 -0
  92. package/apps/shared/components/mail/layout/MailShell.tsx +546 -490
  93. package/apps/shared/components/mail/layout/SidebarSection.tsx +66 -0
  94. package/apps/shared/components/mail/reading/PendingMessageCard.tsx +68 -0
  95. package/apps/shared/components/mail/verificationSeals.ts +125 -125
  96. package/apps/shared/components/rules/RuleBuilder.tsx +311 -311
  97. package/apps/shared/components/settings/SigningCertificateCard.tsx +344 -344
  98. package/apps/shared/components/settings/layout/SettingsShell.tsx +255 -253
  99. package/apps/shared/components/tasks/TasksSidebar.tsx +1 -1
  100. package/apps/shared/components/tasks/layout/TasksShell.tsx +218 -217
  101. package/apps/shared/gestures/useEnterSlide.ts +54 -0
  102. package/apps/shared/gestures/useSwipe.ts +114 -0
  103. package/apps/shared/gestures/useSwipeSlide.ts +113 -0
  104. package/apps/shared/gestures/useWheelPaging.ts +107 -0
  105. package/apps/shared/keyboard/GlobalShortcuts.tsx +51 -51
  106. package/apps/shared/keyboard/ShortcutProvider.tsx +62 -62
  107. package/apps/shared/keyboard/ShortcutsDialog.tsx +84 -84
  108. package/apps/shared/keyboard/dispatch.ts +124 -124
  109. package/apps/shared/keyboard/format.ts +89 -89
  110. package/apps/shared/keyboard/keymap.ts +114 -114
  111. package/apps/shared/keyboard/registry.ts +65 -65
  112. package/apps/shared/keyboard/targets.ts +79 -79
  113. package/apps/shared/mail/folderCounts.ts +17 -0
  114. package/apps/shared/mail/folderTree.ts +143 -143
  115. package/apps/shared/mail/listAllPages.ts +39 -39
  116. package/apps/shared/mail/newMailNotifications.ts +3 -15
  117. package/apps/shared/mail/outbox/outgoingReplies.ts +192 -0
  118. package/apps/shared/mail/outbox/sendJob.ts +19 -1
  119. package/apps/shared/mail/outbox/sendOutcomes.ts +13 -4
  120. package/apps/shared/mail/primaryMailbox.ts +71 -0
  121. package/apps/shared/mail/useCollapsedSections.ts +146 -0
  122. package/apps/shared/mail/useMailConnection.ts +205 -203
  123. package/apps/shared/mail/useMailLiveUpdates.ts +277 -277
  124. package/apps/shared/mail/useMarkMessageRead.ts +47 -47
  125. package/apps/shared/mail/useNewMailNotifications.ts +2 -2
  126. package/apps/shared/navigation/AppRouter.tsx +300 -300
  127. package/apps/shared/navigation/routerContext.tsx +83 -83
  128. package/apps/shared/notifications/preferences.ts +36 -0
  129. package/apps/shared/notifications/store.ts +9 -0
  130. package/apps/shared/search/LocalIndexLifecycle.tsx +114 -114
  131. package/apps/shared/search/crossMailboxSearch.ts +169 -0
  132. package/apps/shared/search/localIndexBuilder.ts +481 -481
  133. package/apps/shared/signing/enrollmentStorage.ts +33 -33
  134. package/apps/shared/signing/enrollmentTracker.ts +385 -385
  135. package/apps/shared/signing/enrollmentView.ts +251 -251
  136. package/apps/shared/signing/useNow.ts +19 -19
  137. package/apps/shared/signing/useSigningEnrollmentWatcher.ts +90 -90
  138. package/apps/shared/styles/app.css +396 -386
  139. package/apps/www/_routes.ts +1 -0
  140. package/apps/www/calendar/index.tsx +578 -469
  141. package/apps/www/contacts/[uid].tsx +109 -109
  142. package/apps/www/contacts/index.tsx +6 -0
  143. package/apps/www/index.tsx +2847 -2332
  144. package/apps/www/messages/[uid].tsx +135 -108
  145. package/apps/www/settings/auto-reply/index.tsx +133 -133
  146. package/apps/www/settings/encryption/index.tsx +1287 -1287
  147. package/apps/www/settings/filters/[uid].tsx +176 -176
  148. package/apps/www/settings/filters/index.tsx +102 -102
  149. package/apps/www/settings/filters/new/index.tsx +140 -140
  150. package/apps/www/settings/labels/index.tsx +204 -204
  151. package/apps/www/settings/privacy/index.tsx +492 -492
  152. package/apps/www/settings/profile/index.tsx +248 -0
  153. package/apps/www/settings/read-receipts/index.tsx +147 -147
  154. package/apps/www/settings/sharing/index.tsx +256 -256
  155. package/apps/www/settings/signatures/[uid].tsx +172 -172
  156. package/apps/www/settings/signatures/index.tsx +88 -88
  157. package/apps/www/settings/signatures/new/index.tsx +135 -135
  158. package/apps/www/tasks/index.tsx +649 -649
  159. package/dist/apps/admin/data-requests/index.js +1 -1
  160. package/dist/apps/admin/domains/[uid].js +4 -2
  161. package/dist/apps/admin/index.js +2 -1
  162. package/dist/apps/admin/mailboxes/[uid].js +12 -2
  163. package/dist/apps/shared/appearance/AppearanceForm.js +9 -1
  164. package/dist/apps/shared/calendar/bookingPlugin.d.ts +50 -0
  165. package/dist/apps/shared/calendar/bookingPlugin.js +57 -0
  166. package/dist/apps/shared/calendar/calendarLiveUpdates.d.ts +11 -0
  167. package/dist/apps/shared/calendar/calendarLiveUpdates.js +23 -0
  168. package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
  169. package/dist/apps/shared/components/admin/layout/AdminShell.js +7 -3
  170. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.d.ts +35 -0
  171. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.js +115 -0
  172. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.d.ts +16 -0
  173. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.js +92 -0
  174. package/dist/apps/shared/components/admin/settings/BrandingForm.js +3 -3
  175. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +28 -4
  176. package/dist/apps/shared/components/admin/settings/PluginsManager.js +40 -6
  177. package/dist/apps/shared/components/calendar/AppointmentQuickForm.d.ts +47 -0
  178. package/dist/apps/shared/components/calendar/AppointmentQuickForm.js +135 -0
  179. package/dist/apps/shared/components/calendar/DescriptionEditor.d.ts +26 -0
  180. package/dist/apps/shared/components/calendar/DescriptionEditor.js +192 -0
  181. package/dist/apps/shared/components/calendar/EventDescriptionView.d.ts +14 -0
  182. package/dist/apps/shared/components/calendar/EventDescriptionView.js +39 -0
  183. package/dist/apps/shared/components/calendar/EventDetails.d.ts +33 -0
  184. package/dist/apps/shared/components/calendar/EventDetails.js +137 -0
  185. package/dist/apps/shared/components/calendar/EventEditor.d.ts +59 -0
  186. package/dist/apps/shared/components/calendar/EventEditor.js +544 -0
  187. package/dist/apps/shared/components/calendar/EventExpandedForm.d.ts +14 -0
  188. package/dist/apps/shared/components/calendar/EventExpandedForm.js +44 -0
  189. package/dist/apps/shared/components/calendar/EventFormParts.d.ts +70 -0
  190. package/dist/apps/shared/components/calendar/EventFormParts.js +191 -0
  191. package/dist/apps/shared/components/calendar/EventModal.d.ts +26 -13
  192. package/dist/apps/shared/components/calendar/EventModal.js +57 -459
  193. package/dist/apps/shared/components/calendar/EventQuickForm.d.ts +18 -0
  194. package/dist/apps/shared/components/calendar/EventQuickForm.js +25 -0
  195. package/dist/apps/shared/components/calendar/EventShell.d.ts +64 -0
  196. package/dist/apps/shared/components/calendar/EventShell.js +134 -0
  197. package/dist/apps/shared/components/calendar/FindATime.d.ts +18 -0
  198. package/dist/apps/shared/components/calendar/FindATime.js +190 -0
  199. package/dist/apps/shared/components/calendar/GuestInput.d.ts +45 -0
  200. package/dist/apps/shared/components/calendar/GuestInput.js +30 -0
  201. package/dist/apps/shared/components/calendar/LazyDescriptionEditor.d.ts +8 -0
  202. package/dist/apps/shared/components/calendar/LazyDescriptionEditor.js +44 -0
  203. package/dist/apps/shared/components/calendar/MonthView.d.ts +5 -1
  204. package/dist/apps/shared/components/calendar/MonthView.js +11 -5
  205. package/dist/apps/shared/components/calendar/QuickCreateFaces.d.ts +30 -0
  206. package/dist/apps/shared/components/calendar/QuickCreateFaces.js +44 -0
  207. package/dist/apps/shared/components/calendar/QuickCreateTabs.d.ts +24 -0
  208. package/dist/apps/shared/components/calendar/QuickCreateTabs.js +46 -0
  209. package/dist/apps/shared/components/calendar/QuickFaceFrame.d.ts +25 -0
  210. package/dist/apps/shared/components/calendar/QuickFaceFrame.js +19 -0
  211. package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +4 -1
  212. package/dist/apps/shared/components/calendar/RecurrenceEditor.js +2 -2
  213. package/dist/apps/shared/components/calendar/RequestChangeForm.d.ts +36 -0
  214. package/dist/apps/shared/components/calendar/RequestChangeForm.js +127 -0
  215. package/dist/apps/shared/components/calendar/SplitDayView.d.ts +3 -2
  216. package/dist/apps/shared/components/calendar/SplitDayView.js +3 -2
  217. package/dist/apps/shared/components/calendar/TaskQuickForm.d.ts +40 -0
  218. package/dist/apps/shared/components/calendar/TaskQuickForm.js +101 -0
  219. package/dist/apps/shared/components/calendar/TimeGridView.d.ts +4 -2
  220. package/dist/apps/shared/components/calendar/TimeGridView.js +3 -2
  221. package/dist/apps/shared/components/calendar/eventDialogFields.d.ts +28 -0
  222. package/dist/apps/shared/components/calendar/eventDialogFields.js +59 -0
  223. package/dist/apps/shared/components/calendar/eventForm.d.ts +98 -0
  224. package/dist/apps/shared/components/calendar/eventForm.js +1 -0
  225. package/dist/apps/shared/components/calendar/eventFormat.d.ts +80 -0
  226. package/dist/apps/shared/components/calendar/eventFormat.js +190 -0
  227. package/dist/apps/shared/components/calendar/findTimeGrid.d.ts +30 -0
  228. package/dist/apps/shared/components/calendar/findTimeGrid.js +83 -0
  229. package/dist/apps/shared/components/calendar/layout/CalendarShell.js +3 -2
  230. package/dist/apps/shared/components/calendar/swipeNavigation.d.ts +9 -0
  231. package/dist/apps/shared/components/calendar/swipeNavigation.js +8 -0
  232. package/dist/apps/shared/components/contacts/ContactsSidebar.js +1 -1
  233. package/dist/apps/shared/components/contacts/ContactsToolbar.d.ts +3 -1
  234. package/dist/apps/shared/components/contacts/ContactsToolbar.js +4 -2
  235. package/dist/apps/shared/components/contacts/layout/ContactsShell.js +4 -3
  236. package/dist/apps/shared/components/layout/FloatingActionButton.d.ts +13 -0
  237. package/dist/apps/shared/components/layout/FloatingActionButton.js +9 -0
  238. package/dist/apps/shared/components/layout/UserMenu.d.ts +14 -9
  239. package/dist/apps/shared/components/layout/UserMenu.js +74 -26
  240. package/dist/apps/shared/components/mail/ConversationList.d.ts +12 -1
  241. package/dist/apps/shared/components/mail/ConversationList.js +21 -4
  242. package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +4 -1
  243. package/dist/apps/shared/components/mail/ConversationThreadPane.js +127 -22
  244. package/dist/apps/shared/components/mail/InviteCard.d.ts +20 -0
  245. package/dist/apps/shared/components/mail/InviteCard.js +150 -0
  246. package/dist/apps/shared/components/mail/MailSelectionBar.d.ts +6 -1
  247. package/dist/apps/shared/components/mail/MailSelectionBar.js +3 -3
  248. package/dist/apps/shared/components/mail/MessageDetailPane.js +13 -2
  249. package/dist/apps/shared/components/mail/SwipeRow.d.ts +22 -0
  250. package/dist/apps/shared/components/mail/SwipeRow.js +71 -0
  251. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +16 -7
  252. package/dist/apps/shared/components/mail/compose/RecipientInput.d.ts +21 -1
  253. package/dist/apps/shared/components/mail/compose/RecipientInput.js +18 -10
  254. package/dist/apps/shared/components/mail/invite/InviteRowChip.d.ts +23 -0
  255. package/dist/apps/shared/components/mail/invite/InviteRowChip.js +46 -0
  256. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.d.ts +20 -0
  257. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.js +141 -0
  258. package/dist/apps/shared/components/mail/invite/InviteTimeline.d.ts +27 -0
  259. package/dist/apps/shared/components/mail/invite/InviteTimeline.js +120 -0
  260. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.d.ts +17 -0
  261. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.js +45 -0
  262. package/dist/apps/shared/components/mail/invite/inviteFormat.d.ts +28 -0
  263. package/dist/apps/shared/components/mail/invite/inviteFormat.js +94 -0
  264. package/dist/apps/shared/components/mail/invite/inviteStore.d.ts +28 -0
  265. package/dist/apps/shared/components/mail/invite/inviteStore.js +95 -0
  266. package/dist/apps/shared/components/mail/layout/FolderBadgeChip.d.ts +6 -0
  267. package/dist/apps/shared/components/mail/layout/FolderBadgeChip.js +9 -0
  268. package/dist/apps/shared/components/mail/layout/MailShell.d.ts +10 -0
  269. package/dist/apps/shared/components/mail/layout/MailShell.js +76 -46
  270. package/dist/apps/shared/components/mail/layout/SidebarSection.d.ts +23 -0
  271. package/dist/apps/shared/components/mail/layout/SidebarSection.js +16 -0
  272. package/dist/apps/shared/components/mail/reading/PendingMessageCard.d.ts +14 -0
  273. package/dist/apps/shared/components/mail/reading/PendingMessageCard.js +16 -0
  274. package/dist/apps/shared/components/settings/layout/SettingsShell.js +7 -5
  275. package/dist/apps/shared/components/tasks/TasksSidebar.js +1 -1
  276. package/dist/apps/shared/components/tasks/layout/TasksShell.js +4 -3
  277. package/dist/apps/shared/gestures/useEnterSlide.d.ts +14 -0
  278. package/dist/apps/shared/gestures/useEnterSlide.js +47 -0
  279. package/dist/apps/shared/gestures/useSwipe.d.ts +45 -0
  280. package/dist/apps/shared/gestures/useSwipe.js +90 -0
  281. package/dist/apps/shared/gestures/useSwipeSlide.d.ts +40 -0
  282. package/dist/apps/shared/gestures/useSwipeSlide.js +95 -0
  283. package/dist/apps/shared/gestures/useWheelPaging.d.ts +32 -0
  284. package/dist/apps/shared/gestures/useWheelPaging.js +85 -0
  285. package/dist/apps/shared/mail/folderCounts.d.ts +10 -0
  286. package/dist/apps/shared/mail/folderCounts.js +12 -0
  287. package/dist/apps/shared/mail/newMailNotifications.d.ts +3 -8
  288. package/dist/apps/shared/mail/newMailNotifications.js +3 -12
  289. package/dist/apps/shared/mail/outbox/outgoingReplies.d.ts +80 -0
  290. package/dist/apps/shared/mail/outbox/outgoingReplies.js +131 -0
  291. package/dist/apps/shared/mail/outbox/sendJob.d.ts +5 -1
  292. package/dist/apps/shared/mail/outbox/sendJob.js +14 -1
  293. package/dist/apps/shared/mail/outbox/sendOutcomes.js +13 -4
  294. package/dist/apps/shared/mail/primaryMailbox.d.ts +29 -0
  295. package/dist/apps/shared/mail/primaryMailbox.js +61 -0
  296. package/dist/apps/shared/mail/useCollapsedSections.d.ts +32 -0
  297. package/dist/apps/shared/mail/useCollapsedSections.js +110 -0
  298. package/dist/apps/shared/mail/useMailConnection.js +3 -1
  299. package/dist/apps/shared/mail/useNewMailNotifications.js +3 -2
  300. package/dist/apps/shared/notifications/preferences.d.ts +13 -0
  301. package/dist/apps/shared/notifications/preferences.js +36 -0
  302. package/dist/apps/shared/notifications/store.d.ts +1 -0
  303. package/dist/apps/shared/notifications/store.js +7 -23
  304. package/dist/apps/shared/search/crossMailboxSearch.d.ts +72 -0
  305. package/dist/apps/shared/search/crossMailboxSearch.js +136 -0
  306. package/dist/apps/shared/styles/app.css +396 -386
  307. package/dist/apps/www/_routes.js +1 -0
  308. package/dist/apps/www/calendar/index.js +78 -7
  309. package/dist/apps/www/contacts/index.js +3 -1
  310. package/dist/apps/www/index.js +548 -210
  311. package/dist/apps/www/messages/[uid].js +13 -5
  312. package/dist/apps/www/settings/profile/index.d.ts +4 -0
  313. package/dist/apps/www/settings/profile/index.js +124 -0
  314. package/package.json +2 -2
@@ -1,124 +1,124 @@
1
- ///////////////////////////////////////////////////////////////////////////////
2
- // Copyright (C) 2026 Jean-Philippe Steinmetz
3
- // SPDX-License-Identifier: MPL-2.0
4
- ///////////////////////////////////////////////////////////////////////////////
5
- import { format } from "date-fns";
6
- import { WeekdayCode } from "@rapidmx/react-shared/calendar/calendarApi.js";
7
- import { CalendarOccurrence, toEventWallClock } from "@rapidmx/react-shared/calendar/recurrence.js";
8
-
9
- const MS_PER_DAY = 86_400_000;
10
-
11
- /**
12
- * All-day events are stored date-only: `startDate` is UTC midnight of the first day and `endDate` is UTC
13
- * midnight of the day *after* the last day (exclusive, like iCalendar's `DTEND;VALUE=DATE`). That keeps
14
- * an all-day event on the same calendar date for every viewer, whatever their timezone.
15
- *
16
- * Older events were saved as the creator's *local* midnight converted to UTC (e.g. `...T22:00Z` for a
17
- * UTC+2 creator), so reading one rounds the instant to the nearest UTC midnight rather than slicing the
18
- * ISO string — which gives the intended date for both formats.
19
- */
20
- export function allDayDateKey(iso: string): string {
21
- const rounded = Math.round(new Date(iso).getTime() / MS_PER_DAY) * MS_PER_DAY;
22
- return new Date(rounded).toISOString().slice(0, 10);
23
- }
24
-
25
- /** `YYYY-MM-DD` -> the stored UTC-midnight instant for that date. */
26
- export function allDayInstant(dateKey: string): string {
27
- return `${dateKey}T00:00:00.000Z`;
28
- }
29
-
30
- /** Adds `days` to a `YYYY-MM-DD` date key. */
31
- export function addDaysToKey(dateKey: string, days: number): string {
32
- return new Date(new Date(allDayInstant(dateKey)).getTime() + days * MS_PER_DAY).toISOString().slice(0, 10);
33
- }
34
-
35
- /** The local calendar date `day` (a local-midnight `Date` from a grid view) as a `YYYY-MM-DD` key. */
36
- export function localDateKey(day: Date): string {
37
- return format(day, "yyyy-MM-dd");
38
- }
39
-
40
- /**
41
- * A recurrence rule's inclusive "Ends on" date -> its stored `until` instant: the end of that day in the
42
- * frame the series expands in. A timed series expands in its own (normally the viewer's) timezone, so that's
43
- * the end of the local day - `new Date("YYYY-MM-DD")` would be UTC midnight, the previous day west of UTC.
44
- * An all-day series expands in UTC (react-shared's `expandOccurrences`), so it's the end of the UTC day: the
45
- * local end of day is already the next UTC day west of UTC and would add one more occurrence.
46
- */
47
- export function recurrenceUntilInstant(dateKey: string, allDay: boolean): string {
48
- if (allDay) {
49
- return `${dateKey}T23:59:59.999Z`;
50
- }
51
- const [y, m, d] = dateKey.split("-").map(Number);
52
- return new Date(y, m - 1, d, 23, 59, 59, 999).toISOString();
53
- }
54
-
55
- /** The stored form of an all-day series' "Ends on" date - the last millisecond of that UTC day. */
56
- const ALL_DAY_UNTIL_PATTERN = /^(\d{4}-\d{2}-\d{2})T23:59:59\.999Z$/;
57
- /** A bare UTC midnight - how the oldest editor (and date-only `UNTIL` values) stored the chosen date itself. */
58
- const UTC_MIDNIGHT_PATTERN = /^(\d{4}-\d{2}-\d{2})T00:00:00(?:\.000)?Z$/;
59
-
60
- /**
61
- * Inverse of `recurrenceUntilInstant()`. An all-day series' value is recognized explicitly in its stored
62
- * `T23:59:59.999Z` form (and as a bare UTC midnight, the oldest form). Anything else is a legacy value stored
63
- * as the creator's *local* end of day, which can land anywhere from just before 10:00Z on the chosen date (UTC+14)
64
- * to just before 12:00Z the day after (UTC-12) - a 26-hour spread no UTC-only rounding can resolve (UTC+14 and UTC-10
65
- * creators' values are exactly 24h apart for the same date), so it reads back on the local calendar, the
66
- * frame it was written in.
67
- */
68
- export function recurrenceUntilDateKey(until: string, allDay: boolean): string {
69
- if (allDay) {
70
- const stored = ALL_DAY_UNTIL_PATTERN.exec(until) ?? UTC_MIDNIGHT_PATTERN.exec(until);
71
- if (stored) {
72
- return stored[1];
73
- }
74
- }
75
- return format(new Date(until), "yyyy-MM-dd");
76
- }
77
-
78
- /** `Date#getUTCDay()` index -> RFC 5545 weekday code. */
79
- const JS_WEEKDAY_CODES: WeekdayCode[] = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
80
-
81
- /** The weekday an event starts on, in the frame its series expands in: the UTC date for an all-day event
82
- * (`start`'s date part), the event's own timezone otherwise (`start` being a local `datetime-local` value).
83
- * `undefined` while the start input is empty/invalid. */
84
- export function startWeekdayCode(start: string, allDay: boolean, timezone: string | undefined): WeekdayCode | undefined {
85
- const ms = allDay ? new Date(allDayInstant(start.slice(0, 10))).getTime() : new Date(start).getTime();
86
- if (Number.isNaN(ms)) {
87
- return undefined;
88
- }
89
- return JS_WEEKDAY_CODES[new Date(toEventWallClock(ms, timezone, allDay)).getUTCDay()];
90
- }
91
-
92
- /**
93
- * Whether `occurrence` should be shown on the grid's local calendar day `day`. All-day events cover every
94
- * date from their start date up to (not including) their exclusive end date — at least their start date.
95
- * Timed events cover every local day their [start, end) interval overlaps, so a multi-day event shows on
96
- * each day rather than only on its start day.
97
- */
98
- export function occursOnDay(occurrence: CalendarOccurrence, day: Date): boolean {
99
- if (occurrence.allDay) {
100
- const key = localDateKey(day);
101
- const startKey = allDayDateKey(occurrence.startDate);
102
- const endKey = allDayDateKey(occurrence.endDate);
103
- return key === startKey || (key > startKey && key < endKey);
104
- }
105
- const dayStart = new Date(day.getFullYear(), day.getMonth(), day.getDate());
106
- const dayEnd = new Date(day.getFullYear(), day.getMonth(), day.getDate() + 1);
107
- const start = new Date(occurrence.startDate);
108
- const end = new Date(occurrence.endDate);
109
- if (start.getTime() === end.getTime()) {
110
- return start >= dayStart && start < dayEnd;
111
- }
112
- return start < dayEnd && end > dayStart;
113
- }
114
-
115
- /**
116
- * Whether `day` is the first day `occurrence` covers. Grid views only make that day's chip/block
117
- * draggable — a drag id must be unique, so the continuation copies on later days are display-only.
118
- */
119
- export function startsOnDay(occurrence: CalendarOccurrence, day: Date): boolean {
120
- if (occurrence.allDay) {
121
- return allDayDateKey(occurrence.startDate) === localDateKey(day);
122
- }
123
- return localDateKey(new Date(occurrence.startDate)) === localDateKey(day);
124
- }
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import { format } from "date-fns";
6
+ import { WeekdayCode } from "@rapidmx/react-shared/calendar/calendarApi.js";
7
+ import { CalendarOccurrence, toEventWallClock } from "@rapidmx/react-shared/calendar/recurrence.js";
8
+
9
+ const MS_PER_DAY = 86_400_000;
10
+
11
+ /**
12
+ * All-day events are stored date-only: `startDate` is UTC midnight of the first day and `endDate` is UTC
13
+ * midnight of the day *after* the last day (exclusive, like iCalendar's `DTEND;VALUE=DATE`). That keeps
14
+ * an all-day event on the same calendar date for every viewer, whatever their timezone.
15
+ *
16
+ * Older events were saved as the creator's *local* midnight converted to UTC (e.g. `...T22:00Z` for a
17
+ * UTC+2 creator), so reading one rounds the instant to the nearest UTC midnight rather than slicing the
18
+ * ISO string — which gives the intended date for both formats.
19
+ */
20
+ export function allDayDateKey(iso: string): string {
21
+ const rounded = Math.round(new Date(iso).getTime() / MS_PER_DAY) * MS_PER_DAY;
22
+ return new Date(rounded).toISOString().slice(0, 10);
23
+ }
24
+
25
+ /** `YYYY-MM-DD` -> the stored UTC-midnight instant for that date. */
26
+ export function allDayInstant(dateKey: string): string {
27
+ return `${dateKey}T00:00:00.000Z`;
28
+ }
29
+
30
+ /** Adds `days` to a `YYYY-MM-DD` date key. */
31
+ export function addDaysToKey(dateKey: string, days: number): string {
32
+ return new Date(new Date(allDayInstant(dateKey)).getTime() + days * MS_PER_DAY).toISOString().slice(0, 10);
33
+ }
34
+
35
+ /** The local calendar date `day` (a local-midnight `Date` from a grid view) as a `YYYY-MM-DD` key. */
36
+ export function localDateKey(day: Date): string {
37
+ return format(day, "yyyy-MM-dd");
38
+ }
39
+
40
+ /**
41
+ * A recurrence rule's inclusive "Ends on" date -> its stored `until` instant: the end of that day in the
42
+ * frame the series expands in. A timed series expands in its own (normally the viewer's) timezone, so that's
43
+ * the end of the local day - `new Date("YYYY-MM-DD")` would be UTC midnight, the previous day west of UTC.
44
+ * An all-day series expands in UTC (react-shared's `expandOccurrences`), so it's the end of the UTC day: the
45
+ * local end of day is already the next UTC day west of UTC and would add one more occurrence.
46
+ */
47
+ export function recurrenceUntilInstant(dateKey: string, allDay: boolean): string {
48
+ if (allDay) {
49
+ return `${dateKey}T23:59:59.999Z`;
50
+ }
51
+ const [y, m, d] = dateKey.split("-").map(Number);
52
+ return new Date(y, m - 1, d, 23, 59, 59, 999).toISOString();
53
+ }
54
+
55
+ /** The stored form of an all-day series' "Ends on" date - the last millisecond of that UTC day. */
56
+ const ALL_DAY_UNTIL_PATTERN = /^(\d{4}-\d{2}-\d{2})T23:59:59\.999Z$/;
57
+ /** A bare UTC midnight - how the oldest editor (and date-only `UNTIL` values) stored the chosen date itself. */
58
+ const UTC_MIDNIGHT_PATTERN = /^(\d{4}-\d{2}-\d{2})T00:00:00(?:\.000)?Z$/;
59
+
60
+ /**
61
+ * Inverse of `recurrenceUntilInstant()`. An all-day series' value is recognized explicitly in its stored
62
+ * `T23:59:59.999Z` form (and as a bare UTC midnight, the oldest form). Anything else is a legacy value stored
63
+ * as the creator's *local* end of day, which can land anywhere from just before 10:00Z on the chosen date (UTC+14)
64
+ * to just before 12:00Z the day after (UTC-12) - a 26-hour spread no UTC-only rounding can resolve (UTC+14 and UTC-10
65
+ * creators' values are exactly 24h apart for the same date), so it reads back on the local calendar, the
66
+ * frame it was written in.
67
+ */
68
+ export function recurrenceUntilDateKey(until: string, allDay: boolean): string {
69
+ if (allDay) {
70
+ const stored = ALL_DAY_UNTIL_PATTERN.exec(until) ?? UTC_MIDNIGHT_PATTERN.exec(until);
71
+ if (stored) {
72
+ return stored[1];
73
+ }
74
+ }
75
+ return format(new Date(until), "yyyy-MM-dd");
76
+ }
77
+
78
+ /** `Date#getUTCDay()` index -> RFC 5545 weekday code. */
79
+ const JS_WEEKDAY_CODES: WeekdayCode[] = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
80
+
81
+ /** The weekday an event starts on, in the frame its series expands in: the UTC date for an all-day event
82
+ * (`start`'s date part), the event's own timezone otherwise (`start` being a local `datetime-local` value).
83
+ * `undefined` while the start input is empty/invalid. */
84
+ export function startWeekdayCode(start: string, allDay: boolean, timezone: string | undefined): WeekdayCode | undefined {
85
+ const ms = allDay ? new Date(allDayInstant(start.slice(0, 10))).getTime() : new Date(start).getTime();
86
+ if (Number.isNaN(ms)) {
87
+ return undefined;
88
+ }
89
+ return JS_WEEKDAY_CODES[new Date(toEventWallClock(ms, timezone, allDay)).getUTCDay()];
90
+ }
91
+
92
+ /**
93
+ * Whether `occurrence` should be shown on the grid's local calendar day `day`. All-day events cover every
94
+ * date from their start date up to (not including) their exclusive end date — at least their start date.
95
+ * Timed events cover every local day their [start, end) interval overlaps, so a multi-day event shows on
96
+ * each day rather than only on its start day.
97
+ */
98
+ export function occursOnDay(occurrence: CalendarOccurrence, day: Date): boolean {
99
+ if (occurrence.allDay) {
100
+ const key = localDateKey(day);
101
+ const startKey = allDayDateKey(occurrence.startDate);
102
+ const endKey = allDayDateKey(occurrence.endDate);
103
+ return key === startKey || (key > startKey && key < endKey);
104
+ }
105
+ const dayStart = new Date(day.getFullYear(), day.getMonth(), day.getDate());
106
+ const dayEnd = new Date(day.getFullYear(), day.getMonth(), day.getDate() + 1);
107
+ const start = new Date(occurrence.startDate);
108
+ const end = new Date(occurrence.endDate);
109
+ if (start.getTime() === end.getTime()) {
110
+ return start >= dayStart && start < dayEnd;
111
+ }
112
+ return start < dayEnd && end > dayStart;
113
+ }
114
+
115
+ /**
116
+ * Whether `day` is the first day `occurrence` covers. Grid views only make that day's chip/block
117
+ * draggable — a drag id must be unique, so the continuation copies on later days are display-only.
118
+ */
119
+ export function startsOnDay(occurrence: CalendarOccurrence, day: Date): boolean {
120
+ if (occurrence.allDay) {
121
+ return allDayDateKey(occurrence.startDate) === localDateKey(day);
122
+ }
123
+ return localDateKey(new Date(occurrence.startDate)) === localDateKey(day);
124
+ }
@@ -0,0 +1,86 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import { EventVisibility, guestPermissionsOf, visibilityOf } from "@rapidmx/react-shared/calendar/calendarApi.js";
6
+ import {
7
+ MAX_EVENT_DESCRIPTION_HTML_LENGTH,
8
+ MAX_EVENT_DESCRIPTION_LENGTH,
9
+ htmlToPlainText,
10
+ sanitizeEventDescriptionHtml,
11
+ } from "@rapidmx/react-shared/calendar/eventDescription.js";
12
+ import { CalendarOccurrence } from "@rapidmx/react-shared/calendar/recurrence.js";
13
+ import { EventFormValues } from "./eventForm.js";
14
+
15
+ /** The event dialog's own fields of a `CalendarEventInput` - only the ones that differ from what the event has, so saving an event no one touched these on
16
+ * says nothing about them (and asks for no new invitations). */
17
+ export interface EventDialogFields {
18
+ /** `null` clears. */
19
+ description?: string | null;
20
+ descriptionHtml?: string | null;
21
+ visibility?: EventVisibility;
22
+ guestsCanModify?: boolean;
23
+ guestsCanInviteOthers?: boolean;
24
+ guestsCanSeeGuestList?: boolean;
25
+ }
26
+
27
+ function escapeHtml(text: string): string {
28
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
29
+ }
30
+
31
+ /** Whether the editor's HTML holds any text (an emptied editor writes `<p></p>`). */
32
+ export function hasDescriptionText(html: string): boolean {
33
+ return html.replace(/<[^>]*>/g, "").trim() !== "";
34
+ }
35
+
36
+ /** A plain-text description as the paragraphs the editor starts from: one for each line (an event whose description has no HTML). */
37
+ export function plainTextToHtml(text: string): string {
38
+ return text
39
+ .split(/\r\n|\r|\n/)
40
+ .map((line) => `<p>${escapeHtml(line)}</p>`)
41
+ .join("");
42
+ }
43
+
44
+ /** What the description editor starts with for `occurrence`: its HTML, else its plain text as paragraphs, else nothing. */
45
+ export function initialDescriptionHtml(occurrence: Pick<CalendarOccurrence, "description" | "descriptionHtml"> | null): string {
46
+ if (occurrence?.descriptionHtml) {
47
+ return occurrence.descriptionHtml;
48
+ }
49
+ return occurrence?.description ? plainTextToHtml(occurrence.description) : "";
50
+ }
51
+
52
+ /** Why the description cannot be saved as it is - too long for the server (400) - or `undefined`. */
53
+ export function descriptionProblem(descriptionHtml: string): string | undefined {
54
+ const html = sanitizeEventDescriptionHtml(descriptionHtml);
55
+ return html.length > MAX_EVENT_DESCRIPTION_HTML_LENGTH || htmlToPlainText(html).length > MAX_EVENT_DESCRIPTION_LENGTH
56
+ ? "The description is too long."
57
+ : undefined;
58
+ }
59
+
60
+ /**
61
+ * What the form says about the description, visibility and guest permissions that differs from `occurrence` (`null` for a new event, which starts from the
62
+ * defaults: no description, default visibility, guests cannot modify, can invite, can see the list). A description is sent as both its sanitized HTML and the
63
+ * plain text derived from it, or as `null` twice when it was emptied; one the user did not change is not sent.
64
+ */
65
+ export function dialogFields(values: EventFormValues, occurrence: CalendarOccurrence | null): EventDialogFields {
66
+ const fields: EventDialogFields = {};
67
+
68
+ const initial = initialDescriptionHtml(occurrence);
69
+ const html = sanitizeEventDescriptionHtml(values.descriptionHtml);
70
+ if (values.descriptionHtml !== initial && html !== sanitizeEventDescriptionHtml(initial)) {
71
+ const plain = htmlToPlainText(html);
72
+ fields.description = plain || null;
73
+ fields.descriptionHtml = plain ? html : null;
74
+ }
75
+
76
+ if (values.visibility !== (occurrence ? visibilityOf(occurrence) : "default")) {
77
+ fields.visibility = values.visibility;
78
+ }
79
+ const permissions = guestPermissionsOf(occurrence ?? {});
80
+ for (const key of ["guestsCanModify", "guestsCanInviteOthers", "guestsCanSeeGuestList"] as const) {
81
+ if (values[key] !== permissions[key]) {
82
+ fields[key] = values[key];
83
+ }
84
+ }
85
+ return fields;
86
+ }
@@ -0,0 +1,108 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import { FormEvent } from "react";
6
+ import { Attendee, BusyStatus, EventVisibility, RecurrenceRule, WeekdayCode } from "@rapidmx/react-shared/calendar/calendarApi.js";
7
+ import { Mailbox } from "@rapidmx/react-shared/mail/mailApi.js";
8
+ import { CalendarOccurrence } from "@rapidmx/react-shared/calendar/recurrence.js";
9
+
10
+ /** Which occurrences of a recurring event an edit applies to. */
11
+ export type EditScope = "occurrence" | "series";
12
+
13
+ /**
14
+ * Everything the event form edits. The quick-create popover and the full form are two faces of the same values, so a title typed in the
15
+ * one is still there when "More options" opens the other.
16
+ */
17
+ export interface EventFormValues {
18
+ title: string;
19
+ location: string;
20
+ /** `YYYY-MM-DDTHH:mm` on the wall clock of `formZone` (for an all-day event only the date part matters). */
21
+ start: string;
22
+ end: string;
23
+ allDay: boolean;
24
+ /** The zone `start` and `end` are read in: the device's own until the user picks another. */
25
+ formZone: string;
26
+ /** The IANA zone the event is stored with. */
27
+ timezone: string;
28
+ attendees: Attendee[];
29
+ /** What has been typed into the guests field but not added yet. */
30
+ guestDraft: string;
31
+ /** What was committed to the guests field (Enter, a comma, leaving it) but is not an address: kept there, flagged, until it is fixed or removed. */
32
+ guestInvalid: string[];
33
+ recurrenceRule: RecurrenceRule | null;
34
+ /** Minutes before the start, as typed; blank means no reminder. */
35
+ reminderMinutes: string;
36
+ busyStatus: BusyStatus;
37
+ /** Who may see the event's details. */
38
+ visibility: EventVisibility;
39
+ /** The description as the editor last wrote it: HTML, `""` when there is none (an emptied editor writes `<p></p>`, which counts as none). */
40
+ descriptionHtml: string;
41
+ /** What guests may do: ask for the event to change, ask for guests to be added, see who else is invited. */
42
+ guestsCanModify: boolean;
43
+ guestsCanInviteOthers: boolean;
44
+ guestsCanSeeGuestList: boolean;
45
+ autoReplyEnabled: boolean;
46
+ autoReplyMessage: string;
47
+ videoEnabled: boolean;
48
+ targetMailboxUid: string;
49
+ targetFolderUid: string;
50
+ }
51
+
52
+ /** What `EventEditor` hands both faces of the form: the values, and every action and derived fact they need. */
53
+ export interface EventFormController {
54
+ /** The event being edited, `null` for a new one. */
55
+ occurrence: CalendarOccurrence | null;
56
+ values: EventFormValues;
57
+ update: (patch: Partial<EventFormValues>) => void;
58
+
59
+ // Date and time.
60
+ setStart: (next: string) => void;
61
+ setEnd: (next: string) => void;
62
+ onAllDayChange: (allDay: boolean) => void;
63
+ onTimeZoneChange: (zone: string) => void;
64
+ timeZones: string[];
65
+ startWeekday: WeekdayCode | undefined;
66
+ /** "This event only" of a recurring event: the copy it detaches has no rule of its own. */
67
+ editingSingleOccurrence: boolean;
68
+
69
+ // Find a time: whose calendar the grid shows as "you", and the zone the device's own clock is in.
70
+ /** The address the event is organized from (the chosen mailbox's, for a new event). */
71
+ organizerAddress: string;
72
+ deviceZone: string;
73
+
74
+ // Guests.
75
+ updateAttendee: (index: number, patch: Partial<Attendee>) => void;
76
+ removeAttendee: (index: number) => void;
77
+ addResource: (mailbox: Mailbox) => void;
78
+ /** Addresses already on the list (lowercased), for the room/equipment picker to leave out. */
79
+ guestAddresses: string[];
80
+
81
+ // Where the event goes.
82
+ mailboxOptions: { mailbox: Mailbox; calendars: { uid: string; name: string }[] }[] | undefined;
83
+ onMailboxChange: (mailboxUid: string) => void;
84
+ /** The calendars to choose between when creating; `undefined` for an existing event, which keeps its own. */
85
+ calendarChoices: { uid: string; name: string }[] | undefined;
86
+ calendarName: string | undefined;
87
+ calendarColor: string | undefined;
88
+
89
+ // Video conferencing.
90
+ videoMeetingUid: string | undefined;
91
+ /** The organizer's own join link once it is known and safe to open. */
92
+ joinUrl: string | undefined;
93
+ /** `undefined` while it is being fetched, `null` once it is known there is none. */
94
+ organizerJoinUrl: string | null | undefined;
95
+ videoError: string | null;
96
+
97
+ // The form as a whole.
98
+ editScope: EditScope;
99
+ setEditScope: (scope: EditScope) => void;
100
+ /** Whether the "Apply changes to" choice is offered (editing an occurrence of a recurring event). */
101
+ showEditScope: boolean;
102
+ error: string | null;
103
+ saving: boolean;
104
+ /** Submits the form. */
105
+ onSubmit: (event: FormEvent) => void;
106
+ /** The X / Cancel: leaves the form (back to the details for an existing event). */
107
+ onCancel: () => void;
108
+ }